Merge package:json_rpc_2 into the tools monorepo
diff --git a/.github/ISSUE_TEMPLATE/boolean_selector.md b/.github/ISSUE_TEMPLATE/boolean_selector.md new file mode 100644 index 0000000..5686d2a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/boolean_selector.md
@@ -0,0 +1,5 @@ +--- +name: "package:boolean_selector" +about: "Create a bug or file a feature request against package:boolean_selector." +labels: "package:boolean_selector" +--- \ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/cli_config.md b/.github/ISSUE_TEMPLATE/cli_config.md new file mode 100644 index 0000000..c47fbcf --- /dev/null +++ b/.github/ISSUE_TEMPLATE/cli_config.md
@@ -0,0 +1,5 @@ +--- +name: "package:cli_config" +about: "Create a bug or file a feature request against package:cli_config." +labels: "package:cli_config" +---
diff --git a/.github/ISSUE_TEMPLATE/coverage.md b/.github/ISSUE_TEMPLATE/coverage.md new file mode 100644 index 0000000..d0b0fb7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/coverage.md
@@ -0,0 +1,5 @@ +--- +name: "package:coverage" +about: "Create a bug or file a feature request against package:coverage." +labels: "package:coverage" +---
diff --git a/.github/ISSUE_TEMPLATE/extension_discovery.md b/.github/ISSUE_TEMPLATE/extension_discovery.md new file mode 100644 index 0000000..165b7cb --- /dev/null +++ b/.github/ISSUE_TEMPLATE/extension_discovery.md
@@ -0,0 +1,5 @@ +--- +name: "package:extension_discovery" +about: "Create a bug or file a feature request against package:extension_discovery." +labels: "package:extension_discovery" +---
diff --git a/.github/ISSUE_TEMPLATE/file.md b/.github/ISSUE_TEMPLATE/file.md new file mode 100644 index 0000000..3430d7e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/file.md
@@ -0,0 +1,5 @@ +--- +name: "package:file" +about: "Create a bug or file a feature request against package:file." +labels: "package:file" +---
diff --git a/.github/ISSUE_TEMPLATE/graphs.md b/.github/ISSUE_TEMPLATE/graphs.md new file mode 100644 index 0000000..b4cb60f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/graphs.md
@@ -0,0 +1,5 @@ +--- +name: "package:graphs" +about: "Create a bug or file a feature request against package:graphs." +labels: "package:graphs" +---
diff --git a/.github/ISSUE_TEMPLATE/unified_analytics.md b/.github/ISSUE_TEMPLATE/unified_analytics.md new file mode 100644 index 0000000..163951e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/unified_analytics.md
@@ -0,0 +1,5 @@ +--- +name: "package:unified_analytics - bug or enhancement" +about: "Create a bug or file a feature request against package:unified_analytics." +labels: "package:unified_analytics" +---
diff --git a/.github/ISSUE_TEMPLATE/unified_analytics_event.yml b/.github/ISSUE_TEMPLATE/unified_analytics_event.yml new file mode 100644 index 0000000..52c8d83 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/unified_analytics_event.yml
@@ -0,0 +1,47 @@ +name: "package:unified_analytics - request a new event" +description: "Create a request for collecting a new event or new event data." +labels: "package:unified_analytics" +body: + - type: markdown + attributes: + value: | + An event is an action that a user, or the tool, performs. + You can see the events that are being collected [here](../../pkgs/unified_analytics/lib/src/enums.dart) + and the data associated with those events [here](../../pkgs/unified_analytics/lib/src/event.dart). + - type: checkboxes + attributes: + label: Has this already been approved in the privacy design documentation? + options: + - label: This field is already covered in the PDD + description: | + You can request that a new event be added to the package + regardless of whether it's included in the privacy design documentation. + However, the privacy team will need to approve before it is added. + + - type: textarea + attributes: + label: Event name + description: | + If the event already exists, please tell us the name of the event + you would like to add data to. + + If this is a new event, tell us the name, description, and tool owner. + Possible tool owners can be found in the `DashTool` enum [here](../../pkgs/unified_analytics/lib/src/enums.dart). + + For example, pub_get represents pub package resolution details. The owner is the Dart tool. + validations: + required: true + + - type: textarea + attributes: + label: Event data + description: | + Event data are key-value pairs that are associated with an event. + Please list the different event data associated with this event. + You should also include a description of the event data values. + + For example, if the event is pub_get, one event data may be + the packageName. The values would be the name of the package + as a string. + validations: + required: true
diff --git a/.github/ISSUE_TEMPLATE/unified_analytics_user_property.yml b/.github/ISSUE_TEMPLATE/unified_analytics_user_property.yml new file mode 100644 index 0000000..3fc960e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/unified_analytics_user_property.yml
@@ -0,0 +1,37 @@ +name: "package:unified_analytics - request a new user property" +description: "Create a request for collecting a new user property." +labels: "package:unified_analytics" +body: + - type: markdown + attributes: + value: | + A user property is a key-value pair that is used to segment users. + For example, the Flutter channel that the user is on. You can see + which user properties are being collected + [here](../../pkgs/unified_analytics/lib/src/user_property.dart). + + - type: checkboxes + attributes: + label: Has this already been approved in the privacy design documentation? + options: + - label: This field is already covered in the PDD + description: | + You can request that a new user property be added to the package + regardless of whether it's included in the privacy design documentation. + However, the privacy team will need to approve before it is added. + + - type: textarea + attributes: + label: User property name + description: | + Please tell us the name of the user property you would like to add (e.g. flutter_channel). + validations: + required: true + + - type: textarea + attributes: + label: User property values + description: | + Please list or describe the unique values for this property (e.g. master, beta, stable). + validations: + required: true
diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml new file mode 100644 index 0000000..bf6b38a --- /dev/null +++ b/.github/dependabot.yaml
@@ -0,0 +1,14 @@ +# Dependabot configuration file. +version: 2 + +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: monthly + labels: + - autosubmit + groups: + github-actions: + patterns: + - "*"
diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 0000000..c3d5de0 --- /dev/null +++ b/.github/labeler.yml
@@ -0,0 +1,49 @@ +# Configuration for .github/workflows/pull_request_label.yml. + +'type-infra': + - changed-files: + - any-glob-to-any-file: '.github/**' + +'package:boolean_selector': + - changed-files: + - any-glob-to-any-file: 'pkgs/boolean_selector/**' + +'package:cli_config': + - changed-files: + - any-glob-to-any-file: 'pkgs/cli_config/**' + +'package:coverage': + - changed-files: + - any-glob-to-any-file: 'pkgs/coverage/**' + +'package:extension_discovery': + - changed-files: + - any-glob-to-any-file: 'pkgs/extension_discovery/**' + +'package:file': + - changed-files: + - any-glob-to-any-file: 'pkgs/file/**' + +'package:file_testing': + - changed-files: + - any-glob-to-any-file: 'pkgs/file_testing/**' + +'package:graphs': + - changed-files: + - any-glob-to-any-file: 'pkgs/graphs/**' + +'package:mime': + - changed-files: + - any-glob-to-any-file: 'pkgs/mime/**' + +'package:oauth2': + - changed-files: + - any-glob-to-any-file: 'pkgs/oauth2/**' + +'package:source_map_stack_trace': + - changed-files: + - any-glob-to-any-file: 'pkgs/source_map_stack_trace/**' + +'package:unified_analytics': + - changed-files: + - any-glob-to-any-file: 'pkgs/unified_analytics/**'
diff --git a/.github/workflows/boolean_selector.yaml b/.github/workflows/boolean_selector.yaml new file mode 100644 index 0000000..9d90c41 --- /dev/null +++ b/.github/workflows/boolean_selector.yaml
@@ -0,0 +1,72 @@ +name: package:boolean_selector + +on: + # Run on PRs and pushes to the default branch. + push: + branches: [ main ] + paths: + - '.github/workflows/boolean_selector.yml' + - 'pkgs/boolean_selector/**' + pull_request: + branches: [ main ] + paths: + - '.github/workflows/boolean_selector.yml' + - 'pkgs/boolean_selector/**' + schedule: + - cron: "0 0 * * 0" + +env: + PUB_ENVIRONMENT: bot.github + + +defaults: + run: + working-directory: pkgs/boolean_selector/ + +jobs: + # Check code formatting and static analysis on a single OS (linux) + # against Dart dev. + analyze: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + sdk: [dev] + steps: + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Check formatting + run: dart format --output=none --set-exit-if-changed . + if: always() && steps.install.outcome == 'success' + - name: Analyze code + run: dart analyze --fatal-infos + if: always() && steps.install.outcome == 'success' + + test: + needs: analyze + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + # Add macos-latest and/or windows-latest if relevant for this package. + os: [ubuntu-latest] + sdk: [3.1, dev] + steps: + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Run VM tests + run: dart test --platform vm + if: always() && steps.install.outcome == 'success' + - name: Run Chrome tests + run: dart test --platform chrome + if: always() && steps.install.outcome == 'success'
diff --git a/.github/workflows/cli_config.yml b/.github/workflows/cli_config.yml new file mode 100644 index 0000000..78eed42 --- /dev/null +++ b/.github/workflows/cli_config.yml
@@ -0,0 +1,80 @@ +name: package:cli_config +permissions: read-all + +on: + pull_request: + branches: [main] + paths: + - ".github/workflows/cli_config.yml" + - "pkgs/cli_config/**" + push: + branches: [main] + paths: + - ".github/workflows/cli_config.yml" + - "pkgs/cli_config/**" + schedule: + - cron: "0 0 * * 0" # weekly + +jobs: + build_linux: + runs-on: ubuntu-latest + defaults: + run: + working-directory: pkgs/cli_config + strategy: + matrix: + sdk: [stable, dev] # {pkgs.versions} + include: + - sdk: stable + run-tests: true + steps: + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + with: + sdk: ${{matrix.sdk}} + + - run: dart pub get + + - run: dart analyze --fatal-infos + + - run: dart format --output=none --set-exit-if-changed . + if: ${{matrix.run-tests}} + + - run: dart test + if: ${{matrix.run-tests}} + + - name: Install coverage + run: dart pub global activate coverage + if: ${{ matrix.sdk == 'stable' }} + - name: Collect coverage + run: dart pub global run coverage:test_with_coverage + if: ${{ matrix.sdk == 'stable' }} + - name: Upload coverage + uses: coverallsapp/github-action@643bc377ffa44ace6394b2b5d0d3950076de9f63 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + flag-name: cli_config_linux + path-to-lcov: ./pkgs/cli_config/coverage/lcov.info + if: ${{ matrix.sdk == 'stable' }} + + build_windows: + runs-on: windows-latest + defaults: + run: + working-directory: pkgs/cli_config + strategy: + matrix: + sdk: [stable, dev] # {pkgs.versions} + include: + - sdk: stable + run-tests: true + steps: + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + with: + sdk: ${{matrix.sdk}} + + - run: dart pub get + + - run: dart test + if: ${{matrix.run-tests}}
diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 0000000..a66a53c --- /dev/null +++ b/.github/workflows/coverage.yml
@@ -0,0 +1,99 @@ +name: Dart CI + +on: + # Run on PRs and pushes to the default branch. + push: + branches: [ main ] + paths: + - '.github/workflows/coverage.yml' + - 'pkgs/coverage/**' + pull_request: + branches: [ main ] + paths: + - '.github/workflows/coverage.yml' + - 'pkgs/coverage/**' + schedule: + - cron: "0 0 * * 0" + +env: + PUB_ENVIRONMENT: bot.github + +jobs: + # Check code formatting and static analysis on a single OS (linux) + # against Dart dev. + analyze: + runs-on: ubuntu-latest + defaults: + run: + working-directory: pkgs/coverage/ + strategy: + fail-fast: false + matrix: + sdk: [dev] + steps: + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Check formatting + run: dart format --output=none --set-exit-if-changed . + if: always() && steps.install.outcome == 'success' + - name: Analyze code + run: dart analyze --fatal-infos + if: always() && steps.install.outcome == 'success' + + # Run tests on a matrix consisting of two dimensions: + # 1. OS: ubuntu-latest, macos-latest, windows-latest + # 2. release channel: dev + test: + needs: analyze + runs-on: ${{ matrix.os }} + defaults: + run: + working-directory: pkgs/coverage/ + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + sdk: [3.4, dev] + exclude: + # VM service times out on windows before Dart 3.5 + # https://github.com/dart-lang/coverage/issues/490 + - os: windows-latest + sdk: 3.4 + steps: + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Run VM tests + run: dart test --platform vm + if: always() && steps.install.outcome == 'success' + + coverage: + needs: test + runs-on: ubuntu-latest + defaults: + run: + working-directory: pkgs/coverage/ + steps: + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + with: + sdk: dev + - id: install + name: Install dependencies + run: dart pub get + - name: Collect and report coverage + run: dart run bin/test_with_coverage.dart --port=9292 + - name: Upload coverage + uses: coverallsapp/github-action@643bc377ffa44ace6394b2b5d0d3950076de9f63 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + path-to-lcov: pkgs/coverage/coverage/lcov.info
diff --git a/.github/workflows/extension_discovery.yml b/.github/workflows/extension_discovery.yml new file mode 100644 index 0000000..b92fddf --- /dev/null +++ b/.github/workflows/extension_discovery.yml
@@ -0,0 +1,48 @@ +name: package:extension_discovery +permissions: read-all + +on: + pull_request: + branches: [ main ] + paths: + - '.github/workflows/unified_analytics.yml' + - 'pkgs/extension_discovery/**' + push: + branches: [ main ] + paths: + - '.github/workflows/extension_discovery.yml' + - 'pkgs/extension_discovery/**' + schedule: + - cron: '0 0 * * 0' # weekly + +jobs: + build: + runs-on: ubuntu-latest + defaults: + run: + working-directory: pkgs/extension_discovery + strategy: + fail-fast: false + matrix: + sdk: [stable, dev] # {pkgs.versions} + include: + - sdk: stable + check-formatting: true + steps: + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + with: + sdk: ${{matrix.sdk}} + + - run: dart pub get + - run: | + (cd example/hello_world && dart pub get) + (cd example/hello_world_app && dart pub get) + (cd example/hello_world_german && dart pub get) + + - run: dart analyze --fatal-infos + + - run: dart format --output=none --set-exit-if-changed . + if: ${{matrix.check-formatting}} + + - run: dart test
diff --git a/.github/workflows/file.yml b/.github/workflows/file.yml new file mode 100644 index 0000000..06ce285 --- /dev/null +++ b/.github/workflows/file.yml
@@ -0,0 +1,66 @@ +name: package:file +permissions: read-all + +on: + # Run on PRs and pushes to the default branch. + push: + branches: [ main ] + paths: + - '.github/workflows/file.yml' + - 'pkgs/file/**' + - 'pkgs/file_testing/**' + pull_request: + branches: [ main ] + paths: + - '.github/workflows/file.yml' + - 'pkgs/file/**' + - 'pkgs/file_testing/**' + schedule: + - cron: "0 0 * * 0" + +jobs: + correctness: + runs-on: ubuntu-latest + strategy: + matrix: + package: [file, file_testing] + + steps: + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + with: + sdk: dev + + - name: Install ${{ matrix.package }} dependencies + working-directory: pkgs/${{ matrix.package }} + run: dart pub get + + - name: Verify formatting in ${{ matrix.package }} + working-directory: pkgs/${{ matrix.package }} + run: dart format --output=none --set-exit-if-changed . + + - name: Analyze package ${{ matrix.package }} source + working-directory: pkgs/${{ matrix.package }} + run: dart analyze --fatal-infos + + test: + runs-on: ${{ matrix.os }} + strategy: + matrix: + package: [file] + os: [ubuntu-latest, macos-latest, windows-latest] + sdk: [stable, dev] + + steps: + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + with: + sdk: ${{ matrix.sdk }} + + - name: Install ${{ matrix.package }} dependencies + working-directory: pkgs/${{ matrix.package }} + run: dart pub get + + - name: Run ${{ matrix.package }} Tests + working-directory: pkgs/${{ matrix.package }} + run: dart pub run test -j1
diff --git a/.github/workflows/graphs.yml b/.github/workflows/graphs.yml new file mode 100644 index 0000000..8de9cf5 --- /dev/null +++ b/.github/workflows/graphs.yml
@@ -0,0 +1,67 @@ +name: package:graphs +permissions: read-all + +on: + # Run on PRs and pushes to the default branch. + push: + branches: [ main ] + paths: + - '.github/workflows/graphs.yml' + - 'pkgs/graphs/**' + pull_request: + branches: [ main ] + paths: + - '.github/workflows/graphs.yml' + - 'pkgs/graphs/**' + schedule: + - cron: "0 0 * * 0" + +env: + PUB_ENVIRONMENT: bot.github + +jobs: + # Check code formatting and static analysis on a single OS (linux) + # against Dart beta. + analyze: + runs-on: ubuntu-latest + defaults: + run: + working-directory: pkgs/graphs/ + strategy: + fail-fast: false + matrix: + sdk: [dev] + steps: + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + with: + sdk: ${{ matrix.sdk }} + - id: install + run: dart pub get + - run: dart format --output=none --set-exit-if-changed . + if: always() && steps.install.outcome == 'success' + - run: dart analyze --fatal-infos + if: always() && steps.install.outcome == 'success' + + test: + needs: analyze + runs-on: ${{ matrix.os }} + defaults: + run: + working-directory: pkgs/graphs/ + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + sdk: [3.4, dev] + steps: + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + with: + sdk: ${{ matrix.sdk }} + - id: install + run: dart pub get + - run: dart test --platform vm + if: always() && steps.install.outcome == 'success' + - run: dart test --platform chrome + if: always() && steps.install.outcome == 'success'
diff --git a/.github/workflows/health.yaml b/.github/workflows/health.yaml new file mode 100644 index 0000000..f258f8b --- /dev/null +++ b/.github/workflows/health.yaml
@@ -0,0 +1,14 @@ +name: Health +on: + pull_request: + branches: [ main ] + types: [opened, synchronize, reopened, labeled, unlabeled] + +jobs: + health: + uses: dart-lang/ecosystem/.github/workflows/health.yaml@main + with: + ignore_coverage: "**.mock.dart,**.g.dart" + ignore_license: "**.mock.dart,**.g.dart,**.mocks.dart" + permissions: + pull-requests: write
diff --git a/.github/workflows/mime.yml b/.github/workflows/mime.yml new file mode 100644 index 0000000..fe07a21 --- /dev/null +++ b/.github/workflows/mime.yml
@@ -0,0 +1,45 @@ +name: Dart CI + +on: + schedule: + # “At 00:00 (UTC) on Sunday.” + - cron: '0 0 * * 0' + push: + branches: [ main ] + paths: + - '.github/workflows/mime.yml' + - 'pkgs/mime/**' + pull_request: + branches: [ main ] + paths: + - '.github/workflows/mime.yml' + - 'pkgs/mime/**' + +jobs: + build: + runs-on: ubuntu-latest + defaults: + run: + working-directory: pkgs/mime/ + + strategy: + matrix: + os: [ubuntu-latest] + sdk: [3.2, dev] + steps: + # These are the latest versions of the github actions; dependabot will + # send PRs to keep these up-to-date. + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + + - name: Install dependencies + run: dart pub get + + - name: Verify formatting + run: dart format --output=none --set-exit-if-changed . + + - name: Analyze project source + run: dart analyze --fatal-infos + + - name: Run tests + run: dart test
diff --git a/.github/workflows/no-response.yml b/.github/workflows/no-response.yml new file mode 100644 index 0000000..ab1ac49 --- /dev/null +++ b/.github/workflows/no-response.yml
@@ -0,0 +1,37 @@ +# A workflow to close issues where the author hasn't responded to a request for +# more information; see https://github.com/actions/stale. + +name: No Response + +# Run as a daily cron. +on: + schedule: + # Every day at 8am + - cron: '0 8 * * *' + +# All permissions not specified are set to 'none'. +permissions: + issues: write + pull-requests: write + +jobs: + no-response: + runs-on: ubuntu-latest + if: ${{ github.repository_owner == 'dart-lang' }} + steps: + - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e + with: + # Don't automatically mark inactive issues+PRs as stale. + days-before-stale: -1 + # Close needs-info issues and PRs after 14 days of inactivity. + days-before-close: 14 + stale-issue-label: "needs-info" + close-issue-message: > + Without additional information we're not able to resolve this issue. + Feel free to add more info or respond to any questions above and we + can reopen the case. Thanks for your contribution! + stale-pr-label: "needs-info" + close-pr-message: > + Without additional information we're not able to resolve this PR. + Feel free to add more info or respond to any questions above. + Thanks for your contribution!
diff --git a/.github/workflows/oauth2.yml b/.github/workflows/oauth2.yml new file mode 100644 index 0000000..fa5d2de --- /dev/null +++ b/.github/workflows/oauth2.yml
@@ -0,0 +1,79 @@ +name: Dart CI + +on: + # Run on PRs and pushes to the default branch. + push: + branches: [ main ] + paths: + - '.github/workflows/oauth2.yml' + - 'pkgs/oauth2/**' + pull_request: + branches: [ main ] + paths: + - '.github/workflows/oauth2.yml' + - 'pkgs/oauth2/**' + schedule: + - cron: "0 0 * * 0" + +env: + PUB_ENVIRONMENT: bot.github + +jobs: + # Check code formatting and lints against Dart dev, check analyzer warnings + # against the oldest supported SDK. + analyze: + runs-on: ubuntu-latest + defaults: + run: + working-directory: pkgs/oauth2/ + strategy: + fail-fast: false + matrix: + sdk: [dev] + steps: + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Check formatting + run: dart format --output=none --set-exit-if-changed . + if: matrix.sdk == 'dev' && steps.install.outcome == 'success' + - name: Analyze code + run: dart analyze --fatal-infos + if: matrix.sdk == 'dev' && steps.install.outcome == 'success' + - name: Analyze code + run: dart analyze + if: matrix.sdk != 'dev' && steps.install.outcome == 'success' + + # Run tests on a matrix consisting of two dimensions: + # 1. OS: ubuntu-latest, (macos-latest, windows-latest) + # 2. release channel: dev + test: + needs: analyze + runs-on: ${{ matrix.os }} + defaults: + run: + working-directory: pkgs/oauth2/ + strategy: + fail-fast: false + matrix: + # Add macos-latest and/or windows-latest if relevant for this package. + os: [ubuntu-latest] + sdk: [3.4, dev] + steps: + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Run VM tests + run: dart test --platform vm + if: always() && steps.install.outcome == 'success' + - name: Run Chrome tests + run: dart test --platform chrome + if: always() && steps.install.outcome == 'success'
diff --git a/.github/workflows/post_summaries.yaml b/.github/workflows/post_summaries.yaml new file mode 100644 index 0000000..f5c8be8 --- /dev/null +++ b/.github/workflows/post_summaries.yaml
@@ -0,0 +1,17 @@ +name: Comment on the pull request + +on: + # Trigger this workflow after the Health workflow completes. This workflow will have permissions to + # do things like create comments on the PR, even if the original workflow couldn't. + workflow_run: + workflows: + - Publish + - Health + types: + - completed + +jobs: + upload: + uses: dart-lang/ecosystem/.github/workflows/post_summaries.yaml@main + permissions: + pull-requests: write
diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml new file mode 100644 index 0000000..2ec45aa --- /dev/null +++ b/.github/workflows/publish.yaml
@@ -0,0 +1,16 @@ +# A CI configuration to auto-publish pub packages. + +name: Publish + +on: + pull_request: + branches: [ main ] + push: + tags: [ '[A-z]+-v[0-9]+.[0-9]+.[0-9]+' ] + +jobs: + publish: + if: ${{ github.repository_owner == 'dart-lang' }} + uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main + with: + write-comments: false
diff --git a/.github/workflows/pull_request_label.yml b/.github/workflows/pull_request_label.yml new file mode 100644 index 0000000..54e3df5 --- /dev/null +++ b/.github/workflows/pull_request_label.yml
@@ -0,0 +1,22 @@ +# This workflow applies labels to pull requests based on the paths that are +# modified in the pull request. +# +# Edit `.github/labeler.yml` to configure labels. For more information, see +# https://github.com/actions/labeler. + +name: Pull Request Labeler +permissions: read-all + +on: + pull_request_target + +jobs: + label: + permissions: + pull-requests: write + runs-on: ubuntu-latest + steps: + - uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 + with: + repo-token: "${{ secrets.GITHUB_TOKEN }}" + sync-labels: true
diff --git a/.github/workflows/source_map_stack_trace.yml b/.github/workflows/source_map_stack_trace.yml new file mode 100644 index 0000000..9d3f0c7 --- /dev/null +++ b/.github/workflows/source_map_stack_trace.yml
@@ -0,0 +1,76 @@ +name: Dart CI + +on: + # Run on PRs and pushes to the default branch. + push: + branches: [ main ] + paths: + - '.github/workflows/source_map_stack_trace.yml' + - 'pkgs/source_map_stack_trace/**' + pull_request: + branches: [ main ] + paths: + - '.github/workflows/source_map_stack_trace.yml' + - 'pkgs/source_map_stack_trace/**' + schedule: + - cron: "0 0 * * 0" + +env: + PUB_ENVIRONMENT: bot.github + +jobs: + # Check code formatting and static analysis on a single OS (linux) + # against Dart dev. + analyze: + runs-on: ubuntu-latest + defaults: + run: + working-directory: pkgs/source_map_stack_trace/ + strategy: + fail-fast: false + matrix: + sdk: [dev] + steps: + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Check formatting + run: dart format --output=none --set-exit-if-changed . + if: always() && steps.install.outcome == 'success' + - name: Analyze code + run: dart analyze --fatal-infos + if: always() && steps.install.outcome == 'success' + + # Run tests on a matrix consisting of two dimensions: + # 1. OS: ubuntu-latest, (macos-latest, windows-latest) + # 2. release channel: dev + test: + needs: analyze + runs-on: ${{ matrix.os }} + defaults: + run: + working-directory: pkgs/source_map_stack_trace/ + strategy: + fail-fast: false + matrix: + # Add macos-latest and/or windows-latest if relevant for this package. + os: [ubuntu-latest] + sdk: [3.3, dev] + steps: + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Run VM tests + run: dart test --platform vm + if: always() && steps.install.outcome == 'success' + - name: Run Chrome tests + run: dart test --platform chrome + if: always() && steps.install.outcome == 'success'
diff --git a/.github/workflows/unified_analytics.yml b/.github/workflows/unified_analytics.yml new file mode 100644 index 0000000..4b1c33e --- /dev/null +++ b/.github/workflows/unified_analytics.yml
@@ -0,0 +1,44 @@ +name: package:unified_analytics +permissions: read-all + +on: + pull_request: + branches: [ main ] + paths: + - '.github/workflows/unified_analytics.yml' + - 'pkgs/unified_analytics/**' + push: + branches: [ main ] + paths: + - '.github/workflows/unified_analytics.yml' + - 'pkgs/unified_analytics/**' + schedule: + - cron: '0 0 * * 0' # weekly + +jobs: + build: + runs-on: ubuntu-latest + defaults: + run: + working-directory: pkgs/unified_analytics + strategy: + matrix: + sdk: [stable, dev] # {pkgs.versions} + include: + - sdk: stable + run-tests: true + steps: + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + with: + sdk: ${{matrix.sdk}} + + - run: dart pub get + + - run: dart analyze --fatal-infos + + - run: dart format --output=none --set-exit-if-changed . + if: ${{matrix.run-tests}} + + - run: dart test + if: ${{matrix.run-tests}}
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5509140 --- /dev/null +++ b/.gitignore
@@ -0,0 +1 @@ +*.DS_Store
diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000..7694822 --- /dev/null +++ b/CODEOWNERS
@@ -0,0 +1,5 @@ +# The CODEOWNERS file helps to define individuals or teams that responsible +# for code within the repository +# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners + +/pkgs/unified_analytics/ @andrewkolos
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..3c28563 --- /dev/null +++ b/CONTRIBUTING.md
@@ -0,0 +1,51 @@ +# How to Contribute + +We'd love to accept your patches and contributions to this project. There are +just a few small guidelines you need to follow. + +## Contributor License Agreement + +Contributions to this project must be accompanied by a Contributor License +Agreement (CLA). You (or your employer) retain the copyright to your +contribution; this simply gives us permission to use and redistribute your +contributions as part of the project. Head over to +<https://cla.developers.google.com/> to see your current agreements on file or +to sign a new one. + +You generally only need to submit a CLA once, so if you've already submitted one +(even if it was for a different project), you probably don't need to do it +again. + +## Code Reviews + +All submissions, including submissions by project members, require review. We +use GitHub pull requests for this purpose. Consult +[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more +information on using pull requests. + +## Coding style + +The Dart source code in this repo follows the: + + * [Dart style guide](https://dart.dev/guides/language/effective-dart/style) + +You should familiarize yourself with those guidelines. + +## File headers + +All files in the Dart project must start with the following header; if you add a +new file please also add this. The year should be a single number stating the +year the file was created (don't use a range like "2011-2012"). Additionally, if +you edit an existing file, you shouldn't update the year. + + // 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. + +## Community Guidelines + +This project follows +[Google's Open Source Community Guidelines](https://opensource.google/conduct/). + +We pledge to maintain an open and welcoming environment. For details, see our +[code of conduct](https://dart.dev/code-of-conduct).
diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..4fd5739 --- /dev/null +++ b/LICENSE
@@ -0,0 +1,27 @@ +Copyright 2023, the Dart project authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google LLC nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md new file mode 100644 index 0000000..ac4edf2 --- /dev/null +++ b/README.md
@@ -0,0 +1,35 @@ +<!-- [](https://github.com/dart-lang/tools/actions/workflows/dart.yml) --> + +## Overview + +This repository is home to tooling related Dart packages. Generally, this means +packages published through the +[tools.dart.dev](https://pub.dev/publishers/tools.dart.dev) publisher that +don't naturally belong to other topic monorepos (like +[dart-lang/build](https://github.com/dart-lang/build), +[dart-lang/test](https://github.com/dart-lang/test), or +[dart-lang/shelf](https://github.com/dart-lang/shelf)). + +## Packages + +| Package | Description | Version | +| --- | --- | --- | +| [boolean_selector](pkgs/boolean_selector/) | A flexible syntax for boolean expressions, based on a simplified version of Dart's expression syntax. | [](https://pub.dev/packages/boolean_selector) | +| [cli_config](pkgs/cli_config/) | A library to take config values from configuration files, CLI arguments, and environment variables. | [](https://pub.dev/packages/cli_config) | +| [coverage](pkgs/coverage/) | Coverage data manipulation and formatting. | [](https://pub.dev/packages/coverage) | +| [extension_discovery](pkgs/extension_discovery/) | A convention and utilities for package extension discovery. | [](https://pub.dev/packages/extension_discovery) | +| [file](pkgs/file/) | A pluggable, mockable file system abstraction for Dart. | [](https://pub.dev/packages/file) | +| [file_testing](pkgs/file_testing/) | Testing utilities for package:file (published but unlisted). | [](https://pub.dev/packages/file_testing) | +| [graphs](pkgs/graphs/) | Graph algorithms that operate on graphs in any representation | [](https://pub.dev/packages/graphs) | +| [mime](pkgs/mime/) | Utilities for handling media (MIME) types. | [](https://pub.dev/packages/mime) | +| [oauth2](pkgs/oauth2/) | A client library for authenticatingand making requests via OAuth2. | [](https://pub.dev/packages/oauth2) | +| [source_map_stack_trace](pkgs/source_map_stack_trace/) | A package for applying source maps to stack traces. | [](https://pub.dev/packages/source_map_stack_trace) | +| [unified_analytics](pkgs/unified_analytics/) | A package for logging analytics for all Dart and Flutter related tooling to Google Analytics. | [](https://pub.dev/packages/unified_analytics) | + +## Publishing automation + +For information about our publishing automation and release process, see +https://github.com/dart-lang/ecosystem/wiki/Publishing-automation. + +For additional information about contributing, see our +[contributing](CONTRIBUTING.md) page.
diff --git a/pkgs/boolean_selector/.gitignore b/pkgs/boolean_selector/.gitignore new file mode 100644 index 0000000..49ce72d --- /dev/null +++ b/pkgs/boolean_selector/.gitignore
@@ -0,0 +1,3 @@ +.dart_tool/ +.packages +pubspec.lock
diff --git a/pkgs/boolean_selector/AUTHORS b/pkgs/boolean_selector/AUTHORS new file mode 100644 index 0000000..e8063a8 --- /dev/null +++ b/pkgs/boolean_selector/AUTHORS
@@ -0,0 +1,6 @@ +# Below is a list of people and organizations that have contributed +# to the project. Names should be added to the list like so: +# +# Name/Organization <email address> + +Google Inc.
diff --git a/pkgs/boolean_selector/CHANGELOG.md b/pkgs/boolean_selector/CHANGELOG.md new file mode 100644 index 0000000..f870787 --- /dev/null +++ b/pkgs/boolean_selector/CHANGELOG.md
@@ -0,0 +1,44 @@ +## 2.1.2 + +* Increase the SDK minimum to `3.1.0`. +* Move to `dart-lang/tools` monorepo. + +## 2.1.1 + +* Increase the SDK minimum to `2.17.0`. +* Populate the pubspec `repository` field. + +## 2.1.0 + +* Stable release for null safety. + +## 2.0.0 + +* Breaking: `BooleanSelector.evaluate` always takes a `bool Function(String)`. + For use cases previously passing a `Set<String>`, tear off the `.contains` + method. For use cases passing an `Iterable<String>` it may be worthwhile to + first use `.toSet()` before tearing off `.contains`. + +## 1.0.5 + +* Update package metadata & add `example/` folder + +## 1.0.4 + +* Now requires Dart 2. + +## 1.0.3 + +* Work around an inference bug in the new common front-end. + +## 1.0.2 + +* Declare compatibility with `string_scanner` 1.0.0. + +## 1.0.1 + +* Fix all strong mode warnings. + +## 1.0.0 + +* Initial release.
diff --git a/pkgs/boolean_selector/LICENSE b/pkgs/boolean_selector/LICENSE new file mode 100644 index 0000000..ac7d7af --- /dev/null +++ b/pkgs/boolean_selector/LICENSE
@@ -0,0 +1,27 @@ +Copyright 2016, the Dart project authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google LLC nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/pkgs/boolean_selector/README.md b/pkgs/boolean_selector/README.md new file mode 100644 index 0000000..8d58dbb --- /dev/null +++ b/pkgs/boolean_selector/README.md
@@ -0,0 +1,42 @@ +[](https://github.com/dart-lang/tools/actions/workflows/boolean_selector.yaml) +[](https://pub.dev/packages/boolean_selector) +[](https://pub.dev/packages/boolean_selector/publisher) + +The `boolean_selector` package defines a simple and flexible syntax for boolean +expressions. It can be used for filtering based on user-defined expressions. For +example, the [`test`][test] package uses boolean selectors to allow users to +define what platforms their tests support. + +[test]: https://github.com/dart-lang/test + +The boolean selector syntax is based on a simplified version of Dart's +expression syntax. Selectors can contain identifiers, parentheses, and boolean +operators, including `||`, `&&`, `!`, and `? :`. Any valid Dart identifier is +allowed, and identifiers may also contain hyphens. For example, `chrome`, +`chrome || content-shell`, and `js || (vm && linux)` are all valid boolean +selectors. + +A boolean selector is parsed from a string using +[`BooleanSelector.parse()`][parse], and evaluated against a set of variables +using [`BooleanSelector.evaluate()`][evaluate]. The variables are supplied as +a function that takes a variable name and returns its value. For example: + +[parse]: https://pub.dev/documentation/boolean_selector/latest/boolean_selector/BooleanSelector/BooleanSelector.parse.html + +[evaluate]: https://pub.dev/documentation/boolean_selector/latest/boolean_selector/BooleanSelector/evaluate.html + +```dart +import 'package:boolean_selector/boolean_selector.dart'; + +void main(List<String> args) { + var selector = BooleanSelector.parse("(x && y) || z"); + print(selector.evaluate((variable) => args.contains(variable))); +} +``` + +## Versioning + +If this package adds new features to the boolean selector syntax, it will +increment its major version number. This ensures that packages that expose the +syntax to their users will be able to update their own minor versions, so their +users can indicate that they rely on the new syntax.
diff --git a/pkgs/boolean_selector/analysis_options.yaml b/pkgs/boolean_selector/analysis_options.yaml new file mode 100644 index 0000000..178039f --- /dev/null +++ b/pkgs/boolean_selector/analysis_options.yaml
@@ -0,0 +1,7 @@ +include: package:dart_flutter_team_lints/analysis_options.yaml + +linter: + rules: + - avoid_unused_constructor_parameters + - cancel_subscriptions + - package_api_docs
diff --git a/pkgs/boolean_selector/example/example.dart b/pkgs/boolean_selector/example/example.dart new file mode 100644 index 0000000..a4f7879 --- /dev/null +++ b/pkgs/boolean_selector/example/example.dart
@@ -0,0 +1,6 @@ +import 'package:boolean_selector/boolean_selector.dart'; + +void main(List<String> args) { + var selector = BooleanSelector.parse('(x && y) || z'); + print(selector.evaluate((variable) => args.contains(variable))); +}
diff --git a/pkgs/boolean_selector/lib/boolean_selector.dart b/pkgs/boolean_selector/lib/boolean_selector.dart new file mode 100644 index 0000000..1c42641 --- /dev/null +++ b/pkgs/boolean_selector/lib/boolean_selector.dart
@@ -0,0 +1,56 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:source_span/source_span.dart'; + +import 'src/all.dart'; +import 'src/impl.dart'; +import 'src/none.dart'; + +/// A boolean expression that evaluates to `true` or `false` based on certain +/// inputs. +/// +/// The syntax is mostly Dart's expression syntax restricted to boolean +/// operations. See [the README][] for full details. +/// +/// [the README]: https://github.com/dart-lang/boolean_selector/blob/master/README.md +/// +/// Boolean selectors support structural equality. Two selectors that have the +/// same parsed structure are considered equal. +abstract class BooleanSelector { + /// A selector that accepts all inputs. + static const all = All(); + + /// A selector that accepts no inputs. + static const none = None(); + + /// All the variables in this selector, in the order they appear. + Iterable<String> get variables; + + /// Parses [selector]. + /// + /// This will throw a [SourceSpanFormatException] if the selector is + /// malformed or if it uses an undefined variable. + factory BooleanSelector.parse(String selector) = BooleanSelectorImpl.parse; + + /// Returns whether the selector matches the given [semantics]. + /// + /// The [semantics] define which variables evaluate to `true` or `false`. When + /// passed a variable name it should return the value of that variable. + bool evaluate(bool Function(String variable) semantics); + + /// Returns a new [BooleanSelector] that matches only inputs matched by both + /// `this` and [other]. + BooleanSelector intersection(BooleanSelector other); + + /// Returns a new [BooleanSelector] that matches all inputs matched by either + /// `this` or [other]. + BooleanSelector union(BooleanSelector other); + + /// Throws a [FormatException] if any variables are undefined. + /// + /// The [isDefined] function should return `true` for any variables that are + /// considered valid, and `false` for any invalid or undefined variables. + void validate(bool Function(String variable) isDefined); +}
diff --git a/pkgs/boolean_selector/lib/src/all.dart b/pkgs/boolean_selector/lib/src/all.dart new file mode 100644 index 0000000..3424319 --- /dev/null +++ b/pkgs/boolean_selector/lib/src/all.dart
@@ -0,0 +1,30 @@ +// Copyright (c) 2016, 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 '../boolean_selector.dart'; + +/// A selector that matches all inputs. +class All implements BooleanSelector { + // TODO(nweiz): Stop explicitly providing a type argument when sdk#32412 is + // fixed. + @override + final Iterable<String> variables = const <String>[]; + + const All(); + + @override + bool evaluate(bool Function(String variable) semantics) => true; + + @override + BooleanSelector intersection(BooleanSelector other) => other; + + @override + BooleanSelector union(BooleanSelector other) => this; + + @override + void validate(bool Function(String variable) isDefined) {} + + @override + String toString() => '<all>'; +}
diff --git a/pkgs/boolean_selector/lib/src/ast.dart b/pkgs/boolean_selector/lib/src/ast.dart new file mode 100644 index 0000000..d0d8583 --- /dev/null +++ b/pkgs/boolean_selector/lib/src/ast.dart
@@ -0,0 +1,210 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:source_span/source_span.dart'; + +import 'visitor.dart'; + +/// The superclass of nodes in the boolean selector abstract syntax tree. +abstract class Node { + /// The span indicating where this node came from. + /// + /// This is a [FileSpan] because the nodes are parsed from a single continuous + /// string, but the string itself isn't actually a file. It might come from a + /// statically-parsed annotation or from a parameter. + /// + /// This may be `null` for nodes without source information. + FileSpan? get span; + + /// All the variables in this node, in the order they appear. + Iterable<String> get variables; + + /// Calls the appropriate [Visitor] method on `this` and returns the result. + T accept<T>(Visitor<T> visitor); +} + +/// A single variable. +class VariableNode implements Node { + @override + final FileSpan? span; + + /// The variable name. + final String name; + + @override + Iterable<String> get variables => [name]; + + VariableNode(this.name, [this.span]); + + @override + T accept<T>(Visitor<T> visitor) => visitor.visitVariable(this); + + @override + String toString() => name; + + @override + bool operator ==(Object other) => other is VariableNode && name == other.name; + + @override + int get hashCode => name.hashCode; +} + +/// A negation expression. +class NotNode implements Node { + @override + final FileSpan? span; + + /// The expression being negated. + final Node child; + + @override + Iterable<String> get variables => child.variables; + + NotNode(this.child, [this.span]); + + @override + T accept<T>(Visitor<T> visitor) => visitor.visitNot(this); + + @override + String toString() => + child is VariableNode || child is NotNode ? '!$child' : '!($child)'; + + @override + bool operator ==(Object other) => other is NotNode && child == other.child; + + @override + int get hashCode => ~child.hashCode; +} + +/// An or expression. +class OrNode implements Node { + @override + FileSpan? get span => _expandSafe(left.span, right.span); + + /// The left-hand branch of the expression. + final Node left; + + /// The right-hand branch of the expression. + final Node right; + + @override + Iterable<String> get variables sync* { + yield* left.variables; + yield* right.variables; + } + + OrNode(this.left, this.right); + + @override + T accept<T>(Visitor<T> visitor) => visitor.visitOr(this); + + @override + String toString() { + var string1 = left is AndNode || left is ConditionalNode ? '($left)' : left; + var string2 = + right is AndNode || right is ConditionalNode ? '($right)' : right; + + return '$string1 || $string2'; + } + + @override + bool operator ==(Object other) => + other is OrNode && left == other.left && right == other.right; + + @override + int get hashCode => left.hashCode ^ right.hashCode; +} + +/// An and expression. +class AndNode implements Node { + @override + FileSpan? get span => _expandSafe(left.span, right.span); + + /// The left-hand branch of the expression. + final Node left; + + /// The right-hand branch of the expression. + final Node right; + + @override + Iterable<String> get variables sync* { + yield* left.variables; + yield* right.variables; + } + + AndNode(this.left, this.right); + + @override + T accept<T>(Visitor<T> visitor) => visitor.visitAnd(this); + + @override + String toString() { + var string1 = left is OrNode || left is ConditionalNode ? '($left)' : left; + var string2 = + right is OrNode || right is ConditionalNode ? '($right)' : right; + + return '$string1 && $string2'; + } + + @override + bool operator ==(Object other) => + other is AndNode && left == other.left && right == other.right; + + @override + int get hashCode => left.hashCode ^ right.hashCode; +} + +/// A ternary conditional expression. +class ConditionalNode implements Node { + @override + FileSpan? get span => _expandSafe(condition.span, whenFalse.span); + + /// The condition expression to check. + final Node condition; + + /// The branch to run if the condition is true. + final Node whenTrue; + + /// The branch to run if the condition is false. + final Node whenFalse; + + @override + Iterable<String> get variables sync* { + yield* condition.variables; + yield* whenTrue.variables; + yield* whenFalse.variables; + } + + ConditionalNode(this.condition, this.whenTrue, this.whenFalse); + + @override + T accept<T>(Visitor<T> visitor) => visitor.visitConditional(this); + + @override + String toString() { + var conditionString = + condition is ConditionalNode ? '($condition)' : condition; + var trueString = whenTrue is ConditionalNode ? '($whenTrue)' : whenTrue; + return '$conditionString ? $trueString : $whenFalse'; + } + + @override + bool operator ==(Object other) => + other is ConditionalNode && + condition == other.condition && + whenTrue == other.whenTrue && + whenFalse == other.whenFalse; + + @override + int get hashCode => + condition.hashCode ^ whenTrue.hashCode ^ whenFalse.hashCode; +} + +/// Like [FileSpan.expand], except if [start] and [end] are `null` or from +/// different files it returns `null` rather than throwing an error. +FileSpan? _expandSafe(FileSpan? start, FileSpan? end) { + if (start == null || end == null) return null; + if (start.file != end.file) return null; + return start.expand(end); +}
diff --git a/pkgs/boolean_selector/lib/src/evaluator.dart b/pkgs/boolean_selector/lib/src/evaluator.dart new file mode 100644 index 0000000..ee57149 --- /dev/null +++ b/pkgs/boolean_selector/lib/src/evaluator.dart
@@ -0,0 +1,33 @@ +// Copyright (c) 2016, 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 'ast.dart'; +import 'visitor.dart'; + +/// A visitor for evaluating boolean selectors against a specific set of +/// semantics. +class Evaluator implements Visitor<bool> { + final bool Function(String variable) _semantics; + + Evaluator(this._semantics); + + @override + bool visitVariable(VariableNode node) => _semantics(node.name); + + @override + bool visitNot(NotNode node) => !node.child.accept(this); + + @override + bool visitOr(OrNode node) => + node.left.accept(this) || node.right.accept(this); + + @override + bool visitAnd(AndNode node) => + node.left.accept(this) && node.right.accept(this); + + @override + bool visitConditional(ConditionalNode node) => node.condition.accept(this) + ? node.whenTrue.accept(this) + : node.whenFalse.accept(this); +}
diff --git a/pkgs/boolean_selector/lib/src/impl.dart b/pkgs/boolean_selector/lib/src/impl.dart new file mode 100644 index 0000000..cafb1a4 --- /dev/null +++ b/pkgs/boolean_selector/lib/src/impl.dart
@@ -0,0 +1,72 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:source_span/source_span.dart'; + +import '../boolean_selector.dart'; +import 'ast.dart'; +import 'evaluator.dart'; +import 'intersection_selector.dart'; +import 'parser.dart'; +import 'union_selector.dart'; +import 'validator.dart'; + +/// The concrete implementation of a [BooleanSelector] parsed from a string. +/// +/// This is separate from [BooleanSelector] so that [intersection] and [union] +/// can check to see whether they're passed a [BooleanSelectorImpl] or a +/// different class that implements [BooleanSelector]. +class BooleanSelectorImpl implements BooleanSelector { + /// The parsed AST. + final Node _selector; + + /// Parses [selector]. + /// + /// This will throw a [SourceSpanFormatException] if the selector is + /// malformed or if it uses an undefined variable. + BooleanSelectorImpl.parse(String selector) + : _selector = Parser(selector).parse(); + + BooleanSelectorImpl._(this._selector); + + @override + Iterable<String> get variables => _selector.variables; + + @override + bool evaluate(bool Function(String variable) semantics) => + _selector.accept(Evaluator(semantics)); + + @override + BooleanSelector intersection(BooleanSelector other) { + if (other == BooleanSelector.all) return this; + if (other == BooleanSelector.none) return other; + return other is BooleanSelectorImpl + ? BooleanSelectorImpl._(AndNode(_selector, other._selector)) + : IntersectionSelector(this, other); + } + + @override + BooleanSelector union(BooleanSelector other) { + if (other == BooleanSelector.all) return other; + if (other == BooleanSelector.none) return this; + return other is BooleanSelectorImpl + ? BooleanSelectorImpl._(OrNode(_selector, other._selector)) + : UnionSelector(this, other); + } + + @override + void validate(bool Function(String variable) isDefined) { + _selector.accept(Validator(isDefined)); + } + + @override + String toString() => _selector.toString(); + + @override + bool operator ==(Object other) => + other is BooleanSelectorImpl && _selector == other._selector; + + @override + int get hashCode => _selector.hashCode; +}
diff --git a/pkgs/boolean_selector/lib/src/intersection_selector.dart b/pkgs/boolean_selector/lib/src/intersection_selector.dart new file mode 100644 index 0000000..3bf468c --- /dev/null +++ b/pkgs/boolean_selector/lib/src/intersection_selector.dart
@@ -0,0 +1,49 @@ +// Copyright (c) 2016, 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 '../boolean_selector.dart'; +import 'union_selector.dart'; + +/// A selector that matches inputs that both of its sub-selectors match. +class IntersectionSelector implements BooleanSelector { + final BooleanSelector _selector1; + final BooleanSelector _selector2; + + @override + Iterable<String> get variables sync* { + yield* _selector1.variables; + yield* _selector2.variables; + } + + IntersectionSelector(this._selector1, this._selector2); + + @override + bool evaluate(bool Function(String variable) semantics) => + _selector1.evaluate(semantics) && _selector2.evaluate(semantics); + + @override + BooleanSelector intersection(BooleanSelector other) => + IntersectionSelector(this, other); + + @override + BooleanSelector union(BooleanSelector other) => UnionSelector(this, other); + + @override + void validate(bool Function(String variable) isDefined) { + _selector1.validate(isDefined); + _selector2.validate(isDefined); + } + + @override + String toString() => '($_selector1) && ($_selector2)'; + + @override + bool operator ==(Object other) => + other is IntersectionSelector && + _selector1 == other._selector1 && + _selector2 == other._selector2; + + @override + int get hashCode => _selector1.hashCode ^ _selector2.hashCode; +}
diff --git a/pkgs/boolean_selector/lib/src/none.dart b/pkgs/boolean_selector/lib/src/none.dart new file mode 100644 index 0000000..08ac08a --- /dev/null +++ b/pkgs/boolean_selector/lib/src/none.dart
@@ -0,0 +1,28 @@ +// Copyright (c) 2016, 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 '../boolean_selector.dart'; + +/// A selector that matches no inputs. +class None implements BooleanSelector { + @override + final Iterable<String> variables = const []; + + const None(); + + @override + bool evaluate(bool Function(String variable) semantics) => false; + + @override + BooleanSelector intersection(BooleanSelector other) => this; + + @override + BooleanSelector union(BooleanSelector other) => other; + + @override + void validate(bool Function(String) isDefined) {} + + @override + String toString() => '<none>'; +}
diff --git a/pkgs/boolean_selector/lib/src/parser.dart b/pkgs/boolean_selector/lib/src/parser.dart new file mode 100644 index 0000000..368ce5e --- /dev/null +++ b/pkgs/boolean_selector/lib/src/parser.dart
@@ -0,0 +1,103 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:source_span/source_span.dart'; + +import 'ast.dart'; +import 'scanner.dart'; +import 'token.dart'; + +/// A class for parsing a boolean selector. +/// +/// Boolean selectors use a stripped-down version of the Dart expression syntax +/// that only contains variables, parentheses, and boolean operators. Variables +/// may also contain dashes, contrary to Dart's syntax; this allows consistency +/// with command-line arguments. +class Parser { + /// The scanner that tokenizes the selector. + final Scanner _scanner; + + Parser(String selector) : _scanner = Scanner(selector); + + /// Parses the selector. + /// + /// This must only be called once per parser. + Node parse() { + var selector = _conditional(); + + if (_scanner.peek().type != TokenType.endOfFile) { + throw SourceSpanFormatException( + 'Expected end of input.', _scanner.peek().span); + } + + return selector; + } + + /// Parses a conditional: + /// + /// conditionalExpression: + /// logicalOrExpression ("?" conditionalExpression ":" + /// conditionalExpression)? + Node _conditional() { + var condition = _or(); + if (!_scanner.scan(TokenType.questionMark)) return condition; + + var whenTrue = _conditional(); + if (!_scanner.scan(TokenType.colon)) { + throw SourceSpanFormatException('Expected ":".', _scanner.peek().span); + } + + var whenFalse = _conditional(); + return ConditionalNode(condition, whenTrue, whenFalse); + } + + /// Parses a logical or: + /// + /// logicalOrExpression: + /// logicalAndExpression ("||" logicalOrExpression)? + Node _or() { + var left = _and(); + if (!_scanner.scan(TokenType.or)) return left; + return OrNode(left, _or()); + } + + /// Parses a logical and: + /// + /// logicalAndExpression: + /// simpleExpression ("&&" logicalAndExpression)? + Node _and() { + var left = _simpleExpression(); + if (!_scanner.scan(TokenType.and)) return left; + return AndNode(left, _and()); + } + + /// Parses a simple expression: + /// + /// simpleExpression: + /// "!" simpleExpression | + /// "(" conditionalExpression ")" | + /// IDENTIFIER + Node _simpleExpression() { + var token = _scanner.next(); + switch (token.type) { + case TokenType.not: + var child = _simpleExpression(); + return NotNode(child, token.span.expand(child.span!)); + + case TokenType.leftParen: + var child = _conditional(); + if (!_scanner.scan(TokenType.rightParen)) { + throw SourceSpanFormatException( + 'Expected ")".', _scanner.peek().span); + } + return child; + + case TokenType.identifier: + return VariableNode((token as IdentifierToken).name, token.span); + + default: + throw SourceSpanFormatException('Expected expression.', token.span); + } + } +}
diff --git a/pkgs/boolean_selector/lib/src/scanner.dart b/pkgs/boolean_selector/lib/src/scanner.dart new file mode 100644 index 0000000..25c4a11 --- /dev/null +++ b/pkgs/boolean_selector/lib/src/scanner.dart
@@ -0,0 +1,144 @@ +// Copyright (c) 2016, 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:string_scanner/string_scanner.dart'; + +import 'token.dart'; + +/// A regular expression matching both whitespace and single-line comments. +/// +/// This will only match if consumes at least one character. +final _whitespaceAndSingleLineComments = RegExp(r'([ \t\n]+|//[^\n]*(\n|$))+'); + +/// A regular expression matching the body of a multi-line comment, after `/*` +/// but before `*/` or a nested `/*`. +/// +/// This will only match if it consumes at least one character. +final _multiLineCommentBody = RegExp(r'([^/*]|/[^*]|\*[^/])+'); + +/// A regular expression matching a hyphenated identifier. +/// +/// This is like a standard Dart identifier, except that it can also contain +/// hyphens. +final _hyphenatedIdentifier = RegExp(r'[a-zA-Z_-][a-zA-Z0-9_-]*'); + +/// A scanner that converts a boolean selector string into a stream of tokens. +class Scanner { + /// The underlying string scanner. + final SpanScanner _scanner; + + /// The next token to emit. + Token? _next; + + /// Whether the scanner has emitted a [TokenType.endOfFile] token. + bool _endOfFileEmitted = false; + + Scanner(String selector) : _scanner = SpanScanner(selector); + + /// Returns the next token that will be returned by [next]. + /// + /// Throws a [StateError] if a [TokenType.endOfFile] token has already been + /// consumed. + Token peek() => _next ??= _readNext(); + + /// Consumes and returns the next token in the stream. + /// + /// Throws a [StateError] if a [TokenType.endOfFile] token has already been + /// consumed. + Token next() { + var token = _next ?? _readNext(); + _endOfFileEmitted = token.type == TokenType.endOfFile; + _next = null; + return token; + } + + /// If the next token matches [type], consumes it and returns `true`; + /// otherwise, returns `false`. + /// + /// Throws a [StateError] if a [TokenType.endOfFile] token has already been + /// consumed. + bool scan(TokenType type) { + if (peek().type != type) return false; + next(); + return true; + } + + /// Scan and return the next token in the stream. + Token _readNext() { + if (_endOfFileEmitted) throw StateError('No more tokens.'); + + _consumeWhitespace(); + if (_scanner.isDone) { + return Token(TokenType.endOfFile, _scanner.spanFrom(_scanner.state)); + } + + return switch (_scanner.peekChar()) { + 0x28 /* ( */ => _scanOperator(TokenType.leftParen), + 0x29 /* ) */ => _scanOperator(TokenType.rightParen), + 0x3F /* ? */ => _scanOperator(TokenType.questionMark), + 0x3A /* : */ => _scanOperator(TokenType.colon), + 0x21 /* ! */ => _scanOperator(TokenType.not), + 0x7C /* | */ => _scanOr(), + 0x26 /* & */ => _scanAnd(), + _ => _scanIdentifier() + }; + } + + /// Scans a single-character operator and returns a token of type [type]. + /// + /// This assumes that the caller has already verified that the next character + /// is correct for the given operator. + Token _scanOperator(TokenType type) { + var start = _scanner.state; + _scanner.readChar(); + return Token(type, _scanner.spanFrom(start)); + } + + /// Scans a `||` operator and returns the appropriate token. + /// + /// This validates that the next two characters are `||`. + Token _scanOr() { + var start = _scanner.state; + _scanner.expect('||'); + return Token(TokenType.or, _scanner.spanFrom(start)); + } + + /// Scans a `&&` operator and returns the appropriate token. + /// + /// This validates that the next two characters are `&&`. + Token _scanAnd() { + var start = _scanner.state; + _scanner.expect('&&'); + return Token(TokenType.and, _scanner.spanFrom(start)); + } + + /// Scans and returns an identifier token. + Token _scanIdentifier() { + _scanner.expect(_hyphenatedIdentifier, name: 'expression'); + return IdentifierToken(_scanner.lastMatch![0]!, _scanner.lastSpan!); + } + + /// Consumes all whitespace and comments immediately following the cursor's + /// current position. + void _consumeWhitespace() { + while (_scanner.scan(_whitespaceAndSingleLineComments) || + _multiLineComment()) { + // Do nothing. + } + } + + /// Consumes a single multi-line comment. + /// + /// Returns whether or not a comment was consumed. + bool _multiLineComment() { + if (!_scanner.scan('/*')) return false; + + while (_scanner.scan(_multiLineCommentBody) || _multiLineComment()) { + // Do nothing. + } + _scanner.expect('*/'); + + return true; + } +}
diff --git a/pkgs/boolean_selector/lib/src/token.dart b/pkgs/boolean_selector/lib/src/token.dart new file mode 100644 index 0000000..19e6864 --- /dev/null +++ b/pkgs/boolean_selector/lib/src/token.dart
@@ -0,0 +1,74 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:source_span/source_span.dart'; + +/// A token in a boolean selector. +class Token { + /// The type of the token. + final TokenType type; + + /// The span indicating where this token came from. + /// + /// This is a [FileSpan] because the tokens are parsed from a single + /// continuous string, but the string itself isn't actually a file. It might + /// come from a statically-parsed annotation or from a parameter. + final FileSpan span; + + Token(this.type, this.span); +} + +/// A token representing an identifier. +class IdentifierToken implements Token { + @override + final type = TokenType.identifier; + @override + final FileSpan span; + + /// The name of the identifier. + final String name; + + IdentifierToken(this.name, this.span); + + @override + String toString() => 'identifier "$name"'; +} + +/// An enumeration of types of tokens. +class TokenType { + /// A `(` character. + static const leftParen = TokenType._('left paren'); + + /// A `)` character. + static const rightParen = TokenType._('right paren'); + + /// A `||` sequence. + static const or = TokenType._('or'); + + /// A `&&` sequence. + static const and = TokenType._('and'); + + /// A `!` character. + static const not = TokenType._('not'); + + /// A `?` character. + static const questionMark = TokenType._('question mark'); + + /// A `:` character. + static const colon = TokenType._('colon'); + + /// A named identifier. + static const identifier = TokenType._('identifier'); + + /// The end of the selector. + static const endOfFile = TokenType._('end of file'); + + /// The name of the token type. + final String name; + + const TokenType._(this.name); + + @override + String toString() => name; +}
diff --git a/pkgs/boolean_selector/lib/src/union_selector.dart b/pkgs/boolean_selector/lib/src/union_selector.dart new file mode 100644 index 0000000..e355eb2 --- /dev/null +++ b/pkgs/boolean_selector/lib/src/union_selector.dart
@@ -0,0 +1,47 @@ +// Copyright (c) 2016, 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 '../boolean_selector.dart'; +import 'intersection_selector.dart'; + +/// A selector that matches inputs that either of its sub-selectors match. +class UnionSelector implements BooleanSelector { + final BooleanSelector _selector1; + final BooleanSelector _selector2; + + UnionSelector(this._selector1, this._selector2); + + @override + List<String> get variables => + _selector1.variables.toList()..addAll(_selector2.variables); + + @override + bool evaluate(bool Function(String variable) semantics) => + _selector1.evaluate(semantics) || _selector2.evaluate(semantics); + + @override + BooleanSelector intersection(BooleanSelector other) => + IntersectionSelector(this, other); + + @override + BooleanSelector union(BooleanSelector other) => UnionSelector(this, other); + + @override + void validate(bool Function(String variable) isDefined) { + _selector1.validate(isDefined); + _selector2.validate(isDefined); + } + + @override + String toString() => '($_selector1) && ($_selector2)'; + + @override + bool operator ==(Object other) => + other is UnionSelector && + _selector1 == other._selector1 && + _selector2 == other._selector2; + + @override + int get hashCode => _selector1.hashCode ^ _selector2.hashCode; +}
diff --git a/pkgs/boolean_selector/lib/src/validator.dart b/pkgs/boolean_selector/lib/src/validator.dart new file mode 100644 index 0000000..a7f49f2 --- /dev/null +++ b/pkgs/boolean_selector/lib/src/validator.dart
@@ -0,0 +1,23 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:source_span/source_span.dart'; + +import 'ast.dart'; +import 'visitor.dart'; + +typedef _IsDefined = bool Function(String variable); + +/// An AST visitor that ensures that all variables are valid. +class Validator extends RecursiveVisitor { + final _IsDefined _isDefined; + + Validator(this._isDefined); + + @override + void visitVariable(VariableNode node) { + if (_isDefined(node.name)) return; + throw SourceSpanFormatException('Undefined variable.', node.span); + } +}
diff --git a/pkgs/boolean_selector/lib/src/visitor.dart b/pkgs/boolean_selector/lib/src/visitor.dart new file mode 100644 index 0000000..c6808c2 --- /dev/null +++ b/pkgs/boolean_selector/lib/src/visitor.dart
@@ -0,0 +1,49 @@ +// Copyright (c) 2016, 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 'ast.dart'; + +/// The interface for visitors of the boolean selector AST. +abstract class Visitor<T> { + T visitVariable(VariableNode node); + T visitNot(NotNode node); + T visitOr(OrNode node); + T visitAnd(AndNode node); + T visitConditional(ConditionalNode node); +} + +/// An abstract superclass for side-effect-based visitors. +/// +/// The default implementations of this visitor's methods just traverse the AST +/// and do nothing with it. +abstract class RecursiveVisitor implements Visitor<void> { + const RecursiveVisitor(); + + @override + void visitVariable(VariableNode node) {} + + @override + void visitNot(NotNode node) { + node.child.accept(this); + } + + @override + void visitOr(OrNode node) { + node.left.accept(this); + node.right.accept(this); + } + + @override + void visitAnd(AndNode node) { + node.left.accept(this); + node.right.accept(this); + } + + @override + void visitConditional(ConditionalNode node) { + node.condition.accept(this); + node.whenTrue.accept(this); + node.whenFalse.accept(this); + } +}
diff --git a/pkgs/boolean_selector/pubspec.yaml b/pkgs/boolean_selector/pubspec.yaml new file mode 100644 index 0000000..8d9a8b6 --- /dev/null +++ b/pkgs/boolean_selector/pubspec.yaml
@@ -0,0 +1,17 @@ +name: boolean_selector +version: 2.1.2 +description: >- + A flexible syntax for boolean expressions, based on a simplified version of + Dart's expression syntax. +repository: https://github.com/dart-lang/tools/tree/main/pkgs/boolean_selector + +environment: + sdk: ^3.1.0 + +dependencies: + source_span: ^1.8.0 + string_scanner: ^1.1.0 + +dev_dependencies: + dart_flutter_team_lints: ^3.0.0 + test: ^1.16.0
diff --git a/pkgs/boolean_selector/test/equality_test.dart b/pkgs/boolean_selector/test/equality_test.dart new file mode 100644 index 0000000..c5ccb64 --- /dev/null +++ b/pkgs/boolean_selector/test/equality_test.dart
@@ -0,0 +1,51 @@ +// Copyright (c) 2016, 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:boolean_selector/boolean_selector.dart'; +import 'package:test/test.dart'; + +void main() { + test('variable', () { + _expectEqualsSelf('foo'); + }); + + test('not', () { + _expectEqualsSelf('!foo'); + }); + + test('or', () { + _expectEqualsSelf('foo || bar'); + }); + + test('and', () { + _expectEqualsSelf('foo && bar'); + }); + + test('conditional', () { + _expectEqualsSelf('foo ? bar : baz'); + }); + + test('all', () { + expect(BooleanSelector.all, equals(BooleanSelector.all)); + }); + + test('none', () { + expect(BooleanSelector.none, equals(BooleanSelector.none)); + }); + + test("redundant parens don't matter", () { + expect(BooleanSelector.parse('foo && (bar && baz)'), + equals(BooleanSelector.parse('foo && (bar && baz)'))); + }); + + test('meaningful parens do matter', () { + expect(BooleanSelector.parse('(foo && bar) || baz'), + equals(BooleanSelector.parse('foo && bar || baz'))); + }); +} + +void _expectEqualsSelf(String selector) { + expect( + BooleanSelector.parse(selector), equals(BooleanSelector.parse(selector))); +}
diff --git a/pkgs/boolean_selector/test/evaluate_test.dart b/pkgs/boolean_selector/test/evaluate_test.dart new file mode 100644 index 0000000..2d94906 --- /dev/null +++ b/pkgs/boolean_selector/test/evaluate_test.dart
@@ -0,0 +1,59 @@ +// Copyright (c) 2016, 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:boolean_selector/boolean_selector.dart'; +import 'package:test/test.dart'; + +void main() { + group('operator:', () { + test('conditional', () { + _expectEval('true ? true : false', true); + _expectEval('true ? false : true', false); + _expectEval('false ? true : false', false); + _expectEval('false ? false : true', true); + }); + + test('or', () { + _expectEval('true || true', true); + _expectEval('true || false', true); + _expectEval('false || true', true); + _expectEval('false || false', false); + }); + + test('and', () { + _expectEval('true && true', true); + _expectEval('true && false', false); + _expectEval('false && true', false); + _expectEval('false && false', false); + }); + + test('not', () { + _expectEval('!true', false); + _expectEval('!false', true); + }); + }); + + test('with a semantics function', () { + _expectEval('foo', false, semantics: (variable) => variable.contains('a')); + _expectEval('bar', true, semantics: (variable) => variable.contains('a')); + _expectEval('baz', true, semantics: (variable) => variable.contains('a')); + }); +} + +/// Asserts that [expression] evaluates to [result] against [semantics]. +/// +/// By default, "true" is true and all other variables are "false". +void _expectEval(String expression, bool result, + {bool Function(String variable)? semantics}) { + expect(_eval(expression, semantics: semantics), equals(result), + reason: 'Expected "$expression" to evaluate to $result.'); +} + +/// Returns the result of evaluating [expression] on [semantics]. +/// +/// By default, "true" is true and all other variables are "false". +bool _eval(String expression, {bool Function(String variable)? semantics}) { + var selector = BooleanSelector.parse(expression); + return selector.evaluate(semantics ?? (v) => v == 'true'); +}
diff --git a/pkgs/boolean_selector/test/parser_test.dart b/pkgs/boolean_selector/test/parser_test.dart new file mode 100644 index 0000000..ba55e70 --- /dev/null +++ b/pkgs/boolean_selector/test/parser_test.dart
@@ -0,0 +1,298 @@ +// Copyright (c) 2016, 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:boolean_selector/src/ast.dart'; +import 'package:boolean_selector/src/parser.dart'; +import 'package:test/test.dart'; + +/// A matcher that asserts that a value is a [ConditionalNode]. +const _isConditionalNode = TypeMatcher<ConditionalNode>(); + +/// A matcher that asserts that a value is an [OrNode]. +const _isOrNode = TypeMatcher<OrNode>(); + +/// A matcher that asserts that a value is an [AndNode]. +const _isAndNode = TypeMatcher<AndNode>(); + +/// A matcher that asserts that a value is a [NotNode]. +const _isNotNode = TypeMatcher<NotNode>(); + +void main() { + group('parses a conditional expression', () { + test('with identifiers', () { + var node = _parse(' a ? b : c '); + expect(node.toString(), equals('a ? b : c')); + + expect(node.span, isNotNull); + expect(node.span!.text, equals('a ? b : c')); + expect(node.span!.start.offset, equals(2)); + expect(node.span!.end.offset, equals(11)); + }); + + test('with nested ors', () { + // Should parse as "(a || b) ? (c || d) : (e || f)". + // Should not parse as "a || (b ? (c || d) : (e || f))". + // Should not parse as "((a || b) ? (c || d) : e) || f". + // Should not parse as "a || (b ? (c || d) : e) || f". + _expectToString('a || b ? c || d : e || f', 'a || b ? c || d : e || f'); + }); + + test('with a conditional expression as branch 1', () { + // Should parse as "a ? (b ? c : d) : e". + var node = _parse('a ? b ? c : d : e'); + expect(node, _isConditionalNode); + node as ConditionalNode; // promote node + + expect(node.condition, _isVar('a')); + expect(node.whenFalse, _isVar('e')); + + expect(node.whenTrue, _isConditionalNode); + var whenTrue = node.whenTrue as ConditionalNode; + expect(whenTrue.condition, _isVar('b')); + expect(whenTrue.whenTrue, _isVar('c')); + expect(whenTrue.whenFalse, _isVar('d')); + }); + + test('with a conditional expression as branch 2', () { + // Should parse as "a ? b : (c ? d : e)". + // Should not parse as "(a ? b : c) ? d : e". + var node = _parse('a ? b : c ? d : e'); + expect(node, _isConditionalNode); + node as ConditionalNode; //promote node + + expect(node.condition, _isVar('a')); + expect(node.whenTrue, _isVar('b')); + + expect(node.whenFalse, _isConditionalNode); + var whenFalse = node.whenFalse as ConditionalNode; + expect(whenFalse.condition, _isVar('c')); + expect(whenFalse.whenTrue, _isVar('d')); + expect(whenFalse.whenFalse, _isVar('e')); + }); + + group('which must have', () { + test('an expression after the ?', () { + expect(() => _parse('a ?'), throwsFormatException); + expect(() => _parse('a ? && b'), throwsFormatException); + }); + + test('a :', () { + expect(() => _parse('a ? b'), throwsFormatException); + expect(() => _parse('a ? b && c'), throwsFormatException); + }); + + test('an expression after the :', () { + expect(() => _parse('a ? b :'), throwsFormatException); + expect(() => _parse('a ? b : && c'), throwsFormatException); + }); + }); + }); + + group('parses an or expression', () { + test('with identifiers', () { + var node = _parse(' a || b '); + expect(node, _isOrNode); + node as OrNode; //promote node + + expect(node.left, _isVar('a')); + expect(node.right, _isVar('b')); + + expect(node.span, isNotNull); + expect(node.span!.text, equals('a || b')); + expect(node.span!.start.offset, equals(2)); + expect(node.span!.end.offset, equals(8)); + }); + + test('with nested ands', () { + // Should parse as "(a && b) || (c && d)". + // Should not parse as "a && (b || c) && d". + var node = _parse('a && b || c && d'); + expect(node, _isOrNode); + node as OrNode; //promote node + + expect(node.left, _isAndNode); + var left = node.left as AndNode; + expect(left.left, _isVar('a')); + expect(left.right, _isVar('b')); + + expect(node.right, _isAndNode); + var right = node.right as AndNode; + expect(right.left, _isVar('c')); + expect(right.right, _isVar('d')); + }); + + test('with trailing ors', () { + // Should parse as "a || (b || (c || d))", although it doesn't affect the + // semantics. + var node = _parse('a || b || c || d'); + + for (var variable in ['a', 'b', 'c']) { + expect(node, _isOrNode); + node as OrNode; //promote node + + expect(node.left, _isVar(variable)); + node = node.right; + } + expect(node, _isVar('d')); + }); + + test('which must have an expression after the ||', () { + expect(() => _parse('a ||'), throwsFormatException); + expect(() => _parse('a || && b'), throwsFormatException); + }); + }); + + group('parses an and expression', () { + test('with identifiers', () { + var node = _parse(' a && b '); + expect(node, _isAndNode); + node as AndNode; //promote node + + expect(node.left, _isVar('a')); + expect(node.right, _isVar('b')); + + expect(node.span, isNotNull); + expect(node.span!.text, equals('a && b')); + expect(node.span!.start.offset, equals(2)); + expect(node.span!.end.offset, equals(8)); + }); + + test('with nested nots', () { + // Should parse as "(!a) && (!b)", obviously. + // Should not parse as "!(a && (!b))". + var node = _parse('!a && !b'); + expect(node, _isAndNode); + node as AndNode; //promote node + + expect(node.left, _isNotNode); + var left = node.left as NotNode; + expect(left.child, _isVar('a')); + + expect(node.right, _isNotNode); + var right = node.right as NotNode; + expect(right.child, _isVar('b')); + }); + + test('with trailing ands', () { + // Should parse as "a && (b && (c && d))", although it doesn't affect the + // semantics since . + var node = _parse('a && b && c && d'); + + for (var variable in ['a', 'b', 'c']) { + expect(node, _isAndNode); + node as AndNode; //promote node + + expect(node.left, _isVar(variable)); + node = node.right; + } + expect(node, _isVar('d')); + }); + + test('which must have an expression after the &&', () { + expect(() => _parse('a &&'), throwsFormatException); + expect(() => _parse('a && && b'), throwsFormatException); + }); + }); + + group('parses a not expression', () { + test('with an identifier', () { + var node = _parse(' ! a '); + expect(node, _isNotNode); + node as NotNode; //promote node + expect(node.child, _isVar('a')); + + expect(node.span, isNotNull); + expect(node.span!.text, equals('! a')); + expect(node.span!.start.offset, equals(2)); + expect(node.span!.end.offset, equals(5)); + }); + + test('with a parenthesized expression', () { + var node = _parse('!(a || b)'); + expect(node, _isNotNode); + node as NotNode; //promote node + + expect(node.child, _isOrNode); + var child = node.child as OrNode; + expect(child.left, _isVar('a')); + expect(child.right, _isVar('b')); + }); + + test('with a nested not', () { + var node = _parse('!!a'); + expect(node, _isNotNode); + node as NotNode; //promote node + + expect(node.child, _isNotNode); + var child = node.child as NotNode; + expect(child.child, _isVar('a')); + }); + + test('which must have an expression after the !', () { + expect(() => _parse('!'), throwsFormatException); + expect(() => _parse('! && a'), throwsFormatException); + }); + }); + + group('parses a parenthesized expression', () { + test('with an identifier', () { + var node = _parse('(a)'); + expect(node, _isVar('a')); + }); + + test('controls precedence', () { + // Without parentheses, this would parse as "(a || b) ? c : d". + var node = _parse('a || (b ? c : d)'); + + expect(node, _isOrNode); + node as OrNode; //promote node + + expect(node.left, _isVar('a')); + + expect(node.right, _isConditionalNode); + var right = node.right as ConditionalNode; + expect(right.condition, _isVar('b')); + expect(right.whenTrue, _isVar('c')); + expect(right.whenFalse, _isVar('d')); + }); + + group('which must have', () { + test('an expression within the ()', () { + expect(() => _parse('()'), throwsFormatException); + expect(() => _parse('( && a )'), throwsFormatException); + }); + + test('a matching )', () { + expect(() => _parse('( a'), throwsFormatException); + }); + }); + }); + + group('disallows', () { + test('an empty selector', () { + expect(() => _parse(''), throwsFormatException); + }); + + test('too many expressions', () { + expect(() => _parse('a b'), throwsFormatException); + }); + }); +} + +/// Parses [selector] and returns its root node. +Node _parse(String selector) => Parser(selector).parse(); + +/// A matcher that asserts that a value is a [VariableNode] with the given +/// [name]. +Matcher _isVar(String name) => predicate( + (dynamic value) => value is VariableNode && value.name == name, + 'is a variable named "$name"'); + +void _expectToString(String selector, [String? result]) { + result ??= selector; + expect(_toString(selector), equals(result), + reason: 'Expected toString of "$selector" to be "$result".'); +} + +String _toString(String selector) => Parser(selector).parse().toString();
diff --git a/pkgs/boolean_selector/test/scanner_test.dart b/pkgs/boolean_selector/test/scanner_test.dart new file mode 100644 index 0000000..7ad78e2 --- /dev/null +++ b/pkgs/boolean_selector/test/scanner_test.dart
@@ -0,0 +1,279 @@ +// Copyright (c) 2016, 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:boolean_selector/src/scanner.dart'; +import 'package:boolean_selector/src/token.dart'; +import 'package:test/test.dart'; + +/// A matcher that asserts that a value is a [IdentifierToken]. +const _isIdentifierToken = TypeMatcher<IdentifierToken>(); + +void main() { + group('peek()', () { + test('returns the next token without consuming it', () { + var scanner = Scanner('( )'); + expect(scanner.peek().type, equals(TokenType.leftParen)); + expect(scanner.peek().type, equals(TokenType.leftParen)); + expect(scanner.peek().type, equals(TokenType.leftParen)); + }); + + test('returns an end-of-file token at the end of a file', () { + var scanner = Scanner('( )'); + scanner.next(); + scanner.next(); + + var token = scanner.peek(); + expect(token.type, equals(TokenType.endOfFile)); + expect(token.span.start.offset, equals(3)); + expect(token.span.end.offset, equals(3)); + }); + + test('throws a StateError if called after end-of-file was consumed', () { + var scanner = Scanner('( )'); + scanner.next(); + scanner.next(); + scanner.next(); + expect(() => scanner.peek(), throwsStateError); + }); + }); + + group('next()', () { + test('consumes and returns the next token', () { + var scanner = Scanner('( )'); + expect(scanner.next().type, equals(TokenType.leftParen)); + expect(scanner.peek().type, equals(TokenType.rightParen)); + expect(scanner.next().type, equals(TokenType.rightParen)); + }); + + test('returns an end-of-file token at the end of a file', () { + var scanner = Scanner('( )'); + scanner.next(); + scanner.next(); + + var token = scanner.next(); + expect(token.type, equals(TokenType.endOfFile)); + expect(token.span.start.offset, equals(3)); + expect(token.span.end.offset, equals(3)); + }); + + test('throws a StateError if called after end-of-file was consumed', () { + var scanner = Scanner('( )'); + scanner.next(); + scanner.next(); + scanner.next(); + expect(() => scanner.next(), throwsStateError); + }); + }); + + group('scan()', () { + test('consumes a matching token and returns true', () { + var scanner = Scanner('( )'); + expect(scanner.scan(TokenType.leftParen), isTrue); + expect(scanner.peek().type, equals(TokenType.rightParen)); + }); + + test("doesn't consume a matching token and returns false", () { + var scanner = Scanner('( )'); + expect(scanner.scan(TokenType.questionMark), isFalse); + expect(scanner.peek().type, equals(TokenType.leftParen)); + }); + + test('throws a StateError called after end-of-file was consumed', () { + var scanner = Scanner('( )'); + scanner.next(); + scanner.next(); + scanner.next(); + expect(() => scanner.scan(TokenType.endOfFile), throwsStateError); + }); + }); + + group('scans a simple token:', () { + test('left paren', () => _expectSimpleScan('(', TokenType.leftParen)); + test('right paren', () => _expectSimpleScan(')', TokenType.rightParen)); + test('or', () => _expectSimpleScan('||', TokenType.or)); + test('and', () => _expectSimpleScan('&&', TokenType.and)); + test('not', () => _expectSimpleScan('!', TokenType.not)); + test('question mark', () => _expectSimpleScan('?', TokenType.questionMark)); + test('colon', () => _expectSimpleScan(':', TokenType.colon)); + }); + + group('scans an identifier that', () { + test('is simple', () { + var token = _scan(' foo '); + expect(token, _isIdentifierToken); + token as IdentifierToken; // promote token + + expect(token.name, equals('foo')); + expect(token.span.text, equals('foo')); + expect(token.span.start.offset, equals(3)); + expect(token.span.end.offset, equals(6)); + }); + + test('is a single character', () { + var token = _scan('f'); + expect(token, _isIdentifierToken); + expect((token as IdentifierToken).name, equals('f')); + }); + + test('has a leading underscore', () { + var token = _scan('_foo'); + expect(token, _isIdentifierToken); + expect((token as IdentifierToken).name, equals('_foo')); + }); + + test('has a leading dash', () { + var token = _scan('-foo'); + expect(token, _isIdentifierToken); + expect((token as IdentifierToken).name, equals('-foo')); + }); + + test('contains an underscore', () { + var token = _scan('foo_bar'); + expect(token, _isIdentifierToken); + expect((token as IdentifierToken).name, equals('foo_bar')); + }); + + test('contains a dash', () { + var token = _scan('foo-bar'); + expect(token, _isIdentifierToken); + expect((token as IdentifierToken).name, equals('foo-bar')); + }); + + test('is capitalized', () { + var token = _scan('FOO'); + expect(token, _isIdentifierToken); + expect((token as IdentifierToken).name, equals('FOO')); + }); + + test('contains numbers', () { + var token = _scan('foo123'); + expect(token, _isIdentifierToken); + expect((token as IdentifierToken).name, equals('foo123')); + }); + }); + + test('scans an empty selector', () { + expect(_scan('').type, equals(TokenType.endOfFile)); + }); + + test('scans multiple tokens', () { + var scanner = Scanner('(foo && bar)'); + + var token = scanner.next(); + expect(token.type, equals(TokenType.leftParen)); + expect(token.span.start.offset, equals(0)); + expect(token.span.end.offset, equals(1)); + + token = scanner.next(); + expect(token.type, equals(TokenType.identifier)); + expect((token as IdentifierToken).name, equals('foo')); + expect(token.span.start.offset, equals(1)); + expect(token.span.end.offset, equals(4)); + + token = scanner.next(); + expect(token.type, equals(TokenType.and)); + expect(token.span.start.offset, equals(5)); + expect(token.span.end.offset, equals(7)); + + token = scanner.next(); + expect(token.type, equals(TokenType.identifier)); + expect((token as IdentifierToken).name, equals('bar')); + expect(token.span.start.offset, equals(8)); + expect(token.span.end.offset, equals(11)); + + token = scanner.next(); + expect(token.type, equals(TokenType.rightParen)); + expect(token.span.start.offset, equals(11)); + expect(token.span.end.offset, equals(12)); + + token = scanner.next(); + expect(token.type, equals(TokenType.endOfFile)); + expect(token.span.start.offset, equals(12)); + expect(token.span.end.offset, equals(12)); + }); + + group('ignores', () { + test('a single-line comment', () { + var scanner = Scanner('( // &&\n// ||\n)'); + expect(scanner.next().type, equals(TokenType.leftParen)); + expect(scanner.next().type, equals(TokenType.rightParen)); + expect(scanner.next().type, equals(TokenType.endOfFile)); + }); + + test('a single-line comment without a trailing newline', () { + var scanner = Scanner('( // &&'); + expect(scanner.next().type, equals(TokenType.leftParen)); + expect(scanner.next().type, equals(TokenType.endOfFile)); + }); + + test('a multi-line comment', () { + var scanner = Scanner('( /* && * /\n|| */\n)'); + expect(scanner.next().type, equals(TokenType.leftParen)); + expect(scanner.next().type, equals(TokenType.rightParen)); + expect(scanner.next().type, equals(TokenType.endOfFile)); + }); + + test('a multi-line nested comment', () { + var scanner = Scanner('(/* && /* ? /* || */ : */ ! */)'); + expect(scanner.next().type, equals(TokenType.leftParen)); + expect(scanner.next().type, equals(TokenType.rightParen)); + expect(scanner.next().type, equals(TokenType.endOfFile)); + }); + + test("Dart's notion of whitespace", () { + var scanner = Scanner('( \t \n)'); + expect(scanner.next().type, equals(TokenType.leftParen)); + expect(scanner.next().type, equals(TokenType.rightParen)); + expect(scanner.next().type, equals(TokenType.endOfFile)); + }); + }); + + group('disallows', () { + test('a single |', () { + expect(() => _scan('|'), throwsFormatException); + }); + + test('"| |"', () { + expect(() => _scan('| |'), throwsFormatException); + }); + + test('a single &', () { + expect(() => _scan('&'), throwsFormatException); + }); + + test('"& &"', () { + expect(() => _scan('& &'), throwsFormatException); + }); + + test('an unknown operator', () { + expect(() => _scan('=='), throwsFormatException); + }); + + test('unicode', () { + expect(() => _scan('öh'), throwsFormatException); + }); + + test('an unclosed multi-line comment', () { + expect(() => _scan('/*'), throwsFormatException); + }); + + test('an unopened multi-line comment', () { + expect(() => _scan('*/'), throwsFormatException); + }); + }); +} + +/// Asserts that the first token scanned from [selector] has type [type], +/// and that that token's span is exactly [selector]. +void _expectSimpleScan(String selector, TokenType type) { + // Complicate the selector to test that the span covers it correctly. + var token = _scan(' $selector '); + expect(token.type, equals(type)); + expect(token.span.text, equals(selector)); + expect(token.span.start.offset, equals(3)); + expect(token.span.end.offset, equals(3 + selector.length)); +} + +/// Scans a single token from [selector]. +Token _scan(String selector) => Scanner(selector).next();
diff --git a/pkgs/boolean_selector/test/to_string_test.dart b/pkgs/boolean_selector/test/to_string_test.dart new file mode 100644 index 0000000..971e5b9 --- /dev/null +++ b/pkgs/boolean_selector/test/to_string_test.dart
@@ -0,0 +1,84 @@ +// Copyright (c) 2016, 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:boolean_selector/boolean_selector.dart'; +import 'package:test/test.dart'; + +void main() { + group('toString() for', () { + test('a variable is its name', () { + _expectToString('foo'); + _expectToString('a-b'); + }); + + group('not', () { + test("doesn't parenthesize a variable", () => _expectToString('!a')); + test("doesn't parenthesize a nested not", () => _expectToString('!!a')); + test('parenthesizes an or', () => _expectToString('!(a || b)')); + test('parenthesizes an and', () => _expectToString('!(a && b)')); + test('parenthesizes a condition', () => _expectToString('!(a ? b : c)')); + }); + + group('or', () { + test("doesn't parenthesize variables", () => _expectToString('a || b')); + test("doesn't parenthesize nots", () => _expectToString('!a || !b')); + + test("doesn't parenthesize ors", () { + _expectToString('a || b || c || d'); + _expectToString('((a || b) || c) || d', 'a || b || c || d'); + }); + + test('parenthesizes ands', + () => _expectToString('a && b || c && d', '(a && b) || (c && d)')); + + test('parenthesizes conditions', + () => _expectToString('(a ? b : c) || (e ? f : g)')); + }); + + group('and', () { + test("doesn't parenthesize variables", () => _expectToString('a && b')); + test("doesn't parenthesize nots", () => _expectToString('!a && !b')); + + test( + 'parenthesizes ors', + () => + _expectToString('(a || b) && (c || d)', '(a || b) && (c || d)')); + + test("doesn't parenthesize ands", () { + _expectToString('a && b && c && d'); + _expectToString('((a && b) && c) && d', 'a && b && c && d'); + }); + + test('parenthesizes conditions', + () => _expectToString('(a ? b : c) && (e ? f : g)')); + }); + + group('conditional', () { + test( + "doesn't parenthesize variables", () => _expectToString('a ? b : c')); + + test("doesn't parenthesize nots", () => _expectToString('!a ? !b : !c')); + + test("doesn't parenthesize ors", + () => _expectToString('a || b ? c || d : e || f')); + + test("doesn't parenthesize ands", + () => _expectToString('a && b ? c && d : e && f')); + + test('parenthesizes non-trailing conditions', () { + _expectToString('(a ? b : c) ? (e ? f : g) : h ? i : j'); + _expectToString('(a ? b : c) ? (e ? f : g) : (h ? i : j)', + '(a ? b : c) ? (e ? f : g) : h ? i : j'); + }); + }); + }); +} + +void _expectToString(String selector, [String? result]) { + result ??= selector; + expect(_toString(selector), equals(result), + reason: 'Expected toString of "$selector" to be "$result".'); +} + +String _toString(String selector) => BooleanSelector.parse(selector).toString();
diff --git a/pkgs/boolean_selector/test/validate_test.dart b/pkgs/boolean_selector/test/validate_test.dart new file mode 100644 index 0000000..ec5b7eb --- /dev/null +++ b/pkgs/boolean_selector/test/validate_test.dart
@@ -0,0 +1,20 @@ +// Copyright (c) 2016, 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:boolean_selector/boolean_selector.dart'; +import 'package:test/test.dart'; + +var _selector = BooleanSelector.parse('foo && bar && baz'); + +void main() { + test('throws if any variables are undefined', () { + expect(() => _selector.validate((variable) => variable == 'bar'), + throwsFormatException); + }); + + test("doesn't throw if all variables are defined", () { + // Should not throw. + _selector.validate((variable) => true); + }); +}
diff --git a/pkgs/boolean_selector/test/variables_test.dart b/pkgs/boolean_selector/test/variables_test.dart new file mode 100644 index 0000000..5331409 --- /dev/null +++ b/pkgs/boolean_selector/test/variables_test.dart
@@ -0,0 +1,43 @@ +// Copyright (c) 2016, 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:boolean_selector/boolean_selector.dart'; +import 'package:test/test.dart'; + +void main() { + test('a variable reports itself', () { + expect(BooleanSelector.parse('foo').variables, equals(['foo'])); + }); + + test('a negation reports its contents', () { + expect(BooleanSelector.parse('!foo').variables, equals(['foo'])); + }); + + test('a parenthesized expression reports its contents', () { + expect(BooleanSelector.parse('(foo)').variables, equals(['foo'])); + }); + + test('an or reports its contents', () { + expect( + BooleanSelector.parse('foo || bar').variables, equals(['foo', 'bar'])); + }); + + test('an and reports its contents', () { + expect( + BooleanSelector.parse('foo && bar').variables, equals(['foo', 'bar'])); + }); + + test('a conditional reports its contents', () { + expect(BooleanSelector.parse('foo ? bar : baz').variables, + equals(['foo', 'bar', 'baz'])); + }); + + test('BooleanSelector.all reports no variables', () { + expect(BooleanSelector.all.variables, isEmpty); + }); + + test('BooleanSelector.none reports no variables', () { + expect(BooleanSelector.none.variables, isEmpty); + }); +}
diff --git a/pkgs/cli_config/.gitignore b/pkgs/cli_config/.gitignore new file mode 100644 index 0000000..58e48f3 --- /dev/null +++ b/pkgs/cli_config/.gitignore
@@ -0,0 +1,9 @@ +# https://dart.dev/guides/libraries/private-files +# Created by `dart pub` +.dart_tool/ + +# Avoid committing pubspec.lock for library packages; see +# https://dart.dev/guides/libraries/private-files#pubspeclock. +pubspec.lock + +coverage/
diff --git a/pkgs/cli_config/CHANGELOG.md b/pkgs/cli_config/CHANGELOG.md new file mode 100644 index 0000000..55fcd2d --- /dev/null +++ b/pkgs/cli_config/CHANGELOG.md
@@ -0,0 +1,22 @@ +## 0.2.1-wip + +- Require Dart 3.4. + +## 0.2.0 + +- **Breaking Change** Rename `Config.fromArgs` to `Config.fromArguments`. +- Add `Config.fromArgumentsSync`. + +## 0.1.2 + +- Add usage docs to the readme. +- Require Dart 3.0. + +## 0.1.1 + +- Support non-String map keys in YAML configuration files. +- Support null values in YAML configuration files. + +## 0.1.0 + +- Initial version.
diff --git a/pkgs/cli_config/LICENSE b/pkgs/cli_config/LICENSE new file mode 100644 index 0000000..ac90031 --- /dev/null +++ b/pkgs/cli_config/LICENSE
@@ -0,0 +1,27 @@ +Copyright 2023, the Dart project authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google LLC nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file
diff --git a/pkgs/cli_config/README.md b/pkgs/cli_config/README.md new file mode 100644 index 0000000..54c08e4 --- /dev/null +++ b/pkgs/cli_config/README.md
@@ -0,0 +1,71 @@ +[](https://github.com/dart-lang/tools/actions/workflows/cli_config.yml) +[](https://coveralls.io/github/dart-lang/tools?branch=main) +[](https://pub.dev/packages/cli_config) +[](https://pub.dev/packages/cli_config/publisher) + +A library to take config values from configuration files, CLI arguments, and +environment variables. + +## Usage + +Configuration can be provided from commandline arguments, environment variables, +and configuration files. This library makes these accessible via a uniform API. + +Configuration can be provided via the three sources as follows: +1. commandline argument defines as `-Dsome_key=some_value`, +2. environment variables as `SOME_KEY=some_value`, and +3. config files as JSON or YAML as `{'some_key': 'some_value'}`. + +The default lookup behavior is that commandline argument defines take precedence +over environment variables, which take precedence over the configuration file. + +If a single value is requested from this configuration, the first source that +can provide the value will provide it. For example +`config.string('some_key')` with `{'some_key': 'file_value'}` in the config file +and `-Dsome_key=cli_value` as commandline argument returns +`'cli_value'`. The implication is that you can not remove keys from the +configuration file, only overwrite or append them. + +If a list value is requested from this configuration, the values provided by the +various sources can be combined or not. For example +`config.optionalStringList('some_key', combineAllConfigs: true)` returns +`['cli_value', 'file_value']`. + +The config is hierarchical in nature, using `.` as the hierarchy separator for +lookup and commandline defines. The hierarchy should be materialized in the JSON +or YAML configuration file. For environment variables `__` is used as hierarchy +separator. + +Hierarchical configuration can be provided via the three sources as follows: +1. commandline argument defines as `-Dsome_key.some_nested_key=some_value`, +2. environment variables as `SOME_KEY__SOME_NESTED_KEY=some_value`, and +3. config files as JSON or YAML as + ```yaml + some_key: + some_nested_key: + some_value + ``` + +The config is opinionated on the format of the keys in the sources. +* Command-line argument keys should be lower-cased alphanumeric + characters or underscores, with `.` for hierarchy. +* Environment variables keys should be upper-cased alphanumeric + characters or underscores, with `__` for hierarchy. +* Config files keys should be lower-cased alphanumeric + characters or underscores. + +In the API they are made available lower-cased and with underscores, and +`.` as hierarchy separator. + +## Example usage + +This example creates a configuration which first looks for command-line defines +in the `arguments` list then looks in `Platform.environment`, then looks in any +local configuration file. + +```dart +final config = await Config.fromArguments(arguments: arguments); +final pathValue = + config.optionalPath('my_path', resolveUri: true, mustExist: false); +print(pathValue?.toFilePath()); +```
diff --git a/pkgs/cli_config/analysis_options.yaml b/pkgs/cli_config/analysis_options.yaml new file mode 100644 index 0000000..dd3dcda --- /dev/null +++ b/pkgs/cli_config/analysis_options.yaml
@@ -0,0 +1,12 @@ +include: package:dart_flutter_team_lints/analysis_options.yaml + +analyzer: + language: + strict-raw-types: true + +linter: + rules: + - prefer_const_declarations + - prefer_expression_function_bodies + - prefer_final_in_for_each + - prefer_final_locals
diff --git a/pkgs/cli_config/example/bin/cli_config_example.dart b/pkgs/cli_config/example/bin/cli_config_example.dart new file mode 100644 index 0000000..1256bd7 --- /dev/null +++ b/pkgs/cli_config/example/bin/cli_config_example.dart
@@ -0,0 +1,12 @@ +// 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:cli_config/cli_config.dart'; + +Future<void> main(List<String> args) async { + final config = await Config.fromArguments(arguments: args); + final myPath = + config.optionalPath('my_path', resolveUri: true, mustExist: false); + print(myPath?.toFilePath()); +}
diff --git a/pkgs/cli_config/example/pubspec.yaml b/pkgs/cli_config/example/pubspec.yaml new file mode 100644 index 0000000..cec900a --- /dev/null +++ b/pkgs/cli_config/example/pubspec.yaml
@@ -0,0 +1,11 @@ +name: cli_config_example +description: An example for cli_config. + +publish_to: none + +environment: + sdk: ">=2.19.3 <4.0.0" + +dependencies: + cli_config: + path: ../
diff --git a/pkgs/cli_config/lib/cli_config.dart b/pkgs/cli_config/lib/cli_config.dart new file mode 100644 index 0000000..51df312 --- /dev/null +++ b/pkgs/cli_config/lib/cli_config.dart
@@ -0,0 +1,9 @@ +// 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. + +/// A library to take config values from configuration files, CLI arguments, +/// and environment variables. +library; + +export 'src/config.dart';
diff --git a/pkgs/cli_config/lib/src/cli_parser.dart b/pkgs/cli_config/lib/src/cli_parser.dart new file mode 100644 index 0000000..9396a7a --- /dev/null +++ b/pkgs/cli_config/lib/src/cli_parser.dart
@@ -0,0 +1,53 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:args/args.dart'; + +class CliParser { + final ArgParser parser = () { + final parser = ArgParser(); + parser.addFlag( + 'help', + abbr: 'h', + help: 'Show this help.', + ); + parser.addMultiOption( + 'define', + abbr: 'D', + help: '''Define or override a config property from command line. +The same option can be passed multiple times. +Keys should only contain lower-case alphanumeric characters, underscores, +and '.'s''', + ); + parser.addOption( + 'config', + abbr: 'c', + help: '''Path to JSON or YAML config file. +Keys should only contain lower-case alphanumeric characters, and underscores. +Hierarchies should be maps.''', + ); + return parser; + }(); + + ArgResults parse(List<String> args) => parser.parse(args); +} + +class DefinesParser { + static final _defineRegex = RegExp('([a-z_.]+)=(.+)'); + + Map<String, List<String>> parse(List<String> args) { + final defines = <String, List<String>>{}; + for (final arg in args) { + final match = _defineRegex.matchAsPrefix(arg); + if (match == null || match.group(0) != arg) { + throw FormatException("Define '$arg' does not match expected pattern " + "'${_defineRegex.pattern}'."); + } + final key = match.group(1)!; + final value = match.group(2)!; + defines[key] = (defines[key] ?? [])..add(value); + } + return defines; + } +}
diff --git a/pkgs/cli_config/lib/src/cli_source.dart b/pkgs/cli_config/lib/src/cli_source.dart new file mode 100644 index 0000000..20e662c --- /dev/null +++ b/pkgs/cli_config/lib/src/cli_source.dart
@@ -0,0 +1,95 @@ +// 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 'config.dart'; +import 'source.dart'; + +class CliSource extends Source { + /// Configuration options passed in via CLI arguments. + /// + /// Options can be passed multiple times, so the values here are a list. + /// + /// Stored as a flat non-hierarchical structure, keys contain `.`. + final Map<String, List<String>> _cli; + + /// If provided, used to resolve paths within [_cli]. + /// + /// Typically the current working directory at application start. + @override + final Uri? baseUri; + + CliSource(this._cli, this.baseUri); + + @override + String? optionalString(String key) { + final value = _cli[key]; + if (value == null) { + return null; + } + if (value.length > 1) { + throw FormatException( + "More than one value was passed for '$key' in the CLI defines." + ' Values passed: $value'); + } + return value.single; + } + + @override + List<String>? optionalStringList( + String key, { + String? splitPattern, + }) { + final cliValue = _cli[key]; + if (cliValue == null) { + return null; + } + if (splitPattern != null) { + return [for (final value in cliValue) ...value.split(splitPattern)]; + } + return cliValue; + } + + @override + bool? optionalBool(String key) { + final stringValue = optionalString(key); + if (stringValue != null) { + Source.throwIfUnexpectedValue(key, stringValue, Config.boolStrings.keys); + return Config.boolStrings[stringValue]!; + } + return null; + } + + @override + int? optionalInt(String key) { + final stringValue = optionalString(key); + if (stringValue != null) { + try { + return int.parse(stringValue); + } on FormatException catch (e) { + throw FormatException( + "Unexpected value '$stringValue' for key '$key'. Expected an int." + ' ${e.message}'); + } + } + return null; + } + + @override + double? optionalDouble(String key) { + final stringValue = optionalString(key); + if (stringValue != null) { + try { + return double.parse(stringValue); + } on FormatException catch (e) { + throw FormatException( + "Unexpected value '$stringValue' for key '$key'. Expected a double." + ' ${e.message}'); + } + } + return null; + } + + @override + String toString() => 'CliSource($_cli)'; +}
diff --git a/pkgs/cli_config/lib/src/config.dart b/pkgs/cli_config/lib/src/config.dart new file mode 100644 index 0000000..85e2c0c --- /dev/null +++ b/pkgs/cli_config/lib/src/config.dart
@@ -0,0 +1,650 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:core' as core show bool, double, int; +import 'dart:core' hide bool, double, int; +import 'dart:io'; + +import 'cli_parser.dart'; +import 'cli_source.dart'; +import 'environment_parser.dart'; +import 'environment_source.dart'; +import 'file_parser.dart'; +import 'file_source.dart'; +import 'source.dart'; + +/// A hierarchical configuration. +/// +/// Configuration can be provided from three sources: commandline arguments, +/// environment variables and configuration files. This configuration makes +/// these accessible via a uniform API. +/// +/// Configuration can be provided via the three sources as follows: +/// 1. commandline argument defines as `-Dsome_key=some_value`, +/// 2. environment variables as `SOME_KEY=some_value`, and +/// 3. config files as JSON or YAML as `{'some_key': 'some_value'}`. +/// +/// The default lookup behavior is that commandline argument defines take +/// precedence over environment variables, which take precedence over the +/// configuration file. +/// +/// If a single value is requested from this configuration, the first source +/// that can provide the value will provide it. For example +/// `config.string('some_key')` with `{'some_key': 'file_value'}` in the +/// config file and `-Dsome_key=cli_value` as commandline argument returns +/// `'cli_value'`. The implication is that you can not remove keys from the +/// configuration file, only overwrite or append them. +/// +/// If a list value is requested from this configuration, the values provided +/// by the various sources can be combined or not. For example +/// `config.optionalStringList('some_key', combineAllConfigs: true)` returns +/// `['cli_value', 'file_value']`. +/// +/// The config is hierarchical in nature, using `.` as the hierarchy separator +/// for lookup and commandline defines. The hierarchy should be materialized in +/// the JSON or YAML configuration file. For environment variables `__` is used +/// as hierarchy separator. +/// +/// Hierarchical configuration can be provided via the three sources as follows: +/// 1. commandline argument defines as `-Dsome_key.some_nested_key=some_value`, +/// 2. environment variables as `SOME_KEY__SOME_NESTED_KEY=some_value`, and +/// 3. config files as JSON or YAML as +/// ```yaml +/// some_key: +/// some_nested_key: +/// some_value +/// ``` +/// +/// The config is opinionated on the format of the keys in the sources. +/// * Command-line argument keys should be lower-cased alphanumeric +/// characters or underscores, with `.` for hierarchy. +/// * Environment variables keys should be upper-cased alphanumeric +/// characters or underscores, with `__` for hierarchy. +/// * Config files keys should be lower-cased alphanumeric +/// characters or underscores. +/// +/// In the API they are made available lower-cased and with underscores, and +/// `.` as hierarchy separator. +class Config { + final CliSource _cliSource; + final EnvironmentSource _environmentSource; + final FileSource _fileSource; + + /// Config sources, ordered by precedence. + late final _sources = [_cliSource, _environmentSource, _fileSource]; + + Config._( + this._cliSource, + this._environmentSource, + this._fileSource, + ); + + /// Constructs a config by parsing the three sources. + /// + /// If provided, [commandLineDefines] must be a list of `<key>=<value>`. + /// + /// If provided, [workingDirectory] is used to resolves paths inside + /// [commandLineDefines]. + /// + /// If provided, [environment] must be a map containing environment variables. + /// + /// If provided, [fileParsed] must be valid parsed YSON or YAML (maps, lists, + /// strings, integers, and booleans). + /// + /// If provided [fileSourceUri] is used to resolve paths inside + /// [fileParsed] and to provide better error messages on parsing the + /// configuration file. + factory Config({ + List<String> commandLineDefines = const [], + Uri? workingDirectory, + Map<String, String> environment = const {}, + Map<String, dynamic> fileParsed = const {}, + Uri? fileSourceUri, + }) { + // Parse config file. + final fileConfig = FileParser().parseToplevelMap(fileParsed); + + // Parse CLI argument defines. + final cliConfig = DefinesParser().parse(commandLineDefines); + + // Parse environment. + final environmentConfig = EnvironmentParser().parse(environment); + + return Config._( + CliSource(cliConfig, workingDirectory?.normalizePath()), + EnvironmentSource(environmentConfig), + FileSource(fileConfig, fileSourceUri?.normalizePath()), + ); + } + + /// Constructs a config by parsing the three sources. + /// + /// If provided, [commandLineDefines] must be a list of `<key>=<value>`. + /// + /// If provided, [workingDirectory] is used to resolves paths inside + /// [commandLineDefines]. + /// + /// If provided, [environment] must be a map containing environment variables. + /// + /// If provided, [fileContents] must be valid JSON or YAML. + /// + /// If provided [fileSourceUri] is used to resolve paths inside + /// [fileContents] and to provide better error messages on parsing the + /// configuration file. + factory Config.fromConfigFileContents({ + List<String> commandLineDefines = const [], + Uri? workingDirectory, + Map<String, String> environment = const {}, + String? fileContents, + Uri? fileSourceUri, + }) { + // Parse config file. + final Map<String, dynamic> fileConfig; + if (fileContents != null) { + fileConfig = FileParser().parse( + fileContents, + sourceUrl: fileSourceUri, + ); + } else { + fileConfig = {}; + } + + // Parse CLI argument defines. + final cliConfig = DefinesParser().parse(commandLineDefines); + + // Parse environment. + final environmentConfig = EnvironmentParser().parse(environment); + + return Config._( + CliSource(cliConfig, workingDirectory), + EnvironmentSource(environmentConfig), + FileSource(fileConfig, fileSourceUri), + ); + } + + /// Constructs a config by parsing CLI arguments and loading the config file. + /// + /// The [arguments] must be commandline arguments. + /// + /// If provided, [environment] must be a map containing environment variables. + /// If not provided, [environment] defaults to [Platform.environment]. + /// + /// If provided, [workingDirectory] is used to resolves paths inside + /// [environment]. + /// If not provided, [workingDirectory] defaults to [Directory.current]. + /// + /// This async constructor is intended to be used directly in CLI files. + static Future<Config> fromArguments({ + required List<String> arguments, + Map<String, String>? environment, + Uri? workingDirectory, + }) async { + final results = CliParser().parse(arguments); + + // Load config file. + final configFile = results['config'] as String?; + String? fileContents; + Uri? fileSourceUri; + if (configFile != null) { + fileContents = await File(configFile).readAsString(); + fileSourceUri = Uri.file(configFile); + } + + return Config.fromConfigFileContents( + commandLineDefines: results['define'] as List<String>, + workingDirectory: workingDirectory ?? Directory.current.uri, + environment: environment ?? Platform.environment, + fileContents: fileContents, + fileSourceUri: fileSourceUri, + ); + } + + /// Constructs a config by parsing CLI arguments and loading the config file. + /// + /// The [arguments] must be commandline arguments. + /// + /// If provided, [environment] must be a map containing environment variables. + /// If not provided, [environment] defaults to [Platform.environment]. + /// + /// If provided, [workingDirectory] is used to resolves paths inside + /// [environment]. + /// If not provided, [workingDirectory] defaults to [Directory.current]. + /// + /// This synchronous constructor is intended to be used directly in CLI files. + static Config fromArgumentsSync({ + required List<String> arguments, + Map<String, String>? environment, + Uri? workingDirectory, + }) { + final results = CliParser().parse(arguments); + + // Load config file. + final configFile = results['config'] as String?; + String? fileContents; + Uri? fileSourceUri; + if (configFile != null) { + fileContents = File(configFile).readAsStringSync(); + fileSourceUri = Uri.file(configFile); + } + + return Config.fromConfigFileContents( + commandLineDefines: results['define'] as List<String>, + workingDirectory: workingDirectory ?? Directory.current.uri, + environment: environment ?? Platform.environment, + fileContents: fileContents, + fileSourceUri: fileSourceUri, + ); + } + + /// Lookup a string value in this config. + /// + /// First tries CLI argument defines, then environment variables, and + /// finally the config file. + /// + /// Throws if one of the configs does not contain the expected value type. + /// + /// If [validValues] is provided, throws if an unxpected value is provided. + String string(String key, {Iterable<String>? validValues}) { + final value = optionalString(key, validValues: validValues); + _throwIfNull(key, value); + return value!; + } + + /// Lookup an optional string value in this config. + /// + /// First tries CLI argument defines, then environment variables, and + /// finally the config file. + /// + /// If [validValues] is provided, throws if an unxpected value is provided. + String? optionalString(String key, {Iterable<String>? validValues}) { + String? value; + for (final source in _sources) { + value ??= source.optionalString(key); + } + if (value != null && validValues != null) { + Source.throwIfUnexpectedValue(key, value, validValues); + } + return value; + } + + /// Lookup an optional string list in this config. + /// + /// If none of the sources provide a list, lookup will fail. + /// If an empty list is provided by one of the sources, lookup wil succeed. + /// + /// First tries CLI argument defines, then environment variables, and + /// finally the config file. + /// + /// If [combineAllConfigs] combines results from cli, environment, and + /// config file. Otherwise, precedence rules apply. + /// + /// If provided, [splitCliPattern] splits cli defines. + /// For example: `-Dfoo=bar;baz` can be split on `;`. + /// If not provided, a list can still be provided with multiple cli defines. + /// For example: `-Dfoo=bar -Dfoo=baz`. + /// + /// If provided, [splitEnvironmentPattern] splits environment values. + List<String> stringList( + String key, { + core.bool combineAllConfigs = true, + String? splitCliPattern, + String? splitEnvironmentPattern, + }) { + final value = optionalStringList( + key, + combineAllConfigs: combineAllConfigs, + splitCliPattern: splitCliPattern, + splitEnvironmentPattern: splitEnvironmentPattern, + ); + _throwIfNull(key, value); + return value!; + } + + /// Lookup an optional string list in this config. + /// + /// First tries CLI argument defines, then environment variables, and + /// finally the config file. + /// + /// If [combineAllConfigs] combines results from cli, environment, and + /// config file. Otherwise, precedence rules apply. + /// + /// If provided, [splitCliPattern] splits cli defines. + /// For example: `-Dfoo=bar;baz` can be split on `;`. + /// If not provided, a list can still be provided with multiple cli defines. + /// For example: `-Dfoo=bar -Dfoo=baz`. + /// + /// If provided, [splitEnvironmentPattern] splits environment values. + List<String>? optionalStringList( + String key, { + core.bool combineAllConfigs = true, + String? splitCliPattern, + String? splitEnvironmentPattern, + }) { + List<String>? result; + for (final entry in { + _cliSource: splitCliPattern, + _environmentSource: splitEnvironmentPattern, + _fileSource: null + }.entries) { + final source = entry.key; + final splitPattern = entry.value; + final value = source.optionalStringList(key, splitPattern: splitPattern); + if (value != null) { + if (combineAllConfigs) { + (result ??= []).addAll(value); + } else { + return value; + } + } + } + return result; + } + + static const boolStrings = { + '0': false, + '1': true, + 'false': false, + 'FALSE': false, + 'no': false, + 'NO': false, + 'true': true, + 'TRUE': true, + 'yes': true, + 'YES': true, + }; + + /// Lookup a boolean value in this config. + /// + /// First tries CLI argument defines, then environment variables, and + /// finally the config file. + /// + /// For cli defines and environment variables, the value must be one of + /// [boolStrings]. + /// For the config file, it must be a boolean. + /// + /// Throws if one of the configs does not contain the expected value type. + core.bool bool(String key) { + final value = optionalBool(key); + _throwIfNull(key, value); + return value!; + } + + /// Lookup an optional boolean value in this config. + /// + /// First tries CLI argument defines, then environment variables, and + /// finally the config file. + /// + /// For cli defines and environment variables, the value must be one of + /// [boolStrings]. + /// For the config file, it must be a boolean or null. + core.bool? optionalBool(String key) { + core.bool? value; + for (final source in _sources) { + value ??= source.optionalBool(key); + } + return value; + } + + /// Lookup an integer value in this config. + /// + /// First tries CLI argument defines, then environment variables, and + /// finally the config file. + /// + /// For cli defines and environment variables, the value must be parseble + /// by [core.int.parse]. + /// For the config file, it must be an integer. + core.int int(String key) { + final value = optionalInt(key); + _throwIfNull(key, value); + return value!; + } + + /// Lookup an optional integer value in this config. + /// + /// First tries CLI argument defines, then environment variables, and + /// finally the config file. + /// + /// For cli defines and environment variables, the value must be parseble + /// by [core.int.parse]. + /// For the config file, it must be an integer or null. + core.int? optionalInt(String key) { + core.int? value; + for (final source in _sources) { + value ??= source.optionalInt(key); + } + return value; + } + + /// Lookup an double value in this config. + /// + /// First tries CLI argument defines, then environment variables, and + /// finally the config file. + /// + /// For cli defines and environment variables, the value must be parseble + /// by [core.double.parse]. + /// For the config file, it must be an double. + core.double double(String key) { + final value = optionalDouble(key); + _throwIfNull(key, value); + return value!; + } + + /// Lookup an optional double value in this config. + /// + /// First tries CLI argument defines, then environment variables, and + /// finally the config file. + /// + /// For cli defines and environment variables, the value must be parseble + /// by [core.double.parse]. + /// For the config file, it must be an double or null. + core.double? optionalDouble(String key) { + core.double? value; + for (final source in _sources) { + value ??= source.optionalDouble(key); + } + return value; + } + + /// Lookup a path in this config. + /// + /// First tries CLI argument defines, then environment variables, and + /// finally the config file. + /// + /// Throws if one of the configs does not contain the expected value type. + /// + /// If [resolveUri], resolves the paths in a source relative to the base + /// uri of that source. The base uri for the config file is the path of the + /// file. The base uri for environment values is the current working + /// directory. + /// + /// If [mustExist], throws if the path doesn't resolve to a file or directory + /// on the file system. + /// + /// Throws if one of the configs does not contain the expected value type. + Uri path( + String key, { + core.bool resolveUri = true, + core.bool mustExist = false, + }) { + final value = + optionalPath(key, resolveUri: resolveUri, mustExist: mustExist); + _throwIfNull(key, value); + return value!; + } + + /// Lookup an optional path in this config. + /// + /// First tries CLI argument defines, then environment variables, and + /// finally the config file. + /// + /// Throws if one of the configs does not contain the expected value type. + /// + /// If [resolveUri], resolves the paths in a source relative to the base + /// uri of that source. The base uri for the config file is the path of the + /// file. The base uri for environment values is the current working + /// directory. + /// + /// If [mustExist], throws if the path doesn't resolve to a file or directory + /// on the file system. + Uri? optionalPath( + String key, { + core.bool resolveUri = true, + core.bool mustExist = false, + }) { + for (final source in _sources) { + final path = source.optionalString(key); + if (path != null) { + final value = _pathToUri( + path, + resolveUri: resolveUri, + baseUri: source.baseUri, + ); + if (mustExist) { + _throwIfNotExists(key, value); + } + return value; + } + } + return null; + } + + Uri _pathToUri( + String path, { + required core.bool resolveUri, + required Uri? baseUri, + }) { + final uri = Source.fileSystemPathToUri(path); + if (resolveUri && baseUri != null) { + return baseUri.resolveUri(uri); + } + return uri; + } + + /// Lookup a list of paths in this config. + /// + /// If none of the sources provide a path, lookup will fail. + /// If an empty list is provided by one of the sources, lookup wil succeed. + /// + /// If [combineAllConfigs] combines results from cli, environment, and + /// config file. Otherwise, precedence rules apply. + /// + /// If provided, [splitCliPattern] splits cli defines. + /// + /// If provided, [splitEnvironmentPattern] splits environment values. + /// + /// If [resolveUri], resolves the paths in a source relative to the base + /// uri of that source. The base uri for the config file is the path of the + /// file. The base uri for environment values is the current working + /// directory. + List<Uri> pathList( + String key, { + core.bool combineAllConfigs = true, + String? splitCliPattern, + String? splitEnvironmentPattern, + core.bool resolveUri = true, + }) { + final value = optionalPathList( + key, + combineAllConfigs: combineAllConfigs, + splitCliPattern: splitCliPattern, + splitEnvironmentPattern: splitEnvironmentPattern, + resolveUri: resolveUri, + ); + _throwIfNull(key, value); + return value!; + } + + /// Lookup an optional list of paths in this config. + /// + /// If [combineAllConfigs] combines results from cli, environment, and + /// config file. Otherwise, precedence rules apply. + /// + /// If provided, [splitCliPattern] splits cli defines. + /// + /// If provided, [splitEnvironmentPattern] splits environment values. + /// + /// If [resolveUri], resolves the paths in a source relative to the base + /// uri of that source. The base uri for the config file is the path of the + /// file. The base uri for environment values is the current working + /// directory. + List<Uri>? optionalPathList( + String key, { + core.bool combineAllConfigs = true, + String? splitCliPattern, + String? splitEnvironmentPattern, + core.bool resolveUri = true, + }) { + List<Uri>? result; + for (final entry in { + _cliSource: splitCliPattern, + _environmentSource: splitEnvironmentPattern, + _fileSource: null + }.entries) { + final source = entry.key; + final splitPattern = entry.value; + final paths = source.optionalStringList( + key, + splitPattern: splitPattern, + ); + if (paths != null) { + final value = [ + for (final path in paths) + _pathToUri( + path, + resolveUri: resolveUri, + baseUri: source.baseUri, + ) + ]; + if (combineAllConfigs) { + (result ??= []).addAll(value); + } else { + return value; + } + } + } + return result; + } + + /// Lookup a value of type [T] in this configuration. + /// + /// Does not support specialized options such as `splitPattern`. One must + /// use the specialized methods such as [optionalStringList] for that. + /// + /// If sources cannot lookup type [T], they return null. + T valueOf<T>(String key) { + T? value; + for (final source in _sources) { + value ??= source.optionalValueOf<T>(key); + } + if (null is! T) { + _throwIfNull(key, value); + } + return value as T; + } + + void _throwIfNull(String key, Object? value) { + if (value == null) { + throw FormatException('No value was provided for required key: $key'); + } + } + + void _throwIfNotExists(String key, Uri value) { + final fileSystemEntity = value.fileSystemEntity; + if (!fileSystemEntity.existsSync()) { + throw FormatException("Path '$value' for key '$key' doesn't exist."); + } + } + + @override + String toString() => 'Config($_sources)'; +} + +extension on Uri { + FileSystemEntity get fileSystemEntity { + if (path.endsWith(Platform.pathSeparator) || path.endsWith('/')) { + return Directory.fromUri(this); + } + return File.fromUri(this); + } +}
diff --git a/pkgs/cli_config/lib/src/environment_parser.dart b/pkgs/cli_config/lib/src/environment_parser.dart new file mode 100644 index 0000000..d91b8fa --- /dev/null +++ b/pkgs/cli_config/lib/src/environment_parser.dart
@@ -0,0 +1,19 @@ +// 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. + +class EnvironmentParser { + /// Parses an environment key into an config key. + /// + /// Environment keys can only contain alphanumeric characters and underscores. + /// Treats `__` as hierarchy separator, and replaces it with `.`. + /// + /// Often, environment variables are uppercased. + /// Replaces all uppercase characters with lowercase characters. + String parseKey(String key) => key.replaceAll('__', '.').toLowerCase(); + + Map<String, String> parse(Map<String, String> environment) => { + for (final entry in environment.entries) + parseKey(entry.key): entry.value, + }; +}
diff --git a/pkgs/cli_config/lib/src/environment_source.dart b/pkgs/cli_config/lib/src/environment_source.dart new file mode 100644 index 0000000..9cff18f --- /dev/null +++ b/pkgs/cli_config/lib/src/environment_source.dart
@@ -0,0 +1,86 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:io'; + +import 'config.dart'; +import 'source.dart'; + +class EnvironmentSource extends Source { + /// Configuration options passed in via the [Platform.environment]. + /// + /// The keys have been transformed by `EnvironmentParser.parseKey`. + /// + /// Environment values are left intact. + /// + /// Stored as a flat non-hierarchical structure, keys contain `.`. + final Map<String, String> _environment; + + EnvironmentSource(this._environment); + + @override + String? optionalString(String key) => _environment[key]; + + @override + List<String>? optionalStringList( + String key, { + String? splitPattern, + }) { + final envValue = _environment[key]; + if (envValue == null) { + return null; + } + if (splitPattern != null) { + return envValue.split(splitPattern); + } + return [envValue]; + } + + @override + bool? optionalBool(String key) { + final stringValue = optionalString(key); + if (stringValue != null) { + Source.throwIfUnexpectedValue(key, stringValue, Config.boolStrings.keys); + return Config.boolStrings[stringValue]!; + } + return null; + } + + @override + int? optionalInt(String key) { + final stringValue = optionalString(key); + if (stringValue != null) { + try { + return int.parse(stringValue); + } on FormatException catch (e) { + throw FormatException( + "Unexpected value '$stringValue' for key '$key'. Expected an int." + ' ${e.message}'); + } + } + return null; + } + + @override + double? optionalDouble(String key) { + final stringValue = optionalString(key); + if (stringValue != null) { + try { + return double.parse(stringValue); + } on FormatException catch (e) { + throw FormatException( + "Unexpected value '$stringValue' for key '$key'. Expected a double." + ' ${e.message}'); + } + } + return null; + } + + @override + String toString() => 'EnvironmentSource($_environment)'; + + /// Environment path are not resolved. + @override + Uri? get baseUri => null; +}
diff --git a/pkgs/cli_config/lib/src/file_parser.dart b/pkgs/cli_config/lib/src/file_parser.dart new file mode 100644 index 0000000..2a647e5 --- /dev/null +++ b/pkgs/cli_config/lib/src/file_parser.dart
@@ -0,0 +1,46 @@ +// 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:yaml/yaml.dart'; + +class FileParser { + Map<String, Object?> parse( + String fileContents, { + Uri? sourceUrl, + }) { + final parsedYaml = loadYaml( + fileContents, + sourceUrl: sourceUrl, + ); + if (parsedYaml is! Map) { + throw const FormatException( + 'YAML config must be set of key value pairs.'); + } + return parseToplevelMap(parsedYaml); + } + + Map<String, Object?> parseToplevelMap(Map<dynamic, dynamic> input) { + final result = <String, Object?>{}; + for (final entry in input.entries) { + final key = parseToplevelKey(entry.key); + final value = entry.value as Object?; + result[key] = value; + } + return result; + } + + static final _keyRegex = RegExp('([a-z-_]+)'); + + String parseToplevelKey(Object? key) { + if (key is! String) { + throw FormatException("Key '$key' is not a String."); + } + final match = _keyRegex.matchAsPrefix(key); + if (match == null || match.group(0) != key) { + throw FormatException("Define '$key' does not match expected pattern " + "'${_keyRegex.pattern}'."); + } + return key.replaceAll('-', '_'); + } +}
diff --git a/pkgs/cli_config/lib/src/file_source.dart b/pkgs/cli_config/lib/src/file_source.dart new file mode 100644 index 0000000..d0594c6 --- /dev/null +++ b/pkgs/cli_config/lib/src/file_source.dart
@@ -0,0 +1,68 @@ +// 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 'source.dart'; + +class FileSource extends Source { + /// Configuration options passed in via a JSON or YAML configuration file. + /// + /// Stored as a partial hierarchical data structure. The values can be maps + /// in which subsequent parts of a key after a `.` can be resolved. + final Map<String, dynamic> _file; + + /// If provided, used to resolve paths within [_file]. + @override + final Uri? baseUri; + + FileSource(this._file, this.baseUri); + + @override + String? optionalString(String key) => optionalValueOf<String>(key); + + @override + List<String>? optionalStringList( + String key, { + String? splitPattern, + }) { + assert(splitPattern == null); + return optionalValueOf<List<dynamic>>(key)?.cast<String>(); + } + + @override + bool? optionalBool(String key) => optionalValueOf<bool>(key); + + @override + int? optionalInt(String key) => optionalValueOf<int>(key); + + @override + double? optionalDouble(String key) => optionalValueOf<double>(key); + + @override + T? optionalValueOf<T>(String key) { + Object? cursor = _file; + var current = ''; + for (final keyPart in key.split('.')) { + if (cursor == null) { + return null; + } + if (cursor is! Map) { + throw FormatException( + "Unexpected value '$cursor' for key '$current' in config file. " + 'Expected a Map.'); + } else { + cursor = cursor[keyPart]; + } + current += '.$keyPart'; + } + if (cursor is! T?) { + throw FormatException( + "Unexpected value '$cursor' for key '$current' in config file. " + 'Expected a $T.'); + } + return cursor; + } + + @override + String toString() => 'FileSource(file: $_file, fileUri: $baseUri)'; +}
diff --git a/pkgs/cli_config/lib/src/source.dart b/pkgs/cli_config/lib/src/source.dart new file mode 100644 index 0000000..14c7965 --- /dev/null +++ b/pkgs/cli_config/lib/src/source.dart
@@ -0,0 +1,65 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:io'; + +abstract class Source { + /// If provided, the uri used for resolving paths. + Uri? get baseUri; + + /// Lookup a nullable string value. + String? optionalString(String key); + + /// Lookup a nullable string list. + /// + /// If provided, [splitPattern] splits config. + List<String>? optionalStringList( + String key, { + String? splitPattern, + }); + + /// Lookup an optional boolean value. + bool? optionalBool(String key); + + /// Lookup an optional int value. + int? optionalInt(String key); + + /// Lookup an optional int value. + double? optionalDouble(String key); + + /// Lookup an optional value of type [T]. + /// + /// Does not support specialized options such as `splitPattern`. One must + /// use the specialized methods such as [optionalStringList] for that. + /// + /// Returns `null` if the source cannot provide a value of type [T]. + T? optionalValueOf<T>(String key) { + if (T == bool) { + return optionalBool(key) as T?; + } + if (T == String) { + return optionalString(key) as T?; + } + if (T == List<String>) { + return optionalStringList(key) as T?; + } + return null; + } + + static void throwIfUnexpectedValue<T>( + String key, T value, Iterable<T> validValues) { + if (!validValues.contains(value)) { + throw FormatException( + "Unexpected value '$value' for key '$key'. Expected one of: " + "${validValues.map((e) => "'$e'").join(', ')}."); + } + } + + static Uri fileSystemPathToUri(String path) { + if (path.endsWith(Platform.pathSeparator)) { + return Uri.directory(path); + } + return Uri.file(path); + } +}
diff --git a/pkgs/cli_config/pubspec.yaml b/pkgs/cli_config/pubspec.yaml new file mode 100644 index 0000000..e2b0721 --- /dev/null +++ b/pkgs/cli_config/pubspec.yaml
@@ -0,0 +1,17 @@ +name: cli_config +description: >- + A library to take config values from configuration files, CLI arguments, and + environment variables. +version: 0.2.1-wip +repository: https://github.com/dart-lang/tools/tree/main/pkgs/cli_config + +environment: + sdk: ^3.4.0 + +dependencies: + args: ^2.4.0 + yaml: ^3.1.1 + +dev_dependencies: + dart_flutter_team_lints: ^3.0.0 + test: ^1.21.0
diff --git a/pkgs/cli_config/test/cli_config_example_test.dart b/pkgs/cli_config/test/cli_config_example_test.dart new file mode 100644 index 0000000..43ed7b9 --- /dev/null +++ b/pkgs/cli_config/test/cli_config_example_test.dart
@@ -0,0 +1,106 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:io'; + +import 'package:test/test.dart'; + +import 'helpers.dart'; + +void main() { + test('resolve command line paths relative to working directory', () async { + await inTempDir((tempUri) async { + final rootUri = Directory.current.uri.normalizePath(); + final examplePackageUri = + rootUri.resolve('example${Platform.pathSeparator}'); + final entryPoint = 'bin${Platform.pathSeparator}cli_config_example.dart'; + const pubSpec = 'pubspec.yaml'; + for (final filename in [entryPoint, pubSpec]) { + final targetUri = tempUri.resolve(filename); + await File.fromUri(targetUri).create(recursive: true); + await File.fromUri(examplePackageUri.resolve(filename)) + .copy(targetUri.toFilePath()); + } + final pubspecFile = File.fromUri(tempUri.resolve(pubSpec)); + await pubspecFile.writeAsString( + (await pubspecFile.readAsString()) + .replaceAll('path: ../', 'path: ${rootUri.toFilePath()}'), + ); + + final pubGetResult = await runProcess( + executable: Uri.file(Platform.resolvedExecutable), + arguments: ['pub', 'get'], + workingDirectory: tempUri, + ); + expect(pubGetResult.exitCode, 0); + + { + final commandLinePath = Uri.file( + 'a${Platform.pathSeparator}b${Platform.pathSeparator}d.ext'); + final result = await runProcess( + executable: Uri.file(Platform.resolvedExecutable), + arguments: [ + tempUri.resolve(entryPoint).toFilePath(), + '-Dmy_path=${commandLinePath.toFilePath()}' + ], + workingDirectory: rootUri, + ); + final stdout = (result.stdout as String).trim(); + final resolvedPath = Uri.file(stdout); + expect(resolvedPath, rootUri.resolveUri(commandLinePath)); + } + + { + final commandLinePath = Uri.file( + 'a${Platform.pathSeparator}b${Platform.pathSeparator}d.ext'); + final result = await runProcess( + executable: Uri.file(Platform.resolvedExecutable), + arguments: [ + tempUri.resolve(entryPoint).toFilePath(), + '-Dmy_path=${commandLinePath.toFilePath()}' + ], + workingDirectory: tempUri, + ); + final stdout = (result.stdout as String).trim(); + final resolvedPath = Uri.file(stdout); + expect(resolvedPath, tempUri.resolveUri(commandLinePath)); + } + + final pathInFile = + Uri.file('a${Platform.pathSeparator}b${Platform.pathSeparator}d.ext'); + final configUri = tempUri.resolve('config.yaml'); + await File.fromUri(configUri).writeAsString(''' +my_path: ${pathInFile.toFilePath()} +'''); + + { + final result = await runProcess( + executable: Uri.file(Platform.resolvedExecutable), + arguments: [ + tempUri.resolve(entryPoint).toFilePath(), + '--config=${configUri.toFilePath()}' + ], + workingDirectory: tempUri, + ); + final stdout = (result.stdout as String).trim(); + final resolvedPath = Uri.file(stdout); + expect(resolvedPath, tempUri.resolveUri(pathInFile)); + } + + { + final result = await runProcess( + executable: Uri.file(Platform.resolvedExecutable), + arguments: [ + tempUri.resolve(entryPoint).toFilePath(), + '--config=${configUri.toFilePath()}' + ], + workingDirectory: rootUri, + ); + final stdout = (result.stdout as String).trim(); + final resolvedPath = Uri.file(stdout); + expect(resolvedPath, tempUri.resolveUri(pathInFile)); + } + }); + }); +}
diff --git a/pkgs/cli_config/test/cli_config_test.dart b/pkgs/cli_config/test/cli_config_test.dart new file mode 100644 index 0000000..073002c --- /dev/null +++ b/pkgs/cli_config/test/cli_config_test.dart
@@ -0,0 +1,567 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; +import 'dart:io'; + +import 'package:cli_config/cli_config.dart'; +import 'package:test/test.dart'; + +import 'helpers.dart'; + +void main() { + test('optionalStringList', () { + const path1 = 'path/in/cli_arguments/'; + const path2 = 'path/in/cli_arguments_2/'; + const path3 = 'path/in/environment/'; + const path4 = 'path/in/environment_2/'; + const path5 = 'path/in/config_file/'; + const path6 = 'path/in/config_file_2/'; + final config = Config.fromConfigFileContents( + commandLineDefines: [ + 'build.out_dir=$path1', + 'build.out_dir=$path2', + ], + environment: { + 'BUILD__OUT_DIR': '$path3:$path4', + }, + fileContents: jsonEncode( + { + 'build': { + 'out_dir': [ + path5, + path6, + ], + } + }, + ), + ); + + { + final result = config.optionalStringList( + 'build.out_dir', + combineAllConfigs: true, + splitEnvironmentPattern: ':', + ); + expect(result, [path1, path2, path3, path4, path5, path6]); + } + + { + final result = config.optionalStringList( + 'build.out_dir', + combineAllConfigs: false, + splitEnvironmentPattern: ':', + ); + expect(result, [path1, path2]); + } + }); + + test('optionalString cli precedence', () { + const path1 = 'path/in/cli_arguments/'; + const path2 = 'path/in/environment/'; + const path3 = 'path/in/config_file/'; + final config = Config.fromConfigFileContents( + commandLineDefines: [ + 'build.out_dir=$path1', + ], + environment: { + 'BUILD__OUT_DIR': path2, + }, + fileContents: jsonEncode( + { + 'build': { + 'out_dir': path3, + } + }, + ), + ); + + final result = config.optionalString( + 'build.out_dir', + ); + expect(result, path1); + }); + + test('optionalString environment precedence', () { + const path2 = 'path/in/environment/'; + const path3 = 'path/in/config_file/'; + final config = Config.fromConfigFileContents( + commandLineDefines: [], + environment: { + 'BUILD__OUT_DIR': path2, + }, + fileContents: jsonEncode( + { + 'build': { + 'out_dir': path3, + } + }, + ), + ); + + final result = config.optionalString( + 'build.out_dir', + ); + expect(result, path2); + }); + + test('optionalString config file', () { + const path3 = 'path/in/config_file/'; + final config = Config.fromConfigFileContents( + commandLineDefines: [], + environment: {}, + fileContents: jsonEncode( + { + 'build': { + 'out_dir': path3, + } + }, + ), + ); + + final result = config.optionalString( + 'build.out_dir', + ); + expect(result, path3); + }); + + test('optionalBool define', () { + final config = Config( + commandLineDefines: ['my_bool=true'], + ); + + expect(config.optionalBool('my_bool'), true); + }); + + test('optionalBool environment', () { + final config = Config( + environment: { + 'MY_BOOL': 'true', + }, + ); + + expect(config.optionalBool('my_bool'), true); + }); + + test('optionalBool file', () { + final config = Config.fromConfigFileContents( + fileContents: jsonEncode( + {'my_bool': true}, + ), + ); + + expect(config.optionalBool('my_bool'), true); + }); + + test('Read file and parse CLI args', () async { + final temp = await Directory.systemTemp.createTemp(); + final configFile = File.fromUri(temp.uri.resolve('config.yaml')); + await configFile.writeAsString(jsonEncode( + { + 'build': { + 'out_dir': 'path/in/config_file/', + } + }, + )); + final config = await Config.fromArguments( + arguments: [ + '--config', + configFile.path, + '-Dbuild.out_dir=path/in/cli_arguments/', + ], + environment: { + 'BUILD__OUT_DIR': 'path/in/environment', + }, + ); + + final result = config.optionalString('build.out_dir'); + expect(result, 'path/in/cli_arguments/'); + }); + + test('Resolve config file path relative to config file', () async { + final temp = await Directory.systemTemp.createTemp(); + final tempUri = temp.uri; + final configUri = tempUri.resolve('config.yaml'); + final configFile = File.fromUri(configUri); + const relativePath = 'path/in/config_file/'; + final resolvedPath = configUri.resolve(relativePath); + + await configFile.writeAsString(jsonEncode( + { + 'build': { + 'out_dir': relativePath, + } + }, + )); + + final config = await Config.fromArguments( + arguments: [ + '--config', + configFile.path, + ], + ); + final result = config.optionalPath('build.out_dir'); + expect(result!.path, resolvedPath.path); + + final configSync = Config.fromArgumentsSync( + arguments: [ + '--config', + configFile.path, + ], + ); + final resultSync = configSync.optionalPath('build.out_dir'); + expect(resultSync!.path, resolvedPath.path); + }); + + test('provide pre-parsed config', () { + const path3 = 'path/in/config_file/'; + final config = Config( + commandLineDefines: [], + environment: {}, + fileParsed: { + 'build': { + 'out_dir': path3, + } + }, + ); + + final result = config.optionalString('build.out_dir'); + expect(result, path3); + }); + + test('path exists', () async { + await inTempDir((tempUri) async { + final tempFileUri = tempUri.resolve('file.ext'); + await File.fromUri(tempFileUri).create(); + final nonExistUri = tempUri.resolve('foo.ext'); + final config = Config( + commandLineDefines: [], + environment: {}, + fileParsed: { + 'build': { + 'out_dir': tempUri.toFilePath(), + 'file': tempFileUri.toFilePath(), + 'non_exist': nonExistUri.toFilePath(), + } + }, + ); + + final result = config.optionalPath('build.out_dir', mustExist: true); + expect(result, tempUri); + final result2 = config.optionalPath('build.file', mustExist: true); + expect(result2, tempFileUri); + expect( + () => config.optionalPath('build.non_exist', mustExist: true), + throwsFormatException, + ); + }); + }); + + test('wrong CLI key format', () { + expect( + () => Config(commandLineDefines: ['CAPITALIZED=value']), + throwsFormatException, + ); + }); + + test('CLI two values when expecting one', () { + final config = Config(commandLineDefines: ['key=value', 'key=value2']); + expect( + () => config.string('key'), + throwsFormatException, + ); + }); + + test('CLI split optionalStringList', () { + final config = Config(commandLineDefines: ['key=value;value2']); + final value = config.optionalStringList('key', splitCliPattern: ';'); + expect(value, ['value', 'value2']); + }); + + test('CLI path', () { + final uri = Uri.file('some/path.ext'); + final config = Config(commandLineDefines: ['key=${uri.path}']); + final value = config.optionalPath('key'); + expect(value, uri); + }); + + test('CLI path list', () { + final uri = Uri.file('some/path.ext'); + final uri2 = Uri.file('some/directory/'); + final config = Config(commandLineDefines: ['key=${uri.path}:${uri2.path}']); + final value = config.optionalPathList('key', splitCliPattern: ':'); + expect(value, [uri, uri2]); + }); + + test('toString', () { + final config = Config( + commandLineDefines: ['key=foo'], + environment: {'key': 'bar'}, + fileParsed: {'key': 'baz'}, + ); + config.toString(); + }); + + test('Missing nonullable throws FormatException', () { + final config = Config.fromConfigFileContents(); + expect(() => config.bool('key'), throwsFormatException); + expect(() => config.string('key'), throwsFormatException); + expect(() => config.path('key'), throwsFormatException); + }); + + test('string not validValue throws FormatException', () { + final config = Config(environment: {'foo': 'bar'}); + expect( + () => config.string('foo', validValues: ['not_bar']), + throwsFormatException, + ); + }); + + test('optionalString validValues', () { + final config = Config(); + expect(config.optionalString('foo', validValues: ['bar']), isNull); + }); + + test('valueOf file source', () { + final config = Config(fileParsed: { + 'key': {'some': 'map'} + }); + final value = config.valueOf<Map<dynamic, dynamic>>('key'); + expect(value, {'some': 'map'}); + }); + + test('valueOf command line source', () { + final config = Config(commandLineDefines: [ + 'string_key=value', + 'bool_key=true', + 'string_list_key=value1', + 'string_list_key=value2', + ]); + expect(config.valueOf<String>('string_key'), 'value'); + expect(config.valueOf<bool>('bool_key'), true); + expect( + config.valueOf<List<String>>('string_list_key'), + ['value1', 'value2'], + ); + }); + + test('environment split optionalStringList', () { + final config = Config(environment: {'key': 'value;value2'}); + final value = + config.optionalStringList('key', splitEnvironmentPattern: ';'); + expect(value, ['value', 'value2']); + }); + + test('environment non split optionalStringList', () { + final config = Config(environment: {'key': 'value'}); + final value = config.optionalStringList('key'); + expect(value, ['value']); + }); + + test('environment path', () { + final uri = Uri.file('some/path.ext'); + final config = Config(environment: {'key': uri.path}); + final value = config.optionalPath('key'); + expect(value, uri); + }); + + test('environment path list', () { + final uri = Uri.file('some/path.ext'); + final uri2 = Uri.file('some/directory/'); + final config = Config(environment: {'key': '${uri.path}:${uri2.path}'}); + final value = config.optionalPathList('key', splitEnvironmentPattern: ':'); + expect(value, [uri, uri2]); + }); + + test('Unexpected config file contents', () { + expect(() => Config.fromConfigFileContents(fileContents: 'asdf'), + throwsFormatException); + expect(() => Config.fromConfigFileContents(fileContents: "['asdf']"), + throwsFormatException); + expect( + () => Config.fromConfigFileContents( + fileContents: ''' +WRONGKEY: + 1 +''' + .trim()), + throwsFormatException, + ); + expect( + () => Config.fromConfigFileContents( + fileContents: ''' +1: 'asdf' +''' + .trim()), + throwsFormatException, + ); + }); + + test('file config try to access object as wrong type', () { + final config = Config.fromConfigFileContents(fileContents: '''foo: + bar: + true +'''); + expect(config.bool('foo.bar'), true); + expect(() => config.bool('foo.bar.baz'), throwsFormatException); + expect(() => config.string('foo.bar'), throwsFormatException); + }); + + test('file config path list unresolved', () { + final uri = Uri.file('some/path.ext'); + final uri2 = Uri.file('some/directory/'); + final config = Config(fileParsed: { + 'key': [uri.path, uri2.path] + }); + final value = config.optionalPathList('key', resolveUri: false); + expect(value, [uri, uri2]); + }); + + test('file config path list resolved', () { + final configUri = Uri.file('path/to/config.json'); + final uri = Uri.file('some/path.ext'); + final uri2 = Uri.file('some/directory/'); + final config = Config( + fileSourceUri: configUri, + fileParsed: { + 'key': [uri.path, uri2.path] + }, + ); + final value = config.optionalPathList('key', resolveUri: true); + expect(value, [configUri.resolveUri(uri), configUri.resolveUri(uri2)]); + }); + + test('resolveUri in working directory', () { + final systemTemp = Directory.systemTemp.uri; + final tempUri = systemTemp.resolve('x/y/z/'); + + final relativePath = Uri.file('a/b/c/d.ext'); + final absolutePath = tempUri.resolveUri(relativePath); + final config = Config( + commandLineDefines: ['path=${relativePath.path}'], + workingDirectory: tempUri, + ); + + expect(config.optionalPath('path', mustExist: false, resolveUri: true), + absolutePath); + }); + + test('ints', () { + final config = Config( + commandLineDefines: ['cl=1', 'not_parsable=asdf'], + environment: { + 'env': '2', + 'not_parsable2': 'asfd', + }, + fileParsed: {'file': 3}, + ); + + expect(config.int('cl'), 1); + expect(config.optionalInt('env'), 2); + expect(config.optionalInt('file'), 3); + expect(config.optionalInt('nothing'), null); + expect(() => config.optionalInt('not_parsable'), throwsFormatException); + expect(() => config.optionalInt('not_parsable2'), throwsFormatException); + }); + + test('doubles', () { + final config = Config( + commandLineDefines: ['cl=1.1', 'not_parsable=asdf'], + environment: { + 'env': '2.2', + 'not_parsable2': 'asfd', + }, + fileParsed: {'file': 3.3}, + ); + + expect(config.double('cl'), 1.1); + expect(config.optionalDouble('env'), 2.2); + expect(config.optionalDouble('file'), 3.3); + expect(config.optionalDouble('nothing'), null); + expect(() => config.optionalDouble('not_parsable'), throwsFormatException); + expect(() => config.optionalDouble('not_parsable2'), throwsFormatException); + }); + + test('stringList and optionalStringList', () { + { + final config = Config( + fileParsed: {}, + ); + + expect(config.optionalStringList('my_list'), null); + expect(() => config.stringList('my_list'), throwsFormatException); + } + + { + final config = Config( + fileParsed: {'my_list': <String>[]}, + ); + + expect(config.optionalStringList('my_list'), <String>[]); + expect(config.stringList('my_list'), <String>[]); + } + }); + + test('pathList and optionalPathList', () { + { + final config = Config( + fileParsed: {}, + ); + + expect(config.optionalPathList('my_list'), null); + expect(() => config.pathList('my_list'), throwsFormatException); + } + + { + final config = Config( + fileParsed: {'my_list': <String>[]}, + ); + + expect(config.optionalPathList('my_list'), <String>[]); + expect(config.pathList('my_list'), <String>[]); + } + }); + + test('non-string key maps', () { + // This is valid in YAML (not in JSON). + // + // Such values cannot be accessed with our hierarchical keys, but they can + // be accessed with [Config.valueOf]. + final config = Config( + fileParsed: { + 'my_non_string_key_map': { + 1: 'asdf', + 2: 'foo', + }, + }, + ); + + expect( + config.valueOf<Map<Object, Object?>>('my_non_string_key_map'), + { + 1: 'asdf', + 2: 'foo', + }, + ); + }); + + test('null values in maps', () { + final config = Config( + fileParsed: { + 'my_non_string_key_map': { + 'x': null, + 'y': 42, + }, + }, + ); + + expect( + config.valueOf<Map<Object, Object?>>('my_non_string_key_map'), + { + 'x': null, + 'y': 42, + }, + ); + }); +}
diff --git a/pkgs/cli_config/test/cli_config_windows_test.dart b/pkgs/cli_config/test/cli_config_windows_test.dart new file mode 100644 index 0000000..2c401f2 --- /dev/null +++ b/pkgs/cli_config/test/cli_config_windows_test.dart
@@ -0,0 +1,23 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +@TestOn('windows') +library; + +import 'package:cli_config/cli_config.dart'; +import 'package:test/test.dart'; + +void main() { + test('path resolving windows', () { + const path = 'C:\\foo\\bar\\'; + final workingDirectory = Uri.parse('file:///C:/baz/baf/'); + + final config = Config( + commandLineDefines: ['key=$path'], + workingDirectory: workingDirectory, + ); + final value = config.path('key', resolveUri: true); + expect(value.toFilePath(), path); + }); +}
diff --git a/pkgs/cli_config/test/helpers.dart b/pkgs/cli_config/test/helpers.dart new file mode 100644 index 0000000..d9fb40e --- /dev/null +++ b/pkgs/cli_config/test/helpers.dart
@@ -0,0 +1,43 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:io'; + +const keepTempKey = 'KEEP_TEMPORARY_DIRECTORIES'; + +Future<void> inTempDir( + Future<void> Function(Uri tempUri) fun, { + String? prefix, +}) async { + final tempDir = await Directory.systemTemp.createTemp(prefix); + // Deal with Windows temp folder aliases. + final tempUri = + Directory(await tempDir.resolveSymbolicLinks()).uri.normalizePath(); + try { + await fun(tempUri); + } finally { + if (!Platform.environment.containsKey(keepTempKey) || + Platform.environment[keepTempKey]!.isEmpty) { + await tempDir.delete(recursive: true); + } + } +} + +Future<ProcessResult> runProcess({ + required Uri executable, + List<String> arguments = const [], + required Uri workingDirectory, +}) async { + final result = await Process.run( + executable.toFilePath(), + arguments, + workingDirectory: workingDirectory.toFilePath(), + ); + if (result.exitCode != 0) { + print(result.stdout); + print(result.stderr); + print(result.exitCode); + } + return result; +}
diff --git a/pkgs/coverage/.gitignore b/pkgs/coverage/.gitignore new file mode 100644 index 0000000..1a25097 --- /dev/null +++ b/pkgs/coverage/.gitignore
@@ -0,0 +1,18 @@ +# Pub +packages +pubspec.lock +build +.dart_tool/ +.pub +.packages + +# IDEs +.project +.settings +.idea +*.iml + +# Temp files +*~ +coverage/ +var/
diff --git a/pkgs/coverage/AUTHORS b/pkgs/coverage/AUTHORS new file mode 100644 index 0000000..7513829 --- /dev/null +++ b/pkgs/coverage/AUTHORS
@@ -0,0 +1,12 @@ +# Below is a list of people and organizations that have contributed +# to the coverage project. Names should be added to the list like so: +# +# Name/Organization <email address> + +Google Inc. +Achilleas Anagnostopoulos <achilleas.imap.mbox@gmail.com> +Adam Singer <adammichaelsinger@gmail.com> +Cédric Belin <cedxbelin@gmail.com> +Evan Weible <ekweible@gmail.com> +Günter Zöchbauer <guenter@gzoechbauer.com> +Will Drach <will.drach@gmail.com>
diff --git a/pkgs/coverage/CHANGELOG.md b/pkgs/coverage/CHANGELOG.md new file mode 100644 index 0000000..a58d0dc --- /dev/null +++ b/pkgs/coverage/CHANGELOG.md
@@ -0,0 +1,496 @@ +## 1.10.0 + +- Fix bug where tests involving multiple isolates never finish (#520). + +## 1.9.2 + +- Fix repository link in pubspec. + +## 1.9.1 + +- Remove outdated VM service version checks. +- Move to `dart-lang/tools`. + +## 1.9.0 + +- Require Dart ^3.4 +- Fix bug where some ranges were able to bypass the `--scope-output` filters. +- Add --ignore-files option allowing to exclude files from coverage reports using glob patterns + +## 1.8.0 + +- Copy collect_coverage's `--scope-output` flag to test_with_coverage. + +## 1.7.2 + +- Update `package:vm_service` constraints to '>=12.0.0 <15.0.0'. + +## 1.7.1 + +- Update `package:vm_service` constraints to '>=12.0.0 <14.0.0'. + +## 1.7.0 + +- Require Dart 3.0.0 +- Update `package:vm_service` constraints to '^12.0.0'. +- Add `coverableLineCache` parameter to `collect`. This allows the set of + coverable lines to be cached between calls to `collect`, avoiding the need to + force compile the same libraries repeatedly. This is only useful when running + multiple coverage collections over the same libraries. + +## 1.6.4 + +- allow omitting space between `//` and `coverage` in coverage ignore comments +- allow text after coverage ignore comments +- throw FormatException when encountering unbalanced ignore comments instead of silently erroring +- Update `package:vm_service` constraints to '>= 9.4.0 <12.0.0'. + +## 1.6.3 + +- Require Dart 2.18 +- Update `package:vm_service` constraints to '>=9.4.0 <12.0.0'. + +## 1.6.2 + +- Update `package:vm_service` constraints to '>=9.4.0 <11.0.0'. + +## 1.6.1 + +- Handle SentinelExceptions thrown by vm_service. + +## 1.6.0 + +- Update to vm_service 9.4.0. +- Use IsolateRef.isolateGroupId to speed up coverage collection. +- Ignore uncoverable abstract methods. +- Fix bug where 'ingore-line' comments etc are applied even if they're inside + string literals. +- Change the LICENSE file to the standard Dart BSD license. + +## 1.5.0 + +- Support passing extra arguments to `test_with_coverage` which are then passed + to `package:test`. + + Example: `dart run coverage:test_with_coverage -- --preset CI` + +## 1.4.0 + +- Added `HitMap.parseJsonSync` which takes a cache of ignored lines which can + speedup calls when `checkIgnoredLines` is true and the function is called + several times with overlapping files in the input json. +- Bump the version of vm_service to 9.0.0. + +## 1.3.2 + +- Fix test_with_coverage listening to an unsupported signal on windows. +- Fix `--reportOn` on windows using incorrect path separators. + +## 1.3.1 + +- Fix running `dart pub global run coverage:test_with_coverage` or + `dart run coverage:test_with_coverage` + +## 1.3.0 + +- Bump the minimum Dart SDK version to 2.15.0 +- Add a `--package` flag, which takes the package's root directory, instead of + the .package file. Deprecate the `--packages` flag. +- Deprecate the packagesPath parameter and add packagePath instead, in + `HitMap.parseJson`, `HitMap.parseFiles`, `createHitmap`, and `parseCoverage`. +- Add a new executable to the package, `test_with_coverage`. This simplifies the + most common use case of coverage, running all the tests for a package, and + generating an lcov.info file. +- Use the `libraryFilters` option in `getSourceReport` to speed up coverage runs + that use `scopedOutput`. + +## 1.2.0 + +- Support branch level coverage information, when running tests in the Dart VM. + This is not supported for web tests yet. +- Add flag `--branch-coverage` (abbr `-b`) to collect_coverage that collects + branch coverage information. The VM must also be run with the + `--branch-coverage` flag. +- Add flag `--pretty-print-branch` to format_coverage that works similarly to + pretty print, but outputs branch level coverage, rather than line level. +- Update `--lcov` (abbr `-l`) in format_coverage to output branch level + coverage, in addition to line level. +- Add an optional bool flag to `collect` that controls whether branch coverage + is collected. +- Add a `branchHits` field to `HitMap`. +- Add support for scraping the service URI from the new Dart VM service message. +- Correctly parse package_config files on Windows when the root URI is relative. + +## 1.1.0 + +- Support function level coverage information, when running tests in the Dart + VM. This is not supported for web tests yet. +- Add flag `--function-coverage` (abbr `-f`) to collect_coverage that collects + function coverage information. +- Add flag `--pretty-print-func` (abbr `-f`) to format_coverage that works + similarly to pretty print, but outputs function level coverage, rather than + line level. +- Update `--lcov` (abbr `-l`) in format_coverage to output function level + coverage, in addition to line level. +- Add an optional bool flag to `collect` that controls whether function coverage + is collected. +- Added `HitMap.parseJson`, `FileHitMaps.merge`, `HitMap.parseFiles`, + `HitMap.toJson`, `FileHitMapsFormatter.formatLcov`, and + `FileHitMapsFormatter.prettyPrint` that switch from using `Map<int, int>` to + represent line coverage to using `HitMap` (which contains both line and + function coverage). Document the old versions of these functions as + deprecated. We will delete the old functions when we update to coverage + version 2.0.0. +- Ensure `createHitmap` returns a sorted hitmap. This fixes a potential issue + with ignore line annotations. +- Use the `reportLines` flag in `vm_service`'s `getSourceReport` RPC. This + typically halves the number of RPCs that the coverage collector needs to run. +- Require Dart `>=2.14.0` + +## 1.0.4 + +- Updated dependency on `vm_service` package from `>=6.1.0 <8.0.0`to + `>=8.1.0 <9.0.0`. + +## 1.0.3 + +- Updated dependency on `vm_service` package from `^6.1.0` to `>=6.1.0 <8.0.0`. + +## 1.0.2 + +- Fix an issue where the `--packages` argument wasn't passed to + `format_coverage`. + +## 1.0.1 + +- Allow the chrome `sourceUriProvider` to return `null`. + +## 1.0.0 + +- Migrate to null safety. +- Removed support for SDK `1.x.x`. + +## 0.15.2 + +- Update `args`, `logging`, and `package_config` deps to allow the latest stable + releases. + +## 0.15.1 + +- Updated dependency on `vm_service` package from `>=1.0.0 < 5.0.0` to + `>=1.0.0 <7.0.0`. + +## 0.15.0 + +- BREAKING CHANGE: Eliminate the `--package-root` option from + `bin/run_and_collect.dart` and `bin/format_coverage.dart` as well as from + `runAndCollect` and the `Resolver` constructor. + +## 0.14.2 + +- Fix an issue where `--wait-paused` with `collect` would attempt to collect + coverage if no isolates have started. + +## 0.14.1 + +- Updated dependency on `vm_service` package from `>=1.0.0 < 5.0.0` to + `>=1.0.0 <6.0.0`. + +## 0.14.0 + +- Add flag `--check-ignore` that is used to ignore lines from coverage depending + on the comments. + + Use // coverage:ignore-line to ignore one line. Use // coverage:ignore-start + and // coverage:ignore-end to ignore range of lines inclusive. Use // + coverage:ignore-file to ignore the whole file. + +## 0.13.11 + +- Revert breaking change in 13.10 + +## 0.13.10 + +- Add flag `--check-ignore` that is used to ignore lines from coverage depending + on the comments. + + Use // coverage:ignore-line to ignore one line. Use // coverage:ignore-start + and // coverage:ignore-end to ignore range of lines inclusive. Use // + coverage:ignore-file to ignore the whole file. + +## 0.13.9 + +- Don't crash on empty JSON input files. +- Loosen the dependency on the `vm_service` package from `>=1.0.0 <4.0.0` to + `>=1.0.0 <5.0.0`. + +## 0.13.8 + +- Update to package_config `1.9.0` which supports package_config.json files and + should be forwards compatible with `2.0.0`. +- Deprecate the `packageRoot` argument on `Resolver`. + +## 0.13.7 + +- Loosen the dependency on the `vm_service` package from `>=1.0.0 <3.0.0` to + `>=1.0.0 <4.0.0`. + +## 0.13.6 + +- Now consider all `.json` files for the `format_coverage` command. + +## 0.13.5 + +- Update `parseChromeCoverage` to merge coverage information for a given line. +- Handle source map parse errors in `parseChromeCoverage`. Coverage will not be + considered for Dart files that have corresponding invalid source maps. + +## 0.13.4 + +- Add `parseChromeCoverage` for creating a Dart based coverage report from a + Chrome coverage report. + +## 0.13.3+3 - 2019-12-03 + +- Re-loosen the dependency on the `vm_service` package from `>=1.0.0 < 2.1.2` to + `>=1.0.0 <3.0.0` now that breakage introduced in version `2.1.2` has been + resolved. Fixed in: + https://github.com/dart-lang/sdk/commit/7a911ce3f1e945f2cbd1967c6109127e3acbab5a. + +## 0.13.3+2 - 2019-12-02 + +- Tighten the dependency on the `vm_service` package from `>=1.0.0 <3.0.0` down + to `>=1.0.0 <2.1.2` in order to exclude version `2.1.2` which is broken on the + current stable Dart VM due to a missing SDK constraint in its pubspec.yaml. + The breakage was introduced in: + https://github.com/dart-lang/sdk/commit/9e636b5ab4de850fb19bc262e0686fdf14bfbfc0. + +## 0.13.3+1 - 2019-10-10 + +- Loosen the dependency on the `vm_service` package from `^1.0.0` to + `>=1.0.0 <3.0.0`. Ensures dependency version range compatibility with the + latest versions of package `test`. + +## 0.13.3 + +- Adds a new named argument to `collect` to filter coverage results by a set of + VM isolate IDs. +- Migrates implementation of VM service protocol library from + `package:vm_service_lib`, which is no longer maintained, to + `package:vm_service`, which is. + +## 0.13.2 + +- Add new multi-flag option `--scope-output` which restricts coverage output so + that only scripts that start with the provided path are considered. + +## 0.13.1 + +- Handle scenario where the VM returns empty coverage information for a range. + +## 0.13.0 + +- BREAKING CHANGE: Skips collecting coverage for `dart:` libraries by default, + which provides a significant performance boost. To restore the previous + behaviour and collect coverage for these libraries, use the `--include-dart` + flag. +- Disables WebSocket compression for coverage collection. Since almost all + coverage collection runs happen over the loopback interface to localhost, this + improves performance and reduces CPU usage. +- Migrates implementation of VM service protocol library from + `package:vm_service_client`, which is no longer maintained, to + `package:vm_service_lib`, which is. + +## 0.12.4 + +- `collect()` now immediately throws `ArgumentError` if a null URI is passed in + the `serviceUri` parameter to avoid a less-easily debuggable null dereference + later. See dart-lang/coverage#240 for details. + +## 0.12.3 + +- Fixed dart-lang/coverage#194. During collection, we now track each script by + its (unique) VMScriptRef. This ensures we look up the correct script when + computing the affected line for each hit token. The hitmap remains URI based, + since in the end, we want a single, unified set of line to hitCount mappings + per script. + +## 0.12.2 + +- Dart SDK upper bound raised to <3.0.0. + +## 0.12.1 + +- Minor type, dartfmt fixes. +- Require package:args >= 1.4.0. + +## 0.12.0 + +- BREAKING CHANGE: This version requires Dart SDK 2.0.0-dev.64.1 or later. +- Strong mode fixes as of Dart SDK 2.0.0-dev.64.1. + +## 0.11.0 + +- BREAKING CHANGE: This version requires Dart SDK 2.0.0-dev.30 or later. +- Updated to Dart 2.0 constants from dart:convert. + +## 0.10.0 + +- BREAKING CHANGE: `createHitmap` and `mergeHitmaps` now specify generic types + (`Map<String, Map<int, int>>`) on their hit map parameter/return value. +- Updated package:args dependency to 1.0.0. + +## 0.9.3 + +- Strong mode fixes as of Dart SDK 1.24.0. +- Restrict the SDK lower version constraint to `>=1.21.0`. Required for method + generics. +- Eliminate dependency on package:async. + +## 0.9.2 + +- Strong mode fixes as of Dart SDK 1.22.0. + +## 0.9.1 + +- Temporarily add back support for the `--host` and `--port` options to + `collect_coverage`. This is a temporary measure for backwards-compatibility + that may stop working on Dart SDKs >= 1.22. See the related + [breaking change note](https://groups.google.com/a/dartlang.org/forum/#!msg/announce/VxSw-V5tx8k/wPV0GfX7BwAJ) + for the Dart VM service protocol. + +## 0.9.0 + +- BREAKING CHANGE: `collect` no longer supports the `host` and `port` + parameters. These are replaced with a `serviceUri` parameter. As of Dart SDK + 1.22, the Dart VM will emit Observatory URIs that include an authentication + token for security reasons. Automated tools will need to scrape stdout for + this URI and pass it to `collect_coverage`. +- BREAKING CHANGE: `collect_coverage`: the `--host` and `--port` options have + been replaced with a `--uri` option. See the above change for details. +- BREAKING CHANGE: `runAndCollect` now defaults to running in checked mode. +- Added `extractObservatoryUri`: scrapes an input string for an Observatory URI. + Potentially useful for automated tooling after Dart SDK 1.22. + +## 0.8.1 + +- Added optional `checked` parameter to `runAndCollect` to run in checked mode. + +## 0.8.0+2 + +- Strong mode fixes as of Dart SDK 1.20.1. + +## 0.8.0+1 + +- Make strong mode clean. + +## 0.8.0 + +- Moved `Formatter.format` parameters `reportOn` and `basePath` to constructor. + Eliminated `pathFilter` parameter. + +## 0.7.9 + +- `format_coverage`: add `--base-directory` option. Source paths in + LCOV/pretty-print output are relative to this directory, or absolute if + unspecified. + +## 0.7.8 + +- `format_coverage`: support `--packages` option for package specs. + +## 0.7.7 + +- Add fallback URI resolution for Bazel http(s) URIs that don't contain a + `packages` path component. + +## 0.7.6 + +- Add [Bazel](http://bazel.io) support to `format_coverage`. + +## 0.7.5 + +- Bugfix in `collect_coverage`: prevent hang if initial VM service connection is + slow. +- Workaround for VM behaviour in which `evaluate:source` ranges may appear in + the returned source report manifesting in a crash in `collect_coverage`. These + generally correspond to source evaluations in the debugger and add little + value to line coverage. +- `format_coverage`: may be slower for large sets of coverage JSON input files. + Unlikely to be an issue due to elimination of `--coverage-dir` VM flag. + +## 0.7.4 + +- Require at least Dart SDK 1.16.0. + +- Bugfix in format_coverage: if `--report-on` is not specified, emit all + coverage, rather than none. + +## 0.7.3 + +- Added support for the latest Dart SDK. + +## 0.7.2 + +- `Formatter.format` added two optional arguments: `reportOn` and `pathFilter`. + They can be used independently to limit the files which are included in the + output. + +- Added `runAndCollect` API to library. + +## 0.7.1 + +- Added `collect` top-level method. + +- Updated support for latest `0.11.0` dev build. + +- Replaced `ServiceEvent.eventType` with `ServiceEvent.kind`. + - `ServiceEvent.eventType` is deprecated and will be removed in `0.8`. + +## 0.7.0 + +- `format_coverage` no longer emits SDK coverage unless --sdk-root is set + explicitly. + +- Removed support for collecting coverage from old (<1.9.0) Dart SDKs. + +- Removed deprecated `Resolver.pkgRoot`. + +## 0.6.5 + +- Fixed early collection bug when --wait-paused is set. + +## 0.6.4 + +- Optimized formatters and fixed return value of `format` methods. + +- Added `Resolver.packageRoot` – deprecated `Resolver.pkgRoot`. + +## 0.6.3 + +- Support the latest release of `args` package. + +- Support the latest release of `logging` package. + +- Fixed error when trying to access invalid paths. + +- Require at least Dart SDK v1.9.0. + +## 0.6.2 + +- Support observatory protocol changes for VM >= 1.11.0. + +## 0.6.1 + +- Support observatory protocol changes for VM >= 1.10.0. + +## 0.6.0+1 + +- Add support for `pub global run`. + +## 0.6.0 + +- Add support for SDK versions >= 1.9.0. For Dartium/content-shell versions past + 1.9.0, coverage collection is no longer done over the remote debugging port, + but via the observatory port emitted on stdout. Backward compatibility with + SDKs back to 1.5.x is provided.
diff --git a/pkgs/coverage/LICENSE b/pkgs/coverage/LICENSE new file mode 100644 index 0000000..000cd7b --- /dev/null +++ b/pkgs/coverage/LICENSE
@@ -0,0 +1,27 @@ +Copyright 2014, the Dart project authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google LLC nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/pkgs/coverage/PATENTS b/pkgs/coverage/PATENTS new file mode 100644 index 0000000..6954196 --- /dev/null +++ b/pkgs/coverage/PATENTS
@@ -0,0 +1,23 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Dart Project. + +Google hereby grants to you a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this +section) patent license to make, have made, use, offer to sell, sell, +import, transfer, and otherwise run, modify and propagate the contents +of this implementation of Dart, where such license applies only to +those patent claims, both currently owned by Google and acquired in +the future, licensable by Google that are necessarily infringed by +this implementation of Dart. This grant does not include claims that +would be infringed only as a consequence of further modification of +this implementation. If you or your agent or exclusive licensee +institute or order or agree to the institution of patent litigation +against any entity (including a cross-claim or counterclaim in a +lawsuit) alleging that this implementation of Dart or any code +incorporated within this implementation of Dart constitutes direct or +contributory patent infringement, or inducement of patent +infringement, then any patent rights granted to you under this License +for this implementation of Dart shall terminate as of the date such +litigation is filed.
diff --git a/pkgs/coverage/README.md b/pkgs/coverage/README.md new file mode 100644 index 0000000..81736a4 --- /dev/null +++ b/pkgs/coverage/README.md
@@ -0,0 +1,123 @@ +Coverage provides coverage data collection, manipulation, and formatting for +Dart. + +[](https://github.com/dart-lang/tools/actions/workflows/coverage.yml) +[](https://coveralls.io/github/dart-lang/tools?branch=main) +[](https://pub.dev/packages/coverage) + +## Tools + +`collect_coverage` collects coverage JSON from the Dart VM Service. +`format_coverage` formats JSON coverage data into either +[LCOV](https://github.com/linux-test-project/lcov) or pretty-printed format. + +#### Install coverage + + dart pub global activate coverage + +Consider adding the `dart pub global run` executables directory to your path. +See +[Running a script from your PATH](https://dart.dev/tools/pub/cmd/pub-global#running-a-script-from-your-path) +for more details. + +#### Running tests with coverage + +For the common use case where you just want to run all your tests, and generate +an lcov.info file, you can use the test_with_coverage script: + +``` +dart pub global run coverage:test_with_coverage +``` + +By default, this script assumes it's being run from the root directory of a +package, and outputs a coverage.json and lcov.info file to ./coverage/ + +This script is essentially the same as running: + +``` +dart run --pause-isolates-on-exit --disable-service-auth-codes --enable-vm-service=8181 test & +dart pub global run coverage:collect_coverage --wait-paused --uri=http://127.0.0.1:8181/ -o coverage/coverage.json --resume-isolates --scope-output=foo +dart pub global run coverage:format_coverage --packages=.dart_tool/package_config.json --lcov -i coverage/coverage.json -o coverage/lcov.info +``` + +For more complicated use cases, where you want to control each of these stages, +see the sections below. + +#### Collecting coverage from the VM + +``` +dart --pause-isolates-on-exit --disable-service-auth-codes --enable-vm-service=NNNN script.dart +dart pub global run coverage:collect_coverage --uri=http://... -o coverage.json --resume-isolates +``` + +or if the `dart pub global run` executables are on your PATH, + +``` +collect_coverage --uri=http://... -o coverage.json --resume-isolates +``` + +where `--uri` specifies the Dart VM Service URI emitted by the VM. + +If `collect_coverage` is invoked before the script from which coverage is to be +collected, it will wait until it detects a VM observatory to which it can +connect. An optional `--connect-timeout` may be specified (in seconds). The +`--wait-paused` flag may be enabled, causing `collect_coverage` to wait until +all isolates are paused before collecting coverage. + +#### Formatting coverage data + +``` +dart pub global run coverage:format_coverage --package=app_package -i coverage.json +``` + +or if the `dart pub global run` exectuables are on your PATH, + +``` +format_coverage --package=app_package -i coverage.json +``` + +where `app_package` is the path to the package whose coverage is being collected +(defaults to the current working directory). If `--sdk-root` is set, Dart SDK +coverage will also be output. + +#### Ignore lines from coverage + +- `// coverage:ignore-line` to ignore one line. +- `// coverage:ignore-start` and `// coverage:ignore-end` to ignore range of + lines inclusive. +- `// coverage:ignore-file` to ignore the whole file. + +Then pass `--check-ignore` to `format_coverage`. + +#### Function and branch coverage + +To gather function level coverage information, pass `--function-coverage` to +collect_coverage: + +``` +dart --pause-isolates-on-exit --disable-service-auth-codes --enable-vm-service=NNNN script.dart +dart pub global run coverage:collect_coverage --uri=http://... -o coverage.json --resume-isolates --function-coverage +``` + +To gather branch level coverage information, pass `--branch-coverage` to _both_ +collect_coverage and the Dart command you're gathering coverage from: + +``` +dart --pause-isolates-on-exit --disable-service-auth-codes --enable-vm-service=NNNN --branch-coverage script.dart +dart pub global run coverage:collect_coverage --uri=http://... -o coverage.json --resume-isolates --branch-coverage +``` + +Branch coverage requires Dart VM 2.17.0, with service API v3.56. Function, +branch, and line coverage can all be gathered at the same time, by combining +those flags: + +``` +dart --pause-isolates-on-exit --disable-service-auth-codes --enable-vm-service=NNNN --branch-coverage script.dart +dart pub global run coverage:collect_coverage --uri=http://... -o coverage.json --resume-isolates --function-coverage --branch-coverage +``` + +These flags can also be passed to test_with_coverage: + +``` +pub global run coverage:test_with_coverage --branch-coverage --function-coverage +```
diff --git a/pkgs/coverage/analysis_options.yaml b/pkgs/coverage/analysis_options.yaml new file mode 100644 index 0000000..1d9542a --- /dev/null +++ b/pkgs/coverage/analysis_options.yaml
@@ -0,0 +1,23 @@ +include: package:dart_flutter_team_lints/analysis_options.yaml + +analyzer: + language: + strict-casts: true + + exclude: + - var/** + +linter: + rules: + - always_declare_return_types + - avoid_slow_async_io + - cancel_subscriptions + - comment_references + - literal_only_boolean_expressions + - package_api_docs + - prefer_final_locals + - sort_constructors_first + - sort_unnamed_constructors_first + - test_types_in_equals + - throw_in_finally + - type_annotate_public_apis
diff --git a/pkgs/coverage/benchmark/.gitignore b/pkgs/coverage/benchmark/.gitignore new file mode 100644 index 0000000..1269488 --- /dev/null +++ b/pkgs/coverage/benchmark/.gitignore
@@ -0,0 +1 @@ +data
diff --git a/pkgs/coverage/benchmark/many_isolates.dart b/pkgs/coverage/benchmark/many_isolates.dart new file mode 100644 index 0000000..185576a --- /dev/null +++ b/pkgs/coverage/benchmark/many_isolates.dart
@@ -0,0 +1,27 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:isolate'; +import 'dart:math'; + +Future<void> main(List<String> args, dynamic message) async { + if (message == null) { + // If there is no message, it means this instance was created by + // run_benchmarks.dart. In that case, this is the parent instance that + // spawns all the others. + var sum = 0; + for (var i = 0; i < 10; ++i) { + final port = ReceivePort(); + final isolate = + Isolate.spawnUri(Uri.file('many_isolates.dart'), [], port.sendPort); + sum += await port.first as int; + await isolate; + } + print('sum = $sum'); + } else { + // If there is a message, it means this instance is one of the child + // instances. The message is the port that this instance replies on. + (message as SendPort).send(Random().nextInt(1000)); + } +}
diff --git a/pkgs/coverage/benchmark/run_benchmarks.dart b/pkgs/coverage/benchmark/run_benchmarks.dart new file mode 100644 index 0000000..1bd2990 --- /dev/null +++ b/pkgs/coverage/benchmark/run_benchmarks.dart
@@ -0,0 +1,143 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:io'; + +import 'package:benchmark_harness/benchmark_harness.dart'; + +import '../bin/collect_coverage.dart' as collect_coverage; +import '../bin/format_coverage.dart' as format_coverage; + +// Runs a test script with various different coverage configurations. +class CoverageBenchmark extends AsyncBenchmarkBase { + CoverageBenchmark( + ScoreEmitter emitter, + super.name, + this.script, { + this.gatherCoverage = false, + this.functionCoverage = false, + this.branchCoverage = false, + }) : super(emitter: emitter); + + final String script; + final bool gatherCoverage; + final bool functionCoverage; + final bool branchCoverage; + int iteration = 0; + + @override + Future<void> run() async { + print('Running $name...'); + final covFile = 'data/$name $iteration coverage.json'; + final lcovFile = 'data/$name $iteration lcov.info'; + ++iteration; + + await Process.start( + Platform.executable, + [ + if (branchCoverage) '--branch-coverage', + 'run', + if (gatherCoverage) ...[ + '--pause-isolates-on-exit', + '--disable-service-auth-codes', + '--enable-vm-service=1234', + ], + script, + ], + mode: ProcessStartMode.detached, + ); + if (gatherCoverage) { + await collect_coverage.main([ + '--wait-paused', + '--resume-isolates', + '--uri=http://127.0.0.1:1234/', + if (branchCoverage) '--branch-coverage', + if (functionCoverage) '--function-coverage', + '-o', + covFile, + ]); + + await format_coverage.main([ + '--lcov', + '--check-ignore', + '-i', + covFile, + '-o', + lcovFile, + ]); + } + } +} + +// Emitter that just captures the value. +class CaptureEmitter implements ScoreEmitter { + late double capturedValue; + + @override + void emit(String testName, double value) { + capturedValue = value; + } +} + +// Prints a JSON representation of the benchmark results, in a format compatible +// with the github benchmark action. +class JsonEmitter implements ScoreEmitter { + JsonEmitter(this._baseline); + + final double _baseline; + final _results = <String, double>{}; + + @override + void emit(String testName, double value) { + _results[testName] = value; + } + + String write() => '[${_results.entries.map((entry) => """{ + "name": "${entry.key}", + "unit": "times slower", + "value": ${(entry.value / _baseline).toStringAsFixed(2)} +}""").join(',\n')}]'; +} + +Future<void> runBenchmark(CoverageBenchmark benchmark) async { + for (var i = 0; i < 3; ++i) { + try { + await benchmark.report().timeout(const Duration(minutes: 2)); + return; + } on TimeoutException { + print('Timed out'); + } + } + print('Timed out too many times. Giving up.'); + exit(127); +} + +Future<String> runBenchmarkSet(String name, String script) async { + final captureEmitter = CaptureEmitter(); + await runBenchmark( + CoverageBenchmark(captureEmitter, '$name - no coverage', script)); + final benchmarkBaseline = captureEmitter.capturedValue; + + final emitter = JsonEmitter(benchmarkBaseline); + await runBenchmark(CoverageBenchmark( + emitter, '$name - basic coverage', script, + gatherCoverage: true)); + await runBenchmark(CoverageBenchmark( + emitter, '$name - function coverage', script, + gatherCoverage: true, functionCoverage: true)); + await runBenchmark(CoverageBenchmark( + emitter, '$name - branch coverage', script, + gatherCoverage: true, branchCoverage: true)); + return emitter.write(); +} + +Future<void> main() async { + // Assume this script was started from the root coverage directory. Change to + // the benchmark directory. + Directory.current = 'benchmark'; + final result = await runBenchmarkSet('Many isolates', 'many_isolates.dart'); + await File('data/benchmark_result.json').writeAsString(result); + exit(0); +}
diff --git a/pkgs/coverage/bin/collect_coverage.dart b/pkgs/coverage/bin/collect_coverage.dart new file mode 100644 index 0000000..b02ac21 --- /dev/null +++ b/pkgs/coverage/bin/collect_coverage.dart
@@ -0,0 +1,149 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:convert' show json; +import 'dart:io'; + +import 'package:args/args.dart'; +import 'package:coverage/src/collect.dart'; +import 'package:logging/logging.dart'; +import 'package:stack_trace/stack_trace.dart'; + +Future<void> main(List<String> arguments) async { + Logger.root.level = Level.WARNING; + Logger.root.onRecord.listen((LogRecord rec) { + print('${rec.level.name}: ${rec.time}: ${rec.message}'); + }); + + final options = _parseArgs(arguments); + await Chain.capture(() async { + final coverage = await collect(options.serviceUri, options.resume, + options.waitPaused, options.includeDart, options.scopedOutput, + timeout: options.timeout, + functionCoverage: options.functionCoverage, + branchCoverage: options.branchCoverage); + options.out.write(json.encode(coverage)); + await options.out.close(); + }, onError: (dynamic error, Chain chain) { + stderr.writeln(error); + stderr.writeln(chain.terse); + // See http://www.retro11.de/ouxr/211bsd/usr/include/sysexits.h.html + // EX_SOFTWARE + exit(70); + }); +} + +class Options { + Options( + this.serviceUri, + this.out, + this.timeout, + this.waitPaused, + this.resume, + this.includeDart, + this.functionCoverage, + this.branchCoverage, + this.scopedOutput); + + final Uri serviceUri; + final IOSink out; + final Duration? timeout; + final bool waitPaused; + final bool resume; + final bool includeDart; + final bool functionCoverage; + final bool branchCoverage; + final Set<String> scopedOutput; +} + +Options _parseArgs(List<String> arguments) { + final parser = ArgParser() + ..addOption('host', + abbr: 'H', + help: 'remote VM host. DEPRECATED: use --uri', + defaultsTo: '127.0.0.1') + ..addOption('port', + abbr: 'p', + help: 'remote VM port. DEPRECATED: use --uri', + defaultsTo: '8181') + ..addOption('uri', abbr: 'u', help: 'VM observatory service URI') + ..addOption('out', + abbr: 'o', defaultsTo: 'stdout', help: 'output: may be file or stdout') + ..addOption('connect-timeout', + abbr: 't', help: 'connect timeout in seconds') + ..addMultiOption('scope-output', + help: 'restrict coverage results so that only scripts that start with ' + 'the provided package path are considered') + ..addFlag('wait-paused', + abbr: 'w', + defaultsTo: false, + help: 'wait for all isolates to be paused before collecting coverage') + ..addFlag('resume-isolates', + abbr: 'r', defaultsTo: false, help: 'resume all isolates on exit') + ..addFlag('include-dart', + abbr: 'd', defaultsTo: false, help: 'include "dart:" libraries') + ..addFlag('function-coverage', + abbr: 'f', defaultsTo: false, help: 'Collect function coverage info') + ..addFlag('branch-coverage', + abbr: 'b', + defaultsTo: false, + help: 'Collect branch coverage info (Dart VM must also be run with ' + '--branch-coverage for this to work)') + ..addFlag('help', abbr: 'h', negatable: false, help: 'show this help'); + + final args = parser.parse(arguments); + + void printUsage() { + print('Usage: dart collect_coverage.dart --uri=http://... [OPTION...]\n'); + print(parser.usage); + } + + Never fail(String message) { + print('Error: $message\n'); + printUsage(); + exit(1); + } + + if (args['help'] as bool) { + printUsage(); + exit(0); + } + + Uri serviceUri; + if (args['uri'] == null) { + // TODO(cbracken) eliminate --host and --port support when VM defaults to + // requiring an auth token. Estimated for Dart SDK 1.22. + serviceUri = Uri.parse('http://${args['host']}:${args['port']}/'); + } else { + try { + serviceUri = Uri.parse(args['uri'] as String); + } on FormatException { + fail('Invalid service URI specified: ${args['uri']}'); + } + } + + final scopedOutput = args['scope-output'] as List<String>; + IOSink out; + if (args['out'] == 'stdout') { + out = stdout; + } else { + final outfile = File(args['out'] as String)..createSync(recursive: true); + out = outfile.openWrite(); + } + final timeout = (args['connect-timeout'] == null) + ? null + : Duration(seconds: int.parse(args['connect-timeout'] as String)); + return Options( + serviceUri, + out, + timeout, + args['wait-paused'] as bool, + args['resume-isolates'] as bool, + args['include-dart'] as bool, + args['function-coverage'] as bool, + args['branch-coverage'] as bool, + scopedOutput.toSet(), + ); +}
diff --git a/pkgs/coverage/bin/format_coverage.dart b/pkgs/coverage/bin/format_coverage.dart new file mode 100644 index 0000000..d24f60d --- /dev/null +++ b/pkgs/coverage/bin/format_coverage.dart
@@ -0,0 +1,310 @@ +// Copyright (c) 2013, 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:args/args.dart'; +import 'package:coverage/coverage.dart'; +import 'package:glob/glob.dart'; +import 'package:path/path.dart' as p; + +/// [Environment] stores gathered arguments information. +class Environment { + Environment({ + required this.baseDirectory, + required this.bazel, + required this.bazelWorkspace, + required this.checkIgnore, + required this.input, + required this.lcov, + required this.output, + required this.packagesPath, + required this.packagePath, + required this.prettyPrint, + required this.prettyPrintFunc, + required this.prettyPrintBranch, + required this.reportOn, + required this.ignoreFiles, + required this.sdkRoot, + required this.verbose, + required this.workers, + }); + + String? baseDirectory; + bool bazel; + String bazelWorkspace; + bool checkIgnore; + String input; + bool lcov; + IOSink output; + String? packagesPath; + String packagePath; + bool prettyPrint; + bool prettyPrintFunc; + bool prettyPrintBranch; + List<String>? reportOn; + List<String>? ignoreFiles; + String? sdkRoot; + bool verbose; + int workers; +} + +Future<void> main(List<String> arguments) async { + final env = parseArgs(arguments); + + final files = filesToProcess(env.input); + if (env.verbose) { + print('Environment:'); + print(' # files: ${files.length}'); + print(' # workers: ${env.workers}'); + print(' sdk-root: ${env.sdkRoot}'); + print(' package-path: ${env.packagePath}'); + print(' packages-path: ${env.packagesPath}'); + print(' report-on: ${env.reportOn}'); + print(' check-ignore: ${env.checkIgnore}'); + } + + final clock = Stopwatch()..start(); + final hitmap = await HitMap.parseFiles( + files, + checkIgnoredLines: env.checkIgnore, + // ignore: deprecated_member_use_from_same_package + packagesPath: env.packagesPath, + packagePath: env.packagePath, + ); + + // All workers are done. Process the data. + if (env.verbose) { + print('Done creating global hitmap. Took ${clock.elapsedMilliseconds} ms.'); + } + + final ignoreGlobs = env.ignoreFiles?.map(Glob.new).toSet(); + + String output; + final resolver = env.bazel + ? BazelResolver(workspacePath: env.bazelWorkspace) + : await Resolver.create( + packagesPath: env.packagesPath, + packagePath: env.packagePath, + sdkRoot: env.sdkRoot, + ); + final loader = Loader(); + if (env.prettyPrint) { + output = await hitmap.prettyPrint(resolver, loader, + reportOn: env.reportOn, + ignoreGlobs: ignoreGlobs, + reportFuncs: env.prettyPrintFunc, + reportBranches: env.prettyPrintBranch); + } else { + assert(env.lcov); + output = hitmap.formatLcov(resolver, + reportOn: env.reportOn, + ignoreGlobs: ignoreGlobs, + basePath: env.baseDirectory); + } + + env.output.write(output); + await env.output.flush(); + if (env.verbose) { + print('Done flushing output. Took ${clock.elapsedMilliseconds} ms.'); + } + + if (env.verbose) { + if (resolver.failed.isNotEmpty) { + print('Failed to resolve:'); + for (var error in resolver.failed.toSet()) { + print(' $error'); + } + } + if (loader.failed.isNotEmpty) { + print('Failed to load:'); + for (var error in loader.failed.toSet()) { + print(' $error'); + } + } + } + await env.output.close(); +} + +/// Checks the validity of the provided arguments. Does not initialize actual +/// processing. +Environment parseArgs(List<String> arguments) { + final parser = ArgParser(); + + parser + ..addOption('sdk-root', abbr: 's', help: 'path to the SDK root') + ..addOption('packages', help: '[DEPRECATED] path to the package spec file') + ..addOption('package', + help: 'root directory of the package', defaultsTo: '.') + ..addOption('in', abbr: 'i', help: 'input(s): may be file or directory') + ..addOption('out', + abbr: 'o', defaultsTo: 'stdout', help: 'output: may be file or stdout') + ..addMultiOption('report-on', + help: 'which directories or files to report coverage on') + ..addOption('workers', + abbr: 'j', defaultsTo: '1', help: 'number of workers') + ..addOption('bazel-workspace', + defaultsTo: '', help: 'Bazel workspace directory') + ..addOption('base-directory', + abbr: 'b', + help: 'the base directory relative to which source paths are output') + ..addFlag('bazel', + defaultsTo: false, help: 'use Bazel-style path resolution') + ..addFlag('pretty-print', + abbr: 'r', + negatable: false, + help: 'convert line coverage data to pretty print format') + ..addFlag('pretty-print-func', + abbr: 'f', + negatable: false, + help: 'convert function coverage data to pretty print format') + ..addFlag('pretty-print-branch', + negatable: false, + help: 'convert branch coverage data to pretty print format') + ..addFlag('lcov', + abbr: 'l', + negatable: false, + help: 'convert coverage data to lcov format') + ..addFlag('verbose', abbr: 'v', negatable: false, help: 'verbose output') + ..addFlag( + 'check-ignore', + abbr: 'c', + negatable: false, + help: 'check for coverage ignore comments.' + ' Not supported in web coverage.', + ) + ..addMultiOption( + 'ignore-files', + defaultsTo: [], + help: 'Ignore files by glob patterns', + ) + ..addFlag('help', abbr: 'h', negatable: false, help: 'show this help'); + + final args = parser.parse(arguments); + + void printUsage() { + print('Usage: dart format_coverage.dart [OPTION...]\n'); + print(parser.usage); + } + + Never fail(String msg) { + print('\n$msg\n'); + printUsage(); + exit(1); + } + + if (args['help'] as bool) { + printUsage(); + exit(0); + } + + var sdkRoot = args['sdk-root'] as String?; + if (sdkRoot != null) { + sdkRoot = p.normalize(p.join(p.absolute(sdkRoot), 'lib')); + if (!FileSystemEntity.isDirectorySync(sdkRoot)) { + fail('Provided SDK root "${args["sdk-root"]}" is not a valid SDK ' + 'top-level directory'); + } + } + + final packagesPath = args['packages'] as String?; + if (packagesPath != null) { + if (!FileSystemEntity.isFileSync(packagesPath)) { + fail('Package spec "${args["packages"]}" not found, or not a file.'); + } + } + + final packagePath = args['package'] as String; + if (!FileSystemEntity.isDirectorySync(packagePath)) { + fail('Package spec "${args["package"]}" not found, or not a directory.'); + } + + if (args['in'] == null) fail('No input files given.'); + final input = p.absolute(p.normalize(args['in'] as String)); + if (!FileSystemEntity.isDirectorySync(input) && + !FileSystemEntity.isFileSync(input)) { + fail('Provided input "${args["in"]}" is neither a directory nor a file.'); + } + + IOSink output; + if (args['out'] == 'stdout') { + output = stdout; + } else { + final outpath = p.absolute(p.normalize(args['out'] as String)); + final outfile = File(outpath)..createSync(recursive: true); + output = outfile.openWrite(); + } + + final reportOnRaw = args['report-on'] as List<String>; + final reportOn = reportOnRaw.isNotEmpty ? reportOnRaw : null; + + final bazel = args['bazel'] as bool; + final bazelWorkspace = args['bazel-workspace'] as String; + if (bazelWorkspace.isNotEmpty && !bazel) { + stderr.writeln('warning: ignoring --bazel-workspace: --bazel not set'); + } + + String? baseDirectory; + if (args['base-directory'] != null) { + baseDirectory = p.absolute(args['base-directory'] as String); + } + + final lcov = args['lcov'] as bool; + var prettyPrint = args['pretty-print'] as bool; + final prettyPrintFunc = args['pretty-print-func'] as bool; + final prettyPrintBranch = args['pretty-print-branch'] as bool; + final numModesChosen = (prettyPrint ? 1 : 0) + + (prettyPrintFunc ? 1 : 0) + + (prettyPrintBranch ? 1 : 0) + + (lcov ? 1 : 0); + if (numModesChosen > 1) { + fail('Choose one of the pretty-print modes or lcov output'); + } + + // The pretty printer is used by all modes other than lcov. + if (!lcov) prettyPrint = true; + + int workers; + try { + workers = int.parse('${args["workers"]}'); + } catch (e) { + fail('Invalid worker count: $e'); + } + + final checkIgnore = args['check-ignore'] as bool; + final ignoredGlobs = args['ignore-files'] as List<String>; + final verbose = args['verbose'] as bool; + return Environment( + baseDirectory: baseDirectory, + bazel: bazel, + bazelWorkspace: bazelWorkspace, + checkIgnore: checkIgnore, + input: input, + lcov: lcov, + output: output, + packagesPath: packagesPath, + packagePath: packagePath, + prettyPrint: prettyPrint, + prettyPrintFunc: prettyPrintFunc, + prettyPrintBranch: prettyPrintBranch, + reportOn: reportOn, + ignoreFiles: ignoredGlobs, + sdkRoot: sdkRoot, + verbose: verbose, + workers: workers); +} + +/// Given an absolute path absPath, this function returns a [List] of files +/// are contained by it if it is a directory, or a [List] containing the file if +/// it is a file. +List<File> filesToProcess(String absPath) { + if (FileSystemEntity.isDirectorySync(absPath)) { + return Directory(absPath) + .listSync(recursive: true) + .whereType<File>() + .where((e) => e.path.endsWith('.json')) + .toList(); + } + return <File>[File(absPath)]; +}
diff --git a/pkgs/coverage/bin/run_and_collect.dart b/pkgs/coverage/bin/run_and_collect.dart new file mode 100644 index 0000000..c255d01 --- /dev/null +++ b/pkgs/coverage/bin/run_and_collect.dart
@@ -0,0 +1,12 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:coverage/src/run_and_collect.dart'; + +Future<void> main(List<String> args) async { + final Map results = await runAndCollect(args[0]); + print(results); +}
diff --git a/pkgs/coverage/bin/test_with_coverage.dart b/pkgs/coverage/bin/test_with_coverage.dart new file mode 100644 index 0000000..010e608 --- /dev/null +++ b/pkgs/coverage/bin/test_with_coverage.dart
@@ -0,0 +1,229 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:io'; + +import 'package:args/args.dart'; +import 'package:coverage/src/util.dart' + show StandardOutExtension, extractVMServiceUri; +import 'package:package_config/package_config.dart'; +import 'package:path/path.dart' as path; + +import 'collect_coverage.dart' as collect_coverage; +import 'format_coverage.dart' as format_coverage; + +final _allProcesses = <Process>[]; + +Future<void> _dartRun(List<String> args, + {void Function(String)? onStdout, String? workingDir}) async { + final process = await Process.start( + Platform.executable, + args, + workingDirectory: workingDir, + ); + _allProcesses.add(process); + final broadStdout = process.stdout.asBroadcastStream(); + broadStdout.listen(stdout.add); + if (onStdout != null) { + broadStdout.lines().listen(onStdout); + } + process.stderr.listen(stderr.add); + final result = await process.exitCode; + if (result != 0) { + throw ProcessException(Platform.executable, args, '', result); + } +} + +Future<String?> _packageNameFromConfig(String packageDir) async { + final config = await findPackageConfig(Directory(packageDir)); + return config?.packageOf(Uri.directory(packageDir))?.name; +} + +void _watchExitSignal(ProcessSignal signal) { + signal.watch().listen((sig) { + for (final process in _allProcesses) { + process.kill(sig); + } + exit(1); + }); +} + +ArgParser _createArgParser() => ArgParser() + ..addOption( + 'package', + help: 'Root directory of the package to test.', + defaultsTo: '.', + ) + ..addOption( + 'package-name', + help: 'Name of the package to test. ' + 'Deduced from --package if not provided.', + ) + ..addOption('port', help: 'VM service port.', defaultsTo: '8181') + ..addOption( + 'out', + abbr: 'o', + help: 'Output directory. Defaults to <package-dir>/coverage.', + ) + ..addOption('test', help: 'Test script to run.', defaultsTo: 'test') + ..addFlag( + 'function-coverage', + abbr: 'f', + defaultsTo: false, + help: 'Collect function coverage info.', + ) + ..addFlag( + 'branch-coverage', + abbr: 'b', + defaultsTo: false, + help: 'Collect branch coverage info.', + ) + ..addMultiOption('scope-output', + help: 'restrict coverage results so that only scripts that start with ' + 'the provided package path are considered. Defaults to the name of ' + 'the package under test.') + ..addFlag('help', abbr: 'h', negatable: false, help: 'Show this help.'); + +class Flags { + Flags( + this.packageDir, + this.packageName, + this.outDir, + this.port, + this.testScript, + this.functionCoverage, + this.branchCoverage, + this.scopeOutput, { + required this.rest, + }); + + final String packageDir; + final String packageName; + final String outDir; + final String port; + final String testScript; + final bool functionCoverage; + final bool branchCoverage; + final List<String> scopeOutput; + final List<String> rest; +} + +Future<Flags> _parseArgs(List<String> arguments) async { + final parser = _createArgParser(); + final args = parser.parse(arguments); + + void printUsage() { + print(''' +Runs tests and collects coverage for a package. + +By default this script assumes it's being run from the root directory of a +package, and outputs a coverage.json and lcov.info to ./coverage/ + +Usage: test_with_coverage [OPTIONS...] [-- <test script OPTIONS>] + +${parser.usage} +'''); + } + + Never fail(String msg) { + print('\n$msg\n'); + printUsage(); + exit(1); + } + + if (args['help'] as bool) { + printUsage(); + exit(0); + } + + final packageDir = path.canonicalize(args['package'] as String); + if (!FileSystemEntity.isDirectorySync(packageDir)) { + fail('--package is not a valid directory.'); + } + + final packageName = (args['package-name'] as String?) ?? + await _packageNameFromConfig(packageDir); + if (packageName == null) { + fail( + "Couldn't figure out package name from --package. Make sure this is a " + 'package directory, or try passing --package-name explicitly.', + ); + } + + return Flags( + packageDir, + packageName, + (args['out'] as String?) ?? path.join(packageDir, 'coverage'), + args['port'] as String, + args['test'] as String, + args['function-coverage'] as bool, + args['branch-coverage'] as bool, + args['scope-output'] as List<String>, + rest: args.rest, + ); +} + +Future<void> main(List<String> arguments) async { + final flags = await _parseArgs(arguments); + final outJson = path.join(flags.outDir, 'coverage.json'); + final outLcov = path.join(flags.outDir, 'lcov.info'); + + if (!FileSystemEntity.isDirectorySync(flags.outDir)) { + await Directory(flags.outDir).create(recursive: true); + } + + _watchExitSignal(ProcessSignal.sighup); + _watchExitSignal(ProcessSignal.sigint); + if (!Platform.isWindows) { + _watchExitSignal(ProcessSignal.sigterm); + } + + final serviceUriCompleter = Completer<Uri>(); + final testProcess = _dartRun( + [ + if (flags.branchCoverage) '--branch-coverage', + 'run', + '--pause-isolates-on-exit', + '--disable-service-auth-codes', + '--enable-vm-service=${flags.port}', + flags.testScript, + ...flags.rest, + ], + onStdout: (line) { + if (!serviceUriCompleter.isCompleted) { + final uri = extractVMServiceUri(line); + if (uri != null) { + serviceUriCompleter.complete(uri); + } + } + }, + ); + final serviceUri = await serviceUriCompleter.future; + + final scopes = + flags.scopeOutput.isEmpty ? [flags.packageName] : flags.scopeOutput; + await collect_coverage.main([ + '--wait-paused', + '--resume-isolates', + '--uri=$serviceUri', + for (final scope in scopes) '--scope-output=$scope', + if (flags.branchCoverage) '--branch-coverage', + if (flags.functionCoverage) '--function-coverage', + '-o', + outJson, + ]); + await testProcess; + + await format_coverage.main([ + '--lcov', + '--check-ignore', + '--package=${flags.packageDir}', + '-i', + outJson, + '-o', + outLcov, + ]); + exit(0); +}
diff --git a/pkgs/coverage/lib/coverage.dart b/pkgs/coverage/lib/coverage.dart new file mode 100644 index 0000000..9cc81ab --- /dev/null +++ b/pkgs/coverage/lib/coverage.dart
@@ -0,0 +1,10 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +export 'src/chrome.dart'; +export 'src/collect.dart'; +export 'src/formatter.dart'; +export 'src/hitmap.dart' hide hitmapToJson; +export 'src/resolver.dart'; +export 'src/run_and_collect.dart';
diff --git a/pkgs/coverage/lib/src/chrome.dart b/pkgs/coverage/lib/src/chrome.dart new file mode 100644 index 0000000..2a97696 --- /dev/null +++ b/pkgs/coverage/lib/src/chrome.dart
@@ -0,0 +1,171 @@ +// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:source_maps/parser.dart'; + +import 'hitmap.dart'; + +/// Returns a Dart based hit-map containing coverage report for the provided +/// Chrome [preciseCoverage]. +/// +/// [sourceProvider] returns the source content for the Chrome scriptId, or null +/// if not available. +/// +/// [sourceMapProvider] returns the associated source map content for the Chrome +/// scriptId, or null if not available. +/// +/// [sourceUriProvider] returns the uri for the provided sourceUrl and +/// associated scriptId, or null if not available. +/// +/// Chrome coverage information for which the corresponding source map or source +/// content is null will be ignored. +Future<Map<String, dynamic>> parseChromeCoverage( + List<Map<String, dynamic>> preciseCoverage, + Future<String?> Function(String scriptId) sourceProvider, + Future<String?> Function(String scriptId) sourceMapProvider, + Future<Uri?> Function(String sourceUrl, String scriptId) sourceUriProvider, +) async { + final coverageReport = <Uri, Map<int, bool>>{}; + for (var entry in preciseCoverage) { + final scriptId = entry['scriptId'] as String; + + final mapResponse = await sourceMapProvider(scriptId); + if (mapResponse == null) continue; + + SingleMapping mapping; + try { + mapping = parse(mapResponse) as SingleMapping; + } on FormatException { + continue; + // ignore: avoid_catching_errors + } on ArgumentError { + continue; + } + + final compiledSource = await sourceProvider(scriptId); + if (compiledSource == null) continue; + + final coverageInfo = _coverageInfoFor(entry); + final offsetCoverage = _offsetCoverage(coverageInfo, compiledSource.length); + final coveredPositions = _coveredPositions(compiledSource, offsetCoverage); + + for (var lineEntry in mapping.lines) { + for (var columnEntry in lineEntry.entries) { + final sourceUrlId = columnEntry.sourceUrlId; + if (sourceUrlId == null) continue; + final sourceUrl = mapping.urls[sourceUrlId]; + + // Ignore coverage information for the SDK. + if (sourceUrl.startsWith('org-dartlang-sdk:')) continue; + + final uri = await sourceUriProvider(sourceUrl, scriptId); + if (uri == null) continue; + final coverage = coverageReport.putIfAbsent(uri, () => <int, bool>{}); + + final sourceLine = columnEntry.sourceLine!; + final current = coverage[sourceLine + 1] ?? false; + coverage[sourceLine + 1] = current || + coveredPositions.contains( + _Position(lineEntry.line + 1, columnEntry.column + 1)); + } + } + } + + final coverageHitMaps = <Uri, HitMap>{}; + coverageReport.forEach((uri, coverage) { + final hitMap = HitMap(); + for (var line in coverage.keys.toList()..sort()) { + hitMap.lineHits[line] = coverage[line]! ? 1 : 0; + } + coverageHitMaps[uri] = hitMap; + }); + + final allCoverage = <Map<String, dynamic>>[]; + coverageHitMaps.forEach((uri, hitMap) { + allCoverage.add(hitmapToJson(hitMap, uri)); + }); + return <String, dynamic>{'type': 'CodeCoverage', 'coverage': allCoverage}; +} + +/// Returns all covered positions in a provided source. +Set<_Position> _coveredPositions( + String compiledSource, List<bool> offsetCoverage) { + final positions = <_Position>{}; + // Line is 1 based. + var line = 1; + // Column is 1 based. + var column = 0; + for (var offset = 0; offset < compiledSource.length; offset++) { + if (compiledSource[offset] == '\n') { + line++; + column = 0; + } else { + column++; + } + if (offsetCoverage[offset]) positions.add(_Position(line, column)); + } + return positions; +} + +/// Returns coverage information for a Chrome entry. +List<_CoverageInfo> _coverageInfoFor(Map<String, dynamic> entry) { + final result = <_CoverageInfo>[]; + for (var functions + in (entry['functions'] as List).cast<Map<String, dynamic>>()) { + for (var range + in (functions['ranges'] as List).cast<Map<String, dynamic>>()) { + result.add(_CoverageInfo( + range['startOffset'] as int, + range['endOffset'] as int, + (range['count'] as int) > 0, + )); + } + } + return result; +} + +/// Returns the coverage information for each offset. +List<bool> _offsetCoverage(List<_CoverageInfo> coverageInfo, int sourceLength) { + final offsetCoverage = List.filled(sourceLength, false); + + // Sort coverage information by their size. + // Coverage information takes granularity as precedence. + coverageInfo.sort((a, b) => + (b.endOffset - b.startOffset).compareTo(a.endOffset - a.startOffset)); + + for (var range in coverageInfo) { + for (var i = range.startOffset; i < range.endOffset; i++) { + offsetCoverage[i] = range.isCovered; + } + } + + return offsetCoverage; +} + +class _CoverageInfo { + _CoverageInfo(this.startOffset, this.endOffset, this.isCovered); + + /// 0 based byte offset. + final int startOffset; + + /// 0 based byte offset. + final int endOffset; + + final bool isCovered; +} + +/// A covered position in a source file where [line] and [column] are 1 based. +class _Position { + _Position(this.line, this.column); + + final int line; + final int column; + + @override + int get hashCode => Object.hash(line, column); + + @override + bool operator ==(Object o) => + o is _Position && o.line == line && o.column == column; +}
diff --git a/pkgs/coverage/lib/src/collect.dart b/pkgs/coverage/lib/src/collect.dart new file mode 100644 index 0000000..76227ba --- /dev/null +++ b/pkgs/coverage/lib/src/collect.dart
@@ -0,0 +1,447 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:io'; + +import 'package:vm_service/vm_service.dart'; + +import 'hitmap.dart'; +import 'isolate_paused_listener.dart'; +import 'util.dart'; + +const _retryInterval = Duration(milliseconds: 200); +const _debugTokenPositions = bool.fromEnvironment('DEBUG_COVERAGE'); + +/// Collects coverage for all isolates in the running VM. +/// +/// Collects a hit-map containing merged coverage for all isolates in the Dart +/// VM associated with the specified [serviceUri]. Returns a map suitable for +/// input to the coverage formatters that ship with this package. +/// +/// [serviceUri] must specify the http/https URI of the service port of a +/// running Dart VM and must not be null. +/// +/// If [resume] is true, all isolates will be resumed once coverage collection +/// is complete. +/// +/// If [waitPaused] is true, collection will not begin for an isolate until it +/// is in the paused state. +/// +/// If [includeDart] is true, code coverage for core `dart:*` libraries will be +/// collected. +/// +/// If [functionCoverage] is true, function coverage information will be +/// collected. +/// +/// If [branchCoverage] is true, branch coverage information will be collected. +/// This will only work correctly if the target VM was run with the +/// --branch-coverage flag. +/// +/// If [scopedOutput] is non-empty, coverage will be restricted so that only +/// scripts that start with any of the provided paths are considered. +/// +/// If [isolateIds] is set, the coverage gathering will be restricted to only +/// those VM isolates. +/// +/// If [coverableLineCache] is set, the collector will avoid recompiling +/// libraries it has already seen (see VmService.getSourceReport's +/// librariesAlreadyCompiled parameter). This is only useful when doing more +/// than one [collect] call over the same libraries. Pass an empty map to the +/// first call, and then pass the same map to all subsequent calls. +/// +/// [serviceOverrideForTesting] is for internal testing only, and should not be +/// set by users. +Future<Map<String, dynamic>> collect(Uri serviceUri, bool resume, + bool waitPaused, bool includeDart, Set<String>? scopedOutput, + {Set<String>? isolateIds, + Duration? timeout, + bool functionCoverage = false, + bool branchCoverage = false, + Map<String, Set<int>>? coverableLineCache, + VmService? serviceOverrideForTesting}) async { + scopedOutput ??= <String>{}; + + late VmService service; + if (serviceOverrideForTesting != null) { + service = serviceOverrideForTesting; + } else { + // Create websocket URI. Handle any trailing slashes. + final pathSegments = + serviceUri.pathSegments.where((c) => c.isNotEmpty).toList()..add('ws'); + final uri = serviceUri.replace(scheme: 'ws', pathSegments: pathSegments); + + await retry(() async { + try { + final options = const CompressionOptions(enabled: false); + final socket = await WebSocket.connect('$uri', compression: options); + final controller = StreamController<String>(); + socket.listen((data) => controller.add(data as String), onDone: () { + controller.close(); + service.dispose(); + }); + service = VmService(controller.stream, socket.add, + log: StdoutLog(), disposeHandler: socket.close); + await service.getVM().timeout(_retryInterval); + } on TimeoutException { + // The signature changed in vm_service version 6.0.0. + // ignore: await_only_futures + await service.dispose(); + rethrow; + } + }, _retryInterval, timeout: timeout); + } + + try { + return await _getAllCoverage( + service, + includeDart, + functionCoverage, + branchCoverage, + scopedOutput, + isolateIds, + coverableLineCache, + waitPaused); + } finally { + if (resume && !waitPaused) { + await _resumeIsolates(service); + } + // The signature changed in vm_service version 6.0.0. + // ignore: await_only_futures + await service.dispose(); + } +} + +Future<Map<String, dynamic>> _getAllCoverage( + VmService service, + bool includeDart, + bool functionCoverage, + bool branchCoverage, + Set<String> scopedOutput, + Set<String>? isolateIds, + Map<String, Set<int>>? coverableLineCache, + bool waitPaused) async { + final allCoverage = <Map<String, dynamic>>[]; + + final sourceReportKinds = [ + SourceReportKind.kCoverage, + if (branchCoverage) SourceReportKind.kBranchCoverage, + ]; + + final librariesAlreadyCompiled = coverableLineCache?.keys.toList(); + + // Program counters are shared between isolates in the same group. So we need + // to make sure we're only gathering coverage data for one isolate in each + // group, otherwise we'll double count the hits. + final coveredIsolateGroups = <String>{}; + + Future<void> collectIsolate(IsolateRef isolateRef) async { + if (!(isolateIds?.contains(isolateRef.id) ?? true)) return; + + // coveredIsolateGroups is only relevant for the !waitPaused flow. The + // waitPaused flow achieves the same once-per-group behavior using the + // isLastIsolateInGroup flag. + final isolateGroupId = isolateRef.isolateGroupId; + if (isolateGroupId != null) { + if (coveredIsolateGroups.contains(isolateGroupId)) return; + coveredIsolateGroups.add(isolateGroupId); + } + + late final SourceReport isolateReport; + try { + isolateReport = await service.getSourceReport( + isolateRef.id!, + sourceReportKinds, + forceCompile: true, + reportLines: true, + libraryFilters: scopedOutput.isNotEmpty + ? List.from(scopedOutput.map((filter) => 'package:$filter/')) + : null, + librariesAlreadyCompiled: librariesAlreadyCompiled, + ); + } on SentinelException { + return; + } + + final coverage = await _processSourceReport( + service, + isolateRef, + isolateReport, + includeDart, + functionCoverage, + coverableLineCache, + scopedOutput); + allCoverage.addAll(coverage); + } + + if (waitPaused) { + await IsolatePausedListener(service, + (IsolateRef isolateRef, bool isLastIsolateInGroup) async { + if (isLastIsolateInGroup) { + await collectIsolate(isolateRef); + } + }, stderr.writeln) + .waitUntilAllExited(); + } else { + for (final isolateRef in await getAllIsolates(service)) { + await collectIsolate(isolateRef); + } + } + + return <String, dynamic>{'type': 'CodeCoverage', 'coverage': allCoverage}; +} + +Future _resumeIsolates(VmService service) async { + final vm = await service.getVM(); + final futures = <Future>[]; + for (var isolateRef in vm.isolates!) { + // Guard against sync as well as async errors: sync - when we are writing + // message to the socket, the socket might be closed; async - when we are + // waiting for the response, the socket again closes. + futures.add(Future.sync(() async { + final isolate = await service.getIsolate(isolateRef.id!); + if (isolate.pauseEvent!.kind != EventKind.kResume) { + await service.resume(isolateRef.id!); + } + })); + } + try { + await Future.wait(futures); + } catch (_) { + // Ignore resume isolate failures + } +} + +/// Returns the line number to which the specified token position maps. +/// +/// Performs a binary search within the script's token position table to locate +/// the line in question. +int? _getLineFromTokenPos(Script script, int tokenPos) { + // TODO(cbracken): investigate whether caching this lookup results in + // significant performance gains. + var min = 0; + var max = script.tokenPosTable!.length; + while (min < max) { + final mid = min + ((max - min) >> 1); + final row = script.tokenPosTable![mid]; + if (row[1] > tokenPos) { + max = mid; + } else { + for (var i = 1; i < row.length; i += 2) { + if (row[i] == tokenPos) return row.first; + } + min = mid + 1; + } + } + return null; +} + +/// Returns a JSON coverage list backward-compatible with pre-1.16.0 SDKs. +Future<List<Map<String, dynamic>>> _processSourceReport( + VmService service, + IsolateRef isolateRef, + SourceReport report, + bool includeDart, + bool functionCoverage, + Map<String, Set<int>>? coverableLineCache, + Set<String> scopedOutput) async { + final hitMaps = <Uri, HitMap>{}; + final scripts = <ScriptRef, Script>{}; + final libraries = <LibraryRef>{}; + final needScripts = functionCoverage; + + Future<Script?> getScript(ScriptRef? scriptRef) async { + if (scriptRef == null) { + return null; + } + if (!scripts.containsKey(scriptRef)) { + scripts[scriptRef] = + await service.getObject(isolateRef.id!, scriptRef.id!) as Script; + } + return scripts[scriptRef]; + } + + HitMap getHitMap(Uri scriptUri) => hitMaps.putIfAbsent(scriptUri, HitMap.new); + + Future<void> processFunction(FuncRef funcRef) async { + final func = await service.getObject(isolateRef.id!, funcRef.id!) as Func; + if ((func.implicit ?? false) || (func.isAbstract ?? false)) { + return; + } + final location = func.location; + if (location == null) { + return; + } + final script = await getScript(location.script); + if (script == null) { + return; + } + final funcName = await _getFuncName(service, isolateRef, func); + // TODO(liama): Is this still necessary, or is location.line valid? + final tokenPos = location.tokenPos!; + final line = _getLineFromTokenPos(script, tokenPos); + if (line == null) { + if (_debugTokenPositions) { + stderr.writeln( + 'tokenPos $tokenPos in function ${funcRef.name} has no line ' + 'mapping for script ${script.uri!}'); + } + return; + } + final hits = getHitMap(Uri.parse(script.uri!)); + hits.funcHits ??= <int, int>{}; + (hits.funcNames ??= <int, String>{})[line] = funcName; + } + + for (var range in report.ranges!) { + final scriptRef = report.scripts![range.scriptIndex!]; + final scriptUriString = scriptRef.uri; + if (!scopedOutput.includesScript(scriptUriString)) { + // Sometimes a range's script can be different to the function's script + // (eg mixins), so we have to re-check the scope filter. + // See https://github.com/dart-lang/tools/issues/530 + continue; + } + final scriptUri = Uri.parse(scriptUriString!); + + // If we have a coverableLineCache, use it in the same way we use + // SourceReportCoverage.misses: to add zeros to the coverage result for all + // the lines that don't have a hit. Afterwards, add all the lines that were + // hit or missed to the cache, so that the next coverage collection won't + // need to compile this library. + final coverableLines = + coverableLineCache?.putIfAbsent(scriptUriString, () => <int>{}); + + // Not returned in scripts section of source report. + if (scriptUri.scheme == 'evaluate') continue; + + // Skip scripts from dart:. + if (!includeDart && scriptUri.scheme == 'dart') continue; + + // Look up the hit maps for this script (shared across isolates). + final hits = getHitMap(scriptUri); + + Script? script; + if (needScripts) { + script = await getScript(scriptRef); + if (script == null) continue; + } + + // If the script's library isn't loaded, load it then look up all its funcs. + final libRef = script?.library; + if (functionCoverage && libRef != null && !libraries.contains(libRef)) { + libraries.add(libRef); + final library = + await service.getObject(isolateRef.id!, libRef.id!) as Library; + if (library.functions != null) { + for (var funcRef in library.functions!) { + await processFunction(funcRef); + } + } + if (library.classes != null) { + for (var classRef in library.classes!) { + final clazz = + await service.getObject(isolateRef.id!, classRef.id!) as Class; + if (clazz.functions != null) { + for (var funcRef in clazz.functions!) { + await processFunction(funcRef); + } + } + } + } + } + + // Collect hits and misses. + final coverage = range.coverage; + + if (coverage == null) continue; + + void forEachLine(List<int>? tokenPositions, void Function(int line) body) { + if (tokenPositions == null) return; + for (final line in tokenPositions) { + body(line); + } + } + + if (coverableLines != null) { + for (final line in coverableLines) { + hits.lineHits.putIfAbsent(line, () => 0); + } + } + + forEachLine(coverage.hits, (line) { + hits.lineHits.increment(line); + coverableLines?.add(line); + if (hits.funcNames != null && hits.funcNames!.containsKey(line)) { + hits.funcHits!.increment(line); + } + }); + forEachLine(coverage.misses, (line) { + hits.lineHits.putIfAbsent(line, () => 0); + coverableLines?.add(line); + }); + hits.funcNames?.forEach((line, funcName) { + hits.funcHits?.putIfAbsent(line, () => 0); + }); + + final branchCoverage = range.branchCoverage; + if (branchCoverage != null) { + hits.branchHits ??= <int, int>{}; + forEachLine(branchCoverage.hits, (line) { + hits.branchHits!.increment(line); + }); + forEachLine(branchCoverage.misses, (line) { + hits.branchHits!.putIfAbsent(line, () => 0); + }); + } + } + + // Output JSON + final coverage = <Map<String, dynamic>>[]; + hitMaps.forEach((uri, hits) { + coverage.add(hitmapToJson(hits, uri)); + }); + return coverage; +} + +extension _MapExtension<T> on Map<T, int> { + void increment(T key) => this[key] = (this[key] ?? 0) + 1; +} + +Future<String> _getFuncName( + VmService service, IsolateRef isolateRef, Func func) async { + if (func.name == null) { + return '${func.type}:${func.location!.tokenPos}'; + } + final owner = func.owner; + if (owner is ClassRef) { + final cls = await service.getObject(isolateRef.id!, owner.id!) as Class; + if (cls.name != null) return '${cls.name}.${func.name}'; + } + return func.name!; +} + +class StdoutLog extends Log { + @override + void warning(String message) => print(message); + + @override + void severe(String message) => print(message); +} + +extension _ScopedOutput on Set<String> { + bool includesScript(String? scriptUriString) { + if (scriptUriString == null) return false; + + // If the set is empty, it means the user didn't specify a --scope-output + // flag, so allow everything. + if (isEmpty) return true; + + final scriptUri = Uri.parse(scriptUriString); + if (scriptUri.scheme != 'package') return false; + + final scope = scriptUri.pathSegments.first; + return contains(scope); + } +}
diff --git a/pkgs/coverage/lib/src/formatter.dart b/pkgs/coverage/lib/src/formatter.dart new file mode 100644 index 0000000..a37df73 --- /dev/null +++ b/pkgs/coverage/lib/src/formatter.dart
@@ -0,0 +1,223 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:glob/glob.dart'; +import 'package:path/path.dart' as p; + +import 'hitmap.dart'; +import 'resolver.dart'; + +@Deprecated('Migrate to FileHitMapsFormatter') +abstract class Formatter { + /// Returns the formatted coverage data. + Future<String> format(Map<String, Map<int, int>> hitmap); +} + +/// Converts the given hitmap to lcov format and appends the result to +/// env.output. +/// +/// Returns a [Future] that completes as soon as all map entries have been +/// emitted. +@Deprecated('Migrate to FileHitMapsFormatter.formatLcov') +class LcovFormatter implements Formatter { + /// Creates a LCOV formatter. + /// + /// If [reportOn] is provided, coverage report output is limited to files + /// prefixed with one of the paths included. If [basePath] is provided, paths + /// are reported relative to that path. + LcovFormatter(this.resolver, {this.reportOn, this.basePath}); + + final Resolver resolver; + final String? basePath; + final List<String>? reportOn; + + @override + Future<String> format(Map<String, Map<int, int>> hitmap) { + return Future.value(hitmap + .map((key, value) => MapEntry(key, HitMap(value))) + .formatLcov(resolver, basePath: basePath, reportOn: reportOn)); + } +} + +/// Converts the given hitmap to a pretty-print format and appends the result +/// to env.output. +/// +/// Returns a [Future] that completes as soon as all map entries have been +/// emitted. +@Deprecated('Migrate to FileHitMapsFormatter.prettyPrint') +class PrettyPrintFormatter implements Formatter { + /// Creates a pretty-print formatter. + /// + /// If [reportOn] is provided, coverage report output is limited to files + /// prefixed with one of the paths included. + PrettyPrintFormatter(this.resolver, this.loader, + {this.reportOn, this.reportFuncs = false}); + + final Resolver resolver; + final Loader loader; + final List<String>? reportOn; + final bool reportFuncs; + + @override + Future<String> format(Map<String, Map<int, int>> hitmap) { + return hitmap.map((key, value) => MapEntry(key, HitMap(value))).prettyPrint( + resolver, loader, + reportOn: reportOn, reportFuncs: reportFuncs); + } +} + +extension FileHitMapsFormatter on Map<String, HitMap> { + /// Converts the given hitmap to lcov format. + /// + /// If [reportOn] is provided, coverage report output is limited to files + /// prefixed with one of the paths included. If [basePath] is provided, paths + /// are reported relative to that path. + String formatLcov( + Resolver resolver, { + String? basePath, + List<String>? reportOn, + Set<Glob>? ignoreGlobs, + }) { + final pathFilter = _getPathFilter( + reportOn: reportOn, + ignoreGlobs: ignoreGlobs, + ); + final buf = StringBuffer(); + for (final entry in entries) { + final v = entry.value; + final lineHits = v.lineHits; + final funcHits = v.funcHits; + final funcNames = v.funcNames; + final branchHits = v.branchHits; + var source = resolver.resolve(entry.key); + if (source == null) { + continue; + } + + if (!pathFilter(source)) { + continue; + } + + if (basePath != null) { + source = p.relative(source, from: basePath); + } + + buf.write('SF:$source\n'); + if (funcHits != null && funcNames != null) { + for (final k in funcNames.keys.toList()..sort()) { + buf.write('FN:$k,${funcNames[k]}\n'); + } + for (final k in funcHits.keys.toList()..sort()) { + if (funcHits[k]! != 0) { + buf.write('FNDA:${funcHits[k]},${funcNames[k]}\n'); + } + } + buf.write('FNF:${funcNames.length}\n'); + buf.write('FNH:${funcHits.values.where((v) => v > 0).length}\n'); + } + for (final k in lineHits.keys.toList()..sort()) { + buf.write('DA:$k,${lineHits[k]}\n'); + } + buf.write('LF:${lineHits.length}\n'); + buf.write('LH:${lineHits.values.where((v) => v > 0).length}\n'); + if (branchHits != null) { + for (final k in branchHits.keys.toList()..sort()) { + buf.write('BRDA:$k,0,0,${branchHits[k]}\n'); + } + } + buf.write('end_of_record\n'); + } + + return buf.toString(); + } + + /// Converts the given hitmap to a pretty-print format. + /// + /// If [reportOn] is provided, coverage report output is limited to files + /// prefixed with one of the paths included. If [reportFuncs] is provided, + /// only function coverage information will be shown. + Future<String> prettyPrint( + Resolver resolver, + Loader loader, { + List<String>? reportOn, + Set<Glob>? ignoreGlobs, + bool reportFuncs = false, + bool reportBranches = false, + }) async { + final pathFilter = _getPathFilter( + reportOn: reportOn, + ignoreGlobs: ignoreGlobs, + ); + final buf = StringBuffer(); + for (final entry in entries) { + final v = entry.value; + if (reportFuncs && v.funcHits == null) { + throw StateError( + 'Function coverage formatting was requested, but the hit map is ' + 'missing function coverage information. Did you run ' + 'collect_coverage with the --function-coverage flag?', + ); + } + if (reportBranches && v.branchHits == null) { + throw StateError( + 'Branch coverage formatting was requested, but the hit map is ' + 'missing branch coverage information. Did you run ' + 'collect_coverage with the --branch-coverage flag?'); + } + final hits = reportFuncs + ? v.funcHits! + : reportBranches + ? v.branchHits! + : v.lineHits; + final source = resolver.resolve(entry.key); + if (source == null) { + continue; + } + + if (!pathFilter(source)) { + continue; + } + + final lines = await loader.load(source); + if (lines == null) { + continue; + } + buf.writeln(source); + for (var line = 1; line <= lines.length; line++) { + var prefix = _prefix; + if (hits.containsKey(line)) { + prefix = hits[line].toString().padLeft(_prefix.length); + } + buf.writeln('$prefix|${lines[line - 1]}'); + } + } + + return buf.toString(); + } +} + +const _prefix = ' '; + +typedef _PathFilter = bool Function(String path); + +_PathFilter _getPathFilter({List<String>? reportOn, Set<Glob>? ignoreGlobs}) { + if (reportOn == null && ignoreGlobs == null) return (String path) => true; + + final absolutePaths = reportOn?.map(p.canonicalize).toList(); + + return (String path) { + final canonicalizedPath = p.canonicalize(path); + + if (absolutePaths != null && + !absolutePaths.any(canonicalizedPath.startsWith)) { + return false; + } + if (ignoreGlobs != null && + ignoreGlobs.any((glob) => glob.matches(canonicalizedPath))) { + return false; + } + + return true; + }; +}
diff --git a/pkgs/coverage/lib/src/hitmap.dart b/pkgs/coverage/lib/src/hitmap.dart new file mode 100644 index 0000000..4c3b468 --- /dev/null +++ b/pkgs/coverage/lib/src/hitmap.dart
@@ -0,0 +1,386 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert' show json; +import 'dart:io'; + +import 'resolver.dart'; +import 'util.dart'; + +/// Contains line and function hit information for a single script. +class HitMap { + /// Constructs a HitMap. + HitMap([ + Map<int, int>? lineHits, + this.funcHits, + this.funcNames, + this.branchHits, + ]) : lineHits = lineHits ?? {}; + + /// Map from line to hit count for that line. + final Map<int, int> lineHits; + + /// Map from the first line of each function, to the hit count for that + /// function. Null if function coverage info was not gathered. + Map<int, int>? funcHits; + + /// Map from the first line of each function, to the function name. Null if + /// function coverage info was not gathered. + Map<int, String>? funcNames; + + /// Map from branch line, to the hit count for that branch. Null if branch + /// coverage info was not gathered. + Map<int, int>? branchHits; + + /// Creates a single hitmap from a raw json object. + /// + /// Note that when [checkIgnoredLines] is `true` all files will be + /// read to get ignore comments. This will add some overhead. + /// To combat this when calling this function multiple times from the + /// same source (e.g. test runs of different files) a cache is taken + /// via [ignoredLinesInFilesCache]. If this cache contains the parsed + /// data for the specific file already, the file will not be read and + /// parsed again. + /// + /// Throws away all entries that are not resolvable. + static Map<String, HitMap> parseJsonSync( + List<Map<String, dynamic>> jsonResult, { + required bool checkIgnoredLines, + required Map<String, List<List<int>>?> ignoredLinesInFilesCache, + required Resolver resolver, + }) { + final loader = Loader(); + + // Map of source file to map of line to hit count for that line. + final globalHitMap = <String, HitMap>{}; + + for (var e in jsonResult) { + final source = e['source'] as String?; + if (source == null) { + // Couldn't resolve import, so skip this entry. + continue; + } + + var ignoredLinesList = <List<int>>[]; + + if (checkIgnoredLines) { + if (ignoredLinesInFilesCache.containsKey(source)) { + final cacheHit = ignoredLinesInFilesCache[source]; + if (cacheHit == null) { + // Null-entry indicates that the whole file was ignored. + continue; + } + ignoredLinesList = cacheHit; + } else { + final path = resolver.resolve(source); + if (path != null) { + final lines = loader.loadSync(path) ?? []; + ignoredLinesList = getIgnoredLines(path, lines); + + // Ignore the whole file. + if (ignoredLinesList.length == 1 && + ignoredLinesList[0][0] == 0 && + ignoredLinesList[0][1] == lines.length) { + // Null-entry indicates that the whole file was ignored. + ignoredLinesInFilesCache[source] = null; + continue; + } + ignoredLinesInFilesCache[source] = ignoredLinesList; + } else { + // Couldn't resolve source. Allow cache to answer next time + // anyway. + ignoredLinesInFilesCache[source] = ignoredLinesList; + } + } + } + + // Move to the first ignore range. + final ignoredLines = ignoredLinesList.iterator; + var hasCurrent = ignoredLines.moveNext(); + + bool shouldIgnoreLine(Iterator<List<int>> ignoredRanges, int line) { + if (!hasCurrent || ignoredRanges.current.isEmpty) { + return false; + } + + if (line < ignoredRanges.current[0]) return false; + + while (hasCurrent && + ignoredRanges.current.isNotEmpty && + ignoredRanges.current[1] < line) { + hasCurrent = ignoredRanges.moveNext(); + } + + if (hasCurrent && + ignoredRanges.current.isNotEmpty && + ignoredRanges.current[0] <= line && + line <= ignoredRanges.current[1]) { + return true; + } + + return false; + } + + void addToMap(Map<int, int> map, int line, int count) { + final oldCount = map.putIfAbsent(line, () => 0); + map[line] = count + oldCount; + } + + void fillHitMap(List hits, Map<int, int> hitMap) { + // Ignore line annotations require hits to be sorted. + hits = _sortHits(hits); + // hits is a flat array of the following format: + // [ <line|linerange>, <hitcount>,...] + // line: number. + // linerange: '<line>-<line>'. + for (var i = 0; i < hits.length; i += 2) { + final k = hits[i]; + if (k is int) { + // Single line. + if (shouldIgnoreLine(ignoredLines, k)) continue; + + addToMap(hitMap, k, hits[i + 1] as int); + } else if (k is String) { + // Linerange. We expand line ranges to actual lines at this point. + final splitPos = k.indexOf('-'); + final start = int.parse(k.substring(0, splitPos)); + final end = int.parse(k.substring(splitPos + 1)); + for (var j = start; j <= end; j++) { + if (shouldIgnoreLine(ignoredLines, j)) continue; + + addToMap(hitMap, j, hits[i + 1] as int); + } + } else { + throw StateError('Expected value of type int or String'); + } + } + } + + final sourceHitMap = globalHitMap.putIfAbsent(source, HitMap.new); + fillHitMap(e['hits'] as List, sourceHitMap.lineHits); + if (e.containsKey('funcHits')) { + sourceHitMap.funcHits ??= <int, int>{}; + fillHitMap(e['funcHits'] as List, sourceHitMap.funcHits!); + } + if (e.containsKey('funcNames')) { + sourceHitMap.funcNames ??= <int, String>{}; + final funcNames = e['funcNames'] as List; + for (var i = 0; i < funcNames.length; i += 2) { + sourceHitMap.funcNames![funcNames[i] as int] = + funcNames[i + 1] as String; + } + } + if (e.containsKey('branchHits')) { + sourceHitMap.branchHits ??= <int, int>{}; + fillHitMap(e['branchHits'] as List, sourceHitMap.branchHits!); + } + } + return globalHitMap; + } + + /// Creates a single hitmap from a raw json object. + /// + /// Throws away all entries that are not resolvable. + static Future<Map<String, HitMap>> parseJson( + List<Map<String, dynamic>> jsonResult, { + bool checkIgnoredLines = false, + @Deprecated('Use packagePath') String? packagesPath, + String? packagePath, + }) async { + final resolver = await Resolver.create( + packagesPath: packagesPath, packagePath: packagePath); + return parseJsonSync(jsonResult, + checkIgnoredLines: checkIgnoredLines, + ignoredLinesInFilesCache: {}, + resolver: resolver); + } + + /// Generates a merged hitmap from a set of coverage JSON files. + static Future<Map<String, HitMap>> parseFiles( + Iterable<File> files, { + bool checkIgnoredLines = false, + @Deprecated('Use packagePath') String? packagesPath, + String? packagePath, + }) async { + final globalHitmap = <String, HitMap>{}; + for (var file in files) { + final contents = file.readAsStringSync(); + final jsonMap = json.decode(contents) as Map<String, dynamic>; + if (jsonMap.containsKey('coverage')) { + final jsonResult = jsonMap['coverage'] as List; + globalHitmap.merge(await HitMap.parseJson( + jsonResult.cast<Map<String, dynamic>>(), + checkIgnoredLines: checkIgnoredLines, + // ignore: deprecated_member_use_from_same_package + packagesPath: packagesPath, + packagePath: packagePath, + )); + } + } + return globalHitmap; + } +} + +extension FileHitMaps on Map<String, HitMap> { + /// Merges [newMap] into this one. + void merge(Map<String, HitMap> newMap) { + newMap.forEach((file, v) { + final fileResult = this[file]; + if (fileResult != null) { + _mergeHitCounts(v.lineHits, fileResult.lineHits); + if (v.funcHits != null) { + fileResult.funcHits ??= <int, int>{}; + _mergeHitCounts(v.funcHits!, fileResult.funcHits!); + } + if (v.funcNames != null) { + fileResult.funcNames ??= <int, String>{}; + v.funcNames?.forEach((line, name) { + fileResult.funcNames![line] = name; + }); + } + if (v.branchHits != null) { + fileResult.branchHits ??= <int, int>{}; + _mergeHitCounts(v.branchHits!, fileResult.branchHits!); + } + } else { + this[file] = v; + } + }); + } + + static void _mergeHitCounts(Map<int, int> src, Map<int, int> dest) { + src.forEach((line, count) { + final lineFileResult = dest[line]; + if (lineFileResult == null) { + dest[line] = count; + } else { + dest[line] = lineFileResult + count; + } + }); + } +} + +/// Class containing information about a coverage hit. +class _HitInfo { + _HitInfo(this.firstLine, this.hitRange, this.hitCount); + + /// The line number of the first line of this hit range. + final int firstLine; + + /// A hit range is either a number (1 line) or a String of the form + /// "start-end" (multi-line range). + final dynamic hitRange; + + /// How many times this hit range was executed. + final int hitCount; +} + +/// Creates a single hitmap from a raw json object. +/// +/// Throws away all entries that are not resolvable. +@Deprecated('Migrate to HitMap.parseJson') +Future<Map<String, Map<int, int>>> createHitmap( + List<Map<String, dynamic>> jsonResult, { + bool checkIgnoredLines = false, + @Deprecated('Use packagePath') String? packagesPath, + String? packagePath, +}) async { + final result = await HitMap.parseJson( + jsonResult, + checkIgnoredLines: checkIgnoredLines, + packagesPath: packagesPath, + packagePath: packagePath, + ); + return result.map((key, value) => MapEntry(key, value.lineHits)); +} + +/// Merges [newMap] into [result]. +@Deprecated('Migrate to FileHitMaps.merge') +void mergeHitmaps( + Map<String, Map<int, int>> newMap, Map<String, Map<int, int>> result) { + newMap.forEach((file, v) { + final fileResult = result[file]; + if (fileResult != null) { + v.forEach((line, count) { + final lineFileResult = fileResult[line]; + if (lineFileResult == null) { + fileResult[line] = count; + } else { + fileResult[line] = lineFileResult + count; + } + }); + } else { + result[file] = v; + } + }); +} + +/// Generates a merged hitmap from a set of coverage JSON files. +@Deprecated('Migrate to HitMap.parseFiles') +Future<Map<String, Map<int, int>>> parseCoverage( + Iterable<File> files, + int _, { + bool checkIgnoredLines = false, + @Deprecated('Use packagePath') String? packagesPath, + String? packagePath, +}) async { + final result = await HitMap.parseFiles(files, + checkIgnoredLines: checkIgnoredLines, + packagesPath: packagesPath, + packagePath: packagePath); + return result.map((key, value) => MapEntry(key, value.lineHits)); +} + +/// Returns a JSON hit map backward-compatible with pre-1.16.0 SDKs. +@Deprecated('Will be removed in 2.0.0') +Map<String, dynamic> toScriptCoverageJson(Uri scriptUri, Map<int, int> hitMap) { + return hitmapToJson(HitMap(hitMap), scriptUri); +} + +List<T> _flattenMap<T>(Map map) { + final kvs = <T>[]; + map.forEach((k, v) { + kvs.add(k as T); + kvs.add(v as T); + }); + return kvs; +} + +/// Returns a JSON hit map backward-compatible with pre-1.16.0 SDKs. +Map<String, dynamic> hitmapToJson(HitMap hitmap, Uri scriptUri) => + <String, dynamic>{ + 'source': '$scriptUri', + 'script': { + 'type': '@Script', + 'fixedId': true, + 'id': + 'libraries/1/scripts/${Uri.encodeComponent(scriptUri.toString())}', + 'uri': '$scriptUri', + '_kind': 'library', + }, + 'hits': _flattenMap<int>(hitmap.lineHits), + if (hitmap.funcHits != null) + 'funcHits': _flattenMap<int>(hitmap.funcHits!), + if (hitmap.funcNames != null) + 'funcNames': _flattenMap<dynamic>(hitmap.funcNames!), + if (hitmap.branchHits != null) + 'branchHits': _flattenMap<int>(hitmap.branchHits!), + }; + +/// Sorts the hits array based on the line numbers. +List _sortHits(List hits) { + final structuredHits = <_HitInfo>[]; + for (var i = 0; i < hits.length - 1; i += 2) { + final lineOrLineRange = hits[i]; + final firstLineInRange = lineOrLineRange is int + ? lineOrLineRange + : int.parse((lineOrLineRange as String).split('-')[0]); + structuredHits.add(_HitInfo(firstLineInRange, hits[i], hits[i + 1] as int)); + } + structuredHits.sort((a, b) => a.firstLine.compareTo(b.firstLine)); + return structuredHits + .map((item) => [item.hitRange, item.hitCount]) + .expand((item) => item) + .toList(); +}
diff --git a/pkgs/coverage/lib/src/isolate_paused_listener.dart b/pkgs/coverage/lib/src/isolate_paused_listener.dart new file mode 100644 index 0000000..a89a88b --- /dev/null +++ b/pkgs/coverage/lib/src/isolate_paused_listener.dart
@@ -0,0 +1,275 @@ +// 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:collection'; + +import 'package:meta/meta.dart'; +import 'package:vm_service/vm_service.dart'; + +import 'util.dart'; + +typedef SyncIsolateCallback = void Function(IsolateRef isolate); +typedef AsyncIsolateCallback = Future<void> Function(IsolateRef isolate); +typedef AsyncIsolatePausedCallback = Future<void> Function( + IsolateRef isolate, bool isLastIsolateInGroup); +typedef AsyncVmServiceEventCallback = Future<void> Function(Event event); +typedef SyncErrorLogger = void Function(String message); + +/// Calls onIsolatePaused whenever an isolate reaches the pause-on-exit state, +/// and passes a flag stating whether that isolate is the last one in the group. +class IsolatePausedListener { + IsolatePausedListener(this._service, this._onIsolatePaused, this._log); + + final VmService _service; + final AsyncIsolatePausedCallback _onIsolatePaused; + final SyncErrorLogger _log; + + final _isolateGroups = <String, IsolateGroupState>{}; + + int _numNonMainIsolates = 0; + final _allNonMainIsolatesExited = Completer<void>(); + bool _finished = false; + + IsolateRef? _mainIsolate; + final _mainIsolatePaused = Completer<bool>(); + + /// Starts listening and returns a future that completes when all isolates + /// have exited. + Future<void> waitUntilAllExited() async { + await listenToIsolateLifecycleEvents(_service, _onStart, _onPause, _onExit); + + await _allNonMainIsolatesExited.future; + + // Resume the main isolate. + try { + if (_mainIsolate != null) { + if (await _mainIsolatePaused.future) { + await _runCallbackAndResume(_mainIsolate!, true); + } + } + } finally { + _finished = true; + } + } + + IsolateGroupState _getGroup(IsolateRef isolateRef) => + _isolateGroups[isolateRef.isolateGroupId!] ??= IsolateGroupState(); + + void _onStart(IsolateRef isolateRef) { + if (_finished) return; + final group = _getGroup(isolateRef); + group.start(isolateRef.id!); + if (_mainIsolate == null && _isMainIsolate(isolateRef)) { + _mainIsolate = isolateRef; + } else { + ++_numNonMainIsolates; + } + } + + Future<void> _onPause(IsolateRef isolateRef) async { + if (_finished) return; + final group = _getGroup(isolateRef); + group.pause(isolateRef.id!); + if (isolateRef.id! == _mainIsolate?.id) { + _mainIsolatePaused.complete(true); + + // If the main isolate is the only isolate, then _allNonMainIsolatesExited + // will never be completed. So check that case here. + _checkCompleted(); + } else { + await _runCallbackAndResume(isolateRef, group.noRunningIsolates); + } + } + + Future<void> _runCallbackAndResume( + IsolateRef isolateRef, bool isLastIsolateInGroup) async { + if (isLastIsolateInGroup) { + _getGroup(isolateRef).collected = true; + } + try { + await _onIsolatePaused(isolateRef, isLastIsolateInGroup); + } finally { + await _service.resume(isolateRef.id!); + } + } + + void _onExit(IsolateRef isolateRef) { + if (_finished) return; + final group = _getGroup(isolateRef); + group.exit(isolateRef.id!); + if (group.noLiveIsolates && !group.collected) { + _log('ERROR: An isolate exited without pausing, causing ' + 'coverage data to be lost for group ${isolateRef.isolateGroupId!}.'); + } + if (isolateRef.id! == _mainIsolate?.id) { + if (!_mainIsolatePaused.isCompleted) { + // Main isolate exited without pausing. + _mainIsolatePaused.complete(false); + } + } else { + --_numNonMainIsolates; + _checkCompleted(); + } + } + + void _checkCompleted() { + if (_numNonMainIsolates == 0 && !_allNonMainIsolatesExited.isCompleted) { + _allNonMainIsolatesExited.complete(); + } + } + + static bool _isMainIsolate(IsolateRef isolateRef) { + // HACK: This should pretty reliably detect the main isolate, but it's not + // foolproof and relies on unstable features. The Dart standalone embedder + // and Flutter both call the main isolate "main", and they both also list + // this isolate first when querying isolates from the VM service. So + // selecting the first isolate named "main" combines these conditions and + // should be reliable enough for now, while we wait for a better test. + // TODO(https://github.com/dart-lang/sdk/issues/56732): Switch to more + // reliable test when it's available. + return isolateRef.name == 'main'; + } +} + +/// Listens to isolate start and pause events, and backfills events for isolates +/// that existed before listening started. +/// +/// Ensures that: +/// - Every [onIsolatePaused] and [onIsolateExited] call will be preceeded by +/// an [onIsolateStarted] call for the same isolate. +/// - Not every [onIsolateExited] call will be preceeded by a [onIsolatePaused] +/// call, but a [onIsolatePaused] will never follow a [onIsolateExited]. +/// - [onIsolateExited] will always run after [onIsolatePaused] completes, even +/// if an exit event arrives while [onIsolatePaused] is being awaited. +/// - Each callback will only be called once per isolate. +Future<void> listenToIsolateLifecycleEvents( + VmService service, + SyncIsolateCallback onIsolateStarted, + AsyncIsolateCallback onIsolatePaused, + SyncIsolateCallback onIsolateExited) async { + final started = <String>{}; + void onStart(IsolateRef isolateRef) { + if (started.add(isolateRef.id!)) onIsolateStarted(isolateRef); + } + + final paused = <String, Future<void>>{}; + Future<void> onPause(IsolateRef isolateRef) async { + try { + onStart(isolateRef); + } finally { + await (paused[isolateRef.id!] ??= onIsolatePaused(isolateRef)); + } + } + + final exited = <String>{}; + Future<void> onExit(IsolateRef isolateRef) async { + onStart(isolateRef); + if (exited.add(isolateRef.id!)) { + try { + // Wait for in-progress pause callbacks, and prevent future pause + // callbacks from running. + await (paused[isolateRef.id!] ??= Future<void>.value()); + } finally { + onIsolateExited(isolateRef); + } + } + } + + final eventBuffer = IsolateEventBuffer((Event event) async { + switch (event.kind) { + case EventKind.kIsolateStart: + return onStart(event.isolate!); + case EventKind.kPauseExit: + return await onPause(event.isolate!); + case EventKind.kIsolateExit: + return await onExit(event.isolate!); + } + }); + + // Listen for isolate start/exit events. + service.onIsolateEvent.listen(eventBuffer.add); + await service.streamListen(EventStreams.kIsolate); + + // Listen for isolate paused events. + service.onDebugEvent.listen(eventBuffer.add); + await service.streamListen(EventStreams.kDebug); + + // Backfill. Add/pause isolates that existed before we subscribed. + for (final isolateRef in await getAllIsolates(service)) { + onStart(isolateRef); + final isolate = await service.getIsolate(isolateRef.id!); + if (isolate.pauseEvent?.kind == EventKind.kPauseExit) { + await onPause(isolateRef); + } + } + + // Flush the buffered stream events, and the start processing them as they + // arrive. + await eventBuffer.flush(); +} + +/// Keeps track of isolates in an isolate group. +class IsolateGroupState { + // IDs of the isolates running in this group. + @visibleForTesting + final running = <String>{}; + + // IDs of the isolates paused just before exiting in this group. + @visibleForTesting + final paused = <String>{}; + + bool collected = false; + + bool get noRunningIsolates => running.isEmpty; + bool get noLiveIsolates => running.isEmpty && paused.isEmpty; + + void start(String id) { + paused.remove(id); + running.add(id); + } + + void pause(String id) { + running.remove(id); + paused.add(id); + } + + void exit(String id) { + running.remove(id); + paused.remove(id); + } + + @override + String toString() => '{running: $running, paused: $paused}'; +} + +/// Buffers VM service isolate [Event]s until [flush] is called. +/// +/// [flush] passes each buffered event to the handler function. After that, any +/// further events are immediately passed to the handler. [flush] returns a +/// future that completes when all the events in the queue have been handled (as +/// well as any events that arrive while flush is in progress). +class IsolateEventBuffer { + IsolateEventBuffer(this._handler); + + final AsyncVmServiceEventCallback _handler; + final _buffer = Queue<Event>(); + var _flushed = false; + + Future<void> add(Event event) async { + if (_flushed) { + await _handler(event); + } else { + _buffer.add(event); + } + } + + Future<void> flush() async { + while (_buffer.isNotEmpty) { + final event = _buffer.removeFirst(); + await _handler(event); + } + _flushed = true; + } +}
diff --git a/pkgs/coverage/lib/src/resolver.dart b/pkgs/coverage/lib/src/resolver.dart new file mode 100644 index 0000000..cb5b728 --- /dev/null +++ b/pkgs/coverage/lib/src/resolver.dart
@@ -0,0 +1,216 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:io'; + +import 'package:package_config/package_config.dart'; +import 'package:path/path.dart' as p; + +/// [Resolver] resolves imports with respect to a given environment. +class Resolver { + @Deprecated('Use Resolver.create') + Resolver({this.packagesPath, this.sdkRoot}) + : _packages = packagesPath != null ? _parsePackages(packagesPath) : null, + packagePath = null; + + Resolver._( + {this.packagesPath, + this.packagePath, + this.sdkRoot, + Map<String, Uri>? packages}) + : _packages = packages; + + static Future<Resolver> create({ + String? packagesPath, + String? packagePath, + String? sdkRoot, + }) async { + return Resolver._( + packagesPath: packagesPath, + packagePath: packagePath, + sdkRoot: sdkRoot, + packages: packagesPath != null + ? _parsePackages(packagesPath) + : (packagePath != null ? await _parsePackage(packagePath) : null), + ); + } + + final String? packagesPath; + final String? packagePath; + final String? sdkRoot; + final List<String> failed = []; + final Map<String, Uri>? _packages; + + /// Returns the absolute path wrt. to the given environment or null, if the + /// import could not be resolved. + String? resolve(String scriptUri) { + final uri = Uri.parse(scriptUri); + if (uri.scheme == 'dart') { + final sdkRoot = this.sdkRoot; + if (sdkRoot == null) { + // No sdk-root given, do not resolve dart: URIs. + return null; + } + String filePath; + if (uri.pathSegments.length > 1) { + var path = uri.pathSegments[0]; + // Drop patch files, since we don't have their source in the compiled + // SDK. + if (path.endsWith('-patch')) { + failed.add('$uri'); + return null; + } + // Canonicalize path. For instance: _collection-dev => _collection_dev. + path = path.replaceAll('-', '_'); + final pathSegments = [ + sdkRoot, + path, + ...uri.pathSegments.sublist(1), + ]; + filePath = p.joinAll(pathSegments); + } else { + // Resolve 'dart:something' to be something/something.dart in the SDK. + final lib = uri.path; + filePath = p.join(sdkRoot, lib, '$lib.dart'); + } + return resolveSymbolicLinks(filePath); + } + if (uri.scheme == 'package') { + final packages = _packages; + if (packages == null) { + return null; + } + + final packageName = uri.pathSegments[0]; + final packageUri = packages[packageName]; + if (packageUri == null) { + failed.add('$uri'); + return null; + } + final packagePath = p.fromUri(packageUri); + final pathInPackage = p.joinAll(uri.pathSegments.sublist(1)); + return resolveSymbolicLinks(p.join(packagePath, pathInPackage)); + } + if (uri.scheme == 'file') { + return resolveSymbolicLinks(p.fromUri(uri)); + } + // We cannot deal with anything else. + failed.add('$uri'); + return null; + } + + /// Returns a canonicalized path, or `null` if the path cannot be resolved. + String? resolveSymbolicLinks(String path) { + final normalizedPath = p.normalize(path); + final type = FileSystemEntity.typeSync(normalizedPath, followLinks: true); + if (type == FileSystemEntityType.notFound) return null; + return File(normalizedPath).resolveSymbolicLinksSync(); + } + + static Map<String, Uri> _parsePackages(String packagesPath) { + final content = File(packagesPath).readAsStringSync(); + final packagesUri = p.toUri(packagesPath); + final parsed = + PackageConfig.parseString(content, Uri.base.resolveUri(packagesUri)); + return { + for (var package in parsed.packages) package.name: package.packageUriRoot + }; + } + + static Future<Map<String, Uri>?> _parsePackage(String packagePath) async { + final parsed = await findPackageConfig(Directory(packagePath)); + if (parsed == null) return null; + return { + for (var package in parsed.packages) package.name: package.packageUriRoot + }; + } +} + +/// Bazel URI resolver. +class BazelResolver extends Resolver { + /// Creates a Bazel resolver with the specified workspace path, if any. + BazelResolver({this.workspacePath = ''}); + + final String workspacePath; + + /// Returns the absolute path wrt. to the given environment or null, if the + /// import could not be resolved. + @override + String? resolve(String scriptUri) { + final uri = Uri.parse(scriptUri); + if (uri.scheme == 'dart') { + // Ignore the SDK + return null; + } + if (uri.scheme == 'package') { + // TODO(cbracken) belongs in a Bazel package + return _resolveBazelPackage(uri.pathSegments); + } + if (uri.scheme == 'file') { + final runfilesPathSegment = + '.runfiles/$workspacePath'.replaceAll(RegExp(r'/*$'), '/'); + final runfilesPos = uri.path.indexOf(runfilesPathSegment); + if (runfilesPos >= 0) { + final pathStart = runfilesPos + runfilesPathSegment.length; + return uri.path.substring(pathStart); + } + return null; + } + if (uri.scheme == 'https' || uri.scheme == 'http') { + return _extractHttpPath(uri); + } + // We cannot deal with anything else. + failed.add('$uri'); + return null; + } + + String _extractHttpPath(Uri uri) { + final packagesPos = uri.pathSegments.indexOf('packages'); + if (packagesPos >= 0) { + final workspacePath = uri.pathSegments.sublist(packagesPos + 1); + return _resolveBazelPackage(workspacePath); + } + return uri.pathSegments.join('/'); + } + + String _resolveBazelPackage(List<String> pathSegments) { + // TODO(cbracken) belongs in a Bazel package + final packageName = pathSegments[0]; + final pathInPackage = pathSegments.sublist(1).join('/'); + final packagePath = packageName.contains('.') + ? packageName.replaceAll('.', '/') + : 'third_party/dart/$packageName'; + return '$packagePath/lib/$pathInPackage'; + } +} + +/// Loads the lines of imported resources. +class Loader { + final List<String> failed = []; + + /// Loads an imported resource and returns a [Future] with a [List] of lines. + /// Returns `null` if the resource could not be loaded. + Future<List<String>?> load(String path) async { + try { + // Ensure `readAsLines` runs within the try block so errors are caught. + return await File(path).readAsLines(); + } catch (_) { + failed.add(path); + return null; + } + } + + /// Loads an imported resource and returns a [List] of lines. + /// Returns `null` if the resource could not be loaded. + List<String>? loadSync(String path) { + try { + // Ensure `readAsLinesSync` runs within the try block so errors are + // caught. + return File(path).readAsLinesSync(); + } catch (_) { + failed.add(path); + return null; + } + } +}
diff --git a/pkgs/coverage/lib/src/run_and_collect.dart b/pkgs/coverage/lib/src/run_and_collect.dart new file mode 100644 index 0000000..f2a9cbc --- /dev/null +++ b/pkgs/coverage/lib/src/run_and_collect.dart
@@ -0,0 +1,50 @@ +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:io'; + +import 'collect.dart'; +import 'util.dart'; + +Future<Map<String, dynamic>> runAndCollect(String scriptPath, + {List<String>? scriptArgs, + bool checked = false, + bool includeDart = false, + Duration? timeout}) async { + final dartArgs = [ + '--enable-vm-service', + '--pause_isolates_on_exit', + if (checked) '--checked', + scriptPath, + ...?scriptArgs, + ]; + + final process = await Process.start(Platform.executable, dartArgs); + + final serviceUri = await serviceUriFromProcess(process.stdout.lines()); + Map<String, dynamic> coverage; + try { + coverage = await collect( + serviceUri, + true, + true, + includeDart, + <String>{}, + timeout: timeout, + ); + } finally { + await process.stderr.drain<void>(); + } + final exitStatus = await process.exitCode; + if (exitStatus != 0) { + throw ProcessException( + Platform.executable, + dartArgs, + 'Process failed.', + exitStatus, + ); + } + return coverage; +}
diff --git a/pkgs/coverage/lib/src/util.dart b/pkgs/coverage/lib/src/util.dart new file mode 100644 index 0000000..cc7f584 --- /dev/null +++ b/pkgs/coverage/lib/src/util.dart
@@ -0,0 +1,186 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:vm_service/vm_service.dart'; + +// TODO(cbracken) make generic +/// Retries the specified function with the specified interval and returns +/// the result on successful completion. +Future<dynamic> retry(Future Function() f, Duration interval, + {Duration? timeout}) async { + var keepGoing = true; + + Future<dynamic> withTimeout(Future Function() f, {Duration? duration}) { + if (duration == null) { + return f(); + } + + return f().timeout(duration, onTimeout: () { + keepGoing = false; + final msg = duration.inSeconds == 0 + ? '${duration.inMilliseconds}ms' + : '${duration.inSeconds}s'; + throw StateError('Failed to complete within $msg'); + }); + } + + return withTimeout(() async { + while (keepGoing) { + try { + return await f(); + } catch (_) { + if (keepGoing) { + await Future<dynamic>.delayed(interval); + } + } + } + }, duration: timeout); +} + +/// Scrapes and returns the Dart VM service URI from a string, or null if not +/// found. +/// +/// Potentially useful as a means to extract it from log statements. +Uri? extractVMServiceUri(String str) { + final listeningMessageRegExp = RegExp( + r'(?:Observatory|The Dart VM service is) listening on ((http|//)[a-zA-Z0-9:/=_\-\.\[\]]+)', + ); + final match = listeningMessageRegExp.firstMatch(str); + if (match != null) { + return Uri.parse(match[1]!); + } + return null; +} + +/// Returns an open port by creating a temporary Socket +Future<int> getOpenPort() async { + ServerSocket socket; + + try { + socket = await ServerSocket.bind(InternetAddress.loopbackIPv4, 0); + } catch (_) { + // try again v/ V6 only. Slight possibility that V4 is disabled + socket = + await ServerSocket.bind(InternetAddress.loopbackIPv6, 0, v6Only: true); + } + + try { + return socket.port; + } finally { + await socket.close(); + } +} + +final muliLineIgnoreStart = RegExp(r'//\s*coverage:ignore-start[\w\d\s]*$'); +final muliLineIgnoreEnd = RegExp(r'//\s*coverage:ignore-end[\w\d\s]*$'); +final singleLineIgnore = RegExp(r'//\s*coverage:ignore-line[\w\d\s]*$'); +final ignoreFile = RegExp(r'//\s*coverage:ignore-file[\w\d\s]*$'); + +/// Return list containing inclusive range of lines to be ignored by coverage. +/// If there is a error in balancing the statements it will throw a +/// [FormatException], +/// unless `coverage:ignore-file` is found. +/// Return [0, lines.length] if the whole file is ignored. +/// +/// ``` +/// 1. final str = ''; // coverage:ignore-line +/// 2. final str = ''; +/// 3. final str = ''; // coverage:ignore-start +/// 4. final str = ''; +/// 5. final str = ''; // coverage:ignore-end +/// ``` +/// +/// Returns +/// ``` +/// [ +/// [1,1], +/// [3,5], +/// ] +/// ``` +/// +List<List<int>> getIgnoredLines(String filePath, List<String>? lines) { + final ignoredLines = <List<int>>[]; + if (lines == null) return ignoredLines; + + final allLines = [ + [0, lines.length] + ]; + + FormatException? err; + var i = 0; + while (i < lines.length) { + if (lines[i].contains(ignoreFile)) return allLines; + + if (lines[i].contains(muliLineIgnoreEnd)) { + err ??= FormatException( + 'unmatched coverage:ignore-end found at $filePath:${i + 1}', + ); + } + + if (lines[i].contains(singleLineIgnore)) ignoredLines.add([i + 1, i + 1]); + + if (lines[i].contains(muliLineIgnoreStart)) { + final start = i; + var isUnmatched = true; + ++i; + while (i < lines.length) { + if (lines[i].contains(ignoreFile)) return allLines; + if (lines[i].contains(muliLineIgnoreStart)) { + err ??= FormatException( + 'coverage:ignore-start found at $filePath:${i + 1}' + ' before previous coverage:ignore-start ended', + ); + break; + } + + if (lines[i].contains(muliLineIgnoreEnd)) { + ignoredLines.add([start + 1, i + 1]); + isUnmatched = false; + break; + } + ++i; + } + + if (isUnmatched) { + err ??= FormatException( + 'coverage:ignore-start found at $filePath:${start + 1}' + ' has no matching coverage:ignore-end', + ); + } + } + ++i; + } + + if (err == null) { + return ignoredLines; + } + + throw err; +} + +extension StandardOutExtension on Stream<List<int>> { + Stream<String> lines() => + transform(const SystemEncoding().decoder).transform(const LineSplitter()); +} + +Future<Uri> serviceUriFromProcess(Stream<String> procStdout) { + // Capture the VM service URI. + final serviceUriCompleter = Completer<Uri>(); + procStdout.listen((line) { + if (!serviceUriCompleter.isCompleted) { + final serviceUri = extractVMServiceUri(line); + if (serviceUri != null) { + serviceUriCompleter.complete(serviceUri); + } + } + }); + return serviceUriCompleter.future; +} + +Future<List<IsolateRef>> getAllIsolates(VmService service) async => + (await service.getVM()).isolates ?? [];
diff --git a/pkgs/coverage/pubspec.yaml b/pkgs/coverage/pubspec.yaml new file mode 100644 index 0000000..87a96d0 --- /dev/null +++ b/pkgs/coverage/pubspec.yaml
@@ -0,0 +1,32 @@ +name: coverage +version: 1.10.0 +description: Coverage data manipulation and formatting +repository: https://github.com/dart-lang/tools/tree/main/pkgs/coverage + +environment: + sdk: ^3.4.0 + +dependencies: + args: ^2.0.0 + glob: ^2.1.2 + logging: ^1.0.0 + meta: ^1.0.2 + package_config: ^2.0.0 + path: ^1.8.0 + source_maps: ^0.10.10 + stack_trace: ^1.10.0 + vm_service: '>=12.0.0 <15.0.0' + +dev_dependencies: + benchmark_harness: ^2.2.0 + build_runner: ^2.3.1 + dart_flutter_team_lints: ^3.0.0 + mockito: ^5.4.4 + test: ^1.24.7 + test_descriptor: ^2.0.0 + test_process: ^2.0.0 + +executables: + collect_coverage: + format_coverage: + test_with_coverage:
diff --git a/pkgs/coverage/test/README.md b/pkgs/coverage/test/README.md new file mode 100644 index 0000000..8fa00df --- /dev/null +++ b/pkgs/coverage/test/README.md
@@ -0,0 +1,9 @@ +## Regenerating mocks + +Some of the tests use a mock VmService that is automatically generated by +Mockito. If the VmService changes, run this command in the root directory of +this repo to regenerate that mock: + +```bash +dart run build_runner build +```
diff --git a/pkgs/coverage/test/chrome_test.dart b/pkgs/coverage/test/chrome_test.dart new file mode 100644 index 0000000..50e7600 --- /dev/null +++ b/pkgs/coverage/test/chrome_test.dart
@@ -0,0 +1,78 @@ +// Copyright (c) 2020, 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. + +// TODO(https://github.com/dart-lang/tools/issues/494): Fix and re-enable this. +@TestOn('!windows') +library; + +import 'dart:convert'; +import 'dart:io'; + +import 'package:coverage/coverage.dart'; +import 'package:test/test.dart'; + +// The scriptId for the main_test.js in the sample report. +const String mainScriptId = '31'; + +Future<String> sourceMapProvider(String scriptId) async { + if (scriptId != mainScriptId) { + return 'something invalid!'; + } + return File('test/test_files/main_test.js.map').readAsString(); +} + +Future<String?> sourceProvider(String scriptId) async { + if (scriptId != mainScriptId) return null; + return File('test/test_files/main_test.js').readAsString(); +} + +Future<Uri> sourceUriProvider(String sourceUrl, String scriptId) async => + Uri.parse(sourceUrl); + +void main() { + test('reports correctly', () async { + final preciseCoverage = json.decode( + await File('test/test_files/chrome_precise_report.txt') + .readAsString()) as List; + + final report = await parseChromeCoverage( + preciseCoverage.cast(), + sourceProvider, + sourceMapProvider, + sourceUriProvider, + ); + + final sourceReport = + (report['coverage'] as List<Map<String, dynamic>>).firstWhere( + (Map<String, dynamic> report) => + report['source'].toString().contains('main_test.dart'), + ); + + final expectedHits = { + 7: 1, + 11: 1, + 13: 1, + 14: 1, + 17: 0, + 19: 0, + 20: 0, + 22: 1, + 23: 1, + 24: 1, + 25: 1, + 28: 1, + 30: 0, + 32: 1, + 34: 1, + 35: 1, + 36: 1, + }; + + final hitMap = sourceReport['hits'] as List<int>; + expect(hitMap.length, equals(expectedHits.keys.length * 2)); + for (var i = 0; i < hitMap.length; i += 2) { + expect(expectedHits[hitMap[i]], equals(hitMap[i + 1])); + } + }); +}
diff --git a/pkgs/coverage/test/collect_coverage_api_test.dart b/pkgs/coverage/test/collect_coverage_api_test.dart new file mode 100644 index 0000000..fd3de43 --- /dev/null +++ b/pkgs/coverage/test/collect_coverage_api_test.dart
@@ -0,0 +1,157 @@ +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:coverage/coverage.dart'; +import 'package:coverage/src/util.dart'; +import 'package:path/path.dart' as p; +import 'package:test/test.dart'; + +import 'test_util.dart'; + +final _isolateLibPath = p.join('test', 'test_files', 'test_app_isolate.dart'); + +final _sampleAppFileUri = p.toUri(p.absolute(testAppPath)).toString(); +final _isolateLibFileUri = p.toUri(p.absolute(_isolateLibPath)).toString(); + +void main() { + test('collect_coverage_api', () async { + final coverage = coverageDataFromJson(await _collectCoverage()); + expect(coverage, isNotEmpty); + + final sources = coverage.sources(); + + for (var sampleCoverageData in sources[_sampleAppFileUri]!) { + expect(sampleCoverageData['hits'], isNotEmpty); + } + + for (var sampleCoverageData in sources[_isolateLibFileUri]!) { + expect(sampleCoverageData['hits'], isNotEmpty); + } + }); + + test('collect_coverage_api with scoped output', () async { + final coverage = coverageDataFromJson( + await _collectCoverage(scopedOutput: <String>{}..add('coverage')), + ); + expect(coverage, isNotEmpty); + + final sources = coverage.sources(); + + for (var key in sources.keys) { + final uri = Uri.parse(key); + expect(uri.path.startsWith('coverage'), isTrue); + } + }); + + test('collect_coverage_api with isolateIds', () async { + final coverage = + coverageDataFromJson(await _collectCoverage(isolateIds: true)); + expect(coverage, isEmpty); + }); + + test('collect_coverage_api with function coverage', () async { + final coverage = + coverageDataFromJson(await _collectCoverage(functionCoverage: true)); + expect(coverage, isNotEmpty); + + final sources = coverage.sources(); + + final functionInfo = functionInfoFromSources(sources); + + expect( + functionInfo[_sampleAppFileUri]!, + { + 'main': 1, + 'usedMethod': 1, + 'unusedMethod': 0, + }, + ); + + expect( + functionInfo[_isolateLibFileUri]!, + { + 'BarClass.BarClass': 1, + 'fooAsync': 1, + 'fooSync': 1, + 'isolateTask': 1, + 'BarClass.baz': 1 + }, + ); + }); + + test('collect_coverage_api with branch coverage', () async { + final coverage = + coverageDataFromJson(await _collectCoverage(branchCoverage: true)); + expect(coverage, isNotEmpty); + + final sources = coverage.sources(); + + // Dart VM versions before 2.17 don't support branch coverage. + expect(sources[_sampleAppFileUri], + everyElement(containsPair('branchHits', isNotEmpty))); + expect(sources[_isolateLibFileUri], + everyElement(containsPair('branchHits', isNotEmpty))); + }); + + test('collect_coverage_api with coverableLineCache', () async { + final coverableLineCache = <String, Set<int>>{}; + final coverage = + await _collectCoverage(coverableLineCache: coverableLineCache); + final result = await HitMap.parseJson( + coverage['coverage'] as List<Map<String, dynamic>>); + + expect(coverableLineCache, contains(_sampleAppFileUri)); + expect(coverableLineCache, contains(_isolateLibFileUri)); + + // Expect that we have some missed lines. + expect(result[_sampleAppFileUri]!.lineHits.containsValue(0), isTrue); + expect(result[_isolateLibFileUri]!.lineHits.containsValue(0), isTrue); + + // Clear _sampleAppFileUri's cache entry, then gather coverage again. We're + // doing this to verify that force compilation is disabled for these + // libraries. The result should be that _isolateLibFileUri should be the + // same, but _sampleAppFileUri should be missing all its missed lines. + coverableLineCache[_sampleAppFileUri] = {}; + final coverage2 = + await _collectCoverage(coverableLineCache: coverableLineCache); + final result2 = await HitMap.parseJson( + coverage2['coverage'] as List<Map<String, dynamic>>); + + // _isolateLibFileUri still has missed lines, but _sampleAppFileUri doesn't. + expect(result2[_sampleAppFileUri]!.lineHits.containsValue(0), isFalse); + expect(result2[_isolateLibFileUri]!.lineHits.containsValue(0), isTrue); + + // _isolateLibFileUri is the same. _sampleAppFileUri is the same, but + // without all its missed lines. + expect(result2[_isolateLibFileUri]!.lineHits, + result[_isolateLibFileUri]!.lineHits); + result[_sampleAppFileUri]!.lineHits.removeWhere((line, hits) => hits == 0); + expect(result2[_sampleAppFileUri]!.lineHits, + result[_sampleAppFileUri]!.lineHits); + }, skip: !platformVersionCheck(3, 2)); +} + +Future<Map<String, dynamic>> _collectCoverage( + {Set<String> scopedOutput = const {}, + bool isolateIds = false, + bool functionCoverage = false, + bool branchCoverage = false, + Map<String, Set<int>>? coverableLineCache}) async { + final openPort = await getOpenPort(); + + // run the sample app, with the right flags + final sampleProcess = await runTestApp(openPort); + + final serviceUri = await serviceUriFromProcess(sampleProcess.stdoutStream()); + final isolateIdSet = isolateIds ? <String>{} : null; + + return collect(serviceUri, true, true, false, scopedOutput, + timeout: timeout, + isolateIds: isolateIdSet, + functionCoverage: functionCoverage, + branchCoverage: branchCoverage, + coverableLineCache: coverableLineCache); +}
diff --git a/pkgs/coverage/test/collect_coverage_mock_test.dart b/pkgs/coverage/test/collect_coverage_mock_test.dart new file mode 100644 index 0000000..372bd48 --- /dev/null +++ b/pkgs/coverage/test/collect_coverage_mock_test.dart
@@ -0,0 +1,416 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:coverage/coverage.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; +import 'package:test/test.dart'; +import 'package:vm_service/vm_service.dart'; + +import 'collect_coverage_mock_test.mocks.dart'; + +@GenerateMocks([VmService]) +SourceReportRange _range(int scriptIndex, SourceReportCoverage coverage) => + SourceReportRange(scriptIndex: scriptIndex, coverage: coverage); + +IsolateRef _isoRef(String id, String isoGroupId) => + IsolateRef(id: id, isolateGroupId: isoGroupId); + +IsolateGroupRef _isoGroupRef(String id) => IsolateGroupRef(id: id); + +IsolateGroup _isoGroup(String id, List<IsolateRef> isolates) => + IsolateGroup(id: id, isolates: isolates); + +class FakeSentinelException implements SentinelException { + @override + dynamic noSuchMethod(Invocation invocation) {} +} + +MockVmService _mockService( + int majorVersion, + int minorVersion, { + Map<String, List<String>> isolateGroups = const { + 'isolateGroup': ['isolate'], + }, +}) { + final service = MockVmService(); + final isoRefs = <IsolateRef>[]; + final isoGroupRefs = <IsolateGroupRef>[]; + final isoGroups = <IsolateGroup>[]; + for (final group in isolateGroups.entries) { + isoGroupRefs.add(_isoGroupRef(group.key)); + final isosOfGroup = <IsolateRef>[]; + for (final isoId in group.value) { + isosOfGroup.add(_isoRef(isoId, group.key)); + } + isoGroups.add(_isoGroup(group.key, isosOfGroup)); + isoRefs.addAll(isosOfGroup); + } + when(service.getVM()).thenAnswer( + (_) async => VM(isolates: isoRefs, isolateGroups: isoGroupRefs)); + for (final group in isoGroups) { + when(service.getIsolateGroup(group.id)).thenAnswer((_) async => group); + } + when(service.getVersion()).thenAnswer( + (_) async => Version(major: majorVersion, minor: minorVersion)); + return service; +} + +void main() { + group('Mock VM Service', () { + test('Collect coverage', () async { + final service = _mockService(4, 13); + when(service.getSourceReport( + 'isolate', + ['Coverage'], + forceCompile: true, + reportLines: true, + )).thenAnswer((_) async => SourceReport( + ranges: [ + _range( + 0, + SourceReportCoverage( + hits: [12], + misses: [47], + ), + ), + _range( + 1, + SourceReportCoverage( + hits: [95], + misses: [52], + ), + ), + ], + scripts: [ + ScriptRef( + uri: 'package:foo/foo.dart', + id: 'foo', + ), + ScriptRef( + uri: 'package:bar/bar.dart', + id: 'bar', + ), + ], + )); + + final jsonResult = await collect(Uri(), false, false, false, null, + serviceOverrideForTesting: service); + final result = await HitMap.parseJson( + jsonResult['coverage'] as List<Map<String, dynamic>>); + + expect(result.length, 2); + expect(result['package:foo/foo.dart']?.lineHits, {12: 1, 47: 0}); + expect(result['package:bar/bar.dart']?.lineHits, {95: 1, 52: 0}); + }); + + test('Collect coverage, scoped output', () async { + final service = _mockService(4, 13); + when(service.getSourceReport( + 'isolate', + ['Coverage'], + forceCompile: true, + reportLines: true, + libraryFilters: ['package:foo/'], + )).thenAnswer((_) async => SourceReport( + ranges: [ + _range( + 0, + SourceReportCoverage( + hits: [12], + misses: [47], + ), + ), + ], + scripts: [ + ScriptRef( + uri: 'package:foo/foo.dart', + id: 'foo', + ), + ], + )); + + final jsonResult = await collect(Uri(), false, false, false, {'foo'}, + serviceOverrideForTesting: service); + final result = await HitMap.parseJson( + jsonResult['coverage'] as List<Map<String, dynamic>>); + + expect(result.length, 1); + expect(result['package:foo/foo.dart']?.lineHits, {12: 1, 47: 0}); + }); + + test('Collect coverage, fast isolate group deduping', () async { + final service = _mockService(4, 13, isolateGroups: { + 'isolateGroupA': ['isolate1', 'isolate2'], + 'isolateGroupB': ['isolate3'], + }); + when(service.getSourceReport( + 'isolate1', + ['Coverage'], + forceCompile: true, + reportLines: true, + )).thenAnswer((_) async => SourceReport( + ranges: [ + _range( + 0, + SourceReportCoverage( + hits: [12], + misses: [47], + ), + ), + _range( + 1, + SourceReportCoverage( + hits: [95], + misses: [52], + ), + ), + ], + scripts: [ + ScriptRef( + uri: 'package:foo/foo.dart', + id: 'foo', + ), + ScriptRef( + uri: 'package:bar/bar.dart', + id: 'bar', + ), + ], + )); + when(service.getSourceReport( + 'isolate3', + ['Coverage'], + forceCompile: true, + reportLines: true, + )).thenAnswer((_) async => SourceReport( + ranges: [ + _range( + 0, + SourceReportCoverage( + hits: [34], + misses: [61], + ), + ), + ], + scripts: [ + ScriptRef( + uri: 'package:baz/baz.dart', + id: 'baz', + ), + ], + )); + + final jsonResult = await collect(Uri(), false, false, false, null, + serviceOverrideForTesting: service); + final result = await HitMap.parseJson( + jsonResult['coverage'] as List<Map<String, dynamic>>); + + expect(result.length, 3); + expect(result['package:foo/foo.dart']?.lineHits, {12: 1, 47: 0}); + expect(result['package:bar/bar.dart']?.lineHits, {95: 1, 52: 0}); + expect(result['package:baz/baz.dart']?.lineHits, {34: 1, 61: 0}); + verifyNever(service.getSourceReport('isolate2', ['Coverage'], + forceCompile: true, reportLines: true)); + verifyNever(service.getIsolateGroup('isolateGroupA')); + verifyNever(service.getIsolateGroup('isolateGroupB')); + }); + + test( + 'Collect coverage, no scoped output, ' + 'handles SentinelException from getSourceReport', () async { + final service = _mockService(4, 13); + when(service.getSourceReport( + 'isolate', + ['Coverage'], + forceCompile: true, + reportLines: true, + )).thenThrow(FakeSentinelException()); + + final jsonResult = await collect(Uri(), false, false, false, null, + serviceOverrideForTesting: service); + final result = await HitMap.parseJson( + jsonResult['coverage'] as List<Map<String, dynamic>>); + + expect(result.length, 0); + }); + + test('Collect coverage, coverableLineCache', () async { + // Expect that on the first getSourceReport call, librariesAlreadyCompiled + // is empty. + final service = _mockService(4, 13); + when(service.getSourceReport( + 'isolate', + ['Coverage'], + forceCompile: true, + reportLines: true, + librariesAlreadyCompiled: [], + )).thenAnswer((_) async => SourceReport( + ranges: [ + _range( + 0, + SourceReportCoverage( + hits: [12], + misses: [47], + ), + ), + _range( + 1, + SourceReportCoverage( + hits: [95], + misses: [52], + ), + ), + ], + scripts: [ + ScriptRef( + uri: 'package:foo/foo.dart', + id: 'foo', + ), + ScriptRef( + uri: 'package:bar/bar.dart', + id: 'bar', + ), + ], + )); + + final coverableLineCache = <String, Set<int>>{}; + final jsonResult = await collect(Uri(), false, false, false, null, + coverableLineCache: coverableLineCache, + serviceOverrideForTesting: service); + final result = await HitMap.parseJson( + jsonResult['coverage'] as List<Map<String, dynamic>>); + + expect(result.length, 2); + expect(result['package:foo/foo.dart']?.lineHits, {12: 1, 47: 0}); + expect(result['package:bar/bar.dart']?.lineHits, {95: 1, 52: 0}); + + // The coverableLineCache should now be filled with all the lines that + // were hit or missed. + expect(coverableLineCache, { + 'package:foo/foo.dart': {12, 47}, + 'package:bar/bar.dart': {95, 52}, + }); + + // The second getSourceReport call should now list all the libraries we've + // seen. The response won't contain any misses for these libraries, + // because they won't be force compiled. We'll also return a 3rd library, + // which will contain misses, as it hasn't been compiled yet. + when(service.getSourceReport( + 'isolate', + ['Coverage'], + forceCompile: true, + reportLines: true, + librariesAlreadyCompiled: [ + 'package:foo/foo.dart', + 'package:bar/bar.dart' + ], + )).thenAnswer((_) async => SourceReport( + ranges: [ + _range( + 0, + SourceReportCoverage( + hits: [47], + ), + ), + _range( + 1, + SourceReportCoverage( + hits: [95], + ), + ), + _range( + 2, + SourceReportCoverage( + hits: [36], + misses: [81], + ), + ), + ], + scripts: [ + ScriptRef( + uri: 'package:foo/foo.dart', + id: 'foo', + ), + ScriptRef( + uri: 'package:bar/bar.dart', + id: 'bar', + ), + ScriptRef( + uri: 'package:baz/baz.dart', + id: 'baz', + ), + ], + )); + + final jsonResult2 = await collect(Uri(), false, false, false, null, + coverableLineCache: coverableLineCache, + serviceOverrideForTesting: service); + final result2 = await HitMap.parseJson( + jsonResult2['coverage'] as List<Map<String, dynamic>>); + + // The missed lines still appear in foo and bar, even though they weren't + // returned in the response. They were read from the cache. + expect(result2.length, 3); + expect(result2['package:foo/foo.dart']?.lineHits, {12: 0, 47: 1}); + expect(result2['package:bar/bar.dart']?.lineHits, {95: 1, 52: 0}); + expect(result2['package:baz/baz.dart']?.lineHits, {36: 1, 81: 0}); + + // The coverableLineCache should now also contain the baz library. + expect(coverableLineCache, { + 'package:foo/foo.dart': {12, 47}, + 'package:bar/bar.dart': {95, 52}, + 'package:baz/baz.dart': {36, 81}, + }); + }); + + test( + 'Collect coverage, scoped output, ' + 'handles SourceReports that contain unfiltered ranges', () async { + // Regression test for https://github.com/dart-lang/tools/issues/530 + final service = _mockService(4, 13); + when(service.getSourceReport( + 'isolate', + ['Coverage'], + forceCompile: true, + reportLines: true, + libraryFilters: ['package:foo/'], + )).thenAnswer((_) async => SourceReport( + ranges: [ + _range( + 0, + SourceReportCoverage( + hits: [12], + misses: [47], + ), + ), + _range( + 1, + SourceReportCoverage( + hits: [86], + misses: [91], + ), + ), + ], + scripts: [ + ScriptRef( + uri: 'package:foo/foo.dart', + id: 'foo', + ), + ScriptRef( + uri: 'package:bar/bar.dart', + id: 'bar', + ), + ], + )); + + final jsonResult = await collect(Uri(), false, false, false, {'foo'}, + serviceOverrideForTesting: service); + final result = await HitMap.parseJson( + jsonResult['coverage'] as List<Map<String, dynamic>>); + + expect(result.length, 1); + expect(result['package:foo/foo.dart']?.lineHits, {12: 1, 47: 0}); + }); + }); +}
diff --git a/pkgs/coverage/test/collect_coverage_mock_test.mocks.dart b/pkgs/coverage/test/collect_coverage_mock_test.mocks.dart new file mode 100644 index 0000000..86f596a --- /dev/null +++ b/pkgs/coverage/test/collect_coverage_mock_test.mocks.dart
@@ -0,0 +1,2047 @@ +// Mocks generated by Mockito 5.4.4 from annotations +// in coverage/test/collect_coverage_mock_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i3; + +import 'package:mockito/mockito.dart' as _i1; +import 'package:mockito/src/dummies.dart' as _i4; +import 'package:vm_service/src/vm_service.dart' as _i2; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class + +class _FakeBreakpoint_0 extends _i1.SmartFake implements _i2.Breakpoint { + _FakeBreakpoint_0( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeSuccess_1 extends _i1.SmartFake implements _i2.Success { + _FakeSuccess_1( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeIdZone_2 extends _i1.SmartFake implements _i2.IdZone { + _FakeIdZone_2( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeResponse_3 extends _i1.SmartFake implements _i2.Response { + _FakeResponse_3( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeAllocationProfile_4 extends _i1.SmartFake + implements _i2.AllocationProfile { + _FakeAllocationProfile_4( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeCpuSamples_5 extends _i1.SmartFake implements _i2.CpuSamples { + _FakeCpuSamples_5( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeClassList_6 extends _i1.SmartFake implements _i2.ClassList { + _FakeClassList_6( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeFlagList_7 extends _i1.SmartFake implements _i2.FlagList { + _FakeFlagList_7( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeInboundReferences_8 extends _i1.SmartFake + implements _i2.InboundReferences { + _FakeInboundReferences_8( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeInstanceSet_9 extends _i1.SmartFake implements _i2.InstanceSet { + _FakeInstanceSet_9( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeInstanceRef_10 extends _i1.SmartFake implements _i2.InstanceRef { + _FakeInstanceRef_10( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeIsolate_11 extends _i1.SmartFake implements _i2.Isolate { + _FakeIsolate_11( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeIsolateGroup_12 extends _i1.SmartFake implements _i2.IsolateGroup { + _FakeIsolateGroup_12( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeEvent_13 extends _i1.SmartFake implements _i2.Event { + _FakeEvent_13( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeMemoryUsage_14 extends _i1.SmartFake implements _i2.MemoryUsage { + _FakeMemoryUsage_14( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeScriptList_15 extends _i1.SmartFake implements _i2.ScriptList { + _FakeScriptList_15( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeObj_16 extends _i1.SmartFake implements _i2.Obj { + _FakeObj_16( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakePerfettoCpuSamples_17 extends _i1.SmartFake + implements _i2.PerfettoCpuSamples { + _FakePerfettoCpuSamples_17( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakePerfettoTimeline_18 extends _i1.SmartFake + implements _i2.PerfettoTimeline { + _FakePerfettoTimeline_18( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakePortList_19 extends _i1.SmartFake implements _i2.PortList { + _FakePortList_19( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeRetainingPath_20 extends _i1.SmartFake implements _i2.RetainingPath { + _FakeRetainingPath_20( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeProcessMemoryUsage_21 extends _i1.SmartFake + implements _i2.ProcessMemoryUsage { + _FakeProcessMemoryUsage_21( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeStack_22 extends _i1.SmartFake implements _i2.Stack { + _FakeStack_22( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeProtocolList_23 extends _i1.SmartFake implements _i2.ProtocolList { + _FakeProtocolList_23( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeSourceReport_24 extends _i1.SmartFake implements _i2.SourceReport { + _FakeSourceReport_24( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeVersion_25 extends _i1.SmartFake implements _i2.Version { + _FakeVersion_25( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeVM_26 extends _i1.SmartFake implements _i2.VM { + _FakeVM_26( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeTimeline_27 extends _i1.SmartFake implements _i2.Timeline { + _FakeTimeline_27( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeTimelineFlags_28 extends _i1.SmartFake implements _i2.TimelineFlags { + _FakeTimelineFlags_28( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeTimestamp_29 extends _i1.SmartFake implements _i2.Timestamp { + _FakeTimestamp_29( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeUriList_30 extends _i1.SmartFake implements _i2.UriList { + _FakeUriList_30( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeReloadReport_31 extends _i1.SmartFake implements _i2.ReloadReport { + _FakeReloadReport_31( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeFuture_32<T1> extends _i1.SmartFake implements _i3.Future<T1> { + _FakeFuture_32( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +/// A class which mocks [VmService]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockVmService extends _i1.Mock implements _i2.VmService { + MockVmService() { + _i1.throwOnMissingStub(this); + } + + @override + _i3.Stream<String> get onSend => (super.noSuchMethod( + Invocation.getter(#onSend), + returnValue: _i3.Stream<String>.empty(), + ) as _i3.Stream<String>); + + @override + _i3.Stream<String> get onReceive => (super.noSuchMethod( + Invocation.getter(#onReceive), + returnValue: _i3.Stream<String>.empty(), + ) as _i3.Stream<String>); + + @override + _i3.Future<void> get onDone => (super.noSuchMethod( + Invocation.getter(#onDone), + returnValue: _i3.Future<void>.value(), + ) as _i3.Future<void>); + + @override + _i3.Stream<_i2.Event> get onVMEvent => (super.noSuchMethod( + Invocation.getter(#onVMEvent), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + + @override + _i3.Stream<_i2.Event> get onIsolateEvent => (super.noSuchMethod( + Invocation.getter(#onIsolateEvent), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + + @override + _i3.Stream<_i2.Event> get onDebugEvent => (super.noSuchMethod( + Invocation.getter(#onDebugEvent), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + + @override + _i3.Stream<_i2.Event> get onProfilerEvent => (super.noSuchMethod( + Invocation.getter(#onProfilerEvent), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + + @override + _i3.Stream<_i2.Event> get onGCEvent => (super.noSuchMethod( + Invocation.getter(#onGCEvent), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + + @override + _i3.Stream<_i2.Event> get onExtensionEvent => (super.noSuchMethod( + Invocation.getter(#onExtensionEvent), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + + @override + _i3.Stream<_i2.Event> get onTimelineEvent => (super.noSuchMethod( + Invocation.getter(#onTimelineEvent), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + + @override + _i3.Stream<_i2.Event> get onLoggingEvent => (super.noSuchMethod( + Invocation.getter(#onLoggingEvent), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + + @override + _i3.Stream<_i2.Event> get onServiceEvent => (super.noSuchMethod( + Invocation.getter(#onServiceEvent), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + + @override + _i3.Stream<_i2.Event> get onHeapSnapshotEvent => (super.noSuchMethod( + Invocation.getter(#onHeapSnapshotEvent), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + + @override + _i3.Stream<_i2.Event> get onStdoutEvent => (super.noSuchMethod( + Invocation.getter(#onStdoutEvent), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + + @override + _i3.Stream<_i2.Event> get onStderrEvent => (super.noSuchMethod( + Invocation.getter(#onStderrEvent), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + + @override + _i3.Stream<_i2.Event> onEvent(String? streamId) => (super.noSuchMethod( + Invocation.method( + #onEvent, + [streamId], + ), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + + @override + _i3.Future<_i2.Breakpoint> addBreakpoint( + String? isolateId, + String? scriptId, + int? line, { + int? column, + }) => + (super.noSuchMethod( + Invocation.method( + #addBreakpoint, + [ + isolateId, + scriptId, + line, + ], + {#column: column}, + ), + returnValue: _i3.Future<_i2.Breakpoint>.value(_FakeBreakpoint_0( + this, + Invocation.method( + #addBreakpoint, + [ + isolateId, + scriptId, + line, + ], + {#column: column}, + ), + )), + ) as _i3.Future<_i2.Breakpoint>); + + @override + _i3.Future<_i2.Breakpoint> addBreakpointWithScriptUri( + String? isolateId, + String? scriptUri, + int? line, { + int? column, + }) => + (super.noSuchMethod( + Invocation.method( + #addBreakpointWithScriptUri, + [ + isolateId, + scriptUri, + line, + ], + {#column: column}, + ), + returnValue: _i3.Future<_i2.Breakpoint>.value(_FakeBreakpoint_0( + this, + Invocation.method( + #addBreakpointWithScriptUri, + [ + isolateId, + scriptUri, + line, + ], + {#column: column}, + ), + )), + ) as _i3.Future<_i2.Breakpoint>); + + @override + _i3.Future<_i2.Breakpoint> addBreakpointAtEntry( + String? isolateId, + String? functionId, + ) => + (super.noSuchMethod( + Invocation.method( + #addBreakpointAtEntry, + [ + isolateId, + functionId, + ], + ), + returnValue: _i3.Future<_i2.Breakpoint>.value(_FakeBreakpoint_0( + this, + Invocation.method( + #addBreakpointAtEntry, + [ + isolateId, + functionId, + ], + ), + )), + ) as _i3.Future<_i2.Breakpoint>); + + @override + _i3.Future<_i2.Success> clearCpuSamples(String? isolateId) => + (super.noSuchMethod( + Invocation.method( + #clearCpuSamples, + [isolateId], + ), + returnValue: _i3.Future<_i2.Success>.value(_FakeSuccess_1( + this, + Invocation.method( + #clearCpuSamples, + [isolateId], + ), + )), + ) as _i3.Future<_i2.Success>); + + @override + _i3.Future<_i2.Success> clearVMTimeline() => (super.noSuchMethod( + Invocation.method( + #clearVMTimeline, + [], + ), + returnValue: _i3.Future<_i2.Success>.value(_FakeSuccess_1( + this, + Invocation.method( + #clearVMTimeline, + [], + ), + )), + ) as _i3.Future<_i2.Success>); + + @override + _i3.Future<_i2.IdZone> createIdZone( + String? isolateId, + String? backingBufferKind, + String? idAssignmentPolicy, { + int? capacity, + }) => + (super.noSuchMethod( + Invocation.method( + #createIdZone, + [ + isolateId, + backingBufferKind, + idAssignmentPolicy, + ], + {#capacity: capacity}, + ), + returnValue: _i3.Future<_i2.IdZone>.value(_FakeIdZone_2( + this, + Invocation.method( + #createIdZone, + [ + isolateId, + backingBufferKind, + idAssignmentPolicy, + ], + {#capacity: capacity}, + ), + )), + ) as _i3.Future<_i2.IdZone>); + + @override + _i3.Future<_i2.Success> deleteIdZone( + String? isolateId, + String? idZoneId, + ) => + (super.noSuchMethod( + Invocation.method( + #deleteIdZone, + [ + isolateId, + idZoneId, + ], + ), + returnValue: _i3.Future<_i2.Success>.value(_FakeSuccess_1( + this, + Invocation.method( + #deleteIdZone, + [ + isolateId, + idZoneId, + ], + ), + )), + ) as _i3.Future<_i2.Success>); + + @override + _i3.Future<_i2.Success> invalidateIdZone( + String? isolateId, + String? idZoneId, + ) => + (super.noSuchMethod( + Invocation.method( + #invalidateIdZone, + [ + isolateId, + idZoneId, + ], + ), + returnValue: _i3.Future<_i2.Success>.value(_FakeSuccess_1( + this, + Invocation.method( + #invalidateIdZone, + [ + isolateId, + idZoneId, + ], + ), + )), + ) as _i3.Future<_i2.Success>); + + @override + _i3.Future<_i2.Response> invoke( + String? isolateId, + String? targetId, + String? selector, + List<String>? argumentIds, { + bool? disableBreakpoints, + String? idZoneId, + }) => + (super.noSuchMethod( + Invocation.method( + #invoke, + [ + isolateId, + targetId, + selector, + argumentIds, + ], + { + #disableBreakpoints: disableBreakpoints, + #idZoneId: idZoneId, + }, + ), + returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_3( + this, + Invocation.method( + #invoke, + [ + isolateId, + targetId, + selector, + argumentIds, + ], + { + #disableBreakpoints: disableBreakpoints, + #idZoneId: idZoneId, + }, + ), + )), + ) as _i3.Future<_i2.Response>); + + @override + _i3.Future<_i2.Response> evaluate( + String? isolateId, + String? targetId, + String? expression, { + Map<String, String>? scope, + bool? disableBreakpoints, + String? idZoneId, + }) => + (super.noSuchMethod( + Invocation.method( + #evaluate, + [ + isolateId, + targetId, + expression, + ], + { + #scope: scope, + #disableBreakpoints: disableBreakpoints, + #idZoneId: idZoneId, + }, + ), + returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_3( + this, + Invocation.method( + #evaluate, + [ + isolateId, + targetId, + expression, + ], + { + #scope: scope, + #disableBreakpoints: disableBreakpoints, + #idZoneId: idZoneId, + }, + ), + )), + ) as _i3.Future<_i2.Response>); + + @override + _i3.Future<_i2.Response> evaluateInFrame( + String? isolateId, + int? frameIndex, + String? expression, { + Map<String, String>? scope, + bool? disableBreakpoints, + String? idZoneId, + }) => + (super.noSuchMethod( + Invocation.method( + #evaluateInFrame, + [ + isolateId, + frameIndex, + expression, + ], + { + #scope: scope, + #disableBreakpoints: disableBreakpoints, + #idZoneId: idZoneId, + }, + ), + returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_3( + this, + Invocation.method( + #evaluateInFrame, + [ + isolateId, + frameIndex, + expression, + ], + { + #scope: scope, + #disableBreakpoints: disableBreakpoints, + #idZoneId: idZoneId, + }, + ), + )), + ) as _i3.Future<_i2.Response>); + + @override + _i3.Future<_i2.AllocationProfile> getAllocationProfile( + String? isolateId, { + bool? reset, + bool? gc, + }) => + (super.noSuchMethod( + Invocation.method( + #getAllocationProfile, + [isolateId], + { + #reset: reset, + #gc: gc, + }, + ), + returnValue: + _i3.Future<_i2.AllocationProfile>.value(_FakeAllocationProfile_4( + this, + Invocation.method( + #getAllocationProfile, + [isolateId], + { + #reset: reset, + #gc: gc, + }, + ), + )), + ) as _i3.Future<_i2.AllocationProfile>); + + @override + _i3.Future<_i2.CpuSamples> getAllocationTraces( + String? isolateId, { + int? timeOriginMicros, + int? timeExtentMicros, + String? classId, + }) => + (super.noSuchMethod( + Invocation.method( + #getAllocationTraces, + [isolateId], + { + #timeOriginMicros: timeOriginMicros, + #timeExtentMicros: timeExtentMicros, + #classId: classId, + }, + ), + returnValue: _i3.Future<_i2.CpuSamples>.value(_FakeCpuSamples_5( + this, + Invocation.method( + #getAllocationTraces, + [isolateId], + { + #timeOriginMicros: timeOriginMicros, + #timeExtentMicros: timeExtentMicros, + #classId: classId, + }, + ), + )), + ) as _i3.Future<_i2.CpuSamples>); + + @override + _i3.Future<_i2.ClassList> getClassList(String? isolateId) => + (super.noSuchMethod( + Invocation.method( + #getClassList, + [isolateId], + ), + returnValue: _i3.Future<_i2.ClassList>.value(_FakeClassList_6( + this, + Invocation.method( + #getClassList, + [isolateId], + ), + )), + ) as _i3.Future<_i2.ClassList>); + + @override + _i3.Future<_i2.CpuSamples> getCpuSamples( + String? isolateId, + int? timeOriginMicros, + int? timeExtentMicros, + ) => + (super.noSuchMethod( + Invocation.method( + #getCpuSamples, + [ + isolateId, + timeOriginMicros, + timeExtentMicros, + ], + ), + returnValue: _i3.Future<_i2.CpuSamples>.value(_FakeCpuSamples_5( + this, + Invocation.method( + #getCpuSamples, + [ + isolateId, + timeOriginMicros, + timeExtentMicros, + ], + ), + )), + ) as _i3.Future<_i2.CpuSamples>); + + @override + _i3.Future<_i2.FlagList> getFlagList() => (super.noSuchMethod( + Invocation.method( + #getFlagList, + [], + ), + returnValue: _i3.Future<_i2.FlagList>.value(_FakeFlagList_7( + this, + Invocation.method( + #getFlagList, + [], + ), + )), + ) as _i3.Future<_i2.FlagList>); + + @override + _i3.Future<_i2.InboundReferences> getInboundReferences( + String? isolateId, + String? targetId, + int? limit, { + String? idZoneId, + }) => + (super.noSuchMethod( + Invocation.method( + #getInboundReferences, + [ + isolateId, + targetId, + limit, + ], + {#idZoneId: idZoneId}, + ), + returnValue: + _i3.Future<_i2.InboundReferences>.value(_FakeInboundReferences_8( + this, + Invocation.method( + #getInboundReferences, + [ + isolateId, + targetId, + limit, + ], + {#idZoneId: idZoneId}, + ), + )), + ) as _i3.Future<_i2.InboundReferences>); + + @override + _i3.Future<_i2.InstanceSet> getInstances( + String? isolateId, + String? objectId, + int? limit, { + bool? includeSubclasses, + bool? includeImplementers, + String? idZoneId, + }) => + (super.noSuchMethod( + Invocation.method( + #getInstances, + [ + isolateId, + objectId, + limit, + ], + { + #includeSubclasses: includeSubclasses, + #includeImplementers: includeImplementers, + #idZoneId: idZoneId, + }, + ), + returnValue: _i3.Future<_i2.InstanceSet>.value(_FakeInstanceSet_9( + this, + Invocation.method( + #getInstances, + [ + isolateId, + objectId, + limit, + ], + { + #includeSubclasses: includeSubclasses, + #includeImplementers: includeImplementers, + #idZoneId: idZoneId, + }, + ), + )), + ) as _i3.Future<_i2.InstanceSet>); + + @override + _i3.Future<_i2.InstanceRef> getInstancesAsList( + String? isolateId, + String? objectId, { + bool? includeSubclasses, + bool? includeImplementers, + String? idZoneId, + }) => + (super.noSuchMethod( + Invocation.method( + #getInstancesAsList, + [ + isolateId, + objectId, + ], + { + #includeSubclasses: includeSubclasses, + #includeImplementers: includeImplementers, + #idZoneId: idZoneId, + }, + ), + returnValue: _i3.Future<_i2.InstanceRef>.value(_FakeInstanceRef_10( + this, + Invocation.method( + #getInstancesAsList, + [ + isolateId, + objectId, + ], + { + #includeSubclasses: includeSubclasses, + #includeImplementers: includeImplementers, + #idZoneId: idZoneId, + }, + ), + )), + ) as _i3.Future<_i2.InstanceRef>); + + @override + _i3.Future<_i2.Isolate> getIsolate(String? isolateId) => (super.noSuchMethod( + Invocation.method( + #getIsolate, + [isolateId], + ), + returnValue: _i3.Future<_i2.Isolate>.value(_FakeIsolate_11( + this, + Invocation.method( + #getIsolate, + [isolateId], + ), + )), + ) as _i3.Future<_i2.Isolate>); + + @override + _i3.Future<_i2.IsolateGroup> getIsolateGroup(String? isolateGroupId) => + (super.noSuchMethod( + Invocation.method( + #getIsolateGroup, + [isolateGroupId], + ), + returnValue: _i3.Future<_i2.IsolateGroup>.value(_FakeIsolateGroup_12( + this, + Invocation.method( + #getIsolateGroup, + [isolateGroupId], + ), + )), + ) as _i3.Future<_i2.IsolateGroup>); + + @override + _i3.Future<_i2.Event> getIsolatePauseEvent(String? isolateId) => + (super.noSuchMethod( + Invocation.method( + #getIsolatePauseEvent, + [isolateId], + ), + returnValue: _i3.Future<_i2.Event>.value(_FakeEvent_13( + this, + Invocation.method( + #getIsolatePauseEvent, + [isolateId], + ), + )), + ) as _i3.Future<_i2.Event>); + + @override + _i3.Future<_i2.MemoryUsage> getMemoryUsage(String? isolateId) => + (super.noSuchMethod( + Invocation.method( + #getMemoryUsage, + [isolateId], + ), + returnValue: _i3.Future<_i2.MemoryUsage>.value(_FakeMemoryUsage_14( + this, + Invocation.method( + #getMemoryUsage, + [isolateId], + ), + )), + ) as _i3.Future<_i2.MemoryUsage>); + + @override + _i3.Future<_i2.MemoryUsage> getIsolateGroupMemoryUsage( + String? isolateGroupId) => + (super.noSuchMethod( + Invocation.method( + #getIsolateGroupMemoryUsage, + [isolateGroupId], + ), + returnValue: _i3.Future<_i2.MemoryUsage>.value(_FakeMemoryUsage_14( + this, + Invocation.method( + #getIsolateGroupMemoryUsage, + [isolateGroupId], + ), + )), + ) as _i3.Future<_i2.MemoryUsage>); + + @override + _i3.Future<_i2.ScriptList> getScripts(String? isolateId) => + (super.noSuchMethod( + Invocation.method( + #getScripts, + [isolateId], + ), + returnValue: _i3.Future<_i2.ScriptList>.value(_FakeScriptList_15( + this, + Invocation.method( + #getScripts, + [isolateId], + ), + )), + ) as _i3.Future<_i2.ScriptList>); + + @override + _i3.Future<_i2.Obj> getObject( + String? isolateId, + String? objectId, { + int? offset, + int? count, + String? idZoneId, + }) => + (super.noSuchMethod( + Invocation.method( + #getObject, + [ + isolateId, + objectId, + ], + { + #offset: offset, + #count: count, + #idZoneId: idZoneId, + }, + ), + returnValue: _i3.Future<_i2.Obj>.value(_FakeObj_16( + this, + Invocation.method( + #getObject, + [ + isolateId, + objectId, + ], + { + #offset: offset, + #count: count, + #idZoneId: idZoneId, + }, + ), + )), + ) as _i3.Future<_i2.Obj>); + + @override + _i3.Future<_i2.PerfettoCpuSamples> getPerfettoCpuSamples( + String? isolateId, { + int? timeOriginMicros, + int? timeExtentMicros, + }) => + (super.noSuchMethod( + Invocation.method( + #getPerfettoCpuSamples, + [isolateId], + { + #timeOriginMicros: timeOriginMicros, + #timeExtentMicros: timeExtentMicros, + }, + ), + returnValue: + _i3.Future<_i2.PerfettoCpuSamples>.value(_FakePerfettoCpuSamples_17( + this, + Invocation.method( + #getPerfettoCpuSamples, + [isolateId], + { + #timeOriginMicros: timeOriginMicros, + #timeExtentMicros: timeExtentMicros, + }, + ), + )), + ) as _i3.Future<_i2.PerfettoCpuSamples>); + + @override + _i3.Future<_i2.PerfettoTimeline> getPerfettoVMTimeline({ + int? timeOriginMicros, + int? timeExtentMicros, + }) => + (super.noSuchMethod( + Invocation.method( + #getPerfettoVMTimeline, + [], + { + #timeOriginMicros: timeOriginMicros, + #timeExtentMicros: timeExtentMicros, + }, + ), + returnValue: + _i3.Future<_i2.PerfettoTimeline>.value(_FakePerfettoTimeline_18( + this, + Invocation.method( + #getPerfettoVMTimeline, + [], + { + #timeOriginMicros: timeOriginMicros, + #timeExtentMicros: timeExtentMicros, + }, + ), + )), + ) as _i3.Future<_i2.PerfettoTimeline>); + + @override + _i3.Future<_i2.PortList> getPorts(String? isolateId) => (super.noSuchMethod( + Invocation.method( + #getPorts, + [isolateId], + ), + returnValue: _i3.Future<_i2.PortList>.value(_FakePortList_19( + this, + Invocation.method( + #getPorts, + [isolateId], + ), + )), + ) as _i3.Future<_i2.PortList>); + + @override + _i3.Future<_i2.RetainingPath> getRetainingPath( + String? isolateId, + String? targetId, + int? limit, { + String? idZoneId, + }) => + (super.noSuchMethod( + Invocation.method( + #getRetainingPath, + [ + isolateId, + targetId, + limit, + ], + {#idZoneId: idZoneId}, + ), + returnValue: _i3.Future<_i2.RetainingPath>.value(_FakeRetainingPath_20( + this, + Invocation.method( + #getRetainingPath, + [ + isolateId, + targetId, + limit, + ], + {#idZoneId: idZoneId}, + ), + )), + ) as _i3.Future<_i2.RetainingPath>); + + @override + _i3.Future<_i2.ProcessMemoryUsage> getProcessMemoryUsage() => + (super.noSuchMethod( + Invocation.method( + #getProcessMemoryUsage, + [], + ), + returnValue: + _i3.Future<_i2.ProcessMemoryUsage>.value(_FakeProcessMemoryUsage_21( + this, + Invocation.method( + #getProcessMemoryUsage, + [], + ), + )), + ) as _i3.Future<_i2.ProcessMemoryUsage>); + + @override + _i3.Future<_i2.Stack> getStack( + String? isolateId, { + int? limit, + String? idZoneId, + }) => + (super.noSuchMethod( + Invocation.method( + #getStack, + [isolateId], + { + #limit: limit, + #idZoneId: idZoneId, + }, + ), + returnValue: _i3.Future<_i2.Stack>.value(_FakeStack_22( + this, + Invocation.method( + #getStack, + [isolateId], + { + #limit: limit, + #idZoneId: idZoneId, + }, + ), + )), + ) as _i3.Future<_i2.Stack>); + + @override + _i3.Future<_i2.ProtocolList> getSupportedProtocols() => (super.noSuchMethod( + Invocation.method( + #getSupportedProtocols, + [], + ), + returnValue: _i3.Future<_i2.ProtocolList>.value(_FakeProtocolList_23( + this, + Invocation.method( + #getSupportedProtocols, + [], + ), + )), + ) as _i3.Future<_i2.ProtocolList>); + + @override + _i3.Future<_i2.SourceReport> getSourceReport( + String? isolateId, + List<String>? reports, { + String? scriptId, + int? tokenPos, + int? endTokenPos, + bool? forceCompile, + bool? reportLines, + List<String>? libraryFilters, + List<String>? librariesAlreadyCompiled, + }) => + (super.noSuchMethod( + Invocation.method( + #getSourceReport, + [ + isolateId, + reports, + ], + { + #scriptId: scriptId, + #tokenPos: tokenPos, + #endTokenPos: endTokenPos, + #forceCompile: forceCompile, + #reportLines: reportLines, + #libraryFilters: libraryFilters, + #librariesAlreadyCompiled: librariesAlreadyCompiled, + }, + ), + returnValue: _i3.Future<_i2.SourceReport>.value(_FakeSourceReport_24( + this, + Invocation.method( + #getSourceReport, + [ + isolateId, + reports, + ], + { + #scriptId: scriptId, + #tokenPos: tokenPos, + #endTokenPos: endTokenPos, + #forceCompile: forceCompile, + #reportLines: reportLines, + #libraryFilters: libraryFilters, + #librariesAlreadyCompiled: librariesAlreadyCompiled, + }, + ), + )), + ) as _i3.Future<_i2.SourceReport>); + + @override + _i3.Future<_i2.Version> getVersion() => (super.noSuchMethod( + Invocation.method( + #getVersion, + [], + ), + returnValue: _i3.Future<_i2.Version>.value(_FakeVersion_25( + this, + Invocation.method( + #getVersion, + [], + ), + )), + ) as _i3.Future<_i2.Version>); + + @override + _i3.Future<_i2.VM> getVM() => (super.noSuchMethod( + Invocation.method( + #getVM, + [], + ), + returnValue: _i3.Future<_i2.VM>.value(_FakeVM_26( + this, + Invocation.method( + #getVM, + [], + ), + )), + ) as _i3.Future<_i2.VM>); + + @override + _i3.Future<_i2.Timeline> getVMTimeline({ + int? timeOriginMicros, + int? timeExtentMicros, + }) => + (super.noSuchMethod( + Invocation.method( + #getVMTimeline, + [], + { + #timeOriginMicros: timeOriginMicros, + #timeExtentMicros: timeExtentMicros, + }, + ), + returnValue: _i3.Future<_i2.Timeline>.value(_FakeTimeline_27( + this, + Invocation.method( + #getVMTimeline, + [], + { + #timeOriginMicros: timeOriginMicros, + #timeExtentMicros: timeExtentMicros, + }, + ), + )), + ) as _i3.Future<_i2.Timeline>); + + @override + _i3.Future<_i2.TimelineFlags> getVMTimelineFlags() => (super.noSuchMethod( + Invocation.method( + #getVMTimelineFlags, + [], + ), + returnValue: _i3.Future<_i2.TimelineFlags>.value(_FakeTimelineFlags_28( + this, + Invocation.method( + #getVMTimelineFlags, + [], + ), + )), + ) as _i3.Future<_i2.TimelineFlags>); + + @override + _i3.Future<_i2.Timestamp> getVMTimelineMicros() => (super.noSuchMethod( + Invocation.method( + #getVMTimelineMicros, + [], + ), + returnValue: _i3.Future<_i2.Timestamp>.value(_FakeTimestamp_29( + this, + Invocation.method( + #getVMTimelineMicros, + [], + ), + )), + ) as _i3.Future<_i2.Timestamp>); + + @override + _i3.Future<_i2.Success> pause(String? isolateId) => (super.noSuchMethod( + Invocation.method( + #pause, + [isolateId], + ), + returnValue: _i3.Future<_i2.Success>.value(_FakeSuccess_1( + this, + Invocation.method( + #pause, + [isolateId], + ), + )), + ) as _i3.Future<_i2.Success>); + + @override + _i3.Future<_i2.Success> kill(String? isolateId) => (super.noSuchMethod( + Invocation.method( + #kill, + [isolateId], + ), + returnValue: _i3.Future<_i2.Success>.value(_FakeSuccess_1( + this, + Invocation.method( + #kill, + [isolateId], + ), + )), + ) as _i3.Future<_i2.Success>); + + @override + _i3.Future<_i2.UriList> lookupResolvedPackageUris( + String? isolateId, + List<String>? uris, { + bool? local, + }) => + (super.noSuchMethod( + Invocation.method( + #lookupResolvedPackageUris, + [ + isolateId, + uris, + ], + {#local: local}, + ), + returnValue: _i3.Future<_i2.UriList>.value(_FakeUriList_30( + this, + Invocation.method( + #lookupResolvedPackageUris, + [ + isolateId, + uris, + ], + {#local: local}, + ), + )), + ) as _i3.Future<_i2.UriList>); + + @override + _i3.Future<_i2.UriList> lookupPackageUris( + String? isolateId, + List<String>? uris, + ) => + (super.noSuchMethod( + Invocation.method( + #lookupPackageUris, + [ + isolateId, + uris, + ], + ), + returnValue: _i3.Future<_i2.UriList>.value(_FakeUriList_30( + this, + Invocation.method( + #lookupPackageUris, + [ + isolateId, + uris, + ], + ), + )), + ) as _i3.Future<_i2.UriList>); + + @override + _i3.Future<_i2.Success> registerService( + String? service, + String? alias, + ) => + (super.noSuchMethod( + Invocation.method( + #registerService, + [ + service, + alias, + ], + ), + returnValue: _i3.Future<_i2.Success>.value(_FakeSuccess_1( + this, + Invocation.method( + #registerService, + [ + service, + alias, + ], + ), + )), + ) as _i3.Future<_i2.Success>); + + @override + _i3.Future<_i2.ReloadReport> reloadSources( + String? isolateId, { + bool? force, + bool? pause, + String? rootLibUri, + String? packagesUri, + }) => + (super.noSuchMethod( + Invocation.method( + #reloadSources, + [isolateId], + { + #force: force, + #pause: pause, + #rootLibUri: rootLibUri, + #packagesUri: packagesUri, + }, + ), + returnValue: _i3.Future<_i2.ReloadReport>.value(_FakeReloadReport_31( + this, + Invocation.method( + #reloadSources, + [isolateId], + { + #force: force, + #pause: pause, + #rootLibUri: rootLibUri, + #packagesUri: packagesUri, + }, + ), + )), + ) as _i3.Future<_i2.ReloadReport>); + + @override + _i3.Future<_i2.Success> removeBreakpoint( + String? isolateId, + String? breakpointId, + ) => + (super.noSuchMethod( + Invocation.method( + #removeBreakpoint, + [ + isolateId, + breakpointId, + ], + ), + returnValue: _i3.Future<_i2.Success>.value(_FakeSuccess_1( + this, + Invocation.method( + #removeBreakpoint, + [ + isolateId, + breakpointId, + ], + ), + )), + ) as _i3.Future<_i2.Success>); + + @override + _i3.Future<_i2.Success> requestHeapSnapshot(String? isolateId) => + (super.noSuchMethod( + Invocation.method( + #requestHeapSnapshot, + [isolateId], + ), + returnValue: _i3.Future<_i2.Success>.value(_FakeSuccess_1( + this, + Invocation.method( + #requestHeapSnapshot, + [isolateId], + ), + )), + ) as _i3.Future<_i2.Success>); + + @override + _i3.Future<_i2.Success> resume( + String? isolateId, { + String? step, + int? frameIndex, + }) => + (super.noSuchMethod( + Invocation.method( + #resume, + [isolateId], + { + #step: step, + #frameIndex: frameIndex, + }, + ), + returnValue: _i3.Future<_i2.Success>.value(_FakeSuccess_1( + this, + Invocation.method( + #resume, + [isolateId], + { + #step: step, + #frameIndex: frameIndex, + }, + ), + )), + ) as _i3.Future<_i2.Success>); + + @override + _i3.Future<_i2.Breakpoint> setBreakpointState( + String? isolateId, + String? breakpointId, + bool? enable, + ) => + (super.noSuchMethod( + Invocation.method( + #setBreakpointState, + [ + isolateId, + breakpointId, + enable, + ], + ), + returnValue: _i3.Future<_i2.Breakpoint>.value(_FakeBreakpoint_0( + this, + Invocation.method( + #setBreakpointState, + [ + isolateId, + breakpointId, + enable, + ], + ), + )), + ) as _i3.Future<_i2.Breakpoint>); + + @override + _i3.Future<_i2.Success> setExceptionPauseMode( + String? isolateId, + String? mode, + ) => + (super.noSuchMethod( + Invocation.method( + #setExceptionPauseMode, + [ + isolateId, + mode, + ], + ), + returnValue: _i3.Future<_i2.Success>.value(_FakeSuccess_1( + this, + Invocation.method( + #setExceptionPauseMode, + [ + isolateId, + mode, + ], + ), + )), + ) as _i3.Future<_i2.Success>); + + @override + _i3.Future<_i2.Success> setIsolatePauseMode( + String? isolateId, { + String? exceptionPauseMode, + bool? shouldPauseOnExit, + }) => + (super.noSuchMethod( + Invocation.method( + #setIsolatePauseMode, + [isolateId], + { + #exceptionPauseMode: exceptionPauseMode, + #shouldPauseOnExit: shouldPauseOnExit, + }, + ), + returnValue: _i3.Future<_i2.Success>.value(_FakeSuccess_1( + this, + Invocation.method( + #setIsolatePauseMode, + [isolateId], + { + #exceptionPauseMode: exceptionPauseMode, + #shouldPauseOnExit: shouldPauseOnExit, + }, + ), + )), + ) as _i3.Future<_i2.Success>); + + @override + _i3.Future<_i2.Response> setFlag( + String? name, + String? value, + ) => + (super.noSuchMethod( + Invocation.method( + #setFlag, + [ + name, + value, + ], + ), + returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_3( + this, + Invocation.method( + #setFlag, + [ + name, + value, + ], + ), + )), + ) as _i3.Future<_i2.Response>); + + @override + _i3.Future<_i2.Success> setLibraryDebuggable( + String? isolateId, + String? libraryId, + bool? isDebuggable, + ) => + (super.noSuchMethod( + Invocation.method( + #setLibraryDebuggable, + [ + isolateId, + libraryId, + isDebuggable, + ], + ), + returnValue: _i3.Future<_i2.Success>.value(_FakeSuccess_1( + this, + Invocation.method( + #setLibraryDebuggable, + [ + isolateId, + libraryId, + isDebuggable, + ], + ), + )), + ) as _i3.Future<_i2.Success>); + + @override + _i3.Future<_i2.Success> setName( + String? isolateId, + String? name, + ) => + (super.noSuchMethod( + Invocation.method( + #setName, + [ + isolateId, + name, + ], + ), + returnValue: _i3.Future<_i2.Success>.value(_FakeSuccess_1( + this, + Invocation.method( + #setName, + [ + isolateId, + name, + ], + ), + )), + ) as _i3.Future<_i2.Success>); + + @override + _i3.Future<_i2.Success> setTraceClassAllocation( + String? isolateId, + String? classId, + bool? enable, + ) => + (super.noSuchMethod( + Invocation.method( + #setTraceClassAllocation, + [ + isolateId, + classId, + enable, + ], + ), + returnValue: _i3.Future<_i2.Success>.value(_FakeSuccess_1( + this, + Invocation.method( + #setTraceClassAllocation, + [ + isolateId, + classId, + enable, + ], + ), + )), + ) as _i3.Future<_i2.Success>); + + @override + _i3.Future<_i2.Success> setVMName(String? name) => (super.noSuchMethod( + Invocation.method( + #setVMName, + [name], + ), + returnValue: _i3.Future<_i2.Success>.value(_FakeSuccess_1( + this, + Invocation.method( + #setVMName, + [name], + ), + )), + ) as _i3.Future<_i2.Success>); + + @override + _i3.Future<_i2.Success> setVMTimelineFlags(List<String>? recordedStreams) => + (super.noSuchMethod( + Invocation.method( + #setVMTimelineFlags, + [recordedStreams], + ), + returnValue: _i3.Future<_i2.Success>.value(_FakeSuccess_1( + this, + Invocation.method( + #setVMTimelineFlags, + [recordedStreams], + ), + )), + ) as _i3.Future<_i2.Success>); + + @override + _i3.Future<_i2.Success> streamCancel(String? streamId) => (super.noSuchMethod( + Invocation.method( + #streamCancel, + [streamId], + ), + returnValue: _i3.Future<_i2.Success>.value(_FakeSuccess_1( + this, + Invocation.method( + #streamCancel, + [streamId], + ), + )), + ) as _i3.Future<_i2.Success>); + + @override + _i3.Future<_i2.Success> streamCpuSamplesWithUserTag(List<String>? userTags) => + (super.noSuchMethod( + Invocation.method( + #streamCpuSamplesWithUserTag, + [userTags], + ), + returnValue: _i3.Future<_i2.Success>.value(_FakeSuccess_1( + this, + Invocation.method( + #streamCpuSamplesWithUserTag, + [userTags], + ), + )), + ) as _i3.Future<_i2.Success>); + + @override + _i3.Future<_i2.Success> streamListen(String? streamId) => (super.noSuchMethod( + Invocation.method( + #streamListen, + [streamId], + ), + returnValue: _i3.Future<_i2.Success>.value(_FakeSuccess_1( + this, + Invocation.method( + #streamListen, + [streamId], + ), + )), + ) as _i3.Future<_i2.Success>); + + @override + _i3.Future<_i2.Response> callMethod( + String? method, { + String? isolateId, + Map<String, dynamic>? args, + }) => + (super.noSuchMethod( + Invocation.method( + #callMethod, + [method], + { + #isolateId: isolateId, + #args: args, + }, + ), + returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_3( + this, + Invocation.method( + #callMethod, + [method], + { + #isolateId: isolateId, + #args: args, + }, + ), + )), + ) as _i3.Future<_i2.Response>); + + @override + _i3.Future<_i2.Response> callServiceExtension( + String? method, { + String? isolateId, + Map<String, dynamic>? args, + }) => + (super.noSuchMethod( + Invocation.method( + #callServiceExtension, + [method], + { + #isolateId: isolateId, + #args: args, + }, + ), + returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_3( + this, + Invocation.method( + #callServiceExtension, + [method], + { + #isolateId: isolateId, + #args: args, + }, + ), + )), + ) as _i3.Future<_i2.Response>); + + @override + _i3.Future<void> dispose() => (super.noSuchMethod( + Invocation.method( + #dispose, + [], + ), + returnValue: _i3.Future<void>.value(), + returnValueForMissingStub: _i3.Future<void>.value(), + ) as _i3.Future<void>); + + @override + _i3.Future<T> wrapFuture<T>( + String? name, + _i3.Future<T>? future, + ) => + (super.noSuchMethod( + Invocation.method( + #wrapFuture, + [ + name, + future, + ], + ), + returnValue: _i4.ifNotNull( + _i4.dummyValueOrNull<T>( + this, + Invocation.method( + #wrapFuture, + [ + name, + future, + ], + ), + ), + (T v) => _i3.Future<T>.value(v), + ) ?? + _FakeFuture_32<T>( + this, + Invocation.method( + #wrapFuture, + [ + name, + future, + ], + ), + ), + ) as _i3.Future<T>); + + @override + void registerServiceCallback( + String? service, + _i2.ServiceCallback? cb, + ) => + super.noSuchMethod( + Invocation.method( + #registerServiceCallback, + [ + service, + cb, + ], + ), + returnValueForMissingStub: null, + ); +}
diff --git a/pkgs/coverage/test/collect_coverage_test.dart b/pkgs/coverage/test/collect_coverage_test.dart new file mode 100644 index 0000000..7262757 --- /dev/null +++ b/pkgs/coverage/test/collect_coverage_test.dart
@@ -0,0 +1,325 @@ +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +@Retry(3) +library; + +import 'dart:async'; +import 'dart:convert' show json; +import 'dart:io'; + +import 'package:coverage/coverage.dart'; +import 'package:coverage/src/util.dart'; +import 'package:path/path.dart' as p; +import 'package:test/test.dart'; +import 'package:test_process/test_process.dart'; + +import 'test_util.dart'; + +final _isolateLibPath = p.join('test', 'test_files', 'test_app_isolate.dart'); +final _collectAppPath = p.join('bin', 'collect_coverage.dart'); + +final _sampleAppFileUri = p.toUri(p.absolute(testAppPath)).toString(); +final _isolateLibFileUri = p.toUri(p.absolute(_isolateLibPath)).toString(); + +void main() { + test('collect_coverage', () async { + final resultString = await _getCoverageResult(); + + // analyze the output json + final coverage = + coverageDataFromJson(json.decode(resultString) as Map<String, dynamic>); + + expect(coverage, isNotEmpty); + + final sources = coverage.sources(); + + for (var sampleCoverageData in sources[_sampleAppFileUri]!) { + expect(sampleCoverageData['hits'], isNotNull); + } + + for (var sampleCoverageData in sources[_isolateLibFileUri]!) { + expect(sampleCoverageData['hits'], isNotEmpty); + } + }); + + test('createHitmap returns a sorted hitmap', () async { + final coverage = [ + { + 'source': 'foo', + 'script': '{type: @Script, fixedId: true, ' + 'id: bar.dart, uri: bar.dart, _kind: library}', + 'hits': [ + 45, + 1, + 46, + 1, + 49, + 0, + 50, + 0, + 15, + 1, + 16, + 2, + 17, + 2, + ] + } + ]; + // ignore: deprecated_member_use_from_same_package + final hitMap = await createHitmap( + coverage.cast<Map<String, dynamic>>(), + ); + final expectedHits = {15: 1, 16: 2, 17: 2, 45: 1, 46: 1, 49: 0, 50: 0}; + expect(hitMap['foo'], expectedHits); + }); + + test('HitMap.parseJson returns a sorted hitmap', () async { + final coverage = [ + { + 'source': 'foo', + 'script': '{type: @Script, fixedId: true, ' + 'id: bar.dart, uri: bar.dart, _kind: library}', + 'hits': [ + 45, + 1, + 46, + 1, + 49, + 0, + 50, + 0, + 15, + 1, + 16, + 2, + 17, + 2, + ] + } + ]; + final hitMap = await HitMap.parseJson( + coverage.cast<Map<String, dynamic>>(), + ); + final expectedHits = {15: 1, 16: 2, 17: 2, 45: 1, 46: 1, 49: 0, 50: 0}; + expect(hitMap['foo']?.lineHits, expectedHits); + }); + + test('HitMap.parseJson', () async { + final resultString = await _collectCoverage(true, true); + final jsonResult = json.decode(resultString) as Map<String, dynamic>; + final coverage = jsonResult['coverage'] as List; + final hitMap = await HitMap.parseJson( + coverage.cast<Map<String, dynamic>>(), + ); + expect(hitMap, contains(_sampleAppFileUri)); + + final isolateFile = hitMap[_isolateLibFileUri]; + final expectedHits = { + 11: 1, + 12: 1, + 13: 1, + 15: 0, + 19: 1, + 23: 1, + 24: 2, + 28: 1, + 29: 1, + 30: 1, + 32: 0, + 38: 1, + 39: 1, + 41: 1, + 42: 4, + 43: 1, + 44: 3, + 45: 1, + 48: 1, + 49: 1, + 51: 1, + 54: 1, + 55: 1, + 56: 1, + 59: 1, + 60: 1, + 62: 1, + 63: 1, + 64: 1, + 66: 1, + 67: 1, + 68: 1, + 71: 3, + }; + expect(isolateFile?.lineHits, expectedHits); + expect(isolateFile?.funcHits, {11: 1, 19: 1, 23: 1, 28: 1, 38: 1}); + expect(isolateFile?.funcNames, { + 11: 'fooSync', + 19: 'BarClass.BarClass', + 23: 'BarClass.baz', + 28: 'fooAsync', + 38: 'isolateTask' + }); + expect( + isolateFile?.branchHits, + { + 11: 1, + 12: 1, + 15: 0, + 19: 1, + 23: 1, + 28: 1, + 29: 1, + 32: 0, + 38: 1, + 42: 1, + 71: 1, + }, + ); + }); + + test('parseCoverage', () async { + final tempDir = await Directory.systemTemp.createTemp('coverage.test.'); + + try { + final outputFile = File(p.join(tempDir.path, 'coverage.json')); + + final coverageResults = await _getCoverageResult(); + await outputFile.writeAsString(coverageResults, flush: true); + + // ignore: deprecated_member_use_from_same_package + final parsedResult = await parseCoverage([outputFile], 1); + + expect(parsedResult, contains(_sampleAppFileUri)); + expect(parsedResult, contains(_isolateLibFileUri)); + } finally { + await tempDir.delete(recursive: true); + } + }); + + test('HitMap.parseFiles', () async { + final tempDir = await Directory.systemTemp.createTemp('coverage.test.'); + + try { + final outputFile = File(p.join(tempDir.path, 'coverage.json')); + + final coverageResults = await _getCoverageResult(); + await outputFile.writeAsString(coverageResults, flush: true); + + final parsedResult = await HitMap.parseFiles([outputFile]); + + expect(parsedResult, contains(_sampleAppFileUri)); + expect(parsedResult, contains(_isolateLibFileUri)); + } finally { + await tempDir.delete(recursive: true); + } + }); + + test('HitMap.parseFiles with packagesPath and checkIgnoredLines', () async { + final tempDir = await Directory.systemTemp.createTemp('coverage.test.'); + + try { + final outputFile = File(p.join(tempDir.path, 'coverage.json')); + + final coverageResults = await _getCoverageResult(); + await outputFile.writeAsString(coverageResults, flush: true); + + final parsedResult = await HitMap.parseFiles([outputFile], + packagePath: '.', checkIgnoredLines: true); + + // This file has ignore:coverage-file. + expect(parsedResult, isNot(contains(_sampleAppFileUri))); + expect(parsedResult, contains(_isolateLibFileUri)); + } finally { + await tempDir.delete(recursive: true); + } + }); + + test('mergeHitmaps', () { + final resultMap = <String, Map<int, int>>{ + 'foo.dart': {10: 2, 20: 0}, + 'bar.dart': {10: 3, 20: 1, 30: 0}, + }; + final newMap = <String, Map<int, int>>{ + 'bar.dart': {10: 2, 20: 0, 40: 3}, + 'baz.dart': {10: 1, 20: 0, 30: 1}, + }; + // ignore: deprecated_member_use_from_same_package + mergeHitmaps(newMap, resultMap); + expect(resultMap, <String, Map<int, int>>{ + 'foo.dart': {10: 2, 20: 0}, + 'bar.dart': {10: 5, 20: 1, 30: 0, 40: 3}, + 'baz.dart': {10: 1, 20: 0, 30: 1}, + }); + }); + + test('FileHitMaps.merge', () { + final resultMap = <String, HitMap>{ + 'foo.dart': + HitMap({10: 2, 20: 0}, {15: 0, 25: 1}, {15: 'bobble', 25: 'cobble'}), + 'bar.dart': HitMap( + {10: 3, 20: 1, 30: 0}, {15: 5, 25: 0}, {15: 'gobble', 25: 'wobble'}), + }; + final newMap = <String, HitMap>{ + 'bar.dart': HitMap( + {10: 2, 20: 0, 40: 3}, {15: 1, 35: 4}, {15: 'gobble', 35: 'dobble'}), + 'baz.dart': HitMap( + {10: 1, 20: 0, 30: 1}, {15: 0, 25: 2}, {15: 'lobble', 25: 'zobble'}), + }; + resultMap.merge(newMap); + expect(resultMap['foo.dart']?.lineHits, <int, int>{10: 2, 20: 0}); + expect(resultMap['foo.dart']?.funcHits, <int, int>{15: 0, 25: 1}); + expect(resultMap['foo.dart']?.funcNames, + <int, String>{15: 'bobble', 25: 'cobble'}); + expect(resultMap['bar.dart']?.lineHits, + <int, int>{10: 5, 20: 1, 30: 0, 40: 3}); + expect(resultMap['bar.dart']?.funcHits, <int, int>{15: 6, 25: 0, 35: 4}); + expect(resultMap['bar.dart']?.funcNames, + <int, String>{15: 'gobble', 25: 'wobble', 35: 'dobble'}); + expect(resultMap['baz.dart']?.lineHits, <int, int>{10: 1, 20: 0, 30: 1}); + expect(resultMap['baz.dart']?.funcHits, <int, int>{15: 0, 25: 2}); + expect(resultMap['baz.dart']?.funcNames, + <int, String>{15: 'lobble', 25: 'zobble'}); + }); +} + +String? _coverageData; + +Future<String> _getCoverageResult() async => + _coverageData ??= await _collectCoverage(false, false); + +Future<String> _collectCoverage( + bool functionCoverage, bool branchCoverage) async { + expect(FileSystemEntity.isFileSync(testAppPath), isTrue); + + final openPort = await getOpenPort(); + + // Run the sample app with the right flags. + final sampleProcess = await runTestApp(openPort); + + // Capture the VM service URI. + final serviceUri = await serviceUriFromProcess(sampleProcess.stdoutStream()); + + // Run the collection tool. + // TODO: need to get all of this functionality in the lib + final toolResult = await TestProcess.start(Platform.resolvedExecutable, [ + _collectAppPath, + if (functionCoverage) '--function-coverage', + if (branchCoverage) '--branch-coverage', + '--uri', + '$serviceUri', + '--resume-isolates', + '--wait-paused' + ]); + + await toolResult.shouldExit(0).timeout( + timeout, + onTimeout: () => + throw StateError('We timed out waiting for the tool to finish.'), + ); + + await sampleProcess.shouldExit(); + + return toolResult.stdoutStream().join('\n'); +}
diff --git a/pkgs/coverage/test/format_coverage_test.dart b/pkgs/coverage/test/format_coverage_test.dart new file mode 100644 index 0000000..85493f7 --- /dev/null +++ b/pkgs/coverage/test/format_coverage_test.dart
@@ -0,0 +1,37 @@ +// 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:io'; + +import 'package:path/path.dart' as p; +import 'package:test/test.dart'; + +import '../bin/format_coverage.dart'; + +void main() { + late Directory testDir; + setUp(() { + testDir = Directory.systemTemp.createTempSync('coverage_test_temp'); + }); + + tearDown(() async { + if (testDir.existsSync()) testDir.deleteSync(recursive: true); + }); + + test('considers all json files', () async { + final fileA = File(p.join(testDir.path, 'coverage_a.json')); + fileA.createSync(); + final fileB = File(p.join(testDir.path, 'coverage_b.json')); + fileB.createSync(); + final fileC = File(p.join(testDir.path, 'not_coverage.foo')); + fileC.createSync(); + + final files = filesToProcess(testDir.path); + expect(files.length, equals(2)); + expect( + files.map((f) => f.path), + containsAll( + [endsWith('coverage_a.json'), endsWith('coverage_b.json')])); + }); +}
diff --git a/pkgs/coverage/test/function_coverage_test.dart b/pkgs/coverage/test/function_coverage_test.dart new file mode 100644 index 0000000..965d0d0 --- /dev/null +++ b/pkgs/coverage/test/function_coverage_test.dart
@@ -0,0 +1,107 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:convert' show json; +import 'dart:io'; + +import 'package:coverage/coverage.dart'; +import 'package:coverage/src/util.dart'; +import 'package:path/path.dart' as p; +import 'package:test/test.dart'; +import 'package:test_process/test_process.dart'; + +import 'test_util.dart'; + +final _collectAppPath = p.join('bin', 'collect_coverage.dart'); +final _funcCovApp = p.join('test', 'test_files', 'function_coverage_app.dart'); +final _sampleAppFileUri = p.toUri(p.absolute(_funcCovApp)).toString(); + +void main() { + test('Function coverage', () async { + final resultString = await _collectCoverage(); + final jsonResult = json.decode(resultString) as Map<String, dynamic>; + final coverage = jsonResult['coverage'] as List; + final hitMap = await HitMap.parseJson( + coverage.cast<Map<String, dynamic>>(), + ); + + // function_coverage_app.dart. + expect(hitMap, contains(_sampleAppFileUri)); + final isolateFile = hitMap[_sampleAppFileUri]!; + expect(isolateFile.funcHits, { + 7: 1, + 16: 1, + 21: 1, + 25: 1, + 29: 1, + 36: 1, + 42: 1, + 47: 1, + }); + expect(isolateFile.funcNames, { + 7: 'normalFunction', + 16: 'SomeClass.SomeClass', + 21: 'SomeClass.normalMethod', + 25: 'SomeClass.staticMethod', + 29: 'SomeClass.abstractMethod', + 36: 'SomeExtension.extensionMethod', + 42: 'OtherClass.otherMethod', + 47: 'main', + }); + + // test_library.dart. + final testLibraryPath = + p.absolute(p.join('test', 'test_files', 'test_library.dart')); + final testLibraryUri = p.toUri(testLibraryPath).toString(); + expect(hitMap, contains(testLibraryUri)); + final libraryfile = hitMap[testLibraryUri]!; + expect(libraryfile.funcHits, {7: 1}); + expect(libraryfile.funcNames, {7: 'libraryFunction'}); + + // test_library_part.dart. + final testLibraryPartPath = + p.absolute(p.join('test', 'test_files', 'test_library_part.dart')); + final testLibraryPartUri = p.toUri(testLibraryPartPath).toString(); + expect(hitMap, contains(testLibraryPartUri)); + final libraryPartFile = hitMap[testLibraryPartUri]!; + expect(libraryPartFile.funcHits, {7: 1}); + expect(libraryPartFile.funcNames, {7: 'otherLibraryFunction'}); + }); +} + +Future<String> _collectCoverage() async { + expect(FileSystemEntity.isFileSync(_funcCovApp), isTrue); + + final openPort = await getOpenPort(); + + // Run the sample app with the right flags. + final sampleProcess = await TestProcess.start(Platform.resolvedExecutable, [ + '--enable-vm-service=$openPort', + '--pause_isolates_on_exit', + _funcCovApp + ]); + + final serviceUri = await serviceUriFromProcess(sampleProcess.stdoutStream()); + + // Run the collection tool. + final toolResult = await TestProcess.start(Platform.resolvedExecutable, [ + _collectAppPath, + '--function-coverage', + '--uri', + '$serviceUri', + '--resume-isolates', + '--wait-paused' + ]); + + await toolResult.shouldExit(0).timeout( + timeout, + onTimeout: () => + throw StateError('We timed out waiting for the tool to finish.'), + ); + + await sampleProcess.shouldExit(); + + return toolResult.stdoutStream().join('\n'); +}
diff --git a/pkgs/coverage/test/isolate_paused_listener_test.dart b/pkgs/coverage/test/isolate_paused_listener_test.dart new file mode 100644 index 0000000..4fc7d4b --- /dev/null +++ b/pkgs/coverage/test/isolate_paused_listener_test.dart
@@ -0,0 +1,753 @@ +// 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 'package:coverage/src/isolate_paused_listener.dart'; +import 'package:mockito/mockito.dart'; +import 'package:test/test.dart'; +import 'package:vm_service/vm_service.dart'; + +import 'collect_coverage_mock_test.mocks.dart'; + +Event event( + String id, { + String? kind, + String? groupId, + String? name, +}) => + Event( + kind: kind, + isolate: IsolateRef( + isolateGroupId: groupId, + id: id, + name: name, + )); + +Isolate isolate( + String id, { + String? groupId, + String? name, + String? pauseKind, +}) => + Isolate( + isolateGroupId: groupId, + id: id, + name: name, + pauseEvent: pauseKind == null ? null : Event(kind: pauseKind), + ); + +(MockVmService, StreamController<Event>) createServiceAndEventStreams() { + final service = MockVmService(); + when(service.streamListen(any)).thenAnswer((_) async => Success()); + + // The VM service events we care about come in on 2 different streams, + // onIsolateEvent and onDebugEvent. We want to write tests that send sequences + // of events like [I1, D1, I2, D2, I3, D3], but since I and D go to separate + // streams, the listener may see them arrive like [I1, I2, I3, D1, D2, D3] or + // [D1, D2, D3, I1, I2, I3] or any other interleaving. So instead we send all + // the events through a single stream that gets split up. This emulates how + // the events work in reality, since they all come from a single web socket. + final allEvents = StreamController<Event>(); + final isolateEvents = StreamController<Event>(); + final debugEvents = StreamController<Event>(); + allEvents.stream.listen((Event e) { + if (e.kind == EventKind.kIsolateStart || + e.kind == EventKind.kIsolateStart) { + isolateEvents.add(e); + } else { + debugEvents.add(e); + } + }); + when(service.onIsolateEvent).thenAnswer((_) => isolateEvents.stream); + when(service.onDebugEvent).thenAnswer((_) => debugEvents.stream); + + return (service, allEvents); +} + +void main() { + group('IsolateEventBuffer', () { + test('buffers events', () async { + final received = <String>[]; + final eventBuffer = IsolateEventBuffer((Event event) async { + await Future<void>.delayed(Duration.zero); + received.add(event.isolate!.id!); + }); + + await eventBuffer.add(event('a')); + await eventBuffer.add(event('b')); + await eventBuffer.add(event('c')); + expect(received, <String>[]); + + await eventBuffer.flush(); + expect(received, ['a', 'b', 'c']); + + await eventBuffer.flush(); + expect(received, ['a', 'b', 'c']); + + await eventBuffer.add(event('d')); + await eventBuffer.add(event('e')); + await eventBuffer.add(event('f')); + expect(received, ['a', 'b', 'c', 'd', 'e', 'f']); + + await eventBuffer.flush(); + expect(received, ['a', 'b', 'c', 'd', 'e', 'f']); + }); + + test('buffers events during flush', () async { + final received = <String>[]; + final pause = Completer<void>(); + final eventBuffer = IsolateEventBuffer((Event event) async { + await pause.future; + received.add(event.isolate!.id!); + }); + + await eventBuffer.add(event('a')); + await eventBuffer.add(event('b')); + await eventBuffer.add(event('c')); + expect(received, <String>[]); + + final flushing = eventBuffer.flush(); + expect(received, <String>[]); + + await eventBuffer.add(event('d')); + await eventBuffer.add(event('e')); + await eventBuffer.add(event('f')); + expect(received, <String>[]); + + pause.complete(); + await flushing; + expect(received, ['a', 'b', 'c', 'd', 'e', 'f']); + }); + }); + + test('IsolateEventBuffer', () { + final group = IsolateGroupState(); + expect(group.running, isEmpty); + expect(group.paused, isEmpty); + expect(group.noRunningIsolates, isTrue); + expect(group.noLiveIsolates, isTrue); + + group.start('a'); + expect(group.running, unorderedEquals(['a'])); + expect(group.paused, isEmpty); + expect(group.noRunningIsolates, isFalse); + expect(group.noLiveIsolates, isFalse); + + group.start('a'); + expect(group.running, unorderedEquals(['a'])); + expect(group.paused, isEmpty); + expect(group.noRunningIsolates, isFalse); + expect(group.noLiveIsolates, isFalse); + + group.start('b'); + expect(group.running, unorderedEquals(['a', 'b'])); + expect(group.paused, isEmpty); + expect(group.noRunningIsolates, isFalse); + expect(group.noLiveIsolates, isFalse); + + group.pause('a'); + expect(group.running, unorderedEquals(['b'])); + expect(group.paused, unorderedEquals(['a'])); + expect(group.noRunningIsolates, isFalse); + expect(group.noLiveIsolates, isFalse); + + group.pause('a'); + expect(group.running, unorderedEquals(['b'])); + expect(group.paused, unorderedEquals(['a'])); + expect(group.noRunningIsolates, isFalse); + expect(group.noLiveIsolates, isFalse); + + group.pause('c'); + expect(group.running, unorderedEquals(['b'])); + expect(group.paused, unorderedEquals(['a', 'c'])); + expect(group.noRunningIsolates, isFalse); + expect(group.noLiveIsolates, isFalse); + + group.start('c'); + expect(group.running, unorderedEquals(['b', 'c'])); + expect(group.paused, unorderedEquals(['a'])); + expect(group.noRunningIsolates, isFalse); + expect(group.noLiveIsolates, isFalse); + + group.pause('c'); + expect(group.running, unorderedEquals(['b'])); + expect(group.paused, unorderedEquals(['a', 'c'])); + expect(group.noRunningIsolates, isFalse); + expect(group.noLiveIsolates, isFalse); + + group.exit('a'); + expect(group.running, unorderedEquals(['b'])); + expect(group.paused, unorderedEquals(['c'])); + expect(group.noRunningIsolates, isFalse); + expect(group.noLiveIsolates, isFalse); + + group.pause('b'); + expect(group.running, isEmpty); + expect(group.paused, unorderedEquals(['b', 'c'])); + expect(group.noRunningIsolates, isTrue); + expect(group.noLiveIsolates, isFalse); + + group.exit('b'); + expect(group.running, isEmpty); + expect(group.paused, unorderedEquals(['c'])); + expect(group.noRunningIsolates, isTrue); + expect(group.noLiveIsolates, isFalse); + + group.exit('c'); + expect(group.running, isEmpty); + expect(group.paused, isEmpty); + expect(group.noRunningIsolates, isTrue); + expect(group.noLiveIsolates, isTrue); + }); + + group('listenToIsolateLifecycleEvents', () { + late MockVmService service; + late StreamController<Event> allEvents; + late Completer<List<Isolate>> isolates; + late Future<void> backfilled; + late Future<void> testEnded; + + late List<String> received; + Future<void>? delayTheOnPauseCallback; + + void startEvent(String id) => + allEvents.add(event(id, kind: EventKind.kIsolateStart)); + void exitEvent(String id) => + allEvents.add(event(id, kind: EventKind.kIsolateExit)); + void pauseEvent(String id) => + allEvents.add(event(id, kind: EventKind.kPauseExit)); + void otherEvent(String id, String kind) => + allEvents.add(event(id, kind: kind)); + + Future<void> backfill(List<Isolate> isos) async { + isolates.complete(isos); + await backfilled; + } + + // We end the test by sending an exit event with a specific ID. + const endTestEventId = 'END'; + Future<void> endTest() { + exitEvent(endTestEventId); + return testEnded; + } + + setUp(() { + (service, allEvents) = createServiceAndEventStreams(); + + isolates = Completer<List<Isolate>>(); + when(service.getVM()) + .thenAnswer((_) async => VM(isolates: await isolates.future)); + when(service.getIsolate(any)).thenAnswer((invocation) async { + final id = invocation.positionalArguments[0]; + return (await isolates.future).firstWhere((iso) => iso.id == id); + }); + + received = <String>[]; + delayTheOnPauseCallback = null; + final testEnder = Completer<void>(); + testEnded = testEnder.future; + backfilled = listenToIsolateLifecycleEvents( + service, + (iso) { + if (iso.id == endTestEventId) return; + received.add('Start ${iso.id}'); + }, + (iso) async { + received.add('Pause ${iso.id}'); + if (delayTheOnPauseCallback != null) { + await delayTheOnPauseCallback; + received.add('Pause done ${iso.id}'); + } + }, + (iso) { + if (iso.id == endTestEventId) { + testEnder.complete(); + } else { + received.add('Exit ${iso.id}'); + } + }, + ); + }); + + test('ordinary flows', () async { + // Events sent before backfill. + startEvent('A'); + startEvent('C'); + startEvent('B'); + pauseEvent('C'); + pauseEvent('A'); + startEvent('D'); + pauseEvent('D'); + exitEvent('A'); + + // Run backfill. + await backfill([ + isolate('B'), + isolate('C', pauseKind: EventKind.kPauseExit), + isolate('D'), + isolate('E'), + isolate('F', pauseKind: EventKind.kPauseExit), + ]); + + // All the backfill events happen before any of the real events. + expect(received, [ + // Backfill events. + 'Start B', + 'Start C', + 'Pause C', + 'Start D', + 'Start E', + 'Start F', + 'Pause F', + + // Real events from before backfill. + 'Start A', + 'Pause A', + 'Pause D', + 'Exit A', + ]); + + // Events sent after backfill. + received.clear(); + startEvent('G'); + exitEvent('C'); + exitEvent('B'); + exitEvent('G'); + exitEvent('D'); + exitEvent('E'); + exitEvent('F'); + + await endTest(); + expect(received, [ + 'Start G', + 'Exit C', + 'Exit B', + 'Exit G', + 'Exit D', + 'Exit E', + 'Exit F', + ]); + + verify(service.streamListen(EventStreams.kIsolate)).called(1); + verify(service.streamListen(EventStreams.kDebug)).called(1); + }); + + test('pause and exit events without start', () async { + await backfill([]); + + pauseEvent('A'); + exitEvent('B'); + + await endTest(); + expect(received, [ + 'Start A', + 'Pause A', + 'Start B', + 'Exit B', + ]); + }); + + test('pause event after exit is ignored', () async { + await backfill([]); + + exitEvent('A'); + pauseEvent('A'); + + await endTest(); + expect(received, [ + 'Start A', + 'Exit A', + ]); + }); + + test('event deduping', () async { + startEvent('A'); + startEvent('A'); + pauseEvent('A'); + pauseEvent('A'); + exitEvent('A'); + exitEvent('A'); + + pauseEvent('B'); + startEvent('B'); + + exitEvent('C'); + startEvent('C'); + + await backfill([]); + await endTest(); + expect(received, [ + 'Start A', + 'Pause A', + 'Exit A', + 'Start B', + 'Pause B', + 'Start C', + 'Exit C', + ]); + }); + + test('ignore other events', () async { + await backfill([]); + + startEvent('A'); + pauseEvent('A'); + otherEvent('A', EventKind.kResume); + exitEvent('A'); + + startEvent('B'); + otherEvent('B', EventKind.kPauseBreakpoint); + exitEvent('B'); + + otherEvent('C', EventKind.kInspect); + + await endTest(); + expect(received, [ + 'Start A', + 'Pause A', + 'Exit A', + 'Start B', + 'Exit B', + ]); + }); + + test('exit event during pause callback', () async { + final delayingTheOnPauseCallback = Completer<void>(); + delayTheOnPauseCallback = delayingTheOnPauseCallback.future; + await backfill([]); + + startEvent('A'); + pauseEvent('A'); + exitEvent('A'); + + while (received.length < 2) { + await Future<void>.delayed(Duration.zero); + } + + expect(received, [ + 'Start A', + 'Pause A', + ]); + + delayingTheOnPauseCallback.complete(); + await endTest(); + expect(received, [ + 'Start A', + 'Pause A', + 'Pause done A', + 'Exit A', + ]); + }); + + test('exit event during pause callback, event deduping', () async { + final delayingTheOnPauseCallback = Completer<void>(); + delayTheOnPauseCallback = delayingTheOnPauseCallback.future; + await backfill([]); + + startEvent('A'); + pauseEvent('A'); + exitEvent('A'); + pauseEvent('A'); + pauseEvent('A'); + exitEvent('A'); + exitEvent('A'); + + while (received.length < 2) { + await Future<void>.delayed(Duration.zero); + } + + expect(received, [ + 'Start A', + 'Pause A', + ]); + + delayingTheOnPauseCallback.complete(); + await endTest(); + expect(received, [ + 'Start A', + 'Pause A', + 'Pause done A', + 'Exit A', + ]); + }); + }); + + group('IsolatePausedListener', () { + late MockVmService service; + late StreamController<Event> allEvents; + late Future<void> allIsolatesExited; + + late List<String> received; + late bool stopped; + + void startEvent(String id, String groupId, [String? name]) => + allEvents.add(event( + id, + kind: EventKind.kIsolateStart, + groupId: groupId, + name: name ?? id, + )); + void exitEvent(String id, String groupId, [String? name]) => + allEvents.add(event( + id, + kind: EventKind.kIsolateExit, + groupId: groupId, + name: name ?? id, + )); + void pauseEvent(String id, String groupId, [String? name]) => + allEvents.add(event( + id, + kind: EventKind.kPauseExit, + groupId: groupId, + name: name ?? id, + )); + + Future<void> endTest() async { + await allIsolatesExited; + stopped = true; + } + + setUp(() { + (service, allEvents) = createServiceAndEventStreams(); + + // Backfill was tested above, so this test does everything using events, + // for simplicity. No need to report any isolates. + when(service.getVM()).thenAnswer((_) async => VM()); + + received = <String>[]; + when(service.resume(any)).thenAnswer((invocation) async { + final id = invocation.positionalArguments[0]; + received.add('Resume $id'); + return Success(); + }); + + stopped = false; + allIsolatesExited = IsolatePausedListener( + service, + (iso, isLastIsolateInGroup) async { + expect(stopped, isFalse); + received.add('Pause ${iso.id}. Last in group ${iso.isolateGroupId}? ' + '${isLastIsolateInGroup ? 'Yes' : 'No'}'); + }, + (message) => received.add(message), + ).waitUntilAllExited(); + }); + + test('ordinary flows', () async { + startEvent('A', '1'); + startEvent('B', '1'); + pauseEvent('A', '1'); + startEvent('C', '1'); + pauseEvent('B', '1'); + exitEvent('A', '1'); + startEvent('D', '2'); + startEvent('E', '2'); + startEvent('F', '2'); + pauseEvent('C', '1'); + pauseEvent('F', '2'); + pauseEvent('E', '2'); + exitEvent('C', '1'); + exitEvent('E', '2'); + startEvent('G', '3'); + exitEvent('F', '2'); + startEvent('H', '3'); + startEvent('I', '3'); + pauseEvent('I', '3'); + exitEvent('I', '3'); + pauseEvent('H', '3'); + exitEvent('H', '3'); + pauseEvent('D', '2'); + pauseEvent('G', '3'); + exitEvent('D', '2'); + exitEvent('G', '3'); + exitEvent('B', '1'); + + await endTest(); + + // Events sent after waitUntilAllExited is finished do nothing. + startEvent('Z', '9'); + pauseEvent('Z', '9'); + exitEvent('Z', '9'); + + expect(received, [ + 'Pause A. Last in group 1? No', + 'Resume A', + 'Pause B. Last in group 1? No', + 'Resume B', + 'Pause C. Last in group 1? Yes', + 'Resume C', + 'Pause F. Last in group 2? No', + 'Resume F', + 'Pause E. Last in group 2? No', + 'Resume E', + 'Pause I. Last in group 3? No', + 'Resume I', + 'Pause H. Last in group 3? No', + 'Resume H', + 'Pause D. Last in group 2? Yes', + 'Resume D', + 'Pause G. Last in group 3? Yes', + 'Resume G', + ]); + }); + + test('exit without pausing', () async { + // If an isolate exits without pausing, this may mess up coverage + // collection (if it happens to be the last isolate in the group, that + // group won't be collected). The best we can do is log an error, and make + // sure not to wait forever for pause events that aren't coming. + startEvent('A', '1'); + startEvent('B', '1'); + exitEvent('A', '1'); + pauseEvent('B', '1'); + startEvent('C', '2'); + startEvent('D', '2'); + pauseEvent('D', '2'); + exitEvent('D', '2'); + exitEvent('C', '2'); + exitEvent('B', '1'); + + await endTest(); + + // B was paused correctly and was the last to exit isolate 1, so isolate 1 + // was collected ok. + expect(received, [ + 'Pause B. Last in group 1? Yes', + 'Resume B', + 'Pause D. Last in group 2? No', + 'Resume D', + 'ERROR: An isolate exited without pausing, causing coverage data to ' + 'be lost for group 2.', + ]); + }); + + test('main isolate resumed last', () async { + startEvent('A', '1', 'main'); + startEvent('B', '1', 'main'); // Second isolate named main, ignored. + pauseEvent('B', '1', 'main'); + startEvent('C', '2', 'main'); // Third isolate named main, ignored. + pauseEvent('A', '1', 'main'); + startEvent('D', '2'); + pauseEvent('C', '2'); + exitEvent('C', '2'); + pauseEvent('D', '2'); + exitEvent('D', '2'); + exitEvent('B', '1'); + + await endTest(); + + expect(received, [ + 'Pause B. Last in group 1? No', + 'Resume B', + 'Pause C. Last in group 2? No', + 'Resume C', + 'Pause D. Last in group 2? Yes', + 'Resume D', + 'Pause A. Last in group 1? Yes', + 'Resume A', + ]); + }); + + test('main isolate exits without pausing', () async { + startEvent('A', '1', 'main'); + startEvent('B', '1'); + pauseEvent('B', '1'); + exitEvent('A', '1', 'main'); + exitEvent('B', '1'); + + await endTest(); + + expect(received, [ + 'Pause B. Last in group 1? No', + 'Resume B', + 'ERROR: An isolate exited without pausing, causing coverage data to ' + 'be lost for group 1.', + ]); + }); + + test('main isolate is the only isolate', () async { + startEvent('A', '1', 'main'); + pauseEvent('A', '1', 'main'); + + await endTest(); + + expect(received, [ + 'Pause A. Last in group 1? Yes', + 'Resume A', + ]); + }); + + test('all other isolates exit before main isolate pauses', () async { + startEvent('A', '1', 'main'); + startEvent('B', '1'); + pauseEvent('B', '1'); + exitEvent('B', '1'); + + await Future<void>.delayed(Duration.zero); + + pauseEvent('A', '1', 'main'); + exitEvent('A', '1', 'main'); + + await endTest(); + + expect(received, [ + 'Pause B. Last in group 1? No', + 'Resume B', + 'Pause A. Last in group 1? Yes', + 'Resume A', + ]); + }); + + test('group reopened', () async { + // If an isolate is reported in a group after the group as believed to be + // closed, reopen the group. This double counts some coverage, but at + // least won't miss any. + + startEvent('Z', '9'); // Separate isolate to keep the system alive until + pauseEvent('Z', '9'); // the test is complete. + + startEvent('A', '1'); + startEvent('B', '1'); + pauseEvent('A', '1'); + pauseEvent('B', '1'); + exitEvent('B', '1'); + exitEvent('A', '1'); + + startEvent('D', '2'); + startEvent('E', '2'); + pauseEvent('E', '2'); + pauseEvent('D', '2'); + exitEvent('E', '2'); + exitEvent('D', '2'); + + startEvent('C', '1'); + pauseEvent('F', '2'); + pauseEvent('C', '1'); + exitEvent('C', '1'); + exitEvent('F', '2'); + + exitEvent('Z', '9'); + + await endTest(); + + expect(received, [ + 'Pause Z. Last in group 9? Yes', + 'Resume Z', + 'Pause A. Last in group 1? No', + 'Resume A', + 'Pause B. Last in group 1? Yes', + 'Resume B', + 'Pause E. Last in group 2? No', + 'Resume E', + 'Pause D. Last in group 2? Yes', + 'Resume D', + 'Pause F. Last in group 2? Yes', + 'Resume F', + 'Pause C. Last in group 1? Yes', + 'Resume C', + ]); + }); + }); +}
diff --git a/pkgs/coverage/test/lcov_test.dart b/pkgs/coverage/test/lcov_test.dart new file mode 100644 index 0000000..ca62117 --- /dev/null +++ b/pkgs/coverage/test/lcov_test.dart
@@ -0,0 +1,364 @@ +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:io'; + +import 'package:coverage/coverage.dart'; +import 'package:coverage/src/util.dart'; +import 'package:glob/glob.dart'; +import 'package:path/path.dart' as p; +import 'package:test/test.dart'; +import 'package:test_process/test_process.dart'; + +final _sampleAppPath = p.join('test', 'test_files', 'test_app.dart'); +final _sampleGeneratedPath = p.join('test', 'test_files', 'test_app.g.dart'); +final _isolateLibPath = p.join('test', 'test_files', 'test_app_isolate.dart'); + +final _sampleAppFileUri = p.toUri(p.absolute(_sampleAppPath)).toString(); +final _sampleGeneratedFileUri = + p.toUri(p.absolute(_sampleGeneratedPath)).toString(); +final _isolateLibFileUri = p.toUri(p.absolute(_isolateLibPath)).toString(); + +void main() { + test('validate hitMap', () async { + final hitmap = await _getHitMap(); + + expect(hitmap, contains(_sampleAppFileUri)); + expect(hitmap, contains(_sampleGeneratedFileUri)); + expect(hitmap, contains(_isolateLibFileUri)); + expect(hitmap, contains('package:coverage/src/util.dart')); + + final sampleAppHitMap = hitmap[_sampleAppFileUri]; + final sampleAppHitLines = sampleAppHitMap?.lineHits; + final sampleAppHitFuncs = sampleAppHitMap?.funcHits; + final sampleAppFuncNames = sampleAppHitMap?.funcNames; + final sampleAppBranchHits = sampleAppHitMap?.branchHits; + + expect(sampleAppHitLines, containsPair(53, greaterThanOrEqualTo(1)), + reason: 'be careful if you modify the test file'); + expect(sampleAppHitLines, containsPair(57, 0), + reason: 'be careful if you modify the test file'); + expect(sampleAppHitLines, isNot(contains(39)), + reason: 'be careful if you modify the test file'); + expect(sampleAppHitFuncs, containsPair(52, 1), + reason: 'be careful if you modify the test file'); + expect(sampleAppHitFuncs, containsPair(56, 0), + reason: 'be careful if you modify the test file'); + expect(sampleAppFuncNames, containsPair(52, 'usedMethod'), + reason: 'be careful if you modify the test file'); + expect(sampleAppBranchHits, containsPair(48, 1), + reason: 'be careful if you modify the test file'); + }); + + test('validate hitMap, old VM without branch coverage', () async { + final hitmap = await _getHitMap(); + + expect(hitmap, contains(_sampleAppFileUri)); + expect(hitmap, contains(_sampleGeneratedFileUri)); + expect(hitmap, contains(_isolateLibFileUri)); + expect(hitmap, contains('package:coverage/src/util.dart')); + + final sampleAppHitMap = hitmap[_sampleAppFileUri]; + final sampleAppHitLines = sampleAppHitMap?.lineHits; + final sampleAppHitFuncs = sampleAppHitMap?.funcHits; + final sampleAppFuncNames = sampleAppHitMap?.funcNames; + + expect(sampleAppHitLines, containsPair(53, greaterThanOrEqualTo(1)), + reason: 'be careful if you modify the test file'); + expect(sampleAppHitLines, containsPair(57, 0), + reason: 'be careful if you modify the test file'); + expect(sampleAppHitLines, isNot(contains(39)), + reason: 'be careful if you modify the test file'); + expect(sampleAppHitFuncs, containsPair(52, 1), + reason: 'be careful if you modify the test file'); + expect(sampleAppHitFuncs, containsPair(56, 0), + reason: 'be careful if you modify the test file'); + expect(sampleAppFuncNames, containsPair(52, 'usedMethod'), + reason: 'be careful if you modify the test file'); + }); + + group('LcovFormatter', () { + test('format()', () async { + final hitmap = await _getHitMap(); + + final resolver = await Resolver.create(packagePath: '.'); + // ignore: deprecated_member_use_from_same_package + final formatter = LcovFormatter(resolver); + + final res = await formatter + .format(hitmap.map((key, value) => MapEntry(key, value.lineHits))); + + expect(res, contains(p.absolute(_sampleAppPath))); + expect(res, contains(p.absolute(_sampleGeneratedPath))); + expect(res, contains(p.absolute(_isolateLibPath))); + expect(res, contains(p.absolute(p.join('lib', 'src', 'util.dart')))); + }); + + test('formatLcov()', () async { + final hitmap = await _getHitMap(); + + final resolver = await Resolver.create(packagePath: '.'); + final res = hitmap.formatLcov(resolver); + + expect(res, contains(p.absolute(_sampleAppPath))); + expect(res, contains(p.absolute(_sampleGeneratedPath))); + expect(res, contains(p.absolute(_isolateLibPath))); + expect(res, contains(p.absolute(p.join('lib', 'src', 'util.dart')))); + }); + + test('formatLcov() includes files in reportOn list', () async { + final hitmap = await _getHitMap(); + + final resolver = await Resolver.create(packagePath: '.'); + final res = hitmap.formatLcov(resolver, reportOn: ['lib/', 'test/']); + + expect(res, contains(p.absolute(_sampleAppPath))); + expect(res, contains(p.absolute(_sampleGeneratedPath))); + expect(res, contains(p.absolute(_isolateLibPath))); + expect(res, contains(p.absolute(p.join('lib', 'src', 'util.dart')))); + }); + + test('formatLcov() excludes files not in reportOn list', () async { + final hitmap = await _getHitMap(); + + final resolver = await Resolver.create(packagePath: '.'); + final res = hitmap.formatLcov(resolver, reportOn: ['lib/']); + + expect(res, isNot(contains(p.absolute(_sampleAppPath)))); + expect(res, isNot(contains(p.absolute(_sampleGeneratedPath)))); + expect(res, isNot(contains(p.absolute(_isolateLibPath)))); + expect(res, contains(p.absolute(p.join('lib', 'src', 'util.dart')))); + }); + + test('formatLcov() excludes files matching glob patterns', () async { + final hitmap = await _getHitMap(); + + final resolver = await Resolver.create(packagePath: '.'); + final res = hitmap.formatLcov( + resolver, + ignoreGlobs: {Glob('**/*.g.dart'), Glob('**/util.dart')}, + ); + + expect(res, contains(p.absolute(_sampleAppPath))); + expect(res, isNot(contains(p.absolute(_sampleGeneratedPath)))); + expect(res, contains(p.absolute(_isolateLibPath))); + expect( + res, + isNot(contains(p.absolute(p.join('lib', 'src', 'util.dart')))), + ); + }); + + test( + 'formatLcov() excludes files matching glob patterns regardless of their' + 'presence on reportOn list', () async { + final hitmap = await _getHitMap(); + + final resolver = await Resolver.create(packagePath: '.'); + final res = hitmap.formatLcov( + resolver, + reportOn: ['test/'], + ignoreGlobs: {Glob('**/*.g.dart')}, + ); + + expect(res, contains(p.absolute(_sampleAppPath))); + expect(res, isNot(contains(p.absolute(_sampleGeneratedPath)))); + expect(res, contains(p.absolute(_isolateLibPath))); + }); + + test('formatLcov() uses paths relative to basePath', () async { + final hitmap = await _getHitMap(); + + final resolver = await Resolver.create(packagePath: '.'); + final res = hitmap.formatLcov(resolver, basePath: p.absolute('lib')); + + expect( + res, isNot(contains(p.absolute(p.join('lib', 'src', 'util.dart'))))); + expect(res, contains(p.join('src', 'util.dart'))); + }); + }); + + group('PrettyPrintFormatter', () { + test('format()', () async { + final hitmap = await _getHitMap(); + + final resolver = await Resolver.create(packagePath: '.'); + // ignore: deprecated_member_use_from_same_package + final formatter = PrettyPrintFormatter(resolver, Loader()); + + final res = await formatter + .format(hitmap.map((key, value) => MapEntry(key, value.lineHits))); + + expect(res, contains(p.absolute(_sampleAppPath))); + expect(res, contains(p.absolute(_sampleGeneratedPath))); + expect(res, contains(p.absolute(_isolateLibPath))); + expect(res, contains(p.absolute(p.join('lib', 'src', 'util.dart')))); + + // be very careful if you change the test file + expect(res, contains(' 0| return a - b;')); + + expect(res, contains('| return withTimeout(() async {'), + reason: 'be careful if you change lib/src/util.dart'); + + final hitLineRegexp = RegExp(r'\s+(\d+)\| return a \+ b;'); + final match = hitLineRegexp.allMatches(res).single; + + final hitCount = int.parse(match[1]!); + expect(hitCount, greaterThanOrEqualTo(1)); + }); + + test('prettyPrint()', () async { + final hitmap = await _getHitMap(); + + final resolver = await Resolver.create(packagePath: '.'); + final res = await hitmap.prettyPrint(resolver, Loader()); + + expect(res, contains(p.absolute(_sampleAppPath))); + expect(res, contains(p.absolute(_sampleGeneratedPath))); + expect(res, contains(p.absolute(_isolateLibPath))); + expect(res, contains(p.absolute(p.join('lib', 'src', 'util.dart')))); + + // be very careful if you change the test file + expect(res, contains(' 0| return a - b;')); + + expect(res, contains('| return withTimeout(() async {'), + reason: 'be careful if you change lib/src/util.dart'); + + final hitLineRegexp = RegExp(r'\s+(\d+)\| return a \+ b;'); + final match = hitLineRegexp.allMatches(res).single; + + final hitCount = int.parse(match[1]!); + expect(hitCount, greaterThanOrEqualTo(1)); + }); + + test('prettyPrint() includes files in reportOn list', () async { + final hitmap = await _getHitMap(); + + final resolver = await Resolver.create(packagePath: '.'); + final res = await hitmap + .prettyPrint(resolver, Loader(), reportOn: ['lib/', 'test/']); + + expect(res, contains(p.absolute(_sampleAppPath))); + expect(res, contains(p.absolute(_sampleGeneratedPath))); + expect(res, contains(p.absolute(_isolateLibPath))); + expect(res, contains(p.absolute(p.join('lib', 'src', 'util.dart')))); + }); + + test('prettyPrint() excludes files not in reportOn list', () async { + final hitmap = await _getHitMap(); + + final resolver = await Resolver.create(packagePath: '.'); + final res = + await hitmap.prettyPrint(resolver, Loader(), reportOn: ['lib/']); + + expect(res, isNot(contains(p.absolute(_sampleAppPath)))); + expect(res, isNot(contains(p.absolute(_sampleGeneratedPath)))); + expect(res, isNot(contains(p.absolute(_isolateLibPath)))); + expect(res, contains(p.absolute(p.join('lib', 'src', 'util.dart')))); + }); + + test('prettyPrint() excludes files matching glob patterns', () async { + final hitmap = await _getHitMap(); + + final resolver = await Resolver.create(packagePath: '.'); + final res = await hitmap.prettyPrint( + resolver, + Loader(), + ignoreGlobs: {Glob('**/*.g.dart'), Glob('**/util.dart')}, + ); + + expect(res, contains(p.absolute(_sampleAppPath))); + expect(res, isNot(contains(p.absolute(_sampleGeneratedPath)))); + expect(res, contains(p.absolute(_isolateLibPath))); + expect( + res, + isNot(contains(p.absolute(p.join('lib', 'src', 'util.dart')))), + ); + }); + + test( + 'prettyPrint() excludes files matching glob patterns regardless of' + 'their presence on reportOn list', () async { + final hitmap = await _getHitMap(); + + final resolver = await Resolver.create(packagePath: '.'); + final res = await hitmap.prettyPrint( + resolver, + Loader(), + reportOn: ['test/'], + ignoreGlobs: {Glob('**/*.g.dart')}, + ); + + expect(res, contains(p.absolute(_sampleAppPath))); + expect(res, isNot(contains(p.absolute(_sampleGeneratedPath)))); + expect(res, contains(p.absolute(_isolateLibPath))); + }); + + test('prettyPrint() functions', () async { + final hitmap = await _getHitMap(); + + final resolver = await Resolver.create(packagePath: '.'); + final res = + await hitmap.prettyPrint(resolver, Loader(), reportFuncs: true); + + expect(res, contains(p.absolute(_sampleAppPath))); + expect(res, contains(p.absolute(_sampleGeneratedPath))); + expect(res, contains(p.absolute(_isolateLibPath))); + expect(res, contains(p.absolute(p.join('lib', 'src', 'util.dart')))); + + // be very careful if you change the test file + expect(res, contains(' 1|Future<void> main() async {')); + expect(res, contains(' 1|int usedMethod(int a, int b) {')); + expect(res, contains(' 0|int unusedMethod(int a, int b) {')); + expect(res, contains(' | return a + b;')); + }); + + test('prettyPrint() branches', () async { + final hitmap = await _getHitMap(); + + final resolver = await Resolver.create(packagePath: '.'); + final res = + await hitmap.prettyPrint(resolver, Loader(), reportBranches: true); + + expect(res, contains(p.absolute(_sampleAppPath))); + expect(res, contains(p.absolute(_sampleGeneratedPath))); + expect(res, contains(p.absolute(_isolateLibPath))); + expect(res, contains(p.absolute(p.join('lib', 'src', 'util.dart')))); + + // be very careful if you change the test file + expect(res, contains(' 1| if (x == answer) {')); + expect(res, contains(' 0| while (i < lines.length) {')); + expect(res, contains(' | bar.baz();')); + }); + }); +} + +Future<Map<String, HitMap>> _getHitMap() async { + expect(FileSystemEntity.isFileSync(_sampleAppPath), isTrue); + + // select service port. + final port = await getOpenPort(); + + // start sample app. + final sampleAppArgs = [ + '--pause-isolates-on-exit', + '--enable-vm-service=$port', + '--branch-coverage', + _sampleAppPath + ]; + final sampleProcess = + await TestProcess.start(Platform.resolvedExecutable, sampleAppArgs); + + final serviceUri = await serviceUriFromProcess(sampleProcess.stdoutStream()); + + // collect hit map. + final coverageJson = (await collect(serviceUri, true, true, false, <String>{}, + functionCoverage: true, + branchCoverage: true))['coverage'] as List<Map<String, dynamic>>; + final hitMap = HitMap.parseJson(coverageJson); + + await sampleProcess.shouldExit(0); + + return hitMap; +}
diff --git a/pkgs/coverage/test/resolver_test.dart b/pkgs/coverage/test/resolver_test.dart new file mode 100644 index 0000000..1161aee --- /dev/null +++ b/pkgs/coverage/test/resolver_test.dart
@@ -0,0 +1,211 @@ +// Copyright (c) 2016, 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:coverage/src/resolver.dart'; +import 'package:path/path.dart' as p; +import 'package:test/test.dart'; +import 'package:test_descriptor/test_descriptor.dart' as d; + +void main() { + group('Default Resolver', () { + setUp(() async { + final sandboxUriPath = p.toUri(d.sandbox).toString(); + await d.dir('bar', [ + d.dir('lib', [ + d.file('bar.dart', 'final fizz = "bar";'), + ]) + ]).create(); + + await d.dir('foo', [ + d.dir('.dart_tool', [ + d.file('bad_package_config.json', 'thisIsntAPackageConfigFile!'), + d.file('package_config.json', ''' +{ + "configVersion": 2, + "packages": [ + { + "name": "foo", + "rootUri": "../", + "packageUri": "lib/" + }, + { + "name": "bar", + "rootUri": "$sandboxUriPath/bar", + "packageUri": "lib/" + } + ] +} +'''), + ]), + d.dir('lib', [ + d.file('foo.dart', 'final foo = "bar";'), + ]), + ]).create(); + + await d.dir('sdk', [ + d.dir('io', [ + d.file('io.dart', 'final io = "hello";'), + ]), + d.dir('io_patch', [ + d.file('io.dart', 'final patch = true;'), + ]), + d.dir('io_dev', [ + d.file('io.dart', 'final dev = true;'), + ]), + ]).create(); + }); + + test('can be created from a package_config.json', () async { + final resolver = await Resolver.create( + packagesPath: + p.join(d.sandbox, 'foo', '.dart_tool', 'package_config.json')); + expect(resolver.resolve('package:foo/foo.dart'), + p.join(d.sandbox, 'foo', 'lib', 'foo.dart')); + expect(resolver.resolve('package:bar/bar.dart'), + p.join(d.sandbox, 'bar', 'lib', 'bar.dart')); + }); + + test('can be created from a package directory', () async { + final resolver = + await Resolver.create(packagePath: p.join(d.sandbox, 'foo')); + expect(resolver.resolve('package:foo/foo.dart'), + p.join(d.sandbox, 'foo', 'lib', 'foo.dart')); + }); + + test('errors if the packagesFile is an unknown format', () async { + expect( + () async => await Resolver.create( + packagesPath: p.join( + d.sandbox, 'foo', '.dart_tool', 'bad_package_config.json')), + throwsA(isA<FormatException>())); + }); + + test('resolves dart: URIs', () async { + final resolver = await Resolver.create( + packagePath: p.join(d.sandbox, 'foo'), + sdkRoot: p.join(d.sandbox, 'sdk')); + expect(resolver.resolve('dart:io'), + p.join(d.sandbox, 'sdk', 'io', 'io.dart')); + expect(resolver.resolve('dart:io-patch/io.dart'), null); + expect(resolver.resolve('dart:io-dev/io.dart'), + p.join(d.sandbox, 'sdk', 'io_dev', 'io.dart')); + }); + + test('cannot resolve SDK URIs if sdkRoot is null', () async { + final resolver = + await Resolver.create(packagePath: p.join(d.sandbox, 'foo')); + expect(resolver.resolve('dart:convert'), null); + }); + + test('cannot resolve package URIs if packagePath is null', () async { + // ignore: deprecated_member_use_from_same_package + final resolver = Resolver(); + expect(resolver.resolve('package:foo/foo.dart'), null); + }); + + test('cannot resolve package URIs if packagePath is not found', () async { + final resolver = + await Resolver.create(packagePath: p.join(d.sandbox, 'foo')); + expect(resolver.resolve('package:baz/baz.dart'), null); + }); + + test('cannot resolve unexpected URI schemes', () async { + final resolver = + await Resolver.create(packagePath: p.join(d.sandbox, 'foo')); + expect(resolver.resolve('thing:foo/foo.dart'), null); + }); + }); + + group('Bazel resolver', () { + const workspace = 'foo'; + final resolver = BazelResolver(workspacePath: workspace); + + test('does not resolve SDK URIs', () { + expect(resolver.resolve('dart:convert'), null); + }); + + test('resolves third-party package URIs', () { + expect(resolver.resolve('package:foo/bar.dart'), + 'third_party/dart/foo/lib/bar.dart'); + expect(resolver.resolve('package:foo/src/bar.dart'), + 'third_party/dart/foo/lib/src/bar.dart'); + }); + + test('resolves non-third-party package URIs', () { + expect( + resolver.resolve('package:foo.bar/baz.dart'), 'foo/bar/lib/baz.dart'); + expect(resolver.resolve('package:foo.bar/src/baz.dart'), + 'foo/bar/lib/src/baz.dart'); + }); + + test('resolves file URIs', () { + expect( + resolver + .resolve('file://x/y/z.runfiles/$workspace/foo/bar/lib/baz.dart'), + 'foo/bar/lib/baz.dart'); + expect( + resolver.resolve( + 'file://x/y/z.runfiles/$workspace/foo/bar/lib/src/baz.dart'), + 'foo/bar/lib/src/baz.dart'); + }); + + test('resolves HTTPS URIs containing /packages/', () { + expect(resolver.resolve('https://host:8080/a/b/packages/foo/bar.dart'), + 'third_party/dart/foo/lib/bar.dart'); + expect( + resolver.resolve('https://host:8080/a/b/packages/foo/src/bar.dart'), + 'third_party/dart/foo/lib/src/bar.dart'); + expect( + resolver.resolve('https://host:8080/a/b/packages/foo.bar/baz.dart'), + 'foo/bar/lib/baz.dart'); + expect( + resolver + .resolve('https://host:8080/a/b/packages/foo.bar/src/baz.dart'), + 'foo/bar/lib/src/baz.dart'); + }); + + test('resolves HTTP URIs containing /packages/', () { + expect(resolver.resolve('http://host:8080/a/b/packages/foo/bar.dart'), + 'third_party/dart/foo/lib/bar.dart'); + expect(resolver.resolve('http://host:8080/a/b/packages/foo/src/bar.dart'), + 'third_party/dart/foo/lib/src/bar.dart'); + expect(resolver.resolve('http://host:8080/a/b/packages/foo.bar/baz.dart'), + 'foo/bar/lib/baz.dart'); + expect( + resolver + .resolve('http://host:8080/a/b/packages/foo.bar/src/baz.dart'), + 'foo/bar/lib/src/baz.dart'); + }); + + test('resolves HTTPS URIs without /packages/', () { + expect( + resolver + .resolve('https://host:8080/third_party/dart/foo/lib/bar.dart'), + 'third_party/dart/foo/lib/bar.dart'); + expect( + resolver.resolve( + 'https://host:8080/third_party/dart/foo/lib/src/bar.dart'), + 'third_party/dart/foo/lib/src/bar.dart'); + expect(resolver.resolve('https://host:8080/foo/lib/bar.dart'), + 'foo/lib/bar.dart'); + expect(resolver.resolve('https://host:8080/foo/lib/src/bar.dart'), + 'foo/lib/src/bar.dart'); + }); + + test('resolves HTTP URIs without /packages/', () { + expect( + resolver + .resolve('http://host:8080/third_party/dart/foo/lib/bar.dart'), + 'third_party/dart/foo/lib/bar.dart'); + expect( + resolver.resolve( + 'http://host:8080/third_party/dart/foo/lib/src/bar.dart'), + 'third_party/dart/foo/lib/src/bar.dart'); + expect(resolver.resolve('http://host:8080/foo/lib/bar.dart'), + 'foo/lib/bar.dart'); + expect(resolver.resolve('http://host:8080/foo/lib/src/bar.dart'), + 'foo/lib/src/bar.dart'); + }); + }); +}
diff --git a/pkgs/coverage/test/run_and_collect_test.dart b/pkgs/coverage/test/run_and_collect_test.dart new file mode 100644 index 0000000..e371f90 --- /dev/null +++ b/pkgs/coverage/test/run_and_collect_test.dart
@@ -0,0 +1,128 @@ +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:coverage/coverage.dart'; +import 'package:path/path.dart' as p; +import 'package:test/test.dart'; + +import 'test_util.dart'; + +final _isolateLibPath = p.join('test', 'test_files', 'test_app_isolate.dart'); + +final _sampleAppFileUri = p.toUri(p.absolute(testAppPath)).toString(); +final _isolateLibFileUri = p.toUri(p.absolute(_isolateLibPath)).toString(); + +void main() { + test('runAndCollect', () async { + // use runAndCollect and verify that the results match w/ running manually + final coverage = coverageDataFromJson(await runAndCollect(testAppPath)); + expect(coverage, isNotEmpty); + + final sources = coverage.sources(); + + for (var sampleCoverageData in sources[_sampleAppFileUri]!) { + expect(sampleCoverageData['hits'], isNotNull); + } + + for (var sampleCoverageData in sources[_isolateLibFileUri]!) { + expect(sampleCoverageData['hits'], isNotEmpty); + } + + final hitMap = await HitMap.parseJson(coverage, checkIgnoredLines: true); + checkHitmap(hitMap); + final resolver = await Resolver.create(); + final ignoredLinesInFilesCache = <String, List<List<int>>?>{}; + final hitMap2 = HitMap.parseJsonSync(coverage, + checkIgnoredLines: true, + ignoredLinesInFilesCache: ignoredLinesInFilesCache, + resolver: resolver); + checkHitmap(hitMap2); + checkIgnoredLinesInFilesCache(ignoredLinesInFilesCache); + + // Asking again the cache should answer questions about ignored lines, + // so providing a resolver that throws when asked for files should be ok. + final hitMap3 = HitMap.parseJsonSync(coverage, + checkIgnoredLines: true, + ignoredLinesInFilesCache: ignoredLinesInFilesCache, + resolver: ThrowingResolver()); + checkHitmap(hitMap3); + checkIgnoredLinesInFilesCache(ignoredLinesInFilesCache); + }); +} + +class ThrowingResolver implements Resolver { + @override + List<String> get failed => throw UnimplementedError(); + + @override + String? get packagePath => throw UnimplementedError(); + + @override + String? get packagesPath => throw UnimplementedError(); + + @override + String? resolve(String scriptUri) => throw UnimplementedError(); + + @override + String? resolveSymbolicLinks(String path) => throw UnimplementedError(); + + @override + String? get sdkRoot => throw UnimplementedError(); +} + +void checkIgnoredLinesInFilesCache( + Map<String, List<List<int>>?> ignoredLinesInFilesCache) { + final keys = ignoredLinesInFilesCache.keys.toList(); + final testAppKey = + keys.where((element) => element.endsWith('test_app.dart')).single; + final testAppIsolateKey = + keys.where((element) => element.endsWith('test_app_isolate.dart')).single; + final packageUtilKey = keys + .where((element) => element.endsWith('package:coverage/src/util.dart')) + .single; + expect(ignoredLinesInFilesCache[packageUtilKey], isEmpty); + expect(ignoredLinesInFilesCache[testAppKey], null /* means whole file */); + expect(ignoredLinesInFilesCache[testAppIsolateKey], [ + [51, 51], + [53, 57], + [62, 65], + [66, 72] + ]); +} + +void checkHitmap(Map<String, HitMap> hitMap) { + expect(hitMap, isNot(contains(_sampleAppFileUri))); + + final actualHitMap = hitMap[_isolateLibFileUri]; + final actualLineHits = actualHitMap?.lineHits; + final expectedLineHits = { + 11: 1, + 12: 1, + 13: 1, + 15: 0, + 19: 1, + 23: 1, + 24: 2, + 28: 1, + 29: 1, + 30: 1, + 32: 0, + 38: 1, + 39: 1, + 41: 1, + 42: 4, + 43: 1, + 44: 3, + 45: 1, + 48: 1, + 49: 1, + 59: 1, + 60: 1 + }; + + expect(actualLineHits, expectedLineHits); + expect(actualHitMap?.funcHits, isNull); + expect(actualHitMap?.funcNames, isNull); + expect(actualHitMap?.branchHits, isNull); +}
diff --git a/pkgs/coverage/test/test_files/chrome_precise_report.txt b/pkgs/coverage/test/test_files/chrome_precise_report.txt new file mode 100644 index 0000000..41a3e64 --- /dev/null +++ b/pkgs/coverage/test/test_files/chrome_precise_report.txt
@@ -0,0 +1 @@ +[{"scriptId":"5","url":"http://localhost:33587/JvrQonmMf3ATS3rRCO76ZTlBfGvy%2Fj69/packages/test/src/runner/browser/static/host.dart.js","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":598832,"count":1}],"isBlockCoverage":true},{"functionName":"dartProgram","ranges":[{"startOffset":1228,"endOffset":598788,"count":1}],"isBlockCoverage":true},{"functionName":"copyProperties","ranges":[{"startOffset":1255,"endOffset":1430,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1465,"endOffset":2035,"count":1},{"startOffset":1646,"endOffset":1659,"count":0},{"startOffset":1822,"endOffset":1884,"count":0},{"startOffset":1886,"endOffset":1989,"count":0},{"startOffset":1995,"endOffset":2034,"count":0}],"isBlockCoverage":true},{"functionName":"cls","ranges":[{"startOffset":1492,"endOffset":1510,"count":1}],"isBlockCoverage":true},{"functionName":"setFunctionNamesIfNecessary","ranges":[{"startOffset":2041,"endOffset":2464,"count":1},{"startOffset":2168,"endOffset":2460,"count":0}],"isBlockCoverage":true},{"functionName":"t","ranges":[{"startOffset":2093,"endOffset":2113,"count":0}],"isBlockCoverage":false},{"functionName":"inherit","ranges":[{"startOffset":2467,"endOffset":2862,"count":1},{"startOffset":2710,"endOffset":2858,"count":0}],"isBlockCoverage":true},{"functionName":"inheritMany","ranges":[{"startOffset":2865,"endOffset":2982,"count":1}],"isBlockCoverage":true},{"functionName":"mixin","ranges":[{"startOffset":2985,"endOffset":3106,"count":1}],"isBlockCoverage":true},{"functionName":"lazy","ranges":[{"startOffset":3109,"endOffset":3858,"count":1}],"isBlockCoverage":true},{"functionName":"holder.<computed>","ranges":[{"startOffset":3271,"endOffset":3853,"count":1},{"startOffset":3606,"endOffset":3644,"count":0},{"startOffset":3716,"endOffset":3736,"count":0}],"isBlockCoverage":true},{"functionName":"holder.<computed>","ranges":[{"startOffset":3311,"endOffset":3364,"count":0}],"isBlockCoverage":false},{"functionName":"holder.<computed>","ranges":[{"startOffset":3766,"endOffset":3817,"count":1}],"isBlockCoverage":true},{"functionName":"makeConstList","ranges":[{"startOffset":3861,"endOffset":3976,"count":1}],"isBlockCoverage":true},{"functionName":"convertToFastObject","ranges":[{"startOffset":3979,"endOffset":4116,"count":1}],"isBlockCoverage":true},{"functionName":"t","ranges":[{"startOffset":4026,"endOffset":4046,"count":1}],"isBlockCoverage":true},{"functionName":"convertAllToFastObject","ranges":[{"startOffset":4119,"endOffset":4270,"count":1}],"isBlockCoverage":true},{"functionName":"tearOffGetter","ranges":[{"startOffset":4300,"endOffset":5215,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff","ranges":[{"startOffset":5218,"endOffset":5626,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":5357,"endOffset":5539,"count":1}],"isBlockCoverage":true},{"functionName":"installTearOff","ranges":[{"startOffset":5652,"endOffset":6582,"count":1}],"isBlockCoverage":true},{"functionName":"installStaticTearOff","ranges":[{"startOffset":6585,"endOffset":6908,"count":1}],"isBlockCoverage":true},{"functionName":"installInstanceTearOff","ranges":[{"startOffset":6911,"endOffset":7260,"count":1}],"isBlockCoverage":true},{"functionName":"setOrUpdateInterceptorsByTag","ranges":[{"startOffset":7263,"endOffset":7466,"count":1},{"startOffset":7427,"endOffset":7465,"count":0}],"isBlockCoverage":true},{"functionName":"setOrUpdateLeafTags","ranges":[{"startOffset":7469,"endOffset":7645,"count":1},{"startOffset":7606,"endOffset":7644,"count":0}],"isBlockCoverage":true},{"functionName":"updateTypes","ranges":[{"startOffset":7648,"endOffset":7801,"count":0}],"isBlockCoverage":false},{"functionName":"updateHolder","ranges":[{"startOffset":7804,"endOffset":7908,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":7929,"endOffset":9593,"count":1}],"isBlockCoverage":true},{"functionName":"mkInstance","ranges":[{"startOffset":7963,"endOffset":8325,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":8083,"endOffset":8316,"count":1}],"isBlockCoverage":true},{"functionName":"mkStatic","ranges":[{"startOffset":8344,"endOffset":8674,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":8449,"endOffset":8665,"count":1}],"isBlockCoverage":true},{"functionName":"initializeDeferredHunk","ranges":[{"startOffset":9599,"endOffset":9720,"count":0}],"isBlockCoverage":false},{"functionName":"getGlobalFromName","ranges":[{"startOffset":9723,"endOffset":9920,"count":0}],"isBlockCoverage":false},{"functionName":"JS_CONST","ranges":[{"startOffset":9952,"endOffset":9979,"count":0}],"isBlockCoverage":false},{"functionName":"hexDigitValue","ranges":[{"startOffset":10000,"endOffset":10228,"count":1},{"startOffset":10205,"endOffset":10227,"count":0}],"isBlockCoverage":true},{"functionName":"SubListIterable$","ranges":[{"startOffset":10252,"endOffset":10660,"count":0}],"isBlockCoverage":false},{"functionName":"MappedIterable_MappedIterable","ranges":[{"startOffset":10697,"endOffset":11098,"count":0}],"isBlockCoverage":false},{"functionName":"IterableElementError_noElement","ranges":[{"startOffset":11136,"endOffset":11199,"count":0}],"isBlockCoverage":false},{"functionName":"IterableElementError_tooFew","ranges":[{"startOffset":11234,"endOffset":11303,"count":0}],"isBlockCoverage":false},{"functionName":"CodeUnits","ranges":[{"startOffset":11320,"endOffset":11375,"count":0}],"isBlockCoverage":false},{"functionName":"EfficientLengthIterable","ranges":[{"startOffset":11406,"endOffset":11448,"count":0}],"isBlockCoverage":false},{"functionName":"ListIterable","ranges":[{"startOffset":11468,"endOffset":11499,"count":0}],"isBlockCoverage":false},{"functionName":"SubListIterable","ranges":[{"startOffset":11522,"endOffset":11702,"count":0}],"isBlockCoverage":false},{"functionName":"ListIterator","ranges":[{"startOffset":11722,"endOffset":11941,"count":0}],"isBlockCoverage":false},{"functionName":"MappedIterable","ranges":[{"startOffset":11963,"endOffset":12085,"count":0}],"isBlockCoverage":false},{"functionName":"EfficientLengthMappedIterable","ranges":[{"startOffset":12122,"endOffset":12259,"count":0}],"isBlockCoverage":false},{"functionName":"MappedIterator","ranges":[{"startOffset":12281,"endOffset":12439,"count":0}],"isBlockCoverage":false},{"functionName":"MappedListIterable","ranges":[{"startOffset":12465,"endOffset":12578,"count":0}],"isBlockCoverage":false},{"functionName":"WhereIterable","ranges":[{"startOffset":12599,"endOffset":12720,"count":0}],"isBlockCoverage":false},{"functionName":"WhereIterator","ranges":[{"startOffset":12741,"endOffset":12851,"count":0}],"isBlockCoverage":false},{"functionName":"ExpandIterable","ranges":[{"startOffset":12873,"endOffset":12995,"count":0}],"isBlockCoverage":false},{"functionName":"ExpandIterator","ranges":[{"startOffset":13017,"endOffset":13211,"count":0}],"isBlockCoverage":false},{"functionName":"SkipWhileIterable","ranges":[{"startOffset":13236,"endOffset":13361,"count":0}],"isBlockCoverage":false},{"functionName":"SkipWhileIterator","ranges":[{"startOffset":13386,"endOffset":13540,"count":0}],"isBlockCoverage":false},{"functionName":"EmptyIterator","ranges":[{"startOffset":13561,"endOffset":13616,"count":1}],"isBlockCoverage":true},{"functionName":"FixedLengthListMixin","ranges":[{"startOffset":13644,"endOffset":13683,"count":0}],"isBlockCoverage":false},{"functionName":"UnmodifiableListMixin","ranges":[{"startOffset":13712,"endOffset":13752,"count":0}],"isBlockCoverage":false},{"functionName":"UnmodifiableListBase","ranges":[{"startOffset":13780,"endOffset":13819,"count":0}],"isBlockCoverage":false},{"functionName":"ReversedListIterable","ranges":[{"startOffset":13847,"endOffset":13938,"count":0}],"isBlockCoverage":false},{"functionName":"Symbol","ranges":[{"startOffset":13952,"endOffset":14013,"count":1}],"isBlockCoverage":true},{"functionName":"ConstantMap__throwUnmodifiable","ranges":[{"startOffset":14051,"endOffset":14153,"count":0}],"isBlockCoverage":false},{"functionName":"instantiate1","ranges":[{"startOffset":14173,"endOffset":14345,"count":0}],"isBlockCoverage":false},{"functionName":"unminifyOrTag","ranges":[{"startOffset":14366,"endOffset":14570,"count":0}],"isBlockCoverage":false},{"functionName":"getType","ranges":[{"startOffset":14585,"endOffset":14656,"count":1}],"isBlockCoverage":true},{"functionName":"isJsIndexable","ranges":[{"startOffset":14677,"endOffset":14915,"count":0}],"isBlockCoverage":false},{"functionName":"S","ranges":[{"startOffset":14924,"endOffset":15426,"count":1},{"startOffset":15015,"endOffset":15425,"count":0}],"isBlockCoverage":true},{"functionName":"Primitives_objectHashCode","ranges":[{"startOffset":15459,"endOffset":15659,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_parseInt","ranges":[{"startOffset":15686,"endOffset":16847,"count":1},{"startOffset":15821,"endOffset":15869,"count":0},{"startOffset":15981,"endOffset":15988,"count":0},{"startOffset":16026,"endOffset":16051,"count":0},{"startOffset":16201,"endOffset":16328,"count":0},{"startOffset":16338,"endOffset":16456,"count":0},{"startOffset":16466,"endOffset":16539,"count":0},{"startOffset":16541,"endOffset":16846,"count":0}],"isBlockCoverage":true},{"functionName":"Primitives_objectTypeName","ranges":[{"startOffset":16880,"endOffset":17014,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives__objectClassName","ranges":[{"startOffset":17049,"endOffset":18437,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_currentUri","ranges":[{"startOffset":18466,"endOffset":18560,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives__fromCharCodeApply","ranges":[{"startOffset":18597,"endOffset":19022,"count":1},{"startOffset":18798,"endOffset":19021,"count":0}],"isBlockCoverage":true},{"functionName":"Primitives_stringFromCodePoints","ranges":[{"startOffset":19061,"endOffset":19851,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_stringFromCharCodes","ranges":[{"startOffset":19889,"endOffset":20367,"count":1},{"startOffset":20086,"endOffset":20133,"count":0},{"startOffset":20163,"endOffset":20210,"count":0},{"startOffset":20244,"endOffset":20296,"count":0}],"isBlockCoverage":true},{"functionName":"Primitives_stringFromNativeUint8List","ranges":[{"startOffset":20411,"endOffset":20838,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_stringFromCharCode","ranges":[{"startOffset":20875,"endOffset":21388,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_lazyAsJsDate","ranges":[{"startOffset":21419,"endOffset":21566,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_getYear","ranges":[{"startOffset":21592,"endOffset":21708,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_getMonth","ranges":[{"startOffset":21735,"endOffset":21848,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_getDay","ranges":[{"startOffset":21873,"endOffset":21985,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_getHours","ranges":[{"startOffset":22012,"endOffset":22125,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_getMinutes","ranges":[{"startOffset":22154,"endOffset":22269,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_getSeconds","ranges":[{"startOffset":22298,"endOffset":22413,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_getMilliseconds","ranges":[{"startOffset":22447,"endOffset":22567,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_functionNoSuchMethod","ranges":[{"startOffset":22606,"endOffset":23376,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_applyFunction","ranges":[{"startOffset":23408,"endOffset":25001,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives__genericApplyFunction2","ranges":[{"startOffset":25042,"endOffset":28197,"count":0}],"isBlockCoverage":false},{"functionName":"iae","ranges":[{"startOffset":28208,"endOffset":28295,"count":0}],"isBlockCoverage":false},{"functionName":"ioore","ranges":[{"startOffset":28308,"endOffset":28473,"count":0}],"isBlockCoverage":false},{"functionName":"diagnoseIndexError","ranges":[{"startOffset":28499,"endOffset":29047,"count":0}],"isBlockCoverage":false},{"functionName":"diagnoseRangeError","ranges":[{"startOffset":29073,"endOffset":29430,"count":0}],"isBlockCoverage":false},{"functionName":"argumentErrorValue","ranges":[{"startOffset":29456,"endOffset":29540,"count":0}],"isBlockCoverage":false},{"functionName":"checkNum","ranges":[{"startOffset":29556,"endOffset":29696,"count":0}],"isBlockCoverage":false},{"functionName":"wrapException","ranges":[{"startOffset":29717,"endOffset":30104,"count":0}],"isBlockCoverage":false},{"functionName":"toStringWrapper","ranges":[{"startOffset":30127,"endOffset":30193,"count":0}],"isBlockCoverage":false},{"functionName":"throwExpression","ranges":[{"startOffset":30216,"endOffset":30269,"count":0}],"isBlockCoverage":false},{"functionName":"throwConcurrentModificationError","ranges":[{"startOffset":30309,"endOffset":30410,"count":0}],"isBlockCoverage":false},{"functionName":"TypeErrorDecoder_extractPattern","ranges":[{"startOffset":30449,"endOffset":31458,"count":0}],"isBlockCoverage":false},{"functionName":"TypeErrorDecoder_provokeCallErrorOn","ranges":[{"startOffset":31501,"endOffset":31745,"count":0}],"isBlockCoverage":false},{"functionName":"TypeErrorDecoder_provokePropertyErrorOn","ranges":[{"startOffset":31792,"endOffset":31974,"count":0}],"isBlockCoverage":false},{"functionName":"NullError$","ranges":[{"startOffset":31992,"endOffset":32102,"count":0}],"isBlockCoverage":false},{"functionName":"JsNoSuchMethodError$","ranges":[{"startOffset":32130,"endOffset":32326,"count":0}],"isBlockCoverage":false},{"functionName":"unwrapException","ranges":[{"startOffset":32349,"endOffset":36809,"count":0}],"isBlockCoverage":false},{"functionName":"getTraceFromException","ranges":[{"startOffset":36838,"endOffset":37203,"count":0}],"isBlockCoverage":false},{"functionName":"fillLiteralMap","ranges":[{"startOffset":37225,"endOffset":37561,"count":0}],"isBlockCoverage":false},{"functionName":"invokeClosure","ranges":[{"startOffset":37582,"endOffset":38172,"count":1},{"startOffset":37758,"endOffset":37800,"count":0},{"startOffset":37864,"endOffset":37916,"count":0},{"startOffset":37925,"endOffset":37983,"count":0},{"startOffset":37992,"endOffset":38056,"count":0},{"startOffset":38064,"endOffset":38171,"count":0}],"isBlockCoverage":true},{"functionName":"convertDartClosureToJS","ranges":[{"startOffset":38202,"endOffset":38679,"count":1},{"startOffset":38314,"endOffset":38321,"count":0},{"startOffset":38390,"endOffset":38407,"count":0}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":38426,"endOffset":38578,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":38476,"endOffset":38569,"count":1}],"isBlockCoverage":true},{"functionName":"Closure_fromTearOff","ranges":[{"startOffset":38706,"endOffset":41471,"count":1},{"startOffset":39469,"endOffset":39486,"count":0},{"startOffset":40204,"endOffset":40709,"count":0}],"isBlockCoverage":true},{"functionName":"static_tear_off","ranges":[{"startOffset":39300,"endOffset":39368,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":40070,"endOffset":40176,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":40110,"endOffset":40165,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":40461,"endOffset":40599,"count":0}],"isBlockCoverage":false},{"functionName":"Closure_cspForwardCall","ranges":[{"startOffset":41501,"endOffset":42886,"count":1},{"startOffset":41627,"endOffset":41634,"count":0},{"startOffset":41646,"endOffset":41801,"count":0},{"startOffset":41810,"endOffset":41967,"count":0},{"startOffset":41976,"endOffset":42139,"count":0},{"startOffset":42148,"endOffset":42317,"count":0},{"startOffset":42326,"endOffset":42501,"count":0},{"startOffset":42510,"endOffset":42691,"count":0}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":41671,"endOffset":41781,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":41835,"endOffset":41947,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":42001,"endOffset":42119,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":42173,"endOffset":42297,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":42351,"endOffset":42481,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":42535,"endOffset":42671,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":42726,"endOffset":42851,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":42762,"endOffset":42838,"count":0}],"isBlockCoverage":false},{"functionName":"Closure_forwardCallTo","ranges":[{"startOffset":42915,"endOffset":44616,"count":1},{"startOffset":43278,"endOffset":43304,"count":0},{"startOffset":43569,"endOffset":43586,"count":0},{"startOffset":43798,"endOffset":43916,"count":0},{"startOffset":44191,"endOffset":44208,"count":0},{"startOffset":44406,"endOffset":44518,"count":0}],"isBlockCoverage":true},{"functionName":"Closure_cspForwardInterceptedCall","ranges":[{"startOffset":44657,"endOffset":46449,"count":1},{"startOffset":44855,"endOffset":44862,"count":0},{"startOffset":44874,"endOffset":44974,"count":0},{"startOffset":44983,"endOffset":45158,"count":0},{"startOffset":45167,"endOffset":45346,"count":0},{"startOffset":45355,"endOffset":45540,"count":0},{"startOffset":45549,"endOffset":45740,"count":0},{"startOffset":45749,"endOffset":45946,"count":0},{"startOffset":45955,"endOffset":46158,"count":0}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":45008,"endOffset":45128,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":45192,"endOffset":45316,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":45380,"endOffset":45510,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":45574,"endOffset":45710,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":45774,"endOffset":45916,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":45980,"endOffset":46128,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":46193,"endOffset":46401,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":46235,"endOffset":46388,"count":0}],"isBlockCoverage":false},{"functionName":"Closure_forwardInterceptedCallTo","ranges":[{"startOffset":46489,"endOffset":48059,"count":1},{"startOffset":47112,"endOffset":47138,"count":0},{"startOffset":47326,"endOffset":47636,"count":0},{"startOffset":47950,"endOffset":47967,"count":0}],"isBlockCoverage":true},{"functionName":"closureFromTearOff","ranges":[{"startOffset":48085,"endOffset":48339,"count":1}],"isBlockCoverage":true},{"functionName":"BoundClosure_selfOf","ranges":[{"startOffset":48366,"endOffset":48419,"count":0}],"isBlockCoverage":false},{"functionName":"BoundClosure_receiverOf","ranges":[{"startOffset":48450,"endOffset":48507,"count":0}],"isBlockCoverage":false},{"functionName":"BoundClosure_computeFieldNamed","ranges":[{"startOffset":48545,"endOffset":48918,"count":1}],"isBlockCoverage":true},{"functionName":"stringTypeCheck","ranges":[{"startOffset":48941,"endOffset":49144,"count":1},{"startOffset":48992,"endOffset":49005,"count":0},{"startOffset":49064,"endOffset":49143,"count":0}],"isBlockCoverage":true},{"functionName":"stringTypeCast","ranges":[{"startOffset":49166,"endOffset":49339,"count":1},{"startOffset":49220,"endOffset":49236,"count":0},{"startOffset":49259,"endOffset":49338,"count":0}],"isBlockCoverage":true},{"functionName":"doubleTypeCheck","ranges":[{"startOffset":49362,"endOffset":49565,"count":0}],"isBlockCoverage":false},{"functionName":"numTypeCheck","ranges":[{"startOffset":49585,"endOffset":49785,"count":0}],"isBlockCoverage":false},{"functionName":"boolTypeCheck","ranges":[{"startOffset":49806,"endOffset":50008,"count":0}],"isBlockCoverage":false},{"functionName":"intTypeCheck","ranges":[{"startOffset":50028,"endOffset":50259,"count":1},{"startOffset":50079,"endOffset":50092,"count":0},{"startOffset":50182,"endOffset":50258,"count":0}],"isBlockCoverage":true},{"functionName":"intTypeCast","ranges":[{"startOffset":50278,"endOffset":50479,"count":1},{"startOffset":50363,"endOffset":50379,"count":0},{"startOffset":50402,"endOffset":50478,"count":0}],"isBlockCoverage":true},{"functionName":"propertyTypeError","ranges":[{"startOffset":50504,"endOffset":50660,"count":0}],"isBlockCoverage":false},{"functionName":"interceptedTypeCheck","ranges":[{"startOffset":50688,"endOffset":50942,"count":1},{"startOffset":50800,"endOffset":50830,"count":0},{"startOffset":50892,"endOffset":50941,"count":0}],"isBlockCoverage":true},{"functionName":"stringSuperNativeTypeCheck","ranges":[{"startOffset":50976,"endOffset":51227,"count":0}],"isBlockCoverage":false},{"functionName":"listTypeCheck","ranges":[{"startOffset":51248,"endOffset":51467,"count":1},{"startOffset":51380,"endOffset":51466,"count":0}],"isBlockCoverage":true},{"functionName":"listSuperNativeTypeCheck","ranges":[{"startOffset":51499,"endOffset":51766,"count":0}],"isBlockCoverage":false},{"functionName":"extractFunctionTypeObjectFromInternal","ranges":[{"startOffset":51811,"endOffset":52082,"count":1},{"startOffset":52062,"endOffset":52081,"count":0}],"isBlockCoverage":true},{"functionName":"functionTypeTest","ranges":[{"startOffset":52106,"endOffset":52520,"count":1},{"startOffset":52204,"endOffset":52217,"count":0},{"startOffset":52417,"endOffset":52430,"count":0}],"isBlockCoverage":true},{"functionName":"functionTypeCheck","ranges":[{"startOffset":52545,"endOffset":53038,"count":1},{"startOffset":52686,"endOffset":52699,"count":0},{"startOffset":52824,"endOffset":52979,"count":0}],"isBlockCoverage":true},{"functionName":"futureOrCheck","ranges":[{"startOffset":53059,"endOffset":53270,"count":1},{"startOffset":53106,"endOffset":53153,"count":0},{"startOffset":53163,"endOffset":53248,"count":0}],"isBlockCoverage":true},{"functionName":"TypeErrorImplementation$","ranges":[{"startOffset":53302,"endOffset":53507,"count":0}],"isBlockCoverage":false},{"functionName":"CastErrorImplementation$","ranges":[{"startOffset":53539,"endOffset":53744,"count":0}],"isBlockCoverage":false},{"functionName":"_typeDescription","ranges":[{"startOffset":53768,"endOffset":54148,"count":0}],"isBlockCoverage":false},{"functionName":"throwCyclicInit","ranges":[{"startOffset":54171,"endOffset":54292,"count":0}],"isBlockCoverage":false},{"functionName":"RuntimeError$","ranges":[{"startOffset":54313,"endOffset":54380,"count":0}],"isBlockCoverage":false},{"functionName":"getIsolateAffinityTag","ranges":[{"startOffset":54409,"endOffset":54472,"count":1}],"isBlockCoverage":true},{"functionName":"setRuntimeTypeInfo","ranges":[{"startOffset":54498,"endOffset":54572,"count":1}],"isBlockCoverage":true},{"functionName":"getRuntimeTypeInfo","ranges":[{"startOffset":54598,"endOffset":54689,"count":1},{"startOffset":54651,"endOffset":54658,"count":0}],"isBlockCoverage":true},{"functionName":"getRuntimeTypeArguments","ranges":[{"startOffset":54720,"endOffset":54876,"count":0}],"isBlockCoverage":false},{"functionName":"getRuntimeTypeArgumentIntercepted","ranges":[{"startOffset":54917,"endOffset":55240,"count":1},{"startOffset":55207,"endOffset":55213,"count":0}],"isBlockCoverage":true},{"functionName":"getRuntimeTypeArgument","ranges":[{"startOffset":55270,"endOffset":55575,"count":1},{"startOffset":55542,"endOffset":55548,"count":0}],"isBlockCoverage":true},{"functionName":"getTypeArgumentByIndex","ranges":[{"startOffset":55605,"endOffset":55768,"count":1}],"isBlockCoverage":true},{"functionName":"runtimeTypeToString","ranges":[{"startOffset":55795,"endOffset":55864,"count":0}],"isBlockCoverage":false},{"functionName":"_runtimeTypeToString","ranges":[{"startOffset":55892,"endOffset":57053,"count":0}],"isBlockCoverage":false},{"functionName":"_functionRtiToString","ranges":[{"startOffset":57081,"endOffset":59945,"count":0}],"isBlockCoverage":false},{"functionName":"_joinArguments","ranges":[{"startOffset":59967,"endOffset":60636,"count":0}],"isBlockCoverage":false},{"functionName":"substitute","ranges":[{"startOffset":60654,"endOffset":61121,"count":1},{"startOffset":60849,"endOffset":60856,"count":0},{"startOffset":60992,"endOffset":61120,"count":0}],"isBlockCoverage":true},{"functionName":"checkSubtype","ranges":[{"startOffset":61141,"endOffset":61627,"count":1},{"startOffset":61512,"endOffset":61525,"count":0}],"isBlockCoverage":true},{"functionName":"assertSubtype","ranges":[{"startOffset":61648,"endOffset":62224,"count":1},{"startOffset":61923,"endOffset":62223,"count":0}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":61987,"endOffset":62115,"count":0}],"isBlockCoverage":false},{"functionName":"assertIsSubtype","ranges":[{"startOffset":62247,"endOffset":62611,"count":1},{"startOffset":62464,"endOffset":62605,"count":0}],"isBlockCoverage":true},{"functionName":"throwTypeError","ranges":[{"startOffset":62633,"endOffset":62746,"count":0}],"isBlockCoverage":false},{"functionName":"areSubtypes","ranges":[{"startOffset":62765,"endOffset":63196,"count":1},{"startOffset":62841,"endOffset":62853,"count":0},{"startOffset":62875,"endOffset":63042,"count":0},{"startOffset":63158,"endOffset":63171,"count":0}],"isBlockCoverage":true},{"functionName":"computeSignature","ranges":[{"startOffset":63220,"endOffset":63407,"count":0}],"isBlockCoverage":false},{"functionName":"isSupertypeOfNullRecursive","ranges":[{"startOffset":63441,"endOffset":63818,"count":0}],"isBlockCoverage":false},{"functionName":"checkSubtypeOfRuntimeType","ranges":[{"startOffset":63851,"endOffset":64616,"count":1},{"startOffset":63918,"endOffset":64038,"count":0},{"startOffset":64201,"endOffset":64290,"count":0}],"isBlockCoverage":true},{"functionName":"assertSubtypeOfRuntimeType","ranges":[{"startOffset":64650,"endOffset":64869,"count":1},{"startOffset":64755,"endOffset":64842,"count":0}],"isBlockCoverage":true},{"functionName":"_isSubtype","ranges":[{"startOffset":64887,"endOffset":67156,"count":1},{"startOffset":65190,"endOffset":65202,"count":0},{"startOffset":65318,"endOffset":65331,"count":0},{"startOffset":65421,"endOffset":65427,"count":0},{"startOffset":65435,"endOffset":65465,"count":0},{"startOffset":65507,"endOffset":65520,"count":0},{"startOffset":65562,"endOffset":65575,"count":0},{"startOffset":65945,"endOffset":65951,"count":0},{"startOffset":65992,"endOffset":66068,"count":0},{"startOffset":66152,"endOffset":66605,"count":0},{"startOffset":66860,"endOffset":66873,"count":0},{"startOffset":67044,"endOffset":67050,"count":0}],"isBlockCoverage":true},{"functionName":"_isFunctionSubtype","ranges":[{"startOffset":67182,"endOffset":69335,"count":1},{"startOffset":67490,"endOffset":67503,"count":0},{"startOffset":67571,"endOffset":67584,"count":0},{"startOffset":67698,"endOffset":67711,"count":0},{"startOffset":67752,"endOffset":67765,"count":0},{"startOffset":67825,"endOffset":67838,"count":0},{"startOffset":68299,"endOffset":68331,"count":0},{"startOffset":68388,"endOffset":68401,"count":0},{"startOffset":68503,"endOffset":68516,"count":0},{"startOffset":68659,"endOffset":68672,"count":0},{"startOffset":68848,"endOffset":68861,"count":0},{"startOffset":68938,"endOffset":69054,"count":0},{"startOffset":69179,"endOffset":69334,"count":0}],"isBlockCoverage":true},{"functionName":"namedParametersSubtypeCheck","ranges":[{"startOffset":69370,"endOffset":69743,"count":0}],"isBlockCoverage":false},{"functionName":"instantiatedGenericFunctionType","ranges":[{"startOffset":69782,"endOffset":69981,"count":0}],"isBlockCoverage":false},{"functionName":"finishBindInstantiatedFunctionType","ranges":[{"startOffset":70023,"endOffset":70893,"count":0}],"isBlockCoverage":false},{"functionName":"bindInstantiatedType","ranges":[{"startOffset":70921,"endOffset":71830,"count":0}],"isBlockCoverage":false},{"functionName":"bindInstantiatedTypes","ranges":[{"startOffset":71859,"endOffset":72120,"count":0}],"isBlockCoverage":false},{"functionName":"JsLinkedHashMap_JsLinkedHashMap$es6","ranges":[{"startOffset":72163,"endOffset":72233,"count":1}],"isBlockCoverage":true},{"functionName":"defineProperty","ranges":[{"startOffset":72255,"endOffset":72427,"count":0}],"isBlockCoverage":false},{"functionName":"lookupAndCacheInterceptor","ranges":[{"startOffset":72460,"endOffset":74952,"count":0}],"isBlockCoverage":false},{"functionName":"patchInteriorProto","ranges":[{"startOffset":74978,"endOffset":75265,"count":0}],"isBlockCoverage":false},{"functionName":"makeLeafDispatchRecord","ranges":[{"startOffset":75295,"endOffset":75430,"count":1}],"isBlockCoverage":true},{"functionName":"makeDefaultDispatchRecord","ranges":[{"startOffset":75463,"endOffset":75734,"count":1}],"isBlockCoverage":true},{"functionName":"initNativeDispatch","ranges":[{"startOffset":75760,"endOffset":75916,"count":1},{"startOffset":75826,"endOffset":75833,"count":0}],"isBlockCoverage":true},{"functionName":"initNativeDispatchContinue","ranges":[{"startOffset":75950,"endOffset":77230,"count":1}],"isBlockCoverage":true},{"functionName":"fun","ranges":[{"startOffset":76329,"endOffset":76351,"count":0}],"isBlockCoverage":false},{"functionName":"initHooks","ranges":[{"startOffset":77247,"endOffset":78506,"count":1},{"startOffset":77761,"endOffset":78174,"count":0}],"isBlockCoverage":true},{"functionName":"applyHooksTransformer","ranges":[{"startOffset":78535,"endOffset":78613,"count":1}],"isBlockCoverage":true},{"functionName":"JSSyntaxRegExp_makeNative","ranges":[{"startOffset":78646,"endOffset":79188,"count":0}],"isBlockCoverage":false},{"functionName":"stringContainsUnchecked","ranges":[{"startOffset":79219,"endOffset":79767,"count":0}],"isBlockCoverage":false},{"functionName":"stringReplaceFirstRE","ranges":[{"startOffset":79795,"endOffset":80070,"count":0}],"isBlockCoverage":false},{"functionName":"stringReplaceAllUnchecked","ranges":[{"startOffset":80103,"endOffset":81120,"count":0}],"isBlockCoverage":false},{"functionName":"stringReplaceFirstUnchecked","ranges":[{"startOffset":81155,"endOffset":82205,"count":0}],"isBlockCoverage":false},{"functionName":"stringReplaceRangeUnchecked","ranges":[{"startOffset":82240,"endOffset":82446,"count":0}],"isBlockCoverage":false},{"functionName":"ConstantMapView","ranges":[{"startOffset":82469,"endOffset":82552,"count":0}],"isBlockCoverage":false},{"functionName":"ConstantMap","ranges":[{"startOffset":82571,"endOffset":82601,"count":0}],"isBlockCoverage":false},{"functionName":"ConstantStringMap","ranges":[{"startOffset":82626,"endOffset":82792,"count":1}],"isBlockCoverage":true},{"functionName":"Instantiation","ranges":[{"startOffset":82813,"endOffset":82845,"count":0}],"isBlockCoverage":false},{"functionName":"Instantiation1","ranges":[{"startOffset":82867,"endOffset":82960,"count":0}],"isBlockCoverage":false},{"functionName":"JSInvocationMirror","ranges":[{"startOffset":82986,"endOffset":83199,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_functionNoSuchMethod_closure","ranges":[{"startOffset":83246,"endOffset":83401,"count":0}],"isBlockCoverage":false},{"functionName":"TypeErrorDecoder","ranges":[{"startOffset":83425,"endOffset":83645,"count":0}],"isBlockCoverage":false},{"functionName":"NullError","ranges":[{"startOffset":83662,"endOffset":83747,"count":0}],"isBlockCoverage":false},{"functionName":"JsNoSuchMethodError","ranges":[{"startOffset":83774,"endOffset":83900,"count":0}],"isBlockCoverage":false},{"functionName":"UnknownJsTypeError","ranges":[{"startOffset":83926,"endOffset":83991,"count":0}],"isBlockCoverage":false},{"functionName":"ExceptionAndStackTrace","ranges":[{"startOffset":84021,"endOffset":84127,"count":0}],"isBlockCoverage":false},{"functionName":"unwrapException_saveStackTrace","ranges":[{"startOffset":84165,"endOffset":84236,"count":0}],"isBlockCoverage":false},{"functionName":"_StackTrace","ranges":[{"startOffset":84255,"endOffset":84353,"count":0}],"isBlockCoverage":false},{"functionName":"Closure","ranges":[{"startOffset":84368,"endOffset":84394,"count":0}],"isBlockCoverage":false},{"functionName":"TearOffClosure","ranges":[{"startOffset":84416,"endOffset":84449,"count":0}],"isBlockCoverage":false},{"functionName":"StaticClosure","ranges":[{"startOffset":84470,"endOffset":84502,"count":1}],"isBlockCoverage":true},{"functionName":"BoundClosure","ranges":[{"startOffset":84522,"endOffset":84673,"count":1}],"isBlockCoverage":true},{"functionName":"TypeErrorImplementation","ranges":[{"startOffset":84704,"endOffset":84773,"count":0}],"isBlockCoverage":false},{"functionName":"CastErrorImplementation","ranges":[{"startOffset":84804,"endOffset":84873,"count":0}],"isBlockCoverage":false},{"functionName":"RuntimeError","ranges":[{"startOffset":84893,"endOffset":84951,"count":0}],"isBlockCoverage":false},{"functionName":"TypeImpl","ranges":[{"startOffset":84967,"endOffset":85065,"count":0}],"isBlockCoverage":false},{"functionName":"JsLinkedHashMap","ranges":[{"startOffset":85088,"endOffset":85289,"count":1}],"isBlockCoverage":true},{"functionName":"JsLinkedHashMap_values_closure","ranges":[{"startOffset":85327,"endOffset":85401,"count":0}],"isBlockCoverage":false},{"functionName":"LinkedHashMapCell","ranges":[{"startOffset":85426,"endOffset":85584,"count":1}],"isBlockCoverage":true},{"functionName":"LinkedHashMapKeyIterable","ranges":[{"startOffset":85616,"endOffset":85720,"count":0}],"isBlockCoverage":false},{"functionName":"LinkedHashMapKeyIterator","ranges":[{"startOffset":85752,"endOffset":85950,"count":0}],"isBlockCoverage":false},{"functionName":"initHooks_closure","ranges":[{"startOffset":85975,"endOffset":86037,"count":1}],"isBlockCoverage":true},{"functionName":"initHooks_closure0","ranges":[{"startOffset":86063,"endOffset":86133,"count":1}],"isBlockCoverage":true},{"functionName":"initHooks_closure1","ranges":[{"startOffset":86159,"endOffset":86231,"count":1}],"isBlockCoverage":true},{"functionName":"JSSyntaxRegExp","ranges":[{"startOffset":86253,"endOffset":86424,"count":0}],"isBlockCoverage":false},{"functionName":"_MatchImplementation","ranges":[{"startOffset":86452,"endOffset":86517,"count":0}],"isBlockCoverage":false},{"functionName":"_AllMatchesIterable","ranges":[{"startOffset":86544,"endOffset":86674,"count":0}],"isBlockCoverage":false},{"functionName":"_AllMatchesIterator","ranges":[{"startOffset":86701,"endOffset":86887,"count":0}],"isBlockCoverage":false},{"functionName":"StringMatch","ranges":[{"startOffset":86906,"endOffset":86990,"count":0}],"isBlockCoverage":false},{"functionName":"_StringAllMatchesIterable","ranges":[{"startOffset":87023,"endOffset":87163,"count":0}],"isBlockCoverage":false},{"functionName":"_StringAllMatchesIterator","ranges":[{"startOffset":87196,"endOffset":87384,"count":0}],"isBlockCoverage":false},{"functionName":"_ensureNativeList","ranges":[{"startOffset":87409,"endOffset":87450,"count":0}],"isBlockCoverage":false},{"functionName":"NativeInt8List__create1","ranges":[{"startOffset":87481,"endOffset":87535,"count":0}],"isBlockCoverage":false},{"functionName":"_checkValidIndex","ranges":[{"startOffset":87559,"endOffset":87716,"count":1},{"startOffset":87653,"endOffset":87710,"count":0}],"isBlockCoverage":true},{"functionName":"_checkValidRange","ranges":[{"startOffset":87740,"endOffset":88027,"count":0}],"isBlockCoverage":false},{"functionName":"NativeByteBuffer","ranges":[{"startOffset":88051,"endOffset":88086,"count":0}],"isBlockCoverage":false},{"functionName":"NativeTypedData","ranges":[{"startOffset":88109,"endOffset":88143,"count":0}],"isBlockCoverage":false},{"functionName":"NativeTypedArray","ranges":[{"startOffset":88167,"endOffset":88202,"count":0}],"isBlockCoverage":false},{"functionName":"NativeTypedArrayOfDouble","ranges":[{"startOffset":88234,"endOffset":88277,"count":0}],"isBlockCoverage":false},{"functionName":"NativeTypedArrayOfInt","ranges":[{"startOffset":88306,"endOffset":88346,"count":0}],"isBlockCoverage":false},{"functionName":"NativeInt16List","ranges":[{"startOffset":88369,"endOffset":88403,"count":0}],"isBlockCoverage":false},{"functionName":"NativeInt32List","ranges":[{"startOffset":88426,"endOffset":88460,"count":0}],"isBlockCoverage":false},{"functionName":"NativeInt8List","ranges":[{"startOffset":88482,"endOffset":88515,"count":0}],"isBlockCoverage":false},{"functionName":"NativeUint16List","ranges":[{"startOffset":88539,"endOffset":88574,"count":0}],"isBlockCoverage":false},{"functionName":"NativeUint32List","ranges":[{"startOffset":88598,"endOffset":88633,"count":0}],"isBlockCoverage":false},{"functionName":"NativeUint8ClampedList","ranges":[{"startOffset":88663,"endOffset":88704,"count":0}],"isBlockCoverage":false},{"functionName":"NativeUint8List","ranges":[{"startOffset":88727,"endOffset":88761,"count":0}],"isBlockCoverage":false},{"functionName":"_NativeTypedArrayOfDouble_NativeTypedArray_ListMixin","ranges":[{"startOffset":88821,"endOffset":88892,"count":0}],"isBlockCoverage":false},{"functionName":"_NativeTypedArrayOfDouble_NativeTypedArray_ListMixin_FixedLengthListMixin","ranges":[{"startOffset":88973,"endOffset":89065,"count":0}],"isBlockCoverage":false},{"functionName":"_NativeTypedArrayOfInt_NativeTypedArray_ListMixin","ranges":[{"startOffset":89122,"endOffset":89190,"count":0}],"isBlockCoverage":false},{"functionName":"_NativeTypedArrayOfInt_NativeTypedArray_ListMixin_FixedLengthListMixin","ranges":[{"startOffset":89268,"endOffset":89357,"count":0}],"isBlockCoverage":false},{"functionName":"extractKeys","ranges":[{"startOffset":89376,"endOffset":89483,"count":0}],"isBlockCoverage":false},{"functionName":"printString","ranges":[{"startOffset":89502,"endOffset":89949,"count":0}],"isBlockCoverage":false},{"functionName":"makeDispatchRecord","ranges":[{"startOffset":89987,"endOffset":90120,"count":1}],"isBlockCoverage":true},{"functionName":"getNativeInterceptor","ranges":[{"startOffset":90148,"endOffset":91834,"count":1},{"startOffset":90602,"endOffset":90616,"count":0},{"startOffset":90731,"endOffset":90881,"count":0},{"startOffset":90889,"endOffset":90978,"count":0},{"startOffset":90979,"endOffset":91030,"count":0},{"startOffset":91071,"endOffset":91833,"count":0}],"isBlockCoverage":true},{"functionName":"JSArray_JSArray$fixed","ranges":[{"startOffset":91863,"endOffset":92096,"count":0}],"isBlockCoverage":false},{"functionName":"JSArray_JSArray$markFixed","ranges":[{"startOffset":92129,"endOffset":92239,"count":0}],"isBlockCoverage":false},{"functionName":"JSArray_markFixedList","ranges":[{"startOffset":92268,"endOffset":92371,"count":1}],"isBlockCoverage":true},{"functionName":"JSArray_markUnmodifiableList","ranges":[{"startOffset":92407,"endOffset":92516,"count":0}],"isBlockCoverage":false},{"functionName":"JSString__isWhitespace","ranges":[{"startOffset":92546,"endOffset":93301,"count":0}],"isBlockCoverage":false},{"functionName":"JSString__skipLeadingWhitespace","ranges":[{"startOffset":93340,"endOffset":93658,"count":0}],"isBlockCoverage":false},{"functionName":"JSString__skipTrailingWhitespace","ranges":[{"startOffset":93698,"endOffset":94027,"count":0}],"isBlockCoverage":false},{"functionName":"getInterceptor$","ranges":[{"startOffset":94050,"endOffset":94813,"count":1},{"startOffset":94193,"endOffset":94238,"count":0},{"startOffset":94426,"endOffset":94452,"count":0},{"startOffset":94569,"endOffset":94695,"count":0}],"isBlockCoverage":true},{"functionName":"getInterceptor$ansx","ranges":[{"startOffset":94840,"endOffset":95426,"count":0}],"isBlockCoverage":false},{"functionName":"getInterceptor$asx","ranges":[{"startOffset":95452,"endOffset":95962,"count":1},{"startOffset":95520,"endOffset":95548,"count":0},{"startOffset":95585,"endOffset":95601,"count":0},{"startOffset":95718,"endOffset":95844,"count":0},{"startOffset":95909,"endOffset":95961,"count":0}],"isBlockCoverage":true},{"functionName":"getInterceptor$ax","ranges":[{"startOffset":95987,"endOffset":96421,"count":1},{"startOffset":96044,"endOffset":96060,"count":0},{"startOffset":96177,"endOffset":96303,"count":0},{"startOffset":96368,"endOffset":96420,"count":0}],"isBlockCoverage":true},{"functionName":"getInterceptor$n","ranges":[{"startOffset":96445,"endOffset":96718,"count":0}],"isBlockCoverage":false},{"functionName":"getInterceptor$s","ranges":[{"startOffset":96742,"endOffset":97015,"count":1},{"startOffset":96838,"endOffset":97014,"count":0}],"isBlockCoverage":true},{"functionName":"getInterceptor$x","ranges":[{"startOffset":97039,"endOffset":97396,"count":1},{"startOffset":97096,"endOffset":97112,"count":0},{"startOffset":97152,"endOffset":97278,"count":0}],"isBlockCoverage":true},{"functionName":"get$hashCode$","ranges":[{"startOffset":97417,"endOffset":97508,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator$ax","ranges":[{"startOffset":97531,"endOffset":97624,"count":0}],"isBlockCoverage":false},{"functionName":"get$length$asx","ranges":[{"startOffset":97646,"endOffset":97738,"count":1}],"isBlockCoverage":true},{"functionName":"get$onClick$x","ranges":[{"startOffset":97759,"endOffset":97850,"count":1}],"isBlockCoverage":true},{"functionName":"$add$ansx","ranges":[{"startOffset":97867,"endOffset":98056,"count":0}],"isBlockCoverage":false},{"functionName":"$eq$","ranges":[{"startOffset":98068,"endOffset":98298,"count":1},{"startOffset":98129,"endOffset":98147,"count":0},{"startOffset":98232,"endOffset":98297,"count":0}],"isBlockCoverage":true},{"functionName":"$gt$n","ranges":[{"startOffset":98311,"endOffset":98496,"count":1},{"startOffset":98429,"endOffset":98495,"count":0}],"isBlockCoverage":true},{"functionName":"$index$asx","ranges":[{"startOffset":98514,"endOffset":98872,"count":1},{"startOffset":98581,"endOffset":98800,"count":0}],"isBlockCoverage":true},{"functionName":"$indexSet$ax","ranges":[{"startOffset":98892,"endOffset":98998,"count":1}],"isBlockCoverage":true},{"functionName":"_codeUnitAt$1$s","ranges":[{"startOffset":99021,"endOffset":99122,"count":1}],"isBlockCoverage":true},{"functionName":"_removeChild$1$x","ranges":[{"startOffset":99146,"endOffset":99248,"count":0}],"isBlockCoverage":false},{"functionName":"_removeEventListener$3$x","ranges":[{"startOffset":99280,"endOffset":99406,"count":0}],"isBlockCoverage":false},{"functionName":"addEventListener$3$x","ranges":[{"startOffset":99434,"endOffset":99556,"count":1}],"isBlockCoverage":true},{"functionName":"codeUnitAt$1$s","ranges":[{"startOffset":99578,"endOffset":99678,"count":0}],"isBlockCoverage":false},{"functionName":"contains$1$asx","ranges":[{"startOffset":99700,"endOffset":99800,"count":0}],"isBlockCoverage":false},{"functionName":"elementAt$1$ax","ranges":[{"startOffset":99822,"endOffset":99922,"count":0}],"isBlockCoverage":false},{"functionName":"endsWith$1$s","ranges":[{"startOffset":99942,"endOffset":100040,"count":0}],"isBlockCoverage":false},{"functionName":"fillRange$3$x","ranges":[{"startOffset":100061,"endOffset":100176,"count":1}],"isBlockCoverage":true},{"functionName":"indexOf$2$s","ranges":[{"startOffset":100195,"endOffset":100300,"count":0}],"isBlockCoverage":false},{"functionName":"matchAsPrefix$2$s","ranges":[{"startOffset":100325,"endOffset":100436,"count":0}],"isBlockCoverage":false},{"functionName":"noSuchMethod$1$","ranges":[{"startOffset":100459,"endOffset":100560,"count":0}],"isBlockCoverage":false},{"functionName":"padRight$1$s","ranges":[{"startOffset":100580,"endOffset":100678,"count":0}],"isBlockCoverage":false},{"functionName":"postMessage$3$x","ranges":[{"startOffset":100701,"endOffset":100818,"count":1}],"isBlockCoverage":true},{"functionName":"replaceFirst$2$s","ranges":[{"startOffset":100842,"endOffset":100952,"count":0}],"isBlockCoverage":false},{"functionName":"replaceRange$3$asx","ranges":[{"startOffset":100978,"endOffset":101098,"count":0}],"isBlockCoverage":false},{"functionName":"startsWith$1$s","ranges":[{"startOffset":101120,"endOffset":101220,"count":0}],"isBlockCoverage":false},{"functionName":"startsWith$2$s","ranges":[{"startOffset":101242,"endOffset":101350,"count":0}],"isBlockCoverage":false},{"functionName":"substring$1$s","ranges":[{"startOffset":101371,"endOffset":101470,"count":0}],"isBlockCoverage":false},{"functionName":"substring$2$s","ranges":[{"startOffset":101491,"endOffset":101598,"count":1}],"isBlockCoverage":true},{"functionName":"toString$0$","ranges":[{"startOffset":101617,"endOffset":101706,"count":0}],"isBlockCoverage":false},{"functionName":"trim$0$s","ranges":[{"startOffset":101722,"endOffset":101808,"count":0}],"isBlockCoverage":false},{"functionName":"waitUntilDone$0$x","ranges":[{"startOffset":101833,"endOffset":101928,"count":0}],"isBlockCoverage":false},{"functionName":"Interceptor","ranges":[{"startOffset":101947,"endOffset":101977,"count":0}],"isBlockCoverage":false},{"functionName":"JSBool","ranges":[{"startOffset":101991,"endOffset":102016,"count":0}],"isBlockCoverage":false},{"functionName":"JSNull","ranges":[{"startOffset":102030,"endOffset":102055,"count":0}],"isBlockCoverage":false},{"functionName":"JavaScriptObject","ranges":[{"startOffset":102079,"endOffset":102114,"count":0}],"isBlockCoverage":false},{"functionName":"PlainJavaScriptObject","ranges":[{"startOffset":102143,"endOffset":102183,"count":0}],"isBlockCoverage":false},{"functionName":"UnknownJavaScriptObject","ranges":[{"startOffset":102214,"endOffset":102256,"count":0}],"isBlockCoverage":false},{"functionName":"JavaScriptFunction","ranges":[{"startOffset":102282,"endOffset":102319,"count":0}],"isBlockCoverage":false},{"functionName":"JSArray","ranges":[{"startOffset":102334,"endOffset":102383,"count":0}],"isBlockCoverage":true},{"functionName":"JSUnmodifiableArray","ranges":[{"startOffset":102410,"endOffset":102471,"count":0}],"isBlockCoverage":false},{"functionName":"ArrayIterator","ranges":[{"startOffset":102492,"endOffset":102698,"count":0}],"isBlockCoverage":false},{"functionName":"JSNumber","ranges":[{"startOffset":102714,"endOffset":102741,"count":0}],"isBlockCoverage":false},{"functionName":"JSInt","ranges":[{"startOffset":102754,"endOffset":102778,"count":0}],"isBlockCoverage":true},{"functionName":"JSDouble","ranges":[{"startOffset":102794,"endOffset":102821,"count":0}],"isBlockCoverage":false},{"functionName":"JSString","ranges":[{"startOffset":102837,"endOffset":102864,"count":0}],"isBlockCoverage":true},{"functionName":"_AsyncRun__initializeScheduleImmediate","ranges":[{"startOffset":102922,"endOffset":103739,"count":1},{"startOffset":103025,"endOffset":103089,"count":0},{"startOffset":103548,"endOffset":103738,"count":0}],"isBlockCoverage":true},{"functionName":"_AsyncRun__scheduleImmediateJsOverride","ranges":[{"startOffset":103785,"endOffset":103984,"count":0}],"isBlockCoverage":false},{"functionName":"_AsyncRun__scheduleImmediateWithSetImmediate","ranges":[{"startOffset":104036,"endOffset":104236,"count":0}],"isBlockCoverage":false},{"functionName":"_AsyncRun__scheduleImmediateWithTimer","ranges":[{"startOffset":104281,"endOffset":104400,"count":0}],"isBlockCoverage":false},{"functionName":"Timer__createTimer","ranges":[{"startOffset":104426,"endOffset":104694,"count":0}],"isBlockCoverage":false},{"functionName":"Timer__createPeriodicTimer","ranges":[{"startOffset":104728,"endOffset":105021,"count":1},{"startOffset":104985,"endOffset":104988,"count":0}],"isBlockCoverage":true},{"functionName":"_TimerImpl$","ranges":[{"startOffset":105040,"endOffset":105179,"count":0}],"isBlockCoverage":false},{"functionName":"_TimerImpl$periodic","ranges":[{"startOffset":105206,"endOffset":105354,"count":1}],"isBlockCoverage":true},{"functionName":"_makeAsyncAwaitCompleter","ranges":[{"startOffset":105386,"endOffset":105529,"count":1}],"isBlockCoverage":true},{"functionName":"_asyncStartSync","ranges":[{"startOffset":105552,"endOffset":105848,"count":1}],"isBlockCoverage":true},{"functionName":"_asyncAwait","ranges":[{"startOffset":105867,"endOffset":106009,"count":1}],"isBlockCoverage":true},{"functionName":"_asyncReturn","ranges":[{"startOffset":106029,"endOffset":106143,"count":1}],"isBlockCoverage":true},{"functionName":"_asyncRethrow","ranges":[{"startOffset":106164,"endOffset":106332,"count":0}],"isBlockCoverage":false},{"functionName":"_awaitOnObject","ranges":[{"startOffset":106354,"endOffset":107170,"count":1},{"startOffset":106791,"endOffset":107164,"count":0}],"isBlockCoverage":true},{"functionName":"_wrapJsFunctionForAsync","ranges":[{"startOffset":107201,"endOffset":107687,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":107246,"endOffset":107537,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":107283,"endOffset":107528,"count":1},{"startOffset":107425,"endOffset":107518,"count":0}],"isBlockCoverage":true},{"functionName":"_Future$zoneValue","ranges":[{"startOffset":107712,"endOffset":107914,"count":0}],"isBlockCoverage":false},{"functionName":"_Future__chainForeignFuture","ranges":[{"startOffset":107949,"endOffset":108400,"count":0}],"isBlockCoverage":false},{"functionName":"_Future__chainCoreFuture","ranges":[{"startOffset":108432,"endOffset":109081,"count":0}],"isBlockCoverage":false},{"functionName":"_Future__propagateToListeners","ranges":[{"startOffset":109118,"endOffset":112741,"count":1},{"startOffset":109462,"endOffset":109649,"count":0},{"startOffset":110172,"endOffset":110183,"count":0},{"startOffset":110194,"endOffset":110220,"count":0},{"startOffset":110323,"endOffset":110467,"count":0},{"startOffset":110515,"endOffset":110754,"count":0},{"startOffset":110835,"endOffset":110858,"count":0},{"startOffset":110970,"endOffset":111079,"count":0},{"startOffset":111261,"endOffset":111383,"count":0},{"startOffset":111427,"endOffset":111453,"count":0},{"startOffset":111547,"endOffset":112035,"count":0},{"startOffset":112531,"endOffset":112674,"count":0}],"isBlockCoverage":true},{"functionName":"_registerErrorHandler","ranges":[{"startOffset":112770,"endOffset":113325,"count":0}],"isBlockCoverage":false},{"functionName":"_microtaskLoop","ranges":[{"startOffset":113347,"endOffset":113621,"count":1}],"isBlockCoverage":true},{"functionName":"_startMicrotaskLoop","ranges":[{"startOffset":113648,"endOffset":113983,"count":1},{"startOffset":113877,"endOffset":113969,"count":0}],"isBlockCoverage":true},{"functionName":"_scheduleAsyncCallback","ranges":[{"startOffset":114013,"endOffset":114484,"count":1},{"startOffset":114386,"endOffset":114478,"count":0}],"isBlockCoverage":true},{"functionName":"_schedulePriorityAsyncCallback","ranges":[{"startOffset":114522,"endOffset":115197,"count":0}],"isBlockCoverage":false},{"functionName":"scheduleMicrotask","ranges":[{"startOffset":115222,"endOffset":115926,"count":0}],"isBlockCoverage":false},{"functionName":"StreamIterator_StreamIterator","ranges":[{"startOffset":115963,"endOffset":116090,"count":0}],"isBlockCoverage":false},{"functionName":"StreamController_StreamController","ranges":[{"startOffset":116131,"endOffset":116365,"count":1}],"isBlockCoverage":true},{"functionName":"_runGuarded","ranges":[{"startOffset":116384,"endOffset":116791,"count":1},{"startOffset":116615,"endOffset":116785,"count":0}],"isBlockCoverage":true},{"functionName":"_nullDataHandler","ranges":[{"startOffset":116815,"endOffset":116838,"count":0}],"isBlockCoverage":false},{"functionName":"_nullErrorHandler","ranges":[{"startOffset":116863,"endOffset":117021,"count":0}],"isBlockCoverage":false},{"functionName":"_nullDoneHandler","ranges":[{"startOffset":117045,"endOffset":117063,"count":0}],"isBlockCoverage":false},{"functionName":"Timer_Timer$periodic","ranges":[{"startOffset":117091,"endOffset":117502,"count":1},{"startOffset":117293,"endOffset":117345,"count":0}],"isBlockCoverage":true},{"functionName":"_ZoneSpecification$","ranges":[{"startOffset":117529,"endOffset":117972,"count":1}],"isBlockCoverage":true},{"functionName":"_parentDelegate","ranges":[{"startOffset":117995,"endOffset":118126,"count":1},{"startOffset":118068,"endOffset":118125,"count":0}],"isBlockCoverage":true},{"functionName":"_rootHandleUncaughtError","ranges":[{"startOffset":118158,"endOffset":118395,"count":0}],"isBlockCoverage":false},{"functionName":"_rootRun","ranges":[{"startOffset":118411,"endOffset":118914,"count":1},{"startOffset":118731,"endOffset":118749,"count":0},{"startOffset":118859,"endOffset":118860,"count":0}],"isBlockCoverage":true},{"functionName":"_rootRunUnary","ranges":[{"startOffset":118935,"endOffset":119510,"count":1},{"startOffset":119455,"endOffset":119456,"count":0}],"isBlockCoverage":true},{"functionName":"_rootRunBinary","ranges":[{"startOffset":119532,"endOffset":120183,"count":0}],"isBlockCoverage":false},{"functionName":"_rootRegisterCallback","ranges":[{"startOffset":120212,"endOffset":120314,"count":1}],"isBlockCoverage":true},{"functionName":"_rootRegisterUnaryCallback","ranges":[{"startOffset":120348,"endOffset":120466,"count":1}],"isBlockCoverage":true},{"functionName":"_rootRegisterBinaryCallback","ranges":[{"startOffset":120501,"endOffset":120627,"count":1}],"isBlockCoverage":true},{"functionName":"_rootErrorCallback","ranges":[{"startOffset":120653,"endOffset":120783,"count":0}],"isBlockCoverage":false},{"functionName":"_rootScheduleMicrotask","ranges":[{"startOffset":120813,"endOffset":121143,"count":1},{"startOffset":121071,"endOffset":121101,"count":0}],"isBlockCoverage":true},{"functionName":"_rootCreateTimer","ranges":[{"startOffset":121167,"endOffset":121430,"count":0}],"isBlockCoverage":false},{"functionName":"_rootCreatePeriodicTimer","ranges":[{"startOffset":121462,"endOffset":121766,"count":1}],"isBlockCoverage":true},{"functionName":"_rootPrint","ranges":[{"startOffset":121784,"endOffset":121874,"count":0}],"isBlockCoverage":false},{"functionName":"_printToZone","ranges":[{"startOffset":121894,"endOffset":121956,"count":0}],"isBlockCoverage":false},{"functionName":"_rootFork","ranges":[{"startOffset":121973,"endOffset":123508,"count":1},{"startOffset":122278,"endOffset":122319,"count":0},{"startOffset":123450,"endOffset":123483,"count":0}],"isBlockCoverage":true},{"functionName":"runZoned","ranges":[{"startOffset":123524,"endOffset":125443,"count":1},{"startOffset":124003,"endOffset":124288,"count":0},{"startOffset":124511,"endOffset":125049,"count":0},{"startOffset":125155,"endOffset":125442,"count":0}],"isBlockCoverage":true},{"functionName":"_runZoned","ranges":[{"startOffset":125460,"endOffset":125673,"count":1}],"isBlockCoverage":true},{"functionName":"_AsyncRun__initializeScheduleImmediate_internalCallback","ranges":[{"startOffset":125736,"endOffset":125836,"count":1}],"isBlockCoverage":true},{"functionName":"_AsyncRun__initializeScheduleImmediate_closure","ranges":[{"startOffset":125890,"endOffset":126032,"count":1}],"isBlockCoverage":true},{"functionName":"_AsyncRun__scheduleImmediateJsOverride_internalCallback","ranges":[{"startOffset":126095,"endOffset":126197,"count":0}],"isBlockCoverage":false},{"functionName":"_AsyncRun__scheduleImmediateWithSetImmediate_internalCallback","ranges":[{"startOffset":126266,"endOffset":126374,"count":0}],"isBlockCoverage":false},{"functionName":"_TimerImpl","ranges":[{"startOffset":126392,"endOffset":126443,"count":1}],"isBlockCoverage":true},{"functionName":"_TimerImpl_internalCallback","ranges":[{"startOffset":126478,"endOffset":126579,"count":0}],"isBlockCoverage":false},{"functionName":"_TimerImpl$periodic_closure","ranges":[{"startOffset":126614,"endOffset":126784,"count":1}],"isBlockCoverage":true},{"functionName":"_AsyncAwaitCompleter","ranges":[{"startOffset":126812,"endOffset":126934,"count":1}],"isBlockCoverage":true},{"functionName":"_AsyncAwaitCompleter_complete_closure","ranges":[{"startOffset":126979,"endOffset":127087,"count":0}],"isBlockCoverage":false},{"functionName":"_AsyncAwaitCompleter_completeError_closure","ranges":[{"startOffset":127137,"endOffset":127270,"count":0}],"isBlockCoverage":false},{"functionName":"_awaitOnObject_closure","ranges":[{"startOffset":127300,"endOffset":127373,"count":1}],"isBlockCoverage":true},{"functionName":"_awaitOnObject_closure0","ranges":[{"startOffset":127404,"endOffset":127478,"count":1}],"isBlockCoverage":true},{"functionName":"_wrapJsFunctionForAsync_closure","ranges":[{"startOffset":127517,"endOffset":127597,"count":1}],"isBlockCoverage":true},{"functionName":"Future","ranges":[{"startOffset":127611,"endOffset":127636,"count":0}],"isBlockCoverage":false},{"functionName":"_Completer","ranges":[{"startOffset":127654,"endOffset":127683,"count":0}],"isBlockCoverage":false},{"functionName":"_AsyncCompleter","ranges":[{"startOffset":127706,"endOffset":127791,"count":1}],"isBlockCoverage":true},{"functionName":"_SyncCompleter","ranges":[{"startOffset":127813,"endOffset":127897,"count":1}],"isBlockCoverage":true},{"functionName":"_FutureListener","ranges":[{"startOffset":127920,"endOffset":128132,"count":1}],"isBlockCoverage":true},{"functionName":"_Future","ranges":[{"startOffset":128147,"endOffset":128297,"count":1}],"isBlockCoverage":true},{"functionName":"_Future__addListener_closure","ranges":[{"startOffset":128333,"endOffset":128435,"count":1}],"isBlockCoverage":true},{"functionName":"_Future__prependListeners_closure","ranges":[{"startOffset":128476,"endOffset":128581,"count":0}],"isBlockCoverage":false},{"functionName":"_Future__chainForeignFuture_closure","ranges":[{"startOffset":128624,"endOffset":128704,"count":0}],"isBlockCoverage":false},{"functionName":"_Future__chainForeignFuture_closure0","ranges":[{"startOffset":128748,"endOffset":128829,"count":0}],"isBlockCoverage":false},{"functionName":"_Future__chainForeignFuture_closure1","ranges":[{"startOffset":128873,"endOffset":129000,"count":0}],"isBlockCoverage":false},{"functionName":"_Future__asyncComplete_closure","ranges":[{"startOffset":129038,"endOffset":129139,"count":1}],"isBlockCoverage":true},{"functionName":"_Future__chainFuture_closure","ranges":[{"startOffset":129175,"endOffset":129274,"count":0}],"isBlockCoverage":false},{"functionName":"_Future__asyncCompleteError_closure","ranges":[{"startOffset":129317,"endOffset":129455,"count":0}],"isBlockCoverage":false},{"functionName":"_Future__propagateToListeners_handleWhenCompleteCallback","ranges":[{"startOffset":129519,"endOffset":129716,"count":0}],"isBlockCoverage":false},{"functionName":"_Future__propagateToListeners_handleWhenCompleteCallback_closure","ranges":[{"startOffset":129788,"endOffset":129905,"count":0}],"isBlockCoverage":false},{"functionName":"_Future__propagateToListeners_handleValueCallback","ranges":[{"startOffset":129962,"endOffset":130120,"count":1}],"isBlockCoverage":true},{"functionName":"_Future__propagateToListeners_handleError","ranges":[{"startOffset":130169,"endOffset":130313,"count":0}],"isBlockCoverage":false},{"functionName":"_AsyncCallbackEntry","ranges":[{"startOffset":130340,"endOffset":130430,"count":1}],"isBlockCoverage":true},{"functionName":"Stream","ranges":[{"startOffset":130444,"endOffset":130469,"count":0}],"isBlockCoverage":false},{"functionName":"Stream_pipe_closure","ranges":[{"startOffset":130496,"endOffset":130568,"count":1}],"isBlockCoverage":true},{"functionName":"Stream_length_closure","ranges":[{"startOffset":130597,"endOffset":130690,"count":0}],"isBlockCoverage":false},{"functionName":"Stream_length_closure0","ranges":[{"startOffset":130720,"endOffset":130815,"count":0}],"isBlockCoverage":false},{"functionName":"StreamSubscription","ranges":[{"startOffset":130841,"endOffset":130878,"count":0}],"isBlockCoverage":false},{"functionName":"StreamTransformerBase","ranges":[{"startOffset":130907,"endOffset":130947,"count":0}],"isBlockCoverage":false},{"functionName":"_StreamController","ranges":[{"startOffset":130972,"endOffset":131008,"count":0}],"isBlockCoverage":false},{"functionName":"_StreamController__subscribe_closure","ranges":[{"startOffset":131052,"endOffset":131132,"count":1}],"isBlockCoverage":true},{"functionName":"_StreamController__recordCancel_complete","ranges":[{"startOffset":131180,"endOffset":131264,"count":0}],"isBlockCoverage":false},{"functionName":"_SyncStreamControllerDispatch","ranges":[{"startOffset":131301,"endOffset":131349,"count":0}],"isBlockCoverage":false},{"functionName":"_SyncStreamController","ranges":[{"startOffset":131378,"endOffset":131643,"count":1}],"isBlockCoverage":true},{"functionName":"_ControllerStream","ranges":[{"startOffset":131668,"endOffset":131760,"count":1}],"isBlockCoverage":true},{"functionName":"_ControllerSubscription","ranges":[{"startOffset":131791,"endOffset":132051,"count":1}],"isBlockCoverage":true},{"functionName":"_StreamSinkWrapper","ranges":[{"startOffset":132077,"endOffset":132173,"count":1}],"isBlockCoverage":true},{"functionName":"_AddStreamState_cancel_closure","ranges":[{"startOffset":132211,"endOffset":132285,"count":0}],"isBlockCoverage":false},{"functionName":"_BufferingStreamSubscription","ranges":[{"startOffset":132321,"endOffset":132368,"count":0}],"isBlockCoverage":false},{"functionName":"_BufferingStreamSubscription__sendError_sendError","ranges":[{"startOffset":132425,"endOffset":132577,"count":0}],"isBlockCoverage":false},{"functionName":"_BufferingStreamSubscription__sendDone_sendDone","ranges":[{"startOffset":132632,"endOffset":132723,"count":0}],"isBlockCoverage":false},{"functionName":"_StreamImpl","ranges":[{"startOffset":132742,"endOffset":132772,"count":0}],"isBlockCoverage":false},{"functionName":"_DelayedEvent","ranges":[{"startOffset":132793,"endOffset":132825,"count":0}],"isBlockCoverage":false},{"functionName":"_DelayedData","ranges":[{"startOffset":132845,"endOffset":132950,"count":0}],"isBlockCoverage":false},{"functionName":"_DelayedError","ranges":[{"startOffset":132971,"endOffset":133084,"count":0}],"isBlockCoverage":false},{"functionName":"_DelayedDone","ranges":[{"startOffset":133104,"endOffset":133135,"count":1}],"isBlockCoverage":true},{"functionName":"_PendingEvents","ranges":[{"startOffset":133157,"endOffset":133190,"count":0}],"isBlockCoverage":false},{"functionName":"_PendingEvents_schedule_closure","ranges":[{"startOffset":133229,"endOffset":133334,"count":0}],"isBlockCoverage":false},{"functionName":"_StreamImplEvents","ranges":[{"startOffset":133359,"endOffset":133515,"count":0}],"isBlockCoverage":false},{"functionName":"_DoneStreamSubscription","ranges":[{"startOffset":133546,"endOffset":133698,"count":0}],"isBlockCoverage":false},{"functionName":"_StreamIterator","ranges":[{"startOffset":133721,"endOffset":133881,"count":0}],"isBlockCoverage":false},{"functionName":"_EmptyStream","ranges":[{"startOffset":133901,"endOffset":133955,"count":0}],"isBlockCoverage":false},{"functionName":"Timer","ranges":[{"startOffset":133968,"endOffset":133992,"count":0}],"isBlockCoverage":false},{"functionName":"AsyncError","ranges":[{"startOffset":134010,"endOffset":134096,"count":0}],"isBlockCoverage":false},{"functionName":"_ZoneFunction","ranges":[{"startOffset":134117,"endOffset":134229,"count":1}],"isBlockCoverage":true},{"functionName":"ZoneSpecification","ranges":[{"startOffset":134254,"endOffset":134290,"count":0}],"isBlockCoverage":false},{"functionName":"_ZoneSpecification","ranges":[{"startOffset":134316,"endOffset":134791,"count":1}],"isBlockCoverage":true},{"functionName":"ZoneDelegate","ranges":[{"startOffset":134811,"endOffset":134842,"count":0}],"isBlockCoverage":false},{"functionName":"Zone","ranges":[{"startOffset":134854,"endOffset":134877,"count":0}],"isBlockCoverage":false},{"functionName":"_ZoneDelegate","ranges":[{"startOffset":134898,"endOffset":134967,"count":0}],"isBlockCoverage":false},{"functionName":"_Zone","ranges":[{"startOffset":134980,"endOffset":135004,"count":0}],"isBlockCoverage":false},{"functionName":"_CustomZone","ranges":[{"startOffset":135023,"endOffset":135402,"count":1}],"isBlockCoverage":true},{"functionName":"_CustomZone_bindCallback_closure","ranges":[{"startOffset":135442,"endOffset":135573,"count":0}],"isBlockCoverage":false},{"functionName":"_CustomZone_bindUnaryCallback_closure","ranges":[{"startOffset":135618,"endOffset":135785,"count":1}],"isBlockCoverage":true},{"functionName":"_CustomZone_bindCallbackGuarded_closure","ranges":[{"startOffset":135832,"endOffset":135947,"count":1}],"isBlockCoverage":true},{"functionName":"_CustomZone_bindUnaryCallbackGuarded_closure","ranges":[{"startOffset":135999,"endOffset":136142,"count":1}],"isBlockCoverage":true},{"functionName":"_rootHandleUncaughtError_closure","ranges":[{"startOffset":136182,"endOffset":136291,"count":0}],"isBlockCoverage":false},{"functionName":"_RootZone","ranges":[{"startOffset":136308,"endOffset":136336,"count":1}],"isBlockCoverage":true},{"functionName":"_RootZone_bindCallback_closure","ranges":[{"startOffset":136374,"endOffset":136494,"count":0}],"isBlockCoverage":false},{"functionName":"_RootZone_bindCallbackGuarded_closure","ranges":[{"startOffset":136539,"endOffset":136643,"count":0}],"isBlockCoverage":false},{"functionName":"_RootZone_bindUnaryCallbackGuarded_closure","ranges":[{"startOffset":136693,"endOffset":136825,"count":0}],"isBlockCoverage":false},{"functionName":"runZoned_closure","ranges":[{"startOffset":136849,"endOffset":136910,"count":1}],"isBlockCoverage":true},{"functionName":"HashMap_HashMap","ranges":[{"startOffset":136933,"endOffset":136996,"count":1}],"isBlockCoverage":true},{"functionName":"_HashMap__getTableEntry","ranges":[{"startOffset":137027,"endOffset":137130,"count":0}],"isBlockCoverage":false},{"functionName":"_HashMap__setTableEntry","ranges":[{"startOffset":137161,"endOffset":137288,"count":0}],"isBlockCoverage":false},{"functionName":"_HashMap__newHashTable","ranges":[{"startOffset":137318,"endOffset":137510,"count":0}],"isBlockCoverage":false},{"functionName":"LinkedHashMap_LinkedHashMap$_literal","ranges":[{"startOffset":137554,"endOffset":137777,"count":0}],"isBlockCoverage":false},{"functionName":"LinkedHashMap_LinkedHashMap$_empty","ranges":[{"startOffset":137819,"endOffset":137889,"count":1}],"isBlockCoverage":true},{"functionName":"LinkedHashMap__makeEmpty","ranges":[{"startOffset":137921,"endOffset":137989,"count":1}],"isBlockCoverage":true},{"functionName":"LinkedHashSet_LinkedHashSet","ranges":[{"startOffset":138024,"endOffset":138085,"count":1}],"isBlockCoverage":true},{"functionName":"_LinkedHashSet__newHashTable","ranges":[{"startOffset":138121,"endOffset":138287,"count":0}],"isBlockCoverage":false},{"functionName":"IterableBase_iterableToShortString","ranges":[{"startOffset":138329,"endOffset":139079,"count":0}],"isBlockCoverage":false},{"functionName":"IterableBase_iterableToFullString","ranges":[{"startOffset":139120,"endOffset":139770,"count":0}],"isBlockCoverage":false},{"functionName":"_isToStringVisiting","ranges":[{"startOffset":139797,"endOffset":139972,"count":0}],"isBlockCoverage":false},{"functionName":"_iterablePartsToStrings","ranges":[{"startOffset":140003,"endOffset":142710,"count":0}],"isBlockCoverage":false},{"functionName":"MapBase_mapToString","ranges":[{"startOffset":142737,"endOffset":143352,"count":0}],"isBlockCoverage":false},{"functionName":"_HashMap","ranges":[{"startOffset":143368,"endOffset":143571,"count":1}],"isBlockCoverage":true},{"functionName":"_HashMapKeyIterable","ranges":[{"startOffset":143598,"endOffset":143685,"count":0}],"isBlockCoverage":false},{"functionName":"_HashMapKeyIterator","ranges":[{"startOffset":143712,"endOffset":143907,"count":0}],"isBlockCoverage":false},{"functionName":"_LinkedHashSet","ranges":[{"startOffset":143929,"endOffset":144201,"count":1}],"isBlockCoverage":true},{"functionName":"_LinkedHashSetCell","ranges":[{"startOffset":144227,"endOffset":144358,"count":0}],"isBlockCoverage":false},{"functionName":"_LinkedHashSetIterator","ranges":[{"startOffset":144388,"endOffset":144596,"count":0}],"isBlockCoverage":false},{"functionName":"IterableBase","ranges":[{"startOffset":144616,"endOffset":144647,"count":0}],"isBlockCoverage":false},{"functionName":"ListBase","ranges":[{"startOffset":144663,"endOffset":144690,"count":0}],"isBlockCoverage":false},{"functionName":"ListMixin","ranges":[{"startOffset":144707,"endOffset":144735,"count":0}],"isBlockCoverage":false},{"functionName":"MapBase","ranges":[{"startOffset":144750,"endOffset":144776,"count":0}],"isBlockCoverage":false},{"functionName":"MapBase_mapToString_closure","ranges":[{"startOffset":144811,"endOffset":144911,"count":0}],"isBlockCoverage":false},{"functionName":"MapMixin","ranges":[{"startOffset":144927,"endOffset":144954,"count":0}],"isBlockCoverage":false},{"functionName":"_UnmodifiableMapMixin","ranges":[{"startOffset":144983,"endOffset":145023,"count":0}],"isBlockCoverage":false},{"functionName":"MapView","ranges":[{"startOffset":145038,"endOffset":145064,"count":0}],"isBlockCoverage":false},{"functionName":"UnmodifiableMapView","ranges":[{"startOffset":145091,"endOffset":145178,"count":1}],"isBlockCoverage":true},{"functionName":"_SetBase","ranges":[{"startOffset":145194,"endOffset":145221,"count":0}],"isBlockCoverage":false},{"functionName":"_ListBase_Object_ListMixin","ranges":[{"startOffset":145255,"endOffset":145300,"count":0}],"isBlockCoverage":false},{"functionName":"_UnmodifiableMapView_MapView__UnmodifiableMapMixin","ranges":[{"startOffset":145358,"endOffset":145427,"count":0}],"isBlockCoverage":false},{"functionName":"_parseJson","ranges":[{"startOffset":145445,"endOffset":145914,"count":1},{"startOffset":145555,"endOffset":145607,"count":0},{"startOffset":145686,"endOffset":145846,"count":0}],"isBlockCoverage":true},{"functionName":"_convertJsonToDartLazy","ranges":[{"startOffset":145944,"endOffset":146324,"count":1}],"isBlockCoverage":true},{"functionName":"Utf8Decoder__convertIntercepted","ranges":[{"startOffset":146363,"endOffset":146629,"count":1},{"startOffset":146529,"endOffset":146609,"count":0}],"isBlockCoverage":true},{"functionName":"Utf8Decoder__convertInterceptedUint8List","ranges":[{"startOffset":146677,"endOffset":147268,"count":0}],"isBlockCoverage":false},{"functionName":"Utf8Decoder__useTextDecoderChecked","ranges":[{"startOffset":147310,"endOffset":147479,"count":0}],"isBlockCoverage":false},{"functionName":"Utf8Decoder__useTextDecoderUnchecked","ranges":[{"startOffset":147523,"endOffset":147743,"count":0}],"isBlockCoverage":false},{"functionName":"Utf8Decoder__unsafe","ranges":[{"startOffset":147770,"endOffset":148014,"count":0}],"isBlockCoverage":false},{"functionName":"Utf8Decoder__makeDecoder","ranges":[{"startOffset":148046,"endOffset":148262,"count":0}],"isBlockCoverage":false},{"functionName":"_scanOneByteCharacters","ranges":[{"startOffset":148292,"endOffset":148695,"count":1},{"startOffset":148570,"endOffset":148589,"count":0},{"startOffset":148635,"endOffset":148651,"count":0}],"isBlockCoverage":true},{"functionName":"Base64Codec__checkPadding","ranges":[{"startOffset":148728,"endOffset":149339,"count":0}],"isBlockCoverage":false},{"functionName":"JsonUnsupportedObjectError$","ranges":[{"startOffset":149374,"endOffset":149504,"count":0}],"isBlockCoverage":false},{"functionName":"_defaultToEncodable","ranges":[{"startOffset":149531,"endOffset":149587,"count":0}],"isBlockCoverage":false},{"functionName":"_JsonStringStringifier_stringify","ranges":[{"startOffset":149627,"endOffset":149885,"count":1},{"startOffset":149869,"endOffset":149873,"count":0}],"isBlockCoverage":true},{"functionName":"_JsonStringStringifier_printOn","ranges":[{"startOffset":149923,"endOffset":150125,"count":1}],"isBlockCoverage":true},{"functionName":"_JsonMap","ranges":[{"startOffset":150141,"endOffset":150254,"count":1}],"isBlockCoverage":true},{"functionName":"_JsonMapKeyIterable","ranges":[{"startOffset":150281,"endOffset":150355,"count":0}],"isBlockCoverage":false},{"functionName":"AsciiCodec","ranges":[{"startOffset":150373,"endOffset":150435,"count":1}],"isBlockCoverage":true},{"functionName":"_UnicodeSubsetEncoder","ranges":[{"startOffset":150464,"endOffset":150504,"count":0}],"isBlockCoverage":false},{"functionName":"AsciiEncoder","ranges":[{"startOffset":150524,"endOffset":150586,"count":1}],"isBlockCoverage":true},{"functionName":"Base64Codec","ranges":[{"startOffset":150605,"endOffset":150663,"count":1}],"isBlockCoverage":true},{"functionName":"Base64Encoder","ranges":[{"startOffset":150684,"endOffset":150744,"count":1}],"isBlockCoverage":true},{"functionName":"Codec","ranges":[{"startOffset":150757,"endOffset":150781,"count":0}],"isBlockCoverage":false},{"functionName":"_FusedCodec","ranges":[{"startOffset":150800,"endOffset":150919,"count":0}],"isBlockCoverage":false},{"functionName":"Converter","ranges":[{"startOffset":150936,"endOffset":150964,"count":0}],"isBlockCoverage":false},{"functionName":"Encoding","ranges":[{"startOffset":150980,"endOffset":151007,"count":0}],"isBlockCoverage":false},{"functionName":"JsonUnsupportedObjectError","ranges":[{"startOffset":151041,"endOffset":151150,"count":0}],"isBlockCoverage":false},{"functionName":"JsonCyclicError","ranges":[{"startOffset":151173,"endOffset":151271,"count":0}],"isBlockCoverage":false},{"functionName":"JsonCodec","ranges":[{"startOffset":151288,"endOffset":151378,"count":1}],"isBlockCoverage":true},{"functionName":"JsonEncoder","ranges":[{"startOffset":151397,"endOffset":151487,"count":1}],"isBlockCoverage":true},{"functionName":"JsonDecoder","ranges":[{"startOffset":151506,"endOffset":151564,"count":1}],"isBlockCoverage":true},{"functionName":"_JsonStringifier","ranges":[{"startOffset":151588,"endOffset":151623,"count":0}],"isBlockCoverage":false},{"functionName":"_JsonStringifier_writeMap_closure","ranges":[{"startOffset":151664,"endOffset":151776,"count":1}],"isBlockCoverage":true},{"functionName":"_JsonStringStringifier","ranges":[{"startOffset":151806,"endOffset":151942,"count":1}],"isBlockCoverage":true},{"functionName":"Utf8Codec","ranges":[{"startOffset":151959,"endOffset":152022,"count":1}],"isBlockCoverage":true},{"functionName":"Utf8Encoder","ranges":[{"startOffset":152041,"endOffset":152071,"count":1}],"isBlockCoverage":true},{"functionName":"_Utf8Encoder","ranges":[{"startOffset":152091,"endOffset":152192,"count":0}],"isBlockCoverage":false},{"functionName":"Utf8Decoder","ranges":[{"startOffset":152211,"endOffset":152276,"count":1}],"isBlockCoverage":true},{"functionName":"_Utf8Decoder","ranges":[{"startOffset":152296,"endOffset":152498,"count":1}],"isBlockCoverage":true},{"functionName":"_Utf8Decoder_convert_addSingleBytes","ranges":[{"startOffset":152541,"endOffset":152721,"count":1}],"isBlockCoverage":true},{"functionName":"int_parse","ranges":[{"startOffset":152738,"endOffset":153106,"count":1},{"startOffset":152965,"endOffset":153105,"count":0}],"isBlockCoverage":true},{"functionName":"Error__objectToString","ranges":[{"startOffset":153135,"endOffset":153309,"count":0}],"isBlockCoverage":false},{"functionName":"List_List$filled","ranges":[{"startOffset":153333,"endOffset":153687,"count":0}],"isBlockCoverage":false},{"functionName":"List_List$from","ranges":[{"startOffset":153709,"endOffset":154115,"count":0}],"isBlockCoverage":false},{"functionName":"List_List$unmodifiable","ranges":[{"startOffset":154145,"endOffset":154366,"count":0}],"isBlockCoverage":false},{"functionName":"String_String$fromCharCodes","ranges":[{"startOffset":154401,"endOffset":155216,"count":1},{"startOffset":154876,"endOffset":154928,"count":0},{"startOffset":154950,"endOffset":155215,"count":0}],"isBlockCoverage":true},{"functionName":"String_String$fromCharCode","ranges":[{"startOffset":155250,"endOffset":155332,"count":0}],"isBlockCoverage":false},{"functionName":"String__stringFromIterable","ranges":[{"startOffset":155366,"endOffset":156339,"count":0}],"isBlockCoverage":false},{"functionName":"RegExp_RegExp","ranges":[{"startOffset":156360,"endOffset":156499,"count":0}],"isBlockCoverage":false},{"functionName":"StringBuffer__writeAll","ranges":[{"startOffset":156529,"endOffset":157013,"count":0}],"isBlockCoverage":false},{"functionName":"NoSuchMethodError$","ranges":[{"startOffset":157039,"endOffset":157217,"count":0}],"isBlockCoverage":false},{"functionName":"Uri_base","ranges":[{"startOffset":157233,"endOffset":157431,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__uriEncode","ranges":[{"startOffset":157454,"endOffset":158643,"count":0}],"isBlockCoverage":false},{"functionName":"DateTime__fourDigits","ranges":[{"startOffset":158671,"endOffset":158964,"count":0}],"isBlockCoverage":false},{"functionName":"DateTime__threeDigits","ranges":[{"startOffset":158993,"endOffset":159121,"count":0}],"isBlockCoverage":false},{"functionName":"DateTime__twoDigits","ranges":[{"startOffset":159148,"endOffset":159231,"count":0}],"isBlockCoverage":false},{"functionName":"Duration$","ranges":[{"startOffset":159248,"endOffset":159321,"count":1}],"isBlockCoverage":true},{"functionName":"Error_safeToString","ranges":[{"startOffset":159347,"endOffset":159619,"count":0}],"isBlockCoverage":false},{"functionName":"ArgumentError$","ranges":[{"startOffset":159641,"endOffset":159728,"count":0}],"isBlockCoverage":false},{"functionName":"ArgumentError$value","ranges":[{"startOffset":159755,"endOffset":159857,"count":0}],"isBlockCoverage":false},{"functionName":"RangeError$value","ranges":[{"startOffset":159881,"endOffset":159996,"count":0}],"isBlockCoverage":false},{"functionName":"RangeError$range","ranges":[{"startOffset":160020,"endOffset":160181,"count":0}],"isBlockCoverage":false},{"functionName":"RangeError_checkValueInInterval","ranges":[{"startOffset":160220,"endOffset":160409,"count":0}],"isBlockCoverage":false},{"functionName":"RangeError_checkValidRange","ranges":[{"startOffset":160443,"endOffset":160875,"count":1},{"startOffset":160520,"endOffset":160540,"count":0},{"startOffset":160589,"endOffset":160665,"count":0},{"startOffset":160743,"endOffset":160819,"count":0}],"isBlockCoverage":true},{"functionName":"RangeError_checkNotNegative","ranges":[{"startOffset":160910,"endOffset":161106,"count":0}],"isBlockCoverage":false},{"functionName":"IndexError$","ranges":[{"startOffset":161125,"endOffset":161363,"count":0}],"isBlockCoverage":false},{"functionName":"UnsupportedError$","ranges":[{"startOffset":161388,"endOffset":161459,"count":0}],"isBlockCoverage":false},{"functionName":"UnimplementedError$","ranges":[{"startOffset":161486,"endOffset":161559,"count":0}],"isBlockCoverage":false},{"functionName":"StateError$","ranges":[{"startOffset":161578,"endOffset":161643,"count":0}],"isBlockCoverage":false},{"functionName":"ConcurrentModificationError$","ranges":[{"startOffset":161679,"endOffset":161775,"count":0}],"isBlockCoverage":false},{"functionName":"FormatException$","ranges":[{"startOffset":161799,"endOffset":161901,"count":0}],"isBlockCoverage":false},{"functionName":"List_List$generate","ranges":[{"startOffset":161927,"endOffset":162297,"count":1}],"isBlockCoverage":true},{"functionName":"Uri_parse","ranges":[{"startOffset":162314,"endOffset":168453,"count":1},{"startOffset":162832,"endOffset":162938,"count":0},{"startOffset":162980,"endOffset":163068,"count":0},{"startOffset":163649,"endOffset":163694,"count":0},{"startOffset":163774,"endOffset":163797,"count":0},{"startOffset":163894,"endOffset":163917,"count":0},{"startOffset":163983,"endOffset":164000,"count":0},{"startOffset":164205,"endOffset":164232,"count":0},{"startOffset":164283,"endOffset":164308,"count":0},{"startOffset":164355,"endOffset":164382,"count":0},{"startOffset":164432,"endOffset":164455,"count":0},{"startOffset":164497,"endOffset":164520,"count":0},{"startOffset":164568,"endOffset":164594,"count":0},{"startOffset":164644,"endOffset":164667,"count":0},{"startOffset":164709,"endOffset":164731,"count":0},{"startOffset":164797,"endOffset":164813,"count":0},{"startOffset":164867,"endOffset":167872,"count":0},{"startOffset":167927,"endOffset":168319,"count":0}],"isBlockCoverage":true},{"functionName":"Uri_decodeComponent","ranges":[{"startOffset":168480,"endOffset":168661,"count":0}],"isBlockCoverage":false},{"functionName":"Uri_splitQueryString","ranges":[{"startOffset":168689,"endOffset":168954,"count":1}],"isBlockCoverage":true},{"functionName":"Uri__parseIPv4Address","ranges":[{"startOffset":168983,"endOffset":170538,"count":0}],"isBlockCoverage":false},{"functionName":"Uri_parseIPv6Address","ranges":[{"startOffset":170566,"endOffset":173975,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__Uri$notSimple","ranges":[{"startOffset":174002,"endOffset":175800,"count":1},{"startOffset":174254,"endOffset":174277,"count":0},{"startOffset":174370,"endOffset":174515,"count":0},{"startOffset":174608,"endOffset":174632,"count":0},{"startOffset":174717,"endOffset":174774,"count":0},{"startOffset":174901,"endOffset":174925,"count":0},{"startOffset":175007,"endOffset":175031,"count":0},{"startOffset":175196,"endOffset":175202,"count":0},{"startOffset":175211,"endOffset":175291,"count":0},{"startOffset":175429,"endOffset":175453,"count":0},{"startOffset":175507,"endOffset":175535,"count":0},{"startOffset":175639,"endOffset":175645,"count":0},{"startOffset":175734,"endOffset":175785,"count":0}],"isBlockCoverage":true},{"functionName":"_Uri__Uri","ranges":[{"startOffset":175817,"endOffset":177057,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__defaultPort","ranges":[{"startOffset":177082,"endOffset":177220,"count":1},{"startOffset":177148,"endOffset":177219,"count":0}],"isBlockCoverage":true},{"functionName":"_Uri__fail","ranges":[{"startOffset":177238,"endOffset":177345,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__Uri$file","ranges":[{"startOffset":177367,"endOffset":177497,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__checkNonWindowsPathReservedCharacters","ranges":[{"startOffset":177548,"endOffset":177751,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__checkWindowsPathReservedCharacters","ranges":[{"startOffset":177799,"endOffset":178489,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__checkWindowsDriveLetter","ranges":[{"startOffset":178526,"endOffset":179005,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__makeFileUri","ranges":[{"startOffset":179030,"endOffset":179320,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__makeWindowsFileUrl","ranges":[{"startOffset":179352,"endOffset":181689,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__makePort","ranges":[{"startOffset":181711,"endOffset":181840,"count":1},{"startOffset":181808,"endOffset":181815,"count":0}],"isBlockCoverage":true},{"functionName":"_Uri__makeHost","ranges":[{"startOffset":181862,"endOffset":182764,"count":1},{"startOffset":181952,"endOffset":181959,"count":0},{"startOffset":181993,"endOffset":182003,"count":0},{"startOffset":182067,"endOffset":182435,"count":0},{"startOffset":182479,"endOffset":182497,"count":0},{"startOffset":182603,"endOffset":182701,"count":0}],"isBlockCoverage":true},{"functionName":"_Uri__normalizeRegName","ranges":[{"startOffset":182794,"endOffset":186280,"count":1},{"startOffset":182973,"endOffset":182991,"count":0},{"startOffset":183204,"endOffset":184074,"count":0},{"startOffset":184178,"endOffset":184209,"count":0},{"startOffset":184281,"endOffset":184310,"count":0},{"startOffset":184389,"endOffset":184714,"count":0},{"startOffset":184747,"endOffset":185904,"count":0},{"startOffset":186013,"endOffset":186268,"count":0},{"startOffset":186269,"endOffset":186273,"count":0}],"isBlockCoverage":true},{"functionName":"_Uri__makeScheme","ranges":[{"startOffset":186304,"endOffset":187376,"count":1},{"startOffset":186414,"endOffset":186424,"count":0},{"startOffset":186532,"endOffset":186609,"count":0},{"startOffset":186653,"endOffset":186671,"count":0},{"startOffset":186911,"endOffset":186942,"count":0},{"startOffset":187014,"endOffset":187041,"count":0},{"startOffset":187069,"endOffset":187121,"count":0},{"startOffset":187178,"endOffset":187203,"count":0},{"startOffset":187337,"endOffset":187359,"count":0}],"isBlockCoverage":true},{"functionName":"_Uri__canonicalizeScheme","ranges":[{"startOffset":187408,"endOffset":187669,"count":1},{"startOffset":187478,"endOffset":187668,"count":0}],"isBlockCoverage":true},{"functionName":"_Uri__makeUserInfo","ranges":[{"startOffset":187695,"endOffset":187864,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__makePath","ranges":[{"startOffset":187886,"endOffset":189059,"count":1},{"startOffset":188222,"endOffset":188245,"count":0},{"startOffset":188255,"endOffset":188280,"count":0},{"startOffset":188343,"endOffset":188423,"count":0},{"startOffset":188520,"endOffset":188795,"count":0},{"startOffset":188827,"endOffset":188878,"count":0},{"startOffset":188965,"endOffset":188987,"count":0}],"isBlockCoverage":true},{"functionName":"_Uri__normalizePath","ranges":[{"startOffset":189086,"endOffset":189363,"count":1},{"startOffset":189174,"endOffset":189190,"count":0},{"startOffset":189191,"endOffset":189237,"count":0},{"startOffset":189247,"endOffset":189311,"count":0}],"isBlockCoverage":true},{"functionName":"_Uri__makeQuery","ranges":[{"startOffset":189386,"endOffset":189559,"count":1},{"startOffset":189539,"endOffset":189558,"count":0}],"isBlockCoverage":true},{"functionName":"_Uri__makeFragment","ranges":[{"startOffset":189585,"endOffset":189750,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__normalizeEscape","ranges":[{"startOffset":189779,"endOffset":190943,"count":1},{"startOffset":189942,"endOffset":189962,"count":0},{"startOffset":190024,"endOffset":190035,"count":0},{"startOffset":190351,"endOffset":190362,"count":0},{"startOffset":190534,"endOffset":190565,"count":0},{"startOffset":190630,"endOffset":190655,"count":0},{"startOffset":190678,"endOffset":190787,"count":0},{"startOffset":190845,"endOffset":190923,"count":0}],"isBlockCoverage":true},{"functionName":"_Uri__escapeChar","ranges":[{"startOffset":190967,"endOffset":192472,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__normalizeOrSubstring","ranges":[{"startOffset":192506,"endOffset":192779,"count":1},{"startOffset":192768,"endOffset":192772,"count":0}],"isBlockCoverage":true},{"functionName":"_Uri__normalize","ranges":[{"startOffset":192802,"endOffset":196002,"count":1},{"startOffset":193232,"endOffset":193251,"count":0},{"startOffset":193299,"endOffset":193317,"count":0},{"startOffset":193526,"endOffset":193556,"count":0},{"startOffset":193627,"endOffset":193656,"count":0},{"startOffset":193933,"endOffset":194100,"count":0},{"startOffset":194114,"endOffset":195678,"count":0},{"startOffset":195738,"endOffset":195990,"count":0},{"startOffset":195991,"endOffset":195995,"count":0}],"isBlockCoverage":true},{"functionName":"_Uri__mayContainDotSegments","ranges":[{"startOffset":196037,"endOffset":196202,"count":1},{"startOffset":196122,"endOffset":196134,"count":0}],"isBlockCoverage":true},{"functionName":"_Uri__removeDotSegments","ranges":[{"startOffset":196233,"endOffset":197172,"count":1},{"startOffset":196374,"endOffset":197171,"count":0}],"isBlockCoverage":true},{"functionName":"_Uri__normalizeRelativePath","ranges":[{"startOffset":197207,"endOffset":198750,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__escapeScheme","ranges":[{"startOffset":198776,"endOffset":199463,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__toWindowsFilePath","ranges":[{"startOffset":199494,"endOffset":200490,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__hexCharPairToByte","ranges":[{"startOffset":200521,"endOffset":201052,"count":1},{"startOffset":200917,"endOffset":201009,"count":0}],"isBlockCoverage":true},{"functionName":"_Uri__uriDecode","ranges":[{"startOffset":201075,"endOffset":202742,"count":1},{"startOffset":201518,"endOffset":201552,"count":0},{"startOffset":201719,"endOffset":201730,"count":0},{"startOffset":201831,"endOffset":201913,"count":0},{"startOffset":202110,"endOffset":202185,"count":0},{"startOffset":202270,"endOffset":202327,"count":0},{"startOffset":202497,"endOffset":202532,"count":0}],"isBlockCoverage":true},{"functionName":"_Uri__isAlphabeticCharacter","ranges":[{"startOffset":202777,"endOffset":202890,"count":1}],"isBlockCoverage":true},{"functionName":"UriData__writeUri","ranges":[{"startOffset":202915,"endOffset":203591,"count":0}],"isBlockCoverage":false},{"functionName":"UriData__validateMimeType","ranges":[{"startOffset":203624,"endOffset":203975,"count":0}],"isBlockCoverage":false},{"functionName":"UriData__parse","ranges":[{"startOffset":203997,"endOffset":205905,"count":0}],"isBlockCoverage":false},{"functionName":"UriData__uriEncodeBytes","ranges":[{"startOffset":205936,"endOffset":207460,"count":0}],"isBlockCoverage":false},{"functionName":"_createTables","ranges":[{"startOffset":207481,"endOffset":213521,"count":1}],"isBlockCoverage":true},{"functionName":"_scan","ranges":[{"startOffset":213534,"endOffset":214326,"count":1},{"startOffset":213774,"endOffset":213792,"count":0},{"startOffset":213934,"endOffset":213964,"count":0},{"startOffset":214075,"endOffset":214085,"count":0},{"startOffset":214130,"endOffset":214158,"count":0}],"isBlockCoverage":true},{"functionName":"NoSuchMethodError_toString_closure","ranges":[{"startOffset":214368,"endOffset":214471,"count":0}],"isBlockCoverage":false},{"functionName":"bool","ranges":[{"startOffset":214483,"endOffset":214506,"count":0}],"isBlockCoverage":false},{"functionName":"DateTime","ranges":[{"startOffset":214522,"endOffset":214608,"count":0}],"isBlockCoverage":false},{"functionName":"double","ranges":[{"startOffset":214622,"endOffset":214647,"count":0}],"isBlockCoverage":false},{"functionName":"Duration","ranges":[{"startOffset":214663,"endOffset":214719,"count":1}],"isBlockCoverage":true},{"functionName":"Duration_toString_sixDigits","ranges":[{"startOffset":214754,"endOffset":214800,"count":0}],"isBlockCoverage":false},{"functionName":"Duration_toString_twoDigits","ranges":[{"startOffset":214835,"endOffset":214881,"count":0}],"isBlockCoverage":false},{"functionName":"Error","ranges":[{"startOffset":214894,"endOffset":214918,"count":0}],"isBlockCoverage":false},{"functionName":"NullThrownError","ranges":[{"startOffset":214941,"endOffset":214975,"count":0}],"isBlockCoverage":false},{"functionName":"ArgumentError","ranges":[{"startOffset":214996,"endOffset":215154,"count":0}],"isBlockCoverage":false},{"functionName":"RangeError","ranges":[{"startOffset":215172,"endOffset":215373,"count":0}],"isBlockCoverage":false},{"functionName":"IndexError","ranges":[{"startOffset":215391,"endOffset":215571,"count":0}],"isBlockCoverage":false},{"functionName":"NoSuchMethodError","ranges":[{"startOffset":215596,"endOffset":215830,"count":0}],"isBlockCoverage":false},{"functionName":"UnsupportedError","ranges":[{"startOffset":215854,"endOffset":215916,"count":0}],"isBlockCoverage":false},{"functionName":"UnimplementedError","ranges":[{"startOffset":215942,"endOffset":216006,"count":0}],"isBlockCoverage":false},{"functionName":"StateError","ranges":[{"startOffset":216024,"endOffset":216080,"count":0}],"isBlockCoverage":false},{"functionName":"ConcurrentModificationError","ranges":[{"startOffset":216115,"endOffset":216195,"count":0}],"isBlockCoverage":false},{"functionName":"OutOfMemoryError","ranges":[{"startOffset":216219,"endOffset":216254,"count":1}],"isBlockCoverage":true},{"functionName":"StackOverflowError","ranges":[{"startOffset":216280,"endOffset":216317,"count":0}],"isBlockCoverage":false},{"functionName":"CyclicInitializationError","ranges":[{"startOffset":216350,"endOffset":216426,"count":0}],"isBlockCoverage":false},{"functionName":"_Exception","ranges":[{"startOffset":216444,"endOffset":216500,"count":0}],"isBlockCoverage":false},{"functionName":"FormatException","ranges":[{"startOffset":216523,"endOffset":216640,"count":0}],"isBlockCoverage":false},{"functionName":"Function","ranges":[{"startOffset":216656,"endOffset":216683,"count":0}],"isBlockCoverage":false},{"functionName":"int","ranges":[{"startOffset":216694,"endOffset":216716,"count":0}],"isBlockCoverage":false},{"functionName":"Iterable","ranges":[{"startOffset":216732,"endOffset":216759,"count":0}],"isBlockCoverage":false},{"functionName":"Iterator","ranges":[{"startOffset":216775,"endOffset":216802,"count":0}],"isBlockCoverage":false},{"functionName":"List","ranges":[{"startOffset":216814,"endOffset":216837,"count":0}],"isBlockCoverage":false},{"functionName":"Map","ranges":[{"startOffset":216848,"endOffset":216870,"count":0}],"isBlockCoverage":false},{"functionName":"Null","ranges":[{"startOffset":216882,"endOffset":216905,"count":0}],"isBlockCoverage":false},{"functionName":"num","ranges":[{"startOffset":216916,"endOffset":216938,"count":0}],"isBlockCoverage":false},{"functionName":"Object","ranges":[{"startOffset":216952,"endOffset":216977,"count":0}],"isBlockCoverage":true},{"functionName":"Match","ranges":[{"startOffset":216990,"endOffset":217014,"count":0}],"isBlockCoverage":false},{"functionName":"StackTrace","ranges":[{"startOffset":217032,"endOffset":217061,"count":0}],"isBlockCoverage":false},{"functionName":"_StringStackTrace","ranges":[{"startOffset":217086,"endOffset":217153,"count":0}],"isBlockCoverage":false},{"functionName":"String","ranges":[{"startOffset":217167,"endOffset":217192,"count":0}],"isBlockCoverage":false},{"functionName":"StringBuffer","ranges":[{"startOffset":217212,"endOffset":217272,"count":1}],"isBlockCoverage":true},{"functionName":"Symbol0","ranges":[{"startOffset":217287,"endOffset":217313,"count":0}],"isBlockCoverage":false},{"functionName":"Uri_splitQueryString_closure","ranges":[{"startOffset":217349,"endOffset":217424,"count":1}],"isBlockCoverage":true},{"functionName":"Uri__parseIPv4Address_error","ranges":[{"startOffset":217459,"endOffset":217529,"count":0}],"isBlockCoverage":false},{"functionName":"Uri_parseIPv6Address_error","ranges":[{"startOffset":217563,"endOffset":217632,"count":0}],"isBlockCoverage":false},{"functionName":"Uri_parseIPv6Address_parseHex","ranges":[{"startOffset":217669,"endOffset":217768,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri","ranges":[{"startOffset":217780,"endOffset":218078,"count":1}],"isBlockCoverage":true},{"functionName":"_Uri__Uri$notSimple_closure","ranges":[{"startOffset":218113,"endOffset":218213,"count":1}],"isBlockCoverage":true},{"functionName":"_Uri__checkNonWindowsPathReservedCharacters_closure","ranges":[{"startOffset":218272,"endOffset":218375,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__makePath_closure","ranges":[{"startOffset":218405,"endOffset":218446,"count":0}],"isBlockCoverage":false},{"functionName":"UriData","ranges":[{"startOffset":218461,"endOffset":218582,"count":0}],"isBlockCoverage":false},{"functionName":"_createTables_closure","ranges":[{"startOffset":218611,"endOffset":218651,"count":1}],"isBlockCoverage":true},{"functionName":"_createTables_build","ranges":[{"startOffset":218678,"endOffset":218742,"count":1}],"isBlockCoverage":true},{"functionName":"_createTables_setChars","ranges":[{"startOffset":218772,"endOffset":218813,"count":1}],"isBlockCoverage":true},{"functionName":"_createTables_setRange","ranges":[{"startOffset":218843,"endOffset":218884,"count":1}],"isBlockCoverage":true},{"functionName":"_SimpleUri","ranges":[{"startOffset":218902,"endOffset":219213,"count":0}],"isBlockCoverage":false},{"functionName":"_DataUri","ranges":[{"startOffset":219229,"endOffset":219531,"count":0}],"isBlockCoverage":false},{"functionName":"convertNativePromiseToDartFuture","ranges":[{"startOffset":219571,"endOffset":219951,"count":0}],"isBlockCoverage":false},{"functionName":"_StructuredClone","ranges":[{"startOffset":219975,"endOffset":220010,"count":0}],"isBlockCoverage":false},{"functionName":"_StructuredClone_walk_closure","ranges":[{"startOffset":220047,"endOffset":220148,"count":1}],"isBlockCoverage":true},{"functionName":"_AcceptStructuredClone","ranges":[{"startOffset":220178,"endOffset":220219,"count":0}],"isBlockCoverage":false},{"functionName":"_AcceptStructuredClone_walk_closure","ranges":[{"startOffset":220262,"endOffset":220369,"count":1}],"isBlockCoverage":true},{"functionName":"_StructuredCloneDart2Js","ranges":[{"startOffset":220400,"endOffset":220496,"count":1}],"isBlockCoverage":true},{"functionName":"_AcceptStructuredCloneDart2Js","ranges":[{"startOffset":220533,"endOffset":220664,"count":1}],"isBlockCoverage":true},{"functionName":"convertNativePromiseToDartFuture_closure","ranges":[{"startOffset":220712,"endOffset":220800,"count":0}],"isBlockCoverage":false},{"functionName":"convertNativePromiseToDartFuture_closure0","ranges":[{"startOffset":220849,"endOffset":220938,"count":0}],"isBlockCoverage":false},{"functionName":"SvgElement","ranges":[{"startOffset":220956,"endOffset":220985,"count":0}],"isBlockCoverage":false},{"functionName":"Uint8List","ranges":[{"startOffset":221002,"endOffset":221030,"count":0}],"isBlockCoverage":false},{"functionName":"_convertDartFunctionFast","ranges":[{"startOffset":221062,"endOffset":221474,"count":1},{"startOffset":221174,"endOffset":221190,"count":0}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":221203,"endOffset":221337,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":221239,"endOffset":221328,"count":0}],"isBlockCoverage":false},{"functionName":"_callDartFunctionFast","ranges":[{"startOffset":221503,"endOffset":221700,"count":0}],"isBlockCoverage":false},{"functionName":"allowInterop","ranges":[{"startOffset":221720,"endOffset":222089,"count":1},{"startOffset":221983,"endOffset":221992,"count":0}],"isBlockCoverage":true},{"functionName":"max","ranges":[{"startOffset":222100,"endOffset":222411,"count":0}],"isBlockCoverage":false},{"functionName":"window","ranges":[{"startOffset":222437,"endOffset":222476,"count":1}],"isBlockCoverage":true},{"functionName":"WebSocket_WebSocket","ranges":[{"startOffset":222503,"endOffset":222557,"count":1}],"isBlockCoverage":true},{"functionName":"_EventStreamSubscription$","ranges":[{"startOffset":222590,"endOffset":222884,"count":1},{"startOffset":222677,"endOffset":222683,"count":0}],"isBlockCoverage":true},{"functionName":"_convertNativeToDart_Window","ranges":[{"startOffset":222919,"endOffset":223033,"count":1},{"startOffset":222966,"endOffset":222973,"count":0}],"isBlockCoverage":true},{"functionName":"_DOMWindowCrossFrame__createSafe","ranges":[{"startOffset":223073,"endOffset":223232,"count":1},{"startOffset":223119,"endOffset":223169,"count":0}],"isBlockCoverage":true},{"functionName":"_wrapZone","ranges":[{"startOffset":223249,"endOffset":223507,"count":1},{"startOffset":223425,"endOffset":223441,"count":0}],"isBlockCoverage":true},{"functionName":"HtmlElement","ranges":[{"startOffset":223526,"endOffset":223556,"count":0}],"isBlockCoverage":false},{"functionName":"AnchorElement","ranges":[{"startOffset":223577,"endOffset":223609,"count":0}],"isBlockCoverage":false},{"functionName":"AreaElement","ranges":[{"startOffset":223628,"endOffset":223658,"count":0}],"isBlockCoverage":false},{"functionName":"Blob","ranges":[{"startOffset":223670,"endOffset":223693,"count":0}],"isBlockCoverage":false},{"functionName":"CharacterData","ranges":[{"startOffset":223714,"endOffset":223746,"count":0}],"isBlockCoverage":false},{"functionName":"DomException","ranges":[{"startOffset":223766,"endOffset":223797,"count":0}],"isBlockCoverage":false},{"functionName":"DomTokenList","ranges":[{"startOffset":223817,"endOffset":223848,"count":0}],"isBlockCoverage":false},{"functionName":"Element","ranges":[{"startOffset":223863,"endOffset":223889,"count":0}],"isBlockCoverage":false},{"functionName":"Event","ranges":[{"startOffset":223902,"endOffset":223926,"count":0}],"isBlockCoverage":false},{"functionName":"EventTarget","ranges":[{"startOffset":223945,"endOffset":223975,"count":0}],"isBlockCoverage":false},{"functionName":"File","ranges":[{"startOffset":223987,"endOffset":224010,"count":0}],"isBlockCoverage":false},{"functionName":"FormElement","ranges":[{"startOffset":224029,"endOffset":224059,"count":0}],"isBlockCoverage":false},{"functionName":"HtmlCollection","ranges":[{"startOffset":224081,"endOffset":224114,"count":0}],"isBlockCoverage":false},{"functionName":"IFrameElement","ranges":[{"startOffset":224135,"endOffset":224167,"count":0}],"isBlockCoverage":false},{"functionName":"Location","ranges":[{"startOffset":224183,"endOffset":224210,"count":0}],"isBlockCoverage":false},{"functionName":"MessageEvent","ranges":[{"startOffset":224230,"endOffset":224261,"count":0}],"isBlockCoverage":false},{"functionName":"MessagePort","ranges":[{"startOffset":224280,"endOffset":224310,"count":0}],"isBlockCoverage":false},{"functionName":"MouseEvent","ranges":[{"startOffset":224328,"endOffset":224357,"count":0}],"isBlockCoverage":false},{"functionName":"Node","ranges":[{"startOffset":224369,"endOffset":224392,"count":0}],"isBlockCoverage":false},{"functionName":"SelectElement","ranges":[{"startOffset":224413,"endOffset":224445,"count":0}],"isBlockCoverage":false},{"functionName":"UIEvent","ranges":[{"startOffset":224460,"endOffset":224486,"count":0}],"isBlockCoverage":false},{"functionName":"Window","ranges":[{"startOffset":224500,"endOffset":224525,"count":0}],"isBlockCoverage":false},{"functionName":"_EventStream","ranges":[{"startOffset":224545,"endOffset":224707,"count":0}],"isBlockCoverage":false},{"functionName":"_ElementEventStreamImpl","ranges":[{"startOffset":224738,"endOffset":224911,"count":1}],"isBlockCoverage":true},{"functionName":"_EventStreamSubscription","ranges":[{"startOffset":224943,"endOffset":225168,"count":1}],"isBlockCoverage":true},{"functionName":"_EventStreamSubscription_closure","ranges":[{"startOffset":225208,"endOffset":225285,"count":1}],"isBlockCoverage":true},{"functionName":"ImmutableListMixin","ranges":[{"startOffset":225311,"endOffset":225348,"count":0}],"isBlockCoverage":false},{"functionName":"FixedSizeListIterator","ranges":[{"startOffset":225377,"endOffset":225561,"count":0}],"isBlockCoverage":false},{"functionName":"_DOMWindowCrossFrame","ranges":[{"startOffset":225589,"endOffset":225655,"count":1}],"isBlockCoverage":true},{"functionName":"_HtmlCollection_Interceptor_ListMixin","ranges":[{"startOffset":225700,"endOffset":225756,"count":0}],"isBlockCoverage":false},{"functionName":"_HtmlCollection_Interceptor_ListMixin_ImmutableListMixin","ranges":[{"startOffset":225820,"endOffset":225895,"count":0}],"isBlockCoverage":false},{"functionName":"NullStreamSink","ranges":[{"startOffset":225924,"endOffset":226081,"count":0}],"isBlockCoverage":false},{"functionName":"NullStreamSink_addStream_closure","ranges":[{"startOffset":226117,"endOffset":226193,"count":0}],"isBlockCoverage":false},{"functionName":"Context_Context","ranges":[{"startOffset":226225,"endOffset":226413,"count":0}],"isBlockCoverage":false},{"functionName":"_parseUri","ranges":[{"startOffset":226430,"endOffset":226613,"count":0}],"isBlockCoverage":false},{"functionName":"_validateArgList","ranges":[{"startOffset":226637,"endOffset":227693,"count":0}],"isBlockCoverage":false},{"functionName":"Context","ranges":[{"startOffset":227708,"endOffset":227798,"count":0}],"isBlockCoverage":false},{"functionName":"Context_join_closure","ranges":[{"startOffset":227826,"endOffset":227865,"count":0}],"isBlockCoverage":false},{"functionName":"Context_joinAll_closure","ranges":[{"startOffset":227896,"endOffset":227938,"count":0}],"isBlockCoverage":false},{"functionName":"Context_split_closure","ranges":[{"startOffset":227967,"endOffset":228007,"count":0}],"isBlockCoverage":false},{"functionName":"_validateArgList_closure","ranges":[{"startOffset":228039,"endOffset":228082,"count":0}],"isBlockCoverage":false},{"functionName":"InternalStyle","ranges":[{"startOffset":228110,"endOffset":228142,"count":0}],"isBlockCoverage":false},{"functionName":"StreamChannelController$","ranges":[{"startOffset":228174,"endOffset":228991,"count":1}],"isBlockCoverage":true},{"functionName":"StreamChannelController","ranges":[{"startOffset":229022,"endOffset":229129,"count":1}],"isBlockCoverage":true},{"functionName":"isAlphabetic","ranges":[{"startOffset":229149,"endOffset":229311,"count":0}],"isBlockCoverage":false},{"functionName":"isDriveLetter","ranges":[{"startOffset":229332,"endOffset":229761,"count":0}],"isBlockCoverage":false},{"functionName":"ParsedPath_ParsedPath$parse","ranges":[{"startOffset":229808,"endOffset":231004,"count":0}],"isBlockCoverage":false},{"functionName":"ParsedPath","ranges":[{"startOffset":231022,"endOffset":231169,"count":0}],"isBlockCoverage":false},{"functionName":"ParsedPath_normalize_closure","ranges":[{"startOffset":231205,"endOffset":231277,"count":0}],"isBlockCoverage":false},{"functionName":"PathException$","ranges":[{"startOffset":231299,"endOffset":231367,"count":0}],"isBlockCoverage":false},{"functionName":"PathException","ranges":[{"startOffset":231388,"endOffset":231447,"count":0}],"isBlockCoverage":false},{"functionName":"Style__getPlatformStyle","ranges":[{"startOffset":231490,"endOffset":231852,"count":0}],"isBlockCoverage":false},{"functionName":"Style","ranges":[{"startOffset":231865,"endOffset":231889,"count":0}],"isBlockCoverage":false},{"functionName":"PosixStyle","ranges":[{"startOffset":231914,"endOffset":231998,"count":0}],"isBlockCoverage":false},{"functionName":"UrlStyle","ranges":[{"startOffset":232018,"endOffset":232098,"count":0}],"isBlockCoverage":false},{"functionName":"WindowsStyle","ranges":[{"startOffset":232122,"endOffset":232211,"count":0}],"isBlockCoverage":false},{"functionName":"WindowsStyle_absolutePathToUri_closure","ranges":[{"startOffset":232253,"endOffset":232310,"count":0}],"isBlockCoverage":false},{"functionName":"Chain_Chain$parse","ranges":[{"startOffset":232344,"endOffset":233600,"count":0}],"isBlockCoverage":false},{"functionName":"Chain","ranges":[{"startOffset":233613,"endOffset":233663,"count":0}],"isBlockCoverage":false},{"functionName":"Chain_Chain$parse_closure","ranges":[{"startOffset":233696,"endOffset":233740,"count":0}],"isBlockCoverage":false},{"functionName":"Chain_Chain$parse_closure0","ranges":[{"startOffset":233774,"endOffset":233819,"count":0}],"isBlockCoverage":false},{"functionName":"Chain_toTrace_closure","ranges":[{"startOffset":233848,"endOffset":233888,"count":0}],"isBlockCoverage":false},{"functionName":"Chain_toString_closure0","ranges":[{"startOffset":233919,"endOffset":233961,"count":0}],"isBlockCoverage":false},{"functionName":"Chain_toString__closure0","ranges":[{"startOffset":233993,"endOffset":234036,"count":0}],"isBlockCoverage":false},{"functionName":"Chain_toString_closure","ranges":[{"startOffset":234066,"endOffset":234134,"count":0}],"isBlockCoverage":false},{"functionName":"Chain_toString__closure","ranges":[{"startOffset":234165,"endOffset":234234,"count":0}],"isBlockCoverage":false},{"functionName":"Frame_Frame$parseVM","ranges":[{"startOffset":234273,"endOffset":234389,"count":0}],"isBlockCoverage":false},{"functionName":"Frame_Frame$parseV8","ranges":[{"startOffset":234416,"endOffset":234532,"count":0}],"isBlockCoverage":false},{"functionName":"Frame_Frame$parseFirefox","ranges":[{"startOffset":234564,"endOffset":234685,"count":0}],"isBlockCoverage":false},{"functionName":"Frame_Frame$parseFriendly","ranges":[{"startOffset":234718,"endOffset":234840,"count":0}],"isBlockCoverage":false},{"functionName":"Frame__uriOrPathToUri","ranges":[{"startOffset":234869,"endOffset":235427,"count":0}],"isBlockCoverage":false},{"functionName":"Frame__catchFormatException","ranges":[{"startOffset":235462,"endOffset":235866,"count":0}],"isBlockCoverage":false},{"functionName":"Frame","ranges":[{"startOffset":235879,"endOffset":236016,"count":0}],"isBlockCoverage":false},{"functionName":"Frame_Frame$parseVM_closure","ranges":[{"startOffset":236051,"endOffset":236122,"count":0}],"isBlockCoverage":false},{"functionName":"Frame_Frame$parseV8_closure","ranges":[{"startOffset":236157,"endOffset":236228,"count":0}],"isBlockCoverage":false},{"functionName":"Frame_Frame$parseV8_closure_parseLocation","ranges":[{"startOffset":236277,"endOffset":236362,"count":0}],"isBlockCoverage":false},{"functionName":"Frame_Frame$parseFirefox_closure","ranges":[{"startOffset":236402,"endOffset":236478,"count":0}],"isBlockCoverage":false},{"functionName":"Frame_Frame$parseFriendly_closure","ranges":[{"startOffset":236519,"endOffset":236596,"count":0}],"isBlockCoverage":false},{"functionName":"LazyTrace","ranges":[{"startOffset":236620,"endOffset":236712,"count":0}],"isBlockCoverage":false},{"functionName":"LazyTrace_terse_closure","ranges":[{"startOffset":236739,"endOffset":236806,"count":0}],"isBlockCoverage":false},{"functionName":"Trace_Trace$from","ranges":[{"startOffset":236839,"endOffset":237153,"count":0}],"isBlockCoverage":false},{"functionName":"Trace_Trace$parse","ranges":[{"startOffset":237178,"endOffset":238690,"count":0}],"isBlockCoverage":false},{"functionName":"Trace__parseVM","ranges":[{"startOffset":238712,"endOffset":239434,"count":0}],"isBlockCoverage":false},{"functionName":"Trace$parseV8","ranges":[{"startOffset":239455,"endOffset":240083,"count":0}],"isBlockCoverage":false},{"functionName":"Trace$parseJSCore","ranges":[{"startOffset":240108,"endOffset":240613,"count":0}],"isBlockCoverage":false},{"functionName":"Trace$parseFirefox","ranges":[{"startOffset":240639,"endOffset":241158,"count":0}],"isBlockCoverage":false},{"functionName":"Trace$parseFriendly","ranges":[{"startOffset":241185,"endOffset":241840,"count":0}],"isBlockCoverage":false},{"functionName":"Trace","ranges":[{"startOffset":241853,"endOffset":241933,"count":0}],"isBlockCoverage":false},{"functionName":"Trace_Trace$from_closure","ranges":[{"startOffset":241965,"endOffset":242033,"count":0}],"isBlockCoverage":false},{"functionName":"Trace__parseVM_closure","ranges":[{"startOffset":242063,"endOffset":242104,"count":0}],"isBlockCoverage":false},{"functionName":"Trace$parseV8_closure","ranges":[{"startOffset":242133,"endOffset":242173,"count":0}],"isBlockCoverage":false},{"functionName":"Trace$parseV8_closure0","ranges":[{"startOffset":242203,"endOffset":242244,"count":0}],"isBlockCoverage":false},{"functionName":"Trace$parseJSCore_closure","ranges":[{"startOffset":242277,"endOffset":242321,"count":0}],"isBlockCoverage":false},{"functionName":"Trace$parseJSCore_closure0","ranges":[{"startOffset":242355,"endOffset":242400,"count":0}],"isBlockCoverage":false},{"functionName":"Trace$parseFirefox_closure","ranges":[{"startOffset":242434,"endOffset":242479,"count":0}],"isBlockCoverage":false},{"functionName":"Trace$parseFirefox_closure0","ranges":[{"startOffset":242514,"endOffset":242560,"count":0}],"isBlockCoverage":false},{"functionName":"Trace$parseFriendly_closure","ranges":[{"startOffset":242595,"endOffset":242641,"count":0}],"isBlockCoverage":false},{"functionName":"Trace$parseFriendly_closure0","ranges":[{"startOffset":242677,"endOffset":242724,"count":0}],"isBlockCoverage":false},{"functionName":"Trace_terse_closure","ranges":[{"startOffset":242751,"endOffset":242789,"count":0}],"isBlockCoverage":false},{"functionName":"Trace_foldFrames_closure","ranges":[{"startOffset":242821,"endOffset":242896,"count":0}],"isBlockCoverage":false},{"functionName":"Trace_foldFrames_closure0","ranges":[{"startOffset":242929,"endOffset":242999,"count":0}],"isBlockCoverage":false},{"functionName":"Trace_toString_closure0","ranges":[{"startOffset":243030,"endOffset":243072,"count":0}],"isBlockCoverage":false},{"functionName":"Trace_toString_closure","ranges":[{"startOffset":243102,"endOffset":243170,"count":0}],"isBlockCoverage":false},{"functionName":"UnparsedFrame","ranges":[{"startOffset":243198,"endOffset":243437,"count":0}],"isBlockCoverage":false},{"functionName":"GuaranteeChannel$","ranges":[{"startOffset":243471,"endOffset":243729,"count":1}],"isBlockCoverage":true},{"functionName":"GuaranteeChannel","ranges":[{"startOffset":243753,"endOffset":243940,"count":1}],"isBlockCoverage":true},{"functionName":"GuaranteeChannel_closure","ranges":[{"startOffset":243972,"endOffset":244068,"count":1}],"isBlockCoverage":true},{"functionName":"GuaranteeChannel__closure","ranges":[{"startOffset":244101,"endOffset":244170,"count":1}],"isBlockCoverage":true},{"functionName":"_GuaranteeSink","ranges":[{"startOffset":244192,"endOffset":244487,"count":1}],"isBlockCoverage":true},{"functionName":"_GuaranteeSink_addStream_closure","ranges":[{"startOffset":244527,"endOffset":244603,"count":1}],"isBlockCoverage":true},{"functionName":"main","ranges":[{"startOffset":244615,"endOffset":244926,"count":1},{"startOffset":244690,"endOffset":244714,"count":0}],"isBlockCoverage":true},{"functionName":"_connectToServer","ranges":[{"startOffset":244950,"endOffset":245613,"count":1}],"isBlockCoverage":true},{"functionName":"_connectToIframe","ranges":[{"startOffset":245637,"endOffset":247021,"count":1}],"isBlockCoverage":true},{"functionName":"_TestRunner","ranges":[{"startOffset":247040,"endOffset":247070,"count":0}],"isBlockCoverage":false},{"functionName":"_JSApi","ranges":[{"startOffset":247084,"endOffset":247109,"count":0}],"isBlockCoverage":false},{"functionName":"main_closure","ranges":[{"startOffset":247129,"endOffset":247160,"count":1}],"isBlockCoverage":true},{"functionName":"main__closure","ranges":[{"startOffset":247181,"endOffset":247246,"count":1}],"isBlockCoverage":true},{"functionName":"main__closure0","ranges":[{"startOffset":247268,"endOffset":247334,"count":1}],"isBlockCoverage":true},{"functionName":"main__closure1","ranges":[{"startOffset":247356,"endOffset":247422,"count":1}],"isBlockCoverage":true},{"functionName":"main__closure2","ranges":[{"startOffset":247444,"endOffset":247510,"count":1}],"isBlockCoverage":true},{"functionName":"main__closure3","ranges":[{"startOffset":247532,"endOffset":247598,"count":1}],"isBlockCoverage":true},{"functionName":"main_closure0","ranges":[{"startOffset":247619,"endOffset":247651,"count":1}],"isBlockCoverage":true},{"functionName":"_connectToServer_closure","ranges":[{"startOffset":247683,"endOffset":247756,"count":1}],"isBlockCoverage":true},{"functionName":"_connectToServer_closure0","ranges":[{"startOffset":247789,"endOffset":247862,"count":1}],"isBlockCoverage":true},{"functionName":"_connectToIframe_closure","ranges":[{"startOffset":247894,"endOffset":248068,"count":1}],"isBlockCoverage":true},{"functionName":"_connectToIframe_closure0","ranges":[{"startOffset":248101,"endOffset":248175,"count":1}],"isBlockCoverage":true},{"functionName":"_connectToIframe_closure1","ranges":[{"startOffset":248208,"endOffset":248315,"count":1}],"isBlockCoverage":true},{"functionName":"_MultiChannel$","ranges":[{"startOffset":248349,"endOffset":248683,"count":1}],"isBlockCoverage":true},{"functionName":"_MultiChannel","ranges":[{"startOffset":248704,"endOffset":249002,"count":1}],"isBlockCoverage":true},{"functionName":"_MultiChannel_closure","ranges":[{"startOffset":249031,"endOffset":249119,"count":1}],"isBlockCoverage":true},{"functionName":"_MultiChannel_closure0","ranges":[{"startOffset":249149,"endOffset":249215,"count":1}],"isBlockCoverage":true},{"functionName":"_MultiChannel_closure1","ranges":[{"startOffset":249245,"endOffset":249334,"count":1}],"isBlockCoverage":true},{"functionName":"_MultiChannel__closure","ranges":[{"startOffset":249364,"endOffset":249477,"count":1}],"isBlockCoverage":true},{"functionName":"_MultiChannel_virtualChannel_closure","ranges":[{"startOffset":249521,"endOffset":249629,"count":1}],"isBlockCoverage":true},{"functionName":"_MultiChannel_virtualChannel_closure0","ranges":[{"startOffset":249674,"endOffset":249783,"count":1}],"isBlockCoverage":true},{"functionName":"VirtualChannel","ranges":[{"startOffset":249805,"endOffset":249952,"count":1}],"isBlockCoverage":true},{"functionName":"current","ranges":[{"startOffset":249967,"endOffset":250526,"count":0}],"isBlockCoverage":false},{"functionName":"StreamChannelMixin","ranges":[{"startOffset":250559,"endOffset":250596,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":250814,"endOffset":250880,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":250900,"endOffset":250978,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":250996,"endOffset":251098,"count":0}],"isBlockCoverage":false},{"functionName":"noSuchMethod$1","ranges":[{"startOffset":251120,"endOffset":251378,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":251425,"endOffset":251482,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":251502,"endOffset":251569,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":251625,"endOffset":251686,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":251704,"endOffset":251751,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":251771,"endOffset":251813,"count":0}],"isBlockCoverage":false},{"functionName":"noSuchMethod$1","ranges":[{"startOffset":251835,"endOffset":251986,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":252061,"endOffset":252103,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":252121,"endOffset":252178,"count":0}],"isBlockCoverage":false},{"functionName":"waitUntilDone$0","ranges":[{"startOffset":252201,"endOffset":252266,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":252411,"endOffset":252677,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":252695,"endOffset":252762,"count":0}],"isBlockCoverage":false},{"functionName":"add$1","ranges":[{"startOffset":252825,"endOffset":253058,"count":1},{"startOffset":252978,"endOffset":253024,"count":0}],"isBlockCoverage":true},{"functionName":"removeAt$1","ranges":[{"startOffset":253076,"endOffset":253376,"count":0}],"isBlockCoverage":false},{"functionName":"insert$2","ranges":[{"startOffset":253392,"endOffset":253775,"count":0}],"isBlockCoverage":false},{"functionName":"insertAll$2","ranges":[{"startOffset":253794,"endOffset":254419,"count":0}],"isBlockCoverage":false},{"functionName":"removeLast$0","ranges":[{"startOffset":254439,"endOffset":254691,"count":0}],"isBlockCoverage":false},{"functionName":"addAll$1","ranges":[{"startOffset":254707,"endOffset":255155,"count":0}],"isBlockCoverage":false},{"functionName":"forEach$1","ranges":[{"startOffset":255172,"endOffset":255530,"count":0}],"isBlockCoverage":false},{"functionName":"join$1","ranges":[{"startOffset":255544,"endOffset":255804,"count":0}],"isBlockCoverage":false},{"functionName":"join$0","ranges":[{"startOffset":255818,"endOffset":255886,"count":0}],"isBlockCoverage":false},{"functionName":"fold$1$2","ranges":[{"startOffset":255902,"endOffset":256434,"count":1},{"startOffset":256336,"endOffset":256400,"count":0}],"isBlockCoverage":true},{"functionName":"elementAt$1","ranges":[{"startOffset":256453,"endOffset":256606,"count":0}],"isBlockCoverage":false},{"functionName":"sublist$2","ranges":[{"startOffset":256623,"endOffset":257154,"count":0}],"isBlockCoverage":false},{"functionName":"get$first","ranges":[{"startOffset":257171,"endOffset":257321,"count":0}],"isBlockCoverage":false},{"functionName":"get$last","ranges":[{"startOffset":257337,"endOffset":257511,"count":0}],"isBlockCoverage":false},{"functionName":"setRange$4","ranges":[{"startOffset":257529,"endOffset":258508,"count":0}],"isBlockCoverage":false},{"functionName":"setRange$3","ranges":[{"startOffset":258526,"endOffset":258641,"count":0}],"isBlockCoverage":false},{"functionName":"get$isNotEmpty","ranges":[{"startOffset":258663,"endOffset":258725,"count":1}],"isBlockCoverage":true},{"functionName":"toString$0","ranges":[{"startOffset":258743,"endOffset":258839,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":258859,"endOffset":258990,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":259010,"endOffset":259088,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":259106,"endOffset":259162,"count":1}],"isBlockCoverage":true},{"functionName":"set$length","ranges":[{"startOffset":259180,"endOffset":259464,"count":1},{"startOffset":259255,"endOffset":259308,"count":0},{"startOffset":259342,"endOffset":259423,"count":0}],"isBlockCoverage":true},{"functionName":"$index","ranges":[{"startOffset":259478,"endOffset":259689,"count":1},{"startOffset":259592,"endOffset":259653,"count":0}],"isBlockCoverage":true},{"functionName":"$indexSet","ranges":[{"startOffset":259706,"endOffset":260245,"count":1},{"startOffset":259897,"endOffset":259951,"count":0},{"startOffset":260028,"endOffset":260089,"count":0},{"startOffset":260147,"endOffset":260208,"count":0}],"isBlockCoverage":true},{"functionName":"get$current","ranges":[{"startOffset":260411,"endOffset":260472,"count":0}],"isBlockCoverage":false},{"functionName":"moveNext$0","ranges":[{"startOffset":260490,"endOffset":260928,"count":0}],"isBlockCoverage":false},{"functionName":"set$__interceptors$_current","ranges":[{"startOffset":260963,"endOffset":261101,"count":0}],"isBlockCoverage":false},{"functionName":"toRadixString$1","ranges":[{"startOffset":261175,"endOffset":262041,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":262059,"endOffset":262195,"count":1},{"startOffset":262134,"endOffset":262148,"count":0}],"isBlockCoverage":true},{"functionName":"get$hashCode","ranges":[{"startOffset":262215,"endOffset":262729,"count":0}],"isBlockCoverage":false},{"functionName":"$mod","ranges":[{"startOffset":262741,"endOffset":262992,"count":0}],"isBlockCoverage":false},{"functionName":"$tdiv","ranges":[{"startOffset":263005,"endOffset":263202,"count":0}],"isBlockCoverage":false},{"functionName":"_tdivFast$1","ranges":[{"startOffset":263221,"endOffset":263355,"count":1},{"startOffset":263313,"endOffset":263348,"count":0}],"isBlockCoverage":true},{"functionName":"_tdivSlow$1","ranges":[{"startOffset":263374,"endOffset":263848,"count":0}],"isBlockCoverage":false},{"functionName":"_shrOtherPositive$1","ranges":[{"startOffset":263875,"endOffset":264112,"count":1},{"startOffset":263995,"endOffset":264089,"count":0}],"isBlockCoverage":true},{"functionName":"_shrReceiverPositive$1","ranges":[{"startOffset":264142,"endOffset":264311,"count":0}],"isBlockCoverage":false},{"functionName":"_shrBothPositive$1","ranges":[{"startOffset":264337,"endOffset":264420,"count":1},{"startOffset":264389,"endOffset":264392,"count":0}],"isBlockCoverage":true},{"functionName":"$gt","ranges":[{"startOffset":264431,"endOffset":264592,"count":0}],"isBlockCoverage":false},{"functionName":"codeUnitAt$1","ranges":[{"startOffset":264740,"endOffset":265145,"count":1},{"startOffset":264844,"endOffset":264905,"count":0},{"startOffset":264935,"endOffset":264996,"count":0},{"startOffset":265041,"endOffset":265098,"count":0}],"isBlockCoverage":true},{"functionName":"_codeUnitAt$1","ranges":[{"startOffset":265166,"endOffset":265346,"count":1},{"startOffset":265238,"endOffset":265299,"count":0}],"isBlockCoverage":true},{"functionName":"allMatches$2","ranges":[{"startOffset":265366,"endOffset":265723,"count":0}],"isBlockCoverage":false},{"functionName":"allMatches$1","ranges":[{"startOffset":265743,"endOffset":265832,"count":0}],"isBlockCoverage":false},{"functionName":"matchAsPrefix$2","ranges":[{"startOffset":265855,"endOffset":266378,"count":0}],"isBlockCoverage":false},{"functionName":"$add","ranges":[{"startOffset":266390,"endOffset":266564,"count":0}],"isBlockCoverage":false},{"functionName":"endsWith$1","ranges":[{"startOffset":266582,"endOffset":266823,"count":0}],"isBlockCoverage":false},{"functionName":"replaceFirst$2","ranges":[{"startOffset":266845,"endOffset":267026,"count":0}],"isBlockCoverage":false},{"functionName":"replaceRange$3","ranges":[{"startOffset":267048,"endOffset":267373,"count":0}],"isBlockCoverage":false},{"functionName":"startsWith$2","ranges":[{"startOffset":267393,"endOffset":268070,"count":1},{"startOffset":267526,"endOffset":267573,"count":0},{"startOffset":267619,"endOffset":267638,"count":0},{"startOffset":267695,"endOffset":267776,"count":0},{"startOffset":267911,"endOffset":267924,"count":0},{"startOffset":267996,"endOffset":268069,"count":0}],"isBlockCoverage":true},{"functionName":"startsWith$1","ranges":[{"startOffset":268090,"endOffset":268181,"count":1}],"isBlockCoverage":true},{"functionName":"substring$2","ranges":[{"startOffset":268200,"endOffset":268888,"count":1},{"startOffset":268334,"endOffset":268386,"count":0},{"startOffset":268501,"endOffset":268525,"count":0},{"startOffset":268560,"endOffset":268620,"count":0},{"startOffset":268662,"endOffset":268722,"count":0},{"startOffset":268769,"endOffset":268827,"count":0}],"isBlockCoverage":true},{"functionName":"substring$1","ranges":[{"startOffset":268907,"endOffset":269006,"count":1}],"isBlockCoverage":true},{"functionName":"trim$0","ranges":[{"startOffset":269020,"endOffset":269700,"count":0}],"isBlockCoverage":false},{"functionName":"$mul","ranges":[{"startOffset":269712,"endOffset":270191,"count":0}],"isBlockCoverage":false},{"functionName":"padRight$1","ranges":[{"startOffset":270209,"endOffset":270458,"count":0}],"isBlockCoverage":false},{"functionName":"indexOf$2","ranges":[{"startOffset":270475,"endOffset":270731,"count":1},{"startOffset":270582,"endOffset":270663,"count":0}],"isBlockCoverage":true},{"functionName":"indexOf$1","ranges":[{"startOffset":270748,"endOffset":270836,"count":1}],"isBlockCoverage":true},{"functionName":"lastIndexOf$2","ranges":[{"startOffset":270857,"endOffset":271276,"count":0}],"isBlockCoverage":false},{"functionName":"lastIndexOf$1","ranges":[{"startOffset":271297,"endOffset":271392,"count":0}],"isBlockCoverage":false},{"functionName":"contains$1","ranges":[{"startOffset":271410,"endOffset":271584,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":271602,"endOffset":271651,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":271671,"endOffset":272077,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":272095,"endOffset":272151,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":272165,"endOffset":272372,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":272459,"endOffset":272512,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":272526,"endOffset":272627,"count":0}],"isBlockCoverage":false},{"functionName":"$asEfficientLengthIterable","ranges":[{"startOffset":272661,"endOffset":272701,"count":0}],"isBlockCoverage":false},{"functionName":"$asUnmodifiableListMixin","ranges":[{"startOffset":272733,"endOffset":272773,"count":0}],"isBlockCoverage":false},{"functionName":"$asListMixin","ranges":[{"startOffset":272793,"endOffset":272833,"count":0}],"isBlockCoverage":false},{"functionName":"$asIterable","ranges":[{"startOffset":272852,"endOffset":272892,"count":0}],"isBlockCoverage":false},{"functionName":"$asList","ranges":[{"startOffset":272907,"endOffset":272947,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":273046,"endOffset":273183,"count":0}],"isBlockCoverage":false},{"functionName":"get$isEmpty","ranges":[{"startOffset":273202,"endOffset":273263,"count":0}],"isBlockCoverage":false},{"functionName":"join$1","ranges":[{"startOffset":273277,"endOffset":274216,"count":0}],"isBlockCoverage":false},{"functionName":"join$0","ranges":[{"startOffset":274230,"endOffset":274298,"count":0}],"isBlockCoverage":false},{"functionName":"fold$1$2","ranges":[{"startOffset":274314,"endOffset":274870,"count":0}],"isBlockCoverage":false},{"functionName":"toList$1$growable","ranges":[{"startOffset":274895,"endOffset":275249,"count":0}],"isBlockCoverage":false},{"functionName":"toList$0","ranges":[{"startOffset":275265,"endOffset":275346,"count":0}],"isBlockCoverage":false},{"functionName":"get$_endIndex","ranges":[{"startOffset":275405,"endOffset":275616,"count":0}],"isBlockCoverage":false},{"functionName":"get$_startIndex","ranges":[{"startOffset":275639,"endOffset":275841,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":275859,"endOffset":276224,"count":0}],"isBlockCoverage":false},{"functionName":"elementAt$1","ranges":[{"startOffset":276243,"endOffset":276692,"count":0}],"isBlockCoverage":false},{"functionName":"get$current","ranges":[{"startOffset":276746,"endOffset":276803,"count":0}],"isBlockCoverage":false},{"functionName":"moveNext$0","ranges":[{"startOffset":276821,"endOffset":277341,"count":0}],"isBlockCoverage":false},{"functionName":"set$__internal$_current","ranges":[{"startOffset":277372,"endOffset":277506,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":277583,"endOffset":277702,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":277720,"endOffset":277797,"count":0}],"isBlockCoverage":false},{"functionName":"$asIterable","ranges":[{"startOffset":277816,"endOffset":277859,"count":0}],"isBlockCoverage":false},{"functionName":"$asEfficientLengthIterable","ranges":[{"startOffset":277975,"endOffset":278018,"count":0}],"isBlockCoverage":false},{"functionName":"moveNext$0","ranges":[{"startOffset":278073,"endOffset":278314,"count":0}],"isBlockCoverage":false},{"functionName":"get$current","ranges":[{"startOffset":278333,"endOffset":278390,"count":0}],"isBlockCoverage":false},{"functionName":"set$__internal$_current","ranges":[{"startOffset":278421,"endOffset":278555,"count":0}],"isBlockCoverage":false},{"functionName":"$asIterator","ranges":[{"startOffset":278574,"endOffset":278617,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":278676,"endOffset":278740,"count":0}],"isBlockCoverage":false},{"functionName":"elementAt$1","ranges":[{"startOffset":278759,"endOffset":278853,"count":0}],"isBlockCoverage":false},{"functionName":"$asEfficientLengthIterable","ranges":[{"startOffset":278887,"endOffset":278930,"count":0}],"isBlockCoverage":false},{"functionName":"$asListIterable","ranges":[{"startOffset":278953,"endOffset":278996,"count":0}],"isBlockCoverage":false},{"functionName":"$asIterable","ranges":[{"startOffset":279015,"endOffset":279058,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":279114,"endOffset":279232,"count":0}],"isBlockCoverage":false},{"functionName":"moveNext$0","ranges":[{"startOffset":279286,"endOffset":279470,"count":0}],"isBlockCoverage":false},{"functionName":"get$current","ranges":[{"startOffset":279489,"endOffset":279550,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":279607,"endOffset":279745,"count":0}],"isBlockCoverage":false},{"functionName":"$asIterable","ranges":[{"startOffset":279764,"endOffset":279807,"count":0}],"isBlockCoverage":false},{"functionName":"get$current","ranges":[{"startOffset":279863,"endOffset":279920,"count":0}],"isBlockCoverage":false},{"functionName":"moveNext$0","ranges":[{"startOffset":279938,"endOffset":280470,"count":0}],"isBlockCoverage":false},{"functionName":"set$_currentExpansion","ranges":[{"startOffset":280499,"endOffset":280668,"count":0}],"isBlockCoverage":false},{"functionName":"set$__internal$_current","ranges":[{"startOffset":280699,"endOffset":280833,"count":0}],"isBlockCoverage":false},{"functionName":"$asIterator","ranges":[{"startOffset":280872,"endOffset":280915,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":280975,"endOffset":281097,"count":0}],"isBlockCoverage":false},{"functionName":"moveNext$0","ranges":[{"startOffset":281155,"endOffset":281440,"count":0}],"isBlockCoverage":false},{"functionName":"get$current","ranges":[{"startOffset":281459,"endOffset":281520,"count":0}],"isBlockCoverage":false},{"functionName":"moveNext$0","ranges":[{"startOffset":281574,"endOffset":281612,"count":0}],"isBlockCoverage":false},{"functionName":"get$current","ranges":[{"startOffset":281631,"endOffset":281663,"count":0}],"isBlockCoverage":false},{"functionName":"$indexSet","ranges":[{"startOffset":281785,"endOffset":282038,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":282140,"endOffset":282204,"count":0}],"isBlockCoverage":false},{"functionName":"elementAt$1","ranges":[{"startOffset":282223,"endOffset":282393,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":282442,"endOffset":282661,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":282679,"endOffset":282759,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":282770,"endOffset":282934,"count":0}],"isBlockCoverage":false},{"functionName":"get$isEmpty","ranges":[{"startOffset":283042,"endOffset":283103,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":283121,"endOffset":283182,"count":0}],"isBlockCoverage":false},{"functionName":"$indexSet","ranges":[{"startOffset":283199,"endOffset":283429,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":283502,"endOffset":283560,"count":0}],"isBlockCoverage":false},{"functionName":"containsKey$1","ranges":[{"startOffset":283581,"endOffset":283761,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":283775,"endOffset":283884,"count":0}],"isBlockCoverage":false},{"functionName":"_fetch$1","ranges":[{"startOffset":283900,"endOffset":283974,"count":0}],"isBlockCoverage":false},{"functionName":"forEach$1","ranges":[{"startOffset":283991,"endOffset":284372,"count":0}],"isBlockCoverage":false},{"functionName":"Instantiation$1","ranges":[{"startOffset":284431,"endOffset":284530,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":284548,"endOffset":284741,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":284792,"endOffset":284881,"count":0}],"isBlockCoverage":false},{"functionName":"call$4","ranges":[{"startOffset":284895,"endOffset":285000,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":285018,"endOffset":285157,"count":0}],"isBlockCoverage":false},{"functionName":"get$memberName","ranges":[{"startOffset":285220,"endOffset":285288,"count":0}],"isBlockCoverage":false},{"functionName":"get$positionalArguments","ranges":[{"startOffset":285319,"endOffset":285850,"count":0}],"isBlockCoverage":false},{"functionName":"get$namedArguments","ranges":[{"startOffset":285876,"endOffset":286722,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":286820,"endOffset":287115,"count":0}],"isBlockCoverage":false},{"functionName":"matchTypeError$1","ranges":[{"startOffset":287198,"endOffset":287850,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":287900,"endOffset":288103,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":288163,"endOffset":288563,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":288622,"endOffset":288728,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":288838,"endOffset":289012,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":289083,"endOffset":289391,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":289461,"endOffset":289555,"count":0}],"isBlockCoverage":false},{"functionName":"get$$call","ranges":[{"startOffset":289592,"endOffset":289629,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":289793,"endOffset":289982,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":290028,"endOffset":290329,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":290349,"endOffset":290718,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":290736,"endOffset":290971,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":291035,"endOffset":291081,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":291145,"endOffset":291191,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":291244,"endOffset":291314,"count":0}],"isBlockCoverage":false},{"functionName":"get$_typeName","ranges":[{"startOffset":291366,"endOffset":291542,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":291560,"endOffset":291614,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":291634,"endOffset":291830,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":291841,"endOffset":292006,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":292062,"endOffset":292120,"count":1}],"isBlockCoverage":true},{"functionName":"get$isEmpty","ranges":[{"startOffset":292139,"endOffset":292203,"count":1}],"isBlockCoverage":true},{"functionName":"get$keys","ranges":[{"startOffset":292219,"endOffset":292325,"count":0}],"isBlockCoverage":false},{"functionName":"get$values","ranges":[{"startOffset":292343,"endOffset":292585,"count":0}],"isBlockCoverage":false},{"functionName":"containsKey$1","ranges":[{"startOffset":292606,"endOffset":293097,"count":1},{"startOffset":292682,"endOffset":292834,"count":0},{"startOffset":292963,"endOffset":292976,"count":0},{"startOffset":293038,"endOffset":293091,"count":0}],"isBlockCoverage":true},{"functionName":"internalContainsKey$1","ranges":[{"startOffset":293126,"endOffset":293341,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":293355,"endOffset":293981,"count":1},{"startOffset":293518,"endOffset":293525,"count":0},{"startOffset":293603,"endOffset":293609,"count":0},{"startOffset":293790,"endOffset":293797,"count":0},{"startOffset":293872,"endOffset":293878,"count":0},{"startOffset":293930,"endOffset":293975,"count":0}],"isBlockCoverage":true},{"functionName":"internalGet$1","ranges":[{"startOffset":294002,"endOffset":294339,"count":0}],"isBlockCoverage":false},{"functionName":"$indexSet","ranges":[{"startOffset":294356,"endOffset":295711,"count":1},{"startOffset":295102,"endOffset":295705,"count":0}],"isBlockCoverage":true},{"functionName":"putIfAbsent$2","ranges":[{"startOffset":295732,"endOffset":296105,"count":1},{"startOffset":296009,"endOffset":296104,"count":0}],"isBlockCoverage":true},{"functionName":"remove$1","ranges":[{"startOffset":296121,"endOffset":296430,"count":0}],"isBlockCoverage":false},{"functionName":"internalRemove$1","ranges":[{"startOffset":296454,"endOffset":296861,"count":0}],"isBlockCoverage":false},{"functionName":"clear$0","ranges":[{"startOffset":296876,"endOffset":297150,"count":0}],"isBlockCoverage":false},{"functionName":"forEach$1","ranges":[{"startOffset":297167,"endOffset":297681,"count":1},{"startOffset":297580,"endOffset":297640,"count":0}],"isBlockCoverage":true},{"functionName":"_addHashTableEntry$3","ranges":[{"startOffset":297709,"endOffset":298113,"count":1},{"startOffset":298057,"endOffset":298107,"count":0}],"isBlockCoverage":true},{"functionName":"_removeHashTableEntry$2","ranges":[{"startOffset":298144,"endOffset":298428,"count":0}],"isBlockCoverage":false},{"functionName":"_modified$0","ranges":[{"startOffset":298447,"endOffset":298529,"count":1}],"isBlockCoverage":true},{"functionName":"_newLinkedCell$2","ranges":[{"startOffset":298553,"endOffset":299085,"count":1}],"isBlockCoverage":true},{"functionName":"_unlinkCell$1","ranges":[{"startOffset":299106,"endOffset":299471,"count":0}],"isBlockCoverage":false},{"functionName":"internalFindBucketIndex$2","ranges":[{"startOffset":299504,"endOffset":299755,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":299773,"endOffset":299834,"count":0}],"isBlockCoverage":false},{"functionName":"_getTableCell$2","ranges":[{"startOffset":299857,"endOffset":299910,"count":1}],"isBlockCoverage":true},{"functionName":"_getTableBucket$2","ranges":[{"startOffset":299935,"endOffset":299988,"count":0}],"isBlockCoverage":false},{"functionName":"_setTableEntry$3","ranges":[{"startOffset":300012,"endOffset":300073,"count":1}],"isBlockCoverage":true},{"functionName":"_deleteTableEntry$2","ranges":[{"startOffset":300100,"endOffset":300153,"count":1}],"isBlockCoverage":true},{"functionName":"_containsTableEntry$2","ranges":[{"startOffset":300182,"endOffset":300265,"count":1}],"isBlockCoverage":true},{"functionName":"_newHashTable$0","ranges":[{"startOffset":300288,"endOffset":300495,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":300587,"endOffset":300732,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":300750,"endOffset":300898,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":301001,"endOffset":301076,"count":0}],"isBlockCoverage":false},{"functionName":"get$isEmpty","ranges":[{"startOffset":301095,"endOffset":301176,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":301196,"endOffset":301388,"count":0}],"isBlockCoverage":false},{"functionName":"get$current","ranges":[{"startOffset":301454,"endOffset":301512,"count":0}],"isBlockCoverage":false},{"functionName":"moveNext$0","ranges":[{"startOffset":301530,"endOffset":302000,"count":0}],"isBlockCoverage":false},{"functionName":"set$__js_helper$_current","ranges":[{"startOffset":302032,"endOffset":302167,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":302241,"endOffset":302289,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":302363,"endOffset":302428,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":302503,"endOffset":302583,"count":1}],"isBlockCoverage":true},{"functionName":"toString$0","ranges":[{"startOffset":302658,"endOffset":302722,"count":0}],"isBlockCoverage":false},{"functionName":"get$_nativeGlobalVersion","ranges":[{"startOffset":302754,"endOffset":303029,"count":0}],"isBlockCoverage":false},{"functionName":"get$_nativeAnchoredVersion","ranges":[{"startOffset":303063,"endOffset":303350,"count":0}],"isBlockCoverage":false},{"functionName":"firstMatch$1","ranges":[{"startOffset":303370,"endOffset":303626,"count":0}],"isBlockCoverage":false},{"functionName":"allMatches$2","ranges":[{"startOffset":303646,"endOffset":303862,"count":0}],"isBlockCoverage":false},{"functionName":"allMatches$1","ranges":[{"startOffset":303882,"endOffset":303971,"count":0}],"isBlockCoverage":false},{"functionName":"_execGlobal$2","ranges":[{"startOffset":303992,"endOffset":304252,"count":0}],"isBlockCoverage":false},{"functionName":"_execAnchored$2","ranges":[{"startOffset":304275,"endOffset":304648,"count":0}],"isBlockCoverage":false},{"functionName":"matchAsPrefix$2","ranges":[{"startOffset":304671,"endOffset":304954,"count":0}],"isBlockCoverage":false},{"functionName":"get$start","ranges":[{"startOffset":305051,"endOffset":305102,"count":0}],"isBlockCoverage":false},{"functionName":"get$end","ranges":[{"startOffset":305117,"endOffset":305201,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":305215,"endOffset":305397,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":305476,"endOffset":305584,"count":0}],"isBlockCoverage":false},{"functionName":"$asIterable","ranges":[{"startOffset":305603,"endOffset":305645,"count":0}],"isBlockCoverage":false},{"functionName":"get$current","ranges":[{"startOffset":305706,"endOffset":305764,"count":0}],"isBlockCoverage":false},{"functionName":"moveNext$0","ranges":[{"startOffset":305782,"endOffset":306369,"count":0}],"isBlockCoverage":false},{"functionName":"$asIterator","ranges":[{"startOffset":306408,"endOffset":306450,"count":0}],"isBlockCoverage":false},{"functionName":"get$end","ranges":[{"startOffset":306499,"endOffset":306643,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":306657,"endOffset":306806,"count":0}],"isBlockCoverage":false},{"functionName":"get$start","ranges":[{"startOffset":306840,"endOffset":306891,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":306959,"endOffset":307077,"count":0}],"isBlockCoverage":false},{"functionName":"$asIterable","ranges":[{"startOffset":307096,"endOffset":307138,"count":0}],"isBlockCoverage":false},{"functionName":"moveNext$0","ranges":[{"startOffset":307204,"endOffset":307851,"count":0}],"isBlockCoverage":false},{"functionName":"get$current","ranges":[{"startOffset":307870,"endOffset":307928,"count":0}],"isBlockCoverage":false},{"functionName":"$asIterator","ranges":[{"startOffset":307967,"endOffset":308009,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":308182,"endOffset":308238,"count":0}],"isBlockCoverage":false},{"functionName":"$asJavaScriptIndexingBehavior","ranges":[{"startOffset":308313,"endOffset":308331,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":308392,"endOffset":308544,"count":0}],"isBlockCoverage":false},{"functionName":"$indexSet","ranges":[{"startOffset":308561,"endOffset":308753,"count":0}],"isBlockCoverage":false},{"functionName":"$asEfficientLengthIterable","ranges":[{"startOffset":308822,"endOffset":308865,"count":0}],"isBlockCoverage":false},{"functionName":"$asFixedLengthListMixin","ranges":[{"startOffset":308896,"endOffset":308939,"count":0}],"isBlockCoverage":false},{"functionName":"$asListMixin","ranges":[{"startOffset":308959,"endOffset":309002,"count":0}],"isBlockCoverage":false},{"functionName":"$asIterable","ranges":[{"startOffset":309041,"endOffset":309084,"count":0}],"isBlockCoverage":false},{"functionName":"$asList","ranges":[{"startOffset":309115,"endOffset":309158,"count":0}],"isBlockCoverage":false},{"functionName":"$indexSet","ranges":[{"startOffset":309219,"endOffset":309408,"count":1}],"isBlockCoverage":true},{"functionName":"$asEfficientLengthIterable","ranges":[{"startOffset":309477,"endOffset":309517,"count":0}],"isBlockCoverage":false},{"functionName":"$asFixedLengthListMixin","ranges":[{"startOffset":309548,"endOffset":309588,"count":0}],"isBlockCoverage":false},{"functionName":"$asListMixin","ranges":[{"startOffset":309608,"endOffset":309648,"count":1}],"isBlockCoverage":true},{"functionName":"$asIterable","ranges":[{"startOffset":309687,"endOffset":309727,"count":0}],"isBlockCoverage":false},{"functionName":"$asList","ranges":[{"startOffset":309758,"endOffset":309798,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":309850,"endOffset":310002,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":310054,"endOffset":310206,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":310257,"endOffset":310409,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":310462,"endOffset":310614,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":310667,"endOffset":310819,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":310882,"endOffset":310938,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":310952,"endOffset":311104,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":311160,"endOffset":311216,"count":1}],"isBlockCoverage":true},{"functionName":"$index","ranges":[{"startOffset":311230,"endOffset":311382,"count":0}],"isBlockCoverage":false},{"functionName":"sublist$2","ranges":[{"startOffset":311399,"endOffset":311541,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":312009,"endOffset":312148,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":312250,"endOffset":312486,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":312598,"endOffset":312646,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":312812,"endOffset":312860,"count":0}],"isBlockCoverage":false},{"functionName":"_TimerImpl$2","ranges":[{"startOffset":312981,"endOffset":313267,"count":0}],"isBlockCoverage":false},{"functionName":"_TimerImpl$periodic$2","ranges":[{"startOffset":313296,"endOffset":313599,"count":1},{"startOffset":313511,"endOffset":313593,"count":0}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":313680,"endOffset":313756,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":313888,"endOffset":314241,"count":0}],"isBlockCoverage":false},{"functionName":"complete$1","ranges":[{"startOffset":314370,"endOffset":314852,"count":1},{"startOffset":314559,"endOffset":314846,"count":0}],"isBlockCoverage":true},{"functionName":"completeError$2","ranges":[{"startOffset":314875,"endOffset":315072,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":315167,"endOffset":315240,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":315387,"endOffset":315467,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":315594,"endOffset":315668,"count":1}],"isBlockCoverage":true},{"functionName":"call$2","ranges":[{"startOffset":315747,"endOffset":315907,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":316044,"endOffset":316137,"count":1}],"isBlockCoverage":true},{"functionName":"completeError$2","ranges":[{"startOffset":316289,"endOffset":316893,"count":0}],"isBlockCoverage":false},{"functionName":"completeError$1","ranges":[{"startOffset":316916,"endOffset":316987,"count":0}],"isBlockCoverage":false},{"functionName":"complete$1","ranges":[{"startOffset":317064,"endOffset":317349,"count":1},{"startOffset":317244,"endOffset":317309,"count":0}],"isBlockCoverage":true},{"functionName":"complete$0","ranges":[{"startOffset":317367,"endOffset":317441,"count":1}],"isBlockCoverage":true},{"functionName":"_completeError$2","ranges":[{"startOffset":317465,"endOffset":317560,"count":0}],"isBlockCoverage":false},{"functionName":"complete$1","ranges":[{"startOffset":317615,"endOffset":317895,"count":1},{"startOffset":317795,"endOffset":317860,"count":0}],"isBlockCoverage":true},{"functionName":"complete$0","ranges":[{"startOffset":317913,"endOffset":317987,"count":0}],"isBlockCoverage":false},{"functionName":"_completeError$2","ranges":[{"startOffset":318011,"endOffset":318101,"count":0}],"isBlockCoverage":false},{"functionName":"matchesErrorTest$1","ranges":[{"startOffset":318165,"endOffset":318401,"count":0}],"isBlockCoverage":false},{"functionName":"handleError$1","ranges":[{"startOffset":318422,"endOffset":319026,"count":0}],"isBlockCoverage":false},{"functionName":"then$1$2$onError","ranges":[{"startOffset":319080,"endOffset":319598,"count":1},{"startOffset":319465,"endOffset":319521,"count":0}],"isBlockCoverage":true},{"functionName":"then$1$1","ranges":[{"startOffset":319614,"endOffset":319686,"count":1}],"isBlockCoverage":true},{"functionName":"_thenNoZoneRegistration$1$2","ranges":[{"startOffset":319721,"endOffset":320105,"count":1}],"isBlockCoverage":true},{"functionName":"whenComplete$1","ranges":[{"startOffset":320127,"endOffset":320534,"count":0}],"isBlockCoverage":false},{"functionName":"_addListener$1","ranges":[{"startOffset":320556,"endOffset":321250,"count":1},{"startOffset":320829,"endOffset":321144,"count":0}],"isBlockCoverage":true},{"functionName":"_prependListeners$1","ranges":[{"startOffset":321277,"endOffset":322404,"count":0}],"isBlockCoverage":false},{"functionName":"_removeListeners$0","ranges":[{"startOffset":322430,"endOffset":322625,"count":1}],"isBlockCoverage":true},{"functionName":"_reverseListeners$1","ranges":[{"startOffset":322652,"endOffset":322909,"count":1}],"isBlockCoverage":true},{"functionName":"_complete$1","ranges":[{"startOffset":322928,"endOffset":323583,"count":1},{"startOffset":323168,"endOffset":323336,"count":0}],"isBlockCoverage":true},{"functionName":"_completeError$2","ranges":[{"startOffset":323607,"endOffset":323915,"count":0}],"isBlockCoverage":false},{"functionName":"_completeError$1","ranges":[{"startOffset":323939,"endOffset":324011,"count":0}],"isBlockCoverage":false},{"functionName":"_asyncComplete$1","ranges":[{"startOffset":324035,"endOffset":324387,"count":1},{"startOffset":324208,"endOffset":324269,"count":0}],"isBlockCoverage":true},{"functionName":"_chainFuture$1","ranges":[{"startOffset":324409,"endOffset":324868,"count":0}],"isBlockCoverage":false},{"functionName":"_asyncCompleteError$2","ranges":[{"startOffset":324897,"endOffset":325120,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":325203,"endOffset":325287,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":325425,"endOffset":325517,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":325657,"endOffset":325758,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":325850,"endOffset":325999,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":326013,"endOffset":326075,"count":0}],"isBlockCoverage":false},{"functionName":"$defaultValues","ranges":[{"startOffset":326120,"endOffset":326159,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":326252,"endOffset":326322,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":326457,"endOffset":326765,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":326898,"endOffset":326974,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":327114,"endOffset":327196,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":327357,"endOffset":328955,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":329075,"endOffset":329128,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":329234,"endOffset":329953,"count":1},{"startOffset":329710,"endOffset":329947,"count":0}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":330050,"endOffset":330966,"count":0}],"isBlockCoverage":false},{"functionName":"pipe$1","ranges":[{"startOffset":331068,"endOffset":331333,"count":1}],"isBlockCoverage":true},{"functionName":"get$length","ranges":[{"startOffset":331351,"endOffset":331673,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":331729,"endOffset":331793,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":331871,"endOffset":332007,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":332025,"endOffset":332139,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":332198,"endOffset":332266,"count":0}],"isBlockCoverage":false},{"functionName":"get$_pendingEvents","ranges":[{"startOffset":332504,"endOffset":332877,"count":1},{"startOffset":332650,"endOffset":332876,"count":0}],"isBlockCoverage":true},{"functionName":"_ensurePendingEvents$0","ranges":[{"startOffset":332907,"endOffset":333600,"count":0}],"isBlockCoverage":false},{"functionName":"get$_subscription","ranges":[{"startOffset":333625,"endOffset":334046,"count":1},{"startOffset":333673,"endOffset":333925,"count":0}],"isBlockCoverage":true},{"functionName":"_badEventState$0","ranges":[{"startOffset":334070,"endOffset":334263,"count":0}],"isBlockCoverage":false},{"functionName":"_ensureDoneFuture$0","ranges":[{"startOffset":334290,"endOffset":334533,"count":0}],"isBlockCoverage":false},{"functionName":"add$1","ranges":[{"startOffset":334546,"endOffset":334760,"count":1},{"startOffset":334681,"endOffset":334728,"count":0}],"isBlockCoverage":true},{"functionName":"addError$2","ranges":[{"startOffset":334778,"endOffset":335358,"count":0}],"isBlockCoverage":false},{"functionName":"addError$1","ranges":[{"startOffset":335376,"endOffset":335442,"count":0}],"isBlockCoverage":false},{"functionName":"close$0","ranges":[{"startOffset":335457,"endOffset":335879,"count":0}],"isBlockCoverage":false},{"functionName":"_add$1","ranges":[{"startOffset":335893,"endOffset":336207,"count":1},{"startOffset":336085,"endOffset":336201,"count":0}],"isBlockCoverage":true},{"functionName":"_async$_addError$2","ranges":[{"startOffset":336233,"endOffset":336487,"count":0}],"isBlockCoverage":false},{"functionName":"_subscribe$4","ranges":[{"startOffset":336507,"endOffset":337709,"count":1},{"startOffset":336834,"endOffset":336911,"count":0},{"startOffset":336965,"endOffset":336968,"count":0},{"startOffset":337264,"endOffset":337491,"count":0}],"isBlockCoverage":true},{"functionName":"_recordCancel$1","ranges":[{"startOffset":337732,"endOffset":338892,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":339105,"endOffset":339165,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":339261,"endOffset":339394,"count":0}],"isBlockCoverage":false},{"functionName":"_sendData$1","ranges":[{"startOffset":339533,"endOffset":339677,"count":1}],"isBlockCoverage":true},{"functionName":"_sendError$2","ranges":[{"startOffset":339697,"endOffset":339802,"count":0}],"isBlockCoverage":false},{"functionName":"_sendDone$0","ranges":[{"startOffset":339821,"endOffset":339882,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":339984,"endOffset":340083,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":340094,"endOffset":340307,"count":0}],"isBlockCoverage":false},{"functionName":"_onCancel$0","ranges":[{"startOffset":340372,"endOffset":340443,"count":0}],"isBlockCoverage":false},{"functionName":"_onPause$0","ranges":[{"startOffset":340461,"endOffset":340868,"count":0}],"isBlockCoverage":false},{"functionName":"_onResume$0","ranges":[{"startOffset":340887,"endOffset":341296,"count":0}],"isBlockCoverage":false},{"functionName":"add$1","ranges":[{"startOffset":341350,"endOffset":341482,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":341597,"endOffset":341672,"count":0}],"isBlockCoverage":false},{"functionName":"_BufferingStreamSubscription$4","ranges":[{"startOffset":341780,"endOffset":343046,"count":1},{"startOffset":342069,"endOffset":342106,"count":0},{"startOffset":342501,"endOffset":342838,"count":0}],"isBlockCoverage":true},{"functionName":"_setPendingEvents$1","ranges":[{"startOffset":343073,"endOffset":343490,"count":1},{"startOffset":343296,"endOffset":343484,"count":0}],"isBlockCoverage":true},{"functionName":"cancel$0","ranges":[{"startOffset":343506,"endOffset":343740,"count":0}],"isBlockCoverage":false},{"functionName":"_cancel$0","ranges":[{"startOffset":343757,"endOffset":344079,"count":0}],"isBlockCoverage":false},{"functionName":"_add$1","ranges":[{"startOffset":344093,"endOffset":344445,"count":1},{"startOffset":344310,"endOffset":344317,"count":0},{"startOffset":344368,"endOffset":344439,"count":0}],"isBlockCoverage":true},{"functionName":"_async$_addError$2","ranges":[{"startOffset":344471,"endOffset":344720,"count":0}],"isBlockCoverage":false},{"functionName":"_close$0","ranges":[{"startOffset":344736,"endOffset":344979,"count":0}],"isBlockCoverage":false},{"functionName":"_onPause$0","ranges":[{"startOffset":344997,"endOffset":345015,"count":0}],"isBlockCoverage":false},{"functionName":"_onResume$0","ranges":[{"startOffset":345034,"endOffset":345052,"count":0}],"isBlockCoverage":false},{"functionName":"_onCancel$0","ranges":[{"startOffset":345071,"endOffset":345103,"count":0}],"isBlockCoverage":false},{"functionName":"_addPending$1","ranges":[{"startOffset":345124,"endOffset":345687,"count":0}],"isBlockCoverage":false},{"functionName":"_sendData$1","ranges":[{"startOffset":345706,"endOffset":346096,"count":1}],"isBlockCoverage":true},{"functionName":"_sendError$2","ranges":[{"startOffset":346116,"endOffset":346631,"count":0}],"isBlockCoverage":false},{"functionName":"_sendDone$0","ranges":[{"startOffset":346650,"endOffset":346982,"count":0}],"isBlockCoverage":false},{"functionName":"_guardCallback$1","ranges":[{"startOffset":347006,"endOffset":347285,"count":1}],"isBlockCoverage":true},{"functionName":"_checkState$1","ranges":[{"startOffset":347306,"endOffset":348403,"count":1},{"startOffset":347416,"endOffset":347457,"count":0},{"startOffset":347459,"endOffset":347850,"count":0},{"startOffset":347932,"endOffset":347996,"count":0},{"startOffset":348099,"endOffset":348318,"count":0},{"startOffset":348345,"endOffset":348356,"count":0},{"startOffset":348366,"endOffset":348397,"count":0}],"isBlockCoverage":true},{"functionName":"set$_async$_onData","ranges":[{"startOffset":348429,"endOffset":348607,"count":1}],"isBlockCoverage":true},{"functionName":"set$_onDone","ranges":[{"startOffset":348626,"endOffset":348722,"count":1}],"isBlockCoverage":true},{"functionName":"set$_pending","ranges":[{"startOffset":348742,"endOffset":348928,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":349070,"endOffset":349703,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":349855,"endOffset":350105,"count":0}],"isBlockCoverage":false},{"functionName":"listen$4$cancelOnError$onDone$onError","ranges":[{"startOffset":350252,"endOffset":350638,"count":1}],"isBlockCoverage":true},{"functionName":"listen$1","ranges":[{"startOffset":350654,"endOffset":350761,"count":1}],"isBlockCoverage":true},{"functionName":"listen$3$onDone$onError","ranges":[{"startOffset":350792,"endOffset":350921,"count":1}],"isBlockCoverage":true},{"functionName":"listen$2$onDone","ranges":[{"startOffset":350944,"endOffset":351061,"count":1}],"isBlockCoverage":true},{"functionName":"set$next","ranges":[{"startOffset":351113,"endOffset":351203,"count":0}],"isBlockCoverage":false},{"functionName":"get$next","ranges":[{"startOffset":351219,"endOffset":351261,"count":0}],"isBlockCoverage":false},{"functionName":"perform$1","ranges":[{"startOffset":351313,"endOffset":351448,"count":0}],"isBlockCoverage":false},{"functionName":"perform$1","ranges":[{"startOffset":351501,"endOffset":351585,"count":0}],"isBlockCoverage":false},{"functionName":"$as_DelayedEvent","ranges":[{"startOffset":351609,"endOffset":351627,"count":0}],"isBlockCoverage":false},{"functionName":"perform$1","ranges":[{"startOffset":351679,"endOffset":351735,"count":0}],"isBlockCoverage":false},{"functionName":"get$next","ranges":[{"startOffset":351751,"endOffset":351783,"count":0}],"isBlockCoverage":false},{"functionName":"set$next","ranges":[{"startOffset":351799,"endOffset":351889,"count":0}],"isBlockCoverage":false},{"functionName":"$as_DelayedEvent","ranges":[{"startOffset":351938,"endOffset":351956,"count":0}],"isBlockCoverage":false},{"functionName":"schedule$1","ranges":[{"startOffset":352011,"endOffset":352371,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":352439,"endOffset":352917,"count":0}],"isBlockCoverage":false},{"functionName":"add$1","ranges":[{"startOffset":353038,"endOffset":353300,"count":0}],"isBlockCoverage":false},{"functionName":"_schedule$0","ranges":[{"startOffset":353365,"endOffset":353539,"count":0}],"isBlockCoverage":false},{"functionName":"cancel$0","ranges":[{"startOffset":353555,"endOffset":353615,"count":0}],"isBlockCoverage":false},{"functionName":"_sendDone$0","ranges":[{"startOffset":353634,"endOffset":353880,"count":0}],"isBlockCoverage":false},{"functionName":"listen$4$cancelOnError$onDone$onError","ranges":[{"startOffset":354026,"endOffset":354367,"count":0}],"isBlockCoverage":false},{"functionName":"listen$1","ranges":[{"startOffset":354383,"endOffset":354490,"count":0}],"isBlockCoverage":false},{"functionName":"listen$3$onDone$onError","ranges":[{"startOffset":354521,"endOffset":354650,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":354727,"endOffset":354776,"count":0}],"isBlockCoverage":false},{"functionName":"handleUncaughtError$3","ranges":[{"startOffset":355050,"endOffset":355408,"count":0}],"isBlockCoverage":false},{"functionName":"get$_delegate","ranges":[{"startOffset":355523,"endOffset":355705,"count":0}],"isBlockCoverage":false},{"functionName":"get$errorZone","ranges":[{"startOffset":355726,"endOffset":355789,"count":1}],"isBlockCoverage":true},{"functionName":"runGuarded$1","ranges":[{"startOffset":355809,"endOffset":356114,"count":1},{"startOffset":355949,"endOffset":356108,"count":0}],"isBlockCoverage":true},{"functionName":"runUnaryGuarded$1$2","ranges":[{"startOffset":356141,"endOffset":356526,"count":1},{"startOffset":356361,"endOffset":356520,"count":0}],"isBlockCoverage":true},{"functionName":"runBinaryGuarded$2$3","ranges":[{"startOffset":356554,"endOffset":357013,"count":0}],"isBlockCoverage":false},{"functionName":"bindCallback$1$1","ranges":[{"startOffset":357037,"endOffset":357198,"count":0}],"isBlockCoverage":false},{"functionName":"bindUnaryCallback$2$1","ranges":[{"startOffset":357227,"endOffset":357422,"count":1}],"isBlockCoverage":true},{"functionName":"bindCallbackGuarded$1","ranges":[{"startOffset":357451,"endOffset":357611,"count":1}],"isBlockCoverage":true},{"functionName":"bindUnaryCallbackGuarded$1$1","ranges":[{"startOffset":357647,"endOffset":357841,"count":1}],"isBlockCoverage":true},{"functionName":"$index","ranges":[{"startOffset":357855,"endOffset":358169,"count":0}],"isBlockCoverage":false},{"functionName":"handleUncaughtError$2","ranges":[{"startOffset":358198,"endOffset":358557,"count":0}],"isBlockCoverage":false},{"functionName":"fork$2$specification$zoneValues","ranges":[{"startOffset":358596,"endOffset":358897,"count":0}],"isBlockCoverage":false},{"functionName":"run$1$1","ranges":[{"startOffset":358912,"endOffset":359343,"count":1}],"isBlockCoverage":true},{"functionName":"runUnary$2$2","ranges":[{"startOffset":359363,"endOffset":359898,"count":1}],"isBlockCoverage":true},{"functionName":"runBinary$3$3","ranges":[{"startOffset":359919,"endOffset":360544,"count":0}],"isBlockCoverage":false},{"functionName":"registerCallback$1$1","ranges":[{"startOffset":360572,"endOffset":361053,"count":1}],"isBlockCoverage":true},{"functionName":"registerUnaryCallback$2$1","ranges":[{"startOffset":361086,"endOffset":361624,"count":1}],"isBlockCoverage":true},{"functionName":"registerBinaryCallback$3$1","ranges":[{"startOffset":361658,"endOffset":362225,"count":1}],"isBlockCoverage":true},{"functionName":"errorCallback$2","ranges":[{"startOffset":362248,"endOffset":362670,"count":0}],"isBlockCoverage":false},{"functionName":"scheduleMicrotask$1","ranges":[{"startOffset":362697,"endOffset":363013,"count":1}],"isBlockCoverage":true},{"functionName":"createPeriodicTimer$2","ranges":[{"startOffset":363042,"endOffset":363397,"count":1}],"isBlockCoverage":true},{"functionName":"print$1","ranges":[{"startOffset":363412,"endOffset":363675,"count":0}],"isBlockCoverage":false},{"functionName":"set$_run","ranges":[{"startOffset":363691,"endOffset":363808,"count":1}],"isBlockCoverage":true},{"functionName":"set$_runUnary","ranges":[{"startOffset":363829,"endOffset":363961,"count":1}],"isBlockCoverage":true},{"functionName":"set$_runBinary","ranges":[{"startOffset":363983,"endOffset":364118,"count":1}],"isBlockCoverage":true},{"functionName":"set$_registerCallback","ranges":[{"startOffset":364147,"endOffset":364303,"count":1}],"isBlockCoverage":true},{"functionName":"set$_registerUnaryCallback","ranges":[{"startOffset":364337,"endOffset":364508,"count":1}],"isBlockCoverage":true},{"functionName":"set$_registerBinaryCallback","ranges":[{"startOffset":364543,"endOffset":364717,"count":1}],"isBlockCoverage":true},{"functionName":"set$_errorCallback","ranges":[{"startOffset":364743,"endOffset":364972,"count":1}],"isBlockCoverage":true},{"functionName":"set$_scheduleMicrotask","ranges":[{"startOffset":365002,"endOffset":365229,"count":1}],"isBlockCoverage":true},{"functionName":"set$_createTimer","ranges":[{"startOffset":365253,"endOffset":365479,"count":1}],"isBlockCoverage":true},{"functionName":"set$_createPeriodicTimer","ranges":[{"startOffset":365511,"endOffset":365778,"count":1}],"isBlockCoverage":true},{"functionName":"set$_print","ranges":[{"startOffset":365796,"endOffset":365977,"count":1}],"isBlockCoverage":true},{"functionName":"set$_fork","ranges":[{"startOffset":365994,"endOffset":366199,"count":1}],"isBlockCoverage":true},{"functionName":"set$_handleUncaughtError","ranges":[{"startOffset":366231,"endOffset":366468,"count":1}],"isBlockCoverage":true},{"functionName":"get$_run","ranges":[{"startOffset":366484,"endOffset":366526,"count":0}],"isBlockCoverage":false},{"functionName":"get$_runUnary","ranges":[{"startOffset":366547,"endOffset":366594,"count":0}],"isBlockCoverage":false},{"functionName":"get$_runBinary","ranges":[{"startOffset":366616,"endOffset":366664,"count":0}],"isBlockCoverage":false},{"functionName":"get$_registerCallback","ranges":[{"startOffset":366693,"endOffset":366748,"count":0}],"isBlockCoverage":false},{"functionName":"get$_registerUnaryCallback","ranges":[{"startOffset":366782,"endOffset":366842,"count":0}],"isBlockCoverage":false},{"functionName":"get$_registerBinaryCallback","ranges":[{"startOffset":366877,"endOffset":366938,"count":0}],"isBlockCoverage":false},{"functionName":"get$_errorCallback","ranges":[{"startOffset":366964,"endOffset":367016,"count":0}],"isBlockCoverage":false},{"functionName":"get$_scheduleMicrotask","ranges":[{"startOffset":367046,"endOffset":367102,"count":0}],"isBlockCoverage":false},{"functionName":"get$_createTimer","ranges":[{"startOffset":367126,"endOffset":367176,"count":0}],"isBlockCoverage":false},{"functionName":"get$_createPeriodicTimer","ranges":[{"startOffset":367208,"endOffset":367266,"count":0}],"isBlockCoverage":false},{"functionName":"get$_print","ranges":[{"startOffset":367284,"endOffset":367328,"count":0}],"isBlockCoverage":false},{"functionName":"get$_fork","ranges":[{"startOffset":367345,"endOffset":367388,"count":0}],"isBlockCoverage":false},{"functionName":"get$_handleUncaughtError","ranges":[{"startOffset":367420,"endOffset":367478,"count":0}],"isBlockCoverage":false},{"functionName":"get$parent","ranges":[{"startOffset":367496,"endOffset":367548,"count":0}],"isBlockCoverage":false},{"functionName":"get$_async$_map","ranges":[{"startOffset":367571,"endOffset":367620,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":367689,"endOffset":367765,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":367783,"endOffset":367838,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":367912,"endOffset":368062,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":368080,"endOffset":368151,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":368227,"endOffset":368300,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":368449,"endOffset":368598,"count":1}],"isBlockCoverage":true},{"functionName":"$signature","ranges":[{"startOffset":368616,"endOffset":368683,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":368752,"endOffset":369158,"count":0}],"isBlockCoverage":false},{"functionName":"get$_run","ranges":[{"startOffset":369225,"endOffset":369292,"count":1}],"isBlockCoverage":true},{"functionName":"get$_runUnary","ranges":[{"startOffset":369313,"endOffset":369385,"count":1}],"isBlockCoverage":true},{"functionName":"get$_runBinary","ranges":[{"startOffset":369407,"endOffset":369480,"count":1}],"isBlockCoverage":true},{"functionName":"get$_registerCallback","ranges":[{"startOffset":369509,"endOffset":369589,"count":1}],"isBlockCoverage":true},{"functionName":"get$_registerUnaryCallback","ranges":[{"startOffset":369623,"endOffset":369675,"count":1}],"isBlockCoverage":true},{"functionName":"get$_registerBinaryCallback","ranges":[{"startOffset":369710,"endOffset":369762,"count":1}],"isBlockCoverage":true},{"functionName":"get$_errorCallback","ranges":[{"startOffset":369788,"endOffset":369865,"count":1}],"isBlockCoverage":true},{"functionName":"get$_scheduleMicrotask","ranges":[{"startOffset":369895,"endOffset":369976,"count":1}],"isBlockCoverage":true},{"functionName":"get$_createTimer","ranges":[{"startOffset":370000,"endOffset":370075,"count":1}],"isBlockCoverage":true},{"functionName":"get$_createPeriodicTimer","ranges":[{"startOffset":370107,"endOffset":370159,"count":1}],"isBlockCoverage":true},{"functionName":"get$_print","ranges":[{"startOffset":370177,"endOffset":370246,"count":1}],"isBlockCoverage":true},{"functionName":"get$_fork","ranges":[{"startOffset":370263,"endOffset":370331,"count":1}],"isBlockCoverage":true},{"functionName":"get$_handleUncaughtError","ranges":[{"startOffset":370363,"endOffset":370415,"count":0}],"isBlockCoverage":false},{"functionName":"get$parent","ranges":[{"startOffset":370433,"endOffset":370466,"count":1}],"isBlockCoverage":true},{"functionName":"get$_async$_map","ranges":[{"startOffset":370489,"endOffset":370549,"count":1}],"isBlockCoverage":true},{"functionName":"get$_delegate","ranges":[{"startOffset":370570,"endOffset":370764,"count":0}],"isBlockCoverage":false},{"functionName":"get$errorZone","ranges":[{"startOffset":370785,"endOffset":370822,"count":1}],"isBlockCoverage":true},{"functionName":"runGuarded$1","ranges":[{"startOffset":370842,"endOffset":371321,"count":0}],"isBlockCoverage":false},{"functionName":"runUnaryGuarded$1$2","ranges":[{"startOffset":371348,"endOffset":371910,"count":0}],"isBlockCoverage":false},{"functionName":"runBinaryGuarded$2$3","ranges":[{"startOffset":371938,"endOffset":372581,"count":0}],"isBlockCoverage":false},{"functionName":"bindCallback$1$1","ranges":[{"startOffset":372605,"endOffset":372733,"count":0}],"isBlockCoverage":false},{"functionName":"bindCallbackGuarded$1","ranges":[{"startOffset":372762,"endOffset":372889,"count":0}],"isBlockCoverage":false},{"functionName":"bindUnaryCallbackGuarded$1$1","ranges":[{"startOffset":372925,"endOffset":373077,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":373091,"endOffset":373129,"count":0}],"isBlockCoverage":false},{"functionName":"handleUncaughtError$2","ranges":[{"startOffset":373158,"endOffset":373305,"count":0}],"isBlockCoverage":false},{"functionName":"fork$2$specification$zoneValues","ranges":[{"startOffset":373344,"endOffset":373458,"count":1}],"isBlockCoverage":true},{"functionName":"run$1$1","ranges":[{"startOffset":373473,"endOffset":373668,"count":0}],"isBlockCoverage":false},{"functionName":"runUnary$2$2","ranges":[{"startOffset":373688,"endOffset":373966,"count":0}],"isBlockCoverage":false},{"functionName":"runBinary$3$3","ranges":[{"startOffset":373987,"endOffset":374346,"count":0}],"isBlockCoverage":false},{"functionName":"registerCallback$1$1","ranges":[{"startOffset":374374,"endOffset":374454,"count":0}],"isBlockCoverage":false},{"functionName":"registerUnaryCallback$2$1","ranges":[{"startOffset":374487,"endOffset":374583,"count":0}],"isBlockCoverage":false},{"functionName":"registerBinaryCallback$3$1","ranges":[{"startOffset":374617,"endOffset":374721,"count":0}],"isBlockCoverage":false},{"functionName":"errorCallback$2","ranges":[{"startOffset":374744,"endOffset":374793,"count":0}],"isBlockCoverage":false},{"functionName":"scheduleMicrotask$1","ranges":[{"startOffset":374820,"endOffset":374933,"count":0}],"isBlockCoverage":false},{"functionName":"createPeriodicTimer$2","ranges":[{"startOffset":374962,"endOffset":375105,"count":0}],"isBlockCoverage":false},{"functionName":"print$1","ranges":[{"startOffset":375120,"endOffset":375172,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":375239,"endOffset":375306,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":375324,"endOffset":375379,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":375453,"endOffset":375517,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":375664,"endOffset":375804,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":375822,"endOffset":375889,"count":0}],"isBlockCoverage":false},{"functionName":"call$5","ranges":[{"startOffset":375942,"endOffset":376743,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":376812,"endOffset":376870,"count":0}],"isBlockCoverage":false},{"functionName":"get$isEmpty","ranges":[{"startOffset":376889,"endOffset":376953,"count":0}],"isBlockCoverage":false},{"functionName":"get$keys","ranges":[{"startOffset":376969,"endOffset":377070,"count":0}],"isBlockCoverage":false},{"functionName":"containsKey$1","ranges":[{"startOffset":377091,"endOffset":377529,"count":0}],"isBlockCoverage":false},{"functionName":"_containsKey$1","ranges":[{"startOffset":377551,"endOffset":377737,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":377751,"endOffset":378258,"count":0}],"isBlockCoverage":false},{"functionName":"_get$1","ranges":[{"startOffset":378272,"endOffset":378549,"count":0}],"isBlockCoverage":false},{"functionName":"$indexSet","ranges":[{"startOffset":378566,"endOffset":379433,"count":0}],"isBlockCoverage":false},{"functionName":"_set$2","ranges":[{"startOffset":379447,"endOffset":380330,"count":0}],"isBlockCoverage":false},{"functionName":"forEach$1","ranges":[{"startOffset":380347,"endOffset":380898,"count":0}],"isBlockCoverage":false},{"functionName":"_collection$_computeKeys$0","ranges":[{"startOffset":380932,"endOffset":382221,"count":0}],"isBlockCoverage":false},{"functionName":"_collection$_addHashTableEntry$3","ranges":[{"startOffset":382261,"endOffset":382617,"count":0}],"isBlockCoverage":false},{"functionName":"_computeHashCode$1","ranges":[{"startOffset":382643,"endOffset":382712,"count":0}],"isBlockCoverage":false},{"functionName":"_getBucket$2","ranges":[{"startOffset":382732,"endOffset":382810,"count":0}],"isBlockCoverage":false},{"functionName":"_findBucketIndex$2","ranges":[{"startOffset":382836,"endOffset":383075,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":383135,"endOffset":383198,"count":0}],"isBlockCoverage":false},{"functionName":"get$isEmpty","ranges":[{"startOffset":383217,"endOffset":383286,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":383306,"endOffset":383438,"count":0}],"isBlockCoverage":false},{"functionName":"get$current","ranges":[{"startOffset":383499,"endOffset":383557,"count":0}],"isBlockCoverage":false},{"functionName":"moveNext$0","ranges":[{"startOffset":383575,"endOffset":384056,"count":0}],"isBlockCoverage":false},{"functionName":"set$_collection$_current","ranges":[{"startOffset":384088,"endOffset":384223,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":384300,"endOffset":384484,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":384502,"endOffset":384560,"count":0}],"isBlockCoverage":false},{"functionName":"contains$1","ranges":[{"startOffset":384578,"endOffset":385195,"count":1},{"startOffset":384662,"endOffset":384687,"count":0},{"startOffset":384689,"endOffset":384885,"count":0},{"startOffset":385049,"endOffset":385189,"count":0}],"isBlockCoverage":true},{"functionName":"_contains$1","ranges":[{"startOffset":385214,"endOffset":385409,"count":0}],"isBlockCoverage":false},{"functionName":"add$1","ranges":[{"startOffset":385422,"endOffset":386268,"count":0}],"isBlockCoverage":false},{"functionName":"_collection$_add$1","ranges":[{"startOffset":386294,"endOffset":386943,"count":0}],"isBlockCoverage":false},{"functionName":"remove$1","ranges":[{"startOffset":386959,"endOffset":387360,"count":1},{"startOffset":387018,"endOffset":387043,"count":0},{"startOffset":387053,"endOffset":387136,"count":0},{"startOffset":387304,"endOffset":387354,"count":0}],"isBlockCoverage":true},{"functionName":"_remove$1","ranges":[{"startOffset":387377,"endOffset":387746,"count":0}],"isBlockCoverage":false},{"functionName":"_collection$_addHashTableEntry$2","ranges":[{"startOffset":387786,"endOffset":388089,"count":0}],"isBlockCoverage":false},{"functionName":"_collection$_removeHashTableEntry$2","ranges":[{"startOffset":388132,"endOffset":388443,"count":1},{"startOffset":388221,"endOffset":388442,"count":0}],"isBlockCoverage":true},{"functionName":"_collection$_modified$0","ranges":[{"startOffset":388474,"endOffset":388582,"count":0}],"isBlockCoverage":false},{"functionName":"_collection$_newLinkedCell$1","ranges":[{"startOffset":388618,"endOffset":389176,"count":0}],"isBlockCoverage":false},{"functionName":"_collection$_unlinkCell$1","ranges":[{"startOffset":389209,"endOffset":389658,"count":0}],"isBlockCoverage":false},{"functionName":"_computeHashCode$1","ranges":[{"startOffset":389684,"endOffset":389761,"count":0}],"isBlockCoverage":false},{"functionName":"_getBucket$2","ranges":[{"startOffset":389781,"endOffset":389867,"count":0}],"isBlockCoverage":false},{"functionName":"_findBucketIndex$2","ranges":[{"startOffset":389893,"endOffset":390203,"count":0}],"isBlockCoverage":false},{"functionName":"get$current","ranges":[{"startOffset":390306,"endOffset":390364,"count":0}],"isBlockCoverage":false},{"functionName":"moveNext$0","ranges":[{"startOffset":390382,"endOffset":390971,"count":0}],"isBlockCoverage":false},{"functionName":"set$_collection$_current","ranges":[{"startOffset":391003,"endOffset":391138,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":391329,"endOffset":391499,"count":0}],"isBlockCoverage":false},{"functionName":"elementAt$1","ranges":[{"startOffset":391518,"endOffset":391594,"count":0}],"isBlockCoverage":false},{"functionName":"get$isEmpty","ranges":[{"startOffset":391613,"endOffset":391685,"count":0}],"isBlockCoverage":false},{"functionName":"get$isNotEmpty","ranges":[{"startOffset":391707,"endOffset":391775,"count":0}],"isBlockCoverage":false},{"functionName":"fillRange$3","ranges":[{"startOffset":391794,"endOffset":392116,"count":1}],"isBlockCoverage":true},{"functionName":"toString$0","ranges":[{"startOffset":392134,"endOffset":392230,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":392322,"endOffset":392591,"count":0}],"isBlockCoverage":false},{"functionName":"forEach$1","ranges":[{"startOffset":392659,"endOffset":393030,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":393048,"endOffset":393131,"count":0}],"isBlockCoverage":false},{"functionName":"get$isEmpty","ranges":[{"startOffset":393150,"endOffset":393234,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":393252,"endOffset":393313,"count":0}],"isBlockCoverage":false},{"functionName":"$indexSet","ranges":[{"startOffset":393389,"endOffset":393708,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":393752,"endOffset":393815,"count":1}],"isBlockCoverage":true},{"functionName":"$indexSet","ranges":[{"startOffset":393832,"endOffset":394035,"count":0}],"isBlockCoverage":false},{"functionName":"forEach$1","ranges":[{"startOffset":394052,"endOffset":394236,"count":0}],"isBlockCoverage":false},{"functionName":"get$isEmpty","ranges":[{"startOffset":394255,"endOffset":394333,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":394351,"endOffset":394428,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":394446,"endOffset":394504,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":394608,"endOffset":394693,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":394926,"endOffset":395244,"count":1},{"startOffset":395025,"endOffset":395058,"count":0},{"startOffset":395107,"endOffset":395114,"count":0},{"startOffset":395221,"endOffset":395229,"count":0}],"isBlockCoverage":true},{"functionName":"get$length","ranges":[{"startOffset":395262,"endOffset":395383,"count":0}],"isBlockCoverage":false},{"functionName":"get$isEmpty","ranges":[{"startOffset":395402,"endOffset":395463,"count":0}],"isBlockCoverage":false},{"functionName":"get$keys","ranges":[{"startOffset":395479,"endOffset":395703,"count":0}],"isBlockCoverage":false},{"functionName":"$indexSet","ranges":[{"startOffset":395720,"endOffset":396180,"count":0}],"isBlockCoverage":false},{"functionName":"containsKey$1","ranges":[{"startOffset":396201,"endOffset":396375,"count":0}],"isBlockCoverage":false},{"functionName":"forEach$1","ranges":[{"startOffset":396392,"endOffset":397032,"count":1},{"startOffset":396553,"endOffset":396587,"count":0},{"startOffset":396958,"endOffset":397018,"count":0}],"isBlockCoverage":true},{"functionName":"_computeKeys$0","ranges":[{"startOffset":397054,"endOffset":397276,"count":1}],"isBlockCoverage":true},{"functionName":"_upgrade$0","ranges":[{"startOffset":397294,"endOffset":397882,"count":0}],"isBlockCoverage":false},{"functionName":"_process$1","ranges":[{"startOffset":397900,"endOffset":398131,"count":1},{"startOffset":398012,"endOffset":398019,"count":0}],"isBlockCoverage":true},{"functionName":"$asMapMixin","ranges":[{"startOffset":398150,"endOffset":398199,"count":0}],"isBlockCoverage":false},{"functionName":"$asMap","ranges":[{"startOffset":398213,"endOffset":398262,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":398322,"endOffset":398411,"count":0}],"isBlockCoverage":false},{"functionName":"elementAt$1","ranges":[{"startOffset":398430,"endOffset":398755,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":398775,"endOffset":399090,"count":0}],"isBlockCoverage":false},{"functionName":"$asEfficientLengthIterable","ranges":[{"startOffset":399124,"endOffset":399167,"count":0}],"isBlockCoverage":false},{"functionName":"$asListIterable","ranges":[{"startOffset":399190,"endOffset":399233,"count":0}],"isBlockCoverage":false},{"functionName":"$asIterable","ranges":[{"startOffset":399252,"endOffset":399295,"count":0}],"isBlockCoverage":false},{"functionName":"encode$1","ranges":[{"startOffset":399344,"endOffset":399419,"count":0}],"isBlockCoverage":false},{"functionName":"convert$1","ranges":[{"startOffset":399480,"endOffset":400124,"count":0}],"isBlockCoverage":false},{"functionName":"$asStreamTransformer","ranges":[{"startOffset":400152,"endOffset":400212,"count":0}],"isBlockCoverage":false},{"functionName":"$asConverter","ranges":[{"startOffset":400232,"endOffset":400292,"count":0}],"isBlockCoverage":false},{"functionName":"normalize$3","ranges":[{"startOffset":400378,"endOffset":404030,"count":0}],"isBlockCoverage":false},{"functionName":"$asCodec","ranges":[{"startOffset":404046,"endOffset":404106,"count":0}],"isBlockCoverage":false},{"functionName":"$asStreamTransformer","ranges":[{"startOffset":404170,"endOffset":404230,"count":0}],"isBlockCoverage":false},{"functionName":"$asConverter","ranges":[{"startOffset":404250,"endOffset":404310,"count":0}],"isBlockCoverage":false},{"functionName":"$asCodec","ranges":[{"startOffset":404386,"endOffset":404437,"count":0}],"isBlockCoverage":false},{"functionName":"$asCodec","ranges":[{"startOffset":404514,"endOffset":404574,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":404641,"endOffset":404894,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":404950,"endOffset":405016,"count":0}],"isBlockCoverage":false},{"functionName":"decode$2$reviver","ranges":[{"startOffset":405072,"endOffset":405191,"count":1}],"isBlockCoverage":true},{"functionName":"encode$2$toEncodable","ranges":[{"startOffset":405219,"endOffset":405389,"count":1}],"isBlockCoverage":true},{"functionName":"get$encoder","ranges":[{"startOffset":405408,"endOffset":405464,"count":1}],"isBlockCoverage":true},{"functionName":"get$decoder","ranges":[{"startOffset":405483,"endOffset":405534,"count":1}],"isBlockCoverage":true},{"functionName":"$asCodec","ranges":[{"startOffset":405550,"endOffset":405603,"count":0}],"isBlockCoverage":false},{"functionName":"$asStreamTransformer","ranges":[{"startOffset":405665,"endOffset":405718,"count":0}],"isBlockCoverage":false},{"functionName":"$asConverter","ranges":[{"startOffset":405738,"endOffset":405791,"count":0}],"isBlockCoverage":false},{"functionName":"$asStreamTransformer","ranges":[{"startOffset":405853,"endOffset":405906,"count":0}],"isBlockCoverage":false},{"functionName":"$asConverter","ranges":[{"startOffset":405926,"endOffset":405979,"count":0}],"isBlockCoverage":false},{"functionName":"writeStringContent$1","ranges":[{"startOffset":406046,"endOffset":407693,"count":1},{"startOffset":406329,"endOffset":407300,"count":0},{"startOffset":407346,"endOffset":407538,"count":0},{"startOffset":407601,"endOffset":407687,"count":0}],"isBlockCoverage":true},{"functionName":"_checkCycle$1","ranges":[{"startOffset":407714,"endOffset":408027,"count":1},{"startOffset":407871,"endOffset":407883,"count":0},{"startOffset":407911,"endOffset":407970,"count":0}],"isBlockCoverage":true},{"functionName":"writeObject$1","ranges":[{"startOffset":408048,"endOffset":408754,"count":1},{"startOffset":408163,"endOffset":408748,"count":0}],"isBlockCoverage":true},{"functionName":"writeJsonValue$1","ranges":[{"startOffset":408778,"endOffset":410030,"count":1},{"startOffset":408901,"endOffset":408914,"count":0},{"startOffset":409006,"endOffset":409072,"count":0},{"startOffset":409100,"endOffset":409167,"count":0},{"startOffset":409655,"endOffset":409678,"count":0},{"startOffset":409908,"endOffset":409931,"count":0},{"startOffset":409987,"endOffset":410016,"count":0}],"isBlockCoverage":true},{"functionName":"writeList$1","ranges":[{"startOffset":410049,"endOffset":410429,"count":1}],"isBlockCoverage":true},{"functionName":"writeMap$1","ranges":[{"startOffset":410447,"endOffset":411384,"count":1},{"startOffset":410929,"endOffset":410942,"count":0},{"startOffset":411241,"endOffset":411274,"count":0}],"isBlockCoverage":true},{"functionName":"call$2","ranges":[{"startOffset":411454,"endOffset":411738,"count":1},{"startOffset":411538,"endOffset":411572,"count":0}],"isBlockCoverage":true},{"functionName":"get$_partialResult","ranges":[{"startOffset":411829,"endOffset":411944,"count":0}],"isBlockCoverage":false},{"functionName":"writeNumber$1","ranges":[{"startOffset":411965,"endOffset":412063,"count":1}],"isBlockCoverage":true},{"functionName":"writeString$1","ranges":[{"startOffset":412084,"endOffset":412151,"count":1}],"isBlockCoverage":true},{"functionName":"writeStringSlice$3","ranges":[{"startOffset":412177,"endOffset":412285,"count":0}],"isBlockCoverage":false},{"functionName":"writeCharCode$1","ranges":[{"startOffset":412308,"endOffset":412387,"count":0}],"isBlockCoverage":false},{"functionName":"get$encoder","ranges":[{"startOffset":412438,"endOffset":412486,"count":0}],"isBlockCoverage":false},{"functionName":"convert$1","ranges":[{"startOffset":412537,"endOffset":413070,"count":0}],"isBlockCoverage":false},{"functionName":"$asStreamTransformer","ranges":[{"startOffset":413098,"endOffset":413158,"count":0}],"isBlockCoverage":false},{"functionName":"$asConverter","ranges":[{"startOffset":413178,"endOffset":413238,"count":0}],"isBlockCoverage":false},{"functionName":"_writeSurrogate$2","ranges":[{"startOffset":413298,"endOffset":414650,"count":0}],"isBlockCoverage":false},{"functionName":"_fillBuffer$3","ranges":[{"startOffset":414671,"endOffset":416478,"count":0}],"isBlockCoverage":false},{"functionName":"convert$1","ranges":[{"startOffset":416529,"endOffset":417119,"count":1},{"startOffset":416771,"endOffset":416785,"count":0},{"startOffset":417103,"endOffset":417107,"count":0}],"isBlockCoverage":true},{"functionName":"$asStreamTransformer","ranges":[{"startOffset":417147,"endOffset":417207,"count":0}],"isBlockCoverage":false},{"functionName":"$asConverter","ranges":[{"startOffset":417227,"endOffset":417287,"count":0}],"isBlockCoverage":false},{"functionName":"flush$2","ranges":[{"startOffset":417337,"endOffset":417609,"count":1},{"startOffset":417475,"endOffset":417603,"count":0}],"isBlockCoverage":true},{"functionName":"convert$3","ranges":[{"startOffset":417626,"endOffset":421538,"count":1},{"startOffset":418311,"endOffset":419809,"count":0},{"startOffset":420150,"endOffset":421331,"count":0},{"startOffset":421410,"endOffset":421532,"count":0}],"isBlockCoverage":true},{"functionName":"call$2","ranges":[{"startOffset":421610,"endOffset":421735,"count":1}],"isBlockCoverage":true},{"functionName":"call$2","ranges":[{"startOffset":421826,"endOffset":422161,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":422248,"endOffset":422415,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":422435,"endOffset":422566,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":422584,"endOffset":423195,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":423264,"endOffset":423417,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":423437,"endOffset":423515,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":423533,"endOffset":424155,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":424219,"endOffset":424494,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":424578,"endOffset":424661,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":424763,"endOffset":424813,"count":0}],"isBlockCoverage":false},{"functionName":"get$_errorName","ranges":[{"startOffset":424871,"endOffset":424955,"count":0}],"isBlockCoverage":false},{"functionName":"get$_errorExplanation","ranges":[{"startOffset":424984,"endOffset":425019,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":425037,"endOffset":425551,"count":0}],"isBlockCoverage":false},{"functionName":"get$_errorName","ranges":[{"startOffset":425606,"endOffset":425651,"count":0}],"isBlockCoverage":false},{"functionName":"get$_errorExplanation","ranges":[{"startOffset":425680,"endOffset":426274,"count":0}],"isBlockCoverage":false},{"functionName":"get$_errorName","ranges":[{"startOffset":426329,"endOffset":426374,"count":0}],"isBlockCoverage":false},{"functionName":"get$_errorExplanation","ranges":[{"startOffset":426403,"endOffset":426799,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":426817,"endOffset":426869,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":426927,"endOffset":427772,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":427829,"endOffset":427903,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":427962,"endOffset":428088,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":428139,"endOffset":428201,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":428269,"endOffset":428498,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":428555,"endOffset":428604,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":428680,"endOffset":428730,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":428813,"endOffset":429012,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":429063,"endOffset":429125,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":429181,"endOffset":431814,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":431916,"endOffset":432069,"count":0}],"isBlockCoverage":false},{"functionName":"get$isEmpty","ranges":[{"startOffset":432088,"endOffset":432159,"count":0}],"isBlockCoverage":false},{"functionName":"skipWhile$1","ranges":[{"startOffset":432178,"endOffset":432378,"count":0}],"isBlockCoverage":false},{"functionName":"get$first","ranges":[{"startOffset":432395,"endOffset":432580,"count":0}],"isBlockCoverage":false},{"functionName":"get$last","ranges":[{"startOffset":432596,"endOffset":432864,"count":0}],"isBlockCoverage":false},{"functionName":"elementAt$1","ranges":[{"startOffset":432883,"endOffset":433294,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":433312,"endOffset":433398,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":433568,"endOffset":433650,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":433668,"endOffset":433708,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":433808,"endOffset":433863,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":433883,"endOffset":433950,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":433968,"endOffset":434059,"count":0}],"isBlockCoverage":false},{"functionName":"noSuchMethod$1","ranges":[{"startOffset":434081,"endOffset":434328,"count":0}],"isBlockCoverage":false},{"functionName":"toString","ranges":[{"startOffset":434344,"endOffset":434398,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":434513,"endOffset":434563,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":434678,"endOffset":434733,"count":0}],"isBlockCoverage":false},{"functionName":"write$1","ranges":[{"startOffset":434748,"endOffset":434803,"count":1}],"isBlockCoverage":true},{"functionName":"writeCharCode$1","ranges":[{"startOffset":434826,"endOffset":434919,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":434937,"endOffset":435033,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":435148,"endOffset":435892,"count":1},{"startOffset":435410,"endOffset":435547,"count":0}],"isBlockCoverage":true},{"functionName":"call$2","ranges":[{"startOffset":435976,"endOffset":436109,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":436192,"endOffset":436325,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":436339,"endOffset":436397,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":436483,"endOffset":436948,"count":0}],"isBlockCoverage":false},{"functionName":"get$userInfo","ranges":[{"startOffset":437015,"endOffset":437062,"count":0}],"isBlockCoverage":false},{"functionName":"get$host","ranges":[{"startOffset":437078,"endOffset":437303,"count":0}],"isBlockCoverage":false},{"functionName":"get$port","ranges":[{"startOffset":437319,"endOffset":437453,"count":0}],"isBlockCoverage":false},{"functionName":"get$query","ranges":[{"startOffset":437470,"endOffset":437551,"count":0}],"isBlockCoverage":false},{"functionName":"get$fragment","ranges":[{"startOffset":437571,"endOffset":437655,"count":0}],"isBlockCoverage":false},{"functionName":"get$pathSegments","ranges":[{"startOffset":437679,"endOffset":438447,"count":0}],"isBlockCoverage":false},{"functionName":"get$queryParameters","ranges":[{"startOffset":438474,"endOffset":438764,"count":1},{"startOffset":438691,"endOffset":438695,"count":0}],"isBlockCoverage":true},{"functionName":"_mergePaths$2","ranges":[{"startOffset":438785,"endOffset":439869,"count":0}],"isBlockCoverage":false},{"functionName":"resolve$1","ranges":[{"startOffset":439886,"endOffset":439969,"count":0}],"isBlockCoverage":false},{"functionName":"resolveUri$1","ranges":[{"startOffset":439989,"endOffset":442823,"count":0}],"isBlockCoverage":false},{"functionName":"get$hasAuthority","ranges":[{"startOffset":442847,"endOffset":442898,"count":0}],"isBlockCoverage":false},{"functionName":"get$hasPort","ranges":[{"startOffset":442917,"endOffset":442968,"count":0}],"isBlockCoverage":false},{"functionName":"get$hasQuery","ranges":[{"startOffset":442988,"endOffset":443040,"count":0}],"isBlockCoverage":false},{"functionName":"get$hasFragment","ranges":[{"startOffset":443063,"endOffset":443118,"count":0}],"isBlockCoverage":false},{"functionName":"get$hasAbsolutePath","ranges":[{"startOffset":443145,"endOffset":443210,"count":0}],"isBlockCoverage":false},{"functionName":"toFilePath$0","ranges":[{"startOffset":443230,"endOffset":444436,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":444454,"endOffset":445288,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":445299,"endOffset":446881,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":446901,"endOffset":447105,"count":0}],"isBlockCoverage":false},{"functionName":"set$_pathSegments","ranges":[{"startOffset":447130,"endOffset":447254,"count":0}],"isBlockCoverage":false},{"functionName":"set$_queryParameters","ranges":[{"startOffset":447282,"endOffset":447436,"count":1}],"isBlockCoverage":true},{"functionName":"get$scheme","ranges":[{"startOffset":447469,"endOffset":447513,"count":0}],"isBlockCoverage":false},{"functionName":"get$path","ranges":[{"startOffset":447529,"endOffset":447579,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":447643,"endOffset":447836,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":447944,"endOffset":448269,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":448348,"endOffset":448460,"count":0}],"isBlockCoverage":false},{"functionName":"get$uri","ranges":[{"startOffset":448525,"endOffset":449212,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":449230,"endOffset":449434,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":449492,"endOffset":449544,"count":1}],"isBlockCoverage":true},{"functionName":"call$2","ranges":[{"startOffset":449620,"endOffset":449847,"count":1},{"startOffset":449723,"endOffset":449749,"count":0}],"isBlockCoverage":true},{"functionName":"call$3","ranges":[{"startOffset":449926,"endOffset":450216,"count":1},{"startOffset":450142,"endOffset":450169,"count":0}],"isBlockCoverage":true},{"functionName":"call$3","ranges":[{"startOffset":450275,"endOffset":450601,"count":1},{"startOffset":450527,"endOffset":450554,"count":0}],"isBlockCoverage":true},{"functionName":"get$hasAuthority","ranges":[{"startOffset":450658,"endOffset":450710,"count":0}],"isBlockCoverage":false},{"functionName":"get$hasPort","ranges":[{"startOffset":450729,"endOffset":451079,"count":0}],"isBlockCoverage":false},{"functionName":"get$hasQuery","ranges":[{"startOffset":451099,"endOffset":451337,"count":0}],"isBlockCoverage":false},{"functionName":"get$hasFragment","ranges":[{"startOffset":451360,"endOffset":451538,"count":0}],"isBlockCoverage":false},{"functionName":"get$_isFile","ranges":[{"startOffset":451557,"endOffset":451650,"count":0}],"isBlockCoverage":false},{"functionName":"get$_isHttp","ranges":[{"startOffset":451669,"endOffset":451762,"count":0}],"isBlockCoverage":false},{"functionName":"get$_isHttps","ranges":[{"startOffset":451782,"endOffset":451876,"count":0}],"isBlockCoverage":false},{"functionName":"get$hasAbsolutePath","ranges":[{"startOffset":451903,"endOffset":451985,"count":0}],"isBlockCoverage":false},{"functionName":"get$scheme","ranges":[{"startOffset":452003,"endOffset":452773,"count":0}],"isBlockCoverage":false},{"functionName":"get$userInfo","ranges":[{"startOffset":452793,"endOffset":453028,"count":0}],"isBlockCoverage":false},{"functionName":"get$host","ranges":[{"startOffset":453044,"endOffset":453171,"count":0}],"isBlockCoverage":false},{"functionName":"get$port","ranges":[{"startOffset":453187,"endOffset":453563,"count":0}],"isBlockCoverage":false},{"functionName":"get$path","ranges":[{"startOffset":453579,"endOffset":453674,"count":0}],"isBlockCoverage":false},{"functionName":"get$query","ranges":[{"startOffset":453691,"endOffset":453975,"count":0}],"isBlockCoverage":false},{"functionName":"get$fragment","ranges":[{"startOffset":453995,"endOffset":454227,"count":0}],"isBlockCoverage":false},{"functionName":"get$pathSegments","ranges":[{"startOffset":454251,"endOffset":455219,"count":0}],"isBlockCoverage":false},{"functionName":"get$queryParameters","ranges":[{"startOffset":455246,"endOffset":455623,"count":0}],"isBlockCoverage":false},{"functionName":"_isPort$1","ranges":[{"startOffset":455640,"endOffset":455927,"count":0}],"isBlockCoverage":false},{"functionName":"removeFragment$0","ranges":[{"startOffset":455951,"endOffset":456335,"count":0}],"isBlockCoverage":false},{"functionName":"resolve$1","ranges":[{"startOffset":456352,"endOffset":456435,"count":0}],"isBlockCoverage":false},{"functionName":"resolveUri$1","ranges":[{"startOffset":456455,"endOffset":456640,"count":0}],"isBlockCoverage":false},{"functionName":"_simpleMerge$2","ranges":[{"startOffset":456662,"endOffset":462688,"count":0}],"isBlockCoverage":false},{"functionName":"toFilePath$0","ranges":[{"startOffset":462708,"endOffset":463987,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":464007,"endOffset":464186,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":464197,"endOffset":464401,"count":0}],"isBlockCoverage":false},{"functionName":"_toNonSimple$0","ranges":[{"startOffset":464423,"endOffset":465061,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":465079,"endOffset":465122,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":465252,"endOffset":465309,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":465361,"endOffset":465418,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":465507,"endOffset":465563,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":465616,"endOffset":465673,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":465726,"endOffset":465782,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":465830,"endOffset":465889,"count":0}],"isBlockCoverage":false},{"functionName":"get$onClick","ranges":[{"startOffset":465908,"endOffset":466020,"count":0}],"isBlockCoverage":false},{"functionName":"addEventListener$3","ranges":[{"startOffset":466136,"endOffset":466350,"count":1}],"isBlockCoverage":true},{"functionName":"_addEventListener$3","ranges":[{"startOffset":466377,"endOffset":466569,"count":1}],"isBlockCoverage":true},{"functionName":"_removeEventListener$3","ranges":[{"startOffset":466599,"endOffset":466794,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":466904,"endOffset":466960,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":467015,"endOffset":467071,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":467085,"endOffset":467319,"count":0}],"isBlockCoverage":false},{"functionName":"$indexSet","ranges":[{"startOffset":467336,"endOffset":467547,"count":0}],"isBlockCoverage":false},{"functionName":"elementAt$1","ranges":[{"startOffset":467566,"endOffset":467719,"count":0}],"isBlockCoverage":false},{"functionName":"$asEfficientLengthIterable","ranges":[{"startOffset":467788,"endOffset":467829,"count":0}],"isBlockCoverage":false},{"functionName":"$asJavaScriptIndexingBehavior","ranges":[{"startOffset":467904,"endOffset":467945,"count":0}],"isBlockCoverage":false},{"functionName":"$asListMixin","ranges":[{"startOffset":467965,"endOffset":468006,"count":0}],"isBlockCoverage":false},{"functionName":"$asIterable","ranges":[{"startOffset":468045,"endOffset":468086,"count":0}],"isBlockCoverage":false},{"functionName":"$asList","ranges":[{"startOffset":468117,"endOffset":468158,"count":0}],"isBlockCoverage":false},{"functionName":"$asImmutableListMixin","ranges":[{"startOffset":468187,"endOffset":468228,"count":0}],"isBlockCoverage":false},{"functionName":"get$origin","ranges":[{"startOffset":468330,"endOffset":468485,"count":1},{"startOffset":468414,"endOffset":468484,"count":0}],"isBlockCoverage":true},{"functionName":"toString$0","ranges":[{"startOffset":468503,"endOffset":468560,"count":0}],"isBlockCoverage":false},{"functionName":"addEventListener$3","ranges":[{"startOffset":468671,"endOffset":468926,"count":1}],"isBlockCoverage":true},{"functionName":"postMessage$1","ranges":[{"startOffset":468947,"endOffset":469079,"count":1}],"isBlockCoverage":true},{"functionName":"toString$0","ranges":[{"startOffset":469194,"endOffset":469338,"count":0}],"isBlockCoverage":false},{"functionName":"_removeChild$1","ranges":[{"startOffset":469360,"endOffset":469435,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":469505,"endOffset":469561,"count":0}],"isBlockCoverage":false},{"functionName":"get$location","ranges":[{"startOffset":469638,"endOffset":469696,"count":1}],"isBlockCoverage":true},{"functionName":"postMessage$3","ranges":[{"startOffset":469717,"endOffset":469975,"count":0}],"isBlockCoverage":false},{"functionName":"_postMessage_1$3","ranges":[{"startOffset":469999,"endOffset":470177,"count":0}],"isBlockCoverage":false},{"functionName":"listen$4$cancelOnError$onDone$onError","ranges":[{"startOffset":470279,"endOffset":470605,"count":0}],"isBlockCoverage":false},{"functionName":"listen$1","ranges":[{"startOffset":470621,"endOffset":470728,"count":0}],"isBlockCoverage":false},{"functionName":"listen$3$onDone$onError","ranges":[{"startOffset":470759,"endOffset":470888,"count":0}],"isBlockCoverage":false},{"functionName":"cancel$0","ranges":[{"startOffset":470995,"endOffset":471170,"count":0}],"isBlockCoverage":false},{"functionName":"_tryResume$0","ranges":[{"startOffset":471190,"endOffset":471364,"count":1}],"isBlockCoverage":true},{"functionName":"_unlisten$0","ranges":[{"startOffset":471383,"endOffset":471696,"count":0}],"isBlockCoverage":false},{"functionName":"set$_onData","ranges":[{"startOffset":471715,"endOffset":471819,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":471888,"endOffset":471979,"count":1}],"isBlockCoverage":true},{"functionName":"get$iterator","ranges":[{"startOffset":472060,"endOffset":472239,"count":0}],"isBlockCoverage":false},{"functionName":"moveNext$0","ranges":[{"startOffset":472301,"endOffset":472764,"count":0}],"isBlockCoverage":false},{"functionName":"get$current","ranges":[{"startOffset":472783,"endOffset":472829,"count":0}],"isBlockCoverage":false},{"functionName":"set$_current","ranges":[{"startOffset":472849,"endOffset":472972,"count":0}],"isBlockCoverage":false},{"functionName":"postMessage$3","ranges":[{"startOffset":473056,"endOffset":473227,"count":1}],"isBlockCoverage":true},{"functionName":"findSlot$1","ranges":[{"startOffset":473464,"endOffset":473763,"count":1},{"startOffset":473634,"endOffset":473643,"count":0}],"isBlockCoverage":true},{"functionName":"walk$1","ranges":[{"startOffset":473777,"endOffset":475247,"count":1},{"startOffset":474098,"endOffset":474130,"count":0},{"startOffset":474165,"endOffset":474240,"count":0},{"startOffset":474273,"endOffset":474282,"count":0},{"startOffset":474315,"endOffset":474324,"count":0},{"startOffset":474419,"endOffset":474428,"count":0},{"startOffset":474556,"endOffset":474581,"count":0},{"startOffset":474667,"endOffset":474679,"count":0},{"startOffset":475007,"endOffset":475032,"count":0},{"startOffset":475094,"endOffset":475106,"count":0},{"startOffset":475155,"endOffset":475246,"count":0}],"isBlockCoverage":true},{"functionName":"copyList$2","ranges":[{"startOffset":475265,"endOffset":475616,"count":1}],"isBlockCoverage":true},{"functionName":"call$2","ranges":[{"startOffset":475682,"endOffset":475766,"count":1}],"isBlockCoverage":true},{"functionName":"findSlot$1","ranges":[{"startOffset":475849,"endOffset":476208,"count":1},{"startOffset":476029,"endOffset":476044,"count":0},{"startOffset":476071,"endOffset":476080,"count":0}],"isBlockCoverage":true},{"functionName":"walk$1","ranges":[{"startOffset":476222,"endOffset":478314,"count":1},{"startOffset":476555,"endOffset":476884,"count":0},{"startOffset":476924,"endOffset":476999,"count":0},{"startOffset":477073,"endOffset":477118,"count":0},{"startOffset":477319,"endOffset":477344,"count":0},{"startOffset":477434,"endOffset":477446,"count":0},{"startOffset":477849,"endOffset":477874,"count":0},{"startOffset":477936,"endOffset":477948,"count":0},{"startOffset":478073,"endOffset":478076,"count":0},{"startOffset":478292,"endOffset":478313,"count":0}],"isBlockCoverage":true},{"functionName":"convertNativeToDart_AcceptStructuredClone$2$mustCopy","ranges":[{"startOffset":478374,"endOffset":478470,"count":1}],"isBlockCoverage":true},{"functionName":"call$2","ranges":[{"startOffset":478542,"endOffset":478706,"count":1}],"isBlockCoverage":true},{"functionName":"forEachJsField$2","ranges":[{"startOffset":478846,"endOffset":479184,"count":1},{"startOffset":479052,"endOffset":479098,"count":0}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":479261,"endOffset":479336,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":479433,"endOffset":479510,"count":0}],"isBlockCoverage":false},{"functionName":"get$onClick","ranges":[{"startOffset":479581,"endOffset":479693,"count":1}],"isBlockCoverage":true},{"functionName":"$asEfficientLengthIterable","ranges":[{"startOffset":479789,"endOffset":479829,"count":0}],"isBlockCoverage":false},{"functionName":"$asIterable","ranges":[{"startOffset":479868,"endOffset":479908,"count":0}],"isBlockCoverage":false},{"functionName":"$asList","ranges":[{"startOffset":479939,"endOffset":479979,"count":0}],"isBlockCoverage":false},{"functionName":"addStream$1","ranges":[{"startOffset":480035,"endOffset":480478,"count":0}],"isBlockCoverage":false},{"functionName":"_checkEventAllowed$0","ranges":[{"startOffset":480506,"endOffset":480767,"count":0}],"isBlockCoverage":false},{"functionName":"close$0","ranges":[{"startOffset":480782,"endOffset":480870,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":480987,"endOffset":481045,"count":0}],"isBlockCoverage":false},{"functionName":"absolute$7","ranges":[{"startOffset":481161,"endOffset":481639,"count":0}],"isBlockCoverage":false},{"functionName":"absolute$1","ranges":[{"startOffset":481657,"endOffset":481775,"count":0}],"isBlockCoverage":false},{"functionName":"join$8","ranges":[{"startOffset":481789,"endOffset":482229,"count":0}],"isBlockCoverage":false},{"functionName":"join$2","ranges":[{"startOffset":482243,"endOffset":482371,"count":0}],"isBlockCoverage":false},{"functionName":"joinAll$1","ranges":[{"startOffset":482388,"endOffset":483822,"count":0}],"isBlockCoverage":false},{"functionName":"split$1","ranges":[{"startOffset":483837,"endOffset":484322,"count":0}],"isBlockCoverage":false},{"functionName":"normalize$1","ranges":[{"startOffset":484341,"endOffset":484574,"count":0}],"isBlockCoverage":false},{"functionName":"_needsNormalization$1","ranges":[{"startOffset":484603,"endOffset":486114,"count":0}],"isBlockCoverage":false},{"functionName":"relative$1","ranges":[{"startOffset":486132,"endOffset":488870,"count":0}],"isBlockCoverage":false},{"functionName":"toUri$1","ranges":[{"startOffset":488885,"endOffset":489181,"count":0}],"isBlockCoverage":false},{"functionName":"prettyUri$1","ranges":[{"startOffset":489200,"endOffset":489763,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":489820,"endOffset":489888,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":489967,"endOffset":490034,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":490111,"endOffset":490184,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":490264,"endOffset":490368,"count":0}],"isBlockCoverage":false},{"functionName":"getRoot$1","ranges":[{"startOffset":490441,"endOffset":490777,"count":0}],"isBlockCoverage":false},{"functionName":"relativePathToUri$1","ranges":[{"startOffset":490804,"endOffset":491061,"count":0}],"isBlockCoverage":false},{"functionName":"pathsEqual$2","ranges":[{"startOffset":491081,"endOffset":491140,"count":0}],"isBlockCoverage":false},{"functionName":"get$hasTrailingSeparator","ranges":[{"startOffset":491205,"endOffset":491442,"count":0}],"isBlockCoverage":false},{"functionName":"removeTrailingSeparators$0","ranges":[{"startOffset":491476,"endOffset":491891,"count":0}],"isBlockCoverage":false},{"functionName":"normalize$0","ranges":[{"startOffset":491910,"endOffset":493391,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":493409,"endOffset":493905,"count":0}],"isBlockCoverage":false},{"functionName":"set$parts","ranges":[{"startOffset":493922,"endOffset":494022,"count":0}],"isBlockCoverage":false},{"functionName":"set$separators","ranges":[{"startOffset":494044,"endOffset":494159,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":494224,"endOffset":494290,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":494364,"endOffset":494430,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":494476,"endOffset":494529,"count":0}],"isBlockCoverage":false},{"functionName":"containsSeparator$1","ranges":[{"startOffset":494589,"endOffset":494666,"count":0}],"isBlockCoverage":false},{"functionName":"isSeparator$1","ranges":[{"startOffset":494687,"endOffset":494743,"count":0}],"isBlockCoverage":false},{"functionName":"needsSeparator$1","ranges":[{"startOffset":494767,"endOffset":494881,"count":0}],"isBlockCoverage":false},{"functionName":"rootLength$2$withDrive","ranges":[{"startOffset":494911,"endOffset":495044,"count":0}],"isBlockCoverage":false},{"functionName":"rootLength$1","ranges":[{"startOffset":495064,"endOffset":495141,"count":0}],"isBlockCoverage":false},{"functionName":"isRootRelative$1","ranges":[{"startOffset":495165,"endOffset":495207,"count":0}],"isBlockCoverage":false},{"functionName":"pathFromUri$1","ranges":[{"startOffset":495228,"endOffset":495555,"count":0}],"isBlockCoverage":false},{"functionName":"absolutePathToUri$1","ranges":[{"startOffset":495582,"endOffset":495981,"count":0}],"isBlockCoverage":false},{"functionName":"get$name","ranges":[{"startOffset":495997,"endOffset":496047,"count":0}],"isBlockCoverage":false},{"functionName":"get$separator","ranges":[{"startOffset":496068,"endOffset":496115,"count":0}],"isBlockCoverage":false},{"functionName":"containsSeparator$1","ranges":[{"startOffset":496173,"endOffset":496250,"count":0}],"isBlockCoverage":false},{"functionName":"isSeparator$1","ranges":[{"startOffset":496271,"endOffset":496327,"count":0}],"isBlockCoverage":false},{"functionName":"needsSeparator$1","ranges":[{"startOffset":496351,"endOffset":496625,"count":0}],"isBlockCoverage":false},{"functionName":"rootLength$2$withDrive","ranges":[{"startOffset":496655,"endOffset":497605,"count":0}],"isBlockCoverage":false},{"functionName":"rootLength$1","ranges":[{"startOffset":497625,"endOffset":497702,"count":0}],"isBlockCoverage":false},{"functionName":"isRootRelative$1","ranges":[{"startOffset":497726,"endOffset":497817,"count":0}],"isBlockCoverage":false},{"functionName":"pathFromUri$1","ranges":[{"startOffset":497838,"endOffset":497892,"count":0}],"isBlockCoverage":false},{"functionName":"relativePathToUri$1","ranges":[{"startOffset":497919,"endOffset":497973,"count":0}],"isBlockCoverage":false},{"functionName":"absolutePathToUri$1","ranges":[{"startOffset":498000,"endOffset":498054,"count":0}],"isBlockCoverage":false},{"functionName":"get$name","ranges":[{"startOffset":498070,"endOffset":498120,"count":0}],"isBlockCoverage":false},{"functionName":"get$separator","ranges":[{"startOffset":498141,"endOffset":498188,"count":0}],"isBlockCoverage":false},{"functionName":"containsSeparator$1","ranges":[{"startOffset":498250,"endOffset":498327,"count":0}],"isBlockCoverage":false},{"functionName":"isSeparator$1","ranges":[{"startOffset":498348,"endOffset":498423,"count":0}],"isBlockCoverage":false},{"functionName":"needsSeparator$1","ranges":[{"startOffset":498447,"endOffset":498622,"count":0}],"isBlockCoverage":false},{"functionName":"rootLength$2$withDrive","ranges":[{"startOffset":498652,"endOffset":499519,"count":0}],"isBlockCoverage":false},{"functionName":"rootLength$1","ranges":[{"startOffset":499539,"endOffset":499616,"count":0}],"isBlockCoverage":false},{"functionName":"isRootRelative$1","ranges":[{"startOffset":499640,"endOffset":499706,"count":0}],"isBlockCoverage":false},{"functionName":"pathFromUri$1","ranges":[{"startOffset":499727,"endOffset":500380,"count":0}],"isBlockCoverage":false},{"functionName":"absolutePathToUri$1","ranges":[{"startOffset":500407,"endOffset":501556,"count":0}],"isBlockCoverage":false},{"functionName":"codeUnitsEqual$2","ranges":[{"startOffset":501580,"endOffset":501969,"count":0}],"isBlockCoverage":false},{"functionName":"pathsEqual$2","ranges":[{"startOffset":501989,"endOffset":502379,"count":0}],"isBlockCoverage":false},{"functionName":"get$name","ranges":[{"startOffset":502395,"endOffset":502445,"count":0}],"isBlockCoverage":false},{"functionName":"get$separator","ranges":[{"startOffset":502466,"endOffset":502513,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":502588,"endOffset":502655,"count":0}],"isBlockCoverage":false},{"functionName":"toTrace$0","ranges":[{"startOffset":502719,"endOffset":503068,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":503086,"endOffset":503628,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":503712,"endOffset":503885,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":503968,"endOffset":504053,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":504131,"endOffset":504223,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":504303,"endOffset":504679,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":504760,"endOffset":504879,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":504958,"endOffset":505296,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":505376,"endOffset":505558,"count":0}],"isBlockCoverage":false},{"functionName":"get$isCore","ranges":[{"startOffset":505624,"endOffset":505689,"count":0}],"isBlockCoverage":false},{"functionName":"get$library","ranges":[{"startOffset":505708,"endOffset":505863,"count":0}],"isBlockCoverage":false},{"functionName":"get$$package","ranges":[{"startOffset":505883,"endOffset":506053,"count":0}],"isBlockCoverage":false},{"functionName":"get$location","ranges":[{"startOffset":506073,"endOffset":506361,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":506379,"endOffset":506469,"count":0}],"isBlockCoverage":false},{"functionName":"get$uri","ranges":[{"startOffset":506484,"endOffset":506525,"count":0}],"isBlockCoverage":false},{"functionName":"get$line","ranges":[{"startOffset":506541,"endOffset":506583,"count":0}],"isBlockCoverage":false},{"functionName":"get$column","ranges":[{"startOffset":506601,"endOffset":506645,"count":0}],"isBlockCoverage":false},{"functionName":"get$member","ranges":[{"startOffset":506663,"endOffset":506707,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":506771,"endOffset":507825,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":507908,"endOffset":508742,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":508839,"endOffset":509859,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":509948,"endOffset":511172,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":511261,"endOffset":512805,"count":0}],"isBlockCoverage":false},{"functionName":"get$_trace","ranges":[{"startOffset":512874,"endOffset":513090,"count":0}],"isBlockCoverage":false},{"functionName":"get$frames","ranges":[{"startOffset":513108,"endOffset":513171,"count":0}],"isBlockCoverage":false},{"functionName":"get$terse","ranges":[{"startOffset":513188,"endOffset":513273,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":513291,"endOffset":513357,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":513456,"endOffset":513524,"count":0}],"isBlockCoverage":false},{"functionName":"get$terse","ranges":[{"startOffset":513589,"endOffset":513680,"count":0}],"isBlockCoverage":false},{"functionName":"foldFrames$2$terse","ranges":[{"startOffset":513706,"endOffset":515185,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":515203,"endOffset":515689,"count":0}],"isBlockCoverage":false},{"functionName":"get$frames","ranges":[{"startOffset":515729,"endOffset":515773,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":515834,"endOffset":515912,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":515991,"endOffset":516074,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":516151,"endOffset":516253,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":516331,"endOffset":516414,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":516495,"endOffset":516567,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":516649,"endOffset":516732,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":516814,"endOffset":516927,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":517010,"endOffset":517098,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":517181,"endOffset":517269,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":517353,"endOffset":517442,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":517517,"endOffset":517556,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":517637,"endOffset":517967,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":518049,"endOffset":518442,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":518522,"endOffset":518641,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":518720,"endOffset":518989,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":519063,"endOffset":519108,"count":0}],"isBlockCoverage":false},{"functionName":"get$uri","ranges":[{"startOffset":519140,"endOffset":519181,"count":0}],"isBlockCoverage":false},{"functionName":"get$line","ranges":[{"startOffset":519197,"endOffset":519239,"count":0}],"isBlockCoverage":false},{"functionName":"get$column","ranges":[{"startOffset":519257,"endOffset":519301,"count":0}],"isBlockCoverage":false},{"functionName":"get$isCore","ranges":[{"startOffset":519319,"endOffset":519363,"count":0}],"isBlockCoverage":false},{"functionName":"get$library","ranges":[{"startOffset":519382,"endOffset":519427,"count":0}],"isBlockCoverage":false},{"functionName":"get$$package","ranges":[{"startOffset":519447,"endOffset":519493,"count":0}],"isBlockCoverage":false},{"functionName":"get$location","ranges":[{"startOffset":519513,"endOffset":519567,"count":0}],"isBlockCoverage":false},{"functionName":"get$member","ranges":[{"startOffset":519585,"endOffset":519629,"count":0}],"isBlockCoverage":false},{"functionName":"GuaranteeChannel$3$allowSinkErrors","ranges":[{"startOffset":519710,"endOffset":520046,"count":1}],"isBlockCoverage":true},{"functionName":"_onSinkDisconnected$0","ranges":[{"startOffset":520075,"endOffset":520266,"count":0}],"isBlockCoverage":false},{"functionName":"set$_sink","ranges":[{"startOffset":520283,"endOffset":520401,"count":1}],"isBlockCoverage":true},{"functionName":"set$_streamController","ranges":[{"startOffset":520430,"endOffset":520588,"count":1}],"isBlockCoverage":true},{"functionName":"set$_guarantee_channel$_subscription","ranges":[{"startOffset":520632,"endOffset":520801,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":520862,"endOffset":521185,"count":1},{"startOffset":520956,"endOffset":520963,"count":0}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":521266,"endOffset":521392,"count":0}],"isBlockCoverage":false},{"functionName":"add$1","ranges":[{"startOffset":521510,"endOffset":522038,"count":1},{"startOffset":521653,"endOffset":521725,"count":0},{"startOffset":521781,"endOffset":521859,"count":0},{"startOffset":521898,"endOffset":521905,"count":0}],"isBlockCoverage":true},{"functionName":"addError$2","ranges":[{"startOffset":522056,"endOffset":522478,"count":0}],"isBlockCoverage":false},{"functionName":"addError$1","ranges":[{"startOffset":522496,"endOffset":522562,"count":0}],"isBlockCoverage":false},{"functionName":"_addError$2","ranges":[{"startOffset":522581,"endOffset":522735,"count":0}],"isBlockCoverage":false},{"functionName":"_addError$1","ranges":[{"startOffset":522754,"endOffset":522821,"count":0}],"isBlockCoverage":false},{"functionName":"addStream$1","ranges":[{"startOffset":522840,"endOffset":523722,"count":1},{"startOffset":522976,"endOffset":523049,"count":0},{"startOffset":523105,"endOffset":523184,"count":0},{"startOffset":523215,"endOffset":523334,"count":0}],"isBlockCoverage":true},{"functionName":"close$0","ranges":[{"startOffset":523737,"endOffset":524196,"count":0}],"isBlockCoverage":false},{"functionName":"_onStreamDisconnected$0","ranges":[{"startOffset":524227,"endOffset":524597,"count":0}],"isBlockCoverage":false},{"functionName":"set$_addStreamSubscription","ranges":[{"startOffset":524631,"endOffset":524808,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":524925,"endOffset":525051,"count":0}],"isBlockCoverage":false},{"functionName":"_MultiChannel$1","ranges":[{"startOffset":525129,"endOffset":525778,"count":1}],"isBlockCoverage":true},{"functionName":"virtualChannel$1","ranges":[{"startOffset":525802,"endOffset":527448,"count":1},{"startOffset":526029,"endOffset":526206,"count":0},{"startOffset":526253,"endOffset":526477,"count":0},{"startOffset":526530,"endOffset":526575,"count":0},{"startOffset":526702,"endOffset":526803,"count":0}],"isBlockCoverage":true},{"functionName":"_closeChannel$2","ranges":[{"startOffset":527471,"endOffset":527872,"count":0}],"isBlockCoverage":false},{"functionName":"_closeInnerChannel$0","ranges":[{"startOffset":527900,"endOffset":528350,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":528432,"endOffset":528620,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":528638,"endOffset":528705,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":528764,"endOffset":528829,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":528956,"endOffset":529518,"count":1},{"startOffset":529164,"endOffset":529171,"count":0},{"startOffset":529457,"endOffset":529512,"count":0}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":529596,"endOffset":529733,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":529751,"endOffset":529835,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":529908,"endOffset":530159,"count":1}],"isBlockCoverage":true},{"functionName":"$signature","ranges":[{"startOffset":530177,"endOffset":530277,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":530351,"endOffset":530463,"count":0}],"isBlockCoverage":false},{"functionName":"get$local","ranges":[{"startOffset":530647,"endOffset":530691,"count":0}],"isBlockCoverage":false},{"functionName":"set$_local","ranges":[{"startOffset":530709,"endOffset":530828,"count":1}],"isBlockCoverage":true},{"functionName":"set$_foreign","ranges":[{"startOffset":530848,"endOffset":530973,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":531139,"endOffset":532002,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":532120,"endOffset":533385,"count":1},{"startOffset":532816,"endOffset":533379,"count":0}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":533455,"endOffset":533696,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":533767,"endOffset":534167,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":534238,"endOffset":534587,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":534706,"endOffset":534887,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":535005,"endOffset":535323,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":535453,"endOffset":535766,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":535848,"endOffset":535966,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":536046,"endOffset":537326,"count":1},{"startOffset":536265,"endOffset":536272,"count":0},{"startOffset":536472,"endOffset":536479,"count":0},{"startOffset":536965,"endOffset":537320,"count":0}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":537408,"endOffset":537676,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":537758,"endOffset":538685,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":537952,"endOffset":538612,"count":1},{"startOffset":538042,"endOffset":538098,"count":0}],"isBlockCoverage":true},{"functionName":"aliases","ranges":[{"startOffset":538714,"endOffset":539149,"count":1}],"isBlockCoverage":true},{"functionName":"installTearOffs","ranges":[{"startOffset":539157,"endOffset":544148,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":540050,"endOffset":540089,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":540135,"endOffset":540205,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":540496,"endOffset":540593,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":540702,"endOffset":540820,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":540931,"endOffset":541070,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":541195,"endOffset":541305,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":541440,"endOffset":541561,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":541698,"endOffset":541826,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":542583,"endOffset":542622,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":542757,"endOffset":542796,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":542921,"endOffset":542960,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":543161,"endOffset":543200,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":543660,"endOffset":543699,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":543800,"endOffset":543839,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":544079,"endOffset":544134,"count":0}],"isBlockCoverage":false},{"functionName":"inheritance","ranges":[{"startOffset":544156,"endOffset":556574,"count":1}],"isBlockCoverage":true},{"functionName":"constants","ranges":[{"startOffset":556582,"endOffset":566012,"count":1}],"isBlockCoverage":true},{"functionName":"getTagFallback","ranges":[{"startOffset":557622,"endOffset":557736,"count":0}],"isBlockCoverage":false},{"functionName":"C.C_JS_CONST0","ranges":[{"startOffset":557758,"endOffset":558873,"count":1},{"startOffset":558781,"endOffset":558796,"count":0}],"isBlockCoverage":true},{"functionName":"getTag","ranges":[{"startOffset":557825,"endOffset":557928,"count":0}],"isBlockCoverage":false},{"functionName":"getUnknownTag","ranges":[{"startOffset":557931,"endOffset":558148,"count":0}],"isBlockCoverage":false},{"functionName":"getUnknownTagGenericBrowser","ranges":[{"startOffset":558151,"endOffset":558326,"count":0}],"isBlockCoverage":false},{"functionName":"prototypeForTag","ranges":[{"startOffset":558329,"endOffset":558595,"count":1},{"startOffset":558399,"endOffset":558411,"count":0},{"startOffset":558545,"endOffset":558557,"count":0}],"isBlockCoverage":true},{"functionName":"discriminator","ranges":[{"startOffset":558598,"endOffset":558642,"count":0}],"isBlockCoverage":false},{"functionName":"C.C_JS_CONST6","ranges":[{"startOffset":558895,"endOffset":559359,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":558931,"endOffset":559356,"count":1},{"startOffset":558987,"endOffset":559000,"count":0},{"startOffset":559078,"endOffset":559091,"count":0},{"startOffset":559317,"endOffset":559355,"count":0}],"isBlockCoverage":true},{"functionName":"confirm","ranges":[{"startOffset":559135,"endOffset":559242,"count":1}],"isBlockCoverage":true},{"functionName":"C.C_JS_CONST1","ranges":[{"startOffset":559381,"endOffset":559530,"count":1},{"startOffset":559468,"endOffset":559529,"count":0}],"isBlockCoverage":true},{"functionName":"C.C_JS_CONST2","ranges":[{"startOffset":559552,"endOffset":560025,"count":1}],"isBlockCoverage":true},{"functionName":"getTagFixed","ranges":[{"startOffset":559648,"endOffset":559829,"count":0}],"isBlockCoverage":false},{"functionName":"prototypeForTagFixed","ranges":[{"startOffset":559832,"endOffset":559945,"count":1}],"isBlockCoverage":true},{"functionName":"C.C_JS_CONST5","ranges":[{"startOffset":560047,"endOffset":560577,"count":1},{"startOffset":560134,"endOffset":560138,"count":0},{"startOffset":560195,"endOffset":560576,"count":0}],"isBlockCoverage":true},{"functionName":"getTagFirefox","ranges":[{"startOffset":560454,"endOffset":560543,"count":0}],"isBlockCoverage":false},{"functionName":"C.C_JS_CONST4","ranges":[{"startOffset":560599,"endOffset":561481,"count":1},{"startOffset":560686,"endOffset":560690,"count":0},{"startOffset":560748,"endOffset":561480,"count":0}],"isBlockCoverage":true},{"functionName":"getTagIE","ranges":[{"startOffset":561013,"endOffset":561256,"count":0}],"isBlockCoverage":false},{"functionName":"prototypeForTagIE","ranges":[{"startOffset":561259,"endOffset":561407,"count":0}],"isBlockCoverage":false},{"functionName":"C.C_JS_CONST3","ranges":[{"startOffset":561503,"endOffset":561536,"count":1}],"isBlockCoverage":true},{"functionName":"staticFields","ranges":[{"startOffset":566020,"endOffset":566720,"count":1}],"isBlockCoverage":true},{"functionName":"lazyInitializers","ranges":[{"startOffset":566728,"endOffset":575683,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":566870,"endOffset":566948,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":567029,"endOffset":567098,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":567199,"endOffset":567387,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":567484,"endOffset":567687,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":567780,"endOffset":567891,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":567998,"endOffset":568249,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":568352,"endOffset":568465,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":568582,"endOffset":568837,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":568938,"endOffset":569053,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":569168,"endOffset":569357,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":569468,"endOffset":569585,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":569710,"endOffset":569903,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":570002,"endOffset":570077,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":570142,"endOffset":570223,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":570288,"endOffset":570350,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":570413,"endOffset":570448,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":570517,"endOffset":570578,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":570669,"endOffset":571283,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":571354,"endOffset":571512,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":571583,"endOffset":571664,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":571721,"endOffset":571771,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":571814,"endOffset":571888,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":571931,"endOffset":572008,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":572059,"endOffset":572220,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":572275,"endOffset":572548,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":572595,"endOffset":572849,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":572906,"endOffset":572966,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":573011,"endOffset":573116,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":573161,"endOffset":573279,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":573336,"endOffset":573422,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":573481,"endOffset":573591,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":573658,"endOffset":573797,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":573854,"endOffset":573959,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":574008,"endOffset":574107,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":574158,"endOffset":574221,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":574282,"endOffset":574368,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":574437,"endOffset":574524,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":574577,"endOffset":574658,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":574703,"endOffset":574773,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":574826,"endOffset":574893,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":574960,"endOffset":575064,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":575121,"endOffset":575225,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":575270,"endOffset":575364,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":575421,"endOffset":575534,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":575585,"endOffset":575677,"count":1}],"isBlockCoverage":true},{"functionName":"nativeSupport","ranges":[{"startOffset":579591,"endOffset":596530,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":579623,"endOffset":580408,"count":1},{"startOffset":580311,"endOffset":580407,"count":0}],"isBlockCoverage":true},{"functionName":"intern","ranges":[{"startOffset":579655,"endOffset":579781,"count":1}],"isBlockCoverage":true},{"functionName":"init.getIsolateTag","ranges":[{"startOffset":579810,"endOffset":579894,"count":1}],"isBlockCoverage":true},{"functionName":"Function.call$0","ranges":[{"startOffset":596565,"endOffset":596600,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$1","ranges":[{"startOffset":596632,"endOffset":596669,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$2","ranges":[{"startOffset":596701,"endOffset":596744,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$3","ranges":[{"startOffset":596776,"endOffset":596825,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$4","ranges":[{"startOffset":596857,"endOffset":596912,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$1$1","ranges":[{"startOffset":596946,"endOffset":596983,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$3$1","ranges":[{"startOffset":597017,"endOffset":597054,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$3$3","ranges":[{"startOffset":597088,"endOffset":597137,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$2$2","ranges":[{"startOffset":597171,"endOffset":597214,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$2$1","ranges":[{"startOffset":597248,"endOffset":597285,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$2$3","ranges":[{"startOffset":597319,"endOffset":597368,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$1$2","ranges":[{"startOffset":597402,"endOffset":597445,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$5","ranges":[{"startOffset":597477,"endOffset":597538,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$3$4","ranges":[{"startOffset":597572,"endOffset":597627,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$2$4","ranges":[{"startOffset":597661,"endOffset":597716,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$1$4","ranges":[{"startOffset":597750,"endOffset":597805,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$3$6","ranges":[{"startOffset":597839,"endOffset":597906,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$2$5","ranges":[{"startOffset":597940,"endOffset":598001,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":598067,"endOffset":598606,"count":1},{"startOffset":598129,"endOffset":598227,"count":0},{"startOffset":598282,"endOffset":598605,"count":0}],"isBlockCoverage":true},{"functionName":"onLoad","ranges":[{"startOffset":598329,"endOffset":598499,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":598608,"endOffset":598784,"count":1},{"startOffset":598726,"endOffset":598753,"count":0}],"isBlockCoverage":true}]},{"scriptId":"6","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":276,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":275,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff_completeError$20","ranges":[{"startOffset":82,"endOffset":273,"count":0}],"isBlockCoverage":false}]},{"scriptId":"7","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":282,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":281,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff_complete$11","ranges":[{"startOffset":82,"endOffset":279,"count":1}],"isBlockCoverage":true}]},{"scriptId":"8","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":277,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":276,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff__completeError$22","ranges":[{"startOffset":82,"endOffset":274,"count":0}],"isBlockCoverage":false}]},{"scriptId":"9","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":277,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":276,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff_add$13","ranges":[{"startOffset":82,"endOffset":274,"count":1}],"isBlockCoverage":true}]},{"scriptId":"10","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":271,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":270,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff_addError$24","ranges":[{"startOffset":82,"endOffset":268,"count":1}],"isBlockCoverage":true}]},{"scriptId":"11","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":277,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":276,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff_add$15","ranges":[{"startOffset":82,"endOffset":274,"count":1}],"isBlockCoverage":true}]},{"scriptId":"12","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":272,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":271,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff__sendDone$06","ranges":[{"startOffset":82,"endOffset":269,"count":0}],"isBlockCoverage":false}]},{"scriptId":"13","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":271,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":270,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff_addError$27","ranges":[{"startOffset":82,"endOffset":268,"count":1}],"isBlockCoverage":true}]},{"scriptId":"14","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":272,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":271,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff__addError$28","ranges":[{"startOffset":82,"endOffset":269,"count":1}],"isBlockCoverage":true}]},{"scriptId":"15","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":281,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":280,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff__closeInnerChannel$09","ranges":[{"startOffset":82,"endOffset":278,"count":1}],"isBlockCoverage":true}]},{"scriptId":"16","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":62,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":61,"count":1}],"isBlockCoverage":true}]},{"scriptId":"17","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":92,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":91,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":32,"endOffset":89,"count":1},{"startOffset":87,"endOffset":88,"count":0}],"isBlockCoverage":true}]},{"scriptId":"18","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":62,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":61,"count":1}],"isBlockCoverage":true}]},{"scriptId":"19","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":86,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":85,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":32,"endOffset":83,"count":0}],"isBlockCoverage":false}]},{"scriptId":"20","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":62,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":61,"count":1}],"isBlockCoverage":true}]},{"scriptId":"21","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":106,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":105,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":32,"endOffset":103,"count":0}],"isBlockCoverage":false}]},{"scriptId":"22","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":62,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":61,"count":1}],"isBlockCoverage":true}]},{"scriptId":"23","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":86,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":85,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":32,"endOffset":83,"count":0}],"isBlockCoverage":false}]},{"scriptId":"24","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":62,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":61,"count":1}],"isBlockCoverage":true}]},{"scriptId":"25","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":92,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":91,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":32,"endOffset":89,"count":1},{"startOffset":87,"endOffset":88,"count":0}],"isBlockCoverage":true}]},{"scriptId":"26","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":64,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":63,"count":1}],"isBlockCoverage":true}]},{"scriptId":"27","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":98,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":97,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":32,"endOffset":95,"count":0}],"isBlockCoverage":false}]},{"scriptId":"28","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":64,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":63,"count":1}],"isBlockCoverage":true}]},{"scriptId":"29","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":89,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":88,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":32,"endOffset":86,"count":0}],"isBlockCoverage":false}]},{"scriptId":"30","url":"http://localhost:33587/JvrQonmMf3ATS3rRCO76ZTlBfGvy%2Fj69/test/packages/test/dart.js","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":2011,"count":1}],"isBlockCoverage":true},{"functionName":"window.onload","ranges":[{"startOffset":384,"endOffset":2009,"count":1},{"startOffset":1295,"endOffset":1442,"count":0},{"startOffset":1491,"endOffset":1629,"count":0}],"isBlockCoverage":true},{"functionName":"sendLoadException","ranges":[{"startOffset":560,"endOffset":762,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":875,"endOffset":921,"count":0}],"isBlockCoverage":false},{"functionName":"script.onerror","ranges":[{"startOffset":1747,"endOffset":1907,"count":0}],"isBlockCoverage":false}]},{"scriptId":"31","url":"http://localhost:33587/JvrQonmMf3ATS3rRCO76ZTlBfGvy%2Fj69/test/main_test.dart.browser_test.dart.js","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":1081547,"count":1}],"isBlockCoverage":true},{"functionName":"dartProgram","ranges":[{"startOffset":1051,"endOffset":1081480,"count":1}],"isBlockCoverage":true},{"functionName":"copyProperties","ranges":[{"startOffset":1078,"endOffset":1253,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1288,"endOffset":1858,"count":1},{"startOffset":1469,"endOffset":1482,"count":0},{"startOffset":1645,"endOffset":1707,"count":0},{"startOffset":1709,"endOffset":1812,"count":0},{"startOffset":1818,"endOffset":1857,"count":0}],"isBlockCoverage":true},{"functionName":"cls","ranges":[{"startOffset":1315,"endOffset":1333,"count":1}],"isBlockCoverage":true},{"functionName":"setFunctionNamesIfNecessary","ranges":[{"startOffset":1864,"endOffset":2287,"count":1},{"startOffset":1991,"endOffset":2283,"count":0}],"isBlockCoverage":true},{"functionName":"t","ranges":[{"startOffset":1916,"endOffset":1936,"count":0}],"isBlockCoverage":false},{"functionName":"inherit","ranges":[{"startOffset":2290,"endOffset":2685,"count":1},{"startOffset":2533,"endOffset":2681,"count":0}],"isBlockCoverage":true},{"functionName":"inheritMany","ranges":[{"startOffset":2688,"endOffset":2805,"count":1}],"isBlockCoverage":true},{"functionName":"mixin","ranges":[{"startOffset":2808,"endOffset":2929,"count":1}],"isBlockCoverage":true},{"functionName":"lazy","ranges":[{"startOffset":2932,"endOffset":3681,"count":1}],"isBlockCoverage":true},{"functionName":"holder.<computed>","ranges":[{"startOffset":3094,"endOffset":3676,"count":1},{"startOffset":3429,"endOffset":3467,"count":0},{"startOffset":3539,"endOffset":3559,"count":0}],"isBlockCoverage":true},{"functionName":"holder.<computed>","ranges":[{"startOffset":3134,"endOffset":3187,"count":0}],"isBlockCoverage":false},{"functionName":"holder.<computed>","ranges":[{"startOffset":3589,"endOffset":3640,"count":1}],"isBlockCoverage":true},{"functionName":"makeConstList","ranges":[{"startOffset":3684,"endOffset":3799,"count":1}],"isBlockCoverage":true},{"functionName":"convertToFastObject","ranges":[{"startOffset":3802,"endOffset":3939,"count":1}],"isBlockCoverage":true},{"functionName":"t","ranges":[{"startOffset":3849,"endOffset":3869,"count":1}],"isBlockCoverage":true},{"functionName":"convertAllToFastObject","ranges":[{"startOffset":3942,"endOffset":4093,"count":1}],"isBlockCoverage":true},{"functionName":"tearOffGetter","ranges":[{"startOffset":4123,"endOffset":5038,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff","ranges":[{"startOffset":5041,"endOffset":5449,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":5180,"endOffset":5362,"count":1}],"isBlockCoverage":true},{"functionName":"installTearOff","ranges":[{"startOffset":5475,"endOffset":6389,"count":1}],"isBlockCoverage":true},{"functionName":"installStaticTearOff","ranges":[{"startOffset":6392,"endOffset":6715,"count":1}],"isBlockCoverage":true},{"functionName":"installInstanceTearOff","ranges":[{"startOffset":6718,"endOffset":7067,"count":1}],"isBlockCoverage":true},{"functionName":"setOrUpdateInterceptorsByTag","ranges":[{"startOffset":7070,"endOffset":7273,"count":1},{"startOffset":7234,"endOffset":7272,"count":0}],"isBlockCoverage":true},{"functionName":"setOrUpdateLeafTags","ranges":[{"startOffset":7276,"endOffset":7452,"count":1},{"startOffset":7413,"endOffset":7451,"count":0}],"isBlockCoverage":true},{"functionName":"updateTypes","ranges":[{"startOffset":7455,"endOffset":7608,"count":0}],"isBlockCoverage":false},{"functionName":"updateHolder","ranges":[{"startOffset":7611,"endOffset":7715,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":7736,"endOffset":9400,"count":1}],"isBlockCoverage":true},{"functionName":"mkInstance","ranges":[{"startOffset":7770,"endOffset":8132,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":7890,"endOffset":8123,"count":1}],"isBlockCoverage":true},{"functionName":"mkStatic","ranges":[{"startOffset":8151,"endOffset":8481,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":8256,"endOffset":8472,"count":1}],"isBlockCoverage":true},{"functionName":"initializeDeferredHunk","ranges":[{"startOffset":9406,"endOffset":9527,"count":0}],"isBlockCoverage":false},{"functionName":"getGlobalFromName","ranges":[{"startOffset":9530,"endOffset":9727,"count":0}],"isBlockCoverage":false},{"functionName":"JS_CONST","ranges":[{"startOffset":9759,"endOffset":9786,"count":0}],"isBlockCoverage":false},{"functionName":"CastIterable_CastIterable","ranges":[{"startOffset":9819,"endOffset":10153,"count":1},{"startOffset":10045,"endOffset":10152,"count":0}],"isBlockCoverage":true},{"functionName":"hexDigitValue","ranges":[{"startOffset":10174,"endOffset":10439,"count":0}],"isBlockCoverage":false},{"functionName":"SubListIterable$","ranges":[{"startOffset":10463,"endOffset":10899,"count":0}],"isBlockCoverage":false},{"functionName":"MappedIterable_MappedIterable","ranges":[{"startOffset":10936,"endOffset":11314,"count":0}],"isBlockCoverage":false},{"functionName":"IterableElementError_noElement","ranges":[{"startOffset":11352,"endOffset":11415,"count":0}],"isBlockCoverage":false},{"functionName":"IterableElementError_tooMany","ranges":[{"startOffset":11451,"endOffset":11521,"count":0}],"isBlockCoverage":false},{"functionName":"IterableElementError_tooFew","ranges":[{"startOffset":11556,"endOffset":11625,"count":0}],"isBlockCoverage":false},{"functionName":"_CastIterableBase","ranges":[{"startOffset":11650,"endOffset":11686,"count":0}],"isBlockCoverage":false},{"functionName":"CastIterator","ranges":[{"startOffset":11706,"endOffset":11789,"count":1}],"isBlockCoverage":true},{"functionName":"CastIterable","ranges":[{"startOffset":11809,"endOffset":11892,"count":0}],"isBlockCoverage":false},{"functionName":"_EfficientLengthCastIterable","ranges":[{"startOffset":11928,"endOffset":12027,"count":1}],"isBlockCoverage":true},{"functionName":"CastMap","ranges":[{"startOffset":12042,"endOffset":12120,"count":1}],"isBlockCoverage":true},{"functionName":"CastMap_forEach_closure","ranges":[{"startOffset":12151,"endOffset":12241,"count":0}],"isBlockCoverage":false},{"functionName":"CodeUnits","ranges":[{"startOffset":12258,"endOffset":12313,"count":0}],"isBlockCoverage":false},{"functionName":"EfficientLengthIterable","ranges":[{"startOffset":12344,"endOffset":12386,"count":0}],"isBlockCoverage":false},{"functionName":"ListIterable","ranges":[{"startOffset":12406,"endOffset":12437,"count":0}],"isBlockCoverage":false},{"functionName":"SubListIterable","ranges":[{"startOffset":12460,"endOffset":12640,"count":0}],"isBlockCoverage":false},{"functionName":"ListIterator","ranges":[{"startOffset":12660,"endOffset":12874,"count":1}],"isBlockCoverage":true},{"functionName":"MappedIterable","ranges":[{"startOffset":12896,"endOffset":13018,"count":1}],"isBlockCoverage":true},{"functionName":"EfficientLengthMappedIterable","ranges":[{"startOffset":13055,"endOffset":13192,"count":0}],"isBlockCoverage":false},{"functionName":"MappedIterator","ranges":[{"startOffset":13214,"endOffset":13372,"count":1}],"isBlockCoverage":true},{"functionName":"MappedListIterable","ranges":[{"startOffset":13398,"endOffset":13511,"count":1}],"isBlockCoverage":true},{"functionName":"WhereIterable","ranges":[{"startOffset":13532,"endOffset":13653,"count":1}],"isBlockCoverage":true},{"functionName":"WhereIterator","ranges":[{"startOffset":13674,"endOffset":13784,"count":1}],"isBlockCoverage":true},{"functionName":"ExpandIterable","ranges":[{"startOffset":13806,"endOffset":13928,"count":0}],"isBlockCoverage":false},{"functionName":"ExpandIterator","ranges":[{"startOffset":13950,"endOffset":14144,"count":0}],"isBlockCoverage":false},{"functionName":"SkipWhileIterable","ranges":[{"startOffset":14169,"endOffset":14294,"count":0}],"isBlockCoverage":false},{"functionName":"SkipWhileIterator","ranges":[{"startOffset":14319,"endOffset":14473,"count":0}],"isBlockCoverage":false},{"functionName":"EmptyIterator","ranges":[{"startOffset":14494,"endOffset":14549,"count":1}],"isBlockCoverage":true},{"functionName":"FixedLengthListMixin","ranges":[{"startOffset":14577,"endOffset":14616,"count":0}],"isBlockCoverage":false},{"functionName":"UnmodifiableListMixin","ranges":[{"startOffset":14645,"endOffset":14685,"count":0}],"isBlockCoverage":false},{"functionName":"UnmodifiableListBase","ranges":[{"startOffset":14713,"endOffset":14752,"count":0}],"isBlockCoverage":false},{"functionName":"ReversedListIterable","ranges":[{"startOffset":14780,"endOffset":14871,"count":1}],"isBlockCoverage":true},{"functionName":"Symbol","ranges":[{"startOffset":14885,"endOffset":14946,"count":1}],"isBlockCoverage":true},{"functionName":"ConstantMap__throwUnmodifiable","ranges":[{"startOffset":14984,"endOffset":15086,"count":0}],"isBlockCoverage":false},{"functionName":"instantiate1","ranges":[{"startOffset":15106,"endOffset":15248,"count":0}],"isBlockCoverage":false},{"functionName":"unminifyOrTag","ranges":[{"startOffset":15269,"endOffset":15468,"count":0}],"isBlockCoverage":false},{"functionName":"isJsIndexable","ranges":[{"startOffset":15489,"endOffset":15722,"count":0}],"isBlockCoverage":false},{"functionName":"S","ranges":[{"startOffset":15731,"endOffset":16230,"count":1},{"startOffset":15821,"endOffset":16229,"count":0}],"isBlockCoverage":true},{"functionName":"Primitives_objectHashCode","ranges":[{"startOffset":16263,"endOffset":16463,"count":1}],"isBlockCoverage":true},{"functionName":"Primitives_parseInt","ranges":[{"startOffset":16490,"endOffset":17741,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_objectTypeName","ranges":[{"startOffset":17774,"endOffset":17874,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives__objectTypeNameNewRti","ranges":[{"startOffset":17914,"endOffset":18695,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives__saneNativeClassName","ranges":[{"startOffset":18734,"endOffset":18825,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_dateNow","ranges":[{"startOffset":18851,"endOffset":18894,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_initTicker","ranges":[{"startOffset":18923,"endOffset":19555,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_currentUri","ranges":[{"startOffset":19584,"endOffset":19683,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives__fromCharCodeApply","ranges":[{"startOffset":19720,"endOffset":20112,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_stringFromCodePoints","ranges":[{"startOffset":20151,"endOffset":20858,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_stringFromCharCodes","ranges":[{"startOffset":20896,"endOffset":21417,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_stringFromNativeUint8List","ranges":[{"startOffset":21461,"endOffset":21888,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_stringFromCharCode","ranges":[{"startOffset":21925,"endOffset":22438,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_lazyAsJsDate","ranges":[{"startOffset":22469,"endOffset":22610,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_getYear","ranges":[{"startOffset":22636,"endOffset":22752,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_getMonth","ranges":[{"startOffset":22779,"endOffset":22892,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_getDay","ranges":[{"startOffset":22917,"endOffset":23029,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_getHours","ranges":[{"startOffset":23056,"endOffset":23169,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_getMinutes","ranges":[{"startOffset":23198,"endOffset":23313,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_getSeconds","ranges":[{"startOffset":23342,"endOffset":23457,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_getMilliseconds","ranges":[{"startOffset":23491,"endOffset":23611,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_getProperty","ranges":[{"startOffset":23641,"endOffset":23862,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_setProperty","ranges":[{"startOffset":23892,"endOffset":24121,"count":0}],"isBlockCoverage":false},{"functionName":"iae","ranges":[{"startOffset":24132,"endOffset":24219,"count":0}],"isBlockCoverage":false},{"functionName":"ioore","ranges":[{"startOffset":24232,"endOffset":24397,"count":0}],"isBlockCoverage":false},{"functionName":"diagnoseIndexError","ranges":[{"startOffset":24423,"endOffset":24943,"count":0}],"isBlockCoverage":false},{"functionName":"diagnoseRangeError","ranges":[{"startOffset":24969,"endOffset":25354,"count":0}],"isBlockCoverage":false},{"functionName":"argumentErrorValue","ranges":[{"startOffset":25380,"endOffset":25464,"count":0}],"isBlockCoverage":false},{"functionName":"checkNum","ranges":[{"startOffset":25480,"endOffset":25619,"count":0}],"isBlockCoverage":false},{"functionName":"wrapException","ranges":[{"startOffset":25640,"endOffset":26027,"count":0}],"isBlockCoverage":false},{"functionName":"toStringWrapper","ranges":[{"startOffset":26050,"endOffset":26116,"count":0}],"isBlockCoverage":false},{"functionName":"throwExpression","ranges":[{"startOffset":26139,"endOffset":26192,"count":0}],"isBlockCoverage":false},{"functionName":"throwConcurrentModificationError","ranges":[{"startOffset":26232,"endOffset":26333,"count":0}],"isBlockCoverage":false},{"functionName":"TypeErrorDecoder_extractPattern","ranges":[{"startOffset":26372,"endOffset":27376,"count":0}],"isBlockCoverage":false},{"functionName":"TypeErrorDecoder_provokeCallErrorOn","ranges":[{"startOffset":27419,"endOffset":27663,"count":0}],"isBlockCoverage":false},{"functionName":"TypeErrorDecoder_provokePropertyErrorOn","ranges":[{"startOffset":27710,"endOffset":27892,"count":0}],"isBlockCoverage":false},{"functionName":"NullError$","ranges":[{"startOffset":27910,"endOffset":28020,"count":0}],"isBlockCoverage":false},{"functionName":"JsNoSuchMethodError$","ranges":[{"startOffset":28048,"endOffset":28232,"count":0}],"isBlockCoverage":false},{"functionName":"unwrapException","ranges":[{"startOffset":28255,"endOffset":32748,"count":0}],"isBlockCoverage":false},{"functionName":"getTraceFromException","ranges":[{"startOffset":32777,"endOffset":33142,"count":1},{"startOffset":32881,"endOffset":32909,"count":0},{"startOffset":32947,"endOffset":32983,"count":0},{"startOffset":33055,"endOffset":33068,"count":0}],"isBlockCoverage":true},{"functionName":"objectHashCode","ranges":[{"startOffset":33164,"endOffset":33346,"count":1}],"isBlockCoverage":true},{"functionName":"fillLiteralMap","ranges":[{"startOffset":33368,"endOffset":33829,"count":1}],"isBlockCoverage":true},{"functionName":"fillLiteralSet","ranges":[{"startOffset":33851,"endOffset":34149,"count":1}],"isBlockCoverage":true},{"functionName":"invokeClosure","ranges":[{"startOffset":34170,"endOffset":34749,"count":1},{"startOffset":34441,"endOffset":34493,"count":0},{"startOffset":34502,"endOffset":34560,"count":0},{"startOffset":34569,"endOffset":34633,"count":0},{"startOffset":34641,"endOffset":34748,"count":0}],"isBlockCoverage":true},{"functionName":"convertDartClosureToJS","ranges":[{"startOffset":34779,"endOffset":35232,"count":1},{"startOffset":34862,"endOffset":34874,"count":0}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":34979,"endOffset":35131,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":35029,"endOffset":35122,"count":1}],"isBlockCoverage":true},{"functionName":"Closure_fromTearOff","ranges":[{"startOffset":35259,"endOffset":37399,"count":1},{"startOffset":36000,"endOffset":36017,"count":0},{"startOffset":37093,"endOffset":37187,"count":0}],"isBlockCoverage":true},{"functionName":"static_tear_off","ranges":[{"startOffset":35831,"endOffset":35899,"count":0}],"isBlockCoverage":false},{"functionName":"Closure__computeSignatureFunctionNewRti","ranges":[{"startOffset":37446,"endOffset":38243,"count":1},{"startOffset":37726,"endOffset":38242,"count":0}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":37580,"endOffset":37686,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":37620,"endOffset":37675,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":37997,"endOffset":38133,"count":0}],"isBlockCoverage":false},{"functionName":"Closure_cspForwardCall","ranges":[{"startOffset":38273,"endOffset":39658,"count":1},{"startOffset":38399,"endOffset":38406,"count":0},{"startOffset":38418,"endOffset":38573,"count":0},{"startOffset":38582,"endOffset":38739,"count":0},{"startOffset":38748,"endOffset":38911,"count":0},{"startOffset":38920,"endOffset":39089,"count":0},{"startOffset":39098,"endOffset":39273,"count":0},{"startOffset":39282,"endOffset":39463,"count":0}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":38443,"endOffset":38553,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":38607,"endOffset":38719,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":38773,"endOffset":38891,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":38945,"endOffset":39069,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":39123,"endOffset":39253,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":39307,"endOffset":39443,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":39498,"endOffset":39623,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":39534,"endOffset":39610,"count":0}],"isBlockCoverage":false},{"functionName":"Closure_forwardCallTo","ranges":[{"startOffset":39687,"endOffset":41342,"count":1},{"startOffset":40050,"endOffset":40076,"count":0},{"startOffset":40341,"endOffset":40358,"count":0},{"startOffset":40594,"endOffset":40672,"count":0},{"startOffset":40960,"endOffset":40977,"count":0},{"startOffset":41199,"endOffset":41277,"count":0}],"isBlockCoverage":true},{"functionName":"Closure_cspForwardInterceptedCall","ranges":[{"startOffset":41383,"endOffset":43149,"count":0}],"isBlockCoverage":false},{"functionName":"Closure_forwardInterceptedCallTo","ranges":[{"startOffset":43189,"endOffset":44760,"count":1},{"startOffset":43766,"endOffset":43792,"count":0},{"startOffset":43880,"endOffset":43956,"count":0},{"startOffset":44175,"endOffset":44192,"count":0},{"startOffset":44651,"endOffset":44668,"count":0}],"isBlockCoverage":true},{"functionName":"closureFromTearOff","ranges":[{"startOffset":44786,"endOffset":45024,"count":1}],"isBlockCoverage":true},{"functionName":"BoundClosure_evalRecipe","ranges":[{"startOffset":45055,"endOffset":45190,"count":0}],"isBlockCoverage":false},{"functionName":"BoundClosure_evalRecipeIntercepted","ranges":[{"startOffset":45232,"endOffset":45371,"count":0}],"isBlockCoverage":false},{"functionName":"BoundClosure_selfOf","ranges":[{"startOffset":45398,"endOffset":45451,"count":0}],"isBlockCoverage":false},{"functionName":"BoundClosure_receiverOf","ranges":[{"startOffset":45482,"endOffset":45539,"count":0}],"isBlockCoverage":false},{"functionName":"BoundClosure_computeFieldNamed","ranges":[{"startOffset":45577,"endOffset":45937,"count":1}],"isBlockCoverage":true},{"functionName":"boolConversionCheck","ranges":[{"startOffset":45964,"endOffset":46094,"count":1},{"startOffset":46015,"endOffset":46068,"count":0}],"isBlockCoverage":true},{"functionName":"extractFunctionTypeObjectFromInternal","ranges":[{"startOffset":46139,"endOffset":46420,"count":0}],"isBlockCoverage":false},{"functionName":"TypeErrorImplementation$","ranges":[{"startOffset":46452,"endOffset":46662,"count":0}],"isBlockCoverage":false},{"functionName":"_typeDescription","ranges":[{"startOffset":46686,"endOffset":47058,"count":0}],"isBlockCoverage":false},{"functionName":"assertTest","ranges":[{"startOffset":47076,"endOffset":47290,"count":1},{"startOffset":47149,"endOffset":47289,"count":0}],"isBlockCoverage":true},{"functionName":"assertThrow","ranges":[{"startOffset":47309,"endOffset":47395,"count":0}],"isBlockCoverage":false},{"functionName":"assertHelper","ranges":[{"startOffset":47415,"endOffset":47533,"count":1},{"startOffset":47480,"endOffset":47527,"count":0}],"isBlockCoverage":true},{"functionName":"throwCyclicInit","ranges":[{"startOffset":47556,"endOffset":47658,"count":0}],"isBlockCoverage":false},{"functionName":"RuntimeError$","ranges":[{"startOffset":47679,"endOffset":47746,"count":0}],"isBlockCoverage":false},{"functionName":"getIsolateAffinityTag","ranges":[{"startOffset":47775,"endOffset":47838,"count":0}],"isBlockCoverage":false},{"functionName":"setRuntimeTypeInfo","ranges":[{"startOffset":47864,"endOffset":47973,"count":1}],"isBlockCoverage":true},{"functionName":"getRuntimeTypeInfo","ranges":[{"startOffset":47999,"endOffset":48095,"count":0}],"isBlockCoverage":false},{"functionName":"getRuntimeTypeArguments","ranges":[{"startOffset":48126,"endOffset":48282,"count":0}],"isBlockCoverage":false},{"functionName":"runtimeTypeToString","ranges":[{"startOffset":48309,"endOffset":48378,"count":0}],"isBlockCoverage":false},{"functionName":"_runtimeTypeToString","ranges":[{"startOffset":48406,"endOffset":49897,"count":0}],"isBlockCoverage":false},{"functionName":"_functionRtiToString0","ranges":[{"startOffset":49926,"endOffset":52750,"count":0}],"isBlockCoverage":false},{"functionName":"_joinArguments","ranges":[{"startOffset":52772,"endOffset":53457,"count":0}],"isBlockCoverage":false},{"functionName":"getRuntimeType","ranges":[{"startOffset":53479,"endOffset":53665,"count":0}],"isBlockCoverage":false},{"functionName":"substitute","ranges":[{"startOffset":53683,"endOffset":54227,"count":0}],"isBlockCoverage":false},{"functionName":"computeSignature","ranges":[{"startOffset":54251,"endOffset":54444,"count":0}],"isBlockCoverage":false},{"functionName":"invokeOn","ranges":[{"startOffset":54460,"endOffset":54686,"count":0}],"isBlockCoverage":false},{"functionName":"defineProperty","ranges":[{"startOffset":54708,"endOffset":54861,"count":0}],"isBlockCoverage":false},{"functionName":"lookupAndCacheInterceptor","ranges":[{"startOffset":54894,"endOffset":57451,"count":0}],"isBlockCoverage":false},{"functionName":"patchInteriorProto","ranges":[{"startOffset":57477,"endOffset":57764,"count":0}],"isBlockCoverage":false},{"functionName":"makeLeafDispatchRecord","ranges":[{"startOffset":57794,"endOffset":57929,"count":1}],"isBlockCoverage":true},{"functionName":"makeDefaultDispatchRecord","ranges":[{"startOffset":57962,"endOffset":58233,"count":1}],"isBlockCoverage":true},{"functionName":"initNativeDispatch","ranges":[{"startOffset":58259,"endOffset":58415,"count":1},{"startOffset":58325,"endOffset":58332,"count":0}],"isBlockCoverage":true},{"functionName":"initNativeDispatchContinue","ranges":[{"startOffset":58449,"endOffset":59729,"count":1}],"isBlockCoverage":true},{"functionName":"fun","ranges":[{"startOffset":58828,"endOffset":58850,"count":0}],"isBlockCoverage":false},{"functionName":"initHooks","ranges":[{"startOffset":59746,"endOffset":61000,"count":1},{"startOffset":60255,"endOffset":60668,"count":0}],"isBlockCoverage":true},{"functionName":"applyHooksTransformer","ranges":[{"startOffset":61029,"endOffset":61107,"count":1}],"isBlockCoverage":true},{"functionName":"JSSyntaxRegExp_makeNative","ranges":[{"startOffset":61140,"endOffset":61765,"count":0}],"isBlockCoverage":false},{"functionName":"_MatchImplementation$","ranges":[{"startOffset":61794,"endOffset":61977,"count":0}],"isBlockCoverage":false},{"functionName":"stringContainsUnchecked","ranges":[{"startOffset":62008,"endOffset":62496,"count":0}],"isBlockCoverage":false},{"functionName":"escapeReplacement","ranges":[{"startOffset":62521,"endOffset":62671,"count":0}],"isBlockCoverage":false},{"functionName":"stringReplaceFirstRE","ranges":[{"startOffset":62699,"endOffset":62974,"count":0}],"isBlockCoverage":false},{"functionName":"quoteStringForRegExp","ranges":[{"startOffset":63002,"endOffset":63154,"count":0}],"isBlockCoverage":false},{"functionName":"stringReplaceAllUnchecked","ranges":[{"startOffset":63187,"endOffset":63770,"count":0}],"isBlockCoverage":false},{"functionName":"stringReplaceAllUncheckedString","ranges":[{"startOffset":63809,"endOffset":64503,"count":0}],"isBlockCoverage":false},{"functionName":"_stringIdentity","ranges":[{"startOffset":64526,"endOffset":64571,"count":0}],"isBlockCoverage":false},{"functionName":"stringReplaceAllFuncUnchecked","ranges":[{"startOffset":64608,"endOffset":65417,"count":0}],"isBlockCoverage":false},{"functionName":"stringReplaceFirstUnchecked","ranges":[{"startOffset":65452,"endOffset":66440,"count":0}],"isBlockCoverage":false},{"functionName":"stringReplaceRangeUnchecked","ranges":[{"startOffset":66475,"endOffset":66661,"count":0}],"isBlockCoverage":false},{"functionName":"ConstantMap","ranges":[{"startOffset":66680,"endOffset":66710,"count":0}],"isBlockCoverage":false},{"functionName":"ConstantMap_map_closure","ranges":[{"startOffset":66741,"endOffset":66867,"count":0}],"isBlockCoverage":false},{"functionName":"ConstantStringMap","ranges":[{"startOffset":66892,"endOffset":67070,"count":1}],"isBlockCoverage":true},{"functionName":"_ConstantMapKeyIterable","ranges":[{"startOffset":67101,"endOffset":67204,"count":0}],"isBlockCoverage":false},{"functionName":"Instantiation","ranges":[{"startOffset":67225,"endOffset":67257,"count":0}],"isBlockCoverage":false},{"functionName":"Instantiation1","ranges":[{"startOffset":67279,"endOffset":67372,"count":0}],"isBlockCoverage":false},{"functionName":"Primitives_initTicker_closure","ranges":[{"startOffset":67409,"endOffset":67488,"count":0}],"isBlockCoverage":false},{"functionName":"TypeErrorDecoder","ranges":[{"startOffset":67512,"endOffset":67732,"count":0}],"isBlockCoverage":false},{"functionName":"NullError","ranges":[{"startOffset":67749,"endOffset":67846,"count":0}],"isBlockCoverage":false},{"functionName":"JsNoSuchMethodError","ranges":[{"startOffset":67873,"endOffset":68011,"count":0}],"isBlockCoverage":false},{"functionName":"UnknownJsTypeError","ranges":[{"startOffset":68037,"endOffset":68114,"count":0}],"isBlockCoverage":false},{"functionName":"ExceptionAndStackTrace","ranges":[{"startOffset":68144,"endOffset":68250,"count":0}],"isBlockCoverage":true},{"functionName":"unwrapException_saveStackTrace","ranges":[{"startOffset":68288,"endOffset":68359,"count":0}],"isBlockCoverage":false},{"functionName":"_StackTrace","ranges":[{"startOffset":68378,"endOffset":68464,"count":1}],"isBlockCoverage":true},{"functionName":"Closure","ranges":[{"startOffset":68479,"endOffset":68505,"count":0}],"isBlockCoverage":true},{"functionName":"TearOffClosure","ranges":[{"startOffset":68527,"endOffset":68560,"count":0}],"isBlockCoverage":false},{"functionName":"StaticClosure","ranges":[{"startOffset":68581,"endOffset":68613,"count":1}],"isBlockCoverage":true},{"functionName":"BoundClosure","ranges":[{"startOffset":68633,"endOffset":68784,"count":1}],"isBlockCoverage":true},{"functionName":"TypeErrorImplementation","ranges":[{"startOffset":68815,"endOffset":68884,"count":0}],"isBlockCoverage":false},{"functionName":"RuntimeError","ranges":[{"startOffset":68904,"endOffset":68962,"count":0}],"isBlockCoverage":false},{"functionName":"_AssertionError","ranges":[{"startOffset":68985,"endOffset":69046,"count":0}],"isBlockCoverage":false},{"functionName":"JsLinkedHashMap","ranges":[{"startOffset":69069,"endOffset":69306,"count":1}],"isBlockCoverage":true},{"functionName":"JsLinkedHashMap_values_closure","ranges":[{"startOffset":69344,"endOffset":69418,"count":0}],"isBlockCoverage":false},{"functionName":"JsLinkedHashMap_addAll_closure","ranges":[{"startOffset":69456,"endOffset":69530,"count":0}],"isBlockCoverage":false},{"functionName":"LinkedHashMapCell","ranges":[{"startOffset":69555,"endOffset":69713,"count":1}],"isBlockCoverage":true},{"functionName":"LinkedHashMapKeyIterable","ranges":[{"startOffset":69745,"endOffset":69849,"count":1}],"isBlockCoverage":true},{"functionName":"LinkedHashMapKeyIterator","ranges":[{"startOffset":69881,"endOffset":70079,"count":1}],"isBlockCoverage":true},{"functionName":"initHooks_closure","ranges":[{"startOffset":70104,"endOffset":70166,"count":1}],"isBlockCoverage":true},{"functionName":"initHooks_closure0","ranges":[{"startOffset":70192,"endOffset":70262,"count":1}],"isBlockCoverage":true},{"functionName":"initHooks_closure1","ranges":[{"startOffset":70288,"endOffset":70360,"count":1}],"isBlockCoverage":true},{"functionName":"JSSyntaxRegExp","ranges":[{"startOffset":70382,"endOffset":70553,"count":0}],"isBlockCoverage":false},{"functionName":"_MatchImplementation","ranges":[{"startOffset":70581,"endOffset":70646,"count":0}],"isBlockCoverage":false},{"functionName":"_AllMatchesIterable","ranges":[{"startOffset":70673,"endOffset":70803,"count":0}],"isBlockCoverage":false},{"functionName":"_AllMatchesIterator","ranges":[{"startOffset":70830,"endOffset":71016,"count":0}],"isBlockCoverage":false},{"functionName":"StringMatch","ranges":[{"startOffset":71035,"endOffset":71119,"count":0}],"isBlockCoverage":false},{"functionName":"_StringAllMatchesIterable","ranges":[{"startOffset":71152,"endOffset":71292,"count":0}],"isBlockCoverage":false},{"functionName":"_StringAllMatchesIterator","ranges":[{"startOffset":71325,"endOffset":71513,"count":0}],"isBlockCoverage":false},{"functionName":"_ensureNativeList","ranges":[{"startOffset":71538,"endOffset":71579,"count":0}],"isBlockCoverage":false},{"functionName":"NativeInt8List__create1","ranges":[{"startOffset":71610,"endOffset":71664,"count":0}],"isBlockCoverage":false},{"functionName":"_checkValidIndex","ranges":[{"startOffset":71688,"endOffset":71845,"count":1},{"startOffset":71782,"endOffset":71839,"count":0}],"isBlockCoverage":true},{"functionName":"_checkValidRange","ranges":[{"startOffset":71869,"endOffset":72275,"count":0}],"isBlockCoverage":false},{"functionName":"NativeByteBuffer","ranges":[{"startOffset":72299,"endOffset":72334,"count":0}],"isBlockCoverage":false},{"functionName":"NativeTypedData","ranges":[{"startOffset":72357,"endOffset":72391,"count":0}],"isBlockCoverage":false},{"functionName":"NativeByteData","ranges":[{"startOffset":72413,"endOffset":72446,"count":0}],"isBlockCoverage":false},{"functionName":"NativeTypedArray","ranges":[{"startOffset":72470,"endOffset":72505,"count":0}],"isBlockCoverage":false},{"functionName":"NativeTypedArrayOfDouble","ranges":[{"startOffset":72537,"endOffset":72580,"count":0}],"isBlockCoverage":false},{"functionName":"NativeTypedArrayOfInt","ranges":[{"startOffset":72609,"endOffset":72649,"count":0}],"isBlockCoverage":false},{"functionName":"NativeFloat32List","ranges":[{"startOffset":72674,"endOffset":72710,"count":0}],"isBlockCoverage":false},{"functionName":"NativeFloat64List","ranges":[{"startOffset":72735,"endOffset":72771,"count":0}],"isBlockCoverage":false},{"functionName":"NativeInt16List","ranges":[{"startOffset":72794,"endOffset":72828,"count":0}],"isBlockCoverage":false},{"functionName":"NativeInt32List","ranges":[{"startOffset":72851,"endOffset":72885,"count":0}],"isBlockCoverage":false},{"functionName":"NativeInt8List","ranges":[{"startOffset":72907,"endOffset":72940,"count":0}],"isBlockCoverage":false},{"functionName":"NativeUint16List","ranges":[{"startOffset":72964,"endOffset":72999,"count":0}],"isBlockCoverage":false},{"functionName":"NativeUint32List","ranges":[{"startOffset":73023,"endOffset":73058,"count":0}],"isBlockCoverage":false},{"functionName":"NativeUint8ClampedList","ranges":[{"startOffset":73088,"endOffset":73129,"count":0}],"isBlockCoverage":false},{"functionName":"NativeUint8List","ranges":[{"startOffset":73152,"endOffset":73186,"count":0}],"isBlockCoverage":false},{"functionName":"_NativeTypedArrayOfDouble_NativeTypedArray_ListMixin","ranges":[{"startOffset":73246,"endOffset":73317,"count":0}],"isBlockCoverage":false},{"functionName":"_NativeTypedArrayOfDouble_NativeTypedArray_ListMixin_FixedLengthListMixin","ranges":[{"startOffset":73398,"endOffset":73490,"count":0}],"isBlockCoverage":false},{"functionName":"_NativeTypedArrayOfInt_NativeTypedArray_ListMixin","ranges":[{"startOffset":73547,"endOffset":73615,"count":0}],"isBlockCoverage":false},{"functionName":"_NativeTypedArrayOfInt_NativeTypedArray_ListMixin_FixedLengthListMixin","ranges":[{"startOffset":73693,"endOffset":73782,"count":0}],"isBlockCoverage":false},{"functionName":"Rti__getFutureFromFutureOr","ranges":[{"startOffset":73816,"endOffset":74142,"count":0}],"isBlockCoverage":false},{"functionName":"Rti__isUnionOfFunctionType","ranges":[{"startOffset":74176,"endOffset":74375,"count":1}],"isBlockCoverage":true},{"functionName":"Rti__getInterfaceTypeArguments","ranges":[{"startOffset":74413,"endOffset":74497,"count":1}],"isBlockCoverage":true},{"functionName":"Rti__getBindingArguments","ranges":[{"startOffset":74529,"endOffset":74614,"count":1}],"isBlockCoverage":true},{"functionName":"Rti__getFunctionParameters","ranges":[{"startOffset":74648,"endOffset":74733,"count":1}],"isBlockCoverage":true},{"functionName":"Rti__getGenericFunctionBounds","ranges":[{"startOffset":74770,"endOffset":74855,"count":1}],"isBlockCoverage":true},{"functionName":"Rti__getCanonicalRecipe","ranges":[{"startOffset":74886,"endOffset":75056,"count":0}],"isBlockCoverage":false},{"functionName":"findType","ranges":[{"startOffset":75072,"endOffset":75154,"count":1}],"isBlockCoverage":true},{"functionName":"instantiatedGenericFunctionType","ranges":[{"startOffset":75193,"endOffset":76127,"count":0}],"isBlockCoverage":false},{"functionName":"_instantiate","ranges":[{"startOffset":76147,"endOffset":80529,"count":0}],"isBlockCoverage":false},{"functionName":"_instantiateArray","ranges":[{"startOffset":80554,"endOffset":81024,"count":0}],"isBlockCoverage":false},{"functionName":"_instantiateNamed","ranges":[{"startOffset":81049,"endOffset":81640,"count":0}],"isBlockCoverage":false},{"functionName":"_instantiateFunctionParameters","ranges":[{"startOffset":81678,"endOffset":82753,"count":0}],"isBlockCoverage":false},{"functionName":"closureFunctionType","ranges":[{"startOffset":82780,"endOffset":83037,"count":1},{"startOffset":83012,"endOffset":83036,"count":0}],"isBlockCoverage":true},{"functionName":"instanceOrFunctionType","ranges":[{"startOffset":83067,"endOffset":83352,"count":1}],"isBlockCoverage":true},{"functionName":"instanceType","ranges":[{"startOffset":83372,"endOffset":83710,"count":1},{"startOffset":83505,"endOffset":83545,"count":0}],"isBlockCoverage":true},{"functionName":"_arrayInstanceType","ranges":[{"startOffset":83736,"endOffset":83981,"count":1},{"startOffset":83939,"endOffset":83957,"count":0}],"isBlockCoverage":true},{"functionName":"_instanceType","ranges":[{"startOffset":84002,"endOffset":84127,"count":1},{"startOffset":84080,"endOffset":84120,"count":0}],"isBlockCoverage":true},{"functionName":"_instanceTypeFromConstructor","ranges":[{"startOffset":84163,"endOffset":84394,"count":1}],"isBlockCoverage":true},{"functionName":"_instanceTypeFromConstructorMiss","ranges":[{"startOffset":84434,"endOffset":84736,"count":1},{"startOffset":84532,"endOffset":84574,"count":0}],"isBlockCoverage":true},{"functionName":"getTypeFromTypesTable","ranges":[{"startOffset":84765,"endOffset":85054,"count":1}],"isBlockCoverage":true},{"functionName":"createRuntimeType","ranges":[{"startOffset":85079,"endOffset":85242,"count":1},{"startOffset":85168,"endOffset":85180,"count":0}],"isBlockCoverage":true},{"functionName":"typeLiteral","ranges":[{"startOffset":85261,"endOffset":85364,"count":1}],"isBlockCoverage":true},{"functionName":"_installSpecializedIsTest","ranges":[{"startOffset":85397,"endOffset":86499,"count":1},{"startOffset":85764,"endOffset":85806,"count":0},{"startOffset":85923,"endOffset":85939,"count":0}],"isBlockCoverage":true},{"functionName":"_generalIsTestImplementation","ranges":[{"startOffset":86535,"endOffset":86701,"count":1}],"isBlockCoverage":true},{"functionName":"_isTestViaProperty","ranges":[{"startOffset":86727,"endOffset":86913,"count":1}],"isBlockCoverage":true},{"functionName":"_generalAsCheckImplementation","ranges":[{"startOffset":86950,"endOffset":87273,"count":1},{"startOffset":87022,"endOffset":87036,"count":0},{"startOffset":87112,"endOffset":87272,"count":0}],"isBlockCoverage":true},{"functionName":"_generalTypeCheckImplementation","ranges":[{"startOffset":87312,"endOffset":87635,"count":1},{"startOffset":87474,"endOffset":87634,"count":0}],"isBlockCoverage":true},{"functionName":"checkTypeBound","ranges":[{"startOffset":87657,"endOffset":88102,"count":0}],"isBlockCoverage":false},{"functionName":"_Error_compose","ranges":[{"startOffset":88124,"endOffset":88496,"count":0}],"isBlockCoverage":false},{"functionName":"_CastError$fromMessage","ranges":[{"startOffset":88526,"endOffset":88607,"count":0}],"isBlockCoverage":false},{"functionName":"_CastError__CastError$forType","ranges":[{"startOffset":88644,"endOffset":88759,"count":0}],"isBlockCoverage":false},{"functionName":"_TypeError$fromMessage","ranges":[{"startOffset":88789,"endOffset":88870,"count":0}],"isBlockCoverage":false},{"functionName":"_TypeError__TypeError$forType","ranges":[{"startOffset":88907,"endOffset":89022,"count":0}],"isBlockCoverage":false},{"functionName":"_isTop","ranges":[{"startOffset":89036,"endOffset":89079,"count":1}],"isBlockCoverage":true},{"functionName":"_asTop","ranges":[{"startOffset":89093,"endOffset":89138,"count":1}],"isBlockCoverage":true},{"functionName":"_isBool","ranges":[{"startOffset":89153,"endOffset":89227,"count":1}],"isBlockCoverage":true},{"functionName":"_asBoolNullable","ranges":[{"startOffset":89250,"endOffset":89471,"count":1},{"startOffset":89387,"endOffset":89470,"count":0}],"isBlockCoverage":true},{"functionName":"_checkBoolNullable","ranges":[{"startOffset":89497,"endOffset":89718,"count":1},{"startOffset":89634,"endOffset":89717,"count":0}],"isBlockCoverage":true},{"functionName":"_asDoubleNullable","ranges":[{"startOffset":89743,"endOffset":89956,"count":0}],"isBlockCoverage":false},{"functionName":"_checkDoubleNullable","ranges":[{"startOffset":89984,"endOffset":90197,"count":0}],"isBlockCoverage":false},{"functionName":"_isInt","ranges":[{"startOffset":90211,"endOffset":90308,"count":1}],"isBlockCoverage":true},{"functionName":"_asIntNullable","ranges":[{"startOffset":90330,"endOffset":90573,"count":1},{"startOffset":90490,"endOffset":90572,"count":0}],"isBlockCoverage":true},{"functionName":"_checkIntNullable","ranges":[{"startOffset":90598,"endOffset":90841,"count":1},{"startOffset":90709,"endOffset":90840,"count":0}],"isBlockCoverage":true},{"functionName":"_isNum","ranges":[{"startOffset":90855,"endOffset":90919,"count":1}],"isBlockCoverage":true},{"functionName":"_asNumNullable","ranges":[{"startOffset":90941,"endOffset":91151,"count":1},{"startOffset":91019,"endOffset":91150,"count":0}],"isBlockCoverage":true},{"functionName":"_checkNumNullable","ranges":[{"startOffset":91176,"endOffset":91386,"count":0}],"isBlockCoverage":false},{"functionName":"_isString","ranges":[{"startOffset":91403,"endOffset":91467,"count":1}],"isBlockCoverage":true},{"functionName":"_asStringNullable","ranges":[{"startOffset":91492,"endOffset":91705,"count":1},{"startOffset":91619,"endOffset":91704,"count":0}],"isBlockCoverage":true},{"functionName":"_checkStringNullable","ranges":[{"startOffset":91733,"endOffset":91946,"count":1},{"startOffset":91811,"endOffset":91945,"count":0}],"isBlockCoverage":true},{"functionName":"_rtiArrayToString","ranges":[{"startOffset":91971,"endOffset":92203,"count":0}],"isBlockCoverage":false},{"functionName":"_functionRtiToString","ranges":[{"startOffset":92231,"endOffset":95348,"count":0}],"isBlockCoverage":false},{"functionName":"_rtiToString","ranges":[{"startOffset":95368,"endOffset":96985,"count":0}],"isBlockCoverage":false},{"functionName":"_unminifyOrTag","ranges":[{"startOffset":97007,"endOffset":97195,"count":0}],"isBlockCoverage":false},{"functionName":"_Universe_findRule","ranges":[{"startOffset":97221,"endOffset":97393,"count":1},{"startOffset":97343,"endOffset":97368,"count":0}],"isBlockCoverage":true},{"functionName":"_Universe_findErasedType","ranges":[{"startOffset":97425,"endOffset":98058,"count":1},{"startOffset":97640,"endOffset":98052,"count":0}],"isBlockCoverage":true},{"functionName":"_Universe_addRules","ranges":[{"startOffset":98084,"endOffset":98173,"count":1}],"isBlockCoverage":true},{"functionName":"_Universe_addErasedTypes","ranges":[{"startOffset":98205,"endOffset":98294,"count":1}],"isBlockCoverage":true},{"functionName":"_Universe_eval","ranges":[{"startOffset":98316,"endOffset":98586,"count":1}],"isBlockCoverage":true},{"functionName":"_Universe_evalInEnvironment","ranges":[{"startOffset":98621,"endOffset":99004,"count":1}],"isBlockCoverage":true},{"functionName":"_Universe_bind","ranges":[{"startOffset":99026,"endOffset":99702,"count":1},{"startOffset":99328,"endOffset":99370,"count":0},{"startOffset":99578,"endOffset":99620,"count":0}],"isBlockCoverage":true},{"functionName":"_Universe__parseRecipe","ranges":[{"startOffset":99732,"endOffset":99879,"count":1}],"isBlockCoverage":true},{"functionName":"_Universe__finishRti","ranges":[{"startOffset":99907,"endOffset":100268,"count":1},{"startOffset":100023,"endOffset":100065,"count":0}],"isBlockCoverage":true},{"functionName":"_Universe__lookupTerminalRti","ranges":[{"startOffset":100304,"endOffset":100628,"count":1}],"isBlockCoverage":true},{"functionName":"_Universe__lookupUnaryRti","ranges":[{"startOffset":100661,"endOffset":101026,"count":1}],"isBlockCoverage":true},{"functionName":"_Universe__lookupGenericFunctionParameterRti","ranges":[{"startOffset":101078,"endOffset":101456,"count":1}],"isBlockCoverage":true},{"functionName":"_Universe__canonicalRecipeJoin","ranges":[{"startOffset":101494,"endOffset":101845,"count":1},{"startOffset":101750,"endOffset":101792,"count":0}],"isBlockCoverage":true},{"functionName":"_Universe__canonicalRecipeJoinNamed","ranges":[{"startOffset":101888,"endOffset":102332,"count":0}],"isBlockCoverage":false},{"functionName":"_Universe__lookupInterfaceRti","ranges":[{"startOffset":102369,"endOffset":102971,"count":1}],"isBlockCoverage":true},{"functionName":"_Universe__lookupBindingRti","ranges":[{"startOffset":103006,"endOffset":103877,"count":1},{"startOffset":103457,"endOffset":103499,"count":0}],"isBlockCoverage":true},{"functionName":"_Universe__lookupFunctionRti","ranges":[{"startOffset":103913,"endOffset":105417,"count":1},{"startOffset":104216,"endOffset":104258,"count":0},{"startOffset":104965,"endOffset":105084,"count":0}],"isBlockCoverage":true},{"functionName":"_Universe__lookupGenericFunctionRti","ranges":[{"startOffset":105460,"endOffset":106050,"count":1},{"startOffset":105635,"endOffset":105677,"count":0},{"startOffset":105817,"endOffset":105830,"count":0}],"isBlockCoverage":true},{"functionName":"_Parser_create","ranges":[{"startOffset":106072,"endOffset":106187,"count":1}],"isBlockCoverage":true},{"functionName":"_Parser_parse","ranges":[{"startOffset":106208,"endOffset":111999,"count":1},{"startOffset":106817,"endOffset":106880,"count":0},{"startOffset":106989,"endOffset":107018,"count":0},{"startOffset":107031,"endOffset":107137,"count":0},{"startOffset":107388,"endOffset":107493,"count":0},{"startOffset":108690,"endOffset":108784,"count":0},{"startOffset":108797,"endOffset":109122,"count":0},{"startOffset":109135,"endOffset":109460,"count":0},{"startOffset":109682,"endOffset":109703,"count":0},{"startOffset":110356,"endOffset":110440,"count":0},{"startOffset":111456,"endOffset":111561,"count":0},{"startOffset":111574,"endOffset":111816,"count":0},{"startOffset":111829,"endOffset":111880,"count":0}],"isBlockCoverage":true},{"functionName":"_Parser_handleDigit","ranges":[{"startOffset":112026,"endOffset":112337,"count":1},{"startOffset":112242,"endOffset":112290,"count":0}],"isBlockCoverage":true},{"functionName":"_Parser_handleIdentifier","ranges":[{"startOffset":112369,"endOffset":113633,"count":1},{"startOffset":112644,"endOffset":112650,"count":0},{"startOffset":113401,"endOffset":113494,"count":0}],"isBlockCoverage":true},{"functionName":"_Parser_handleExtendedOperations","ranges":[{"startOffset":113673,"endOffset":114066,"count":0}],"isBlockCoverage":false},{"functionName":"_Parser_toType","ranges":[{"startOffset":114088,"endOffset":114385,"count":1}],"isBlockCoverage":true},{"functionName":"_Parser_toTypes","ranges":[{"startOffset":114408,"endOffset":114605,"count":1}],"isBlockCoverage":true},{"functionName":"_Parser_toTypesNamed","ranges":[{"startOffset":114633,"endOffset":114876,"count":0}],"isBlockCoverage":false},{"functionName":"_Parser_indexToType","ranges":[{"startOffset":114903,"endOffset":115904,"count":1},{"startOffset":115075,"endOffset":115162,"count":0},{"startOffset":115556,"endOffset":115639,"count":0},{"startOffset":115790,"endOffset":115903,"count":0}],"isBlockCoverage":true},{"functionName":"_isSubtype","ranges":[{"startOffset":115922,"endOffset":118887,"count":1},{"startOffset":116182,"endOffset":116194,"count":0},{"startOffset":116235,"endOffset":116248,"count":0},{"startOffset":116365,"endOffset":116512,"count":0},{"startOffset":116574,"endOffset":116694,"count":0},{"startOffset":116718,"endOffset":116850,"count":0},{"startOffset":116874,"endOffset":117119,"count":0},{"startOffset":117143,"endOffset":117280,"count":0},{"startOffset":117431,"endOffset":117542,"count":0},{"startOffset":117566,"endOffset":117698,"count":0},{"startOffset":117735,"endOffset":117748,"count":0},{"startOffset":117932,"endOffset":117944,"count":0},{"startOffset":117981,"endOffset":117994,"count":0},{"startOffset":118164,"endOffset":118177,"count":0},{"startOffset":118216,"endOffset":118238,"count":0},{"startOffset":118278,"endOffset":118300,"count":0},{"startOffset":118576,"endOffset":118588,"count":0},{"startOffset":118615,"endOffset":118628,"count":0},{"startOffset":118768,"endOffset":118781,"count":0},{"startOffset":118861,"endOffset":118886,"count":0}],"isBlockCoverage":true},{"functionName":"_isFunctionSubtype","ranges":[{"startOffset":118913,"endOffset":121867,"count":1},{"startOffset":119567,"endOffset":119580,"count":0},{"startOffset":120006,"endOffset":120019,"count":0},{"startOffset":120482,"endOffset":120495,"count":0},{"startOffset":120682,"endOffset":120695,"count":0},{"startOffset":120916,"endOffset":120929,"count":0},{"startOffset":120992,"endOffset":121171,"count":0},{"startOffset":121437,"endOffset":121842,"count":0}],"isBlockCoverage":true},{"functionName":"_isInterfaceSubtype","ranges":[{"startOffset":121894,"endOffset":123121,"count":1},{"startOffset":122175,"endOffset":122584,"count":0},{"startOffset":122669,"endOffset":122682,"count":0},{"startOffset":123083,"endOffset":123096,"count":0}],"isBlockCoverage":true},{"functionName":"typeEqual","ranges":[{"startOffset":123138,"endOffset":124947,"count":1},{"startOffset":123229,"endOffset":123426,"count":0},{"startOffset":123435,"endOffset":123442,"count":0},{"startOffset":123451,"endOffset":123518,"count":0},{"startOffset":123527,"endOffset":123808,"count":0},{"startOffset":123817,"endOffset":124067,"count":0},{"startOffset":124076,"endOffset":124623,"count":0},{"startOffset":124632,"endOffset":124892,"count":0},{"startOffset":124901,"endOffset":124933,"count":0}],"isBlockCoverage":true},{"functionName":"typesEqual","ranges":[{"startOffset":124965,"endOffset":125245,"count":1},{"startOffset":125093,"endOffset":125106,"count":0},{"startOffset":125207,"endOffset":125220,"count":0}],"isBlockCoverage":true},{"functionName":"namedTypesEqual","ranges":[{"startOffset":125268,"endOffset":125761,"count":0}],"isBlockCoverage":false},{"functionName":"isLegacyTopType","ranges":[{"startOffset":125784,"endOffset":125838,"count":1}],"isBlockCoverage":true},{"functionName":"isTopType","ranges":[{"startOffset":125855,"endOffset":126428,"count":1},{"startOffset":126261,"endOffset":126341,"count":0}],"isBlockCoverage":true},{"functionName":"_Utils_objectAssign","ranges":[{"startOffset":126455,"endOffset":126663,"count":1}],"isBlockCoverage":true},{"functionName":"Rti","ranges":[{"startOffset":126674,"endOffset":126970,"count":1}],"isBlockCoverage":true},{"functionName":"_FunctionParameters","ranges":[{"startOffset":126997,"endOffset":127123,"count":1}],"isBlockCoverage":true},{"functionName":"_Type","ranges":[{"startOffset":127136,"endOffset":127213,"count":1}],"isBlockCoverage":true},{"functionName":"_Error","ranges":[{"startOffset":127227,"endOffset":127252,"count":0}],"isBlockCoverage":false},{"functionName":"_CastError","ranges":[{"startOffset":127270,"endOffset":127327,"count":0}],"isBlockCoverage":false},{"functionName":"_TypeError","ranges":[{"startOffset":127345,"endOffset":127402,"count":0}],"isBlockCoverage":false},{"functionName":"extractKeys","ranges":[{"startOffset":127421,"endOffset":127537,"count":0}],"isBlockCoverage":false},{"functionName":"unmangleGlobalNameIfPreservedAnyways","ranges":[{"startOffset":127581,"endOffset":127649,"count":0}],"isBlockCoverage":false},{"functionName":"printString","ranges":[{"startOffset":127668,"endOffset":128115,"count":0}],"isBlockCoverage":false},{"functionName":"makeDispatchRecord","ranges":[{"startOffset":128153,"endOffset":128286,"count":1}],"isBlockCoverage":true},{"functionName":"getNativeInterceptor","ranges":[{"startOffset":128314,"endOffset":129994,"count":1},{"startOffset":128762,"endOffset":128776,"count":0},{"startOffset":128891,"endOffset":129041,"count":0},{"startOffset":129049,"endOffset":129138,"count":0},{"startOffset":129139,"endOffset":129190,"count":0},{"startOffset":129231,"endOffset":129993,"count":0}],"isBlockCoverage":true},{"functionName":"JSArray_JSArray$fixed","ranges":[{"startOffset":130023,"endOffset":130380,"count":0}],"isBlockCoverage":false},{"functionName":"JSArray_JSArray$markFixed","ranges":[{"startOffset":130413,"endOffset":130543,"count":0}],"isBlockCoverage":false},{"functionName":"JSArray_markFixedList","ranges":[{"startOffset":130572,"endOffset":130646,"count":1}],"isBlockCoverage":true},{"functionName":"JSString__isWhitespace","ranges":[{"startOffset":130676,"endOffset":131431,"count":0}],"isBlockCoverage":false},{"functionName":"JSString__skipLeadingWhitespace","ranges":[{"startOffset":131470,"endOffset":131788,"count":0}],"isBlockCoverage":false},{"functionName":"JSString__skipTrailingWhitespace","ranges":[{"startOffset":131828,"endOffset":132157,"count":0}],"isBlockCoverage":false},{"functionName":"getInterceptor$","ranges":[{"startOffset":132180,"endOffset":132943,"count":1},{"startOffset":132240,"endOffset":132368,"count":0},{"startOffset":132699,"endOffset":132825,"count":0}],"isBlockCoverage":true},{"functionName":"getInterceptor$ansx","ranges":[{"startOffset":132970,"endOffset":133556,"count":0}],"isBlockCoverage":false},{"functionName":"getInterceptor$asx","ranges":[{"startOffset":133582,"endOffset":134092,"count":1},{"startOffset":133715,"endOffset":133731,"count":0},{"startOffset":133848,"endOffset":133974,"count":0},{"startOffset":134039,"endOffset":134091,"count":0}],"isBlockCoverage":true},{"functionName":"getInterceptor$ax","ranges":[{"startOffset":134117,"endOffset":134551,"count":1},{"startOffset":134174,"endOffset":134190,"count":0},{"startOffset":134307,"endOffset":134433,"count":0}],"isBlockCoverage":true},{"functionName":"getInterceptor$n","ranges":[{"startOffset":134575,"endOffset":134848,"count":0}],"isBlockCoverage":false},{"functionName":"getInterceptor$s","ranges":[{"startOffset":134872,"endOffset":135145,"count":1},{"startOffset":134968,"endOffset":135144,"count":0}],"isBlockCoverage":true},{"functionName":"getInterceptor$x","ranges":[{"startOffset":135169,"endOffset":135526,"count":1},{"startOffset":135226,"endOffset":135242,"count":0},{"startOffset":135282,"endOffset":135408,"count":0},{"startOffset":135457,"endOffset":135473,"count":0}],"isBlockCoverage":true},{"functionName":"get$first$ax","ranges":[{"startOffset":135546,"endOffset":135636,"count":1}],"isBlockCoverage":true},{"functionName":"get$hashCode$","ranges":[{"startOffset":135657,"endOffset":135748,"count":1}],"isBlockCoverage":true},{"functionName":"get$isEmpty$asx","ranges":[{"startOffset":135771,"endOffset":135864,"count":1}],"isBlockCoverage":true},{"functionName":"get$iterator$ax","ranges":[{"startOffset":135887,"endOffset":135980,"count":1}],"isBlockCoverage":true},{"functionName":"get$last$ax","ranges":[{"startOffset":135999,"endOffset":136088,"count":0}],"isBlockCoverage":false},{"functionName":"get$length$asx","ranges":[{"startOffset":136110,"endOffset":136202,"count":1}],"isBlockCoverage":true},{"functionName":"get$message$x","ranges":[{"startOffset":136223,"endOffset":136314,"count":0}],"isBlockCoverage":false},{"functionName":"get$runtimeType$","ranges":[{"startOffset":136338,"endOffset":136432,"count":0}],"isBlockCoverage":false},{"functionName":"get$startsWith$s","ranges":[{"startOffset":136456,"endOffset":136550,"count":0}],"isBlockCoverage":false},{"functionName":"$add$ansx","ranges":[{"startOffset":136567,"endOffset":136756,"count":0}],"isBlockCoverage":false},{"functionName":"$eq$","ranges":[{"startOffset":136768,"endOffset":136998,"count":1}],"isBlockCoverage":true},{"functionName":"$index$asx","ranges":[{"startOffset":137016,"endOffset":137374,"count":0}],"isBlockCoverage":false},{"functionName":"$indexSet$ax","ranges":[{"startOffset":137394,"endOffset":137500,"count":1}],"isBlockCoverage":true},{"functionName":"_codeUnitAt$1$s","ranges":[{"startOffset":137523,"endOffset":137624,"count":1}],"isBlockCoverage":true},{"functionName":"_removeEventListener$3$x","ranges":[{"startOffset":137656,"endOffset":137782,"count":1}],"isBlockCoverage":true},{"functionName":"addEventListener$3$x","ranges":[{"startOffset":137810,"endOffset":137932,"count":1}],"isBlockCoverage":true},{"functionName":"allMatches$1$s","ranges":[{"startOffset":137954,"endOffset":138054,"count":0}],"isBlockCoverage":false},{"functionName":"allMatches$2$s","ranges":[{"startOffset":138076,"endOffset":138184,"count":0}],"isBlockCoverage":false},{"functionName":"codeUnitAt$1$s","ranges":[{"startOffset":138206,"endOffset":138306,"count":0}],"isBlockCoverage":false},{"functionName":"contains$1$asx","ranges":[{"startOffset":138328,"endOffset":138428,"count":0}],"isBlockCoverage":false},{"functionName":"elementAt$1$ax","ranges":[{"startOffset":138450,"endOffset":138550,"count":1}],"isBlockCoverage":true},{"functionName":"endsWith$1$s","ranges":[{"startOffset":138570,"endOffset":138668,"count":0}],"isBlockCoverage":false},{"functionName":"fillRange$3$ax","ranges":[{"startOffset":138690,"endOffset":138806,"count":1}],"isBlockCoverage":true},{"functionName":"map$1$1$ax","ranges":[{"startOffset":138824,"endOffset":138930,"count":0}],"isBlockCoverage":false},{"functionName":"matchAsPrefix$2$s","ranges":[{"startOffset":138955,"endOffset":139066,"count":0}],"isBlockCoverage":false},{"functionName":"padRight$1$s","ranges":[{"startOffset":139086,"endOffset":139184,"count":0}],"isBlockCoverage":false},{"functionName":"replaceRange$3$asx","ranges":[{"startOffset":139210,"endOffset":139330,"count":0}],"isBlockCoverage":false},{"functionName":"startsWith$1$s","ranges":[{"startOffset":139352,"endOffset":139452,"count":0}],"isBlockCoverage":false},{"functionName":"startsWith$2$s","ranges":[{"startOffset":139474,"endOffset":139582,"count":1}],"isBlockCoverage":true},{"functionName":"substring$1$s","ranges":[{"startOffset":139603,"endOffset":139702,"count":0}],"isBlockCoverage":false},{"functionName":"substring$2$s","ranges":[{"startOffset":139723,"endOffset":139830,"count":0}],"isBlockCoverage":false},{"functionName":"toRadixString$1$n","ranges":[{"startOffset":139855,"endOffset":139958,"count":0}],"isBlockCoverage":false},{"functionName":"toSet$0$ax","ranges":[{"startOffset":139976,"endOffset":140064,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0$","ranges":[{"startOffset":140083,"endOffset":140172,"count":0}],"isBlockCoverage":false},{"functionName":"trim$0$s","ranges":[{"startOffset":140188,"endOffset":140274,"count":0}],"isBlockCoverage":false},{"functionName":"Interceptor","ranges":[{"startOffset":140293,"endOffset":140323,"count":0}],"isBlockCoverage":false},{"functionName":"JSBool","ranges":[{"startOffset":140337,"endOffset":140362,"count":0}],"isBlockCoverage":false},{"functionName":"JSNull","ranges":[{"startOffset":140376,"endOffset":140401,"count":0}],"isBlockCoverage":false},{"functionName":"JSObject","ranges":[{"startOffset":140417,"endOffset":140444,"count":0}],"isBlockCoverage":false},{"functionName":"JavaScriptObject","ranges":[{"startOffset":140468,"endOffset":140503,"count":0}],"isBlockCoverage":false},{"functionName":"PlainJavaScriptObject","ranges":[{"startOffset":140532,"endOffset":140572,"count":0}],"isBlockCoverage":false},{"functionName":"UnknownJavaScriptObject","ranges":[{"startOffset":140603,"endOffset":140645,"count":0}],"isBlockCoverage":false},{"functionName":"JavaScriptFunction","ranges":[{"startOffset":140671,"endOffset":140708,"count":0}],"isBlockCoverage":false},{"functionName":"JSArray","ranges":[{"startOffset":140723,"endOffset":140772,"count":0}],"isBlockCoverage":true},{"functionName":"JSUnmodifiableArray","ranges":[{"startOffset":140799,"endOffset":140860,"count":0}],"isBlockCoverage":false},{"functionName":"ArrayIterator","ranges":[{"startOffset":140881,"endOffset":141052,"count":1}],"isBlockCoverage":true},{"functionName":"JSNumber","ranges":[{"startOffset":141068,"endOffset":141095,"count":0}],"isBlockCoverage":false},{"functionName":"JSInt","ranges":[{"startOffset":141108,"endOffset":141132,"count":0}],"isBlockCoverage":false},{"functionName":"JSDouble","ranges":[{"startOffset":141148,"endOffset":141175,"count":0}],"isBlockCoverage":false},{"functionName":"JSString","ranges":[{"startOffset":141191,"endOffset":141218,"count":0}],"isBlockCoverage":true},{"functionName":"_AsyncRun__initializeScheduleImmediate","ranges":[{"startOffset":141276,"endOffset":142083,"count":1},{"startOffset":141369,"endOffset":141433,"count":0},{"startOffset":141892,"endOffset":142082,"count":0}],"isBlockCoverage":true},{"functionName":"_AsyncRun__scheduleImmediateJsOverride","ranges":[{"startOffset":142129,"endOffset":142315,"count":0}],"isBlockCoverage":false},{"functionName":"_AsyncRun__scheduleImmediateWithSetImmediate","ranges":[{"startOffset":142367,"endOffset":142554,"count":0}],"isBlockCoverage":false},{"functionName":"_AsyncRun__scheduleImmediateWithTimer","ranges":[{"startOffset":142599,"endOffset":142705,"count":0}],"isBlockCoverage":false},{"functionName":"Timer__createTimer","ranges":[{"startOffset":142731,"endOffset":142922,"count":1},{"startOffset":142886,"endOffset":142889,"count":0}],"isBlockCoverage":true},{"functionName":"_TimerImpl$","ranges":[{"startOffset":142941,"endOffset":143084,"count":1}],"isBlockCoverage":true},{"functionName":"_TimerImpl$periodic","ranges":[{"startOffset":143111,"endOffset":143264,"count":0}],"isBlockCoverage":false},{"functionName":"_makeAsyncAwaitCompleter","ranges":[{"startOffset":143296,"endOffset":143454,"count":1}],"isBlockCoverage":true},{"functionName":"_asyncStartSync","ranges":[{"startOffset":143477,"endOffset":143617,"count":1}],"isBlockCoverage":true},{"functionName":"_asyncAwait","ranges":[{"startOffset":143636,"endOffset":143720,"count":1}],"isBlockCoverage":true},{"functionName":"_asyncReturn","ranges":[{"startOffset":143740,"endOffset":143811,"count":1}],"isBlockCoverage":true},{"functionName":"_asyncRethrow","ranges":[{"startOffset":143832,"endOffset":143960,"count":0}],"isBlockCoverage":false},{"functionName":"_awaitOnObject","ranges":[{"startOffset":143982,"endOffset":144686,"count":1},{"startOffset":144384,"endOffset":144441,"count":0}],"isBlockCoverage":true},{"functionName":"_wrapJsFunctionForAsync","ranges":[{"startOffset":144717,"endOffset":145220,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":144762,"endOffset":145053,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":144799,"endOffset":145044,"count":1},{"startOffset":144941,"endOffset":145034,"count":0}],"isBlockCoverage":true},{"functionName":"Future_Future","ranges":[{"startOffset":145241,"endOffset":145457,"count":1}],"isBlockCoverage":true},{"functionName":"Future_Future$microtask","ranges":[{"startOffset":145488,"endOffset":145706,"count":0}],"isBlockCoverage":false},{"functionName":"Future_Future$sync","ranges":[{"startOffset":145732,"endOffset":146777,"count":1},{"startOffset":145947,"endOffset":145961,"count":0},{"startOffset":146185,"endOffset":146771,"count":0}],"isBlockCoverage":true},{"functionName":"Future_Future$error","ranges":[{"startOffset":146804,"endOffset":147339,"count":0}],"isBlockCoverage":false},{"functionName":"Future_wait","ranges":[{"startOffset":147358,"endOffset":148702,"count":0}],"isBlockCoverage":false},{"functionName":"Future_forEach","ranges":[{"startOffset":148724,"endOffset":148925,"count":1}],"isBlockCoverage":true},{"functionName":"Future__kTrue","ranges":[{"startOffset":148946,"endOffset":148984,"count":0}],"isBlockCoverage":false},{"functionName":"Future_doWhile","ranges":[{"startOffset":149006,"endOffset":149408,"count":1}],"isBlockCoverage":true},{"functionName":"_completeWithErrorCallback","ranges":[{"startOffset":149442,"endOffset":149802,"count":0}],"isBlockCoverage":false},{"functionName":"_Future$zoneValue","ranges":[{"startOffset":149827,"endOffset":150023,"count":1}],"isBlockCoverage":true},{"functionName":"_Future__chainForeignFuture","ranges":[{"startOffset":150058,"endOffset":150653,"count":0}],"isBlockCoverage":false},{"functionName":"_Future__chainCoreFuture","ranges":[{"startOffset":150685,"endOffset":151411,"count":1},{"startOffset":150866,"endOffset":150958,"count":0},{"startOffset":150978,"endOffset":151135,"count":0}],"isBlockCoverage":true},{"functionName":"_Future__propagateToListeners","ranges":[{"startOffset":151448,"endOffset":155442,"count":1},{"startOffset":151952,"endOffset":152109,"count":0},{"startOffset":152235,"endOffset":152357,"count":0},{"startOffset":152661,"endOffset":152687,"count":0},{"startOffset":152790,"endOffset":152910,"count":0},{"startOffset":152958,"endOffset":153223,"count":0},{"startOffset":153845,"endOffset":153967,"count":0},{"startOffset":154108,"endOffset":154697,"count":0},{"startOffset":155231,"endOffset":155375,"count":0}],"isBlockCoverage":true},{"functionName":"_registerErrorHandler","ranges":[{"startOffset":155471,"endOffset":156025,"count":0}],"isBlockCoverage":false},{"functionName":"_microtaskLoop","ranges":[{"startOffset":156047,"endOffset":156321,"count":1}],"isBlockCoverage":true},{"functionName":"_startMicrotaskLoop","ranges":[{"startOffset":156348,"endOffset":156683,"count":1},{"startOffset":156577,"endOffset":156669,"count":0}],"isBlockCoverage":true},{"functionName":"_scheduleAsyncCallback","ranges":[{"startOffset":156713,"endOffset":157097,"count":1}],"isBlockCoverage":true},{"functionName":"_schedulePriorityAsyncCallback","ranges":[{"startOffset":157135,"endOffset":157721,"count":0}],"isBlockCoverage":false},{"functionName":"scheduleMicrotask","ranges":[{"startOffset":157746,"endOffset":158408,"count":1},{"startOffset":157973,"endOffset":158407,"count":0}],"isBlockCoverage":true},{"functionName":"Stream_Stream$fromFuture","ranges":[{"startOffset":158440,"endOffset":158865,"count":0}],"isBlockCoverage":false},{"functionName":"Stream_Stream$fromIterable","ranges":[{"startOffset":158899,"endOffset":159065,"count":1}],"isBlockCoverage":true},{"functionName":"StreamIterator_StreamIterator","ranges":[{"startOffset":159102,"endOffset":159288,"count":0}],"isBlockCoverage":false},{"functionName":"StreamController_StreamController","ranges":[{"startOffset":159329,"endOffset":159628,"count":1},{"startOffset":159516,"endOffset":159621,"count":0}],"isBlockCoverage":true},{"functionName":"_runGuarded","ranges":[{"startOffset":159647,"endOffset":159995,"count":1},{"startOffset":159819,"endOffset":159989,"count":0}],"isBlockCoverage":true},{"functionName":"_AddStreamState_makeErrorHandler","ranges":[{"startOffset":160035,"endOffset":160136,"count":0}],"isBlockCoverage":false},{"functionName":"_BufferingStreamSubscription$","ranges":[{"startOffset":160173,"endOffset":160505,"count":1},{"startOffset":160287,"endOffset":160290,"count":0}],"isBlockCoverage":true},{"functionName":"_nullDataHandler","ranges":[{"startOffset":160529,"endOffset":160552,"count":0}],"isBlockCoverage":false},{"functionName":"_nullErrorHandler","ranges":[{"startOffset":160577,"endOffset":160719,"count":0}],"isBlockCoverage":false},{"functionName":"_nullDoneHandler","ranges":[{"startOffset":160743,"endOffset":160761,"count":0}],"isBlockCoverage":false},{"functionName":"_runUserCode","ranges":[{"startOffset":160781,"endOffset":161431,"count":1},{"startOffset":160958,"endOffset":161425,"count":0}],"isBlockCoverage":true},{"functionName":"_cancelAndError","ranges":[{"startOffset":161454,"endOffset":161799,"count":0}],"isBlockCoverage":false},{"functionName":"_cancelAndErrorClosure","ranges":[{"startOffset":161829,"endOffset":161940,"count":1}],"isBlockCoverage":true},{"functionName":"_cancelAndValue","ranges":[{"startOffset":161963,"endOffset":162267,"count":1}],"isBlockCoverage":true},{"functionName":"Timer_Timer","ranges":[{"startOffset":162286,"endOffset":162516,"count":1},{"startOffset":162389,"endOffset":162433,"count":0}],"isBlockCoverage":true},{"functionName":"_ZoneSpecification$","ranges":[{"startOffset":162543,"endOffset":162986,"count":1}],"isBlockCoverage":true},{"functionName":"Zone__enter","ranges":[{"startOffset":163005,"endOffset":163218,"count":1}],"isBlockCoverage":true},{"functionName":"_parentDelegate","ranges":[{"startOffset":163241,"endOffset":163377,"count":1}],"isBlockCoverage":true},{"functionName":"_rootHandleUncaughtError","ranges":[{"startOffset":163409,"endOffset":163630,"count":0}],"isBlockCoverage":false},{"functionName":"_rootRun","ranges":[{"startOffset":163646,"endOffset":164117,"count":1},{"startOffset":164009,"endOffset":164010,"count":0}],"isBlockCoverage":true},{"functionName":"_rootRunUnary","ranges":[{"startOffset":164138,"endOffset":164675,"count":1},{"startOffset":164567,"endOffset":164568,"count":0}],"isBlockCoverage":true},{"functionName":"_rootRunBinary","ranges":[{"startOffset":164697,"endOffset":165297,"count":0}],"isBlockCoverage":false},{"functionName":"_rootRegisterCallback","ranges":[{"startOffset":165326,"endOffset":165413,"count":1}],"isBlockCoverage":true},{"functionName":"_rootRegisterUnaryCallback","ranges":[{"startOffset":165447,"endOffset":165567,"count":1}],"isBlockCoverage":true},{"functionName":"_rootRegisterBinaryCallback","ranges":[{"startOffset":165602,"endOffset":165740,"count":1}],"isBlockCoverage":true},{"functionName":"_rootErrorCallback","ranges":[{"startOffset":165766,"endOffset":165885,"count":0}],"isBlockCoverage":false},{"functionName":"_rootScheduleMicrotask","ranges":[{"startOffset":165915,"endOffset":166240,"count":1},{"startOffset":166160,"endOffset":166198,"count":0}],"isBlockCoverage":true},{"functionName":"_rootCreateTimer","ranges":[{"startOffset":166264,"endOffset":166506,"count":1}],"isBlockCoverage":true},{"functionName":"_rootCreatePeriodicTimer","ranges":[{"startOffset":166538,"endOffset":166935,"count":0}],"isBlockCoverage":false},{"functionName":"_rootPrint","ranges":[{"startOffset":166953,"endOffset":167048,"count":0}],"isBlockCoverage":false},{"functionName":"_printToZone","ranges":[{"startOffset":167068,"endOffset":167130,"count":0}],"isBlockCoverage":false},{"functionName":"_rootFork","ranges":[{"startOffset":167147,"endOffset":169398,"count":1}],"isBlockCoverage":true},{"functionName":"runZoned","ranges":[{"startOffset":169414,"endOffset":171320,"count":1},{"startOffset":169842,"endOffset":170101,"count":0},{"startOffset":170196,"endOffset":170336,"count":0},{"startOffset":170963,"endOffset":171319,"count":0}],"isBlockCoverage":true},{"functionName":"_runZoned","ranges":[{"startOffset":171337,"endOffset":171497,"count":1}],"isBlockCoverage":true},{"functionName":"_AsyncRun__initializeScheduleImmediate_internalCallback","ranges":[{"startOffset":171560,"endOffset":171660,"count":1}],"isBlockCoverage":true},{"functionName":"_AsyncRun__initializeScheduleImmediate_closure","ranges":[{"startOffset":171714,"endOffset":171856,"count":1}],"isBlockCoverage":true},{"functionName":"_AsyncRun__scheduleImmediateJsOverride_internalCallback","ranges":[{"startOffset":171919,"endOffset":172021,"count":0}],"isBlockCoverage":false},{"functionName":"_AsyncRun__scheduleImmediateWithSetImmediate_internalCallback","ranges":[{"startOffset":172090,"endOffset":172198,"count":0}],"isBlockCoverage":false},{"functionName":"_TimerImpl","ranges":[{"startOffset":172216,"endOffset":172319,"count":1}],"isBlockCoverage":true},{"functionName":"_TimerImpl_internalCallback","ranges":[{"startOffset":172354,"endOffset":172455,"count":1}],"isBlockCoverage":true},{"functionName":"_TimerImpl$periodic_closure","ranges":[{"startOffset":172490,"endOffset":172660,"count":0}],"isBlockCoverage":false},{"functionName":"_AsyncAwaitCompleter","ranges":[{"startOffset":172688,"endOffset":172806,"count":1}],"isBlockCoverage":true},{"functionName":"_awaitOnObject_closure","ranges":[{"startOffset":172836,"endOffset":172909,"count":1}],"isBlockCoverage":true},{"functionName":"_awaitOnObject_closure0","ranges":[{"startOffset":172940,"endOffset":173014,"count":1}],"isBlockCoverage":true},{"functionName":"_wrapJsFunctionForAsync_closure","ranges":[{"startOffset":173053,"endOffset":173133,"count":1}],"isBlockCoverage":true},{"functionName":"_BroadcastStream","ranges":[{"startOffset":173157,"endOffset":173248,"count":1}],"isBlockCoverage":true},{"functionName":"_BroadcastSubscription","ranges":[{"startOffset":173278,"endOffset":173605,"count":1}],"isBlockCoverage":true},{"functionName":"_BroadcastStreamController","ranges":[{"startOffset":173639,"endOffset":173684,"count":0}],"isBlockCoverage":false},{"functionName":"_SyncBroadcastStreamController","ranges":[{"startOffset":173722,"endOffset":173978,"count":1}],"isBlockCoverage":true},{"functionName":"_SyncBroadcastStreamController__sendData_closure","ranges":[{"startOffset":174034,"endOffset":174152,"count":0}],"isBlockCoverage":false},{"functionName":"_SyncBroadcastStreamController__sendError_closure","ranges":[{"startOffset":174209,"endOffset":174361,"count":0}],"isBlockCoverage":false},{"functionName":"_SyncBroadcastStreamController__sendDone_closure","ranges":[{"startOffset":174417,"endOffset":174509,"count":0}],"isBlockCoverage":false},{"functionName":"_AsyncBroadcastStreamController","ranges":[{"startOffset":174548,"endOffset":174805,"count":0}],"isBlockCoverage":false},{"functionName":"Future","ranges":[{"startOffset":174819,"endOffset":174844,"count":0}],"isBlockCoverage":false},{"functionName":"Future_Future_closure","ranges":[{"startOffset":174873,"endOffset":174972,"count":1}],"isBlockCoverage":true},{"functionName":"Future_Future$microtask_closure","ranges":[{"startOffset":175011,"endOffset":175120,"count":0}],"isBlockCoverage":false},{"functionName":"Future_wait_handleError","ranges":[{"startOffset":175151,"endOffset":175316,"count":0}],"isBlockCoverage":false},{"functionName":"Future_wait_closure","ranges":[{"startOffset":175343,"endOffset":175546,"count":0}],"isBlockCoverage":false},{"functionName":"Future_forEach_closure","ranges":[{"startOffset":175576,"endOffset":175673,"count":1}],"isBlockCoverage":true},{"functionName":"Future_doWhile_closure","ranges":[{"startOffset":175703,"endOffset":175830,"count":1}],"isBlockCoverage":true},{"functionName":"TimeoutException","ranges":[{"startOffset":175854,"endOffset":175946,"count":0}],"isBlockCoverage":false},{"functionName":"Completer","ranges":[{"startOffset":175963,"endOffset":175991,"count":0}],"isBlockCoverage":false},{"functionName":"_Completer","ranges":[{"startOffset":176009,"endOffset":176038,"count":0}],"isBlockCoverage":false},{"functionName":"_AsyncCompleter","ranges":[{"startOffset":176061,"endOffset":176146,"count":1}],"isBlockCoverage":true},{"functionName":"_SyncCompleter","ranges":[{"startOffset":176168,"endOffset":176252,"count":1}],"isBlockCoverage":true},{"functionName":"_FutureListener","ranges":[{"startOffset":176275,"endOffset":176487,"count":1}],"isBlockCoverage":true},{"functionName":"_Future","ranges":[{"startOffset":176502,"endOffset":176647,"count":1}],"isBlockCoverage":true},{"functionName":"_Future__addListener_closure","ranges":[{"startOffset":176683,"endOffset":176785,"count":1}],"isBlockCoverage":true},{"functionName":"_Future__prependListeners_closure","ranges":[{"startOffset":176826,"endOffset":176931,"count":0}],"isBlockCoverage":false},{"functionName":"_Future__chainForeignFuture_closure","ranges":[{"startOffset":176974,"endOffset":177054,"count":0}],"isBlockCoverage":false},{"functionName":"_Future__chainForeignFuture_closure0","ranges":[{"startOffset":177098,"endOffset":177179,"count":0}],"isBlockCoverage":false},{"functionName":"_Future__chainForeignFuture_closure1","ranges":[{"startOffset":177223,"endOffset":177350,"count":0}],"isBlockCoverage":false},{"functionName":"_Future__asyncComplete_closure","ranges":[{"startOffset":177388,"endOffset":177489,"count":1}],"isBlockCoverage":true},{"functionName":"_Future__chainFuture_closure","ranges":[{"startOffset":177525,"endOffset":177624,"count":0}],"isBlockCoverage":false},{"functionName":"_Future__asyncCompleteError_closure","ranges":[{"startOffset":177667,"endOffset":177805,"count":0}],"isBlockCoverage":false},{"functionName":"_Future__propagateToListeners_handleWhenCompleteCallback","ranges":[{"startOffset":177869,"endOffset":178066,"count":1}],"isBlockCoverage":true},{"functionName":"_Future__propagateToListeners_handleWhenCompleteCallback_closure","ranges":[{"startOffset":178138,"endOffset":178255,"count":0}],"isBlockCoverage":false},{"functionName":"_Future__propagateToListeners_handleValueCallback","ranges":[{"startOffset":178312,"endOffset":178470,"count":1}],"isBlockCoverage":true},{"functionName":"_Future__propagateToListeners_handleError","ranges":[{"startOffset":178519,"endOffset":178663,"count":0}],"isBlockCoverage":false},{"functionName":"_AsyncCallbackEntry","ranges":[{"startOffset":178690,"endOffset":178780,"count":1}],"isBlockCoverage":true},{"functionName":"Stream","ranges":[{"startOffset":178794,"endOffset":178819,"count":0}],"isBlockCoverage":false},{"functionName":"Stream_Stream$fromFuture_closure","ranges":[{"startOffset":178859,"endOffset":178963,"count":0}],"isBlockCoverage":false},{"functionName":"Stream_Stream$fromFuture_closure0","ranges":[{"startOffset":179004,"endOffset":179086,"count":0}],"isBlockCoverage":false},{"functionName":"Stream_Stream$fromIterable_closure","ranges":[{"startOffset":179128,"endOffset":179232,"count":1}],"isBlockCoverage":true},{"functionName":"Stream_pipe_closure","ranges":[{"startOffset":179259,"endOffset":179331,"count":1}],"isBlockCoverage":true},{"functionName":"Stream_length_closure","ranges":[{"startOffset":179360,"endOffset":179453,"count":0}],"isBlockCoverage":false},{"functionName":"Stream_length_closure0","ranges":[{"startOffset":179483,"endOffset":179578,"count":0}],"isBlockCoverage":false},{"functionName":"Stream_first_closure","ranges":[{"startOffset":179606,"endOffset":179726,"count":1}],"isBlockCoverage":true},{"functionName":"Stream_first_closure0","ranges":[{"startOffset":179755,"endOffset":179821,"count":1}],"isBlockCoverage":true},{"functionName":"Stream_last_closure","ranges":[{"startOffset":179848,"endOffset":179939,"count":0}],"isBlockCoverage":false},{"functionName":"Stream_last_closure0","ranges":[{"startOffset":179967,"endOffset":180060,"count":0}],"isBlockCoverage":false},{"functionName":"Stream_firstWhere_closure","ranges":[{"startOffset":180093,"endOffset":180252,"count":1}],"isBlockCoverage":true},{"functionName":"Stream_firstWhere__closure","ranges":[{"startOffset":180286,"endOffset":180382,"count":1}],"isBlockCoverage":true},{"functionName":"Stream_firstWhere__closure0","ranges":[{"startOffset":180417,"endOffset":180544,"count":1}],"isBlockCoverage":true},{"functionName":"Stream_firstWhere_closure0","ranges":[{"startOffset":180578,"endOffset":180704,"count":1}],"isBlockCoverage":true},{"functionName":"StreamSubscription","ranges":[{"startOffset":180730,"endOffset":180767,"count":0}],"isBlockCoverage":false},{"functionName":"StreamTransformerBase","ranges":[{"startOffset":180796,"endOffset":180836,"count":0}],"isBlockCoverage":false},{"functionName":"_StreamController","ranges":[{"startOffset":180861,"endOffset":180897,"count":0}],"isBlockCoverage":false},{"functionName":"_StreamController__subscribe_closure","ranges":[{"startOffset":180941,"endOffset":181021,"count":1}],"isBlockCoverage":true},{"functionName":"_StreamController__recordCancel_complete","ranges":[{"startOffset":181069,"endOffset":181153,"count":1}],"isBlockCoverage":true},{"functionName":"_SyncStreamControllerDispatch","ranges":[{"startOffset":181190,"endOffset":181238,"count":0}],"isBlockCoverage":false},{"functionName":"_AsyncStreamControllerDispatch","ranges":[{"startOffset":181276,"endOffset":181325,"count":0}],"isBlockCoverage":false},{"functionName":"_AsyncStreamController","ranges":[{"startOffset":181355,"endOffset":181616,"count":0}],"isBlockCoverage":false},{"functionName":"_SyncStreamController","ranges":[{"startOffset":181645,"endOffset":181905,"count":1}],"isBlockCoverage":true},{"functionName":"_ControllerStream","ranges":[{"startOffset":181930,"endOffset":182022,"count":1}],"isBlockCoverage":true},{"functionName":"_ControllerSubscription","ranges":[{"startOffset":182053,"endOffset":182306,"count":1}],"isBlockCoverage":true},{"functionName":"_StreamSinkWrapper","ranges":[{"startOffset":182332,"endOffset":182428,"count":1}],"isBlockCoverage":true},{"functionName":"_AddStreamState","ranges":[{"startOffset":182451,"endOffset":182485,"count":0}],"isBlockCoverage":false},{"functionName":"_AddStreamState_makeErrorHandler_closure","ranges":[{"startOffset":182533,"endOffset":182622,"count":0}],"isBlockCoverage":false},{"functionName":"_AddStreamState_cancel_closure","ranges":[{"startOffset":182660,"endOffset":182734,"count":1}],"isBlockCoverage":true},{"functionName":"_StreamControllerAddStreamState","ranges":[{"startOffset":182773,"endOffset":182957,"count":1}],"isBlockCoverage":true},{"functionName":"_BufferingStreamSubscription","ranges":[{"startOffset":182993,"endOffset":183221,"count":1}],"isBlockCoverage":true},{"functionName":"_BufferingStreamSubscription__sendError_sendError","ranges":[{"startOffset":183278,"endOffset":183430,"count":0}],"isBlockCoverage":false},{"functionName":"_BufferingStreamSubscription__sendDone_sendDone","ranges":[{"startOffset":183485,"endOffset":183576,"count":0}],"isBlockCoverage":false},{"functionName":"_StreamImpl","ranges":[{"startOffset":183595,"endOffset":183625,"count":0}],"isBlockCoverage":false},{"functionName":"_GeneratedStreamImpl","ranges":[{"startOffset":183653,"endOffset":183773,"count":1}],"isBlockCoverage":true},{"functionName":"_IterablePendingEvents","ranges":[{"startOffset":183803,"endOffset":183928,"count":1}],"isBlockCoverage":true},{"functionName":"_DelayedEvent","ranges":[{"startOffset":183949,"endOffset":183981,"count":0}],"isBlockCoverage":false},{"functionName":"_DelayedData","ranges":[{"startOffset":184001,"endOffset":184106,"count":0}],"isBlockCoverage":false},{"functionName":"_DelayedError","ranges":[{"startOffset":184127,"endOffset":184240,"count":0}],"isBlockCoverage":false},{"functionName":"_DelayedDone","ranges":[{"startOffset":184260,"endOffset":184291,"count":1}],"isBlockCoverage":true},{"functionName":"_PendingEvents","ranges":[{"startOffset":184313,"endOffset":184346,"count":0}],"isBlockCoverage":false},{"functionName":"_PendingEvents_schedule_closure","ranges":[{"startOffset":184385,"endOffset":184490,"count":1}],"isBlockCoverage":true},{"functionName":"_StreamImplEvents","ranges":[{"startOffset":184515,"endOffset":184666,"count":0}],"isBlockCoverage":false},{"functionName":"_DoneStreamSubscription","ranges":[{"startOffset":184697,"endOffset":184849,"count":0}],"isBlockCoverage":false},{"functionName":"_StreamIterator","ranges":[{"startOffset":184872,"endOffset":184929,"count":0}],"isBlockCoverage":false},{"functionName":"_EmptyStream","ranges":[{"startOffset":184949,"endOffset":185003,"count":0}],"isBlockCoverage":false},{"functionName":"_cancelAndError_closure","ranges":[{"startOffset":185034,"endOffset":185161,"count":0}],"isBlockCoverage":false},{"functionName":"_cancelAndErrorClosure_closure","ranges":[{"startOffset":185199,"endOffset":185308,"count":1}],"isBlockCoverage":true},{"functionName":"_cancelAndValue_closure","ranges":[{"startOffset":185339,"endOffset":185434,"count":1}],"isBlockCoverage":true},{"functionName":"Timer","ranges":[{"startOffset":185447,"endOffset":185471,"count":0}],"isBlockCoverage":false},{"functionName":"AsyncError","ranges":[{"startOffset":185489,"endOffset":185575,"count":0}],"isBlockCoverage":false},{"functionName":"_ZoneFunction","ranges":[{"startOffset":185596,"endOffset":185708,"count":1}],"isBlockCoverage":true},{"functionName":"ZoneSpecification","ranges":[{"startOffset":185733,"endOffset":185769,"count":0}],"isBlockCoverage":false},{"functionName":"_ZoneSpecification","ranges":[{"startOffset":185795,"endOffset":186270,"count":1}],"isBlockCoverage":true},{"functionName":"ZoneDelegate","ranges":[{"startOffset":186290,"endOffset":186321,"count":0}],"isBlockCoverage":false},{"functionName":"Zone","ranges":[{"startOffset":186333,"endOffset":186356,"count":0}],"isBlockCoverage":false},{"functionName":"_ZoneDelegate","ranges":[{"startOffset":186377,"endOffset":186446,"count":1}],"isBlockCoverage":true},{"functionName":"_Zone","ranges":[{"startOffset":186459,"endOffset":186483,"count":0}],"isBlockCoverage":false},{"functionName":"_CustomZone","ranges":[{"startOffset":186502,"endOffset":186881,"count":1}],"isBlockCoverage":true},{"functionName":"_CustomZone_bindCallback_closure","ranges":[{"startOffset":186921,"endOffset":187052,"count":1}],"isBlockCoverage":true},{"functionName":"_CustomZone_bindUnaryCallback_closure","ranges":[{"startOffset":187097,"endOffset":187264,"count":0}],"isBlockCoverage":false},{"functionName":"_CustomZone_bindCallbackGuarded_closure","ranges":[{"startOffset":187311,"endOffset":187426,"count":1}],"isBlockCoverage":true},{"functionName":"_CustomZone_bindUnaryCallbackGuarded_closure","ranges":[{"startOffset":187478,"endOffset":187621,"count":1}],"isBlockCoverage":true},{"functionName":"_rootHandleUncaughtError_closure","ranges":[{"startOffset":187661,"endOffset":187770,"count":0}],"isBlockCoverage":false},{"functionName":"_RootZone","ranges":[{"startOffset":187787,"endOffset":187815,"count":1}],"isBlockCoverage":true},{"functionName":"_RootZone_bindCallback_closure","ranges":[{"startOffset":187853,"endOffset":187973,"count":0}],"isBlockCoverage":false},{"functionName":"_RootZone_bindCallbackGuarded_closure","ranges":[{"startOffset":188018,"endOffset":188122,"count":0}],"isBlockCoverage":false},{"functionName":"_RootZone_bindUnaryCallbackGuarded_closure","ranges":[{"startOffset":188172,"endOffset":188304,"count":0}],"isBlockCoverage":false},{"functionName":"runZoned_closure","ranges":[{"startOffset":188328,"endOffset":188389,"count":1}],"isBlockCoverage":true},{"functionName":"HashMap_HashMap","ranges":[{"startOffset":188412,"endOffset":188522,"count":1}],"isBlockCoverage":true},{"functionName":"_HashMap__getTableEntry","ranges":[{"startOffset":188553,"endOffset":188656,"count":0}],"isBlockCoverage":false},{"functionName":"_HashMap__setTableEntry","ranges":[{"startOffset":188687,"endOffset":188814,"count":1},{"startOffset":188750,"endOffset":188769,"count":0}],"isBlockCoverage":true},{"functionName":"_HashMap__newHashTable","ranges":[{"startOffset":188844,"endOffset":189036,"count":1}],"isBlockCoverage":true},{"functionName":"LinkedHashMap_LinkedHashMap","ranges":[{"startOffset":189071,"endOffset":189195,"count":1}],"isBlockCoverage":true},{"functionName":"LinkedHashMap_LinkedHashMap$_literal","ranges":[{"startOffset":189239,"endOffset":189480,"count":1}],"isBlockCoverage":true},{"functionName":"LinkedHashMap_LinkedHashMap$_empty","ranges":[{"startOffset":189522,"endOffset":189646,"count":1}],"isBlockCoverage":true},{"functionName":"LinkedHashSet_LinkedHashSet","ranges":[{"startOffset":189681,"endOffset":189769,"count":1}],"isBlockCoverage":true},{"functionName":"LinkedHashSet_LinkedHashSet$_empty","ranges":[{"startOffset":189811,"endOffset":189899,"count":1}],"isBlockCoverage":true},{"functionName":"LinkedHashSet_LinkedHashSet$_literal","ranges":[{"startOffset":189943,"endOffset":190104,"count":1}],"isBlockCoverage":true},{"functionName":"_LinkedHashSet__newHashTable","ranges":[{"startOffset":190140,"endOffset":190343,"count":1}],"isBlockCoverage":true},{"functionName":"_LinkedHashSetIterator$","ranges":[{"startOffset":190374,"endOffset":190595,"count":1}],"isBlockCoverage":true},{"functionName":"HashMap_HashMap$from","ranges":[{"startOffset":190623,"endOffset":190799,"count":1}],"isBlockCoverage":true},{"functionName":"IterableBase_iterableToShortString","ranges":[{"startOffset":190841,"endOffset":191704,"count":0}],"isBlockCoverage":false},{"functionName":"IterableBase_iterableToFullString","ranges":[{"startOffset":191745,"endOffset":192506,"count":0}],"isBlockCoverage":false},{"functionName":"_isToStringVisiting","ranges":[{"startOffset":192533,"endOffset":192718,"count":0}],"isBlockCoverage":false},{"functionName":"_iterablePartsToStrings","ranges":[{"startOffset":192749,"endOffset":195409,"count":0}],"isBlockCoverage":false},{"functionName":"LinkedHashMap_LinkedHashMap$from","ranges":[{"startOffset":195449,"endOffset":195649,"count":1}],"isBlockCoverage":true},{"functionName":"LinkedHashSet_LinkedHashSet$from","ranges":[{"startOffset":195689,"endOffset":195923,"count":1}],"isBlockCoverage":true},{"functionName":"MapBase_mapToString","ranges":[{"startOffset":195950,"endOffset":196637,"count":0}],"isBlockCoverage":false},{"functionName":"ListQueue$","ranges":[{"startOffset":196655,"endOffset":196883,"count":1}],"isBlockCoverage":true},{"functionName":"_ListQueueIterator$","ranges":[{"startOffset":196910,"endOffset":197072,"count":0}],"isBlockCoverage":false},{"functionName":"_HashMap","ranges":[{"startOffset":197088,"endOffset":197255,"count":1}],"isBlockCoverage":true},{"functionName":"_IdentityHashMap","ranges":[{"startOffset":197279,"endOffset":197454,"count":1}],"isBlockCoverage":true},{"functionName":"_HashMapKeyIterable","ranges":[{"startOffset":197481,"endOffset":197568,"count":0}],"isBlockCoverage":false},{"functionName":"_HashMapKeyIterator","ranges":[{"startOffset":197595,"endOffset":197778,"count":0}],"isBlockCoverage":false},{"functionName":"_LinkedHashSet","ranges":[{"startOffset":197800,"endOffset":198048,"count":1}],"isBlockCoverage":true},{"functionName":"_LinkedHashSetCell","ranges":[{"startOffset":198074,"endOffset":198205,"count":1}],"isBlockCoverage":true},{"functionName":"_LinkedHashSetIterator","ranges":[{"startOffset":198235,"endOffset":198443,"count":1}],"isBlockCoverage":true},{"functionName":"UnmodifiableListView","ranges":[{"startOffset":198471,"endOffset":198574,"count":0}],"isBlockCoverage":false},{"functionName":"HashMap_HashMap$from_closure","ranges":[{"startOffset":198610,"endOffset":198729,"count":1}],"isBlockCoverage":true},{"functionName":"IterableBase","ranges":[{"startOffset":198749,"endOffset":198780,"count":0}],"isBlockCoverage":false},{"functionName":"LinkedHashMap_LinkedHashMap$from_closure","ranges":[{"startOffset":198828,"endOffset":198959,"count":1}],"isBlockCoverage":true},{"functionName":"ListBase","ranges":[{"startOffset":198975,"endOffset":199002,"count":0}],"isBlockCoverage":false},{"functionName":"ListMixin","ranges":[{"startOffset":199019,"endOffset":199047,"count":0}],"isBlockCoverage":false},{"functionName":"MapBase","ranges":[{"startOffset":199062,"endOffset":199088,"count":0}],"isBlockCoverage":false},{"functionName":"MapBase_mapToString_closure","ranges":[{"startOffset":199123,"endOffset":199223,"count":0}],"isBlockCoverage":false},{"functionName":"MapMixin","ranges":[{"startOffset":199239,"endOffset":199266,"count":0}],"isBlockCoverage":false},{"functionName":"_UnmodifiableMapMixin","ranges":[{"startOffset":199295,"endOffset":199335,"count":0}],"isBlockCoverage":false},{"functionName":"MapView","ranges":[{"startOffset":199350,"endOffset":199376,"count":0}],"isBlockCoverage":false},{"functionName":"UnmodifiableMapView","ranges":[{"startOffset":199403,"endOffset":199490,"count":1}],"isBlockCoverage":true},{"functionName":"ListQueue","ranges":[{"startOffset":199507,"endOffset":199650,"count":1}],"isBlockCoverage":true},{"functionName":"_ListQueueIterator","ranges":[{"startOffset":199676,"endOffset":199903,"count":0}],"isBlockCoverage":false},{"functionName":"SetMixin","ranges":[{"startOffset":199919,"endOffset":199946,"count":0}],"isBlockCoverage":false},{"functionName":"SetBase","ranges":[{"startOffset":199961,"endOffset":199987,"count":0}],"isBlockCoverage":false},{"functionName":"_SetBase","ranges":[{"startOffset":200003,"endOffset":200030,"count":0}],"isBlockCoverage":false},{"functionName":"_ListBase_Object_ListMixin","ranges":[{"startOffset":200064,"endOffset":200109,"count":0}],"isBlockCoverage":false},{"functionName":"_SetBase_Object_SetMixin","ranges":[{"startOffset":200141,"endOffset":200184,"count":0}],"isBlockCoverage":false},{"functionName":"_UnmodifiableMapView_MapView__UnmodifiableMapMixin","ranges":[{"startOffset":200242,"endOffset":200311,"count":0}],"isBlockCoverage":false},{"functionName":"_parseJson","ranges":[{"startOffset":200329,"endOffset":200797,"count":0}],"isBlockCoverage":false},{"functionName":"_convertJsonToDartLazy","ranges":[{"startOffset":200827,"endOffset":201212,"count":0}],"isBlockCoverage":false},{"functionName":"Utf8Decoder__convertIntercepted","ranges":[{"startOffset":201251,"endOffset":201457,"count":0}],"isBlockCoverage":false},{"functionName":"Utf8Decoder__convertInterceptedUint8List","ranges":[{"startOffset":201505,"endOffset":202094,"count":0}],"isBlockCoverage":false},{"functionName":"Utf8Decoder__useTextDecoderChecked","ranges":[{"startOffset":202136,"endOffset":202310,"count":0}],"isBlockCoverage":false},{"functionName":"Utf8Decoder__useTextDecoderUnchecked","ranges":[{"startOffset":202354,"endOffset":202579,"count":0}],"isBlockCoverage":false},{"functionName":"Utf8Decoder__unsafe","ranges":[{"startOffset":202606,"endOffset":202845,"count":0}],"isBlockCoverage":false},{"functionName":"Utf8Decoder__makeDecoder","ranges":[{"startOffset":202877,"endOffset":203098,"count":0}],"isBlockCoverage":false},{"functionName":"_scanOneByteCharacters","ranges":[{"startOffset":203128,"endOffset":203470,"count":0}],"isBlockCoverage":false},{"functionName":"Base64Codec__checkPadding","ranges":[{"startOffset":203503,"endOffset":204114,"count":0}],"isBlockCoverage":false},{"functionName":"_JsonMap","ranges":[{"startOffset":204130,"endOffset":204243,"count":0}],"isBlockCoverage":false},{"functionName":"_JsonMapKeyIterable","ranges":[{"startOffset":204270,"endOffset":204335,"count":0}],"isBlockCoverage":false},{"functionName":"AsciiCodec","ranges":[{"startOffset":204353,"endOffset":204382,"count":1}],"isBlockCoverage":true},{"functionName":"_UnicodeSubsetEncoder","ranges":[{"startOffset":204411,"endOffset":204451,"count":0}],"isBlockCoverage":false},{"functionName":"AsciiEncoder","ranges":[{"startOffset":204471,"endOffset":204533,"count":1}],"isBlockCoverage":true},{"functionName":"Base64Codec","ranges":[{"startOffset":204552,"endOffset":204582,"count":1}],"isBlockCoverage":true},{"functionName":"Base64Encoder","ranges":[{"startOffset":204603,"endOffset":204635,"count":1}],"isBlockCoverage":true},{"functionName":"Codec","ranges":[{"startOffset":204648,"endOffset":204672,"count":0}],"isBlockCoverage":false},{"functionName":"_FusedCodec","ranges":[{"startOffset":204691,"endOffset":204810,"count":0}],"isBlockCoverage":false},{"functionName":"Converter","ranges":[{"startOffset":204827,"endOffset":204855,"count":0}],"isBlockCoverage":false},{"functionName":"Encoding","ranges":[{"startOffset":204871,"endOffset":204898,"count":0}],"isBlockCoverage":false},{"functionName":"JsonCodec","ranges":[{"startOffset":204915,"endOffset":204943,"count":1}],"isBlockCoverage":true},{"functionName":"JsonDecoder","ranges":[{"startOffset":204962,"endOffset":205020,"count":1}],"isBlockCoverage":true},{"functionName":"Utf8Codec","ranges":[{"startOffset":205037,"endOffset":205065,"count":1}],"isBlockCoverage":true},{"functionName":"Utf8Encoder","ranges":[{"startOffset":205084,"endOffset":205114,"count":1}],"isBlockCoverage":true},{"functionName":"_Utf8Encoder","ranges":[{"startOffset":205134,"endOffset":205235,"count":0}],"isBlockCoverage":false},{"functionName":"Utf8Decoder","ranges":[{"startOffset":205254,"endOffset":205319,"count":0}],"isBlockCoverage":false},{"functionName":"_Utf8Decoder","ranges":[{"startOffset":205339,"endOffset":205550,"count":0}],"isBlockCoverage":false},{"functionName":"int_parse","ranges":[{"startOffset":205567,"endOffset":205845,"count":0}],"isBlockCoverage":false},{"functionName":"Error__objectToString","ranges":[{"startOffset":205874,"endOffset":206053,"count":0}],"isBlockCoverage":false},{"functionName":"List_List$filled","ranges":[{"startOffset":206077,"endOffset":206334,"count":0}],"isBlockCoverage":false},{"functionName":"List_List$from","ranges":[{"startOffset":206356,"endOffset":206723,"count":1}],"isBlockCoverage":true},{"functionName":"List_List$unmodifiable","ranges":[{"startOffset":206753,"endOffset":206964,"count":1}],"isBlockCoverage":true},{"functionName":"String_String$fromCharCodes","ranges":[{"startOffset":206999,"endOffset":207622,"count":0}],"isBlockCoverage":false},{"functionName":"String_String$fromCharCode","ranges":[{"startOffset":207656,"endOffset":207738,"count":0}],"isBlockCoverage":false},{"functionName":"String__stringFromIterable","ranges":[{"startOffset":207772,"endOffset":208694,"count":0}],"isBlockCoverage":false},{"functionName":"RegExp_RegExp","ranges":[{"startOffset":208715,"endOffset":208868,"count":0}],"isBlockCoverage":false},{"functionName":"StringBuffer__writeAll","ranges":[{"startOffset":208898,"endOffset":209382,"count":0}],"isBlockCoverage":false},{"functionName":"Uri_base","ranges":[{"startOffset":209398,"endOffset":209596,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__uriEncode","ranges":[{"startOffset":209619,"endOffset":210718,"count":0}],"isBlockCoverage":false},{"functionName":"StackTrace_current","ranges":[{"startOffset":210744,"endOffset":211119,"count":1},{"startOffset":210908,"endOffset":211113,"count":0}],"isBlockCoverage":true},{"functionName":"DateTime__fourDigits","ranges":[{"startOffset":211147,"endOffset":211424,"count":0}],"isBlockCoverage":false},{"functionName":"DateTime__threeDigits","ranges":[{"startOffset":211453,"endOffset":211581,"count":0}],"isBlockCoverage":false},{"functionName":"DateTime__twoDigits","ranges":[{"startOffset":211608,"endOffset":211691,"count":0}],"isBlockCoverage":false},{"functionName":"Duration$","ranges":[{"startOffset":211708,"endOffset":211891,"count":1},{"startOffset":211794,"endOffset":211821,"count":0}],"isBlockCoverage":true},{"functionName":"Error_safeToString","ranges":[{"startOffset":211917,"endOffset":212177,"count":0}],"isBlockCoverage":false},{"functionName":"AssertionError$","ranges":[{"startOffset":212200,"endOffset":212269,"count":0}],"isBlockCoverage":false},{"functionName":"ArgumentError$","ranges":[{"startOffset":212291,"endOffset":212378,"count":0}],"isBlockCoverage":false},{"functionName":"ArgumentError$value","ranges":[{"startOffset":212405,"endOffset":212507,"count":0}],"isBlockCoverage":false},{"functionName":"ArgumentError$notNull","ranges":[{"startOffset":212536,"endOffset":212633,"count":0}],"isBlockCoverage":false},{"functionName":"RangeError$","ranges":[{"startOffset":212652,"endOffset":212776,"count":0}],"isBlockCoverage":false},{"functionName":"RangeError$value","ranges":[{"startOffset":212800,"endOffset":212915,"count":0}],"isBlockCoverage":false},{"functionName":"RangeError$range","ranges":[{"startOffset":212939,"endOffset":213100,"count":0}],"isBlockCoverage":false},{"functionName":"RangeError_checkValueInInterval","ranges":[{"startOffset":213139,"endOffset":213328,"count":0}],"isBlockCoverage":false},{"functionName":"RangeError_checkValidRange","ranges":[{"startOffset":213362,"endOffset":213728,"count":1},{"startOffset":213442,"endOffset":213518,"count":0},{"startOffset":213596,"endOffset":213672,"count":0},{"startOffset":213700,"endOffset":213727,"count":0}],"isBlockCoverage":true},{"functionName":"RangeError_checkNotNegative","ranges":[{"startOffset":213763,"endOffset":213959,"count":0}],"isBlockCoverage":false},{"functionName":"IndexError$","ranges":[{"startOffset":213978,"endOffset":214221,"count":0}],"isBlockCoverage":false},{"functionName":"UnsupportedError$","ranges":[{"startOffset":214246,"endOffset":214317,"count":0}],"isBlockCoverage":false},{"functionName":"UnimplementedError$","ranges":[{"startOffset":214344,"endOffset":214417,"count":0}],"isBlockCoverage":false},{"functionName":"StateError$","ranges":[{"startOffset":214436,"endOffset":214501,"count":0}],"isBlockCoverage":false},{"functionName":"ConcurrentModificationError$","ranges":[{"startOffset":214537,"endOffset":214633,"count":0}],"isBlockCoverage":false},{"functionName":"FormatException$","ranges":[{"startOffset":214657,"endOffset":214759,"count":0}],"isBlockCoverage":false},{"functionName":"List_List$generate","ranges":[{"startOffset":214785,"endOffset":215096,"count":1}],"isBlockCoverage":true},{"functionName":"Map_castFrom","ranges":[{"startOffset":215116,"endOffset":215276,"count":1}],"isBlockCoverage":true},{"functionName":"print","ranges":[{"startOffset":215289,"endOffset":215458,"count":0}],"isBlockCoverage":false},{"functionName":"_combineSurrogatePair","ranges":[{"startOffset":215487,"endOffset":215575,"count":0}],"isBlockCoverage":false},{"functionName":"Uri_parse","ranges":[{"startOffset":215592,"endOffset":222061,"count":1},{"startOffset":216121,"endOffset":216228,"count":0},{"startOffset":216270,"endOffset":216359,"count":0},{"startOffset":216950,"endOffset":216995,"count":0},{"startOffset":217075,"endOffset":217098,"count":0},{"startOffset":217195,"endOffset":217218,"count":0},{"startOffset":217284,"endOffset":217301,"count":0},{"startOffset":217506,"endOffset":217533,"count":0},{"startOffset":217584,"endOffset":217609,"count":0},{"startOffset":217656,"endOffset":217683,"count":0},{"startOffset":217733,"endOffset":217756,"count":0},{"startOffset":217798,"endOffset":217821,"count":0},{"startOffset":217869,"endOffset":217895,"count":0},{"startOffset":217945,"endOffset":217968,"count":0},{"startOffset":218399,"endOffset":218415,"count":0},{"startOffset":218500,"endOffset":218565,"count":0},{"startOffset":218652,"endOffset":218723,"count":0},{"startOffset":218766,"endOffset":218797,"count":0},{"startOffset":218798,"endOffset":218839,"count":0},{"startOffset":218936,"endOffset":218978,"count":0},{"startOffset":218999,"endOffset":219076,"count":0},{"startOffset":219213,"endOffset":219911,"count":0},{"startOffset":219947,"endOffset":220222,"count":0},{"startOffset":220275,"endOffset":221412,"count":0},{"startOffset":221479,"endOffset":221514,"count":0},{"startOffset":221584,"endOffset":221802,"count":0},{"startOffset":221927,"endOffset":222060,"count":0}],"isBlockCoverage":true},{"functionName":"Uri_decodeComponent","ranges":[{"startOffset":222088,"endOffset":222270,"count":0}],"isBlockCoverage":false},{"functionName":"Uri__parseIPv4Address","ranges":[{"startOffset":222299,"endOffset":223833,"count":0}],"isBlockCoverage":false},{"functionName":"Uri_parseIPv6Address","ranges":[{"startOffset":223861,"endOffset":226795,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__Uri$notSimple","ranges":[{"startOffset":226822,"endOffset":228163,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__Uri","ranges":[{"startOffset":228180,"endOffset":229390,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__defaultPort","ranges":[{"startOffset":229415,"endOffset":229553,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__fail","ranges":[{"startOffset":229571,"endOffset":229678,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__Uri$file","ranges":[{"startOffset":229700,"endOffset":229830,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__checkNonWindowsPathReservedCharacters","ranges":[{"startOffset":229881,"endOffset":230033,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__checkWindowsPathReservedCharacters","ranges":[{"startOffset":230081,"endOffset":230721,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__checkWindowsDriveLetter","ranges":[{"startOffset":230758,"endOffset":231242,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__makeFileUri","ranges":[{"startOffset":231267,"endOffset":231594,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__makeWindowsFileUrl","ranges":[{"startOffset":231626,"endOffset":234062,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__makePort","ranges":[{"startOffset":234084,"endOffset":234218,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__makeHost","ranges":[{"startOffset":234240,"endOffset":235817,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__checkZoneID","ranges":[{"startOffset":235842,"endOffset":236000,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__normalizeZoneID","ranges":[{"startOffset":236029,"endOffset":238805,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__normalizeRegName","ranges":[{"startOffset":238835,"endOffset":242233,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__makeScheme","ranges":[{"startOffset":242257,"endOffset":243253,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__canonicalizeScheme","ranges":[{"startOffset":243285,"endOffset":243546,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__makeUserInfo","ranges":[{"startOffset":243572,"endOffset":243741,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__makePath","ranges":[{"startOffset":243763,"endOffset":244818,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__normalizePath","ranges":[{"startOffset":244845,"endOffset":245122,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__makeQuery","ranges":[{"startOffset":245145,"endOffset":245323,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__makeFragment","ranges":[{"startOffset":245349,"endOffset":245519,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__normalizeEscape","ranges":[{"startOffset":245548,"endOffset":246720,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__escapeChar","ranges":[{"startOffset":246744,"endOffset":248292,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__normalizeOrSubstring","ranges":[{"startOffset":248326,"endOffset":248566,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__normalize","ranges":[{"startOffset":248589,"endOffset":251311,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__mayContainDotSegments","ranges":[{"startOffset":251346,"endOffset":251505,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__removeDotSegments","ranges":[{"startOffset":251536,"endOffset":252526,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__normalizeRelativePath","ranges":[{"startOffset":252561,"endOffset":254222,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__escapeScheme","ranges":[{"startOffset":254248,"endOffset":254933,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__toWindowsFilePath","ranges":[{"startOffset":254964,"endOffset":255945,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__hexCharPairToByte","ranges":[{"startOffset":255976,"endOffset":256491,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__uriDecode","ranges":[{"startOffset":256514,"endOffset":258126,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__isAlphabeticCharacter","ranges":[{"startOffset":258161,"endOffset":258274,"count":0}],"isBlockCoverage":false},{"functionName":"UriData__writeUri","ranges":[{"startOffset":258299,"endOffset":258967,"count":0}],"isBlockCoverage":false},{"functionName":"UriData__validateMimeType","ranges":[{"startOffset":259000,"endOffset":259351,"count":0}],"isBlockCoverage":false},{"functionName":"UriData__parse","ranges":[{"startOffset":259373,"endOffset":261418,"count":0}],"isBlockCoverage":false},{"functionName":"UriData__uriEncodeBytes","ranges":[{"startOffset":261449,"endOffset":262927,"count":0}],"isBlockCoverage":false},{"functionName":"_createTables","ranges":[{"startOffset":262948,"endOffset":267507,"count":1}],"isBlockCoverage":true},{"functionName":"_scan","ranges":[{"startOffset":267520,"endOffset":268208,"count":1},{"startOffset":267816,"endOffset":267846,"count":0},{"startOffset":267957,"endOffset":267967,"count":0},{"startOffset":268012,"endOffset":268040,"count":0}],"isBlockCoverage":true},{"functionName":"bool","ranges":[{"startOffset":268220,"endOffset":268243,"count":0}],"isBlockCoverage":false},{"functionName":"DateTime","ranges":[{"startOffset":268259,"endOffset":268339,"count":0}],"isBlockCoverage":false},{"functionName":"double","ranges":[{"startOffset":268353,"endOffset":268378,"count":0}],"isBlockCoverage":false},{"functionName":"Duration","ranges":[{"startOffset":268394,"endOffset":268450,"count":1}],"isBlockCoverage":true},{"functionName":"Duration_toString_sixDigits","ranges":[{"startOffset":268485,"endOffset":268531,"count":0}],"isBlockCoverage":false},{"functionName":"Duration_toString_twoDigits","ranges":[{"startOffset":268566,"endOffset":268612,"count":0}],"isBlockCoverage":false},{"functionName":"Error","ranges":[{"startOffset":268625,"endOffset":268649,"count":0}],"isBlockCoverage":false},{"functionName":"AssertionError","ranges":[{"startOffset":268671,"endOffset":268731,"count":0}],"isBlockCoverage":false},{"functionName":"NullThrownError","ranges":[{"startOffset":268754,"endOffset":268788,"count":0}],"isBlockCoverage":false},{"functionName":"ArgumentError","ranges":[{"startOffset":268809,"endOffset":268967,"count":0}],"isBlockCoverage":false},{"functionName":"RangeError","ranges":[{"startOffset":268985,"endOffset":269186,"count":0}],"isBlockCoverage":false},{"functionName":"IndexError","ranges":[{"startOffset":269204,"endOffset":269384,"count":0}],"isBlockCoverage":false},{"functionName":"UnsupportedError","ranges":[{"startOffset":269408,"endOffset":269470,"count":0}],"isBlockCoverage":false},{"functionName":"UnimplementedError","ranges":[{"startOffset":269496,"endOffset":269560,"count":0}],"isBlockCoverage":false},{"functionName":"StateError","ranges":[{"startOffset":269578,"endOffset":269634,"count":0}],"isBlockCoverage":false},{"functionName":"ConcurrentModificationError","ranges":[{"startOffset":269669,"endOffset":269749,"count":0}],"isBlockCoverage":false},{"functionName":"OutOfMemoryError","ranges":[{"startOffset":269773,"endOffset":269808,"count":1}],"isBlockCoverage":true},{"functionName":"StackOverflowError","ranges":[{"startOffset":269834,"endOffset":269871,"count":0}],"isBlockCoverage":false},{"functionName":"CyclicInitializationError","ranges":[{"startOffset":269904,"endOffset":269980,"count":0}],"isBlockCoverage":false},{"functionName":"_Exception","ranges":[{"startOffset":269998,"endOffset":270054,"count":0}],"isBlockCoverage":false},{"functionName":"FormatException","ranges":[{"startOffset":270077,"endOffset":270194,"count":0}],"isBlockCoverage":false},{"functionName":"Expando","ranges":[{"startOffset":270209,"endOffset":270321,"count":1}],"isBlockCoverage":true},{"functionName":"Function","ranges":[{"startOffset":270337,"endOffset":270364,"count":0}],"isBlockCoverage":false},{"functionName":"int","ranges":[{"startOffset":270375,"endOffset":270397,"count":0}],"isBlockCoverage":false},{"functionName":"Iterable","ranges":[{"startOffset":270413,"endOffset":270440,"count":0}],"isBlockCoverage":false},{"functionName":"Iterator","ranges":[{"startOffset":270456,"endOffset":270483,"count":0}],"isBlockCoverage":false},{"functionName":"List","ranges":[{"startOffset":270495,"endOffset":270518,"count":0}],"isBlockCoverage":false},{"functionName":"Map","ranges":[{"startOffset":270529,"endOffset":270551,"count":0}],"isBlockCoverage":false},{"functionName":"MapEntry","ranges":[{"startOffset":270567,"endOffset":270669,"count":1}],"isBlockCoverage":true},{"functionName":"Null","ranges":[{"startOffset":270681,"endOffset":270704,"count":0}],"isBlockCoverage":false},{"functionName":"num","ranges":[{"startOffset":270715,"endOffset":270737,"count":0}],"isBlockCoverage":false},{"functionName":"Object","ranges":[{"startOffset":270751,"endOffset":270776,"count":1}],"isBlockCoverage":true},{"functionName":"Pattern","ranges":[{"startOffset":270791,"endOffset":270817,"count":0}],"isBlockCoverage":false},{"functionName":"Match","ranges":[{"startOffset":270830,"endOffset":270854,"count":0}],"isBlockCoverage":false},{"functionName":"RegExpMatch","ranges":[{"startOffset":270873,"endOffset":270903,"count":0}],"isBlockCoverage":false},{"functionName":"Set","ranges":[{"startOffset":270914,"endOffset":270936,"count":0}],"isBlockCoverage":false},{"functionName":"StackTrace","ranges":[{"startOffset":270954,"endOffset":270983,"count":0}],"isBlockCoverage":false},{"functionName":"_StringStackTrace","ranges":[{"startOffset":271008,"endOffset":271075,"count":0}],"isBlockCoverage":false},{"functionName":"Stopwatch","ranges":[{"startOffset":271092,"endOffset":271162,"count":0}],"isBlockCoverage":false},{"functionName":"String","ranges":[{"startOffset":271176,"endOffset":271201,"count":0}],"isBlockCoverage":false},{"functionName":"Runes","ranges":[{"startOffset":271214,"endOffset":271264,"count":0}],"isBlockCoverage":false},{"functionName":"RuneIterator","ranges":[{"startOffset":271284,"endOffset":271439,"count":0}],"isBlockCoverage":false},{"functionName":"StringBuffer","ranges":[{"startOffset":271459,"endOffset":271519,"count":0}],"isBlockCoverage":false},{"functionName":"Uri","ranges":[{"startOffset":271530,"endOffset":271552,"count":0}],"isBlockCoverage":false},{"functionName":"Uri__parseIPv4Address_error","ranges":[{"startOffset":271587,"endOffset":271657,"count":0}],"isBlockCoverage":false},{"functionName":"Uri_parseIPv6Address_error","ranges":[{"startOffset":271691,"endOffset":271760,"count":0}],"isBlockCoverage":false},{"functionName":"Uri_parseIPv6Address_parseHex","ranges":[{"startOffset":271797,"endOffset":271896,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri","ranges":[{"startOffset":271908,"endOffset":272185,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__Uri$notSimple_closure","ranges":[{"startOffset":272220,"endOffset":272320,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__checkNonWindowsPathReservedCharacters_closure","ranges":[{"startOffset":272379,"endOffset":272482,"count":0}],"isBlockCoverage":false},{"functionName":"_Uri__makePath_closure","ranges":[{"startOffset":272512,"endOffset":272553,"count":0}],"isBlockCoverage":false},{"functionName":"UriData","ranges":[{"startOffset":272568,"endOffset":272689,"count":0}],"isBlockCoverage":false},{"functionName":"_createTables_closure","ranges":[{"startOffset":272718,"endOffset":272758,"count":1}],"isBlockCoverage":true},{"functionName":"_createTables_build","ranges":[{"startOffset":272785,"endOffset":272849,"count":1}],"isBlockCoverage":true},{"functionName":"_createTables_setChars","ranges":[{"startOffset":272879,"endOffset":272920,"count":1}],"isBlockCoverage":true},{"functionName":"_createTables_setRange","ranges":[{"startOffset":272950,"endOffset":272991,"count":1}],"isBlockCoverage":true},{"functionName":"_SimpleUri","ranges":[{"startOffset":273009,"endOffset":273320,"count":1}],"isBlockCoverage":true},{"functionName":"_DataUri","ranges":[{"startOffset":273336,"endOffset":273617,"count":0}],"isBlockCoverage":false},{"functionName":"_StructuredClone","ranges":[{"startOffset":273641,"endOffset":273676,"count":0}],"isBlockCoverage":false},{"functionName":"_StructuredClone_walk_closure","ranges":[{"startOffset":273713,"endOffset":273814,"count":1}],"isBlockCoverage":true},{"functionName":"_StructuredClone_walk_closure0","ranges":[{"startOffset":273852,"endOffset":273954,"count":0}],"isBlockCoverage":false},{"functionName":"_AcceptStructuredClone","ranges":[{"startOffset":273984,"endOffset":274025,"count":0}],"isBlockCoverage":false},{"functionName":"_AcceptStructuredClone_walk_closure","ranges":[{"startOffset":274068,"endOffset":274175,"count":1}],"isBlockCoverage":true},{"functionName":"_StructuredCloneDart2Js","ranges":[{"startOffset":274206,"endOffset":274302,"count":1}],"isBlockCoverage":true},{"functionName":"_AcceptStructuredCloneDart2Js","ranges":[{"startOffset":274339,"endOffset":274470,"count":1}],"isBlockCoverage":true},{"functionName":"_convertDataTree","ranges":[{"startOffset":274494,"endOffset":274639,"count":1}],"isBlockCoverage":true},{"functionName":"promiseToFuture","ranges":[{"startOffset":274662,"endOffset":275033,"count":0}],"isBlockCoverage":false},{"functionName":"_convertDataTree__convert","ranges":[{"startOffset":275066,"endOffset":275147,"count":1}],"isBlockCoverage":true},{"functionName":"promiseToFuture_closure","ranges":[{"startOffset":275178,"endOffset":275272,"count":0}],"isBlockCoverage":false},{"functionName":"promiseToFuture_closure0","ranges":[{"startOffset":275304,"endOffset":275376,"count":0}],"isBlockCoverage":false},{"functionName":"ByteBuffer","ranges":[{"startOffset":275394,"endOffset":275423,"count":0}],"isBlockCoverage":false},{"functionName":"ByteData","ranges":[{"startOffset":275439,"endOffset":275466,"count":0}],"isBlockCoverage":false},{"functionName":"Int8List","ranges":[{"startOffset":275482,"endOffset":275509,"count":0}],"isBlockCoverage":false},{"functionName":"Uint8List","ranges":[{"startOffset":275526,"endOffset":275554,"count":0}],"isBlockCoverage":false},{"functionName":"Uint8ClampedList","ranges":[{"startOffset":275578,"endOffset":275613,"count":0}],"isBlockCoverage":false},{"functionName":"Int16List","ranges":[{"startOffset":275630,"endOffset":275658,"count":0}],"isBlockCoverage":false},{"functionName":"Uint16List","ranges":[{"startOffset":275676,"endOffset":275705,"count":0}],"isBlockCoverage":false},{"functionName":"Int32List","ranges":[{"startOffset":275722,"endOffset":275750,"count":0}],"isBlockCoverage":false},{"functionName":"Uint32List","ranges":[{"startOffset":275768,"endOffset":275797,"count":0}],"isBlockCoverage":false},{"functionName":"Float32List","ranges":[{"startOffset":275816,"endOffset":275846,"count":0}],"isBlockCoverage":false},{"functionName":"Float64List","ranges":[{"startOffset":275865,"endOffset":275895,"count":0}],"isBlockCoverage":false},{"functionName":"SqlError","ranges":[{"startOffset":275911,"endOffset":275938,"count":0}],"isBlockCoverage":false},{"functionName":"max","ranges":[{"startOffset":275949,"endOffset":276119,"count":0}],"isBlockCoverage":false},{"functionName":"pow","ranges":[{"startOffset":276130,"endOffset":276195,"count":0}],"isBlockCoverage":false},{"functionName":"_EventStreamSubscription$","ranges":[{"startOffset":276240,"endOffset":276575,"count":1},{"startOffset":276327,"endOffset":276333,"count":0}],"isBlockCoverage":true},{"functionName":"_wrapZone","ranges":[{"startOffset":276592,"endOffset":276771,"count":1},{"startOffset":276705,"endOffset":276770,"count":0}],"isBlockCoverage":true},{"functionName":"ApplicationCacheErrorEvent","ranges":[{"startOffset":276805,"endOffset":276850,"count":0}],"isBlockCoverage":false},{"functionName":"Blob","ranges":[{"startOffset":276862,"endOffset":276885,"count":0}],"isBlockCoverage":false},{"functionName":"DomError","ranges":[{"startOffset":276901,"endOffset":276928,"count":0}],"isBlockCoverage":false},{"functionName":"DomException","ranges":[{"startOffset":276948,"endOffset":276979,"count":0}],"isBlockCoverage":false},{"functionName":"ErrorEvent","ranges":[{"startOffset":276997,"endOffset":277026,"count":0}],"isBlockCoverage":false},{"functionName":"Event","ranges":[{"startOffset":277039,"endOffset":277063,"count":0}],"isBlockCoverage":false},{"functionName":"EventTarget","ranges":[{"startOffset":277082,"endOffset":277112,"count":0}],"isBlockCoverage":false},{"functionName":"File","ranges":[{"startOffset":277124,"endOffset":277147,"count":0}],"isBlockCoverage":false},{"functionName":"Location","ranges":[{"startOffset":277163,"endOffset":277190,"count":0}],"isBlockCoverage":false},{"functionName":"MediaError","ranges":[{"startOffset":277208,"endOffset":277237,"count":0}],"isBlockCoverage":false},{"functionName":"MediaKeyMessageEvent","ranges":[{"startOffset":277265,"endOffset":277304,"count":0}],"isBlockCoverage":false},{"functionName":"MessageEvent","ranges":[{"startOffset":277324,"endOffset":277355,"count":0}],"isBlockCoverage":false},{"functionName":"MessagePort","ranges":[{"startOffset":277374,"endOffset":277404,"count":0}],"isBlockCoverage":false},{"functionName":"NavigatorUserMediaError","ranges":[{"startOffset":277435,"endOffset":277477,"count":0}],"isBlockCoverage":false},{"functionName":"OverconstrainedError","ranges":[{"startOffset":277505,"endOffset":277544,"count":0}],"isBlockCoverage":false},{"functionName":"PositionError","ranges":[{"startOffset":277565,"endOffset":277597,"count":0}],"isBlockCoverage":false},{"functionName":"PresentationConnectionCloseEvent","ranges":[{"startOffset":277637,"endOffset":277688,"count":0}],"isBlockCoverage":false},{"functionName":"SpeechRecognitionError","ranges":[{"startOffset":277718,"endOffset":277759,"count":0}],"isBlockCoverage":false},{"functionName":"EventStreamProvider","ranges":[{"startOffset":277786,"endOffset":277847,"count":0}],"isBlockCoverage":false},{"functionName":"_EventStream","ranges":[{"startOffset":277867,"endOffset":278029,"count":1}],"isBlockCoverage":true},{"functionName":"_EventStreamSubscription","ranges":[{"startOffset":278061,"endOffset":278292,"count":1}],"isBlockCoverage":true},{"functionName":"_EventStreamSubscription_closure","ranges":[{"startOffset":278332,"endOffset":278409,"count":1}],"isBlockCoverage":true},{"functionName":"AsyncMemoizer","ranges":[{"startOffset":278437,"endOffset":278540,"count":0}],"isBlockCoverage":false},{"functionName":"NullStreamSink","ranges":[{"startOffset":278558,"endOffset":278715,"count":0}],"isBlockCoverage":false},{"functionName":"NullStreamSink_addStream_closure","ranges":[{"startOffset":278751,"endOffset":278827,"count":0}],"isBlockCoverage":false},{"functionName":"Validator","ranges":[{"startOffset":278840,"endOffset":278898,"count":0}],"isBlockCoverage":false},{"functionName":"SpanScanner$","ranges":[{"startOffset":278918,"endOffset":279265,"count":0}],"isBlockCoverage":false},{"functionName":"SpanScanner","ranges":[{"startOffset":279284,"endOffset":279530,"count":0}],"isBlockCoverage":false},{"functionName":"_SpanScannerState","ranges":[{"startOffset":279555,"endOffset":279663,"count":0}],"isBlockCoverage":false},{"functionName":"RemoteListener_start","ranges":[{"startOffset":279691,"endOffset":280824,"count":1}],"isBlockCoverage":true},{"functionName":"RemoteListener__deserializeSet","ranges":[{"startOffset":280862,"endOffset":281054,"count":1},{"startOffset":280911,"endOffset":280923,"count":0},{"startOffset":280979,"endOffset":281053,"count":0}],"isBlockCoverage":true},{"functionName":"RemoteListener__sendLoadException","ranges":[{"startOffset":281095,"endOffset":281308,"count":0}],"isBlockCoverage":false},{"functionName":"RemoteListener__sendError","ranges":[{"startOffset":281341,"endOffset":281720,"count":0}],"isBlockCoverage":false},{"functionName":"RemoteListener","ranges":[{"startOffset":281742,"endOffset":281833,"count":1}],"isBlockCoverage":true},{"functionName":"RemoteListener_start_closure","ranges":[{"startOffset":281869,"endOffset":281974,"count":1}],"isBlockCoverage":true},{"functionName":"RemoteListener_start_closure0","ranges":[{"startOffset":282011,"endOffset":282059,"count":1}],"isBlockCoverage":true},{"functionName":"RemoteListener_start_closure1","ranges":[{"startOffset":282096,"endOffset":282348,"count":1}],"isBlockCoverage":true},{"functionName":"RemoteListener_start__closure","ranges":[{"startOffset":282385,"endOffset":282637,"count":1}],"isBlockCoverage":true},{"functionName":"RemoteListener_start___closure","ranges":[{"startOffset":282675,"endOffset":282905,"count":1}],"isBlockCoverage":true},{"functionName":"RemoteListener_start____closure","ranges":[{"startOffset":282944,"endOffset":283053,"count":1}],"isBlockCoverage":true},{"functionName":"RemoteListener_start____closure0","ranges":[{"startOffset":283093,"endOffset":283229,"count":1}],"isBlockCoverage":true},{"functionName":"RemoteListener_start_____closure","ranges":[{"startOffset":283269,"endOffset":283405,"count":1}],"isBlockCoverage":true},{"functionName":"RemoteListener_start___closure0","ranges":[{"startOffset":283444,"endOffset":283549,"count":1}],"isBlockCoverage":true},{"functionName":"RemoteListener__serializeGroup_closure","ranges":[{"startOffset":283595,"endOffset":283734,"count":1}],"isBlockCoverage":true},{"functionName":"RemoteListener__serializeTest_closure","ranges":[{"startOffset":283779,"endOffset":283951,"count":1}],"isBlockCoverage":true},{"functionName":"RemoteListener__runLiveTest_closure","ranges":[{"startOffset":283994,"endOffset":284076,"count":1}],"isBlockCoverage":true},{"functionName":"RemoteListener__runLiveTest_closure0","ranges":[{"startOffset":284120,"endOffset":284202,"count":1}],"isBlockCoverage":true},{"functionName":"RemoteListener__runLiveTest_closure1","ranges":[{"startOffset":284246,"endOffset":284358,"count":1}],"isBlockCoverage":true},{"functionName":"RemoteListener__runLiveTest_closure2","ranges":[{"startOffset":284402,"endOffset":284511,"count":1}],"isBlockCoverage":true},{"functionName":"RemoteListener__runLiveTest_closure3","ranges":[{"startOffset":284555,"endOffset":284667,"count":1}],"isBlockCoverage":true},{"functionName":"RemoteListener__runLiveTest__closure","ranges":[{"startOffset":284711,"endOffset":284793,"count":1}],"isBlockCoverage":true},{"functionName":"DelegatingSink","ranges":[{"startOffset":284822,"endOffset":284911,"count":0}],"isBlockCoverage":false},{"functionName":"None","ranges":[{"startOffset":284919,"endOffset":284942,"count":1}],"isBlockCoverage":true},{"functionName":"Scanner","ranges":[{"startOffset":284953,"endOffset":285079,"count":0}],"isBlockCoverage":false},{"functionName":"EmptyUnmodifiableSet","ranges":[{"startOffset":285103,"endOffset":285165,"count":1}],"isBlockCoverage":true},{"functionName":"Style__getPlatformStyle","ranges":[{"startOffset":285196,"endOffset":285573,"count":0}],"isBlockCoverage":false},{"functionName":"Style","ranges":[{"startOffset":285586,"endOffset":285610,"count":0}],"isBlockCoverage":false},{"functionName":"Pool$","ranges":[{"startOffset":285623,"endOffset":286231,"count":0}],"isBlockCoverage":false},{"functionName":"Pool","ranges":[{"startOffset":286243,"endOffset":286547,"count":0}],"isBlockCoverage":false},{"functionName":"Pool_close_closure","ranges":[{"startOffset":286573,"endOffset":286635,"count":0}],"isBlockCoverage":false},{"functionName":"Pool__onResourceReleaseAllowed_closure","ranges":[{"startOffset":286681,"endOffset":286794,"count":0}],"isBlockCoverage":false},{"functionName":"Pool__runOnRelease_closure","ranges":[{"startOffset":286828,"endOffset":286898,"count":0}],"isBlockCoverage":false},{"functionName":"Pool__runOnRelease_closure0","ranges":[{"startOffset":286933,"endOffset":287004,"count":0}],"isBlockCoverage":false},{"functionName":"PoolResource","ranges":[{"startOffset":287024,"endOffset":287110,"count":0}],"isBlockCoverage":false},{"functionName":"mapStackTrace","ranges":[{"startOffset":287131,"endOffset":288220,"count":0}],"isBlockCoverage":false},{"functionName":"_prettifyMember","ranges":[{"startOffset":288243,"endOffset":289263,"count":0}],"isBlockCoverage":false},{"functionName":"mapStackTrace_closure","ranges":[{"startOffset":289292,"endOffset":289456,"count":0}],"isBlockCoverage":false},{"functionName":"mapStackTrace_closure0","ranges":[{"startOffset":289486,"endOffset":289676,"count":0}],"isBlockCoverage":false},{"functionName":"mapStackTrace_closure1","ranges":[{"startOffset":289706,"endOffset":289747,"count":0}],"isBlockCoverage":false},{"functionName":"_prettifyMember_closure","ranges":[{"startOffset":289778,"endOffset":289820,"count":0}],"isBlockCoverage":false},{"functionName":"_prettifyMember_closure0","ranges":[{"startOffset":289852,"endOffset":289895,"count":0}],"isBlockCoverage":false},{"functionName":"StackZoneSpecification","ranges":[{"startOffset":289925,"endOffset":290121,"count":1}],"isBlockCoverage":true},{"functionName":"StackZoneSpecification_chainFor_closure","ranges":[{"startOffset":290168,"endOffset":290252,"count":0}],"isBlockCoverage":false},{"functionName":"StackZoneSpecification_chainFor_closure0","ranges":[{"startOffset":290300,"endOffset":290414,"count":0}],"isBlockCoverage":false},{"functionName":"StackZoneSpecification__registerCallback_closure","ranges":[{"startOffset":290470,"endOffset":290642,"count":1}],"isBlockCoverage":true},{"functionName":"StackZoneSpecification__registerUnaryCallback_closure","ranges":[{"startOffset":290703,"endOffset":290900,"count":1}],"isBlockCoverage":true},{"functionName":"StackZoneSpecification__registerUnaryCallback__closure","ranges":[{"startOffset":290962,"endOffset":291104,"count":1}],"isBlockCoverage":true},{"functionName":"StackZoneSpecification__registerBinaryCallback_closure","ranges":[{"startOffset":291166,"endOffset":291386,"count":1}],"isBlockCoverage":true},{"functionName":"StackZoneSpecification__registerBinaryCallback__closure","ranges":[{"startOffset":291449,"endOffset":291627,"count":1}],"isBlockCoverage":true},{"functionName":"StackZoneSpecification__currentTrace_closure","ranges":[{"startOffset":291679,"endOffset":291827,"count":1}],"isBlockCoverage":true},{"functionName":"_Node","ranges":[{"startOffset":291840,"endOffset":291919,"count":1}],"isBlockCoverage":true},{"functionName":"Group$","ranges":[{"startOffset":291933,"endOffset":292150,"count":1}],"isBlockCoverage":true},{"functionName":"Group","ranges":[{"startOffset":292163,"endOffset":292362,"count":1}],"isBlockCoverage":true},{"functionName":"Group_forPlatform_closure","ranges":[{"startOffset":292395,"endOffset":292467,"count":1}],"isBlockCoverage":true},{"functionName":"Group__map_closure","ranges":[{"startOffset":292493,"endOffset":292558,"count":1}],"isBlockCoverage":true},{"functionName":"Group__map_closure0","ranges":[{"startOffset":292585,"endOffset":292623,"count":1}],"isBlockCoverage":true},{"functionName":"Metadata__parseOnPlatform","ranges":[{"startOffset":292656,"endOffset":292775,"count":1}],"isBlockCoverage":true},{"functionName":"Metadata__parseTags","ranges":[{"startOffset":292802,"endOffset":292889,"count":1}],"isBlockCoverage":true},{"functionName":"Metadata_Metadata","ranges":[{"startOffset":292914,"endOffset":293928,"count":1},{"startOffset":293321,"endOffset":293340,"count":0},{"startOffset":293880,"endOffset":293927,"count":0}],"isBlockCoverage":true},{"functionName":"Metadata$_","ranges":[{"startOffset":293946,"endOffset":294846,"count":1},{"startOffset":294749,"endOffset":294795,"count":0}],"isBlockCoverage":true},{"functionName":"Metadata$parse","ranges":[{"startOffset":294868,"endOffset":295398,"count":1},{"startOffset":294999,"endOffset":295008,"count":0},{"startOffset":295061,"endOffset":295067,"count":0},{"startOffset":295301,"endOffset":295347,"count":0}],"isBlockCoverage":true},{"functionName":"Metadata$deserialize","ranges":[{"startOffset":295426,"endOffset":296886,"count":1},{"startOffset":295595,"endOffset":295675,"count":0},{"startOffset":296451,"endOffset":296672,"count":0}],"isBlockCoverage":true},{"functionName":"Metadata__deserializeTimeout","ranges":[{"startOffset":296922,"endOffset":297350,"count":1},{"startOffset":297058,"endOffset":297085,"count":0},{"startOffset":297241,"endOffset":297349,"count":0}],"isBlockCoverage":true},{"functionName":"Metadata","ranges":[{"startOffset":297366,"endOffset":297685,"count":1}],"isBlockCoverage":true},{"functionName":"Metadata_Metadata__unresolved","ranges":[{"startOffset":297722,"endOffset":298035,"count":1}],"isBlockCoverage":true},{"functionName":"Metadata_Metadata_closure","ranges":[{"startOffset":298068,"endOffset":298138,"count":1}],"isBlockCoverage":true},{"functionName":"Metadata$deserialize_closure","ranges":[{"startOffset":298174,"endOffset":298221,"count":1}],"isBlockCoverage":true},{"functionName":"Metadata__validateTags_closure","ranges":[{"startOffset":298259,"endOffset":298308,"count":1}],"isBlockCoverage":true},{"functionName":"Metadata__validateTags_closure0","ranges":[{"startOffset":298347,"endOffset":298397,"count":1}],"isBlockCoverage":true},{"functionName":"Metadata_validatePlatformSelectors_closure","ranges":[{"startOffset":298447,"endOffset":298542,"count":1}],"isBlockCoverage":true},{"functionName":"Metadata_merge_closure","ranges":[{"startOffset":298572,"endOffset":298613,"count":1}],"isBlockCoverage":true},{"functionName":"Metadata_merge_closure0","ranges":[{"startOffset":298644,"endOffset":298686,"count":1}],"isBlockCoverage":true},{"functionName":"Metadata_forPlatform_closure","ranges":[{"startOffset":298722,"endOffset":298825,"count":0}],"isBlockCoverage":false},{"functionName":"Metadata_serialize_closure","ranges":[{"startOffset":298859,"endOffset":298944,"count":1}],"isBlockCoverage":true},{"functionName":"Metadata_serialize_closure0","ranges":[{"startOffset":298979,"endOffset":299025,"count":1}],"isBlockCoverage":true},{"functionName":"IterableSet","ranges":[{"startOffset":299044,"endOffset":299138,"count":0}],"isBlockCoverage":false},{"functionName":"_IterableSet_SetMixin_UnmodifiableSetMixin","ranges":[{"startOffset":299188,"endOffset":299249,"count":0}],"isBlockCoverage":false},{"functionName":"Engine$","ranges":[{"startOffset":299264,"endOffset":300874,"count":0}],"isBlockCoverage":false},{"functionName":"Engine","ranges":[{"startOffset":300888,"endOffset":301558,"count":0}],"isBlockCoverage":false},{"functionName":"Engine_success_closure","ranges":[{"startOffset":301588,"endOffset":301629,"count":0}],"isBlockCoverage":false},{"functionName":"Engine_closure","ranges":[{"startOffset":301651,"endOffset":301709,"count":0}],"isBlockCoverage":false},{"functionName":"Engine_closure0","ranges":[{"startOffset":301732,"endOffset":301766,"count":0}],"isBlockCoverage":false},{"functionName":"Engine_run_closure","ranges":[{"startOffset":301792,"endOffset":301854,"count":0}],"isBlockCoverage":false},{"functionName":"Engine_run__closure","ranges":[{"startOffset":301881,"endOffset":301971,"count":0}],"isBlockCoverage":false},{"functionName":"Engine_run___closure","ranges":[{"startOffset":301999,"endOffset":302125,"count":0}],"isBlockCoverage":false},{"functionName":"Engine_run____closure","ranges":[{"startOffset":302154,"endOffset":302220,"count":0}],"isBlockCoverage":false},{"functionName":"Engine_run_closure0","ranges":[{"startOffset":302247,"endOffset":302338,"count":0}],"isBlockCoverage":false},{"functionName":"Engine__runLiveTest_closure","ranges":[{"startOffset":302373,"endOffset":302474,"count":0}],"isBlockCoverage":false},{"functionName":"Engine__runLiveTest_closure0","ranges":[{"startOffset":302510,"endOffset":302610,"count":0}],"isBlockCoverage":false},{"functionName":"Engine__runLiveTest_closure1","ranges":[{"startOffset":302646,"endOffset":302693,"count":0}],"isBlockCoverage":false},{"functionName":"Engine__runSkippedTest_closure","ranges":[{"startOffset":302731,"endOffset":302780,"count":0}],"isBlockCoverage":false},{"functionName":"Engine__runSkippedTest_closure0","ranges":[{"startOffset":302819,"endOffset":302924,"count":0}],"isBlockCoverage":false},{"functionName":"Engine__runSkippedTest_closure1","ranges":[{"startOffset":302963,"endOffset":303013,"count":0}],"isBlockCoverage":false},{"functionName":"binarySearch","ranges":[{"startOffset":303033,"endOffset":303712,"count":0}],"isBlockCoverage":false},{"functionName":"DelegatingStreamSubscription","ranges":[{"startOffset":303755,"endOffset":303802,"count":0}],"isBlockCoverage":false},{"functionName":"StreamCompleter","ranges":[{"startOffset":303821,"endOffset":303907,"count":1}],"isBlockCoverage":true},{"functionName":"_CompleterStream","ranges":[{"startOffset":303927,"endOffset":304055,"count":1}],"isBlockCoverage":true},{"functionName":"BooleanSelectorImpl","ranges":[{"startOffset":304078,"endOffset":304145,"count":0}],"isBlockCoverage":false},{"functionName":"mapMap","ranges":[{"startOffset":304159,"endOffset":304498,"count":1}],"isBlockCoverage":true},{"functionName":"mergeMaps","ranges":[{"startOffset":304515,"endOffset":304721,"count":1}],"isBlockCoverage":true},{"functionName":"mapMap_closure","ranges":[{"startOffset":304743,"endOffset":304846,"count":1}],"isBlockCoverage":true},{"functionName":"mapMap_closure0","ranges":[{"startOffset":304869,"endOffset":305013,"count":1}],"isBlockCoverage":true},{"functionName":"mergeMaps_closure","ranges":[{"startOffset":305038,"endOffset":305181,"count":1}],"isBlockCoverage":true},{"functionName":"UnionSetController$","ranges":[{"startOffset":305208,"endOffset":305497,"count":0}],"isBlockCoverage":false},{"functionName":"UnionSetController","ranges":[{"startOffset":305523,"endOffset":305678,"count":0}],"isBlockCoverage":false},{"functionName":"_IsTrue","ranges":[{"startOffset":305693,"endOffset":305719,"count":1}],"isBlockCoverage":true},{"functionName":"_Predicate","ranges":[{"startOffset":305737,"endOffset":305868,"count":0}],"isBlockCoverage":false},{"functionName":"FileLocation$_","ranges":[{"startOffset":305890,"endOffset":306294,"count":0}],"isBlockCoverage":false},{"functionName":"_FileSpan$","ranges":[{"startOffset":306312,"endOffset":306850,"count":0}],"isBlockCoverage":false},{"functionName":"SourceFile","ranges":[{"startOffset":306868,"endOffset":307027,"count":0}],"isBlockCoverage":false},{"functionName":"FileLocation","ranges":[{"startOffset":307047,"endOffset":307130,"count":0}],"isBlockCoverage":false},{"functionName":"_FileSpan","ranges":[{"startOffset":307147,"endOffset":307265,"count":0}],"isBlockCoverage":false},{"functionName":"SourceSpanMixin","ranges":[{"startOffset":307288,"endOffset":307322,"count":0}],"isBlockCoverage":false},{"functionName":"Trace_Trace$current","ranges":[{"startOffset":307349,"endOffset":307488,"count":0}],"isBlockCoverage":false},{"functionName":"Trace_Trace$from","ranges":[{"startOffset":307512,"endOffset":307838,"count":1},{"startOffset":307563,"endOffset":307639,"count":0},{"startOffset":307695,"endOffset":307837,"count":0}],"isBlockCoverage":true},{"functionName":"Trace_Trace$parse","ranges":[{"startOffset":307863,"endOffset":309377,"count":0}],"isBlockCoverage":false},{"functionName":"Trace__parseVM","ranges":[{"startOffset":309399,"endOffset":310090,"count":0}],"isBlockCoverage":false},{"functionName":"Trace$parseV8","ranges":[{"startOffset":310111,"endOffset":310662,"count":0}],"isBlockCoverage":false},{"functionName":"Trace$parseJSCore","ranges":[{"startOffset":310687,"endOffset":311118,"count":0}],"isBlockCoverage":false},{"functionName":"Trace$parseFirefox","ranges":[{"startOffset":311144,"endOffset":311604,"count":0}],"isBlockCoverage":false},{"functionName":"Trace$parseFriendly","ranges":[{"startOffset":311631,"endOffset":312181,"count":0}],"isBlockCoverage":false},{"functionName":"Trace","ranges":[{"startOffset":312194,"endOffset":312274,"count":0}],"isBlockCoverage":false},{"functionName":"Trace_Trace$current_closure","ranges":[{"startOffset":312309,"endOffset":312407,"count":0}],"isBlockCoverage":false},{"functionName":"Trace_Trace$from_closure","ranges":[{"startOffset":312439,"endOffset":312507,"count":0}],"isBlockCoverage":false},{"functionName":"Trace__parseVM_closure","ranges":[{"startOffset":312537,"endOffset":312578,"count":0}],"isBlockCoverage":false},{"functionName":"Trace$parseV8_closure","ranges":[{"startOffset":312607,"endOffset":312647,"count":0}],"isBlockCoverage":false},{"functionName":"Trace$parseV8_closure0","ranges":[{"startOffset":312677,"endOffset":312718,"count":0}],"isBlockCoverage":false},{"functionName":"Trace$parseJSCore_closure","ranges":[{"startOffset":312751,"endOffset":312795,"count":0}],"isBlockCoverage":false},{"functionName":"Trace$parseJSCore_closure0","ranges":[{"startOffset":312829,"endOffset":312874,"count":0}],"isBlockCoverage":false},{"functionName":"Trace$parseFirefox_closure","ranges":[{"startOffset":312908,"endOffset":312953,"count":0}],"isBlockCoverage":false},{"functionName":"Trace$parseFirefox_closure0","ranges":[{"startOffset":312988,"endOffset":313034,"count":0}],"isBlockCoverage":false},{"functionName":"Trace$parseFriendly_closure","ranges":[{"startOffset":313069,"endOffset":313115,"count":0}],"isBlockCoverage":false},{"functionName":"Trace$parseFriendly_closure0","ranges":[{"startOffset":313151,"endOffset":313198,"count":0}],"isBlockCoverage":false},{"functionName":"Trace_foldFrames_closure","ranges":[{"startOffset":313230,"endOffset":313305,"count":0}],"isBlockCoverage":false},{"functionName":"Trace_foldFrames_closure0","ranges":[{"startOffset":313338,"endOffset":313408,"count":0}],"isBlockCoverage":false},{"functionName":"Trace_toString_closure0","ranges":[{"startOffset":313439,"endOffset":313481,"count":0}],"isBlockCoverage":false},{"functionName":"Trace_toString_closure","ranges":[{"startOffset":313511,"endOffset":313579,"count":0}],"isBlockCoverage":false},{"functionName":"RunnerSuite","ranges":[{"startOffset":313598,"endOffset":313764,"count":0}],"isBlockCoverage":false},{"functionName":"RunnerSuiteController","ranges":[{"startOffset":313793,"endOffset":314020,"count":0}],"isBlockCoverage":false},{"functionName":"RunnerSuiteController__close_closure","ranges":[{"startOffset":314064,"endOffset":314144,"count":0}],"isBlockCoverage":false},{"functionName":"FutureGroup","ranges":[{"startOffset":314170,"endOffset":314384,"count":0}],"isBlockCoverage":false},{"functionName":"FutureGroup_add_closure","ranges":[{"startOffset":314411,"endOffset":314505,"count":0}],"isBlockCoverage":false},{"functionName":"FutureGroup_add_closure0","ranges":[{"startOffset":314533,"endOffset":314601,"count":0}],"isBlockCoverage":false},{"functionName":"ValueResult","ranges":[{"startOffset":314616,"endOffset":314696,"count":1}],"isBlockCoverage":true},{"functionName":"PackageConfigResolver__normalizeMap","ranges":[{"startOffset":314739,"endOffset":314975,"count":1}],"isBlockCoverage":true},{"functionName":"PackageConfigResolver","ranges":[{"startOffset":315004,"endOffset":315080,"count":1}],"isBlockCoverage":true},{"functionName":"PackageConfigResolver__normalizeMap_closure","ranges":[{"startOffset":315131,"endOffset":315193,"count":1}],"isBlockCoverage":true},{"functionName":"UrlStyle","ranges":[{"startOffset":315209,"endOffset":315397,"count":0}],"isBlockCoverage":false},{"functionName":"ErrorResult","ranges":[{"startOffset":315423,"endOffset":315510,"count":0}],"isBlockCoverage":false},{"functionName":"SourceLocation$","ranges":[{"startOffset":315533,"endOffset":316255,"count":0}],"isBlockCoverage":false},{"functionName":"SourceLocation","ranges":[{"startOffset":316277,"endOffset":316429,"count":0}],"isBlockCoverage":false},{"functionName":"SourceSpan","ranges":[{"startOffset":316447,"endOffset":316476,"count":0}],"isBlockCoverage":false},{"functionName":"SourceSpanBase","ranges":[{"startOffset":316498,"endOffset":316531,"count":0}],"isBlockCoverage":false},{"functionName":"GroupEntry","ranges":[{"startOffset":316549,"endOffset":316578,"count":0}],"isBlockCoverage":false},{"functionName":"LiveTestController$","ranges":[{"startOffset":316605,"endOffset":317396,"count":1}],"isBlockCoverage":true},{"functionName":"_LiveTest","ranges":[{"startOffset":317413,"endOffset":317494,"count":1}],"isBlockCoverage":true},{"functionName":"LiveTestController","ranges":[{"startOffset":317520,"endOffset":318000,"count":1}],"isBlockCoverage":true},{"functionName":"Test","ranges":[{"startOffset":318012,"endOffset":318035,"count":0}],"isBlockCoverage":false},{"functionName":"errorsDontStopTest","ranges":[{"startOffset":318061,"endOffset":318525,"count":0}],"isBlockCoverage":false},{"functionName":"errorsDontStopTest_closure","ranges":[{"startOffset":318559,"endOffset":318659,"count":0}],"isBlockCoverage":false},{"functionName":"errorsDontStopTest_closure0","ranges":[{"startOffset":318694,"endOffset":318740,"count":0}],"isBlockCoverage":false},{"functionName":"Result","ranges":[{"startOffset":318761,"endOffset":318786,"count":0}],"isBlockCoverage":false},{"functionName":"StringDescription","ranges":[{"startOffset":318807,"endOffset":318867,"count":0}],"isBlockCoverage":false},{"functionName":"FeatureMatcher","ranges":[{"startOffset":318885,"endOffset":318918,"count":0}],"isBlockCoverage":false},{"functionName":"PosixStyle","ranges":[{"startOffset":318932,"endOffset":319073,"count":0}],"isBlockCoverage":false},{"functionName":"StringScannerException$","ranges":[{"startOffset":319104,"endOffset":319201,"count":0}],"isBlockCoverage":false},{"functionName":"StringScannerException","ranges":[{"startOffset":319231,"endOffset":319359,"count":0}],"isBlockCoverage":false},{"functionName":"PlatformSelector$parse","ranges":[{"startOffset":319389,"endOffset":319570,"count":0}],"isBlockCoverage":false},{"functionName":"PlatformSelector__wrapFormatException","ranges":[{"startOffset":319615,"endOffset":319694,"count":0}],"isBlockCoverage":false},{"functionName":"PlatformSelector","ranges":[{"startOffset":319718,"endOffset":319798,"count":1}],"isBlockCoverage":true},{"functionName":"PlatformSelector$parse_closure","ranges":[{"startOffset":319836,"endOffset":319913,"count":0}],"isBlockCoverage":false},{"functionName":"PlatformSelector_validate_closure","ranges":[{"startOffset":319954,"endOffset":320067,"count":0}],"isBlockCoverage":false},{"functionName":"PlatformSelector_validate__closure","ranges":[{"startOffset":320109,"endOffset":320196,"count":0}],"isBlockCoverage":false},{"functionName":"PlatformSelector_evaluate_closure","ranges":[{"startOffset":320237,"endOffset":320317,"count":1}],"isBlockCoverage":true},{"functionName":"SuitePlatform$","ranges":[{"startOffset":320339,"endOffset":320703,"count":1},{"startOffset":320429,"endOffset":320433,"count":0},{"startOffset":320533,"endOffset":320640,"count":0}],"isBlockCoverage":true},{"functionName":"SuitePlatform","ranges":[{"startOffset":320724,"endOffset":320837,"count":1}],"isBlockCoverage":true},{"functionName":"StackTraceMapper","ranges":[{"startOffset":320861,"endOffset":320896,"count":0}],"isBlockCoverage":false},{"functionName":"LiveSuite","ranges":[{"startOffset":320913,"endOffset":320941,"count":0}],"isBlockCoverage":false},{"functionName":"JSStackTraceMapper_deserialize","ranges":[{"startOffset":320979,"endOffset":321921,"count":1},{"startOffset":321375,"endOffset":321508,"count":0}],"isBlockCoverage":true},{"functionName":"JSStackTraceMapper__deserializePackageConfigMap","ranges":[{"startOffset":321976,"endOffset":322130,"count":1}],"isBlockCoverage":true},{"functionName":"JSStackTraceMapper","ranges":[{"startOffset":322156,"endOffset":322355,"count":1}],"isBlockCoverage":true},{"functionName":"JSStackTraceMapper__deserializePackageConfigMap_closure","ranges":[{"startOffset":322418,"endOffset":322492,"count":1}],"isBlockCoverage":true},{"functionName":"StreamGroup","ranges":[{"startOffset":322518,"endOffset":322755,"count":0}],"isBlockCoverage":false},{"functionName":"StreamGroup_add_closure","ranges":[{"startOffset":322782,"endOffset":322824,"count":0}],"isBlockCoverage":false},{"functionName":"StreamGroup_add_closure0","ranges":[{"startOffset":322852,"endOffset":322948,"count":0}],"isBlockCoverage":false},{"functionName":"StreamGroup__onListen_closure","ranges":[{"startOffset":322981,"endOffset":323054,"count":0}],"isBlockCoverage":false},{"functionName":"StreamGroup__onCancelBroadcast_closure","ranges":[{"startOffset":323096,"endOffset":323178,"count":0}],"isBlockCoverage":false},{"functionName":"StreamGroup__listenToStream_closure","ranges":[{"startOffset":323217,"endOffset":323324,"count":0}],"isBlockCoverage":false},{"functionName":"_StreamGroupState","ranges":[{"startOffset":323345,"endOffset":323405,"count":1}],"isBlockCoverage":true},{"functionName":"Token","ranges":[{"startOffset":323414,"endOffset":323488,"count":0}],"isBlockCoverage":false},{"functionName":"IdentifierToken","ranges":[{"startOffset":323507,"endOffset":323591,"count":0}],"isBlockCoverage":false},{"functionName":"TokenType","ranges":[{"startOffset":323604,"endOffset":323656,"count":1}],"isBlockCoverage":true},{"functionName":"UnmodifiableSetView$","ranges":[{"startOffset":323684,"endOffset":323800,"count":0}],"isBlockCoverage":false},{"functionName":"UnmodifiableSetView","ranges":[{"startOffset":323827,"endOffset":323915,"count":1}],"isBlockCoverage":true},{"functionName":"UnmodifiableSetMixin","ranges":[{"startOffset":323943,"endOffset":323982,"count":0}],"isBlockCoverage":false},{"functionName":"_UnmodifiableSetView_DelegatingSet_UnmodifiableSetMixin","ranges":[{"startOffset":324045,"endOffset":324119,"count":0}],"isBlockCoverage":false},{"functionName":"WindowsStyle","ranges":[{"startOffset":324139,"endOffset":324331,"count":0}],"isBlockCoverage":false},{"functionName":"WindowsStyle_absolutePathToUri_closure","ranges":[{"startOffset":324377,"endOffset":324434,"count":0}],"isBlockCoverage":false},{"functionName":"decodeVlq","ranges":[{"startOffset":324451,"endOffset":325682,"count":0}],"isBlockCoverage":false},{"functionName":"closure","ranges":[{"startOffset":325697,"endOffset":325723,"count":0}],"isBlockCoverage":false},{"functionName":"internalBootstrapBrowserTest","ranges":[{"startOffset":325759,"endOffset":326211,"count":1}],"isBlockCoverage":true},{"functionName":"internalBootstrapBrowserTest_closure","ranges":[{"startOffset":326255,"endOffset":326310,"count":1}],"isBlockCoverage":true},{"functionName":"StreamQueue","ranges":[{"startOffset":326336,"endOffset":326620,"count":1}],"isBlockCoverage":true},{"functionName":"StreamQueue__ensureListening_closure","ranges":[{"startOffset":326660,"endOffset":326740,"count":1}],"isBlockCoverage":true},{"functionName":"StreamQueue__ensureListening_closure1","ranges":[{"startOffset":326781,"endOffset":326862,"count":1}],"isBlockCoverage":true},{"functionName":"StreamQueue__ensureListening_closure0","ranges":[{"startOffset":326903,"endOffset":326984,"count":1}],"isBlockCoverage":true},{"functionName":"_EventRequest","ranges":[{"startOffset":327001,"endOffset":327033,"count":0}],"isBlockCoverage":false},{"functionName":"_NextRequest","ranges":[{"startOffset":327049,"endOffset":327135,"count":1}],"isBlockCoverage":true},{"functionName":"_RestRequest","ranges":[{"startOffset":327151,"endOffset":327271,"count":1}],"isBlockCoverage":true},{"functionName":"Parser","ranges":[{"startOffset":327281,"endOffset":327343,"count":0}],"isBlockCoverage":false},{"functionName":"Matcher","ranges":[{"startOffset":327354,"endOffset":327380,"count":0}],"isBlockCoverage":false},{"functionName":"SourceMapSpan","ranges":[{"startOffset":327397,"endOffset":327547,"count":0}],"isBlockCoverage":false},{"functionName":"SourceSpanFormatException$","ranges":[{"startOffset":327581,"endOffset":327682,"count":0}],"isBlockCoverage":false},{"functionName":"SourceSpanException","ranges":[{"startOffset":327709,"endOffset":327747,"count":0}],"isBlockCoverage":false},{"functionName":"SourceSpanFormatException","ranges":[{"startOffset":327780,"endOffset":327911,"count":0}],"isBlockCoverage":false},{"functionName":"State","ranges":[{"startOffset":327924,"endOffset":328002,"count":1}],"isBlockCoverage":true},{"functionName":"Status","ranges":[{"startOffset":328016,"endOffset":328065,"count":1}],"isBlockCoverage":true},{"functionName":"Result0","ranges":[{"startOffset":328080,"endOffset":328130,"count":1}],"isBlockCoverage":true},{"functionName":"expect","ranges":[{"startOffset":328144,"endOffset":328244,"count":1}],"isBlockCoverage":true},{"functionName":"_expect","ranges":[{"startOffset":328259,"endOffset":329408,"count":1},{"startOffset":328467,"endOffset":328550,"count":0},{"startOffset":328759,"endOffset":328803,"count":0},{"startOffset":329097,"endOffset":329407,"count":0}],"isBlockCoverage":true},{"functionName":"fail","ranges":[{"startOffset":329420,"endOffset":329505,"count":0}],"isBlockCoverage":false},{"functionName":"formatFailure","ranges":[{"startOffset":329526,"endOffset":330135,"count":0}],"isBlockCoverage":false},{"functionName":"TestFailure","ranges":[{"startOffset":330154,"endOffset":330211,"count":0}],"isBlockCoverage":false},{"functionName":"_expect_closure0","ranges":[{"startOffset":330235,"endOffset":330270,"count":0}],"isBlockCoverage":false},{"functionName":"_expect_closure","ranges":[{"startOffset":330293,"endOffset":330327,"count":1}],"isBlockCoverage":true},{"functionName":"method1","ranges":[{"startOffset":330342,"endOffset":330388,"count":1}],"isBlockCoverage":true},{"functionName":"method2","ranges":[{"startOffset":330403,"endOffset":330449,"count":0}],"isBlockCoverage":false},{"functionName":"main0","ranges":[{"startOffset":330462,"endOffset":330529,"count":1}],"isBlockCoverage":true},{"functionName":"main_closure0","ranges":[{"startOffset":330550,"endOffset":330582,"count":1}],"isBlockCoverage":true},{"functionName":"main__closure","ranges":[{"startOffset":330603,"endOffset":330635,"count":1}],"isBlockCoverage":true},{"functionName":"StreamSinkCompleter","ranges":[{"startOffset":330669,"endOffset":330756,"count":1}],"isBlockCoverage":true},{"functionName":"_CompleterSink","ranges":[{"startOffset":330774,"endOffset":330961,"count":1}],"isBlockCoverage":true},{"functionName":"_CompleterSink__setDestinationSink_closure","ranges":[{"startOffset":331007,"endOffset":331068,"count":0}],"isBlockCoverage":false},{"functionName":"SubscriptionStream","ranges":[{"startOffset":331090,"endOffset":331200,"count":1}],"isBlockCoverage":true},{"functionName":"_CancelOnErrorSubscriptionWrapper","ranges":[{"startOffset":331237,"endOffset":331362,"count":0}],"isBlockCoverage":false},{"functionName":"_CancelOnErrorSubscriptionWrapper_onError_closure","ranges":[{"startOffset":331415,"endOffset":331541,"count":0}],"isBlockCoverage":false},{"functionName":"_CancelOnErrorSubscriptionWrapper_onError__closure","ranges":[{"startOffset":331595,"endOffset":331754,"count":0}],"isBlockCoverage":false},{"functionName":"Evaluator","ranges":[{"startOffset":331767,"endOffset":331825,"count":0}],"isBlockCoverage":false},{"functionName":"parseJsonExtended","ranges":[{"startOffset":331850,"endOffset":332085,"count":0}],"isBlockCoverage":false},{"functionName":"parseJson","ranges":[{"startOffset":332102,"endOffset":332830,"count":0}],"isBlockCoverage":false},{"functionName":"MultiSectionMapping$fromJson","ranges":[{"startOffset":332866,"endOffset":333186,"count":0}],"isBlockCoverage":false},{"functionName":"MappingBundle$fromJson","ranges":[{"startOffset":333216,"endOffset":333428,"count":0}],"isBlockCoverage":false},{"functionName":"SingleMapping$fromJson","ranges":[{"startOffset":333458,"endOffset":334453,"count":0}],"isBlockCoverage":false},{"functionName":"Mapping","ranges":[{"startOffset":334468,"endOffset":334494,"count":0}],"isBlockCoverage":false},{"functionName":"MultiSectionMapping","ranges":[{"startOffset":334521,"endOffset":334650,"count":0}],"isBlockCoverage":false},{"functionName":"MappingBundle","ranges":[{"startOffset":334671,"endOffset":334732,"count":0}],"isBlockCoverage":false},{"functionName":"SingleMapping","ranges":[{"startOffset":334753,"endOffset":335018,"count":0}],"isBlockCoverage":false},{"functionName":"SingleMapping$fromJson_closure","ranges":[{"startOffset":335056,"endOffset":335130,"count":0}],"isBlockCoverage":false},{"functionName":"SingleMapping__findLine_closure","ranges":[{"startOffset":335169,"endOffset":335243,"count":0}],"isBlockCoverage":false},{"functionName":"SingleMapping__findColumn_closure","ranges":[{"startOffset":335284,"endOffset":335362,"count":0}],"isBlockCoverage":false},{"functionName":"TargetLineEntry","ranges":[{"startOffset":335385,"endOffset":335472,"count":0}],"isBlockCoverage":false},{"functionName":"TargetEntry","ranges":[{"startOffset":335491,"endOffset":335685,"count":0}],"isBlockCoverage":false},{"functionName":"_MappingTokenizer","ranges":[{"startOffset":335710,"endOffset":335835,"count":0}],"isBlockCoverage":false},{"functionName":"_TokenKind","ranges":[{"startOffset":335853,"endOffset":335972,"count":1}],"isBlockCoverage":true},{"functionName":"LazyTrace","ranges":[{"startOffset":335989,"endOffset":336093,"count":1}],"isBlockCoverage":true},{"functionName":"LazyTrace_foldFrames_closure","ranges":[{"startOffset":336129,"endOffset":336259,"count":0}],"isBlockCoverage":false},{"functionName":"RuntimeSelection","ranges":[{"startOffset":336283,"endOffset":336318,"count":0}],"isBlockCoverage":false},{"functionName":"BooleanSelector","ranges":[{"startOffset":336348,"endOffset":336382,"count":0}],"isBlockCoverage":false},{"functionName":"All","ranges":[{"startOffset":336389,"endOffset":336411,"count":1}],"isBlockCoverage":true},{"functionName":"ParsedPath_ParsedPath$parse","ranges":[{"startOffset":336446,"endOffset":337648,"count":0}],"isBlockCoverage":false},{"functionName":"ParsedPath","ranges":[{"startOffset":337666,"endOffset":337813,"count":0}],"isBlockCoverage":false},{"functionName":"ParsedPath_normalize_closure","ranges":[{"startOffset":337849,"endOffset":337921,"count":0}],"isBlockCoverage":false},{"functionName":"PathException$","ranges":[{"startOffset":337943,"endOffset":338011,"count":0}],"isBlockCoverage":false},{"functionName":"PathException","ranges":[{"startOffset":338032,"endOffset":338091,"count":0}],"isBlockCoverage":false},{"functionName":"SourceSpanWithContext$","ranges":[{"startOffset":338121,"endOffset":338709,"count":0}],"isBlockCoverage":false},{"functionName":"SourceSpanWithContext","ranges":[{"startOffset":338738,"endOffset":338892,"count":0}],"isBlockCoverage":false},{"functionName":"LazyChain","ranges":[{"startOffset":338909,"endOffset":339001,"count":0}],"isBlockCoverage":false},{"functionName":"LazyChain_foldFrames_closure","ranges":[{"startOffset":339037,"endOffset":339167,"count":0}],"isBlockCoverage":false},{"functionName":"LazyChain_toTrace_closure","ranges":[{"startOffset":339200,"endOffset":339269,"count":0}],"isBlockCoverage":false},{"functionName":"StringScanner","ranges":[{"startOffset":339290,"endOffset":339322,"count":0}],"isBlockCoverage":false},{"functionName":"Declarer$","ranges":[{"startOffset":339339,"endOffset":340044,"count":1},{"startOffset":339457,"endOffset":339548,"count":0},{"startOffset":339600,"endOffset":339626,"count":0}],"isBlockCoverage":true},{"functionName":"Declarer","ranges":[{"startOffset":340060,"endOffset":340568,"count":1}],"isBlockCoverage":true},{"functionName":"Declarer_test_closure","ranges":[{"startOffset":340597,"endOffset":340688,"count":1}],"isBlockCoverage":true},{"functionName":"Declarer_test__closure","ranges":[{"startOffset":340718,"endOffset":340810,"count":1}],"isBlockCoverage":true},{"functionName":"Declarer_test___closure","ranges":[{"startOffset":340841,"endOffset":340934,"count":1}],"isBlockCoverage":true},{"functionName":"Declarer_group_closure","ranges":[{"startOffset":340964,"endOffset":341029,"count":1}],"isBlockCoverage":true},{"functionName":"Declarer_build_closure","ranges":[{"startOffset":341059,"endOffset":341125,"count":1}],"isBlockCoverage":true},{"functionName":"Declarer__runSetUps_closure","ranges":[{"startOffset":341160,"endOffset":341206,"count":1}],"isBlockCoverage":true},{"functionName":"Declarer__tearDownAll_closure","ranges":[{"startOffset":341243,"endOffset":341316,"count":0}],"isBlockCoverage":false},{"functionName":"Declarer__tearDownAll__closure","ranges":[{"startOffset":341354,"endOffset":341428,"count":0}],"isBlockCoverage":false},{"functionName":"Declarer__tearDownAll___closure","ranges":[{"startOffset":341467,"endOffset":341542,"count":0}],"isBlockCoverage":false},{"functionName":"PrintSink","ranges":[{"startOffset":341559,"endOffset":341626,"count":0}],"isBlockCoverage":false},{"functionName":"_expandSafe","ranges":[{"startOffset":341657,"endOffset":341839,"count":0}],"isBlockCoverage":false},{"functionName":"VariableNode","ranges":[{"startOffset":341859,"endOffset":341940,"count":0}],"isBlockCoverage":false},{"functionName":"NotNode","ranges":[{"startOffset":341955,"endOffset":342032,"count":0}],"isBlockCoverage":false},{"functionName":"OrNode","ranges":[{"startOffset":342046,"endOffset":342122,"count":0}],"isBlockCoverage":false},{"functionName":"AndNode","ranges":[{"startOffset":342137,"endOffset":342214,"count":0}],"isBlockCoverage":false},{"functionName":"ConditionalNode","ranges":[{"startOffset":342237,"endOffset":342361,"count":0}],"isBlockCoverage":false},{"functionName":"Highlighter__normalizeNewlines","ranges":[{"startOffset":342399,"endOffset":343195,"count":0}],"isBlockCoverage":false},{"functionName":"Highlighter__normalizeTrailingNewline","ranges":[{"startOffset":343240,"endOffset":344711,"count":0}],"isBlockCoverage":false},{"functionName":"Highlighter__normalizeEndOfLine","ranges":[{"startOffset":344750,"endOffset":345414,"count":0}],"isBlockCoverage":false},{"functionName":"Highlighter__lastLineLength","ranges":[{"startOffset":345449,"endOffset":345775,"count":0}],"isBlockCoverage":false},{"functionName":"Highlighter","ranges":[{"startOffset":345794,"endOffset":345999,"count":0}],"isBlockCoverage":false},{"functionName":"Highlighter__writeFirstLine_closure","ranges":[{"startOffset":346042,"endOffset":346147,"count":0}],"isBlockCoverage":false},{"functionName":"Highlighter__writeFirstLine_closure0","ranges":[{"startOffset":346191,"endOffset":346303,"count":0}],"isBlockCoverage":false},{"functionName":"Highlighter__writeFirstLine_closure1","ranges":[{"startOffset":346347,"endOffset":346455,"count":0}],"isBlockCoverage":false},{"functionName":"Highlighter__writeFirstLine_closure2","ranges":[{"startOffset":346499,"endOffset":346607,"count":0}],"isBlockCoverage":false},{"functionName":"Highlighter__writeIntermediateLines_closure","ranges":[{"startOffset":346658,"endOffset":346771,"count":0}],"isBlockCoverage":false},{"functionName":"Highlighter__writeLastLine_closure","ranges":[{"startOffset":346813,"endOffset":346917,"count":0}],"isBlockCoverage":false},{"functionName":"Highlighter__writeLastLine_closure0","ranges":[{"startOffset":346960,"endOffset":347071,"count":0}],"isBlockCoverage":false},{"functionName":"Highlighter__writeLastLine_closure1","ranges":[{"startOffset":347114,"endOffset":347221,"count":0}],"isBlockCoverage":false},{"functionName":"Highlighter__writeSidebar_closure","ranges":[{"startOffset":347262,"endOffset":347390,"count":0}],"isBlockCoverage":false},{"functionName":"Chain_capture","ranges":[{"startOffset":347411,"endOffset":348428,"count":1},{"startOffset":347512,"endOffset":347565,"count":0},{"startOffset":347633,"endOffset":347760,"count":0}],"isBlockCoverage":true},{"functionName":"Chain_Chain$current","ranges":[{"startOffset":348455,"endOffset":348942,"count":0}],"isBlockCoverage":false},{"functionName":"Chain_Chain$forTrace","ranges":[{"startOffset":348970,"endOffset":349524,"count":0}],"isBlockCoverage":false},{"functionName":"Chain_Chain$parse","ranges":[{"startOffset":349549,"endOffset":350621,"count":0}],"isBlockCoverage":false},{"functionName":"Chain","ranges":[{"startOffset":350634,"endOffset":350684,"count":0}],"isBlockCoverage":false},{"functionName":"Chain_capture_closure","ranges":[{"startOffset":350713,"endOffset":350804,"count":1}],"isBlockCoverage":true},{"functionName":"Chain_Chain$current_closure","ranges":[{"startOffset":350839,"endOffset":350937,"count":0}],"isBlockCoverage":false},{"functionName":"Chain_Chain$forTrace_closure","ranges":[{"startOffset":350973,"endOffset":351045,"count":0}],"isBlockCoverage":false},{"functionName":"Chain_Chain$parse_closure","ranges":[{"startOffset":351078,"endOffset":351122,"count":0}],"isBlockCoverage":false},{"functionName":"Chain_Chain$parse_closure0","ranges":[{"startOffset":351156,"endOffset":351201,"count":0}],"isBlockCoverage":false},{"functionName":"Chain_foldFrames_closure","ranges":[{"startOffset":351233,"endOffset":351332,"count":0}],"isBlockCoverage":false},{"functionName":"Chain_foldFrames_closure0","ranges":[{"startOffset":351365,"endOffset":351434,"count":0}],"isBlockCoverage":false},{"functionName":"Chain_toTrace_closure","ranges":[{"startOffset":351463,"endOffset":351503,"count":0}],"isBlockCoverage":false},{"functionName":"Chain_toString_closure0","ranges":[{"startOffset":351534,"endOffset":351576,"count":0}],"isBlockCoverage":false},{"functionName":"Chain_toString__closure0","ranges":[{"startOffset":351608,"endOffset":351651,"count":0}],"isBlockCoverage":false},{"functionName":"Chain_toString_closure","ranges":[{"startOffset":351681,"endOffset":351749,"count":0}],"isBlockCoverage":false},{"functionName":"Chain_toString__closure","ranges":[{"startOffset":351780,"endOffset":351849,"count":0}],"isBlockCoverage":false},{"functionName":"Invoker_guard","ranges":[{"startOffset":351870,"endOffset":352115,"count":1}],"isBlockCoverage":true},{"functionName":"LocalTest","ranges":[{"startOffset":352132,"endOffset":352335,"count":1}],"isBlockCoverage":true},{"functionName":"Invoker","ranges":[{"startOffset":352350,"endOffset":352742,"count":1}],"isBlockCoverage":true},{"functionName":"Invoker_guard_closure","ranges":[{"startOffset":352771,"endOffset":352811,"count":1}],"isBlockCoverage":true},{"functionName":"Invoker_guard__closure","ranges":[{"startOffset":352841,"endOffset":353002,"count":0}],"isBlockCoverage":false},{"functionName":"Invoker_waitForOutstandingCallbacks_closure","ranges":[{"startOffset":353053,"endOffset":353229,"count":1}],"isBlockCoverage":true},{"functionName":"Invoker_waitForOutstandingCallbacks_closure0","ranges":[{"startOffset":353281,"endOffset":353397,"count":1}],"isBlockCoverage":true},{"functionName":"Invoker_heartbeat_message","ranges":[{"startOffset":353430,"endOffset":353501,"count":1}],"isBlockCoverage":true},{"functionName":"Invoker_heartbeat_closure","ranges":[{"startOffset":353534,"endOffset":353661,"count":1}],"isBlockCoverage":true},{"functionName":"Invoker_heartbeat__closure","ranges":[{"startOffset":353695,"endOffset":353823,"count":0}],"isBlockCoverage":false},{"functionName":"Invoker__handleError_closure","ranges":[{"startOffset":353859,"endOffset":353932,"count":0}],"isBlockCoverage":false},{"functionName":"Invoker__handleError_closure0","ranges":[{"startOffset":353969,"endOffset":354042,"count":0}],"isBlockCoverage":false},{"functionName":"Invoker__onRun_closure","ranges":[{"startOffset":354072,"endOffset":354187,"count":1}],"isBlockCoverage":true},{"functionName":"Invoker__onRun__closure","ranges":[{"startOffset":354218,"endOffset":354334,"count":1}],"isBlockCoverage":true},{"functionName":"Invoker__onRun___closure","ranges":[{"startOffset":354366,"endOffset":354434,"count":1}],"isBlockCoverage":true},{"functionName":"Invoker__onRun____closure","ranges":[{"startOffset":354467,"endOffset":354536,"count":1}],"isBlockCoverage":true},{"functionName":"Invoker__onRun___closure0","ranges":[{"startOffset":354569,"endOffset":354638,"count":1}],"isBlockCoverage":true},{"functionName":"_AsyncCounter","ranges":[{"startOffset":354659,"endOffset":354753,"count":1}],"isBlockCoverage":true},{"functionName":"StackTraceFormatter","ranges":[{"startOffset":354780,"endOffset":354899,"count":1}],"isBlockCoverage":true},{"functionName":"StackTraceFormatter_formatStackTrace_closure","ranges":[{"startOffset":354951,"endOffset":355039,"count":0}],"isBlockCoverage":false},{"functionName":"Suite__filterGroup","ranges":[{"startOffset":355065,"endOffset":355410,"count":1},{"startOffset":355223,"endOffset":355409,"count":0}],"isBlockCoverage":true},{"functionName":"Suite","ranges":[{"startOffset":355423,"endOffset":355528,"count":1}],"isBlockCoverage":true},{"functionName":"SuiteConfiguration__list","ranges":[{"startOffset":355560,"endOffset":355606,"count":0}],"isBlockCoverage":false},{"functionName":"SuiteConfiguration__map","ranges":[{"startOffset":355637,"endOffset":355695,"count":0}],"isBlockCoverage":false},{"functionName":"SuiteConfiguration","ranges":[{"startOffset":355721,"endOffset":355758,"count":0}],"isBlockCoverage":false},{"functionName":"RemoteException_serialize","ranges":[{"startOffset":355791,"endOffset":356552,"count":0}],"isBlockCoverage":false},{"functionName":"IntersectionSelector","ranges":[{"startOffset":356587,"endOffset":356688,"count":0}],"isBlockCoverage":false},{"functionName":"StreamChannel","ranges":[{"startOffset":356705,"endOffset":356737,"count":0}],"isBlockCoverage":false},{"functionName":"_StreamChannel","ranges":[{"startOffset":356755,"endOffset":356865,"count":1}],"isBlockCoverage":true},{"functionName":"StreamChannelMixin","ranges":[{"startOffset":356887,"endOffset":356924,"count":0}],"isBlockCoverage":false},{"functionName":"Timeout","ranges":[{"startOffset":356935,"endOffset":357022,"count":1}],"isBlockCoverage":true},{"functionName":"ExpandedReporter","ranges":[{"startOffset":357042,"endOffset":357603,"count":0}],"isBlockCoverage":false},{"functionName":"ExpandedReporter__onTestStarted_closure","ranges":[{"startOffset":357646,"endOffset":357759,"count":0}],"isBlockCoverage":false},{"functionName":"ExpandedReporter__onTestStarted_closure0","ranges":[{"startOffset":357803,"endOffset":357917,"count":0}],"isBlockCoverage":false},{"functionName":"ExpandedReporter__onTestStarted_closure1","ranges":[{"startOffset":357961,"endOffset":358075,"count":0}],"isBlockCoverage":false},{"functionName":"_declarer","ranges":[{"startOffset":358092,"endOffset":358479,"count":1},{"startOffset":358251,"endOffset":358478,"count":0}],"isBlockCoverage":true},{"functionName":"test","ranges":[{"startOffset":358491,"endOffset":358707,"count":1}],"isBlockCoverage":true},{"functionName":"group","ranges":[{"startOffset":358720,"endOffset":358937,"count":1}],"isBlockCoverage":true},{"functionName":"_declarer_closure","ranges":[{"startOffset":358962,"endOffset":358998,"count":0}],"isBlockCoverage":false},{"functionName":"_declarer__closure","ranges":[{"startOffset":359024,"endOffset":359087,"count":0}],"isBlockCoverage":false},{"functionName":"main","ranges":[{"startOffset":359099,"endOffset":359177,"count":1}],"isBlockCoverage":true},{"functionName":"main_closure","ranges":[{"startOffset":359197,"endOffset":359228,"count":1}],"isBlockCoverage":true},{"functionName":"RecursiveVisitor","ranges":[{"startOffset":359259,"endOffset":359294,"count":0}],"isBlockCoverage":false},{"functionName":"InternalStyle","ranges":[{"startOffset":359311,"endOffset":359343,"count":0}],"isBlockCoverage":false},{"functionName":"StreamChannelController$","ranges":[{"startOffset":359375,"endOffset":360324,"count":1}],"isBlockCoverage":true},{"functionName":"StreamChannelController","ranges":[{"startOffset":360355,"endOffset":360462,"count":1}],"isBlockCoverage":true},{"functionName":"Runtime_Runtime$deserialize","ranges":[{"startOffset":360497,"endOffset":361558,"count":1},{"startOffset":360735,"endOffset":361557,"count":0}],"isBlockCoverage":true},{"functionName":"Runtime","ranges":[{"startOffset":361573,"endOffset":361827,"count":1}],"isBlockCoverage":true},{"functionName":"Runtime_Runtime$deserialize_closure","ranges":[{"startOffset":361870,"endOffset":361954,"count":1}],"isBlockCoverage":true},{"functionName":"indent","ranges":[{"startOffset":361968,"endOffset":362129,"count":0}],"isBlockCoverage":false},{"functionName":"toSentence","ranges":[{"startOffset":362147,"endOffset":362529,"count":0}],"isBlockCoverage":false},{"functionName":"pluralize","ranges":[{"startOffset":362546,"endOffset":362649,"count":0}],"isBlockCoverage":false},{"functionName":"prefixLines","ranges":[{"startOffset":362668,"endOffset":363386,"count":0}],"isBlockCoverage":false},{"functionName":"closure0","ranges":[{"startOffset":363402,"endOffset":363429,"count":0}],"isBlockCoverage":false},{"functionName":"LiveSuiteController$","ranges":[{"startOffset":363457,"endOffset":364346,"count":0}],"isBlockCoverage":false},{"functionName":"_LiveSuite","ranges":[{"startOffset":364364,"endOffset":364447,"count":0}],"isBlockCoverage":false},{"functionName":"LiveSuiteController","ranges":[{"startOffset":364474,"endOffset":364920,"count":0}],"isBlockCoverage":false},{"functionName":"LiveSuiteController_closure","ranges":[{"startOffset":364955,"endOffset":365026,"count":0}],"isBlockCoverage":false},{"functionName":"LiveSuiteController_closure0","ranges":[{"startOffset":365062,"endOffset":365109,"count":0}],"isBlockCoverage":false},{"functionName":"LiveSuiteController_reportLiveTest_closure","ranges":[{"startOffset":365159,"endOffset":365309,"count":0}],"isBlockCoverage":false},{"functionName":"LiveSuiteController_close_closure","ranges":[{"startOffset":365350,"endOffset":365427,"count":0}],"isBlockCoverage":false},{"functionName":"asUri","ranges":[{"startOffset":365440,"endOffset":365612,"count":0}],"isBlockCoverage":false},{"functionName":"ensureTrailingSlash","ranges":[{"startOffset":365639,"endOffset":366120,"count":1},{"startOffset":365724,"endOffset":365758,"count":0},{"startOffset":365898,"endOffset":366119,"count":0}],"isBlockCoverage":true},{"functionName":"isAlphabetic","ranges":[{"startOffset":366140,"endOffset":366302,"count":0}],"isBlockCoverage":false},{"functionName":"isDriveLetter","ranges":[{"startOffset":366323,"endOffset":366734,"count":0}],"isBlockCoverage":false},{"functionName":"countCodeUnits","ranges":[{"startOffset":366756,"endOffset":367071,"count":0}],"isBlockCoverage":false},{"functionName":"findLineStart","ranges":[{"startOffset":367092,"endOffset":367938,"count":0}],"isBlockCoverage":false},{"functionName":"validateErrorArgs","ranges":[{"startOffset":367963,"endOffset":368466,"count":0}],"isBlockCoverage":false},{"functionName":"QueueList$","ranges":[{"startOffset":368496,"endOffset":368736,"count":1}],"isBlockCoverage":true},{"functionName":"QueueList__nextPowerOf2","ranges":[{"startOffset":368767,"endOffset":369042,"count":0}],"isBlockCoverage":false},{"functionName":"QueueList","ranges":[{"startOffset":369059,"endOffset":369215,"count":1}],"isBlockCoverage":true},{"functionName":"_QueueList_Object_ListMixin","ranges":[{"startOffset":369250,"endOffset":369296,"count":0}],"isBlockCoverage":false},{"functionName":"UnionSet","ranges":[{"startOffset":369319,"endOffset":369427,"count":0}],"isBlockCoverage":false},{"functionName":"UnionSet_length_closure","ranges":[{"startOffset":369454,"endOffset":369521,"count":0}],"isBlockCoverage":false},{"functionName":"UnionSet__iterable_closure","ranges":[{"startOffset":369551,"endOffset":369621,"count":0}],"isBlockCoverage":false},{"functionName":"_UnionSet_SetBase_UnmodifiableSetMixin","ranges":[{"startOffset":369663,"endOffset":369720,"count":0}],"isBlockCoverage":false},{"functionName":"_DelegatingIterableBase","ranges":[{"startOffset":369747,"endOffset":369789,"count":0}],"isBlockCoverage":false},{"functionName":"DelegatingIterable","ranges":[{"startOffset":369811,"endOffset":369848,"count":0}],"isBlockCoverage":false},{"functionName":"DelegatingSet","ranges":[{"startOffset":369865,"endOffset":369947,"count":0}],"isBlockCoverage":false},{"functionName":"TypeMatcher","ranges":[{"startOffset":369962,"endOffset":369992,"count":0}],"isBlockCoverage":false},{"functionName":"wrapMatcher","ranges":[{"startOffset":370011,"endOffset":370493,"count":1},{"startOffset":370116,"endOffset":370487,"count":0}],"isBlockCoverage":true},{"functionName":"escape","ranges":[{"startOffset":370507,"endOffset":370736,"count":0}],"isBlockCoverage":false},{"functionName":"_getHexLiteral","ranges":[{"startOffset":370758,"endOffset":371247,"count":0}],"isBlockCoverage":false},{"functionName":"wrapMatcher_closure","ranges":[{"startOffset":371274,"endOffset":371333,"count":0}],"isBlockCoverage":false},{"functionName":"escape_closure","ranges":[{"startOffset":371355,"endOffset":371388,"count":0}],"isBlockCoverage":false},{"functionName":"Context_Context","ranges":[{"startOffset":371411,"endOffset":371599,"count":0}],"isBlockCoverage":false},{"functionName":"_parseUri","ranges":[{"startOffset":371616,"endOffset":371786,"count":0}],"isBlockCoverage":false},{"functionName":"_validateArgList","ranges":[{"startOffset":371810,"endOffset":372805,"count":0}],"isBlockCoverage":false},{"functionName":"Context","ranges":[{"startOffset":372820,"endOffset":372910,"count":0}],"isBlockCoverage":false},{"functionName":"Context_join_closure","ranges":[{"startOffset":372938,"endOffset":372977,"count":0}],"isBlockCoverage":false},{"functionName":"Context_joinAll_closure","ranges":[{"startOffset":373008,"endOffset":373050,"count":0}],"isBlockCoverage":false},{"functionName":"Context_split_closure","ranges":[{"startOffset":373079,"endOffset":373119,"count":0}],"isBlockCoverage":false},{"functionName":"_validateArgList_closure","ranges":[{"startOffset":373151,"endOffset":373194,"count":0}],"isBlockCoverage":false},{"functionName":"_PathDirection","ranges":[{"startOffset":373216,"endOffset":373273,"count":1}],"isBlockCoverage":true},{"functionName":"_PathRelation","ranges":[{"startOffset":373294,"endOffset":373350,"count":1}],"isBlockCoverage":true},{"functionName":"_StringEqualsMatcher__writeLeading","ranges":[{"startOffset":373404,"endOffset":373714,"count":0}],"isBlockCoverage":false},{"functionName":"_StringEqualsMatcher__writeTrailing","ranges":[{"startOffset":373757,"endOffset":374094,"count":0}],"isBlockCoverage":false},{"functionName":"_StringEqualsMatcher","ranges":[{"startOffset":374122,"endOffset":374203,"count":0}],"isBlockCoverage":false},{"functionName":"_DeepMatcher","ranges":[{"startOffset":374223,"endOffset":374311,"count":0}],"isBlockCoverage":false},{"functionName":"_DeepMatcher__compareSets_closure","ranges":[{"startOffset":374352,"endOffset":374533,"count":0}],"isBlockCoverage":false},{"functionName":"PackageRootResolver","ranges":[{"startOffset":374560,"endOffset":374629,"count":0}],"isBlockCoverage":false},{"functionName":"SourceLocationMixin","ranges":[{"startOffset":374656,"endOffset":374694,"count":0}],"isBlockCoverage":false},{"functionName":"_MultiChannel$","ranges":[{"startOffset":374716,"endOffset":375095,"count":1}],"isBlockCoverage":true},{"functionName":"_MultiChannel","ranges":[{"startOffset":375116,"endOffset":375414,"count":1}],"isBlockCoverage":true},{"functionName":"_MultiChannel_closure","ranges":[{"startOffset":375443,"endOffset":375531,"count":1}],"isBlockCoverage":true},{"functionName":"_MultiChannel_closure0","ranges":[{"startOffset":375561,"endOffset":375627,"count":1}],"isBlockCoverage":true},{"functionName":"_MultiChannel_closure1","ranges":[{"startOffset":375657,"endOffset":375746,"count":1}],"isBlockCoverage":true},{"functionName":"_MultiChannel__closure","ranges":[{"startOffset":375776,"endOffset":375889,"count":1}],"isBlockCoverage":true},{"functionName":"_MultiChannel_virtualChannel_closure","ranges":[{"startOffset":375933,"endOffset":376041,"count":1}],"isBlockCoverage":true},{"functionName":"_MultiChannel_virtualChannel_closure0","ranges":[{"startOffset":376086,"endOffset":376195,"count":1}],"isBlockCoverage":true},{"functionName":"VirtualChannel","ranges":[{"startOffset":376217,"endOffset":376400,"count":1}],"isBlockCoverage":true},{"functionName":"Message","ranges":[{"startOffset":376415,"endOffset":376491,"count":0}],"isBlockCoverage":false},{"functionName":"MessageType","ranges":[{"startOffset":376510,"endOffset":376564,"count":1}],"isBlockCoverage":true},{"functionName":"current","ranges":[{"startOffset":376579,"endOffset":377522,"count":0}],"isBlockCoverage":false},{"functionName":"prettyPrint","ranges":[{"startOffset":377553,"endOffset":377748,"count":0}],"isBlockCoverage":false},{"functionName":"_typeName","ranges":[{"startOffset":377765,"endOffset":377994,"count":0}],"isBlockCoverage":false},{"functionName":"_escapeString","ranges":[{"startOffset":378015,"endOffset":378154,"count":0}],"isBlockCoverage":false},{"functionName":"prettyPrint__prettyPrint","ranges":[{"startOffset":378186,"endOffset":378292,"count":0}],"isBlockCoverage":false},{"functionName":"prettyPrint__prettyPrint_pp","ranges":[{"startOffset":378327,"endOffset":378461,"count":0}],"isBlockCoverage":false},{"functionName":"prettyPrint__prettyPrint_closure","ranges":[{"startOffset":378501,"endOffset":378578,"count":0}],"isBlockCoverage":false},{"functionName":"prettyPrint__prettyPrint_closure0","ranges":[{"startOffset":378619,"endOffset":378721,"count":0}],"isBlockCoverage":false},{"functionName":"prettyPrint__prettyPrint_closure1","ranges":[{"startOffset":378762,"endOffset":378840,"count":0}],"isBlockCoverage":false},{"functionName":"LiveTest","ranges":[{"startOffset":378856,"endOffset":378883,"count":0}],"isBlockCoverage":false},{"functionName":"Frame_Frame$parseVM","ranges":[{"startOffset":378922,"endOffset":379038,"count":0}],"isBlockCoverage":false},{"functionName":"Frame_Frame$parseV8","ranges":[{"startOffset":379065,"endOffset":379181,"count":0}],"isBlockCoverage":false},{"functionName":"Frame_Frame$parseFirefox","ranges":[{"startOffset":379213,"endOffset":379334,"count":0}],"isBlockCoverage":false},{"functionName":"Frame_Frame$parseFriendly","ranges":[{"startOffset":379367,"endOffset":379489,"count":0}],"isBlockCoverage":false},{"functionName":"Frame__uriOrPathToUri","ranges":[{"startOffset":379518,"endOffset":380076,"count":0}],"isBlockCoverage":false},{"functionName":"Frame__catchFormatException","ranges":[{"startOffset":380111,"endOffset":380455,"count":0}],"isBlockCoverage":false},{"functionName":"Frame","ranges":[{"startOffset":380468,"endOffset":380605,"count":0}],"isBlockCoverage":false},{"functionName":"Frame_Frame$parseVM_closure","ranges":[{"startOffset":380640,"endOffset":380711,"count":0}],"isBlockCoverage":false},{"functionName":"Frame_Frame$parseV8_closure","ranges":[{"startOffset":380746,"endOffset":380817,"count":0}],"isBlockCoverage":false},{"functionName":"Frame_Frame$parseV8_closure_parseLocation","ranges":[{"startOffset":380866,"endOffset":380951,"count":0}],"isBlockCoverage":false},{"functionName":"Frame_Frame$parseFirefox_closure","ranges":[{"startOffset":380991,"endOffset":381067,"count":0}],"isBlockCoverage":false},{"functionName":"Frame_Frame$parseFriendly_closure","ranges":[{"startOffset":381108,"endOffset":381185,"count":0}],"isBlockCoverage":false},{"functionName":"AsciiGlyphSet","ranges":[{"startOffset":381206,"endOffset":381238,"count":1}],"isBlockCoverage":true},{"functionName":"UnparsedFrame","ranges":[{"startOffset":381266,"endOffset":381349,"count":0}],"isBlockCoverage":false},{"functionName":"StreamChannelCompleter","ranges":[{"startOffset":381375,"endOffset":381623,"count":1}],"isBlockCoverage":true},{"functionName":"postMessageChannel","ranges":[{"startOffset":381649,"endOffset":382274,"count":1}],"isBlockCoverage":true},{"functionName":"postMessageChannel_closure","ranges":[{"startOffset":382308,"endOffset":382353,"count":1}],"isBlockCoverage":true},{"functionName":"postMessageChannel_closure0","ranges":[{"startOffset":382388,"endOffset":382464,"count":1}],"isBlockCoverage":true},{"functionName":"postMessageChannel__closure","ranges":[{"startOffset":382499,"endOffset":382575,"count":1}],"isBlockCoverage":true},{"functionName":"postMessageChannel__closure0","ranges":[{"startOffset":382611,"endOffset":382682,"count":1}],"isBlockCoverage":true},{"functionName":"postMessageChannel__closure1","ranges":[{"startOffset":382718,"endOffset":382827,"count":1}],"isBlockCoverage":true},{"functionName":"OperatingSystem_find","ranges":[{"startOffset":382855,"endOffset":383034,"count":1}],"isBlockCoverage":true},{"functionName":"OperatingSystem","ranges":[{"startOffset":383057,"endOffset":383147,"count":1}],"isBlockCoverage":true},{"functionName":"OperatingSystem_find_closure","ranges":[{"startOffset":383183,"endOffset":383260,"count":1}],"isBlockCoverage":true},{"functionName":"OperatingSystem_find_closure0","ranges":[{"startOffset":383297,"endOffset":383345,"count":1}],"isBlockCoverage":true},{"functionName":"SuiteChannelManager","ranges":[{"startOffset":383372,"endOffset":383520,"count":1}],"isBlockCoverage":true},{"functionName":"GuaranteeChannel$","ranges":[{"startOffset":383557,"endOffset":383845,"count":1}],"isBlockCoverage":true},{"functionName":"GuaranteeChannel","ranges":[{"startOffset":383869,"endOffset":384037,"count":1}],"isBlockCoverage":true},{"functionName":"GuaranteeChannel_closure","ranges":[{"startOffset":384069,"endOffset":384165,"count":1}],"isBlockCoverage":true},{"functionName":"GuaranteeChannel__closure","ranges":[{"startOffset":384198,"endOffset":384267,"count":1}],"isBlockCoverage":true},{"functionName":"_GuaranteeSink","ranges":[{"startOffset":384289,"endOffset":384584,"count":1}],"isBlockCoverage":true},{"functionName":"_GuaranteeSink__addError_closure","ranges":[{"startOffset":384624,"endOffset":384675,"count":0}],"isBlockCoverage":false},{"functionName":"_GuaranteeSink_addStream_closure","ranges":[{"startOffset":384715,"endOffset":384791,"count":1}],"isBlockCoverage":true},{"functionName":"UnicodeGlyphSet","ranges":[{"startOffset":384814,"endOffset":384848,"count":1}],"isBlockCoverage":true},{"functionName":"ClosedException$","ranges":[{"startOffset":384872,"endOffset":384928,"count":0}],"isBlockCoverage":false},{"functionName":"ClosedException","ranges":[{"startOffset":384951,"endOffset":384985,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":385218,"endOffset":385284,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":385304,"endOffset":385382,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":385400,"endOffset":385507,"count":0}],"isBlockCoverage":false},{"functionName":"get$runtimeType","ranges":[{"startOffset":385530,"endOffset":385597,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":385644,"endOffset":385701,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":385721,"endOffset":385788,"count":1},{"startOffset":385773,"endOffset":385781,"count":0}],"isBlockCoverage":true},{"functionName":"get$runtimeType","ranges":[{"startOffset":385811,"endOffset":385867,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":385923,"endOffset":385984,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":386002,"endOffset":386049,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":386069,"endOffset":386111,"count":0}],"isBlockCoverage":false},{"functionName":"get$runtimeType","ranges":[{"startOffset":386134,"endOffset":386190,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":386294,"endOffset":386336,"count":0}],"isBlockCoverage":false},{"functionName":"get$runtimeType","ranges":[{"startOffset":386359,"endOffset":386419,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":386437,"endOffset":386494,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":386659,"endOffset":386925,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":386943,"endOffset":387010,"count":0}],"isBlockCoverage":false},{"functionName":"add$1","ranges":[{"startOffset":387073,"endOffset":387290,"count":1},{"startOffset":387210,"endOffset":387256,"count":0}],"isBlockCoverage":true},{"functionName":"removeAt$1","ranges":[{"startOffset":387308,"endOffset":387608,"count":0}],"isBlockCoverage":false},{"functionName":"insert$2","ranges":[{"startOffset":387624,"endOffset":387991,"count":0}],"isBlockCoverage":false},{"functionName":"insertAll$2","ranges":[{"startOffset":388010,"endOffset":388615,"count":0}],"isBlockCoverage":false},{"functionName":"removeLast$0","ranges":[{"startOffset":388635,"endOffset":388887,"count":0}],"isBlockCoverage":false},{"functionName":"remove$1","ranges":[{"startOffset":388903,"endOffset":389218,"count":1},{"startOffset":388989,"endOffset":389038,"count":0},{"startOffset":389192,"endOffset":389217,"count":0}],"isBlockCoverage":true},{"functionName":"addAll$1","ranges":[{"startOffset":389234,"endOffset":389764,"count":0}],"isBlockCoverage":false},{"functionName":"forEach$1","ranges":[{"startOffset":389781,"endOffset":390106,"count":0}],"isBlockCoverage":false},{"functionName":"map$1$1","ranges":[{"startOffset":390121,"endOffset":390359,"count":0}],"isBlockCoverage":false},{"functionName":"join$1","ranges":[{"startOffset":390373,"endOffset":390629,"count":0}],"isBlockCoverage":false},{"functionName":"join$0","ranges":[{"startOffset":390643,"endOffset":390711,"count":0}],"isBlockCoverage":false},{"functionName":"fold$1$2","ranges":[{"startOffset":390727,"endOffset":391213,"count":1},{"startOffset":391010,"endOffset":391187,"count":0}],"isBlockCoverage":true},{"functionName":"firstWhere$2$orElse","ranges":[{"startOffset":391240,"endOffset":391854,"count":1},{"startOffset":391653,"endOffset":391717,"count":0},{"startOffset":391783,"endOffset":391853,"count":0}],"isBlockCoverage":true},{"functionName":"firstWhere$1","ranges":[{"startOffset":391874,"endOffset":391969,"count":1}],"isBlockCoverage":true},{"functionName":"elementAt$1","ranges":[{"startOffset":391988,"endOffset":392141,"count":1},{"startOffset":392073,"endOffset":392105,"count":0}],"isBlockCoverage":true},{"functionName":"sublist$2","ranges":[{"startOffset":392158,"endOffset":392671,"count":0}],"isBlockCoverage":false},{"functionName":"get$first","ranges":[{"startOffset":392688,"endOffset":392838,"count":1},{"startOffset":392767,"endOffset":392837,"count":0}],"isBlockCoverage":true},{"functionName":"get$last","ranges":[{"startOffset":392854,"endOffset":393028,"count":1},{"startOffset":392957,"endOffset":393027,"count":0}],"isBlockCoverage":true},{"functionName":"get$single","ranges":[{"startOffset":393046,"endOffset":393372,"count":0}],"isBlockCoverage":false},{"functionName":"setRange$4","ranges":[{"startOffset":393390,"endOffset":394326,"count":0}],"isBlockCoverage":false},{"functionName":"setRange$3","ranges":[{"startOffset":394344,"endOffset":394459,"count":0}],"isBlockCoverage":false},{"functionName":"fillRange$3","ranges":[{"startOffset":394478,"endOffset":394843,"count":0}],"isBlockCoverage":false},{"functionName":"replaceRange$3","ranges":[{"startOffset":394865,"endOffset":395890,"count":0}],"isBlockCoverage":false},{"functionName":"contains$1","ranges":[{"startOffset":395908,"endOffset":396081,"count":0}],"isBlockCoverage":false},{"functionName":"get$isEmpty","ranges":[{"startOffset":396100,"endOffset":396162,"count":1}],"isBlockCoverage":true},{"functionName":"toString$0","ranges":[{"startOffset":396180,"endOffset":396276,"count":0}],"isBlockCoverage":false},{"functionName":"toSet$0","ranges":[{"startOffset":396291,"endOffset":396422,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":396442,"endOffset":396589,"count":1}],"isBlockCoverage":true},{"functionName":"get$hashCode","ranges":[{"startOffset":396609,"endOffset":396687,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":396705,"endOffset":396761,"count":1}],"isBlockCoverage":true},{"functionName":"set$length","ranges":[{"startOffset":396779,"endOffset":397195,"count":1},{"startOffset":396884,"endOffset":396937,"count":0},{"startOffset":396978,"endOffset":397046,"count":0},{"startOffset":397080,"endOffset":397154,"count":0}],"isBlockCoverage":true},{"functionName":"$index","ranges":[{"startOffset":397209,"endOffset":397523,"count":1},{"startOffset":397307,"endOffset":397368,"count":0},{"startOffset":397426,"endOffset":397487,"count":0}],"isBlockCoverage":true},{"functionName":"$indexSet","ranges":[{"startOffset":397540,"endOffset":398028,"count":1},{"startOffset":397720,"endOffset":397774,"count":0},{"startOffset":397811,"endOffset":397872,"count":0},{"startOffset":397930,"endOffset":397991,"count":0}],"isBlockCoverage":true},{"functionName":"get$current","ranges":[{"startOffset":398194,"endOffset":398240,"count":1}],"isBlockCoverage":true},{"functionName":"moveNext$0","ranges":[{"startOffset":398258,"endOffset":398662,"count":1},{"startOffset":398403,"endOffset":398465,"count":0}],"isBlockCoverage":true},{"functionName":"set$_current","ranges":[{"startOffset":398682,"endOffset":398771,"count":1}],"isBlockCoverage":true},{"functionName":"floor$0","ranges":[{"startOffset":398837,"endOffset":399285,"count":0}],"isBlockCoverage":false},{"functionName":"round$0","ranges":[{"startOffset":399300,"endOffset":399582,"count":1},{"startOffset":399425,"endOffset":399581,"count":0}],"isBlockCoverage":true},{"functionName":"toRadixString$1","ranges":[{"startOffset":399605,"endOffset":400471,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":400489,"endOffset":400625,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":400645,"endOffset":401151,"count":0}],"isBlockCoverage":false},{"functionName":"$mod","ranges":[{"startOffset":401163,"endOffset":401414,"count":0}],"isBlockCoverage":false},{"functionName":"$tdiv","ranges":[{"startOffset":401427,"endOffset":401624,"count":0}],"isBlockCoverage":false},{"functionName":"_tdivFast$1","ranges":[{"startOffset":401643,"endOffset":401777,"count":1},{"startOffset":401735,"endOffset":401770,"count":0}],"isBlockCoverage":true},{"functionName":"_tdivSlow$1","ranges":[{"startOffset":401796,"endOffset":402270,"count":0}],"isBlockCoverage":false},{"functionName":"_shlPositive$1","ranges":[{"startOffset":402292,"endOffset":402380,"count":0}],"isBlockCoverage":false},{"functionName":"_shrOtherPositive$1","ranges":[{"startOffset":402407,"endOffset":402644,"count":0}],"isBlockCoverage":false},{"functionName":"_shrReceiverPositive$1","ranges":[{"startOffset":402674,"endOffset":402843,"count":0}],"isBlockCoverage":false},{"functionName":"_shrBothPositive$1","ranges":[{"startOffset":402869,"endOffset":402952,"count":0}],"isBlockCoverage":false},{"functionName":"get$runtimeType","ranges":[{"startOffset":402975,"endOffset":403030,"count":0}],"isBlockCoverage":false},{"functionName":"get$runtimeType","ranges":[{"startOffset":403114,"endOffset":403169,"count":0}],"isBlockCoverage":false},{"functionName":"get$runtimeType","ranges":[{"startOffset":403238,"endOffset":403296,"count":0}],"isBlockCoverage":false},{"functionName":"codeUnitAt$1","ranges":[{"startOffset":403347,"endOffset":403614,"count":1},{"startOffset":403404,"endOffset":403465,"count":0},{"startOffset":403510,"endOffset":403567,"count":0}],"isBlockCoverage":true},{"functionName":"_codeUnitAt$1","ranges":[{"startOffset":403635,"endOffset":403815,"count":1},{"startOffset":403707,"endOffset":403768,"count":0}],"isBlockCoverage":true},{"functionName":"allMatches$2","ranges":[{"startOffset":403835,"endOffset":404180,"count":0}],"isBlockCoverage":false},{"functionName":"allMatches$1","ranges":[{"startOffset":404200,"endOffset":404289,"count":0}],"isBlockCoverage":false},{"functionName":"matchAsPrefix$2","ranges":[{"startOffset":404312,"endOffset":404833,"count":0}],"isBlockCoverage":false},{"functionName":"$add","ranges":[{"startOffset":404845,"endOffset":405018,"count":0}],"isBlockCoverage":false},{"functionName":"endsWith$1","ranges":[{"startOffset":405036,"endOffset":405256,"count":0}],"isBlockCoverage":false},{"functionName":"splitMapJoin$2$onMatch","ranges":[{"startOffset":405286,"endOffset":405477,"count":0}],"isBlockCoverage":false},{"functionName":"replaceFirst$2","ranges":[{"startOffset":405499,"endOffset":405680,"count":0}],"isBlockCoverage":false},{"functionName":"replaceRange$3","ranges":[{"startOffset":405702,"endOffset":405903,"count":0}],"isBlockCoverage":false},{"functionName":"startsWith$2","ranges":[{"startOffset":405923,"endOffset":406447,"count":1},{"startOffset":406073,"endOffset":406154,"count":0},{"startOffset":406288,"endOffset":406301,"count":0},{"startOffset":406373,"endOffset":406446,"count":0}],"isBlockCoverage":true},{"functionName":"startsWith$1","ranges":[{"startOffset":406467,"endOffset":406558,"count":0}],"isBlockCoverage":false},{"functionName":"substring$2","ranges":[{"startOffset":406577,"endOffset":407046,"count":1},{"startOffset":406656,"endOffset":406683,"count":0},{"startOffset":406718,"endOffset":406778,"count":0},{"startOffset":406820,"endOffset":406880,"count":0},{"startOffset":406927,"endOffset":406985,"count":0}],"isBlockCoverage":true},{"functionName":"substring$1","ranges":[{"startOffset":407065,"endOffset":407164,"count":0}],"isBlockCoverage":false},{"functionName":"trim$0","ranges":[{"startOffset":407178,"endOffset":407844,"count":0}],"isBlockCoverage":false},{"functionName":"$mul","ranges":[{"startOffset":407856,"endOffset":408335,"count":0}],"isBlockCoverage":false},{"functionName":"padLeft$2","ranges":[{"startOffset":408352,"endOffset":408535,"count":0}],"isBlockCoverage":false},{"functionName":"padRight$1","ranges":[{"startOffset":408553,"endOffset":408802,"count":0}],"isBlockCoverage":false},{"functionName":"indexOf$2","ranges":[{"startOffset":408819,"endOffset":409075,"count":0}],"isBlockCoverage":false},{"functionName":"indexOf$1","ranges":[{"startOffset":409092,"endOffset":409180,"count":0}],"isBlockCoverage":false},{"functionName":"lastIndexOf$2","ranges":[{"startOffset":409201,"endOffset":409620,"count":0}],"isBlockCoverage":false},{"functionName":"lastIndexOf$1","ranges":[{"startOffset":409641,"endOffset":409736,"count":0}],"isBlockCoverage":false},{"functionName":"contains$1","ranges":[{"startOffset":409754,"endOffset":409928,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":409946,"endOffset":409995,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":410015,"endOffset":410421,"count":1}],"isBlockCoverage":true},{"functionName":"get$runtimeType","ranges":[{"startOffset":410444,"endOffset":410502,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":410520,"endOffset":410576,"count":1}],"isBlockCoverage":true},{"functionName":"$index","ranges":[{"startOffset":410590,"endOffset":410806,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":410903,"endOffset":411111,"count":1}],"isBlockCoverage":true},{"functionName":"get$length","ranges":[{"startOffset":411129,"endOffset":411209,"count":0}],"isBlockCoverage":false},{"functionName":"get$isEmpty","ranges":[{"startOffset":411228,"endOffset":411309,"count":0}],"isBlockCoverage":false},{"functionName":"get$first","ranges":[{"startOffset":411326,"endOffset":411441,"count":0}],"isBlockCoverage":false},{"functionName":"get$last","ranges":[{"startOffset":411457,"endOffset":411571,"count":0}],"isBlockCoverage":false},{"functionName":"contains$1","ranges":[{"startOffset":411589,"endOffset":411663,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":411681,"endOffset":411741,"count":0}],"isBlockCoverage":false},{"functionName":"moveNext$0","ranges":[{"startOffset":411794,"endOffset":411852,"count":1}],"isBlockCoverage":true},{"functionName":"get$current","ranges":[{"startOffset":411871,"endOffset":411953,"count":1}],"isBlockCoverage":true},{"functionName":"cast$2$0","ranges":[{"startOffset":412130,"endOffset":412317,"count":0}],"isBlockCoverage":false},{"functionName":"containsKey$1","ranges":[{"startOffset":412338,"endOffset":412405,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":412419,"endOffset":412508,"count":1}],"isBlockCoverage":true},{"functionName":"remove$1","ranges":[{"startOffset":412524,"endOffset":412615,"count":0}],"isBlockCoverage":false},{"functionName":"forEach$1","ranges":[{"startOffset":412632,"endOffset":412762,"count":0}],"isBlockCoverage":false},{"functionName":"get$keys","ranges":[{"startOffset":412778,"endOffset":412919,"count":1}],"isBlockCoverage":true},{"functionName":"get$length","ranges":[{"startOffset":412937,"endOffset":413017,"count":0}],"isBlockCoverage":false},{"functionName":"get$isEmpty","ranges":[{"startOffset":413036,"endOffset":413117,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":413177,"endOffset":413372,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":413390,"endOffset":413458,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":413508,"endOffset":413561,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":413575,"endOffset":413681,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":413780,"endOffset":413952,"count":1}],"isBlockCoverage":true},{"functionName":"get$isEmpty","ranges":[{"startOffset":413971,"endOffset":414032,"count":0}],"isBlockCoverage":false},{"functionName":"get$first","ranges":[{"startOffset":414049,"endOffset":414211,"count":0}],"isBlockCoverage":false},{"functionName":"get$last","ranges":[{"startOffset":414227,"endOffset":414442,"count":0}],"isBlockCoverage":false},{"functionName":"contains$1","ranges":[{"startOffset":414460,"endOffset":414822,"count":0}],"isBlockCoverage":false},{"functionName":"join$1","ranges":[{"startOffset":414836,"endOffset":415796,"count":0}],"isBlockCoverage":false},{"functionName":"join$0","ranges":[{"startOffset":415810,"endOffset":415878,"count":0}],"isBlockCoverage":false},{"functionName":"map$1$1","ranges":[{"startOffset":415893,"endOffset":416137,"count":0}],"isBlockCoverage":false},{"functionName":"fold$1$2","ranges":[{"startOffset":416153,"endOffset":416676,"count":0}],"isBlockCoverage":false},{"functionName":"toList$1$growable","ranges":[{"startOffset":416701,"endOffset":417074,"count":1}],"isBlockCoverage":true},{"functionName":"toList$0","ranges":[{"startOffset":417090,"endOffset":417171,"count":1}],"isBlockCoverage":true},{"functionName":"toSet$0","ranges":[{"startOffset":417186,"endOffset":417453,"count":0}],"isBlockCoverage":false},{"functionName":"get$_endIndex","ranges":[{"startOffset":417512,"endOffset":417706,"count":0}],"isBlockCoverage":false},{"functionName":"get$_startIndex","ranges":[{"startOffset":417729,"endOffset":417914,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":417932,"endOffset":418288,"count":0}],"isBlockCoverage":false},{"functionName":"elementAt$1","ranges":[{"startOffset":418307,"endOffset":418765,"count":0}],"isBlockCoverage":false},{"functionName":"take$1","ranges":[{"startOffset":418779,"endOffset":419284,"count":0}],"isBlockCoverage":false},{"functionName":"get$current","ranges":[{"startOffset":419338,"endOffset":419395,"count":1}],"isBlockCoverage":true},{"functionName":"moveNext$0","ranges":[{"startOffset":419413,"endOffset":419942,"count":1},{"startOffset":419627,"endOffset":419685,"count":0}],"isBlockCoverage":true},{"functionName":"set$__internal$_current","ranges":[{"startOffset":419973,"endOffset":420073,"count":1}],"isBlockCoverage":true},{"functionName":"get$iterator","ranges":[{"startOffset":420150,"endOffset":420369,"count":1}],"isBlockCoverage":true},{"functionName":"get$length","ranges":[{"startOffset":420387,"endOffset":420464,"count":0}],"isBlockCoverage":false},{"functionName":"get$isEmpty","ranges":[{"startOffset":420483,"endOffset":420561,"count":0}],"isBlockCoverage":false},{"functionName":"get$first","ranges":[{"startOffset":420578,"endOffset":420669,"count":0}],"isBlockCoverage":false},{"functionName":"get$last","ranges":[{"startOffset":420685,"endOffset":420775,"count":0}],"isBlockCoverage":false},{"functionName":"moveNext$0","ranges":[{"startOffset":420909,"endOffset":421176,"count":1},{"startOffset":421003,"endOffset":421107,"count":0}],"isBlockCoverage":true},{"functionName":"get$current","ranges":[{"startOffset":421195,"endOffset":421252,"count":0}],"isBlockCoverage":false},{"functionName":"set$__internal$_current","ranges":[{"startOffset":421283,"endOffset":421378,"count":1}],"isBlockCoverage":true},{"functionName":"get$length","ranges":[{"startOffset":421437,"endOffset":421501,"count":1}],"isBlockCoverage":true},{"functionName":"elementAt$1","ranges":[{"startOffset":421520,"endOffset":421614,"count":1}],"isBlockCoverage":true},{"functionName":"get$iterator","ranges":[{"startOffset":421670,"endOffset":421816,"count":1}],"isBlockCoverage":true},{"functionName":"map$1$1","ranges":[{"startOffset":421831,"endOffset":422028,"count":0}],"isBlockCoverage":false},{"functionName":"moveNext$0","ranges":[{"startOffset":422082,"endOffset":422289,"count":1}],"isBlockCoverage":true},{"functionName":"get$current","ranges":[{"startOffset":422308,"endOffset":422369,"count":1}],"isBlockCoverage":true},{"functionName":"get$iterator","ranges":[{"startOffset":422426,"endOffset":422651,"count":0}],"isBlockCoverage":false},{"functionName":"get$current","ranges":[{"startOffset":422707,"endOffset":422764,"count":0}],"isBlockCoverage":false},{"functionName":"moveNext$0","ranges":[{"startOffset":422782,"endOffset":423337,"count":0}],"isBlockCoverage":false},{"functionName":"set$_currentExpansion","ranges":[{"startOffset":423366,"endOffset":423491,"count":0}],"isBlockCoverage":false},{"functionName":"set$__internal$_current","ranges":[{"startOffset":423522,"endOffset":423617,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":423697,"endOffset":423851,"count":0}],"isBlockCoverage":false},{"functionName":"moveNext$0","ranges":[{"startOffset":423909,"endOffset":424236,"count":0}],"isBlockCoverage":false},{"functionName":"get$current","ranges":[{"startOffset":424255,"endOffset":424316,"count":0}],"isBlockCoverage":false},{"functionName":"moveNext$0","ranges":[{"startOffset":424370,"endOffset":424408,"count":0}],"isBlockCoverage":false},{"functionName":"get$current","ranges":[{"startOffset":424427,"endOffset":424464,"count":0}],"isBlockCoverage":false},{"functionName":"set$length","ranges":[{"startOffset":424545,"endOffset":424683,"count":0}],"isBlockCoverage":false},{"functionName":"$indexSet","ranges":[{"startOffset":424744,"endOffset":424977,"count":0}],"isBlockCoverage":false},{"functionName":"set$length","ranges":[{"startOffset":424995,"endOffset":425127,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":425229,"endOffset":425293,"count":1}],"isBlockCoverage":true},{"functionName":"elementAt$1","ranges":[{"startOffset":425312,"endOffset":425470,"count":1}],"isBlockCoverage":true},{"functionName":"get$hashCode","ranges":[{"startOffset":425519,"endOffset":425738,"count":1}],"isBlockCoverage":true},{"functionName":"toString$0","ranges":[{"startOffset":425756,"endOffset":425836,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":425847,"endOffset":426011,"count":1},{"startOffset":425901,"endOffset":425914,"count":0}],"isBlockCoverage":true},{"functionName":"cast$2$0","ranges":[{"startOffset":426061,"endOffset":426200,"count":0}],"isBlockCoverage":false},{"functionName":"get$isEmpty","ranges":[{"startOffset":426219,"endOffset":426280,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":426298,"endOffset":426359,"count":0}],"isBlockCoverage":false},{"functionName":"remove$1","ranges":[{"startOffset":426375,"endOffset":426448,"count":0}],"isBlockCoverage":false},{"functionName":"map$2$1","ranges":[{"startOffset":426463,"endOffset":426752,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":426827,"endOffset":427051,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":427069,"endOffset":427150,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":427208,"endOffset":427266,"count":0}],"isBlockCoverage":false},{"functionName":"containsKey$1","ranges":[{"startOffset":427287,"endOffset":427466,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":427480,"endOffset":427594,"count":0}],"isBlockCoverage":false},{"functionName":"_fetch$1","ranges":[{"startOffset":427610,"endOffset":427689,"count":0}],"isBlockCoverage":false},{"functionName":"forEach$1","ranges":[{"startOffset":427706,"endOffset":428021,"count":1},{"startOffset":427929,"endOffset":428015,"count":0}],"isBlockCoverage":true},{"functionName":"get$keys","ranges":[{"startOffset":428037,"endOffset":428166,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":428232,"endOffset":428410,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":428428,"endOffset":428508,"count":0}],"isBlockCoverage":false},{"functionName":"Instantiation$1","ranges":[{"startOffset":428567,"endOffset":428666,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":428684,"endOffset":428871,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":428922,"endOffset":429017,"count":0}],"isBlockCoverage":false},{"functionName":"call$4","ranges":[{"startOffset":429031,"endOffset":429142,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":429160,"endOffset":429281,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":429347,"endOffset":429437,"count":0}],"isBlockCoverage":false},{"functionName":"matchTypeError$1","ranges":[{"startOffset":429520,"endOffset":430192,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":430242,"endOffset":430457,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":430546,"endOffset":430987,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":431075,"endOffset":431193,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":431303,"endOffset":431464,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":431536,"endOffset":431793,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":431863,"endOffset":432075,"count":0}],"isBlockCoverage":false},{"functionName":"get$$call","ranges":[{"startOffset":432112,"endOffset":432149,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":432313,"endOffset":432502,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":432548,"endOffset":432877,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":432897,"endOffset":433264,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":433282,"endOffset":433522,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":433586,"endOffset":433632,"count":0}],"isBlockCoverage":false},{"functionName":"get$message","ranges":[{"startOffset":433651,"endOffset":433704,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":433757,"endOffset":433827,"count":0}],"isBlockCoverage":false},{"functionName":"get$message","ranges":[{"startOffset":433846,"endOffset":433899,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":433955,"endOffset":434046,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":434102,"endOffset":434160,"count":0}],"isBlockCoverage":false},{"functionName":"get$isEmpty","ranges":[{"startOffset":434179,"endOffset":434243,"count":1}],"isBlockCoverage":true},{"functionName":"get$keys","ranges":[{"startOffset":434259,"endOffset":434390,"count":1}],"isBlockCoverage":true},{"functionName":"get$values","ranges":[{"startOffset":434408,"endOffset":434602,"count":0}],"isBlockCoverage":false},{"functionName":"containsKey$1","ranges":[{"startOffset":434623,"endOffset":435155,"count":1},{"startOffset":435019,"endOffset":435032,"count":0},{"startOffset":435095,"endOffset":435149,"count":0}],"isBlockCoverage":true},{"functionName":"internalContainsKey$1","ranges":[{"startOffset":435184,"endOffset":435440,"count":0}],"isBlockCoverage":false},{"functionName":"addAll$1","ranges":[{"startOffset":435456,"endOffset":435602,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":435616,"endOffset":436311,"count":1},{"startOffset":435819,"endOffset":435832,"count":0},{"startOffset":435911,"endOffset":435918,"count":0},{"startOffset":436111,"endOffset":436124,"count":0},{"startOffset":436200,"endOffset":436207,"count":0},{"startOffset":436259,"endOffset":436305,"count":0}],"isBlockCoverage":true},{"functionName":"internalGet$1","ranges":[{"startOffset":436332,"endOffset":436708,"count":0}],"isBlockCoverage":false},{"functionName":"$indexSet","ranges":[{"startOffset":436725,"endOffset":437424,"count":1}],"isBlockCoverage":true},{"functionName":"internalSet$2","ranges":[{"startOffset":437445,"endOffset":438198,"count":1},{"startOffset":437963,"endOffset":438192,"count":0}],"isBlockCoverage":true},{"functionName":"putIfAbsent$2","ranges":[{"startOffset":438219,"endOffset":438560,"count":1},{"startOffset":438463,"endOffset":438559,"count":0}],"isBlockCoverage":true},{"functionName":"remove$1","ranges":[{"startOffset":438576,"endOffset":438960,"count":1},{"startOffset":438743,"endOffset":438954,"count":0}],"isBlockCoverage":true},{"functionName":"internalRemove$1","ranges":[{"startOffset":438984,"endOffset":439546,"count":0}],"isBlockCoverage":false},{"functionName":"clear$0","ranges":[{"startOffset":439561,"endOffset":439847,"count":0}],"isBlockCoverage":false},{"functionName":"forEach$1","ranges":[{"startOffset":439864,"endOffset":440326,"count":1},{"startOffset":440224,"endOffset":440285,"count":0}],"isBlockCoverage":true},{"functionName":"__js_helper$_addHashTableEntry$3","ranges":[{"startOffset":440366,"endOffset":440739,"count":1},{"startOffset":440683,"endOffset":440733,"count":0}],"isBlockCoverage":true},{"functionName":"__js_helper$_removeHashTableEntry$2","ranges":[{"startOffset":440782,"endOffset":441088,"count":1},{"startOffset":440854,"endOffset":440866,"count":0},{"startOffset":440946,"endOffset":440958,"count":0}],"isBlockCoverage":true},{"functionName":"_modified$0","ranges":[{"startOffset":441107,"endOffset":441189,"count":1}],"isBlockCoverage":true},{"functionName":"_newLinkedCell$2","ranges":[{"startOffset":441213,"endOffset":441682,"count":1}],"isBlockCoverage":true},{"functionName":"__js_helper$_unlinkCell$1","ranges":[{"startOffset":441715,"endOffset":442185,"count":1},{"startOffset":441930,"endOffset":441966,"count":0},{"startOffset":442077,"endOffset":442117,"count":0}],"isBlockCoverage":true},{"functionName":"internalComputeHashCode$1","ranges":[{"startOffset":442218,"endOffset":442286,"count":1}],"isBlockCoverage":true},{"functionName":"internalFindBucketIndex$2","ranges":[{"startOffset":442319,"endOffset":442570,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":442588,"endOffset":442649,"count":0}],"isBlockCoverage":false},{"functionName":"_getTableCell$2","ranges":[{"startOffset":442672,"endOffset":442725,"count":1}],"isBlockCoverage":true},{"functionName":"_getTableBucket$2","ranges":[{"startOffset":442750,"endOffset":442803,"count":1}],"isBlockCoverage":true},{"functionName":"_setTableEntry$3","ranges":[{"startOffset":442827,"endOffset":442925,"count":1}],"isBlockCoverage":true},{"functionName":"_deleteTableEntry$2","ranges":[{"startOffset":442952,"endOffset":443005,"count":1}],"isBlockCoverage":true},{"functionName":"_containsTableEntry$2","ranges":[{"startOffset":443034,"endOffset":443117,"count":1}],"isBlockCoverage":true},{"functionName":"_newHashTable$0","ranges":[{"startOffset":443140,"endOffset":443353,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":443445,"endOffset":443569,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":443587,"endOffset":443663,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":443730,"endOffset":443899,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":443917,"endOffset":443998,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":444101,"endOffset":444176,"count":0}],"isBlockCoverage":false},{"functionName":"get$isEmpty","ranges":[{"startOffset":444195,"endOffset":444276,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":444296,"endOffset":444515,"count":1}],"isBlockCoverage":true},{"functionName":"contains$1","ranges":[{"startOffset":444533,"endOffset":444620,"count":0}],"isBlockCoverage":false},{"functionName":"get$current","ranges":[{"startOffset":444686,"endOffset":444744,"count":1}],"isBlockCoverage":true},{"functionName":"moveNext$0","ranges":[{"startOffset":444762,"endOffset":445261,"count":1},{"startOffset":444898,"endOffset":444956,"count":0}],"isBlockCoverage":true},{"functionName":"set$__js_helper$_current","ranges":[{"startOffset":445293,"endOffset":445394,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":445468,"endOffset":445516,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":445591,"endOffset":445656,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":445732,"endOffset":445817,"count":1}],"isBlockCoverage":true},{"functionName":"toString$0","ranges":[{"startOffset":445892,"endOffset":445983,"count":0}],"isBlockCoverage":false},{"functionName":"get$_nativeGlobalVersion","ranges":[{"startOffset":446015,"endOffset":446314,"count":0}],"isBlockCoverage":false},{"functionName":"get$_nativeAnchoredVersion","ranges":[{"startOffset":446348,"endOffset":446659,"count":0}],"isBlockCoverage":false},{"functionName":"firstMatch$1","ranges":[{"startOffset":446679,"endOffset":446942,"count":0}],"isBlockCoverage":false},{"functionName":"allMatches$2","ranges":[{"startOffset":446962,"endOffset":447186,"count":0}],"isBlockCoverage":false},{"functionName":"allMatches$1","ranges":[{"startOffset":447206,"endOffset":447295,"count":0}],"isBlockCoverage":false},{"functionName":"_execGlobal$2","ranges":[{"startOffset":447316,"endOffset":447578,"count":0}],"isBlockCoverage":false},{"functionName":"_execAnchored$2","ranges":[{"startOffset":447601,"endOffset":447981,"count":0}],"isBlockCoverage":false},{"functionName":"matchAsPrefix$2","ranges":[{"startOffset":448004,"endOffset":448222,"count":0}],"isBlockCoverage":false},{"functionName":"get$start","ranges":[{"startOffset":448319,"endOffset":448369,"count":0}],"isBlockCoverage":false},{"functionName":"get$end","ranges":[{"startOffset":448384,"endOffset":448468,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":448482,"endOffset":448669,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":448771,"endOffset":448879,"count":0}],"isBlockCoverage":false},{"functionName":"get$current","ranges":[{"startOffset":448940,"endOffset":448998,"count":0}],"isBlockCoverage":false},{"functionName":"moveNext$0","ranges":[{"startOffset":449016,"endOffset":450272,"count":0}],"isBlockCoverage":false},{"functionName":"get$end","ranges":[{"startOffset":450341,"endOffset":450406,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":450420,"endOffset":450574,"count":0}],"isBlockCoverage":false},{"functionName":"get$start","ranges":[{"startOffset":450608,"endOffset":450651,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":450719,"endOffset":450837,"count":0}],"isBlockCoverage":false},{"functionName":"get$first","ranges":[{"startOffset":450854,"endOffset":451101,"count":0}],"isBlockCoverage":false},{"functionName":"moveNext$0","ranges":[{"startOffset":451167,"endOffset":451827,"count":0}],"isBlockCoverage":false},{"functionName":"get$current","ranges":[{"startOffset":451846,"endOffset":451904,"count":0}],"isBlockCoverage":false},{"functionName":"get$runtimeType","ranges":[{"startOffset":451986,"endOffset":452048,"count":0}],"isBlockCoverage":false},{"functionName":"get$runtimeType","ranges":[{"startOffset":452215,"endOffset":452275,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":452332,"endOffset":452388,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":452487,"endOffset":452644,"count":0}],"isBlockCoverage":false},{"functionName":"$indexSet","ranges":[{"startOffset":452661,"endOffset":452863,"count":0}],"isBlockCoverage":false},{"functionName":"$indexSet","ranges":[{"startOffset":452995,"endOffset":453194,"count":1}],"isBlockCoverage":true},{"functionName":"get$runtimeType","ranges":[{"startOffset":453328,"endOffset":453391,"count":0}],"isBlockCoverage":false},{"functionName":"get$runtimeType","ranges":[{"startOffset":453454,"endOffset":453517,"count":0}],"isBlockCoverage":false},{"functionName":"get$runtimeType","ranges":[{"startOffset":453578,"endOffset":453639,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":453653,"endOffset":453810,"count":0}],"isBlockCoverage":false},{"functionName":"get$runtimeType","ranges":[{"startOffset":453871,"endOffset":453932,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":453946,"endOffset":454103,"count":0}],"isBlockCoverage":false},{"functionName":"get$runtimeType","ranges":[{"startOffset":454163,"endOffset":454223,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":454237,"endOffset":454394,"count":0}],"isBlockCoverage":false},{"functionName":"get$runtimeType","ranges":[{"startOffset":454456,"endOffset":454518,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":454532,"endOffset":454689,"count":0}],"isBlockCoverage":false},{"functionName":"get$runtimeType","ranges":[{"startOffset":454751,"endOffset":454813,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":454827,"endOffset":454984,"count":0}],"isBlockCoverage":false},{"functionName":"sublist$2","ranges":[{"startOffset":455001,"endOffset":455144,"count":0}],"isBlockCoverage":false},{"functionName":"get$runtimeType","ranges":[{"startOffset":455234,"endOffset":455302,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":455320,"endOffset":455376,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":455390,"endOffset":455547,"count":0}],"isBlockCoverage":false},{"functionName":"get$runtimeType","ranges":[{"startOffset":455608,"endOffset":455669,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":455687,"endOffset":455743,"count":1}],"isBlockCoverage":true},{"functionName":"$index","ranges":[{"startOffset":455757,"endOffset":455914,"count":0}],"isBlockCoverage":false},{"functionName":"sublist$2","ranges":[{"startOffset":455931,"endOffset":456073,"count":0}],"isBlockCoverage":false},{"functionName":"_eval$1","ranges":[{"startOffset":456490,"endOffset":456591,"count":1}],"isBlockCoverage":true},{"functionName":"_bind$1","ranges":[{"startOffset":456606,"endOffset":456704,"count":1}],"isBlockCoverage":true},{"functionName":"get$hashCode","ranges":[{"startOffset":456792,"endOffset":457109,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":457120,"endOffset":457259,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":457277,"endOffset":457342,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":457405,"endOffset":457452,"count":0}],"isBlockCoverage":false},{"functionName":"get$message","ranges":[{"startOffset":457535,"endOffset":457582,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":457674,"endOffset":457802,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":457904,"endOffset":458207,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":458319,"endOffset":458367,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":458484,"endOffset":458532,"count":0}],"isBlockCoverage":false},{"functionName":"_TimerImpl$2","ranges":[{"startOffset":458604,"endOffset":458905,"count":1},{"startOffset":458807,"endOffset":458899,"count":0}],"isBlockCoverage":true},{"functionName":"_TimerImpl$periodic$2","ranges":[{"startOffset":458934,"endOffset":459252,"count":0}],"isBlockCoverage":false},{"functionName":"cancel$0","ranges":[{"startOffset":459268,"endOffset":459616,"count":1},{"startOffset":459383,"endOffset":459390,"count":0},{"startOffset":459447,"endOffset":459494,"count":0},{"startOffset":459531,"endOffset":459610,"count":0}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":459697,"endOffset":459817,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":459900,"endOffset":460263,"count":0}],"isBlockCoverage":false},{"functionName":"complete$1","ranges":[{"startOffset":460343,"endOffset":460659,"count":1}],"isBlockCoverage":true},{"functionName":"completeError$2","ranges":[{"startOffset":460682,"endOffset":460845,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":460925,"endOffset":460999,"count":1}],"isBlockCoverage":true},{"functionName":"call$2","ranges":[{"startOffset":461079,"endOffset":461223,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":461310,"endOffset":461408,"count":1}],"isBlockCoverage":true},{"functionName":"get$isBroadcast","ranges":[{"startOffset":461490,"endOffset":461527,"count":0}],"isBlockCoverage":false},{"functionName":"_onPause$0","ranges":[{"startOffset":461590,"endOffset":461608,"count":0}],"isBlockCoverage":false},{"functionName":"_onResume$0","ranges":[{"startOffset":461627,"endOffset":461645,"count":0}],"isBlockCoverage":false},{"functionName":"set$_async$_next","ranges":[{"startOffset":461669,"endOffset":461742,"count":1}],"isBlockCoverage":true},{"functionName":"set$_async$_previous","ranges":[{"startOffset":461770,"endOffset":461855,"count":1}],"isBlockCoverage":true},{"functionName":"get$_mayAddEvent","ranges":[{"startOffset":461928,"endOffset":461976,"count":1}],"isBlockCoverage":true},{"functionName":"_ensureDoneFuture$0","ranges":[{"startOffset":462003,"endOffset":462182,"count":0}],"isBlockCoverage":false},{"functionName":"_removeListener$1","ranges":[{"startOffset":462207,"endOffset":462934,"count":0}],"isBlockCoverage":false},{"functionName":"_subscribe$4","ranges":[{"startOffset":462954,"endOffset":464472,"count":1},{"startOffset":463220,"endOffset":463469,"count":0},{"startOffset":463523,"endOffset":463526,"count":0},{"startOffset":464278,"endOffset":464337,"count":0}],"isBlockCoverage":true},{"functionName":"_recordCancel$1","ranges":[{"startOffset":464495,"endOffset":465046,"count":0}],"isBlockCoverage":false},{"functionName":"_recordPause$1","ranges":[{"startOffset":465068,"endOffset":465181,"count":0}],"isBlockCoverage":false},{"functionName":"_recordResume$1","ranges":[{"startOffset":465204,"endOffset":465317,"count":0}],"isBlockCoverage":false},{"functionName":"_addEventError$0","ranges":[{"startOffset":465341,"endOffset":465610,"count":0}],"isBlockCoverage":false},{"functionName":"add$1","ranges":[{"startOffset":465623,"endOffset":465854,"count":1},{"startOffset":465769,"endOffset":465817,"count":0}],"isBlockCoverage":true},{"functionName":"addError$2","ranges":[{"startOffset":465872,"endOffset":466438,"count":0}],"isBlockCoverage":false},{"functionName":"addError$1","ranges":[{"startOffset":466456,"endOffset":466522,"count":0}],"isBlockCoverage":false},{"functionName":"close$0","ranges":[{"startOffset":466537,"endOffset":466942,"count":0}],"isBlockCoverage":false},{"functionName":"_async$_addError$2","ranges":[{"startOffset":466968,"endOffset":467072,"count":0}],"isBlockCoverage":false},{"functionName":"_close$0","ranges":[{"startOffset":467088,"endOffset":467356,"count":0}],"isBlockCoverage":false},{"functionName":"_forEachListener$1","ranges":[{"startOffset":467382,"endOffset":468483,"count":0}],"isBlockCoverage":false},{"functionName":"_callOnCancel$0","ranges":[{"startOffset":468506,"endOffset":468761,"count":0}],"isBlockCoverage":false},{"functionName":"set$_firstSubscription","ranges":[{"startOffset":468791,"endOffset":468946,"count":1}],"isBlockCoverage":true},{"functionName":"set$_lastSubscription","ranges":[{"startOffset":468975,"endOffset":469127,"count":1}],"isBlockCoverage":true},{"functionName":"set$_addStreamState","ranges":[{"startOffset":469154,"endOffset":469293,"count":0}],"isBlockCoverage":false},{"functionName":"get$_mayAddEvent","ranges":[{"startOffset":469547,"endOffset":469673,"count":1}],"isBlockCoverage":true},{"functionName":"_addEventError$0","ranges":[{"startOffset":469697,"endOffset":469916,"count":0}],"isBlockCoverage":false},{"functionName":"_sendData$1","ranges":[{"startOffset":469935,"endOffset":470463,"count":1},{"startOffset":470076,"endOffset":470083,"count":0},{"startOffset":470308,"endOffset":470332,"count":0},{"startOffset":470356,"endOffset":470462,"count":0}],"isBlockCoverage":true},{"functionName":"_sendError$2","ranges":[{"startOffset":470483,"endOffset":470690,"count":0}],"isBlockCoverage":false},{"functionName":"_sendDone$0","ranges":[{"startOffset":470709,"endOffset":471070,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":471155,"endOffset":471289,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":471307,"endOffset":471403,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":471489,"endOffset":471653,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":471671,"endOffset":471767,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":471852,"endOffset":471979,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":471997,"endOffset":472093,"count":0}],"isBlockCoverage":false},{"functionName":"_sendData$1","ranges":[{"startOffset":472166,"endOffset":472489,"count":0}],"isBlockCoverage":false},{"functionName":"_sendError$2","ranges":[{"startOffset":472509,"endOffset":472759,"count":0}],"isBlockCoverage":false},{"functionName":"_sendDone$0","ranges":[{"startOffset":472778,"endOffset":473214,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":473299,"endOffset":473599,"count":1},{"startOffset":473419,"endOffset":473593,"count":0}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":473686,"endOffset":473986,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":474065,"endOffset":474620,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":474695,"endOffset":475141,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":475159,"endOffset":475217,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":475276,"endOffset":475578,"count":1},{"startOffset":475384,"endOffset":475577,"count":0}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":475657,"endOffset":476933,"count":1},{"startOffset":475992,"endOffset":476655,"count":0},{"startOffset":476684,"endOffset":476827,"count":0}],"isBlockCoverage":true},{"functionName":"toString$0","ranges":[{"startOffset":477010,"endOffset":477201,"count":0}],"isBlockCoverage":false},{"functionName":"get$message","ranges":[{"startOffset":477241,"endOffset":477294,"count":0}],"isBlockCoverage":false},{"functionName":"completeError$2","ranges":[{"startOffset":477380,"endOffset":477925,"count":0}],"isBlockCoverage":false},{"functionName":"completeError$1","ranges":[{"startOffset":477948,"endOffset":478019,"count":0}],"isBlockCoverage":false},{"functionName":"complete$1","ranges":[{"startOffset":478096,"endOffset":478336,"count":1},{"startOffset":478231,"endOffset":478296,"count":0}],"isBlockCoverage":true},{"functionName":"complete$0","ranges":[{"startOffset":478354,"endOffset":478408,"count":1}],"isBlockCoverage":true},{"functionName":"_completeError$2","ranges":[{"startOffset":478432,"endOffset":478527,"count":0}],"isBlockCoverage":false},{"functionName":"complete$1","ranges":[{"startOffset":478582,"endOffset":478817,"count":0}],"isBlockCoverage":false},{"functionName":"complete$0","ranges":[{"startOffset":478835,"endOffset":478889,"count":0}],"isBlockCoverage":false},{"functionName":"_completeError$2","ranges":[{"startOffset":478913,"endOffset":479003,"count":0}],"isBlockCoverage":false},{"functionName":"matchesErrorTest$1","ranges":[{"startOffset":479067,"endOffset":479290,"count":0}],"isBlockCoverage":false},{"functionName":"handleError$1","ranges":[{"startOffset":479311,"endOffset":480110,"count":0}],"isBlockCoverage":false},{"functionName":"then$1$2$onError","ranges":[{"startOffset":480164,"endOffset":480845,"count":1},{"startOffset":480507,"endOffset":480563,"count":0},{"startOffset":480676,"endOffset":480679,"count":0}],"isBlockCoverage":true},{"functionName":"then$1$1","ranges":[{"startOffset":480861,"endOffset":480933,"count":1}],"isBlockCoverage":true},{"functionName":"_thenAwait$1$2","ranges":[{"startOffset":480955,"endOffset":481337,"count":1}],"isBlockCoverage":true},{"functionName":"catchError$1","ranges":[{"startOffset":481357,"endOffset":481806,"count":0}],"isBlockCoverage":false},{"functionName":"whenComplete$1","ranges":[{"startOffset":481828,"endOffset":482281,"count":1}],"isBlockCoverage":true},{"functionName":"_cloneResult$1","ranges":[{"startOffset":482303,"endOffset":482502,"count":0}],"isBlockCoverage":false},{"functionName":"_addListener$1","ranges":[{"startOffset":482524,"endOffset":483257,"count":1},{"startOffset":482868,"endOffset":483106,"count":0}],"isBlockCoverage":true},{"functionName":"_prependListeners$1","ranges":[{"startOffset":483284,"endOffset":484374,"count":1},{"startOffset":483471,"endOffset":484368,"count":0}],"isBlockCoverage":true},{"functionName":"_removeListeners$0","ranges":[{"startOffset":484400,"endOffset":484667,"count":1}],"isBlockCoverage":true},{"functionName":"_reverseListeners$1","ranges":[{"startOffset":484694,"endOffset":484951,"count":1}],"isBlockCoverage":true},{"functionName":"_complete$1","ranges":[{"startOffset":484970,"endOffset":485601,"count":1},{"startOffset":485249,"endOffset":485317,"count":0}],"isBlockCoverage":true},{"functionName":"_completeWithValue$1","ranges":[{"startOffset":485629,"endOffset":486055,"count":1}],"isBlockCoverage":true},{"functionName":"_completeError$2","ranges":[{"startOffset":486079,"endOffset":486469,"count":0}],"isBlockCoverage":false},{"functionName":"_completeError$1","ranges":[{"startOffset":486493,"endOffset":486565,"count":0}],"isBlockCoverage":false},{"functionName":"_asyncComplete$1","ranges":[{"startOffset":486589,"endOffset":487004,"count":1},{"startOffset":486779,"endOffset":486841,"count":0}],"isBlockCoverage":true},{"functionName":"_chainFuture$1","ranges":[{"startOffset":487026,"endOffset":487512,"count":0}],"isBlockCoverage":false},{"functionName":"_asyncCompleteError$2","ranges":[{"startOffset":487541,"endOffset":487857,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":487940,"endOffset":488024,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":488113,"endOffset":488205,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":488296,"endOffset":488475,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":488567,"endOffset":488768,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":488782,"endOffset":488844,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":488937,"endOffset":489007,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":489093,"endOffset":489210,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":489294,"endOffset":489370,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":489461,"endOffset":489543,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":489655,"endOffset":491612,"count":1},{"startOffset":490115,"endOffset":490871,"count":0},{"startOffset":491050,"endOffset":491298,"count":0},{"startOffset":491326,"endOffset":491606,"count":0}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":491732,"endOffset":491785,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":491891,"endOffset":492537,"count":1},{"startOffset":492293,"endOffset":492531,"count":0}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":492634,"endOffset":493916,"count":0}],"isBlockCoverage":false},{"functionName":"get$isBroadcast","ranges":[{"startOffset":494027,"endOffset":494065,"count":1}],"isBlockCoverage":true},{"functionName":"pipe$1","ranges":[{"startOffset":494079,"endOffset":494313,"count":1}],"isBlockCoverage":true},{"functionName":"get$length","ranges":[{"startOffset":494331,"endOffset":494644,"count":0}],"isBlockCoverage":false},{"functionName":"get$first","ranges":[{"startOffset":494661,"endOffset":495037,"count":1}],"isBlockCoverage":true},{"functionName":"get$last","ranges":[{"startOffset":495053,"endOffset":495429,"count":0}],"isBlockCoverage":false},{"functionName":"firstWhere$1","ranges":[{"startOffset":495449,"endOffset":495994,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":496063,"endOffset":496187,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":496205,"endOffset":496263,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":496333,"endOffset":496503,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":496593,"endOffset":496811,"count":1}],"isBlockCoverage":true},{"functionName":"$signature","ranges":[{"startOffset":496829,"endOffset":496907,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":496963,"endOffset":497027,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":497105,"endOffset":497216,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":497234,"endOffset":497320,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":497379,"endOffset":497447,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":497523,"endOffset":497686,"count":1}],"isBlockCoverage":true},{"functionName":"$signature","ranges":[{"startOffset":497704,"endOffset":497790,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":497848,"endOffset":498176,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":498251,"endOffset":498435,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":498453,"endOffset":498539,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":498596,"endOffset":499042,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":499123,"endOffset":499482,"count":1}],"isBlockCoverage":true},{"functionName":"$signature","ranges":[{"startOffset":499500,"endOffset":499586,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":499649,"endOffset":499710,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":499794,"endOffset":499961,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":500044,"endOffset":500372,"count":0}],"isBlockCoverage":false},{"functionName":"get$_pendingEvents","ranges":[{"startOffset":500561,"endOffset":500951,"count":1},{"startOffset":500776,"endOffset":500950,"count":0}],"isBlockCoverage":true},{"functionName":"_ensurePendingEvents$0","ranges":[{"startOffset":500981,"endOffset":501700,"count":0}],"isBlockCoverage":false},{"functionName":"get$_async$_subscription","ranges":[{"startOffset":501732,"endOffset":502152,"count":1}],"isBlockCoverage":true},{"functionName":"_badEventState$0","ranges":[{"startOffset":502176,"endOffset":502426,"count":0}],"isBlockCoverage":false},{"functionName":"addStream$2$cancelOnError","ranges":[{"startOffset":502459,"endOffset":503511,"count":1},{"startOffset":502668,"endOffset":502716,"count":0},{"startOffset":502743,"endOffset":502874,"count":0},{"startOffset":503017,"endOffset":503060,"count":0},{"startOffset":503300,"endOffset":503316,"count":0},{"startOffset":503326,"endOffset":503339,"count":0}],"isBlockCoverage":true},{"functionName":"_ensureDoneFuture$0","ranges":[{"startOffset":503538,"endOffset":503771,"count":1},{"startOffset":503692,"endOffset":503747,"count":0}],"isBlockCoverage":true},{"functionName":"add$1","ranges":[{"startOffset":503784,"endOffset":504005,"count":1},{"startOffset":503924,"endOffset":503972,"count":0}],"isBlockCoverage":true},{"functionName":"addError$2","ranges":[{"startOffset":504023,"endOffset":504587,"count":0}],"isBlockCoverage":false},{"functionName":"addError$1","ranges":[{"startOffset":504605,"endOffset":504671,"count":0}],"isBlockCoverage":false},{"functionName":"close$0","ranges":[{"startOffset":504686,"endOffset":504977,"count":1},{"startOffset":504785,"endOffset":504820,"count":0},{"startOffset":504848,"endOffset":504896,"count":0}],"isBlockCoverage":true},{"functionName":"_closeUnchecked$0","ranges":[{"startOffset":505002,"endOffset":505204,"count":1},{"startOffset":505082,"endOffset":505101,"count":0},{"startOffset":505141,"endOffset":505198,"count":0}],"isBlockCoverage":true},{"functionName":"_add$1","ranges":[{"startOffset":505218,"endOffset":505567,"count":1},{"startOffset":505423,"endOffset":505561,"count":0}],"isBlockCoverage":true},{"functionName":"_async$_addError$2","ranges":[{"startOffset":505593,"endOffset":505900,"count":0}],"isBlockCoverage":false},{"functionName":"_close$0","ranges":[{"startOffset":505916,"endOffset":506256,"count":0}],"isBlockCoverage":false},{"functionName":"_subscribe$4","ranges":[{"startOffset":506276,"endOffset":507433,"count":1},{"startOffset":506562,"endOffset":506639,"count":0},{"startOffset":507026,"endOffset":507213,"count":0}],"isBlockCoverage":true},{"functionName":"_recordCancel$1","ranges":[{"startOffset":507456,"endOffset":508586,"count":1},{"startOffset":507936,"endOffset":508391,"count":0}],"isBlockCoverage":true},{"functionName":"_recordPause$1","ranges":[{"startOffset":508608,"endOffset":508942,"count":1},{"startOffset":508802,"endOffset":508900,"count":0}],"isBlockCoverage":true},{"functionName":"_recordResume$1","ranges":[{"startOffset":508965,"endOffset":509301,"count":1},{"startOffset":509159,"endOffset":509258,"count":0}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":509551,"endOffset":509611,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":509707,"endOffset":509840,"count":1},{"startOffset":509780,"endOffset":509798,"count":0},{"startOffset":509808,"endOffset":509834,"count":0}],"isBlockCoverage":true},{"functionName":"_sendData$1","ranges":[{"startOffset":509930,"endOffset":510047,"count":1}],"isBlockCoverage":true},{"functionName":"_sendError$2","ranges":[{"startOffset":510067,"endOffset":510179,"count":0}],"isBlockCoverage":false},{"functionName":"_sendDone$0","ranges":[{"startOffset":510198,"endOffset":510266,"count":0}],"isBlockCoverage":false},{"functionName":"_sendData$1","ranges":[{"startOffset":510338,"endOffset":510532,"count":0}],"isBlockCoverage":false},{"functionName":"_sendError$2","ranges":[{"startOffset":510552,"endOffset":510680,"count":0}],"isBlockCoverage":false},{"functionName":"_sendDone$0","ranges":[{"startOffset":510699,"endOffset":510788,"count":0}],"isBlockCoverage":false},{"functionName":"_createSubscription$4","ranges":[{"startOffset":510942,"endOffset":511156,"count":1}],"isBlockCoverage":true},{"functionName":"get$hashCode","ranges":[{"startOffset":511176,"endOffset":511275,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":511286,"endOffset":511499,"count":0}],"isBlockCoverage":false},{"functionName":"_onCancel$0","ranges":[{"startOffset":511564,"endOffset":511635,"count":1}],"isBlockCoverage":true},{"functionName":"_onPause$0","ranges":[{"startOffset":511653,"endOffset":511716,"count":1}],"isBlockCoverage":true},{"functionName":"_onResume$0","ranges":[{"startOffset":511735,"endOffset":511799,"count":1}],"isBlockCoverage":true},{"functionName":"add$1","ranges":[{"startOffset":511853,"endOffset":511951,"count":1}],"isBlockCoverage":true},{"functionName":"cancel$0","ranges":[{"startOffset":512090,"endOffset":512350,"count":1},{"startOffset":512181,"endOffset":512264,"count":0}],"isBlockCoverage":true},{"functionName":"call$2","ranges":[{"startOffset":512427,"endOffset":512562,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":512648,"endOffset":512723,"count":1}],"isBlockCoverage":true},{"functionName":"_BufferingStreamSubscription$4","ranges":[{"startOffset":512883,"endOffset":513035,"count":1}],"isBlockCoverage":true},{"functionName":"_setPendingEvents$1","ranges":[{"startOffset":513062,"endOffset":513518,"count":1}],"isBlockCoverage":true},{"functionName":"onData$1","ranges":[{"startOffset":513534,"endOffset":513897,"count":1}],"isBlockCoverage":true},{"functionName":"onError$1","ranges":[{"startOffset":513914,"endOffset":514590,"count":1},{"startOffset":514246,"endOffset":514584,"count":0}],"isBlockCoverage":true},{"functionName":"onDone$1","ranges":[{"startOffset":514606,"endOffset":514849,"count":1}],"isBlockCoverage":true},{"functionName":"pause$1","ranges":[{"startOffset":514864,"endOffset":515291,"count":1},{"startOffset":514982,"endOffset":514989,"count":0},{"startOffset":515094,"endOffset":515186,"count":0},{"startOffset":515240,"endOffset":515285,"count":0}],"isBlockCoverage":true},{"functionName":"pause$0","ranges":[{"startOffset":515306,"endOffset":515357,"count":1}],"isBlockCoverage":true},{"functionName":"resume$0","ranges":[{"startOffset":515373,"endOffset":516055,"count":1},{"startOffset":515471,"endOffset":515478,"count":0},{"startOffset":515591,"endOffset":515675,"count":0},{"startOffset":515735,"endOffset":515768,"count":0}],"isBlockCoverage":true},{"functionName":"cancel$0","ranges":[{"startOffset":516071,"endOffset":516331,"count":1}],"isBlockCoverage":true},{"functionName":"get$_mayResumeInput","ranges":[{"startOffset":516358,"endOffset":516536,"count":1},{"startOffset":516458,"endOffset":516479,"count":0},{"startOffset":516488,"endOffset":516513,"count":0}],"isBlockCoverage":true},{"functionName":"get$isPaused","ranges":[{"startOffset":516556,"endOffset":516607,"count":1}],"isBlockCoverage":true},{"functionName":"_cancel$0","ranges":[{"startOffset":516624,"endOffset":516954,"count":1}],"isBlockCoverage":true},{"functionName":"_add$1","ranges":[{"startOffset":516968,"endOffset":517413,"count":1},{"startOffset":517222,"endOffset":517229,"count":0},{"startOffset":517281,"endOffset":517407,"count":0}],"isBlockCoverage":true},{"functionName":"_async$_addError$2","ranges":[{"startOffset":517439,"endOffset":517688,"count":0}],"isBlockCoverage":false},{"functionName":"_close$0","ranges":[{"startOffset":517704,"endOffset":518023,"count":0}],"isBlockCoverage":false},{"functionName":"_onPause$0","ranges":[{"startOffset":518041,"endOffset":518106,"count":0}],"isBlockCoverage":false},{"functionName":"_onResume$0","ranges":[{"startOffset":518125,"endOffset":518190,"count":0}],"isBlockCoverage":false},{"functionName":"_onCancel$0","ranges":[{"startOffset":518209,"endOffset":518293,"count":1}],"isBlockCoverage":true},{"functionName":"_addPending$1","ranges":[{"startOffset":518314,"endOffset":518843,"count":0}],"isBlockCoverage":false},{"functionName":"_sendData$1","ranges":[{"startOffset":518862,"endOffset":519379,"count":1}],"isBlockCoverage":true},{"functionName":"_sendError$2","ranges":[{"startOffset":519399,"endOffset":520116,"count":0}],"isBlockCoverage":false},{"functionName":"_sendDone$0","ranges":[{"startOffset":520135,"endOffset":520625,"count":0}],"isBlockCoverage":false},{"functionName":"_guardCallback$1","ranges":[{"startOffset":520649,"endOffset":520983,"count":1}],"isBlockCoverage":true},{"functionName":"_checkState$1","ranges":[{"startOffset":521004,"endOffset":522070,"count":1},{"startOffset":521160,"endOffset":521231,"count":0},{"startOffset":521271,"endOffset":521474,"count":0},{"startOffset":521848,"endOffset":521892,"count":0},{"startOffset":522010,"endOffset":522021,"count":0},{"startOffset":522031,"endOffset":522064,"count":0}],"isBlockCoverage":true},{"functionName":"set$_onData","ranges":[{"startOffset":522089,"endOffset":522219,"count":1}],"isBlockCoverage":true},{"functionName":"set$_onDone","ranges":[{"startOffset":522238,"endOffset":522321,"count":1}],"isBlockCoverage":true},{"functionName":"set$_pending","ranges":[{"startOffset":522341,"endOffset":522487,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":522629,"endOffset":523285,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":523388,"endOffset":523626,"count":0}],"isBlockCoverage":false},{"functionName":"listen$4$cancelOnError$onDone$onError","ranges":[{"startOffset":523724,"endOffset":523966,"count":1}],"isBlockCoverage":true},{"functionName":"listen$2$onDone","ranges":[{"startOffset":523989,"endOffset":524106,"count":1}],"isBlockCoverage":true},{"functionName":"listen$3$onDone$onError","ranges":[{"startOffset":524137,"endOffset":524266,"count":1}],"isBlockCoverage":true},{"functionName":"listen$1","ranges":[{"startOffset":524282,"endOffset":524389,"count":1}],"isBlockCoverage":true},{"functionName":"_createSubscription$4","ranges":[{"startOffset":524418,"endOffset":524671,"count":0}],"isBlockCoverage":false},{"functionName":"_createSubscription$4","ranges":[{"startOffset":524743,"endOffset":525243,"count":1},{"startOffset":524958,"endOffset":525035,"count":0}],"isBlockCoverage":true},{"functionName":"get$isEmpty","ranges":[{"startOffset":525307,"endOffset":525370,"count":1}],"isBlockCoverage":true},{"functionName":"handleNext$1","ranges":[{"startOffset":525390,"endOffset":526251,"count":0}],"isBlockCoverage":false},{"functionName":"set$_async$_iterator","ranges":[{"startOffset":526279,"endOffset":526387,"count":0}],"isBlockCoverage":false},{"functionName":"set$next","ranges":[{"startOffset":526439,"endOffset":526521,"count":0}],"isBlockCoverage":false},{"functionName":"get$next","ranges":[{"startOffset":526537,"endOffset":526579,"count":0}],"isBlockCoverage":false},{"functionName":"perform$1","ranges":[{"startOffset":526631,"endOffset":526743,"count":0}],"isBlockCoverage":false},{"functionName":"perform$1","ranges":[{"startOffset":526796,"endOffset":526880,"count":0}],"isBlockCoverage":false},{"functionName":"perform$1","ranges":[{"startOffset":526932,"endOffset":526988,"count":0}],"isBlockCoverage":false},{"functionName":"get$next","ranges":[{"startOffset":527004,"endOffset":527041,"count":0}],"isBlockCoverage":false},{"functionName":"set$next","ranges":[{"startOffset":527057,"endOffset":527147,"count":0}],"isBlockCoverage":false},{"functionName":"schedule$1","ranges":[{"startOffset":527227,"endOffset":527689,"count":1},{"startOffset":527390,"endOffset":527397,"count":0},{"startOffset":527491,"endOffset":527576,"count":0}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":527757,"endOffset":527933,"count":1},{"startOffset":527889,"endOffset":527932,"count":0}],"isBlockCoverage":true},{"functionName":"get$isEmpty","ranges":[{"startOffset":528011,"endOffset":528074,"count":0}],"isBlockCoverage":false},{"functionName":"add$1","ranges":[{"startOffset":528087,"endOffset":528355,"count":0}],"isBlockCoverage":false},{"functionName":"handleNext$1","ranges":[{"startOffset":528375,"endOffset":528743,"count":0}],"isBlockCoverage":false},{"functionName":"get$isPaused","ranges":[{"startOffset":528809,"endOffset":528858,"count":0}],"isBlockCoverage":false},{"functionName":"_schedule$0","ranges":[{"startOffset":528877,"endOffset":529080,"count":0}],"isBlockCoverage":false},{"functionName":"onData$1","ranges":[{"startOffset":529096,"endOffset":529175,"count":0}],"isBlockCoverage":false},{"functionName":"onError$1","ranges":[{"startOffset":529192,"endOffset":529224,"count":0}],"isBlockCoverage":false},{"functionName":"onDone$1","ranges":[{"startOffset":529240,"endOffset":529332,"count":0}],"isBlockCoverage":false},{"functionName":"pause$1","ranges":[{"startOffset":529347,"endOffset":529401,"count":0}],"isBlockCoverage":false},{"functionName":"pause$0","ranges":[{"startOffset":529416,"endOffset":529467,"count":0}],"isBlockCoverage":false},{"functionName":"resume$0","ranges":[{"startOffset":529483,"endOffset":529661,"count":0}],"isBlockCoverage":false},{"functionName":"cancel$0","ranges":[{"startOffset":529677,"endOffset":529737,"count":0}],"isBlockCoverage":false},{"functionName":"_sendDone$0","ranges":[{"startOffset":529756,"endOffset":530019,"count":0}],"isBlockCoverage":false},{"functionName":"set$_onDone","ranges":[{"startOffset":530038,"endOffset":530121,"count":0}],"isBlockCoverage":false},{"functionName":"get$isBroadcast","ranges":[{"startOffset":530245,"endOffset":530282,"count":0}],"isBlockCoverage":false},{"functionName":"listen$4$cancelOnError$onDone$onError","ranges":[{"startOffset":530327,"endOffset":530684,"count":0}],"isBlockCoverage":false},{"functionName":"listen$3$onDone$onError","ranges":[{"startOffset":530715,"endOffset":530844,"count":0}],"isBlockCoverage":false},{"functionName":"listen$1","ranges":[{"startOffset":530860,"endOffset":530967,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":531027,"endOffset":531117,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":531203,"endOffset":531339,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":531418,"endOffset":531486,"count":1}],"isBlockCoverage":true},{"functionName":"toString$0","ranges":[{"startOffset":531582,"endOffset":531631,"count":0}],"isBlockCoverage":false},{"functionName":"handleUncaughtError$3","ranges":[{"startOffset":531905,"endOffset":532247,"count":0}],"isBlockCoverage":false},{"functionName":"registerCallback$1$2","ranges":[{"startOffset":532275,"endOffset":532668,"count":1}],"isBlockCoverage":true},{"functionName":"registerUnaryCallback$2$2","ranges":[{"startOffset":532701,"endOffset":533146,"count":1}],"isBlockCoverage":true},{"functionName":"registerBinaryCallback$3$2","ranges":[{"startOffset":533180,"endOffset":533670,"count":1}],"isBlockCoverage":true},{"functionName":"errorCallback$3","ranges":[{"startOffset":533693,"endOffset":534015,"count":0}],"isBlockCoverage":false},{"functionName":"get$_delegate","ranges":[{"startOffset":534130,"endOffset":534287,"count":1}],"isBlockCoverage":true},{"functionName":"get$errorZone","ranges":[{"startOffset":534308,"endOffset":534371,"count":1}],"isBlockCoverage":true},{"functionName":"runGuarded$1","ranges":[{"startOffset":534391,"endOffset":534691,"count":1},{"startOffset":534526,"endOffset":534685,"count":0}],"isBlockCoverage":true},{"functionName":"runUnaryGuarded$1$2","ranges":[{"startOffset":534718,"endOffset":535062,"count":1},{"startOffset":534897,"endOffset":535056,"count":0}],"isBlockCoverage":true},{"functionName":"runBinaryGuarded$2$3","ranges":[{"startOffset":535090,"endOffset":535511,"count":0}],"isBlockCoverage":false},{"functionName":"bindCallback$1$1","ranges":[{"startOffset":535535,"endOffset":535681,"count":1}],"isBlockCoverage":true},{"functionName":"bindUnaryCallback$2$1","ranges":[{"startOffset":535710,"endOffset":535907,"count":0}],"isBlockCoverage":false},{"functionName":"bindCallbackGuarded$1","ranges":[{"startOffset":535936,"endOffset":536091,"count":1}],"isBlockCoverage":true},{"functionName":"bindUnaryCallbackGuarded$1$1","ranges":[{"startOffset":536127,"endOffset":536303,"count":1}],"isBlockCoverage":true},{"functionName":"$index","ranges":[{"startOffset":536317,"endOffset":536623,"count":1}],"isBlockCoverage":true},{"functionName":"handleUncaughtError$2","ranges":[{"startOffset":536652,"endOffset":537041,"count":0}],"isBlockCoverage":false},{"functionName":"fork$2$specification$zoneValues","ranges":[{"startOffset":537080,"endOffset":537413,"count":1}],"isBlockCoverage":true},{"functionName":"run$1$1","ranges":[{"startOffset":537428,"endOffset":537846,"count":1}],"isBlockCoverage":true},{"functionName":"runUnary$2$2","ranges":[{"startOffset":537866,"endOffset":538372,"count":1}],"isBlockCoverage":true},{"functionName":"runBinary$3$3","ranges":[{"startOffset":538393,"endOffset":538980,"count":0}],"isBlockCoverage":false},{"functionName":"registerCallback$1$1","ranges":[{"startOffset":539008,"endOffset":539469,"count":1}],"isBlockCoverage":true},{"functionName":"registerUnaryCallback$2$1","ranges":[{"startOffset":539502,"endOffset":540015,"count":1}],"isBlockCoverage":true},{"functionName":"registerBinaryCallback$3$1","ranges":[{"startOffset":540049,"endOffset":540607,"count":1}],"isBlockCoverage":true},{"functionName":"errorCallback$2","ranges":[{"startOffset":540630,"endOffset":541146,"count":0}],"isBlockCoverage":false},{"functionName":"scheduleMicrotask$1","ranges":[{"startOffset":541173,"endOffset":541522,"count":1}],"isBlockCoverage":true},{"functionName":"createTimer$2","ranges":[{"startOffset":541543,"endOffset":541906,"count":1}],"isBlockCoverage":true},{"functionName":"print$1","ranges":[{"startOffset":541921,"endOffset":542216,"count":0}],"isBlockCoverage":false},{"functionName":"set$_run","ranges":[{"startOffset":542232,"endOffset":542315,"count":1}],"isBlockCoverage":true},{"functionName":"set$_runUnary","ranges":[{"startOffset":542336,"endOffset":542434,"count":1}],"isBlockCoverage":true},{"functionName":"set$_runBinary","ranges":[{"startOffset":542456,"endOffset":542557,"count":1}],"isBlockCoverage":true},{"functionName":"set$_registerCallback","ranges":[{"startOffset":542586,"endOffset":542708,"count":1}],"isBlockCoverage":true},{"functionName":"set$_registerUnaryCallback","ranges":[{"startOffset":542742,"endOffset":542879,"count":1}],"isBlockCoverage":true},{"functionName":"set$_registerBinaryCallback","ranges":[{"startOffset":542914,"endOffset":543054,"count":1}],"isBlockCoverage":true},{"functionName":"set$_errorCallback","ranges":[{"startOffset":543080,"endOffset":543248,"count":1}],"isBlockCoverage":true},{"functionName":"set$_scheduleMicrotask","ranges":[{"startOffset":543278,"endOffset":543462,"count":1}],"isBlockCoverage":true},{"functionName":"set$_createTimer","ranges":[{"startOffset":543486,"endOffset":543666,"count":1}],"isBlockCoverage":true},{"functionName":"set$_createPeriodicTimer","ranges":[{"startOffset":543698,"endOffset":543908,"count":1}],"isBlockCoverage":true},{"functionName":"set$_print","ranges":[{"startOffset":543926,"endOffset":544053,"count":1}],"isBlockCoverage":true},{"functionName":"set$_fork","ranges":[{"startOffset":544070,"endOffset":544243,"count":1}],"isBlockCoverage":true},{"functionName":"set$_handleUncaughtError","ranges":[{"startOffset":544275,"endOffset":544455,"count":1}],"isBlockCoverage":true},{"functionName":"get$_run","ranges":[{"startOffset":544471,"endOffset":544513,"count":1}],"isBlockCoverage":true},{"functionName":"get$_runUnary","ranges":[{"startOffset":544534,"endOffset":544581,"count":1}],"isBlockCoverage":true},{"functionName":"get$_runBinary","ranges":[{"startOffset":544603,"endOffset":544651,"count":1}],"isBlockCoverage":true},{"functionName":"get$_registerCallback","ranges":[{"startOffset":544680,"endOffset":544735,"count":1}],"isBlockCoverage":true},{"functionName":"get$_registerUnaryCallback","ranges":[{"startOffset":544769,"endOffset":544829,"count":1}],"isBlockCoverage":true},{"functionName":"get$_registerBinaryCallback","ranges":[{"startOffset":544864,"endOffset":544925,"count":1}],"isBlockCoverage":true},{"functionName":"get$_errorCallback","ranges":[{"startOffset":544951,"endOffset":545003,"count":1}],"isBlockCoverage":true},{"functionName":"get$_scheduleMicrotask","ranges":[{"startOffset":545033,"endOffset":545089,"count":1}],"isBlockCoverage":true},{"functionName":"get$_createTimer","ranges":[{"startOffset":545113,"endOffset":545163,"count":1}],"isBlockCoverage":true},{"functionName":"get$_createPeriodicTimer","ranges":[{"startOffset":545195,"endOffset":545253,"count":1}],"isBlockCoverage":true},{"functionName":"get$_print","ranges":[{"startOffset":545271,"endOffset":545315,"count":1}],"isBlockCoverage":true},{"functionName":"get$_fork","ranges":[{"startOffset":545332,"endOffset":545375,"count":1}],"isBlockCoverage":true},{"functionName":"get$_handleUncaughtError","ranges":[{"startOffset":545407,"endOffset":545465,"count":1}],"isBlockCoverage":true},{"functionName":"get$parent","ranges":[{"startOffset":545483,"endOffset":545535,"count":1}],"isBlockCoverage":true},{"functionName":"get$_async$_map","ranges":[{"startOffset":545558,"endOffset":545607,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":545676,"endOffset":545752,"count":1}],"isBlockCoverage":true},{"functionName":"$signature","ranges":[{"startOffset":545770,"endOffset":545824,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":545898,"endOffset":546051,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":546069,"endOffset":546156,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":546232,"endOffset":546305,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":546405,"endOffset":546531,"count":1}],"isBlockCoverage":true},{"functionName":"$signature","ranges":[{"startOffset":546549,"endOffset":546604,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":546673,"endOffset":546999,"count":0}],"isBlockCoverage":false},{"functionName":"get$_run","ranges":[{"startOffset":547066,"endOffset":547133,"count":1}],"isBlockCoverage":true},{"functionName":"get$_runUnary","ranges":[{"startOffset":547154,"endOffset":547226,"count":1}],"isBlockCoverage":true},{"functionName":"get$_runBinary","ranges":[{"startOffset":547248,"endOffset":547321,"count":1}],"isBlockCoverage":true},{"functionName":"get$_registerCallback","ranges":[{"startOffset":547350,"endOffset":547430,"count":1}],"isBlockCoverage":true},{"functionName":"get$_registerUnaryCallback","ranges":[{"startOffset":547464,"endOffset":547516,"count":1}],"isBlockCoverage":true},{"functionName":"get$_registerBinaryCallback","ranges":[{"startOffset":547551,"endOffset":547603,"count":1}],"isBlockCoverage":true},{"functionName":"get$_errorCallback","ranges":[{"startOffset":547629,"endOffset":547706,"count":1}],"isBlockCoverage":true},{"functionName":"get$_scheduleMicrotask","ranges":[{"startOffset":547736,"endOffset":547817,"count":1}],"isBlockCoverage":true},{"functionName":"get$_createTimer","ranges":[{"startOffset":547841,"endOffset":547916,"count":1}],"isBlockCoverage":true},{"functionName":"get$_createPeriodicTimer","ranges":[{"startOffset":547948,"endOffset":548000,"count":1}],"isBlockCoverage":true},{"functionName":"get$_print","ranges":[{"startOffset":548018,"endOffset":548087,"count":1}],"isBlockCoverage":true},{"functionName":"get$_fork","ranges":[{"startOffset":548104,"endOffset":548172,"count":1}],"isBlockCoverage":true},{"functionName":"get$_handleUncaughtError","ranges":[{"startOffset":548204,"endOffset":548256,"count":1}],"isBlockCoverage":true},{"functionName":"get$parent","ranges":[{"startOffset":548274,"endOffset":548312,"count":1}],"isBlockCoverage":true},{"functionName":"get$_async$_map","ranges":[{"startOffset":548335,"endOffset":548395,"count":0}],"isBlockCoverage":false},{"functionName":"get$_delegate","ranges":[{"startOffset":548416,"endOffset":548585,"count":0}],"isBlockCoverage":false},{"functionName":"get$errorZone","ranges":[{"startOffset":548606,"endOffset":548643,"count":1}],"isBlockCoverage":true},{"functionName":"runGuarded$1","ranges":[{"startOffset":548663,"endOffset":549139,"count":0}],"isBlockCoverage":false},{"functionName":"runUnaryGuarded$1$2","ranges":[{"startOffset":549166,"endOffset":549689,"count":1},{"startOffset":549479,"endOffset":549683,"count":0}],"isBlockCoverage":true},{"functionName":"runBinaryGuarded$2$3","ranges":[{"startOffset":549717,"endOffset":550324,"count":0}],"isBlockCoverage":false},{"functionName":"bindCallback$1$1","ranges":[{"startOffset":550348,"endOffset":550461,"count":0}],"isBlockCoverage":false},{"functionName":"bindCallbackGuarded$1","ranges":[{"startOffset":550490,"endOffset":550604,"count":0}],"isBlockCoverage":false},{"functionName":"bindUnaryCallbackGuarded$1$1","ranges":[{"startOffset":550640,"endOffset":550766,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":550780,"endOffset":550823,"count":0}],"isBlockCoverage":false},{"functionName":"handleUncaughtError$2","ranges":[{"startOffset":550852,"endOffset":550983,"count":0}],"isBlockCoverage":false},{"functionName":"fork$2$specification$zoneValues","ranges":[{"startOffset":551022,"endOffset":551136,"count":1}],"isBlockCoverage":true},{"functionName":"run$1$1","ranges":[{"startOffset":551151,"endOffset":551331,"count":0}],"isBlockCoverage":false},{"functionName":"runUnary$2$2","ranges":[{"startOffset":551351,"endOffset":551608,"count":1},{"startOffset":551538,"endOffset":551607,"count":0}],"isBlockCoverage":true},{"functionName":"runBinary$3$3","ranges":[{"startOffset":551629,"endOffset":551954,"count":0}],"isBlockCoverage":false},{"functionName":"registerCallback$1$1","ranges":[{"startOffset":551982,"endOffset":552047,"count":1}],"isBlockCoverage":true},{"functionName":"registerUnaryCallback$2$1","ranges":[{"startOffset":552080,"endOffset":552178,"count":1}],"isBlockCoverage":true},{"functionName":"registerBinaryCallback$3$1","ranges":[{"startOffset":552212,"endOffset":552328,"count":1}],"isBlockCoverage":true},{"functionName":"errorCallback$2","ranges":[{"startOffset":552351,"endOffset":552448,"count":0}],"isBlockCoverage":false},{"functionName":"scheduleMicrotask$1","ranges":[{"startOffset":552475,"endOffset":552575,"count":1}],"isBlockCoverage":true},{"functionName":"createTimer$2","ranges":[{"startOffset":552596,"endOffset":552701,"count":0}],"isBlockCoverage":false},{"functionName":"print$1","ranges":[{"startOffset":552716,"endOffset":552768,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":552835,"endOffset":552902,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":552920,"endOffset":552974,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":553048,"endOffset":553112,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":553210,"endOffset":553327,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":553345,"endOffset":553400,"count":0}],"isBlockCoverage":false},{"functionName":"call$5","ranges":[{"startOffset":553453,"endOffset":554320,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":554389,"endOffset":554447,"count":0}],"isBlockCoverage":false},{"functionName":"get$isEmpty","ranges":[{"startOffset":554466,"endOffset":554530,"count":0}],"isBlockCoverage":false},{"functionName":"get$keys","ranges":[{"startOffset":554546,"endOffset":554667,"count":0}],"isBlockCoverage":false},{"functionName":"containsKey$1","ranges":[{"startOffset":554688,"endOffset":555100,"count":1},{"startOffset":554860,"endOffset":554882,"count":0},{"startOffset":554924,"endOffset":554953,"count":0},{"startOffset":554955,"endOffset":555048,"count":0}],"isBlockCoverage":true},{"functionName":"_containsKey$1","ranges":[{"startOffset":555122,"endOffset":555308,"count":1}],"isBlockCoverage":true},{"functionName":"$index","ranges":[{"startOffset":555322,"endOffset":555803,"count":1},{"startOffset":555403,"endOffset":555425,"count":0},{"startOffset":555427,"endOffset":555567,"count":0},{"startOffset":555600,"endOffset":555629,"count":0},{"startOffset":555631,"endOffset":555759,"count":0}],"isBlockCoverage":true},{"functionName":"_get$1","ranges":[{"startOffset":555817,"endOffset":556095,"count":1},{"startOffset":555929,"endOffset":555941,"count":0}],"isBlockCoverage":true},{"functionName":"$indexSet","ranges":[{"startOffset":556112,"endOffset":556762,"count":1},{"startOffset":556316,"endOffset":556338,"count":0},{"startOffset":556340,"endOffset":556504,"count":0},{"startOffset":556537,"endOffset":556566,"count":0},{"startOffset":556568,"endOffset":556717,"count":0}],"isBlockCoverage":true},{"functionName":"_set$2","ranges":[{"startOffset":556776,"endOffset":557585,"count":1},{"startOffset":557442,"endOffset":557571,"count":0}],"isBlockCoverage":true},{"functionName":"remove$1","ranges":[{"startOffset":557601,"endOffset":557678,"count":0}],"isBlockCoverage":false},{"functionName":"_remove$1","ranges":[{"startOffset":557695,"endOffset":558203,"count":0}],"isBlockCoverage":false},{"functionName":"forEach$1","ranges":[{"startOffset":558220,"endOffset":558693,"count":0}],"isBlockCoverage":false},{"functionName":"_computeKeys$0","ranges":[{"startOffset":558715,"endOffset":560019,"count":0}],"isBlockCoverage":false},{"functionName":"_addHashTableEntry$3","ranges":[{"startOffset":560047,"endOffset":560344,"count":0}],"isBlockCoverage":false},{"functionName":"_computeHashCode$1","ranges":[{"startOffset":560370,"endOffset":560439,"count":1}],"isBlockCoverage":true},{"functionName":"_getBucket$2","ranges":[{"startOffset":560459,"endOffset":560537,"count":1}],"isBlockCoverage":true},{"functionName":"_findBucketIndex$2","ranges":[{"startOffset":560563,"endOffset":560802,"count":1},{"startOffset":560779,"endOffset":560801,"count":0}],"isBlockCoverage":true},{"functionName":"_computeHashCode$1","ranges":[{"startOffset":560867,"endOffset":560937,"count":1}],"isBlockCoverage":true},{"functionName":"_findBucketIndex$2","ranges":[{"startOffset":560963,"endOffset":561255,"count":1},{"startOffset":561057,"endOffset":561254,"count":0}],"isBlockCoverage":true},{"functionName":"get$length","ranges":[{"startOffset":561315,"endOffset":561378,"count":0}],"isBlockCoverage":false},{"functionName":"get$isEmpty","ranges":[{"startOffset":561397,"endOffset":561466,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":561486,"endOffset":561640,"count":0}],"isBlockCoverage":false},{"functionName":"contains$1","ranges":[{"startOffset":561658,"endOffset":561733,"count":0}],"isBlockCoverage":false},{"functionName":"get$current","ranges":[{"startOffset":561794,"endOffset":561852,"count":0}],"isBlockCoverage":false},{"functionName":"moveNext$0","ranges":[{"startOffset":561870,"endOffset":562335,"count":0}],"isBlockCoverage":false},{"functionName":"set$_collection$_current","ranges":[{"startOffset":562367,"endOffset":562468,"count":0}],"isBlockCoverage":false},{"functionName":"_newSet$0","ranges":[{"startOffset":562542,"endOffset":562647,"count":1}],"isBlockCoverage":true},{"functionName":"get$iterator","ranges":[{"startOffset":562667,"endOffset":562927,"count":1}],"isBlockCoverage":true},{"functionName":"get$length","ranges":[{"startOffset":562945,"endOffset":563003,"count":0}],"isBlockCoverage":false},{"functionName":"get$isEmpty","ranges":[{"startOffset":563022,"endOffset":563086,"count":0}],"isBlockCoverage":false},{"functionName":"contains$1","ranges":[{"startOffset":563104,"endOffset":563663,"count":1},{"startOffset":563301,"endOffset":563382,"count":0},{"startOffset":563533,"endOffset":563657,"count":0}],"isBlockCoverage":true},{"functionName":"_contains$1","ranges":[{"startOffset":563682,"endOffset":563883,"count":0}],"isBlockCoverage":false},{"functionName":"get$first","ranges":[{"startOffset":563900,"endOffset":564112,"count":0}],"isBlockCoverage":false},{"functionName":"get$last","ranges":[{"startOffset":564128,"endOffset":564339,"count":0}],"isBlockCoverage":false},{"functionName":"add$1","ranges":[{"startOffset":564352,"endOffset":565009,"count":1},{"startOffset":564713,"endOffset":565003,"count":0}],"isBlockCoverage":true},{"functionName":"_collection$_add$1","ranges":[{"startOffset":565035,"endOffset":565721,"count":0}],"isBlockCoverage":false},{"functionName":"remove$1","ranges":[{"startOffset":565737,"endOffset":566117,"count":1},{"startOffset":565819,"endOffset":565844,"count":0},{"startOffset":565854,"endOffset":565915,"count":0},{"startOffset":566060,"endOffset":566111,"count":0}],"isBlockCoverage":true},{"functionName":"_remove$1","ranges":[{"startOffset":566134,"endOffset":566619,"count":0}],"isBlockCoverage":false},{"functionName":"_addHashTableEntry$2","ranges":[{"startOffset":566647,"endOffset":566913,"count":1},{"startOffset":566808,"endOffset":566821,"count":0}],"isBlockCoverage":true},{"functionName":"_removeHashTableEntry$2","ranges":[{"startOffset":566944,"endOffset":567227,"count":1},{"startOffset":567033,"endOffset":567226,"count":0}],"isBlockCoverage":true},{"functionName":"_collection$_modified$0","ranges":[{"startOffset":567258,"endOffset":567366,"count":1}],"isBlockCoverage":true},{"functionName":"_collection$_newLinkedCell$1","ranges":[{"startOffset":567402,"endOffset":567925,"count":1}],"isBlockCoverage":true},{"functionName":"_unlinkCell$1","ranges":[{"startOffset":567946,"endOffset":568524,"count":0}],"isBlockCoverage":false},{"functionName":"_computeHashCode$1","ranges":[{"startOffset":568550,"endOffset":568627,"count":0}],"isBlockCoverage":false},{"functionName":"_findBucketIndex$2","ranges":[{"startOffset":568653,"endOffset":568906,"count":0}],"isBlockCoverage":false},{"functionName":"get$current","ranges":[{"startOffset":569034,"endOffset":569092,"count":0}],"isBlockCoverage":false},{"functionName":"moveNext$0","ranges":[{"startOffset":569110,"endOffset":569695,"count":1},{"startOffset":569258,"endOffset":569316,"count":0},{"startOffset":569475,"endOffset":569681,"count":0}],"isBlockCoverage":true},{"functionName":"set$_collection$_current","ranges":[{"startOffset":569727,"endOffset":569828,"count":1}],"isBlockCoverage":true},{"functionName":"get$length","ranges":[{"startOffset":569909,"endOffset":570001,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":570015,"endOffset":570118,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":570183,"endOffset":570273,"count":1}],"isBlockCoverage":true},{"functionName":"call$2","ranges":[{"startOffset":570402,"endOffset":570492,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":570649,"endOffset":570808,"count":0}],"isBlockCoverage":false},{"functionName":"elementAt$1","ranges":[{"startOffset":570827,"endOffset":570903,"count":0}],"isBlockCoverage":false},{"functionName":"get$isEmpty","ranges":[{"startOffset":570922,"endOffset":570994,"count":0}],"isBlockCoverage":false},{"functionName":"get$first","ranges":[{"startOffset":571011,"endOffset":571186,"count":0}],"isBlockCoverage":false},{"functionName":"get$last","ranges":[{"startOffset":571202,"endOffset":571405,"count":0}],"isBlockCoverage":false},{"functionName":"map$1$1","ranges":[{"startOffset":571420,"endOffset":571672,"count":0}],"isBlockCoverage":false},{"functionName":"toList$1$growable","ranges":[{"startOffset":571697,"endOffset":572067,"count":0}],"isBlockCoverage":false},{"functionName":"toList$0","ranges":[{"startOffset":572083,"endOffset":572164,"count":0}],"isBlockCoverage":false},{"functionName":"toSet$0","ranges":[{"startOffset":572179,"endOffset":572441,"count":0}],"isBlockCoverage":false},{"functionName":"remove$1","ranges":[{"startOffset":572457,"endOffset":572717,"count":0}],"isBlockCoverage":false},{"functionName":"_closeGap$2","ranges":[{"startOffset":572736,"endOffset":573112,"count":0}],"isBlockCoverage":false},{"functionName":"fillRange$3","ranges":[{"startOffset":573131,"endOffset":573410,"count":1}],"isBlockCoverage":true},{"functionName":"toString$0","ranges":[{"startOffset":573428,"endOffset":573524,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":573616,"endOffset":573883,"count":0}],"isBlockCoverage":false},{"functionName":"cast$2$0","ranges":[{"startOffset":573949,"endOffset":574109,"count":1}],"isBlockCoverage":true},{"functionName":"forEach$1","ranges":[{"startOffset":574126,"endOffset":574420,"count":0}],"isBlockCoverage":false},{"functionName":"map$2$1","ranges":[{"startOffset":574435,"endOffset":574940,"count":1}],"isBlockCoverage":true},{"functionName":"containsKey$1","ranges":[{"startOffset":574961,"endOffset":575031,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":575049,"endOffset":575132,"count":0}],"isBlockCoverage":false},{"functionName":"get$isEmpty","ranges":[{"startOffset":575151,"endOffset":575235,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":575253,"endOffset":575314,"count":0}],"isBlockCoverage":false},{"functionName":"remove$1","ranges":[{"startOffset":575389,"endOffset":575497,"count":0}],"isBlockCoverage":false},{"functionName":"cast$2$0","ranges":[{"startOffset":575543,"endOffset":575614,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":575628,"endOffset":575691,"count":0}],"isBlockCoverage":false},{"functionName":"containsKey$1","ranges":[{"startOffset":575712,"endOffset":575776,"count":0}],"isBlockCoverage":false},{"functionName":"forEach$1","ranges":[{"startOffset":575793,"endOffset":575906,"count":1}],"isBlockCoverage":true},{"functionName":"get$isEmpty","ranges":[{"startOffset":575925,"endOffset":576003,"count":1}],"isBlockCoverage":true},{"functionName":"get$length","ranges":[{"startOffset":576021,"endOffset":576098,"count":0}],"isBlockCoverage":false},{"functionName":"get$keys","ranges":[{"startOffset":576114,"endOffset":576167,"count":0}],"isBlockCoverage":false},{"functionName":"remove$1","ranges":[{"startOffset":576183,"endOffset":576248,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":576266,"endOffset":576323,"count":0}],"isBlockCoverage":false},{"functionName":"map$2$1","ranges":[{"startOffset":576338,"endOffset":576514,"count":1}],"isBlockCoverage":true},{"functionName":"cast$2$0","ranges":[{"startOffset":576587,"endOffset":576753,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":576805,"endOffset":576990,"count":0}],"isBlockCoverage":false},{"functionName":"get$isEmpty","ranges":[{"startOffset":577009,"endOffset":577068,"count":1}],"isBlockCoverage":true},{"functionName":"get$length","ranges":[{"startOffset":577086,"endOffset":577176,"count":0}],"isBlockCoverage":false},{"functionName":"get$first","ranges":[{"startOffset":577193,"endOffset":577451,"count":0}],"isBlockCoverage":false},{"functionName":"get$last","ranges":[{"startOffset":577467,"endOffset":577803,"count":0}],"isBlockCoverage":false},{"functionName":"elementAt$1","ranges":[{"startOffset":577822,"endOffset":578227,"count":0}],"isBlockCoverage":false},{"functionName":"clear$0","ranges":[{"startOffset":578242,"endOffset":578565,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":578583,"endOffset":578668,"count":0}],"isBlockCoverage":false},{"functionName":"removeFirst$0","ranges":[{"startOffset":578689,"endOffset":579148,"count":1},{"startOffset":578802,"endOffset":578860,"count":0},{"startOffset":578955,"endOffset":578978,"count":0}],"isBlockCoverage":true},{"functionName":"_collection$_add$1","ranges":[{"startOffset":579174,"endOffset":580057,"count":1},{"startOffset":579524,"endOffset":580017,"count":0}],"isBlockCoverage":true},{"functionName":"set$_table","ranges":[{"startOffset":580075,"endOffset":580163,"count":1}],"isBlockCoverage":true},{"functionName":"get$current","ranges":[{"startOffset":580240,"endOffset":580298,"count":0}],"isBlockCoverage":false},{"functionName":"moveNext$0","ranges":[{"startOffset":580316,"endOffset":580875,"count":0}],"isBlockCoverage":false},{"functionName":"set$_collection$_current","ranges":[{"startOffset":580907,"endOffset":581008,"count":0}],"isBlockCoverage":false},{"functionName":"get$isEmpty","ranges":[{"startOffset":581078,"endOffset":581139,"count":0}],"isBlockCoverage":false},{"functionName":"map$1$1","ranges":[{"startOffset":581154,"endOffset":581394,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":581412,"endOffset":581497,"count":0}],"isBlockCoverage":false},{"functionName":"every$1","ranges":[{"startOffset":581512,"endOffset":581772,"count":0}],"isBlockCoverage":false},{"functionName":"get$first","ranges":[{"startOffset":581789,"endOffset":581974,"count":0}],"isBlockCoverage":false},{"functionName":"get$last","ranges":[{"startOffset":581990,"endOffset":582256,"count":0}],"isBlockCoverage":false},{"functionName":"toSet$0","ranges":[{"startOffset":582456,"endOffset":582553,"count":1}],"isBlockCoverage":true},{"functionName":"get$isEmpty","ranges":[{"startOffset":582572,"endOffset":582636,"count":0}],"isBlockCoverage":false},{"functionName":"addAll$1","ranges":[{"startOffset":582652,"endOffset":582872,"count":1},{"startOffset":582834,"endOffset":582866,"count":0}],"isBlockCoverage":true},{"functionName":"union$1","ranges":[{"startOffset":582887,"endOffset":583059,"count":1}],"isBlockCoverage":true},{"functionName":"toList$1$growable","ranges":[{"startOffset":583084,"endOffset":583579,"count":1},{"startOffset":583450,"endOffset":583552,"count":0}],"isBlockCoverage":true},{"functionName":"toList$0","ranges":[{"startOffset":583595,"endOffset":583676,"count":1}],"isBlockCoverage":true},{"functionName":"map$1$1","ranges":[{"startOffset":583691,"endOffset":583931,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":583949,"endOffset":584034,"count":0}],"isBlockCoverage":false},{"functionName":"where$1","ranges":[{"startOffset":584049,"endOffset":584214,"count":1}],"isBlockCoverage":true},{"functionName":"fold$1$2","ranges":[{"startOffset":584230,"endOffset":584642,"count":0}],"isBlockCoverage":false},{"functionName":"every$1","ranges":[{"startOffset":584657,"endOffset":584988,"count":0}],"isBlockCoverage":false},{"functionName":"any$1","ranges":[{"startOffset":585001,"endOffset":585340,"count":0}],"isBlockCoverage":false},{"functionName":"get$first","ranges":[{"startOffset":585357,"endOffset":585627,"count":0}],"isBlockCoverage":false},{"functionName":"get$last","ranges":[{"startOffset":585643,"endOffset":585994,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":586272,"endOffset":586605,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":586623,"endOffset":586845,"count":0}],"isBlockCoverage":false},{"functionName":"get$isEmpty","ranges":[{"startOffset":586864,"endOffset":586925,"count":0}],"isBlockCoverage":false},{"functionName":"get$keys","ranges":[{"startOffset":586941,"endOffset":587091,"count":0}],"isBlockCoverage":false},{"functionName":"containsKey$1","ranges":[{"startOffset":587112,"endOffset":587355,"count":0}],"isBlockCoverage":false},{"functionName":"remove$1","ranges":[{"startOffset":587371,"endOffset":587528,"count":0}],"isBlockCoverage":false},{"functionName":"forEach$1","ranges":[{"startOffset":587545,"endOffset":588211,"count":0}],"isBlockCoverage":false},{"functionName":"get$_upgradedMap","ranges":[{"startOffset":588235,"endOffset":588325,"count":0}],"isBlockCoverage":false},{"functionName":"_convert$_computeKeys$0","ranges":[{"startOffset":588356,"endOffset":588651,"count":0}],"isBlockCoverage":false},{"functionName":"_upgrade$0","ranges":[{"startOffset":588669,"endOffset":589287,"count":0}],"isBlockCoverage":false},{"functionName":"_process$1","ranges":[{"startOffset":589305,"endOffset":589541,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":589601,"endOffset":589681,"count":0}],"isBlockCoverage":false},{"functionName":"elementAt$1","ranges":[{"startOffset":589700,"endOffset":590025,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":590045,"endOffset":590376,"count":0}],"isBlockCoverage":false},{"functionName":"contains$1","ranges":[{"startOffset":590394,"endOffset":590464,"count":0}],"isBlockCoverage":false},{"functionName":"encode$1","ranges":[{"startOffset":590513,"endOffset":590588,"count":0}],"isBlockCoverage":false},{"functionName":"convert$1","ranges":[{"startOffset":590649,"endOffset":591298,"count":0}],"isBlockCoverage":false},{"functionName":"normalize$3","ranges":[{"startOffset":591384,"endOffset":595104,"count":0}],"isBlockCoverage":false},{"functionName":"decode$2$reviver","ranges":[{"startOffset":595311,"endOffset":595497,"count":0}],"isBlockCoverage":false},{"functionName":"get$decoder","ranges":[{"startOffset":595516,"endOffset":595567,"count":0}],"isBlockCoverage":false},{"functionName":"get$encoder","ranges":[{"startOffset":595650,"endOffset":595698,"count":0}],"isBlockCoverage":false},{"functionName":"convert$1","ranges":[{"startOffset":595749,"endOffset":596529,"count":0}],"isBlockCoverage":false},{"functionName":"_writeSurrogate$2","ranges":[{"startOffset":596589,"endOffset":598037,"count":0}],"isBlockCoverage":false},{"functionName":"_fillBuffer$3","ranges":[{"startOffset":598058,"endOffset":599908,"count":0}],"isBlockCoverage":false},{"functionName":"convert$1","ranges":[{"startOffset":599959,"endOffset":601081,"count":0}],"isBlockCoverage":false},{"functionName":"flush$2","ranges":[{"startOffset":601131,"endOffset":601378,"count":0}],"isBlockCoverage":false},{"functionName":"convert$3","ranges":[{"startOffset":601395,"endOffset":605325,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":605392,"endOffset":605547,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":605567,"endOffset":605692,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":605710,"endOffset":606328,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":606397,"endOffset":606550,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":606570,"endOffset":606648,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":606666,"endOffset":607284,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":607348,"endOffset":607623,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":607707,"endOffset":607790,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":607891,"endOffset":608058,"count":0}],"isBlockCoverage":false},{"functionName":"get$message","ranges":[{"startOffset":608077,"endOffset":608130,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":608186,"endOffset":608236,"count":0}],"isBlockCoverage":false},{"functionName":"get$_errorName","ranges":[{"startOffset":608294,"endOffset":608378,"count":0}],"isBlockCoverage":false},{"functionName":"get$_errorExplanation","ranges":[{"startOffset":608407,"endOffset":608442,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":608460,"endOffset":608982,"count":0}],"isBlockCoverage":false},{"functionName":"get$message","ranges":[{"startOffset":609001,"endOffset":609054,"count":0}],"isBlockCoverage":false},{"functionName":"get$_errorName","ranges":[{"startOffset":609109,"endOffset":609154,"count":0}],"isBlockCoverage":false},{"functionName":"get$_errorExplanation","ranges":[{"startOffset":609183,"endOffset":609833,"count":0}],"isBlockCoverage":false},{"functionName":"get$_errorName","ranges":[{"startOffset":609888,"endOffset":609933,"count":0}],"isBlockCoverage":false},{"functionName":"get$_errorExplanation","ranges":[{"startOffset":609962,"endOffset":610401,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":610419,"endOffset":610471,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":610528,"endOffset":610602,"count":0}],"isBlockCoverage":false},{"functionName":"get$message","ranges":[{"startOffset":610621,"endOffset":610674,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":610733,"endOffset":610859,"count":0}],"isBlockCoverage":false},{"functionName":"get$message","ranges":[{"startOffset":610878,"endOffset":610931,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":610982,"endOffset":611044,"count":0}],"isBlockCoverage":false},{"functionName":"get$message","ranges":[{"startOffset":611063,"endOffset":611116,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":611184,"endOffset":611413,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":611470,"endOffset":611519,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":611595,"endOffset":611645,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":611728,"endOffset":611927,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":611978,"endOffset":612040,"count":0}],"isBlockCoverage":false},{"functionName":"get$message","ranges":[{"startOffset":612080,"endOffset":612133,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":612189,"endOffset":614795,"count":0}],"isBlockCoverage":false},{"functionName":"get$message","ranges":[{"startOffset":614835,"endOffset":614888,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":614932,"endOffset":615559,"count":0}],"isBlockCoverage":false},{"functionName":"$indexSet","ranges":[{"startOffset":615576,"endOffset":616073,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":616091,"endOffset":616147,"count":0}],"isBlockCoverage":false},{"functionName":"map$1$1","ranges":[{"startOffset":616246,"endOffset":616443,"count":0}],"isBlockCoverage":false},{"functionName":"where$1","ranges":[{"startOffset":616458,"endOffset":616647,"count":1}],"isBlockCoverage":true},{"functionName":"contains$1","ranges":[{"startOffset":616665,"endOffset":616856,"count":0}],"isBlockCoverage":false},{"functionName":"join$1","ranges":[{"startOffset":616870,"endOffset":617364,"count":0}],"isBlockCoverage":false},{"functionName":"join$0","ranges":[{"startOffset":617378,"endOffset":617446,"count":0}],"isBlockCoverage":false},{"functionName":"toList$1$growable","ranges":[{"startOffset":617471,"endOffset":617588,"count":0}],"isBlockCoverage":false},{"functionName":"toList$0","ranges":[{"startOffset":617604,"endOffset":617685,"count":0}],"isBlockCoverage":false},{"functionName":"toSet$0","ranges":[{"startOffset":617700,"endOffset":617819,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":617837,"endOffset":618062,"count":0}],"isBlockCoverage":false},{"functionName":"get$isEmpty","ranges":[{"startOffset":618081,"endOffset":618152,"count":0}],"isBlockCoverage":false},{"functionName":"skipWhile$1","ranges":[{"startOffset":618171,"endOffset":618368,"count":0}],"isBlockCoverage":false},{"functionName":"get$first","ranges":[{"startOffset":618385,"endOffset":618570,"count":0}],"isBlockCoverage":false},{"functionName":"get$last","ranges":[{"startOffset":618586,"endOffset":618852,"count":0}],"isBlockCoverage":false},{"functionName":"elementAt$1","ranges":[{"startOffset":618871,"endOffset":619282,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":619300,"endOffset":619386,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":619558,"endOffset":619650,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":619697,"endOffset":619779,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":619797,"endOffset":619837,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":619937,"endOffset":619992,"count":1}],"isBlockCoverage":true},{"functionName":"get$hashCode","ranges":[{"startOffset":620012,"endOffset":620079,"count":1}],"isBlockCoverage":true},{"functionName":"toString$0","ranges":[{"startOffset":620097,"endOffset":620193,"count":0}],"isBlockCoverage":false},{"functionName":"get$runtimeType","ranges":[{"startOffset":620216,"endOffset":620272,"count":0}],"isBlockCoverage":false},{"functionName":"toString","ranges":[{"startOffset":620288,"endOffset":620342,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":620552,"endOffset":620602,"count":0}],"isBlockCoverage":false},{"functionName":"get$elapsedMicroseconds","ranges":[{"startOffset":620687,"endOffset":621099,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":621187,"endOffset":621252,"count":0}],"isBlockCoverage":false},{"functionName":"get$last","ranges":[{"startOffset":621268,"endOffset":621758,"count":0}],"isBlockCoverage":false},{"functionName":"get$current","ranges":[{"startOffset":621812,"endOffset":621867,"count":0}],"isBlockCoverage":false},{"functionName":"moveNext$0","ranges":[{"startOffset":621885,"endOffset":622720,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":622793,"endOffset":622848,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":622866,"endOffset":622962,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":623072,"endOffset":623205,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":623288,"endOffset":623421,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":623435,"endOffset":623493,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":623579,"endOffset":624044,"count":0}],"isBlockCoverage":false},{"functionName":"get$userInfo","ranges":[{"startOffset":624111,"endOffset":624158,"count":0}],"isBlockCoverage":false},{"functionName":"get$host","ranges":[{"startOffset":624174,"endOffset":624399,"count":0}],"isBlockCoverage":false},{"functionName":"get$port","ranges":[{"startOffset":624415,"endOffset":624549,"count":0}],"isBlockCoverage":false},{"functionName":"get$query","ranges":[{"startOffset":624566,"endOffset":624647,"count":0}],"isBlockCoverage":false},{"functionName":"get$fragment","ranges":[{"startOffset":624667,"endOffset":624751,"count":0}],"isBlockCoverage":false},{"functionName":"replace$2$path$pathSegments","ranges":[{"startOffset":624786,"endOffset":625788,"count":0}],"isBlockCoverage":false},{"functionName":"replace$1$path","ranges":[{"startOffset":625810,"endOffset":625913,"count":0}],"isBlockCoverage":false},{"functionName":"replace$1$pathSegments","ranges":[{"startOffset":625943,"endOffset":626062,"count":0}],"isBlockCoverage":false},{"functionName":"get$pathSegments","ranges":[{"startOffset":626086,"endOffset":626770,"count":0}],"isBlockCoverage":false},{"functionName":"_mergePaths$2","ranges":[{"startOffset":626791,"endOffset":627849,"count":0}],"isBlockCoverage":false},{"functionName":"resolve$1","ranges":[{"startOffset":627866,"endOffset":627949,"count":0}],"isBlockCoverage":false},{"functionName":"resolveUri$1","ranges":[{"startOffset":627969,"endOffset":630843,"count":0}],"isBlockCoverage":false},{"functionName":"get$hasAuthority","ranges":[{"startOffset":630867,"endOffset":630918,"count":0}],"isBlockCoverage":false},{"functionName":"get$hasPort","ranges":[{"startOffset":630937,"endOffset":630988,"count":0}],"isBlockCoverage":false},{"functionName":"get$hasQuery","ranges":[{"startOffset":631008,"endOffset":631060,"count":0}],"isBlockCoverage":false},{"functionName":"get$hasFragment","ranges":[{"startOffset":631083,"endOffset":631138,"count":0}],"isBlockCoverage":false},{"functionName":"get$hasAbsolutePath","ranges":[{"startOffset":631165,"endOffset":631245,"count":0}],"isBlockCoverage":false},{"functionName":"toFilePath$0","ranges":[{"startOffset":631265,"endOffset":632530,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":632548,"endOffset":633376,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":633387,"endOffset":634982,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":635002,"endOffset":635163,"count":0}],"isBlockCoverage":false},{"functionName":"set$_pathSegments","ranges":[{"startOffset":635188,"endOffset":635287,"count":0}],"isBlockCoverage":false},{"functionName":"get$scheme","ranges":[{"startOffset":635320,"endOffset":635364,"count":0}],"isBlockCoverage":false},{"functionName":"get$path","ranges":[{"startOffset":635380,"endOffset":635430,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":635494,"endOffset":635608,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":635716,"endOffset":636051,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":636130,"endOffset":636243,"count":0}],"isBlockCoverage":false},{"functionName":"get$uri","ranges":[{"startOffset":636307,"endOffset":637019,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":637037,"endOffset":637234,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":637292,"endOffset":637344,"count":1}],"isBlockCoverage":true},{"functionName":"call$2","ranges":[{"startOffset":637420,"endOffset":637648,"count":1},{"startOffset":637523,"endOffset":637549,"count":0}],"isBlockCoverage":true},{"functionName":"call$3","ranges":[{"startOffset":637727,"endOffset":638030,"count":1},{"startOffset":637956,"endOffset":637983,"count":0}],"isBlockCoverage":true},{"functionName":"call$3","ranges":[{"startOffset":638109,"endOffset":638448,"count":1},{"startOffset":638374,"endOffset":638401,"count":0}],"isBlockCoverage":true},{"functionName":"get$hasAuthority","ranges":[{"startOffset":638525,"endOffset":638577,"count":0}],"isBlockCoverage":false},{"functionName":"get$hasPort","ranges":[{"startOffset":638596,"endOffset":638689,"count":0}],"isBlockCoverage":false},{"functionName":"get$hasQuery","ranges":[{"startOffset":638709,"endOffset":638780,"count":0}],"isBlockCoverage":false},{"functionName":"get$hasFragment","ranges":[{"startOffset":638803,"endOffset":638874,"count":0}],"isBlockCoverage":false},{"functionName":"get$_isFile","ranges":[{"startOffset":638893,"endOffset":639001,"count":0}],"isBlockCoverage":false},{"functionName":"get$_isHttp","ranges":[{"startOffset":639020,"endOffset":639128,"count":0}],"isBlockCoverage":false},{"functionName":"get$_isHttps","ranges":[{"startOffset":639148,"endOffset":639257,"count":0}],"isBlockCoverage":false},{"functionName":"get$hasAbsolutePath","ranges":[{"startOffset":639284,"endOffset":639381,"count":0}],"isBlockCoverage":false},{"functionName":"get$scheme","ranges":[{"startOffset":639399,"endOffset":640155,"count":0}],"isBlockCoverage":false},{"functionName":"get$userInfo","ranges":[{"startOffset":640175,"endOffset":640342,"count":0}],"isBlockCoverage":false},{"functionName":"get$host","ranges":[{"startOffset":640358,"endOffset":640500,"count":0}],"isBlockCoverage":false},{"functionName":"get$port","ranges":[{"startOffset":640516,"endOffset":640832,"count":0}],"isBlockCoverage":false},{"functionName":"get$path","ranges":[{"startOffset":640848,"endOffset":640958,"count":0}],"isBlockCoverage":false},{"functionName":"get$query","ranges":[{"startOffset":640975,"endOffset":641143,"count":0}],"isBlockCoverage":false},{"functionName":"get$fragment","ranges":[{"startOffset":641163,"endOffset":641320,"count":0}],"isBlockCoverage":false},{"functionName":"get$pathSegments","ranges":[{"startOffset":641344,"endOffset":642029,"count":1},{"startOffset":641575,"endOffset":641595,"count":0}],"isBlockCoverage":true},{"functionName":"_isPort$1","ranges":[{"startOffset":642046,"endOffset":642247,"count":0}],"isBlockCoverage":false},{"functionName":"removeFragment$0","ranges":[{"startOffset":642271,"endOffset":642611,"count":0}],"isBlockCoverage":false},{"functionName":"replace$2$path$pathSegments","ranges":[{"startOffset":642646,"endOffset":644260,"count":0}],"isBlockCoverage":false},{"functionName":"replace$1$path","ranges":[{"startOffset":644282,"endOffset":644385,"count":0}],"isBlockCoverage":false},{"functionName":"replace$1$pathSegments","ranges":[{"startOffset":644415,"endOffset":644534,"count":0}],"isBlockCoverage":false},{"functionName":"resolve$1","ranges":[{"startOffset":644551,"endOffset":644634,"count":0}],"isBlockCoverage":false},{"functionName":"resolveUri$1","ranges":[{"startOffset":644654,"endOffset":644839,"count":0}],"isBlockCoverage":false},{"functionName":"_simpleMerge$2","ranges":[{"startOffset":644861,"endOffset":648814,"count":0}],"isBlockCoverage":false},{"functionName":"toFilePath$0","ranges":[{"startOffset":648834,"endOffset":649861,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":649881,"endOffset":650033,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":650044,"endOffset":650236,"count":0}],"isBlockCoverage":false},{"functionName":"_toNonSimple$0","ranges":[{"startOffset":650258,"endOffset":650822,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":650840,"endOffset":650883,"count":0}],"isBlockCoverage":false},{"functionName":"get$message","ranges":[{"startOffset":650995,"endOffset":651052,"count":0}],"isBlockCoverage":false},{"functionName":"get$message","ranges":[{"startOffset":651137,"endOffset":651194,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":651247,"endOffset":651304,"count":0}],"isBlockCoverage":false},{"functionName":"get$message","ranges":[{"startOffset":651323,"endOffset":651380,"count":0}],"isBlockCoverage":false},{"functionName":"get$message","ranges":[{"startOffset":651432,"endOffset":651489,"count":0}],"isBlockCoverage":false},{"functionName":"addEventListener$3","ranges":[{"startOffset":651586,"endOffset":651788,"count":1}],"isBlockCoverage":true},{"functionName":"_addEventListener$3","ranges":[{"startOffset":651815,"endOffset":651995,"count":1}],"isBlockCoverage":true},{"functionName":"_removeEventListener$3","ranges":[{"startOffset":652025,"endOffset":652208,"count":1}],"isBlockCoverage":true},{"functionName":"get$origin","ranges":[{"startOffset":652315,"endOffset":652470,"count":1},{"startOffset":652399,"endOffset":652469,"count":0}],"isBlockCoverage":true},{"functionName":"toString$0","ranges":[{"startOffset":652488,"endOffset":652545,"count":0}],"isBlockCoverage":false},{"functionName":"get$message","ranges":[{"startOffset":652597,"endOffset":652654,"count":0}],"isBlockCoverage":false},{"functionName":"get$message","ranges":[{"startOffset":652716,"endOffset":652773,"count":0}],"isBlockCoverage":false},{"functionName":"addEventListener$3","ranges":[{"startOffset":652884,"endOffset":653127,"count":1}],"isBlockCoverage":true},{"functionName":"postMessage$1","ranges":[{"startOffset":653148,"endOffset":653318,"count":1}],"isBlockCoverage":true},{"functionName":"get$message","ranges":[{"startOffset":653406,"endOffset":653463,"count":0}],"isBlockCoverage":false},{"functionName":"get$message","ranges":[{"startOffset":653525,"endOffset":653582,"count":0}],"isBlockCoverage":false},{"functionName":"get$message","ranges":[{"startOffset":653637,"endOffset":653694,"count":0}],"isBlockCoverage":false},{"functionName":"get$message","ranges":[{"startOffset":653768,"endOffset":653825,"count":0}],"isBlockCoverage":false},{"functionName":"get$message","ranges":[{"startOffset":653889,"endOffset":653946,"count":0}],"isBlockCoverage":false},{"functionName":"get$isBroadcast","ranges":[{"startOffset":654044,"endOffset":654081,"count":0}],"isBlockCoverage":false},{"functionName":"listen$4$cancelOnError$onDone$onError","ranges":[{"startOffset":654126,"endOffset":654445,"count":1}],"isBlockCoverage":true},{"functionName":"listen$3$onDone$onError","ranges":[{"startOffset":654476,"endOffset":654605,"count":0}],"isBlockCoverage":false},{"functionName":"listen$1","ranges":[{"startOffset":654621,"endOffset":654728,"count":0}],"isBlockCoverage":false},{"functionName":"cancel$0","ranges":[{"startOffset":654791,"endOffset":655010,"count":1},{"startOffset":654875,"endOffset":654887,"count":0}],"isBlockCoverage":true},{"functionName":"pause$1","ranges":[{"startOffset":655025,"endOffset":655161,"count":0}],"isBlockCoverage":false},{"functionName":"pause$0","ranges":[{"startOffset":655176,"endOffset":655227,"count":0}],"isBlockCoverage":false},{"functionName":"resume$0","ranges":[{"startOffset":655243,"endOffset":655421,"count":0}],"isBlockCoverage":false},{"functionName":"_tryResume$0","ranges":[{"startOffset":655441,"endOffset":655647,"count":1}],"isBlockCoverage":true},{"functionName":"_unlisten$0","ranges":[{"startOffset":655666,"endOffset":655969,"count":1}],"isBlockCoverage":true},{"functionName":"set$_html$_onData","ranges":[{"startOffset":655994,"endOffset":656092,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":656161,"endOffset":656236,"count":1}],"isBlockCoverage":true},{"functionName":"findSlot$1","ranges":[{"startOffset":656313,"endOffset":656603,"count":1},{"startOffset":656474,"endOffset":656483,"count":0}],"isBlockCoverage":true},{"functionName":"walk$1","ranges":[{"startOffset":656617,"endOffset":658566,"count":1},{"startOffset":656751,"endOffset":656760,"count":0},{"startOffset":656904,"endOffset":656930,"count":0},{"startOffset":656970,"endOffset":657045,"count":0},{"startOffset":657083,"endOffset":657092,"count":0},{"startOffset":657130,"endOffset":657139,"count":0},{"startOffset":657249,"endOffset":657258,"count":0},{"startOffset":657409,"endOffset":657434,"count":0},{"startOffset":657506,"endOffset":657518,"count":0},{"startOffset":657862,"endOffset":657887,"count":0},{"startOffset":657949,"endOffset":657961,"count":0},{"startOffset":658011,"endOffset":658565,"count":0}],"isBlockCoverage":true},{"functionName":"copyList$2","ranges":[{"startOffset":658584,"endOffset":658922,"count":1}],"isBlockCoverage":true},{"functionName":"call$2","ranges":[{"startOffset":658988,"endOffset":659072,"count":1}],"isBlockCoverage":true},{"functionName":"call$2","ranges":[{"startOffset":659158,"endOffset":659242,"count":0}],"isBlockCoverage":false},{"functionName":"findSlot$1","ranges":[{"startOffset":659324,"endOffset":659614,"count":1},{"startOffset":659485,"endOffset":659494,"count":0}],"isBlockCoverage":true},{"functionName":"walk$1","ranges":[{"startOffset":659628,"endOffset":661744,"count":1},{"startOffset":659949,"endOffset":660278,"count":0},{"startOffset":660318,"endOffset":660393,"count":0},{"startOffset":660467,"endOffset":660510,"count":0},{"startOffset":660713,"endOffset":660738,"count":0},{"startOffset":660814,"endOffset":660826,"count":0},{"startOffset":661277,"endOffset":661302,"count":0},{"startOffset":661364,"endOffset":661376,"count":0},{"startOffset":661502,"endOffset":661505,"count":0},{"startOffset":661722,"endOffset":661743,"count":0}],"isBlockCoverage":true},{"functionName":"convertNativeToDart_AcceptStructuredClone$2$mustCopy","ranges":[{"startOffset":661804,"endOffset":661900,"count":1}],"isBlockCoverage":true},{"functionName":"call$2","ranges":[{"startOffset":661972,"endOffset":662124,"count":1}],"isBlockCoverage":true},{"functionName":"forEachObjectKey$2","ranges":[{"startOffset":662216,"endOffset":662485,"count":0}],"isBlockCoverage":false},{"functionName":"forEachJsField$2","ranges":[{"startOffset":662561,"endOffset":662902,"count":1},{"startOffset":662770,"endOffset":662816,"count":0}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":662964,"endOffset":663725,"count":1},{"startOffset":663098,"endOffset":663121,"count":0},{"startOffset":663497,"endOffset":663696,"count":0}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":663805,"endOffset":663896,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":663977,"endOffset":664044,"count":0}],"isBlockCoverage":false},{"functionName":"get$message","ranges":[{"startOffset":664969,"endOffset":665026,"count":0}],"isBlockCoverage":false},{"functionName":"runOnce$1","ranges":[{"startOffset":665079,"endOffset":665381,"count":0}],"isBlockCoverage":false},{"functionName":"onData$1","ranges":[{"startOffset":665493,"endOffset":665616,"count":0}],"isBlockCoverage":false},{"functionName":"onError$1","ranges":[{"startOffset":665633,"endOffset":665732,"count":0}],"isBlockCoverage":false},{"functionName":"onDone$1","ranges":[{"startOffset":665748,"endOffset":665866,"count":0}],"isBlockCoverage":false},{"functionName":"pause$1","ranges":[{"startOffset":665881,"endOffset":665974,"count":0}],"isBlockCoverage":false},{"functionName":"pause$0","ranges":[{"startOffset":665989,"endOffset":666040,"count":0}],"isBlockCoverage":false},{"functionName":"resume$0","ranges":[{"startOffset":666056,"endOffset":666126,"count":0}],"isBlockCoverage":false},{"functionName":"cancel$0","ranges":[{"startOffset":666142,"endOffset":666219,"count":0}],"isBlockCoverage":false},{"functionName":"add$1","ranges":[{"startOffset":666296,"endOffset":666782,"count":0}],"isBlockCoverage":false},{"functionName":"close$0","ranges":[{"startOffset":666797,"endOffset":667077,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":667153,"endOffset":667619,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":667637,"endOffset":667703,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":667764,"endOffset":667976,"count":0}],"isBlockCoverage":false},{"functionName":"add$1","ranges":[{"startOffset":668045,"endOffset":668148,"count":0}],"isBlockCoverage":false},{"functionName":"addStream$1","ranges":[{"startOffset":668167,"endOffset":668625,"count":0}],"isBlockCoverage":false},{"functionName":"_checkEventAllowed$0","ranges":[{"startOffset":668653,"endOffset":668914,"count":0}],"isBlockCoverage":false},{"functionName":"close$0","ranges":[{"startOffset":668929,"endOffset":669017,"count":0}],"isBlockCoverage":false},{"functionName":"get$done","ranges":[{"startOffset":669118,"endOffset":669160,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":669229,"endOffset":669287,"count":0}],"isBlockCoverage":false},{"functionName":"complete$1","ranges":[{"startOffset":669358,"endOffset":669447,"count":0}],"isBlockCoverage":false},{"functionName":"addTo$1","ranges":[{"startOffset":669462,"endOffset":669536,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":669556,"endOffset":669672,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":669683,"endOffset":669875,"count":0}],"isBlockCoverage":false},{"functionName":"complete$1","ranges":[{"startOffset":669972,"endOffset":670080,"count":1}],"isBlockCoverage":true},{"functionName":"addTo$1","ranges":[{"startOffset":670095,"endOffset":670191,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":670211,"endOffset":670292,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":670303,"endOffset":670456,"count":0}],"isBlockCoverage":false},{"functionName":"setSourceStream$1","ranges":[{"startOffset":670537,"endOffset":670945,"count":1},{"startOffset":670703,"endOffset":670769,"count":0}],"isBlockCoverage":true},{"functionName":"listen$4$cancelOnError$onDone$onError","ranges":[{"startOffset":671029,"endOffset":671873,"count":1},{"startOffset":671585,"endOffset":671619,"count":0}],"isBlockCoverage":true},{"functionName":"listen$3$onDone$onError","ranges":[{"startOffset":671904,"endOffset":672033,"count":0}],"isBlockCoverage":false},{"functionName":"listen$1","ranges":[{"startOffset":672049,"endOffset":672156,"count":1}],"isBlockCoverage":true},{"functionName":"_linkStreamToController$0","ranges":[{"startOffset":672189,"endOffset":672550,"count":1}],"isBlockCoverage":true},{"functionName":"_createController$0","ranges":[{"startOffset":672577,"endOffset":672786,"count":1}],"isBlockCoverage":true},{"functionName":"set$_stream_completer$_controller","ranges":[{"startOffset":672827,"endOffset":672960,"count":1}],"isBlockCoverage":true},{"functionName":"set$_sourceStream","ranges":[{"startOffset":672985,"endOffset":673096,"count":1}],"isBlockCoverage":true},{"functionName":"add$1","ranges":[{"startOffset":673143,"endOffset":673811,"count":0}],"isBlockCoverage":false},{"functionName":"_onListen$0","ranges":[{"startOffset":673830,"endOffset":674010,"count":0}],"isBlockCoverage":false},{"functionName":"_onCancelBroadcast$0","ranges":[{"startOffset":674038,"endOffset":674225,"count":0}],"isBlockCoverage":false},{"functionName":"_listenToStream$1","ranges":[{"startOffset":674250,"endOffset":674687,"count":0}],"isBlockCoverage":false},{"functionName":"close$0","ranges":[{"startOffset":674702,"endOffset":675097,"count":0}],"isBlockCoverage":false},{"functionName":"set$_stream_group$_controller","ranges":[{"startOffset":675134,"endOffset":675263,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":675339,"endOffset":675376,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":675456,"endOffset":675530,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":675548,"endOffset":675630,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":675696,"endOffset":676010,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":676028,"endOffset":676124,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":676199,"endOffset":676545,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":676563,"endOffset":676659,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":676731,"endOffset":677110,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":677188,"endOffset":677231,"count":0}],"isBlockCoverage":false},{"functionName":"get$next","ranges":[{"startOffset":677281,"endOffset":677676,"count":1},{"startOffset":677618,"endOffset":677675,"count":0}],"isBlockCoverage":true},{"functionName":"_updateRequests$0","ranges":[{"startOffset":677701,"endOffset":678244,"count":1},{"startOffset":677901,"endOffset":677955,"count":0},{"startOffset":678019,"endOffset":678042,"count":0},{"startOffset":678120,"endOffset":678151,"count":0}],"isBlockCoverage":true},{"functionName":"_extractStream$0","ranges":[{"startOffset":678268,"endOffset":678938,"count":1},{"startOffset":678406,"endOffset":678470,"count":0},{"startOffset":678575,"endOffset":678610,"count":0}],"isBlockCoverage":true},{"functionName":"_ensureListening$0","ranges":[{"startOffset":678964,"endOffset":679408,"count":1},{"startOffset":679038,"endOffset":679045,"count":0},{"startOffset":679368,"endOffset":679402,"count":0}],"isBlockCoverage":true},{"functionName":"_addResult$1","ranges":[{"startOffset":679428,"endOffset":679693,"count":1}],"isBlockCoverage":true},{"functionName":"_failClosed$0","ranges":[{"startOffset":679714,"endOffset":679784,"count":0}],"isBlockCoverage":false},{"functionName":"_addRequest$1","ranges":[{"startOffset":679805,"endOffset":680179,"count":1}],"isBlockCoverage":true},{"functionName":"set$_stream_queue$_subscription","ranges":[{"startOffset":680218,"endOffset":680355,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":680428,"endOffset":680601,"count":1}],"isBlockCoverage":true},{"functionName":"$signature","ranges":[{"startOffset":680619,"endOffset":680685,"count":1}],"isBlockCoverage":true},{"functionName":"call$2","ranges":[{"startOffset":680759,"endOffset":680888,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":680981,"endOffset":681129,"count":0}],"isBlockCoverage":false},{"functionName":"update$2","ranges":[{"startOffset":681233,"endOffset":681629,"count":1},{"startOffset":681475,"endOffset":681603,"count":0}],"isBlockCoverage":true},{"functionName":"update$2","ranges":[{"startOffset":681705,"endOffset":683204,"count":1},{"startOffset":681986,"endOffset":682524,"count":0},{"startOffset":682592,"endOffset":683179,"count":0}],"isBlockCoverage":true},{"functionName":"get$_canSendDirectly","ranges":[{"startOffset":683334,"endOffset":683447,"count":0}],"isBlockCoverage":false},{"functionName":"get$done","ranges":[{"startOffset":683463,"endOffset":683878,"count":0}],"isBlockCoverage":false},{"functionName":"addStream$1","ranges":[{"startOffset":683897,"endOffset":684228,"count":0}],"isBlockCoverage":false},{"functionName":"close$0","ranges":[{"startOffset":684243,"endOffset":684519,"count":0}],"isBlockCoverage":false},{"functionName":"_ensureController$0","ranges":[{"startOffset":684546,"endOffset":684755,"count":0}],"isBlockCoverage":false},{"functionName":"_setDestinationSink$1","ranges":[{"startOffset":684784,"endOffset":685386,"count":1},{"startOffset":685061,"endOffset":685262,"count":0},{"startOffset":685349,"endOffset":685380,"count":0}],"isBlockCoverage":true},{"functionName":"set$_stream_sink_completer$_controller","ranges":[{"startOffset":685432,"endOffset":685570,"count":0}],"isBlockCoverage":false},{"functionName":"set$_destinationSink","ranges":[{"startOffset":685598,"endOffset":685722,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":685886,"endOffset":685905,"count":0}],"isBlockCoverage":false},{"functionName":"listen$4$cancelOnError$onDone$onError","ranges":[{"startOffset":686010,"endOffset":686754,"count":1},{"startOffset":686321,"endOffset":686398,"count":0},{"startOffset":686489,"endOffset":686590,"count":0}],"isBlockCoverage":true},{"functionName":"listen$3$onDone$onError","ranges":[{"startOffset":686785,"endOffset":686914,"count":0}],"isBlockCoverage":false},{"functionName":"listen$1","ranges":[{"startOffset":686930,"endOffset":687037,"count":0}],"isBlockCoverage":false},{"functionName":"set$_subscription_stream$_source","ranges":[{"startOffset":687077,"endOffset":687203,"count":1}],"isBlockCoverage":true},{"functionName":"onError$1","ranges":[{"startOffset":687276,"endOffset":687442,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":687528,"endOffset":688068,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":688174,"endOffset":688382,"count":0}],"isBlockCoverage":false},{"functionName":"evaluate$1","ranges":[{"startOffset":688481,"endOffset":688527,"count":1}],"isBlockCoverage":true},{"functionName":"intersection$1","ranges":[{"startOffset":688549,"endOffset":688592,"count":0}],"isBlockCoverage":false},{"functionName":"validate$1","ranges":[{"startOffset":688610,"endOffset":688689,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":688707,"endOffset":688748,"count":0}],"isBlockCoverage":false},{"functionName":"accept$1","ranges":[{"startOffset":688826,"endOffset":688895,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":688913,"endOffset":688956,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":688967,"endOffset":689113,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":689133,"endOffset":689193,"count":0}],"isBlockCoverage":false},{"functionName":"get$span","ranges":[{"startOffset":689225,"endOffset":689267,"count":0}],"isBlockCoverage":false},{"functionName":"accept$1","ranges":[{"startOffset":689313,"endOffset":689377,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":689395,"endOffset":689568,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":689579,"endOffset":689727,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":689747,"endOffset":689834,"count":0}],"isBlockCoverage":false},{"functionName":"get$span","ranges":[{"startOffset":689866,"endOffset":689908,"count":0}],"isBlockCoverage":false},{"functionName":"get$span","ranges":[{"startOffset":689953,"endOffset":690044,"count":0}],"isBlockCoverage":false},{"functionName":"accept$1","ranges":[{"startOffset":690060,"endOffset":690123,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":690141,"endOffset":690553,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":690564,"endOffset":690743,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":690763,"endOffset":690897,"count":0}],"isBlockCoverage":false},{"functionName":"get$span","ranges":[{"startOffset":690959,"endOffset":691050,"count":0}],"isBlockCoverage":false},{"functionName":"accept$1","ranges":[{"startOffset":691066,"endOffset":691130,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":691148,"endOffset":691558,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":691569,"endOffset":691749,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":691769,"endOffset":691903,"count":0}],"isBlockCoverage":false},{"functionName":"get$span","ranges":[{"startOffset":691973,"endOffset":692073,"count":0}],"isBlockCoverage":false},{"functionName":"accept$1","ranges":[{"startOffset":692089,"endOffset":692161,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":692179,"endOffset":692631,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":692642,"endOffset":692888,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":692908,"endOffset":693101,"count":0}],"isBlockCoverage":false},{"functionName":"visitVariable$1","ranges":[{"startOffset":693172,"endOffset":693242,"count":0}],"isBlockCoverage":false},{"functionName":"visitNot$1","ranges":[{"startOffset":693260,"endOffset":693346,"count":0}],"isBlockCoverage":false},{"functionName":"visitOr$1","ranges":[{"startOffset":693363,"endOffset":693499,"count":0}],"isBlockCoverage":false},{"functionName":"visitAnd$1","ranges":[{"startOffset":693517,"endOffset":693653,"count":0}],"isBlockCoverage":false},{"functionName":"visitConditional$1","ranges":[{"startOffset":693679,"endOffset":693831,"count":0}],"isBlockCoverage":false},{"functionName":"evaluate$1","ranges":[{"startOffset":693910,"endOffset":694228,"count":0}],"isBlockCoverage":false},{"functionName":"intersection$1","ranges":[{"startOffset":694250,"endOffset":694597,"count":0}],"isBlockCoverage":false},{"functionName":"validate$1","ranges":[{"startOffset":694615,"endOffset":694736,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":694754,"endOffset":694816,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":694827,"endOffset":694995,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":695015,"endOffset":695099,"count":0}],"isBlockCoverage":false},{"functionName":"evaluate$1","ranges":[{"startOffset":695187,"endOffset":695353,"count":0}],"isBlockCoverage":false},{"functionName":"intersection$1","ranges":[{"startOffset":695375,"endOffset":695452,"count":0}],"isBlockCoverage":false},{"functionName":"validate$1","ranges":[{"startOffset":695470,"endOffset":695639,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":695657,"endOffset":695766,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":695777,"endOffset":695993,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":696013,"endOffset":696141,"count":0}],"isBlockCoverage":false},{"functionName":"evaluate$1","ranges":[{"startOffset":696213,"endOffset":696260,"count":0}],"isBlockCoverage":false},{"functionName":"intersection$1","ranges":[{"startOffset":696282,"endOffset":696324,"count":0}],"isBlockCoverage":false},{"functionName":"validate$1","ranges":[{"startOffset":696342,"endOffset":696421,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":696439,"endOffset":696481,"count":0}],"isBlockCoverage":false},{"functionName":"parse$0","ranges":[{"startOffset":696552,"endOffset":696864,"count":0}],"isBlockCoverage":false},{"functionName":"_conditional$0","ranges":[{"startOffset":696886,"endOffset":697347,"count":0}],"isBlockCoverage":false},{"functionName":"_or$0","ranges":[{"startOffset":697360,"endOffset":697536,"count":0}],"isBlockCoverage":false},{"functionName":"_and$0","ranges":[{"startOffset":697550,"endOffset":697742,"count":0}],"isBlockCoverage":false},{"functionName":"_simpleExpression$0","ranges":[{"startOffset":697769,"endOffset":698600,"count":0}],"isBlockCoverage":false},{"functionName":"peek$0","ranges":[{"startOffset":698644,"endOffset":698770,"count":0}],"isBlockCoverage":false},{"functionName":"next$0","ranges":[{"startOffset":698784,"endOffset":699055,"count":0}],"isBlockCoverage":false},{"functionName":"scan$1","ranges":[{"startOffset":699069,"endOffset":699219,"count":0}],"isBlockCoverage":false},{"functionName":"_getNext$0","ranges":[{"startOffset":699237,"endOffset":700677,"count":0}],"isBlockCoverage":false},{"functionName":"_scanOperator$1","ranges":[{"startOffset":700700,"endOffset":701057,"count":0}],"isBlockCoverage":false},{"functionName":"_consumeWhitespace$0","ranges":[{"startOffset":701085,"endOffset":701439,"count":0}],"isBlockCoverage":false},{"functionName":"_multiLineComment$0","ranges":[{"startOffset":701466,"endOffset":701903,"count":0}],"isBlockCoverage":false},{"functionName":"get$type","ranges":[{"startOffset":701947,"endOffset":701997,"count":0}],"isBlockCoverage":false},{"functionName":"get$span","ranges":[{"startOffset":702013,"endOffset":702055,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":702111,"endOffset":702182,"count":0}],"isBlockCoverage":false},{"functionName":"get$type","ranges":[{"startOffset":702215,"endOffset":702270,"count":0}],"isBlockCoverage":false},{"functionName":"get$span","ranges":[{"startOffset":702286,"endOffset":702328,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":702378,"endOffset":702421,"count":0}],"isBlockCoverage":false},{"functionName":"visitVariable$1","ranges":[{"startOffset":702476,"endOffset":702681,"count":0}],"isBlockCoverage":false},{"functionName":"visitNot$1","ranges":[{"startOffset":702738,"endOffset":702793,"count":0}],"isBlockCoverage":false},{"functionName":"visitOr$1","ranges":[{"startOffset":702810,"endOffset":702897,"count":0}],"isBlockCoverage":false},{"functionName":"visitAnd$1","ranges":[{"startOffset":702915,"endOffset":703002,"count":0}],"isBlockCoverage":false},{"functionName":"visitConditional$1","ranges":[{"startOffset":703028,"endOffset":703160,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":703242,"endOffset":703293,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":703311,"endOffset":703346,"count":0}],"isBlockCoverage":false},{"functionName":"contains$1","ranges":[{"startOffset":703364,"endOffset":703412,"count":0}],"isBlockCoverage":false},{"functionName":"toSet$0","ranges":[{"startOffset":703427,"endOffset":703514,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":703615,"endOffset":703731,"count":1}],"isBlockCoverage":true},{"functionName":"$signature","ranges":[{"startOffset":703749,"endOffset":703857,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":703909,"endOffset":704161,"count":1}],"isBlockCoverage":true},{"functionName":"$signature","ranges":[{"startOffset":704179,"endOffset":704273,"count":1}],"isBlockCoverage":true},{"functionName":"call$2","ranges":[{"startOffset":704327,"endOffset":704582,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":704600,"endOffset":704692,"count":1}],"isBlockCoverage":true},{"functionName":"toString$0","ranges":[{"startOffset":704742,"endOffset":704827,"count":0}],"isBlockCoverage":false},{"functionName":"removeFirst$0","ranges":[{"startOffset":704848,"endOffset":705338,"count":1},{"startOffset":704985,"endOffset":705036,"count":0},{"startOffset":705109,"endOffset":705132,"count":0}],"isBlockCoverage":true},{"functionName":"get$length","ranges":[{"startOffset":705356,"endOffset":705482,"count":1}],"isBlockCoverage":true},{"functionName":"set$length","ranges":[{"startOffset":705500,"endOffset":706426,"count":0}],"isBlockCoverage":false},{"functionName":"$index","ranges":[{"startOffset":706440,"endOffset":706924,"count":0}],"isBlockCoverage":false},{"functionName":"$indexSet","ranges":[{"startOffset":706941,"endOffset":707471,"count":0}],"isBlockCoverage":false},{"functionName":"_queue_list$_add$1","ranges":[{"startOffset":707497,"endOffset":708514,"count":1},{"startOffset":707919,"endOffset":708508,"count":0}],"isBlockCoverage":true},{"functionName":"_writeToList$1","ranges":[{"startOffset":708536,"endOffset":709305,"count":0}],"isBlockCoverage":false},{"functionName":"_preGrow$1","ranges":[{"startOffset":709323,"endOffset":709960,"count":0}],"isBlockCoverage":false},{"functionName":"set$_queue_list$_table","ranges":[{"startOffset":709990,"endOffset":710090,"count":1}],"isBlockCoverage":true},{"functionName":"get$length","ranges":[{"startOffset":710275,"endOffset":710401,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":710421,"endOffset":710522,"count":0}],"isBlockCoverage":false},{"functionName":"get$_union_set$_iterable","ranges":[{"startOffset":710554,"endOffset":710878,"count":0}],"isBlockCoverage":false},{"functionName":"toSet$0","ranges":[{"startOffset":710893,"endOffset":711220,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":711280,"endOffset":711601,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":711619,"endOffset":711693,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":711756,"endOffset":711836,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":711854,"endOffset":711927,"count":0}],"isBlockCoverage":false},{"functionName":"set$_union_set_controller$_set","ranges":[{"startOffset":712065,"endOffset":712173,"count":0}],"isBlockCoverage":false},{"functionName":"contains$1","ranges":[{"startOffset":712394,"endOffset":712470,"count":0}],"isBlockCoverage":false},{"functionName":"every$1","ranges":[{"startOffset":712485,"endOffset":712601,"count":0}],"isBlockCoverage":false},{"functionName":"get$first","ranges":[{"startOffset":712618,"endOffset":712695,"count":0}],"isBlockCoverage":false},{"functionName":"get$isEmpty","ranges":[{"startOffset":712714,"endOffset":712793,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":712813,"endOffset":712893,"count":0}],"isBlockCoverage":false},{"functionName":"get$last","ranges":[{"startOffset":712909,"endOffset":712985,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":713003,"endOffset":713081,"count":0}],"isBlockCoverage":false},{"functionName":"map$1$1","ranges":[{"startOffset":713096,"endOffset":713223,"count":0}],"isBlockCoverage":false},{"functionName":"toList$1$growable","ranges":[{"startOffset":713248,"endOffset":713329,"count":1}],"isBlockCoverage":true},{"functionName":"toList$0","ranges":[{"startOffset":713345,"endOffset":713426,"count":1}],"isBlockCoverage":true},{"functionName":"toSet$0","ranges":[{"startOffset":713441,"endOffset":713496,"count":0}],"isBlockCoverage":false},{"functionName":"where$1","ranges":[{"startOffset":713511,"endOffset":713627,"count":1}],"isBlockCoverage":true},{"functionName":"toString$0","ranges":[{"startOffset":713645,"endOffset":713703,"count":0}],"isBlockCoverage":false},{"functionName":"union$1","ranges":[{"startOffset":713813,"endOffset":713967,"count":1}],"isBlockCoverage":true},{"functionName":"toSet$0","ranges":[{"startOffset":713982,"endOffset":714157,"count":0}],"isBlockCoverage":false},{"functionName":"matches$2","ranges":[{"startOffset":714254,"endOffset":714324,"count":1}],"isBlockCoverage":true},{"functionName":"describe$1","ranges":[{"startOffset":714342,"endOffset":714441,"count":0}],"isBlockCoverage":false},{"functionName":"typedMatches$2","ranges":[{"startOffset":714496,"endOffset":714602,"count":0}],"isBlockCoverage":false},{"functionName":"describe$1","ranges":[{"startOffset":714620,"endOffset":714745,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":714803,"endOffset":714863,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":714881,"endOffset":714982,"count":0}],"isBlockCoverage":false},{"functionName":"addDescriptionOf$1","ranges":[{"startOffset":715008,"endOffset":715192,"count":0}],"isBlockCoverage":false},{"functionName":"typedMatches$2","ranges":[{"startOffset":715280,"endOffset":715389,"count":0}],"isBlockCoverage":false},{"functionName":"describe$1","ranges":[{"startOffset":715407,"endOffset":715510,"count":0}],"isBlockCoverage":false},{"functionName":"describeTypedMismatch$4","ranges":[{"startOffset":715541,"endOffset":717567,"count":0}],"isBlockCoverage":false},{"functionName":"_compareIterables$5","ranges":[{"startOffset":717629,"endOffset":718839,"count":0}],"isBlockCoverage":false},{"functionName":"_compareSets$5","ranges":[{"startOffset":718861,"endOffset":720203,"count":0}],"isBlockCoverage":false},{"functionName":"_recursiveMatch$4","ranges":[{"startOffset":720228,"endOffset":723384,"count":0}],"isBlockCoverage":false},{"functionName":"_equals_matcher$_match$3","ranges":[{"startOffset":723416,"endOffset":724262,"count":0}],"isBlockCoverage":false},{"functionName":"matches$2","ranges":[{"startOffset":724279,"endOffset":724402,"count":0}],"isBlockCoverage":false},{"functionName":"describe$1","ranges":[{"startOffset":724420,"endOffset":724510,"count":0}],"isBlockCoverage":false},{"functionName":"describeMismatch$4","ranges":[{"startOffset":724536,"endOffset":725070,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":725140,"endOffset":725305,"count":0}],"isBlockCoverage":false},{"functionName":"matches$2","ranges":[{"startOffset":725378,"endOffset":725603,"count":0}],"isBlockCoverage":false},{"functionName":"describeMismatch$4","ranges":[{"startOffset":725629,"endOffset":725977,"count":0}],"isBlockCoverage":false},{"functionName":"describeTypedMismatch$4","ranges":[{"startOffset":726008,"endOffset":726176,"count":0}],"isBlockCoverage":false},{"functionName":"describeMismatch$4","ranges":[{"startOffset":726232,"endOffset":726330,"count":0}],"isBlockCoverage":false},{"functionName":"call$4","ranges":[{"startOffset":726391,"endOffset":730032,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":730116,"endOffset":730227,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":730316,"endOffset":730510,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":730599,"endOffset":730730,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":730820,"endOffset":731014,"count":0}],"isBlockCoverage":false},{"functionName":"describe$1","ranges":[{"startOffset":731085,"endOffset":731450,"count":0}],"isBlockCoverage":false},{"functionName":"matches$2","ranges":[{"startOffset":731467,"endOffset":731575,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":731631,"endOffset":731703,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":731773,"endOffset":731958,"count":0}],"isBlockCoverage":false},{"functionName":"get$packageRoot","ranges":[{"startOffset":732071,"endOffset":732108,"count":0}],"isBlockCoverage":false},{"functionName":"get$packageConfigMap","ranges":[{"startOffset":732136,"endOffset":732190,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":732270,"endOffset":732353,"count":1}],"isBlockCoverage":true},{"functionName":"get$packageConfigMap","ranges":[{"startOffset":732469,"endOffset":732506,"count":0}],"isBlockCoverage":false},{"functionName":"get$packageRoot","ranges":[{"startOffset":732529,"endOffset":732578,"count":0}],"isBlockCoverage":false},{"functionName":"absolute$7","ranges":[{"startOffset":732626,"endOffset":733114,"count":0}],"isBlockCoverage":false},{"functionName":"absolute$1","ranges":[{"startOffset":733132,"endOffset":733250,"count":0}],"isBlockCoverage":false},{"functionName":"join$8","ranges":[{"startOffset":733264,"endOffset":733650,"count":0}],"isBlockCoverage":false},{"functionName":"join$2","ranges":[{"startOffset":733664,"endOffset":733792,"count":0}],"isBlockCoverage":false},{"functionName":"joinAll$1","ranges":[{"startOffset":733809,"endOffset":735362,"count":0}],"isBlockCoverage":false},{"functionName":"split$1","ranges":[{"startOffset":735377,"endOffset":735875,"count":0}],"isBlockCoverage":false},{"functionName":"normalize$1","ranges":[{"startOffset":735894,"endOffset":736127,"count":0}],"isBlockCoverage":false},{"functionName":"_needsNormalization$1","ranges":[{"startOffset":736156,"endOffset":737652,"count":0}],"isBlockCoverage":false},{"functionName":"relative$2$from","ranges":[{"startOffset":737675,"endOffset":741067,"count":0}],"isBlockCoverage":false},{"functionName":"relative$1","ranges":[{"startOffset":741085,"endOffset":741154,"count":0}],"isBlockCoverage":false},{"functionName":"_isWithinOrEquals$2","ranges":[{"startOffset":741181,"endOffset":743129,"count":0}],"isBlockCoverage":false},{"functionName":"_isWithinOrEqualsFast$2","ranges":[{"startOffset":743160,"endOffset":747690,"count":0}],"isBlockCoverage":false},{"functionName":"_pathDirection$2","ranges":[{"startOffset":747714,"endOffset":748939,"count":0}],"isBlockCoverage":false},{"functionName":"toUri$1","ranges":[{"startOffset":748954,"endOffset":749248,"count":0}],"isBlockCoverage":false},{"functionName":"prettyUri$1","ranges":[{"startOffset":749267,"endOffset":749843,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":749900,"endOffset":749973,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":750052,"endOffset":750124,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":750201,"endOffset":750279,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":750359,"endOffset":750468,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":750542,"endOffset":750585,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":750639,"endOffset":750682,"count":0}],"isBlockCoverage":false},{"functionName":"getRoot$1","ranges":[{"startOffset":750735,"endOffset":751064,"count":0}],"isBlockCoverage":false},{"functionName":"relativePathToUri$1","ranges":[{"startOffset":751091,"endOffset":751348,"count":0}],"isBlockCoverage":false},{"functionName":"codeUnitsEqual$2","ranges":[{"startOffset":751372,"endOffset":751448,"count":0}],"isBlockCoverage":false},{"functionName":"pathsEqual$2","ranges":[{"startOffset":751468,"endOffset":751527,"count":0}],"isBlockCoverage":false},{"functionName":"get$hasTrailingSeparator","ranges":[{"startOffset":751592,"endOffset":751829,"count":0}],"isBlockCoverage":false},{"functionName":"removeTrailingSeparators$0","ranges":[{"startOffset":751863,"endOffset":752298,"count":0}],"isBlockCoverage":false},{"functionName":"normalize$0","ranges":[{"startOffset":752317,"endOffset":753935,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":753953,"endOffset":754466,"count":0}],"isBlockCoverage":false},{"functionName":"set$parts","ranges":[{"startOffset":754483,"endOffset":754558,"count":0}],"isBlockCoverage":false},{"functionName":"set$separators","ranges":[{"startOffset":754580,"endOffset":754670,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":754735,"endOffset":754801,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":754875,"endOffset":754941,"count":0}],"isBlockCoverage":false},{"functionName":"get$message","ranges":[{"startOffset":754981,"endOffset":755034,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":755080,"endOffset":755133,"count":0}],"isBlockCoverage":false},{"functionName":"containsSeparator$1","ranges":[{"startOffset":755193,"endOffset":755270,"count":0}],"isBlockCoverage":false},{"functionName":"isSeparator$1","ranges":[{"startOffset":755291,"endOffset":755347,"count":0}],"isBlockCoverage":false},{"functionName":"needsSeparator$1","ranges":[{"startOffset":755371,"endOffset":755500,"count":0}],"isBlockCoverage":false},{"functionName":"rootLength$2$withDrive","ranges":[{"startOffset":755530,"endOffset":755678,"count":0}],"isBlockCoverage":false},{"functionName":"rootLength$1","ranges":[{"startOffset":755698,"endOffset":755775,"count":0}],"isBlockCoverage":false},{"functionName":"isRootRelative$1","ranges":[{"startOffset":755799,"endOffset":755841,"count":0}],"isBlockCoverage":false},{"functionName":"pathFromUri$1","ranges":[{"startOffset":755862,"endOffset":756185,"count":0}],"isBlockCoverage":false},{"functionName":"absolutePathToUri$1","ranges":[{"startOffset":756212,"endOffset":756605,"count":0}],"isBlockCoverage":false},{"functionName":"get$name","ranges":[{"startOffset":756621,"endOffset":756661,"count":0}],"isBlockCoverage":false},{"functionName":"get$separator","ranges":[{"startOffset":756682,"endOffset":756718,"count":0}],"isBlockCoverage":false},{"functionName":"containsSeparator$1","ranges":[{"startOffset":756776,"endOffset":756853,"count":0}],"isBlockCoverage":false},{"functionName":"isSeparator$1","ranges":[{"startOffset":756874,"endOffset":756930,"count":0}],"isBlockCoverage":false},{"functionName":"needsSeparator$1","ranges":[{"startOffset":756954,"endOffset":757222,"count":0}],"isBlockCoverage":false},{"functionName":"rootLength$2$withDrive","ranges":[{"startOffset":757252,"endOffset":758194,"count":0}],"isBlockCoverage":false},{"functionName":"rootLength$1","ranges":[{"startOffset":758214,"endOffset":758291,"count":0}],"isBlockCoverage":false},{"functionName":"isRootRelative$1","ranges":[{"startOffset":758315,"endOffset":758421,"count":0}],"isBlockCoverage":false},{"functionName":"pathFromUri$1","ranges":[{"startOffset":758442,"endOffset":758496,"count":0}],"isBlockCoverage":false},{"functionName":"relativePathToUri$1","ranges":[{"startOffset":758523,"endOffset":758577,"count":0}],"isBlockCoverage":false},{"functionName":"absolutePathToUri$1","ranges":[{"startOffset":758604,"endOffset":758658,"count":0}],"isBlockCoverage":false},{"functionName":"get$name","ranges":[{"startOffset":758674,"endOffset":758712,"count":0}],"isBlockCoverage":false},{"functionName":"get$separator","ranges":[{"startOffset":758733,"endOffset":758769,"count":0}],"isBlockCoverage":false},{"functionName":"containsSeparator$1","ranges":[{"startOffset":758831,"endOffset":758908,"count":0}],"isBlockCoverage":false},{"functionName":"isSeparator$1","ranges":[{"startOffset":758929,"endOffset":759004,"count":0}],"isBlockCoverage":false},{"functionName":"needsSeparator$1","ranges":[{"startOffset":759028,"endOffset":759218,"count":0}],"isBlockCoverage":false},{"functionName":"rootLength$2$withDrive","ranges":[{"startOffset":759248,"endOffset":760107,"count":0}],"isBlockCoverage":false},{"functionName":"rootLength$1","ranges":[{"startOffset":760127,"endOffset":760204,"count":0}],"isBlockCoverage":false},{"functionName":"isRootRelative$1","ranges":[{"startOffset":760228,"endOffset":760294,"count":0}],"isBlockCoverage":false},{"functionName":"pathFromUri$1","ranges":[{"startOffset":760315,"endOffset":760968,"count":0}],"isBlockCoverage":false},{"functionName":"absolutePathToUri$1","ranges":[{"startOffset":760995,"endOffset":762083,"count":0}],"isBlockCoverage":false},{"functionName":"codeUnitsEqual$2","ranges":[{"startOffset":762107,"endOffset":762496,"count":0}],"isBlockCoverage":false},{"functionName":"pathsEqual$2","ranges":[{"startOffset":762516,"endOffset":762906,"count":0}],"isBlockCoverage":false},{"functionName":"get$name","ranges":[{"startOffset":762922,"endOffset":762964,"count":0}],"isBlockCoverage":false},{"functionName":"get$separator","ranges":[{"startOffset":762985,"endOffset":763022,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":763097,"endOffset":763169,"count":0}],"isBlockCoverage":false},{"functionName":"request$0","ranges":[{"startOffset":763232,"endOffset":764213,"count":0}],"isBlockCoverage":false},{"functionName":"withResource$1$1","ranges":[{"startOffset":764237,"endOffset":764370,"count":0}],"isBlockCoverage":false},{"functionName":"withResource$body$Pool","ranges":[{"startOffset":764400,"endOffset":766633,"count":0}],"isBlockCoverage":false},{"functionName":"close$0","ranges":[{"startOffset":766648,"endOffset":766745,"count":0}],"isBlockCoverage":false},{"functionName":"_onResourceReleaseAllowed$1","ranges":[{"startOffset":766780,"endOffset":767623,"count":0}],"isBlockCoverage":false},{"functionName":"_runOnRelease$1","ranges":[{"startOffset":767646,"endOffset":768136,"count":0}],"isBlockCoverage":false},{"functionName":"_resetTimer$0","ranges":[{"startOffset":768157,"endOffset":768543,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":768598,"endOffset":769521,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":769616,"endOffset":769695,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":769777,"endOffset":769909,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":769992,"endOffset":770160,"count":0}],"isBlockCoverage":false},{"functionName":"release$0","ranges":[{"startOffset":770231,"endOffset":770780,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":770838,"endOffset":771040,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":771119,"endOffset":773479,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":773558,"endOffset":773629,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":773709,"endOffset":773806,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":773887,"endOffset":773961,"count":0}],"isBlockCoverage":false},{"functionName":"MultiSectionMapping$fromJson$3$mapUrl","ranges":[{"startOffset":774096,"endOffset":775955,"count":0}],"isBlockCoverage":false},{"functionName":"_indexFor$2","ranges":[{"startOffset":775974,"endOffset":776437,"count":0}],"isBlockCoverage":false},{"functionName":"spanFor$4$files$uri","ranges":[{"startOffset":776464,"endOffset":777052,"count":0}],"isBlockCoverage":false},{"functionName":"spanFor$3$uri","ranges":[{"startOffset":777073,"endOffset":777172,"count":0}],"isBlockCoverage":false},{"functionName":"spanFor$3$files","ranges":[{"startOffset":777195,"endOffset":777298,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":777316,"endOffset":777847,"count":0}],"isBlockCoverage":false},{"functionName":"MappingBundle$fromJson$2$mapUrl","ranges":[{"startOffset":777922,"endOffset":778250,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":778268,"endOffset":778496,"count":0}],"isBlockCoverage":false},{"functionName":"spanFor$4$files$uri","ranges":[{"startOffset":778523,"endOffset":779530,"count":0}],"isBlockCoverage":false},{"functionName":"spanFor$3$uri","ranges":[{"startOffset":779551,"endOffset":779650,"count":0}],"isBlockCoverage":false},{"functionName":"SingleMapping$fromJson$2$mapUrl","ranges":[{"startOffset":779725,"endOffset":783823,"count":0}],"isBlockCoverage":false},{"functionName":"_segmentError$2","ranges":[{"startOffset":783846,"endOffset":784041,"count":0}],"isBlockCoverage":false},{"functionName":"_findLine$1","ranges":[{"startOffset":784060,"endOffset":784406,"count":0}],"isBlockCoverage":false},{"functionName":"_findColumn$3","ranges":[{"startOffset":784427,"endOffset":785004,"count":0}],"isBlockCoverage":false},{"functionName":"spanFor$4$files$uri","ranges":[{"startOffset":785031,"endOffset":786224,"count":0}],"isBlockCoverage":false},{"functionName":"spanFor$3$uri","ranges":[{"startOffset":786245,"endOffset":786344,"count":0}],"isBlockCoverage":false},{"functionName":"spanFor$3$files","ranges":[{"startOffset":786367,"endOffset":786470,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":786488,"endOffset":786852,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":786919,"endOffset":787072,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":787159,"endOffset":787217,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":787306,"endOffset":787368,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":787443,"endOffset":787558,"count":0}],"isBlockCoverage":false},{"functionName":"get$line","ranges":[{"startOffset":787574,"endOffset":787616,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":787668,"endOffset":787921,"count":0}],"isBlockCoverage":false},{"functionName":"get$column","ranges":[{"startOffset":787939,"endOffset":787983,"count":0}],"isBlockCoverage":false},{"functionName":"moveNext$0","ranges":[{"startOffset":788041,"endOffset":788109,"count":0}],"isBlockCoverage":false},{"functionName":"get$current","ranges":[{"startOffset":788128,"endOffset":788407,"count":0}],"isBlockCoverage":false},{"functionName":"get$hasTokens","ranges":[{"startOffset":788428,"endOffset":788527,"count":0}],"isBlockCoverage":false},{"functionName":"get$nextKind","ranges":[{"startOffset":788547,"endOffset":788997,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":789015,"endOffset":789583,"count":0}],"isBlockCoverage":false},{"functionName":"get$isIdentifier","ranges":[{"startOffset":789694,"endOffset":789744,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":789788,"endOffset":790045,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":790116,"endOffset":790175,"count":0}],"isBlockCoverage":false},{"functionName":"get$lines","ranges":[{"startOffset":790192,"endOffset":790248,"count":0}],"isBlockCoverage":false},{"functionName":"SourceFile$decoded$2$url","ranges":[{"startOffset":790280,"endOffset":790792,"count":0}],"isBlockCoverage":false},{"functionName":"span$2","ranges":[{"startOffset":790806,"endOffset":790879,"count":0}],"isBlockCoverage":false},{"functionName":"getLine$1","ranges":[{"startOffset":790896,"endOffset":791616,"count":0}],"isBlockCoverage":false},{"functionName":"_isNearCachedLine$1","ranges":[{"startOffset":791643,"endOffset":792548,"count":0}],"isBlockCoverage":false},{"functionName":"_binarySearch$1","ranges":[{"startOffset":792571,"endOffset":792981,"count":0}],"isBlockCoverage":false},{"functionName":"getColumn$1","ranges":[{"startOffset":793000,"endOffset":793683,"count":0}],"isBlockCoverage":false},{"functionName":"getOffset$2","ranges":[{"startOffset":793702,"endOffset":794481,"count":0}],"isBlockCoverage":false},{"functionName":"getOffset$1","ranges":[{"startOffset":794500,"endOffset":794565,"count":0}],"isBlockCoverage":false},{"functionName":"get$sourceUrl","ranges":[{"startOffset":794621,"endOffset":794667,"count":0}],"isBlockCoverage":false},{"functionName":"get$line","ranges":[{"startOffset":794683,"endOffset":794748,"count":0}],"isBlockCoverage":false},{"functionName":"get$column","ranges":[{"startOffset":794766,"endOffset":794833,"count":0}],"isBlockCoverage":false},{"functionName":"get$offset","ranges":[{"startOffset":794851,"endOffset":794903,"count":0}],"isBlockCoverage":false},{"functionName":"get$sourceUrl","ranges":[{"startOffset":794956,"endOffset":795002,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":795020,"endOffset":795089,"count":0}],"isBlockCoverage":false},{"functionName":"get$start","ranges":[{"startOffset":795106,"endOffset":795185,"count":0}],"isBlockCoverage":false},{"functionName":"get$end","ranges":[{"startOffset":795200,"endOffset":795277,"count":0}],"isBlockCoverage":false},{"functionName":"get$text","ranges":[{"startOffset":795293,"endOffset":795463,"count":0}],"isBlockCoverage":false},{"functionName":"get$context","ranges":[{"startOffset":795482,"endOffset":796567,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":796578,"endOffset":797060,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":797080,"endOffset":797171,"count":0}],"isBlockCoverage":false},{"functionName":"expand$1","ranges":[{"startOffset":797187,"endOffset":797617,"count":0}],"isBlockCoverage":false},{"functionName":"highlight$0","ranges":[{"startOffset":797723,"endOffset":800062,"count":0}],"isBlockCoverage":false},{"functionName":"_writeFirstLine$1","ranges":[{"startOffset":800087,"endOffset":801960,"count":0}],"isBlockCoverage":false},{"functionName":"_writeIntermediateLines$1","ranges":[{"startOffset":801993,"endOffset":802716,"count":0}],"isBlockCoverage":false},{"functionName":"_writeLastLine$1","ranges":[{"startOffset":802740,"endOffset":803867,"count":0}],"isBlockCoverage":false},{"functionName":"_writeTrailingLines$1","ranges":[{"startOffset":803896,"endOffset":804584,"count":0}],"isBlockCoverage":false},{"functionName":"_writeText$1","ranges":[{"startOffset":804604,"endOffset":805084,"count":0}],"isBlockCoverage":false},{"functionName":"_writeSidebar$2$end$line","ranges":[{"startOffset":805116,"endOffset":805243,"count":0}],"isBlockCoverage":false},{"functionName":"_writeSidebar$1$end","ranges":[{"startOffset":805270,"endOffset":805346,"count":0}],"isBlockCoverage":false},{"functionName":"_writeSidebar$1$line","ranges":[{"startOffset":805374,"endOffset":805452,"count":0}],"isBlockCoverage":false},{"functionName":"_writeSidebar$0","ranges":[{"startOffset":805475,"endOffset":805549,"count":0}],"isBlockCoverage":false},{"functionName":"_countTabs$1","ranges":[{"startOffset":805569,"endOffset":805863,"count":0}],"isBlockCoverage":false},{"functionName":"_isOnlyWhitespace$1","ranges":[{"startOffset":805890,"endOffset":806214,"count":0}],"isBlockCoverage":false},{"functionName":"_colorize$2$color","ranges":[{"startOffset":806239,"endOffset":806594,"count":0}],"isBlockCoverage":false},{"functionName":"_colorize$1","ranges":[{"startOffset":806613,"endOffset":806692,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":806764,"endOffset":806982,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":807074,"endOffset":807147,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":807239,"endOffset":807514,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":807606,"endOffset":807796,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":807895,"endOffset":808102,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":808192,"endOffset":808411,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":808502,"endOffset":808715,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":808806,"endOffset":809078,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":809167,"endOffset":809588,"count":0}],"isBlockCoverage":false},{"functionName":"distance$1","ranges":[{"startOffset":809662,"endOffset":809961,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":809972,"endOffset":810183,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":810203,"endOffset":810282,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":810300,"endOffset":810590,"count":0}],"isBlockCoverage":false},{"functionName":"get$sourceUrl","ranges":[{"startOffset":810611,"endOffset":810658,"count":0}],"isBlockCoverage":false},{"functionName":"get$offset","ranges":[{"startOffset":810676,"endOffset":810728,"count":0}],"isBlockCoverage":false},{"functionName":"get$line","ranges":[{"startOffset":810744,"endOffset":810786,"count":0}],"isBlockCoverage":false},{"functionName":"get$column","ranges":[{"startOffset":810804,"endOffset":810848,"count":0}],"isBlockCoverage":false},{"functionName":"distance$1","ranges":[{"startOffset":810908,"endOffset":811205,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":811216,"endOffset":811426,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":811446,"endOffset":811524,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":811542,"endOffset":811946,"count":0}],"isBlockCoverage":false},{"functionName":"SourceSpanBase$3","ranges":[{"startOffset":812064,"endOffset":812766,"count":0}],"isBlockCoverage":false},{"functionName":"get$start","ranges":[{"startOffset":812783,"endOffset":812826,"count":0}],"isBlockCoverage":false},{"functionName":"get$end","ranges":[{"startOffset":812841,"endOffset":812882,"count":0}],"isBlockCoverage":false},{"functionName":"get$text","ranges":[{"startOffset":812898,"endOffset":812940,"count":0}],"isBlockCoverage":false},{"functionName":"get$message","ranges":[{"startOffset":813001,"endOffset":813064,"count":0}],"isBlockCoverage":false},{"functionName":"toString$1$color","ranges":[{"startOffset":813088,"endOffset":813313,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":813331,"endOffset":813411,"count":0}],"isBlockCoverage":false},{"functionName":"get$sourceUrl","ranges":[{"startOffset":813558,"endOffset":813623,"count":0}],"isBlockCoverage":false},{"functionName":"get$length","ranges":[{"startOffset":813641,"endOffset":813799,"count":0}],"isBlockCoverage":false},{"functionName":"message$2$color","ranges":[{"startOffset":813822,"endOffset":814454,"count":0}],"isBlockCoverage":false},{"functionName":"message$1","ranges":[{"startOffset":814471,"endOffset":814568,"count":0}],"isBlockCoverage":false},{"functionName":"highlight$1$color","ranges":[{"startOffset":814593,"endOffset":815709,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":815720,"endOffset":815923,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":815943,"endOffset":816110,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":816128,"endOffset":816349,"count":0}],"isBlockCoverage":false},{"functionName":"get$context","ranges":[{"startOffset":816434,"endOffset":816480,"count":0}],"isBlockCoverage":false},{"functionName":"foldFrames$2$terse","ranges":[{"startOffset":816534,"endOffset":817349,"count":0}],"isBlockCoverage":false},{"functionName":"toTrace$0","ranges":[{"startOffset":817366,"endOffset":817684,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":817702,"endOffset":818222,"count":0}],"isBlockCoverage":false},{"functionName":"get$traces","ranges":[{"startOffset":818262,"endOffset":818306,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":818364,"endOffset":818720,"count":1},{"startOffset":818496,"endOffset":818714,"count":0}],"isBlockCoverage":true},{"functionName":"$signature","ranges":[{"startOffset":818738,"endOffset":818792,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":818856,"endOffset":819515,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":819600,"endOffset":819679,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":819761,"endOffset":819943,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":820026,"endOffset":820116,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":820197,"endOffset":820307,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":820389,"endOffset":820699,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":820777,"endOffset":820853,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":820933,"endOffset":821283,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":821364,"endOffset":821467,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":821546,"endOffset":821837,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":821917,"endOffset":822083,"count":0}],"isBlockCoverage":false},{"functionName":"get$isCore","ranges":[{"startOffset":822149,"endOffset":822214,"count":0}],"isBlockCoverage":false},{"functionName":"get$library","ranges":[{"startOffset":822233,"endOffset":822388,"count":0}],"isBlockCoverage":false},{"functionName":"get$$package","ranges":[{"startOffset":822408,"endOffset":822583,"count":0}],"isBlockCoverage":false},{"functionName":"get$location","ranges":[{"startOffset":822603,"endOffset":822908,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":822926,"endOffset":823016,"count":0}],"isBlockCoverage":false},{"functionName":"get$uri","ranges":[{"startOffset":823031,"endOffset":823072,"count":0}],"isBlockCoverage":false},{"functionName":"get$line","ranges":[{"startOffset":823088,"endOffset":823130,"count":0}],"isBlockCoverage":false},{"functionName":"get$column","ranges":[{"startOffset":823148,"endOffset":823192,"count":0}],"isBlockCoverage":false},{"functionName":"get$member","ranges":[{"startOffset":823210,"endOffset":823254,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":823318,"endOffset":824399,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":824483,"endOffset":825317,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":825415,"endOffset":826447,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":826536,"endOffset":827780,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":827870,"endOffset":829445,"count":0}],"isBlockCoverage":false},{"functionName":"get$_chain","ranges":[{"startOffset":829515,"endOffset":829701,"count":0}],"isBlockCoverage":false},{"functionName":"get$traces","ranges":[{"startOffset":829719,"endOffset":829782,"count":0}],"isBlockCoverage":false},{"functionName":"foldFrames$2$terse","ranges":[{"startOffset":829808,"endOffset":829965,"count":0}],"isBlockCoverage":false},{"functionName":"toTrace$0","ranges":[{"startOffset":829982,"endOffset":830069,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":830087,"endOffset":830153,"count":0}],"isBlockCoverage":false},{"functionName":"set$_lazy_chain$_inner","ranges":[{"startOffset":830183,"endOffset":830267,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":830371,"endOffset":830474,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":830556,"endOffset":830624,"count":0}],"isBlockCoverage":false},{"functionName":"get$_lazy_trace$_trace","ranges":[{"startOffset":830705,"endOffset":830903,"count":0}],"isBlockCoverage":false},{"functionName":"get$frames","ranges":[{"startOffset":830921,"endOffset":830996,"count":0}],"isBlockCoverage":false},{"functionName":"get$original","ranges":[{"startOffset":831016,"endOffset":831093,"count":0}],"isBlockCoverage":false},{"functionName":"foldFrames$2$terse","ranges":[{"startOffset":831119,"endOffset":831276,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":831294,"endOffset":831372,"count":0}],"isBlockCoverage":false},{"functionName":"set$_lazy_trace$_inner","ranges":[{"startOffset":831402,"endOffset":831486,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":831590,"endOffset":831705,"count":0}],"isBlockCoverage":false},{"functionName":"chainFor$1","ranges":[{"startOffset":831787,"endOffset":832653,"count":0}],"isBlockCoverage":false},{"functionName":"_stack_zone_specification$_registerCallback$1$4","ranges":[{"startOffset":832708,"endOffset":833201,"count":1},{"startOffset":832917,"endOffset":832966,"count":0}],"isBlockCoverage":true},{"functionName":"_stack_zone_specification$_registerCallback$4","ranges":[{"startOffset":833254,"endOffset":833402,"count":0}],"isBlockCoverage":false},{"functionName":"_stack_zone_specification$_registerUnaryCallback$2$4","ranges":[{"startOffset":833462,"endOffset":834015,"count":1},{"startOffset":833704,"endOffset":833762,"count":0}],"isBlockCoverage":true},{"functionName":"_stack_zone_specification$_registerUnaryCallback$4","ranges":[{"startOffset":834073,"endOffset":834241,"count":0}],"isBlockCoverage":false},{"functionName":"_stack_zone_specification$_registerBinaryCallback$3$4","ranges":[{"startOffset":834302,"endOffset":834911,"count":1},{"startOffset":834516,"endOffset":834648,"count":0}],"isBlockCoverage":true},{"functionName":"_stack_zone_specification$_registerBinaryCallback$4","ranges":[{"startOffset":834970,"endOffset":835154,"count":0}],"isBlockCoverage":false},{"functionName":"_stack_zone_specification$_errorCallback$5","ranges":[{"startOffset":835204,"endOffset":836108,"count":0}],"isBlockCoverage":false},{"functionName":"_stack_zone_specification$_run$1$2","ranges":[{"startOffset":836150,"endOffset":836761,"count":1},{"startOffset":836415,"endOffset":836692,"count":0}],"isBlockCoverage":true},{"functionName":"_currentTrace$1","ranges":[{"startOffset":836784,"endOffset":836966,"count":1}],"isBlockCoverage":true},{"functionName":"_trimVMChain$1","ranges":[{"startOffset":836988,"endOffset":837222,"count":0}],"isBlockCoverage":false},{"functionName":"set$_currentNode","ranges":[{"startOffset":837246,"endOffset":837336,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":837412,"endOffset":837498,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":837595,"endOffset":837689,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":837793,"endOffset":837926,"count":1}],"isBlockCoverage":true},{"functionName":"$signature","ranges":[{"startOffset":837944,"endOffset":837998,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":838088,"endOffset":838328,"count":1}],"isBlockCoverage":true},{"functionName":"$signature","ranges":[{"startOffset":838346,"endOffset":838433,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":838524,"endOffset":838580,"count":1}],"isBlockCoverage":true},{"functionName":"$signature","ranges":[{"startOffset":838598,"endOffset":838652,"count":1}],"isBlockCoverage":true},{"functionName":"call$2","ranges":[{"startOffset":838743,"endOffset":839016,"count":1}],"isBlockCoverage":true},{"functionName":"$signature","ranges":[{"startOffset":839034,"endOffset":839141,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":839233,"endOffset":839344,"count":1}],"isBlockCoverage":true},{"functionName":"$signature","ranges":[{"startOffset":839362,"endOffset":839416,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":839497,"endOffset":839889,"count":0}],"isBlockCoverage":false},{"functionName":"toChain$0","ranges":[{"startOffset":839953,"endOffset":840253,"count":0}],"isBlockCoverage":false},{"functionName":"foldFrames$2$terse","ranges":[{"startOffset":840307,"endOffset":841859,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":841877,"endOffset":842341,"count":0}],"isBlockCoverage":false},{"functionName":"get$frames","ranges":[{"startOffset":842381,"endOffset":842425,"count":0}],"isBlockCoverage":false},{"functionName":"get$original","ranges":[{"startOffset":842445,"endOffset":842491,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":842555,"endOffset":842867,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":842947,"endOffset":843025,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":843103,"endOffset":843191,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":843269,"endOffset":843376,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":843454,"endOffset":843542,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":843624,"endOffset":843701,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":843783,"endOffset":843871,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":843954,"endOffset":844072,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":844155,"endOffset":844248,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":844332,"endOffset":844425,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":844509,"endOffset":844603,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":844684,"endOffset":845037,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":845119,"endOffset":845519,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":845599,"endOffset":845702,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":845781,"endOffset":846034,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":846108,"endOffset":846153,"count":0}],"isBlockCoverage":false},{"functionName":"get$uri","ranges":[{"startOffset":846185,"endOffset":846226,"count":0}],"isBlockCoverage":false},{"functionName":"get$line","ranges":[{"startOffset":846242,"endOffset":846279,"count":0}],"isBlockCoverage":false},{"functionName":"get$column","ranges":[{"startOffset":846297,"endOffset":846334,"count":0}],"isBlockCoverage":false},{"functionName":"get$isCore","ranges":[{"startOffset":846352,"endOffset":846390,"count":0}],"isBlockCoverage":false},{"functionName":"get$library","ranges":[{"startOffset":846409,"endOffset":846452,"count":0}],"isBlockCoverage":false},{"functionName":"get$$package","ranges":[{"startOffset":846472,"endOffset":846509,"count":0}],"isBlockCoverage":false},{"functionName":"get$location","ranges":[{"startOffset":846529,"endOffset":846572,"count":0}],"isBlockCoverage":false},{"functionName":"get$member","ranges":[{"startOffset":846590,"endOffset":846634,"count":0}],"isBlockCoverage":false},{"functionName":"get$stream","ranges":[{"startOffset":846691,"endOffset":846863,"count":1}],"isBlockCoverage":true},{"functionName":"get$sink","ranges":[{"startOffset":846879,"endOffset":846922,"count":1}],"isBlockCoverage":true},{"functionName":"GuaranteeChannel$3$allowSinkErrors","ranges":[{"startOffset":846964,"endOffset":847401,"count":1}],"isBlockCoverage":true},{"functionName":"_onSinkDisconnected$0","ranges":[{"startOffset":847430,"endOffset":847602,"count":0}],"isBlockCoverage":false},{"functionName":"set$_sink","ranges":[{"startOffset":847619,"endOffset":847714,"count":1}],"isBlockCoverage":true},{"functionName":"set$_streamController","ranges":[{"startOffset":847743,"endOffset":847876,"count":1}],"isBlockCoverage":true},{"functionName":"set$_subscription","ranges":[{"startOffset":847901,"endOffset":848024,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":848085,"endOffset":848387,"count":1},{"startOffset":848177,"endOffset":848184,"count":0}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":848468,"endOffset":848594,"count":0}],"isBlockCoverage":false},{"functionName":"get$done","ranges":[{"startOffset":848666,"endOffset":848725,"count":0}],"isBlockCoverage":false},{"functionName":"add$1","ranges":[{"startOffset":848738,"endOffset":849217,"count":1},{"startOffset":848863,"endOffset":848935,"count":0},{"startOffset":848992,"endOffset":849070,"count":0},{"startOffset":849110,"endOffset":849117,"count":0}],"isBlockCoverage":true},{"functionName":"addError$2","ranges":[{"startOffset":849235,"endOffset":849669,"count":0}],"isBlockCoverage":false},{"functionName":"addError$1","ranges":[{"startOffset":849687,"endOffset":849753,"count":0}],"isBlockCoverage":false},{"functionName":"_addError$2","ranges":[{"startOffset":849772,"endOffset":850246,"count":0}],"isBlockCoverage":false},{"functionName":"_addError$1","ranges":[{"startOffset":850265,"endOffset":850332,"count":0}],"isBlockCoverage":false},{"functionName":"addStream$1","ranges":[{"startOffset":850351,"endOffset":851289,"count":1},{"startOffset":850488,"endOffset":850561,"count":0},{"startOffset":850618,"endOffset":850697,"count":0},{"startOffset":850729,"endOffset":850857,"count":0}],"isBlockCoverage":true},{"functionName":"close$0","ranges":[{"startOffset":851304,"endOffset":851793,"count":0}],"isBlockCoverage":false},{"functionName":"_onStreamDisconnected$0","ranges":[{"startOffset":851824,"endOffset":852220,"count":0}],"isBlockCoverage":false},{"functionName":"set$_addStreamSubscription","ranges":[{"startOffset":852254,"endOffset":852404,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":852558,"endOffset":852577,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":852665,"endOffset":852791,"count":0}],"isBlockCoverage":false},{"functionName":"_MultiChannel$1","ranges":[{"startOffset":852869,"endOffset":853574,"count":1}],"isBlockCoverage":true},{"functionName":"virtualChannel$1","ranges":[{"startOffset":853598,"endOffset":855403,"count":1},{"startOffset":854008,"endOffset":854335,"count":0},{"startOffset":854389,"endOffset":854435,"count":0},{"startOffset":854564,"endOffset":854665,"count":0}],"isBlockCoverage":true},{"functionName":"virtualChannel$0","ranges":[{"startOffset":855427,"endOffset":855487,"count":1}],"isBlockCoverage":true},{"functionName":"_closeChannel$2","ranges":[{"startOffset":855510,"endOffset":855929,"count":0}],"isBlockCoverage":false},{"functionName":"_closeInnerChannel$0","ranges":[{"startOffset":855957,"endOffset":856432,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":856514,"endOffset":856645,"count":1}],"isBlockCoverage":true},{"functionName":"$signature","ranges":[{"startOffset":856663,"endOffset":856718,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":856777,"endOffset":856842,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":856920,"endOffset":857524,"count":1},{"startOffset":857122,"endOffset":857129,"count":0},{"startOffset":857353,"endOffset":857369,"count":0},{"startOffset":857463,"endOffset":857518,"count":0}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":857602,"endOffset":857750,"count":0}],"isBlockCoverage":false},{"functionName":"$signature","ranges":[{"startOffset":857768,"endOffset":857847,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":857920,"endOffset":858103,"count":1}],"isBlockCoverage":true},{"functionName":"$signature","ranges":[{"startOffset":858121,"endOffset":858184,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":858258,"endOffset":858370,"count":0}],"isBlockCoverage":false},{"functionName":"get$stream","ranges":[{"startOffset":858463,"endOffset":858515,"count":0}],"isBlockCoverage":false},{"functionName":"set$_stream_channel_completer$_channel","ranges":[{"startOffset":858606,"endOffset":858735,"count":1}],"isBlockCoverage":true},{"functionName":"get$local","ranges":[{"startOffset":858798,"endOffset":858842,"count":0}],"isBlockCoverage":false},{"functionName":"set$_local","ranges":[{"startOffset":858860,"endOffset":858957,"count":1}],"isBlockCoverage":true},{"functionName":"set$_foreign","ranges":[{"startOffset":858977,"endOffset":859080,"count":1}],"isBlockCoverage":true},{"functionName":"get$stream","ranges":[{"startOffset":859169,"endOffset":859221,"count":1}],"isBlockCoverage":true},{"functionName":"spanFrom$1","ranges":[{"startOffset":859374,"endOffset":859530,"count":0}],"isBlockCoverage":false},{"functionName":"matches$1","ranges":[{"startOffset":859547,"endOffset":859856,"count":0}],"isBlockCoverage":false},{"functionName":"error$3$length$position","ranges":[{"startOffset":859887,"endOffset":860142,"count":0}],"isBlockCoverage":false},{"functionName":"get$lastMatch","ranges":[{"startOffset":860259,"endOffset":860437,"count":0}],"isBlockCoverage":false},{"functionName":"peekChar$0","ranges":[{"startOffset":860455,"endOffset":860647,"count":0}],"isBlockCoverage":false},{"functionName":"scan$1","ranges":[{"startOffset":860661,"endOffset":860895,"count":0}],"isBlockCoverage":false},{"functionName":"expect$2$name","ranges":[{"startOffset":860916,"endOffset":861423,"count":0}],"isBlockCoverage":false},{"functionName":"expect$1","ranges":[{"startOffset":861439,"endOffset":861512,"count":0}],"isBlockCoverage":false},{"functionName":"matches$1","ranges":[{"startOffset":861529,"endOffset":861791,"count":0}],"isBlockCoverage":false},{"functionName":"glyphOrAscii$2","ranges":[{"startOffset":861849,"endOffset":861911,"count":0}],"isBlockCoverage":false},{"functionName":"get$horizontalLine","ranges":[{"startOffset":861937,"endOffset":861973,"count":0}],"isBlockCoverage":false},{"functionName":"get$verticalLine","ranges":[{"startOffset":861997,"endOffset":862033,"count":0}],"isBlockCoverage":false},{"functionName":"get$topLeftCorner","ranges":[{"startOffset":862058,"endOffset":862094,"count":0}],"isBlockCoverage":false},{"functionName":"get$bottomLeftCorner","ranges":[{"startOffset":862122,"endOffset":862158,"count":0}],"isBlockCoverage":false},{"functionName":"get$upEnd","ranges":[{"startOffset":862175,"endOffset":862211,"count":0}],"isBlockCoverage":false},{"functionName":"get$downEnd","ranges":[{"startOffset":862230,"endOffset":862266,"count":0}],"isBlockCoverage":false},{"functionName":"glyphOrAscii$2","ranges":[{"startOffset":862326,"endOffset":862382,"count":0}],"isBlockCoverage":false},{"functionName":"get$horizontalLine","ranges":[{"startOffset":862408,"endOffset":862449,"count":0}],"isBlockCoverage":false},{"functionName":"get$verticalLine","ranges":[{"startOffset":862473,"endOffset":862514,"count":0}],"isBlockCoverage":false},{"functionName":"get$topLeftCorner","ranges":[{"startOffset":862539,"endOffset":862580,"count":0}],"isBlockCoverage":false},{"functionName":"get$bottomLeftCorner","ranges":[{"startOffset":862608,"endOffset":862649,"count":0}],"isBlockCoverage":false},{"functionName":"get$upEnd","ranges":[{"startOffset":862666,"endOffset":862707,"count":0}],"isBlockCoverage":false},{"functionName":"get$downEnd","ranges":[{"startOffset":862726,"endOffset":862767,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":862840,"endOffset":864682,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":863077,"endOffset":864609,"count":1},{"startOffset":863167,"endOffset":863223,"count":0},{"startOffset":863485,"endOffset":863577,"count":0},{"startOffset":863993,"endOffset":864097,"count":0},{"startOffset":864323,"endOffset":864422,"count":0}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":864764,"endOffset":865103,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":865187,"endOffset":865869,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":865953,"endOffset":866183,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":866268,"endOffset":866429,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":866513,"endOffset":866721,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":866796,"endOffset":866858,"count":0}],"isBlockCoverage":false},{"functionName":"test$9$onPlatform$retry$skip$solo$tags$testOn$timeout","ranges":[{"startOffset":866971,"endOffset":867811,"count":1},{"startOffset":867323,"endOffset":867326,"count":0},{"startOffset":867550,"endOffset":867557,"count":0},{"startOffset":867633,"endOffset":867659,"count":0}],"isBlockCoverage":true},{"functionName":"group$9$onPlatform$retry$skip$solo$tags$testOn$timeout","ranges":[{"startOffset":867873,"endOffset":869608,"count":1},{"startOffset":868325,"endOffset":868328,"count":0},{"startOffset":868584,"endOffset":868610,"count":0},{"startOffset":868684,"endOffset":868702,"count":0},{"startOffset":869525,"endOffset":869602,"count":0}],"isBlockCoverage":true},{"functionName":"build$0","ranges":[{"startOffset":869623,"endOffset":870102,"count":1}],"isBlockCoverage":true},{"functionName":"_checkNotBuilt$1","ranges":[{"startOffset":870126,"endOffset":870294,"count":1},{"startOffset":870183,"endOffset":870293,"count":0}],"isBlockCoverage":true},{"functionName":"_runSetUps$0","ranges":[{"startOffset":870314,"endOffset":871575,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":870514,"endOffset":871496,"count":1},{"startOffset":870604,"endOffset":870660,"count":0}],"isBlockCoverage":true},{"functionName":"get$_setUpAll","ranges":[{"startOffset":871596,"endOffset":871633,"count":1}],"isBlockCoverage":true},{"functionName":"get$_tearDownAll","ranges":[{"startOffset":871657,"endOffset":872027,"count":1},{"startOffset":871775,"endOffset":871849,"count":0},{"startOffset":871850,"endOffset":871873,"count":0}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":872085,"endOffset":874867,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":872360,"endOffset":874794,"count":1},{"startOffset":872450,"endOffset":872506,"count":0},{"startOffset":873288,"endOffset":874287,"count":0}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":874945,"endOffset":875120,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":875200,"endOffset":876169,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":875387,"endOffset":876096,"count":1},{"startOffset":875477,"endOffset":875533,"count":0}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":876247,"endOffset":876413,"count":1},{"startOffset":876332,"endOffset":876412,"count":0}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":876491,"endOffset":876827,"count":1},{"startOffset":876626,"endOffset":876669,"count":0},{"startOffset":876670,"endOffset":876812,"count":0}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":876911,"endOffset":876963,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":877049,"endOffset":877288,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":877374,"endOffset":877550,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":877637,"endOffset":879068,"count":0}],"isBlockCoverage":false},{"functionName":"forPlatform$1","ranges":[{"startOffset":879136,"endOffset":879644,"count":1},{"startOffset":879307,"endOffset":879319,"count":0},{"startOffset":879481,"endOffset":879510,"count":0},{"startOffset":879520,"endOffset":879532,"count":0}],"isBlockCoverage":true},{"functionName":"_group$_map$1","ranges":[{"startOffset":879665,"endOffset":880149,"count":1}],"isBlockCoverage":true},{"functionName":"get$name","ranges":[{"startOffset":880187,"endOffset":880237,"count":0}],"isBlockCoverage":false},{"functionName":"get$metadata","ranges":[{"startOffset":880257,"endOffset":880303,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":880365,"endOffset":880437,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":880512,"endOffset":880602,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":880678,"endOffset":880754,"count":1}],"isBlockCoverage":true},{"functionName":"load$2$groups","ranges":[{"startOffset":880858,"endOffset":881479,"count":1}],"isBlockCoverage":true},{"functionName":"forPlatform$1","ranges":[{"startOffset":881500,"endOffset":881799,"count":1},{"startOffset":881648,"endOffset":881660,"count":0}],"isBlockCoverage":true},{"functionName":"get$name","ranges":[{"startOffset":881815,"endOffset":881865,"count":0}],"isBlockCoverage":false},{"functionName":"get$metadata","ranges":[{"startOffset":881885,"endOffset":881931,"count":0}],"isBlockCoverage":false},{"functionName":"get$_outstandingCallbacks","ranges":[{"startOffset":881994,"endOffset":882266,"count":1},{"startOffset":882147,"endOffset":882265,"count":0}],"isBlockCoverage":true},{"functionName":"addOutstandingCallback$0","ranges":[{"startOffset":882298,"endOffset":882562,"count":0}],"isBlockCoverage":false},{"functionName":"waitForOutstandingCallbacks$1","ranges":[{"startOffset":882599,"endOffset":883243,"count":1}],"isBlockCoverage":true},{"functionName":"unclosable$1$1","ranges":[{"startOffset":883265,"endOffset":883512,"count":1}],"isBlockCoverage":true},{"functionName":"heartbeat$0","ranges":[{"startOffset":883531,"endOffset":884164,"count":1},{"startOffset":883729,"endOffset":883736,"count":0},{"startOffset":883989,"endOffset":883996,"count":0}],"isBlockCoverage":true},{"functionName":"_handleError$3","ranges":[{"startOffset":884186,"endOffset":885992,"count":0}],"isBlockCoverage":false},{"functionName":"_handleError$2","ranges":[{"startOffset":886014,"endOffset":886096,"count":0}],"isBlockCoverage":false},{"functionName":"_invoker$_onRun$0","ranges":[{"startOffset":886121,"endOffset":886628,"count":1}],"isBlockCoverage":true},{"functionName":"_runTearDowns$0","ranges":[{"startOffset":886651,"endOffset":888109,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":886875,"endOffset":888027,"count":1},{"startOffset":886965,"endOffset":887021,"count":0},{"startOffset":887385,"endOffset":887694,"count":0},{"startOffset":887707,"endOffset":887841,"count":0}],"isBlockCoverage":true},{"functionName":"call$5","ranges":[{"startOffset":888167,"endOffset":888558,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":888637,"endOffset":888765,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":888865,"endOffset":889886,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":889058,"endOffset":889813,"count":1},{"startOffset":889148,"endOffset":889204,"count":0}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":889986,"endOffset":890094,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":890175,"endOffset":890978,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":891060,"endOffset":891255,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":891337,"endOffset":891638,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":891722,"endOffset":891930,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":892015,"endOffset":892186,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":892264,"endOffset":892515,"count":1},{"startOffset":892445,"endOffset":892477,"count":0}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":892594,"endOffset":893102,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":893182,"endOffset":895232,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":893413,"endOffset":895159,"count":1},{"startOffset":893503,"endOffset":893559,"count":0},{"startOffset":894440,"endOffset":894592,"count":0},{"startOffset":894648,"endOffset":894893,"count":0}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":895313,"endOffset":896507,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":895504,"endOffset":896434,"count":1},{"startOffset":895594,"endOffset":895650,"count":0}],"isBlockCoverage":true},{"functionName":"call$4","ranges":[{"startOffset":896588,"endOffset":896759,"count":0}],"isBlockCoverage":false},{"functionName":"decrement$0","ranges":[{"startOffset":896834,"endOffset":897013,"count":1},{"startOffset":896886,"endOffset":896893,"count":0},{"startOffset":896977,"endOffset":896984,"count":0}],"isBlockCoverage":true},{"functionName":"run$0","ranges":[{"startOffset":897087,"endOffset":897565,"count":0}],"isBlockCoverage":false},{"functionName":"addError$2","ranges":[{"startOffset":897624,"endOffset":897936,"count":0}],"isBlockCoverage":false},{"functionName":"setState$1","ranges":[{"startOffset":897954,"endOffset":898264,"count":1},{"startOffset":898062,"endOffset":898069,"count":0},{"startOffset":898141,"endOffset":898148,"count":0}],"isBlockCoverage":true},{"functionName":"message$1","ranges":[{"startOffset":898281,"endOffset":898470,"count":0}],"isBlockCoverage":false},{"functionName":"_live_test_controller$_run$0","ranges":[{"startOffset":898506,"endOffset":898976,"count":1},{"startOffset":898579,"endOffset":898668,"count":0},{"startOffset":898737,"endOffset":898829,"count":0}],"isBlockCoverage":true},{"functionName":"_live_test_controller$_close$0","ranges":[{"startOffset":899014,"endOffset":899384,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":899464,"endOffset":899507,"count":0}],"isBlockCoverage":false},{"functionName":"_validateTags$0","ranges":[{"startOffset":899561,"endOffset":900156,"count":1},{"startOffset":899966,"endOffset":900155,"count":0}],"isBlockCoverage":true},{"functionName":"validatePlatformSelectors$1","ranges":[{"startOffset":900191,"endOffset":900418,"count":1}],"isBlockCoverage":true},{"functionName":"merge$1","ranges":[{"startOffset":900433,"endOffset":901393,"count":1}],"isBlockCoverage":true},{"functionName":"change$4$onPlatform$skip$skipReason$timeout","ranges":[{"startOffset":901444,"endOffset":902100,"count":0}],"isBlockCoverage":false},{"functionName":"change$1$onPlatform","ranges":[{"startOffset":902127,"endOffset":902248,"count":0}],"isBlockCoverage":false},{"functionName":"change$1$timeout","ranges":[{"startOffset":902272,"endOffset":902387,"count":0}],"isBlockCoverage":false},{"functionName":"change$2$skip$skipReason","ranges":[{"startOffset":902419,"endOffset":902546,"count":0}],"isBlockCoverage":false},{"functionName":"forPlatform$1","ranges":[{"startOffset":902567,"endOffset":902916,"count":1},{"startOffset":902687,"endOffset":902915,"count":0}],"isBlockCoverage":true},{"functionName":"serialize$0","ranges":[{"startOffset":902935,"endOffset":903762,"count":1},{"startOffset":903242,"endOffset":903261,"count":0}],"isBlockCoverage":true},{"functionName":"_serializeTimeout$1","ranges":[{"startOffset":903789,"endOffset":904104,"count":1},{"startOffset":903878,"endOffset":903892,"count":0},{"startOffset":903951,"endOffset":903965,"count":0}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":904170,"endOffset":904437,"count":1}],"isBlockCoverage":true},{"functionName":"call$2","ranges":[{"startOffset":904519,"endOffset":904859,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":904944,"endOffset":905183,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":905270,"endOffset":905391,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":905478,"endOffset":905558,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":905656,"endOffset":905903,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":905982,"endOffset":906116,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":906196,"endOffset":906330,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":906415,"endOffset":906760,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":906843,"endOffset":907050,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":907134,"endOffset":907382,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":907458,"endOffset":907501,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":907566,"endOffset":907676,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":907762,"endOffset":907799,"count":1}],"isBlockCoverage":true},{"functionName":"validate$1","ranges":[{"startOffset":907875,"endOffset":908141,"count":1},{"startOffset":908007,"endOffset":908140,"count":0}],"isBlockCoverage":true},{"functionName":"evaluate$1","ranges":[{"startOffset":908159,"endOffset":908292,"count":1}],"isBlockCoverage":true},{"functionName":"intersection$1","ranges":[{"startOffset":908314,"endOffset":908542,"count":1},{"startOffset":908448,"endOffset":908541,"count":0}],"isBlockCoverage":true},{"functionName":"toString$0","ranges":[{"startOffset":908560,"endOffset":908639,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":908650,"endOffset":908848,"count":0}],"isBlockCoverage":false},{"functionName":"get$hashCode","ranges":[{"startOffset":908868,"endOffset":908949,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":909016,"endOffset":909144,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":909234,"endOffset":909377,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":909467,"endOffset":909603,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":909692,"endOffset":910518,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":910585,"endOffset":910628,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":910700,"endOffset":910802,"count":1}],"isBlockCoverage":true},{"functionName":"configure$3$except$mapper$only","ranges":[{"startOffset":910902,"endOffset":911192,"count":1},{"startOffset":911107,"endOffset":911132,"count":0},{"startOffset":911165,"endOffset":911186,"count":0}],"isBlockCoverage":true},{"functionName":"configure$2$except$only","ranges":[{"startOffset":911223,"endOffset":911323,"count":1}],"isBlockCoverage":true},{"functionName":"configure$1$mapper","ranges":[{"startOffset":911349,"endOffset":911443,"count":1}],"isBlockCoverage":true},{"functionName":"formatStackTrace$2$verbose","ranges":[{"startOffset":911477,"endOffset":912169,"count":0}],"isBlockCoverage":false},{"functionName":"set$_except","ranges":[{"startOffset":912188,"endOffset":912268,"count":0}],"isBlockCoverage":false},{"functionName":"set$_only","ranges":[{"startOffset":912285,"endOffset":912359,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":912440,"endOffset":912670,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":912729,"endOffset":912905,"count":1},{"startOffset":912783,"endOffset":912796,"count":0},{"startOffset":912867,"endOffset":912898,"count":0}],"isBlockCoverage":true},{"functionName":"get$hashCode","ranges":[{"startOffset":912925,"endOffset":913054,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":913072,"endOffset":913383,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":913430,"endOffset":913473,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":913521,"endOffset":913564,"count":0}],"isBlockCoverage":false},{"functionName":"toString$0","ranges":[{"startOffset":913717,"endOffset":913763,"count":0}],"isBlockCoverage":false},{"functionName":"get$message","ranges":[{"startOffset":913782,"endOffset":913835,"count":0}],"isBlockCoverage":false},{"functionName":"call$5","ranges":[{"startOffset":913888,"endOffset":914188,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":914260,"endOffset":914278,"count":1}],"isBlockCoverage":true},{"functionName":"merge$1","ranges":[{"startOffset":914342,"endOffset":915081,"count":1},{"startOffset":914467,"endOffset":914494,"count":0},{"startOffset":914552,"endOffset":914583,"count":0},{"startOffset":914632,"endOffset":914853,"count":0},{"startOffset":914955,"endOffset":914972,"count":0},{"startOffset":915015,"endOffset":915032,"count":0}],"isBlockCoverage":true},{"functionName":"apply$1","ranges":[{"startOffset":915096,"endOffset":915445,"count":1},{"startOffset":915179,"endOffset":915191,"count":0},{"startOffset":915319,"endOffset":915336,"count":0}],"isBlockCoverage":true},{"functionName":"get$hashCode","ranges":[{"startOffset":915465,"endOffset":915577,"count":0}],"isBlockCoverage":false},{"functionName":"$eq","ranges":[{"startOffset":915588,"endOffset":915784,"count":1},{"startOffset":915642,"endOffset":915655,"count":0}],"isBlockCoverage":true},{"functionName":"toString$0","ranges":[{"startOffset":915802,"endOffset":916008,"count":0}],"isBlockCoverage":false},{"functionName":"_serializeGroup$3","ranges":[{"startOffset":916070,"endOffset":917084,"count":1},{"startOffset":916473,"endOffset":916517,"count":0}],"isBlockCoverage":true},{"functionName":"_serializeTest$3","ranges":[{"startOffset":917108,"endOffset":917764,"count":1},{"startOffset":917540,"endOffset":917584,"count":0}],"isBlockCoverage":true},{"functionName":"_runLiveTest$2","ranges":[{"startOffset":917786,"endOffset":918752,"count":1}],"isBlockCoverage":true},{"functionName":"call$4","ranges":[{"startOffset":918817,"endOffset":919145,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":919231,"endOffset":919250,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":919335,"endOffset":919891,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":919976,"endOffset":920289,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":920375,"endOffset":925739,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":920701,"endOffset":925666,"count":1},{"startOffset":920791,"endOffset":920847,"count":0},{"startOffset":921070,"endOffset":921774,"count":0},{"startOffset":921820,"endOffset":922042,"count":0},{"startOffset":922087,"endOffset":922311,"count":0},{"startOffset":923050,"endOffset":923091,"count":0},{"startOffset":923567,"endOffset":923597,"count":0}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":925826,"endOffset":927365,"count":1},{"startOffset":925967,"endOffset":926041,"count":0},{"startOffset":926601,"endOffset":926671,"count":0},{"startOffset":927004,"endOffset":927069,"count":0},{"startOffset":927115,"endOffset":927359,"count":0}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":927453,"endOffset":927588,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":927676,"endOffset":928035,"count":1}],"isBlockCoverage":true},{"functionName":"call$2","ranges":[{"startOffset":928122,"endOffset":928276,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":928370,"endOffset":928663,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":928757,"endOffset":929103,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":929194,"endOffset":929380,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":929472,"endOffset":929733,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":929826,"endOffset":930378,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":930471,"endOffset":930825,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":930918,"endOffset":931101,"count":1}],"isBlockCoverage":true},{"functionName":"call$1","ranges":[{"startOffset":931193,"endOffset":931352,"count":1}],"isBlockCoverage":true},{"functionName":"connectOut$1","ranges":[{"startOffset":931434,"endOffset":932439,"count":1},{"startOffset":931560,"endOffset":931587,"count":0},{"startOffset":931674,"endOffset":931767,"count":0}],"isBlockCoverage":true},{"functionName":"get$length","ranges":[{"startOffset":932491,"endOffset":932603,"count":0}],"isBlockCoverage":false},{"functionName":"get$iterator","ranges":[{"startOffset":932623,"endOffset":932784,"count":0}],"isBlockCoverage":false},{"functionName":"toSet$0","ranges":[{"startOffset":932799,"endOffset":932888,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":933051,"endOffset":933169,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":933252,"endOffset":933441,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":933506,"endOffset":933888,"count":0}],"isBlockCoverage":false},{"functionName":"get$_onUnpaused","ranges":[{"startOffset":933961,"endOffset":934099,"count":0}],"isBlockCoverage":false},{"functionName":"get$success","ranges":[{"startOffset":934118,"endOffset":935569,"count":0}],"isBlockCoverage":false},{"functionName":"get$liveTests","ranges":[{"startOffset":935590,"endOffset":936069,"count":0}],"isBlockCoverage":false},{"functionName":"Engine$3$concurrency$coverage$maxSuites","ranges":[{"startOffset":936116,"endOffset":936304,"count":0}],"isBlockCoverage":false},{"functionName":"run$0","ranges":[{"startOffset":936317,"endOffset":936943,"count":0}],"isBlockCoverage":false},{"functionName":"_runGroup$3","ranges":[{"startOffset":936962,"endOffset":937125,"count":0}],"isBlockCoverage":false},{"functionName":"_runGroup$body$Engine","ranges":[{"startOffset":937154,"endOffset":945098,"count":0}],"isBlockCoverage":false},{"functionName":"_engine$_runLiveTest$3$countSuccess","ranges":[{"startOffset":945141,"endOffset":945283,"count":0}],"isBlockCoverage":false},{"functionName":"_engine$_runLiveTest$2","ranges":[{"startOffset":945313,"endOffset":945444,"count":0}],"isBlockCoverage":false},{"functionName":"_runLiveTest$body$Engine","ranges":[{"startOffset":945476,"endOffset":948266,"count":0}],"isBlockCoverage":false},{"functionName":"_runSkippedTest$3","ranges":[{"startOffset":948291,"endOffset":948443,"count":0}],"isBlockCoverage":false},{"functionName":"_runSkippedTest$body$Engine","ranges":[{"startOffset":948478,"endOffset":950257,"count":0}],"isBlockCoverage":false},{"functionName":"_addLiveSuite$1","ranges":[{"startOffset":950280,"endOffset":951177,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":951236,"endOffset":951499,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":951570,"endOffset":951828,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":951900,"endOffset":951919,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":951993,"endOffset":952254,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":952330,"endOffset":952400,"count":0}],"isBlockCoverage":false},{"functionName":"$call$body$Engine_run__closure","ranges":[{"startOffset":952438,"endOffset":953809,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":953885,"endOffset":955623,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":955700,"endOffset":955766,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":955842,"endOffset":956062,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":956145,"endOffset":956558,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":956643,"endOffset":956740,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":956824,"endOffset":956842,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":956928,"endOffset":956946,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":957033,"endOffset":957502,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":957589,"endOffset":957607,"count":0}],"isBlockCoverage":false},{"functionName":"LiveSuiteController$1","ranges":[{"startOffset":957758,"endOffset":958027,"count":0}],"isBlockCoverage":false},{"functionName":"reportLiveTest$2$countSuccess","ranges":[{"startOffset":958064,"endOffset":958889,"count":0}],"isBlockCoverage":false},{"functionName":"close$0","ranges":[{"startOffset":958904,"endOffset":959033,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":959097,"endOffset":959152,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":959237,"endOffset":959256,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":959354,"endOffset":959967,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":960057,"endOffset":961699,"count":0}],"isBlockCoverage":false},{"functionName":"_onTestStarted$1","ranges":[{"startOffset":961781,"endOffset":963251,"count":0}],"isBlockCoverage":false},{"functionName":"_onStateChange$2","ranges":[{"startOffset":963275,"endOffset":963683,"count":0}],"isBlockCoverage":false},{"functionName":"_expanded$_onError$3","ranges":[{"startOffset":963711,"endOffset":964186,"count":0}],"isBlockCoverage":false},{"functionName":"_expanded$_onDone$1","ranges":[{"startOffset":964213,"endOffset":965237,"count":0}],"isBlockCoverage":false},{"functionName":"_progressLine$3$color$suffix","ranges":[{"startOffset":965273,"endOffset":967686,"count":0}],"isBlockCoverage":false},{"functionName":"_progressLine$2$suffix","ranges":[{"startOffset":967716,"endOffset":967820,"count":0}],"isBlockCoverage":false},{"functionName":"_progressLine$2$color","ranges":[{"startOffset":967849,"endOffset":967951,"count":0}],"isBlockCoverage":false},{"functionName":"_progressLine$1","ranges":[{"startOffset":967974,"endOffset":968068,"count":0}],"isBlockCoverage":false},{"functionName":"_description$1","ranges":[{"startOffset":968090,"endOffset":968203,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":968279,"endOffset":968386,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":968484,"endOffset":968637,"count":0}],"isBlockCoverage":false},{"functionName":"call$1","ranges":[{"startOffset":968735,"endOffset":969071,"count":0}],"isBlockCoverage":false},{"functionName":"_runner_suite$_close$0","ranges":[{"startOffset":969197,"endOffset":969305,"count":0}],"isBlockCoverage":false},{"functionName":"set$_runner_suite$_suite","ranges":[{"startOffset":969337,"endOffset":969408,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":969481,"endOffset":970301,"count":0}],"isBlockCoverage":false},{"functionName":"writeln$1","ranges":[{"startOffset":970445,"endOffset":970545,"count":0}],"isBlockCoverage":false},{"functionName":"_flush$0","ranges":[{"startOffset":970561,"endOffset":970743,"count":0}],"isBlockCoverage":false},{"functionName":"call$2","ranges":[{"startOffset":970896,"endOffset":971053,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":971128,"endOffset":974564,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":974638,"endOffset":974728,"count":0}],"isBlockCoverage":false},{"functionName":"call$0","ranges":[{"startOffset":974798,"endOffset":974868,"count":1}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":974937,"endOffset":975688,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":975109,"endOffset":975615,"count":1},{"startOffset":975199,"endOffset":975255,"count":0},{"startOffset":975440,"endOffset":975452,"count":0}],"isBlockCoverage":true},{"functionName":"call$0","ranges":[{"startOffset":975756,"endOffset":975816,"count":1}],"isBlockCoverage":true},{"functionName":"aliases","ranges":[{"startOffset":975846,"endOffset":976773,"count":1}],"isBlockCoverage":true},{"functionName":"installTearOffs","ranges":[{"startOffset":976781,"endOffset":984996,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":978155,"endOffset":978225,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":978518,"endOffset":978624,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":978734,"endOffset":978870,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":979096,"endOffset":979215,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":979350,"endOffset":979489,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":979626,"endOffset":979781,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":984923,"endOffset":984982,"count":0}],"isBlockCoverage":false},{"functionName":"inheritance","ranges":[{"startOffset":985004,"endOffset":1007745,"count":1}],"isBlockCoverage":true},{"functionName":"rtii","ranges":[{"startOffset":1029633,"endOffset":1042848,"count":1},{"startOffset":1042844,"endOffset":1042847,"count":0}],"isBlockCoverage":true},{"functionName":"constants","ranges":[{"startOffset":1042856,"endOffset":1058765,"count":1}],"isBlockCoverage":true},{"functionName":"getTagFallback","ranges":[{"startOffset":1044143,"endOffset":1044257,"count":0}],"isBlockCoverage":false},{"functionName":"C.C_JS_CONST0","ranges":[{"startOffset":1044279,"endOffset":1045394,"count":1},{"startOffset":1045302,"endOffset":1045317,"count":0}],"isBlockCoverage":true},{"functionName":"getTag","ranges":[{"startOffset":1044346,"endOffset":1044449,"count":0}],"isBlockCoverage":false},{"functionName":"getUnknownTag","ranges":[{"startOffset":1044452,"endOffset":1044669,"count":0}],"isBlockCoverage":false},{"functionName":"getUnknownTagGenericBrowser","ranges":[{"startOffset":1044672,"endOffset":1044847,"count":0}],"isBlockCoverage":false},{"functionName":"prototypeForTag","ranges":[{"startOffset":1044850,"endOffset":1045116,"count":1},{"startOffset":1044920,"endOffset":1044932,"count":0},{"startOffset":1045066,"endOffset":1045078,"count":0}],"isBlockCoverage":true},{"functionName":"discriminator","ranges":[{"startOffset":1045119,"endOffset":1045163,"count":0}],"isBlockCoverage":false},{"functionName":"C.C_JS_CONST6","ranges":[{"startOffset":1045416,"endOffset":1045880,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1045452,"endOffset":1045877,"count":1},{"startOffset":1045508,"endOffset":1045521,"count":0},{"startOffset":1045599,"endOffset":1045612,"count":0},{"startOffset":1045838,"endOffset":1045876,"count":0}],"isBlockCoverage":true},{"functionName":"confirm","ranges":[{"startOffset":1045656,"endOffset":1045763,"count":1}],"isBlockCoverage":true},{"functionName":"C.C_JS_CONST1","ranges":[{"startOffset":1045902,"endOffset":1046051,"count":1},{"startOffset":1045989,"endOffset":1046050,"count":0}],"isBlockCoverage":true},{"functionName":"C.C_JS_CONST2","ranges":[{"startOffset":1046073,"endOffset":1046546,"count":1}],"isBlockCoverage":true},{"functionName":"getTagFixed","ranges":[{"startOffset":1046169,"endOffset":1046350,"count":0}],"isBlockCoverage":false},{"functionName":"prototypeForTagFixed","ranges":[{"startOffset":1046353,"endOffset":1046466,"count":1},{"startOffset":1046417,"endOffset":1046429,"count":0}],"isBlockCoverage":true},{"functionName":"C.C_JS_CONST5","ranges":[{"startOffset":1046568,"endOffset":1047098,"count":1},{"startOffset":1046655,"endOffset":1046659,"count":0},{"startOffset":1046716,"endOffset":1047097,"count":0}],"isBlockCoverage":true},{"functionName":"getTagFirefox","ranges":[{"startOffset":1046975,"endOffset":1047064,"count":0}],"isBlockCoverage":false},{"functionName":"C.C_JS_CONST4","ranges":[{"startOffset":1047120,"endOffset":1048002,"count":1},{"startOffset":1047207,"endOffset":1047211,"count":0},{"startOffset":1047269,"endOffset":1048001,"count":0}],"isBlockCoverage":true},{"functionName":"getTagIE","ranges":[{"startOffset":1047534,"endOffset":1047777,"count":0}],"isBlockCoverage":false},{"functionName":"prototypeForTagIE","ranges":[{"startOffset":1047780,"endOffset":1047928,"count":0}],"isBlockCoverage":false},{"functionName":"C.C_JS_CONST3","ranges":[{"startOffset":1048024,"endOffset":1048057,"count":1}],"isBlockCoverage":true},{"functionName":"staticFields","ranges":[{"startOffset":1058773,"endOffset":1059835,"count":1}],"isBlockCoverage":true},{"functionName":"lazyInitializers","ranges":[{"startOffset":1059843,"endOffset":1071865,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1059985,"endOffset":1060063,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1060144,"endOffset":1060213,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1060314,"endOffset":1060502,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1060599,"endOffset":1060802,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1060895,"endOffset":1061006,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1061113,"endOffset":1061364,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1061467,"endOffset":1061580,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1061697,"endOffset":1061952,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1062053,"endOffset":1062168,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1062283,"endOffset":1062472,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1062583,"endOffset":1062700,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1062825,"endOffset":1063018,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1063117,"endOffset":1063192,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1063257,"endOffset":1063342,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1063407,"endOffset":1063495,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1063564,"endOffset":1063625,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1063716,"endOffset":1064340,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1064411,"endOffset":1064569,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1064640,"endOffset":1064721,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1064794,"endOffset":1064854,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1064911,"endOffset":1064961,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1065054,"endOffset":1065143,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1065214,"endOffset":1065295,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1065367,"endOffset":1065450,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1065513,"endOffset":1065593,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1065648,"endOffset":1065830,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1065873,"endOffset":1065947,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1065982,"endOffset":1066052,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1066095,"endOffset":1066172,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1066223,"endOffset":1066364,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1066419,"endOffset":1066666,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1066713,"endOffset":1066941,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1066998,"endOffset":1067058,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1067101,"endOffset":1067158,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1067205,"endOffset":1067275,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1067322,"endOffset":1067389,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1067434,"endOffset":1067481,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1067526,"endOffset":1067631,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1067676,"endOffset":1067794,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1067851,"endOffset":1067937,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1067996,"endOffset":1068106,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1068173,"endOffset":1068312,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1068369,"endOffset":1068474,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1068523,"endOffset":1068622,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1068673,"endOffset":1068736,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1068797,"endOffset":1068883,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1068952,"endOffset":1069039,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1069134,"endOffset":1069181,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1069234,"endOffset":1069315,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1069360,"endOffset":1069430,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1069483,"endOffset":1069550,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1069617,"endOffset":1069721,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1069778,"endOffset":1069882,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1069939,"endOffset":1070078,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1070155,"endOffset":1070594,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1070646,"endOffset":1070693,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1070745,"endOffset":1070792,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1070849,"endOffset":1070907,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1070979,"endOffset":1071062,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1071147,"endOffset":1071254,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1071331,"endOffset":1071859,"count":0}],"isBlockCoverage":false},{"functionName":"nativeSupport","ranges":[{"startOffset":1071873,"endOffset":1079153,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1071905,"endOffset":1072690,"count":1},{"startOffset":1072593,"endOffset":1072689,"count":0}],"isBlockCoverage":true},{"functionName":"intern","ranges":[{"startOffset":1071937,"endOffset":1072063,"count":1}],"isBlockCoverage":true},{"functionName":"init.getIsolateTag","ranges":[{"startOffset":1072092,"endOffset":1072176,"count":1}],"isBlockCoverage":true},{"functionName":"Function.call$0","ranges":[{"startOffset":1079188,"endOffset":1079223,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$1","ranges":[{"startOffset":1079255,"endOffset":1079292,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$2","ranges":[{"startOffset":1079324,"endOffset":1079367,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$3$3","ranges":[{"startOffset":1079401,"endOffset":1079450,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$2$2","ranges":[{"startOffset":1079484,"endOffset":1079527,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$1$1","ranges":[{"startOffset":1079561,"endOffset":1079598,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$2$1","ranges":[{"startOffset":1079632,"endOffset":1079669,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$3","ranges":[{"startOffset":1079701,"endOffset":1079750,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$4","ranges":[{"startOffset":1079782,"endOffset":1079837,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$3$1","ranges":[{"startOffset":1079871,"endOffset":1079908,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$2$3","ranges":[{"startOffset":1079942,"endOffset":1079991,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$1$2","ranges":[{"startOffset":1080025,"endOffset":1080068,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$5","ranges":[{"startOffset":1080100,"endOffset":1080161,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$3$4","ranges":[{"startOffset":1080195,"endOffset":1080250,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$2$4","ranges":[{"startOffset":1080284,"endOffset":1080339,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$1$4","ranges":[{"startOffset":1080373,"endOffset":1080428,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$3$6","ranges":[{"startOffset":1080462,"endOffset":1080529,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$2$5","ranges":[{"startOffset":1080563,"endOffset":1080624,"count":0}],"isBlockCoverage":false},{"functionName":"Function.call$2$0","ranges":[{"startOffset":1080658,"endOffset":1080693,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1080759,"endOffset":1081298,"count":1},{"startOffset":1080821,"endOffset":1080919,"count":0},{"startOffset":1080974,"endOffset":1081297,"count":0}],"isBlockCoverage":true},{"functionName":"onLoad","ranges":[{"startOffset":1081021,"endOffset":1081191,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1081300,"endOffset":1081476,"count":1},{"startOffset":1081418,"endOffset":1081445,"count":0}],"isBlockCoverage":true}]},{"scriptId":"32","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":284,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":283,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff_startsWith$20","ranges":[{"startOffset":82,"endOffset":281,"count":0}],"isBlockCoverage":false}]},{"scriptId":"33","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":271,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":270,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff__onPause$01","ranges":[{"startOffset":82,"endOffset":268,"count":0}],"isBlockCoverage":false}]},{"scriptId":"34","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":272,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":271,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff__onResume$02","ranges":[{"startOffset":82,"endOffset":269,"count":0}],"isBlockCoverage":false}]},{"scriptId":"35","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":277,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":276,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff_add$13","ranges":[{"startOffset":82,"endOffset":274,"count":0}],"isBlockCoverage":false}]},{"scriptId":"36","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":271,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":270,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff_addError$24","ranges":[{"startOffset":82,"endOffset":268,"count":0}],"isBlockCoverage":false}]},{"scriptId":"37","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":271,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":270,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff_complete$15","ranges":[{"startOffset":82,"endOffset":268,"count":1}],"isBlockCoverage":true}]},{"scriptId":"38","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":271,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":270,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff_complete$16","ranges":[{"startOffset":82,"endOffset":268,"count":1}],"isBlockCoverage":true}]},{"scriptId":"39","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":277,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":276,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff__completeError$27","ranges":[{"startOffset":82,"endOffset":274,"count":1}],"isBlockCoverage":true}]},{"scriptId":"40","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":277,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":276,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff_add$18","ranges":[{"startOffset":82,"endOffset":274,"count":1}],"isBlockCoverage":true}]},{"scriptId":"41","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":271,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":270,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff_addError$29","ranges":[{"startOffset":82,"endOffset":268,"count":1}],"isBlockCoverage":true}]},{"scriptId":"42","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":280,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":279,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff_close$010","ranges":[{"startOffset":82,"endOffset":277,"count":1}],"isBlockCoverage":true}]},{"scriptId":"43","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":268,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":267,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff__add$111","ranges":[{"startOffset":82,"endOffset":265,"count":1}],"isBlockCoverage":true}]},{"scriptId":"44","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":280,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":279,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff__async$_addError$212","ranges":[{"startOffset":82,"endOffset":277,"count":1}],"isBlockCoverage":true}]},{"scriptId":"45","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":270,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":269,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff__close$013","ranges":[{"startOffset":82,"endOffset":267,"count":1}],"isBlockCoverage":true}]},{"scriptId":"46","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":272,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":271,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff__onPause$014","ranges":[{"startOffset":82,"endOffset":269,"count":0}],"isBlockCoverage":false}]},{"scriptId":"47","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":273,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":272,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff__onResume$015","ranges":[{"startOffset":82,"endOffset":270,"count":1}],"isBlockCoverage":true}]},{"scriptId":"48","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":278,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":277,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff_add$116","ranges":[{"startOffset":82,"endOffset":275,"count":1}],"isBlockCoverage":true}]},{"scriptId":"49","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":272,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":271,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff__onPause$017","ranges":[{"startOffset":82,"endOffset":269,"count":0}],"isBlockCoverage":false}]},{"scriptId":"50","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":273,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":272,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff__onResume$018","ranges":[{"startOffset":82,"endOffset":270,"count":0}],"isBlockCoverage":false}]},{"scriptId":"51","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":273,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":272,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff__sendDone$019","ranges":[{"startOffset":82,"endOffset":270,"count":0}],"isBlockCoverage":false}]},{"scriptId":"52","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":283,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":282,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff_contains$120","ranges":[{"startOffset":82,"endOffset":280,"count":0}],"isBlockCoverage":false}]},{"scriptId":"53","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":280,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":279,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff_close$021","ranges":[{"startOffset":82,"endOffset":277,"count":0}],"isBlockCoverage":false}]},{"scriptId":"54","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":273,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":272,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff__onListen$022","ranges":[{"startOffset":82,"endOffset":270,"count":0}],"isBlockCoverage":false}]},{"scriptId":"55","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":282,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":281,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff__onCancelBroadcast$023","ranges":[{"startOffset":82,"endOffset":279,"count":0}],"isBlockCoverage":false}]},{"scriptId":"56","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":283,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":282,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff_contains$124","ranges":[{"startOffset":82,"endOffset":280,"count":0}],"isBlockCoverage":false}]},{"scriptId":"57","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":279,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":278,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff__recursiveMatch$425","ranges":[{"startOffset":82,"endOffset":276,"count":0}],"isBlockCoverage":false}]},{"scriptId":"58","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":288,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":287,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff_message$2$color26","ranges":[{"startOffset":82,"endOffset":285,"count":0}],"isBlockCoverage":false}]},{"scriptId":"59","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":309,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":308,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff__stack_zone_specification$_registerCallback$1$427","ranges":[{"startOffset":82,"endOffset":306,"count":1}],"isBlockCoverage":true}]},{"scriptId":"60","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":314,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":313,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff__stack_zone_specification$_registerUnaryCallback$2$428","ranges":[{"startOffset":82,"endOffset":311,"count":1}],"isBlockCoverage":true}]},{"scriptId":"61","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":315,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":314,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff__stack_zone_specification$_registerBinaryCallback$3$429","ranges":[{"startOffset":82,"endOffset":312,"count":1}],"isBlockCoverage":true}]},{"scriptId":"62","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":304,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":303,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff__stack_zone_specification$_errorCallback$530","ranges":[{"startOffset":82,"endOffset":301,"count":1}],"isBlockCoverage":true}]},{"scriptId":"63","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":272,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":271,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff_addError$231","ranges":[{"startOffset":82,"endOffset":269,"count":1}],"isBlockCoverage":true}]},{"scriptId":"64","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":273,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":272,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff__addError$232","ranges":[{"startOffset":82,"endOffset":270,"count":1}],"isBlockCoverage":true}]},{"scriptId":"65","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":280,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":279,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff_close$033","ranges":[{"startOffset":82,"endOffset":277,"count":0}],"isBlockCoverage":false}]},{"scriptId":"66","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":282,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":281,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff__closeInnerChannel$034","ranges":[{"startOffset":82,"endOffset":279,"count":1}],"isBlockCoverage":true}]},{"scriptId":"67","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":279,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":278,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff__invoker$_onRun$035","ranges":[{"startOffset":82,"endOffset":276,"count":1}],"isBlockCoverage":true}]},{"scriptId":"68","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":277,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":276,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff__runTearDowns$036","ranges":[{"startOffset":82,"endOffset":274,"count":1}],"isBlockCoverage":true}]},{"scriptId":"69","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":267,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":266,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff_run$037","ranges":[{"startOffset":82,"endOffset":264,"count":0}],"isBlockCoverage":false}]},{"scriptId":"70","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":282,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":281,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff_message$138","ranges":[{"startOffset":82,"endOffset":279,"count":0}],"isBlockCoverage":false}]},{"scriptId":"71","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":267,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":266,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff_run$039","ranges":[{"startOffset":82,"endOffset":264,"count":0}],"isBlockCoverage":false}]},{"scriptId":"72","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":278,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":277,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff__onTestStarted$140","ranges":[{"startOffset":82,"endOffset":275,"count":0}],"isBlockCoverage":false}]},{"scriptId":"73","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":281,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":280,"count":1}],"isBlockCoverage":true},{"functionName":"tearOff__expanded$_onDone$141","ranges":[{"startOffset":82,"endOffset":278,"count":0}],"isBlockCoverage":false}]},{"scriptId":"74","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":62,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":61,"count":1}],"isBlockCoverage":true}]},{"scriptId":"75","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":92,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":91,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":32,"endOffset":89,"count":1},{"startOffset":87,"endOffset":88,"count":0}],"isBlockCoverage":true}]},{"scriptId":"76","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":62,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":61,"count":1}],"isBlockCoverage":true}]},{"scriptId":"77","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":86,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":85,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":32,"endOffset":83,"count":0}],"isBlockCoverage":false}]},{"scriptId":"78","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":62,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":61,"count":1}],"isBlockCoverage":true}]},{"scriptId":"79","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":106,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":105,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":32,"endOffset":103,"count":0}],"isBlockCoverage":false}]},{"scriptId":"80","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":62,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":61,"count":1}],"isBlockCoverage":true}]},{"scriptId":"81","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":86,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":85,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":32,"endOffset":83,"count":0}],"isBlockCoverage":false}]},{"scriptId":"82","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":62,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":61,"count":1}],"isBlockCoverage":true}]},{"scriptId":"83","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":92,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":91,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":32,"endOffset":89,"count":0}],"isBlockCoverage":false}]},{"scriptId":"84","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":64,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":63,"count":1}],"isBlockCoverage":true}]},{"scriptId":"85","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":93,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":92,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":32,"endOffset":90,"count":1},{"startOffset":87,"endOffset":89,"count":0}],"isBlockCoverage":true}]},{"scriptId":"86","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":64,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":63,"count":1}],"isBlockCoverage":true}]},{"scriptId":"87","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":84,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":83,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":32,"endOffset":81,"count":0}],"isBlockCoverage":false}]},{"scriptId":"88","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":64,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":63,"count":1}],"isBlockCoverage":true}]},{"scriptId":"89","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":89,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":88,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":32,"endOffset":86,"count":0}],"isBlockCoverage":false}]},{"scriptId":"90","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":64,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":63,"count":1}],"isBlockCoverage":true}]},{"scriptId":"91","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":99,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":98,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":32,"endOffset":96,"count":1}],"isBlockCoverage":true}]},{"scriptId":"92","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":64,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":63,"count":1}],"isBlockCoverage":true}]},{"scriptId":"93","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":96,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":95,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":32,"endOffset":93,"count":0}],"isBlockCoverage":false}]},{"scriptId":"94","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":64,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":63,"count":1}],"isBlockCoverage":true}]},{"scriptId":"95","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":80,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":79,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":32,"endOffset":77,"count":1}],"isBlockCoverage":true}]},{"scriptId":"96","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":64,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":63,"count":1}],"isBlockCoverage":true}]},{"scriptId":"97","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":96,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":95,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":32,"endOffset":93,"count":0}],"isBlockCoverage":false}]},{"scriptId":"98","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":64,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":63,"count":1}],"isBlockCoverage":true}]},{"scriptId":"99","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":91,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":90,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":32,"endOffset":88,"count":1},{"startOffset":85,"endOffset":87,"count":0}],"isBlockCoverage":true}]},{"scriptId":"100","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":64,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":63,"count":1}],"isBlockCoverage":true}]},{"scriptId":"101","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":105,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":104,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":32,"endOffset":102,"count":1}],"isBlockCoverage":true}]},{"scriptId":"102","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":64,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":63,"count":1}],"isBlockCoverage":true}]},{"scriptId":"103","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":84,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":83,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":32,"endOffset":81,"count":0}],"isBlockCoverage":false}]},{"scriptId":"104","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":64,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":63,"count":1}],"isBlockCoverage":true}]},{"scriptId":"105","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":132,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":131,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":32,"endOffset":129,"count":0}],"isBlockCoverage":false}]},{"scriptId":"106","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":64,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":63,"count":1}],"isBlockCoverage":true}]},{"scriptId":"107","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":151,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":150,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":32,"endOffset":148,"count":1}],"isBlockCoverage":true}]},{"scriptId":"108","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":64,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":63,"count":1}],"isBlockCoverage":true}]},{"scriptId":"109","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":137,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":136,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":32,"endOffset":134,"count":1}],"isBlockCoverage":true}]},{"scriptId":"110","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":64,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":63,"count":1}],"isBlockCoverage":true}]},{"scriptId":"111","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":146,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":145,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":32,"endOffset":143,"count":1}],"isBlockCoverage":true}]},{"scriptId":"112","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":64,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":63,"count":1}],"isBlockCoverage":true}]},{"scriptId":"113","url":"","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":103,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1,"endOffset":102,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":32,"endOffset":100,"count":1}],"isBlockCoverage":true}]}] \ No newline at end of file
diff --git a/pkgs/coverage/test/test_files/function_coverage_app.dart b/pkgs/coverage/test/test_files/function_coverage_app.dart new file mode 100644 index 0000000..c4868f9 --- /dev/null +++ b/pkgs/coverage/test/test_files/function_coverage_app.dart
@@ -0,0 +1,58 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'test_library.dart'; + +int normalFunction() { + return 123; +} + +abstract class BaseClass { + int abstractMethod(); +} + +class SomeClass extends BaseClass { + SomeClass() : x = 123; + + // Creates an implicit getter and setter that should be ignored. + int x; + + int normalMethod() { + return 123; + } + + static int staticMethod() { + return 123; + } + + @override + int abstractMethod() { + return 123; + } +} + +extension SomeExtension on SomeClass { + int extensionMethod() { + return 123; + } +} + +class OtherClass { + int otherMethod() { + return 123; + } +} + +void main() { + print(normalFunction()); + print(SomeClass().normalMethod()); + print(SomeClass.staticMethod()); + print(SomeClass().extensionMethod()); + print(SomeClass().abstractMethod()); + print(OtherClass().otherMethod()); + print(libraryFunction()); + print(otherLibraryFunction()); +} + +// ignore_for_file: unreachable_from_main
diff --git a/pkgs/coverage/test/test_files/main_test.js b/pkgs/coverage/test/test_files/main_test.js new file mode 100644 index 0000000..4c4fb3e --- /dev/null +++ b/pkgs/coverage/test/test_files/main_test.js
@@ -0,0 +1,26570 @@ +// Generated by dart2js (fast startup emitter, strong), the Dart to JavaScript compiler version: 2.8.0-292505767. +// The code supports the following hooks: +// dartPrint(message): +// if this function is defined it is called instead of the Dart [print] +// method. +// +// dartMainRunner(main, args): +// if this function is defined, the Dart [main] method will not be invoked +// directly. Instead, a closure that will invoke [main], and its arguments +// [args] is passed to [dartMainRunner]. +// +// dartDeferredLibraryLoader(uri, successCallback, errorCallback): +// if this function is defined, it will be called when a deferred library +// is loaded. It should load and eval the javascript of `uri`, and call +// successCallback. If it fails to do so, it should call errorCallback with +// an error. +// +// dartCallInstrumentation(id, qualifiedName): +// if this function is defined, it will be called at each entry of a +// method or constructor. Used only when compiling programs with +// --experiment-call-instrumentation. +(function dartProgram() { + function copyProperties(from, to) { + var keys = Object.keys(from); + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + to[key] = from[key]; + } + } + var supportsDirectProtoAccess = function() { + var cls = function() { + }; + cls.prototype = {p: {}}; + var object = new cls(); + if (!(object.__proto__ && object.__proto__.p === cls.prototype.p)) + return false; + try { + if (typeof navigator != "undefined" && typeof navigator.userAgent == "string" && navigator.userAgent.indexOf("Chrome/") >= 0) + return true; + if (typeof version == "function" && version.length == 0) { + var v = version(); + if (/^\d+\.\d+\.\d+\.\d+$/.test(v)) + return true; + } + } catch (_) { + } + return false; + }(); + function setFunctionNamesIfNecessary(holders) { + function t() { + } + ; + if (typeof t.name == "string") + return; + for (var i = 0; i < holders.length; i++) { + var holder = holders[i]; + var keys = Object.keys(holder); + for (var j = 0; j < keys.length; j++) { + var key = keys[j]; + var f = holder[key]; + if (typeof f == 'function') + f.name = key; + } + } + } + function inherit(cls, sup) { + cls.prototype.constructor = cls; + cls.prototype["$is" + cls.name] = cls; + if (sup != null) { + if (supportsDirectProtoAccess) { + cls.prototype.__proto__ = sup.prototype; + return; + } + var clsPrototype = Object.create(sup.prototype); + copyProperties(cls.prototype, clsPrototype); + cls.prototype = clsPrototype; + } + } + function inheritMany(sup, classes) { + for (var i = 0; i < classes.length; i++) + inherit(classes[i], sup); + } + function mixin(cls, mixin) { + copyProperties(mixin.prototype, cls.prototype); + cls.prototype.constructor = cls; + } + function lazy(holder, name, getterName, initializer) { + var uninitializedSentinel = holder; + holder[name] = uninitializedSentinel; + holder[getterName] = function() { + holder[getterName] = function() { + H.throwCyclicInit(name); + }; + var result; + var sentinelInProgress = initializer; + try { + if (holder[name] === uninitializedSentinel) { + result = holder[name] = sentinelInProgress; + result = holder[name] = initializer(); + } else + result = holder[name]; + } finally { + if (result === sentinelInProgress) + holder[name] = null; + holder[getterName] = function() { + return this[name]; + }; + } + return result; + }; + } + function makeConstList(list) { + list.immutable$list = Array; + list.fixed$length = Array; + return list; + } + function convertToFastObject(properties) { + function t() { + } + t.prototype = properties; + new t(); + return properties; + } + function convertAllToFastObject(arrayOfObjects) { + for (var i = 0; i < arrayOfObjects.length; ++i) + convertToFastObject(arrayOfObjects[i]); + } + var functionCounter = 0; + function tearOffGetter(funcs, applyTrampolineIndex, reflectionInfo, name, isIntercepted) { + return isIntercepted ? new Function("funcs", "applyTrampolineIndex", "reflectionInfo", "name", "H", "c", "return function tearOff_" + name + functionCounter++ + "(receiver) {" + "if (c === null) c = " + "H.closureFromTearOff" + "(" + "this, funcs, applyTrampolineIndex, reflectionInfo, false, true, name);" + "return new c(this, funcs[0], receiver, name);" + "}")(funcs, applyTrampolineIndex, reflectionInfo, name, H, null) : new Function("funcs", "applyTrampolineIndex", "reflectionInfo", "name", "H", "c", "return function tearOff_" + name + functionCounter++ + "() {" + "if (c === null) c = " + "H.closureFromTearOff" + "(" + "this, funcs, applyTrampolineIndex, reflectionInfo, false, false, name);" + "return new c(this, funcs[0], null, name);" + "}")(funcs, applyTrampolineIndex, reflectionInfo, name, H, null); + } + function tearOff(funcs, applyTrampolineIndex, reflectionInfo, isStatic, name, isIntercepted) { + var cache = null; + return isStatic ? function() { + if (cache === null) + cache = H.closureFromTearOff(this, funcs, applyTrampolineIndex, reflectionInfo, true, false, name).prototype; + return cache; + } : tearOffGetter(funcs, applyTrampolineIndex, reflectionInfo, name, isIntercepted); + } + var typesOffset = 0; + function installTearOff(container, getterName, isStatic, isIntercepted, requiredParameterCount, optionalParameterDefaultValues, callNames, funsOrNames, funType, applyIndex) { + var funs = []; + for (var i = 0; i < funsOrNames.length; i++) { + var fun = funsOrNames[i]; + if (typeof fun == 'string') + fun = container[fun]; + fun.$callName = callNames[i]; + funs.push(fun); + } + var fun = funs[0]; + fun.$requiredArgCount = requiredParameterCount; + fun.$defaultValues = optionalParameterDefaultValues; + var reflectionInfo = funType; + if (typeof reflectionInfo == "number") + reflectionInfo += typesOffset; + var name = funsOrNames[0]; + fun.$stubName = name; + var getterFunction = tearOff(funs, applyIndex || 0, reflectionInfo, isStatic, name, isIntercepted); + container[getterName] = getterFunction; + if (isStatic) + fun.$tearOff = getterFunction; + } + function installStaticTearOff(container, getterName, requiredParameterCount, optionalParameterDefaultValues, callNames, funsOrNames, funType, applyIndex) { + return installTearOff(container, getterName, true, false, requiredParameterCount, optionalParameterDefaultValues, callNames, funsOrNames, funType, applyIndex); + } + function installInstanceTearOff(container, getterName, isIntercepted, requiredParameterCount, optionalParameterDefaultValues, callNames, funsOrNames, funType, applyIndex) { + return installTearOff(container, getterName, false, isIntercepted, requiredParameterCount, optionalParameterDefaultValues, callNames, funsOrNames, funType, applyIndex); + } + function setOrUpdateInterceptorsByTag(newTags) { + var tags = init.interceptorsByTag; + if (!tags) { + init.interceptorsByTag = newTags; + return; + } + copyProperties(newTags, tags); + } + function setOrUpdateLeafTags(newTags) { + var tags = init.leafTags; + if (!tags) { + init.leafTags = newTags; + return; + } + copyProperties(newTags, tags); + } + function updateTypes(newTypes) { + var types = init.types; + var length = types.length; + types.push.apply(types, newTypes); + return length; + } + function updateHolder(holder, newHolder) { + copyProperties(newHolder, holder); + return holder; + } + var hunkHelpers = function() { + var mkInstance = function(isIntercepted, requiredParameterCount, optionalParameterDefaultValues, callNames, applyIndex) { + return function(container, getterName, name, funType) { + return installInstanceTearOff(container, getterName, isIntercepted, requiredParameterCount, optionalParameterDefaultValues, callNames, [name], funType, applyIndex); + }; + }, + mkStatic = function(requiredParameterCount, optionalParameterDefaultValues, callNames, applyIndex) { + return function(container, getterName, name, funType) { + return installStaticTearOff(container, getterName, requiredParameterCount, optionalParameterDefaultValues, callNames, [name], funType, applyIndex); + }; + }; + return {inherit: inherit, inheritMany: inheritMany, mixin: mixin, installStaticTearOff: installStaticTearOff, installInstanceTearOff: installInstanceTearOff, _instance_0u: mkInstance(0, 0, null, ["call$0"], 0), _instance_1u: mkInstance(0, 1, null, ["call$1"], 0), _instance_2u: mkInstance(0, 2, null, ["call$2"], 0), _instance_0i: mkInstance(1, 0, null, ["call$0"], 0), _instance_1i: mkInstance(1, 1, null, ["call$1"], 0), _instance_2i: mkInstance(1, 2, null, ["call$2"], 0), _static_0: mkStatic(0, null, ["call$0"], 0), _static_1: mkStatic(1, null, ["call$1"], 0), _static_2: mkStatic(2, null, ["call$2"], 0), makeConstList: makeConstList, lazy: lazy, updateHolder: updateHolder, convertToFastObject: convertToFastObject, setFunctionNamesIfNecessary: setFunctionNamesIfNecessary, updateTypes: updateTypes, setOrUpdateInterceptorsByTag: setOrUpdateInterceptorsByTag, setOrUpdateLeafTags: setOrUpdateLeafTags}; + }(); + function initializeDeferredHunk(hunk) { + typesOffset = init.types.length; + hunk(hunkHelpers, init, holders, $); + } + function getGlobalFromName(name) { + for (var i = 0; i < holders.length; i++) { + if (holders[i] == C) + continue; + if (holders[i][name]) + return holders[i][name]; + } + } + var C = {}, + H = {JS_CONST: function JS_CONST() { + }, + CastIterable_CastIterable: function(source, $S, $T) { + if ($S._eval$1("EfficientLengthIterable<0>")._is(source)) + return new H._EfficientLengthCastIterable(source, $S._eval$1("@<0>")._bind$1($T)._eval$1("_EfficientLengthCastIterable<1,2>")); + return new H.CastIterable(source, $S._eval$1("@<0>")._bind$1($T)._eval$1("CastIterable<1,2>")); + }, + hexDigitValue: function(char) { + var digit, letter; + H.assertHelper(char <= 65535); + digit = char ^ 48; + if (digit <= 9) + return digit; + letter = char | 32; + if (97 <= letter && letter <= 102) + return letter - 87; + return -1; + }, + SubListIterable$: function(_iterable, _start, _endOrLength, $E) { + P.RangeError_checkNotNegative(_start, "start"); + if (_endOrLength != null) { + P.RangeError_checkNotNegative(_endOrLength, "end"); + if (_start > _endOrLength) + H.throwExpression(P.RangeError$range(_start, 0, _endOrLength, "start", null)); + } + return new H.SubListIterable(_iterable, _start, _endOrLength, $E._eval$1("SubListIterable<0>")); + }, + MappedIterable_MappedIterable: function(iterable, $function, $S, $T) { + if (type$.EfficientLengthIterable_dynamic._is(iterable)) + return new H.EfficientLengthMappedIterable(iterable, $function, $S._eval$1("@<0>")._bind$1($T)._eval$1("EfficientLengthMappedIterable<1,2>")); + return new H.MappedIterable(iterable, $function, $S._eval$1("@<0>")._bind$1($T)._eval$1("MappedIterable<1,2>")); + }, + IterableElementError_noElement: function() { + return new P.StateError("No element"); + }, + IterableElementError_tooMany: function() { + return new P.StateError("Too many elements"); + }, + IterableElementError_tooFew: function() { + return new P.StateError("Too few elements"); + }, + _CastIterableBase: function _CastIterableBase() { + }, + CastIterator: function CastIterator(t0, t1) { + this._source = t0; + this.$ti = t1; + }, + CastIterable: function CastIterable(t0, t1) { + this._source = t0; + this.$ti = t1; + }, + _EfficientLengthCastIterable: function _EfficientLengthCastIterable(t0, t1) { + this._source = t0; + this.$ti = t1; + }, + CastMap: function CastMap(t0, t1) { + this._source = t0; + this.$ti = t1; + }, + CastMap_forEach_closure: function CastMap_forEach_closure(t0, t1) { + this.$this = t0; + this.f = t1; + }, + CodeUnits: function CodeUnits(t0) { + this._string = t0; + }, + EfficientLengthIterable: function EfficientLengthIterable() { + }, + ListIterable: function ListIterable() { + }, + SubListIterable: function SubListIterable(t0, t1, t2, t3) { + var _ = this; + _.__internal$_iterable = t0; + _.__internal$_start = t1; + _._endOrLength = t2; + _.$ti = t3; + }, + ListIterator: function ListIterator(t0, t1, t2) { + var _ = this; + _.__internal$_iterable = t0; + _.__internal$_length = t1; + _.__internal$_index = 0; + _.__internal$_current = null; + _.$ti = t2; + }, + MappedIterable: function MappedIterable(t0, t1, t2) { + this.__internal$_iterable = t0; + this._f = t1; + this.$ti = t2; + }, + EfficientLengthMappedIterable: function EfficientLengthMappedIterable(t0, t1, t2) { + this.__internal$_iterable = t0; + this._f = t1; + this.$ti = t2; + }, + MappedIterator: function MappedIterator(t0, t1, t2) { + var _ = this; + _.__internal$_current = null; + _._iterator = t0; + _._f = t1; + _.$ti = t2; + }, + MappedListIterable: function MappedListIterable(t0, t1, t2) { + this._source = t0; + this._f = t1; + this.$ti = t2; + }, + WhereIterable: function WhereIterable(t0, t1, t2) { + this.__internal$_iterable = t0; + this._f = t1; + this.$ti = t2; + }, + WhereIterator: function WhereIterator(t0, t1, t2) { + this._iterator = t0; + this._f = t1; + this.$ti = t2; + }, + ExpandIterable: function ExpandIterable(t0, t1, t2) { + this.__internal$_iterable = t0; + this._f = t1; + this.$ti = t2; + }, + ExpandIterator: function ExpandIterator(t0, t1, t2, t3) { + var _ = this; + _._iterator = t0; + _._f = t1; + _._currentExpansion = t2; + _.__internal$_current = null; + _.$ti = t3; + }, + SkipWhileIterable: function SkipWhileIterable(t0, t1, t2) { + this.__internal$_iterable = t0; + this._f = t1; + this.$ti = t2; + }, + SkipWhileIterator: function SkipWhileIterator(t0, t1, t2) { + var _ = this; + _._iterator = t0; + _._f = t1; + _._hasSkipped = false; + _.$ti = t2; + }, + EmptyIterator: function EmptyIterator(t0) { + this.$ti = t0; + }, + FixedLengthListMixin: function FixedLengthListMixin() { + }, + UnmodifiableListMixin: function UnmodifiableListMixin() { + }, + UnmodifiableListBase: function UnmodifiableListBase() { + }, + ReversedListIterable: function ReversedListIterable(t0, t1) { + this._source = t0; + this.$ti = t1; + }, + Symbol: function Symbol(t0) { + this.__internal$_name = t0; + }, + ConstantMap__throwUnmodifiable: function() { + throw H.wrapException(P.UnsupportedError$("Cannot modify unmodifiable Map")); + }, + instantiate1: function(f, T1) { + var t1 = new H.Instantiation1(f, T1._eval$1("Instantiation1<0>")); + t1.Instantiation$1(f); + return t1; + }, + unminifyOrTag: function(rawClassName) { + var preserved = H.unmangleGlobalNameIfPreservedAnyways(rawClassName); + if (typeof preserved == "string") + return preserved; + return rawClassName; + }, + isJsIndexable: function(object, record) { + var result; + if (record != null) { + result = record.x; + if (result != null) + return result; + } + return type$.JavaScriptIndexingBehavior_dynamic._is(object); + }, + S: function(value) { + var res; + if (typeof value == "string") + return value; + if (typeof value == "number") { + if (value !== 0) + return "" + value; + } else if (true === value) + return "true"; + else if (false === value) + return "false"; + else if (value == null) + return "null"; + res = J.toString$0$(value); + if (typeof res != "string") + throw H.wrapException(H.argumentErrorValue(value)); + return res; + }, + Primitives_objectHashCode: function(object) { + var hash = object.$identityHash; + if (hash == null) { + hash = Math.random() * 0x3fffffff | 0; + object.$identityHash = hash; + } + return hash; + }, + Primitives_parseInt: function(source, radix) { + var match, decimalMatch, maxCharCode, digitsPart, t1, i, _null = null; + if (typeof source != "string") + H.throwExpression(H.argumentErrorValue(source)); + match = /^\s*[+-]?((0x[a-f0-9]+)|(\d+)|([a-z0-9]+))\s*$/i.exec(source); + if (match == null) + return _null; + if (3 >= match.length) + return H.ioore(match, 3); + decimalMatch = H._checkStringNullable(match[3]); + if (radix == null) { + if (decimalMatch != null) + return parseInt(source, 10); + if (match[2] != null) + return parseInt(source, 16); + return _null; + } + if (radix < 2 || radix > 36) + throw H.wrapException(P.RangeError$range(radix, 2, 36, "radix", _null)); + if (radix === 10 && decimalMatch != null) + return parseInt(source, 10); + if (radix < 10 || decimalMatch == null) { + maxCharCode = radix <= 10 ? 47 + radix : 86 + radix; + H.assertHelper(typeof match[1] == "string"); + digitsPart = match[1]; + for (t1 = digitsPart.length, i = 0; i < t1; ++i) + if ((C.JSString_methods._codeUnitAt$1(digitsPart, i) | 32) > maxCharCode) + return _null; + } + return parseInt(source, radix); + }, + Primitives_objectTypeName: function(object) { + var t1 = H.Primitives__objectTypeNameNewRti(object); + return t1; + }, + Primitives__objectTypeNameNewRti: function(object) { + var dispatchName, $constructor, constructorName; + if (object instanceof P.Object) + return H._rtiToString(H.instanceType(object), null); + if (J.getInterceptor$(object) === C.Interceptor_methods || type$.UnknownJavaScriptObject._is(object)) { + dispatchName = C.C_JS_CONST(object); + if (H.Primitives__saneNativeClassName(dispatchName)) + return dispatchName; + $constructor = object.constructor; + if (typeof $constructor == "function") { + constructorName = $constructor.name; + if (typeof constructorName == "string" && H.Primitives__saneNativeClassName(constructorName)) + return constructorName; + } + } + return H._rtiToString(H.instanceType(object), null); + }, + Primitives__saneNativeClassName: function($name) { + var t1 = $name !== "Object" && $name !== ""; + return t1; + }, + Primitives_dateNow: function() { + return Date.now(); + }, + Primitives_initTicker: function() { + var $window, performance; + if ($.Primitives_timerFrequency != null) + return; + $.Primitives_timerFrequency = 1000; + $.Primitives_timerTicks = H._js_helper_Primitives_dateNow$closure(); + if (typeof window == "undefined") + return; + $window = window; + if ($window == null) + return; + performance = $window.performance; + if (performance == null) + return; + if (typeof performance.now != "function") + return; + $.Primitives_timerFrequency = 1000000; + $.Primitives_timerTicks = new H.Primitives_initTicker_closure(performance); + }, + Primitives_currentUri: function() { + if (!!self.location) + return self.location.href; + return null; + }, + Primitives__fromCharCodeApply: function(array) { + var result, i, i0, chunkEnd, + end = J.get$length$asx(array); + if (end <= 500) + return String.fromCharCode.apply(null, array); + for (result = "", i = 0; i < end; i = i0) { + i0 = i + 500; + chunkEnd = i0 < end ? i0 : end; + result += String.fromCharCode.apply(null, array.slice(i, chunkEnd)); + } + return result; + }, + Primitives_stringFromCodePoints: function(codePoints) { + var t1, i, + a = H.setRuntimeTypeInfo([], type$.JSArray_int); + for (t1 = J.get$iterator$ax(type$.Iterable_dynamic._check(codePoints)); t1.moveNext$0();) { + i = t1.get$current(); + if (!H._isInt(i)) + throw H.wrapException(H.argumentErrorValue(i)); + if (i <= 65535) + C.JSArray_methods.add$1(a, i); + else if (i <= 1114111) { + C.JSArray_methods.add$1(a, 55296 + (C.JSInt_methods._shrOtherPositive$1(i - 65536, 10) & 1023)); + C.JSArray_methods.add$1(a, 56320 + (i & 1023)); + } else + throw H.wrapException(H.argumentErrorValue(i)); + } + return H.Primitives__fromCharCodeApply(a); + }, + Primitives_stringFromCharCodes: function(charCodes) { + var t1, i; + for (type$.Iterable_dynamic._check(charCodes), t1 = J.get$iterator$ax(charCodes); t1.moveNext$0();) { + i = t1.get$current(); + if (!H._isInt(i)) + throw H.wrapException(H.argumentErrorValue(i)); + if (i < 0) + throw H.wrapException(H.argumentErrorValue(i)); + if (i > 65535) + return H.Primitives_stringFromCodePoints(charCodes); + } + return H.Primitives__fromCharCodeApply(type$.List_dynamic._check(charCodes)); + }, + Primitives_stringFromNativeUint8List: function(charCodes, start, end) { + var i, result, i0, chunkEnd; + if (end <= 500 && start === 0 && end === charCodes.length) + return String.fromCharCode.apply(null, charCodes); + for (i = start, result = ""; i < end; i = i0) { + i0 = i + 500; + chunkEnd = i0 < end ? i0 : end; + result += String.fromCharCode.apply(null, charCodes.subarray(i, chunkEnd)); + } + return result; + }, + Primitives_stringFromCharCode: function(charCode) { + var bits; + if (typeof charCode !== "number") + return H.iae(charCode); + if (0 <= charCode) { + if (charCode <= 65535) + return String.fromCharCode(charCode); + if (charCode <= 1114111) { + bits = charCode - 65536; + return String.fromCharCode((55296 | C.JSInt_methods._shrOtherPositive$1(bits, 10)) >>> 0, 56320 | bits & 1023); + } + } + throw H.wrapException(P.RangeError$range(charCode, 0, 1114111, null, null)); + }, + Primitives_lazyAsJsDate: function(receiver) { + if (receiver.date === void 0) + receiver.date = new Date(receiver._value); + return receiver.date; + }, + Primitives_getYear: function(receiver) { + var t1 = H.Primitives_lazyAsJsDate(receiver).getUTCFullYear() + 0; + return t1; + }, + Primitives_getMonth: function(receiver) { + var t1 = H.Primitives_lazyAsJsDate(receiver).getUTCMonth() + 1; + return t1; + }, + Primitives_getDay: function(receiver) { + var t1 = H.Primitives_lazyAsJsDate(receiver).getUTCDate() + 0; + return t1; + }, + Primitives_getHours: function(receiver) { + var t1 = H.Primitives_lazyAsJsDate(receiver).getUTCHours() + 0; + return t1; + }, + Primitives_getMinutes: function(receiver) { + var t1 = H.Primitives_lazyAsJsDate(receiver).getUTCMinutes() + 0; + return t1; + }, + Primitives_getSeconds: function(receiver) { + var t1 = H.Primitives_lazyAsJsDate(receiver).getUTCSeconds() + 0; + return t1; + }, + Primitives_getMilliseconds: function(receiver) { + var t1 = H.Primitives_lazyAsJsDate(receiver).getUTCMilliseconds() + 0; + return t1; + }, + Primitives_getProperty: function(object, key) { + if (object == null || H._isBool(object) || typeof object == "number" || typeof object == "string") + throw H.wrapException(H.argumentErrorValue(object)); + return object[key]; + }, + Primitives_setProperty: function(object, key, value) { + if (object == null || H._isBool(object) || typeof object == "number" || typeof object == "string") + throw H.wrapException(H.argumentErrorValue(object)); + object[key] = value; + }, + iae: function(argument) { + throw H.wrapException(H.argumentErrorValue(argument)); + }, + ioore: function(receiver, index) { + if (receiver == null) + J.get$length$asx(receiver); + throw H.wrapException(H.diagnoseIndexError(receiver, index)); + }, + diagnoseIndexError: function(indexable, index) { + var $length, t1, _s5_ = "index"; + if (!H._isInt(index)) + return new P.ArgumentError(true, index, _s5_, null); + $length = H._checkIntNullable(J.get$length$asx(indexable)); + if (!(index < 0)) { + if (typeof $length !== "number") + return H.iae($length); + t1 = index >= $length; + } else + t1 = true; + if (t1) + return P.IndexError$(index, indexable, _s5_, null, $length); + return P.RangeError$value(index, _s5_); + }, + diagnoseRangeError: function(start, end, $length) { + var _s13_ = "Invalid value"; + if (start < 0 || start > $length) + return new P.RangeError(0, $length, true, start, "start", _s13_); + if (end != null) + if (end < start || end > $length) + return new P.RangeError(start, $length, true, end, "end", _s13_); + return new P.ArgumentError(true, end, "end", null); + }, + argumentErrorValue: function(object) { + return new P.ArgumentError(true, object, null, null); + }, + checkNum: function(value) { + if (typeof value != "number") + throw H.wrapException(H.argumentErrorValue(value)); + return value; + }, + wrapException: function(ex) { + var wrapper; + if (ex == null) + ex = new P.NullThrownError(); + wrapper = new Error(); + wrapper.dartException = ex; + if ("defineProperty" in Object) { + Object.defineProperty(wrapper, "message", {get: H.toStringWrapper}); + wrapper.name = ""; + } else + wrapper.toString = H.toStringWrapper; + return wrapper; + }, + toStringWrapper: function() { + return J.toString$0$(this.dartException); + }, + throwExpression: function(ex) { + throw H.wrapException(ex); + }, + throwConcurrentModificationError: function(collection) { + throw H.wrapException(P.ConcurrentModificationError$(collection)); + }, + TypeErrorDecoder_extractPattern: function(message) { + var match, $arguments, argumentsExpr, expr, method, receiver; + message = H.quoteStringForRegExp(message.replace(String({}), '$receiver$')); + match = message.match(/\\\$[a-zA-Z]+\\\$/g); + if (match == null) + match = H.setRuntimeTypeInfo([], type$.JSArray_String); + $arguments = match.indexOf("\\$arguments\\$"); + argumentsExpr = match.indexOf("\\$argumentsExpr\\$"); + expr = match.indexOf("\\$expr\\$"); + method = match.indexOf("\\$method\\$"); + receiver = match.indexOf("\\$receiver\\$"); + return new H.TypeErrorDecoder(message.replace(new RegExp('\\\\\\$arguments\\\\\\$', 'g'), '((?:x|[^x])*)').replace(new RegExp('\\\\\\$argumentsExpr\\\\\\$', 'g'), '((?:x|[^x])*)').replace(new RegExp('\\\\\\$expr\\\\\\$', 'g'), '((?:x|[^x])*)').replace(new RegExp('\\\\\\$method\\\\\\$', 'g'), '((?:x|[^x])*)').replace(new RegExp('\\\\\\$receiver\\\\\\$', 'g'), '((?:x|[^x])*)'), $arguments, argumentsExpr, expr, method, receiver); + }, + TypeErrorDecoder_provokeCallErrorOn: function(expression) { + return function($expr$) { + var $argumentsExpr$ = '$arguments$'; + try { + $expr$.$method$($argumentsExpr$); + } catch (e) { + return e.message; + } + }(expression); + }, + TypeErrorDecoder_provokePropertyErrorOn: function(expression) { + return function($expr$) { + try { + $expr$.$method$; + } catch (e) { + return e.message; + } + }(expression); + }, + NullError$: function(_message, match) { + return new H.NullError(_message, match == null ? null : match.method); + }, + JsNoSuchMethodError$: function(_message, match) { + var t1 = match == null, + t2 = t1 ? null : match.method; + return new H.JsNoSuchMethodError(_message, t2, t1 ? null : match.receiver); + }, + unwrapException: function(ex) { + var message, number, ieErrorCode, nsme, notClosure, nullCall, nullLiteralCall, undefCall, undefLiteralCall, nullProperty, undefProperty, undefLiteralProperty, match, t2, _null = null, + t1 = new H.unwrapException_saveStackTrace(ex); + if (ex == null) + return _null; + if (ex instanceof H.ExceptionAndStackTrace) + return t1.call$1(ex.dartException); + if (typeof ex !== "object") + return ex; + if ("dartException" in ex) + return t1.call$1(ex.dartException); + else if (!("message" in ex)) + return ex; + message = ex.message; + if ("number" in ex && typeof ex.number == "number") { + number = ex.number; + ieErrorCode = number & 65535; + if ((C.JSInt_methods._shrOtherPositive$1(number, 16) & 8191) === 10) + switch (ieErrorCode) { + case 438: + return t1.call$1(H.JsNoSuchMethodError$(H.S(message) + " (Error " + ieErrorCode + ")", _null)); + case 445: + case 5007: + return t1.call$1(H.NullError$(H.S(message) + " (Error " + ieErrorCode + ")", _null)); + } + } + if (ex instanceof TypeError) { + nsme = $.$get$TypeErrorDecoder_noSuchMethodPattern(); + notClosure = $.$get$TypeErrorDecoder_notClosurePattern(); + nullCall = $.$get$TypeErrorDecoder_nullCallPattern(); + nullLiteralCall = $.$get$TypeErrorDecoder_nullLiteralCallPattern(); + undefCall = $.$get$TypeErrorDecoder_undefinedCallPattern(); + undefLiteralCall = $.$get$TypeErrorDecoder_undefinedLiteralCallPattern(); + nullProperty = $.$get$TypeErrorDecoder_nullPropertyPattern(); + $.$get$TypeErrorDecoder_nullLiteralPropertyPattern(); + undefProperty = $.$get$TypeErrorDecoder_undefinedPropertyPattern(); + undefLiteralProperty = $.$get$TypeErrorDecoder_undefinedLiteralPropertyPattern(); + match = nsme.matchTypeError$1(message); + if (match != null) + return t1.call$1(H.JsNoSuchMethodError$(H._checkStringNullable(message), match)); + else { + match = notClosure.matchTypeError$1(message); + if (match != null) { + match.method = "call"; + return t1.call$1(H.JsNoSuchMethodError$(H._checkStringNullable(message), match)); + } else { + match = nullCall.matchTypeError$1(message); + if (match == null) { + match = nullLiteralCall.matchTypeError$1(message); + if (match == null) { + match = undefCall.matchTypeError$1(message); + if (match == null) { + match = undefLiteralCall.matchTypeError$1(message); + if (match == null) { + match = nullProperty.matchTypeError$1(message); + if (match == null) { + match = nullLiteralCall.matchTypeError$1(message); + if (match == null) { + match = undefProperty.matchTypeError$1(message); + if (match == null) { + match = undefLiteralProperty.matchTypeError$1(message); + t2 = match != null; + } else + t2 = true; + } else + t2 = true; + } else + t2 = true; + } else + t2 = true; + } else + t2 = true; + } else + t2 = true; + } else + t2 = true; + if (t2) + return t1.call$1(H.NullError$(H._checkStringNullable(message), match)); + } + } + return t1.call$1(new H.UnknownJsTypeError(typeof message == "string" ? message : "")); + } + if (ex instanceof RangeError) { + if (typeof message == "string" && message.indexOf("call stack") !== -1) + return new P.StackOverflowError(); + message = function(ex) { + try { + return String(ex); + } catch (e) { + } + return null; + }(ex); + return t1.call$1(new P.ArgumentError(false, _null, _null, typeof message == "string" ? message.replace(/^RangeError:\s*/, "") : message)); + } + if (typeof InternalError == "function" && ex instanceof InternalError) + if (typeof message == "string" && message === "too much recursion") + return new P.StackOverflowError(); + return ex; + }, + getTraceFromException: function(exception) { + var trace; + if (exception instanceof H.ExceptionAndStackTrace) + return exception.stackTrace; + if (exception == null) + return new H._StackTrace(exception); + trace = exception.$cachedTrace; + if (trace != null) + return trace; + return exception.$cachedTrace = new H._StackTrace(exception); + }, + objectHashCode: function(object) { + if (object == null || typeof object != 'object') + return J.get$hashCode$(object); + else + return H.Primitives_objectHashCode(object); + }, + fillLiteralMap: function(keyValuePairs, result) { + var $length, index, index0, key, + t1 = Array.isArray(keyValuePairs); + H.assertHelper(t1); + $length = keyValuePairs.length; + for (index = 0; index < $length;) { + index0 = index + 1; + H.assertHelper(t1); + key = keyValuePairs[index]; + index = index0 + 1; + H.assertHelper(t1); + result.$indexSet(0, key, keyValuePairs[index0]); + } + return result; + }, + fillLiteralSet: function(values, result) { + var $length, index, + t1 = Array.isArray(values); + H.assertHelper(t1); + $length = values.length; + for (index = 0; index < $length; ++index) { + H.assertHelper(t1); + result.add$1(0, values[index]); + } + return result; + }, + invokeClosure: function(closure, numberOfArguments, arg1, arg2, arg3, arg4) { + type$.Function._check(closure); + switch (H._checkIntNullable(numberOfArguments)) { + case 0: + return closure.call$0(); + case 1: + return closure.call$1(arg1); + case 2: + return closure.call$2(arg1, arg2); + case 3: + return closure.call$3(arg1, arg2, arg3); + case 4: + return closure.call$4(arg1, arg2, arg3, arg4); + } + throw H.wrapException(new P._Exception("Unsupported number of arguments for wrapped closure")); + }, + convertDartClosureToJS: function(closure, arity) { + var $function; + if (closure == null) + return null; + $function = closure.$identity; + if (!!$function) + return $function; + $function = function(closure, arity, invoke) { + return function(a1, a2, a3, a4) { + return invoke(closure, arity, a1, a2, a3, a4); + }; + }(closure, arity, H.invokeClosure); + closure.$identity = $function; + return $function; + }, + Closure_fromTearOff: function(receiver, functions, applyTrampolineIndex, reflectionInfo, isStatic, isIntercepted, propertyName) { + var $constructor, t1, trampoline, signatureFunction, applyTrampoline, i, stub, stubCallName, _null = null, + $function = functions[0], + callName = $function.$callName, + $prototype = isStatic ? Object.create(new H.StaticClosure().constructor.prototype) : Object.create(new H.BoundClosure(_null, _null, _null, _null).constructor.prototype); + $prototype.$initialize = $prototype.constructor; + if (isStatic) + $constructor = function static_tear_off() { + this.$initialize(); + }; + else { + t1 = $.Closure_functionCounter; + if (typeof t1 !== "number") + return t1.$add(); + $.Closure_functionCounter = t1 + 1; + t1 = new Function("a,b,c,d" + t1, "this.$initialize(a,b,c,d" + t1 + ")"); + $constructor = t1; + } + $prototype.constructor = $constructor; + $constructor.prototype = $prototype; + if (!isStatic) { + trampoline = H.Closure_forwardCallTo(receiver, $function, isIntercepted); + trampoline.$reflectionInfo = reflectionInfo; + } else { + $prototype.$static_name = propertyName; + trampoline = $function; + } + signatureFunction = H.Closure__computeSignatureFunctionNewRti(reflectionInfo, isStatic, isIntercepted); + $prototype.$signature = signatureFunction; + $prototype[callName] = trampoline; + for (applyTrampoline = trampoline, i = 1; i < functions.length; ++i) { + stub = functions[i]; + stubCallName = stub.$callName; + if (stubCallName != null) { + stub = isStatic ? stub : H.Closure_forwardCallTo(receiver, stub, isIntercepted); + $prototype[stubCallName] = stub; + } + if (i === applyTrampolineIndex) { + stub.$reflectionInfo = reflectionInfo; + applyTrampoline = stub; + } + } + $prototype["call*"] = applyTrampoline; + $prototype.$requiredArgCount = $function.$requiredArgCount; + $prototype.$defaultValues = $function.$defaultValues; + return $constructor; + }, + Closure__computeSignatureFunctionNewRti: function(functionType, isStatic, isIntercepted) { + var typeEvalMethod; + if (typeof functionType == "number") + return function(getType, t) { + return function() { + return getType(t); + }; + }(H.getTypeFromTypesTable, functionType); + if (typeof functionType == "string") { + if (isStatic) + throw H.wrapException("Cannot compute signature for static tearoff."); + typeEvalMethod = isIntercepted ? H.BoundClosure_evalRecipeIntercepted : H.BoundClosure_evalRecipe; + return function(recipe, evalOnReceiver) { + return function() { + return evalOnReceiver(this, recipe); + }; + }(functionType, typeEvalMethod); + } + throw H.wrapException("Error in functionType of tearoff"); + }, + Closure_cspForwardCall: function(arity, isSuperCall, stubName, $function) { + var getSelf = H.BoundClosure_selfOf; + switch (isSuperCall ? -1 : arity) { + case 0: + return function(n, S) { + return function() { + return S(this)[n](); + }; + }(stubName, getSelf); + case 1: + return function(n, S) { + return function(a) { + return S(this)[n](a); + }; + }(stubName, getSelf); + case 2: + return function(n, S) { + return function(a, b) { + return S(this)[n](a, b); + }; + }(stubName, getSelf); + case 3: + return function(n, S) { + return function(a, b, c) { + return S(this)[n](a, b, c); + }; + }(stubName, getSelf); + case 4: + return function(n, S) { + return function(a, b, c, d) { + return S(this)[n](a, b, c, d); + }; + }(stubName, getSelf); + case 5: + return function(n, S) { + return function(a, b, c, d, e) { + return S(this)[n](a, b, c, d, e); + }; + }(stubName, getSelf); + default: + return function(f, s) { + return function() { + return f.apply(s(this), arguments); + }; + }($function, getSelf); + } + }, + Closure_forwardCallTo: function(receiver, $function, isIntercepted) { + var stubName, arity, lookedUpFunction, t1, t2, selfName, $arguments; + if (isIntercepted) + return H.Closure_forwardInterceptedCallTo(receiver, $function); + stubName = $function.$stubName; + arity = $function.length; + lookedUpFunction = receiver[stubName]; + t1 = $function == null ? lookedUpFunction == null : $function === lookedUpFunction; + t2 = !t1 || arity >= 27; + if (t2) + return H.Closure_cspForwardCall(arity, !t1, stubName, $function); + if (arity === 0) { + t1 = $.Closure_functionCounter; + if (typeof t1 !== "number") + return t1.$add(); + $.Closure_functionCounter = t1 + 1; + selfName = "self" + t1; + t1 = "return function(){var " + selfName + " = this."; + t2 = $.BoundClosure_selfFieldNameCache; + return new Function(t1 + H.S(t2 == null ? $.BoundClosure_selfFieldNameCache = H.BoundClosure_computeFieldNamed("self") : t2) + ";return " + selfName + "." + H.S(stubName) + "();}")(); + } + H.assertHelper(1 <= arity && arity < 27); + $arguments = "abcdefghijklmnopqrstuvwxyz".split("").splice(0, arity).join(","); + t1 = $.Closure_functionCounter; + if (typeof t1 !== "number") + return t1.$add(); + $.Closure_functionCounter = t1 + 1; + $arguments += t1; + t1 = "return function(" + $arguments + "){return this."; + t2 = $.BoundClosure_selfFieldNameCache; + return new Function(t1 + H.S(t2 == null ? $.BoundClosure_selfFieldNameCache = H.BoundClosure_computeFieldNamed("self") : t2) + "." + H.S(stubName) + "(" + $arguments + ");}")(); + }, + Closure_cspForwardInterceptedCall: function(arity, isSuperCall, $name, $function) { + var getSelf = H.BoundClosure_selfOf, + getReceiver = H.BoundClosure_receiverOf; + switch (isSuperCall ? -1 : arity) { + case 0: + throw H.wrapException(H.RuntimeError$("Intercepted function with no arguments.")); + case 1: + return function(n, s, r) { + return function() { + return s(this)[n](r(this)); + }; + }($name, getSelf, getReceiver); + case 2: + return function(n, s, r) { + return function(a) { + return s(this)[n](r(this), a); + }; + }($name, getSelf, getReceiver); + case 3: + return function(n, s, r) { + return function(a, b) { + return s(this)[n](r(this), a, b); + }; + }($name, getSelf, getReceiver); + case 4: + return function(n, s, r) { + return function(a, b, c) { + return s(this)[n](r(this), a, b, c); + }; + }($name, getSelf, getReceiver); + case 5: + return function(n, s, r) { + return function(a, b, c, d) { + return s(this)[n](r(this), a, b, c, d); + }; + }($name, getSelf, getReceiver); + case 6: + return function(n, s, r) { + return function(a, b, c, d, e) { + return s(this)[n](r(this), a, b, c, d, e); + }; + }($name, getSelf, getReceiver); + default: + return function(f, s, r, a) { + return function() { + a = [r(this)]; + Array.prototype.push.apply(a, arguments); + return f.apply(s(this), a); + }; + }($function, getSelf, getReceiver); + } + }, + Closure_forwardInterceptedCallTo: function(receiver, $function) { + var t2, stubName, arity, lookedUpFunction, t3, t4, $arguments, + t1 = $.BoundClosure_selfFieldNameCache; + if (t1 == null) + t1 = $.BoundClosure_selfFieldNameCache = H.BoundClosure_computeFieldNamed("self"); + t2 = $.BoundClosure_receiverFieldNameCache; + if (t2 == null) + t2 = $.BoundClosure_receiverFieldNameCache = H.BoundClosure_computeFieldNamed("receiver"); + stubName = $function.$stubName; + arity = $function.length; + lookedUpFunction = receiver[stubName]; + t3 = $function == null ? lookedUpFunction == null : $function === lookedUpFunction; + t4 = !t3 || arity >= 28; + if (t4) + return H.Closure_cspForwardInterceptedCall(arity, !t3, stubName, $function); + if (arity === 1) { + t1 = "return function(){return this." + H.S(t1) + "." + H.S(stubName) + "(this." + H.S(t2) + ");"; + t2 = $.Closure_functionCounter; + if (typeof t2 !== "number") + return t2.$add(); + $.Closure_functionCounter = t2 + 1; + return new Function(t1 + t2 + "}")(); + } + H.assertHelper(1 < arity && arity < 28); + $arguments = "abcdefghijklmnopqrstuvwxyz".split("").splice(0, arity - 1).join(","); + t1 = "return function(" + $arguments + "){return this." + H.S(t1) + "." + H.S(stubName) + "(this." + H.S(t2) + ", " + $arguments + ");"; + t2 = $.Closure_functionCounter; + if (typeof t2 !== "number") + return t2.$add(); + $.Closure_functionCounter = t2 + 1; + return new Function(t1 + t2 + "}")(); + }, + closureFromTearOff: function(receiver, functions, applyTrampolineIndex, reflectionInfo, isStatic, isIntercepted, $name) { + return H.Closure_fromTearOff(receiver, functions, applyTrampolineIndex, reflectionInfo, !!isStatic, !!isIntercepted, $name); + }, + BoundClosure_evalRecipe: function(closure, recipe) { + return H._Universe_evalInEnvironment(init.typeUniverse, H.instanceType(closure._self), recipe); + }, + BoundClosure_evalRecipeIntercepted: function(closure, recipe) { + return H._Universe_evalInEnvironment(init.typeUniverse, H.instanceType(closure._receiver), recipe); + }, + BoundClosure_selfOf: function(closure) { + return closure._self; + }, + BoundClosure_receiverOf: function(closure) { + return closure._receiver; + }, + BoundClosure_computeFieldNamed: function(fieldName) { + var t1, i, $name, + template = new H.BoundClosure("self", "target", "receiver", "name"), + names = J.JSArray_markFixedList(Object.getOwnPropertyNames(template)); + for (t1 = names.length, i = 0; i < t1; ++i) { + $name = names[i]; + if (template[$name] === fieldName) + return $name; + } + }, + boolConversionCheck: function(value) { + if (value == null) + H.assertThrow("boolean expression must not be null"); + return value; + }, + extractFunctionTypeObjectFromInternal: function(o) { + var signature; + if ("$signature" in o) { + signature = o.$signature; + if (typeof signature == "number") + return init.types[H._checkIntNullable(signature)]; + else + return o.$signature(); + } + return null; + }, + TypeErrorImplementation$: function(value, type) { + return new H.TypeErrorImplementation("TypeError: " + P.Error_safeToString(value) + ": type '" + H.S(H._typeDescription(value)) + "' is not a subtype of type '" + type + "'"); + }, + _typeDescription: function(value) { + var functionTypeObject; + if (value instanceof H.Closure) { + functionTypeObject = H.extractFunctionTypeObjectFromInternal(J.getInterceptor$(value)); + if (functionTypeObject != null) + return H.runtimeTypeToString(functionTypeObject); + return "Closure"; + } + return H.Primitives_objectTypeName(value); + }, + assertTest: function(condition) { + if (true === condition) + return false; + if (H._isBool(condition)) + return !condition; + throw H.wrapException(H.TypeErrorImplementation$(condition, "bool")); + }, + assertThrow: function(message) { + throw H.wrapException(new H._AssertionError(message)); + }, + assertHelper: function(condition) { + if (H.assertTest(condition)) + throw H.wrapException(P.AssertionError$(null)); + }, + throwCyclicInit: function(staticName) { + throw H.wrapException(new P.CyclicInitializationError(staticName)); + }, + RuntimeError$: function(message) { + return new H.RuntimeError(message); + }, + getIsolateAffinityTag: function($name) { + return init.getIsolateTag($name); + }, + setRuntimeTypeInfo: function(target, rti) { + H.assertHelper(rti != null); + target.$ti = rti; + return target; + }, + getRuntimeTypeInfo: function(target) { + if (target == null) + return null; + return target.$ti; + }, + getRuntimeTypeArguments: function(interceptor, object, substitutionName) { + return H.substitute(interceptor["$as" + H.S(substitutionName)], H.getRuntimeTypeInfo(object)); + }, + runtimeTypeToString: function(rti) { + return H._runtimeTypeToString(rti, null); + }, + _runtimeTypeToString: function(rti, genericContext) { + var t1, t2; + if (rti == null) + return "dynamic"; + if (rti === -1) + return "void"; + if (Array.isArray(rti)) + return H.unminifyOrTag(rti[0].name) + H._joinArguments(rti, 1, genericContext); + if (typeof rti == "function") + return H.unminifyOrTag(rti.name); + if (rti === -2) + return "dynamic"; + H.assertHelper(!(rti === -1)); + if (typeof rti == "number") { + H._checkIntNullable(rti); + if (genericContext == null || rti < 0 || rti >= genericContext.length) + return "unexpected-generic-index:" + rti; + t1 = genericContext.length; + t2 = t1 - rti - 1; + if (t2 < 0 || t2 >= t1) + return H.ioore(genericContext, t2); + return H.S(genericContext[t2]); + } + t1 = rti != null; + if (t1) + t2 = typeof rti == "string"; + else + t2 = true; + H.assertHelper(!t2); + if ('func' in rti) + return H._functionRtiToString0(rti, genericContext); + if (t1) + t2 = typeof rti == "string"; + else + t2 = true; + H.assertHelper(!t2); + if ('futureOr' in rti) { + if (t1) + t1 = typeof rti == "string"; + else + t1 = true; + H.assertHelper(!t1); + H.assertHelper('futureOr' in rti); + return "FutureOr<" + H._runtimeTypeToString("type" in rti ? rti.type : null, genericContext) + ">"; + } + return "unknown-reified-type"; + }, + _functionRtiToString0: function(rti, genericContext) { + var boundsRti, outerContextLength, offset, i, i0, typeParameters, typeSep, t1, t2, boundRti, returnTypeText, $arguments, argumentsText, sep, _i, argument, optionalArguments, namedArguments, $name, _s2_ = ", "; + if ("bounds" in rti) { + boundsRti = rti.bounds; + if (genericContext == null) { + genericContext = H.setRuntimeTypeInfo([], type$.JSArray_String); + outerContextLength = null; + } else + outerContextLength = genericContext.length; + offset = genericContext.length; + for (i = boundsRti.length, i0 = i; i0 > 0; --i0) + C.JSArray_methods.add$1(genericContext, "T" + (offset + i0)); + for (typeParameters = "<", typeSep = "", i0 = 0; i0 < i; ++i0, typeSep = _s2_) { + typeParameters += typeSep; + t1 = genericContext.length; + t2 = t1 - i0 - 1; + if (t2 < 0) + return H.ioore(genericContext, t2); + typeParameters = C.JSString_methods.$add(typeParameters, genericContext[t2]); + boundRti = boundsRti[i0]; + if (boundRti != null && boundRti !== P.Object) + typeParameters += " extends " + H._runtimeTypeToString(boundRti, genericContext); + } + typeParameters += ">"; + } else { + typeParameters = ""; + outerContextLength = null; + } + returnTypeText = !!rti.v ? "void" : H._runtimeTypeToString(rti.ret, genericContext); + if ("args" in rti) { + $arguments = rti.args; + for (t1 = $arguments.length, argumentsText = "", sep = "", _i = 0; _i < t1; ++_i, sep = _s2_) { + argument = $arguments[_i]; + argumentsText = argumentsText + sep + H._runtimeTypeToString(argument, genericContext); + } + } else { + argumentsText = ""; + sep = ""; + } + if ("opt" in rti) { + optionalArguments = rti.opt; + argumentsText += sep + "["; + for (t1 = optionalArguments.length, sep = "", _i = 0; _i < t1; ++_i, sep = _s2_) { + argument = optionalArguments[_i]; + argumentsText = argumentsText + sep + H._runtimeTypeToString(argument, genericContext); + } + argumentsText += "]"; + } + if ("named" in rti) { + namedArguments = rti.named; + argumentsText += sep + "{"; + for (t1 = H.extractKeys(namedArguments), t2 = t1.length, sep = "", _i = 0; _i < t2; ++_i, sep = _s2_) { + $name = H._checkStringNullable(t1[_i]); + argumentsText = argumentsText + sep + H._runtimeTypeToString(namedArguments[$name], genericContext) + (" " + H.S($name)); + } + argumentsText += "}"; + } + if (outerContextLength != null) + genericContext.length = outerContextLength; + return typeParameters + "(" + argumentsText + ") => " + returnTypeText; + }, + _joinArguments: function(types, startIndex, genericContext) { + var t1, buffer, index, separator, allDynamic, argument; + if (types == null) + return ""; + t1 = Array.isArray(types); + H.assertHelper(t1); + buffer = new P.StringBuffer(""); + for (index = startIndex, separator = "", allDynamic = true; H.assertHelper(t1), index < types.length; ++index, separator = ", ") { + buffer._contents += separator; + H.assertHelper(t1); + argument = types[index]; + if (argument != null) + allDynamic = false; + buffer._contents += H._runtimeTypeToString(argument, genericContext); + } + return "<" + buffer.toString$0(0) + ">"; + }, + getRuntimeType: function(object) { + var rti = object instanceof H.Closure ? H.closureFunctionType(object) : null; + return H.createRuntimeType(rti == null ? H.instanceType(object) : rti); + }, + substitute: function(substitution, $arguments) { + if (substitution == null) + return $arguments; + H.assertHelper(typeof substitution == "function"); + H.assertHelper($arguments == null || Array.isArray($arguments)); + substitution = H.invokeOn(substitution, null, $arguments); + if (substitution == null) + return null; + if (Array.isArray(substitution)) + return substitution; + if (typeof substitution == "function") + return H.invokeOn(substitution, null, $arguments); + return $arguments; + }, + computeSignature: function(signature, context, contextName) { + return H.invokeOn(signature, context, H.substitute(J.getInterceptor$(context)["$as" + H.S(contextName)], H.getRuntimeTypeInfo(context))); + }, + invokeOn: function($function, receiver, $arguments) { + H.assertHelper(typeof $function == "function"); + H.assertHelper($arguments == null || Array.isArray($arguments)); + return $function.apply(receiver, $arguments); + }, + defineProperty: function(obj, property, value) { + Object.defineProperty(obj, property, {value: value, enumerable: false, writable: true, configurable: true}); + }, + lookupAndCacheInterceptor: function(obj) { + var tag, record, interceptor, interceptorClass, mark, t1; + H.assertHelper(!(obj instanceof P.Object)); + tag = H._checkStringNullable($.getTagFunction.call$1(obj)); + record = $.dispatchRecordsForInstanceTags[tag]; + if (record != null) { + Object.defineProperty(obj, init.dispatchPropertyName, {value: record, enumerable: false, writable: true, configurable: true}); + return record.i; + } + interceptor = $.interceptorsForUncacheableTags[tag]; + if (interceptor != null) + return interceptor; + interceptorClass = init.interceptorsByTag[tag]; + if (interceptorClass == null) { + tag = H._checkStringNullable($.alternateTagFunction.call$2(obj, tag)); + if (tag != null) { + record = $.dispatchRecordsForInstanceTags[tag]; + if (record != null) { + Object.defineProperty(obj, init.dispatchPropertyName, {value: record, enumerable: false, writable: true, configurable: true}); + return record.i; + } + interceptor = $.interceptorsForUncacheableTags[tag]; + if (interceptor != null) + return interceptor; + interceptorClass = init.interceptorsByTag[tag]; + } + } + if (interceptorClass == null) + return null; + interceptor = interceptorClass.prototype; + mark = tag[0]; + if (mark === "!") { + record = H.makeLeafDispatchRecord(interceptor); + $.dispatchRecordsForInstanceTags[tag] = record; + Object.defineProperty(obj, init.dispatchPropertyName, {value: record, enumerable: false, writable: true, configurable: true}); + return record.i; + } + if (mark === "~") { + $.interceptorsForUncacheableTags[tag] = interceptor; + return interceptor; + } + if (mark === "-") { + t1 = H.makeLeafDispatchRecord(interceptor); + Object.defineProperty(Object.getPrototypeOf(obj), init.dispatchPropertyName, {value: t1, enumerable: false, writable: true, configurable: true}); + return t1.i; + } + if (mark === "+") + return H.patchInteriorProto(obj, interceptor); + if (mark === "*") + throw H.wrapException(P.UnimplementedError$(tag)); + if (init.leafTags[tag] === true) { + t1 = H.makeLeafDispatchRecord(interceptor); + Object.defineProperty(Object.getPrototypeOf(obj), init.dispatchPropertyName, {value: t1, enumerable: false, writable: true, configurable: true}); + return t1.i; + } else + return H.patchInteriorProto(obj, interceptor); + }, + patchInteriorProto: function(obj, interceptor) { + var proto = Object.getPrototypeOf(obj); + Object.defineProperty(proto, init.dispatchPropertyName, {value: J.makeDispatchRecord(interceptor, proto, null, null), enumerable: false, writable: true, configurable: true}); + return interceptor; + }, + makeLeafDispatchRecord: function(interceptor) { + return J.makeDispatchRecord(interceptor, false, null, !!interceptor.$isJavaScriptIndexingBehavior); + }, + makeDefaultDispatchRecord: function(tag, interceptorClass, proto) { + var interceptor = interceptorClass.prototype; + if (init.leafTags[tag] === true) + return H.makeLeafDispatchRecord(interceptor); + else + return J.makeDispatchRecord(interceptor, proto, null, null); + }, + initNativeDispatch: function() { + if (true === $.initNativeDispatchFlag) + return; + $.initNativeDispatchFlag = true; + H.initNativeDispatchContinue(); + }, + initNativeDispatchContinue: function() { + var map, tags, fun, i, tag, proto, record, interceptorClass; + $.dispatchRecordsForInstanceTags = Object.create(null); + $.interceptorsForUncacheableTags = Object.create(null); + H.initHooks(); + map = init.interceptorsByTag; + tags = Object.getOwnPropertyNames(map); + if (typeof window != "undefined") { + window; + fun = function() { + }; + for (i = 0; i < tags.length; ++i) { + tag = tags[i]; + proto = $.prototypeForTagFunction.call$1(tag); + if (proto != null) { + record = H.makeDefaultDispatchRecord(tag, map[tag], proto); + if (record != null) { + Object.defineProperty(proto, init.dispatchPropertyName, {value: record, enumerable: false, writable: true, configurable: true}); + fun.prototype = proto; + } + } + } + } + for (i = 0; i < tags.length; ++i) { + tag = tags[i]; + if (/^[A-Za-z_]/.test(tag)) { + interceptorClass = map[tag]; + map["!" + tag] = interceptorClass; + map["~" + tag] = interceptorClass; + map["-" + tag] = interceptorClass; + map["+" + tag] = interceptorClass; + map["*" + tag] = interceptorClass; + } + } + }, + initHooks: function() { + var transformers, i, transformer, getTag, getUnknownTag, prototypeForTag, + hooks = C.C_JS_CONST0(); + hooks = H.applyHooksTransformer(C.C_JS_CONST1, H.applyHooksTransformer(C.C_JS_CONST2, H.applyHooksTransformer(C.C_JS_CONST3, H.applyHooksTransformer(C.C_JS_CONST3, H.applyHooksTransformer(C.C_JS_CONST4, H.applyHooksTransformer(C.C_JS_CONST5, H.applyHooksTransformer(C.C_JS_CONST6(C.C_JS_CONST), hooks))))))); + if (typeof dartNativeDispatchHooksTransformer != "undefined") { + transformers = dartNativeDispatchHooksTransformer; + if (typeof transformers == "function") + transformers = [transformers]; + if (transformers.constructor == Array) + for (i = 0; i < transformers.length; ++i) { + transformer = transformers[i]; + if (typeof transformer == "function") + hooks = transformer(hooks) || hooks; + } + } + getTag = hooks.getTag; + getUnknownTag = hooks.getUnknownTag; + prototypeForTag = hooks.prototypeForTag; + $.getTagFunction = new H.initHooks_closure(getTag); + $.alternateTagFunction = new H.initHooks_closure0(getUnknownTag); + $.prototypeForTagFunction = new H.initHooks_closure1(prototypeForTag); + }, + applyHooksTransformer: function(transformer, hooks) { + return transformer(hooks) || hooks; + }, + JSSyntaxRegExp_makeNative: function(source, multiLine, caseSensitive, unicode, dotAll, global) { + var m = multiLine ? "m" : "", + i = caseSensitive ? "" : "i", + u = unicode ? "u" : "", + s = dotAll ? "s" : "", + g = global ? "g" : "", + regexp = function(source, modifiers) { + try { + return new RegExp(source, modifiers); + } catch (e) { + return e; + } + }(source, m + i + u + s + g); + if (regexp instanceof RegExp) + return regexp; + throw H.wrapException(P.FormatException$("Illegal RegExp pattern (" + String(regexp) + ")", source, null)); + }, + _MatchImplementation$: function(pattern, _match) { + H.assertHelper(typeof _match.input == "string"); + H.assertHelper(H._isInt(_match.index)); + return new H._MatchImplementation(_match); + }, + stringContainsUnchecked: function(receiver, other, startIndex) { + var t1, t2; + if (typeof other == "string") + return receiver.indexOf(other, startIndex) >= 0; + else if (other instanceof H.JSSyntaxRegExp) { + t1 = C.JSString_methods.substring$1(receiver, startIndex); + t2 = other._nativeRegExp; + return t2.test(t1); + } else { + t1 = J.allMatches$1$s(other, C.JSString_methods.substring$1(receiver, startIndex)); + return !t1.get$isEmpty(t1); + } + }, + escapeReplacement: function(replacement) { + if (replacement.indexOf("$", 0) >= 0) + return replacement.replace(/\$/g, "$$$$"); + return replacement; + }, + stringReplaceFirstRE: function(receiver, regexp, replacement, startIndex) { + var match = regexp._execGlobal$2(receiver, startIndex); + if (match == null) + return receiver; + return H.stringReplaceRangeUnchecked(receiver, match._match.index, match.get$end(), replacement); + }, + quoteStringForRegExp: function(string) { + if (/[[\]{}()*+?.\\^$|]/.test(string)) + return string.replace(/[[\]{}()*+?.\\^$|]/g, "\\$&"); + return string; + }, + stringReplaceAllUnchecked: function(receiver, pattern, replacement) { + var nativeRegexp; + if (typeof pattern == "string") + return H.stringReplaceAllUncheckedString(receiver, pattern, replacement); + if (pattern instanceof H.JSSyntaxRegExp) { + nativeRegexp = pattern.get$_nativeGlobalVersion(); + nativeRegexp.lastIndex = 0; + return receiver.replace(nativeRegexp, H.escapeReplacement(replacement)); + } + if (pattern == null) + H.throwExpression(H.argumentErrorValue(pattern)); + throw H.wrapException("String.replaceAll(Pattern) UNIMPLEMENTED"); + }, + stringReplaceAllUncheckedString: function(receiver, pattern, replacement) { + var $length, t1, i, index; + if (pattern === "") { + if (receiver === "") + return replacement; + $length = receiver.length; + for (t1 = replacement, i = 0; i < $length; ++i) + t1 = t1 + receiver[i] + replacement; + return t1.charCodeAt(0) == 0 ? t1 : t1; + } + index = receiver.indexOf(pattern, 0); + if (index < 0) + return receiver; + if (receiver.length < 500 || replacement.indexOf("$", 0) >= 0) + return receiver.split(pattern).join(replacement); + return receiver.replace(new RegExp(H.quoteStringForRegExp(pattern), 'g'), H.escapeReplacement(replacement)); + }, + _stringIdentity: function(string) { + return string; + }, + stringReplaceAllFuncUnchecked: function(receiver, pattern, onMatch, onNonMatch) { + var t1, startIndex, t2, t3, t4, t5; + if (!type$.Pattern._is(pattern)) + throw H.wrapException(P.ArgumentError$value(pattern, "pattern", "is not a Pattern")); + for (t1 = pattern.allMatches$1(0, receiver), t1 = new H._AllMatchesIterator(t1._re, t1.__js_helper$_string, t1._start), startIndex = 0, t2 = ""; t1.moveNext$0(); t2 = t3) { + t3 = t1.__js_helper$_current; + t4 = t3._match; + t5 = t4.index; + t3 = t2 + H.S(H._stringIdentity(C.JSString_methods.substring$2(receiver, startIndex, t5))) + H.S(onMatch.call$1(t3)); + startIndex = t5 + t4[0].length; + } + t1 = t2 + H.S(H._stringIdentity(C.JSString_methods.substring$1(receiver, startIndex))); + return t1.charCodeAt(0) == 0 ? t1 : t1; + }, + stringReplaceFirstUnchecked: function(receiver, pattern, replacement, startIndex) { + var index, t1, matches, match; + if (typeof pattern == "string") { + index = receiver.indexOf(pattern, startIndex); + if (index < 0) + return receiver; + return H.stringReplaceRangeUnchecked(receiver, index, index + pattern.length, replacement); + } + if (pattern instanceof H.JSSyntaxRegExp) + return startIndex === 0 ? receiver.replace(pattern._nativeRegExp, H.escapeReplacement(replacement)) : H.stringReplaceFirstRE(receiver, pattern, replacement, startIndex); + if (pattern == null) + H.throwExpression(H.argumentErrorValue(pattern)); + t1 = J.allMatches$2$s(pattern, receiver, startIndex); + matches = type$.Iterator_Match._check(t1.get$iterator(t1)); + if (!matches.moveNext$0()) + return receiver; + match = matches.get$current(); + return C.JSString_methods.replaceRange$3(receiver, match.get$start(), match.get$end(), replacement); + }, + stringReplaceRangeUnchecked: function(receiver, start, end, replacement) { + var prefix = receiver.substring(0, start), + suffix = receiver.substring(end); + return prefix + replacement + suffix; + }, + ConstantMap: function ConstantMap() { + }, + ConstantMap_map_closure: function ConstantMap_map_closure(t0, t1, t2) { + this.$this = t0; + this.transform = t1; + this.result = t2; + }, + ConstantStringMap: function ConstantStringMap(t0, t1, t2, t3) { + var _ = this; + _.__js_helper$_length = t0; + _._jsObject = t1; + _.__js_helper$_keys = t2; + _.$ti = t3; + }, + _ConstantMapKeyIterable: function _ConstantMapKeyIterable(t0, t1) { + this.__js_helper$_map = t0; + this.$ti = t1; + }, + Instantiation: function Instantiation() { + }, + Instantiation1: function Instantiation1(t0, t1) { + this._genericClosure = t0; + this.$ti = t1; + }, + Primitives_initTicker_closure: function Primitives_initTicker_closure(t0) { + this.performance = t0; + }, + TypeErrorDecoder: function TypeErrorDecoder(t0, t1, t2, t3, t4, t5) { + var _ = this; + _._pattern = t0; + _._arguments = t1; + _._argumentsExpr = t2; + _._expr = t3; + _._method = t4; + _._receiver = t5; + }, + NullError: function NullError(t0, t1) { + this.__js_helper$_message = t0; + this._method = t1; + }, + JsNoSuchMethodError: function JsNoSuchMethodError(t0, t1, t2) { + this.__js_helper$_message = t0; + this._method = t1; + this._receiver = t2; + }, + UnknownJsTypeError: function UnknownJsTypeError(t0) { + this.__js_helper$_message = t0; + }, + ExceptionAndStackTrace: function ExceptionAndStackTrace(t0, t1) { + this.dartException = t0; + this.stackTrace = t1; + }, + unwrapException_saveStackTrace: function unwrapException_saveStackTrace(t0) { + this.ex = t0; + }, + _StackTrace: function _StackTrace(t0) { + this._exception = t0; + this._trace = null; + }, + Closure: function Closure() { + }, + TearOffClosure: function TearOffClosure() { + }, + StaticClosure: function StaticClosure() { + }, + BoundClosure: function BoundClosure(t0, t1, t2, t3) { + var _ = this; + _._self = t0; + _._target = t1; + _._receiver = t2; + _._name = t3; + }, + TypeErrorImplementation: function TypeErrorImplementation(t0) { + this.message = t0; + }, + RuntimeError: function RuntimeError(t0) { + this.message = t0; + }, + _AssertionError: function _AssertionError(t0) { + this.message = t0; + }, + JsLinkedHashMap: function JsLinkedHashMap(t0) { + var _ = this; + _.__js_helper$_length = 0; + _._last = _._first = _.__js_helper$_rest = _.__js_helper$_nums = _.__js_helper$_strings = null; + _._modifications = 0; + _.$ti = t0; + }, + JsLinkedHashMap_values_closure: function JsLinkedHashMap_values_closure(t0) { + this.$this = t0; + }, + JsLinkedHashMap_addAll_closure: function JsLinkedHashMap_addAll_closure(t0) { + this.$this = t0; + }, + LinkedHashMapCell: function LinkedHashMapCell(t0, t1) { + var _ = this; + _.hashMapCellKey = t0; + _.hashMapCellValue = t1; + _._previous = _._next = null; + }, + LinkedHashMapKeyIterable: function LinkedHashMapKeyIterable(t0, t1) { + this.__js_helper$_map = t0; + this.$ti = t1; + }, + LinkedHashMapKeyIterator: function LinkedHashMapKeyIterator(t0, t1, t2) { + var _ = this; + _.__js_helper$_map = t0; + _._modifications = t1; + _.__js_helper$_current = _._cell = null; + _.$ti = t2; + }, + initHooks_closure: function initHooks_closure(t0) { + this.getTag = t0; + }, + initHooks_closure0: function initHooks_closure0(t0) { + this.getUnknownTag = t0; + }, + initHooks_closure1: function initHooks_closure1(t0) { + this.prototypeForTag = t0; + }, + JSSyntaxRegExp: function JSSyntaxRegExp(t0, t1) { + var _ = this; + _.pattern = t0; + _._nativeRegExp = t1; + _._nativeAnchoredRegExp = _._nativeGlobalRegExp = null; + }, + _MatchImplementation: function _MatchImplementation(t0) { + this._match = t0; + }, + _AllMatchesIterable: function _AllMatchesIterable(t0, t1, t2) { + this._re = t0; + this.__js_helper$_string = t1; + this._start = t2; + }, + _AllMatchesIterator: function _AllMatchesIterator(t0, t1, t2) { + var _ = this; + _._regExp = t0; + _.__js_helper$_string = t1; + _._nextIndex = t2; + _.__js_helper$_current = null; + }, + StringMatch: function StringMatch(t0, t1) { + this.start = t0; + this.pattern = t1; + }, + _StringAllMatchesIterable: function _StringAllMatchesIterable(t0, t1, t2) { + this._input = t0; + this._pattern = t1; + this.__js_helper$_index = t2; + }, + _StringAllMatchesIterator: function _StringAllMatchesIterator(t0, t1, t2) { + var _ = this; + _._input = t0; + _._pattern = t1; + _.__js_helper$_index = t2; + _.__js_helper$_current = null; + }, + _ensureNativeList: function(list) { + return list; + }, + NativeInt8List__create1: function(arg) { + return new Int8Array(arg); + }, + _checkValidIndex: function(index, list, $length) { + if (index >>> 0 !== index || index >= $length) + throw H.wrapException(H.diagnoseIndexError(list, index)); + }, + _checkValidRange: function(start, end, $length) { + var t1; + if (!(start >>> 0 !== start)) + if (end == null) + t1 = start > $length; + else + t1 = end >>> 0 !== end || start > end || end > $length; + else + t1 = true; + if (t1) + throw H.wrapException(H.diagnoseRangeError(start, end, $length)); + if (end == null) + return $length; + return end; + }, + NativeByteBuffer: function NativeByteBuffer() { + }, + NativeTypedData: function NativeTypedData() { + }, + NativeByteData: function NativeByteData() { + }, + NativeTypedArray: function NativeTypedArray() { + }, + NativeTypedArrayOfDouble: function NativeTypedArrayOfDouble() { + }, + NativeTypedArrayOfInt: function NativeTypedArrayOfInt() { + }, + NativeFloat32List: function NativeFloat32List() { + }, + NativeFloat64List: function NativeFloat64List() { + }, + NativeInt16List: function NativeInt16List() { + }, + NativeInt32List: function NativeInt32List() { + }, + NativeInt8List: function NativeInt8List() { + }, + NativeUint16List: function NativeUint16List() { + }, + NativeUint32List: function NativeUint32List() { + }, + NativeUint8ClampedList: function NativeUint8ClampedList() { + }, + NativeUint8List: function NativeUint8List() { + }, + _NativeTypedArrayOfDouble_NativeTypedArray_ListMixin: function _NativeTypedArrayOfDouble_NativeTypedArray_ListMixin() { + }, + _NativeTypedArrayOfDouble_NativeTypedArray_ListMixin_FixedLengthListMixin: function _NativeTypedArrayOfDouble_NativeTypedArray_ListMixin_FixedLengthListMixin() { + }, + _NativeTypedArrayOfInt_NativeTypedArray_ListMixin: function _NativeTypedArrayOfInt_NativeTypedArray_ListMixin() { + }, + _NativeTypedArrayOfInt_NativeTypedArray_ListMixin_FixedLengthListMixin: function _NativeTypedArrayOfInt_NativeTypedArray_ListMixin_FixedLengthListMixin() { + }, + Rti__getFutureFromFutureOr: function(universe, rti) { + var future; + H.assertHelper(rti._kind === 8); + future = rti._precomputed1; + if (future == null) { + H.assertHelper(rti._kind === 8); + future = rti._precomputed1 = H._Universe__lookupInterfaceRti(universe, "Future", [rti._primary]); + } + return future; + }, + Rti__isUnionOfFunctionType: function(rti) { + var kind = rti._kind; + if (kind === 6 || kind === 7 || kind === 8) + return H.Rti__isUnionOfFunctionType(rti._primary); + return kind === 11 || kind === 12; + }, + Rti__getInterfaceTypeArguments: function(rti) { + H.assertHelper(rti._kind === 9); + return rti._rest; + }, + Rti__getBindingArguments: function(rti) { + H.assertHelper(rti._kind === 10); + return rti._rest; + }, + Rti__getFunctionParameters: function(rti) { + H.assertHelper(rti._kind === 11); + return rti._rest; + }, + Rti__getGenericFunctionBounds: function(rti) { + H.assertHelper(rti._kind === 12); + return rti._rest; + }, + Rti__getCanonicalRecipe: function(rti) { + var s = rti._canonicalRecipe; + if (H.assertTest(typeof s == "string")) + H.assertThrow("Missing canonical recipe"); + return s; + }, + findType: function(recipe) { + return H._Universe_eval(init.typeUniverse, recipe); + }, + instantiatedGenericFunctionType: function(genericFunctionRti, instantiationRti) { + var bounds, typeArguments, cache, s, key, probe, rti; + if (genericFunctionRti == null) + return null; + bounds = H.Rti__getGenericFunctionBounds(genericFunctionRti); + typeArguments = H.Rti__getInterfaceTypeArguments(instantiationRti); + H.assertHelper(bounds.length === typeArguments.length); + cache = genericFunctionRti._bindCache; + if (cache == null) + cache = genericFunctionRti._bindCache = new Map(); + s = instantiationRti._canonicalRecipe; + if (H.assertTest(typeof s == "string")) + H.assertThrow("Missing canonical recipe"); + key = s; + probe = cache.get(key); + if (probe != null) + return probe; + H.assertHelper(genericFunctionRti._kind === 12); + rti = H._instantiate(init.typeUniverse, genericFunctionRti._primary, typeArguments, 0); + cache.set(key, rti); + return rti; + }, + _instantiate: function(universe, rti, typeArguments, depth) { + var baseType, instantiatedBaseType, s, interfaceTypeArguments, instantiatedInterfaceTypeArguments, base, instantiatedBase, $arguments, instantiatedArguments, returnType, instantiatedReturnType, functionParameters, instantiatedFunctionParameters, bounds, instantiatedBounds, index, + _s24_ = "Missing canonical recipe", + t1 = rti._kind, + kind = t1; + switch (kind) { + case 5: + case 1: + case 2: + case 3: + case 4: + return rti; + case 6: + baseType = rti._primary; + instantiatedBaseType = H._instantiate(universe, baseType, typeArguments, depth); + if (instantiatedBaseType === baseType) + return rti; + s = instantiatedBaseType._canonicalRecipe; + if (H.assertTest(typeof s == "string")) + H.assertThrow(_s24_); + return H._Universe__lookupUnaryRti(universe, 6, instantiatedBaseType, s + "*"); + case 7: + baseType = rti._primary; + instantiatedBaseType = H._instantiate(universe, baseType, typeArguments, depth); + if (instantiatedBaseType === baseType) + return rti; + s = instantiatedBaseType._canonicalRecipe; + if (H.assertTest(typeof s == "string")) + H.assertThrow(_s24_); + return H._Universe__lookupUnaryRti(universe, 7, instantiatedBaseType, s + "?"); + case 8: + baseType = rti._primary; + instantiatedBaseType = H._instantiate(universe, baseType, typeArguments, depth); + if (instantiatedBaseType === baseType) + return rti; + s = instantiatedBaseType._canonicalRecipe; + if (H.assertTest(typeof s == "string")) + H.assertThrow(_s24_); + return H._Universe__lookupUnaryRti(universe, 8, instantiatedBaseType, s + "/"); + case 9: + interfaceTypeArguments = H.Rti__getInterfaceTypeArguments(rti); + instantiatedInterfaceTypeArguments = H._instantiateArray(universe, interfaceTypeArguments, typeArguments, depth); + if (instantiatedInterfaceTypeArguments === interfaceTypeArguments) + return rti; + H.assertHelper(rti._kind === 9); + return H._Universe__lookupInterfaceRti(universe, rti._primary, instantiatedInterfaceTypeArguments); + case 10: + H.assertHelper(t1 === 10); + base = rti._primary; + instantiatedBase = H._instantiate(universe, base, typeArguments, depth); + $arguments = H.Rti__getBindingArguments(rti); + instantiatedArguments = H._instantiateArray(universe, $arguments, typeArguments, depth); + if (instantiatedBase === base && instantiatedArguments === $arguments) + return rti; + return H._Universe__lookupBindingRti(universe, instantiatedBase, instantiatedArguments); + case 11: + H.assertHelper(t1 === 11); + returnType = rti._primary; + instantiatedReturnType = H._instantiate(universe, returnType, typeArguments, depth); + functionParameters = H.Rti__getFunctionParameters(rti); + instantiatedFunctionParameters = H._instantiateFunctionParameters(universe, functionParameters, typeArguments, depth); + if (instantiatedReturnType === returnType && instantiatedFunctionParameters === functionParameters) + return rti; + return H._Universe__lookupFunctionRti(universe, instantiatedReturnType, instantiatedFunctionParameters); + case 12: + bounds = H.Rti__getGenericFunctionBounds(rti); + depth += bounds.length; + instantiatedBounds = H._instantiateArray(universe, bounds, typeArguments, depth); + H.assertHelper(rti._kind === 12); + base = rti._primary; + instantiatedBase = H._instantiate(universe, base, typeArguments, depth); + if (instantiatedBounds === bounds && instantiatedBase === base) + return rti; + return H._Universe__lookupGenericFunctionRti(universe, instantiatedBase, instantiatedBounds); + case 13: + H.assertHelper(t1 === 13); + index = rti._primary; + if (index < depth) + return null; + return typeArguments[index - depth]; + default: + throw H.wrapException(P.AssertionError$("Attempted to instantiate unexpected RTI kind " + kind)); + } + }, + _instantiateArray: function(universe, rtiArray, typeArguments, depth) { + var changed, i, rti, instantiatedRti, + $length = rtiArray.length, + result = []; + for (changed = false, i = 0; i < $length; ++i) { + rti = rtiArray[i]; + instantiatedRti = H._instantiate(universe, rti, typeArguments, depth); + if (instantiatedRti !== rti) + changed = true; + result.push(instantiatedRti); + } + return changed ? result : rtiArray; + }, + _instantiateNamed: function(universe, namedArray, typeArguments, depth) { + var result, changed, i, t1, rti, instantiatedRti, + $length = namedArray.length; + H.assertHelper(($length & 1) === 0); + result = []; + for (changed = false, i = 0; i < $length; i += 2) { + t1 = namedArray[i]; + rti = namedArray[i + 1]; + instantiatedRti = H._instantiate(universe, rti, typeArguments, depth); + if (instantiatedRti !== rti) + changed = true; + result.push(t1); + result.push(instantiatedRti); + } + return changed ? result : namedArray; + }, + _instantiateFunctionParameters: function(universe, functionParameters, typeArguments, depth) { + var result, + requiredPositional = functionParameters._requiredPositional, + instantiatedRequiredPositional = H._instantiateArray(universe, requiredPositional, typeArguments, depth), + optionalPositional = functionParameters._optionalPositional, + instantiatedOptionalPositional = H._instantiateArray(universe, optionalPositional, typeArguments, depth), + optionalNamed = functionParameters._optionalNamed, + instantiatedOptionalNamed = H._instantiateNamed(universe, optionalNamed, typeArguments, depth); + if (instantiatedRequiredPositional === requiredPositional && instantiatedOptionalPositional === optionalPositional && instantiatedOptionalNamed === optionalNamed) + return functionParameters; + result = new H._FunctionParameters(); + result._requiredPositional = instantiatedRequiredPositional; + result._optionalPositional = instantiatedOptionalPositional; + result._optionalNamed = instantiatedOptionalNamed; + return result; + }, + closureFunctionType: function(closure) { + var signature = closure.$signature; + if (signature != null) { + if (typeof signature == "number") + return H.getTypeFromTypesTable(signature); + return closure.$signature(); + } + return null; + }, + instanceOrFunctionType: function(object, testRti) { + var rti; + if (H.Rti__isUnionOfFunctionType(testRti)) + if (object instanceof H.Closure) { + rti = H.closureFunctionType(object); + if (rti != null) + return rti; + } + return H.instanceType(object); + }, + instanceType: function(object) { + var rti; + if (object instanceof P.Object) { + rti = object.$ti; + return rti != null ? rti : H._instanceTypeFromConstructor(object); + } + if (Array.isArray(object)) + return H._arrayInstanceType(object); + return H._instanceTypeFromConstructor(J.getInterceptor$(object)); + }, + _arrayInstanceType: function(object) { + var rti = object.$ti, + defaultRti = type$.JSArray_dynamic; + if (rti == null) + return defaultRti; + if (rti.constructor !== defaultRti.constructor) + return defaultRti; + return rti; + }, + _instanceType: function(object) { + var rti = object.$ti; + return rti != null ? rti : H._instanceTypeFromConstructor(object); + }, + _instanceTypeFromConstructor: function(instance) { + var $constructor = instance.constructor, + probe = $constructor.$ccache; + if (probe != null) + return probe; + return H._instanceTypeFromConstructorMiss(instance, $constructor); + }, + _instanceTypeFromConstructorMiss: function(instance, $constructor) { + var effectiveConstructor = instance instanceof H.Closure ? instance.__proto__.__proto__.constructor : $constructor, + rti = H._Universe_findErasedType(init.typeUniverse, effectiveConstructor.name); + $constructor.$ccache = rti; + return rti; + }, + getTypeFromTypesTable: function(_index) { + var rti, + index = _index, + table = init.types, + type = table[index]; + if (typeof type == "string") { + rti = H._Universe_eval(init.typeUniverse, type); + table[index] = rti; + return rti; + } + return type; + }, + createRuntimeType: function(rti) { + var type = rti._cachedRuntimeType; + if (type != null) + return type; + return rti._cachedRuntimeType = new H._Type(rti); + }, + typeLiteral: function(recipe) { + return H.createRuntimeType(H._Universe_eval(init.typeUniverse, recipe)); + }, + _installSpecializedIsTest: function(object) { + var s, key, testRti = this, + t1 = testRti._kind, + isFn = H._generalIsTestImplementation; + if (H.isTopType(testRti, true)) { + isFn = H._isTop; + testRti._check = testRti._as = H._asTop; + } else if (t1 === 9) { + s = testRti._canonicalRecipe; + if (H.assertTest(typeof s == "string")) + H.assertThrow("Missing canonical recipe"); + key = s; + if ("int" === key) + isFn = H._isInt; + else if ("double" === key) + isFn = H._isNum; + else if ("num" === key) + isFn = H._isNum; + else if ("String" === key) + isFn = H._isString; + else if ("bool" === key) + isFn = H._isBool; + else { + H.assertHelper(testRti._kind === 9); + t1 = testRti._primary; + if (H.Rti__getInterfaceTypeArguments(testRti).every(H.isLegacyTopType)) { + testRti._specializedTestResource = "$is" + t1; + isFn = H._isTestViaProperty; + } + } + } + testRti._is = isFn; + return testRti._is(object); + }, + _generalIsTestImplementation: function(object) { + var testRti = this; + return H._isSubtype(init.typeUniverse, H.instanceOrFunctionType(object, testRti), null, testRti, null, true); + }, + _isTestViaProperty: function(object) { + var tag = this._specializedTestResource; + if (object instanceof P.Object) + return !!object[tag]; + return !!J.getInterceptor$(object)[tag]; + }, + _generalAsCheckImplementation: function(object) { + var testRti; + if (object == null) + return object; + testRti = this; + if (testRti._is(object)) + return object; + throw H.wrapException(H._CastError$fromMessage(H._Error_compose(object, H.instanceOrFunctionType(object, testRti), H._rtiToString(testRti, null)))); + }, + _generalTypeCheckImplementation: function(object) { + var testRti; + if (object == null) + return object; + testRti = this; + if (testRti._is(object)) + return object; + throw H.wrapException(H._TypeError$fromMessage(H._Error_compose(object, H.instanceOrFunctionType(object, testRti), H._rtiToString(testRti, null)))); + }, + checkTypeBound: function(type, bound, variable, methodName) { + var _null = null; + if (H._isSubtype(init.typeUniverse, type, _null, bound, _null, true)) + return type; + throw H.wrapException(H._TypeError$fromMessage("The type argument '" + H.S(H._rtiToString(type, _null)) + "' is not a subtype of the type variable bound '" + H.S(H._rtiToString(bound, _null)) + "' of type variable '" + variable + "' in '" + H.S(methodName) + "'.")); + }, + _Error_compose: function(object, objectRti, checkedTypeDescription) { + var objectDescription = P.Error_safeToString(object), + objectTypeDescription = H._rtiToString(objectRti == null ? H.instanceType(object) : objectRti, null); + return objectDescription + ": type '" + H.S(objectTypeDescription) + "' is not a subtype of type '" + H.S(checkedTypeDescription) + "'"; + }, + _CastError$fromMessage: function(message) { + return new H._CastError("CastError: " + message); + }, + _CastError__CastError$forType: function(object, type) { + return new H._CastError("CastError: " + H._Error_compose(object, null, type)); + }, + _TypeError$fromMessage: function(message) { + return new H._TypeError("TypeError: " + message); + }, + _TypeError__TypeError$forType: function(object, type) { + return new H._TypeError("TypeError: " + H._Error_compose(object, null, type)); + }, + _isTop: function(object) { + return true; + }, + _asTop: function(object) { + return object; + }, + _isBool: function(object) { + return true === object || false === object; + }, + _asBoolNullable: function(object) { + if (true === object || false === object) + return object; + if (object == null) + return object; + throw H.wrapException(H._CastError__CastError$forType(object, "bool")); + }, + _checkBoolNullable: function(object) { + if (true === object || false === object) + return object; + if (object == null) + return object; + throw H.wrapException(H._TypeError__TypeError$forType(object, "bool")); + }, + _asDoubleNullable: function(object) { + if (typeof object == "number") + return object; + if (object == null) + return object; + throw H.wrapException(H._CastError__CastError$forType(object, "double")); + }, + _checkDoubleNullable: function(object) { + if (typeof object == "number") + return object; + if (object == null) + return object; + throw H.wrapException(H._TypeError__TypeError$forType(object, "double")); + }, + _isInt: function(object) { + return typeof object == "number" && Math.floor(object) === object; + }, + _asIntNullable: function(object) { + if (typeof object == "number" && Math.floor(object) === object) + return object; + if (object == null) + return object; + throw H.wrapException(H._CastError__CastError$forType(object, "int")); + }, + _checkIntNullable: function(object) { + if (typeof object == "number" && Math.floor(object) === object) + return object; + if (object == null) + return object; + throw H.wrapException(H._TypeError__TypeError$forType(object, "int")); + }, + _isNum: function(object) { + return typeof object == "number"; + }, + _asNumNullable: function(object) { + if (typeof object == "number") + return object; + if (object == null) + return object; + throw H.wrapException(H._CastError__CastError$forType(object, "num")); + }, + _checkNumNullable: function(object) { + if (typeof object == "number") + return object; + if (object == null) + return object; + throw H.wrapException(H._TypeError__TypeError$forType(object, "num")); + }, + _isString: function(object) { + return typeof object == "string"; + }, + _asStringNullable: function(object) { + if (typeof object == "string") + return object; + if (object == null) + return object; + throw H.wrapException(H._CastError__CastError$forType(object, "String")); + }, + _checkStringNullable: function(object) { + if (typeof object == "string") + return object; + if (object == null) + return object; + throw H.wrapException(H._TypeError__TypeError$forType(object, "String")); + }, + _rtiArrayToString: function(array, genericContext) { + var s, sep, i; + for (s = "", sep = "", i = 0; i < array.length; ++i, sep = ", ") + s += C.JSString_methods.$add(sep, H._rtiToString(array[i], genericContext)); + return s; + }, + _functionRtiToString: function(functionType, genericContext, bounds) { + var boundsLength, outerContextLength, offset, i, typeParametersText, typeSep, t1, t2, boundRti, parameters, requiredPositional, requiredPositionalLength, optionalPositional, optionalPositionalLength, optionalNamed, optionalNamedLength, returnTypeText, argumentsText, sep, _s2_ = ", "; + if (bounds != null) { + boundsLength = bounds.length; + if (genericContext == null) { + genericContext = H.setRuntimeTypeInfo([], type$.JSArray_String); + outerContextLength = null; + } else + outerContextLength = genericContext.length; + offset = genericContext.length; + for (i = boundsLength; i > 0; --i) + C.JSArray_methods.add$1(genericContext, "T" + (offset + i)); + for (typeParametersText = "<", typeSep = "", i = 0; i < boundsLength; ++i, typeSep = _s2_) { + typeParametersText += typeSep; + t1 = genericContext.length; + t2 = t1 - 1 - i; + if (t2 < 0) + return H.ioore(genericContext, t2); + typeParametersText = C.JSString_methods.$add(typeParametersText, genericContext[t2]); + boundRti = bounds[i]; + if (!H.isTopType(boundRti, true)) + typeParametersText += C.JSString_methods.$add(" extends ", H._rtiToString(boundRti, genericContext)); + } + typeParametersText += ">"; + } else { + typeParametersText = ""; + outerContextLength = null; + } + H.assertHelper(functionType._kind === 11); + t1 = functionType._primary; + parameters = H.Rti__getFunctionParameters(functionType); + requiredPositional = parameters._requiredPositional; + requiredPositionalLength = requiredPositional.length; + optionalPositional = parameters._optionalPositional; + optionalPositionalLength = optionalPositional.length; + optionalNamed = parameters._optionalNamed; + optionalNamedLength = optionalNamed.length; + H.assertHelper(optionalPositionalLength === 0 || optionalNamedLength === 0); + returnTypeText = H._rtiToString(t1, genericContext); + for (argumentsText = "", sep = "", i = 0; i < requiredPositionalLength; ++i, sep = _s2_) + argumentsText += C.JSString_methods.$add(sep, H._rtiToString(requiredPositional[i], genericContext)); + if (optionalPositionalLength > 0) { + argumentsText += sep + "["; + for (sep = "", i = 0; i < optionalPositionalLength; ++i, sep = _s2_) + argumentsText += C.JSString_methods.$add(sep, H._rtiToString(optionalPositional[i], genericContext)); + argumentsText += "]"; + } + if (optionalNamedLength > 0) { + argumentsText += sep + "{"; + for (sep = "", i = 0; i < optionalNamedLength; i += 2, sep = _s2_) + argumentsText += C.JSString_methods.$add(sep, H._rtiToString(optionalNamed[i + 1], genericContext)) + " " + optionalNamed[i]; + argumentsText += "}"; + } + if (outerContextLength != null) + genericContext.length = outerContextLength; + return typeParametersText + "(" + argumentsText + ") => " + H.S(returnTypeText); + }, + _rtiToString: function(rti, genericContext) { + var $name, $arguments, t2, + t1 = rti._kind, + kind = t1; + if (kind === 5) + return "erased"; + if (kind === 2) + return "dynamic"; + if (kind === 3) + return "void"; + if (kind === 1) + return "Never"; + if (kind === 4) + return "any"; + if (kind === 6) { + H.assertHelper(t1 === 6); + return H.S(H._rtiToString(rti._primary, genericContext)) + "*"; + } + if (kind === 7) { + H.assertHelper(t1 === 7); + return H.S(H._rtiToString(rti._primary, genericContext)) + "?"; + } + if (kind === 8) { + H.assertHelper(t1 === 8); + return "FutureOr<" + H.S(H._rtiToString(rti._primary, genericContext)) + ">"; + } + if (kind === 9) { + H.assertHelper(t1 === 9); + $name = H._unminifyOrTag(rti._primary); + $arguments = H.Rti__getInterfaceTypeArguments(rti); + return $arguments.length !== 0 ? $name + ("<" + H._rtiArrayToString($arguments, genericContext) + ">") : $name; + } + if (kind === 11) + return H._functionRtiToString(rti, genericContext, null); + if (kind === 12) { + H.assertHelper(t1 === 12); + return H._functionRtiToString(rti._primary, genericContext, H.Rti__getGenericFunctionBounds(rti)); + } + if (kind === 13) { + H.assertHelper(t1 === 13); + t1 = rti._primary; + t2 = genericContext.length; + t1 = t2 - 1 - t1; + if (t1 < 0 || t1 >= t2) + return H.ioore(genericContext, t1); + return genericContext[t1]; + } + return "?"; + }, + _unminifyOrTag: function(rawClassName) { + var preserved = H.unmangleGlobalNameIfPreservedAnyways(rawClassName); + if (preserved != null) + return preserved; + return rawClassName; + }, + _Universe_findRule: function(universe, targetType) { + var rule = universe.tR[targetType]; + for (; typeof rule == "string";) + rule = universe.tR[rule]; + return rule; + }, + _Universe_findErasedType: function(universe, cls) { + var $length, erased, $arguments, i, $interface, + metadata = universe.eT, + probe = metadata[cls]; + if (probe == null) + return H._Universe_eval(universe, cls); + else if (typeof probe == "number") { + $length = probe; + erased = H._Universe__lookupTerminalRti(universe, 5, "#"); + $arguments = []; + for (i = 0; i < $length; ++i) + $arguments.push(erased); + $interface = H._Universe__lookupInterfaceRti(universe, cls, $arguments); + metadata[cls] = $interface; + return $interface; + } else + return probe; + }, + _Universe_addRules: function(universe, rules) { + return H._Utils_objectAssign(universe.tR, rules); + }, + _Universe_addErasedTypes: function(universe, types) { + return H._Utils_objectAssign(universe.eT, types); + }, + _Universe_eval: function(universe, recipe) { + var rti, + cache = universe.eC, + probe = cache.get(recipe); + if (probe != null) + return probe; + rti = H._Universe__parseRecipe(universe, null, recipe); + cache.set(recipe, rti); + return rti; + }, + _Universe_evalInEnvironment: function(universe, environment, recipe) { + var probe, rti, + cache = environment._evalCache; + if (cache == null) + cache = environment._evalCache = new Map(); + probe = cache.get(recipe); + if (probe != null) + return probe; + rti = H._Universe__parseRecipe(universe, environment, recipe); + cache.set(recipe, rti); + return rti; + }, + _Universe_bind: function(universe, environment, argumentsRti) { + var s, argumentsRecipe, probe, rti, + cache = environment._bindCache; + if (cache == null) + cache = environment._bindCache = new Map(); + s = argumentsRti._canonicalRecipe; + if (H.assertTest(typeof s == "string")) + H.assertThrow("Missing canonical recipe"); + argumentsRecipe = s; + probe = cache.get(argumentsRecipe); + if (probe != null) + return probe; + rti = H._Universe__lookupBindingRti(universe, environment, argumentsRti._kind === 10 ? H.Rti__getBindingArguments(argumentsRti) : [argumentsRti]); + cache.set(argumentsRecipe, rti); + return rti; + }, + _Universe__parseRecipe: function(universe, environment, recipe) { + var rti = H._Parser_parse(H._Parser_create(universe, environment, recipe)); + return rti; + }, + _Universe__finishRti: function(universe, rti) { + var s = rti._canonicalRecipe; + if (H.assertTest(typeof s == "string")) + H.assertThrow("Missing canonical recipe"); + universe.eC.set(s, rti); + rti._as = H._generalAsCheckImplementation; + rti._check = H._generalTypeCheckImplementation; + rti._is = H._installSpecializedIsTest; + return rti; + }, + _Universe__lookupTerminalRti: function(universe, kind, canonicalRecipe) { + var rti, + probe = universe.eC.get(canonicalRecipe); + if (probe != null) + return probe; + rti = new H.Rti(null, null, null); + rti._kind = kind; + rti._canonicalRecipe = canonicalRecipe; + return H._Universe__finishRti(universe, rti); + }, + _Universe__lookupUnaryRti: function(universe, kind, baseType, canonicalRecipe) { + var rti, + probe = universe.eC.get(canonicalRecipe); + if (probe != null) + return probe; + rti = new H.Rti(null, null, null); + rti._kind = kind; + rti._primary = baseType; + rti._canonicalRecipe = canonicalRecipe; + return H._Universe__finishRti(universe, rti); + }, + _Universe__lookupGenericFunctionParameterRti: function(universe, index) { + var rti, + canonicalRecipe = "" + index + "^", + probe = universe.eC.get(canonicalRecipe); + if (probe != null) + return probe; + rti = new H.Rti(null, null, null); + rti._kind = 13; + rti._primary = index; + rti._canonicalRecipe = canonicalRecipe; + return H._Universe__finishRti(universe, rti); + }, + _Universe__canonicalRecipeJoin: function($arguments) { + var s, sep, i, s0, + $length = $arguments.length; + for (s = "", sep = "", i = 0; i < $length; ++i, sep = ",") { + s0 = $arguments[i]._canonicalRecipe; + if (H.assertTest(typeof s0 == "string")) + H.assertThrow("Missing canonical recipe"); + s += sep + s0; + } + return s; + }, + _Universe__canonicalRecipeJoinNamed: function($arguments) { + var s, sep, i, t1, s0, + $length = $arguments.length; + H.assertHelper(($length & 1) === 0); + for (s = "", sep = "", i = 0; i < $length; i += 2, sep = ",") { + t1 = $arguments[i]; + s0 = $arguments[i + 1]._canonicalRecipe; + if (H.assertTest(typeof s0 == "string")) + H.assertThrow("Missing canonical recipe"); + s += sep + t1 + ":" + s0; + } + return s; + }, + _Universe__lookupInterfaceRti: function(universe, $name, $arguments) { + var s, probe, rti; + H.assertHelper(typeof $name == "string"); + s = $name; + if ($arguments.length !== 0) + s += "<" + H._Universe__canonicalRecipeJoin($arguments) + ">"; + probe = universe.eC.get(s); + if (probe != null) + return probe; + rti = new H.Rti(null, null, null); + rti._kind = 9; + rti._primary = $name; + rti._rest = $arguments; + if ($arguments.length > 0) + rti._precomputed1 = $arguments[0]; + rti._canonicalRecipe = s; + return H._Universe__finishRti(universe, rti); + }, + _Universe__lookupBindingRti: function(universe, base, $arguments) { + var newBase, newArguments, s, probe, rti, + t1 = base._kind; + if (t1 === 10) { + H.assertHelper(t1 === 10); + newBase = base._primary; + newArguments = H.Rti__getBindingArguments(base).concat($arguments); + } else { + newArguments = $arguments; + newBase = base; + } + s = newBase._canonicalRecipe; + if (H.assertTest(typeof s == "string")) + H.assertThrow("Missing canonical recipe"); + s = s + ";" + ("<" + H._Universe__canonicalRecipeJoin(newArguments) + ">"); + probe = universe.eC.get(s); + if (probe != null) + return probe; + rti = new H.Rti(null, null, null); + rti._kind = 10; + rti._primary = newBase; + rti._rest = newArguments; + rti._canonicalRecipe = s; + return H._Universe__finishRti(universe, rti); + }, + _Universe__lookupFunctionRti: function(universe, returnType, parameters) { + var requiredPositional, requiredPositionalLength, optionalPositional, optionalPositionalLength, optionalNamed, optionalNamedLength, recipe, key, probe, rti, + s = returnType._canonicalRecipe; + if (H.assertTest(typeof s == "string")) + H.assertThrow("Missing canonical recipe"); + requiredPositional = parameters._requiredPositional; + requiredPositionalLength = requiredPositional.length; + optionalPositional = parameters._optionalPositional; + optionalPositionalLength = optionalPositional.length; + optionalNamed = parameters._optionalNamed; + optionalNamedLength = optionalNamed.length; + H.assertHelper(optionalPositionalLength === 0 || optionalNamedLength === 0); + recipe = "(" + H._Universe__canonicalRecipeJoin(requiredPositional); + if (optionalPositionalLength > 0) + recipe += (requiredPositionalLength > 0 ? "," : "") + "[" + H._Universe__canonicalRecipeJoin(optionalPositional) + "]"; + if (optionalNamedLength > 0) + recipe += (requiredPositionalLength > 0 ? "," : "") + "{" + H._Universe__canonicalRecipeJoinNamed(optionalNamed) + "}"; + key = s + (recipe + ")"); + probe = universe.eC.get(key); + if (probe != null) + return probe; + rti = new H.Rti(null, null, null); + rti._kind = 11; + rti._primary = returnType; + rti._rest = parameters; + rti._canonicalRecipe = key; + return H._Universe__finishRti(universe, rti); + }, + _Universe__lookupGenericFunctionRti: function(universe, baseFunctionType, bounds) { + var key, probe, rti, + s = baseFunctionType._canonicalRecipe; + if (H.assertTest(typeof s == "string")) + H.assertThrow("Missing canonical recipe"); + key = s + "<" + H._Universe__canonicalRecipeJoin(bounds) + ">"; + probe = universe.eC.get(key); + if (probe != null) + return probe; + rti = new H.Rti(null, null, null); + rti._kind = 12; + rti._primary = baseFunctionType; + rti._rest = bounds; + rti._canonicalRecipe = key; + return H._Universe__finishRti(universe, rti); + }, + _Parser_create: function(universe, environment, recipe) { + return {u: universe, e: environment, r: recipe, s: [], p: 0}; + }, + _Parser_parse: function(parser) { + var t1, i, ch, t2, t3, universe, array, head, base, u, s, parameters, optionalPositional, optionalNamed, item, + _s24_ = "Missing canonical recipe", + source = parser.r, + stack = parser.s; + for (t1 = source.length, i = 0; i < t1;) { + ch = source.charCodeAt(i); + if (ch >= 48 && ch <= 57) + i = H._Parser_handleDigit(i + 1, ch, source, stack); + else if ((((ch | 32) >>> 0) - 97 & 65535) < 26 || ch === 95 || ch === 36) + i = H._Parser_handleIdentifier(parser, i, source, stack, false); + else if (ch === 46) + i = H._Parser_handleIdentifier(parser, i, source, stack, true); + else { + ++i; + switch (ch) { + case 44: + break; + case 58: + break; + case 59: + stack.push(H._Parser_toType(parser.u, parser.e, stack.pop())); + break; + case 94: + t2 = parser.u; + t3 = stack.pop(); + H.assertHelper(typeof t3 == "number"); + stack.push(H._Universe__lookupGenericFunctionParameterRti(t2, t3)); + break; + case 35: + stack.push(H._Universe__lookupTerminalRti(parser.u, 5, "#")); + break; + case 64: + stack.push(H._Universe__lookupTerminalRti(parser.u, 2, "@")); + break; + case 126: + stack.push(H._Universe__lookupTerminalRti(parser.u, 3, "~")); + break; + case 60: + stack.push(parser.p); + parser.p = stack.length; + break; + case 62: + universe = parser.u; + array = stack.splice(parser.p); + H._Parser_toTypes(parser.u, parser.e, array); + parser.p = stack.pop(); + head = stack.pop(); + if (typeof head == "string") + stack.push(H._Universe__lookupInterfaceRti(universe, head, array)); + else { + base = H._Parser_toType(universe, parser.e, head); + switch (base._kind) { + case 11: + stack.push(H._Universe__lookupGenericFunctionRti(universe, base, array)); + break; + default: + stack.push(H._Universe__lookupBindingRti(universe, base, array)); + break; + } + } + break; + case 38: + H._Parser_handleExtendedOperations(parser, stack); + break; + case 42: + u = parser.u; + t2 = H._Parser_toType(u, parser.e, stack.pop()); + s = t2._canonicalRecipe; + if (H.assertTest(typeof s == "string")) + H.assertThrow(_s24_); + stack.push(H._Universe__lookupUnaryRti(u, 6, t2, s + "*")); + break; + case 63: + u = parser.u; + t2 = H._Parser_toType(u, parser.e, stack.pop()); + s = t2._canonicalRecipe; + if (H.assertTest(typeof s == "string")) + H.assertThrow(_s24_); + stack.push(H._Universe__lookupUnaryRti(u, 7, t2, s + "?")); + break; + case 47: + u = parser.u; + t2 = H._Parser_toType(u, parser.e, stack.pop()); + s = t2._canonicalRecipe; + if (H.assertTest(typeof s == "string")) + H.assertThrow(_s24_); + stack.push(H._Universe__lookupUnaryRti(u, 8, t2, s + "/")); + break; + case 40: + stack.push(parser.p); + parser.p = stack.length; + break; + case 41: + universe = parser.u; + parameters = new H._FunctionParameters(); + optionalPositional = universe.sEA; + optionalNamed = universe.sEA; + head = stack.pop(); + if (typeof head == "number") + switch (head) { + case -1: + optionalPositional = stack.pop(); + break; + case -2: + optionalNamed = stack.pop(); + break; + default: + stack.push(head); + break; + } + else + stack.push(head); + array = stack.splice(parser.p); + H._Parser_toTypes(parser.u, parser.e, array); + parser.p = stack.pop(); + parameters._requiredPositional = array; + parameters._optionalPositional = optionalPositional; + parameters._optionalNamed = optionalNamed; + stack.push(H._Universe__lookupFunctionRti(universe, H._Parser_toType(universe, parser.e, stack.pop()), parameters)); + break; + case 91: + stack.push(parser.p); + parser.p = stack.length; + break; + case 93: + array = stack.splice(parser.p); + H._Parser_toTypes(parser.u, parser.e, array); + parser.p = stack.pop(); + stack.push(array); + stack.push(-1); + break; + case 123: + stack.push(parser.p); + parser.p = stack.length; + break; + case 125: + array = stack.splice(parser.p); + H._Parser_toTypesNamed(parser.u, parser.e, array); + parser.p = stack.pop(); + stack.push(array); + stack.push(-2); + break; + default: + throw "Bad character " + ch; + } + } + } + item = stack.pop(); + return H._Parser_toType(parser.u, parser.e, item); + }, + _Parser_handleDigit: function(i, digit, source, stack) { + var t1, ch, + value = digit - 48; + for (t1 = source.length; i < t1; ++i) { + ch = source.charCodeAt(i); + if (!(ch >= 48 && ch <= 57)) + break; + value = value * 10 + (ch - 48); + } + stack.push(value); + return i; + }, + _Parser_handleIdentifier: function(parser, start, source, stack, hasPeriod) { + var t1, ch, t2, string, environment, rule, recipe, + i = start + 1; + for (t1 = source.length; i < t1; ++i) { + ch = source.charCodeAt(i); + if (ch === 46) { + if (hasPeriod) + break; + hasPeriod = true; + } else { + if (!((((ch | 32) >>> 0) - 97 & 65535) < 26 || ch === 95 || ch === 36)) + t2 = ch >= 48 && ch <= 57; + else + t2 = true; + if (!t2) + break; + } + } + string = source.substring(start, i); + if (hasPeriod) { + t1 = parser.u; + environment = parser.e; + t2 = environment._kind; + if (t2 === 10) { + H.assertHelper(t2 === 10); + environment = environment._primary; + } + H.assertHelper(environment._kind === 9); + rule = H._Universe_findRule(t1, environment._primary); + H.assertHelper(rule != null); + recipe = rule[string]; + if (recipe == null) + H.throwExpression('No "' + string + '" in "' + H.Rti__getCanonicalRecipe(environment) + '"'); + stack.push(H._Universe_evalInEnvironment(t1, environment, recipe)); + } else + stack.push(string); + return i; + }, + _Parser_handleExtendedOperations: function(parser, stack) { + var $top = stack.pop(); + if (0 === $top) { + stack.push(H._Universe__lookupTerminalRti(parser.u, 1, "0&")); + return; + } + if (1 === $top) { + stack.push(H._Universe__lookupTerminalRti(parser.u, 4, "1&")); + return; + } + throw H.wrapException(P.AssertionError$("Unexpected extended operation " + H.S($top))); + }, + _Parser_toType: function(universe, environment, item) { + if (typeof item == "string") + return H._Universe__lookupInterfaceRti(universe, item, universe.sEA); + else if (typeof item == "number") + return H._Parser_indexToType(universe, environment, item); + else + return item; + }, + _Parser_toTypes: function(universe, environment, items) { + var i, + $length = items.length; + for (i = 0; i < $length; ++i) + items[i] = H._Parser_toType(universe, environment, items[i]); + }, + _Parser_toTypesNamed: function(universe, environment, items) { + var i, + $length = items.length; + H.assertHelper(($length & 1) === 0); + for (i = 1; i < $length; i += 2) + items[i] = H._Parser_toType(universe, environment, items[i]); + }, + _Parser_indexToType: function(universe, environment, index) { + var typeArguments, len, + t1 = environment._kind, + kind = t1; + if (kind === 10) { + if (index === 0) { + H.assertHelper(t1 === 10); + return environment._primary; + } + typeArguments = H.Rti__getBindingArguments(environment); + len = typeArguments.length; + if (index <= len) + return typeArguments[index - 1]; + index -= len; + H.assertHelper(t1 === 10); + environment = environment._primary; + kind = environment._kind; + } else if (index === 0) + return environment; + if (kind !== 9) + throw H.wrapException(P.AssertionError$("Indexed base must be an interface type")); + typeArguments = H.Rti__getInterfaceTypeArguments(environment); + if (index <= typeArguments.length) + return typeArguments[index - 1]; + throw H.wrapException(P.AssertionError$("Bad index " + index + " for " + environment.toString$0(0))); + }, + _isSubtype: function(universe, s, sEnv, t, tEnv, isLegacy) { + var sKind, leftTypeVariable, t1, tKind, sBounds, tBounds; + if (s === t) + return true; + if (H.isTopType(t, true)) + return true; + sKind = s._kind; + if (sKind === 4) + return true; + if (H.isTopType(s, true)) + return false; + if (s === type$.Null) + return true; + leftTypeVariable = sKind === 13; + if (leftTypeVariable) { + H.assertHelper(s._kind === 13); + if (H._isSubtype(universe, sEnv[s._primary], sEnv, t, tEnv, true)) + return true; + } + t1 = t._kind; + tKind = t1; + if (sKind === 6) { + H.assertHelper(s._kind === 6); + return H._isSubtype(universe, s._primary, sEnv, t, tEnv, true); + } + if (tKind === 6) { + H.assertHelper(t1 === 6); + t1 = t._primary; + return H._isSubtype(universe, s, sEnv, t1, tEnv, true); + } + if (sKind === 8) { + H.assertHelper(s._kind === 8); + if (!H._isSubtype(universe, s._primary, sEnv, t, tEnv, true)) + return false; + return H._isSubtype(universe, H.Rti__getFutureFromFutureOr(universe, s), sEnv, t, tEnv, true); + } + if (sKind === 7) { + H.assertHelper(s._kind === 7); + t1 = H._isSubtype(universe, s._primary, sEnv, t, tEnv, true); + return t1; + } + if (tKind === 8) { + H.assertHelper(t1 === 8); + if (H._isSubtype(universe, s, sEnv, t._primary, tEnv, true)) + return true; + return H._isSubtype(universe, s, sEnv, H.Rti__getFutureFromFutureOr(universe, t), tEnv, true); + } + if (tKind === 7) { + H.assertHelper(t1 === 7); + t1 = H._isSubtype(universe, s, sEnv, t._primary, tEnv, true); + return t1; + } + if (leftTypeVariable) + return false; + t1 = sKind !== 11; + if ((!t1 || sKind === 12) && t === type$.Function) + return true; + if (tKind === 12) { + if (s === type$.JavaScriptFunction) + return true; + if (sKind !== 12) + return false; + sBounds = H.Rti__getGenericFunctionBounds(s); + tBounds = H.Rti__getGenericFunctionBounds(t); + if (!H.typesEqual(sBounds, tBounds, true)) + return false; + sEnv = sEnv == null ? sBounds : sBounds.concat(sEnv); + tEnv = tEnv == null ? tBounds : tBounds.concat(tEnv); + H.assertHelper(s._kind === 12); + t1 = s._primary; + H.assertHelper(t._kind === 12); + return H._isFunctionSubtype(universe, t1, sEnv, t._primary, tEnv, true); + } + if (tKind === 11) { + if (s === type$.JavaScriptFunction) + return true; + if (t1) + return false; + return H._isFunctionSubtype(universe, s, sEnv, t, tEnv, true); + } + if (sKind === 9) { + if (tKind !== 9) + return false; + return H._isInterfaceSubtype(universe, s, sEnv, t, tEnv, true); + } + return false; + }, + _isFunctionSubtype: function(universe, s, sEnv, t, tEnv, isLegacy) { + var t1, sParameters, tParameters, sRequiredPositional, tRequiredPositional, sRequiredPositionalLength, tRequiredPositionalLength, requiredPositionalDelta, sOptionalPositional, tOptionalPositional, sOptionalPositionalLength, tOptionalPositionalLength, i, sOptionalNamed, tOptionalNamed, sOptionalNamedLength, tOptionalNamedLength, j, tName, sName; + H.assertHelper(s._kind === 11); + H.assertHelper(t._kind === 11); + H.assertHelper(s._kind === 11); + t1 = s._primary; + H.assertHelper(t._kind === 11); + if (!H._isSubtype(universe, t1, sEnv, t._primary, tEnv, true)) + return false; + sParameters = H.Rti__getFunctionParameters(s); + tParameters = H.Rti__getFunctionParameters(t); + sRequiredPositional = sParameters._requiredPositional; + tRequiredPositional = tParameters._requiredPositional; + sRequiredPositionalLength = sRequiredPositional.length; + tRequiredPositionalLength = tRequiredPositional.length; + if (sRequiredPositionalLength > tRequiredPositionalLength) + return false; + requiredPositionalDelta = tRequiredPositionalLength - sRequiredPositionalLength; + sOptionalPositional = sParameters._optionalPositional; + tOptionalPositional = tParameters._optionalPositional; + sOptionalPositionalLength = sOptionalPositional.length; + tOptionalPositionalLength = tOptionalPositional.length; + if (sRequiredPositionalLength + sOptionalPositionalLength < tRequiredPositionalLength + tOptionalPositionalLength) + return false; + for (i = 0; i < sRequiredPositionalLength; ++i) { + t1 = sRequiredPositional[i]; + if (!H._isSubtype(universe, tRequiredPositional[i], tEnv, t1, sEnv, true)) + return false; + } + for (i = 0; i < requiredPositionalDelta; ++i) { + t1 = sOptionalPositional[i]; + if (!H._isSubtype(universe, tRequiredPositional[sRequiredPositionalLength + i], tEnv, t1, sEnv, true)) + return false; + } + for (i = 0; i < tOptionalPositionalLength; ++i) { + t1 = sOptionalPositional[requiredPositionalDelta + i]; + if (!H._isSubtype(universe, tOptionalPositional[i], tEnv, t1, sEnv, true)) + return false; + } + sOptionalNamed = sParameters._optionalNamed; + tOptionalNamed = tParameters._optionalNamed; + sOptionalNamedLength = sOptionalNamed.length; + tOptionalNamedLength = tOptionalNamed.length; + for (i = 0, j = 0; j < tOptionalNamedLength; j += 2) { + tName = tOptionalNamed[j]; + do { + if (i >= sOptionalNamedLength) + return false; + sName = sOptionalNamed[i]; + i += 2; + } while (sName < tName); + if (tName < sName) + return false; + t1 = sOptionalNamed[i - 1]; + if (!H._isSubtype(universe, tOptionalNamed[j + 1], tEnv, t1, sEnv, true)) + return false; + } + return true; + }, + _isInterfaceSubtype: function(universe, s, sEnv, t, tEnv, isLegacy) { + var sName, tName, sArgs, tArgs, $length, i, t1, t2, rule, supertypeArgs; + H.assertHelper(s._kind === 9); + sName = s._primary; + H.assertHelper(t._kind === 9); + tName = t._primary; + if (sName === tName) { + sArgs = H.Rti__getInterfaceTypeArguments(s); + tArgs = H.Rti__getInterfaceTypeArguments(t); + $length = sArgs.length; + H.assertHelper($length === tArgs.length); + for (i = 0; i < $length; ++i) { + t1 = sArgs[i]; + t2 = tArgs[i]; + if (!H._isSubtype(universe, t1, sEnv, t2, tEnv, true)) + return false; + } + return true; + } + rule = H._Universe_findRule(universe, sName); + if (rule == null) + return false; + supertypeArgs = rule[tName]; + if (supertypeArgs == null) + return false; + $length = supertypeArgs.length; + tArgs = H.Rti__getInterfaceTypeArguments(t); + H.assertHelper($length === tArgs.length); + for (i = 0; i < $length; ++i) + if (!H._isSubtype(universe, H._Universe_evalInEnvironment(universe, s, supertypeArgs[i]), sEnv, tArgs[i], tEnv, true)) + return false; + return true; + }, + typeEqual: function(s, t, isLegacy) { + var t1, sKind, t2; + if (s === t) + return true; + if (H.isTopType(s, true)) + return H.isTopType(t, true); + t1 = s._kind; + sKind = t1; + if (sKind !== t._kind) + return false; + switch (sKind) { + case 6: + case 7: + case 8: + return H.typeEqual(s._primary, t._primary, true); + case 9: + H.assertHelper(t1 === 9); + t1 = s._primary; + H.assertHelper(t._kind === 9); + if (t1 !== t._primary) + return false; + return H.typesEqual(H.Rti__getInterfaceTypeArguments(s), H.Rti__getInterfaceTypeArguments(t), true); + case 10: + H.assertHelper(t1 === 10); + t1 = s._primary; + H.assertHelper(t._kind === 10); + return H.typeEqual(t1, t._primary, true) && H.typesEqual(H.Rti__getBindingArguments(s), H.Rti__getBindingArguments(t), true); + case 11: + H.assertHelper(t1 === 11); + t1 = s._primary; + H.assertHelper(t._kind === 11); + if (H.typeEqual(t1, t._primary, true)) { + t1 = H.Rti__getFunctionParameters(s); + t2 = H.Rti__getFunctionParameters(t); + t1 = H.typesEqual(t1._requiredPositional, t2._requiredPositional, true) && H.typesEqual(t1._optionalPositional, t2._optionalPositional, true) && H.namedTypesEqual(t1._optionalNamed, t2._optionalNamed, true); + } else + t1 = false; + return t1; + case 12: + H.assertHelper(t1 === 12); + t1 = s._primary; + H.assertHelper(t._kind === 12); + return H.typeEqual(t1, t._primary, true) && H.typesEqual(H.Rti__getGenericFunctionBounds(s), H.Rti__getGenericFunctionBounds(t), true); + default: + return false; + } + }, + typesEqual: function(sArray, tArray, isLegacy) { + var i, + sLength = sArray.length; + if (sLength !== tArray.length) + return false; + for (i = 0; i < sLength; ++i) + if (!H.typeEqual(sArray[i], tArray[i], true)) + return false; + return true; + }, + namedTypesEqual: function(sArray, tArray, isLegacy) { + var i, t1, + sLength = sArray.length, + tLength = tArray.length; + H.assertHelper((sLength & 1) === 0); + H.assertHelper((tLength & 1) === 0); + if (sLength !== tLength) + return false; + for (i = 0; i < sLength; i += 2) { + if (sArray[i] !== tArray[i]) + return false; + t1 = i + 1; + if (!H.typeEqual(sArray[t1], tArray[t1], true)) + return false; + } + return true; + }, + isLegacyTopType: function(t) { + return H.isTopType(t, true); + }, + isTopType: function(t, isLegacy) { + var t1, kind; + if (t === type$.Object) + return true; + t1 = t._kind; + kind = t1; + if (kind !== 2) + if (kind !== 3) + if (kind !== 4) + if (kind !== 5) + if (kind === 8) { + H.assertHelper(t1 === 8); + t1 = H.isTopType(t._primary, true); + } else + t1 = false; + else + t1 = true; + else + t1 = true; + else + t1 = true; + else + t1 = true; + return t1; + }, + _Utils_objectAssign: function(o, other) { + var i, key, + keys = Object.keys(other), + $length = keys.length; + for (i = 0; i < $length; ++i) { + key = keys[i]; + o[key] = other[key]; + } + }, + Rti: function Rti(t0, t1, t2) { + var _ = this; + _._as = t0; + _._check = t1; + _._is = t2; + _._cachedRuntimeType = _._specializedTestResource = _._precomputed1 = null; + _._kind = 0; + _._canonicalRecipe = _._bindCache = _._evalCache = _._rest = _._primary = null; + }, + _FunctionParameters: function _FunctionParameters() { + this._optionalNamed = this._optionalPositional = this._requiredPositional = null; + }, + _Type: function _Type(t0) { + this._rti = t0; + this._hashCode = null; + }, + _Error: function _Error() { + }, + _CastError: function _CastError(t0) { + this._message = t0; + }, + _TypeError: function _TypeError(t0) { + this._message = t0; + }, + extractKeys: function(victim) { + return J.JSArray_JSArray$markFixed(victim ? Object.keys(victim) : [], type$.dynamic); + }, + unmangleGlobalNameIfPreservedAnyways: function($name) { + return init.mangledGlobalNames[$name]; + }, + printString: function(string) { + if (typeof dartPrint == "function") { + dartPrint(string); + return; + } + if (typeof console == "object" && typeof console.log != "undefined") { + console.log(string); + return; + } + if (typeof window == "object") + return; + if (typeof print == "function") { + print(string); + return; + } + throw "Unable to print message: " + String(string); + } + }, + J = { + makeDispatchRecord: function(interceptor, proto, extension, indexability) { + return {i: interceptor, p: proto, e: extension, x: indexability}; + }, + getNativeInterceptor: function(object) { + var proto, objectProto, $constructor, interceptor, + record = object[init.dispatchPropertyName]; + if (record == null) + if ($.initNativeDispatchFlag == null) { + H.initNativeDispatch(); + record = object[init.dispatchPropertyName]; + } + if (record != null) { + proto = record.p; + if (false === proto) + return record.i; + if (true === proto) + return object; + objectProto = Object.getPrototypeOf(object); + if (proto === objectProto) + return record.i; + if (record.e === objectProto) + throw H.wrapException(P.UnimplementedError$("Return interceptor for " + H.S(proto(object, record)))); + } + $constructor = object.constructor; + interceptor = $constructor == null ? null : $constructor[$.$get$JS_INTEROP_INTERCEPTOR_TAG()]; + if (interceptor != null) + return interceptor; + interceptor = H.lookupAndCacheInterceptor(object); + if (interceptor != null) + return interceptor; + if (typeof object == "function") + return C.JavaScriptFunction_methods; + proto = Object.getPrototypeOf(object); + if (proto == null) + return C.PlainJavaScriptObject_methods; + if (proto === Object.prototype) + return C.PlainJavaScriptObject_methods; + if (typeof $constructor == "function") { + Object.defineProperty($constructor, $.$get$JS_INTEROP_INTERCEPTOR_TAG(), {value: C.UnknownJavaScriptObject_methods, enumerable: false, writable: true, configurable: true}); + return C.UnknownJavaScriptObject_methods; + } + return C.UnknownJavaScriptObject_methods; + }, + JSArray_JSArray$fixed: function($length, $E) { + if (!H._isInt($length)) + throw H.wrapException(P.ArgumentError$value($length, "length", "is not an integer")); + if ($length < 0 || $length > 4294967295) + throw H.wrapException(P.RangeError$range($length, 0, 4294967295, "length", null)); + return J.JSArray_JSArray$markFixed(new Array($length), $E); + }, + JSArray_JSArray$markFixed: function(allocation, $E) { + return J.JSArray_markFixedList(H.setRuntimeTypeInfo(allocation, $E._eval$1("JSArray<0>"))); + }, + JSArray_markFixedList: function(list) { + list.fixed$length = Array; + return list; + }, + JSString__isWhitespace: function(codeUnit) { + if (codeUnit < 256) + switch (codeUnit) { + case 9: + case 10: + case 11: + case 12: + case 13: + case 32: + case 133: + case 160: + return true; + default: + return false; + } + switch (codeUnit) { + case 5760: + case 8192: + case 8193: + case 8194: + case 8195: + case 8196: + case 8197: + case 8198: + case 8199: + case 8200: + case 8201: + case 8202: + case 8232: + case 8233: + case 8239: + case 8287: + case 12288: + case 65279: + return true; + default: + return false; + } + }, + JSString__skipLeadingWhitespace: function(string, index) { + var t1, codeUnit; + for (t1 = string.length; index < t1;) { + codeUnit = C.JSString_methods._codeUnitAt$1(string, index); + if (codeUnit !== 32 && codeUnit !== 13 && !J.JSString__isWhitespace(codeUnit)) + break; + ++index; + } + return index; + }, + JSString__skipTrailingWhitespace: function(string, index) { + var index0, codeUnit; + for (; index > 0; index = index0) { + index0 = index - 1; + codeUnit = C.JSString_methods.codeUnitAt$1(string, index0); + if (codeUnit !== 32 && codeUnit !== 13 && !J.JSString__isWhitespace(codeUnit)) + break; + } + return index; + }, + getInterceptor$: function(receiver) { + if (typeof receiver == "number") { + if (Math.floor(receiver) == receiver) + return J.JSInt.prototype; + return J.JSDouble.prototype; + } + if (typeof receiver == "string") + return J.JSString.prototype; + if (receiver == null) + return J.JSNull.prototype; + if (typeof receiver == "boolean") + return J.JSBool.prototype; + if (receiver.constructor == Array) + return J.JSArray.prototype; + if (typeof receiver != "object") { + if (typeof receiver == "function") + return J.JavaScriptFunction.prototype; + return receiver; + } + if (receiver instanceof P.Object) + return receiver; + return J.getNativeInterceptor(receiver); + }, + getInterceptor$ansx: function(receiver) { + if (typeof receiver == "number") + return J.JSNumber.prototype; + if (typeof receiver == "string") + return J.JSString.prototype; + if (receiver == null) + return receiver; + if (receiver.constructor == Array) + return J.JSArray.prototype; + if (typeof receiver != "object") { + if (typeof receiver == "function") + return J.JavaScriptFunction.prototype; + return receiver; + } + if (receiver instanceof P.Object) + return receiver; + return J.getNativeInterceptor(receiver); + }, + getInterceptor$asx: function(receiver) { + if (typeof receiver == "string") + return J.JSString.prototype; + if (receiver == null) + return receiver; + if (receiver.constructor == Array) + return J.JSArray.prototype; + if (typeof receiver != "object") { + if (typeof receiver == "function") + return J.JavaScriptFunction.prototype; + return receiver; + } + if (receiver instanceof P.Object) + return receiver; + return J.getNativeInterceptor(receiver); + }, + getInterceptor$ax: function(receiver) { + if (receiver == null) + return receiver; + if (receiver.constructor == Array) + return J.JSArray.prototype; + if (typeof receiver != "object") { + if (typeof receiver == "function") + return J.JavaScriptFunction.prototype; + return receiver; + } + if (receiver instanceof P.Object) + return receiver; + return J.getNativeInterceptor(receiver); + }, + getInterceptor$n: function(receiver) { + if (typeof receiver == "number") + return J.JSNumber.prototype; + if (receiver == null) + return receiver; + if (!(receiver instanceof P.Object)) + return J.UnknownJavaScriptObject.prototype; + return receiver; + }, + getInterceptor$s: function(receiver) { + if (typeof receiver == "string") + return J.JSString.prototype; + if (receiver == null) + return receiver; + if (!(receiver instanceof P.Object)) + return J.UnknownJavaScriptObject.prototype; + return receiver; + }, + getInterceptor$x: function(receiver) { + if (receiver == null) + return receiver; + if (typeof receiver != "object") { + if (typeof receiver == "function") + return J.JavaScriptFunction.prototype; + return receiver; + } + if (receiver instanceof P.Object) + return receiver; + return J.getNativeInterceptor(receiver); + }, + get$first$ax: function(receiver) { + return J.getInterceptor$ax(receiver).get$first(receiver); + }, + get$hashCode$: function(receiver) { + return J.getInterceptor$(receiver).get$hashCode(receiver); + }, + get$isEmpty$asx: function(receiver) { + return J.getInterceptor$asx(receiver).get$isEmpty(receiver); + }, + get$iterator$ax: function(receiver) { + return J.getInterceptor$ax(receiver).get$iterator(receiver); + }, + get$last$ax: function(receiver) { + return J.getInterceptor$ax(receiver).get$last(receiver); + }, + get$length$asx: function(receiver) { + return J.getInterceptor$asx(receiver).get$length(receiver); + }, + get$message$x: function(receiver) { + return J.getInterceptor$x(receiver).get$message(receiver); + }, + get$runtimeType$: function(receiver) { + return J.getInterceptor$(receiver).get$runtimeType(receiver); + }, + get$startsWith$s: function(receiver) { + return J.getInterceptor$s(receiver).get$startsWith(receiver); + }, + $add$ansx: function(receiver, a0) { + if (typeof receiver == "number" && typeof a0 == "number") + return receiver + a0; + return J.getInterceptor$ansx(receiver).$add(receiver, a0); + }, + $eq$: function(receiver, a0) { + if (receiver == null) + return a0 == null; + if (typeof receiver != "object") + return a0 != null && receiver === a0; + return J.getInterceptor$(receiver).$eq(receiver, a0); + }, + $index$asx: function(receiver, a0) { + if (typeof a0 === "number") + if (receiver.constructor == Array || typeof receiver == "string" || H.isJsIndexable(receiver, receiver[init.dispatchPropertyName])) + if (a0 >>> 0 === a0 && a0 < receiver.length) + return receiver[a0]; + return J.getInterceptor$asx(receiver).$index(receiver, a0); + }, + $indexSet$ax: function(receiver, a0, a1) { + return J.getInterceptor$ax(receiver).$indexSet(receiver, a0, a1); + }, + _codeUnitAt$1$s: function(receiver, a0) { + return J.getInterceptor$s(receiver)._codeUnitAt$1(receiver, a0); + }, + _removeEventListener$3$x: function(receiver, a0, a1, a2) { + return J.getInterceptor$x(receiver)._removeEventListener$3(receiver, a0, a1, a2); + }, + addEventListener$3$x: function(receiver, a0, a1, a2) { + return J.getInterceptor$x(receiver).addEventListener$3(receiver, a0, a1, a2); + }, + allMatches$1$s: function(receiver, a0) { + return J.getInterceptor$s(receiver).allMatches$1(receiver, a0); + }, + allMatches$2$s: function(receiver, a0, a1) { + return J.getInterceptor$s(receiver).allMatches$2(receiver, a0, a1); + }, + codeUnitAt$1$s: function(receiver, a0) { + return J.getInterceptor$s(receiver).codeUnitAt$1(receiver, a0); + }, + contains$1$asx: function(receiver, a0) { + return J.getInterceptor$asx(receiver).contains$1(receiver, a0); + }, + elementAt$1$ax: function(receiver, a0) { + return J.getInterceptor$ax(receiver).elementAt$1(receiver, a0); + }, + endsWith$1$s: function(receiver, a0) { + return J.getInterceptor$s(receiver).endsWith$1(receiver, a0); + }, + fillRange$3$ax: function(receiver, a0, a1, a2) { + return J.getInterceptor$ax(receiver).fillRange$3(receiver, a0, a1, a2); + }, + map$1$1$ax: function(receiver, a0, $T1) { + return J.getInterceptor$ax(receiver).map$1$1(receiver, a0, $T1); + }, + matchAsPrefix$2$s: function(receiver, a0, a1) { + return J.getInterceptor$s(receiver).matchAsPrefix$2(receiver, a0, a1); + }, + padRight$1$s: function(receiver, a0) { + return J.getInterceptor$s(receiver).padRight$1(receiver, a0); + }, + replaceRange$3$asx: function(receiver, a0, a1, a2) { + return J.getInterceptor$asx(receiver).replaceRange$3(receiver, a0, a1, a2); + }, + startsWith$1$s: function(receiver, a0) { + return J.getInterceptor$s(receiver).startsWith$1(receiver, a0); + }, + startsWith$2$s: function(receiver, a0, a1) { + return J.getInterceptor$s(receiver).startsWith$2(receiver, a0, a1); + }, + substring$1$s: function(receiver, a0) { + return J.getInterceptor$s(receiver).substring$1(receiver, a0); + }, + substring$2$s: function(receiver, a0, a1) { + return J.getInterceptor$s(receiver).substring$2(receiver, a0, a1); + }, + toRadixString$1$n: function(receiver, a0) { + return J.getInterceptor$n(receiver).toRadixString$1(receiver, a0); + }, + toSet$0$ax: function(receiver) { + return J.getInterceptor$ax(receiver).toSet$0(receiver); + }, + toString$0$: function(receiver) { + return J.getInterceptor$(receiver).toString$0(receiver); + }, + trim$0$s: function(receiver) { + return J.getInterceptor$s(receiver).trim$0(receiver); + }, + Interceptor: function Interceptor() { + }, + JSBool: function JSBool() { + }, + JSNull: function JSNull() { + }, + JSObject: function JSObject() { + }, + JavaScriptObject: function JavaScriptObject() { + }, + PlainJavaScriptObject: function PlainJavaScriptObject() { + }, + UnknownJavaScriptObject: function UnknownJavaScriptObject() { + }, + JavaScriptFunction: function JavaScriptFunction() { + }, + JSArray: function JSArray(t0) { + this.$ti = t0; + }, + JSUnmodifiableArray: function JSUnmodifiableArray(t0) { + this.$ti = t0; + }, + ArrayIterator: function ArrayIterator(t0, t1, t2) { + var _ = this; + _._iterable = t0; + _._length = t1; + _._index = 0; + _._current = null; + _.$ti = t2; + }, + JSNumber: function JSNumber() { + }, + JSInt: function JSInt() { + }, + JSDouble: function JSDouble() { + }, + JSString: function JSString() { + } + }, + P = { + _AsyncRun__initializeScheduleImmediate: function() { + var div, span, t1 = {}; + if (self.scheduleImmediate != null) + return P.async__AsyncRun__scheduleImmediateJsOverride$closure(); + if (self.MutationObserver != null && self.document != null) { + div = self.document.createElement("div"); + span = self.document.createElement("span"); + t1.storedCallback = null; + new self.MutationObserver(H.convertDartClosureToJS(new P._AsyncRun__initializeScheduleImmediate_internalCallback(t1), 1)).observe(div, {childList: true}); + return new P._AsyncRun__initializeScheduleImmediate_closure(t1, div, span); + } else if (self.setImmediate != null) + return P.async__AsyncRun__scheduleImmediateWithSetImmediate$closure(); + return P.async__AsyncRun__scheduleImmediateWithTimer$closure(); + }, + _AsyncRun__scheduleImmediateJsOverride: function(callback) { + self.scheduleImmediate(H.convertDartClosureToJS(new P._AsyncRun__scheduleImmediateJsOverride_internalCallback(type$.void_Function._check(callback)), 0)); + }, + _AsyncRun__scheduleImmediateWithSetImmediate: function(callback) { + self.setImmediate(H.convertDartClosureToJS(new P._AsyncRun__scheduleImmediateWithSetImmediate_internalCallback(type$.void_Function._check(callback)), 0)); + }, + _AsyncRun__scheduleImmediateWithTimer: function(callback) { + P.Timer__createTimer(C.Duration_0, type$.void_Function._check(callback)); + }, + Timer__createTimer: function(duration, callback) { + var milliseconds = C.JSInt_methods._tdivFast$1(duration._duration, 1000); + return P._TimerImpl$(milliseconds < 0 ? 0 : milliseconds, callback); + }, + _TimerImpl$: function(milliseconds, callback) { + var t1 = new P._TimerImpl(true); + t1._TimerImpl$2(milliseconds, callback); + return t1; + }, + _TimerImpl$periodic: function(milliseconds, callback) { + var t1 = new P._TimerImpl(false); + t1._TimerImpl$periodic$2(milliseconds, callback); + return t1; + }, + _makeAsyncAwaitCompleter: function($T) { + return new P._AsyncAwaitCompleter(new P._Future($.Zone__current, $T._eval$1("_Future<0>")), $T._eval$1("_AsyncAwaitCompleter<0>")); + }, + _asyncStartSync: function(bodyFunction, completer) { + bodyFunction.call$2(0, null); + completer.isSync = true; + return completer._future; + }, + _asyncAwait: function(object, bodyFunction) { + P._awaitOnObject(object, bodyFunction); + }, + _asyncReturn: function(object, completer) { + completer.complete$1(object); + }, + _asyncRethrow: function(object, completer) { + completer.completeError$2(H.unwrapException(object), H.getTraceFromException(object)); + }, + _awaitOnObject: function(object, bodyFunction) { + var t1, future, + thenCallback = new P._awaitOnObject_closure(bodyFunction), + errorCallback = new P._awaitOnObject_closure0(bodyFunction); + if (object instanceof P._Future) + object._thenAwait$1$2(thenCallback, errorCallback, type$.dynamic); + else { + t1 = type$.dynamic; + if (type$.Future_dynamic._is(object)) + object.then$1$2$onError(thenCallback, errorCallback, t1); + else { + future = new P._Future($.Zone__current, type$._Future_dynamic); + future._state = 4; + future._resultOrListeners = object; + future._thenAwait$1$2(thenCallback, null, t1); + } + } + }, + _wrapJsFunctionForAsync: function($function) { + var $protected = function(fn, ERROR) { + return function(errorCode, result) { + while (true) + try { + fn(errorCode, result); + break; + } catch (error) { + result = error; + errorCode = ERROR; + } + }; + }($function, 1); + return $.Zone__current.registerBinaryCallback$3$1(new P._wrapJsFunctionForAsync_closure($protected), type$.Null, type$.int, type$.dynamic); + }, + Future_Future: function(computation, $T) { + var result = new P._Future($.Zone__current, $T._eval$1("_Future<0>")); + P.Timer_Timer(C.Duration_0, new P.Future_Future_closure(result, computation)); + return result; + }, + Future_Future$microtask: function(computation, $T) { + var result = new P._Future($.Zone__current, $T._eval$1("_Future<0>")); + P.scheduleMicrotask(new P.Future_Future$microtask_closure(result, computation)); + return result; + }, + Future_Future$sync: function(computation, $T) { + var result, error, stackTrace, future, replacement, t1, t2, exception; + try { + result = computation.call$0(); + if ($T._eval$1("Future<0>")._is(result)) + return result; + else { + t1 = $T._check(result); + t2 = new P._Future($.Zone__current, $T._eval$1("_Future<0>")); + t2._state = 4; + t2._resultOrListeners = t1; + return t2; + } + } catch (exception) { + error = H.unwrapException(exception); + stackTrace = H.getTraceFromException(exception); + t1 = $.Zone__current; + future = new P._Future(t1, $T._eval$1("_Future<0>")); + replacement = t1.errorCallback$2(error, stackTrace); + if (replacement != null) { + t1 = replacement.error; + if (t1 == null) + t1 = new P.NullThrownError(); + future._asyncCompleteError$2(t1, replacement.stackTrace); + } else + future._asyncCompleteError$2(error, stackTrace); + return future; + } + }, + Future_Future$error: function(error, stackTrace, $T) { + var replacement, + t1 = $.Zone__current; + if (t1 !== C.C__RootZone) { + replacement = t1.errorCallback$2(error, stackTrace); + if (replacement != null) { + error = replacement.error; + if (error == null) + error = new P.NullThrownError(); + stackTrace = replacement.stackTrace; + } + } + t1 = new P._Future($.Zone__current, $T._eval$1("_Future<0>")); + t1._asyncCompleteError$2(error, stackTrace); + return t1; + }, + Future_wait: function(futures, eagerError, $T) { + var handleError, future, pos, e, st, t2, t3, _i, t4, exception, _box_0 = {}, cleanUp = null, + t1 = $T._eval$1("_Future<List<0>>"), + result = new P._Future($.Zone__current, t1); + _box_0.values = null; + _box_0.remaining = 0; + _box_0.stackTrace = _box_0.error = null; + handleError = new P.Future_wait_handleError(_box_0, cleanUp, true, result); + try { + for (t2 = futures.length, t3 = type$.Null, _i = 0, t4 = 0; _i < futures.length; futures.length === t2 || (0, H.throwConcurrentModificationError)(futures), ++_i) { + future = futures[_i]; + pos = t4; + future.then$1$2$onError(new P.Future_wait_closure(_box_0, pos, result, cleanUp, true, $T), handleError, t3); + t4 = ++_box_0.remaining; + } + if (t4 === 0) { + t1 = new P._Future($.Zone__current, t1); + t1._asyncComplete$1(C.List_empty1); + return t1; + } + t1 = new Array(t4); + t1.fixed$length = Array; + _box_0.values = H.setRuntimeTypeInfo(t1, $T._eval$1("JSArray<0>")); + } catch (exception) { + e = H.unwrapException(exception); + st = H.getTraceFromException(exception); + t1 = P.Future_Future$error(e, st, $T._eval$1("List<0>")); + return t1; + } + return result; + }, + Future_forEach: function(elements, action, $T) { + return P.Future_doWhile(new P.Future_forEach_closure(new J.ArrayIterator(elements, 0, H._arrayInstanceType(elements)._eval$1("ArrayIterator<1>")), action)); + }, + Future__kTrue: function(_) { + return true; + }, + Future_doWhile: function(action) { + var nextIteration, t1 = {}, + t2 = $.Zone__current, + doneSignal = new P._Future(t2, type$._Future_dynamic); + t1.nextIteration = null; + nextIteration = t2.bindUnaryCallbackGuarded$1$1(new P.Future_doWhile_closure(t1, action, doneSignal), type$.bool); + t1.nextIteration = nextIteration; + nextIteration.call$1(true); + return doneSignal; + }, + _completeWithErrorCallback: function(result, error, stackTrace) { + var replacement = $.Zone__current.errorCallback$2(error, stackTrace); + if (replacement != null) { + error = replacement.error; + if (error == null) + error = new P.NullThrownError(); + stackTrace = replacement.stackTrace; + } + result._completeError$2(error, stackTrace); + }, + _Future$zoneValue: function(value, _zone, $T) { + var t1 = new P._Future(_zone, $T._eval$1("_Future<0>")); + $T._check(value); + t1._state = 4; + t1._resultOrListeners = value; + return t1; + }, + _Future__chainForeignFuture: function(source, target) { + var e, s, exception; + H.assertHelper(target._state < 4); + H.assertHelper(!(source instanceof P._Future)); + H.assertHelper(target._state === 0); + target._state = 1; + try { + source.then$1$2$onError(new P._Future__chainForeignFuture_closure(target), new P._Future__chainForeignFuture_closure0(target), type$.Null); + } catch (exception) { + e = H.unwrapException(exception); + s = H.getTraceFromException(exception); + P.scheduleMicrotask(new P._Future__chainForeignFuture_closure1(target, e, s)); + } + }, + _Future__chainCoreFuture: function(source, target) { + var t1, t2, t3, listeners; + H.assertHelper(target._state <= 1); + for (t1 = type$._Future_dynamic; t2 = source._state, t3 = t2 === 2, t3;) { + H.assertHelper(t3); + source = t1._check(source._resultOrListeners); + } + if (t2 >= 4) { + listeners = target._removeListeners$0(); + target._cloneResult$1(source); + P._Future__propagateToListeners(target, listeners); + } else { + listeners = type$._FutureListener_dynamic_dynamic._check(target._resultOrListeners); + H.assertHelper(target._state <= 1); + target._state = 2; + target._resultOrListeners = source; + source._prependListeners$1(listeners); + } + }, + _Future__propagateToListeners: function(source, listeners) { + var t2, t3, t4, _box_0, hasError, asyncError, listeners0, sourceResult, t5, t6, zone, previous, oldZone, current, result, _box_1 = {}, + t1 = _box_1.source = source; + for (t2 = type$.AsyncError, t3 = type$._FutureListener_dynamic_dynamic, t4 = type$.Future_dynamic; true;) { + _box_0 = {}; + H.assertHelper(t1._state >= 4); + t1 = _box_1.source; + hasError = t1._state === 8; + if (listeners == null) { + if (hasError) { + asyncError = t2._check(t1._resultOrListeners); + t1._zone.handleUncaughtError$2(asyncError.error, asyncError.stackTrace); + } + return; + } + for (; listeners0 = listeners._nextListener, listeners0 != null; listeners = listeners0) { + listeners._nextListener = null; + P._Future__propagateToListeners(_box_1.source, listeners); + } + t1 = _box_1.source; + sourceResult = t1._resultOrListeners; + _box_0.listenerHasError = hasError; + _box_0.listenerValueOrError = sourceResult; + t5 = !hasError; + if (t5) { + t6 = listeners.state; + t6 = (t6 & 1) !== 0 || (t6 & 15) === 8; + } else + t6 = true; + if (t6) { + t6 = listeners.result; + zone = t6._zone; + if (hasError) { + t1 = t1._zone; + t1 = !(t1 === zone || t1.get$errorZone() === zone.get$errorZone()); + } else + t1 = false; + if (t1) { + t1 = _box_1.source; + H.assertHelper(t1._state === 8); + asyncError = t2._check(t1._resultOrListeners); + _box_1.source._zone.handleUncaughtError$2(asyncError.error, asyncError.stackTrace); + return; + } + t1 = $.Zone__current; + if (t1 !== zone) { + H.assertHelper(zone !== t1); + previous = $.Zone__current; + $.Zone__current = zone; + oldZone = previous; + } else + oldZone = null; + t1 = listeners.state; + if ((t1 & 15) === 8) + new P._Future__propagateToListeners_handleWhenCompleteCallback(_box_1, _box_0, listeners, hasError).call$0(); + else if (t5) { + if ((t1 & 1) !== 0) + new P._Future__propagateToListeners_handleValueCallback(_box_0, listeners, sourceResult).call$0(); + } else if ((t1 & 2) !== 0) + new P._Future__propagateToListeners_handleError(_box_1, _box_0, listeners).call$0(); + if (oldZone != null) + $.Zone__current = oldZone; + t1 = _box_0.listenerValueOrError; + if (t4._is(t1)) { + if (t1._state >= 4) { + H.assertHelper(t6._state < 4); + current = t3._check(t6._resultOrListeners); + t6._resultOrListeners = null; + listeners = t6._reverseListeners$1(current); + H.assertHelper(t6._state < 4); + H.assertHelper(t1._state >= 4); + t6._state = t1._state; + t6._resultOrListeners = t1._resultOrListeners; + _box_1.source = t1; + continue; + } else + P._Future__chainCoreFuture(t1, t6); + return; + } + } + result = listeners.result; + H.assertHelper(result._state < 4); + current = t3._check(result._resultOrListeners); + result._resultOrListeners = null; + listeners = result._reverseListeners$1(current); + t1 = _box_0.listenerHasError; + t5 = _box_0.listenerValueOrError; + t6 = result._state >= 4; + if (!t1) { + result.$ti._precomputed1._check(t5); + H.assertHelper(!t6); + result._state = 4; + result._resultOrListeners = t5; + } else { + t2._check(t5); + H.assertHelper(!t6); + result._state = 8; + result._resultOrListeners = t5; + } + _box_1.source = result; + t1 = result; + } + }, + _registerErrorHandler: function(errorHandler, zone) { + if (type$.dynamic_Function_Object_StackTrace._is(errorHandler)) + return zone.registerBinaryCallback$3$1(errorHandler, type$.dynamic, type$.Object, type$.StackTrace); + if (type$.dynamic_Function_Object._is(errorHandler)) + return zone.registerUnaryCallback$2$1(errorHandler, type$.dynamic, type$.Object); + throw H.wrapException(P.ArgumentError$value(errorHandler, "onError", "Error handler must accept one Object or one Object and a StackTrace as arguments, and return a a valid result")); + }, + _microtaskLoop: function() { + var t1, t2; + for (; t1 = $._nextCallback, t1 != null;) { + $._lastPriorityCallback = null; + t2 = t1.next; + $._nextCallback = t2; + if (t2 == null) + $._lastCallback = null; + t1.callback.call$0(); + } + }, + _startMicrotaskLoop: function() { + $._isInCallbackLoop = true; + try { + P._microtaskLoop(); + } finally { + $._lastPriorityCallback = null; + $._isInCallbackLoop = false; + if ($._nextCallback != null) + $.$get$_AsyncRun__scheduleImmediateClosure().call$1(P.async___startMicrotaskLoop$closure()); + } + }, + _scheduleAsyncCallback: function(callback) { + var newEntry = new P._AsyncCallbackEntry(callback); + if ($._nextCallback == null) { + $._nextCallback = $._lastCallback = newEntry; + if (!$._isInCallbackLoop) + $.$get$_AsyncRun__scheduleImmediateClosure().call$1(P.async___startMicrotaskLoop$closure()); + } else + $._lastCallback = $._lastCallback.next = newEntry; + }, + _schedulePriorityAsyncCallback: function(callback) { + var entry, t2, + t1 = $._nextCallback; + if (t1 == null) { + P._scheduleAsyncCallback(callback); + $._lastPriorityCallback = $._lastCallback; + return; + } + entry = new P._AsyncCallbackEntry(callback); + t2 = $._lastPriorityCallback; + if (t2 == null) { + entry.next = t1; + $._nextCallback = $._lastPriorityCallback = entry; + } else { + entry.next = t2.next; + $._lastPriorityCallback = t2.next = entry; + if (entry.next == null) + $._lastCallback = entry; + } + }, + scheduleMicrotask: function(callback) { + var t1, _null = null, + currentZone = $.Zone__current; + if (C.C__RootZone === currentZone) { + P._rootScheduleMicrotask(_null, _null, C.C__RootZone, callback); + return; + } + if (C.C__RootZone === currentZone.get$_scheduleMicrotask().zone) + t1 = C.C__RootZone.get$errorZone() === currentZone.get$errorZone(); + else + t1 = false; + if (t1) { + P._rootScheduleMicrotask(_null, _null, currentZone, currentZone.registerCallback$1$1(callback, type$.void)); + return; + } + t1 = $.Zone__current; + t1.scheduleMicrotask$1(t1.bindCallbackGuarded$1(callback)); + }, + Stream_Stream$fromFuture: function(future, $T) { + var _null = null, + t1 = $T._eval$1("_SyncStreamController<0>"), + controller = new P._SyncStreamController(_null, _null, _null, _null, t1); + future.then$1$2$onError(new P.Stream_Stream$fromFuture_closure(controller, $T), new P.Stream_Stream$fromFuture_closure0(controller), type$.Null); + return new P._ControllerStream(controller, t1._eval$1("_ControllerStream<1>")); + }, + Stream_Stream$fromIterable: function(elements, $T) { + return new P._GeneratedStreamImpl(new P.Stream_Stream$fromIterable_closure(elements, $T), $T._eval$1("_GeneratedStreamImpl<0>")); + }, + StreamIterator_StreamIterator: function(stream, $T) { + if (stream == null) + H.throwExpression(P.ArgumentError$notNull("stream")); + return new P._StreamIterator($T._eval$1("_StreamIterator<0>")); + }, + StreamController_StreamController: function(onCancel, onListen, sync, $T) { + var _null = null; + return sync ? new P._SyncStreamController(onListen, _null, _null, onCancel, $T._eval$1("_SyncStreamController<0>")) : new P._AsyncStreamController(onListen, _null, _null, onCancel, $T._eval$1("_AsyncStreamController<0>")); + }, + _runGuarded: function(notificationHandler) { + var e, s, exception; + if (notificationHandler == null) + return; + try { + notificationHandler.call$0(); + } catch (exception) { + e = H.unwrapException(exception); + s = H.getTraceFromException(exception); + $.Zone__current.handleUncaughtError$2(e, s); + } + }, + _AddStreamState_makeErrorHandler: function(controller) { + return new P._AddStreamState_makeErrorHandler_closure(controller); + }, + _BufferingStreamSubscription$: function(onData, onError, onDone, cancelOnError, $T) { + var t1 = $.Zone__current, + t2 = cancelOnError ? 1 : 0; + t2 = new P._BufferingStreamSubscription(t1, t2, $T._eval$1("_BufferingStreamSubscription<0>")); + t2._BufferingStreamSubscription$4(onData, onError, onDone, cancelOnError, $T); + return t2; + }, + _nullDataHandler: function(value) { + }, + _nullErrorHandler: function(error, stackTrace) { + type$.StackTrace._check(stackTrace); + $.Zone__current.handleUncaughtError$2(error, stackTrace); + }, + _nullDoneHandler: function() { + }, + _runUserCode: function(userCode, onSuccess, onError, $T) { + var e, s, replacement, error, stackTrace, exception, error0; + try { + onSuccess.call$1(userCode.call$0()); + } catch (exception) { + e = H.unwrapException(exception); + s = H.getTraceFromException(exception); + replacement = $.Zone__current.errorCallback$2(e, s); + if (replacement == null) + onError.call$2(e, s); + else { + error0 = replacement.error; + error = error0 == null ? new P.NullThrownError() : error0; + stackTrace = replacement.stackTrace; + onError.call$2(error, stackTrace); + } + } + }, + _cancelAndError: function(subscription, future, error, stackTrace) { + var cancelFuture = subscription.cancel$0(); + if (cancelFuture != null && cancelFuture !== $.$get$Future__nullFuture()) + cancelFuture.whenComplete$1(new P._cancelAndError_closure(future, error, stackTrace)); + else + future._completeError$2(error, stackTrace); + }, + _cancelAndErrorClosure: function(subscription, future) { + return new P._cancelAndErrorClosure_closure(subscription, future); + }, + _cancelAndValue: function(subscription, future, value) { + var cancelFuture = subscription.cancel$0(); + if (cancelFuture != null && cancelFuture !== $.$get$Future__nullFuture()) + cancelFuture.whenComplete$1(new P._cancelAndValue_closure(future, value)); + else + future._complete$1(value); + }, + Timer_Timer: function(duration, callback) { + var t1 = $.Zone__current; + if (t1 === C.C__RootZone) + return t1.createTimer$2(duration, callback); + return t1.createTimer$2(duration, t1.bindCallbackGuarded$1(callback)); + }, + _ZoneSpecification$: function(createPeriodicTimer, createTimer, errorCallback, fork, handleUncaughtError, $print, registerBinaryCallback, registerCallback, registerUnaryCallback, run, runBinary, runUnary, scheduleMicrotask) { + return new P._ZoneSpecification(handleUncaughtError, run, runUnary, runBinary, registerCallback, registerUnaryCallback, registerBinaryCallback, errorCallback, scheduleMicrotask, createTimer, createPeriodicTimer, $print, fork); + }, + Zone__enter: function(zone) { + var previous; + H.assertHelper(zone != null); + H.assertHelper(zone !== $.Zone__current); + previous = $.Zone__current; + $.Zone__current = zone; + return previous; + }, + _parentDelegate: function(zone) { + if (zone.get$parent(zone) == null) + return null; + return zone.get$parent(zone).get$_delegate(); + }, + _rootHandleUncaughtError: function($self, $parent, zone, error, stackTrace) { + var t1 = {}; + t1.error = error; + P._schedulePriorityAsyncCallback(new P._rootHandleUncaughtError_closure(t1, type$.StackTrace._check(stackTrace))); + }, + _rootRun: function($self, $parent, zone, f, $R) { + var old, + t1 = type$.Zone; + t1._check($self); + type$.ZoneDelegate._check($parent); + t1._check(zone); + $R._eval$1("0()")._check(f); + if ($.Zone__current === zone) + return f.call$0(); + old = P.Zone__enter(zone); + try { + t1 = f.call$0(); + return t1; + } finally { + t1 = old; + H.assertHelper(t1 != null); + $.Zone__current = t1; + } + }, + _rootRunUnary: function($self, $parent, zone, f, arg, $R, $T) { + var old, + t1 = type$.Zone; + t1._check($self); + type$.ZoneDelegate._check($parent); + t1._check(zone); + $R._eval$1("@<0>")._bind$1($T)._eval$1("1(2)")._check(f); + $T._check(arg); + if ($.Zone__current === zone) + return f.call$1(arg); + old = P.Zone__enter(zone); + try { + t1 = f.call$1(arg); + return t1; + } finally { + t1 = old; + H.assertHelper(t1 != null); + $.Zone__current = t1; + } + }, + _rootRunBinary: function($self, $parent, zone, f, arg1, arg2, $R, T1, T2) { + var old, + t1 = type$.Zone; + t1._check($self); + type$.ZoneDelegate._check($parent); + t1._check(zone); + $R._eval$1("@<0>")._bind$1(T1)._bind$1(T2)._eval$1("1(2,3)")._check(f); + T1._check(arg1); + T2._check(arg2); + if ($.Zone__current === zone) + return f.call$2(arg1, arg2); + old = P.Zone__enter(zone); + try { + t1 = f.call$2(arg1, arg2); + return t1; + } finally { + t1 = old; + H.assertHelper(t1 != null); + $.Zone__current = t1; + } + }, + _rootRegisterCallback: function($self, $parent, zone, f, $R) { + return $R._eval$1("0()")._check(f); + }, + _rootRegisterUnaryCallback: function($self, $parent, zone, f, $R, $T) { + return $R._eval$1("@<0>")._bind$1($T)._eval$1("1(2)")._check(f); + }, + _rootRegisterBinaryCallback: function($self, $parent, zone, f, $R, T1, T2) { + return $R._eval$1("@<0>")._bind$1(T1)._bind$1(T2)._eval$1("1(2,3)")._check(f); + }, + _rootErrorCallback: function($self, $parent, zone, error, stackTrace) { + type$.StackTrace._check(stackTrace); + return null; + }, + _rootScheduleMicrotask: function($self, $parent, zone, f) { + var t1; + type$.void_Function._check(f); + t1 = C.C__RootZone !== zone; + if (t1) + f = !(!t1 || C.C__RootZone.get$errorZone() === zone.get$errorZone()) ? zone.bindCallbackGuarded$1(f) : zone.bindCallback$1$1(f, type$.void); + P._scheduleAsyncCallback(f); + }, + _rootCreateTimer: function($self, $parent, zone, duration, callback) { + type$.Duration._check(duration); + callback = zone.bindCallback$1$1(type$.void_Function._check(callback), type$.void); + return P.Timer__createTimer(duration, callback); + }, + _rootCreatePeriodicTimer: function($self, $parent, zone, duration, callback) { + var milliseconds; + type$.Duration._check(duration); + callback = zone.bindUnaryCallback$2$1(type$.void_Function_Timer._check(callback), type$.dynamic, type$.Timer); + milliseconds = C.JSInt_methods._tdivFast$1(duration._duration, 1000); + return P._TimerImpl$periodic(milliseconds < 0 ? 0 : milliseconds, callback); + }, + _rootPrint: function($self, $parent, zone, line) { + H.printString(H._checkStringNullable(line)); + }, + _printToZone: function(line) { + $.Zone__current.print$1(0, line); + }, + _rootFork: function($self, $parent, zone, specification, zoneValues) { + var valueMap, t1, t2; + type$.ZoneSpecification._check(specification); + type$.Map_dynamic_dynamic._check(zoneValues); + $.printToZone = P.async___printToZone$closure(); + if (specification == null) + specification = C._ZoneSpecification_ALf; + if (zoneValues == null) + valueMap = zone.get$_async$_map(); + else { + t1 = type$.dynamic; + valueMap = P.HashMap_HashMap$from(zoneValues, t1, t1); + } + t1 = new P._CustomZone(zone, valueMap); + t2 = zone.get$_run(); + t1.set$_run(t2); + t2 = zone.get$_runUnary(); + t1.set$_runUnary(t2); + t2 = zone.get$_runBinary(); + t1.set$_runBinary(t2); + t2 = specification.registerCallback; + t1.set$_registerCallback(t2 != null ? new P._ZoneFunction(t1, t2, type$._ZoneFunction_Function) : zone.get$_registerCallback()); + t2 = specification.registerUnaryCallback; + t1.set$_registerUnaryCallback(t2 != null ? new P._ZoneFunction(t1, t2, type$._ZoneFunction_Function) : zone.get$_registerUnaryCallback()); + t2 = specification.registerBinaryCallback; + t1.set$_registerBinaryCallback(t2 != null ? new P._ZoneFunction(t1, t2, type$._ZoneFunction_Function) : zone.get$_registerBinaryCallback()); + t2 = specification.errorCallback; + t1.set$_errorCallback(t2 != null ? new P._ZoneFunction(t1, t2, type$._ZoneFunction_of_AsyncError_Function_Zone_ZoneDelegate_Zone_Object_StackTrace) : zone.get$_errorCallback()); + t2 = zone.get$_scheduleMicrotask(); + t1.set$_scheduleMicrotask(t2); + t2 = zone.get$_createTimer(); + t1.set$_createTimer(t2); + t2 = zone.get$_createPeriodicTimer(); + t1.set$_createPeriodicTimer(t2); + t2 = specification.print; + t1.set$_print(t2 != null ? new P._ZoneFunction(t1, t2, type$._ZoneFunction_of_void_Function_Zone_ZoneDelegate_Zone_String) : zone.get$_print()); + t2 = zone.get$_fork(); + t1.set$_fork(t2); + t2 = specification.handleUncaughtError; + t1.set$_handleUncaughtError(t2 != null ? new P._ZoneFunction(t1, t2, type$._ZoneFunction_of_void_Function_Zone_ZoneDelegate_Zone_Object_StackTrace) : zone.get$_handleUncaughtError()); + return t1; + }, + runZoned: function(body, onError, zoneSpecification, zoneValues, $R) { + var e, stackTrace, errorHandler, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, exception, _null = null, t1 = {}; + if (onError == null) + return P._runZoned(body, zoneValues, zoneSpecification, $R); + t1.binaryOnError = t1.unaryOnError = null; + if (type$.void_Function_Object_StackTrace._is(onError)) + t1.binaryOnError = onError; + else if (type$.void_Function_Object._is(onError)) + t1.unaryOnError = onError; + else + throw H.wrapException(P.ArgumentError$("onError callback must take either an Object (the error), or both an Object (the error) and a StackTrace.")); + errorHandler = new P.runZoned_closure(t1); + if (zoneSpecification == null) + zoneSpecification = P._ZoneSpecification$(_null, _null, _null, _null, errorHandler, _null, _null, _null, _null, _null, _null, _null, _null); + else { + t2 = zoneSpecification; + t3 = t2.run; + t4 = t2.runUnary; + t5 = t2.runBinary; + t6 = t2.registerCallback; + t7 = t2.registerUnaryCallback; + t8 = t2.registerBinaryCallback; + t9 = t2.errorCallback; + t10 = t2.scheduleMicrotask; + t11 = t2.createTimer; + t12 = t2.createPeriodicTimer; + t13 = t2.print; + zoneSpecification = P._ZoneSpecification$(t12, t11, t9, t2.fork, errorHandler, t13, t8, t6, t7, t3, t5, t4, t10); + } + try { + t2 = P._runZoned(body, zoneValues, zoneSpecification, $R); + return t2; + } catch (exception) { + e = H.unwrapException(exception); + stackTrace = H.getTraceFromException(exception); + t2 = t1.binaryOnError; + if (t2 != null) + t2.call$2(e, stackTrace); + else { + H.assertHelper(t1.unaryOnError != null); + t1.unaryOnError.call$1(e); + } + } + return _null; + }, + _runZoned: function(body, zoneValues, specification, $R) { + return $.Zone__current.fork$2$specification$zoneValues(specification, zoneValues).run$1$1(body, $R); + }, + _AsyncRun__initializeScheduleImmediate_internalCallback: function _AsyncRun__initializeScheduleImmediate_internalCallback(t0) { + this._box_0 = t0; + }, + _AsyncRun__initializeScheduleImmediate_closure: function _AsyncRun__initializeScheduleImmediate_closure(t0, t1, t2) { + this._box_0 = t0; + this.div = t1; + this.span = t2; + }, + _AsyncRun__scheduleImmediateJsOverride_internalCallback: function _AsyncRun__scheduleImmediateJsOverride_internalCallback(t0) { + this.callback = t0; + }, + _AsyncRun__scheduleImmediateWithSetImmediate_internalCallback: function _AsyncRun__scheduleImmediateWithSetImmediate_internalCallback(t0) { + this.callback = t0; + }, + _TimerImpl: function _TimerImpl(t0) { + this._once = t0; + this._handle = null; + this._tick = 0; + }, + _TimerImpl_internalCallback: function _TimerImpl_internalCallback(t0, t1) { + this.$this = t0; + this.callback = t1; + }, + _TimerImpl$periodic_closure: function _TimerImpl$periodic_closure(t0, t1, t2, t3) { + var _ = this; + _.$this = t0; + _.milliseconds = t1; + _.start = t2; + _.callback = t3; + }, + _AsyncAwaitCompleter: function _AsyncAwaitCompleter(t0, t1) { + this._future = t0; + this.isSync = false; + this.$ti = t1; + }, + _awaitOnObject_closure: function _awaitOnObject_closure(t0) { + this.bodyFunction = t0; + }, + _awaitOnObject_closure0: function _awaitOnObject_closure0(t0) { + this.bodyFunction = t0; + }, + _wrapJsFunctionForAsync_closure: function _wrapJsFunctionForAsync_closure(t0) { + this.$protected = t0; + }, + _BroadcastStream: function _BroadcastStream(t0, t1) { + this._controller = t0; + this.$ti = t1; + }, + _BroadcastSubscription: function _BroadcastSubscription(t0, t1, t2, t3) { + var _ = this; + _._eventState = 0; + _._async$_previous = _._async$_next = null; + _._controller = t0; + _._onDone = _._onError = _._onData = null; + _._zone = t1; + _._state = t2; + _._pending = _._cancelFuture = null; + _.$ti = t3; + }, + _BroadcastStreamController: function _BroadcastStreamController() { + }, + _SyncBroadcastStreamController: function _SyncBroadcastStreamController(t0, t1, t2) { + var _ = this; + _.onListen = t0; + _.onCancel = t1; + _._state = 0; + _._doneFuture = _._addStreamState = _._lastSubscription = _._firstSubscription = null; + _.$ti = t2; + }, + _SyncBroadcastStreamController__sendData_closure: function _SyncBroadcastStreamController__sendData_closure(t0, t1) { + this.$this = t0; + this.data = t1; + }, + _SyncBroadcastStreamController__sendError_closure: function _SyncBroadcastStreamController__sendError_closure(t0, t1, t2) { + this.$this = t0; + this.error = t1; + this.stackTrace = t2; + }, + _SyncBroadcastStreamController__sendDone_closure: function _SyncBroadcastStreamController__sendDone_closure(t0) { + this.$this = t0; + }, + _AsyncBroadcastStreamController: function _AsyncBroadcastStreamController(t0, t1, t2) { + var _ = this; + _.onListen = t0; + _.onCancel = t1; + _._state = 0; + _._doneFuture = _._addStreamState = _._lastSubscription = _._firstSubscription = null; + _.$ti = t2; + }, + Future: function Future() { + }, + Future_Future_closure: function Future_Future_closure(t0, t1) { + this.result = t0; + this.computation = t1; + }, + Future_Future$microtask_closure: function Future_Future$microtask_closure(t0, t1) { + this.result = t0; + this.computation = t1; + }, + Future_wait_handleError: function Future_wait_handleError(t0, t1, t2, t3) { + var _ = this; + _._box_0 = t0; + _.cleanUp = t1; + _.eagerError = t2; + _.result = t3; + }, + Future_wait_closure: function Future_wait_closure(t0, t1, t2, t3, t4, t5) { + var _ = this; + _._box_0 = t0; + _.pos = t1; + _.result = t2; + _.cleanUp = t3; + _.eagerError = t4; + _.T = t5; + }, + Future_forEach_closure: function Future_forEach_closure(t0, t1) { + this.iterator = t0; + this.action = t1; + }, + Future_doWhile_closure: function Future_doWhile_closure(t0, t1, t2) { + this._box_0 = t0; + this.action = t1; + this.doneSignal = t2; + }, + TimeoutException: function TimeoutException(t0, t1) { + this.message = t0; + this.duration = t1; + }, + Completer: function Completer() { + }, + _Completer: function _Completer() { + }, + _AsyncCompleter: function _AsyncCompleter(t0, t1) { + this.future = t0; + this.$ti = t1; + }, + _SyncCompleter: function _SyncCompleter(t0, t1) { + this.future = t0; + this.$ti = t1; + }, + _FutureListener: function _FutureListener(t0, t1, t2, t3, t4) { + var _ = this; + _._nextListener = null; + _.result = t0; + _.state = t1; + _.callback = t2; + _.errorCallback = t3; + _.$ti = t4; + }, + _Future: function _Future(t0, t1) { + var _ = this; + _._state = 0; + _._zone = t0; + _._resultOrListeners = null; + _.$ti = t1; + }, + _Future__addListener_closure: function _Future__addListener_closure(t0, t1) { + this.$this = t0; + this.listener = t1; + }, + _Future__prependListeners_closure: function _Future__prependListeners_closure(t0, t1) { + this._box_0 = t0; + this.$this = t1; + }, + _Future__chainForeignFuture_closure: function _Future__chainForeignFuture_closure(t0) { + this.target = t0; + }, + _Future__chainForeignFuture_closure0: function _Future__chainForeignFuture_closure0(t0) { + this.target = t0; + }, + _Future__chainForeignFuture_closure1: function _Future__chainForeignFuture_closure1(t0, t1, t2) { + this.target = t0; + this.e = t1; + this.s = t2; + }, + _Future__asyncComplete_closure: function _Future__asyncComplete_closure(t0, t1) { + this.$this = t0; + this.value = t1; + }, + _Future__chainFuture_closure: function _Future__chainFuture_closure(t0, t1) { + this.$this = t0; + this.value = t1; + }, + _Future__asyncCompleteError_closure: function _Future__asyncCompleteError_closure(t0, t1, t2) { + this.$this = t0; + this.error = t1; + this.stackTrace = t2; + }, + _Future__propagateToListeners_handleWhenCompleteCallback: function _Future__propagateToListeners_handleWhenCompleteCallback(t0, t1, t2, t3) { + var _ = this; + _._box_1 = t0; + _._box_0 = t1; + _.listener = t2; + _.hasError = t3; + }, + _Future__propagateToListeners_handleWhenCompleteCallback_closure: function _Future__propagateToListeners_handleWhenCompleteCallback_closure(t0) { + this.originalSource = t0; + }, + _Future__propagateToListeners_handleValueCallback: function _Future__propagateToListeners_handleValueCallback(t0, t1, t2) { + this._box_0 = t0; + this.listener = t1; + this.sourceResult = t2; + }, + _Future__propagateToListeners_handleError: function _Future__propagateToListeners_handleError(t0, t1, t2) { + this._box_1 = t0; + this._box_0 = t1; + this.listener = t2; + }, + _AsyncCallbackEntry: function _AsyncCallbackEntry(t0) { + this.callback = t0; + this.next = null; + }, + Stream: function Stream() { + }, + Stream_Stream$fromFuture_closure: function Stream_Stream$fromFuture_closure(t0, t1) { + this.controller = t0; + this.T = t1; + }, + Stream_Stream$fromFuture_closure0: function Stream_Stream$fromFuture_closure0(t0) { + this.controller = t0; + }, + Stream_Stream$fromIterable_closure: function Stream_Stream$fromIterable_closure(t0, t1) { + this.elements = t0; + this.T = t1; + }, + Stream_pipe_closure: function Stream_pipe_closure(t0) { + this.streamConsumer = t0; + }, + Stream_length_closure: function Stream_length_closure(t0, t1) { + this._box_0 = t0; + this.$this = t1; + }, + Stream_length_closure0: function Stream_length_closure0(t0, t1) { + this._box_0 = t0; + this.future = t1; + }, + Stream_first_closure: function Stream_first_closure(t0, t1, t2) { + this._box_0 = t0; + this.$this = t1; + this.future = t2; + }, + Stream_first_closure0: function Stream_first_closure0(t0) { + this.future = t0; + }, + Stream_last_closure: function Stream_last_closure(t0, t1) { + this._box_0 = t0; + this.$this = t1; + }, + Stream_last_closure0: function Stream_last_closure0(t0, t1) { + this._box_0 = t0; + this.future = t1; + }, + Stream_firstWhere_closure: function Stream_firstWhere_closure(t0, t1, t2, t3) { + var _ = this; + _._box_0 = t0; + _.$this = t1; + _.test = t2; + _.future = t3; + }, + Stream_firstWhere__closure: function Stream_firstWhere__closure(t0, t1) { + this.test = t0; + this.value = t1; + }, + Stream_firstWhere__closure0: function Stream_firstWhere__closure0(t0, t1, t2) { + this._box_0 = t0; + this.future = t1; + this.value = t2; + }, + Stream_firstWhere_closure0: function Stream_firstWhere_closure0(t0, t1, t2) { + this.$this = t0; + this.orElse = t1; + this.future = t2; + }, + StreamSubscription: function StreamSubscription() { + }, + StreamTransformerBase: function StreamTransformerBase() { + }, + _StreamController: function _StreamController() { + }, + _StreamController__subscribe_closure: function _StreamController__subscribe_closure(t0) { + this.$this = t0; + }, + _StreamController__recordCancel_complete: function _StreamController__recordCancel_complete(t0) { + this.$this = t0; + }, + _SyncStreamControllerDispatch: function _SyncStreamControllerDispatch() { + }, + _AsyncStreamControllerDispatch: function _AsyncStreamControllerDispatch() { + }, + _AsyncStreamController: function _AsyncStreamController(t0, t1, t2, t3, t4) { + var _ = this; + _._varData = null; + _._state = 0; + _._doneFuture = null; + _.onListen = t0; + _.onPause = t1; + _.onResume = t2; + _.onCancel = t3; + _.$ti = t4; + }, + _SyncStreamController: function _SyncStreamController(t0, t1, t2, t3, t4) { + var _ = this; + _._varData = null; + _._state = 0; + _._doneFuture = null; + _.onListen = t0; + _.onPause = t1; + _.onResume = t2; + _.onCancel = t3; + _.$ti = t4; + }, + _ControllerStream: function _ControllerStream(t0, t1) { + this._controller = t0; + this.$ti = t1; + }, + _ControllerSubscription: function _ControllerSubscription(t0, t1, t2, t3) { + var _ = this; + _._controller = t0; + _._onDone = _._onError = _._onData = null; + _._zone = t1; + _._state = t2; + _._pending = _._cancelFuture = null; + _.$ti = t3; + }, + _StreamSinkWrapper: function _StreamSinkWrapper(t0, t1) { + this._async$_target = t0; + this.$ti = t1; + }, + _AddStreamState: function _AddStreamState() { + }, + _AddStreamState_makeErrorHandler_closure: function _AddStreamState_makeErrorHandler_closure(t0) { + this.controller = t0; + }, + _AddStreamState_cancel_closure: function _AddStreamState_cancel_closure(t0) { + this.$this = t0; + }, + _StreamControllerAddStreamState: function _StreamControllerAddStreamState(t0, t1, t2, t3) { + var _ = this; + _.varData = t0; + _.addStreamFuture = t1; + _.addSubscription = t2; + _.$ti = t3; + }, + _BufferingStreamSubscription: function _BufferingStreamSubscription(t0, t1, t2) { + var _ = this; + _._onDone = _._onError = _._onData = null; + _._zone = t0; + _._state = t1; + _._pending = _._cancelFuture = null; + _.$ti = t2; + }, + _BufferingStreamSubscription__sendError_sendError: function _BufferingStreamSubscription__sendError_sendError(t0, t1, t2) { + this.$this = t0; + this.error = t1; + this.stackTrace = t2; + }, + _BufferingStreamSubscription__sendDone_sendDone: function _BufferingStreamSubscription__sendDone_sendDone(t0) { + this.$this = t0; + }, + _StreamImpl: function _StreamImpl() { + }, + _GeneratedStreamImpl: function _GeneratedStreamImpl(t0, t1) { + this._pending = t0; + this._isUsed = false; + this.$ti = t1; + }, + _IterablePendingEvents: function _IterablePendingEvents(t0, t1) { + this._async$_iterator = t0; + this._state = 0; + this.$ti = t1; + }, + _DelayedEvent: function _DelayedEvent() { + }, + _DelayedData: function _DelayedData(t0, t1) { + this.value = t0; + this.next = null; + this.$ti = t1; + }, + _DelayedError: function _DelayedError(t0, t1) { + this.error = t0; + this.stackTrace = t1; + this.next = null; + }, + _DelayedDone: function _DelayedDone() { + }, + _PendingEvents: function _PendingEvents() { + }, + _PendingEvents_schedule_closure: function _PendingEvents_schedule_closure(t0, t1) { + this.$this = t0; + this.dispatch = t1; + }, + _StreamImplEvents: function _StreamImplEvents(t0) { + var _ = this; + _.lastPendingEvent = _.firstPendingEvent = null; + _._state = 0; + _.$ti = t0; + }, + _DoneStreamSubscription: function _DoneStreamSubscription(t0, t1, t2) { + var _ = this; + _._zone = t0; + _._state = 0; + _._onDone = t1; + _.$ti = t2; + }, + _StreamIterator: function _StreamIterator(t0) { + this.$ti = t0; + }, + _EmptyStream: function _EmptyStream(t0) { + this.$ti = t0; + }, + _cancelAndError_closure: function _cancelAndError_closure(t0, t1, t2) { + this.future = t0; + this.error = t1; + this.stackTrace = t2; + }, + _cancelAndErrorClosure_closure: function _cancelAndErrorClosure_closure(t0, t1) { + this.subscription = t0; + this.future = t1; + }, + _cancelAndValue_closure: function _cancelAndValue_closure(t0, t1) { + this.future = t0; + this.value = t1; + }, + Timer: function Timer() { + }, + AsyncError: function AsyncError(t0, t1) { + this.error = t0; + this.stackTrace = t1; + }, + _ZoneFunction: function _ZoneFunction(t0, t1, t2) { + this.zone = t0; + this.$function = t1; + this.$ti = t2; + }, + ZoneSpecification: function ZoneSpecification() { + }, + _ZoneSpecification: function _ZoneSpecification(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12) { + var _ = this; + _.handleUncaughtError = t0; + _.run = t1; + _.runUnary = t2; + _.runBinary = t3; + _.registerCallback = t4; + _.registerUnaryCallback = t5; + _.registerBinaryCallback = t6; + _.errorCallback = t7; + _.scheduleMicrotask = t8; + _.createTimer = t9; + _.createPeriodicTimer = t10; + _.print = t11; + _.fork = t12; + }, + ZoneDelegate: function ZoneDelegate() { + }, + Zone: function Zone() { + }, + _ZoneDelegate: function _ZoneDelegate(t0) { + this._delegationTarget = t0; + }, + _Zone: function _Zone() { + }, + _CustomZone: function _CustomZone(t0, t1) { + var _ = this; + _._delegateCache = _._handleUncaughtError = _._fork = _._print = _._createPeriodicTimer = _._createTimer = _._scheduleMicrotask = _._errorCallback = _._registerBinaryCallback = _._registerUnaryCallback = _._registerCallback = _._runBinary = _._runUnary = _._run = null; + _.parent = t0; + _._async$_map = t1; + }, + _CustomZone_bindCallback_closure: function _CustomZone_bindCallback_closure(t0, t1, t2) { + this.$this = t0; + this.registered = t1; + this.R = t2; + }, + _CustomZone_bindUnaryCallback_closure: function _CustomZone_bindUnaryCallback_closure(t0, t1, t2, t3) { + var _ = this; + _.$this = t0; + _.registered = t1; + _.T = t2; + _.R = t3; + }, + _CustomZone_bindCallbackGuarded_closure: function _CustomZone_bindCallbackGuarded_closure(t0, t1) { + this.$this = t0; + this.registered = t1; + }, + _CustomZone_bindUnaryCallbackGuarded_closure: function _CustomZone_bindUnaryCallbackGuarded_closure(t0, t1, t2) { + this.$this = t0; + this.registered = t1; + this.T = t2; + }, + _rootHandleUncaughtError_closure: function _rootHandleUncaughtError_closure(t0, t1) { + this._box_0 = t0; + this.stackTrace = t1; + }, + _RootZone: function _RootZone() { + }, + _RootZone_bindCallback_closure: function _RootZone_bindCallback_closure(t0, t1, t2) { + this.$this = t0; + this.f = t1; + this.R = t2; + }, + _RootZone_bindCallbackGuarded_closure: function _RootZone_bindCallbackGuarded_closure(t0, t1) { + this.$this = t0; + this.f = t1; + }, + _RootZone_bindUnaryCallbackGuarded_closure: function _RootZone_bindUnaryCallbackGuarded_closure(t0, t1, t2) { + this.$this = t0; + this.f = t1; + this.T = t2; + }, + runZoned_closure: function runZoned_closure(t0) { + this._box_0 = t0; + }, + HashMap_HashMap: function($K, $V) { + return new P._HashMap($K._eval$1("@<0>")._bind$1($V)._eval$1("_HashMap<1,2>")); + }, + _HashMap__getTableEntry: function(table, key) { + var entry = table[key]; + return entry === table ? null : entry; + }, + _HashMap__setTableEntry: function(table, key, value) { + if (value == null) + table[key] = table; + else + table[key] = value; + }, + _HashMap__newHashTable: function() { + var table = Object.create(null); + P._HashMap__setTableEntry(table, "<non-identifier-key>", table); + delete table["<non-identifier-key>"]; + return table; + }, + LinkedHashMap_LinkedHashMap: function($K, $V) { + return new H.JsLinkedHashMap($K._eval$1("@<0>")._bind$1($V)._eval$1("JsLinkedHashMap<1,2>")); + }, + LinkedHashMap_LinkedHashMap$_literal: function(keyValuePairs, $K, $V) { + return $K._eval$1("@<0>")._bind$1($V)._eval$1("LinkedHashMap<1,2>")._check(H.fillLiteralMap(keyValuePairs, new H.JsLinkedHashMap($K._eval$1("@<0>")._bind$1($V)._eval$1("JsLinkedHashMap<1,2>")))); + }, + LinkedHashMap_LinkedHashMap$_empty: function($K, $V) { + return new H.JsLinkedHashMap($K._eval$1("@<0>")._bind$1($V)._eval$1("JsLinkedHashMap<1,2>")); + }, + LinkedHashSet_LinkedHashSet: function($E) { + return new P._LinkedHashSet($E._eval$1("_LinkedHashSet<0>")); + }, + LinkedHashSet_LinkedHashSet$_empty: function($E) { + return new P._LinkedHashSet($E._eval$1("_LinkedHashSet<0>")); + }, + LinkedHashSet_LinkedHashSet$_literal: function(values, $E) { + return $E._eval$1("LinkedHashSet<0>")._check(H.fillLiteralSet(values, new P._LinkedHashSet($E._eval$1("_LinkedHashSet<0>")))); + }, + _LinkedHashSet__newHashTable: function() { + var table = Object.create(null); + H.assertHelper(table != null); + table["<non-identifier-key>"] = table; + delete table["<non-identifier-key>"]; + return table; + }, + _LinkedHashSetIterator$: function(_set, _modifications, $E) { + var t1 = new P._LinkedHashSetIterator(_set, _modifications, $E._eval$1("_LinkedHashSetIterator<0>")); + t1._collection$_cell = _set._collection$_first; + return t1; + }, + HashMap_HashMap$from: function(other, $K, $V) { + var result = P.HashMap_HashMap($K, $V); + other.forEach$1(0, new P.HashMap_HashMap$from_closure(result, $K, $V)); + return result; + }, + IterableBase_iterableToShortString: function(iterable, leftDelimiter, rightDelimiter) { + var parts, t1; + if (P._isToStringVisiting(iterable)) { + if (leftDelimiter === "(" && rightDelimiter === ")") + return "(...)"; + return leftDelimiter + "..." + rightDelimiter; + } + parts = H.setRuntimeTypeInfo([], type$.JSArray_String); + C.JSArray_methods.add$1($._toStringVisiting, iterable); + try { + P._iterablePartsToStrings(iterable, parts); + } finally { + H.assertHelper(C.JSArray_methods.get$last($._toStringVisiting) === iterable); + if (0 >= $._toStringVisiting.length) + return H.ioore($._toStringVisiting, -1); + $._toStringVisiting.pop(); + } + t1 = P.StringBuffer__writeAll(leftDelimiter, type$.Iterable_dynamic._check(parts), ", ") + rightDelimiter; + return t1.charCodeAt(0) == 0 ? t1 : t1; + }, + IterableBase_iterableToFullString: function(iterable, leftDelimiter, rightDelimiter) { + var buffer, t1; + if (P._isToStringVisiting(iterable)) + return leftDelimiter + "..." + rightDelimiter; + buffer = new P.StringBuffer(leftDelimiter); + C.JSArray_methods.add$1($._toStringVisiting, iterable); + try { + t1 = buffer; + t1._contents = P.StringBuffer__writeAll(t1._contents, iterable, ", "); + } finally { + H.assertHelper(C.JSArray_methods.get$last($._toStringVisiting) === iterable); + if (0 >= $._toStringVisiting.length) + return H.ioore($._toStringVisiting, -1); + $._toStringVisiting.pop(); + } + buffer._contents += rightDelimiter; + t1 = buffer._contents; + return t1.charCodeAt(0) == 0 ? t1 : t1; + }, + _isToStringVisiting: function(o) { + var t1, i; + for (t1 = $._toStringVisiting.length, i = 0; i < t1; ++i) + if (o === $._toStringVisiting[i]) + return true; + return false; + }, + _iterablePartsToStrings: function(iterable, parts) { + var next, ultimateString, penultimateString, penultimate, ultimate, ultimate0, elision, + it = iterable.get$iterator(iterable), + $length = 0, count = 0; + while (true) { + if (!($length < 80 || count < 3)) + break; + if (!it.moveNext$0()) + return; + next = H.S(it.get$current()); + C.JSArray_methods.add$1(parts, next); + $length += next.length + 2; + ++count; + } + if (!it.moveNext$0()) { + if (count <= 5) + return; + if (0 >= parts.length) + return H.ioore(parts, -1); + ultimateString = parts.pop(); + if (0 >= parts.length) + return H.ioore(parts, -1); + penultimateString = parts.pop(); + } else { + penultimate = it.get$current(); + ++count; + if (!it.moveNext$0()) { + if (count <= 4) { + C.JSArray_methods.add$1(parts, H.S(penultimate)); + return; + } + ultimateString = H.S(penultimate); + if (0 >= parts.length) + return H.ioore(parts, -1); + penultimateString = parts.pop(); + $length += ultimateString.length + 2; + } else { + ultimate = it.get$current(); + ++count; + H.assertHelper(count < 100); + for (; it.moveNext$0(); penultimate = ultimate, ultimate = ultimate0) { + ultimate0 = it.get$current(); + ++count; + if (count > 100) { + while (true) { + if (!($length > 75 && count > 3)) + break; + if (0 >= parts.length) + return H.ioore(parts, -1); + $length -= parts.pop().length + 2; + --count; + } + C.JSArray_methods.add$1(parts, "..."); + return; + } + } + penultimateString = H.S(penultimate); + ultimateString = H.S(ultimate); + $length += ultimateString.length + penultimateString.length + 4; + } + } + if (count > parts.length + 2) { + $length += 5; + elision = "..."; + } else + elision = null; + while (true) { + if (!($length > 80 && parts.length > 3)) + break; + if (0 >= parts.length) + return H.ioore(parts, -1); + $length -= parts.pop().length + 2; + if (elision == null) { + $length += 5; + elision = "..."; + } + } + if (elision != null) + C.JSArray_methods.add$1(parts, elision); + C.JSArray_methods.add$1(parts, penultimateString); + C.JSArray_methods.add$1(parts, ultimateString); + }, + LinkedHashMap_LinkedHashMap$from: function(other, $K, $V) { + var result = P.LinkedHashMap_LinkedHashMap($K, $V); + other.forEach$1(0, new P.LinkedHashMap_LinkedHashMap$from_closure(result, $K, $V)); + return result; + }, + LinkedHashSet_LinkedHashSet$from: function(elements, $E) { + var t1, + result = P.LinkedHashSet_LinkedHashSet($E); + for (t1 = J.get$iterator$ax(elements); t1.moveNext$0();) + result.add$1(0, $E._check(t1.get$current())); + return result; + }, + MapBase_mapToString: function(m) { + var result, t1 = {}; + if (P._isToStringVisiting(m)) + return "{...}"; + result = new P.StringBuffer(""); + try { + C.JSArray_methods.add$1($._toStringVisiting, m); + result._contents += "{"; + t1.first = true; + m.forEach$1(0, new P.MapBase_mapToString_closure(t1, result)); + result._contents += "}"; + } finally { + H.assertHelper(C.JSArray_methods.get$last($._toStringVisiting) === m); + if (0 >= $._toStringVisiting.length) + return H.ioore($._toStringVisiting, -1); + $._toStringVisiting.pop(); + } + t1 = result._contents; + return t1.charCodeAt(0) == 0 ? t1 : t1; + }, + ListQueue$: function($E) { + var t1 = new P.ListQueue($E._eval$1("ListQueue<0>")), + t2 = new Array(8); + t2.fixed$length = Array; + t1.set$_table(H.setRuntimeTypeInfo(t2, $E._eval$1("JSArray<0>"))); + return t1; + }, + _ListQueueIterator$: function(queue, $E) { + return new P._ListQueueIterator(queue, queue._tail, queue._modificationCount, queue._head, $E._eval$1("_ListQueueIterator<0>")); + }, + _HashMap: function _HashMap(t0) { + var _ = this; + _._collection$_length = 0; + _._keys = _._collection$_rest = _._nums = _._strings = null; + _.$ti = t0; + }, + _IdentityHashMap: function _IdentityHashMap(t0) { + var _ = this; + _._collection$_length = 0; + _._keys = _._collection$_rest = _._nums = _._strings = null; + _.$ti = t0; + }, + _HashMapKeyIterable: function _HashMapKeyIterable(t0, t1) { + this._map = t0; + this.$ti = t1; + }, + _HashMapKeyIterator: function _HashMapKeyIterator(t0, t1, t2) { + var _ = this; + _._map = t0; + _._keys = t1; + _._offset = 0; + _._collection$_current = null; + _.$ti = t2; + }, + _LinkedHashSet: function _LinkedHashSet(t0) { + var _ = this; + _._collection$_length = 0; + _._collection$_last = _._collection$_first = _._collection$_rest = _._nums = _._strings = null; + _._collection$_modifications = 0; + _.$ti = t0; + }, + _LinkedHashSetCell: function _LinkedHashSetCell(t0) { + this._element = t0; + this._collection$_previous = this._collection$_next = null; + }, + _LinkedHashSetIterator: function _LinkedHashSetIterator(t0, t1, t2) { + var _ = this; + _._set = t0; + _._collection$_modifications = t1; + _._collection$_current = _._collection$_cell = null; + _.$ti = t2; + }, + UnmodifiableListView: function UnmodifiableListView(t0, t1) { + this._collection$_source = t0; + this.$ti = t1; + }, + HashMap_HashMap$from_closure: function HashMap_HashMap$from_closure(t0, t1, t2) { + this.result = t0; + this.K = t1; + this.V = t2; + }, + IterableBase: function IterableBase() { + }, + LinkedHashMap_LinkedHashMap$from_closure: function LinkedHashMap_LinkedHashMap$from_closure(t0, t1, t2) { + this.result = t0; + this.K = t1; + this.V = t2; + }, + ListBase: function ListBase() { + }, + ListMixin: function ListMixin() { + }, + MapBase: function MapBase() { + }, + MapBase_mapToString_closure: function MapBase_mapToString_closure(t0, t1) { + this._box_0 = t0; + this.result = t1; + }, + MapMixin: function MapMixin() { + }, + _UnmodifiableMapMixin: function _UnmodifiableMapMixin() { + }, + MapView: function MapView() { + }, + UnmodifiableMapView: function UnmodifiableMapView(t0, t1) { + this._map = t0; + this.$ti = t1; + }, + ListQueue: function ListQueue(t0) { + var _ = this; + _._table = null; + _._modificationCount = _._tail = _._head = 0; + _.$ti = t0; + }, + _ListQueueIterator: function _ListQueueIterator(t0, t1, t2, t3, t4) { + var _ = this; + _._queue = t0; + _._end = t1; + _._modificationCount = t2; + _._position = t3; + _._collection$_current = null; + _.$ti = t4; + }, + SetMixin: function SetMixin() { + }, + SetBase: function SetBase() { + }, + _SetBase: function _SetBase() { + }, + _ListBase_Object_ListMixin: function _ListBase_Object_ListMixin() { + }, + _SetBase_Object_SetMixin: function _SetBase_Object_SetMixin() { + }, + _UnmodifiableMapView_MapView__UnmodifiableMapMixin: function _UnmodifiableMapView_MapView__UnmodifiableMapMixin() { + }, + _parseJson: function(source, reviver) { + var parsed, e, exception, t1; + if (typeof source != "string") + throw H.wrapException(H.argumentErrorValue(source)); + parsed = null; + try { + parsed = JSON.parse(source); + } catch (exception) { + e = H.unwrapException(exception); + t1 = P.FormatException$(String(e), null, null); + throw H.wrapException(t1); + } + t1 = P._convertJsonToDartLazy(parsed); + return t1; + }, + _convertJsonToDartLazy: function(object) { + var i; + if (object == null) + return null; + if (typeof object != "object") + return object; + if (Object.getPrototypeOf(object) !== Array.prototype) + return new P._JsonMap(object, Object.create(null)); + for (i = 0; i < object.length; ++i) + object[i] = P._convertJsonToDartLazy(object[i]); + return object; + }, + Utf8Decoder__convertIntercepted: function(allowMalformed, codeUnits, start, end) { + if (codeUnits instanceof Uint8Array) + return P.Utf8Decoder__convertInterceptedUint8List(false, codeUnits, start, end); + return null; + }, + Utf8Decoder__convertInterceptedUint8List: function(allowMalformed, codeUnits, start, end) { + var t1, $length, + decoder = $.$get$Utf8Decoder__decoder(); + if (decoder == null) + return null; + t1 = 0 === start; + if (t1 && true) + return P.Utf8Decoder__useTextDecoderChecked(decoder, codeUnits); + $length = codeUnits.length; + end = P.RangeError_checkValidRange(start, end, $length); + if (t1 && end === $length) + return P.Utf8Decoder__useTextDecoderChecked(decoder, codeUnits); + return P.Utf8Decoder__useTextDecoderChecked(decoder, codeUnits.subarray(start, end)); + }, + Utf8Decoder__useTextDecoderChecked: function(decoder, codeUnits) { + if (P.Utf8Decoder__unsafe(codeUnits)) + return null; + return P.Utf8Decoder__useTextDecoderUnchecked(decoder, codeUnits); + }, + Utf8Decoder__useTextDecoderUnchecked: function(decoder, codeUnits) { + var t1, exception; + try { + t1 = decoder.decode(codeUnits); + return t1; + } catch (exception) { + H.unwrapException(exception); + } + return null; + }, + Utf8Decoder__unsafe: function(codeUnits) { + var i, + limit = codeUnits.length - 2; + for (i = 0; i < limit; ++i) + if (codeUnits[i] === 237) + if ((codeUnits[i + 1] & 224) === 160) + return true; + return false; + }, + Utf8Decoder__makeDecoder: function() { + var t1, exception; + try { + t1 = new TextDecoder("utf-8", {fatal: true}); + return t1; + } catch (exception) { + H.unwrapException(exception); + } + return null; + }, + _scanOneByteCharacters: function(units, from, endIndex) { + var t1, i, unit; + for (t1 = J.getInterceptor$asx(units), i = from; i < endIndex; ++i) { + unit = t1.$index(units, i); + if (typeof unit !== "number") + return unit.$and(); + if ((unit & 127) !== unit) + return i - from; + } + return endIndex - from; + }, + Base64Codec__checkPadding: function(source, sourceIndex, sourceEnd, firstPadding, paddingCount, $length) { + if (C.JSInt_methods.$mod($length, 4) !== 0) + throw H.wrapException(P.FormatException$("Invalid base64 padding, padded length must be multiple of four, is " + $length, source, sourceEnd)); + if (firstPadding + paddingCount !== $length) + throw H.wrapException(P.FormatException$("Invalid base64 padding, '=' not at the end", source, sourceIndex)); + if (paddingCount > 2) + throw H.wrapException(P.FormatException$("Invalid base64 padding, more than two '=' characters", source, sourceIndex)); + }, + _JsonMap: function _JsonMap(t0, t1) { + this._original = t0; + this._processed = t1; + this._data = null; + }, + _JsonMapKeyIterable: function _JsonMapKeyIterable(t0) { + this._parent = t0; + }, + AsciiCodec: function AsciiCodec() { + }, + _UnicodeSubsetEncoder: function _UnicodeSubsetEncoder() { + }, + AsciiEncoder: function AsciiEncoder(t0) { + this._subsetMask = t0; + }, + Base64Codec: function Base64Codec() { + }, + Base64Encoder: function Base64Encoder() { + }, + Codec: function Codec() { + }, + _FusedCodec: function _FusedCodec(t0, t1, t2) { + this._convert$_first = t0; + this._second = t1; + this.$ti = t2; + }, + Converter: function Converter() { + }, + Encoding: function Encoding() { + }, + JsonCodec: function JsonCodec() { + }, + JsonDecoder: function JsonDecoder(t0) { + this._reviver = t0; + }, + Utf8Codec: function Utf8Codec() { + }, + Utf8Encoder: function Utf8Encoder() { + }, + _Utf8Encoder: function _Utf8Encoder(t0) { + this._bufferIndex = this._carry = 0; + this._buffer = t0; + }, + Utf8Decoder: function Utf8Decoder(t0) { + this._allowMalformed = t0; + }, + _Utf8Decoder: function _Utf8Decoder(t0, t1) { + var _ = this; + _._allowMalformed = t0; + _._stringSink = t1; + _._isFirstCharacter = true; + _._extraUnits = _._expectedUnits = _._convert$_value = 0; + }, + int_parse: function(source, onError, radix) { + var value = H.Primitives_parseInt(source, radix); + if (value != null) + return value; + if (onError != null) + return onError.call$1(source); + throw H.wrapException(P.FormatException$(source, null, null)); + }, + Error__objectToString: function(object) { + if (object instanceof H.Closure) + return object.toString$0(0); + return "Instance of '" + H.S(H.Primitives_objectTypeName(object)) + "'"; + }, + List_List$filled: function($length, fill, $E) { + var i, + result = J.JSArray_JSArray$fixed($length, $E); + if ($length !== 0 && true) + for (i = 0; i < result.length; ++i) + C.JSArray_methods.$indexSet(result, i, fill); + return result; + }, + List_List$from: function(elements, growable, $E) { + var t1, + list = H.setRuntimeTypeInfo([], $E._eval$1("JSArray<0>")); + for (t1 = J.get$iterator$ax(elements); t1.moveNext$0();) + C.JSArray_methods.add$1(list, $E._check(t1.get$current())); + if (growable) + return list; + return $E._eval$1("List<0>")._check(J.JSArray_markFixedList(list)); + }, + List_List$unmodifiable: function(elements, $E) { + var result = P.List_List$from(elements, false, $E); + result.fixed$length = Array; + result.immutable$list = Array; + return $E._eval$1("List<0>")._check(result); + }, + String_String$fromCharCodes: function(charCodes, start, end) { + var len; + if (Array.isArray(charCodes)) { + type$.JSArray_int._check(charCodes); + len = charCodes.length; + end = P.RangeError_checkValidRange(start, end, len); + return H.Primitives_stringFromCharCodes(start > 0 || end < len ? C.JSArray_methods.sublist$2(charCodes, start, end) : charCodes); + } + if (type$.NativeUint8List._is(charCodes)) + return H.Primitives_stringFromNativeUint8List(charCodes, start, P.RangeError_checkValidRange(start, end, charCodes.length)); + return P.String__stringFromIterable(charCodes, start, end); + }, + String_String$fromCharCode: function(charCode) { + return H.Primitives_stringFromCharCode(charCode); + }, + String__stringFromIterable: function(charCodes, start, end) { + var t1, it, i, list, _null = null; + if (start < 0) + throw H.wrapException(P.RangeError$range(start, 0, J.get$length$asx(charCodes), _null, _null)); + t1 = end == null; + if (!t1 && end < start) + throw H.wrapException(P.RangeError$range(end, start, J.get$length$asx(charCodes), _null, _null)); + it = J.get$iterator$ax(charCodes); + for (i = 0; i < start; ++i) + if (!it.moveNext$0()) + throw H.wrapException(P.RangeError$range(start, 0, i, _null, _null)); + list = []; + if (t1) + for (; it.moveNext$0();) + list.push(it.get$current()); + else + for (i = start; i < end; ++i) { + if (!it.moveNext$0()) + throw H.wrapException(P.RangeError$range(end, start, i, _null, _null)); + list.push(it.get$current()); + } + return H.Primitives_stringFromCharCodes(list); + }, + RegExp_RegExp: function(source, multiLine) { + return new H.JSSyntaxRegExp(source, H.JSSyntaxRegExp_makeNative(source, multiLine, true, false, false, false)); + }, + StringBuffer__writeAll: function(string, objects, separator) { + var iterator = J.get$iterator$ax(objects); + if (!iterator.moveNext$0()) + return string; + if (separator.length === 0) { + do + string += H.S(iterator.get$current()); + while (iterator.moveNext$0()); + } else { + string += H.S(iterator.get$current()); + for (; iterator.moveNext$0();) + string = string + separator + H.S(iterator.get$current()); + } + return string; + }, + Uri_base: function() { + var uri = H.Primitives_currentUri(); + if (uri != null) + return P.Uri_parse(uri); + throw H.wrapException(P.UnsupportedError$("'Uri.base' is not supported")); + }, + _Uri__uriEncode: function(canonicalTable, text, encoding, spaceToPlus) { + var t1, bytes, i, t2, byte, t3, + _s16_ = "0123456789ABCDEF"; + if (encoding === C.C_Utf8Codec) { + t1 = $.$get$_Uri__needsNoEncoding()._nativeRegExp; + if (typeof text != "string") + H.throwExpression(H.argumentErrorValue(text)); + t1 = t1.test(text); + } else + t1 = false; + if (t1) + return text; + H._instanceType(encoding)._eval$1("Codec.S")._check(text); + bytes = encoding.get$encoder().convert$1(text); + for (t1 = bytes.length, i = 0, t2 = ""; i < t1; ++i) { + byte = bytes[i]; + if (byte < 128) { + t3 = byte >>> 4; + if (t3 >= 8) + return H.ioore(canonicalTable, t3); + t3 = (canonicalTable[t3] & 1 << (byte & 15)) !== 0; + } else + t3 = false; + if (t3) + t2 += H.Primitives_stringFromCharCode(byte); + else + t2 = spaceToPlus && byte === 32 ? t2 + "+" : t2 + "%" + _s16_[byte >>> 4 & 15] + _s16_[byte & 15]; + } + return t2.charCodeAt(0) == 0 ? t2 : t2; + }, + StackTrace_current: function() { + var stackTrace, exception; + if (H.boolConversionCheck($.$get$_hasErrorStackProperty())) + return H.getTraceFromException(new Error()); + try { + throw H.wrapException(""); + } catch (exception) { + H.unwrapException(exception); + stackTrace = H.getTraceFromException(exception); + return stackTrace; + } + }, + DateTime__fourDigits: function(n) { + var absN = Math.abs(n), + sign = n < 0 ? "-" : ""; + if (absN >= 1000) + return "" + n; + if (absN >= 100) + return sign + "0" + absN; + if (absN >= 10) + return sign + "00" + absN; + return sign + "000" + absN; + }, + DateTime__threeDigits: function(n) { + if (n >= 100) + return "" + n; + if (n >= 10) + return "0" + n; + return "00" + n; + }, + DateTime__twoDigits: function(n) { + if (n >= 10) + return "" + n; + return "0" + n; + }, + Duration$: function(microseconds, minutes) { + if (typeof microseconds !== "number") + return H.iae(microseconds); + return new P.Duration(60000000 * minutes + microseconds); + }, + Error_safeToString: function(object) { + if (typeof object == "number" || H._isBool(object) || null == object) + return J.toString$0$(object); + if (typeof object == "string") + return JSON.stringify(object); + return P.Error__objectToString(object); + }, + AssertionError$: function(message) { + return new P.AssertionError(message); + }, + ArgumentError$: function(message) { + return new P.ArgumentError(false, null, null, message); + }, + ArgumentError$value: function(value, $name, message) { + return new P.ArgumentError(true, value, $name, message); + }, + ArgumentError$notNull: function($name) { + return new P.ArgumentError(false, null, $name, "Must not be null"); + }, + RangeError$: function(message) { + var _null = null; + return new P.RangeError(_null, _null, false, _null, _null, message); + }, + RangeError$value: function(value, $name) { + return new P.RangeError(null, null, true, value, $name, "Value not in range"); + }, + RangeError$range: function(invalidValue, minValue, maxValue, $name, message) { + return new P.RangeError(minValue, maxValue, true, invalidValue, $name, "Invalid value"); + }, + RangeError_checkValueInInterval: function(value, minValue, maxValue, $name) { + if (value < minValue || value > maxValue) + throw H.wrapException(P.RangeError$range(value, minValue, maxValue, $name, null)); + }, + RangeError_checkValidRange: function(start, end, $length) { + if (0 > start || start > $length) + throw H.wrapException(P.RangeError$range(start, 0, $length, "start", null)); + if (end != null) { + if (start > end || end > $length) + throw H.wrapException(P.RangeError$range(end, start, $length, "end", null)); + return end; + } + return $length; + }, + RangeError_checkNotNegative: function(value, $name) { + if (typeof value !== "number") + return value.$lt(); + if (value < 0) + throw H.wrapException(P.RangeError$range(value, 0, null, $name, null)); + }, + IndexError$: function(invalidValue, indexable, $name, message, $length) { + var t1 = H._checkIntNullable($length == null ? J.get$length$asx(indexable) : $length); + return new P.IndexError(t1, true, invalidValue, $name, "Index out of range"); + }, + UnsupportedError$: function(message) { + return new P.UnsupportedError(message); + }, + UnimplementedError$: function(message) { + return new P.UnimplementedError(message); + }, + StateError$: function(message) { + return new P.StateError(message); + }, + ConcurrentModificationError$: function(modifiedObject) { + return new P.ConcurrentModificationError(modifiedObject); + }, + FormatException$: function(message, source, offset) { + return new P.FormatException(message, source, offset); + }, + List_List$generate: function($length, generator, growable, $E) { + var i, + result = H.setRuntimeTypeInfo([], $E._eval$1("JSArray<0>")); + C.JSArray_methods.set$length(result, $length); + for (i = 0; i < $length; ++i) + C.JSArray_methods.$indexSet(result, i, generator.call$1(i)); + return result; + }, + Map_castFrom: function(source, $K, $V, K2, V2) { + return new H.CastMap(source, $K._eval$1("@<0>")._bind$1($V)._bind$1(K2)._bind$1(V2)._eval$1("CastMap<1,2,3,4>")); + }, + print: function(object) { + var line = H.S(object), + t1 = $.printToZone; + if (t1 == null) + H.printString(line); + else + t1.call$1(line); + }, + _combineSurrogatePair: function(start, end) { + return 65536 + ((start & 1023) << 10) + (end & 1023); + }, + Uri_parse: function(uri) { + var delta, t1, indices, schemeEnd, hostStart, portStart, pathStart, queryStart, fragmentStart, isSimple, scheme, t2, schemeAuth, queryStart0, pathStart0, _null = null, + end = uri.length; + if (end >= 5) { + delta = ((J._codeUnitAt$1$s(uri, 4) ^ 58) * 3 | C.JSString_methods._codeUnitAt$1(uri, 0) ^ 100 | C.JSString_methods._codeUnitAt$1(uri, 1) ^ 97 | C.JSString_methods._codeUnitAt$1(uri, 2) ^ 116 | C.JSString_methods._codeUnitAt$1(uri, 3) ^ 97) >>> 0; + if (delta === 0) + return P.UriData__parse(end < end ? C.JSString_methods.substring$2(uri, 0, end) : uri, 5, _null).get$uri(); + else if (delta === 32) + return P.UriData__parse(C.JSString_methods.substring$2(uri, 5, end), 0, _null).get$uri(); + } + t1 = new Array(8); + t1.fixed$length = Array; + indices = H.setRuntimeTypeInfo(t1, type$.JSArray_int); + C.JSArray_methods.$indexSet(indices, 0, 0); + C.JSArray_methods.$indexSet(indices, 1, -1); + C.JSArray_methods.$indexSet(indices, 2, -1); + C.JSArray_methods.$indexSet(indices, 7, -1); + C.JSArray_methods.$indexSet(indices, 3, 0); + C.JSArray_methods.$indexSet(indices, 4, 0); + C.JSArray_methods.$indexSet(indices, 5, end); + C.JSArray_methods.$indexSet(indices, 6, end); + if (P._scan(uri, 0, end, 0, indices) >= 14) + C.JSArray_methods.$indexSet(indices, 7, end); + schemeEnd = indices[1]; + if (typeof schemeEnd !== "number") + return schemeEnd.$ge(); + if (schemeEnd >= 0) + if (P._scan(uri, 0, schemeEnd, 20, indices) === 20) + indices[7] = schemeEnd; + t1 = indices[2]; + if (typeof t1 !== "number") + return t1.$add(); + hostStart = t1 + 1; + portStart = indices[3]; + pathStart = indices[4]; + queryStart = indices[5]; + fragmentStart = indices[6]; + if (typeof fragmentStart !== "number") + return fragmentStart.$lt(); + if (typeof queryStart !== "number") + return H.iae(queryStart); + if (fragmentStart < queryStart) + queryStart = fragmentStart; + if (typeof pathStart !== "number") + return pathStart.$lt(); + if (pathStart < hostStart) + pathStart = queryStart; + else if (pathStart <= schemeEnd) + pathStart = schemeEnd + 1; + if (typeof portStart !== "number") + return portStart.$lt(); + if (portStart < hostStart) + portStart = pathStart; + H.assertHelper(hostStart === 0 || schemeEnd <= hostStart); + H.assertHelper(hostStart <= portStart); + H.assertHelper(schemeEnd <= pathStart); + H.assertHelper(portStart <= pathStart); + H.assertHelper(pathStart <= queryStart); + H.assertHelper(queryStart <= fragmentStart); + t1 = indices[7]; + if (typeof t1 !== "number") + return t1.$lt(); + isSimple = t1 < 0; + if (isSimple) + if (hostStart > schemeEnd + 3) { + scheme = _null; + isSimple = false; + } else { + t1 = portStart > 0; + if (t1 && portStart + 1 === pathStart) { + scheme = _null; + isSimple = false; + } else { + if (!(queryStart < end && queryStart === pathStart + 2 && J.startsWith$2$s(uri, "..", pathStart))) + t2 = queryStart > pathStart + 2 && J.startsWith$2$s(uri, "/..", queryStart - 3); + else + t2 = true; + if (t2) { + scheme = _null; + isSimple = false; + } else { + if (schemeEnd === 4) + if (J.startsWith$2$s(uri, "file", 0)) { + if (hostStart <= 0) { + if (!C.JSString_methods.startsWith$2(uri, "/", pathStart)) { + schemeAuth = "file:///"; + delta = 3; + } else { + schemeAuth = "file://"; + delta = 2; + } + uri = schemeAuth + C.JSString_methods.substring$2(uri, pathStart, end); + schemeEnd -= 0; + t1 = delta - 0; + queryStart += t1; + fragmentStart += t1; + end = uri.length; + hostStart = 7; + portStart = 7; + pathStart = 7; + } else if (pathStart === queryStart) { + queryStart0 = queryStart + 1; + ++fragmentStart; + uri = C.JSString_methods.replaceRange$3(uri, pathStart, queryStart, "/"); + ++end; + queryStart = queryStart0; + } + scheme = "file"; + } else if (C.JSString_methods.startsWith$2(uri, "http", 0)) { + if (t1 && portStart + 3 === pathStart && C.JSString_methods.startsWith$2(uri, "80", portStart + 1)) { + pathStart0 = pathStart - 3; + queryStart -= 3; + fragmentStart -= 3; + uri = C.JSString_methods.replaceRange$3(uri, portStart, pathStart, ""); + end -= 3; + pathStart = pathStart0; + } + scheme = "http"; + } else + scheme = _null; + else if (schemeEnd === 5 && J.startsWith$2$s(uri, "https", 0)) { + if (t1 && portStart + 4 === pathStart && J.startsWith$2$s(uri, "443", portStart + 1)) { + pathStart0 = pathStart - 4; + queryStart -= 4; + fragmentStart -= 4; + uri = J.replaceRange$3$asx(uri, portStart, pathStart, ""); + end -= 3; + pathStart = pathStart0; + } + scheme = "https"; + } else + scheme = _null; + isSimple = true; + } + } + } + else + scheme = _null; + if (isSimple) { + t1 = uri.length; + if (end < t1) { + uri = J.substring$2$s(uri, 0, end); + schemeEnd -= 0; + hostStart -= 0; + portStart -= 0; + pathStart -= 0; + queryStart -= 0; + fragmentStart -= 0; + } + return new P._SimpleUri(uri, schemeEnd, hostStart, portStart, pathStart, queryStart, fragmentStart, scheme); + } + return P._Uri__Uri$notSimple(uri, 0, end, schemeEnd, hostStart, portStart, pathStart, queryStart, fragmentStart, scheme); + }, + Uri_decodeComponent: function(encodedComponent) { + H._checkStringNullable(encodedComponent); + return P._Uri__uriDecode(encodedComponent, 0, encodedComponent.length, C.C_Utf8Codec, false); + }, + Uri__parseIPv4Address: function(host, start, end) { + var t1, i, partStart, partIndex, char, part, partIndex0, _null = null, + _s43_ = "IPv4 address should contain exactly 4 parts", + _s37_ = "each part must be in the range 0..255", + error = new P.Uri__parseIPv4Address_error(host), + result = new Uint8Array(4); + for (t1 = result.length, i = start, partStart = i, partIndex = 0; i < end; ++i) { + char = C.JSString_methods.codeUnitAt$1(host, i); + if (char !== 46) { + if ((char ^ 48) > 9) + error.call$2("invalid character", i); + } else { + if (partIndex === 3) + error.call$2(_s43_, i); + part = P.int_parse(C.JSString_methods.substring$2(host, partStart, i), _null, _null); + if (typeof part !== "number") + return part.$gt(); + if (part > 255) + error.call$2(_s37_, partStart); + partIndex0 = partIndex + 1; + if (partIndex >= t1) + return H.ioore(result, partIndex); + result[partIndex] = part; + partStart = i + 1; + partIndex = partIndex0; + } + } + if (partIndex !== 3) + error.call$2(_s43_, end); + part = P.int_parse(C.JSString_methods.substring$2(host, partStart, end), _null, _null); + if (typeof part !== "number") + return part.$gt(); + if (part > 255) + error.call$2(_s37_, partStart); + if (partIndex >= t1) + return H.ioore(result, partIndex); + result[partIndex] = part; + return result; + }, + Uri_parseIPv6Address: function(host, start, end) { + var parts, i, partStart, wildcardSeen, seenDot, char, atEnd, t1, last, bytes, t2, wildCardLength, index, value, j, t3, + error = new P.Uri_parseIPv6Address_error(host), + parseHex = new P.Uri_parseIPv6Address_parseHex(error, host); + if (host.length < 2) + error.call$1("address is too short"); + parts = H.setRuntimeTypeInfo([], type$.JSArray_int); + for (i = start, partStart = i, wildcardSeen = false, seenDot = false; i < end; ++i) { + char = C.JSString_methods.codeUnitAt$1(host, i); + if (char === 58) { + if (i === start) { + ++i; + if (C.JSString_methods.codeUnitAt$1(host, i) !== 58) + error.call$2("invalid start colon.", i); + partStart = i; + } + if (i === partStart) { + if (wildcardSeen) + error.call$2("only one wildcard `::` is allowed", i); + C.JSArray_methods.add$1(parts, -1); + wildcardSeen = true; + } else + C.JSArray_methods.add$1(parts, parseHex.call$2(partStart, i)); + partStart = i + 1; + } else if (char === 46) + seenDot = true; + } + if (parts.length === 0) + error.call$1("too few parts"); + atEnd = partStart === end; + t1 = C.JSArray_methods.get$last(parts); + if (atEnd && t1 !== -1) + error.call$2("expected a part after last `:`", end); + if (!atEnd) + if (!seenDot) + C.JSArray_methods.add$1(parts, parseHex.call$2(partStart, end)); + else { + last = P.Uri__parseIPv4Address(host, partStart, end); + C.JSArray_methods.add$1(parts, (last[0] << 8 | last[1]) >>> 0); + C.JSArray_methods.add$1(parts, (last[2] << 8 | last[3]) >>> 0); + } + if (wildcardSeen) { + if (parts.length > 7) + error.call$1("an address with a wildcard must have less than 7 parts"); + } else if (parts.length !== 8) + error.call$1("an address without a wildcard must contain exactly 8 parts"); + bytes = new Uint8Array(16); + for (t1 = parts.length, t2 = bytes.length, wildCardLength = 9 - t1, i = 0, index = 0; i < t1; ++i) { + value = parts[i]; + if (value === -1) + for (j = 0; j < wildCardLength; ++j) { + if (index < 0 || index >= t2) + return H.ioore(bytes, index); + bytes[index] = 0; + t3 = index + 1; + if (t3 >= t2) + return H.ioore(bytes, t3); + bytes[t3] = 0; + index += 2; + } + else { + t3 = C.JSInt_methods._shrOtherPositive$1(value, 8); + if (index < 0 || index >= t2) + return H.ioore(bytes, index); + bytes[index] = t3; + t3 = index + 1; + if (t3 >= t2) + return H.ioore(bytes, t3); + bytes[t3] = value & 255; + index += 2; + } + } + return bytes; + }, + _Uri__Uri$notSimple: function(uri, start, end, schemeEnd, hostStart, portStart, pathStart, queryStart, fragmentStart, scheme) { + var userInfoStart, userInfo, host, t1, port, path, query, _null = null; + if (scheme == null) + if (schemeEnd > start) + scheme = P._Uri__makeScheme(uri, start, schemeEnd); + else { + if (schemeEnd === start) + P._Uri__fail(uri, start, "Invalid empty scheme"); + scheme = ""; + } + if (hostStart > start) { + userInfoStart = schemeEnd + 3; + userInfo = userInfoStart < hostStart ? P._Uri__makeUserInfo(uri, userInfoStart, hostStart - 1) : ""; + host = P._Uri__makeHost(uri, hostStart, portStart, false); + t1 = portStart + 1; + port = t1 < pathStart ? P._Uri__makePort(P.int_parse(J.substring$2$s(uri, t1, pathStart), new P._Uri__Uri$notSimple_closure(uri, portStart), _null), scheme) : _null; + } else { + port = _null; + host = port; + userInfo = ""; + } + path = P._Uri__makePath(uri, pathStart, queryStart, _null, scheme, host != null); + query = queryStart < fragmentStart ? P._Uri__makeQuery(uri, queryStart + 1, fragmentStart, _null) : _null; + return new P._Uri(scheme, userInfo, host, port, path, query, fragmentStart < end ? P._Uri__makeFragment(uri, fragmentStart + 1, end) : _null); + }, + _Uri__Uri: function(host, path, pathSegments, scheme) { + var userInfo, query, fragment, port, isFile, t1, hasAuthority, t2, _null = null; + scheme = P._Uri__makeScheme(scheme, 0, scheme == null ? 0 : scheme.length); + userInfo = P._Uri__makeUserInfo(_null, 0, 0); + host = P._Uri__makeHost(host, 0, host == null ? 0 : host.length, false); + query = P._Uri__makeQuery(_null, 0, 0, _null); + fragment = P._Uri__makeFragment(_null, 0, 0); + port = P._Uri__makePort(_null, scheme); + isFile = scheme === "file"; + if (host == null) + t1 = userInfo.length !== 0 || port != null || isFile; + else + t1 = false; + if (t1) + host = ""; + t1 = host == null; + hasAuthority = !t1; + path = P._Uri__makePath(path, 0, path == null ? 0 : path.length, pathSegments, scheme, hasAuthority); + t2 = scheme.length === 0; + if (t2 && t1 && !C.JSString_methods.startsWith$1(path, "/")) + path = P._Uri__normalizeRelativePath(path, !t2 || hasAuthority); + else + path = P._Uri__removeDotSegments(path); + return new P._Uri(scheme, userInfo, t1 && C.JSString_methods.startsWith$1(path, "//") ? "" : host, port, path, query, fragment); + }, + _Uri__defaultPort: function(scheme) { + if (scheme === "http") + return 80; + if (scheme === "https") + return 443; + return 0; + }, + _Uri__fail: function(uri, index, message) { + throw H.wrapException(P.FormatException$(message, uri, index)); + }, + _Uri__Uri$file: function(path, windows) { + return windows ? P._Uri__makeWindowsFileUrl(path, false) : P._Uri__makeFileUri(path, false); + }, + _Uri__checkNonWindowsPathReservedCharacters: function(segments, argumentError) { + C.JSArray_methods.forEach$1(segments, new P._Uri__checkNonWindowsPathReservedCharacters_closure(false)); + }, + _Uri__checkWindowsPathReservedCharacters: function(segments, argumentError, firstSegment) { + var t1, t2; + for (t1 = H.SubListIterable$(segments, firstSegment, null, H._arrayInstanceType(segments)._precomputed1), t1 = new H.ListIterator(t1, t1.get$length(t1), t1.$ti._eval$1("ListIterator<ListIterable.E>")); t1.moveNext$0();) { + t2 = t1.__internal$_current; + if (J.contains$1$asx(t2, P.RegExp_RegExp('["*/:<>?\\\\|]', false))) + if (argumentError) + throw H.wrapException(P.ArgumentError$("Illegal character in path")); + else + throw H.wrapException(P.UnsupportedError$("Illegal character in path: " + t2)); + } + }, + _Uri__checkWindowsDriveLetter: function(charCode, argumentError) { + var t1, + _s21_ = "Illegal drive letter "; + if (!(65 <= charCode && charCode <= 90)) + t1 = 97 <= charCode && charCode <= 122; + else + t1 = true; + if (t1) + return; + if (argumentError) + throw H.wrapException(P.ArgumentError$(_s21_ + P.String_String$fromCharCode(charCode))); + else + throw H.wrapException(P.UnsupportedError$(_s21_ + P.String_String$fromCharCode(charCode))); + }, + _Uri__makeFileUri: function(path, slashTerminated) { + var _null = null, + segments = H.setRuntimeTypeInfo(path.split("/"), type$.JSArray_String); + if (C.JSString_methods.startsWith$1(path, "/")) + return P._Uri__Uri(_null, _null, segments, "file"); + else + return P._Uri__Uri(_null, _null, segments, _null); + }, + _Uri__makeWindowsFileUrl: function(path, slashTerminated) { + var t1, pathSegments, pathStart, hostPart, _s1_ = "\\", _null = null, _s4_ = "file"; + if (C.JSString_methods.startsWith$1(path, "\\\\?\\")) + if (C.JSString_methods.startsWith$2(path, "UNC\\", 4)) + path = C.JSString_methods.replaceRange$3(path, 0, 7, _s1_); + else { + path = C.JSString_methods.substring$1(path, 4); + if (path.length < 3 || C.JSString_methods._codeUnitAt$1(path, 1) !== 58 || C.JSString_methods._codeUnitAt$1(path, 2) !== 92) + throw H.wrapException(P.ArgumentError$("Windows paths with \\\\?\\ prefix must be absolute")); + } + else + path = H.stringReplaceAllUnchecked(path, "/", _s1_); + t1 = path.length; + if (t1 > 1 && C.JSString_methods._codeUnitAt$1(path, 1) === 58) { + P._Uri__checkWindowsDriveLetter(C.JSString_methods._codeUnitAt$1(path, 0), true); + if (t1 === 2 || C.JSString_methods._codeUnitAt$1(path, 2) !== 92) + throw H.wrapException(P.ArgumentError$("Windows paths with drive letter must be absolute")); + pathSegments = H.setRuntimeTypeInfo(path.split(_s1_), type$.JSArray_String); + P._Uri__checkWindowsPathReservedCharacters(pathSegments, true, 1); + return P._Uri__Uri(_null, _null, pathSegments, _s4_); + } + if (C.JSString_methods.startsWith$1(path, _s1_)) + if (C.JSString_methods.startsWith$2(path, _s1_, 1)) { + pathStart = C.JSString_methods.indexOf$2(path, _s1_, 2); + t1 = pathStart < 0; + hostPart = t1 ? C.JSString_methods.substring$1(path, 2) : C.JSString_methods.substring$2(path, 2, pathStart); + pathSegments = H.setRuntimeTypeInfo((t1 ? "" : C.JSString_methods.substring$1(path, pathStart + 1)).split(_s1_), type$.JSArray_String); + P._Uri__checkWindowsPathReservedCharacters(pathSegments, true, 0); + return P._Uri__Uri(hostPart, _null, pathSegments, _s4_); + } else { + pathSegments = H.setRuntimeTypeInfo(path.split(_s1_), type$.JSArray_String); + P._Uri__checkWindowsPathReservedCharacters(pathSegments, true, 0); + return P._Uri__Uri(_null, _null, pathSegments, _s4_); + } + else { + pathSegments = H.setRuntimeTypeInfo(path.split(_s1_), type$.JSArray_String); + P._Uri__checkWindowsPathReservedCharacters(pathSegments, true, 0); + return P._Uri__Uri(_null, _null, pathSegments, _null); + } + }, + _Uri__makePort: function(port, scheme) { + if (port != null && port === P._Uri__defaultPort(scheme)) + return null; + return port; + }, + _Uri__makeHost: function(host, start, end, strictIPv6) { + var t1, t2, index, zoneIDstart, zoneID, i; + if (host == null) + return null; + if (start === end) + return ""; + if (C.JSString_methods.codeUnitAt$1(host, start) === 91) { + t1 = end - 1; + if (C.JSString_methods.codeUnitAt$1(host, t1) !== 93) + P._Uri__fail(host, start, "Missing end `]` to match `[` in host"); + t2 = start + 1; + index = P._Uri__checkZoneID(host, t2, t1); + if (index < t1) { + zoneIDstart = index + 1; + zoneID = P._Uri__normalizeZoneID(host, C.JSString_methods.startsWith$2(host, "25", zoneIDstart) ? index + 3 : zoneIDstart, t1, "%25"); + } else + zoneID = ""; + P.Uri_parseIPv6Address(host, t2, index); + return C.JSString_methods.substring$2(host, start, index).toLowerCase() + zoneID + "]"; + } + for (i = start; i < end; ++i) + if (C.JSString_methods.codeUnitAt$1(host, i) === 58) { + index = C.JSString_methods.indexOf$2(host, "%", start); + index = index >= start && index < end ? index : end; + if (index < end) { + zoneIDstart = index + 1; + zoneID = P._Uri__normalizeZoneID(host, C.JSString_methods.startsWith$2(host, "25", zoneIDstart) ? index + 3 : zoneIDstart, end, "%25"); + } else + zoneID = ""; + P.Uri_parseIPv6Address(host, start, index); + return "[" + C.JSString_methods.substring$2(host, start, index) + zoneID + "]"; + } + return P._Uri__normalizeRegName(host, start, end); + }, + _Uri__checkZoneID: function(host, start, end) { + var index = C.JSString_methods.indexOf$2(host, "%", start); + return index >= start && index < end ? index : end; + }, + _Uri__normalizeZoneID: function(host, start, end, prefix) { + var index, sectionStart, isNormalized, char, replacement, t1, t2, tail, sourceLength, + buffer = prefix !== "" ? new P.StringBuffer(prefix) : null; + for (index = start, sectionStart = index, isNormalized = true; index < end;) { + char = C.JSString_methods.codeUnitAt$1(host, index); + if (char === 37) { + replacement = P._Uri__normalizeEscape(host, index, true); + t1 = replacement == null; + if (t1 && isNormalized) { + index += 3; + continue; + } + if (buffer == null) + buffer = new P.StringBuffer(""); + t2 = buffer._contents += C.JSString_methods.substring$2(host, sectionStart, index); + if (t1) + replacement = C.JSString_methods.substring$2(host, index, index + 3); + else if (replacement === "%") + P._Uri__fail(host, index, "ZoneID should not contain % anymore"); + buffer._contents = t2 + replacement; + index += 3; + sectionStart = index; + isNormalized = true; + } else { + if (char < 127) { + t1 = char >>> 4; + if (t1 >= 8) + return H.ioore(C.List_nxB, t1); + t1 = (C.List_nxB[t1] & 1 << (char & 15)) !== 0; + } else + t1 = false; + if (t1) { + if (isNormalized && 65 <= char && 90 >= char) { + if (buffer == null) + buffer = new P.StringBuffer(""); + if (sectionStart < index) { + buffer._contents += C.JSString_methods.substring$2(host, sectionStart, index); + sectionStart = index; + } + isNormalized = false; + } + ++index; + } else { + if ((char & 64512) === 55296 && index + 1 < end) { + tail = C.JSString_methods.codeUnitAt$1(host, index + 1); + if ((tail & 64512) === 56320) { + char = 65536 | (char & 1023) << 10 | tail & 1023; + sourceLength = 2; + } else + sourceLength = 1; + } else + sourceLength = 1; + if (buffer == null) + buffer = new P.StringBuffer(""); + buffer._contents += C.JSString_methods.substring$2(host, sectionStart, index); + buffer._contents += P._Uri__escapeChar(char); + index += sourceLength; + sectionStart = index; + } + } + } + if (buffer == null) + return C.JSString_methods.substring$2(host, start, end); + if (sectionStart < end) + buffer._contents += C.JSString_methods.substring$2(host, sectionStart, end); + t1 = buffer._contents; + return t1.charCodeAt(0) == 0 ? t1 : t1; + }, + _Uri__normalizeRegName: function(host, start, end) { + var index, sectionStart, buffer, isNormalized, char, replacement, t1, slice, t2, sourceLength, tail; + for (index = start, sectionStart = index, buffer = null, isNormalized = true; index < end;) { + char = C.JSString_methods.codeUnitAt$1(host, index); + if (char === 37) { + replacement = P._Uri__normalizeEscape(host, index, true); + t1 = replacement == null; + if (t1 && isNormalized) { + index += 3; + continue; + } + if (buffer == null) + buffer = new P.StringBuffer(""); + slice = C.JSString_methods.substring$2(host, sectionStart, index); + t2 = buffer._contents += !isNormalized ? slice.toLowerCase() : slice; + if (t1) { + replacement = C.JSString_methods.substring$2(host, index, index + 3); + sourceLength = 3; + } else if (replacement === "%") { + replacement = "%25"; + sourceLength = 1; + } else + sourceLength = 3; + buffer._contents = t2 + replacement; + index += sourceLength; + sectionStart = index; + isNormalized = true; + } else { + if (char < 127) { + t1 = char >>> 4; + if (t1 >= 8) + return H.ioore(C.List_qNA, t1); + t1 = (C.List_qNA[t1] & 1 << (char & 15)) !== 0; + } else + t1 = false; + if (t1) { + if (isNormalized && 65 <= char && 90 >= char) { + if (buffer == null) + buffer = new P.StringBuffer(""); + if (sectionStart < index) { + buffer._contents += C.JSString_methods.substring$2(host, sectionStart, index); + sectionStart = index; + } + isNormalized = false; + } + ++index; + } else { + if (char <= 93) { + t1 = char >>> 4; + if (t1 >= 8) + return H.ioore(C.List_2Vk, t1); + t1 = (C.List_2Vk[t1] & 1 << (char & 15)) !== 0; + } else + t1 = false; + if (t1) + P._Uri__fail(host, index, "Invalid character"); + else { + if ((char & 64512) === 55296 && index + 1 < end) { + tail = C.JSString_methods.codeUnitAt$1(host, index + 1); + if ((tail & 64512) === 56320) { + char = 65536 | (char & 1023) << 10 | tail & 1023; + sourceLength = 2; + } else + sourceLength = 1; + } else + sourceLength = 1; + if (buffer == null) + buffer = new P.StringBuffer(""); + slice = C.JSString_methods.substring$2(host, sectionStart, index); + buffer._contents += !isNormalized ? slice.toLowerCase() : slice; + buffer._contents += P._Uri__escapeChar(char); + index += sourceLength; + sectionStart = index; + } + } + } + } + if (buffer == null) + return C.JSString_methods.substring$2(host, start, end); + if (sectionStart < end) { + slice = C.JSString_methods.substring$2(host, sectionStart, end); + buffer._contents += !isNormalized ? slice.toLowerCase() : slice; + } + t1 = buffer._contents; + return t1.charCodeAt(0) == 0 ? t1 : t1; + }, + _Uri__makeScheme: function(scheme, start, end) { + var i, containsUpperCase, codeUnit, t1; + if (start === end) + return ""; + if (!P._Uri__isAlphabeticCharacter(J.getInterceptor$s(scheme)._codeUnitAt$1(scheme, start))) + P._Uri__fail(scheme, start, "Scheme not starting with alphabetic character"); + for (i = start, containsUpperCase = false; i < end; ++i) { + codeUnit = C.JSString_methods._codeUnitAt$1(scheme, i); + if (codeUnit < 128) { + t1 = codeUnit >>> 4; + if (t1 >= 8) + return H.ioore(C.List_JYB, t1); + t1 = (C.List_JYB[t1] & 1 << (codeUnit & 15)) !== 0; + } else + t1 = false; + if (!t1) + P._Uri__fail(scheme, i, "Illegal scheme character"); + if (65 <= codeUnit && codeUnit <= 90) + containsUpperCase = true; + } + scheme = C.JSString_methods.substring$2(scheme, start, end); + return P._Uri__canonicalizeScheme(containsUpperCase ? scheme.toLowerCase() : scheme); + }, + _Uri__canonicalizeScheme: function(scheme) { + if (scheme === "http") + return "http"; + if (scheme === "file") + return "file"; + if (scheme === "https") + return "https"; + if (scheme === "package") + return "package"; + return scheme; + }, + _Uri__makeUserInfo: function(userInfo, start, end) { + if (userInfo == null) + return ""; + return P._Uri__normalizeOrSubstring(userInfo, start, end, C.List_gRj, false); + }, + _Uri__makePath: function(path, start, end, pathSegments, scheme, hasAuthority) { + var result, + isFile = scheme === "file", + ensureLeadingSlash = isFile || hasAuthority, + t1 = path == null; + if (t1 && pathSegments == null) + return isFile ? "/" : ""; + t1 = !t1; + if (t1 && pathSegments != null) + throw H.wrapException(P.ArgumentError$("Both path and pathSegments specified")); + if (t1) + result = P._Uri__normalizeOrSubstring(path, start, end, C.List_qg4, true); + else { + pathSegments.toString; + t1 = H._arrayInstanceType(pathSegments); + result = new H.MappedListIterable(pathSegments, t1._eval$1("String(1)")._check(new P._Uri__makePath_closure()), t1._eval$1("MappedListIterable<1,String>")).join$1(0, "/"); + } + if (result.length === 0) { + if (isFile) + return "/"; + } else if (ensureLeadingSlash && !C.JSString_methods.startsWith$1(result, "/")) + result = "/" + result; + return P._Uri__normalizePath(result, scheme, hasAuthority); + }, + _Uri__normalizePath: function(path, scheme, hasAuthority) { + var t1 = scheme.length === 0; + if (t1 && !hasAuthority && !C.JSString_methods.startsWith$1(path, "/")) + return P._Uri__normalizeRelativePath(path, !t1 || hasAuthority); + return P._Uri__removeDotSegments(path); + }, + _Uri__makeQuery: function(query, start, end, queryParameters) { + if (query != null) + return P._Uri__normalizeOrSubstring(query, start, end, C.List_CVk, true); + return null; + }, + _Uri__makeFragment: function(fragment, start, end) { + if (fragment == null) + return null; + return P._Uri__normalizeOrSubstring(fragment, start, end, C.List_CVk, true); + }, + _Uri__normalizeEscape: function(source, index, lowerCase) { + var t1, firstDigit, secondDigit, firstDigitValue, secondDigitValue, value; + H.assertHelper(C.JSString_methods.codeUnitAt$1(source, index) === 37); + t1 = index + 2; + if (t1 >= source.length) + return "%"; + firstDigit = C.JSString_methods.codeUnitAt$1(source, index + 1); + secondDigit = C.JSString_methods.codeUnitAt$1(source, t1); + firstDigitValue = H.hexDigitValue(firstDigit); + secondDigitValue = H.hexDigitValue(secondDigit); + if (firstDigitValue < 0 || secondDigitValue < 0) + return "%"; + value = firstDigitValue * 16 + secondDigitValue; + if (value < 127) { + t1 = C.JSInt_methods._shrOtherPositive$1(value, 4); + if (t1 >= 8) + return H.ioore(C.List_nxB, t1); + t1 = (C.List_nxB[t1] & 1 << (value & 15)) !== 0; + } else + t1 = false; + if (t1) + return H.Primitives_stringFromCharCode(lowerCase && 65 <= value && 90 >= value ? (value | 32) >>> 0 : value); + if (firstDigit >= 97 || secondDigit >= 97) + return C.JSString_methods.substring$2(source, index, index + 3).toUpperCase(); + return null; + }, + _Uri__escapeChar: function(char) { + var t1, codeUnits, flag, encodedBytes, index, byte, + _s16_ = "0123456789ABCDEF"; + H.assertHelper(char <= 1114111); + if (char < 128) { + t1 = new Array(3); + t1.fixed$length = Array; + codeUnits = H.setRuntimeTypeInfo(t1, type$.JSArray_int); + C.JSArray_methods.$indexSet(codeUnits, 0, 37); + C.JSArray_methods.$indexSet(codeUnits, 1, C.JSString_methods._codeUnitAt$1(_s16_, char >>> 4)); + C.JSArray_methods.$indexSet(codeUnits, 2, C.JSString_methods._codeUnitAt$1(_s16_, char & 15)); + } else { + if (char > 2047) + if (char > 65535) { + flag = 240; + encodedBytes = 4; + } else { + flag = 224; + encodedBytes = 3; + } + else { + flag = 192; + encodedBytes = 2; + } + t1 = new Array(3 * encodedBytes); + t1.fixed$length = Array; + codeUnits = H.setRuntimeTypeInfo(t1, type$.JSArray_int); + for (index = 0; --encodedBytes, encodedBytes >= 0; flag = 128) { + byte = C.JSInt_methods._shrReceiverPositive$1(char, 6 * encodedBytes) & 63 | flag; + C.JSArray_methods.$indexSet(codeUnits, index, 37); + C.JSArray_methods.$indexSet(codeUnits, index + 1, C.JSString_methods._codeUnitAt$1(_s16_, byte >>> 4)); + C.JSArray_methods.$indexSet(codeUnits, index + 2, C.JSString_methods._codeUnitAt$1(_s16_, byte & 15)); + index += 3; + } + } + return P.String_String$fromCharCodes(codeUnits, 0, null); + }, + _Uri__normalizeOrSubstring: function(component, start, end, charTable, escapeDelimiters) { + var t1 = P._Uri__normalize(component, start, end, charTable, escapeDelimiters); + return t1 == null ? C.JSString_methods.substring$2(component, start, end) : t1; + }, + _Uri__normalize: function(component, start, end, charTable, escapeDelimiters) { + var t1, index, sectionStart, buffer, char, t2, replacement, sourceLength, tail, _null = null; + for (t1 = !escapeDelimiters, index = start, sectionStart = index, buffer = _null; index < end;) { + char = C.JSString_methods.codeUnitAt$1(component, index); + if (char < 127) { + t2 = char >>> 4; + if (t2 >= 8) + return H.ioore(charTable, t2); + t2 = (charTable[t2] & 1 << (char & 15)) !== 0; + } else + t2 = false; + if (t2) + ++index; + else { + if (char === 37) { + replacement = P._Uri__normalizeEscape(component, index, false); + if (replacement == null) { + index += 3; + continue; + } + if ("%" === replacement) { + replacement = "%25"; + sourceLength = 1; + } else + sourceLength = 3; + } else { + if (t1) + if (char <= 93) { + t2 = char >>> 4; + if (t2 >= 8) + return H.ioore(C.List_2Vk, t2); + t2 = (C.List_2Vk[t2] & 1 << (char & 15)) !== 0; + } else + t2 = false; + else + t2 = false; + if (t2) { + P._Uri__fail(component, index, "Invalid character"); + sourceLength = _null; + replacement = sourceLength; + } else { + if ((char & 64512) === 55296) { + t2 = index + 1; + if (t2 < end) { + tail = C.JSString_methods.codeUnitAt$1(component, t2); + if ((tail & 64512) === 56320) { + char = 65536 | (char & 1023) << 10 | tail & 1023; + sourceLength = 2; + } else + sourceLength = 1; + } else + sourceLength = 1; + } else + sourceLength = 1; + replacement = P._Uri__escapeChar(char); + } + } + if (buffer == null) + buffer = new P.StringBuffer(""); + buffer._contents += C.JSString_methods.substring$2(component, sectionStart, index); + buffer._contents += H.S(replacement); + if (typeof sourceLength !== "number") + return H.iae(sourceLength); + index += sourceLength; + sectionStart = index; + } + } + if (buffer == null) + return _null; + if (sectionStart < end) + buffer._contents += C.JSString_methods.substring$2(component, sectionStart, end); + t1 = buffer._contents; + return t1.charCodeAt(0) == 0 ? t1 : t1; + }, + _Uri__mayContainDotSegments: function(path) { + if (C.JSString_methods.startsWith$1(path, ".")) + return true; + return C.JSString_methods.indexOf$1(path, "/.") !== -1; + }, + _Uri__removeDotSegments: function(path) { + var output, t1, t2, appendSlash, _i, segment, t3; + if (!P._Uri__mayContainDotSegments(path)) + return path; + H.assertHelper(path.length !== 0); + output = H.setRuntimeTypeInfo([], type$.JSArray_String); + for (t1 = path.split("/"), t2 = t1.length, appendSlash = false, _i = 0; _i < t2; ++_i) { + segment = t1[_i]; + if (J.$eq$(segment, "..")) { + t3 = output.length; + if (t3 !== 0) { + if (0 >= t3) + return H.ioore(output, -1); + output.pop(); + if (output.length === 0) + C.JSArray_methods.add$1(output, ""); + } + appendSlash = true; + } else if ("." === segment) + appendSlash = true; + else { + C.JSArray_methods.add$1(output, segment); + appendSlash = false; + } + } + if (appendSlash) + C.JSArray_methods.add$1(output, ""); + return C.JSArray_methods.join$1(output, "/"); + }, + _Uri__normalizeRelativePath: function(path, allowScheme) { + var output, t1, t2, appendSlash, _i, segment; + H.assertHelper(!C.JSString_methods.startsWith$1(path, "/")); + if (!P._Uri__mayContainDotSegments(path)) + return !allowScheme ? P._Uri__escapeScheme(path) : path; + H.assertHelper(path.length !== 0); + output = H.setRuntimeTypeInfo([], type$.JSArray_String); + for (t1 = path.split("/"), t2 = t1.length, appendSlash = false, _i = 0; _i < t2; ++_i) { + segment = t1[_i]; + if (".." === segment) + if (output.length !== 0 && C.JSArray_methods.get$last(output) !== "..") { + if (0 >= output.length) + return H.ioore(output, -1); + output.pop(); + appendSlash = true; + } else { + C.JSArray_methods.add$1(output, ".."); + appendSlash = false; + } + else if ("." === segment) + appendSlash = true; + else { + C.JSArray_methods.add$1(output, segment); + appendSlash = false; + } + } + t1 = output.length; + if (t1 !== 0) + if (t1 === 1) { + if (0 >= t1) + return H.ioore(output, 0); + t1 = output[0].length === 0; + } else + t1 = false; + else + t1 = true; + if (t1) + return "./"; + if (appendSlash || C.JSArray_methods.get$last(output) === "..") + C.JSArray_methods.add$1(output, ""); + if (!allowScheme) { + if (0 >= output.length) + return H.ioore(output, 0); + C.JSArray_methods.$indexSet(output, 0, P._Uri__escapeScheme(output[0])); + } + return C.JSArray_methods.join$1(output, "/"); + }, + _Uri__escapeScheme: function(path) { + var i, char, t2, + t1 = path.length; + if (t1 >= 2 && P._Uri__isAlphabeticCharacter(J._codeUnitAt$1$s(path, 0))) + for (i = 1; i < t1; ++i) { + char = C.JSString_methods._codeUnitAt$1(path, i); + if (char === 58) + return C.JSString_methods.substring$2(path, 0, i) + "%3A" + C.JSString_methods.substring$1(path, i + 1); + if (char <= 127) { + t2 = char >>> 4; + if (t2 >= 8) + return H.ioore(C.List_JYB, t2); + t2 = (C.List_JYB[t2] & 1 << (char & 15)) === 0; + } else + t2 = true; + if (t2) + break; + } + return path; + }, + _Uri__toWindowsFilePath: function(uri) { + var hasDriveLetter, t2, host, + segments = uri.get$pathSegments(), + t1 = segments.length; + if (t1 > 0 && J.get$length$asx(segments[0]) === 2 && J.codeUnitAt$1$s(segments[0], 1) === 58) { + if (0 >= t1) + return H.ioore(segments, 0); + P._Uri__checkWindowsDriveLetter(J.codeUnitAt$1$s(segments[0], 0), false); + P._Uri__checkWindowsPathReservedCharacters(segments, false, 1); + hasDriveLetter = true; + } else { + P._Uri__checkWindowsPathReservedCharacters(segments, false, 0); + hasDriveLetter = false; + } + t2 = uri.get$hasAbsolutePath() && !hasDriveLetter ? "\\" : ""; + if (uri.get$hasAuthority()) { + host = uri.get$host(uri); + if (host.length !== 0) + t2 = t2 + "\\" + host + "\\"; + } + t2 = P.StringBuffer__writeAll(t2, segments, "\\"); + t1 = hasDriveLetter && t1 === 1 ? t2 + "\\" : t2; + return t1.charCodeAt(0) == 0 ? t1 : t1; + }, + _Uri__hexCharPairToByte: function(s, pos) { + var byte, i, charCode; + for (byte = 0, i = 0; i < 2; ++i) { + charCode = C.JSString_methods._codeUnitAt$1(s, pos + i); + if (48 <= charCode && charCode <= 57) + byte = byte * 16 + charCode - 48; + else { + charCode |= 32; + if (97 <= charCode && charCode <= 102) + byte = byte * 16 + charCode - 87; + else + throw H.wrapException(P.ArgumentError$("Invalid URL encoding")); + } + } + return byte; + }, + _Uri__uriDecode: function(text, start, end, encoding, plusToSpace) { + var t1, simple, t2, i, codeUnit, t3, bytes; + H.assertHelper(start <= end); + t1 = text.length; + H.assertHelper(end <= t1); + t2 = J.getInterceptor$s(text); + i = start; + while (true) { + if (!(i < end)) { + simple = true; + break; + } + codeUnit = t2._codeUnitAt$1(text, i); + if (codeUnit <= 127) + if (codeUnit !== 37) + t3 = false; + else + t3 = true; + else + t3 = true; + if (t3) { + simple = false; + break; + } + ++i; + } + if (simple) { + if (C.C_Utf8Codec !== encoding) + t1 = false; + else + t1 = true; + if (t1) + return t2.substring$2(text, start, end); + else + bytes = new H.CodeUnits(t2.substring$2(text, start, end)); + } else { + bytes = H.setRuntimeTypeInfo([], type$.JSArray_int); + for (i = start; i < end; ++i) { + codeUnit = t2._codeUnitAt$1(text, i); + if (codeUnit > 127) + throw H.wrapException(P.ArgumentError$("Illegal percent encoding in URI")); + if (codeUnit === 37) { + if (i + 3 > t1) + throw H.wrapException(P.ArgumentError$("Truncated URI")); + C.JSArray_methods.add$1(bytes, P._Uri__hexCharPairToByte(text, i + 1)); + i += 2; + } else + C.JSArray_methods.add$1(bytes, codeUnit); + } + } + type$.List_int._check(bytes); + return new P.Utf8Decoder(false).convert$1(bytes); + }, + _Uri__isAlphabeticCharacter: function(codeUnit) { + var lowerCase = codeUnit | 32; + return 97 <= lowerCase && lowerCase <= 122; + }, + UriData__writeUri: function(mimeType, charsetName, parameters, buffer, indices) { + var slashIndex, t1; + if (true) + buffer._contents = buffer._contents; + else { + slashIndex = P.UriData__validateMimeType(""); + if (slashIndex < 0) + throw H.wrapException(P.ArgumentError$value("", "mimeType", "Invalid MIME type")); + t1 = buffer._contents += H.S(P._Uri__uriEncode(C.List_qFt, C.JSString_methods.substring$2("", 0, slashIndex), C.C_Utf8Codec, false)); + buffer._contents = t1 + "/"; + buffer._contents += H.S(P._Uri__uriEncode(C.List_qFt, C.JSString_methods.substring$1("", slashIndex + 1), C.C_Utf8Codec, false)); + } + }, + UriData__validateMimeType: function(mimeType) { + var t1, slashIndex, i; + for (t1 = mimeType.length, slashIndex = -1, i = 0; i < t1; ++i) { + if (C.JSString_methods._codeUnitAt$1(mimeType, i) !== 47) + continue; + if (slashIndex < 0) { + slashIndex = i; + continue; + } + return -1; + } + return slashIndex; + }, + UriData__parse: function(text, start, sourceUri) { + var indices, t1, i, slashIndex, char, equalsIndex, lastSeparator, t2, data, + _s17_ = "Invalid MIME type"; + H.assertHelper(start === 0 || start === 5); + H.assertHelper(start === 5 === C.JSString_methods.startsWith$1(text, "data:")); + indices = H.setRuntimeTypeInfo([start - 1], type$.JSArray_int); + for (t1 = text.length, i = start, slashIndex = -1, char = null; i < t1; ++i) { + char = C.JSString_methods._codeUnitAt$1(text, i); + if (char === 44 || char === 59) + break; + if (char === 47) { + if (slashIndex < 0) { + slashIndex = i; + continue; + } + throw H.wrapException(P.FormatException$(_s17_, text, i)); + } + } + if (slashIndex < 0 && i > start) + throw H.wrapException(P.FormatException$(_s17_, text, i)); + for (; char !== 44;) { + C.JSArray_methods.add$1(indices, i); + ++i; + for (equalsIndex = -1; i < t1; ++i) { + char = C.JSString_methods._codeUnitAt$1(text, i); + if (char === 61) { + if (equalsIndex < 0) + equalsIndex = i; + } else if (char === 59 || char === 44) + break; + } + if (equalsIndex >= 0) + C.JSArray_methods.add$1(indices, equalsIndex); + else { + lastSeparator = C.JSArray_methods.get$last(indices); + if (char !== 44 || i !== lastSeparator + 7 || !C.JSString_methods.startsWith$2(text, "base64", lastSeparator + 1)) + throw H.wrapException(P.FormatException$("Expecting '='", text, i)); + break; + } + } + C.JSArray_methods.add$1(indices, i); + t2 = i + 1; + if ((indices.length & 1) === 1) + text = C.C_Base64Codec.normalize$3(text, t2, t1); + else { + data = P._Uri__normalize(text, t2, t1, C.List_CVk, true); + if (data != null) + text = C.JSString_methods.replaceRange$3(text, t2, t1, data); + } + return new P.UriData(text, indices, sourceUri); + }, + UriData__uriEncodeBytes: function(canonicalTable, bytes, buffer) { + var t1, byteOr, i, byte, t2, t3, + _s16_ = "0123456789ABCDEF"; + for (t1 = J.getInterceptor$asx(bytes), byteOr = 0, i = 0; i < t1.get$length(bytes); ++i) { + byte = t1.$index(bytes, i); + if (typeof byte !== "number") + return H.iae(byte); + byteOr |= byte; + if (byte < 128) { + t2 = C.JSInt_methods._shrOtherPositive$1(byte, 4); + if (t2 >= 8) + return H.ioore(canonicalTable, t2); + t2 = (canonicalTable[t2] & 1 << (byte & 15)) !== 0; + } else + t2 = false; + t3 = buffer._contents; + if (t2) + buffer._contents = t3 + H.Primitives_stringFromCharCode(byte); + else { + t2 = t3 + H.Primitives_stringFromCharCode(37); + buffer._contents = t2; + t2 += H.Primitives_stringFromCharCode(C.JSString_methods._codeUnitAt$1(_s16_, C.JSInt_methods._shrOtherPositive$1(byte, 4))); + buffer._contents = t2; + buffer._contents = t2 + H.Primitives_stringFromCharCode(C.JSString_methods._codeUnitAt$1(_s16_, byte & 15)); + } + } + if ((byteOr & 4294967040) >>> 0 !== 0) + for (i = 0; i < t1.get$length(bytes); ++i) { + byte = t1.$index(bytes, i); + if (typeof byte !== "number") + return byte.$lt(); + if (byte < 0 || byte > 255) + throw H.wrapException(P.ArgumentError$value(byte, "non-byte value", null)); + } + }, + _createTables: function() { + var _s77_ = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._~!$&'()*+,;=", + _s1_ = ".", _s1_0 = ":", _s1_1 = "/", _s1_2 = "?", _s1_3 = "#", + t1 = type$.Uint8List, + tables = P.List_List$generate(22, new P._createTables_closure(), true, t1), + t2 = new P._createTables_build(tables), + t3 = new P._createTables_setChars(), + t4 = new P._createTables_setRange(), + t5 = t1._check(t2.call$2(0, 225)); + t3.call$3(t5, _s77_, 1); + t3.call$3(t5, _s1_, 14); + t3.call$3(t5, _s1_0, 34); + t3.call$3(t5, _s1_1, 3); + t3.call$3(t5, _s1_2, 172); + t3.call$3(t5, _s1_3, 205); + t5 = t1._check(t2.call$2(14, 225)); + t3.call$3(t5, _s77_, 1); + t3.call$3(t5, _s1_, 15); + t3.call$3(t5, _s1_0, 34); + t3.call$3(t5, _s1_1, 234); + t3.call$3(t5, _s1_2, 172); + t3.call$3(t5, _s1_3, 205); + t5 = t1._check(t2.call$2(15, 225)); + t3.call$3(t5, _s77_, 1); + t3.call$3(t5, "%", 225); + t3.call$3(t5, _s1_0, 34); + t3.call$3(t5, _s1_1, 9); + t3.call$3(t5, _s1_2, 172); + t3.call$3(t5, _s1_3, 205); + t5 = t1._check(t2.call$2(1, 225)); + t3.call$3(t5, _s77_, 1); + t3.call$3(t5, _s1_0, 34); + t3.call$3(t5, _s1_1, 10); + t3.call$3(t5, _s1_2, 172); + t3.call$3(t5, _s1_3, 205); + t5 = t1._check(t2.call$2(2, 235)); + t3.call$3(t5, _s77_, 139); + t3.call$3(t5, _s1_1, 131); + t3.call$3(t5, _s1_, 146); + t3.call$3(t5, _s1_2, 172); + t3.call$3(t5, _s1_3, 205); + t5 = t1._check(t2.call$2(3, 235)); + t3.call$3(t5, _s77_, 11); + t3.call$3(t5, _s1_1, 68); + t3.call$3(t5, _s1_, 18); + t3.call$3(t5, _s1_2, 172); + t3.call$3(t5, _s1_3, 205); + t5 = t1._check(t2.call$2(4, 229)); + t3.call$3(t5, _s77_, 5); + t4.call$3(t5, "AZ", 229); + t3.call$3(t5, _s1_0, 102); + t3.call$3(t5, "@", 68); + t3.call$3(t5, "[", 232); + t3.call$3(t5, _s1_1, 138); + t3.call$3(t5, _s1_2, 172); + t3.call$3(t5, _s1_3, 205); + t5 = t1._check(t2.call$2(5, 229)); + t3.call$3(t5, _s77_, 5); + t4.call$3(t5, "AZ", 229); + t3.call$3(t5, _s1_0, 102); + t3.call$3(t5, "@", 68); + t3.call$3(t5, _s1_1, 138); + t3.call$3(t5, _s1_2, 172); + t3.call$3(t5, _s1_3, 205); + t5 = t1._check(t2.call$2(6, 231)); + t4.call$3(t5, "19", 7); + t3.call$3(t5, "@", 68); + t3.call$3(t5, _s1_1, 138); + t3.call$3(t5, _s1_2, 172); + t3.call$3(t5, _s1_3, 205); + t5 = t1._check(t2.call$2(7, 231)); + t4.call$3(t5, "09", 7); + t3.call$3(t5, "@", 68); + t3.call$3(t5, _s1_1, 138); + t3.call$3(t5, _s1_2, 172); + t3.call$3(t5, _s1_3, 205); + t3.call$3(t1._check(t2.call$2(8, 8)), "]", 5); + t5 = t1._check(t2.call$2(9, 235)); + t3.call$3(t5, _s77_, 11); + t3.call$3(t5, _s1_, 16); + t3.call$3(t5, _s1_1, 234); + t3.call$3(t5, _s1_2, 172); + t3.call$3(t5, _s1_3, 205); + t5 = t1._check(t2.call$2(16, 235)); + t3.call$3(t5, _s77_, 11); + t3.call$3(t5, _s1_, 17); + t3.call$3(t5, _s1_1, 234); + t3.call$3(t5, _s1_2, 172); + t3.call$3(t5, _s1_3, 205); + t5 = t1._check(t2.call$2(17, 235)); + t3.call$3(t5, _s77_, 11); + t3.call$3(t5, _s1_1, 9); + t3.call$3(t5, _s1_2, 172); + t3.call$3(t5, _s1_3, 205); + t5 = t1._check(t2.call$2(10, 235)); + t3.call$3(t5, _s77_, 11); + t3.call$3(t5, _s1_, 18); + t3.call$3(t5, _s1_1, 234); + t3.call$3(t5, _s1_2, 172); + t3.call$3(t5, _s1_3, 205); + t5 = t1._check(t2.call$2(18, 235)); + t3.call$3(t5, _s77_, 11); + t3.call$3(t5, _s1_, 19); + t3.call$3(t5, _s1_1, 234); + t3.call$3(t5, _s1_2, 172); + t3.call$3(t5, _s1_3, 205); + t5 = t1._check(t2.call$2(19, 235)); + t3.call$3(t5, _s77_, 11); + t3.call$3(t5, _s1_1, 234); + t3.call$3(t5, _s1_2, 172); + t3.call$3(t5, _s1_3, 205); + t5 = t1._check(t2.call$2(11, 235)); + t3.call$3(t5, _s77_, 11); + t3.call$3(t5, _s1_1, 10); + t3.call$3(t5, _s1_2, 172); + t3.call$3(t5, _s1_3, 205); + t5 = t1._check(t2.call$2(12, 236)); + t3.call$3(t5, _s77_, 12); + t3.call$3(t5, _s1_2, 12); + t3.call$3(t5, _s1_3, 205); + t5 = t1._check(t2.call$2(13, 237)); + t3.call$3(t5, _s77_, 13); + t3.call$3(t5, _s1_2, 13); + t4.call$3(t1._check(t2.call$2(20, 245)), "az", 21); + t2 = t1._check(t2.call$2(21, 245)); + t4.call$3(t2, "az", 21); + t4.call$3(t2, "09", 21); + t3.call$3(t2, "+-.", 21); + return tables; + }, + _scan: function(uri, start, end, state, indices) { + var t1, i, table, char, transition, + tables = $.$get$_scannerTables(); + H.assertHelper(end <= uri.length); + for (t1 = J.getInterceptor$s(uri), i = start; i < end; ++i) { + if (state < 0 || state >= tables.length) + return H.ioore(tables, state); + table = tables[state]; + char = t1._codeUnitAt$1(uri, i) ^ 96; + if (char > 95) + char = 31; + if (char >= table.length) + return H.ioore(table, char); + transition = table[char]; + state = transition & 31; + C.JSArray_methods.$indexSet(indices, transition >>> 5, i); + } + return state; + }, + bool: function bool() { + }, + DateTime: function DateTime(t0, t1) { + this._value = t0; + this.isUtc = t1; + }, + double: function double() { + }, + Duration: function Duration(t0) { + this._duration = t0; + }, + Duration_toString_sixDigits: function Duration_toString_sixDigits() { + }, + Duration_toString_twoDigits: function Duration_toString_twoDigits() { + }, + Error: function Error() { + }, + AssertionError: function AssertionError(t0) { + this.message = t0; + }, + NullThrownError: function NullThrownError() { + }, + ArgumentError: function ArgumentError(t0, t1, t2, t3) { + var _ = this; + _._hasValue = t0; + _.invalidValue = t1; + _.name = t2; + _.message = t3; + }, + RangeError: function RangeError(t0, t1, t2, t3, t4, t5) { + var _ = this; + _.start = t0; + _.end = t1; + _._hasValue = t2; + _.invalidValue = t3; + _.name = t4; + _.message = t5; + }, + IndexError: function IndexError(t0, t1, t2, t3, t4) { + var _ = this; + _.length = t0; + _._hasValue = t1; + _.invalidValue = t2; + _.name = t3; + _.message = t4; + }, + UnsupportedError: function UnsupportedError(t0) { + this.message = t0; + }, + UnimplementedError: function UnimplementedError(t0) { + this.message = t0; + }, + StateError: function StateError(t0) { + this.message = t0; + }, + ConcurrentModificationError: function ConcurrentModificationError(t0) { + this.modifiedObject = t0; + }, + OutOfMemoryError: function OutOfMemoryError() { + }, + StackOverflowError: function StackOverflowError() { + }, + CyclicInitializationError: function CyclicInitializationError(t0) { + this.variableName = t0; + }, + _Exception: function _Exception(t0) { + this.message = t0; + }, + FormatException: function FormatException(t0, t1, t2) { + this.message = t0; + this.source = t1; + this.offset = t2; + }, + Expando: function Expando(t0, t1, t2) { + this._jsWeakMapOrKey = t0; + this.name = t1; + this.$ti = t2; + }, + Function: function Function() { + }, + int: function int() { + }, + Iterable: function Iterable() { + }, + Iterator: function Iterator() { + }, + List: function List() { + }, + Map: function Map() { + }, + MapEntry: function MapEntry(t0, t1, t2) { + this.key = t0; + this.value = t1; + this.$ti = t2; + }, + Null: function Null() { + }, + num: function num() { + }, + Object: function Object() { + }, + Pattern: function Pattern() { + }, + Match: function Match() { + }, + RegExpMatch: function RegExpMatch() { + }, + Set: function Set() { + }, + StackTrace: function StackTrace() { + }, + _StringStackTrace: function _StringStackTrace(t0) { + this._stackTrace = t0; + }, + Stopwatch: function Stopwatch() { + this._stop = this._core$_start = 0; + }, + String: function String() { + }, + Runes: function Runes(t0) { + this.string = t0; + }, + RuneIterator: function RuneIterator(t0) { + var _ = this; + _.string = t0; + _._nextPosition = _._core$_position = 0; + _._currentCodePoint = null; + }, + StringBuffer: function StringBuffer(t0) { + this._contents = t0; + }, + Uri: function Uri() { + }, + Uri__parseIPv4Address_error: function Uri__parseIPv4Address_error(t0) { + this.host = t0; + }, + Uri_parseIPv6Address_error: function Uri_parseIPv6Address_error(t0) { + this.host = t0; + }, + Uri_parseIPv6Address_parseHex: function Uri_parseIPv6Address_parseHex(t0, t1) { + this.error = t0; + this.host = t1; + }, + _Uri: function _Uri(t0, t1, t2, t3, t4, t5, t6) { + var _ = this; + _.scheme = t0; + _._userInfo = t1; + _._host = t2; + _._port = t3; + _.path = t4; + _._query = t5; + _._fragment = t6; + _._hashCodeCache = _._text = _._pathSegments = null; + }, + _Uri__Uri$notSimple_closure: function _Uri__Uri$notSimple_closure(t0, t1) { + this.uri = t0; + this.portStart = t1; + }, + _Uri__checkNonWindowsPathReservedCharacters_closure: function _Uri__checkNonWindowsPathReservedCharacters_closure(t0) { + this.argumentError = t0; + }, + _Uri__makePath_closure: function _Uri__makePath_closure() { + }, + UriData: function UriData(t0, t1, t2) { + this._text = t0; + this._separatorIndices = t1; + this._uriCache = t2; + }, + _createTables_closure: function _createTables_closure() { + }, + _createTables_build: function _createTables_build(t0) { + this.tables = t0; + }, + _createTables_setChars: function _createTables_setChars() { + }, + _createTables_setRange: function _createTables_setRange() { + }, + _SimpleUri: function _SimpleUri(t0, t1, t2, t3, t4, t5, t6, t7) { + var _ = this; + _._uri = t0; + _._schemeEnd = t1; + _._hostStart = t2; + _._portStart = t3; + _._pathStart = t4; + _._queryStart = t5; + _._fragmentStart = t6; + _._schemeCache = t7; + _._hashCodeCache = null; + }, + _DataUri: function _DataUri(t0, t1, t2, t3, t4, t5, t6) { + var _ = this; + _.scheme = t0; + _._userInfo = t1; + _._host = t2; + _._port = t3; + _.path = t4; + _._query = t5; + _._fragment = t6; + _._hashCodeCache = _._text = _._pathSegments = null; + }, + _StructuredClone: function _StructuredClone() { + }, + _StructuredClone_walk_closure: function _StructuredClone_walk_closure(t0, t1) { + this._box_0 = t0; + this.$this = t1; + }, + _StructuredClone_walk_closure0: function _StructuredClone_walk_closure0(t0, t1) { + this._box_0 = t0; + this.$this = t1; + }, + _AcceptStructuredClone: function _AcceptStructuredClone() { + }, + _AcceptStructuredClone_walk_closure: function _AcceptStructuredClone_walk_closure(t0, t1) { + this._box_0 = t0; + this.$this = t1; + }, + _StructuredCloneDart2Js: function _StructuredCloneDart2Js(t0, t1) { + this.values = t0; + this.copies = t1; + }, + _AcceptStructuredCloneDart2Js: function _AcceptStructuredCloneDart2Js(t0, t1) { + this.values = t0; + this.copies = t1; + this.mustCopy = false; + }, + _convertDataTree: function(data) { + return new P._convertDataTree__convert(new P._IdentityHashMap(type$._IdentityHashMap_dynamic_dynamic)).call$1(data); + }, + promiseToFuture: function(jsPromise, $T) { + var t1 = new P._Future($.Zone__current, $T._eval$1("_Future<0>")), + completer = new P._AsyncCompleter(t1, $T._eval$1("_AsyncCompleter<0>")); + jsPromise.then(H.convertDartClosureToJS(new P.promiseToFuture_closure(completer, $T), 1), H.convertDartClosureToJS(new P.promiseToFuture_closure0(completer), 1)); + return t1; + }, + _convertDataTree__convert: function _convertDataTree__convert(t0) { + this._convertedObjects = t0; + }, + promiseToFuture_closure: function promiseToFuture_closure(t0, t1) { + this.completer = t0; + this.T = t1; + }, + promiseToFuture_closure0: function promiseToFuture_closure0(t0) { + this.completer = t0; + }, + ByteBuffer: function ByteBuffer() { + }, + ByteData: function ByteData() { + }, + Int8List: function Int8List() { + }, + Uint8List: function Uint8List() { + }, + Uint8ClampedList: function Uint8ClampedList() { + }, + Int16List: function Int16List() { + }, + Uint16List: function Uint16List() { + }, + Int32List: function Int32List() { + }, + Uint32List: function Uint32List() { + }, + Float32List: function Float32List() { + }, + Float64List: function Float64List() { + }, + SqlError: function SqlError() { + }, + max: function(a, b, $T) { + H.checkTypeBound($T, type$.num, "T", "max"); + $T._check(a); + $T._check(b); + return Math.max(H.checkNum(a), H.checkNum(b)); + }, + pow: function(x, exponent) { + return Math.pow(x, exponent); + } + }, + W = { + _EventStreamSubscription$: function(_target, _eventType, onData, _useCapture, $T) { + var t1 = onData == null ? null : W._wrapZone(new W._EventStreamSubscription_closure(onData), type$.Event); + t1 = new W._EventStreamSubscription(_target, _eventType, t1, false, $T._eval$1("_EventStreamSubscription<0>")); + t1._tryResume$0(); + return t1; + }, + _wrapZone: function(callback, $T) { + var t1 = $.Zone__current; + if (t1 === C.C__RootZone) + return callback; + return t1.bindUnaryCallbackGuarded$1$1(callback, $T); + }, + ApplicationCacheErrorEvent: function ApplicationCacheErrorEvent() { + }, + Blob: function Blob() { + }, + DomError: function DomError() { + }, + DomException: function DomException() { + }, + ErrorEvent: function ErrorEvent() { + }, + Event: function Event() { + }, + EventTarget: function EventTarget() { + }, + File: function File() { + }, + Location: function Location() { + }, + MediaError: function MediaError() { + }, + MediaKeyMessageEvent: function MediaKeyMessageEvent() { + }, + MessageEvent: function MessageEvent() { + }, + MessagePort: function MessagePort() { + }, + NavigatorUserMediaError: function NavigatorUserMediaError() { + }, + OverconstrainedError: function OverconstrainedError() { + }, + PositionError: function PositionError() { + }, + PresentationConnectionCloseEvent: function PresentationConnectionCloseEvent() { + }, + SpeechRecognitionError: function SpeechRecognitionError() { + }, + EventStreamProvider: function EventStreamProvider(t0) { + this.$ti = t0; + }, + _EventStream: function _EventStream(t0, t1, t2, t3) { + var _ = this; + _._html$_target = t0; + _._eventType = t1; + _._useCapture = t2; + _.$ti = t3; + }, + _EventStreamSubscription: function _EventStreamSubscription(t0, t1, t2, t3, t4) { + var _ = this; + _._pauseCount = 0; + _._html$_target = t0; + _._eventType = t1; + _._html$_onData = t2; + _._useCapture = t3; + _.$ti = t4; + }, + _EventStreamSubscription_closure: function _EventStreamSubscription_closure(t0) { + this.onData = t0; + } + }, + S = {AsyncMemoizer: function AsyncMemoizer(t0, t1) { + this._async_memoizer$_completer = t0; + this.$ti = t1; + }, NullStreamSink: function NullStreamSink(t0, t1) { + var _ = this; + _.done = t0; + _._addingStream = _._null_stream_sink$_closed = false; + _.$ti = t1; + }, NullStreamSink_addStream_closure: function NullStreamSink_addStream_closure(t0) { + this.$this = t0; + }, Validator: function Validator(t0) { + this._isDefined = t0; + }, + SpanScanner$: function(string) { + var t1, t2; + string.toString; + t1 = new H.CodeUnits(string); + t2 = H.setRuntimeTypeInfo([0], type$.JSArray_int); + t2 = new Y.SourceFile(null, t2, new Uint32Array(H._ensureNativeList(t1.toList$0(t1)))); + t2.SourceFile$decoded$2$url(t1, null); + return new S.SpanScanner(t2, null, string); + }, + SpanScanner: function SpanScanner(t0, t1, t2) { + var _ = this; + _._sourceFile = t0; + _._lastSpan = null; + _.sourceUrl = t1; + _.string = t2; + _._string_scanner$_position = 0; + _._lastMatchPosition = _._lastMatch = null; + }, + _SpanScannerState: function _SpanScannerState(t0, t1) { + this._span_scanner$_scanner = t0; + this.position = t1; + }, + RemoteListener_start: function(getMain, beforeLoad, hidePrints) { + var printZone, spec, t3, _null = null, t1 = {}, + controller = B.StreamChannelController$(false, true, type$.Object), + t2 = type$.dynamic, + channel = D._MultiChannel$(controller._local, t2); + t1.verboseChain = true; + printZone = $.Zone__current; + spec = P._ZoneSpecification$(_null, _null, _null, _null, _null, new S.RemoteListener_start_closure(printZone, channel), _null, _null, _null, _null, _null, _null, _null); + P.Stream_Stream$fromIterable([], t2).listen$1(new S.RemoteListener_start_closure0()).cancel$0(); + t3 = type$.String; + P.runZoned(type$.Null_Function._check(new S.RemoteListener_start_closure1(t1, getMain, channel, controller, beforeLoad, printZone, spec)), _null, _null, P.LinkedHashMap_LinkedHashMap$_literal([$.$get$_currentKey(), new N.SuiteChannelManager(P.LinkedHashMap_LinkedHashMap$_empty(t3, type$.StreamChannel_dynamic), P.LinkedHashMap_LinkedHashMap$_empty(t3, type$.StreamChannelCompleter_dynamic), P.LinkedHashSet_LinkedHashSet$_empty(t3))], t2, t2), type$.Null); + return controller._foreign; + }, + RemoteListener__deserializeSet: function(list) { + if (list == null) + return null; + if (J.get$isEmpty$asx(list)) + return null; + return P.LinkedHashSet_LinkedHashSet$from(list, type$.String); + }, + RemoteListener__sendLoadException: function(channel, message) { + var t1 = type$.String; + channel._mainController._foreign._sink.add$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["type", "loadException", "message", message], t1, t1)); + }, + RemoteListener__sendError: function(channel, error, stackTrace, verboseChain) { + channel._mainController._foreign._sink.add$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["type", "error", "error", U.RemoteException_serialize(error, type$.StackTraceFormatter._as($.Zone__current.$index(0, $.$get$_currentKey0())).formatStackTrace$2$verbose(stackTrace, verboseChain))], type$.String, type$.Object)); + }, + RemoteListener: function RemoteListener(t0, t1) { + this._suite = t0; + this._printZone = t1; + }, + RemoteListener_start_closure: function RemoteListener_start_closure(t0, t1) { + this.printZone = t0; + this.channel = t1; + }, + RemoteListener_start_closure0: function RemoteListener_start_closure0() { + }, + RemoteListener_start_closure1: function RemoteListener_start_closure1(t0, t1, t2, t3, t4, t5, t6) { + var _ = this; + _._box_0 = t0; + _.getMain = t1; + _.channel = t2; + _.controller = t3; + _.beforeLoad = t4; + _.printZone = t5; + _.spec = t6; + }, + RemoteListener_start__closure: function RemoteListener_start__closure(t0, t1, t2, t3, t4, t5, t6) { + var _ = this; + _._box_0 = t0; + _.getMain = t1; + _.channel = t2; + _.controller = t3; + _.beforeLoad = t4; + _.printZone = t5; + _.spec = t6; + }, + RemoteListener_start___closure: function RemoteListener_start___closure(t0, t1, t2, t3, t4, t5) { + var _ = this; + _._box_0 = t0; + _.getMain = t1; + _.channel = t2; + _.controller = t3; + _.beforeLoad = t4; + _.printZone = t5; + }, + RemoteListener_start____closure: function RemoteListener_start____closure(t0, t1) { + this.controller = t0; + this.channel = t1; + }, + RemoteListener_start____closure0: function RemoteListener_start____closure0(t0, t1, t2) { + this.suite = t0; + this.printZone = t1; + this.channel = t2; + }, + RemoteListener_start_____closure: function RemoteListener_start_____closure(t0, t1, t2) { + this.suite = t0; + this.printZone = t1; + this.channel = t2; + }, + RemoteListener_start___closure0: function RemoteListener_start___closure0(t0, t1) { + this._box_0 = t0; + this.channel = t1; + }, + RemoteListener__serializeGroup_closure: function RemoteListener__serializeGroup_closure(t0, t1, t2) { + this._box_0 = t0; + this.$this = t1; + this.channel = t2; + }, + RemoteListener__serializeTest_closure: function RemoteListener__serializeTest_closure(t0, t1, t2, t3) { + var _ = this; + _.$this = t0; + _.test = t1; + _.groups = t2; + _.channel = t3; + }, + RemoteListener__runLiveTest_closure: function RemoteListener__runLiveTest_closure(t0) { + this.liveTest = t0; + }, + RemoteListener__runLiveTest_closure0: function RemoteListener__runLiveTest_closure0(t0) { + this.channel = t0; + }, + RemoteListener__runLiveTest_closure1: function RemoteListener__runLiveTest_closure1(t0, t1) { + this.channel = t0; + this.liveTest = t1; + }, + RemoteListener__runLiveTest_closure2: function RemoteListener__runLiveTest_closure2(t0, t1) { + this.$this = t0; + this.channel = t1; + }, + RemoteListener__runLiveTest_closure3: function RemoteListener__runLiveTest_closure3(t0, t1) { + this.liveTest = t0; + this.channel = t1; + }, + RemoteListener__runLiveTest__closure: function RemoteListener__runLiveTest__closure(t0) { + this.channel = t0; + } + }, + O = {DelegatingSink: function DelegatingSink(t0, t1) { + this._sink$_sink = t0; + this.$ti = t1; + }, None: function None() { + }, Scanner: function Scanner(t0) { + this._scanner = t0; + this._scanner$_next = null; + this._endOfFileEmitted = false; + }, EmptyUnmodifiableSet: function EmptyUnmodifiableSet(t0) { + this.$ti = t0; + }, + Style__getPlatformStyle: function() { + if (P.Uri_base().get$scheme() !== "file") + return $.$get$Style_url(); + var t1 = P.Uri_base(); + if (!C.JSString_methods.endsWith$1(t1.get$path(t1), "/")) + return $.$get$Style_url(); + if (P._Uri__Uri(null, "a/b", null, null).toFilePath$0() === "a\\b") + return $.$get$Style_windows(); + return $.$get$Style_posix(); + }, + Style: function Style() { + }, + Pool$: function(_maxAllocatedResources) { + var t4, + t1 = type$.Completer_PoolResource, + t2 = P.ListQueue$(t1), + t3 = P.ListQueue$(type$.void_Function); + t1 = P.ListQueue$(t1); + t4 = $.Zone__current; + if (_maxAllocatedResources <= 0) + H.throwExpression(P.ArgumentError$value(_maxAllocatedResources, "maxAllocatedResources", "Must be greater than zero.")); + return new O.Pool(t2, t3, t1, _maxAllocatedResources, new S.AsyncMemoizer(new P._AsyncCompleter(new P._Future(t4, type$._Future_dynamic), type$._AsyncCompleter_dynamic), type$.AsyncMemoizer_dynamic)); + }, + Pool: function Pool(t0, t1, t2, t3, t4) { + var _ = this; + _._requestedResources = t0; + _._onReleaseCallbacks = t1; + _._onReleaseCompleters = t2; + _._maxAllocatedResources = t3; + _._allocatedResources = 0; + _._closeGroup = _._timer = null; + _._pool$_closeMemo = t4; + }, + Pool_close_closure: function Pool_close_closure(t0) { + this.$this = t0; + }, + Pool__onResourceReleaseAllowed_closure: function Pool__onResourceReleaseAllowed_closure(t0, t1) { + this.zone = t0; + this.registered = t1; + }, + Pool__runOnRelease_closure: function Pool__runOnRelease_closure(t0) { + this.$this = t0; + }, + Pool__runOnRelease_closure0: function Pool__runOnRelease_closure0(t0) { + this.$this = t0; + }, + PoolResource: function PoolResource(t0) { + this._pool = t0; + this._released = false; + }, + mapStackTrace: function(sourceMap, stackTrace, minified, packageResolver, sdkRoot) { + var t2, t3, sdkLib, t4, t1 = {}; + t1.packageResolver = packageResolver; + if (type$.Chain._is(stackTrace)) { + t2 = stackTrace.get$traces(); + t3 = H._arrayInstanceType(t2); + return new U.Chain(P.List_List$unmodifiable(new H.MappedListIterable(t2, t3._eval$1("Trace(1)")._check(new O.mapStackTrace_closure(t1, sourceMap, false, sdkRoot)), t3._eval$1("MappedListIterable<1,Trace>")), type$.Trace)); + } + t2 = sdkRoot == null; + !t2; + sdkLib = t2 ? null : sdkRoot.toString$0(0) + "/lib"; + t2 = Y.Trace_Trace$from(stackTrace).get$frames(); + t3 = H._arrayInstanceType(t2); + t4 = t3._eval$1("MappedListIterable<1,Frame>"); + return new Y.Trace(P.List_List$unmodifiable(new H.MappedListIterable(t2, t3._eval$1("Frame(1)")._check(new O.mapStackTrace_closure0(t1, sourceMap, sdkRoot, sdkLib, false)), t4).super$Iterable$where(0, t4._eval$1("bool(ListIterable.E)")._check(new O.mapStackTrace_closure1())), type$.Frame), new P._StringStackTrace(null)); + }, + _prettifyMember: function(member) { + var t2, t3, + t1 = P.RegExp_RegExp("/?<$", false); + member.toString; + t1 = H.stringReplaceAllUnchecked(member, t1, ""); + t2 = P.RegExp_RegExp("\\$\\d+(\\$[a-zA-Z_0-9]+)*$", false); + t3 = type$.String_Function_Match; + t2 = C.JSString_methods.splitMapJoin$2$onMatch(H.stringReplaceAllUnchecked(t1, t2, ""), P.RegExp_RegExp("(_+)closure\\d*\\.call$", false), t3._check(new O._prettifyMember_closure())); + t1 = P.RegExp_RegExp("\\.call$", false); + t1 = H.stringReplaceAllUnchecked(t2, t1, ""); + t2 = P.RegExp_RegExp("^dart\\.", false); + t1 = H.stringReplaceAllUnchecked(t1, t2, ""); + t2 = P.RegExp_RegExp("[a-zA-Z_0-9]+\\$", false); + t1 = H.stringReplaceAllUnchecked(t1, t2, ""); + t2 = P.RegExp_RegExp("^[a-zA-Z_0-9]+.(static|dart).", false); + return C.JSString_methods.splitMapJoin$2$onMatch(H.stringReplaceAllUnchecked(t1, t2, ""), P.RegExp_RegExp("([a-zA-Z0-9]+)_", false), t3._check(new O._prettifyMember_closure0())); + }, + mapStackTrace_closure: function mapStackTrace_closure(t0, t1, t2, t3) { + var _ = this; + _._box_0 = t0; + _.sourceMap = t1; + _.minified = t2; + _.sdkRoot = t3; + }, + mapStackTrace_closure0: function mapStackTrace_closure0(t0, t1, t2, t3, t4) { + var _ = this; + _._box_0 = t0; + _.sourceMap = t1; + _.sdkRoot = t2; + _.sdkLib = t3; + _.minified = t4; + }, + mapStackTrace_closure1: function mapStackTrace_closure1() { + }, + _prettifyMember_closure: function _prettifyMember_closure() { + }, + _prettifyMember_closure0: function _prettifyMember_closure0() { + }, + StackZoneSpecification: function StackZoneSpecification(t0, t1, t2) { + var _ = this; + _._chains = t0; + _._stack_zone_specification$_onError = t1; + _._currentNode = null; + _._errorZone = t2; + }, + StackZoneSpecification_chainFor_closure: function StackZoneSpecification_chainFor_closure(t0) { + this._box_0 = t0; + }, + StackZoneSpecification_chainFor_closure0: function StackZoneSpecification_chainFor_closure0(t0, t1) { + this.$this = t0; + this.original = t1; + }, + StackZoneSpecification__registerCallback_closure: function StackZoneSpecification__registerCallback_closure(t0, t1, t2, t3) { + var _ = this; + _.$this = t0; + _.f = t1; + _.node = t2; + _.R = t3; + }, + StackZoneSpecification__registerUnaryCallback_closure: function StackZoneSpecification__registerUnaryCallback_closure(t0, t1, t2, t3, t4) { + var _ = this; + _.$this = t0; + _.f = t1; + _.node = t2; + _.T = t3; + _.R = t4; + }, + StackZoneSpecification__registerUnaryCallback__closure: function StackZoneSpecification__registerUnaryCallback__closure(t0, t1, t2) { + this.f = t0; + this.arg = t1; + this.R = t2; + }, + StackZoneSpecification__registerBinaryCallback_closure: function StackZoneSpecification__registerBinaryCallback_closure(t0, t1, t2, t3, t4, t5) { + var _ = this; + _.$this = t0; + _.f = t1; + _.node = t2; + _.T1 = t3; + _.T2 = t4; + _.R = t5; + }, + StackZoneSpecification__registerBinaryCallback__closure: function StackZoneSpecification__registerBinaryCallback__closure(t0, t1, t2, t3) { + var _ = this; + _.f = t0; + _.arg1 = t1; + _.arg2 = t2; + _.R = t3; + }, + StackZoneSpecification__currentTrace_closure: function StackZoneSpecification__currentTrace_closure(t0, t1, t2) { + this._box_0 = t0; + this.$this = t1; + this.stackTrace = t2; + }, + _Node: function _Node(t0, t1) { + this.trace = t0; + this.previous = t1; + }, + Group$: function($name, entries, metadata, setUpAll, tearDownAll, trace) { + var t1 = P.List_List$unmodifiable(entries, type$.GroupEntry); + return new O.Group($name, metadata, trace, t1, setUpAll, tearDownAll); + }, + Group: function Group(t0, t1, t2, t3, t4, t5) { + var _ = this; + _.name = t0; + _.metadata = t1; + _.trace = t2; + _.entries = t3; + _.setUpAll = t4; + _.tearDownAll = t5; + }, + Group_forPlatform_closure: function Group_forPlatform_closure(t0) { + this.platform = t0; + }, + Group__map_closure: function Group__map_closure(t0) { + this.callback = t0; + }, + Group__map_closure0: function Group__map_closure0() { + }, + Metadata__parseOnPlatform: function(onPlatform) { + return P.LinkedHashMap_LinkedHashMap$_empty(type$.PlatformSelector, type$.Metadata); + }, + Metadata__parseTags: function(tags) { + return P.LinkedHashSet_LinkedHashSet$_empty(type$.String); + }, + Metadata_Metadata: function(chainStackTraces, forTag, onPlatform, retry, skip, skipReason, tags, testOn, timeout, verboseTrace) { + var t2, t3, empty, t4, merged, _null = null, t1 = {}; + t1.tags = tags; + t1.forTag = forTag; + t2 = new O.Metadata_Metadata__unresolved(t1, testOn, timeout, skip, verboseTrace, chainStackTraces, retry, skipReason, onPlatform); + if (forTag == null || tags == null) + return t2.call$0(); + t1.tags = P.LinkedHashSet_LinkedHashSet$from(tags, type$.String); + t3 = type$.Metadata; + t1.forTag = P.LinkedHashMap_LinkedHashMap$from(t1.forTag, type$.BooleanSelector, t3); + empty = O.Metadata$_(_null, _null, _null, _null, _null, _null, _null, _null, _null, _null); + t4 = t1.forTag.get$keys(); + merged = C.JSArray_methods.fold$1$2(P.List_List$from(t4, true, H._instanceType(t4)._eval$1("Iterable.E")), empty, new O.Metadata_Metadata_closure(t1), t3); + if (merged === empty) + return t2.call$0(); + return merged.merge$1(t2.call$0()); + }, + Metadata$_: function(chainStackTraces, forTag, onPlatform, retry, skip, skipReason, tags, testOn, timeout, verboseTrace) { + var t1 = testOn == null ? C.PlatformSelector_All : testOn, + t2 = timeout == null ? C.Timeout_null_1 : timeout, + t3 = tags == null ? P.LinkedHashSet_LinkedHashSet$_empty(type$.String) : tags.toSet$0(0), + t4 = onPlatform == null ? C.Map_empty : new P.UnmodifiableMapView(onPlatform, type$.UnmodifiableMapView_PlatformSelector_Metadata), + t5 = forTag == null ? C.Map_empty0 : new P.UnmodifiableMapView(forTag, type$.UnmodifiableMapView_BooleanSelector_Metadata); + t5 = new O.Metadata(t1, t2, skip, skipReason, verboseTrace, chainStackTraces, new L.UnmodifiableSetView(t3, type$.UnmodifiableSetView_String), retry, t4, t5); + if (retry != null) + P.RangeError_checkNotNegative(retry, "retry"); + t5._validateTags$0(); + return t5; + }, + Metadata$parse: function(onPlatform, retry, skip, tags, testOn, timeout) { + var _null = null, + t1 = timeout == null ? C.Timeout_null_1 : timeout, + t2 = skip == null, + t3 = t2 ? _null : skip, + t4 = O.Metadata__parseOnPlatform(onPlatform); + t4 = new O.Metadata(C.PlatformSelector_All, t1, t3, _null, _null, _null, O.Metadata__parseTags(tags), retry, t4, C.Map_empty0); + !t2; + if (retry != null) + P.RangeError_checkNotNegative(retry, "retry"); + t4._validateTags$0(); + return t4; + }, + Metadata$deserialize: function(serialized) { + var pair, t13, + t1 = J.getInterceptor$asx(serialized), + t2 = t1.$index(serialized, "testOn") == null ? C.PlatformSelector_All : E.PlatformSelector$parse(H._asStringNullable(t1.$index(serialized, "testOn"))), + t3 = O.Metadata__deserializeTimeout(t1.$index(serialized, "timeout")), + t4 = H._asBoolNullable(t1.$index(serialized, "skip")), + t5 = H._asStringNullable(t1.$index(serialized, "skipReason")), + t6 = H._asBoolNullable(t1.$index(serialized, "verboseTrace")), + t7 = H._asBoolNullable(t1.$index(serialized, "chainStackTraces")), + t8 = H._asIntNullable(t1.$index(serialized, "retry")), + t9 = type$.Iterable_dynamic, + t10 = P.LinkedHashSet_LinkedHashSet$from(t9._as(t1.$index(serialized, "tags")), type$.String), + t11 = type$.Metadata, + t12 = P.LinkedHashMap_LinkedHashMap$_empty(type$.PlatformSelector, t11); + for (t9 = J.get$iterator$ax(t9._check(t1.$index(serialized, "onPlatform"))); t9.moveNext$0();) { + pair = t9.get$current(); + t13 = J.getInterceptor$ax(pair); + t12.$indexSet(0, E.PlatformSelector$parse(H._asStringNullable(t13.get$first(pair))), O.Metadata$deserialize(t13.get$last(pair))); + } + return new O.Metadata(t2, t3, t4, t5, t6, t7, t10, t8, t12, type$.Map_dynamic_dynamic._as(t1.$index(serialized, "forTag")).map$2$1(0, new O.Metadata$deserialize_closure(), type$.BooleanSelector, t11)); + }, + Metadata__deserializeTimeout: function(serialized) { + var scaleFactor, + t1 = J.getInterceptor$(serialized); + if (t1.$eq(serialized, "none")) + return C.Timeout_null_null; + scaleFactor = t1.$index(serialized, "scaleFactor"); + if (scaleFactor != null) + return new R.Timeout(null, H._asNumNullable(scaleFactor)); + return new R.Timeout(P.Duration$(H._asIntNullable(t1.$index(serialized, "duration")), 0), null); + }, + Metadata: function Metadata(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9) { + var _ = this; + _.testOn = t0; + _.timeout = t1; + _._skip = t2; + _.skipReason = t3; + _._verboseTrace = t4; + _._chainStackTraces = t5; + _.tags = t6; + _._retry = t7; + _.onPlatform = t8; + _.forTag = t9; + }, + Metadata_Metadata__unresolved: function Metadata_Metadata__unresolved(t0, t1, t2, t3, t4, t5, t6, t7, t8) { + var _ = this; + _._box_0 = t0; + _.testOn = t1; + _.timeout = t2; + _.skip = t3; + _.verboseTrace = t4; + _.chainStackTraces = t5; + _.retry = t6; + _.skipReason = t7; + _.onPlatform = t8; + }, + Metadata_Metadata_closure: function Metadata_Metadata_closure(t0) { + this._box_0 = t0; + }, + Metadata$deserialize_closure: function Metadata$deserialize_closure() { + }, + Metadata__validateTags_closure: function Metadata__validateTags_closure() { + }, + Metadata__validateTags_closure0: function Metadata__validateTags_closure0() { + }, + Metadata_validatePlatformSelectors_closure: function Metadata_validatePlatformSelectors_closure(t0) { + this.validVariables = t0; + }, + Metadata_merge_closure: function Metadata_merge_closure() { + }, + Metadata_merge_closure0: function Metadata_merge_closure0() { + }, + Metadata_forPlatform_closure: function Metadata_forPlatform_closure(t0, t1) { + this._box_0 = t0; + this.platform = t1; + }, + Metadata_serialize_closure: function Metadata_serialize_closure(t0) { + this.serializedOnPlatform = t0; + }, + Metadata_serialize_closure0: function Metadata_serialize_closure0() { + }, + IterableSet: function IterableSet(t0, t1) { + this._iterable_set$_base = t0; + this.$ti = t1; + }, + _IterableSet_SetMixin_UnmodifiableSetMixin: function _IterableSet_SetMixin_UnmodifiableSetMixin() { + }, + Engine$: function() { + var t6, t7, t8, t9, t10, t11, _null = null, + t1 = $.Zone__current, + t2 = H.setRuntimeTypeInfo([], type$.JSArray_dynamic), + t3 = type$.RunnerSuite, + t4 = P.StreamController_StreamController(_null, _null, false, t3), + t5 = new L.StreamGroup(C._StreamGroupState_dormant, new H.JsLinkedHashMap(type$.JsLinkedHashMap_of_Stream_LiveTest_and_StreamSubscription_LiveTest), type$.StreamGroup_LiveTest); + t5.set$_stream_group$_controller(new P._SyncBroadcastStreamController(t5.get$_onListen(), t5.get$_onCancelBroadcast(), type$._SyncBroadcastStreamController_LiveTest)); + t6 = type$.LiveTest; + t7 = Y.UnionSetController$(true, t6); + t8 = Y.UnionSetController$(true, t6); + t9 = Y.UnionSetController$(true, t6); + t10 = Q.QueueList$(t6); + t11 = O.Pool$(1); + t1 = new O.Engine(t11, O.Pool$(2), new F.FutureGroup(new P._AsyncCompleter(new P._Future(t1, type$._Future_List_dynamic), type$._AsyncCompleter_List_dynamic), t2, type$.FutureGroup_dynamic), P.LinkedHashSet_LinkedHashSet$_empty(type$.StreamSubscription_dynamic), t4, P.LinkedHashSet_LinkedHashSet$_empty(t3), new P._AsyncBroadcastStreamController(_null, _null, type$._AsyncBroadcastStreamController_RunnerSuite), P.LinkedHashSet_LinkedHashSet$_empty(type$.LiveSuite), new P._AsyncBroadcastStreamController(_null, _null, type$._AsyncBroadcastStreamController_LiveSuite), t5, t7, t8, t9, t10, P.LinkedHashSet_LinkedHashSet$_empty(t6), P.LinkedHashSet_LinkedHashSet$_empty(t6)); + t1.Engine$3$concurrency$coverage$maxSuites(_null, _null, _null); + return t1; + }, + Engine: function Engine(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15) { + var _ = this; + _._engine$_closed = _._engine$_runCalled = false; + _._closedBeforeDone = null; + _._runPool = t0; + _._loadPool = t1; + _._group = t2; + _._engine$_subscriptions = t3; + _._suiteController = t4; + _._addedSuites = t5; + _._onSuiteAddedController = t6; + _._liveSuites = t7; + _._onSuiteStartedController = t8; + _._onTestStartedGroup = t9; + _._passedGroup = t10; + _._skippedGroup = t11; + _._failedGroup = t12; + _._active = t13; + _._restarted = t14; + _._activeLoadTests = t15; + }, + Engine_success_closure: function Engine_success_closure() { + }, + Engine_closure: function Engine_closure(t0) { + this.$this = t0; + }, + Engine_closure0: function Engine_closure0() { + }, + Engine_run_closure: function Engine_run_closure(t0) { + this.$this = t0; + }, + Engine_run__closure: function Engine_run__closure(t0, t1) { + this.$this = t0; + this.suite = t1; + }, + Engine_run___closure: function Engine_run___closure(t0, t1, t2) { + this._box_0 = t0; + this.$this = t1; + this.loadResource = t2; + }, + Engine_run____closure: function Engine_run____closure(t0) { + this._box_0 = t0; + }, + Engine_run_closure0: function Engine_run_closure0(t0, t1) { + this._box_1 = t0; + this.$this = t1; + }, + Engine__runLiveTest_closure: function Engine__runLiveTest_closure(t0, t1) { + this.$this = t0; + this.liveTest = t1; + }, + Engine__runLiveTest_closure0: function Engine__runLiveTest_closure0(t0, t1) { + this._box_0 = t0; + this.$this = t1; + }, + Engine__runLiveTest_closure1: function Engine__runLiveTest_closure1() { + }, + Engine__runSkippedTest_closure: function Engine__runSkippedTest_closure() { + }, + Engine__runSkippedTest_closure0: function Engine__runSkippedTest_closure0(t0, t1) { + this._box_0 = t0; + this.skipped = t1; + }, + Engine__runSkippedTest_closure1: function Engine__runSkippedTest_closure1() { + }, + binarySearch: function(list, matches) { + var max, min, half; + if (list.length === 0) + return -1; + if (H.boolConversionCheck(matches.call$1(C.JSArray_methods.get$first(list)))) + return 0; + if (!H.boolConversionCheck(matches.call$1(C.JSArray_methods.get$last(list)))) + return list.length; + max = list.length - 1; + for (min = 0; min < max;) { + half = min + C.JSInt_methods._tdivFast$1(max - min, 2); + if (half < 0 || half >= list.length) + return H.ioore(list, half); + if (H.boolConversionCheck(matches.call$1(list[half]))) + max = half; + else + min = half + 1; + } + return max; + } + }, + Y = {DelegatingStreamSubscription: function DelegatingStreamSubscription() { + }, StreamCompleter: function StreamCompleter(t0, t1) { + this._stream = t0; + this.$ti = t1; + }, _CompleterStream: function _CompleterStream(t0) { + this._sourceStream = this._stream_completer$_controller = null; + this.$ti = t0; + }, BooleanSelectorImpl: function BooleanSelectorImpl(t0) { + this._selector = t0; + }, + mapMap: function(map, value, K1, V1, K2, V2) { + var key, result, t1 = {}; + t1.key = key; + t1.value = value; + t1.key = null; + t1.key = new Y.mapMap_closure(K2, K1, V1); + result = P.LinkedHashMap_LinkedHashMap$_empty(K2, V2); + map.forEach$1(0, new Y.mapMap_closure0(t1, result, K1, V1)); + return result; + }, + mergeMaps: function(map1, map2, value, $K, $V) { + var result = P.LinkedHashMap_LinkedHashMap$from(map1, $K, $V); + map2.forEach$1(0, new Y.mergeMaps_closure(result, value, $K, $V)); + return result; + }, + mapMap_closure: function mapMap_closure(t0, t1, t2) { + this.K2 = t0; + this.K1 = t1; + this.V1 = t2; + }, + mapMap_closure0: function mapMap_closure0(t0, t1, t2, t3) { + var _ = this; + _._box_0 = t0; + _.result = t1; + _.K1 = t2; + _.V1 = t3; + }, + mergeMaps_closure: function mergeMaps_closure(t0, t1, t2, t3) { + var _ = this; + _.result = t0; + _.value = t1; + _.K = t2; + _.V = t3; + }, + UnionSetController$: function(disjoint, $E) { + var t1 = P.LinkedHashSet_LinkedHashSet($E._eval$1("Set<0>")), + t2 = new Y.UnionSetController(t1, $E._eval$1("UnionSetController<0>")); + t2.set$_union_set_controller$_set(new M.UnionSet(t1, true, $E._eval$1("UnionSet<0>"))); + return t2; + }, + UnionSetController: function UnionSetController(t0, t1) { + this._union_set_controller$_set = null; + this._union_set_controller$_sets = t0; + this.$ti = t1; + }, + _IsTrue: function _IsTrue() { + }, + _Predicate: function _Predicate(t0, t1, t2) { + this._matcher = t0; + this._core_matchers$_description = t1; + this.$ti = t2; + }, + FileLocation$_: function(file, offset) { + if (offset < 0) + H.throwExpression(P.RangeError$("Offset may not be negative, was " + offset + ".")); + else if (offset > file._decodedChars.length) + H.throwExpression(P.RangeError$("Offset " + offset + " must not be greater than the number of characters in the file, " + file.get$length(file) + ".")); + return new Y.FileLocation(file, offset); + }, + _FileSpan$: function(file, _start, _end) { + if (_end < _start) + H.throwExpression(P.ArgumentError$("End " + _end + " must come after start " + _start + ".")); + else if (_end > file._decodedChars.length) + H.throwExpression(P.RangeError$("End " + _end + " must not be greater than the number of characters in the file, " + file.get$length(file) + ".")); + else if (_start < 0) + H.throwExpression(P.RangeError$("Start may not be negative, was " + _start + ".")); + return new Y._FileSpan(file, _start, _end); + }, + SourceFile: function SourceFile(t0, t1, t2) { + var _ = this; + _.url = t0; + _._lineStarts = t1; + _._decodedChars = t2; + _._cachedLine = null; + }, + FileLocation: function FileLocation(t0, t1) { + this.file = t0; + this.offset = t1; + }, + _FileSpan: function _FileSpan(t0, t1, t2) { + this.file = t0; + this._file$_start = t1; + this._file$_end = t2; + }, + SourceSpanMixin: function SourceSpanMixin() { + }, + Trace_Trace$current: function(level) { + return new T.LazyTrace(new Y.Trace_Trace$current_closure(Y.Trace_Trace$from(P.StackTrace_current()), level)); + }, + Trace_Trace$from: function(trace) { + if (trace == null) + throw H.wrapException(P.ArgumentError$("Cannot create a Trace from null.")); + if (type$.Trace._is(trace)) + return trace; + if (type$.Chain._is(trace)) + return trace.toTrace$0(); + return new T.LazyTrace(new Y.Trace_Trace$from_closure(trace)); + }, + Trace_Trace$parse: function(trace) { + var error, t1, exception; + try { + if (trace.length === 0) { + t1 = P.List_List$unmodifiable(H.setRuntimeTypeInfo([], type$.JSArray_Frame), type$.Frame); + return new Y.Trace(t1, new P._StringStackTrace(null)); + } + if (C.JSString_methods.contains$1(trace, $.$get$_v8Trace())) { + t1 = Y.Trace$parseV8(trace); + return t1; + } + if (C.JSString_methods.contains$1(trace, "\tat ")) { + t1 = Y.Trace$parseJSCore(trace); + return t1; + } + if (C.JSString_methods.contains$1(trace, $.$get$_firefoxSafariTrace())) { + t1 = Y.Trace$parseFirefox(trace); + return t1; + } + if (C.JSString_methods.contains$1(trace, "===== asynchronous gap ===========================\n")) { + t1 = U.Chain_Chain$parse(trace).toTrace$0(); + return t1; + } + if (C.JSString_methods.contains$1(trace, $.$get$_friendlyTrace())) { + t1 = Y.Trace$parseFriendly(trace); + return t1; + } + t1 = P.List_List$unmodifiable(Y.Trace__parseVM(trace), type$.Frame); + return new Y.Trace(t1, new P._StringStackTrace(trace)); + } catch (exception) { + t1 = H.unwrapException(exception); + if (type$.FormatException._is(t1)) { + error = t1; + throw H.wrapException(P.FormatException$(H.S(J.get$message$x(error)) + "\nStack trace:\n" + H.S(trace), null, null)); + } else + throw exception; + } + }, + Trace__parseVM: function(trace) { + var t2, $frames, + t1 = J.trim$0$s(trace), + lines = H.setRuntimeTypeInfo(H.stringReplaceAllUnchecked(t1, "<asynchronous suspension>\n", "").split("\n"), type$.JSArray_String); + t1 = H.SubListIterable$(lines, 0, lines.length - 1, type$.String); + t2 = t1.$ti; + $frames = new H.MappedListIterable(t1, t2._eval$1("Frame(ListIterable.E)")._check(new Y.Trace__parseVM_closure()), t2._eval$1("MappedListIterable<ListIterable.E,Frame>")).toList$0(0); + if (!J.endsWith$1$s(C.JSArray_methods.get$last(lines), ".da")) + C.JSArray_methods.add$1($frames, A.Frame_Frame$parseVM(C.JSArray_methods.get$last(lines))); + return $frames; + }, + Trace$parseV8: function(trace) { + var t2, t3, + t1 = H.SubListIterable$(H.setRuntimeTypeInfo(trace.split("\n"), type$.JSArray_String), 1, null, type$.String); + t1 = t1.super$Iterable$skipWhile(0, t1.$ti._eval$1("bool(ListIterable.E)")._check(new Y.Trace$parseV8_closure())); + t2 = type$.Frame; + t3 = t1.$ti; + return new Y.Trace(P.List_List$unmodifiable(H.MappedIterable_MappedIterable(t1, t3._eval$1("Frame(Iterable.E)")._check(new Y.Trace$parseV8_closure0()), t3._eval$1("Iterable.E"), t2), t2), new P._StringStackTrace(trace)); + }, + Trace$parseJSCore: function(trace) { + return new Y.Trace(P.List_List$unmodifiable(new H.MappedIterable(new H.WhereIterable(H.setRuntimeTypeInfo(trace.split("\n"), type$.JSArray_String), type$.bool_Function_String._check(new Y.Trace$parseJSCore_closure()), type$.WhereIterable_String), type$.Frame_Function_String._check(new Y.Trace$parseJSCore_closure0()), type$.MappedIterable_String_Frame), type$.Frame), new P._StringStackTrace(trace)); + }, + Trace$parseFirefox: function(trace) { + return new Y.Trace(P.List_List$unmodifiable(new H.MappedIterable(new H.WhereIterable(H.setRuntimeTypeInfo(C.JSString_methods.trim$0(trace).split("\n"), type$.JSArray_String), type$.bool_Function_String._check(new Y.Trace$parseFirefox_closure()), type$.WhereIterable_String), type$.Frame_Function_String._check(new Y.Trace$parseFirefox_closure0()), type$.MappedIterable_String_Frame), type$.Frame), new P._StringStackTrace(trace)); + }, + Trace$parseFriendly: function(trace) { + var t1 = trace.length === 0 ? H.setRuntimeTypeInfo([], type$.JSArray_Frame) : new H.MappedIterable(new H.WhereIterable(H.setRuntimeTypeInfo(C.JSString_methods.trim$0(trace).split("\n"), type$.JSArray_String), type$.bool_Function_String._check(new Y.Trace$parseFriendly_closure()), type$.WhereIterable_String), type$.Frame_Function_String._check(new Y.Trace$parseFriendly_closure0()), type$.MappedIterable_String_Frame); + return new Y.Trace(P.List_List$unmodifiable(t1, type$.Frame), new P._StringStackTrace(trace)); + }, + Trace: function Trace(t0, t1) { + this.frames = t0; + this.original = t1; + }, + Trace_Trace$current_closure: function Trace_Trace$current_closure(t0, t1) { + this.trace = t0; + this.level = t1; + }, + Trace_Trace$from_closure: function Trace_Trace$from_closure(t0) { + this.trace = t0; + }, + Trace__parseVM_closure: function Trace__parseVM_closure() { + }, + Trace$parseV8_closure: function Trace$parseV8_closure() { + }, + Trace$parseV8_closure0: function Trace$parseV8_closure0() { + }, + Trace$parseJSCore_closure: function Trace$parseJSCore_closure() { + }, + Trace$parseJSCore_closure0: function Trace$parseJSCore_closure0() { + }, + Trace$parseFirefox_closure: function Trace$parseFirefox_closure() { + }, + Trace$parseFirefox_closure0: function Trace$parseFirefox_closure0() { + }, + Trace$parseFriendly_closure: function Trace$parseFriendly_closure() { + }, + Trace$parseFriendly_closure0: function Trace$parseFriendly_closure0() { + }, + Trace_foldFrames_closure: function Trace_foldFrames_closure(t0) { + this.oldPredicate = t0; + }, + Trace_foldFrames_closure0: function Trace_foldFrames_closure0(t0) { + this._box_0 = t0; + }, + Trace_toString_closure0: function Trace_toString_closure0() { + }, + Trace_toString_closure: function Trace_toString_closure(t0) { + this.longest = t0; + }, + RunnerSuite: function RunnerSuite(t0, t1, t2, t3) { + var _ = this; + _._runner_suite$_controller = t0; + _.platform = t1; + _.path = t2; + _.group = t3; + }, + RunnerSuiteController: function RunnerSuiteController(t0, t1, t2, t3, t4) { + var _ = this; + _._config = t0; + _._runner_suite$_onClose = t1; + _._onDebuggingController = t2; + _._channelNames = t3; + _._closeMemo = t4; + }, + RunnerSuiteController__close_closure: function RunnerSuiteController__close_closure(t0) { + this.$this = t0; + } + }, + F = {FutureGroup: function FutureGroup(t0, t1, t2) { + var _ = this; + _._future_group$_pending = 0; + _._future_group$_closed = false; + _._future_group$_completer = t0; + _._values = t1; + _.$ti = t2; + }, FutureGroup_add_closure: function FutureGroup_add_closure(t0, t1) { + this.$this = t0; + this.index = t1; + }, FutureGroup_add_closure0: function FutureGroup_add_closure0(t0) { + this.$this = t0; + }, ValueResult: function ValueResult(t0, t1) { + this.value = t0; + this.$ti = t1; + }, + PackageConfigResolver__normalizeMap: function(map) { + var t1 = type$.String, + t2 = type$.Uri; + return new P.UnmodifiableMapView(Y.mapMap(map, new F.PackageConfigResolver__normalizeMap_closure(), t1, t2, t1, t2), type$.UnmodifiableMapView_String_Uri); + }, + PackageConfigResolver: function PackageConfigResolver(t0) { + this.packageConfigMap = t0; + }, + PackageConfigResolver__normalizeMap_closure: function PackageConfigResolver__normalizeMap_closure() { + }, + UrlStyle: function UrlStyle(t0, t1, t2, t3) { + var _ = this; + _.separatorPattern = t0; + _.needsSeparatorPattern = t1; + _.rootPattern = t2; + _.relativeRootPattern = t3; + } + }, + V = {ErrorResult: function ErrorResult(t0, t1) { + this.error = t0; + this.stackTrace = t1; + }, + SourceLocation$: function(offset, column, line, sourceUrl) { + var t2, t3, t4, t5, + t1 = typeof sourceUrl == "string" ? P.Uri_parse(sourceUrl) : sourceUrl; + type$.Uri._check(t1); + t2 = line == null; + t3 = t2 ? 0 : line; + t4 = column == null; + t5 = t4 ? offset : column; + if (offset < 0) + H.throwExpression(P.RangeError$("Offset may not be negative, was " + offset + ".")); + else if (!t2 && line < 0) + H.throwExpression(P.RangeError$("Line may not be negative, was " + H.S(line) + ".")); + else if (!t4 && column < 0) + H.throwExpression(P.RangeError$("Column may not be negative, was " + H.S(column) + ".")); + return new V.SourceLocation(t1, offset, t3, t5); + }, + SourceLocation: function SourceLocation(t0, t1, t2, t3) { + var _ = this; + _.sourceUrl = t0; + _.offset = t1; + _.line = t2; + _.column = t3; + }, + SourceSpan: function SourceSpan() { + }, + SourceSpanBase: function SourceSpanBase() { + }, + GroupEntry: function GroupEntry() { + }, + LiveTestController$: function(suite, _test, onRun, onClose, groups) { + var _null = null, + t1 = H.setRuntimeTypeInfo([], type$.JSArray_AsyncError), + t2 = $.Zone__current, + t3 = P.List_List$unmodifiable(groups, type$.Group); + t1 = new V.LiveTestController(suite, t3, _test, onRun, onClose, t1, C.State_Status_pending_Result_success, new P._SyncBroadcastStreamController(_null, _null, type$._SyncBroadcastStreamController_State), new P._SyncBroadcastStreamController(_null, _null, type$._SyncBroadcastStreamController_AsyncError), new P._SyncBroadcastStreamController(_null, _null, type$._SyncBroadcastStreamController_Message), new P._AsyncCompleter(new P._Future(t2, type$._Future_void), type$._AsyncCompleter_void)); + t1._liveTest = new V._LiveTest(t1); + return t1; + }, + _LiveTest: function _LiveTest(t0) { + this._live_test_controller$_controller = t0; + }, + LiveTestController: function LiveTestController(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10) { + var _ = this; + _._liveTest = null; + _._live_test_controller$_suite = t0; + _._groups = t1; + _._test = t2; + _._onRun = t3; + _._onClose = t4; + _._errors = t5; + _._live_test_controller$_state = t6; + _._onStateChangeController = t7; + _._onErrorController = t8; + _._onMessageController = t9; + _.completer = t10; + _._runCalled = false; + }, + Test: function Test() { + }, + errorsDontStopTest: function(body) { + var t1 = $.Zone__current, + t2 = new P._Future(t1, type$._Future_dynamic), + t3 = type$.Invoker; + t3._as(t1.$index(0, C.Symbol_cQL)).addOutstandingCallback$0(); + t3._as($.Zone__current.$index(0, C.Symbol_cQL)).waitForOutstandingCallbacks$1(new V.errorsDontStopTest_closure(body, new P._AsyncCompleter(t2, type$._AsyncCompleter_dynamic))).then$1$1(new V.errorsDontStopTest_closure0(), type$.void); + return t2; + }, + errorsDontStopTest_closure: function errorsDontStopTest_closure(t0, t1) { + this.body = t0; + this.completer = t1; + }, + errorsDontStopTest_closure0: function errorsDontStopTest_closure0() { + } + }, + E = {Result: function Result() { + }, StringDescription: function StringDescription(t0) { + this._out = t0; + }, FeatureMatcher: function FeatureMatcher() { + }, PosixStyle: function PosixStyle(t0, t1, t2) { + this.separatorPattern = t0; + this.needsSeparatorPattern = t1; + this.rootPattern = t2; + }, + StringScannerException$: function(message, span, source) { + return new E.StringScannerException(message, span); + }, + StringScannerException: function StringScannerException(t0, t1) { + this._span_exception$_message = t0; + this._span_exception$_span = t1; + }, + PlatformSelector$parse: function(selector) { + return new E.PlatformSelector(E.PlatformSelector__wrapFormatException(new E.PlatformSelector$parse_closure(selector), null, type$.BooleanSelector)); + }, + PlatformSelector__wrapFormatException: function(body, span, $T) { + var t1 = body.call$0(); + return t1; + }, + PlatformSelector: function PlatformSelector(t0) { + this._platform_selector$_inner = t0; + }, + PlatformSelector$parse_closure: function PlatformSelector$parse_closure(t0) { + this.selector = t0; + }, + PlatformSelector_validate_closure: function PlatformSelector_validate_closure(t0, t1) { + this.$this = t0; + this.validVariables = t1; + }, + PlatformSelector_validate__closure: function PlatformSelector_validate__closure(t0) { + this.validVariables = t0; + }, + PlatformSelector_evaluate_closure: function PlatformSelector_evaluate_closure(t0) { + this.platform = t0; + }, + SuitePlatform$: function(runtime, inGoogle, os) { + var t1 = os == null ? C.OperatingSystem_none_none : os; + if (H.boolConversionCheck(runtime.isBrowser) && t1 !== C.OperatingSystem_none_none) + H.throwExpression(P.ArgumentError$('No OS should be passed for runtime "' + runtime.toString$0(0) + '".')); + return new E.SuitePlatform(runtime, t1, inGoogle); + }, + SuitePlatform: function SuitePlatform(t0, t1, t2) { + this.runtime = t0; + this.os = t1; + this.inGoogle = t2; + }, + StackTraceMapper: function StackTraceMapper() { + }, + LiveSuite: function LiveSuite() { + }, + JSStackTraceMapper_deserialize: function(serialized) { + var t1, t2, t3, + _s11_ = "packageRoot", + packageRoot = H._asStringNullable(serialized.$index(0, _s11_)); + if (packageRoot == null) + packageRoot = ""; + t1 = H._asStringNullable(serialized.$index(0, "mapContents")); + t2 = P.Uri_parse(H._asStringNullable(serialized.$index(0, "sdkRoot"))); + if (packageRoot.length !== 0) + t3 = new D.PackageRootResolver(B.ensureTrailingSlash(B.asUri(P.Uri_parse(H._asStringNullable(serialized.$index(0, _s11_))), _s11_))); + else { + t3 = type$.String; + t3 = F.PackageConfigResolver__normalizeMap(E.JSStackTraceMapper__deserializePackageConfigMap(type$.Map_dynamic_dynamic._as(serialized.$index(0, "packageConfigMap")).cast$2$0(0, t3, t3))); + t3 = new F.PackageConfigResolver(t3); + } + return new E.JSStackTraceMapper(t3, t2, t1, P.Uri_parse(H._asStringNullable(serialized.$index(0, "mapUrl")))); + }, + JSStackTraceMapper__deserializePackageConfigMap: function(serialized) { + return serialized.map$2$1(0, new E.JSStackTraceMapper__deserializePackageConfigMap_closure(), type$.String, type$.Uri); + }, + JSStackTraceMapper: function JSStackTraceMapper(t0, t1, t2, t3) { + var _ = this; + _._mapping = null; + _._packageResolver = t0; + _._sdkRoot = t1; + _._mapContents = t2; + _._mapUrl = t3; + }, + JSStackTraceMapper__deserializePackageConfigMap_closure: function JSStackTraceMapper__deserializePackageConfigMap_closure() { + } + }, + L = {StreamGroup: function StreamGroup(t0, t1, t2) { + var _ = this; + _._stream_group$_controller = null; + _._stream_group$_closed = false; + _._stream_group$_state = t0; + _._stream_group$_subscriptions = t1; + _.$ti = t2; + }, StreamGroup_add_closure: function StreamGroup_add_closure() { + }, StreamGroup_add_closure0: function StreamGroup_add_closure0(t0, t1) { + this.$this = t0; + this.stream = t1; + }, StreamGroup__onListen_closure: function StreamGroup__onListen_closure(t0) { + this.$this = t0; + }, StreamGroup__onCancelBroadcast_closure: function StreamGroup__onCancelBroadcast_closure(t0) { + this.$this = t0; + }, StreamGroup__listenToStream_closure: function StreamGroup__listenToStream_closure(t0, t1) { + this.$this = t0; + this.stream = t1; + }, _StreamGroupState: function _StreamGroupState(t0) { + this.name = t0; + }, Token: function Token(t0, t1) { + this.type = t0; + this.span = t1; + }, IdentifierToken: function IdentifierToken(t0, t1) { + this.span = t0; + this.name = t1; + }, TokenType: function TokenType(t0) { + this.name = t0; + }, + UnmodifiableSetView$: function(setBase, $E) { + return new L.UnmodifiableSetView(setBase, $E._eval$1("UnmodifiableSetView<0>")); + }, + UnmodifiableSetView: function UnmodifiableSetView(t0, t1) { + this._base = t0; + this.$ti = t1; + }, + UnmodifiableSetMixin: function UnmodifiableSetMixin() { + }, + _UnmodifiableSetView_DelegatingSet_UnmodifiableSetMixin: function _UnmodifiableSetView_DelegatingSet_UnmodifiableSetMixin() { + }, + WindowsStyle: function WindowsStyle(t0, t1, t2, t3) { + var _ = this; + _.separatorPattern = t0; + _.needsSeparatorPattern = t1; + _.rootPattern = t2; + _.relativeRootPattern = t3; + }, + WindowsStyle_absolutePathToUri_closure: function WindowsStyle_absolutePathToUri_closure() { + }, + decodeVlq: function(chars) { + var t1, t2, result, $stop, shift, t3, char, digit, result0, _null = null; + for (t1 = chars._parser$_length, t2 = chars._internal, result = 0, $stop = false, shift = 0; !$stop;) { + t3 = ++chars.index; + if (t3 >= t1) + throw H.wrapException(P.StateError$("incomplete VLQ value")); + if (t3 >= 0 && true) { + if (t3 < 0 || t3 >= t2.length) + return H.ioore(t2, t3); + char = t2[t3]; + } else + char = _null; + t3 = $.$get$_digits(); + if (!t3.containsKey$1(char)) + throw H.wrapException(P.FormatException$("invalid character in VLQ encoding: " + H.S(char), _null, _null)); + digit = t3.$index(0, char); + if (typeof digit !== "number") + return digit.$and(); + $stop = (digit & 32) === 0; + result += C.JSInt_methods._shlPositive$1(digit & 31, shift); + shift += 5; + } + result0 = result >>> 1; + result = (result & 1) === 1 ? -result0 : result0; + if (result < $.$get$MIN_INT32() || result > $.$get$MAX_INT32()) + throw H.wrapException(P.FormatException$("expected an encoded 32 bit int, but we got: " + result, _null, _null)); + return result; + }, + closure: function closure() { + }, + internalBootstrapBrowserTest: function(getMain) { + var t2, + channel = S.RemoteListener_start(getMain, new L.internalBootstrapBrowserTest_closure(), false), + t1 = N.postMessageChannel(); + t1.$ti._eval$1("StreamChannel<1>")._check(channel); + t1.get$stream(t1).pipe$1(channel._sink); + t2 = channel._streamController; + t2.toString; + new P._ControllerStream(t2, H._instanceType(t2)._eval$1("_ControllerStream<1>")).pipe$1(t1.get$sink()); + }, + internalBootstrapBrowserTest_closure: function internalBootstrapBrowserTest_closure() { + } + }, + G = {StreamQueue: function StreamQueue(t0, t1, t2, t3) { + var _ = this; + _._stream_queue$_source = t0; + _._stream_queue$_subscription = null; + _._isClosed = _._isDone = false; + _._eventsReceived = 0; + _._eventQueue = t1; + _._requestQueue = t2; + _.$ti = t3; + }, StreamQueue__ensureListening_closure: function StreamQueue__ensureListening_closure(t0) { + this.$this = t0; + }, StreamQueue__ensureListening_closure1: function StreamQueue__ensureListening_closure1(t0) { + this.$this = t0; + }, StreamQueue__ensureListening_closure0: function StreamQueue__ensureListening_closure0(t0) { + this.$this = t0; + }, _EventRequest: function _EventRequest() { + }, _NextRequest: function _NextRequest(t0, t1) { + this._completer = t0; + this.$ti = t1; + }, _RestRequest: function _RestRequest(t0, t1, t2) { + this._completer = t0; + this._streamQueue = t1; + this.$ti = t2; + }, Parser: function Parser(t0) { + this._parser0$_scanner = t0; + }, Matcher: function Matcher() { + }, SourceMapSpan: function SourceMapSpan(t0, t1, t2, t3) { + var _ = this; + _.isIdentifier = t0; + _.start = t1; + _.end = t2; + _.text = t3; + }, + SourceSpanFormatException$: function(message, span, _source) { + return new G.SourceSpanFormatException(message, span); + }, + SourceSpanException: function SourceSpanException() { + }, + SourceSpanFormatException: function SourceSpanFormatException(t0, t1) { + this._span_exception$_message = t0; + this._span_exception$_span = t1; + }, + State: function State(t0, t1) { + this.status = t0; + this.result = t1; + }, + Status: function Status(t0) { + this.name = t0; + }, + Result0: function Result0(t0) { + this.name = t0; + }, + expect: function(actual, matcher, reason) { + G._expect(true, matcher, null, reason, null, false); + }, + _expect: function(actual, matcher, formatter, reason, skip, verbose) { + var matchState, e, trace, exception, + t1 = type$.Invoker; + if (t1._as($.Zone__current.$index(0, C.Symbol_cQL)) == null) + throw H.wrapException(P.StateError$("expect() may only be called within a test.")); + t1 = t1._as($.Zone__current.$index(0, C.Symbol_cQL)); + if (H.boolConversionCheck(H._asBoolNullable($.Zone__current.$index(0, t1._closableKey))) && t1._onCloseCompleter.future._state !== 0) + throw H.wrapException(K.ClosedException$()); + matcher = M.wrapMatcher(matcher); + t1 = type$.dynamic; + matchState = P.LinkedHashMap_LinkedHashMap$_empty(t1, t1); + try { + if (matcher.matches$2(0, true, matchState)) { + t1 = P.Future_Future$sync(new G._expect_closure(), t1); + return t1; + } + t1 = reason; + } catch (exception) { + e = H.unwrapException(exception); + trace = H.getTraceFromException(exception); + t1 = reason == null ? H.S(e) + " at " + H.S(trace) : reason; + } + G.fail(new G._expect_closure0().call$5(true, matcher, t1, matchState, false)); + }, + fail: function(message) { + return H.throwExpression(new G.TestFailure(message)); + }, + formatFailure: function(expected, actual, which, reason) { + var t2, + t1 = new E.StringDescription(new P.StringBuffer("")).addDescriptionOf$1(expected)._out._contents; + t1 = B.indent(t1.charCodeAt(0) == 0 ? t1 : t1, "Expected: ") + "\n"; + t2 = new E.StringDescription(new P.StringBuffer("")).addDescriptionOf$1(true)._out._contents; + t2 = t1 + (B.indent(t2.charCodeAt(0) == 0 ? t2 : t2, " Actual: ") + "\n"); + t1 = which.length !== 0 ? t2 + (B.indent(which, " Which: ") + "\n") : t2; + if (reason != null) + t1 += reason + "\n"; + return t1.charCodeAt(0) == 0 ? t1 : t1; + }, + TestFailure: function TestFailure(t0) { + this.message = t0; + }, + _expect_closure0: function _expect_closure0() { + }, + _expect_closure: function _expect_closure() { + }, + method1: function() { + return $.x = $.x + 1; + }, + method2: function() { + return $.x = $.x + 1; + }, + main0: function() { + R.group("a group", new G.main_closure0()); + }, + main_closure0: function main_closure0() { + }, + main__closure: function main__closure() { + } + }, + T = {StreamSinkCompleter: function StreamSinkCompleter(t0, t1) { + this.sink = t0; + this.$ti = t1; + }, _CompleterSink: function _CompleterSink(t0) { + var _ = this; + _._destinationSink = _._stream_sink_completer$_doneCompleter = _._stream_sink_completer$_controller = null; + _.$ti = t0; + }, _CompleterSink__setDestinationSink_closure: function _CompleterSink__setDestinationSink_closure() { + }, SubscriptionStream: function SubscriptionStream(t0, t1) { + this._subscription_stream$_source = t0; + this.$ti = t1; + }, _CancelOnErrorSubscriptionWrapper: function _CancelOnErrorSubscriptionWrapper(t0, t1) { + this._stream_subscription$_source = t0; + this.$ti = t1; + }, _CancelOnErrorSubscriptionWrapper_onError_closure: function _CancelOnErrorSubscriptionWrapper_onError_closure(t0, t1) { + this.$this = t0; + this.handleError = t1; + }, _CancelOnErrorSubscriptionWrapper_onError__closure: function _CancelOnErrorSubscriptionWrapper_onError__closure(t0, t1, t2) { + this.handleError = t0; + this.error = t1; + this.stackTrace = t2; + }, Evaluator: function Evaluator(t0) { + this._semantics = t0; + }, + parseJsonExtended: function(json, mapUrl, otherMaps) { + if (type$.List_dynamic._is(json)) + return T.MappingBundle$fromJson(json, H._checkStringNullable(mapUrl)); + return T.parseJson(type$.Map_dynamic_dynamic._as(json), null, null); + }, + parseJson: function(map, mapUrl, otherMaps) { + var _s8_ = "sections"; + if (!J.$eq$(map.$index(0, "version"), 3)) + throw H.wrapException(P.ArgumentError$("unexpected source map version: " + H.S(map.$index(0, "version")) + ". Only version 3 is supported.")); + if (map.containsKey$1(_s8_)) { + if (map.containsKey$1("mappings") || map.containsKey$1("sources") || map.containsKey$1("names")) + throw H.wrapException(P.FormatException$('map containing "sections" cannot contain "mappings", "sources", or "names".', null, null)); + return T.MultiSectionMapping$fromJson(type$.List_dynamic._check(map.$index(0, _s8_)), otherMaps, mapUrl); + } + return T.SingleMapping$fromJson(map, mapUrl); + }, + MultiSectionMapping$fromJson: function(sections, otherMaps, mapUrl) { + var t1 = type$.JSArray_int; + t1 = new T.MultiSectionMapping(H.setRuntimeTypeInfo([], t1), H.setRuntimeTypeInfo([], t1), H.setRuntimeTypeInfo([], type$.JSArray_Mapping)); + t1.MultiSectionMapping$fromJson$3$mapUrl(sections, otherMaps, mapUrl); + return t1; + }, + MappingBundle$fromJson: function(json, mapUrl) { + var t1 = new T.MappingBundle(P.LinkedHashMap_LinkedHashMap$_empty(type$.String, type$.SingleMapping)); + t1.MappingBundle$fromJson$2$mapUrl(json, mapUrl); + return t1; + }, + SingleMapping$fromJson: function(map, mapUrl) { + var t5, t6, t7, t8, + t1 = H._checkStringNullable(map.$index(0, "file")), + t2 = type$.Iterable_dynamic, + t3 = type$.String, + t4 = P.List_List$from(t2._check(map.$index(0, "sources")), true, t3); + t2 = P.List_List$from(t2._check(map.$index(0, "names")), true, t3); + t5 = H._checkIntNullable(J.get$length$asx(map.$index(0, "sources"))); + if (typeof t5 !== "number") + return H.iae(t5); + t5 = new Array(t5); + t5.fixed$length = Array; + t5 = H.setRuntimeTypeInfo(t5, type$.JSArray_SourceFile); + t6 = H._checkStringNullable(map.$index(0, "sourceRoot")); + t7 = H.setRuntimeTypeInfo([], type$.JSArray_TargetLineEntry); + t8 = typeof mapUrl == "string" ? P.Uri_parse(mapUrl) : mapUrl; + t3 = new T.SingleMapping(t4, t2, t5, t7, t1, t6, type$.Uri._check(t8), P.LinkedHashMap_LinkedHashMap$_empty(t3, type$.dynamic)); + t3.SingleMapping$fromJson$2$mapUrl(map, mapUrl); + return t3; + }, + Mapping: function Mapping() { + }, + MultiSectionMapping: function MultiSectionMapping(t0, t1, t2) { + this._lineStart = t0; + this._columnStart = t1; + this._maps = t2; + }, + MappingBundle: function MappingBundle(t0) { + this._mappings = t0; + }, + SingleMapping: function SingleMapping(t0, t1, t2, t3, t4, t5, t6, t7) { + var _ = this; + _.urls = t0; + _.names = t1; + _.files = t2; + _.lines = t3; + _.targetUrl = t4; + _.sourceRoot = t5; + _._parser$_mapUrl = t6; + _.extensions = t7; + }, + SingleMapping$fromJson_closure: function SingleMapping$fromJson_closure(t0) { + this.$this = t0; + }, + SingleMapping__findLine_closure: function SingleMapping__findLine_closure(t0) { + this.line = t0; + }, + SingleMapping__findColumn_closure: function SingleMapping__findColumn_closure(t0) { + this.column = t0; + }, + TargetLineEntry: function TargetLineEntry(t0, t1) { + this.line = t0; + this.entries = t1; + }, + TargetEntry: function TargetEntry(t0, t1, t2, t3, t4) { + var _ = this; + _.column = t0; + _.sourceUrlId = t1; + _.sourceLine = t2; + _.sourceColumn = t3; + _.sourceNameId = t4; + }, + _MappingTokenizer: function _MappingTokenizer(t0, t1) { + this._internal = t0; + this._parser$_length = t1; + this.index = -1; + }, + _TokenKind: function _TokenKind(t0, t1, t2) { + this.isNewLine = t0; + this.isNewSegment = t1; + this.isEof = t2; + }, + LazyTrace: function LazyTrace(t0) { + this._lazy_trace$_thunk = t0; + this._lazy_trace$_inner = null; + }, + LazyTrace_foldFrames_closure: function LazyTrace_foldFrames_closure(t0, t1, t2) { + this.$this = t0; + this.predicate = t1; + this.terse = t2; + }, + RuntimeSelection: function RuntimeSelection() { + } + }, + X = {BooleanSelector: function BooleanSelector() { + }, All: function All() { + }, + ParsedPath_ParsedPath$parse: function(path, style) { + var t1, parts, separators, start, i, + root = style.getRoot$1(path); + style.isRootRelative$1(path); + if (root != null) + path = J.substring$1$s(path, root.length); + t1 = type$.JSArray_String; + parts = H.setRuntimeTypeInfo([], t1); + separators = H.setRuntimeTypeInfo([], t1); + t1 = path.length; + if (t1 !== 0 && style.isSeparator$1(C.JSString_methods._codeUnitAt$1(path, 0))) { + if (0 >= t1) + return H.ioore(path, 0); + C.JSArray_methods.add$1(separators, path[0]); + start = 1; + } else { + C.JSArray_methods.add$1(separators, ""); + start = 0; + } + for (i = start; i < t1; ++i) + if (style.isSeparator$1(C.JSString_methods._codeUnitAt$1(path, i))) { + C.JSArray_methods.add$1(parts, C.JSString_methods.substring$2(path, start, i)); + C.JSArray_methods.add$1(separators, path[i]); + start = i + 1; + } + if (start < t1) { + C.JSArray_methods.add$1(parts, C.JSString_methods.substring$1(path, start)); + C.JSArray_methods.add$1(separators, ""); + } + return new X.ParsedPath(style, root, parts, separators); + }, + ParsedPath: function ParsedPath(t0, t1, t2, t3) { + var _ = this; + _.style = t0; + _.root = t1; + _.parts = t2; + _.separators = t3; + }, + ParsedPath_normalize_closure: function ParsedPath_normalize_closure(t0) { + this.$this = t0; + }, + PathException$: function(message) { + return new X.PathException(message); + }, + PathException: function PathException(t0) { + this.message = t0; + }, + SourceSpanWithContext$: function(start, end, text, _context) { + var t1 = new X.SourceSpanWithContext(_context, start, end, text); + t1.SourceSpanBase$3(start, end, text); + if (!C.JSString_methods.contains$1(_context, text)) + H.throwExpression(P.ArgumentError$('The context line "' + _context + '" must contain "' + text + '".')); + if (B.findLineStart(_context, text, start.get$column()) == null) + H.throwExpression(P.ArgumentError$('The span text "' + text + '" must start at column ' + (start.get$column() + 1) + ' in a line within "' + _context + '".')); + return t1; + }, + SourceSpanWithContext: function SourceSpanWithContext(t0, t1, t2, t3) { + var _ = this; + _._context = t0; + _.start = t1; + _.end = t2; + _.text = t3; + }, + LazyChain: function LazyChain(t0) { + this._thunk = t0; + this._lazy_chain$_inner = null; + }, + LazyChain_foldFrames_closure: function LazyChain_foldFrames_closure(t0, t1, t2) { + this.$this = t0; + this.predicate = t1; + this.terse = t2; + }, + LazyChain_toTrace_closure: function LazyChain_toTrace_closure(t0) { + this.$this = t0; + }, + StringScanner: function StringScanner() { + }, + Declarer$: function(collectTraces, metadata, noRetry, platformVariables) { + var _null = null, + t1 = metadata == null ? O.Metadata_Metadata(_null, _null, _null, _null, _null, _null, _null, _null, _null, _null) : metadata, + t2 = platformVariables == null ? C.C_EmptyUnmodifiableSet : platformVariables, + t3 = type$.JSArray_of_dynamic_Function, + t4 = type$.JSArray_GroupEntry; + return new X.Declarer(_null, _null, t1, t2, _null, collectTraces, noRetry, H.setRuntimeTypeInfo([], t3), H.setRuntimeTypeInfo([], t3), H.setRuntimeTypeInfo([], t3), new R.Timeout(P.Duration$(0, 12), _null), H.setRuntimeTypeInfo([], t3), H.setRuntimeTypeInfo([], t4), H.setRuntimeTypeInfo([], t4)); + }, + Declarer: function Declarer(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13) { + var _ = this; + _._declarer$_parent = t0; + _._declarer$_name = t1; + _._metadata = t2; + _._platformVariables = t3; + _._declarer$_trace = t4; + _._collectTraces = t5; + _._noRetry = t6; + _._setUps = t7; + _._tearDowns = t8; + _._setUpAlls = t9; + _._timeout = t10; + _._tearDownAlls = t11; + _._entries = t12; + _._built = false; + _._soloEntries = t13; + }, + Declarer_test_closure: function Declarer_test_closure(t0, t1) { + this.$this = t0; + this.body = t1; + }, + Declarer_test__closure: function Declarer_test__closure(t0, t1) { + this.$this = t0; + this.body = t1; + }, + Declarer_test___closure: function Declarer_test___closure(t0, t1) { + this.$this = t0; + this.body = t1; + }, + Declarer_group_closure: function Declarer_group_closure(t0) { + this.body = t0; + }, + Declarer_build_closure: function Declarer_build_closure(t0) { + this.$this = t0; + }, + Declarer__runSetUps_closure: function Declarer__runSetUps_closure() { + }, + Declarer__tearDownAll_closure: function Declarer__tearDownAll_closure(t0) { + this.$this = t0; + }, + Declarer__tearDownAll__closure: function Declarer__tearDownAll__closure(t0) { + this.$this = t0; + }, + Declarer__tearDownAll___closure: function Declarer__tearDownAll___closure(t0) { + this.$this = t0; + }, + PrintSink: function PrintSink(t0) { + this._print_sink$_buffer = t0; + } + }, + U = { + _expandSafe: function(start, end) { + if (start == null || end == null) + return null; + if (start.file !== end.file) + return null; + return start.expand$1(0, end); + }, + VariableNode: function VariableNode(t0, t1) { + this.span = t0; + this.name = t1; + }, + NotNode: function NotNode(t0, t1) { + this.span = t0; + this.child = t1; + }, + OrNode: function OrNode(t0, t1) { + this.left = t0; + this.right = t1; + }, + AndNode: function AndNode(t0, t1) { + this.left = t0; + this.right = t1; + }, + ConditionalNode: function ConditionalNode(t0, t1, t2) { + this.condition = t0; + this.whenTrue = t1; + this.whenFalse = t2; + }, + Highlighter__normalizeNewlines: function(span) { + var t1, endOffset, i, t2, t3, t4, + text = span.get$text(); + if (!C.JSString_methods.contains$1(text, "\r\n")) + return span; + t1 = span.get$end(); + endOffset = t1.get$offset(t1); + for (t1 = text.length - 1, i = 0; i < t1; ++i) + if (C.JSString_methods._codeUnitAt$1(text, i) === 13 && C.JSString_methods._codeUnitAt$1(text, i + 1) === 10) + --endOffset; + t1 = span.get$start(); + t2 = span.get$sourceUrl(); + t3 = span.get$end().get$line(); + t2 = V.SourceLocation$(endOffset, span.get$end().get$column(), t3, t2); + t3 = H.stringReplaceAllUnchecked(text, "\r\n", "\n"); + t4 = span.get$context(); + return X.SourceSpanWithContext$(t1, t2, t3, H.stringReplaceAllUnchecked(t4, "\r\n", "\n")); + }, + Highlighter__normalizeTrailingNewline: function(span) { + var context, text, start, end, t1, t2, t3; + if (!C.JSString_methods.endsWith$1(span.get$context(), "\n")) + return span; + if (C.JSString_methods.endsWith$1(span.get$text(), "\n\n")) + return span; + context = C.JSString_methods.substring$2(span.get$context(), 0, span.get$context().length - 1); + text = span.get$text(); + start = span.get$start(); + end = span.get$end(); + if (C.JSString_methods.endsWith$1(span.get$text(), "\n")) { + t1 = B.findLineStart(span.get$context(), span.get$text(), span.get$start().get$column()); + t2 = span.get$start().get$column(); + if (typeof t1 !== "number") + return t1.$add(); + t2 = t1 + t2 + span.get$length(span) === span.get$context().length; + t1 = t2; + } else + t1 = false; + if (t1) { + text = C.JSString_methods.substring$2(span.get$text(), 0, span.get$text().length - 1); + t1 = span.get$end(); + t1 = t1.get$offset(t1); + t2 = span.get$sourceUrl(); + t3 = span.get$end().get$line(); + if (typeof t3 !== "number") + return t3.$sub(); + end = V.SourceLocation$(t1 - 1, U.Highlighter__lastLineLength(text), t3 - 1, t2); + t1 = span.get$start(); + t1 = t1.get$offset(t1); + t2 = span.get$end(); + start = t1 === t2.get$offset(t2) ? end : span.get$start(); + } + return X.SourceSpanWithContext$(start, end, text, context); + }, + Highlighter__normalizeEndOfLine: function(span) { + var text, t1, t2, t3, t4; + if (span.get$end().get$column() !== 0) + return span; + if (span.get$end().get$line() == span.get$start().get$line()) + return span; + text = C.JSString_methods.substring$2(span.get$text(), 0, span.get$text().length - 1); + t1 = span.get$start(); + t2 = span.get$end(); + t2 = t2.get$offset(t2); + t3 = span.get$sourceUrl(); + t4 = span.get$end().get$line(); + if (typeof t4 !== "number") + return t4.$sub(); + return X.SourceSpanWithContext$(t1, V.SourceLocation$(t2 - 1, U.Highlighter__lastLineLength(text), t4 - 1, t3), text, span.get$context()); + }, + Highlighter__lastLineLength: function(text) { + var t1 = text.length; + if (t1 === 0) + return 0; + if (C.JSString_methods.codeUnitAt$1(text, t1 - 1) === 10) + return t1 === 1 ? 0 : t1 - C.JSString_methods.lastIndexOf$2(text, "\n", t1 - 2) - 1; + else + return t1 - C.JSString_methods.lastIndexOf$1(text, "\n") - 1; + }, + Highlighter: function Highlighter(t0, t1, t2, t3, t4) { + var _ = this; + _._span = t0; + _._color = t1; + _._multiline = t2; + _._paddingBeforeSidebar = t3; + _._highlighter$_buffer = t4; + }, + Highlighter__writeFirstLine_closure: function Highlighter__writeFirstLine_closure(t0, t1) { + this.$this = t0; + this.line = t1; + }, + Highlighter__writeFirstLine_closure0: function Highlighter__writeFirstLine_closure0(t0, t1) { + this.$this = t0; + this.textInside = t1; + }, + Highlighter__writeFirstLine_closure1: function Highlighter__writeFirstLine_closure1(t0, t1) { + this._box_0 = t0; + this.$this = t1; + }, + Highlighter__writeFirstLine_closure2: function Highlighter__writeFirstLine_closure2(t0, t1) { + this._box_0 = t0; + this.$this = t1; + }, + Highlighter__writeIntermediateLines_closure: function Highlighter__writeIntermediateLines_closure(t0, t1) { + this.$this = t0; + this.line = t1; + }, + Highlighter__writeLastLine_closure: function Highlighter__writeLastLine_closure(t0, t1) { + this.$this = t0; + this.line = t1; + }, + Highlighter__writeLastLine_closure0: function Highlighter__writeLastLine_closure0(t0, t1) { + this.$this = t0; + this.textInside = t1; + }, + Highlighter__writeLastLine_closure1: function Highlighter__writeLastLine_closure1(t0, t1) { + this._box_0 = t0; + this.$this = t1; + }, + Highlighter__writeSidebar_closure: function Highlighter__writeSidebar_closure(t0, t1, t2) { + this.$this = t0; + this.line = t1; + this.end = t2; + }, + Chain_capture: function(callback, errorZone, when, $T) { + var t1, spec, _null = null; + if (!when) + return P.runZoned(callback, _null, _null, _null, $T); + if (typeof WeakMap == "function") + t1 = new WeakMap(); + else { + t1 = $.Expando__keyCount; + $.Expando__keyCount = t1 + 1; + t1 = "expando$key$" + t1; + } + spec = new O.StackZoneSpecification(new P.Expando(t1, "stack chains", type$.Expando__Node), _null, false); + t1 = type$.dynamic; + return P.runZoned(new U.Chain_capture_closure(callback, $T), _null, P._ZoneSpecification$(_null, _null, spec.get$_stack_zone_specification$_errorCallback(), _null, _null, _null, spec.get$_stack_zone_specification$_registerBinaryCallback(), spec.get$_stack_zone_specification$_registerCallback(), spec.get$_stack_zone_specification$_registerUnaryCallback(), _null, _null, _null, _null), P.LinkedHashMap_LinkedHashMap$_literal([$.$get$_specKey(), spec, $.$get$StackZoneSpecification_disableKey(), false], t1, t1), $T); + }, + Chain_Chain$current: function() { + var t1 = $.Zone__current, + t2 = $.$get$_specKey(), + t3 = type$.StackZoneSpecification; + if (t3._check(t1.$index(0, t2)) != null) { + t1 = t3._check($.Zone__current.$index(0, t2)); + t2 = t1._currentTrace$1(3); + t1 = t1._currentNode; + return new O._Node(Y.Trace_Trace$from(t2), t1).toChain$0(); + } + return new X.LazyChain(new U.Chain_Chain$current_closure(U.Chain_Chain$forTrace(P.StackTrace_current()), 0)); + }, + Chain_Chain$forTrace: function(trace) { + var t1, t2, t3; + if (type$.Chain._is(trace)) + return trace; + t1 = $.Zone__current; + t2 = $.$get$_specKey(); + t3 = type$.StackZoneSpecification; + if (t3._check(t1.$index(0, t2)) != null) + return t3._check($.Zone__current.$index(0, t2)).chainFor$1(trace); + t1 = type$.Trace; + if (t1._is(trace)) + return new U.Chain(P.List_List$unmodifiable(H.setRuntimeTypeInfo([trace], type$.JSArray_Trace), t1)); + return new X.LazyChain(new U.Chain_Chain$forTrace_closure(trace)); + }, + Chain_Chain$parse: function(chain) { + var _s26_ = "<asynchronous suspension>\n", + _s51_ = "===== asynchronous gap ===========================\n"; + if (chain.length === 0) + return new U.Chain(P.List_List$unmodifiable(H.setRuntimeTypeInfo([], type$.JSArray_Trace), type$.Trace)); + if (C.JSString_methods.contains$1(chain, _s26_)) + return new U.Chain(P.List_List$unmodifiable(new H.MappedListIterable(H.setRuntimeTypeInfo(chain.split(_s26_), type$.JSArray_String), type$.Trace_Function_String._check(new U.Chain_Chain$parse_closure()), type$.MappedListIterable_String_Trace), type$.Trace)); + if (!C.JSString_methods.contains$1(chain, _s51_)) + return new U.Chain(P.List_List$unmodifiable(H.setRuntimeTypeInfo([Y.Trace_Trace$parse(chain)], type$.JSArray_Trace), type$.Trace)); + return new U.Chain(P.List_List$unmodifiable(new H.MappedListIterable(H.setRuntimeTypeInfo(chain.split(_s51_), type$.JSArray_String), type$.Trace_Function_String._check(new U.Chain_Chain$parse_closure0()), type$.MappedListIterable_String_Trace), type$.Trace)); + }, + Chain: function Chain(t0) { + this.traces = t0; + }, + Chain_capture_closure: function Chain_capture_closure(t0, t1) { + this.callback = t0; + this.T = t1; + }, + Chain_Chain$current_closure: function Chain_Chain$current_closure(t0, t1) { + this.chain = t0; + this.level = t1; + }, + Chain_Chain$forTrace_closure: function Chain_Chain$forTrace_closure(t0) { + this.trace = t0; + }, + Chain_Chain$parse_closure: function Chain_Chain$parse_closure() { + }, + Chain_Chain$parse_closure0: function Chain_Chain$parse_closure0() { + }, + Chain_foldFrames_closure: function Chain_foldFrames_closure(t0, t1) { + this.predicate = t0; + this.terse = t1; + }, + Chain_foldFrames_closure0: function Chain_foldFrames_closure0(t0) { + this.terse = t0; + }, + Chain_toTrace_closure: function Chain_toTrace_closure() { + }, + Chain_toString_closure0: function Chain_toString_closure0() { + }, + Chain_toString__closure0: function Chain_toString__closure0() { + }, + Chain_toString_closure: function Chain_toString_closure(t0) { + this.longest = t0; + }, + Chain_toString__closure: function Chain_toString__closure(t0) { + this.longest = t0; + }, + Invoker_guard: function(callback, $T) { + var _null = null; + return P.runZoned(callback, _null, P._ZoneSpecification$(_null, _null, _null, _null, new U.Invoker_guard_closure(), _null, _null, _null, _null, _null, _null, _null, _null), _null, $T); + }, + LocalTest: function LocalTest(t0, t1, t2, t3, t4, t5) { + var _ = this; + _.name = t0; + _.metadata = t1; + _.trace = t2; + _.isScaffoldAll = t3; + _._body = t4; + _._guarded = t5; + }, + Invoker: function Invoker(t0, t1, t2, t3, t4, t5, t6) { + var _ = this; + _._invoker$_controller = null; + _._guarded = t0; + _._closableKey = t1; + _._onCloseCompleter = t2; + _._outstandingCallbackZones = t3; + _._counterKey = t4; + _._runCount = 0; + _._timeoutTimer = _._invokerZone = null; + _._invoker$_tearDowns = t5; + _._printsOnFailure = t6; + }, + Invoker_guard_closure: function Invoker_guard_closure() { + }, + Invoker_guard__closure: function Invoker_guard__closure(t0, t1, t2, t3) { + var _ = this; + _.invoker = t0; + _.zone = t1; + _.error = t2; + _.stackTrace = t3; + }, + Invoker_waitForOutstandingCallbacks_closure: function Invoker_waitForOutstandingCallbacks_closure(t0, t1, t2, t3) { + var _ = this; + _._box_0 = t0; + _.$this = t1; + _.fn = t2; + _.counter = t3; + }, + Invoker_waitForOutstandingCallbacks_closure0: function Invoker_waitForOutstandingCallbacks_closure0(t0, t1) { + this._box_0 = t0; + this.$this = t1; + }, + Invoker_heartbeat_message: function Invoker_heartbeat_message(t0) { + this.timeout = t0; + }, + Invoker_heartbeat_closure: function Invoker_heartbeat_closure(t0, t1, t2) { + this.$this = t0; + this.message = t1; + this.timeout = t2; + }, + Invoker_heartbeat__closure: function Invoker_heartbeat__closure(t0, t1, t2) { + this.$this = t0; + this.message = t1; + this.timeout = t2; + }, + Invoker__handleError_closure: function Invoker__handleError_closure(t0) { + this._box_0 = t0; + }, + Invoker__handleError_closure0: function Invoker__handleError_closure0(t0) { + this.$this = t0; + }, + Invoker__onRun_closure: function Invoker__onRun_closure(t0, t1) { + this.$this = t0; + this.outstandingCallbacksForBody = t1; + }, + Invoker__onRun__closure: function Invoker__onRun__closure(t0, t1) { + this.$this = t0; + this.outstandingCallbacksForBody = t1; + }, + Invoker__onRun___closure: function Invoker__onRun___closure(t0) { + this.$this = t0; + }, + Invoker__onRun____closure: function Invoker__onRun____closure(t0) { + this.$this = t0; + }, + Invoker__onRun___closure0: function Invoker__onRun___closure0(t0) { + this.$this = t0; + }, + _AsyncCounter: function _AsyncCounter(t0) { + this._count = 1; + this._invoker$_completer = t0; + }, + StackTraceFormatter: function StackTraceFormatter(t0, t1) { + this._mapper = null; + this._except = t0; + this._only = t1; + }, + StackTraceFormatter_formatStackTrace_closure: function StackTraceFormatter_formatStackTrace_closure(t0) { + this.$this = t0; + }, + Suite__filterGroup: function(group, platform) { + var t1, _null = null, + filtered = group.forPlatform$1(platform); + if (filtered != null) + return filtered; + t1 = P.List_List$unmodifiable(H.setRuntimeTypeInfo([], type$.JSArray_GroupEntry), type$.GroupEntry); + return new O.Group(_null, group.metadata, _null, t1, _null, _null); + }, + Suite: function Suite(t0, t1, t2) { + this.platform = t0; + this.path = t1; + this.group = t2; + }, + SuiteConfiguration__list: function(input, $T) { + return null; + }, + SuiteConfiguration__map: function(input, $K, $V) { + return C.Map_empty1; + }, + SuiteConfiguration: function SuiteConfiguration() { + }, + RemoteException_serialize: function(error, stackTrace) { + var exception, supertype, t1, message = null; + if (typeof error == "string") + message = error; + else + try { + message = J.toString$0$(J.get$message$x(error)); + } catch (exception) { + if (!type$.NoSuchMethodError._is(H.unwrapException(exception))) + throw exception; + } + supertype = error instanceof G.TestFailure ? "TestFailure" : null; + t1 = J.getInterceptor$(error); + return P.LinkedHashMap_LinkedHashMap$_literal(["message", message, "type", t1.get$runtimeType(error).toString$0(0), "supertype", supertype, "toString", t1.toString$0(error), "stackChain", J.toString$0$(U.Chain_Chain$forTrace(stackTrace))], type$.String, type$.dynamic); + } + }, + R = {IntersectionSelector: function IntersectionSelector(t0, t1) { + this._selector1 = t0; + this._selector2 = t1; + }, StreamChannel: function StreamChannel() { + }, _StreamChannel: function _StreamChannel(t0, t1, t2) { + this.stream = t0; + this.sink = t1; + this.$ti = t2; + }, StreamChannelMixin: function StreamChannelMixin() { + }, Timeout: function Timeout(t0, t1) { + this.duration = t0; + this.scaleFactor = t1; + }, ExpandedReporter: function ExpandedReporter(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12) { + var _ = this; + _._expanded$_color = t0; + _._green = t1; + _._red = t2; + _._yellow = t3; + _._gray = t4; + _._bold = t5; + _._noColor = t6; + _._engine = t7; + _._printPath = t8; + _._printPlatform = t9; + _._stopwatch = t10; + _._lastProgressSuffix = _._lastProgressMessage = _._lastProgressFailed = _._lastProgressSkipped = _._lastProgressPassed = null; + _._subscriptions = t11; + _._expanded$_sink = t12; + }, ExpandedReporter__onTestStarted_closure: function ExpandedReporter__onTestStarted_closure(t0, t1) { + this.$this = t0; + this.liveTest = t1; + }, ExpandedReporter__onTestStarted_closure0: function ExpandedReporter__onTestStarted_closure0(t0, t1) { + this.$this = t0; + this.liveTest = t1; + }, ExpandedReporter__onTestStarted_closure1: function ExpandedReporter__onTestStarted_closure1(t0, t1) { + this.$this = t0; + this.liveTest = t1; + }, + _declarer: function() { + var t1, + declarer = type$.Declarer._as($.Zone__current.$index(0, C.Symbol_Drw)); + if (declarer != null) + return declarer; + t1 = $._globalDeclarer; + if (t1 != null) + return t1; + $._globalDeclarer = X.Declarer$(false, null, false, null); + P.scheduleMicrotask(new R._declarer_closure()); + return $._globalDeclarer; + }, + test: function(description, body) { + var _null = null; + R._declarer().test$9$onPlatform$retry$skip$solo$tags$testOn$timeout(description, body, _null, _null, _null, false, _null, _null, _null); + return; + }, + group: function(description, body) { + var _null = null; + R._declarer().group$9$onPlatform$retry$skip$solo$tags$testOn$timeout(description, body, _null, _null, _null, false, _null, _null, _null); + return; + }, + _declarer_closure: function _declarer_closure() { + }, + _declarer__closure: function _declarer__closure(t0) { + this.engine = t0; + }, + main: function() { + L.internalBootstrapBrowserTest(new R.main_closure()); + }, + main_closure: function main_closure() { + } + }, + B = {RecursiveVisitor: function RecursiveVisitor() { + }, InternalStyle: function InternalStyle() { + }, + StreamChannelController$: function(allowForeignErrors, sync, $T) { + var _null = null, + t1 = new B.StreamChannelController($T._eval$1("StreamChannelController<0>")), + localToForeignController = P.StreamController_StreamController(_null, _null, true, $T), + foreignToLocalController = P.StreamController_StreamController(_null, _null, true, $T), + t2 = H._instanceType(foreignToLocalController), + t3 = H._instanceType(localToForeignController); + t1.set$_local(K.GuaranteeChannel$(new P._ControllerStream(foreignToLocalController, t2._eval$1("_ControllerStream<1>")), new P._StreamSinkWrapper(localToForeignController, t3._eval$1("_StreamSinkWrapper<1>")), true, $T)); + t1.set$_foreign(K.GuaranteeChannel$(new P._ControllerStream(localToForeignController, t3._eval$1("_ControllerStream<1>")), new P._StreamSinkWrapper(foreignToLocalController, t2._eval$1("_StreamSinkWrapper<1>")), allowForeignErrors, $T)); + return t1; + }, + StreamChannelController: function StreamChannelController(t0) { + this._foreign = this._local = null; + this.$ti = t0; + }, + Runtime_Runtime$deserialize: function(serialized) { + var $parent, t1, t2, t3, + _s10_ = "identifier"; + if (typeof serialized == "string") + return C.JSArray_methods.firstWhere$1(C.List_m7e, new B.Runtime_Runtime$deserialize_closure(serialized)); + type$.Map_dynamic_dynamic._as(serialized); + $parent = serialized.$index(0, "parent"); + if ($parent != null) { + t1 = H._asStringNullable(serialized.$index(0, "name")); + t2 = H._asStringNullable(serialized.$index(0, _s10_)); + t3 = B.Runtime_Runtime$deserialize($parent); + return new B.Runtime(t1, t2, t3, t3.isDartVM, t3.isBrowser, t3.isJS, t3.isBlink, t3.isHeadless); + } + return new B.Runtime(H._asStringNullable(serialized.$index(0, "name")), H._asStringNullable(serialized.$index(0, _s10_)), null, H._asBoolNullable(serialized.$index(0, "isDartVM")), H._asBoolNullable(serialized.$index(0, "isBrowser")), H._asBoolNullable(serialized.$index(0, "isJS")), H._asBoolNullable(serialized.$index(0, "isBlink")), H._asBoolNullable(serialized.$index(0, "isHeadless"))); + }, + Runtime: function Runtime(t0, t1, t2, t3, t4, t5, t6, t7) { + var _ = this; + _.name = t0; + _.identifier = t1; + _.parent = t2; + _.isDartVM = t3; + _.isBrowser = t4; + _.isJS = t5; + _.isBlink = t6; + _.isHeadless = t7; + }, + Runtime_Runtime$deserialize_closure: function Runtime_Runtime$deserialize_closure(t0) { + this.serialized = t0; + }, + indent: function(string, first) { + var size = first == null ? 2 : first.length; + return B.prefixLines(string, C.JSString_methods.$mul(" ", size), first); + }, + toSentence: function(iter) { + var result, + t1 = iter.length; + if (t1 === 1) + return J.toString$0$(C.JSArray_methods.get$first(iter)); + result = H.SubListIterable$(iter, 0, t1 - 1, H._arrayInstanceType(iter)._precomputed1).join$1(0, ", "); + if (iter.length > 2) + result += ","; + return result + " and " + H.S(C.JSArray_methods.get$last(iter)); + }, + pluralize: function($name, number) { + if (number === 1) + return $name; + return $name + "s"; + }, + prefixLines: function(text, prefix, first) { + var single, lines, t1, t2; + if (first == null) + first = prefix; + single = first; + lines = H.setRuntimeTypeInfo(text.split("\n"), type$.JSArray_String); + if (lines.length === 1) + return single + text; + t1 = first + H.S(C.JSArray_methods.get$first(lines)) + "\n"; + for (t2 = H.SubListIterable$(lines, 1, null, type$.String).take$1(0, lines.length - 2), t2 = new H.ListIterator(t2, t2.get$length(t2), t2.$ti._eval$1("ListIterator<ListIterable.E>")); t2.moveNext$0();) + t1 += prefix + H.S(t2.__internal$_current) + "\n"; + t1 += prefix + H.S(C.JSArray_methods.get$last(lines)); + return t1.charCodeAt(0) == 0 ? t1 : t1; + }, + closure0: function closure0() { + }, + LiveSuiteController$: function(_suite) { + var t1 = $.Zone__current, + t2 = H.setRuntimeTypeInfo([], type$.JSArray_dynamic), + t3 = $.Zone__current, + t4 = type$._Future_dynamic, + t5 = type$._AsyncCompleter_dynamic, + t6 = type$.LiveTest; + t5 = new B.LiveSuiteController(_suite, new F.FutureGroup(new P._AsyncCompleter(new P._Future(t1, type$._Future_List_dynamic), type$._AsyncCompleter_List_dynamic), t2, type$.FutureGroup_dynamic), new P._AsyncCompleter(new P._Future(t3, t4), t5), new P._SyncBroadcastStreamController(null, null, type$._SyncBroadcastStreamController_LiveTest), P.LinkedHashSet_LinkedHashSet$_empty(t6), P.LinkedHashSet_LinkedHashSet$_empty(t6), P.LinkedHashSet_LinkedHashSet$_empty(t6), new S.AsyncMemoizer(new P._AsyncCompleter(new P._Future(t3, t4), t5), type$.AsyncMemoizer_dynamic)); + t5.LiveSuiteController$1(_suite); + return t5; + }, + _LiveSuite: function _LiveSuite(t0) { + this._live_suite_controller$_controller = t0; + }, + LiveSuiteController: function LiveSuiteController(t0, t1, t2, t3, t4, t5, t6, t7) { + var _ = this; + _._liveSuite = null; + _._live_suite_controller$_suite = t0; + _._onCompleteGroup = t1; + _._live_suite_controller$_onCloseCompleter = t2; + _._onTestStartedController = t3; + _._passed = t4; + _._skipped = t5; + _._failed = t6; + _._live_suite_controller$_active = null; + _._live_suite_controller$_closeMemo = t7; + }, + LiveSuiteController_closure: function LiveSuiteController_closure(t0) { + this.$this = t0; + }, + LiveSuiteController_closure0: function LiveSuiteController_closure0() { + }, + LiveSuiteController_reportLiveTest_closure: function LiveSuiteController_reportLiveTest_closure(t0, t1, t2) { + this.$this = t0; + this.liveTest = t1; + this.countSuccess = t2; + }, + LiveSuiteController_close_closure: function LiveSuiteController_close_closure(t0) { + this.$this = t0; + }, + asUri: function(uri, $name) { + if (type$.Uri._is(uri)) + return uri; + throw H.wrapException(P.ArgumentError$value(uri, $name, "Must be a String or a Uri.")); + }, + ensureTrailingSlash: function(uri) { + var t1; + if (uri.get$pathSegments().length === 0) + return uri.replace$1$path(0, "/"); + t1 = C.JSArray_methods.get$last(uri.get$pathSegments()); + t1.toString; + if (J.get$length$asx(t1) === 0) + return uri; + t1 = uri.get$pathSegments(); + t1 = H.setRuntimeTypeInfo(t1.slice(0), H._arrayInstanceType(t1)._eval$1("JSArray<1>")); + C.JSArray_methods.add$1(t1, ""); + return uri.replace$1$pathSegments(0, t1); + }, + isAlphabetic: function(char) { + var t1; + if (!(char >= 65 && char <= 90)) + t1 = char >= 97 && char <= 122; + else + t1 = true; + return t1; + }, + isDriveLetter: function(path, index) { + var t1 = path.length, + t2 = index + 2; + if (t1 < t2) + return false; + if (!B.isAlphabetic(C.JSString_methods.codeUnitAt$1(path, index))) + return false; + if (C.JSString_methods.codeUnitAt$1(path, index + 1) !== 58) + return false; + if (t1 === t2) + return true; + return C.JSString_methods.codeUnitAt$1(path, t2) === 47; + }, + countCodeUnits: function(string, codeUnit) { + var t1, count; + for (t1 = new H.CodeUnits(string), t1 = new H.ListIterator(t1, t1.get$length(t1), type$.CodeUnits._eval$1("ListIterator<ListMixin.E>")), count = 0; t1.moveNext$0();) + if (t1.__internal$_current === codeUnit) + ++count; + return count; + }, + findLineStart: function(context, text, column) { + var beginningOfLine, index, lineStart; + if (text.length === 0) + for (beginningOfLine = 0; true;) { + index = C.JSString_methods.indexOf$2(context, "\n", beginningOfLine); + if (index === -1) + return context.length - beginningOfLine >= column ? beginningOfLine : null; + if (index - beginningOfLine >= column) + return beginningOfLine; + beginningOfLine = index + 1; + } + index = C.JSString_methods.indexOf$1(context, text); + for (; index !== -1;) { + lineStart = index === 0 ? 0 : C.JSString_methods.lastIndexOf$2(context, "\n", index - 1) + 1; + if (column === index - lineStart) + return lineStart; + index = C.JSString_methods.indexOf$2(context, text, index + 1); + } + return null; + }, + validateErrorArgs: function(string, match, position, $length) { + var t1; + if (position < 0) + throw H.wrapException(P.RangeError$("position must be greater than or equal to 0.")); + else if (position > string.length) + throw H.wrapException(P.RangeError$("position must be less than or equal to the string length.")); + t1 = position + $length > string.length; + if (t1) + throw H.wrapException(P.RangeError$("position plus length must not go beyond the end of the string.")); + } + }, + Q = { + QueueList$: function($E) { + var t1 = new Q.QueueList($E._eval$1("QueueList<0>")), + t2 = new Array(8); + t2.fixed$length = Array; + t1.set$_queue_list$_table(H.setRuntimeTypeInfo(t2, $E._eval$1("JSArray<0>"))); + return t1; + }, + QueueList__nextPowerOf2: function(number) { + var nextNumber; + H.assertHelper(number > 0); + number = (number << 1 >>> 0) - 1; + for (; true; number = nextNumber) { + nextNumber = (number & number - 1) >>> 0; + if (nextNumber === 0) + return number; + } + }, + QueueList: function QueueList(t0) { + var _ = this; + _._queue_list$_table = null; + _._queue_list$_tail = _._queue_list$_head = 0; + _.$ti = t0; + }, + _QueueList_Object_ListMixin: function _QueueList_Object_ListMixin() { + } + }, + M = {UnionSet: function UnionSet(t0, t1, t2) { + this._sets = t0; + this._disjoint = t1; + this.$ti = t2; + }, UnionSet_length_closure: function UnionSet_length_closure(t0) { + this.$this = t0; + }, UnionSet__iterable_closure: function UnionSet__iterable_closure(t0) { + this.$this = t0; + }, _UnionSet_SetBase_UnmodifiableSetMixin: function _UnionSet_SetBase_UnmodifiableSetMixin() { + }, _DelegatingIterableBase: function _DelegatingIterableBase() { + }, DelegatingIterable: function DelegatingIterable() { + }, DelegatingSet: function DelegatingSet(t0, t1) { + this._base = t0; + this.$ti = t1; + }, TypeMatcher: function TypeMatcher() { + }, + wrapMatcher: function(x) { + var _s18_ = "satisfies function"; + if (x instanceof G.Matcher) + return x; + else if (type$.bool_Function_Object._is(x)) + return new Y._Predicate(x, _s18_, type$._Predicate_Object); + else if (type$.bool_Function_Null._is(x)) + return new Y._Predicate(new M.wrapMatcher_closure(x), _s18_, type$._Predicate_dynamic); + else + return typeof x == "string" ? new D._StringEqualsMatcher(x) : new D._DeepMatcher(x, 100); + }, + escape: function(str) { + str.toString; + return C.JSString_methods.splitMapJoin$2$onMatch(H.stringReplaceAllUnchecked(str, "\\", "\\\\"), $.$get$_escapeRegExp(), type$.String_Function_Match._check(new M.escape_closure())); + }, + _getHexLiteral: function(input) { + var t1, it, result; + H._checkStringNullable(input); + input.toString; + t1 = new P.Runes(input); + it = t1.get$iterator(t1); + if (!it.moveNext$0()) + H.throwExpression(H.IterableElementError_noElement()); + result = it.get$current(); + if (it.moveNext$0()) + H.throwExpression(H.IterableElementError_tooMany()); + return "\\x" + C.JSString_methods.padLeft$2(J.toRadixString$1$n(result, 16).toUpperCase(), 2, "0"); + }, + wrapMatcher_closure: function wrapMatcher_closure(t0) { + this.x = t0; + }, + escape_closure: function escape_closure() { + }, + Context_Context: function(style) { + var current = style == null ? D.current() : "."; + if (style == null) + style = $.$get$Style_platform(); + return new M.Context(style, current); + }, + _parseUri: function(uri) { + if (type$.Uri._is(uri)) + return uri; + throw H.wrapException(P.ArgumentError$value(uri, "uri", "Value must be a String or a Uri")); + }, + _validateArgList: function(method, args) { + var numArgs, i, numArgs0, message, t1, t2, t3; + for (numArgs = args.length, i = 1; i < numArgs; ++i) { + if (args[i] == null || args[i - 1] != null) + continue; + for (; numArgs >= 1; numArgs = numArgs0) { + numArgs0 = numArgs - 1; + if (args[numArgs0] != null) + break; + } + message = new P.StringBuffer(""); + t1 = method + "("; + message._contents = t1; + t2 = H.SubListIterable$(args, 0, numArgs, H._arrayInstanceType(args)._precomputed1); + t3 = t2.$ti; + t3 = t1 + new H.MappedListIterable(t2, t3._eval$1("String(ListIterable.E)")._check(new M._validateArgList_closure()), t3._eval$1("MappedListIterable<ListIterable.E,String>")).join$1(0, ", "); + message._contents = t3; + message._contents = t3 + ("): part " + (i - 1) + " was null, but part " + i + " was not."); + throw H.wrapException(P.ArgumentError$(message.toString$0(0))); + } + }, + Context: function Context(t0, t1) { + this.style = t0; + this._context$_current = t1; + }, + Context_join_closure: function Context_join_closure() { + }, + Context_joinAll_closure: function Context_joinAll_closure() { + }, + Context_split_closure: function Context_split_closure() { + }, + _validateArgList_closure: function _validateArgList_closure() { + }, + _PathDirection: function _PathDirection(t0) { + this.name = t0; + }, + _PathRelation: function _PathRelation(t0) { + this.name = t0; + } + }, + D = { + _StringEqualsMatcher__writeLeading: function(buff, s, start) { + var t1 = buff._contents; + if (start > 10) { + t1 += "... "; + buff._contents = t1; + buff._contents = t1 + C.JSString_methods.substring$2(s, start - 10, start); + } else + buff._contents = t1 + C.JSString_methods.substring$2(s, 0, start); + }, + _StringEqualsMatcher__writeTrailing: function(buff, s, start) { + var t1 = start + 10, + t2 = buff._contents; + if (t1 > s.length) + buff._contents = t2 + C.JSString_methods.substring$1(s, start); + else { + t1 = t2 + C.JSString_methods.substring$2(s, start, t1); + buff._contents = t1; + buff._contents = t1 + " ..."; + } + }, + _StringEqualsMatcher: function _StringEqualsMatcher(t0) { + this._equals_matcher$_value = t0; + }, + _DeepMatcher: function _DeepMatcher(t0, t1) { + this._expected = t0; + this._limit = t1; + }, + _DeepMatcher__compareSets_closure: function _DeepMatcher__compareSets_closure(t0, t1, t2, t3) { + var _ = this; + _.matcher = t0; + _.expectedElement = t1; + _.location = t2; + _.depth = t3; + }, + PackageRootResolver: function PackageRootResolver(t0) { + this.packageRoot = t0; + }, + SourceLocationMixin: function SourceLocationMixin() { + }, + _MultiChannel$: function(_inner, $T) { + var t1 = type$.int; + t1 = new D._MultiChannel(_inner, B.StreamChannelController$(true, true, $T), P.LinkedHashMap_LinkedHashMap$_empty(t1, $T._eval$1("StreamChannelController<0>")), P.LinkedHashSet_LinkedHashSet(t1), P.LinkedHashSet_LinkedHashSet(t1), $T._eval$1("_MultiChannel<0>")); + t1._MultiChannel$1(_inner, $T); + return t1; + }, + _MultiChannel: function _MultiChannel(t0, t1, t2, t3, t4, t5) { + var _ = this; + _._multi_channel$_inner = t0; + _._innerStreamSubscription = null; + _._mainController = t1; + _._controllers = t2; + _._pendingIds = t3; + _._closedIds = t4; + _._nextId = 1; + _.$ti = t5; + }, + _MultiChannel_closure: function _MultiChannel_closure(t0, t1) { + this.$this = t0; + this.T = t1; + }, + _MultiChannel_closure0: function _MultiChannel_closure0(t0) { + this.$this = t0; + }, + _MultiChannel_closure1: function _MultiChannel_closure1(t0, t1) { + this.$this = t0; + this.T = t1; + }, + _MultiChannel__closure: function _MultiChannel__closure(t0, t1, t2) { + this.$this = t0; + this.id = t1; + this.T = t2; + }, + _MultiChannel_virtualChannel_closure: function _MultiChannel_virtualChannel_closure(t0, t1) { + this._box_0 = t0; + this.$this = t1; + }, + _MultiChannel_virtualChannel_closure0: function _MultiChannel_virtualChannel_closure0(t0, t1) { + this._box_0 = t0; + this.$this = t1; + }, + VirtualChannel: function VirtualChannel(t0, t1, t2, t3, t4) { + var _ = this; + _._multi_channel$_parent = t0; + _.id = t1; + _.stream = t2; + _.sink = t3; + _.$ti = t4; + }, + Message: function Message(t0, t1) { + this.type = t0; + this.text = t1; + }, + MessageType: function MessageType(t0) { + this.name = t0; + }, + current: function() { + var exception, t1, path, lastIndex, uri = null; + try { + uri = P.Uri_base(); + } catch (exception) { + if (type$.Exception._is(H.unwrapException(exception))) { + t1 = $._current; + if (t1 != null) + return t1; + throw exception; + } else + throw exception; + } + if (J.$eq$(uri, $._currentUriBase)) + return $._current; + $._currentUriBase = uri; + if ($.$get$Style_platform() == $.$get$Style_url()) + return $._current = uri.resolve$1(".").toString$0(0); + else { + path = uri.toFilePath$0(); + t1 = path.length; + lastIndex = t1 - 1; + if (lastIndex < 0) + return H.ioore(path, lastIndex); + t1 = path[lastIndex]; + H.assertHelper(t1 === "/" || t1 === "\\"); + return $._current = lastIndex === 0 ? path : C.JSString_methods.substring$2(path, 0, lastIndex); + } + } + }, + Z = { + prettyPrint: function(object, maxItems, maxLineLength) { + return new Z.prettyPrint__prettyPrint(maxItems, maxLineLength).call$4(object, 0, P.LinkedHashSet_LinkedHashSet$_empty(type$.Object), true); + }, + _typeName: function(x) { + if (type$.Type._is(x)) + return "Type"; + if (type$.Uri._is(x)) + return "Uri"; + if (type$.Set_dynamic._is(x)) + return "Set"; + return J.get$runtimeType$(x).toString$0(0); + }, + _escapeString: function(source) { + var t1 = M.escape(H._checkStringNullable(source)); + return H.stringReplaceAllUnchecked(t1, "'", "\\'"); + }, + prettyPrint__prettyPrint: function prettyPrint__prettyPrint(t0, t1) { + this.maxItems = t0; + this.maxLineLength = t1; + }, + prettyPrint__prettyPrint_pp: function prettyPrint__prettyPrint_pp(t0, t1, t2) { + this._box_0 = t0; + this._prettyPrint = t1; + this.indent = t2; + }, + prettyPrint__prettyPrint_closure: function prettyPrint__prettyPrint_closure(t0) { + this.indent = t0; + }, + prettyPrint__prettyPrint_closure0: function prettyPrint__prettyPrint_closure0(t0, t1) { + this.pp = t0; + this.object = t1; + }, + prettyPrint__prettyPrint_closure1: function prettyPrint__prettyPrint_closure1(t0) { + this.indent = t0; + }, + LiveTest: function LiveTest() { + } + }, + A = { + Frame_Frame$parseVM: function(frame) { + return A.Frame__catchFormatException(frame, new A.Frame_Frame$parseVM_closure(frame)); + }, + Frame_Frame$parseV8: function(frame) { + return A.Frame__catchFormatException(frame, new A.Frame_Frame$parseV8_closure(frame)); + }, + Frame_Frame$parseFirefox: function(frame) { + return A.Frame__catchFormatException(frame, new A.Frame_Frame$parseFirefox_closure(frame)); + }, + Frame_Frame$parseFriendly: function(frame) { + return A.Frame__catchFormatException(frame, new A.Frame_Frame$parseFriendly_closure(frame)); + }, + Frame__uriOrPathToUri: function(uriOrPath) { + if (J.getInterceptor$asx(uriOrPath).contains$1(uriOrPath, $.$get$Frame__uriRegExp())) + return P.Uri_parse(uriOrPath); + else if (C.JSString_methods.contains$1(uriOrPath, $.$get$Frame__windowsRegExp())) + return P._Uri__Uri$file(uriOrPath, true); + else if (C.JSString_methods.startsWith$1(uriOrPath, "/")) + return P._Uri__Uri$file(uriOrPath, false); + if (C.JSString_methods.contains$1(uriOrPath, "\\")) + return $.$get$windows().toUri$1(uriOrPath); + return P.Uri_parse(uriOrPath); + }, + Frame__catchFormatException: function(text, body) { + var t1, exception; + try { + t1 = body.call$0(); + return t1; + } catch (exception) { + if (type$.FormatException._is(H.unwrapException(exception))) + return new N.UnparsedFrame(P._Uri__Uri(null, "unparsed", null, null), text); + else + throw exception; + } + }, + Frame: function Frame(t0, t1, t2, t3) { + var _ = this; + _.uri = t0; + _.line = t1; + _.column = t2; + _.member = t3; + }, + Frame_Frame$parseVM_closure: function Frame_Frame$parseVM_closure(t0) { + this.frame = t0; + }, + Frame_Frame$parseV8_closure: function Frame_Frame$parseV8_closure(t0) { + this.frame = t0; + }, + Frame_Frame$parseV8_closure_parseLocation: function Frame_Frame$parseV8_closure_parseLocation(t0) { + this.frame = t0; + }, + Frame_Frame$parseFirefox_closure: function Frame_Frame$parseFirefox_closure(t0) { + this.frame = t0; + }, + Frame_Frame$parseFriendly_closure: function Frame_Frame$parseFriendly_closure(t0) { + this.frame = t0; + }, + AsciiGlyphSet: function AsciiGlyphSet() { + } + }, + N = {UnparsedFrame: function UnparsedFrame(t0, t1) { + this.uri = t0; + this.member = t1; + }, StreamChannelCompleter: function StreamChannelCompleter(t0, t1, t2) { + var _ = this; + _._streamCompleter = t0; + _._sinkCompleter = t1; + _._stream_channel_completer$_channel = null; + _._stream_channel_completer$_set = false; + _.$ti = t2; + }, + postMessageChannel: function() { + var t1, t2, + controller = B.StreamChannelController$(true, true, type$.dynamic); + new W._EventStream(window, "message", false, type$._EventStream_MessageEvent).firstWhere$1(0, new N.postMessageChannel_closure()).then$1$1(new N.postMessageChannel_closure0(controller), type$.Null); + t1 = P.LinkedHashMap_LinkedHashMap$_literal(["href", window.location.href, "ready", true], type$.String, type$.Object); + t1 = P._convertDataTree(t1); + t2 = window.location; + self.window.parent.postMessage(t1, (t2 && C.Location_methods).get$origin(t2)); + return controller._foreign; + }, + postMessageChannel_closure: function postMessageChannel_closure() { + }, + postMessageChannel_closure0: function postMessageChannel_closure0(t0) { + this.controller = t0; + }, + postMessageChannel__closure: function postMessageChannel__closure(t0) { + this.controller = t0; + }, + postMessageChannel__closure0: function postMessageChannel__closure0(t0) { + this.port = t0; + }, + postMessageChannel__closure1: function postMessageChannel__closure1(t0, t1) { + this.port = t0; + this.portSubscription = t1; + }, + OperatingSystem_find: function(identifier) { + return C.JSArray_methods.firstWhere$2$orElse(C.List_opx, new N.OperatingSystem_find_closure(identifier), new N.OperatingSystem_find_closure0()); + }, + OperatingSystem: function OperatingSystem(t0, t1) { + this.name = t0; + this.identifier = t1; + }, + OperatingSystem_find_closure: function OperatingSystem_find_closure(t0) { + this.identifier = t0; + }, + OperatingSystem_find_closure0: function OperatingSystem_find_closure0() { + }, + SuiteChannelManager: function SuiteChannelManager(t0, t1, t2) { + this._incomingConnections = t0; + this._outgoingConnections = t1; + this._names = t2; + } + }, + K = { + GuaranteeChannel$: function(innerStream, innerSink, allowSinkErrors, $T) { + var t2, t1 = {}; + t1.innerStream = innerStream; + t2 = new K.GuaranteeChannel($T._eval$1("GuaranteeChannel<0>")); + t2.GuaranteeChannel$3$allowSinkErrors(innerSink, allowSinkErrors, t1, $T); + return t2; + }, + GuaranteeChannel: function GuaranteeChannel(t0) { + var _ = this; + _._subscription = _._streamController = _._sink = null; + _._disconnected = false; + _.$ti = t0; + }, + GuaranteeChannel_closure: function GuaranteeChannel_closure(t0, t1) { + this._box_0 = t0; + this.$this = t1; + }, + GuaranteeChannel__closure: function GuaranteeChannel__closure(t0) { + this.$this = t0; + }, + _GuaranteeSink: function _GuaranteeSink(t0, t1, t2, t3, t4) { + var _ = this; + _._inner = t0; + _._channel = t1; + _._doneCompleter = t2; + _._closed = _._disconnected = false; + _._addStreamCompleter = _._addStreamSubscription = null; + _._allowErrors = t3; + _.$ti = t4; + }, + _GuaranteeSink__addError_closure: function _GuaranteeSink__addError_closure() { + }, + _GuaranteeSink_addStream_closure: function _GuaranteeSink_addStream_closure(t0) { + this.$this = t0; + }, + UnicodeGlyphSet: function UnicodeGlyphSet() { + }, + ClosedException$: function() { + return new K.ClosedException(); + }, + ClosedException: function ClosedException() { + } + }; + var holders = [C, H, J, P, W, S, O, Y, F, V, E, L, G, T, X, U, R, B, Q, M, D, Z, A, N, K]; + hunkHelpers.setFunctionNamesIfNecessary(holders); + var $ = {}; + H.JS_CONST.prototype = {}; + J.Interceptor.prototype = { + $eq: function(receiver, other) { + return receiver === other; + }, + get$hashCode: function(receiver) { + return H.Primitives_objectHashCode(receiver); + }, + toString$0: function(receiver) { + return "Instance of '" + H.S(H.Primitives_objectTypeName(receiver)) + "'"; + }, + get$runtimeType: function(receiver) { + return H.getRuntimeType(receiver); + } + }; + J.JSBool.prototype = { + toString$0: function(receiver) { + return String(receiver); + }, + get$hashCode: function(receiver) { + return receiver ? 519018 : 218159; + }, + get$runtimeType: function(receiver) { + return C.Type_bool_lhE; + }, + $isbool: 1 + }; + J.JSNull.prototype = { + $eq: function(receiver, other) { + return null == other; + }, + toString$0: function(receiver) { + return "null"; + }, + get$hashCode: function(receiver) { + return 0; + }, + get$runtimeType: function(receiver) { + return C.Type_Null_Yyn; + }, + $isNull: 1 + }; + J.JSObject.prototype = {}; + J.JavaScriptObject.prototype = { + get$hashCode: function(receiver) { + return 0; + }, + get$runtimeType: function(receiver) { + return C.Type_JSObject_8k0; + }, + toString$0: function(receiver) { + return String(receiver); + }, + $isJSObject: 1 + }; + J.PlainJavaScriptObject.prototype = {}; + J.UnknownJavaScriptObject.prototype = {}; + J.JavaScriptFunction.prototype = { + toString$0: function(receiver) { + var dartClosure = receiver[$.$get$DART_CLOSURE_PROPERTY_NAME()]; + if (dartClosure == null) + return this.super$JavaScriptObject$toString(receiver); + return "JavaScript function for " + H.S(J.toString$0$(dartClosure)); + }, + $signature: function() { + return {func: 1, opt: [,,,,,,,,,,,,,,,,]}; + }, + $isFunction: 1 + }; + J.JSArray.prototype = { + add$1: function(receiver, value) { + H._arrayInstanceType(receiver)._precomputed1._check(value); + if (!!receiver.fixed$length) + H.throwExpression(P.UnsupportedError$("add")); + receiver.push(value); + }, + removeAt$1: function(receiver, index) { + var t1; + if (!!receiver.fixed$length) + H.throwExpression(P.UnsupportedError$("removeAt")); + t1 = receiver.length; + if (index >= t1) + throw H.wrapException(P.RangeError$value(index, null)); + return receiver.splice(index, 1)[0]; + }, + insert$2: function(receiver, index, value) { + var t1; + H._arrayInstanceType(receiver)._precomputed1._check(value); + if (!!receiver.fixed$length) + H.throwExpression(P.UnsupportedError$("insert")); + t1 = receiver.length; + if (index > t1) + throw H.wrapException(P.RangeError$value(index, null)); + receiver.splice(index, 0, value); + }, + insertAll$2: function(receiver, index, iterable) { + var t1, insertionLength, end; + H._arrayInstanceType(receiver)._eval$1("Iterable<1>")._check(iterable); + if (!!receiver.fixed$length) + H.throwExpression(P.UnsupportedError$("insertAll")); + t1 = receiver.length; + P.RangeError_checkValueInInterval(index, 0, t1, "index"); + insertionLength = iterable.length; + this.set$length(receiver, t1 + insertionLength); + end = index + insertionLength; + this.setRange$4(receiver, end, receiver.length, receiver, index); + this.setRange$3(receiver, index, end, iterable); + }, + removeLast$0: function(receiver) { + if (!!receiver.fixed$length) + H.throwExpression(P.UnsupportedError$("removeLast")); + if (receiver.length === 0) + throw H.wrapException(H.diagnoseIndexError(receiver, -1)); + return receiver.pop(); + }, + remove$1: function(receiver, element) { + var i; + if (!!receiver.fixed$length) + H.throwExpression(P.UnsupportedError$("remove")); + for (i = 0; i < receiver.length; ++i) + if (J.$eq$(receiver[i], element)) { + receiver.splice(i, 1); + return true; + } + return false; + }, + addAll$1: function(receiver, collection) { + var i, t1, e, i0; + H._arrayInstanceType(receiver)._eval$1("Iterable<1>")._check(collection); + i = receiver.length; + if (!!receiver.fixed$length) + H.throwExpression(P.UnsupportedError$("addAll")); + for (t1 = J.get$iterator$ax(collection); t1.moveNext$0(); i = i0) { + e = t1.get$current(); + i0 = i + 1; + H.assertHelper(i === receiver.length || H.throwExpression(P.ConcurrentModificationError$(receiver))); + receiver.push(e); + } + }, + forEach$1: function(receiver, f) { + var end, i; + H._arrayInstanceType(receiver)._eval$1("~(1)")._check(f); + end = receiver.length; + for (i = 0; i < end; ++i) { + f.call$1(receiver[i]); + if (receiver.length !== end) + throw H.wrapException(P.ConcurrentModificationError$(receiver)); + } + }, + map$1$1: function(receiver, f, $T) { + var t1 = H._arrayInstanceType(receiver); + return new H.MappedListIterable(receiver, t1._bind$1($T)._eval$1("1(2)")._check(f), t1._eval$1("@<1>")._bind$1($T)._eval$1("MappedListIterable<1,2>")); + }, + join$1: function(receiver, separator) { + var i, + list = new Array(receiver.length); + list.fixed$length = Array; + for (i = 0; i < receiver.length; ++i) + this.$indexSet(list, i, H.S(receiver[i])); + return list.join(separator); + }, + join$0: function($receiver) { + return this.join$1($receiver, ""); + }, + fold$1$2: function(receiver, initialValue, combine, $T) { + var $length, value, i; + $T._check(initialValue); + H._arrayInstanceType(receiver)._bind$1($T)._eval$1("1(1,2)")._check(combine); + $length = receiver.length; + for (value = initialValue, i = 0; i < $length; ++i) { + value = combine.call$2(value, receiver[i]); + if (receiver.length !== $length) + throw H.wrapException(P.ConcurrentModificationError$(receiver)); + } + return value; + }, + firstWhere$2$orElse: function(receiver, test, orElse) { + var end, i, element, + t1 = H._arrayInstanceType(receiver); + t1._eval$1("bool(1)")._check(test); + t1._eval$1("1()")._check(orElse); + end = receiver.length; + for (i = 0; i < end; ++i) { + element = receiver[i]; + if (H.boolConversionCheck(test.call$1(element))) + return element; + if (receiver.length !== end) + throw H.wrapException(P.ConcurrentModificationError$(receiver)); + } + if (orElse != null) + return orElse.call$0(); + throw H.wrapException(H.IterableElementError_noElement()); + }, + firstWhere$1: function($receiver, test) { + return this.firstWhere$2$orElse($receiver, test, null); + }, + elementAt$1: function(receiver, index) { + if (index < 0 || index >= receiver.length) + return H.ioore(receiver, index); + return receiver[index]; + }, + sublist$2: function(receiver, start, end) { + if (start < 0 || start > receiver.length) + throw H.wrapException(P.RangeError$range(start, 0, receiver.length, "start", null)); + if (end < start || end > receiver.length) + throw H.wrapException(P.RangeError$range(end, start, receiver.length, "end", null)); + if (start === end) + return H.setRuntimeTypeInfo([], H._arrayInstanceType(receiver)); + return H.setRuntimeTypeInfo(receiver.slice(start, end), H._arrayInstanceType(receiver)); + }, + get$first: function(receiver) { + if (receiver.length > 0) + return receiver[0]; + throw H.wrapException(H.IterableElementError_noElement()); + }, + get$last: function(receiver) { + var t1 = receiver.length; + if (t1 > 0) + return receiver[t1 - 1]; + throw H.wrapException(H.IterableElementError_noElement()); + }, + get$single: function(receiver) { + var t1 = receiver.length; + if (t1 === 1) { + if (0 >= t1) + return H.ioore(receiver, 0); + return receiver[0]; + } + if (t1 === 0) + throw H.wrapException(H.IterableElementError_noElement()); + throw H.wrapException(H.IterableElementError_tooMany()); + }, + setRange$4: function(receiver, start, end, iterable, skipCount) { + var $length, i, + t1 = H._arrayInstanceType(receiver); + t1._eval$1("Iterable<1>")._check(iterable); + if (!!receiver.immutable$list) + H.throwExpression(P.UnsupportedError$("setRange")); + P.RangeError_checkValidRange(start, end, receiver.length); + $length = end - start; + if ($length === 0) + return; + P.RangeError_checkNotNegative(skipCount, "skipCount"); + t1._eval$1("List<1>")._check(iterable); + t1 = J.getInterceptor$asx(iterable); + if (skipCount + $length > t1.get$length(iterable)) + throw H.wrapException(H.IterableElementError_tooFew()); + if (skipCount < start) + for (i = $length - 1; i >= 0; --i) + receiver[start + i] = t1.$index(iterable, skipCount + i); + else + for (i = 0; i < $length; ++i) + receiver[start + i] = t1.$index(iterable, skipCount + i); + }, + setRange$3: function($receiver, start, end, iterable) { + return this.setRange$4($receiver, start, end, iterable, 0); + }, + fillRange$3: function(receiver, start, end, fillValue) { + var i; + H._arrayInstanceType(receiver)._precomputed1._check(fillValue); + if (!!receiver.immutable$list) + H.throwExpression(P.UnsupportedError$("fill range")); + P.RangeError_checkValidRange(start, end, receiver.length); + for (i = start; i < end; ++i) + receiver[i] = fillValue; + }, + replaceRange$3: function(receiver, start, end, replacement) { + var t1, removeLength, insertEnd, delta, newLength, _this = this; + H._arrayInstanceType(receiver)._eval$1("Iterable<1>")._check(replacement); + if (!!receiver.fixed$length) + H.throwExpression(P.UnsupportedError$("replaceRange")); + t1 = receiver.length; + P.RangeError_checkValidRange(start, end, t1); + removeLength = end - start; + insertEnd = start + 1; + if (removeLength >= 1) { + delta = removeLength - 1; + newLength = t1 - delta; + _this.setRange$3(receiver, start, insertEnd, replacement); + if (delta !== 0) { + _this.setRange$4(receiver, insertEnd, newLength, receiver, end); + _this.set$length(receiver, newLength); + } + } else { + newLength = t1 + (1 - removeLength); + _this.set$length(receiver, newLength); + _this.setRange$4(receiver, insertEnd, newLength, receiver, end); + _this.setRange$3(receiver, start, insertEnd, replacement); + } + }, + contains$1: function(receiver, other) { + var i; + for (i = 0; i < receiver.length; ++i) + if (J.$eq$(receiver[i], other)) + return true; + return false; + }, + get$isEmpty: function(receiver) { + return receiver.length === 0; + }, + toString$0: function(receiver) { + return P.IterableBase_iterableToFullString(receiver, "[", "]"); + }, + toSet$0: function(receiver) { + return P.LinkedHashSet_LinkedHashSet$from(receiver, H._arrayInstanceType(receiver)._precomputed1); + }, + get$iterator: function(receiver) { + return new J.ArrayIterator(receiver, receiver.length, H._arrayInstanceType(receiver)._eval$1("ArrayIterator<1>")); + }, + get$hashCode: function(receiver) { + return H.Primitives_objectHashCode(receiver); + }, + get$length: function(receiver) { + return receiver.length; + }, + set$length: function(receiver, newLength) { + var _s9_ = "newLength"; + if (!!receiver.fixed$length) + H.throwExpression(P.UnsupportedError$("set length")); + if (!H._isInt(newLength)) + throw H.wrapException(P.ArgumentError$value(newLength, _s9_, null)); + if (newLength < 0) + throw H.wrapException(P.RangeError$range(newLength, 0, null, _s9_, null)); + receiver.length = newLength; + }, + $index: function(receiver, index) { + H._checkIntNullable(index); + if (!H._isInt(index)) + throw H.wrapException(H.diagnoseIndexError(receiver, index)); + if (index >= receiver.length || index < 0) + throw H.wrapException(H.diagnoseIndexError(receiver, index)); + return receiver[index]; + }, + $indexSet: function(receiver, index, value) { + H._checkIntNullable(index); + H._arrayInstanceType(receiver)._precomputed1._check(value); + if (!!receiver.immutable$list) + H.throwExpression(P.UnsupportedError$("indexed set")); + if (!H._isInt(index)) + throw H.wrapException(H.diagnoseIndexError(receiver, index)); + if (index >= receiver.length || index < 0) + throw H.wrapException(H.diagnoseIndexError(receiver, index)); + receiver[index] = value; + }, + $isEfficientLengthIterable: 1, + $isIterable: 1, + $isList: 1 + }; + J.JSUnmodifiableArray.prototype = {}; + J.ArrayIterator.prototype = { + get$current: function() { + return this._current; + }, + moveNext$0: function() { + var t2, _this = this, + t1 = _this._iterable, + $length = t1.length; + if (_this._length !== $length) + throw H.wrapException(H.throwConcurrentModificationError(t1)); + t2 = _this._index; + if (t2 >= $length) { + _this.set$_current(null); + return false; + } + _this.set$_current(t1[t2]); + ++_this._index; + return true; + }, + set$_current: function(_current) { + this._current = this.$ti._precomputed1._check(_current); + }, + $isIterator: 1 + }; + J.JSNumber.prototype = { + floor$0: function(receiver) { + var truncated, d; + if (receiver >= 0) { + if (receiver <= 2147483647) + return receiver | 0; + } else if (receiver >= -2147483648) { + truncated = receiver | 0; + return receiver === truncated ? truncated : truncated - 1; + } + d = Math.floor(receiver); + if (isFinite(d)) + return d; + throw H.wrapException(P.UnsupportedError$("" + receiver + ".floor()")); + }, + round$0: function(receiver) { + if (receiver > 0) { + if (receiver !== 1 / 0) + return Math.round(receiver); + } else if (receiver > -1 / 0) + return 0 - Math.round(0 - receiver); + throw H.wrapException(P.UnsupportedError$("" + receiver + ".round()")); + }, + toRadixString$1: function(receiver, radix) { + var result, match, t1, exponent; + if (radix < 2 || radix > 36) + throw H.wrapException(P.RangeError$range(radix, 2, 36, "radix", null)); + result = receiver.toString(radix); + if (C.JSString_methods.codeUnitAt$1(result, result.length - 1) !== 41) + return result; + match = /^([\da-z]+)(?:\.([\da-z]+))?\(e\+(\d+)\)$/.exec(result); + if (match == null) + H.throwExpression(P.UnsupportedError$("Unexpected toString result: " + result)); + t1 = match.length; + if (1 >= t1) + return H.ioore(match, 1); + result = match[1]; + if (3 >= t1) + return H.ioore(match, 3); + exponent = +match[3]; + t1 = match[2]; + if (t1 != null) { + result += t1; + exponent -= t1.length; + } + return result + C.JSString_methods.$mul("0", exponent); + }, + toString$0: function(receiver) { + if (receiver === 0 && 1 / receiver < 0) + return "-0.0"; + else + return "" + receiver; + }, + get$hashCode: function(receiver) { + var absolute, floorLog2, factor, scaled, + intValue = receiver | 0; + if (receiver === intValue) + return 536870911 & intValue; + absolute = Math.abs(receiver); + floorLog2 = Math.log(absolute) / 0.6931471805599453 | 0; + factor = Math.pow(2, floorLog2); + scaled = absolute < 1 ? absolute / factor : factor / absolute; + return 536870911 & ((scaled * 9007199254740992 | 0) + (scaled * 3542243181176521 | 0)) * 599197 + floorLog2 * 1259; + }, + $mod: function(receiver, other) { + var result = receiver % other; + if (result === 0) + return 0; + if (result > 0) + return result; + if (other < 0) + return result - other; + else + return result + other; + }, + $tdiv: function(receiver, other) { + if ((receiver | 0) === receiver) + if (other >= 1 || other < -1) + return receiver / other | 0; + return this._tdivSlow$1(receiver, other); + }, + _tdivFast$1: function(receiver, other) { + return (receiver | 0) === receiver ? receiver / other | 0 : this._tdivSlow$1(receiver, other); + }, + _tdivSlow$1: function(receiver, other) { + var quotient = receiver / other; + if (quotient >= -2147483648 && quotient <= 2147483647) + return quotient | 0; + if (quotient > 0) { + if (quotient !== 1 / 0) + return Math.floor(quotient); + } else if (quotient > -1 / 0) + return Math.ceil(quotient); + throw H.wrapException(P.UnsupportedError$("Result of truncating division is " + H.S(quotient) + ": " + H.S(receiver) + " ~/ " + other)); + }, + _shlPositive$1: function(receiver, other) { + return other > 31 ? 0 : receiver << other >>> 0; + }, + _shrOtherPositive$1: function(receiver, other) { + var t1; + if (receiver > 0) + t1 = this._shrBothPositive$1(receiver, other); + else { + t1 = other > 31 ? 31 : other; + t1 = receiver >> t1 >>> 0; + } + return t1; + }, + _shrReceiverPositive$1: function(receiver, other) { + if (other < 0) + throw H.wrapException(H.argumentErrorValue(other)); + return this._shrBothPositive$1(receiver, other); + }, + _shrBothPositive$1: function(receiver, other) { + return other > 31 ? 0 : receiver >>> other; + }, + get$runtimeType: function(receiver) { + return C.Type_num_cv7; + }, + $isdouble: 1, + $isnum: 1 + }; + J.JSInt.prototype = { + get$runtimeType: function(receiver) { + return C.Type_int_tHn; + }, + $isint: 1 + }; + J.JSDouble.prototype = { + get$runtimeType: function(receiver) { + return C.Type_double_K1J; + } + }; + J.JSString.prototype = { + codeUnitAt$1: function(receiver, index) { + if (index < 0) + throw H.wrapException(H.diagnoseIndexError(receiver, index)); + if (index >= receiver.length) + H.throwExpression(H.diagnoseIndexError(receiver, index)); + return receiver.charCodeAt(index); + }, + _codeUnitAt$1: function(receiver, index) { + if (index >= receiver.length) + throw H.wrapException(H.diagnoseIndexError(receiver, index)); + return receiver.charCodeAt(index); + }, + allMatches$2: function(receiver, string, start) { + var t1; + if (typeof string != "string") + H.throwExpression(H.argumentErrorValue(string)); + t1 = string.length; + if (start > t1) + throw H.wrapException(P.RangeError$range(start, 0, t1, null, null)); + return new H._StringAllMatchesIterable(string, receiver, start); + }, + allMatches$1: function($receiver, string) { + return this.allMatches$2($receiver, string, 0); + }, + matchAsPrefix$2: function(receiver, string, start) { + var t1, t2, i, _null = null; + if (start < 0 || start > string.length) + throw H.wrapException(P.RangeError$range(start, 0, string.length, _null, _null)); + t1 = receiver.length; + if (start + t1 > string.length) + return _null; + for (t2 = J.getInterceptor$s(string), i = 0; i < t1; ++i) + if (t2.codeUnitAt$1(string, start + i) !== this._codeUnitAt$1(receiver, i)) + return _null; + return new H.StringMatch(start, receiver); + }, + $add: function(receiver, other) { + if (typeof other != "string") + throw H.wrapException(P.ArgumentError$value(other, null, null)); + return receiver + other; + }, + endsWith$1: function(receiver, other) { + var otherLength = other.length, + t1 = receiver.length; + if (otherLength > t1) + return false; + return other === this.substring$1(receiver, t1 - otherLength); + }, + splitMapJoin$2$onMatch: function(receiver, from, onMatch) { + return H.stringReplaceAllFuncUnchecked(receiver, from, type$.String_Function_Match._check(onMatch), type$.String_Function_String._check(null)); + }, + replaceFirst$2: function(receiver, from, to) { + P.RangeError_checkValueInInterval(0, 0, receiver.length, "startIndex"); + return H.stringReplaceFirstUnchecked(receiver, from, to, 0); + }, + replaceRange$3: function(receiver, start, end, replacement) { + end = P.RangeError_checkValidRange(start, end, receiver.length); + return H.stringReplaceRangeUnchecked(receiver, start, end, replacement); + }, + startsWith$2: function(receiver, pattern, index) { + var endIndex; + type$.Pattern._check(pattern); + if (index < 0 || index > receiver.length) + throw H.wrapException(P.RangeError$range(index, 0, receiver.length, null, null)); + if (typeof pattern == "string") { + endIndex = index + pattern.length; + if (endIndex > receiver.length) + return false; + return pattern === receiver.substring(index, endIndex); + } + return J.matchAsPrefix$2$s(pattern, receiver, index) != null; + }, + startsWith$1: function($receiver, pattern) { + return this.startsWith$2($receiver, pattern, 0); + }, + substring$2: function(receiver, startIndex, endIndex) { + if (endIndex == null) + endIndex = receiver.length; + if (startIndex < 0) + throw H.wrapException(P.RangeError$value(startIndex, null)); + if (startIndex > endIndex) + throw H.wrapException(P.RangeError$value(startIndex, null)); + if (endIndex > receiver.length) + throw H.wrapException(P.RangeError$value(endIndex, null)); + return receiver.substring(startIndex, endIndex); + }, + substring$1: function($receiver, startIndex) { + return this.substring$2($receiver, startIndex, null); + }, + trim$0: function(receiver) { + var startIndex, t1, endIndex0, + result = receiver.trim(), + endIndex = result.length; + if (endIndex === 0) + return result; + if (this._codeUnitAt$1(result, 0) === 133) { + startIndex = J.JSString__skipLeadingWhitespace(result, 1); + if (startIndex === endIndex) + return ""; + } else + startIndex = 0; + t1 = endIndex - 1; + endIndex0 = this.codeUnitAt$1(result, t1) === 133 ? J.JSString__skipTrailingWhitespace(result, t1) : endIndex; + if (startIndex === 0 && endIndex0 === endIndex) + return result; + return result.substring(startIndex, endIndex0); + }, + $mul: function(receiver, times) { + var s, result; + if (0 >= times) + return ""; + if (times === 1 || receiver.length === 0) + return receiver; + if (times !== times >>> 0) + throw H.wrapException(C.C_OutOfMemoryError); + for (s = receiver, result = ""; true;) { + if ((times & 1) === 1) + result = s + result; + times = times >>> 1; + if (times === 0) + break; + s += s; + } + return result; + }, + padLeft$2: function(receiver, width, padding) { + var delta = width - receiver.length; + if (delta <= 0) + return receiver; + return this.$mul(padding, delta) + receiver; + }, + padRight$1: function(receiver, width) { + var delta; + if (typeof width !== "number") + return width.$sub(); + delta = width - receiver.length; + if (delta <= 0) + return receiver; + return receiver + this.$mul(" ", delta); + }, + indexOf$2: function(receiver, pattern, start) { + var t1; + if (start < 0 || start > receiver.length) + throw H.wrapException(P.RangeError$range(start, 0, receiver.length, null, null)); + t1 = receiver.indexOf(pattern, start); + return t1; + }, + indexOf$1: function($receiver, pattern) { + return this.indexOf$2($receiver, pattern, 0); + }, + lastIndexOf$2: function(receiver, pattern, start) { + var t1, t2; + if (start == null) + start = receiver.length; + else if (start < 0 || start > receiver.length) + throw H.wrapException(P.RangeError$range(start, 0, receiver.length, null, null)); + t1 = pattern.length; + t2 = receiver.length; + if (start + t1 > t2) + start = t2 - t1; + return receiver.lastIndexOf(pattern, start); + }, + lastIndexOf$1: function($receiver, pattern) { + return this.lastIndexOf$2($receiver, pattern, null); + }, + contains$1: function(receiver, other) { + if (other == null) + H.throwExpression(H.argumentErrorValue(other)); + return H.stringContainsUnchecked(receiver, other, 0); + }, + toString$0: function(receiver) { + return receiver; + }, + get$hashCode: function(receiver) { + var t1, hash, i; + for (t1 = receiver.length, hash = 0, i = 0; i < t1; ++i) { + hash = 536870911 & hash + receiver.charCodeAt(i); + hash = 536870911 & hash + ((524287 & hash) << 10); + hash ^= hash >> 6; + } + hash = 536870911 & hash + ((67108863 & hash) << 3); + hash ^= hash >> 11; + return 536870911 & hash + ((16383 & hash) << 15); + }, + get$runtimeType: function(receiver) { + return C.Type_String_k8F; + }, + get$length: function(receiver) { + return receiver.length; + }, + $index: function(receiver, index) { + H._checkIntNullable(index); + if (index >= receiver.length || index < 0) + throw H.wrapException(H.diagnoseIndexError(receiver, index)); + return receiver[index]; + }, + $isPattern: 1, + $isString: 1 + }; + H._CastIterableBase.prototype = { + get$iterator: function(_) { + var t1 = this._source, + t2 = H._instanceType(this); + return new H.CastIterator(t1.get$iterator(t1), t2._eval$1("@<1>")._bind$1(t2._rest[1])._eval$1("CastIterator<1,2>")); + }, + get$length: function(_) { + var t1 = this._source; + return t1.get$length(t1); + }, + get$isEmpty: function(_) { + var t1 = this._source; + return t1.get$isEmpty(t1); + }, + get$first: function(_) { + var t1 = this._source; + return H._instanceType(this)._rest[1]._as(t1.get$first(t1)); + }, + get$last: function(_) { + var t1 = this._source; + return H._instanceType(this)._rest[1]._as(t1.get$last(t1)); + }, + contains$1: function(_, other) { + return this._source.contains$1(0, other); + }, + toString$0: function(_) { + return this._source.toString$0(0); + } + }; + H.CastIterator.prototype = { + moveNext$0: function() { + return this._source.moveNext$0(); + }, + get$current: function() { + return this.$ti._rest[1]._as(this._source.get$current()); + }, + $isIterator: 1 + }; + H.CastIterable.prototype = {}; + H._EfficientLengthCastIterable.prototype = {$isEfficientLengthIterable: 1}; + H.CastMap.prototype = { + cast$2$0: function(_, RK, RV) { + var t1 = this.$ti; + return new H.CastMap(this._source, t1._eval$1("@<1>")._bind$1(t1._rest[1])._bind$1(RK)._bind$1(RV)._eval$1("CastMap<1,2,3,4>")); + }, + containsKey$1: function(key) { + return this._source.containsKey$1(key); + }, + $index: function(_, key) { + return this.$ti._rest[3]._as(this._source.$index(0, key)); + }, + remove$1: function(_, key) { + return this.$ti._rest[3]._as(this._source.remove$1(0, key)); + }, + forEach$1: function(_, f) { + this._source.forEach$1(0, new H.CastMap_forEach_closure(this, this.$ti._eval$1("~(3,4)")._check(f))); + }, + get$keys: function() { + var t1 = this.$ti; + return H.CastIterable_CastIterable(this._source.get$keys(), t1._precomputed1, t1._rest[2]); + }, + get$length: function(_) { + var t1 = this._source; + return t1.get$length(t1); + }, + get$isEmpty: function(_) { + var t1 = this._source; + return t1.get$isEmpty(t1); + } + }; + H.CastMap_forEach_closure.prototype = { + call$2: function(key, value) { + var t1 = this.$this.$ti; + t1._precomputed1._check(key); + t1._rest[1]._check(value); + this.f.call$2(t1._rest[2]._as(key), t1._rest[3]._as(value)); + }, + $signature: function() { + return this.$this.$ti._eval$1("Null(1,2)"); + } + }; + H.CodeUnits.prototype = { + get$length: function(_) { + return this._string.length; + }, + $index: function(_, i) { + return C.JSString_methods.codeUnitAt$1(this._string, H._checkIntNullable(i)); + } + }; + H.EfficientLengthIterable.prototype = {}; + H.ListIterable.prototype = { + get$iterator: function(_) { + var _this = this; + return new H.ListIterator(_this, _this.get$length(_this), H._instanceType(_this)._eval$1("ListIterator<ListIterable.E>")); + }, + get$isEmpty: function(_) { + return this.get$length(this) === 0; + }, + get$first: function(_) { + if (this.get$length(this) === 0) + throw H.wrapException(H.IterableElementError_noElement()); + return this.elementAt$1(0, 0); + }, + get$last: function(_) { + var _this = this; + if (_this.get$length(_this) === 0) + throw H.wrapException(H.IterableElementError_noElement()); + return _this.elementAt$1(0, _this.get$length(_this) - 1); + }, + contains$1: function(_, element) { + var i, _this = this, + $length = _this.get$length(_this); + for (i = 0; i < $length; ++i) { + if (J.$eq$(_this.elementAt$1(0, i), element)) + return true; + if ($length !== _this.get$length(_this)) + throw H.wrapException(P.ConcurrentModificationError$(_this)); + } + return false; + }, + join$1: function(_, separator) { + var first, t1, i, _this = this, + $length = _this.get$length(_this); + if (separator.length !== 0) { + if ($length === 0) + return ""; + first = H.S(_this.elementAt$1(0, 0)); + if ($length !== _this.get$length(_this)) + throw H.wrapException(P.ConcurrentModificationError$(_this)); + for (t1 = first, i = 1; i < $length; ++i) { + t1 = t1 + separator + H.S(_this.elementAt$1(0, i)); + if ($length !== _this.get$length(_this)) + throw H.wrapException(P.ConcurrentModificationError$(_this)); + } + return t1.charCodeAt(0) == 0 ? t1 : t1; + } else { + for (i = 0, t1 = ""; i < $length; ++i) { + t1 += H.S(_this.elementAt$1(0, i)); + if ($length !== _this.get$length(_this)) + throw H.wrapException(P.ConcurrentModificationError$(_this)); + } + return t1.charCodeAt(0) == 0 ? t1 : t1; + } + }, + join$0: function($receiver) { + return this.join$1($receiver, ""); + }, + map$1$1: function(_, f, $T) { + var t1 = H._instanceType(this); + return new H.MappedListIterable(this, t1._bind$1($T)._eval$1("1(ListIterable.E)")._check(f), t1._eval$1("@<ListIterable.E>")._bind$1($T)._eval$1("MappedListIterable<1,2>")); + }, + fold$1$2: function(_, initialValue, combine, $T) { + var $length, value, i, _this = this; + $T._check(initialValue); + H._instanceType(_this)._bind$1($T)._eval$1("1(1,ListIterable.E)")._check(combine); + $length = _this.get$length(_this); + for (value = initialValue, i = 0; i < $length; ++i) { + value = combine.call$2(value, _this.elementAt$1(0, i)); + if ($length !== _this.get$length(_this)) + throw H.wrapException(P.ConcurrentModificationError$(_this)); + } + return value; + }, + toList$1$growable: function(_, growable) { + var i, _this = this, + result = H.setRuntimeTypeInfo([], H._instanceType(_this)._eval$1("JSArray<ListIterable.E>")); + C.JSArray_methods.set$length(result, _this.get$length(_this)); + for (i = 0; i < _this.get$length(_this); ++i) + C.JSArray_methods.$indexSet(result, i, _this.elementAt$1(0, i)); + return result; + }, + toList$0: function($receiver) { + return this.toList$1$growable($receiver, true); + }, + toSet$0: function(_) { + var i, _this = this, + result = P.LinkedHashSet_LinkedHashSet(H._instanceType(_this)._eval$1("ListIterable.E")); + for (i = 0; i < _this.get$length(_this); ++i) + result.add$1(0, _this.elementAt$1(0, i)); + return result; + } + }; + H.SubListIterable.prototype = { + get$_endIndex: function() { + var $length = J.get$length$asx(this.__internal$_iterable), + t1 = this._endOrLength; + if (t1 == null || t1 > $length) + return $length; + return t1; + }, + get$_startIndex: function() { + var $length = J.get$length$asx(this.__internal$_iterable), + t1 = this.__internal$_start; + if (t1 > $length) + return $length; + return t1; + }, + get$length: function(_) { + var t2, + $length = J.get$length$asx(this.__internal$_iterable), + t1 = this.__internal$_start; + if (t1 >= $length) + return 0; + t2 = this._endOrLength; + if (t2 == null || t2 >= $length) + return $length - t1; + if (typeof t2 !== "number") + return t2.$sub(); + return t2 - t1; + }, + elementAt$1: function(_, index) { + var t1, _this = this, + realIndex = _this.get$_startIndex() + index; + if (index >= 0) { + t1 = _this.get$_endIndex(); + if (typeof t1 !== "number") + return H.iae(t1); + t1 = realIndex >= t1; + } else + t1 = true; + if (t1) + throw H.wrapException(P.IndexError$(index, _this, "index", null, null)); + return J.elementAt$1$ax(_this.__internal$_iterable, realIndex); + }, + take$1: function(_, count) { + var t1, t2, newEnd, _this = this; + P.RangeError_checkNotNegative(count, "count"); + t1 = _this._endOrLength; + t2 = _this.__internal$_start; + newEnd = t2 + count; + if (t1 == null) + return H.SubListIterable$(_this.__internal$_iterable, t2, newEnd, _this.$ti._precomputed1); + else { + if (t1 < newEnd) + return _this; + return H.SubListIterable$(_this.__internal$_iterable, t2, newEnd, _this.$ti._precomputed1); + } + } + }; + H.ListIterator.prototype = { + get$current: function() { + return this.__internal$_current; + }, + moveNext$0: function() { + var t3, _this = this, + t1 = _this.__internal$_iterable, + t2 = J.getInterceptor$asx(t1), + $length = t2.get$length(t1); + if (_this.__internal$_length !== $length) + throw H.wrapException(P.ConcurrentModificationError$(t1)); + t3 = _this.__internal$_index; + if (t3 >= $length) { + _this.set$__internal$_current(null); + return false; + } + _this.set$__internal$_current(t2.elementAt$1(t1, t3)); + ++_this.__internal$_index; + return true; + }, + set$__internal$_current: function(_current) { + this.__internal$_current = this.$ti._precomputed1._check(_current); + }, + $isIterator: 1 + }; + H.MappedIterable.prototype = { + get$iterator: function(_) { + var t1 = H._instanceType(this); + return new H.MappedIterator(J.get$iterator$ax(this.__internal$_iterable), this._f, t1._eval$1("@<1>")._bind$1(t1._rest[1])._eval$1("MappedIterator<1,2>")); + }, + get$length: function(_) { + return J.get$length$asx(this.__internal$_iterable); + }, + get$isEmpty: function(_) { + return J.get$isEmpty$asx(this.__internal$_iterable); + }, + get$first: function(_) { + return this._f.call$1(J.get$first$ax(this.__internal$_iterable)); + }, + get$last: function(_) { + return this._f.call$1(J.get$last$ax(this.__internal$_iterable)); + } + }; + H.EfficientLengthMappedIterable.prototype = {$isEfficientLengthIterable: 1}; + H.MappedIterator.prototype = { + moveNext$0: function() { + var _this = this, + t1 = _this._iterator; + if (t1.moveNext$0()) { + _this.set$__internal$_current(_this._f.call$1(t1.get$current())); + return true; + } + _this.set$__internal$_current(null); + return false; + }, + get$current: function() { + return this.__internal$_current; + }, + set$__internal$_current: function(_current) { + this.__internal$_current = this.$ti._rest[1]._check(_current); + } + }; + H.MappedListIterable.prototype = { + get$length: function(_) { + return J.get$length$asx(this._source); + }, + elementAt$1: function(_, index) { + return this._f.call$1(J.elementAt$1$ax(this._source, index)); + } + }; + H.WhereIterable.prototype = { + get$iterator: function(_) { + return new H.WhereIterator(J.get$iterator$ax(this.__internal$_iterable), this._f, this.$ti._eval$1("WhereIterator<1>")); + }, + map$1$1: function(_, f, $T) { + var t1 = this.$ti; + return new H.MappedIterable(this, t1._bind$1($T)._eval$1("1(2)")._check(f), t1._eval$1("@<1>")._bind$1($T)._eval$1("MappedIterable<1,2>")); + } + }; + H.WhereIterator.prototype = { + moveNext$0: function() { + var t1, t2; + for (t1 = this._iterator, t2 = this._f; t1.moveNext$0();) + if (H.boolConversionCheck(t2.call$1(t1.get$current()))) + return true; + return false; + }, + get$current: function() { + return this._iterator.get$current(); + } + }; + H.ExpandIterable.prototype = { + get$iterator: function(_) { + var t1 = this.$ti; + return new H.ExpandIterator(J.get$iterator$ax(this.__internal$_iterable), this._f, C.C_EmptyIterator, t1._eval$1("@<1>")._bind$1(t1._rest[1])._eval$1("ExpandIterator<1,2>")); + } + }; + H.ExpandIterator.prototype = { + get$current: function() { + return this.__internal$_current; + }, + moveNext$0: function() { + var t1, t2, _this = this; + if (_this._currentExpansion == null) + return false; + for (t1 = _this._iterator, t2 = _this._f; !_this._currentExpansion.moveNext$0();) { + _this.set$__internal$_current(null); + if (t1.moveNext$0()) { + _this.set$_currentExpansion(null); + _this.set$_currentExpansion(J.get$iterator$ax(t2.call$1(t1.get$current()))); + } else + return false; + } + _this.set$__internal$_current(_this._currentExpansion.get$current()); + return true; + }, + set$_currentExpansion: function(_currentExpansion) { + this._currentExpansion = this.$ti._eval$1("Iterator<2>")._check(_currentExpansion); + }, + set$__internal$_current: function(_current) { + this.__internal$_current = this.$ti._rest[1]._check(_current); + }, + $isIterator: 1 + }; + H.SkipWhileIterable.prototype = { + get$iterator: function(_) { + return new H.SkipWhileIterator(J.get$iterator$ax(this.__internal$_iterable), this._f, this.$ti._eval$1("SkipWhileIterator<1>")); + } + }; + H.SkipWhileIterator.prototype = { + moveNext$0: function() { + var t1, t2, _this = this; + if (!_this._hasSkipped) { + _this._hasSkipped = true; + for (t1 = _this._iterator, t2 = _this._f; t1.moveNext$0();) + if (!H.boolConversionCheck(t2.call$1(t1.get$current()))) + return true; + } + return _this._iterator.moveNext$0(); + }, + get$current: function() { + return this._iterator.get$current(); + } + }; + H.EmptyIterator.prototype = { + moveNext$0: function() { + return false; + }, + get$current: function() { + return null; + }, + $isIterator: 1 + }; + H.FixedLengthListMixin.prototype = { + set$length: function(receiver, newLength) { + throw H.wrapException(P.UnsupportedError$("Cannot change the length of a fixed-length list")); + } + }; + H.UnmodifiableListMixin.prototype = { + $indexSet: function(_, index, value) { + H._checkIntNullable(index); + H._instanceType(this)._eval$1("UnmodifiableListMixin.E")._check(value); + throw H.wrapException(P.UnsupportedError$("Cannot modify an unmodifiable list")); + }, + set$length: function(_, newLength) { + throw H.wrapException(P.UnsupportedError$("Cannot change the length of an unmodifiable list")); + } + }; + H.UnmodifiableListBase.prototype = {}; + H.ReversedListIterable.prototype = { + get$length: function(_) { + return J.get$length$asx(this._source); + }, + elementAt$1: function(_, index) { + var t1 = this._source, + t2 = J.getInterceptor$asx(t1); + return t2.elementAt$1(t1, t2.get$length(t1) - 1 - index); + } + }; + H.Symbol.prototype = { + get$hashCode: function(_) { + var hash = this._hashCode; + if (hash != null) + return hash; + hash = 536870911 & 664597 * J.get$hashCode$(this.__internal$_name); + this._hashCode = hash; + return hash; + }, + toString$0: function(_) { + return 'Symbol("' + H.S(this.__internal$_name) + '")'; + }, + $eq: function(_, other) { + if (other == null) + return false; + return other instanceof H.Symbol && this.__internal$_name == other.__internal$_name; + } + }; + H.ConstantMap.prototype = { + cast$2$0: function(_, RK, RV) { + var t1 = H._instanceType(this); + return P.Map_castFrom(this, t1._precomputed1, t1._rest[1], RK, RV); + }, + get$isEmpty: function(_) { + return this.get$length(this) === 0; + }, + toString$0: function(_) { + return P.MapBase_mapToString(this); + }, + remove$1: function(_, key) { + return H.ConstantMap__throwUnmodifiable(); + }, + map$2$1: function(_, transform, K2, V2) { + var result = P.LinkedHashMap_LinkedHashMap$_empty(K2, V2); + this.forEach$1(0, new H.ConstantMap_map_closure(this, H._instanceType(this)._bind$1(K2)._bind$1(V2)._eval$1("MapEntry<1,2>(3,4)")._check(transform), result)); + return result; + }, + $isMap: 1 + }; + H.ConstantMap_map_closure.prototype = { + call$2: function(key, value) { + var t1 = H._instanceType(this.$this), + entry = this.transform.call$2(t1._precomputed1._check(key), t1._rest[1]._check(value)); + this.result.$indexSet(0, entry.key, entry.value); + }, + $signature: function() { + return H._instanceType(this.$this)._eval$1("Null(1,2)"); + } + }; + H.ConstantStringMap.prototype = { + get$length: function(_) { + return this.__js_helper$_length; + }, + containsKey$1: function(key) { + if (typeof key != "string") + return false; + if ("__proto__" === key) + return false; + return this._jsObject.hasOwnProperty(key); + }, + $index: function(_, key) { + if (!this.containsKey$1(key)) + return null; + return this._fetch$1(key); + }, + _fetch$1: function(key) { + return this._jsObject[H._checkStringNullable(key)]; + }, + forEach$1: function(_, f) { + var keys, t2, i, key, + t1 = H._instanceType(this); + t1._eval$1("~(1,2)")._check(f); + keys = this.__js_helper$_keys; + for (t2 = keys.length, t1 = t1._rest[1], i = 0; i < t2; ++i) { + key = keys[i]; + f.call$2(key, t1._check(this._fetch$1(key))); + } + }, + get$keys: function() { + return new H._ConstantMapKeyIterable(this, H._instanceType(this)._eval$1("_ConstantMapKeyIterable<1>")); + } + }; + H._ConstantMapKeyIterable.prototype = { + get$iterator: function(_) { + var t1 = this.__js_helper$_map.__js_helper$_keys; + return new J.ArrayIterator(t1, t1.length, H._arrayInstanceType(t1)._eval$1("ArrayIterator<1>")); + }, + get$length: function(_) { + return this.__js_helper$_map.__js_helper$_keys.length; + } + }; + H.Instantiation.prototype = { + Instantiation$1: function(_genericClosure) { + if (false) + H.instantiatedGenericFunctionType(0, 0); + }, + toString$0: function(_) { + var types = "<" + C.JSArray_methods.join$1([H.createRuntimeType(this.$ti._precomputed1)], ", ") + ">"; + return H.S(this._genericClosure) + " with " + types; + } + }; + H.Instantiation1.prototype = { + call$2: function(a0, a1) { + return this._genericClosure.call$1$2(a0, a1, this.$ti._rest[0]); + }, + call$4: function(a0, a1, a2, a3) { + return this._genericClosure.call$1$4(a0, a1, a2, a3, this.$ti._rest[0]); + }, + $signature: function() { + return H.instantiatedGenericFunctionType(H.closureFunctionType(this._genericClosure), this.$ti); + } + }; + H.Primitives_initTicker_closure.prototype = { + call$0: function() { + return C.JSNumber_methods.floor$0(1000 * this.performance.now()); + }, + $signature: 36 + }; + H.TypeErrorDecoder.prototype = { + matchTypeError$1: function(message) { + var result, t1, _this = this, + match = new RegExp(_this._pattern).exec(message); + if (match == null) + return null; + result = Object.create(null); + t1 = _this._arguments; + if (t1 !== -1) + result.arguments = match[t1 + 1]; + t1 = _this._argumentsExpr; + if (t1 !== -1) + result.argumentsExpr = match[t1 + 1]; + t1 = _this._expr; + if (t1 !== -1) + result.expr = match[t1 + 1]; + t1 = _this._method; + if (t1 !== -1) + result.method = match[t1 + 1]; + t1 = _this._receiver; + if (t1 !== -1) + result.receiver = match[t1 + 1]; + return result; + } + }; + H.NullError.prototype = { + toString$0: function(_) { + var t1 = this._method; + if (t1 == null) + return "NoSuchMethodError: " + H.S(this.__js_helper$_message); + return "NoSuchMethodError: method not found: '" + t1 + "' on null"; + }, + $isNoSuchMethodError: 1 + }; + H.JsNoSuchMethodError.prototype = { + toString$0: function(_) { + var t2, _this = this, + _s38_ = "NoSuchMethodError: method not found: '", + t1 = _this._method; + if (t1 == null) + return "NoSuchMethodError: " + H.S(_this.__js_helper$_message); + t2 = _this._receiver; + if (t2 == null) + return _s38_ + t1 + "' (" + H.S(_this.__js_helper$_message) + ")"; + return _s38_ + t1 + "' on '" + t2 + "' (" + H.S(_this.__js_helper$_message) + ")"; + }, + $isNoSuchMethodError: 1 + }; + H.UnknownJsTypeError.prototype = { + toString$0: function(_) { + var t1 = this.__js_helper$_message; + return t1.length === 0 ? "Error" : "Error: " + t1; + } + }; + H.ExceptionAndStackTrace.prototype = {}; + H.unwrapException_saveStackTrace.prototype = { + call$1: function(error) { + if (type$.Error._is(error)) + if (error.$thrownJsError == null) + error.$thrownJsError = this.ex; + return error; + }, + $signature: 18 + }; + H._StackTrace.prototype = { + toString$0: function(_) { + var trace, + t1 = this._trace; + if (t1 != null) + return t1; + t1 = this._exception; + trace = t1 !== null && typeof t1 === "object" ? t1.stack : null; + return this._trace = trace == null ? "" : trace; + }, + $isStackTrace: 1 + }; + H.Closure.prototype = { + toString$0: function(_) { + var $constructor = this.constructor, + $name = $constructor == null ? null : $constructor.name; + return "Closure '" + H.unminifyOrTag($name == null ? "unknown" : $name) + "'"; + }, + $isFunction: 1, + get$$call: function() { + return this; + }, + "call*": "call$1", + $requiredArgCount: 1, + $defaultValues: null + }; + H.TearOffClosure.prototype = {}; + H.StaticClosure.prototype = { + toString$0: function(_) { + var $name = this.$static_name; + if ($name == null) + return "Closure of unknown static method"; + return "Closure '" + H.unminifyOrTag($name) + "'"; + } + }; + H.BoundClosure.prototype = { + $eq: function(_, other) { + var _this = this; + if (other == null) + return false; + if (_this === other) + return true; + if (!(other instanceof H.BoundClosure)) + return false; + return _this._self === other._self && _this._target === other._target && _this._receiver === other._receiver; + }, + get$hashCode: function(_) { + var receiverHashCode, + t1 = this._receiver; + if (t1 == null) + receiverHashCode = H.Primitives_objectHashCode(this._self); + else + receiverHashCode = typeof t1 !== "object" ? J.get$hashCode$(t1) : H.Primitives_objectHashCode(t1); + return (receiverHashCode ^ H.Primitives_objectHashCode(this._target)) >>> 0; + }, + toString$0: function(_) { + var receiver = this._receiver; + if (receiver == null) + receiver = this._self; + return "Closure '" + H.S(this._name) + "' of " + ("Instance of '" + H.S(H.Primitives_objectTypeName(receiver)) + "'"); + } + }; + H.TypeErrorImplementation.prototype = { + toString$0: function(_) { + return this.message; + }, + get$message: function(receiver) { + return this.message; + } + }; + H.RuntimeError.prototype = { + toString$0: function(_) { + return "RuntimeError: " + H.S(this.message); + }, + get$message: function(receiver) { + return this.message; + } + }; + H._AssertionError.prototype = { + toString$0: function(_) { + return "Assertion failed: " + P.Error_safeToString(this.message); + } + }; + H.JsLinkedHashMap.prototype = { + get$length: function(_) { + return this.__js_helper$_length; + }, + get$isEmpty: function(_) { + return this.__js_helper$_length === 0; + }, + get$keys: function() { + return new H.LinkedHashMapKeyIterable(this, H._instanceType(this)._eval$1("LinkedHashMapKeyIterable<1>")); + }, + get$values: function() { + var t1 = H._instanceType(this); + return H.MappedIterable_MappedIterable(this.get$keys(), new H.JsLinkedHashMap_values_closure(this), t1._precomputed1, t1._rest[1]); + }, + containsKey$1: function(key) { + var strings, nums, _this = this; + if (typeof key == "string") { + strings = _this.__js_helper$_strings; + if (strings == null) + return false; + return _this._containsTableEntry$2(strings, key); + } else if (typeof key == "number" && (key & 0x3ffffff) === key) { + nums = _this.__js_helper$_nums; + if (nums == null) + return false; + return _this._containsTableEntry$2(nums, key); + } else + return _this.internalContainsKey$1(key); + }, + internalContainsKey$1: function(key) { + var _this = this, + rest = _this.__js_helper$_rest; + if (rest == null) + return false; + return _this.internalFindBucketIndex$2(_this._getTableBucket$2(rest, _this.internalComputeHashCode$1(key)), key) >= 0; + }, + addAll$1: function(_, other) { + H._instanceType(this)._eval$1("Map<1,2>")._check(other).forEach$1(0, new H.JsLinkedHashMap_addAll_closure(this)); + }, + $index: function(_, key) { + var strings, cell, t1, nums, _this = this, _null = null; + if (typeof key == "string") { + strings = _this.__js_helper$_strings; + if (strings == null) + return _null; + cell = _this._getTableCell$2(strings, key); + t1 = cell == null ? _null : cell.hashMapCellValue; + return t1; + } else if (typeof key == "number" && (key & 0x3ffffff) === key) { + nums = _this.__js_helper$_nums; + if (nums == null) + return _null; + cell = _this._getTableCell$2(nums, key); + t1 = cell == null ? _null : cell.hashMapCellValue; + return t1; + } else + return _this.internalGet$1(key); + }, + internalGet$1: function(key) { + var bucket, index, _this = this, + rest = _this.__js_helper$_rest; + if (rest == null) + return null; + bucket = _this._getTableBucket$2(rest, _this.internalComputeHashCode$1(key)); + index = _this.internalFindBucketIndex$2(bucket, key); + if (index < 0) + return null; + return bucket[index].hashMapCellValue; + }, + $indexSet: function(_, key, value) { + var strings, nums, _this = this, + t1 = H._instanceType(_this); + t1._precomputed1._check(key); + t1._rest[1]._check(value); + if (typeof key == "string") { + strings = _this.__js_helper$_strings; + _this.__js_helper$_addHashTableEntry$3(strings == null ? _this.__js_helper$_strings = _this._newHashTable$0() : strings, key, value); + } else if (typeof key == "number" && (key & 0x3ffffff) === key) { + nums = _this.__js_helper$_nums; + _this.__js_helper$_addHashTableEntry$3(nums == null ? _this.__js_helper$_nums = _this._newHashTable$0() : nums, key, value); + } else + _this.internalSet$2(key, value); + }, + internalSet$2: function(key, value) { + var rest, hash, bucket, index, _this = this, + t1 = H._instanceType(_this); + t1._precomputed1._check(key); + t1._rest[1]._check(value); + rest = _this.__js_helper$_rest; + if (rest == null) + rest = _this.__js_helper$_rest = _this._newHashTable$0(); + hash = _this.internalComputeHashCode$1(key); + bucket = _this._getTableBucket$2(rest, hash); + if (bucket == null) + _this._setTableEntry$3(rest, hash, [_this._newLinkedCell$2(key, value)]); + else { + index = _this.internalFindBucketIndex$2(bucket, key); + if (index >= 0) + bucket[index].hashMapCellValue = value; + else + bucket.push(_this._newLinkedCell$2(key, value)); + } + }, + putIfAbsent$2: function(key, ifAbsent) { + var value, _this = this, + t1 = H._instanceType(_this); + t1._precomputed1._check(key); + t1._eval$1("2()")._check(ifAbsent); + if (_this.containsKey$1(key)) + return _this.$index(0, key); + value = ifAbsent.call$0(); + _this.$indexSet(0, key, value); + return value; + }, + remove$1: function(_, key) { + var _this = this; + if (typeof key == "string") + return _this.__js_helper$_removeHashTableEntry$2(_this.__js_helper$_strings, key); + else if (typeof key == "number" && (key & 0x3ffffff) === key) + return _this.__js_helper$_removeHashTableEntry$2(_this.__js_helper$_nums, key); + else + return _this.internalRemove$1(key); + }, + internalRemove$1: function(key) { + var hash, bucket, index, cell, _this = this, + rest = _this.__js_helper$_rest; + if (rest == null) + return null; + hash = _this.internalComputeHashCode$1(key); + bucket = _this._getTableBucket$2(rest, hash); + index = _this.internalFindBucketIndex$2(bucket, key); + if (index < 0) + return null; + cell = bucket.splice(index, 1)[0]; + _this.__js_helper$_unlinkCell$1(cell); + if (bucket.length === 0) + _this._deleteTableEntry$2(rest, hash); + return cell.hashMapCellValue; + }, + clear$0: function(_) { + var _this = this; + if (_this.__js_helper$_length > 0) { + _this.__js_helper$_strings = _this.__js_helper$_nums = _this.__js_helper$_rest = _this._first = _this._last = null; + _this.__js_helper$_length = 0; + _this._modified$0(); + } + }, + forEach$1: function(_, action) { + var cell, modifications, _this = this; + H._instanceType(_this)._eval$1("~(1,2)")._check(action); + cell = _this._first; + modifications = _this._modifications; + for (; cell != null;) { + action.call$2(cell.hashMapCellKey, cell.hashMapCellValue); + if (modifications !== _this._modifications) + throw H.wrapException(P.ConcurrentModificationError$(_this)); + cell = cell._next; + } + }, + __js_helper$_addHashTableEntry$3: function(table, key, value) { + var cell, _this = this, + t1 = H._instanceType(_this); + t1._precomputed1._check(key); + t1._rest[1]._check(value); + cell = _this._getTableCell$2(table, key); + if (cell == null) + _this._setTableEntry$3(table, key, _this._newLinkedCell$2(key, value)); + else + cell.hashMapCellValue = value; + }, + __js_helper$_removeHashTableEntry$2: function(table, key) { + var cell; + if (table == null) + return null; + cell = this._getTableCell$2(table, key); + if (cell == null) + return null; + this.__js_helper$_unlinkCell$1(cell); + this._deleteTableEntry$2(table, key); + return cell.hashMapCellValue; + }, + _modified$0: function() { + this._modifications = this._modifications + 1 & 67108863; + }, + _newLinkedCell$2: function(key, value) { + var last, _this = this, + t1 = H._instanceType(_this), + cell = new H.LinkedHashMapCell(t1._precomputed1._check(key), t1._rest[1]._check(value)); + if (_this._first == null) + _this._first = _this._last = cell; + else { + last = _this._last; + cell._previous = last; + _this._last = last._next = cell; + } + ++_this.__js_helper$_length; + _this._modified$0(); + return cell; + }, + __js_helper$_unlinkCell$1: function(cell) { + var _this = this, + previous = cell._previous, + next = cell._next; + if (previous == null) { + H.assertHelper(cell == _this._first); + _this._first = next; + } else + previous._next = next; + if (next == null) { + H.assertHelper(cell == _this._last); + _this._last = previous; + } else + next._previous = previous; + --_this.__js_helper$_length; + _this._modified$0(); + }, + internalComputeHashCode$1: function(key) { + return J.get$hashCode$(key) & 0x3ffffff; + }, + internalFindBucketIndex$2: function(bucket, key) { + var $length, i; + if (bucket == null) + return -1; + $length = bucket.length; + for (i = 0; i < $length; ++i) + if (J.$eq$(bucket[i].hashMapCellKey, key)) + return i; + return -1; + }, + toString$0: function(_) { + return P.MapBase_mapToString(this); + }, + _getTableCell$2: function(table, key) { + return table[key]; + }, + _getTableBucket$2: function(table, key) { + return table[key]; + }, + _setTableEntry$3: function(table, key, value) { + H.assertHelper(value != null); + table[key] = value; + }, + _deleteTableEntry$2: function(table, key) { + delete table[key]; + }, + _containsTableEntry$2: function(table, key) { + return this._getTableCell$2(table, key) != null; + }, + _newHashTable$0: function() { + var _s20_ = "<non-identifier-key>", + table = Object.create(null); + this._setTableEntry$3(table, _s20_, table); + this._deleteTableEntry$2(table, _s20_); + return table; + }, + $isLinkedHashMap: 1 + }; + H.JsLinkedHashMap_values_closure.prototype = { + call$1: function(each) { + var t1 = this.$this; + return t1.$index(0, H._instanceType(t1)._precomputed1._check(each)); + }, + $signature: function() { + return H._instanceType(this.$this)._eval$1("2(1)"); + } + }; + H.JsLinkedHashMap_addAll_closure.prototype = { + call$2: function(key, value) { + var t1 = this.$this, + t2 = H._instanceType(t1); + t1.$indexSet(0, t2._precomputed1._check(key), t2._rest[1]._check(value)); + }, + $signature: function() { + return H._instanceType(this.$this)._eval$1("Null(1,2)"); + } + }; + H.LinkedHashMapCell.prototype = {}; + H.LinkedHashMapKeyIterable.prototype = { + get$length: function(_) { + return this.__js_helper$_map.__js_helper$_length; + }, + get$isEmpty: function(_) { + return this.__js_helper$_map.__js_helper$_length === 0; + }, + get$iterator: function(_) { + var t1 = this.__js_helper$_map, + t2 = new H.LinkedHashMapKeyIterator(t1, t1._modifications, this.$ti._eval$1("LinkedHashMapKeyIterator<1>")); + t2._cell = t1._first; + return t2; + }, + contains$1: function(_, element) { + return this.__js_helper$_map.containsKey$1(element); + } + }; + H.LinkedHashMapKeyIterator.prototype = { + get$current: function() { + return this.__js_helper$_current; + }, + moveNext$0: function() { + var _this = this, + t1 = _this.__js_helper$_map; + if (_this._modifications !== t1._modifications) + throw H.wrapException(P.ConcurrentModificationError$(t1)); + else { + t1 = _this._cell; + if (t1 == null) { + _this.set$__js_helper$_current(null); + return false; + } else { + _this.set$__js_helper$_current(t1.hashMapCellKey); + _this._cell = _this._cell._next; + return true; + } + } + }, + set$__js_helper$_current: function(_current) { + this.__js_helper$_current = this.$ti._precomputed1._check(_current); + }, + $isIterator: 1 + }; + H.initHooks_closure.prototype = { + call$1: function(o) { + return this.getTag(o); + }, + $signature: 18 + }; + H.initHooks_closure0.prototype = { + call$2: function(o, tag) { + return this.getUnknownTag(o, tag); + }, + $signature: 104 + }; + H.initHooks_closure1.prototype = { + call$1: function(tag) { + return this.prototypeForTag(H._checkStringNullable(tag)); + }, + $signature: 94 + }; + H.JSSyntaxRegExp.prototype = { + toString$0: function(_) { + return "RegExp/" + this.pattern + "/" + this._nativeRegExp.flags; + }, + get$_nativeGlobalVersion: function() { + var _this = this, + t1 = _this._nativeGlobalRegExp; + if (t1 != null) + return t1; + t1 = _this._nativeRegExp; + return _this._nativeGlobalRegExp = H.JSSyntaxRegExp_makeNative(_this.pattern, t1.multiline, !t1.ignoreCase, t1.unicode, t1.dotAll, true); + }, + get$_nativeAnchoredVersion: function() { + var _this = this, + t1 = _this._nativeAnchoredRegExp; + if (t1 != null) + return t1; + t1 = _this._nativeRegExp; + return _this._nativeAnchoredRegExp = H.JSSyntaxRegExp_makeNative(_this.pattern + "|()", t1.multiline, !t1.ignoreCase, t1.unicode, t1.dotAll, true); + }, + firstMatch$1: function(string) { + var m; + if (typeof string != "string") + H.throwExpression(H.argumentErrorValue(string)); + m = this._nativeRegExp.exec(string); + if (m == null) + return null; + return H._MatchImplementation$(this, m); + }, + allMatches$2: function(_, string, start) { + var t1 = string.length; + if (start > t1) + throw H.wrapException(P.RangeError$range(start, 0, t1, null, null)); + return new H._AllMatchesIterable(this, string, start); + }, + allMatches$1: function($receiver, string) { + return this.allMatches$2($receiver, string, 0); + }, + _execGlobal$2: function(string, start) { + var match, + regexp = this.get$_nativeGlobalVersion(); + regexp.lastIndex = start; + match = regexp.exec(string); + if (match == null) + return null; + return H._MatchImplementation$(this, match); + }, + _execAnchored$2: function(string, start) { + var match, + regexp = this.get$_nativeAnchoredVersion(); + regexp.lastIndex = start; + match = regexp.exec(string); + if (match == null) + return null; + if (0 >= match.length) + return H.ioore(match, -1); + if (match.pop() != null) + return null; + return H._MatchImplementation$(this, match); + }, + matchAsPrefix$2: function(_, string, start) { + if (start < 0 || start > string.length) + throw H.wrapException(P.RangeError$range(start, 0, string.length, null, null)); + return this._execAnchored$2(string, start); + }, + $isPattern: 1, + $isRegExp: 1 + }; + H._MatchImplementation.prototype = { + get$start: function() { + return this._match.index; + }, + get$end: function() { + var t1 = this._match; + return t1.index + t1[0].length; + }, + $index: function(_, index) { + var t1; + H._checkIntNullable(index); + t1 = this._match; + if (index >= t1.length) + return H.ioore(t1, index); + return t1[index]; + }, + $isMatch: 1, + $isRegExpMatch: 1 + }; + H._AllMatchesIterable.prototype = { + get$iterator: function(_) { + return new H._AllMatchesIterator(this._re, this.__js_helper$_string, this._start); + } + }; + H._AllMatchesIterator.prototype = { + get$current: function() { + return this.__js_helper$_current; + }, + moveNext$0: function() { + var t2, t3, match, nextIndex, _this = this, + t1 = _this.__js_helper$_string; + if (t1 == null) + return false; + t2 = _this._nextIndex; + if (t2 <= t1.length) { + t3 = _this._regExp; + match = t3._execGlobal$2(t1, t2); + if (match != null) { + _this.__js_helper$_current = match; + nextIndex = match.get$end(); + if (match._match.index === nextIndex) { + if (t3._nativeRegExp.unicode) { + t1 = _this._nextIndex; + t2 = t1 + 1; + t3 = _this.__js_helper$_string; + if (t2 < t3.length) { + t1 = J.getInterceptor$s(t3).codeUnitAt$1(t3, t1); + if (t1 >= 55296 && t1 <= 56319) { + t1 = C.JSString_methods.codeUnitAt$1(t3, t2); + t1 = t1 >= 56320 && t1 <= 57343; + } else + t1 = false; + } else + t1 = false; + } else + t1 = false; + nextIndex = (t1 ? nextIndex + 1 : nextIndex) + 1; + } + _this._nextIndex = nextIndex; + return true; + } + } + _this.__js_helper$_string = _this.__js_helper$_current = null; + return false; + }, + $isIterator: 1 + }; + H.StringMatch.prototype = { + get$end: function() { + return this.start + this.pattern.length; + }, + $index: function(_, g) { + H._checkIntNullable(g); + if (g !== 0) + H.throwExpression(P.RangeError$value(g, null)); + return this.pattern; + }, + $isMatch: 1, + get$start: function() { + return this.start; + } + }; + H._StringAllMatchesIterable.prototype = { + get$iterator: function(_) { + return new H._StringAllMatchesIterator(this._input, this._pattern, this.__js_helper$_index); + }, + get$first: function(_) { + var t1 = this._pattern, + index = this._input.indexOf(t1, this.__js_helper$_index); + if (index >= 0) + return new H.StringMatch(index, t1); + throw H.wrapException(H.IterableElementError_noElement()); + } + }; + H._StringAllMatchesIterator.prototype = { + moveNext$0: function() { + var index, end, _this = this, + t1 = _this.__js_helper$_index, + t2 = _this._pattern, + t3 = t2.length, + t4 = _this._input, + t5 = t4.length; + if (t1 + t3 > t5) { + _this.__js_helper$_current = null; + return false; + } + index = t4.indexOf(t2, t1); + if (index < 0) { + _this.__js_helper$_index = t5 + 1; + _this.__js_helper$_current = null; + return false; + } + end = index + t3; + _this.__js_helper$_current = new H.StringMatch(index, t2); + _this.__js_helper$_index = end === _this.__js_helper$_index ? end + 1 : end; + return true; + }, + get$current: function() { + return this.__js_helper$_current; + }, + $isIterator: 1 + }; + H.NativeByteBuffer.prototype = { + get$runtimeType: function(receiver) { + return C.Type_ByteBuffer_RkP; + }, + $isNativeByteBuffer: 1, + $isByteBuffer: 1 + }; + H.NativeTypedData.prototype = {$isNativeTypedData: 1}; + H.NativeByteData.prototype = { + get$runtimeType: function(receiver) { + return C.Type_ByteData_zNC; + } + }; + H.NativeTypedArray.prototype = { + get$length: function(receiver) { + return receiver.length; + }, + $isJavaScriptIndexingBehavior: 1 + }; + H.NativeTypedArrayOfDouble.prototype = { + $index: function(receiver, index) { + H._checkIntNullable(index); + H._checkValidIndex(index, receiver, receiver.length); + return receiver[index]; + }, + $indexSet: function(receiver, index, value) { + H._checkIntNullable(index); + H._checkDoubleNullable(value); + H._checkValidIndex(index, receiver, receiver.length); + receiver[index] = value; + }, + $isEfficientLengthIterable: 1, + $isIterable: 1, + $isList: 1 + }; + H.NativeTypedArrayOfInt.prototype = { + $indexSet: function(receiver, index, value) { + H._checkIntNullable(index); + H._checkIntNullable(value); + H._checkValidIndex(index, receiver, receiver.length); + receiver[index] = value; + }, + $isEfficientLengthIterable: 1, + $isIterable: 1, + $isList: 1 + }; + H.NativeFloat32List.prototype = { + get$runtimeType: function(receiver) { + return C.Type_Float32List_LB7; + } + }; + H.NativeFloat64List.prototype = { + get$runtimeType: function(receiver) { + return C.Type_Float64List_LB7; + } + }; + H.NativeInt16List.prototype = { + get$runtimeType: function(receiver) { + return C.Type_Int16List_uXf; + }, + $index: function(receiver, index) { + H._checkIntNullable(index); + H._checkValidIndex(index, receiver, receiver.length); + return receiver[index]; + } + }; + H.NativeInt32List.prototype = { + get$runtimeType: function(receiver) { + return C.Type_Int32List_O50; + }, + $index: function(receiver, index) { + H._checkIntNullable(index); + H._checkValidIndex(index, receiver, receiver.length); + return receiver[index]; + } + }; + H.NativeInt8List.prototype = { + get$runtimeType: function(receiver) { + return C.Type_Int8List_ekJ; + }, + $index: function(receiver, index) { + H._checkIntNullable(index); + H._checkValidIndex(index, receiver, receiver.length); + return receiver[index]; + } + }; + H.NativeUint16List.prototype = { + get$runtimeType: function(receiver) { + return C.Type_Uint16List_2bx; + }, + $index: function(receiver, index) { + H._checkIntNullable(index); + H._checkValidIndex(index, receiver, receiver.length); + return receiver[index]; + } + }; + H.NativeUint32List.prototype = { + get$runtimeType: function(receiver) { + return C.Type_Uint32List_2bx; + }, + $index: function(receiver, index) { + H._checkIntNullable(index); + H._checkValidIndex(index, receiver, receiver.length); + return receiver[index]; + }, + sublist$2: function(receiver, start, end) { + return new Uint32Array(receiver.subarray(start, H._checkValidRange(start, end, receiver.length))); + }, + $isUint32List: 1 + }; + H.NativeUint8ClampedList.prototype = { + get$runtimeType: function(receiver) { + return C.Type_Uint8ClampedList_Jik; + }, + get$length: function(receiver) { + return receiver.length; + }, + $index: function(receiver, index) { + H._checkIntNullable(index); + H._checkValidIndex(index, receiver, receiver.length); + return receiver[index]; + } + }; + H.NativeUint8List.prototype = { + get$runtimeType: function(receiver) { + return C.Type_Uint8List_WLA; + }, + get$length: function(receiver) { + return receiver.length; + }, + $index: function(receiver, index) { + H._checkIntNullable(index); + H._checkValidIndex(index, receiver, receiver.length); + return receiver[index]; + }, + sublist$2: function(receiver, start, end) { + return new Uint8Array(receiver.subarray(start, H._checkValidRange(start, end, receiver.length))); + }, + $isNativeUint8List: 1, + $isUint8List: 1 + }; + H._NativeTypedArrayOfDouble_NativeTypedArray_ListMixin.prototype = {}; + H._NativeTypedArrayOfDouble_NativeTypedArray_ListMixin_FixedLengthListMixin.prototype = {}; + H._NativeTypedArrayOfInt_NativeTypedArray_ListMixin.prototype = {}; + H._NativeTypedArrayOfInt_NativeTypedArray_ListMixin_FixedLengthListMixin.prototype = {}; + H.Rti.prototype = { + _eval$1: function(recipe) { + return H._Universe_evalInEnvironment(init.typeUniverse, this, recipe); + }, + _bind$1: function(typeOrTuple) { + return H._Universe_bind(init.typeUniverse, this, typeOrTuple); + } + }; + H._FunctionParameters.prototype = {}; + H._Type.prototype = { + get$hashCode: function(_) { + var s, + t1 = this._hashCode; + if (t1 == null) { + s = this._rti._canonicalRecipe; + if (H.assertTest(typeof s == "string")) + H.assertThrow("Missing canonical recipe"); + t1 = this._hashCode = C.JSString_methods.get$hashCode(s); + } + return t1; + }, + $eq: function(_, other) { + if (other == null) + return false; + return other instanceof H._Type && this._rti == other._rti; + }, + toString$0: function(_) { + return H._rtiToString(this._rti, null); + }, + $isType: 1 + }; + H._Error.prototype = { + toString$0: function(_) { + return this._message; + } + }; + H._CastError.prototype = {}; + H._TypeError.prototype = { + get$message: function(_) { + return this._message; + } + }; + P._AsyncRun__initializeScheduleImmediate_internalCallback.prototype = { + call$1: function(_) { + var t1 = this._box_0, + f = t1.storedCallback; + t1.storedCallback = null; + f.call$0(); + }, + $signature: 3 + }; + P._AsyncRun__initializeScheduleImmediate_closure.prototype = { + call$1: function(callback) { + var t1, t2; + type$.void_Function._check(callback); + t1 = this._box_0; + H.assertHelper(t1.storedCallback == null); + t1.storedCallback = callback; + t1 = this.div; + t2 = this.span; + t1.firstChild ? t1.removeChild(t2) : t1.appendChild(t2); + }, + $signature: 91 + }; + P._AsyncRun__scheduleImmediateJsOverride_internalCallback.prototype = { + call$0: function() { + this.callback.call$0(); + }, + $signature: 0 + }; + P._AsyncRun__scheduleImmediateWithSetImmediate_internalCallback.prototype = { + call$0: function() { + this.callback.call$0(); + }, + $signature: 0 + }; + P._TimerImpl.prototype = { + _TimerImpl$2: function(milliseconds, callback) { + if (self.setTimeout != null) + this._handle = self.setTimeout(H.convertDartClosureToJS(new P._TimerImpl_internalCallback(this, callback), 0), milliseconds); + else + throw H.wrapException(P.UnsupportedError$("`setTimeout()` not found.")); + }, + _TimerImpl$periodic$2: function(milliseconds, callback) { + if (self.setTimeout != null) + this._handle = self.setInterval(H.convertDartClosureToJS(new P._TimerImpl$periodic_closure(this, milliseconds, Date.now(), callback), 0), milliseconds); + else + throw H.wrapException(P.UnsupportedError$("Periodic timer.")); + }, + cancel$0: function() { + if (self.setTimeout != null) { + var t1 = this._handle; + if (t1 == null) + return; + if (this._once) + self.clearTimeout(t1); + else + self.clearInterval(t1); + this._handle = null; + } else + throw H.wrapException(P.UnsupportedError$("Canceling a timer.")); + }, + $isTimer: 1 + }; + P._TimerImpl_internalCallback.prototype = { + call$0: function() { + var t1 = this.$this; + t1._handle = null; + t1._tick = 1; + this.callback.call$0(); + }, + $signature: 1 + }; + P._TimerImpl$periodic_closure.prototype = { + call$0: function() { + var duration, _this = this, + t1 = _this.$this, + tick = t1._tick + 1, + t2 = _this.milliseconds; + if (t2 > 0) { + duration = Date.now() - _this.start; + if (duration > (tick + 1) * t2) + tick = C.JSInt_methods.$tdiv(duration, t2); + } + t1._tick = tick; + _this.callback.call$1(t1); + }, + $signature: 0 + }; + P._AsyncAwaitCompleter.prototype = { + complete$1: function(value) { + var t2, t3, + t1 = this.$ti; + t1._eval$1("1/")._check(value); + t2 = !this.isSync || t1._eval$1("Future<1>")._is(value); + t3 = this._future; + if (t2) + t3._asyncComplete$1(value); + else + t3._completeWithValue$1(t1._precomputed1._check(value)); + }, + completeError$2: function(e, st) { + var t1 = this._future; + if (this.isSync) + t1._completeError$2(e, st); + else + t1._asyncCompleteError$2(e, st); + }, + $isCompleter: 1 + }; + P._awaitOnObject_closure.prototype = { + call$1: function(result) { + return this.bodyFunction.call$2(0, result); + }, + $signature: 15 + }; + P._awaitOnObject_closure0.prototype = { + call$2: function(error, stackTrace) { + this.bodyFunction.call$2(1, new H.ExceptionAndStackTrace(error, type$.StackTrace._check(stackTrace))); + }, + $signature: 5 + }; + P._wrapJsFunctionForAsync_closure.prototype = { + call$2: function(errorCode, result) { + this.$protected(H._checkIntNullable(errorCode), result); + }, + $signature: 89 + }; + P._BroadcastStream.prototype = { + get$isBroadcast: function() { + return true; + } + }; + P._BroadcastSubscription.prototype = { + _onPause$0: function() { + }, + _onResume$0: function() { + }, + set$_async$_next: function(_next) { + this._async$_next = this.$ti._check(_next); + }, + set$_async$_previous: function(_previous) { + this._async$_previous = this.$ti._check(_previous); + } + }; + P._BroadcastStreamController.prototype = { + get$_mayAddEvent: function() { + return this._state < 4; + }, + _ensureDoneFuture$0: function() { + var t1 = this._doneFuture; + if (t1 != null) + return t1; + return this._doneFuture = new P._Future($.Zone__current, type$._Future_dynamic); + }, + _removeListener$1: function(subscription) { + var previous, next, _this = this; + H._instanceType(_this)._eval$1("_BroadcastSubscription<1>")._check(subscription); + H.assertHelper(subscription._controller === _this); + H.assertHelper(subscription._async$_next !== subscription); + previous = subscription._async$_previous; + next = subscription._async$_next; + if (previous == null) + _this.set$_firstSubscription(next); + else + previous.set$_async$_next(next); + if (next == null) + _this.set$_lastSubscription(previous); + else + next.set$_async$_previous(previous); + subscription.set$_async$_previous(subscription); + subscription.set$_async$_next(subscription); + }, + _subscribe$4: function(onData, onError, onDone, cancelOnError) { + var t2, t3, t4, subscription, oldLast, _this = this, + t1 = H._instanceType(_this); + t1._eval$1("~(1)")._check(onData); + type$.void_Function._check(onDone); + if ((_this._state & 4) !== 0) { + if (onDone == null) + onDone = P.async___nullDoneHandler$closure(); + t1 = new P._DoneStreamSubscription($.Zone__current, onDone, t1._eval$1("_DoneStreamSubscription<1>")); + t1._schedule$0(); + return t1; + } + t2 = $.Zone__current; + t3 = cancelOnError ? 1 : 0; + t4 = t1._eval$1("_BroadcastSubscription<1>"); + subscription = new P._BroadcastSubscription(_this, t2, t3, t4); + subscription._BufferingStreamSubscription$4(onData, onError, onDone, cancelOnError, t1._precomputed1); + subscription.set$_async$_previous(subscription); + subscription.set$_async$_next(subscription); + t4._check(subscription); + H.assertHelper(subscription._async$_next === subscription); + subscription._eventState = _this._state & 1; + oldLast = _this._lastSubscription; + _this.set$_lastSubscription(subscription); + subscription.set$_async$_next(null); + subscription.set$_async$_previous(oldLast); + if (oldLast == null) + _this.set$_firstSubscription(subscription); + else + oldLast.set$_async$_next(subscription); + if (_this._firstSubscription == _this._lastSubscription) + P._runGuarded(_this.onListen); + return subscription; + }, + _recordCancel$1: function(sub) { + var _this = this, + t1 = H._instanceType(_this); + sub = t1._eval$1("_BroadcastSubscription<1>")._check(t1._eval$1("StreamSubscription<1>")._check(sub)); + if (sub._async$_next === sub) + return null; + t1 = (sub._eventState & 2) !== 0; + if (t1) { + H.assertHelper(t1); + sub._eventState |= 4; + } else { + _this._removeListener$1(sub); + if ((_this._state & 2) === 0 && _this._firstSubscription == null) + _this._callOnCancel$0(); + } + return null; + }, + _recordPause$1: function(subscription) { + H._instanceType(this)._eval$1("StreamSubscription<1>")._check(subscription); + }, + _recordResume$1: function(subscription) { + H._instanceType(this)._eval$1("StreamSubscription<1>")._check(subscription); + }, + _addEventError$0: function() { + var t1 = this._state; + if ((t1 & 4) !== 0) + return new P.StateError("Cannot add new events after calling close"); + H.assertHelper((t1 & 8) !== 0); + return new P.StateError("Cannot add new events while doing an addStream"); + }, + add$1: function(_, data) { + var _this = this; + H._instanceType(_this)._precomputed1._check(data); + if (!_this.get$_mayAddEvent()) + throw H.wrapException(_this._addEventError$0()); + _this._sendData$1(data); + }, + addError$2: function(error, stackTrace) { + var replacement; + type$.StackTrace._check(stackTrace); + if (error == null) + error = new P.NullThrownError(); + if (!this.get$_mayAddEvent()) + throw H.wrapException(this._addEventError$0()); + replacement = $.Zone__current.errorCallback$2(error, stackTrace); + if (replacement != null) { + error = replacement.error; + if (error == null) + error = new P.NullThrownError(); + stackTrace = replacement.stackTrace; + } + this._sendError$2(error, stackTrace); + }, + addError$1: function(error) { + return this.addError$2(error, null); + }, + close$0: function(_) { + var doneFuture, _this = this; + if ((_this._state & 4) !== 0) { + H.assertHelper(_this._doneFuture != null); + return _this._doneFuture; + } + if (!_this.get$_mayAddEvent()) + throw H.wrapException(_this._addEventError$0()); + _this._state |= 4; + doneFuture = _this._ensureDoneFuture$0(); + _this._sendDone$0(); + return doneFuture; + }, + _async$_addError$2: function(error, stackTrace) { + this._sendError$2(error, type$.StackTrace._check(stackTrace)); + }, + _close$0: function() { + var addState, _this = this; + H.assertHelper((_this._state & 8) !== 0); + addState = _this._addStreamState; + _this.set$_addStreamState(null); + _this._state &= 4294967287; + addState.addStreamFuture._asyncComplete$1(null); + }, + _forEachListener$1: function(action) { + var t1, subscription, id, next, _this = this; + H._instanceType(_this)._eval$1("~(_BufferingStreamSubscription<1>)")._check(action); + t1 = _this._state; + if ((t1 & 2) !== 0) + throw H.wrapException(P.StateError$("Cannot fire new event. Controller is already firing an event")); + subscription = _this._firstSubscription; + if (subscription == null) + return; + id = t1 & 1; + _this._state = t1 ^ 3; + for (; subscription != null;) { + t1 = subscription._eventState; + if ((t1 & 1) === id) { + subscription._eventState = t1 | 2; + action.call$1(subscription); + t1 = subscription._eventState ^= 1; + next = subscription._async$_next; + if ((t1 & 4) !== 0) + _this._removeListener$1(subscription); + subscription._eventState &= 4294967293; + subscription = next; + } else + subscription = subscription._async$_next; + } + _this._state &= 4294967293; + if (_this._firstSubscription == null) + _this._callOnCancel$0(); + }, + _callOnCancel$0: function() { + var _this = this; + H.assertHelper(_this._firstSubscription == null); + if ((_this._state & 4) !== 0 && _this._doneFuture._state === 0) + _this._doneFuture._asyncComplete$1(null); + P._runGuarded(_this.onCancel); + }, + set$_firstSubscription: function(_firstSubscription) { + this._firstSubscription = H._instanceType(this)._eval$1("_BroadcastSubscription<1>")._check(_firstSubscription); + }, + set$_lastSubscription: function(_lastSubscription) { + this._lastSubscription = H._instanceType(this)._eval$1("_BroadcastSubscription<1>")._check(_lastSubscription); + }, + set$_addStreamState: function(_addStreamState) { + this._addStreamState = H._instanceType(this)._eval$1("_AddStreamState<1>")._check(_addStreamState); + }, + $isEventSink: 1, + $isStreamConsumer: 1, + $isStreamSink: 1, + $isStreamController: 1, + $is_StreamControllerLifecycle: 1, + $is_EventDispatch: 1, + $isSink: 1 + }; + P._SyncBroadcastStreamController.prototype = { + get$_mayAddEvent: function() { + return P._BroadcastStreamController.prototype.get$_mayAddEvent.call(this) && (this._state & 2) === 0; + }, + _addEventError$0: function() { + if ((this._state & 2) !== 0) + return new P.StateError("Cannot fire new event. Controller is already firing an event"); + return this.super$_BroadcastStreamController$_addEventError(); + }, + _sendData$1: function(data) { + var t1, _this = this; + _this.$ti._precomputed1._check(data); + if (_this._firstSubscription == null) + return; + t1 = _this._firstSubscription; + if (t1 == _this._lastSubscription) { + _this._state |= 2; + t1._add$1(data); + _this._state &= 4294967293; + if (_this._firstSubscription == null) + _this._callOnCancel$0(); + return; + } + _this._forEachListener$1(new P._SyncBroadcastStreamController__sendData_closure(_this, data)); + }, + _sendError$2: function(error, stackTrace) { + if (this._firstSubscription == null) + return; + this._forEachListener$1(new P._SyncBroadcastStreamController__sendError_closure(this, error, stackTrace)); + }, + _sendDone$0: function() { + var _this = this; + if (_this._firstSubscription != null) + _this._forEachListener$1(new P._SyncBroadcastStreamController__sendDone_closure(_this)); + else { + H.assertHelper(_this._doneFuture != null); + H.assertHelper(_this._doneFuture._state === 0); + _this._doneFuture._asyncComplete$1(null); + } + } + }; + P._SyncBroadcastStreamController__sendData_closure.prototype = { + call$1: function(subscription) { + this.$this.$ti._eval$1("_BufferingStreamSubscription<1>")._check(subscription)._add$1(this.data); + }, + $signature: function() { + return this.$this.$ti._eval$1("Null(_BufferingStreamSubscription<1>)"); + } + }; + P._SyncBroadcastStreamController__sendError_closure.prototype = { + call$1: function(subscription) { + this.$this.$ti._eval$1("_BufferingStreamSubscription<1>")._check(subscription)._async$_addError$2(this.error, this.stackTrace); + }, + $signature: function() { + return this.$this.$ti._eval$1("Null(_BufferingStreamSubscription<1>)"); + } + }; + P._SyncBroadcastStreamController__sendDone_closure.prototype = { + call$1: function(subscription) { + this.$this.$ti._eval$1("_BufferingStreamSubscription<1>")._check(subscription)._close$0(); + }, + $signature: function() { + return this.$this.$ti._eval$1("Null(_BufferingStreamSubscription<1>)"); + } + }; + P._AsyncBroadcastStreamController.prototype = { + _sendData$1: function(data) { + var subscription, + t1 = this.$ti; + t1._precomputed1._check(data); + for (subscription = this._firstSubscription, t1 = t1._eval$1("_DelayedData<1>"); subscription != null; subscription = subscription._async$_next) + subscription._addPending$1(new P._DelayedData(data, t1)); + }, + _sendError$2: function(error, stackTrace) { + var subscription; + for (subscription = this._firstSubscription; subscription != null; subscription = subscription._async$_next) + subscription._addPending$1(new P._DelayedError(error, stackTrace)); + }, + _sendDone$0: function() { + var _this = this, + subscription = _this._firstSubscription; + if (subscription != null) + for (; subscription != null; subscription = subscription._async$_next) + subscription._addPending$1(C.C__DelayedDone); + else { + H.assertHelper(_this._doneFuture != null); + H.assertHelper(_this._doneFuture._state === 0); + _this._doneFuture._asyncComplete$1(null); + } + } + }; + P.Future.prototype = {}; + P.Future_Future_closure.prototype = { + call$0: function() { + var e, s, exception; + try { + this.result._complete$1(this.computation.call$0()); + } catch (exception) { + e = H.unwrapException(exception); + s = H.getTraceFromException(exception); + P._completeWithErrorCallback(this.result, e, s); + } + }, + $signature: 0 + }; + P.Future_Future$microtask_closure.prototype = { + call$0: function() { + var e, s, exception; + try { + this.result._complete$1(this.computation.call$0()); + } catch (exception) { + e = H.unwrapException(exception); + s = H.getTraceFromException(exception); + P._completeWithErrorCallback(this.result, e, s); + } + }, + $signature: 0 + }; + P.Future_wait_handleError.prototype = { + call$2: function(theError, theStackTrace) { + var t1, t2, _this = this; + type$.StackTrace._check(theStackTrace); + t1 = _this._box_0; + t2 = --t1.remaining; + if (t1.values != null) { + t1.values = null; + if (t1.remaining === 0 || _this.eagerError) + _this.result._completeError$2(theError, theStackTrace); + else { + t1.error = theError; + t1.stackTrace = theStackTrace; + } + } else if (t2 === 0 && !_this.eagerError) + _this.result._completeError$2(t1.error, t1.stackTrace); + }, + $signature: 5 + }; + P.Future_wait_closure.prototype = { + call$1: function(value) { + var t1, t2, _this = this; + _this.T._check(value); + t1 = _this._box_0; + --t1.remaining; + t2 = t1.values; + if (t2 != null) { + C.JSArray_methods.$indexSet(t2, _this.pos, value); + if (t1.remaining === 0) + _this.result._completeWithValue$1(t1.values); + } else if (t1.remaining === 0 && !_this.eagerError) + _this.result._completeError$2(t1.error, t1.stackTrace); + }, + $signature: function() { + return this.T._eval$1("Null(0)"); + } + }; + P.Future_forEach_closure.prototype = { + call$0: function() { + var result, + t1 = this.iterator; + if (!t1.moveNext$0()) + return false; + result = this.action.call$1(t1._current); + if (type$.Future_dynamic._is(result)) + return result.then$1$1(P.async_Future__kTrue$closure(), type$.bool); + return true; + }, + $signature: 81 + }; + P.Future_doWhile_closure.prototype = { + call$1: function(keepGoing) { + var result, error, stackTrace, t1, t2, exception, error0, stackTrace0, replacement, _this = this; + H._checkBoolNullable(keepGoing); + for (t1 = type$.Future_bool, t2 = _this.action; H.boolConversionCheck(keepGoing);) { + result = null; + try { + result = t2.call$0(); + } catch (exception) { + error = H.unwrapException(exception); + stackTrace = H.getTraceFromException(exception); + error0 = error; + stackTrace0 = stackTrace; + replacement = $.Zone__current.errorCallback$2(error0, stackTrace0); + if (replacement != null) { + error = replacement.error; + if (error == null) + error = new P.NullThrownError(); + stackTrace = replacement.stackTrace; + } else { + stackTrace = stackTrace0; + error = error0; + } + _this.doneSignal._asyncCompleteError$2(error, stackTrace); + return; + } + if (t1._is(result)) { + result.then$1$2$onError(_this._box_0.nextIteration, _this.doneSignal.get$_completeError(), type$.void); + return; + } + keepGoing = H._checkBoolNullable(result); + } + _this.doneSignal._complete$1(null); + }, + $signature: 43 + }; + P.TimeoutException.prototype = { + toString$0: function(_) { + var t1 = this.duration, + result = (t1 != null ? "TimeoutException after " + t1.toString$0(0) : "TimeoutException") + ": " + this.message; + return result; + }, + $isException: 1, + get$message: function(receiver) { + return this.message; + } + }; + P.Completer.prototype = {}; + P._Completer.prototype = { + completeError$2: function(error, stackTrace) { + var replacement; + if (error == null) + error = new P.NullThrownError(); + if (this.future._state !== 0) + throw H.wrapException(P.StateError$("Future already completed")); + replacement = $.Zone__current.errorCallback$2(error, stackTrace); + if (replacement != null) { + error = replacement.error; + if (error == null) + error = new P.NullThrownError(); + stackTrace = replacement.stackTrace; + } + this._completeError$2(error, stackTrace); + }, + completeError$1: function(error) { + return this.completeError$2(error, null); + }, + $isCompleter: 1 + }; + P._AsyncCompleter.prototype = { + complete$1: function(value) { + var t1; + this.$ti._eval$1("1/")._check(value); + t1 = this.future; + if (t1._state !== 0) + throw H.wrapException(P.StateError$("Future already completed")); + t1._asyncComplete$1(value); + }, + complete$0: function() { + return this.complete$1(null); + }, + _completeError$2: function(error, stackTrace) { + this.future._asyncCompleteError$2(error, stackTrace); + } + }; + P._SyncCompleter.prototype = { + complete$1: function(value) { + var t1; + this.$ti._eval$1("1/")._check(value); + t1 = this.future; + if (t1._state !== 0) + throw H.wrapException(P.StateError$("Future already completed")); + t1._complete$1(value); + }, + complete$0: function() { + return this.complete$1(null); + }, + _completeError$2: function(error, stackTrace) { + this.future._completeError$2(error, stackTrace); + } + }; + P._FutureListener.prototype = { + matchesErrorTest$1: function(asyncError) { + if ((this.state & 15) !== 6) + return true; + return this.result._zone.runUnary$2$2(type$.bool_Function_Object._check(this.callback), asyncError.error, type$.bool, type$.Object); + }, + handleError$1: function(asyncError) { + var errorCallback, t2, t3, t4, _this = this, + t1 = (_this.state & 2) !== 0; + if (t1) { + H.assertHelper(t1); + t1 = _this.errorCallback != null; + } else + t1 = false; + H.assertHelper(t1); + errorCallback = _this.errorCallback; + t1 = type$.dynamic; + t2 = type$.Object; + t3 = _this.$ti._eval$1("2/"); + t4 = _this.result._zone; + if (type$.dynamic_Function_Object_StackTrace._is(errorCallback)) + return t3._check(t4.runBinary$3$3(errorCallback, asyncError.error, asyncError.stackTrace, t1, t2, type$.StackTrace)); + else { + H.assertHelper(type$.dynamic_Function_Object._is(errorCallback)); + return t3._check(t4.runUnary$2$2(errorCallback, asyncError.error, t1, t2)); + } + } + }; + P._Future.prototype = { + then$1$2$onError: function(f, onError, $R) { + var currentZone, result, t2, + t1 = this.$ti; + t1._bind$1($R)._eval$1("1/(2)")._check(f); + currentZone = $.Zone__current; + if (currentZone !== C.C__RootZone) { + f = currentZone.registerUnaryCallback$2$1(f, $R._eval$1("0/"), t1._precomputed1); + if (onError != null) + onError = P._registerErrorHandler(onError, currentZone); + } + result = new P._Future($.Zone__current, $R._eval$1("_Future<0>")); + t2 = onError == null ? 1 : 3; + this._addListener$1(new P._FutureListener(result, t2, f, onError, t1._eval$1("@<1>")._bind$1($R)._eval$1("_FutureListener<1,2>"))); + return result; + }, + then$1$1: function(f, $R) { + return this.then$1$2$onError(f, null, $R); + }, + _thenAwait$1$2: function(f, onError, $E) { + var result, + t1 = this.$ti; + t1._bind$1($E)._eval$1("1/(2)")._check(f); + result = new P._Future($.Zone__current, $E._eval$1("_Future<0>")); + this._addListener$1(new P._FutureListener(result, (onError == null ? 1 : 3) | 16, f, onError, t1._eval$1("@<1>")._bind$1($E)._eval$1("_FutureListener<1,2>"))); + return result; + }, + catchError$1: function(onError) { + var t1, t2, result; + type$.bool_Function_dynamic._check(null); + t1 = this.$ti; + t2 = $.Zone__current; + result = new P._Future(t2, t1); + if (t2 !== C.C__RootZone) + onError = P._registerErrorHandler(onError, t2); + this._addListener$1(new P._FutureListener(result, 2, null, onError, t1._eval$1("@<1>")._bind$1(t1._precomputed1)._eval$1("_FutureListener<1,2>"))); + return result; + }, + whenComplete$1: function(action) { + var t1, t2, result; + type$.dynamic_Function._check(action); + t1 = this.$ti; + t2 = $.Zone__current; + result = new P._Future(t2, t1); + if (t2 !== C.C__RootZone) + action = t2.registerCallback$1$1(action, type$.dynamic); + this._addListener$1(new P._FutureListener(result, 8, action, null, t1._eval$1("@<1>")._bind$1(t1._precomputed1)._eval$1("_FutureListener<1,2>"))); + return result; + }, + _cloneResult$1: function(source) { + H.assertHelper(this._state < 4); + H.assertHelper(source._state >= 4); + this._state = source._state; + this._resultOrListeners = source._resultOrListeners; + }, + _addListener$1: function(listener) { + var t1, source, _this = this; + H.assertHelper(listener._nextListener == null); + t1 = _this._state; + if (t1 <= 1) { + listener._nextListener = type$._FutureListener_dynamic_dynamic._check(_this._resultOrListeners); + _this._resultOrListeners = listener; + } else { + if (t1 === 2) { + source = type$._Future_dynamic._check(_this._resultOrListeners); + if (source._state < 4) { + source._addListener$1(listener); + return; + } + _this._cloneResult$1(source); + } + H.assertHelper(_this._state >= 4); + _this._zone.scheduleMicrotask$1(new P._Future__addListener_closure(_this, listener)); + } + }, + _prependListeners$1: function(listeners) { + var t1, existingListeners, cursor, cursor0, source, _this = this, _box_0 = {}; + _box_0.listeners = listeners; + if (listeners == null) + return; + t1 = _this._state; + if (t1 <= 1) { + existingListeners = type$._FutureListener_dynamic_dynamic._check(_this._resultOrListeners); + cursor = _this._resultOrListeners = listeners; + if (existingListeners != null) { + for (; cursor0 = cursor._nextListener, cursor0 != null; cursor = cursor0) + ; + cursor._nextListener = existingListeners; + } + } else { + if (t1 === 2) { + source = type$._Future_dynamic._check(_this._resultOrListeners); + if (source._state < 4) { + source._prependListeners$1(listeners); + return; + } + _this._cloneResult$1(source); + } + H.assertHelper(_this._state >= 4); + _box_0.listeners = _this._reverseListeners$1(listeners); + _this._zone.scheduleMicrotask$1(new P._Future__prependListeners_closure(_box_0, _this)); + } + }, + _removeListeners$0: function() { + var current, _this = this; + H.assertHelper(_this._state < 4); + current = type$._FutureListener_dynamic_dynamic._check(_this._resultOrListeners); + _this._resultOrListeners = null; + return _this._reverseListeners$1(current); + }, + _reverseListeners$1: function(listeners) { + var current, prev, next; + for (current = listeners, prev = null; current != null; prev = current, current = next) { + next = current._nextListener; + current._nextListener = prev; + } + return prev; + }, + _complete$1: function(value) { + var listeners, _this = this, + t1 = _this.$ti; + t1._eval$1("1/")._check(value); + H.assertHelper(_this._state < 4); + if (t1._eval$1("Future<1>")._is(value)) + if (t1._is(value)) + P._Future__chainCoreFuture(value, _this); + else + P._Future__chainForeignFuture(value, _this); + else { + listeners = _this._removeListeners$0(); + t1._precomputed1._check(value); + H.assertHelper(_this._state < 4); + _this._state = 4; + _this._resultOrListeners = value; + P._Future__propagateToListeners(_this, listeners); + } + }, + _completeWithValue$1: function(value) { + var listeners, _this = this, + t1 = _this.$ti; + t1._precomputed1._check(value); + H.assertHelper(_this._state < 4); + H.assertHelper(!t1._eval$1("Future<1>")._is(value)); + listeners = _this._removeListeners$0(); + H.assertHelper(_this._state < 4); + _this._state = 4; + _this._resultOrListeners = value; + P._Future__propagateToListeners(_this, listeners); + }, + _completeError$2: function(error, stackTrace) { + var listeners, _this = this; + type$.StackTrace._check(stackTrace); + H.assertHelper(_this._state < 4); + listeners = _this._removeListeners$0(); + H.assertHelper(_this._state < 4); + _this._state = 8; + _this._resultOrListeners = new P.AsyncError(error, stackTrace); + P._Future__propagateToListeners(_this, listeners); + }, + _completeError$1: function(error) { + return this._completeError$2(error, null); + }, + _asyncComplete$1: function(value) { + var _this = this, + t1 = _this.$ti; + t1._eval$1("1/")._check(value); + H.assertHelper(_this._state < 4); + if (t1._eval$1("Future<1>")._is(value)) { + _this._chainFuture$1(value); + return; + } + H.assertHelper(_this._state === 0); + _this._state = 1; + _this._zone.scheduleMicrotask$1(new P._Future__asyncComplete_closure(_this, value)); + }, + _chainFuture$1: function(value) { + var _this = this, + t1 = _this.$ti; + t1._eval$1("Future<1>")._check(value); + if (t1._is(value)) { + if (value._state === 8) { + H.assertHelper(_this._state === 0); + _this._state = 1; + _this._zone.scheduleMicrotask$1(new P._Future__chainFuture_closure(_this, value)); + } else + P._Future__chainCoreFuture(value, _this); + return; + } + P._Future__chainForeignFuture(value, _this); + }, + _asyncCompleteError$2: function(error, stackTrace) { + var _this = this; + type$.StackTrace._check(stackTrace); + H.assertHelper(_this._state < 4); + H.assertHelper(_this._state === 0); + _this._state = 1; + _this._zone.scheduleMicrotask$1(new P._Future__asyncCompleteError_closure(_this, error, stackTrace)); + }, + $isFuture: 1 + }; + P._Future__addListener_closure.prototype = { + call$0: function() { + P._Future__propagateToListeners(this.$this, this.listener); + }, + $signature: 0 + }; + P._Future__prependListeners_closure.prototype = { + call$0: function() { + P._Future__propagateToListeners(this.$this, this._box_0.listeners); + }, + $signature: 0 + }; + P._Future__chainForeignFuture_closure.prototype = { + call$1: function(value) { + var t1 = this.target; + H.assertHelper(t1._state === 1); + H.assertHelper(t1._state === 1); + t1._state = 0; + t1._complete$1(value); + }, + $signature: 3 + }; + P._Future__chainForeignFuture_closure0.prototype = { + call$2: function(error, stackTrace) { + var t1; + type$.StackTrace._check(stackTrace); + t1 = this.target; + H.assertHelper(t1._state === 1); + t1._completeError$2(error, stackTrace); + }, + call$1: function(error) { + return this.call$2(error, null); + }, + $signature: 80 + }; + P._Future__chainForeignFuture_closure1.prototype = { + call$0: function() { + this.target._completeError$2(this.e, this.s); + }, + $signature: 0 + }; + P._Future__asyncComplete_closure.prototype = { + call$0: function() { + var t1 = this.$this; + t1._completeWithValue$1(t1.$ti._precomputed1._check(this.value)); + }, + $signature: 0 + }; + P._Future__chainFuture_closure.prototype = { + call$0: function() { + P._Future__chainCoreFuture(this.value, this.$this); + }, + $signature: 0 + }; + P._Future__asyncCompleteError_closure.prototype = { + call$0: function() { + this.$this._completeError$2(this.error, this.stackTrace); + }, + $signature: 0 + }; + P._Future__propagateToListeners_handleWhenCompleteCallback.prototype = { + call$0: function() { + var completeResult, e, s, t3, exception, originalSource, _this = this, + t1 = _this.listener, + t2 = t1.state; + H.assertHelper((t2 & 1) === 0); + t3 = (t2 & 2) === 0; + H.assertHelper(t3); + completeResult = null; + try { + H.assertHelper(t3); + H.assertHelper((t2 & 15) === 8); + completeResult = t1.result._zone.run$1$1(type$.dynamic_Function._check(t1.callback), type$.dynamic); + } catch (exception) { + e = H.unwrapException(exception); + s = H.getTraceFromException(exception); + if (_this.hasError) { + t1 = _this._box_1.source; + H.assertHelper(t1._state === 8); + t1 = type$.AsyncError._check(t1._resultOrListeners).error; + t2 = e; + t2 = t1 == null ? t2 == null : t1 === t2; + t1 = t2; + } else + t1 = false; + t2 = _this._box_0; + if (t1) { + t1 = _this._box_1.source; + H.assertHelper(t1._state === 8); + t2.listenerValueOrError = type$.AsyncError._check(t1._resultOrListeners); + } else + t2.listenerValueOrError = new P.AsyncError(e, s); + t2.listenerHasError = true; + return; + } + if (type$.Future_dynamic._is(completeResult)) { + if (completeResult instanceof P._Future && completeResult._state >= 4) { + if (completeResult._state === 8) { + t1 = completeResult; + H.assertHelper(t1._state === 8); + t2 = _this._box_0; + t2.listenerValueOrError = type$.AsyncError._check(t1._resultOrListeners); + t2.listenerHasError = true; + } + return; + } + originalSource = _this._box_1.source; + t1 = _this._box_0; + t1.listenerValueOrError = completeResult.then$1$1(new P._Future__propagateToListeners_handleWhenCompleteCallback_closure(originalSource), type$.dynamic); + t1.listenerHasError = false; + } + }, + $signature: 1 + }; + P._Future__propagateToListeners_handleWhenCompleteCallback_closure.prototype = { + call$1: function(_) { + return this.originalSource; + }, + $signature: 75 + }; + P._Future__propagateToListeners_handleValueCallback.prototype = { + call$0: function() { + var e, s, t1, t2, t3, t4, exception, _this = this; + try { + t1 = _this.listener; + t2 = t1.$ti; + t3 = t2._precomputed1; + t4 = t3._check(_this.sourceResult); + H.assertHelper((t1.state & 1) !== 0); + _this._box_0.listenerValueOrError = t1.result._zone.runUnary$2$2(t2._eval$1("2/(1)")._check(t1.callback), t4, t2._eval$1("2/"), t3); + } catch (exception) { + e = H.unwrapException(exception); + s = H.getTraceFromException(exception); + t1 = _this._box_0; + t1.listenerValueOrError = new P.AsyncError(e, s); + t1.listenerHasError = true; + } + }, + $signature: 1 + }; + P._Future__propagateToListeners_handleError.prototype = { + call$0: function() { + var asyncError, e, s, t1, t2, exception, t3, t4, t5, _this = this; + try { + t1 = _this._box_1.source; + H.assertHelper(t1._state === 8); + asyncError = type$.AsyncError._check(t1._resultOrListeners); + t1 = _this.listener; + if (H.boolConversionCheck(t1.matchesErrorTest$1(asyncError))) { + H.assertHelper((t1.state & 2) !== 0); + t2 = t1.errorCallback != null; + } else + t2 = false; + if (t2) { + t2 = _this._box_0; + t2.listenerValueOrError = t1.handleError$1(asyncError); + t2.listenerHasError = false; + } + } catch (exception) { + e = H.unwrapException(exception); + s = H.getTraceFromException(exception); + t1 = _this._box_1; + t2 = t1.source; + H.assertHelper(t2._state === 8); + t3 = type$.AsyncError; + t2 = t3._check(t2._resultOrListeners).error; + t4 = e; + t5 = _this._box_0; + if (t2 == null ? t4 == null : t2 === t4) { + t1 = t1.source; + H.assertHelper(t1._state === 8); + t5.listenerValueOrError = t3._check(t1._resultOrListeners); + } else + t5.listenerValueOrError = new P.AsyncError(e, s); + t5.listenerHasError = true; + } + }, + $signature: 1 + }; + P._AsyncCallbackEntry.prototype = {}; + P.Stream.prototype = { + get$isBroadcast: function() { + return false; + }, + pipe$1: function(streamConsumer) { + H._instanceType(this)._eval$1("StreamConsumer<Stream.T>")._check(streamConsumer); + return streamConsumer.addStream$1(this).then$1$1(new P.Stream_pipe_closure(streamConsumer), type$.dynamic); + }, + get$length: function(_) { + var t1 = {}, + future = new P._Future($.Zone__current, type$._Future_int); + t1.count = 0; + this.listen$4$cancelOnError$onDone$onError(new P.Stream_length_closure(t1, this), true, new P.Stream_length_closure0(t1, future), future.get$_completeError()); + return future; + }, + get$first: function(_) { + var t1 = {}, + future = new P._Future($.Zone__current, H._instanceType(this)._eval$1("_Future<Stream.T>")); + t1.subscription = null; + t1.subscription = this.listen$4$cancelOnError$onDone$onError(new P.Stream_first_closure(t1, this, future), true, new P.Stream_first_closure0(future), future.get$_completeError()); + return future; + }, + get$last: function(_) { + var t1 = {}, + future = new P._Future($.Zone__current, H._instanceType(this)._eval$1("_Future<Stream.T>")); + t1.result = null; + t1.foundResult = false; + this.listen$4$cancelOnError$onDone$onError(new P.Stream_last_closure(t1, this), true, new P.Stream_last_closure0(t1, future), future.get$_completeError()); + return future; + }, + firstWhere$1: function(_, test) { + var future, _this = this, t1 = {}, + t2 = H._instanceType(_this); + t2._eval$1("bool(Stream.T)")._check(test); + t2._eval$1("Stream.T()")._check(null); + future = new P._Future($.Zone__current, t2._eval$1("_Future<Stream.T>")); + t1.subscription = null; + t1.subscription = _this.listen$4$cancelOnError$onDone$onError(new P.Stream_firstWhere_closure(t1, _this, test, future), true, new P.Stream_firstWhere_closure0(_this, null, future), future.get$_completeError()); + return future; + } + }; + P.Stream_Stream$fromFuture_closure.prototype = { + call$1: function(value) { + var t1 = this.controller; + t1._add$1(this.T._check(value)); + t1._closeUnchecked$0(); + }, + $signature: function() { + return this.T._eval$1("Null(0)"); + } + }; + P.Stream_Stream$fromFuture_closure0.prototype = { + call$2: function(error, stackTrace) { + var t1 = this.controller; + t1._async$_addError$2(error, type$.StackTrace._check(stackTrace)); + t1._closeUnchecked$0(); + }, + $signature: 6 + }; + P.Stream_Stream$fromIterable_closure.prototype = { + call$0: function() { + var t1 = this.elements; + return new P._IterablePendingEvents(new J.ArrayIterator(t1, 0, H._arrayInstanceType(t1)._eval$1("ArrayIterator<1>")), this.T._eval$1("_IterablePendingEvents<0>")); + }, + $signature: function() { + return this.T._eval$1("_IterablePendingEvents<0>()"); + } + }; + P.Stream_pipe_closure.prototype = { + call$1: function(_) { + return this.streamConsumer.close$0(0); + }, + $signature: 73 + }; + P.Stream_length_closure.prototype = { + call$1: function(_) { + H._instanceType(this.$this)._eval$1("Stream.T")._check(_); + ++this._box_0.count; + }, + $signature: function() { + return H._instanceType(this.$this)._eval$1("Null(Stream.T)"); + } + }; + P.Stream_length_closure0.prototype = { + call$0: function() { + this.future._complete$1(this._box_0.count); + }, + $signature: 0 + }; + P.Stream_first_closure.prototype = { + call$1: function(value) { + H._instanceType(this.$this)._eval$1("Stream.T")._check(value); + P._cancelAndValue(this._box_0.subscription, this.future, value); + }, + $signature: function() { + return H._instanceType(this.$this)._eval$1("Null(Stream.T)"); + } + }; + P.Stream_first_closure0.prototype = { + call$0: function() { + var e, s, t1, exception; + try { + t1 = H.IterableElementError_noElement(); + throw H.wrapException(t1); + } catch (exception) { + e = H.unwrapException(exception); + s = H.getTraceFromException(exception); + P._completeWithErrorCallback(this.future, e, s); + } + }, + $signature: 0 + }; + P.Stream_last_closure.prototype = { + call$1: function(value) { + var t1; + H._instanceType(this.$this)._eval$1("Stream.T")._check(value); + t1 = this._box_0; + t1.foundResult = true; + t1.result = value; + }, + $signature: function() { + return H._instanceType(this.$this)._eval$1("Null(Stream.T)"); + } + }; + P.Stream_last_closure0.prototype = { + call$0: function() { + var e, s, exception, + t1 = this._box_0; + if (t1.foundResult) { + this.future._complete$1(t1.result); + return; + } + try { + t1 = H.IterableElementError_noElement(); + throw H.wrapException(t1); + } catch (exception) { + e = H.unwrapException(exception); + s = H.getTraceFromException(exception); + P._completeWithErrorCallback(this.future, e, s); + } + }, + $signature: 0 + }; + P.Stream_firstWhere_closure.prototype = { + call$1: function(value) { + var t1, t2, _this = this; + H._instanceType(_this.$this)._eval$1("Stream.T")._check(value); + t1 = _this._box_0; + t2 = _this.future; + P._runUserCode(new P.Stream_firstWhere__closure(_this.test, value), new P.Stream_firstWhere__closure0(t1, t2, value), P._cancelAndErrorClosure(t1.subscription, t2), type$.bool); + }, + $signature: function() { + return H._instanceType(this.$this)._eval$1("Null(Stream.T)"); + } + }; + P.Stream_firstWhere__closure.prototype = { + call$0: function() { + return this.test.call$1(this.value); + }, + $signature: 49 + }; + P.Stream_firstWhere__closure0.prototype = { + call$1: function(isMatch) { + if (H.boolConversionCheck(H._checkBoolNullable(isMatch))) + P._cancelAndValue(this._box_0.subscription, this.future, this.value); + }, + $signature: 43 + }; + P.Stream_firstWhere_closure0.prototype = { + call$0: function() { + var e, s, t1, exception; + try { + t1 = H.IterableElementError_noElement(); + throw H.wrapException(t1); + } catch (exception) { + e = H.unwrapException(exception); + s = H.getTraceFromException(exception); + P._completeWithErrorCallback(this.future, e, s); + } + }, + $signature: 0 + }; + P.StreamSubscription.prototype = {}; + P.StreamTransformerBase.prototype = {$isStreamTransformer: 1}; + P._StreamController.prototype = { + get$_pendingEvents: function() { + var t1, _this = this; + H.assertHelper((_this._state & 3) === 0); + if ((_this._state & 8) === 0) + return H._instanceType(_this)._eval$1("_PendingEvents<1>")._check(_this._varData); + t1 = H._instanceType(_this); + return t1._eval$1("_PendingEvents<1>")._check(t1._eval$1("_StreamControllerAddStreamState<1>")._check(_this._varData).varData); + }, + _ensurePendingEvents$0: function() { + var t1, state, t2, _this = this; + H.assertHelper((_this._state & 3) === 0); + if ((_this._state & 8) === 0) { + t1 = _this._varData; + if (t1 == null) + t1 = _this._varData = new P._StreamImplEvents(H._instanceType(_this)._eval$1("_StreamImplEvents<1>")); + return H._instanceType(_this)._eval$1("_StreamImplEvents<1>")._check(t1); + } + t1 = H._instanceType(_this); + state = t1._eval$1("_StreamControllerAddStreamState<1>")._check(_this._varData); + t2 = state.varData; + if (t2 == null) + t2 = state.varData = new P._StreamImplEvents(t1._eval$1("_StreamImplEvents<1>")); + return t1._eval$1("_StreamImplEvents<1>")._check(t2); + }, + get$_async$_subscription: function() { + var t1, _this = this; + H.assertHelper((_this._state & 1) !== 0); + if ((_this._state & 8) !== 0) { + t1 = H._instanceType(_this); + return t1._eval$1("_ControllerSubscription<1>")._check(t1._eval$1("_StreamControllerAddStreamState<1>")._check(_this._varData).varData); + } + return H._instanceType(_this)._eval$1("_ControllerSubscription<1>")._check(_this._varData); + }, + _badEventState$0: function() { + var t1 = this._state; + if ((t1 & 4) !== 0) + return new P.StateError("Cannot add event after closing"); + H.assertHelper((t1 & 8) !== 0); + return new P.StateError("Cannot add event while adding a stream"); + }, + addStream$2$cancelOnError: function(source, cancelOnError) { + var t2, t3, t4, t5, _this = this, + t1 = H._instanceType(_this); + t1._eval$1("Stream<1>")._check(source); + t2 = _this._state; + if (t2 >= 4) + throw H.wrapException(_this._badEventState$0()); + if ((t2 & 2) !== 0) { + t1 = new P._Future($.Zone__current, type$._Future_dynamic); + t1._asyncComplete$1(null); + return t1; + } + t2 = _this._varData; + t3 = cancelOnError === true; + t4 = new P._Future($.Zone__current, type$._Future_dynamic); + t5 = t3 ? P._AddStreamState_makeErrorHandler(_this) : _this.get$_async$_addError(); + t5 = source.listen$4$cancelOnError$onDone$onError(_this.get$_add(), t3, _this.get$_close(), t5); + t3 = _this._state; + if ((t3 & 1) !== 0 ? (_this.get$_async$_subscription()._state & 4) !== 0 : (t3 & 2) === 0) + t5.pause$0(); + _this._varData = new P._StreamControllerAddStreamState(t2, t4, t5, t1._eval$1("_StreamControllerAddStreamState<1>")); + _this._state |= 8; + return t4; + }, + _ensureDoneFuture$0: function() { + var t1 = this._doneFuture; + if (t1 == null) + t1 = this._doneFuture = (this._state & 2) !== 0 ? $.$get$Future__nullFuture() : new P._Future($.Zone__current, type$._Future_dynamic); + return t1; + }, + add$1: function(_, value) { + var _this = this; + H._instanceType(_this)._precomputed1._check(value); + if (_this._state >= 4) + throw H.wrapException(_this._badEventState$0()); + _this._add$1(value); + }, + addError$2: function(error, stackTrace) { + var replacement; + type$.StackTrace._check(stackTrace); + if (this._state >= 4) + throw H.wrapException(this._badEventState$0()); + if (error == null) + error = new P.NullThrownError(); + replacement = $.Zone__current.errorCallback$2(error, stackTrace); + if (replacement != null) { + error = replacement.error; + if (error == null) + error = new P.NullThrownError(); + stackTrace = replacement.stackTrace; + } + this._async$_addError$2(error, stackTrace); + }, + addError$1: function(error) { + return this.addError$2(error, null); + }, + close$0: function(_) { + var _this = this, + t1 = _this._state; + if ((t1 & 4) !== 0) + return _this._ensureDoneFuture$0(); + if (t1 >= 4) + throw H.wrapException(_this._badEventState$0()); + _this._closeUnchecked$0(); + return _this._ensureDoneFuture$0(); + }, + _closeUnchecked$0: function() { + var t1 = this._state |= 4; + if ((t1 & 1) !== 0) + this._sendDone$0(); + else if ((t1 & 3) === 0) + this._ensurePendingEvents$0().add$1(0, C.C__DelayedDone); + }, + _add$1: function(value) { + var t2, _this = this, + t1 = H._instanceType(_this); + t1._precomputed1._check(value); + t2 = _this._state; + if ((t2 & 1) !== 0) + _this._sendData$1(value); + else if ((t2 & 3) === 0) + _this._ensurePendingEvents$0().add$1(0, new P._DelayedData(value, t1._eval$1("_DelayedData<1>"))); + }, + _async$_addError$2: function(error, stackTrace) { + var t1; + type$.StackTrace._check(stackTrace); + t1 = this._state; + if ((t1 & 1) !== 0) + this._sendError$2(error, stackTrace); + else if ((t1 & 3) === 0) + this._ensurePendingEvents$0().add$1(0, new P._DelayedError(error, stackTrace)); + }, + _close$0: function() { + var addState, _this = this; + H.assertHelper((_this._state & 8) !== 0); + addState = H._instanceType(_this)._eval$1("_StreamControllerAddStreamState<1>")._check(_this._varData); + _this._varData = addState.varData; + _this._state &= 4294967287; + addState.addStreamFuture._asyncComplete$1(null); + }, + _subscribe$4: function(onData, onError, onDone, cancelOnError) { + var t2, t3, subscription, pendingEvents, addState, _this = this, + t1 = H._instanceType(_this); + t1._eval$1("~(1)")._check(onData); + type$.void_Function._check(onDone); + if ((_this._state & 3) !== 0) + throw H.wrapException(P.StateError$("Stream has already been listened to.")); + t2 = $.Zone__current; + t3 = cancelOnError ? 1 : 0; + subscription = new P._ControllerSubscription(_this, t2, t3, t1._eval$1("_ControllerSubscription<1>")); + subscription._BufferingStreamSubscription$4(onData, onError, onDone, cancelOnError, t1._precomputed1); + pendingEvents = _this.get$_pendingEvents(); + t3 = _this._state |= 1; + if ((t3 & 8) !== 0) { + addState = t1._eval$1("_StreamControllerAddStreamState<1>")._check(_this._varData); + addState.varData = subscription; + addState.addSubscription.resume$0(); + } else + _this._varData = subscription; + subscription._setPendingEvents$1(pendingEvents); + subscription._guardCallback$1(new P._StreamController__subscribe_closure(_this)); + return subscription; + }, + _recordCancel$1: function(subscription) { + var result, e, s, exception, result0, _this = this, + t1 = H._instanceType(_this); + t1._eval$1("StreamSubscription<1>")._check(subscription); + result = null; + if ((_this._state & 8) !== 0) + result = t1._eval$1("_StreamControllerAddStreamState<1>")._check(_this._varData).cancel$0(); + _this._varData = null; + _this._state = _this._state & 4294967286 | 2; + t1 = _this.onCancel; + if (t1 != null) + if (result == null) + try { + result = type$.Future_dynamic._check(t1.call$0()); + } catch (exception) { + e = H.unwrapException(exception); + s = H.getTraceFromException(exception); + result0 = new P._Future($.Zone__current, type$._Future_dynamic); + result0._asyncCompleteError$2(e, s); + result = result0; + } + else + result = result.whenComplete$1(t1); + t1 = new P._StreamController__recordCancel_complete(_this); + if (result != null) + result = result.whenComplete$1(t1); + else + t1.call$0(); + return result; + }, + _recordPause$1: function(subscription) { + var _this = this, + t1 = H._instanceType(_this); + t1._eval$1("StreamSubscription<1>")._check(subscription); + if ((_this._state & 8) !== 0) + t1._eval$1("_StreamControllerAddStreamState<1>")._check(_this._varData).addSubscription.pause$0(); + P._runGuarded(_this.onPause); + }, + _recordResume$1: function(subscription) { + var _this = this, + t1 = H._instanceType(_this); + t1._eval$1("StreamSubscription<1>")._check(subscription); + if ((_this._state & 8) !== 0) + t1._eval$1("_StreamControllerAddStreamState<1>")._check(_this._varData).addSubscription.resume$0(); + P._runGuarded(_this.onResume); + }, + $isEventSink: 1, + $isStreamConsumer: 1, + $isStreamSink: 1, + $isStreamController: 1, + $is_StreamControllerLifecycle: 1, + $is_EventDispatch: 1, + $isSink: 1 + }; + P._StreamController__subscribe_closure.prototype = { + call$0: function() { + P._runGuarded(this.$this.onListen); + }, + $signature: 0 + }; + P._StreamController__recordCancel_complete.prototype = { + call$0: function() { + var t1 = this.$this._doneFuture; + if (t1 != null && t1._state === 0) + t1._asyncComplete$1(null); + }, + $signature: 1 + }; + P._SyncStreamControllerDispatch.prototype = { + _sendData$1: function(data) { + this.$ti._precomputed1._check(data); + this.get$_async$_subscription()._add$1(data); + }, + _sendError$2: function(error, stackTrace) { + this.get$_async$_subscription()._async$_addError$2(error, stackTrace); + }, + _sendDone$0: function() { + this.get$_async$_subscription()._close$0(); + } + }; + P._AsyncStreamControllerDispatch.prototype = { + _sendData$1: function(data) { + var t1 = this.$ti; + t1._precomputed1._check(data); + this.get$_async$_subscription()._addPending$1(new P._DelayedData(data, t1._eval$1("_DelayedData<1>"))); + }, + _sendError$2: function(error, stackTrace) { + this.get$_async$_subscription()._addPending$1(new P._DelayedError(error, stackTrace)); + }, + _sendDone$0: function() { + this.get$_async$_subscription()._addPending$1(C.C__DelayedDone); + } + }; + P._AsyncStreamController.prototype = {}; + P._SyncStreamController.prototype = {}; + P._ControllerStream.prototype = { + _createSubscription$4: function(onData, onError, onDone, cancelOnError) { + return this._controller._subscribe$4(H._instanceType(this)._eval$1("~(1)")._check(onData), onError, type$.void_Function._check(onDone), cancelOnError); + }, + get$hashCode: function(_) { + return (H.Primitives_objectHashCode(this._controller) ^ 892482866) >>> 0; + }, + $eq: function(_, other) { + if (other == null) + return false; + if (this === other) + return true; + return other instanceof P._ControllerStream && other._controller === this._controller; + } + }; + P._ControllerSubscription.prototype = { + _onCancel$0: function() { + return this._controller._recordCancel$1(this); + }, + _onPause$0: function() { + this._controller._recordPause$1(this); + }, + _onResume$0: function() { + this._controller._recordResume$1(this); + } + }; + P._StreamSinkWrapper.prototype = { + add$1: function(_, data) { + this._async$_target.add$1(0, this.$ti._precomputed1._check(data)); + }, + $isEventSink: 1, + $isStreamConsumer: 1, + $isStreamSink: 1, + $isSink: 1 + }; + P._AddStreamState.prototype = { + cancel$0: function() { + var cancel = this.addSubscription.cancel$0(); + if (cancel == null) { + this.addStreamFuture._asyncComplete$1(null); + return null; + } + return cancel.whenComplete$1(new P._AddStreamState_cancel_closure(this)); + } + }; + P._AddStreamState_makeErrorHandler_closure.prototype = { + call$2: function(e, s) { + var t1 = this.controller; + t1._async$_addError$2(e, type$.StackTrace._check(s)); + t1._close$0(); + }, + $signature: 5 + }; + P._AddStreamState_cancel_closure.prototype = { + call$0: function() { + this.$this.addStreamFuture._asyncComplete$1(null); + }, + $signature: 0 + }; + P._StreamControllerAddStreamState.prototype = {}; + P._BufferingStreamSubscription.prototype = { + _BufferingStreamSubscription$4: function(onData, onError, onDone, cancelOnError, $T) { + this.onData$1(onData); + this.onError$1(0, onError); + this.onDone$1(onDone); + }, + _setPendingEvents$1: function(pendingEvents) { + var _this = this; + H._instanceType(_this)._eval$1("_PendingEvents<_BufferingStreamSubscription.T>")._check(pendingEvents); + H.assertHelper(_this._pending == null); + if (pendingEvents == null) + return; + _this.set$_pending(pendingEvents); + if (!pendingEvents.get$isEmpty(pendingEvents)) { + _this._state = (_this._state | 64) >>> 0; + _this._pending.schedule$1(_this); + } + }, + onData$1: function(handleData) { + var t1 = H._instanceType(this); + t1._eval$1("~(_BufferingStreamSubscription.T)")._check(handleData); + if (handleData == null) + handleData = P.async___nullDataHandler$closure(); + this.set$_onData(this._zone.registerUnaryCallback$2$1(handleData, type$.dynamic, t1._eval$1("_BufferingStreamSubscription.T"))); + }, + onError$1: function(_, handleError) { + var _this = this; + if (handleError == null) + handleError = P.async___nullErrorHandler$closure(); + if (type$.void_Function_Object_StackTrace._is(handleError)) + _this._onError = _this._zone.registerBinaryCallback$3$1(handleError, type$.dynamic, type$.Object, type$.StackTrace); + else if (type$.void_Function_Object._is(handleError)) + _this._onError = _this._zone.registerUnaryCallback$2$1(handleError, type$.dynamic, type$.Object); + else + throw H.wrapException(P.ArgumentError$("handleError callback must take either an Object (the error), or both an Object (the error) and a StackTrace.")); + }, + onDone$1: function(handleDone) { + type$.void_Function._check(handleDone); + if (handleDone == null) + handleDone = P.async___nullDoneHandler$closure(); + this.set$_onDone(this._zone.registerCallback$1$1(handleDone, type$.void)); + }, + pause$1: function(resumeSignal) { + var t2, t3, _this = this, + t1 = _this._state; + if ((t1 & 8) !== 0) + return; + t2 = (t1 + 128 | 4) >>> 0; + _this._state = t2; + if (t1 < 128 && _this._pending != null) { + t3 = _this._pending; + if (t3._state === 1) + t3._state = 3; + } + if ((t1 & 4) === 0 && (t2 & 32) === 0) + _this._guardCallback$1(_this.get$_onPause()); + }, + pause$0: function() { + return this.pause$1(null); + }, + resume$0: function() { + var _this = this, + t1 = _this._state; + if ((t1 & 8) !== 0) + return; + if (t1 >= 128) { + t1 = _this._state -= 128; + if (t1 < 128) { + if ((t1 & 64) !== 0) { + t1 = _this._pending; + t1 = !t1.get$isEmpty(t1); + } else + t1 = false; + if (t1) + _this._pending.schedule$1(_this); + else { + H.assertHelper(_this.get$_mayResumeInput()); + t1 = (_this._state & 4294967291) >>> 0; + _this._state = t1; + if ((t1 & 32) === 0) + _this._guardCallback$1(_this.get$_onResume()); + } + } + } + }, + cancel$0: function() { + var _this = this, + t1 = (_this._state & 4294967279) >>> 0; + _this._state = t1; + if ((t1 & 8) === 0) + _this._cancel$0(); + t1 = _this._cancelFuture; + return t1 == null ? $.$get$Future__nullFuture() : t1; + }, + get$_mayResumeInput: function() { + if (this._state < 128) { + var t1 = this._pending; + t1 = t1 == null || t1.get$isEmpty(t1); + } else + t1 = false; + return t1; + }, + get$isPaused: function() { + return this._state >= 128; + }, + _cancel$0: function() { + var t2, _this = this, + t1 = _this._state = (_this._state | 8) >>> 0; + if ((t1 & 64) !== 0) { + t2 = _this._pending; + if (t2._state === 1) + t2._state = 3; + } + if ((t1 & 32) === 0) + _this.set$_pending(null); + _this._cancelFuture = _this._onCancel$0(); + }, + _add$1: function(data) { + var t2, _this = this, + t1 = H._instanceType(_this); + t1._eval$1("_BufferingStreamSubscription.T")._check(data); + H.assertHelper((_this._state & 2) === 0); + t2 = _this._state; + if ((t2 & 8) !== 0) + return; + if (t2 < 32) + _this._sendData$1(data); + else + _this._addPending$1(new P._DelayedData(data, t1._eval$1("_DelayedData<_BufferingStreamSubscription.T>"))); + }, + _async$_addError$2: function(error, stackTrace) { + var t1 = this._state; + if ((t1 & 8) !== 0) + return; + if (t1 < 32) + this._sendError$2(error, stackTrace); + else + this._addPending$1(new P._DelayedError(error, stackTrace)); + }, + _close$0: function() { + var t1, _this = this; + H.assertHelper((_this._state & 2) === 0); + t1 = _this._state; + if ((t1 & 8) !== 0) + return; + t1 = (t1 | 2) >>> 0; + _this._state = t1; + if (t1 < 32) + _this._sendDone$0(); + else + _this._addPending$1(C.C__DelayedDone); + }, + _onPause$0: function() { + H.assertHelper((this._state & 4) !== 0); + }, + _onResume$0: function() { + H.assertHelper((this._state & 4) === 0); + }, + _onCancel$0: function() { + H.assertHelper((this._state & 8) !== 0); + return null; + }, + _addPending$1: function($event) { + var _this = this, + t1 = H._instanceType(_this)._eval$1("_StreamImplEvents<_BufferingStreamSubscription.T>"), + pending = t1._check(_this._pending); + if (pending == null) { + pending = new P._StreamImplEvents(t1); + _this.set$_pending(pending); + } + pending.add$1(0, $event); + t1 = _this._state; + if ((t1 & 64) === 0) { + t1 = (t1 | 64) >>> 0; + _this._state = t1; + if (t1 < 128) + _this._pending.schedule$1(_this); + } + }, + _sendData$1: function(data) { + var t2, _this = this, + t1 = H._instanceType(_this)._eval$1("_BufferingStreamSubscription.T"); + t1._check(data); + H.assertHelper((_this._state & 8) === 0); + H.assertHelper(_this._state < 128); + H.assertHelper((_this._state & 32) === 0); + t2 = _this._state; + _this._state = (t2 | 32) >>> 0; + _this._zone.runUnaryGuarded$1$2(_this._onData, data, t1); + _this._state = (_this._state & 4294967263) >>> 0; + _this._checkState$1((t2 & 4) !== 0); + }, + _sendError$2: function(error, stackTrace) { + var t1, t2, _this = this; + type$.StackTrace._check(stackTrace); + H.assertHelper((_this._state & 8) === 0); + H.assertHelper(_this._state < 128); + H.assertHelper((_this._state & 32) === 0); + t1 = _this._state; + t2 = new P._BufferingStreamSubscription__sendError_sendError(_this, error, stackTrace); + if ((t1 & 1) !== 0) { + _this._state = (t1 | 16) >>> 0; + _this._cancel$0(); + t1 = _this._cancelFuture; + if (t1 != null && t1 !== $.$get$Future__nullFuture()) + t1.whenComplete$1(t2); + else + t2.call$0(); + } else { + t2.call$0(); + _this._checkState$1((t1 & 4) !== 0); + } + }, + _sendDone$0: function() { + var t1, t2, _this = this; + H.assertHelper((_this._state & 8) === 0); + H.assertHelper(_this._state < 128); + H.assertHelper((_this._state & 32) === 0); + t1 = new P._BufferingStreamSubscription__sendDone_sendDone(_this); + _this._cancel$0(); + _this._state = (_this._state | 16) >>> 0; + t2 = _this._cancelFuture; + if (t2 != null && t2 !== $.$get$Future__nullFuture()) + t2.whenComplete$1(t1); + else + t1.call$0(); + }, + _guardCallback$1: function(callback) { + var t1, _this = this; + type$.void_Function._check(callback); + H.assertHelper((_this._state & 32) === 0); + t1 = _this._state; + _this._state = (t1 | 32) >>> 0; + callback.call$0(); + _this._state = (_this._state & 4294967263) >>> 0; + _this._checkState$1((t1 & 4) !== 0); + }, + _checkState$1: function(wasInputPaused) { + var t1, isInputPaused, _this = this; + H.assertHelper((_this._state & 32) === 0); + if ((_this._state & 64) !== 0) { + t1 = _this._pending; + t1 = t1.get$isEmpty(t1); + } else + t1 = false; + if (t1) { + t1 = (_this._state & 4294967231) >>> 0; + _this._state = t1; + if ((t1 & 4) !== 0 && _this.get$_mayResumeInput()) + _this._state = (_this._state & 4294967291) >>> 0; + } + for (; true; wasInputPaused = isInputPaused) { + t1 = _this._state; + if ((t1 & 8) !== 0) { + _this.set$_pending(null); + return; + } + isInputPaused = (t1 & 4) !== 0; + if (wasInputPaused === isInputPaused) + break; + _this._state = (t1 ^ 32) >>> 0; + if (isInputPaused) + _this._onPause$0(); + else + _this._onResume$0(); + _this._state = (_this._state & 4294967263) >>> 0; + } + t1 = _this._state; + if ((t1 & 64) !== 0 && t1 < 128) + _this._pending.schedule$1(_this); + }, + set$_onData: function(_onData) { + this._onData = H._instanceType(this)._eval$1("~(_BufferingStreamSubscription.T)")._check(_onData); + }, + set$_onDone: function(_onDone) { + this._onDone = type$.void_Function._check(_onDone); + }, + set$_pending: function(_pending) { + this._pending = H._instanceType(this)._eval$1("_PendingEvents<_BufferingStreamSubscription.T>")._check(_pending); + }, + $isStreamSubscription: 1, + $is_EventDispatch: 1 + }; + P._BufferingStreamSubscription__sendError_sendError.prototype = { + call$0: function() { + var onError, t3, t4, t5, + t1 = this.$this, + t2 = t1._state; + if ((t2 & 8) !== 0 && (t2 & 16) === 0) + return; + t1._state = (t2 | 32) >>> 0; + onError = t1._onError; + t2 = this.error; + t3 = type$.Object; + t4 = t1._zone; + if (type$.void_Function_Object_StackTrace._is(onError)) + t4.runBinaryGuarded$2$3(onError, t2, this.stackTrace, t3, type$.StackTrace); + else { + t5 = type$.void_Function_Object; + H.assertHelper(t5._is(onError)); + t4.runUnaryGuarded$1$2(t5._check(t1._onError), t2, t3); + } + t1._state = (t1._state & 4294967263) >>> 0; + }, + $signature: 1 + }; + P._BufferingStreamSubscription__sendDone_sendDone.prototype = { + call$0: function() { + var t1 = this.$this, + t2 = t1._state; + if ((t2 & 16) === 0) + return; + t1._state = (t2 | 42) >>> 0; + t1._zone.runGuarded$1(t1._onDone); + t1._state = (t1._state & 4294967263) >>> 0; + }, + $signature: 1 + }; + P._StreamImpl.prototype = { + listen$4$cancelOnError$onDone$onError: function(onData, cancelOnError, onDone, onError) { + return this._createSubscription$4(H._instanceType(this)._eval$1("~(1)")._check(onData), onError, type$.void_Function._check(onDone), true === H._checkBoolNullable(cancelOnError)); + }, + listen$2$onDone: function(onData, onDone) { + return this.listen$4$cancelOnError$onDone$onError(onData, null, onDone, null); + }, + listen$3$onDone$onError: function(onData, onDone, onError) { + return this.listen$4$cancelOnError$onDone$onError(onData, null, onDone, onError); + }, + listen$1: function(onData) { + return this.listen$4$cancelOnError$onDone$onError(onData, null, null, null); + }, + _createSubscription$4: function(onData, onError, onDone, cancelOnError) { + var t1 = H._instanceType(this); + return P._BufferingStreamSubscription$(t1._eval$1("~(1)")._check(onData), onError, type$.void_Function._check(onDone), cancelOnError, t1._precomputed1); + } + }; + P._GeneratedStreamImpl.prototype = { + _createSubscription$4: function(onData, onError, onDone, cancelOnError) { + var _this = this, + t1 = _this.$ti; + t1._eval$1("~(1)")._check(onData); + type$.void_Function._check(onDone); + if (_this._isUsed) + throw H.wrapException(P.StateError$("Stream has already been listened to.")); + _this._isUsed = true; + t1 = P._BufferingStreamSubscription$(onData, onError, onDone, cancelOnError, t1._precomputed1); + t1._setPendingEvents$1(_this._pending.call$0()); + return t1; + } + }; + P._IterablePendingEvents.prototype = { + get$isEmpty: function(_) { + return this._async$_iterator == null; + }, + handleNext$1: function(dispatch) { + var hasMore, e, s, t1, exception, _this = this; + _this.$ti._eval$1("_EventDispatch<1>")._check(dispatch); + t1 = _this._async$_iterator; + if (t1 == null) + throw H.wrapException(P.StateError$("No events pending.")); + hasMore = null; + try { + hasMore = t1.moveNext$0(); + if (H.boolConversionCheck(hasMore)) + dispatch._sendData$1(_this._async$_iterator.get$current()); + else { + _this.set$_async$_iterator(null); + dispatch._sendDone$0(); + } + } catch (exception) { + e = H.unwrapException(exception); + s = H.getTraceFromException(exception); + if (hasMore == null) { + _this.set$_async$_iterator(C.C_EmptyIterator); + dispatch._sendError$2(e, s); + } else + dispatch._sendError$2(e, s); + } + }, + set$_async$_iterator: function(_iterator) { + this._async$_iterator = this.$ti._eval$1("Iterator<1>")._check(_iterator); + } + }; + P._DelayedEvent.prototype = { + set$next: function(next) { + this.next = type$._DelayedEvent_dynamic._check(next); + }, + get$next: function() { + return this.next; + } + }; + P._DelayedData.prototype = { + perform$1: function(dispatch) { + this.$ti._eval$1("_EventDispatch<1>")._check(dispatch)._sendData$1(this.value); + } + }; + P._DelayedError.prototype = { + perform$1: function(dispatch) { + dispatch._sendError$2(this.error, this.stackTrace); + } + }; + P._DelayedDone.prototype = { + perform$1: function(dispatch) { + dispatch._sendDone$0(); + }, + get$next: function() { + return null; + }, + set$next: function(_) { + throw H.wrapException(P.StateError$("No events after a done.")); + }, + $is_DelayedEvent: 1 + }; + P._PendingEvents.prototype = { + schedule$1: function(dispatch) { + var t1, _this = this; + H._instanceType(_this)._eval$1("_EventDispatch<1>")._check(dispatch); + if (_this._state === 1) + return; + H.assertHelper(!_this.get$isEmpty(_this)); + t1 = _this._state; + if (t1 >= 1) { + H.assertHelper(t1 === 3); + _this._state = 1; + return; + } + P.scheduleMicrotask(new P._PendingEvents_schedule_closure(_this, dispatch)); + _this._state = 1; + } + }; + P._PendingEvents_schedule_closure.prototype = { + call$0: function() { + var t1 = this.$this, + oldState = t1._state; + t1._state = 0; + if (oldState === 3) + return; + t1.handleNext$1(this.dispatch); + }, + $signature: 0 + }; + P._StreamImplEvents.prototype = { + get$isEmpty: function(_) { + return this.lastPendingEvent == null; + }, + add$1: function(_, $event) { + var _this = this, + t1 = _this.lastPendingEvent; + if (t1 == null) + _this.firstPendingEvent = _this.lastPendingEvent = $event; + else { + t1.set$next($event); + _this.lastPendingEvent = $event; + } + }, + handleNext$1: function(dispatch) { + var $event, t1, _this = this; + _this.$ti._eval$1("_EventDispatch<1>")._check(dispatch); + H.assertHelper(_this._state !== 1); + $event = _this.firstPendingEvent; + t1 = $event.get$next(); + _this.firstPendingEvent = t1; + if (t1 == null) + _this.lastPendingEvent = null; + $event.perform$1(dispatch); + } + }; + P._DoneStreamSubscription.prototype = { + get$isPaused: function() { + return this._state >= 4; + }, + _schedule$0: function() { + var _this = this; + if ((_this._state & 2) !== 0) + return; + _this._zone.scheduleMicrotask$1(_this.get$_sendDone()); + _this._state = (_this._state | 2) >>> 0; + }, + onData$1: function(handleData) { + this.$ti._eval$1("~(1)")._check(handleData); + }, + onError$1: function(_, handleError) { + }, + onDone$1: function(handleDone) { + this.set$_onDone(type$.void_Function._check(handleDone)); + }, + pause$1: function(resumeSignal) { + this._state += 4; + }, + pause$0: function() { + return this.pause$1(null); + }, + resume$0: function() { + var t1 = this._state; + if (t1 >= 4) { + t1 = this._state = t1 - 4; + if (t1 < 4 && (t1 & 1) === 0) + this._schedule$0(); + } + }, + cancel$0: function() { + return $.$get$Future__nullFuture(); + }, + _sendDone$0: function() { + var _this = this, + t1 = _this._state = (_this._state & 4294967293) >>> 0; + if (t1 >= 4) + return; + _this._state = (t1 | 1) >>> 0; + t1 = _this._onDone; + if (t1 != null) + _this._zone.runGuarded$1(t1); + }, + set$_onDone: function(_onDone) { + this._onDone = type$.void_Function._check(_onDone); + }, + $isStreamSubscription: 1 + }; + P._StreamIterator.prototype = {}; + P._EmptyStream.prototype = { + get$isBroadcast: function() { + return true; + }, + listen$4$cancelOnError$onDone$onError: function(onData, cancelOnError, onDone, onError) { + var t1 = this.$ti; + t1._eval$1("~(1)")._check(onData); + type$.void_Function._check(onDone); + H._checkBoolNullable(cancelOnError); + t1 = new P._DoneStreamSubscription($.Zone__current, onDone, t1._eval$1("_DoneStreamSubscription<1>")); + t1._schedule$0(); + return t1; + }, + listen$3$onDone$onError: function(onData, onDone, onError) { + return this.listen$4$cancelOnError$onDone$onError(onData, null, onDone, onError); + }, + listen$1: function(onData) { + return this.listen$4$cancelOnError$onDone$onError(onData, null, null, null); + } + }; + P._cancelAndError_closure.prototype = { + call$0: function() { + return this.future._completeError$2(this.error, this.stackTrace); + }, + $signature: 1 + }; + P._cancelAndErrorClosure_closure.prototype = { + call$2: function(error, stackTrace) { + P._cancelAndError(this.subscription, this.future, error, type$.StackTrace._check(stackTrace)); + }, + $signature: 5 + }; + P._cancelAndValue_closure.prototype = { + call$0: function() { + return this.future._complete$1(this.value); + }, + $signature: 1 + }; + P.Timer.prototype = {}; + P.AsyncError.prototype = { + toString$0: function(_) { + return H.S(this.error); + }, + $isError: 1 + }; + P._ZoneFunction.prototype = {}; + P.ZoneSpecification.prototype = {}; + P._ZoneSpecification.prototype = {$isZoneSpecification: 1}; + P.ZoneDelegate.prototype = {}; + P.Zone.prototype = {}; + P._ZoneDelegate.prototype = { + handleUncaughtError$3: function(zone, error, stackTrace) { + var implementation, implZone; + type$.StackTrace._check(stackTrace); + implementation = this._delegationTarget.get$_handleUncaughtError(); + implZone = implementation.zone; + return implementation.$function.call$5(implZone, P._parentDelegate(implZone), zone, error, stackTrace); + }, + registerCallback$1$2: function(zone, f, $R) { + var implementation, implZone; + $R._eval$1("0()")._check(f); + implementation = this._delegationTarget.get$_registerCallback(); + implZone = implementation.zone; + return type$.A_Function_Function_A_4_Zone_and_ZoneDelegate_and_Zone_and_A_Function._check(implementation.$function).call$1$4(implZone, P._parentDelegate(implZone), zone, f, $R); + }, + registerUnaryCallback$2$2: function(zone, f, $R, $T) { + var implementation, implZone; + $R._eval$1("@<0>")._bind$1($T)._eval$1("1(2)")._check(f); + implementation = this._delegationTarget.get$_registerUnaryCallback(); + implZone = implementation.zone; + return type$.A_Function_B_Function_A_and_B_4_Zone_and_ZoneDelegate_and_Zone_and_A_Function_B._check(implementation.$function).call$2$4(implZone, P._parentDelegate(implZone), zone, f, $R, $T); + }, + registerBinaryCallback$3$2: function(zone, f, $R, T1, T2) { + var implementation, implZone; + $R._eval$1("@<0>")._bind$1(T1)._bind$1(T2)._eval$1("1(2,3)")._check(f); + implementation = this._delegationTarget.get$_registerBinaryCallback(); + implZone = implementation.zone; + return type$.A_Function_2_B_and_C_Function_A_and_B_and_C_4_Zone_and_ZoneDelegate_and_Zone_and_A_Function_2_B_and_C._check(implementation.$function).call$3$4(implZone, P._parentDelegate(implZone), zone, f, $R, T1, T2); + }, + errorCallback$3: function(zone, error, stackTrace) { + var implementation = this._delegationTarget.get$_errorCallback(), + implZone = implementation.zone; + if (implZone === C.C__RootZone) + return null; + return implementation.$function.call$5(implZone, P._parentDelegate(implZone), zone, error, stackTrace); + }, + $isZoneDelegate: 1 + }; + P._Zone.prototype = {$isZone: 1}; + P._CustomZone.prototype = { + get$_delegate: function() { + var t1 = this._delegateCache; + if (t1 != null) + return t1; + return this._delegateCache = new P._ZoneDelegate(this); + }, + get$errorZone: function() { + return this._handleUncaughtError.zone; + }, + runGuarded$1: function(f) { + var e, s, exception; + type$.void_Function._check(f); + try { + this.run$1$1(f, type$.void); + } catch (exception) { + e = H.unwrapException(exception); + s = H.getTraceFromException(exception); + this.handleUncaughtError$2(e, s); + } + }, + runUnaryGuarded$1$2: function(f, arg, $T) { + var e, s, exception; + $T._eval$1("~(0)")._check(f); + $T._check(arg); + try { + this.runUnary$2$2(f, arg, type$.void, $T); + } catch (exception) { + e = H.unwrapException(exception); + s = H.getTraceFromException(exception); + this.handleUncaughtError$2(e, s); + } + }, + runBinaryGuarded$2$3: function(f, arg1, arg2, T1, T2) { + var e, s, exception; + T1._eval$1("@<0>")._bind$1(T2)._eval$1("~(1,2)")._check(f); + T1._check(arg1); + T2._check(arg2); + try { + this.runBinary$3$3(f, arg1, arg2, type$.void, T1, T2); + } catch (exception) { + e = H.unwrapException(exception); + s = H.getTraceFromException(exception); + this.handleUncaughtError$2(e, s); + } + }, + bindCallback$1$1: function(f, $R) { + return new P._CustomZone_bindCallback_closure(this, this.registerCallback$1$1($R._eval$1("0()")._check(f), $R), $R); + }, + bindUnaryCallback$2$1: function(f, $R, $T) { + return new P._CustomZone_bindUnaryCallback_closure(this, this.registerUnaryCallback$2$1($R._eval$1("@<0>")._bind$1($T)._eval$1("1(2)")._check(f), $R, $T), $T, $R); + }, + bindCallbackGuarded$1: function(f) { + return new P._CustomZone_bindCallbackGuarded_closure(this, this.registerCallback$1$1(type$.void_Function._check(f), type$.void)); + }, + bindUnaryCallbackGuarded$1$1: function(f, $T) { + return new P._CustomZone_bindUnaryCallbackGuarded_closure(this, this.registerUnaryCallback$2$1($T._eval$1("~(0)")._check(f), type$.void, $T), $T); + }, + $index: function(_, key) { + var value, + t1 = this._async$_map, + result = t1.$index(0, key); + if (result != null || t1.containsKey$1(key)) + return result; + value = this.parent.$index(0, key); + if (value != null) + t1.$indexSet(0, key, value); + return value; + }, + handleUncaughtError$2: function(error, stackTrace) { + var implementation, t1, parentDelegate; + type$.StackTrace._check(stackTrace); + implementation = this._handleUncaughtError; + H.assertHelper(implementation != null); + t1 = implementation.zone; + parentDelegate = P._parentDelegate(t1); + return implementation.$function.call$5(t1, parentDelegate, this, error, stackTrace); + }, + fork$2$specification$zoneValues: function(specification, zoneValues) { + var t1, parentDelegate, + implementation = this._fork; + H.assertHelper(implementation != null); + t1 = implementation.zone; + parentDelegate = P._parentDelegate(t1); + return implementation.$function.call$5(t1, parentDelegate, this, specification, zoneValues); + }, + run$1$1: function(f, $R) { + var implementation, t1, parentDelegate; + $R._eval$1("0()")._check(f); + implementation = this._run; + H.assertHelper(implementation != null); + t1 = implementation.zone; + parentDelegate = P._parentDelegate(t1); + return type$.A_Function_A_4_Zone_and_ZoneDelegate_and_Zone_and_A_Function._check(implementation.$function).call$1$4(t1, parentDelegate, this, f, $R); + }, + runUnary$2$2: function(f, arg, $R, $T) { + var implementation, t1, parentDelegate; + $R._eval$1("@<0>")._bind$1($T)._eval$1("1(2)")._check(f); + $T._check(arg); + implementation = this._runUnary; + H.assertHelper(implementation != null); + t1 = implementation.zone; + parentDelegate = P._parentDelegate(t1); + return type$.A_Function_A_and_B_5_Zone_and_ZoneDelegate_and_Zone_and_A_Function_B_and_B._check(implementation.$function).call$2$5(t1, parentDelegate, this, f, arg, $R, $T); + }, + runBinary$3$3: function(f, arg1, arg2, $R, T1, T2) { + var implementation, t1, parentDelegate; + $R._eval$1("@<0>")._bind$1(T1)._bind$1(T2)._eval$1("1(2,3)")._check(f); + T1._check(arg1); + T2._check(arg2); + implementation = this._runBinary; + H.assertHelper(implementation != null); + t1 = implementation.zone; + parentDelegate = P._parentDelegate(t1); + return type$.A_Function_A_and_B_and_C_6_Zone_and_ZoneDelegate_and_Zone_and_A_Function_2_B_and_C_and_B_and_C._check(implementation.$function).call$3$6(t1, parentDelegate, this, f, arg1, arg2, $R, T1, T2); + }, + registerCallback$1$1: function(callback, $R) { + var implementation, t1, parentDelegate; + $R._eval$1("0()")._check(callback); + implementation = this._registerCallback; + H.assertHelper(implementation != null); + t1 = implementation.zone; + parentDelegate = P._parentDelegate(t1); + return type$.A_Function_Function_A_4_Zone_and_ZoneDelegate_and_Zone_and_A_Function._check(implementation.$function).call$1$4(t1, parentDelegate, this, callback, $R); + }, + registerUnaryCallback$2$1: function(callback, $R, $T) { + var implementation, t1, parentDelegate; + $R._eval$1("@<0>")._bind$1($T)._eval$1("1(2)")._check(callback); + implementation = this._registerUnaryCallback; + H.assertHelper(implementation != null); + t1 = implementation.zone; + parentDelegate = P._parentDelegate(t1); + return type$.A_Function_B_Function_A_and_B_4_Zone_and_ZoneDelegate_and_Zone_and_A_Function_B._check(implementation.$function).call$2$4(t1, parentDelegate, this, callback, $R, $T); + }, + registerBinaryCallback$3$1: function(callback, $R, T1, T2) { + var implementation, t1, parentDelegate; + $R._eval$1("@<0>")._bind$1(T1)._bind$1(T2)._eval$1("1(2,3)")._check(callback); + implementation = this._registerBinaryCallback; + H.assertHelper(implementation != null); + t1 = implementation.zone; + parentDelegate = P._parentDelegate(t1); + return type$.A_Function_2_B_and_C_Function_A_and_B_and_C_4_Zone_and_ZoneDelegate_and_Zone_and_A_Function_2_B_and_C._check(implementation.$function).call$3$4(t1, parentDelegate, this, callback, $R, T1, T2); + }, + errorCallback$2: function(error, stackTrace) { + var implementation, implementationZone, parentDelegate; + type$.StackTrace._check(stackTrace); + implementation = this._errorCallback; + H.assertHelper(implementation != null); + implementationZone = implementation.zone; + if (implementationZone === C.C__RootZone) + return null; + parentDelegate = P._parentDelegate(implementationZone); + return implementation.$function.call$5(implementationZone, parentDelegate, this, error, stackTrace); + }, + scheduleMicrotask$1: function(f) { + var implementation, t1, parentDelegate; + type$.void_Function._check(f); + implementation = this._scheduleMicrotask; + H.assertHelper(implementation != null); + t1 = implementation.zone; + parentDelegate = P._parentDelegate(t1); + return implementation.$function.call$4(t1, parentDelegate, this, f); + }, + createTimer$2: function(duration, f) { + var implementation, t1, parentDelegate; + type$.void_Function._check(f); + implementation = this._createTimer; + H.assertHelper(implementation != null); + t1 = implementation.zone; + parentDelegate = P._parentDelegate(t1); + return implementation.$function.call$5(t1, parentDelegate, this, duration, f); + }, + print$1: function(_, line) { + var t1, parentDelegate, + implementation = this._print; + H.assertHelper(implementation != null); + t1 = implementation.zone; + parentDelegate = P._parentDelegate(t1); + return implementation.$function.call$4(t1, parentDelegate, this, line); + }, + set$_run: function(_run) { + this._run = type$._ZoneFunction_Function._check(_run); + }, + set$_runUnary: function(_runUnary) { + this._runUnary = type$._ZoneFunction_Function._check(_runUnary); + }, + set$_runBinary: function(_runBinary) { + this._runBinary = type$._ZoneFunction_Function._check(_runBinary); + }, + set$_registerCallback: function(_registerCallback) { + this._registerCallback = type$._ZoneFunction_Function._check(_registerCallback); + }, + set$_registerUnaryCallback: function(_registerUnaryCallback) { + this._registerUnaryCallback = type$._ZoneFunction_Function._check(_registerUnaryCallback); + }, + set$_registerBinaryCallback: function(_registerBinaryCallback) { + this._registerBinaryCallback = type$._ZoneFunction_Function._check(_registerBinaryCallback); + }, + set$_errorCallback: function(_errorCallback) { + this._errorCallback = type$._ZoneFunction_of_AsyncError_Function_Zone_ZoneDelegate_Zone_Object_StackTrace._check(_errorCallback); + }, + set$_scheduleMicrotask: function(_scheduleMicrotask) { + this._scheduleMicrotask = type$._ZoneFunction_of_void_Function_4_Zone_and_ZoneDelegate_and_Zone_and_void_Function._check(_scheduleMicrotask); + }, + set$_createTimer: function(_createTimer) { + this._createTimer = type$._ZoneFunction_of_Timer_Function_5_Zone_and_ZoneDelegate_and_Zone_and_Duration_and_void_Function._check(_createTimer); + }, + set$_createPeriodicTimer: function(_createPeriodicTimer) { + this._createPeriodicTimer = type$._ZoneFunction_of_Timer_Function_5_Zone_and_ZoneDelegate_and_Zone_and_Duration_and_void_Function_Timer._check(_createPeriodicTimer); + }, + set$_print: function(_print) { + this._print = type$._ZoneFunction_of_void_Function_Zone_ZoneDelegate_Zone_String._check(_print); + }, + set$_fork: function(_fork) { + this._fork = type$._ZoneFunction_of_Zone_Function_5_Zone_and_ZoneDelegate_and_Zone_and_ZoneSpecification_and_Map_dynamic_dynamic._check(_fork); + }, + set$_handleUncaughtError: function(_handleUncaughtError) { + this._handleUncaughtError = type$._ZoneFunction_of_void_Function_Zone_ZoneDelegate_Zone_Object_StackTrace._check(_handleUncaughtError); + }, + get$_run: function() { + return this._run; + }, + get$_runUnary: function() { + return this._runUnary; + }, + get$_runBinary: function() { + return this._runBinary; + }, + get$_registerCallback: function() { + return this._registerCallback; + }, + get$_registerUnaryCallback: function() { + return this._registerUnaryCallback; + }, + get$_registerBinaryCallback: function() { + return this._registerBinaryCallback; + }, + get$_errorCallback: function() { + return this._errorCallback; + }, + get$_scheduleMicrotask: function() { + return this._scheduleMicrotask; + }, + get$_createTimer: function() { + return this._createTimer; + }, + get$_createPeriodicTimer: function() { + return this._createPeriodicTimer; + }, + get$_print: function() { + return this._print; + }, + get$_fork: function() { + return this._fork; + }, + get$_handleUncaughtError: function() { + return this._handleUncaughtError; + }, + get$parent: function(receiver) { + return this.parent; + }, + get$_async$_map: function() { + return this._async$_map; + } + }; + P._CustomZone_bindCallback_closure.prototype = { + call$0: function() { + return this.$this.run$1$1(this.registered, this.R); + }, + $signature: function() { + return this.R._eval$1("0()"); + } + }; + P._CustomZone_bindUnaryCallback_closure.prototype = { + call$1: function(arg) { + var _this = this, + t1 = _this.T; + return _this.$this.runUnary$2$2(_this.registered, t1._check(arg), _this.R, t1); + }, + $signature: function() { + return this.R._eval$1("@<0>")._bind$1(this.T)._eval$1("1(2)"); + } + }; + P._CustomZone_bindCallbackGuarded_closure.prototype = { + call$0: function() { + return this.$this.runGuarded$1(this.registered); + }, + $signature: 1 + }; + P._CustomZone_bindUnaryCallbackGuarded_closure.prototype = { + call$1: function(arg) { + var t1 = this.T; + return this.$this.runUnaryGuarded$1$2(this.registered, t1._check(arg), t1); + }, + $signature: function() { + return this.T._eval$1("~(0)"); + } + }; + P._rootHandleUncaughtError_closure.prototype = { + call$0: function() { + var error, + t1 = this._box_0, + t2 = t1.error; + t1 = t2 == null ? t1.error = new P.NullThrownError() : t2; + t2 = this.stackTrace; + if (t2 == null) + throw H.wrapException(t1); + error = H.wrapException(t1); + error.stack = t2.toString$0(0); + throw error; + }, + $signature: 0 + }; + P._RootZone.prototype = { + get$_run: function() { + return C._ZoneFunction__RootZone__rootRun; + }, + get$_runUnary: function() { + return C._ZoneFunction__RootZone__rootRunUnary; + }, + get$_runBinary: function() { + return C._ZoneFunction__RootZone__rootRunBinary; + }, + get$_registerCallback: function() { + return C._ZoneFunction__RootZone__rootRegisterCallback; + }, + get$_registerUnaryCallback: function() { + return C._ZoneFunction_Eeh; + }, + get$_registerBinaryCallback: function() { + return C._ZoneFunction_7G2; + }, + get$_errorCallback: function() { + return C._ZoneFunction__RootZone__rootErrorCallback; + }, + get$_scheduleMicrotask: function() { + return C._ZoneFunction__RootZone__rootScheduleMicrotask; + }, + get$_createTimer: function() { + return C._ZoneFunction__RootZone__rootCreateTimer; + }, + get$_createPeriodicTimer: function() { + return C._ZoneFunction_3bB; + }, + get$_print: function() { + return C._ZoneFunction__RootZone__rootPrint; + }, + get$_fork: function() { + return C._ZoneFunction__RootZone__rootFork; + }, + get$_handleUncaughtError: function() { + return C._ZoneFunction_NMc; + }, + get$parent: function(_) { + return null; + }, + get$_async$_map: function() { + return $.$get$_RootZone__rootMap(); + }, + get$_delegate: function() { + var t1 = $._RootZone__rootDelegate; + if (t1 != null) + return t1; + return $._RootZone__rootDelegate = new P._ZoneDelegate(this); + }, + get$errorZone: function() { + return this; + }, + runGuarded$1: function(f) { + var e, s, exception, _null = null; + type$.void_Function._check(f); + try { + if (C.C__RootZone === $.Zone__current) { + f.call$0(); + return; + } + P._rootRun(_null, _null, this, f, type$.void); + } catch (exception) { + e = H.unwrapException(exception); + s = H.getTraceFromException(exception); + P._rootHandleUncaughtError(_null, _null, this, e, type$.StackTrace._check(s)); + } + }, + runUnaryGuarded$1$2: function(f, arg, $T) { + var e, s, exception, _null = null; + $T._eval$1("~(0)")._check(f); + $T._check(arg); + try { + if (C.C__RootZone === $.Zone__current) { + f.call$1(arg); + return; + } + P._rootRunUnary(_null, _null, this, f, arg, type$.void, $T); + } catch (exception) { + e = H.unwrapException(exception); + s = H.getTraceFromException(exception); + P._rootHandleUncaughtError(_null, _null, this, e, type$.StackTrace._check(s)); + } + }, + runBinaryGuarded$2$3: function(f, arg1, arg2, T1, T2) { + var e, s, exception, _null = null; + T1._eval$1("@<0>")._bind$1(T2)._eval$1("~(1,2)")._check(f); + T1._check(arg1); + T2._check(arg2); + try { + if (C.C__RootZone === $.Zone__current) { + f.call$2(arg1, arg2); + return; + } + P._rootRunBinary(_null, _null, this, f, arg1, arg2, type$.void, T1, T2); + } catch (exception) { + e = H.unwrapException(exception); + s = H.getTraceFromException(exception); + P._rootHandleUncaughtError(_null, _null, this, e, type$.StackTrace._check(s)); + } + }, + bindCallback$1$1: function(f, $R) { + return new P._RootZone_bindCallback_closure(this, $R._eval$1("0()")._check(f), $R); + }, + bindCallbackGuarded$1: function(f) { + return new P._RootZone_bindCallbackGuarded_closure(this, type$.void_Function._check(f)); + }, + bindUnaryCallbackGuarded$1$1: function(f, $T) { + return new P._RootZone_bindUnaryCallbackGuarded_closure(this, $T._eval$1("~(0)")._check(f), $T); + }, + $index: function(_, key) { + return null; + }, + handleUncaughtError$2: function(error, stackTrace) { + P._rootHandleUncaughtError(null, null, this, error, type$.StackTrace._check(stackTrace)); + }, + fork$2$specification$zoneValues: function(specification, zoneValues) { + return P._rootFork(null, null, this, specification, zoneValues); + }, + run$1$1: function(f, $R) { + $R._eval$1("0()")._check(f); + if ($.Zone__current === C.C__RootZone) + return f.call$0(); + return P._rootRun(null, null, this, f, $R); + }, + runUnary$2$2: function(f, arg, $R, $T) { + $R._eval$1("@<0>")._bind$1($T)._eval$1("1(2)")._check(f); + $T._check(arg); + if ($.Zone__current === C.C__RootZone) + return f.call$1(arg); + return P._rootRunUnary(null, null, this, f, arg, $R, $T); + }, + runBinary$3$3: function(f, arg1, arg2, $R, T1, T2) { + $R._eval$1("@<0>")._bind$1(T1)._bind$1(T2)._eval$1("1(2,3)")._check(f); + T1._check(arg1); + T2._check(arg2); + if ($.Zone__current === C.C__RootZone) + return f.call$2(arg1, arg2); + return P._rootRunBinary(null, null, this, f, arg1, arg2, $R, T1, T2); + }, + registerCallback$1$1: function(f, $R) { + return $R._eval$1("0()")._check(f); + }, + registerUnaryCallback$2$1: function(f, $R, $T) { + return $R._eval$1("@<0>")._bind$1($T)._eval$1("1(2)")._check(f); + }, + registerBinaryCallback$3$1: function(f, $R, T1, T2) { + return $R._eval$1("@<0>")._bind$1(T1)._bind$1(T2)._eval$1("1(2,3)")._check(f); + }, + errorCallback$2: function(error, stackTrace) { + type$.StackTrace._check(stackTrace); + return null; + }, + scheduleMicrotask$1: function(f) { + P._rootScheduleMicrotask(null, null, this, type$.void_Function._check(f)); + }, + createTimer$2: function(duration, f) { + return P.Timer__createTimer(duration, type$.void_Function._check(f)); + }, + print$1: function(_, line) { + H.printString(line); + } + }; + P._RootZone_bindCallback_closure.prototype = { + call$0: function() { + return this.$this.run$1$1(this.f, this.R); + }, + $signature: function() { + return this.R._eval$1("0()"); + } + }; + P._RootZone_bindCallbackGuarded_closure.prototype = { + call$0: function() { + return this.$this.runGuarded$1(this.f); + }, + $signature: 1 + }; + P._RootZone_bindUnaryCallbackGuarded_closure.prototype = { + call$1: function(arg) { + var t1 = this.T; + return this.$this.runUnaryGuarded$1$2(this.f, t1._check(arg), t1); + }, + $signature: function() { + return this.T._eval$1("~(0)"); + } + }; + P.runZoned_closure.prototype = { + call$5: function($self, $parent, zone, error, stackTrace) { + var e, s, t2, t3, t4, exception, + t1 = type$.StackTrace; + t1._check(stackTrace); + try { + t2 = this._box_0; + t3 = type$.void; + t4 = type$.Object; + if (t2.binaryOnError != null) + $self.get$parent($self).runBinary$3$3(t2.binaryOnError, error, stackTrace, t3, t4, t1); + else { + H.assertHelper(t2.unaryOnError != null); + $self.get$parent($self).runUnary$2$2(t2.unaryOnError, error, t3, t4); + } + } catch (exception) { + e = H.unwrapException(exception); + s = H.getTraceFromException(exception); + t1 = e; + if (t1 == null ? error == null : t1 === error) + $parent.handleUncaughtError$3(zone, error, stackTrace); + else + $parent.handleUncaughtError$3(zone, e, s); + } + }, + $signature: 28 + }; + P._HashMap.prototype = { + get$length: function(_) { + return this._collection$_length; + }, + get$isEmpty: function(_) { + return this._collection$_length === 0; + }, + get$keys: function() { + return new P._HashMapKeyIterable(this, H._instanceType(this)._eval$1("_HashMapKeyIterable<1>")); + }, + containsKey$1: function(key) { + var strings, nums; + if (typeof key == "string" && key !== "__proto__") { + strings = this._strings; + return strings == null ? false : strings[key] != null; + } else if (typeof key == "number" && (key & 1073741823) === key) { + nums = this._nums; + return nums == null ? false : nums[key] != null; + } else + return this._containsKey$1(key); + }, + _containsKey$1: function(key) { + var rest = this._collection$_rest; + if (rest == null) + return false; + return this._findBucketIndex$2(this._getBucket$2(rest, key), key) >= 0; + }, + $index: function(_, key) { + var strings, t1, nums; + if (typeof key == "string" && key !== "__proto__") { + strings = this._strings; + t1 = strings == null ? null : P._HashMap__getTableEntry(strings, key); + return t1; + } else if (typeof key == "number" && (key & 1073741823) === key) { + nums = this._nums; + t1 = nums == null ? null : P._HashMap__getTableEntry(nums, key); + return t1; + } else + return this._get$1(key); + }, + _get$1: function(key) { + var bucket, index, + rest = this._collection$_rest; + if (rest == null) + return null; + bucket = this._getBucket$2(rest, key); + index = this._findBucketIndex$2(bucket, key); + return index < 0 ? null : bucket[index + 1]; + }, + $indexSet: function(_, key, value) { + var strings, nums, _this = this, + t1 = H._instanceType(_this); + t1._precomputed1._check(key); + t1._rest[1]._check(value); + if (typeof key == "string" && key !== "__proto__") { + strings = _this._strings; + _this._addHashTableEntry$3(strings == null ? _this._strings = P._HashMap__newHashTable() : strings, key, value); + } else if (typeof key == "number" && (key & 1073741823) === key) { + nums = _this._nums; + _this._addHashTableEntry$3(nums == null ? _this._nums = P._HashMap__newHashTable() : nums, key, value); + } else + _this._set$2(key, value); + }, + _set$2: function(key, value) { + var rest, hash, bucket, index, _this = this, + t1 = H._instanceType(_this); + t1._precomputed1._check(key); + t1._rest[1]._check(value); + rest = _this._collection$_rest; + if (rest == null) + rest = _this._collection$_rest = P._HashMap__newHashTable(); + hash = _this._computeHashCode$1(key); + bucket = rest[hash]; + if (bucket == null) { + P._HashMap__setTableEntry(rest, hash, [key, value]); + ++_this._collection$_length; + _this._keys = null; + } else { + index = _this._findBucketIndex$2(bucket, key); + if (index >= 0) + bucket[index + 1] = value; + else { + bucket.push(key, value); + ++_this._collection$_length; + _this._keys = null; + } + } + }, + remove$1: function(_, key) { + var t1 = this._remove$1(key); + return t1; + }, + _remove$1: function(key) { + var hash, bucket, index, result, _this = this, + rest = _this._collection$_rest; + if (rest == null) + return null; + hash = _this._computeHashCode$1(key); + bucket = rest[hash]; + index = _this._findBucketIndex$2(bucket, key); + if (index < 0) + return null; + --_this._collection$_length; + _this._keys = null; + result = bucket.splice(index, 2)[1]; + if (0 === bucket.length) + delete rest[hash]; + return result; + }, + forEach$1: function(_, action) { + var keys, $length, i, key, _this = this, + t1 = H._instanceType(_this); + t1._eval$1("~(1,2)")._check(action); + keys = _this._computeKeys$0(); + for ($length = keys.length, t1 = t1._precomputed1, i = 0; i < $length; ++i) { + key = keys[i]; + action.call$2(t1._check(key), _this.$index(0, key)); + if (keys !== _this._keys) + throw H.wrapException(P.ConcurrentModificationError$(_this)); + } + }, + _computeKeys$0: function() { + var result, strings, names, entries, index, i, nums, rest, bucket, $length, i0, _this = this, + t1 = _this._keys; + if (t1 != null) + return t1; + result = new Array(_this._collection$_length); + result.fixed$length = Array; + strings = _this._strings; + if (strings != null) { + names = Object.getOwnPropertyNames(strings); + entries = names.length; + for (index = 0, i = 0; i < entries; ++i) { + result[index] = names[i]; + ++index; + } + } else + index = 0; + nums = _this._nums; + if (nums != null) { + names = Object.getOwnPropertyNames(nums); + entries = names.length; + for (i = 0; i < entries; ++i) { + result[index] = +names[i]; + ++index; + } + } + rest = _this._collection$_rest; + if (rest != null) { + names = Object.getOwnPropertyNames(rest); + entries = names.length; + for (i = 0; i < entries; ++i) { + bucket = rest[names[i]]; + $length = bucket.length; + for (i0 = 0; i0 < $length; i0 += 2) { + result[index] = bucket[i0]; + ++index; + } + } + } + H.assertHelper(index === _this._collection$_length); + return _this._keys = result; + }, + _addHashTableEntry$3: function(table, key, value) { + var t1 = H._instanceType(this); + t1._precomputed1._check(key); + t1._rest[1]._check(value); + if (table[key] == null) { + ++this._collection$_length; + this._keys = null; + } + P._HashMap__setTableEntry(table, key, value); + }, + _computeHashCode$1: function(key) { + return J.get$hashCode$(key) & 1073741823; + }, + _getBucket$2: function(table, key) { + return table[this._computeHashCode$1(key)]; + }, + _findBucketIndex$2: function(bucket, key) { + var $length, i; + if (bucket == null) + return -1; + $length = bucket.length; + for (i = 0; i < $length; i += 2) + if (J.$eq$(bucket[i], key)) + return i; + return -1; + } + }; + P._IdentityHashMap.prototype = { + _computeHashCode$1: function(key) { + return H.objectHashCode(key) & 1073741823; + }, + _findBucketIndex$2: function(bucket, key) { + var $length, i, t1; + if (bucket == null) + return -1; + $length = bucket.length; + for (i = 0; i < $length; i += 2) { + t1 = bucket[i]; + if (t1 == null ? key == null : t1 === key) + return i; + } + return -1; + } + }; + P._HashMapKeyIterable.prototype = { + get$length: function(_) { + return this._map._collection$_length; + }, + get$isEmpty: function(_) { + return this._map._collection$_length === 0; + }, + get$iterator: function(_) { + var t1 = this._map; + return new P._HashMapKeyIterator(t1, t1._computeKeys$0(), this.$ti._eval$1("_HashMapKeyIterator<1>")); + }, + contains$1: function(_, element) { + return this._map.containsKey$1(element); + } + }; + P._HashMapKeyIterator.prototype = { + get$current: function() { + return this._collection$_current; + }, + moveNext$0: function() { + var _this = this, + keys = _this._keys, + offset = _this._offset, + t1 = _this._map; + if (keys !== t1._keys) + throw H.wrapException(P.ConcurrentModificationError$(t1)); + else if (offset >= keys.length) { + _this.set$_collection$_current(null); + return false; + } else { + _this.set$_collection$_current(keys[offset]); + _this._offset = offset + 1; + return true; + } + }, + set$_collection$_current: function(_current) { + this._collection$_current = this.$ti._precomputed1._check(_current); + }, + $isIterator: 1 + }; + P._LinkedHashSet.prototype = { + _newSet$0: function() { + return new P._LinkedHashSet(H._instanceType(this)._eval$1("_LinkedHashSet<1>")); + }, + get$iterator: function(_) { + var _this = this, + t1 = new P._LinkedHashSetIterator(_this, _this._collection$_modifications, H._instanceType(_this)._eval$1("_LinkedHashSetIterator<1>")); + t1._collection$_cell = _this._collection$_first; + return t1; + }, + get$length: function(_) { + return this._collection$_length; + }, + get$isEmpty: function(_) { + return this._collection$_length === 0; + }, + contains$1: function(_, object) { + var strings, nums; + if (typeof object == "string" && object !== "__proto__") { + strings = this._strings; + if (strings == null) + return false; + return type$._LinkedHashSetCell._check(strings[object]) != null; + } else if (typeof object == "number" && (object & 1073741823) === object) { + nums = this._nums; + if (nums == null) + return false; + return type$._LinkedHashSetCell._check(nums[object]) != null; + } else + return this._contains$1(object); + }, + _contains$1: function(object) { + var rest = this._collection$_rest; + if (rest == null) + return false; + return this._findBucketIndex$2(rest[this._computeHashCode$1(object)], object) >= 0; + }, + get$first: function(_) { + var t1 = this._collection$_first; + if (t1 == null) + throw H.wrapException(P.StateError$("No elements")); + return H._instanceType(this)._precomputed1._check(t1._element); + }, + get$last: function(_) { + var t1 = this._collection$_last; + if (t1 == null) + throw H.wrapException(P.StateError$("No elements")); + return H._instanceType(this)._precomputed1._check(t1._element); + }, + add$1: function(_, element) { + var strings, nums, _this = this; + H._instanceType(_this)._precomputed1._check(element); + if (typeof element == "string" && element !== "__proto__") { + strings = _this._strings; + return _this._addHashTableEntry$2(strings == null ? _this._strings = P._LinkedHashSet__newHashTable() : strings, element); + } else if (typeof element == "number" && (element & 1073741823) === element) { + nums = _this._nums; + return _this._addHashTableEntry$2(nums == null ? _this._nums = P._LinkedHashSet__newHashTable() : nums, element); + } else + return _this._collection$_add$1(element); + }, + _collection$_add$1: function(element) { + var rest, hash, bucket, t1, _this = this; + H._instanceType(_this)._precomputed1._check(element); + rest = _this._collection$_rest; + if (rest == null) + rest = _this._collection$_rest = P._LinkedHashSet__newHashTable(); + hash = _this._computeHashCode$1(element); + bucket = rest[hash]; + if (bucket == null) { + t1 = [_this._collection$_newLinkedCell$1(element)]; + H.assertHelper(t1 != null); + rest[hash] = t1; + } else { + if (_this._findBucketIndex$2(bucket, element) >= 0) + return false; + bucket.push(_this._collection$_newLinkedCell$1(element)); + } + return true; + }, + remove$1: function(_, object) { + var _this = this; + if (typeof object == "string" && object !== "__proto__") + return _this._removeHashTableEntry$2(_this._strings, object); + else if (typeof object == "number" && (object & 1073741823) === object) + return _this._removeHashTableEntry$2(_this._nums, object); + else + return _this._remove$1(object); + }, + _remove$1: function(object) { + var hash, bucket, index, cell, _this = this, + rest = _this._collection$_rest; + if (rest == null) + return false; + hash = _this._computeHashCode$1(object); + bucket = rest[hash]; + index = _this._findBucketIndex$2(bucket, object); + if (index < 0) + return false; + cell = bucket.splice(index, 1)[0]; + if (0 === bucket.length) + delete rest[hash]; + _this._unlinkCell$1(cell); + return true; + }, + _addHashTableEntry$2: function(table, element) { + H._instanceType(this)._precomputed1._check(element); + if (type$._LinkedHashSetCell._check(table[element]) != null) + return false; + table[element] = this._collection$_newLinkedCell$1(element); + return true; + }, + _removeHashTableEntry$2: function(table, element) { + var cell; + if (table == null) + return false; + cell = type$._LinkedHashSetCell._check(table[element]); + if (cell == null) + return false; + this._unlinkCell$1(cell); + delete table[element]; + return true; + }, + _collection$_modified$0: function() { + this._collection$_modifications = 1073741823 & this._collection$_modifications + 1; + }, + _collection$_newLinkedCell$1: function(element) { + var last, _this = this, + cell = new P._LinkedHashSetCell(H._instanceType(_this)._precomputed1._check(element)); + if (_this._collection$_first == null) + _this._collection$_first = _this._collection$_last = cell; + else { + last = _this._collection$_last; + cell._collection$_previous = last; + _this._collection$_last = last._collection$_next = cell; + } + ++_this._collection$_length; + _this._collection$_modified$0(); + return cell; + }, + _unlinkCell$1: function(cell) { + var _this = this, + previous = cell._collection$_previous, + next = cell._collection$_next; + if (previous == null) { + H.assertHelper(cell == _this._collection$_first); + _this._collection$_first = next; + } else + previous._collection$_next = next; + if (next == null) { + H.assertHelper(cell == _this._collection$_last); + _this._collection$_last = previous; + } else + next._collection$_previous = previous; + --_this._collection$_length; + _this._collection$_modified$0(); + }, + _computeHashCode$1: function(element) { + return J.get$hashCode$(element) & 1073741823; + }, + _findBucketIndex$2: function(bucket, element) { + var $length, i; + if (bucket == null) + return -1; + $length = bucket.length; + for (i = 0; i < $length; ++i) + if (J.$eq$(bucket[i]._element, element)) + return i; + return -1; + }, + $isLinkedHashSet: 1 + }; + P._LinkedHashSetCell.prototype = {}; + P._LinkedHashSetIterator.prototype = { + get$current: function() { + return this._collection$_current; + }, + moveNext$0: function() { + var _this = this, + t1 = _this._set; + if (_this._collection$_modifications !== t1._collection$_modifications) + throw H.wrapException(P.ConcurrentModificationError$(t1)); + else { + t1 = _this._collection$_cell; + if (t1 == null) { + _this.set$_collection$_current(null); + return false; + } else { + _this.set$_collection$_current(_this.$ti._precomputed1._check(t1._element)); + _this._collection$_cell = _this._collection$_cell._collection$_next; + return true; + } + } + }, + set$_collection$_current: function(_current) { + this._collection$_current = this.$ti._precomputed1._check(_current); + }, + $isIterator: 1 + }; + P.UnmodifiableListView.prototype = { + get$length: function(_) { + var t1 = this._collection$_source; + return t1.get$length(t1); + }, + $index: function(_, index) { + return this._collection$_source.$index(0, H._checkIntNullable(index)); + } + }; + P.HashMap_HashMap$from_closure.prototype = { + call$2: function(k, v) { + this.result.$indexSet(0, this.K._check(k), this.V._check(v)); + }, + $signature: 6 + }; + P.IterableBase.prototype = {}; + P.LinkedHashMap_LinkedHashMap$from_closure.prototype = { + call$2: function(k, v) { + this.result.$indexSet(0, this.K._check(k), this.V._check(v)); + }, + $signature: 6 + }; + P.ListBase.prototype = {$isEfficientLengthIterable: 1, $isIterable: 1, $isList: 1}; + P.ListMixin.prototype = { + get$iterator: function(receiver) { + return new H.ListIterator(receiver, this.get$length(receiver), H.instanceType(receiver)._eval$1("ListIterator<ListMixin.E>")); + }, + elementAt$1: function(receiver, index) { + return this.$index(receiver, index); + }, + get$isEmpty: function(receiver) { + return this.get$length(receiver) === 0; + }, + get$first: function(receiver) { + if (this.get$length(receiver) === 0) + throw H.wrapException(H.IterableElementError_noElement()); + return this.$index(receiver, 0); + }, + get$last: function(receiver) { + if (this.get$length(receiver) === 0) + throw H.wrapException(H.IterableElementError_noElement()); + return this.$index(receiver, this.get$length(receiver) - 1); + }, + map$1$1: function(receiver, f, $T) { + var t1 = H.instanceType(receiver); + return new H.MappedListIterable(receiver, t1._bind$1($T)._eval$1("1(ListMixin.E)")._check(f), t1._eval$1("@<ListMixin.E>")._bind$1($T)._eval$1("MappedListIterable<1,2>")); + }, + toList$1$growable: function(receiver, growable) { + var i, + result = H.setRuntimeTypeInfo([], H.instanceType(receiver)._eval$1("JSArray<ListMixin.E>")); + C.JSArray_methods.set$length(result, this.get$length(receiver)); + for (i = 0; i < this.get$length(receiver); ++i) + C.JSArray_methods.$indexSet(result, i, this.$index(receiver, i)); + return result; + }, + toList$0: function($receiver) { + return this.toList$1$growable($receiver, true); + }, + toSet$0: function(receiver) { + var i, + result = P.LinkedHashSet_LinkedHashSet(H.instanceType(receiver)._eval$1("ListMixin.E")); + for (i = 0; i < this.get$length(receiver); ++i) + result.add$1(0, this.$index(receiver, i)); + return result; + }, + remove$1: function(receiver, element) { + var i; + for (i = 0; i < this.get$length(receiver); ++i) + if (J.$eq$(this.$index(receiver, i), element)) { + this._closeGap$2(receiver, i, i + 1); + return true; + } + return false; + }, + _closeGap$2: function(receiver, start, end) { + var size, i, _this = this, + $length = _this.get$length(receiver); + H.assertHelper(start < end); + H.assertHelper(end <= $length); + size = end - start; + for (i = end; i < $length; ++i) + _this.$indexSet(receiver, i - size, _this.$index(receiver, i)); + _this.set$length(receiver, $length - size); + }, + fillRange$3: function(receiver, start, end, fill) { + var i; + H.instanceType(receiver)._eval$1("ListMixin.E")._check(fill); + P.RangeError_checkValidRange(start, end, this.get$length(receiver)); + for (i = start; i < end; ++i) + this.$indexSet(receiver, i, fill); + }, + toString$0: function(receiver) { + return P.IterableBase_iterableToFullString(receiver, "[", "]"); + } + }; + P.MapBase.prototype = {}; + P.MapBase_mapToString_closure.prototype = { + call$2: function(k, v) { + var t2, + t1 = this._box_0; + if (!t1.first) + this.result._contents += ", "; + t1.first = false; + t1 = this.result; + t2 = t1._contents += H.S(k); + t1._contents = t2 + ": "; + t1._contents += H.S(v); + }, + $signature: 6 + }; + P.MapMixin.prototype = { + cast$2$0: function(_, RK, RV) { + var t1 = H._instanceType(this); + return P.Map_castFrom(this, t1._eval$1("MapMixin.K"), t1._eval$1("MapMixin.V"), RK, RV); + }, + forEach$1: function(_, action) { + var t1, key; + H._instanceType(this)._eval$1("~(MapMixin.K,MapMixin.V)")._check(action); + for (t1 = this.get$keys(), t1 = t1.get$iterator(t1); t1.moveNext$0();) { + key = t1.get$current(); + action.call$2(key, this.$index(0, key)); + } + }, + map$2$1: function(_, transform, K2, V2) { + var result, t1, key, entry; + H._instanceType(this)._bind$1(K2)._bind$1(V2)._eval$1("MapEntry<1,2>(MapMixin.K,MapMixin.V)")._check(transform); + result = P.LinkedHashMap_LinkedHashMap$_empty(K2, V2); + for (t1 = this.get$keys(), t1 = t1.get$iterator(t1); t1.moveNext$0();) { + key = t1.get$current(); + entry = transform.call$2(key, this.$index(0, key)); + result.$indexSet(0, entry.key, entry.value); + } + return result; + }, + containsKey$1: function(key) { + return this.get$keys().contains$1(0, key); + }, + get$length: function(_) { + var t1 = this.get$keys(); + return t1.get$length(t1); + }, + get$isEmpty: function(_) { + var t1 = this.get$keys(); + return t1.get$isEmpty(t1); + }, + toString$0: function(_) { + return P.MapBase_mapToString(this); + }, + $isMap: 1 + }; + P._UnmodifiableMapMixin.prototype = { + remove$1: function(_, key) { + throw H.wrapException(P.UnsupportedError$("Cannot modify unmodifiable map")); + } + }; + P.MapView.prototype = { + cast$2$0: function(_, RK, RV) { + return this._map.cast$2$0(0, RK, RV); + }, + $index: function(_, key) { + return this._map.$index(0, key); + }, + containsKey$1: function(key) { + return this._map.containsKey$1(key); + }, + forEach$1: function(_, action) { + this._map.forEach$1(0, H._instanceType(this)._eval$1("~(1,2)")._check(action)); + }, + get$isEmpty: function(_) { + var t1 = this._map; + return t1.get$isEmpty(t1); + }, + get$length: function(_) { + var t1 = this._map; + return t1.get$length(t1); + }, + get$keys: function() { + return this._map.get$keys(); + }, + remove$1: function(_, key) { + return this._map.remove$1(0, key); + }, + toString$0: function(_) { + return this._map.toString$0(0); + }, + map$2$1: function(_, transform, K2, V2) { + return this._map.map$2$1(0, H._instanceType(this)._bind$1(K2)._bind$1(V2)._eval$1("MapEntry<1,2>(3,4)")._check(transform), K2, V2); + }, + $isMap: 1 + }; + P.UnmodifiableMapView.prototype = { + cast$2$0: function(_, RK, RV) { + return new P.UnmodifiableMapView(this._map.cast$2$0(0, RK, RV), RK._eval$1("@<0>")._bind$1(RV)._eval$1("UnmodifiableMapView<1,2>")); + } + }; + P.ListQueue.prototype = { + get$iterator: function(_) { + var _this = this; + return new P._ListQueueIterator(_this, _this._tail, _this._modificationCount, _this._head, _this.$ti._eval$1("_ListQueueIterator<1>")); + }, + get$isEmpty: function(_) { + return this._head === this._tail; + }, + get$length: function(_) { + return (this._tail - this._head & this._table.length - 1) >>> 0; + }, + get$first: function(_) { + var t2, + t1 = this._head; + if (t1 === this._tail) + throw H.wrapException(H.IterableElementError_noElement()); + t2 = this._table; + if (t1 >= t2.length) + return H.ioore(t2, t1); + return t2[t1]; + }, + get$last: function(_) { + var t3, + t1 = this._head, + t2 = this._tail; + if (t1 === t2) + throw H.wrapException(H.IterableElementError_noElement()); + t1 = this._table; + t3 = t1.length; + t2 = (t2 - 1 & t3 - 1) >>> 0; + if (t2 < 0 || t2 >= t3) + return H.ioore(t1, t2); + return t1[t2]; + }, + elementAt$1: function(_, index) { + var t1, t2, t3, _this = this, + $length = _this.get$length(_this); + if (0 > index || index >= $length) + H.throwExpression(P.IndexError$(index, _this, "index", null, $length)); + t1 = _this._table; + t2 = t1.length; + t3 = (_this._head + index & t2 - 1) >>> 0; + if (t3 < 0 || t3 >= t2) + return H.ioore(t1, t3); + return t1[t3]; + }, + clear$0: function(_) { + var _this = this, + i = _this._head; + if (i !== _this._tail) { + for (; i !== _this._tail; i = (i + 1 & _this._table.length - 1) >>> 0) + C.JSArray_methods.$indexSet(_this._table, i, null); + _this._head = _this._tail = 0; + ++_this._modificationCount; + } + }, + toString$0: function(_) { + return P.IterableBase_iterableToFullString(this, "{", "}"); + }, + removeFirst$0: function() { + var t2, result, _this = this, + t1 = _this._head; + if (t1 === _this._tail) + throw H.wrapException(H.IterableElementError_noElement()); + ++_this._modificationCount; + t2 = _this._table; + if (t1 >= t2.length) + return H.ioore(t2, t1); + result = t2[t1]; + C.JSArray_methods.$indexSet(t2, t1, null); + _this._head = (_this._head + 1 & _this._table.length - 1) >>> 0; + return result; + }, + _collection$_add$1: function(element) { + var t2, t3, newTable, split, _this = this, + t1 = _this.$ti; + t1._precomputed1._check(element); + C.JSArray_methods.$indexSet(_this._table, _this._tail, element); + t2 = _this._tail; + t3 = _this._table.length; + t2 = (t2 + 1 & t3 - 1) >>> 0; + _this._tail = t2; + if (_this._head === t2) { + t2 = new Array(t3 * 2); + t2.fixed$length = Array; + newTable = H.setRuntimeTypeInfo(t2, t1._eval$1("JSArray<1>")); + t1 = _this._table; + t2 = _this._head; + split = t1.length - t2; + C.JSArray_methods.setRange$4(newTable, 0, split, t1, t2); + C.JSArray_methods.setRange$4(newTable, split, split + _this._head, _this._table, 0); + _this._head = 0; + _this._tail = _this._table.length; + _this.set$_table(newTable); + } + ++_this._modificationCount; + }, + set$_table: function(_table) { + this._table = this.$ti._eval$1("List<1>")._check(_table); + }, + $isQueue: 1 + }; + P._ListQueueIterator.prototype = { + get$current: function() { + return this._collection$_current; + }, + moveNext$0: function() { + var t2, t3, _this = this, + t1 = _this._queue; + if (_this._modificationCount !== t1._modificationCount) + H.throwExpression(P.ConcurrentModificationError$(t1)); + t2 = _this._position; + if (t2 === _this._end) { + _this.set$_collection$_current(null); + return false; + } + t3 = t1._table; + if (t2 >= t3.length) + return H.ioore(t3, t2); + _this.set$_collection$_current(t3[t2]); + _this._position = (_this._position + 1 & t1._table.length - 1) >>> 0; + return true; + }, + set$_collection$_current: function(_current) { + this._collection$_current = this.$ti._precomputed1._check(_current); + }, + $isIterator: 1 + }; + P.SetMixin.prototype = { + get$isEmpty: function(_) { + return this.get$length(this) === 0; + }, + map$1$1: function(_, f, $T) { + var t1 = H._instanceType(this); + return new H.EfficientLengthMappedIterable(this, t1._bind$1($T)._eval$1("1(2)")._check(f), t1._eval$1("@<1>")._bind$1($T)._eval$1("EfficientLengthMappedIterable<1,2>")); + }, + toString$0: function(_) { + return P.IterableBase_iterableToFullString(this, "{", "}"); + }, + every$1: function(_, f) { + var t1; + H._instanceType(this)._eval$1("bool(1)")._check(f); + for (t1 = this.get$iterator(this); t1.moveNext$0();) + if (!H.boolConversionCheck(f.call$1(t1.get$current()))) + return false; + return true; + }, + get$first: function(_) { + var it = this.get$iterator(this); + if (!it.moveNext$0()) + throw H.wrapException(H.IterableElementError_noElement()); + return it.get$current(); + }, + get$last: function(_) { + var result, + it = this.get$iterator(this); + if (!it.moveNext$0()) + throw H.wrapException(H.IterableElementError_noElement()); + do + result = it.get$current(); + while (it.moveNext$0()); + return result; + }, + $isEfficientLengthIterable: 1, + $isIterable: 1, + $isSet: 1 + }; + P.SetBase.prototype = {$isEfficientLengthIterable: 1, $isIterable: 1, $isSet: 1}; + P._SetBase.prototype = { + toSet$0: function(_) { + var t1 = this._newSet$0(); + t1.addAll$1(0, this); + return t1; + }, + get$isEmpty: function(_) { + return this._collection$_length === 0; + }, + addAll$1: function(_, elements) { + var t1; + H._instanceType(this)._eval$1("Iterable<1>")._check(elements); + for (t1 = elements.get$iterator(elements); t1.moveNext$0();) + this.add$1(0, t1.get$current()); + }, + union$1: function(other) { + var t1; + H._instanceType(this)._eval$1("Set<1>")._check(other); + t1 = this.toSet$0(0); + t1.addAll$1(0, other); + return t1; + }, + toList$1$growable: function(_, growable) { + var i, i0, _this = this, + t1 = H._instanceType(_this), + result = H.setRuntimeTypeInfo([], t1._eval$1("JSArray<1>")); + C.JSArray_methods.set$length(result, _this._collection$_length); + for (t1 = P._LinkedHashSetIterator$(_this, _this._collection$_modifications, t1._precomputed1), i = 0; t1.moveNext$0(); i = i0) { + i0 = i + 1; + C.JSArray_methods.$indexSet(result, i, t1._collection$_current); + } + return result; + }, + toList$0: function($receiver) { + return this.toList$1$growable($receiver, true); + }, + map$1$1: function(_, f, $T) { + var t1 = H._instanceType(this); + return new H.EfficientLengthMappedIterable(this, t1._bind$1($T)._eval$1("1(2)")._check(f), t1._eval$1("@<1>")._bind$1($T)._eval$1("EfficientLengthMappedIterable<1,2>")); + }, + toString$0: function(_) { + return P.IterableBase_iterableToFullString(this, "{", "}"); + }, + where$1: function(_, f) { + var t1 = H._instanceType(this); + return new H.WhereIterable(this, t1._eval$1("bool(1)")._check(f), t1._eval$1("WhereIterable<1>")); + }, + fold$1$2: function(_, initialValue, combine, $T) { + var t1, value; + $T._check(initialValue); + t1 = H._instanceType(this); + t1._bind$1($T)._eval$1("1(1,2)")._check(combine); + for (t1 = P._LinkedHashSetIterator$(this, this._collection$_modifications, t1._precomputed1), value = initialValue; t1.moveNext$0();) + value = combine.call$2(value, t1._collection$_current); + return value; + }, + every$1: function(_, f) { + var t1 = H._instanceType(this); + t1._eval$1("bool(1)")._check(f); + for (t1 = P._LinkedHashSetIterator$(this, this._collection$_modifications, t1._precomputed1); t1.moveNext$0();) + if (!H.boolConversionCheck(f.call$1(t1._collection$_current))) + return false; + return true; + }, + any$1: function(_, test) { + var t1 = H._instanceType(this); + t1._eval$1("bool(1)")._check(test); + for (t1 = P._LinkedHashSetIterator$(this, this._collection$_modifications, t1._precomputed1); t1.moveNext$0();) + if (H.boolConversionCheck(test.call$1(t1._collection$_current))) + return true; + return false; + }, + get$first: function(_) { + var it = P._LinkedHashSetIterator$(this, this._collection$_modifications, H._instanceType(this)._precomputed1); + if (!it.moveNext$0()) + throw H.wrapException(H.IterableElementError_noElement()); + return it._collection$_current; + }, + get$last: function(_) { + var result, + it = P._LinkedHashSetIterator$(this, this._collection$_modifications, H._instanceType(this)._precomputed1); + if (!it.moveNext$0()) + throw H.wrapException(H.IterableElementError_noElement()); + do + result = it._collection$_current; + while (it.moveNext$0()); + return result; + }, + $isEfficientLengthIterable: 1, + $isIterable: 1, + $isSet: 1 + }; + P._ListBase_Object_ListMixin.prototype = {}; + P._SetBase_Object_SetMixin.prototype = {}; + P._UnmodifiableMapView_MapView__UnmodifiableMapMixin.prototype = {}; + P._JsonMap.prototype = { + $index: function(_, key) { + var result, + t1 = this._processed; + if (t1 == null) + return this.get$_upgradedMap().$index(0, key); + else if (typeof key != "string") + return null; + else { + result = t1[key]; + return typeof result == "undefined" ? this._process$1(key) : result; + } + }, + get$length: function(_) { + var t1; + if (this._processed == null) { + t1 = this.get$_upgradedMap(); + t1 = t1.get$length(t1); + } else + t1 = this._convert$_computeKeys$0().length; + return t1; + }, + get$isEmpty: function(_) { + return this.get$length(this) === 0; + }, + get$keys: function() { + if (this._processed == null) + return this.get$_upgradedMap().get$keys(); + return new P._JsonMapKeyIterable(this); + }, + containsKey$1: function(key) { + if (this._processed == null) + return this.get$_upgradedMap().containsKey$1(key); + if (typeof key != "string") + return false; + return Object.prototype.hasOwnProperty.call(this._original, key); + }, + remove$1: function(_, key) { + if (this._processed != null && !this.containsKey$1(key)) + return null; + return this._upgrade$0().remove$1(0, key); + }, + forEach$1: function(_, f) { + var keys, i, key, value, _this = this; + type$.void_Function_String_dynamic._check(f); + if (_this._processed == null) + return _this.get$_upgradedMap().forEach$1(0, f); + keys = _this._convert$_computeKeys$0(); + for (i = 0; i < keys.length; ++i) { + key = keys[i]; + value = _this._processed[key]; + if (typeof value == "undefined") { + value = P._convertJsonToDartLazy(_this._original[key]); + _this._processed[key] = value; + } + f.call$2(key, value); + if (keys !== _this._data) + throw H.wrapException(P.ConcurrentModificationError$(_this)); + } + }, + get$_upgradedMap: function() { + H.assertHelper(this._processed == null); + return this._data; + }, + _convert$_computeKeys$0: function() { + var keys, _this = this; + H.assertHelper(_this._processed != null); + keys = type$.List_dynamic._check(_this._data); + if (keys == null) + keys = _this._data = H.setRuntimeTypeInfo(Object.keys(_this._original), type$.JSArray_String); + return keys; + }, + _upgrade$0: function() { + var result, keys, i, t1, key, _this = this; + if (_this._processed == null) + return _this.get$_upgradedMap(); + result = P.LinkedHashMap_LinkedHashMap$_empty(type$.String, type$.dynamic); + keys = _this._convert$_computeKeys$0(); + for (i = 0; t1 = keys.length, i < t1; ++i) { + key = keys[i]; + result.$indexSet(0, key, _this.$index(0, key)); + } + if (t1 === 0) + C.JSArray_methods.add$1(keys, null); + else + C.JSArray_methods.set$length(keys, 0); + _this._original = _this._processed = null; + return _this._data = result; + }, + _process$1: function(key) { + var result; + if (!Object.prototype.hasOwnProperty.call(this._original, key)) + return null; + result = P._convertJsonToDartLazy(this._original[key]); + return this._processed[key] = result; + } + }; + P._JsonMapKeyIterable.prototype = { + get$length: function(_) { + var t1 = this._parent; + return t1.get$length(t1); + }, + elementAt$1: function(_, index) { + var t1 = this._parent; + if (t1._processed == null) + t1 = t1.get$keys().elementAt$1(0, index); + else { + t1 = t1._convert$_computeKeys$0(); + if (index < 0 || index >= t1.length) + return H.ioore(t1, index); + t1 = t1[index]; + } + return t1; + }, + get$iterator: function(_) { + var t1 = this._parent; + if (t1._processed == null) { + t1 = t1.get$keys(); + t1 = t1.get$iterator(t1); + } else { + t1 = t1._convert$_computeKeys$0(); + t1 = new J.ArrayIterator(t1, t1.length, H._arrayInstanceType(t1)._eval$1("ArrayIterator<1>")); + } + return t1; + }, + contains$1: function(_, key) { + return this._parent.containsKey$1(key); + } + }; + P.AsciiCodec.prototype = { + encode$1: function(source) { + return C.AsciiEncoder_127.convert$1(source); + } + }; + P._UnicodeSubsetEncoder.prototype = { + convert$1: function(string) { + var $length, result, t1, t2, t3, i, codeUnit; + H._checkStringNullable(string); + $length = P.RangeError_checkValidRange(0, null, string.length) - 0; + result = new Uint8Array($length); + for (t1 = result.length, t2 = ~this._subsetMask, t3 = J.getInterceptor$s(string), i = 0; i < $length; ++i) { + codeUnit = t3._codeUnitAt$1(string, i); + if ((codeUnit & t2) !== 0) + throw H.wrapException(P.ArgumentError$value(string, "string", "Contains invalid characters.")); + if (i >= t1) + return H.ioore(result, i); + result[i] = codeUnit; + } + return result; + } + }; + P.AsciiEncoder.prototype = {}; + P.Base64Codec.prototype = { + normalize$3: function(source, start, end) { + var inverseAlphabet, i, sliceStart, buffer, firstPadding, firstPaddingSourceIndex, paddingCount, i0, char, i1, digit1, digit2, char0, value, t2, endLength, $length, + _s31_ = "Invalid base64 encoding length ", + t1 = source.length; + end = P.RangeError_checkValidRange(start, end, t1); + inverseAlphabet = $.$get$_Base64Decoder__inverseAlphabet(); + for (i = start, sliceStart = i, buffer = null, firstPadding = -1, firstPaddingSourceIndex = -1, paddingCount = 0; i < end; i = i0) { + i0 = i + 1; + char = C.JSString_methods._codeUnitAt$1(source, i); + if (char === 37) { + i1 = i0 + 2; + if (i1 <= end) { + H.assertHelper(i1 <= t1); + digit1 = H.hexDigitValue(C.JSString_methods._codeUnitAt$1(source, i0)); + digit2 = H.hexDigitValue(C.JSString_methods._codeUnitAt$1(source, i0 + 1)); + char0 = digit1 * 16 + digit2 - (digit2 & 256); + if (char0 === 37) + char0 = -1; + i0 = i1; + } else + char0 = -1; + } else + char0 = char; + if (0 <= char0 && char0 <= 127) { + if (char0 < 0 || char0 >= inverseAlphabet.length) + return H.ioore(inverseAlphabet, char0); + value = inverseAlphabet[char0]; + if (value >= 0) { + char0 = C.JSString_methods.codeUnitAt$1("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", value); + if (char0 === char) + continue; + char = char0; + } else { + if (value === -1) { + if (firstPadding < 0) { + t2 = buffer == null ? null : buffer._contents.length; + if (t2 == null) + t2 = 0; + firstPadding = t2 + (i - sliceStart); + firstPaddingSourceIndex = i; + } + ++paddingCount; + if (char === 61) + continue; + } + char = char0; + } + if (value !== -2) { + if (buffer == null) + buffer = new P.StringBuffer(""); + t2 = buffer._contents += C.JSString_methods.substring$2(source, sliceStart, i); + buffer._contents = t2 + H.Primitives_stringFromCharCode(char); + sliceStart = i0; + continue; + } + } + throw H.wrapException(P.FormatException$("Invalid base64 data", source, i)); + } + if (buffer != null) { + t1 = buffer._contents += C.JSString_methods.substring$2(source, sliceStart, end); + t2 = t1.length; + if (firstPadding >= 0) + P.Base64Codec__checkPadding(source, firstPaddingSourceIndex, end, firstPadding, paddingCount, t2); + else { + endLength = C.JSInt_methods.$mod(t2 - 1, 4) + 1; + if (endLength === 1) + throw H.wrapException(P.FormatException$(_s31_, source, end)); + for (; endLength < 4;) { + t1 += "="; + buffer._contents = t1; + ++endLength; + } + } + t1 = buffer._contents; + return C.JSString_methods.replaceRange$3(source, start, end, t1.charCodeAt(0) == 0 ? t1 : t1); + } + $length = end - start; + if (firstPadding >= 0) + P.Base64Codec__checkPadding(source, firstPaddingSourceIndex, end, firstPadding, paddingCount, $length); + else { + endLength = C.JSInt_methods.$mod($length, 4); + if (endLength === 1) + throw H.wrapException(P.FormatException$(_s31_, source, end)); + if (endLength > 1) + source = C.JSString_methods.replaceRange$3(source, end, end, endLength === 2 ? "==" : "="); + } + return source; + } + }; + P.Base64Encoder.prototype = {}; + P.Codec.prototype = {}; + P._FusedCodec.prototype = {}; + P.Converter.prototype = {}; + P.Encoding.prototype = {}; + P.JsonCodec.prototype = { + decode$2$reviver: function(source, reviver) { + var t1; + type$.dynamic_Function_Object_Object._check(reviver); + t1 = P._parseJson(source, this.get$decoder()._reviver); + return t1; + }, + get$decoder: function() { + return C.JsonDecoder_null; + } + }; + P.JsonDecoder.prototype = {}; + P.Utf8Codec.prototype = { + get$encoder: function() { + return C.C_Utf8Encoder; + } + }; + P.Utf8Encoder.prototype = { + convert$1: function(string) { + var end, $length, t1, encoder, endPosition, t2, lastCodeUnit; + H._checkStringNullable(string); + end = P.RangeError_checkValidRange(0, null, string.length); + $length = end - 0; + if ($length === 0) + return new Uint8Array(0); + t1 = new Uint8Array($length * 3); + encoder = new P._Utf8Encoder(t1); + endPosition = encoder._fillBuffer$3(string, 0, end); + t2 = end - 1; + H.assertHelper(endPosition >= t2); + if (endPosition !== end) { + lastCodeUnit = J.codeUnitAt$1$s(string, t2); + H.assertHelper((lastCodeUnit & 64512) === 55296); + H.assertHelper(!encoder._writeSurrogate$2(lastCodeUnit, 0)); + } + return C.NativeUint8List_methods.sublist$2(t1, 0, encoder._bufferIndex); + } + }; + P._Utf8Encoder.prototype = { + _writeSurrogate$2: function(leadingSurrogate, nextCodeUnit) { + var rune, t3, t4, _this = this, + t1 = _this._buffer, + t2 = t1.length; + if ((nextCodeUnit & 64512) === 56320) { + rune = 65536 + ((leadingSurrogate & 1023) << 10) | nextCodeUnit & 1023; + H.assertHelper(rune > 65535); + H.assertHelper(rune <= 1114111); + t3 = _this._bufferIndex; + t4 = _this._bufferIndex = t3 + 1; + if (t3 >= t2) + return H.ioore(t1, t3); + t1[t3] = 240 | rune >>> 18; + t3 = _this._bufferIndex = t4 + 1; + if (t4 >= t2) + return H.ioore(t1, t4); + t1[t4] = 128 | rune >>> 12 & 63; + t4 = _this._bufferIndex = t3 + 1; + if (t3 >= t2) + return H.ioore(t1, t3); + t1[t3] = 128 | rune >>> 6 & 63; + _this._bufferIndex = t4 + 1; + if (t4 >= t2) + return H.ioore(t1, t4); + t1[t4] = 128 | rune & 63; + return true; + } else { + t3 = _this._bufferIndex; + t4 = _this._bufferIndex = t3 + 1; + if (t3 >= t2) + return H.ioore(t1, t3); + t1[t3] = 224 | leadingSurrogate >>> 12; + t3 = _this._bufferIndex = t4 + 1; + if (t4 >= t2) + return H.ioore(t1, t4); + t1[t4] = 128 | leadingSurrogate >>> 6 & 63; + _this._bufferIndex = t3 + 1; + if (t3 >= t2) + return H.ioore(t1, t3); + t1[t3] = 128 | leadingSurrogate & 63; + return false; + } + }, + _fillBuffer$3: function(str, start, end) { + var t1, t2, t3, stringIndex, codeUnit, t4, stringIndex0, t5, _this = this; + if (start !== end && (J.codeUnitAt$1$s(str, end - 1) & 64512) === 55296) + --end; + for (t1 = _this._buffer, t2 = t1.length, t3 = J.getInterceptor$s(str), stringIndex = start; stringIndex < end; ++stringIndex) { + codeUnit = t3._codeUnitAt$1(str, stringIndex); + if (codeUnit <= 127) { + t4 = _this._bufferIndex; + if (t4 >= t2) + break; + _this._bufferIndex = t4 + 1; + t1[t4] = codeUnit; + } else if ((codeUnit & 64512) === 55296) { + if (_this._bufferIndex + 3 >= t2) + break; + stringIndex0 = stringIndex + 1; + if (_this._writeSurrogate$2(codeUnit, C.JSString_methods._codeUnitAt$1(str, stringIndex0))) + stringIndex = stringIndex0; + } else if (codeUnit <= 2047) { + t4 = _this._bufferIndex; + t5 = t4 + 1; + if (t5 >= t2) + break; + _this._bufferIndex = t5; + if (t4 >= t2) + return H.ioore(t1, t4); + t1[t4] = 192 | codeUnit >>> 6; + _this._bufferIndex = t5 + 1; + t1[t5] = 128 | codeUnit & 63; + } else { + H.assertHelper(codeUnit <= 65535); + t4 = _this._bufferIndex; + if (t4 + 2 >= t2) + break; + t5 = _this._bufferIndex = t4 + 1; + if (t4 >= t2) + return H.ioore(t1, t4); + t1[t4] = 224 | codeUnit >>> 12; + t4 = _this._bufferIndex = t5 + 1; + if (t5 >= t2) + return H.ioore(t1, t5); + t1[t5] = 128 | codeUnit >>> 6 & 63; + _this._bufferIndex = t4 + 1; + if (t4 >= t2) + return H.ioore(t1, t4); + t1[t4] = 128 | codeUnit & 63; + } + } + return stringIndex; + } + }; + P.Utf8Decoder.prototype = { + convert$1: function(codeUnits) { + var result, end, oneBytes, firstPart, buffer, start, isFirstCharacter, decoder, t1; + type$.List_int._check(codeUnits); + result = P.Utf8Decoder__convertIntercepted(false, codeUnits, 0, null); + if (result != null) + return result; + end = P.RangeError_checkValidRange(0, null, J.get$length$asx(codeUnits)); + oneBytes = P._scanOneByteCharacters(codeUnits, 0, end); + if (oneBytes > 0) { + firstPart = P.String_String$fromCharCodes(codeUnits, 0, oneBytes); + if (oneBytes === end) + return firstPart; + buffer = new P.StringBuffer(firstPart); + start = oneBytes; + isFirstCharacter = false; + } else { + start = 0; + buffer = null; + isFirstCharacter = true; + } + if (buffer == null) + buffer = new P.StringBuffer(""); + decoder = new P._Utf8Decoder(false, buffer); + decoder._isFirstCharacter = isFirstCharacter; + decoder.convert$3(codeUnits, start, end); + decoder.flush$2(codeUnits, end); + t1 = buffer._contents; + return t1.charCodeAt(0) == 0 ? t1 : t1; + } + }; + P._Utf8Decoder.prototype = { + flush$2: function(source, offset) { + var t1; + type$.List_int._check(source); + if (this._expectedUnits > 0) { + t1 = P.FormatException$("Unfinished UTF-8 octet sequence", source, offset); + throw H.wrapException(t1); + } + }, + convert$3: function(codeUnits, startIndex, endIndex) { + var value, expectedUnits, extraUnits, t1, t2, i, unit, t3, oneBytes, i0, i1, t4, _this = this, + _s21_ = "Bad UTF-8 encoding 0x"; + type$.List_int._check(codeUnits); + value = _this._convert$_value; + expectedUnits = _this._expectedUnits; + extraUnits = _this._extraUnits; + _this._extraUnits = _this._expectedUnits = _this._convert$_value = 0; + $label0$0: + for (t1 = J.getInterceptor$asx(codeUnits), t2 = _this._stringSink, i = startIndex; true; i = i1) { + $label1$1: + if (expectedUnits > 0) { + do { + if (i === endIndex) + break $label0$0; + unit = t1.$index(codeUnits, i); + if (typeof unit !== "number") + return unit.$and(); + if ((unit & 192) !== 128) { + t3 = P.FormatException$(_s21_ + C.JSInt_methods.toRadixString$1(unit, 16), codeUnits, i); + throw H.wrapException(t3); + } else { + value = (value << 6 | unit & 63) >>> 0; + --expectedUnits; + ++i; + } + } while (expectedUnits > 0); + t3 = extraUnits - 1; + if (t3 < 0 || t3 >= 4) + return H.ioore(C.List_127_2047_65535_1114111, t3); + if (value <= C.List_127_2047_65535_1114111[t3]) { + t3 = P.FormatException$("Overlong encoding of 0x" + C.JSInt_methods.toRadixString$1(value, 16), codeUnits, i - extraUnits - 1); + throw H.wrapException(t3); + } + if (value > 1114111) { + t3 = P.FormatException$("Character outside valid Unicode range: 0x" + C.JSInt_methods.toRadixString$1(value, 16), codeUnits, i - extraUnits - 1); + throw H.wrapException(t3); + } + if (!_this._isFirstCharacter || value !== 65279) + t2._contents += H.Primitives_stringFromCharCode(value); + _this._isFirstCharacter = false; + } + for (t3 = i < endIndex; t3;) { + oneBytes = P._scanOneByteCharacters(codeUnits, i, endIndex); + if (oneBytes > 0) { + _this._isFirstCharacter = false; + i0 = i + oneBytes; + H.assertHelper(i0 <= endIndex); + t2._contents += P.String_String$fromCharCodes(codeUnits, i, i0); + if (i0 === endIndex) + break; + } else + i0 = i; + i1 = i0 + 1; + unit = t1.$index(codeUnits, i0); + if (typeof unit !== "number") + return unit.$lt(); + if (unit < 0) { + t4 = P.FormatException$("Negative UTF-8 code unit: -0x" + C.JSInt_methods.toRadixString$1(-unit, 16), codeUnits, i1 - 1); + throw H.wrapException(t4); + } else { + H.assertHelper(unit > 127); + if ((unit & 224) === 192) { + value = unit & 31; + expectedUnits = 1; + extraUnits = 1; + continue $label0$0; + } + if ((unit & 240) === 224) { + value = unit & 15; + expectedUnits = 2; + extraUnits = 2; + continue $label0$0; + } + if ((unit & 248) === 240 && unit < 245) { + value = unit & 7; + expectedUnits = 3; + extraUnits = 3; + continue $label0$0; + } + t4 = P.FormatException$(_s21_ + C.JSInt_methods.toRadixString$1(unit, 16), codeUnits, i1 - 1); + throw H.wrapException(t4); + } + } + break $label0$0; + } + if (expectedUnits > 0) { + _this._convert$_value = value; + _this._expectedUnits = expectedUnits; + _this._extraUnits = extraUnits; + } + } + }; + P.bool.prototype = {}; + P.DateTime.prototype = { + $eq: function(_, other) { + if (other == null) + return false; + return other instanceof P.DateTime && this._value === other._value && true; + }, + get$hashCode: function(_) { + var t1 = this._value; + return (t1 ^ C.JSInt_methods._shrOtherPositive$1(t1, 30)) & 1073741823; + }, + toString$0: function(_) { + var _this = this, + y = P.DateTime__fourDigits(H.Primitives_getYear(_this)), + m = P.DateTime__twoDigits(H.Primitives_getMonth(_this)), + d = P.DateTime__twoDigits(H.Primitives_getDay(_this)), + h = P.DateTime__twoDigits(H.Primitives_getHours(_this)), + min = P.DateTime__twoDigits(H.Primitives_getMinutes(_this)), + sec = P.DateTime__twoDigits(H.Primitives_getSeconds(_this)), + ms = P.DateTime__threeDigits(H.Primitives_getMilliseconds(_this)), + t1 = y + "-" + m + "-" + d + " " + h + ":" + min + ":" + sec + "." + ms + "Z"; + return t1; + } + }; + P.double.prototype = {}; + P.Duration.prototype = { + $eq: function(_, other) { + if (other == null) + return false; + return other instanceof P.Duration && this._duration === other._duration; + }, + get$hashCode: function(_) { + return C.JSInt_methods.get$hashCode(this._duration); + }, + toString$0: function(_) { + var twoDigitMinutes, twoDigitSeconds, sixDigitUs, + t1 = new P.Duration_toString_twoDigits(), + t2 = this._duration; + if (t2 < 0) + return "-" + new P.Duration(0 - t2).toString$0(0); + twoDigitMinutes = t1.call$1(C.JSInt_methods._tdivFast$1(t2, 60000000) % 60); + twoDigitSeconds = t1.call$1(C.JSInt_methods._tdivFast$1(t2, 1000000) % 60); + sixDigitUs = new P.Duration_toString_sixDigits().call$1(t2 % 1000000); + return "" + C.JSInt_methods._tdivFast$1(t2, 3600000000) + ":" + H.S(twoDigitMinutes) + ":" + H.S(twoDigitSeconds) + "." + H.S(sixDigitUs); + } + }; + P.Duration_toString_sixDigits.prototype = { + call$1: function(n) { + if (n >= 100000) + return "" + n; + if (n >= 10000) + return "0" + n; + if (n >= 1000) + return "00" + n; + if (n >= 100) + return "000" + n; + if (n >= 10) + return "0000" + n; + return "00000" + n; + }, + $signature: 25 + }; + P.Duration_toString_twoDigits.prototype = { + call$1: function(n) { + if (n >= 10) + return "" + n; + return "0" + n; + }, + $signature: 25 + }; + P.Error.prototype = {}; + P.AssertionError.prototype = { + toString$0: function(_) { + var t1 = this.message; + if (t1 != null) + return "Assertion failed: " + P.Error_safeToString(t1); + return "Assertion failed"; + }, + get$message: function(receiver) { + return this.message; + } + }; + P.NullThrownError.prototype = { + toString$0: function(_) { + return "Throw of null."; + } + }; + P.ArgumentError.prototype = { + get$_errorName: function() { + return "Invalid argument" + (!this._hasValue ? "(s)" : ""); + }, + get$_errorExplanation: function() { + return ""; + }, + toString$0: function(_) { + var message, prefix, explanation, errorValue, _this = this, + t1 = _this.name, + nameString = t1 != null ? " (" + t1 + ")" : ""; + t1 = _this.message; + message = t1 == null ? "" : ": " + H.S(t1); + prefix = _this.get$_errorName() + nameString + message; + if (!_this._hasValue) + return prefix; + explanation = _this.get$_errorExplanation(); + errorValue = P.Error_safeToString(_this.invalidValue); + return prefix + explanation + ": " + errorValue; + }, + get$message: function(receiver) { + return this.message; + } + }; + P.RangeError.prototype = { + get$_errorName: function() { + return "RangeError"; + }, + get$_errorExplanation: function() { + var t1, explanation, t2, _this = this; + H.assertHelper(_this._hasValue); + t1 = _this.start; + if (t1 == null) { + t1 = _this.end; + explanation = t1 != null ? ": Not less than or equal to " + H.S(t1) : ""; + } else { + t2 = _this.end; + if (t2 == null) + explanation = ": Not greater than or equal to " + H.S(t1); + else if (t2 > t1) + explanation = ": Not in range " + H.S(t1) + ".." + H.S(t2) + ", inclusive"; + else + explanation = t2 < t1 ? ": Valid value range is empty" : ": Only valid value is " + H.S(t1); + } + return explanation; + } + }; + P.IndexError.prototype = { + get$_errorName: function() { + return "RangeError"; + }, + get$_errorExplanation: function() { + var invalidValue, t1; + H.assertHelper(this._hasValue); + invalidValue = H._checkIntNullable(this.invalidValue); + if (typeof invalidValue !== "number") + return invalidValue.$lt(); + if (invalidValue < 0) + return ": index must not be negative"; + t1 = this.length; + if (t1 === 0) + return ": no indices are valid"; + return ": index should be less than " + H.S(t1); + }, + get$length: function(receiver) { + return this.length; + } + }; + P.UnsupportedError.prototype = { + toString$0: function(_) { + return "Unsupported operation: " + this.message; + }, + get$message: function(receiver) { + return this.message; + } + }; + P.UnimplementedError.prototype = { + toString$0: function(_) { + var t1 = this.message; + return t1 != null ? "UnimplementedError: " + t1 : "UnimplementedError"; + }, + get$message: function(receiver) { + return this.message; + } + }; + P.StateError.prototype = { + toString$0: function(_) { + return "Bad state: " + this.message; + }, + get$message: function(receiver) { + return this.message; + } + }; + P.ConcurrentModificationError.prototype = { + toString$0: function(_) { + var t1 = this.modifiedObject; + if (t1 == null) + return "Concurrent modification during iteration."; + return "Concurrent modification during iteration: " + P.Error_safeToString(t1) + "."; + } + }; + P.OutOfMemoryError.prototype = { + toString$0: function(_) { + return "Out of Memory"; + }, + $isError: 1 + }; + P.StackOverflowError.prototype = { + toString$0: function(_) { + return "Stack Overflow"; + }, + $isError: 1 + }; + P.CyclicInitializationError.prototype = { + toString$0: function(_) { + var t1 = this.variableName; + return t1 == null ? "Reading static variable during its initialization" : "Reading static variable '" + t1 + "' during its initialization"; + } + }; + P._Exception.prototype = { + toString$0: function(_) { + return "Exception: " + this.message; + }, + $isException: 1, + get$message: function(receiver) { + return this.message; + } + }; + P.FormatException.prototype = { + toString$0: function(_) { + var source, lineNum, lineStart, previousCharWasCR, i, char, lineEnd, end, start, prefix, postfix, slice, + t1 = this.message, + report = t1 != null && "" !== t1 ? "FormatException: " + H.S(t1) : "FormatException", + offset = this.offset, + objectSource = this.source; + if (typeof objectSource == "string") { + if (offset != null) + t1 = offset < 0 || offset > objectSource.length; + else + t1 = false; + if (t1) + offset = null; + if (offset == null) { + source = objectSource.length > 78 ? C.JSString_methods.substring$2(objectSource, 0, 75) + "..." : objectSource; + return report + "\n" + source; + } + for (lineNum = 1, lineStart = 0, previousCharWasCR = false, i = 0; i < offset; ++i) { + char = C.JSString_methods._codeUnitAt$1(objectSource, i); + if (char === 10) { + if (lineStart !== i || !previousCharWasCR) + ++lineNum; + lineStart = i + 1; + previousCharWasCR = false; + } else if (char === 13) { + ++lineNum; + lineStart = i + 1; + previousCharWasCR = true; + } + } + report = lineNum > 1 ? report + (" (at line " + lineNum + ", character " + (offset - lineStart + 1) + ")\n") : report + (" (at character " + (offset + 1) + ")\n"); + lineEnd = objectSource.length; + for (i = offset; i < lineEnd; ++i) { + char = C.JSString_methods.codeUnitAt$1(objectSource, i); + if (char === 10 || char === 13) { + lineEnd = i; + break; + } + } + if (lineEnd - lineStart > 78) + if (offset - lineStart < 75) { + end = lineStart + 75; + start = lineStart; + prefix = ""; + postfix = "..."; + } else { + if (lineEnd - offset < 75) { + start = lineEnd - 75; + end = lineEnd; + postfix = ""; + } else { + start = offset - 36; + end = offset + 36; + postfix = "..."; + } + prefix = "..."; + } + else { + end = lineEnd; + start = lineStart; + prefix = ""; + postfix = ""; + } + slice = C.JSString_methods.substring$2(objectSource, start, end); + return report + prefix + slice + postfix + "\n" + C.JSString_methods.$mul(" ", offset - start + prefix.length) + "^\n"; + } else + return offset != null ? report + (" (at offset " + H.S(offset) + ")") : report; + }, + $isException: 1, + get$message: function(receiver) { + return this.message; + } + }; + P.Expando.prototype = { + $index: function(_, object) { + var t2, values, + t1 = this._jsWeakMapOrKey; + if (typeof t1 != "string") { + if (object != null) + t2 = typeof object == "number" || typeof object == "string"; + else + t2 = true; + if (t2) + H.throwExpression(P.ArgumentError$value(object, "Expandos are not allowed on strings, numbers, booleans or null", null)); + return t1.get(object); + } + values = H.Primitives_getProperty(object, "expando$values"); + t1 = values == null ? null : H.Primitives_getProperty(values, t1); + return this.$ti._precomputed1._check(t1); + }, + $indexSet: function(_, object, value) { + var t1, values, + _s14_ = "expando$values"; + this.$ti._precomputed1._check(value); + t1 = this._jsWeakMapOrKey; + if (typeof t1 != "string") + t1.set(object, value); + else { + values = H.Primitives_getProperty(object, _s14_); + if (values == null) { + values = new P.Object(); + H.Primitives_setProperty(object, _s14_, values); + } + H.Primitives_setProperty(values, t1, value); + } + }, + toString$0: function(_) { + return "Expando:" + this.name; + } + }; + P.Function.prototype = {}; + P.int.prototype = {}; + P.Iterable.prototype = { + map$1$1: function(_, f, $T) { + var t1 = H._instanceType(this); + return H.MappedIterable_MappedIterable(this, t1._bind$1($T)._eval$1("1(Iterable.E)")._check(f), t1._eval$1("Iterable.E"), $T); + }, + where$1: function(_, test) { + var t1 = H._instanceType(this); + return new H.WhereIterable(this, t1._eval$1("bool(Iterable.E)")._check(test), t1._eval$1("WhereIterable<Iterable.E>")); + }, + contains$1: function(_, element) { + var t1; + for (t1 = this.get$iterator(this); t1.moveNext$0();) + if (J.$eq$(t1.get$current(), element)) + return true; + return false; + }, + join$1: function(_, separator) { + var t1, + iterator = this.get$iterator(this); + if (!iterator.moveNext$0()) + return ""; + if (separator === "") { + t1 = ""; + do + t1 += H.S(iterator.get$current()); + while (iterator.moveNext$0()); + } else { + t1 = H.S(iterator.get$current()); + for (; iterator.moveNext$0();) + t1 = t1 + separator + H.S(iterator.get$current()); + } + return t1.charCodeAt(0) == 0 ? t1 : t1; + }, + join$0: function($receiver) { + return this.join$1($receiver, ""); + }, + toList$1$growable: function(_, growable) { + return P.List_List$from(this, true, H._instanceType(this)._eval$1("Iterable.E")); + }, + toList$0: function($receiver) { + return this.toList$1$growable($receiver, true); + }, + toSet$0: function(_) { + return P.LinkedHashSet_LinkedHashSet$from(this, H._instanceType(this)._eval$1("Iterable.E")); + }, + get$length: function(_) { + var it, count; + H.assertHelper(!type$.EfficientLengthIterable_dynamic._is(this)); + it = this.get$iterator(this); + for (count = 0; it.moveNext$0();) + ++count; + return count; + }, + get$isEmpty: function(_) { + return !this.get$iterator(this).moveNext$0(); + }, + skipWhile$1: function(_, test) { + var t1 = H._instanceType(this); + return new H.SkipWhileIterable(this, t1._eval$1("bool(Iterable.E)")._check(test), t1._eval$1("SkipWhileIterable<Iterable.E>")); + }, + get$first: function(_) { + var it = this.get$iterator(this); + if (!it.moveNext$0()) + throw H.wrapException(H.IterableElementError_noElement()); + return it.get$current(); + }, + get$last: function(_) { + var result, + it = this.get$iterator(this); + if (!it.moveNext$0()) + throw H.wrapException(H.IterableElementError_noElement()); + do + result = it.get$current(); + while (it.moveNext$0()); + return result; + }, + elementAt$1: function(_, index) { + var t1, elementIndex, element; + P.RangeError_checkNotNegative(index, "index"); + for (t1 = this.get$iterator(this), elementIndex = 0; t1.moveNext$0();) { + element = t1.get$current(); + if (index === elementIndex) + return element; + ++elementIndex; + } + throw H.wrapException(P.IndexError$(index, this, "index", null, elementIndex)); + }, + toString$0: function(_) { + return P.IterableBase_iterableToShortString(this, "(", ")"); + } + }; + P.Iterator.prototype = {}; + P.List.prototype = {$isEfficientLengthIterable: 1, $isIterable: 1}; + P.Map.prototype = {}; + P.MapEntry.prototype = { + toString$0: function(_) { + return "MapEntry(" + H.S(this.key) + ": " + H.S(this.value) + ")"; + } + }; + P.Null.prototype = { + get$hashCode: function(_) { + return P.Object.prototype.get$hashCode.call(this, this); + }, + toString$0: function(_) { + return "null"; + } + }; + P.num.prototype = {}; + P.Object.prototype = {constructor: P.Object, $isObject: 1, + $eq: function(_, other) { + return this === other; + }, + get$hashCode: function(_) { + return H.Primitives_objectHashCode(this); + }, + toString$0: function(_) { + return "Instance of '" + H.S(H.Primitives_objectTypeName(this)) + "'"; + }, + get$runtimeType: function(_) { + return H.getRuntimeType(this); + }, + toString: function() { + return this.toString$0(this); + } + }; + P.Pattern.prototype = {}; + P.Match.prototype = {}; + P.RegExpMatch.prototype = {$isMatch: 1}; + P.Set.prototype = {}; + P.StackTrace.prototype = {}; + P._StringStackTrace.prototype = { + toString$0: function(_) { + return this._stackTrace; + }, + $isStackTrace: 1 + }; + P.Stopwatch.prototype = { + get$elapsedMicroseconds: function() { + var t2, ticks, + t1 = this._stop; + if (t1 == null) + t1 = H._checkIntNullable($.Primitives_timerTicks.call$0()); + t2 = this._core$_start; + if (typeof t1 !== "number") + return t1.$sub(); + ticks = t1 - t2; + t1 = $.Stopwatch__frequency; + if (t1 === 1000000) + return ticks; + H.assertHelper(t1 === 1000); + return ticks * 1000; + } + }; + P.String.prototype = {$isPattern: 1}; + P.Runes.prototype = { + get$iterator: function(_) { + return new P.RuneIterator(this.string); + }, + get$last: function(_) { + var code, previousCode, + t1 = this.string, + t2 = t1.length; + if (t2 === 0) + throw H.wrapException(P.StateError$("No elements.")); + code = C.JSString_methods.codeUnitAt$1(t1, t2 - 1); + if ((code & 64512) === 56320 && t2 > 1) { + previousCode = C.JSString_methods.codeUnitAt$1(t1, t2 - 2); + if ((previousCode & 64512) === 55296) + return P._combineSurrogatePair(previousCode, code); + } + return code; + } + }; + P.RuneIterator.prototype = { + get$current: function() { + return this._currentCodePoint; + }, + moveNext$0: function() { + var codeUnit, nextPosition, nextCodeUnit, _this = this, + t1 = _this._core$_position = _this._nextPosition, + t2 = _this.string, + t3 = t2.length; + if (t1 === t3) { + _this._currentCodePoint = null; + return false; + } + codeUnit = C.JSString_methods._codeUnitAt$1(t2, t1); + nextPosition = t1 + 1; + if ((codeUnit & 64512) === 55296 && nextPosition < t3) { + nextCodeUnit = C.JSString_methods._codeUnitAt$1(t2, nextPosition); + if ((nextCodeUnit & 64512) === 56320) { + _this._nextPosition = nextPosition + 1; + _this._currentCodePoint = P._combineSurrogatePair(codeUnit, nextCodeUnit); + return true; + } + } + _this._nextPosition = nextPosition; + _this._currentCodePoint = codeUnit; + return true; + }, + $isIterator: 1 + }; + P.StringBuffer.prototype = { + get$length: function(_) { + return this._contents.length; + }, + toString$0: function(_) { + var t1 = this._contents; + return t1.charCodeAt(0) == 0 ? t1 : t1; + }, + $isStringSink: 1 + }; + P.Uri.prototype = {}; + P.Uri__parseIPv4Address_error.prototype = { + call$2: function(msg, position) { + throw H.wrapException(P.FormatException$("Illegal IPv4 address, " + msg, this.host, position)); + }, + $signature: 68 + }; + P.Uri_parseIPv6Address_error.prototype = { + call$2: function(msg, position) { + throw H.wrapException(P.FormatException$("Illegal IPv6 address, " + msg, this.host, position)); + }, + call$1: function(msg) { + return this.call$2(msg, null); + }, + $signature: 67 + }; + P.Uri_parseIPv6Address_parseHex.prototype = { + call$2: function(start, end) { + var value; + if (end - start > 4) + this.error.call$2("an IPv6 part can only contain a maximum of 4 hex digits", start); + value = P.int_parse(C.JSString_methods.substring$2(this.host, start, end), null, 16); + if (typeof value !== "number") + return value.$lt(); + if (value < 0 || value > 65535) + this.error.call$2("each part must be in the range of `0x0..0xFFFF`", start); + return value; + }, + $signature: 65 + }; + P._Uri.prototype = { + get$userInfo: function() { + return this._userInfo; + }, + get$host: function(_) { + var t1 = this._host; + if (t1 == null) + return ""; + if (C.JSString_methods.startsWith$1(t1, "[")) + return C.JSString_methods.substring$2(t1, 1, t1.length - 1); + return t1; + }, + get$port: function(_) { + var t1 = this._port; + if (t1 == null) + return P._Uri__defaultPort(this.scheme); + return t1; + }, + get$query: function() { + var t1 = this._query; + return t1 == null ? "" : t1; + }, + get$fragment: function() { + var t1 = this._fragment; + return t1 == null ? "" : t1; + }, + replace$2$path$pathSegments: function(_, path, pathSegments) { + var scheme, isFile, userInfo, port, host, hasAuthority, t1, _this = this; + type$.Iterable_String._check(pathSegments); + type$.Map_String_dynamic._check(null); + scheme = _this.scheme; + isFile = scheme === "file"; + userInfo = _this._userInfo; + port = _this._port; + host = _this._host; + if (!(host != null)) + host = userInfo.length !== 0 || port != null || isFile ? "" : null; + hasAuthority = host != null; + t1 = path == null; + if (!t1 || pathSegments != null) + path = P._Uri__makePath(path, 0, t1 ? 0 : path.length, pathSegments, scheme, hasAuthority); + else { + path = _this.path; + if (!isFile) + t1 = hasAuthority && path.length !== 0; + else + t1 = true; + if (t1 && !C.JSString_methods.startsWith$1(path, "/")) + path = "/" + path; + } + return new P._Uri(scheme, userInfo, host, port, path, _this._query, _this._fragment); + }, + replace$1$path: function($receiver, path) { + return this.replace$2$path$pathSegments($receiver, path, null); + }, + replace$1$pathSegments: function($receiver, pathSegments) { + return this.replace$2$path$pathSegments($receiver, null, pathSegments); + }, + get$pathSegments: function() { + var pathToSplit, + result = this._pathSegments; + if (result != null) + return result; + pathToSplit = this.path; + if (pathToSplit.length !== 0 && C.JSString_methods._codeUnitAt$1(pathToSplit, 0) === 47) + pathToSplit = C.JSString_methods.substring$1(pathToSplit, 1); + result = pathToSplit === "" ? C.List_empty : P.List_List$unmodifiable(new H.MappedListIterable(H.setRuntimeTypeInfo(pathToSplit.split("/"), type$.JSArray_String), type$.dynamic_Function_String._check(P.core_Uri_decodeComponent$closure()), type$.MappedListIterable_String_dynamic), type$.String); + this.set$_pathSegments(result); + return result; + }, + _mergePaths$2: function(base, reference) { + var backCount, refStart, baseEnd, newEnd, delta, t1; + for (backCount = 0, refStart = 0; C.JSString_methods.startsWith$2(reference, "../", refStart);) { + refStart += 3; + ++backCount; + } + baseEnd = C.JSString_methods.lastIndexOf$1(base, "/"); + while (true) { + if (!(baseEnd > 0 && backCount > 0)) + break; + newEnd = C.JSString_methods.lastIndexOf$2(base, "/", baseEnd - 1); + if (newEnd < 0) + break; + delta = baseEnd - newEnd; + t1 = delta !== 2; + if (!t1 || delta === 3) + if (C.JSString_methods.codeUnitAt$1(base, newEnd + 1) === 46) + t1 = !t1 || C.JSString_methods.codeUnitAt$1(base, newEnd + 2) === 46; + else + t1 = false; + else + t1 = false; + if (t1) + break; + --backCount; + baseEnd = newEnd; + } + return C.JSString_methods.replaceRange$3(base, baseEnd + 1, null, C.JSString_methods.substring$1(reference, refStart - 3 * backCount)); + }, + resolve$1: function(reference) { + return this.resolveUri$1(P.Uri_parse(reference)); + }, + resolveUri$1: function(reference) { + var targetScheme, targetUserInfo, targetHost, targetPort, targetPath, targetQuery, t1, mergedPath, t2, _this = this, _null = null; + if (reference.get$scheme().length !== 0) { + targetScheme = reference.get$scheme(); + if (reference.get$hasAuthority()) { + targetUserInfo = reference.get$userInfo(); + targetHost = reference.get$host(reference); + targetPort = reference.get$hasPort() ? reference.get$port(reference) : _null; + } else { + targetPort = _null; + targetHost = targetPort; + targetUserInfo = ""; + } + targetPath = P._Uri__removeDotSegments(reference.get$path(reference)); + targetQuery = reference.get$hasQuery() ? reference.get$query() : _null; + } else { + targetScheme = _this.scheme; + if (reference.get$hasAuthority()) { + targetUserInfo = reference.get$userInfo(); + targetHost = reference.get$host(reference); + targetPort = P._Uri__makePort(reference.get$hasPort() ? reference.get$port(reference) : _null, targetScheme); + targetPath = P._Uri__removeDotSegments(reference.get$path(reference)); + targetQuery = reference.get$hasQuery() ? reference.get$query() : _null; + } else { + targetUserInfo = _this._userInfo; + targetHost = _this._host; + targetPort = _this._port; + if (reference.get$path(reference) === "") { + targetPath = _this.path; + targetQuery = reference.get$hasQuery() ? reference.get$query() : _this._query; + } else { + if (reference.get$hasAbsolutePath()) + targetPath = P._Uri__removeDotSegments(reference.get$path(reference)); + else { + t1 = _this.path; + if (t1.length === 0) + if (targetHost == null) + targetPath = targetScheme.length === 0 ? reference.get$path(reference) : P._Uri__removeDotSegments(reference.get$path(reference)); + else + targetPath = P._Uri__removeDotSegments("/" + reference.get$path(reference)); + else { + mergedPath = _this._mergePaths$2(t1, reference.get$path(reference)); + t2 = targetScheme.length === 0; + if (!t2 || targetHost != null || C.JSString_methods.startsWith$1(t1, "/")) + targetPath = P._Uri__removeDotSegments(mergedPath); + else + targetPath = P._Uri__normalizeRelativePath(mergedPath, !t2 || targetHost != null); + } + } + targetQuery = reference.get$hasQuery() ? reference.get$query() : _null; + } + } + } + return new P._Uri(targetScheme, targetUserInfo, targetHost, targetPort, targetPath, targetQuery, reference.get$hasFragment() ? reference.get$fragment() : _null); + }, + get$hasAuthority: function() { + return this._host != null; + }, + get$hasPort: function() { + return this._port != null; + }, + get$hasQuery: function() { + return this._query != null; + }, + get$hasFragment: function() { + return this._fragment != null; + }, + get$hasAbsolutePath: function() { + return C.JSString_methods.startsWith$1(this.path, "/"); + }, + toFilePath$0: function() { + var windows, pathSegments, _this = this, + t1 = _this.scheme; + if (t1 !== "" && t1 !== "file") + throw H.wrapException(P.UnsupportedError$("Cannot extract a file path from a " + H.S(t1) + " URI")); + t1 = _this._query; + if ((t1 == null ? "" : t1) !== "") + throw H.wrapException(P.UnsupportedError$("Cannot extract a file path from a URI with a query component")); + t1 = _this._fragment; + if ((t1 == null ? "" : t1) !== "") + throw H.wrapException(P.UnsupportedError$("Cannot extract a file path from a URI with a fragment component")); + windows = $.$get$_Uri__isWindowsCached(); + if (H.boolConversionCheck(windows)) + t1 = P._Uri__toWindowsFilePath(_this); + else { + if (_this._host != null && _this.get$host(_this) !== "") + H.throwExpression(P.UnsupportedError$("Cannot extract a non-Windows file path from a file URI with an authority")); + pathSegments = _this.get$pathSegments(); + P._Uri__checkNonWindowsPathReservedCharacters(pathSegments, false); + t1 = P.StringBuffer__writeAll(C.JSString_methods.startsWith$1(_this.path, "/") ? "/" : "", pathSegments, "/"); + t1 = t1.charCodeAt(0) == 0 ? t1 : t1; + } + return t1; + }, + toString$0: function(_) { + var t2, t3, t4, _this = this, + t1 = _this._text; + if (t1 == null) { + t1 = _this.scheme; + t2 = t1.length !== 0 ? t1 + ":" : ""; + t3 = _this._host; + t4 = t3 == null; + if (!t4 || t1 === "file") { + t1 = t2 + "//"; + t2 = _this._userInfo; + if (t2.length !== 0) + t1 = t1 + t2 + "@"; + if (!t4) + t1 += t3; + t2 = _this._port; + if (t2 != null) + t1 = t1 + ":" + H.S(t2); + } else + t1 = t2; + t1 += _this.path; + t2 = _this._query; + if (t2 != null) + t1 = t1 + "?" + t2; + t2 = _this._fragment; + if (t2 != null) + t1 = t1 + "#" + t2; + t1 = _this._text = t1.charCodeAt(0) == 0 ? t1 : t1; + } + return t1; + }, + $eq: function(_, other) { + var t1, t2, _this = this; + if (other == null) + return false; + if (_this === other) + return true; + if (type$.Uri._is(other)) + if (_this.scheme == other.get$scheme()) + if (_this._host != null === other.get$hasAuthority()) + if (_this._userInfo == other.get$userInfo()) + if (_this.get$host(_this) == other.get$host(other)) + if (_this.get$port(_this) == other.get$port(other)) + if (_this.path === other.get$path(other)) { + t1 = _this._query; + t2 = t1 == null; + if (!t2 === other.get$hasQuery()) { + if (t2) + t1 = ""; + if (t1 === other.get$query()) { + t1 = _this._fragment; + t2 = t1 == null; + if (!t2 === other.get$hasFragment()) { + if (t2) + t1 = ""; + t1 = t1 === other.get$fragment(); + } else + t1 = false; + } else + t1 = false; + } else + t1 = false; + } else + t1 = false; + else + t1 = false; + else + t1 = false; + else + t1 = false; + else + t1 = false; + else + t1 = false; + else + t1 = false; + return t1; + }, + get$hashCode: function(_) { + var t1 = this._hashCodeCache; + return t1 == null ? this._hashCodeCache = C.JSString_methods.get$hashCode(this.toString$0(0)) : t1; + }, + set$_pathSegments: function(_pathSegments) { + this._pathSegments = type$.List_String._check(_pathSegments); + }, + $isUri: 1, + get$scheme: function() { + return this.scheme; + }, + get$path: function(receiver) { + return this.path; + } + }; + P._Uri__Uri$notSimple_closure.prototype = { + call$1: function(_) { + throw H.wrapException(P.FormatException$("Invalid port", this.uri, this.portStart + 1)); + }, + $signature: 30 + }; + P._Uri__checkNonWindowsPathReservedCharacters_closure.prototype = { + call$1: function(segment) { + var _s23_ = "Illegal path character "; + H._checkStringNullable(segment); + if (J.contains$1$asx(segment, "/")) + if (this.argumentError) + throw H.wrapException(P.ArgumentError$(_s23_ + segment)); + else + throw H.wrapException(P.UnsupportedError$(_s23_ + segment)); + }, + $signature: 30 + }; + P._Uri__makePath_closure.prototype = { + call$1: function(s) { + return P._Uri__uriEncode(C.List_qg40, H._checkStringNullable(s), C.C_Utf8Codec, false); + }, + $signature: 7 + }; + P.UriData.prototype = { + get$uri: function() { + var t2, queryIndex, end, query, _this = this, _null = null, + t1 = _this._uriCache; + if (t1 != null) + return t1; + t1 = _this._separatorIndices; + if (0 >= t1.length) + return H.ioore(t1, 0); + t2 = _this._text; + t1 = t1[0] + 1; + queryIndex = C.JSString_methods.indexOf$2(t2, "?", t1); + end = t2.length; + if (queryIndex >= 0) { + query = P._Uri__normalizeOrSubstring(t2, queryIndex + 1, end, C.List_CVk, false); + end = queryIndex; + } else + query = _null; + return _this._uriCache = new P._DataUri("data", _null, _null, _null, P._Uri__normalizeOrSubstring(t2, t1, end, C.List_qg4, false), query, _null); + }, + toString$0: function(_) { + var t2, + t1 = this._separatorIndices; + if (0 >= t1.length) + return H.ioore(t1, 0); + t2 = this._text; + return t1[0] === -1 ? "data:" + t2 : t2; + } + }; + P._createTables_closure.prototype = { + call$1: function(_) { + return new Uint8Array(96); + }, + $signature: 64 + }; + P._createTables_build.prototype = { + call$2: function(state, defaultTransition) { + var t1 = this.tables; + if (state >= t1.length) + return H.ioore(t1, state); + t1 = t1[state]; + J.fillRange$3$ax(t1, 0, 96, defaultTransition); + return t1; + }, + $signature: 62 + }; + P._createTables_setChars.prototype = { + call$3: function(target, chars, transition) { + var t1, t2, i, t3; + for (t1 = chars.length, t2 = target.length, i = 0; i < t1; ++i) { + t3 = C.JSString_methods._codeUnitAt$1(chars, i) ^ 96; + if (t3 >= t2) + return H.ioore(target, t3); + target[t3] = transition; + } + }, + $signature: 41 + }; + P._createTables_setRange.prototype = { + call$3: function(target, range, transition) { + var i, n, t1, t2; + for (i = C.JSString_methods._codeUnitAt$1(range, 0), n = C.JSString_methods._codeUnitAt$1(range, 1), t1 = target.length; i <= n; ++i) { + t2 = (i ^ 96) >>> 0; + if (t2 >= t1) + return H.ioore(target, t2); + target[t2] = transition; + } + }, + $signature: 41 + }; + P._SimpleUri.prototype = { + get$hasAuthority: function() { + return this._hostStart > 0; + }, + get$hasPort: function() { + return this._hostStart > 0 && this._portStart + 1 < this._pathStart; + }, + get$hasQuery: function() { + return this._queryStart < this._fragmentStart; + }, + get$hasFragment: function() { + return this._fragmentStart < this._uri.length; + }, + get$_isFile: function() { + return this._schemeEnd === 4 && C.JSString_methods.startsWith$1(this._uri, "file"); + }, + get$_isHttp: function() { + return this._schemeEnd === 4 && C.JSString_methods.startsWith$1(this._uri, "http"); + }, + get$_isHttps: function() { + return this._schemeEnd === 5 && C.JSString_methods.startsWith$1(this._uri, "https"); + }, + get$hasAbsolutePath: function() { + return C.JSString_methods.startsWith$2(this._uri, "/", this._pathStart); + }, + get$scheme: function() { + var t2, _this = this, + _s7_ = "package", + t1 = _this._schemeEnd; + if (t1 <= 0) + return ""; + t2 = _this._schemeCache; + if (t2 != null) + return t2; + if (_this.get$_isHttp()) + t1 = _this._schemeCache = "http"; + else if (_this.get$_isHttps()) { + _this._schemeCache = "https"; + t1 = "https"; + } else if (_this.get$_isFile()) { + _this._schemeCache = "file"; + t1 = "file"; + } else if (t1 === 7 && C.JSString_methods.startsWith$1(_this._uri, _s7_)) { + _this._schemeCache = _s7_; + t1 = _s7_; + } else { + t1 = C.JSString_methods.substring$2(_this._uri, 0, t1); + _this._schemeCache = t1; + } + return t1; + }, + get$userInfo: function() { + var t1 = this._hostStart, + t2 = this._schemeEnd + 3; + return t1 > t2 ? C.JSString_methods.substring$2(this._uri, t2, t1 - 1) : ""; + }, + get$host: function(_) { + var t1 = this._hostStart; + return t1 > 0 ? C.JSString_methods.substring$2(this._uri, t1, this._portStart) : ""; + }, + get$port: function(_) { + var _this = this; + if (_this.get$hasPort()) + return P.int_parse(C.JSString_methods.substring$2(_this._uri, _this._portStart + 1, _this._pathStart), null, null); + if (_this.get$_isHttp()) + return 80; + if (_this.get$_isHttps()) + return 443; + return 0; + }, + get$path: function(_) { + return C.JSString_methods.substring$2(this._uri, this._pathStart, this._queryStart); + }, + get$query: function() { + var t1 = this._queryStart, + t2 = this._fragmentStart; + return t1 < t2 ? C.JSString_methods.substring$2(this._uri, t1 + 1, t2) : ""; + }, + get$fragment: function() { + var t1 = this._fragmentStart, + t2 = this._uri; + return t1 < t2.length ? C.JSString_methods.substring$1(t2, t1 + 1) : ""; + }, + get$pathSegments: function() { + var parts, i, + start = this._pathStart, + end = this._queryStart, + t1 = this._uri; + if (C.JSString_methods.startsWith$2(t1, "/", start)) + ++start; + if (start === end) + return C.List_empty; + parts = H.setRuntimeTypeInfo([], type$.JSArray_String); + for (i = start; i < end; ++i) + if (C.JSString_methods.codeUnitAt$1(t1, i) === 47) { + C.JSArray_methods.add$1(parts, C.JSString_methods.substring$2(t1, start, i)); + start = i + 1; + } + C.JSArray_methods.add$1(parts, C.JSString_methods.substring$2(t1, start, end)); + return P.List_List$unmodifiable(parts, type$.String); + }, + _isPort$1: function(port) { + var portDigitStart = this._portStart + 1; + return portDigitStart + port.length === this._pathStart && C.JSString_methods.startsWith$2(this._uri, port, portDigitStart); + }, + removeFragment$0: function() { + var _this = this, + t1 = _this._fragmentStart, + t2 = _this._uri; + if (t1 >= t2.length) + return _this; + return new P._SimpleUri(C.JSString_methods.substring$2(t2, 0, t1), _this._schemeEnd, _this._hostStart, _this._portStart, _this._pathStart, _this._queryStart, t1, _this._schemeCache); + }, + replace$2$path$pathSegments: function(_, path, pathSegments) { + var scheme, isFile, t1, userInfo, port, host, hasAuthority, t2, query, fragment, _this = this, _null = null; + type$.Iterable_String._check(pathSegments); + type$.Map_String_dynamic._check(null); + scheme = _this.get$scheme(); + isFile = scheme === "file"; + t1 = _this._hostStart; + userInfo = t1 > 0 ? C.JSString_methods.substring$2(_this._uri, _this._schemeEnd + 3, t1) : ""; + port = _this.get$hasPort() ? _this.get$port(_this) : _null; + t1 = _this._hostStart; + if (t1 > 0) + host = C.JSString_methods.substring$2(_this._uri, t1, _this._portStart); + else + host = userInfo.length !== 0 || port != null || isFile ? "" : _null; + hasAuthority = host != null; + t1 = path == null; + if (!t1 || pathSegments != null) + path = P._Uri__makePath(path, 0, t1 ? 0 : path.length, pathSegments, scheme, hasAuthority); + else { + path = C.JSString_methods.substring$2(_this._uri, _this._pathStart, _this._queryStart); + if (!isFile) + t1 = hasAuthority && path.length !== 0; + else + t1 = true; + if (t1 && !C.JSString_methods.startsWith$1(path, "/")) + path = "/" + path; + } + t1 = _this._queryStart; + t2 = _this._fragmentStart; + query = t1 < t2 ? C.JSString_methods.substring$2(_this._uri, t1 + 1, t2) : _null; + t1 = _this._fragmentStart; + t2 = _this._uri; + fragment = t1 < t2.length ? C.JSString_methods.substring$1(t2, t1 + 1) : _null; + return new P._Uri(scheme, userInfo, host, port, path, query, fragment); + }, + replace$1$path: function($receiver, path) { + return this.replace$2$path$pathSegments($receiver, path, null); + }, + replace$1$pathSegments: function($receiver, pathSegments) { + return this.replace$2$path$pathSegments($receiver, null, pathSegments); + }, + resolve$1: function(reference) { + return this.resolveUri$1(P.Uri_parse(reference)); + }, + resolveUri$1: function(reference) { + if (reference instanceof P._SimpleUri) + return this._simpleMerge$2(this, reference); + return this._toNonSimple$0().resolveUri$1(reference); + }, + _simpleMerge$2: function(base, ref) { + var t2, t3, isSimple, delta, refStart, baseStart, baseEnd, baseUri, baseStart0, backCount, refStart0, insert, + t1 = ref._schemeEnd; + if (t1 > 0) + return ref; + t2 = ref._hostStart; + if (t2 > 0) { + t3 = base._schemeEnd; + if (t3 <= 0) + return ref; + if (base.get$_isFile()) + isSimple = ref._pathStart !== ref._queryStart; + else if (base.get$_isHttp()) + isSimple = !ref._isPort$1("80"); + else + isSimple = !base.get$_isHttps() || !ref._isPort$1("443"); + if (isSimple) { + delta = t3 + 1; + return new P._SimpleUri(C.JSString_methods.substring$2(base._uri, 0, delta) + C.JSString_methods.substring$1(ref._uri, t1 + 1), t3, t2 + delta, ref._portStart + delta, ref._pathStart + delta, ref._queryStart + delta, ref._fragmentStart + delta, base._schemeCache); + } else + return this._toNonSimple$0().resolveUri$1(ref); + } + refStart = ref._pathStart; + t1 = ref._queryStart; + if (refStart === t1) { + t2 = ref._fragmentStart; + if (t1 < t2) { + t3 = base._queryStart; + delta = t3 - t1; + return new P._SimpleUri(C.JSString_methods.substring$2(base._uri, 0, t3) + C.JSString_methods.substring$1(ref._uri, t1), base._schemeEnd, base._hostStart, base._portStart, base._pathStart, t1 + delta, t2 + delta, base._schemeCache); + } + t1 = ref._uri; + if (t2 < t1.length) { + t3 = base._fragmentStart; + return new P._SimpleUri(C.JSString_methods.substring$2(base._uri, 0, t3) + C.JSString_methods.substring$1(t1, t2), base._schemeEnd, base._hostStart, base._portStart, base._pathStart, base._queryStart, t2 + (t3 - t2), base._schemeCache); + } + return base.removeFragment$0(); + } + t2 = ref._uri; + if (C.JSString_methods.startsWith$2(t2, "/", refStart)) { + t3 = base._pathStart; + delta = t3 - refStart; + return new P._SimpleUri(C.JSString_methods.substring$2(base._uri, 0, t3) + C.JSString_methods.substring$1(t2, refStart), base._schemeEnd, base._hostStart, base._portStart, t3, t1 + delta, ref._fragmentStart + delta, base._schemeCache); + } + baseStart = base._pathStart; + baseEnd = base._queryStart; + if (baseStart === baseEnd && base._hostStart > 0) { + for (; C.JSString_methods.startsWith$2(t2, "../", refStart);) + refStart += 3; + delta = baseStart - refStart + 1; + return new P._SimpleUri(C.JSString_methods.substring$2(base._uri, 0, baseStart) + "/" + C.JSString_methods.substring$1(t2, refStart), base._schemeEnd, base._hostStart, base._portStart, baseStart, t1 + delta, ref._fragmentStart + delta, base._schemeCache); + } + baseUri = base._uri; + for (baseStart0 = baseStart; C.JSString_methods.startsWith$2(baseUri, "../", baseStart0);) + baseStart0 += 3; + backCount = 0; + while (true) { + refStart0 = refStart + 3; + if (!(refStart0 <= t1 && C.JSString_methods.startsWith$2(t2, "../", refStart))) + break; + ++backCount; + refStart = refStart0; + } + for (insert = ""; baseEnd > baseStart0;) { + --baseEnd; + if (C.JSString_methods.codeUnitAt$1(baseUri, baseEnd) === 47) { + if (backCount === 0) { + insert = "/"; + break; + } + --backCount; + insert = "/"; + } + } + if (baseEnd === baseStart0 && base._schemeEnd <= 0 && !C.JSString_methods.startsWith$2(baseUri, "/", baseStart)) { + refStart -= backCount * 3; + insert = ""; + } + delta = baseEnd - refStart + insert.length; + return new P._SimpleUri(C.JSString_methods.substring$2(baseUri, 0, baseEnd) + insert + C.JSString_methods.substring$1(t2, refStart), base._schemeEnd, base._hostStart, base._portStart, baseStart, t1 + delta, ref._fragmentStart + delta, base._schemeCache); + }, + toFilePath$0: function() { + var t1, t2, windows, _this = this; + if (_this._schemeEnd >= 0 && !_this.get$_isFile()) + throw H.wrapException(P.UnsupportedError$("Cannot extract a file path from a " + H.S(_this.get$scheme()) + " URI")); + t1 = _this._queryStart; + t2 = _this._uri; + if (t1 < t2.length) { + if (t1 < _this._fragmentStart) + throw H.wrapException(P.UnsupportedError$("Cannot extract a file path from a URI with a query component")); + throw H.wrapException(P.UnsupportedError$("Cannot extract a file path from a URI with a fragment component")); + } + windows = $.$get$_Uri__isWindowsCached(); + if (H.boolConversionCheck(windows)) + t1 = P._Uri__toWindowsFilePath(_this); + else { + if (_this._hostStart < _this._portStart) + H.throwExpression(P.UnsupportedError$("Cannot extract a non-Windows file path from a file URI with an authority")); + t1 = C.JSString_methods.substring$2(t2, _this._pathStart, t1); + } + return t1; + }, + get$hashCode: function(_) { + var t1 = this._hashCodeCache; + return t1 == null ? this._hashCodeCache = C.JSString_methods.get$hashCode(this._uri) : t1; + }, + $eq: function(_, other) { + if (other == null) + return false; + if (this === other) + return true; + return type$.Uri._is(other) && this._uri === other.toString$0(0); + }, + _toNonSimple$0: function() { + var _this = this, _null = null, + t1 = _this.get$scheme(), + t2 = _this.get$userInfo(), + t3 = _this._hostStart > 0 ? _this.get$host(_this) : _null, + t4 = _this.get$hasPort() ? _this.get$port(_this) : _null, + t5 = _this._uri, + t6 = _this._queryStart, + t7 = C.JSString_methods.substring$2(t5, _this._pathStart, t6), + t8 = _this._fragmentStart; + t6 = t6 < t8 ? _this.get$query() : _null; + return new P._Uri(t1, t2, t3, t4, t7, t6, t8 < t5.length ? _this.get$fragment() : _null); + }, + toString$0: function(_) { + return this._uri; + }, + $isUri: 1 + }; + P._DataUri.prototype = {}; + W.ApplicationCacheErrorEvent.prototype = { + get$message: function(receiver) { + return receiver.message; + } + }; + W.Blob.prototype = {$isBlob: 1}; + W.DomError.prototype = { + get$message: function(receiver) { + return receiver.message; + } + }; + W.DomException.prototype = { + toString$0: function(receiver) { + return String(receiver); + }, + get$message: function(receiver) { + return receiver.message; + } + }; + W.ErrorEvent.prototype = { + get$message: function(receiver) { + return receiver.message; + } + }; + W.Event.prototype = {$isEvent: 1}; + W.EventTarget.prototype = { + addEventListener$3: function(receiver, type, listener, useCapture) { + type$.dynamic_Function_Event._check(listener); + if (listener != null) + this._addEventListener$3(receiver, type, listener, false); + }, + _addEventListener$3: function(receiver, type, listener, options) { + return receiver.addEventListener(type, H.convertDartClosureToJS(type$.dynamic_Function_Event._check(listener), 1), false); + }, + _removeEventListener$3: function(receiver, type, listener, options) { + return receiver.removeEventListener(type, H.convertDartClosureToJS(type$.dynamic_Function_Event._check(listener), 1), false); + }, + $isEventTarget: 1 + }; + W.File.prototype = {$isFile: 1}; + W.Location.prototype = { + get$origin: function(receiver) { + if ("origin" in receiver) + return receiver.origin; + return H.S(receiver.protocol) + "//" + H.S(receiver.host); + }, + toString$0: function(receiver) { + return String(receiver); + } + }; + W.MediaError.prototype = { + get$message: function(receiver) { + return receiver.message; + } + }; + W.MediaKeyMessageEvent.prototype = { + get$message: function(receiver) { + return receiver.message; + } + }; + W.MessageEvent.prototype = {$isMessageEvent: 1}; + W.MessagePort.prototype = { + addEventListener$3: function(receiver, type, listener, useCapture) { + type$.dynamic_Function_Event._check(listener); + if (type === "message") + receiver.start(); + this.super$EventTarget$addEventListener(receiver, type, listener, false); + }, + postMessage$1: function(receiver, message) { + type$.List_Object._check(null); + receiver.postMessage(new P._StructuredCloneDart2Js([], []).walk$1(message)); + return; + }, + $isMessagePort: 1 + }; + W.NavigatorUserMediaError.prototype = { + get$message: function(receiver) { + return receiver.message; + } + }; + W.OverconstrainedError.prototype = { + get$message: function(receiver) { + return receiver.message; + } + }; + W.PositionError.prototype = { + get$message: function(receiver) { + return receiver.message; + } + }; + W.PresentationConnectionCloseEvent.prototype = { + get$message: function(receiver) { + return receiver.message; + } + }; + W.SpeechRecognitionError.prototype = { + get$message: function(receiver) { + return receiver.message; + } + }; + W.EventStreamProvider.prototype = {}; + W._EventStream.prototype = { + get$isBroadcast: function() { + return true; + }, + listen$4$cancelOnError$onDone$onError: function(onData, cancelOnError, onDone, onError) { + var t1 = this.$ti; + t1._eval$1("~(1)")._check(onData); + type$.void_Function._check(onDone); + H._checkBoolNullable(cancelOnError); + return W._EventStreamSubscription$(this._html$_target, this._eventType, onData, false, t1._precomputed1); + }, + listen$3$onDone$onError: function(onData, onDone, onError) { + return this.listen$4$cancelOnError$onDone$onError(onData, null, onDone, onError); + }, + listen$1: function(onData) { + return this.listen$4$cancelOnError$onDone$onError(onData, null, null, null); + } + }; + W._EventStreamSubscription.prototype = { + cancel$0: function() { + var _this = this; + if (_this._html$_target == null) + return null; + _this._unlisten$0(); + _this._html$_target = null; + _this.set$_html$_onData(null); + return null; + }, + pause$1: function(resumeSignal) { + if (this._html$_target == null) + return; + ++this._pauseCount; + this._unlisten$0(); + }, + pause$0: function() { + return this.pause$1(null); + }, + resume$0: function() { + var _this = this; + if (_this._html$_target == null || _this._pauseCount <= 0) + return; + --_this._pauseCount; + _this._tryResume$0(); + }, + _tryResume$0: function() { + var _this = this, + t1 = _this._html$_onData; + if (t1 != null && _this._pauseCount <= 0) + J.addEventListener$3$x(_this._html$_target, _this._eventType, t1, false); + }, + _unlisten$0: function() { + var t3, + t1 = this._html$_onData, + t2 = t1 != null; + if (t2) { + t3 = this._html$_target; + t3.toString; + type$.dynamic_Function_Event._check(t1); + if (t2) + J._removeEventListener$3$x(t3, this._eventType, t1, false); + } + }, + set$_html$_onData: function(_onData) { + this._html$_onData = type$.dynamic_Function_Event._check(_onData); + } + }; + W._EventStreamSubscription_closure.prototype = { + call$1: function(e) { + return this.onData.call$1(type$.Event._check(e)); + }, + $signature: 61 + }; + P._StructuredClone.prototype = { + findSlot$1: function(value) { + var i, + t1 = this.values, + $length = t1.length; + for (i = 0; i < $length; ++i) + if (t1[i] === value) + return i; + C.JSArray_methods.add$1(t1, value); + C.JSArray_methods.add$1(this.copies, null); + return $length; + }, + walk$1: function(e) { + var slot, t2, copy, _this = this, t1 = {}; + if (e == null) + return e; + if (H._isBool(e)) + return e; + if (typeof e == "number") + return e; + if (typeof e == "string") + return e; + if (e instanceof P.DateTime) + return new Date(e._value); + if (type$.RegExp._is(e)) + throw H.wrapException(P.UnimplementedError$("structured clone of RegExp")); + if (type$.File._is(e)) + return e; + if (type$.Blob._is(e)) + return e; + if (type$.NativeByteBuffer._is(e) || type$.NativeTypedData._is(e) || type$.MessagePort._is(e)) + return e; + if (type$.Map_dynamic_dynamic._is(e)) { + slot = _this.findSlot$1(e); + t2 = _this.copies; + if (slot >= t2.length) + return H.ioore(t2, slot); + copy = t1.copy = t2[slot]; + if (copy != null) + return copy; + copy = {}; + t1.copy = copy; + C.JSArray_methods.$indexSet(t2, slot, copy); + e.forEach$1(0, new P._StructuredClone_walk_closure(t1, _this)); + return t1.copy; + } + if (type$.List_dynamic._is(e)) { + slot = _this.findSlot$1(e); + t1 = _this.copies; + if (slot >= t1.length) + return H.ioore(t1, slot); + copy = t1[slot]; + if (copy != null) + return copy; + return _this.copyList$2(e, slot); + } + if (type$.JSObject._is(e)) { + slot = _this.findSlot$1(e); + t2 = _this.copies; + if (slot >= t2.length) + return H.ioore(t2, slot); + copy = t1.copy = t2[slot]; + if (copy != null) + return copy; + copy = {}; + t1.copy = copy; + C.JSArray_methods.$indexSet(t2, slot, copy); + _this.forEachObjectKey$2(e, new P._StructuredClone_walk_closure0(t1, _this)); + return t1.copy; + } + throw H.wrapException(P.UnimplementedError$("structured clone of other type")); + }, + copyList$2: function(e, slot) { + var i, + t1 = J.getInterceptor$asx(e), + $length = t1.get$length(e), + copy = new Array($length); + C.JSArray_methods.$indexSet(this.copies, slot, copy); + for (i = 0; i < $length; ++i) + C.JSArray_methods.$indexSet(copy, i, this.walk$1(t1.$index(e, i))); + return copy; + } + }; + P._StructuredClone_walk_closure.prototype = { + call$2: function(key, value) { + this._box_0.copy[key] = this.$this.walk$1(value); + }, + $signature: 6 + }; + P._StructuredClone_walk_closure0.prototype = { + call$2: function(key, value) { + this._box_0.copy[key] = this.$this.walk$1(value); + }, + $signature: 6 + }; + P._AcceptStructuredClone.prototype = { + findSlot$1: function(value) { + var i, + t1 = this.values, + $length = t1.length; + for (i = 0; i < $length; ++i) + if (t1[i] === value) + return i; + C.JSArray_methods.add$1(t1, value); + C.JSArray_methods.add$1(this.copies, null); + return $length; + }, + walk$1: function(e) { + var millisSinceEpoch, t1, proto, slot, copy, t2, l, $length, i, _this = this, _box_0 = {}; + if (e == null) + return e; + if (H._isBool(e)) + return e; + if (typeof e == "number") + return e; + if (typeof e == "string") + return e; + if (e instanceof Date) { + millisSinceEpoch = e.getTime(); + if (Math.abs(millisSinceEpoch) <= 864e13) + t1 = false; + else + t1 = true; + if (t1) + H.throwExpression(P.ArgumentError$("DateTime is outside valid range: " + millisSinceEpoch)); + return new P.DateTime(millisSinceEpoch, true); + } + if (e instanceof RegExp) + throw H.wrapException(P.UnimplementedError$("structured clone of RegExp")); + if (typeof Promise != "undefined" && e instanceof Promise) + return P.promiseToFuture(e, type$.dynamic); + proto = Object.getPrototypeOf(e); + if (proto === Object.prototype || proto === null) { + slot = _this.findSlot$1(e); + t1 = _this.copies; + if (slot >= t1.length) + return H.ioore(t1, slot); + copy = _box_0.copy = t1[slot]; + if (copy != null) + return copy; + t2 = type$.dynamic; + copy = P.LinkedHashMap_LinkedHashMap$_empty(t2, t2); + _box_0.copy = copy; + C.JSArray_methods.$indexSet(t1, slot, copy); + _this.forEachJsField$2(e, new P._AcceptStructuredClone_walk_closure(_box_0, _this)); + return _box_0.copy; + } + if (e instanceof Array) { + l = e; + slot = _this.findSlot$1(l); + t1 = _this.copies; + if (slot >= t1.length) + return H.ioore(t1, slot); + copy = t1[slot]; + if (copy != null) + return copy; + t2 = J.getInterceptor$asx(l); + $length = t2.get$length(l); + copy = _this.mustCopy ? new Array($length) : l; + C.JSArray_methods.$indexSet(t1, slot, copy); + for (t1 = J.getInterceptor$ax(copy), i = 0; i < $length; ++i) + t1.$indexSet(copy, i, _this.walk$1(t2.$index(l, i))); + return copy; + } + return e; + }, + convertNativeToDart_AcceptStructuredClone$2$mustCopy: function(object, mustCopy) { + this.mustCopy = true; + return this.walk$1(object); + } + }; + P._AcceptStructuredClone_walk_closure.prototype = { + call$2: function(key, value) { + var t1 = this._box_0.copy, + t2 = this.$this.walk$1(value); + J.$indexSet$ax(t1, key, t2); + return t2; + }, + $signature: 60 + }; + P._StructuredCloneDart2Js.prototype = { + forEachObjectKey$2: function(object, action) { + var t1, t2, _i, key; + type$.dynamic_Function_dynamic_dynamic._check(action); + for (t1 = Object.keys(object), t2 = t1.length, _i = 0; _i < t2; ++_i) { + key = t1[_i]; + action.call$2(key, object[key]); + } + } + }; + P._AcceptStructuredCloneDart2Js.prototype = { + forEachJsField$2: function(object, action) { + var t1, t2, _i, key; + type$.dynamic_Function_dynamic_dynamic._check(action); + for (t1 = Object.keys(object), t2 = t1.length, _i = 0; _i < t1.length; t1.length === t2 || (0, H.throwConcurrentModificationError)(t1), ++_i) { + key = t1[_i]; + action.call$2(key, object[key]); + } + } + }; + P._convertDataTree__convert.prototype = { + call$1: function(o) { + var convertedMap, key, convertedList, + t1 = this._convertedObjects; + if (t1.containsKey$1(o)) + return t1.$index(0, o); + if (type$.Map_dynamic_dynamic._is(o)) { + convertedMap = {}; + t1.$indexSet(0, o, convertedMap); + for (t1 = o.get$keys(), t1 = t1.get$iterator(t1); t1.moveNext$0();) { + key = t1.get$current(); + convertedMap[key] = this.call$1(o.$index(0, key)); + } + return convertedMap; + } else if (type$.Iterable_dynamic._is(o)) { + convertedList = []; + t1.$indexSet(0, o, convertedList); + C.JSArray_methods.addAll$1(convertedList, J.map$1$1$ax(o, this, type$.dynamic)); + return convertedList; + } else + return o; + }, + $signature: 18 + }; + P.promiseToFuture_closure.prototype = { + call$1: function(r) { + return this.completer.complete$1(this.T._eval$1("0/")._check(r)); + }, + $signature: 15 + }; + P.promiseToFuture_closure0.prototype = { + call$1: function(e) { + return this.completer.completeError$1(e); + }, + $signature: 15 + }; + P.ByteBuffer.prototype = {}; + P.ByteData.prototype = {}; + P.Int8List.prototype = {$isEfficientLengthIterable: 1, $isIterable: 1, $isList: 1}; + P.Uint8List.prototype = {$isEfficientLengthIterable: 1, $isIterable: 1, $isList: 1}; + P.Uint8ClampedList.prototype = {$isEfficientLengthIterable: 1, $isIterable: 1, $isList: 1}; + P.Int16List.prototype = {$isEfficientLengthIterable: 1, $isIterable: 1, $isList: 1}; + P.Uint16List.prototype = {$isEfficientLengthIterable: 1, $isIterable: 1, $isList: 1}; + P.Int32List.prototype = {$isEfficientLengthIterable: 1, $isIterable: 1, $isList: 1}; + P.Uint32List.prototype = {$isEfficientLengthIterable: 1, $isIterable: 1, $isList: 1}; + P.Float32List.prototype = {$isEfficientLengthIterable: 1, $isIterable: 1, $isList: 1}; + P.Float64List.prototype = {$isEfficientLengthIterable: 1, $isIterable: 1, $isList: 1}; + P.SqlError.prototype = { + get$message: function(receiver) { + return receiver.message; + } + }; + S.AsyncMemoizer.prototype = { + runOnce$1: function(computation) { + var t2, t3, + t1 = this.$ti; + t1._eval$1("1/()")._check(computation); + t2 = this._async_memoizer$_completer; + t3 = t2.future; + if (t3._state === 0) + t2.complete$1(P.Future_Future$sync(computation, t1._precomputed1)); + return t3; + } + }; + O.DelegatingSink.prototype = {$isSink: 1}; + Y.DelegatingStreamSubscription.prototype = { + onData$1: function(handleData) { + this._stream_subscription$_source.onData$1(this.$ti._eval$1("~(1)")._check(handleData)); + }, + onError$1: function(_, handleError) { + this._stream_subscription$_source.onError$1(0, handleError); + }, + onDone$1: function(handleDone) { + this._stream_subscription$_source.onDone$1(type$.void_Function._check(handleDone)); + }, + pause$1: function(resumeFuture) { + this._stream_subscription$_source.pause$1(resumeFuture); + }, + pause$0: function() { + return this.pause$1(null); + }, + resume$0: function() { + this._stream_subscription$_source.resume$0(); + }, + cancel$0: function() { + return this._stream_subscription$_source.cancel$0(); + }, + $isStreamSubscription: 1 + }; + F.FutureGroup.prototype = { + add$1: function(_, task) { + var t1, index, _this = this; + _this.$ti._eval$1("Future<1>")._check(task); + if (_this._future_group$_closed) + throw H.wrapException(P.StateError$("The FutureGroup is closed.")); + t1 = _this._values; + index = t1.length; + C.JSArray_methods.add$1(t1, null); + ++_this._future_group$_pending; + task.then$1$1(new F.FutureGroup_add_closure(_this, index), type$.Null).catchError$1(new F.FutureGroup_add_closure0(_this)); + }, + close$0: function(_) { + var t1, _this = this; + _this._future_group$_closed = true; + if (_this._future_group$_pending !== 0) + return; + t1 = _this._future_group$_completer; + if (t1.future._state !== 0) + return; + t1.complete$1(_this._values); + }, + $isSink: 1 + }; + F.FutureGroup_add_closure.prototype = { + call$1: function(value) { + var t2, t3, + t1 = this.$this; + t1.$ti._precomputed1._check(value); + t2 = t1._future_group$_completer; + if (t2.future._state !== 0) + return null; + --t1._future_group$_pending; + t3 = t1._values; + C.JSArray_methods.$indexSet(t3, this.index, value); + if (t1._future_group$_pending !== 0) + return null; + if (!t1._future_group$_closed) + return null; + t2.complete$1(t3); + }, + $signature: function() { + return this.$this.$ti._eval$1("Null(1)"); + } + }; + F.FutureGroup_add_closure0.prototype = { + call$2: function(error, stackTrace) { + var t1 = this.$this._future_group$_completer; + if (t1.future._state !== 0) + return null; + t1.completeError$2(error, type$.StackTrace._check(stackTrace)); + }, + $signature: 6 + }; + S.NullStreamSink.prototype = { + add$1: function(_, data) { + this.$ti._precomputed1._check(data); + this._checkEventAllowed$0(); + }, + addStream$1: function(stream) { + var future, _this = this; + _this.$ti._eval$1("Stream<1>")._check(stream); + _this._checkEventAllowed$0(); + _this._addingStream = true; + future = stream.listen$1(null).cancel$0(); + if (future == null) { + future = new P._Future($.Zone__current, type$._Future_dynamic); + future._asyncComplete$1(null); + } + return future.whenComplete$1(new S.NullStreamSink_addStream_closure(_this)); + }, + _checkEventAllowed$0: function() { + if (this._null_stream_sink$_closed) + throw H.wrapException(P.StateError$("Cannot add to a closed sink.")); + if (this._addingStream) + throw H.wrapException(P.StateError$("Cannot add to a sink while adding a stream.")); + }, + close$0: function(_) { + this._null_stream_sink$_closed = true; + return this.done; + }, + $isEventSink: 1, + $isStreamConsumer: 1, + $isStreamSink: 1, + $isSink: 1, + get$done: function() { + return this.done; + } + }; + S.NullStreamSink_addStream_closure.prototype = { + call$0: function() { + this.$this._addingStream = false; + }, + $signature: 0 + }; + V.ErrorResult.prototype = { + complete$1: function(completer) { + completer.completeError$2(this.error, this.stackTrace); + }, + addTo$1: function(sink) { + sink.addError$2(this.error, this.stackTrace); + }, + get$hashCode: function(_) { + return (J.get$hashCode$(this.error) ^ J.get$hashCode$(this.stackTrace) ^ 492929599) >>> 0; + }, + $eq: function(_, other) { + if (other == null) + return false; + return other instanceof V.ErrorResult && J.$eq$(this.error, other.error) && this.stackTrace == other.stackTrace; + }, + $isResult: 1 + }; + E.Result.prototype = {}; + F.ValueResult.prototype = { + complete$1: function(completer) { + this.$ti._eval$1("Completer<1>")._check(completer).complete$1(this.value); + }, + addTo$1: function(sink) { + this.$ti._eval$1("EventSink<1>")._check(sink).add$1(0, this.value); + }, + get$hashCode: function(_) { + return (J.get$hashCode$(this.value) ^ 842997089) >>> 0; + }, + $eq: function(_, other) { + if (other == null) + return false; + return other instanceof F.ValueResult && J.$eq$(this.value, other.value); + }, + $isResult: 1 + }; + Y.StreamCompleter.prototype = { + setSourceStream$1: function(sourceStream) { + var t1; + this.$ti._eval$1("Stream<1>")._check(sourceStream); + t1 = this._stream; + if (t1._sourceStream != null) + throw H.wrapException(P.StateError$("Source stream already set")); + t1.set$_sourceStream(t1.$ti._eval$1("Stream<1>")._check(sourceStream)); + if (t1._stream_completer$_controller != null) + t1._linkStreamToController$0(); + } + }; + Y._CompleterStream.prototype = { + listen$4$cancelOnError$onDone$onError: function(onData, cancelOnError, onDone, onError) { + var t1, _this = this; + _this.$ti._eval$1("@(1)")._check(onData); + type$.void_Function._check(onDone); + H._checkBoolNullable(cancelOnError); + if (_this._stream_completer$_controller == null) { + t1 = _this._sourceStream; + if (t1 != null && !t1.get$isBroadcast()) + return _this._sourceStream.listen$4$cancelOnError$onDone$onError(onData, cancelOnError, onDone, onError); + _this._createController$0(); + if (_this._sourceStream != null) + _this._linkStreamToController$0(); + } + t1 = _this._stream_completer$_controller; + t1.toString; + return new P._ControllerStream(t1, H._instanceType(t1)._eval$1("_ControllerStream<1>")).listen$4$cancelOnError$onDone$onError(onData, cancelOnError, onDone, onError); + }, + listen$3$onDone$onError: function(onData, onDone, onError) { + return this.listen$4$cancelOnError$onDone$onError(onData, null, onDone, onError); + }, + listen$1: function(onData) { + return this.listen$4$cancelOnError$onDone$onError(onData, null, null, null); + }, + _linkStreamToController$0: function() { + var t1, t2, _this = this; + H.assertHelper(_this._stream_completer$_controller != null); + H.assertHelper(_this._sourceStream != null); + t1 = _this._stream_completer$_controller.addStream$2$cancelOnError(_this._sourceStream, false); + t2 = _this._stream_completer$_controller; + t1.whenComplete$1(t2.get$close(t2)); + }, + _createController$0: function() { + H.assertHelper(this._stream_completer$_controller == null); + this.set$_stream_completer$_controller(P.StreamController_StreamController(null, null, true, this.$ti._precomputed1)); + }, + set$_stream_completer$_controller: function(_controller) { + this._stream_completer$_controller = this.$ti._eval$1("StreamController<1>")._check(_controller); + }, + set$_sourceStream: function(_sourceStream) { + this._sourceStream = this.$ti._eval$1("Stream<1>")._check(_sourceStream); + } + }; + L.StreamGroup.prototype = { + add$1: function(_, stream) { + var t1, _this = this; + _this.$ti._eval$1("Stream<1>")._check(stream); + if (_this._stream_group$_closed) + throw H.wrapException(P.StateError$("Can't add a Stream to a closed StreamGroup.")); + t1 = _this._stream_group$_state; + if (t1 === C._StreamGroupState_dormant) + _this._stream_group$_subscriptions.putIfAbsent$2(stream, new L.StreamGroup_add_closure()); + else if (t1 === C._StreamGroupState_canceled) + return stream.listen$1(null).cancel$0(); + else + _this._stream_group$_subscriptions.putIfAbsent$2(stream, new L.StreamGroup_add_closure0(_this, stream)); + return null; + }, + _onListen$0: function() { + this._stream_group$_state = C._StreamGroupState_listening; + this._stream_group$_subscriptions.forEach$1(0, new L.StreamGroup__onListen_closure(this)); + }, + _onCancelBroadcast$0: function() { + this._stream_group$_state = C._StreamGroupState_dormant; + this._stream_group$_subscriptions.forEach$1(0, new L.StreamGroup__onCancelBroadcast_closure(this)); + }, + _listenToStream$1: function(stream) { + var t1, subscription, _this = this; + _this.$ti._eval$1("Stream<1>")._check(stream); + t1 = _this._stream_group$_controller; + subscription = stream.listen$3$onDone$onError(t1.get$add(t1), new L.StreamGroup__listenToStream_closure(_this, stream), t1.get$addError()); + if (_this._stream_group$_state === C._StreamGroupState_paused) + subscription.pause$0(); + return subscription; + }, + close$0: function(_) { + var t1, _this = this; + if (_this._stream_group$_closed) + return _this._stream_group$_controller._ensureDoneFuture$0(); + _this._stream_group$_closed = true; + t1 = _this._stream_group$_subscriptions; + if (t1.get$isEmpty(t1)) + _this._stream_group$_controller.close$0(0); + return _this._stream_group$_controller._ensureDoneFuture$0(); + }, + set$_stream_group$_controller: function(_controller) { + this._stream_group$_controller = this.$ti._eval$1("StreamController<1>")._check(_controller); + }, + $isSink: 1 + }; + L.StreamGroup_add_closure.prototype = { + call$0: function() { + return null; + }, + $signature: 0 + }; + L.StreamGroup_add_closure0.prototype = { + call$0: function() { + return this.$this._listenToStream$1(this.stream); + }, + $signature: function() { + return this.$this.$ti._eval$1("StreamSubscription<1>()"); + } + }; + L.StreamGroup__onListen_closure.prototype = { + call$2: function(stream, subscription) { + var t1 = this.$this, + t2 = t1.$ti; + t2._eval$1("Stream<1>")._check(stream); + if (t2._eval$1("StreamSubscription<1>")._check(subscription) != null) + return; + t1._stream_group$_subscriptions.$indexSet(0, stream, t1._listenToStream$1(stream)); + }, + $signature: function() { + return this.$this.$ti._eval$1("Null(Stream<1>,StreamSubscription<1>)"); + } + }; + L.StreamGroup__onCancelBroadcast_closure.prototype = { + call$2: function(stream, subscription) { + var t1 = this.$this, + t2 = t1.$ti; + t2._eval$1("Stream<1>")._check(stream); + t2._eval$1("StreamSubscription<1>")._check(subscription); + if (!stream.get$isBroadcast()) + return; + subscription.cancel$0(); + t1._stream_group$_subscriptions.$indexSet(0, stream, null); + }, + $signature: function() { + return this.$this.$ti._eval$1("Null(Stream<1>,StreamSubscription<1>)"); + } + }; + L.StreamGroup__listenToStream_closure.prototype = { + call$0: function() { + var t1 = this.$this, + t2 = t1._stream_group$_subscriptions, + subscription = t2.remove$1(0, t1.$ti._eval$1("Stream<1>")._check(this.stream)), + future = subscription == null ? null : subscription.cancel$0(); + if (t1._stream_group$_closed && t2.get$isEmpty(t2)) + t1._stream_group$_controller.close$0(0); + return future; + }, + $signature: 14 + }; + L._StreamGroupState.prototype = { + toString$0: function(_) { + return this.name; + } + }; + G.StreamQueue.prototype = { + get$next: function() { + var t1, t2, _this = this; + if (!_this._isClosed) { + t1 = _this.$ti; + t2 = new P._Future($.Zone__current, t1._eval$1("_Future<1>")); + _this._addRequest$1(new G._NextRequest(new P._AsyncCompleter(t2, t1._eval$1("_AsyncCompleter<1>")), t1._eval$1("_NextRequest<1>"))); + return t2; + } + throw H.wrapException(_this._failClosed$0()); + }, + _updateRequests$0: function() { + var t1, t2, t3, t4, _this = this; + for (t1 = _this._requestQueue, t2 = _this._eventQueue; !t1.get$isEmpty(t1);) { + t3 = t1._head; + if (t3 === t1._tail) + H.throwExpression(H.IterableElementError_noElement()); + t4 = t1._table; + if (t3 >= t4.length) + return H.ioore(t4, t3); + if (t4[t3].update$2(t2, _this._isDone)) + t1.removeFirst$0(); + else + return; + } + if (!_this._isDone) + _this._stream_queue$_subscription.pause$0(); + }, + _extractStream$0: function() { + var t1, wasPaused, _this = this, _null = null; + H.assertHelper(_this._isClosed); + if (_this._isDone) + return new P._EmptyStream(_this.$ti._eval$1("_EmptyStream<1>")); + _this._isDone = true; + t1 = _this._stream_queue$_subscription; + if (t1 == null) + return _this._stream_queue$_source; + _this.set$_stream_queue$_subscription(_null); + wasPaused = t1.get$isPaused(); + t1.pause$0(); + t1.onData$1(_null); + t1.onError$1(0, _null); + t1.onDone$1(_null); + if (wasPaused) + t1.resume$0(); + return new T.SubscriptionStream(t1, _this.$ti._eval$1("SubscriptionStream<1>")); + }, + _ensureListening$0: function() { + var t1, _this = this; + if (_this._isDone) + return; + t1 = _this._stream_queue$_subscription; + if (t1 == null) + _this.set$_stream_queue$_subscription(_this._stream_queue$_source.listen$3$onDone$onError(new G.StreamQueue__ensureListening_closure(_this), new G.StreamQueue__ensureListening_closure0(_this), new G.StreamQueue__ensureListening_closure1(_this))); + else + t1.resume$0(); + }, + _addResult$1: function(result) { + var t1, _this = this; + _this.$ti._eval$1("Result<1>")._check(result); + ++_this._eventsReceived; + t1 = _this._eventQueue; + t1._queue_list$_add$1(t1.$ti._precomputed1._check(result)); + _this._updateRequests$0(); + }, + _failClosed$0: function() { + return new P.StateError("Already cancelled"); + }, + _addRequest$1: function(request) { + var t1, _this = this; + _this.$ti._eval$1("_EventRequest<1>")._check(request); + t1 = _this._requestQueue; + if (t1._head === t1._tail) { + if (request.update$2(_this._eventQueue, _this._isDone)) + return; + _this._ensureListening$0(); + } + t1._collection$_add$1(t1.$ti._precomputed1._check(request)); + }, + set$_stream_queue$_subscription: function(_subscription) { + this._stream_queue$_subscription = this.$ti._eval$1("StreamSubscription<1>")._check(_subscription); + } + }; + G.StreamQueue__ensureListening_closure.prototype = { + call$1: function(data) { + var t1 = this.$this, + t2 = t1.$ti; + t1._addResult$1(new F.ValueResult(t2._precomputed1._check(data), t2._eval$1("ValueResult<1>"))); + }, + $signature: function() { + return this.$this.$ti._eval$1("Null(1)"); + } + }; + G.StreamQueue__ensureListening_closure1.prototype = { + call$2: function(error, stackTrace) { + this.$this._addResult$1(new V.ErrorResult(error, type$.StackTrace._check(stackTrace))); + }, + $signature: 5 + }; + G.StreamQueue__ensureListening_closure0.prototype = { + call$0: function() { + var t1 = this.$this; + t1.set$_stream_queue$_subscription(null); + t1._isDone = true; + t1._updateRequests$0(); + }, + $signature: 0 + }; + G._EventRequest.prototype = {}; + G._NextRequest.prototype = { + update$2: function(events, isDone) { + this.$ti._eval$1("QueueList<Result<1>>")._check(events); + if (events.get$length(events) !== 0) { + events.removeFirst$0().complete$1(this._completer); + return true; + } + if (isDone) { + this._completer.completeError$2(new P.StateError("No elements"), P.StackTrace_current()); + return true; + } + return false; + }, + $is_EventRequest: 1 + }; + G._RestRequest.prototype = { + update$2: function(events, isDone) { + var t2, controller, _this = this, + t1 = _this.$ti; + t1._eval$1("QueueList<Result<1>>")._check(events); + if (events.get$length(events) === 0) { + t1 = _this._streamQueue; + t2 = _this._completer; + if (t1._isDone) { + t1 = t2._stream; + t2 = t1._sourceStream == null; + if (!t2) + H.throwExpression(P.StateError$("Source stream already set")); + H.assertHelper(t2); + if (t1._stream_completer$_controller == null) + t1._createController$0(); + t2 = t1._stream_completer$_controller; + t2.toString; + t1.set$_sourceStream(new P._ControllerStream(t2, H._instanceType(t2)._eval$1("_ControllerStream<1>"))); + t1._stream_completer$_controller.close$0(0); + } else + t2.setSourceStream$1(t1._extractStream$0()); + } else { + controller = P.StreamController_StreamController(null, null, false, t1._precomputed1); + for (t1 = new H.ListIterator(events, events.get$length(events), events.$ti._eval$1("ListIterator<ListMixin.E>")); t1.moveNext$0();) + t1.__internal$_current.addTo$1(controller); + controller.addStream$2$cancelOnError(_this._streamQueue._extractStream$0(), false).whenComplete$1(controller.get$close(controller)); + _this._completer.setSourceStream$1(new P._ControllerStream(controller, H._instanceType(controller)._eval$1("_ControllerStream<1>"))); + } + return true; + }, + $is_EventRequest: 1 + }; + T.StreamSinkCompleter.prototype = {}; + T._CompleterSink.prototype = { + get$_canSendDirectly: function() { + return this._stream_sink_completer$_controller == null && this._destinationSink != null; + }, + get$done: function() { + var t1 = this._stream_sink_completer$_doneCompleter; + if (t1 != null) + return t1.future; + t1 = this._destinationSink; + if (t1 == null) { + t1 = new P._Future($.Zone__current, type$._Future_dynamic); + this._stream_sink_completer$_doneCompleter = new P._SyncCompleter(t1, type$._SyncCompleter_dynamic); + return t1; + } + return t1.get$done(); + }, + addStream$1: function(stream) { + var _this = this; + _this.$ti._eval$1("Stream<1>")._check(stream); + if (_this.get$_canSendDirectly()) + return _this._destinationSink.addStream$1(stream); + _this._ensureController$0(); + return _this._stream_sink_completer$_controller.addStream$2$cancelOnError(stream, false); + }, + close$0: function(_) { + var _this = this; + if (_this.get$_canSendDirectly()) + _this._destinationSink.close$0(0); + else { + _this._ensureController$0(); + _this._stream_sink_completer$_controller.close$0(0); + } + return _this.get$done(); + }, + _ensureController$0: function() { + if (this._stream_sink_completer$_controller == null) + this.set$_stream_sink_completer$_controller(P.StreamController_StreamController(null, null, true, this.$ti._precomputed1)); + }, + _setDestinationSink$1: function(sink) { + var t1, _this = this; + _this.$ti._eval$1("StreamSink<1>")._check(sink); + H.assertHelper(_this._destinationSink == null); + _this.set$_destinationSink(sink); + t1 = _this._stream_sink_completer$_controller; + if (t1 != null) + sink.addStream$1(new P._ControllerStream(t1, H._instanceType(t1)._eval$1("_ControllerStream<1>"))).whenComplete$1(sink.get$close(sink)).catchError$1(new T._CompleterSink__setDestinationSink_closure()); + t1 = _this._stream_sink_completer$_doneCompleter; + if (t1 != null) + t1.complete$1(sink.get$done()); + }, + set$_stream_sink_completer$_controller: function(_controller) { + this._stream_sink_completer$_controller = this.$ti._eval$1("StreamController<1>")._check(_controller); + }, + set$_destinationSink: function(_destinationSink) { + this._destinationSink = this.$ti._eval$1("StreamSink<1>")._check(_destinationSink); + }, + $isEventSink: 1, + $isStreamConsumer: 1, + $isStreamSink: 1, + $isSink: 1 + }; + T._CompleterSink__setDestinationSink_closure.prototype = { + call$1: function(_) { + }, + $signature: 3 + }; + T.SubscriptionStream.prototype = { + listen$4$cancelOnError$onDone$onError: function(onData, cancelOnError, onDone, onError) { + var result, result0, + t1 = this.$ti; + t1._eval$1("~(1)")._check(onData); + type$.void_Function._check(onDone); + H._checkBoolNullable(cancelOnError); + result = this._subscription_stream$_source; + if (result == null) + throw H.wrapException(P.StateError$("Stream has already been listened to.")); + this.set$_subscription_stream$_source(null); + result0 = true === cancelOnError ? new T._CancelOnErrorSubscriptionWrapper(result, t1._eval$1("_CancelOnErrorSubscriptionWrapper<1>")) : result; + result0.onData$1(onData); + result0.onError$1(0, onError); + result0.onDone$1(onDone); + result.resume$0(); + return result0; + }, + listen$3$onDone$onError: function(onData, onDone, onError) { + return this.listen$4$cancelOnError$onDone$onError(onData, null, onDone, onError); + }, + listen$1: function(onData) { + return this.listen$4$cancelOnError$onDone$onError(onData, null, null, null); + }, + set$_subscription_stream$_source: function(_source) { + this._subscription_stream$_source = this.$ti._eval$1("StreamSubscription<1>")._check(_source); + } + }; + T._CancelOnErrorSubscriptionWrapper.prototype = { + onError$1: function(_, handleError) { + this.super$DelegatingStreamSubscription$onError(0, new T._CancelOnErrorSubscriptionWrapper_onError_closure(this, handleError)); + } + }; + T._CancelOnErrorSubscriptionWrapper_onError_closure.prototype = { + call$2: function(error, stackTrace) { + var cancelFuture, t1; + type$.StackTrace._check(stackTrace); + cancelFuture = this.$this.super$DelegatingStreamSubscription$cancel(); + if (cancelFuture != null) + cancelFuture.whenComplete$1(new T._CancelOnErrorSubscriptionWrapper_onError__closure(this.handleError, error, stackTrace)); + else { + t1 = this.handleError; + if (type$.dynamic_Function_dynamic_dynamic._is(t1)) + t1.call$2(error, stackTrace); + else + t1.call$1(error); + } + }, + $signature: 5 + }; + T._CancelOnErrorSubscriptionWrapper_onError__closure.prototype = { + call$0: function() { + var t1 = this.handleError, + t2 = this.error; + if (type$.dynamic_Function_dynamic_dynamic._is(t1)) + t1.call$2(t2, this.stackTrace); + else + t1.call$1(t2); + }, + $signature: 0 + }; + X.BooleanSelector.prototype = {}; + X.All.prototype = { + evaluate$1: function(semantics) { + return true; + }, + intersection$1: function(other) { + return other; + }, + validate$1: function(isDefined) { + type$.bool_Function_String._check(isDefined); + }, + toString$0: function(_) { + return "<all>"; + }, + $isBooleanSelector: 1 + }; + U.VariableNode.prototype = { + accept$1: function(visitor) { + return visitor.visitVariable$1(this); + }, + toString$0: function(_) { + return this.name; + }, + $eq: function(_, other) { + if (other == null) + return false; + return other instanceof U.VariableNode && this.name == other.name; + }, + get$hashCode: function(_) { + return J.get$hashCode$(this.name); + }, + $isNode: 1, + get$span: function() { + return this.span; + } + }; + U.NotNode.prototype = { + accept$1: function(visitor) { + return visitor.visitNot$1(this); + }, + toString$0: function(_) { + var t1 = this.child; + return t1 instanceof U.VariableNode || t1 instanceof U.NotNode ? "!" + t1.toString$0(0) : "!(" + t1.toString$0(0) + ")"; + }, + $eq: function(_, other) { + if (other == null) + return false; + return other instanceof U.NotNode && this.child.$eq(0, other.child); + }, + get$hashCode: function(_) { + var t1 = this.child; + return ~t1.get$hashCode(t1) >>> 0; + }, + $isNode: 1, + get$span: function() { + return this.span; + } + }; + U.OrNode.prototype = { + get$span: function() { + return U._expandSafe(this.left.get$span(), this.right.get$span()); + }, + accept$1: function(visitor) { + return visitor.visitOr$1(this); + }, + toString$0: function(_) { + var string2, + string1 = this.left; + if (string1 instanceof U.AndNode || string1 instanceof U.ConditionalNode) + string1 = "(" + string1.toString$0(0) + ")"; + string2 = this.right; + if (string2 instanceof U.AndNode || string2 instanceof U.ConditionalNode) + string2 = "(" + string2.toString$0(0) + ")"; + return H.S(string1) + " || " + H.S(string2); + }, + $eq: function(_, other) { + if (other == null) + return false; + return other instanceof U.OrNode && this.left.$eq(0, other.left) && this.right.$eq(0, other.right); + }, + get$hashCode: function(_) { + var t1 = this.left, + t2 = this.right; + return (t1.get$hashCode(t1) ^ t2.get$hashCode(t2)) >>> 0; + }, + $isNode: 1 + }; + U.AndNode.prototype = { + get$span: function() { + return U._expandSafe(this.left.get$span(), this.right.get$span()); + }, + accept$1: function(visitor) { + return visitor.visitAnd$1(this); + }, + toString$0: function(_) { + var string2, + string1 = this.left; + if (string1 instanceof U.OrNode || string1 instanceof U.ConditionalNode) + string1 = "(" + string1.toString$0(0) + ")"; + string2 = this.right; + if (string2 instanceof U.OrNode || string2 instanceof U.ConditionalNode) + string2 = "(" + string2.toString$0(0) + ")"; + return H.S(string1) + " && " + H.S(string2); + }, + $eq: function(_, other) { + if (other == null) + return false; + return other instanceof U.AndNode && this.left.$eq(0, other.left) && this.right.$eq(0, other.right); + }, + get$hashCode: function(_) { + var t1 = this.left, + t2 = this.right; + return (t1.get$hashCode(t1) ^ t2.get$hashCode(t2)) >>> 0; + }, + $isNode: 1 + }; + U.ConditionalNode.prototype = { + get$span: function() { + return U._expandSafe(this.condition.get$span(), this.whenFalse.get$span()); + }, + accept$1: function(visitor) { + return visitor.visitConditional$1(this); + }, + toString$0: function(_) { + var trueString, + conditionString = this.condition; + if (conditionString instanceof U.ConditionalNode) + conditionString = "(" + conditionString.toString$0(0) + ")"; + trueString = this.whenTrue; + if (trueString instanceof U.ConditionalNode) + trueString = "(" + trueString.toString$0(0) + ")"; + return H.S(conditionString) + " ? " + H.S(trueString) + " : " + this.whenFalse.toString$0(0); + }, + $eq: function(_, other) { + if (other == null) + return false; + return other instanceof U.ConditionalNode && this.condition.$eq(0, other.condition) && this.whenTrue.$eq(0, other.whenTrue) && this.whenFalse.$eq(0, other.whenFalse); + }, + get$hashCode: function(_) { + var t1 = this.condition, + t2 = this.whenTrue, + t3 = this.whenFalse; + return (t1.get$hashCode(t1) ^ t2.get$hashCode(t2) ^ t3.get$hashCode(t3)) >>> 0; + }, + $isNode: 1 + }; + T.Evaluator.prototype = { + visitVariable$1: function(node) { + return this._semantics.call$1(node.name); + }, + visitNot$1: function(node) { + return !H.boolConversionCheck(node.child.accept$1(this)); + }, + visitOr$1: function(node) { + return H.boolConversionCheck(node.left.accept$1(this)) || H.boolConversionCheck(node.right.accept$1(this)); + }, + visitAnd$1: function(node) { + return H.boolConversionCheck(node.left.accept$1(this)) && H.boolConversionCheck(node.right.accept$1(this)); + }, + visitConditional$1: function(node) { + return H.boolConversionCheck(node.condition.accept$1(this)) ? node.whenTrue.accept$1(this) : node.whenFalse.accept$1(this); + }, + $isVisitor: 1 + }; + Y.BooleanSelectorImpl.prototype = { + evaluate$1: function(semantics) { + var t1; + if (type$.Iterable_dynamic._is(semantics)) { + t1 = semantics.toSet$0(0); + t1 = t1.get$contains(t1); + } else { + type$.bool_Function_String._as(semantics); + t1 = semantics; + } + return this._selector.accept$1(new T.Evaluator(t1)); + }, + intersection$1: function(other) { + var t1 = J.getInterceptor$(other); + if (t1.$eq(other, C.C_All)) + return this; + if (t1.$eq(other, C.C_None)) + return other; + return other instanceof Y.BooleanSelectorImpl ? new Y.BooleanSelectorImpl(new U.AndNode(this._selector, other._selector)) : new R.IntersectionSelector(this, other); + }, + validate$1: function(isDefined) { + this._selector.accept$1(new S.Validator(type$.bool_Function_String._check(isDefined))); + }, + toString$0: function(_) { + return this._selector.toString$0(0); + }, + $eq: function(_, other) { + if (other == null) + return false; + return other instanceof Y.BooleanSelectorImpl && this._selector.$eq(0, other._selector); + }, + get$hashCode: function(_) { + var t1 = this._selector; + return t1.get$hashCode(t1); + }, + $isBooleanSelector: 1 + }; + R.IntersectionSelector.prototype = { + evaluate$1: function(semantics) { + return H.boolConversionCheck(this._selector1.evaluate$1(semantics)) && H.boolConversionCheck(this._selector2.evaluate$1(semantics)); + }, + intersection$1: function(other) { + return new R.IntersectionSelector(this, other); + }, + validate$1: function(isDefined) { + type$.bool_Function_String._check(isDefined); + this._selector1.validate$1(isDefined); + this._selector2.validate$1(isDefined); + }, + toString$0: function(_) { + return "(" + this._selector1.toString$0(0) + ") && (" + H.S(this._selector2) + ")"; + }, + $eq: function(_, other) { + if (other == null) + return false; + return other instanceof R.IntersectionSelector && this._selector1.$eq(0, other._selector1) && J.$eq$(this._selector2, other._selector2); + }, + get$hashCode: function(_) { + var t1 = this._selector1; + return (t1.get$hashCode(t1) ^ J.get$hashCode$(this._selector2)) >>> 0; + }, + $isBooleanSelector: 1 + }; + O.None.prototype = { + evaluate$1: function(semantics) { + return false; + }, + intersection$1: function(other) { + return this; + }, + validate$1: function(isDefined) { + type$.bool_Function_String._check(isDefined); + }, + toString$0: function(_) { + return "<none>"; + }, + $isBooleanSelector: 1 + }; + G.Parser.prototype = { + parse$0: function() { + var selector = this._conditional$0(), + t1 = this._parser0$_scanner, + t2 = t1.peek$0(); + if (t2.get$type(t2) !== C.TokenType_wwi) + throw H.wrapException(G.SourceSpanFormatException$("Expected end of input.", t1.peek$0().get$span(), null)); + return selector; + }, + _conditional$0: function() { + var whenTrue, _this = this, + condition = _this._or$0(), + t1 = _this._parser0$_scanner; + if (!t1.scan$1(C.TokenType_69P)) + return condition; + whenTrue = _this._conditional$0(); + if (!t1.scan$1(C.TokenType_colon)) + throw H.wrapException(G.SourceSpanFormatException$('Expected ":".', t1.peek$0().get$span(), null)); + return new U.ConditionalNode(condition, whenTrue, _this._conditional$0()); + }, + _or$0: function() { + var left = this._and$0(); + if (!this._parser0$_scanner.scan$1(C.TokenType_or)) + return left; + return new U.OrNode(left, this._or$0()); + }, + _and$0: function() { + var left = this._simpleExpression$0(); + if (!this._parser0$_scanner.scan$1(C.TokenType_and)) + return left; + return new U.AndNode(left, this._and$0()); + }, + _simpleExpression$0: function() { + var child, + t1 = this._parser0$_scanner, + token = t1.next$0(); + switch (token.get$type(token)) { + case C.TokenType_not: + child = this._simpleExpression$0(); + return new U.NotNode(token.get$span().expand$1(0, child.get$span()), child); + case C.TokenType_e7P: + child = this._conditional$0(); + if (!t1.scan$1(C.TokenType_31K)) + throw H.wrapException(G.SourceSpanFormatException$('Expected ")".', t1.peek$0().get$span(), null)); + return child; + case C.TokenType_identifier: + type$.IdentifierToken._as(token); + return new U.VariableNode(token.span, token.name); + default: + throw H.wrapException(G.SourceSpanFormatException$("Expected expression.", token.get$span(), null)); + } + } + }; + O.Scanner.prototype = { + peek$0: function() { + var t1 = this._scanner$_next; + return t1 == null ? this._scanner$_next = this._getNext$0() : t1; + }, + next$0: function() { + var _this = this, + token = _this._scanner$_next; + if (token == null) + token = _this._getNext$0(); + _this._endOfFileEmitted = token.get$type(token) === C.TokenType_wwi; + _this._scanner$_next = null; + return token; + }, + scan$1: function(type) { + var t1 = this.peek$0(); + if (t1.get$type(t1) !== type) + return false; + this.next$0(); + return true; + }, + _getNext$0: function() { + var t1, t2, _this = this; + if (_this._endOfFileEmitted) + throw H.wrapException(P.StateError$("No more tokens.")); + _this._consumeWhitespace$0(); + t1 = _this._scanner; + t2 = t1._string_scanner$_position; + if (t2 === t1.string.length) + return new L.Token(C.TokenType_wwi, t1.spanFrom$1(new S._SpanScannerState(t1, t2))); + switch (t1.peekChar$0()) { + case 40: + return _this._scanOperator$1(C.TokenType_e7P); + case 41: + return _this._scanOperator$1(C.TokenType_31K); + case 63: + return _this._scanOperator$1(C.TokenType_69P); + case 58: + return _this._scanOperator$1(C.TokenType_colon); + case 33: + return _this._scanOperator$1(C.TokenType_not); + case 124: + t2 = t1._string_scanner$_position; + t1.expect$1("||"); + return new L.Token(C.TokenType_or, t1.spanFrom$1(new S._SpanScannerState(t1, t2))); + case 38: + t2 = t1._string_scanner$_position; + t1.expect$1("&&"); + return new L.Token(C.TokenType_and, t1.spanFrom$1(new S._SpanScannerState(t1, t2))); + default: + t1.expect$2$name($.$get$_hyphenatedIdentifier0(), "expression"); + t2 = t1.get$lastMatch().$index(0, 0); + if (t1.get$lastMatch() == null) + t1._lastSpan = null; + return new L.IdentifierToken(t1._lastSpan, t2); + } + }, + _scanOperator$1: function(type) { + var t1 = this._scanner, + t2 = t1._string_scanner$_position, + t3 = t1.string; + if (t2 === t3.length) + t1.error$3$length$position(0, "expected more input.", 0, t2); + J.codeUnitAt$1$s(t3, t1._string_scanner$_position++); + return new L.Token(type, t1.spanFrom$1(new S._SpanScannerState(t1, t2))); + }, + _consumeWhitespace$0: function() { + var success, + t1 = this._scanner; + while (true) { + success = t1.matches$1(0, $.$get$_whitespaceAndSingleLineComments()); + if (success) + t1._lastMatchPosition = t1._string_scanner$_position = t1._lastMatch.get$end(); + if (!(success || this._multiLineComment$0())) + break; + } + }, + _multiLineComment$0: function() { + var success, + t1 = this._scanner; + if (!t1.scan$1("/*")) + return false; + while (true) { + success = t1.matches$1(0, $.$get$_multiLineCommentBody()); + if (success) + t1._lastMatchPosition = t1._string_scanner$_position = t1._lastMatch.get$end(); + if (!(success || this._multiLineComment$0())) + break; + } + t1.expect$1("*/"); + return true; + } + }; + L.Token.prototype = { + get$type: function(receiver) { + return this.type; + }, + get$span: function() { + return this.span; + } + }; + L.IdentifierToken.prototype = { + toString$0: function(_) { + return 'identifier "' + H.S(this.name) + '"'; + }, + $isToken: 1, + get$type: function() { + return C.TokenType_identifier; + }, + get$span: function() { + return this.span; + } + }; + L.TokenType.prototype = { + toString$0: function(_) { + return this.name; + } + }; + S.Validator.prototype = { + visitVariable$1: function(node) { + if (H.boolConversionCheck(this._isDefined.call$1(node.name))) + return; + throw H.wrapException(G.SourceSpanFormatException$("Undefined variable.", node.span, null)); + } + }; + B.RecursiveVisitor.prototype = { + visitNot$1: function(node) { + node.child.accept$1(this); + }, + visitOr$1: function(node) { + node.left.accept$1(this); + node.right.accept$1(this); + }, + visitAnd$1: function(node) { + node.left.accept$1(this); + node.right.accept$1(this); + }, + visitConditional$1: function(node) { + node.condition.accept$1(this); + node.whenTrue.accept$1(this); + node.whenFalse.accept$1(this); + }, + $isVisitor: 1 + }; + O.EmptyUnmodifiableSet.prototype = { + get$iterator: function(_) { + return C.C_EmptyIterator; + }, + get$length: function(_) { + return 0; + }, + contains$1: function(_, element) { + return false; + }, + toSet$0: function(_) { + return P.LinkedHashSet_LinkedHashSet(this.$ti._precomputed1); + }, + $isEfficientLengthIterable: 1, + $isSet: 1 + }; + Y.mapMap_closure.prototype = { + call$2: function(mapKey, _) { + this.K1._check(mapKey); + this.V1._check(_); + return this.K2._as(mapKey); + }, + $signature: function() { + return this.K2._eval$1("@<0>")._bind$1(this.K1)._bind$1(this.V1)._eval$1("1(2,3)"); + } + }; + Y.mapMap_closure0.prototype = { + call$2: function(mapKey, mapValue) { + var t1, _this = this; + _this.K1._check(mapKey); + _this.V1._check(mapValue); + t1 = _this._box_0; + _this.result.$indexSet(0, t1.key.call$2(mapKey, mapValue), t1.value.call$2(mapKey, mapValue)); + }, + $signature: function() { + return this.K1._eval$1("@<0>")._bind$1(this.V1)._eval$1("Null(1,2)"); + } + }; + Y.mergeMaps_closure.prototype = { + call$2: function(key, mapValue) { + var t1, _this = this; + _this.K._check(key); + _this.V._check(mapValue); + t1 = _this.result; + t1.$indexSet(0, key, t1.containsKey$1(key) ? _this.value.call$2(t1.$index(0, key), mapValue) : mapValue); + }, + $signature: function() { + return this.K._eval$1("@<0>")._bind$1(this.V)._eval$1("Null(1,2)"); + } + }; + Q.QueueList.prototype = { + toString$0: function(_) { + return P.IterableBase_iterableToFullString(this, "{", "}"); + }, + removeFirst$0: function() { + var t2, result, _this = this, + t1 = _this._queue_list$_head; + if (t1 === _this._queue_list$_tail) + throw H.wrapException(P.StateError$("No element")); + t2 = _this._queue_list$_table; + if (t1 >= t2.length) + return H.ioore(t2, t1); + result = t2[t1]; + C.JSArray_methods.$indexSet(t2, t1, null); + _this._queue_list$_head = (_this._queue_list$_head + 1 & _this._queue_list$_table.length - 1) >>> 0; + return result; + }, + get$length: function(_) { + return (this._queue_list$_tail - this._queue_list$_head & this._queue_list$_table.length - 1) >>> 0; + }, + set$length: function(_, value) { + var delta, t1, newTail, t2, _this = this; + if (value < 0) + throw H.wrapException(P.RangeError$("Length " + value + " may not be negative.")); + delta = value - _this.get$length(_this); + if (delta >= 0) { + if (_this._queue_list$_table.length <= value) + _this._preGrow$1(value); + _this._queue_list$_tail = (_this._queue_list$_tail + delta & _this._queue_list$_table.length - 1) >>> 0; + return; + } + t1 = _this._queue_list$_tail; + newTail = t1 + delta; + t2 = _this._queue_list$_table; + if (newTail >= 0) + C.JSArray_methods.fillRange$3(t2, newTail, t1, null); + else { + newTail += t2.length; + C.JSArray_methods.fillRange$3(t2, 0, t1, null); + t1 = _this._queue_list$_table; + C.JSArray_methods.fillRange$3(t1, newTail, t1.length, null); + } + _this._queue_list$_tail = newTail; + }, + $index: function(_, index) { + var t1, t2, t3, _this = this; + H._checkIntNullable(index); + if (index < 0 || index >= _this.get$length(_this)) + throw H.wrapException(P.RangeError$("Index " + index + " must be in the range [0.." + _this.get$length(_this) + ").")); + t1 = _this._queue_list$_table; + t2 = t1.length; + t3 = (_this._queue_list$_head + index & t2 - 1) >>> 0; + if (t3 < 0 || t3 >= t2) + return H.ioore(t1, t3); + return t1[t3]; + }, + $indexSet: function(_, index, value) { + var t1, _this = this; + H._checkIntNullable(index); + _this.$ti._precomputed1._check(value); + if (typeof index !== "number") + return index.$lt(); + if (index < 0 || index >= _this.get$length(_this)) + throw H.wrapException(P.RangeError$("Index " + index + " must be in the range [0.." + _this.get$length(_this) + ").")); + t1 = _this._queue_list$_table; + C.JSArray_methods.$indexSet(t1, (_this._queue_list$_head + index & t1.length - 1) >>> 0, value); + }, + _queue_list$_add$1: function(element) { + var t2, t3, newTable, split, _this = this, + t1 = _this.$ti; + t1._precomputed1._check(element); + C.JSArray_methods.$indexSet(_this._queue_list$_table, _this._queue_list$_tail, element); + t2 = _this._queue_list$_tail; + t3 = _this._queue_list$_table.length; + t2 = (t2 + 1 & t3 - 1) >>> 0; + _this._queue_list$_tail = t2; + if (_this._queue_list$_head === t2) { + t2 = new Array(t3 * 2); + t2.fixed$length = Array; + newTable = H.setRuntimeTypeInfo(t2, t1._eval$1("JSArray<1>")); + t1 = _this._queue_list$_table; + t2 = _this._queue_list$_head; + split = t1.length - t2; + C.JSArray_methods.setRange$4(newTable, 0, split, t1, t2); + C.JSArray_methods.setRange$4(newTable, split, split + _this._queue_list$_head, _this._queue_list$_table, 0); + _this._queue_list$_head = 0; + _this._queue_list$_tail = _this._queue_list$_table.length; + _this.set$_queue_list$_table(newTable); + } + }, + _writeToList$1: function(target) { + var t1, t2, t3, $length, firstPartSize, _this = this; + _this.$ti._eval$1("List<1>")._check(target); + H.assertHelper(target.length >= _this.get$length(_this)); + t1 = _this._queue_list$_head; + t2 = _this._queue_list$_tail; + t3 = _this._queue_list$_table; + if (t1 <= t2) { + $length = t2 - t1; + C.JSArray_methods.setRange$4(target, 0, $length, t3, t1); + return $length; + } else { + firstPartSize = t3.length - t1; + C.JSArray_methods.setRange$4(target, 0, firstPartSize, t3, t1); + C.JSArray_methods.setRange$4(target, firstPartSize, firstPartSize + _this._queue_list$_tail, _this._queue_list$_table, 0); + return _this._queue_list$_tail + firstPartSize; + } + }, + _preGrow$1: function(newElementCount) { + var newCapacity, t1, newTable, _this = this; + H.assertHelper(newElementCount >= _this.get$length(_this)); + newCapacity = Q.QueueList__nextPowerOf2(newElementCount + C.JSInt_methods._shrOtherPositive$1(newElementCount, 1)); + if (typeof newCapacity !== "number") + return H.iae(newCapacity); + t1 = new Array(newCapacity); + t1.fixed$length = Array; + newTable = H.setRuntimeTypeInfo(t1, _this.$ti._eval$1("JSArray<1>")); + _this._queue_list$_tail = _this._writeToList$1(newTable); + _this.set$_queue_list$_table(newTable); + _this._queue_list$_head = 0; + }, + set$_queue_list$_table: function(_table) { + this._queue_list$_table = this.$ti._eval$1("List<1>")._check(_table); + }, + $isEfficientLengthIterable: 1, + $isQueue: 1, + $isIterable: 1, + $isList: 1 + }; + Q._QueueList_Object_ListMixin.prototype = {}; + M.UnionSet.prototype = { + get$length: function(_) { + var t1 = this._sets.fold$1$2(0, 0, new M.UnionSet_length_closure(this), type$.int); + return t1; + }, + get$iterator: function(_) { + var t1 = this.get$_union_set$_iterable(); + return t1.get$iterator(t1); + }, + get$_union_set$_iterable: function() { + var t1 = this._sets, + t2 = this.$ti._precomputed1, + t3 = H._instanceType(t1), + t4 = t3._bind$1(t2)._eval$1("Iterable<1>(2)")._check(new M.UnionSet__iterable_closure(this)); + return new H.ExpandIterable(t1, t4, t3._eval$1("@<1>")._bind$1(t2)._eval$1("ExpandIterable<1,2>")); + }, + toSet$0: function(_) { + var t1, + result = P.LinkedHashSet_LinkedHashSet(this.$ti._precomputed1); + for (t1 = this._sets, t1 = P._LinkedHashSetIterator$(t1, t1._collection$_modifications, H._instanceType(t1)._precomputed1); t1.moveNext$0();) + result.addAll$1(0, t1._collection$_current); + return result; + } + }; + M.UnionSet_length_closure.prototype = { + call$2: function($length, set) { + var t1; + H._checkIntNullable($length); + this.$this.$ti._eval$1("Set<1>")._check(set); + t1 = set.get$length(set); + if (typeof $length !== "number") + return $length.$add(); + if (typeof t1 !== "number") + return H.iae(t1); + return $length + t1; + }, + $signature: function() { + return this.$this.$ti._eval$1("int(int,Set<1>)"); + } + }; + M.UnionSet__iterable_closure.prototype = { + call$1: function(set) { + return this.$this.$ti._eval$1("Set<1>")._check(set); + }, + $signature: function() { + return this.$this.$ti._eval$1("Set<1>(Set<1>)"); + } + }; + M._UnionSet_SetBase_UnmodifiableSetMixin.prototype = {}; + Y.UnionSetController.prototype = { + set$_union_set_controller$_set: function(_set) { + this._union_set_controller$_set = this.$ti._eval$1("UnionSet<1>")._check(_set); + } + }; + L.UnmodifiableSetView.prototype = {}; + L.UnmodifiableSetMixin.prototype = {}; + L._UnmodifiableSetView_DelegatingSet_UnmodifiableSetMixin.prototype = {}; + M._DelegatingIterableBase.prototype = { + contains$1: function(_, element) { + return this._base.contains$1(0, element); + }, + every$1: function(_, test) { + return this._base.every$1(0, H._instanceType(this)._eval$1("bool(1)")._check(test)); + }, + get$first: function(_) { + var t1 = this._base; + return t1.get$first(t1); + }, + get$isEmpty: function(_) { + var t1 = this._base; + return t1.get$isEmpty(t1); + }, + get$iterator: function(_) { + var t1 = this._base; + return t1.get$iterator(t1); + }, + get$last: function(_) { + var t1 = this._base; + return t1.get$last(t1); + }, + get$length: function(_) { + var t1 = this._base; + return t1.get$length(t1); + }, + map$1$1: function(_, f, $T) { + return this._base.map$1$1(0, H._instanceType(this)._bind$1($T)._eval$1("1(2)")._check(f), $T); + }, + toList$1$growable: function(_, growable) { + return this._base.toList$1$growable(0, true); + }, + toList$0: function($receiver) { + return this.toList$1$growable($receiver, true); + }, + toSet$0: function(_) { + return this._base.toSet$0(0); + }, + where$1: function(_, test) { + return this._base.where$1(0, H._instanceType(this)._eval$1("bool(1)")._check(test)); + }, + toString$0: function(_) { + return this._base.toString$0(0); + }, + $isIterable: 1 + }; + M.DelegatingIterable.prototype = {}; + M.DelegatingSet.prototype = { + union$1: function(other) { + var t1 = H._instanceType(this)._eval$1("Set<1>"); + t1._check(other); + return t1._check(this._base).union$1(other); + }, + toSet$0: function(_) { + var t1 = H._instanceType(this); + return new M.DelegatingSet(t1._eval$1("Set<1>")._check(this._base).toSet$0(0), t1._eval$1("DelegatingSet<1>")); + }, + $isEfficientLengthIterable: 1, + $isSet: 1 + }; + Y._IsTrue.prototype = { + matches$2: function(_, item, matchState) { + return J.$eq$(item, true); + }, + describe$1: function(description) { + description._out._contents += "true"; + return description; + } + }; + Y._Predicate.prototype = { + typedMatches$2: function(item, matchState) { + return this._matcher.call$1(this.$ti._precomputed1._check(item)); + }, + describe$1: function(description) { + description._out._contents += this._core_matchers$_description; + return description; + } + }; + E.StringDescription.prototype = { + get$length: function(_) { + return this._out._contents.length; + }, + toString$0: function(_) { + var t1 = this._out._contents; + return t1.charCodeAt(0) == 0 ? t1 : t1; + }, + addDescriptionOf$1: function(value) { + if (value instanceof G.Matcher) + value.describe$1(this); + else + this._out._contents += Z.prettyPrint(value, 25, 80); + return this; + }, + $isDescription: 1 + }; + D._StringEqualsMatcher.prototype = { + typedMatches$2: function(item, matchState) { + return this._equals_matcher$_value === H._checkStringNullable(item); + }, + describe$1: function(description) { + return description.addDescriptionOf$1(this._equals_matcher$_value); + }, + describeTypedMismatch$4: function(item, mismatchDescription, matchState, verbose) { + var buff, escapedItem, escapedValue, minLength, minLength0, minLength1, start, t1, i; + H._checkStringNullable(true); + buff = new P.StringBuffer(""); + buff._contents = "is different."; + escapedItem = M.escape(true); + escapedValue = M.escape(this._equals_matcher$_value); + minLength = escapedItem.length; + minLength0 = escapedValue.length; + minLength1 = minLength < minLength0 ? minLength : minLength0; + for (start = 0; start < minLength1; ++start) + if (C.JSString_methods._codeUnitAt$1(escapedValue, start) !== C.JSString_methods._codeUnitAt$1(escapedItem, start)) + break; + if (start === minLength1) { + t1 = buff._contents; + if (minLength0 < minLength) { + buff._contents = t1 + " Both strings start the same, but the actual value also has the following trailing characters: "; + D._StringEqualsMatcher__writeTrailing(buff, escapedItem, minLength0); + } else { + buff._contents = t1 + " Both strings start the same, but the actual value is missing the following trailing characters: "; + D._StringEqualsMatcher__writeTrailing(buff, escapedValue, minLength); + } + } else { + buff._contents += "\nExpected: "; + D._StringEqualsMatcher__writeLeading(buff, escapedValue, start); + D._StringEqualsMatcher__writeTrailing(buff, escapedValue, start); + buff._contents += "\n Actual: "; + D._StringEqualsMatcher__writeLeading(buff, escapedItem, start); + D._StringEqualsMatcher__writeTrailing(buff, escapedItem, start); + t1 = buff._contents += "\n "; + i = start > 10 ? 14 : start; + for (; i > 0; --i) { + t1 += " "; + buff._contents = t1; + } + buff._contents += "^\n Differ at offset " + start; + } + t1 = buff._contents; + mismatchDescription._out._contents += t1.charCodeAt(0) == 0 ? t1 : t1; + return mismatchDescription; + } + }; + D._DeepMatcher.prototype = { + _compareIterables$5: function(expected, actual, matcher, depth, $location) { + var expectedIterator, actualIterator, index, expectedNext, actualNext, t1, newLocation, rp; + type$.List_String_Function_dynamic_dynamic_String_int._check(matcher); + if (type$.Iterable_dynamic._is(actual)) { + expectedIterator = J.get$iterator$ax(expected); + actualIterator = J.get$iterator$ax(actual); + for (index = 0; true; ++index) { + expectedNext = expectedIterator.moveNext$0(); + actualNext = actualIterator.moveNext$0(); + t1 = !expectedNext; + if (t1 && !actualNext) + return null; + newLocation = $location + "[" + index + "]"; + if (t1) + return H.setRuntimeTypeInfo(["longer than expected", newLocation], type$.JSArray_String); + if (!actualNext) + return H.setRuntimeTypeInfo(["shorter than expected", newLocation], type$.JSArray_String); + rp = matcher.call$4(expectedIterator.get$current(), actualIterator.get$current(), newLocation, depth); + if (rp != null) + return rp; + } + } else + return H.setRuntimeTypeInfo(["is not Iterable", $location], type$.JSArray_String); + }, + _compareSets$5: function(expected, actual, matcher, depth, $location) { + var other, t1, expectedElement, t2; + type$.List_String_Function_dynamic_dynamic_String_int._check(matcher); + if (type$.Iterable_dynamic._is(actual)) { + other = J.toSet$0$ax(actual); + for (t1 = expected.get$iterator(expected); t1.moveNext$0();) { + expectedElement = t1.get$current(); + if (other.every$1(0, new D._DeepMatcher__compareSets_closure(matcher, expectedElement, $location, depth))) + return H.setRuntimeTypeInfo(["does not contain " + H.S(expectedElement), $location], type$.JSArray_String); + } + t1 = other.get$length(other); + t2 = expected.get$length(expected); + if (typeof t2 !== "number") + return H.iae(t2); + if (t1 > t2) + return H.setRuntimeTypeInfo(["larger than expected", $location], type$.JSArray_String); + else { + t1 = other.get$length(other); + t2 = expected.get$length(expected); + if (typeof t2 !== "number") + return H.iae(t2); + if (t1 < t2) + return H.setRuntimeTypeInfo(["smaller than expected", $location], type$.JSArray_String); + else + return null; + } + } else + return H.setRuntimeTypeInfo(["is not Iterable", $location], type$.JSArray_String); + }, + _recursiveMatch$4: function(expected, actual, $location, depth) { + var e, t1, description, exception, err, key, t2, rp, _this = this; + if (expected instanceof G.Matcher) { + t1 = type$.dynamic; + if (expected.matches$2(0, actual, P.LinkedHashMap_LinkedHashMap$_empty(t1, t1))) + return null; + description = new E.StringDescription(new P.StringBuffer("")); + expected.describe$1(description); + return H.setRuntimeTypeInfo(["does not match " + description.toString$0(0), $location], type$.JSArray_String); + } else + try { + if (J.$eq$(expected, actual)) + return null; + } catch (exception) { + e = H.unwrapException(exception); + t1 = H.setRuntimeTypeInfo(['== threw "' + H.S(e) + '"', $location], type$.JSArray_String); + return t1; + } + t1 = _this._limit; + if (depth > t1) + return H.setRuntimeTypeInfo(["recursion depth limit exceeded", $location], type$.JSArray_String); + if (depth === 0 || t1 > 1) + if (type$.Set_dynamic._is(expected)) + return _this._compareSets$5(expected, actual, _this.get$_recursiveMatch(), depth + 1, $location); + else if (type$.Iterable_dynamic._is(expected)) + return _this._compareIterables$5(expected, actual, _this.get$_recursiveMatch(), depth + 1, $location); + else { + t1 = type$.Map_dynamic_dynamic; + if (t1._is(expected)) { + if (!t1._is(actual)) + return H.setRuntimeTypeInfo(["expected a map", $location], type$.JSArray_String); + err = expected.get$length(expected) == actual.get$length(actual) ? "" : "has different length and "; + for (t1 = expected.get$keys(), t1 = t1.get$iterator(t1); t1.moveNext$0();) { + key = t1.get$current(); + if (!actual.containsKey$1(key)) + return H.setRuntimeTypeInfo([err + "is missing map key '" + H.S(key) + "'", $location], type$.JSArray_String); + } + for (t1 = actual.get$keys(), t1 = t1.get$iterator(t1); t1.moveNext$0();) { + key = t1.get$current(); + if (!expected.containsKey$1(key)) + return H.setRuntimeTypeInfo([err + "has extra map key '" + H.S(key) + "'", $location], type$.JSArray_String); + } + for (t1 = expected.get$keys(), t1 = t1.get$iterator(t1), t2 = depth + 1; t1.moveNext$0();) { + key = t1.get$current(); + rp = _this._recursiveMatch$4(expected.$index(0, key), actual.$index(0, key), $location + "['" + H.S(key) + "']", t2); + if (rp != null) + return rp; + } + return null; + } + } + t1 = new P.StringBuffer(""); + if (depth > 0) { + t1._contents = "was "; + t2 = new E.StringDescription(t1).addDescriptionOf$1(actual); + t2._out._contents += " instead of "; + t2.addDescriptionOf$1(expected); + t1 = t1._contents; + return H.setRuntimeTypeInfo([t1.charCodeAt(0) == 0 ? t1 : t1, $location], type$.JSArray_String); + } + return H.setRuntimeTypeInfo(["", $location], type$.JSArray_String); + }, + _equals_matcher$_match$3: function(expected, actual, matchState) { + var t1, t2, reason, innerState, + rp = this._recursiveMatch$4(expected, actual, "", 0); + if (rp == null) + return null; + t1 = J.getInterceptor$asx(rp); + t2 = t1.$index(rp, 0); + t2.toString; + if (J.get$length$asx(t2) !== 0) { + t2 = t1.$index(rp, 1); + t2.toString; + reason = J.get$length$asx(t2) !== 0 ? H.S(t1.$index(rp, 0)) + " at location " + H.S(t1.$index(rp, 1)) : t1.$index(rp, 0); + } else + reason = ""; + t1 = type$.dynamic; + t2 = P.LinkedHashMap_LinkedHashMap$_literal(["reason", reason], t1, t1); + innerState = P.LinkedHashMap_LinkedHashMap$from(matchState, t1, t1); + matchState.clear$0(0); + matchState.$indexSet(0, "state", innerState); + matchState.addAll$1(0, t2); + return reason; + }, + matches$2: function(_, item, matchState) { + return this._equals_matcher$_match$3(this._expected, item, matchState) == null; + }, + describe$1: function(description) { + return description.addDescriptionOf$1(this._expected); + }, + describeMismatch$4: function(item, mismatchDescription, matchState, verbose) { + var t1, t2, t3, + reason = H._asStringNullable(matchState.$index(0, "reason")); + if (reason == null) + reason = ""; + t1 = reason.length === 0 && mismatchDescription._out._contents.length > 0; + t2 = mismatchDescription._out; + t3 = t2._contents; + if (t1) { + t2._contents = t3 + "is "; + mismatchDescription.addDescriptionOf$1(true); + } else + t2._contents = t3 + reason; + return mismatchDescription; + } + }; + D._DeepMatcher__compareSets_closure.prototype = { + call$1: function(actualElement) { + var _this = this; + return _this.matcher.call$4(_this.expectedElement, actualElement, _this.location, _this.depth) != null; + }, + $signature: 9 + }; + E.FeatureMatcher.prototype = { + matches$2: function(_, item, matchState) { + return this.super$TypeMatcher$matches(0, item, matchState) && H.boolConversionCheck(this.typedMatches$2(H._instanceType(this)._eval$1("FeatureMatcher.T")._check(item), matchState)); + }, + describeMismatch$4: function(item, mismatchDescription, matchState, verbose) { + if (H._instanceType(this)._eval$1("FeatureMatcher.T")._is(true)) + return this.describeTypedMismatch$4(true, mismatchDescription, matchState, false); + mismatchDescription._out._contents += "not an "; + return this.super$TypeMatcher$describe(mismatchDescription); + }, + describeTypedMismatch$4: function(item, mismatchDescription, matchState, verbose) { + H._instanceType(this)._eval$1("FeatureMatcher.T")._check(true); + return mismatchDescription; + } + }; + G.Matcher.prototype = { + describeMismatch$4: function(item, mismatchDescription, matchState, verbose) { + return mismatchDescription; + } + }; + Z.prettyPrint__prettyPrint.prototype = { + call$4: function(object, indent, seen, $top) { + var description, type, t2, strings, t3, singleLine, value, defaultToString, _this = this, t1 = {}; + t1.seen = seen; + if (object instanceof G.Matcher) { + description = new E.StringDescription(new P.StringBuffer("")); + object.describe$1(description); + return "<" + description.toString$0(0) + ">"; + } + if (seen.contains$1(0, object)) + return "(recursive)"; + t1.seen = seen.union$1(P.LinkedHashSet_LinkedHashSet$_literal([object], type$.dynamic)); + t1 = new Z.prettyPrint__prettyPrint_pp(t1, _this, indent); + if (type$.Iterable_dynamic._is(object)) { + type = type$.List_dynamic._is(object) ? "" : Z._typeName(object) + ":"; + t2 = type$.String; + strings = J.map$1$1$ax(object, t1, t2).toList$0(0); + t1 = strings.length; + t3 = _this.maxItems; + if (t1 > t3) + C.JSArray_methods.replaceRange$3(strings, t3 - 1, t1, H.setRuntimeTypeInfo(["..."], type$.JSArray_String)); + singleLine = type + "[" + C.JSArray_methods.join$1(strings, ", ") + "]"; + if (singleLine.length + indent <= _this.maxLineLength && !C.JSString_methods.contains$1(singleLine, "\n")) + return singleLine; + t1 = H._arrayInstanceType(strings); + return type + "[\n" + new H.MappedListIterable(strings, t1._eval$1("String(1)")._check(new Z.prettyPrint__prettyPrint_closure(indent)), t1._eval$1("MappedListIterable<1,String>")).join$1(0, ",\n") + "\n" + C.JSArray_methods.join$1(P.List_List$filled(indent, " ", t2), "") + "]"; + } else if (type$.Map_dynamic_dynamic._is(object)) { + t2 = type$.String; + strings = object.get$keys().map$1$1(0, new Z.prettyPrint__prettyPrint_closure0(t1, object), t2).toList$0(0); + t1 = strings.length; + t3 = _this.maxItems; + if (t1 > t3) + C.JSArray_methods.replaceRange$3(strings, t3 - 1, t1, H.setRuntimeTypeInfo(["..."], type$.JSArray_String)); + singleLine = "{" + C.JSArray_methods.join$1(strings, ", ") + "}"; + if (singleLine.length + indent <= _this.maxLineLength && !C.JSString_methods.contains$1(singleLine, "\n")) + return singleLine; + t1 = H._arrayInstanceType(strings); + return "{\n" + new H.MappedListIterable(strings, t1._eval$1("String(1)")._check(new Z.prettyPrint__prettyPrint_closure1(indent)), t1._eval$1("MappedListIterable<1,String>")).join$1(0, ",\n") + "\n" + C.JSArray_methods.join$1(P.List_List$filled(indent, " ", t2), "") + "}"; + } else { + t1 = type$.String; + if (typeof object == "string") + return "'" + new H.MappedListIterable(H.setRuntimeTypeInfo(object.split("\n"), type$.JSArray_String), type$.String_Function_String._check(Z.pretty_print___escapeString$closure()), type$.MappedListIterable_String_String).join$1(0, "\\n'\n" + C.JSArray_methods.join$1(P.List_List$filled(indent + 2, " ", t1), "") + "'") + "'"; + else { + t2 = J.toString$0$(object); + t1 = C.JSArray_methods.join$1(P.List_List$filled(indent, " ", t1), "") + "\n"; + t2.toString; + value = H.stringReplaceAllUnchecked(t2, "\n", t1); + defaultToString = C.JSString_methods.startsWith$1(value, "Instance of "); + if ($top) + value = "<" + value + ">"; + if (typeof object == "number" || H._isBool(object) || type$.Function._is(object) || type$.RegExp._is(object) || object instanceof P.MapEntry || object instanceof P.Expando || object == null || defaultToString) + return value; + else + return Z._typeName(object) + ":" + value; + } + } + }, + $signature: 55 + }; + Z.prettyPrint__prettyPrint_pp.prototype = { + call$1: function(child) { + return this._prettyPrint.call$4(child, this.indent + 2, this._box_0.seen, false); + }, + $signature: 40 + }; + Z.prettyPrint__prettyPrint_closure.prototype = { + call$1: function(string) { + H._checkStringNullable(string); + return C.JSString_methods.$add(C.JSArray_methods.join$1(P.List_List$filled(this.indent + 2, " ", type$.String), ""), string); + }, + $signature: 7 + }; + Z.prettyPrint__prettyPrint_closure0.prototype = { + call$1: function(key) { + var t1 = this.pp; + return H.S(t1.call$1(key)) + ": " + H.S(t1.call$1(this.object.$index(0, key))); + }, + $signature: 40 + }; + Z.prettyPrint__prettyPrint_closure1.prototype = { + call$1: function(string) { + H._checkStringNullable(string); + return C.JSString_methods.$add(C.JSArray_methods.join$1(P.List_List$filled(this.indent + 2, " ", type$.String), ""), string); + }, + $signature: 7 + }; + M.TypeMatcher.prototype = { + describe$1: function(description) { + var $name, + t1 = H._rtiToString(H.createRuntimeType(H._instanceType(this)._eval$1("TypeMatcher.T"))._rti, null), + t2 = $.$get$_dart2DynamicArgs(); + t1.toString; + $name = H.stringReplaceAllUnchecked(t1, t2, ""); + description._out._contents += "<Instance of '" + $name + "'>"; + return description; + }, + matches$2: function(_, item, matchState) { + return H._instanceType(this)._eval$1("TypeMatcher.T")._is(item); + } + }; + M.wrapMatcher_closure.prototype = { + call$1: function(a) { + return H._checkBoolNullable(this.x.call$1(a)); + }, + $signature: 9 + }; + M.escape_closure.prototype = { + call$1: function(match) { + var mapped = C.Map_F9GZw.$index(0, match.$index(0, 0)); + if (mapped != null) + return mapped; + return M._getHexLiteral(match.$index(0, 0)); + }, + $signature: 24 + }; + F.PackageConfigResolver.prototype = {$isSyncPackageResolver: 1, + get$packageRoot: function() { + return null; + }, + get$packageConfigMap: function() { + return this.packageConfigMap; + } + }; + F.PackageConfigResolver__normalizeMap_closure.prototype = { + call$2: function(_, uri) { + return B.ensureTrailingSlash(type$.Uri._check(uri)); + }, + $signature: 51 + }; + D.PackageRootResolver.prototype = {$isSyncPackageResolver: 1, + get$packageConfigMap: function() { + return null; + }, + get$packageRoot: function() { + return this.packageRoot; + } + }; + M.Context.prototype = { + absolute$7: function(_, part1, part2, part3, part4, part5, part6, part7) { + var t1; + M._validateArgList("absolute", H.setRuntimeTypeInfo([part1, part2, part3, part4, part5, part6, part7], type$.JSArray_String)); + t1 = this.style; + t1 = t1.rootLength$1(part1) > 0 && !t1.isRootRelative$1(part1); + if (t1) + return part1; + t1 = this._context$_current; + return this.join$8(0, t1 != null ? t1 : D.current(), part1, part2, part3, part4, part5, part6, part7); + }, + absolute$1: function($receiver, part1) { + return this.absolute$7($receiver, part1, null, null, null, null, null, null); + }, + join$8: function(_, part1, part2, part3, part4, part5, part6, part7, part8) { + var parts = H.setRuntimeTypeInfo([part1, part2, part3, part4, part5, part6, part7, part8], type$.JSArray_String); + M._validateArgList("join", parts); + return this.joinAll$1(new H.WhereIterable(parts, type$.bool_Function_String._check(new M.Context_join_closure()), type$.WhereIterable_String)); + }, + join$2: function($receiver, part1, part2) { + return this.join$8($receiver, part1, part2, null, null, null, null, null, null); + }, + joinAll$1: function(parts) { + var t1, t2, t3, needsSeparator, isAbsoluteAndNotRootRelative, t4, t5, parsed, path, t6; + type$.Iterable_String._check(parts); + for (t1 = parts.$ti, t2 = t1._eval$1("bool(Iterable.E)")._check(new M.Context_joinAll_closure()), t3 = parts.get$iterator(parts), t1 = new H.WhereIterator(t3, t2, t1._eval$1("WhereIterator<Iterable.E>")), t2 = this.style, needsSeparator = false, isAbsoluteAndNotRootRelative = false, t4 = ""; t1.moveNext$0();) { + t5 = t3.get$current(); + if (t2.isRootRelative$1(t5) && isAbsoluteAndNotRootRelative) { + parsed = X.ParsedPath_ParsedPath$parse(t5, t2); + path = t4.charCodeAt(0) == 0 ? t4 : t4; + t4 = C.JSString_methods.substring$2(path, 0, t2.rootLength$2$withDrive(path, true)); + parsed.root = t4; + if (t2.needsSeparator$1(t4)) + C.JSArray_methods.$indexSet(parsed.separators, 0, t2.get$separator()); + t4 = parsed.toString$0(0); + } else if (t2.rootLength$1(t5) > 0) { + isAbsoluteAndNotRootRelative = !t2.isRootRelative$1(t5); + t4 = H.S(t5); + } else { + t6 = t5.length; + if (t6 !== 0) { + if (0 >= t6) + return H.ioore(t5, 0); + t6 = t2.containsSeparator$1(t5[0]); + } else + t6 = false; + if (!t6) + if (needsSeparator) + t4 += t2.get$separator(); + t4 += t5; + } + needsSeparator = t2.needsSeparator$1(t5); + } + return t4.charCodeAt(0) == 0 ? t4 : t4; + }, + split$1: function(_, path) { + var parsed = X.ParsedPath_ParsedPath$parse(path, this.style), + t1 = parsed.parts, + t2 = H._arrayInstanceType(t1), + t3 = t2._eval$1("WhereIterable<1>"); + parsed.set$parts(P.List_List$from(new H.WhereIterable(t1, t2._eval$1("bool(1)")._check(new M.Context_split_closure()), t3), true, t3._eval$1("Iterable.E"))); + t1 = parsed.root; + if (t1 != null) + C.JSArray_methods.insert$2(parsed.parts, 0, t1); + return parsed.parts; + }, + normalize$1: function(path) { + var parsed; + if (!this._needsNormalization$1(path)) + return path; + parsed = X.ParsedPath_ParsedPath$parse(path, this.style); + parsed.normalize$0(); + return parsed.toString$0(0); + }, + _needsNormalization$1: function(path) { + var t1, root, i, start, previous, t2, t3, previousPrevious, codeUnit, t4; + path.toString; + t1 = this.style; + root = t1.rootLength$1(path); + if (root !== 0) { + if (t1 === $.$get$Style_windows()) + for (i = 0; i < root; ++i) + if (C.JSString_methods._codeUnitAt$1(path, i) === 47) + return true; + start = root; + previous = 47; + } else { + start = 0; + previous = null; + } + for (t2 = new H.CodeUnits(path)._string, t3 = t2.length, i = start, previousPrevious = null; i < t3; ++i, previousPrevious = previous, previous = codeUnit) { + codeUnit = C.JSString_methods.codeUnitAt$1(t2, i); + if (t1.isSeparator$1(codeUnit)) { + if (t1 === $.$get$Style_windows() && codeUnit === 47) + return true; + if (previous != null && t1.isSeparator$1(previous)) + return true; + if (previous === 46) + t4 = previousPrevious == null || previousPrevious === 46 || t1.isSeparator$1(previousPrevious); + else + t4 = false; + if (t4) + return true; + } + } + if (previous == null) + return true; + if (t1.isSeparator$1(previous)) + return true; + if (previous === 46) + t1 = previousPrevious == null || t1.isSeparator$1(previousPrevious) || previousPrevious === 46; + else + t1 = false; + if (t1) + return true; + return false; + }, + relative$2$from: function(path, from) { + var fromParsed, pathParsed, t2, t3, t4, t5, _this = this, + _s26_ = 'Unable to find a path to "', + t1 = from == null; + if (t1 && _this.style.rootLength$1(path) <= 0) + return _this.normalize$1(path); + if (t1) { + t1 = _this._context$_current; + from = t1 != null ? t1 : D.current(); + } else + from = _this.absolute$1(0, from); + t1 = _this.style; + if (t1.rootLength$1(from) <= 0 && t1.rootLength$1(path) > 0) + return _this.normalize$1(path); + if (t1.rootLength$1(path) <= 0 || t1.isRootRelative$1(path)) + path = _this.absolute$1(0, path); + if (t1.rootLength$1(path) <= 0 && t1.rootLength$1(from) > 0) + throw H.wrapException(X.PathException$(_s26_ + H.S(path) + '" from "' + H.S(from) + '".')); + fromParsed = X.ParsedPath_ParsedPath$parse(from, t1); + fromParsed.normalize$0(); + pathParsed = X.ParsedPath_ParsedPath$parse(path, t1); + pathParsed.normalize$0(); + t2 = fromParsed.parts; + t3 = t2.length; + if (t3 !== 0) { + if (0 >= t3) + return H.ioore(t2, 0); + t2 = J.$eq$(t2[0], "."); + } else + t2 = false; + if (t2) + return pathParsed.toString$0(0); + t2 = fromParsed.root; + t3 = pathParsed.root; + if (t2 != t3) + t2 = t2 == null || t3 == null || !t1.pathsEqual$2(t2, t3); + else + t2 = false; + if (t2) + return pathParsed.toString$0(0); + while (true) { + t2 = fromParsed.parts; + t3 = t2.length; + if (t3 !== 0) { + t4 = pathParsed.parts; + t5 = t4.length; + if (t5 !== 0) { + if (0 >= t3) + return H.ioore(t2, 0); + t2 = t2[0]; + if (0 >= t5) + return H.ioore(t4, 0); + t4 = t1.pathsEqual$2(t2, t4[0]); + t2 = t4; + } else + t2 = false; + } else + t2 = false; + if (!t2) + break; + C.JSArray_methods.removeAt$1(fromParsed.parts, 0); + C.JSArray_methods.removeAt$1(fromParsed.separators, 1); + C.JSArray_methods.removeAt$1(pathParsed.parts, 0); + C.JSArray_methods.removeAt$1(pathParsed.separators, 1); + } + t2 = fromParsed.parts; + t3 = t2.length; + if (t3 !== 0) { + if (0 >= t3) + return H.ioore(t2, 0); + t2 = J.$eq$(t2[0], ".."); + } else + t2 = false; + if (t2) + throw H.wrapException(X.PathException$(_s26_ + H.S(path) + '" from "' + H.S(from) + '".')); + t2 = type$.String; + C.JSArray_methods.insertAll$2(pathParsed.parts, 0, P.List_List$filled(fromParsed.parts.length, "..", t2)); + C.JSArray_methods.$indexSet(pathParsed.separators, 0, ""); + C.JSArray_methods.insertAll$2(pathParsed.separators, 1, P.List_List$filled(fromParsed.parts.length, t1.get$separator(), t2)); + t1 = pathParsed.parts; + t2 = t1.length; + if (t2 === 0) + return "."; + if (t2 > 1 && J.$eq$(C.JSArray_methods.get$last(t1), ".")) { + C.JSArray_methods.removeLast$0(pathParsed.parts); + t1 = pathParsed.separators; + C.JSArray_methods.removeLast$0(t1); + C.JSArray_methods.removeLast$0(t1); + C.JSArray_methods.add$1(t1, ""); + } + pathParsed.root = ""; + pathParsed.removeTrailingSeparators$0(); + return pathParsed.toString$0(0); + }, + relative$1: function(path) { + return this.relative$2$from(path, null); + }, + _isWithinOrEquals$2: function($parent, child) { + var relative, childIsRootRelative, parentIsRootRelative, result, exception, _this = this, + t1 = _this.style, + parentIsAbsolute = t1.rootLength$1(H._checkStringNullable($parent)) > 0, + childIsAbsolute = t1.rootLength$1(H._checkStringNullable(child)) > 0; + if (parentIsAbsolute && !childIsAbsolute) { + child = _this.absolute$1(0, child); + if (t1.isRootRelative$1($parent)) + $parent = _this.absolute$1(0, $parent); + } else if (childIsAbsolute && !parentIsAbsolute) { + $parent = _this.absolute$1(0, $parent); + if (t1.isRootRelative$1(child)) + child = _this.absolute$1(0, child); + } else if (childIsAbsolute && parentIsAbsolute) { + childIsRootRelative = t1.isRootRelative$1(child); + parentIsRootRelative = t1.isRootRelative$1($parent); + if (childIsRootRelative && !parentIsRootRelative) + child = _this.absolute$1(0, child); + else if (parentIsRootRelative && !childIsRootRelative) + $parent = _this.absolute$1(0, $parent); + } + result = _this._isWithinOrEqualsFast$2($parent, child); + if (result !== C._PathRelation_inconclusive) + return result; + relative = null; + try { + relative = _this.relative$2$from(child, $parent); + } catch (exception) { + if (H.unwrapException(exception) instanceof X.PathException) + return C._PathRelation_different; + else + throw exception; + } + if (t1.rootLength$1(H._checkStringNullable(relative)) > 0) + return C._PathRelation_different; + if (J.$eq$(relative, ".")) + return C._PathRelation_equal; + if (J.$eq$(relative, "..")) + return C._PathRelation_different; + return J.get$length$asx(relative) >= 3 && J.startsWith$1$s(relative, "..") && t1.isSeparator$1(J.codeUnitAt$1$s(relative, 2)) ? C._PathRelation_different : C._PathRelation_within; + }, + _isWithinOrEqualsFast$2: function($parent, child) { + var t1, parentRootLength, childRootLength, t2, t3, i, childIndex, parentIndex, lastCodeUnit, lastParentSeparator, parentCodeUnit, childCodeUnit, parentIndex0, t4, direction, _this = this; + if ($parent === ".") + $parent = ""; + t1 = _this.style; + parentRootLength = t1.rootLength$1($parent); + childRootLength = t1.rootLength$1(child); + if (parentRootLength !== childRootLength) + return C._PathRelation_different; + for (t2 = J.getInterceptor$s($parent), t3 = J.getInterceptor$s(child), i = 0; i < parentRootLength; ++i) + if (!t1.codeUnitsEqual$2(t2._codeUnitAt$1($parent, i), t3._codeUnitAt$1(child, i))) + return C._PathRelation_different; + t2 = $parent.length; + childIndex = childRootLength; + parentIndex = parentRootLength; + lastCodeUnit = 47; + lastParentSeparator = null; + while (true) { + if (!(parentIndex < t2 && childIndex < child.length)) + break; + c$0: { + parentCodeUnit = C.JSString_methods.codeUnitAt$1($parent, parentIndex); + childCodeUnit = t3.codeUnitAt$1(child, childIndex); + if (t1.codeUnitsEqual$2(parentCodeUnit, childCodeUnit)) { + if (t1.isSeparator$1(parentCodeUnit)) + lastParentSeparator = parentIndex; + ++parentIndex; + ++childIndex; + lastCodeUnit = parentCodeUnit; + break c$0; + } + if (t1.isSeparator$1(parentCodeUnit) && t1.isSeparator$1(lastCodeUnit)) { + parentIndex0 = parentIndex + 1; + lastParentSeparator = parentIndex; + parentIndex = parentIndex0; + break c$0; + } else if (t1.isSeparator$1(childCodeUnit) && t1.isSeparator$1(lastCodeUnit)) { + ++childIndex; + break c$0; + } + if (parentCodeUnit === 46 && t1.isSeparator$1(lastCodeUnit)) { + ++parentIndex; + if (parentIndex === t2) + break; + parentCodeUnit = C.JSString_methods.codeUnitAt$1($parent, parentIndex); + if (t1.isSeparator$1(parentCodeUnit)) { + parentIndex0 = parentIndex + 1; + lastParentSeparator = parentIndex; + parentIndex = parentIndex0; + break c$0; + } + if (parentCodeUnit === 46) { + ++parentIndex; + if (parentIndex === t2 || t1.isSeparator$1(C.JSString_methods.codeUnitAt$1($parent, parentIndex))) + return C._PathRelation_inconclusive; + } + } + if (childCodeUnit === 46 && t1.isSeparator$1(lastCodeUnit)) { + ++childIndex; + t4 = child.length; + if (childIndex === t4) + break; + childCodeUnit = C.JSString_methods.codeUnitAt$1(child, childIndex); + if (t1.isSeparator$1(childCodeUnit)) { + ++childIndex; + break c$0; + } + if (childCodeUnit === 46) { + ++childIndex; + if (childIndex === t4 || t1.isSeparator$1(C.JSString_methods.codeUnitAt$1(child, childIndex))) + return C._PathRelation_inconclusive; + } + } + if (_this._pathDirection$2(child, childIndex) !== C._PathDirection_988) + return C._PathRelation_inconclusive; + if (_this._pathDirection$2($parent, parentIndex) !== C._PathDirection_988) + return C._PathRelation_inconclusive; + return C._PathRelation_different; + } + } + if (childIndex === child.length) { + if (parentIndex === t2 || t1.isSeparator$1(C.JSString_methods.codeUnitAt$1($parent, parentIndex))) + lastParentSeparator = parentIndex; + else if (lastParentSeparator == null) + lastParentSeparator = Math.max(0, parentRootLength - 1); + direction = _this._pathDirection$2($parent, lastParentSeparator); + if (direction === C._PathDirection_8Gl) + return C._PathRelation_equal; + return direction === C._PathDirection_ZGD ? C._PathRelation_inconclusive : C._PathRelation_different; + } + direction = _this._pathDirection$2(child, childIndex); + if (direction === C._PathDirection_8Gl) + return C._PathRelation_equal; + if (direction === C._PathDirection_ZGD) + return C._PathRelation_inconclusive; + return t1.isSeparator$1(C.JSString_methods.codeUnitAt$1(child, childIndex)) || t1.isSeparator$1(lastCodeUnit) ? C._PathRelation_within : C._PathRelation_different; + }, + _pathDirection$2: function(path, index) { + var t1, t2, i, depth, reachedRoot, i0, t3; + for (t1 = path.length, t2 = this.style, i = index, depth = 0, reachedRoot = false; i < t1;) { + while (true) { + if (!(i < t1 && t2.isSeparator$1(C.JSString_methods.codeUnitAt$1(path, i)))) + break; + ++i; + } + if (i === t1) + break; + i0 = i; + while (true) { + if (!(i0 < t1 && !t2.isSeparator$1(C.JSString_methods.codeUnitAt$1(path, i0)))) + break; + ++i0; + } + t3 = i0 - i; + if (!(t3 === 1 && C.JSString_methods.codeUnitAt$1(path, i) === 46)) + if (t3 === 2 && C.JSString_methods.codeUnitAt$1(path, i) === 46 && C.JSString_methods.codeUnitAt$1(path, i + 1) === 46) { + --depth; + if (depth < 0) + break; + if (depth === 0) + reachedRoot = true; + } else + ++depth; + if (i0 === t1) + break; + i = i0 + 1; + } + if (depth < 0) + return C._PathDirection_ZGD; + if (depth === 0) + return C._PathDirection_8Gl; + if (reachedRoot) + return C._PathDirection_FIw; + return C._PathDirection_988; + }, + toUri$1: function(path) { + var t2, + t1 = this.style; + if (t1.rootLength$1(path) <= 0) + return t1.relativePathToUri$1(path); + else { + t2 = this._context$_current; + return t1.absolutePathToUri$1(this.join$2(0, t2 != null ? t2 : D.current(), path)); + } + }, + prettyUri$1: function(uri) { + var path, rel, _this = this, + typedUri = M._parseUri(uri); + if (typedUri.get$scheme() === "file" && _this.style == $.$get$Style_url()) + return typedUri.toString$0(0); + else if (typedUri.get$scheme() !== "file" && typedUri.get$scheme() !== "" && _this.style != $.$get$Style_url()) + return typedUri.toString$0(0); + path = _this.normalize$1(_this.style.pathFromUri$1(M._parseUri(typedUri))); + rel = _this.relative$1(path); + return _this.split$1(0, rel).length > _this.split$1(0, path).length ? path : rel; + } + }; + M.Context_join_closure.prototype = { + call$1: function(part) { + return H._checkStringNullable(part) != null; + }, + $signature: 4 + }; + M.Context_joinAll_closure.prototype = { + call$1: function(part) { + return H._checkStringNullable(part) !== ""; + }, + $signature: 4 + }; + M.Context_split_closure.prototype = { + call$1: function(part) { + return H._checkStringNullable(part).length !== 0; + }, + $signature: 4 + }; + M._validateArgList_closure.prototype = { + call$1: function(arg) { + H._checkStringNullable(arg); + return arg == null ? "null" : '"' + arg + '"'; + }, + $signature: 7 + }; + M._PathDirection.prototype = { + toString$0: function(_) { + return this.name; + } + }; + M._PathRelation.prototype = { + toString$0: function(_) { + return this.name; + } + }; + B.InternalStyle.prototype = { + getRoot$1: function(path) { + var t1, + $length = this.rootLength$1(path); + if ($length > 0) + return J.substring$2$s(path, 0, $length); + if (this.isRootRelative$1(path)) { + if (0 >= path.length) + return H.ioore(path, 0); + t1 = path[0]; + } else + t1 = null; + return t1; + }, + relativePathToUri$1: function(path) { + var segments = M.Context_Context(this).split$1(0, path); + if (this.isSeparator$1(J.codeUnitAt$1$s(path, path.length - 1))) + C.JSArray_methods.add$1(segments, ""); + return P._Uri__Uri(null, null, segments, null); + }, + codeUnitsEqual$2: function(codeUnit1, codeUnit2) { + return codeUnit1 === codeUnit2; + }, + pathsEqual$2: function(path1, path2) { + return path1 == path2; + } + }; + X.ParsedPath.prototype = { + get$hasTrailingSeparator: function() { + var t1 = this.parts; + if (t1.length !== 0) + t1 = J.$eq$(C.JSArray_methods.get$last(t1), "") || !J.$eq$(C.JSArray_methods.get$last(this.separators), ""); + else + t1 = false; + return t1; + }, + removeTrailingSeparators$0: function() { + var t1, t2, _this = this; + while (true) { + t1 = _this.parts; + if (!(t1.length !== 0 && J.$eq$(C.JSArray_methods.get$last(t1), ""))) + break; + C.JSArray_methods.removeLast$0(_this.parts); + C.JSArray_methods.removeLast$0(_this.separators); + } + t1 = _this.separators; + t2 = t1.length; + if (t2 !== 0) + C.JSArray_methods.$indexSet(t1, t2 - 1, ""); + }, + normalize$0: function() { + var t1, t2, leadingDoubles, _i, part, t3, newSeparators, _this = this, + newParts = H.setRuntimeTypeInfo([], type$.JSArray_String); + for (t1 = _this.parts, t2 = t1.length, leadingDoubles = 0, _i = 0; _i < t1.length; t1.length === t2 || (0, H.throwConcurrentModificationError)(t1), ++_i) { + part = t1[_i]; + t3 = J.getInterceptor$(part); + if (!(t3.$eq(part, ".") || t3.$eq(part, ""))) + if (t3.$eq(part, "..")) { + t3 = newParts.length; + if (t3 !== 0) { + if (0 >= t3) + return H.ioore(newParts, -1); + newParts.pop(); + } else + ++leadingDoubles; + } else + C.JSArray_methods.add$1(newParts, part); + } + if (_this.root == null) + C.JSArray_methods.insertAll$2(newParts, 0, P.List_List$filled(leadingDoubles, "..", type$.String)); + if (newParts.length === 0 && _this.root == null) + C.JSArray_methods.add$1(newParts, "."); + newSeparators = P.List_List$generate(newParts.length, new X.ParsedPath_normalize_closure(_this), true, type$.String); + t1 = _this.root; + C.JSArray_methods.insert$2(newSeparators, 0, t1 != null && newParts.length !== 0 && _this.style.needsSeparator$1(t1) ? _this.style.get$separator() : ""); + _this.set$parts(newParts); + _this.set$separators(newSeparators); + t1 = _this.root; + if (t1 != null && _this.style === $.$get$Style_windows()) { + t1.toString; + _this.root = H.stringReplaceAllUnchecked(t1, "/", "\\"); + } + _this.removeTrailingSeparators$0(); + }, + toString$0: function(_) { + var i, t2, _this = this, + t1 = _this.root; + t1 = t1 != null ? t1 : ""; + for (i = 0; i < _this.parts.length; ++i) { + t2 = _this.separators; + if (i >= t2.length) + return H.ioore(t2, i); + t2 = t1 + H.S(t2[i]); + t1 = _this.parts; + if (i >= t1.length) + return H.ioore(t1, i); + t1 = t2 + H.S(t1[i]); + } + t1 += H.S(C.JSArray_methods.get$last(_this.separators)); + return t1.charCodeAt(0) == 0 ? t1 : t1; + }, + set$parts: function(parts) { + this.parts = type$.List_String._check(parts); + }, + set$separators: function(separators) { + this.separators = type$.List_String._check(separators); + } + }; + X.ParsedPath_normalize_closure.prototype = { + call$1: function(_) { + return this.$this.style.get$separator(); + }, + $signature: 25 + }; + X.PathException.prototype = { + toString$0: function(_) { + return "PathException: " + this.message; + }, + $isException: 1, + get$message: function(receiver) { + return this.message; + } + }; + O.Style.prototype = { + toString$0: function(_) { + return this.get$name(this); + } + }; + E.PosixStyle.prototype = { + containsSeparator$1: function(path) { + return C.JSString_methods.contains$1(path, "/"); + }, + isSeparator$1: function(codeUnit) { + return codeUnit === 47; + }, + needsSeparator$1: function(path) { + var t1 = path.length; + return t1 !== 0 && C.JSString_methods.codeUnitAt$1(path, t1 - 1) !== 47; + }, + rootLength$2$withDrive: function(path, withDrive) { + if (path.length !== 0 && C.JSString_methods._codeUnitAt$1(path, 0) === 47) + return 1; + return 0; + }, + rootLength$1: function(path) { + return this.rootLength$2$withDrive(path, false); + }, + isRootRelative$1: function(path) { + return false; + }, + pathFromUri$1: function(uri) { + var t1; + if (uri.get$scheme() === "" || uri.get$scheme() === "file") { + t1 = uri.get$path(uri); + return P._Uri__uriDecode(t1, 0, t1.length, C.C_Utf8Codec, false); + } + throw H.wrapException(P.ArgumentError$("Uri " + uri.toString$0(0) + " must have scheme 'file:'.")); + }, + absolutePathToUri$1: function(path) { + var parsed = X.ParsedPath_ParsedPath$parse(path, this), + t1 = parsed.parts; + if (t1.length === 0) + C.JSArray_methods.addAll$1(t1, H.setRuntimeTypeInfo(["", ""], type$.JSArray_String)); + else if (parsed.get$hasTrailingSeparator()) + C.JSArray_methods.add$1(parsed.parts, ""); + return P._Uri__Uri(null, null, parsed.parts, "file"); + }, + get$name: function() { + return "posix"; + }, + get$separator: function() { + return "/"; + } + }; + F.UrlStyle.prototype = { + containsSeparator$1: function(path) { + return C.JSString_methods.contains$1(path, "/"); + }, + isSeparator$1: function(codeUnit) { + return codeUnit === 47; + }, + needsSeparator$1: function(path) { + var t1 = path.length; + if (t1 === 0) + return false; + if (C.JSString_methods.codeUnitAt$1(path, t1 - 1) !== 47) + return true; + return C.JSString_methods.endsWith$1(path, "://") && this.rootLength$1(path) === t1; + }, + rootLength$2$withDrive: function(path, withDrive) { + var i, codeUnit, index, t2, + t1 = path.length; + if (t1 === 0) + return 0; + if (C.JSString_methods._codeUnitAt$1(path, 0) === 47) + return 1; + for (i = 0; i < t1; ++i) { + codeUnit = C.JSString_methods._codeUnitAt$1(path, i); + if (codeUnit === 47) + return 0; + if (codeUnit === 58) { + if (i === 0) + return 0; + index = C.JSString_methods.indexOf$2(path, "/", C.JSString_methods.startsWith$2(path, "//", i + 1) ? i + 3 : i); + if (index <= 0) + return t1; + if (!withDrive || t1 < index + 3) + return index; + if (!C.JSString_methods.startsWith$1(path, "file://")) + return index; + if (!B.isDriveLetter(path, index + 1)) + return index; + t2 = index + 3; + return t1 === t2 ? t2 : index + 4; + } + } + return 0; + }, + rootLength$1: function(path) { + return this.rootLength$2$withDrive(path, false); + }, + isRootRelative$1: function(path) { + return path.length !== 0 && C.JSString_methods._codeUnitAt$1(path, 0) === 47; + }, + pathFromUri$1: function(uri) { + return J.toString$0$(uri); + }, + relativePathToUri$1: function(path) { + return P.Uri_parse(path); + }, + absolutePathToUri$1: function(path) { + return P.Uri_parse(path); + }, + get$name: function() { + return "url"; + }, + get$separator: function() { + return "/"; + } + }; + L.WindowsStyle.prototype = { + containsSeparator$1: function(path) { + return C.JSString_methods.contains$1(path, "/"); + }, + isSeparator$1: function(codeUnit) { + return codeUnit === 47 || codeUnit === 92; + }, + needsSeparator$1: function(path) { + var t1 = path.length; + if (t1 === 0) + return false; + t1 = C.JSString_methods.codeUnitAt$1(path, t1 - 1); + return !(t1 === 47 || t1 === 92); + }, + rootLength$2$withDrive: function(path, withDrive) { + var t2, index, + t1 = path.length; + if (t1 === 0) + return 0; + t2 = C.JSString_methods._codeUnitAt$1(path, 0); + if (t2 === 47) + return 1; + if (t2 === 92) { + if (t1 < 2 || C.JSString_methods._codeUnitAt$1(path, 1) !== 92) + return 1; + index = C.JSString_methods.indexOf$2(path, "\\", 2); + if (index > 0) { + index = C.JSString_methods.indexOf$2(path, "\\", index + 1); + if (index > 0) + return index; + } + return t1; + } + if (t1 < 3) + return 0; + if (!B.isAlphabetic(t2)) + return 0; + if (C.JSString_methods._codeUnitAt$1(path, 1) !== 58) + return 0; + t1 = C.JSString_methods._codeUnitAt$1(path, 2); + if (!(t1 === 47 || t1 === 92)) + return 0; + return 3; + }, + rootLength$1: function(path) { + return this.rootLength$2$withDrive(path, false); + }, + isRootRelative$1: function(path) { + return this.rootLength$1(path) === 1; + }, + pathFromUri$1: function(uri) { + var path, t1; + if (uri.get$scheme() !== "" && uri.get$scheme() !== "file") + throw H.wrapException(P.ArgumentError$("Uri " + uri.toString$0(0) + " must have scheme 'file:'.")); + path = uri.get$path(uri); + if (uri.get$host(uri) === "") { + if (path.length >= 3 && C.JSString_methods.startsWith$1(path, "/") && B.isDriveLetter(path, 1)) + path = C.JSString_methods.replaceFirst$2(path, "/", ""); + } else + path = "\\\\" + H.S(uri.get$host(uri)) + path; + t1 = H.stringReplaceAllUnchecked(path, "/", "\\"); + return P._Uri__uriDecode(t1, 0, t1.length, C.C_Utf8Codec, false); + }, + absolutePathToUri$1: function(path) { + var rootParts, t2, + parsed = X.ParsedPath_ParsedPath$parse(path, this), + t1 = parsed.root; + if (J.startsWith$1$s(t1, "\\\\")) { + rootParts = new H.WhereIterable(H.setRuntimeTypeInfo(t1.split("\\"), type$.JSArray_String), type$.bool_Function_String._check(new L.WindowsStyle_absolutePathToUri_closure()), type$.WhereIterable_String); + C.JSArray_methods.insert$2(parsed.parts, 0, rootParts.get$last(rootParts)); + if (parsed.get$hasTrailingSeparator()) + C.JSArray_methods.add$1(parsed.parts, ""); + return P._Uri__Uri(rootParts.get$first(rootParts), null, parsed.parts, "file"); + } else { + if (parsed.parts.length === 0 || parsed.get$hasTrailingSeparator()) + C.JSArray_methods.add$1(parsed.parts, ""); + t1 = parsed.parts; + t2 = parsed.root; + t2.toString; + t2 = H.stringReplaceAllUnchecked(t2, "/", ""); + C.JSArray_methods.insert$2(t1, 0, H.stringReplaceAllUnchecked(t2, "\\", "")); + return P._Uri__Uri(null, null, parsed.parts, "file"); + } + }, + codeUnitsEqual$2: function(codeUnit1, codeUnit2) { + var upperCase1; + if (codeUnit1 === codeUnit2) + return true; + if (codeUnit1 === 47) + return codeUnit2 === 92; + if (codeUnit1 === 92) + return codeUnit2 === 47; + if ((codeUnit1 ^ codeUnit2) !== 32) + return false; + upperCase1 = codeUnit1 | 32; + return upperCase1 >= 97 && upperCase1 <= 122; + }, + pathsEqual$2: function(path1, path2) { + var t1, t2, i; + if (path1 == path2) + return true; + t1 = path1.length; + if (t1 !== path2.length) + return false; + for (t2 = J.getInterceptor$s(path2), i = 0; i < t1; ++i) + if (!this.codeUnitsEqual$2(C.JSString_methods._codeUnitAt$1(path1, i), t2._codeUnitAt$1(path2, i))) + return false; + return true; + }, + get$name: function() { + return "windows"; + }, + get$separator: function() { + return "\\"; + } + }; + L.WindowsStyle_absolutePathToUri_closure.prototype = { + call$1: function(part) { + return H._checkStringNullable(part) !== ""; + }, + $signature: 4 + }; + O.Pool.prototype = { + request$0: function(_) { + var t1, t2, _this = this; + if (_this._pool$_closeMemo._async_memoizer$_completer.future._state !== 0) + throw H.wrapException(P.StateError$("request() may not be called on a closed Pool.")); + t1 = _this._allocatedResources; + if (t1 < _this._maxAllocatedResources) { + _this._allocatedResources = t1 + 1; + t1 = new P._Future($.Zone__current, type$._Future_PoolResource); + t1._asyncComplete$1(new O.PoolResource(_this)); + return t1; + } else { + t1 = _this._onReleaseCallbacks; + if (!t1.get$isEmpty(t1)) + return _this._runOnRelease$1(t1.removeFirst$0()); + else { + t1 = new P._Future($.Zone__current, type$._Future_PoolResource); + t2 = _this._requestedResources; + t2._collection$_add$1(t2.$ti._precomputed1._check(new P._AsyncCompleter(t1, type$._AsyncCompleter_PoolResource))); + _this._resetTimer$0(); + return t1; + } + } + }, + withResource$1$1: function(callback, $T) { + $T._eval$1("0/()")._check(callback); + return this.withResource$body$Pool(callback, $T, $T); + }, + withResource$body$Pool: function(callback, $T, $async$type) { + var $async$goto = 0, + $async$completer = P._makeAsyncAwaitCompleter($async$type), + $async$returnValue, $async$handler = 2, $async$currentError, $async$next = [], $async$self = this, resource, t1; + var $async$withResource$1$1 = P._wrapJsFunctionForAsync(function($async$errorCode, $async$result) { + if ($async$errorCode === 1) { + $async$currentError = $async$result; + $async$goto = $async$handler; + } + while (true) + switch ($async$goto) { + case 0: + // Function start + if ($async$self._pool$_closeMemo._async_memoizer$_completer.future._state !== 0) + throw H.wrapException(P.StateError$("withResource() may not be called on a closed Pool.")); + $async$goto = 3; + return P._asyncAwait($async$self.request$0(0), $async$withResource$1$1); + case 3: + // returning from await. + resource = $async$result; + $async$handler = 4; + $async$goto = 7; + return P._asyncAwait(callback.call$0(), $async$withResource$1$1); + case 7: + // returning from await. + t1 = $async$result; + $async$returnValue = t1; + $async$next = [1]; + // goto finally + $async$goto = 5; + break; + $async$next.push(6); + // goto finally + $async$goto = 5; + break; + case 4: + // uncaught + $async$next = [2]; + case 5: + // finally + $async$handler = 2; + resource.release$0(); + // goto the next finally handler + $async$goto = $async$next.pop(); + break; + case 6: + // after finally + case 1: + // return + return P._asyncReturn($async$returnValue, $async$completer); + case 2: + // rethrow + return P._asyncRethrow($async$currentError, $async$completer); + } + }); + return P._asyncStartSync($async$withResource$1$1, $async$completer); + }, + close$0: function(_) { + return this._pool$_closeMemo.runOnce$1(new O.Pool_close_closure(this)); + }, + _onResourceReleaseAllowed$1: function(onRelease) { + var t1, zone, t2, _this = this; + type$.dynamic_Function._check(onRelease); + _this._resetTimer$0(); + t1 = _this._requestedResources; + if (!t1.get$isEmpty(t1)) + t1.removeFirst$0().complete$1(_this._runOnRelease$1(onRelease)); + else { + t1 = type$.dynamic; + if (_this._pool$_closeMemo._async_memoizer$_completer.future._state !== 0) { + _this._closeGroup.add$1(0, P.Future_Future$sync(onRelease, t1)); + if (--_this._allocatedResources === 0) + _this._closeGroup.close$0(0); + } else { + zone = $.Zone__current; + t2 = _this._onReleaseCallbacks; + t2._collection$_add$1(t2.$ti._precomputed1._check(new O.Pool__onResourceReleaseAllowed_closure(zone, zone.registerCallback$1$1(onRelease, t1)))); + } + } + }, + _runOnRelease$1: function(onRelease) { + var t1, t2; + P.Future_Future$sync(type$.dynamic_Function._check(onRelease), type$.dynamic).then$1$1(new O.Pool__runOnRelease_closure(this), type$.Null).catchError$1(new O.Pool__runOnRelease_closure0(this)); + t1 = new P._Future($.Zone__current, type$._Future_PoolResource); + t2 = this._onReleaseCompleters; + t2._collection$_add$1(t2.$ti._precomputed1._check(new P._SyncCompleter(t1, type$._SyncCompleter_PoolResource))); + return t1; + }, + _resetTimer$0: function() { + var t2, + t1 = this._timer; + if (t1 == null) + return; + t2 = this._requestedResources; + if (t2._head === t2._tail) + t1._restartable_timer$_timer.cancel$0(); + else { + t1._restartable_timer$_timer.cancel$0(); + t1._restartable_timer$_timer = P.Timer_Timer(t1._restartable_timer$_duration, t1._callback); + } + } + }; + O.Pool_close_closure.prototype = { + call$0: function() { + var t3, t4, callback, + t1 = this.$this, + t2 = t1._closeGroup; + if (t2 != null) + return t2._future_group$_completer.future; + t1._resetTimer$0(); + t1._closeGroup = new F.FutureGroup(new P._AsyncCompleter(new P._Future($.Zone__current, type$._Future_List_dynamic), type$._AsyncCompleter_List_dynamic), H.setRuntimeTypeInfo([], type$.JSArray_dynamic), type$.FutureGroup_dynamic); + for (t2 = t1._onReleaseCallbacks, t3 = P._ListQueueIterator$(t2, t2.$ti._precomputed1), t4 = type$.dynamic; t3.moveNext$0();) { + callback = t3._collection$_current; + t1._closeGroup.add$1(0, P.Future_Future$sync(callback, t4)); + } + t1._allocatedResources = t1._allocatedResources - t2.get$length(t2); + t2.clear$0(0); + if (t1._allocatedResources === 0) + t1._closeGroup.close$0(0); + return t1._closeGroup._future_group$_completer.future; + }, + $signature: 50 + }; + O.Pool__onResourceReleaseAllowed_closure.prototype = { + call$0: function() { + return this.zone.run$1$1(this.registered, type$.void); + }, + $signature: 1 + }; + O.Pool__runOnRelease_closure.prototype = { + call$1: function(value) { + var t1 = this.$this; + t1._onReleaseCompleters.removeFirst$0().complete$1(new O.PoolResource(t1)); + }, + $signature: 3 + }; + O.Pool__runOnRelease_closure0.prototype = { + call$2: function(error, stackTrace) { + type$.StackTrace._check(stackTrace); + this.$this._onReleaseCompleters.removeFirst$0().completeError$2(error, stackTrace); + }, + $signature: 5 + }; + O.PoolResource.prototype = { + release$0: function() { + var t1, t2; + if (this._released) + throw H.wrapException(P.StateError$("A PoolResource may only be released once.")); + this._released = true; + t1 = this._pool; + t1._resetTimer$0(); + t2 = t1._requestedResources; + if (!t2.get$isEmpty(t2)) + t2.removeFirst$0().complete$1(new O.PoolResource(t1)); + else { + t2 = --t1._allocatedResources; + if (t1._pool$_closeMemo._async_memoizer$_completer.future._state !== 0 && t2 === 0) + t1._closeGroup.close$0(0); + } + } + }; + O.mapStackTrace_closure.prototype = { + call$1: function(trace) { + var _this = this; + return Y.Trace_Trace$from(O.mapStackTrace(_this.sourceMap, type$.Trace._check(trace), _this.minified, _this._box_0.packageResolver, _this.sdkRoot)); + }, + $signature: 45 + }; + O.mapStackTrace_closure0.prototype = { + call$1: function(frame) { + var column, t1, t2, span, sourceUrl, t3, packageUrl, t4, _this = this; + type$.Frame._check(frame); + if (frame.get$line() == null) + return null; + column = frame.get$column() == null ? 0 : frame.get$column(); + t1 = frame.get$line(); + if (typeof t1 !== "number") + return t1.$sub(); + if (typeof column !== "number") + return column.$sub(); + t2 = frame.get$uri(); + t2 = t2 == null ? null : t2.toString$0(0); + span = _this.sourceMap.spanFor$3$uri(t1 - 1, column - 1, t2); + if (span == null) + return null; + sourceUrl = J.toString$0$(span.get$sourceUrl()); + if (_this.sdkRoot != null && $.$get$url()._isWithinOrEquals$2(_this.sdkLib, sourceUrl) === C._PathRelation_within) + sourceUrl = C.JSString_methods.$add("dart:", $.$get$url().relative$2$from(sourceUrl, _this.sdkLib)); + else { + t1 = _this._box_0; + t2 = t1.packageResolver; + if (t2 != null) + if (t2.get$packageRoot() != null && $.$get$url()._isWithinOrEquals$2(J.toString$0$(t1.packageResolver.get$packageRoot()), sourceUrl) === C._PathRelation_within) + sourceUrl = C.JSString_methods.$add("package:", $.$get$url().relative$2$from(sourceUrl, J.toString$0$(t1.packageResolver.get$packageRoot()))); + else if (t1.packageResolver.get$packageConfigMap() != null) + for (t2 = t1.packageResolver.get$packageConfigMap()._map.get$keys(), t2 = t2.get$iterator(t2); t2.moveNext$0();) { + t3 = t2.get$current(); + packageUrl = J.toString$0$(t1.packageResolver.get$packageConfigMap()._map.$index(0, t3)); + t4 = $.$get$url(); + if (t4._isWithinOrEquals$2(packageUrl, sourceUrl) !== C._PathRelation_within) + continue; + sourceUrl = C.JSString_methods.$add("package:" + H.S(t3) + "/", t4.relative$2$from(sourceUrl, packageUrl)); + break; + } + } + t1 = P.Uri_parse(sourceUrl); + t2 = span.get$start().get$line(); + if (typeof t2 !== "number") + return t2.$add(); + t3 = span.get$start().get$column(); + if (_this.minified) + t4 = span.get$isIdentifier() ? span.get$text() : frame.get$member(); + else + t4 = O._prettifyMember(frame.get$member()); + return new A.Frame(t1, t2 + 1, t3 + 1, t4); + }, + $signature: 46 + }; + O.mapStackTrace_closure1.prototype = { + call$1: function(frame) { + return type$.Frame._check(frame) != null; + }, + $signature: 21 + }; + O._prettifyMember_closure.prototype = { + call$1: function(match) { + return C.JSString_methods.$mul(".<fn>", match.$index(0, 1).length); + }, + $signature: 24 + }; + O._prettifyMember_closure0.prototype = { + call$1: function(match) { + return J.$add$ansx(match.$index(0, 1), "."); + }, + $signature: 24 + }; + T.Mapping.prototype = {}; + T.MultiSectionMapping.prototype = { + MultiSectionMapping$fromJson$3$mapUrl: function(sections, otherMaps, mapUrl) { + var t1, t2, t3, t4, t5, section, t6, line, column, url, map, _s6_ = "offset", _null = null; + for (t1 = J.get$iterator$ax(sections), t2 = this._maps, t3 = type$.Map_dynamic_dynamic, t4 = this._lineStart, t5 = this._columnStart; t1.moveNext$0();) { + section = t1.get$current(); + t6 = J.getInterceptor$asx(section); + if (t6.$index(section, _s6_) == null) + throw H.wrapException(P.FormatException$("section missing offset", _null, _null)); + line = J.$index$asx(t6.$index(section, _s6_), "line"); + if (line == null) + throw H.wrapException(P.FormatException$("offset missing line", _null, _null)); + column = J.$index$asx(t6.$index(section, _s6_), "column"); + if (column == null) + throw H.wrapException(P.FormatException$("offset missing column", _null, _null)); + C.JSArray_methods.add$1(t4, H._checkIntNullable(line)); + C.JSArray_methods.add$1(t5, H._checkIntNullable(column)); + url = t6.$index(section, "url"); + map = t6.$index(section, "map"); + t6 = url != null; + if (t6 && map != null) + throw H.wrapException(P.FormatException$("section can't use both url and map entries", _null, _null)); + else if (t6) { + t6 = P.FormatException$("section contains refers to " + H.S(url) + ', but no map was given for it. Make sure a map is passed in "otherMaps"', _null, _null); + throw H.wrapException(t6); + } else if (map != null) + C.JSArray_methods.add$1(t2, T.parseJson(t3._check(map), mapUrl, otherMaps)); + else + throw H.wrapException(P.FormatException$("section missing url or map", _null, _null)); + } + if (t4.length === 0) + throw H.wrapException(P.FormatException$("expected at least one section", _null, _null)); + }, + _indexFor$2: function(line, column) { + var t1, t2, t3, t4, i, t5; + for (t1 = this._lineStart, t2 = t1.length, t3 = this._columnStart, t4 = t3.length, i = 0; i < t2; ++i) { + t5 = t1[i]; + if (line < t5) + return i - 1; + if (line === t5) { + if (i >= t4) + return H.ioore(t3, i); + t5 = column < t3[i]; + } else + t5 = false; + if (t5) + return i - 1; + } + return t2 - 1; + }, + spanFor$4$files$uri: function(line, column, files, uri) { + var index, t1, t2, t3, _this = this; + type$.Map_String_SourceFile._check(files); + index = _this._indexFor$2(line, column); + t1 = _this._maps; + if (index < 0 || index >= t1.length) + return H.ioore(t1, index); + t1 = t1[index]; + t2 = _this._lineStart; + if (index >= t2.length) + return H.ioore(t2, index); + t2 = t2[index]; + t3 = _this._columnStart; + if (index >= t3.length) + return H.ioore(t3, index); + return t1.spanFor$3$files(line - t2, column - t3[index], files); + }, + spanFor$3$uri: function(line, column, uri) { + return this.spanFor$4$files$uri(line, column, null, uri); + }, + spanFor$3$files: function(line, column, files) { + return this.spanFor$4$files$uri(line, column, files, null); + }, + toString$0: function(_) { + var t2, t3, t4, i, _this = this, + t1 = H.getRuntimeType(_this).toString$0(0) + " : ["; + for (t2 = _this._lineStart, t3 = _this._columnStart, t4 = _this._maps, i = 0; i < t2.length; ++i) { + t1 = t1 + "(" + t2[i] + ","; + if (i >= t3.length) + return H.ioore(t3, i); + t1 = t1 + t3[i] + ":"; + if (i >= t4.length) + return H.ioore(t4, i); + t1 = t1 + t4[i].toString$0(0) + ")"; + } + t1 += "]"; + return t1.charCodeAt(0) == 0 ? t1 : t1; + } + }; + T.MappingBundle.prototype = { + MappingBundle$fromJson$2$mapUrl: function(json, mapUrl) { + var t1, t2, t3, t4, t5; + for (t1 = J.get$iterator$ax(json), t2 = type$.Map_dynamic_dynamic, t3 = type$.SingleMapping, t4 = this._mappings; t1.moveNext$0();) { + t5 = t3._as(T.parseJson(t2._check(t1.get$current()), mapUrl, null)); + t4.$indexSet(0, t5.targetUrl, t5); + } + }, + toString$0: function(_) { + var t1, t2; + for (t1 = this._mappings.get$values(), t1 = t1.get$iterator(t1), t2 = ""; t1.moveNext$0();) + t2 += J.toString$0$(t1.get$current()); + return t2.charCodeAt(0) == 0 ? t2 : t2; + }, + spanFor$4$files$uri: function(line, column, files, uri) { + var separatorCodeUnits, t1, t2, onBoundary, i, candidate, $location; + type$.Map_String_SourceFile._check(files); + if (uri == null) + throw H.wrapException(P.ArgumentError$notNull("uri")); + separatorCodeUnits = H.setRuntimeTypeInfo([47, 58], type$.JSArray_int); + for (t1 = uri.length, t2 = this._mappings, onBoundary = true, i = 0; i < t1; ++i) { + if (onBoundary) { + candidate = C.JSString_methods.substring$1(uri, i); + if (t2.containsKey$1(candidate)) + return t2.$index(0, candidate).spanFor$4$files$uri(line, column, files, candidate); + } + onBoundary = C.JSArray_methods.contains$1(separatorCodeUnits, C.JSString_methods._codeUnitAt$1(uri, i)); + } + $location = V.SourceLocation$(line * 1000000 + column, column, line, P.Uri_parse(uri)); + t1 = new G.SourceMapSpan(false, $location, $location, ""); + t1.SourceSpanBase$3($location, $location, ""); + return t1; + }, + spanFor$3$uri: function(line, column, uri) { + return this.spanFor$4$files$uri(line, column, null, uri); + } + }; + T.SingleMapping.prototype = { + SingleMapping$fromJson$2$mapUrl: function(map, mapUrl) { + var t5, source, t6, t7, tokenizer, entries, line, column, srcUrlId, srcLine, srcColumn, srcNameId, _this = this, + _s14_ = "sourcesContent", + _null = null, + sourcesContent = map.$index(0, _s14_) == null ? C.List_empty0 : P.List_List$from(type$.Iterable_dynamic._check(map.$index(0, _s14_)), true, type$.String), + t1 = type$.Uri, + t2 = _this.files, + t3 = _this.urls, + t4 = type$.JSArray_int, + i = 0; + while (true) { + t5 = t3.length; + if (!(i < t5 && i < sourcesContent.length)) + break; + c$0: { + if (i >= sourcesContent.length) + return H.ioore(sourcesContent, i); + source = sourcesContent[i]; + if (source == null) + break c$0; + H._checkStringNullable(source); + if (i >= t5) + return H.ioore(t3, i); + t5 = t3[i]; + t6 = new H.CodeUnits(source); + t7 = H.setRuntimeTypeInfo([0], t4); + t7 = new Y.SourceFile(t1._check(typeof t5 == "string" ? P.Uri_parse(t5) : t5), t7, new Uint32Array(H._ensureNativeList(t6.toList$0(t6)))); + t7.SourceFile$decoded$2$url(t6, t5); + C.JSArray_methods.$indexSet(t2, i, t7); + } + ++i; + } + t1 = H._checkStringNullable(map.$index(0, "mappings")); + t2 = t1.length; + tokenizer = new T._MappingTokenizer(t1, t2); + t1 = type$.JSArray_TargetEntry; + entries = H.setRuntimeTypeInfo([], t1); + t4 = _this.names; + t5 = t2 - 1; + t2 = t2 > 0; + t6 = _this.lines; + line = 0; + column = 0; + srcUrlId = 0; + srcLine = 0; + srcColumn = 0; + srcNameId = 0; + while (true) { + if (!(tokenizer.index < t5 && t2)) + break; + c$1: { + if (tokenizer.get$nextKind().isNewLine) { + if (entries.length !== 0) { + C.JSArray_methods.add$1(t6, new T.TargetLineEntry(line, entries)); + entries = H.setRuntimeTypeInfo([], t1); + } + ++line; + ++tokenizer.index; + column = 0; + break c$1; + } + if (tokenizer.get$nextKind().isNewSegment) + throw H.wrapException(_this._segmentError$2(0, line)); + column += L.decodeVlq(tokenizer); + t7 = tokenizer.get$nextKind(); + if (!(!t7.isNewLine && !t7.isNewSegment && !t7.isEof)) + C.JSArray_methods.add$1(entries, new T.TargetEntry(column, _null, _null, _null, _null)); + else { + srcUrlId += L.decodeVlq(tokenizer); + if (srcUrlId >= t3.length) + throw H.wrapException(P.StateError$("Invalid source url id. " + H.S(_this.targetUrl) + ", " + line + ", " + srcUrlId)); + t7 = tokenizer.get$nextKind(); + if (!(!t7.isNewLine && !t7.isNewSegment && !t7.isEof)) + throw H.wrapException(_this._segmentError$2(2, line)); + srcLine += L.decodeVlq(tokenizer); + t7 = tokenizer.get$nextKind(); + if (!(!t7.isNewLine && !t7.isNewSegment && !t7.isEof)) + throw H.wrapException(_this._segmentError$2(3, line)); + srcColumn += L.decodeVlq(tokenizer); + t7 = tokenizer.get$nextKind(); + if (!(!t7.isNewLine && !t7.isNewSegment && !t7.isEof)) + C.JSArray_methods.add$1(entries, new T.TargetEntry(column, srcUrlId, srcLine, srcColumn, _null)); + else { + srcNameId += L.decodeVlq(tokenizer); + if (srcNameId >= t4.length) + throw H.wrapException(P.StateError$("Invalid name id: " + H.S(_this.targetUrl) + ", " + line + ", " + srcNameId)); + C.JSArray_methods.add$1(entries, new T.TargetEntry(column, srcUrlId, srcLine, srcColumn, srcNameId)); + } + } + if (tokenizer.get$nextKind().isNewSegment) + ++tokenizer.index; + } + } + if (entries.length !== 0) + C.JSArray_methods.add$1(t6, new T.TargetLineEntry(line, entries)); + map.forEach$1(0, new T.SingleMapping$fromJson_closure(_this)); + }, + _segmentError$2: function(seen, line) { + return new P.StateError("Invalid entry in sourcemap, expected 1, 4, or 5 values, but got " + seen + ".\ntargeturl: " + H.S(this.targetUrl) + ", line: " + line); + }, + _findLine$1: function(line) { + var t2, + t1 = this.lines, + index = O.binarySearch(t1, new T.SingleMapping__findLine_closure(line)); + if (index <= 0) + t1 = null; + else { + t2 = index - 1; + if (t2 >= t1.length) + return H.ioore(t1, t2); + t2 = t1[t2]; + t1 = t2; + } + return t1; + }, + _findColumn$3: function(line, column, lineEntry) { + var entries, index, t1; + if (lineEntry == null || lineEntry.entries.length === 0) + return null; + if (lineEntry.line !== line) + return C.JSArray_methods.get$last(lineEntry.entries); + entries = lineEntry.entries; + index = O.binarySearch(entries, new T.SingleMapping__findColumn_closure(column)); + if (index <= 0) + t1 = null; + else { + t1 = index - 1; + if (t1 >= entries.length) + return H.ioore(entries, t1); + t1 = entries[t1]; + } + return t1; + }, + spanFor$4$files$uri: function(line, column, files, uri) { + var entry, url, t1, t2, start, t3, _this = this; + type$.Map_String_SourceFile._check(files); + entry = _this._findColumn$3(line, column, _this._findLine$1(line)); + if (entry == null || entry.sourceUrlId == null) + return null; + url = C.JSArray_methods.$index(_this.urls, entry.sourceUrlId); + t1 = _this.sourceRoot; + if (t1 != null) + url = t1 + H.S(url); + t1 = _this._parser$_mapUrl; + t1 = t1 == null ? url : t1.resolve$1(url); + t2 = entry.sourceLine; + start = V.SourceLocation$(0, entry.sourceColumn, t2, t1); + t1 = entry.sourceNameId; + if (t1 != null) { + t2 = _this.names; + if (t1 >>> 0 !== t1 || t1 >= t2.length) + return H.ioore(t2, t1); + t1 = t2[t1]; + t2 = t1.length; + t2 = V.SourceLocation$(start.offset + t2, start.column + t2, start.line, start.sourceUrl); + t3 = new G.SourceMapSpan(true, start, t2, t1); + t3.SourceSpanBase$3(start, t2, t1); + return t3; + } else { + t1 = new G.SourceMapSpan(false, start, start, ""); + t1.SourceSpanBase$3(start, start, ""); + return t1; + } + }, + spanFor$3$uri: function(line, column, uri) { + return this.spanFor$4$files$uri(line, column, null, uri); + }, + spanFor$3$files: function(line, column, files) { + return this.spanFor$4$files$uri(line, column, files, null); + }, + toString$0: function(_) { + var _this = this, + t1 = H.getRuntimeType(_this).toString$0(0); + t1 + " : ["; + t1 = t1 + " : [targetUrl: " + H.S(_this.targetUrl) + ", sourceRoot: " + H.S(_this.sourceRoot) + ", urls: " + H.S(_this.urls) + ", names: " + H.S(_this.names) + ", lines: " + H.S(_this.lines) + "]"; + return t1.charCodeAt(0) == 0 ? t1 : t1; + } + }; + T.SingleMapping$fromJson_closure.prototype = { + call$2: function($name, value) { + if (J.startsWith$1$s($name, "x_")) + this.$this.extensions.$indexSet(0, H._checkStringNullable($name), value); + }, + $signature: 6 + }; + T.SingleMapping__findLine_closure.prototype = { + call$1: function(e) { + return e.get$line() > this.line; + }, + $signature: 9 + }; + T.SingleMapping__findColumn_closure.prototype = { + call$1: function(e) { + return e.get$column() > this.column; + }, + $signature: 9 + }; + T.TargetLineEntry.prototype = { + toString$0: function(_) { + return H.getRuntimeType(this).toString$0(0) + ": " + this.line + " " + H.S(this.entries); + }, + get$line: function() { + return this.line; + } + }; + T.TargetEntry.prototype = { + toString$0: function(_) { + var _this = this; + return H.getRuntimeType(_this).toString$0(0) + ": (" + _this.column + ", " + H.S(_this.sourceUrlId) + ", " + H.S(_this.sourceLine) + ", " + H.S(_this.sourceColumn) + ", " + H.S(_this.sourceNameId) + ")"; + }, + get$column: function() { + return this.column; + } + }; + T._MappingTokenizer.prototype = { + moveNext$0: function() { + return ++this.index < this._parser$_length; + }, + get$current: function() { + var t2, + t1 = this.index; + if (t1 >= 0 && t1 < this._parser$_length) { + t2 = this._internal; + if (t1 < 0 || t1 >= t2.length) + return H.ioore(t2, t1); + t1 = t2[t1]; + } else + t1 = null; + return t1; + }, + get$hasTokens: function() { + var t1 = this._parser$_length; + return this.index < t1 - 1 && t1 > 0; + }, + get$nextKind: function() { + var t1, t2, next; + if (!this.get$hasTokens()) + return C._TokenKind_false_false_true; + t1 = this._internal; + t2 = this.index + 1; + if (t2 < 0 || t2 >= t1.length) + return H.ioore(t1, t2); + next = t1[t2]; + if (next === ";") + return C._TokenKind_true_false_false; + if (next === ",") + return C._TokenKind_false_true_false; + return C._TokenKind_false_false_false; + }, + toString$0: function(_) { + var t1, i, t2, t3, _this = this; + for (t1 = _this._internal, i = 0, t2 = ""; i < _this.index; ++i) { + if (i >= t1.length) + return H.ioore(t1, i); + t2 += t1[i]; + } + t2 += "\x1b[31m"; + t2 = t2 + H.S(_this.get$current() == null ? "" : _this.get$current()) + "\x1b[0m"; + for (i = _this.index + 1, t3 = t1.length; i < t3; ++i) { + if (i < 0) + return H.ioore(t1, i); + t2 += t1[i]; + } + t1 = t2 + (" (" + _this.index + ")"); + return t1.charCodeAt(0) == 0 ? t1 : t1; + }, + $isIterator: 1 + }; + T._TokenKind.prototype = {}; + G.SourceMapSpan.prototype = { + get$isIdentifier: function() { + return this.isIdentifier; + } + }; + L.closure.prototype = { + call$0: function() { + var i, + map = P.LinkedHashMap_LinkedHashMap$_empty(type$.String, type$.int); + for (i = 0; i < 64; ++i) + map.$indexSet(0, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[i], i); + return map; + }, + $signature: 93 + }; + Y.SourceFile.prototype = { + get$length: function(_) { + return this._decodedChars.length; + }, + get$lines: function() { + return this._lineStarts.length; + }, + SourceFile$decoded$2$url: function(decodedChars, url) { + var t1, t2, t3, i, c, j, t4; + for (t1 = this._decodedChars, t2 = t1.length, t3 = this._lineStarts, i = 0; i < t2; ++i) { + c = t1[i]; + if (c === 13) { + j = i + 1; + if (j < t2) { + if (j >= t2) + return H.ioore(t1, j); + t4 = t1[j] !== 10; + } else + t4 = true; + if (t4) + c = 10; + } + if (c === 10) + C.JSArray_methods.add$1(t3, i + 1); + } + }, + span$2: function(start, end) { + return Y._FileSpan$(this, start, end); + }, + getLine$1: function(offset) { + var t1, _this = this; + if (offset < 0) + throw H.wrapException(P.RangeError$("Offset may not be negative, was " + offset + ".")); + else if (offset > _this._decodedChars.length) + throw H.wrapException(P.RangeError$("Offset " + offset + " must not be greater than the number of characters in the file, " + _this.get$length(_this) + ".")); + t1 = _this._lineStarts; + if (offset < C.JSArray_methods.get$first(t1)) + return -1; + if (offset >= C.JSArray_methods.get$last(t1)) + return t1.length - 1; + if (_this._isNearCachedLine$1(offset)) + return _this._cachedLine; + return _this._cachedLine = _this._binarySearch$1(offset) - 1; + }, + _isNearCachedLine$1: function(offset) { + var t2, t3, t4, _this = this, + t1 = _this._cachedLine; + if (t1 == null) + return false; + t2 = _this._lineStarts; + if (t1 >>> 0 !== t1 || t1 >= t2.length) + return H.ioore(t2, t1); + if (offset < t2[t1]) + return false; + t1 = _this._cachedLine; + t3 = t2.length; + if (typeof t1 !== "number") + return t1.$ge(); + if (t1 < t3 - 1) { + t4 = t1 + 1; + if (t4 < 0 || t4 >= t3) + return H.ioore(t2, t4); + t4 = offset < t2[t4]; + } else + t4 = true; + if (t4) + return true; + if (t1 < t3 - 2) { + t4 = t1 + 2; + if (t4 < 0 || t4 >= t3) + return H.ioore(t2, t4); + t4 = offset < t2[t4]; + t2 = t4; + } else + t2 = true; + if (t2) { + _this._cachedLine = t1 + 1; + return true; + } + return false; + }, + _binarySearch$1: function(offset) { + var min, half, + t1 = this._lineStarts, + t2 = t1.length, + max = t2 - 1; + for (min = 0; min < max;) { + half = min + C.JSInt_methods._tdivFast$1(max - min, 2); + if (half < 0 || half >= t2) + return H.ioore(t1, half); + if (t1[half] > offset) + max = half; + else + min = half + 1; + } + return max; + }, + getColumn$1: function(offset) { + var line, lineStart, _this = this; + if (offset < 0) + throw H.wrapException(P.RangeError$("Offset may not be negative, was " + offset + ".")); + else if (offset > _this._decodedChars.length) + throw H.wrapException(P.RangeError$("Offset " + offset + " must be not be greater than the number of characters in the file, " + _this.get$length(_this) + ".")); + line = _this.getLine$1(offset); + lineStart = C.JSArray_methods.$index(_this._lineStarts, line); + if (lineStart > offset) + throw H.wrapException(P.RangeError$("Line " + H.S(line) + " comes after offset " + offset + ".")); + return offset - lineStart; + }, + getOffset$2: function(line, column) { + var t1, t2, result, t3; + if (typeof line !== "number") + return line.$lt(); + if (line < 0) + throw H.wrapException(P.RangeError$("Line may not be negative, was " + line + ".")); + else { + t1 = this._lineStarts; + t2 = t1.length; + if (line >= t2) + throw H.wrapException(P.RangeError$("Line " + line + " must be less than the number of lines in the file, " + this.get$lines() + ".")); + } + result = t1[line]; + if (result <= this._decodedChars.length) { + t3 = line + 1; + t1 = t3 < t2 && result >= t1[t3]; + } else + t1 = true; + if (t1) + throw H.wrapException(P.RangeError$("Line " + line + " doesn't have 0 columns.")); + return result; + }, + getOffset$1: function(line) { + return this.getOffset$2(line, null); + } + }; + Y.FileLocation.prototype = { + get$sourceUrl: function() { + return this.file.url; + }, + get$line: function() { + return this.file.getLine$1(this.offset); + }, + get$column: function() { + return this.file.getColumn$1(this.offset); + }, + get$offset: function(receiver) { + return this.offset; + } + }; + Y._FileSpan.prototype = { + get$sourceUrl: function() { + return this.file.url; + }, + get$length: function(_) { + return this._file$_end - this._file$_start; + }, + get$start: function() { + return Y.FileLocation$_(this.file, this._file$_start); + }, + get$end: function() { + return Y.FileLocation$_(this.file, this._file$_end); + }, + get$text: function() { + return P.String_String$fromCharCodes(C.NativeUint32List_methods.sublist$2(this.file._decodedChars, this._file$_start, this._file$_end), 0, null); + }, + get$context: function() { + var t2, _this = this, + t1 = _this.file, + endOffset = _this._file$_end, + endLine = t1.getLine$1(endOffset); + if (t1.getColumn$1(endOffset) === 0 && endLine !== 0) { + if (endOffset - _this._file$_start === 0) { + if (endLine === t1._lineStarts.length - 1) + t1 = ""; + else { + t2 = t1.getOffset$1(endLine); + if (typeof endLine !== "number") + return endLine.$add(); + t1 = P.String_String$fromCharCodes(C.NativeUint32List_methods.sublist$2(t1._decodedChars, t2, t1.getOffset$1(endLine + 1)), 0, null); + } + return t1; + } + } else if (endLine === t1._lineStarts.length - 1) + endOffset = t1._decodedChars.length; + else { + if (typeof endLine !== "number") + return endLine.$add(); + endOffset = t1.getOffset$1(endLine + 1); + } + return P.String_String$fromCharCodes(C.NativeUint32List_methods.sublist$2(t1._decodedChars, t1.getOffset$1(t1.getLine$1(_this._file$_start)), endOffset), 0, null); + }, + $eq: function(_, other) { + var _this = this; + if (other == null) + return false; + if (!type$.FileSpan._is(other)) + return _this.super$SourceSpanMixin$$eq(0, other); + if (!(other instanceof Y._FileSpan)) + return _this.super$SourceSpanMixin$$eq(0, other) && J.$eq$(_this.file.url, other.get$sourceUrl()); + return _this._file$_start === other._file$_start && _this._file$_end === other._file$_end && J.$eq$(_this.file.url, other.file.url); + }, + get$hashCode: function(_) { + return Y.SourceSpanMixin.prototype.get$hashCode.call(this, this); + }, + expand$1: function(_, other) { + var start, _this = this, + t1 = _this.file; + if (!J.$eq$(t1.url, other.file.url)) + throw H.wrapException(P.ArgumentError$('Source URLs "' + H.S(_this.get$sourceUrl()) + '" and "' + H.S(other.get$sourceUrl()) + "\" don't match.")); + start = Math.min(_this._file$_start, other._file$_start); + return Y._FileSpan$(t1, start, Math.max(_this._file$_end, other._file$_end)); + }, + $isFileSpan: 1, + $isSourceSpanWithContext: 1 + }; + U.Highlighter.prototype = { + highlight$0: function() { + var t1, t2, lineStart, context, lines, t3, t4, lineNumber, _i, line, lastLineIndex, _this = this; + _this._writeSidebar$1$end($._glyphs.get$downEnd()); + t1 = _this._highlighter$_buffer; + t1._contents += "\n"; + t2 = _this._span; + lineStart = B.findLineStart(t2.get$context(), t2.get$text(), t2.get$start().get$column()); + H.assertHelper(lineStart != null); + context = t2.get$context(); + if (typeof lineStart !== "number") + return lineStart.$gt(); + if (lineStart > 0) { + lines = C.JSString_methods.substring$2(context, 0, lineStart - 1).split("\n"); + t3 = t2.get$start().get$line(); + t4 = lines.length; + if (typeof t3 !== "number") + return t3.$sub(); + lineNumber = t3 - t4; + for (t3 = _this._multiline, _i = 0; _i < t4; ++_i) { + line = lines[_i]; + _this._writeSidebar$1$line(lineNumber); + t1._contents += C.JSString_methods.$mul(" ", t3 ? 3 : 1); + _this._writeText$1(line); + t1._contents += "\n"; + ++lineNumber; + } + context = C.JSString_methods.substring$1(context, lineStart); + } + lines = H.setRuntimeTypeInfo(context.split("\n"), type$.JSArray_String); + t3 = t2.get$end().get$line(); + t2 = t2.get$start().get$line(); + if (typeof t3 !== "number") + return t3.$sub(); + if (typeof t2 !== "number") + return H.iae(t2); + lastLineIndex = t3 - t2; + t2 = C.JSArray_methods.get$last(lines); + t2.toString; + if (J.get$length$asx(t2) === 0 && lines.length > lastLineIndex + 1) { + if (0 >= lines.length) + return H.ioore(lines, -1); + lines.pop(); + } + _this._writeFirstLine$1(C.JSArray_methods.get$first(lines)); + if (_this._multiline) { + _this._writeIntermediateLines$1(H.SubListIterable$(lines, 1, null, type$.String).take$1(0, lastLineIndex - 1)); + if (lastLineIndex < 0 || lastLineIndex >= lines.length) + return H.ioore(lines, lastLineIndex); + _this._writeLastLine$1(lines[lastLineIndex]); + } + _this._writeTrailingLines$1(H.SubListIterable$(lines, lastLineIndex + 1, null, type$.String)); + _this._writeSidebar$1$end($._glyphs.get$upEnd()); + t1 = t1._contents; + return t1.charCodeAt(0) == 0 ? t1 : t1; + }, + _writeFirstLine$1: function(line) { + var t3, t4, startColumn, endColumn, textBefore, textInside, tabsBefore, tabsInside, _this = this, t1 = {}, + t2 = _this._span; + _this._writeSidebar$1$line(t2.get$start().get$line()); + t3 = t2.get$start().get$column(); + t4 = line.length; + startColumn = t1.startColumn = Math.min(t3, t4); + t3 = t2.get$end(); + t3 = t3.get$offset(t3); + t2 = t2.get$start(); + endColumn = t1.endColumn = Math.min(startColumn + t3 - t2.get$offset(t2), t4); + textBefore = J.substring$2$s(line, 0, startColumn); + t2 = _this._multiline; + if (t2 && _this._isOnlyWhitespace$1(textBefore)) { + t1 = _this._highlighter$_buffer; + t1._contents += " "; + _this._colorize$1(new U.Highlighter__writeFirstLine_closure(_this, line)); + t1._contents += "\n"; + return; + } + t3 = _this._highlighter$_buffer; + t3._contents += C.JSString_methods.$mul(" ", t2 ? 3 : 1); + _this._writeText$1(textBefore); + textInside = C.JSString_methods.substring$2(line, startColumn, endColumn); + _this._colorize$1(new U.Highlighter__writeFirstLine_closure0(_this, textInside)); + _this._writeText$1(C.JSString_methods.substring$1(line, endColumn)); + t3._contents += "\n"; + tabsBefore = _this._countTabs$1(textBefore); + tabsInside = _this._countTabs$1(textInside); + startColumn += tabsBefore * 3; + t1.startColumn = startColumn; + t1.endColumn = endColumn + (tabsBefore + tabsInside) * 3; + _this._writeSidebar$0(); + if (t2) { + t3._contents += " "; + _this._colorize$1(new U.Highlighter__writeFirstLine_closure1(t1, _this)); + } else { + t3._contents += C.JSString_methods.$mul(" ", startColumn + 1); + _this._colorize$1(new U.Highlighter__writeFirstLine_closure2(t1, _this)); + } + t3._contents += "\n"; + }, + _writeIntermediateLines$1: function(lines) { + var t1, lineNumber, t2, t3, _this = this; + type$.Iterable_String._check(lines); + H.assertHelper(_this._multiline); + t1 = _this._span.get$start().get$line(); + if (typeof t1 !== "number") + return t1.$add(); + lineNumber = t1 + 1; + for (t1 = new H.ListIterator(lines, lines.get$length(lines), lines.$ti._eval$1("ListIterator<ListIterable.E>")), t2 = _this._highlighter$_buffer; t1.moveNext$0();) { + t3 = t1.__internal$_current; + _this._writeSidebar$1$line(lineNumber); + t2._contents += " "; + _this._colorize$1(new U.Highlighter__writeIntermediateLines_closure(_this, t3)); + t2._contents += "\n"; + ++lineNumber; + } + }, + _writeLastLine$1: function(line) { + var t3, t4, endColumn, textInside, _this = this, t1 = {}, + t2 = _this._multiline; + H.assertHelper(t2); + t3 = _this._span; + _this._writeSidebar$1$line(t3.get$end().get$line()); + t3 = t3.get$end().get$column(); + t4 = line.length; + endColumn = t1.endColumn = Math.min(t3, t4); + if (t2 && endColumn === t4) { + t1 = _this._highlighter$_buffer; + t1._contents += " "; + _this._colorize$1(new U.Highlighter__writeLastLine_closure(_this, line)); + t1._contents += "\n"; + return; + } + t2 = _this._highlighter$_buffer; + t2._contents += " "; + textInside = J.substring$2$s(line, 0, endColumn); + _this._colorize$1(new U.Highlighter__writeLastLine_closure0(_this, textInside)); + _this._writeText$1(C.JSString_methods.substring$1(line, endColumn)); + t2._contents += "\n"; + t1.endColumn = endColumn + _this._countTabs$1(textInside) * 3; + _this._writeSidebar$0(); + t2._contents += " "; + _this._colorize$1(new U.Highlighter__writeLastLine_closure1(t1, _this)); + t2._contents += "\n"; + }, + _writeTrailingLines$1: function(lines) { + var t1, lineNumber, t2, t3, t4, _this = this; + type$.Iterable_String._check(lines); + t1 = _this._span.get$end().get$line(); + if (typeof t1 !== "number") + return t1.$add(); + lineNumber = t1 + 1; + for (t1 = new H.ListIterator(lines, lines.get$length(lines), lines.$ti._eval$1("ListIterator<ListIterable.E>")), t2 = _this._highlighter$_buffer, t3 = _this._multiline; t1.moveNext$0();) { + t4 = t1.__internal$_current; + _this._writeSidebar$1$line(lineNumber); + t2._contents += C.JSString_methods.$mul(" ", t3 ? 3 : 1); + _this._writeText$1(t4); + t2._contents += "\n"; + ++lineNumber; + } + }, + _writeText$1: function(text) { + var t1, t2, t3; + text.toString; + t1 = new H.CodeUnits(text); + t1 = new H.ListIterator(t1, t1.get$length(t1), type$.CodeUnits._eval$1("ListIterator<ListMixin.E>")); + t2 = this._highlighter$_buffer; + for (; t1.moveNext$0();) { + t3 = t1.__internal$_current; + if (t3 === 9) + t2._contents += C.JSString_methods.$mul(" ", 4); + else + t2._contents += H.Primitives_stringFromCharCode(t3); + } + }, + _writeSidebar$2$end$line: function(end, line) { + this._colorize$2$color(new U.Highlighter__writeSidebar_closure(this, line, end), "\x1b[34m"); + }, + _writeSidebar$1$end: function(end) { + return this._writeSidebar$2$end$line(end, null); + }, + _writeSidebar$1$line: function(line) { + return this._writeSidebar$2$end$line(null, line); + }, + _writeSidebar$0: function() { + return this._writeSidebar$2$end$line(null, null); + }, + _countTabs$1: function(text) { + var t1, count; + for (t1 = new H.CodeUnits(text), t1 = new H.ListIterator(t1, t1.get$length(t1), type$.CodeUnits._eval$1("ListIterator<ListMixin.E>")), count = 0; t1.moveNext$0();) + if (t1.__internal$_current === 9) + ++count; + return count; + }, + _isOnlyWhitespace$1: function(text) { + var t1, t2; + for (t1 = new H.CodeUnits(text), t1 = new H.ListIterator(t1, t1.get$length(t1), type$.CodeUnits._eval$1("ListIterator<ListMixin.E>")); t1.moveNext$0();) { + t2 = t1.__internal$_current; + if (t2 !== 32 && t2 !== 9) + return false; + } + return true; + }, + _colorize$2$color: function(callback, color) { + var t1, t2; + type$.void_Function._check(callback); + t1 = this._color; + t2 = t1 != null; + if (t2) { + t1 = color == null ? t1 : color; + this._highlighter$_buffer._contents += t1; + } + callback.call$0(); + if (t2) + this._highlighter$_buffer._contents += "\x1b[0m"; + }, + _colorize$1: function(callback) { + return this._colorize$2$color(callback, null); + } + }; + U.Highlighter__writeFirstLine_closure.prototype = { + call$0: function() { + var t1 = this.$this, + t2 = t1._highlighter$_buffer, + t3 = t2._contents += $._glyphs.glyphOrAscii$2("\u250c", "/"); + t2._contents = t3 + " "; + t1._writeText$1(this.line); + }, + $signature: 0 + }; + U.Highlighter__writeFirstLine_closure0.prototype = { + call$0: function() { + return this.$this._writeText$1(this.textInside); + }, + $signature: 1 + }; + U.Highlighter__writeFirstLine_closure1.prototype = { + call$0: function() { + var t2, + t1 = this.$this._highlighter$_buffer; + t1._contents += $._glyphs.get$topLeftCorner(); + t2 = t1._contents += C.JSString_methods.$mul($._glyphs.get$horizontalLine(), this._box_0.startColumn + 1); + t1._contents = t2 + "^"; + }, + $signature: 0 + }; + U.Highlighter__writeFirstLine_closure2.prototype = { + call$0: function() { + var t1 = this._box_0; + this.$this._highlighter$_buffer._contents += C.JSString_methods.$mul("^", Math.max(t1.endColumn - t1.startColumn, 1)); + return null; + }, + $signature: 1 + }; + U.Highlighter__writeIntermediateLines_closure.prototype = { + call$0: function() { + var t1 = this.$this, + t2 = t1._highlighter$_buffer, + t3 = t2._contents += $._glyphs.get$verticalLine(); + t2._contents = t3 + " "; + t1._writeText$1(this.line); + }, + $signature: 0 + }; + U.Highlighter__writeLastLine_closure.prototype = { + call$0: function() { + var t1 = this.$this, + t2 = t1._highlighter$_buffer, + t3 = t2._contents += $._glyphs.glyphOrAscii$2("\u2514", "\\"); + t2._contents = t3 + " "; + t1._writeText$1(this.line); + }, + $signature: 0 + }; + U.Highlighter__writeLastLine_closure0.prototype = { + call$0: function() { + var t1 = this.$this, + t2 = t1._highlighter$_buffer, + t3 = t2._contents += $._glyphs.get$verticalLine(); + t2._contents = t3 + " "; + t1._writeText$1(this.textInside); + }, + $signature: 0 + }; + U.Highlighter__writeLastLine_closure1.prototype = { + call$0: function() { + var t2, + t1 = this.$this._highlighter$_buffer; + t1._contents += $._glyphs.get$bottomLeftCorner(); + t2 = t1._contents += C.JSString_methods.$mul($._glyphs.get$horizontalLine(), this._box_0.endColumn); + t1._contents = t2 + "^"; + }, + $signature: 0 + }; + U.Highlighter__writeSidebar_closure.prototype = { + call$0: function() { + var t1 = this.line, + t2 = this.$this, + t3 = t2._highlighter$_buffer; + t2 = t2._paddingBeforeSidebar; + if (t1 != null) + t3._contents += C.JSString_methods.padRight$1(C.JSInt_methods.toString$0(t1 + 1), t2); + else + t3._contents += C.JSString_methods.$mul(" ", t2); + t1 = this.end; + t3._contents += t1 == null ? $._glyphs.get$verticalLine() : t1; + }, + $signature: 0 + }; + V.SourceLocation.prototype = { + distance$1: function(other) { + var t1 = this.sourceUrl; + if (!J.$eq$(t1, other.get$sourceUrl())) + throw H.wrapException(P.ArgumentError$('Source URLs "' + H.S(t1) + '" and "' + H.S(other.get$sourceUrl()) + "\" don't match.")); + return Math.abs(this.offset - other.get$offset(other)); + }, + $eq: function(_, other) { + if (other == null) + return false; + return type$.SourceLocation._is(other) && J.$eq$(this.sourceUrl, other.get$sourceUrl()) && this.offset === other.get$offset(other); + }, + get$hashCode: function(_) { + return J.get$hashCode$(this.sourceUrl) + this.offset; + }, + toString$0: function(_) { + var _this = this, + t1 = "<" + H.getRuntimeType(_this).toString$0(0) + ": " + _this.offset + " ", + source = _this.sourceUrl; + return t1 + (H.S(source == null ? "unknown source" : source) + ":" + (_this.line + 1) + ":" + (_this.column + 1)) + ">"; + }, + get$sourceUrl: function() { + return this.sourceUrl; + }, + get$offset: function(receiver) { + return this.offset; + }, + get$line: function() { + return this.line; + }, + get$column: function() { + return this.column; + } + }; + D.SourceLocationMixin.prototype = { + distance$1: function(other) { + if (!J.$eq$(this.file.url, other.get$sourceUrl())) + throw H.wrapException(P.ArgumentError$('Source URLs "' + H.S(this.get$sourceUrl()) + '" and "' + H.S(other.get$sourceUrl()) + "\" don't match.")); + return Math.abs(this.offset - other.get$offset(other)); + }, + $eq: function(_, other) { + if (other == null) + return false; + return type$.SourceLocation._is(other) && J.$eq$(this.file.url, other.get$sourceUrl()) && this.offset === other.get$offset(other); + }, + get$hashCode: function(_) { + return J.get$hashCode$(this.file.url) + this.offset; + }, + toString$0: function(_) { + var t1 = this.offset, + t2 = "<" + H.getRuntimeType(this).toString$0(0) + ": " + t1 + " ", + t3 = this.file, + source = t3.url, + t4 = H.S(source == null ? "unknown source" : source) + ":", + t5 = t3.getLine$1(t1); + if (typeof t5 !== "number") + return t5.$add(); + return t2 + (t4 + (t5 + 1) + ":" + (t3.getColumn$1(t1) + 1)) + ">"; + }, + $isSourceLocation: 1 + }; + V.SourceSpan.prototype = {}; + V.SourceSpanBase.prototype = { + SourceSpanBase$3: function(start, end, text) { + var t3, + t1 = this.end, + t2 = this.start; + if (!J.$eq$(t1.get$sourceUrl(), t2.get$sourceUrl())) + throw H.wrapException(P.ArgumentError$('Source URLs "' + H.S(t2.get$sourceUrl()) + '" and "' + H.S(t1.get$sourceUrl()) + "\" don't match.")); + else if (t1.get$offset(t1) < t2.get$offset(t2)) + throw H.wrapException(P.ArgumentError$("End " + t1.toString$0(0) + " must come after start " + t2.toString$0(0) + ".")); + else { + t3 = this.text; + if (t3.length !== t2.distance$1(t1)) + throw H.wrapException(P.ArgumentError$('Text "' + t3 + '" must be ' + t2.distance$1(t1) + " characters long.")); + } + }, + get$start: function() { + return this.start; + }, + get$end: function() { + return this.end; + }, + get$text: function() { + return this.text; + } + }; + G.SourceSpanException.prototype = { + get$message: function(_) { + return this._span_exception$_message; + }, + toString$1$color: function(_, color) { + var t1 = this._span_exception$_span; + if (t1 == null) + return this._span_exception$_message; + return "Error on " + t1.message$2$color(0, this._span_exception$_message, color); + }, + toString$0: function($receiver) { + return this.toString$1$color($receiver, null); + }, + $isException: 1 + }; + G.SourceSpanFormatException.prototype = {$isFormatException: 1}; + Y.SourceSpanMixin.prototype = { + get$sourceUrl: function() { + return this.get$start().get$sourceUrl(); + }, + get$length: function(_) { + var t2, + t1 = this.get$end(); + t1 = t1.get$offset(t1); + t2 = this.get$start(); + return t1 - t2.get$offset(t2); + }, + message$2$color: function(_, message, color) { + var t2, highlight, _this = this, + t1 = _this.get$start().get$line(); + if (typeof t1 !== "number") + return t1.$add(); + t1 = "line " + (t1 + 1) + ", column " + (_this.get$start().get$column() + 1); + if (_this.get$sourceUrl() != null) { + t2 = _this.get$sourceUrl(); + t2 = t1 + (" of " + H.S($.$get$context().prettyUri$1(t2))); + t1 = t2; + } + t1 += ": " + H.S(message); + highlight = _this.highlight$1$color(color); + if (highlight.length !== 0) + t1 = t1 + "\n" + highlight; + return t1.charCodeAt(0) == 0 ? t1 : t1; + }, + message$1: function($receiver, message) { + return this.message$2$color($receiver, message, null); + }, + highlight$1$color: function(color) { + var t2, t3, t4, newSpan, _this = this, + t1 = type$.SourceSpanWithContext._is(_this); + if (!t1 && _this.get$length(_this) === 0) + return ""; + if (t1 && B.findLineStart(_this.get$context(), _this.get$text(), _this.get$start().get$column()) != null) + t1 = _this; + else { + t1 = _this.get$start(); + t1 = V.SourceLocation$(t1.get$offset(t1), 0, 0, _this.get$sourceUrl()); + t2 = _this.get$end(); + t2 = t2.get$offset(t2); + t3 = _this.get$sourceUrl(); + t4 = B.countCodeUnits(_this.get$text(), 10); + t3 = X.SourceSpanWithContext$(t1, V.SourceLocation$(t2, U.Highlighter__lastLineLength(_this.get$text()), t4, t3), _this.get$text(), _this.get$text()); + t1 = t3; + } + newSpan = U.Highlighter__normalizeEndOfLine(U.Highlighter__normalizeTrailingNewline(U.Highlighter__normalizeNewlines(t1))); + return new U.Highlighter(newSpan, color, newSpan.get$start().get$line() != newSpan.get$end().get$line(), J.toString$0$(newSpan.get$end().get$line()).length + 1, new P.StringBuffer("")).highlight$0(); + }, + $eq: function(_, other) { + if (other == null) + return false; + return type$.SourceSpan._is(other) && this.get$start().$eq(0, other.get$start()) && this.get$end().$eq(0, other.get$end()); + }, + get$hashCode: function(_) { + var t2, + t1 = this.get$start(); + t1 = t1.get$hashCode(t1); + t2 = this.get$end(); + return t1 + 31 * t2.get$hashCode(t2); + }, + toString$0: function(_) { + var _this = this; + return "<" + H.getRuntimeType(_this).toString$0(0) + ": from " + _this.get$start().toString$0(0) + " to " + _this.get$end().toString$0(0) + ' "' + _this.get$text() + '">'; + }, + $isSourceSpan: 1 + }; + X.SourceSpanWithContext.prototype = { + get$context: function() { + return this._context; + } + }; + U.Chain.prototype = { + foldFrames$2$terse: function(predicate, terse) { + var t1 = this.traces, + t2 = H._arrayInstanceType(t1), + t3 = t2._eval$1("MappedListIterable<1,Trace>"), + foldedTraces = new H.MappedListIterable(t1, t2._eval$1("Trace(1)")._check(new U.Chain_foldFrames_closure(type$.bool_Function_Frame._check(predicate), true)), t3), + nonEmptyTraces = foldedTraces.super$Iterable$where(0, t3._eval$1("bool(ListIterable.E)")._check(new U.Chain_foldFrames_closure0(true))); + if (!nonEmptyTraces.get$iterator(nonEmptyTraces).moveNext$0() && !foldedTraces.get$isEmpty(foldedTraces)) + return new U.Chain(P.List_List$unmodifiable(H.setRuntimeTypeInfo([foldedTraces.get$last(foldedTraces)], type$.JSArray_Trace), type$.Trace)); + return new U.Chain(P.List_List$unmodifiable(nonEmptyTraces, type$.Trace)); + }, + toTrace$0: function() { + var t1 = this.traces, + t2 = H._arrayInstanceType(t1); + return new Y.Trace(P.List_List$unmodifiable(new H.ExpandIterable(t1, t2._eval$1("Iterable<Frame>(1)")._check(new U.Chain_toTrace_closure()), t2._eval$1("ExpandIterable<1,Frame>")), type$.Frame), new P._StringStackTrace(null)); + }, + toString$0: function(_) { + var t1 = this.traces, + t2 = H._arrayInstanceType(t1), + t3 = type$.int; + return new H.MappedListIterable(t1, t2._eval$1("String(1)")._check(new U.Chain_toString_closure(new H.MappedListIterable(t1, t2._eval$1("int(1)")._check(new U.Chain_toString_closure0()), t2._eval$1("MappedListIterable<1,int>")).fold$1$2(0, 0, H.instantiate1(P.math__max$closure(), t3), t3))), t2._eval$1("MappedListIterable<1,String>")).join$1(0, "===== asynchronous gap ===========================\n"); + }, + $isStackTrace: 1, + get$traces: function() { + return this.traces; + } + }; + U.Chain_capture_closure.prototype = { + call$0: function() { + var error, stackTrace, t1, exception; + try { + t1 = this.callback.call$0(); + return t1; + } catch (exception) { + error = H.unwrapException(exception); + stackTrace = H.getTraceFromException(exception); + $.Zone__current.handleUncaughtError$2(error, stackTrace); + return null; + } + }, + $signature: function() { + return this.T._eval$1("0()"); + } + }; + U.Chain_Chain$current_closure.prototype = { + call$0: function() { + var t3, + t1 = this.chain, + t2 = C.JSArray_methods.get$first(t1.get$traces()).get$frames(); + t2 = H.SubListIterable$(t2, this.level + 2, null, H._arrayInstanceType(t2)._precomputed1); + t3 = C.JSArray_methods.get$first(t1.get$traces()).get$original(); + t3 = H.setRuntimeTypeInfo([new Y.Trace(P.List_List$unmodifiable(t2, type$.Frame), new P._StringStackTrace(t3._stackTrace))], type$.JSArray_Trace); + t1 = t1.get$traces(); + C.JSArray_methods.addAll$1(t3, H.SubListIterable$(t1, 1, null, H._arrayInstanceType(t1)._precomputed1)); + return new U.Chain(P.List_List$unmodifiable(t3, type$.Trace)); + }, + $signature: 16 + }; + U.Chain_Chain$forTrace_closure.prototype = { + call$0: function() { + return U.Chain_Chain$parse(J.toString$0$(this.trace)); + }, + $signature: 16 + }; + U.Chain_Chain$parse_closure.prototype = { + call$1: function(trace) { + H._checkStringNullable(trace); + return new Y.Trace(P.List_List$unmodifiable(Y.Trace__parseVM(trace), type$.Frame), new P._StringStackTrace(trace)); + }, + $signature: 42 + }; + U.Chain_Chain$parse_closure0.prototype = { + call$1: function(trace) { + return Y.Trace$parseFriendly(H._checkStringNullable(trace)); + }, + $signature: 42 + }; + U.Chain_foldFrames_closure.prototype = { + call$1: function(trace) { + return type$.Trace._check(trace).foldFrames$2$terse(this.predicate, this.terse); + }, + $signature: 45 + }; + U.Chain_foldFrames_closure0.prototype = { + call$1: function(trace) { + type$.Trace._check(trace); + if (trace.get$frames().length > 1) + return true; + if (trace.get$frames().length === 0) + return false; + if (!this.terse) + return false; + return C.JSArray_methods.get$single(trace.get$frames()).get$line() != null; + }, + $signature: 52 + }; + U.Chain_toTrace_closure.prototype = { + call$1: function(trace) { + return type$.Trace._check(trace).get$frames(); + }, + $signature: 53 + }; + U.Chain_toString_closure0.prototype = { + call$1: function(trace) { + var t1 = type$.Trace._check(trace).get$frames(), + t2 = H._arrayInstanceType(t1), + t3 = type$.int; + return new H.MappedListIterable(t1, t2._eval$1("int(1)")._check(new U.Chain_toString__closure0()), t2._eval$1("MappedListIterable<1,int>")).fold$1$2(0, 0, H.instantiate1(P.math__max$closure(), t3), t3); + }, + $signature: 54 + }; + U.Chain_toString__closure0.prototype = { + call$1: function(frame) { + type$.Frame._check(frame); + return frame.get$location(frame).length; + }, + $signature: 39 + }; + U.Chain_toString_closure.prototype = { + call$1: function(trace) { + var t1 = type$.Trace._check(trace).get$frames(), + t2 = H._arrayInstanceType(t1); + return new H.MappedListIterable(t1, t2._eval$1("String(1)")._check(new U.Chain_toString__closure(this.longest)), t2._eval$1("MappedListIterable<1,String>")).join$0(0); + }, + $signature: 56 + }; + U.Chain_toString__closure.prototype = { + call$1: function(frame) { + type$.Frame._check(frame); + return J.padRight$1$s(frame.get$location(frame), this.longest) + " " + H.S(frame.get$member()) + "\n"; + }, + $signature: 38 + }; + A.Frame.prototype = { + get$isCore: function() { + return this.uri.get$scheme() === "dart"; + }, + get$library: function() { + var t1 = this.uri; + if (t1.get$scheme() === "data") + return "data:..."; + return $.$get$context().prettyUri$1(t1); + }, + get$$package: function() { + var t1 = this.uri; + if (t1.get$scheme() !== "package") + return null; + return C.JSArray_methods.get$first(t1.get$path(t1).split("/")); + }, + get$location: function(_) { + var t2, _this = this, + t1 = _this.line; + if (t1 == null) + return _this.get$library(); + t2 = _this.column; + if (t2 == null) + return H.S(_this.get$library()) + " " + H.S(t1); + return H.S(_this.get$library()) + " " + H.S(t1) + ":" + H.S(t2); + }, + toString$0: function(_) { + return H.S(this.get$location(this)) + " in " + H.S(this.member); + }, + get$uri: function() { + return this.uri; + }, + get$line: function() { + return this.line; + }, + get$column: function() { + return this.column; + }, + get$member: function() { + return this.member; + } + }; + A.Frame_Frame$parseVM_closure.prototype = { + call$0: function() { + var match, t2, t3, member, uri, lineAndColumn, line, _null = null, + t1 = this.frame; + if (t1 === "...") + return new A.Frame(P._Uri__Uri(_null, _null, _null, _null), _null, _null, "..."); + match = $.$get$_vmFrame().firstMatch$1(t1); + if (match == null) + return new N.UnparsedFrame(P._Uri__Uri(_null, "unparsed", _null, _null), t1); + t1 = match._match; + if (1 >= t1.length) + return H.ioore(t1, 1); + t2 = t1[1]; + t3 = $.$get$_asyncBody(); + t2.toString; + t2 = H.stringReplaceAllUnchecked(t2, t3, "<async>"); + member = H.stringReplaceAllUnchecked(t2, "<anonymous closure>", "<fn>"); + if (2 >= t1.length) + return H.ioore(t1, 2); + uri = P.Uri_parse(t1[2]); + if (3 >= t1.length) + return H.ioore(t1, 3); + lineAndColumn = t1[3].split(":"); + t1 = lineAndColumn.length; + line = t1 > 1 ? P.int_parse(lineAndColumn[1], _null, _null) : _null; + return new A.Frame(uri, line, t1 > 2 ? P.int_parse(lineAndColumn[2], _null, _null) : _null, member); + }, + $signature: 17 + }; + A.Frame_Frame$parseV8_closure.prototype = { + call$0: function() { + var t2, t3, t4, _s4_ = "<fn>", + t1 = this.frame, + match = $.$get$_v8Frame().firstMatch$1(t1); + if (match == null) + return new N.UnparsedFrame(P._Uri__Uri(null, "unparsed", null, null), t1); + t1 = new A.Frame_Frame$parseV8_closure_parseLocation(t1); + t2 = match._match; + t3 = t2.length; + if (2 >= t3) + return H.ioore(t2, 2); + t4 = t2[2]; + if (t4 != null) { + t2 = t2[1]; + t2.toString; + t2 = H.stringReplaceAllUnchecked(t2, "<anonymous>", _s4_); + t2 = H.stringReplaceAllUnchecked(t2, "Anonymous function", _s4_); + return t1.call$2(t4, H.stringReplaceAllUnchecked(t2, "(anonymous function)", _s4_)); + } else { + if (3 >= t3) + return H.ioore(t2, 3); + return t1.call$2(t2[3], _s4_); + } + }, + $signature: 17 + }; + A.Frame_Frame$parseV8_closure_parseLocation.prototype = { + call$2: function($location, member) { + var t2, urlMatch, t3, _null = null, + t1 = $.$get$_v8EvalLocation(), + evalMatch = t1.firstMatch$1($location); + for (; evalMatch != null;) { + t2 = evalMatch._match; + if (1 >= t2.length) + return H.ioore(t2, 1); + $location = t2[1]; + evalMatch = t1.firstMatch$1($location); + } + if ($location === "native") + return new A.Frame(P.Uri_parse("native"), _null, _null, member); + urlMatch = $.$get$_v8UrlLocation().firstMatch$1($location); + if (urlMatch == null) + return new N.UnparsedFrame(P._Uri__Uri(_null, "unparsed", _null, _null), this.frame); + t1 = urlMatch._match; + if (1 >= t1.length) + return H.ioore(t1, 1); + t2 = A.Frame__uriOrPathToUri(t1[1]); + if (2 >= t1.length) + return H.ioore(t1, 2); + t3 = P.int_parse(t1[2], _null, _null); + if (3 >= t1.length) + return H.ioore(t1, 3); + return new A.Frame(t2, t3, P.int_parse(t1[3], _null, _null), member); + }, + $signature: 59 + }; + A.Frame_Frame$parseFirefox_closure.prototype = { + call$0: function() { + var uri, t2, t3, member, line, _null = null, + t1 = this.frame, + match = $.$get$_firefoxSafariFrame().firstMatch$1(t1); + if (match == null) + return new N.UnparsedFrame(P._Uri__Uri(_null, "unparsed", _null, _null), t1); + t1 = match._match; + if (3 >= t1.length) + return H.ioore(t1, 3); + uri = A.Frame__uriOrPathToUri(t1[3]); + t2 = t1.length; + if (1 >= t2) + return H.ioore(t1, 1); + t3 = t1[1]; + if (t3 != null) { + if (2 >= t2) + return H.ioore(t1, 2); + t2 = C.JSString_methods.allMatches$1("/", t1[2]); + member = J.$add$ansx(t3, C.JSArray_methods.join$0(P.List_List$filled(t2.get$length(t2), ".<fn>", type$.String))); + if (member === "") + member = "<fn>"; + member = C.JSString_methods.replaceFirst$2(member, $.$get$_initialDot(), ""); + } else + member = "<fn>"; + if (4 >= t1.length) + return H.ioore(t1, 4); + t2 = t1[4]; + line = t2 === "" ? _null : P.int_parse(t2, _null, _null); + if (5 >= t1.length) + return H.ioore(t1, 5); + t1 = t1[5]; + return new A.Frame(uri, line, t1 == null || t1 === "" ? _null : P.int_parse(t1, _null, _null), member); + }, + $signature: 17 + }; + A.Frame_Frame$parseFriendly_closure.prototype = { + call$0: function() { + var t2, buffer, indices, uri, line, column, _null = null, + t1 = this.frame, + match = $.$get$_friendlyFrame().firstMatch$1(t1); + if (match == null) + throw H.wrapException(P.FormatException$("Couldn't parse package:stack_trace stack trace line '" + H.S(t1) + "'.", _null, _null)); + t1 = match._match; + if (1 >= t1.length) + return H.ioore(t1, 1); + t2 = t1[1]; + if (t2 === "data:...") { + buffer = new P.StringBuffer(""); + indices = H.setRuntimeTypeInfo([-1], type$.JSArray_int); + P.UriData__writeUri(_null, _null, _null, buffer, indices); + C.JSArray_methods.add$1(indices, buffer._contents.length); + buffer._contents += ","; + P.UriData__uriEncodeBytes(C.List_CVk, C.C_AsciiCodec.encode$1(""), buffer); + t2 = buffer._contents; + uri = new P.UriData(t2.charCodeAt(0) == 0 ? t2 : t2, indices, _null).get$uri(); + } else + uri = P.Uri_parse(t2); + if (uri.get$scheme() === "") { + t2 = $.$get$context(); + uri = t2.toUri$1(t2.absolute$7(0, t2.style.pathFromUri$1(M._parseUri(uri)), _null, _null, _null, _null, _null, _null)); + } + if (2 >= t1.length) + return H.ioore(t1, 2); + t2 = t1[2]; + line = t2 == null ? _null : P.int_parse(t2, _null, _null); + if (3 >= t1.length) + return H.ioore(t1, 3); + t2 = t1[3]; + column = t2 == null ? _null : P.int_parse(t2, _null, _null); + if (4 >= t1.length) + return H.ioore(t1, 4); + return new A.Frame(uri, line, column, t1[4]); + }, + $signature: 17 + }; + X.LazyChain.prototype = { + get$_chain: function() { + var _this = this; + if (_this._lazy_chain$_inner == null) + _this.set$_lazy_chain$_inner(_this._thunk.call$0()); + return _this._lazy_chain$_inner; + }, + get$traces: function() { + return this.get$_chain().get$traces(); + }, + foldFrames$2$terse: function(predicate, terse) { + return new X.LazyChain(new X.LazyChain_foldFrames_closure(this, type$.bool_Function_Frame._check(predicate), true)); + }, + toTrace$0: function() { + return new T.LazyTrace(new X.LazyChain_toTrace_closure(this)); + }, + toString$0: function(_) { + return J.toString$0$(this.get$_chain()); + }, + set$_lazy_chain$_inner: function(_inner) { + this._lazy_chain$_inner = type$.Chain._check(_inner); + }, + $isStackTrace: 1, + $isChain: 1 + }; + X.LazyChain_foldFrames_closure.prototype = { + call$0: function() { + return this.$this.get$_chain().foldFrames$2$terse(this.predicate, this.terse); + }, + $signature: 16 + }; + X.LazyChain_toTrace_closure.prototype = { + call$0: function() { + return this.$this.get$_chain().toTrace$0(); + }, + $signature: 8 + }; + T.LazyTrace.prototype = { + get$_lazy_trace$_trace: function() { + var _this = this; + if (_this._lazy_trace$_inner == null) + _this.set$_lazy_trace$_inner(_this._lazy_trace$_thunk.call$0()); + return _this._lazy_trace$_inner; + }, + get$frames: function() { + return this.get$_lazy_trace$_trace().get$frames(); + }, + get$original: function() { + return this.get$_lazy_trace$_trace().get$original(); + }, + foldFrames$2$terse: function(predicate, terse) { + return new T.LazyTrace(new T.LazyTrace_foldFrames_closure(this, type$.bool_Function_Frame._check(predicate), true)); + }, + toString$0: function(_) { + return J.toString$0$(this.get$_lazy_trace$_trace()); + }, + set$_lazy_trace$_inner: function(_inner) { + this._lazy_trace$_inner = type$.Trace._check(_inner); + }, + $isStackTrace: 1, + $isTrace: 1 + }; + T.LazyTrace_foldFrames_closure.prototype = { + call$0: function() { + return this.$this.get$_lazy_trace$_trace().foldFrames$2$terse(this.predicate, this.terse); + }, + $signature: 8 + }; + O.StackZoneSpecification.prototype = { + chainFor$1: function(trace) { + var t2, previous, t3, t1 = {}; + t1.trace = trace; + if (type$.Chain._is(trace)) + return trace; + if (trace == null) { + trace = P.StackTrace_current(); + t1.trace = trace; + t2 = trace; + } else + t2 = trace; + previous = this._chains.$index(0, t2); + if (previous == null) + previous = this._currentNode; + if (previous == null) { + t3 = type$.Trace; + if (t3._is(t2)) + return new U.Chain(P.List_List$unmodifiable(H.setRuntimeTypeInfo([t2], type$.JSArray_Trace), t3)); + return new X.LazyChain(new O.StackZoneSpecification_chainFor_closure(t1)); + } else + return new O._Node(Y.Trace_Trace$from(!type$.Trace._is(t2) ? t1.trace = new T.LazyTrace(new O.StackZoneSpecification_chainFor_closure0(this, t2)) : t2), previous).toChain$0(); + }, + _stack_zone_specification$_registerCallback$1$4: function($self, $parent, zone, f, $R) { + var t1, t2; + $R._eval$1("0()")._check(f); + if (f == null || J.$eq$($.Zone__current.$index(0, $.$get$StackZoneSpecification_disableKey()), true)) + return $parent.registerCallback$1$2(zone, f, $R); + t1 = this._currentTrace$1(2); + t2 = this._currentNode; + return $parent.registerCallback$1$2(zone, new O.StackZoneSpecification__registerCallback_closure(this, f, new O._Node(Y.Trace_Trace$from(t1), t2), $R), $R); + }, + _stack_zone_specification$_registerCallback$4: function($self, $parent, zone, f) { + return this._stack_zone_specification$_registerCallback$1$4($self, $parent, zone, f, type$.dynamic); + }, + _stack_zone_specification$_registerUnaryCallback$2$4: function($self, $parent, zone, f, $R, $T) { + var t1, t2; + $R._eval$1("@<0>")._bind$1($T)._eval$1("1(2)")._check(f); + if (f == null || J.$eq$($.Zone__current.$index(0, $.$get$StackZoneSpecification_disableKey()), true)) + return $parent.registerUnaryCallback$2$2(zone, f, $R, $T); + t1 = this._currentTrace$1(2); + t2 = this._currentNode; + return $parent.registerUnaryCallback$2$2(zone, new O.StackZoneSpecification__registerUnaryCallback_closure(this, f, new O._Node(Y.Trace_Trace$from(t1), t2), $T, $R), $R, $T); + }, + _stack_zone_specification$_registerUnaryCallback$4: function($self, $parent, zone, f) { + return this._stack_zone_specification$_registerUnaryCallback$2$4($self, $parent, zone, f, type$.dynamic, type$.dynamic); + }, + _stack_zone_specification$_registerBinaryCallback$3$4: function($self, $parent, zone, f, $R, T1, T2) { + var t1, t2; + type$.Function._check(f); + if (f == null || J.$eq$($.Zone__current.$index(0, $.$get$StackZoneSpecification_disableKey()), true)) + return $parent.registerBinaryCallback$3$2(zone, $R._eval$1("@<0>")._bind$1(T1)._bind$1(T2)._eval$1("1(2,3)")._check(f), $R, T1, T2); + t1 = this._currentTrace$1(2); + t2 = this._currentNode; + return $parent.registerBinaryCallback$3$2(zone, new O.StackZoneSpecification__registerBinaryCallback_closure(this, f, new O._Node(Y.Trace_Trace$from(t1), t2), T1, T2, $R), $R, T1, T2); + }, + _stack_zone_specification$_registerBinaryCallback$4: function($self, $parent, zone, f) { + return this._stack_zone_specification$_registerBinaryCallback$3$4($self, $parent, zone, f, type$.dynamic, type$.dynamic, type$.dynamic); + }, + _stack_zone_specification$_errorCallback$5: function($self, $parent, zone, error, stackTrace) { + var t1, t2, t3, asyncError, _this = this; + type$.StackTrace._check(stackTrace); + if (J.$eq$($.Zone__current.$index(0, $.$get$StackZoneSpecification_disableKey()), true)) + return $parent.errorCallback$3(zone, error, stackTrace); + if (stackTrace == null) { + t1 = _this._currentTrace$1(3); + t2 = _this._currentNode; + stackTrace = new O._Node(Y.Trace_Trace$from(t1), t2).toChain$0(); + } else { + t1 = _this._chains; + if (t1.$index(0, stackTrace) == null) { + t2 = _this._currentTrace$1(3); + t3 = _this._currentNode; + t1.$indexSet(0, stackTrace, new O._Node(Y.Trace_Trace$from(t2), t3)); + } + } + asyncError = $parent.errorCallback$3(zone, error, stackTrace); + return asyncError == null ? new P.AsyncError(error, stackTrace) : asyncError; + }, + _stack_zone_specification$_run$1$2: function(f, node, $T) { + var previousNode, stackTrace, t1, exception, t2, _this = this; + $T._eval$1("0()")._check(f); + previousNode = _this._currentNode; + _this._currentNode = node; + try { + t1 = f.call$0(); + return t1; + } catch (exception) { + H.unwrapException(exception); + stackTrace = H.getTraceFromException(exception); + t1 = _this._chains; + t2 = stackTrace; + if (t1.$index(0, t2) == null) + t1.$indexSet(0, t2, node); + throw exception; + } finally { + _this.set$_currentNode(previousNode); + } + }, + _currentTrace$1: function(level) { + var t1 = {}; + t1.level = level; + return new T.LazyTrace(new O.StackZoneSpecification__currentTrace_closure(t1, this, P.StackTrace_current())); + }, + _trimVMChain$1: function(trace) { + var text = J.toString$0$(trace), + index = J.getInterceptor$s(text).indexOf$1(text, "<asynchronous suspension>\n"); + return index === -1 ? text : C.JSString_methods.substring$2(text, 0, index); + }, + set$_currentNode: function(_currentNode) { + this._currentNode = type$._Node._check(_currentNode); + } + }; + O.StackZoneSpecification_chainFor_closure.prototype = { + call$0: function() { + return U.Chain_Chain$parse(J.toString$0$(this._box_0.trace)); + }, + $signature: 16 + }; + O.StackZoneSpecification_chainFor_closure0.prototype = { + call$0: function() { + return Y.Trace_Trace$parse(this.$this._trimVMChain$1(this.original)); + }, + $signature: 8 + }; + O.StackZoneSpecification__registerCallback_closure.prototype = { + call$0: function() { + var _this = this; + return _this.$this._stack_zone_specification$_run$1$2(_this.f, _this.node, _this.R); + }, + $signature: function() { + return this.R._eval$1("0()"); + } + }; + O.StackZoneSpecification__registerUnaryCallback_closure.prototype = { + call$1: function(arg) { + var _this = this, + t1 = _this.R; + return _this.$this._stack_zone_specification$_run$1$2(new O.StackZoneSpecification__registerUnaryCallback__closure(_this.f, _this.T._check(arg), t1), _this.node, t1); + }, + $signature: function() { + return this.R._eval$1("@<0>")._bind$1(this.T)._eval$1("1(2)"); + } + }; + O.StackZoneSpecification__registerUnaryCallback__closure.prototype = { + call$0: function() { + return this.f.call$1(this.arg); + }, + $signature: function() { + return this.R._eval$1("0()"); + } + }; + O.StackZoneSpecification__registerBinaryCallback_closure.prototype = { + call$2: function(arg1, arg2) { + var _this = this, + t1 = _this.R; + return _this.$this._stack_zone_specification$_run$1$2(new O.StackZoneSpecification__registerBinaryCallback__closure(_this.f, _this.T1._check(arg1), _this.T2._check(arg2), t1), _this.node, t1); + }, + $signature: function() { + return this.R._eval$1("@<0>")._bind$1(this.T1)._bind$1(this.T2)._eval$1("1(2,3)"); + } + }; + O.StackZoneSpecification__registerBinaryCallback__closure.prototype = { + call$0: function() { + var _this = this; + return _this.R._check(_this.f.call$2(_this.arg1, _this.arg2)); + }, + $signature: function() { + return this.R._eval$1("0()"); + } + }; + O.StackZoneSpecification__currentTrace_closure.prototype = { + call$0: function() { + var text = this.$this._trimVMChain$1(this.stackTrace), + t1 = Y.Trace_Trace$parse(text).frames, + t2 = this._box_0.level; + if (typeof t2 !== "number") + return t2.$add(); + return new Y.Trace(P.List_List$unmodifiable(H.SubListIterable$(t1, t2 + 2, null, H._arrayInstanceType(t1)._precomputed1), type$.Frame), new P._StringStackTrace(text)); + }, + $signature: 8 + }; + O._Node.prototype = { + toChain$0: function() { + var node, + nodes = H.setRuntimeTypeInfo([], type$.JSArray_Trace); + for (node = this; node != null;) { + C.JSArray_methods.add$1(nodes, node.trace); + node = node.previous; + } + return new U.Chain(P.List_List$unmodifiable(nodes, type$.Trace)); + } + }; + Y.Trace.prototype = { + foldFrames$2$terse: function(predicate, terse) { + var newFrames, t1, t2, _box_0 = {}; + _box_0.predicate = predicate; + _box_0.predicate = new Y.Trace_foldFrames_closure(type$.bool_Function_Frame._check(predicate)); + newFrames = H.setRuntimeTypeInfo([], type$.JSArray_Frame); + for (t1 = this.frames, t2 = H._arrayInstanceType(t1)._eval$1("ReversedListIterable<1>"), t1 = new H.ReversedListIterable(t1, t2), t2 = new H.ListIterator(t1, t1.get$length(t1), t2._eval$1("ListIterator<ListIterable.E>")); t2.moveNext$0();) { + t1 = t2.__internal$_current; + if (t1 instanceof N.UnparsedFrame || !H.boolConversionCheck(_box_0.predicate.call$1(t1))) + C.JSArray_methods.add$1(newFrames, t1); + else if (newFrames.length === 0 || !H.boolConversionCheck(_box_0.predicate.call$1(C.JSArray_methods.get$last(newFrames)))) + C.JSArray_methods.add$1(newFrames, new A.Frame(t1.get$uri(), t1.get$line(), t1.get$column(), t1.get$member())); + } + newFrames = new H.MappedListIterable(newFrames, type$.Frame_Function_Frame._check(new Y.Trace_foldFrames_closure0(_box_0)), type$.MappedListIterable_Frame_Frame).toList$0(0); + if (newFrames.length > 1 && H.boolConversionCheck(_box_0.predicate.call$1(C.JSArray_methods.get$first(newFrames)))) + C.JSArray_methods.removeAt$1(newFrames, 0); + return new Y.Trace(P.List_List$unmodifiable(new H.ReversedListIterable(newFrames, H._arrayInstanceType(newFrames)._eval$1("ReversedListIterable<1>")), type$.Frame), new P._StringStackTrace(this.original._stackTrace)); + }, + toString$0: function(_) { + var t1 = this.frames, + t2 = H._arrayInstanceType(t1), + t3 = type$.int; + return new H.MappedListIterable(t1, t2._eval$1("String(1)")._check(new Y.Trace_toString_closure(new H.MappedListIterable(t1, t2._eval$1("int(1)")._check(new Y.Trace_toString_closure0()), t2._eval$1("MappedListIterable<1,int>")).fold$1$2(0, 0, H.instantiate1(P.math__max$closure(), t3), t3))), t2._eval$1("MappedListIterable<1,String>")).join$0(0); + }, + $isStackTrace: 1, + get$frames: function() { + return this.frames; + }, + get$original: function() { + return this.original; + } + }; + Y.Trace_Trace$current_closure.prototype = { + call$0: function() { + var t1 = this.trace, + t2 = t1.get$frames(); + t2 = H.SubListIterable$(t2, this.level + 2, null, H._arrayInstanceType(t2)._precomputed1); + t1 = t1.get$original(); + return new Y.Trace(P.List_List$unmodifiable(t2, type$.Frame), new P._StringStackTrace(t1._stackTrace)); + }, + $signature: 8 + }; + Y.Trace_Trace$from_closure.prototype = { + call$0: function() { + return Y.Trace_Trace$parse(this.trace.toString$0(0)); + }, + $signature: 8 + }; + Y.Trace__parseVM_closure.prototype = { + call$1: function(line) { + return A.Frame_Frame$parseVM(H._checkStringNullable(line)); + }, + $signature: 10 + }; + Y.Trace$parseV8_closure.prototype = { + call$1: function(line) { + return !J.startsWith$1$s(H._checkStringNullable(line), $.$get$_v8TraceLine()); + }, + $signature: 4 + }; + Y.Trace$parseV8_closure0.prototype = { + call$1: function(line) { + return A.Frame_Frame$parseV8(H._checkStringNullable(line)); + }, + $signature: 10 + }; + Y.Trace$parseJSCore_closure.prototype = { + call$1: function(line) { + return H._checkStringNullable(line) !== "\tat "; + }, + $signature: 4 + }; + Y.Trace$parseJSCore_closure0.prototype = { + call$1: function(line) { + return A.Frame_Frame$parseV8(H._checkStringNullable(line)); + }, + $signature: 10 + }; + Y.Trace$parseFirefox_closure.prototype = { + call$1: function(line) { + H._checkStringNullable(line); + return line.length !== 0 && line !== "[native code]"; + }, + $signature: 4 + }; + Y.Trace$parseFirefox_closure0.prototype = { + call$1: function(line) { + return A.Frame_Frame$parseFirefox(H._checkStringNullable(line)); + }, + $signature: 10 + }; + Y.Trace$parseFriendly_closure.prototype = { + call$1: function(line) { + return !J.startsWith$1$s(H._checkStringNullable(line), "====="); + }, + $signature: 4 + }; + Y.Trace$parseFriendly_closure0.prototype = { + call$1: function(line) { + return A.Frame_Frame$parseFriendly(H._checkStringNullable(line)); + }, + $signature: 10 + }; + Y.Trace_foldFrames_closure.prototype = { + call$1: function(frame) { + if (H.boolConversionCheck(this.oldPredicate.call$1(frame))) + return true; + if (frame.get$isCore()) + return true; + if (frame.get$$package() === "stack_trace") + return true; + if (!J.contains$1$asx(frame.get$member(), "<async>")) + return false; + return frame.get$line() == null; + }, + $signature: 21 + }; + Y.Trace_foldFrames_closure0.prototype = { + call$1: function(frame) { + var t1, t2; + type$.Frame._check(frame); + if (frame instanceof N.UnparsedFrame || !H.boolConversionCheck(this._box_0.predicate.call$1(frame))) + return frame; + t1 = frame.get$library(); + t2 = $.$get$_terseRegExp(); + t1.toString; + return new A.Frame(P.Uri_parse(H.stringReplaceAllUnchecked(t1, t2, "")), null, null, frame.get$member()); + }, + $signature: 46 + }; + Y.Trace_toString_closure0.prototype = { + call$1: function(frame) { + type$.Frame._check(frame); + return frame.get$location(frame).length; + }, + $signature: 39 + }; + Y.Trace_toString_closure.prototype = { + call$1: function(frame) { + type$.Frame._check(frame); + if (frame instanceof N.UnparsedFrame) + return frame.toString$0(0) + "\n"; + return J.padRight$1$s(frame.get$location(frame), this.longest) + " " + H.S(frame.get$member()) + "\n"; + }, + $signature: 38 + }; + N.UnparsedFrame.prototype = { + toString$0: function(_) { + return this.member; + }, + $isFrame: 1, + get$uri: function() { + return this.uri; + }, + get$line: function() { + return null; + }, + get$column: function() { + return null; + }, + get$isCore: function() { + return false; + }, + get$library: function() { + return "unparsed"; + }, + get$$package: function() { + return null; + }, + get$location: function() { + return "unparsed"; + }, + get$member: function() { + return this.member; + } + }; + K.GuaranteeChannel.prototype = { + get$stream: function(_) { + var t1 = this._streamController; + t1.toString; + return new P._ControllerStream(t1, H._instanceType(t1)._eval$1("_ControllerStream<1>")); + }, + get$sink: function() { + return this._sink; + }, + GuaranteeChannel$3$allowSinkErrors: function(innerSink, allowSinkErrors, _box_0, $T) { + var _this = this; + _this.set$_sink(new K._GuaranteeSink(innerSink, _this, new P._AsyncCompleter(new P._Future($.Zone__current, type$._Future_dynamic), type$._AsyncCompleter_dynamic), allowSinkErrors, $T._eval$1("_GuaranteeSink<0>"))); + _this.set$_streamController(P.StreamController_StreamController(null, new K.GuaranteeChannel_closure(_box_0, _this), true, $T)); + }, + _onSinkDisconnected$0: function() { + this._disconnected = true; + var t1 = this._subscription; + if (t1 != null) + t1.cancel$0(); + this._streamController.close$0(0); + }, + set$_sink: function(_sink) { + this._sink = this.$ti._eval$1("_GuaranteeSink<1>")._check(_sink); + }, + set$_streamController: function(_streamController) { + this._streamController = this.$ti._eval$1("StreamController<1>")._check(_streamController); + }, + set$_subscription: function(_subscription) { + this._subscription = this.$ti._eval$1("StreamSubscription<1>")._check(_subscription); + } + }; + K.GuaranteeChannel_closure.prototype = { + call$0: function() { + var t2, t3, + t1 = this.$this; + if (t1._disconnected) + return; + t2 = this._box_0.innerStream; + t3 = t1._streamController; + t1.set$_subscription(t2.listen$3$onDone$onError(t3.get$add(t3), new K.GuaranteeChannel__closure(t1), t3.get$addError())); + }, + $signature: 0 + }; + K.GuaranteeChannel__closure.prototype = { + call$0: function() { + var t1 = this.$this; + t1._sink._onStreamDisconnected$0(); + t1._streamController.close$0(0); + }, + $signature: 0 + }; + K._GuaranteeSink.prototype = { + get$done: function() { + return this._doneCompleter.future; + }, + add$1: function(_, data) { + var t1, _this = this; + _this.$ti._precomputed1._check(data); + if (_this._closed) + throw H.wrapException(P.StateError$("Cannot add event after closing.")); + if (_this._addStreamSubscription != null) + throw H.wrapException(P.StateError$("Cannot add event while adding stream.")); + if (_this._disconnected) + return; + t1 = _this._inner; + t1._async$_target.add$1(0, t1.$ti._precomputed1._check(data)); + }, + addError$2: function(error, stackTrace) { + var _this = this; + type$.StackTrace._check(stackTrace); + if (_this._closed) + throw H.wrapException(P.StateError$("Cannot add event after closing.")); + if (_this._addStreamSubscription != null) + throw H.wrapException(P.StateError$("Cannot add event while adding stream.")); + if (_this._disconnected) + return; + _this._addError$2(error, stackTrace); + }, + addError$1: function(error) { + return this.addError$2(error, null); + }, + _addError$2: function(error, stackTrace) { + var _this = this; + type$.StackTrace._check(stackTrace); + if (_this._allowErrors) { + _this._inner._async$_target.addError$2(error, stackTrace); + return; + } + _this._doneCompleter.completeError$2(error, stackTrace); + _this._onStreamDisconnected$0(); + _this._channel._onSinkDisconnected$0(); + _this._inner._async$_target.close$0(0).catchError$1(new K._GuaranteeSink__addError_closure()); + }, + _addError$1: function(error) { + return this._addError$2(error, null); + }, + addStream$1: function(stream) { + var t1, t2, _this = this; + _this.$ti._eval$1("Stream<1>")._check(stream); + if (_this._closed) + throw H.wrapException(P.StateError$("Cannot add stream after closing.")); + if (_this._addStreamSubscription != null) + throw H.wrapException(P.StateError$("Cannot add stream while adding stream.")); + if (_this._disconnected) { + t1 = new P._Future($.Zone__current, type$._Future_void); + t1._asyncComplete$1(null); + return t1; + } + t1 = new P._SyncCompleter(new P._Future($.Zone__current, type$._Future_dynamic), type$._SyncCompleter_dynamic); + _this._addStreamCompleter = t1; + t2 = _this._inner; + _this.set$_addStreamSubscription(stream.listen$3$onDone$onError(t2.get$add(t2), t1.get$complete(), _this.get$_addError())); + return _this._addStreamCompleter.future.then$1$1(new K._GuaranteeSink_addStream_closure(_this), type$.void); + }, + close$0: function(_) { + var _this = this; + if (_this._addStreamSubscription != null) + throw H.wrapException(P.StateError$("Cannot close sink while adding stream.")); + if (_this._closed) + return _this._doneCompleter.future; + _this._closed = true; + if (!_this._disconnected) { + _this._channel._onSinkDisconnected$0(); + _this._doneCompleter.complete$1(_this._inner._async$_target.close$0(0)); + } + return _this._doneCompleter.future; + }, + _onStreamDisconnected$0: function() { + var t1, _this = this; + _this._disconnected = true; + t1 = _this._doneCompleter; + if (t1.future._state === 0) + t1.complete$0(); + t1 = _this._addStreamSubscription; + if (t1 == null) + return; + _this._addStreamCompleter.complete$1(t1.cancel$0()); + _this._addStreamCompleter = null; + _this.set$_addStreamSubscription(null); + }, + set$_addStreamSubscription: function(_addStreamSubscription) { + this._addStreamSubscription = this.$ti._eval$1("StreamSubscription<1>")._check(_addStreamSubscription); + }, + $isEventSink: 1, + $isStreamConsumer: 1, + $isStreamSink: 1, + $isSink: 1 + }; + K._GuaranteeSink__addError_closure.prototype = { + call$1: function(_) { + }, + $signature: 3 + }; + K._GuaranteeSink_addStream_closure.prototype = { + call$1: function(_) { + var t1 = this.$this; + t1._addStreamCompleter = null; + t1.set$_addStreamSubscription(null); + }, + $signature: 3 + }; + D._MultiChannel.prototype = { + _MultiChannel$1: function(_inner, $T) { + var t2, _this = this, + t1 = _this._mainController; + _this._controllers.$indexSet(0, 0, t1); + t2 = t1._local._streamController; + t2.toString; + new P._ControllerStream(t2, H._instanceType(t2)._eval$1("_ControllerStream<1>")).listen$2$onDone(new D._MultiChannel_closure(_this, $T), new D._MultiChannel_closure0(_this)); + t2 = _this._multi_channel$_inner._streamController; + t2.toString; + _this._innerStreamSubscription = new P._ControllerStream(t2, H._instanceType(t2)._eval$1("_ControllerStream<1>")).listen$3$onDone$onError(new D._MultiChannel_closure1(_this, $T), _this.get$_closeInnerChannel(), t1._local._sink.get$addError()); + }, + virtualChannel$1: function(id) { + var t2, t3, controller, _this = this, t1 = {}; + t1.outputId = t1.inputId = null; + if (id != null) { + t1.inputId = id; + t1.outputId = id + 1; + t2 = id; + } else { + t2 = _this._nextId; + t3 = t1.inputId = t2 + 1; + t1.outputId = t2; + _this._nextId = t2 + 2; + t2 = t3; + } + if (_this._multi_channel$_inner == null) { + t1 = _this.$ti; + t3 = new P._Future($.Zone__current, type$._Future_dynamic); + t3._asyncComplete$1(null); + return new D.VirtualChannel(_this, t2, new P._EmptyStream(t1._eval$1("_EmptyStream<1>")), new S.NullStreamSink(t3, t1._eval$1("NullStreamSink<1>")), t1._eval$1("VirtualChannel<1>")); + } + if (_this._pendingIds.remove$1(0, t2)) + controller = _this._controllers.$index(0, t2); + else { + t3 = _this._controllers; + if (t3.containsKey$1(t2) || _this._closedIds.contains$1(0, t2)) + throw H.wrapException(P.ArgumentError$("A virtual channel with id " + H.S(id) + " already exists.")); + else { + controller = B.StreamChannelController$(true, true, _this.$ti._precomputed1); + t3.$indexSet(0, t2, controller); + } + } + t2 = controller._local._streamController; + t2.toString; + new P._ControllerStream(t2, H._instanceType(t2)._eval$1("_ControllerStream<1>")).listen$2$onDone(new D._MultiChannel_virtualChannel_closure(t1, _this), new D._MultiChannel_virtualChannel_closure0(t1, _this)); + t1 = t1.outputId; + t2 = controller._foreign; + t3 = t2._streamController; + t3.toString; + return new D.VirtualChannel(_this, t1, new P._ControllerStream(t3, H._instanceType(t3)._eval$1("_ControllerStream<1>")), t2._sink, _this.$ti._eval$1("VirtualChannel<1>")); + }, + virtualChannel$0: function() { + return this.virtualChannel$1(null); + }, + _closeChannel$2: function(inputId, outputId) { + var t1, t2, _this = this; + _this._closedIds.add$1(0, inputId); + t1 = _this._controllers; + t1.remove$1(0, inputId)._local._sink.close$0(0); + t2 = _this._multi_channel$_inner; + if (t2 == null) + return; + t2._sink.add$1(0, H.setRuntimeTypeInfo([outputId], type$.JSArray_int)); + if (t1.get$isEmpty(t1)) + _this._closeInnerChannel$0(); + }, + _closeInnerChannel$0: function() { + var t1, t2, t3, _i, _this = this; + _this._multi_channel$_inner._sink.close$0(0); + _this._innerStreamSubscription.cancel$0(); + _this._multi_channel$_inner = null; + for (t1 = _this._controllers, t2 = P.List_List$from(t1.get$values(), true, type$.dynamic), t3 = t2.length, _i = 0; _i < t2.length; t2.length === t3 || (0, H.throwConcurrentModificationError)(t2), ++_i) + t2[_i].get$local()._sink.close$0(0); + t1.clear$0(0); + }, + $isMultiChannel: 1 + }; + D._MultiChannel_closure.prototype = { + call$1: function(message) { + this.T._check(message); + return this.$this._multi_channel$_inner._sink.add$1(0, [0, message]); + }, + $signature: function() { + return this.T._eval$1("~(0)"); + } + }; + D._MultiChannel_closure0.prototype = { + call$0: function() { + return this.$this._closeChannel$2(0, 0); + }, + $signature: 1 + }; + D._MultiChannel_closure1.prototype = { + call$1: function(message) { + var t3, controller, + t1 = J.getInterceptor$asx(message), + id = t1.$index(message, 0), + t2 = this.$this; + if (t2._closedIds.contains$1(0, id)) + return; + H._checkIntNullable(id); + t3 = this.T; + controller = t2._controllers.putIfAbsent$2(id, new D._MultiChannel__closure(t2, id, t3)); + t2 = t1.get$length(message); + if (typeof t2 !== "number") + return t2.$gt(); + if (t2 > 1) + controller._local._sink.add$1(0, t3._check(t1.$index(message, 1))); + else + controller._local._sink.close$0(0); + }, + $signature: 3 + }; + D._MultiChannel__closure.prototype = { + call$0: function() { + this.$this._pendingIds.add$1(0, H._checkIntNullable(this.id)); + return B.StreamChannelController$(true, true, this.T); + }, + $signature: function() { + return this.T._eval$1("StreamChannelController<0>()"); + } + }; + D._MultiChannel_virtualChannel_closure.prototype = { + call$1: function(message) { + var t1 = this.$this; + t1.$ti._precomputed1._check(message); + return t1._multi_channel$_inner._sink.add$1(0, [this._box_0.outputId, message]); + }, + $signature: function() { + return this.$this.$ti._eval$1("~(1)"); + } + }; + D._MultiChannel_virtualChannel_closure0.prototype = { + call$0: function() { + var t1 = this._box_0; + return this.$this._closeChannel$2(t1.inputId, t1.outputId); + }, + $signature: 1 + }; + D.VirtualChannel.prototype = {$isMultiChannel: 1, + get$stream: function(receiver) { + return this.stream; + } + }; + N.StreamChannelCompleter.prototype = { + set$_stream_channel_completer$_channel: function(_channel) { + this._stream_channel_completer$_channel = this.$ti._eval$1("StreamChannel<1>")._check(_channel); + } + }; + B.StreamChannelController.prototype = { + get$local: function() { + return this._local; + }, + set$_local: function(_local) { + this._local = this.$ti._eval$1("StreamChannel<1>")._check(_local); + }, + set$_foreign: function(_foreign) { + this._foreign = this.$ti._eval$1("StreamChannel<1>")._check(_foreign); + } + }; + R.StreamChannel.prototype = {}; + R._StreamChannel.prototype = { + get$stream: function(receiver) { + return this.stream; + } + }; + R.StreamChannelMixin.prototype = {$isStreamChannel: 1}; + E.StringScannerException.prototype = {}; + S.SpanScanner.prototype = { + spanFrom$1: function(startState) { + var endPosition = this._string_scanner$_position; + return this._sourceFile.span$2(startState.position, endPosition); + }, + matches$1: function(_, pattern) { + var _this = this; + if (!_this.super$StringScanner$matches(0, pattern)) { + _this._lastSpan = null; + return false; + } + _this._lastSpan = _this._sourceFile.span$2(_this._string_scanner$_position, _this.get$lastMatch().get$end()); + return true; + }, + error$3$length$position: function(_, message, $length, position) { + var t1 = this.string; + B.validateErrorArgs(t1, null, position, $length); + throw H.wrapException(E.StringScannerException$(message, this._sourceFile.span$2(position, position + $length), t1)); + } + }; + S._SpanScannerState.prototype = {$isLineScannerState: 1}; + X.StringScanner.prototype = { + get$lastMatch: function() { + var _this = this; + if (_this._string_scanner$_position !== _this._lastMatchPosition) + _this._lastMatch = null; + return _this._lastMatch; + }, + peekChar$0: function() { + var index = this._string_scanner$_position; + if (index < 0 || index >= this.string.length) + return null; + return J.codeUnitAt$1$s(this.string, index); + }, + scan$1: function(pattern) { + var _this = this, + success = _this.matches$1(0, pattern); + if (success) + _this._lastMatchPosition = _this._string_scanner$_position = _this._lastMatch.get$end(); + return success; + }, + expect$2$name: function(pattern, $name) { + var t1; + if (this.scan$1(pattern)) + return; + if ($name == null) + if (type$.RegExp._is(pattern)) + $name = "/" + pattern.pattern + "/"; + else { + t1 = J.toString$0$(pattern); + t1 = H.stringReplaceAllUnchecked(t1, "\\", "\\\\"); + $name = '"' + H.stringReplaceAllUnchecked(t1, '"', '\\"') + '"'; + } + this.error$3$length$position(0, "expected " + $name + ".", 0, this._string_scanner$_position); + }, + expect$1: function(pattern) { + return this.expect$2$name(pattern, null); + }, + matches$1: function(_, pattern) { + var _this = this, + t1 = J.matchAsPrefix$2$s(pattern, _this.string, _this._string_scanner$_position); + _this._lastMatch = t1; + _this._lastMatchPosition = _this._string_scanner$_position; + return t1 != null; + } + }; + A.AsciiGlyphSet.prototype = { + glyphOrAscii$2: function(glyph, alternative) { + return alternative; + }, + get$horizontalLine: function() { + return "-"; + }, + get$verticalLine: function() { + return "|"; + }, + get$topLeftCorner: function() { + return ","; + }, + get$bottomLeftCorner: function() { + return "'"; + }, + get$upEnd: function() { + return "'"; + }, + get$downEnd: function() { + return ","; + } + }; + K.UnicodeGlyphSet.prototype = { + glyphOrAscii$2: function(glyph, alternative) { + return glyph; + }, + get$horizontalLine: function() { + return "\u2500"; + }, + get$verticalLine: function() { + return "\u2502"; + }, + get$topLeftCorner: function() { + return "\u250c"; + }, + get$bottomLeftCorner: function() { + return "\u2514"; + }, + get$upEnd: function() { + return "\u2575"; + }, + get$downEnd: function() { + return "\u2577"; + } + }; + L.internalBootstrapBrowserTest_closure.prototype = { + call$0: function() { + var $async$goto = 0, + $async$completer = P._makeAsyncAwaitCompleter(type$.Null), + $async$returnValue, t1, serialized, formatter, manager, $async$temp1; + var $async$call$0 = P._wrapJsFunctionForAsync(function($async$errorCode, $async$result) { + if ($async$errorCode === 1) + return P._asyncRethrow($async$result, $async$completer); + while (true) + switch ($async$goto) { + case 0: + // Function start + manager = type$.SuiteChannelManager._as($.Zone__current.$index(0, $.$get$_currentKey())); + if (manager == null) + H.throwExpression(P.StateError$("suiteChannel() may only be called within a test worker.")); + t1 = manager.connectOut$1("test.browser.mapper"); + t1 = t1.get$stream(t1); + $async$temp1 = type$.Map_dynamic_dynamic; + $async$goto = 3; + return P._asyncAwait(t1.get$first(t1), $async$call$0); + case 3: + // returning from await. + serialized = $async$temp1._as($async$result); + if (serialized == null) { + // goto return + $async$goto = 1; + break; + } + t1 = E.JSStackTraceMapper_deserialize(serialized); + formatter = type$.StackTraceFormatter._as($.Zone__current.$index(0, $.$get$_currentKey0())); + if (formatter == null) + H.throwExpression(P.StateError$("setStackTraceMapper() may only be called within a test worker.")); + formatter.configure$1$mapper(t1); + case 1: + // return + return P._asyncReturn($async$returnValue, $async$completer); + } + }); + return P._asyncStartSync($async$call$0, $async$completer); + }, + $signature: 2 + }; + N.postMessageChannel_closure.prototype = { + call$1: function(message) { + var t1, t2; + type$.MessageEvent._check(message); + t1 = message.origin; + t2 = window.location; + return t1 === (t2 && C.Location_methods).get$origin(t2) && J.$eq$(new P._AcceptStructuredCloneDart2Js([], []).convertNativeToDart_AcceptStructuredClone$2$mustCopy(message.data, true), "port"); + }, + $signature: 69 + }; + N.postMessageChannel_closure0.prototype = { + call$1: function(message) { + var t2, t3, portSubscription, + t1 = type$.MessageEvent, + port = J.get$first$ax(t1._check(message).ports); + port.toString; + t2 = this.controller; + t3 = type$.void_Function_MessageEvent._check(new N.postMessageChannel__closure(t2)); + type$.void_Function._check(null); + portSubscription = W._EventStreamSubscription$(port, "message", t3, false, t1); + t2 = t2._local._streamController; + t2.toString; + new P._ControllerStream(t2, H._instanceType(t2)._eval$1("_ControllerStream<1>")).listen$2$onDone(new N.postMessageChannel__closure0(port), new N.postMessageChannel__closure1(port, portSubscription)); + }, + $signature: 29 + }; + N.postMessageChannel__closure.prototype = { + call$1: function(message) { + type$.MessageEvent._check(message); + this.controller._local._sink.add$1(0, new P._AcceptStructuredCloneDart2Js([], []).convertNativeToDart_AcceptStructuredClone$2$mustCopy(message.data, true)); + }, + $signature: 29 + }; + N.postMessageChannel__closure0.prototype = { + call$1: function(data) { + C.MessagePort_methods.postMessage$1(this.port, P.LinkedHashMap_LinkedHashMap$_literal(["data", data], type$.String, type$.dynamic)); + }, + $signature: 3 + }; + N.postMessageChannel__closure1.prototype = { + call$0: function() { + var t1 = type$.String; + C.MessagePort_methods.postMessage$1(this.port, P.LinkedHashMap_LinkedHashMap$_literal(["event", "done"], t1, t1)); + this.portSubscription.cancel$0(); + }, + $signature: 0 + }; + K.ClosedException.prototype = { + toString$0: function(_) { + return "This test has been closed."; + }, + $isException: 1 + }; + X.Declarer.prototype = { + test$9$onPlatform$retry$skip$solo$tags$testOn$timeout: function($name, body, onPlatform, retry, skip, solo, tags, testOn, timeout) { + var newMetadata, metadata, t1, t2, _this = this; + type$.dynamic_Function._check(body); + type$.Map_String_dynamic._check(onPlatform); + _this._checkNotBuilt$1("test"); + newMetadata = O.Metadata$parse(onPlatform, H.boolConversionCheck(_this._noRetry) ? 0 : retry, skip, tags, testOn, timeout); + newMetadata.validatePlatformSelectors$1(_this._platformVariables); + metadata = _this._metadata.merge$1(newMetadata); + t1 = _this._declarer$_name; + t1 = t1 == null ? $name : t1 + " " + $name; + t2 = H.boolConversionCheck(_this._collectTraces) ? Y.Trace_Trace$current(2) : null; + C.JSArray_methods.add$1(_this._entries, new U.LocalTest(t1, metadata, t2, false, new X.Declarer_test_closure(_this, body), false)); + }, + group$9$onPlatform$retry$skip$solo$tags$testOn$timeout: function($name, body, onPlatform, retry, skip, solo, tags, testOn, timeout) { + var t2, newMetadata, t3, metadata, t4, trace, t5, t6, t7, t8, t9, t10, t11, t12, declarer, _this = this, _null = null, + t1 = type$.void_Function; + t1._check(body); + type$.Map_String_dynamic._check(onPlatform); + _this._checkNotBuilt$1("group"); + t2 = H.boolConversionCheck(_this._noRetry); + newMetadata = O.Metadata$parse(onPlatform, t2 ? 0 : retry, skip, tags, testOn, timeout); + t3 = _this._platformVariables; + newMetadata.validatePlatformSelectors$1(t3); + metadata = _this._metadata.merge$1(newMetadata); + t4 = H.boolConversionCheck(_this._collectTraces); + trace = t4 ? Y.Trace_Trace$current(2) : _null; + t5 = _this._declarer$_name; + t5 = t5 == null ? $name : t5 + " " + $name; + t6 = type$.JSArray_of_dynamic_Function; + t7 = H.setRuntimeTypeInfo([], t6); + t8 = H.setRuntimeTypeInfo([], t6); + t9 = H.setRuntimeTypeInfo([], t6); + t10 = P.Duration$(0, 12); + t6 = H.setRuntimeTypeInfo([], t6); + t11 = type$.JSArray_GroupEntry; + t12 = H.setRuntimeTypeInfo([], t11); + t11 = H.setRuntimeTypeInfo([], t11); + declarer = new X.Declarer(_this, t5, metadata, t3, trace, t4, t2, t7, t8, t9, new R.Timeout(t10, _null), t6, t12, t11); + t12 = type$.dynamic; + P.runZoned(t1._check(new X.Declarer_group_closure(body)), _null, _null, P.LinkedHashMap_LinkedHashMap$_literal([C.Symbol_Drw, declarer], t12, t12), type$.void); + t12 = _this._entries; + C.JSArray_methods.add$1(t12, declarer.build$0()); + t1 = t11.length; + if (t1 !== 0) + C.JSArray_methods.add$1(_this._soloEntries, C.JSArray_methods.get$last(t12)); + }, + build$0: function() { + var t1, t2, _this = this; + _this._checkNotBuilt$1("build"); + _this._built = true; + t1 = _this._entries; + t2 = H._arrayInstanceType(t1); + return O.Group$(_this._declarer$_name, new H.MappedListIterable(t1, t2._eval$1("GroupEntry(1)")._check(new X.Declarer_build_closure(_this)), t2._eval$1("MappedListIterable<1,GroupEntry>")).toList$0(0), _this._metadata, _this.get$_setUpAll(), _this.get$_tearDownAll(), _this._declarer$_trace); + }, + _checkNotBuilt$1: function($name) { + if (!this._built) + return; + throw H.wrapException(P.StateError$("Can't call " + $name + "() once tests have begun running.")); + }, + _runSetUps$0: function() { + var $async$goto = 0, + $async$completer = P._makeAsyncAwaitCompleter(type$.dynamic), + $async$self = this, t1; + var $async$_runSetUps$0 = P._wrapJsFunctionForAsync(function($async$errorCode, $async$result) { + if ($async$errorCode === 1) + return P._asyncRethrow($async$result, $async$completer); + while (true) + switch ($async$goto) { + case 0: + // Function start + t1 = $async$self._declarer$_parent; + $async$goto = t1 != null ? 2 : 3; + break; + case 2: + // then + $async$goto = 4; + return P._asyncAwait(t1._runSetUps$0(), $async$_runSetUps$0); + case 4: + // returning from await. + case 3: + // join + $async$goto = 5; + return P._asyncAwait(P.Future_forEach($async$self._setUps, new X.Declarer__runSetUps_closure(), type$.dynamic_Function), $async$_runSetUps$0); + case 5: + // returning from await. + // implicit return + return P._asyncReturn(null, $async$completer); + } + }); + return P._asyncStartSync($async$_runSetUps$0, $async$completer); + }, + get$_setUpAll: function() { + return null; + }, + get$_tearDownAll: function() { + var _this = this, + t1 = _this._tearDownAlls.length; + if (t1 === 0) + return null; + t1 = _this._declarer$_name; + t1 = t1 == null ? "(tearDownAll)" : t1 + " (tearDownAll)"; + return new U.LocalTest(t1, _this._metadata.change$1$timeout(_this._timeout), null, true, new X.Declarer__tearDownAll_closure(_this), false); + } + }; + X.Declarer_test_closure.prototype = { + call$0: function() { + var $async$goto = 0, + $async$completer = P._makeAsyncAwaitCompleter(type$.Null), + $async$returnValue, $async$self = this, declarer, declarer0, t1, t2, t3, t4, t5, _i, tearDown, t6, parents; + var $async$call$0 = P._wrapJsFunctionForAsync(function($async$errorCode, $async$result) { + if ($async$errorCode === 1) + return P._asyncRethrow($async$result, $async$completer); + while (true) + $async$outer: + switch ($async$goto) { + case 0: + // Function start + parents = H.setRuntimeTypeInfo([], type$.JSArray_Declarer); + for (declarer = $async$self.$this, declarer0 = declarer; declarer0 != null; declarer0 = declarer0._declarer$_parent) + C.JSArray_methods.add$1(parents, declarer0); + for (t1 = type$.ReversedListIterable_Declarer, t2 = new H.ReversedListIterable(parents, t1), t1 = new H.ListIterator(t2, t2.get$length(t2), t1._eval$1("ListIterator<ListIterable.E>")), t2 = type$.Invoker, t3 = type$.dynamic_Function, t4 = type$.Declarer; t1.moveNext$0();) + for (t5 = t1.__internal$_current._tearDowns, _i = 0; false; ++_i) { + if (_i >= 0) { + $async$returnValue = H.ioore(t5, _i); + // goto return + $async$goto = 1; + break $async$outer; + } + tearDown = t5[_i]; + t6 = t2._as($.Zone__current.$index(0, C.Symbol_cQL)); + t6.toString; + t3._check(tearDown); + if (H.boolConversionCheck(H._asBoolNullable($.Zone__current.$index(0, t6._closableKey))) && t6._onCloseCompleter.future._state !== 0) + H.throwExpression(K.ClosedException$()); + if (t6._invoker$_controller._liveTest._live_test_controller$_controller._test.isScaffoldAll) + C.JSArray_methods.add$1(t4._as($.Zone__current.$index(0, C.Symbol_Drw))._tearDownAlls, tearDown); + else + C.JSArray_methods.add$1(t6._invoker$_tearDowns, tearDown); + } + t1 = type$.dynamic; + $async$goto = 3; + return P._asyncAwait(P.runZoned(new X.Declarer_test__closure(declarer, $async$self.body), null, null, P.LinkedHashMap_LinkedHashMap$_literal([C.Symbol_Drw, declarer], t1, t1), type$.Future_void), $async$call$0); + case 3: + // returning from await. + case 1: + // return + return P._asyncReturn($async$returnValue, $async$completer); + } + }); + return P._asyncStartSync($async$call$0, $async$completer); + }, + $signature: 2 + }; + X.Declarer_test__closure.prototype = { + call$0: function() { + return type$.Invoker._as($.Zone__current.$index(0, C.Symbol_cQL)).waitForOutstandingCallbacks$1(new X.Declarer_test___closure(this.$this, this.body)); + }, + $signature: 13 + }; + X.Declarer_test___closure.prototype = { + call$0: function() { + var $async$goto = 0, + $async$completer = P._makeAsyncAwaitCompleter(type$.Null), + $async$self = this; + var $async$call$0 = P._wrapJsFunctionForAsync(function($async$errorCode, $async$result) { + if ($async$errorCode === 1) + return P._asyncRethrow($async$result, $async$completer); + while (true) + switch ($async$goto) { + case 0: + // Function start + $async$goto = 2; + return P._asyncAwait($async$self.$this._runSetUps$0(), $async$call$0); + case 2: + // returning from await. + $async$goto = 3; + return P._asyncAwait($async$self.body.call$0(), $async$call$0); + case 3: + // returning from await. + // implicit return + return P._asyncReturn(null, $async$completer); + } + }); + return P._asyncStartSync($async$call$0, $async$completer); + }, + $signature: 2 + }; + X.Declarer_group_closure.prototype = { + call$0: function() { + if (!type$.Future_dynamic._is(this.body.call$0())) + return; + throw H.wrapException(P.ArgumentError$("Groups may not be async.")); + }, + $signature: 0 + }; + X.Declarer_build_closure.prototype = { + call$1: function(entry) { + var t1; + type$.GroupEntry._check(entry); + t1 = this.$this._soloEntries; + return t1.length !== 0 && !C.JSArray_methods.contains$1(t1, entry) ? new U.LocalTest(entry.get$name(entry), entry.get$metadata().change$2$skip$skipReason(true, 'does not have "solo"'), null, false, null, true) : entry; + }, + $signature: 22 + }; + X.Declarer__runSetUps_closure.prototype = { + call$1: function(setUp) { + return setUp.call$0(); + }, + $signature: 18 + }; + X.Declarer__tearDownAll_closure.prototype = { + call$0: function() { + var t1 = this.$this, + t2 = type$.dynamic; + return P.runZoned(new X.Declarer__tearDownAll__closure(t1), null, null, P.LinkedHashMap_LinkedHashMap$_literal([C.Symbol_Drw, t1], t2, t2), type$.Future_Null); + }, + $signature: 2 + }; + X.Declarer__tearDownAll__closure.prototype = { + call$0: function() { + return type$.Invoker._as($.Zone__current.$index(0, C.Symbol_cQL)).unclosable$1$1(new X.Declarer__tearDownAll___closure(this.$this), type$.Future_Null); + }, + $signature: 2 + }; + X.Declarer__tearDownAll___closure.prototype = { + call$0: function() { + var $async$goto = 0, + $async$completer = P._makeAsyncAwaitCompleter(type$.Null), + $async$returnValue, $async$self = this, t1, t2; + var $async$call$0 = P._wrapJsFunctionForAsync(function($async$errorCode, $async$result) { + if ($async$errorCode === 1) + return P._asyncRethrow($async$result, $async$completer); + while (true) + switch ($async$goto) { + case 0: + // Function start + t1 = $async$self.$this._tearDownAlls; + case 3: + // for condition + if (!(t2 = t1.length, t2 !== 0)) { + // goto after for + $async$goto = 4; + break; + } + if (0 >= t2) { + $async$returnValue = H.ioore(t1, -1); + // goto return + $async$goto = 1; + break; + } + $async$goto = 5; + return P._asyncAwait(V.errorsDontStopTest(t1.pop()), $async$call$0); + case 5: + // returning from await. + // goto for condition + $async$goto = 3; + break; + case 4: + // after for + case 1: + // return + return P._asyncReturn($async$returnValue, $async$completer); + } + }); + return P._asyncStartSync($async$call$0, $async$completer); + }, + $signature: 2 + }; + O.Group.prototype = { + forPlatform$1: function(platform) { + var newMetadata, filtered, _this = this, + t1 = _this.metadata; + if (!H.boolConversionCheck(t1.testOn.evaluate$1(platform))) + return null; + newMetadata = t1.forPlatform$1(platform); + filtered = _this._group$_map$1(new O.Group_forPlatform_closure(platform)); + if (filtered.length === 0 && _this.entries.length !== 0) + return null; + return O.Group$(_this.name, filtered, newMetadata, _this.setUpAll, _this.tearDownAll, _this.trace); + }, + _group$_map$1: function(callback) { + var t1 = this.entries, + t2 = H._arrayInstanceType(t1), + t3 = t2._eval$1("MappedListIterable<1,GroupEntry>"); + t3 = new H.MappedListIterable(t1, t2._eval$1("GroupEntry(1)")._check(new O.Group__map_closure(type$.GroupEntry_Function_GroupEntry._check(callback))), t3).super$Iterable$where(0, t3._eval$1("bool(ListIterable.E)")._check(new O.Group__map_closure0())); + return P.List_List$from(t3, true, t3.$ti._eval$1("Iterable.E")); + }, + $isGroupEntry: 1, + get$name: function(receiver) { + return this.name; + }, + get$metadata: function() { + return this.metadata; + } + }; + O.Group_forPlatform_closure.prototype = { + call$1: function(entry) { + return entry.forPlatform$1(this.platform); + }, + $signature: 22 + }; + O.Group__map_closure.prototype = { + call$1: function(entry) { + return this.callback.call$1(type$.GroupEntry._check(entry)); + }, + $signature: 22 + }; + O.Group__map_closure0.prototype = { + call$1: function(entry) { + return type$.GroupEntry._check(entry) != null; + }, + $signature: 72 + }; + V.GroupEntry.prototype = {}; + U.LocalTest.prototype = { + load$2$groups: function(suite, groups) { + var t1, invoker; + type$.Iterable_Group._check(groups); + t1 = new P._AsyncCompleter(new P._Future($.Zone__current, type$._Future_void), type$._AsyncCompleter_void); + invoker = new U.Invoker(this._guarded, new P.Object(), t1, H.setRuntimeTypeInfo([], type$.JSArray_Zone), new P.Object(), H.setRuntimeTypeInfo([], type$.JSArray_of_dynamic_Function), H.setRuntimeTypeInfo([], type$.JSArray_String)); + t1 = V.LiveTestController$(suite, this, invoker.get$_invoker$_onRun(), t1.get$complete(), groups); + invoker._invoker$_controller = t1; + return t1._liveTest; + }, + forPlatform$1: function(platform) { + var _this = this, + t1 = _this.metadata; + if (!H.boolConversionCheck(t1.testOn.evaluate$1(platform))) + return null; + return new U.LocalTest(_this.name, t1.forPlatform$1(platform), _this.trace, _this.isScaffoldAll, _this._body, _this._guarded); + }, + get$name: function(receiver) { + return this.name; + }, + get$metadata: function() { + return this.metadata; + } + }; + U.Invoker.prototype = { + get$_outstandingCallbacks: function() { + var counter = type$._AsyncCounter._as($.Zone__current.$index(0, this._counterKey)); + if (counter != null) + return counter; + throw H.wrapException(P.StateError$("Can't add or remove outstanding callbacks outside of a test body.")); + }, + addOutstandingCallback$0: function() { + if (H.boolConversionCheck(H._asBoolNullable($.Zone__current.$index(0, this._closableKey))) && this._onCloseCompleter.future._state !== 0) + throw H.wrapException(K.ClosedException$()); + ++this.get$_outstandingCallbacks()._count; + }, + waitForOutstandingCallbacks$1: function(fn) { + var t2, counter, t3, _this = this, t1 = {}; + type$.FutureOr_void_Function._check(fn); + _this.heartbeat$0(); + t1.zone = null; + t2 = new P._Future($.Zone__current, type$._Future_void); + counter = new U._AsyncCounter(new P._AsyncCompleter(t2, type$._AsyncCompleter_void)); + t3 = type$.dynamic; + P.runZoned(new U.Invoker_waitForOutstandingCallbacks_closure(t1, _this, fn, counter), null, null, P.LinkedHashMap_LinkedHashMap$_literal([_this._counterKey, counter], t3, t3), type$.Future_Null); + return t2.whenComplete$1(new U.Invoker_waitForOutstandingCallbacks_closure0(t1, _this)); + }, + unclosable$1$1: function(fn, $T) { + var t1; + $T._eval$1("0()")._check(fn); + this.heartbeat$0(); + t1 = type$.dynamic; + return P.runZoned(fn, null, null, P.LinkedHashMap_LinkedHashMap$_literal([this._closableKey, false], t1, t1), $T); + }, + heartbeat$0: function() { + var t1, timeout, _this = this; + if (_this._invoker$_controller._liveTest._live_test_controller$_controller._live_test_controller$_state.status === C.Status_complete) + return; + t1 = _this._timeoutTimer; + if (t1 != null) + t1.cancel$0(); + timeout = _this._invoker$_controller._liveTest._live_test_controller$_controller._test.metadata.timeout.apply$1(C.Duration_30000000); + if (timeout == null) + return; + _this._timeoutTimer = _this._invokerZone.createTimer$2(timeout, new U.Invoker_heartbeat_closure(_this, new U.Invoker_heartbeat_message(timeout), timeout)); + }, + _handleError$3: function(zone, error, stackTrace) { + var t2, t3, t4, shouldBeDone, _this = this, t1 = {}; + t1.stackTrace = stackTrace; + if (_this._runCount !== zone.$index(0, C.Symbol_runCount)) + return; + zone.run$1$1(new U.Invoker__handleError_closure(t1), type$.Null); + t2 = _this._invoker$_controller; + t3 = t2._liveTest._live_test_controller$_controller._live_test_controller$_state; + if (t3.status === C.Status_complete) { + t4 = t3.result; + shouldBeDone = t4 === C.Result_success || t4 === C.Result_skipped; + } else + shouldBeDone = false; + if (!(error instanceof G.TestFailure)) + t2.setState$1(C.State_Status_complete_Result_error); + else if (t3.result !== C.Result_error) + t2.setState$1(C.State_Status_complete_Result_failure); + _this._invoker$_controller.addError$2(error, t1.stackTrace); + zone.run$1$1(new U.Invoker__handleError_closure0(_this), type$.void); + t2 = _this._invoker$_controller._liveTest._live_test_controller$_controller; + if (t2._test.metadata._chainStackTraces === false) + C.JSArray_methods.add$1(_this._printsOnFailure, "Consider enabling the flag chain-stack-traces to receive more detailed exceptions.\nFor example, 'pub run test --chain-stack-traces'."); + t2 = _this._printsOnFailure; + if (t2.length !== 0) { + P.print(C.JSArray_methods.join$1(t2, "\n\n")); + C.JSArray_methods.set$length(t2, 0); + } + if (!shouldBeDone) + return; + _this._invoker$_controller._liveTest._live_test_controller$_controller._live_test_controller$_suite.toString; + _this._handleError$3(zone, "This test failed after it had already completed. Make sure to use [expectAsync]\nor the [completes] matcher when testing async code.", t1.stackTrace); + }, + _handleError$2: function(zone, error) { + return this._handleError$3(zone, error, null); + }, + _invoker$_onRun$0: function() { + var t1, t2, _this = this; + _this._invoker$_controller.setState$1(C.State_Status_running_Result_success); + t1 = $.Zone__current; + ++_this._runCount; + t2 = _this._invoker$_controller._liveTest._live_test_controller$_controller; + U.Chain_capture(new U.Invoker__onRun_closure(_this, new U._AsyncCounter(new P._AsyncCompleter(new P._Future(t1, type$._Future_void), type$._AsyncCompleter_void))), false, t2._test.metadata._chainStackTraces !== false, type$.Null); + }, + _runTearDowns$0: function() { + var $async$goto = 0, + $async$completer = P._makeAsyncAwaitCompleter(type$.void), + $async$returnValue, $async$self = this, t1, t2; + var $async$_runTearDowns$0 = P._wrapJsFunctionForAsync(function($async$errorCode, $async$result) { + if ($async$errorCode === 1) + return P._asyncRethrow($async$result, $async$completer); + while (true) + switch ($async$goto) { + case 0: + // Function start + t1 = $async$self._invoker$_tearDowns; + case 3: + // for condition + if (!(t2 = t1.length, t2 !== 0)) { + // goto after for + $async$goto = 4; + break; + } + if (0 >= t2) { + $async$returnValue = H.ioore(t1, -1); + // goto return + $async$goto = 1; + break; + } + $async$goto = 5; + return P._asyncAwait(V.errorsDontStopTest(t1.pop()), $async$_runTearDowns$0); + case 5: + // returning from await. + // goto for condition + $async$goto = 3; + break; + case 4: + // after for + case 1: + // return + return P._asyncReturn($async$returnValue, $async$completer); + } + }); + return P._asyncStartSync($async$_runTearDowns$0, $async$completer); + } + }; + U.Invoker_guard_closure.prototype = { + call$5: function($self, _, zone, error, stackTrace) { + var invoker; + type$.StackTrace._check(stackTrace); + invoker = zone.$index(0, C.Symbol_cQL); + if (invoker != null) + $self.get$parent($self).run$1$1(new U.Invoker_guard__closure(invoker, zone, error, stackTrace), type$.dynamic); + else + $self.get$parent($self).handleUncaughtError$2(error, stackTrace); + }, + $signature: 28 + }; + U.Invoker_guard__closure.prototype = { + call$0: function() { + var _this = this; + return _this.invoker._handleError$3(_this.zone, _this.error, _this.stackTrace); + }, + $signature: 34 + }; + U.Invoker_waitForOutstandingCallbacks_closure.prototype = { + call$0: function() { + var $async$goto = 0, + $async$completer = P._makeAsyncAwaitCompleter(type$.Null), + $async$self = this, zone; + var $async$call$0 = P._wrapJsFunctionForAsync(function($async$errorCode, $async$result) { + if ($async$errorCode === 1) + return P._asyncRethrow($async$result, $async$completer); + while (true) + switch ($async$goto) { + case 0: + // Function start + zone = $.Zone__current; + $async$self._box_0.zone = zone; + C.JSArray_methods.add$1($async$self.$this._outstandingCallbackZones, zone); + $async$goto = 2; + return P._asyncAwait($async$self.fn.call$0(), $async$call$0); + case 2: + // returning from await. + $async$self.counter.decrement$0(); + // implicit return + return P._asyncReturn(null, $async$completer); + } + }); + return P._asyncStartSync($async$call$0, $async$completer); + }, + $signature: 2 + }; + U.Invoker_waitForOutstandingCallbacks_closure0.prototype = { + call$0: function() { + C.JSArray_methods.remove$1(this.$this._outstandingCallbackZones, this._box_0.zone); + }, + $signature: 0 + }; + U.Invoker_heartbeat_message.prototype = { + call$0: function() { + var message, + t1 = this.timeout._duration, + minutes = C.JSInt_methods._tdivFast$1(t1, 60000000), + seconds = C.JSInt_methods.$mod(C.JSInt_methods._tdivFast$1(t1, 1000000), 60), + decaseconds = C.JSInt_methods._tdivFast$1(C.JSInt_methods.$mod(C.JSInt_methods._tdivFast$1(t1, 1000), 1000), 100), + t2 = minutes !== 0, + t3 = t2 ? "" + minutes + " minutes" : ""; + if (!t2 || seconds !== 0) { + t2 = t2 ? t3 + ", " : t3; + t2 += seconds; + t2 = (decaseconds !== 0 ? t2 + ("." + decaseconds) : t2) + " seconds"; + } else + t2 = t3; + message = "Test timed out after " + (t2.charCodeAt(0) == 0 ? t2 : t2) + "."; + return t1 === 30000000 ? message + " See https://pub.dev/packages/test#timeouts" : message; + }, + $signature: 74 + }; + U.Invoker_heartbeat_closure.prototype = { + call$0: function() { + var t1 = this.$this; + C.JSArray_methods.get$last(t1._outstandingCallbackZones).run$1$1(new U.Invoker_heartbeat__closure(t1, this.message, this.timeout), type$.Null); + }, + $signature: 0 + }; + U.Invoker_heartbeat__closure.prototype = { + call$0: function() { + var t1 = this.$this; + if (t1._invoker$_controller._liveTest._live_test_controller$_controller._live_test_controller$_state.status === C.Status_complete) + return; + t1._handleError$2($.Zone__current, new P.TimeoutException(this.message.call$0(), this.timeout)); + }, + $signature: 0 + }; + U.Invoker__handleError_closure.prototype = { + call$0: function() { + var t1 = this._box_0, + t2 = t1.stackTrace; + if (t2 == null) + t1.stackTrace = U.Chain_Chain$current(); + else + t1.stackTrace = U.Chain_Chain$forTrace(t2); + }, + $signature: 0 + }; + U.Invoker__handleError_closure0.prototype = { + call$0: function() { + var t1 = this.$this.get$_outstandingCallbacks()._invoker$_completer; + if (t1.future._state === 0) + t1.complete$0(); + return null; + }, + $signature: 1 + }; + U.Invoker__onRun_closure.prototype = { + call$0: function() { + var t1 = this.$this, + t2 = type$.void_Function._check(new U.Invoker__onRun__closure(t1, this.outstandingCallbacksForBody)); + if (t1._guarded) + U.Invoker_guard(t2, type$.void); + else + t2.call$0(); + }, + $signature: 0 + }; + U.Invoker__onRun__closure.prototype = { + call$0: function() { + var _null = null, + t1 = this.$this, + t2 = type$.dynamic; + t2 = P.LinkedHashMap_LinkedHashMap$_literal([C.Symbol_cQL, t1, t1._counterKey, this.outstandingCallbacksForBody, t1._closableKey, true, C.Symbol_runCount, t1._runCount], t2, t2); + P.runZoned(new U.Invoker__onRun___closure(t1), _null, P._ZoneSpecification$(_null, _null, _null, _null, _null, new U.Invoker__onRun___closure0(t1), _null, _null, _null, _null, _null, _null, _null), t2, type$.Future_Null); + }, + $signature: 0 + }; + U.Invoker__onRun___closure.prototype = { + call$0: function() { + var $async$goto = 0, + $async$completer = P._makeAsyncAwaitCompleter(type$.Null), + $async$returnValue, $async$self = this, t3, t4, t5, t6, t1, t2; + var $async$call$0 = P._wrapJsFunctionForAsync(function($async$errorCode, $async$result) { + if ($async$errorCode === 1) + return P._asyncRethrow($async$result, $async$completer); + while (true) + switch ($async$goto) { + case 0: + // Function start + t1 = $async$self.$this; + t2 = $.Zone__current; + t1._invokerZone = t2; + C.JSArray_methods.add$1(t1._outstandingCallbackZones, t2); + P.Future_Future(new U.Invoker__onRun____closure(t1), type$.void); + $async$goto = 3; + return P._asyncAwait(t1.get$_outstandingCallbacks()._invoker$_completer.future, $async$call$0); + case 3: + // returning from await. + t2 = t1._timeoutTimer; + if (t2 != null) + t2.cancel$0(); + t2 = t1._invoker$_controller; + t3 = t2._liveTest._live_test_controller$_controller; + t4 = t3._live_test_controller$_state.result; + if (t4 !== C.Result_success) { + t5 = t1._runCount; + t6 = t3._test.metadata._retry; + t5 = t5 < (t6 == null ? 0 : t6) + 1; + } else + t5 = false; + if (t5) { + t2.message$1(0, new D.Message(C.MessageType_print, "Retry: " + H.S(t3._test.name))); + t1._invoker$_onRun$0(); + // goto return + $async$goto = 1; + break; + } + t2.setState$1(new G.State(C.Status_complete, t4)); + t1._invoker$_controller.completer.complete$0(); + case 1: + // return + return P._asyncReturn($async$returnValue, $async$completer); + } + }); + return P._asyncStartSync($async$call$0, $async$completer); + }, + $signature: 2 + }; + U.Invoker__onRun____closure.prototype = { + call$0: function() { + var $async$goto = 0, + $async$completer = P._makeAsyncAwaitCompleter(type$.Null), + $async$self = this, t1; + var $async$call$0 = P._wrapJsFunctionForAsync(function($async$errorCode, $async$result) { + if ($async$errorCode === 1) + return P._asyncRethrow($async$result, $async$completer); + while (true) + switch ($async$goto) { + case 0: + // Function start + t1 = $async$self.$this; + $async$goto = 2; + return P._asyncAwait(t1._invoker$_controller._liveTest._live_test_controller$_controller._test._body.call$0(), $async$call$0); + case 2: + // returning from await. + $async$goto = 3; + return P._asyncAwait(t1.unclosable$1$1(t1.get$_runTearDowns(), type$.Future_void), $async$call$0); + case 3: + // returning from await. + t1.heartbeat$0(); + t1.get$_outstandingCallbacks().decrement$0(); + // implicit return + return P._asyncReturn(null, $async$completer); + } + }); + return P._asyncStartSync($async$call$0, $async$completer); + }, + $signature: 2 + }; + U.Invoker__onRun___closure0.prototype = { + call$4: function(_, __, ___, line) { + H._checkStringNullable(line); + return this.$this._invoker$_controller.message$1(0, new D.Message(C.MessageType_print, line)); + }, + $signature: 37 + }; + U._AsyncCounter.prototype = { + decrement$0: function() { + if (--this._count !== 0) + return; + var t1 = this._invoker$_completer; + if (t1.future._state !== 0) + return; + t1.complete$0(); + } + }; + Z.LiveTest.prototype = {}; + V._LiveTest.prototype = { + run$0: function() { + var t1 = this._live_test_controller$_controller; + if (t1._runCalled) + H.throwExpression(P.StateError$("LiveTest.run() may not be called more than once.")); + else if ((t1._onErrorController._state & 4) !== 0) + H.throwExpression(P.StateError$("LiveTest.run() may not be called for a closed test.")); + t1._runCalled = true; + t1._onRun.call$0(); + return t1._liveTest._live_test_controller$_controller.completer.future; + } + }; + V.LiveTestController.prototype = { + addError$2: function(error, stackTrace) { + var asyncError, + t1 = this._onErrorController; + if ((t1._state & 4) !== 0) + return; + asyncError = new P.AsyncError(error, U.Chain_Chain$forTrace(stackTrace)); + C.JSArray_methods.add$1(this._errors, asyncError); + t1.add$1(0, asyncError); + }, + setState$1: function(newState) { + var _this = this; + if ((_this._onErrorController._state & 4) !== 0) + return; + if (_this._live_test_controller$_state.$eq(0, newState)) + return; + _this._live_test_controller$_state = newState; + _this._onStateChangeController.add$1(0, newState); + }, + message$1: function(_, message) { + var t1 = this._onMessageController; + if (t1._firstSubscription != null) + t1.add$1(0, message); + else + H.printString(message.text); + }, + _live_test_controller$_run$0: function() { + var _this = this; + if (_this._runCalled) + throw H.wrapException(P.StateError$("LiveTest.run() may not be called more than once.")); + else if ((_this._onErrorController._state & 4) !== 0) + throw H.wrapException(P.StateError$("LiveTest.run() may not be called for a closed test.")); + _this._runCalled = true; + _this._onRun.call$0(); + return _this._liveTest._live_test_controller$_controller.completer.future; + }, + _live_test_controller$_close$0: function() { + var _this = this, + t1 = _this._onErrorController; + if ((t1._state & 4) !== 0) + return _this.completer.future; + _this._onStateChangeController.close$0(0); + t1.close$0(0); + if (_this._runCalled) + _this._onClose.call$0(); + else + _this.completer.complete$0(); + return _this.completer.future; + } + }; + D.Message.prototype = {}; + D.MessageType.prototype = { + toString$0: function(_) { + return this.name; + } + }; + O.Metadata.prototype = { + _validateTags$0: function() { + var t1 = this.tags.where$1(0, new O.Metadata__validateTags_closure()), + t2 = t1.$ti, + t3 = t2._eval$1("MappedIterable<1,String>"), + invalidTags = P.List_List$from(new H.MappedIterable(t1, t2._eval$1("String(1)")._check(new O.Metadata__validateTags_closure0()), t3), true, t3._eval$1("Iterable.E")); + t1 = invalidTags.length; + if (t1 === 0) + return; + throw H.wrapException(P.ArgumentError$("Invalid " + B.pluralize("tag", t1) + " " + H.S(B.toSentence(invalidTags)) + ". Tags must be (optionally hyphenated) Dart identifiers.")); + }, + validatePlatformSelectors$1: function(validVariables) { + type$.Set_String._check(validVariables); + this.testOn.validate$1(validVariables); + this.onPlatform.forEach$1(0, new O.Metadata_validatePlatformSelectors_closure(validVariables)); + }, + merge$1: function(other) { + var t4, t5, t6, t7, t8, t9, t10, _this = this, + t1 = _this.testOn.intersection$1(other.testOn), + t2 = _this.timeout.merge$1(other.timeout), + t3 = other._skip; + if (t3 == null) + t3 = _this._skip; + t4 = other.skipReason; + if (t4 == null) + t4 = _this.skipReason; + t5 = other._verboseTrace; + if (t5 == null) + t5 = _this._verboseTrace; + t6 = other._chainStackTraces; + if (t6 == null) + t6 = _this._chainStackTraces; + t7 = other._retry; + if (t7 == null) + t7 = _this._retry; + t8 = _this.tags.union$1(other.tags); + t9 = type$.Metadata; + t10 = Y.mergeMaps(_this.onPlatform, other.onPlatform, new O.Metadata_merge_closure(), type$.PlatformSelector, t9); + return O.Metadata_Metadata(t6, Y.mergeMaps(_this.forTag, other.forTag, new O.Metadata_merge_closure0(), type$.BooleanSelector, t9), t10, t7, t3, t4, t8, t1, t2, t5); + }, + change$4$onPlatform$skip$skipReason$timeout: function(onPlatform, skip, skipReason, timeout) { + var _this = this; + type$.Map_PlatformSelector_Metadata._check(onPlatform); + type$.Set_String._check(null); + type$.Map_BooleanSelector_Metadata._check(null); + if (timeout == null) + timeout = _this.timeout; + if (skip == null) + skip = _this._skip; + if (skipReason == null) + skipReason = _this.skipReason; + if (onPlatform == null) + onPlatform = _this.onPlatform; + return O.Metadata_Metadata(_this._chainStackTraces, _this.forTag, onPlatform, _this._retry, skip, skipReason, _this.tags, _this.testOn, timeout, _this._verboseTrace); + }, + change$1$onPlatform: function(onPlatform) { + return this.change$4$onPlatform$skip$skipReason$timeout(onPlatform, null, null, null); + }, + change$1$timeout: function(timeout) { + return this.change$4$onPlatform$skip$skipReason$timeout(null, null, null, timeout); + }, + change$2$skip$skipReason: function(skip, skipReason) { + return this.change$4$onPlatform$skip$skipReason$timeout(null, skip, skipReason, null); + }, + forPlatform$1: function(platform) { + var t1 = {}, + t2 = this.onPlatform; + if (t2.get$isEmpty(t2)) + return this; + t1.metadata = this; + t2.forEach$1(0, new O.Metadata_forPlatform_closure(t1, platform)); + return t1.metadata.change$1$onPlatform(P.LinkedHashMap_LinkedHashMap$_empty(type$.PlatformSelector, type$.Metadata)); + }, + serialize$0: function() { + var t1, t2, t3, _this = this, serializedOnPlatform = []; + _this.onPlatform.forEach$1(0, new O.Metadata_serialize_closure(serializedOnPlatform)); + t1 = _this.testOn._platform_selector$_inner; + t2 = J.getInterceptor$(t1); + t3 = t2.$eq(t1, C.C_All); + t1 = t3 ? null : t2.toString$0(t1); + t2 = type$.String; + return P.LinkedHashMap_LinkedHashMap$_literal(["testOn", t1, "timeout", _this._serializeTimeout$1(_this.timeout), "skip", _this._skip, "skipReason", _this.skipReason, "verboseTrace", _this._verboseTrace, "chainStackTraces", _this._chainStackTraces, "retry", _this._retry, "tags", _this.tags.toList$0(0), "onPlatform", serializedOnPlatform, "forTag", _this.forTag.map$2$1(0, new O.Metadata_serialize_closure0(), t2, type$.Map_String_dynamic)], t2, type$.dynamic); + }, + _serializeTimeout$1: function(timeout) { + var t1; + if (timeout.$eq(0, C.Timeout_null_null)) + return "none"; + t1 = timeout.duration; + t1 = t1 == null ? null : t1._duration; + return P.LinkedHashMap_LinkedHashMap$_literal(["duration", t1, "scaleFactor", timeout.scaleFactor], type$.String, type$.num); + } + }; + O.Metadata_Metadata__unresolved.prototype = { + call$0: function() { + var _this = this, + t1 = _this._box_0, + t2 = t1.tags; + return O.Metadata$_(_this.chainStackTraces, t1.forTag, _this.onPlatform, _this.retry, _this.skip, _this.skipReason, t2, _this.testOn, _this.timeout, _this.verboseTrace); + }, + $signature: 77 + }; + O.Metadata_Metadata_closure.prototype = { + call$2: function(merged, selector) { + var t1, t2; + type$.Metadata._check(merged); + type$.BooleanSelector._check(selector); + t1 = this._box_0; + t2 = t1.tags; + if (!H.boolConversionCheck(selector.evaluate$1(t2.get$contains(t2)))) + return merged; + return merged.merge$1(t1.forTag.remove$1(0, selector)); + }, + $signature: 78 + }; + O.Metadata$deserialize_closure.prototype = { + call$2: function(key, nested) { + return new P.MapEntry(new Y.BooleanSelectorImpl(new G.Parser(new O.Scanner(S.SpanScanner$(H._asStringNullable(key)))).parse$0()), O.Metadata$deserialize(nested), type$.MapEntry_BooleanSelector_Metadata); + }, + $signature: 79 + }; + O.Metadata__validateTags_closure.prototype = { + call$1: function(tag) { + return !J.contains$1$asx(H._checkStringNullable(tag), $.$get$anchoredHyphenatedIdentifier()); + }, + $signature: 4 + }; + O.Metadata__validateTags_closure0.prototype = { + call$1: function(tag) { + return '"' + H.S(H._checkStringNullable(tag)) + '"'; + }, + $signature: 7 + }; + O.Metadata_validatePlatformSelectors_closure.prototype = { + call$2: function(selector, metadata) { + var t1; + type$.PlatformSelector._check(selector); + type$.Metadata._check(metadata); + t1 = this.validVariables; + selector.validate$1(t1); + metadata.validatePlatformSelectors$1(t1); + }, + $signature: 19 + }; + O.Metadata_merge_closure.prototype = { + call$2: function(metadata1, metadata2) { + var t1 = type$.Metadata; + return t1._check(metadata1).merge$1(t1._check(metadata2)); + }, + $signature: 44 + }; + O.Metadata_merge_closure0.prototype = { + call$2: function(metadata1, metadata2) { + var t1 = type$.Metadata; + return t1._check(metadata1).merge$1(t1._check(metadata2)); + }, + $signature: 44 + }; + O.Metadata_forPlatform_closure.prototype = { + call$2: function(platformSelector, platformMetadata) { + var t1; + type$.PlatformSelector._check(platformSelector); + type$.Metadata._check(platformMetadata); + if (!H.boolConversionCheck(platformSelector.evaluate$1(this.platform))) + return; + t1 = this._box_0; + t1.metadata = t1.metadata.merge$1(platformMetadata); + }, + $signature: 19 + }; + O.Metadata_serialize_closure.prototype = { + call$2: function(key, value) { + type$.PlatformSelector._check(key); + type$.Metadata._check(value); + C.JSArray_methods.add$1(this.serializedOnPlatform, [J.toString$0$(key), value.serialize$0()]); + }, + $signature: 19 + }; + O.Metadata_serialize_closure0.prototype = { + call$2: function(selector, metadata) { + type$.BooleanSelector._check(selector); + type$.Metadata._check(metadata); + return new P.MapEntry(J.toString$0$(selector), metadata.serialize$0(), type$.MapEntry_of_String_and_Map_String_dynamic); + }, + $signature: 82 + }; + N.OperatingSystem.prototype = { + toString$0: function(_) { + return this.name; + } + }; + N.OperatingSystem_find_closure.prototype = { + call$1: function(platform) { + return type$.OperatingSystem._check(platform).identifier === this.identifier; + }, + $signature: 83 + }; + N.OperatingSystem_find_closure0.prototype = { + call$0: function() { + return null; + }, + $signature: 0 + }; + E.PlatformSelector.prototype = { + validate$1: function(validVariables) { + type$.Set_String._check(validVariables); + if (this === C.PlatformSelector_All) + return; + E.PlatformSelector__wrapFormatException(new E.PlatformSelector_validate_closure(this, validVariables), null, type$.void); + }, + evaluate$1: function(platform) { + return this._platform_selector$_inner.evaluate$1(new E.PlatformSelector_evaluate_closure(platform)); + }, + intersection$1: function(other) { + var t1 = other._platform_selector$_inner, + t2 = J.$eq$(t1, C.C_All); + if (t2) + return this; + return new E.PlatformSelector(this._platform_selector$_inner.intersection$1(t1)); + }, + toString$0: function(_) { + return J.toString$0$(this._platform_selector$_inner); + }, + $eq: function(_, other) { + if (other == null) + return false; + return other instanceof E.PlatformSelector && J.$eq$(this._platform_selector$_inner, other._platform_selector$_inner); + }, + get$hashCode: function(_) { + return J.get$hashCode$(this._platform_selector$_inner); + } + }; + E.PlatformSelector$parse_closure.prototype = { + call$0: function() { + return new Y.BooleanSelectorImpl(new G.Parser(new O.Scanner(S.SpanScanner$(this.selector))).parse$0()); + }, + $signature: 84 + }; + E.PlatformSelector_validate_closure.prototype = { + call$0: function() { + return this.$this._platform_selector$_inner.validate$1(new E.PlatformSelector_validate__closure(this.validVariables)); + }, + $signature: 1 + }; + E.PlatformSelector_validate__closure.prototype = { + call$1: function($name) { + return $.$get$_universalValidVariables().contains$1(0, $name) || this.validVariables.contains$1(0, $name); + }, + $signature: 4 + }; + E.PlatformSelector_evaluate_closure.prototype = { + call$1: function(variable) { + var t1, t2, t3; + H._checkStringNullable(variable); + t1 = this.platform; + t2 = t1.runtime; + if (variable == t2.identifier) + return true; + t3 = t2.parent; + if (variable == (t3 == null ? null : t3.identifier)) + return true; + t3 = t1.os; + if (variable === t3.identifier) + return true; + switch (variable) { + case "dart-vm": + return t2.isDartVM; + case "browser": + return t2.isBrowser; + case "js": + return t2.isJS; + case "blink": + return t2.isBlink; + case "posix": + return t3 !== C.OperatingSystem_Windows_windows && t3 !== C.OperatingSystem_none_none; + case "google": + return t1.inGoogle; + default: + return false; + } + }, + $signature: 4 + }; + B.Runtime.prototype = { + toString$0: function(_) { + return this.name; + } + }; + B.Runtime_Runtime$deserialize_closure.prototype = { + call$1: function(platform) { + return type$.Runtime._check(platform).identifier === this.serialized; + }, + $signature: 85 + }; + U.StackTraceFormatter.prototype = { + configure$3$except$mapper$only: function(except, mapper, only) { + var t1 = type$.Set_String; + t1._check(except); + t1._check(only); + if (mapper != null) + this._mapper = mapper; + if (except != null) + this.set$_except(except); + if (only != null) + this.set$_only(only); + }, + configure$2$except$only: function(except, only) { + return this.configure$3$except$mapper$only(except, null, only); + }, + configure$1$mapper: function(mapper) { + return this.configure$3$except$mapper$only(null, mapper, null); + }, + formatStackTrace$2$verbose: function(stackTrace, verbose) { + var t2, t3, chain, + t1 = this._mapper; + if (t1 == null) + t1 = null; + else { + t2 = t1._mapping; + if (t2 == null) { + t2 = t1._mapContents; + t3 = t1._mapUrl; + t3 = t1._mapping = T.parseJsonExtended(C.C_JsonCodec.decode$2$reviver(t2, null), t3, null); + t2 = t3; + } + t1 = O.mapStackTrace(t2, stackTrace, false, t1._packageResolver, t1._sdkRoot); + } + chain = U.Chain_Chain$forTrace(t1 == null ? stackTrace : t1); + if (verbose) + return chain; + return chain.foldFrames$2$terse(new U.StackTraceFormatter_formatStackTrace_closure(this), true); + }, + set$_except: function(_except) { + this._except = type$.Set_String._check(_except); + }, + set$_only: function(_only) { + this._only = type$.Set_String._check(_only); + } + }; + U.StackTraceFormatter_formatStackTrace_closure.prototype = { + call$1: function(frame) { + var t1 = this.$this, + t2 = t1._only; + if (t2._collection$_length !== 0) + return !t2.contains$1(0, frame.get$$package()); + return t1._except.contains$1(0, frame.get$$package()); + }, + $signature: 21 + }; + G.State.prototype = { + $eq: function(_, other) { + if (other == null) + return false; + return other instanceof G.State && this.status === other.status && this.result === other.result; + }, + get$hashCode: function(_) { + return (H.Primitives_objectHashCode(this.status) ^ 7 * H.Primitives_objectHashCode(this.result)) >>> 0; + }, + toString$0: function(_) { + var t1 = this.status; + if (t1 === C.Status_pending) + return "pending"; + if (t1 === C.Status_complete) + return this.result.name; + t1 = this.result; + if (t1 === C.Result_success) + return "running"; + return "running with " + t1.toString$0(0); + } + }; + G.Status.prototype = { + toString$0: function(_) { + return this.name; + } + }; + G.Result0.prototype = { + toString$0: function(_) { + return this.name; + } + }; + U.Suite.prototype = {}; + E.SuitePlatform.prototype = {}; + V.Test.prototype = {$isGroupEntry: 1}; + G.TestFailure.prototype = { + toString$0: function(_) { + return this.message; + }, + get$message: function(receiver) { + return this.message; + } + }; + G._expect_closure0.prototype = { + call$5: function(actual, matcher, reason, matchState, verbose) { + var t1 = new P.StringBuffer(""); + matcher.describeMismatch$4(true, new E.StringDescription(t1), matchState, false); + t1 = t1._contents; + return G.formatFailure(matcher, true, t1.charCodeAt(0) == 0 ? t1 : t1, reason); + }, + $signature: 86 + }; + G._expect_closure.prototype = { + call$0: function() { + }, + $signature: 0 + }; + R.Timeout.prototype = { + merge$1: function(other) { + var t1, t2; + if (this.$eq(0, C.Timeout_null_null) || other.$eq(0, C.Timeout_null_null)) + return C.Timeout_null_null; + t1 = other.duration; + if (t1 != null) + return new R.Timeout(t1, null); + t1 = this.duration; + if (t1 != null) { + t2 = other.scaleFactor; + t1 = t1._duration; + if (typeof t2 !== "number") + return H.iae(t2); + return new R.Timeout(new P.Duration(C.JSNumber_methods.round$0(t1 * t2)), null); + } + t1 = this.scaleFactor; + t2 = other.scaleFactor; + if (typeof t1 !== "number") + return t1.$mul(); + if (typeof t2 !== "number") + return H.iae(t2); + return new R.Timeout(null, t1 * t2); + }, + apply$1: function(base) { + var t1; + if (this.$eq(0, C.Timeout_null_null)) + return null; + t1 = this.duration; + if (t1 == null) { + t1 = this.scaleFactor; + if (typeof t1 !== "number") + return H.iae(t1); + t1 = new P.Duration(C.JSNumber_methods.round$0(base._duration * t1)); + } + return t1; + }, + get$hashCode: function(_) { + return (J.get$hashCode$(this.duration) ^ 5 * J.get$hashCode$(this.scaleFactor)) >>> 0; + }, + $eq: function(_, other) { + if (other == null) + return false; + return other instanceof R.Timeout && J.$eq$(other.duration, this.duration) && other.scaleFactor == this.scaleFactor; + }, + toString$0: function(_) { + var t1 = this.duration; + if (t1 != null) + return t1.toString$0(0); + t1 = this.scaleFactor; + if (t1 != null) + return H.S(t1) + "x"; + return "none"; + } + }; + S.RemoteListener.prototype = { + _serializeGroup$3: function(channel, group, parents) { + var t2, t3, t4, t5, t6, t1 = {}; + t1.parents = parents; + type$.Iterable_Group._check(parents); + parents = H.setRuntimeTypeInfo(parents.slice(0), H._arrayInstanceType(parents)); + C.JSArray_methods.add$1(parents, group); + t1.parents = parents; + t2 = group.metadata.serialize$0(); + t3 = group.trace; + t3 = t3 == null ? null : J.toString$0$(t3.get$_lazy_trace$_trace()); + t4 = group.entries; + t5 = H._arrayInstanceType(t4); + t6 = type$.dynamic; + return P.LinkedHashMap_LinkedHashMap$_literal(["type", "group", "name", group.name, "metadata", t2, "trace", t3, "setUpAll", this._serializeTest$3(channel, group.setUpAll, parents), "tearDownAll", this._serializeTest$3(channel, group.tearDownAll, parents), "entries", new H.MappedListIterable(t4, t5._eval$1("Map<@,@>(1)")._check(new S.RemoteListener__serializeGroup_closure(t1, this, channel)), t5._eval$1("MappedListIterable<1,Map<@,@>>")).toList$0(0)], t6, t6); + }, + _serializeTest$3: function(channel, test, groups) { + var testChannel, t1, t2, t3, t4; + type$.Iterable_Group._check(groups); + if (test == null) + return null; + testChannel = channel.virtualChannel$0(); + testChannel.stream.listen$1(new S.RemoteListener__serializeTest_closure(this, test, groups, channel)); + t1 = test.name; + t2 = test.metadata.serialize$0(); + t3 = test.trace; + t3 = t3 == null ? null : J.toString$0$(t3.get$_lazy_trace$_trace()); + t4 = type$.dynamic; + return P.LinkedHashMap_LinkedHashMap$_literal(["type", "test", "name", t1, "metadata", t2, "trace", t3, "channel", testChannel.id], t4, t4); + }, + _runLiveTest$2: function(liveTest, channel) { + var t1, t2; + channel.stream.listen$1(new S.RemoteListener__runLiveTest_closure(liveTest)); + t1 = liveTest._live_test_controller$_controller; + t2 = t1._onStateChangeController; + new P._BroadcastStream(t2, H._instanceType(t2)._eval$1("_BroadcastStream<1>")).listen$1(new S.RemoteListener__runLiveTest_closure0(channel)); + t2 = t1._onErrorController; + new P._BroadcastStream(t2, H._instanceType(t2)._eval$1("_BroadcastStream<1>")).listen$1(new S.RemoteListener__runLiveTest_closure1(channel, liveTest)); + t1 = t1._onMessageController; + new P._BroadcastStream(t1, H._instanceType(t1)._eval$1("_BroadcastStream<1>")).listen$1(new S.RemoteListener__runLiveTest_closure2(this, channel)); + t1 = type$.dynamic; + P.runZoned(new S.RemoteListener__runLiveTest_closure3(liveTest, channel), null, null, P.LinkedHashMap_LinkedHashMap$_literal([C.Symbol_MAi, channel], t1, t1), type$.Null); + } + }; + S.RemoteListener_start_closure.prototype = { + call$4: function(_, __, ___, line) { + var t1; + H._checkStringNullable(line); + t1 = this.printZone; + if (t1 != null) + t1.print$1(0, line); + t1 = type$.String; + this.channel._mainController._foreign._sink.add$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["type", "print", "line", line], t1, t1)); + }, + $signature: 87 + }; + S.RemoteListener_start_closure0.prototype = { + call$1: function(_) { + }, + $signature: 3 + }; + S.RemoteListener_start_closure1.prototype = { + call$0: function() { + var _this = this, + t1 = type$.String, + t2 = P.LinkedHashSet_LinkedHashSet$_literal(["test", "stream_channel", "test_api"], t1), + t3 = type$.dynamic; + P.runZoned(type$.Null_Function._check(new S.RemoteListener_start__closure(_this._box_0, _this.getMain, _this.channel, _this.controller, _this.beforeLoad, _this.printZone, _this.spec)), null, null, P.LinkedHashMap_LinkedHashMap$_literal([$.$get$_currentKey0(), new U.StackTraceFormatter(t2, P.LinkedHashSet_LinkedHashSet$_empty(t1))], t3, t3), type$.Null); + }, + $signature: 0 + }; + S.RemoteListener_start__closure.prototype = { + call$0: function() { + var _this = this, + t1 = _this._box_0, + t2 = _this.channel; + P.runZoned(new S.RemoteListener_start___closure(t1, _this.getMain, t2, _this.controller, _this.beforeLoad, _this.printZone), new S.RemoteListener_start___closure0(t1, t2), _this.spec, null, type$.Future_Null); + }, + $signature: 0 + }; + S.RemoteListener_start___closure.prototype = { + call$0: function() { + var $async$goto = 0, + $async$completer = P._makeAsyncAwaitCompleter(type$.Null), + $async$returnValue, $async$next = [], $async$self = this, error, stackTrace, exception, t1, t2, queue, message, t3, metadata, declarer, t4, map, t5, t6, main; + var $async$call$0 = P._wrapJsFunctionForAsync(function($async$errorCode, $async$result) { + if ($async$errorCode === 1) + return P._asyncRethrow($async$result, $async$completer); + while (true) + switch ($async$goto) { + case 0: + // Function start + main = null; + try { + main = $async$self.getMain.call$0(); + } catch (exception) { + t1 = H.unwrapException(exception); + if (type$.NoSuchMethodError._is(t1)) { + S.RemoteListener__sendLoadException($async$self.channel, "No top-level main() function defined."); + // goto return + $async$goto = 1; + break; + } else { + error = t1; + stackTrace = H.getTraceFromException(exception); + S.RemoteListener__sendError($async$self.channel, error, stackTrace, $async$self._box_0.verboseChain); + // goto return + $async$goto = 1; + break; + } + } + if (!type$.Function._is(main)) { + S.RemoteListener__sendLoadException($async$self.channel, "Top-level main getter is not a function."); + // goto return + $async$goto = 1; + break; + } else if (!type$.dynamic_Function._is(main)) { + S.RemoteListener__sendLoadException($async$self.channel, "Top-level main() function takes arguments."); + // goto return + $async$goto = 1; + break; + } + t1 = $async$self.channel; + t2 = t1._mainController._foreign._streamController; + t2.toString; + queue = new G.StreamQueue(new P._ControllerStream(t2, H._instanceType(t2)._eval$1("_ControllerStream<1>")), Q.QueueList$(type$.Result_dynamic), P.ListQueue$(type$._EventRequest_dynamic), type$.StreamQueue_dynamic); + $async$goto = 3; + return P._asyncAwait(queue.get$next(), $async$call$0); + case 3: + // returning from await. + message = $async$result; + t2 = J.getInterceptor$asx(message); + H.assertHelper(J.$eq$(t2.$index(message, "type"), "initial")); + if (queue._isClosed) + H.throwExpression(queue._failClosed$0()); + t3 = new Y._CompleterStream(type$._CompleterStream_dynamic); + queue._isClosed = true; + queue._addRequest$1(new G._RestRequest(new Y.StreamCompleter(t3, type$.StreamCompleter_dynamic), queue, type$._RestRequest_dynamic)); + t3.listen$1(new S.RemoteListener_start____closure($async$self.controller, t1)); + t3 = H._asBoolNullable(t2.$index(message, "asciiGlyphs")); + if (t3 === true) + $._glyphs = C.C_AsciiGlyphSet; + metadata = O.Metadata$deserialize(t2.$index(message, "metadata")); + $async$self._box_0.verboseChain = metadata._verboseTrace === true; + t3 = P.LinkedHashSet_LinkedHashSet$from(type$.Iterable_dynamic._as(t2.$index(message, "platformVariables")), type$.String); + declarer = X.Declarer$(H._asBoolNullable(t2.$index(message, "collectTraces")), metadata, H._asBoolNullable(t2.$index(message, "noRetry")), t3); + t3 = type$.List_dynamic; + type$.StackTraceFormatter._as($.Zone__current.$index(0, $.$get$_currentKey0())).configure$2$except$only(S.RemoteListener__deserializeSet(t3._as(t2.$index(message, "foldTraceExcept"))), S.RemoteListener__deserializeSet(t3._as(t2.$index(message, "foldTraceOnly")))); + $async$goto = 4; + return P._asyncAwait($async$self.beforeLoad.call$0(), $async$call$0); + case 4: + // returning from await. + t3 = type$.dynamic; + $async$goto = 5; + return P._asyncAwait(P.runZoned(type$.void_Function._check(main), null, null, P.LinkedHashMap_LinkedHashMap$_literal([C.Symbol_Drw, declarer], t3, t3), type$.void), $async$call$0); + case 5: + // returning from await. + t4 = declarer.build$0(); + map = type$.Map_dynamic_dynamic._as(t2.$index(message, "platform")); + t5 = B.Runtime_Runtime$deserialize(map.$index(0, "runtime")); + t6 = N.OperatingSystem_find(H._asStringNullable(map.$index(0, "os"))); + t6 = E.SuitePlatform$(t5, H._asBoolNullable(map.$index(0, "inGoogle")), t6); + P.runZoned(new S.RemoteListener_start____closure0(new U.Suite(t6, H._asStringNullable(t2.$index(message, "path")), U.Suite__filterGroup(t4, t6)), $async$self.printZone, t1), null, null, P.LinkedHashMap_LinkedHashMap$_literal([C.Symbol_Drw, declarer], t3, t3), type$.Null); + case 1: + // return + return P._asyncReturn($async$returnValue, $async$completer); + } + }); + return P._asyncStartSync($async$call$0, $async$completer); + }, + $signature: 2 + }; + S.RemoteListener_start____closure.prototype = { + call$1: function(message) { + var t2, t3, t4, + t1 = J.getInterceptor$asx(message); + if (J.$eq$(t1.$index(message, "type"), "close")) { + this.controller._local._sink.close$0(0); + return; + } + H.assertHelper(J.$eq$(t1.$index(message, "type"), "suiteChannel")); + t2 = type$.SuiteChannelManager._as($.Zone__current.$index(0, $.$get$_currentKey())); + t3 = H._asStringNullable(t1.$index(message, "name")); + t1 = this.channel.virtualChannel$1(H._asIntNullable(t1.$index(message, "id"))); + t4 = t2._outgoingConnections; + if (t4.containsKey$1(t3)) { + t2 = t4.remove$1(0, t3); + t2.toString; + H.instanceType(t2)._eval$1("StreamChannel<1>")._check(t1); + if (t2._stream_channel_completer$_set) + H.throwExpression(P.StateError$("The channel has already been set.")); + t2._stream_channel_completer$_set = true; + t2._streamCompleter.setSourceStream$1(t1.stream); + t2 = t2._sinkCompleter; + t3 = t2.$ti; + t1 = t3._eval$1("StreamSink<1>")._check(t1.sink); + t2 = t3._eval$1("_CompleterSink<1>")._check(t2.sink); + if (t2._destinationSink != null) + H.throwExpression(P.StateError$("Destination sink already set")); + t2._setDestinationSink$1(t1); + } else { + t2 = t2._incomingConnections; + if (t2.containsKey$1(t3)) + H.throwExpression(P.StateError$('Duplicate RunnerSuite.channel() connection "' + H.S(t3) + '".')); + else + t2.$indexSet(0, t3, t1); + } + }, + $signature: 3 + }; + S.RemoteListener_start____closure0.prototype = { + call$0: function() { + U.Invoker_guard(new S.RemoteListener_start_____closure(this.suite, this.printZone, this.channel), type$.void); + }, + $signature: 0 + }; + S.RemoteListener_start_____closure.prototype = { + call$0: function() { + var t1 = this.suite, + t2 = this.channel; + t2._mainController._foreign._sink.add$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["type", "success", "root", new S.RemoteListener(t1, this.printZone)._serializeGroup$3(t2, t1.group, H.setRuntimeTypeInfo([], type$.JSArray_Group))], type$.String, type$.Object)); + return null; + }, + $signature: 1 + }; + S.RemoteListener_start___closure0.prototype = { + call$2: function(error, stackTrace) { + S.RemoteListener__sendError(this.channel, error, type$.StackTrace._check(stackTrace), this._box_0.verboseChain); + }, + $signature: 5 + }; + S.RemoteListener__serializeGroup_closure.prototype = { + call$1: function(entry) { + var t1, t2, t3; + type$.GroupEntry._check(entry); + t1 = this.$this; + t2 = this.channel; + t3 = this._box_0.parents; + return entry instanceof O.Group ? t1._serializeGroup$3(t2, entry, t3) : t1._serializeTest$3(t2, type$.Test._as(entry), t3); + }, + $signature: 88 + }; + S.RemoteListener__serializeTest_closure.prototype = { + call$1: function(message) { + var t2, _this = this, + t1 = J.getInterceptor$asx(message); + H.assertHelper(J.$eq$(t1.$index(message, "command"), "run")); + t2 = _this.$this; + t2._runLiveTest$2(_this.test.load$2$groups(t2._suite, _this.groups), _this.channel.virtualChannel$1(H._asIntNullable(t1.$index(message, "channel")))); + }, + $signature: 3 + }; + S.RemoteListener__runLiveTest_closure.prototype = { + call$1: function(message) { + H.assertHelper(J.$eq$(J.$index$asx(message, "command"), "close")); + this.liveTest._live_test_controller$_controller._live_test_controller$_close$0(); + }, + $signature: 3 + }; + S.RemoteListener__runLiveTest_closure0.prototype = { + call$1: function(state) { + var t1; + type$.State._check(state); + t1 = type$.String; + this.channel.sink.add$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["type", "state-change", "status", state.status.name, "result", state.result.name], t1, t1)); + }, + $signature: 23 + }; + S.RemoteListener__runLiveTest_closure1.prototype = { + call$1: function(asyncError) { + var t1, t2, t3, t4; + type$.AsyncError._check(asyncError); + t1 = asyncError.error; + t2 = type$.StackTraceFormatter._as($.Zone__current.$index(0, $.$get$_currentKey0())); + t3 = asyncError.stackTrace; + t4 = this.liveTest._live_test_controller$_controller; + this.channel.sink.add$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["type", "error", "error", U.RemoteException_serialize(t1, t2.formatStackTrace$2$verbose(t3, t4._test.metadata._verboseTrace === true))], type$.String, type$.Object)); + }, + $signature: 90 + }; + S.RemoteListener__runLiveTest_closure2.prototype = { + call$1: function(message) { + var t1; + type$.Message._check(message); + t1 = this.$this._printZone; + if (t1 != null) + t1.print$1(0, message.text); + t1 = type$.String; + this.channel.sink.add$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["type", "message", "message-type", message.type.name, "text", message.text], t1, t1)); + }, + $signature: 27 + }; + S.RemoteListener__runLiveTest_closure3.prototype = { + call$0: function() { + this.liveTest._live_test_controller$_controller._live_test_controller$_run$0().then$1$1(new S.RemoteListener__runLiveTest__closure(this.channel), type$.void); + }, + $signature: 0 + }; + S.RemoteListener__runLiveTest__closure.prototype = { + call$1: function(_) { + var t1 = type$.String; + return this.channel.sink.add$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["type", "complete"], t1, t1)); + }, + $signature: 15 + }; + N.SuiteChannelManager.prototype = { + connectOut$1: function($name) { + var t2, completer, + t1 = this._incomingConnections; + if (t1.containsKey$1($name)) + return t1.$index(0, $name); + else { + t1 = this._names; + if (t1.contains$1(0, $name)) + throw H.wrapException(P.StateError$('Duplicate suiteChannel() connection "' + $name + '".')); + else { + t1.add$1(0, $name); + t1 = new Y._CompleterStream(type$._CompleterStream_dynamic); + t2 = new T._CompleterSink(type$._CompleterSink_dynamic); + completer = new N.StreamChannelCompleter(new Y.StreamCompleter(t1, type$.StreamCompleter_dynamic), new T.StreamSinkCompleter(t2, type$.StreamSinkCompleter_dynamic), type$.StreamChannelCompleter_dynamic); + completer.set$_stream_channel_completer$_channel(new R._StreamChannel(t1, t2, type$._StreamChannel_dynamic)); + this._outgoingConnections.$indexSet(0, $name, completer); + return completer._stream_channel_completer$_channel; + } + } + } + }; + O.IterableSet.prototype = { + get$length: function(_) { + var t1 = this._iterable_set$_base._collection$_source; + return t1.get$length(t1); + }, + get$iterator: function(_) { + var t1 = this._iterable_set$_base; + return new H.ListIterator(t1, t1.get$length(t1), t1.$ti._eval$1("ListIterator<ListMixin.E>")); + }, + toSet$0: function(_) { + var t1 = this._iterable_set$_base; + return t1.toSet$0(t1); + } + }; + O._IterableSet_SetMixin_UnmodifiableSetMixin.prototype = {}; + E.StackTraceMapper.prototype = {}; + V.errorsDontStopTest_closure.prototype = { + call$0: function() { + P.Future_Future$sync(this.body, type$.dynamic).whenComplete$1(this.completer.get$complete()); + }, + $signature: 0 + }; + V.errorsDontStopTest_closure0.prototype = { + call$1: function(_) { + var t1 = type$.Invoker._as($.Zone__current.$index(0, C.Symbol_cQL)); + t1.heartbeat$0(); + t1.get$_outstandingCallbacks().decrement$0(); + return null; + }, + $signature: 92 + }; + B.closure0.prototype = { + call$0: function() { + var t1 = $.$get$context().style; + if (t1 == $.$get$Style_url()) + return C.OperatingSystem_none_none; + if (t1 == $.$get$Style_windows()) + return C.OperatingSystem_Windows_windows; + if ($._macOSDirectories.any$1(0, J.get$startsWith$s(D.current()))) + return C.OperatingSystem_RkP; + return C.OperatingSystem_Linux_linux; + }, + $signature: 115 + }; + O.Engine.prototype = { + get$_onUnpaused: function() { + var t1 = new P._Future($.Zone__current, type$._Future_dynamic); + t1._asyncComplete$1(null); + return t1; + }, + get$success: function() { + var $async$goto = 0, + $async$completer = P._makeAsyncAwaitCompleter(type$.bool), + $async$returnValue, $async$self = this; + var $async$get$success = P._wrapJsFunctionForAsync(function($async$errorCode, $async$result) { + if ($async$errorCode === 1) + return P._asyncRethrow($async$result, $async$completer); + while (true) + switch ($async$goto) { + case 0: + // Function start + $async$goto = 3; + return P._asyncAwait(P.Future_wait(H.setRuntimeTypeInfo([$async$self._group._future_group$_completer.future, $async$self._loadPool._pool$_closeMemo._async_memoizer$_completer.future], type$.JSArray_Future_dynamic), true, type$.dynamic), $async$get$success); + case 3: + // returning from await. + if (H.boolConversionCheck($async$self._closedBeforeDone)) { + $async$returnValue = null; + // goto return + $async$goto = 1; + break; + } + $async$returnValue = $async$self.get$liveTests().every$1(0, new O.Engine_success_closure()); + // goto return + $async$goto = 1; + break; + case 1: + // return + return P._asyncReturn($async$returnValue, $async$completer); + } + }); + return P._asyncStartSync($async$get$success, $async$completer); + }, + get$liveTests: function() { + var _this = this; + return new M.UnionSet(P.LinkedHashSet_LinkedHashSet$from(H.setRuntimeTypeInfo([_this._passedGroup._union_set_controller$_set, _this._skippedGroup._union_set_controller$_set, _this._failedGroup._union_set_controller$_set, new O.IterableSet(new P.UnmodifiableListView(_this._active, type$.UnmodifiableListView_LiveTest), type$.IterableSet_LiveTest)], type$.JSArray_Set_LiveTest), type$.Set_LiveTest), true, type$.UnionSet_LiveTest); + }, + Engine$3$concurrency$coverage$maxSuites: function(concurrency, coverage, maxSuites) { + this._group._future_group$_completer.future.then$1$1(new O.Engine_closure(this), type$.Null).catchError$1(new O.Engine_closure0()); + }, + run$0: function() { + var t2, subscription, _this = this, t1 = {}; + if (_this._engine$_runCalled) + throw H.wrapException(P.StateError$("Engine.run() may not be called more than once.")); + _this._engine$_runCalled = true; + t1.subscription = null; + t2 = _this._suiteController; + subscription = new P._ControllerStream(t2, H._instanceType(t2)._eval$1("_ControllerStream<1>")).listen$2$onDone(new O.Engine_run_closure(_this), new O.Engine_run_closure0(t1, _this)); + t1.subscription = subscription; + _this._engine$_subscriptions.add$1(0, subscription); + return _this.get$success(); + }, + _runGroup$3: function(suiteController, group, parents) { + type$.List_Group._check(parents); + return this._runGroup$body$Engine(suiteController, group, parents); + }, + _runGroup$body$Engine: function(suiteController, group, parents) { + var $async$goto = 0, + $async$completer = P._makeAsyncAwaitCompleter(type$.dynamic), + $async$returnValue, $async$handler = 2, $async$currentError, $async$next = [], $async$self = this, suiteConfig, skipGroup, setUpAllSucceeded, liveTest, entries, entry, test, liveTest0, t1, skipGroup0, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, _i, t16, t17, t18, invoker, t19, t20, result, t21; + var $async$_runGroup$3 = P._wrapJsFunctionForAsync(function($async$errorCode, $async$result) { + if ($async$errorCode === 1) { + $async$currentError = $async$result; + $async$goto = $async$handler; + } + while (true) + switch ($async$goto) { + case 0: + // Function start + C.JSArray_methods.add$1(parents, group); + $async$handler = 3; + t1 = suiteController._liveSuite._live_suite_controller$_controller._live_suite_controller$_suite; + suiteConfig = t1._runner_suite$_controller._config; + suiteConfig.toString; + skipGroup0 = group.metadata._skip === true; + skipGroup = skipGroup0; + setUpAllSucceeded = true; + $async$goto = !H.boolConversionCheck(skipGroup) && group.setUpAll != null ? 6 : 7; + break; + case 6: + // then + liveTest = group.setUpAll.load$2$groups(t1, parents); + $async$goto = 8; + return P._asyncAwait($async$self._engine$_runLiveTest$3$countSuccess(suiteController, liveTest, false), $async$_runGroup$3); + case 8: + // returning from await. + t1 = liveTest._live_test_controller$_controller._live_test_controller$_state.result; + setUpAllSucceeded = t1 === C.Result_success || t1 === C.Result_skipped; + case 7: + // join + $async$goto = !$async$self._engine$_closed && H.boolConversionCheck(setUpAllSucceeded) ? 9 : 10; + break; + case 9: + // then + t1 = group.entries; + t1 = H.setRuntimeTypeInfo(t1.slice(0), H._arrayInstanceType(t1)._eval$1("JSArray<1>")); + entries = t1; + suiteConfig.toString; + t1 = entries, t2 = t1.length, t3 = type$.Group, t4 = type$.List_Group, t5 = type$._Future_void, t6 = type$._AsyncCompleter_void, t7 = type$._SyncBroadcastStreamController_Message, t8 = type$._SyncBroadcastStreamController_AsyncError, t9 = type$._SyncBroadcastStreamController_State, t10 = type$.Test, t11 = type$.Iterable_Group, t12 = type$.JSArray_Zone, t13 = type$.JSArray_of_dynamic_Function, t14 = type$.JSArray_String, t15 = type$.JSArray_AsyncError, _i = 0; + case 11: + // for condition + if (!(_i < t1.length)) { + // goto after for + $async$goto = 13; + break; + } + entry = t1[_i]; + if ($async$self._engine$_closed) { + $async$next = [1]; + // goto finally + $async$goto = 4; + break; + } + $async$goto = entry instanceof O.Group ? 14 : 16; + break; + case 14: + // then + $async$goto = 17; + return P._asyncAwait($async$self._runGroup$3(suiteController, entry, parents), $async$_runGroup$3); + case 17: + // returning from await. + // goto join + $async$goto = 15; + break; + case 16: + // else + suiteConfig.toString; + t16 = entry.get$metadata(); + t16 = t16._skip === true; + $async$goto = t16 ? 18 : 20; + break; + case 18: + // then + $async$goto = 21; + return P._asyncAwait($async$self._runSkippedTest$3(suiteController, t10._as(entry), parents), $async$_runGroup$3); + case 21: + // returning from await. + // goto join + $async$goto = 19; + break; + case 20: + // else + test = t10._as(entry); + t16 = test; + t17 = suiteController._liveSuite._live_suite_controller$_controller; + t16.toString; + t11._check(parents); + t18 = new P._AsyncCompleter(new P._Future($.Zone__current, t5), t6); + invoker = new U.Invoker(t16._guarded, new P.Object(), t18, H.setRuntimeTypeInfo([], t12), new P.Object(), H.setRuntimeTypeInfo([], t13), H.setRuntimeTypeInfo([], t14)); + t19 = H.setRuntimeTypeInfo([], t15); + t20 = $.Zone__current; + result = P.List_List$from(parents, false, t3); + result.fixed$length = Array; + result.immutable$list = Array; + t21 = t4._check(result); + t16 = new V.LiveTestController(t17._live_suite_controller$_suite, t21, t16, invoker.get$_invoker$_onRun(), t18.get$complete(), t19, C.State_Status_pending_Result_success, new P._SyncBroadcastStreamController(null, null, t9), new P._SyncBroadcastStreamController(null, null, t8), new P._SyncBroadcastStreamController(null, null, t7), new P._AsyncCompleter(new P._Future(t20, t5), t6)); + t17 = new V._LiveTest(t16); + t16._liveTest = t17; + invoker._invoker$_controller = t16; + $async$goto = 22; + return P._asyncAwait($async$self._engine$_runLiveTest$2(suiteController, t17), $async$_runGroup$3); + case 22: + // returning from await. + case 19: + // join + case 15: + // join + case 12: + // for update + t1.length === t2 || (0, H.throwConcurrentModificationError)(t1), ++_i; + // goto for condition + $async$goto = 11; + break; + case 13: + // after for + case 10: + // join + $async$goto = !H.boolConversionCheck(skipGroup) && group.tearDownAll != null ? 23 : 24; + break; + case 23: + // then + liveTest0 = group.tearDownAll.load$2$groups(suiteController._liveSuite._live_suite_controller$_controller._live_suite_controller$_suite, parents); + $async$goto = 25; + return P._asyncAwait($async$self._engine$_runLiveTest$3$countSuccess(suiteController, liveTest0, false), $async$_runGroup$3); + case 25: + // returning from await. + $async$goto = $async$self._engine$_closed ? 26 : 27; + break; + case 26: + // then + $async$goto = 28; + return P._asyncAwait(liveTest0._live_test_controller$_controller._live_test_controller$_close$0(), $async$_runGroup$3); + case 28: + // returning from await. + case 27: + // join + case 24: + // join + $async$next.push(5); + // goto finally + $async$goto = 4; + break; + case 3: + // uncaught + $async$next = [2]; + case 4: + // finally + $async$handler = 2; + C.JSArray_methods.remove$1(parents, group); + // goto the next finally handler + $async$goto = $async$next.pop(); + break; + case 5: + // after finally + case 1: + // return + return P._asyncReturn($async$returnValue, $async$completer); + case 2: + // rethrow + return P._asyncRethrow($async$currentError, $async$completer); + } + }); + return P._asyncStartSync($async$_runGroup$3, $async$completer); + }, + _engine$_runLiveTest$3$countSuccess: function(suiteController, liveTest, countSuccess) { + return this._runLiveTest$body$Engine(suiteController, liveTest, countSuccess); + }, + _engine$_runLiveTest$2: function(suiteController, liveTest) { + return this._engine$_runLiveTest$3$countSuccess(suiteController, liveTest, true); + }, + _runLiveTest$body$Engine: function(suiteController, liveTest, countSuccess) { + var $async$goto = 0, + $async$completer = P._makeAsyncAwaitCompleter(type$.dynamic), + $async$returnValue, $async$self = this, t2, t3, subscription, t1; + var $async$_engine$_runLiveTest$3$countSuccess = P._wrapJsFunctionForAsync(function($async$errorCode, $async$result) { + if ($async$errorCode === 1) + return P._asyncRethrow($async$result, $async$completer); + while (true) + switch ($async$goto) { + case 0: + // Function start + t1 = {}; + $async$goto = 3; + return P._asyncAwait($async$self.get$_onUnpaused(), $async$_engine$_runLiveTest$3$countSuccess); + case 3: + // returning from await. + t2 = $async$self._active; + t2._queue_list$_add$1(t2.$ti._precomputed1._check(liveTest)); + t2.get$first(t2).toString; + t1.subscription = null; + t2 = liveTest._live_test_controller$_controller; + t3 = t2._onStateChangeController; + subscription = new P._BroadcastStream(t3, H._instanceType(t3)._eval$1("_BroadcastStream<1>")).listen$2$onDone(new O.Engine__runLiveTest_closure($async$self, liveTest), new O.Engine__runLiveTest_closure0(t1, $async$self)); + t1.subscription = subscription; + $async$self._engine$_subscriptions.add$1(0, subscription); + suiteController.reportLiveTest$2$countSuccess(liveTest, countSuccess); + $async$goto = 4; + return P._asyncAwait(P.Future_Future$microtask(liveTest.get$run(), type$.dynamic), $async$_engine$_runLiveTest$3$countSuccess); + case 4: + // returning from await. + $async$goto = 5; + return P._asyncAwait(P.Future_Future(new O.Engine__runLiveTest_closure1(), type$.Null), $async$_engine$_runLiveTest$3$countSuccess); + case 5: + // returning from await. + t1 = $async$self._restarted; + if (!t1.contains$1(0, liveTest)) { + // goto return + $async$goto = 1; + break; + } + $async$goto = 6; + return P._asyncAwait($async$self._engine$_runLiveTest$3$countSuccess(suiteController, t2._test.load$2$groups(t2._live_test_controller$_suite, t2._groups), countSuccess), $async$_engine$_runLiveTest$3$countSuccess); + case 6: + // returning from await. + t1.remove$1(0, liveTest); + case 1: + // return + return P._asyncReturn($async$returnValue, $async$completer); + } + }); + return P._asyncStartSync($async$_engine$_runLiveTest$3$countSuccess, $async$completer); + }, + _runSkippedTest$3: function(suiteController, test, parents) { + return this._runSkippedTest$body$Engine(suiteController, test, type$.List_Group._check(parents)); + }, + _runSkippedTest$body$Engine: function(suiteController, test, parents) { + var $async$goto = 0, + $async$completer = P._makeAsyncAwaitCompleter(type$.dynamic), + $async$returnValue, $async$self = this, skipped, controller, t1; + var $async$_runSkippedTest$3 = P._wrapJsFunctionForAsync(function($async$errorCode, $async$result) { + if ($async$errorCode === 1) + return P._asyncRethrow($async$result, $async$completer); + while (true) + switch ($async$goto) { + case 0: + // Function start + t1 = {}; + $async$goto = 3; + return P._asyncAwait($async$self.get$_onUnpaused(), $async$_runSkippedTest$3); + case 3: + // returning from await. + skipped = new U.LocalTest(test.name, test.metadata, test.trace, false, new O.Engine__runSkippedTest_closure(), true); + t1.controller = null; + controller = V.LiveTestController$(suiteController._liveSuite._live_suite_controller$_controller._live_suite_controller$_suite, skipped, new O.Engine__runSkippedTest_closure0(t1, skipped), new O.Engine__runSkippedTest_closure1(), parents); + t1.controller = controller; + $async$goto = 4; + return P._asyncAwait($async$self._engine$_runLiveTest$2(suiteController, controller._liveTest), $async$_runSkippedTest$3); + case 4: + // returning from await. + $async$returnValue = $async$result; + // goto return + $async$goto = 1; + break; + case 1: + // return + return P._asyncReturn($async$returnValue, $async$completer); + } + }); + return P._asyncStartSync($async$_runSkippedTest$3, $async$completer); + }, + _addLiveSuite$1: function(liveSuite) { + var t1, t2, t3, _this = this; + _this._liveSuites.add$1(0, liveSuite); + _this._onSuiteStartedController.add$1(0, liveSuite); + t1 = liveSuite._live_suite_controller$_controller; + t2 = t1._onTestStartedController; + _this._onTestStartedGroup.add$1(0, new P._BroadcastStream(t2, H._instanceType(t2)._eval$1("_BroadcastStream<1>"))); + t2 = _this._passedGroup; + t3 = type$.UnmodifiableSetView_LiveTest; + t2._union_set_controller$_sets.add$1(0, t2.$ti._eval$1("Set<1>")._check(new L.UnmodifiableSetView(t1._passed, t3))); + t2 = _this._skippedGroup; + t2._union_set_controller$_sets.add$1(0, t2.$ti._eval$1("Set<1>")._check(new L.UnmodifiableSetView(t1._skipped, t3))); + t2 = _this._failedGroup; + t2._union_set_controller$_sets.add$1(0, t2.$ti._eval$1("Set<1>")._check(new L.UnmodifiableSetView(t1._failed, t3))); + } + }; + O.Engine_success_closure.prototype = { + call$1: function(liveTest) { + var t1 = type$.LiveTest._check(liveTest)._live_test_controller$_controller._live_test_controller$_state, + t2 = t1.result; + return (t2 === C.Result_success || t2 === C.Result_skipped) && t1.status === C.Status_complete; + }, + $signature: 95 + }; + O.Engine_closure.prototype = { + call$1: function(_) { + var t1; + type$.List_dynamic._check(_); + t1 = this.$this; + t1._onTestStartedGroup.close$0(0); + t1._onSuiteStartedController.close$0(0); + if (t1._closedBeforeDone == null) + t1._closedBeforeDone = false; + }, + $signature: 48 + }; + O.Engine_closure0.prototype = { + call$1: function(_) { + }, + $signature: 3 + }; + O.Engine_run_closure.prototype = { + call$1: function(suite) { + var t1; + type$.RunnerSuite._check(suite); + t1 = this.$this; + t1._addedSuites.add$1(0, suite); + t1._onSuiteAddedController.add$1(0, suite); + t1._group.add$1(0, new O.Engine_run__closure(t1, suite).call$0()); + }, + $signature: 97 + }; + O.Engine_run__closure.prototype = { + call$0: function() { + return this.$call$body$Engine_run__closure(); + }, + $call$body$Engine_run__closure: function() { + var $async$goto = 0, + $async$completer = P._makeAsyncAwaitCompleter(type$.Null), + $async$self = this, controller, t1, t2, loadResource; + var $async$call$0 = P._wrapJsFunctionForAsync(function($async$errorCode, $async$result) { + if ($async$errorCode === 1) + return P._asyncRethrow($async$result, $async$completer); + while (true) + switch ($async$goto) { + case 0: + // Function start + t1 = {}; + t2 = $async$self.$this; + $async$goto = 2; + return P._asyncAwait(t2._loadPool.request$0(0), $async$call$0); + case 2: + // returning from await. + loadResource = $async$result; + t1.controller = null; + controller = B.LiveSuiteController$($async$self.suite); + t1.controller = controller; + t2._addLiveSuite$1(controller._liveSuite); + $async$goto = 3; + return P._asyncAwait(t2._runPool.withResource$1$1(new O.Engine_run___closure(t1, t2, loadResource), type$.Null), $async$call$0); + case 3: + // returning from await. + // implicit return + return P._asyncReturn(null, $async$completer); + } + }); + return P._asyncStartSync($async$call$0, $async$completer); + }, + $signature: 2 + }; + O.Engine_run___closure.prototype = { + call$0: function() { + var $async$goto = 0, + $async$completer = P._makeAsyncAwaitCompleter(type$.Null), + $async$returnValue, $async$self = this, t2, t3, t1; + var $async$call$0 = P._wrapJsFunctionForAsync(function($async$errorCode, $async$result) { + if ($async$errorCode === 1) + return P._asyncRethrow($async$result, $async$completer); + while (true) + switch ($async$goto) { + case 0: + // Function start + t1 = $async$self.$this; + if (t1._engine$_closed) { + // goto return + $async$goto = 1; + break; + } + t2 = $async$self._box_0; + t3 = t2.controller; + $async$goto = 3; + return P._asyncAwait(t1._runGroup$3(t3, t3._liveSuite._live_suite_controller$_controller._live_suite_controller$_suite.group, H.setRuntimeTypeInfo([], type$.JSArray_Group)), $async$call$0); + case 3: + // returning from await. + t3 = t2.controller; + t3._onTestStartedController.close$0(0); + t3._onCompleteGroup.close$0(0); + t1 = $async$self.loadResource; + t1.toString; + t2 = type$.dynamic_Function._check(new O.Engine_run____closure(t2)); + if (t1._released) + H.throwExpression(P.StateError$("A PoolResource may only be released once.")); + t1._released = true; + t1._pool._onResourceReleaseAllowed$1(t2); + case 1: + // return + return P._asyncReturn($async$returnValue, $async$completer); + } + }); + return P._asyncStartSync($async$call$0, $async$completer); + }, + $signature: 2 + }; + O.Engine_run____closure.prototype = { + call$0: function() { + return this._box_0.controller.close$0(0); + }, + $signature: 14 + }; + O.Engine_run_closure0.prototype = { + call$0: function() { + var t1 = this.$this; + t1._engine$_subscriptions.remove$1(0, this._box_1.subscription); + t1._onSuiteAddedController.close$0(0); + t1._group.close$0(0); + t1._loadPool.close$0(0); + }, + $signature: 0 + }; + O.Engine__runLiveTest_closure.prototype = { + call$1: function(state) { + var t1, t2; + if (type$.State._check(state).status !== C.Status_complete) + return; + t1 = this.$this; + t2 = t1._active; + t2.remove$1(t2, this.liveTest); + if (t2.get$length(t2) === 0 && t1._activeLoadTests._collection$_length !== 0) { + t1 = t1._activeLoadTests; + t2._queue_list$_add$1(t2.$ti._precomputed1._check(t1.get$first(t1))); + } + }, + $signature: 23 + }; + O.Engine__runLiveTest_closure0.prototype = { + call$0: function() { + this.$this._engine$_subscriptions.remove$1(0, this._box_0.subscription); + }, + $signature: 0 + }; + O.Engine__runLiveTest_closure1.prototype = { + call$0: function() { + }, + $signature: 0 + }; + O.Engine__runSkippedTest_closure.prototype = { + call$0: function() { + }, + $signature: 0 + }; + O.Engine__runSkippedTest_closure0.prototype = { + call$0: function() { + var t2, + t1 = this._box_0; + t1.controller.setState$1(C.State_Status_running_Result_success); + t1.controller.setState$1(C.State_Status_running_Result_skipped); + t2 = this.skipped.metadata.skipReason; + if (t2 != null) + t1.controller.message$1(0, new D.Message(C.MessageType_skip, "Skip: " + t2)); + t1.controller.setState$1(C.State_Status_complete_Result_skipped); + t1.controller.completer.complete$0(); + }, + $signature: 0 + }; + O.Engine__runSkippedTest_closure1.prototype = { + call$0: function() { + }, + $signature: 0 + }; + E.LiveSuite.prototype = {}; + B._LiveSuite.prototype = {}; + B.LiveSuiteController.prototype = { + LiveSuiteController$1: function(_suite) { + var _this = this; + _this._liveSuite = new B._LiveSuite(_this); + _this._onCompleteGroup._future_group$_completer.future.then$1$2$onError(new B.LiveSuiteController_closure(_this), new B.LiveSuiteController_closure0(), type$.Null); + }, + reportLiveTest$2$countSuccess: function(liveTest, countSuccess) { + var t2, t3, _this = this, + t1 = _this._onTestStartedController; + if ((t1._state & 4) !== 0) + throw H.wrapException(P.StateError$("Can't call reportLiveTest() after noMoreTests().")); + t2 = liveTest._live_test_controller$_controller; + H.assertHelper(t2._live_test_controller$_suite == _this._live_suite_controller$_suite); + H.assertHelper(_this._live_suite_controller$_active == null); + _this._live_suite_controller$_active = liveTest; + t3 = t2._onStateChangeController; + new P._BroadcastStream(t3, H._instanceType(t3)._eval$1("_BroadcastStream<1>")).listen$1(new B.LiveSuiteController_reportLiveTest_closure(_this, liveTest, countSuccess)); + t1.add$1(0, liveTest); + _this._onCompleteGroup.add$1(0, t2.completer.future); + }, + close$0: function(_) { + return this._live_suite_controller$_closeMemo.runOnce$1(new B.LiveSuiteController_close_closure(this)); + } + }; + B.LiveSuiteController_closure.prototype = { + call$1: function(_) { + type$.List_dynamic._check(_); + }, + $signature: 48 + }; + B.LiveSuiteController_closure0.prototype = { + call$1: function(_) { + }, + $signature: 3 + }; + B.LiveSuiteController_reportLiveTest_closure.prototype = { + call$1: function(state) { + var t1, t2, _this = this; + type$.State._check(state); + if (state.status !== C.Status_complete) + return; + t1 = _this.$this; + t1._live_suite_controller$_active = null; + t2 = state.result; + if (t2 === C.Result_skipped) + t1._skipped.add$1(0, _this.liveTest); + else if (t2 !== C.Result_success) { + t2 = _this.liveTest; + t1._passed.remove$1(0, t2); + t1._failed.add$1(0, t2); + } else if (_this.countSuccess) { + t2 = _this.liveTest; + t1._passed.add$1(0, t2); + t1._failed.remove$1(0, t2); + } + }, + $signature: 23 + }; + B.LiveSuiteController_close_closure.prototype = { + call$0: function() { + var $async$goto = 0, + $async$completer = P._makeAsyncAwaitCompleter(type$.Null), + $async$handler = 1, $async$currentError, $async$next = [], $async$self = this; + var $async$call$0 = P._wrapJsFunctionForAsync(function($async$errorCode, $async$result) { + if ($async$errorCode === 1) { + $async$currentError = $async$result; + $async$goto = $async$handler; + } + while (true) + switch ($async$goto) { + case 0: + // Function start + $async$handler = 2; + $async$goto = 5; + return P._asyncAwait($async$self.$this._live_suite_controller$_suite._runner_suite$_controller._runner_suite$_close$0(), $async$call$0); + case 5: + // returning from await. + $async$next.push(4); + // goto finally + $async$goto = 3; + break; + case 2: + // uncaught + $async$next = [1]; + case 3: + // finally + $async$handler = 1; + $async$self.$this._live_suite_controller$_onCloseCompleter.complete$0(); + // goto the next finally handler + $async$goto = $async$next.pop(); + break; + case 4: + // after finally + // implicit return + return P._asyncReturn(null, $async$completer); + case 1: + // rethrow + return P._asyncRethrow($async$currentError, $async$completer); + } + }); + return P._asyncStartSync($async$call$0, $async$completer); + }, + $signature: 2 + }; + R.ExpandedReporter.prototype = { + _onTestStarted$1: function(liveTest) { + var t1, t2, t3, t4, _this = this; + type$.LiveTest._check(liveTest); + liveTest.toString; + t1 = _this._stopwatch; + t2 = t1._stop != null; + if (t2) + if (t2) { + t2 = t1._core$_start; + t3 = H._checkIntNullable($.Primitives_timerTicks.call$0()); + t4 = t1._stop; + if (typeof t3 !== "number") + return t3.$sub(); + if (typeof t4 !== "number") + return H.iae(t4); + t1._core$_start = t2 + (t3 - t4); + t1._stop = null; + } + t1 = _this._engine._active; + if (t1.get$length(t1) === 1) + _this._progressLine$1(_this._description$1(liveTest)); + t1 = liveTest._live_test_controller$_controller._onStateChangeController; + _this._subscriptions.add$1(0, new P._BroadcastStream(t1, H._instanceType(t1)._eval$1("_BroadcastStream<1>")).listen$1(new R.ExpandedReporter__onTestStarted_closure(_this, liveTest))); + t1 = _this._subscriptions; + t2 = liveTest._live_test_controller$_controller; + t3 = t2._onErrorController; + t1.add$1(0, new P._BroadcastStream(t3, H._instanceType(t3)._eval$1("_BroadcastStream<1>")).listen$1(new R.ExpandedReporter__onTestStarted_closure0(_this, liveTest))); + t2 = t2._onMessageController; + t1.add$1(0, new P._BroadcastStream(t2, H._instanceType(t2)._eval$1("_BroadcastStream<1>")).listen$1(new R.ExpandedReporter__onTestStarted_closure1(_this, liveTest))); + }, + _onStateChange$2: function(liveTest, state) { + var t1, t2, t3; + if (state.status !== C.Status_complete) + return; + t1 = this._engine._active; + t2 = type$.UnmodifiableListView_LiveTest; + t3 = new P.UnmodifiableListView(t1, t2); + if (t3.get$length(t3) !== 0) { + t1 = new P.UnmodifiableListView(t1, t2); + this._progressLine$1(this._description$1(t1.get$first(t1))); + } + }, + _expanded$_onError$3: function(liveTest, error, stackTrace) { + var t1, _this = this; + if (liveTest._live_test_controller$_controller._live_test_controller$_state.status !== C.Status_complete) + return; + _this._progressLine$2$suffix(_this._description$1(liveTest), " " + _this._bold + _this._red + "[E]" + _this._noColor); + t1 = _this._expanded$_sink; + t1.writeln$1(B.indent(H.S(error), null)); + t1.writeln$1(B.indent(H.S(stackTrace), null)); + return; + }, + _expanded$_onDone$1: function(success) { + var t1, t2, t3, t4, _this = this; + H._checkBoolNullable(success); + if (success == null) + return; + t1 = _this._engine; + t2 = t1.get$liveTests(); + if (t2.get$length(t2) === 0) + _this._expanded$_sink.writeln$1("No tests ran."); + else if (!success) { + for (t2 = type$.UnmodifiableListView_LiveTest, t1 = new P.UnmodifiableListView(t1._active, t2), t2 = new H.ListIterator(t1, t1.get$length(t1), t2._eval$1("ListIterator<ListMixin.E>")), t1 = _this._bold, t3 = _this._red, t4 = _this._noColor; t2.moveNext$0();) + _this._progressLine$2$suffix(_this._description$1(t2.__internal$_current), " - did not complete " + t1 + t3 + "[E]" + t4); + _this._progressLine$2$color("Some tests failed.", t3); + } else { + t1 = t1._passedGroup._union_set_controller$_set; + if (t1.get$length(t1) === 0) + _this._progressLine$1("All tests skipped."); + else + _this._progressLine$1("All tests passed!"); + } + }, + _progressLine$3$color$suffix: function(message, color, suffix) { + var t4, t5, _this = this, + t1 = _this._engine, + t2 = t1._passedGroup, + t3 = t2._union_set_controller$_set; + if (t3.get$length(t3) == _this._lastProgressPassed) { + t3 = t1._skippedGroup._union_set_controller$_set; + if (t3.get$length(t3) == _this._lastProgressSkipped) { + t3 = t1._failedGroup._union_set_controller$_set; + if (t3.get$length(t3) == _this._lastProgressFailed) + if (message == _this._lastProgressMessage) + t3 = suffix == null || suffix === _this._lastProgressSuffix; + else + t3 = false; + else + t3 = false; + } else + t3 = false; + } else + t3 = false; + if (t3) + return; + t3 = t2._union_set_controller$_set; + _this._lastProgressPassed = t3.get$length(t3); + t3 = t1._skippedGroup; + t4 = t3._union_set_controller$_set; + _this._lastProgressSkipped = t4.get$length(t4); + t1 = t1._failedGroup; + t4 = t1._union_set_controller$_set; + _this._lastProgressFailed = t4.get$length(t4); + _this._lastProgressMessage = message; + _this._lastProgressSuffix = suffix; + if (suffix != null) + message = J.$add$ansx(message, suffix); + if (color == null) + color = ""; + t4 = P.Duration$(_this._stopwatch.get$elapsedMicroseconds(), 0)._duration; + t4 = C.JSString_methods.padLeft$2(C.JSInt_methods.toString$0(C.JSInt_methods._tdivFast$1(t4, 60000000)), 2, "0") + ":" + C.JSString_methods.padLeft$2(C.JSInt_methods.toString$0(C.JSInt_methods.$mod(C.JSInt_methods._tdivFast$1(t4, 1000000), 60)), 2, "0") + " " + _this._green + "+"; + t2 = t2._union_set_controller$_set; + t5 = _this._noColor; + t2 = t4 + H.S(t2.get$length(t2)) + t5; + t4 = t3._union_set_controller$_set; + if (t4.get$length(t4) !== 0) { + t2 = t2 + _this._yellow + " ~"; + t3 = t3._union_set_controller$_set; + t3 = t2 + H.S(t3.get$length(t3)) + t5; + t2 = t3; + } + t3 = t1._union_set_controller$_set; + if (t3.get$length(t3) !== 0) { + t2 = t2 + _this._red + " -"; + t1 = t1._union_set_controller$_set; + t1 = t2 + H.S(t1.get$length(t1)) + t5; + } else + t1 = t2; + t5 = t1 + ": " + color + H.S(message) + t5; + _this._expanded$_sink.writeln$1(t5.charCodeAt(0) == 0 ? t5 : t5); + }, + _progressLine$2$suffix: function(message, suffix) { + return this._progressLine$3$color$suffix(message, null, suffix); + }, + _progressLine$2$color: function(message, color) { + return this._progressLine$3$color$suffix(message, color, null); + }, + _progressLine$1: function(message) { + return this._progressLine$3$color$suffix(message, null, null); + }, + _description$1: function(liveTest) { + var t1 = liveTest._live_test_controller$_controller; + return t1._test.name; + } + }; + R.ExpandedReporter__onTestStarted_closure.prototype = { + call$1: function(state) { + return this.$this._onStateChange$2(this.liveTest, type$.State._check(state)); + }, + $signature: 100 + }; + R.ExpandedReporter__onTestStarted_closure0.prototype = { + call$1: function(error) { + type$.AsyncError._check(error); + return this.$this._expanded$_onError$3(this.liveTest, error.error, error.stackTrace); + }, + $signature: 101 + }; + R.ExpandedReporter__onTestStarted_closure1.prototype = { + call$1: function(message) { + var t1, text; + type$.Message._check(message); + t1 = this.$this; + t1._progressLine$1(t1._description$1(this.liveTest)); + text = message.text; + if (message.type === C.MessageType_skip) + text = " " + t1._yellow + text + t1._noColor; + t1._expanded$_sink.writeln$1(text); + }, + $signature: 27 + }; + Y.RunnerSuite.prototype = {}; + Y.RunnerSuiteController.prototype = { + _runner_suite$_close$0: function() { + return this._closeMemo.runOnce$1(new Y.RunnerSuiteController__close_closure(this)); + }, + set$_runner_suite$_suite: function(_suite) { + type$.Future_RunnerSuite._check(_suite); + } + }; + Y.RunnerSuiteController__close_closure.prototype = { + call$0: function() { + var $async$goto = 0, + $async$completer = P._makeAsyncAwaitCompleter(type$.Null), + $async$self = this; + var $async$call$0 = P._wrapJsFunctionForAsync(function($async$errorCode, $async$result) { + if ($async$errorCode === 1) + return P._asyncRethrow($async$result, $async$completer); + while (true) + switch ($async$goto) { + case 0: + // Function start + $async$goto = 2; + return P._asyncAwait($async$self.$this._onDebuggingController.close$0(0), $async$call$0); + case 2: + // returning from await. + // implicit return + return P._asyncReturn(null, $async$completer); + } + }); + return P._asyncStartSync($async$call$0, $async$completer); + }, + $signature: 2 + }; + T.RuntimeSelection.prototype = {}; + U.SuiteConfiguration.prototype = {}; + X.PrintSink.prototype = { + writeln$1: function(obj) { + this._print_sink$_buffer._contents += obj + "\n"; + this._flush$0(); + }, + _flush$0: function() { + var t1 = this._print_sink$_buffer; + if (C.JSString_methods.endsWith$1(t1.toString$0(0), "\n")) { + P.print(t1); + t1._contents = ""; + } + }, + $isStringSink: 1 + }; + E.JSStackTraceMapper.prototype = {}; + E.JSStackTraceMapper__deserializePackageConfigMap_closure.prototype = { + call$2: function(key, value) { + return new P.MapEntry(H._checkStringNullable(key), P.Uri_parse(H._checkStringNullable(value)), type$.MapEntry_String_Uri); + }, + $signature: 102 + }; + R._declarer_closure.prototype = { + call$0: function() { + var $async$goto = 0, + $async$completer = P._makeAsyncAwaitCompleter(type$.Null), + $async$returnValue, controller, suite, engine, t1, t2, t3, t4, $async$temp1; + var $async$call$0 = P._wrapJsFunctionForAsync(function($async$errorCode, $async$result) { + if ($async$errorCode === 1) + return P._asyncRethrow($async$result, $async$completer); + while (true) + switch ($async$goto) { + case 0: + // Function start + t1 = $.$get$SuiteConfiguration_empty(); + t2 = $._globalDeclarer.build$0(); + t3 = E.SuitePlatform$(C.Runtime_ql0, false, $.$get$currentOSGuess()); + t4 = P.Uri_base(); + t4 = $.$get$context().prettyUri$1(t4); + controller = new Y.RunnerSuiteController(t1, null, new P._AsyncBroadcastStreamController(null, null, type$._AsyncBroadcastStreamController_bool), P.LinkedHashSet_LinkedHashSet$_empty(type$.String), new S.AsyncMemoizer(new P._AsyncCompleter(new P._Future($.Zone__current, type$._Future_dynamic), type$._AsyncCompleter_dynamic), type$.AsyncMemoizer_dynamic)); + suite = new Y.RunnerSuite(controller, t3, t4, U.Suite__filterGroup(t2, t3)); + t1 = new P._Future($.Zone__current, type$._Future_RunnerSuite); + t1._asyncComplete$1(suite); + controller.set$_runner_suite$_suite(t1); + engine = O.Engine$(); + t1 = engine._suiteController; + t1.add$1(0, H._instanceType(t1)._precomputed1._check(type$.RunnerSuite._check(suite))); + t1.close$0(0); + if ($.Stopwatch__frequency == null) { + H.Primitives_initTicker(); + $.Stopwatch__frequency = $.Primitives_timerFrequency; + } + t1 = P.LinkedHashSet_LinkedHashSet$_empty(type$.StreamSubscription_dynamic); + t2 = new R.ExpandedReporter(true, "\x1b[32m", "\x1b[31m", "\x1b[33m", "\x1b[1;30m", "\x1b[1m", "\x1b[0m", engine, false, false, new P.Stopwatch(), t1, new X.PrintSink(new P.StringBuffer(""))); + t3 = engine._onTestStartedGroup._stream_group$_controller; + t3.toString; + t1.add$1(0, new P._BroadcastStream(t3, H._instanceType(t3)._eval$1("_BroadcastStream<1>")).listen$1(t2.get$_onTestStarted())); + t3 = engine.get$success(); + t3.toString; + t1.add$1(0, P.Stream_Stream$fromFuture(t3, t3.$ti._precomputed1).listen$1(t2.get$_expanded$_onDone())); + t2 = type$.dynamic; + $async$temp1 = H; + $async$goto = 3; + return P._asyncAwait(P.runZoned(new R._declarer__closure(engine), null, null, P.LinkedHashMap_LinkedHashMap$_literal([C.Symbol_Drw, $._globalDeclarer], t2, t2), type$.Future_bool), $async$call$0); + case 3: + // returning from await. + if ($async$temp1.boolConversionCheck($async$result)) { + $async$returnValue = null; + // goto return + $async$goto = 1; + break; + } + P.print(""); + P.Future_Future$error("Dummy exception to set exit code.", null, type$.void); + case 1: + // return + return P._asyncReturn($async$returnValue, $async$completer); + } + }); + return P._asyncStartSync($async$call$0, $async$completer); + }, + $signature: 2 + }; + R._declarer__closure.prototype = { + call$0: function() { + return U.Invoker_guard(this.engine.get$run(), type$.Future_bool); + }, + $signature: 31 + }; + G.main_closure0.prototype = { + call$0: function() { + R.test("sample test", new G.main__closure()); + }, + $signature: 0 + }; + G.main__closure.prototype = { + call$0: function() { + var $async$goto = 0, + $async$completer = P._makeAsyncAwaitCompleter(type$.Null), + res; + var $async$call$0 = P._wrapJsFunctionForAsync(function($async$errorCode, $async$result) { + if ($async$errorCode === 1) + return P._asyncRethrow($async$result, $async$completer); + while (true) + switch ($async$goto) { + case 0: + // Function start + res = G.method1(); + if (res === 0) + G.method2(); + G.expect(true, C.C__IsTrue, null); + // implicit return + return P._asyncReturn(null, $async$completer); + } + }); + return P._asyncStartSync($async$call$0, $async$completer); + }, + $signature: 2 + }; + R.main_closure.prototype = { + call$0: function() { + return G.main_test__main$closure(); + }, + $signature: 103 + }; + (function aliases() { + var _ = J.JavaScriptObject.prototype; + _.super$JavaScriptObject$toString = _.toString$0; + _ = P._BroadcastStreamController.prototype; + _.super$_BroadcastStreamController$_addEventError = _._addEventError$0; + _ = P.Iterable.prototype; + _.super$Iterable$where = _.where$1; + _.super$Iterable$skipWhile = _.skipWhile$1; + _ = W.EventTarget.prototype; + _.super$EventTarget$addEventListener = _.addEventListener$3; + _ = Y.DelegatingStreamSubscription.prototype; + _.super$DelegatingStreamSubscription$onError = _.onError$1; + _.super$DelegatingStreamSubscription$cancel = _.cancel$0; + _ = M.TypeMatcher.prototype; + _.super$TypeMatcher$describe = _.describe$1; + _.super$TypeMatcher$matches = _.matches$2; + _ = Y.SourceSpanMixin.prototype; + _.super$SourceSpanMixin$$eq = _.$eq; + _ = X.StringScanner.prototype; + _.super$StringScanner$matches = _.matches$1; + })(); + (function installTearOffs() { + var _instance = hunkHelpers.installInstanceTearOff, + _static_0 = hunkHelpers._static_0, + _static_1 = hunkHelpers._static_1, + _static = hunkHelpers.installStaticTearOff, + _instance_0_u = hunkHelpers._instance_0u, + _instance_1_i = hunkHelpers._instance_1i, + _instance_0_i = hunkHelpers._instance_0i, + _instance_1_u = hunkHelpers._instance_1u, + _instance_2_u = hunkHelpers._instance_2u; + _instance(J.JSString.prototype, "get$startsWith", 1, 1, null, ["call$2", "call$1"], ["startsWith$2", "startsWith$1"], 57, 0); + _static_0(H, "_js_helper_Primitives_dateNow$closure", "Primitives_dateNow", 36); + _static_1(P, "async__AsyncRun__scheduleImmediateJsOverride$closure", "_AsyncRun__scheduleImmediateJsOverride", 20); + _static_1(P, "async__AsyncRun__scheduleImmediateWithSetImmediate$closure", "_AsyncRun__scheduleImmediateWithSetImmediate", 20); + _static_1(P, "async__AsyncRun__scheduleImmediateWithTimer$closure", "_AsyncRun__scheduleImmediateWithTimer", 20); + _static_1(P, "async_Future__kTrue$closure", "Future__kTrue", 9); + _static_0(P, "async___startMicrotaskLoop$closure", "_startMicrotaskLoop", 1); + _static_1(P, "async___nullDataHandler$closure", "_nullDataHandler", 11); + _static(P, "async___nullErrorHandler$closure", 1, null, ["call$2", "call$1"], ["_nullErrorHandler", function(error) { + return P._nullErrorHandler(error, null); + }], 12, 0); + _static_0(P, "async___nullDoneHandler$closure", "_nullDoneHandler", 1); + _static(P, "async___rootHandleUncaughtError$closure", 5, null, ["call$5"], ["_rootHandleUncaughtError"], 105, 0); + _static(P, "async___rootRun$closure", 4, null, ["call$1$4", "call$4"], ["_rootRun", function($self, $parent, zone, f) { + return P._rootRun($self, $parent, zone, f, type$.dynamic); + }], 106, 0); + _static(P, "async___rootRunUnary$closure", 5, null, ["call$2$5", "call$5"], ["_rootRunUnary", function($self, $parent, zone, f, arg) { + return P._rootRunUnary($self, $parent, zone, f, arg, type$.dynamic, type$.dynamic); + }], 107, 0); + _static(P, "async___rootRunBinary$closure", 6, null, ["call$3$6"], ["_rootRunBinary"], 108, 0); + _static(P, "async___rootRegisterCallback$closure", 4, null, ["call$1$4", "call$4"], ["_rootRegisterCallback", function($self, $parent, zone, f) { + return P._rootRegisterCallback($self, $parent, zone, f, type$.dynamic); + }], 35, 0); + _static(P, "async___rootRegisterUnaryCallback$closure", 4, null, ["call$2$4", "call$4"], ["_rootRegisterUnaryCallback", function($self, $parent, zone, f) { + return P._rootRegisterUnaryCallback($self, $parent, zone, f, type$.dynamic, type$.dynamic); + }], 33, 0); + _static(P, "async___rootRegisterBinaryCallback$closure", 4, null, ["call$3$4", "call$4"], ["_rootRegisterBinaryCallback", function($self, $parent, zone, f) { + return P._rootRegisterBinaryCallback($self, $parent, zone, f, type$.dynamic, type$.dynamic, type$.dynamic); + }], 109, 0); + _static(P, "async___rootErrorCallback$closure", 5, null, ["call$5"], ["_rootErrorCallback"], 32, 0); + _static(P, "async___rootScheduleMicrotask$closure", 4, null, ["call$4"], ["_rootScheduleMicrotask"], 110, 0); + _static(P, "async___rootCreateTimer$closure", 5, null, ["call$5"], ["_rootCreateTimer"], 111, 0); + _static(P, "async___rootCreatePeriodicTimer$closure", 5, null, ["call$5"], ["_rootCreatePeriodicTimer"], 112, 0); + _static(P, "async___rootPrint$closure", 4, null, ["call$4"], ["_rootPrint"], 37, 0); + _static_1(P, "async___printToZone$closure", "_printToZone", 113); + _static(P, "async___rootFork$closure", 5, null, ["call$5"], ["_rootFork"], 114, 0); + var _; + _instance_0_u(_ = P._BroadcastSubscription.prototype, "get$_onPause", "_onPause$0", 1); + _instance_0_u(_, "get$_onResume", "_onResume$0", 1); + _instance_1_i(_ = P._BroadcastStreamController.prototype, "get$add", "add$1", 11); + _instance(_, "get$addError", 0, 1, null, ["call$2", "call$1"], ["addError$2", "addError$1"], 12, 0); + _instance(P._AsyncCompleter.prototype, "get$complete", 0, 0, null, ["call$1", "call$0"], ["complete$1", "complete$0"], 47, 0); + _instance(P._SyncCompleter.prototype, "get$complete", 0, 0, null, ["call$1", "call$0"], ["complete$1", "complete$0"], 47, 0); + _instance(P._Future.prototype, "get$_completeError", 0, 1, null, ["call$2", "call$1"], ["_completeError$2", "_completeError$1"], 12, 0); + _instance_1_i(_ = P._StreamController.prototype, "get$add", "add$1", 11); + _instance(_, "get$addError", 0, 1, null, ["call$2", "call$1"], ["addError$2", "addError$1"], 12, 0); + _instance_0_i(_, "get$close", "close$0", 14); + _instance_1_u(_, "get$_add", "_add$1", 11); + _instance_2_u(_, "get$_async$_addError", "_async$_addError$2", 70); + _instance_0_u(_, "get$_close", "_close$0", 1); + _instance_0_u(_ = P._ControllerSubscription.prototype, "get$_onPause", "_onPause$0", 1); + _instance_0_u(_, "get$_onResume", "_onResume$0", 1); + _instance_1_i(P._StreamSinkWrapper.prototype, "get$add", "add$1", 11); + _instance_0_u(_ = P._BufferingStreamSubscription.prototype, "get$_onPause", "_onPause$0", 1); + _instance_0_u(_, "get$_onResume", "_onResume$0", 1); + _instance_0_u(P._DoneStreamSubscription.prototype, "get$_sendDone", "_sendDone$0", 1); + _instance_1_i(P._LinkedHashSet.prototype, "get$contains", "contains$1", 26); + _static_1(P, "core_Uri_decodeComponent$closure", "Uri_decodeComponent", 7); + _instance_0_i(S.NullStreamSink.prototype, "get$close", "close$0", 14); + _instance_0_u(_ = L.StreamGroup.prototype, "get$_onListen", "_onListen$0", 1); + _instance_0_u(_, "get$_onCancelBroadcast", "_onCancelBroadcast$0", 1); + _instance_1_i(M._DelegatingIterableBase.prototype, "get$contains", "contains$1", 26); + _instance(D._DeepMatcher.prototype, "get$_recursiveMatch", 0, 4, null, ["call$4"], ["_recursiveMatch$4"], 58, 0); + _static_1(Z, "pretty_print___escapeString$closure", "_escapeString", 7); + _static_1(M, "util___getHexLiteral$closure", "_getHexLiteral", 7); + _instance(Y.SourceSpanMixin.prototype, "get$message", 1, 1, null, ["call$2$color", "call$1"], ["message$2$color", "message$1"], 71, 0); + _instance(_ = O.StackZoneSpecification.prototype, "get$_stack_zone_specification$_registerCallback", 0, 4, null, ["call$1$4", "call$4"], ["_stack_zone_specification$_registerCallback$1$4", "_stack_zone_specification$_registerCallback$4"], 35, 0); + _instance(_, "get$_stack_zone_specification$_registerUnaryCallback", 0, 4, null, ["call$2$4", "call$4"], ["_stack_zone_specification$_registerUnaryCallback$2$4", "_stack_zone_specification$_registerUnaryCallback$4"], 33, 0); + _instance(_, "get$_stack_zone_specification$_registerBinaryCallback", 0, 4, null, ["call$3$4", "call$4"], ["_stack_zone_specification$_registerBinaryCallback$3$4", "_stack_zone_specification$_registerBinaryCallback$4"], 63, 0); + _instance(_, "get$_stack_zone_specification$_errorCallback", 0, 5, null, ["call$5"], ["_stack_zone_specification$_errorCallback$5"], 32, 0); + _instance(_ = K._GuaranteeSink.prototype, "get$addError", 0, 1, null, ["call$2", "call$1"], ["addError$2", "addError$1"], 12, 0); + _instance(_, "get$_addError", 0, 1, null, ["call$2", "call$1"], ["_addError$2", "_addError$1"], 66, 0); + _instance_0_i(_, "get$close", "close$0", 13); + _instance_0_u(D._MultiChannel.prototype, "get$_closeInnerChannel", "_closeInnerChannel$0", 1); + _instance_0_u(_ = U.Invoker.prototype, "get$_invoker$_onRun", "_invoker$_onRun$0", 1); + _instance_0_u(_, "get$_runTearDowns", "_runTearDowns$0", 13); + _instance_0_u(V._LiveTest.prototype, "get$run", "run$0", 13); + _instance_1_i(V.LiveTestController.prototype, "get$message", "message$1", 96); + _instance_0_u(O.Engine.prototype, "get$run", "run$0", 31); + _instance_1_u(_ = R.ExpandedReporter.prototype, "get$_onTestStarted", "_onTestStarted$1", 98); + _instance_1_u(_, "get$_expanded$_onDone", "_expanded$_onDone$1", 99); + _static_0(G, "main_test__main$closure", "main0", 34); + _static(P, "math__max$closure", 2, null, ["call$1$2", "call$2"], ["max", function(a, b) { + return P.max(a, b, type$.num); + }], 76, 0); + })(); + (function inheritance() { + var _mixin = hunkHelpers.mixin, + _inherit = hunkHelpers.inherit, + _inheritMany = hunkHelpers.inheritMany; + _inherit(P.Object, null); + _inheritMany(P.Object, [H.JS_CONST, J.Interceptor, J.JSObject, J.ArrayIterator, P.Iterable, H.CastIterator, P.MapMixin, H.Closure, P._ListBase_Object_ListMixin, H.ListIterator, P.Iterator, H.ExpandIterator, H.EmptyIterator, H.FixedLengthListMixin, H.UnmodifiableListMixin, H.Symbol, H.ConstantMap, H.TypeErrorDecoder, P.Error, H.ExceptionAndStackTrace, H._StackTrace, H.LinkedHashMapCell, H.LinkedHashMapKeyIterator, H.JSSyntaxRegExp, H._MatchImplementation, H._AllMatchesIterator, H.StringMatch, H._StringAllMatchesIterator, H.Rti, H._FunctionParameters, H._Type, P._TimerImpl, P._AsyncAwaitCompleter, P.Stream, P._BufferingStreamSubscription, P._BroadcastStreamController, P.Future, P.TimeoutException, P.Completer, P._Completer, P._FutureListener, P._Future, P._AsyncCallbackEntry, P.StreamSubscription, P.StreamTransformerBase, P._StreamController, P._SyncStreamControllerDispatch, P._AsyncStreamControllerDispatch, P._StreamSinkWrapper, P._AddStreamState, P._PendingEvents, P._DelayedEvent, P._DelayedDone, P._DoneStreamSubscription, P._StreamIterator, P.Timer, P.AsyncError, P._ZoneFunction, P.ZoneSpecification, P._ZoneSpecification, P.ZoneDelegate, P.Zone, P._ZoneDelegate, P._Zone, P._HashMapKeyIterator, P._SetBase, P._LinkedHashSetCell, P._LinkedHashSetIterator, P.ListMixin, P._UnmodifiableMapMixin, P.MapView, P._ListQueueIterator, P.SetMixin, P._SetBase_Object_SetMixin, P.Codec, P._Utf8Encoder, P._Utf8Decoder, P.bool, P.DateTime, P.num, P.Duration, P.OutOfMemoryError, P.StackOverflowError, P._Exception, P.FormatException, P.Expando, P.Function, P.List, P.Map, P.MapEntry, P.Null, P.Pattern, P.Match, P.RegExpMatch, P.StackTrace, P._StringStackTrace, P.Stopwatch, P.String, P.RuneIterator, P.StringBuffer, P.Uri, P._Uri, P.UriData, P._SimpleUri, W.EventStreamProvider, P._StructuredClone, P._AcceptStructuredClone, P.ByteBuffer, P.ByteData, P.Int8List, P.Uint8List, P.Uint8ClampedList, P.Int16List, P.Uint16List, P.Int32List, P.Uint32List, P.Float32List, P.Float64List, S.AsyncMemoizer, O.DelegatingSink, Y.DelegatingStreamSubscription, F.FutureGroup, S.NullStreamSink, V.ErrorResult, E.Result, F.ValueResult, Y.StreamCompleter, L.StreamGroup, L._StreamGroupState, G.StreamQueue, G._EventRequest, G._NextRequest, G._RestRequest, T.StreamSinkCompleter, T._CompleterSink, X.BooleanSelector, X.All, U.VariableNode, U.NotNode, U.OrNode, U.AndNode, U.ConditionalNode, T.Evaluator, Y.BooleanSelectorImpl, R.IntersectionSelector, O.None, G.Parser, O.Scanner, L.Token, L.IdentifierToken, L.TokenType, B.RecursiveVisitor, Q._QueueList_Object_ListMixin, Y.UnionSetController, M._DelegatingIterableBase, L.UnmodifiableSetMixin, G.Matcher, E.StringDescription, F.PackageConfigResolver, D.PackageRootResolver, M.Context, M._PathDirection, M._PathRelation, O.Style, X.ParsedPath, X.PathException, O.Pool, O.PoolResource, T.Mapping, T.TargetLineEntry, T.TargetEntry, T._MappingTokenizer, T._TokenKind, Y.SourceSpanMixin, Y.SourceFile, D.SourceLocationMixin, U.Highlighter, V.SourceLocation, V.SourceSpan, G.SourceSpanException, U.Chain, A.Frame, X.LazyChain, T.LazyTrace, O.StackZoneSpecification, O._Node, Y.Trace, N.UnparsedFrame, R.StreamChannelMixin, K._GuaranteeSink, N.StreamChannelCompleter, B.StreamChannelController, R.StreamChannel, X.StringScanner, S._SpanScannerState, A.AsciiGlyphSet, K.UnicodeGlyphSet, K.ClosedException, X.Declarer, O.Group, V.GroupEntry, V.Test, U.Invoker, U._AsyncCounter, Z.LiveTest, V.LiveTestController, D.Message, D.MessageType, O.Metadata, N.OperatingSystem, E.PlatformSelector, B.Runtime, U.StackTraceFormatter, G.State, G.Status, G.Result0, U.Suite, E.SuitePlatform, G.TestFailure, R.Timeout, S.RemoteListener, N.SuiteChannelManager, E.StackTraceMapper, O.Engine, E.LiveSuite, B.LiveSuiteController, R.ExpandedReporter, Y.RunnerSuiteController, T.RuntimeSelection, U.SuiteConfiguration, X.PrintSink]); + _inheritMany(J.Interceptor, [J.JSBool, J.JSNull, J.JavaScriptObject, J.JSArray, J.JSNumber, J.JSString, H.NativeByteBuffer, H.NativeTypedData, W.Event, W.Blob, W.DomError, W.DomException, W.EventTarget, W.Location, W.MediaError, W.NavigatorUserMediaError, W.OverconstrainedError, W.PositionError, P.SqlError]); + _inheritMany(J.JavaScriptObject, [J.PlainJavaScriptObject, J.UnknownJavaScriptObject, J.JavaScriptFunction]); + _inherit(J.JSUnmodifiableArray, J.JSArray); + _inheritMany(J.JSNumber, [J.JSInt, J.JSDouble]); + _inheritMany(P.Iterable, [H._CastIterableBase, H.EfficientLengthIterable, H.MappedIterable, H.WhereIterable, H.ExpandIterable, H.SkipWhileIterable, H._ConstantMapKeyIterable, P.IterableBase, H._StringAllMatchesIterable, P.Runes]); + _inherit(H.CastIterable, H._CastIterableBase); + _inherit(H._EfficientLengthCastIterable, H.CastIterable); + _inherit(P.MapBase, P.MapMixin); + _inheritMany(P.MapBase, [H.CastMap, H.JsLinkedHashMap, P._HashMap, P._JsonMap]); + _inheritMany(H.Closure, [H.CastMap_forEach_closure, H.ConstantMap_map_closure, H.Instantiation, H.Primitives_initTicker_closure, H.unwrapException_saveStackTrace, H.TearOffClosure, H.JsLinkedHashMap_values_closure, H.JsLinkedHashMap_addAll_closure, H.initHooks_closure, H.initHooks_closure0, H.initHooks_closure1, P._AsyncRun__initializeScheduleImmediate_internalCallback, P._AsyncRun__initializeScheduleImmediate_closure, P._AsyncRun__scheduleImmediateJsOverride_internalCallback, P._AsyncRun__scheduleImmediateWithSetImmediate_internalCallback, P._TimerImpl_internalCallback, P._TimerImpl$periodic_closure, P._awaitOnObject_closure, P._awaitOnObject_closure0, P._wrapJsFunctionForAsync_closure, P._SyncBroadcastStreamController__sendData_closure, P._SyncBroadcastStreamController__sendError_closure, P._SyncBroadcastStreamController__sendDone_closure, P.Future_Future_closure, P.Future_Future$microtask_closure, P.Future_wait_handleError, P.Future_wait_closure, P.Future_forEach_closure, P.Future_doWhile_closure, P._Future__addListener_closure, P._Future__prependListeners_closure, P._Future__chainForeignFuture_closure, P._Future__chainForeignFuture_closure0, P._Future__chainForeignFuture_closure1, P._Future__asyncComplete_closure, P._Future__chainFuture_closure, P._Future__asyncCompleteError_closure, P._Future__propagateToListeners_handleWhenCompleteCallback, P._Future__propagateToListeners_handleWhenCompleteCallback_closure, P._Future__propagateToListeners_handleValueCallback, P._Future__propagateToListeners_handleError, P.Stream_Stream$fromFuture_closure, P.Stream_Stream$fromFuture_closure0, P.Stream_Stream$fromIterable_closure, P.Stream_pipe_closure, P.Stream_length_closure, P.Stream_length_closure0, P.Stream_first_closure, P.Stream_first_closure0, P.Stream_last_closure, P.Stream_last_closure0, P.Stream_firstWhere_closure, P.Stream_firstWhere__closure, P.Stream_firstWhere__closure0, P.Stream_firstWhere_closure0, P._StreamController__subscribe_closure, P._StreamController__recordCancel_complete, P._AddStreamState_makeErrorHandler_closure, P._AddStreamState_cancel_closure, P._BufferingStreamSubscription__sendError_sendError, P._BufferingStreamSubscription__sendDone_sendDone, P._PendingEvents_schedule_closure, P._cancelAndError_closure, P._cancelAndErrorClosure_closure, P._cancelAndValue_closure, P._CustomZone_bindCallback_closure, P._CustomZone_bindUnaryCallback_closure, P._CustomZone_bindCallbackGuarded_closure, P._CustomZone_bindUnaryCallbackGuarded_closure, P._rootHandleUncaughtError_closure, P._RootZone_bindCallback_closure, P._RootZone_bindCallbackGuarded_closure, P._RootZone_bindUnaryCallbackGuarded_closure, P.runZoned_closure, P.HashMap_HashMap$from_closure, P.LinkedHashMap_LinkedHashMap$from_closure, P.MapBase_mapToString_closure, P.Duration_toString_sixDigits, P.Duration_toString_twoDigits, P.Uri__parseIPv4Address_error, P.Uri_parseIPv6Address_error, P.Uri_parseIPv6Address_parseHex, P._Uri__Uri$notSimple_closure, P._Uri__checkNonWindowsPathReservedCharacters_closure, P._Uri__makePath_closure, P._createTables_closure, P._createTables_build, P._createTables_setChars, P._createTables_setRange, W._EventStreamSubscription_closure, P._StructuredClone_walk_closure, P._StructuredClone_walk_closure0, P._AcceptStructuredClone_walk_closure, P._convertDataTree__convert, P.promiseToFuture_closure, P.promiseToFuture_closure0, F.FutureGroup_add_closure, F.FutureGroup_add_closure0, S.NullStreamSink_addStream_closure, L.StreamGroup_add_closure, L.StreamGroup_add_closure0, L.StreamGroup__onListen_closure, L.StreamGroup__onCancelBroadcast_closure, L.StreamGroup__listenToStream_closure, G.StreamQueue__ensureListening_closure, G.StreamQueue__ensureListening_closure1, G.StreamQueue__ensureListening_closure0, T._CompleterSink__setDestinationSink_closure, T._CancelOnErrorSubscriptionWrapper_onError_closure, T._CancelOnErrorSubscriptionWrapper_onError__closure, Y.mapMap_closure, Y.mapMap_closure0, Y.mergeMaps_closure, M.UnionSet_length_closure, M.UnionSet__iterable_closure, D._DeepMatcher__compareSets_closure, Z.prettyPrint__prettyPrint, Z.prettyPrint__prettyPrint_pp, Z.prettyPrint__prettyPrint_closure, Z.prettyPrint__prettyPrint_closure0, Z.prettyPrint__prettyPrint_closure1, M.wrapMatcher_closure, M.escape_closure, F.PackageConfigResolver__normalizeMap_closure, M.Context_join_closure, M.Context_joinAll_closure, M.Context_split_closure, M._validateArgList_closure, X.ParsedPath_normalize_closure, L.WindowsStyle_absolutePathToUri_closure, O.Pool_close_closure, O.Pool__onResourceReleaseAllowed_closure, O.Pool__runOnRelease_closure, O.Pool__runOnRelease_closure0, O.mapStackTrace_closure, O.mapStackTrace_closure0, O.mapStackTrace_closure1, O._prettifyMember_closure, O._prettifyMember_closure0, T.SingleMapping$fromJson_closure, T.SingleMapping__findLine_closure, T.SingleMapping__findColumn_closure, L.closure, U.Highlighter__writeFirstLine_closure, U.Highlighter__writeFirstLine_closure0, U.Highlighter__writeFirstLine_closure1, U.Highlighter__writeFirstLine_closure2, U.Highlighter__writeIntermediateLines_closure, U.Highlighter__writeLastLine_closure, U.Highlighter__writeLastLine_closure0, U.Highlighter__writeLastLine_closure1, U.Highlighter__writeSidebar_closure, U.Chain_capture_closure, U.Chain_Chain$current_closure, U.Chain_Chain$forTrace_closure, U.Chain_Chain$parse_closure, U.Chain_Chain$parse_closure0, U.Chain_foldFrames_closure, U.Chain_foldFrames_closure0, U.Chain_toTrace_closure, U.Chain_toString_closure0, U.Chain_toString__closure0, U.Chain_toString_closure, U.Chain_toString__closure, A.Frame_Frame$parseVM_closure, A.Frame_Frame$parseV8_closure, A.Frame_Frame$parseV8_closure_parseLocation, A.Frame_Frame$parseFirefox_closure, A.Frame_Frame$parseFriendly_closure, X.LazyChain_foldFrames_closure, X.LazyChain_toTrace_closure, T.LazyTrace_foldFrames_closure, O.StackZoneSpecification_chainFor_closure, O.StackZoneSpecification_chainFor_closure0, O.StackZoneSpecification__registerCallback_closure, O.StackZoneSpecification__registerUnaryCallback_closure, O.StackZoneSpecification__registerUnaryCallback__closure, O.StackZoneSpecification__registerBinaryCallback_closure, O.StackZoneSpecification__registerBinaryCallback__closure, O.StackZoneSpecification__currentTrace_closure, Y.Trace_Trace$current_closure, Y.Trace_Trace$from_closure, Y.Trace__parseVM_closure, Y.Trace$parseV8_closure, Y.Trace$parseV8_closure0, Y.Trace$parseJSCore_closure, Y.Trace$parseJSCore_closure0, Y.Trace$parseFirefox_closure, Y.Trace$parseFirefox_closure0, Y.Trace$parseFriendly_closure, Y.Trace$parseFriendly_closure0, Y.Trace_foldFrames_closure, Y.Trace_foldFrames_closure0, Y.Trace_toString_closure0, Y.Trace_toString_closure, K.GuaranteeChannel_closure, K.GuaranteeChannel__closure, K._GuaranteeSink__addError_closure, K._GuaranteeSink_addStream_closure, D._MultiChannel_closure, D._MultiChannel_closure0, D._MultiChannel_closure1, D._MultiChannel__closure, D._MultiChannel_virtualChannel_closure, D._MultiChannel_virtualChannel_closure0, L.internalBootstrapBrowserTest_closure, N.postMessageChannel_closure, N.postMessageChannel_closure0, N.postMessageChannel__closure, N.postMessageChannel__closure0, N.postMessageChannel__closure1, X.Declarer_test_closure, X.Declarer_test__closure, X.Declarer_test___closure, X.Declarer_group_closure, X.Declarer_build_closure, X.Declarer__runSetUps_closure, X.Declarer__tearDownAll_closure, X.Declarer__tearDownAll__closure, X.Declarer__tearDownAll___closure, O.Group_forPlatform_closure, O.Group__map_closure, O.Group__map_closure0, U.Invoker_guard_closure, U.Invoker_guard__closure, U.Invoker_waitForOutstandingCallbacks_closure, U.Invoker_waitForOutstandingCallbacks_closure0, U.Invoker_heartbeat_message, U.Invoker_heartbeat_closure, U.Invoker_heartbeat__closure, U.Invoker__handleError_closure, U.Invoker__handleError_closure0, U.Invoker__onRun_closure, U.Invoker__onRun__closure, U.Invoker__onRun___closure, U.Invoker__onRun____closure, U.Invoker__onRun___closure0, O.Metadata_Metadata__unresolved, O.Metadata_Metadata_closure, O.Metadata$deserialize_closure, O.Metadata__validateTags_closure, O.Metadata__validateTags_closure0, O.Metadata_validatePlatformSelectors_closure, O.Metadata_merge_closure, O.Metadata_merge_closure0, O.Metadata_forPlatform_closure, O.Metadata_serialize_closure, O.Metadata_serialize_closure0, N.OperatingSystem_find_closure, N.OperatingSystem_find_closure0, E.PlatformSelector$parse_closure, E.PlatformSelector_validate_closure, E.PlatformSelector_validate__closure, E.PlatformSelector_evaluate_closure, B.Runtime_Runtime$deserialize_closure, U.StackTraceFormatter_formatStackTrace_closure, G._expect_closure0, G._expect_closure, S.RemoteListener_start_closure, S.RemoteListener_start_closure0, S.RemoteListener_start_closure1, S.RemoteListener_start__closure, S.RemoteListener_start___closure, S.RemoteListener_start____closure, S.RemoteListener_start____closure0, S.RemoteListener_start_____closure, S.RemoteListener_start___closure0, S.RemoteListener__serializeGroup_closure, S.RemoteListener__serializeTest_closure, S.RemoteListener__runLiveTest_closure, S.RemoteListener__runLiveTest_closure0, S.RemoteListener__runLiveTest_closure1, S.RemoteListener__runLiveTest_closure2, S.RemoteListener__runLiveTest_closure3, S.RemoteListener__runLiveTest__closure, V.errorsDontStopTest_closure, V.errorsDontStopTest_closure0, B.closure0, O.Engine_success_closure, O.Engine_closure, O.Engine_closure0, O.Engine_run_closure, O.Engine_run__closure, O.Engine_run___closure, O.Engine_run____closure, O.Engine_run_closure0, O.Engine__runLiveTest_closure, O.Engine__runLiveTest_closure0, O.Engine__runLiveTest_closure1, O.Engine__runSkippedTest_closure, O.Engine__runSkippedTest_closure0, O.Engine__runSkippedTest_closure1, B.LiveSuiteController_closure, B.LiveSuiteController_closure0, B.LiveSuiteController_reportLiveTest_closure, B.LiveSuiteController_close_closure, R.ExpandedReporter__onTestStarted_closure, R.ExpandedReporter__onTestStarted_closure0, R.ExpandedReporter__onTestStarted_closure1, Y.RunnerSuiteController__close_closure, E.JSStackTraceMapper__deserializePackageConfigMap_closure, R._declarer_closure, R._declarer__closure, G.main_closure0, G.main__closure, R.main_closure]); + _inherit(P.ListBase, P._ListBase_Object_ListMixin); + _inherit(H.UnmodifiableListBase, P.ListBase); + _inheritMany(H.UnmodifiableListBase, [H.CodeUnits, P.UnmodifiableListView]); + _inheritMany(H.EfficientLengthIterable, [H.ListIterable, H.LinkedHashMapKeyIterable, P._HashMapKeyIterable, P.Set]); + _inheritMany(H.ListIterable, [H.SubListIterable, H.MappedListIterable, H.ReversedListIterable, P.ListQueue, P._JsonMapKeyIterable]); + _inherit(H.EfficientLengthMappedIterable, H.MappedIterable); + _inheritMany(P.Iterator, [H.MappedIterator, H.WhereIterator, H.SkipWhileIterator]); + _inherit(H.ConstantStringMap, H.ConstantMap); + _inherit(H.Instantiation1, H.Instantiation); + _inheritMany(P.Error, [H.NullError, H.JsNoSuchMethodError, H.UnknownJsTypeError, H.TypeErrorImplementation, H.RuntimeError, P.AssertionError, H._Error, P.NullThrownError, P.ArgumentError, P.UnsupportedError, P.UnimplementedError, P.StateError, P.ConcurrentModificationError, P.CyclicInitializationError]); + _inheritMany(H.TearOffClosure, [H.StaticClosure, H.BoundClosure]); + _inherit(H._AssertionError, P.AssertionError); + _inheritMany(P.IterableBase, [H._AllMatchesIterable, O.EmptyUnmodifiableSet]); + _inheritMany(H.NativeTypedData, [H.NativeByteData, H.NativeTypedArray]); + _inheritMany(H.NativeTypedArray, [H._NativeTypedArrayOfDouble_NativeTypedArray_ListMixin, H._NativeTypedArrayOfInt_NativeTypedArray_ListMixin]); + _inherit(H._NativeTypedArrayOfDouble_NativeTypedArray_ListMixin_FixedLengthListMixin, H._NativeTypedArrayOfDouble_NativeTypedArray_ListMixin); + _inherit(H.NativeTypedArrayOfDouble, H._NativeTypedArrayOfDouble_NativeTypedArray_ListMixin_FixedLengthListMixin); + _inherit(H._NativeTypedArrayOfInt_NativeTypedArray_ListMixin_FixedLengthListMixin, H._NativeTypedArrayOfInt_NativeTypedArray_ListMixin); + _inherit(H.NativeTypedArrayOfInt, H._NativeTypedArrayOfInt_NativeTypedArray_ListMixin_FixedLengthListMixin); + _inheritMany(H.NativeTypedArrayOfDouble, [H.NativeFloat32List, H.NativeFloat64List]); + _inheritMany(H.NativeTypedArrayOfInt, [H.NativeInt16List, H.NativeInt32List, H.NativeInt8List, H.NativeUint16List, H.NativeUint32List, H.NativeUint8ClampedList, H.NativeUint8List]); + _inheritMany(H._Error, [H._CastError, H._TypeError]); + _inheritMany(P.Stream, [P._StreamImpl, P._EmptyStream, W._EventStream, Y._CompleterStream, T.SubscriptionStream]); + _inheritMany(P._StreamImpl, [P._ControllerStream, P._GeneratedStreamImpl]); + _inherit(P._BroadcastStream, P._ControllerStream); + _inherit(P._ControllerSubscription, P._BufferingStreamSubscription); + _inherit(P._BroadcastSubscription, P._ControllerSubscription); + _inheritMany(P._BroadcastStreamController, [P._SyncBroadcastStreamController, P._AsyncBroadcastStreamController]); + _inheritMany(P._Completer, [P._AsyncCompleter, P._SyncCompleter]); + _inheritMany(P._StreamController, [P._AsyncStreamController, P._SyncStreamController]); + _inherit(P._StreamControllerAddStreamState, P._AddStreamState); + _inheritMany(P._PendingEvents, [P._IterablePendingEvents, P._StreamImplEvents]); + _inheritMany(P._DelayedEvent, [P._DelayedData, P._DelayedError]); + _inheritMany(P._Zone, [P._CustomZone, P._RootZone]); + _inherit(P._IdentityHashMap, P._HashMap); + _inherit(P._LinkedHashSet, P._SetBase); + _inherit(P._UnmodifiableMapView_MapView__UnmodifiableMapMixin, P.MapView); + _inherit(P.UnmodifiableMapView, P._UnmodifiableMapView_MapView__UnmodifiableMapMixin); + _inherit(P.SetBase, P._SetBase_Object_SetMixin); + _inheritMany(P.Codec, [P.Encoding, P.Base64Codec, P._FusedCodec, P.JsonCodec]); + _inheritMany(P.Encoding, [P.AsciiCodec, P.Utf8Codec]); + _inherit(P.Converter, P.StreamTransformerBase); + _inheritMany(P.Converter, [P._UnicodeSubsetEncoder, P.Base64Encoder, P.JsonDecoder, P.Utf8Encoder, P.Utf8Decoder]); + _inherit(P.AsciiEncoder, P._UnicodeSubsetEncoder); + _inheritMany(P.num, [P.double, P.int]); + _inheritMany(P.ArgumentError, [P.RangeError, P.IndexError]); + _inherit(P._DataUri, P._Uri); + _inheritMany(W.Event, [W.ApplicationCacheErrorEvent, W.ErrorEvent, W.MediaKeyMessageEvent, W.MessageEvent, W.PresentationConnectionCloseEvent, W.SpeechRecognitionError]); + _inherit(W.File, W.Blob); + _inherit(W.MessagePort, W.EventTarget); + _inherit(W._EventStreamSubscription, P.StreamSubscription); + _inherit(P._StructuredCloneDart2Js, P._StructuredClone); + _inherit(P._AcceptStructuredCloneDart2Js, P._AcceptStructuredClone); + _inherit(T._CancelOnErrorSubscriptionWrapper, Y.DelegatingStreamSubscription); + _inherit(S.Validator, B.RecursiveVisitor); + _inherit(Q.QueueList, Q._QueueList_Object_ListMixin); + _inherit(M._UnionSet_SetBase_UnmodifiableSetMixin, P.SetBase); + _inherit(M.UnionSet, M._UnionSet_SetBase_UnmodifiableSetMixin); + _inherit(M.DelegatingIterable, M._DelegatingIterableBase); + _inherit(M.DelegatingSet, M.DelegatingIterable); + _inherit(L._UnmodifiableSetView_DelegatingSet_UnmodifiableSetMixin, M.DelegatingSet); + _inherit(L.UnmodifiableSetView, L._UnmodifiableSetView_DelegatingSet_UnmodifiableSetMixin); + _inheritMany(G.Matcher, [Y._IsTrue, M.TypeMatcher, D._DeepMatcher]); + _inherit(E.FeatureMatcher, M.TypeMatcher); + _inheritMany(E.FeatureMatcher, [Y._Predicate, D._StringEqualsMatcher]); + _inherit(B.InternalStyle, O.Style); + _inheritMany(B.InternalStyle, [E.PosixStyle, F.UrlStyle, L.WindowsStyle]); + _inheritMany(T.Mapping, [T.MultiSectionMapping, T.MappingBundle, T.SingleMapping]); + _inheritMany(Y.SourceSpanMixin, [V.SourceSpanBase, Y._FileSpan]); + _inheritMany(V.SourceSpanBase, [G.SourceMapSpan, X.SourceSpanWithContext]); + _inherit(Y.FileLocation, D.SourceLocationMixin); + _inherit(G.SourceSpanFormatException, G.SourceSpanException); + _inheritMany(R.StreamChannelMixin, [K.GuaranteeChannel, D._MultiChannel, D.VirtualChannel, R._StreamChannel]); + _inherit(E.StringScannerException, G.SourceSpanFormatException); + _inherit(S.SpanScanner, X.StringScanner); + _inherit(U.LocalTest, V.Test); + _inherit(V._LiveTest, Z.LiveTest); + _inherit(O._IterableSet_SetMixin_UnmodifiableSetMixin, P.SetMixin); + _inherit(O.IterableSet, O._IterableSet_SetMixin_UnmodifiableSetMixin); + _inherit(B._LiveSuite, E.LiveSuite); + _inherit(Y.RunnerSuite, U.Suite); + _inherit(E.JSStackTraceMapper, E.StackTraceMapper); + _mixin(H.UnmodifiableListBase, H.UnmodifiableListMixin); + _mixin(H._NativeTypedArrayOfDouble_NativeTypedArray_ListMixin, P.ListMixin); + _mixin(H._NativeTypedArrayOfDouble_NativeTypedArray_ListMixin_FixedLengthListMixin, H.FixedLengthListMixin); + _mixin(H._NativeTypedArrayOfInt_NativeTypedArray_ListMixin, P.ListMixin); + _mixin(H._NativeTypedArrayOfInt_NativeTypedArray_ListMixin_FixedLengthListMixin, H.FixedLengthListMixin); + _mixin(P._AsyncStreamController, P._AsyncStreamControllerDispatch); + _mixin(P._SyncStreamController, P._SyncStreamControllerDispatch); + _mixin(P._ListBase_Object_ListMixin, P.ListMixin); + _mixin(P._SetBase_Object_SetMixin, P.SetMixin); + _mixin(P._UnmodifiableMapView_MapView__UnmodifiableMapMixin, P._UnmodifiableMapMixin); + _mixin(Q._QueueList_Object_ListMixin, P.ListMixin); + _mixin(M._UnionSet_SetBase_UnmodifiableSetMixin, L.UnmodifiableSetMixin); + _mixin(L._UnmodifiableSetView_DelegatingSet_UnmodifiableSetMixin, L.UnmodifiableSetMixin); + _mixin(O._IterableSet_SetMixin_UnmodifiableSetMixin, L.UnmodifiableSetMixin); + })(); + var init = {typeUniverse: {eC: new Map(), tR: {}, eT: {}, tPV: {}, sEA: []}, mangledGlobalNames: {int: "int", double: "double", num: "num", String: "String", bool: "bool", Null: "Null", List: "List"}, mangledNames: {}, getTypeFromName: getGlobalFromName, metadata: [], types: ["Null()", "~()", "Future<Null>()", "Null(@)", "bool(String)", "Null(@,StackTrace)", "Null(@,@)", "String(String)", "Trace()", "bool(@)", "Frame(String)", "~(Object)", "~(Object[StackTrace])", "Future<~>()", "Future<@>()", "~(@)", "Chain()", "Frame()", "@(@)", "Null(PlatformSelector,Metadata)", "~(~())", "bool(Frame)", "GroupEntry(GroupEntry)", "Null(State)", "String(Match)", "String(int)", "bool(Object)", "Null(Message)", "Null(Zone,ZoneDelegate,Zone,Object,StackTrace)", "Null(MessageEvent)", "Null(String)", "Future<bool>()", "AsyncError(Zone,ZoneDelegate,Zone,Object,StackTrace)", "0^(1^)(Zone,ZoneDelegate,Zone,0^(1^))<Object,Object>", "@()", "0^()(Zone,ZoneDelegate,Zone,0^())<Object>", "int()", "~(Zone,ZoneDelegate,Zone,String)", "String(Frame)", "int(Frame)", "String(@)", "~(Uint8List,String,int)", "Trace(String)", "Null(bool)", "Metadata(Metadata,Metadata)", "Trace(Trace)", "Frame(Frame)", "~([Object])", "Null(List<@>)", "bool()", "Future<List<@>>()", "Uri(@,@)", "bool(Trace)", "List<Frame>(Trace)", "int(Trace)", "String(@,int,Set<@>,bool)", "String(Trace)", "bool(Pattern[int])", "List<String>(Object,Object,String,int)", "Frame(@,@)", "@(@,@)", "@(Event)", "Uint8List(@,@)", "0^(1^,2^)(Zone,ZoneDelegate,Zone,Function)<Object,Object,Object>", "Uint8List(int)", "int(int,int)", "~(@[StackTrace])", "~(String[@])", "~(String,int)", "bool(MessageEvent)", "~(Object,StackTrace)", "String(String{color:@})", "bool(GroupEntry)", "Future<@>(@)", "String()", "_Future<@>(@)", "0^(0^,0^)<num>", "Metadata()", "Metadata(Metadata,BooleanSelector)", "MapEntry<BooleanSelector,Metadata>(@,@)", "Null(@[StackTrace])", "bool/()", "MapEntry<String,Map<String,@>>(BooleanSelector,Metadata)", "bool(OperatingSystem)", "BooleanSelector()", "bool(Runtime)", "String(@,Matcher,String,Map<@,@>,bool)", "Null(Zone,ZoneDelegate,Zone,String)", "Map<@,@>(GroupEntry)", "Null(int,@)", "Null(AsyncError)", "Null(~())", "~(~)", "Map<String,int>()", "@(String)", "bool(LiveTest)", "~(Message)", "Null(RunnerSuite)", "~(LiveTest)", "~(bool)", "~(State)", "~(AsyncError)", "MapEntry<String,Uri>(String,String)", "@()()", "@(@,String)", "~(Zone,ZoneDelegate,Zone,@,StackTrace)", "0^(Zone,ZoneDelegate,Zone,0^())<Object>", "0^(Zone,ZoneDelegate,Zone,0^(1^),1^)<Object,Object>", "0^(Zone,ZoneDelegate,Zone,0^(1^,2^),1^,2^)<Object,Object,Object>", "0^(1^,2^)(Zone,ZoneDelegate,Zone,0^(1^,2^))<Object,Object,Object>", "~(Zone,ZoneDelegate,Zone,~())", "Timer(Zone,ZoneDelegate,Zone,Duration,~())", "Timer(Zone,ZoneDelegate,Zone,Duration,~(Timer))", "~(String)", "Zone(Zone,ZoneDelegate,Zone,ZoneSpecification,Map<@,@>)", "OperatingSystem()"], interceptorsByTag: null, leafTags: null}; + H._Universe_addRules(init.typeUniverse, JSON.parse('{"JavaScriptFunction":"JavaScriptObject","PlainJavaScriptObject":"JavaScriptObject","UnknownJavaScriptObject":"JavaScriptObject","AbortPaymentEvent":"Event","ExtendableEvent":"Event","Window":"EventTarget","JSBool":{"bool":[]},"JSNull":{"Null":[]},"JavaScriptObject":{"JSObject":[],"Function":[]},"JSArray":{"List":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"JSUnmodifiableArray":{"JSArray":["1"],"List":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"ArrayIterator":{"Iterator":["1"]},"JSNumber":{"double":[],"num":[]},"JSInt":{"int":[],"double":[],"num":[]},"JSDouble":{"double":[],"num":[]},"JSString":{"String":[],"Pattern":[]},"_CastIterableBase":{"Iterable":["2"]},"CastIterator":{"Iterator":["2"]},"CastIterable":{"_CastIterableBase":["1","2"],"Iterable":["2"],"Iterable.E":"2"},"_EfficientLengthCastIterable":{"CastIterable":["1","2"],"EfficientLengthIterable":["2"],"_CastIterableBase":["1","2"],"Iterable":["2"],"Iterable.E":"2"},"CastMap":{"MapMixin":["3","4"],"Map":["3","4"],"MapMixin.K":"3","MapMixin.V":"4"},"CodeUnits":{"UnmodifiableListMixin":["int"],"ListMixin":["int"],"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"],"ListMixin.E":"int","UnmodifiableListMixin.E":"int"},"EfficientLengthIterable":{"Iterable":["1"]},"ListIterable":{"EfficientLengthIterable":["1"],"Iterable":["1"]},"SubListIterable":{"ListIterable":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1","ListIterable.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"],"Iterable.E":"2","ListIterable.E":"2"},"WhereIterable":{"Iterable":["1"],"Iterable.E":"1"},"WhereIterator":{"Iterator":["1"]},"ExpandIterable":{"Iterable":["2"],"Iterable.E":"2"},"ExpandIterator":{"Iterator":["2"]},"SkipWhileIterable":{"Iterable":["1"],"Iterable.E":"1"},"SkipWhileIterator":{"Iterator":["1"]},"EmptyIterator":{"Iterator":["1"]},"UnmodifiableListBase":{"UnmodifiableListMixin":["1"],"ListMixin":["1"],"List":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"ReversedListIterable":{"ListIterable":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1","ListIterable.E":"1"},"ConstantMap":{"Map":["1","2"]},"ConstantStringMap":{"ConstantMap":["1","2"],"Map":["1","2"]},"_ConstantMapKeyIterable":{"Iterable":["1"],"Iterable.E":"1"},"Instantiation":{"Closure":[],"Function":[]},"Instantiation1":{"Closure":[],"Function":[]},"NullError":{"NoSuchMethodError":[],"Error":[]},"JsNoSuchMethodError":{"NoSuchMethodError":[],"Error":[]},"UnknownJsTypeError":{"Error":[]},"_StackTrace":{"StackTrace":[]},"Closure":{"Function":[]},"TearOffClosure":{"Closure":[],"Function":[]},"StaticClosure":{"Closure":[],"Function":[]},"BoundClosure":{"Closure":[],"Function":[]},"TypeErrorImplementation":{"Error":[]},"RuntimeError":{"Error":[]},"_AssertionError":{"Error":[]},"JsLinkedHashMap":{"LinkedHashMap":["1","2"],"MapMixin":["1","2"],"Map":["1","2"],"MapMixin.K":"1","MapMixin.V":"2"},"LinkedHashMapKeyIterable":{"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1"},"LinkedHashMapKeyIterator":{"Iterator":["1"]},"JSSyntaxRegExp":{"RegExp":[],"Pattern":[]},"_MatchImplementation":{"RegExpMatch":[],"Match":[]},"_AllMatchesIterable":{"Iterable":["RegExpMatch"],"Iterable.E":"RegExpMatch"},"_AllMatchesIterator":{"Iterator":["RegExpMatch"]},"StringMatch":{"Match":[]},"_StringAllMatchesIterable":{"Iterable":["Match"],"Iterable.E":"Match"},"_StringAllMatchesIterator":{"Iterator":["Match"]},"NativeByteBuffer":{"ByteBuffer":[]},"NativeByteData":{"NativeTypedData":[]},"NativeTypedArray":{"JavaScriptIndexingBehavior":["@"],"NativeTypedData":[]},"NativeTypedArrayOfDouble":{"ListMixin":["double"],"JavaScriptIndexingBehavior":["@"],"List":["double"],"NativeTypedData":[],"EfficientLengthIterable":["double"],"FixedLengthListMixin":["double"],"Iterable":["double"]},"NativeTypedArrayOfInt":{"ListMixin":["int"],"List":["int"],"JavaScriptIndexingBehavior":["@"],"NativeTypedData":[],"EfficientLengthIterable":["int"],"FixedLengthListMixin":["int"],"Iterable":["int"]},"NativeFloat32List":{"ListMixin":["double"],"JavaScriptIndexingBehavior":["@"],"List":["double"],"NativeTypedData":[],"EfficientLengthIterable":["double"],"FixedLengthListMixin":["double"],"Iterable":["double"],"ListMixin.E":"double"},"NativeFloat64List":{"ListMixin":["double"],"JavaScriptIndexingBehavior":["@"],"List":["double"],"NativeTypedData":[],"EfficientLengthIterable":["double"],"FixedLengthListMixin":["double"],"Iterable":["double"],"ListMixin.E":"double"},"NativeInt16List":{"ListMixin":["int"],"List":["int"],"JavaScriptIndexingBehavior":["@"],"NativeTypedData":[],"EfficientLengthIterable":["int"],"FixedLengthListMixin":["int"],"Iterable":["int"],"ListMixin.E":"int"},"NativeInt32List":{"ListMixin":["int"],"List":["int"],"JavaScriptIndexingBehavior":["@"],"NativeTypedData":[],"EfficientLengthIterable":["int"],"FixedLengthListMixin":["int"],"Iterable":["int"],"ListMixin.E":"int"},"NativeInt8List":{"ListMixin":["int"],"List":["int"],"JavaScriptIndexingBehavior":["@"],"NativeTypedData":[],"EfficientLengthIterable":["int"],"FixedLengthListMixin":["int"],"Iterable":["int"],"ListMixin.E":"int"},"NativeUint16List":{"ListMixin":["int"],"List":["int"],"JavaScriptIndexingBehavior":["@"],"NativeTypedData":[],"EfficientLengthIterable":["int"],"FixedLengthListMixin":["int"],"Iterable":["int"],"ListMixin.E":"int"},"NativeUint32List":{"Uint32List":[],"ListMixin":["int"],"List":["int"],"JavaScriptIndexingBehavior":["@"],"NativeTypedData":[],"EfficientLengthIterable":["int"],"FixedLengthListMixin":["int"],"Iterable":["int"],"ListMixin.E":"int"},"NativeUint8ClampedList":{"ListMixin":["int"],"List":["int"],"JavaScriptIndexingBehavior":["@"],"NativeTypedData":[],"EfficientLengthIterable":["int"],"FixedLengthListMixin":["int"],"Iterable":["int"],"ListMixin.E":"int"},"NativeUint8List":{"Uint8List":[],"ListMixin":["int"],"List":["int"],"JavaScriptIndexingBehavior":["@"],"NativeTypedData":[],"EfficientLengthIterable":["int"],"FixedLengthListMixin":["int"],"Iterable":["int"],"ListMixin.E":"int"},"_Type":{"Type":[]},"_Error":{"Error":[]},"_CastError":{"Error":[]},"_TypeError":{"Error":[]},"_TimerImpl":{"Timer":[]},"_AsyncAwaitCompleter":{"Completer":["1"]},"_BroadcastStream":{"_ControllerStream":["1"],"_StreamImpl":["1"],"Stream":["1"],"Stream.T":"1"},"_BroadcastSubscription":{"_ControllerSubscription":["1"],"_BufferingStreamSubscription":["1"],"_EventDispatch":["1"],"StreamSubscription":["1"],"_BufferingStreamSubscription.T":"1"},"_BroadcastStreamController":{"StreamController":["1"],"StreamSink":["1"],"EventSink":["1"],"_EventDispatch":["1"],"_StreamControllerLifecycle":["1"],"StreamConsumer":["1"],"Sink":["1"]},"_SyncBroadcastStreamController":{"_BroadcastStreamController":["1"],"StreamController":["1"],"StreamSink":["1"],"EventSink":["1"],"_EventDispatch":["1"],"_StreamControllerLifecycle":["1"],"StreamConsumer":["1"],"Sink":["1"]},"_AsyncBroadcastStreamController":{"_BroadcastStreamController":["1"],"StreamController":["1"],"StreamSink":["1"],"EventSink":["1"],"_EventDispatch":["1"],"_StreamControllerLifecycle":["1"],"StreamConsumer":["1"],"Sink":["1"]},"TimeoutException":{"Exception":[]},"_Completer":{"Completer":["1"]},"_AsyncCompleter":{"_Completer":["1"],"Completer":["1"]},"_SyncCompleter":{"_Completer":["1"],"Completer":["1"]},"_Future":{"Future":["1"]},"StreamTransformerBase":{"StreamTransformer":["1","2"]},"_StreamController":{"StreamController":["1"],"StreamSink":["1"],"EventSink":["1"],"_EventDispatch":["1"],"_StreamControllerLifecycle":["1"],"StreamConsumer":["1"],"Sink":["1"]},"_AsyncStreamController":{"_AsyncStreamControllerDispatch":["1"],"_StreamController":["1"],"StreamController":["1"],"StreamSink":["1"],"EventSink":["1"],"_EventDispatch":["1"],"_StreamControllerLifecycle":["1"],"StreamConsumer":["1"],"Sink":["1"]},"_SyncStreamController":{"_SyncStreamControllerDispatch":["1"],"_StreamController":["1"],"StreamController":["1"],"StreamSink":["1"],"EventSink":["1"],"_EventDispatch":["1"],"_StreamControllerLifecycle":["1"],"StreamConsumer":["1"],"Sink":["1"]},"_ControllerStream":{"_StreamImpl":["1"],"Stream":["1"],"Stream.T":"1"},"_ControllerSubscription":{"_BufferingStreamSubscription":["1"],"_EventDispatch":["1"],"StreamSubscription":["1"],"_BufferingStreamSubscription.T":"1"},"_StreamSinkWrapper":{"StreamSink":["1"],"EventSink":["1"],"StreamConsumer":["1"],"Sink":["1"]},"_StreamControllerAddStreamState":{"_AddStreamState":["1"]},"_BufferingStreamSubscription":{"_EventDispatch":["1"],"StreamSubscription":["1"],"_BufferingStreamSubscription.T":"1"},"_StreamImpl":{"Stream":["1"]},"_GeneratedStreamImpl":{"_StreamImpl":["1"],"Stream":["1"],"Stream.T":"1"},"_IterablePendingEvents":{"_PendingEvents":["1"]},"_DelayedData":{"_DelayedEvent":["1"]},"_DelayedError":{"_DelayedEvent":["@"]},"_DelayedDone":{"_DelayedEvent":["@"]},"_StreamImplEvents":{"_PendingEvents":["1"]},"_DoneStreamSubscription":{"StreamSubscription":["1"]},"_EmptyStream":{"Stream":["1"],"Stream.T":"1"},"AsyncError":{"Error":[]},"_ZoneSpecification":{"ZoneSpecification":[]},"_ZoneDelegate":{"ZoneDelegate":[]},"_Zone":{"Zone":[]},"_CustomZone":{"_Zone":[],"Zone":[]},"_RootZone":{"_Zone":[],"Zone":[]},"_HashMap":{"MapMixin":["1","2"],"Map":["1","2"],"MapMixin.K":"1","MapMixin.V":"2"},"_IdentityHashMap":{"_HashMap":["1","2"],"MapMixin":["1","2"],"Map":["1","2"],"MapMixin.K":"1","MapMixin.V":"2"},"_HashMapKeyIterable":{"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1"},"_HashMapKeyIterator":{"Iterator":["1"]},"_LinkedHashSet":{"_SetBase":["1"],"LinkedHashSet":["1"],"Set":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"_LinkedHashSetIterator":{"Iterator":["1"]},"UnmodifiableListView":{"UnmodifiableListMixin":["1"],"ListMixin":["1"],"List":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"ListMixin.E":"1","UnmodifiableListMixin.E":"1"},"IterableBase":{"Iterable":["1"]},"ListBase":{"ListMixin":["1"],"List":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"MapBase":{"MapMixin":["1","2"],"Map":["1","2"]},"MapMixin":{"Map":["1","2"]},"MapView":{"Map":["1","2"]},"UnmodifiableMapView":{"_UnmodifiableMapView_MapView__UnmodifiableMapMixin":["1","2"],"MapView":["1","2"],"_UnmodifiableMapMixin":["1","2"],"Map":["1","2"]},"ListQueue":{"ListIterable":["1"],"Queue":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1","ListIterable.E":"1"},"_ListQueueIterator":{"Iterator":["1"]},"SetMixin":{"Set":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"SetBase":{"SetMixin":["1"],"Set":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"_SetBase":{"Set":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"_JsonMap":{"MapMixin":["String","@"],"Map":["String","@"],"MapMixin.K":"String","MapMixin.V":"@"},"_JsonMapKeyIterable":{"ListIterable":["String"],"EfficientLengthIterable":["String"],"Iterable":["String"],"Iterable.E":"String","ListIterable.E":"String"},"AsciiCodec":{"Codec":["String","List<int>"],"Codec.S":"String"},"_UnicodeSubsetEncoder":{"Converter":["String","List<int>"],"StreamTransformer":["String","List<int>"]},"AsciiEncoder":{"Converter":["String","List<int>"],"StreamTransformer":["String","List<int>"]},"Base64Codec":{"Codec":["List<int>","String"],"Codec.S":"List<int>"},"Base64Encoder":{"Converter":["List<int>","String"],"StreamTransformer":["List<int>","String"]},"_FusedCodec":{"Codec":["1","3"],"Codec.S":"1"},"Converter":{"StreamTransformer":["1","2"]},"Encoding":{"Codec":["String","List<int>"]},"JsonCodec":{"Codec":["Object","String"],"Codec.S":"Object"},"JsonDecoder":{"Converter":["String","Object"],"StreamTransformer":["String","Object"]},"Utf8Codec":{"Codec":["String","List<int>"],"Codec.S":"String"},"Utf8Encoder":{"Converter":["String","List<int>"],"StreamTransformer":["String","List<int>"]},"Utf8Decoder":{"Converter":["List<int>","String"],"StreamTransformer":["List<int>","String"]},"double":{"num":[]},"AssertionError":{"Error":[]},"NullThrownError":{"Error":[]},"ArgumentError":{"Error":[]},"RangeError":{"Error":[]},"IndexError":{"Error":[]},"UnsupportedError":{"Error":[]},"UnimplementedError":{"Error":[]},"StateError":{"Error":[]},"ConcurrentModificationError":{"Error":[]},"OutOfMemoryError":{"Error":[]},"StackOverflowError":{"Error":[]},"CyclicInitializationError":{"Error":[]},"_Exception":{"Exception":[]},"FormatException":{"Exception":[]},"int":{"num":[]},"List":{"EfficientLengthIterable":["1"],"Iterable":["1"]},"RegExpMatch":{"Match":[]},"Set":{"EfficientLengthIterable":["1"],"Iterable":["1"]},"_StringStackTrace":{"StackTrace":[]},"String":{"Pattern":[]},"Runes":{"Iterable":["int"],"Iterable.E":"int"},"RuneIterator":{"Iterator":["int"]},"StringBuffer":{"StringSink":[]},"_Uri":{"Uri":[]},"_SimpleUri":{"Uri":[]},"_DataUri":{"Uri":[]},"ApplicationCacheErrorEvent":{"Event":[]},"ErrorEvent":{"Event":[]},"File":{"Blob":[]},"MediaKeyMessageEvent":{"Event":[]},"MessageEvent":{"Event":[]},"MessagePort":{"EventTarget":[]},"PresentationConnectionCloseEvent":{"Event":[]},"SpeechRecognitionError":{"Event":[]},"_EventStream":{"Stream":["1"],"Stream.T":"1"},"_EventStreamSubscription":{"StreamSubscription":["1"]},"Int8List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Uint8List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Uint8ClampedList":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Int16List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Uint16List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Int32List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Uint32List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Float32List":{"List":["double"],"EfficientLengthIterable":["double"],"Iterable":["double"]},"Float64List":{"List":["double"],"EfficientLengthIterable":["double"],"Iterable":["double"]},"DelegatingSink":{"Sink":["1"]},"DelegatingStreamSubscription":{"StreamSubscription":["1"]},"FutureGroup":{"Sink":["Future<1>"]},"NullStreamSink":{"StreamSink":["1"],"EventSink":["1"],"StreamConsumer":["1"],"Sink":["1"]},"ErrorResult":{"Result":["Null"]},"ValueResult":{"Result":["1"]},"_CompleterStream":{"Stream":["1"],"Stream.T":"1"},"StreamGroup":{"Sink":["Stream<1>"]},"_NextRequest":{"_EventRequest":["1"]},"_RestRequest":{"_EventRequest":["1"]},"_CompleterSink":{"StreamSink":["1"],"EventSink":["1"],"StreamConsumer":["1"],"Sink":["1"]},"SubscriptionStream":{"Stream":["1"],"Stream.T":"1"},"_CancelOnErrorSubscriptionWrapper":{"DelegatingStreamSubscription":["1"],"StreamSubscription":["1"]},"All":{"BooleanSelector":[]},"VariableNode":{"Node":[]},"NotNode":{"Node":[]},"OrNode":{"Node":[]},"AndNode":{"Node":[]},"ConditionalNode":{"Node":[]},"Evaluator":{"Visitor":["bool"]},"BooleanSelectorImpl":{"BooleanSelector":[]},"IntersectionSelector":{"BooleanSelector":[]},"None":{"BooleanSelector":[]},"IdentifierToken":{"Token":[]},"Validator":{"Visitor":["@"]},"RecursiveVisitor":{"Visitor":["@"]},"EmptyUnmodifiableSet":{"Set":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1"},"QueueList":{"ListMixin":["1"],"Queue":["1"],"List":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"ListMixin.E":"1"},"UnionSet":{"UnmodifiableSetMixin":["1"],"SetMixin":["1"],"Set":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"UnmodifiableSetView":{"_UnmodifiableSetView_DelegatingSet_UnmodifiableSetMixin":["1"],"DelegatingSet":["1"],"UnmodifiableSetMixin":["1"],"DelegatingIterable":["1"],"Set":["1"],"_DelegatingIterableBase":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"_DelegatingIterableBase":{"Iterable":["1"]},"DelegatingIterable":{"_DelegatingIterableBase":["1"],"Iterable":["1"]},"DelegatingSet":{"DelegatingIterable":["1"],"Set":["1"],"_DelegatingIterableBase":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"_IsTrue":{"Matcher":[]},"_Predicate":{"FeatureMatcher":["1"],"TypeMatcher":["1"],"Matcher":[],"TypeMatcher.T":"1","FeatureMatcher.T":"1"},"StringDescription":{"Description":[]},"_StringEqualsMatcher":{"FeatureMatcher":["String"],"TypeMatcher":["String"],"Matcher":[],"TypeMatcher.T":"String","FeatureMatcher.T":"String"},"_DeepMatcher":{"Matcher":[]},"FeatureMatcher":{"TypeMatcher":["1"],"Matcher":[]},"TypeMatcher":{"Matcher":[],"TypeMatcher.T":"1"},"PackageConfigResolver":{"SyncPackageResolver":[]},"PackageRootResolver":{"SyncPackageResolver":[]},"PathException":{"Exception":[]},"PosixStyle":{"InternalStyle":[]},"UrlStyle":{"InternalStyle":[]},"WindowsStyle":{"InternalStyle":[]},"MultiSectionMapping":{"Mapping":[]},"MappingBundle":{"Mapping":[]},"SingleMapping":{"Mapping":[]},"_MappingTokenizer":{"Iterator":["String"]},"SourceMapSpan":{"SourceSpan":[]},"FileLocation":{"SourceLocation":[]},"_FileSpan":{"FileSpan":[],"SourceSpanWithContext":[],"SourceSpan":[]},"SourceLocationMixin":{"SourceLocation":[]},"SourceSpanBase":{"SourceSpan":[]},"SourceSpanException":{"Exception":[]},"SourceSpanFormatException":{"FormatException":[],"Exception":[]},"SourceSpanMixin":{"SourceSpan":[]},"SourceSpanWithContext":{"SourceSpan":[]},"Chain":{"StackTrace":[]},"LazyChain":{"Chain":[],"StackTrace":[]},"LazyTrace":{"Trace":[],"StackTrace":[]},"Trace":{"StackTrace":[]},"UnparsedFrame":{"Frame":[]},"GuaranteeChannel":{"StreamChannelMixin":["1"],"StreamChannel":["1"]},"_GuaranteeSink":{"StreamSink":["1"],"EventSink":["1"],"StreamConsumer":["1"],"Sink":["1"]},"_MultiChannel":{"StreamChannelMixin":["1"],"MultiChannel":["1"],"StreamChannel":["1"]},"VirtualChannel":{"StreamChannelMixin":["1"],"MultiChannel":["1"],"StreamChannel":["1"]},"_StreamChannel":{"StreamChannelMixin":["1"],"StreamChannel":["1"]},"StreamChannelMixin":{"StreamChannel":["1"]},"StringScannerException":{"FormatException":[],"Exception":[]},"_SpanScannerState":{"LineScannerState":[]},"ClosedException":{"Exception":[]},"Group":{"GroupEntry":[]},"LocalTest":{"Test":[],"GroupEntry":[]},"_LiveTest":{"LiveTest":[]},"Test":{"GroupEntry":[]},"IterableSet":{"SetMixin":["1"],"UnmodifiableSetMixin":["1"],"Set":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"_LiveSuite":{"LiveSuite":[]},"RunnerSuite":{"Suite":[]},"PrintSink":{"StringSink":[]},"JSStackTraceMapper":{"StackTraceMapper":[]}}')); + H._Universe_addErasedTypes(init.typeUniverse, JSON.parse('{"UnmodifiableListBase":1,"StreamTransformerBase":2,"IterableBase":1,"ListBase":1,"MapBase":2,"SetBase":1,"_ListBase_Object_ListMixin":1,"_SetBase_Object_SetMixin":1,"_QueueList_Object_ListMixin":1,"_UnionSet_SetBase_UnmodifiableSetMixin":1,"_IterableSet_SetMixin_UnmodifiableSetMixin":1}')); + var type$ = (function rtii() { + var findType = H.findType; + return { + A_Function_2_B_and_C_Function_A_and_B_and_C_4_Zone_and_ZoneDelegate_and_Zone_and_A_Function_2_B_and_C: findType("0^(1^,2^)(Zone,ZoneDelegate,Zone,0^(1^,2^))<Object,Object,Object>"), + A_Function_A_4_Zone_and_ZoneDelegate_and_Zone_and_A_Function: findType("0^(Zone,ZoneDelegate,Zone,0^())<Object>"), + A_Function_A_and_B_5_Zone_and_ZoneDelegate_and_Zone_and_A_Function_B_and_B: findType("0^(Zone,ZoneDelegate,Zone,0^(1^),1^)<Object,Object>"), + A_Function_A_and_B_and_C_6_Zone_and_ZoneDelegate_and_Zone_and_A_Function_2_B_and_C_and_B_and_C: findType("0^(Zone,ZoneDelegate,Zone,0^(1^,2^),1^,2^)<Object,Object,Object>"), + A_Function_B_Function_A_and_B_4_Zone_and_ZoneDelegate_and_Zone_and_A_Function_B: findType("0^(1^)(Zone,ZoneDelegate,Zone,0^(1^))<Object,Object>"), + A_Function_Function_A_4_Zone_and_ZoneDelegate_and_Zone_and_A_Function: findType("0^()(Zone,ZoneDelegate,Zone,0^())<Object>"), + AsyncError: findType("AsyncError"), + AsyncMemoizer_dynamic: findType("AsyncMemoizer<@>"), + Blob: findType("Blob"), + BooleanSelector: findType("BooleanSelector"), + Chain: findType("Chain"), + CodeUnits: findType("CodeUnits"), + Completer_PoolResource: findType("Completer<PoolResource>"), + Declarer: findType("Declarer"), + Duration: findType("Duration"), + EfficientLengthIterable_dynamic: findType("EfficientLengthIterable<@>"), + Error: findType("Error"), + Event: findType("Event"), + Exception: findType("Exception"), + Expando__Node: findType("Expando<_Node>"), + File: findType("File"), + FileSpan: findType("FileSpan"), + FormatException: findType("FormatException"), + Frame: findType("Frame"), + Frame_Function_Frame: findType("Frame(Frame)"), + Frame_Function_String: findType("Frame(String)"), + Function: findType("Function"), + FutureGroup_dynamic: findType("FutureGroup<@>"), + FutureOr_void_Function: findType("~/()"), + Future_Null: findType("Future<Null>"), + Future_RunnerSuite: findType("Future<RunnerSuite>"), + Future_bool: findType("Future<bool>"), + Future_dynamic: findType("Future<@>"), + Future_void: findType("Future<~>"), + Group: findType("Group"), + GroupEntry: findType("GroupEntry"), + GroupEntry_Function_GroupEntry: findType("GroupEntry(GroupEntry)"), + IdentifierToken: findType("IdentifierToken"), + Invoker: findType("Invoker"), + IterableSet_LiveTest: findType("IterableSet<LiveTest>"), + Iterable_Group: findType("Iterable<Group>"), + Iterable_String: findType("Iterable<String>"), + Iterable_dynamic: findType("Iterable<@>"), + Iterator_Match: findType("Iterator<Match>"), + JSArray_AsyncError: findType("JSArray<AsyncError>"), + JSArray_Declarer: findType("JSArray<Declarer>"), + JSArray_Frame: findType("JSArray<Frame>"), + JSArray_Future_dynamic: findType("JSArray<Future<@>>"), + JSArray_Group: findType("JSArray<Group>"), + JSArray_GroupEntry: findType("JSArray<GroupEntry>"), + JSArray_Mapping: findType("JSArray<Mapping>"), + JSArray_Set_LiveTest: findType("JSArray<Set<LiveTest>>"), + JSArray_SourceFile: findType("JSArray<SourceFile>"), + JSArray_String: findType("JSArray<String>"), + JSArray_TargetEntry: findType("JSArray<TargetEntry>"), + JSArray_TargetLineEntry: findType("JSArray<TargetLineEntry>"), + JSArray_Trace: findType("JSArray<Trace>"), + JSArray_Zone: findType("JSArray<Zone>"), + JSArray_dynamic: findType("JSArray<@>"), + JSArray_int: findType("JSArray<int>"), + JSArray_of_dynamic_Function: findType("JSArray<@()>"), + JSObject: findType("JSObject"), + JavaScriptFunction: findType("JavaScriptFunction"), + JavaScriptIndexingBehavior_dynamic: findType("JavaScriptIndexingBehavior<@>"), + JsLinkedHashMap_of_Stream_LiveTest_and_StreamSubscription_LiveTest: findType("JsLinkedHashMap<Stream<LiveTest>,StreamSubscription<LiveTest>>"), + List_Group: findType("List<Group>"), + List_Object: findType("List<Object>"), + List_String: findType("List<String>"), + List_String_Function_dynamic_dynamic_String_int: findType("List<String>(@,@,String,int)"), + List_dynamic: findType("List<@>"), + List_int: findType("List<int>"), + LiveSuite: findType("LiveSuite"), + LiveTest: findType("LiveTest"), + MapEntry_BooleanSelector_Metadata: findType("MapEntry<BooleanSelector,Metadata>"), + MapEntry_String_Uri: findType("MapEntry<String,Uri>"), + MapEntry_of_String_and_Map_String_dynamic: findType("MapEntry<String,Map<String,@>>"), + Map_BooleanSelector_Metadata: findType("Map<BooleanSelector,Metadata>"), + Map_PlatformSelector_Metadata: findType("Map<PlatformSelector,Metadata>"), + Map_String_SourceFile: findType("Map<String,SourceFile>"), + Map_String_dynamic: findType("Map<String,@>"), + Map_dynamic_dynamic: findType("Map<@,@>"), + MappedIterable_String_Frame: findType("MappedIterable<String,Frame>"), + MappedListIterable_Frame_Frame: findType("MappedListIterable<Frame,Frame>"), + MappedListIterable_String_String: findType("MappedListIterable<String,String>"), + MappedListIterable_String_Trace: findType("MappedListIterable<String,Trace>"), + MappedListIterable_String_dynamic: findType("MappedListIterable<String,@>"), + Message: findType("Message"), + MessageEvent: findType("MessageEvent"), + MessagePort: findType("MessagePort"), + Metadata: findType("Metadata"), + NativeByteBuffer: findType("NativeByteBuffer"), + NativeTypedData: findType("NativeTypedData"), + NativeUint8List: findType("NativeUint8List"), + NoSuchMethodError: findType("NoSuchMethodError"), + Null: findType("Null"), + Null_Function: findType("Null()"), + Object: findType("Object"), + OperatingSystem: findType("OperatingSystem"), + Pattern: findType("Pattern"), + PlatformSelector: findType("PlatformSelector"), + RegExp: findType("RegExp"), + Result_dynamic: findType("Result<@>"), + ReversedListIterable_Declarer: findType("ReversedListIterable<Declarer>"), + RunnerSuite: findType("RunnerSuite"), + Runtime: findType("Runtime"), + Set_LiveTest: findType("Set<LiveTest>"), + Set_String: findType("Set<String>"), + Set_dynamic: findType("Set<@>"), + SingleMapping: findType("SingleMapping"), + SourceLocation: findType("SourceLocation"), + SourceSpan: findType("SourceSpan"), + SourceSpanWithContext: findType("SourceSpanWithContext"), + StackTrace: findType("StackTrace"), + StackTraceFormatter: findType("StackTraceFormatter"), + StackZoneSpecification: findType("StackZoneSpecification"), + State: findType("State"), + StreamChannelCompleter_dynamic: findType("StreamChannelCompleter<@>"), + StreamChannel_dynamic: findType("StreamChannel<@>"), + StreamCompleter_dynamic: findType("StreamCompleter<@>"), + StreamGroup_LiveTest: findType("StreamGroup<LiveTest>"), + StreamQueue_dynamic: findType("StreamQueue<@>"), + StreamSinkCompleter_dynamic: findType("StreamSinkCompleter<@>"), + StreamSubscription_dynamic: findType("StreamSubscription<@>"), + String: findType("String"), + String_Function_Match: findType("String(Match)"), + String_Function_String: findType("String(String)"), + SuiteChannelManager: findType("SuiteChannelManager"), + Test: findType("Test"), + Timer: findType("Timer"), + Trace: findType("Trace"), + Trace_Function_String: findType("Trace(String)"), + Type: findType("Type"), + Uint8List: findType("Uint8List"), + UnionSet_LiveTest: findType("UnionSet<LiveTest>"), + UnknownJavaScriptObject: findType("UnknownJavaScriptObject"), + UnmodifiableListView_LiveTest: findType("UnmodifiableListView<LiveTest>"), + UnmodifiableMapView_BooleanSelector_Metadata: findType("UnmodifiableMapView<BooleanSelector,Metadata>"), + UnmodifiableMapView_PlatformSelector_Metadata: findType("UnmodifiableMapView<PlatformSelector,Metadata>"), + UnmodifiableMapView_String_Uri: findType("UnmodifiableMapView<String,Uri>"), + UnmodifiableSetView_LiveTest: findType("UnmodifiableSetView<LiveTest>"), + UnmodifiableSetView_String: findType("UnmodifiableSetView<String>"), + Uri: findType("Uri"), + WhereIterable_String: findType("WhereIterable<String>"), + Zone: findType("Zone"), + ZoneDelegate: findType("ZoneDelegate"), + ZoneSpecification: findType("ZoneSpecification"), + _AsyncBroadcastStreamController_LiveSuite: findType("_AsyncBroadcastStreamController<LiveSuite>"), + _AsyncBroadcastStreamController_RunnerSuite: findType("_AsyncBroadcastStreamController<RunnerSuite>"), + _AsyncBroadcastStreamController_bool: findType("_AsyncBroadcastStreamController<bool>"), + _AsyncCompleter_List_dynamic: findType("_AsyncCompleter<List<@>>"), + _AsyncCompleter_PoolResource: findType("_AsyncCompleter<PoolResource>"), + _AsyncCompleter_dynamic: findType("_AsyncCompleter<@>"), + _AsyncCompleter_void: findType("_AsyncCompleter<~>"), + _AsyncCounter: findType("_AsyncCounter"), + _CompleterSink_dynamic: findType("_CompleterSink<@>"), + _CompleterStream_dynamic: findType("_CompleterStream<@>"), + _DelayedEvent_dynamic: findType("_DelayedEvent<@>"), + _EventRequest_dynamic: findType("_EventRequest<@>"), + _EventStream_MessageEvent: findType("_EventStream<MessageEvent>"), + _FutureListener_dynamic_dynamic: findType("_FutureListener<@,@>"), + _Future_List_dynamic: findType("_Future<List<@>>"), + _Future_PoolResource: findType("_Future<PoolResource>"), + _Future_RunnerSuite: findType("_Future<RunnerSuite>"), + _Future_dynamic: findType("_Future<@>"), + _Future_int: findType("_Future<int>"), + _Future_void: findType("_Future<~>"), + _IdentityHashMap_dynamic_dynamic: findType("_IdentityHashMap<@,@>"), + _LinkedHashSetCell: findType("_LinkedHashSetCell"), + _Node: findType("_Node"), + _Predicate_Object: findType("_Predicate<Object>"), + _Predicate_dynamic: findType("_Predicate<@>"), + _RestRequest_dynamic: findType("_RestRequest<@>"), + _StreamChannel_dynamic: findType("_StreamChannel<@>"), + _SyncBroadcastStreamController_AsyncError: findType("_SyncBroadcastStreamController<AsyncError>"), + _SyncBroadcastStreamController_LiveTest: findType("_SyncBroadcastStreamController<LiveTest>"), + _SyncBroadcastStreamController_Message: findType("_SyncBroadcastStreamController<Message>"), + _SyncBroadcastStreamController_State: findType("_SyncBroadcastStreamController<State>"), + _SyncCompleter_PoolResource: findType("_SyncCompleter<PoolResource>"), + _SyncCompleter_dynamic: findType("_SyncCompleter<@>"), + _ZoneFunction_Function: findType("_ZoneFunction<Function>"), + _ZoneFunction_of_AsyncError_Function_Zone_ZoneDelegate_Zone_Object_StackTrace: findType("_ZoneFunction<AsyncError(Zone,ZoneDelegate,Zone,Object,StackTrace)>"), + _ZoneFunction_of_Timer_Function_5_Zone_and_ZoneDelegate_and_Zone_and_Duration_and_void_Function: findType("_ZoneFunction<Timer(Zone,ZoneDelegate,Zone,Duration,~())>"), + _ZoneFunction_of_Timer_Function_5_Zone_and_ZoneDelegate_and_Zone_and_Duration_and_void_Function_Timer: findType("_ZoneFunction<Timer(Zone,ZoneDelegate,Zone,Duration,~(Timer))>"), + _ZoneFunction_of_Zone_Function_5_Zone_and_ZoneDelegate_and_Zone_and_ZoneSpecification_and_Map_dynamic_dynamic: findType("_ZoneFunction<Zone(Zone,ZoneDelegate,Zone,ZoneSpecification,Map<@,@>)>"), + _ZoneFunction_of_void_Function_4_Zone_and_ZoneDelegate_and_Zone_and_void_Function: findType("_ZoneFunction<~(Zone,ZoneDelegate,Zone,~())>"), + _ZoneFunction_of_void_Function_Zone_ZoneDelegate_Zone_Object_StackTrace: findType("_ZoneFunction<~(Zone,ZoneDelegate,Zone,Object,StackTrace)>"), + _ZoneFunction_of_void_Function_Zone_ZoneDelegate_Zone_String: findType("_ZoneFunction<~(Zone,ZoneDelegate,Zone,String)>"), + bool: findType("bool"), + bool_Function_Frame: findType("bool(Frame)"), + bool_Function_Null: findType("bool(Null)"), + bool_Function_Object: findType("bool(Object)"), + bool_Function_String: findType("bool(String)"), + bool_Function_dynamic: findType("bool(@)"), + dynamic: findType("@"), + dynamic_Function: findType("@()"), + dynamic_Function_Event: findType("@(Event)"), + dynamic_Function_Object: findType("@(Object)"), + dynamic_Function_Object_Object: findType("@(Object,Object)"), + dynamic_Function_Object_StackTrace: findType("@(Object,StackTrace)"), + dynamic_Function_String: findType("@(String)"), + dynamic_Function_dynamic_dynamic: findType("@(@,@)"), + int: findType("int"), + num: findType("num"), + void: findType("~"), + void_Function: findType("~()"), + void_Function_MessageEvent: findType("~(MessageEvent)"), + void_Function_Object: findType("~(Object)"), + void_Function_Object_StackTrace: findType("~(Object,StackTrace)"), + void_Function_String_dynamic: findType("~(String,@)"), + void_Function_Timer: findType("~(Timer)") + }; + })(); + (function constants() { + var makeConstList = hunkHelpers.makeConstList; + C.Interceptor_methods = J.Interceptor.prototype; + C.JSArray_methods = J.JSArray.prototype; + C.JSInt_methods = J.JSInt.prototype; + C.JSNumber_methods = J.JSNumber.prototype; + C.JSString_methods = J.JSString.prototype; + C.JavaScriptFunction_methods = J.JavaScriptFunction.prototype; + C.Location_methods = W.Location.prototype; + C.MessagePort_methods = W.MessagePort.prototype; + C.NativeUint32List_methods = H.NativeUint32List.prototype; + C.NativeUint8List_methods = H.NativeUint8List.prototype; + C.PlainJavaScriptObject_methods = J.PlainJavaScriptObject.prototype; + C.UnknownJavaScriptObject_methods = J.UnknownJavaScriptObject.prototype; + C.AsciiEncoder_127 = new P.AsciiEncoder(127); + C.List_empty = H.setRuntimeTypeInfo(makeConstList([]), type$.JSArray_String); + C.C_All = new X.All(); + C.C_AsciiCodec = new P.AsciiCodec(); + C.C_AsciiGlyphSet = new A.AsciiGlyphSet(); + C.C_Base64Encoder = new P.Base64Encoder(); + C.C_Base64Codec = new P.Base64Codec(); + C.C_EmptyIterator = new H.EmptyIterator(H.findType("EmptyIterator<Null>")); + C.C_EmptyUnmodifiableSet = new O.EmptyUnmodifiableSet(H.findType("EmptyUnmodifiableSet<String>")); + C.C_JS_CONST = function getTagFallback(o) { + var s = Object.prototype.toString.call(o); + return s.substring(8, s.length - 1); +}; + C.C_JS_CONST0 = function() { + var toStringFunction = Object.prototype.toString; + function getTag(o) { + var s = toStringFunction.call(o); + return s.substring(8, s.length - 1); + } + function getUnknownTag(object, tag) { + if (/^HTML[A-Z].*Element$/.test(tag)) { + var name = toStringFunction.call(object); + if (name == "[object Object]") return null; + return "HTMLElement"; + } + } + function getUnknownTagGenericBrowser(object, tag) { + if (self.HTMLElement && object instanceof HTMLElement) return "HTMLElement"; + return getUnknownTag(object, tag); + } + function prototypeForTag(tag) { + if (typeof window == "undefined") return null; + if (typeof window[tag] == "undefined") return null; + var constructor = window[tag]; + if (typeof constructor != "function") return null; + return constructor.prototype; + } + function discriminator(tag) { return null; } + var isBrowser = typeof navigator == "object"; + return { + getTag: getTag, + getUnknownTag: isBrowser ? getUnknownTagGenericBrowser : getUnknownTag, + prototypeForTag: prototypeForTag, + discriminator: discriminator }; +}; + C.C_JS_CONST6 = function(getTagFallback) { + return function(hooks) { + if (typeof navigator != "object") return hooks; + var ua = navigator.userAgent; + if (ua.indexOf("DumpRenderTree") >= 0) return hooks; + if (ua.indexOf("Chrome") >= 0) { + function confirm(p) { + return typeof window == "object" && window[p] && window[p].name == p; + } + if (confirm("Window") && confirm("HTMLElement")) return hooks; + } + hooks.getTag = getTagFallback; + }; +}; + C.C_JS_CONST1 = function(hooks) { + if (typeof dartExperimentalFixupGetTag != "function") return hooks; + hooks.getTag = dartExperimentalFixupGetTag(hooks.getTag); +}; + C.C_JS_CONST2 = function(hooks) { + var getTag = hooks.getTag; + var prototypeForTag = hooks.prototypeForTag; + function getTagFixed(o) { + var tag = getTag(o); + if (tag == "Document") { + if (!!o.xmlVersion) return "!Document"; + return "!HTMLDocument"; + } + return tag; + } + function prototypeForTagFixed(tag) { + if (tag == "Document") return null; + return prototypeForTag(tag); + } + hooks.getTag = getTagFixed; + hooks.prototypeForTag = prototypeForTagFixed; +}; + C.C_JS_CONST5 = function(hooks) { + var userAgent = typeof navigator == "object" ? navigator.userAgent : ""; + if (userAgent.indexOf("Firefox") == -1) return hooks; + var getTag = hooks.getTag; + var quickMap = { + "BeforeUnloadEvent": "Event", + "DataTransfer": "Clipboard", + "GeoGeolocation": "Geolocation", + "Location": "!Location", + "WorkerMessageEvent": "MessageEvent", + "XMLDocument": "!Document"}; + function getTagFirefox(o) { + var tag = getTag(o); + return quickMap[tag] || tag; + } + hooks.getTag = getTagFirefox; +}; + C.C_JS_CONST4 = function(hooks) { + var userAgent = typeof navigator == "object" ? navigator.userAgent : ""; + if (userAgent.indexOf("Trident/") == -1) return hooks; + var getTag = hooks.getTag; + var quickMap = { + "BeforeUnloadEvent": "Event", + "DataTransfer": "Clipboard", + "HTMLDDElement": "HTMLElement", + "HTMLDTElement": "HTMLElement", + "HTMLPhraseElement": "HTMLElement", + "Position": "Geoposition" + }; + function getTagIE(o) { + var tag = getTag(o); + var newTag = quickMap[tag]; + if (newTag) return newTag; + if (tag == "Object") { + if (window.DataView && (o instanceof window.DataView)) return "DataView"; + } + return tag; + } + function prototypeForTagIE(tag) { + var constructor = window[tag]; + if (constructor == null) return null; + return constructor.prototype; + } + hooks.getTag = getTagIE; + hooks.prototypeForTag = prototypeForTagIE; +}; + C.C_JS_CONST3 = function(hooks) { return hooks; } +; + C.C_JsonCodec = new P.JsonCodec(); + C.C_None = new O.None(); + C.C_OutOfMemoryError = new P.OutOfMemoryError(); + C.C_UnicodeGlyphSet = new K.UnicodeGlyphSet(); + C.C_Utf8Codec = new P.Utf8Codec(); + C.C_Utf8Encoder = new P.Utf8Encoder(); + C.C__DelayedDone = new P._DelayedDone(); + C.C__IsTrue = new Y._IsTrue(); + C.C__RootZone = new P._RootZone(); + C.Duration_0 = new P.Duration(0); + C.Duration_30000000 = new P.Duration(30000000); + C.JsonDecoder_null = new P.JsonDecoder(null); + C.List_127_2047_65535_1114111 = H.setRuntimeTypeInfo(makeConstList([127, 2047, 65535, 1114111]), type$.JSArray_int); + C.List_2Vk = H.setRuntimeTypeInfo(makeConstList([0, 0, 32776, 33792, 1, 10240, 0, 0]), type$.JSArray_int); + C.List_CVk = H.setRuntimeTypeInfo(makeConstList([0, 0, 65490, 45055, 65535, 34815, 65534, 18431]), type$.JSArray_int); + C.List_JYB = H.setRuntimeTypeInfo(makeConstList([0, 0, 26624, 1023, 65534, 2047, 65534, 2047]), type$.JSArray_int); + C.List_empty1 = H.setRuntimeTypeInfo(makeConstList([]), H.findType("JSArray<Null>")); + C.List_empty0 = H.setRuntimeTypeInfo(makeConstList([]), type$.JSArray_dynamic); + C.List_gRj = H.setRuntimeTypeInfo(makeConstList([0, 0, 32722, 12287, 65534, 34815, 65534, 18431]), type$.JSArray_int); + C.Runtime_ql0 = new B.Runtime("VM", "vm", null, true, false, false, false, false); + C.Runtime_4e8 = new B.Runtime("Chrome", "chrome", null, false, true, true, true, false); + C.Runtime_IBZ = new B.Runtime("PhantomJS", "phantomjs", null, false, true, true, true, true); + C.Runtime_8Rg = new B.Runtime("Firefox", "firefox", null, false, true, true, false, false); + C.Runtime_ivT = new B.Runtime("Safari", "safari", null, false, true, true, false, false); + C.Runtime_Mzn = new B.Runtime("Internet Explorer", "ie", null, false, true, true, false, false); + C.Runtime_R5O = new B.Runtime("Node.js", "node", null, false, false, true, false, false); + C.List_m7e = H.setRuntimeTypeInfo(makeConstList([C.Runtime_ql0, C.Runtime_4e8, C.Runtime_IBZ, C.Runtime_8Rg, C.Runtime_ivT, C.Runtime_Mzn, C.Runtime_R5O]), H.findType("JSArray<Runtime>")); + C.List_nxB = H.setRuntimeTypeInfo(makeConstList([0, 0, 24576, 1023, 65534, 34815, 65534, 18431]), type$.JSArray_int); + C.OperatingSystem_Windows_windows = new N.OperatingSystem("Windows", "windows"); + C.OperatingSystem_RkP = new N.OperatingSystem("OS X", "mac-os"); + C.OperatingSystem_Linux_linux = new N.OperatingSystem("Linux", "linux"); + C.OperatingSystem_Android_android = new N.OperatingSystem("Android", "android"); + C.OperatingSystem_iOS_ios = new N.OperatingSystem("iOS", "ios"); + C.List_opx = H.setRuntimeTypeInfo(makeConstList([C.OperatingSystem_Windows_windows, C.OperatingSystem_RkP, C.OperatingSystem_Linux_linux, C.OperatingSystem_Android_android, C.OperatingSystem_iOS_ios]), H.findType("JSArray<OperatingSystem>")); + C.List_qFt = H.setRuntimeTypeInfo(makeConstList([0, 0, 27858, 1023, 65534, 51199, 65535, 32767]), type$.JSArray_int); + C.List_qNA = H.setRuntimeTypeInfo(makeConstList([0, 0, 32754, 11263, 65534, 34815, 65534, 18431]), type$.JSArray_int); + C.List_qg40 = H.setRuntimeTypeInfo(makeConstList([0, 0, 32722, 12287, 65535, 34815, 65534, 18431]), type$.JSArray_int); + C.List_qg4 = H.setRuntimeTypeInfo(makeConstList([0, 0, 65490, 12287, 65535, 34815, 65534, 18431]), type$.JSArray_int); + C.List_F9h = H.setRuntimeTypeInfo(makeConstList(["\n", "\r", "\f", "\b", "\t", "\v", "\x7f"]), type$.JSArray_String); + C.Map_F9GZw = new H.ConstantStringMap(7, {"\n": "\\n", "\r": "\\r", "\f": "\\f", "\b": "\\b", "\t": "\\t", "\v": "\\v", "\x7f": "\\x7F"}, C.List_F9h, H.findType("ConstantStringMap<String,String>")); + C.List_empty2 = H.setRuntimeTypeInfo(makeConstList([]), H.findType("JSArray<BooleanSelector>")); + C.Map_empty0 = new H.ConstantStringMap(0, {}, C.List_empty2, H.findType("ConstantStringMap<BooleanSelector,Metadata>")); + C.Map_empty1 = new H.ConstantStringMap(0, {}, C.List_empty1, H.findType("ConstantStringMap<Null,Null>")); + C.List_empty3 = H.setRuntimeTypeInfo(makeConstList([]), H.findType("JSArray<PlatformSelector>")); + C.Map_empty = new H.ConstantStringMap(0, {}, C.List_empty3, H.findType("ConstantStringMap<PlatformSelector,Metadata>")); + C.MessageType_print = new D.MessageType("print"); + C.MessageType_skip = new D.MessageType("skip"); + C.OperatingSystem_none_none = new N.OperatingSystem("none", "none"); + C.PlatformSelector_All = new E.PlatformSelector(C.C_All); + C.Result_error = new G.Result0("error"); + C.Result_skipped = new G.Result0("skipped"); + C.Result_success = new G.Result0("success"); + C.Status_complete = new G.Status("complete"); + C.State_Status_complete_Result_error = new G.State(C.Status_complete, C.Result_error); + C.Result_failure = new G.Result0("failure"); + C.State_Status_complete_Result_failure = new G.State(C.Status_complete, C.Result_failure); + C.State_Status_complete_Result_skipped = new G.State(C.Status_complete, C.Result_skipped); + C.Status_pending = new G.Status("pending"); + C.State_Status_pending_Result_success = new G.State(C.Status_pending, C.Result_success); + C.Status_running = new G.Status("running"); + C.State_Status_running_Result_skipped = new G.State(C.Status_running, C.Result_skipped); + C.State_Status_running_Result_success = new G.State(C.Status_running, C.Result_success); + C.Symbol_Drw = new H.Symbol("test.declarer"); + C.Symbol_MAi = new H.Symbol("test.runner.test_channel"); + C.Symbol_cQL = new H.Symbol("test.invoker"); + C.Symbol_runCount = new H.Symbol("runCount"); + C.Timeout_null_1 = new R.Timeout(null, 1); + C.Timeout_null_null = new R.Timeout(null, null); + C.TokenType_31K = new L.TokenType("right paren"); + C.TokenType_69P = new L.TokenType("question mark"); + C.TokenType_and = new L.TokenType("and"); + C.TokenType_colon = new L.TokenType("colon"); + C.TokenType_e7P = new L.TokenType("left paren"); + C.TokenType_identifier = new L.TokenType("identifier"); + C.TokenType_not = new L.TokenType("not"); + C.TokenType_or = new L.TokenType("or"); + C.TokenType_wwi = new L.TokenType("end of file"); + C.Type_ByteBuffer_RkP = H.typeLiteral("ByteBuffer"); + C.Type_ByteData_zNC = H.typeLiteral("ByteData"); + C.Type_Float32List_LB7 = H.typeLiteral("Float32List"); + C.Type_Float64List_LB7 = H.typeLiteral("Float64List"); + C.Type_Int16List_uXf = H.typeLiteral("Int16List"); + C.Type_Int32List_O50 = H.typeLiteral("Int32List"); + C.Type_Int8List_ekJ = H.typeLiteral("Int8List"); + C.Type_JSObject_8k0 = H.typeLiteral("JSObject"); + C.Type_Null_Yyn = H.typeLiteral("Null"); + C.Type_String_k8F = H.typeLiteral("String"); + C.Type_Uint16List_2bx = H.typeLiteral("Uint16List"); + C.Type_Uint32List_2bx = H.typeLiteral("Uint32List"); + C.Type_Uint8ClampedList_Jik = H.typeLiteral("Uint8ClampedList"); + C.Type_Uint8List_WLA = H.typeLiteral("Uint8List"); + C.Type_bool_lhE = H.typeLiteral("bool"); + C.Type_double_K1J = H.typeLiteral("double"); + C.Type_int_tHn = H.typeLiteral("int"); + C.Type_num_cv7 = H.typeLiteral("num"); + C._PathDirection_8Gl = new M._PathDirection("at root"); + C._PathDirection_988 = new M._PathDirection("below root"); + C._PathDirection_FIw = new M._PathDirection("reaches root"); + C._PathDirection_ZGD = new M._PathDirection("above root"); + C._PathRelation_different = new M._PathRelation("different"); + C._PathRelation_equal = new M._PathRelation("equal"); + C._PathRelation_inconclusive = new M._PathRelation("inconclusive"); + C._PathRelation_within = new M._PathRelation("within"); + C._StreamGroupState_canceled = new L._StreamGroupState("canceled"); + C._StreamGroupState_dormant = new L._StreamGroupState("dormant"); + C._StreamGroupState_listening = new L._StreamGroupState("listening"); + C._StreamGroupState_paused = new L._StreamGroupState("paused"); + C._TokenKind_false_false_false = new T._TokenKind(false, false, false); + C._TokenKind_false_false_true = new T._TokenKind(false, false, true); + C._TokenKind_false_true_false = new T._TokenKind(false, true, false); + C._TokenKind_true_false_false = new T._TokenKind(true, false, false); + C._ZoneFunction_3bB = new P._ZoneFunction(C.C__RootZone, P.async___rootCreatePeriodicTimer$closure(), type$._ZoneFunction_of_Timer_Function_5_Zone_and_ZoneDelegate_and_Zone_and_Duration_and_void_Function_Timer); + C._ZoneFunction_7G2 = new P._ZoneFunction(C.C__RootZone, P.async___rootRegisterBinaryCallback$closure(), type$._ZoneFunction_Function); + C._ZoneFunction_Eeh = new P._ZoneFunction(C.C__RootZone, P.async___rootRegisterUnaryCallback$closure(), type$._ZoneFunction_Function); + C._ZoneFunction_NMc = new P._ZoneFunction(C.C__RootZone, P.async___rootHandleUncaughtError$closure(), type$._ZoneFunction_of_void_Function_Zone_ZoneDelegate_Zone_Object_StackTrace); + C._ZoneFunction__RootZone__rootCreateTimer = new P._ZoneFunction(C.C__RootZone, P.async___rootCreateTimer$closure(), type$._ZoneFunction_of_Timer_Function_5_Zone_and_ZoneDelegate_and_Zone_and_Duration_and_void_Function); + C._ZoneFunction__RootZone__rootErrorCallback = new P._ZoneFunction(C.C__RootZone, P.async___rootErrorCallback$closure(), type$._ZoneFunction_of_AsyncError_Function_Zone_ZoneDelegate_Zone_Object_StackTrace); + C._ZoneFunction__RootZone__rootFork = new P._ZoneFunction(C.C__RootZone, P.async___rootFork$closure(), type$._ZoneFunction_of_Zone_Function_5_Zone_and_ZoneDelegate_and_Zone_and_ZoneSpecification_and_Map_dynamic_dynamic); + C._ZoneFunction__RootZone__rootPrint = new P._ZoneFunction(C.C__RootZone, P.async___rootPrint$closure(), type$._ZoneFunction_of_void_Function_Zone_ZoneDelegate_Zone_String); + C._ZoneFunction__RootZone__rootRegisterCallback = new P._ZoneFunction(C.C__RootZone, P.async___rootRegisterCallback$closure(), type$._ZoneFunction_Function); + C._ZoneFunction__RootZone__rootRun = new P._ZoneFunction(C.C__RootZone, P.async___rootRun$closure(), type$._ZoneFunction_Function); + C._ZoneFunction__RootZone__rootRunBinary = new P._ZoneFunction(C.C__RootZone, P.async___rootRunBinary$closure(), type$._ZoneFunction_Function); + C._ZoneFunction__RootZone__rootRunUnary = new P._ZoneFunction(C.C__RootZone, P.async___rootRunUnary$closure(), type$._ZoneFunction_Function); + C._ZoneFunction__RootZone__rootScheduleMicrotask = new P._ZoneFunction(C.C__RootZone, P.async___rootScheduleMicrotask$closure(), type$._ZoneFunction_of_void_Function_4_Zone_and_ZoneDelegate_and_Zone_and_void_Function); + C._ZoneSpecification_ALf = new P._ZoneSpecification(null, null, null, null, null, null, null, null, null, null, null, null, null); + })(); + (function staticFields() { + $.printToZone = null; + $.Primitives_timerFrequency = null; + $.Primitives_timerTicks = null; + $.Closure_functionCounter = 0; + $.BoundClosure_selfFieldNameCache = null; + $.BoundClosure_receiverFieldNameCache = null; + $.getTagFunction = null; + $.alternateTagFunction = null; + $.prototypeForTagFunction = null; + $.dispatchRecordsForInstanceTags = null; + $.interceptorsForUncacheableTags = null; + $.initNativeDispatchFlag = null; + $._nextCallback = null; + $._lastCallback = null; + $._lastPriorityCallback = null; + $._isInCallbackLoop = false; + $.Zone__current = C.C__RootZone; + $._RootZone__rootDelegate = null; + $._toStringVisiting = []; + $.Expando__keyCount = 0; + $.Stopwatch__frequency = null; + $._currentUriBase = null; + $._current = null; + $._glyphs = C.C_UnicodeGlyphSet; + $._macOSDirectories = P.LinkedHashSet_LinkedHashSet$_literal(["/Applications", "/Library", "/Network", "/System", "/Users"], type$.String); + $._globalDeclarer = null; + $.x = 0; + })(); + (function lazyInitializers() { + var _lazy = hunkHelpers.lazy; + _lazy($, "DART_CLOSURE_PROPERTY_NAME", "$get$DART_CLOSURE_PROPERTY_NAME", function() { + return H.getIsolateAffinityTag("_$dart_dartClosure"); + }); + _lazy($, "JS_INTEROP_INTERCEPTOR_TAG", "$get$JS_INTEROP_INTERCEPTOR_TAG", function() { + return H.getIsolateAffinityTag("_$dart_js"); + }); + _lazy($, "TypeErrorDecoder_noSuchMethodPattern", "$get$TypeErrorDecoder_noSuchMethodPattern", function() { + return H.TypeErrorDecoder_extractPattern(H.TypeErrorDecoder_provokeCallErrorOn({ + toString: function() { + return "$receiver$"; + } + })); + }); + _lazy($, "TypeErrorDecoder_notClosurePattern", "$get$TypeErrorDecoder_notClosurePattern", function() { + return H.TypeErrorDecoder_extractPattern(H.TypeErrorDecoder_provokeCallErrorOn({$method$: null, + toString: function() { + return "$receiver$"; + } + })); + }); + _lazy($, "TypeErrorDecoder_nullCallPattern", "$get$TypeErrorDecoder_nullCallPattern", function() { + return H.TypeErrorDecoder_extractPattern(H.TypeErrorDecoder_provokeCallErrorOn(null)); + }); + _lazy($, "TypeErrorDecoder_nullLiteralCallPattern", "$get$TypeErrorDecoder_nullLiteralCallPattern", function() { + return H.TypeErrorDecoder_extractPattern(function() { + var $argumentsExpr$ = '$arguments$'; + try { + null.$method$($argumentsExpr$); + } catch (e) { + return e.message; + } + }()); + }); + _lazy($, "TypeErrorDecoder_undefinedCallPattern", "$get$TypeErrorDecoder_undefinedCallPattern", function() { + return H.TypeErrorDecoder_extractPattern(H.TypeErrorDecoder_provokeCallErrorOn(void 0)); + }); + _lazy($, "TypeErrorDecoder_undefinedLiteralCallPattern", "$get$TypeErrorDecoder_undefinedLiteralCallPattern", function() { + return H.TypeErrorDecoder_extractPattern(function() { + var $argumentsExpr$ = '$arguments$'; + try { + (void 0).$method$($argumentsExpr$); + } catch (e) { + return e.message; + } + }()); + }); + _lazy($, "TypeErrorDecoder_nullPropertyPattern", "$get$TypeErrorDecoder_nullPropertyPattern", function() { + return H.TypeErrorDecoder_extractPattern(H.TypeErrorDecoder_provokePropertyErrorOn(null)); + }); + _lazy($, "TypeErrorDecoder_nullLiteralPropertyPattern", "$get$TypeErrorDecoder_nullLiteralPropertyPattern", function() { + return H.TypeErrorDecoder_extractPattern(function() { + try { + null.$method$; + } catch (e) { + return e.message; + } + }()); + }); + _lazy($, "TypeErrorDecoder_undefinedPropertyPattern", "$get$TypeErrorDecoder_undefinedPropertyPattern", function() { + return H.TypeErrorDecoder_extractPattern(H.TypeErrorDecoder_provokePropertyErrorOn(void 0)); + }); + _lazy($, "TypeErrorDecoder_undefinedLiteralPropertyPattern", "$get$TypeErrorDecoder_undefinedLiteralPropertyPattern", function() { + return H.TypeErrorDecoder_extractPattern(function() { + try { + (void 0).$method$; + } catch (e) { + return e.message; + } + }()); + }); + _lazy($, "_AsyncRun__scheduleImmediateClosure", "$get$_AsyncRun__scheduleImmediateClosure", function() { + return P._AsyncRun__initializeScheduleImmediate(); + }); + _lazy($, "Future__nullFuture", "$get$Future__nullFuture", function() { + return P._Future$zoneValue(null, C.C__RootZone, type$.Null); + }); + _lazy($, "_RootZone__rootMap", "$get$_RootZone__rootMap", function() { + var t1 = type$.dynamic; + return P.HashMap_HashMap(t1, t1); + }); + _lazy($, "Utf8Decoder__decoder", "$get$Utf8Decoder__decoder", function() { + return P.Utf8Decoder__makeDecoder(); + }); + _lazy($, "_Base64Decoder__inverseAlphabet", "$get$_Base64Decoder__inverseAlphabet", function() { + return H.NativeInt8List__create1(H._ensureNativeList(H.setRuntimeTypeInfo([-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -2, -2, -2, -2, -2, 62, -2, 62, -2, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -2, -2, -2, -1, -2, -2, -2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -2, -2, -2, -2, 63, -2, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -2, -2, -2, -2, -2], type$.JSArray_int))); + }); + _lazy($, "_Uri__isWindowsCached", "$get$_Uri__isWindowsCached", function() { + return typeof process != "undefined" && Object.prototype.toString.call(process) == "[object process]" && process.platform == "win32"; + }); + _lazy($, "_Uri__needsNoEncoding", "$get$_Uri__needsNoEncoding", function() { + return P.RegExp_RegExp("^[\\-\\.0-9A-Z_a-z~]*$", false); + }); + _lazy($, "_hasErrorStackProperty", "$get$_hasErrorStackProperty", function() { + return new Error().stack != void 0; + }); + _lazy($, "_scannerTables", "$get$_scannerTables", function() { + return P._createTables(); + }); + _lazy($, "_whitespaceAndSingleLineComments", "$get$_whitespaceAndSingleLineComments", function() { + return P.RegExp_RegExp("([ \\t\\n]+|//[^\\n]*(\\n|$))+", false); + }); + _lazy($, "_multiLineCommentBody", "$get$_multiLineCommentBody", function() { + return P.RegExp_RegExp("([^/*]|/[^*]|\\*[^/])+", false); + }); + _lazy($, "_hyphenatedIdentifier", "$get$_hyphenatedIdentifier0", function() { + return P.RegExp_RegExp("[a-zA-Z_-][a-zA-Z0-9_-]*", false); + }); + _lazy($, "_dart2DynamicArgs", "$get$_dart2DynamicArgs", function() { + return P.RegExp_RegExp("<dynamic(, dynamic)*>", false); + }); + _lazy($, "_escapeRegExp", "$get$_escapeRegExp", function() { + return P.RegExp_RegExp("[\\x00-\\x07\\x0E-\\x1F" + C.Map_F9GZw.get$keys().map$1$1(0, M.util___getHexLiteral$closure(), type$.String).join$0(0) + "]", false); + }); + _lazy($, "windows", "$get$windows", function() { + return M.Context_Context($.$get$Style_windows()); + }); + _lazy($, "url", "$get$url", function() { + return M.Context_Context($.$get$Style_url()); + }); + _lazy($, "context", "$get$context", function() { + return new M.Context($.$get$Style_platform(), null); + }); + _lazy($, "Style_posix", "$get$Style_posix", function() { + return new E.PosixStyle(P.RegExp_RegExp("/", false), P.RegExp_RegExp("[^/]$", false), P.RegExp_RegExp("^/", false)); + }); + _lazy($, "Style_windows", "$get$Style_windows", function() { + return new L.WindowsStyle(P.RegExp_RegExp("[/\\\\]", false), P.RegExp_RegExp("[^/\\\\]$", false), P.RegExp_RegExp("^(\\\\\\\\[^\\\\]+\\\\[^\\\\/]+|[a-zA-Z]:[/\\\\])", false), P.RegExp_RegExp("^[/\\\\](?![/\\\\])", false)); + }); + _lazy($, "Style_url", "$get$Style_url", function() { + return new F.UrlStyle(P.RegExp_RegExp("/", false), P.RegExp_RegExp("(^[a-zA-Z][-+.a-zA-Z\\d]*://|[^/])$", false), P.RegExp_RegExp("[a-zA-Z][-+.a-zA-Z\\d]*://[^/]*", false), P.RegExp_RegExp("^/", false)); + }); + _lazy($, "Style_platform", "$get$Style_platform", function() { + return O.Style__getPlatformStyle(); + }); + _lazy($, "_digits", "$get$_digits", function() { + return new L.closure().call$0(); + }); + _lazy($, "MAX_INT32", "$get$MAX_INT32", function() { + return H._checkIntNullable(P.pow(2, 31) - 1); + }); + _lazy($, "MIN_INT32", "$get$MIN_INT32", function() { + return H._checkIntNullable(-P.pow(2, 31)); + }); + _lazy($, "_specKey", "$get$_specKey", function() { + return new P.Object(); + }); + _lazy($, "_vmFrame", "$get$_vmFrame", function() { + return P.RegExp_RegExp("^#\\d+\\s+(\\S.*) \\((.+?)((?::\\d+){0,2})\\)$", false); + }); + _lazy($, "_v8Frame", "$get$_v8Frame", function() { + return P.RegExp_RegExp("^\\s*at (?:(\\S.*?)(?: \\[as [^\\]]+\\])? \\((.*)\\)|(.*))$", false); + }); + _lazy($, "_v8UrlLocation", "$get$_v8UrlLocation", function() { + return P.RegExp_RegExp("^(.*):(\\d+):(\\d+)|native$", false); + }); + _lazy($, "_v8EvalLocation", "$get$_v8EvalLocation", function() { + return P.RegExp_RegExp("^eval at (?:\\S.*?) \\((.*)\\)(?:, .*?:\\d+:\\d+)?$", false); + }); + _lazy($, "_firefoxSafariFrame", "$get$_firefoxSafariFrame", function() { + return P.RegExp_RegExp("^(?:([^@(/]*)(?:\\(.*\\))?((?:/[^/]*)*)(?:\\(.*\\))?@)?(.*?):(\\d*)(?::(\\d*))?$", false); + }); + _lazy($, "_friendlyFrame", "$get$_friendlyFrame", function() { + return P.RegExp_RegExp("^(\\S+)(?: (\\d+)(?::(\\d+))?)?\\s+([^\\d].*)$", false); + }); + _lazy($, "_asyncBody", "$get$_asyncBody", function() { + return P.RegExp_RegExp("<(<anonymous closure>|[^>]+)_async_body>", false); + }); + _lazy($, "_initialDot", "$get$_initialDot", function() { + return P.RegExp_RegExp("^\\.", false); + }); + _lazy($, "Frame__uriRegExp", "$get$Frame__uriRegExp", function() { + return P.RegExp_RegExp("^[a-zA-Z][-+.a-zA-Z\\d]*://", false); + }); + _lazy($, "Frame__windowsRegExp", "$get$Frame__windowsRegExp", function() { + return P.RegExp_RegExp("^([a-zA-Z]:[\\\\/]|\\\\\\\\)", false); + }); + _lazy($, "StackZoneSpecification_disableKey", "$get$StackZoneSpecification_disableKey", function() { + return new P.Object(); + }); + _lazy($, "_terseRegExp", "$get$_terseRegExp", function() { + return P.RegExp_RegExp("(-patch)?([/\\\\].*)?$", false); + }); + _lazy($, "_v8Trace", "$get$_v8Trace", function() { + return P.RegExp_RegExp("\\n ?at ", false); + }); + _lazy($, "_v8TraceLine", "$get$_v8TraceLine", function() { + return P.RegExp_RegExp(" ?at ", false); + }); + _lazy($, "_firefoxSafariTrace", "$get$_firefoxSafariTrace", function() { + return P.RegExp_RegExp("^(([.0-9A-Za-z_$/<]|\\(.*\\))*@)?[^\\s]*:\\d*$", true); + }); + _lazy($, "_friendlyTrace", "$get$_friendlyTrace", function() { + return P.RegExp_RegExp("^[^\\s<][^\\s]*( \\d+(:\\d+)?)?[ \\t]+[^\\s]+$", true); + }); + _lazy($, "Metadata_empty", "$get$Metadata_empty", function() { + var _null = null; + return O.Metadata$_(_null, _null, _null, _null, _null, _null, _null, _null, _null, _null); + }); + _lazy($, "_universalValidVariables", "$get$_universalValidVariables", function() { + var _i, + t1 = P.LinkedHashSet_LinkedHashSet(type$.String); + t1.add$1(0, "posix"); + t1.add$1(0, "dart-vm"); + t1.add$1(0, "browser"); + t1.add$1(0, "js"); + t1.add$1(0, "blink"); + t1.add$1(0, "google"); + for (_i = 0; _i < 7; ++_i) + t1.add$1(0, C.List_m7e[_i].identifier); + for (_i = 0; _i < 5; ++_i) + t1.add$1(0, C.List_opx[_i].identifier); + return t1; + }); + _lazy($, "_currentKey", "$get$_currentKey0", function() { + return new P.Object(); + }); + _lazy($, "_currentKey0", "$get$_currentKey", function() { + return new P.Object(); + }); + _lazy($, "currentOSGuess", "$get$currentOSGuess", function() { + return new B.closure0().call$0(); + }); + _lazy($, "_hyphenatedIdentifier0", "$get$_hyphenatedIdentifier", function() { + return P.RegExp_RegExp("[a-zA-Z_-][a-zA-Z0-9_-]*", false); + }); + _lazy($, "anchoredHyphenatedIdentifier", "$get$anchoredHyphenatedIdentifier", function() { + return P.RegExp_RegExp("^" + $.$get$_hyphenatedIdentifier().pattern + "$", false); + }); + _lazy($, "SuiteConfiguration_empty", "$get$SuiteConfiguration_empty", function() { + var t1, _null = null; + U.SuiteConfiguration__list(_null, type$.String); + t1 = type$.Pattern; + L.UnmodifiableSetView$(P.LinkedHashSet_LinkedHashSet$_empty(t1), t1); + U.SuiteConfiguration__list(_null, H.findType("RuntimeSelection")); + t1 = H.findType("SuiteConfiguration"); + U.SuiteConfiguration__map(_null, type$.BooleanSelector, t1); + U.SuiteConfiguration__map(_null, type$.PlatformSelector, t1); + $.$get$Metadata_empty(); + return new U.SuiteConfiguration(); + }); + })(); + (function nativeSupport() { + !function() { + var intern = function(s) { + var o = {}; + o[s] = 1; + return Object.keys(hunkHelpers.convertToFastObject(o))[0]; + }; + init.getIsolateTag = function(name) { + return intern("___dart_" + name + init.isolateTag); + }; + var tableProperty = "___dart_isolate_tags_"; + var usedProperties = Object[tableProperty] || (Object[tableProperty] = Object.create(null)); + var rootProperty = "_ZxYxX"; + for (var i = 0;; i++) { + var property = intern(rootProperty + "_" + i + "_"); + if (!(property in usedProperties)) { + usedProperties[property] = 1; + init.isolateTag = property; + break; + } + } + init.dispatchPropertyName = init.getIsolateTag("dispatch_record"); + }(); + hunkHelpers.setOrUpdateInterceptorsByTag({ArrayBuffer: H.NativeByteBuffer, ArrayBufferView: H.NativeTypedData, DataView: H.NativeByteData, Float32Array: H.NativeFloat32List, Float64Array: H.NativeFloat64List, Int16Array: H.NativeInt16List, Int32Array: H.NativeInt32List, Int8Array: H.NativeInt8List, Uint16Array: H.NativeUint16List, Uint32Array: H.NativeUint32List, Uint8ClampedArray: H.NativeUint8ClampedList, CanvasPixelArray: H.NativeUint8ClampedList, Uint8Array: H.NativeUint8List, ApplicationCacheErrorEvent: W.ApplicationCacheErrorEvent, Blob: W.Blob, DOMError: W.DomError, DOMException: W.DomException, ErrorEvent: W.ErrorEvent, AbortPaymentEvent: W.Event, AnimationEvent: W.Event, AnimationPlaybackEvent: W.Event, BackgroundFetchClickEvent: W.Event, BackgroundFetchEvent: W.Event, BackgroundFetchFailEvent: W.Event, BackgroundFetchedEvent: W.Event, BeforeInstallPromptEvent: W.Event, BeforeUnloadEvent: W.Event, BlobEvent: W.Event, CanMakePaymentEvent: W.Event, ClipboardEvent: W.Event, CloseEvent: W.Event, CompositionEvent: W.Event, CustomEvent: W.Event, DeviceMotionEvent: W.Event, DeviceOrientationEvent: W.Event, ExtendableEvent: W.Event, ExtendableMessageEvent: W.Event, FetchEvent: W.Event, FocusEvent: W.Event, FontFaceSetLoadEvent: W.Event, ForeignFetchEvent: W.Event, GamepadEvent: W.Event, HashChangeEvent: W.Event, InstallEvent: W.Event, KeyboardEvent: W.Event, MediaEncryptedEvent: W.Event, MediaQueryListEvent: W.Event, MediaStreamEvent: W.Event, MediaStreamTrackEvent: W.Event, MIDIConnectionEvent: W.Event, MIDIMessageEvent: W.Event, MouseEvent: W.Event, DragEvent: W.Event, MutationEvent: W.Event, NotificationEvent: W.Event, PageTransitionEvent: W.Event, PaymentRequestEvent: W.Event, PaymentRequestUpdateEvent: W.Event, PointerEvent: W.Event, PopStateEvent: W.Event, PresentationConnectionAvailableEvent: W.Event, ProgressEvent: W.Event, PromiseRejectionEvent: W.Event, PushEvent: W.Event, RTCDataChannelEvent: W.Event, RTCDTMFToneChangeEvent: W.Event, RTCPeerConnectionIceEvent: W.Event, RTCTrackEvent: W.Event, SecurityPolicyViolationEvent: W.Event, SensorErrorEvent: W.Event, SpeechRecognitionEvent: W.Event, SpeechSynthesisEvent: W.Event, StorageEvent: W.Event, SyncEvent: W.Event, TextEvent: W.Event, TouchEvent: W.Event, TrackEvent: W.Event, TransitionEvent: W.Event, WebKitTransitionEvent: W.Event, UIEvent: W.Event, VRDeviceEvent: W.Event, VRDisplayEvent: W.Event, VRSessionEvent: W.Event, WheelEvent: W.Event, MojoInterfaceRequestEvent: W.Event, ResourceProgressEvent: W.Event, USBConnectionEvent: W.Event, IDBVersionChangeEvent: W.Event, AudioProcessingEvent: W.Event, OfflineAudioCompletionEvent: W.Event, WebGLContextEvent: W.Event, Event: W.Event, InputEvent: W.Event, Window: W.EventTarget, DOMWindow: W.EventTarget, EventTarget: W.EventTarget, File: W.File, Location: W.Location, MediaError: W.MediaError, MediaKeyMessageEvent: W.MediaKeyMessageEvent, MessageEvent: W.MessageEvent, MessagePort: W.MessagePort, NavigatorUserMediaError: W.NavigatorUserMediaError, OverconstrainedError: W.OverconstrainedError, PositionError: W.PositionError, PresentationConnectionCloseEvent: W.PresentationConnectionCloseEvent, SpeechRecognitionError: W.SpeechRecognitionError, SQLError: P.SqlError}); + hunkHelpers.setOrUpdateLeafTags({ArrayBuffer: true, ArrayBufferView: false, DataView: true, Float32Array: true, Float64Array: true, Int16Array: true, Int32Array: true, Int8Array: true, Uint16Array: true, Uint32Array: true, Uint8ClampedArray: true, CanvasPixelArray: true, Uint8Array: false, ApplicationCacheErrorEvent: true, Blob: false, DOMError: true, DOMException: true, ErrorEvent: true, AbortPaymentEvent: true, AnimationEvent: true, AnimationPlaybackEvent: true, BackgroundFetchClickEvent: true, BackgroundFetchEvent: true, BackgroundFetchFailEvent: true, BackgroundFetchedEvent: true, BeforeInstallPromptEvent: true, BeforeUnloadEvent: true, BlobEvent: true, CanMakePaymentEvent: true, ClipboardEvent: true, CloseEvent: true, CompositionEvent: true, CustomEvent: true, DeviceMotionEvent: true, DeviceOrientationEvent: true, ExtendableEvent: true, ExtendableMessageEvent: true, FetchEvent: true, FocusEvent: true, FontFaceSetLoadEvent: true, ForeignFetchEvent: true, GamepadEvent: true, HashChangeEvent: true, InstallEvent: true, KeyboardEvent: true, MediaEncryptedEvent: true, MediaQueryListEvent: true, MediaStreamEvent: true, MediaStreamTrackEvent: true, MIDIConnectionEvent: true, MIDIMessageEvent: true, MouseEvent: true, DragEvent: true, MutationEvent: true, NotificationEvent: true, PageTransitionEvent: true, PaymentRequestEvent: true, PaymentRequestUpdateEvent: true, PointerEvent: true, PopStateEvent: true, PresentationConnectionAvailableEvent: true, ProgressEvent: true, PromiseRejectionEvent: true, PushEvent: true, RTCDataChannelEvent: true, RTCDTMFToneChangeEvent: true, RTCPeerConnectionIceEvent: true, RTCTrackEvent: true, SecurityPolicyViolationEvent: true, SensorErrorEvent: true, SpeechRecognitionEvent: true, SpeechSynthesisEvent: true, StorageEvent: true, SyncEvent: true, TextEvent: true, TouchEvent: true, TrackEvent: true, TransitionEvent: true, WebKitTransitionEvent: true, UIEvent: true, VRDeviceEvent: true, VRDisplayEvent: true, VRSessionEvent: true, WheelEvent: true, MojoInterfaceRequestEvent: true, ResourceProgressEvent: true, USBConnectionEvent: true, IDBVersionChangeEvent: true, AudioProcessingEvent: true, OfflineAudioCompletionEvent: true, WebGLContextEvent: true, Event: false, InputEvent: false, Window: true, DOMWindow: true, EventTarget: false, File: true, Location: true, MediaError: true, MediaKeyMessageEvent: true, MessageEvent: true, MessagePort: true, NavigatorUserMediaError: true, OverconstrainedError: true, PositionError: true, PresentationConnectionCloseEvent: true, SpeechRecognitionError: true, SQLError: true}); + H.NativeTypedArray.$nativeSuperclassTag = "ArrayBufferView"; + H._NativeTypedArrayOfDouble_NativeTypedArray_ListMixin.$nativeSuperclassTag = "ArrayBufferView"; + H._NativeTypedArrayOfDouble_NativeTypedArray_ListMixin_FixedLengthListMixin.$nativeSuperclassTag = "ArrayBufferView"; + H.NativeTypedArrayOfDouble.$nativeSuperclassTag = "ArrayBufferView"; + H._NativeTypedArrayOfInt_NativeTypedArray_ListMixin.$nativeSuperclassTag = "ArrayBufferView"; + H._NativeTypedArrayOfInt_NativeTypedArray_ListMixin_FixedLengthListMixin.$nativeSuperclassTag = "ArrayBufferView"; + H.NativeTypedArrayOfInt.$nativeSuperclassTag = "ArrayBufferView"; + })(); + Function.prototype.call$0 = function() { + return this(); + }; + Function.prototype.call$1 = function(a) { + return this(a); + }; + Function.prototype.call$2 = function(a, b) { + return this(a, b); + }; + Function.prototype.call$3$3 = function(a, b, c) { + return this(a, b, c); + }; + Function.prototype.call$2$2 = function(a, b) { + return this(a, b); + }; + Function.prototype.call$1$1 = function(a) { + return this(a); + }; + Function.prototype.call$2$1 = function(a) { + return this(a); + }; + Function.prototype.call$3 = function(a, b, c) { + return this(a, b, c); + }; + Function.prototype.call$4 = function(a, b, c, d) { + return this(a, b, c, d); + }; + Function.prototype.call$3$1 = function(a) { + return this(a); + }; + Function.prototype.call$2$3 = function(a, b, c) { + return this(a, b, c); + }; + Function.prototype.call$1$2 = function(a, b) { + return this(a, b); + }; + Function.prototype.call$5 = function(a, b, c, d, e) { + return this(a, b, c, d, e); + }; + Function.prototype.call$3$4 = function(a, b, c, d) { + return this(a, b, c, d); + }; + Function.prototype.call$2$4 = function(a, b, c, d) { + return this(a, b, c, d); + }; + Function.prototype.call$1$4 = function(a, b, c, d) { + return this(a, b, c, d); + }; + Function.prototype.call$3$6 = function(a, b, c, d, e, f) { + return this(a, b, c, d, e, f); + }; + Function.prototype.call$2$5 = function(a, b, c, d, e) { + return this(a, b, c, d, e); + }; + Function.prototype.call$2$0 = function() { + return this(); + }; + convertAllToFastObject(holders); + convertToFastObject($); + (function(callback) { + if (typeof document === "undefined") { + callback(null); + return; + } + if (typeof document.currentScript != 'undefined') { + callback(document.currentScript); + return; + } + var scripts = document.scripts; + function onLoad(event) { + for (var i = 0; i < scripts.length; ++i) + scripts[i].removeEventListener("load", onLoad, false); + callback(event.target); + } + for (var i = 0; i < scripts.length; ++i) + scripts[i].addEventListener("load", onLoad, false); + })(function(currentScript) { + init.currentScript = currentScript; + if (typeof dartMainRunner === "function") + dartMainRunner(R.main, []); + else + R.main([]); + }); +})(); + +//# sourceMappingURL=main_test.dart.browser_test.dart.js.map
diff --git a/pkgs/coverage/test/test_files/main_test.js.map b/pkgs/coverage/test/test_files/main_test.js.map new file mode 100644 index 0000000..38669ba --- /dev/null +++ b/pkgs/coverage/test/test_files/main_test.js.map
@@ -0,0 +1 @@ +{"version":3,"engine":"v2","file":"main_test.dart.browser_test.dart.js","sourceRoot":"","sources":["google3:///third_party/dart_lang/v2/sdk/lib/internal/cast.dart","google3:///third_party/dart_lang/v2/sdk/lib/internal/internal.dart","google3:///third_party/dart_lang/v2/sdk/lib/internal/iterable.dart","google3:///third_party/dart_lang/v2/sdk/lib/core/errors.dart","google3:///third_party/dart_lang/v2/sdk/lib/_internal/js_runtime/lib/constant_map.dart","google3:///third_party/dart_lang/v2/sdk/lib/_internal/js_runtime/lib/instantiation.dart","google3:///third_party/dart_lang/v2/sdk/lib/_internal/js_runtime/lib/js_helper.dart","google3:///third_party/dart_lang/v2/sdk/lib/_internal/js_runtime/lib/rti.dart","google3:///third_party/dart_lang/v2/sdk/lib/_internal/js_runtime/lib/native_helper.dart","google3:///third_party/dart_lang/v2/sdk/lib/_internal/js_runtime/lib/core_patch.dart","google3:///third_party/dart_lang/v2/sdk/lib/_internal/js_runtime/lib/js_rti.dart","google3:///third_party/dart_lang/v2/sdk/lib/core/exceptions.dart","google3:///third_party/dart_lang/v2/sdk/lib/_internal/js_runtime/lib/interceptors.dart","google3:///third_party/dart_lang/v2/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart","google3:///third_party/dart_lang/v2/sdk/lib/_internal/js_runtime/lib/string_helper.dart","google3:///third_party/dart_lang/v2/sdk/lib/core/iterable.dart","google3:///third_party/dart_lang/v2/sdk/lib/_internal/js_runtime/lib/native_typed_data.dart","google3:///third_party/dart_lang/v2/sdk/lib/_internal/js_runtime/lib/shared/recipe_syntax.dart","google3:///third_party/dart_lang/v2/sdk/lib/_internal/js_runtime/lib/js_names.dart","google3:///third_party/dart_lang/v2/sdk/lib/_internal/js_runtime/lib/js_primitives.dart","google3:///third_party/dart_lang/v2/sdk/lib/_internal/js_runtime/lib/js_array.dart","google3:///third_party/dart_lang/v2/sdk/lib/_internal/js_runtime/lib/js_string.dart","google3:///third_party/dart_lang/v2/sdk/lib/_internal/js_runtime/lib/async_patch.dart","google3:///third_party/dart_lang/v2/sdk/lib/core/duration.dart","google3:///third_party/dart_lang/v2/sdk/lib/async/future_impl.dart","google3:///third_party/dart_lang/v2/sdk/lib/async/zone.dart","google3:///third_party/dart_lang/v2/sdk/lib/async/future.dart","google3:///third_party/dart_lang/v2/sdk/lib/async/timer.dart","google3:///third_party/dart_lang/v2/sdk/lib/async/schedule_microtask.dart","google3:///third_party/dart_lang/v2/sdk/lib/async/stream.dart","google3:///third_party/dart_lang/v2/sdk/lib/async/stream_controller.dart","google3:///third_party/dart_lang/v2/sdk/lib/async/stream_impl.dart","google3:///third_party/dart_lang/v2/sdk/lib/async/stream_pipe.dart","google3:///third_party/dart_lang/v2/sdk/lib/_internal/js_runtime/lib/internal_patch.dart","google3:///third_party/dart_lang/v2/sdk/lib/_internal/js_runtime/lib/collection_patch.dart","google3:///third_party/dart_lang/v2/sdk/lib/_internal/js_runtime/lib/linked_hash_map.dart","google3:///third_party/dart_lang/v2/sdk/lib/collection/hash_map.dart","google3:///third_party/dart_lang/v2/sdk/lib/collection/iterable.dart","google3:///third_party/dart_lang/v2/sdk/lib/collection/linked_hash_map.dart","google3:///third_party/dart_lang/v2/sdk/lib/collection/linked_hash_set.dart","google3:///third_party/dart_lang/v2/sdk/lib/collection/maps.dart","google3:///third_party/dart_lang/v2/sdk/lib/collection/queue.dart","google3:///third_party/dart_lang/v2/sdk/lib/_internal/js_runtime/lib/convert_patch.dart","google3:///third_party/dart_lang/v2/sdk/lib/convert/base64.dart","google3:///third_party/dart_lang/v2/sdk/lib/convert/codec.dart","google3:///third_party/dart_lang/v2/sdk/lib/core/date_time.dart","google3:///third_party/dart_lang/v2/sdk/lib/core/list.dart","google3:///third_party/dart_lang/v2/sdk/lib/core/map.dart","google3:///third_party/dart_lang/v2/sdk/lib/core/print.dart","google3:///third_party/dart_lang/v2/sdk/lib/core/string.dart","google3:///third_party/dart_lang/v2/sdk/lib/core/uri.dart","google3:///third_party/dart_lang/v2/sdk/lib/convert/utf.dart","google3:///third_party/dart_lang/v2/sdk/lib/js_util/js_util.dart","google3:///third_party/dart_lang/v2/sdk/lib/_internal/js_runtime/lib/math_patch.dart","google3:///third_party/dart_lang/v2/sdk/lib/html/dart2js/html_dart2js.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.0.5/lib/src/span_scanner.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/source_span-1.5.5/lib/src/file.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_api/lib/src/remote_listener.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/stream_channel-2.0.0/lib/src/multi_channel.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/stream_channel-2.0.0/lib/src/stream_channel_controller.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_api/lib/src/suite_channel_manager.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/stream_channel-2.0.0/lib/src/guarantee_channel.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_api/lib/src/backend/stack_trace_formatter.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/path-1.6.4/lib/src/style.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/pool-1.4.0/lib/pool.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/async-2.4.0/lib/src/async_memoizer.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/source_map_stack_trace-1.1.5/lib/source_map_stack_trace.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.9.3/lib/src/chain.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.9.3/lib/src/trace.dart","google3:///third_party/dart_lang/v2/sdk/lib/core/stacktrace.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_api/lib/src/backend/group.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_api/lib/src/backend/metadata.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/collection-1.14.12/lib/src/unmodifiable_wrappers.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_api/lib/src/frontend/timeout.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_core/lib/src/runner/engine.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/async-2.4.0/lib/src/future_group.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/async-2.4.0/lib/src/stream_group.dart","google3:///third_party/dart_lang/v2/sdk/lib/async/broadcast_stream_controller.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/source_maps-0.10.8/lib/src/utils.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/collection-1.14.12/lib/src/functions.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/collection-1.14.12/lib/src/union_set_controller.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/collection-1.14.12/lib/src/union_set.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.9.3/lib/src/lazy_trace.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/package_resolver-1.0.10/lib/src/package_config_resolver.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/source_span-1.5.5/lib/src/location.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_api/lib/src/backend/live_test_controller.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_api/lib/src/util/test.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_api/lib/src/backend/invoker.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.0.5/lib/src/exception.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_api/lib/src/backend/platform_selector.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_api/lib/src/backend/suite_platform.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_core/lib/src/util/stack_trace_mapper.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/package_resolver-1.0.10/lib/src/package_root_resolver.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/source_maps-0.10.8/lib/src/vlq.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/source_maps-0.10.8/lib/parser.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test/lib/src/bootstrap/browser.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_core/lib/src/runner/plugin/remote_platform_helpers.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/stream_channel-2.0.0/lib/stream_channel.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/source_span-1.5.5/lib/src/span_exception.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_api/lib/src/frontend/expect.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.6/lib/src/description.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_api/lib/src/utils.dart","file:///usr/local/google/home/grouma/Projects/sample-test/test/main_test.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/path-1.6.4/lib/src/parsed_path.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/path-1.6.4/lib/src/path_exception.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/source_span-1.5.5/lib/src/span_with_context.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_api/lib/src/backend/declarer.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/boolean_selector-1.0.5/lib/src/ast.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/source_span-1.5.5/lib/src/highlighter.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.9.3/lib/src/stack_zone_specification.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.9.3/lib/src/lazy_chain.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_api/lib/src/backend/suite.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_core/lib/src/runner/suite.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_api/lib/src/util/remote_exception.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_core/lib/test_core.dart","","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_api/lib/src/backend/runtime.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_core/lib/src/runner/live_suite_controller.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/package_resolver-1.0.10/lib/src/utils.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/path-1.6.4/lib/src/utils.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/source_span-1.5.5/lib/src/utils.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.0.5/lib/src/utils.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/collection-1.14.12/lib/src/queue_list.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.6/lib/src/util.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.6/lib/src/core_matchers.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.6/lib/src/equals_matcher.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/path-1.6.4/lib/src/context.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/path-1.6.4/lib/path.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.6/lib/src/pretty_print.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.9.3/lib/src/frame.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.9.3/lib/src/unparsed_frame.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test/lib/src/runner/browser/post_message_channel.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_api/lib/src/backend/operating_system.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_api/lib/src/backend/closed_exception.dart","google3:///third_party/dart_lang/v2/sdk/lib/collection/list.dart","google3:///third_party/dart_lang/v2/sdk/lib/_internal/js_runtime/lib/js_number.dart","google3:///third_party/dart_lang/v2/sdk/lib/internal/list.dart","google3:///third_party/dart_lang/v2/sdk/lib/internal/symbol.dart","google3:///third_party/dart_lang/v2/sdk/lib/collection/collections.dart","google3:///third_party/dart_lang/v2/sdk/lib/collection/set.dart","google3:///third_party/dart_lang/v2/sdk/lib/convert/ascii.dart","google3:///third_party/dart_lang/v2/sdk/lib/convert/json.dart","google3:///third_party/dart_lang/v2/sdk/lib/core/object.dart","google3:///third_party/dart_lang/v2/sdk/lib/core/expando.dart","google3:///third_party/dart_lang/v2/sdk/lib/core/null.dart","google3:///third_party/dart_lang/v2/sdk/lib/core/stopwatch.dart","google3:///third_party/dart_lang/v2/sdk/lib/html/html_common/conversions_dart2js.dart","google3:///third_party/dart_lang/v2/sdk/lib/html/html_common/conversions.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/async-2.4.0/lib/src/delegate/stream_subscription.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/async-2.4.0/lib/src/null_stream_sink.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/async-2.4.0/lib/src/result/error.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/async-2.4.0/lib/src/result/value.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/async-2.4.0/lib/src/stream_completer.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/async-2.4.0/lib/src/stream_queue.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/async-2.4.0/lib/src/subscription_stream.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/async-2.4.0/lib/src/stream_sink_completer.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/boolean_selector-1.0.5/lib/src/all.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/boolean_selector-1.0.5/lib/src/evaluator.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/boolean_selector-1.0.5/lib/src/impl.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/boolean_selector-1.0.5/lib/src/intersection_selector.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/boolean_selector-1.0.5/lib/src/validator.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/boolean_selector-1.0.5/lib/src/none.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/boolean_selector-1.0.5/lib/src/parser.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/boolean_selector-1.0.5/lib/src/scanner.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.0.5/lib/src/string_scanner.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/boolean_selector-1.0.5/lib/src/token.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/boolean_selector-1.0.5/lib/src/visitor.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/collection-1.14.12/lib/src/empty_unmodifiable_set.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/collection-1.14.12/lib/src/wrappers.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.6/lib/src/feature_matcher.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.6/lib/src/interfaces.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.6/lib/src/type_matcher.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/path-1.6.4/lib/src/internal_style.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/path-1.6.4/lib/src/style/posix.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/path-1.6.4/lib/src/style/url.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/path-1.6.4/lib/src/style/windows.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/async-2.4.0/lib/src/restartable_timer.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/source_maps-0.10.8/lib/src/source_map_span.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.1.0/lib/src/generated/top_level.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.1.0/lib/term_glyph.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/source_span-1.5.5/lib/src/location_mixin.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/source_span-1.5.5/lib/src/span.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/source_span-1.5.5/lib/src/span_mixin.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/stream_channel-2.0.0/lib/src/stream_channel_completer.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.1.0/lib/src/generated/ascii_glyph_set.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.1.0/lib/src/generated/unicode_glyph_set.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_api/lib/src/backend/live_test.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_api/lib/src/backend/state.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_api/lib/src/backend/message.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_api/lib/src/util/iterable_set.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_core/lib/src/runner/runner_suite.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_core/lib/src/runner/reporter/expanded.dart","file:///usr/local/google/home/grouma/Projects/test/pkgs/test_core/lib/src/util/print_sink.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/async-2.4.0/lib/src/delegate/sink.dart","file:///usr/local/google/home/grouma/.pub-cache/hosted/pub.dartlang.org/async-2.4.0/lib/src/result/result.dart"],"names":["CastIterable","hexDigitValue","SubListIterable","MappedIterable","IterableElementError.noElement","IterableElementError.tooMany","IterableElementError.tooFew","ConstantMap._throwUnmodifiable","instantiate1","Instantiation1","unminifyOrTag","isJsIndexable","S","Primitives.objectHashCode","Primitives.parseInt","Primitives.objectTypeName","Primitives._objectTypeNameNewRti","Primitives._saneNativeClassName","Primitives.dateNow","Primitives.initTicker","Primitives.currentUri","Primitives._fromCharCodeApply","Primitives.stringFromCodePoints","Primitives.stringFromCharCodes","Primitives.stringFromNativeUint8List","Primitives.stringFromCharCode","Primitives.lazyAsJsDate","Primitives.getYear","Primitives.getMonth","Primitives.getDay","Primitives.getHours","Primitives.getMinutes","Primitives.getSeconds","Primitives.getMilliseconds","Primitives.getProperty","Primitives.setProperty","iae","ioore","diagnoseIndexError","diagnoseRangeError","argumentErrorValue","checkNum","wrapException","toStringWrapper","throwExpression","throwConcurrentModificationError","TypeErrorDecoder.extractPattern","TypeErrorDecoder.provokeCallErrorOn","TypeErrorDecoder.provokePropertyErrorOn","NullError","JsNoSuchMethodError","unwrapException","getTraceFromException","objectHashCode","fillLiteralMap","getLength","fillLiteralSet","invokeClosure","Exception","convertDartClosureToJS","Closure.fromTearOff","Closure._computeSignatureFunctionNewRti","Closure.cspForwardCall","Closure.forwardCallTo","Closure.cspForwardInterceptedCall","Closure.forwardInterceptedCallTo","closureFromTearOff","BoundClosure.evalRecipe","evalInInstance","BoundClosure.evalRecipeIntercepted","BoundClosure.selfOf","BoundClosure.receiverOf","BoundClosure.computeFieldNamed","boolConversionCheck","extractFunctionTypeObjectFromInternal","TypeErrorImplementation","_typeDescription","assertTest","assertThrow","assertHelper","throwCyclicInit","RuntimeError","getIsolateAffinityTag","setRuntimeTypeInfo","getRuntimeTypeInfo","getRuntimeTypeArguments","runtimeTypeToString","_runtimeTypeToString","_getRuntimeTypeAsString","getFutureOrArgument","_functionRtiToString","isInterestingBound","_joinArguments","getRuntimeType","_isClosure","substitute","computeSignature","invokeOn","defineProperty","lookupAndCacheInterceptor","patchProto","patchInteriorProto","makeLeafDispatchRecord","makeDefaultDispatchRecord","initNativeDispatch","initNativeDispatchContinue","lookupInterceptor","initHooks","applyHooksTransformer","JSSyntaxRegExp.makeNative","_MatchImplementation","stringContainsUnchecked","escapeReplacement","stringReplaceFirstRE","quoteStringForRegExp","stringReplaceAllUnchecked","stringReplaceAllUncheckedString","_stringIdentity","stringReplaceAllFuncUnchecked","_AllMatchesIterable.iterator","stringReplaceFirstUnchecked","stringReplaceRangeUnchecked","_ensureNativeList","NativeInt8List._create1","_checkValidIndex","_checkValidRange","Rti._getFutureFromFutureOr","Rti._isUnionOfFunctionType","Rti._getInterfaceTypeArguments","Rti._getBindingArguments","Rti._getFunctionParameters","Rti._getGenericFunctionBounds","Rti._getCanonicalRecipe","findType","instantiatedGenericFunctionType","_instantiate","_Universe._canonicalRecipeOfStar","_Universe._canonicalRecipeOfQuestion","_Universe._canonicalRecipeOfFutureOr","_instantiateArray","_instantiateNamed","_instantiateFunctionParameters","_FunctionParameters.allocate","closureFunctionType","instanceOrFunctionType","instanceType","_isDartObject","_arrayInstanceType","_instanceType","_instanceTypeFromConstructor","_instanceTypeFromConstructorMiss","getTypeFromTypesTable","createRuntimeType","typeLiteral","_installSpecializedIsTest","Rti._getInterfaceName","_generalIsTestImplementation","_isTestViaProperty","_generalAsCheckImplementation","_generalTypeCheckImplementation","checkTypeBound","_Error.compose","_CastError.fromMessage","_CastError.forType","_TypeError.fromMessage","_TypeError.forType","_isTop","_asTop","_isBool","_asBoolNullable","_checkBoolNullable","_asDoubleNullable","_checkDoubleNullable","_isInt","_asIntNullable","_checkIntNullable","_isNum","_asNumNullable","_checkNumNullable","_isString","_asStringNullable","_checkStringNullable","_rtiArrayToString","Rti._getReturnType","_rtiToString","Rti._getGenericFunctionParameterIndex","_unminifyOrTag","_Universe.findRule","_Universe.findErasedType","_Universe.addRules","_Universe.addErasedTypes","_Universe.eval","_Universe.evalInEnvironment","_Universe.bind","_Universe._parseRecipe","_Universe._finishRti","_Universe._lookupTerminalRti","Rti.allocate","_Universe._createTerminalRti","_Universe._lookupUnaryRti","_Universe._createUnaryRti","_Universe._lookupGenericFunctionParameterRti","_Universe._createGenericFunctionParameterRti","_Universe._canonicalRecipeJoin","_Universe._canonicalRecipeJoinNamed","_Universe._lookupInterfaceRti","_Universe._createInterfaceRti","_Universe._lookupBindingRti","_Universe._canonicalRecipeOfBinding","_Universe._createBindingRti","_Universe._lookupFunctionRti","_Universe._canonicalRecipeOfFunction","_Universe._createFunctionRti","_Universe._lookupGenericFunctionRti","_Universe._canonicalRecipeOfGenericFunction","_Universe._createGenericFunctionRti","_Parser.create","_Parser.parse","_Parser.pushStackFrame","_Parser.handleTypeArguments","_Parser.collectArray","_Parser.handleFunctionArguments","_Parser.handleOptionalGroup","_Parser.handleNamedGroup","_Parser.collectNamed","_Parser.handleDigit","_Parser.handleIdentifier","_Universe.evalTypeVariable","_Parser.handleExtendedOperations","_Parser.toType","_Parser.toTypes","_Parser.toTypesNamed","_Parser.indexToType","_isSubtype","Rti._getStarArgument","Rti._getGenericFunctionBase","_isFunctionSubtype","_isInterfaceSubtype","typeEqual","Rti._getBindingBase","typesEqual","namedTypesEqual","isLegacyTopType","isTopType","_Utils.objectAssign","extractKeys","unmangleGlobalNameIfPreservedAnyways","printString","makeDispatchRecord","getNativeInterceptor","JSArray.fixed","JSArray.markFixed","JSArray.markFixedList","JSString._isWhitespace","JSString._skipLeadingWhitespace","JSString._skipTrailingWhitespace","_AsyncRun._initializeScheduleImmediate","_AsyncRun._scheduleImmediateJsOverride","_AsyncRun._scheduleImmediateWithSetImmediate","_AsyncRun._scheduleImmediateWithTimer","Timer._createTimer","_TimerImpl","_TimerImpl.periodic","_makeAsyncAwaitCompleter","_AsyncAwaitCompleter._future","_Future","_asyncStartSync","_asyncAwait","_asyncReturn","_asyncRethrow","_awaitOnObject","_wrapJsFunctionForAsync","Future","Future.microtask","Future.sync","_Future.value","_Future.zoneValue","_nonNullError","Future.error","_Future.immediateError","Future.wait","Future.value","_Future.immediate","Future.forEach","JSArray.iterator","Future._kTrue","Future.doWhile","_completeWithErrorCallback","_Future._chainForeignFuture","_Future._setPendingComplete","_Future._chainCoreFuture","_Future._setChained","_Future._propagateToListeners","_Future._error","_Future._removeListeners","_Future._cloneResult","_Future._setErrorObject","_registerErrorHandler","_microtaskLoop","_startMicrotaskLoop","_scheduleAsyncCallback","_schedulePriorityAsyncCallback","scheduleMicrotask","Stream.fromFuture","_StreamController.stream","Stream.fromIterable","StreamIterator","StreamController","_runGuarded","_AddStreamState.makeErrorHandler","_BufferingStreamSubscription","_BufferingStreamSubscription._zone","_nullDataHandler","_nullErrorHandler","_nullDoneHandler","_runUserCode","_cancelAndError","_cancelAndErrorClosure","_cancelAndValue","Timer","_ZoneSpecification","Zone._enter","_parentDelegate","_rootHandleUncaughtError","_rootRun","_rootRunUnary","_rootRunBinary","_rootRegisterCallback","_rootRegisterUnaryCallback","_rootRegisterBinaryCallback","_rootErrorCallback","_rootScheduleMicrotask","_rootCreateTimer","_rootCreatePeriodicTimer","Timer._createPeriodicTimer","_rootPrint","_printToZone","_rootFork","_CustomZone","runZoned","_runZoned","HashMap","_HashMap._getTableEntry","_HashMap._setTableEntry","_HashMap._newHashTable","JsLinkedHashMap.es6","LinkedHashMap","LinkedHashMap._literal","LinkedHashMap._empty","LinkedHashSet","LinkedHashSet._empty","LinkedHashSet._literal","_LinkedHashSet._newHashTable","_LinkedHashSetIterator","HashMap.from","IterableBase.iterableToShortString","IterableBase.iterableToFullString","_isToStringVisiting","_iterablePartsToStrings","LinkedHashMap.from","LinkedHashSet.from","MapBase.mapToString","ListQueue","_ListQueueIterator","_parseJson","_convertJsonToDartLazy","Utf8Decoder._convertIntercepted","Utf8Decoder._convertInterceptedUint8List","Utf8Decoder._useTextDecoderChecked","Utf8Decoder._useTextDecoderUnchecked","Utf8Decoder._unsafe","Utf8Decoder._makeDecoder","_scanOneByteCharacters","Base64Codec._checkPadding","int.parse","Error._objectToString","List.filled","List.from","List.unmodifiable","String.fromCharCodes","String.fromCharCode","String._stringFromIterable","RegExp","StringBuffer._writeAll","Uri.base","_Uri._uriEncode","JSSyntaxRegExp.hasMatch","StringBuffer.writeCharCode","StackTrace.current","DateTime._fourDigits","DateTime._threeDigits","DateTime._twoDigits","Duration","Error.safeToString","AssertionError","ArgumentError","ArgumentError.value","ArgumentError.notNull","RangeError","RangeError.value","RangeError.range","RangeError.checkValueInInterval","RangeError.checkValidRange","RangeError.checkNotNegative","IndexError","UnsupportedError","UnimplementedError","StateError","ConcurrentModificationError","FormatException","List.generate","Map.castFrom","print","_combineSurrogatePair","Uri.parse","Uri.decodeComponent","Uri._parseIPv4Address","Uri.parseIPv6Address","NativeUint8List","_Uri.notSimple","_Uri","JSString.isNotEmpty","_Uri._defaultPort","_Uri._fail","_Uri.file","_Uri._checkNonWindowsPathReservedCharacters","_Uri._checkWindowsPathReservedCharacters","ListIterable.iterator","_Uri._checkWindowsDriveLetter","_Uri._makeFileUri","_Uri._makeWindowsFileUrl","_Uri._makePort","_Uri._makeHost","_Uri._checkZoneID","_Uri._normalizeZoneID","StringBuffer.write","_Uri._normalizeRegName","_Uri._makeScheme","_Uri._canonicalizeScheme","_Uri._makeUserInfo","_Uri._makePath","JSArray.map","_Uri._normalizePath","_Uri._makeQuery","_Uri._makeFragment","_Uri._normalizeEscape","_Uri._escapeChar","_Uri._normalizeOrSubstring","_Uri._normalize","_Uri._mayContainDotSegments","_Uri._removeDotSegments","JSArray.isNotEmpty","_Uri._normalizeRelativePath","_Uri._escapeScheme","_Uri._toWindowsFilePath","_Uri._hexCharPairToByte","_Uri._uriDecode","JSString.codeUnits","Utf8Codec.decode","_Uri._isAlphabeticCharacter","UriData._writeUri","UriData._validateMimeType","UriData._parse","UriData._uriEncodeBytes","_createTables","_scan","_convertDataTree","promiseToFuture","_Completer.future","Completer","max","pow","_EventStreamSubscription","_wrapZone","SpanScanner","SourceFile.decoded","SourceFile.fromString","RemoteListener.start","SuiteChannelManager","RemoteListener._deserializeSet","RemoteListener._sendLoadException","_MultiChannel.sink","RemoteListener._sendError","StackTraceFormatter.current","Style._getPlatformStyle","Pool","Pool._closeMemo","mapStackTrace","Trace","_prettifyMember","Group","Metadata._parseOnPlatform","Metadata._parseTags","Metadata","Metadata._","Metadata.parse","Metadata.deserialize","Metadata._deserializeTimeout","Engine","FutureGroup","Engine._onTestStartedGroup","StreamGroup.broadcast","StreamController.broadcast","Engine._group","binarySearch","mapMap","mergeMaps","UnionSetController","FileLocation._","_FileSpan","Trace.current","Trace.from","Trace.parse","Trace.parseVM","Trace._parseVM","ListIterable.map","Trace.parseV8","Trace.parseJSCore","WhereIterable.map","JSArray.where","Trace.parseFirefox","Trace.parseFriendly","PackageConfigResolver._normalizeMap","SourceLocation","LiveTestController","errorsDontStopTest","Invoker.current","StringScannerException","PlatformSelector.parse","PlatformSelector._wrapFormatException","SuitePlatform","JSStackTraceMapper.deserialize","JSStackTraceMapper._deserializePackageConfigMap","UnmodifiableSetView","decodeVlq","internalBootstrapBrowserTest","StreamChannelMixin.pipe","GuaranteeChannel.stream","SourceSpanFormatException","expect","_expect","Invoker.closed","Invoker._closable","_Completer.isCompleted","fail","formatFailure","prettyPrint","StringDescription._out","StringDescription.toString","StringBuffer.writeln","method1","method2","main","parseJsonExtended","parseJson","MultiSectionMapping.fromJson","MappingBundle.fromJson","SingleMapping.fromJson","ParsedPath.parse","PathException","SourceSpanWithContext","Declarer","Declarer._","Declarer._timeout","_expandSafe","Highlighter._normalizeNewlines","Highlighter._normalizeTrailingNewline","Highlighter._normalizeEndOfLine","Highlighter._lastLineLength","Chain.capture","Expando","StackZoneSpecification._chains","Chain.current","Chain._currentSpec","StackZoneSpecification.currentChain","StackZoneSpecification._createNode","Chain.forTrace","Chain.parse","Invoker.guard","Suite._filterGroup","Group.root","SuiteConfiguration._list","SuiteConfiguration._map","RemoteException.serialize","_declarer","Declarer.current","test","group","StreamChannelController","_StreamController.sink","Runtime.deserialize","indent","toSentence","pluralize","prefixLines","LiveSuiteController","LiveSuiteController._onCompleteGroup","LiveSuiteController._closeMemo","asUri","ensureTrailingSlash","JSArray.toList","isAlphabetic","isDriveLetter","countCodeUnits","ListMixin.iterator","findLineStart","validateErrorArgs","QueueList","QueueList._nextPowerOf2","wrapMatcher","predicate","equals","escape","_getHexLiteral","JSString.runes","Context","_parseUri","_validateArgList","_StringEqualsMatcher._writeLeading","_StringEqualsMatcher._writeTrailing","_MultiChannel","current","_typeName","_escapeString","Frame.parseVM","Frame.parseV8","Frame.parseFirefox","Frame.parseFriendly","Frame._uriOrPathToUri","Frame._catchFormatException","UnparsedFrame","postMessageChannel","EventStreamProvider.forTarget","OperatingSystem.find","GuaranteeChannel","ClosedException","Interceptor.hashCode","Interceptor.==","Interceptor.toString","Interceptor.runtimeType","JSBool.toString","JSBool.hashCode","JSBool.runtimeType","JSNull.==","JSNull.toString","JSNull.hashCode","JSNull.runtimeType","JavaScriptObject.hashCode","JavaScriptObject.runtimeType","JavaScriptObject.toString","JavaScriptFunction.toString","JSArray.add","JSArray.removeAt","JSArray.insert","JSArray.insertAll","JSArray.removeLast","JSArray.remove","JSArray.addAll","JSArray.forEach","JSArray.join","JSArray.join[function-entry$0]","JSArray.fold","JSArray.firstWhere","JSArray.firstWhere[function-entry$1]","JSArray.elementAt","JSArray.sublist","JSArray.first","JSArray.last","JSArray.single","JSArray.setRange","JSArray.setRange[function-entry$3]","JSArray.fillRange","JSArray.replaceRange","JSArray.contains","JSArray.isEmpty","JSArray.toString","JSArray.toSet","JSArray.hashCode","JSArray.length","JSArray.[]","JSArray.[]=","ArrayIterator.current","ArrayIterator.moveNext","ArrayIterator._current","JSNumber.floor","JSNumber.round","JSNumber.toRadixString","JSNumber.toString","JSNumber.hashCode","JSNumber.%","JSNumber.~/","JSNumber._tdivFast","JSNumber._tdivSlow","JSNumber._shlPositive","JSNumber._shrOtherPositive","JSNumber._shrReceiverPositive","JSNumber._shrBothPositive","JSNumber.runtimeType","JSInt.runtimeType","JSDouble.runtimeType","JSString.codeUnitAt","JSString._codeUnitAt","JSString.allMatches","allMatchesInStringUnchecked","JSString.allMatches[function-entry$1]","JSString.matchAsPrefix","JSString.+","JSString.endsWith","JSString.splitMapJoin","JSString.replaceFirst","JSString.replaceRange","JSString.startsWith","JSString.startsWith[function-entry$1]","JSString.substring","JSString.substring[function-entry$1]","JSString.trim","JSString.*","JSString.padLeft","JSString.padRight","JSString.indexOf","JSString.indexOf[function-entry$1]","JSString.lastIndexOf","JSString.lastIndexOf[function-entry$1]","JSString.contains","JSString.toString","JSString.hashCode","JSString.runtimeType","JSString.length","JSString.[]","_CastIterableBase.iterator","_CastIterableBase.length","_CastIterableBase.isEmpty","_CastIterableBase.first","_CastIterableBase.last","_CastIterableBase.contains","_CastIterableBase.toString","CastIterator.moveNext","CastIterator.current","CastMap.cast","CastMap.containsKey","CastMap.[]","CastMap.remove","CastMap.forEach","CastMap.keys","CastMap.length","CastMap.isEmpty","CastMap.forEach.<anonymous function>","CastMap_forEach_closure","CodeUnits.[]","CodeUnits.length","ListIterable.isEmpty","ListIterable.first","ListIterable.last","ListIterable.contains","ListIterable.join","ListIterable.join[function-entry$0]","ListIterable.fold","ListIterable.toList","ListIterable.toList[function-entry$0]","ListIterable.toSet","SubListIterable._endIndex","SubListIterable._startIndex","SubListIterable.length","SubListIterable.elementAt","SubListIterable.take","ListIterator.current","ListIterator.moveNext","ListIterator._current","MappedIterable.iterator","MappedIterable.length","MappedIterable.isEmpty","MappedIterable.first","MappedIterable.last","MappedIterator.moveNext","MappedIterator.current","MappedIterator._current","MappedListIterable.length","MappedListIterable.elementAt","WhereIterable.iterator","WhereIterator.moveNext","WhereIterator.current","ExpandIterable.iterator","ExpandIterator","ExpandIterator.current","ExpandIterator.moveNext","ExpandIterator._currentExpansion","ExpandIterator._current","SkipWhileIterable.iterator","SkipWhileIterator.moveNext","SkipWhileIterator.current","EmptyIterator.moveNext","EmptyIterator.current","FixedLengthListMixin.length","UnmodifiableListMixin.[]=","UnmodifiableListMixin.length","ReversedListIterable.length","ReversedListIterable.elementAt","Symbol.hashCode","Symbol.toString","Symbol.==","ConstantMap.cast","ConstantMap.isEmpty","ConstantMap.toString","ConstantMap.remove","ConstantMap.map","ConstantMap.map.<anonymous function>","ConstantMap_map_closure","ConstantStringMap.length","ConstantStringMap.containsKey","ConstantStringMap.[]","ConstantStringMap._fetch","ConstantStringMap.forEach","ConstantStringMap.keys","_ConstantMapKeyIterable.iterator","_ConstantMapKeyIterable.length","Instantiation","Instantiation.toString","Primitives.initTicker.<anonymous function>","TypeErrorDecoder.matchTypeError","NullError.toString","JsNoSuchMethodError.toString","UnknownJsTypeError.toString","unwrapException.saveStackTrace","_StackTrace.toString","Closure.toString","StaticClosure.toString","BoundClosure.==","BoundClosure.hashCode","BoundClosure.toString","TypeErrorImplementation.toString","RuntimeError.toString","_AssertionError.toString","JsLinkedHashMap.keys","JsLinkedHashMap.length","JsLinkedHashMap.isEmpty","JsLinkedHashMap.values","JsLinkedHashMap.containsKey","JsLinkedHashMap.internalContainsKey","JsLinkedHashMap.addAll","JsLinkedHashMap.[]","JsLinkedHashMap.internalGet","JsLinkedHashMap.[]=","JsLinkedHashMap.internalSet","JsLinkedHashMap.putIfAbsent","JsLinkedHashMap.remove","JsLinkedHashMap.internalRemove","JsLinkedHashMap.clear","JsLinkedHashMap.forEach","JsLinkedHashMap._addHashTableEntry","JsLinkedHashMap._removeHashTableEntry","JsLinkedHashMap._modified","JsLinkedHashMap._newLinkedCell","JsLinkedHashMap._unlinkCell","JsLinkedHashMap.internalComputeHashCode","JsLinkedHashMap.internalFindBucketIndex","JsLinkedHashMap.toString","JsLinkedHashMap._getTableCell","JsLinkedHashMap._getTableBucket","JsLinkedHashMap._setTableEntry","JsLinkedHashMap._deleteTableEntry","JsLinkedHashMap._containsTableEntry","JsLinkedHashMap._newHashTable","JsLinkedHashMap.values.<anonymous function>","JsLinkedHashMap_values_closure","JsLinkedHashMap.addAll.<anonymous function>","JsLinkedHashMap_addAll_closure","LinkedHashMapKeyIterable.length","LinkedHashMapKeyIterable.isEmpty","LinkedHashMapKeyIterable.iterator","LinkedHashMapKeyIterable.contains","LinkedHashMapKeyIterator","LinkedHashMapKeyIterator.current","LinkedHashMapKeyIterator.moveNext","LinkedHashMapKeyIterator._current","initHooks.<anonymous function>","JSSyntaxRegExp.toString","JSSyntaxRegExp._nativeGlobalVersion","JSSyntaxRegExp._nativeAnchoredVersion","JSSyntaxRegExp.firstMatch","JSSyntaxRegExp.allMatches","JSSyntaxRegExp.allMatches[function-entry$1]","JSSyntaxRegExp._execGlobal","JSSyntaxRegExp._execAnchored","JSSyntaxRegExp.matchAsPrefix","_MatchImplementation.start","_MatchImplementation.end","_MatchImplementation.[]","_AllMatchesIterator.current","_AllMatchesIterator.moveNext","JSSyntaxRegExp.isUnicode","StringMatch.end","StringMatch.[]","_StringAllMatchesIterable.iterator","_StringAllMatchesIterable.first","_StringAllMatchesIterator.moveNext","_StringAllMatchesIterator.current","NativeByteBuffer.runtimeType","NativeByteData.runtimeType","NativeTypedArray.length","NativeTypedArrayOfDouble.[]","NativeTypedArrayOfDouble.[]=","NativeTypedArrayOfInt.[]=","NativeFloat32List.runtimeType","NativeFloat64List.runtimeType","NativeInt16List.runtimeType","NativeInt16List.[]","NativeInt32List.runtimeType","NativeInt32List.[]","NativeInt8List.runtimeType","NativeInt8List.[]","NativeUint16List.runtimeType","NativeUint16List.[]","NativeUint32List.runtimeType","NativeUint32List.[]","NativeUint32List.sublist","NativeUint8ClampedList.runtimeType","NativeUint8ClampedList.length","NativeUint8ClampedList.[]","NativeUint8List.runtimeType","NativeUint8List.length","NativeUint8List.[]","NativeUint8List.sublist","Rti._eval","Rti._bind","_Type.hashCode","_Type.==","_Type.toString","_Error.toString","_TypeError.message","_AsyncRun._initializeScheduleImmediate.internalCallback","_AsyncRun._initializeScheduleImmediate.<anonymous function>","_AsyncRun._scheduleImmediateJsOverride.internalCallback","_AsyncRun._scheduleImmediateWithSetImmediate.internalCallback","_TimerImpl.cancel","_TimerImpl.internalCallback","_TimerImpl.periodic.<anonymous function>","_AsyncAwaitCompleter.complete","_AsyncAwaitCompleter.completeError","_awaitOnObject.<anonymous function>","_wrapJsFunctionForAsync.<anonymous function>","_BroadcastStream.isBroadcast","_BroadcastSubscription._onPause","_BroadcastSubscription._onResume","_BroadcastSubscription._next","_BroadcastSubscription._previous","_BroadcastStreamController._mayAddEvent","_BroadcastStreamController._ensureDoneFuture","_BroadcastStreamController._removeListener","_BroadcastStreamController._subscribe","_DoneStreamSubscription","_BroadcastSubscription","_BroadcastStreamController._recordCancel","_BroadcastStreamController._recordPause","_BroadcastStreamController._recordResume","_BroadcastStreamController._addEventError","_BroadcastStreamController.add","_BroadcastStreamController.addError","_BroadcastStreamController.addError[function-entry$1]","_BroadcastStreamController.close","_BroadcastStreamController._addError","_BroadcastStreamController._close","_BroadcastStreamController._forEachListener","_BroadcastStreamController._callOnCancel","_BroadcastStreamController._firstSubscription","_BroadcastStreamController._lastSubscription","_BroadcastStreamController._addStreamState","_SyncBroadcastStreamController._mayAddEvent","_SyncBroadcastStreamController._addEventError","_SyncBroadcastStreamController._sendData","_SyncBroadcastStreamController._sendError","_SyncBroadcastStreamController._sendDone","_SyncBroadcastStreamController._sendData.<anonymous function>","_SyncBroadcastStreamController__sendData_closure","_SyncBroadcastStreamController._sendError.<anonymous function>","_SyncBroadcastStreamController__sendError_closure","_SyncBroadcastStreamController._sendDone.<anonymous function>","_SyncBroadcastStreamController__sendDone_closure","_AsyncBroadcastStreamController._sendData","_AsyncBroadcastStreamController._sendError","_AsyncBroadcastStreamController._sendDone","Future.<anonymous function>","Future.microtask.<anonymous function>","Future.wait.handleError","Future.wait.<anonymous function>","Future_wait_closure","Future.forEach.<anonymous function>","Future.doWhile.<anonymous function>","_asyncCompleteWithErrorCallback","TimeoutException.toString","_Completer.completeError","_Completer.completeError[function-entry$1]","_AsyncCompleter.complete","_AsyncCompleter.complete[function-entry$0]","_AsyncCompleter._completeError","_SyncCompleter.complete","_SyncCompleter.complete[function-entry$0]","_SyncCompleter._completeError","_FutureListener.matchesErrorTest","_FutureListener.handleError","_FutureListener.hasErrorCallback","_Future.then","_Future.then[function-entry$1]","_Future._thenAwait","_Future.catchError","_Future.whenComplete","_Future._addListener","_Future._prependListeners","_Future._reverseListeners","_Future._complete","_Future._setValue","_Future._completeWithValue","_Future._completeError","_Future._setError","_Future._completeError[function-entry$1]","_Future._asyncComplete","_Future._chainFuture","_Future._asyncCompleteError","_Future._addListener.<anonymous function>","_Future._prependListeners.<anonymous function>","_Future._chainForeignFuture.<anonymous function>","_Future._clearPendingComplete","_Future._chainForeignFuture[function-entry$1].<anonymous function>","_Future._asyncComplete.<anonymous function>","_Future._chainFuture.<anonymous function>","_Future._asyncCompleteError.<anonymous function>","_Future._propagateToListeners.handleWhenCompleteCallback","_FutureListener.handleWhenComplete","_Future._propagateToListeners.handleWhenCompleteCallback.<anonymous function>","_Future._propagateToListeners.handleValueCallback","_FutureListener.handleValue","_FutureListener._onValue","_Future._propagateToListeners.handleError","Stream.isBroadcast","Stream.pipe","Stream.length","Stream.first","Stream.last","Stream.firstWhere","Stream.fromFuture.<anonymous function>","Stream_Stream$fromFuture_closure","Stream.fromIterable.<anonymous function>","_IterablePendingEvents","Stream_Stream$fromIterable_closure","Stream.pipe.<anonymous function>","Stream.length.<anonymous function>","Stream_length_closure","Stream.first.<anonymous function>","Stream_first_closure","Stream.last.<anonymous function>","Stream_last_closure","Stream.firstWhere.<anonymous function>","Stream_firstWhere_closure","Stream.firstWhere.<anonymous function>.<anonymous function>","_StreamController._pendingEvents","_StreamController._ensurePendingEvents","_StreamController._subscription","_StreamController._badEventState","_StreamController.addStream","_AddStreamState","_StreamControllerAddStreamState","_StreamController.isPaused","_StreamController._ensureDoneFuture","_StreamController.add","_StreamController.addError","_StreamController.addError[function-entry$1]","_StreamController.close","_StreamController._closeUnchecked","_StreamController._add","_StreamController._addError","_StreamController._close","_StreamController._subscribe","_ControllerSubscription","_StreamController._recordCancel","_StreamController._recordPause","_StreamController._recordResume","_StreamController._subscribe.<anonymous function>","_StreamController._recordCancel.complete","_SyncStreamControllerDispatch._sendData","_SyncStreamControllerDispatch._sendError","_SyncStreamControllerDispatch._sendDone","_AsyncStreamControllerDispatch._sendData","_AsyncStreamControllerDispatch._sendError","_AsyncStreamControllerDispatch._sendDone","_ControllerStream._createSubscription","_ControllerStream.hashCode","_ControllerStream.==","_ControllerSubscription._onCancel","_ControllerSubscription._onPause","_ControllerSubscription._onResume","_StreamSinkWrapper.add","_AddStreamState.cancel","_AddStreamState.makeErrorHandler.<anonymous function>","_AddStreamState.cancel.<anonymous function>","_BufferingStreamSubscription._setPendingEvents","_BufferingStreamSubscription.onData","_BufferingStreamSubscription.onError","_BufferingStreamSubscription.onDone","_BufferingStreamSubscription.pause","_BufferingStreamSubscription.pause[function-entry$0]","_BufferingStreamSubscription.resume","_BufferingStreamSubscription.cancel","_BufferingStreamSubscription._mayResumeInput","_BufferingStreamSubscription.isPaused","_BufferingStreamSubscription._cancel","_BufferingStreamSubscription._add","_BufferingStreamSubscription._addError","_BufferingStreamSubscription._close","_BufferingStreamSubscription._onPause","_BufferingStreamSubscription._onResume","_BufferingStreamSubscription._onCancel","_BufferingStreamSubscription._addPending","_BufferingStreamSubscription._sendData","_BufferingStreamSubscription._sendError","_BufferingStreamSubscription._sendDone","_BufferingStreamSubscription._guardCallback","_BufferingStreamSubscription._checkState","_BufferingStreamSubscription._onData","_BufferingStreamSubscription._onDone","_BufferingStreamSubscription._pending","_BufferingStreamSubscription._sendError.sendError","_BufferingStreamSubscription._sendDone.sendDone","_StreamImpl.listen","_StreamImpl.listen[function-entry$1$onDone]","_StreamImpl.listen[function-entry$1$onDone$onError]","_StreamImpl.listen[function-entry$1]","_StreamImpl._createSubscription","_GeneratedStreamImpl._createSubscription","_IterablePendingEvents.isEmpty","_IterablePendingEvents.handleNext","_IterablePendingEvents._iterator","_DelayedEvent.next","_DelayedData.perform","_DelayedError.perform","_DelayedDone.perform","_DelayedDone.next","_PendingEvents.schedule","_PendingEvents.schedule.<anonymous function>","_StreamImplEvents.isEmpty","_StreamImplEvents.add","_StreamImplEvents.handleNext","_DoneStreamSubscription.isPaused","_DoneStreamSubscription._schedule","_DoneStreamSubscription.onData","_DoneStreamSubscription.onError","_DoneStreamSubscription.onDone","_DoneStreamSubscription.pause","_DoneStreamSubscription.pause[function-entry$0]","_DoneStreamSubscription.resume","_DoneStreamSubscription.cancel","_DoneStreamSubscription._sendDone","_DoneStreamSubscription._onDone","_EmptyStream.isBroadcast","_EmptyStream.listen","_EmptyStream.listen[function-entry$1$onDone$onError]","_EmptyStream.listen[function-entry$1]","_cancelAndError.<anonymous function>","_cancelAndErrorClosure.<anonymous function>","_cancelAndValue.<anonymous function>","AsyncError.toString","_ZoneDelegate.handleUncaughtError","_ZoneDelegate.registerCallback","_ZoneDelegate.registerUnaryCallback","_ZoneDelegate.registerBinaryCallback","_ZoneDelegate.errorCallback","_CustomZone._delegate","_CustomZone.errorZone","_CustomZone.runGuarded","_CustomZone.runUnaryGuarded","_CustomZone.runBinaryGuarded","_CustomZone.bindCallback","_CustomZone.bindUnaryCallback","_CustomZone.bindCallbackGuarded","_CustomZone.bindUnaryCallbackGuarded","_CustomZone.[]","_CustomZone.handleUncaughtError","_CustomZone.fork","_CustomZone.run","_CustomZone.runUnary","_CustomZone.runBinary","_CustomZone.registerCallback","_CustomZone.registerUnaryCallback","_CustomZone.registerBinaryCallback","_CustomZone.errorCallback","_CustomZone.scheduleMicrotask","_CustomZone.createTimer","_CustomZone.print","_CustomZone._run","_CustomZone._runUnary","_CustomZone._runBinary","_CustomZone._registerCallback","_CustomZone._registerUnaryCallback","_CustomZone._registerBinaryCallback","_CustomZone._errorCallback","_CustomZone._scheduleMicrotask","_CustomZone._createTimer","_CustomZone._createPeriodicTimer","_CustomZone._print","_CustomZone._fork","_CustomZone._handleUncaughtError","_CustomZone.bindCallback.<anonymous function>","_CustomZone_bindCallback_closure","_CustomZone.bindUnaryCallback.<anonymous function>","_CustomZone_bindUnaryCallback_closure","_CustomZone.bindCallbackGuarded.<anonymous function>","_CustomZone.bindUnaryCallbackGuarded.<anonymous function>","_CustomZone_bindUnaryCallbackGuarded_closure","_rootHandleUncaughtError.<anonymous function>","_RootZone._map","_RootZone._run","_RootZone._runUnary","_RootZone._runBinary","_RootZone._registerCallback","_RootZone._registerUnaryCallback","_RootZone._registerBinaryCallback","_RootZone._errorCallback","_RootZone._scheduleMicrotask","_RootZone._createTimer","_RootZone._createPeriodicTimer","_RootZone._print","_RootZone._fork","_RootZone._handleUncaughtError","_RootZone.parent","_RootZone._delegate","_RootZone.errorZone","_RootZone.runGuarded","_RootZone.runUnaryGuarded","_RootZone.runBinaryGuarded","_RootZone.bindCallback","_RootZone.bindCallbackGuarded","_RootZone.bindUnaryCallbackGuarded","_RootZone.[]","_RootZone.handleUncaughtError","_RootZone.fork","_RootZone.run","_RootZone.runUnary","_RootZone.runBinary","_RootZone.registerCallback","_RootZone.registerUnaryCallback","_RootZone.registerBinaryCallback","_RootZone.errorCallback","_RootZone.scheduleMicrotask","_RootZone.createTimer","_RootZone.print","_RootZone.bindCallback.<anonymous function>","_RootZone_bindCallback_closure","_RootZone.bindCallbackGuarded.<anonymous function>","_RootZone.bindUnaryCallbackGuarded.<anonymous function>","_RootZone_bindUnaryCallbackGuarded_closure","runZoned.<anonymous function>","_HashMap.keys","_HashMap.length","_HashMap.isEmpty","_HashMap.containsKey","_HashMap._containsKey","_HashMap.[]","_HashMap._get","_HashMap.[]=","_HashMap._set","_HashMap.remove","_HashMap._remove","_HashMap.forEach","_HashMap._computeKeys","_HashMap._addHashTableEntry","_HashMap._computeHashCode","_HashMap._getBucket","_HashMap._findBucketIndex","_IdentityHashMap._computeHashCode","_IdentityHashMap._findBucketIndex","_HashMapKeyIterable.length","_HashMapKeyIterable.isEmpty","_HashMapKeyIterable.iterator","_HashMapKeyIterable.contains","_HashMapKeyIterator.current","_HashMapKeyIterator.moveNext","_HashMapKeyIterator._current","_LinkedHashSet._newSet","_LinkedHashSet.iterator","_LinkedHashSet.length","_LinkedHashSet.isEmpty","_LinkedHashSet.contains","_LinkedHashSet._contains","_LinkedHashSet.first","_LinkedHashSet.last","_LinkedHashSet.add","_LinkedHashSet._add","_LinkedHashSet.remove","_LinkedHashSet._remove","_LinkedHashSet._addHashTableEntry","_LinkedHashSet._removeHashTableEntry","_LinkedHashSet._modified","_LinkedHashSet._newLinkedCell","_LinkedHashSet._unlinkCell","_LinkedHashSet._computeHashCode","_LinkedHashSet._findBucketIndex","_LinkedHashSetIterator.current","_LinkedHashSetIterator.moveNext","_LinkedHashSetIterator._current","UnmodifiableListView.length","UnmodifiableListView.[]","HashMap.from.<anonymous function>","LinkedHashMap.from.<anonymous function>","ListMixin.elementAt","ListMixin.isEmpty","ListMixin.first","ListMixin.last","ListMixin.map","ListMixin.toList","ListMixin.toList[function-entry$0]","ListMixin.toSet","ListMixin.remove","ListMixin._closeGap","ListMixin.fillRange","ListMixin.toString","MapBase.mapToString.<anonymous function>","MapMixin.cast","MapMixin.forEach","MapMixin.map","MapMixin.containsKey","MapMixin.length","MapMixin.isEmpty","MapMixin.toString","_UnmodifiableMapMixin.remove","MapView.cast","MapView.[]","MapView.containsKey","MapView.forEach","MapView.isEmpty","MapView.length","MapView.keys","MapView.remove","MapView.toString","MapView.map","UnmodifiableMapView.cast","ListQueue.iterator","ListQueue.isEmpty","ListQueue.length","ListQueue.first","ListQueue.last","ListQueue.elementAt","ListQueue.clear","ListQueue.toString","ListQueue.removeFirst","ListQueue._add","ListQueue._table","_ListQueueIterator.current","_ListQueueIterator.moveNext","_ListQueueIterator._current","SetMixin.isEmpty","SetMixin.map","SetMixin.toString","SetMixin.every","SetMixin.first","SetMixin.last","_SetBase.toSet","_SetBase.isEmpty","_SetBase.addAll","_SetBase.union","_SetBase.toList","_SetBase.toList[function-entry$0]","_SetBase.map","_SetBase.toString","_SetBase.where","_SetBase.fold","_SetBase.every","_SetBase.any","_SetBase.first","_SetBase.last","_JsonMap.[]","_JsonMap.length","_JsonMap.isEmpty","_JsonMap.keys","_JsonMap.containsKey","_JsonMap.remove","_JsonMap.forEach","_JsonMap._upgradedMap","_JsonMap._computeKeys","_JsonMap._upgrade","_JsonMap._process","_JsonMapKeyIterable.length","_JsonMapKeyIterable.elementAt","_JsonMapKeyIterable.iterator","_JsonMapKeyIterable.contains","AsciiCodec.encode","_UnicodeSubsetEncoder.convert","Base64Codec.normalize","JsonCodec.decode","JsonCodec.decoder","Utf8Codec.encoder","Utf8Encoder.convert","_Utf8Encoder._writeSurrogate","_Utf8Encoder._fillBuffer","Utf8Decoder.convert","_Utf8Decoder.flush","_Utf8Decoder.convert","DateTime.==","DateTime.hashCode","DateTime.toString","Duration.==","Duration.hashCode","Duration.toString","Duration.unary-","Duration.toString.sixDigits","Duration.toString.twoDigits","AssertionError.toString","NullThrownError.toString","ArgumentError._errorName","ArgumentError._errorExplanation","ArgumentError.toString","RangeError._errorName","RangeError._errorExplanation","IndexError._errorName","IndexError._errorExplanation","UnsupportedError.toString","UnimplementedError.toString","StateError.toString","ConcurrentModificationError.toString","OutOfMemoryError.toString","StackOverflowError.toString","CyclicInitializationError.toString","_Exception.toString","FormatException.toString","Expando.[]","Expando.[]=","Expando._setOnObject","Expando.toString","Iterable.map","Iterable.where","Iterable.contains","Iterable.join","Iterable.join[function-entry$0]","Iterable.toList","Iterable.toList[function-entry$0]","Iterable.toSet","Iterable.length","Iterable.isEmpty","Iterable.skipWhile","Iterable.first","Iterable.last","Iterable.elementAt","Iterable.toString","MapEntry.toString","Null.hashCode","Null.toString","Object.hashCode","Object.==","Object.toString","Object.runtimeType","_StringStackTrace.toString","Stopwatch.elapsedMicroseconds","Stopwatch.elapsedTicks","Runes.iterator","Runes.last","RuneIterator.current","RuneIterator.moveNext","StringBuffer.length","StringBuffer.toString","Uri._parseIPv4Address.error","Uri.parseIPv6Address.error","Uri.parseIPv6Address[function-entry$1].error","Uri.parseIPv6Address.parseHex","_Uri.userInfo","_Uri.host","_Uri.port","_Uri.query","_Uri.fragment","_Uri.replace","_Uri.replace[function-entry$0$path]","_Uri.replace[function-entry$0$pathSegments]","_Uri.pathSegments","_Uri._mergePaths","_Uri.resolve","_Uri.resolveUri","_Uri.hasEmptyPath","_Uri.hasAuthority","_Uri.hasPort","_Uri.hasQuery","_Uri.hasFragment","_Uri.hasAbsolutePath","_Uri.toFilePath","_Uri._toFilePath","_Uri.toString","_Uri._initializeText","_Uri._writeAuthority","_Uri.==","_Uri.hashCode","_Uri._pathSegments","_Uri.notSimple.<anonymous function>","_Uri._checkNonWindowsPathReservedCharacters.<anonymous function>","_Uri._makePath.<anonymous function>","UriData.uri","UriData.toString","_createTables.<anonymous function>","_createTables.build","_createTables.setChars","_createTables.setRange","_SimpleUri._isFile","_SimpleUri.hasAuthority","_SimpleUri.hasPort","_SimpleUri.hasQuery","_SimpleUri.hasFragment","_SimpleUri._isHttp","_SimpleUri._isHttps","_SimpleUri.hasAbsolutePath","_SimpleUri.scheme","_SimpleUri.userInfo","_SimpleUri.host","_SimpleUri.port","_SimpleUri.path","_SimpleUri.query","_SimpleUri.fragment","_SimpleUri.pathSegments","_SimpleUri._isPort","_SimpleUri.removeFragment","_SimpleUri.replace","_SimpleUri.replace[function-entry$0$path]","_SimpleUri.replace[function-entry$0$pathSegments]","_SimpleUri.resolve","_SimpleUri.resolveUri","_SimpleUri._simpleMerge","_SimpleUri.toFilePath","_SimpleUri._toFilePath","_SimpleUri.hashCode","_SimpleUri.==","_SimpleUri._toNonSimple","_SimpleUri.toString","DomException.toString","EventTarget.addEventListener","EventTarget._addEventListener","EventTarget._removeEventListener","Location.origin","Location.toString","MessagePort.addEventListener","MessagePort.postMessage","convertDartToNative_PrepareForStructuredClone","_EventStream.isBroadcast","_EventStream.listen","_EventStream.listen[function-entry$1$onDone$onError]","_EventStream.listen[function-entry$1]","_EventStreamSubscription.cancel","_EventStreamSubscription.pause","_EventStreamSubscription.pause[function-entry$0]","_EventStreamSubscription.resume","_EventStreamSubscription._tryResume","_EventStreamSubscription._unlisten","_EventStreamSubscription._onData","_EventStreamSubscription.<anonymous function>","_StructuredClone.findSlot","_StructuredClone.walk","convertDartToNative_DateTime","_StructuredClone.copyList","_StructuredClone.walk.<anonymous function>","_AcceptStructuredClone.findSlot","_AcceptStructuredClone.walk","DateTime._withValue","convertNativeToDart_DateTime","_AcceptStructuredClone.convertNativeToDart_AcceptStructuredClone","_AcceptStructuredClone.walk.<anonymous function>","_StructuredCloneDart2Js.forEachObjectKey","_AcceptStructuredCloneDart2Js.forEachJsField","_convertDataTree._convert","promiseToFuture.<anonymous function>","AsyncMemoizer.runOnce","AsyncMemoizer.hasRun","DelegatingStreamSubscription.onData","DelegatingStreamSubscription.onError","DelegatingStreamSubscription.onDone","DelegatingStreamSubscription.pause","DelegatingStreamSubscription.pause[function-entry$0]","DelegatingStreamSubscription.resume","DelegatingStreamSubscription.cancel","FutureGroup.add","FutureGroup.close","FutureGroup.add.<anonymous function>","FutureGroup_add_closure","NullStreamSink.add","NullStreamSink.addStream","NullStreamSink._checkEventAllowed","NullStreamSink.close","NullStreamSink.addStream.<anonymous function>","ErrorResult.complete","ErrorResult.addTo","ErrorResult.hashCode","ErrorResult.==","ValueResult.complete","ValueResult.addTo","ValueResult.hashCode","ValueResult.==","StreamCompleter.setSourceStream","_CompleterStream.listen","_CompleterStream.listen[function-entry$1$onDone$onError]","_CompleterStream.listen[function-entry$1]","_CompleterStream._linkStreamToController","_CompleterStream._createController","_CompleterStream._controller","_CompleterStream._sourceStream","StreamGroup.add","StreamGroup._onListen","StreamGroup._onCancelBroadcast","StreamGroup._listenToStream","StreamGroup.close","StreamGroup._controller","StreamGroup.add.<anonymous function>","StreamGroup_add_closure","StreamGroup._onListen.<anonymous function>","StreamGroup__onListen_closure","StreamGroup._onCancelBroadcast.<anonymous function>","StreamGroup__onCancelBroadcast_closure","StreamGroup._listenToStream.<anonymous function>","_StreamGroupState.toString","StreamQueue.next","StreamQueue._updateRequests","StreamQueue._extractStream","SubscriptionStream","StreamQueue._ensureListening","StreamQueue._addResult","StreamQueue._failClosed","StreamQueue._addRequest","StreamQueue._subscription","StreamQueue._ensureListening.<anonymous function>","StreamQueue__ensureListening_closure","Result.error","_NextRequest.update","ListMixin.isNotEmpty","_RestRequest.update","StreamCompleter.setEmpty","_CompleterStream._setEmpty","_CompleterSink._canSendDirectly","_CompleterSink.done","Completer.sync","_CompleterSink.addStream","_CompleterSink.close","_CompleterSink._ensureController","_CompleterSink._setDestinationSink","_CompleterSink._controller","_CompleterSink._destinationSink","_CompleterSink._setDestinationSink.<anonymous function>","SubscriptionStream.listen","SubscriptionStream.listen[function-entry$1$onDone$onError]","SubscriptionStream.listen[function-entry$1]","SubscriptionStream._source","_CancelOnErrorSubscriptionWrapper.onError","_CancelOnErrorSubscriptionWrapper.onError.<anonymous function>","_CancelOnErrorSubscriptionWrapper.onError.<anonymous function>.<anonymous function>","All.evaluate","All.intersection","All.validate","All.toString","VariableNode.accept","VariableNode.toString","VariableNode.==","VariableNode.hashCode","NotNode.accept","NotNode.toString","NotNode.==","NotNode.hashCode","OrNode.span","OrNode.accept","OrNode.toString","OrNode.==","OrNode.hashCode","AndNode.span","AndNode.accept","AndNode.toString","AndNode.==","AndNode.hashCode","ConditionalNode.span","ConditionalNode.accept","ConditionalNode.toString","ConditionalNode.==","ConditionalNode.hashCode","Evaluator.visitVariable","Evaluator.visitNot","Evaluator.visitOr","Evaluator.visitAnd","Evaluator.visitConditional","BooleanSelectorImpl.evaluate","BooleanSelectorImpl.intersection","BooleanSelectorImpl.validate","BooleanSelectorImpl.toString","BooleanSelectorImpl.==","BooleanSelectorImpl.hashCode","IntersectionSelector.evaluate","IntersectionSelector.intersection","IntersectionSelector.validate","IntersectionSelector.toString","IntersectionSelector.==","IntersectionSelector.hashCode","None.evaluate","None.intersection","None.validate","None.toString","Parser.parse","Parser._conditional","Parser._or","Parser._and","Parser._simpleExpression","Scanner.peek","Scanner.next","Scanner.scan","Scanner._getNext","StringScanner.isDone","SpanScanner.state","Scanner._scanOr","Scanner._scanAnd","Scanner._scanIdentifier","Scanner._scanOperator","StringScanner.readChar","Scanner._consumeWhitespace","Scanner._multiLineComment","IdentifierToken.toString","TokenType.toString","Validator.visitVariable","RecursiveVisitor.visitNot","RecursiveVisitor.visitOr","RecursiveVisitor.visitAnd","RecursiveVisitor.visitConditional","EmptyUnmodifiableSet.toSet","EmptyUnmodifiableSet.iterator","EmptyUnmodifiableSet.length","EmptyUnmodifiableSet.contains","mapMap.<anonymous function>","mapMap_closure","mergeMaps.<anonymous function>","mergeMaps_closure","QueueList.toString","QueueList.removeFirst","QueueList.length","QueueList.[]","QueueList.[]=","QueueList._add","QueueList._writeToList","QueueList._preGrow","QueueList._table","UnionSet.length","UnionSet.iterator","UnionSet._iterable","_SetBase.expand","UnionSet.toSet","UnionSet.length.<anonymous function>","UnionSet_length_closure","UnionSet._iterable.<anonymous function>","UnionSet__iterable_closure","UnionSetController._set","_DelegatingIterableBase.contains","_DelegatingIterableBase.every","_DelegatingIterableBase.first","_DelegatingIterableBase.isEmpty","_DelegatingIterableBase.iterator","_DelegatingIterableBase.last","_DelegatingIterableBase.length","_DelegatingIterableBase.map","_DelegatingIterableBase.toList","_DelegatingIterableBase.toList[function-entry$0]","_DelegatingIterableBase.toSet","_DelegatingIterableBase.where","_DelegatingIterableBase.toString","DelegatingSet.union","DelegatingSet.toSet","_IsTrue.matches","_IsTrue.describe","_Predicate.typedMatches","_Predicate.describe","StringDescription.length","StringDescription.addDescriptionOf","_StringEqualsMatcher.typedMatches","_StringEqualsMatcher.describe","_StringEqualsMatcher.describeTypedMismatch","_DeepMatcher._compareIterables","_DeepMatcher._compareSets","_DeepMatcher._recursiveMatch","_DeepMatcher._match","_DeepMatcher.matches","_DeepMatcher.describe","_DeepMatcher.describeMismatch","_DeepMatcher._compareSets.<anonymous function>","FeatureMatcher.matches","FeatureMatcher.describeMismatch","FeatureMatcher.describeTypedMismatch","Matcher.describeMismatch","prettyPrint._prettyPrint","prettyPrint._prettyPrint.pp","prettyPrint._prettyPrint.<anonymous function>","TypeMatcher.describe","_stripDynamic","TypeMatcher.matches","wrapMatcher.<anonymous function>","escape.<anonymous function>","PackageConfigResolver._normalizeMap.<anonymous function>","Context.absolute","Context.absolute[function-entry$1]","Context.join","Context.join[function-entry$2]","Context.joinAll","Context.split","Context.normalize","Context._needsNormalization","Context.relative","Context.isRelative","Context.relative[function-entry$1]","Context._isWithinOrEquals","Context._isWithinOrEqualsFast","Context._pathDirection","Context.toUri","Context.prettyUri","Context.join.<anonymous function>","Context.joinAll.<anonymous function>","Context.split.<anonymous function>","_validateArgList.<anonymous function>","_PathDirection.toString","_PathRelation.toString","InternalStyle.getRoot","InternalStyle.relativePathToUri","InternalStyle.codeUnitsEqual","InternalStyle.pathsEqual","ParsedPath.hasTrailingSeparator","ParsedPath.removeTrailingSeparators","ParsedPath.normalize","ParsedPath.toString","ParsedPath.parts","ParsedPath.separators","ParsedPath.normalize.<anonymous function>","PathException.toString","Style.toString","PosixStyle.containsSeparator","PosixStyle.isSeparator","PosixStyle.needsSeparator","PosixStyle.rootLength","PosixStyle.rootLength[function-entry$1]","PosixStyle.isRootRelative","PosixStyle.pathFromUri","PosixStyle.absolutePathToUri","UrlStyle.containsSeparator","UrlStyle.isSeparator","UrlStyle.needsSeparator","UrlStyle.rootLength","UrlStyle.rootLength[function-entry$1]","UrlStyle.isRootRelative","UrlStyle.pathFromUri","UrlStyle.relativePathToUri","UrlStyle.absolutePathToUri","WindowsStyle.containsSeparator","WindowsStyle.isSeparator","WindowsStyle.needsSeparator","WindowsStyle.rootLength","WindowsStyle.rootLength[function-entry$1]","WindowsStyle.isRootRelative","WindowsStyle.pathFromUri","WindowsStyle.absolutePathToUri","WindowsStyle.codeUnitsEqual","WindowsStyle.pathsEqual","WindowsStyle.absolutePathToUri.<anonymous function>","Pool.request","Pool.isClosed","Pool.withResource","Pool.close","Pool._onResourceReleaseAllowed","Pool._runOnRelease","Pool._resetTimer","Pool.close.<anonymous function>","Pool._onResourceReleaseAllowed.<anonymous function>","Pool._runOnRelease.<anonymous function>","PoolResource.release","Pool._onResourceReleased","mapStackTrace.<anonymous function>","_prettifyMember.<anonymous function>","MultiSectionMapping._indexFor","MultiSectionMapping.spanFor","MultiSectionMapping.spanFor[function-entry$2$uri]","MultiSectionMapping.spanFor[function-entry$2$files]","MultiSectionMapping.toString","MappingBundle.toString","MappingBundle.spanFor","SourceMapSpan","MappingBundle.spanFor[function-entry$2$uri]","SingleMapping._segmentError","SingleMapping._findLine","SingleMapping._findColumn","SingleMapping.spanFor","SourceMapSpan.identifier","SingleMapping.spanFor[function-entry$2$uri]","SingleMapping.spanFor[function-entry$2$files]","SingleMapping.toString","SingleMapping.fromJson.<anonymous function>","SingleMapping._findLine.<anonymous function>","SingleMapping._findColumn.<anonymous function>","TargetLineEntry.toString","TargetEntry.toString","_MappingTokenizer.moveNext","_MappingTokenizer.current","_MappingTokenizer.hasTokens","_MappingTokenizer.nextKind","_MappingTokenizer.toString","_digits.<anonymous function>","SourceFile.length","SourceFile.lines","SourceFile.span","SourceFile.getLine","SourceFile._isNearCachedLine","SourceFile._binarySearch","SourceFile.getColumn","SourceFile.getOffset","SourceFile.getOffset[function-entry$1]","FileLocation.line","FileLocation.sourceUrl","FileLocation.column","_FileSpan.start","_FileSpan.sourceUrl","_FileSpan.length","_FileSpan.end","_FileSpan.text","_FileSpan.context","_FileSpan.==","_FileSpan.hashCode","_FileSpan.expand","Highlighter.highlight","downEnd","upEnd","Highlighter._writeFirstLine","Highlighter._writeIntermediateLines","Highlighter._writeLastLine","Highlighter._writeTrailingLines","Highlighter._writeText","Highlighter._writeSidebar","Highlighter._writeSidebar[function-entry$0$end]","Highlighter._writeSidebar[function-entry$0$line]","Highlighter._writeSidebar[function-entry$0]","Highlighter._countTabs","Highlighter._isOnlyWhitespace","Highlighter._colorize","Highlighter._colorize[function-entry$1]","Highlighter._writeFirstLine.<anonymous function>","glyphOrAscii","topLeftCorner","horizontalLine","Highlighter._writeIntermediateLines.<anonymous function>","verticalLine","Highlighter._writeLastLine.<anonymous function>","bottomLeftCorner","Highlighter._writeSidebar.<anonymous function>","SourceLocation.distance","SourceLocation.==","SourceLocation.hashCode","SourceLocation.toString","SourceLocationMixin.distance","SourceLocationMixin.==","SourceLocationMixin.hashCode","SourceLocationMixin.toString","SourceLocationMixin.toolString","SourceSpanBase","SourceSpanException.message","SourceSpanException.toString","SourceSpanException.toString[function-entry$0]","SourceSpanMixin.sourceUrl","SourceSpanMixin.length","SourceSpanMixin.message","SourceSpanMixin.message[function-entry$1]","SourceSpanMixin.highlight","Highlighter","Highlighter._buffer","SourceSpanMixin.==","SourceSpanMixin.hashCode","SourceSpanMixin.toString","SourceSpanWithContext.context","Chain.foldFrames","Chain.toTrace","JSArray.expand","Chain.toString","Chain.capture.<anonymous function>","Chain_capture_closure","Chain.current.<anonymous function>","Chain.forTrace.<anonymous function>","Chain.parse.<anonymous function>","Chain.foldFrames.<anonymous function>","Chain.toTrace.<anonymous function>","Chain.toString.<anonymous function>","Chain.toString.<anonymous function>.<anonymous function>","Frame.isCore","Frame.library","Frame.package","Frame.location","Frame.toString","Frame.parseVM.<anonymous function>","Frame.parseV8.<anonymous function>","Frame.parseV8.<anonymous function>.parseLocation","Frame.parseFirefox.<anonymous function>","Frame.parseFriendly.<anonymous function>","UriData.fromString","Uri.dataFromString","fromUri","LazyChain._chain","LazyChain.traces","LazyChain.foldFrames","LazyChain.toTrace","LazyChain.toString","LazyChain._inner","LazyChain.foldFrames.<anonymous function>","LazyChain.toTrace.<anonymous function>","LazyTrace._trace","LazyTrace.frames","LazyTrace.original","LazyTrace.foldFrames","LazyTrace.toString","LazyTrace._inner","LazyTrace.foldFrames.<anonymous function>","StackZoneSpecification.chainFor","StackZoneSpecification._registerCallback","StackZoneSpecification._disabled","StackZoneSpecification._registerCallback[function-entry$4]","StackZoneSpecification._registerUnaryCallback","StackZoneSpecification._registerUnaryCallback[function-entry$4]","StackZoneSpecification._registerBinaryCallback","StackZoneSpecification._registerBinaryCallback[function-entry$4]","StackZoneSpecification._errorCallback","StackZoneSpecification._run","StackZoneSpecification._currentTrace","StackZoneSpecification._trimVMChain","StackZoneSpecification._currentNode","StackZoneSpecification.chainFor.<anonymous function>","StackZoneSpecification._registerCallback.<anonymous function>","StackZoneSpecification__registerCallback_closure","StackZoneSpecification._registerUnaryCallback.<anonymous function>","StackZoneSpecification__registerUnaryCallback_closure","StackZoneSpecification._registerUnaryCallback.<anonymous function>.<anonymous function>","StackZoneSpecification__registerUnaryCallback__closure","StackZoneSpecification._registerBinaryCallback.<anonymous function>","StackZoneSpecification__registerBinaryCallback_closure","StackZoneSpecification._registerBinaryCallback.<anonymous function>.<anonymous function>","StackZoneSpecification__registerBinaryCallback__closure","StackZoneSpecification._currentTrace.<anonymous function>","_Node.toChain","Trace.foldFrames","JSArray.reversed","Trace.toString","Trace.current.<anonymous function>","Trace.from.<anonymous function>","Trace._parseVM.<anonymous function>","Trace.parseV8.<anonymous function>","Trace.parseJSCore.<anonymous function>","Trace.parseFirefox.<anonymous function>","Trace.parseFriendly.<anonymous function>","Trace.foldFrames.<anonymous function>","Trace.toString.<anonymous function>","UnparsedFrame.toString","GuaranteeChannel.sink","GuaranteeChannel._onSinkDisconnected","GuaranteeChannel._sink","GuaranteeChannel._streamController","GuaranteeChannel._subscription","GuaranteeChannel.<anonymous function>","GuaranteeChannel.<anonymous function>.<anonymous function>","_GuaranteeSink.done","_GuaranteeSink.add","_GuaranteeSink.addError","_GuaranteeSink.addError[function-entry$1]","_GuaranteeSink._addError","_GuaranteeSink._addError[function-entry$1]","_GuaranteeSink.addStream","_GuaranteeSink.close","_GuaranteeSink._onStreamDisconnected","_GuaranteeSink._addStreamSubscription","_GuaranteeSink._addError.<anonymous function>","_GuaranteeSink.addStream.<anonymous function>","_MultiChannel.virtualChannel","_MultiChannel.virtualChannel[function-entry$0]","_MultiChannel._closeChannel","_MultiChannel._closeInnerChannel","_MultiChannel.<anonymous function>","_MultiChannel_closure","_MultiChannel.<anonymous function>.<anonymous function>","_MultiChannel__closure","_MultiChannel.virtualChannel.<anonymous function>","_MultiChannel_virtualChannel_closure","StreamChannelCompleter._channel","StreamChannelController.local","StreamChannelController._local","StreamChannelController._foreign","SpanScanner.spanFrom","SpanScanner.matches","SpanScanner.error","StringScanner.lastMatch","StringScanner.peekChar","StringScanner.scan","StringScanner.expect","StringScanner._fail","StringScanner.expect[function-entry$1]","StringScanner.matches","AsciiGlyphSet.glyphOrAscii","AsciiGlyphSet.horizontalLine","AsciiGlyphSet.verticalLine","AsciiGlyphSet.topLeftCorner","AsciiGlyphSet.bottomLeftCorner","AsciiGlyphSet.upEnd","AsciiGlyphSet.downEnd","UnicodeGlyphSet.glyphOrAscii","UnicodeGlyphSet.horizontalLine","UnicodeGlyphSet.verticalLine","UnicodeGlyphSet.topLeftCorner","UnicodeGlyphSet.bottomLeftCorner","UnicodeGlyphSet.upEnd","UnicodeGlyphSet.downEnd","internalBootstrapBrowserTest.<anonymous function>","suiteChannel","setStackTraceMapper","postMessageChannel.<anonymous function>","convertNativeToDart_AcceptStructuredClone","convertNativeToDart_SerializedScriptValue","postMessageChannel.<anonymous function>.<anonymous function>","ClosedException.toString","Declarer.test","Declarer.group","Declarer.build","Declarer._checkNotBuilt","Declarer._runSetUps","Declarer._setUpAll","Declarer._tearDownAll","Declarer.test.<anonymous function>","Invoker.addTearDown","Declarer.test.<anonymous function>.<anonymous function>","Declarer.test.<anonymous function>.<anonymous function>.<anonymous function>","Declarer.group.<anonymous function>","Declarer.build.<anonymous function>","Declarer._runSetUps.<anonymous function>","Declarer._tearDownAll.<anonymous function>","Declarer._tearDownAll.<anonymous function>.<anonymous function>","Declarer._tearDownAll.<anonymous function>.<anonymous function>.<anonymous function>","Group.forPlatform","Group._map","Group.forPlatform.<anonymous function>","Group._map.<anonymous function>","LocalTest.load","Invoker._closableKey","Invoker._","Invoker._counterKey","Invoker.liveTest","LocalTest.forPlatform","Invoker._outstandingCallbacks","Invoker.addOutstandingCallback","Invoker.waitForOutstandingCallbacks","Invoker.unclosable","Invoker.heartbeat","LiveTest.isComplete","Invoker._handleError","State.shouldBeDone","Invoker._handleError[function-entry$2]","Invoker._onRun","Invoker._runTearDowns","Invoker.guard.<anonymous function>","Invoker.guard.<anonymous function>.<anonymous function>","Invoker.waitForOutstandingCallbacks.<anonymous function>","Invoker.heartbeat.message","niceDuration","Invoker.heartbeat.<anonymous function>","Invoker.heartbeat.<anonymous function>.<anonymous function>","Invoker._handleError.<anonymous function>","_AsyncCounter.complete","Invoker._onRun.<anonymous function>","Invoker._onRun.<anonymous function>.<anonymous function>","Invoker._onRun.<anonymous function>.<anonymous function>.<anonymous function>","Invoker._onRun.<anonymous function>.<anonymous function>.<anonymous function>.<anonymous function>","Invoker._print","_AsyncCounter.decrement","_LiveTest.run","LiveTestController._run","LiveTestController._isClosed","_LiveTest.onComplete","LiveTestController.addError","LiveTestController.setState","LiveTestController.message","_BroadcastStreamController.hasListener","LiveTestController._close","MessageType.toString","Metadata._validateTags","Metadata.validatePlatformSelectors","Metadata.merge","Metadata.change","Metadata.change[function-entry$0$onPlatform]","Metadata.change[function-entry$0$timeout]","Metadata.change[function-entry$0$skip$skipReason]","Metadata.forPlatform","Metadata.serialize","Metadata._serializeTimeout","Metadata._unresolved","Metadata.<anonymous function>","Metadata.deserialize.<anonymous function>","BooleanSelectorImpl.parse","Parser","Metadata._validateTags.<anonymous function>","Metadata.validatePlatformSelectors.<anonymous function>","Metadata.merge.<anonymous function>","Metadata.forPlatform.<anonymous function>","Metadata.serialize.<anonymous function>","OperatingSystem.toString","OperatingSystem.find.<anonymous function>","PlatformSelector.validate","PlatformSelector.evaluate","PlatformSelector.intersection","PlatformSelector.toString","PlatformSelector.==","PlatformSelector.hashCode","PlatformSelector.parse.<anonymous function>","PlatformSelector.validate.<anonymous function>","PlatformSelector.validate.<anonymous function>.<anonymous function>","PlatformSelector.evaluate.<anonymous function>","Runtime.toString","Runtime.deserialize.<anonymous function>","StackTraceFormatter.configure","StackTraceFormatter.configure[function-entry$0$except$only]","StackTraceFormatter.configure[function-entry$0$mapper]","StackTraceFormatter.formatStackTrace","parseExtended","JSStackTraceMapper.mapStackTrace","StackTraceFormatter._except","StackTraceFormatter._only","StackTraceFormatter.formatStackTrace.<anonymous function>","_LinkedHashSet.isNotEmpty","State.==","State.hashCode","State.toString","Status.toString","Result.toString","TestFailure.toString","_expect.<anonymous function>","Timeout.merge","Duration.*","Timeout.apply","Timeout.hashCode","Timeout.==","Timeout.toString","RemoteListener._serializeGroup","RemoteListener._serializeTest","RemoteListener._runLiveTest","_BroadcastStreamController.stream","_LiveTest.onStateChange","_LiveTest.onError","_LiveTest.onMessage","RemoteListener.start.<anonymous function>","StackTraceFormatter","RemoteListener.start.<anonymous function>.<anonymous function>","RemoteListener.start.<anonymous function>.<anonymous function>.<anonymous function>","StreamQueue._","RemoteListener.start.<anonymous function>.<anonymous function>.<anonymous function>.<anonymous function>","SuiteChannelManager.current","SuiteChannelManager.connectIn","StreamChannelCompleter.setChannel","StreamSinkCompleter.setDestinationSink","RemoteListener.start.<anonymous function>.<anonymous function>.<anonymous function>.<anonymous function>.<anonymous function>","RemoteListener._listen","RemoteListener._serializeGroup.<anonymous function>","RemoteListener._serializeTest.<anonymous function>","RemoteListener._runLiveTest.<anonymous function>","RemoteListener._runLiveTest.<anonymous function>.<anonymous function>","SuiteChannelManager.connectOut","StreamCompleter._stream","StreamSinkCompleter.sink","StreamChannelCompleter._streamCompleter","StreamChannelCompleter._sinkCompleter","StreamChannelCompleter","StreamChannel","IterableSet.length","IterableSet.iterator","IterableSet.toSet","errorsDontStopTest.<anonymous function>","currentOSGuess.<anonymous function>","Engine._onUnpaused","Engine.success","Engine.liveTests","UnionSet.from","Engine.passed","Engine.skipped","Engine.failed","Engine.active","Engine.run","Engine._runGroup","JSArray._toListGrowable","Engine._runLiveTest","Engine._runLiveTest[function-entry$2]","Engine._runSkippedTest","Engine._addLiveSuite","_LiveSuite.onTestStarted","_LiveSuite.passed","_LiveSuite.skipped","_LiveSuite.failed","Engine.success.<anonymous function>","Engine.<anonymous function>","Engine.run.<anonymous function>","Engine.run.<anonymous function>.<anonymous function>","Engine_run__closure","Engine.run.<anonymous function>.<anonymous function>.<anonymous function>","Engine.run.<anonymous function>.<anonymous function>.<anonymous function>.<anonymous function>","Engine._runLiveTest.<anonymous function>","Engine._runSkippedTest.<anonymous function>","LiveSuiteController.reportLiveTest","LiveSuiteController.close","LiveSuiteController.<anonymous function>","LiveSuiteController.reportLiveTest.<anonymous function>","LiveSuiteController.close.<anonymous function>","ExpandedReporter._onTestStarted","Stopwatch.start","ExpandedReporter._onStateChange","ExpandedReporter._onError","ExpandedReporter._onDone","ExpandedReporter._progressLine","ExpandedReporter._timeString","ExpandedReporter._progressLine[function-entry$1$suffix]","ExpandedReporter._progressLine[function-entry$1$color]","ExpandedReporter._progressLine[function-entry$1]","ExpandedReporter._description","ExpandedReporter._onTestStarted.<anonymous function>","RunnerSuiteController._close","RunnerSuiteController._suite","RunnerSuiteController._close.<anonymous function>","PrintSink.writeln","PrintSink._flush","JSStackTraceMapper._deserializePackageConfigMap.<anonymous function>","_declarer.<anonymous function>","RunnerSuiteController._local","RunnerSuite._","DelegatingSink.add","Engine.suiteSink","DelegatingSink.close","Stopwatch","ExpandedReporter._","StreamGroup.stream","_declarer.<anonymous function>.<anonymous function>","main.<anonymous function>","main.<anonymous function>.<anonymous function>","_nullErrorHandler[function-entry$1]","_rootRun[function-entry$4]","_rootRunUnary[function-entry$5]","_rootRegisterCallback[function-entry$4]","_rootRegisterUnaryCallback[function-entry$4]","_rootRegisterBinaryCallback[function-entry$4]","max[function-entry$2]","DART_CLOSURE_PROPERTY_NAME","JS_INTEROP_INTERCEPTOR_TAG","TypeErrorDecoder.noSuchMethodPattern","TypeErrorDecoder.notClosurePattern","TypeErrorDecoder.nullCallPattern","TypeErrorDecoder.nullLiteralCallPattern","TypeErrorDecoder.undefinedCallPattern","TypeErrorDecoder.undefinedLiteralCallPattern","TypeErrorDecoder.nullPropertyPattern","TypeErrorDecoder.nullLiteralPropertyPattern","TypeErrorDecoder.undefinedPropertyPattern","TypeErrorDecoder.undefinedLiteralPropertyPattern","_AsyncRun._scheduleImmediateClosure","Future._nullFuture","_RootZone._rootMap","Utf8Decoder._decoder","_Base64Decoder._inverseAlphabet","_Uri._isWindowsCached","_Uri._needsNoEncoding","_hasErrorStackProperty","_scannerTables","_whitespaceAndSingleLineComments","_multiLineCommentBody","_hyphenatedIdentifier","_dart2DynamicArgs","_escapeRegExp","windows","url","context","createInternal","Style.posix","PosixStyle","Style.windows","WindowsStyle","Style.url","UrlStyle","Style.platform","_digits","MAX_INT32","MIN_INT32","_specKey","_vmFrame","_v8Frame","_v8UrlLocation","_v8EvalLocation","_firefoxSafariFrame","_friendlyFrame","_asyncBody","_initialDot","Frame._uriRegExp","Frame._windowsRegExp","StackZoneSpecification.disableKey","_terseRegExp","_v8Trace","_v8TraceLine","_firefoxSafariTrace","_friendlyTrace","Metadata.empty","_universalValidVariables","_currentKey","currentOSGuess","anchoredHyphenatedIdentifier","SuiteConfiguration.empty","patchInstance","main_closure","fromTearOff","StaticClosure","BoundClosure","functionCounter","forwardCallTo","_computeSignatureFunctionNewRti","CyclicInitializationError","NullThrownError","safeToString","_objectToString","Closure","objectTypeName","_objectTypeNameNewRti","Object","_saneNativeClassName","_getInterfaceTypeArguments","_getGenericFunctionBounds","","value","_getFunctionParameters","markFixed","JSArray","markFixedList","StringBuffer","iterableToFullString","_toStringVisiting","_writeAll","noElement","ArrayIterator","ListIterator","ListMixin","Iterable","initNativeDispatchFlag","getTagFunction","dispatchRecordsForInstanceTags","interceptorsForUncacheableTags","alternateTagFunction","JavaScriptIndexingBehavior","prototypeForTagFunction","initHooks_closure","forType","_TypeError","compose","_CastError","fromMessage","_isUnionOfFunctionType","eval","_parseRecipe","create","parse","handleDigit","handleIdentifier","toType","_lookupGenericFunctionParameterRti","_lookupTerminalRti","toTypes","_lookupInterfaceRti","_lookupGenericFunctionRti","_lookupBindingRti","handleExtendedOperations","_lookupUnaryRti","_FunctionParameters","_lookupFunctionRti","toTypesNamed","_canonicalRecipeJoin","_canonicalRecipeJoinNamed","Rti","_finishRti","int","double","num","String","bool","_AssertionError","_getBindingArguments","indexToType","findRule","_getCanonicalRecipe","evalInEnvironment","_getFutureFromFutureOr","bind","findErasedType","evalRecipeIntercepted","evalRecipe","forwardInterceptedCallTo","cspForwardCall","selfFieldNameCache","computeFieldNamed","selfOf","receiverFieldNameCache","cspForwardInterceptedCall","receiverOf","internalBootstrapBrowserTest_closure","start","_ControllerStream","_current","Null","Stream","AsyncError","_propagateToListeners","_Future__propagateToListeners_handleWhenCompleteCallback","_Future__propagateToListeners_handleValueCallback","_Future__propagateToListeners_handleError","_chainCoreFuture","_Future__prependListeners_closure","ExceptionAndStackTrace","_StackTrace","unwrapException_saveStackTrace","UnknownJsTypeError","StackOverflowError","extractPattern","TypeErrorDecoder","provokePropertyErrorOn","provokeCallErrorOn","_Future__propagateToListeners_handleWhenCompleteCallback_closure","_FutureListener","_RootZone_bindCallbackGuarded_closure","_rootHandleUncaughtError_closure","_nextCallback","_lastPriorityCallback","_lastCallback","_AsyncCallbackEntry","_enter","_isInCallbackLoop","_initializeScheduleImmediate","_AsyncRun__initializeScheduleImmediate_internalCallback","_AsyncRun__initializeScheduleImmediate_closure","_createTimer","Duration_toString_twoDigits","Duration_toString_sixDigits","_TimerImpl_internalCallback","_AsyncRun__scheduleImmediateWithSetImmediate_internalCallback","_AsyncRun__scheduleImmediateJsOverride_internalCallback","_Exception","_Future__addListener_closure","_PendingEvents","_chainForeignFuture","_Future__chainForeignFuture_closure","_StreamControllerLifecycle","StreamConsumer","Stream_pipe_closure","_GuaranteeSink","_EventStream","postMessageChannel_closure","_literal","_EventStreamSubscription_closure","_convertDataTree__convert","_IdentityHashMap","mapToString","MapBase_mapToString_closure","MapMixin","_getTableEntry","_HashMapKeyIterable","iterableToShortString","checkNotNegative","range","_HashMapKeyIterator","MappedIterator","Iterator","EfficientLengthMappedIterable","MappedListIterable","ListIterable","_newHashTable","_setTableEntry","JsLinkedHashMap","LinkedHashMapKeyIterable","LinkedHashMapCell","postMessageChannel__closure","_StructuredCloneDart2Js","DateTime","_StructuredClone_walk_closure","_AcceptStructuredCloneDart2Js","StreamSink","StreamSubscription","_empty","_AcceptStructuredClone_walk_closure","getYear","_fourDigits","getMonth","_twoDigits","getDay","getHours","getMinutes","getSeconds","getMilliseconds","_threeDigits","lazyAsJsDate","_AsyncCompleter","promiseToFuture_closure","_Future__asyncCompleteError_closure","_Future__asyncComplete_closure","_Future__chainFuture_closure","Stream_firstWhere__closure","_cancelAndErrorClosure_closure","_cancelAndError_closure","zoneValue","_cancelAndValue_closure","_StreamSinkWrapper","GuaranteeChannel_closure","_StreamImplEvents","_SyncCompleter","_GuaranteeSink_addStream_closure","_GuaranteeSink__addError_closure","GuaranteeChannel__closure","_SyncStreamController","_AsyncStreamController","_EventDispatch","_PendingEvents_schedule_closure","_BufferingStreamSubscription__sendDone_sendDone","_StreamController__subscribe_closure","_StreamController__recordCancel_complete","_AddStreamState_cancel_closure","_DelayedError","_BufferingStreamSubscription__sendError_sendError","_DelayedData","RemoteListener_start_closure","fromIterable","Map","runZoned_closure","_rootDelegate","_ZoneDelegate","printToZone","from","_ZoneFunction","_CustomZone_bindCallbackGuarded_closure","periodic","_TimerImpl$periodic_closure","_HashMap","HashMap_HashMap$from_closure","_LinkedHashSet","RemoteListener_start__closure","RemoteListener_start___closure","_sendError","serialize","TestFailure","forTrace","Chain_toString_closure","Chain_toString__closure","_Type","Chain","unmodifiable","LazyChain","Chain_Chain$forTrace_closure","Chain_Chain$parse_closure","Trace_toString_closure","parseFriendly","WhereIterable","Trace$parseFriendly_closure","_StringStackTrace","WhereIterator","Context_split_closure","List","ParsedPath","filled","ParsedPath_normalize_closure","generate","JSSyntaxRegExp","makeNative","_uriDecode","StringMatch","CodeUnits","_hexCharPairToByte","Utf8Decoder","UnmodifiableListMixin","_convertIntercepted","checkValidRange","fromCharCodes","_Utf8Decoder","stringFromCharCode","stringFromCharCodes","stringFromNativeUint8List","_stringFromIterable","stringFromCodePoints","_fromCharCodeApply","_convertInterceptedUint8List","_useTextDecoderChecked","_unsafe","_useTextDecoderUnchecked","_makeDecoder","checkValueInInterval","_StringAllMatchesIterable","_StringAllMatchesIterator","_AllMatchesIterable","_AllMatchesIterator","tooFew","fixed","Context_join_closure","Context_joinAll_closure","_validateArgList_closure","base","_currentUriBase","currentUri","_parse","_SimpleUri","notSimple","parseInt","_defaultPort","_toWindowsFilePath","_checkNonWindowsPathReservedCharacters","_Uri__checkNonWindowsPathReservedCharacters_closure","_checkWindowsDriveLetter","_checkWindowsPathReservedCharacters","fromCharCode","_removeDotSegments","_makePort","_normalizeRelativePath","_mayContainDotSegments","_escapeScheme","_isAlphabeticCharacter","_makeScheme","_fail","_makeUserInfo","_makeHost","_Uri__Uri$notSimple_closure","_makePath","_makeQuery","_makeFragment","_normalizeOrSubstring","_normalize","_normalizeEscape","_escapeChar","_Uri__makePath_closure","_normalizePath","_uriEncode","Codec","_Utf8Encoder","_checkZoneID","_normalizeZoneID","parseIPv6Address","_normalizeRegName","Uri_parseIPv6Address_error","Uri_parseIPv6Address_parseHex","_parseIPv4Address","Uri__parseIPv4Address_error","_canonicalizeScheme","_createTables_closure","_createTables_build","_createTables_setChars","_createTables_setRange","_DataUri","UriData","_checkPadding","_create1","_getPlatformStyle","Frame_Frame$parseFriendly_closure","_catchFormatException","_writeUri","_uriEncodeBytes","Frame","WindowsStyle_absolutePathToUri_closure","_validateMimeType","_skipLeadingWhitespace","_skipTrailingWhitespace","_isWhitespace","parseV8","parseJSCore","parseFirefox","_parseVM","Trace__parseVM_closure","parseVM","Frame_Frame$parseVM_closure","ExpandIterable","Chain_toTrace_closure","Trace$parseFirefox_closure","Frame_Frame$parseFirefox_closure","_uriOrPathToUri","file","_makeWindowsFileUrl","_makeFileUri","Trace$parseJSCore_closure","Frame_Frame$parseV8_closure","Frame_Frame$parseV8_closure_parseLocation","Trace$parseV8_closure","SkipWhileIterable","SkipWhileIterator","StackZoneSpecification_chainFor_closure","_Node","LazyTrace","Trace_Trace$from_closure","LazyChain_toTrace_closure","getProperty","StackTraceFormatter_formatStackTrace_closure","LazyChain_foldFrames_closure","Chain_foldFrames_closure","tooMany","LazyTrace_foldFrames_closure","Trace_foldFrames_closure","ReversedListIterable","mapStackTrace_closure","_prettifyMember_closure","fromJson","notNull","_lastLineLength","_normalizeNewlines","_normalizeTrailingNewline","_normalizeEndOfLine","_glyphs","Highlighter__writeSidebar_closure","Highlighter__writeLastLine_closure","Highlighter__writeIntermediateLines_closure","Highlighter__writeFirstLine_closure","SingleMapping__findColumn_closure","SingleMapping__findLine_closure","SingleMapping","SourceFile","_MappingTokenizer","TargetLineEntry","TargetEntry","SingleMapping$fromJson_closure","closure","MultiSectionMapping","MappingBundle","_JsonMap","_JsonMapKeyIterable","_sendLoadException","StreamQueue","_CompleterStream","_RestRequest","StreamCompleter","RemoteListener_start____closure","deserialize","_deserializeSet","find","Suite","_filterGroup","Symbol","makeErrorHandler","_AddStreamState_makeErrorHandler_closure","Result","_wrapJsFunctionForAsync_closure","_StreamIterator","_awaitOnObject_closure","_AsyncAwaitCompleter","RemoteListener_start_____closure","guard","Invoker_guard_closure","Invoker_guard__closure","RemoteListener","RemoteListener__serializeGroup_closure","RemoteListener__serializeTest_closure","VirtualChannel","_EmptyStream","NullStreamSink","MultiChannel","NullStreamSink_addStream_closure","_LinkedHashSetCell","RemoteListener__runLiveTest_closure","_BroadcastStream","RemoteListener__runLiveTest__closure","Invoker","State","Invoker__onRun_closure","_AsyncCounter","capture","_keyCount","StackZoneSpecification","setProperty","StackZoneSpecification__currentTrace_closure","Invoker__onRun__closure","Invoker__onRun___closure","Message","Invoker__onRun____closure","Future_Future_closure","errorsDontStopTest_closure","Invoker_waitForOutstandingCallbacks_closure","sync","Invoker_heartbeat_closure","Invoker_heartbeat_message","Invoker_heartbeat__closure","TimeoutException","Timeout","Invoker__handleError_closure","Chain_Chain$current_closure","_SyncBroadcastStreamController","_LiveTest","_BroadcastStreamController","Metadata_serialize_closure","MapEntry","PlatformSelector","Group_forPlatform_closure","GroupEntry","Group__map_closure","Metadata_forPlatform_closure","Metadata_Metadata__unresolved","_","Metadata_Metadata_closure","Metadata_merge_closure","Set","UnmodifiableMapView","_throwUnmodifiable","_ConstantMapKeyIterable","ConstantStringMap","DelegatingSet","Metadata__validateTags_closure","LinkedHashMap_LinkedHashMap$from_closure","PlatformSelector_evaluate_closure","OperatingSystem_find_closure","Runtime_Runtime$deserialize_closure","Runtime","Declarer_build_closure","LocalTest","Declarer__tearDownAll_closure","Declarer__tearDownAll__closure","Declarer__tearDownAll___closure","_deserializeTimeout","Metadata$deserialize_closure","BooleanSelectorImpl","Scanner","AndNode","IntersectionSelector","OrNode","ConditionalNode","Evaluator","Token","_SpanScannerState","IdentifierToken","SourceSpanMixin","FileLocation","NotNode","VariableNode","PlatformSelector$parse_closure","_wrapFormatException","_CompleterSink","_CompleterSink__setDestinationSink_closure","StreamSinkCompleter","_EventRequest","_CancelOnErrorSubscriptionWrapper","_CancelOnErrorSubscriptionWrapper_onError_closure","_CancelOnErrorSubscriptionWrapper_onError__closure","ErrorResult","ValueResult","EventSink","_NextRequest","_GeneratedStreamImpl","PackageRootResolver","_deserializePackageConfigMap","_normalizeMap","PackageConfigResolver","JSStackTraceMapper","castFrom","CastMap","CastIterator","EfficientLengthIterable","_EfficientLengthCastIterable","PackageConfigResolver__normalizeMap_closure","JSStackTraceMapper__deserializePackageConfigMap_closure","_StreamChannel","Declarer_group_closure","Trace_Trace$current_closure","Metadata_validatePlatformSelectors_closure","PlatformSelector_validate_closure","PlatformSelector_validate__closure","Validator","_parseOnPlatform","_parseTags","_globalDeclarer","_declarer_closure","RunnerSuiteController","_AsyncBroadcastStreamController","AsyncMemoizer","RunnerSuite","_frequency","initTicker","timerFrequency","ExpandedReporter","PrintSink","fromFuture","_declarer__closure","error","UnmodifiableListView","timerTicks","UnionSet","IterableSet","ExpandedReporter__onTestStarted_closure","Engine_run_closure","Pool_close_closure","Engine_run___closure","Engine_run____closure","Pool__onResourceReleaseAllowed_closure","Pool__runOnRelease_closure","PoolResource","LiveSuiteController_close_closure","RunnerSuiteController__close_closure","Engine__runSkippedTest_closure","Engine__runLiveTest_closure","microtask","Future_Future$microtask_closure","LiveSuiteController_reportLiveTest_closure","_nextPowerOf2","StreamGroup__listenToStream_closure","_LiveSuite","LiveSuiteController_closure","wait","Engine_success_closure","Future_wait_handleError","Primitives_initTicker_closure","StreamGroup","Engine_closure","_macOSDirectories","_list","_map","SuiteConfiguration","main__closure","Declarer_test_closure","Declarer_test__closure","Declarer_test___closure","Declarer__runSetUps_closure","forEach","Future_forEach_closure","doWhile","Future_doWhile_closure","_expect_closure","StringDescription","Matcher","prettyPrint__prettyPrint","prettyPrint__prettyPrint_pp","prettyPrint__prettyPrint_closure","escape_closure","Runes","RuneIterator","_Predicate","wrapMatcher_closure","_StringEqualsMatcher","_DeepMatcher","_DeepMatcher__compareSets_closure","TypeMatcher","FeatureMatcher","_writeTrailing","_writeLeading","x","objectAssign","JS_CONST","Interceptor","JSBool","JSNull","JSObject","JavaScriptObject","PlainJavaScriptObject","UnknownJavaScriptObject","Function","JavaScriptFunction","JSUnmodifiableArray","JSNumber","JSInt","JSDouble","Pattern","JSString","_CastIterableBase","EmptyIterator","FixedLengthListMixin","UnmodifiableListBase","ConstantMap","noSuchMethodPattern","notClosurePattern","nullCallPattern","nullLiteralCallPattern","undefinedCallPattern","undefinedLiteralCallPattern","nullPropertyPattern","nullLiteralPropertyPattern","undefinedPropertyPattern","undefinedLiteralPropertyPattern","NoSuchMethodError","StackTrace","TearOffClosure","RegExpMatch","Match","NativeByteBuffer","ByteBuffer","NativeTypedData","NativeByteData","NativeTypedArray","NativeTypedArrayOfDouble","NativeTypedArrayOfInt","NativeFloat32List","NativeFloat64List","NativeInt16List","NativeInt32List","NativeInt8List","NativeUint16List","Uint32List","NativeUint32List","NativeUint8ClampedList","Uint8List","Type","_Error","Sink","_Completer","StreamTransformer","StreamTransformerBase","_StreamController","_SyncStreamControllerDispatch","_AsyncStreamControllerDispatch","_StreamImpl","_DelayedEvent","_DelayedDone","Error","ZoneSpecification","ZoneDelegate","Zone","_Zone","_rootMap","_RootZone","IterableBase","ListBase","MapBase","_UnmodifiableMapMixin","MapView","Queue","SetMixin","SetBase","_SetBase","AsciiCodec","_UnicodeSubsetEncoder","AsciiEncoder","Base64Codec","Base64Encoder","_FusedCodec","Converter","Encoding","JsonCodec","JsonDecoder","Utf8Codec","Utf8Encoder","_decoder","OutOfMemoryError","StringSink","Uri","_isWindowsCached","_needsNoEncoding","AbortPaymentEvent","AnimationEvent","AnimationPlaybackEvent","ApplicationCacheErrorEvent","BackgroundFetchClickEvent","BackgroundFetchEvent","BackgroundFetchFailEvent","BackgroundFetchedEvent","BeforeInstallPromptEvent","BeforeUnloadEvent","Blob","BlobEvent","CanMakePaymentEvent","ClipboardEvent","CloseEvent","CompositionEvent","CustomEvent","DeviceMotionEvent","DeviceOrientationEvent","DomError","DomException","ErrorEvent","Event","EventTarget","ExtendableEvent","ExtendableMessageEvent","FetchEvent","File","FocusEvent","FontFaceSetLoadEvent","ForeignFetchEvent","GamepadEvent","HashChangeEvent","InstallEvent","KeyboardEvent","Location","MediaEncryptedEvent","MediaError","MediaKeyMessageEvent","MediaQueryListEvent","MediaStreamEvent","MediaStreamTrackEvent","MessageEvent","MessagePort","MidiConnectionEvent","MidiMessageEvent","MouseEvent","MutationEvent","NavigatorUserMediaError","NotificationEvent","OverconstrainedError","PageTransitionEvent","PaymentRequestEvent","PaymentRequestUpdateEvent","PointerEvent","PopStateEvent","PositionError","PresentationConnectionAvailableEvent","PresentationConnectionCloseEvent","ProgressEvent","PromiseRejectionEvent","PushEvent","RtcDataChannelEvent","RtcDtmfToneChangeEvent","RtcPeerConnectionIceEvent","RtcTrackEvent","SecurityPolicyViolationEvent","SensorErrorEvent","SpeechRecognitionError","SpeechRecognitionEvent","SpeechSynthesisEvent","StorageEvent","SyncEvent","TextEvent","TouchEvent","TrackEvent","TransitionEvent","UIEvent","VRDeviceEvent","VRDisplayEvent","VRSessionEvent","WheelEvent","Window","_MojoInterfaceRequestEvent","_ResourceProgressEvent","_USBConnectionEvent","EventStreamProvider","_StructuredClone","_AcceptStructuredClone","VersionChangeEvent","ByteData","Int8List","Uint8ClampedList","Int16List","Uint16List","Int32List","Float32List","Float64List","AudioProcessingEvent","OfflineAudioCompletionEvent","ContextEvent","SqlError","DelegatingSink","DelegatingStreamSubscription","_StreamGroupState","BooleanSelector","All","Node","Visitor","None","TokenType","RecursiveVisitor","EmptyUnmodifiableSet","UnmodifiableSetMixin","_DelegatingIterableBase","DelegatingIterable","_IsTrue","Description","SyncPackageResolver","_PathDirection","_PathRelation","InternalStyle","Style","Mapping","_TokenKind","FileSpan","SourceLocationMixin","SourceSpan","SourceSpanException","_uriRegExp","_windowsRegExp","disableKey","StreamChannelMixin","LineScannerState","StringScanner","AsciiGlyphSet","UnicodeGlyphSet","LiveTest","MessageType","empty","OperatingSystem","Status","Test","StackTraceMapper","LiveSuite","RuntimeSelection","_NativeTypedArrayOfDouble&NativeTypedArray&ListMixin","_NativeTypedArrayOfDouble&NativeTypedArray&ListMixin&FixedLengthListMixin","_NativeTypedArrayOfInt&NativeTypedArray&ListMixin","_NativeTypedArrayOfInt&NativeTypedArray&ListMixin&FixedLengthListMixin","_ListBase&Object&ListMixin","_SetBase&Object&SetMixin","_UnmodifiableMapView&MapView&_UnmodifiableMapMixin","_QueueList&Object&ListMixin","_UnionSet&SetBase&UnmodifiableSetMixin","_UnmodifiableSetView&DelegatingSet&UnmodifiableSetMixin","_IterableSet&SetMixin&UnmodifiableSetMixin","dateNow","addRules","addErasedTypes","_scheduleImmediateJsOverride","_scheduleImmediateWithSetImmediate","_scheduleImmediateWithTimer","_kTrue","decodeComponent","_scheduleImmediateClosure","_nullFuture","_inverseAlphabet","posix","platform","getInterceptor$","getInterceptor$asx","async___startMicrotaskLoop$closure","async__AsyncRun__scheduleImmediateJsOverride$closure","async__AsyncRun__scheduleImmediateWithSetImmediate$closure","async__AsyncRun__scheduleImmediateWithTimer$closure","async___nullDoneHandler$closure","async___nullErrorHandler$closure","async___nullDataHandler$closure","getInterceptor$ax","async___printToZone$closure","math__max$closure","getInterceptor$s","core_Uri_decodeComponent$closure","main_test__main$closure","_js_helper_Primitives_dateNow$closure","async_Future__kTrue$closure","pretty_print___escapeString$closure","util___getHexLiteral$closure","getInterceptor$x","getInterceptor$ansx","getInterceptor$n","async___rootHandleUncaughtError$closure","async___rootRun$closure","async___rootRunUnary$closure","async___rootRunBinary$closure","async___rootRegisterCallback$closure","async___rootRegisterUnaryCallback$closure","async___rootRegisterBinaryCallback$closure","async___rootErrorCallback$closure","async___rootScheduleMicrotask$closure","async___rootCreateTimer$closure","async___rootCreatePeriodicTimer$closure","async___rootPrint$closure","async___rootFork$closure","_captured_K1_1","_captured_this_1","dart.async#_box_0","_captured_matcher_0","future","_captured_V1_2","_captured_listener_2","_captured_frame_0","_captured_expectedElement_1","_captured_getMain_1","location","channel","_captured_depth_3","controller","matches","_captured_beforeLoad_4","_captured_f_1","line","_captured_printZone_5","_captured_R_3","end","_captured_transform_1","result","_captured_selector_0","handleError","_captured_body_1","_captured_elements_0","_captured_x_0","suite","_captured_T_3","index","_captured_validVariables_0","_captured_terse_2","addEventListener","stackTrace","timeout","_withValue","message","immediate","_captured_performance_0","trace","_captured_div_1","level","span","_captured_registered_1","where","toString","callback","decoded","groups","liveTest","_captured_engine_0","_captured_chain_0","completer","_captured_longest_0","dart.async#_box_1","skipWhile","_captured_fn_2","call","_captured_oldPredicate_0","_captured_counter_3","_captured_hasError_3","_captured_loadResource_2","describe","id","_captured_milliseconds_1","_captured_originalSource_0","stream","immediateError","_captured_outstandingCallbacksForBody_1","_captured_sourceResult_2","_captured_K_1","_captured_serializedOnPlatform_0","_captured_V_2","broadcast","onData","_captured_target_0","_captured_sourceMap_1","_captured_invoker_0","_captured_minified_4","zone","_captured_sdkRoot_2","_captured_streamConsumer_0","_captured_e_1","_captured_s_2","_captured_sdkLib_3","_addEventError","column","_captured_cleanUp_3","_captured_eagerError_4","iterator","identifier","port","_captured_action_1","_captured_node_2","_captured_T1_3","_captured_T2_4","withResource","_captured_portSubscription_1","_captured_serialized_0","_captured_doneSignal_2","_captured_arg1_1","_captured_pos_1","_captured_arg2_2","_captured_dispatch_1","_captured_getTag_0","testOn","_captured_getUnknownTag_0","skip","verboseTrace","_captured_prototypeForTag_0","chainStackTraces","_captured_argumentError_0","==","retry","_captured_arg_1","skipReason","_captured__convertedObjects_0","onPlatform","uri","_captured_portStart_1","skipped","_captured_textInside_1","_captured_maxItems_0","_captured_maxLineLength_1","original","_runGroup","host","_captured__prettyPrint_1","_runLiveTest","_captured_indent_0","_runSkippedTest","_captured_computation_1","_captured_orElse_1","_captured_countSuccess_2","_captured_K2_0","_captured_protected_0","_captured_spec_6","_captured_pp_0","onError","_captured_object_1","_captured_ex_0","subscription","cancel","_captured_bodyFunction_0","_captured_tables_0","data","stream_channel_controller.dart#_foreign","stack_zone_specification.dart#_disabled","expanded.dart#_onTestStarted","newDartList","configure","elapsedMicroseconds","dart.core#_captured_argumentError_0","platform_selector.dart#_captured_this_0","dart.async#_completeWithValue","source_maps.parser#_captured_this_0","dart.async#_isScheduled","hashMapCellKey","dart.async#_captured_future_1","multi_channel.dart#_closeChannel","encode","dart.async#_error","dart.core#_start","onClose","dart.async#_captured_callback_1","dart.async#_completeError","dart.async#_captured_doneSignal_2","_js_helper#_captured_result_2","separators","async_memoizer.dart#_completer","invoker.dart#_counterKey","functions.dart#_captured_V1_2","prettyUri","metadata.dart#_captured_serializedOnPlatform_0","equals_matcher.dart#_compareSets","fold","getRoot","dart.collection#_newSet","invoker.dart#_captured_stackTrace_3","dart.core#_isPort","catchError","*","parser.dart#_and","metadata.dart#_captured_verboseTrace_4","scanner.dart#_scanOperator","highlighter.dart#_writeFirstLine","dart.async#_handleUncaughtError","engine.dart#_failedGroup","rti#_kind","isOdd","source_maps.parser#_findLine","functions.dart#_captured_V_3","stack_zone_specification.dart#_currentNode","engine.dart#_onSuiteStartedController","stack_zone_specification.dart#_captured_f_0","pool.dart#_requestedResources","indexOf","rti#_precomputed4","source_maps.parser#_consumeValue","replaceAll","stream_queue.dart#_completer","tags","source_map_stack_trace.dart#_captured_sdkRoot_3","_js_helper#_previous","needsSeparatorPattern","dart.async#_run","replace","dart.collection#_add","_interceptors#_shlPositive","stream_sink_completer.dart#_ensureController","dart.dom.html#_location","dart.async#_mayAddListener","lazy_chain.dart#_captured_terse_2","queue_list.dart#_preGrow","evaluate","wrappers.dart#_base","context.dart#_isWithinOrEqualsFast","_js_helper#_modified","shouldBeDone","isBlink","dart.core#_currentCodePoint","stream_queue.dart#_addResult","source_map_stack_trace.dart#_box_0","typedMatches","moveNext","_js_helper#_execAnchored","duration","guarantee_channel.dart#_onSinkDisconnected","isCompleted","query","visitVariable","bindCallback","stack_zone_specification.dart#_currentTrace","sourceRoot","take","expanded.dart#_progressLine","listenerHasError","liveTests","createPeriodicTimer","live_suite_controller.dart#_onCloseCompleter","remote_listener.dart#_captured_controller_0","dart.async#_onCancel","pathsEqual","distance","dart.core#_position","asStream","abs","listenerValueOrError","dart.async#_decrementPauseCount","html_common#_captured_this_1","hasTrailingSeparator","stack_trace_formatter.dart#_captured_this_0","declarer.dart#_name","stack_zone_specification.dart#_registerBinaryCallback","dart.collection#_tail","asUint8List","isScaffoldAll","remote_listener.dart#_captured_test_1","isWithin","platform_selector.dart#_captured_validVariables_0","functions.dart#_box_0","live_suite_controller.dart#_passed","addTearDown","dart._internal#_iterator","hashMapCellValue","functions.dart#_captured_K1_1","lastSpan","runner_suite.dart#_environment","registerCallback","handleUncaughtError","stack_zone_specification.dart#_captured_this_1","allMatches","dart.collection#_position","_js_helper#_expr","dart.convert#_data","runner_suite.dart#_suiteChannel","engine.dart#_captured_suite_1","onListen","equals_matcher.dart#_recursiveMatch","highlighter.dart#_writeSidebar","stream_group.dart#_onCancelBroadcast","dart._internal#_iterable","dart.convert#_buffer","print_sink.dart#_flush","operating_system.dart#_captured_identifier_0","invoker.dart#_print","scan","onCancel","dart.async#_schedule","declarer.dart#_metadata","highlighter.dart#_colorize","source_map_stack_trace.dart#_captured_sdkRoot_2","_js_helper#_target","highlighter.dart#_multiline","highlighter.dart#_paddingBeforeSidebar","dart._internal#_startIndex","rti#_specializedTestResource","_interceptors#_isInt32","dart.collection#_contains","invoker.dart#_handleError","engine.dart#_runPool","dart.async#_setPendingComplete","parser.dart#_simpleExpression","dart.async#_rootRunUnary","dart.async#_cloneResult","stack_zone_specification.dart#_trimVMChain","live_test_controller.dart#_run","dart.collection#_first","metadata.dart#_serializeTimeout","relative","declarer.dart#_collectTraces","span_exception.dart#_message","live_test_controller.dart#_onRun","join","stack_zone_specification.dart#_errorCallback","stack_zone_specification.dart#_registerUnaryCallback","runner_suite.dart#_closeMemo","change","addAll","dart.async#_isPaused","previous","dart.async#_addError","source_map_stack_trace.dart#_captured_minified_4","dart.core#_queryStart","dart.async#_captured_eagerError_4","dart.async#_captured_T_2","whenComplete","position","_js_helper#_newLinkedCell","asCurrent","addDescriptionOf","dart.async#_captured_orElse_1","dart.async#_captured_subscription_0","invoker.dart#_count","rti#_eval","dart.async#_addEventError","rti#_optionalPositional","queue_list.dart#_writeToList","dart.async#_hasPending","live_test_controller.dart#_test","runner_suite.dart#_captured_this_0","pool.dart#_captured_zone_0","invoker.dart#_controller","setRange","write","pretty_print.dart#_captured_maxItems_0","stream_queue.dart#_isClosed","multi_channel.dart#_closeInnerChannel","invoker.dart#_closable","update","test.src.runner.browser.post_message_channel#_captured_controller_0","dart.collection#_current=","dart.async#_thenAwait","dart.convert#_upgrade","_js_helper#_fetch","isNewSegment","evaluator.dart#_semantics","internalFindBucketIndex","stack_zone_specification.dart#_registerCallback","file.dart#_cachedLine","live_suite_controller.dart#_controller","dart.async#_cancel","isPassing","source_maps.parser#_lineStart","expanded.dart#_noColor","dart.async#_forEachListener","runner_suite.dart#_isDebugging","fillRange","dart.convert#_second","removeTrailingSeparators","dart.core#_errorName","union_set_controller.dart#_set","visitAnd","pool.dart#_closeMemo","dart.async#_chainFuture","declare","needsSeparator","second","dart.async#_isCanceled","handleNext","union_set.dart#_disjoint","live_test_controller.dart#_liveTest","dart.async#_ensurePendingEvents","failed","context.dart#_parse","string_scanner.dart#_lastMatch","replaceRange","dart.convert#_carry","expand","stack_zone_specification.dart#_captured_this_0","isAbsolute","peek","pretty_print.dart#_captured_object_1","dart.async#_rootRegisterCallback","guarantee_channel.dart#_doneCompleter","isValue","_interceptors#_defaultSplit","_js_helper#_execGlobal","pool.dart#_onResourceReleaseAllowed","_interceptors#_shrBothPositive","chain.dart#_captured_longest_0","dart.core#_captured_error_0","dart.collection#_remove","dart._internal#_string","padRight","dart.async#_iterator","success","stack_zone_specification.dart#_captured_stackTrace_2","multi_channel.dart#_pendingIds","dart.core#_toNonSimple","remote_listener.dart#_captured_spec_6","readChar","scaleFactor","_js_helper#_string","stream_group.dart#_controller","remote_listener.dart#_serializeGroup","microsecond","declarer.dart#_checkNotBuilt","dart.collection#_computeKeys","binaryOnError","parser.dart#_or","dart.async#_captured_computation_1","dart.collection#_findBucketIndex","release","runner_suite.dart#_close","union","_interceptors#_iterable","dart.typed_data.implementation#_setRangeFast","live_suite_controller.dart#_captured_countSuccess_2","dart.collection#_map","internalSet","dart.collection#_checkModification","single","functions.dart#_captured_K_2","joinAll","dart.async#_isEmpty","load","pipe","identicalInJs","dart.async#_asyncCompleteError","lazy_trace.dart#_trace","hashCode","pool.dart#_pool","decrement","registerUnaryCallback","pool.dart#_maxAllocatedResources","isComplete","indexable","hasTokens","dart.dom.html#_onData","_js_helper#_strings","pathSegments","expanded.dart#_green","dart.async#_captured_registered_1","describeTypedMismatch","equals_matcher.dart#_expected","whenFalse","decode","dart._internal#_captured_f_1","any","convert","[]=","future_group.dart#_completer","dart.async#_add","matchTypeError","_js_helper#_last","unclosable","containsKey","engine.dart#_runGroup","queue_list.dart#_grow","chain.dart#_captured_predicate_0","minute","source_maps.parser#_length","declarer.dart#_setUpAllTrace","codeUnitAt","modifiedObject","dart.js_util#_captured_completer_0","newJsObject","active","expanded.dart#_lastProgressSuffix","future_group.dart#_captured_index_1","union_set.dart#_dedupIterable","live_suite_controller.dart#_captured_this_0","endsWith","dart.async#_captured_streamConsumer_0","removeLast","urls","dart.async#_captured_hasError_3","remote_listener.dart#_captured_this_1","dart.async#_varData","_js_helper#_name","engine.dart#_coverage","dart._internal#_endIndex","codeUnitsEqual","dart.async#_captured_s_2","toTrace","source_maps.parser#_segmentError","pool.dart#_closeGroup","bindUnaryCallback","dart.collection#_length","runner_suite.dart#_controller","dart.js_util#_captured_T_1","dart.async#_delegationTarget","storedCallback","declarer.dart#_solo","round","rti#_bind","errorCallback","functions.dart#_captured_V1_3","dart.convert#_allowMalformed","lastIndexOf","expanded.dart#_onError","declarer.dart#_setUpAll","core_matchers.dart#_description","restartable_timer.dart#_callback","metadata.dart#_skip","dart2jsArgs","subscription_stream.dart#_captured_error_1","dart.async#_resultOrListeners","relativeRootPattern","dart.async#_onError","stream_completer.dart#_createController","dart.collection#_previous","dart.async#_setError","file.dart#_isNearCachedLine","wrappers.dart#_setBase","equals_matcher.dart#_compareIterables","add","stream_group.dart#_listenToStream","html_common#_box_0","visitNot","complete","cast","engine.dart#_skippedGroup","type_matcher.dart#_name","dart.core#_errorExplanation","close","highlight","source_maps.parser#_mappings","putIfAbsent","_js_helper#_captured_performance_0","isFinite","runSkipped","isUnicode","addError","toChain","_js_helper#_map","dart.async#_captured_this_1","setUpAll","declarer.dart#_noRetry","spanFor","dart.async#_errorCallback=","dart.dom.html#_captured_onData_0","count","dart.async#_isComplete","dart.async#_captured_span_2","remote_listener.dart#_captured_groups_2","setAll","dart.async#_onValue","setDestinationSink","scanner.dart#_getNext","packageConfigMap","dart.core#_captured_tables_0","writeln","expanded.dart#_printPlatform","_js_helper#_trace","dart.async#_mayResumeInput","invalidValue","dart.async#_recordPause","stack_zone_specification.dart#_captured_T1_3","span_scanner.dart#_scanner","expanded.dart#_bold","file.dart#_start","noMoreLiveTests","dart.dom.html#_unlisten","engine.dart#_runCalled","string_scanner.dart#_position","removeFragment","pool.dart#_released","dart.async#_setValue","firstMatch","dart.async#_captured_originalSource_0","liveSuite","_js_helper#_next","source_maps.parser#_internal","dart.core#_isFile","isLoadSuite","guarantee_channel.dart#_streamController","dart.dom.html#_addEventListener","dart._internal#_endOrLength","resolveUri","_js_helper#_addHashTableEntry","whenTrue","isEmpty","scanner.dart#_multiLineComment","iterable_set.dart#_base","dart.async#_checkState","dart.async#_captured_future_3","dart.async#_inCallback","expanded.dart#_captured_this_0","files","splitMapJoin","toFilePath","internalRemove","toolString","stream_queue.dart#_failClosed","_interceptors#_toListFixed","group.dart#_captured_platform_0","lazy_trace.dart#_captured_this_0","remaining","dart.core#_captured_portStart_1","parser.dart#_conditional","equals_matcher.dart#_match","dart.core#_pathSegments","firstWhere","floor","padLeft","stack_zone_specification.dart#_captured_R_5","trace.dart#_captured_longest_0","onMessage","engine.dart#_addedSuites","dart.core#_captured_host_0","engine.dart#_captured_skipped_1","expanded.dart#_color","stack_zone_specification.dart#_run","dart.core#_mergePaths","getText","declarer.dart#_trace","subscription_stream.dart#_captured_handleError_1","dart.core#_isHttp","expanded.dart#_lastProgressPassed","month","apply","invoker.dart#_captured_outstandingCallbacksForBody_1","dart.async#_badEventState","metadata.dart#_captured_validVariables_0","canonicalizePart","toRadixString","dart.collection#_cell","dart.core#_simpleMerge","remote_listener.dart#_runLiveTest","stream_queue.dart#_addRequest","dart.collection#_removeHashTableEntry","validate","queue_list.dart#_table","future_group.dart#_pending","matchesErrorTest","dart.async#_removeListener","hasErrorTest","expanded.dart#_onDone","dart.async#_onPause","packageConfigUri","expanded.dart#_lastProgressSkipped","engine.dart#_box_0","rti#_check","isRelative","platform_selector.dart#_captured_selector_0","metadata.dart#_retry","_js_helper#_input","nextIteration","expanded.dart#_timeString","pointSpan","variableName","dart.core#_schemeCache","insert","day","lazy_trace.dart#_captured_predicate_1","putIntoMap","live_test_controller.dart#_state","lines","dart.async#_recordCancel","dart.async#_sendError","_js_helper#_newHashTable","removeFirst","pool.dart#_runOnRelease","source_maps.parser#_findColumn","dart.async#_removeListeners","trim","stream_queue.dart#_close","queue_list.dart#_head","_js_helper#_index","isDartVM","stream_sink_completer.dart#_sink","virtualChannel","listeners","dart.core#_host","stream_queue.dart#_subscription","bindCallbackGuarded","containsSeparator","inMinutes","endColumn","stream_channel_completer.dart#_streamCompleter","right","hasAbsolutePath","_js_helper#_re","varData","onComplete","dart.collection#_get","toUri","dart.core#_fragmentStart","suite_channel_manager.dart#_outgoingConnections","hasPort","dart.collection#_modified","runtime","getLine","highlighter.dart#_countTabs","_js_helper#_nativeAnchoredRegExp","dart.async#_waitsForCancel","run","_js_helper#_captured_ex_0","errorZone","foundResult","engine.dart#_onSuiteAddedController","dart.async#_captured_future_2","stream_completer.dart#_setSourceStream","suite_channel_manager.dart#_incomingConnections","declarer.dart#_setUpAlls","getColumn","dart.collection#_element","dart.async#_errorTest","_js_helper#_argumentsExpr","schedule","dart.collection#_captured_result_0","stream_channel_completer.dart#_sinkCompleter","dart.async#_eventScheduled","highlighter.dart#_writeTrailingLines","rootLength","live_suite_controller.dart#_captured_liveTest_1","normalize","invoker.dart#_closableKey","live_test_controller.dart#_controller","isSync","dart.convert#_parent","source","engine.dart#_runLiveTest","dart.async#_isPendingComplete","source_maps.parser#_captured_line_0","copyList","dart.convert#_writeSurrogate","remote_listener.dart#_serializeTest","dart.convert#_fillBuffer","toJson","highlighter.dart#_writeLastLine","addOutstandingCallback","_interceptors#_codeUnitAt","chainFor","~/","dart.collection#_addHashTableEntry","package","isHeadless","completeError","verboseChain","declarer.dart#_parent","stream_group.dart#_subscriptions","listen","describeMismatch","closed","stream_queue.dart#_streamQueue","declarer.dart#_runSetUps","pretty_print.dart#_captured_indent_0","dart.typed_data.implementation#_checkPosition","declarer.dart#_prefix","stream_completer.dart#_linkStreamToController","setSourceStream","targetUrl","_js_helper#_message","inMilliseconds","dart.async#_previous","dart.js_util#_captured__convertedObjects_0","declarer.dart#_entries","dart.async#_setPendingEvents","stack_zone_specification.dart#_captured_node_2","dart._internal#_length","invoker.dart#_guardIfGuarded","done","declarer.dart#_platformVariables","highlighter.dart#_isOnlyWhitespace","isJS","isEof","sourceLine","dart._internal#_f","isBroadcast","invoker.dart#_captured_invoker_0","remote_listener.dart#_box_0","declarer.dart#_tearDowns","dart.async#_close","multi_channel.dart#_nextId","remote_listener.dart#_captured_liveTest_0","engine.dart#_closed","highlighter.dart#_writeText","matchAsPrefix","invoker.dart#_guarded","lazy_trace.dart#_inner","_js_helper#_unlinkCell","live_suite_controller.dart#_failed","stack_zone_specification.dart#_box_0","lazy_chain.dart#_captured_this_0","relativePathToUri","dart.async#_isChained","newJsMap","pool.dart#_allocatedResources","highlighter.dart#_color","dart.async#_mayAddEvent","group.dart#_map","multi_channel.dart#_captured_this_1","dart.collection#_computeHashCode","dart.async#_complete","dart.async#_captured_result_2","dart.async#_captured_e_1","null_stream_sink.dart#_captured_this_0","remote_listener.dart#_captured_printZone_0","dart.async#_isAddingStream","dart.collection#_newLinkedCell","_interceptors#_shrReceiverPositive","fragment","dart.async#_sendData","dart.dom.html#_pauseCount","runUnary","dart.convert#_upgradedMap","scanner.dart#_scanner","precompiledPath","dart.dom.html#_target","dart.core#_hashCodeCache","runGuarded","span_scanner.dart#_lastSpan","toList","metadata.dart#_verboseTrace","dart.async#_whenCompleteAction","replaceAllMapped","rti#_as","invoker.dart#_captured_counter_3","_js_helper#_nativeGlobalRegExp","declarer.dart#_soloEntries","addSubscription","increment","stack_zone_specification.dart#_captured_R_4","pool.dart#_onResourceReleased","dart.collection#_strings","dart.async#_handle","hasListener","dart.async#_ensureDoneFuture","stack_zone_specification.dart#_handleUncaughtError","remote_listener.dart#_captured_printZone_1","invoker.dart#_invokerZone","_js_helper#_captured_transform_1","pause","runUnaryGuarded","spanFrom","runner_suite.dart#_config","runner_suite.dart#_onClose","dart.async#_zone","stream_sink_completer.dart#_controller","highlighter.dart#_captured_textInside_1","[]","expanded.dart#_lastProgressMessage","invoker.dart#_captured_fn_2","lastPendingEvent","inMicroseconds","visitConditional","dart._internal#_index","stream_sink_completer.dart#_doneCompleter","inSeconds","live_test_controller.dart#_onStateChangeController","rti#_cachedRuntimeType","dart.async#_captured_controller_0","packageResolver","dart.async#_captured_eagerError_2","stack_zone_specification.dart#_captured_T2_4","live_test_controller.dart#_onClose","live_test_controller.dart#_groups","dart.core#_duration","file.dart#_decodedChars","parents","parent","_js_helper#_jsObject","dart.async#_captured_test_0","stream_group.dart#_state","startsWith","dart.collection#_set","absolute","foreign","dart.async#_hasError","merge","handleValue","resolve","rti#_message","stream_queue.dart#_updateRequests","dart.async#_delegateCache","hasFragment","traces","isScheduled","union_set.dart#_iterable","invoker.dart#_onCloseCompleter","isNotEmpty","test.dart#_captured_body_0","hasScheme","engine.dart#_closedBeforeDone","span_exception.dart#_span","dart.async#_captured_cleanUp_1","dart._internal#_source","fuse","live_suite_controller.dart#_suite","invoker.dart#_runTearDowns","dart.async#_captured_elements_0","addStream","rti#_precomputed3","null_stream_sink.dart#_checkEventAllowed","chain.dart#_captured_terse_0","patterns","stream_completer.dart#_setEmpty","dart.core#_fragment","createTimer","variables","runner_suite.dart#_onDebuggingController","dart.async#_captured_protected_0","every","trace.dart#_captured_trace_0","perform","dart.async#_captured_bodyFunction_0","dart.convert#_allowInvalid","pool.dart#_captured_this_0","outputId","dart.async#_onResume","dart.convert#_extraUnits","toUpperCase","equals_matcher.dart#_value","dart.async#_controller","multi_channel.dart#_captured_this_0","engine.dart#_group","guarantee_channel.dart#_addStreamSubscription","queue_list.dart#_add","forEachJsField","_js_helper#_regExp","_js_helper#_nums","_js_helper#_getTableBucket","dart.convert#_computeKeys","stack_trace_mapper.dart#_mapping","millisecondsSinceEpoch","_js_helper#_cell","connectOut","union_set.dart#_sets","engine.dart#_onUnpaused","_js_helper#_genericClosure","stack_trace_mapper.dart#_mapContents","pretty_print.dart#_captured_indent_2","multi_channel.dart#_innerStreamSubscription","substring","entries","multi_channel.dart#_inner","hasRun","stack_zone_specification.dart#_onError","elapsedTicks","engine.dart#_onTestStartedGroup","tearDownAll","core_matchers.dart#_matcher","expanded.dart#_engine","dart.async#_captured_future_0","_js_helper#_captured_getTag_0","names","internalContainsKey","dart.async#_captured_start_2","dart.async#_addStreamState","stream_queue.dart#_extractStream","setState","clear","dart.core#_stop","stream_group.dart#_closed","os","hasPartialInput","dart.collection#_getBucket","declarer.dart#_timeout","parts","context.dart#_pathDirection","findSlot","dart.async#_scheduleMicrotask","engine.dart#_loadPool","stream_sink_completer.dart#_canSendDirectly","local","hour","packageRoot","scanner.dart#_endOfFileEmitted","dart.async#_captured_callback_0","chain.dart#_captured_terse_1","future_group.dart#_closed","dart.convert#_value","readSlot","fork","elementAt","dart.async#_runUnary","writeAll","dart.async#_captured_callback_3","stack_zone_specification.dart#_captured_arg_1","writeSlot","dart.async#_next","rti#_hashCode","stream_group.dart#_onListen","dart.async#_captured_sourceResult_2","runOnce","dart.convert#_reviver","invoker.dart#_captured_this_1","innerStream","lazy_chain.dart#_thunk","stream_queue.dart#_ensureListening","stack_zone_specification.dart#_chains","dart.async#_captured_listener_1","startColumn","status","dart.async#_removeAfterFiring","multi_channel.dart#_box_0","dart.dom.html#_eventType","dart.collection#_head","resume","_js_helper#_removeHashTableEntry","_js_helper#_match","dart.async#_isFiring","includeTags","_interceptors#_current=","intersection_selector.dart#_selector2","rti#_rti","dart.async#_asyncComplete","request","expanded.dart#_gray","stack_trace_formatter.dart#_except","engine.dart#_subscriptions","subscription_stream.dart#_source","stack_trace_mapper.dart#_sdkRoot","dart.async#_recordResume","scheme","dart.convert#_expectedUnits","source_maps.parser#_captured_column_0","dart.collection#_closeGap","highlighter.dart#_buffer","sink.dart#_sink","map","parser.dart#_scanner","rti#_bindCache","dart._internal#_name","stack_trace_formatter.dart#_only","removeEventListener","_js_helper#_setTableEntry","live_test_controller.dart#_close","dart.core#_queryParameters","_js_helper#_length","engine.dart#_captured_this_1","pretty_print.dart#_box_0","addMapping","description.dart#_out","dart.async#_captured_R_3","dart.async#_isClosed","flush","remote_listener.dart#_captured_getMain_1","expanded.dart#_onStateChange","functions.dart#_captured_K1_2","toLowerCase","heartbeat","registerBinaryCallback","_js_helper#_method","dart.collection#_writeToList","contains","removeOutstandingCallback","functions.dart#_captured_value_1","dart.async#_prependListeners","dart.core#_data","chain.dart#_captured_callback_0","guarantee_channel.dart#_inner","dart.async#_fork","_js_helper#_nextIndex","dart.core#_captured_uri_0","source_maps.parser#_maps","dart.convert#_bufferIndex","expanded.dart#_red","dart.collection#_unlinkCell","forEachObjectKey","isRootRelative","engine.dart#_restarted","platform_selector.dart#_captured_validVariables_1","dart.async#_doneFuture","dart.convert#_original","dart.async#_registerCallback=","foldFrames","remote_listener.dart#_captured_channel_3","live_test_controller.dart#_onMessageController","separatorPattern","dart.convert#_isFirstCharacter","stack_zone_specification.dart#_errorZone","addStreamFuture","declarer.dart#_built","rti#_requiredPositional","dart.async#_captured_test_2","dart.collection#_table","_js_helper#_deleteTableEntry","split","group.dart#_captured_callback_0","remote_listener.dart#_listen","source_maps.parser#_mapUrl","validatePlatformSelectors","dart.async#_map","hasEmptyPath","sublist","stream_completer.dart#_stream","invoker.dart#_onRun","dart.async#_subscribe","util.dart#_captured_x_0","stream_completer.dart#_sourceStream","metadata.dart#_chainStackTraces","stream_sink_completer.dart#_setDestinationSink","addTearDownAll","live_suite_controller.dart#_isComplete","dart.async#_captured_result_0","equals_matcher.dart#_captured_expectedElement_1","package_config_resolver.dart#_uri","dart.async#_reverseListeners","dart.collection#_last","invoker.dart#_captured_timeout_0","walk","dart.core#_userInfo","formatStackTrace","remove","dart.async#_captured_listener_2","_js_helper#_keys","dart.convert#_encoder","runBinary","dart.async#_cancelFuture","future_group.dart#_captured_this_0","handlesComplete","trace.dart#_box_0","dart.async#_captured_pos_1","invoker.dart#_test","metadata.dart#_captured_timeout_2","guarantee_channel.dart#_box_0","cancelSchedule","sourceNameId","runtimeType","dart.collection#_modifications","then","pretty_print.dart#_captured_maxLineLength_1","dart.convert#_subsetMask","testRandomizeOrderingSeed","visitOr","expanded.dart#_lastProgressFailed","dart.convert#_first","millisecond","highlighter.dart#_captured_this_1","dart.async#_rootRegisterUnaryCallback","dart.async#_captured_f_1","remote_listener.dart#_captured_this_0","reversed","dart.core#_queryParameterLists","hasErrorCallback","metadata.dart#_captured_testOn_1","left","live_test_controller.dart#_isClosed","highlighter.dart#_captured_this_0","dart.dom.html#_start","lazy_chain.dart#_chain","null_stream_sink.dart#_addingStream","_js_helper#_getTableCell","forTarget","source_map_stack_trace.dart#_captured_minified_2","peekChar","dart.collection#_next","build","dart.convert#_process","rti#_precomputed2","lastMatch","expanded.dart#_description","metadata.dart#_captured_chainStackTraces_5","remote_listener.dart#_captured_printZone_5","decoder","hasAuthority","unaryOnError","context.dart#_needsNormalization","onResume","expanded.dart#_printPath","_interceptors#_tdivSlow","_js_helper#_rest","expanded.dart#_paused","declarer.dart#_tearDownAll","dart.async#_captured_result_3","lazy_trace.dart#_thunk","waitForOutstandingCallbacks","dart.async#_mayComplete","dart.async#_captured_T_5","function","dart.collection#_offset","dart.async#_captured_value_1","bindUnaryCallbackGuarded","dart.async#_sendDone","invoker.dart#_outstandingCallbacks","extensions","dart.async#_closeUnchecked","_interceptors#_toListGrowable","highlighter.dart#_captured_end_2","invoker.dart#_captured_this_0","codeUnits","rti#_precomputed1","stack_zone_specification.dart#_captured_f_1","internalGet","suite_channel_manager.dart#_names","pattern","dart.async#_captured_stackTrace_1","live_suite_controller.dart#_liveSuite","source_maps.parser#_consumeNewLine","metadata.dart#_box_0","suiteSink","dart.core#_port","engine.dart#_passedGroup","dart.core#_hostStart","context.dart#_isWithinOrEquals","expanded.dart#_captured_liveTest_1","live_suite_controller.dart#_closeMemo","dart.async#_captured_target_0","dart.core#_captured_host_1","dart.core#_uriCache","_js_helper#_nativeAnchoredVersion","scanner.dart#_consumeWhitespace","scanner.dart#_scanOr","dart.dom.html#_tryResume","runner_suite.dart#_suite=","toSet","chain.dart#_captured_level_1","sourceColumn","dart.async#_nextListener","connectIn","_js_helper#_isCaseSensitive","invoker.dart#_body","encoder","metadata","dart.async#_isInputPaused","inHours","allowRelease","_js_helper#_captured_getUnknownTag_0","invoker.dart#_completer","intersection","state","dart.async#_state","reportLiveTest","dart.async#_clearPendingComplete","invoker.dart#_captured_timeout_2","stack_trace_mapper.dart#_mapUrl","multi_channel.dart#_controllers","declarer.dart#_tearDownAllTrace","chain.dart#_captured_T_1","highlighter.dart#_box_0","multi_channel.dart#_captured_T_2","expanded.dart#_subscriptions","dart.collection#_captured_V_2","stack_zone_specification.dart#_captured_original_1","subscription_stream.dart#_captured_this_0","stream_queue.dart#_captured_this_0","live_test_controller.dart#_runCalled","group.dart#_testCount","onDone","dart.async#_isInitialState","isEven","_js_helper#_types","root","highlighter.dart#_writeIntermediateLines","library","dart.core#_hasValue","member","dart.async#_lastSubscription=","dartException","dart.core#_schemeEnd","_js_helper#_captured_this_0","isPosix","dart._internal#_hasSkipped","dart.convert#_isUpgraded","dart.async#_print=","dart.async#_rootRegisterBinaryCallback","dart.dom.html#_useCapture","test.src.runner.browser.post_message_channel#_captured_port_0","type","scanner.dart#_scanIdentifier","dart.async#_onDone","origin","multi_channel.dart#_parent","%","_js_helper#_keysArray","span_scanner.dart#_sourceFile","metadata.dart#_captured_skip_3","insertAll","platform_selector.dart#_inner","pretty_print.dart#_captured_pp_0","engine.dart#_captured_this_0","dart.async#_eventState","child","forTag","guarantee_channel.dart#_channel","dart.async#_captured_iterator_0","checkMutable","remote_listener.dart#_captured_controller_3","replaceFirst","file.dart#_binarySearch","transform","stack_trace_formatter.dart#_mapper","_interceptors#_tdivFast","trace.dart#_captured_oldPredicate_0","_js_helper#_exception","stack_zone_specification.dart#_captured_arg2_2","remote_listener.dart#_suite","isIdentifier","rti#_primary","removeAt","dart.async#_captured_div_1","dart._internal#_current=","_js_helper#_current=","dart.dom.html#_removeEventListener","rti#_optionalNamed","dart.async#_isSent","_js_helper#_receiver","forPlatform","dart.async#_delegate","firstPendingEvent","inSameErrorZone","frames","highlighter.dart#_span","remote_listener.dart#_captured_channel_2","dart._internal#_currentExpansion","union_set_controller.dart#_sets","dart.async#_captured_this_0","_js_helper#_isUnicode","lazy_trace.dart#_captured_terse_2","span_exception.dart#_source","dart._internal#_start","_js_helper#_modifications","dart.core#_nextPosition","dart.convert#_toEncodable","hasMatch","dart.async#_canFire","postMessage","internalComputeHashCode","invoker.dart#_outstandingCallbackZones","invoker.dart#_captured_zone_1","rootPattern","multi_channel.dart#_captured_id_1","platform_selector.dart#_span","isUtc","dart.dom.html#_postMessage_2","set","pathFromUri","dart.async#_hasOneListener","engine.dart#_activeLoadTests","_js_helper#_containsTableEntry","restartable_timer.dart#_timer","dart.async#_pendingEvents","guarantee_channel.dart#_addError","_js_helper#_captured_prototypeForTag_0","dart.async#_nullErrorHandler","dart.async#_captured_cleanUp_3","+","dart.async#_chainSource","dart.core#_portStart","remote_listener.dart#_printZone","multi_channel.dart#_captured_T_1","frame.dart#_captured_frame_0","source_maps.parser#_columnStart","functions.dart#_captured_result_0","engine.dart#_addLiveSuite","_js_helper#_pattern","guarantee_channel.dart#_onStreamDisconnected","dart.core#_stackTrace","elapsed","accept","dart.async#_subscription","stack_trace_mapper.dart#_packageResolver","stream_queue.dart#_eventsReceived","_js_helper#_isMultiLine","live_test_controller.dart#_errors","_interceptors#_index","onZero","chain.dart#_captured_chain_0","engine.dart#_runSkippedTest","pretty_print.dart#_captured__prettyPrint_1","removeAll","stack_zone_specification.dart#_captured_arg1_1","dart.async#_callOnCancel","live_suite_controller.dart#_onCompleteGroup","last","runner_suite.dart#_channelNames","sourceUrl","dart.async#_onListen","pool.dart#_resetTimer","engine.dart#_liveSuites","stream_channel_completer.dart#_set","file.dart#_end","dart.async#_captured_value_2","runner_suite.dart#_gatherCoverage","dart.core#_isHttps","dart.collection#_captured_result_1","multi_channel.dart#_closedIds","remote_listener.dart#_captured_channel_0","isNewLine","invoker.dart#_runCount","union_set.dart#_captured_this_0","suite.dart#_runSkipped","live_suite_controller.dart#_skipped","stack_zone_specification.dart#_captured_R_2","dart.core#_isPackage","dart.async#_expectsEvent","metadata.dart#_validateTags","copy","invoker.dart#_captured_error_2","dart.async#_addPending","dart.convert#_stringSink","remainder","guarantee_channel.dart#_inAddStream","pool.dart#_captured_registered_1","runtime.dart#_captured_serialized_0","pool.dart#_onReleaseCompleters","functions.dart#_captured_result_1","inGoogle","runBinaryGuarded","guarantee_channel.dart#_allowErrors","declarer.dart#_captured_body_0","dart.async#_createSubscription","condition","checkGrowable","absolutePathToUri","suite.dart#_runtimes","engine.dart#_captured_loadResource_2","dart.collection#_rest","dart.async#_setRemoveAfterFiring","guarantee_channel.dart#_sink","metadata.dart#_captured_retry_6","context.dart#_current","dart.async#_registerBinaryCallback=","stream_completer.dart#_controller","isCore","highlighter.dart#_captured_line_1","getOffset","dart.async#_createPeriodicTimer","pool.dart#_timeout","mustCopy","dart.async#_firstSubscription","scanner.dart#_next","onTestStarted","scanner.dart#_scanAnd","dart.async#_once","dart.core#_query","config","dart.async#_future","next","style","invoker.dart#_tearDowns","_js_helper#_getBucket","expanded.dart#_stopwatch","engine.dart#_active","dart.async#_rootRun","dart.async#_guardCallback","live_suite_controller.dart#_onTestStartedController","path","dart.async#_target","functions.dart#_captured_K2_0","suite.dart#_knownTags","dart.async#_tick","pool.dart#_onReleaseCallbacks","remote_listener.dart#_captured_suite_0","dart.core#_pathStart","platform_selector.dart#_captured_platform_0","restartable_timer.dart#_duration","test.src.runner.browser.post_message_channel#_captured_portSubscription_1","guarantee_channel.dart#_captured_this_0","setEmpty","dart.typed_data.implementation#_invalidPosition","dart.collection#_containsKey","string_scanner.dart#_lastMatchPosition","metadata.dart#_captured_onPlatform_8","lazy_chain.dart#_captured_predicate_1","dart.async#_addListener","multi_channel.dart#_mainController","guarantee_channel.dart#_captured_this_1","invoker.dart#_box_0","_interceptors#_length","nextKind","dart.collection#_box_0","guarantee_channel.dart#_subscription","addTo","dart.core#_uri","isDone","dart.async#_stateData","setChannel","dart.async#_captured_R_2","stream_channel_completer.dart#_channel=","runes","dart.core#_jsWeakMapOrKey","dart.collection#_queue","null_stream_sink.dart#_closed","file.dart#_lineStarts","stream_queue.dart#_eventQueue","isSeparator","_js_helper#_arguments","guarantee_channel.dart#_disconnected","span_with_context.dart#_context","stream_group.dart#_captured_stream_1","source_maps.parser#_indexFor","dart.async#_cancelOnError","rest","rti#_rest","dart.async#_captured_stackTrace_2","stream_subscription.dart#_source","dart.core#_toFilePath","sourceUrlId","_interceptors#_shrOtherPositive","guarantee_channel.dart#_closed","future_group.dart#_onIdleController","dart.core#_value","dart.async#_captured_error_1","writeCharCode","declarer.dart#_tearDownAlls","source_map_stack_trace.dart#_captured_sourceMap_1","_js_helper#_self","onStateChange","invoker.dart#_timeoutTimer","currentChain","print_sink.dart#_buffer","live_test_controller.dart#_suite","string","engine.dart#_captured_liveTest_1","isBrowser","engine.dart#_suiteController","rti#_canonicalRecipe","dart.dom.html#_canceled","_js_helper#_nativeGlobalVersion","dart.async#_pending","queue_list.dart#_tail","dart.async#_createTimer","passed","dart.async#_onData","dart.async#_captured_action_1","declarer.dart#_captured_body_1","stream_group.dart#_captured_this_0","remote_listener.dart#_captured_liveTest_1","remote_listener.dart#_captured_beforeLoad_4","invoker.dart#_printsOnFailure","dart.core#_writeAuthority","pool.dart#_onTimeout","startChunkedConversion","handleWhenComplete","guarantee_channel.dart#_addStreamCompleter","dart.collection#_captured_K_1","inputId","cloneNotRequired","first","shuffle","engine.dart#_pauseCompleter","newJsList","dart.async#_registerUnaryCallback=","key","_js_helper#_first","dart.async#_captured_T_1","name","dart.dom.html#_postMessage_1","dart.collection#_keys","onPause","dart.async#_captured_data_1","hasQuery","dart.collection#_nums","dart.async#_setErrorObject","dart.collection#_source","handlesValue","stack_zone_specification.dart#_captured_R_3","remote_listener.dart#_captured_channel_1","seen","lazy_chain.dart#_inner","intersection_selector.dart#_selector1","source_maps.parser#_consumeNewSegment","dart.convert#_urlSafe","input","subscription_stream.dart#_captured_stackTrace_2","isRunning","trace.dart#_captured_level_1","impl.dart#_selector","stream_queue.dart#_pause","dart.core#_isScheme","parsed_path.dart#_captured_this_0","declarer.dart#_captured_this_0","stream_completer.dart#_isSourceStreamSet","stream_channel_controller.dart#_local","length","separator","stack_zone_specification.dart#_captured_T_3","subscription_stream.dart#_captured_handleError_0","dart.async#_setChained","expanded.dart#_yellow","equals_matcher.dart#_captured_location_2","cleanupSlots","equals_matcher.dart#_captured_depth_3","suite.dart#_jsTrace","dart.async#_captured_dispatch_1","dart.collection#_end","equals_matcher.dart#_captured_matcher_0","dart.collection#_modificationCount","dart.convert#_processed","pool.dart#_timer","dart.core#_writeString","metadata.dart#_captured_platform_1","string_scanner.dart#_fail","isClosed","keys","isPaused","test_core#_captured_engine_0","declarer.dart#_setUps","expanded.dart#_sink","dart.collection#_grow","text","live_test_controller.dart#_onErrorController","dart.core#_text","dart._internal#_captured_this_0","handlesError","dart.core#_contents","dart.async#_captured_milliseconds_1","source_map_stack_trace.dart#_captured_sdkLib_3","dart.core#_initializeText","chain.dart#_captured_trace_0","rti#_evalCache","equals_matcher.dart#_limit","dart.async#_toggleEventId","live_suite_controller.dart#_active","stack_zone_specification.dart#_createNode","toSpec","userInfo","excludeTags","dart.core#_separatorIndices","test.dart#_captured_completer_1","rti#_is","dart.async#_isUsed","highlighter.dart#_paddingAfterSidebar","code","sink","metadata.dart#_captured_skipReason_7","stream_sink_completer.dart#_destinationSink","future_group.dart#_values","suite.dart#_metadata","engine.dart#_addLoadSuite","invoker.dart#_captured_message_1","values","_js_helper#_nativeRegExp","validator.dart#_isDefined","stream_queue.dart#_isDone","_js_helper#_isDotAll","offset","putIntoObject","copies","dart.async#_runBinary","_js_helper#_start","stream_queue.dart#_source","year","stream_queue.dart#_requestQueue","$le","$indexSet","$index","$xor","$or","$eq","$mod","$shr","$and","$ge","$gt","$lt","$mul","$not","$shl","$div","$sub","$add","$negate","$tdiv","checkString","instanceTypeName","constructorNameFallback","isJsArray","getIndex","selfFieldName","receiverFieldName","_rtiEval","extractFunctionTypeObjectFrom","rawRtiToJsConstructorName","isGenericFunctionTypeParameter","isDartFunctionType","isDartFutureOrType","isNotIdentical","_instanceFunctionType","instanceOf","invoke","setDispatchProperty","propertyGet","regExpGetGlobalNative","stringReplaceJS","checkNull","regExpGetNative","_getFutureOrArgument","_lookupFutureRti","_setPrecomputed1","_getBindCache","_setBindCache","_getGenericFunctionBase","_getKind","_lookupStarRti","_canonicalRecipeOfStar","_Universe._lookupStarRti","_lookupQuestionRti","_canonicalRecipeOfQuestion","_Universe._lookupQuestionRti","_lookupFutureOrRti","_canonicalRecipeOfFutureOr","_Universe._lookupFutureOrRti","_getInterfaceName","_getBindingBase","_getReturnType","_getGenericFunctionParameterIndex","asString","allocate","_setRequiredPositional","_setOptionalPositional","_setOptionalNamed","_setCachedRuntimeType","_setTypeCheckFunction","_setAsCheckFunction","_getPrimary","_setSpecializedTestResource","_setIsTestFunction","isLegacySubtype","_getSpecializedTestResource","_getStarArgument","_getQuestionArgument","_lookupErasedRti","_getEvalCache","_setEvalCache","_cacheSet","_createTerminalRti","_setKind","_setCanonicalRecipe","_createUnaryRti","_setPrimary","_createGenericFunctionParameterRti","_canonicalRecipeOfInterface","_createInterfaceRti","_setRest","_canonicalRecipeOfBinding","_createBindingRti","_canonicalRecipeOfFunction","_canonicalRecipeOfFunctionParameters","_createFunctionRti","_canonicalRecipeOfGenericFunction","_createGenericFunctionRti","charCodeAt","toGenericFunctionParameter","_lookupDynamicRti","_lookupVoidRti","pushStackFrame","push","setPosition","handleTypeArguments","collectArray","arraySplice","handleFunctionArguments","handleOptionalGroup","handleNamedGroup","collectNamed","isDigit","evalTypeVariable","_lookupNeverRti","_lookupAnyRti","_castToRti","stringLessThan","functionParametersEqual","lookupInterceptorByConstructor","cacheInterceptorOnConstructor","_future","_setValue","_isComplete","_setPendingComplete","_mayComplete","_mayAddListener","_chainSource","_setChained","_hasError","_error","_zone","_removeListeners","_cloneResult","_setErrorObject","_scheduleImmediate","_leave","_createPeriodicTimer","printToConsole","es6","tryParse","objectToHumanReadableString","makeListFixedLength","makeFixedListUnmodifiable","_stringFromJSArray","_stringFromUint8List","_writeOne","_startsWithData","_checkLength","_internal","_stringOrNullLength","_writeString","_isZoneIDChar","_isRegNameChar","_isGeneralDelimiter","_isSchemeCharacter","_isUnreservedChar","fromString","_lineStarts","fromList","_incomingConnections","_outgoingConnections","_names","_requestedResources","_onReleaseCallbacks","_onReleaseCompleters","_closeMemo","_completer","AsyncMemoizer._completer","factor","_group","_values","FutureGroup._completer","_suiteController","_onTestStartedGroup","_state","_subscriptions","StreamGroup._subscriptions","_passedGroup","_skippedGroup","_failedGroup","_active","_addedSuites","_onSuiteAddedController","Engine._onSuiteAddedController","_liveSuites","_onSuiteStartedController","Engine._onSuiteStartedController","_restarted","_activeLoadTests","_sets","_errors","LiveTestController.completer","_onStateChangeController","LiveTestController._onStateChangeController","_onErrorController","LiveTestController._onErrorController","_onMessageController","LiveTestController._onMessageController","serializeSuite","_closable","_out","myInlinedMethod","_lineStart","_columnStart","_maps","_mappings","_setUps","_tearDowns","_setUpAlls","_timeout","_tearDownAlls","_entries","_soloEntries","_isTextAtEndOfContext","_chains","_createKey","_currentSpec","_createNode","withGuarantees","_child","_onCompleteGroup","_onCloseCompleter","LiveSuiteController._onCloseCompleter","_onTestStartedController","LiveSuiteController._onTestStartedController","_passed","_skipped","_failed","_toListGrowable","_mainController","_controllers","_pendingIds","_closedIds","Window.onMessage","jsify","listToString","_handleIEtoString","_codeUnitAt","_currentExpansion","_types","_getBucket","_isMultiLine","_isUnicode","_isTrailSurrogate","_rtiBind","_addListener","_isFiring","_setRemoveAfterFiring","_isEmpty","_isAddingStream","_expectsEvent","_hasOneListener","_errorTest","_onError","thenAwait","_setError","_isPendingComplete","_clearPendingComplete","_whenCompleteAction","_onValue","_isInitialState","_mayAddEvent","_isCanceled","_isPaused","_isClosed","_isInputPaused","_hasPending","_inCallback","_waitsForCancel","_eventScheduled","_isScheduled","_rethrow","_hasTableEntry","identityHashCode","checkValidIndex","_grow","_checkModification","_isUpgraded","parseHexByte","withBufferSize","unary-","_microseconds","_checkType","_getFromObject","_setOnObject","_now","_isWindows","_toFilePath","_initializeText","_writeAuthority","_isPackage","convertDartToNative_SerializedScriptValue","_canceled","fromMillisecondsSinceEpoch","isJavaScriptSimpleObject","_isSourceStreamSet","_setSourceStream","_NextRequest._completer","_pause","_close","_setEmpty","_scanOr","_scanAnd","_scanIdentifier","_setBase","StringDescription.add","addStateInfo","_indent","reset","_onResourceReleased","_consumeValue","glyphs","_paddingAfterSidebar","_normalizeContext","_buffer","Highlighter._","dataFromString","_disabled","_doneCompleter","_GuaranteeSink._doneCompleter","_inAddStream","MessageEvent.data","_prefix","_solo","Declarer._solo","Invoker._onCloseCompleter","_closableKey","_outstandingCallbackZones","_counterKey","_printsOnFailure","_AsyncCounter._completer","_guardIfGuarded","_print","_run","jsonDecode","_except","_only","_MultiChannel.stream","_eventQueue","_requestQueue","ascii","_sink","_listen","_streamCompleter","_stream","_sinkCompleter","markGrowable","_timeString","_local","_channelNames","watch","ExpandedReporter.watch","_stopwatch","ExpandedReporter._stopwatch","_initTicker","Engine.onTestStarted","provokeCallErrorOnNull","provokeCallErrorOnUndefined","provokePropertyErrorOnNull","provokePropertyErrorOnUndefined"],"mappings":"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","x_org_dartlang_dart2js":{"minified_names":{"global":"main_closure,2397,internalBootstrapBrowserTest,535,Closure_fromTearOff,2398,StaticClosure,2399,BoundClosure,2400,Closure_functionCounter,2401,Closure_forwardCallTo,2402,Closure__computeSignatureFunctionNewRti,2403,_checkStringNullable,181,wrapException,42,CyclicInitializationError,2404,toStringWrapper,43,NullThrownError,2405,S,12,argumentErrorValue,40,ArgumentError,395,Error_safeToString,2406,_isBool,168,Error__objectToString,2407,Closure,2408,Primitives_objectTypeName,2409,Primitives__objectTypeNameNewRti,2410,Object,2411,instanceType,145,_rtiToString,184,Primitives__saneNativeClassName,2412,assertHelper,79,_unminifyOrTag,186,Rti__getInterfaceTypeArguments,2413,_rtiArrayToString,182,_functionRtiToString,90,Rti__getGenericFunctionBounds,2414,ioore,37,diagnoseIndexError,38,_isInt,173,_checkIntNullable,175,iae,36,IndexError$,2415,RangeError$value,2416,_checkNumNullable,178,RangeError,398,IndexError,404,setRuntimeTypeInfo,83,isTopType,243,Rti__getFunctionParameters,2417,ArgumentError$value,2416,_arrayInstanceType,147,UnsupportedError$,2415,throwExpression,44,UnsupportedError,405,unmangleGlobalNameIfPreservedAnyways,246,assertTest,77,AssertionError$,2415,AssertionError,394,TypeErrorImplementation$,2415,TypeErrorImplementation,75,_typeDescription,76,extractFunctionTypeObjectFromInternal,74,runtimeTypeToString,86,_runtimeTypeToString,87,unminifyOrTag,10,_joinArguments,92,_functionRtiToString0,90,extractKeys,245,JSArray_JSArray$markFixed,2418,JSArray,2419,JSArray_markFixedList,2420,StringBuffer,2421,_checkBoolNullable,170,getIsolateAffinityTag,82,IterableBase_iterableToFullString,2422,_isToStringVisiting,357,_toStringVisiting,2423,StringBuffer__writeAll,2424,IterableElementError_noElement,2425,StateError,407,ArrayIterator,2426,throwConcurrentModificationError,45,ConcurrentModificationError$,2415,ConcurrentModificationError,408,ListIterator,2427,ListMixin,2428,_checkValidIndex,124,Iterable,2429,initNativeDispatchFlag,2430,initNativeDispatch,104,UnimplementedError$,2415,lookupAndCacheInterceptor,99,getTagFunction,2431,dispatchRecordsForInstanceTags,2432,interceptorsForUncacheableTags,2433,alternateTagFunction,2434,makeLeafDispatchRecord,102,patchInteriorProto,101,makeDispatchRecord,248,JavaScriptIndexingBehavior,2435,UnimplementedError,406,initNativeDispatchContinue,105,initHooks,107,prototypeForTagFunction,2436,makeDefaultDispatchRecord,103,applyHooksTransformer,108,initHooks_closure,2437,initHooks_closure0,2437,initHooks_closure1,2437,_TypeError__TypeError$forType,2438,_TypeError,2439,_Error_compose,2440,_CastError__CastError$forType,2438,_CastError,2441,instanceOrFunctionType,144,_TypeError$fromMessage,2442,Rti__isUnionOfFunctionType,2443,closureFunctionType,143,getTypeFromTypesTable,151,_Universe_eval,2444,_Universe__parseRecipe,2445,_Parser_create,2446,_Parser_parse,2447,_Parser_handleDigit,2448,_Parser_handleIdentifier,2449,_Parser_toType,2450,_Universe__lookupGenericFunctionParameterRti,2451,_Universe__lookupTerminalRti,2452,_Parser_toTypes,2453,_Universe__lookupInterfaceRti,2454,_Universe__lookupGenericFunctionRti,2455,_Universe__lookupBindingRti,2456,_Parser_handleExtendedOperations,2457,assertThrow,78,_Universe__lookupUnaryRti,2458,_FunctionParameters,2459,_Universe__lookupFunctionRti,2460,_Parser_toTypesNamed,2461,_Universe__canonicalRecipeJoin,2462,_Universe__canonicalRecipeJoinNamed,2463,Rti,2464,_Universe__finishRti,2465,_generalTypeCheckImplementation,159,_generalAsCheckImplementation,158,_installSpecializedIsTest,154,_generalIsTestImplementation,156,_isTop,166,_asTop,167,int,2466,double,2467,_isNum,176,num,2468,String,2469,_isString,179,bool,2470,isLegacyTopType,242,_isTestViaProperty,157,_AssertionError,2471,Rti__getBindingArguments,2472,_Parser_indexToType,2473,_Universe_findRule,2474,Rti__getCanonicalRecipe,2475,_Universe_evalInEnvironment,2476,_CastError$fromMessage,2442,_isSubtype,233,Rti__getFutureFromFutureOr,2477,typesEqual,240,_isFunctionSubtype,236,_isInterfaceSubtype,237,typeEqual,238,namedTypesEqual,241,Future,272,_Universe_bind,2478,_instanceTypeFromConstructor,149,_instanceTypeFromConstructorMiss,150,_Universe_findErasedType,2479,BoundClosure_evalRecipeIntercepted,2480,BoundClosure_evalRecipe,2481,Closure_forwardInterceptedCallTo,2482,Closure_cspForwardCall,2483,BoundClosure_selfFieldNameCache,2484,BoundClosure_computeFieldNamed,2485,BoundClosure_selfOf,2486,BoundClosure_receiverFieldNameCache,2487,Closure_cspForwardInterceptedCall,2488,BoundClosure_receiverOf,2489,RuntimeError$,2415,RuntimeError,81,getRuntimeTypeInfo,84,substitute,95,invokeOn,97,internalBootstrapBrowserTest_closure,2490,RemoteListener_start,2491,postMessageChannel,631,StreamChannel,2257,_ControllerStream,2492,_instanceType,148,_Future,265,Zone__current,2493,Stream_length_closure,1045,Stream_length_closure0,1045,Null,2494,Stream,2495,AsyncError,2496,_Future__propagateToListeners,2497,_Future__propagateToListeners_handleWhenCompleteCallback,2498,_Future__propagateToListeners_handleValueCallback,2499,_Future__propagateToListeners_handleError,2500,_Future__chainCoreFuture,2501,_Future__prependListeners_closure,2502,boolConversionCheck,73,unwrapException,51,getTraceFromException,52,ExceptionAndStackTrace,2503,_StackTrace,2504,unwrapException_saveStackTrace,2505,JsNoSuchMethodError$,2415,NullError$,2415,UnknownJsTypeError,2506,StackOverflowError,2507,TypeErrorDecoder_extractPattern,2508,quoteStringForRegExp,114,TypeErrorDecoder,2509,TypeErrorDecoder_provokePropertyErrorOn,2510,TypeErrorDecoder_provokeCallErrorOn,2511,NullError,49,JsNoSuchMethodError,50,_Future__propagateToListeners_handleWhenCompleteCallback_closure,2512,_registerErrorHandler,297,_FutureListener,2513,_rootScheduleMicrotask,331,_scheduleAsyncCallback,300,_RootZone_bindCallback_closure,1244,_RootZone_bindCallbackGuarded_closure,2514,_rootRun,324,_rootHandleUncaughtError,323,_rootHandleUncaughtError_closure,2515,_schedulePriorityAsyncCallback,301,_nextCallback,2516,_lastPriorityCallback,2517,_lastCallback,2518,_AsyncCallbackEntry,2519,Zone__enter,2520,_isInCallbackLoop,2521,_microtaskLoop,298,_AsyncRun__initializeScheduleImmediate,2522,_AsyncRun__initializeScheduleImmediate_internalCallback,2523,convertDartClosureToJS,59,_AsyncRun__initializeScheduleImmediate_closure,2524,Timer__createTimer,2525,Duration_toString_twoDigits,2526,Duration,392,Duration_toString_sixDigits,2527,_TimerImpl$,2415,_TimerImpl,261,_TimerImpl_internalCallback,2528,_AsyncRun__scheduleImmediateWithSetImmediate_internalCallback,2529,_AsyncRun__scheduleImmediateJsOverride_internalCallback,2530,invokeClosure,57,_Exception,2531,_rootRunBinary,326,_rootRunUnary,325,_Future__addListener_closure,2532,_BufferingStreamSubscription$,2415,_PendingEvents,2533,_BufferingStreamSubscription,310,ArgumentError$,2415,_Future__chainForeignFuture,2534,_Future__chainForeignFuture_closure,2535,_Future__chainForeignFuture_closure0,2535,_Future__chainForeignFuture_closure1,2535,scheduleMicrotask,302,get$scheduleMicrotask,302,_StreamControllerLifecycle,2536,StreamController,307,StreamConsumer,2537,Stream_pipe_closure,2538,_GuaranteeSink,2539,StreamChannelController$,2415,_EventStream,2540,postMessageChannel_closure,2541,postMessageChannel_closure0,2541,LinkedHashMap_LinkedHashMap$_literal,2542,_convertDataTree,466,_EventStreamSubscription$,2415,_EventStreamSubscription_closure,2543,_wrapZone,473,_EventStreamSubscription,472,_RootZone_bindUnaryCallbackGuarded_closure,1247,_convertDataTree__convert,2544,_IdentityHashMap,2545,MapBase_mapToString,2546,MapBase_mapToString_closure,2547,MapMixin,2548,_HashMap__getTableEntry,2549,Primitives_objectHashCode,53,objectHashCode,53,_HashMapKeyIterable,2550,IterableBase_iterableToShortString,2551,_iterablePartsToStrings,358,RangeError_checkNotNegative,2552,RangeError$range,2553,_HashMapKeyIterator,2554,MappedIterable_MappedIterable,2415,MappedIterator,2555,Iterator,2556,EfficientLengthMappedIterable,2557,MappedIterable,3,MappedListIterable,2558,ListIterable,2559,_HashMap__newHashTable,2560,_HashMap__setTableEntry,2561,LinkedHashMap,346,JsLinkedHashMap,2562,fillLiteralMap,54,LinkedHashMapKeyIterable,2563,LinkedHashMapKeyIterator,870,LinkedHashMapCell,2564,postMessageChannel__closure,2565,postMessageChannel__closure0,2565,postMessageChannel__closure1,2565,_StructuredCloneDart2Js,2566,DateTime,2567,_StructuredClone_walk_closure,2568,_StructuredClone_walk_closure0,2568,_AcceptStructuredCloneDart2Js,2569,StateError$,2415,StreamSink,2570,StreamSubscription,2571,promiseToFuture,467,LinkedHashMap_LinkedHashMap$_empty,2572,_AcceptStructuredClone_walk_closure,2573,Primitives_getYear,2574,DateTime__fourDigits,2575,Primitives_getMonth,2576,DateTime__twoDigits,2577,Primitives_getDay,2578,Primitives_getHours,2579,Primitives_getMinutes,2580,Primitives_getSeconds,2581,Primitives_getMilliseconds,2582,DateTime__threeDigits,2583,Primitives_lazyAsJsDate,2584,_checkDoubleNullable,172,_AsyncCompleter,2585,promiseToFuture_closure,2586,promiseToFuture_closure0,2586,_Future__asyncCompleteError_closure,2587,_Future__asyncComplete_closure,2588,_Future__chainFuture_closure,2589,Stream_firstWhere_closure,1051,Stream_firstWhere_closure0,1051,_completeWithErrorCallback,287,Stream_firstWhere__closure,2590,Stream_firstWhere__closure0,2590,_cancelAndErrorClosure,317,_runUserCode,315,_cancelAndErrorClosure_closure,2591,_cancelAndError,316,_cancelAndError_closure,2592,_Future$zoneValue,2593,_cancelAndValue,318,_cancelAndValue_closure,2594,StreamChannelController,588,StreamController_StreamController,2415,_StreamSinkWrapper,2595,GuaranteeChannel$,2415,GuaranteeChannel,634,GuaranteeChannel_closure,2596,_StreamImplEvents,2597,_StreamControllerAddStreamState,1059,_SyncCompleter,2598,_GuaranteeSink_addStream_closure,2599,_GuaranteeSink__addError_closure,2600,GuaranteeChannel__closure,2601,_SyncStreamController,2602,_AsyncStreamController,2603,_EventDispatch,2604,_PendingEvents_schedule_closure,2605,_BufferingStreamSubscription__sendDone_sendDone,2606,_ControllerSubscription,1071,_StreamController__subscribe_closure,2607,_StreamController__recordCancel_complete,2608,_AddStreamState_cancel_closure,2609,_runGuarded,308,_DelayedError,2610,_BufferingStreamSubscription__sendError_sendError,2611,_DelayedData,2612,_MultiChannel$,2415,RemoteListener_start_closure,2613,_ZoneSpecification$,2415,Stream_Stream$fromIterable,2614,RemoteListener_start_closure0,2613,RemoteListener_start_closure1,2613,SuiteChannelManager,478,LinkedHashSet_LinkedHashSet$_empty,2572,runZoned,339,Map,2615,_runZoned,340,runZoned_closure,2616,_parentDelegate,322,_RootZone__rootDelegate,2617,_ZoneDelegate,2618,_rootFork,337,printToZone,2619,HashMap_HashMap$from,2620,_CustomZone,338,_ZoneFunction,2621,printString,247,_CustomZone_bindUnaryCallbackGuarded_closure,1205,_CustomZone_bindCallbackGuarded_closure,2622,_CustomZone_bindCallback_closure,1200,_TimerImpl$periodic,2623,_TimerImpl$periodic_closure,2624,_CustomZone_bindUnaryCallback_closure,1202,HashMap_HashMap,2415,_HashMap,2625,HashMap_HashMap$from_closure,2626,_LinkedHashSet,2627,_LinkedHashSetIterator,353,LinkedHashSet_LinkedHashSet$_literal,2542,RemoteListener_start__closure,2628,StackTraceFormatter,2236,RemoteListener_start___closure,2629,RemoteListener_start___closure0,2629,RemoteListener__sendError,2630,RemoteException_serialize,2631,TestFailure,2632,Chain_Chain$forTrace,2633,Chain_toString_closure,2634,Chain_toString_closure0,2634,instantiate1,8,checkTypeBound,160,checkNum,41,Chain_toString__closure,2635,Instantiation1,9,createRuntimeType,152,_Type,2636,instantiatedGenericFunctionType,134,_instantiate,135,_instantiateArray,139,_instantiateFunctionParameters,141,_instantiateNamed,140,Chain_toString__closure0,2635,getRuntimeType,93,Chain,2637,List_List$unmodifiable,2638,LazyChain,2639,Chain_Chain$forTrace_closure,2640,Chain_Chain$parse,2447,Chain_Chain$parse_closure,2641,Trace_Trace$parse,2447,Chain_Chain$parse_closure0,2641,Trace_toString_closure,2642,Trace_toString_closure0,2642,UnparsedFrame,630,Trace$parseFriendly,2643,WhereIterable,2644,Trace$parseFriendly_closure,2645,Trace$parseFriendly_closure0,2645,Trace,488,_StringStackTrace,2646,WhereIterator,2647,Frame_Frame$parseFriendly,2643,_parseUri,616,ParsedPath_ParsedPath$parse,2447,Context_split_closure,2648,List_List$from,2620,List,2649,ParsedPath,2650,List_List$filled,2651,ParsedPath_normalize_closure,2652,List_List$generate,2653,stringReplaceAllUnchecked,115,stringReplaceAllUncheckedString,116,JSSyntaxRegExp,2654,escapeReplacement,112,JSSyntaxRegExp_makeNative,2655,FormatException$,2415,FormatException,409,WindowsStyle,2366,RegExp_RegExp,2415,isDriveLetter,602,_Uri__uriDecode,2656,StringMatch,2657,CodeUnits,2658,_Uri__hexCharPairToByte,2659,Utf8Decoder,2660,UnmodifiableListMixin,2661,Utf8Decoder__convertIntercepted,2662,RangeError_checkValidRange,2663,_scanOneByteCharacters,372,String_String$fromCharCodes,2664,_Utf8Decoder,2665,Primitives_stringFromCharCode,2666,Primitives_stringFromCharCodes,2667,Primitives_stringFromNativeUint8List,2668,String__stringFromIterable,2669,Primitives_stringFromCodePoints,2670,Primitives__fromCharCodeApply,2671,Utf8Decoder__convertInterceptedUint8List,2672,Utf8Decoder__useTextDecoderChecked,2673,Utf8Decoder__unsafe,2674,Utf8Decoder__useTextDecoderUnchecked,2675,Utf8Decoder__makeDecoder,2676,RangeError_checkValueInInterval,2677,stringReplaceFirstUnchecked,120,stringReplaceRangeUnchecked,121,stringReplaceFirstRE,113,_StringAllMatchesIterable,2678,_StringAllMatchesIterator,2679,_MatchImplementation$,2415,_MatchImplementation,110,isAlphabetic,601,_AllMatchesIterable,2680,_AllMatchesIterator,2681,IterableElementError_tooFew,2682,JSArray_JSArray$fixed,2683,UrlStyle,2368,Context,615,current,621,get$current,621,PathException$,2415,_validateArgList,617,Context_join_closure,2684,Context_joinAll_closure,2685,SubListIterable$,2415,_validateArgList_closure,2686,SubListIterable,2,PathException,559,Uri_base,2687,_current,2493,set$_current,2493,_currentUriBase,2688,Primitives_currentUri,2689,Uri_parse,2447,UriData__parse,2690,_scan,465,_SimpleUri,2691,_Uri__Uri$notSimple,2692,int_parse,2447,Primitives_parseInt,2693,_Uri__defaultPort,2694,_Uri__toWindowsFilePath,2695,_Uri__checkNonWindowsPathReservedCharacters,2696,_Uri__checkNonWindowsPathReservedCharacters_closure,2697,_Uri__checkWindowsDriveLetter,2698,_Uri__checkWindowsPathReservedCharacters,2699,String_String$fromCharCode,2700,_Uri__removeDotSegments,2701,_Uri__makePort,2702,_Uri__normalizeRelativePath,2703,_Uri,420,_Uri__mayContainDotSegments,2704,_Uri__escapeScheme,2705,_Uri__isAlphabeticCharacter,2706,_Uri__makeScheme,2707,_Uri__fail,2708,_Uri__makeUserInfo,2709,_Uri__makeHost,2710,_Uri__Uri$notSimple_closure,2711,_Uri__makePath,2712,_Uri__makeQuery,2713,_Uri__makeFragment,2714,_Uri__normalizeOrSubstring,2715,_Uri__normalize,2716,_Uri__normalizeEscape,2717,_Uri__escapeChar,2718,hexDigitValue,1,_Uri__makePath_closure,2719,_Uri__normalizePath,2720,_Uri__uriEncode,2721,Codec,2722,_Utf8Encoder,2723,_checkValidRange,125,diagnoseRangeError,39,_Uri__checkZoneID,2724,_Uri__normalizeZoneID,2725,Uri_parseIPv6Address,2726,_Uri__normalizeRegName,2727,Uri_parseIPv6Address_error,2728,Uri_parseIPv6Address_parseHex,2729,Uri__parseIPv4Address,2730,Uri__parseIPv4Address_error,2731,_Uri__canonicalizeScheme,2732,_createTables,464,_createTables_closure,2733,_createTables_build,2734,_createTables_setChars,2735,_createTables_setRange,2736,_DataUri,2737,UriData,2738,Base64Codec__checkPadding,2739,_ensureNativeList,122,NativeInt8List__create1,2740,Style__getPlatformStyle,2741,_Uri__Uri,2415,PosixStyle,2364,Frame_Frame$parseFriendly_closure,2742,Frame__catchFormatException,2743,UriData__writeUri,2744,UriData__uriEncodeBytes,2745,Frame,2746,WindowsStyle_absolutePathToUri_closure,2747,Context_Context,2415,UriData__validateMimeType,2748,JSString__skipLeadingWhitespace,2749,JSString__skipTrailingWhitespace,2750,JSString__isWhitespace,2751,Trace$parseV8,2752,Trace$parseJSCore,2753,Trace$parseFirefox,2754,Trace__parseVM,2755,Trace__parseVM_closure,2756,Frame_Frame$parseVM,2757,Frame_Frame$parseVM_closure,2758,ExpandIterable,2759,Chain_toTrace_closure,2760,ExpandIterator,782,Trace$parseFirefox_closure,2761,Trace$parseFirefox_closure0,2761,Frame_Frame$parseFirefox,2754,Frame_Frame$parseFirefox_closure,2762,Frame__uriOrPathToUri,2763,_Uri__Uri$file,2764,_Uri__makeWindowsFileUrl,2765,_Uri__makeFileUri,2766,Trace$parseJSCore_closure,2767,Trace$parseJSCore_closure0,2767,Frame_Frame$parseV8,2752,Frame_Frame$parseV8_closure,2768,Frame_Frame$parseV8_closure_parseLocation,2769,Trace$parseV8_closure,2770,Trace$parseV8_closure0,2770,SkipWhileIterable,2771,SkipWhileIterator,2772,stringContainsUnchecked,111,StackTrace_current,621,StackZoneSpecification_chainFor_closure,2773,_Node,2774,LazyTrace,2775,StackZoneSpecification_chainFor_closure0,2773,Trace_Trace$from,2620,Trace_Trace$from_closure,2776,LazyChain_toTrace_closure,2777,Primitives_getProperty,2778,parseJsonExtended,553,mapStackTrace,487,StackTraceFormatter_formatStackTrace_closure,2779,LazyChain_foldFrames_closure,2780,Chain_foldFrames_closure,2781,Chain_foldFrames_closure0,2781,IterableElementError_tooMany,2782,LazyTrace_foldFrames_closure,2783,Trace_foldFrames_closure,2784,ReversedListIterable,2785,Trace_foldFrames_closure0,2784,mapStackTrace_closure,2786,mapStackTrace_closure0,2786,mapStackTrace_closure1,2786,_prettifyMember,489,_prettifyMember_closure,2787,_prettifyMember_closure0,2787,stringReplaceAllFuncUnchecked,118,_stringIdentity,117,MappingBundle$fromJson,2788,parseJson,554,ArgumentError$notNull,2789,SourceLocation$,2415,SourceMapSpan,1872,findLineStart,605,countCodeUnits,603,Highlighter__lastLineLength,2790,SourceSpanWithContext$,2415,Highlighter__normalizeNewlines,2791,Highlighter__normalizeTrailingNewline,2792,Highlighter__normalizeEndOfLine,2793,Highlighter,1957,_glyphs,2794,Highlighter__writeSidebar_closure,2795,Highlighter__writeLastLine_closure,2796,Highlighter__writeLastLine_closure0,2796,Highlighter__writeLastLine_closure1,2796,Highlighter__writeIntermediateLines_closure,2797,Highlighter__writeFirstLine_closure,2798,Highlighter__writeFirstLine_closure0,2798,Highlighter__writeFirstLine_closure1,2798,Highlighter__writeFirstLine_closure2,2798,SourceSpanWithContext,560,RangeError$,2415,SourceLocation,523,SingleMapping__findColumn_closure,2799,binarySearch,504,SingleMapping__findLine_closure,2800,JsLinkedHashMap_values_closure,863,MultiSectionMapping$fromJson,2788,SingleMapping$fromJson,2788,SingleMapping,2801,SourceFile,2802,_MappingTokenizer,2803,TargetLineEntry,2804,decodeVlq,534,TargetEntry,2805,SingleMapping$fromJson_closure,2806,pow,471,closure,2807,MultiSectionMapping,2808,MappingBundle,2809,_parseJson,364,_convertJsonToDartLazy,365,_JsonMap,2810,_JsonMapKeyIterable,2811,RemoteListener__sendLoadException,2812,StreamQueue,2813,QueueList$,2415,ListQueue$,2415,_CompleterStream,2814,_RestRequest,2815,StreamCompleter,2816,RemoteListener_start____closure,2817,_asBoolNullable,169,Metadata$deserialize,2818,LinkedHashSet_LinkedHashSet$from,2620,Declarer$,2415,RemoteListener__deserializeSet,2819,Runtime_Runtime$deserialize,2818,_asStringNullable,180,OperatingSystem_find,2820,SuitePlatform$,2415,RemoteListener_start____closure0,2817,Suite,2821,Suite__filterGroup,2822,_asyncStartSync,266,_asyncAwait,267,_asyncReturn,268,_asyncRethrow,269,_wrapJsFunctionForAsync,271,_makeAsyncAwaitCompleter,263,Symbol,2823,_AddStreamState_makeErrorHandler,2824,_AddStreamState_makeErrorHandler_closure,2825,_ListQueueIterator,363,ListQueue,362,QueueList,607,Result,2826,_wrapJsFunctionForAsync_closure,2827,_StreamIterator,2828,_awaitOnObject,270,_awaitOnObject_closure,2829,_awaitOnObject_closure0,2829,_AsyncAwaitCompleter,2830,RemoteListener_start_____closure,2831,Invoker_guard,2832,Invoker_guard_closure,2833,Invoker_guard__closure,2834,RemoteListener,2835,RemoteListener__serializeGroup_closure,2836,Group,490,RemoteListener__serializeTest_closure,2837,VirtualChannel,2838,_EmptyStream,2839,NullStreamSink,2840,_MultiChannel_virtualChannel_closure,2071,_MultiChannel_virtualChannel_closure0,2071,MultiChannel,2841,_DoneStreamSubscription,949,NullStreamSink_addStream_closure,2842,_LinkedHashSet__newHashTable,2560,_LinkedHashSetCell,2843,_asIntNullable,174,RemoteListener__runLiveTest_closure,2844,_BroadcastStream,2845,RemoteListener__runLiveTest_closure0,2844,RemoteListener__runLiveTest_closure1,2844,RemoteListener__runLiveTest_closure2,2844,RemoteListener__runLiveTest_closure3,2844,RemoteListener__runLiveTest__closure,2846,Invoker,2847,LiveTestController$,2415,_BroadcastSubscription,950,State,2848,Invoker__onRun_closure,2849,_AsyncCounter,2850,Chain_capture,2851,Expando__keyCount,2852,StackZoneSpecification,2853,Expando,570,Chain_capture_closure,1968,Primitives_setProperty,2854,StackZoneSpecification__currentTrace_closure,2855,StackZoneSpecification__registerBinaryCallback_closure,2025,StackZoneSpecification__registerBinaryCallback__closure,2027,StackZoneSpecification__registerUnaryCallback_closure,2021,StackZoneSpecification__registerUnaryCallback__closure,2023,StackZoneSpecification__registerCallback_closure,2019,Invoker__onRun__closure,2856,Invoker__onRun___closure,2857,Invoker__onRun___closure0,2857,Message,2858,Invoker__onRun____closure,2859,Future_Future,2415,Future_Future_closure,2860,Timer_Timer,2415,errorsDontStopTest,525,errorsDontStopTest_closure,2861,errorsDontStopTest_closure0,2861,Invoker_waitForOutstandingCallbacks_closure,2862,Invoker_waitForOutstandingCallbacks_closure0,2862,Future_Future$sync,2863,ClosedException$,2415,ClosedException,635,Invoker_heartbeat_closure,2864,Invoker_heartbeat_message,2865,Invoker_heartbeat__closure,2866,TimeoutException,2867,Timeout,2868,Invoker__handleError_closure,2869,Invoker__handleError_closure0,2869,print,412,get$print,412,Chain_Chain$current,621,Chain_Chain$current_closure,2870,LiveTestController,524,_SyncBroadcastStreamController,2871,_LiveTest,2872,_SyncBroadcastStreamController__sendError_closure,974,_AddStreamState,1058,_SyncBroadcastStreamController__sendDone_closure,976,_SyncBroadcastStreamController__sendData_closure,972,_BroadcastStreamController,2873,Metadata_serialize_closure,2874,Metadata_serialize_closure0,2874,MapEntry,2875,_LinkedHashSetIterator$,2415,PlatformSelector,2876,Group_forPlatform_closure,2877,Group$,2415,GroupEntry,2878,Group__map_closure,2879,Group__map_closure0,2879,Metadata_forPlatform_closure,2880,Metadata_Metadata,2415,Metadata_Metadata__unresolved,2881,LinkedHashMap_LinkedHashMap$from,2620,Metadata$_,2882,Metadata_Metadata_closure,2883,Metadata_merge_closure,2884,mergeMaps,506,Metadata_merge_closure0,2884,Set,2885,mergeMaps_closure,1723,UnmodifiableMapView,2886,Metadata,493,UnmodifiableSetView,533,ConstantMap_map_closure,806,ConstantMap__throwUnmodifiable,2887,_ConstantMapKeyIterable,2888,ConstantStringMap,2889,DelegatingSet,2890,Metadata__validateTags_closure,2891,Metadata__validateTags_closure0,2891,pluralize,593,toSentence,592,LinkedHashMap_LinkedHashMap,2415,LinkedHashMap_LinkedHashMap$from_closure,2892,PlatformSelector_evaluate_closure,2893,SuitePlatform,530,OperatingSystem_find_closure,2894,OperatingSystem_find_closure0,2894,Runtime_Runtime$deserialize_closure,2895,Runtime,2896,Declarer_build_closure,2897,LocalTest,2898,Declarer__tearDownAll_closure,2899,Declarer__tearDownAll__closure,2900,Declarer__tearDownAll___closure,2901,Declarer,561,Duration$,2415,LinkedHashSet_LinkedHashSet,2415,PlatformSelector$parse,2447,Metadata__deserializeTimeout,2902,Metadata$deserialize_closure,2903,Stream_last_closure,1049,Stream_last_closure0,1049,Stream_first_closure,1047,Stream_first_closure0,1047,BooleanSelectorImpl,2904,Parser,2185,Scanner,2905,SpanScanner$,2415,AndNode,2906,IntersectionSelector,2907,OrNode,2908,ConditionalNode,2909,Evaluator,2910,SourceSpanFormatException$,2415,SourceSpanFormatException,538,Token,2911,_SpanScannerState,2912,IdentifierToken,2913,validateErrorArgs,606,StringScannerException$,2415,StringScannerException,527,_FileSpan$,2415,SourceSpanMixin,2914,_FileSpan,509,FileLocation$_,2882,FileLocation,2915,NotNode,2916,VariableNode,2917,_expandSafe,564,SpanScanner,474,_asNumNullable,177,PlatformSelector$parse_closure,2918,PlatformSelector__wrapFormatException,2919,_CompleterSink,2920,_CompleterSink__setDestinationSink_closure,2921,StreamSinkCompleter,2922,_EventRequest,2923,SubscriptionStream,1612,_CancelOnErrorSubscriptionWrapper,2924,_CancelOnErrorSubscriptionWrapper_onError_closure,2925,_CancelOnErrorSubscriptionWrapper_onError__closure,2926,StreamQueue__ensureListening_closure,1619,StreamQueue__ensureListening_closure0,1619,StreamQueue__ensureListening_closure1,1619,ErrorResult,2927,ValueResult,2928,EventSink,2929,_NextRequest,2930,Completer,469,LinkedHashSet,349,fillLiteralSet,56,_GeneratedStreamImpl,2931,Stream_Stream$fromIterable_closure,1042,_IterablePendingEvents,1041,_ZoneSpecification,320,_MultiChannel,620,_MultiChannel_closure,2067,_MultiChannel_closure0,2067,_MultiChannel_closure1,2067,_MultiChannel__closure,2069,JSStackTraceMapper_deserialize,2818,PackageRootResolver,2932,asUri,598,ensureTrailingSlash,599,JSStackTraceMapper__deserializePackageConfigMap,2933,PackageConfigResolver__normalizeMap,2934,PackageConfigResolver,2935,JSStackTraceMapper,2936,Map_castFrom,2937,CastMap,2938,CastIterable_CastIterable,2415,CastIterator,2939,EfficientLengthIterable,2940,_EfficientLengthCastIterable,2941,CastIterable,0,CastMap_forEach_closure,747,PackageConfigResolver__normalizeMap_closure,2942,mapMap,505,mapMap_closure,1721,mapMap_closure0,1721,JSStackTraceMapper__deserializePackageConfigMap_closure,2943,StreamChannelCompleter,2256,_StreamChannel,2944,main_closure0,2397,group,587,get$group,587,_declarer,584,Metadata$parse,2447,Trace_Trace$current,621,Declarer_group_closure,2945,Trace_Trace$current_closure,2946,Metadata_validatePlatformSelectors_closure,2947,PlatformSelector_validate_closure,2948,PlatformSelector_validate__closure,2949,Validator,2950,Metadata__parseOnPlatform,2951,Metadata__parseTags,2952,_globalDeclarer,2953,_declarer_closure,2954,RunnerSuiteController,2955,_AsyncBroadcastStreamController,2956,AsyncMemoizer,2957,RunnerSuite,2958,Engine$,2415,Stopwatch__frequency,2959,Primitives_initTicker,2960,Primitives_timerFrequency,2961,ExpandedReporter,2962,Stopwatch,2320,PrintSink,2963,Stream_Stream$fromFuture,2964,_declarer__closure,2965,Future_Future$error,2966,UnmodifiableListView,2967,Primitives_timerTicks,2968,UnionSet,2969,UnionSet_length_closure,1739,IterableSet,2970,UnionSet__iterable_closure,1741,ExpandedReporter__onTestStarted_closure,2971,ExpandedReporter__onTestStarted_closure0,2971,ExpandedReporter__onTestStarted_closure1,2971,indent,591,prefixLines,594,Engine_run_closure,2972,Engine_run_closure0,2972,Pool_close_closure,2973,FutureGroup,499,_ListQueueIterator$,2415,FutureGroup_add_closure,1573,FutureGroup_add_closure0,1573,Engine_run__closure,2286,LiveSuiteController$,2415,Engine_run___closure,2974,Engine_run____closure,2975,Pool__onResourceReleaseAllowed_closure,2976,Pool__runOnRelease_closure,2977,Pool__runOnRelease_closure0,2977,PoolResource,2978,LiveSuiteController_close_closure,2979,RunnerSuiteController__close_closure,2980,Engine__runSkippedTest_closure,2981,Engine__runSkippedTest_closure0,2981,Engine__runSkippedTest_closure1,2981,Engine__runLiveTest_closure,2982,Engine__runLiveTest_closure0,2982,Future_Future$microtask,2983,Engine__runLiveTest_closure1,2982,Future_Future$microtask_closure,2984,LiveSuiteController_reportLiveTest_closure,2985,QueueList__nextPowerOf2,2986,StreamGroup_add_closure,1602,StreamGroup_add_closure0,1602,StreamGroup__listenToStream_closure,2987,LiveSuiteController,595,_LiveSuite,2988,LiveSuiteController_closure,2989,LiveSuiteController_closure0,2989,Stream_Stream$fromFuture_closure,1039,Stream_Stream$fromFuture_closure0,1039,Future_wait,2990,Engine_success_closure,2991,Future_wait_handleError,2992,Future_wait_closure,984,Primitives_initTicker_closure,2993,StreamGroup,2994,UnionSetController$,2415,Pool$,2415,Engine,498,StreamGroup__onCancelBroadcast_closure,1606,StreamGroup__onListen_closure,1604,Engine_closure,2995,Engine_closure0,2995,Pool,485,UnionSetController,507,closure0,2807,_macOSDirectories,2996,SuiteConfiguration__list,2997,UnmodifiableSetView$,2415,SuiteConfiguration__map,2998,SuiteConfiguration,2999,main__closure,3000,test,586,get$test,586,Declarer_test_closure,3001,Declarer_test__closure,3002,Declarer_test___closure,3003,Declarer__runSetUps_closure,3004,Future_forEach,3005,Future_forEach_closure,3006,Future_doWhile,3007,Future_doWhile_closure,3008,method1,550,method2,551,expect,539,get$expect,539,_expect,540,wrapMatcher,609,_expect_closure,3009,_expect_closure0,3009,fail,544,StringDescription,3010,formatFailure,545,Matcher,3011,prettyPrint,546,prettyPrint__prettyPrint,3012,prettyPrint__prettyPrint_pp,3013,_typeName,622,prettyPrint__prettyPrint_closure,3014,prettyPrint__prettyPrint_closure0,3014,prettyPrint__prettyPrint_closure1,3014,escape,612,escape_closure,3015,_getHexLiteral,613,Runes,3016,_combineSurrogatePair,413,RuneIterator,3017,_Predicate,3018,wrapMatcher_closure,3019,_StringEqualsMatcher,3020,_DeepMatcher,3021,JsLinkedHashMap_addAll_closure,865,_DeepMatcher__compareSets_closure,3022,TypeMatcher,3023,FeatureMatcher,3024,_StringEqualsMatcher__writeTrailing,3025,_StringEqualsMatcher__writeLeading,3026,x,3027,_Utils_objectAssign,3028,JS_CONST,3029,Interceptor,3030,JSBool,3031,JSNull,3032,JSObject,3033,JavaScriptObject,3034,PlainJavaScriptObject,3035,UnknownJavaScriptObject,3036,Function,3037,JavaScriptFunction,3038,JSUnmodifiableArray,3039,JSNumber,3040,JSInt,3041,JSDouble,3042,Pattern,3043,JSString,3044,_CastIterableBase,3045,EmptyIterator,3046,FixedLengthListMixin,3047,UnmodifiableListBase,3048,ConstantMap,3049,Instantiation,815,TypeErrorDecoder_noSuchMethodPattern,3050,TypeErrorDecoder_notClosurePattern,3051,TypeErrorDecoder_nullCallPattern,3052,TypeErrorDecoder_nullLiteralCallPattern,3053,TypeErrorDecoder_undefinedCallPattern,3054,TypeErrorDecoder_undefinedLiteralCallPattern,3055,TypeErrorDecoder_nullPropertyPattern,3056,TypeErrorDecoder_nullLiteralPropertyPattern,3057,TypeErrorDecoder_undefinedPropertyPattern,3058,TypeErrorDecoder_undefinedLiteralPropertyPattern,3059,NoSuchMethodError,3060,StackTrace,3061,TearOffClosure,3062,RegExp,382,RegExpMatch,3063,Match,3064,NativeByteBuffer,3065,ByteBuffer,3066,NativeTypedData,3067,NativeByteData,3068,NativeTypedArray,3069,NativeTypedArrayOfDouble,3070,NativeTypedArrayOfInt,3071,NativeFloat32List,3072,NativeFloat64List,3073,NativeInt16List,3074,NativeInt32List,3075,NativeInt8List,3076,NativeUint16List,3077,Uint32List,3078,NativeUint32List,3079,NativeUint8ClampedList,3080,NativeUint8List,418,Uint8List,3081,Type,3082,_Error,3083,Timer,319,Sink,3084,Exception,58,_Completer,3085,StreamTransformer,3086,StreamTransformerBase,3087,_StreamController,3088,_SyncStreamControllerDispatch,3089,_AsyncStreamControllerDispatch,3090,_StreamImpl,3091,_DelayedEvent,3092,_DelayedDone,3093,Error,3094,ZoneSpecification,3095,ZoneDelegate,3096,Zone,3097,_Zone,3098,_RootZone__rootMap,3099,_RootZone,3100,IterableBase,3101,ListBase,3102,MapBase,3103,_UnmodifiableMapMixin,3104,MapView,3105,Queue,3106,SetMixin,3107,SetBase,3108,_SetBase,3109,AsciiCodec,3110,_UnicodeSubsetEncoder,3111,AsciiEncoder,3112,Base64Codec,3113,Base64Encoder,3114,_FusedCodec,3115,Converter,3116,Encoding,3117,JsonCodec,3118,JsonDecoder,3119,Utf8Codec,3120,Utf8Encoder,3121,Utf8Decoder__decoder,3122,OutOfMemoryError,3123,StringSink,3124,Uri,3125,_Uri__isWindowsCached,3126,_Uri__needsNoEncoding,3127,AbortPaymentEvent,3128,AnimationEvent,3129,AnimationPlaybackEvent,3130,ApplicationCacheErrorEvent,3131,BackgroundFetchClickEvent,3132,BackgroundFetchEvent,3133,BackgroundFetchFailEvent,3134,BackgroundFetchedEvent,3135,BeforeInstallPromptEvent,3136,BeforeUnloadEvent,3137,Blob,3138,BlobEvent,3139,CanMakePaymentEvent,3140,ClipboardEvent,3141,CloseEvent,3142,CompositionEvent,3143,CustomEvent,3144,DeviceMotionEvent,3145,DeviceOrientationEvent,3146,DomError,3147,DomException,3148,ErrorEvent,3149,Event,3150,EventTarget,3151,ExtendableEvent,3152,ExtendableMessageEvent,3153,FetchEvent,3154,File,3155,FocusEvent,3156,FontFaceSetLoadEvent,3157,ForeignFetchEvent,3158,GamepadEvent,3159,HashChangeEvent,3160,InstallEvent,3161,KeyboardEvent,3162,Location,3163,MediaEncryptedEvent,3164,MediaError,3165,MediaKeyMessageEvent,3166,MediaQueryListEvent,3167,MediaStreamEvent,3168,MediaStreamTrackEvent,3169,MessageEvent,3170,MessagePort,3171,MidiConnectionEvent,3172,MidiMessageEvent,3173,MouseEvent,3174,MutationEvent,3175,NavigatorUserMediaError,3176,NotificationEvent,3177,OverconstrainedError,3178,PageTransitionEvent,3179,PaymentRequestEvent,3180,PaymentRequestUpdateEvent,3181,PointerEvent,3182,PopStateEvent,3183,PositionError,3184,PresentationConnectionAvailableEvent,3185,PresentationConnectionCloseEvent,3186,ProgressEvent,3187,PromiseRejectionEvent,3188,PushEvent,3189,RtcDataChannelEvent,3190,RtcDtmfToneChangeEvent,3191,RtcPeerConnectionIceEvent,3192,RtcTrackEvent,3193,SecurityPolicyViolationEvent,3194,SensorErrorEvent,3195,SpeechRecognitionError,3196,SpeechRecognitionEvent,3197,SpeechSynthesisEvent,3198,StorageEvent,3199,SyncEvent,3200,TextEvent,3201,TouchEvent,3202,TrackEvent,3203,TransitionEvent,3204,UIEvent,3205,VRDeviceEvent,3206,VRDisplayEvent,3207,VRSessionEvent,3208,WheelEvent,3209,Window,3210,_MojoInterfaceRequestEvent,3211,_ResourceProgressEvent,3212,_USBConnectionEvent,3213,EventStreamProvider,3214,_StructuredClone,3215,_AcceptStructuredClone,3216,VersionChangeEvent,3217,ByteData,3218,Int8List,3219,Uint8ClampedList,3220,Int16List,3221,Uint16List,3222,Int32List,3223,Float32List,3224,Float64List,3225,AudioProcessingEvent,3226,OfflineAudioCompletionEvent,3227,ContextEvent,3228,SqlError,3229,DelegatingSink,3230,DelegatingStreamSubscription,3231,_StreamGroupState,3232,BooleanSelector,3233,All,3234,Node,3235,Visitor,3236,None,3237,TokenType,3238,RecursiveVisitor,3239,EmptyUnmodifiableSet,3240,UnmodifiableSetMixin,3241,_DelegatingIterableBase,3242,DelegatingIterable,3243,_IsTrue,3244,Description,3245,SyncPackageResolver,3246,_PathDirection,3247,_PathRelation,3248,InternalStyle,3249,Style,3250,Mapping,3251,_TokenKind,3252,FileSpan,3253,SourceLocationMixin,3254,SourceSpan,3255,SourceSpanBase,1948,SourceSpanException,3256,Frame__uriRegExp,3257,Frame__windowsRegExp,3258,StackZoneSpecification_disableKey,3259,StreamChannelMixin,3260,LineScannerState,3261,StringScanner,3262,AsciiGlyphSet,3263,UnicodeGlyphSet,3264,LiveTest,3265,MessageType,3266,Metadata_empty,3267,OperatingSystem,3268,Status,3269,Result0,2826,Test,3270,StackTraceMapper,3271,LiveSuite,3272,RuntimeSelection,3273,SuiteConfiguration_empty,3267,_NativeTypedArrayOfDouble_NativeTypedArray_ListMixin,3274,_NativeTypedArrayOfDouble_NativeTypedArray_ListMixin_FixedLengthListMixin,3275,_NativeTypedArrayOfInt_NativeTypedArray_ListMixin,3276,_NativeTypedArrayOfInt_NativeTypedArray_ListMixin_FixedLengthListMixin,3277,_ListBase_Object_ListMixin,3278,_SetBase_Object_SetMixin,3279,_UnmodifiableMapView_MapView__UnmodifiableMapMixin,3280,_QueueList_Object_ListMixin,3281,_UnionSet_SetBase_UnmodifiableSetMixin,3282,_UnmodifiableSetView_DelegatingSet_UnmodifiableSetMixin,3283,_IterableSet_SetMixin_UnmodifiableSetMixin,3284,main,552,getNativeInterceptor,249,isJsIndexable,11,Primitives_dateNow,3285,closureFromTearOff,66,throwCyclicInit,80,getRuntimeTypeArguments,85,computeSignature,96,defineProperty,98,findType,133,typeLiteral,153,_asDoubleNullable,171,_Universe_addRules,3286,_Universe_addErasedTypes,3287,_AsyncRun__scheduleImmediateJsOverride,3288,_AsyncRun__scheduleImmediateWithSetImmediate,3289,_AsyncRun__scheduleImmediateWithTimer,3290,Future__kTrue,3291,_startMicrotaskLoop,299,StreamIterator_StreamIterator,2415,_nullDataHandler,312,_nullErrorHandler,313,_nullDoneHandler,314,_rootRegisterCallback,327,_rootRegisterUnaryCallback,328,_rootRegisterBinaryCallback,329,_rootErrorCallback,330,_rootCreateTimer,332,_rootCreatePeriodicTimer,333,_rootPrint,335,_printToZone,336,Uri_decodeComponent,3292,_escapeString,623,main0,552,max,470,DART_CLOSURE_PROPERTY_NAME,2333,JS_INTEROP_INTERCEPTOR_TAG,2334,_AsyncRun__scheduleImmediateClosure,3293,Future__nullFuture,3294,_Base64Decoder__inverseAlphabet,3295,_hasErrorStackProperty,2352,_scannerTables,2353,_whitespaceAndSingleLineComments,2354,_multiLineCommentBody,2355,_hyphenatedIdentifier,2356,_dart2DynamicArgs,2357,_escapeRegExp,2358,windows,2359,url,2360,context,2361,get$context,2361,Style_posix,3296,Style_windows,2359,Style_url,2360,Style_platform,3297,_digits,2370,MAX_INT32,2371,MIN_INT32,2372,_specKey,2373,_vmFrame,2374,_v8Frame,2375,_v8UrlLocation,2376,_v8EvalLocation,2377,_firefoxSafariFrame,2378,_friendlyFrame,2379,_asyncBody,2380,_initialDot,2381,_terseRegExp,2385,_v8Trace,2386,_v8TraceLine,2387,_firefoxSafariTrace,2388,_friendlyTrace,2389,_universalValidVariables,2391,_currentKey,2392,_currentKey0,2392,currentOSGuess,2393,_hyphenatedIdentifier0,2356,anchoredHyphenatedIdentifier,2394,$get$DART_CLOSURE_PROPERTY_NAME,2333,$get$JS_INTEROP_INTERCEPTOR_TAG,2334,$get$TypeErrorDecoder_noSuchMethodPattern,3050,$get$TypeErrorDecoder_notClosurePattern,3051,$get$TypeErrorDecoder_nullCallPattern,3052,$get$TypeErrorDecoder_nullLiteralCallPattern,3053,$get$TypeErrorDecoder_undefinedCallPattern,3054,$get$TypeErrorDecoder_undefinedLiteralCallPattern,3055,$get$TypeErrorDecoder_nullPropertyPattern,3056,$get$TypeErrorDecoder_nullLiteralPropertyPattern,3057,$get$TypeErrorDecoder_undefinedPropertyPattern,3058,$get$TypeErrorDecoder_undefinedLiteralPropertyPattern,3059,$get$_AsyncRun__scheduleImmediateClosure,3293,$get$Future__nullFuture,3294,$get$_currentKey,2392,$get$_RootZone__rootMap,3099,$get$_currentKey0,2392,$get$_specKey,2373,$get$context,2361,$get$Style_url,2360,$get$Style_windows,2359,$get$Utf8Decoder__decoder,3122,$get$Style_platform,3297,$get$_Uri__isWindowsCached,3126,$get$_Uri__needsNoEncoding,3127,$get$_scannerTables,2353,$get$_Base64Decoder__inverseAlphabet,3295,$get$Style_posix,3296,$get$_friendlyFrame,2379,$get$_v8Trace,2386,$get$_firefoxSafariTrace,2388,$get$_friendlyTrace,2389,$get$_vmFrame,2374,$get$_asyncBody,2380,$get$_firefoxSafariFrame,2378,$get$_initialDot,2381,$get$Frame__uriRegExp,3257,$get$Frame__windowsRegExp,3258,$get$windows,2359,$get$_v8Frame,2375,$get$_v8EvalLocation,2377,$get$_v8UrlLocation,2376,$get$_v8TraceLine,2387,$get$_hasErrorStackProperty,2352,$get$_terseRegExp,2385,$get$url,2360,$get$_digits,2370,$get$MIN_INT32,2372,$get$MAX_INT32,2371,$get$StackZoneSpecification_disableKey,3259,$get$anchoredHyphenatedIdentifier,2394,$get$_hyphenatedIdentifier,2356,$get$_hyphenatedIdentifier0,2356,$get$_whitespaceAndSingleLineComments,2354,$get$_multiLineCommentBody,2355,$get$_universalValidVariables,2391,$get$SuiteConfiguration_empty,3267,$get$currentOSGuess,2393,$get$Metadata_empty,3267,$get$_escapeRegExp,2358,$get$_dart2DynamicArgs,2357,getInterceptor$,3298,getInterceptor$asx,3299,async___startMicrotaskLoop$closure,3300,async__AsyncRun__scheduleImmediateJsOverride$closure,3301,async__AsyncRun__scheduleImmediateWithSetImmediate$closure,3302,async__AsyncRun__scheduleImmediateWithTimer$closure,3303,async___nullDoneHandler$closure,3304,async___nullErrorHandler$closure,3305,async___nullDataHandler$closure,3306,getInterceptor$ax,3307,async___printToZone$closure,3308,math__max$closure,3309,getInterceptor$s,3310,core_Uri_decodeComponent$closure,3311,main_test__main$closure,3312,_js_helper_Primitives_dateNow$closure,3313,async_Future__kTrue$closure,3314,pretty_print___escapeString$closure,3315,util___getHexLiteral$closure,3316,getInterceptor$x,3317,getInterceptor$ansx,3318,getInterceptor$n,3319,async___rootHandleUncaughtError$closure,3320,async___rootRun$closure,3321,async___rootRunUnary$closure,3322,async___rootRunBinary$closure,3323,async___rootRegisterCallback$closure,3324,async___rootRegisterUnaryCallback$closure,3325,async___rootRegisterBinaryCallback$closure,3326,async___rootErrorCallback$closure,3327,async___rootScheduleMicrotask$closure,3328,async___rootCreateTimer$closure,3329,async___rootCreatePeriodicTimer$closure,3330,async___rootPrint$closure,3331,async___rootFork$closure,3332","instance":"K1,3333,$this,3334,_box_0,3335,matcher,3336,future,3337,get$future,3337,V1,3338,listener,3339,frame,3340,expectedElement,3341,getMain,3342,value,2416,location,3343,get$location,3343,channel,3344,get$channel,3344,depth,3345,controller,3346,super$StringScanner$matches,3347,beforeLoad,3348,f,3349,line,3350,get$line,3350,printZone,3351,R,3352,end,3353,get$end,3353,transform,3354,result,3355,selector,3356,handleError,3357,get$handleError,3357,body,3358,elements,3359,x,3360,suite,3361,get$suite,3361,T,3362,index,3363,predicate,610,error,2966,get$error,2966,validVariables,3364,terse,3365,super$EventTarget$addEventListener,3366,_TimerImpl$2,2415,stackTrace,3367,_BufferingStreamSubscription$4,2415,_EventStreamSubscription$4,2415,LinkedHashMapKeyIterator$2,2415,timeout,3368,DateTime$_withValue$2$isUtc,3369,_Future$zoneValue$2,2593,StreamChannelController$2$allowForeignErrors$sync,2415,GuaranteeChannel$3$allowSinkErrors,2415,message,3370,get$message,3370,_Future$immediate$1,3371,_CustomZone$3,2415,performance,3372,trace,3373,div,3374,_TimerImpl$periodic$2,2623,level,3375,span,3376,get$span,3376,_LinkedHashSetIterator$2,2415,registered,3377,Instantiation$1,2415,_MatchImplementation$2,2415,SubListIterable$3,2415,super$Iterable$where,3378,SourceSpanBase$3,2415,SourceSpanWithContext$4,2415,SourceLocation$4$column$line$sourceUrl,2415,super$JavaScriptObject$toString,3379,SingleMapping$fromJson$2$mapUrl,2788,callback,3380,SourceFile$decoded$2$url,3381,test,586,get$test,586,MultiSectionMapping$fromJson$3$mapUrl,2788,groups,3382,get$groups,3382,liveTest,3383,get$liveTest,3383,engine,3384,MappingBundle$fromJson$2$mapUrl,2788,_StreamControllerAddStreamState$4,2415,_DoneStreamSubscription$1,2415,Invoker$_$4$groups$guarded,2882,chain,3385,LiveTestController$5$groups,2415,_BroadcastSubscription$5,2415,Metadata$_$10$chainStackTraces$forTag$onPlatform$retry$skip$skipReason$tags$testOn$timeout$verboseTrace,2882,completer,3386,longest,3387,SuitePlatform$3$inGoogle$os,2415,FileLocation$_$2,2882,_FileSpan$3,2415,StringScanner$3$position$sourceUrl,2415,_box_1,3388,SubscriptionStream$1,2415,super$Iterable$skipWhile,3389,fn,3390,$call$body$Engine_run__closure,3391,oldPredicate,3392,ListQueue$1,2415,counter,3393,QueueList$1,2415,hasError,3394,_MultiChannel$1,2415,loadResource,3395,StreamChannelCompleter$0,2415,super$TypeMatcher$describe,3396,id,3397,Metadata$parse$8$chainStackTraces$onPlatform$retry$skip$tags$testOn$timeout$verboseTrace,2447,milliseconds,3398,super$TypeMatcher$matches,3347,originalSource,3399,Stopwatch$0,2415,start,2491,get$start,2491,stream,3400,get$stream,3400,ExpandedReporter$_$5$color$printPath$printPlatform,2882,_Future$immediateError$2,3401,outstandingCallbacksForBody,3402,sourceResult,3403,K,3404,serializedOnPlatform,3405,V,3406,LiveSuiteController$1,2415,StreamGroup$broadcast$0,3407,onData,3408,get$onData,3408,Engine$3$concurrency$coverage$maxSuites,2415,Pool$2$timeout,2415,UnionSetController$1$disjoint,2415,target,3409,StringDescription$1,2415,sourceMap,3410,invoker,3411,minified,3412,zone,3413,sdkRoot,3414,streamConsumer,3415,e,3416,platform,3297,s,3417,sdkLib,3418,super$_BroadcastStreamController$_addEventError,3419,column,3420,get$column,3420,cleanUp,3421,eagerError,3422,iterator,3423,get$iterator,3423,identifier,3424,port,3425,get$port,3425,action,3426,node,3427,T1,3428,T2,3429,withResource$body$Pool,3430,portSubscription,3431,serialized,3432,doneSignal,3433,arg1,3434,pos,3435,arg2,3436,dispatch,3437,getTag,3438,testOn,3439,getUnknownTag,3440,skip,3441,get$skip,3441,verboseTrace,3442,get$verboseTrace,3442,prototypeForTag,3443,chainStackTraces,3444,get$chainStackTraces,3444,argumentError,3445,super$SourceSpanMixin$$eq,3446,retry,3447,get$retry,3447,arg,3448,skipReason,3449,_convertedObjects,3450,onPlatform,3451,uri,3452,get$uri,3452,portStart,3453,skipped,3454,get$skipped,3454,textInside,3455,maxItems,3456,maxLineLength,3457,original,3458,get$original,3458,_runGroup$body$Engine,3459,host,3460,get$host,3460,_prettyPrint,3461,_runLiveTest$body$Engine,3462,indent,3463,_runSkippedTest$body$Engine,3464,computation,3465,orElse,3466,countSuccess,3467,K2,3468,$protected,3469,spec,3470,pp,3471,super$DelegatingStreamSubscription$onError,3472,object,3473,ex,3474,subscription,3475,super$DelegatingStreamSubscription$cancel,3476,bodyFunction,3477,tables,3478,data,3479,get$data,3479,_foreign,3480,set$_foreign,3480,_disabled,3481,get$_disabled,3481,test$9$onPlatform$retry$skip$solo$tags$testOn$timeout,586,_onTestStarted,3482,get$_onTestStarted,3482,newDartList$1,3483,configure$1$mapper,3484,elapsedMicroseconds,3485,get$elapsedMicroseconds,3485,_captured_argumentError_0,3486,_platform_selector$_captured_this_0,3487,_completeWithValue,3488,get$_completeWithValue,3488,_parser$_captured_this_0,3489,_isScheduled,3490,get$_isScheduled,3490,hashMapCellKey,3491,_captured_future_1,3492,_closeChannel,3493,get$_closeChannel,3493,encode$1,3494,_error,3495,get$_error,3495,_core$_start,3496,onClose,3497,get$onClose,3497,_captured_callback_1,3498,_completeError,3499,get$_completeError,3499,onData$1,3408,_captured_doneSignal_2,3500,_captured_result_2,3501,configure$3$except$mapper$only,3484,separators,3502,set$separators,3502,_async_memoizer$_completer,3503,_counterKey,3504,_captured_V1_2,3505,prettyUri,3506,get$prettyUri,3506,_captured_serializedOnPlatform_0,3507,_compareSets,3508,get$_compareSets,3508,fold$1$2,3509,getRoot,3510,get$getRoot,3510,_newSet$0,3511,_captured_stackTrace_3,3512,_isPort$1,3513,catchError$1,3514,*,3515,get$*,3515,_and$0,3516,_captured_verboseTrace_4,3517,_scanOperator$1,3518,_writeFirstLine$1,3519,_handleUncaughtError,3520,get$_handleUncaughtError,3520,set$_handleUncaughtError,3520,_failedGroup,3521,_kind,3522,isOdd,3523,get$isOdd,3523,_findLine,3524,get$_findLine,3524,_captured_V_3,3525,_currentNode,3526,set$_currentNode,3526,_onSuiteStartedController,3527,_captured_f_0,3528,_requestedResources,3529,indexOf$2,3530,_precomputed4,3531,_consumeValue$0,3532,replaceAll$2,3533,_completer,3534,tags,3535,_captured_sdkRoot_3,3536,_previous,3537,needsSeparatorPattern,3538,_run,3539,get$_run,3539,set$_run,3539,replace$1$path,3540,_collection$_add,3541,get$_collection$_add,3541,_shlPositive$1,3542,_ensureController,3543,get$_ensureController,3543,_location,3544,get$_location,3544,_mayAddListener,3545,get$_mayAddListener,3545,_captured_terse_2,3546,_preGrow,3547,get$_preGrow,3547,evaluate$1,3548,_base,3549,_isWithinOrEqualsFast,3550,get$_isWithinOrEqualsFast,3550,_modified$0,3551,shouldBeDone,3552,get$shouldBeDone,3552,isBlink,3553,_currentCodePoint,3554,_addResult,3555,get$_addResult,3555,_source_map_stack_trace$_box_0,3556,typedMatches$2,3557,moveNext$0,3558,_execAnchored$2,3559,duration,3560,_onSinkDisconnected$0,3561,isCompleted,3562,get$isCompleted,3562,query,3563,get$query,3563,visitVariable$1,3564,bindCallback,3565,get$bindCallback,3565,_currentTrace,3566,get$_currentTrace,3566,sourceRoot,3567,take,3568,get$take,3568,_progressLine$2$suffix,3569,listenerHasError,3570,liveTests,3571,get$liveTests,3571,createPeriodicTimer,3572,_live_suite_controller$_onCloseCompleter,3573,_remote_listener$_captured_controller_0,3574,_onCancel$0,3575,pathsEqual,3576,get$pathsEqual,3576,distance,3577,get$distance,3577,_core$_position,3578,asStream$0,3579,abs$0,3580,verticalLine,1935,get$verticalLine,1935,listenerValueOrError,3581,_decrementPauseCount$0,3582,_html_common$_captured_this_1,3583,hasTrailingSeparator,3584,get$hasTrailingSeparator,3584,_stack_trace_formatter$_captured_this_0,3585,_declarer$_name,3586,_stack_zone_specification$_registerBinaryCallback$4,3587,_tail,3588,asUint8List$2,3589,isScaffoldAll,3590,_captured_test_1,3591,isWithin$2,3592,_platform_selector$_captured_validVariables_0,3593,_functions$_box_0,3594,_passed,3595,addTearDown$1,3596,_iterator,3597,hashMapCellValue,3598,_captured_K1_1,3599,lastSpan,3600,get$lastSpan,3600,_environment,3601,registerCallback$1$1,3602,handleUncaughtError$3,3603,_stack_zone_specification$_captured_this_1,3604,allMatches$2,3605,_position,3606,_expr,3607,_data,3608,_suiteChannel,3609,_captured_suite_1,3610,onListen,3611,_recursiveMatch$4,3612,_writeSidebar$2$end$line,3613,_onCancelBroadcast$0,3614,__internal$_iterable,3615,_buffer,3616,_flush$0,3617,_captured_identifier_0,3618,_invoker$_print$1,3619,handleUncaughtError,3603,get$handleUncaughtError,3603,scan,3620,get$scan,3620,onCancel,3621,_schedule$0,3622,_metadata,3623,_colorize$1,3624,_captured_sdkRoot_2,3625,_target,3626,_multiline,3627,_paddingBeforeSidebar,3628,_startIndex,3629,get$_startIndex,3629,_specializedTestResource,3630,_isInt32$1,3631,_contains,3632,get$_contains,3632,_handleError$3,3633,_modified,3551,get$_modified,3551,_runPool,3634,_setPendingComplete$0,3635,_simpleExpression$0,3636,_rootRunUnary$5,3637,_cloneResult$1,3638,_trimVMChain,3639,get$_trimVMChain,3639,_live_test_controller$_run,3640,get$_live_test_controller$_run,3640,_collection$_first,3641,_serializeTimeout,3642,get$_serializeTimeout,3642,relative$1,3643,_collectTraces,3644,_span_exception$_message,3645,_onRun,3646,join,3647,get$join,3647,_stack_zone_specification$_errorCallback$5,3648,_stack_zone_specification$_registerUnaryCallback$4,3649,_closeMemo,3650,change$4$onPlatform$skip$skipReason$timeout,3651,addAll$1,3652,_isPaused,3653,get$_isPaused,3653,previous,3654,_async$_addError$2,3655,_captured_minified_4,3656,_queryStart,3657,_captured_eagerError_4,3658,_captured_T_2,3659,join$8,3647,whenComplete$1,3660,position,3661,get$position,3661,set$position,3661,_newLinkedCell$2,3662,asCurrent$1$1,3663,addDescriptionOf$1,3664,_captured_orElse_1,3665,_captured_subscription_0,3666,_count,3667,_isPort,3513,get$_isPort,3513,_eval,3668,get$_eval,3668,_addEventError,3669,get$_addEventError,3669,_optionalPositional,3670,encode,3494,get$encode,3494,_writeToList$1,3671,getRoot$1,3510,_hasPending,3672,get$_hasPending,3672,_test,3673,_runner_suite$_captured_this_0,3674,_captured_zone_0,3675,_invoker$_controller,3676,setRange$4,3677,write$1,3678,_captured_maxItems_0,3679,_isClosed,3680,_closeInnerChannel$0,3681,_closable,3682,get$_closable,3682,update,3683,get$update,3683,_newSet,3511,get$_newSet,3511,_post_message_channel$_captured_controller_0,3684,_collection$_current,3685,set$_collection$_current,3685,_thenAwait$1$2,3686,_upgrade$0,3687,_fetch,3688,get$_fetch,3688,isNewSegment,3689,where$1,3378,_semantics,3690,internalFindBucketIndex,3691,get$internalFindBucketIndex,3691,_stack_zone_specification$_registerCallback$4,3692,_cachedLine,3693,_live_suite_controller$_controller,3694,_cancel,3695,get$_cancel,3695,isPassing,3696,get$isPassing,3696,_lineStart,3697,_noColor,3698,_forEachListener$1,3699,_isDebugging,3700,fillRange$3,3701,_second,3702,removeTrailingSeparators,3703,get$removeTrailingSeparators,3703,_errorName,3704,get$_errorName,3704,_union_set_controller$_set,3705,set$_union_set_controller$_set,3705,visitAnd$1,3706,_pool$_closeMemo,3707,_chainFuture,3708,get$_chainFuture,3708,declare$1,3709,needsSeparator$1,3710,second,3711,get$second,3711,_isCanceled,3712,get$_isCanceled,3712,handleNext$1,3713,_disjoint,3714,_liveTest,3715,_ensurePendingEvents$0,3716,failed,3717,get$failed,3717,_parse$1,3718,_lastMatch,3719,replaceRange$3,3720,_carry,3721,expand$1$1,3722,_stack_zone_specification$_captured_this_0,3723,isAbsolute,3724,get$isAbsolute,3724,peek,3725,get$peek,3725,_captured_object_1,3726,_rootRegisterCallback$4,3727,_doneCompleter,3728,isValue,3729,get$isValue,3729,distance$1,3577,_defaultSplit$1,3730,_execGlobal$2,3731,_simpleExpression,3636,get$_simpleExpression,3636,_onResourceReleaseAllowed$1,3732,topLeftCorner,1932,get$topLeftCorner,1932,_shrBothPositive$1,3733,_captured_longest_0,3734,_stack_zone_specification$_registerCallback,3692,get$_stack_zone_specification$_registerCallback,3692,_captured_error_0,3735,_remove$1,3736,_string,3737,padRight$1,3738,_async$_iterator,3739,set$_async$_iterator,3739,success,3740,get$success,3740,_stack_zone_specification$_captured_stackTrace_2,3741,_pendingIds,3742,_toNonSimple,3743,get$_toNonSimple,3743,_captured_spec_6,3744,readChar$0,3745,scaleFactor,3746,__js_helper$_string,3747,_stream_group$_controller,3748,set$_stream_group$_controller,3748,_serializeGroup,3749,get$_serializeGroup,3749,microsecond,3750,get$microsecond,3750,_checkNotBuilt,3751,get$_checkNotBuilt,3751,_computeKeys$0,3752,binaryOnError,3753,_or$0,3754,_captured_computation_1,3755,_execAnchored,3559,get$_execAnchored,3559,_findBucketIndex,3756,get$_findBucketIndex,3756,release,3757,get$release,3757,_runner_suite$_close$0,3758,union,3759,get$union,3759,_iterable,3760,_setRangeFast$4,3761,_captured_countSuccess_2,3762,_map,3763,internalSet$2,3764,_checkModification$1,3765,single,3766,get$single,3766,_captured_K_2,3767,joinAll$1,3768,configure,3484,get$configure,3484,_isEmpty,3769,get$_isEmpty,3769,load,3770,get$load,3770,pipe,3771,get$pipe,3771,identicalInJs$2,3772,_asyncCompleteError,3773,get$_asyncCompleteError,3773,_lazy_trace$_trace,3774,get$_lazy_trace$_trace,3774,hashCode,3775,get$hashCode,3775,_pool,3776,onError$1,3472,decrement$0,3777,registerUnaryCallback,3778,get$registerUnaryCallback,3778,_maxAllocatedResources,3779,isComplete,3780,get$isComplete,3780,indexable,3781,hasTokens,3782,get$hasTokens,3782,_html$_onData,3783,set$_html$_onData,3783,__js_helper$_strings,3784,pathSegments,3785,get$pathSegments,3785,_green,3786,_captured_registered_1,3787,describeTypedMismatch$4,3788,_expected,3789,parse,2447,get$parse,2447,whenFalse,3790,decode$2$reviver,3791,_captured_f_1,3792,any$1,3793,convert,3794,get$convert,3794,[]=,3795,get$[]=,3795,_future_group$_completer,3796,_add$1,3797,_fetch$1,3688,matchTypeError$1,3798,_last,3799,unclosable,3800,get$unclosable,3800,replace,3540,get$replace,3540,containsKey$1,3801,_runGroup$3,3802,_queue_list$_grow$0,3803,_captured_predicate_0,3804,minute,3805,get$minute,3805,_parser$_length,3806,_setUpAllTrace,3807,codeUnitAt,3808,get$codeUnitAt,3808,modifiedObject,3809,_captured_completer_0,3810,newJsObject$0,3811,active,3812,get$active,3812,_lastProgressSuffix,3813,_captured_index_1,3814,padRight,3738,get$padRight,3738,_dedupIterable,3815,get$_dedupIterable,3815,_eval$1,3668,_live_suite_controller$_captured_this_0,3816,endsWith,3817,get$endsWith,3817,_captured_streamConsumer_0,3818,removeLast$0,3819,urls,3820,_captured_hasError_3,3821,_remote_listener$_captured_this_1,3822,_varData,3823,_name,3824,_coverage,3825,_endIndex,3826,get$_endIndex,3826,codeUnitsEqual,3827,get$codeUnitsEqual,3827,_captured_s_2,3828,toTrace,3829,get$toTrace,3829,_segmentError$2,3830,_closeGroup,3831,bindUnaryCallback,3832,get$bindUnaryCallback,3832,_collection$_length,3833,_runner_suite$_controller,3834,_js_util$_captured_T_1,3835,_delegationTarget,3836,storedCallback,3837,_solo,3838,get$_solo,3838,round$0,3839,_bind$1,3840,errorCallback$2,3841,_captured_V1_3,3842,_allowMalformed,3843,lastIndexOf,3844,get$lastIndexOf,3844,_expanded$_onError,3845,get$_expanded$_onError,3845,_setUpAll,3846,get$_setUpAll,3846,_core_matchers$_description,3847,_callback,3848,_skip,3849,dart2jsArgs,3850,cancel,3476,get$cancel,3476,skipWhile$1,3389,group$1,587,_subscription_stream$_captured_error_1,3851,_resultOrListeners,3852,relativeRootPattern,3853,_onError,3854,get$_onError,3854,_createController$0,3855,_collection$_previous,3856,_setError$2,3857,_isNearCachedLine,3858,get$_isNearCachedLine,3858,convert$3,3794,_setBase,3859,get$_setBase,3859,_compareIterables$5,3860,add$1,3861,bindUnaryCallback$2$1,3832,_listenToStream,3862,get$_listenToStream,3862,_html_common$_box_0,3863,visitNot$1,3864,upEnd,1916,get$upEnd,1916,complete,3865,get$complete,3865,cast,3866,get$cast,3866,_skippedGroup,3867,_type_matcher$_name,3868,lastIndexOf$1,3844,_errorExplanation,3869,get$_errorExplanation,3869,close$0,3870,highlight$1$color,3871,_onCancelBroadcast,3614,get$_onCancelBroadcast,3614,_mappings,3872,putIfAbsent,3873,get$putIfAbsent,3873,_captured_performance_0,3874,_completeError$2,3499,isFinite,3875,get$isFinite,3875,runSkipped,3876,get$runSkipped,3876,isUnicode,3877,get$isUnicode,3877,_upgrade,3687,get$_upgrade,3687,span$2,3376,addError$1,3878,toChain$0,3879,__js_helper$_map,3880,_captured_this_1,3881,setUpAll,3882,_noRetry,3883,spanFor$4$files$uri,3884,_errorCallback,3885,get$_errorCallback,3885,set$_errorCallback,3885,_captured_onData_0,3886,count,3887,whenComplete,3660,get$whenComplete,3660,_isComplete,3888,get$_isComplete,3888,_captured_span_2,3889,_captured_groups_2,3890,setAll$2,3891,_onValue,3892,get$_onValue,3892,setDestinationSink$1,3893,_getNext$0,3894,packageConfigMap,3895,get$packageConfigMap,3895,_captured_tables_0,3896,writeln$1,3897,registerUnaryCallback$2$2,3778,_printPlatform,3898,skip$1,3441,_trace,3899,_mayResumeInput,3900,get$_mayResumeInput,3900,invalidValue,3901,_recordPause,3902,get$_recordPause,3902,_captured_T1_3,3903,_span_scanner$_scanner,3904,_bold,3905,_file$_start,3906,noMoreLiveTests$0,3907,change,3651,get$change,3651,_unlisten$0,3908,_engine$_runCalled,3909,_string_scanner$_position,3910,removeFragment$0,3911,_released,3912,_setValue$1,3913,firstMatch$1,3914,_captured_originalSource_0,3915,union$1,3759,liveSuite,3916,get$liveSuite,3916,_next,3917,_internal,3918,_isFile,3919,get$_isFile,3919,isLoadSuite,3920,get$isLoadSuite,3920,where,3378,get$where,3378,_streamController,3921,set$_streamController,3921,unclosable$1$1,3800,_addEventListener,3922,get$_addEventListener,3922,_endOrLength,3923,resolveUri$1,3924,__js_helper$_addHashTableEntry,3925,get$__js_helper$_addHashTableEntry,3925,whenTrue,3926,serialize$0,2631,highlight$0,3871,isEmpty,3927,get$isEmpty,3927,_multiLineComment,3928,get$_multiLineComment,3928,_iterable_set$_base,3929,_checkState,3930,get$_checkState,3930,_captured_future_3,3931,addAll$4,3652,_thenAwait,3686,get$_thenAwait,3686,_inCallback,3932,get$_inCallback,3932,_expanded$_captured_this_0,3933,files,3934,splitMapJoin,3935,get$splitMapJoin,3935,visitNot,3864,get$visitNot,3864,toFilePath$0,3936,internalRemove$1,3937,toolString,3938,get$toolString,3938,toString,3379,get$toString,3379,_failClosed$0,3939,_toListFixed$0,3940,glyphOrAscii,1931,get$glyphOrAscii,1931,_captured_platform_0,3941,_lazy_trace$_captured_this_0,3942,remaining,3943,_captured_portStart_1,3944,_conditional,3945,get$_conditional,3945,_equals_matcher$_match,3946,get$_equals_matcher$_match,3946,_pathSegments,3947,set$_pathSegments,3947,firstWhere,3948,get$firstWhere,3948,floor,3949,get$floor,3949,padLeft$2,3950,_captured_R_5,3951,_trace$_captured_longest_0,3952,onMessage,3953,get$onMessage,3953,_addedSuites,3954,_captured_host_0,3955,_captured_skipped_1,3956,_expanded$_color,3957,_stack_zone_specification$_run,3958,get$_stack_zone_specification$_run,3958,change$1$onPlatform,3651,_mergePaths$2,3959,getText$2,3960,_declarer$_trace,3961,_captured_handleError_1,3962,_isHttp,3963,get$_isHttp,3963,_lastProgressPassed,3964,month,3965,get$month,3965,apply$1,3966,_captured_outstandingCallbacksForBody_1,3967,_createController,3855,get$_createController,3855,_badEventState$0,3968,_captured_validVariables_0,3969,canonicalizePart$1,3970,forEach,3005,get$forEach,3005,toRadixString$1,3971,message$2$color,3370,_asyncCompleteError$2,3773,join$2,3647,update$2,3683,_collection$_cell,3972,_simpleMerge,3973,get$_simpleMerge,3973,_runLiveTest$2,3974,_addRequest$1,3975,_removeHashTableEntry,3976,get$_removeHashTableEntry,3976,_onResourceReleaseAllowed,3732,get$_onResourceReleaseAllowed,3732,validate$1,3977,_queue_list$_table,3978,set$_queue_list$_table,3978,_future_group$_pending,3979,matchesErrorTest,3980,get$matchesErrorTest,3980,_removeListener,3981,get$_removeListener,3981,hasErrorTest,3982,get$hasErrorTest,3982,_expanded$_onDone$1,3983,_onPause$0,3984,packageConfigUri,3985,_lastProgressSkipped,3986,_engine$_box_0,3987,_check,3988,isRelative$1,3989,_captured_selector_0,3990,_retry,3991,_input,3992,addEventListener$3,3366,nextIteration,3993,_timeString$1,3994,pointSpan$0,3995,variableName,3996,_schemeCache,3997,insert,3998,get$insert,3998,day,3999,get$day,3999,_lazy_trace$_captured_predicate_1,4000,putIntoMap$3,4001,_live_test_controller$_state,4002,lines,4003,get$lines,4003,_recordCancel$1,4004,_sendError$2,4005,_newHashTable,4006,get$_newHashTable,4006,removeFirst$0,4007,_runOnRelease$1,4008,_findColumn,4009,get$_findColumn,4009,_removeListeners$0,4010,trim,4011,get$trim,4011,_stream_queue$_close$0,4012,_queue_list$_head,4013,indexOf$1,3530,__js_helper$_index,4014,isDartVM,4015,_stream_sink_completer$_sink,4016,get$_stream_sink_completer$_sink,4016,_flush,3617,get$_flush,3617,virtualChannel$0,4017,listeners,4018,_host,4019,_stream_queue$_subscription,4020,set$_stream_queue$_subscription,4020,_addRequest,3975,get$_addRequest,3975,bindCallbackGuarded,4021,get$bindCallbackGuarded,4021,handleError$1,3357,containsSeparator$1,4022,inMinutes,4023,get$inMinutes,4023,endColumn,4024,_streamCompleter,4025,right,4026,setRange$3,3677,hasAbsolutePath,4027,get$hasAbsolutePath,4027,_mergePaths,3959,get$_mergePaths,3959,_re,4028,varData,4029,expand$1,3722,onComplete,4030,get$onComplete,4030,_get,4031,get$_get,4031,toUri,4032,get$toUri,4032,_fragmentStart,4033,_outgoingConnections,4034,hasPort,4035,get$hasPort,4035,_collection$_modified,4036,get$_collection$_modified,4036,runtime,4037,getLine,4038,get$getLine,4038,_countTabs$1,4039,_nativeAnchoredRegExp,4040,_waitsForCancel,4041,get$_waitsForCancel,4041,file,2764,run$1$1,4042,_captured_ex_0,4043,errorZone,4044,get$errorZone,4044,foundResult,4045,relative$2$from,3643,_onSuiteAddedController,4046,_captured_future_2,4047,run$0,4042,virtualChannel,4017,get$virtualChannel,4017,_setSourceStream$1,4048,_incomingConnections,4049,_setUpAlls,4050,getColumn$1,4051,_element,4052,_errorTest,4053,get$_errorTest,4053,_argumentsExpr,4054,schedule$1,4055,_collection$_captured_result_0,4056,_sinkCompleter,4057,_eventScheduled,4058,get$_eventScheduled,4058,_writeTrailingLines,4059,get$_writeTrailingLines,4059,removeTrailingSeparators$0,3703,rootLength$2$withDrive,4060,_live_suite_controller$_captured_liveTest_1,4061,normalize$1,4062,_closableKey,4063,_live_test_controller$_controller,4064,isSync,4065,_parent,4066,source,4067,scheduleMicrotask,302,get$scheduleMicrotask,302,_engine$_runLiveTest$3$countSuccess,4068,_isPendingComplete,4069,get$_isPendingComplete,4069,message$1,3370,_captured_line_0,4070,copyList$2,4071,_writeSurrogate$2,4072,_serializeTest,4073,get$_serializeTest,4073,_fillBuffer$3,4074,toJson$0,4075,_writeLastLine,4076,get$_writeLastLine,4076,_schedule,3622,get$_schedule,3622,addOutstandingCallback,4077,get$addOutstandingCallback,4077,_codeUnitAt$1,4078,chainFor$1,4079,_serializeTimeout$1,3642,~/,4080,get$~/,4080,print$1,412,_addHashTableEntry$2,4081,$package,4082,get$$package,4082,_stack_zone_specification$_registerBinaryCallback,3587,get$_stack_zone_specification$_registerBinaryCallback,3587,isHeadless,4083,completeError,4084,get$completeError,4084,verboseChain,4085,containsSeparator,4022,get$containsSeparator,4022,_addHashTableEntry,4081,get$_addHashTableEntry,4081,_declarer$_parent,4086,_stream_group$_subscriptions,4087,listen$4$cancelOnError$onDone$onError,4088,describeMismatch$4,4089,closed,4090,get$closed,4090,_streamQueue,4091,_runSetUps$0,4092,_captured_indent_0,4093,_checkPosition$3,4094,_prefix$1,4095,_linkStreamToController,4096,get$_linkStreamToController,4096,setSourceStream,4097,get$setSourceStream,4097,targetUrl,4098,_and,3516,get$_and,3516,peek$0,3725,__js_helper$_message,4099,inMilliseconds,4100,get$inMilliseconds,4100,_async$_previous,4101,set$_async$_previous,4101,_captured__convertedObjects_0,4102,_entries,4103,_setPendingEvents,4104,get$_setPendingEvents,4104,listen$2$onDone,4088,_captured_node_2,4105,addDescriptionOf,3664,get$addDescriptionOf,3664,__internal$_length,4106,_guardIfGuarded$1,4107,scan$1,3620,_runOnRelease,4008,get$_runOnRelease,4008,done,4108,get$done,4108,_platformVariables,4109,_isOnlyWhitespace$1,4110,isJS,4111,isEof,4112,sourceLine,4113,_runSetUps,4092,get$_runSetUps,4092,matchesErrorTest$1,3980,_f,4114,isBroadcast,4115,get$isBroadcast,4115,_captured_invoker_0,4116,_remote_listener$_box_0,4117,_conditional$0,3945,_tearDowns,4118,_close,4119,get$_close,4119,endsWith$1,3817,_nextId,4120,addAll,3652,get$addAll,3652,_captured_liveTest_0,4121,_engine$_closed,4122,_writeText,4123,get$_writeText,4123,matchAsPrefix,4124,get$matchAsPrefix,4124,_guarded,4125,_lazy_trace$_inner,4126,set$_lazy_trace$_inner,4126,_runGroup,3802,get$_runGroup,3802,__js_helper$_unlinkCell$1,4127,describe,3396,get$describe,3396,setSourceStream$1,4097,_failed,4128,_stack_zone_specification$_box_0,4129,_lazy_chain$_captured_this_0,4130,_colorize,3624,get$_colorize,3624,relativePathToUri,4131,get$relativePathToUri,4131,_isChained,4132,get$_isChained,4132,newJsMap$0,4133,_allocatedResources,4134,_color,4135,_mayAddEvent,4136,get$_mayAddEvent,4136,_group$_map$1,4137,_multi_channel$_captured_this_1,4138,_computeHashCode$1,4139,_complete$1,4140,_async$_captured_result_2,4141,_ensurePendingEvents,3716,get$_ensurePendingEvents,3716,_captured_e_1,4142,_null_stream_sink$_captured_this_0,4143,_captured_printZone_0,4144,_isAddingStream,4145,get$_isAddingStream,4145,_collection$_newLinkedCell,4146,get$_collection$_newLinkedCell,4146,_shrReceiverPositive,4147,get$_shrReceiverPositive,4147,fragment,4148,get$fragment,4148,_sendData,4149,get$_sendData,4149,_pauseCount,4150,runUnary$2$2,4151,_upgradedMap,4152,get$_upgradedMap,4152,_scanner,4153,precompiledPath,4154,_html$_target,4155,_hashCodeCache,4156,runGuarded,4157,get$runGuarded,4157,_lastSpan,4158,toList,4159,get$toList,4159,_verboseTrace,4160,_whenCompleteAction,4161,get$_whenCompleteAction,4161,relativePathToUri$1,4131,replaceAllMapped$2,4162,_as,4163,_captured_counter_3,4164,_nativeGlobalRegExp,4165,allMatches,3605,get$allMatches,3605,_soloEntries,4166,_writeTrailingLines$1,4059,addSubscription,4167,_writeSurrogate,4072,get$_writeSurrogate,4072,increment$0,4168,_captured_R_4,4169,_onResourceReleased$0,4170,_strings,4171,_handle,4172,hasListener,4173,get$hasListener,4173,_ensureDoneFuture$0,4174,_stack_zone_specification$_handleUncaughtError$5,4175,_captured_printZone_1,4176,_invokerZone,4177,_captured_transform_1,4178,evaluate,3548,get$evaluate,3548,_findBucketIndex$2,3756,pause$0,4179,_compareSets$5,3508,runUnaryGuarded$1$2,4180,spanFrom,4181,get$spanFrom,4181,fold,3509,get$fold,3509,_config,4182,_runner_suite$_onClose,4183,_zone,4184,get$_zone,4184,_stream_sink_completer$_controller,4185,set$_stream_sink_completer$_controller,4185,_captured_textInside_1,4186,pipe$1,3771,[],4187,get$[],4187,_lastProgressMessage,4188,matches$2,3347,_captured_fn_2,4189,_ensureController$0,3543,lastPendingEvent,4190,inMicroseconds,4191,get$inMicroseconds,4191,joinAll,3768,get$joinAll,3768,visitConditional$1,4192,__internal$_index,4193,_stream_sink_completer$_doneCompleter,4194,inSeconds,4195,get$inSeconds,4195,_onStateChangeController,4196,_cachedRuntimeType,4197,_captured_controller_0,4198,packageResolver,4199,_captured_eagerError_2,4200,_captured_T2_4,4201,_onClose,4202,_groups,4203,_addEventError$0,3669,convertNativeToDart_AcceptStructuredClone$2$mustCopy,2104,_duration,4204,_addHashTableEntry$3,4081,_decodedChars,4205,parents,4206,parent,4207,get$parent,4207,skipWhile,3389,get$skipWhile,3389,runGuarded$1,4157,join$1,3647,_jsObject,4208,_captured_test_0,4209,_stream_group$_state,4210,startsWith$2,4211,_set,4212,get$_set,4212,absolute$1,4213,foreign,4214,get$foreign,4214,_collection$_add$1,3541,_hasError,4215,get$_hasError,4215,merge,4216,get$merge,4216,registerUnaryCallback$2$1,3778,firstWhere$2$orElse,3948,handleValue$1,4217,resolve,4218,get$resolve,4218,_message,4219,bindCallbackGuarded$1,4021,_updateRequests,4220,get$_updateRequests,4220,_delegateCache,4221,_recordCancel,4004,get$_recordCancel,4004,hasFragment,4222,get$hasFragment,4222,traces,4223,get$traces,4223,isScheduled,4224,get$isScheduled,4224,_union_set$_iterable,4225,get$_union_set$_iterable,4225,parse$0,2447,_onCloseCompleter,4226,isNotEmpty,4227,get$isNotEmpty,4227,_test$_captured_body_0,4228,hasScheme,4229,get$hasScheme,4229,_closedBeforeDone,4230,_span_exception$_span,4231,_captured_cleanUp_1,4232,_source,4233,fuse$1$1,4234,_isNearCachedLine$1,3858,_live_suite_controller$_suite,4235,_runTearDowns,4236,get$_runTearDowns,4236,rootLength,4060,get$rootLength,4060,trim$0,4011,_captured_elements_0,4237,addStream$2$cancelOnError,4238,_precomputed3,4239,_completeError$1,3499,_checkEventAllowed,4240,get$_checkEventAllowed,4240,_captured_terse_0,4241,patterns,4242,_setEmpty$0,4243,_fragment,4244,createTimer,4245,get$createTimer,4245,variables,4246,_chainFuture$1,3708,_onDebuggingController,4247,_captured_protected_0,4248,every,4249,get$every,4249,_trace$_captured_trace_0,4250,location$1,3343,perform,4251,get$perform,4251,completeError$1,4084,_captured_bodyFunction_0,4252,_allowInvalid,4253,change$1$timeout,3651,_countTabs,4039,get$_countTabs,4039,_pool$_captured_this_0,4254,outputId,4255,_onResume$0,4256,_extraUnits,4257,toUpperCase$0,4258,__js_helper$_addHashTableEntry$3,3925,_equals_matcher$_value,4259,_controller,4260,_multi_channel$_captured_this_0,4261,_group,4262,_addStreamSubscription,4263,set$_addStreamSubscription,4263,_queue_list$_add$1,4264,forEachJsField,4265,get$forEachJsField,4265,glyphOrAscii$2,1931,_writeLastLine$1,4076,_regExp,4266,__js_helper$_nums,4267,_getTableBucket,4268,get$_getTableBucket,4268,_convert$_computeKeys,4269,get$_convert$_computeKeys,4269,_mapping,4270,millisecondsSinceEpoch,4271,get$millisecondsSinceEpoch,4271,_cell,4272,_checkNotBuilt$1,3751,connectOut$1,4273,_sets,4274,_onUnpaused,4275,get$_onUnpaused,4275,_genericClosure,4276,_mapContents,4277,_captured_indent_2,4278,_innerStreamSubscription,4279,startsWith,4211,get$startsWith,4211,context,2361,get$context,2361,substring$1,4280,matchAsPrefix$2,4124,entries,4281,_multi_channel$_inner,4282,_fillBuffer,4074,get$_fillBuffer,4074,hasRun,4283,get$hasRun,4283,forEachJsField$2,4265,_stack_zone_specification$_onError,4284,elapsedTicks,4285,get$elapsedTicks,4285,_onTestStartedGroup,4286,tearDownAll,4287,_matcher,4288,_engine,4289,_onSinkDisconnected,3561,get$_onSinkDisconnected,3561,containsKey,3801,get$containsKey,3801,_captured_future_0,4290,_captured_getTag_0,4291,error$3$length$position,2966,names,4292,internalContainsKey$1,4293,_runTearDowns$0,4236,_captured_start_2,4294,_addStreamState,4295,set$_addStreamState,4295,_extractStream,4296,get$_extractStream,4296,cancel$0,3476,setState$1,4297,substring,4280,get$substring,4280,clear,4298,get$clear,4298,errorCallback$3,3841,_stop,4299,_stream_group$_closed,4300,os,4301,hasPartialInput,4302,get$hasPartialInput,4302,_getBucket,4303,get$_getBucket,4303,_timeout,4304,parts,4305,set$parts,4305,_pathDirection,4306,get$_pathDirection,4306,describeTypedMismatch,3788,get$describeTypedMismatch,3788,findSlot$1,4307,_scheduleMicrotask,4308,get$_scheduleMicrotask,4308,set$_scheduleMicrotask,4308,_loadPool,4309,_canSendDirectly,4310,get$_canSendDirectly,4310,local,4311,get$local,4311,hour,4312,get$hour,4312,packageRoot,4313,get$packageRoot,4313,_endOfFileEmitted,4314,_captured_callback_0,4315,_captured_terse_1,4316,_future_group$_closed,4317,_convert$_value,4318,readSlot$1,4319,fork,4320,get$fork,4320,elementAt$1,4321,_runUnary,4322,get$_runUnary,4322,set$_runUnary,4322,writeAll$2,4323,_captured_callback_3,4324,_captured_arg_1,4325,_progressLine$2$color,3569,writeSlot$2,4326,_async$_next,4327,set$_async$_next,4327,toChain,3879,get$toChain,3879,_hashCode,4328,_onListen,4329,get$_onListen,4329,_captured_sourceResult_2,4330,runOnce$1,4331,_reviver,4332,_invoker$_captured_this_1,4333,toList$1$growable,4159,innerStream,4334,expect$2$name,539,_thunk,4335,_writeToList,3671,get$_writeToList,3671,_ensureListening$0,4336,_chains,4337,visitConditional,4192,get$visitConditional,4192,_captured_listener_1,4338,_failClosed,3939,get$_failClosed,3939,startColumn,4339,matchTypeError,3798,get$matchTypeError,3798,status,4340,toString$0,3379,_runLiveTest,3974,get$_runLiveTest,3974,_removeAfterFiring,4341,get$_removeAfterFiring,4341,_multi_channel$_box_0,4342,_eventType,4343,_head,4344,url,2360,resume,4345,get$resume,4345,__js_helper$_removeHashTableEntry$2,4346,_removeListeners,4010,get$_removeListeners,4010,codeUnitsEqual$2,3827,_match,4347,_isFiring,4348,get$_isFiring,4348,includeTags,4349,_pathDirection$2,4306,_stack_zone_specification$_registerBinaryCallback$3$4,3587,add,3861,get$add,3861,_current,4350,set$_current,4350,_selector2,4351,toString$1$color,3379,_rti,4352,_asyncComplete,4353,get$_asyncComplete,4353,request,4354,get$request,4354,_sendData$1,4149,_gray,4355,listen$3$onDone$onError,4088,matches,3347,get$matches,3347,_stack_zone_specification$_errorCallback,3648,get$_stack_zone_specification$_errorCallback,3648,toFilePath,3936,get$toFilePath,3936,setRange,3677,get$setRange,3677,_except,4356,set$_except,4356,_engine$_subscriptions,4357,_subscription_stream$_source,4358,set$_subscription_stream$_source,4358,_sdkRoot,4359,_recordResume$1,4360,scheme,4361,get$scheme,4361,_expectedUnits,4362,_captured_column_0,4363,convertDartToNative_PrepareForStructuredClone$1,1533,_closeGap$2,4364,_highlighter$_buffer,4365,_sink$_sink,4366,$call,3391,get$$call,3391,map$2$1,4367,_parser0$_scanner,4368,_bindCache,4369,__internal$_name,4370,_only,4371,set$_only,4371,removeEventListener$3,4372,_setTableEntry,4373,get$_setTableEntry,4373,_live_test_controller$_close$0,4374,toTrace$0,3829,_queryParameters,4375,resolveUri,3924,get$resolveUri,3924,__js_helper$_length,4376,_engine$_captured_this_1,4377,_pretty_print$_box_0,4378,addMapping$1,4379,absolute,4213,get$absolute,4213,_out,4380,_captured_R_3,4381,_async$_isClosed,4382,get$_async$_isClosed,4382,flush,4383,get$flush,4383,_captured_getMain_1,4384,_onStateChange,4385,get$_onStateChange,4385,_captured_K1_2,4386,toLowerCase$0,4387,heartbeat$0,4388,_writeFirstLine,3519,get$_writeFirstLine,3519,registerBinaryCallback$3$1,4389,_method,4390,_collection$_writeToList$1,4391,contains$1,4392,_writeSidebar$1$line,3613,removeOutstandingCallback$0,4393,_functions$_captured_value_1,4394,_prependListeners,4395,get$_prependListeners,4395,_core$_data,4396,_chain$_captured_callback_0,4397,_inner,4398,_fork,4399,get$_fork,4399,set$_fork,4399,_extractStream$0,4296,catchError,3514,get$catchError,3514,_nextIndex,4400,_captured_uri_0,4401,_maps,4402,_async$_addError,3655,get$_async$_addError,3655,_bufferIndex,4403,_red,4404,_unlinkCell,4405,get$_unlinkCell,4405,forEachObjectKey,4406,get$forEachObjectKey,4406,isRootRelative$1,4407,addStream,4238,get$addStream,4238,_restarted,4408,_captured_validVariables_1,4409,_doneFuture,4410,_original,4411,_registerCallback,4412,get$_registerCallback,4412,set$_registerCallback,4412,foldFrames$2$terse,4413,normalize$0,4062,_captured_channel_3,4414,_onMessageController,4415,separatorPattern,4416,_isFirstCharacter,4417,_errorZone,4418,contains,4392,get$contains,4392,addStreamFuture,4419,_built,4420,_requiredPositional,4421,_captured_test_2,4422,_table,4423,set$_table,4423,_deleteTableEntry$2,4424,split$1,4425,padLeft,3950,get$padLeft,3950,_group$_captured_callback_0,4426,_listen$1,4427,_parser$_mapUrl,4428,validatePlatformSelectors$1,4429,_shrBothPositive,3733,get$_shrBothPositive,3733,_async$_map,4430,get$_async$_map,4430,hasEmptyPath,4431,get$hasEmptyPath,4431,sublist,4432,get$sublist,4432,_stream,4433,_invoker$_onRun$0,4434,complete$1,3865,_subscribe,4435,get$_subscribe,4435,_captured_x_0,4436,_sourceStream,4437,set$_sourceStream,4437,_completeWithValue$1,3488,_chainStackTraces,4438,_setDestinationSink$1,4439,internalFindBucketIndex$2,3691,addTearDownAll$1,4440,_live_suite_controller$_isComplete,4441,_captured_result_0,4442,_captured_expectedElement_1,4443,getColumn,4051,get$getColumn,4051,_package_config_resolver$_uri,4444,_reverseListeners$1,4445,_collection$_last,4446,findSlot,4307,get$findSlot,4307,_captured_timeout_0,4447,walk$1,4448,_userInfo,4449,formatStackTrace$2$verbose,4450,replaceRange,3720,get$replaceRange,3720,_addResult$1,3555,remove,4451,get$remove,4451,_queue_list$_add,4264,get$_queue_list$_add,4264,_captured_listener_2,4452,__js_helper$_keys,4453,_encoder,4454,runBinary,4455,get$runBinary,4455,_cancelFuture,4456,_future_group$_captured_this_0,4457,handlesComplete,4458,get$handlesComplete,4458,_trace$_box_0,4459,_captured_pos_1,4460,sublist$2,4432,_invoker$_test,4461,get$_invoker$_test,4461,_metadata$_captured_timeout_2,4462,_guarantee_channel$_box_0,4463,cancelSchedule$0,4464,sourceNameId,4465,runtimeType,4466,get$runtimeType,4466,_collection$_modifications,4467,then,4468,get$then,4468,absolute$7,4213,_captured_maxLineLength_1,4469,_subsetMask,4470,_recordResume,4360,get$_recordResume,4360,_forEachListener,3699,get$_forEachListener,3699,testRandomizeOrderingSeed,4471,visitOr,4472,get$visitOr,4472,expect,539,get$expect,539,_lastProgressFailed,4473,internalContainsKey,4293,get$internalContainsKey,4293,splitMapJoin$2$onMatch,3935,_getTableBucket$2,4268,writeln,3897,get$writeln,3897,_convert$_first,4474,_expanded$_onError$3,3845,_removeListener$1,3981,millisecond,4475,get$millisecond,4475,_highlighter$_captured_this_1,4476,validatePlatformSelectors,4429,get$validatePlatformSelectors,4429,_preGrow$1,3547,configure$2$except$only,3484,request$0,4354,_rootRegisterUnaryCallback$4,4477,_async$_captured_f_1,4478,_remote_listener$_captured_this_0,4479,reversed,4480,get$reversed,4480,_queryParameterLists,4481,hasErrorCallback,4482,get$hasErrorCallback,4482,_scanOperator,3518,get$_scanOperator,3518,_captured_testOn_1,4483,split,4425,get$split,4425,left,4484,_listenToStream$1,3862,_live_test_controller$_isClosed,4485,get$_live_test_controller$_isClosed,4485,_codeUnitAt,4078,get$_codeUnitAt,4078,_highlighter$_captured_this_0,4486,_html$_start$0,4487,_chain,4488,get$_chain,4488,_addingStream,4489,_getTableCell$2,4490,forTarget$1,4491,_captured_minified_2,4492,connectOut,4273,get$connectOut,4273,peekChar,4493,get$peekChar,4493,_collection$_next,4494,_equals_matcher$_match$3,3946,cast$2$0,3866,build,4495,get$build,4495,_engine$_runLiveTest$2,4068,_segmentError,3830,get$_segmentError,3830,_process$1,4496,_precomputed2,4497,lastMatch,4498,get$lastMatch,4498,_description,4499,get$_description,4499,_captured_chainStackTraces_5,4500,startsWith$1,4211,_captured_printZone_5,4501,decoder,4502,get$decoder,4502,hasAuthority,4503,get$hasAuthority,4503,unaryOnError,4504,_needsNormalization$1,4505,_collection$_modified$0,4036,onResume,4506,build$0,4495,_or,3754,get$_or,3754,_printPath,4507,_tdivSlow$1,4508,withResource$1$1,3430,_writeText$1,4123,handleNext,3713,get$handleNext,3713,__js_helper$_rest,4509,_paused,4510,_tearDownAll,4511,get$_tearDownAll,4511,_captured_result_3,4512,_lazy_trace$_thunk,4513,waitForOutstandingCallbacks,4514,get$waitForOutstandingCallbacks,4514,_mayComplete,4515,get$_mayComplete,4515,_captured_T_5,4516,$function,4517,_offset,4518,_asyncComplete$1,4353,load$2$groups,3770,_captured_value_1,4519,runUnaryGuarded,4180,get$runUnaryGuarded,4180,bindUnaryCallbackGuarded$1$1,4520,_sendDone$0,4521,_outstandingCallbacks,4522,get$_outstandingCallbacks,4522,extensions,4523,_closeUnchecked,4524,get$_closeUnchecked,4524,_toListGrowable$0,4525,_captured_end_2,4526,_invoker$_captured_this_0,4527,_convert$_computeKeys$0,4269,codeUnits,4528,get$codeUnits,4528,mapStackTrace$1,487,_precomputed1,4529,_stack_zone_specification$_captured_f_1,4530,insert$2,3998,floor$0,3949,internalGet$1,4531,_names,4532,internalGet,4531,get$internalGet,4531,pattern,4533,_captured_stackTrace_1,4534,_liveSuite,4535,_collection$_newLinkedCell$1,4146,then$1$2$onError,4468,_consumeNewLine$0,4536,_live_test_controller$_close,4374,get$_live_test_controller$_close,4374,_newHashTable$0,4006,_metadata$_box_0,4537,suiteSink,4538,get$suiteSink,4538,_port,4539,_passedGroup,4540,_hostStart,4541,_isWithinOrEquals$2,4542,_unlisten,3908,get$_unlisten,3908,_expanded$_captured_liveTest_1,4543,_live_suite_controller$_closeMemo,4544,_captured_target_0,4545,_captured_host_1,4546,_uriCache,4547,_nativeAnchoredVersion,4548,get$_nativeAnchoredVersion,4548,relative,3643,get$relative,3643,_consumeWhitespace,4549,get$_consumeWhitespace,4549,_scanOr$0,4550,_tryResume,4551,get$_tryResume,4551,_runner_suite$_suite,4552,set$_runner_suite$_suite,4552,bind$1,2478,toSet,4553,get$toSet,4553,_captured_level_1,4554,sourceColumn,4555,_nextListener,4556,connectIn$2,4557,_isCaseSensitive,4558,get$_isCaseSensitive,4558,_progressLine,3569,get$_progressLine,3569,_body,4559,waitForOutstandingCallbacks$1,4514,_description$1,4499,encoder,4560,get$encoder,4560,metadata,4561,get$metadata,4561,_isInputPaused,4562,get$_isInputPaused,4562,inHours,4563,get$inHours,4563,allowRelease$1,4564,serialize,2631,get$serialize,2631,_captured_getUnknownTag_0,4565,_invoker$_completer,4566,intersection$1,4567,_ensureDoneFuture,4174,get$_ensureDoneFuture,4174,state,4568,get$state,4568,_state,4569,reportLiveTest$2$countSuccess,4570,_clearPendingComplete$0,4571,_captured_timeout_2,4572,_mapUrl,4573,_controllers,4574,forEachObjectKey$2,4406,fromUri$1,1988,_tearDownAllTrace,4575,_chain$_captured_T_1,4576,_highlighter$_box_0,4577,_multi_channel$_captured_T_2,4578,_subscriptions,4579,every$1,4249,_captured_V_2,4580,_captured_original_1,4581,formatStackTrace,4450,get$formatStackTrace,4450,_subscription_stream$_captured_this_0,4582,_newLinkedCell,3662,get$_newLinkedCell,3662,_stream_queue$_captured_this_0,4583,_runCalled,4584,_testCount,4585,onDone$1,4586,_isInitialState,4587,get$_isInitialState,4587,_stack_zone_specification$_registerUnaryCallback$2$4,3649,isEven,4588,get$isEven,4588,completeError$2,4084,_checkState$1,3930,_types,4589,get$_types,4589,_stack_zone_specification$_registerUnaryCallback,3649,get$_stack_zone_specification$_registerUnaryCallback,3649,_closeInnerChannel,3681,get$_closeInnerChannel,3681,root,4590,_writeIntermediateLines$1,4591,library,4592,get$library,4592,_multiLineComment$0,3928,_hasValue,4593,member,4594,get$member,4594,addStream$1,4238,_lastSubscription,4595,set$_lastSubscription,4595,_onListen$0,4329,dartException,4596,==,3446,get$==,3446,_schemeEnd,4597,__js_helper$_captured_this_0,4598,isPosix,4599,get$isPosix,4599,_hasSkipped,4600,heartbeat,4388,get$heartbeat,4388,_cancel$0,3695,_isUpgraded,4601,get$_isUpgraded,4601,_writeSidebar$0,3613,_print,4602,get$_print,4602,set$_print,4602,_tryResume$0,4551,_rootRegisterBinaryCallback$4,4603,_recordPause$1,3902,_useCapture,4604,firstMatch,3914,get$firstMatch,3914,_captured_port_0,4605,pause$1,4179,type,4606,get$type,4606,_scanIdentifier$0,4607,substring$2,4280,_onDone,4608,set$_onDone,4608,_computeKeys,3752,get$_computeKeys,3752,origin,4609,get$origin,4609,bindUnaryCallbackGuarded,4520,get$bindUnaryCallbackGuarded,4520,convert$1,3794,_multi_channel$_parent,4610,%,4611,get$%,4611,_keysArray,4612,get$_keysArray,4612,runUnary,4151,get$runUnary,4151,_sourceFile,4613,_captured_skip_3,4614,registerBinaryCallback,4389,get$registerBinaryCallback,4389,insertAll$2,4615,_platform_selector$_inner,4616,_captured_pp_0,4617,_engine$_captured_this_0,4618,_eventState,4619,child,4620,forTag,4621,_channel,4622,_captured_iterator_0,4623,checkMutable$1,4624,_captured_controller_3,4625,flush$2,4383,replaceFirst$2,4626,_binarySearch$1,4627,transform$1$1,4628,_mapper,4629,start$0,2491,replace$2$path$pathSegments,3540,_tdivFast$1,4630,_captured_oldPredicate_0,4631,_exception,4632,replace$1$pathSegments,3540,_captured_arg2_2,4633,toUri$1,4032,_suite,4634,isIdentifier,4635,get$isIdentifier,4635,convertNativeToDart_AcceptStructuredClone,2104,get$convertNativeToDart_AcceptStructuredClone,2104,_primary,4636,then$1$1,4468,removeAt,4637,get$removeAt,4637,_captured_div_1,4638,__internal$_current,4639,set$__internal$_current,4639,__js_helper$_current,4640,set$__js_helper$_current,4640,_removeEventListener,4641,get$_removeEventListener,4641,_optionalNamed,4642,onDone,4586,get$onDone,4586,reportLiveTest,4570,get$reportLiveTest,4570,_isSent,4643,get$_isSent,4643,_receiver,4644,forPlatform$1,4645,_runner_suite$_close,3758,get$_runner_suite$_close,3758,_delegate,4646,get$_delegate,4646,firstPendingEvent,4647,inSameErrorZone$1,4648,expect$1,539,intersection,4567,get$intersection,4567,horizontalLine,1933,get$horizontalLine,1933,frames,4649,get$frames,4649,onError,3472,get$onError,3472,_span,4650,_captured_channel_2,4651,group,587,get$group,587,_currentExpansion,4652,set$_currentExpansion,4652,_union_set_controller$_sets,4653,_async$_captured_this_0,4654,_serializeTest$3,4073,_isUnicode,4655,get$_isUnicode,4655,_shlPositive,3542,get$_shlPositive,3542,_lazy_trace$_captured_terse_2,4656,spanFor,3884,get$spanFor,3884,peekChar$0,4493,_writeSidebar,3613,get$_writeSidebar,3613,_expanded$_onDone,3983,get$_expanded$_onDone,3983,_span_exception$_source,4657,__internal$_start,4658,_modifications,4659,_nextPosition,4660,_toEncodable,4661,hasMatch$1,4662,_bind,3840,get$_bind,3840,_canFire,4663,get$_canFire,4663,postMessage$1,4664,_setPendingEvents$1,4104,internalComputeHashCode,4665,get$internalComputeHashCode,4665,_isOnlyWhitespace,4110,get$_isOnlyWhitespace,4110,_outstandingCallbackZones,4666,_captured_zone_1,4667,_isWithinOrEqualsFast$2,3550,rootPattern,4668,_captured_id_1,4669,pause,4179,get$pause,4179,_platform_selector$_span,4670,decode$1,3791,replaceFirst,4626,get$replaceFirst,4626,isUtc,4671,_postMessage_2$1,4672,set,4673,get$set,4673,pathFromUri,4674,get$pathFromUri,4674,_hasOneListener,4675,get$_hasOneListener,4675,_activeLoadTests,4676,_containsTableEntry$2,4677,_restartable_timer$_timer,4678,_recursiveMatch,3612,get$_recursiveMatch,3612,_pendingEvents,4679,get$_pendingEvents,4679,_addError$2,4680,_captured_prototypeForTag_0,4681,_nullErrorHandler$1,4682,_captured_cleanUp_3,4683,+,4684,get$+,4684,_chainSource,4685,get$_chainSource,4685,_complete,4140,get$_complete,4140,_portStart,4686,_isWithinOrEquals,4542,get$_isWithinOrEquals,4542,_printZone,4687,_multi_channel$_captured_T_1,4688,_captured_frame_0,4689,_columnStart,4690,_functions$_captured_result_0,4691,_addLiveSuite$1,4692,_pattern,4693,_onStreamDisconnected$0,4694,describeMismatch,4089,get$describeMismatch,4089,_stackTrace,4695,elapsed,4696,get$elapsed,4696,_process,4496,get$_process,4496,_closeChannel$2,3493,accept$1,4697,_containsTableEntry,4677,get$_containsTableEntry,4677,_async$_subscription,4698,get$_async$_subscription,4698,_packageResolver,4699,_eventsReceived,4700,_isMultiLine,4701,get$_isMultiLine,4701,_errors,4702,_index,4703,onZero,4704,get$onZero,4704,internalRemove,3937,get$internalRemove,3937,_captured_chain_0,4705,_runSkippedTest,4706,get$_runSkippedTest,4706,take$1,3568,visitAnd,3706,get$visitAnd,3706,_captured__prettyPrint_1,4707,_shrReceiverPositive$1,4147,removeAll$1,4708,apply,3966,get$apply,3966,_captured_arg1_1,4709,_callOnCancel$0,4710,firstWhere$1,3948,spanFrom$1,4181,_binarySearch,4627,get$_binarySearch,4627,_computeHashCode,4139,get$_computeHashCode,4139,_onCompleteGroup,4711,last,4712,get$last,4712,_getNext,3894,get$_getNext,3894,_channelNames,4713,sourceUrl,4714,get$sourceUrl,4714,_async$_onListen$1,4715,_resetTimer,4716,get$_resetTimer,4716,runBinary$3$3,4455,pathsEqual$2,3576,_currentTrace$1,3566,perform$1,4251,_liveSuites,4717,_stream_channel_completer$_set,4718,_file$_end,4719,forPlatform,4645,get$forPlatform,4645,_captured_value_2,4720,remove$1,4451,_gatherCoverage,4721,_isHttps,4722,get$_isHttps,4722,_closeUnchecked$0,4524,_captured_result_1,4723,removeFragment,3911,get$removeFragment,3911,_closedIds,4724,_captured_channel_0,4725,isNewLine,4726,handleUncaughtError$2,3603,elementAt,4321,get$elementAt,4321,highlight,3871,get$highlight,3871,_runCount,4727,close,3870,get$close,3870,_add,3797,get$_add,3797,_union_set$_captured_this_0,4728,_runSkipped,4729,_skipped,4730,_stack_zone_specification$_captured_R_2,4731,_writeIntermediateLines,4591,get$_writeIntermediateLines,4591,_isPackage,4732,get$_isPackage,4732,_findLine$1,3524,_expectsEvent$1,4733,_validateTags,4734,get$_validateTags,4734,copy,4735,_captured_error_2,4736,bottomLeftCorner,1937,get$bottomLeftCorner,1937,_addPending$1,4737,_stringSink,4738,expand,3722,get$expand,3722,_get$1,4031,_progressLine$1,3569,toRadixString,3971,get$toRadixString,3971,resolve$1,4218,insertAll,4615,get$insertAll,4615,remainder$1,4739,_inAddStream,4740,get$_inAddStream,4740,_pool$_captured_registered_1,4741,_captured_serialized_0,4742,_addError$1,4680,_onReleaseCompleters,4743,_functions$_captured_result_1,4744,inGoogle,4745,runBinaryGuarded$2$3,4746,_allowErrors,4747,_captured_body_0,4748,registerBinaryCallback$3$2,4389,_createSubscription$4,4749,condition,4750,map,4367,get$map,4367,checkGrowable$1,4751,moveNext,3558,get$moveNext,3558,absolutePathToUri$1,4752,_runtimes,4753,_captured_loadResource_2,4754,_collection$_rest,4755,_addError,4680,get$_addError,4680,registerCallback$1$2,3602,_setRemoveAfterFiring$0,4756,_sink,4757,set$_sink,4757,_captured_retry_6,4758,internalComputeHashCode$1,4665,_linkStreamToController$0,4096,_context$_current,4759,_onResume,4256,get$_onResume,4256,_registerBinaryCallback,4760,get$_registerBinaryCallback,4760,set$_registerBinaryCallback,4760,_ensureListening,4336,get$_ensureListening,4336,_stream_completer$_controller,4761,set$_stream_completer$_controller,4761,isCore,4762,get$isCore,4762,_setDestinationSink,4439,get$_setDestinationSink,4439,_captured_line_1,4763,_invoker$_onRun,4434,get$_invoker$_onRun,4434,getOffset,4764,get$getOffset,4764,listen$1,4088,indexOf,3530,get$indexOf,3530,_createPeriodicTimer,4765,get$_createPeriodicTimer,4765,set$_createPeriodicTimer,4765,_pool$_timeout,4766,mustCopy,4767,_firstSubscription,4768,set$_firstSubscription,4768,_scanner$_next,4769,foldFrames,4413,get$foldFrames,4413,_callOnCancel,4710,get$_callOnCancel,4710,onTestStarted,4770,get$onTestStarted,4770,_scanAnd$0,4771,__js_helper$_removeHashTableEntry,4346,get$__js_helper$_removeHashTableEntry,4346,_sendDone,4521,get$_sendDone,4521,_once,4772,absolutePathToUri,4752,get$absolutePathToUri,4752,_query,4773,config,4774,get$config,4774,_future,4775,removeFirst,4007,get$removeFirst,4007,_subscribe$4,4435,next,4776,get$next,4776,set$next,4776,_removeEventListener$3,4641,style,4777,_invoker$_tearDowns,4778,map$1$1,4367,_contains$1,3632,__js_helper$_getBucket$2,4779,_execGlobal,3731,get$_execGlobal,3731,_removeHashTableEntry$2,3976,complete$0,3865,_stopwatch,4780,decode,3791,get$decode,3791,addOutstandingCallback$0,4077,internalSet,3764,get$internalSet,3764,_getBucket$2,4303,join$0,3647,toSet$0,4553,_active,4781,_rootRun$4,4782,_remove,3736,get$_remove,3736,decrement,3777,get$decrement,3777,_guardCallback,4783,get$_guardCallback,4783,_onTestStartedController,4784,isAbsolute$1,3724,path,4785,get$path,4785,_async$_target,4786,_handleError,3633,get$_handleError,3633,_captured_K2_0,4787,_knownTags,4788,_tick,4789,_onReleaseCallbacks,4790,schedule,4055,get$schedule,4055,_captured_suite_0,4791,_pathStart,4792,_platform_selector$_captured_platform_0,4793,_restartable_timer$_duration,4794,_captured_portSubscription_1,4795,_badEventState,3968,get$_badEventState,3968,_guarantee_channel$_captured_this_0,4796,setEmpty$0,4797,_invalidPosition$3,4798,visitVariable,3564,get$visitVariable,3564,_containsKey$1,4799,_lastMatchPosition,4800,_captured_onPlatform_8,4801,_captured_predicate_1,4802,_addListener$1,4803,_mainController,4804,_colorize$2$color,3624,_guarantee_channel$_captured_this_1,4805,_invoker$_box_0,4806,_length,4807,typedMatches,3557,get$typedMatches,3557,_sendError,4005,get$_sendError,4005,nextKind,4808,get$nextKind,4808,_collection$_box_0,4809,isRootRelative,4407,get$isRootRelative,4407,_subscription,4810,set$_subscription,4810,addTo$1,4811,_tdivFast,4630,get$_tdivFast,4630,_uri,4812,isDone,4813,get$isDone,4813,_stateData,4814,setChannel$1,4815,_writeSidebar$1$end,3613,_captured_R_2,4816,_stream_channel_completer$_channel,4817,set$_stream_channel_completer$_channel,4817,runes,4818,get$runes,4818,_jsWeakMapOrKey,4819,_containsKey,4799,get$_containsKey,4799,_trimVMChain$1,3639,_queue,4820,_null_stream_sink$_closed,4821,_lineStarts,4822,listen,4088,get$listen,4088,_eventQueue,4823,bindCallback$1$1,3565,_engine$_runLiveTest,4068,get$_engine$_runLiveTest,4068,isSeparator$1,4824,_arguments,4825,_disconnected,4826,_validateTags$0,4734,_context,4827,_createSubscription,4749,get$_createSubscription,4749,_captured_stream_1,4828,_indexFor$2,4829,scheduleMicrotask$1,302,_cancelOnError,4830,get$_cancelOnError,4830,runOnce,4331,get$runOnce,4331,_tdivSlow,4508,get$_tdivSlow,4508,needsSeparator,3710,get$needsSeparator,3710,rest,4831,get$rest,4831,_rest,4832,errorCallback,3841,get$errorCallback,3841,rootLength$1,4060,_captured_stackTrace_2,4833,downEnd,1915,get$downEnd,1915,group$9$onPlatform$retry$skip$solo$tags$testOn$timeout,587,_onPause,3984,get$_onPause,3984,release$0,3757,_guardCallback$1,4783,forEach$1,3005,_stream_subscription$_source,4834,_checkEventAllowed$0,4240,_stack_zone_specification$_run$1$2,3958,_toFilePath$0,4835,sourceUrlId,4836,_shrOtherPositive,4837,get$_shrOtherPositive,4837,_closed,4838,_onIdleController,4839,_value,4840,_captured_error_1,4841,writeCharCode$1,4842,_close$0,4119,_tearDownAlls,4843,addError,3878,get$addError,3878,_captured_sourceMap_1,4844,walk,4448,get$walk,4448,_self,4845,onStateChange,4846,get$onStateChange,4846,addError$2,3878,_timeoutTimer,4847,currentChain$1,4848,_print_sink$_buffer,4849,_live_test_controller$_suite,4850,string,4851,_engine$_captured_liveTest_1,4852,isBrowser,4853,getOffset$1,4764,_suiteController,4854,_canonicalRecipe,4855,_canceled,4856,get$_canceled,4856,_nativeGlobalVersion,4857,get$_nativeGlobalVersion,4857,_pending,4858,set$_pending,4858,_queue_list$_tail,4859,_createTimer,4860,get$_createTimer,4860,set$_createTimer,4860,passed,4861,get$passed,4861,_onData,4862,set$_onData,4862,change$2$skip$skipReason,3651,_getTableCell,4490,get$_getTableCell,4490,_captured_action_1,4863,_captured_body_1,4864,_stream_group$_captured_this_0,4865,_captured_liveTest_1,4866,addEventListener,3366,get$addEventListener,3366,_captured_beforeLoad_4,4867,spanFor$3$files,3884,_printsOnFailure,4868,merge$1,4216,_writeAuthority$1,4869,_runSkippedTest$3,4706,spanFor$3$uri,3884,current,621,get$current,621,_onTimeout$0,4870,_onStateChange$2,4385,startChunkedConversion$1,4871,next$0,4776,accept,4697,get$accept,4697,handleWhenComplete$0,4872,_addStreamCompleter,4873,_group$_map,4137,get$_group$_map,4137,_captured_K_1,4874,runBinaryGuarded,4746,get$runBinaryGuarded,4746,_toNonSimple$0,3743,normalize$3,4062,getOffset$2,4764,clear$0,4298,inputId,4875,cloneNotRequired$1,4876,first,4877,get$first,4877,matches$1,3347,_handleError$2,3633,shuffle$1,4878,_pauseCompleter,4879,newJsList$1,4880,createTimer$2,4245,_registerUnaryCallback,4881,get$_registerUnaryCallback,4881,set$_registerUnaryCallback,4881,key,4882,_first,4883,_captured_T_1,4884,name,4885,get$name,4885,_simpleMerge$2,3973,_postMessage_1$2,4886,_addEventListener$3,3922,_resetTimer$0,4716,_consumeWhitespace$0,4549,_keys,4887,_live_test_controller$_run$0,3640,allMatches$1,3605,onPause,4888,fork$2$specification$zoneValues,4320,_captured_data_1,4889,isSeparator,4824,get$isSeparator,4824,withResource,3430,get$withResource,3430,hasQuery,4890,get$hasQuery,4890,_nums,4891,_setErrorObject$1,4892,_collection$_source,4893,handlesValue,4894,get$handlesValue,4894,_progressLine$3$color$suffix,3569,_stack_zone_specification$_captured_R_3,4895,_captured_channel_1,4896,run,4042,get$run,4042,getLine$1,4038,_stack_zone_specification$_registerCallback$1$4,3692,seen,4897,_lazy_chain$_inner,4898,set$_lazy_chain$_inner,4898,_selector1,4899,_consumeNewSegment$0,4900,lastIndexOf$2,3844,_urlSafe,4901,input,4902,_subscription_stream$_captured_stackTrace_2,4903,_reverseListeners,4445,get$_reverseListeners,4445,normalize,4062,get$normalize,4062,isRunning,4904,get$isRunning,4904,postMessage,4664,get$postMessage,4664,round,3839,get$round,3839,_deleteTableEntry,4424,get$_deleteTableEntry,4424,prettyUri$1,3506,_trace$_captured_level_1,4905,_selector,4906,virtualChannel$1,4017,_pause$0,4907,_isScheme$1,4908,_onStreamDisconnected,4694,get$_onStreamDisconnected,4694,_parsed_path$_captured_this_0,4909,_declarer$_captured_this_0,4910,_isSourceStreamSet,4911,get$_isSourceStreamSet,4911,_local,4912,set$_local,4912,length,4913,get$length,4913,set$length,4913,separator,4914,get$separator,4914,_captured_T_3,4915,_captured_handleError_0,4916,toList$0,4159,_serializeGroup$3,3749,fillRange,3701,get$fillRange,3701,_setChained$1,4917,_yellow,4918,visitOr$1,4472,_captured_location_2,4919,describe$1,3396,removeLast,3819,get$removeLast,3819,registerCallback,3602,get$registerCallback,3602,validate,3977,get$validate,3977,cleanupSlots$0,4920,max$2,470,_captured_depth_3,4921,_jsTrace,4922,codeUnitAt$1,3808,_captured_dispatch_1,4923,_end,4924,__js_helper$_unlinkCell,4127,get$__js_helper$_unlinkCell,4127,_captured_matcher_0,4925,addTo,4811,get$addTo,4811,_modificationCount,4926,_processed,4927,_timer,4928,_writeString$1,4929,_cloneResult,3638,get$_cloneResult,3638,_captured_platform_1,4930,_fail$1,4931,isClosed,4932,get$isClosed,4932,keys,4933,get$keys,4933,isPaused,4934,get$isPaused,4934,pathFromUri$1,4674,_onCancel,3575,get$_onCancel,3575,_captured_engine_0,4935,_set$2,4212,_setUps,4936,_expanded$_sink,4937,_grow$0,4938,text,4939,get$text,4939,any,3793,get$any,3793,_findColumn$3,4009,_onErrorController,4940,_text,4941,_captured_this_0,4942,copyList,4071,get$copyList,4071,_prependListeners$1,4395,handlesError,4943,get$handlesError,4943,_contents,4944,_captured_milliseconds_1,4945,_updateRequests$0,4220,_captured_sdkLib_3,4946,_initializeText$0,4947,_captured_trace_0,4948,_evalCache,4949,_closeGap,4364,get$_closeGap,4364,_limit,4950,_toggleEventId$0,4951,_live_suite_controller$_active,4952,_addLiveSuite,4692,get$_addLiveSuite,4692,_createNode$1,4953,copy$0,4735,toSpec$0,4954,userInfo,4955,get$userInfo,4955,_addListener,4803,get$_addListener,4803,excludeTags,4956,_indexFor,4829,get$_indexFor,4829,_separatorIndices,4957,setState,4297,get$setState,4297,_captured_completer_1,4958,_is,4959,_shrOtherPositive$1,4837,_isUsed,4960,putIfAbsent$2,3873,_paddingAfterSidebar,4961,get$_paddingAfterSidebar,4961,code,4962,sink,4963,get$sink,4963,_captured_skipReason_7,4964,_destinationSink,4965,set$_destinationSink,4965,_values,4966,_suite$_metadata,4967,_addLoadSuite$1,4968,_captured_message_1,4969,_compareIterables,3860,get$_compareIterables,3860,values,4970,get$values,4970,_nativeRegExp,4971,chainFor,4079,get$chainFor,4079,_setTableEntry$3,4373,removeAt$1,4637,_isDefined,4972,_isDone,4973,resume$0,4345,_isDotAll,4974,get$_isDotAll,4974,_unlinkCell$1,4405,offset,4975,get$offset,4975,putIntoObject$3,4976,copies,4977,print,412,get$print,412,_runBinary,4978,get$_runBinary,4978,set$_runBinary,4978,_addPending,4737,get$_addPending,4737,_start,4979,_onTestStarted$1,3482,_stream_queue$_source,4980,year,4981,get$year,4981,_requestQueue,4982,_needsNormalization,4505,get$_needsNormalization,4505,$le,4983,$indexSet,4984,$index,4985,$xor,4986,$or,4987,$eq,4988,$mod,4989,$shr,4990,$and,4991,$ge,4992,$gt,4993,$lt,4994,$mul,4995,$not,4996,$shl,4997,$div,4998,$sub,4999,$add,5000,$negate,5001,$tdiv,5002"},"frames":"qsTAyEiB+2EuH;eAEFmduF;mXEqKbndAAAAAwR,A;iQAuHeAsI;eAEFmdwG;uEAohBwBnd8B;qEAEFAqC;oEAEDAoC;w7GGrpBvBAyEAhOXA6B,A;u1CC+YE4hF8F;qxCA0MSCuB;uCAAAA6B;wIAqBeC6B;0YAYjBD4C;uyHA4NQ7tBgB;+5DA8Ya/zD4C;igBAmBjByIyD;oFAOEAyD;eAIJzI2C;iEASAA6C;uPAmCcDoC;urCA4QZA+S;wnJAgSHAoE;iJAKKA0B;qLAWaAwH;oLASbA0B;sOAiCmBA4B;6HAGtBA4B;iRAmCCxzEAIn4BNu1JkF,gE;wEJq4BKC+C;6CACEA4B;0IAUDx1JAIh5BNu1J8D,yD;oDJk5BMC4B;2kBAmBHhiFAKj9D0BA8E,A;q1BLqlEtBA6D;AAEAA0Q;w+IAwPmCiiF0C;8EAAAA+E;wZAYXAwC;8EAAAAuD;49DAkGJA+J;AACICyL;w6CAsI7B70JACnsEF80JiD,sB;0GDusEE90JACvsEF80JiD,sB;qQDyuEcniF+G;0iCAgbMoiFgG;+dA6BjBpiFqC;qNAqBAAkD;m4BIt6FN+hFgC;OAEKtzJmBArBwB4zJY,wC;wEAyBVAM;wDAKnBCqC;sYAOACwF;AAhBK9zJAAtBFszJiB,A;AAsCHQ2B;sFAIACgE;AApBK/zJAAtBFszJiB,A;AA0CHS2B;iCACiB9zJAAwYd8zJsE,A;AA7ZE/zJAAtBFszJmB,A;AA2CcrzJAAwYd8zJ6B,2C;8xCA9VC5zJAAq2BN6zJqB,A;4zDAhxBKViC;0BAGmB/hFuC;4DACWxzE0C;4EAGpBw1J4C;8PAqDsBlzJAHmW7B4zJ6BAjBR3zJAA3I8B4zJuD,A,A,A;OGvMO7zJ+D;6NAWXizJkC;AACbaiE;qDAEXbyC;iFASKa0C;gJA0HLt0Ja;0BAAAA2D;oKAygBwByzJkC;gnEF/1BnB1yJAA2BTwzJoI,A;kTAZSxzJAAYTwzJoI,A;6yCApEuBlzJAAzChBmzJwE,A;0zDA+QSjzJsL;0gCKjNhBmwEAAAAAqG,A;+WCpESusEwB;+IAGyBnbkB;0bA0BhBxsDO;qfAuBPm+E+F;sCACFCiC;gBAGTCqF;6vBA2CODiC;0YAyBPhkDADKQh/B4B,mE;2CCLRlwDsC;wCACEi/Fc;+EACAAI;2EAGFAc;kmBA8DkCm0CgB;AAA1BFoC;0EAGRCqF;grPP/KkDEyC;AAA3BCY;AACfCyE;AADeD2B;m8CAySPEmB;qDAGVCmD;AAEW3/E0H;4FAIT4/EuD;yiBAcOCiC;+WAaMCAAqnCiBCAA/C9B//EiH,A,A;OAtkCa8/EuE;2PAMAGAAqnCjBCAAnDIlgFiH,A,A;OAlkCaigFuE;2PAMAGAAqnCjBCAAvDIrgFiH,A,A;OA9jCaogFuE;uUAQkCG2C;+HAGpCC+C;geAUMCqD;wvBAiBNbsD;mUAOCcgD;qiCAgCGC6B;ymCA+B0BCAA5ORxkFkD,A;AA6OrBykFmE;AAEACmE;AAEACmD;ycAgCd51JAAzB0B4zJsB,A;+NAgD5BxwJAAnD+BwwJmB,A;AAoD1BtwJ0B;mhCA8EkBtDAA/HK4zJoM,A;8MAoJpBrxJqF;2LAoBRszJsB;AADG5kFgB;8EAOkB1uE4C;iHAsCVmyJ6D;AAKXtrJ0E;AAIE0sJiB;AADACQ;yDAGalhFgI;+UAaGugF2DAxlBGYqB,A;6FAkmBfC4H;AAMNCmB;+HAWGCgC;6IAQOCiC;uBAKVhzJAAvR+BwwJiB,A;83BA8T/BuC8E;u2BA6BgBvjFiC;sOAQAAiC;+1IAmKXxpE8C;oPAUYksJkEAp1BDUiB,A;mnDAk5BLtBiC;gQASU2BkC;wGAKICkC;wGAKAlCkC;sHAKTgBkC;8VAcSXmC;4IAOXc2CA36BISsC,A;+4BA0mCLO4F;u4BAwCCCmB;8CAGVC+B;+UAUUlCmB;8CAGVC+C;AAEuB3/E0H;6jBAgDZAkI;AACjB6hF0B;AASIXQ;yCACADW;2CACAIQ;yPAyDGSAAIOlBAArvCHxkF4C,A,AAsvCP2lFqB,GACAC2C,A;gQAwBGCAAKOrBAApxCHxkF4C,A,AAqxCP2lFwB,AACAG4B,GACAF2C,A;qSASGGAAKOvBAAryCHxkF4C,A,AAsyCP2lFsB,AACAGyB,GACAF2C,A;2QASqBhiFiI;wTAYF2gF4B;OAEE3gFiI;mKAqBZoiF2K;iFAINCAAKOzBAA71CHxkF4C,A,AA81CP2lFqB,AACAG4B,AACAIyC,wBAGE7CsC,GAEFuC6B,A;8LAuBInCc;yBACQWoE;uKAIH+BAAlBEviF0H,kF;iFAsBRwiFAAKO5BAA14CHxkF4C,A,AA24CP2lFsB,AACAG8B,AACAI6B,GACAN6B,A;6TA8CSSAAxCPziFyJ,AACJ0iF2xB,gC;mFA2CKCAAKO/BAAr8CHxkF4C,A,AAs8CP2lFsB,AACAGiC,AACAI2B,GACAN+B,A;oMAaSYAAPP5iF0H,sE;mFAWC6iFAAKOjCAA/9CHxkF4C,A,AAg+CP2lFsB,AACAGuC,AACAIuB,GACAN+B,A;4ZAoKOcoD;itBAuBCCyL;qDAIkBrBiE;qDAIAsBiE;sDAIACiE;2DAItBCAAqERCmC,AACACuB,A;2DAlEQCkBA4GWC2BAmFACmB,4DAEnBHsC,A,imB;sPAtLsBtDAAjccCAA/C9B//EwI,A,+D;2IAwfgBigFAAncpBCAAnDIlgFwI,A,+D;2IA8fgBogFAArcpBCAAvDIrgFwI,A,+D;2DAigBEkjFAAiCRCmC,AACACuB,A;2DA9BQIkBAiG6C5CAApyDdxkFqJ,A,meA6zDvBknF2BAiCGCmB,4DAEnBHgD,A,AApCoBvCsD,AAEACmE,AACAC0D,wH;2DAxHZmCAAyBRCmC,AACACuB,A;0CAtBQKAA0HYH2BAyBDCmB,4DAEnBHqG,A,A;4DAjJQFAAiBRCmC,AACACuB,A;2CAdQMAAwHYC2BA0BDJmB,iEAEnBHqG,A,A;o9BAhHoDQsD;wJAUpCC4DAroBDhEgB,2BAEKW2F,AAGODiD,2X;0JAktBHuD4D;2DAIAC4D;uhCAsDTlEiC;wDAEcWqC;+OAQTA4D;w7BAuGJEwC;8GAKFbc;6CA6BI2BuC;yGAUJAkC;MAAAAAAxoEILmB,A;iGAipEA5BuC;sOAYIkCuC;0HAWKlCkC;oOAYIkCkC;4rBA4BS7B8CAvrEtBuBmB,A;AAwrEVvBwC;s9BAsBYa4CAxtEFUiB,A;AAytEEVsC;gkCA4BHuDa;iMAQAAa;+NASAAuC;oZAoBDC4B;+NAEJDiB;mSASKzD8C;iBACAA8C;gSAkBJyDyB;AACAAe;80BA0ECnEc;4NAYJU0CAp7EaYqB,A;AAo7EeZyC;2LAMxBC2CA96EIWqB,A;AA86EoBX0C;yJAMxBC2CA35EIUqB,A;AA25EmBV0C;yJAC/ByD6O;4DAIiBtE2CAt5ELuBqB,A;AAu5EJvB0C;qrCAqDDCc;+JAMON0C;w2FK1kFJ4EqG;oiBA+BhBC8C;grZUpF4B3+BuD;sMAmB9BrpD+C;4HAeAgNwD;4EAiFWhN2BA7BSioFAAAAjoFeE0BKlwDgB,2B,A,sC;2JFkBR4pFQ;y1BA2DM15BwBE7EElwDwD,A;AF6EFo4IqE;mdAiCXp4I0C;sJI9JckwD4BFgDDlwDgB,iC;AE/CjB61G4B;8IAyBkB3lD4BFsBDlwDgB,iC;saEORmwDoBFUmCnwDgB,uCAVpDo7DAAUAAAATEg9E6D,A,A,A;sKEEmBloFAFVIlwDwB,8D;gKEcfxVAAsrBuC0lEwC,A;0QA9oB3BlwDkC;8LAGRxVAA2oBmC0lEmE,A;qCAvoBpC09BoBFjDM5tFgB,iCADnB4tFAAAAAmD,A,A;6EE4HsC19B0KFvIblwD6D,A;kkBEuMRmwDAAlKJ27BoBFnCwC9rF+B,AAArD8rFAAAAAqB,A,A,A;uhBE0Q0BoDANsHMh/BiC,+BAAAAsC,A;iHMnFLA0CF/SFlwDoH,A;4TEgrBKAyD;mGAEpBxVAAkBuC0lEiE,A;uMF7rBjDkLAAAAAAACEg9EkF,A,A;oIAiOeCoB;sDAIfCqBArIOC4B,iC;6dAqKOCiE;uCAEICyF;uRAQhBCqBAvOKF6B,iE;ycAmUSHkC;8BACSMuB;+DAGYC2D;yjBA8BV3NkB;iEAaNt0EmB;kCAZIkiF8C;uDACGldiG;AAWPhlEsB;sDATgBiiFiBAvS9BD4B,2D;oIA8SiB34I0B;+BAEH22DqH;yFAoEJk5DkB;+lBAuBOwoB8B;AACFSiBA5SdT4B,iK;AA6SEUiBA/WFV4B,iBACMA+B,sG;gMA2XASqBA1TNTsB,sK;gFA+TJWAA9YIXsB,A;qBA2YJDsK;yBAGAYoH;mqCIrrBQCoD;+GAYqB/oF+D;4HAIrB+oFoD;yXAsBkB/oFyD;qZAwCPlwD2B;gNASrB27HM;iCAAAAgD;qLAKC37HsB;8HCuBKkwD+J;+JAQUy9BAC4SQz9BuE,A;+ED7OfA2B;wDAAAAsC;qGAs6DLA4D;OAAAAuD;qIClkEIAwG;AACAAuG;6TAwtBLlwDwD;0PChtBiB64IAAAA74I0D,A;sGAgBxBkwDqF;wKA+cKlwD6D;qXChjB2BA8C;wHAIhBxVAN84BiC0lE6F,A;u9BCj3BtClwDsB;2pDFwjCJk5IsE;weAYAAsE;wiBAYAAsE;2vBA0BmBvdc;iCAAAAwB;uoBA0BbwdAH/jCiB5/BmD,yB;OG+jCjB4/BoE;sEAIbCc;gFAIKp5IqC;4hBA0BMkwD8CArXXAAAAAAgQAcYA4D,gIAGAA4D,uIAGAA4D,sHAIAAmH,kUAeAAkG,sKAMAA6G,wC,A,A;u/BA4kBc6Mie;ygBAkBnB/8D0E;6/gBSr8CYkwD8C;+CAAAAwD;0cA4dAmpFAC/cPnpF4C,A;4GD+cOmpFAC/cPnpF+D,A;sMD4e+BmpFAC5e/BnpFuF,A;iFDofCmpFACpfDnpFqF,A;sEDupCOAqD;6EA8BmBAqD;sJAKPAuD;qGAqU7BkJ8H;2MA2GFlJAAAAAoD,A;u8BGz6CUo3DiH;wQAqBcp3DkD;iGAGpBo3DiG;oRAMKh7BkB;4gHGrPMp8BqD;gdAoBNo8BkB;uJCwdTp8BAAAAA4H,A;+kIC7ZaA2C;26IjCkDCopFwD;gVAwDMC8C;mmBAiOXC2D;iKAYACqC;6BAAAAc;qMAoBEC8E;OAAAAyH;yEAGACoH;yrCAoEHzpFuG;yMA+DQw+CsC;AAEDkrCc;uFAGFAc;0EAGEAkC;qhBA+GoBndAI3lBcqVuI,A;kGJkmBnCr+CyF;0TAKRo0CAA/Ja9lEiI,A;+7IsCnZf7RyG;+HClKFkpFwC;kZEixBkBSgQ;usGAAAA8D;8CAAAAqD;ovEA8NT3pFoG;82FAuUSAAlCrS4B4pFkD,A;sIkCqS5B5pFAlCrS4B4pFuC,A;24FkC6blCC4E;8RAcoBCgB;4GAENAuB;gOAOI14BA7B/jCR5S4D,A;8J6BokCTsrC+D;AACFtrCqB;8MASCqrCmC;y1BAgMQ3pD+G;AAApBlBAhD7pD8Bh/B2F,A;mCgD6pD9BlwD8B;00DAsDSg2FoE;szFAkNSzyBiI;6sBAsCPrTgK;uZAeIA2C;8TASX+uCAzC18CJg7CyC,A;sGyC88CaCoH;qBAAAA4F;wHAGIhqF+C;2rBAiBFA6C;2cAaRo8BkB;+nBA8BQp8B2C;icAWX+uCAzCxhDJg7CyC,A;iHyC4hDaEoH;qBAAAA4F;wHAGIjqF+C;uRAQJkqF0H;uBAAAAkG;+hBAWElqF+C;ymBAeRo8BkB;ggBAiBA+tDsH;mBAAAA0F;w6CAyCInwBA9B/6DAh6DwE,O;iC8B+6DAg6DA9B/6DAh6D4C,A;wC8Bm7DAw+CyB;gkDA0FP4rC4I;iBAAAAiF;uBAIYv4EqG;q+FAmGoBq4EgI;yBAAAAyH;w0BAiBrBlqF2C;8FAEX+uCgD;0VAWG3SkB;qbAoEKg1BA7B5iEU5SsB,A;4O6BkjEP4SA9Bt5DO5SmB,A;mI8Bw5DLA6B;osBAgCL4SA7BplEU5SsB,A;oO6B0lENA4E;obAYLAe;knEAiMX4YiH;s7CAwKuC6MA7BvgFVjkEwB,A;yoB6B6hFtBg2CoC;OAAAAAC31FAh2CyB,gB;2SDoyGL+uCAzCpyFFg7CoD,A;+KyC0yFEh7C6B;uHAEAAAzC5yFFg7C+B,A;AyC6yFEh7CwB;49EAgXa5xBuC;gpBAkBXw6DAzC1qGJoSoB,A;kByC0qGIpSAzC1qGa9lEM,AAAjBk4EkF,A;AyC4qGIpSAzC5qGa9lE+D,AAAjBk4E2B,A;AyC6qGIpSAzC7qGa9lEsC,A;wGyC6qGb8lEAzC7qGJoS2B,A;AyC8qGIpSAzC9qGa9lEM,AAAjBk4EkD,A;gxX2C3hB8B/pFgE;0EA6GdAA1BooBSAAFjvBvBAAAtB0B05BAAAA15BwBA4MLlwDgB,+C,A,A,kF,A;uoD8B0plCzBkwDAAAAAyB,A;0EA44GSlwDsB;wwECvssCsBu6IiBCEPpmBAnC6TOjkEoC,A,AmC7TpBs8BAA7BcguDyD,A,gDA6BdhuDAAaeiuDoB,0B,AAF1BjuD6C,A;urBCnBgBt8B2B;AAAwBw2DsB;yCAIG1mHsB;gTAUzCk+FsC;mHAAAA8D;AAAAhuC0BGpDkDwqFuE,AAISCgF,AAGtCCwE,A;iBH0HHn6BS;6VAcV6uBgBC/DgC7uBS,AAAQ6uBgB,A;wMDqExCAgBCrEgC7uBS,AAAQ6uBgB,A;qGDyEtBtvI+BKtInBAyB,wB;m8HEXmB66I+F;AAMACyC;AAOCCmC;AA4NVCAAAA9qFAC/NA+qFAAAA/qFAvCsvBQAAFjvBvBAAAtB0B05BAAAA15BAA4MLlwDsB,A,A,A,A,A,A,A,A;AwC5IzBkwDAAAAAwK,A;sDAgLmB8qFAAAA9qFoBC/NA+qFAAAA/qFAvCsvBQAsBFjvBvBAAAtB0B05BAAAA15BuG,A,A,A,A,A,A,A;yqC0CuBjBAqC;AAAiBg6DA9CiOjBh6DoD,O;6D8CjOiBg6DA9CiOjBh6DyD,A;+M8CjNUg6DA9CiNVh6DsD,A;O8CjNFAqC;AAAYg6DA9CiNVh6DoD,O;0E8CjNiBm8BkE;gDAAnBn8BAEmLUA8B,A;6IF9Hd8lCwD;0GAIFqnB+C;AAFArnByC;mDAEAqnBU;wFAEArnBoD;+CAMAAoD;uDAEAAoD;2EAKAqnB0C;AAHArnByC;2CAGAqnBU;m4IK8CiBH8E;giBA+BoBhtD2H;cACCA6F;8EAH9BAuF;AAjBbmdAAAAA4G,A;ibA6BAnbAAAAAuH,A;gxDAuD0CipFoB;6CACjCjrFc;89DGnKMkrFAAAAlrFACnDCmrF0D,AAvBGJAAAA/qFAjDsvBQAAFjvBvBAAAtB0B05BAAAA15BAA4MLlwD2H,A,A,A,A,A,A,A,A;AkDpGAu7I2E;AAwDCCAAAAttDmBEzIKutD4B,AAURCAAAArCAzCEXnpFoI,A,A,AyCiCZg+BAAAAAiCACcAA9C2DFh+BqC,A,mI,A,A,A;A4CoCS0rF4C;AAICC4C;AAIDC4C;AAILC8B;2DArFDXAAAAlrFkBC1EI+qFAAAA/qFAjDsvBQAsBFjvBvBAAAtB0B05BAAAA15BoH,A,A,A,A,A,A,A;AkD8FawrF4E;AAiBTM0C;AAUJCAAAA/tDA5CQlBh+BwG,A,A;A4CGmBisFuD;AAQCCAAAAluDA5CXpBh+B2H,A,A;A4CqDiBosF0C;AAMMCiD;AAgBnCrsFuE;6xIM/LcssF2E;yEAOdtsFAAAAAkCACSA4D,A,A;wbxBqMTmdAAAAAyIAG2B++D+B,+J,A;qGA0F3Bl8EAAAAAoJAGyBk8E+B,iR,A;qbYnPZl8E+G;4aAsBAAgB;gLAUqBA8B;8EAAAAgBAmHbA8B,A;gyBArGNsVAAOetV8B,+C;OAPfsVgBAOetVAA8FTA+B,A,A;ucAzFD8lCmE;0CACLmCuC;qDACR+xBAlE8BmCh6D2E,O;iCkE9BnCg6DAlE8BmCh6DwD,A;8PkEd3BkgC4C;6FACApDkF;qGAHT98ByB;AAOSg6D2E;iCAAAAoC;AAPTh6DAAyEeA+B,A;2EA5DfAyB;AAGSg6DAlE6P2B78CqB,A;AkE9P3BgfAhDuDFn8BoB,A;+DgDvDEm8BkC;iEACA69BmC;uFAHTh6DAA4DeA+B,A;4EA7CfAyB;AAISg6DAlE6O2B78CqB,A;AkE9O3BgfAhDuCFn8BoB,A;0FgDvCEm8BkC;kEACA69BmC;wFAJTh6DAA6CeA+B,A;wIAPFg6DAlE2MuB78CqB,A;AkE7MvBgfAhDMNn8BoB,A;0FgDNMm8BkC;mEAEA69BmC;oGAPbh6D2CAceA+B,A;2hFe9LbAqD;s/BCARAAAAAAqX,A;2cC6C4BusFiG;AAyBV5vDAAAA38BA3DqqBSAAFjvBvBAAAtB0B05BAAAA15BAA4MLlwD6B,A,A,A,A,A,A;0H6DhINy7IsC;AAMYkBAAAAzuDAvD8CnBh+BgG,A,A;AuDvCa2sFAAAA3uDAvDuCbh+BqG,A,A;AuDjCe6sFAAAA7uDAvDiCfh+BkG,A,A;AuD9BM28BAAAA38BA3DqqBSAsBFjvBvBAAAtB0B05BAAAA15B2E,A,A,A,A,A;A6D0H9BAAAAAAAAOcAE,wC,A;gsBCjIEAA5DuwBWAAFjvBvBAAAtB0B05BAAAA15BUA4MLlwDyG,A,A,A,A,A;A8D1MjBAmC;kCACAAQC0HMA0B,A;AD3HNAc;qEAFQkwDA5DuwBWA2D,A;8+DgE7vB3BAAAAAAuB,A;oCAAAAAAAAAkH,A;isBCoCmCoxDAtEoXX5SuB,A;AsEnXQx+C6D;yHAEAA2C;yJAAAAoD;OALvBAqC;iqFEWFunC4B;AACYz3FkD;8KAAAAiE;qBAAAA+B;80BE5Dfi9I0D;oIAMJn4CuDEsIoBwqC2B,AACZ3hD6CpC1IkCAA/Bgddz9B4B,oBAAAAiC,A,A,2B;4oEqEvYhBlwDYZqDEA0B,+B;0FYjDFAaZiDEA0B,A;AYrDFA+C;AAIQ64GAZODqkCmBAdQl9I2B,A,A;sBYOP64GkBZO8BhhBO/DhElB0gDuB,A,A;wsB2EsHCroF2B;8EAMX70DAE6JpB60D6CDjTwBitFAAAAjtFwB,A,A,4BCiTJo8BKDrSDAkB,A,A;2EDyICjxFAE4JpB60D6BDjTwBitFAAAAjtFwB,A,A,wBCiTJo8BKDrSDAkB,A,A;4FD0IXg1BA9EiRc5SwE,A;4B8EhRJ9BA1FyalBqtC2B,A;6R6FhkBFmDM;uDAMAAM;u+ER8EkCC8B;AAGEC8B;AAICCwD;AAGrCh2E6E;0GA0EuCi2EgF;AAIvCj2EwD;08BA4JAAuD;olGS1QoB8FgD;qlB8EkBpBnd6C;A5EpEAAAAAAA0Z,A;mmCC2FWmdAA9DyBowE8B,AAGGC8B,AAGAC8B,AAGtBCAAAA1tFc,4B,AAUiB2tF8B,AASLC8B,AAMIC6B,A;05FEqB3B/nD4D;2EACKA8C;gjBAmBuBgoDoM;UAAAA4E;+6CAgCvBtvCe;inEzC9DMx+CA0C7CG+tFAAAA/tFApGyDRguF0G,A,A,oCoGzDQDAAAA/tF6E,A,A;8F1CuDK2+E8T;sLAgCnBsPUA1FiDn+IiG,mD;AA0FpBm+IgBA1FoBn+IuC,A;AA0FpBmoIA0CvDIiWoCAgH/BluFO,uB,A;mB1CzD2Bi4EA0CvDIiWAAgH/BluF4B,A,W;uB1CtDKAgB;oOAoBPiuFAAjHiDn+IsB,wH;OAiHpBm+IWAjHoBn+I8B,A;mFAkHtBkwDqC;uEACpBAgB;2NASmBAS;0CAAAAyB;oIAEjBAqC;AACDg6DA/CwFDh6DyB,A;gE+CxFCg6DmC;kKAE8Bh6DqC;qGAE/BAqC;AACDg6DA/CmFCh6DyB,A;gE+CnFDg6DmC;kmJ4C1IG+NAzCdT/nE8B,A;oFyCcS+nEwB;urFGCSj4H+CRgDYA0B,qB;40C/CtCpCkwDAAAAA0KAI+By9BwD,AAAiC2hDiD,cADvD+OoB,AACsB1wDA7BqaHz9BuF,A,A6BraoCo/EA7B0alCp/E2G,A,gB6BzanBmuFoB,AACoB1wDA7BmaHz9BuF,A,A6BnaoCo/EA7BwalCp/EyH,A,A,A;6uBsFtXXouFwF;uBAIVpuFc;6lCfOIioCuF;mnBAuLI/H2D;kCAAjBlBAnG7QgCh/B2F,A;+CmG6QhClwDoC;0MgBvOyBu+IAAAAruFA1CjBTmrFU,AAvBGJAAAA/qFAjDsvBQAAFjvBvBAAAtB0B05BAAAA15BAA4MLlwD4F,A,A,A,A,A,A,A,A;A6F3ICw+IAAAAtuFA3FssBCAAFjvBvBAAAtB0B05BAAAA15BAA4MLlwDmI,A,A,A,A,A,A;uC6FnJAu+IAAAAruFkB1CxCN+qFAAAA/qFAjDsvBQAsBFjvBvBAAAtB0B05BAAAA15BoH,A,A,A,A,A,A,A;A6FiEJsuFAAAAtuFA3FssBCAsBFjvBvBAAAtB0B05BAAAA15B4B,A,A,A,A,A;A6FoECwuFAAAAxwDAvF4DnBh+BiG,A,A;AuFxDc0uF0C;AAGCC0C;AAGDC0C;AAwEP9DAAAA9qFoBpDrIA+qFAAAA/qFAvCsvBQAsBFjvBvBAAAtB0B05BAAAA15BiE,A,A,A,A,A,A,A;A6FyF9BAwC;21CC1BqBw+CuB;2HACKAwC;4FACWwOAlGkgBtB6hCuD,A;0wBoGlkBoB5qBAnGyWJjkEwC,A;AmGzW/Bg/BAcyC4Bh/B4G,A;gCdzC5BlwD6C;oJAaS0uGuB;g2CEMTx+CAAAAAwI,A;s7CCOS7wDAC0QP6wDmD,A;iEDrQO7wDACqQP6wDiB,A;iHDnQO5wDAE/BL4wDgC,AACAA0B,A;2CFwCGmtDG;kEADDrnBgD;wBACCqnBmC;kKASUgpBAtGuTMn2E+B,A;AsGvTAu0CoP;qaG1BNp3B6B;6kBA4gCDnd0C;AACd+uCkCrH5fAg7CyB,A;AqH6fc9hDkH;AACT+xBA5Hz4BmCh6D4E,O;mC4Hy4BnCg6DA5Hz4BmCh6DyD,A;gC4Hw4BxC+uCArH7fAg7CgC,A;AqHigBAh7CArHjgBAg7C6F,A;ktBoHteEh7CApHseFg7CkB,A;0BoHzeEh7C0BpHyeFg7CyB,A;IoHxeEh7CApHweFg7C6F,A;IoHteEh7CApHseFg7CmE,A;mHoHheEh7CApHgeFg7C4B,A;qBoHheEh7CApHgeFg7CiF,A;oEoH9dEh7CApH8dFg7C6B,A;AoH7dEh7CApH6dFg7CsC,A;usBiD1dsB+E4C;AAI8BCoF;AAIlCCmC;AAIDCmC;uCAwBnBjvFsC;i9FsEIqC8lC2C;yoECmKtB9lCoBCnSK6gCgD,A;k1CCgBbqfA7Eor+B+B0hBAA49G9B5hE8E,A,A;0L6EznlCiCg6BS;0DAAtBm1D8C;AACRn1D+E;wCAEOu2BS;y8CtElBlBvwDiF;ulDjDsSgCqpFgD;8qDQrM9BrX+E;wGAKAAuE;8TASAAqE;kWASAAwE;saAqBAAwE;0NAMAAwD;4YA2DAAwD;wsBAwBWhyEkE;WAAAAkE;srGA8JXiqE0D;09BAwCAA4D;4YASA+H2E;ygCAyH4BoduD;+MAcEpvF+C;+BAAAA4B;8SAO9BgyE8F;suBAoBA/H2F;2kEmH7ZOolBgQ;sBAAAAwD;yBAAAAqH;2gGlHzMACiF;6TASP1NyG;yHAKO5sIAPyBEgrDwD,A;2mBOXEAkC;k2JA0XXijFiF;smCrB5Z8BjjFmB;qBAAAA6B;WAAAA6B;8hCAuPEAyB;mCAAAA6B;mCAAAA4B;i/CEjOFAmD;uBAAAAwC;w/BAiHfw+CyB;6QASXzP0B;2RASAAU;uYAWoC/uC2E;WAAAA+E;q/HA6LVAqB;uDAAAA6B;WAAAA+B;4uCA6DAAgD;sGAAAAqC;iDAGUmdyB;4EAAAA8D;yaA6BVndyB;oFAAAAAASMuvFkB,6B;WATNvvF+B;y+BAmMnBAoD;0GAAAAyC;2nIE/fAAoC;sBAAAAsC;6FA8B+Bg/BAgBibZh/Ba,A;iBhBjbYg/B0B;iCAAAAAgBibZh/BS,yBAAAA4B,A;yVf5jBdwvFiE;6xECitDYhxCwC;wuEAo2BV6qCiD;2hB6B5hFPrpFgD;kPAAAAuC;48BAwBEyvF8E;qhCAiCAAoF;opJA8HgBzvFwB;85FA0JlBAa;sFAAAAwD;EAAAAAA0BbAAAAAA0B,A,A;knDtBzWe0vFsB;yTAU4CAsB;mNA4CrD9N8F;kUAqBO5hF8C;qtCAyDT4Ee;uIAQ6Bh3DwE;+EA0CzBoyDsD;6oBA4BQ4EiD;AAII02CAA5GEq0CkD,A;gUA+GVC0E;4iBCrPiBhiJ2E;WAAAAQ;4FAoCrBoyD4D;0RAKOA4B;wnBA0BEAK;urJPZRmiFiC;yJAMiB0NqB;AA+vBnB3KiC;oMA/E+BthFgI;0hIehf5B5DoC;+6BuDjIiBAerD+DFlwDsC,A;igCqDfnButI4D;sDAESr9EoC9C6gBsClwDwB,mDAArDkwDAAAAA0B,A,A;+B8C3gB2CAAApLrCAA/CizBAAAC/uBkB2oFAAAA74IwD,A,A,A,0HAgBxBkwDsF,A;uB8CkG2CAAAtL3CAAAAAA0G,A,A;AAwLE8vF8d;gZAYiBC+B;kBACfCyE;gDAKKD2B;AAAaEuC;gYAahB5Se;mCACSr9E6D;qDAGFAkE;8YASH1lEAnDiqBuC0lEuC,A;2GmD/pBjBlwDyD;mGAEpBxVAnD6pBqC0lEiE,A;2OmDtpB3Cq9E8B;ihBA8BG6S2C;iGAIPx1CQ;0PAMIq1Ce;4JAIAE2B;yJAaEEsB;meAgBFFqC;oHAMGA8C;AACH5S2B;8+BAe0C0SkB;kDAIjC/vFS;AADT+vF4B;8RAQAEqC;wBACAGmG;sEAKEHuC;2NAWFAqC;qMAOCAqC;m8CAsB0BjwFwB;4JAAAAmC;iOAQAA6C;qFAK1BiwF2B;u/EnD4D0BngJkB;gvBA8CzB8WeA8XsB9W+D,+GAEpBxVAAOuC0lEqE,A,6H;43BF34BvC1lEAE24BuC0lE+C,A;OF14BnCqoFuB;uFACkBv4IyD;mGAEpBxVAEu4BqC0lEiE,A;qWFx3BnCqoFuB;+cAWAAuB;oYA4FPtmC4B;8BACE4mC2B;AAA6B0H4D;0JAI7BrSyB;kBAAgB7csCAbhBmvB6C,A;wLAkBE3HqB;wkBAyHe74I2C;wNAUAkwDwBAhEDlwDgB,qE;oBAiENuwHsH;6PAYOrgEwBA7EDlwDgB,iC;oBA8ENygJkJ;uKAKOvwFAAnFDlwDsB,kD;gGAwFN60F6E;gBAAAAyC;qKAKO3kCAA7FDlwDsB,kD;yGAiGN+9F4E;gBAAAAyC;sFA+CTs6CoB;qBACMAyB;8OAOVGe;sNAQiBCqF;0KAOZJuB;0UAULGe;oaAeiBCqF;gLAOZJuB;yQAWDAoB;2mBA2EAAgD;4QASNDoBAzKMC2B,+D;yOA+KAAoB;yGAIRDoBAnLQCyB,2D;sNAwLAAoB;8CAGRqIAA/KA1HoBANQXyB,mB,AAMYnoFK,AAApB8oFiE,A;kTAoLQXgD;iFAgBRCoBArOOC2B,mB;2QA6OKI2B;AAERLoBA/OGC+B,uB;8XA6PCFoB;AAERCoBA/POC2B,mB;umBAwIWoIsB;AAIdCiBAvIGDwB,mB;8PA+IWAsB;0iCA+KK1Vc;sCACAiD2B;qEAGEvE4BAxeRkXyC,mBAAVhIsB,AAAUgIgG,A;8JA0ewBjIiBA/TlCD0B,mD;iOAgUiCCiBAhUjCD0B,E;kDAgUiCC+C;AAEH1oFE;mOAMmBmoF4C;AAC3BM6B;iCACqBCiBA1U3CD2D,E;kDA0U2CCoC;iyBAiBnBh4BoB;wBAAAAAA9hBOkgCkBAxB/B7V4B,A,Y;0BAsjBwBrqBAA9hBxBi4B2B,AAA+BiIwG,A;qHAgiBH5wFE;8UAOI0oFiBApWhCDwB,+E;6FAsWctnBkBA9iBd6cqC,AACAsSiD,A;+VAkjBsB5HiBA3WtBDuD,qC;0IA4WiCCiBA5WjCD0B,E;oCA4WiCC+C;AAEH1oFE;ohBK+RXA6CL/vBHlwD4C,A;iPKogCCkwD6CLpgCDlwDgB,A;sBKogCCkwDmE;kPA6BAA6CLjiCDlwDgB,A;sBKiiCCkwD+D;4aA+FAAwBLhoCDlwDgB,sE;u1BKuBTkwDa;qDAAAAAEsR4Cg/BAXqF5Bh/B2B,yBAAAA8B,A,I;yxHUxFvB6wF2B;UACFX4B;8WASEWqC;AACFXwC;6CACclwFU;2DAAAA0C;oQAI4BAU;mCAAAA2C;+JAQxC8tDqC;AACHoiC8B;qVAaA7Se;mCACSr9EkD;qDAGFA0D;qNAKN8wFe;0GACuBl1DoBNxVuB9rFgD,AAArD8rFAAAAAmC,A,A;oDM0VU57BmCAyXJAAArDsBAoBNhqBHlwD8C,A,2M,AMmtBzBkwDAAAAAAAGiBu9EAA3bbzvBe,mG,oB,A,K;8DAiEM9tDkF;oJAiBQ+wFmD;AAAuC/wFeN7WhClwD8C,A;mJMqXlBghJsB;iNAQAAsB;iFACGx2JAJsUuC0lEuC,A;eIrUjBlwDyD;mGAEpBxVAJmUqC0lEiE,A;uOI9S3Cq9Ee;slBAqBAvvBe;qIAG6B9tD+D;iIAK7B8tDe;gJAG6B9tD6C;2FAM1BkwF2B;yLAIPx1CqD;uRAOKm2C4B;0FAGyC7wFAAwK1CAAC/uBkB2oFAAAA74IwD,A,A,6GAgBxBkwDsF,A;0QD+jBI04D+D;6bAsBEw3B4B;wdAkBelwFyBN1fIlwDoD,A;wgBMkhBnBogJ4B;wFAEF9hCiB;gOAME8hC4B;wFAEFx3BkB;wgBAzBuC2vBuB;qpBAoDXroF8D;uGAIAA6C;6gBAyCAg1CgC;unHC7pB1B+7Ce;oNAMgC9wB2B;2OAKhC8wBe;86BA2DDCsC;mKAGgBAc;0NAKjB/wB2B;ySAqBMgxBqC;AACJFe;+HAIc/wF2F;4EAKd+wFe;2IAIc/wF6C;qFAKVixFqC;AACJFe;gQAcGGyB;2DAICAyB;2DAIDH2B;sQAeoB/wF+C;qFAGtBmxFe;gWAWGJ2B;oBACACsB;qBACAIsC;AACcFoB;2VAQdH2B;oBACACsB;qBACAIsC;AACcFe;qhBAmCdH2B;oBACACsB;qBACAI4B;4bA6BAAsC;AACcFoB;kRAkBdEsC;AACJDyC;8WASEJiB;8FAIiBGwC;sRAWnBCe;mtBAzGEJe;2sBAqCCMe;q0HA6QHpgCuB;yEAEAqgCe;mhCA2CIrgCoC;qXAsCJsgC4B;6iBAiBAhUe;6+BAiTOv9EoCA3UwClwDwB,iDAArDkwDAAAAAwB,A,A;mgHNgIuBAyB;8rYA4PPAoB;kIAEdwxF0F;mhDA6K2BxxFyB;qdAqBzBoqC2F;2cAYAA2F;giBAYAA2F;m3EAgFF8+CyB;6iDSvyCWlpFyC;6OAAAAkC;iNAU0ByxFa;gJAGHAa;wiKAuL7BAiE;kiBAuGqBCyD;+nBAiEf1xFa;uEAAAA2C;+1BAg1BWA8C;qEAAAA6B;+CASXAwE;oDAAAA+CA2XbAAAAAAqD,A,A;u5BAjWeyvF8C;2jDAiEXvmF4E;y1DA4F4BlJqG;w9EwGj8CJk3DI;wiBJkCAl3D4C;+DAAAA2B;yBAAAAqC;6rBA2IUA4E;WAAAA4E;0kE9F9JhC+uCqC;AACAAA/BohBJg7C8B,A;A+BnhBIh7C4B;+lFAiVF/uCkD;4FAAAAmE;8GCyMwBA+H;k2BA+Bf2xFkN;m8CA0KSC0gB;qXAmGpBCoG;yrBkGjvBE7xFyE;WAAAA6E;gsCAmOgBk8E0B;wpBA2D2BA6B;AAE7Cl9CuG;gGAAAlvFsC;4MAKEkwDyE;WAAAA6E;iMAYoCAgD;WAAAA+B;oNAuBtCg/BoH;0DAAAlvF8B;sIAKAkvF8F;gEAAAlvFmC;6JAyBAkvF8F;kEAAAlvFmC;2EAuBiBkvFsH;wGAIPlvFqB;2CAIOkvFsI;qHAMHlvFoC;wXjG5XVgiJmB;gUAWYA+B;gRAMZA6B;wDACO9xF+B;0DAwCP8xF6B;yOAaCAyD;qNAoBDA6B;0jBA+BGA4B;4HAQCA4B;sSASJA6B;+XAiBFn8BkD;yiBAyCam8B6B;qTASAA+B;wHAEc9yDAtBiQCh/BwC,yBAAAA4C,A;0LwHpjBGimEmC;4+CjGyEpB8rB6Q;+sBAqBmB7V6F;0TAQfl8E6C;4FAEX23EAlC+aW9lEM,AAAjBk4EkG,A;kQkCja6B7NiB;uWASvBntC6BlCmZNg7C6B,A;sDkC/YyC3tDoB;w5BkGrBb+Z0B;kBAAAAkB;6kB1FlED67CwC;0pBA0DdlvJgF;0mHAiLFk9DgD;0BAKGAiD;6GADHAuC;AACGA0D;+IAIPo8BkB;2LAkFH25B+B;4jEAsEE4hBA1C+FW9lE2E,A;wiEAnNCmiDe;mPoC2MKssB0C;sBACDx/B2C;sBACAkCyC;sBACAyT6C;sBACE3f+C;sBACA9F8C;wBACC4vBmI;6NtBrWiB5RU;oQAyCtCAkB;iCACSijCAAiCmBCoC,A;oCA/BG1tCuD;4BACA4KsD;yFAG1BgXoD;0qPdxJP+rByR;qCAGKC4I;uTAQLC0FAYaryFmC,4H;ycM2E0BAyD;cAAAAwC;oZAwJnBA8B;gpCA8IfA6D;cAAAA4C;qvDN9buBqpF4C;wiBAkVlBv0BsCwIjTKw9B2E,yE;QxIiTLx9B6B;0LwCqPe90DwC;62HC4sCXwiEc;0PAQYsnB+E;+DAIYtrCsC;4HAkB5BqrCoD;wfAaIz4BA7Bx8CM5SkF,A;0I6B88CFwbA9BxnDTh6DyB,A;oE8BwnDSg6DqC;4jGAiuBHgE2BA+CWxf+B,A;mEA7CN8SgD;yTAcHA+B;AAAuC1M6F;2UAiB9CilC0F;suBAsCRjiDe;uKAIAykBkB;gKAIQkmC4F;4DACgCCSAIxChwB0D,yPAUJpL8B,AADIxS6I,A;wJA2Da6tCyEAObjwByC,0EAIFkwBsLA1BA3jD8E,A,8L;0UAsCEyzByD;SACAockD;oNAIAjEkE;2LAEA5pB6E;yiFAqsBQ/wD4C;y4FA8xBD2yFkF;kzEA4FN5hCgD;AACE/wDY;AADF+wDiB;k5BA2CeKA7B/8HE5S4D,A;mJ6Bq9HWsrCmE;gJAIOtrCsC;iaAmB5BqrC+D;0vBAoBJv4BmB;8CACAkRmB;+BACIlRqB;2FAGQ0M8C;uNAUTh+DiB;sVAcHg+D+C;uCACE2cyB;4FAIC36EiB;2OAUD+wD+C;AAIC/wDS;gVAYH4kDwF;2DAIC5kDiB;kPAUAg+DsF;AAAqBwEkC;yIAUrBxiEiB;k6BA4D4C4kDkC;AAAnB0MyF;8DAmB3BtxDmC;s4BAuBUuyF4F;qEACgCCsKAUrCte6E,A;siBAmBH1RkB;mHAEA0RgI;AACAyGuB;uDANGkP0C;AAOH94BU;y5EI89eO6hCA6F3koBX9pHADgBDk3BsC,AAAAl3BwB,A,A;kgD5F80lCA+pHgC;6LA4BAAgC;uMAYAA+B;AAActV2B;4LAMMA2B;qQAOtBljBsG;89B6Ft1lCOxwFADjDuBmqFQ,A;yNCqE5B6lBuG;8GAIS7iB0E;6BAAAAgB;4FAGXOqD;6LAckDP0E;uNAQvCA0E;6BAAAAgB;4FAGXOqD;+WAeFA4D;+oCAsESptFwCD9LA2oHArG2VXp3DApC/IAAuF,A,mBoC+IAAApC/IAAuH,A,A,A;O0IdWvxDAD9LA2oHsC,A;wPC0MLCoG;8CAIS/7B0E;iCAAAAgB;sKAIXOqD;8NAQwDP0E;sNAOxDOqD;qjHlFhOG3C0CANuBjtBqBzCDE0gDuB,A,A;2qDmDyDf1gDOnDzDe0gDuB,A;wRmDmCb1gDOnDnCa0gDuB,A;wgBmD+Cb1gDOnD/Ca0gDuB,A;0hB6HiCsBpoFA3H6LzC27BwBFnCwC9rFgD,AAArD8rFAAAAA6C,A,A,A;glEgIlJco3DgC;yEAGZCwK;kuBAqDmBx1DA1H2VOz9BE,A;oD0H3VPy9BoB1H2VOz9BiC,A;i5F8CtQM6pDS;sRAKbAK;4qDAjB8BuVa;uBAAAA4G;0DAAAA0I;0S6EhC7Bp/DAAugBH+qFAAAA/qFA/HmGQAAFjvBvBAAAtB0B05BAAAA15BoBA4MLlwDgB,mC,A,A,A,A,A,A;oBiI/CHkwDmBAugBH+qFAAAA/qFA/HmGQA6D,A,A,yC;uN+H/WJoxDuC;AACD0oB2L;gBAAAAuB;kHAQlBqZiD;wIAaAnzFS;4CAAAAqC;6OAYWAAC3afAAAAAAsG,A,A;mDD2aeAwE;wpBAsDbs6CkE;+EAmBOt6CqC;qLAQWw+C+B;4HAIlBlEiE;iVA5DsBt6CkB;+BAAAAoC;2NAEAuiBAyCtZpBviByB,A;yOzCyZEozFmD;yMAmNOhiCAnB7mBW5S+C,A;6ImBknBKx+CiC;qTAyLhBw+CyD;yFAEPs2B2BDpyBQkekC,8FAGZKyNAoF4B51DA1HiTFz9B4B,oBAAAA6C,A,sE,A;mK2HoaxBg/BAnBz0BwBh/BkH,A;8BmBy0BxBlwDkD;gLAMsC2tFA3H1adz9BoC,4BAAAAiD,A;+c6HxXGgcAjIouBChcAF1xB5BAAAjC0B05BAAAA15BoBA4MLlwDgD,A,A,A,I,A;60CmIvDM2tFA7H0THz9B4B,oBAAAAkC,A;gxC4H7apBAuJ;irOIlBqCA0N;+BAAAAoB;8PAMjBmd0B;AAAEndkB;gCACtBAuC;6EAYWAgB;mtBC5BfAuC;qyDG4BKA2C;oLAUAAmB;yLAUAAoB;oRAcIAc;oZAWAAwB;2/BCtBE81EACtBIhoCkC,A;ADuBR9tCa;AADI81EwB;kDACkDrPA5GnDnCzmEiC,A;0b4GkEjBszFAAsBU7sBA5GxF+B34BsC,A,6B;O4GkEzCwlDAAwBJtzFa,6BAFcymEA5GxFOzmEiC,A,A;oC4GoEjBuzFAA6BU9sBA5GjG+B34BsC,A,6B;O4GoEzCylDAA+BJvzFa,8BAFcymEA5GjGOzmEiC,A,A;6B4GsEjBwzF2HAmC4CvpD4C,AAAhDjqCE,AAAgDiqC6B,A;+BAnC5CupDAAmC4CvpDe,A;oGA1BlCw8BA5G/E+B34B2C,A;A4GgFpDoFAClCI4iC6C,AAAQzjEoE,4D;ODmCLrSkB;cAFcymEA5G/EOzmEiC,A;4H4G+GrBqrC0B;oDAAAA+G;kPAYAA0B;yCAAAA+G;+8CIlIuCrMgB;miJ7C6L1B4yDwkB;sjEzCxJNjgD+G;sDAAAAA0D4XZ3xC2F,A;gI1DhWFg/Bc;6CAAAAiE;+CAAAlvF8B;oqFuFsO4B2jJsB;wDAEKAsC;OAAjBzzFoB;AAAiByzFwC;YAAjBzzF+B;yO5CtP+Bs6CiC;qPAgQ7CAuB;2JxBjTmB4hCiB;+DAIF9/CkB;sLAyBjBkeuD;gjByBPSt6CyC;AACX+uCApHkhBAg7CoC,A;+doHpgBIh7CApHogBJg7CoB,A;4CoHpgBIh7CApHogBJg7C+H,A;qGoHhgBIh7CApHggBJg7CiI,A;klBoHnfIh7CyBpHmfJg7C6G,A;AoH9e+B3tDqC;AAAxBke0D;67FAwFat6CsCzB3JIitFAAAAjtFiC,A,A;6wEyB6MNAAzB7MMitFAAAAjtFmC,A,A;2ByBkNtBs6CAzBjMFvLA3FgiBAg7C6B,A,A;AoHpWkB/pFiC;sCAOXs6C2C;gDAGGleAzB3MSAoB,A;2eyBsNTg1BAxGqMY5S0C,A;oDwGpMV4SAxGoMU5SsC,A;qOwG3LtBm1C8L;6fAoBWn1CoC;AAA+B09BKzBxPrBAqD,A;AyByPnB5hCoBzBhPFvLA3FgiBAg7CkB,A,A;oBoHhTEzvCAzBhPFvLA3FgiBAg7CiC,A,A;qEoH9SEzvCAzBlPFvLA3FgiBAg7CgC,A,A;s0BgKjiBsBzvCoC;urBzCNFt6CsC5BVIitFAAAAjtFiC,A,A;ygC4ByClBg6DA5GoNKh6D0D,O;iD4GpNLg6DA5GoNKh6D4C,A;0B4GhNL4zFuE;8qBAwBA55BA5GwLKh6D0D,O;kD4GxLLg6DA5GwLKh6D4C,A;0B4GpLL4zFuE;0GAMA55BA5G8KKh6DyB,A;gE4G9KLg6DoC;uGAAuC45BkF;iEAGIA2F;qBAA5B9tD6D;i1BAxCN8tDgD;wcA4BAAgD;yJ2CMKp7GAAiBpB4jDuC,A;mEAjBoB5jDAAiBpB4jD2B,qDAAK0JkE,A;AAhBEwU0D;k5C7CFczIkD;AAAsB2qBkC;6CAI/B1sH0B;wCAAAA6D;gaA6IGqsFA1GAJn8B2B,kC;2b0GsBMm8BO;uCAAjB6CgC5H8K8Bh/B+E,A;2G4H9K9BlwD+B;AACM0sHyE;AAGWrrD4G;+RASJ0gCyC;AACuB2qBmE;AAGhCztBgD;2PAKeotCgE;8IAiCNhrEiF;4DAESgrBA1G/EXn8BsC,A;iB0G+EiBgtDiB;AAAN7wBA1G/EXn8B8C,O;2C0G+EiBgtD6C;oPAqCf77CgE;gYAwBHy9CoE;mIAhBWqVAzGuBQjkE+B,A;AyGFKk8E8D;yEACjBttB2D;w8BA2EGtMAAzQWzQuD,A;kEA2QT/hGuF;kDAGlBwyGAA9Q2BzQgD,A;AA8QFAmC;sCAMzByQAApR2BzQkC,A;AAoRF2qBmC;wCAMzBlaAA1R2BzQkC,A;AA0RFAmC;kGAIZ1gC4D;gCACAA4D;oEAEIigDA1GkHC5Se,A;ue0GnGE4SA1GmGF5SiB,A;kE0GlGD4SA1GkGC5SmB,A;8nB0GvFD4SA1GuFC5Se,A;onB0G9EDAe;slBA4CE3M+N;AACDA0D;2qCA8BjByQAAhZ0BzQoB,+C;qmMAgzB3ByQAAhzB2BzQsD,A;mEAmzBO/hG4B;+DAAAAmB;8aAuCjBu1CyD;k3C8C19BNqXuC;2erE8BP00DAnFqfc5SuB,A;gTmFlfT4SAnFkfS5SwB,A;wNmF9eP4SAnF8eO5Se,A;0kBmFleL4SAnFkeK5SqB,A;uQmFtdjB3MuB;sHAKQ2MsB;AAAY3MuB;oLAUrBAa;mEAAuBufAnFucL5SiB,A;wQmF7bb1YK;yXASPiJgB;qGACAAgB;oBAEFAU;umDsEpHalYyD;0QAOI2nBuB;u4IEyCU1YyD;OAAhBjPyD;oNAUmBsFA3JoInBn8BgC,A;4D2JpImBm8BkC;qYAkBXqiB8D;6HAOK1YuD;kCAAKAoD;6vC/G1BzBu3CiBAjC0BzoB2BC7BFjtBOzCDE0gDuB,A,A,A;gOwCqEdpoFAtCyJL27BoBFnCwC9rFqD,AAArD8rFAAAAAoB,A,A,A;AwCtHqCzeoC;0EACJi0CmC;2EAGbpxDAtC2qBOAAFjvBvBAAAtB0B05BAAAA15BoBA4MLlwDiE,A,A,A,A,A;gCwC/GrBwqGkD;AADgBt6CAtC2qBOA2E,A;+vFsCngBDoxDiC;2HAGbisBiBAtNmBzoB2BC7BFjtBOzCDE0gD2B,A,A,A;+LwCyPZv4IoC;gCAEhBwqGkD;oYAgBYt+BAtC6hBgBhcAF1xB5BAAAjC0B05BAAAA15BoBA4MLlwD4D,A,A,A,A,A;6BwCmFvBwqGkD;AADct+BAtC6hBgBhcqE,A;iLsCphBNw+C6B;AACtBnc8D;AAEAwxD0J;8LAzE8Cn6DgC;kCAI9B15BE;iCAAAAAWpND+qFAAAA/qFAjDsvBQAsBFjvBvBAAAtB0B05BAAAA15BeA4MLlwDkF,A,A,A,A,A,A,AmDpKTq7ImF,A;AX8LVnsDY;2DAAAAqC;yCAAAlvF+B;oSAQmB4pFO;6WA2CoCvc6B;ihBAwD3D22E6DA3FwB1iCiC,8BAEQj0C2F,AAG1BkgEiBA1MwBzoB2BC7BFjtBOzCDE0gDqC,A,A,A,uC;mhC0CsCL5+CyB;yBAAAA+B;iQAIjBAoB;qEAJiBAmC;0RASgC6zCiB;sKAClB1uB8B;iCAC1BnlBuD;AAXYAuC;mhBAoBdzpCmC;wxH4BqEmBmgEmH;2RAE5BpxBY;uCASFAiB;2RAYE6rBY;yGAAAA+C;2nCA8DS56DiEuF5JbAqD,A;gnCvFuQmBqqFAtCrSKpmBAnC6TOjkEwC,A,AmC7TpBs8BAA7BcguD8C,A,sBA6BdhuD6EAaeiuDoB,8B,AAF1BjuD+C,A;kJsCmSsBt8BwG;sEAGHu1CgD;uKAAAA8D;iEAEAiJ+B;4BACGx+CqD;sSAqBR+zF4C;kDACc7hD0D;iCACNlyCqF;AAEJ+zFkE;+MAKY7hD4D;mEACb6hD+C;oDACa7hD4D;mEACX6hDiD;oDACW7hD4D;iCACNlyCkG;AAEH+zFsE;2LAML/zFyG;6GAKDw+CuB;4BACGx+C6C;+HA4EVAgH;2zDAmDSi/B2KuFtcjBj/B4C,A;kCvFwciBA2DuFxcjBA+C,A;oTvF8c6BmgE4E;AAAfngEmB;AAAA+uCuC;iCAAAAS;4BAAAAS;uBAAAAS;wBAAAAS;imBAoDSoxBgD;oRAiBAAqD;y7CA4CrBpxBwB;AACAAc;wxDtCtjBoBmtC+B;siEAiEAA+B;otBA8BD94B8C;2NAQN84BiC;kiCAwFIz7BuE;KAAAAoB;iTAYXy7BmD;AAGqB94B2E;4HAEjB3C8F;kHAKiB2C+C;AAGR84B4C;wIAOZz7BqF;uYA2CoBkvBW;uIAKvBAgB;AAAmBAU;4MAWnBAa;cAAAAW;KAAmBAe;6iBoDlME/uFCsEzDDozGyC,A;0mBtE4EACqB;8sBAWTz1CuC;yQAQWteiD;+OAGNAyE;0BAEKr/CCsE1GHmzGoC,A;AtE4Gf53DkB;ytEA+DP4CA1GtQ8Bh/B2H,A;0D0GsQ9BlwD8B;snDAmEAkvFA1GzU8Bh/B2H,A;iC0G2URi0Fa;mCAFtBnkJ8B;iSAYsBm0HAvFEOjkEkC,A;AuFF7Bg/BA0B9T0Bh/BqH,A;uE1B8T1BlwD8B;gGAII6nIAnGqMa9lEiE,A;khBmG9KKoyDAvFzBOjkEsC,A;AuFyB7Bg/BA0BzV0Bh/B4G,A;gC1ByV1BlwDsC;sGAQsBm0HAvFjCOjkEsC,A;AuFiC7Bg/BA0BjW0Bh/BiG,A;mC1BiW1BlwD8B;6QAWoBi/F6C;kVA3KFntDa;4EAAAAAuEvNlBoyGgD,A;AvEwNIjlDAnGgUJg7C6B,A;iXmGrSwBloGiBsE/MMmyGoC,A;6CtEgNNlyGCsE5NOkyG0C,A;2BtE6N3BjlDAnGmSJg7C2B,A;iZmG9QwB/nGa;4EAAAAAsE5OKgyGqC,A;AtE6OzBjlDAnG6QJg7C6B,A;8ImGvPkBnoGa;4EAAAAAuEjSlBoyGiD,A;AvEkSIjlDAnGsPJg7C6B,A;+ImG5OsB/nGa;4EAAAAAsE9QOgyGqC,A;AtE+Q3BjlDAnG2OFg7C6B,A;iNmG3NsB7nGiBsE7QW8xGuC,A;6CtE8QXlyGCsEtSSkyG0C,A;qBtEuS7BjlDAnGyNFg7C2B,A;0bmGhL6B/nG8BsE1UAgyGsC,A;6tB9FwBP7zByF;qCAAsBhhBkB;aAAAA0G;6WgGpExCwwBW;gYAmBFAW;2IAGgBAiB;oDAEIxPa;qGAAsBhhBAA7B/BwwB6C,oEACKp1CwB,oD;4CA4B0B4kBAA5BdtgB8B,A;qqClFY1B5C8B;mCAAqBNyB;uDACSAiC;m3BoFkBSwImE;gGAI5BqayD;qXAUJx+CA1EHGk0FglB,kI;O0EGHl0FA1EEAmd0JA3BOg3EAAAAn0FwB,A,A,A;gf0EiCImgEoD;sZnHgJlBnGA/CiDOh6DsH,O;kH+ChDUm8B+E;+CAcFqiBkE;AAAwB4SgD;OAC9BpxDqC;8GAGFAkE;qHAOUAqC;AAAM2xCA/CNhB3xC0D,O;gC+CMgB2xCA/CNhB3xCsD,A;A+CMUAACPFA8B,A;+IDmBZg6DA/CWIh6DqD,O;6B+CnBGg6DA/CmBHh6DkD,O;kC+CnBGg6DA/CmBHh6DyC,A;iE+CXJg6DA/CWIh6D4C,A;+d+CjKFlwDiE;oSA2CgBowFgC;kBAAAA+C;mGADPlgCuDCyFCA0B,A;ADvFgBo8B6C;2DACM8DgF;OAA5BlgCsD;iUA4BoCsVYCpCrBtVyB,uCAAAAAA8FTA+B,A,A;klBDfAw+CuB;ihBA2BJwbA/CkBJh6DkD,O;mC+ClBIg6DA/CkBJh6DyC,A;wc+CVIg6DA/CUJh6DqD,O;8C+CVIg6DA/CUJh6D4C,A;ghB6GtKJmkCgC;+jCAoCUnkCY;yJAIiBAoBChIhB6gCiD,A;kBDoID+tBApH2DchhHgE,A;6EoH3DTk4F2D;AACbA+E;AAEe8oBApHwDOhhHiD,A;wCoHtDPghHApHsDOhhHiD,A;mKoHjDhBoyDgC;8TAMmBAoBCpJhB6gC8C,A;kFD2KV+tBApHoBuBhhH+E,A;eoHpBvBghHApHoBuBhhHW,A;mEoHdhBk4FmE;AACAA0E;qBACAA8D;yBAKY8oBApHOIhhH4C,A;gXoHpCZghHApHoCYhhHoE,A;sIoH/BZoyDY;2JAIoBAoBCpKrB6gCkD,A;4BDsKqB+tBApHyBRhhHgE,A;mDoHzBgCghHApHyBhChhHiD,A;qDoHxBXghHApHwBWhhHiD,A;eoHzBdoyDoB;yUAkCiBAoBCxMhB6gCiD,A;kBD2MY+tBApHZChhHgE,A;0EoHevBghHApHfuBhhH0C,A;eoHevBghHApHfuBhhHW,A;0BoHkBUghHApHlBVhhH4C,A;8WoH4BhBghHApH5BgBhhHiD,A;eoH4BhBghHApH5BgBhhHW,A;gEoH8BvBghHApH9BuBhhHiD,A;QoH+BhBoyDO;AADP4uDApH9BuBhhHW,A;2hBoHsDjBghHApHtDiBhhHgE,A;eoHsDjBghHApHtDiBhhH4C,A;AoHuDjBymJA/EiDShKAAi9FDrqFyC,2KAeHk8E6D,+FASF9/CoB,AAAFjfqE,A,gC;oE+ErhGsB93B+B;AAAzB4/DiB;AAAWqLiB;AAAcjrEAF8JlBAE,qBAAAA6E,A;AE3JJupEApH/DgBhhHiD,A;eoH+DhBghHApH/DgBhhHW,A;iEoHgEdghHApHhEchhHiD,A;eoHgEdghHApHhEchhHW,A;mEoHiESghHApHjEThhHiD,A;eoHiEhBoyDqC;4ZnB7OTAgB;8IACeAgB;inC5BDfAgB;2kC2BuE2BAqC;sEACpBAgB;gFAOAAgC;iCAHGAgB;uPAWCs0FyBA1EQxkJyB,4D;wDA2Edo+IoC;SAAAAqB;0GAAAAAA+ELluFiD,A;gZAvEWs0FyBAnFQxkJyB,4D;iEAoFdo+IoC;SAAAAqB;oHAAAAAAsELluFyD,A;8YA5DWs0FyBA9FQxkJyB,4D;2IAgGdo+IoC;SAAAAqB;sHAAAAAA0DLluFiE,A;icApBFs0FYAtIqBxkJyB,4D;iGA0IVo+IwEAgBTluFqD,A;kHAdmDkuF4E;4BAAAAAAcnDluFkE,A;iGAV0BAgD;stBAuCrBAwB;wzFAKEAqC;AAAYkgC4F;AAAZlgCAzCIMA8B,A;wQyC4BRAW;4CAAAA6C;qVzCgCcihEc;uCAAAAAhDmOKjhEkF,A;AgDnO9Bg/BAlEnQ8Bh/BuF,A;mCkEmQ9BlwD0F;0GAGuB0uGwC;8GAENx+CY;+EAKHg6DAhDxCHh6DgD,kC;wRgDmDAAqC;AAAgBihEAhD8MGjhEsC,gCAAAAmD,A;AgD9MnBAAAjFQA4B,A;SAiFiCo8Bc;+IAU7C49BAhD7DIh6DqD,O;6BgD0DPg6DAhD1DOh6DkD,O;kCgD0DPg6DAhD1DOh6DyC,A;iEgD6DJg6DAhD7DIh6D4C,A;kTgD9KckgCgC;kBAAAA+C;qCAAZlgCuDAgJMA0B,A;AA/IGo8Bc;i+EAwNPp8BE;gDADS8lCsD;yuCPnSgBrIA/Bgddz9BE,A;oD+Bhdcy9BoB/Bgddz9BgC,A;6M+B3blBAuCAgDau0FAAAAv0FAnCmsBIAsBFjvBvBAAAtB0B05BAAAA15BeA4MLlwDyF,A,A,A,A,A,A,yC;opDqCtGnB2kJyC;6JAKJn6CmE;6OAMIm6CyC;+ZAcFl5CK;OAAAAuD;0KAYFRK;OAAAA2B;wYAMI05CyC;yHAG6Bx0FAnC6FtB27BoBFnCwC9rF6C,AAArD8rFAAAAAmC,A,A,A;yBqCxDkC5fAnCqqBFhc0BF1xB5BAAAjC0B05BAAAA15BeA4MLlwDkF,A,A,A,A,A;kXqC3CnB2kJyC;6HAIgB5qCsB;wJAKM9OK;OAAAA2C;YAGnB8OsB;8JASaliBOrCnKU0gDuB,A;iCqCqKzBoM+B;i9BH9DWj+BO;AAAM/4B6CG3HkBAA/Bgddz9B4B,oBAAAAiC,A,A;gK4BjVQy9BiBG/HMAA/Bgddz9BK,A,A;wD4BjVQy9BAG/HMAoB/Bgddz9BiC,A,A;mG4BvTGw2DO;AAAM4oB4B;qdAyBsBp/EA2FrJLCA3HqNzC27BoBFnCwC9rFgD,AAArD8rFAAAAAmC,A,A,A,A;OkC7B0BzegC;AAAwBndmD;AAASA2D;AAAjCmdgC;ohBAgBPsgB6CGlMuBAA/Bgddz9B4B,oBAAAAiC,A,A;6K4B1QKuwDwB;AAAQ9yB0B;AADjBtgBE;AACiBsgBiB;uCAAAAAGtMCAA/Bgddz9B4B,oBAAAAoC,A,A;A4B1QwCo/EQ;AAD5CjiEuC;6RASLiiEO;kGAMVAgB;ykBAaYAO;2/BAlFEAgB;uEAMAAuB;82DH7EgBtxCkC;uTAURA4B;orB6GdjBAkC;gpBAkEIhI8D;AAAWAiF;AAI3BzzBkEA2DmCy7BiC,A;uNA5CQAwC;moDrE1JjCxhDACiCsBx8C6I,2K;ygBD/BhCy8CAC6CkCz8CkJ,8M;uWmC9BFkqFiB;kEAA2BwIA7E4+nBzC91CA6Fp+nBbDADcDuT4C,4D,A,qB;oSfnBwByoD6C;sFAAAA6F;AAIjB+NO;AAAM/4B6CtEvBuBAA/Bgddz9B4B,oBAAAAiC,A,A;mSqG5bbw2DO;AAAM4oBgB;AAAiB58CA7Ew+nBlB91CA6Fp+nBbDADcDuT4C,4D,A,A;m0CxCoGmB20FwB;AAAV30FkF;kGAAAAyC;i3BAoDmB20FwB;AAARx3EgGAzJUowEyC,AAGGCyC,AAGACyC,AAGtBCgC,AAUiBC+E,AASLC2C,AAMIC2C,8EAzBhBHAAAA1tF2E,A,A;AAkJf8wCqB;mDAAAA0G;iFASqB8jDAA/HQxjCAtFqfP5Se,A,A;oVsFvURwbAtFCHh6DyD,O;sCsFDGg6DAtFCHh6DgD,A;qsDsFmD6Bw+Ce;mDAGpCm2CwB;AADG30FiE;OAAAAoB;wnCA3JLg/BAxG/H4Bh/BsI,A;8YwGiIhBlwD2G;AAAA+5FmEnB0BV8eAA3FaqkCkI,A,gLA8FNvuBwB,AAAA3uHyH,mI;gLmB7BG+5FAnB6BH/5FmE,A;uTmBxBSAmD;4CAAAACnB5BRA0B,c;ghDmB2HN8kJqB;SAAAAAA/KuBxjCAtFqfP5S4D,A,A;AsFrUVx+CgB;mnBAuDOlwD2D;4CAAAACnBnLPA0B,c;w9DjBhFC0uGsB;QAAmB4SAlDihBV5SuB,A;uPkD1ffwbAlDoLIh6DoH,O;sFkDnLNm8BkE;4CACA6wBwD;8yBiB7BiB7vCAAkDEmxEAAAAtuFA7D4qBCA2BFjvBvBAAAtB0B05BAAAA15BeA4MLlwDwE,A,A,A,A,A,A,4B;W+DnKDqtEAAmCH43EAAAA/0FoB,A,AAgCmBg1F8C,AAOpBCAAAAj1FgB,A,AAyCWwtF6D,AAGE0HuD,AAEjC/3EAAAAAkJ,A,A;SAvHiBqfAAoBoBAU,A;0MAdlBrfqB;qWAkDErtE6B;sQAgGf64GAA/GaqkCmBAdQl9I6B,wB,kBAcuB63FO/DhElB0gDuB,A,A;+S+D8MhBroFAA2NG+qFAAAA/qFA7D2UQAAFjvBvBAAAtB0B05BAAAA15BoBA4MLlwD2C,A,A,A,A,A,A,8B+DgPNi7IAAAA/qFA7D2UQAwF,A,A,A;yoB6DzgBrBw8B+B;kCAAS6YAmGlNQoxB6B,uC;0GnGsNPjqC+B;kCAAS7uFM;kkBAkEJ6uF8C;kCAASiqC2C;AAAMx/BwFoG3TyBgJiE,2E;gUpGsUtDzT+B;gDAAS7uFM;SAAc0yFsC;yOAMP+wBAnEyOC5SyB,A;uDmEvOpBmXmD;8CASEn5B+B;kCAAStB6B;udAcqBl7BAA8EjB+qFAAAA/qFA7D2UQAAFjvBvBAAAtB0B05BAAAA15BAA4MLlwDyD,A,A,A,A,A,A,A;A+DkNd0sF+B;8FAhDyBx8BoBA8EjB+qFAAAA/qFA7D2UQAsBFjvBvBAAAtB0B05BAAAA15B+E,A,A,A,A,A,A;A+D8ZVryDM;SAAc0yF+C;++GAzJQ9wCAc7EnBi1D8B,A;Qd6EmBj1DAc7EnBi1D2F,qBACA4KqE,iDACK/FwI,2R;4fdoFlB7sB+B;kCAAS6YAmGlOIoxB6B,uC;iCnGmOC32HgB;AAASkwDuB;ueA8DhB06CkCAgIC/SO/D1bc0gDuB,A,uB;mH+D+V5B+Ma;kIAAAAwF;uoEAwBkCvyJgC;0+CAR5B64H6H;0SA0BmD25BI;MAAAAmCAeLxyJyC,A;mMA0BvC8kGO/Dlbe0gDuB,A;8L6DcViN6HA6ITrEmBAtE4B5T4B,A,qJ;SAvEnBiYAAoJb94DU,kCAASuoBAAvJyBAiB,A,A;uIA4GrCksCkCAlCmC5T4B,A;cAoCtBr9EqC;iNAWbixFmBA/CmC5T4B,A;wSAwDdvvBARxCFmiCqC,A;yCQ6ChBptJA5D+sCPqmJqB,A;yO4DtsCW+HmBAtE4B5T4B,A;2KA6EhC7gDU;kCAASuoBAAvJyBAiB,A;oGAiKrCksCkCAvFmC5T4B,A;YAuFjBt4BiB;wMAWfAiB;oTd2DFiVArEyJmC78C8D,A;AqExJnC6vCiB;AADAgNArEyJmC78CiD,O;qDqExJnC6vCiD;AAGWxOe;snGA+FJjeoG;AAAwCnE0C;8qBAmBK4yBkB;k5BAtIO7xCyD;oDACxCnb0BuF5ORhCaINmBA6B,A,A;4B3FkPXgCY;+mEA4HlBmbe;oiCkBvRFojBkF;0CACoBpjBuB;wdA/D2Bnb2D;oDAAAAAqEnBnChCaINmBAiC,A,A;azEyBgBgCU;krCAkD1BwmEsE;8pC3B5BNhhIA6B9BN0rDAGHKqiGuC,A,0GHGLriGO,gCAAAAAGHKqiG0F,A,6F;kjBhCqCNnkCA5BguCU5SoC,A;6YyJrwCGxJgC;eAAuBAgC;6MAKV5YK;qsBxF0CZp8BACtEFitFAAAAjtFuC,A,A;iCDsEEAuD;OAGYo8BAC7DnBAkB,A;wc3B8GgBp8BuB;mGACE4kC0E;iBAAR5kCc;AAAQ4kCAlDErBstDe,2C;0MkDDDjH4B;+MAQIrmDsD;UAAAAAlDPHstDoB,gE;20BkCqDNllCArCsZG6hCsC,A;4IqCjZIzyDqF;2VAGE49BArCmERh6DuD,O;kEqCnEQg6DArCmERh6D8C,A;6cqCzCKo8B2E;0YAYP27CiC4BzM8Bt6CARuFbz9B2B,oBAAAAgC,A,A;4EpB0HjBiiC2B4B3MsDxEARiFrCz9B2B,oBAAAAgC,A,A;sFpBoIjBkgD6B4BlNuDziBAR8EtCz9B2B,oBAAAAgC,A,A;+hBpB7DhBo/EgBCmC8B7uBS,AAAQ6uBgB,A;wSD3B9Cp/EAK3CUw1FgL,A;AL2CVxnDsC;+JAAAA+D;AAAAhuC8BKvCgBy1FsE,A;+jFL+DoBh4DACCQAAG9ENAoB/Bgddz9BkC,A,A,A;A2BnYRAAgGyBiCmdAARZw4EoC,AAKECqF,A,A;0WhGlB7B5e6T;qNAW+C6egC;ifAUjC/lJgF;2cAObghG8J;kHAG6B33BoC;+CAAAA4P;mHADxBnZuE;yCAFL8wCwG;sZA1BQ0lBO;AAAM4oB2B;gGAKCtvIoCG5ErBAyB,8B;sLH4EqBg2HyIGlDLkQsV2HKvB15BS,gBAAAAA5BEIw5CoE,2K,A,kO;iYlGwE6BCEA8CzB3WgBCnFgC7uBS,AAAQ6uBgB,A,mE;ADqCfjiE6B;YAAA44EqH;4vCAoG/Bh7CI;gpBAgB0BjrGoCKtNrBAyB,8C;gPLuNuBnCM;SAAcwyF8D;gjBAc1CwlBI;k3BG3NgB3lDA2H3BKg2FAAAAh2FA/BSTi2FAAAAj2FuE,A,A,A,A+BNOk2FAAAAl2FA5BMIo/EAAAAp/EmE,A,A,A,yC4BTFg2FAAAAh2F0D,A,AAGFk2FAAAAl2FmH,A,AAuBvBAAAAAAiDACaAAtF6BTAuE,A,A,A,A;oFrC3BiBi6BmC;iGiIxBGiiDa;oBAAAA4B;uEAGUl9CAvDiCNh/Ba,A;0DuDjCMg/BAvDiCNh/B+D,A;+ehDrCLlwD4BCwHTA0B,qB;ADxHS4rH4E;sGeuCjBgYuC;ga3B8B+BzzEAhDuKxB27BwBFnCwC9rF8C,AAArD8rFAAAAAiC,A,A,A;qhDkDrDa/uBeO7HF64DmC,A;2BP6HQoTaAUsB5LkC,A;AAVdnsCcAcgBmsCkC,A;AAdP57BaAkBK47B6B,A;AAlBGltEkB;AAAYq3CAAsB3Br3CgC,8J;oHAiCpB05B0C;mZAsCyB+DA5CyNNz9B2C,oBAAAAiC,A;qnD4CtKKq7CyI;ueAMepLmN;iGAKtB+cAtD+QX6hCAAIPsHuC,4tB,A;i9CsDnQMxhDiLa3RUx3BAAmEgB63E+C,AAgDTxH+B,AAGE0H8C,AAEjC/3EAAAAAAAGgBndAF3FYusFwF,AAuD0Bx+EqJ5EmT7Cw7EmH,A,A,yD8E/QOvpFAFxFGurFyY,A,A,A,A,A;q0CXmQMxwCiG;spEAcvBT4E;wOAQwBy9BAWnVet6CoBRuFbz9BgC,A,A;umCHoRUgxE+H;2hFA8GFmCiC;mCAAAAA2CtdK11CAxCoFbz9B2B,oBAAAAkD,A,A;oEHmY1Bs6CwE;AAA2Bw+BA2CpdD94E4B,iC;sB3Cqd1Bs6CwE;AAA4BvZA2CldD/gC4B,kC;qB3Cmd3Bs6CwE;AAA2BhJA2ChdDtxC4B,qB;iK3CwDbymE8C;+BAAax2BiD;k6GAwLpBmN4K;AAEAipByV;m3BA0FQ7nBiC;iBAA4B4SAxC66BpB5S6C,A;2BwC56BlBlEkD;qyBAwCqBpayD;oa2CzTZlgCK;mEAEI05BkD;oQAaY2jD4B;6GAIbniD0C;iBAAAAsC;yKAKP68CiChChG8Bt6CARuFbz9B2B,oBAAAAgC,A,A;gKwC2BI+kDAhCtGWAwB,A;wwDgCmH7BhKkH;0nC0EPM0gCsB;gBAAW72EoD9ClGjB0tF6E,0E;Y8CkGiB1tFwD;cAAAAqF;QAIfyyCgB;AAAO6kCqC;0EAKSnEmE;8BAAAAA1GjISt6CARuFbz9B2B,oBAAAAgC,A,A;+HkHoDEiiC4E;YAAAAA1GrImCxEARiFrCz9B2B,oBAAAAgC,A,A;yFkHuDEkgD6B;YAAAAA1GrIoCziBAR8EtCz9B2B,oBAAAAgC,A,A;gPkHqEdq3CgErHCer3C+C,A;AqHDRoxDAzDhHG5SuC,A;AyDiHenHArHAVr3CiD,A;4LqHMdymE+D;4iBA4BSjoBqC;qFAGSnHArHrCJr3CiF,oB;AqHqCzBg/BAzD1KwBh/B8F,A;8HyD0KxBlwD+E;qFAKiBgpIarHtDoB5LqC,A;AqHsDb1uBuC;+QAcds6B8BrHpE2B5LmC,A;qEqHqE3BnsCcrHjE6BmsCqC,A;wEqHkE7B57BarH9D2B47BuC,A;yXqHqET4LArH7ES5LmC,A;4DqH8ERnsC6BrH1EUmsCmC,A;6DqH2EX57B4BrHvES47BmC,A;gPqH8E1BltEkB;AADayuEsB;yCAIV2nBAA8BG5xCkB,6DAAAA4D,6EACF4KqE,A;4BA5BI0pBArH5FkB5L6C,A;iBqH4FvCn+Bc;sCAGYhOArH3F6BmsCmC,A;AqH2FrB9bsD;gCAGGrwBArH9FkBmsCqC,A;AqH8FvCn+Bc;+DAIUuCArH9F2B47BmC,A;AqH8FpB9bsD;6BAGI9fArHjGgB47BqC,A;AqHiGrCn+Bc;6DAMFAkD;0jBAiBoBphGM;09EChRlBgoH6B;sErGiDoCx4CoF;k8BuB5B5BgnBuM;AAFEnkCA4EKcq2FAAqDECgR,A,AApDJn5EAAOpBnd2H,A,AANuBCApKoMhB27BAFnCbAAAAAA0C,A,A,A,uD;gF0FnKS0eA+EjCPAY,A;A/EiCOqqBAxC4D0DyakC,A;AwC5D1D9kCA+EjCPAO,iD;A/EkCOSA+E9BPAmF,A;A/E+BiBw7CA6EsCOp5EAAvCPs5EAAAAz2FA9C1BnBAAAAAAAAC0B22F+H,A,A,A,A,A8CiDiBnL8Y,AAmB3CruEAAAAAuCAW6Bg2DArH6D6B11CAEjJtBAoBC2FRz9BgC,A,A,A,kIkHHC4oCqD,uH,A,A,A;i5qFzL2zCViuDoL;oZAUACwL;kZAUACsH;waAUAC0H;+tBqCn8BgCzM8C;6xEoFpc7B5tFAD3DYktF4C,A;oF/DAP7pFiB8GKFi9D6B,AACK92BiC,AACV0mC6B,A;wF9GAS7sEmBgHGJi9DmC,AACK92BqC,AACV0mC6E,AACQ/yB8C,A;gFhHEH95Ce+GVAi9D6B,AACK92B+D,AACV0mC2D,AACQ/yB6B,A;8gB3GHT95Cc;spD0CqBWAc;09C/C3BZAc;qFFHAAc;ilBoDesBmdyb;OAAAA0B;kwBxGmIbteAAqE3BgkF4B,A;"}} \ No newline at end of file
diff --git a/pkgs/coverage/test/test_files/test_app.dart b/pkgs/coverage/test/test_files/test_app.dart new file mode 100644 index 0000000..1e50703 --- /dev/null +++ b/pkgs/coverage/test/test_files/test_app.dart
@@ -0,0 +1,61 @@ +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// coverage:ignore-file + +import 'dart:async'; +import 'dart:developer'; +import 'dart:isolate'; + +import 'package:coverage/src/util.dart'; + +import 'test_app_isolate.dart'; + +part 'test_app.g.dart'; + +Future<void> main() async { + for (var i = 0; i < 10; i++) { + for (var j = 0; j < 10; j++) { + final sum = usedMethod(i, j); + if (sum != (i + j)) { + throw 'bad method!'; + } + + final multiplication = usedGeneratedMethod(i, j); + if (multiplication != i * j) { + throw 'bad generated method!'; + } + } + } + + final port = ReceivePort(); + + final isolate = + await Isolate.spawn(isolateTask, [port.sendPort, 1, 2], paused: true); + await Service.controlWebServer(enable: true); + final isolateID = Service.getIsolateID(isolate); + print('isolateId = $isolateID'); + + isolate.addOnExitListener(port.sendPort); + isolate.resume(isolate.pauseCapability!); + + final value = await port.first as int; + if (value != 3) { + throw 'expected 3!'; + } + + final result = await retry(() async => 42, const Duration(seconds: 1)) as int; + print(result); +} + +int usedMethod(int a, int b) { + return a + b; +} + +int unusedMethod(int a, int b) { + return a - b; +} + +// ignore_for_file: unreachable_from_main, only_throw_errors +// ignore_for_file: deprecated_member_use
diff --git a/pkgs/coverage/test/test_files/test_app.g.dart b/pkgs/coverage/test/test_files/test_app.g.dart new file mode 100644 index 0000000..c80718a --- /dev/null +++ b/pkgs/coverage/test/test_files/test_app.g.dart
@@ -0,0 +1,5 @@ +part of 'test_app.dart'; + +int usedGeneratedMethod(int a, int b) { + return a * b; +}
diff --git a/pkgs/coverage/test/test_files/test_app_isolate.dart b/pkgs/coverage/test/test_files/test_app_isolate.dart new file mode 100644 index 0000000..8bbc6be --- /dev/null +++ b/pkgs/coverage/test/test_files/test_app_isolate.dart
@@ -0,0 +1,73 @@ +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:io'; +import 'dart:isolate'; + +const int answer = 42; + +String fooSync(int x) { + if (x == answer) { + return '*' * x; + } + return List.generate(x, (_) => 'xyzzy').join(' '); +} + +class BarClass { + BarClass(this.x); + + int x; + + void baz() { + print(x); + } +} + +Future<String> fooAsync(int x) async { + if (x == answer) { + return '*' * x; + } + return List.generate(x, (_) => 'xyzzy').join(' '); +} + +/// The number of covered lines is tested and expected to be 4. +/// +/// If you modify this method, you may have to update the tests! +void isolateTask(List threeThings) async { + sleep(const Duration(milliseconds: 500)); + + fooSync(answer); + unawaited(fooAsync(answer).then((_) { + final port = threeThings.first as SendPort; + final sum = (threeThings[1] as int) + (threeThings[2] as int); + port.send(sum); + })); + + final bar = BarClass(123); + bar.baz(); + + print('678'); // coverage:ignore-line + + // coverage:ignore-start + print('1'); + print('2'); + print('3'); + // coverage:ignore-end + + print('4 // coverage:ignore-line'); + print('5 // coverage:ignore-file'); + + print('6'); // coverage:ignore-start + print('7'); + print('8'); + // coverage:ignore-end + print('9'); // coverage:ignore-start + print('10'); + print('11'); // coverage:ignore-line + + // Regression test for https://github.com/dart-lang/tools/issues/520. + await Isolate.run(() => print('Isolate.run'), debugName: 'Grandchild'); + // coverage:ignore-end +}
diff --git a/pkgs/coverage/test/test_files/test_library.dart b/pkgs/coverage/test/test_files/test_library.dart new file mode 100644 index 0000000..d2fe49f --- /dev/null +++ b/pkgs/coverage/test/test_files/test_library.dart
@@ -0,0 +1,9 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part 'test_library_part.dart'; + +int libraryFunction() { + return 123; +}
diff --git a/pkgs/coverage/test/test_files/test_library_part.dart b/pkgs/coverage/test/test_files/test_library_part.dart new file mode 100644 index 0000000..c99876d --- /dev/null +++ b/pkgs/coverage/test/test_files/test_library_part.dart
@@ -0,0 +1,9 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of 'test_library.dart'; + +int otherLibraryFunction() { + return 123; +}
diff --git a/pkgs/coverage/test/test_util.dart b/pkgs/coverage/test/test_util.dart new file mode 100644 index 0000000..e0a3edb --- /dev/null +++ b/pkgs/coverage/test/test_util.dart
@@ -0,0 +1,91 @@ +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:io'; + +import 'package:path/path.dart' as p; +import 'package:test/test.dart'; +import 'package:test_process/test_process.dart'; + +final String testAppPath = p.join('test', 'test_files', 'test_app.dart'); + +const Duration timeout = Duration(seconds: 20); + +Future<TestProcess> runTestApp(int openPort) => TestProcess.start( + Platform.resolvedExecutable, + [ + '--enable-vm-service=$openPort', + '--pause_isolates_on_exit', + '--branch-coverage', + testAppPath + ], + ); + +List<Map<String, dynamic>> coverageDataFromJson(Map<String, dynamic> json) { + expect(json.keys, unorderedEquals(<String>['type', 'coverage'])); + expect(json, containsPair('type', 'CodeCoverage')); + + return (json['coverage'] as List).cast<Map<String, dynamic>>(); +} + +final _versionPattern = RegExp('([0-9]+)\\.([0-9]+)\\.([0-9]+)'); + +bool platformVersionCheck(int minMajor, int minMinor) { + final match = _versionPattern.matchAsPrefix(Platform.version); + if (match == null) return false; + if (match.groupCount < 3) return false; + final major = int.parse(match.group(1)!); + final minor = int.parse(match.group(2)!); + return major > minMajor || (major == minMajor && minor >= minMinor); +} + +/// Returns a mapping of (URL: (function_name: hit_count)) from [sources]. +Map<String, Map<String, int>> functionInfoFromSources( + Map<String, List<Map<dynamic, dynamic>>> sources, +) { + Map<int, String> getFuncNames(List list) { + return { + for (var i = 0; i < list.length; i += 2) + list[i] as int: list[i + 1] as String, + }; + } + + Map<int, int> getFuncHits(List list) { + return { + for (var i = 0; i < list.length; i += 2) + list[i] as int: list[i + 1] as int, + }; + } + + return { + for (var entry in sources.entries) + entry.key: entry.value.fold( + {}, + (previousValue, element) { + expect(element['source'], entry.key); + final names = getFuncNames(element['funcNames'] as List); + final hits = getFuncHits(element['funcHits'] as List); + + for (var pair in hits.entries) { + previousValue[names[pair.key]!] = + (previousValue[names[pair.key]!] ?? 0) + pair.value; + } + + return previousValue; + }, + ), + }; +} + +extension ListTestExtension on List { + Map<String, List<Map<dynamic, dynamic>>> sources() => cast<Map>().fold( + <String, List<Map>>{}, + (Map<String, List<Map>> map, value) { + final sourceUri = value['source'] as String; + map.putIfAbsent(sourceUri, () => <Map>[]).add(value); + return map; + }, + ); +}
diff --git a/pkgs/coverage/test/test_with_coverage_package/lib/validate_lib.dart b/pkgs/coverage/test/test_with_coverage_package/lib/validate_lib.dart new file mode 100644 index 0000000..771c040 --- /dev/null +++ b/pkgs/coverage/test/test_with_coverage_package/lib/validate_lib.dart
@@ -0,0 +1,19 @@ +// 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. + +int sum(Iterable<int> values) { + var val = 0; + for (var value in values) { + val += value; + } + return val; +} + +int product(Iterable<int> values) { + var val = 1; + for (var value in values) { + val *= value; + } + return val; +}
diff --git a/pkgs/coverage/test/test_with_coverage_package/pubspec.yaml b/pkgs/coverage/test/test_with_coverage_package/pubspec.yaml new file mode 100644 index 0000000..3fa7ee0 --- /dev/null +++ b/pkgs/coverage/test/test_with_coverage_package/pubspec.yaml
@@ -0,0 +1,12 @@ +name: coverage_integration_test_for_test_with_coverage +publish_to: none + +environment: + sdk: '>=2.15.0 <3.0.0' + +dev_dependencies: + test: ^1.16.0 + +dependency_overrides: + coverage: + path: ../../
diff --git a/pkgs/coverage/test/test_with_coverage_package/test/product_test.dart b/pkgs/coverage/test/test_with_coverage_package/test/product_test.dart new file mode 100644 index 0000000..91eac53 --- /dev/null +++ b/pkgs/coverage/test/test_with_coverage_package/test/product_test.dart
@@ -0,0 +1,14 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:test/test.dart'; + +// ignore: avoid_relative_lib_imports +import '../lib/validate_lib.dart'; + +void main() { + test('product', () { + expect(product([2, 3]), 6); + }); +}
diff --git a/pkgs/coverage/test/test_with_coverage_package/test/sum_test.dart b/pkgs/coverage/test/test_with_coverage_package/test/sum_test.dart new file mode 100644 index 0000000..f5b1ea4 --- /dev/null +++ b/pkgs/coverage/test/test_with_coverage_package/test/sum_test.dart
@@ -0,0 +1,14 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:test/test.dart'; + +// ignore: avoid_relative_lib_imports +import '../lib/validate_lib.dart'; + +void main() { + test('sum', () { + expect(sum([1, 2]), 3); + }); +}
diff --git a/pkgs/coverage/test/test_with_coverage_test.dart b/pkgs/coverage/test/test_with_coverage_test.dart new file mode 100644 index 0000000..689452d --- /dev/null +++ b/pkgs/coverage/test/test_with_coverage_test.dart
@@ -0,0 +1,157 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +@Timeout(Duration(seconds: 60)) +library; + +import 'dart:convert'; +import 'dart:io'; + +import 'package:path/path.dart' as p; +import 'package:test/test.dart'; +import 'package:test_descriptor/test_descriptor.dart' as d; +import 'package:test_process/test_process.dart'; + +import 'test_util.dart'; + +// this package +final _pkgDir = p.absolute(''); +final _testWithCoveragePath = p.join(_pkgDir, 'bin', 'test_with_coverage.dart'); + +// test package +final _testPkgDirPath = p.join(_pkgDir, 'test', 'test_with_coverage_package'); + +/// Override PUB_CACHE +/// +/// Use a subdirectory different from `test/` just in case there is a problem +/// with the clean up. If other packages are present under the `test/` +/// subdirectory their tests may accidentally get run when running `dart test` +final _pubCachePathInTestPkgSubDir = p.join(_pkgDir, 'var', 'pub-cache'); +final _env = {'PUB_CACHE': _pubCachePathInTestPkgSubDir}; + +const _testPackageName = 'coverage_integration_test_for_test_with_coverage'; + +int _port = 9300; + +Iterable<File> _dartFiles(String dir) => + Directory(p.join(_testPkgDirPath, dir)).listSync().whereType<File>(); + +String _fixTestFile(String content) => content.replaceAll( + "import '../lib/", + "import 'package:$_testPackageName/", + ); + +void main() { + setUpAll(() async { + for (var dir in const ['lib', 'test']) { + await d.dir(dir, [ + for (var dartFile in _dartFiles(dir)) + d.file( + p.basename(dartFile.path), + _fixTestFile(dartFile.readAsStringSync()), + ), + ]).create(); + } + + var pubspecContent = + File(p.join(_testPkgDirPath, 'pubspec.yaml')).readAsStringSync(); + + expect( + pubspecContent.replaceAll('\r\n', '\n'), + contains(r''' +dependency_overrides: + coverage: + path: ../../ +'''), + ); + + pubspecContent = + pubspecContent.replaceFirst('path: ../../', 'path: $_pkgDir'); + + await d.file('pubspec.yaml', pubspecContent).create(); + + final localPub = await _run(['pub', 'get']); + await localPub.shouldExit(0); + }); + + test('dart run bin/test_with_coverage.dart -f', () async { + final list = await _runTest(['run', _testWithCoveragePath, '-f']); + + final sources = list.sources(); + final functionHits = functionInfoFromSources(sources); + + expect( + functionHits['package:$_testPackageName/validate_lib.dart'], + { + 'product': 1, + 'sum': 1, + }, + ); + }); + + test('dart run bin/test_with_coverage.dart -f -- -N sum', () async { + final list = await _runTest( + ['run', _testWithCoveragePath, '-f'], + extraArgs: ['--', '-N', 'sum'], + ); + + final sources = list.sources(); + final functionHits = functionInfoFromSources(sources); + + expect( + functionHits['package:$_testPackageName/validate_lib.dart'], + { + 'product': 0, + 'sum': 1, + }, + reason: 'only `sum` tests should be run', + ); + }); + + test('dart run coverage:test_with_coverage', () async { + await _runTest(['run', 'coverage:test_with_coverage']); + }); + + test('dart pub global run coverage:test_with_coverage', () async { + final globalPub = + await _run(['pub', 'global', 'activate', '-s', 'path', _pkgDir]); + await globalPub.shouldExit(0); + + await _runTest( + ['pub', 'global', 'run', 'coverage:test_with_coverage'], + ); + }); +} + +Future<TestProcess> _run(List<String> args) => TestProcess.start( + Platform.executable, + args, + workingDirectory: d.sandbox, + environment: _env, + ); + +Future<List<Map<String, dynamic>>> _runTest( + List<String> invokeArgs, { + List<String>? extraArgs, +}) async { + final process = await _run([ + ...invokeArgs, + '--port', + '${_port++}', + ...?extraArgs, + ]); + + await process.shouldExit(0); + + await d.dir( + 'coverage', + [d.file('coverage.json', isNotEmpty), d.file('lcov.info', isNotEmpty)], + ).validate(); + + final coverageDataFile = File(p.join(d.sandbox, 'coverage', 'coverage.json')); + + final json = jsonDecode(coverageDataFile.readAsStringSync()); + + return coverageDataFromJson(json as Map<String, dynamic>); +}
diff --git a/pkgs/coverage/test/util_test.dart b/pkgs/coverage/test/util_test.dart new file mode 100644 index 0000000..6a4e556 --- /dev/null +++ b/pkgs/coverage/test/util_test.dart
@@ -0,0 +1,358 @@ +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// ignore_for_file: only_throw_errors + +import 'dart:async'; + +import 'package:coverage/src/util.dart'; +import 'package:test/test.dart'; + +const _failCount = 5; +const _delay = Duration(milliseconds: 10); + +void main() { + test('retry', () async { + var count = 0; + final stopwatch = Stopwatch()..start(); + + Future failCountTimes() async { + expect(stopwatch.elapsed, greaterThanOrEqualTo(_delay * count)); + + while (count < _failCount) { + count++; + throw 'not yet!'; + } + return 42; + } + + final value = await retry(failCountTimes, _delay) as int; + + expect(value, 42); + expect(count, _failCount); + expect(stopwatch.elapsed, greaterThanOrEqualTo(_delay * count)); + }); + + group('retry with timeout', () { + test('if it finishes', () async { + var count = 0; + final stopwatch = Stopwatch()..start(); + + Future failCountTimes() async { + expect(stopwatch.elapsed, greaterThanOrEqualTo(_delay * count)); + + while (count < _failCount) { + count++; + throw 'not yet!'; + } + return 42; + } + + final safeTimoutDuration = _delay * _failCount * 10; + final value = await retry( + failCountTimes, + _delay, + timeout: safeTimoutDuration, + ) as int; + + expect(value, 42); + expect(count, _failCount); + expect(stopwatch.elapsed, greaterThanOrEqualTo(_delay * count)); + }); + + test('if it does not finish', () async { + var count = 0; + final stopwatch = Stopwatch()..start(); + + var caught = false; + var countAfterError = 0; + + Future failCountTimes() async { + if (caught) { + countAfterError++; + } + expect(stopwatch.elapsed, greaterThanOrEqualTo(_delay * count)); + + count++; + throw 'never'; + } + + final unsafeTimeoutDuration = _delay * (_failCount / 2); + + try { + await retry(failCountTimes, _delay, timeout: unsafeTimeoutDuration); + // ignore: avoid_catching_errors + } on StateError catch (e) { + expect(e.message, 'Failed to complete within 25ms'); + caught = true; + + expect(countAfterError, 0, + reason: 'Execution should stop after a timeout'); + + await Future<dynamic>.delayed(_delay * 3); + + expect(countAfterError, 0, reason: 'Even after a delay'); + } + + expect(caught, isTrue); + }); + }); + + group('extractVMServiceUri', () { + test('returns null when not found', () { + expect(extractVMServiceUri('foo bar baz'), isNull); + }); + + test('returns null for an incorrectly formatted URI', () { + const msg = 'Observatory listening on :://'; + expect(extractVMServiceUri(msg), null); + }); + + test('returns URI at end of string', () { + const msg = 'Observatory listening on http://foo.bar:9999/'; + expect(extractVMServiceUri(msg), Uri.parse('http://foo.bar:9999/')); + }); + + test('returns URI with auth token at end of string', () { + const msg = 'Observatory listening on http://foo.bar:9999/cG90YXRv/'; + expect( + extractVMServiceUri(msg), Uri.parse('http://foo.bar:9999/cG90YXRv/')); + }); + + test('return URI embedded within string', () { + const msg = '1985-10-26 Observatory listening on http://foo.bar:9999/ **'; + expect(extractVMServiceUri(msg), Uri.parse('http://foo.bar:9999/')); + }); + + test('return URI with auth token embedded within string', () { + const msg = + '1985-10-26 Observatory listening on http://foo.bar:9999/cG90YXRv/ **'; + expect( + extractVMServiceUri(msg), Uri.parse('http://foo.bar:9999/cG90YXRv/')); + }); + + test('handles new Dart VM service message format', () { + const msg = + 'The Dart VM service is listening on http://foo.bar:9999/cG90YXRv/'; + expect( + extractVMServiceUri(msg), Uri.parse('http://foo.bar:9999/cG90YXRv/')); + }); + }); + + group('getIgnoredLines', () { + const invalidSources = [ + '''final str = ''; // coverage:ignore-start + final str = ''; + final str = ''; // coverage:ignore-start + ''', + '''final str = ''; // coverage:ignore-start + final str = ''; + final str = ''; // coverage:ignore-start + final str = ''; // coverage:ignore-end + final str = ''; + final str = ''; // coverage:ignore-end + ''', + '''final str = ''; // coverage:ignore-start + final str = ''; + final str = ''; // coverage:ignore-end + final str = ''; + final str = ''; // coverage:ignore-end + ''', + '''final str = ''; // coverage:ignore-end + final str = ''; + final str = ''; // coverage:ignore-start + final str = ''; + final str = ''; // coverage:ignore-end + ''', + '''final str = ''; // coverage:ignore-end + final str = ''; + final str = ''; // coverage:ignore-end + ''', + '''final str = ''; // coverage:ignore-end + final str = ''; + final str = ''; // coverage:ignore-start + ''', + '''final str = ''; // coverage:ignore-end + ''', + '''final str = ''; // coverage:ignore-start + ''', + ]; + + test('throws FormatException when the annotations are not balanced', () { + void runTest(int index, String errMsg) { + final content = invalidSources[index].split('\n'); + expect( + () => getIgnoredLines('content-$index.dart', content), + throwsA( + allOf( + isFormatException, + predicate((FormatException e) => e.message == errMsg), + ), + ), + reason: 'expected FormatException with message "$errMsg"', + ); + } + + runTest( + 0, + 'coverage:ignore-start found at content-0.dart:' + '3 before previous coverage:ignore-start ended', + ); + runTest( + 1, + 'coverage:ignore-start found at content-1.dart:' + '3 before previous coverage:ignore-start ended', + ); + runTest( + 2, + 'unmatched coverage:ignore-end found at content-2.dart:5', + ); + runTest( + 3, + 'unmatched coverage:ignore-end found at content-3.dart:1', + ); + runTest( + 4, + 'unmatched coverage:ignore-end found at content-4.dart:1', + ); + runTest( + 5, + 'unmatched coverage:ignore-end found at content-5.dart:1', + ); + runTest( + 6, + 'unmatched coverage:ignore-end found at content-6.dart:1', + ); + runTest( + 7, + 'coverage:ignore-start found at content-7.dart:' + '1 has no matching coverage:ignore-end', + ); + }); + + test( + 'returns [[0,lines.length]] when the annotations are not ' + 'balanced but the whole file is ignored', () { + for (final content in invalidSources) { + final lines = content.split('\n'); + lines.add(' // coverage:ignore-file'); + expect(getIgnoredLines('', lines), [ + [0, lines.length] + ]); + } + }); + + test('returns [[0,lines.length]] when the whole file is ignored', () { + final lines = '''final str = ''; // coverage:ignore-start + final str = ''; // coverage:ignore-end + final str = ''; // coverage:ignore-file + ''' + .split('\n'); + + expect(getIgnoredLines('', lines), [ + [0, lines.length] + ]); + }); + + test('return the correct range of lines ignored', () { + final lines = ''' + final str = ''; // coverage:ignore-start + final str = ''; // coverage:ignore-line + final str = ''; // coverage:ignore-end + final str = ''; // coverage:ignore-start + final str = ''; // coverage:ignore-line + final str = ''; // coverage:ignore-end + ''' + .split('\n'); + + expect(getIgnoredLines('', lines), [ + [1, 3], + [4, 6], + ]); + }); + + test('return the correct list of lines ignored', () { + final lines = ''' + final str = ''; // coverage:ignore-line + final str = ''; // coverage:ignore-line + final str = ''; // coverage:ignore-line + ''' + .split('\n'); + + expect(getIgnoredLines('', lines), [ + [1, 1], + [2, 2], + [3, 3], + ]); + }); + + test('ignore comments have no effect inside string literals', () { + final lines = ''' + final str = '// coverage:ignore-file'; + final str = '// coverage:ignore-line'; + final str = ''; // coverage:ignore-line + final str = '// coverage:ignore-start'; + final str = '// coverage:ignore-end'; + ''' + .split('\n'); + + expect(getIgnoredLines('', lines), [ + [3, 3], + ]); + }); + + test('allow white-space after ignore comments', () { + // Using multiple strings, rather than splitting a multi-line string, + // because many code editors remove trailing white-space. + final lines = [ + "final str = ''; // coverage:ignore-start ", + "final str = ''; // coverage:ignore-line\t", + "final str = ''; // coverage:ignore-end \t \t ", + "final str = ''; // coverage:ignore-line \t ", + "final str = ''; // coverage:ignore-start \t ", + "final str = ''; // coverage:ignore-end \t \t ", + ]; + + expect(getIgnoredLines('', lines), [ + [1, 3], + [4, 4], + [5, 6], + ]); + }); + + test('allow omitting space after //', () { + final lines = [ + "final str = ''; //coverage:ignore-start", + "final str = ''; //coverage:ignore-line", + "final str = ''; //coverage:ignore-end", + "final str = ''; //coverage:ignore-line", + "final str = ''; //coverage:ignore-start", + "final str = ''; //coverage:ignore-end", + ]; + + expect(getIgnoredLines('', lines), [ + [1, 3], + [4, 4], + [5, 6], + ]); + }); + + test('allow text after ignore comments', () { + final lines = [ + "final str = ''; // coverage:ignore-start due to XYZ", + "final str = ''; // coverage:ignore-line", + "final str = ''; // coverage:ignore-end due to XYZ", + "final str = ''; // coverage:ignore-line due to 123", + "final str = ''; // coverage:ignore-start", + "final str = ''; // coverage:ignore-end it is done", + ]; + + expect(getIgnoredLines('', lines), [ + [1, 3], + [4, 4], + [5, 6], + ]); + }); + }); +}
diff --git a/pkgs/extension_discovery/.gitignore b/pkgs/extension_discovery/.gitignore new file mode 100644 index 0000000..ddfdca1 --- /dev/null +++ b/pkgs/extension_discovery/.gitignore
@@ -0,0 +1,5 @@ +.dart_tool/ +.packages +.pub/ +build/ +pubspec.lock
diff --git a/pkgs/extension_discovery/CHANGELOG.md b/pkgs/extension_discovery/CHANGELOG.md new file mode 100644 index 0000000..f35371e --- /dev/null +++ b/pkgs/extension_discovery/CHANGELOG.md
@@ -0,0 +1,24 @@ +## 2.1.0 + +- Require Dart 3.4. +- Update to the latest version of `package:dart_flutter_team_lints`. +- Add `findPackageConfig()` allowing for automatic discovery of the + packageConfig based on a package directory. + +## 2.0.0 + +- Use `extension/<package>/config.yaml` instead of + `extension/<package>/config.json` for better consistency with other tooling. +- Require that the top-level value in `extension/<package>/config.yaml` is + always a `Map`, and that the structure can be converted to a JSON equivalent + structure. + +## 1.0.1 + +- Support optional `packageUri`. +- Improve error messaging for `package_config.json` parsing. +- Update the package description. + +## 1.0.0 + +- Initial version.
diff --git a/pkgs/extension_discovery/LICENSE b/pkgs/extension_discovery/LICENSE new file mode 100644 index 0000000..ac90031 --- /dev/null +++ b/pkgs/extension_discovery/LICENSE
@@ -0,0 +1,27 @@ +Copyright 2023, the Dart project authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google LLC nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file
diff --git a/pkgs/extension_discovery/README.md b/pkgs/extension_discovery/README.md new file mode 100644 index 0000000..0214ae9 --- /dev/null +++ b/pkgs/extension_discovery/README.md
@@ -0,0 +1,237 @@ +[](https://github.com/dart-lang/tools/actions/workflows/extension_discovery.yml) +[](https://pub.dev/packages/extension_discovery) +[](https://pub.dev/packages/extension_discovery/publisher) + +A convention and utilities for package extension discovery. + +## What's this? + +A convention to allow other packages to provide extensions for your package +(or tool). Including logic for finding extensions that honor this convention. + +The convention implemented in this package is that if `foo` provides an +extension for `<targetPackage>`. +Then `foo` must contain a config file `extension/<targetPackage>/config.yaml`. +This file indicates that `foo` provides an extension for `<targetPackage>`. + +If `<targetPackage>` accepts extensions from other packages it must: + * Find extensions using `findExtensions('<targetPackage>')` from this package. + * Document how extensions are implemented: + * What should the contents of the `extension/<targetPackage>/config.yaml` file be? + * Should packages providing extensions have a dependency constraint on `<targetPackage>`? + * What libraries/assets should packages that provide extensions include? + * Should packages providing extensions specify a [topic in `pubspec.yaml`][1] + for easy discovery on pub.dev. + +The `findExtensions(targetPackage, packageConfig: ...)` function will: + * Load `.dart_tool/package_config.json` and find all packages that contain a + valid YAML file: `extension/<targetPackage>/config.yaml`. + * Provide the package name, location and contents of the `config.yaml` file, + for all detected extensions (aimed at `targetPackage`). + * Cache the results for fast loading, comparing modification timestamps to + ensure consistent results. + +It is the responsibility package that can be extended to validate extensions, +decide when they should be enabled, and documenting how such extensions are +created. + + +## Packages that extend tools + +You can also use this package (and associated convention), if you are developing +a tool that can be extended by packages. In this case, you would call +`findExtensions(<my_tool_package_name>, packageConfig: ...)` where +`packageConfig` points to the `.dart_tool/package_config.json` in the workspace +the tool is operating on. + +If you tool is not distributed through pub.dev, you might consider publishing +a placeholder package in order to reserve a unique name (and avoid collisions). +Using a placeholder package to reserve a unique is also recommended for tools +that wish to cache files in `.dart_tool/<my_tool_package_name>/`. +See [package layout documentation][2] for details. + + +## Example: Hello World + +Imagine that we have a `hello_world` package that defines a single method +`sayHello(String language)`, along the lines of: + +```dart +void sayHello(String language) { + if (language == 'danish') { + print('Hej verden'); + } else { + print('Hello world!'); + } +} +``` + +### Enabling packages to extend `hello_world` + +If we wanted to allow other packages to provide additional languages by +extending the `hello_world` package. Then we could do: + +```dart +import 'package:extension_discovery/extension_discovery.dart'; + +Future<void> sayHello(String language) async { + // Find extensions for the "hello_world" package. + // WARNING: This only works when running in JIT-mode, if running in AOT-mode + // you must supply the `packageConfig` argument, and have a local + // `.dart_tool/package_config.json` and `$PUB_CACHE`. + // See "Runtime limitations" section further down. + final extensions = await findExtensions('hello_world'); + + // Search extensions to see if one provides a message for language + for (final ext in extensions) { + final config = ext.config; + if (config is! Map<String, Object?>) { + continue; // ignore extensions with invalid configation + } + if (config['language'] == language) { + print(config['message']); + return; // Don't print more messages! + } + } + + if (language == 'danish') { + print('Hej verden'); + } else { + print('Hello world!'); + } +} +``` + +The `findExtensions` function will search other packages for +`extension/hello_world/config.yaml`, and provide the contents of this file as +well as provide the location of the extending packages. +As authors of the `hello_world` package we should also document how other +packages can extend `hello_world`. This is typically done by adding a segment +to the `README.md`. + + +### Extending `hello_world` from another package + +If in another package `hello_world_german` we wanted to extend `hello_world` +and provide a translation for German, then we would create a +`hello_world_german` package containing an +**`extension/hello_world/config.yaml`**: + +```yaml +language: german +message: "Hello Welt!" +``` + +Obviously, this is a contrived example. The authors of the `hello_world` package +could specify all sorts configuration options that extension authors can +specify in `extension/hello_world/config.yaml`. + +The authors of `hello_world` could also specify that extensions must provide +certain assets in `extension/hello_world/` or that they must provide certain +Dart libraries implementing a specified interface somewhere in `lib/src/...`. + +It is up to the authors of `hello_world` to specify what extension authors must +provide. The `extension_discovery` package only provides a utility for finding +extensions. + + +### Using `hello_world` and `hello_world_german` + +If writing `my_hello_world_app` I can now take advantage of `hello_world` and +`hello_world_german`. Simply write a `pubspec.yaml` as follows: + +```yaml +# pubspec.yaml +name: my_hello_world_app +dependencies: + hello_world: ^1.0.0 + hello_world_german: ^1.0.0 +environment: + sdk: ^3.4.0 +``` + +Then I can write a `bin/hello.dart` as follows: + +```dart +// bin/hello.dart +import 'package:hello_world/hello_world.dart'; + +Future<void> main() async { + await sayHello('german'); +} +``` + + +## What can an extension provide? + +As far as the `extension_discovery` package is concerned an extension can +provide anything. Naturally, it is the authors of the extendable package that +decides what extensions can be provide. + +In the example above it is the authors of the `hello_world` package that decides +what extension packages can provide. For this reason it is important that the +authors of `hello_world` very explicitly document how an extension is written. + +Obviously, authors of `hello_world` should document what should be specified in +`extension/hello_world/config.yaml`. They could also specify that other files +should be provided in `extension/hello_world/`, or that certain Dart libraries +should be provided in `lib/src/hello_world/...` or something like that. + +When authors of `hello_world` consumes the extensions discovered through +`findExtensions` they would naturally also be wise to validate that the +extension provides the required configuration and files. + + +## Compatibility considerations + +When writing an extension it is strongly encouraged to have a dependency +constraint on the package being extended. This ensures that the extending +package will be incompatibility with new major versions of the extended package. + +In the example above, it is strongly encouraged for `hello_world_german` to +have a dependency constraint `hello_world: ^1.0.0`. Even if `hello_world_german` +doesn't import libraries from `package:hello_world`. + +Because the next major version of `hello_world` (version `2.0.0`) might change +what is required of an extension. Thus, it's fair to assume that +`hello_world_german` might not be compatible with newer versions of +`hello_world`. Hence, adding a dependency constraint `hello_world: ^1.0.0` saves +users from resolving dependencies that aren't compatible. + +Naturally, after a new major version of `hello_world` is published a new +version of `hello_world_german` can then also be published, addressing any +breaking changes and bumping the dependency constraint. + +**Tip:** Authors of packages that can be extended might want to force extension +authors take dependency on their package, to ensure that they have the ability +to do breaking changes in the future. + + +## Runtime limitations + +The `findExtensions` function only works when running in JIT-mode, otherwise the +`packageConfig` parameter must be used to provide the location of +`.dart_tool/package_config.json`. Obviously, the `package_config.json` must be +present, as must the pub-cache locations referenced here. + +Hence, `findExtensions` effectively **only works from project workspace!**. + +You can't use `findExtensions` in a compiled Flutter application or an +AOT-compiled executable distributed to end-users. Because in these environments +you don't have a `package_config.json` nor do you have a pub-cache. You don't +even have access to your own source files. + +If your deployment target a compiled Flutter application or AOT-compiled +executable, then you will have to create some code/asset-generation. +You code/asset-generation scripts can use `findExtensions` to find extensions, +and then use the assets or Dart libraries from here to generate assets or code +that is embedded in the final Flutter application (or AOT-compiled executable). + +This makes `findExtensions` immediately useful, if you are writing development +tools that users will install into their project workspace. But if you're +writing a package for use in deployed applications, you'll likely need to figure +out how to embed the extensions, `findExtensions` only helps +you find the extensions during code-gen. + +[1]: https://dart.dev/tools/pub/pubspec#topics +[2]: https://dart.dev/tools/pub/package-layout#project-specific-caching-for-tools
diff --git a/pkgs/extension_discovery/analysis_options.yaml b/pkgs/extension_discovery/analysis_options.yaml new file mode 100644 index 0000000..aadd26e --- /dev/null +++ b/pkgs/extension_discovery/analysis_options.yaml
@@ -0,0 +1,5 @@ +include: package:dart_flutter_team_lints/analysis_options.yaml + +linter: + rules: + - avoid_catches_without_on_clauses
diff --git a/pkgs/extension_discovery/example/hello_world/README.md b/pkgs/extension_discovery/example/hello_world/README.md new file mode 100644 index 0000000..39ec96d --- /dev/null +++ b/pkgs/extension_discovery/example/hello_world/README.md
@@ -0,0 +1,26 @@ +# `hello_world` package + +Example of a package that can be extended, and uses `extension_discovery` to +find extensions. + +## Limitations + +The `sayHello` function in this package can only be used in a project workspace, +where dependencies are resolved and you're running in JIT-mode. + +The `sayHello` function uses `findExtensions` and, thus, cannot be called in a +compiled Flutter application or AOT-compiled executable. For this to work, we'd +need to augment this package with code-generation, such that the code-generation +uses `findExtensions` and compiles a `sayHello` function into your application. + +## Extending the `hello_world` package + +Other packages can extend this package by providing an `extension/hello_world/config.json` file the following form: + +```js +// extension/hello_world/config.json +{ + "language": "<language>", + "message": "<message>" +} +```
diff --git a/pkgs/extension_discovery/example/hello_world/lib/hello_world.dart b/pkgs/extension_discovery/example/hello_world/lib/hello_world.dart new file mode 100644 index 0000000..9e4a848 --- /dev/null +++ b/pkgs/extension_discovery/example/hello_world/lib/hello_world.dart
@@ -0,0 +1,28 @@ +// 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:extension_discovery/extension_discovery.dart'; + +Future<void> sayHello(String language) async { + // Find extensions for the "hello_world" package. + // WARNING: This only works when running in JIT-mode, if running in AOT-mode + // you must supply the `packageConfig` argument, and have a local + // `.dart_tool/package_config.json` and `$PUB_CACHE`. + final extensions = await findExtensions('hello_world'); + + // Search extensions to see if one provides a message for language + for (final ext in extensions) { + final config = ext.config; + if (config['language'] == language) { + print(config['message']); + return; // Don't print more messages! + } + } + + if (language == 'danish') { + print('Hej verden'); + } else { + print('Hello world!'); + } +}
diff --git a/pkgs/extension_discovery/example/hello_world/pubspec.yaml b/pkgs/extension_discovery/example/hello_world/pubspec.yaml new file mode 100644 index 0000000..40c68a3 --- /dev/null +++ b/pkgs/extension_discovery/example/hello_world/pubspec.yaml
@@ -0,0 +1,10 @@ +name: hello_world +version: 1.0.0 +publish_to: none # This is an example, don't publish! + +dependencies: + extension_discovery: # ^1.0.0 + path: ../../ + +environment: + sdk: ^3.4.0
diff --git a/pkgs/extension_discovery/example/hello_world_app/README.md b/pkgs/extension_discovery/example/hello_world_app/README.md new file mode 100644 index 0000000..1d45229 --- /dev/null +++ b/pkgs/extension_discovery/example/hello_world_app/README.md
@@ -0,0 +1,8 @@ +# `hello_world_app` + +An application that uses the `hello_world` package and has a dependency on +`hello_world_german` such that when `hello_world` calls `findExtensions` it will +find the extension in `hello_world_german`. + +**Notice**: This application only works when running from a project workspace. +See "runtime limitation" in the README for `package:extension_discovery`.
diff --git a/pkgs/extension_discovery/example/hello_world_app/bin/hello.dart b/pkgs/extension_discovery/example/hello_world_app/bin/hello.dart new file mode 100644 index 0000000..a4715ef --- /dev/null +++ b/pkgs/extension_discovery/example/hello_world_app/bin/hello.dart
@@ -0,0 +1,9 @@ +// 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:hello_world/hello_world.dart'; + +Future<void> main() async { + await sayHello('german'); +}
diff --git a/pkgs/extension_discovery/example/hello_world_app/pubspec.yaml b/pkgs/extension_discovery/example/hello_world_app/pubspec.yaml new file mode 100644 index 0000000..30338d2 --- /dev/null +++ b/pkgs/extension_discovery/example/hello_world_app/pubspec.yaml
@@ -0,0 +1,11 @@ +name: my_hello_world_app +publish_to: none # applications should never be published! + +dependencies: + hello_world: # ^1.0.0 + path: ../hello_world + hello_world_german: # ^1.0.0 + path: ../hello_world_german + +environment: + sdk: ^3.4.0
diff --git a/pkgs/extension_discovery/example/hello_world_german/README.md b/pkgs/extension_discovery/example/hello_world_german/README.md new file mode 100644 index 0000000..4a58703 --- /dev/null +++ b/pkgs/extension_discovery/example/hello_world_german/README.md
@@ -0,0 +1,4 @@ +# `hello_world_german` + +Example of a simple package that provides an extension for the `hello_world` +package.
diff --git a/pkgs/extension_discovery/example/hello_world_german/extension/hello_world/config.yaml b/pkgs/extension_discovery/example/hello_world_german/extension/hello_world/config.yaml new file mode 100644 index 0000000..ef57087 --- /dev/null +++ b/pkgs/extension_discovery/example/hello_world_german/extension/hello_world/config.yaml
@@ -0,0 +1,9 @@ +# This config file let's `package:extension_discovery` find out that +# `package:hello_world_german` has an extension for `package:hello_world`. +# +# The root object must be a map, and the data structure must be representable +# as JSON, but those are the only constraints. Beyond that it is the +# responsibility of `package:hello_world` to define what this file should +# contain, to validate the contents, and do something useful with it. +language: german +message: "Hello Welt!"
diff --git a/pkgs/extension_discovery/example/hello_world_german/pubspec.yaml b/pkgs/extension_discovery/example/hello_world_german/pubspec.yaml new file mode 100644 index 0000000..39e80be --- /dev/null +++ b/pkgs/extension_discovery/example/hello_world_german/pubspec.yaml
@@ -0,0 +1,15 @@ +name: hello_world_german +version: 1.0.0 +publish_to: none # This is an example, don't publish! + +dependencies: + # We keep a dependency on package `hello_world` because this package provides + # an extension for this package. Hence, a newer major version of hello_world + # might be incompatible with the extension options we've provided in + # extension/hello_world/config.json + # It is `hello_world` that specifies what is required in `config.json`. + hello_world: # ^1.0.0 + path: ../hello_world + +environment: + sdk: ^3.4.0
diff --git a/pkgs/extension_discovery/lib/extension_discovery.dart b/pkgs/extension_discovery/lib/extension_discovery.dart new file mode 100644 index 0000000..662435a --- /dev/null +++ b/pkgs/extension_discovery/lib/extension_discovery.dart
@@ -0,0 +1,285 @@ +// 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. + +/// Find extensions with [findExtensions]. +library; + +import 'dart:collection' show UnmodifiableListView; +import 'dart:io' show File, IOException; +import 'dart:isolate' show Isolate; + +import 'src/io.dart'; +import 'src/package_config.dart'; +import 'src/registry.dart'; +import 'src/yaml_config_format.dart'; + +export 'src/package_config.dart' show PackageConfigException, findPackageConfig; + +/// Information about an extension for target package. +final class Extension { + /// Name of the package providing an extension. + final String package; + + /// Absolute path to the package root. + /// + /// This folder usually contains a `lib/` folder and a `pubspec.yaml` + /// (assuming dependencies are fetched using the pub package manager). + /// + /// **Examples:** If `foo` is installed in pub-cache this would be: + /// * `/home/my_user/.pub-cache/hosted/pub.dev/foo-1.0.0/` + /// + /// See `rootUri` in the [specification for `package_config.json`][1], + /// for details. + /// + /// [1]: https://github.com/dart-lang/language/blob/main/accepted/2.8/language-versioning/package-config-file-v2.md + final Uri rootUri; + + /// Path to the library import path relative to [rootUri]. + /// + /// In Dart code the `package:<package>/<path>` will be resolved as + /// `<rootUri>/<packageUri>/<path>`. + /// + /// If dependencies are installed using `dart pub`, then this is + /// **always** `lib/`. + /// + /// See `packageUri` in the [specification for `package_config.json`][1], + /// for details. + /// + /// [1]: https://github.com/dart-lang/language/blob/main/accepted/2.8/language-versioning/package-config-file-v2.md + final Uri packageUri; + + /// Contents of `extension/<targetPackage>/config.yaml` parsed as YAML and + /// converted to JSON compatible types. + /// + /// If parsing YAML from this file failed, then no [Extension] entry + /// will exist. + /// + /// This field is always a structure consisting of the following types: + /// * `null`, + /// * [bool] (`true` or `false`), + /// * [String], + /// * [num] ([int] or [double]), + /// * `List<Object?>`, and, + /// * `Map<String, Object?>`. + final Map<String, Object?> config; + + Extension._({ + required this.package, + required this.rootUri, + required this.packageUri, + required this.config, + }); +} + +/// Find extensions for [targetPackage] provided by packages in +/// `.dart_tool/package_config.json`. +/// +/// ## Locating `.dart_tool/package_config.json` +/// +/// This method requires the location of the [packageConfig], unless the current +/// isolate has been setup for package resolution. +/// Notably, Dart programs compiled for AOT cannot find their own +/// `package_config.json`. +/// +/// If operating on a project that isn't the current project, for example, if +/// you are developing a tool that users are globally activating and then +/// running against their own projects, and you wish to detect extensions within +/// their projects, then you must specify the path the +/// `.dart_tool/package_config.json` for the users project as [packageConfig]. +/// +/// The [packageConfig] parameter must reference a file, absolute or +/// relative-path, may use the `file://` scheme. This method throws, if +/// [packageConfig] is not a valid [Uri] for a file-path. +/// +/// ## Detection of extensions +/// +/// An extension for [targetPackage] is detected in `package:foo` if `foo` +/// contains `extension/<targetPackage>/config.yaml`, and the contents of this +/// file is valid YAML, that can be represented as JSON. +/// +/// ### Caching results +/// +/// When [useCache] is `true` then the detected extensions will be cached +/// in `.dart_tool/extension_discovery/<targetPackage>.json`. +/// This function will compare modification timestamps of +/// `.dart_tool/package_config.json` with the cache file, before reusing cached +/// results. +/// This function will also treat relative path-dependencies as mutable +/// packages, and check such packages for extensions every time [findExtensions] +/// is called. Notably, it'll compare the modification time of the +/// `extension/<targetPackage>/config.yaml` file, to ensure that it's older than +/// the extension cache file. Otherwise, it'll reload the extension +/// configuration. +/// +/// ## Exceptions +/// +/// This method will throw [PackageConfigException], if the +/// `.dart_tool/package_config.json` file specified in [packageConfig] could not +/// be loaded or is invalid. This usually happens if dependencies are not +/// resolved, and users can probably address it by running `dart pub get`. +/// +/// But, **do consider catch** [PackageConfigException] and handling the failure +/// to load extensions appropriately. +/// +/// This method will throw an [Error] if [packageConfig] is not specified, and +/// the current isolate isn't configured for package resolution. +Future<List<Extension>> findExtensions( + String targetPackage, { + bool useCache = true, + Uri? packageConfig, +}) async { + packageConfig ??= await Isolate.packageConfig; + if (packageConfig == null) { + throw UnsupportedError( + 'packageConfigUri must be provided, if not running in JIT mode', + ); + } + if ((packageConfig.hasScheme && !packageConfig.isScheme('file')) || + packageConfig.hasEmptyPath || + packageConfig.hasFragment || + packageConfig.hasPort || + packageConfig.hasQuery) { + throw ArgumentError.value( + packageConfig, + 'packageConfig', + 'must be a file:// URI', + ); + } + // Always normalize to an absolute URI + final packageConfigUri = File.fromUri(packageConfig).absolute.uri; + + return await _findExtensions( + targetPackage: targetPackage, + useCache: useCache, + packageConfigUri: packageConfigUri, + ); +} + +/// Find extensions with normalized arguments. +Future<List<Extension>> _findExtensions({ + required String targetPackage, + required bool useCache, + required Uri packageConfigUri, +}) async { + final packageConfigFile = File.fromUri(packageConfigUri); + final registryFile = File.fromUri(packageConfigFile.parent.uri.resolve( + 'extension_discovery/$targetPackage.json', + )); + + Registry? registry; + final registryStat = registryFile.statSync(); + if (registryStat.isFileOrLink && useCache) { + final packageConfigStat = packageConfigFile.statSync(); + if (!packageConfigStat.isFileOrLink) { + throw packageConfigNotFound(packageConfigUri); + } + if (packageConfigStat.isPossiblyModifiedAfter(registryStat.modified)) { + await registryFile.tryDelete(); + } else { + registry = await loadRegistry(registryFile); + } + } + + final configFileName = 'extension/$targetPackage/config.yaml'; + var registryUpdated = false; + if (registry != null) { + // Update mutable entries in registry + for (var i = 0; i < registry.length; i++) { + final p = registry[i]; + if (p.rootUri.hasAbsolutePath) continue; + + final rootUri = packageConfigUri.resolveUri(p.rootUri); + final configFile = File.fromUri(rootUri.resolve(configFileName)); + final configStat = configFile.statSync(); + if (configStat.isFileOrLink) { + if (configStat.isPossiblyModifiedAfter(registryStat.modified)) { + try { + registryUpdated = true; + registry[i] = ( + package: p.package, + rootUri: p.rootUri, + packageUri: p.packageUri, + config: parseYamlFromConfigFile(await configFile.readAsString()), + ); + continue; + } on FormatException { + // pass + } on IOException { + // pass + } + registryUpdated = true; + registry[i] = ( + package: p.package, + rootUri: p.rootUri, + packageUri: p.packageUri, + config: null, + ); + } + } else { + // If there is no file present, but registry says there is then we need + // to update the registry. + if (p.config != null) { + registryUpdated = true; + registry[i] = ( + package: p.package, + rootUri: p.rootUri, + packageUri: p.packageUri, + config: null, + ); + } + } + } + } else { + // Load packages from package_config.json + final packages = await loadPackageConfig(packageConfigFile); + registryUpdated = true; + registry = (await Future.wait(packages.map((p) async { + try { + final rootUri = packageConfigUri.resolveUri(p.rootUri); + final configFile = File.fromUri(rootUri.resolve(configFileName)); + final configStat = configFile.statSync(); + if (configStat.isFileOrLink) { + return ( + package: p.name, + rootUri: p.rootUri, + packageUri: p.packageUri, + config: parseYamlFromConfigFile(await configFile.readAsString()), + ); + } + } on FormatException { + // pass + } on IOException { + // pass + } + if (!p.rootUri.hasAbsolutePath) { + return ( + package: p.name, + rootUri: p.rootUri, + packageUri: p.packageUri, + config: null, + ); + } + return null; + }))) + .whereType<RegistryEntry>() + .toList(growable: false); + } + + // Save registry + if (registryUpdated && useCache) { + await saveRegistry(registryFile, registry); + } + + return UnmodifiableListView( + registry + .where((e) => e.config != null) + .map((e) => Extension._( + package: e.package, + rootUri: packageConfigUri.resolveUri(e.rootUri), + packageUri: e.packageUri, + config: e.config!, + )) + .toList(growable: false), + ); +}
diff --git a/pkgs/extension_discovery/lib/src/expect_json.dart b/pkgs/extension_discovery/lib/src/expect_json.dart new file mode 100644 index 0000000..c2784bc --- /dev/null +++ b/pkgs/extension_discovery/lib/src/expect_json.dart
@@ -0,0 +1,73 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert' show jsonDecode; + +Map<String, Object?> decodeJsonMap(String json) { + final root = jsonDecode(json); + if (root case Map<String, Object?> v) return v; + throw const FormatException('root must be a map'); +} + +extension ExpectJson on Map<String, Object?> { + bool expectBool(String key) { + if (this[key] case bool v) return v; + throw FormatException('The value at "$key" must be a bool:\n$toString()'); + } + + num expectNumber(String key) { + if (this[key] case num v) return v; + throw FormatException('The value at "$key" must be a number:\n$toString()'); + } + + String expectString(String key) { + if (this[key] case String v) return v; + throw FormatException('The value at "$key" must be a string:\n$toString()'); + } + + Uri expectUri(String key) { + try { + return Uri.parse(expectString(key)); + } on FormatException { + throw FormatException('The value at "$key" must be a URI:\n$toString()'); + } + } + + Map<String, Object?> expectMap(String key) { + if (this[key] case Map<String, Object?> v) return v; + throw FormatException('The value at "$key" must be a map:\n$toString()'); + } + + Map<String, Object?>? optionalMap(String key) { + if (containsKey(key)) { + return expectMap(key); + } + return null; + } + + Uri? optionalUri(String key) { + if (containsKey(key)) { + return expectUri(key); + } + return null; + } + + List<Object?> expectList(String key) { + if (this[key] case List<Object?> v) return v; + throw FormatException('The value at "$key" must be a list:\n$toString()'); + } + + Iterable<Map<String, Object?>> expectListObjects(String key) sync* { + final list = expectList(key); + for (final entry in list) { + if (entry case Map<String, Object?> v) { + yield v; + } else { + throw FormatException( + 'The value at "$key" must be a list of map:\n$toString()', + ); + } + } + } +}
diff --git a/pkgs/extension_discovery/lib/src/io.dart b/pkgs/extension_discovery/lib/src/io.dart new file mode 100644 index 0000000..9343ced --- /dev/null +++ b/pkgs/extension_discovery/lib/src/io.dart
@@ -0,0 +1,84 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:io' + show + File, + FileStat, + FileSystemEntityType, + FileSystemException, + IOException, + Platform; + +const _maxAttempts = 20; + +/// When comparing modification timestamps of files to see if A is newer than B, +/// such that data cached in A about B does not need to be recomputed, we +/// required that A is at-least [modificationMaturityDelay] older than B. +/// +/// This ensures that if `pub get` is racing with cache writing then we won't +/// rely on the result. +Duration modificationMaturityDelay = const Duration(seconds: 5); + +/// On windows some renaming files/folders recently created can be problematic +/// as they may be locked by security scanning systems. +/// +/// This function will retry [fn] a few times with a short delay, if running on +/// Windows and the error appears to be related to permissions or file locking. +Future<T> _attempt<T>(FutureOr<T> Function() fn) async { + if (!Platform.isWindows) { + return await fn(); + } + var attempts = 0; + while (true) { + try { + await fn(); + } on FileSystemException catch (e) { + attempts += 1; + if (attempts >= _maxAttempts) rethrow; + + // Cargo culting error codes from: + // https://github.com/dart-lang/pub/blob/98565c3e5defcd80c59910795ba3548552102f2c/lib/src/io.dart#L419-L427 + final code = e.osError?.errorCode; + if (code != 5 && code != 32) rethrow; + + // Sleep a bit a try again. + await Future<void>.delayed(const Duration(milliseconds: 5)); + } + } +} + +extension FileExt on File { + /// Try to delete this file, ignore errors. + Future<void> tryDelete() async { + try { + await delete(); + } on IOException { + // pass + } + } + + Future<void> reliablyRename(String newPath) => + _attempt(() => rename(newPath)); +} + +extension FileStatExt on FileStat { + /// Returns `false` if we're pretty certain that the current file was NOT + /// modified after [other]. + /// + /// We do this by subtracting 5 seconds from [other], thus, making it more + /// likely that the current file was _possibly modified_ after [other]. + /// + /// This, aims to ensure that file where modified within 5 seconds of + /// eachother then we don't trust the file modification stamps. This mostly + /// makes sense if someone is updating a file while we're writing the registry + /// cache file. + bool isPossiblyModifiedAfter(DateTime other) => + modified.isAfter(other.subtract(modificationMaturityDelay)); + + /// True, if current [FileStat] is possibly a file (link or file) + bool get isFileOrLink => + type == FileSystemEntityType.file || type == FileSystemEntityType.link; +}
diff --git a/pkgs/extension_discovery/lib/src/package_config.dart b/pkgs/extension_discovery/lib/src/package_config.dart new file mode 100644 index 0000000..f2eaffc --- /dev/null +++ b/pkgs/extension_discovery/lib/src/package_config.dart
@@ -0,0 +1,107 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:io' show File, IOException; +import 'expect_json.dart'; + +typedef PackageConfigEntry = ({String name, Uri rootUri, Uri packageUri}); +typedef PackageConfig = List<PackageConfigEntry>; + +/// Searches in [packageDir] and all directories above for a +/// `.dart_tool/package_config.json` file. Returns the Uri of that file if +/// found. +/// +/// Returns `null` if no file was found. +Uri? findPackageConfig(Uri packageDir) { + if (!packageDir.isScheme('file')) { + throw ArgumentError( + 'Expected [packageDir] to be a file URI, got $packageDir', + ); + } + if (!packageDir.path.endsWith('/')) { + packageDir = packageDir.replace(path: '${packageDir.path}/'); + } + while (true) { + final packageConfigCandidate = + packageDir.resolve('.dart_tool/package_config.json'); + try { + if (File.fromUri(packageConfigCandidate).existsSync()) { + return packageConfigCandidate; + } + } on IOException { + return null; // if we get a permission error, etc, we return null + } + final next = packageDir.resolve('..'); + if (next == packageDir) return null; + packageDir = next; + } +} + +/// Load list of packages and associated URIs from the +/// `.dart_tool/package_config.json` file in [packageConfigFile]. +Future<PackageConfig> loadPackageConfig( + File packageConfigFile, +) async { + try { + final packageConfig = decodeJsonMap(await packageConfigFile.readAsString()); + if (packageConfig.expectNumber('configVersion') != 2) { + throw const FormatException('"configVersion" must be 2'); + } + return packageConfig.expectListObjects('packages').map((p) { + final rootUri = p.expectUri('rootUri').asDirectory(); + return ( + name: p.expectString('name'), + rootUri: rootUri, + packageUri: p.optionalUri('packageUri')?.asDirectory() ?? rootUri, + ); + }).toList(); + } on IOException catch (e) { + if (!packageConfigFile.existsSync()) { + throw packageConfigNotFound(packageConfigFile.uri); + } + throw packageConfigIOException(e); + } on FormatException catch (e) { + throw packageConfigInvalid(packageConfigFile.uri, e); + } +} + +/// Thrown, if the `.dart_tool/package_config.json` cannot be found or parsing +/// it fails. +/// +/// This could be because the `package_config.json` file is missing or simply +/// invalid. +/// +/// Mostly, this will happen if dependencies are not resolved, the solution is +/// call `dart pub get`. +final class PackageConfigException implements Exception { + final String message; + PackageConfigException._(this.message); + + @override + String toString() => message; +} + +PackageConfigException packageConfigNotFound(Uri packageConfigUri) => + PackageConfigException._( + 'package_config.json not found at: "$packageConfigUri"', + ); + +PackageConfigException packageConfigInvalid( + Uri packageConfigUri, FormatException e) => + PackageConfigException._( + 'Invalid package_config.json found at "$packageConfigUri": $e', + ); + +PackageConfigException packageConfigIOException(IOException e) => + PackageConfigException._( + 'Failed to read package_config.json: $e', + ); + +extension on Uri { + Uri asDirectory() => replace( + pathSegments: pathSegments.lastOrNull != '' + ? pathSegments.followedBy(['']) + : pathSegments, + ); +}
diff --git a/pkgs/extension_discovery/lib/src/registry.dart b/pkgs/extension_discovery/lib/src/registry.dart new file mode 100644 index 0000000..60efc75 --- /dev/null +++ b/pkgs/extension_discovery/lib/src/registry.dart
@@ -0,0 +1,144 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert' show jsonEncode; +import 'dart:io' show File, FileSystemEntityType, IOException; + +import 'expect_json.dart'; +import 'io.dart'; + +// TODO: Convert the 'rootUri' reference below to a doc comment reference once +// https://github.com/dart-lang/linter/issues/4645 is addressed. + +/// Entry in the `.dart_tool/extension_discovery/<package>.json` file. +/// +/// If the `rootUri` is not an absolute path, then we will assume that the +/// package is mutable (either it's the root package or a path dependency). +/// If there is no extension config file for a mutable package, then we will +/// still store a [RegistryEntry] with `config = null`. Because everytime we +/// load the registry, we still need to check if a configuration file has been +/// added to the mutable package. +typedef RegistryEntry = ({ + String package, + Uri rootUri, + Uri packageUri, + Map<String, Object?>? config, +}); + +typedef Registry = List<RegistryEntry>; + +Future<Registry?> loadRegistry(File registryFile) async { + try { + final registryJson = decodeJsonMap(await registryFile.readAsString()); + if (registryJson.expectNumber('version') != 2) { + throw const FormatException('"version" must be 2'); + } + return registryJson + .expectListObjects('entries') + .map((e) => ( + package: e.expectString('package'), + rootUri: e.expectUri('rootUri'), + packageUri: e.expectUri('packageUri'), + config: e.optionalMap('config'), + )) + .toList(growable: false); + } on IOException { + return null; // pass + } on FormatException { + await registryFile.tryDelete(); + return null; + } +} + +Future<void> saveRegistry( + File registryFile, + Registry registry, +) async { + try { + if (!registryFile.parent.existsSync()) { + await registryFile.parent.create(); + } + final tmpFile = File('${registryFile.path}.tmp'); + final tmpFileStat = tmpFile.statSync(); + if (tmpFileStat.type != FileSystemEntityType.notFound) { + final tmpAge = DateTime.now().difference(tmpFileStat.modified); + if (tmpAge.inSeconds < 5) { + // Don't try to write registry, if there is an abandoned temporary file + // no older than 5 seconds. Otherwise, we could have race conditions! + // Note: That saving the registry is a performance improvement, not a + // strict necessity! + return; + } else { + await tmpFile.delete(); + } + } + + await tmpFile.writeAsString(jsonEncode({ + 'version': 2, + 'entries': registry + .map((e) => { + 'package': e.package, + 'rootUri': e.rootUri.toString(), + 'packageUri': e.packageUri.toString(), + if (e.config != null) 'config': e.config, + }) + .toList(), + })); + await tmpFile.reliablyRename(registryFile.path); + await _ensureReadme( + File.fromUri(registryFile.parent.uri.resolve('README.md')), + ); + } on IOException { + // pass + } +} + +Future<void> _ensureReadme(File readmeFile) async { + try { + final stat = readmeFile.statSync(); + if (stat.type != FileSystemEntityType.notFound) { + final age = DateTime.now().difference(stat.modified); + if (age.inDays < 5) { + return; // don't update README.md, if it's less than 5 days old + } + } + await readmeFile.writeAsString(_readmeContents); + } on IOException { + // pass + } +} + +const _readmeContents = ''' +Extension Discovery Cache +========================= + +This folder is used by `package:extension_discovery` to cache lists of +packages that contains extensions for other packages. + +DO NOT USE THIS FOLDER +---------------------- + + * Do not read (or rely) the contents of this folder. + * Do write to this folder. + +If you're interested in the lists of extensions stored in this folder use the +API offered by package `extension_discovery` to get this information. + +If this package doesn't work for your use-case, then don't try to read the +contents of this folder. It may change, and will not remain stable. + +Use package `extension_discovery` +--------------------------------- + +If you want to access information from this folder. + +Feel free to delete this folder +------------------------------- + +Files in this folder act as a cache, and the cache is discarded if the files +are older than the modification time of `.dart_tool/package_config.json`. + +Hence, it should never be necessary to clear this cache manually, if you find a +need to do please file a bug. +''';
diff --git a/pkgs/extension_discovery/lib/src/yaml_config_format.dart b/pkgs/extension_discovery/lib/src/yaml_config_format.dart new file mode 100644 index 0000000..a28b31b --- /dev/null +++ b/pkgs/extension_discovery/lib/src/yaml_config_format.dart
@@ -0,0 +1,85 @@ +// 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. + +/// Utilities for loading and validating YAML from a config file. +/// +/// When writing YAML config files it's often preferable to force a few +/// constraints on the YAML files. Specifically: +/// * Root value must be a map. +/// * No anchors / aliases, this can't be represented in JSON and +/// can be used to created cycles, which might crash someone trying to +/// serialize the data as JSON. +/// * Maps can only have string keys. +/// +/// Basically, only allow value that can't be represented in JSON. +/// +/// This library aims to provide a [parseYamlFromConfigFile] that throws +/// a [FormatException] when parsing YAML files that doesn't satisfy this +/// constraint. +library; + +import 'package:yaml/yaml.dart' + show YamlList, YamlMap, YamlNode, YamlScalar, loadYamlNode; + +/// Parse YAML from a config file. +/// +/// This will validate that: +/// * Maps only have string keys. +/// * Anchor and aliases are not used (to avoid cycles). +/// * Values can be represented as JSON. +/// * Root node is a map. +/// +/// Throw will throw [FormatException], if the [yamlString] does not satisfy +/// constraints above. +/// +/// Returns a structure consisting of the following types: +/// * `null`, +/// * [bool] (`true` or `false`), +/// * [String], +/// * [num] ([int] or [double]), +/// * `List<Object?>`, and, +/// * `Map<String, Object?>`. +Map<String, Object?> parseYamlFromConfigFile(String yamlString) { + final visited = <YamlNode>{}; + Object? toPlainType(YamlNode n) { + if (!visited.add(n)) { + throw const FormatException( + 'Anchors/aliases are not supported in YAML config files', + ); + } + if (n is YamlScalar) { + return switch (n.value) { + null => null, + String s => s, + num n => n, + bool b => b, + _ => throw const FormatException( + 'Only null, string, number, bool, map and lists are supported ' + 'in YAML config files', + ), + }; + } + if (n is YamlList) { + return n.nodes.map(toPlainType).toList(); + } + if (n is YamlMap) { + return n.nodes.map((key, value) { + final k = toPlainType(key as YamlNode); + if (k is! String) { + throw const FormatException( + 'Only string keys are allowed in YAML config files', + ); + } + return MapEntry(k, toPlainType(value)); + }); + } + throw UnsupportedError('Unknown YamlNode: $n'); + } + + final value = toPlainType(loadYamlNode(yamlString)); + if (value is! Map<String, Object?>) { + throw const FormatException('The root of a YAML config file must be a map'); + } + return value; +}
diff --git a/pkgs/extension_discovery/pubspec.yaml b/pkgs/extension_discovery/pubspec.yaml new file mode 100644 index 0000000..05acdbd --- /dev/null +++ b/pkgs/extension_discovery/pubspec.yaml
@@ -0,0 +1,17 @@ +name: extension_discovery +description: >- + A convention and utilities for package extension discovery. +version: 2.1.0 +repository: https://github.com/dart-lang/tools/tree/main/pkgs/extension_discovery + +environment: + sdk: ^3.4.0 + +dependencies: + yaml: ^3.0.0 + +dev_dependencies: + collection: ^1.18.0 + dart_flutter_team_lints: ^3.0.0 + test: ^1.21.0 + test_descriptor: ^2.0.1
diff --git a/pkgs/extension_discovery/test/find_extensions_test.dart b/pkgs/extension_discovery/test/find_extensions_test.dart new file mode 100644 index 0000000..33e8bf7 --- /dev/null +++ b/pkgs/extension_discovery/test/find_extensions_test.dart
@@ -0,0 +1,350 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:isolate' show Isolate; + +import 'package:extension_discovery/extension_discovery.dart'; +import 'package:extension_discovery/src/io.dart'; +import 'package:test/test.dart'; + +import 'test_descriptor.dart' as d; + +void main() { + test('findExtensions', () async { + // Override the maturity delay for reliable testing of caching logic. + modificationMaturityDelay = const Duration(milliseconds: 500); + + final pkgLibDir = await Isolate.resolvePackageUri( + Uri.parse('package:extension_discovery/'), + ); + final pkgDir = pkgLibDir!.resolve('..'); + + await d.dir('myapp', [ + d.pubspec({ + 'name': 'myapp', + 'dependencies': { + 'extension_discovery': {'path': pkgDir.toFilePath()}, + }, + 'environment': {'sdk': '^3.0.0'}, + }), + ]).create(); + + // Get dependencies + await d.dartPubGet(d.path('myapp')); + + // Check that we don't find any extensions + expect( + await findExtensions( + 'myapp', + packageConfig: d.fileUri('myapp/.dart_tool/package_config.json'), + ), + isEmpty); + + // Check that there is a myapp.json cache file + await d + .file( + 'myapp/.dart_tool/extension_discovery/myapp.json', + isNotEmpty, + ) + .validate(); + + // ################################## Create foo that provides extension + await d.dir('foo', [ + d.pubspec({ + 'name': 'foo', + 'environment': {'sdk': '^3.0.0'}, + }), + // It has a config.yaml for myapp + d.dir('extension/myapp', [ + d.json('config.yaml', {'fromFoo': true}), + ]), + ]).create(); + + // Update the pubspec.yaml with a dependency on foo + await d.dir('myapp', [ + d.pubspec({ + 'name': 'myapp', + 'dependencies': { + 'extension_discovery': {'path': pkgDir.toFilePath()}, + 'foo': {'path': '../foo'}, + }, + 'environment': {'sdk': '^3.0.0'}, + }), + ]).create(); + + // Get dependencies + await d.dartPubGet(d.path('myapp')); + + // Check that we do find an extension + { + final ext = await findExtensions( + 'myapp', + packageConfig: d.fileUri('myapp/.dart_tool/package_config.json'), + ); + expect(ext, isNotEmpty); + expect( + ext.any( + (e) => + e.package == 'foo' && + e.rootUri == d.directoryUri('foo/') && + e.packageUri == Uri.parse('lib/') && + e.config['fromFoo'] == true, + ), + isTrue, + ); + } + + // ################################## Modify the config + await d.json('foo/extension/myapp/config.yaml', {'fromFoo': 42}).create(); + + // Check that we do find an extension + { + final ext = await findExtensions( + 'myapp', + packageConfig: d.fileUri('myapp/.dart_tool/package_config.json'), + ); + expect(ext, isNotEmpty); + expect( + ext.any( + (e) => + e.package == 'foo' && + e.rootUri == d.directoryUri('foo/') && + e.packageUri == Uri.parse('lib/') && + e.config['fromFoo'] == 42, + ), + isTrue, + ); + } + + // ################################## Make config invalid + await d.file('foo/extension/myapp/config.yaml', 'invalid YAML').create(); + + // Check that we do not find extensions + { + final ext = await findExtensions( + 'myapp', + packageConfig: d.fileUri('myapp/.dart_tool/package_config.json'), + ); + expect(ext, isEmpty); + } + + // ################################## Make config valid again + await d.json('foo/extension/myapp/config.yaml', {'fromFoo': true}).create(); + + // Check that we do find extensions + { + final ext = await findExtensions( + 'myapp', + packageConfig: d.fileUri('myapp/.dart_tool/package_config.json'), + ); + expect(ext, isNotEmpty); + } + + // ################################## Remove config file + await d.file('foo/extension/myapp/config.yaml').io.delete(); + // Check that we do not find extensions + { + final ext = await findExtensions( + 'myapp', + packageConfig: d.fileUri('myapp/.dart_tool/package_config.json'), + ); + expect(ext, isEmpty); + } + + // ################################## Make config valid again + await d.json('foo/extension/myapp/config.yaml', {'fromFoo': true}).create(); + + // Check that we do find extensions + { + final ext = await findExtensions( + 'myapp', + packageConfig: d.fileUri('myapp/.dart_tool/package_config.json'), + ); + expect(ext, isNotEmpty); + } + + // ################################## Create bar as absolute path-dep + await d.dir('bar', [ + d.pubspec({ + 'name': 'bar', + 'environment': {'sdk': '^3.0.0'}, + }), + // It has a config.yaml for myapp + d.dir('extension/myapp', [ + d.json('config.yaml', {'fromFoo': false}), + ]), + ]).create(); + + // Update the pubspec.yaml with a dependency on foo + await d.dir('myapp', [ + d.pubspec({ + 'name': 'myapp', + 'dependencies': { + 'extension_discovery': {'path': pkgDir.toFilePath()}, + 'foo': {'path': '../foo'}, + 'bar': {'path': d.path('bar')}, + }, + 'environment': {'sdk': '^3.0.0'}, + }), + ]).create(); + + // We won't find bar without running `dart pub get` + { + final ext = await findExtensions( + 'myapp', + packageConfig: d.fileUri('myapp/.dart_tool/package_config.json'), + ); + expect(ext.any((e) => e.package == 'bar'), isFalse); + } + + // Get dependencies + await d.dartPubGet(d.path('myapp')); + + // Check that we do find both extensions + { + final ext = await findExtensions( + 'myapp', + packageConfig: d.fileUri('myapp/.dart_tool/package_config.json'), + ); + expect(ext, isNotEmpty); + expect( + ext.any( + (e) => + e.package == 'foo' && + e.rootUri == d.directoryUri('foo/') && + e.packageUri == Uri.parse('lib/') && + e.config['fromFoo'] == true, + ), + isTrue, + ); + expect( + ext.any( + (e) => + e.package == 'bar' && + e.rootUri == d.directoryUri('bar/') && + e.packageUri == Uri.parse('lib/') && + e.config['fromFoo'] == false, + ), + isTrue, + ); + } + + // ################################## Changes to bar are not detected + + // Ensure that we wait long enough for the cache to be trusted, + // this delay is to make sure that the logic we have handling races isn't + // triggered. Think of it as waiting... + // If the modification time of package_config.json and the cache is no more + // than [modificationMaturityDelay] time apart, we'll ignore the cache. + // Under the assumption that there was a tiny risk of a race condition. + await Future<void>.delayed(modificationMaturityDelay * 2); + // Ensure that we have a cache value! + await findExtensions( + 'myapp', + packageConfig: d.fileUri('myapp/.dart_tool/package_config.json'), + ); + + // Delete config from package that has an absolute path, hence, a package + // we assume to be immutable. + await d.file('bar/extension/myapp/config.yaml').io.delete(); + + // Check that we do find both extensions + { + final ext = await findExtensions( + 'myapp', + packageConfig: d.fileUri('myapp/.dart_tool/package_config.json'), + ); + expect(ext.any((e) => e.package == 'foo'), isTrue); + // This is the wrong result, but it is expected. Essentially, if we expect + // that if you have packages in package_config.json using an absolute path + // then these won't be modified. If you do modify the + // extension/<targetPackage>/config.yaml + // file, then the cache will give the wrong result. The workaround is to + // touch `package_config.json`, or run `dart pub get` (essentially). + expect(ext.any((e) => e.package == 'bar'), isTrue); + } + + // Get dependencies + await d.dartPubGet(d.path('myapp')); + + // We won't find bar after `dart pub get`, because we removed the config + { + final ext = await findExtensions( + 'myapp', + packageConfig: d.fileUri('myapp/.dart_tool/package_config.json'), + ); + expect(ext.any((e) => e.package == 'foo'), isTrue); + expect(ext.any((e) => e.package == 'bar'), isFalse); + } + + // ################################## Sanity check bar and foo + expect( + await findExtensions( + 'foo', + packageConfig: d.fileUri('myapp/.dart_tool/package_config.json'), + ), + isEmpty, + ); + expect( + await findExtensions( + 'bar', + packageConfig: d.fileUri('myapp/.dart_tool/package_config.json'), + ), + isEmpty, + ); + + // ################################## What if foo has extensions for bar + await d.dir('foo/extension/bar', [ + d.json('config.yaml', {'fromFoo': true}), + ]).create(); + + { + final ext = await findExtensions( + 'bar', + packageConfig: d.fileUri('myapp/.dart_tool/package_config.json'), + ); + expect(ext.any((e) => e.package == 'foo'), isTrue); + expect(ext.any((e) => e.package == 'bar'), isFalse); + expect(ext.any((e) => e.package == 'myapp'), isFalse); + } + + // ################################## myapp could also extend bar + await d.dir('myapp/extension/bar', [ + d.json('config.yaml', {'fromFoo': false}), + ]).create(); + + { + final ext = await findExtensions( + 'bar', + packageConfig: d.fileUri('myapp/.dart_tool/package_config.json'), + ); + expect(ext.any((e) => e.package == 'foo'), isTrue); + expect(ext.any((e) => e.package == 'bar'), isFalse); + expect(ext.any((e) => e.package == 'myapp'), isTrue); + } + + // ################################## config could also be written in YAML + await d.dir('myapp/extension/bar', [ + d.file('config.yaml', ''' +writtenAsYaml: true +'''), + ]).create(); + + { + final ext = await findExtensions( + 'bar', + packageConfig: d.fileUri('myapp/.dart_tool/package_config.json'), + ); + expect(ext.any((e) => e.package == 'foo'), isTrue); + expect(ext.any((e) => e.package == 'bar'), isFalse); + expect(ext.any((e) => e.package == 'myapp'), isTrue); + expect( + ext.any( + (e) => e.package == 'myapp' && e.config['writtenAsYaml'] == true, + ), + isTrue, + ); + } + }); +}
diff --git a/pkgs/extension_discovery/test/integration_test.dart b/pkgs/extension_discovery/test/integration_test.dart new file mode 100644 index 0000000..ec52265 --- /dev/null +++ b/pkgs/extension_discovery/test/integration_test.dart
@@ -0,0 +1,134 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert' show jsonDecode; +import 'dart:isolate' show Isolate; + +import 'package:test/test.dart'; + +import 'test_descriptor.dart' as d; + +typedef Ext = ({ + String package, + String rootUri, + String packageUri, + dynamic config +}); + +void main() { + test('findExtensions', () async { + final pkgLibDir = await Isolate.resolvePackageUri( + Uri.parse('package:extension_discovery/'), + ); + final pkgDir = pkgLibDir!.resolve('..'); + + await d.dir('myapp', [ + d.pubspec({ + 'name': 'myapp', + 'dependencies': { + 'extension_discovery': {'path': pkgDir.toFilePath()}, + }, + 'environment': {'sdk': '^3.0.0'}, + }), + d.dir('bin', [ + d.file('find_extensions.dart', ''' +import 'dart:convert' show JsonEncoder; +import 'package:extension_discovery/extension_discovery.dart'; + +Future<void> main(List<String> args) async { + final extensions = await findExtensions(args.first); + print(JsonEncoder.withIndent(' ').convert([ + for (final e in extensions) + { + 'package': e.package, + 'rootUri': e.rootUri.toString(), + 'packageUri': e.packageUri.toString(), + 'config': e.config, + }, + ])); +} + '''), + ]) + ]).create(); + + Future<List<Ext>> findExtensionsInSandbox(String target) async { + final out = await d.dart( + d.path('myapp/bin/find_extensions.dart'), + target, + ); + return (jsonDecode(out) as List<Object?>) + .cast<Map>() + .map((e) => ( + package: e['package'] as String, + rootUri: e['rootUri'] as String, + packageUri: e['packageUri'] as String, + config: e['config'], + )) + .toList(); + } + + // Get dependencies + await d.dartPubGet(d.path('myapp')); + + // Check that we don't find any extensions + expect(await findExtensionsInSandbox('myapp'), isEmpty); + + // Check that there is a myapp.json cache file + await d + .file( + 'myapp/.dart_tool/extension_discovery/myapp.json', + isNotEmpty, + ) + .validate(); + + // Check that there is README.md + await d + .file( + 'myapp/.dart_tool/extension_discovery/README.md', + isNotEmpty, + ) + .validate(); + + // Create a foo package + await d.dir('foo', [ + d.pubspec({ + 'name': 'foo', + 'environment': {'sdk': '^3.0.0'}, + }), + // It has a config.yaml for myapp + d.dir('extension/myapp', [ + d.json('config.yaml', {'fromFoo': true}), + ]), + ]).create(); + + // Update the pubspec.yaml with a dependency on foo + await d.dir('myapp', [ + d.pubspec({ + 'name': 'myapp', + 'dependencies': { + 'extension_discovery': {'path': pkgDir.toFilePath()}, + 'foo': {'path': '../foo'}, + }, + 'environment': {'sdk': '^3.0.0'}, + }), + ]).create(); + + // Get dependencies + await d.dartPubGet(d.path('myapp')); + + // Check that we do find an extension + final ext = await findExtensionsInSandbox('myapp'); + expect(ext, isNotEmpty); + expect( + ext.any( + (e) => + e.package == 'foo' && + e.rootUri == d.directoryUri('foo/').toString() && + e.packageUri == Uri.parse('lib/').toString() && + (e.config as Map)['fromFoo'] == true, + ), + isTrue, + ); + }); +}
diff --git a/pkgs/extension_discovery/test/package_config_test.dart b/pkgs/extension_discovery/test/package_config_test.dart new file mode 100644 index 0000000..83c6c4d --- /dev/null +++ b/pkgs/extension_discovery/test/package_config_test.dart
@@ -0,0 +1,192 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert' show jsonDecode, jsonEncode; + +import 'package:extension_discovery/src/package_config.dart'; +import 'package:test/test.dart'; + +import 'test_descriptor.dart' as d; + +void main() { + test('loadPackageConfig', () async { + await d.dir('myapp', [ + d.pubspec({ + 'name': 'myapp', + 'dependencies': {}, + 'environment': {'sdk': '^3.0.0'}, + }), + ]).create(); + + final packageConfigFile = d.file('myapp/.dart_tool/package_config.json').io; + + // Loading before `dart pub get` throws PackageConfigException + expect( + loadPackageConfig(packageConfigFile), + throwsA(isA<PackageConfigException>()), + ); + + // Get dependencies + await d.dartPubGet(d.path('myapp')); + + // Parse package_config + { + final packages = await loadPackageConfig(packageConfigFile); + expect(packages, isNotEmpty); + expect(packages.any((p) => p.name == 'myapp'), isTrue); + expect(packages.any((p) => p.name == 'foo'), isFalse); + expect(packages.any((p) => p.name == 'bar'), isFalse); + } + + // ################################## Create foo as relative path-dep + await d.dir('foo', [ + d.pubspec({ + 'name': 'foo', + 'environment': {'sdk': '^3.0.0'}, + }), + ]).create(); + + // Update the pubspec.yaml with a dependency on foo + await d.dir('myapp', [ + d.pubspec({ + 'name': 'myapp', + 'dependencies': { + 'foo': {'path': '../foo'}, + }, + 'environment': {'sdk': '^3.0.0'}, + }), + ]).create(); + + // Get dependencies + await d.dartPubGet(d.path('myapp')); + + // Parse package_config + { + final packages = await loadPackageConfig(packageConfigFile); + expect(packages, isNotEmpty); + expect(packages.any((p) => p.name == 'myapp'), isTrue); + expect(packages.any((p) => p.name == 'foo'), isTrue); + expect(packages.any((p) => p.name == 'bar'), isFalse); + } + + // ################################## Create bar as absolute path-dep + + await d.dir('bar', [ + d.pubspec({ + 'name': 'bar', + 'environment': {'sdk': '^3.0.0'}, + }), + ]).create(); + + // Update the pubspec.yaml with a dependency on foo + await d.dir('myapp', [ + d.pubspec({ + 'name': 'myapp', + 'dependencies': { + 'foo': {'path': '../foo'}, + 'bar': {'path': d.path('bar')}, + }, + 'environment': {'sdk': '^3.0.0'}, + }), + ]).create(); + + // Get dependencies + await d.dartPubGet(d.path('myapp')); + + // Parse package_config + { + final packages = await loadPackageConfig(packageConfigFile); + expect(packages, isNotEmpty); + expect(packages.any((p) => p.name == 'myapp'), isTrue); + expect(packages.any((p) => p.name == 'foo'), isTrue); + expect(packages.any((p) => p.name == 'bar'), isTrue); + } + + // ################################## Cannot read version 99 + + { + final pkgcfg = jsonDecode(packageConfigFile.readAsStringSync()) as Map; + pkgcfg['configVersion'] = 99; + packageConfigFile.writeAsStringSync(jsonEncode(pkgcfg)); + } + + // Loading before `dart pub get` throws PackageConfigException + expect( + loadPackageConfig(packageConfigFile), + throwsA(isA<PackageConfigException>()), + ); + + // ################################## packageUri is optional + + // Get dependencies + await d.dartPubGet(d.path('myapp')); + + { + final pkgcfg = jsonDecode(packageConfigFile.readAsStringSync()) as Map; + for (final p in pkgcfg['packages'] as List) { + (p as Map).remove('packageUri'); + } + packageConfigFile.writeAsStringSync(jsonEncode(pkgcfg)); + } + + // Parse package_config + { + final packages = await loadPackageConfig(packageConfigFile); + expect(packages, isNotEmpty); + expect(packages.any((p) => p.name == 'myapp'), isTrue); + expect(packages.any((p) => p.name == 'foo'), isTrue); + expect(packages.any((p) => p.name == 'bar'), isTrue); + expect(packages.every((p) => p.rootUri == p.packageUri), isTrue); + } + + // ################################## packageUri is optional + + // Get dependencies + await d.dartPubGet(d.path('myapp')); + + { + final pkgcfg = jsonDecode(packageConfigFile.readAsStringSync()) as Map; + for (final p in pkgcfg['packages'] as List) { + (p as Map).remove('rootUri'); + } + packageConfigFile.writeAsStringSync(jsonEncode(pkgcfg)); + } + + // Loading before `dart pub get` throws PackageConfigException + expect( + loadPackageConfig(packageConfigFile), + throwsA(isA<PackageConfigException>()), + ); + }); + + test('`findPackageConfig()`', () async { + await d.dir('workspace', [ + d.dir('.dart_tool', [ + d.file('package_config.json'), + ]), + d.dir('myapp', []) + ]).create(); + + expect( + findPackageConfig(d.fileUri('workspace')), + d.fileUri('workspace/.dart_tool/package_config.json'), + ); + expect( + findPackageConfig(d.fileUri('workspace/')), + d.fileUri('workspace/.dart_tool/package_config.json'), + ); + expect( + findPackageConfig(d.fileUri('workspace/myapp')), + d.fileUri('workspace/.dart_tool/package_config.json'), + ); + expect( + findPackageConfig(d.fileUri('.')), + isNull, + ); + expect( + findPackageConfig(d.fileUri('foo')), + isNull, + ); + }); +}
diff --git a/pkgs/extension_discovery/test/test_descriptor.dart b/pkgs/extension_discovery/test/test_descriptor.dart new file mode 100644 index 0000000..0bd4a63 --- /dev/null +++ b/pkgs/extension_discovery/test/test_descriptor.dart
@@ -0,0 +1,56 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert' show JsonEncoder; +import 'dart:io' show Platform, Process; + +import 'package:test/test.dart'; +import 'package:test_descriptor/test_descriptor.dart' as d; +export 'package:test_descriptor/test_descriptor.dart'; + +d.FileDescriptor json(String fileName, Object? json) => + d.file(fileName, const JsonEncoder.withIndent(' ').convert(json)); + +d.FileDescriptor pubspec(Map<String, Object?> pubspec) => + json('pubspec.yaml', pubspec); + +Uri fileUri(String path) => Uri.file(d.path(path)); +Uri directoryUri(String path) => Uri.directory(d.path(path)); + +Future<String> dart([ + String? arg1, + String? arg2, + String? arg3, + String? arg4, + String? arg5, + String? arg6, + String? arg7, + String? arg8, +]) async { + final arguments = [ + if (arg1 != null) arg1, + if (arg2 != null) arg2, + if (arg3 != null) arg3, + if (arg4 != null) arg4, + if (arg5 != null) arg5, + if (arg6 != null) arg6, + if (arg7 != null) arg7, + if (arg8 != null) arg8, + ]; + final result = await Process.run( + Platform.executable, + arguments, + workingDirectory: d.sandbox, + ); + if (result.exitCode != 0) { + print(result.stderr); + print(result.stdout); + } + expect(result.exitCode, 0, + reason: 'failed executing "dart ${arguments.join(' ')}"'); + return result.stdout as String; +} + +Future<String> dartPubGet(String folder) async => + await dart('pub', 'get', '-C', folder);
diff --git a/pkgs/extension_discovery/test/yaml_config_format_test.dart b/pkgs/extension_discovery/test/yaml_config_format_test.dart new file mode 100644 index 0000000..0e3f568 --- /dev/null +++ b/pkgs/extension_discovery/test/yaml_config_format_test.dart
@@ -0,0 +1,149 @@ +// 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:collection/collection.dart' show DeepCollectionEquality; + +import 'package:extension_discovery/src/yaml_config_format.dart'; +import 'package:test/test.dart'; + +void _testInvalid(String name, String yaml, {String match = ''}) { + test(name, () { + expect( + () => parseYamlFromConfigFile(yaml), + throwsA(isFormatException.having( + (e) => e.message, + 'message', + contains(match), + )), + ); + }); +} + +void _testValid(String name, String yaml) { + test(name, () { + parseYamlFromConfigFile(yaml); + }); +} + +void main() { + group('parseYamlFromConfigFile', () { + group('root must be a map', () { + _testInvalid('empty string', '', match: 'map'); + _testInvalid('null', 'null', match: 'map'); + _testInvalid('list', '[]', match: 'map'); + _testInvalid('number (1)', '42', match: 'map'); + _testInvalid('number (2)', '42.2', match: 'map'); + _testInvalid('bool (1)', 'true', match: 'map'); + _testInvalid('bool (2)', 'false', match: 'map'); + _testInvalid('string', '"hello world"', match: 'map'); + }); + + _testInvalid('must not have alias', match: 'alias', ''' + keyA: &myref + - value 1 + - value 2 + KeyB: *myref + '''); + + // it works without aliases + _testValid('listed inside a map is fine', ''' + keyA: + - value 1 + - value 2 + KeyB: + - value 1 + - value 2 + '''); + + _testValid('comments are cool', ''' + keyA: + - value 1 # this is fine + - value 2 + '''); + + _testInvalid( + 'Top-level map with integer keys is not allowed', match: 'key', ''' + 42: "value" # this is NOT fine + 43: true + '''); + + _testValid('Map with quoted integer keys is fine', ''' + "42": "value" # this is fine + '43': true + '''); + + _testInvalid('Map with integer keys is not allowed', match: 'key', ''' + keyA: + - value 1 # this is fine + - value 2 + KeyB: + 42: value 3 # this is NOT fine + '''); + + _testInvalid('Map with list keys is not allowed', match: 'key', ''' + keyA: + - [1, 2, 3] # this is fine, crazy but fine! + keyB: + [1, 2, 3]: value 3 # this is NOT fine + '''); + + _testInvalid('Map with boolean keys is not allowed (1)', match: 'key', ''' + keyA: true + keyB: + true: value 3 # this is NOT fine + '''); + + _testInvalid('Map with boolean keys is not allowed (2)', match: 'key', ''' + keyA: true + keyB: + false: value 3 # this is NOT fine + '''); + + _testInvalid('Map with null keys is not allowed', match: 'key', ''' + keyA: null # fine + keyB: + null: value 3 # this is NOT fine + '''); + + _testValid('complex structures is fine', ''' + keyA: | + multi-line + string + keyB: 42 # number + keyC: 42.2 # double + keyD: [1, 2] + keyE: + - 1 + - 2 + keyF: + k: "v" + '''); + + test('complex structures matches the same JSON', () { + final yaml = ''' + keyA: "hello" + keyB: 42 # number + keyC: 42.2 # double + keyD: [1, 2] + keyE: + - 1 + - 2 + keyF: + k: "v" + '''; + final data = parseYamlFromConfigFile(yaml); + expect( + const DeepCollectionEquality().equals(data, { + 'keyA': 'hello', + 'keyB': 42, + 'keyC': 42.2, + 'keyD': [1, 2], + 'keyE': [1, 2], + 'keyF': {'k': 'v'}, + }), + isTrue, + ); + }); + }); +}
diff --git a/pkgs/file/.gitignore b/pkgs/file/.gitignore new file mode 100644 index 0000000..ddfdca1 --- /dev/null +++ b/pkgs/file/.gitignore
@@ -0,0 +1,5 @@ +.dart_tool/ +.packages +.pub/ +build/ +pubspec.lock
diff --git a/pkgs/file/CHANGELOG.md b/pkgs/file/CHANGELOG.md new file mode 100644 index 0000000..50c96c4 --- /dev/null +++ b/pkgs/file/CHANGELOG.md
@@ -0,0 +1,242 @@ +## 7.0.1 + +* Update the pubspec repository field to reflect the new package repository. + +## 7.0.0 + +* Dart 3 fixes for class modifiers. +* Require Dart 3.0. +* `MemoryFileSystem` now treats empty paths as non-existent. +* Fix `FileSystem.isLink`/`FileSystem.isLinkSync` to not follow symbolic links. +* Make the return type of `MemoryFile.openRead` and `_ChrootFile.openRead` again + match the return type from `dart:io`. + +## 6.1.4 + +* Populate the pubspec `repository` field. + +## 6.1.3 + +* In classes that implement `File` methods `create`, `createSync` now take `bool exclusive = true` parameter. No functional changes. + +## 6.1.2 + +* `MemoryFileSystem` now provides `opHandle`s for exists operations. + +## 6.1.1 + +* `MemoryFile` now provides `opHandle`s for copy and open operations. + +## 6.1.0 + +* Reading invalid UTF8 with the `MemoryFileSystem` now correctly throws a `FileSystemException` instead of a `FormatError`. +* `MemoryFileSystem` now provides an `opHandle` to inspect read/write operations. +* `MemoryFileSystem` now creates the temporary directory before returning in `createTemp`/`createTempSync`. + +## 6.0.1 + +* Fix sound type error in memory backend when reading non-existent `MemoryDirectory`. + +## 6.0.0 + +* First stable null safe release. + +## 6.0.0-nullsafety.4 + +* Update upper bound of SDK constraint. + +## 6.0.0-nullsafety.3 + +* Update upper bound of SDK constraint. + +## 6.0.0-nullsafety.2 + +* Make `ForwardingFile.openRead`'s return type again match the return type from + `dart:io`. +* Remove some unnecessary `Uint8List` conversions in `ForwardingFile`. + +## 6.0.0-nullsafety.1 + +* Update to null safety. +* Remove record/replay functionality. +* Made `MemoryRandomAccessFile` and `MemoryFile.openWrite` handle the file + being removed or renamed while open. +* Fixed incorrect formatting in `NoMatchingInvocationError.toString()`. +* Fixed more test flakiness. +* Enabled more tests. +* Internal cleanup. +* Remove implicit dynamic in preparation for null safety. +* Remove dependency on Intl. + +## 5.2.1 + +* systemTemp directories created by `MemoryFileSystem` will allot names + based on the file system instance instead of globally. +* `MemoryFile.readAsLines()`/`readAsLinesSync()` no longer treat a final newline + in the file as the start of a new, empty line. +* `RecordingFile.readAsLine()`/`readAsLinesSync()` now always record a final + newline. +* `MemoryFile.flush()` now returns `Future<void>` instead of `Future<dynamic>`. +* Fixed some test flakiness. +* Enabled more tests. +* Internal cleanup. + +## 5.2.0 + +* Added a `MemoryRandomAccessFile` class and implemented + `MemoryFile.open()`/`openSync()`. + +## 5.1.0 + +* Added a new `MemoryFileSystem` constructor to use a test clock + +## 5.0.10 + +* Added example + +## 5.0.9 + +* Fix lints for project health + +## 5.0.8 + +* Return `Uint8List` rather than `List<int>`. + +## 5.0.7 + +* Dart 2 fixes for `RecordingProxyMixin` and `ReplayProxyMixin`. + +## 5.0.6 + +* Dart 2 fixes for `RecordingFile.open()` + +## 5.0.5 + +* Dart 2 fixes + +## 5.0.4 + +* Update SDK constraint to 2.0.0-dev.67.0, remove workaround in + recording_proxy_mixin.dart. +* Fix usage within Dart 2 runtime mode in Dart 2.0.0-dev.61.0 and later. +* Relax constraints on `package:test` + +## 5.0.3 + +* Update `package:test` dependency to 1.0 + +## 5.0.2 + +* Declare compatibility with Dart 2 stable + +## 5.0.1 + +* Remove upper case constants +* Update SDK constraint to 2.0.0-dev.54.0. + +## 5.0.0 + +* Moved `testing` library into a dedicated `package:file_testing` so that + libraries don't need to take on a transitive dependency on `package:test` + in order to use `package:file`. + +## 4.0.1 + +* General library cleanup +* Add `style` support in `MemoryFileSystem`, so that callers can choose to + have a memory file system with windows-like paths. [#68] + (https://github.com/google/file.dart/issues/68) + +## 4.0.0 + +* Change method signature for `RecordingRandomAccessFile._close` to return a + `Future<void>` instead of `Future<RandomAccessFile>`. This follows a change in + dart:io, Dart SDK `2.0.0-dev.40`. + +## 3.0.0 + +* Import `dart:io` unconditionally. More recent Dart SDK revisions allow + `dart:io` to be imported in a browser context, though if methods are actually + invoked, they will fail. This matches well with `package:file`, where users + can use the `memory` library and get in-memory implementations of the + `dart:io` interfaces. +* Bump minimum Dart SDK to `1.24.0` + +## 2.3.7 + +* Fix Dart 2 error. + +## 2.3.6 + +* Relax sdk upper bound constraint to '<2.0.0' to allow 'edge' dart sdk use. + +## 2.3.5 + +* Fix internal use of a cast which fails on Dart 2.0 . + +## 2.3.4 + +* Bumped maximum Dart SDK version to 2.0.0-dev.infinity + +## 2.3.3 + +* Relaxes version requirements on `package:intl` + +## 2.3.2 + +* Fixed `FileSystem.directory(Uri)`, `FileSystem.file(Uri)`, and + `FileSystem.link(Uri)` to consult the file system's path context when + converting the URI to a file path rather than using `Uri.toFilePath()`. + +## 2.3.1 + +* Fixed `MemoryFileSystem` to make `File.writeAs...()` update the last modified + time of the file. + +## 2.3.0 + +* Added the following convenience methods in `Directory`: + * `Directory.childDirectory(String basename)` + * `Directory.childFile(String basename)` + * `Directory.childLink(String basename)` + +## 2.2.0 + +* Added `ErrorCodes` class, which holds errno values. + +## 2.1.0 + +* Add support for new `dart:io` API methods added in Dart SDK 1.23 + +## 2.0.1 + +* Minor doc updates + +## 2.0.0 + +* Improved `toString` implementations in file system entity classes +* Added `ForwardingFileSystem` and associated forwarding classes to the + main `file` library +* Removed `FileSystem.pathSeparator`, and added a more comprehensive + `FileSystem.path` property +* Added `FileSystemEntity.basename` and `FileSystemEntity.dirname` +* Added the `record_replay` library +* Added the `testing` library + +## 1.0.1 + +* Added `FileSystem.systemTempDirectory` +* Added the ability to pass `Uri` and `FileSystemEntity` types to + `FileSystem.directory()`, `FileSystem.file()`, and `FileSystem.link()` +* Added `FileSystem.pathSeparator` + +## 1.0.0 + +* Unified interface to match dart:io API +* Local file system implementation +* In-memory file system implementation +* Chroot file system implementation + +## 0.1.0 + +* Initial version
diff --git a/pkgs/file/LICENSE b/pkgs/file/LICENSE new file mode 100644 index 0000000..076334f --- /dev/null +++ b/pkgs/file/LICENSE
@@ -0,0 +1,26 @@ +Copyright 2017, the Dart project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file
diff --git a/pkgs/file/README.md b/pkgs/file/README.md new file mode 100644 index 0000000..a63d6e6 --- /dev/null +++ b/pkgs/file/README.md
@@ -0,0 +1,44 @@ +[](https://github.com/dart-lang/tools/actions/workflows/file.yml) +[](https://pub.dev/packages/file) +[](https://pub.dev/packages/file/publisher) + +A generic file system abstraction for Dart. + +## Features + +Like `dart:io`, `package:file` supplies a rich Dart-idiomatic API for accessing +a file system. + +Unlike `dart:io`, `package:file`: + +- Can be used to implement custom file systems. +- Comes with an in-memory implementation out-of-the-box, making it super-easy to + test code that works with the file system. +- Allows using multiple file systems simultaneously. A file system is a + first-class object. Instantiate however many you want and use them all. + +## Usage + +Implement your own custom file system: + +```dart +import 'package:file/file.dart'; + +class FooBarFileSystem implements FileSystem { ... } +``` + +Use the in-memory file system: + +```dart +import 'package:file/memory.dart'; + +var fs = MemoryFileSystem(); +``` + +Use the local file system (requires dart:io access): + +```dart +import 'package:file/local.dart'; + +var fs = const LocalFileSystem(); +```
diff --git a/pkgs/file/analysis_options.yaml b/pkgs/file/analysis_options.yaml new file mode 100644 index 0000000..8fbd2e4 --- /dev/null +++ b/pkgs/file/analysis_options.yaml
@@ -0,0 +1,6 @@ +include: package:lints/recommended.yaml + +analyzer: + errors: + # Allow having TODOs in the code + todo: ignore
diff --git a/pkgs/file/example/main.dart b/pkgs/file/example/main.dart new file mode 100644 index 0000000..7ca0bc7 --- /dev/null +++ b/pkgs/file/example/main.dart
@@ -0,0 +1,14 @@ +// 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'; +import 'package:file/memory.dart'; + +Future<void> main() async { + final FileSystem fs = MemoryFileSystem(); + final Directory tmp = await fs.systemTempDirectory.createTemp('example_'); + final File outputFile = tmp.childFile('output'); + await outputFile.writeAsString('Hello world!'); + print(outputFile.readAsStringSync()); +}
diff --git a/pkgs/file/lib/chroot.dart b/pkgs/file/lib/chroot.dart new file mode 100644 index 0000000..56d2bd5 --- /dev/null +++ b/pkgs/file/lib/chroot.dart
@@ -0,0 +1,6 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// A file system that provides a view into _another_ `FileSystem` via a path. +export 'src/backends/chroot.dart';
diff --git a/pkgs/file/lib/file.dart b/pkgs/file/lib/file.dart new file mode 100644 index 0000000..cdde9fe --- /dev/null +++ b/pkgs/file/lib/file.dart
@@ -0,0 +1,8 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Core interfaces containing the abstract `FileSystem` interface definition +/// and all associated types used by `FileSystem`. +export 'src/forwarding.dart'; +export 'src/interface.dart';
diff --git a/pkgs/file/lib/local.dart b/pkgs/file/lib/local.dart new file mode 100644 index 0000000..74f506e --- /dev/null +++ b/pkgs/file/lib/local.dart
@@ -0,0 +1,7 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// A local file system implementation. This relies on the use of `dart:io` +/// and is thus not suitable for use in the browser. +export 'src/backends/local.dart';
diff --git a/pkgs/file/lib/memory.dart b/pkgs/file/lib/memory.dart new file mode 100644 index 0000000..c5705ef --- /dev/null +++ b/pkgs/file/lib/memory.dart
@@ -0,0 +1,8 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// An implementation of `FileSystem` that exists entirely in memory with an +/// internal representation loosely based on the Filesystem Hierarchy Standard. +export 'src/backends/memory.dart'; +export 'src/backends/memory/operations.dart';
diff --git a/pkgs/file/lib/src/backends/chroot.dart b/pkgs/file/lib/src/backends/chroot.dart new file mode 100644 index 0000000..6082e80 --- /dev/null +++ b/pkgs/file/lib/src/backends/chroot.dart
@@ -0,0 +1,20 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library file.src.backends.chroot; + +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:file/file.dart'; +import 'package:file/src/common.dart' as common; +import 'package:file/src/io.dart' as io; +import 'package:path/path.dart' as p; + +part 'chroot/chroot_directory.dart'; +part 'chroot/chroot_file.dart'; +part 'chroot/chroot_file_system.dart'; +part 'chroot/chroot_file_system_entity.dart'; +part 'chroot/chroot_link.dart'; +part 'chroot/chroot_random_access_file.dart';
diff --git a/pkgs/file/lib/src/backends/chroot/chroot_directory.dart b/pkgs/file/lib/src/backends/chroot/chroot_directory.dart new file mode 100644 index 0000000..8fec7b1 --- /dev/null +++ b/pkgs/file/lib/src/backends/chroot/chroot_directory.dart
@@ -0,0 +1,176 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of file.src.backends.chroot; + +class _ChrootDirectory extends _ChrootFileSystemEntity<Directory, io.Directory> + with ForwardingDirectory<Directory>, common.DirectoryAddOnsMixin { + _ChrootDirectory(ChrootFileSystem fs, String path) : super(fs, path); + + factory _ChrootDirectory.wrapped( + ChrootFileSystem fs, + Directory delegate, { + bool relative = false, + }) { + String localPath = fs._local(delegate.path, relative: relative); + return _ChrootDirectory(fs, localPath); + } + + @override + FileSystemEntityType get expectedType => FileSystemEntityType.directory; + + @override + io.Directory _rawDelegate(String path) => fileSystem.delegate.directory(path); + + @override + Uri get uri => Uri.directory(path); + + @override + Future<Directory> rename(String newPath) async { + if (_isLink) { + if (await fileSystem.type(path) != expectedType) { + throw common.notADirectory(path); + } + FileSystemEntityType type = await fileSystem.type(newPath); + if (type != FileSystemEntityType.notFound) { + if (type != expectedType) { + throw common.notADirectory(newPath); + } + if (!(await fileSystem + .directory(newPath) + .list(followLinks: false) + .isEmpty)) { + throw common.directoryNotEmpty(newPath); + } + } + String target = await fileSystem.link(path).target(); + await fileSystem.link(path).delete(); + await fileSystem.link(newPath).create(target); + return fileSystem.directory(newPath); + } else { + return wrap(await getDelegate(followLinks: true) + .rename(fileSystem._real(newPath))); + } + } + + @override + Directory renameSync(String newPath) { + if (_isLink) { + if (fileSystem.typeSync(path) != expectedType) { + throw common.notADirectory(path); + } + FileSystemEntityType type = fileSystem.typeSync(newPath); + if (type != FileSystemEntityType.notFound) { + if (type != expectedType) { + throw common.notADirectory(newPath); + } + if (fileSystem + .directory(newPath) + .listSync(followLinks: false) + .isNotEmpty) { + throw common.directoryNotEmpty(newPath); + } + } + String target = fileSystem.link(path).targetSync(); + fileSystem.link(path).deleteSync(); + fileSystem.link(newPath).createSync(target); + return fileSystem.directory(newPath); + } else { + return wrap( + getDelegate(followLinks: true).renameSync(fileSystem._real(newPath))); + } + } + + @override + Directory get absolute => _ChrootDirectory(fileSystem, _absolutePath); + + @override + Directory get parent { + try { + return wrapDirectory(delegate.parent); + } on _ChrootJailException { + return this; + } + } + + @override + Future<Directory> create({bool recursive = false}) async { + if (_isLink) { + switch (await fileSystem.type(path)) { + case FileSystemEntityType.notFound: + throw common.noSuchFileOrDirectory(path); + case FileSystemEntityType.file: + throw common.fileExists(path); + case FileSystemEntityType.directory: + // Nothing to do. + return this; + default: + throw AssertionError(); + } + } else { + return wrap(await delegate.create(recursive: recursive)); + } + } + + @override + void createSync({bool recursive = false}) { + if (_isLink) { + switch (fileSystem.typeSync(path)) { + case FileSystemEntityType.notFound: + throw common.noSuchFileOrDirectory(path); + case FileSystemEntityType.file: + throw common.fileExists(path); + case FileSystemEntityType.directory: + // Nothing to do. + return; + default: + throw AssertionError(); + } + } else { + delegate.createSync(recursive: recursive); + } + } + + @override + Stream<FileSystemEntity> list({ + bool recursive = false, + bool followLinks = true, + }) { + Directory delegate = this.delegate as Directory; + String dirname = delegate.path; + return delegate + .list(recursive: recursive, followLinks: followLinks) + .map((io.FileSystemEntity entity) => _denormalize(entity, dirname)); + } + + @override + List<FileSystemEntity> listSync({ + bool recursive = false, + bool followLinks = true, + }) { + Directory delegate = this.delegate as Directory; + String dirname = delegate.path; + return delegate + .listSync(recursive: recursive, followLinks: followLinks) + .map((io.FileSystemEntity entity) => _denormalize(entity, dirname)) + .toList(); + } + + FileSystemEntity _denormalize(io.FileSystemEntity entity, String dirname) { + p.Context ctx = fileSystem.path; + String relativePart = ctx.relative(entity.path, from: dirname); + String entityPath = ctx.join(path, relativePart); + if (entity is io.File) { + return _ChrootFile(fileSystem, entityPath); + } else if (entity is io.Directory) { + return _ChrootDirectory(fileSystem, entityPath); + } else if (entity is io.Link) { + return _ChrootLink(fileSystem, entityPath); + } + throw FileSystemException('Unsupported type: $entity', entity.path); + } + + @override + String toString() => "ChrootDirectory: '$path'"; +}
diff --git a/pkgs/file/lib/src/backends/chroot/chroot_file.dart b/pkgs/file/lib/src/backends/chroot/chroot_file.dart new file mode 100644 index 0000000..4b67bc1 --- /dev/null +++ b/pkgs/file/lib/src/backends/chroot/chroot_file.dart
@@ -0,0 +1,339 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of file.src.backends.chroot; + +typedef _SetupCallback = dynamic Function(); + +class _ChrootFile extends _ChrootFileSystemEntity<File, io.File> + with ForwardingFile { + _ChrootFile(ChrootFileSystem fs, String path) : super(fs, path); + + factory _ChrootFile.wrapped( + ChrootFileSystem fs, + io.File delegate, { + bool relative = false, + }) { + String localPath = fs._local(delegate.path, relative: relative); + return _ChrootFile(fs, localPath); + } + + @override + FileSystemEntityType get expectedType => FileSystemEntityType.file; + + @override + io.File _rawDelegate(String path) => fileSystem.delegate.file(path); + + @override + Future<File> rename(String newPath) async { + _SetupCallback setUp = () async {}; + + if (await fileSystem.type(newPath, followLinks: false) == + FileSystemEntityType.link) { + // The delegate file system will ensure that the link target references + // an actual file before allowing the rename, but we want the link target + // to be resolved with respect to this file system. Thus, we perform that + // validation here instead. + switch (await fileSystem.type(newPath)) { + case FileSystemEntityType.file: + case FileSystemEntityType.notFound: + // Validation passed; delete the link to keep the delegate file + // system's validation from getting in the way. + setUp = () async { + await fileSystem.link(newPath).delete(); + }; + break; + case FileSystemEntityType.directory: + throw common.isADirectory(newPath); + default: + // Should never happen. + throw AssertionError(); + } + } + + if (_isLink) { + switch (await fileSystem.type(path)) { + case FileSystemEntityType.notFound: + throw common.noSuchFileOrDirectory(path); + case FileSystemEntityType.directory: + throw common.isADirectory(path); + case FileSystemEntityType.file: + await setUp(); + await fileSystem.delegate + .link(fileSystem._real(path)) + .rename(fileSystem._real(newPath)); + return _ChrootFile(fileSystem, newPath); + default: + throw AssertionError(); + } + } else { + await setUp(); + return wrap(await delegate.rename(fileSystem._real(newPath))); + } + } + + @override + File renameSync(String newPath) { + _SetupCallback setUp = () {}; + + if (fileSystem.typeSync(newPath, followLinks: false) == + FileSystemEntityType.link) { + // The delegate file system will ensure that the link target references + // an actual file before allowing the rename, but we want the link target + // to be resolved with respect to this file system. Thus, we perform that + // validation here instead. + switch (fileSystem.typeSync(newPath)) { + case FileSystemEntityType.file: + case FileSystemEntityType.notFound: + // Validation passed; delete the link to keep the delegate file + // system's validation from getting in the way. + setUp = () { + fileSystem.link(newPath).deleteSync(); + }; + break; + case FileSystemEntityType.directory: + throw common.isADirectory(newPath); + default: + // Should never happen. + throw AssertionError(); + } + } + + if (_isLink) { + switch (fileSystem.typeSync(path)) { + case FileSystemEntityType.notFound: + throw common.noSuchFileOrDirectory(path); + case FileSystemEntityType.directory: + throw common.isADirectory(path); + case FileSystemEntityType.file: + setUp(); + fileSystem.delegate + .link(fileSystem._real(path)) + .renameSync(fileSystem._real(newPath)); + return _ChrootFile(fileSystem, newPath); + default: + throw AssertionError(); + } + } else { + setUp(); + return wrap(delegate.renameSync(fileSystem._real(newPath))); + } + } + + @override + File get absolute => _ChrootFile(fileSystem, _absolutePath); + + @override + Future<File> create({bool recursive = false, bool exclusive = false}) async { + String path = fileSystem._resolve( + this.path, + followLinks: false, + notFound: recursive ? _NotFoundBehavior.mkdir : _NotFoundBehavior.allow, + ); + + String real() => fileSystem._real(path, resolve: false); + Future<FileSystemEntityType> type() => + fileSystem.delegate.type(real(), followLinks: false); + + if (await type() == FileSystemEntityType.link) { + path = fileSystem._resolve(p.basename(path), + from: p.dirname(path), notFound: _NotFoundBehavior.allowAtTail); + switch (await type()) { + case FileSystemEntityType.notFound: + await _rawDelegate(real()).create(); + return this; + case FileSystemEntityType.file: + // Nothing to do. + return this; + case FileSystemEntityType.directory: + throw common.isADirectory(path); + default: + throw AssertionError(); + } + } else { + return wrap(await _rawDelegate(real()).create()); + } + } + + @override + void createSync({bool recursive = false, bool exclusive = false}) { + String path = fileSystem._resolve( + this.path, + followLinks: false, + notFound: recursive ? _NotFoundBehavior.mkdir : _NotFoundBehavior.allow, + ); + + String real() => fileSystem._real(path, resolve: false); + FileSystemEntityType type() => + fileSystem.delegate.typeSync(real(), followLinks: false); + + if (type() == FileSystemEntityType.link) { + path = fileSystem._resolve(p.basename(path), + from: p.dirname(path), notFound: _NotFoundBehavior.allowAtTail); + switch (type()) { + case FileSystemEntityType.notFound: + _rawDelegate(real()).createSync(); + return; + case FileSystemEntityType.file: + // Nothing to do. + return; + case FileSystemEntityType.directory: + throw common.isADirectory(path); + default: + throw AssertionError(); + } + } else { + _rawDelegate(real()).createSync(); + } + } + + @override + Future<File> copy(String newPath) async { + return wrap(await getDelegate(followLinks: true) + .copy(fileSystem._real(newPath, followLinks: true))); + } + + @override + File copySync(String newPath) { + return wrap(getDelegate(followLinks: true) + .copySync(fileSystem._real(newPath, followLinks: true))); + } + + @override + Future<int> length() => getDelegate(followLinks: true).length(); + + @override + int lengthSync() => getDelegate(followLinks: true).lengthSync(); + + @override + Future<DateTime> lastAccessed() => + getDelegate(followLinks: true).lastAccessed(); + + @override + DateTime lastAccessedSync() => + getDelegate(followLinks: true).lastAccessedSync(); + + @override + Future<dynamic> setLastAccessed(DateTime time) => + getDelegate(followLinks: true).setLastAccessed(time); + + @override + void setLastAccessedSync(DateTime time) => + getDelegate(followLinks: true).setLastAccessedSync(time); + + @override + Future<DateTime> lastModified() => + getDelegate(followLinks: true).lastModified(); + + @override + DateTime lastModifiedSync() => + getDelegate(followLinks: true).lastModifiedSync(); + + @override + Future<dynamic> setLastModified(DateTime time) => + getDelegate(followLinks: true).setLastModified(time); + + @override + void setLastModifiedSync(DateTime time) => + getDelegate(followLinks: true).setLastModifiedSync(time); + + @override + Future<RandomAccessFile> open({ + FileMode mode = FileMode.read, + }) async => + _ChrootRandomAccessFile( + path, await getDelegate(followLinks: true).open(mode: mode)); + + @override + RandomAccessFile openSync({FileMode mode = FileMode.read}) => + _ChrootRandomAccessFile( + path, getDelegate(followLinks: true).openSync(mode: mode)); + + @override + Stream<List<int>> openRead([int? start, int? end]) => + getDelegate(followLinks: true).openRead(start, end); + + @override + IOSink openWrite({ + FileMode mode = FileMode.write, + Encoding encoding = utf8, + }) => + getDelegate(followLinks: true).openWrite(mode: mode, encoding: encoding); + + @override + Future<Uint8List> readAsBytes() => + getDelegate(followLinks: true).readAsBytes(); + + @override + Uint8List readAsBytesSync() => + getDelegate(followLinks: true).readAsBytesSync(); + + @override + Future<String> readAsString({Encoding encoding = utf8}) => + getDelegate(followLinks: true).readAsString(encoding: encoding); + + @override + String readAsStringSync({Encoding encoding = utf8}) => + getDelegate(followLinks: true).readAsStringSync(encoding: encoding); + + @override + Future<List<String>> readAsLines({Encoding encoding = utf8}) => + getDelegate(followLinks: true).readAsLines(encoding: encoding); + + @override + List<String> readAsLinesSync({Encoding encoding = utf8}) => + getDelegate(followLinks: true).readAsLinesSync(encoding: encoding); + + @override + Future<File> writeAsBytes( + List<int> bytes, { + FileMode mode = FileMode.write, + bool flush = false, + }) async => + wrap(await getDelegate(followLinks: true).writeAsBytes( + bytes, + mode: mode, + flush: flush, + )); + + @override + void writeAsBytesSync( + List<int> bytes, { + FileMode mode = FileMode.write, + bool flush = false, + }) => + getDelegate(followLinks: true) + .writeAsBytesSync(bytes, mode: mode, flush: flush); + + @override + Future<File> writeAsString( + String contents, { + FileMode mode = FileMode.write, + Encoding encoding = utf8, + bool flush = false, + }) async => + wrap(await getDelegate(followLinks: true).writeAsString( + contents, + mode: mode, + encoding: encoding, + flush: flush, + )); + + @override + void writeAsStringSync( + String contents, { + FileMode mode = FileMode.write, + Encoding encoding = utf8, + bool flush = false, + }) => + getDelegate(followLinks: true).writeAsStringSync( + contents, + mode: mode, + encoding: encoding, + flush: flush, + ); + + @override + String toString() => "ChrootFile: '$path'"; +}
diff --git a/pkgs/file/lib/src/backends/chroot/chroot_file_system.dart b/pkgs/file/lib/src/backends/chroot/chroot_file_system.dart new file mode 100644 index 0000000..6889c98 --- /dev/null +++ b/pkgs/file/lib/src/backends/chroot/chroot_file_system.dart
@@ -0,0 +1,391 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of file.src.backends.chroot; + +const String _thisDir = '.'; +const String _parentDir = '..'; + +/// File system that provides a view into _another_ [FileSystem] via a path. +/// +/// This is similar in concept to the `chroot` operation in Linux operating +/// systems. Such a modified file system cannot name or access files outside of +/// the designated directory tree. +/// +/// ## Example use: +/// ```dart +/// // Create a "file system" where the root directory is /tmp/some-dir. +/// var fs = ChrootFileSystem(existingFileSystem, '/tmp/some-dir'); +/// ``` +/// +/// **Notes on usage**: +/// +/// * This file system maintains its _own_ [currentDirectory], distinct from +/// that of the underlying file system, and new instances automatically start +/// at the root (i.e. `/`). +/// +/// * This file system does _not_ leverage any underlying OS system calls (such +/// as `chroot` itself), so the developer needs to take care to not assume any +/// more of a secure environment than is actually provided. For instance, the +/// underlying system is available via the [delegate] - which underscores this +/// file system is intended to be a convenient abstraction, not a security +/// measure. +/// +/// * This file system _necessarily_ carries certain performance overhead due +/// to the fact that symbolic links are resolved manually (not delegated). +class ChrootFileSystem extends FileSystem { + /// Creates a new file system backed by [root] path in [delegate] file system. + /// + /// **NOTE**: [root] must be a _canonicalized_ path; see [p.canonicalize]. + ChrootFileSystem(this.delegate, this.root) { + if (root != delegate.path.canonicalize(root)) { + throw ArgumentError.value(root, 'root', 'Must be canonical path'); + } + _cwd = _localRoot; + } + + /// Underlying file system. + final FileSystem delegate; + + /// Directory in [delegate] file system that is treated as the root here. + final String root; + + String? _systemTemp; + + /// Path to the synthetic current working directory in this file system. + late String _cwd; + + /// Gets the root path, as seen by entities in this file system. + String get _localRoot => delegate.path.rootPrefix(root); + + @override + Directory directory(dynamic path) => _ChrootDirectory(this, getPath(path)); + + @override + File file(dynamic path) => _ChrootFile(this, getPath(path)); + + @override + Link link(dynamic path) => _ChrootLink(this, getPath(path)); + + @override + p.Context get path => p.Context(style: delegate.path.style, current: _cwd); + + /// Gets the system temp directory. This directory will be created on-demand + /// in the local root of the file system. Once created, its location is fixed + /// for the life of the process. + @override + Directory get systemTempDirectory { + _systemTemp ??= directory(_localRoot).createTempSync('.tmp_').path; + return directory(_systemTemp)..createSync(); + } + + /// Creates a directory object pointing to the current working directory. + /// + /// **NOTE** This does _not_ proxy to the underlying file system's current + /// directory in any way; the state of this file system's current directory + /// is local to this file system. + @override + Directory get currentDirectory => directory(_cwd); + + /// Sets the current working directory to the specified [path]. + /// + /// **NOTE** This does _not_ proxy to the underlying file system's current + /// directory in any way; the state of this file system's current directory + /// is local to this file system. + /// Gets the path context for this file system given the current working dir. + + @override + set currentDirectory(dynamic path) { + String value; + if (path is io.Directory) { + value = path.path; + } else if (path is String) { + value = path; + } else { + throw ArgumentError('Invalid type for "path": ${path?.runtimeType}'); + } + + value = _resolve(value, notFound: _NotFoundBehavior.throwError); + String realPath = _real(value, resolve: false); + switch (delegate.typeSync(realPath, followLinks: false)) { + case FileSystemEntityType.directory: + break; + case FileSystemEntityType.notFound: + throw common.noSuchFileOrDirectory(path as String); + default: + throw common.notADirectory(path as String); + } + assert(() { + p.Context ctx = delegate.path; + return ctx.isAbsolute(value) && value == ctx.canonicalize(value); + }()); + _cwd = value; + } + + @override + Future<FileStat> stat(String path) { + try { + path = _resolve(path); + } on FileSystemException { + return Future<FileStat>.value(const _NotFoundFileStat()); + } + return delegate.stat(_real(path, resolve: false)); + } + + @override + FileStat statSync(String path) { + try { + path = _resolve(path); + } on FileSystemException { + return const _NotFoundFileStat(); + } + return delegate.statSync(_real(path, resolve: false)); + } + + @override + Future<bool> identical(String path1, String path2) => delegate.identical( + _real(_resolve(path1, followLinks: false)), + _real(_resolve(path2, followLinks: false)), + ); + + @override + bool identicalSync(String path1, String path2) => delegate.identicalSync( + _real(_resolve(path1, followLinks: false)), + _real(_resolve(path2, followLinks: false)), + ); + + @override + bool get isWatchSupported => false; + + @override + Future<FileSystemEntityType> type(String path, {bool followLinks = true}) { + String realPath; + try { + realPath = _real(path, followLinks: followLinks); + } on FileSystemException { + return Future<FileSystemEntityType>.value(FileSystemEntityType.notFound); + } + return delegate.type(realPath, followLinks: false); + } + + @override + FileSystemEntityType typeSync(String path, {bool followLinks = true}) { + String realPath; + try { + realPath = _real(path, followLinks: followLinks); + } on FileSystemException { + return FileSystemEntityType.notFound; + } + return delegate.typeSync(realPath, followLinks: false); + } + + /// Converts a [realPath] in the underlying file system to a local path here. + /// + /// If [relative] is set to `true`, then the resulting path will be relative + /// to [currentDirectory], otherwise the resulting path will be absolute. + /// + /// An exception is thrown if the path is outside of this file system's root + /// directory unless [keepInJail] is true, in which case this will instead + /// return the path of the root of this file system. + String _local( + String realPath, { + bool relative = false, + bool keepInJail = false, + }) { + assert(path.isAbsolute(realPath)); + if (!realPath.startsWith(root)) { + if (keepInJail) { + return _localRoot; + } + throw _ChrootJailException(); + } + // TODO(tvolkert): See if _context.relative() works here + String result = realPath.substring(root.length); + if (result.isEmpty) { + result = _localRoot; + } + if (relative) { + assert(result.startsWith(_cwd)); + result = path.relative(result, from: _cwd); + } + return result; + } + + /// Converts [localPath] in this file system to the real path in the delegate. + /// + /// The returned path will always be absolute. + /// + /// If [resolve] is true, symbolic links will be resolved in the local file + /// system _before_ converting the path to the delegate file system's + /// namespace, and if the tail element of the path is a symbolic link, it will + /// only be resolved if [followLinks] is true (where-as symbolic links found + /// in the middle of the path will always be resolved). + String _real( + String localPath, { + bool resolve = true, + bool followLinks = false, + }) { + if (resolve) { + localPath = _resolve(localPath, followLinks: followLinks); + } else { + assert(path.isAbsolute(localPath)); + } + return '$root$localPath'; + } + + /// Resolves symbolic links on [path] and returns the resulting resolved path. + /// + /// The return value will always be an absolute path; if [path] is relative + /// it will be interpreted relative to [from] (or [currentDirectory] if + /// `null`). + /// + /// If the tail element is a symbolic link, then the link will be resolved + /// only if [followLinks] is `true`. Symbolic links found in the middle of + /// the path will always be resolved. + /// + /// If the path cannot be resolved, and [notFound] is: + /// - [_NotFoundBehavior.throwError]: a [FileSystemException] is thrown. + /// - [_NotFoundBehavior.mkdir]: the path will be created as needed. + /// - [_NotFoundBehavior.allowAtTail]: a [FileSystemException] is thrown, + /// unless only the *tail* path element cannot be resolved, in which case + /// the resolution will halt at the tail element, and the partially + /// resolved path will be returned. + /// - [_NotFoundBehavior.allow] (the default), the resolution will halt and + /// the partially resolved path will be returned. + String _resolve( + String path, { + String? from, + bool followLinks = true, + _NotFoundBehavior notFound = _NotFoundBehavior.allow, + }) { + if (path.isEmpty) { + throw common.noSuchFileOrDirectory(path); + } + + p.Context ctx = this.path; + String root = _localRoot; + List<String> parts, ledger; + if (ctx.isAbsolute(path)) { + parts = ctx.split(path).sublist(1); + ledger = <String>[]; + } else { + from ??= _cwd; + assert(ctx.isAbsolute(from)); + parts = ctx.split(path); + ledger = ctx.split(from).sublist(1); + } + + String getCurrentPath() => root + ctx.joinAll(ledger); + Set<String> breadcrumbs = <String>{}; + while (parts.isNotEmpty) { + String segment = parts.removeAt(0); + if (segment == _thisDir) { + continue; + } else if (segment == _parentDir) { + if (ledger.isNotEmpty) { + ledger.removeLast(); + } + continue; + } + + ledger.add(segment); + String currentPath = getCurrentPath(); + String realPath = _real(currentPath, resolve: false); + + switch (delegate.typeSync(realPath, followLinks: false)) { + case FileSystemEntityType.directory: + breadcrumbs.clear(); + break; + case FileSystemEntityType.file: + breadcrumbs.clear(); + if (parts.isNotEmpty) { + throw common.notADirectory(currentPath); + } + break; + case FileSystemEntityType.notFound: + String returnEarly() { + ledger.addAll(parts); + return getCurrentPath(); + } + + switch (notFound) { + case _NotFoundBehavior.mkdir: + if (parts.isNotEmpty) { + delegate.directory(realPath).createSync(); + } + break; + case _NotFoundBehavior.allow: + return returnEarly(); + case _NotFoundBehavior.allowAtTail: + if (parts.isEmpty) { + return returnEarly(); + } + throw common.noSuchFileOrDirectory(path); + case _NotFoundBehavior.throwError: + throw common.noSuchFileOrDirectory(path); + } + break; + case FileSystemEntityType.link: + if (parts.isEmpty && !followLinks) { + break; + } + if (!breadcrumbs.add(currentPath)) { + throw common.tooManyLevelsOfSymbolicLinks(path); + } + String target = delegate.link(realPath).targetSync(); + if (ctx.isAbsolute(target)) { + ledger.clear(); + parts.insertAll(0, ctx.split(target).sublist(1)); + } else { + ledger.removeLast(); + parts.insertAll(0, ctx.split(target)); + } + break; + default: + throw AssertionError(); + } + } + + return getCurrentPath(); + } +} + +/// Thrown when a path is encountered that exists outside of the root path. +class _ChrootJailException implements IOException {} + +/// What to do when `NOT_FOUND` paths are encountered while resolving. +enum _NotFoundBehavior { + allow, + allowAtTail, + throwError, + mkdir, +} + +/// A [FileStat] representing a `NOT_FOUND` entity. +class _NotFoundFileStat implements FileStat { + const _NotFoundFileStat(); + + static final DateTime _empty = DateTime(0); + + @override + DateTime get changed => _empty; + + @override + DateTime get modified => _empty; + + @override + DateTime get accessed => _empty; + + @override + FileSystemEntityType get type => FileSystemEntityType.notFound; + + @override + int get mode => 0; + + @override + int get size => -1; + + @override + String modeString() => '---------'; +}
diff --git a/pkgs/file/lib/src/backends/chroot/chroot_file_system_entity.dart b/pkgs/file/lib/src/backends/chroot/chroot_file_system_entity.dart new file mode 100644 index 0000000..8e859ac --- /dev/null +++ b/pkgs/file/lib/src/backends/chroot/chroot_file_system_entity.dart
@@ -0,0 +1,169 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of file.src.backends.chroot; + +abstract class _ChrootFileSystemEntity<T extends FileSystemEntity, + D extends io.FileSystemEntity> extends ForwardingFileSystemEntity<T, D> { + _ChrootFileSystemEntity(this.fileSystem, this.path); + + @override + final ChrootFileSystem fileSystem; + + @override + final String path; + + @override + String get dirname => fileSystem.path.dirname(path); + + @override + String get basename => fileSystem.path.basename(path); + + @override + D get delegate => getDelegate(); + + /// Gets the delegate file system entity in the underlying file system that + /// corresponds to this entity's local file system path. + /// + /// If [followLinks] is true and this entity's path references a symbolic + /// link, then the path of the delegate entity will reference the ultimate + /// target of that symbolic link. Symbolic links in the middle of the path + /// will always be resolved in the delegate entity's path. + D getDelegate({bool followLinks = false}) => + _rawDelegate(fileSystem._real(path, followLinks: followLinks)); + + /// Returns the expected type of this entity, which may differ from the type + /// of the entity that's found at the path specified by this entity. + FileSystemEntityType get expectedType; + + /// Returns a delegate entity at the specified [realPath] (the path in the + /// underlying file system). + D _rawDelegate(String realPath); + + /// Gets the path of this entity as an absolute path (unchanged if the + /// entity already specifies an absolute path). + String get _absolutePath => fileSystem.path.absolute(path); + + /// Tells whether this entity's path references a symbolic link. + bool get _isLink => + fileSystem.typeSync(path, followLinks: false) == + FileSystemEntityType.link; + + @override + Directory wrapDirectory(io.Directory delegate) => + _ChrootDirectory.wrapped(fileSystem, delegate as Directory, + relative: !isAbsolute); + + @override + File wrapFile(io.File delegate) => + _ChrootFile.wrapped(fileSystem, delegate, relative: !isAbsolute); + + @override + Link wrapLink(io.Link delegate) => + _ChrootLink.wrapped(fileSystem, delegate, relative: !isAbsolute); + + @override + Uri get uri => Uri.file(path); + + @override + Future<bool> exists() => getDelegate(followLinks: true).exists(); + + @override + bool existsSync() => getDelegate(followLinks: true).existsSync(); + + @override + Future<String> resolveSymbolicLinks() async => resolveSymbolicLinksSync(); + + @override + String resolveSymbolicLinksSync() => + fileSystem._resolve(path, notFound: _NotFoundBehavior.throwError); + + @override + Future<FileStat> stat() { + D delegate; + try { + delegate = getDelegate(followLinks: true); + } on FileSystemException { + return Future<FileStat>.value(const _NotFoundFileStat()); + } + return delegate.stat(); + } + + @override + FileStat statSync() { + D delegate; + try { + delegate = getDelegate(followLinks: true); + } on FileSystemException { + return const _NotFoundFileStat(); + } + return delegate.statSync(); + } + + @override + Future<T> delete({bool recursive = false}) async { + String path = fileSystem._resolve(this.path, + followLinks: false, notFound: _NotFoundBehavior.throwError); + + String real(String path) => fileSystem._real(path, resolve: false); + Future<FileSystemEntityType> type(String path) => + fileSystem.delegate.type(real(path), followLinks: false); + + if (await type(path) == FileSystemEntityType.link) { + if (expectedType == FileSystemEntityType.link) { + await fileSystem.delegate.link(real(path)).delete(); + } else { + String resolvedPath = fileSystem._resolve(p.basename(path), + from: p.dirname(path), notFound: _NotFoundBehavior.allowAtTail); + if (!recursive && await type(resolvedPath) != expectedType) { + throw expectedType == FileSystemEntityType.file + ? common.isADirectory(path) + : common.notADirectory(path); + } + await fileSystem.delegate.link(real(path)).delete(); + } + return this as T; + } else { + return wrap( + await _rawDelegate(real(path)).delete(recursive: recursive) as D); + } + } + + @override + void deleteSync({bool recursive = false}) { + String path = fileSystem._resolve(this.path, + followLinks: false, notFound: _NotFoundBehavior.throwError); + + String real(String path) => fileSystem._real(path, resolve: false); + FileSystemEntityType type(String path) => + fileSystem.delegate.typeSync(real(path), followLinks: false); + + if (type(path) == FileSystemEntityType.link) { + if (expectedType == FileSystemEntityType.link) { + fileSystem.delegate.link(real(path)).deleteSync(); + } else { + String resolvedPath = fileSystem._resolve(p.basename(path), + from: p.dirname(path), notFound: _NotFoundBehavior.allowAtTail); + if (!recursive && type(resolvedPath) != expectedType) { + throw expectedType == FileSystemEntityType.file + ? common.isADirectory(path) + : common.notADirectory(path); + } + fileSystem.delegate.link(real(path)).deleteSync(); + } + } else { + _rawDelegate(real(path)).deleteSync(recursive: recursive); + } + } + + @override + Stream<FileSystemEvent> watch({ + int events = FileSystemEvent.all, + bool recursive = false, + }) => + throw UnsupportedError('watch is not supported on ChrootFileSystem'); + + @override + bool get isAbsolute => fileSystem.path.isAbsolute(path); +}
diff --git a/pkgs/file/lib/src/backends/chroot/chroot_link.dart b/pkgs/file/lib/src/backends/chroot/chroot_link.dart new file mode 100644 index 0000000..acbeda6 --- /dev/null +++ b/pkgs/file/lib/src/backends/chroot/chroot_link.dart
@@ -0,0 +1,47 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of file.src.backends.chroot; + +class _ChrootLink extends _ChrootFileSystemEntity<Link, io.Link> + with ForwardingLink { + _ChrootLink(ChrootFileSystem fs, String path) : super(fs, path); + + factory _ChrootLink.wrapped( + ChrootFileSystem fs, + io.Link delegate, { + bool relative = false, + }) { + String localPath = fs._local(delegate.path, relative: relative); + return _ChrootLink(fs, localPath); + } + + @override + Future<bool> exists() => delegate.exists(); + + @override + bool existsSync() => delegate.existsSync(); + + @override + Future<Link> rename(String newPath) async { + return wrap(await delegate.rename(fileSystem._real(newPath))); + } + + @override + Link renameSync(String newPath) { + return wrap(delegate.renameSync(fileSystem._real(newPath))); + } + + @override + FileSystemEntityType get expectedType => FileSystemEntityType.link; + + @override + io.Link _rawDelegate(String path) => fileSystem.delegate.link(path); + + @override + Link get absolute => _ChrootLink(fileSystem, _absolutePath); + + @override + String toString() => "ChrootLink: '$path'"; +}
diff --git a/pkgs/file/lib/src/backends/chroot/chroot_random_access_file.dart b/pkgs/file/lib/src/backends/chroot/chroot_random_access_file.dart new file mode 100644 index 0000000..4105ac8 --- /dev/null +++ b/pkgs/file/lib/src/backends/chroot/chroot_random_access_file.dart
@@ -0,0 +1,15 @@ +// Copyright (c) 2020, 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. + +part of file.src.backends.chroot; + +class _ChrootRandomAccessFile with ForwardingRandomAccessFile { + _ChrootRandomAccessFile(this.path, this.delegate); + + @override + final io.RandomAccessFile delegate; + + @override + final String path; +}
diff --git a/pkgs/file/lib/src/backends/local.dart b/pkgs/file/lib/src/backends/local.dart new file mode 100644 index 0000000..1e92241 --- /dev/null +++ b/pkgs/file/lib/src/backends/local.dart
@@ -0,0 +1,5 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +export 'local/local_file_system.dart' show LocalFileSystem;
diff --git a/pkgs/file/lib/src/backends/local/local_directory.dart b/pkgs/file/lib/src/backends/local/local_directory.dart new file mode 100644 index 0000000..e23e68f --- /dev/null +++ b/pkgs/file/lib/src/backends/local/local_directory.dart
@@ -0,0 +1,20 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:file/file.dart'; +import 'package:file/src/common.dart' as common; +import 'package:file/src/io.dart' as io; + +import 'local_file_system_entity.dart'; + +/// [Directory] implementation that forwards all calls to `dart:io`. +class LocalDirectory extends LocalFileSystemEntity<LocalDirectory, io.Directory> + with ForwardingDirectory<LocalDirectory>, common.DirectoryAddOnsMixin { + /// Instantiates a new [LocalDirectory] tied to the specified file system + /// and delegating to the specified [delegate]. + LocalDirectory(FileSystem fs, io.Directory delegate) : super(fs, delegate); + + @override + String toString() => "LocalDirectory: '$path'"; +}
diff --git a/pkgs/file/lib/src/backends/local/local_file.dart b/pkgs/file/lib/src/backends/local/local_file.dart new file mode 100644 index 0000000..36293ba --- /dev/null +++ b/pkgs/file/lib/src/backends/local/local_file.dart
@@ -0,0 +1,19 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:file/file.dart'; +import 'package:file/src/io.dart' as io; + +import 'local_file_system_entity.dart'; + +/// [File] implementation that forwards all calls to `dart:io`. +class LocalFile extends LocalFileSystemEntity<File, io.File> + with ForwardingFile { + /// Instantiates a new [LocalFile] tied to the specified file system + /// and delegating to the specified [delegate]. + LocalFile(FileSystem fs, io.File delegate) : super(fs, delegate); + + @override + String toString() => "LocalFile: '$path'"; +}
diff --git a/pkgs/file/lib/src/backends/local/local_file_system.dart b/pkgs/file/lib/src/backends/local/local_file_system.dart new file mode 100644 index 0000000..635998e --- /dev/null +++ b/pkgs/file/lib/src/backends/local/local_file_system.dart
@@ -0,0 +1,72 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:file/src/io.dart' as io; +import 'package:file/file.dart'; +import 'package:path/path.dart' as p; + +import 'local_directory.dart'; +import 'local_file.dart'; +import 'local_link.dart'; + +/// A wrapper implementation around `dart:io`'s implementation. +/// +/// Since this implementation of the [FileSystem] interface delegates to +/// `dart:io`, is is not suitable for use in the browser. +class LocalFileSystem extends FileSystem { + /// Creates a new `LocalFileSystem`. + const LocalFileSystem(); + + @override + Directory directory(dynamic path) => + LocalDirectory(this, io.Directory(getPath(path))); + + @override + File file(dynamic path) => LocalFile(this, io.File(getPath(path))); + + @override + Link link(dynamic path) => LocalLink(this, io.Link(getPath(path))); + + @override + p.Context get path => p.Context(); + + /// Gets the directory provided by the operating system for creating temporary + /// files and directories in. The location of the system temp directory is + /// platform-dependent, and may be set by an environment variable. + @override + Directory get systemTempDirectory => + LocalDirectory(this, io.Directory.systemTemp); + + @override + Directory get currentDirectory => directory(io.Directory.current.path); + + @override + set currentDirectory(dynamic path) => io.Directory.current = path; + + @override + Future<io.FileStat> stat(String path) => io.FileStat.stat(path); + + @override + io.FileStat statSync(String path) => io.FileStat.statSync(path); + + @override + Future<bool> identical(String path1, String path2) => + io.FileSystemEntity.identical(path1, path2); + + @override + bool identicalSync(String path1, String path2) => + io.FileSystemEntity.identicalSync(path1, path2); + + @override + bool get isWatchSupported => io.FileSystemEntity.isWatchSupported; + + @override + Future<io.FileSystemEntityType> type(String path, + {bool followLinks = true}) => + io.FileSystemEntity.type(path, followLinks: followLinks); + + @override + io.FileSystemEntityType typeSync(String path, {bool followLinks = true}) => + io.FileSystemEntity.typeSync(path, followLinks: followLinks); +}
diff --git a/pkgs/file/lib/src/backends/local/local_file_system_entity.dart b/pkgs/file/lib/src/backends/local/local_file_system_entity.dart new file mode 100644 index 0000000..ca4617b --- /dev/null +++ b/pkgs/file/lib/src/backends/local/local_file_system_entity.dart
@@ -0,0 +1,40 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:file/file.dart'; +import 'package:file/src/io.dart' as io; + +import 'local_directory.dart'; +import 'local_file.dart'; +import 'local_link.dart'; + +/// [FileSystemEntity] implementation that forwards all calls to `dart:io`. +abstract class LocalFileSystemEntity<T extends FileSystemEntity, + D extends io.FileSystemEntity> extends ForwardingFileSystemEntity<T, D> { + /// Instantiates a new [LocalFileSystemEntity] tied to the specified file + /// system and delegating to the specified [delegate]. + LocalFileSystemEntity(this.fileSystem, this.delegate); + + @override + final FileSystem fileSystem; + + @override + final D delegate; + + @override + String get dirname => fileSystem.path.dirname(path); + + @override + String get basename => fileSystem.path.basename(path); + + @override + Directory wrapDirectory(io.Directory delegate) => + LocalDirectory(fileSystem, delegate); + + @override + File wrapFile(io.File delegate) => LocalFile(fileSystem, delegate); + + @override + Link wrapLink(io.Link delegate) => LocalLink(fileSystem, delegate); +}
diff --git a/pkgs/file/lib/src/backends/local/local_link.dart b/pkgs/file/lib/src/backends/local/local_link.dart new file mode 100644 index 0000000..fc67d5e --- /dev/null +++ b/pkgs/file/lib/src/backends/local/local_link.dart
@@ -0,0 +1,19 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:file/file.dart'; +import 'package:file/src/io.dart' as io; + +import 'local_file_system_entity.dart'; + +/// [Link] implementation that forwards all calls to `dart:io`. +class LocalLink extends LocalFileSystemEntity<Link, io.Link> + with ForwardingLink { + /// Instantiates a new [LocalLink] tied to the specified file system + /// and delegating to the specified [delegate]. + LocalLink(FileSystem fs, io.Link delegate) : super(fs, delegate); + + @override + String toString() => "LocalLink: '$path'"; +}
diff --git a/pkgs/file/lib/src/backends/memory.dart b/pkgs/file/lib/src/backends/memory.dart new file mode 100644 index 0000000..428bc54 --- /dev/null +++ b/pkgs/file/lib/src/backends/memory.dart
@@ -0,0 +1,6 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +export 'memory/memory_file_system.dart' show MemoryFileSystem; +export 'memory/style.dart' show FileSystemStyle, StyleableFileSystem;
diff --git a/pkgs/file/lib/src/backends/memory/clock.dart b/pkgs/file/lib/src/backends/memory/clock.dart new file mode 100644 index 0000000..98d5434 --- /dev/null +++ b/pkgs/file/lib/src/backends/memory/clock.dart
@@ -0,0 +1,52 @@ +// Copyright (c) 2018, 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. + +/// Interface describing clocks used by the [MemoryFileSystem]. +/// +/// The [MemoryFileSystem] uses a clock to determine the modification times of +/// files that are created in that file system. +abstract class Clock { + /// Abstract const constructor. This constructor enables subclasses to provide + /// const constructors so that they can be used in const expressions. + const Clock(); + + /// A real-time clock. + /// + /// Uses [DateTime.now] to reflect the actual time reported by the operating + /// system. + const factory Clock.realTime() = _RealtimeClock; + + /// A monotonically-increasing test clock. + /// + /// Each time [now] is called, the time increases by one minute. + /// + /// The `start` argument can be used to set the seed time for the clock. + /// The first value will be that time plus one minute. + /// By default, `start` is midnight on the first of January, 2000. + factory Clock.monotonicTest() = _MonotonicTestClock; + + /// Returns the value of the clock. + DateTime get now; +} + +class _RealtimeClock extends Clock { + const _RealtimeClock(); + + @override + DateTime get now => DateTime.now(); +} + +class _MonotonicTestClock extends Clock { + _MonotonicTestClock({ + DateTime? start, + }) : _current = start ?? DateTime(2000); + + DateTime _current; + + @override + DateTime get now { + _current = _current.add(const Duration(minutes: 1)); + return _current; + } +}
diff --git a/pkgs/file/lib/src/backends/memory/common.dart b/pkgs/file/lib/src/backends/memory/common.dart new file mode 100644 index 0000000..80e3c38 --- /dev/null +++ b/pkgs/file/lib/src/backends/memory/common.dart
@@ -0,0 +1,15 @@ +// Copyright (c) 2018, 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/src/common.dart' as common; + +/// Generates a path to use in error messages. +typedef PathGenerator = dynamic Function(); + +/// Throws a `FileSystemException` if [object] is null. +void checkExists(Object? object, PathGenerator path) { + if (object == null) { + throw common.noSuchFileOrDirectory(path() as String); + } +}
diff --git a/pkgs/file/lib/src/backends/memory/memory_directory.dart b/pkgs/file/lib/src/backends/memory/memory_directory.dart new file mode 100644 index 0000000..95fe542 --- /dev/null +++ b/pkgs/file/lib/src/backends/memory/memory_directory.dart
@@ -0,0 +1,184 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:file/file.dart'; +import 'package:file/src/common.dart' as common; +import 'package:file/src/io.dart' as io; +import 'package:meta/meta.dart'; + +import 'common.dart'; +import 'memory_file.dart'; +import 'memory_file_system_entity.dart'; +import 'memory_link.dart'; +import 'node.dart'; +import 'operations.dart'; +import 'style.dart'; +import 'utils.dart' as utils; + +// Tracks a unique name for system temp directories, per filesystem +// instance. +final Expando<int> _systemTempCounter = Expando<int>(); + +/// Internal implementation of [Directory]. +class MemoryDirectory extends MemoryFileSystemEntity + with common.DirectoryAddOnsMixin + implements Directory { + /// Instantiates a new [MemoryDirectory]. + MemoryDirectory(NodeBasedFileSystem fileSystem, String path) + : super(fileSystem, path); + + @override + io.FileSystemEntityType get expectedType => io.FileSystemEntityType.directory; + + @override + Uri get uri { + return Uri.directory(path, + windows: fileSystem.style == FileSystemStyle.windows); + } + + @override + bool existsSync() { + fileSystem.opHandle.call(path, FileSystemOp.exists); + return backingOrNull?.stat.type == expectedType; + } + + @override + Future<Directory> create({bool recursive = false}) async { + createSync(recursive: recursive); + return this; + } + + @override + void createSync({bool recursive = false}) { + fileSystem.opHandle(path, FileSystemOp.create); + Node? node = internalCreateSync( + followTailLink: true, + visitLinks: true, + createChild: (DirectoryNode parent, bool isFinalSegment) { + if (recursive || isFinalSegment) { + return DirectoryNode(parent); + } + return null; + }, + ); + if (node?.type != expectedType) { + // There was an existing non-directory node at this object's path + throw common.notADirectory(path); + } + } + + @override + Future<Directory> createTemp([String? prefix]) async => + createTempSync(prefix); + + @override + Directory createTempSync([String? prefix]) { + prefix = '${prefix ?? ''}rand'; + String fullPath = fileSystem.path.join(path, prefix); + String dirname = fileSystem.path.dirname(fullPath); + String basename = fileSystem.path.basename(fullPath); + DirectoryNode? node = fileSystem.findNode(dirname) as DirectoryNode?; + checkExists(node, () => dirname); + utils.checkIsDir(node!, () => dirname); + int tempCounter = _systemTempCounter[fileSystem] ?? 0; + String name() => '$basename$tempCounter'; + while (node.children.containsKey(name())) { + tempCounter++; + } + _systemTempCounter[fileSystem] = tempCounter; + DirectoryNode tempDir = DirectoryNode(node); + node.children[name()] = tempDir; + return MemoryDirectory(fileSystem, fileSystem.path.join(dirname, name())) + ..createSync(); + } + + @override + Future<Directory> rename(String newPath) async => renameSync(newPath); + + @override + Directory renameSync(String newPath) => internalRenameSync<DirectoryNode>( + newPath, + validateOverwriteExistingEntity: (DirectoryNode existingNode) { + if (existingNode.children.isNotEmpty) { + throw common.directoryNotEmpty(newPath); + } + }, + ) as Directory; + + @override + Directory get parent => + (backingOrNull?.isRoot ?? false) ? this : super.parent; + + @override + Directory get absolute => super.absolute as Directory; + + @override + Stream<FileSystemEntity> list({ + bool recursive = false, + bool followLinks = true, + }) => + Stream<FileSystemEntity>.fromIterable(listSync( + recursive: recursive, + followLinks: followLinks, + )); + + @override + List<FileSystemEntity> listSync({ + bool recursive = false, + bool followLinks = true, + }) { + DirectoryNode node = backing as DirectoryNode; + List<FileSystemEntity> listing = <FileSystemEntity>[]; + List<_PendingListTask> tasks = <_PendingListTask>[ + _PendingListTask( + node, + path.endsWith(fileSystem.path.separator) + ? path.substring(0, path.length - 1) + : path, + <LinkNode>{}, + ), + ]; + while (tasks.isNotEmpty) { + _PendingListTask task = tasks.removeLast(); + task.dir.children.forEach((String name, Node child) { + Set<LinkNode> breadcrumbs = Set<LinkNode>.from(task.breadcrumbs); + String childPath = fileSystem.path.join(task.path, name); + while (followLinks && + utils.isLink(child) && + breadcrumbs.add(child as LinkNode)) { + Node? referent = child.referentOrNull; + if (referent != null) { + child = referent; + } + } + if (utils.isDirectory(child)) { + listing.add(MemoryDirectory(fileSystem, childPath)); + if (recursive) { + tasks.add(_PendingListTask( + child as DirectoryNode, childPath, breadcrumbs)); + } + } else if (utils.isLink(child)) { + listing.add(MemoryLink(fileSystem, childPath)); + } else if (utils.isFile(child)) { + listing.add(MemoryFile(fileSystem, childPath)); + } + }); + } + return listing; + } + + @override + @protected + Directory clone(String path) => MemoryDirectory(fileSystem, path); + + @override + String toString() => "MemoryDirectory: '$path'"; +} + +class _PendingListTask { + _PendingListTask(this.dir, this.path, this.breadcrumbs); + final DirectoryNode dir; + final String path; + final Set<LinkNode> breadcrumbs; +}
diff --git a/pkgs/file/lib/src/backends/memory/memory_file.dart b/pkgs/file/lib/src/backends/memory/memory_file.dart new file mode 100644 index 0000000..ba4faab --- /dev/null +++ b/pkgs/file/lib/src/backends/memory/memory_file.dart
@@ -0,0 +1,470 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:convert'; +import 'dart:math' as math show min; +import 'dart:typed_data'; + +import 'package:file/file.dart'; +import 'package:file/src/backends/memory/operations.dart'; +import 'package:file/src/common.dart' as common; +import 'package:file/src/io.dart' as io; +import 'package:meta/meta.dart'; + +import 'common.dart'; +import 'memory_file_system_entity.dart'; +import 'memory_random_access_file.dart'; +import 'node.dart'; +import 'utils.dart' as utils; + +/// Internal implementation of [File]. +class MemoryFile extends MemoryFileSystemEntity implements File { + /// Instantiates a new [MemoryFile]. + const MemoryFile(NodeBasedFileSystem fileSystem, String path) + : super(fileSystem, path); + + FileNode get _resolvedBackingOrCreate { + Node? node = backingOrNull; + if (node == null) { + node = _doCreate(); + } else { + node = utils.isLink(node) + ? utils.resolveLinks(node as LinkNode, () => path) + : node; + utils.checkType(expectedType, node.type, () => path); + } + return node as FileNode; + } + + @override + io.FileSystemEntityType get expectedType => io.FileSystemEntityType.file; + + @override + bool existsSync() { + fileSystem.opHandle.call(path, FileSystemOp.exists); + return backingOrNull?.stat.type == expectedType; + } + + @override + Future<File> create({bool recursive = false, bool exclusive = false}) async { + createSync(recursive: recursive, exclusive: exclusive); + return this; + } + + // TODO(dartbug.com/49647): Pass `exclusive` through after it lands. + @override + void createSync({bool recursive = false, bool exclusive = false}) { + fileSystem.opHandle(path, FileSystemOp.create); + _doCreate(recursive: recursive /*, exclusive: exclusive*/); + } + + Node? _doCreate({bool recursive = false}) { + Node? node = internalCreateSync( + followTailLink: true, + createChild: (DirectoryNode parent, bool isFinalSegment) { + if (isFinalSegment) { + return FileNode(parent); + } else if (recursive) { + return DirectoryNode(parent); + } + return null; + }, + ); + if (node?.type != expectedType) { + // There was an existing non-file entity at this object's path + assert(node?.type == FileSystemEntityType.directory); + throw common.isADirectory(path); + } + return node; + } + + @override + Future<File> rename(String newPath) async => renameSync(newPath); + + @override + File renameSync(String newPath) => internalRenameSync( + newPath, + followTailLink: true, + checkType: (Node node) { + FileSystemEntityType actualType = node.stat.type; + if (actualType != expectedType) { + throw actualType == FileSystemEntityType.notFound + ? common.noSuchFileOrDirectory(path) + : common.isADirectory(path); + } + }, + ) as File; + + @override + Future<File> copy(String newPath) async => copySync(newPath); + + @override + File copySync(String newPath) { + fileSystem.opHandle(path, FileSystemOp.copy); + FileNode sourceNode = resolvedBacking as FileNode; + fileSystem.findNode( + newPath, + segmentVisitor: ( + DirectoryNode parent, + String childName, + Node? child, + int currentSegment, + int finalSegment, + ) { + if (currentSegment == finalSegment) { + if (child != null) { + if (utils.isLink(child)) { + List<String> ledger = <String>[]; + child = utils.resolveLinks(child as LinkNode, () => newPath, + ledger: ledger); + checkExists(child, () => newPath); + parent = child.parent; + childName = ledger.last; + assert(parent.children.containsKey(childName)); + } + utils.checkType(expectedType, child.type, () => newPath); + parent.children.remove(childName); + } + FileNode newNode = FileNode(parent); + newNode.copyFrom(sourceNode); + parent.children[childName] = newNode; + } + return child; + }, + ); + return clone(newPath); + } + + @override + Future<int> length() async => lengthSync(); + + @override + int lengthSync() => (resolvedBacking as FileNode).size; + + @override + File get absolute => super.absolute as File; + + @override + Future<DateTime> lastAccessed() async => lastAccessedSync(); + + @override + DateTime lastAccessedSync() => (resolvedBacking as FileNode).stat.accessed; + + @override + Future<dynamic> setLastAccessed(DateTime time) async => + setLastAccessedSync(time); + + @override + void setLastAccessedSync(DateTime time) { + FileNode node = resolvedBacking as FileNode; + node.accessed = time.millisecondsSinceEpoch; + } + + @override + Future<DateTime> lastModified() async => lastModifiedSync(); + + @override + DateTime lastModifiedSync() => (resolvedBacking as FileNode).stat.modified; + + @override + Future<dynamic> setLastModified(DateTime time) async => + setLastModifiedSync(time); + + @override + void setLastModifiedSync(DateTime time) { + FileNode node = resolvedBacking as FileNode; + node.modified = time.millisecondsSinceEpoch; + } + + @override + Future<io.RandomAccessFile> open( + {io.FileMode mode = io.FileMode.read}) async => + openSync(mode: mode); + + @override + io.RandomAccessFile openSync({io.FileMode mode = io.FileMode.read}) { + fileSystem.opHandle(path, FileSystemOp.open); + if (utils.isWriteMode(mode) && !existsSync()) { + // [resolvedBacking] requires that the file already exists, so we must + // create it here first. + createSync(); + } + + return MemoryRandomAccessFile(path, resolvedBacking as FileNode, mode); + } + + @override + Stream<List<int>> openRead([int? start, int? end]) { + fileSystem.opHandle(path, FileSystemOp.open); + try { + FileNode node = resolvedBacking as FileNode; + Uint8List content = node.content; + if (start != null) { + content = end == null + ? content.sublist(start) + : content.sublist(start, math.min(end, content.length)); + } + return Stream.value(content); + } catch (e) { + return Stream.error(e); + } + } + + @override + io.IOSink openWrite({ + io.FileMode mode = io.FileMode.write, + Encoding encoding = utf8, + }) { + fileSystem.opHandle(path, FileSystemOp.open); + if (!utils.isWriteMode(mode)) { + throw ArgumentError.value(mode, 'mode', + 'Must be either WRITE, APPEND, WRITE_ONLY, or WRITE_ONLY_APPEND'); + } + return _FileSink.fromFile(this, mode, encoding); + } + + @override + Future<Uint8List> readAsBytes() async => readAsBytesSync(); + + @override + Uint8List readAsBytesSync() { + fileSystem.opHandle(path, FileSystemOp.read); + return Uint8List.fromList((resolvedBacking as FileNode).content); + } + + @override + Future<String> readAsString({Encoding encoding = utf8}) async => + readAsStringSync(encoding: encoding); + + @override + String readAsStringSync({Encoding encoding = utf8}) { + try { + return encoding.decode(readAsBytesSync()); + } on FormatException catch (err) { + throw FileSystemException(err.message, path); + } + } + + @override + Future<List<String>> readAsLines({Encoding encoding = utf8}) async => + readAsLinesSync(encoding: encoding); + + @override + List<String> readAsLinesSync({Encoding encoding = utf8}) { + String str = readAsStringSync(encoding: encoding); + + if (str.isEmpty) { + return <String>[]; + } + + final List<String> lines = str.split('\n'); + if (str.endsWith('\n')) { + // A final newline should not create an additional line. + lines.removeLast(); + } + + return lines; + } + + @override + Future<File> writeAsBytes( + List<int> bytes, { + io.FileMode mode = io.FileMode.write, + bool flush = false, + }) async { + writeAsBytesSync(bytes, mode: mode, flush: flush); + return this; + } + + @override + void writeAsBytesSync( + List<int> bytes, { + io.FileMode mode = io.FileMode.write, + bool flush = false, + }) { + if (!utils.isWriteMode(mode)) { + throw common.badFileDescriptor(path); + } + FileNode node = _resolvedBackingOrCreate; + _truncateIfNecessary(node, mode); + fileSystem.opHandle(path, FileSystemOp.write); + node.write(bytes); + node.touch(); + } + + @override + Future<File> writeAsString( + String contents, { + io.FileMode mode = io.FileMode.write, + Encoding encoding = utf8, + bool flush = false, + }) async { + writeAsStringSync(contents, mode: mode, encoding: encoding, flush: flush); + return this; + } + + @override + void writeAsStringSync( + String contents, { + io.FileMode mode = io.FileMode.write, + Encoding encoding = utf8, + bool flush = false, + }) => + writeAsBytesSync(encoding.encode(contents), mode: mode, flush: flush); + + @override + @protected + File clone(String path) => MemoryFile(fileSystem, path); + + void _truncateIfNecessary(FileNode node, io.FileMode mode) { + if (mode == io.FileMode.write || mode == io.FileMode.writeOnly) { + node.clear(); + } + } + + @override + String toString() => "MemoryFile: '$path'"; +} + +/// Implementation of an [io.IOSink] that's backed by a [FileNode]. +class _FileSink implements io.IOSink { + factory _FileSink.fromFile( + MemoryFile file, + io.FileMode mode, + Encoding encoding, + ) { + late FileNode node; + Exception? deferredException; + + // Resolve the backing immediately to ensure that the [FileNode] we write + // to is the same as when [openWrite] was called. This can matter if the + // file is moved or removed while open. + try { + node = file._resolvedBackingOrCreate; + } on Exception catch (e) { + // For behavioral consistency with [LocalFile], do not report failures + // immediately. + deferredException = e; + } + + Future<FileNode> future = Future<FileNode>.microtask(() { + if (deferredException != null) { + throw deferredException; + } + file._truncateIfNecessary(node, mode); + return node; + }); + return _FileSink._(future, encoding); + } + + _FileSink._(Future<FileNode> node, this.encoding) : _pendingWrites = node; + + final Completer<void> _completer = Completer<void>(); + + Future<FileNode> _pendingWrites; + Completer<void>? _streamCompleter; + bool _isClosed = false; + + @override + Encoding encoding; + + bool get isStreaming => !(_streamCompleter?.isCompleted ?? true); + + @override + void add(List<int> data) { + _checkNotStreaming(); + if (_isClosed) { + throw StateError('StreamSink is closed'); + } + + _addData(data); + } + + @override + void write(Object? obj) => add(encoding.encode(obj?.toString() ?? 'null')); + + @override + void writeAll(Iterable<dynamic> objects, [String separator = '']) { + bool firstIter = true; + for (dynamic obj in objects) { + if (!firstIter) { + write(separator); + } + firstIter = false; + write(obj); + } + } + + @override + void writeln([Object? obj = '']) { + write(obj); + write('\n'); + } + + @override + void writeCharCode(int charCode) => write(String.fromCharCode(charCode)); + + @override + void addError(Object error, [StackTrace? stackTrace]) { + _checkNotStreaming(); + _completer.completeError(error, stackTrace); + } + + @override + Future<void> addStream(Stream<List<int>> stream) { + _checkNotStreaming(); + _streamCompleter = Completer<void>(); + + stream.listen( + (List<int> data) => _addData(data), + cancelOnError: true, + onError: (Object error, StackTrace stackTrace) { + _streamCompleter!.completeError(error, stackTrace); + _streamCompleter = null; + }, + onDone: () { + _streamCompleter!.complete(); + _streamCompleter = null; + }, + ); + return _streamCompleter!.future; + } + + @override + Future<void> flush() { + _checkNotStreaming(); + return _pendingWrites; + } + + @override + Future<void> close() { + _checkNotStreaming(); + if (!_isClosed) { + _isClosed = true; + _pendingWrites.then( + (_) => _completer.complete(), + onError: (Object error, StackTrace stackTrace) => + _completer.completeError(error, stackTrace), + ); + } + return _completer.future; + } + + @override + Future<void> get done => _completer.future; + + void _addData(List<int> data) { + _pendingWrites = _pendingWrites.then((FileNode node) { + node.write(data); + return node; + }); + } + + void _checkNotStreaming() { + if (isStreaming) { + throw StateError('StreamSink is bound to a stream'); + } + } +}
diff --git a/pkgs/file/lib/src/backends/memory/memory_file_stat.dart b/pkgs/file/lib/src/backends/memory/memory_file_stat.dart new file mode 100644 index 0000000..94f86d1 --- /dev/null +++ b/pkgs/file/lib/src/backends/memory/memory_file_stat.dart
@@ -0,0 +1,68 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:file/src/io.dart' as io; + +/// Internal implementation of [io.FileStat]. +class MemoryFileStat implements io.FileStat { + /// Creates a new [MemoryFileStat] with the specified properties. + const MemoryFileStat( + this.changed, + this.modified, + this.accessed, + this.type, + this.mode, + this.size, + ); + + MemoryFileStat._internalNotFound() + : changed = DateTime(0), + modified = DateTime(0), + accessed = DateTime(0), + type = io.FileSystemEntityType.notFound, + mode = 0, + size = -1; + + /// Shared instance representing a non-existent entity. + static final MemoryFileStat notFound = MemoryFileStat._internalNotFound(); + + @override + final DateTime changed; + + @override + final DateTime modified; + + @override + final DateTime accessed; + + @override + final io.FileSystemEntityType type; + + @override + final int mode; + + @override + final int size; + + @override + String modeString() { + int permissions = mode & 0xFFF; + List<String> codes = const <String>[ + '---', + '--x', + '-w-', + '-wx', + 'r--', + 'r-x', + 'rw-', + 'rwx', + ]; + List<String> result = <String>[]; + result + ..add(codes[(permissions >> 6) & 0x7]) + ..add(codes[(permissions >> 3) & 0x7]) + ..add(codes[permissions & 0x7]); + return result.join(); + } +}
diff --git a/pkgs/file/lib/src/backends/memory/memory_file_system.dart b/pkgs/file/lib/src/backends/memory/memory_file_system.dart new file mode 100644 index 0000000..f3cdaee --- /dev/null +++ b/pkgs/file/lib/src/backends/memory/memory_file_system.dart
@@ -0,0 +1,282 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:file/file.dart'; +import 'package:file/src/backends/memory/operations.dart'; +import 'package:file/src/io.dart' as io; +import 'package:path/path.dart' as p; + +import 'clock.dart'; +import 'common.dart'; +import 'memory_directory.dart'; +import 'memory_file.dart'; +import 'memory_file_stat.dart'; +import 'memory_link.dart'; +import 'node.dart'; +import 'style.dart'; +import 'utils.dart' as utils; + +const String _thisDir = '.'; +const String _parentDir = '..'; + +void _defaultOpHandle(String context, FileSystemOp operation) {} + +/// An implementation of [FileSystem] that exists entirely in memory with an +/// internal representation loosely based on the Filesystem Hierarchy Standard. +/// +/// [MemoryFileSystem] is suitable for mocking and tests, as well as for +/// caching or staging before writing or reading to a live system. +/// +/// This implementation of the [FileSystem] interface does not directly use +/// any `dart:io` APIs; it merely uses the library's enum values and interfaces. +/// As such, it is suitable for use in the browser. +abstract class MemoryFileSystem implements StyleableFileSystem { + /// Creates a new `MemoryFileSystem`. + /// + /// The file system will be empty, and the current directory will be the + /// root directory. + /// + /// The clock will be a real-time clock; file modification times will + /// reflect the real time as reported by the operating system. + /// + /// If [style] is specified, the file system will use the specified path + /// style. The default is [FileSystemStyle.posix]. + factory MemoryFileSystem({ + FileSystemStyle style = FileSystemStyle.posix, + void Function(String context, FileSystemOp operation) opHandle = + _defaultOpHandle, + }) => + _MemoryFileSystem( + style: style, + clock: const Clock.realTime(), + opHandle: opHandle, + ); + + /// Creates a new `MemoryFileSystem` that has a fake clock. + /// + /// The file system will be empty, and the current directory will be the + /// root directory. + /// + /// The clock will increase monotonically each time it is used, disconnected + /// from any real-world clock. + /// + /// If [style] is specified, the file system will use the specified path + /// style. The default is [FileSystemStyle.posix]. + factory MemoryFileSystem.test({ + FileSystemStyle style = FileSystemStyle.posix, + void Function(String context, FileSystemOp operation) opHandle = + _defaultOpHandle, + }) => + _MemoryFileSystem( + style: style, + clock: Clock.monotonicTest(), + opHandle: opHandle, + ); +} + +/// Internal implementation of [MemoryFileSystem]. +class _MemoryFileSystem extends FileSystem + implements MemoryFileSystem, NodeBasedFileSystem { + _MemoryFileSystem({ + this.style = FileSystemStyle.posix, + required this.clock, + this.opHandle = _defaultOpHandle, + }) : _context = style.contextFor(style.root) { + _root = RootNode(this); + } + + RootNode? _root; + String? _systemTemp; + p.Context _context; + + @override + final Function(String context, FileSystemOp operation) opHandle; + + @override + final Clock clock; + + @override + final FileSystemStyle style; + + @override + RootNode? get root => _root; + + @override + String get cwd => _context.current; + + @override + Directory directory(dynamic path) => MemoryDirectory(this, getPath(path)); + + @override + File file(dynamic path) => MemoryFile(this, getPath(path)); + + @override + Link link(dynamic path) => MemoryLink(this, getPath(path)); + + @override + p.Context get path => _context; + + /// Gets the system temp directory. This directory will be created on-demand + /// in the root of the file system. Once created, its location is fixed for + /// the life of the process. + @override + Directory get systemTempDirectory { + _systemTemp ??= directory(style.root).createTempSync('.tmp_').path; + return directory(_systemTemp)..createSync(); + } + + @override + Directory get currentDirectory => directory(cwd); + + @override + set currentDirectory(dynamic path) { + String value; + if (path is io.Directory) { + value = path.path; + } else if (path is String) { + value = path; + } else { + throw ArgumentError('Invalid type for "path": ${path?.runtimeType}'); + } + + value = directory(value).resolveSymbolicLinksSync(); + Node? node = findNode(value); + checkExists(node, () => value); + utils.checkIsDir(node!, () => value); + assert(_context.isAbsolute(value)); + _context = style.contextFor(value); + } + + @override + Future<io.FileStat> stat(String path) async => statSync(path); + + @override + io.FileStat statSync(String path) { + try { + return findNode(path)?.stat ?? MemoryFileStat.notFound; + } on io.FileSystemException { + return MemoryFileStat.notFound; + } + } + + @override + Future<bool> identical(String path1, String path2) async => + identicalSync(path1, path2); + + @override + bool identicalSync(String path1, String path2) { + Node? node1 = findNode(path1); + checkExists(node1, () => path1); + Node? node2 = findNode(path2); + checkExists(node2, () => path2); + return node1 != null && node1 == node2; + } + + @override + bool get isWatchSupported => false; + + @override + Future<io.FileSystemEntityType> type( + String path, { + bool followLinks = true, + }) async => + typeSync(path, followLinks: followLinks); + + @override + io.FileSystemEntityType typeSync(String path, {bool followLinks = true}) { + Node? node; + try { + node = findNode(path, followTailLink: followLinks); + } on io.FileSystemException { + node = null; + } + if (node == null) { + return io.FileSystemEntityType.notFound; + } + return node.type; + } + + /// Gets the node backing for the current working directory. Note that this + /// can return null if the directory has been deleted or moved from under our + /// feet. + DirectoryNode? get _current => findNode(cwd) as DirectoryNode?; + + @override + Node? findNode( + String path, { + Node? reference, + SegmentVisitor? segmentVisitor, + bool visitLinks = false, + List<String>? pathWithSymlinks, + bool followTailLink = false, + }) { + if (path.isEmpty) { + return null; + } else if (_context.isAbsolute(path)) { + reference = _root; + path = path.substring(style.drive.length); + } else { + reference ??= _current; + } + + List<String> parts = path.split(style.separator) + ..removeWhere(utils.isEmpty); + DirectoryNode? directory = reference?.directory; + Node? child = directory; + + int finalSegment = parts.length - 1; + for (int i = 0; i <= finalSegment; i++) { + String basename = parts[i]; + assert(basename.isNotEmpty); + + switch (basename) { + case _thisDir: + child = directory; + break; + case _parentDir: + child = directory?.parent; + directory = directory?.parent; + break; + default: + child = directory?.children[basename]; + } + + if (pathWithSymlinks != null) { + pathWithSymlinks.add(basename); + } + + // Generates a subpath for the current segment. + String subpath() => parts.sublist(0, i + 1).join(_context.separator); + + if (utils.isLink(child) && (i < finalSegment || followTailLink)) { + if (visitLinks || segmentVisitor == null) { + if (segmentVisitor != null) { + child = + segmentVisitor(directory!, basename, child, i, finalSegment); + } + child = utils.resolveLinks(child as LinkNode, subpath, + ledger: pathWithSymlinks); + } else { + child = utils.resolveLinks( + child as LinkNode, + subpath, + ledger: pathWithSymlinks, + tailVisitor: (DirectoryNode parent, String childName, Node? child) { + return segmentVisitor(parent, childName, child, i, finalSegment); + }, + ); + } + } else if (segmentVisitor != null) { + child = segmentVisitor(directory!, basename, child, i, finalSegment); + } + + if (i < finalSegment) { + checkExists(child, subpath); + utils.checkIsDir(child!, subpath); + directory = child as DirectoryNode; + } + } + return child; + } +}
diff --git a/pkgs/file/lib/src/backends/memory/memory_file_system_entity.dart b/pkgs/file/lib/src/backends/memory/memory_file_system_entity.dart new file mode 100644 index 0000000..ad987d7 --- /dev/null +++ b/pkgs/file/lib/src/backends/memory/memory_file_system_entity.dart
@@ -0,0 +1,309 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:file/file.dart'; +import 'package:file/src/common.dart' as common; +import 'package:file/src/io.dart' as io; +import 'package:meta/meta.dart'; + +import 'common.dart'; +import 'memory_directory.dart'; +import 'node.dart'; +import 'operations.dart'; +import 'style.dart'; +import 'utils.dart' as utils; + +/// Validator function for use with `_renameSync`. This will be invoked if the +/// rename would overwrite an existing entity at the new path. If this operation +/// should not be allowed, this function is expected to throw a +/// [io.FileSystemException]. The lack of such an exception will be interpreted +/// as the overwrite being permissible. +typedef RenameOverwriteValidator<T extends Node> = void Function( + T existingNode); + +/// Base class for all in-memory file system entity types. +abstract class MemoryFileSystemEntity implements FileSystemEntity { + /// Constructor for subclasses. + const MemoryFileSystemEntity(this.fileSystem, this.path); + + @override + final NodeBasedFileSystem fileSystem; + + @override + final String path; + + @override + String get dirname => fileSystem.path.dirname(path); + + @override + String get basename => fileSystem.path.basename(path); + + /// Returns the expected type of this entity, which may differ from the type + /// of the node that's found at the path specified by this entity. + io.FileSystemEntityType get expectedType; + + /// Gets the node that backs this file system entity, or null if this + /// entity does not exist. + @protected + Node? get backingOrNull { + try { + return fileSystem.findNode(path); + } on io.FileSystemException { + return null; + } + } + + /// Gets the node that backs this file system entity. Throws a + /// [io.FileSystemException] if this entity doesn't exist. + /// + /// The type of the node is not guaranteed to match [expectedType]. + @protected + Node get backing { + Node? node = fileSystem.findNode(path); + checkExists(node, () => path); + return node!; + } + + /// Gets the node that backs this file system entity, or if that node is + /// a symbolic link, the target node. This also will check that the type of + /// the node (after symlink resolution) matches [expectedType]. If the type + /// doesn't match, this will throw a [io.FileSystemException]. + @protected + Node get resolvedBacking { + Node node = backing; + node = utils.isLink(node) + ? utils.resolveLinks(node as LinkNode, () => path) + : node; + utils.checkType(expectedType, node.type, () => path); + return node; + } + + /// Checks the expected type of this file system entity against the specified + /// node's `stat` type, throwing a [FileSystemException] if the types don't + /// match. Note that since this checks the node's `stat` type, symbolic links + /// will be resolved to their target type for the purpose of this validation. + /// + /// Protected methods that accept a `checkType` argument will default to this + /// method if the `checkType` argument is unspecified. + @protected + void defaultCheckType(Node node) { + utils.checkType(expectedType, node.stat.type, () => path); + } + + @override + Uri get uri { + return Uri.file(path, windows: fileSystem.style == FileSystemStyle.windows); + } + + @override + Future<bool> exists() async => existsSync(); + + @override + Future<String> resolveSymbolicLinks() async => resolveSymbolicLinksSync(); + + @override + String resolveSymbolicLinksSync() { + if (path.isEmpty) { + throw common.noSuchFileOrDirectory(path); + } + List<String> ledger = <String>[]; + if (isAbsolute) { + ledger.add(fileSystem.style.drive); + } + Node? node = fileSystem.findNode(path, + pathWithSymlinks: ledger, followTailLink: true); + checkExists(node, () => path); + String resolved = ledger.join(fileSystem.path.separator); + if (resolved == fileSystem.style.drive) { + resolved = fileSystem.style.root; + } else if (!fileSystem.path.isAbsolute(resolved)) { + resolved = fileSystem.cwd + fileSystem.path.separator + resolved; + } + return fileSystem.path.normalize(resolved); + } + + @override + Future<io.FileStat> stat() => fileSystem.stat(path); + + @override + io.FileStat statSync() => fileSystem.statSync(path); + + @override + Future<FileSystemEntity> delete({bool recursive = false}) async { + deleteSync(recursive: recursive); + return this; + } + + @override + void deleteSync({bool recursive = false}) => + internalDeleteSync(recursive: recursive); + + @override + Stream<io.FileSystemEvent> watch({ + int events = io.FileSystemEvent.all, + bool recursive = false, + }) => + throw UnsupportedError('Watching not supported in MemoryFileSystem'); + + @override + bool get isAbsolute => fileSystem.path.isAbsolute(path); + + @override + FileSystemEntity get absolute { + String absolutePath = path; + if (!fileSystem.path.isAbsolute(absolutePath)) { + absolutePath = fileSystem.path.join(fileSystem.cwd, absolutePath); + } + return clone(absolutePath); + } + + @override + Directory get parent => MemoryDirectory(fileSystem, dirname); + + /// Helper method for subclasses wishing to synchronously create this entity. + /// This method will traverse the path to this entity one segment at a time, + /// calling [createChild] for each segment whose child does not already exist. + /// + /// When [createChild] is invoked: + /// - `parent` will be the parent node for the current segment and is + /// guaranteed to be non-null. + /// - `isFinalSegment` will indicate whether the current segment is the tail + /// segment, which in turn indicates that this is the segment into which to + /// create the node for this entity. + /// + /// This method returns with the backing node for the entity at this [path]. + /// If an entity already existed at this path, [createChild] will not be + /// invoked at all, and this method will return with the backing node for the + /// existing entity (whose type may differ from this entity's type). + /// + /// If [followTailLink] is true and the result node is a link, this will + /// resolve it to its target prior to returning it. + @protected + Node? internalCreateSync({ + required Node? Function(DirectoryNode parent, bool isFinalSegment) + createChild, + bool followTailLink = false, + bool visitLinks = false, + }) { + return fileSystem.findNode( + path, + followTailLink: followTailLink, + visitLinks: visitLinks, + segmentVisitor: ( + DirectoryNode parent, + String childName, + Node? child, + int currentSegment, + int finalSegment, + ) { + if (child == null) { + assert(!parent.children.containsKey(childName)); + child = createChild(parent, currentSegment == finalSegment); + if (child != null) { + parent.children[childName] = child; + } + } + return child; + }, + ); + } + + /// Helper method for subclasses wishing to synchronously rename this entity. + /// This method will look for an existing file system entity at the location + /// identified by [newPath], and if it finds an existing entity, it will check + /// the following: + /// + /// - If the entity is of a different type than this entity, the operation + /// will fail, and a [io.FileSystemException] will be thrown. + /// - If the caller has specified [validateOverwriteExistingEntity], then that + /// method will be invoked and passed the node backing of the existing + /// entity that would overwritten by the rename action. That callback is + /// expected to throw a [io.FileSystemException] if overwriting the existing + /// entity is not allowed. + /// + /// If the previous two checks pass, or if there was no existing entity at + /// the specified location, this will perform the rename. + /// + /// If [newPath] cannot be traversed to because its directory does not exist, + /// a [io.FileSystemException] will be thrown. + /// + /// If [followTailLink] is true and there is an existing link at the location + /// identified by [newPath], this will resolve the link to its target prior + /// to running the validation checks above. + /// + /// If [checkType] is specified, it will be used to validate that the file + /// system entity that exists at [path] is of the expected type. By default, + /// [defaultCheckType] is used to perform this validation. + @protected + FileSystemEntity internalRenameSync<T extends Node>( + String newPath, { + RenameOverwriteValidator<T>? validateOverwriteExistingEntity, + bool followTailLink = false, + utils.TypeChecker? checkType, + }) { + Node node = backing; + (checkType ?? defaultCheckType)(node); + fileSystem.findNode( + newPath, + segmentVisitor: ( + DirectoryNode parent, + String childName, + Node? child, + int currentSegment, + int finalSegment, + ) { + if (currentSegment == finalSegment) { + if (child != null) { + if (followTailLink) { + FileSystemEntityType childType = child.stat.type; + if (childType != FileSystemEntityType.notFound) { + utils.checkType(expectedType, child.stat.type, () => newPath); + } + } else { + utils.checkType(expectedType, child.type, () => newPath); + } + if (validateOverwriteExistingEntity != null) { + validateOverwriteExistingEntity(child as T); + } + parent.children.remove(childName); + } + node.parent.children.remove(basename); + parent.children[childName] = node; + node.parent = parent; + } + return child; + }, + ); + return clone(newPath); + } + + /// Deletes this entity from the node tree. + /// + /// If [checkType] is specified, it will be used to validate that the file + /// system entity that exists at [path] is of the expected type. By default, + /// [defaultCheckType] is used to perform this validation. + @protected + void internalDeleteSync({ + bool recursive = false, + utils.TypeChecker? checkType, + }) { + fileSystem.opHandle(path, FileSystemOp.delete); + Node node = backing; + if (!recursive) { + if (node is DirectoryNode && node.children.isNotEmpty) { + throw common.directoryNotEmpty(path); + } + (checkType ?? defaultCheckType)(node); + } + // Once we remove this reference, the node and all its children will be + // garbage collected; we don't need to explicitly delete all children in + // the recursive:true case. + node.parent.children.remove(basename); + } + + /// Creates a new entity with the same type as this entity but with the + /// specified path. + @protected + FileSystemEntity clone(String path); +}
diff --git a/pkgs/file/lib/src/backends/memory/memory_link.dart b/pkgs/file/lib/src/backends/memory/memory_link.dart new file mode 100644 index 0000000..7d5afb4 --- /dev/null +++ b/pkgs/file/lib/src/backends/memory/memory_link.dart
@@ -0,0 +1,113 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:file/file.dart'; +import 'package:file/src/common.dart' as common; +import 'package:file/src/io.dart' as io; +import 'package:meta/meta.dart'; + +import 'memory_file_system_entity.dart'; +import 'node.dart'; +import 'operations.dart'; +import 'utils.dart' as utils; + +/// Internal implementation of [Link]. +class MemoryLink extends MemoryFileSystemEntity implements Link { + /// Instantiates a new [MemoryLink]. + const MemoryLink(NodeBasedFileSystem fileSystem, String path) + : super(fileSystem, path); + + @override + io.FileSystemEntityType get expectedType => io.FileSystemEntityType.link; + + @override + bool existsSync() { + fileSystem.opHandle.call(path, FileSystemOp.exists); + return backingOrNull?.type == expectedType; + } + + @override + Future<Link> rename(String newPath) async => renameSync(newPath); + + @override + Link renameSync(String newPath) => internalRenameSync( + newPath, + checkType: (Node node) { + if (node.type != expectedType) { + throw node.type == FileSystemEntityType.directory + ? common.isADirectory(newPath) + : common.invalidArgument(newPath); + } + }, + ) as Link; + + @override + Future<Link> create(String target, {bool recursive = false}) async { + createSync(target, recursive: recursive); + return this; + } + + @override + void createSync(String target, {bool recursive = false}) { + bool preexisting = true; + fileSystem.opHandle(path, FileSystemOp.create); + internalCreateSync( + createChild: (DirectoryNode parent, bool isFinalSegment) { + if (isFinalSegment) { + preexisting = false; + return LinkNode(parent, target); + } else if (recursive) { + return DirectoryNode(parent); + } + return null; + }); + if (preexisting) { + // Per the spec, this is an error. + throw common.fileExists(path); + } + } + + @override + Future<Link> update(String target) async { + updateSync(target); + return this; + } + + @override + void updateSync(String target) { + Node node = backing; + utils.checkType(expectedType, node.type, () => path); + (node as LinkNode).target = target; + } + + @override + void deleteSync({bool recursive = false}) => internalDeleteSync( + recursive: recursive, + checkType: (Node node) => + utils.checkType(expectedType, node.type, () => path), + ); + + @override + Future<String> target() async => targetSync(); + + @override + String targetSync() { + Node node = backing; + if (node.type != expectedType) { + // Note: this may change; https://github.com/dart-lang/sdk/issues/28204 + throw common.noSuchFileOrDirectory(path); + } + return (node as LinkNode).target; + } + + @override + Link get absolute => super.absolute as Link; + + @override + @protected + Link clone(String path) => MemoryLink(fileSystem, path); + + @override + String toString() => "MemoryLink: '$path'"; +}
diff --git a/pkgs/file/lib/src/backends/memory/memory_random_access_file.dart b/pkgs/file/lib/src/backends/memory/memory_random_access_file.dart new file mode 100644 index 0000000..d4fe73d --- /dev/null +++ b/pkgs/file/lib/src/backends/memory/memory_random_access_file.dart
@@ -0,0 +1,390 @@ +// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; +import 'dart:math' as math show min; +import 'dart:typed_data'; + +import 'package:file/src/common.dart' as common; +import 'package:file/src/io.dart' as io; + +import 'memory_file.dart'; +import 'node.dart'; +import 'utils.dart' as utils; + +/// A [MemoryFileSystem]-backed implementation of [io.RandomAccessFile]. +class MemoryRandomAccessFile implements io.RandomAccessFile { + /// Constructs a [MemoryRandomAccessFile]. + /// + /// This should be used only by [MemoryFile.open] or [MemoryFile.openSync]. + MemoryRandomAccessFile(this.path, this._node, this._mode) { + switch (_mode) { + case io.FileMode.read: + break; + case io.FileMode.write: + case io.FileMode.writeOnly: + truncateSync(0); + break; + case io.FileMode.append: + case io.FileMode.writeOnlyAppend: + _position = lengthSync(); + break; + default: + // [FileMode] provides no way of retrieving its value or name. + throw UnimplementedError('Unsupported FileMode'); + } + } + + @override + final String path; + + final FileNode _node; + final io.FileMode _mode; + + bool _isOpen = true; + int _position = 0; + + /// Whether an asynchronous operation is pending. + /// + /// See [_asyncWrapper] for details. + bool get _asyncOperationPending => __asyncOperationPending; + + set _asyncOperationPending(bool value) { + assert(__asyncOperationPending != value); + __asyncOperationPending = value; + } + + bool __asyncOperationPending = false; + + /// Throws a [io.FileSystemException] if an operation is attempted on a file + /// that is not open. + void _checkOpen() { + if (!_isOpen) { + throw io.FileSystemException('File closed', path); + } + } + + /// Throws a [io.FileSystemException] if attempting to read from a file that + /// has not been opened for reading. + void _checkReadable(String operation) { + switch (_mode) { + case io.FileMode.read: + case io.FileMode.write: + case io.FileMode.append: + return; + case io.FileMode.writeOnly: + case io.FileMode.writeOnlyAppend: + default: + throw io.FileSystemException( + '$operation failed', path, common.badFileDescriptor(path).osError); + } + } + + /// Throws a [io.FileSystemException] if attempting to read from a file that + /// has not been opened for writing. + void _checkWritable(String operation) { + if (utils.isWriteMode(_mode)) { + return; + } + + throw io.FileSystemException( + '$operation failed', path, common.badFileDescriptor(path).osError); + } + + /// Throws a [io.FileSystemException] if attempting to perform an operation + /// while an asynchronous operation is already in progress. + /// + /// See [_asyncWrapper] for details. + void _checkAsync() { + if (_asyncOperationPending) { + throw io.FileSystemException( + 'An async operation is currently pending', path); + } + } + + /// Wraps a synchronous function to make it appear asynchronous. + /// + /// [_asyncOperationPending], [_checkAsync], and [_asyncWrapper] are used to + /// mimic [RandomAccessFile]'s enforcement that only one asynchronous + /// operation is pending for a [RandomAccessFile] instance. Since + /// [MemoryFileSystem]-based classes are likely to be used in tests, fidelity + /// is important to catch errors that might occur in production. + /// + /// [_asyncWrapper] does not call [f] directly since setting and unsetting + /// [_asyncOperationPending] synchronously would not be meaningful. We + /// instead execute [f] through a [Future.delayed] callback to better simulate + /// asynchrony. + Future<R> _asyncWrapper<R>(R Function() f) async { + _checkAsync(); + + _asyncOperationPending = true; + try { + return await Future<R>.delayed( + Duration.zero, + () { + // Temporarily reset [_asyncOpPending] in case [f]'s has its own + // checks for pending asynchronous operations. + _asyncOperationPending = false; + try { + return f(); + } finally { + _asyncOperationPending = true; + } + }, + ); + } finally { + _asyncOperationPending = false; + } + } + + @override + Future<void> close() async => _asyncWrapper(closeSync); + + @override + void closeSync() { + _checkOpen(); + _isOpen = false; + } + + @override + Future<io.RandomAccessFile> flush() async { + await _asyncWrapper(flushSync); + return this; + } + + @override + void flushSync() { + _checkOpen(); + _checkAsync(); + } + + @override + Future<int> length() => _asyncWrapper(lengthSync); + + @override + int lengthSync() { + _checkOpen(); + _checkAsync(); + return _node.size; + } + + @override + Future<io.RandomAccessFile> lock([ + io.FileLock mode = io.FileLock.exclusive, + int start = 0, + int end = -1, + ]) async { + await _asyncWrapper(() => lockSync(mode, start, end)); + return this; + } + + @override + void lockSync([ + io.FileLock mode = io.FileLock.exclusive, + int start = 0, + int end = -1, + ]) { + _checkOpen(); + _checkAsync(); + // TODO(jamesderlin): Implement, https://github.com/google/file.dart/issues/140 + throw UnimplementedError('TODO'); + } + + @override + Future<int> position() => _asyncWrapper(positionSync); + + @override + int positionSync() { + _checkOpen(); + _checkAsync(); + return _position; + } + + @override + Future<Uint8List> read(int bytes) => _asyncWrapper(() => readSync(bytes)); + + @override + Uint8List readSync(int bytes) { + _checkOpen(); + _checkAsync(); + _checkReadable('read'); + // TODO(jamesderlin): Check for integer overflow. + final int end = math.min(_position + bytes, lengthSync()); + final Uint8List copy = _node.content.sublist(_position, end); + _position = end; + return copy; + } + + @override + Future<int> readByte() => _asyncWrapper(readByteSync); + + @override + int readByteSync() { + _checkOpen(); + _checkAsync(); + _checkReadable('readByte'); + + if (_position >= lengthSync()) { + return -1; + } + return _node.content[_position++]; + } + + @override + Future<int> readInto(List<int> buffer, [int start = 0, int? end]) => + _asyncWrapper(() => readIntoSync(buffer, start, end)); + + @override + int readIntoSync(List<int> buffer, [int start = 0, int? end]) { + _checkOpen(); + _checkAsync(); + _checkReadable('readInto'); + + end = RangeError.checkValidRange(start, end, buffer.length); + + final int length = lengthSync(); + int i; + for (i = start; i < end && _position < length; i += 1, _position += 1) { + buffer[i] = _node.content[_position]; + } + return i - start; + } + + @override + Future<io.RandomAccessFile> setPosition(int position) async { + await _asyncWrapper(() => setPositionSync(position)); + return this; + } + + @override + void setPositionSync(int position) { + _checkOpen(); + _checkAsync(); + + if (position < 0) { + throw io.FileSystemException( + 'setPosition failed', path, common.invalidArgument(path).osError); + } + + // Empirical testing indicates that setting the position to be beyond the + // end of the file is legal and will zero-fill upon the next write. + _position = position; + } + + @override + Future<io.RandomAccessFile> truncate(int length) async { + await _asyncWrapper(() => truncateSync(length)); + return this; + } + + @override + void truncateSync(int length) { + _checkOpen(); + _checkAsync(); + + if (length < 0 || !utils.isWriteMode(_mode)) { + throw io.FileSystemException( + 'truncate failed', path, common.invalidArgument(path).osError); + } + + final int oldLength = lengthSync(); + if (length < oldLength) { + _node.truncate(length); + + // [_position] is intentionally left untouched to match the observed + // behavior of [RandomAccessFile]. + } else if (length > oldLength) { + _node.write(Uint8List(length - oldLength)); + } + assert(lengthSync() == length); + } + + @override + Future<io.RandomAccessFile> unlock([int start = 0, int end = -1]) async { + await _asyncWrapper(() => unlockSync(start, end)); + return this; + } + + @override + void unlockSync([int start = 0, int end = -1]) { + _checkOpen(); + _checkAsync(); + // TODO(jamesderlin): Implement, https://github.com/google/file.dart/issues/140 + throw UnimplementedError('TODO'); + } + + @override + Future<io.RandomAccessFile> writeByte(int value) async { + await _asyncWrapper(() => writeByteSync(value)); + return this; + } + + @override + int writeByteSync(int value) { + _checkOpen(); + _checkAsync(); + _checkWritable('writeByte'); + + // [Uint8List] will truncate values to 8-bits automatically, so we don't + // need to check [value]. + + int length = lengthSync(); + if (_position >= length) { + // If [_position] is out of bounds, [RandomAccessFile] zero-fills the + // file. + truncateSync(_position + 1); + length = lengthSync(); + } + assert(_position < length); + _node.content[_position++] = value; + + // Despite what the documentation states, [RandomAccessFile.writeByteSync] + // always seems to return 1, even if we had to extend the file for an out of + // bounds write. See https://github.com/dart-lang/sdk/issues/42298. + return 1; + } + + @override + Future<io.RandomAccessFile> writeFrom( + List<int> buffer, [ + int start = 0, + int? end, + ]) async { + await _asyncWrapper(() => writeFromSync(buffer, start, end)); + return this; + } + + @override + void writeFromSync(List<int> buffer, [int start = 0, int? end]) { + _checkOpen(); + _checkAsync(); + _checkWritable('writeFrom'); + + end = RangeError.checkValidRange(start, end, buffer.length); + + final int writeByteCount = end - start; + final int endPosition = _position + writeByteCount; + + if (endPosition > lengthSync()) { + truncateSync(endPosition); + } + + _node.content.setRange(_position, endPosition, buffer, start); + _position = endPosition; + } + + @override + Future<io.RandomAccessFile> writeString( + String string, { + Encoding encoding = utf8, + }) async { + await _asyncWrapper(() => writeStringSync(string, encoding: encoding)); + return this; + } + + @override + void writeStringSync(String string, {Encoding encoding = utf8}) { + writeFromSync(encoding.encode(string)); + } +}
diff --git a/pkgs/file/lib/src/backends/memory/node.dart b/pkgs/file/lib/src/backends/memory/node.dart new file mode 100644 index 0000000..ae4d3f7 --- /dev/null +++ b/pkgs/file/lib/src/backends/memory/node.dart
@@ -0,0 +1,358 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:typed_data'; + +import 'package:file/file.dart'; +import 'package:file/src/backends/memory/operations.dart'; +import 'package:file/src/io.dart' as io; + +import 'clock.dart'; +import 'common.dart'; +import 'memory_file_stat.dart'; +import 'style.dart'; + +/// Visitor callback for use with [NodeBasedFileSystem.findNode]. +/// +/// [parent] is the parent node of the current path segment and is guaranteed +/// to be non-null. +/// +/// [childName] is the basename of the entity at the current path segment. It +/// is guaranteed to be non-null. +/// +/// [childNode] is the node at the current path segment. It will be +/// non-null only if such an entity exists. The return value of this callback +/// will be used as the value of this node, which allows this callback to +/// do things like recursively create or delete folders. +/// +/// [currentSegment] is the index of the current segment within the overall +/// path that's being walked by [NodeBasedFileSystem.findNode]. +/// +/// [finalSegment] is the index of the final segment that will be walked by +/// [NodeBasedFileSystem.findNode]. +typedef SegmentVisitor = Node? Function( + DirectoryNode parent, + String childName, + Node? childNode, + int currentSegment, + int finalSegment, +); + +/// A [FileSystem] whose internal structure is made up of a tree of [Node] +/// instances, rooted at a single node. +abstract class NodeBasedFileSystem implements StyleableFileSystem { + /// An optional handle to hook into common file system operations. + void Function(String context, FileSystemOp operation) get opHandle; + + /// The root node. + RootNode? get root; + + /// The path of the current working directory. + String get cwd; + + /// The clock to use when finding the current time (e.g. to set the creation + /// time of a new node). + Clock get clock; + + /// Gets the backing node of the entity at the specified path. If the tail + /// element of the path does not exist, this will return null. If the tail + /// element cannot be reached because its directory does not exist, a + /// [io.FileSystemException] will be thrown. + /// + /// If [path] is a relative path, it will be resolved relative to + /// [reference], or the current working directory ([cwd]) if [reference] is + /// null. If [path] is an absolute path, [reference] will be ignored. + /// + /// If the last element in [path] represents a symbolic link, this will + /// return the [LinkNode] node for the link (it will not return the + /// node to which the link points), unless [followTailLink] is true. + /// Directory links in the _middle_ of the path will be followed in order to + /// find the node regardless of the value of [followTailLink]. + /// + /// If [segmentVisitor] is specified, it will be invoked for every path + /// segment visited along the way starting where the reference (root folder + /// if the path is absolute) is the parent. For each segment, the return value + /// of [segmentVisitor] will be used as the backing node of that path + /// segment, thus allowing callers to create nodes on demand in the + /// specified path. Note that `..` and `.` segments may cause the visitor to + /// get invoked with the same node multiple times. When [segmentVisitor] is + /// invoked, for each path segment that resolves to a link node, the visitor + /// will visit the actual link node if [visitLinks] is true; otherwise it + /// will visit the target of the link node. + /// + /// If [pathWithSymlinks] is specified, the path to the node with symbolic + /// links explicitly broken out will be appended to the buffer. `..` and `.` + /// path segments will *not* be resolved and are left to the caller. + Node? findNode( + String path, { + Node reference, + SegmentVisitor segmentVisitor, + bool visitLinks = false, + List<String> pathWithSymlinks, + bool followTailLink = false, + }); +} + +/// A class that represents the actual storage of an existent file system +/// entity (whereas classes [File], [Directory], and [Link] represent less +/// concrete entities that may or may not yet exist). +/// +/// This data structure is loosely based on a Unix-style file system inode +/// (hence the name). +abstract class Node { + /// Constructs a new [Node] as a child of the specified parent. + Node(this._parent) { + if (_parent == null && !isRoot) { + throw const io.FileSystemException('All nodes must have a parent.'); + } + } + + DirectoryNode? _parent; + + /// Gets the directory that holds this node. + DirectoryNode get parent => _parent!; + + /// Reparents this node to live in the specified directory. + set parent(DirectoryNode parent) { + DirectoryNode ancestor = parent; + while (!ancestor.isRoot) { + if (ancestor == this) { + throw const io.FileSystemException( + 'A directory cannot be its own ancestor.'); + } + ancestor = ancestor.parent; + } + _parent = parent; + } + + /// Returns the type of the file system entity that this node represents. + io.FileSystemEntityType get type; + + /// Returns the POSIX stat information for this file system object. + io.FileStat get stat; + + /// Returns the closest directory in the ancestry hierarchy starting with + /// this node. For directory nodes, it returns the node itself; for other + /// nodes, it returns the parent node. + DirectoryNode get directory => _parent!; + + /// Tells if this node is a root node. + bool get isRoot => false; + + /// Returns the file system responsible for this node. + NodeBasedFileSystem get fs => _parent!.fs; +} + +/// Base class that represents the backing for those nodes that have +/// substance (namely, node types that will not redirect to other types when +/// you call [stat] on them). +abstract class RealNode extends Node { + /// Constructs a new [RealNode] as a child of the specified [parent]. + RealNode(DirectoryNode? parent) : super(parent) { + int now = clock.now.millisecondsSinceEpoch; + changed = now; + modified = now; + accessed = now; + } + + /// See [NodeBasedFileSystem.clock]. + Clock get clock => parent.clock; + + /// Last changed time in milliseconds since the Epoch. + late int changed; + + /// Last modified time in milliseconds since the Epoch. + late int modified; + + /// Last accessed time in milliseconds since the Epoch. + late int accessed; + + /// Bitmask representing the file read/write/execute mode. + int mode = 0x777; + + @override + io.FileStat get stat { + return MemoryFileStat( + DateTime.fromMillisecondsSinceEpoch(changed), + DateTime.fromMillisecondsSinceEpoch(modified), + DateTime.fromMillisecondsSinceEpoch(accessed), + type, + mode, + size, + ); + } + + /// The size of the file system entity in bytes. + int get size; + + /// Updates the last modified time of the node. + void touch() { + modified = clock.now.millisecondsSinceEpoch; + } +} + +/// Class that represents the backing for an in-memory directory. +class DirectoryNode extends RealNode { + /// Constructs a new [DirectoryNode] as a child of the specified [parent]. + DirectoryNode(DirectoryNode? parent) : super(parent); + + /// Child nodes, indexed by their basename. + final Map<String, Node> children = <String, Node>{}; + + @override + io.FileSystemEntityType get type => io.FileSystemEntityType.directory; + + @override + DirectoryNode get directory => this; + + @override + int get size => 0; +} + +/// Class that represents the backing for the root of the in-memory file system. +class RootNode extends DirectoryNode { + /// Constructs a new [RootNode] tied to the specified file system. + RootNode(this.fs) + : assert(fs.root == null), + super(null); + + @override + final NodeBasedFileSystem fs; + + @override + Clock get clock => fs.clock; + + @override + DirectoryNode get parent => this; + + @override + bool get isRoot => true; + + @override + set parent(DirectoryNode parent) => + throw UnsupportedError('Cannot set the parent of the root directory.'); +} + +/// Class that represents the backing for an in-memory regular file. +class FileNode extends RealNode { + /// Constructs a new [FileNode] as a child of the specified [parent]. + FileNode(DirectoryNode parent) : super(parent); + + /// File contents in bytes. + Uint8List get content => _content; + Uint8List _content = Uint8List(0); + + @override + io.FileSystemEntityType get type => io.FileSystemEntityType.file; + + @override + int get size => _content.length; + + /// Appends the specified bytes to the end of this node's [content]. + void write(List<int> bytes) { + Uint8List existing = _content; + _content = Uint8List(existing.length + bytes.length); + _content.setRange(0, existing.length, existing); + _content.setRange(existing.length, _content.length, bytes); + } + + /// Truncates this node's [content] to the specified length. + /// + /// [length] must be in the range \[0, [size]\]. + void truncate(int length) { + assert(length >= 0); + assert(length <= _content.length); + _content = _content.sublist(0, length); + } + + /// Clears the [content] of the node. + void clear() { + _content = Uint8List(0); + } + + /// Copies data from [source] into this node. The [modified] and [changed] + /// fields will be reset as opposed to copied to indicate that this file + /// has been modified and changed. + void copyFrom(FileNode source) { + modified = changed = clock.now.millisecondsSinceEpoch; + accessed = source.accessed; + mode = source.mode; + _content = Uint8List.fromList(source.content); + } +} + +/// Class that represents the backing for an in-memory symbolic link. +class LinkNode extends Node { + /// Constructs a new [LinkNode] as a child of the specified [parent] and + /// linking to the specified [target] path. + LinkNode(DirectoryNode parent, this.target) + : assert(target.isNotEmpty), + super(parent); + + /// The path to which this link points. + String target; + + /// A marker used to detect circular link references. + bool _reentrant = false; + + /// Gets the node backing for this link's target. Throws a + /// [FileSystemException] if this link references a non-existent file + /// system entity. + /// + /// If [tailVisitor] is specified, it will be invoked for the tail path + /// segment of this link's target, and its return value will be used as the + /// return value of this method. If the tail path segment of this link's + /// target cannot be traversed into, a [FileSystemException] will be thrown, + /// and [tailVisitor] will not be invoked. + Node getReferent({ + Node? Function(DirectoryNode parent, String childName, Node? child)? + tailVisitor, + }) { + Node? referent = fs.findNode( + target, + reference: this, + segmentVisitor: ( + DirectoryNode parent, + String childName, + Node? child, + int currentSegment, + int finalSegment, + ) { + if (tailVisitor != null && currentSegment == finalSegment) { + child = tailVisitor(parent, childName, child); + } + return child; + }, + ); + checkExists(referent, () => target); + return referent!; + } + + /// Gets the node backing for this link's target, or null if this link + /// references a non-existent file system entity. + Node? get referentOrNull { + try { + return getReferent(); + } on io.FileSystemException { + return null; + } + } + + @override + io.FileSystemEntityType get type => io.FileSystemEntityType.link; + + @override + io.FileStat get stat { + if (_reentrant) { + return MemoryFileStat.notFound; + } + _reentrant = true; + try { + Node? node = referentOrNull; + return node == null ? MemoryFileStat.notFound : node.stat; + } finally { + _reentrant = false; + } + } +}
diff --git a/pkgs/file/lib/src/backends/memory/operations.dart b/pkgs/file/lib/src/backends/memory/operations.dart new file mode 100644 index 0000000..9fc7462 --- /dev/null +++ b/pkgs/file/lib/src/backends/memory/operations.dart
@@ -0,0 +1,86 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// A file system operation used by the [MemoryFileSytem] to allow +/// tests to insert errors for certain operations. +/// +/// This is not implemented as an enum to allow new values to be added in a +/// backwards compatible manner. +class FileSystemOp { + const FileSystemOp._(this._value); + + // This field added to ensure const values can be different. + // ignore: unused_field + final int _value; + + /// A file system operation used for all read methods. + /// + /// * [FileSystemEntity.readAsString] + /// * [FileSystemEntity.readAsStringSync] + /// * [FileSystemEntity.readAsBytes] + /// * [FileSystemEntity.readAsBytesSync] + static const FileSystemOp read = FileSystemOp._(0); + + /// A file system operation used for all write methods. + /// + /// * [FileSystemEntity.writeAsString] + /// * [FileSystemEntity.writeAsStringSync] + /// * [FileSystemEntity.writeAsBytes] + /// * [FileSystemEntity.writeAsBytesSync] + static const FileSystemOp write = FileSystemOp._(1); + + /// A file system operation used for all delete methods. + /// + /// * [FileSystemEntity.delete] + /// * [FileSystemEntity.deleteSync] + static const FileSystemOp delete = FileSystemOp._(2); + + /// A file system operation used for all create methods. + /// + /// * [FileSystemEntity.create] + /// * [FileSystemEntity.createSync] + static const FileSystemOp create = FileSystemOp._(3); + + /// A file operation used for all open methods. + /// + /// * [File.open] + /// * [File.openSync] + /// * [File.openRead] + /// * [File.openWrite] + static const FileSystemOp open = FileSystemOp._(4); + + /// A file operation used for all copy methods. + /// + /// * [File.copy] + /// * [File.copySync] + static const FileSystemOp copy = FileSystemOp._(5); + + /// A file system operation used for all exists methods. + /// + /// * [FileSystemEntity.exists] + /// * [FileSystemEntity.existsSync] + static const FileSystemOp exists = FileSystemOp._(6); + + @override + String toString() { + switch (_value) { + case 0: + return 'FileSystemOp.read'; + case 1: + return 'FileSystemOp.write'; + case 2: + return 'FileSystemOp.delete'; + case 3: + return 'FileSystemOp.create'; + case 4: + return 'FileSystemOp.open'; + case 5: + return 'FileSystemOp.copy'; + case 6: + return 'FileSystemOp.exists'; + default: + throw StateError('Invalid FileSytemOp type: $this'); + } + } +}
diff --git a/pkgs/file/lib/src/backends/memory/style.dart b/pkgs/file/lib/src/backends/memory/style.dart new file mode 100644 index 0000000..701c9d0 --- /dev/null +++ b/pkgs/file/lib/src/backends/memory/style.dart
@@ -0,0 +1,98 @@ +// Copyright (c) 2018, 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'; +import 'package:path/path.dart' as p; + +/// Class that represents the path style that a memory file system should +/// adopt. +/// +/// This is primarily useful if you want to test how your code will behave +/// when faced with particular paths or particular path separator characters. +/// For instance, you may want to test that your code will work on Windows, +/// while still using a memory file system in order to gain hermeticity in your +/// tests. +abstract class FileSystemStyle { + const FileSystemStyle._(); + + /// Mimics the Unix file system style. + /// + /// * This style does not have the notion of drives + /// * All file system paths are rooted at `/` + /// * The path separator is `/` + /// + /// An example path in this style is `/path/to/file`. + static const FileSystemStyle posix = _Posix(); + + /// Mimics the Windows file system style. + /// + /// * This style mounts its root folder on a single root drive (`C:`) + /// * All file system paths are rooted at `C:\` + /// * The path separator is `\` + /// + /// An example path in this style is `C:\path\to\file`. + static const FileSystemStyle windows = _Windows(); + + /// The drive upon which the root directory is mounted. + /// + /// While real-world file systems that have the notion of drives will support + /// multiple drives per system, memory file system will only support one + /// root drive. + /// + /// This will be the empty string for styles that don't have the notion of + /// drives (e.g. [posix]). + String get drive; + + /// The String that represents the delineation between a directory and its + /// children. + String get separator; + + /// The string that represents the root of the file system. + /// + /// Memory file system is always single-rooted. + String get root => '$drive$separator'; + + /// Gets an object useful for manipulating paths in this style. + /// + /// Relative path manipulations will be relative to the specified [path]. + p.Context contextFor(String path); +} + +class _Posix extends FileSystemStyle { + const _Posix() : super._(); + + @override + String get drive => ''; + + @override + String get separator { + return p.Style.posix.separator; // ignore: deprecated_member_use + } + + @override + p.Context contextFor(String path) => + p.Context(style: p.Style.posix, current: path); +} + +class _Windows extends FileSystemStyle { + const _Windows() : super._(); + + @override + String get drive => 'C:'; + + @override + String get separator { + return p.Style.windows.separator; // ignore: deprecated_member_use + } + + @override + p.Context contextFor(String path) => + p.Context(style: p.Style.windows, current: path); +} + +/// A file system that supports different styles. +abstract class StyleableFileSystem implements FileSystem { + /// The style used by this file system. + FileSystemStyle get style; +}
diff --git a/pkgs/file/lib/src/backends/memory/utils.dart b/pkgs/file/lib/src/backends/memory/utils.dart new file mode 100644 index 0000000..eec9980 --- /dev/null +++ b/pkgs/file/lib/src/backends/memory/utils.dart
@@ -0,0 +1,117 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:file/file.dart'; +import 'package:file/src/common.dart' as common; +import 'package:file/src/io.dart' as io; + +import 'common.dart'; +import 'node.dart'; + +/// Checks if `node.type` returns [io.FileSystemEntityType.FILE]. +bool isFile(Node? node) => node?.type == io.FileSystemEntityType.file; + +/// Checks if `node.type` returns [io.FileSystemEntityType.DIRECTORY]. +bool isDirectory(Node? node) => node?.type == io.FileSystemEntityType.directory; + +/// Checks if `node.type` returns [io.FileSystemEntityType.LINK]. +bool isLink(Node? node) => node?.type == io.FileSystemEntityType.link; + +/// Validator function that is expected to throw a [FileSystemException] if +/// the node does not represent the type that is expected in any given context. +typedef TypeChecker = void Function(Node node); + +/// Throws a [io.FileSystemException] if [node] is not a directory. +void checkIsDir(Node node, PathGenerator path) { + if (!isDirectory(node)) { + throw common.notADirectory(path() as String); + } +} + +/// Throws a [io.FileSystemException] if [expectedType] doesn't match +/// [actualType]. +void checkType( + FileSystemEntityType expectedType, + FileSystemEntityType actualType, + PathGenerator path, +) { + if (expectedType != actualType) { + switch (expectedType) { + case FileSystemEntityType.directory: + throw common.notADirectory(path() as String); + case FileSystemEntityType.file: + assert(actualType == FileSystemEntityType.directory); + throw common.isADirectory(path() as String); + case FileSystemEntityType.link: + throw common.invalidArgument(path() as String); + default: + // Should not happen + throw AssertionError(); + } + } +} + +/// Tells if the specified file mode represents a write mode. +bool isWriteMode(io.FileMode mode) => + mode == io.FileMode.write || + mode == io.FileMode.append || + mode == io.FileMode.writeOnly || + mode == io.FileMode.writeOnlyAppend; + +/// Tells whether the given string is empty. +bool isEmpty(String str) => str.isEmpty; + +/// Returns the node ultimately referred to by [link]. This will resolve +/// the link references (following chains of links as necessary) and return +/// the node at the end of the link chain. +/// +/// If a loop in the link chain is found, this will throw a +/// [FileSystemException], calling [path] to generate the path. +/// +/// If [ledger] is specified, the resolved path to the terminal node will be +/// appended to the ledger (or overwritten in the ledger if a link target +/// specified an absolute path). The path will not be normalized, meaning +/// `..` and `.` path segments may be present. +/// +/// If [tailVisitor] is specified, it will be invoked for the tail element of +/// the last link in the symbolic link chain, and its return value will be the +/// return value of this method (thus allowing callers to create the entity +/// at the end of the chain on demand). +Node resolveLinks( + LinkNode link, + PathGenerator path, { + List<String>? ledger, + Node? Function(DirectoryNode parent, String childName, Node? child)? + tailVisitor, +}) { + // Record a breadcrumb trail to guard against symlink loops. + Set<LinkNode> breadcrumbs = <LinkNode>{}; + + Node node = link; + while (isLink(node)) { + link = node as LinkNode; + if (!breadcrumbs.add(link)) { + throw common.tooManyLevelsOfSymbolicLinks(path() as String); + } + if (ledger != null) { + if (link.fs.path.isAbsolute(link.target)) { + ledger.clear(); + } else if (ledger.isNotEmpty) { + ledger.removeLast(); + } + ledger.addAll(link.target.split(link.fs.path.separator)); + } + node = link.getReferent( + tailVisitor: (DirectoryNode parent, String childName, Node? child) { + if (tailVisitor != null && !isLink(child)) { + // Only invoke [tailListener] on the final resolution pass. + child = tailVisitor(parent, childName, child); + } + return child; + }, + ); + } + + return node; +}
diff --git a/pkgs/file/lib/src/common.dart b/pkgs/file/lib/src/common.dart new file mode 100644 index 0000000..6706ec9 --- /dev/null +++ b/pkgs/file/lib/src/common.dart
@@ -0,0 +1,70 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'interface.dart'; + +/// Returns a 'No such file or directory' [FileSystemException]. +FileSystemException noSuchFileOrDirectory(String path) { + return _fsException(path, 'No such file or directory', ErrorCodes.ENOENT); +} + +/// Returns a 'Not a directory' [FileSystemException]. +FileSystemException notADirectory(String path) { + return _fsException(path, 'Not a directory', ErrorCodes.ENOTDIR); +} + +/// Returns a 'Is a directory' [FileSystemException]. +FileSystemException isADirectory(String path) { + return _fsException(path, 'Is a directory', ErrorCodes.EISDIR); +} + +/// Returns a 'Directory not empty' [FileSystemException]. +FileSystemException directoryNotEmpty(String path) { + return _fsException(path, 'Directory not empty', ErrorCodes.ENOTEMPTY); +} + +/// Returns a 'File exists' [FileSystemException]. +FileSystemException fileExists(String path) { + return _fsException(path, 'File exists', ErrorCodes.EEXIST); +} + +/// Returns a 'Invalid argument' [FileSystemException]. +FileSystemException invalidArgument(String path) { + return _fsException(path, 'Invalid argument', ErrorCodes.EINVAL); +} + +/// Returns a 'Too many levels of symbolic links' [FileSystemException]. +FileSystemException tooManyLevelsOfSymbolicLinks(String path) { + // TODO(tvolkert): Switch to ErrorCodes.EMLINK + return _fsException( + path, 'Too many levels of symbolic links', ErrorCodes.ELOOP); +} + +/// Returns a 'Bad file descriptor' [FileSystemException]. +FileSystemException badFileDescriptor(String path) { + return _fsException(path, 'Bad file descriptor', ErrorCodes.EBADF); +} + +FileSystemException _fsException(String path, String msg, int errorCode) { + return FileSystemException(msg, path, OSError(msg, errorCode)); +} + +/// Mixin containing implementations of [Directory] methods that are common +/// to all implementations. +mixin DirectoryAddOnsMixin implements Directory { + @override + Directory childDirectory(String basename) { + return fileSystem.directory(fileSystem.path.join(path, basename)); + } + + @override + File childFile(String basename) { + return fileSystem.file(fileSystem.path.join(path, basename)); + } + + @override + Link childLink(String basename) { + return fileSystem.link(fileSystem.path.join(path, basename)); + } +}
diff --git a/pkgs/file/lib/src/forwarding.dart b/pkgs/file/lib/src/forwarding.dart new file mode 100644 index 0000000..9566a30 --- /dev/null +++ b/pkgs/file/lib/src/forwarding.dart
@@ -0,0 +1,10 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +export 'forwarding/forwarding_directory.dart'; +export 'forwarding/forwarding_file.dart'; +export 'forwarding/forwarding_file_system.dart'; +export 'forwarding/forwarding_file_system_entity.dart'; +export 'forwarding/forwarding_link.dart'; +export 'forwarding/forwarding_random_access_file.dart';
diff --git a/pkgs/file/lib/src/forwarding/forwarding_directory.dart b/pkgs/file/lib/src/forwarding/forwarding_directory.dart new file mode 100644 index 0000000..dba0c8e --- /dev/null +++ b/pkgs/file/lib/src/forwarding/forwarding_directory.dart
@@ -0,0 +1,57 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:file/src/io.dart' as io; +import 'package:file/file.dart'; + +/// A directory that forwards all methods and properties to a delegate. +mixin ForwardingDirectory<T extends Directory> + implements ForwardingFileSystemEntity<T, io.Directory>, Directory { + @override + T wrap(io.Directory delegate) => wrapDirectory(delegate) as T; + + @override + Future<Directory> create({bool recursive = false}) async => + wrap(await delegate.create(recursive: recursive)); + + @override + void createSync({bool recursive = false}) => + delegate.createSync(recursive: recursive); + + @override + Future<Directory> createTemp([String? prefix]) async => + wrap(await delegate.createTemp(prefix)); + + @override + Directory createTempSync([String? prefix]) => + wrap(delegate.createTempSync(prefix)); + + @override + Stream<FileSystemEntity> list({ + bool recursive = false, + bool followLinks = true, + }) => + delegate.list(recursive: recursive, followLinks: followLinks).map(_wrap); + + @override + List<FileSystemEntity> listSync({ + bool recursive = false, + bool followLinks = true, + }) => + delegate + .listSync(recursive: recursive, followLinks: followLinks) + .map(_wrap) + .toList(); + + FileSystemEntity _wrap(io.FileSystemEntity entity) { + if (entity is io.File) { + return wrapFile(entity); + } else if (entity is io.Directory) { + return wrapDirectory(entity); + } else if (entity is io.Link) { + return wrapLink(entity); + } + throw FileSystemException('Unsupported type: $entity', entity.path); + } +}
diff --git a/pkgs/file/lib/src/forwarding/forwarding_file.dart b/pkgs/file/lib/src/forwarding/forwarding_file.dart new file mode 100644 index 0000000..49c211d --- /dev/null +++ b/pkgs/file/lib/src/forwarding/forwarding_file.dart
@@ -0,0 +1,156 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:file/src/io.dart' as io; +import 'package:file/file.dart'; + +/// A file that forwards all methods and properties to a delegate. +mixin ForwardingFile + implements ForwardingFileSystemEntity<File, io.File>, File { + @override + ForwardingFile wrap(io.File delegate) => wrapFile(delegate) as ForwardingFile; + + // TODO(dartbug.com/49647): Pass `exclusive` through after it lands. + @override + Future<File> create({bool recursive = false, bool exclusive = false}) async => + wrap(await delegate.create( + recursive: recursive /*, exclusive: exclusive*/)); + + // TODO(dartbug.com/49647): Pass `exclusive` through after it lands. + @override + void createSync({bool recursive = false, bool exclusive = false}) => + delegate.createSync(recursive: recursive /*, exclusive: exclusive*/); + + @override + Future<File> copy(String newPath) async => wrap(await delegate.copy(newPath)); + + @override + File copySync(String newPath) => wrap(delegate.copySync(newPath)); + + @override + Future<int> length() => delegate.length(); + + @override + int lengthSync() => delegate.lengthSync(); + + @override + Future<DateTime> lastAccessed() => delegate.lastAccessed(); + + @override + DateTime lastAccessedSync() => delegate.lastAccessedSync(); + + @override + Future<dynamic> setLastAccessed(DateTime time) => + delegate.setLastAccessed(time); + + @override + void setLastAccessedSync(DateTime time) => delegate.setLastAccessedSync(time); + + @override + Future<DateTime> lastModified() => delegate.lastModified(); + + @override + DateTime lastModifiedSync() => delegate.lastModifiedSync(); + + @override + Future<dynamic> setLastModified(DateTime time) => + delegate.setLastModified(time); + + @override + void setLastModifiedSync(DateTime time) => delegate.setLastModifiedSync(time); + + @override + Future<RandomAccessFile> open({ + FileMode mode = FileMode.read, + }) => + delegate.open(mode: mode); + + @override + RandomAccessFile openSync({FileMode mode = FileMode.read}) => + delegate.openSync(mode: mode); + + @override + Stream<List<int>> openRead([int? start, int? end]) => + delegate.openRead(start, end); + + @override + IOSink openWrite({ + FileMode mode = FileMode.write, + Encoding encoding = utf8, + }) => + delegate.openWrite(mode: mode, encoding: encoding); + + @override + Future<Uint8List> readAsBytes() => delegate.readAsBytes(); + + @override + Uint8List readAsBytesSync() => delegate.readAsBytesSync(); + + @override + Future<String> readAsString({Encoding encoding = utf8}) => + delegate.readAsString(encoding: encoding); + + @override + String readAsStringSync({Encoding encoding = utf8}) => + delegate.readAsStringSync(encoding: encoding); + + @override + Future<List<String>> readAsLines({Encoding encoding = utf8}) => + delegate.readAsLines(encoding: encoding); + + @override + List<String> readAsLinesSync({Encoding encoding = utf8}) => + delegate.readAsLinesSync(encoding: encoding); + + @override + Future<File> writeAsBytes( + List<int> bytes, { + FileMode mode = FileMode.write, + bool flush = false, + }) async => + wrap(await delegate.writeAsBytes( + bytes, + mode: mode, + flush: flush, + )); + + @override + void writeAsBytesSync( + List<int> bytes, { + FileMode mode = FileMode.write, + bool flush = false, + }) => + delegate.writeAsBytesSync(bytes, mode: mode, flush: flush); + + @override + Future<File> writeAsString( + String contents, { + FileMode mode = FileMode.write, + Encoding encoding = utf8, + bool flush = false, + }) async => + wrap(await delegate.writeAsString( + contents, + mode: mode, + encoding: encoding, + flush: flush, + )); + + @override + void writeAsStringSync( + String contents, { + FileMode mode = FileMode.write, + Encoding encoding = utf8, + bool flush = false, + }) => + delegate.writeAsStringSync( + contents, + mode: mode, + encoding: encoding, + flush: flush, + ); +}
diff --git a/pkgs/file/lib/src/forwarding/forwarding_file_system.dart b/pkgs/file/lib/src/forwarding/forwarding_file_system.dart new file mode 100644 index 0000000..d864db9 --- /dev/null +++ b/pkgs/file/lib/src/forwarding/forwarding_file_system.dart
@@ -0,0 +1,66 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:file/src/io.dart' as io; +import 'package:file/file.dart'; +import 'package:meta/meta.dart'; +import 'package:path/path.dart' as p; + +/// A file system that forwards all methods and properties to a delegate. +abstract class ForwardingFileSystem extends FileSystem { + /// Creates a new [ForwardingFileSystem] that forwards all methods and + /// properties to the specified [delegate]. + ForwardingFileSystem(this.delegate); + + /// The file system to which this file system will forward all activity. + @protected + final FileSystem delegate; + + @override + Directory directory(dynamic path) => delegate.directory(path); + + @override + File file(dynamic path) => delegate.file(path); + + @override + Link link(dynamic path) => delegate.link(path); + + @override + p.Context get path => delegate.path; + + @override + Directory get systemTempDirectory => delegate.systemTempDirectory; + + @override + Directory get currentDirectory => delegate.currentDirectory; + + @override + set currentDirectory(dynamic path) => delegate.currentDirectory = path; + + @override + Future<io.FileStat> stat(String path) => delegate.stat(path); + + @override + io.FileStat statSync(String path) => delegate.statSync(path); + + @override + Future<bool> identical(String path1, String path2) => + delegate.identical(path1, path2); + + @override + bool identicalSync(String path1, String path2) => + delegate.identicalSync(path1, path2); + + @override + bool get isWatchSupported => delegate.isWatchSupported; + + @override + Future<io.FileSystemEntityType> type(String path, + {bool followLinks = true}) => + delegate.type(path, followLinks: followLinks); + + @override + io.FileSystemEntityType typeSync(String path, {bool followLinks = true}) => + delegate.typeSync(path, followLinks: followLinks); +}
diff --git a/pkgs/file/lib/src/forwarding/forwarding_file_system_entity.dart b/pkgs/file/lib/src/forwarding/forwarding_file_system_entity.dart new file mode 100644 index 0000000..3c41b39 --- /dev/null +++ b/pkgs/file/lib/src/forwarding/forwarding_file_system_entity.dart
@@ -0,0 +1,96 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:file/src/io.dart' as io; +import 'package:file/file.dart'; +import 'package:meta/meta.dart'; + +/// A file system entity that forwards all methods and properties to a delegate. +abstract class ForwardingFileSystemEntity<T extends FileSystemEntity, + D extends io.FileSystemEntity> implements FileSystemEntity { + /// The entity to which this entity will forward all methods and properties. + @protected + D get delegate; + + /// Creates a new entity with the same file system and same type as this + /// entity but backed by the specified delegate. + @protected + T wrap(D delegate); + + /// Creates a new directory with the same file system as this entity and + /// backed by the specified delegate. + @protected + Directory wrapDirectory(io.Directory delegate); + + /// Creates a new file with the same file system as this entity and + /// backed by the specified delegate. + @protected + File wrapFile(io.File delegate); + + /// Creates a new link with the same file system as this entity and + /// backed by the specified delegate. + @protected + Link wrapLink(io.Link delegate); + + @override + Uri get uri => delegate.uri; + + @override + Future<bool> exists() => delegate.exists(); + + @override + bool existsSync() => delegate.existsSync(); + + @override + Future<T> rename(String newPath) async => + wrap(await delegate.rename(newPath) as D); + + @override + T renameSync(String newPath) => wrap(delegate.renameSync(newPath) as D); + + @override + Future<String> resolveSymbolicLinks() => delegate.resolveSymbolicLinks(); + + @override + String resolveSymbolicLinksSync() => delegate.resolveSymbolicLinksSync(); + + @override + Future<io.FileStat> stat() => delegate.stat(); + + @override + io.FileStat statSync() => delegate.statSync(); + + @override + Future<T> delete({bool recursive = false}) async => + wrap(await delegate.delete(recursive: recursive) as D); + + @override + void deleteSync({bool recursive = false}) => + delegate.deleteSync(recursive: recursive); + + @override + Stream<FileSystemEvent> watch({ + int events = FileSystemEvent.all, + bool recursive = false, + }) => + delegate.watch(events: events, recursive: recursive); + + @override + bool get isAbsolute => delegate.isAbsolute; + + @override + T get absolute => wrap(delegate.absolute as D); + + @override + Directory get parent => wrapDirectory(delegate.parent); + + @override + String get path => delegate.path; + + @override + String get basename => fileSystem.path.basename(path); + + @override + String get dirname => fileSystem.path.dirname(path); +}
diff --git a/pkgs/file/lib/src/forwarding/forwarding_link.dart b/pkgs/file/lib/src/forwarding/forwarding_link.dart new file mode 100644 index 0000000..7a60ecb --- /dev/null +++ b/pkgs/file/lib/src/forwarding/forwarding_link.dart
@@ -0,0 +1,34 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:file/src/io.dart' as io; +import 'package:file/file.dart'; + +/// A link that forwards all methods and properties to a delegate. +mixin ForwardingLink + implements ForwardingFileSystemEntity<Link, io.Link>, Link { + @override + ForwardingLink wrap(io.Link delegate) => wrapLink(delegate) as ForwardingLink; + + @override + Future<Link> create(String target, {bool recursive = false}) async => + wrap(await delegate.create(target, recursive: recursive)); + + @override + void createSync(String target, {bool recursive = false}) => + delegate.createSync(target, recursive: recursive); + + @override + Future<Link> update(String target) async => + wrap(await delegate.update(target)); + + @override + void updateSync(String target) => delegate.updateSync(target); + + @override + Future<String> target() => delegate.target(); + + @override + String targetSync() => delegate.targetSync(); +}
diff --git a/pkgs/file/lib/src/forwarding/forwarding_random_access_file.dart b/pkgs/file/lib/src/forwarding/forwarding_random_access_file.dart new file mode 100644 index 0000000..9dd4079 --- /dev/null +++ b/pkgs/file/lib/src/forwarding/forwarding_random_access_file.dart
@@ -0,0 +1,149 @@ +// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:file/src/io.dart' as io; +import 'package:meta/meta.dart'; + +/// A [RandomAccessFile] implementation that forwards all methods and properties +/// to a delegate. +mixin ForwardingRandomAccessFile implements io.RandomAccessFile { + /// The entity to which this entity will forward all methods and properties. + @protected + io.RandomAccessFile get delegate; + + @override + String get path => delegate.path; + + @override + Future<void> close() => delegate.close(); + + @override + void closeSync() => delegate.closeSync(); + + @override + Future<io.RandomAccessFile> flush() async { + await delegate.flush(); + return this; + } + + @override + void flushSync() => delegate.flushSync(); + + @override + Future<int> length() => delegate.length(); + + @override + int lengthSync() => delegate.lengthSync(); + + @override + Future<io.RandomAccessFile> lock([ + io.FileLock mode = io.FileLock.exclusive, + int start = 0, + int end = -1, + ]) async { + await delegate.lock(mode, start, end); + return this; + } + + @override + void lockSync([ + io.FileLock mode = io.FileLock.exclusive, + int start = 0, + int end = -1, + ]) => + delegate.lockSync(mode, start, end); + + @override + Future<int> position() => delegate.position(); + + @override + int positionSync() => delegate.positionSync(); + + @override + Future<Uint8List> read(int bytes) => delegate.read(bytes); + + @override + Uint8List readSync(int bytes) => delegate.readSync(bytes); + + @override + Future<int> readByte() => delegate.readByte(); + + @override + int readByteSync() => delegate.readByteSync(); + + @override + Future<int> readInto(List<int> buffer, [int start = 0, int? end]) => + delegate.readInto(buffer, start, end); + + @override + int readIntoSync(List<int> buffer, [int start = 0, int? end]) => + delegate.readIntoSync(buffer, start, end); + + @override + Future<io.RandomAccessFile> setPosition(int position) async { + await delegate.setPosition(position); + return this; + } + + @override + void setPositionSync(int position) => delegate.setPositionSync(position); + + @override + Future<io.RandomAccessFile> truncate(int length) async { + await delegate.truncate(length); + return this; + } + + @override + void truncateSync(int length) => delegate.truncateSync(length); + + @override + Future<io.RandomAccessFile> unlock([int start = 0, int end = -1]) async { + await delegate.unlock(start, end); + return this; + } + + @override + void unlockSync([int start = 0, int end = -1]) => + delegate.unlockSync(start, end); + + @override + Future<io.RandomAccessFile> writeByte(int value) async { + await delegate.writeByte(value); + return this; + } + + @override + int writeByteSync(int value) => delegate.writeByteSync(value); + + @override + Future<io.RandomAccessFile> writeFrom( + List<int> buffer, [ + int start = 0, + int? end, + ]) async { + await delegate.writeFrom(buffer, start, end); + return this; + } + + @override + void writeFromSync(List<int> buffer, [int start = 0, int? end]) => + delegate.writeFromSync(buffer, start, end); + + @override + Future<io.RandomAccessFile> writeString( + String string, { + Encoding encoding = utf8, + }) async { + await delegate.writeString(string, encoding: encoding); + return this; + } + + @override + void writeStringSync(String string, {Encoding encoding = utf8}) => + delegate.writeStringSync(string, encoding: encoding); +}
diff --git a/pkgs/file/lib/src/interface.dart b/pkgs/file/lib/src/interface.dart new file mode 100644 index 0000000..4662e35 --- /dev/null +++ b/pkgs/file/lib/src/interface.dart
@@ -0,0 +1,13 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library file.src.interface; + +export 'interface/directory.dart'; +export 'interface/error_codes.dart'; +export 'interface/file.dart'; +export 'interface/file_system.dart'; +export 'interface/file_system_entity.dart'; +export 'interface/link.dart'; +export 'io.dart' hide Directory, File, FileSystemEntity, Link;
diff --git a/pkgs/file/lib/src/interface/directory.dart b/pkgs/file/lib/src/interface/directory.dart new file mode 100644 index 0000000..e62ad8c --- /dev/null +++ b/pkgs/file/lib/src/interface/directory.dart
@@ -0,0 +1,51 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../io.dart' as io; + +import 'file.dart'; +import 'file_system_entity.dart'; +import 'link.dart'; + +/// A reference to a directory on the file system. +abstract class Directory implements FileSystemEntity, io.Directory { + // Override method definitions to codify the return type covariance. + @override + Future<Directory> create({bool recursive = false}); + + @override + Future<Directory> createTemp([String? prefix]); + + @override + Directory createTempSync([String? prefix]); + + @override + Future<Directory> rename(String newPath); + + @override + Directory renameSync(String newPath); + + @override + Directory get absolute; + + @override + Stream<FileSystemEntity> list( + {bool recursive = false, bool followLinks = true}); + + @override + List<FileSystemEntity> listSync( + {bool recursive = false, bool followLinks = true}); + + /// Returns a reference to a [Directory] that exists as a child of this + /// directory and has the specified [basename]. + Directory childDirectory(String basename); + + /// Returns a reference to a [File] that exists as a child of this directory + /// and has the specified [basename]. + File childFile(String basename); + + /// Returns a reference to a [Link] that exists as a child of this directory + /// and has the specified [basename]. + Link childLink(String basename); +}
diff --git a/pkgs/file/lib/src/interface/error_codes.dart b/pkgs/file/lib/src/interface/error_codes.dart new file mode 100644 index 0000000..8943538 --- /dev/null +++ b/pkgs/file/lib/src/interface/error_codes.dart
@@ -0,0 +1,585 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'error_codes_internal.dart' + if (dart.library.io) 'error_codes_dart_io.dart'; + +/// Operating system error codes. +// TODO(tvolkert): Remove (https://github.com/dart-lang/sdk/issues/28860) +class ErrorCodes { + ErrorCodes._(); + + /// Argument list too long + // ignore: non_constant_identifier_names + static int get E2BIG => _platform((_Codes codes) => codes.e2big); + + /// Permission denied + // ignore: non_constant_identifier_names + static int get EACCES => _platform((_Codes codes) => codes.eacces); + + /// Try again + // ignore: non_constant_identifier_names + static int get EAGAIN => _platform((_Codes codes) => codes.eagain); + + /// Bad file number + // ignore: non_constant_identifier_names + static int get EBADF => _platform((_Codes codes) => codes.ebadf); + + /// Device or resource busy + // ignore: non_constant_identifier_names + static int get EBUSY => _platform((_Codes codes) => codes.ebusy); + + /// No child processes + // ignore: non_constant_identifier_names + static int get ECHILD => _platform((_Codes codes) => codes.echild); + + /// Resource deadlock would occur + // ignore: non_constant_identifier_names + static int get EDEADLK => _platform((_Codes codes) => codes.edeadlk); + + /// Math argument out of domain of func + // ignore: non_constant_identifier_names + static int get EDOM => _platform((_Codes codes) => codes.edom); + + /// File exists + // ignore: non_constant_identifier_names + static int get EEXIST => _platform((_Codes codes) => codes.eexist); + + /// Bad address + // ignore: non_constant_identifier_names + static int get EFAULT => _platform((_Codes codes) => codes.efault); + + /// File too large + // ignore: non_constant_identifier_names + static int get EFBIG => _platform((_Codes codes) => codes.efbig); + + /// Illegal byte sequence + // ignore: non_constant_identifier_names + static int get EILSEQ => _platform((_Codes codes) => codes.eilseq); + + /// Interrupted system call + // ignore: non_constant_identifier_names + static int get EINTR => _platform((_Codes codes) => codes.eintr); + + /// Invalid argument + // ignore: non_constant_identifier_names + static int get EINVAL => _platform((_Codes codes) => codes.einval); + + /// I/O error + // ignore: non_constant_identifier_names + static int get EIO => _platform((_Codes codes) => codes.eio); + + /// Is a directory + // ignore: non_constant_identifier_names + static int get EISDIR => _platform((_Codes codes) => codes.eisdir); + + /// Too many levels of symbolic links + // ignore: non_constant_identifier_names + static int get ELOOP => _platform((_Codes codes) => codes.eloop); + + /// Too many open files + // ignore: non_constant_identifier_names + static int get EMFILE => _platform((_Codes codes) => codes.emfile); + + /// Too many links + // ignore: non_constant_identifier_names + static int get EMLINK => _platform((_Codes codes) => codes.emlink); + + /// File name too long + // ignore: non_constant_identifier_names + static int get ENAMETOOLONG => + _platform((_Codes codes) => codes.enametoolong); + + /// File table overflow + // ignore: non_constant_identifier_names + static int get ENFILE => _platform((_Codes codes) => codes.enfile); + + /// No such device + // ignore: non_constant_identifier_names + static int get ENODEV => _platform((_Codes codes) => codes.enodev); + + /// No such file or directory + // ignore: non_constant_identifier_names + static int get ENOENT => _platform((_Codes codes) => codes.enoent); + + /// Exec format error + // ignore: non_constant_identifier_names + static int get ENOEXEC => _platform((_Codes codes) => codes.enoexec); + + /// No record locks available + // ignore: non_constant_identifier_names + static int get ENOLCK => _platform((_Codes codes) => codes.enolck); + + /// Out of memory + // ignore: non_constant_identifier_names + static int get ENOMEM => _platform((_Codes codes) => codes.enomem); + + /// No space left on device + // ignore: non_constant_identifier_names + static int get ENOSPC => _platform((_Codes codes) => codes.enospc); + + /// Function not implemented + // ignore: non_constant_identifier_names + static int get ENOSYS => _platform((_Codes codes) => codes.enosys); + + /// Not a directory + // ignore: non_constant_identifier_names + static int get ENOTDIR => _platform((_Codes codes) => codes.enotdir); + + /// Directory not empty + // ignore: non_constant_identifier_names + static int get ENOTEMPTY => _platform((_Codes codes) => codes.enotempty); + + /// Not a typewriter + // ignore: non_constant_identifier_names + static int get ENOTTY => _platform((_Codes codes) => codes.enotty); + + /// No such device or address + // ignore: non_constant_identifier_names + static int get ENXIO => _platform((_Codes codes) => codes.enxio); + + /// Operation not permitted + // ignore: non_constant_identifier_names + static int get EPERM => _platform((_Codes codes) => codes.eperm); + + /// Broken pipe + // ignore: non_constant_identifier_names + static int get EPIPE => _platform((_Codes codes) => codes.epipe); + + /// Math result not representable + // ignore: non_constant_identifier_names + static int get ERANGE => _platform((_Codes codes) => codes.erange); + + /// Read-only file system + // ignore: non_constant_identifier_names + static int get EROFS => _platform((_Codes codes) => codes.erofs); + + /// Illegal seek + // ignore: non_constant_identifier_names + static int get ESPIPE => _platform((_Codes codes) => codes.espipe); + + /// No such process + // ignore: non_constant_identifier_names + static int get ESRCH => _platform((_Codes codes) => codes.esrch); + + /// Cross-device link + // ignore: non_constant_identifier_names + static int get EXDEV => _platform((_Codes codes) => codes.exdev); + + static int _platform(int Function(_Codes codes) getCode) { + _Codes codes = (_platforms[operatingSystem] ?? _platforms['linux'])!; + return getCode(codes); + } +} + +const Map<String, _Codes> _platforms = <String, _Codes>{ + 'linux': _LinuxCodes(), + 'macos': _MacOSCodes(), + 'windows': _WindowsCodes(), +}; + +abstract class _Codes { + int get e2big; + int get eacces; + int get eagain; + int get ebadf; + int get ebusy; + int get echild; + int get edeadlk; + int get edom; + int get eexist; + int get efault; + int get efbig; + int get eilseq; + int get eintr; + int get einval; + int get eio; + int get eisdir; + int get eloop; + int get emfile; + int get emlink; + int get enametoolong; + int get enfile; + int get enodev; + int get enoent; + int get enoexec; + int get enolck; + int get enomem; + int get enospc; + int get enosys; + int get enotdir; + int get enotempty; + int get enotty; + int get enxio; + int get eperm; + int get epipe; + int get erange; + int get erofs; + int get espipe; + int get esrch; + int get exdev; +} + +class _LinuxCodes implements _Codes { + const _LinuxCodes(); + + @override + int get e2big => 7; + + @override + int get eacces => 13; + + @override + int get eagain => 11; + + @override + int get ebadf => 9; + + @override + int get ebusy => 16; + + @override + int get echild => 10; + + @override + int get edeadlk => 35; + + @override + int get edom => 33; + + @override + int get eexist => 17; + + @override + int get efault => 14; + + @override + int get efbig => 27; + + @override + int get eilseq => 84; + + @override + int get eintr => 4; + + @override + int get einval => 22; + + @override + int get eio => 5; + + @override + int get eisdir => 21; + + @override + int get eloop => 40; + + @override + int get emfile => 24; + + @override + int get emlink => 31; + + @override + int get enametoolong => 36; + + @override + int get enfile => 23; + + @override + int get enodev => 19; + + @override + int get enoent => 2; + + @override + int get enoexec => 8; + + @override + int get enolck => 37; + + @override + int get enomem => 12; + + @override + int get enospc => 28; + + @override + int get enosys => 38; + + @override + int get enotdir => 20; + + @override + int get enotempty => 39; + + @override + int get enotty => 25; + + @override + int get enxio => 6; + + @override + int get eperm => 1; + + @override + int get epipe => 32; + + @override + int get erange => 34; + + @override + int get erofs => 30; + + @override + int get espipe => 29; + + @override + int get esrch => 3; + + @override + int get exdev => 18; +} + +class _MacOSCodes implements _Codes { + const _MacOSCodes(); + + @override + int get e2big => 7; + + @override + int get eacces => 13; + + @override + int get eagain => 35; + + @override + int get ebadf => 9; + + @override + int get ebusy => 16; + + @override + int get echild => 10; + + @override + int get edeadlk => 11; + + @override + int get edom => 33; + + @override + int get eexist => 17; + + @override + int get efault => 14; + + @override + int get efbig => 27; + + @override + int get eilseq => 92; + + @override + int get eintr => 4; + + @override + int get einval => 22; + + @override + int get eio => 5; + + @override + int get eisdir => 21; + + @override + int get eloop => 62; + + @override + int get emfile => 24; + + @override + int get emlink => 31; + + @override + int get enametoolong => 63; + + @override + int get enfile => 23; + + @override + int get enodev => 19; + + @override + int get enoent => 2; + + @override + int get enoexec => 8; + + @override + int get enolck => 77; + + @override + int get enomem => 12; + + @override + int get enospc => 28; + + @override + int get enosys => 78; + + @override + int get enotdir => 20; + + @override + int get enotempty => 66; + + @override + int get enotty => 25; + + @override + int get enxio => 6; + + @override + int get eperm => 1; + + @override + int get epipe => 32; + + @override + int get erange => 34; + + @override + int get erofs => 30; + + @override + int get espipe => 29; + + @override + int get esrch => 3; + + @override + int get exdev => 18; +} + +class _WindowsCodes implements _Codes { + const _WindowsCodes(); + + @override + int get e2big => 7; + + @override + int get eacces => 13; + + @override + int get eagain => 11; + + @override + int get ebadf => 9; + + @override + int get ebusy => 16; + + @override + int get echild => 10; + + @override + int get edeadlk => 36; + + @override + int get edom => 33; + + @override + int get eexist => 17; + + @override + int get efault => 14; + + @override + int get efbig => 27; + + @override + int get eilseq => 42; + + @override + int get eintr => 4; + + @override + int get einval => 22; + + @override + int get eio => 5; + + @override + int get eisdir => 21; + + @override + int get eloop => -1; + + @override + int get emfile => 24; + + @override + int get emlink => 31; + + @override + int get enametoolong => 38; + + @override + int get enfile => 23; + + @override + int get enodev => 19; + + @override + int get enoent => 2; + + @override + int get enoexec => 8; + + @override + int get enolck => 39; + + @override + int get enomem => 12; + + @override + int get enospc => 28; + + @override + int get enosys => 40; + + @override + int get enotdir => 20; + + @override + int get enotempty => 41; + + @override + int get enotty => 25; + + @override + int get enxio => 6; + + @override + int get eperm => 1; + + @override + int get epipe => 32; + + @override + int get erange => 34; + + @override + int get erofs => 30; + + @override + int get espipe => 29; + + @override + int get esrch => 3; + + @override + int get exdev => 18; +}
diff --git a/pkgs/file/lib/src/interface/error_codes_dart_io.dart b/pkgs/file/lib/src/interface/error_codes_dart_io.dart new file mode 100644 index 0000000..3f0a97f --- /dev/null +++ b/pkgs/file/lib/src/interface/error_codes_dart_io.dart
@@ -0,0 +1,10 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:io' show Platform; + +/// If we have `dart:io` available, we pull the current operating system from +/// the [Platform] class, so we'll get errno values that match our current +/// operating system. +final String operatingSystem = Platform.operatingSystem;
diff --git a/pkgs/file/lib/src/interface/error_codes_internal.dart b/pkgs/file/lib/src/interface/error_codes_internal.dart new file mode 100644 index 0000000..0a9d7dc --- /dev/null +++ b/pkgs/file/lib/src/interface/error_codes_internal.dart
@@ -0,0 +1,8 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// In environments that don't have `dart:io`, we can't access the Platform +/// class to determine what platform we're on, so we just pretend we're on +/// Linux, meaning we'll get errno values that match Linux's errno.h. +const String operatingSystem = 'linux';
diff --git a/pkgs/file/lib/src/interface/file.dart b/pkgs/file/lib/src/interface/file.dart new file mode 100644 index 0000000..87417c6 --- /dev/null +++ b/pkgs/file/lib/src/interface/file.dart
@@ -0,0 +1,41 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; + +import '../io.dart' as io; + +import 'file_system_entity.dart'; + +/// A reference to a file on the file system. +abstract class File implements FileSystemEntity, io.File { + // Override method definitions to codify the return type covariance. + @override + Future<File> create({bool recursive = false, bool exclusive = false}); + + @override + Future<File> rename(String newPath); + + @override + File renameSync(String newPath); + + @override + Future<File> copy(String newPath); + + @override + File copySync(String newPath); + + @override + File get absolute; + + @override + Future<File> writeAsBytes(List<int> bytes, + {io.FileMode mode = io.FileMode.write, bool flush = false}); + + @override + Future<File> writeAsString(String contents, + {io.FileMode mode = io.FileMode.write, + Encoding encoding = utf8, + bool flush = false}); +}
diff --git a/pkgs/file/lib/src/interface/file_system.dart b/pkgs/file/lib/src/interface/file_system.dart new file mode 100644 index 0000000..4fd528d --- /dev/null +++ b/pkgs/file/lib/src/interface/file_system.dart
@@ -0,0 +1,163 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:meta/meta.dart'; +import 'package:path/path.dart' as p; + +import '../io.dart' as io; + +import 'directory.dart'; +import 'file.dart'; +import 'file_system_entity.dart'; +import 'link.dart'; + +/// A generic representation of a file system. +/// +/// Note that this class uses `dart:io` only inasmuch as it deals in the types +/// exposed by the `dart:io` library. Subclasses should document their level of +/// dependence on the library (and the associated implications of using that +/// implementation in the browser). +abstract class FileSystem { + /// Creates a new `FileSystem`. + const FileSystem(); + + /// Returns a reference to a [Directory] at [path]. + /// + /// [path] can be either a [`String`], a [`Uri`], or a [`FileSystemEntity`]. + Directory directory(dynamic path); + + /// Returns a reference to a [File] at [path]. + /// + /// [path] can be either a [`String`], a [`Uri`], or a [`FileSystemEntity`]. + File file(dynamic path); + + /// Returns a reference to a [Link] at [path]. + /// + /// [path] can be either a [`String`], a [`Uri`], or a [`FileSystemEntity`]. + Link link(dynamic path); + + /// An object for manipulating paths in this file system. + p.Context get path; + + /// Gets the system temp directory. + /// + /// It is left to file system implementations to decide how to define the + /// "system temp directory". + Directory get systemTempDirectory; + + /// Creates a directory object pointing to the current working directory. + Directory get currentDirectory; + + /// Sets the current working directory to the specified [path]. + /// + /// The new value set can be either a [Directory] or a [String]. + /// + /// Relative paths will be resolved by the underlying file system + /// implementation (meaning it is up to the underlying implementation to + /// decide whether to support relative paths). + set currentDirectory(dynamic path); + + /// Asynchronously calls the operating system's stat() function on [path]. + /// Returns a Future which completes with a [io.FileStat] object containing + /// the data returned by stat(). + /// If the call fails, completes the future with a [io.FileStat] object with + /// .type set to FileSystemEntityType.NOT_FOUND and the other fields invalid. + Future<io.FileStat> stat(String path); + + /// Calls the operating system's stat() function on [path]. + /// Returns a [io.FileStat] object containing the data returned by stat(). + /// If the call fails, returns a [io.FileStat] object with .type set to + /// FileSystemEntityType.NOT_FOUND and the other fields invalid. + io.FileStat statSync(String path); + + /// Checks whether two paths refer to the same object in the + /// file system. Returns a [Future<bool>] that completes with the result. + /// + /// Comparing a link to its target returns false, as does comparing two links + /// that point to the same target. To check the target of a link, use + /// Link.target explicitly to fetch it. Directory links appearing + /// inside a path are followed, though, to find the file system object. + /// + /// Completes the returned Future with an error if one of the paths points + /// to an object that does not exist. + Future<bool> identical(String path1, String path2); + + /// Synchronously checks whether two paths refer to the same object in the + /// file system. + /// + /// Comparing a link to its target returns false, as does comparing two links + /// that point to the same target. To check the target of a link, use + /// Link.target explicitly to fetch it. Directory links appearing + /// inside a path are followed, though, to find the file system object. + /// + /// Throws an error if one of the paths points to an object that does not + /// exist. + bool identicalSync(String path1, String path2); + + /// Tests if [FileSystemEntity.watch] is supported on the current system. + bool get isWatchSupported; + + /// Finds the type of file system object that a [path] points to. Returns + /// a Future<FileSystemEntityType> that completes with the result. + /// + /// [io.FileSystemEntityType.LINK] will only be returned if [followLinks] is + /// `false`, and [path] points to a link + /// + /// If the [path] does not point to a file system object or an error occurs + /// then [io.FileSystemEntityType.notFound] is returned. + Future<io.FileSystemEntityType> type(String path, {bool followLinks = true}); + + /// Syncronously finds the type of file system object that a [path] points + /// to. Returns a [io.FileSystemEntityType]. + /// + /// [io.FileSystemEntityType.LINK] will only be returned if [followLinks] is + /// `false`, and [path] points to a link + /// + /// If the [path] does not point to a file system object or an error occurs + /// then [io.FileSystemEntityType.notFound] is returned. + io.FileSystemEntityType typeSync(String path, {bool followLinks = true}); + + /// Checks if [`type(path)`](type) returns [io.FileSystemEntityType.FILE]. + Future<bool> isFile(String path) async => + await type(path) == io.FileSystemEntityType.file; + + /// Synchronously checks if [`type(path)`](type) returns + /// [io.FileSystemEntityType.FILE]. + bool isFileSync(String path) => + typeSync(path) == io.FileSystemEntityType.file; + + /// Checks if [`type(path)`](type) returns [io.FileSystemEntityType.DIRECTORY]. + Future<bool> isDirectory(String path) async => + await type(path) == io.FileSystemEntityType.directory; + + /// Synchronously checks if [`type(path)`](type) returns + /// [io.FileSystemEntityType.DIRECTORY]. + bool isDirectorySync(String path) => + typeSync(path) == io.FileSystemEntityType.directory; + + /// Checks if [`type(path)`](type) returns [io.FileSystemEntityType.LINK]. + Future<bool> isLink(String path) async => + await type(path, followLinks: false) == io.FileSystemEntityType.link; + + /// Synchronously checks if [`type(path)`](type) returns + /// [io.FileSystemEntityType.LINK]. + bool isLinkSync(String path) => + typeSync(path, followLinks: false) == io.FileSystemEntityType.link; + + /// Gets the string path represented by the specified generic [path]. + /// + /// [path] may be a [io.FileSystemEntity], a [String], or a [Uri]. + @protected + String getPath(dynamic path) { + if (path is io.FileSystemEntity) { + return path.path; + } else if (path is String) { + return path; + } else if (path is Uri) { + return this.path.fromUri(path); + } else { + throw ArgumentError('Invalid type for "path": ${path?.runtimeType}'); + } + } +}
diff --git a/pkgs/file/lib/src/interface/file_system_entity.dart b/pkgs/file/lib/src/interface/file_system_entity.dart new file mode 100644 index 0000000..a377397 --- /dev/null +++ b/pkgs/file/lib/src/interface/file_system_entity.dart
@@ -0,0 +1,42 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../io.dart' as io; + +import 'directory.dart'; +import 'file_system.dart'; + +/// The common super class for [io.File], [io.Directory], and [io.Link] objects. +abstract class FileSystemEntity implements io.FileSystemEntity { + /// Returns the file system responsible for this entity. + FileSystem get fileSystem; + + /// Gets the part of this entity's path after the last separator. + /// + /// context.basename('path/to/foo.dart'); // -> 'foo.dart' + /// context.basename('path/to'); // -> 'to' + /// + /// Trailing separators are ignored. + /// + /// context.basename('path/to/'); // -> 'to' + String get basename; + + /// Gets the part of this entity's path before the last separator. + /// + /// context.dirname('path/to/foo.dart'); // -> 'path/to' + /// context.dirname('path/to'); // -> 'path' + /// context.dirname('foo.dart'); // -> '.' + /// + /// Trailing separators are ignored. + /// + /// context.dirname('path/to/'); // -> 'path' + String get dirname; + + // Override method definitions to codify the return type covariance. + @override + Future<FileSystemEntity> delete({bool recursive = false}); + + @override + Directory get parent; +}
diff --git a/pkgs/file/lib/src/interface/link.dart b/pkgs/file/lib/src/interface/link.dart new file mode 100644 index 0000000..27874b3 --- /dev/null +++ b/pkgs/file/lib/src/interface/link.dart
@@ -0,0 +1,26 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../io.dart' as io; + +import 'file_system_entity.dart'; + +/// A reference to a symbolic link on the file system. +abstract class Link implements FileSystemEntity, io.Link { + // Override method definitions to codify the return type covariance. + @override + Future<Link> create(String target, {bool recursive = false}); + + @override + Future<Link> update(String target); + + @override + Future<Link> rename(String newPath); + + @override + Link renameSync(String newPath); + + @override + Link get absolute; +}
diff --git a/pkgs/file/lib/src/io.dart b/pkgs/file/lib/src/io.dart new file mode 100644 index 0000000..9d57e78 --- /dev/null +++ b/pkgs/file/lib/src/io.dart
@@ -0,0 +1,26 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// For internal use only! +/// +/// This exposes the subset of the `dart:io` interfaces that are required by +/// the `file` package. The `file` package re-exports these interfaces (or in +/// some cases, implementations of these interfaces by the same name), so this +/// file need not be exposes publicly and exists for internal use only. +export 'dart:io' + show + Directory, + File, + FileLock, + FileMode, + FileStat, + FileSystemEntity, + FileSystemEntityType, + FileSystemEvent, + FileSystemException, + IOException, + IOSink, + Link, + OSError, + RandomAccessFile;
diff --git a/pkgs/file/pubspec.yaml b/pkgs/file/pubspec.yaml new file mode 100644 index 0000000..b4195f7 --- /dev/null +++ b/pkgs/file/pubspec.yaml
@@ -0,0 +1,19 @@ +name: file +version: 7.0.1 +description: + A pluggable, mockable file system abstraction for Dart. Supports local file + system access, as well as in-memory file systems, record-replay file systems, + and chroot file systems. +repository: https://github.com/dart-lang/tools/tree/main/pkgs/file + +environment: + sdk: ^3.0.0 + +dependencies: + meta: ^1.9.1 + path: ^1.8.3 + +dev_dependencies: + file_testing: ^3.0.0 + lints: ^2.0.1 + test: ^1.23.1
diff --git a/pkgs/file/test/chroot_test.dart b/pkgs/file/test/chroot_test.dart new file mode 100644 index 0000000..6c34ff2 --- /dev/null +++ b/pkgs/file/test/chroot_test.dart
@@ -0,0 +1,177 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +@TestOn('vm') +import 'dart:io' as io; + +import 'package:file/chroot.dart'; +import 'package:file/file.dart'; +import 'package:file/local.dart'; +import 'package:file/memory.dart'; +import 'package:file_testing/file_testing.dart'; +import 'package:test/test.dart'; + +import 'common_tests.dart'; + +void main() { + group('ChrootFileSystem', () { + ChrootFileSystem createMemoryBackedChrootFileSystem() { + MemoryFileSystem fs = MemoryFileSystem(); + fs.directory('/tmp').createSync(); + return ChrootFileSystem(fs, '/tmp'); + } + + // TODO(jamesderlin): Make ChrootFile.openSync return a delegating + // RandomAccessFile that uses the chroot'd path. + List<String> skipCommon = <String>[ + 'File > open > .* > RandomAccessFile > read > openReadHandleDoesNotChange', + 'File > open > .* > RandomAccessFile > openWriteHandleDoesNotChange', + ]; + + group('memoryBacked', () { + runCommonTests(createMemoryBackedChrootFileSystem, skip: skipCommon); + }); + + group('localBacked', () { + late ChrootFileSystem fs; + late io.Directory tmp; + + setUp(() { + tmp = io.Directory.systemTemp.createTempSync('file_test_'); + tmp = io.Directory(tmp.resolveSymbolicLinksSync()); + fs = ChrootFileSystem(const LocalFileSystem(), tmp.path); + }); + + tearDown(() { + tmp.deleteSync(recursive: true); + }); + + runCommonTests( + () => fs, + skip: <String>[ + // https://github.com/dart-lang/sdk/issues/28275 + 'Link > rename > throwsIfDestinationExistsAsDirectory', + + // https://github.com/dart-lang/sdk/issues/28277 + 'Link > rename > throwsIfDestinationExistsAsFile', + + ...skipCommon, + ], + ); + }, skip: io.Platform.isWindows); + + group('chrootSpecific', () { + late ChrootFileSystem fs; + late MemoryFileSystem mem; + + setUp(() { + fs = createMemoryBackedChrootFileSystem(); + mem = fs.delegate as MemoryFileSystem; + }); + + group('FileSystem', () { + group('currentDirectory', () { + test('staysInJailIfSetToParentOfRoot', () { + fs.currentDirectory = '../../../..'; + fs.file('foo').createSync(); + expect(mem.file('/tmp/foo'), exists); + }); + + test('throwsIfSetToSymlinkToDirectoryOutsideJail', () { + mem.directory('/bar').createSync(); + mem.link('/tmp/foo').createSync('/bar'); + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.currentDirectory = '/foo'; + }); + }); + }); + + group('stat', () { + test('isNotFoundForJailbreakPath', () { + mem.file('/foo').createSync(); + expect(fs.statSync('../foo').type, FileSystemEntityType.notFound); + }); + + test('isNotFoundForSymlinkWithJailbreakTarget', () { + mem.file('/foo').createSync(); + mem.link('/tmp/bar').createSync('/foo'); + expect(mem.statSync('/tmp/bar').type, FileSystemEntityType.file); + expect(fs.statSync('/bar').type, FileSystemEntityType.notFound); + }); + + test('isNotFoundForSymlinkToOutsideAndBackInsideJail', () { + mem.file('/tmp/bar').createSync(); + mem.link('/foo').createSync('/tmp/bar'); + mem.link('/tmp/baz').createSync('/foo'); + expect(mem.statSync('/tmp/baz').type, FileSystemEntityType.file); + expect(fs.statSync('/baz').type, FileSystemEntityType.notFound); + }); + }); + + group('type', () { + test('isNotFoundForJailbreakPath', () { + mem.file('/foo').createSync(); + expect(fs.typeSync('../foo'), FileSystemEntityType.notFound); + }); + + test('isNotFoundForSymlinkWithJailbreakTarget', () { + mem.file('/foo').createSync(); + mem.link('/tmp/bar').createSync('/foo'); + expect(mem.typeSync('/tmp/bar'), FileSystemEntityType.file); + expect(fs.typeSync('/bar'), FileSystemEntityType.notFound); + }); + + test('isNotFoundForSymlinkToOutsideAndBackInsideJail', () { + mem.file('/tmp/bar').createSync(); + mem.link('/foo').createSync('/tmp/bar'); + mem.link('/tmp/baz').createSync('/foo'); + expect(mem.typeSync('/tmp/baz'), FileSystemEntityType.file); + expect(fs.typeSync('/baz'), FileSystemEntityType.notFound); + }); + }); + }); + + group('File', () { + group('delegate', () { + test('referencesRootEntityForJailbreakPath', () { + mem.file('/foo').createSync(); + dynamic f = fs.file('../foo'); + expect(f.delegate.path, '/tmp/foo'); + }); + }); + + group('create', () { + test('createsAtRootIfPathReferencesJailbreakFile', () { + fs.file('../foo').createSync(); + expect(mem.file('/foo'), isNot(exists)); + expect(mem.file('/tmp/foo'), exists); + }); + }); + + group('copy', () { + test('copiesToRootDirectoryIfDestinationIsJailbreakPath', () { + File f = fs.file('/foo')..createSync(); + f.copySync('../bar'); + expect(mem.file('/bar'), isNot(exists)); + expect(mem.file('/tmp/bar'), exists); + }); + }); + }); + + group('Link', () { + group('target', () { + test('chrootAndDelegateFileSystemsReturnSameValue', () { + mem.file('/foo').createSync(); + mem.link('/tmp/bar').createSync('/foo'); + mem.link('/tmp/baz').createSync('../foo'); + expect(mem.link('/tmp/bar').targetSync(), '/foo'); + expect(fs.link('/bar').targetSync(), '/foo'); + expect(mem.link('/tmp/baz').targetSync(), '../foo'); + expect(fs.link('/baz').targetSync(), '../foo'); + }); + }); + }); + }); + }); +}
diff --git a/pkgs/file/test/common_tests.dart b/pkgs/file/test/common_tests.dart new file mode 100644 index 0000000..6028c77 --- /dev/null +++ b/pkgs/file/test/common_tests.dart
@@ -0,0 +1,3517 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +@TestOn('vm') +import 'dart:async'; +import 'dart:convert'; +import 'dart:io' as io; + +import 'package:file/file.dart'; +import 'package:file_testing/file_testing.dart'; +import 'package:path/path.dart' as p; +import 'package:test/test.dart'; +import 'package:test/test.dart' as testpkg show group, setUp, tearDown, test; + +import 'utils.dart'; + +/// Callback used in [runCommonTests] to produce the root folder in which all +/// file system entities will be created. +typedef RootPathGenerator = String Function(); + +/// Callback used in [runCommonTests] to create the file system under test. +/// It must return either a [FileSystem] or a [Future] that completes with a +/// [FileSystem]. +typedef FileSystemGenerator = dynamic Function(); + +/// A function to run before tests (passed to [setUp]) or after tests +/// (passed to [tearDown]). +typedef SetUpTearDown = dynamic Function(); + +/// Runs a suite of tests common to all file system implementations. All file +/// system implementations should run *at least* these tests to ensure +/// compliance with file system API. +/// +/// If [root] is specified, its return value will be used as the root folder +/// in which all file system entities will be created. If not specified, the +/// tests will attempt to create entities in the file system root. +/// +/// [skip] may be used to skip certain tests (or entire groups of tests) in +/// this suite (to be used, for instance, if a file system implementation is +/// not yet fully complete). The format of each entry in the list is: +/// `$group1Description > $group2Description > ... > $testDescription`. +/// Entries may use regular expression syntax. +/// +/// If [replay] is specified, each test (and its setup callbacks) will run +/// twice - once as a "setup" pass with the file system returned by +/// [createFileSystem], and again as the "test" pass with the file system +/// returned by [replay]. This is intended for use with `ReplayFileSystem`, +/// where in order for the file system to behave as expected, a recording of +/// the invocation(s) must first be made. +void runCommonTests( + FileSystemGenerator createFileSystem, { + RootPathGenerator? root, + List<String> skip = const <String>[], + FileSystemGenerator? replay, +}) { + RootPathGenerator? rootfn = root; + + group('common', () { + late FileSystemGenerator createFs; + late List<SetUpTearDown> setUps; + late List<SetUpTearDown> tearDowns; + late FileSystem fs; + late String root; + List<String> stack = <String>[]; + + void skipIfNecessary(String description, void Function() callback) { + stack.add(description); + bool matchesCurrentFrame(String input) => + RegExp('^$input\$').hasMatch(stack.join(' > ')); + if (skip.where(matchesCurrentFrame).isEmpty) { + callback(); + } + stack.removeLast(); + } + + testpkg.setUp(() async { + createFs = createFileSystem; + setUps = <SetUpTearDown>[]; + tearDowns = <SetUpTearDown>[]; + }); + + void setUp(FutureOr<void> Function() callback) { + testpkg.setUp(replay == null ? callback : () => setUps.add(callback)); + } + + void tearDown(FutureOr<void> Function() callback) { + if (replay == null) { + testpkg.tearDown(callback); + } else { + testpkg.setUp(() => tearDowns.insert(0, callback)); + } + } + + void group(String description, void Function() body) => + skipIfNecessary(description, () => testpkg.group(description, body)); + + void test(String description, FutureOr<void> Function() body, + {dynamic skip}) => + skipIfNecessary(description, () { + if (replay == null) { + testpkg.test(description, body, skip: skip); + } else { + group('rerun', () { + testpkg.setUp(() async { + await Future.forEach(setUps, (SetUpTearDown setUp) => setUp()); + await body(); + for (SetUpTearDown tearDown in tearDowns) { + await tearDown(); + } + createFs = replay; + await Future.forEach(setUps, (SetUpTearDown setUp) => setUp()); + }); + + testpkg.test(description, body, skip: skip); + + testpkg.tearDown(() async { + for (SetUpTearDown tearDown in tearDowns) { + await tearDown(); + } + }); + }); + } + }); + + /// Returns [path] prefixed by the [root] namespace. + /// This is only intended for absolute paths. + String ns(String path) { + p.Context posix = p.Context(style: p.Style.posix); + List<String> parts = posix.split(path); + parts[0] = root; + path = fs.path.joinAll(parts); + String rootPrefix = fs.path.rootPrefix(path); + assert(rootPrefix.isNotEmpty); + String result = root == rootPrefix + ? path + : (path == rootPrefix + ? root + : fs.path.join(root, fs.path.joinAll(parts.sublist(1)))); + return result; + } + + setUp(() async { + root = rootfn != null ? rootfn() : '/'; + fs = await createFs() as FileSystem; + assert(fs.path.isAbsolute(root)); + assert(!root.endsWith(fs.path.separator) || + fs.path.rootPrefix(root) == root); + }); + + group('FileSystem', () { + group('directory', () { + test('allowsStringArgument', () { + expect(fs.directory(ns('/foo')), isDirectory); + }); + + test('allowsUriArgument', () { + expect(fs.directory(Uri.parse('file:///')), isDirectory); + }); + + test('succeedsWithUriArgument', () { + fs.directory(ns('/foo')).createSync(); + Uri uri = fs.path.toUri(ns('/foo')); + expect(fs.directory(uri), exists); + }); + + test('allowsDirectoryArgument', () { + expect(fs.directory(io.Directory(ns('/foo'))), isDirectory); + }); + + test('disallowsOtherArgumentType', () { + expect(() => fs.directory(123), throwsArgumentError); + }); + + // Fails due to + // https://github.com/google/file.dart/issues/112 + test('considersBothSlashesEquivalent', () { + fs.directory(r'foo\bar_dir').createSync(recursive: true); + expect(fs.directory(r'foo/bar_dir'), exists); + }, skip: 'Fails due to https://github.com/google/file.dart/issues/112'); + }); + + group('file', () { + test('allowsStringArgument', () { + expect(fs.file(ns('/foo')), isFile); + }); + + test('allowsUriArgument', () { + expect(fs.file(Uri.parse('file:///')), isFile); + }); + + test('succeedsWithUriArgument', () { + fs.file(ns('/foo')).createSync(); + Uri uri = fs.path.toUri(ns('/foo')); + expect(fs.file(uri), exists); + }); + + test('allowsDirectoryArgument', () { + expect(fs.file(io.File(ns('/foo'))), isFile); + }); + + test('disallowsOtherArgumentType', () { + expect(() => fs.file(123), throwsArgumentError); + }); + + // Fails due to + // https://github.com/google/file.dart/issues/112 + test('considersBothSlashesEquivalent', () { + fs.file(r'foo\bar_file').createSync(recursive: true); + expect(fs.file(r'foo/bar_file'), exists); + }, skip: 'Fails due to https://github.com/google/file.dart/issues/112'); + }); + + group('link', () { + test('allowsStringArgument', () { + expect(fs.link(ns('/foo')), isLink); + }); + + test('allowsUriArgument', () { + expect(fs.link(Uri.parse('file:///')), isLink); + }); + + test('succeedsWithUriArgument', () { + fs.file(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + Uri uri = fs.path.toUri(ns('/bar')); + expect(fs.link(uri), exists); + }); + + test('allowsDirectoryArgument', () { + expect(fs.link(io.File(ns('/foo'))), isLink); + }); + + test('disallowsOtherArgumentType', () { + expect(() => fs.link(123), throwsArgumentError); + }); + }); + + group('path', () { + test('hasCorrectCurrentWorkingDirectory', () { + expect(fs.path.current, fs.currentDirectory.path); + }); + + test('separatorIsAmongExpectedValues', () { + expect(fs.path.separator, anyOf('/', r'\')); + }); + }); + + group('systemTempDirectory', () { + test('existsAsDirectory', () { + Directory tmp = fs.systemTempDirectory; + expect(tmp, isDirectory); + expect(tmp, exists); + }); + }); + + group('currentDirectory', () { + test('defaultsToRoot', () { + expect(fs.currentDirectory.path, root); + }); + + test('throwsIfSetToNonExistentPath', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.currentDirectory = ns('/foo'); + }); + }); + + test('throwsIfHasNonExistentPathInComplexChain', () { + fs.directory(ns('/foo')).createSync(); + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.currentDirectory = ns('/bar/../foo'); + }); + }); + + test('succeedsIfSetToValidStringPath', () { + fs.directory(ns('/foo')).createSync(); + fs.currentDirectory = ns('/foo'); + expect(fs.currentDirectory.path, ns('/foo')); + }); + + test('succeedsIfSetToValidDirectory', () { + fs.directory(ns('/foo')).createSync(); + fs.currentDirectory = io.Directory(ns('/foo')); + expect(fs.currentDirectory.path, ns('/foo')); + }); + + test('throwsIfArgumentIsNotStringOrDirectory', () { + expect(() { + fs.currentDirectory = 123; + }, throwsArgumentError); + }); + + test('succeedsIfSetToRelativePath', () { + fs.directory(ns('/foo/bar')).createSync(recursive: true); + fs.currentDirectory = 'foo'; + expect(fs.currentDirectory.path, ns('/foo')); + fs.currentDirectory = 'bar'; + expect(fs.currentDirectory.path, ns('/foo/bar')); + }); + + test('succeedsIfSetToAbsolutePathWhenCwdIsNotRoot', () { + fs.directory(ns('/foo/bar')).createSync(recursive: true); + fs.directory(ns('/baz/qux')).createSync(recursive: true); + fs.currentDirectory = ns('/foo/bar'); + expect(fs.currentDirectory.path, ns('/foo/bar')); + fs.currentDirectory = fs.directory(ns('/baz/qux')); + expect(fs.currentDirectory.path, ns('/baz/qux')); + }); + + test('succeedsIfSetToParentDirectory', () { + fs.directory(ns('/foo')).createSync(); + fs.currentDirectory = 'foo'; + expect(fs.currentDirectory.path, ns('/foo')); + fs.currentDirectory = '..'; + expect(fs.currentDirectory.path, ns('/')); + }); + + test('staysAtRootIfSetToParentOfRoot', () { + fs.currentDirectory = + List<String>.filled(20, '..').join(fs.path.separator); + String cwd = fs.currentDirectory.path; + expect(cwd, fs.path.rootPrefix(cwd)); + }); + + test('removesTrailingSlashIfSet', () { + fs.directory(ns('/foo')).createSync(); + fs.currentDirectory = ns('/foo/'); + expect(fs.currentDirectory.path, ns('/foo')); + }); + + test('throwsIfSetToFilePathSegmentAtTail', () { + fs.file(ns('/foo')).createSync(); + expectFileSystemException(ErrorCodes.ENOTDIR, () { + fs.currentDirectory = ns('/foo'); + }); + }); + + test('throwsIfSetToFilePathSegmentViaTraversal', () { + fs.file(ns('/foo')).createSync(); + expectFileSystemException(ErrorCodes.ENOTDIR, () { + fs.currentDirectory = ns('/foo/bar/baz'); + }); + }); + + test('resolvesLinksIfEncountered', () { + fs.link(ns('/foo/bar/baz')).createSync(ns('/qux'), recursive: true); + fs.directory(ns('/qux')).createSync(); + fs.directory(ns('/quux')).createSync(); + fs.currentDirectory = ns('/foo/bar/baz/../quux/'); + expect(fs.currentDirectory.path, ns('/quux')); + }); + + test('succeedsIfSetToDirectoryLinkAtTail', () { + fs.directory(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + fs.currentDirectory = ns('/bar'); + expect(fs.currentDirectory.path, ns('/foo')); + }); + + test('throwsIfSetToLinkLoop', () { + fs.link(ns('/foo')).createSync(ns('/bar')); + fs.link(ns('/bar')).createSync(ns('/foo')); + expectFileSystemException( + anyOf(ErrorCodes.EMLINK, ErrorCodes.ELOOP), + () { + fs.currentDirectory = ns('/foo'); + }, + ); + }); + }); + + group('stat', () { + test('isNotFoundForEmptyPath', () { + FileStat stat = fs.statSync(''); + expect(stat.type, FileSystemEntityType.notFound); + }); + + test('isNotFoundForPathToNonExistentEntityAtTail', () { + FileStat stat = fs.statSync(ns('/foo')); + expect(stat.type, FileSystemEntityType.notFound); + }); + + test('isNotFoundForPathToNonExistentEntityInTraversal', () { + FileStat stat = fs.statSync(ns('/foo/bar')); + expect(stat.type, FileSystemEntityType.notFound); + }); + + test('isDirectoryForDirectory', () { + fs.directory(ns('/foo')).createSync(); + FileStat stat = fs.statSync(ns('/foo')); + expect(stat.type, FileSystemEntityType.directory); + }); + + test('isFileForFile', () { + fs.file(ns('/foo')).createSync(); + FileStat stat = fs.statSync(ns('/foo')); + expect(stat.type, FileSystemEntityType.file); + }); + + test('isFileForLinkToFile', () { + fs.file(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + FileStat stat = fs.statSync(ns('/bar')); + expect(stat.type, FileSystemEntityType.file); + }); + + test('isNotFoundForLinkWithCircularReference', () { + fs.link(ns('/foo')).createSync(ns('/bar')); + fs.link(ns('/bar')).createSync(ns('/baz')); + fs.link(ns('/baz')).createSync(ns('/foo')); + FileStat stat = fs.statSync(ns('/foo')); + expect(stat.type, FileSystemEntityType.notFound); + }); + }); + + group('identical', () { + test('isTrueForIdenticalPathsToExistentFile', () { + fs.file(ns('/foo')).createSync(); + expect(fs.identicalSync(ns('/foo'), ns('/foo')), true); + }); + + test('isFalseForDifferentPathsToDifferentFiles', () { + fs.file(ns('/foo')).createSync(); + fs.file(ns('/bar')).createSync(); + expect(fs.identicalSync(ns('/foo'), ns('/bar')), false); + }); + + test('isTrueForDifferentPathsToSameFileViaLinkInTraversal', () { + fs.file(ns('/foo/file')).createSync(recursive: true); + fs.link(ns('/bar')).createSync(ns('/foo')); + expect(fs.identicalSync(ns('/foo/file'), ns('/bar/file')), true); + }); + + test('isFalseForDifferentPathsToSameFileViaLinkAtTail', () { + fs.file(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + expect(fs.identicalSync(ns('/foo'), ns('/bar')), false); + }); + + test('throwsForDifferentPathsToNonExistentEntities', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.identicalSync(ns('/foo'), ns('/bar')); + }); + }); + + test('throwsForDifferentPathsToOneFileOneNonExistentEntity', () { + fs.file(ns('/foo')).createSync(); + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.identicalSync(ns('/foo'), ns('/bar')); + }); + }); + }); + + group('type', () { + test('isFileForFile', () { + fs.file(ns('/foo')).createSync(); + FileSystemEntityType type = fs.typeSync(ns('/foo')); + expect(type, FileSystemEntityType.file); + }); + + test('isDirectoryForDirectory', () { + fs.directory(ns('/foo')).createSync(); + FileSystemEntityType type = fs.typeSync(ns('/foo')); + expect(type, FileSystemEntityType.directory); + }); + + test('isDirectoryForAncestorOfRoot', () { + FileSystemEntityType type = fs + .typeSync(List<String>.filled(20, '..').join(fs.path.separator)); + expect(type, FileSystemEntityType.directory); + }); + + test('isFileForLinkToFileAndFollowLinksTrue', () { + fs.file(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + FileSystemEntityType type = fs.typeSync(ns('/bar')); + expect(type, FileSystemEntityType.file); + }); + + test('isLinkForLinkToFileAndFollowLinksFalse', () { + fs.file(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + FileSystemEntityType type = + fs.typeSync(ns('/bar'), followLinks: false); + expect(type, FileSystemEntityType.link); + }); + + test('isNotFoundForLinkWithCircularReferenceAndFollowLinksTrue', () { + fs.link(ns('/foo')).createSync(ns('/bar')); + fs.link(ns('/bar')).createSync(ns('/baz')); + fs.link(ns('/baz')).createSync(ns('/foo')); + FileSystemEntityType type = fs.typeSync(ns('/foo')); + expect(type, FileSystemEntityType.notFound); + }); + + test('isNotFoundForNoEntityAtTail', () { + FileSystemEntityType type = fs.typeSync(ns('/foo')); + expect(type, FileSystemEntityType.notFound); + }); + + test('isNotFoundForNoDirectoryInTraversal', () { + FileSystemEntityType type = fs.typeSync(ns('/foo/bar/baz')); + expect(type, FileSystemEntityType.notFound); + }); + }); + + group('isFile/isDirectory/isLink', () { + late String filePath; + late String directoryPath; + late String fileLinkPath; + late String directoryLinkPath; + + setUp(() { + filePath = ns('/file'); + directoryPath = ns('/directory'); + fileLinkPath = ns('/file-link'); + directoryLinkPath = ns('/directory-link'); + + fs.file(filePath).createSync(); + fs.directory(directoryPath).createSync(); + fs.link(fileLinkPath).createSync(filePath); + fs.link(directoryLinkPath).createSync(directoryPath); + }); + + test('isFile', () { + expect(fs.isFileSync(filePath), true); + expect(fs.isFileSync(directoryPath), false); + expect(fs.isFileSync(fileLinkPath), true); + expect(fs.isFileSync(directoryLinkPath), false); + }); + + test('isDirectory', () { + expect(fs.isDirectorySync(filePath), false); + expect(fs.isDirectorySync(directoryPath), true); + expect(fs.isDirectorySync(fileLinkPath), false); + expect(fs.isDirectorySync(directoryLinkPath), true); + }); + + test('isLink', () { + expect(fs.isLinkSync(filePath), false); + expect(fs.isLinkSync(directoryPath), false); + expect(fs.isLinkSync(fileLinkPath), true); + expect(fs.isLinkSync(directoryLinkPath), true); + }); + }); + }); + + group('Directory', () { + test('uri', () { + expect(fs.directory(ns('/foo')).uri, fs.path.toUri('${ns('/foo')}/')); + expect(fs.directory('foo').uri.toString(), 'foo/'); + }); + + group('exists', () { + test('falseIfNotExists', () { + expect(fs.directory(ns('/foo')), isNot(exists)); + expect(fs.directory('foo'), isNot(exists)); + expect(fs.directory(ns('/foo/bar')), isNot(exists)); + }); + + test('trueIfExistsAsDirectory', () { + fs.directory(ns('/foo')).createSync(); + expect(fs.directory(ns('/foo')), exists); + expect(fs.directory('foo'), exists); + }); + + test('falseIfExistsAsFile', () { + fs.file(ns('/foo')).createSync(); + expect(fs.directory(ns('/foo')), isNot(exists)); + expect(fs.directory('foo'), isNot(exists)); + }); + + test('trueIfExistsAsLinkToDirectory', () { + fs.directory(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + expect(fs.directory(ns('/bar')), exists); + expect(fs.directory('bar'), exists); + }); + + test('falseIfExistsAsLinkToFile', () { + fs.file(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + expect(fs.directory(ns('/bar')), isNot(exists)); + expect(fs.directory('bar'), isNot(exists)); + }); + + test('falseIfNotFoundSegmentExistsThenIsBackedOut', () { + fs.directory(ns('/foo')).createSync(); + expect(fs.directory(ns('/bar/../foo')), isNot(exists)); + }); + }); + + group('create', () { + test('returnsCovariantType', () async { + expect(await fs.directory(ns('/foo')).create(), isDirectory); + }); + + test('succeedsIfAlreadyExistsAsDirectory', () { + fs.directory(ns('/foo')).createSync(); + fs.directory(ns('/foo')).createSync(); + }); + + test('throwsIfAlreadyExistsAsFile', () { + fs.file(ns('/foo')).createSync(); + expectFileSystemException(ErrorCodes.ENOTDIR, () { + fs.directory(ns('/foo')).createSync(); + }); + }); + + test('succeedsIfAlreadyExistsAsLinkToDirectory', () { + fs.directory(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + fs.directory(ns('/bar')).createSync(); + }); + + test('throwsIfAlreadyExistsAsLinkToFile', () { + fs.file(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + // TODO(tvolkert): Change this to just be 'Not a directory' + // once Dart 1.22 is stable. + expectFileSystemException( + anyOf(ErrorCodes.EEXIST, ErrorCodes.ENOTDIR), + () { + fs.directory(ns('/bar')).createSync(); + }, + ); + }); + + test('throwsIfAlreadyExistsAsLinkToNotFoundAtTail', () { + fs.link(ns('/foo')).createSync(ns('/bar')); + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.directory(ns('/foo')).createSync(); + }); + }); + + test('throwsIfAlreadyExistsAsLinkToNotFoundViaTraversal', () { + fs.link(ns('/foo')).createSync(ns('/bar/baz')); + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.directory(ns('/foo')).createSync(); + }); + }); + + test('throwsIfAlreadyExistsAsLinkToNotFoundInDifferentDirectory', () { + fs.directory(ns('/foo')).createSync(); + fs.directory(ns('/bar')).createSync(); + fs.link(ns('/bar/baz')).createSync(ns('/foo/qux')); + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.directory(ns('/bar/baz')).createSync(); + }); + }); + + test('succeedsIfTailDoesntExist', () { + expect(fs.directory(ns('/')), exists); + fs.directory(ns('/foo')).createSync(); + expect(fs.directory(ns('/foo')), exists); + }); + + test('throwsIfAncestorDoesntExistRecursiveFalse', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.directory(ns('/foo/bar')).createSync(); + }); + }); + + test('succeedsIfAncestorDoesntExistRecursiveTrue', () { + fs.directory(ns('/foo/bar')).createSync(recursive: true); + expect(fs.directory(ns('/foo')), exists); + expect(fs.directory(ns('/foo/bar')), exists); + }); + }); + + group('rename', () { + test('returnsCovariantType', () async { + Directory src() => fs.directory(ns('/foo'))..createSync(); + expect(src().renameSync(ns('/bar')), isDirectory); + expect(await src().rename(ns('/baz')), isDirectory); + }); + + test('succeedsIfDestinationDoesntExist', () { + Directory src = fs.directory(ns('/foo'))..createSync(); + Directory dest = src.renameSync(ns('/bar')); + expect(dest.path, ns('/bar')); + expect(dest, exists); + }); + + test( + 'succeedsIfDestinationIsEmptyDirectory', + () { + fs.directory(ns('/bar')).createSync(); + Directory src = fs.directory(ns('/foo'))..createSync(); + Directory dest = src.renameSync(ns('/bar')); + expect(src, isNot(exists)); + expect(dest, exists); + }, + // See https://github.com/google/file.dart/issues/197. + skip: io.Platform.isWindows, + ); + + test('throwsIfDestinationIsFile', () { + fs.file(ns('/bar')).createSync(); + Directory src = fs.directory(ns('/foo'))..createSync(); + expectFileSystemException(ErrorCodes.ENOTDIR, () { + src.renameSync(ns('/bar')); + }); + }); + + test('throwsIfDestinationParentFolderDoesntExist', () { + Directory src = fs.directory(ns('/foo'))..createSync(); + expectFileSystemException(ErrorCodes.ENOENT, () { + src.renameSync(ns('/bar/baz')); + }); + }); + + test('throwsIfDestinationIsNonEmptyDirectory', () { + fs.file(ns('/bar/baz')).createSync(recursive: true); + Directory src = fs.directory(ns('/foo'))..createSync(); + // The error will be 'Directory not empty' on OS X, but it will be + // 'File exists' on Linux. + expectFileSystemException( + anyOf(ErrorCodes.ENOTEMPTY, ErrorCodes.EEXIST), + () { + src.renameSync(ns('/bar')); + }, + ); + }); + + test('throwsIfSourceDoesntExist', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.directory(ns('/foo')).renameSync(ns('/bar')); + }); + }); + + test('throwsIfSourceIsFile', () { + fs.file(ns('/foo')).createSync(); + expectFileSystemException(ErrorCodes.ENOTDIR, () { + fs.directory(ns('/foo')).renameSync(ns('/bar')); + }); + }); + + test('succeedsIfSourceIsLinkToDirectory', () { + fs.directory(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + fs.directory(ns('/bar')).renameSync(ns('/baz')); + expect(fs.typeSync(ns('/foo'), followLinks: false), + FileSystemEntityType.directory); + expect(fs.typeSync(ns('/bar')), FileSystemEntityType.notFound); + expect(fs.typeSync(ns('/baz'), followLinks: false), + FileSystemEntityType.link); + expect(fs.link(ns('/baz')).targetSync(), ns('/foo')); + }); + + test('throwsIfDestinationIsLinkToNotFound', () { + Directory src = fs.directory(ns('/foo'))..createSync(); + fs.link(ns('/bar')).createSync(ns('/baz')); + expectFileSystemException(ErrorCodes.ENOTDIR, () { + src.renameSync(ns('/bar')); + }); + }); + + test('throwsIfDestinationIsLinkToEmptyDirectory', () { + Directory src = fs.directory(ns('/foo'))..createSync(); + fs.directory(ns('/bar')).createSync(); + fs.link(ns('/baz')).createSync(ns('/bar')); + expectFileSystemException(ErrorCodes.ENOTDIR, () { + src.renameSync(ns('/baz')); + }); + }); + + test('succeedsIfDestinationIsInDifferentDirectory', () { + Directory src = fs.directory(ns('/foo'))..createSync(); + fs.directory(ns('/bar')).createSync(); + src.renameSync(ns('/bar/baz')); + expect(fs.typeSync(ns('/foo')), FileSystemEntityType.notFound); + expect(fs.typeSync(ns('/bar/baz')), FileSystemEntityType.directory); + }); + + test('succeedsIfSourceIsLinkToDifferentDirectory', () { + fs.directory(ns('/foo/subfoo')).createSync(recursive: true); + fs.directory(ns('/bar/subbar')).createSync(recursive: true); + fs.directory(ns('/baz/subbaz')).createSync(recursive: true); + fs.link(ns('/foo/subfoo/lnk')).createSync(ns('/bar/subbar')); + fs.directory(ns('/foo/subfoo/lnk')).renameSync(ns('/baz/subbaz/dst')); + expect(fs.typeSync(ns('/foo/subfoo/lnk')), + FileSystemEntityType.notFound); + expect(fs.typeSync(ns('/baz/subbaz/dst'), followLinks: false), + FileSystemEntityType.link); + expect(fs.typeSync(ns('/baz/subbaz/dst'), followLinks: true), + FileSystemEntityType.directory); + }); + }); + + group('delete', () { + test('returnsCovariantType', () async { + Directory dir = fs.directory(ns('/foo'))..createSync(); + expect(await dir.delete(), isDirectory); + }); + + test('succeedsIfEmptyDirectoryExistsAndRecursiveFalse', () { + Directory dir = fs.directory(ns('/foo'))..createSync(); + dir.deleteSync(); + expect(dir, isNot(exists)); + }); + + test('succeedsIfEmptyDirectoryExistsAndRecursiveTrue', () { + Directory dir = fs.directory(ns('/foo'))..createSync(); + dir.deleteSync(recursive: true); + expect(dir, isNot(exists)); + }); + + test('throwsIfNonEmptyDirectoryExistsAndRecursiveFalse', () { + Directory dir = fs.directory(ns('/foo'))..createSync(); + fs.file(ns('/foo/bar')).createSync(); + expectFileSystemException(ErrorCodes.ENOTEMPTY, () { + dir.deleteSync(); + }); + }); + + test('succeedsIfNonEmptyDirectoryExistsAndRecursiveTrue', () { + Directory dir = fs.directory(ns('/foo'))..createSync(); + fs.file(ns('/foo/bar')).createSync(); + dir.deleteSync(recursive: true); + expect(fs.directory(ns('/foo')), isNot(exists)); + expect(fs.file(ns('/foo/bar')), isNot(exists)); + }); + + test('throwsIfDirectoryDoesntExistAndRecursiveFalse', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.directory(ns('/foo')).deleteSync(); + }); + }); + + test('throwsIfDirectoryDoesntExistAndRecursiveTrue', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.directory(ns('/foo')).deleteSync(recursive: true); + }); + }); + + test('succeedsIfPathReferencesFileAndRecursiveTrue', () { + fs.file(ns('/foo')).createSync(); + fs.directory(ns('/foo')).deleteSync(recursive: true); + expect(fs.typeSync(ns('/foo')), FileSystemEntityType.notFound); + }); + + test('throwsIfPathReferencesFileAndRecursiveFalse', () { + fs.file(ns('/foo')).createSync(); + expectFileSystemException(ErrorCodes.ENOTDIR, () { + fs.directory(ns('/foo')).deleteSync(); + }); + }); + + test('succeedsIfPathReferencesLinkToDirectoryAndRecursiveTrue', () { + fs.directory(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + fs.directory(ns('/bar')).deleteSync(recursive: true); + expect(fs.typeSync(ns('/foo'), followLinks: false), + FileSystemEntityType.directory); + expect(fs.typeSync(ns('/bar'), followLinks: false), + FileSystemEntityType.notFound); + }); + + test('succeedsIfPathReferencesLinkToDirectoryAndRecursiveFalse', () { + fs.directory(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + fs.directory(ns('/bar')).deleteSync(); + expect(fs.typeSync(ns('/foo'), followLinks: false), + FileSystemEntityType.directory); + expect(fs.typeSync(ns('/bar'), followLinks: false), + FileSystemEntityType.notFound); + }); + + test('succeedsIfExistsAsLinkToDirectoryInDifferentDirectory', () { + fs.directory(ns('/foo/bar')).createSync(recursive: true); + fs.link(ns('/baz/qux')).createSync(ns('/foo/bar'), recursive: true); + fs.directory(ns('/baz/qux')).deleteSync(); + expect(fs.typeSync(ns('/foo/bar'), followLinks: false), + FileSystemEntityType.directory); + expect(fs.typeSync(ns('/baz/qux'), followLinks: false), + FileSystemEntityType.notFound); + }); + + test('succeedsIfPathReferencesLinkToFileAndRecursiveTrue', () { + fs.file(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + fs.directory(ns('/bar')).deleteSync(recursive: true); + expect(fs.typeSync(ns('/foo'), followLinks: false), + FileSystemEntityType.file); + expect(fs.typeSync(ns('/bar'), followLinks: false), + FileSystemEntityType.notFound); + }); + + test('throwsIfPathReferencesLinkToFileAndRecursiveFalse', () { + fs.file(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + expectFileSystemException(ErrorCodes.ENOTDIR, () { + fs.directory(ns('/bar')).deleteSync(); + }); + }); + + test('throwsIfPathReferencesLinkToNotFoundAndRecursiveFalse', () { + fs.link(ns('/foo')).createSync(ns('/bar')); + expectFileSystemException(ErrorCodes.ENOTDIR, () { + fs.directory(ns('/foo')).deleteSync(); + }); + }); + }); + + group('resolveSymbolicLinks', () { + test('succeedsForRootDirectory', () { + expect(fs.directory(ns('/')).resolveSymbolicLinksSync(), ns('/')); + }); + + test('throwsIfPathIsEmpty', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.directory('').resolveSymbolicLinksSync(); + }); + }); + + test('throwsIfLoopInLinkChain', () { + fs.link(ns('/foo')).createSync(ns('/bar')); + fs.link(ns('/bar')).createSync(ns('/baz')); + fs.link(ns('/baz')).createSync(ns('/foo')); + expectFileSystemException( + anyOf(ErrorCodes.EMLINK, ErrorCodes.ELOOP), + () { + fs.directory(ns('/foo')).resolveSymbolicLinksSync(); + }, + ); + }); + + test('throwsIfPathNotFoundInTraversal', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.directory(ns('/foo/bar')).resolveSymbolicLinksSync(); + }); + }); + + test('throwsIfPathNotFoundAtTail', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.directory(ns('/foo')).resolveSymbolicLinksSync(); + }); + }); + + test('throwsIfPathNotFoundInMiddleThenBackedOut', () { + fs.directory(ns('/foo/bar')).createSync(recursive: true); + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.directory(ns('/foo/baz/../bar')).resolveSymbolicLinksSync(); + }); + }); + + test('resolvesRelativePathToCurrentDirectory', () { + fs.directory(ns('/foo/bar')).createSync(recursive: true); + fs.link(ns('/foo/baz')).createSync(ns('/foo/bar')); + fs.currentDirectory = ns('/foo'); + expect( + fs.directory('baz').resolveSymbolicLinksSync(), ns('/foo/bar')); + }); + + test('resolvesAbsolutePathsAbsolutely', () { + fs.directory(ns('/foo/bar')).createSync(recursive: true); + fs.currentDirectory = ns('/foo'); + expect(fs.directory(ns('/foo/bar')).resolveSymbolicLinksSync(), + ns('/foo/bar')); + }); + + test('handlesRelativeLinks', () { + fs.directory(ns('/foo/bar/baz')).createSync(recursive: true); + fs.link(ns('/foo/qux')).createSync(fs.path.join('bar', 'baz')); + expect( + fs.directory(ns('/foo/qux')).resolveSymbolicLinksSync(), + ns('/foo/bar/baz'), + ); + expect( + fs.directory(fs.path.join('foo', 'qux')).resolveSymbolicLinksSync(), + ns('/foo/bar/baz'), + ); + }); + + test('handlesAbsoluteLinks', () { + fs.directory(ns('/foo')).createSync(); + fs.directory(ns('/bar/baz/qux')).createSync(recursive: true); + fs.link(ns('/foo/quux')).createSync(ns('/bar/baz/qux')); + expect(fs.directory(ns('/foo/quux')).resolveSymbolicLinksSync(), + ns('/bar/baz/qux')); + }); + + test('handlesLinksWhoseTargetsHaveNestedLinks', () { + fs.directory(ns('/foo')).createSync(); + fs.link(ns('/foo/quuz')).createSync(ns('/bar')); + fs.link(ns('/foo/grault')).createSync(ns('/baz/quux')); + fs.directory(ns('/bar')).createSync(); + fs.link(ns('/bar/qux')).createSync(ns('/baz')); + fs.link(ns('/bar/garply')).createSync(ns('/foo')); + fs.directory(ns('/baz')).createSync(); + fs.link(ns('/baz/quux')).createSync(ns('/bar/garply/quuz')); + expect(fs.directory(ns('/foo/grault/qux')).resolveSymbolicLinksSync(), + ns('/baz')); + }); + + test('handlesParentAndThisFolderReferences', () { + fs.directory(ns('/foo/bar/baz')).createSync(recursive: true); + fs.link(ns('/foo/bar/baz/qux')).createSync(fs.path.join('..', '..')); + String resolved = fs + .directory(ns('/foo/./bar/baz/../baz/qux/bar')) + .resolveSymbolicLinksSync(); + expect(resolved, ns('/foo/bar')); + }); + + test('handlesBackToBackSlashesInPath', () { + fs.directory(ns('/foo/bar/baz')).createSync(recursive: true); + expect(fs.directory(ns('//foo/bar///baz')).resolveSymbolicLinksSync(), + ns('/foo/bar/baz')); + }); + + test('handlesComplexPathWithMultipleLinks', () { + fs + .link(ns('/foo/bar/baz')) + .createSync(fs.path.join('..', '..', 'qux'), recursive: true); + fs.link(ns('/qux')).createSync('quux'); + fs.link(ns('/quux/quuz')).createSync(ns('/foo'), recursive: true); + String resolved = fs + .directory(ns('/foo//bar/./baz/quuz/bar/..///bar/baz/')) + .resolveSymbolicLinksSync(); + expect(resolved, ns('/quux')); + }); + }); + + group('absolute', () { + test('returnsCovariantType', () { + expect(fs.directory('foo').absolute, isDirectory); + }); + + test('returnsSamePathIfAlreadyAbsolute', () { + expect(fs.directory(ns('/foo')).absolute.path, ns('/foo')); + }); + + test('succeedsForRelativePaths', () { + expect(fs.directory('foo').absolute.path, ns('/foo')); + }); + }); + + group('parent', () { + late String root; + + setUp(() { + root = fs.path.style.name == 'windows' ? r'C:\' : '/'; + }); + + test('returnsCovariantType', () { + expect(fs.directory(root).parent, isDirectory); + }); + + test('returnsRootForRoot', () { + expect(fs.directory(root).parent.path, root); + }); + + test('succeedsForNonRoot', () { + expect(fs.directory(ns('/foo/bar')).parent.path, ns('/foo')); + }); + }); + + group('createTemp', () { + test('returnsCovariantType', () { + expect(fs.directory(ns('/')).createTempSync(), isDirectory); + }); + + test('throwsIfDirectoryDoesntExist', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.directory(ns('/foo')).createTempSync(); + }); + }); + + test('resolvesNameCollisions', () { + fs.directory(ns('/foo/bar')).createSync(recursive: true); + Directory tmp = fs.directory(ns('/foo')).createTempSync('bar'); + expect(tmp.path, + allOf(isNot(ns('/foo/bar')), startsWith(ns('/foo/bar')))); + }); + + test('succeedsWithoutPrefix', () { + Directory dir = fs.directory(ns('/foo'))..createSync(); + expect(dir.createTempSync().path, startsWith(ns('/foo/'))); + }); + + test('succeedsWithPrefix', () { + Directory dir = fs.directory(ns('/foo'))..createSync(); + expect(dir.createTempSync('bar').path, startsWith(ns('/foo/bar'))); + }); + + test('succeedsWithNestedPathPrefixThatExists', () { + fs.directory(ns('/foo/bar')).createSync(recursive: true); + Directory tmp = fs.directory(ns('/foo')).createTempSync('bar/baz'); + expect(tmp.path, startsWith(ns('/foo/bar/baz'))); + }); + + test('throwsWithNestedPathPrefixThatDoesntExist', () { + Directory dir = fs.directory(ns('/foo'))..createSync(); + expectFileSystemException(ErrorCodes.ENOENT, () { + dir.createTempSync('bar/baz'); + }); + }); + }); + + group('list', () { + late Directory dir; + + setUp(() { + dir = fs.currentDirectory = fs.directory(ns('/foo'))..createSync(); + fs.file('bar').createSync(); + fs.file(fs.path.join('baz', 'qux')).createSync(recursive: true); + fs.link('quux').createSync(fs.path.join('baz', 'qux')); + fs + .link(fs.path.join('baz', 'quuz')) + .createSync(fs.path.join('..', 'quux')); + fs.link(fs.path.join('baz', 'grault')).createSync('.'); + fs.currentDirectory = ns('/'); + }); + + test('returnsCovariantType', () async { + void expectIsFileSystemEntity(dynamic entity) { + expect(entity, isFileSystemEntity); + } + + dir.listSync().forEach(expectIsFileSystemEntity); + (await dir.list().toList()).forEach(expectIsFileSystemEntity); + }); + + test('returnsEmptyListForEmptyDirectory', () { + Directory empty = fs.directory(ns('/bar'))..createSync(); + expect(empty.listSync(), isEmpty); + }); + + test('throwsIfDirectoryDoesntExist', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.directory(ns('/bar')).listSync(); + }); + }); + + test('returnsLinkObjectsIfFollowLinksFalse', () { + List<FileSystemEntity> list = dir.listSync(followLinks: false); + expect(list, hasLength(3)); + expect(list, contains(allOf(isFile, hasPath(ns('/foo/bar'))))); + expect(list, contains(allOf(isDirectory, hasPath(ns('/foo/baz'))))); + expect(list, contains(allOf(isLink, hasPath(ns('/foo/quux'))))); + }); + + test('followsLinksIfFollowLinksTrue', () { + List<FileSystemEntity> list = dir.listSync(); + expect(list, hasLength(3)); + expect(list, contains(allOf(isFile, hasPath(ns('/foo/bar'))))); + expect(list, contains(allOf(isDirectory, hasPath(ns('/foo/baz'))))); + expect(list, contains(allOf(isFile, hasPath(ns('/foo/quux'))))); + }); + + test('returnsLinkObjectsForRecursiveLinkIfFollowLinksTrue', () { + expect( + dir.listSync(recursive: true), + allOf( + hasLength(9), + allOf( + contains(allOf(isFile, hasPath(ns('/foo/bar')))), + contains(allOf(isFile, hasPath(ns('/foo/quux')))), + contains(allOf(isFile, hasPath(ns('/foo/baz/qux')))), + contains(allOf(isFile, hasPath(ns('/foo/baz/quuz')))), + contains(allOf(isFile, hasPath(ns('/foo/baz/grault/qux')))), + contains(allOf(isFile, hasPath(ns('/foo/baz/grault/quuz')))), + ), + allOf( + contains(allOf(isDirectory, hasPath(ns('/foo/baz')))), + contains(allOf(isDirectory, hasPath(ns('/foo/baz/grault')))), + ), + contains(allOf(isLink, hasPath(ns('/foo/baz/grault/grault')))), + ), + ); + }); + + test('recurseIntoDirectoriesIfRecursiveTrueFollowLinksFalse', () { + expect( + dir.listSync(recursive: true, followLinks: false), + allOf( + hasLength(6), + contains(allOf(isFile, hasPath(ns('/foo/bar')))), + contains(allOf(isFile, hasPath(ns('/foo/baz/qux')))), + contains(allOf(isLink, hasPath(ns('/foo/quux')))), + contains(allOf(isLink, hasPath(ns('/foo/baz/quuz')))), + contains(allOf(isLink, hasPath(ns('/foo/baz/grault')))), + contains(allOf(isDirectory, hasPath(ns('/foo/baz')))), + ), + ); + }); + + test('childEntriesNotNormalized', () { + dir = fs.directory(ns('/bar/baz'))..createSync(recursive: true); + fs.file(ns('/bar/baz/qux')).createSync(); + List<FileSystemEntity> list = + fs.directory(ns('/bar//../bar/./baz')).listSync(); + expect(list, hasLength(1)); + expect(list[0], allOf(isFile, hasPath(ns('/bar//../bar/./baz/qux')))); + }); + + test('symlinksToNotFoundAlwaysReturnedAsLinks', () { + dir = fs.directory(ns('/bar'))..createSync(); + fs.link(ns('/bar/baz')).createSync('qux'); + for (bool followLinks in const <bool>[true, false]) { + List<FileSystemEntity> list = + dir.listSync(followLinks: followLinks); + expect(list, hasLength(1)); + expect(list[0], allOf(isLink, hasPath(ns('/bar/baz')))); + } + }); + }); + + test('childEntities', () { + Directory dir = fs.directory(ns('/foo'))..createSync(); + dir.childDirectory('bar').createSync(); + dir.childFile('baz').createSync(); + dir.childLink('qux').createSync('bar'); + expect(fs.directory(ns('/foo/bar')), exists); + expect(fs.file(ns('/foo/baz')), exists); + expect(fs.link(ns('/foo/qux')), exists); + }); + }); + + group('File', () { + test('uri', () { + expect(fs.file(ns('/foo')).uri, fs.path.toUri(ns('/foo'))); + expect(fs.file('foo').uri.toString(), 'foo'); + }); + + group('create', () { + test('returnsCovariantType', () async { + expect(await fs.file(ns('/foo')).create(), isFile); + }); + + test('succeedsIfTailDoesntAlreadyExist', () { + fs.file(ns('/foo')).createSync(); + expect(fs.file(ns('/foo')), exists); + }); + + test('succeedsIfAlreadyExistsAsFile', () { + fs.file(ns('/foo')).createSync(); + fs.file(ns('/foo')).createSync(); + expect(fs.file(ns('/foo')), exists); + }); + + test('throwsIfAncestorDoesntExistRecursiveFalse', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.file(ns('/foo/bar')).createSync(); + }); + }); + + test('succeedsIfAncestorDoesntExistRecursiveTrue', () { + fs.file(ns('/foo/bar')).createSync(recursive: true); + expect(fs.file(ns('/foo/bar')), exists); + }); + + test('throwsIfAlreadyExistsAsDirectory', () { + fs.directory(ns('/foo')).createSync(); + expectFileSystemException(ErrorCodes.EISDIR, () { + fs.file(ns('/foo')).createSync(); + }); + }); + + test('throwsIfAlreadyExistsAsLinkToDirectory', () { + fs.directory(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + expectFileSystemException(ErrorCodes.EISDIR, () { + fs.file(ns('/bar')).createSync(); + }); + }); + + test('succeedsIfAlreadyExistsAsLinkToFile', () { + fs.file(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + fs.file(ns('/bar')).createSync(); + expect(fs.file(ns('/bar')), exists); + }); + + test('succeedsIfAlreadyExistsAsLinkToNotFoundAtTail', () { + fs.link(ns('/foo')).createSync(ns('/bar')); + fs.file(ns('/foo')).createSync(); + expect(fs.typeSync(ns('/foo'), followLinks: false), + FileSystemEntityType.link); + expect(fs.typeSync(ns('/bar'), followLinks: false), + FileSystemEntityType.file); + }); + + test('throwsIfAlreadyExistsAsLinkToNotFoundViaTraversal', () { + fs.link(ns('/foo')).createSync(ns('/bar/baz')); + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.file(ns('/foo')).createSync(); + }); + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.file(ns('/foo')).createSync(recursive: true); + }); + }); + + /* + test('throwsIfPathSegmentIsLinkToNotFoundAndRecursiveTrue', () { + fs.link(ns('/foo')).createSync(ns('/bar')); + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.file(ns('/foo/baz')).createSync(recursive: true); + }); + }); + */ + + test('succeedsIfAlreadyExistsAsLinkToNotFoundInDifferentDirectory', () { + fs.directory(ns('/foo')).createSync(); + fs.directory(ns('/bar')).createSync(); + fs.link(ns('/bar/baz')).createSync(ns('/foo/qux')); + fs.file(ns('/bar/baz')).createSync(); + expect(fs.typeSync(ns('/bar/baz'), followLinks: false), + FileSystemEntityType.link); + expect(fs.typeSync(ns('/foo/qux'), followLinks: false), + FileSystemEntityType.file); + }); + }); + + group('rename', () { + test('returnsCovariantType', () async { + File f() => fs.file(ns('/foo'))..createSync(); + expect(await f().rename(ns('/bar')), isFile); + expect(f().renameSync(ns('/baz')), isFile); + }); + + test('succeedsIfDestinationDoesntExistAtTail', () { + File src = fs.file(ns('/foo'))..createSync(); + File dest = src.renameSync(ns('/bar')); + expect(fs.file(ns('/foo')), isNot(exists)); + expect(fs.file(ns('/bar')), exists); + expect(dest.path, ns('/bar')); + }); + + test('throwsIfDestinationDoesntExistViaTraversal', () { + File f = fs.file(ns('/foo'))..createSync(); + expectFileSystemException(ErrorCodes.ENOENT, () { + f.renameSync(ns('/bar/baz')); + }); + }); + + test('succeedsIfDestinationExistsAsFile', () { + File f = fs.file(ns('/foo'))..createSync(); + fs.file(ns('/bar')).createSync(); + f.renameSync(ns('/bar')); + expect(fs.file(ns('/foo')), isNot(exists)); + expect(fs.file(ns('/bar')), exists); + }); + + test('throwsIfDestinationExistsAsDirectory', () { + File f = fs.file(ns('/foo'))..createSync(); + fs.directory(ns('/bar')).createSync(); + expectFileSystemException(ErrorCodes.EISDIR, () { + f.renameSync(ns('/bar')); + }); + }); + + test('succeedsIfDestinationExistsAsLinkToFile', () { + File f = fs.file(ns('/foo'))..createSync(); + fs.file(ns('/bar')).createSync(); + fs.link(ns('/baz')).createSync(ns('/bar')); + f.renameSync(ns('/baz')); + expect(fs.typeSync(ns('/foo')), FileSystemEntityType.notFound); + expect(fs.typeSync(ns('/bar'), followLinks: false), + FileSystemEntityType.file); + expect(fs.typeSync(ns('/baz'), followLinks: false), + FileSystemEntityType.file); + }); + + test('throwsIfDestinationExistsAsLinkToDirectory', () { + File f = fs.file(ns('/foo'))..createSync(); + fs.directory(ns('/bar')).createSync(); + fs.link(ns('/baz')).createSync(ns('/bar')); + expectFileSystemException(ErrorCodes.EISDIR, () { + f.renameSync(ns('/baz')); + }); + }); + + test('succeedsIfDestinationExistsAsLinkToNotFound', () { + File f = fs.file(ns('/foo'))..createSync(); + fs.link(ns('/bar')).createSync(ns('/baz')); + f.renameSync(ns('/bar')); + expect(fs.typeSync(ns('/foo')), FileSystemEntityType.notFound); + expect(fs.typeSync(ns('/bar'), followLinks: false), + FileSystemEntityType.file); + }); + + test('throwsIfSourceDoesntExist', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.file(ns('/foo')).renameSync(ns('/bar')); + }); + }); + + test('throwsIfSourceExistsAsDirectory', () { + fs.directory(ns('/foo')).createSync(); + expectFileSystemException(ErrorCodes.EISDIR, () { + fs.file(ns('/foo')).renameSync(ns('/bar')); + }); + }); + + test('succeedsIfSourceExistsAsLinkToFile', () { + fs.file(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + fs.file(ns('/bar')).renameSync(ns('/baz')); + expect(fs.typeSync(ns('/bar')), FileSystemEntityType.notFound); + expect(fs.typeSync(ns('/baz'), followLinks: false), + FileSystemEntityType.link); + expect(fs.typeSync(ns('/baz'), followLinks: true), + FileSystemEntityType.file); + }); + + test('throwsIfSourceExistsAsLinkToDirectory', () { + fs.directory(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + expectFileSystemException(ErrorCodes.EISDIR, () { + fs.file(ns('/bar')).renameSync(ns('/baz')); + }); + }); + + test('throwsIfSourceExistsAsLinkToNotFound', () { + fs.link(ns('/foo')).createSync(ns('/bar')); + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.file(ns('/foo')).renameSync(ns('/baz')); + }); + }); + }); + + group('copy', () { + test('returnsCovariantType', () async { + File f() => fs.file(ns('/foo'))..createSync(); + expect(await f().copy(ns('/bar')), isFile); + expect(f().copySync(ns('/baz')), isFile); + }); + + test('succeedsIfDestinationDoesntExistAtTail', () { + File f = fs.file(ns('/foo')) + ..createSync() + ..writeAsStringSync('foo'); + f.copySync(ns('/bar')); + expect(fs.file(ns('/foo')), exists); + expect(fs.file(ns('/bar')), exists); + expect(fs.file(ns('/foo')).readAsStringSync(), 'foo'); + }); + + test('throwsIfDestinationDoesntExistViaTraversal', () { + File f = fs.file(ns('/foo'))..createSync(); + expectFileSystemException(ErrorCodes.ENOENT, () { + f.copySync(ns('/bar/baz')); + }); + }); + + test('succeedsIfDestinationExistsAsFile', () { + File f = fs.file(ns('/foo')) + ..createSync() + ..writeAsStringSync('foo'); + fs.file(ns('/bar')) + ..createSync() + ..writeAsStringSync('bar'); + f.copySync(ns('/bar')); + expect(fs.file(ns('/foo')), exists); + expect(fs.file(ns('/bar')), exists); + expect(fs.file(ns('/foo')).readAsStringSync(), 'foo'); + expect(fs.file(ns('/bar')).readAsStringSync(), 'foo'); + }); + + test('throwsIfDestinationExistsAsDirectory', () { + File f = fs.file(ns('/foo'))..createSync(); + fs.directory(ns('/bar')).createSync(); + expectFileSystemException(ErrorCodes.EISDIR, () { + f.copySync(ns('/bar')); + }); + }); + + test('succeedsIfDestinationExistsAsLinkToFile', () { + File f = fs.file(ns('/foo')) + ..createSync() + ..writeAsStringSync('foo'); + fs.file(ns('/bar')) + ..createSync() + ..writeAsStringSync('bar'); + fs.link(ns('/baz')).createSync(ns('/bar')); + f.copySync(ns('/baz')); + expect(fs.typeSync(ns('/foo'), followLinks: false), + FileSystemEntityType.file); + expect(fs.typeSync(ns('/bar'), followLinks: false), + FileSystemEntityType.file); + expect(fs.typeSync(ns('/baz'), followLinks: false), + FileSystemEntityType.link); + expect(fs.file(ns('/foo')).readAsStringSync(), 'foo'); + expect(fs.file(ns('/bar')).readAsStringSync(), 'foo'); + }, skip: io.Platform.isWindows /* No links on Windows */); + + test('throwsIfDestinationExistsAsLinkToDirectory', () { + File f = fs.file(ns('/foo'))..createSync(); + fs.directory(ns('/bar')).createSync(); + fs.link(ns('/baz')).createSync(ns('/bar')); + expectFileSystemException(ErrorCodes.EISDIR, () { + f.copySync(ns('/baz')); + }); + }); + + test('throwsIfSourceDoesntExist', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.file(ns('/foo')).copySync(ns('/bar')); + }); + }); + + test('throwsIfSourceExistsAsDirectory', () { + fs.directory(ns('/foo')).createSync(); + expectFileSystemException(ErrorCodes.EISDIR, () { + fs.file(ns('/foo')).copySync(ns('/bar')); + }); + }); + + test('succeedsIfSourceExistsAsLinkToFile', () { + fs.file(ns('/foo')) + ..createSync() + ..writeAsStringSync('foo'); + fs.link(ns('/bar')).createSync(ns('/foo')); + fs.file(ns('/bar')).copySync(ns('/baz')); + expect(fs.typeSync(ns('/foo'), followLinks: false), + FileSystemEntityType.file); + expect(fs.typeSync(ns('/bar'), followLinks: false), + FileSystemEntityType.link); + expect(fs.typeSync(ns('/baz'), followLinks: false), + FileSystemEntityType.file); + expect(fs.file(ns('/foo')).readAsStringSync(), 'foo'); + expect(fs.file(ns('/baz')).readAsStringSync(), 'foo'); + }); + + test('succeedsIfDestinationIsInDifferentDirectoryThanSource', () { + File f = fs.file(ns('/foo/bar')) + ..createSync(recursive: true) + ..writeAsStringSync('foo'); + fs.directory(ns('/baz')).createSync(); + f.copySync(ns('/baz/qux')); + expect(fs.file(ns('/foo/bar')), exists); + expect(fs.file(ns('/baz/qux')), exists); + expect(fs.file(ns('/foo/bar')).readAsStringSync(), 'foo'); + expect(fs.file(ns('/baz/qux')).readAsStringSync(), 'foo'); + }); + + test('succeedsIfSourceIsLinkToFileInDifferentDirectory', () { + fs.file(ns('/foo/bar')) + ..createSync(recursive: true) + ..writeAsStringSync('foo'); + fs.link(ns('/baz/qux')).createSync(ns('/foo/bar'), recursive: true); + fs.file(ns('/baz/qux')).copySync(ns('/baz/quux')); + expect(fs.typeSync(ns('/foo/bar'), followLinks: false), + FileSystemEntityType.file); + expect(fs.typeSync(ns('/baz/qux'), followLinks: false), + FileSystemEntityType.link); + expect(fs.typeSync(ns('/baz/quux'), followLinks: false), + FileSystemEntityType.file); + expect(fs.file(ns('/foo/bar')).readAsStringSync(), 'foo'); + expect(fs.file(ns('/baz/quux')).readAsStringSync(), 'foo'); + }); + + test('succeedsIfDestinationIsLinkToFileInDifferentDirectory', () { + fs.file(ns('/foo/bar')) + ..createSync(recursive: true) + ..writeAsStringSync('bar'); + fs.file(ns('/baz/qux')) + ..createSync(recursive: true) + ..writeAsStringSync('qux'); + fs.link(ns('/baz/quux')).createSync(ns('/foo/bar')); + fs.file(ns('/baz/qux')).copySync(ns('/baz/quux')); + expect(fs.typeSync(ns('/foo/bar'), followLinks: false), + FileSystemEntityType.file); + expect(fs.typeSync(ns('/baz/qux'), followLinks: false), + FileSystemEntityType.file); + expect(fs.typeSync(ns('/baz/quux'), followLinks: false), + FileSystemEntityType.link); + expect(fs.file(ns('/foo/bar')).readAsStringSync(), 'qux'); + expect(fs.file(ns('/baz/qux')).readAsStringSync(), 'qux'); + }, skip: io.Platform.isWindows /* No links on Windows */); + }); + + group('length', () { + test('throwsIfDoesntExist', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.file(ns('/foo')).lengthSync(); + }); + }); + + test('throwsIfExistsAsDirectory', () { + fs.directory(ns('/foo')).createSync(); + expectFileSystemException(ErrorCodes.EISDIR, () { + fs.file(ns('/foo')).lengthSync(); + }); + }); + + test('returnsZeroForNewlyCreatedFile', () { + File f = fs.file(ns('/foo'))..createSync(); + expect(f.lengthSync(), 0); + }); + + test('writeNBytesReturnsLengthN', () { + File f = fs.file(ns('/foo'))..createSync(); + f.writeAsBytesSync(<int>[1, 2, 3, 4], flush: true); + expect(f.lengthSync(), 4); + }); + + test('succeedsIfExistsAsLinkToFile', () { + fs.file(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + expect(fs.file(ns('/bar')).lengthSync(), 0); + }); + }); + + group('absolute', () { + test('returnsSamePathIfAlreadyAbsolute', () { + expect(fs.file(ns('/foo')).absolute.path, ns('/foo')); + }); + + test('succeedsForRelativePaths', () { + expect(fs.file('foo').absolute.path, ns('/foo')); + }); + }); + + group('lastAccessed', () { + test('isNowForNewlyCreatedFile', () { + DateTime before = downstairs(); + File f = fs.file(ns('/foo'))..createSync(); + DateTime after = ceil(); + DateTime accessed = f.lastAccessedSync(); + expect(accessed, isSameOrAfter(before)); + expect(accessed, isSameOrBefore(after)); + }); + + test('throwsIfDoesntExist', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.file(ns('/foo')).lastAccessedSync(); + }); + }); + + test('throwsIfExistsAsDirectory', () { + fs.directory(ns('/foo')).createSync(); + expectFileSystemException(ErrorCodes.EISDIR, () { + fs.file(ns('/foo')).lastAccessedSync(); + }); + }); + + test('succeedsIfExistsAsLinkToFile', () { + DateTime before = downstairs(); + fs.file(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + DateTime after = ceil(); + DateTime accessed = fs.file(ns('/bar')).lastAccessedSync(); + expect(accessed, isSameOrAfter(before)); + expect(accessed, isSameOrBefore(after)); + }); + }); + + group('setLastAccessed', () { + final DateTime time = DateTime(1999); + + test('throwsIfDoesntExist', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.file(ns('/foo')).setLastAccessedSync(time); + }); + }); + + test('throwsIfExistsAsDirectory', () { + fs.directory(ns('/foo')).createSync(); + expectFileSystemException(ErrorCodes.EISDIR, () { + fs.file(ns('/foo')).setLastAccessedSync(time); + }); + }); + + test('succeedsIfExistsAsFile', () { + File f = fs.file(ns('/foo'))..createSync(); + f.setLastAccessedSync(time); + expect(fs.file(ns('/foo')).lastAccessedSync(), time); + }); + + test('succeedsIfExistsAsLinkToFile', () { + File f = fs.file(ns('/foo'))..createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + f.setLastAccessedSync(time); + expect(fs.file(ns('/bar')).lastAccessedSync(), time); + }); + }); + + group('lastModified', () { + test('isNowForNewlyCreatedFile', () { + DateTime before = downstairs(); + File f = fs.file(ns('/foo'))..createSync(); + DateTime after = ceil(); + DateTime modified = f.lastModifiedSync(); + expect(modified, isSameOrAfter(before)); + expect(modified, isSameOrBefore(after)); + }); + + test('throwsIfDoesntExist', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.file(ns('/foo')).lastModifiedSync(); + }); + }); + + test('throwsIfExistsAsDirectory', () { + fs.directory(ns('/foo')).createSync(); + expectFileSystemException(ErrorCodes.EISDIR, () { + fs.file(ns('/foo')).lastModifiedSync(); + }); + }); + + test('succeedsIfExistsAsLinkToFile', () { + DateTime before = downstairs(); + fs.file(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + DateTime after = ceil(); + DateTime modified = fs.file(ns('/bar')).lastModifiedSync(); + expect(modified, isSameOrAfter(before)); + expect(modified, isSameOrBefore(after)); + }); + }); + + group('setLastModified', () { + final DateTime time = DateTime(1999); + + test('throwsIfDoesntExist', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.file(ns('/foo')).setLastModifiedSync(time); + }); + }); + + test('throwsIfExistsAsDirectory', () { + fs.directory(ns('/foo')).createSync(); + expectFileSystemException(ErrorCodes.EISDIR, () { + fs.file(ns('/foo')).setLastModifiedSync(time); + }); + }); + + test('succeedsIfExistsAsFile', () { + File f = fs.file(ns('/foo'))..createSync(); + f.setLastModifiedSync(time); + expect(fs.file(ns('/foo')).lastModifiedSync(), time); + }); + + test('succeedsIfExistsAsLinkToFile', () { + File f = fs.file(ns('/foo'))..createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + f.setLastModifiedSync(time); + expect(fs.file(ns('/bar')).lastModifiedSync(), time); + }); + }); + + group('open', () { + void testIfDoesntExistAtTail(FileMode mode) { + if (mode == FileMode.read) { + test('throwsIfDoesntExistAtTail', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.file(ns('/bar')).openSync(mode: mode); + }); + }); + } else { + test('createsFileIfDoesntExistAtTail', () { + RandomAccessFile raf = fs.file(ns('/bar')).openSync(mode: mode); + raf.closeSync(); + expect(fs.file(ns('/bar')), exists); + }); + } + } + + void testThrowsIfDoesntExistViaTraversal(FileMode mode) { + test('throwsIfDoesntExistViaTraversal', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.file(ns('/bar/baz')).openSync(mode: mode); + }); + }); + } + + void testRandomAccessFileOperations(FileMode mode) { + group('RandomAccessFile', () { + late File f; + late RandomAccessFile raf; + + setUp(() { + f = fs.file(ns('/foo'))..createSync(); + f.writeAsStringSync('pre-existing content\n', flush: true); + raf = f.openSync(mode: mode); + }); + + tearDown(() { + try { + raf.closeSync(); + } on FileSystemException { + // Ignore; a test may have already closed it. + } + }); + + test('succeedsIfClosedAfterClosed', () { + raf.closeSync(); + expectFileSystemException(null, () { + raf.closeSync(); + }); + }); + + test('throwsIfReadAfterClose', () { + raf.closeSync(); + expectFileSystemException(null, () { + raf.readByteSync(); + }); + }); + + test('throwsIfWriteAfterClose', () { + raf.closeSync(); + expectFileSystemException(null, () { + raf.writeByteSync(0xBAD); + }); + }); + + test('throwsIfTruncateAfterClose', () { + raf.closeSync(); + expectFileSystemException(null, () { + raf.truncateSync(0); + }); + }); + + if (mode == FileMode.write || mode == FileMode.writeOnly) { + test('lengthIsResetToZeroIfOpened', () { + expect(raf.lengthSync(), equals(0)); + }); + + test('throwsIfAsyncUnawaited', () async { + try { + final Future<void> future = raf.flush(); + expectFileSystemException(null, () => raf.flush()); + expectFileSystemException(null, () => raf.flushSync()); + await expectLater(future, completes); + raf.flushSync(); + } finally { + raf.closeSync(); + } + }); + } else { + test('lengthIsNotModifiedIfOpened', () { + expect(raf.lengthSync(), isNot(equals(0))); + }); + } + + if (mode == FileMode.writeOnly || + mode == FileMode.writeOnlyAppend) { + test('throwsIfReadByte', () { + expectFileSystemException(ErrorCodes.EBADF, () { + raf.readByteSync(); + }); + }); + + test('throwsIfRead', () { + expectFileSystemException(ErrorCodes.EBADF, () { + raf.readSync(2); + }); + }); + + test('throwsIfReadInto', () { + expectFileSystemException(ErrorCodes.EBADF, () { + raf.readIntoSync(List<int>.filled(5, 0)); + }); + }); + } else { + group('read', () { + setUp(() { + if (mode == FileMode.write) { + // Write data back that we truncated when opening the file. + raf.writeStringSync('pre-existing content\n'); + } + // Reset the position to zero so we can read the content. + raf.setPositionSync(0); + }); + + test('readByte', () { + expect(utf8.decode(<int>[raf.readByteSync()]), 'p'); + }); + + test('read', () { + List<int> bytes = raf.readSync(1024); + expect(bytes.length, 21); + expect(utf8.decode(bytes), 'pre-existing content\n'); + }); + + test('readIntoWithBufferLargerThanContent', () { + List<int> buffer = List<int>.filled(1024, 0); + int numRead = raf.readIntoSync(buffer); + expect(numRead, 21); + expect(utf8.decode(buffer.sublist(0, 21)), + 'pre-existing content\n'); + }); + + test('readIntoWithBufferSmallerThanContent', () { + List<int> buffer = List<int>.filled(10, 0); + int numRead = raf.readIntoSync(buffer); + expect(numRead, 10); + expect(utf8.decode(buffer), 'pre-existi'); + }); + + test('readIntoWithStart', () { + List<int> buffer = List<int>.filled(10, 0); + int numRead = raf.readIntoSync(buffer, 2); + expect(numRead, 8); + expect(utf8.decode(buffer.sublist(2)), 'pre-exis'); + }); + + test('readIntoWithStartAndEnd', () { + List<int> buffer = List<int>.filled(10, 0); + int numRead = raf.readIntoSync(buffer, 2, 5); + expect(numRead, 3); + expect(utf8.decode(buffer.sublist(2, 5)), 'pre'); + }); + + test('openReadHandleDoesNotChange', () { + final String initial = utf8.decode(raf.readSync(4)); + expect(initial, 'pre-'); + final File newFile = f.renameSync(ns('/bar')); + String rest = utf8.decode(raf.readSync(1024)); + expect(rest, 'existing content\n'); + + assert(newFile.path != f.path); + expect(f, isNot(exists)); + expect(newFile, exists); + + // [RandomAccessFile.path] always returns the original path. + expect(raf.path, f.path); + }); + }); + } + + if (mode == FileMode.read) { + test('throwsIfWriteByte', () { + expectFileSystemException(ErrorCodes.EBADF, () { + raf.writeByteSync(0xBAD); + }); + }); + + test('throwsIfWriteFrom', () { + expectFileSystemException(ErrorCodes.EBADF, () { + raf.writeFromSync(<int>[1, 2, 3, 4]); + }); + }); + + test('throwsIfWriteString', () { + expectFileSystemException(ErrorCodes.EBADF, () { + raf.writeStringSync('This should throw.'); + }); + }); + } else { + test('lengthGrowsAsDataIsWritten', () { + int lengthBefore = f.lengthSync(); + raf.writeByteSync(0xFACE); + expect(raf.lengthSync(), lengthBefore + 1); + }); + + test('flush', () { + int lengthBefore = f.lengthSync(); + raf.writeByteSync(0xFACE); + raf.flushSync(); + expect(f.lengthSync(), lengthBefore + 1); + }); + + test('writeByte', () { + raf.writeByteSync(utf8.encode('A').first); + raf.flushSync(); + if (mode == FileMode.write || mode == FileMode.writeOnly) { + expect(f.readAsStringSync(), 'A'); + } else { + expect(f.readAsStringSync(), 'pre-existing content\nA'); + } + }); + + test('writeFrom', () { + raf.writeFromSync(utf8.encode('Hello world')); + raf.flushSync(); + if (mode == FileMode.write || mode == FileMode.writeOnly) { + expect(f.readAsStringSync(), 'Hello world'); + } else { + expect(f.readAsStringSync(), + 'pre-existing content\nHello world'); + } + }); + + test('writeFromWithStart', () { + raf.writeFromSync(utf8.encode('Hello world'), 2); + raf.flushSync(); + if (mode == FileMode.write || mode == FileMode.writeOnly) { + expect(f.readAsStringSync(), 'llo world'); + } else { + expect( + f.readAsStringSync(), 'pre-existing content\nllo world'); + } + }); + + test('writeFromWithStartAndEnd', () { + raf.writeFromSync(utf8.encode('Hello world'), 2, 5); + raf.flushSync(); + if (mode == FileMode.write || mode == FileMode.writeOnly) { + expect(f.readAsStringSync(), 'llo'); + } else { + expect(f.readAsStringSync(), 'pre-existing content\nllo'); + } + }); + + test('writeString', () { + raf.writeStringSync('Hello world'); + raf.flushSync(); + if (mode == FileMode.write || mode == FileMode.writeOnly) { + expect(f.readAsStringSync(), 'Hello world'); + } else { + expect(f.readAsStringSync(), + 'pre-existing content\nHello world'); + } + }); + + test('openWriteHandleDoesNotChange', () { + raf.writeStringSync('Hello '); + final File newFile = f.renameSync(ns('/bar')); + raf.writeStringSync('world'); + + final String contents = newFile.readAsStringSync(); + if (mode == FileMode.write || mode == FileMode.writeOnly) { + expect(contents, 'Hello world'); + } else { + expect(contents, 'pre-existing content\nHello world'); + } + + assert(newFile.path != f.path); + expect(f, isNot(exists)); + expect(newFile, exists); + + // [RandomAccessFile.path] always returns the original path. + expect(raf.path, f.path); + }); + } + + if (mode == FileMode.append || mode == FileMode.writeOnlyAppend) { + test('positionInitializedToEndOfFile', () { + expect(raf.positionSync(), 21); + }); + } else { + test('positionInitializedToZero', () { + expect(raf.positionSync(), 0); + }); + } + + group('position', () { + setUp(() { + if (mode == FileMode.write || mode == FileMode.writeOnly) { + // Write data back that we truncated when opening the file. + raf.writeStringSync('pre-existing content\n'); + } + }); + + if (mode != FileMode.writeOnly && + mode != FileMode.writeOnlyAppend) { + test('growsAfterRead', () { + raf.setPositionSync(0); + raf.readSync(10); + expect(raf.positionSync(), 10); + }); + + test('affectsRead', () { + raf.setPositionSync(5); + expect(utf8.decode(raf.readSync(5)), 'xisti'); + }); + } + + if (mode == FileMode.read) { + test('succeedsIfSetPastEndOfFile', () { + raf.setPositionSync(32); + expect(raf.positionSync(), 32); + }); + } else { + test('growsAfterWrite', () { + int positionBefore = raf.positionSync(); + raf.writeStringSync('Hello world'); + expect(raf.positionSync(), positionBefore + 11); + }); + + test('affectsWrite', () { + raf.setPositionSync(5); + raf.writeStringSync('-yo-'); + raf.flushSync(); + expect(f.readAsStringSync(), 'pre-e-yo-ing content\n'); + }); + + test('succeedsIfSetAndWrittenPastEndOfFile', () { + raf.setPositionSync(32); + expect(raf.positionSync(), 32); + raf.writeStringSync('here'); + raf.flushSync(); + List<int> bytes = f.readAsBytesSync(); + expect(bytes.length, 36); + expect(utf8.decode(bytes.sublist(0, 21)), + 'pre-existing content\n'); + expect(utf8.decode(bytes.sublist(32, 36)), 'here'); + expect(bytes.sublist(21, 32), everyElement(0)); + }); + } + + test('throwsIfSetToNegativeNumber', () { + expectFileSystemException(ErrorCodes.EINVAL, () { + raf.setPositionSync(-12); + }); + }); + }); + + if (mode == FileMode.read) { + test('throwsIfTruncate', () { + expectFileSystemException(ErrorCodes.EINVAL, () { + raf.truncateSync(5); + }); + }); + } else { + group('truncate', () { + setUp(() { + if (mode == FileMode.write || mode == FileMode.writeOnly) { + // Write data back that we truncated when opening the file. + raf.writeStringSync('pre-existing content\n'); + } + }); + + test('succeedsIfSetWithinRangeOfContent', () { + raf.truncateSync(5); + raf.flushSync(); + expect(f.lengthSync(), 5); + expect(f.readAsStringSync(), 'pre-e'); + }); + + test('succeedsIfSetToZero', () { + raf.truncateSync(0); + raf.flushSync(); + expect(f.lengthSync(), 0); + expect(f.readAsStringSync(), isEmpty); + }); + + test('throwsIfSetToNegativeNumber', () { + expectFileSystemException(ErrorCodes.EINVAL, () { + raf.truncateSync(-2); + }); + }); + + test('extendsFileIfSetPastEndOfFile', () { + raf.truncateSync(32); + raf.flushSync(); + List<int> bytes = f.readAsBytesSync(); + expect(bytes.length, 32); + expect(utf8.decode(bytes.sublist(0, 21)), + 'pre-existing content\n'); + expect(bytes.sublist(21, 32), everyElement(0)); + }); + }); + } + }); + } + + void testOpenWithMode(FileMode mode) { + testIfDoesntExistAtTail(mode); + testThrowsIfDoesntExistViaTraversal(mode); + testRandomAccessFileOperations(mode); + } + + group('READ', () => testOpenWithMode(FileMode.read)); + group('WRITE', () => testOpenWithMode(FileMode.write)); + group('APPEND', () => testOpenWithMode(FileMode.append)); + group('WRITE_ONLY', () => testOpenWithMode(FileMode.writeOnly)); + group('WRITE_ONLY_APPEND', + () => testOpenWithMode(FileMode.writeOnlyAppend)); + }); + + group('openRead', () { + test('throwsIfDoesntExist', () { + Stream<List<int>> stream = fs.file(ns('/foo')).openRead(); + expect(stream.drain<void>(), + throwsFileSystemException(ErrorCodes.ENOENT)); + }); + + test('succeedsIfExistsAsFile', () async { + File f = fs.file(ns('/foo'))..createSync(); + f.writeAsStringSync('Hello world', flush: true); + Stream<List<int>> stream = f.openRead(); + List<List<int>> data = await stream.toList(); + expect(data, hasLength(1)); + expect(utf8.decode(data[0]), 'Hello world'); + }); + + test('throwsIfExistsAsDirectory', () { + fs.directory(ns('/foo')).createSync(); + Stream<List<int>> stream = fs.file(ns('/foo')).openRead(); + expect(stream.drain<void>(), + throwsFileSystemException(ErrorCodes.EISDIR)); + }); + + test('succeedsIfExistsAsLinkToFile', () async { + File f = fs.file(ns('/foo'))..createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + f.writeAsStringSync('Hello world', flush: true); + Stream<List<int>> stream = fs.file(ns('/bar')).openRead(); + List<List<int>> data = await stream.toList(); + expect(data, hasLength(1)); + expect(utf8.decode(data[0]), 'Hello world'); + }); + + test('respectsStartAndEndParameters', () async { + File f = fs.file(ns('/foo'))..createSync(); + f.writeAsStringSync('Hello world', flush: true); + Stream<List<int>> stream = f.openRead(2); + List<List<int>> data = await stream.toList(); + expect(data, hasLength(1)); + expect(utf8.decode(data[0]), 'llo world'); + stream = f.openRead(2, 5); + data = await stream.toList(); + expect(data, hasLength(1)); + expect(utf8.decode(data[0]), 'llo'); + }); + + test('throwsIfStartParameterIsNegative', () async { + File f = fs.file(ns('/foo'))..createSync(); + Stream<List<int>> stream = f.openRead(-2); + expect(stream.drain<void>(), throwsRangeError); + }); + + test('stopsAtEndOfFileIfEndParameterIsPastEndOfFile', () async { + File f = fs.file(ns('/foo'))..createSync(); + f.writeAsStringSync('Hello world', flush: true); + Stream<List<int>> stream = f.openRead(2, 1024); + List<List<int>> data = await stream.toList(); + expect(data, hasLength(1)); + expect(utf8.decode(data[0]), 'llo world'); + }); + + test('providesSingleSubscriptionStream', () async { + File f = fs.file(ns('/foo'))..createSync(); + f.writeAsStringSync('Hello world', flush: true); + Stream<List<int>> stream = f.openRead(); + expect(stream.isBroadcast, isFalse); + await stream.drain<void>(); + }); + + test('openReadHandleDoesNotChange', () async { + // Ideally, `data` should be large enough so that its contents are + // split across multiple chunks in the [Stream]. However, there + // doesn't seem to be a good way to determine the chunk size used by + // [io.File]. + final List<int> data = List<int>.generate( + 1024 * 256, + (int index) => index & 0xFF, + growable: false, + ); + + final File f = fs.file(ns('/foo'))..createSync(); + + f.writeAsBytesSync(data, flush: true); + final Stream<List<int>> stream = f.openRead(); + + File? newFile; + List<int>? initialChunk; + final List<int> remainingChunks = <int>[]; + + await for (List<int> chunk in stream) { + if (initialChunk == null) { + initialChunk = chunk; + assert(initialChunk.isNotEmpty); + expect(initialChunk, data.getRange(0, initialChunk.length)); + + newFile = f.renameSync(ns('/bar')); + } else { + remainingChunks.addAll(chunk); + } + } + + expect( + remainingChunks, + data.getRange(initialChunk!.length, data.length), + ); + + assert(newFile?.path != f.path); + expect(f, isNot(exists)); + expect(newFile, exists); + }); + + test('openReadCompatibleWithUtf8Decoder', () async { + const content = 'Hello world!'; + File file = fs.file(ns('/foo')) + ..createSync() + ..writeAsStringSync(content); + expect( + await file + .openRead() + .transform(utf8.decoder) + .transform(const LineSplitter()) + .first, + content, + ); + }); + }); + + group('openWrite', () { + test('createsFileIfDoesntExist', () async { + await fs.file(ns('/foo')).openWrite().close(); + expect(fs.file(ns('/foo')), exists); + }); + + test('throwsIfExistsAsDirectory', () { + fs.directory(ns('/foo')).createSync(); + expect(fs.file(ns('/foo')).openWrite().close(), + throwsFileSystemException(ErrorCodes.EISDIR)); + }); + + test('throwsIfExistsAsLinkToDirectory', () { + fs.directory(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + expect(fs.file(ns('/bar')).openWrite().close(), + throwsFileSystemException(ErrorCodes.EISDIR)); + }); + + test('throwsIfModeIsRead', () { + expect(() => fs.file(ns('/foo')).openWrite(mode: FileMode.read), + throwsArgumentError); + }); + + test('succeedsIfExistsAsEmptyFile', () async { + File f = fs.file(ns('/foo'))..createSync(); + IOSink sink = f.openWrite(); + sink.write('Hello world'); + await sink.flush(); + await sink.close(); + expect(f.readAsStringSync(), 'Hello world'); + }); + + test('succeedsIfExistsAsLinkToFile', () async { + fs.file(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + IOSink sink = fs.file(ns('/bar')).openWrite(); + sink.write('Hello world'); + await sink.flush(); + await sink.close(); + expect(fs.file(ns('/foo')).readAsStringSync(), 'Hello world'); + }); + + test('overwritesContentInWriteMode', () async { + File f = fs.file(ns('/foo'))..createSync(); + f.writeAsStringSync('Hello'); + IOSink sink = f.openWrite(); + sink.write('Goodbye'); + await sink.flush(); + await sink.close(); + expect(fs.file(ns('/foo')).readAsStringSync(), 'Goodbye'); + }); + + test('appendsContentInAppendMode', () async { + File f = fs.file(ns('/foo'))..createSync(); + f.writeAsStringSync('Hello'); + IOSink sink = f.openWrite(mode: FileMode.append); + sink.write('Goodbye'); + await sink.flush(); + await sink.close(); + expect(fs.file(ns('/foo')).readAsStringSync(), 'HelloGoodbye'); + }); + + test('openWriteHandleDoesNotChange', () async { + File f = fs.file(ns('/foo'))..createSync(); + IOSink sink = f.openWrite(); + sink.write('Hello'); + await sink.flush(); + + final File newFile = f.renameSync(ns('/bar')); + sink.write('Goodbye'); + await sink.flush(); + await sink.close(); + + expect(newFile.readAsStringSync(), 'HelloGoodbye'); + + assert(newFile.path != f.path); + expect(f, isNot(exists)); + expect(newFile, exists); + }); + + group('ioSink', () { + late File f; + late IOSink sink; + late bool isSinkClosed; + + Future<dynamic> closeSink() { + Future<dynamic> future = sink.close(); + isSinkClosed = true; + return future; + } + + setUp(() { + f = fs.file(ns('/foo')); + sink = f.openWrite(); + isSinkClosed = false; + }); + + tearDown(() async { + if (!isSinkClosed) { + await closeSink(); + } + }); + + test('throwsIfAddError', () async { + sink.addError(ArgumentError()); + expect(sink.done, throwsArgumentError); + isSinkClosed = true; + }); + + test('allowsChangingEncoding', () async { + sink.encoding = latin1; + sink.write('ÿ'); + sink.encoding = utf8; + sink.write('ÿ'); + await sink.flush(); + expect(await f.readAsBytes(), <int>[255, 195, 191]); + }); + + test('succeedsIfAddRawData', () async { + sink.add(<int>[1, 2, 3, 4]); + await sink.flush(); + expect(await f.readAsBytes(), <int>[1, 2, 3, 4]); + }); + + test('succeedsIfWrite', () async { + sink.write('Hello world'); + await sink.flush(); + expect(await f.readAsString(), 'Hello world'); + }); + + test('succeedsIfWriteAll', () async { + sink.writeAll(<String>['foo', 'bar', 'baz'], ' '); + await sink.flush(); + expect(await f.readAsString(), 'foo bar baz'); + }); + + test('succeedsIfWriteCharCode', () async { + sink.writeCharCode(35); + await sink.flush(); + expect(await f.readAsString(), '#'); + }); + + test('succeedsIfWriteln', () async { + sink.writeln('Hello world'); + await sink.flush(); + expect(await f.readAsString(), 'Hello world\n'); + }); + + test('ignoresDataWrittenAfterClose', () async { + sink.write('Before close'); + await closeSink(); + expect(() => sink.write('After close'), throwsStateError); + expect(await f.readAsString(), 'Before close'); + }); + + test('ignoresCloseAfterAlreadyClosed', () async { + sink.write('Hello world'); + Future<dynamic> f1 = closeSink(); + Future<dynamic> f2 = closeSink(); + await Future.wait<dynamic>(<Future<dynamic>>[f1, f2]); + }); + + test('returnsAccurateDoneFuture', () async { + bool done = false; + // ignore: unawaited_futures + sink.done.then((dynamic _) => done = true); + expect(done, isFalse); + sink.write('foo'); + expect(done, isFalse); + await sink.close(); + expect(done, isTrue); + }); + + group('addStream', () { + late StreamController<List<int>> controller; + late bool isControllerClosed; + + Future<dynamic> closeController() { + Future<dynamic> future = controller.close(); + isControllerClosed = true; + return future; + } + + setUp(() { + controller = StreamController<List<int>>(); + isControllerClosed = false; + sink.addStream(controller.stream); + }); + + tearDown(() async { + if (!isControllerClosed) { + await closeController(); + } + }); + + test('succeedsIfStreamProducesData', () async { + controller.add(<int>[1, 2, 3, 4, 5]); + await closeController(); + await sink.flush(); + expect(await f.readAsBytes(), <int>[1, 2, 3, 4, 5]); + }); + + test('blocksCallToAddWhileStreamIsActive', () { + expect(() => sink.add(<int>[1, 2, 3]), throwsStateError); + }); + + test('blocksCallToWriteWhileStreamIsActive', () { + expect(() => sink.write('foo'), throwsStateError); + }); + + test('blocksCallToWriteAllWhileStreamIsActive', () { + expect(() => sink.writeAll(<String>['a', 'b']), throwsStateError); + }); + + test('blocksCallToWriteCharCodeWhileStreamIsActive', () { + expect(() => sink.writeCharCode(35), throwsStateError); + }); + + test('blocksCallToWritelnWhileStreamIsActive', () { + expect(() => sink.writeln('foo'), throwsStateError); + }); + + test('blocksCallToFlushWhileStreamIsActive', () { + expect(() => sink.flush(), throwsStateError); + }); + }); + }); + }); + + group('readAsBytes', () { + test('throwsIfDoesntExist', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.file(ns('/foo')).readAsBytesSync(); + }); + }); + + test('throwsIfExistsAsDirectory', () { + fs.directory(ns('/foo')).createSync(); + expectFileSystemException(ErrorCodes.EISDIR, () { + fs.file(ns('/foo')).readAsBytesSync(); + }); + }); + + test('throwsIfExistsAsLinkToDirectory', () { + fs.directory(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + expectFileSystemException(ErrorCodes.EISDIR, () { + fs.file(ns('/bar')).readAsBytesSync(); + }); + }); + + test('succeedsIfExistsAsFile', () { + File f = fs.file(ns('/foo'))..createSync(); + f.writeAsBytesSync(<int>[1, 2, 3, 4]); + expect(f.readAsBytesSync(), <int>[1, 2, 3, 4]); + }); + + test('succeedsIfExistsAsLinkToFile', () { + fs.file(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + fs.file(ns('/foo')).writeAsBytesSync(<int>[1, 2, 3, 4]); + expect(fs.file(ns('/bar')).readAsBytesSync(), <int>[1, 2, 3, 4]); + }); + + test('returnsEmptyListForZeroByteFile', () { + File f = fs.file(ns('/foo'))..createSync(); + expect(f.readAsBytesSync(), isEmpty); + }); + + test('returns a copy, not a view, of the file content', () { + File f = fs.file(ns('/foo'))..createSync(); + f.writeAsBytesSync(<int>[1, 2, 3, 4]); + List<int> result = f.readAsBytesSync(); + expect(result, <int>[1, 2, 3, 4]); + result[0] = 10; + expect(f.readAsBytesSync(), <int>[1, 2, 3, 4]); + }); + }); + + group('readAsString', () { + test('throwsIfDoesntExist', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.file(ns('/foo')).readAsStringSync(); + }); + }); + + test('throwsIfExistsAsDirectory', () { + fs.directory(ns('/foo')).createSync(); + expectFileSystemException(ErrorCodes.EISDIR, () { + fs.file(ns('/foo')).readAsStringSync(); + }); + }); + + test('throwsIfExistsAsLinkToDirectory', () { + fs.directory(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + expectFileSystemException(ErrorCodes.EISDIR, () { + fs.file(ns('/bar')).readAsStringSync(); + }); + }); + + test('succeedsIfExistsAsFile', () { + File f = fs.file(ns('/foo'))..createSync(); + f.writeAsStringSync('Hello world'); + expect(f.readAsStringSync(), 'Hello world'); + }); + + test('succeedsIfExistsAsLinkToFile', () { + fs.file(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + fs.file(ns('/foo')).writeAsStringSync('Hello world'); + expect(fs.file(ns('/bar')).readAsStringSync(), 'Hello world'); + }); + + test('returnsEmptyStringForZeroByteFile', () { + File f = fs.file(ns('/foo'))..createSync(); + expect(f.readAsStringSync(), isEmpty); + }); + }); + + group('readAsLines', () { + const String testString = 'Hello world\nHow are you?\nI am fine'; + final List<String> expectedLines = <String>[ + 'Hello world', + 'How are you?', + 'I am fine', + ]; + + test('throwsIfDoesntExist', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.file(ns('/foo')).readAsLinesSync(); + }); + }); + + test('throwsIfExistsAsDirectory', () { + fs.directory(ns('/foo')).createSync(); + expectFileSystemException(ErrorCodes.EISDIR, () { + fs.file(ns('/foo')).readAsLinesSync(); + }); + }); + + test('throwsIfExistsAsLinkToDirectory', () { + fs.directory(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + expectFileSystemException(ErrorCodes.EISDIR, () { + fs.file(ns('/bar')).readAsLinesSync(); + }); + }); + + test('succeedsIfExistsAsFile', () { + File f = fs.file(ns('/foo'))..createSync(); + f.writeAsStringSync(testString); + expect(f.readAsLinesSync(), expectedLines); + }); + + test('succeedsIfExistsAsLinkToFile', () { + File f = fs.file(ns('/foo'))..createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + f.writeAsStringSync(testString); + expect(f.readAsLinesSync(), expectedLines); + }); + + test('returnsEmptyListForZeroByteFile', () { + File f = fs.file(ns('/foo'))..createSync(); + expect(f.readAsLinesSync(), isEmpty); + }); + + test('isTrailingNewlineAgnostic', () { + File f = fs.file(ns('/foo'))..createSync(); + f.writeAsStringSync('$testString\n'); + expect(f.readAsLinesSync(), expectedLines); + + f.writeAsStringSync('\n'); + expect(f.readAsLinesSync(), <String>['']); + + f.writeAsStringSync('\n\n'); + expect(f.readAsLinesSync(), <String>['', '']); + }); + }); + + group('writeAsBytes', () { + test('returnsCovariantType', () async { + expect(await fs.file(ns('/foo')).writeAsBytes(<int>[]), isFile); + }); + + test('createsFileIfDoesntExist', () { + File f = fs.file(ns('/foo')); + expect(f, isNot(exists)); + f.writeAsBytesSync(<int>[1, 2, 3, 4]); + expect(f, exists); + }); + + test('throwsIfExistsAsDirectory', () { + fs.directory(ns('/foo')).createSync(); + expectFileSystemException(ErrorCodes.EISDIR, () { + fs.file(ns('/foo')).writeAsBytesSync(<int>[1, 2, 3, 4]); + }); + }); + + test('throwsIfExistsAsLinkToDirectory', () { + fs.directory(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + expectFileSystemException(ErrorCodes.EISDIR, () { + fs.file(ns('/foo')).writeAsBytesSync(<int>[1, 2, 3, 4]); + }); + }); + + test('succeedsIfExistsAsLinkToFile', () { + File f = fs.file(ns('/foo'))..createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + fs.file(ns('/bar')).writeAsBytesSync(<int>[1, 2, 3, 4]); + expect(f.readAsBytesSync(), <int>[1, 2, 3, 4]); + }); + + test('throwsIfFileModeRead', () { + File f = fs.file(ns('/foo'))..createSync(); + expectFileSystemException(ErrorCodes.EBADF, () { + f.writeAsBytesSync(<int>[1], mode: FileMode.read); + }); + }); + + test('overwritesContentIfFileModeWrite', () { + File f = fs.file(ns('/foo'))..createSync(); + f.writeAsBytesSync(<int>[1, 2]); + expect(f.readAsBytesSync(), <int>[1, 2]); + f.writeAsBytesSync(<int>[3, 4]); + expect(f.readAsBytesSync(), <int>[3, 4]); + }); + + test('appendsContentIfFileModeAppend', () { + File f = fs.file(ns('/foo'))..createSync(); + f.writeAsBytesSync(<int>[1, 2], mode: FileMode.append); + expect(f.readAsBytesSync(), <int>[1, 2]); + f.writeAsBytesSync(<int>[3, 4], mode: FileMode.append); + expect(f.readAsBytesSync(), <int>[1, 2, 3, 4]); + }); + + test('acceptsEmptyBytesList', () { + File f = fs.file(ns('/foo'))..createSync(); + f.writeAsBytesSync(<int>[]); + expect(f.readAsBytesSync(), <int>[]); + }); + + test('updatesLastModifiedTime', () async { + File f = fs.file(ns('/foo'))..createSync(); + DateTime before = f.statSync().modified; + await Future<void>.delayed(const Duration(seconds: 2)); + f.writeAsBytesSync(<int>[1, 2, 3]); + DateTime after = f.statSync().modified; + expect(after, isAfter(before)); + }); + }); + + group('writeAsString', () { + test('returnsCovariantType', () async { + expect(await fs.file(ns('/foo')).writeAsString('foo'), isFile); + }); + + test('createsFileIfDoesntExist', () { + File f = fs.file(ns('/foo')); + expect(f, isNot(exists)); + f.writeAsStringSync('Hello world'); + expect(f, exists); + }); + + test('throwsIfExistsAsDirectory', () { + fs.directory(ns('/foo')).createSync(); + expectFileSystemException(ErrorCodes.EISDIR, () { + fs.file(ns('/foo')).writeAsStringSync('Hello world'); + }); + }); + + test('throwsIfExistsAsLinkToDirectory', () { + fs.directory(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + expectFileSystemException(ErrorCodes.EISDIR, () { + fs.file(ns('/foo')).writeAsStringSync('Hello world'); + }); + }); + + test('succeedsIfExistsAsLinkToFile', () { + File f = fs.file(ns('/foo'))..createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + fs.file(ns('/bar')).writeAsStringSync('Hello world'); + expect(f.readAsStringSync(), 'Hello world'); + }); + + test('throwsIfFileModeRead', () { + File f = fs.file(ns('/foo'))..createSync(); + expectFileSystemException(ErrorCodes.EBADF, () { + f.writeAsStringSync('Hello world', mode: FileMode.read); + }); + }); + + test('overwritesContentIfFileModeWrite', () { + File f = fs.file(ns('/foo'))..createSync(); + f.writeAsStringSync('Hello world'); + expect(f.readAsStringSync(), 'Hello world'); + f.writeAsStringSync('Goodbye cruel world'); + expect(f.readAsStringSync(), 'Goodbye cruel world'); + }); + + test('appendsContentIfFileModeAppend', () { + File f = fs.file(ns('/foo'))..createSync(); + f.writeAsStringSync('Hello', mode: FileMode.append); + expect(f.readAsStringSync(), 'Hello'); + f.writeAsStringSync('Goodbye', mode: FileMode.append); + expect(f.readAsStringSync(), 'HelloGoodbye'); + }); + + test('acceptsEmptyString', () { + File f = fs.file(ns('/foo'))..createSync(); + f.writeAsStringSync(''); + expect(f.readAsStringSync(), isEmpty); + }); + }); + + group('exists', () { + test('trueIfExists', () { + fs.file(ns('/foo')).createSync(); + expect(fs.file(ns('/foo')), exists); + }); + + test('falseIfDoesntExistAtTail', () { + expect(fs.file(ns('/foo')), isNot(exists)); + }); + + test('falseIfDoesntExistViaTraversal', () { + expect(fs.file(ns('/foo/bar')), isNot(exists)); + }); + + test('falseIfExistsAsDirectory', () { + fs.directory(ns('/foo')).createSync(); + expect(fs.file(ns('/foo')), isNot(exists)); + }); + + test('falseIfExistsAsLinkToDirectory', () { + fs.directory(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + expect(fs.file(ns('/bar')), isNot(exists)); + }); + + test('trueIfExistsAsLinkToFile', () { + fs.file(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + expect(fs.file(ns('/bar')), exists); + }); + + test('falseIfNotFoundSegmentExistsThenIsBackedOut', () { + fs.file(ns('/foo/bar')).createSync(recursive: true); + expect(fs.directory(ns('/baz/../foo/bar')), isNot(exists)); + }); + }); + + group('stat', () { + test('isNotFoundIfDoesntExistAtTail', () { + FileStat stat = fs.file(ns('/foo')).statSync(); + expect(stat.type, FileSystemEntityType.notFound); + }); + + test('isNotFoundIfDoesntExistViaTraversal', () { + FileStat stat = fs.file(ns('/foo/bar')).statSync(); + expect(stat.type, FileSystemEntityType.notFound); + }); + + test('isDirectoryIfExistsAsDirectory', () { + fs.directory(ns('/foo')).createSync(); + FileStat stat = fs.file(ns('/foo')).statSync(); + expect(stat.type, FileSystemEntityType.directory); + }); + + test('isFileIfExistsAsFile', () { + fs.file(ns('/foo')).createSync(); + FileStat stat = fs.file(ns('/foo')).statSync(); + expect(stat.type, FileSystemEntityType.file); + }); + + test('isFileIfExistsAsLinkToFile', () { + fs.file(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + FileStat stat = fs.file(ns('/bar')).statSync(); + expect(stat.type, FileSystemEntityType.file); + }); + }); + + group('delete', () { + test('returnsCovariantType', () async { + File f = fs.file(ns('/foo'))..createSync(); + expect(await f.delete(), isFile); + }); + + test('succeedsIfExistsAsFile', () { + fs.file(ns('/foo')).createSync(); + expect(fs.file(ns('/foo')), exists); + fs.file(ns('/foo')).deleteSync(); + expect(fs.file(ns('/foo')), isNot(exists)); + }); + + test('throwsIfDoesntExistAndRecursiveFalse', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.file(ns('/foo')).deleteSync(); + }); + }); + + test('throwsIfDoesntExistAndRecursiveTrue', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.file(ns('/foo')).deleteSync(recursive: true); + }); + }); + + test('succeedsIfExistsAsDirectoryAndRecursiveTrue', () { + fs.directory(ns('/foo')).createSync(); + fs.file(ns('/foo')).deleteSync(recursive: true); + expect(fs.typeSync(ns('/foo')), FileSystemEntityType.notFound); + }); + + test('throwsIfExistsAsDirectoryAndRecursiveFalse', () { + fs.directory(ns('/foo')).createSync(); + expectFileSystemException(ErrorCodes.EISDIR, () { + fs.file(ns('/foo')).deleteSync(); + }); + }); + + test('succeedsIfExistsAsLinkToFileAndRecursiveTrue', () { + fs.file(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + expect(fs.file(ns('/bar')), exists); + fs.file(ns('/bar')).deleteSync(recursive: true); + expect(fs.file(ns('/bar')), isNot(exists)); + }); + + test('succeedsIfExistsAsLinkToFileAndRecursiveFalse', () { + fs.file(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + expect(fs.file(ns('/bar')), exists); + fs.file(ns('/bar')).deleteSync(); + expect(fs.file(ns('/bar')), isNot(exists)); + }); + + test('succeedsIfExistsAsLinkToDirectoryAndRecursiveTrue', () { + fs.directory(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + expect(fs.typeSync(ns('/bar')), FileSystemEntityType.directory); + fs.file(ns('/bar')).deleteSync(recursive: true); + expect(fs.typeSync(ns('/foo')), FileSystemEntityType.directory); + expect(fs.typeSync(ns('/bar')), FileSystemEntityType.notFound); + }); + + test('throwsIfExistsAsLinkToDirectoryAndRecursiveFalse', () { + fs.directory(ns('/foo')).createSync(); + fs.link(ns('/bar')).createSync(ns('/foo')); + expectFileSystemException(ErrorCodes.EISDIR, () { + fs.file(ns('/bar')).deleteSync(); + }); + }); + }); + }); + + group('Link', () { + group('uri', () { + test('whenTargetIsDirectory', () { + fs.directory(ns('/foo')).createSync(); + Link l = fs.link(ns('/bar'))..createSync(ns('/foo')); + expect(l.uri, fs.path.toUri(ns('/bar'))); + expect(fs.link('bar').uri.toString(), 'bar'); + }); + + test('whenTargetIsFile', () { + fs.file(ns('/foo')).createSync(); + Link l = fs.link(ns('/bar'))..createSync(ns('/foo')); + expect(l.uri, fs.path.toUri(ns('/bar'))); + expect(fs.link('bar').uri.toString(), 'bar'); + }); + + test('whenLinkDoesntExist', () { + expect(fs.link(ns('/foo')).uri, fs.path.toUri(ns('/foo'))); + expect(fs.link('foo').uri.toString(), 'foo'); + }); + }); + + group('exists', () { + test('isFalseIfLinkDoesntExistAtTail', () { + expect(fs.link(ns('/foo')), isNot(exists)); + }); + + test('isFalseIfLinkDoesntExistViaTraversal', () { + expect(fs.link(ns('/foo/bar')), isNot(exists)); + }); + + test('isFalseIfPathReferencesFile', () { + fs.file(ns('/foo')).createSync(); + expect(fs.link(ns('/foo')), isNot(exists)); + }); + + test('isFalseIfPathReferencesDirectory', () { + fs.directory(ns('/foo')).createSync(); + expect(fs.link(ns('/foo')), isNot(exists)); + }); + + test('isTrueIfTargetIsNotFound', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + expect(l, exists); + }); + + test('isTrueIfTargetIsFile', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + fs.file(ns('/bar')).createSync(); + expect(l, exists); + }); + + test('isTrueIfTargetIsDirectory', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + fs.directory(ns('/bar')).createSync(); + expect(l, exists); + }); + + test('isTrueIfTargetIsLinkLoop', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + fs.link(ns('/bar')).createSync(ns('/foo')); + expect(l, exists); + }); + }); + + group('stat', () { + test('isNotFoundIfLinkDoesntExistAtTail', () { + expect(fs.link(ns('/foo')).statSync().type, + FileSystemEntityType.notFound); + }); + + test('isNotFoundIfLinkDoesntExistViaTraversal', () { + expect(fs.link(ns('/foo/bar')).statSync().type, + FileSystemEntityType.notFound); + }); + + test('isFileIfPathReferencesFile', () { + fs.file(ns('/foo')).createSync(); + expect( + fs.link(ns('/foo')).statSync().type, FileSystemEntityType.file); + }); + + test('isDirectoryIfPathReferencesDirectory', () { + fs.directory(ns('/foo')).createSync(); + expect(fs.link(ns('/foo')).statSync().type, + FileSystemEntityType.directory); + }); + + test('isNotFoundIfTargetNotFoundAtTail', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + expect(l.statSync().type, FileSystemEntityType.notFound); + }); + + test('isNotFoundIfTargetNotFoundViaTraversal', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar/baz')); + expect(l.statSync().type, FileSystemEntityType.notFound); + }); + + test('isNotFoundIfTargetIsLinkLoop', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + fs.link(ns('/bar')).createSync(ns('/foo')); + expect(l.statSync().type, FileSystemEntityType.notFound); + }); + + test('isFileIfTargetIsFile', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + fs.file(ns('/bar')).createSync(); + expect(l.statSync().type, FileSystemEntityType.file); + }); + + test('isDirectoryIfTargetIsDirectory', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + fs.directory(ns('/bar')).createSync(); + expect(l.statSync().type, FileSystemEntityType.directory); + }); + }); + + group('delete', () { + test('returnsCovariantType', () async { + Link link = fs.link(ns('/foo'))..createSync(ns('/bar')); + expect(await link.delete(), isLink); + }); + + test('throwsIfLinkDoesntExistAtTail', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.link(ns('/foo')).deleteSync(); + }); + }); + + test('throwsIfLinkDoesntExistViaTraversal', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.link(ns('/foo/bar')).deleteSync(); + }); + }); + + test('throwsIfPathReferencesFileAndRecursiveFalse', () { + fs.file(ns('/foo')).createSync(); + expectFileSystemException(ErrorCodes.EINVAL, () { + fs.link(ns('/foo')).deleteSync(); + }); + }); + + test('succeedsIfPathReferencesFileAndRecursiveTrue', () { + fs.file(ns('/foo')).createSync(); + fs.link(ns('/foo')).deleteSync(recursive: true); + expect(fs.typeSync(ns('/foo'), followLinks: false), + FileSystemEntityType.notFound); + }); + + test('throwsIfPathReferencesDirectoryAndRecursiveFalse', () { + fs.directory(ns('/foo')).createSync(); + // TODO(tvolkert): Change this to just be 'Is a directory' + // once Dart 1.22 is stable. + expectFileSystemException( + anyOf(ErrorCodes.EINVAL, ErrorCodes.EISDIR), + () { + fs.link(ns('/foo')).deleteSync(); + }, + ); + }); + + test('succeedsIfPathReferencesDirectoryAndRecursiveTrue', () { + fs.directory(ns('/foo')).createSync(); + fs.link(ns('/foo')).deleteSync(recursive: true); + expect(fs.typeSync(ns('/foo'), followLinks: false), + FileSystemEntityType.notFound); + }); + + test('unlinksIfTargetIsFileAndRecursiveFalse', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + fs.file(ns('/bar')).createSync(); + l.deleteSync(); + expect(fs.typeSync(ns('/foo'), followLinks: false), + FileSystemEntityType.notFound); + expect(fs.typeSync(ns('/bar'), followLinks: false), + FileSystemEntityType.file); + }); + + test('unlinksIfTargetIsFileAndRecursiveTrue', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + fs.file(ns('/bar')).createSync(); + l.deleteSync(recursive: true); + expect(fs.typeSync(ns('/foo'), followLinks: false), + FileSystemEntityType.notFound); + expect(fs.typeSync(ns('/bar'), followLinks: false), + FileSystemEntityType.file); + }); + + test('unlinksIfTargetIsDirectoryAndRecursiveFalse', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + fs.directory(ns('/bar')).createSync(); + l.deleteSync(); + expect(fs.typeSync(ns('/foo'), followLinks: false), + FileSystemEntityType.notFound); + expect(fs.typeSync(ns('/bar'), followLinks: false), + FileSystemEntityType.directory); + }); + + test('unlinksIfTargetIsDirectoryAndRecursiveTrue', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + fs.directory(ns('/bar')).createSync(); + l.deleteSync(recursive: true); + expect(fs.typeSync(ns('/foo'), followLinks: false), + FileSystemEntityType.notFound); + expect(fs.typeSync(ns('/bar'), followLinks: false), + FileSystemEntityType.directory); + }); + + test('unlinksIfTargetIsLinkLoop', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + fs.link(ns('/bar')).createSync(ns('/foo')); + l.deleteSync(); + expect(fs.typeSync(ns('/foo'), followLinks: false), + FileSystemEntityType.notFound); + expect(fs.typeSync(ns('/bar'), followLinks: false), + FileSystemEntityType.link); + }); + }); + + group('parent', () { + test('returnsCovariantType', () { + expect(fs.link(ns('/foo')).parent, isDirectory); + }); + + test('succeedsIfLinkDoesntExist', () { + expect(fs.link(ns('/foo')).parent.path, ns('/')); + }); + + test('ignoresLinkTarget', () { + Link l = fs.link(ns('/foo/bar')) + ..createSync(ns('/baz/qux'), recursive: true); + expect(l.parent.path, ns('/foo')); + }); + }); + + group('create', () { + test('returnsCovariantType', () async { + expect(await fs.link(ns('/foo')).create(ns('/bar')), isLink); + }); + + test('succeedsIfLinkDoesntExistAtTail', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + expect(fs.typeSync(ns('/foo'), followLinks: false), + FileSystemEntityType.link); + expect(l.targetSync(), ns('/bar')); + }); + + test('throwsIfLinkDoesntExistViaTraversalAndRecursiveFalse', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.link(ns('/foo/bar')).createSync('baz'); + }); + }); + + test('succeedsIfLinkDoesntExistViaTraversalAndRecursiveTrue', () { + Link l = fs.link(ns('/foo/bar'))..createSync('baz', recursive: true); + expect(fs.typeSync(ns('/foo'), followLinks: false), + FileSystemEntityType.directory); + expect(fs.typeSync(ns('/foo/bar'), followLinks: false), + FileSystemEntityType.link); + expect(l.targetSync(), 'baz'); + }); + + test('throwsIfAlreadyExistsAsFile', () { + fs.file(ns('/foo')).createSync(); + expectFileSystemException(ErrorCodes.EEXIST, () { + fs.link(ns('/foo')).createSync(ns('/bar')); + }); + }); + + test('throwsIfAlreadyExistsAsDirectory', () { + fs.directory(ns('/foo')).createSync(); + expectFileSystemException(ErrorCodes.EEXIST, () { + fs.link(ns('/foo')).createSync(ns('/bar')); + }); + }); + + test('throwsIfAlreadyExistsWithSameTarget', () { + fs.link(ns('/foo')).createSync(ns('/bar')); + expectFileSystemException(ErrorCodes.EEXIST, () { + fs.link(ns('/foo')).createSync(ns('/bar')); + }); + }); + + test('throwsIfAlreadyExistsWithDifferentTarget', () { + fs.link(ns('/foo')).createSync(ns('/bar')); + expectFileSystemException(ErrorCodes.EEXIST, () { + fs.link(ns('/foo')).createSync(ns('/baz')); + }); + }); + }); + + group('update', () { + test('returnsCovariantType', () async { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + expect(await l.update(ns('/baz')), isLink); + }); + + test('throwsIfLinkDoesntExistAtTail', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.link(ns('/foo')).updateSync(ns('/bar')); + }); + }); + + test('throwsIfLinkDoesntExistViaTraversal', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.link(ns('/foo/bar')).updateSync(ns('/baz')); + }); + }); + + test('throwsIfPathReferencesFile', () { + fs.file(ns('/foo')).createSync(); + expectFileSystemException(ErrorCodes.EINVAL, () { + fs.link(ns('/foo')).updateSync(ns('/bar')); + }); + }); + + test('throwsIfPathReferencesDirectory', () { + fs.directory(ns('/foo')).createSync(); + // TODO(tvolkert): Change this to just be 'Is a directory' + // once Dart 1.22 is stable. + expectFileSystemException( + anyOf(ErrorCodes.EINVAL, ErrorCodes.EISDIR), + () { + fs.link(ns('/foo')).updateSync(ns('/bar')); + }, + ); + }); + + test('succeedsIfNewTargetSameAsOldTarget', () { + fs.link(ns('/foo')).createSync(ns('/bar')); + fs.link(ns('/foo')).updateSync(ns('/bar')); + expect(fs.typeSync(ns('/foo'), followLinks: false), + FileSystemEntityType.link); + expect(fs.link(ns('/foo')).targetSync(), ns('/bar')); + }); + + test('succeedsIfNewTargetDifferentFromOldTarget', () { + fs.link(ns('/foo')).createSync(ns('/bar')); + fs.link(ns('/foo')).updateSync(ns('/baz')); + expect(fs.typeSync(ns('/foo'), followLinks: false), + FileSystemEntityType.link); + expect(fs.link(ns('/foo')).targetSync(), ns('/baz')); + }); + }); + + group('absolute', () { + test('returnsCovariantType', () { + expect(fs.link('foo').absolute, isLink); + }); + + test('returnsSamePathIfAlreadyAbsolute', () { + expect(fs.link(ns('/foo')).absolute.path, ns('/foo')); + }); + + test('succeedsForRelativePaths', () { + expect(fs.link('foo').absolute.path, ns('/foo')); + }); + }); + + group('target', () { + test('throwsIfLinkDoesntExistAtTail', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.link(ns('/foo')).targetSync(); + }); + }); + + test('throwsIfLinkDoesntExistViaTraversal', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.link(ns('/foo/bar')).targetSync(); + }); + }); + + test('throwsIfPathReferencesFile', () { + fs.file(ns('/foo')).createSync(); + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.link(ns('/foo')).targetSync(); + }); + }); + + test('throwsIfPathReferencesDirectory', () { + fs.directory(ns('/foo')).createSync(); + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.link(ns('/foo')).targetSync(); + }); + }); + + test('succeedsIfTargetIsNotFound', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + expect(l.targetSync(), ns('/bar')); + }); + + test('succeedsIfTargetIsFile', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + fs.file(ns('/bar')).createSync(); + expect(l.targetSync(), ns('/bar')); + }); + + test('succeedsIfTargetIsDirectory', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + fs.directory(ns('/bar')).createSync(); + expect(l.targetSync(), ns('/bar')); + }); + + test('succeedsIfTargetIsLinkLoop', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + fs.link(ns('/bar')).createSync(ns('/foo')); + expect(l.targetSync(), ns('/bar')); + }); + }); + + group('rename', () { + test('returnsCovariantType', () async { + Link l() => fs.link(ns('/foo'))..createSync(ns('/bar')); + expect(l().renameSync(ns('/bar')), isLink); + expect(await l().rename(ns('/bar')), isLink); + }); + + test('throwsIfSourceDoesntExistAtTail', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.link(ns('/foo')).renameSync(ns('/bar')); + }); + }); + + test('throwsIfSourceDoesntExistViaTraversal', () { + expectFileSystemException(ErrorCodes.ENOENT, () { + fs.link(ns('/foo/bar')).renameSync(ns('/bar')); + }); + }); + + test('throwsIfSourceIsFile', () { + fs.file(ns('/foo')).createSync(); + expectFileSystemException(ErrorCodes.EINVAL, () { + fs.link(ns('/foo')).renameSync(ns('/bar')); + }); + }); + + test('throwsIfSourceIsDirectory', () { + fs.directory(ns('/foo')).createSync(); + expectFileSystemException(ErrorCodes.EISDIR, () { + fs.link(ns('/foo')).renameSync(ns('/bar')); + }); + }); + + test('succeedsIfSourceIsLinkToFile', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + fs.file(ns('/bar')).createSync(); + Link renamed = l.renameSync(ns('/baz')); + expect(renamed.path, ns('/baz')); + expect(fs.typeSync(ns('/foo'), followLinks: false), + FileSystemEntityType.notFound); + expect(fs.typeSync(ns('/bar'), followLinks: false), + FileSystemEntityType.file); + expect(fs.typeSync(ns('/baz'), followLinks: false), + FileSystemEntityType.link); + expect(fs.link(ns('/baz')).targetSync(), ns('/bar')); + }); + + test('succeedsIfSourceIsLinkToNotFound', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + Link renamed = l.renameSync(ns('/baz')); + expect(renamed.path, ns('/baz')); + expect(fs.typeSync(ns('/foo'), followLinks: false), + FileSystemEntityType.notFound); + expect(fs.typeSync(ns('/baz'), followLinks: false), + FileSystemEntityType.link); + expect(fs.link(ns('/baz')).targetSync(), ns('/bar')); + }); + + test('succeedsIfSourceIsLinkToDirectory', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + fs.directory(ns('/bar')).createSync(); + Link renamed = l.renameSync(ns('/baz')); + expect(renamed.path, ns('/baz')); + expect(fs.typeSync(ns('/foo'), followLinks: false), + FileSystemEntityType.notFound); + expect(fs.typeSync(ns('/bar'), followLinks: false), + FileSystemEntityType.directory); + expect(fs.typeSync(ns('/baz'), followLinks: false), + FileSystemEntityType.link); + expect(fs.link(ns('/baz')).targetSync(), ns('/bar')); + }); + + test('succeedsIfSourceIsLinkLoop', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + fs.link(ns('/bar')).createSync(ns('/foo')); + Link renamed = l.renameSync(ns('/baz')); + expect(renamed.path, ns('/baz')); + expect(fs.typeSync(ns('/foo'), followLinks: false), + FileSystemEntityType.notFound); + expect(fs.typeSync(ns('/bar'), followLinks: false), + FileSystemEntityType.link); + expect(fs.typeSync(ns('/baz'), followLinks: false), + FileSystemEntityType.link); + expect(fs.link(ns('/baz')).targetSync(), ns('/bar')); + }); + + test('succeedsIfDestinationDoesntExistAtTail', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + Link renamed = l.renameSync(ns('/baz')); + expect(renamed.path, ns('/baz')); + expect(fs.link(ns('/foo')), isNot(exists)); + expect(fs.link(ns('/baz')), exists); + }); + + test('throwsIfDestinationDoesntExistViaTraversal', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + expectFileSystemException(ErrorCodes.ENOENT, () { + l.renameSync(ns('/baz/qux')); + }); + }); + + test('throwsIfDestinationExistsAsFile', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + fs.file(ns('/baz')).createSync(); + expectFileSystemException(ErrorCodes.EINVAL, () { + l.renameSync(ns('/baz')); + }); + }); + + test('throwsIfDestinationExistsAsDirectory', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + fs.directory(ns('/baz')).createSync(); + expectFileSystemException(ErrorCodes.EINVAL, () { + l.renameSync(ns('/baz')); + }); + }); + + test('succeedsIfDestinationExistsAsLinkToFile', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + fs.file(ns('/baz')).createSync(); + fs.link(ns('/qux')).createSync(ns('/baz')); + l.renameSync(ns('/qux')); + expect(fs.typeSync(ns('/foo')), FileSystemEntityType.notFound); + expect(fs.typeSync(ns('/baz'), followLinks: false), + FileSystemEntityType.file); + expect(fs.typeSync(ns('/qux'), followLinks: false), + FileSystemEntityType.link); + expect(fs.link(ns('/qux')).targetSync(), ns('/bar')); + }); + + test('throwsIfDestinationExistsAsLinkToDirectory', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + fs.directory(ns('/baz')).createSync(); + fs.link(ns('/qux')).createSync(ns('/baz')); + l.renameSync(ns('/qux')); + expect(fs.typeSync(ns('/foo')), FileSystemEntityType.notFound); + expect(fs.typeSync(ns('/baz'), followLinks: false), + FileSystemEntityType.directory); + expect(fs.typeSync(ns('/qux'), followLinks: false), + FileSystemEntityType.link); + expect(fs.link(ns('/qux')).targetSync(), ns('/bar')); + }); + + test('succeedsIfDestinationExistsAsLinkToNotFound', () { + Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + fs.link(ns('/baz')).createSync(ns('/qux')); + l.renameSync(ns('/baz')); + expect(fs.typeSync(ns('/foo')), FileSystemEntityType.notFound); + expect(fs.typeSync(ns('/baz'), followLinks: false), + FileSystemEntityType.link); + expect(fs.link(ns('/baz')).targetSync(), ns('/bar')); + }); + }); + }); + }); +}
diff --git a/pkgs/file/test/local_test.dart b/pkgs/file/test/local_test.dart new file mode 100644 index 0000000..e1618d2 --- /dev/null +++ b/pkgs/file/test/local_test.dart
@@ -0,0 +1,132 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +@TestOn('vm') +import 'dart:io' as io; + +import 'package:file/local.dart'; +import 'package:file_testing/src/testing/internal.dart'; +import 'package:test/test.dart'; + +import 'common_tests.dart'; + +void main() { + group('LocalFileSystem', () { + late LocalFileSystem fs; + late io.Directory tmp; + late String cwd; + + setUp(() { + fs = const LocalFileSystem(); + tmp = io.Directory.systemTemp.createTempSync('file_test_'); + tmp = io.Directory(tmp.resolveSymbolicLinksSync()); + cwd = io.Directory.current.path; + io.Directory.current = tmp; + }); + + tearDown(() { + io.Directory.current = cwd; + tmp.deleteSync(recursive: true); + }); + + setUpAll(() { + if (io.Platform.isWindows) { + // TODO(tvolkert): Remove once all more serious test failures are fixed + // https://github.com/google/file.dart/issues/56 + ignoreOsErrorCodes = true; + } + }); + + tearDownAll(() { + ignoreOsErrorCodes = false; + }); + + Map<String, List<String>> skipOnPlatform = <String, List<String>>{ + 'windows': <String>[ + 'FileSystem > currentDirectory > throwsIfHasNonExistentPathInComplexChain', + 'FileSystem > currentDirectory > resolvesLinksIfEncountered', + 'FileSystem > currentDirectory > succeedsIfSetToDirectoryLinkAtTail', + 'FileSystem > stat > isFileForLinkToFile', + 'FileSystem > type > isFileForLinkToFileAndFollowLinksTrue', + 'FileSystem > type > isNotFoundForLinkWithCircularReferenceAndFollowLinksTrue', + 'Directory > exists > falseIfNotFoundSegmentExistsThenIsBackedOut', + 'Directory > rename > throwsIfDestinationIsNonEmptyDirectory', + 'Directory > rename > throwsIfDestinationIsLinkToEmptyDirectory', + 'Directory > resolveSymbolicLinks > throwsIfPathNotFoundInMiddleThenBackedOut', + 'Directory > resolveSymbolicLinks > handlesRelativeLinks', + 'Directory > resolveSymbolicLinks > handlesLinksWhoseTargetsHaveNestedLinks', + 'Directory > resolveSymbolicLinks > handlesComplexPathWithMultipleLinks', + 'Directory > createTemp > succeedsWithNestedPathPrefixThatExists', + 'Directory > list > followsLinksIfFollowLinksTrue', + 'Directory > list > returnsCovariantType', + 'Directory > list > returnsLinkObjectsForRecursiveLinkIfFollowLinksTrue', + 'Directory > delete > succeedsIfPathReferencesLinkToFileAndRecursiveTrue', + 'File > rename > succeedsIfSourceExistsAsLinkToFile', + 'File > copy > succeedsIfSourceExistsAsLinkToFile', + 'File > copy > succeedsIfSourceIsLinkToFileInDifferentDirectory', + 'File > delete > succeedsIfExistsAsLinkToFileAndRecursiveTrue', + 'File > openWrite > ioSink > throwsIfEncodingIsNullAndWriteObject', + 'File > openWrite > ioSink > allowsChangingEncoding', + 'File > openWrite > ioSink > succeedsIfAddRawData', + 'File > openWrite > ioSink > succeedsIfWrite', + 'File > openWrite > ioSink > succeedsIfWriteAll', + 'File > openWrite > ioSink > succeedsIfWriteCharCode', + 'File > openWrite > ioSink > succeedsIfWriteln', + 'File > openWrite > ioSink > addStream > succeedsIfStreamProducesData', + 'File > openWrite > ioSink > addStream > blocksCallToAddWhileStreamIsActive', + 'File > openWrite > ioSink > addStream > blocksCallToWriteWhileStreamIsActive', + 'File > openWrite > ioSink > addStream > blocksCallToWriteAllWhileStreamIsActive', + 'File > openWrite > ioSink > addStream > blocksCallToWriteCharCodeWhileStreamIsActive', + 'File > openWrite > ioSink > addStream > blocksCallToWritelnWhileStreamIsActive', + 'File > openWrite > ioSink > addStream > blocksCallToFlushWhileStreamIsActive', + 'File > stat > isFileIfExistsAsLinkToFile', + 'Link > stat > isFileIfTargetIsFile', + 'Link > stat > isDirectoryIfTargetIsDirectory', + 'Link > delete > unlinksIfTargetIsDirectoryAndRecursiveTrue', + 'Link > delete > unlinksIfTargetIsFileAndRecursiveTrue', + + // Fixed in SDK 1.23 (https://github.com/dart-lang/sdk/issues/28852) + 'File > open > WRITE > RandomAccessFile > truncate > throwsIfSetToNegativeNumber', + 'File > open > APPEND > RandomAccessFile > truncate > throwsIfSetToNegativeNumber', + 'File > open > WRITE_ONLY > RandomAccessFile > truncate > throwsIfSetToNegativeNumber', + 'File > open > WRITE_ONLY_APPEND > RandomAccessFile > truncate > throwsIfSetToNegativeNumber', + + // Windows does not allow removing or renaming open files. + '.* > openReadHandleDoesNotChange', + '.* > openWriteHandleDoesNotChange', + ], + }; + + runCommonTests( + () => fs, + root: () => tmp.path, + skip: <String>[ + // https://github.com/dart-lang/sdk/issues/28171 + 'File > rename > throwsIfDestinationExistsAsLinkToDirectory', + + // https://github.com/dart-lang/sdk/issues/28275 + 'Link > rename > throwsIfDestinationExistsAsDirectory', + + // https://github.com/dart-lang/sdk/issues/28277 + 'Link > rename > throwsIfDestinationExistsAsFile', + + ...skipOnPlatform[io.Platform.operatingSystem] ?? <String>[], + ], + ); + + group('toString', () { + test('File', () { + expect(fs.file('/foo').toString(), "LocalFile: '/foo'"); + }); + + test('Directory', () { + expect(fs.directory('/foo').toString(), "LocalDirectory: '/foo'"); + }); + + test('Link', () { + expect(fs.link('/foo').toString(), "LocalLink: '/foo'"); + }); + }); + }); +}
diff --git a/pkgs/file/test/memory_operations_test.dart b/pkgs/file/test/memory_operations_test.dart new file mode 100644 index 0000000..5e27843 --- /dev/null +++ b/pkgs/file/test/memory_operations_test.dart
@@ -0,0 +1,231 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:file/file.dart'; +import 'package:file/memory.dart'; +import 'package:test/test.dart'; + +void main() { + test('Read operations invoke opHandle', () async { + List<String> contexts = <String>[]; + List<FileSystemOp> operations = <FileSystemOp>[]; + MemoryFileSystem fs = MemoryFileSystem.test( + opHandle: (String context, FileSystemOp operation) { + if (operation == FileSystemOp.read) { + contexts.add(context); + operations.add(operation); + } + }); + final File file = fs.file('test')..createSync(); + + await file.readAsBytes(); + file.readAsBytesSync(); + await file.readAsString(); + file.readAsStringSync(); + + expect(contexts, <String>['test', 'test', 'test', 'test']); + expect(operations, <FileSystemOp>[ + FileSystemOp.read, + FileSystemOp.read, + FileSystemOp.read, + FileSystemOp.read + ]); + }); + + test('Write operations invoke opHandle', () async { + List<String> contexts = <String>[]; + List<FileSystemOp> operations = <FileSystemOp>[]; + MemoryFileSystem fs = MemoryFileSystem.test( + opHandle: (String context, FileSystemOp operation) { + if (operation == FileSystemOp.write) { + contexts.add(context); + operations.add(operation); + } + }); + final File file = fs.file('test')..createSync(); + + await file.writeAsBytes(<int>[]); + file.writeAsBytesSync(<int>[]); + await file.writeAsString(''); + file.writeAsStringSync(''); + + expect(contexts, <String>['test', 'test', 'test', 'test']); + expect(operations, <FileSystemOp>[ + FileSystemOp.write, + FileSystemOp.write, + FileSystemOp.write, + FileSystemOp.write + ]); + }); + + test('Delete operations invoke opHandle', () async { + List<String> contexts = <String>[]; + List<FileSystemOp> operations = <FileSystemOp>[]; + MemoryFileSystem fs = MemoryFileSystem.test( + opHandle: (String context, FileSystemOp operation) { + if (operation == FileSystemOp.delete) { + contexts.add(context); + operations.add(operation); + } + }); + final File file = fs.file('test')..createSync(); + final Directory directory = fs.directory('testDir')..createSync(); + final Link link = fs.link('testLink')..createSync('foo'); + + await file.delete(); + file.createSync(); + file.deleteSync(); + + await directory.delete(); + directory.createSync(); + directory.deleteSync(); + + await link.delete(); + link.createSync('foo'); + link.deleteSync(); + + expect(contexts, + <String>['test', 'test', 'testDir', 'testDir', 'testLink', 'testLink']); + expect(operations, <FileSystemOp>[ + FileSystemOp.delete, + FileSystemOp.delete, + FileSystemOp.delete, + FileSystemOp.delete, + FileSystemOp.delete, + FileSystemOp.delete, + ]); + }); + + test('Create operations invoke opHandle', () async { + List<String> contexts = <String>[]; + List<FileSystemOp> operations = <FileSystemOp>[]; + MemoryFileSystem fs = MemoryFileSystem.test( + opHandle: (String context, FileSystemOp operation) { + if (operation == FileSystemOp.create) { + contexts.add(context); + operations.add(operation); + } + }); + fs.file('testA').createSync(); + await fs.file('testB').create(); + fs.directory('testDirA').createSync(); + await fs.directory('testDirB').create(); + fs.link('testLinkA').createSync('foo'); + await fs.link('testLinkB').create('foo'); + fs.currentDirectory.createTempSync('tmp.bar'); + await fs.currentDirectory.createTemp('tmp.bar'); + + expect(contexts, <dynamic>[ + 'testA', + 'testB', + 'testDirA', + 'testDirB', + 'testLinkA', + 'testLinkB', + startsWith('/tmp.bar'), + startsWith('/tmp.bar'), + ]); + expect(operations, <FileSystemOp>[ + FileSystemOp.create, + FileSystemOp.create, + FileSystemOp.create, + FileSystemOp.create, + FileSystemOp.create, + FileSystemOp.create, + FileSystemOp.create, + FileSystemOp.create, + ]); + }); + + test('Open operations invoke opHandle', () async { + List<String> contexts = <String>[]; + List<FileSystemOp> operations = <FileSystemOp>[]; + MemoryFileSystem fs = MemoryFileSystem.test( + opHandle: (String context, FileSystemOp operation) { + if (operation == FileSystemOp.open) { + contexts.add(context); + operations.add(operation); + } + }); + final File file = fs.file('test')..createSync(); + + await file.open(); + file.openSync(); + file.openRead(); + file.openWrite(); + + expect(contexts, <String>['test', 'test', 'test', 'test']); + expect(operations, <FileSystemOp>[ + FileSystemOp.open, + FileSystemOp.open, + FileSystemOp.open, + FileSystemOp.open, + ]); + }); + + test('Copy operations invoke opHandle', () async { + List<String> contexts = <String>[]; + List<FileSystemOp> operations = <FileSystemOp>[]; + MemoryFileSystem fs = MemoryFileSystem.test( + opHandle: (String context, FileSystemOp operation) { + if (operation == FileSystemOp.copy) { + contexts.add(context); + operations.add(operation); + } + }); + final File file = fs.file('test')..createSync(); + + await file.copy('A'); + file.copySync('B'); + + expect(contexts, <String>['test', 'test']); + expect(operations, <FileSystemOp>[ + FileSystemOp.copy, + FileSystemOp.copy, + ]); + }); + + test('Exists operations invoke opHandle', () async { + List<String> contexts = <String>[]; + List<FileSystemOp> operations = <FileSystemOp>[]; + MemoryFileSystem fs = MemoryFileSystem.test( + opHandle: (String context, FileSystemOp operation) { + if (operation == FileSystemOp.exists) { + contexts.add(context); + operations.add(operation); + } + }); + fs.file('testA').existsSync(); + await fs.file('testB').exists(); + fs.directory('testDirA').existsSync(); + await fs.directory('testDirB').exists(); + fs.link('testLinkA').existsSync(); + await fs.link('testLinkB').exists(); + + expect(contexts, <dynamic>[ + 'testA', + 'testB', + 'testDirA', + 'testDirB', + 'testLinkA', + 'testLinkB', + ]); + expect(operations, <FileSystemOp>[ + FileSystemOp.exists, + FileSystemOp.exists, + FileSystemOp.exists, + FileSystemOp.exists, + FileSystemOp.exists, + FileSystemOp.exists, + ]); + }); + + test('FileSystemOp toString', () { + expect(FileSystemOp.create.toString(), 'FileSystemOp.create'); + expect(FileSystemOp.delete.toString(), 'FileSystemOp.delete'); + expect(FileSystemOp.read.toString(), 'FileSystemOp.read'); + expect(FileSystemOp.write.toString(), 'FileSystemOp.write'); + expect(FileSystemOp.exists.toString(), 'FileSystemOp.exists'); + }); +}
diff --git a/pkgs/file/test/memory_test.dart b/pkgs/file/test/memory_test.dart new file mode 100644 index 0000000..f3b324e --- /dev/null +++ b/pkgs/file/test/memory_test.dart
@@ -0,0 +1,173 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:io' as io; + +import 'package:file/file.dart'; +import 'package:file/memory.dart'; +import 'package:file/src/backends/memory/memory_random_access_file.dart'; +import 'package:test/test.dart'; + +import 'common_tests.dart'; + +void main() { + group('MemoryFileSystem unix style', () { + late MemoryFileSystem fs; + + setUp(() { + fs = MemoryFileSystem(); + }); + + runCommonTests(() => fs); + + group('toString', () { + test('File', () { + expect(fs.file('/foo').toString(), "MemoryFile: '/foo'"); + }); + + test('Directory', () { + expect(fs.directory('/foo').toString(), "MemoryDirectory: '/foo'"); + }); + + test('Link', () { + expect(fs.link('/foo').toString(), "MemoryLink: '/foo'"); + }); + }); + }); + + group('MemoryFileSystem windows style', () { + late MemoryFileSystem fs; + + setUp(() { + fs = MemoryFileSystem(style: FileSystemStyle.windows); + }); + + runCommonTests( + () => fs, + root: () => fs.style.root, + ); + + group('toString', () { + test('File', () { + expect(fs.file('C:\\foo').toString(), "MemoryFile: 'C:\\foo'"); + }); + + test('Directory', () { + expect( + fs.directory('C:\\foo').toString(), "MemoryDirectory: 'C:\\foo'"); + }); + + test('Link', () { + expect(fs.link('C:\\foo').toString(), "MemoryLink: 'C:\\foo'"); + }); + }); + }); + + test('MemoryFileSystem.test', () { + final MemoryFileSystem fs = + MemoryFileSystem.test(); // creates root directory + fs.file('/test1.txt').createSync(); // creates file + fs.file('/test2.txt').createSync(); // creates file + expect(fs.directory('/').statSync().modified, DateTime(2000, 1, 1, 0, 1)); + expect( + fs.file('/test1.txt').statSync().modified, DateTime(2000, 1, 1, 0, 2)); + expect( + fs.file('/test2.txt').statSync().modified, DateTime(2000, 1, 1, 0, 3)); + fs.file('/test1.txt').createSync(); + fs.file('/test2.txt').createSync(); + expect(fs.file('/test1.txt').statSync().modified, + DateTime(2000, 1, 1, 0, 2)); // file already existed + expect(fs.file('/test2.txt').statSync().modified, + DateTime(2000, 1, 1, 0, 3)); // file already existed + fs.file('/test1.txt').writeAsStringSync('test'); // touches file + expect( + fs.file('/test1.txt').statSync().modified, DateTime(2000, 1, 1, 0, 4)); + expect(fs.file('/test2.txt').statSync().modified, + DateTime(2000, 1, 1, 0, 3)); // didn't touch it + fs.file('/test1.txt').copySync( + '/test2.txt'); // creates file, then mutates file (so time changes twice) + expect(fs.file('/test1.txt').statSync().modified, + DateTime(2000, 1, 1, 0, 4)); // didn't touch it + expect( + fs.file('/test2.txt').statSync().modified, DateTime(2000, 1, 1, 0, 6)); + }); + + test('MemoryFile.openSync returns a MemoryRandomAccessFile', () async { + final MemoryFileSystem fs = MemoryFileSystem.test(); + final io.File file = fs.file('/test1')..createSync(); + + io.RandomAccessFile raf = file.openSync(); + try { + expect(raf, isA<MemoryRandomAccessFile>()); + } finally { + raf.closeSync(); + } + + raf = await file.open(); + try { + expect(raf, isA<MemoryRandomAccessFile>()); + } finally { + raf.closeSync(); + } + }); + + test('MemoryFileSystem.systemTempDirectory test', () { + final MemoryFileSystem fs = MemoryFileSystem.test(); + + final io.Directory fooA = fs.systemTempDirectory.createTempSync('foo'); + final io.Directory fooB = fs.systemTempDirectory.createTempSync('foo'); + + expect(fooA.path, '/.tmp_rand0/foorand0'); + expect(fooB.path, '/.tmp_rand0/foorand1'); + + final MemoryFileSystem secondFs = MemoryFileSystem.test(); + + final io.Directory fooAA = + secondFs.systemTempDirectory.createTempSync('foo'); + final io.Directory fooBB = + secondFs.systemTempDirectory.createTempSync('foo'); + + // Names are recycled with a new instance + expect(fooAA.path, '/.tmp_rand0/foorand0'); + expect(fooBB.path, '/.tmp_rand0/foorand1'); + }); + + test('Failed UTF8 decoding in MemoryFileSystem throws a FileSystemException', + () { + final MemoryFileSystem fileSystem = MemoryFileSystem.test(); + final File file = fileSystem.file('foo') + ..writeAsBytesSync(<int>[0xFFFE]); // Invalid UTF8 + + expect(file.readAsStringSync, throwsA(isA<FileSystemException>())); + }); + + test('Creating a temporary directory actually creates the directory', () { + final MemoryFileSystem fileSystem = MemoryFileSystem.test(); + final Directory tempDir = fileSystem.currentDirectory.createTempSync('foo'); + + expect(tempDir.existsSync(), true); + }); + + test( + 'addStream forwards error to returned future and file can still be ' + 'closed', () async { + final file = MemoryFileSystem.test().file('foo').openWrite(); + await expectLater(file.addStream(Stream.error('bar')), throwsA('bar')); + await file.close(); + }); + + test( + 'addStream cancels on error and does not misbehave if the stream ' + 'produces multiple errors and then closes', () async { + final file = MemoryFileSystem.test().file('foo').openWrite(); + final controller = StreamController<List<int>>() + ..addError('bar') + ..addError('baz'); + final close = controller.close(); + await expectLater(file.addStream(controller.stream), throwsA('bar')); + await file.close(); + await close; + }); +}
diff --git a/pkgs/file/test/utils.dart b/pkgs/file/test/utils.dart new file mode 100644 index 0000000..231312f --- /dev/null +++ b/pkgs/file/test/utils.dart
@@ -0,0 +1,117 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:meta/meta.dart'; +import 'package:test/test.dart'; + +const Duration _oneSecond = Duration(seconds: 1); + +/// Returns a [DateTime] with an exact second-precision by removing the +/// milliseconds and microseconds from the specified [time]. +/// +/// If [time] is not specified, it will default to the current time. +DateTime floor([DateTime? time]) { + time ??= DateTime.now(); + return time.subtract(Duration( + milliseconds: time.millisecond, + microseconds: time.microsecond, + )); +} + +/// Returns a [DateTime] with an exact second precision, rounding up to the +/// nearest second if necessary. +/// +/// If [time] is not specified, it will default to the current time. +DateTime ceil([DateTime? time]) { + time ??= DateTime.now(); + int microseconds = (1000 * time.millisecond) + time.microsecond; + return (microseconds == 0) + ? time + // Add just enough milliseconds and microseconds to reach the next second. + : time.add(Duration(microseconds: 1000000 - microseconds)); +} + +/// Returns 1 second before the [floor] of the specified [DateTime]. +// TODO(jamesderlin): Remove this and use [floor], https://github.com/dart-lang/sdk/issues/42444 +DateTime downstairs([DateTime? time]) => floor(time).subtract(_oneSecond); + +/// Successfully matches against a [DateTime] that is the same moment or before +/// the specified [time]. +Matcher isSameOrBefore(DateTime time) => _IsSameOrBefore(time); + +/// Successfully matches against a [DateTime] that is the same moment or after +/// the specified [time]. +Matcher isSameOrAfter(DateTime time) => _IsSameOrAfter(time); + +/// Successfully matches against a [DateTime] that is after the specified +/// [time]. +Matcher isAfter(DateTime time) => _IsAfter(time); + +abstract class _CompareDateTime extends Matcher { + const _CompareDateTime(this._time, this._matcher); + + final DateTime _time; + final Matcher _matcher; + + @override + bool matches(dynamic item, Map<dynamic, dynamic> matchState) { + return item is DateTime && + _matcher.matches(item.compareTo(_time), <dynamic, dynamic>{}); + } + + @protected + String get descriptionOperator; + + @override + Description describe(Description description) => + description.add('a DateTime $descriptionOperator $_time'); + + @protected + String get mismatchAdjective; + + @override + Description describeMismatch( + dynamic item, + Description description, + Map<dynamic, dynamic> matchState, + bool verbose, + ) { + if (item is DateTime) { + Duration diff = item.difference(_time).abs(); + return description.add('is $mismatchAdjective $_time by $diff'); + } else { + return description.add('is not a DateTime'); + } + } +} + +class _IsSameOrBefore extends _CompareDateTime { + const _IsSameOrBefore(DateTime time) : super(time, isNonPositive); + + @override + String get descriptionOperator => '<='; + + @override + String get mismatchAdjective => 'after'; +} + +class _IsSameOrAfter extends _CompareDateTime { + const _IsSameOrAfter(DateTime time) : super(time, isNonNegative); + + @override + String get descriptionOperator => '>='; + + @override + String get mismatchAdjective => 'before'; +} + +class _IsAfter extends _CompareDateTime { + const _IsAfter(DateTime time) : super(time, isPositive); + + @override + String get descriptionOperator => '>'; + + @override + String get mismatchAdjective => 'before'; +}
diff --git a/pkgs/file/test/utils_test.dart b/pkgs/file/test/utils_test.dart new file mode 100644 index 0000000..75293bf --- /dev/null +++ b/pkgs/file/test/utils_test.dart
@@ -0,0 +1,43 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:test/test.dart'; + +import 'utils.dart'; + +void main() { + test('floorAndCeilProduceExactSecondDateTime', () { + DateTime time = DateTime.fromMicrosecondsSinceEpoch(1001); + DateTime lower = floor(time); + DateTime upper = ceil(time); + expect(lower.millisecond, 0); + expect(upper.millisecond, 0); + expect(lower.microsecond, 0); + expect(upper.microsecond, 0); + }); + + test('floorAndCeilWorkWithNow', () { + DateTime time = DateTime.now(); + int lower = time.difference(floor(time)).inMicroseconds; + int upper = ceil(time).difference(time).inMicroseconds; + expect(lower, lessThan(1000000)); + expect(upper, lessThanOrEqualTo(1000000)); + }); + + test('floorAndCeilWorkWithExactSecondDateTime', () { + DateTime time = DateTime.parse('1999-12-31 23:59:59'); + DateTime lower = floor(time); + DateTime upper = ceil(time); + expect(lower, time); + expect(upper, time); + }); + + test('floorAndCeilWorkWithInexactSecondDateTime', () { + DateTime time = DateTime.parse('1999-12-31 23:59:59.500'); + DateTime lower = floor(time); + DateTime upper = ceil(time); + Duration difference = upper.difference(lower); + expect(difference.inMicroseconds, 1000000); + }); +}
diff --git a/pkgs/file_testing/.gitignore b/pkgs/file_testing/.gitignore new file mode 100644 index 0000000..ddfdca1 --- /dev/null +++ b/pkgs/file_testing/.gitignore
@@ -0,0 +1,5 @@ +.dart_tool/ +.packages +.pub/ +build/ +pubspec.lock
diff --git a/pkgs/file_testing/CHANGELOG.md b/pkgs/file_testing/CHANGELOG.md new file mode 100644 index 0000000..0af779d --- /dev/null +++ b/pkgs/file_testing/CHANGELOG.md
@@ -0,0 +1,44 @@ +## 3.0.2 + +* Require Dart 3.1. + +## 3.0.1 + +* Update the pubspec repository field to reflect the new package repository. +* Require Dart 3.0. + +## 3.0.0 + +* Migrate to null safety. + +## 2.2.0 + +* Change dependency on `package:test_api` back to `package:test`. + +## 2.1.0 + +* Changed dependency on `package:test` to `package:test_api` +* Bumped Dart SDK constraint to match `package:test_api`'s requirements +* Updated style to match latest lint rules from Flutter repo. + +## 2.0.3 + +* Relaxed constraints on `package:test` + +## 2.0.2 + +* Bumped dependency on `package:test` to version 1.0 + +## 2.0.1 + +* Bumped Dart SDK constraint to allow for Dart 2 stable + +## 2.0.0 + +* Removed `record_replay_matchers.dart` from API + +## 1.0.0 + +* Moved `package:file/testing.dart` library into a dedicated package so that + libraries don't need to take on a transitive dependency on `package:test` + in order to use `package:file`.
diff --git a/pkgs/file_testing/LICENSE b/pkgs/file_testing/LICENSE new file mode 100644 index 0000000..076334f --- /dev/null +++ b/pkgs/file_testing/LICENSE
@@ -0,0 +1,26 @@ +Copyright 2017, the Dart project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file
diff --git a/pkgs/file_testing/README.md b/pkgs/file_testing/README.md new file mode 100644 index 0000000..7dda57e --- /dev/null +++ b/pkgs/file_testing/README.md
@@ -0,0 +1,39 @@ +[](https://pub.dev/packages/file_testing) +[](https://pub.dev/packages/file_testing/publisher) + +Testing utilities intended to work with `package:file`. + +## Features + +This package provides a series of matchers to be used in tests that work with file +system types. + +## Usage + +```dart +import 'package:file/file.dart'; +import 'package:file/memory.dart'; +import 'package:file_testing/file_testing.dart'; +import 'package:test/test.dart'; + +void main() { + MemoryFileSystem fs; + + setUp(() { + fs = MemoryFileSystem(); + fs.file('/foo').createSync(); + }); + + test('some test', () { + expectFileSystemException( + ErrorCodes.ENOENT, + () { + fs.directory('').resolveSymbolicLinksSync(); + }, + ); + expect(fs.file('/path/to/file'), isFile); + expect(fs.file('/path/to/directory'), isDirectory); + expect(fs.file('/foo'), exists); + }); +} +```
diff --git a/pkgs/file_testing/analysis_options.yaml b/pkgs/file_testing/analysis_options.yaml new file mode 100644 index 0000000..8fbd2e4 --- /dev/null +++ b/pkgs/file_testing/analysis_options.yaml
@@ -0,0 +1,6 @@ +include: package:lints/recommended.yaml + +analyzer: + errors: + # Allow having TODOs in the code + todo: ignore
diff --git a/pkgs/file_testing/lib/file_testing.dart b/pkgs/file_testing/lib/file_testing.dart new file mode 100644 index 0000000..2ac2d0a --- /dev/null +++ b/pkgs/file_testing/lib/file_testing.dart
@@ -0,0 +1,8 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Matchers (from `package:test`) for use in tests that deal with file systems. +library; + +export 'src/testing/core_matchers.dart';
diff --git a/pkgs/file_testing/lib/src/testing/core_matchers.dart b/pkgs/file_testing/lib/src/testing/core_matchers.dart new file mode 100644 index 0000000..f58539f --- /dev/null +++ b/pkgs/file_testing/lib/src/testing/core_matchers.dart
@@ -0,0 +1,155 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:io'; + +import 'package:test/test.dart'; + +import 'internal.dart'; + +/// Matcher that successfully matches against any instance of [Directory]. +const Matcher isDirectory = TypeMatcher<Directory>(); + +/// Matcher that successfully matches against any instance of [File]. +const Matcher isFile = TypeMatcher<File>(); + +/// Matcher that successfully matches against any instance of [Link]. +const Matcher isLink = TypeMatcher<Link>(); + +/// Matcher that successfully matches against any instance of +/// [FileSystemEntity]. +const Matcher isFileSystemEntity = TypeMatcher<FileSystemEntity>(); + +/// Matcher that successfully matches against any instance of [FileStat]. +const Matcher isFileStat = TypeMatcher<FileStat>(); + +/// Returns a [Matcher] that matches [path] against an entity's path. +/// +/// [path] may be a String, a predicate function, or a [Matcher]. If it is +/// a String, it will be wrapped in an equality matcher. +Matcher hasPath(dynamic path) => _HasPath(path); + +/// Returns a [Matcher] that successfully matches against an instance of +/// [FileSystemException]. +/// +/// If [osErrorCode] is specified, matches will be limited to exceptions whose +/// `osError.errorCode` also match the specified matcher. +/// +/// [osErrorCode] may be an `int`, a predicate function, or a [Matcher]. If it +/// is an `int`, it will be wrapped in an equality matcher. +Matcher isFileSystemException([dynamic osErrorCode]) => + _FileSystemException(osErrorCode); + +/// Returns a matcher that successfully matches against a future or function +/// that throws a [FileSystemException]. +/// +/// If [osErrorCode] is specified, matches will be limited to exceptions whose +/// `osError.errorCode` also match the specified matcher. +/// +/// [osErrorCode] may be an `int`, a predicate function, or a [Matcher]. If it +/// is an `int`, it will be wrapped in an equality matcher. +Matcher throwsFileSystemException([dynamic osErrorCode]) => + throwsA(isFileSystemException(osErrorCode)); + +/// Expects the specified [callback] to throw a [FileSystemException] with the +/// specified [osErrorCode] (matched against the exception's +/// `osError.errorCode`). +/// +/// [osErrorCode] may be an `int`, a predicate function, or a [Matcher]. If it +/// is an `int`, it will be wrapped in an equality matcher. +/// +/// See also: +/// - [ErrorCodes] +void expectFileSystemException(dynamic osErrorCode, void Function() callback) { + expect(callback, throwsFileSystemException(osErrorCode)); +} + +/// Matcher that successfully matches against a [FileSystemEntity] that +/// exists ([FileSystemEntity.existsSync] returns true). +const Matcher exists = _Exists(); + +class _FileSystemException extends Matcher { + _FileSystemException(dynamic osErrorCode) + : _matcher = _wrapMatcher(osErrorCode); + + final Matcher? _matcher; + + static Matcher? _wrapMatcher(dynamic osErrorCode) { + if (osErrorCode == null) { + return null; + } + return ignoreOsErrorCodes ? anything : wrapMatcher(osErrorCode); + } + + @override + bool matches(dynamic item, Map<dynamic, dynamic> matchState) { + if (item is FileSystemException) { + return _matcher == null || + _matcher!.matches(item.osError?.errorCode, matchState); + } + return false; + } + + @override + Description describe(Description desc) { + if (_matcher == null) { + return desc.add('FileSystemException'); + } else { + desc.add('FileSystemException with osError.errorCode: '); + return _matcher!.describe(desc); + } + } +} + +class _HasPath extends Matcher { + _HasPath(dynamic path) : _matcher = wrapMatcher(path); + + final Matcher _matcher; + + @override + bool matches(dynamic item, Map<dynamic, dynamic> matchState) => + _matcher.matches(item.path, matchState); + + @override + Description describe(Description desc) { + desc.add('has path: '); + return _matcher.describe(desc); + } + + @override + Description describeMismatch( + dynamic item, + Description desc, + Map<dynamic, dynamic> matchState, + bool verbose, + ) { + desc.add('has path: \'${item.path}\'').add('\n Which: '); + final Description pathDesc = StringDescription(); + _matcher.describeMismatch(item.path, pathDesc, matchState, verbose); + desc.add(pathDesc.toString()); + return desc; + } +} + +class _Exists extends Matcher { + const _Exists(); + + @override + bool matches(dynamic item, Map<dynamic, dynamic> matchState) => + item is FileSystemEntity && item.existsSync(); + + @override + Description describe(Description description) => + description.add('a file system entity that exists'); + + @override + Description describeMismatch( + dynamic item, + Description description, + Map<dynamic, dynamic> matchState, + bool verbose, + ) { + return description.add('does not exist'); + } +}
diff --git a/pkgs/file_testing/lib/src/testing/internal.dart b/pkgs/file_testing/lib/src/testing/internal.dart new file mode 100644 index 0000000..8f53a65 --- /dev/null +++ b/pkgs/file_testing/lib/src/testing/internal.dart
@@ -0,0 +1,6 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// True if we should ignore OS error codes in our matchers. +bool ignoreOsErrorCodes = false;
diff --git a/pkgs/file_testing/pubspec.yaml b/pkgs/file_testing/pubspec.yaml new file mode 100644 index 0000000..1dd0396 --- /dev/null +++ b/pkgs/file_testing/pubspec.yaml
@@ -0,0 +1,13 @@ +name: file_testing +version: 3.0.2 +description: Testing utilities for package:file. +repository: https://github.com/dart-lang/tools/tree/main/pkgs/file_testing + +environment: + sdk: ^3.1.0 + +dependencies: + test: ^1.23.1 + +dev_dependencies: + lints: ^5.0.0
diff --git a/pkgs/graphs/.gitignore b/pkgs/graphs/.gitignore new file mode 100644 index 0000000..ddfdca1 --- /dev/null +++ b/pkgs/graphs/.gitignore
@@ -0,0 +1,5 @@ +.dart_tool/ +.packages +.pub/ +build/ +pubspec.lock
diff --git a/pkgs/graphs/CHANGELOG.md b/pkgs/graphs/CHANGELOG.md new file mode 100644 index 0000000..7213b5a --- /dev/null +++ b/pkgs/graphs/CHANGELOG.md
@@ -0,0 +1,77 @@ +## 2.3.3-wip + +- Add an example usage to the README. + +## 2.3.2 + +- Require Dart 3.4 +- Update to the latest version of `package:dart_flutter_team_lints`. + +## 2.3.1 + +- Update package repository after move. + +## 2.3.0 + +- Add a `transitiveClosure` function. +- Make `stronglyConnectedComponents` and `topologicalSort` iterative rather than + recursive to avoid stack overflows on very large graphs. +- Require Dart 2.18 + +## 2.2.0 + +- Add a `secondarySort` parameter to the `topologicalSort()` function which + applies an additional lexical sort where that doesn't break the topological + sort. + +## 2.1.0 + +- Add a `topologicalSort()` function. + +## 2.0.0 + +- **Breaking**: `crawlAsync` will no longer ignore a node from the graph if the + `readNode` callback returns null. + +## 1.0.0 + +- Migrate to null safety. +- **Breaking**: Paths from `shortestPath[s]` are now returned as iterables to + reduce memory consumption of the algorithm to O(n). + +## 0.2.0 + +- **BREAKING** `shortestPath`, `shortestPaths` and `stronglyConnectedComponents` + now have one generic parameter and have replaced the `key` parameter with + optional params: `{bool equals(T key1, T key2), int hashCode(T key)}`. + This follows the pattern used in `dart:collection` classes `HashMap` and + `LinkedHashMap`. It improves the usability and performance of the case where + the source values are directly usable in a hash data structure. + +## 0.1.3+1 + +- Fixed a bug with non-identity `key` in `shortestPath` and `shortestPaths`. + +## 0.1.3 + +- Added `shortestPath` and `shortestPaths` functions. +- Use `HashMap` and `HashSet` from `dart:collection` for + `stronglyConnectedComponents`. Improves runtime performance. + +## 0.1.2+1 + +- Allow using non-dev Dart 2 SDK. + +## 0.1.2 + +- `crawlAsync` surfaces exceptions while crawling through the result stream + rather than as uncaught asynchronous errors. + +## 0.1.1 + +- `crawlAsync` will now ignore nodes that are resolved to `null`. + +## 0.1.0 + +- Initial release with an implementation of `stronglyConnectedComponents` and + `crawlAsync`.
diff --git a/pkgs/graphs/LICENSE b/pkgs/graphs/LICENSE new file mode 100644 index 0000000..03af64a --- /dev/null +++ b/pkgs/graphs/LICENSE
@@ -0,0 +1,27 @@ +Copyright 2017, the Dart project authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google LLC nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/pkgs/graphs/README.md b/pkgs/graphs/README.md new file mode 100644 index 0000000..09512b8 --- /dev/null +++ b/pkgs/graphs/README.md
@@ -0,0 +1,57 @@ +[](https://github.com/dart-lang/tools/actions/workflows/graphs.yml) +[](https://pub.dev/packages/graphs) +[](https://pub.dev/packages/graphs/publisher) + +Graph algorithms that do not specify a particular approach for representing a +Graph. + +Each algorithm is a top level function which takes callback arguments that +provide the mechanism for traversing the graph. For example, two common +approaches for representing a graph: + +```dart +class AdjacencyListGraph<T> { + Map<T, List<T>> nodes; + // ... +} +``` + +```dart +class TreeGraph<T> { + Node<T> root; + // ... +} +class Node<T> { + List<Node<T>> edges; + T value; +} +``` + +Any representation can be adapted to the callback arguments. + +- Algorithms which need to traverse the graph take an `edges` callback which + provides the immediate neighbors of a given node. +- Algorithms which need to associate unique data with each node in the graph + allow passing `equals` and/or `hashCode` callbacks if the unique data type + does not correctly or efficiently implement `operator==` or `get hashCode`. + + +Algorithms that support graphs which are resolved asynchronously will have +similar callbacks which return `FutureOr`. + +```dart +import 'package:graphs/graphs.dart'; + +void sendMessage() { + final network = AdjacencyListGraph(); + // ... + final route = shortestPath( + sender, receiver, (node) => network.nodes[node] ?? const []); +} + +void resolveBuildOrder() { + final dependencies = TreeGraph(); + // ... + final buildOrder = topologicalSort([dependencies.root], (node) => node.edges); +} +```
diff --git a/pkgs/graphs/analysis_options.yaml b/pkgs/graphs/analysis_options.yaml new file mode 100644 index 0000000..19437b4 --- /dev/null +++ b/pkgs/graphs/analysis_options.yaml
@@ -0,0 +1,36 @@ +# https://dart.dev/guides/language/analysis-options +include: package:dart_flutter_team_lints/analysis_options.yaml + +analyzer: + language: + strict-raw-types: true + errors: + sort_pub_dependencies: ignore + # https://github.com/dart-lang/sdk/issues/56465 + unintended_html_in_doc_comment: ignore + +linter: + rules: + - avoid_bool_literals_in_conditional_expressions + - avoid_classes_with_only_static_members + - avoid_private_typedef_functions + - avoid_redundant_argument_values + - avoid_returning_this + - avoid_unused_constructor_parameters + - avoid_void_async + - cancel_subscriptions + - join_return_with_assignment + - literal_only_boolean_expressions + - missing_whitespace_between_adjacent_strings + - no_adjacent_strings_in_list + - no_runtimeType_toString + - package_api_docs + - prefer_const_declarations + - prefer_expression_function_bodies + - prefer_final_locals + - require_trailing_commas + - unnecessary_await_in_return + - unnecessary_raw_strings + - use_if_null_to_convert_nulls_to_bools + - use_raw_strings + - use_string_buffers
diff --git a/pkgs/graphs/benchmark/connected_components_benchmark.dart b/pkgs/graphs/benchmark/connected_components_benchmark.dart new file mode 100644 index 0000000..1f71879 --- /dev/null +++ b/pkgs/graphs/benchmark/connected_components_benchmark.dart
@@ -0,0 +1,50 @@ +// Copyright (c) 2018, 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:collection'; +import 'dart:math' show Random; + +import 'package:graphs/graphs.dart'; + +void main() { + final rnd = Random(0); + const size = 2000; + final graph = HashMap<int, List<int>>(); + + for (var i = 0; i < size * 3; i++) { + final toList = graph.putIfAbsent(rnd.nextInt(size), () => <int>[]); + + final toValue = rnd.nextInt(size); + if (!toList.contains(toValue)) { + toList.add(toValue); + } + } + + var maxCount = 0; + var maxIteration = 0; + + const duration = Duration(milliseconds: 100); + + for (var i = 1;; i++) { + var count = 0; + final watch = Stopwatch()..start(); + while (watch.elapsed < duration) { + count++; + final length = + stronglyConnectedComponents(graph.keys, (e) => graph[e] ?? <Never>[]) + .length; + assert(length == 244, '$length'); + } + + if (count > maxCount) { + maxCount = count; + maxIteration = i; + } + + if (maxIteration == i || (i - maxIteration) % 20 == 0) { + print('max iterations in ${duration.inMilliseconds}ms: $maxCount\t' + 'after $maxIteration of $i iterations'); + } + } +}
diff --git a/pkgs/graphs/benchmark/shortest_path_benchmark.dart b/pkgs/graphs/benchmark/shortest_path_benchmark.dart new file mode 100644 index 0000000..67e7367 --- /dev/null +++ b/pkgs/graphs/benchmark/shortest_path_benchmark.dart
@@ -0,0 +1,54 @@ +// Copyright (c) 2018, 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:collection'; +import 'dart:math' show Random; + +import 'package:graphs/graphs.dart'; + +void main() { + final rnd = Random(1); + const size = 1000; + final graph = HashMap<int, List<int>>(); + + for (var i = 0; i < size * 5; i++) { + final toList = graph.putIfAbsent(rnd.nextInt(size), () => <int>[]); + + final toValue = rnd.nextInt(size); + if (!toList.contains(toValue)) { + toList.add(toValue); + } + } + + int? minTicks; + var maxIteration = 0; + + final testOutput = + shortestPath(0, size - 1, (e) => graph[e] ?? <Never>[]).toString(); + print(testOutput); + assert(testOutput == '(258, 252, 819, 999)', testOutput); + + final watch = Stopwatch(); + for (var i = 1;; i++) { + watch + ..reset() + ..start(); + final result = shortestPath(0, size - 1, (e) => graph[e] ?? <Never>[])!; + final length = result.length; + final first = result.first; + watch.stop(); + assert(length == 4, '$length'); + assert(first == 258, '$first'); + + if (minTicks == null || watch.elapsedTicks < minTicks) { + minTicks = watch.elapsedTicks; + maxIteration = i; + } + + if (maxIteration == i || (i - maxIteration) % 100000 == 0) { + print('min ticks for one run: $minTicks\t' + 'after $maxIteration of $i iterations'); + } + } +}
diff --git a/pkgs/graphs/benchmark/shortest_path_worst_case_benchmark.dart b/pkgs/graphs/benchmark/shortest_path_worst_case_benchmark.dart new file mode 100644 index 0000000..d3117ac --- /dev/null +++ b/pkgs/graphs/benchmark/shortest_path_worst_case_benchmark.dart
@@ -0,0 +1,58 @@ +// Copyright (c) 2020, 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:collection'; + +import 'package:graphs/graphs.dart'; + +void main() { + const size = 1000; + final graph = HashMap<int, List<int>>(); + + // We create a graph where every subsequent node has an edge to every other + // node before it as well as the next node. This triggers worst case behavior + // in many algorithms as it requires visiting all nodes and edges before + // finding a solution, and there are a maximum number of edges. + for (var i = 0; i < size; i++) { + final toList = graph.putIfAbsent(i, () => <int>[]); + for (var t = 0; t < i + 2 && i < size; t++) { + if (i == t) continue; + toList.add(t); + } + } + + int? minTicks; + var maxIteration = 0; + + final testOutput = + shortestPath(0, size - 1, (e) => graph[e] ?? <Never>[]).toString(); + print(testOutput); + assert( + testOutput == Iterable.generate(size - 1, (i) => i + 1).toString(), + testOutput, + ); + + final watch = Stopwatch(); + for (var i = 1;; i++) { + watch + ..reset() + ..start(); + final result = shortestPath(0, size - 1, (e) => graph[e] ?? <Never>[])!; + final length = result.length; + final first = result.first; + watch.stop(); + assert(length == 999, '$length'); + assert(first == 1, '$first'); + + if (minTicks == null || watch.elapsedTicks < minTicks) { + minTicks = watch.elapsedTicks; + maxIteration = i; + } + + if (maxIteration == i || (i - maxIteration) % 100000 == 0) { + print('min ticks for one run: $minTicks\t' + 'after $maxIteration of $i iterations'); + } + } +}
diff --git a/pkgs/graphs/example/crawl_async_example.dart b/pkgs/graphs/example/crawl_async_example.dart new file mode 100644 index 0000000..bd305c9 --- /dev/null +++ b/pkgs/graphs/example/crawl_async_example.dart
@@ -0,0 +1,84 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:isolate'; + +import 'package:analyzer/dart/analysis/analysis_context_collection.dart'; +import 'package:analyzer/dart/analysis/results.dart'; +import 'package:analyzer/dart/ast/ast.dart'; +import 'package:graphs/graphs.dart'; +import 'package:path/path.dart' as p; +import 'package:pool/pool.dart'; + +/// Print a transitive set of imported URIs where libraries are read +/// asynchronously. +Future<void> main() async { + // Limits calls to [findImports]. + final pool = Pool(10); + final allImports = await crawlAsync<Uri, Source>( + [Uri.parse('package:graphs/graphs.dart')], + read, + (from, source) => pool.withResource(() => findImports(from, source)), + ).toList(); + print(allImports.map((s) => s.uri).toList()); +} + +AnalysisContextCollection? _analysisContextCollection; + +Future<AnalysisContextCollection> get analysisContextCollection async { + var collection = _analysisContextCollection; + if (collection == null) { + final libUri = Uri.parse('package:graphs/'); + final libPath = await pathForUri(libUri); + final packagePath = p.dirname(libPath); + + collection = _analysisContextCollection = AnalysisContextCollection( + includedPaths: [packagePath], + ); + } + + return collection; +} + +Future<Iterable<Uri>> findImports(Uri from, Source source) async => + source.unit.directives + .whereType<UriBasedDirective>() + .map((d) => d.uri.stringValue!) + .where((uri) => !uri.startsWith('dart:')) + .map((import) => resolveImport(import, from)); + +Future<CompilationUnit> parseUri(Uri uri) async { + final path = await pathForUri(uri); + final analysisContext = (await analysisContextCollection).contexts.single; + final analysisSession = analysisContext.currentSession; + final parseResult = analysisSession.getParsedUnit(path); + return (parseResult as ParsedUnitResult).unit; +} + +Future<String> pathForUri(Uri uri) async { + final fileUri = await Isolate.resolvePackageUri(uri); + if (fileUri == null || !fileUri.isScheme('file')) { + throw StateError('Expected to resolve $uri to a file URI, got $fileUri'); + } + return p.fromUri(fileUri); +} + +Future<Source> read(Uri uri) async => Source(uri, await parseUri(uri)); + +Uri resolveImport(String import, Uri from) { + if (import.startsWith('package:')) return Uri.parse(import); + assert(from.scheme == 'package'); + final package = from.pathSegments.first; + final fromPath = p.joinAll(from.pathSegments.skip(1)); + final path = p.normalize(p.join(p.dirname(fromPath), import)); + return Uri.parse('package:${p.join(package, path)}'); +} + +class Source { + final Uri uri; + final CompilationUnit unit; + + Source(this.uri, this.unit); +}
diff --git a/pkgs/graphs/example/example.dart b/pkgs/graphs/example/example.dart new file mode 100644 index 0000000..c9cf6dd --- /dev/null +++ b/pkgs/graphs/example/example.dart
@@ -0,0 +1,49 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:graphs/graphs.dart'; + +/// A representation of a directed graph. +/// +/// Data is stored on the [Node] class. +class Graph { + final Map<Node, List<Node>> nodes; + + Graph(this.nodes); +} + +class Node { + final String id; + final int data; + + Node(this.id, this.data); + + @override + bool operator ==(Object other) => other is Node && other.id == id; + + @override + int get hashCode => id.hashCode; + + @override + String toString() => '<$id -> $data>'; +} + +void main() { + final nodeA = Node('A', 1); + final nodeB = Node('B', 2); + final nodeC = Node('C', 3); + final nodeD = Node('D', 4); + final graph = Graph({ + nodeA: [nodeB, nodeC], + nodeB: [nodeC, nodeD], + nodeC: [nodeB, nodeD], + }); + + final components = stronglyConnectedComponents<Node>( + graph.nodes.keys, + (node) => graph.nodes[node] ?? [], + ); + + print(components); +}
diff --git a/pkgs/graphs/lib/graphs.dart b/pkgs/graphs/lib/graphs.dart new file mode 100644 index 0000000..f10b2e4 --- /dev/null +++ b/pkgs/graphs/lib/graphs.dart
@@ -0,0 +1,11 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +export 'src/crawl_async.dart' show crawlAsync; +export 'src/cycle_exception.dart' show CycleException; +export 'src/shortest_path.dart' show shortestPath, shortestPaths; +export 'src/strongly_connected_components.dart' + show stronglyConnectedComponents; +export 'src/topological_sort.dart' show topologicalSort; +export 'src/transitive_closure.dart' show transitiveClosure;
diff --git a/pkgs/graphs/lib/src/crawl_async.dart b/pkgs/graphs/lib/src/crawl_async.dart new file mode 100644 index 0000000..68c0a5b --- /dev/null +++ b/pkgs/graphs/lib/src/crawl_async.dart
@@ -0,0 +1,85 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:collection'; + +final _empty = Future<void>.value(); + +/// Finds and returns every node in a graph who's nodes and edges are +/// asynchronously resolved. +/// +/// Cycles are allowed. If this is an undirected graph the [edges] function +/// may be symmetric. In this case the [roots] may be any node in each connected +/// graph. +/// +/// [V] is the type of values in the graph nodes. [K] must be a type suitable +/// for using as a Map or Set key. [edges] should return the next reachable +/// nodes. +/// +/// There are no ordering guarantees. This is useful for ensuring some work is +/// performed at every node in an asynchronous graph, but does not give +/// guarantees that the work is done in topological order. +/// +/// If either [readNode] or [edges] throws the error will be forwarded +/// through the result stream and no further nodes will be crawled, though some +/// work may have already been started. +/// +/// Crawling is eager, so calls to [edges] may overlap with other calls that +/// have not completed. If the [edges] callback needs to be limited or throttled +/// that must be done by wrapping it before calling [crawlAsync]. +Stream<V> crawlAsync<K extends Object, V>( + Iterable<K> roots, + FutureOr<V> Function(K) readNode, + FutureOr<Iterable<K>> Function(K, V) edges, +) { + final crawl = _CrawlAsync(roots, readNode, edges)..run(); + return crawl.result.stream; +} + +class _CrawlAsync<K, V> { + final result = StreamController<V>(); + + final FutureOr<V> Function(K) readNode; + final FutureOr<Iterable<K>> Function(K, V) edges; + final Iterable<K> roots; + + final _seen = HashSet<K>(); + + _CrawlAsync(this.roots, this.readNode, this.edges); + + /// Add all nodes in the graph to [result] and return a Future which fires + /// after all nodes have been seen. + Future<void> run() async { + try { + await Future.wait(roots.map(_visit), eagerError: true); + await result.close(); + } catch (e, st) { + result.addError(e, st); + await result.close(); + } + } + + /// Resolve the node at [key] and output it, then start crawling all of it's + /// edges. + Future<void> _crawlFrom(K key) async { + final value = await readNode(key); + if (result.isClosed) return; + result.add(value); + final next = await edges(key, value); + await Future.wait(next.map(_visit), eagerError: true); + } + + /// Synchronously record that [key] is being handled then start work on the + /// node for [key]. + /// + /// The returned Future will complete only after the work for [key] and all + /// transitively reachable nodes has either been finished, or will be finished + /// by some other Future in [_seen]. + Future<void> _visit(K key) { + if (_seen.contains(key)) return _empty; + _seen.add(key); + return _crawlFrom(key); + } +}
diff --git a/pkgs/graphs/lib/src/cycle_exception.dart b/pkgs/graphs/lib/src/cycle_exception.dart new file mode 100644 index 0000000..eb9b433 --- /dev/null +++ b/pkgs/graphs/lib/src/cycle_exception.dart
@@ -0,0 +1,19 @@ +// 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. + +/// An exception indicating that a cycle was detected in a graph that was +/// expected to be acyclic. +class CycleException<T> implements Exception { + /// The list of nodes comprising the cycle. + /// + /// Each node in this list has an edge to the next node. The final node has an + /// edge to the first node. + final List<T> cycle; + + CycleException(Iterable<T> cycle) : cycle = List.unmodifiable(cycle); + + @override + String toString() => 'A cycle was detected in a graph that must be acyclic:\n' + '${cycle.map((node) => '* $node').join('\n')}'; +}
diff --git a/pkgs/graphs/lib/src/shortest_path.dart b/pkgs/graphs/lib/src/shortest_path.dart new file mode 100644 index 0000000..28f7e51 --- /dev/null +++ b/pkgs/graphs/lib/src/shortest_path.dart
@@ -0,0 +1,144 @@ +// Copyright (c) 2018, 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:collection'; + +/// Returns the shortest path from [start] to [target] given the directed +/// edges of a graph provided by [edges]. +/// +/// If [start] `==` [target], an empty [List] is returned and [edges] is never +/// called. +/// +/// If [equals] is provided, it is used to compare nodes in the graph. If +/// [equals] is omitted, the node's own [Object.==] is used instead. +/// +/// Similarly, if [hashCode] is provided, it is used to produce a hash value +/// for nodes to efficiently calculate the return value. If it is omitted, the +/// key's own [Object.hashCode] is used. +/// +/// If you supply one of [equals] or [hashCode], you should generally also to +/// supply the other. +Iterable<T>? shortestPath<T extends Object>( + T start, + T target, + Iterable<T> Function(T) edges, { + bool Function(T, T)? equals, + int Function(T)? hashCode, +}) => + _shortestPaths<T>( + start, + edges, + target: target, + equals: equals, + hashCode: hashCode, + )[target]; + +/// Returns a [Map] of the shortest paths from [start] to all of the nodes in +/// the directed graph defined by [edges]. +/// +/// All return values will contain the key [start] with an empty [List] value. +/// +/// [start] and all values returned by [edges] must not be `null`. +/// If asserts are enabled, an [AssertionError] is raised if these conditions +/// are not met. If asserts are not enabled, violations result in undefined +/// behavior. +/// +/// If [equals] is provided, it is used to compare nodes in the graph. If +/// [equals] is omitted, the node's own [Object.==] is used instead. +/// +/// Similarly, if [hashCode] is provided, it is used to produce a hash value +/// for nodes to efficiently calculate the return value. If it is omitted, the +/// key's own [Object.hashCode] is used. +/// +/// If you supply one of [equals] or [hashCode], you should generally also to +/// supply the other. +Map<T, Iterable<T>> shortestPaths<T extends Object>( + T start, + Iterable<T> Function(T) edges, { + bool Function(T, T)? equals, + int Function(T)? hashCode, +}) => + _shortestPaths<T>( + start, + edges, + equals: equals, + hashCode: hashCode, + ); + +Map<T, Iterable<T>> _shortestPaths<T extends Object>( + T start, + Iterable<T> Function(T) edges, { + T? target, + bool Function(T, T)? equals, + int Function(T)? hashCode, +}) { + final distances = HashMap<T, _Tail<T>>(equals: equals, hashCode: hashCode); + distances[start] = _Tail<T>(); + + final nonNullEquals = equals ??= _defaultEquals; + final isTarget = + target == null ? _neverTarget : (T node) => nonNullEquals(node, target); + if (isTarget(start)) { + return distances; + } + + final toVisit = ListQueue<T>()..add(start); + + while (toVisit.isNotEmpty) { + final current = toVisit.removeFirst(); + final currentPath = distances[current]!; + + for (var edge in edges(current)) { + final existingPath = distances[edge]; + + if (existingPath == null) { + distances[edge] = currentPath.append(edge); + if (isTarget(edge)) { + return distances; + } + toVisit.add(edge); + } + } + } + + return distances; +} + +bool _defaultEquals(Object a, Object b) => a == b; +bool _neverTarget(Object _) => false; + +/// An immutable iterable that can efficiently return a copy with a value +/// appended. +/// +/// This implementation has an efficient [length] property. +/// +/// Note that grabbing an [iterator] for the first time is O(n) in time and +/// space because it copies all the values to a new list and uses that +/// iterator in order to avoid stack overflows for large paths. This copy is +/// cached for subsequent calls. +class _Tail<T extends Object> extends Iterable<T> { + final T? tail; + final _Tail<T>? head; + @override + final int length; + _Tail() + : tail = null, + head = null, + length = 0; + _Tail._(this.tail, this.head, this.length); + _Tail<T> append(T value) => _Tail._(value, this, length + 1); + + @override + Iterator<T> get iterator => _asIterable.iterator; + + late final _asIterable = () { + _Tail<T>? next = this; + final reversed = List.generate(length, (_) { + final val = next!.tail; + next = next!.head; + return val as T; + }); + return reversed.reversed; + }(); +}
diff --git a/pkgs/graphs/lib/src/strongly_connected_components.dart b/pkgs/graphs/lib/src/strongly_connected_components.dart new file mode 100644 index 0000000..e8a775c --- /dev/null +++ b/pkgs/graphs/lib/src/strongly_connected_components.dart
@@ -0,0 +1,117 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:collection'; +import 'dart:math' show min; + +/// Finds the strongly connected components of a directed graph using Tarjan's +/// algorithm. +/// +/// The result will be a valid reverse topological order ordering of the +/// strongly connected components. Components further from a root will appear in +/// the result before the components which they are connected to. +/// +/// Nodes within a strongly connected component have no ordering guarantees, +/// except that if the first value in [nodes] is a valid root, and is contained +/// in a cycle, it will be the last element of that cycle. +/// +/// [nodes] must contain at least a root of every tree in the graph if there are +/// disjoint subgraphs but it may contain all nodes in the graph if the roots +/// are not known. +/// +/// If [equals] is provided, it is used to compare nodes in the graph. If +/// [equals] is omitted, the node's own [Object.==] is used instead. +/// +/// Similarly, if [hashCode] is provided, it is used to produce a hash value +/// for nodes to efficiently calculate the return value. If it is omitted, the +/// key's own [Object.hashCode] is used. +/// +/// If you supply one of [equals] or [hashCode], you should generally also to +/// supply the other. +List<List<T>> stronglyConnectedComponents<T extends Object>( + Iterable<T> nodes, + Iterable<T> Function(T) edges, { + bool Function(T, T)? equals, + int Function(T)? hashCode, +}) { + final result = <List<T>>[]; + final lowLinks = HashMap<T, int>(equals: equals, hashCode: hashCode); + final indexes = HashMap<T, int>(equals: equals, hashCode: hashCode); + final onStack = HashSet<T>(equals: equals, hashCode: hashCode); + + final nonNullEquals = equals ?? _defaultEquals; + + var index = 0; + final lastVisited = Queue<T>(); + + final stack = [for (final node in nodes) _StackState(node)]; + outer: + while (stack.isNotEmpty) { + final state = stack.removeLast(); + final node = state.node; + var iterator = state.iterator; + + int lowLink; + if (iterator == null) { + if (indexes.containsKey(node)) continue; + indexes[node] = index; + lowLink = lowLinks[node] = index; + index++; + iterator = edges(node).iterator; + + // Nodes with no edges are always in their own component. + if (!iterator.moveNext()) { + result.add([node]); + continue; + } + + lastVisited.addLast(node); + onStack.add(node); + } else { + lowLink = min(lowLinks[node]!, lowLinks[iterator.current]!); + } + + do { + final next = iterator.current; + if (!indexes.containsKey(next)) { + stack.add(_StackState(node, iterator)); + stack.add(_StackState(next)); + continue outer; + } else if (onStack.contains(next)) { + lowLink = lowLinks[node] = min(lowLink, indexes[next]!); + } + } while (iterator.moveNext()); + + if (lowLink == indexes[node]) { + final component = <T>[]; + T next; + do { + next = lastVisited.removeLast(); + onStack.remove(next); + component.add(next); + } while (!nonNullEquals(next, node)); + result.add(component); + } + } + + return result; +} + +/// The state of a pass on a single node in Tarjan's Algorithm. +/// +/// This is used to perform the algorithm with an explicit stack rather than +/// recursively, to avoid stack overflow errors for very large graphs. +class _StackState<T> { + /// The node being inspected. + final T node; + + /// The iterator traversing [node]'s edges. + /// + /// This is null if the node hasn't yet begun being traversed. + final Iterator<T>? iterator; + + _StackState(this.node, [this.iterator]); +} + +bool _defaultEquals(Object a, Object b) => a == b;
diff --git a/pkgs/graphs/lib/src/topological_sort.dart b/pkgs/graphs/lib/src/topological_sort.dart new file mode 100644 index 0000000..948e696 --- /dev/null +++ b/pkgs/graphs/lib/src/topological_sort.dart
@@ -0,0 +1,146 @@ +// 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 'dart:collection'; + +import 'package:collection/collection.dart' hide stronglyConnectedComponents; + +import 'cycle_exception.dart'; + +/// Returns a topological sort of the nodes of the directed edges of a graph +/// provided by [nodes] and [edges]. +/// +/// Each element of the returned iterable is guaranteed to appear after all +/// nodes that have edges leading to that node. The result is not guaranteed to +/// be unique, nor is it guaranteed to be stable across releases of this +/// package; however, it will be stable for a given input within a given package +/// version. +/// +/// If [equals] is provided, it is used to compare nodes in the graph. If +/// [equals] is omitted, the node's own [Object.==] is used instead. +/// +/// Similarly, if [hashCode] is provided, it is used to produce a hash value +/// for nodes to efficiently calculate the return value. If it is omitted, the +/// key's own [Object.hashCode] is used. +/// +/// If you supply one of [equals] or [hashCode], you should generally also to +/// supply the other. +/// +/// If you supply [secondarySort], the resulting list will be sorted by that +/// comparison function as much as possible without violating the topological +/// ordering. Note that even with a secondary sort, the result is _still_ not +/// guaranteed to be unique or stable across releases of this package. +/// +/// Note: this requires that [nodes] and each iterable returned by [edges] +/// contain no duplicate entries. +/// +/// Throws a [CycleException<T>] if the graph is cyclical. +List<T> topologicalSort<T>( + Iterable<T> nodes, + Iterable<T> Function(T) edges, { + bool Function(T, T)? equals, + int Function(T)? hashCode, + Comparator<T>? secondarySort, +}) { + if (secondarySort != null) { + return _topologicalSortWithSecondary( + [...nodes], + edges, + secondarySort, + equals, + hashCode, + ); + } + + // https://en.wikipedia.org/wiki/Topological_sorting#Depth-first_search + final result = QueueList<T>(); + final permanentMark = HashSet<T>(equals: equals, hashCode: hashCode); + final temporaryMark = LinkedHashSet<T>(equals: equals, hashCode: hashCode); + final stack = [...nodes]; + while (stack.isNotEmpty) { + final node = stack.removeLast(); + if (permanentMark.contains(node)) continue; + + // If we're visiting this node while it's already marked and not through a + // dependency, that must mean we've traversed all its dependencies and it's + // safe to add it to the result. + if (temporaryMark.contains(node)) { + temporaryMark.remove(node); + permanentMark.add(node); + result.addFirst(node); + } else { + temporaryMark.add(node); + + // Revisit this node once we've visited all its children. + stack.add(node); + for (var child in edges(node)) { + if (temporaryMark.contains(child)) throw CycleException(temporaryMark); + stack.add(child); + } + } + } + + return result; +} + +/// An implementation of [topologicalSort] with a secondary comparison function. +List<T> _topologicalSortWithSecondary<T>( + List<T> nodes, + Iterable<T> Function(T) edges, + Comparator<T> comparator, + bool Function(T, T)? equals, + int Function(T)? hashCode, +) { + // https://en.wikipedia.org/wiki/Topological_sorting#Kahn's_algorithm, + // modified to sort the nodes to traverse. Also documented in + // https://www.algotree.org/algorithms/tree_graph_traversal/lexical_topological_sort_c++/ + + // For each node, the number of incoming edges it has that we haven't yet + // traversed. + final incomingEdges = HashMap<T, int>(equals: equals, hashCode: hashCode); + for (var node in nodes) { + for (var child in edges(node)) { + incomingEdges[child] = (incomingEdges[child] ?? 0) + 1; + } + } + + // A priority queue of nodes that have no remaining incoming edges. + final nodesToTraverse = PriorityQueue<T>(comparator); + for (var node in nodes) { + if (!incomingEdges.containsKey(node)) nodesToTraverse.add(node); + } + + final result = <T>[]; + while (nodesToTraverse.isNotEmpty) { + final node = nodesToTraverse.removeFirst(); + result.add(node); + for (var child in edges(node)) { + var remainingEdges = incomingEdges[child]!; + remainingEdges--; + incomingEdges[child] = remainingEdges; + if (remainingEdges == 0) nodesToTraverse.add(child); + } + } + + if (result.length < nodes.length) { + // This algorithm doesn't automatically produce a cycle list as a side + // effect of sorting, so to throw the appropriate [CycleException] we just + // call the normal [topologicalSort] with a view of this graph that only + // includes nodes that still have edges. + bool nodeIsInCycle(T node) { + final edges = incomingEdges[node]; + return edges != null && edges > 0; + } + + topologicalSort<T>( + nodes.where(nodeIsInCycle), + edges, + equals: equals, + hashCode: hashCode, + ); + assert(false, 'topologicalSort() should throw if the graph has a cycle'); + } + + return result; +}
diff --git a/pkgs/graphs/lib/src/transitive_closure.dart b/pkgs/graphs/lib/src/transitive_closure.dart new file mode 100644 index 0000000..24791d6 --- /dev/null +++ b/pkgs/graphs/lib/src/transitive_closure.dart
@@ -0,0 +1,143 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:collection'; + +import 'cycle_exception.dart'; +import 'strongly_connected_components.dart'; +import 'topological_sort.dart'; + +/// Returns a transitive closure of a directed graph provided by [nodes] and +/// [edges]. +/// +/// The result is a map from [nodes] to the sets of nodes that are transitively +/// reachable through [edges]. No particular ordering is guaranteed. +/// +/// If [equals] is provided, it is used to compare nodes in the graph. If +/// [equals] is omitted, the node's own [Object.==] is used instead. +/// +/// Similarly, if [hashCode] is provided, it is used to produce a hash value +/// for nodes to efficiently calculate the return value. If it is omitted, the +/// key's own [Object.hashCode] is used. +/// +/// If you supply one of [equals] or [hashCode], you should generally also to +/// supply the other. +/// +/// Note: this requires that [nodes] and each iterable returned by [edges] +/// contain no duplicate entries. +/// +/// By default, this can handle either cyclic or acyclic graphs. If [acyclic] is +/// true, this will run more efficiently but throw a [CycleException] if the +/// graph is cyclical. +Map<T, Set<T>> transitiveClosure<T extends Object>( + Iterable<T> nodes, + Iterable<T> Function(T) edges, { + bool Function(T, T)? equals, + int Function(T)? hashCode, + bool acyclic = false, +}) { + if (!acyclic) { + return _cyclicTransitiveClosure( + nodes, + edges, + equals: equals, + hashCode: hashCode, + ); + } + + final topologicalOrder = + topologicalSort(nodes, edges, equals: equals, hashCode: hashCode); + final result = LinkedHashMap<T, Set<T>>(equals: equals, hashCode: hashCode); + for (final node in topologicalOrder.reversed) { + final closure = LinkedHashSet<T>(equals: equals, hashCode: hashCode); + for (var child in edges(node)) { + closure.add(child); + closure.addAll(result[child]!); + } + + result[node] = closure; + } + + return result; +} + +/// Returns the transitive closure of a cyclic graph using [Purdom's algorithm]. +/// +/// [Purdom's algorithm]: https://algowiki-project.org/en/Purdom%27s_algorithm +/// +/// This first computes the strongly connected components of the graph and finds +/// the transitive closure of those before flattening it out into the transitive +/// closure of the entire graph. +Map<T, Set<T>> _cyclicTransitiveClosure<T extends Object>( + Iterable<T> nodes, + Iterable<T> Function(T) edges, { + bool Function(T, T)? equals, + int Function(T)? hashCode, +}) { + final components = stronglyConnectedComponents<T>( + nodes, + edges, + equals: equals, + hashCode: hashCode, + ); + final nodesToComponents = + HashMap<T, List<T>>(equals: equals, hashCode: hashCode); + for (final component in components) { + for (final node in component) { + nodesToComponents[node] = component; + } + } + + // Because [stronglyConnectedComponents] returns the components in reverse + // topological order, we can avoid an additional topological sort here. + // Instead, we directly traverse the component list with the knowledge that + // once we reach a component, everything reachable from it has already been + // registered in [result]. + final result = LinkedHashMap<T, Set<T>>(equals: equals, hashCode: hashCode); + for (final component in components) { + final closure = LinkedHashSet<T>(equals: equals, hashCode: hashCode); + if (_componentIncludesCycle(component, edges, equals)) { + closure.addAll(component); + } + + // De-duplicate downstream components to avoid adding the same transitive + // children over and over. + final downstreamComponents = { + for (final node in component) + for (final child in edges(node)) nodesToComponents[child]!, + }; + for (final childComponent in downstreamComponents) { + if (childComponent == component) continue; + + // This if check is just for efficiency. If [childComponent] has multiple + // nodes, `result[childComponent.first]` will contain all the nodes in + // `childComponent` anyway since it's cyclical. + if (childComponent.length == 1) closure.addAll(childComponent); + closure.addAll(result[childComponent.first]!); + } + + for (final node in component) { + result[node] = closure; + } + } + return result; +} + +/// Returns whether the strongly-connected component [component] of a graph +/// defined by [edges] includes a cycle. +bool _componentIncludesCycle<T>( + List<T> component, + Iterable<T> Function(T) edges, + bool Function(T, T)? equals, +) { + // A strongly-connected component with more than one node always contains a + // cycle, by definition. + if (component.length > 1) return true; + + // A component with only a single node only contains a cycle if that node has + // an edge to itself. + final node = component.single; + return edges(node) + .any((edge) => equals == null ? edge == node : equals(edge, node)); +}
diff --git a/pkgs/graphs/pubspec.yaml b/pkgs/graphs/pubspec.yaml new file mode 100644 index 0000000..5b5457a --- /dev/null +++ b/pkgs/graphs/pubspec.yaml
@@ -0,0 +1,19 @@ +name: graphs +version: 2.3.3-wip +description: Graph algorithms that operate on graphs in any representation. +repository: https://github.com/dart-lang/tools/tree/main/pkgs/graphs + +environment: + sdk: ^3.4.0 + +dependencies: + collection: ^1.15.0 + +dev_dependencies: + dart_flutter_team_lints: ^3.0.0 + test: ^1.21.6 + + # For examples + analyzer: '>=5.2.0 <7.0.0' + path: ^1.8.0 + pool: ^1.5.0
diff --git a/pkgs/graphs/test/crawl_async_test.dart b/pkgs/graphs/test/crawl_async_test.dart new file mode 100644 index 0000000..9e168e6 --- /dev/null +++ b/pkgs/graphs/test/crawl_async_test.dart
@@ -0,0 +1,113 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:graphs/graphs.dart'; +import 'package:test/test.dart'; + +import 'utils/graph.dart'; + +void main() { + group('asyncCrawl', () { + Future<List<String?>> crawl( + Map<String, List<String>?> g, + Iterable<String> roots, + ) { + final graph = AsyncGraph(g); + return crawlAsync(roots, graph.readNode, graph.edges).toList(); + } + + test('empty result for empty graph', () async { + final result = await crawl({}, []); + expect(result, isEmpty); + }); + + test('single item for a single node', () async { + final result = await crawl({'a': []}, ['a']); + expect(result, ['a']); + }); + + test('hits every node in a graph', () async { + final result = await crawl({ + 'a': ['b', 'c'], + 'b': ['c'], + 'c': ['d'], + 'd': [], + }, [ + 'a', + ]); + expect(result, hasLength(4)); + expect( + result, + allOf(contains('a'), contains('b'), contains('c'), contains('d')), + ); + }); + + test('handles cycles', () async { + final result = await crawl({ + 'a': ['b'], + 'b': ['c'], + 'c': ['b'], + }, [ + 'a', + ]); + expect(result, hasLength(3)); + expect(result, allOf(contains('a'), contains('b'), contains('c'))); + }); + + test('handles self cycles', () async { + final result = await crawl({ + 'a': ['b'], + 'b': ['b'], + }, [ + 'a', + ]); + expect(result, hasLength(2)); + expect(result, allOf(contains('a'), contains('b'))); + }); + + test('allows null edges', () async { + final result = await crawl({ + 'a': ['b'], + 'b': null, + }, [ + 'a', + ]); + expect(result, hasLength(2)); + expect(result, allOf(contains('a'), contains('b'))); + }); + + test('allows null nodes', () async { + final result = await crawl({ + 'a': ['b'], + }, [ + 'a', + ]); + expect(result, ['a', null]); + }); + + test('surfaces exceptions for crawling edges', () { + final graph = { + 'a': ['b'], + }; + final nodes = crawlAsync( + ['a'], + (n) => n, + (k, n) => k == 'b' ? throw ArgumentError() : graph[k] ?? <String>[], + ); + expect(nodes, emitsThrough(emitsError(isArgumentError))); + }); + + test('surfaces exceptions for resolving keys', () { + final graph = { + 'a': ['b'], + }; + final nodes = crawlAsync( + ['a'], + (n) => n == 'b' ? throw ArgumentError() : n, + (k, n) => graph[k] ?? <Never>[], + ); + expect(nodes, emitsThrough(emitsError(isArgumentError))); + }); + }); +}
diff --git a/pkgs/graphs/test/shortest_path_test.dart b/pkgs/graphs/test/shortest_path_test.dart new file mode 100644 index 0000000..88281d4 --- /dev/null +++ b/pkgs/graphs/test/shortest_path_test.dart
@@ -0,0 +1,161 @@ +// Copyright (c) 2018, 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:collection'; +import 'dart:math' show Random; + +import 'package:graphs/graphs.dart'; +import 'package:test/test.dart'; + +import 'utils/utils.dart'; + +void main() { + const graph = <String, List<String>>{ + '1': ['2', '5'], + '2': ['3'], + '3': ['4', '5'], + '4': ['1'], + '5': ['8'], + '6': ['7'], + }; + + List<String> readEdges(String key) => graph[key] ?? []; + + List<X> getXValues(X key) => graph[key.value]?.map(X.new).toList() ?? []; + + void singlePathTest(String from, String to, List<String>? expected) { + test('$from -> $to should be $expected (mapped)', () { + expect( + shortestPath<X>( + X(from), + X(to), + getXValues, + equals: xEquals, + hashCode: xHashCode, + )?.map((x) => x.value), + expected, + ); + }); + + test('$from -> $to should be $expected', () { + expect(shortestPath(from, to, readEdges), expected); + }); + } + + void pathsTest( + String from, + Map<String, List<String>> expected, + List<String> nullPaths, + ) { + test('paths from $from (mapped)', () { + final result = shortestPaths<X>( + X(from), + getXValues, + equals: xEquals, + hashCode: xHashCode, + ).map((k, v) => MapEntry(k.value, v.map((x) => x.value).toList())); + expect(result, expected); + }); + + test('paths from $from', () { + final result = shortestPaths(from, readEdges); + expect(result, expected); + }); + + for (var entry in expected.entries) { + singlePathTest(from, entry.key, entry.value); + } + + for (var entry in nullPaths) { + singlePathTest(from, entry, null); + } + } + + pathsTest('1', { + '5': ['5'], + '3': ['2', '3'], + '8': ['5', '8'], + '1': [], + '2': ['2'], + '4': ['2', '3', '4'], + }, [ + '6', + '7', + ]); + + pathsTest('6', { + '7': ['7'], + '6': [], + }, [ + '1', + ]); + pathsTest('7', {'7': []}, ['1', '6']); + + pathsTest('42', {'42': []}, ['1', '6']); + + test('integration test', () { + // Be deterministic in the generated graph. This test may have to be updated + // if the behavior of `Random` changes for the provided seed. + final rnd = Random(1); + const size = 1000; + final graph = HashMap<int, List<int>>(); + + Iterable<int>? resultForGraph() => + shortestPath(0, size - 1, (e) => graph[e] ?? const []); + + void addRandomEdge() { + final toList = graph.putIfAbsent(rnd.nextInt(size), () => <int>[]); + + final toValue = rnd.nextInt(size); + if (!toList.contains(toValue)) { + toList.add(toValue); + } + } + + Iterable<int>? result; + + // Add edges until there is a shortest path between `0` and `size - 1` + do { + addRandomEdge(); + result = resultForGraph(); + } while (result == null); + + expect(result, [313, 547, 91, 481, 74, 64, 439, 388, 660, 275, 999]); + + var count = 0; + // Add edges until the shortest path between `0` and `size - 1` is 2 items + // Adding edges should never increase the length of the shortest path. + // Adding enough edges should reduce the length of the shortest path. + do { + expect(++count, lessThan(size * 5), reason: 'This loop should finish.'); + addRandomEdge(); + final previousResultLength = result!.length; + result = resultForGraph(); + expect(result, hasLength(lessThanOrEqualTo(previousResultLength))); + } while (result!.length > 2); + + expect(result, [275, 999]); + + count = 0; + // Remove edges until there is no shortest path. + // Removing edges should never reduce the length of the shortest path. + // Removing enough edges should increase the length of the shortest path and + // eventually eliminate any path. + do { + expect(++count, lessThan(size * 5), reason: 'This loop should finish.'); + final randomKey = graph.keys.elementAt(rnd.nextInt(graph.length)); + final list = graph[randomKey]!; + expect(list, isNotEmpty); + list.removeAt(rnd.nextInt(list.length)); + if (list.isEmpty) { + graph.remove(randomKey); + } + final previousResultLength = result!.length; + result = resultForGraph(); + if (result != null) { + expect(result, hasLength(greaterThanOrEqualTo(previousResultLength))); + } + } while (result != null); + }); +}
diff --git a/pkgs/graphs/test/strongly_connected_components_test.dart b/pkgs/graphs/test/strongly_connected_components_test.dart new file mode 100644 index 0000000..2fa4d88 --- /dev/null +++ b/pkgs/graphs/test/strongly_connected_components_test.dart
@@ -0,0 +1,304 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:graphs/graphs.dart'; +import 'package:test/test.dart'; + +import 'utils/graph.dart'; +import 'utils/utils.dart'; + +void main() { + group('strongly connected components', () { + /// Run [stronglyConnectedComponents] on [g]. + List<List<String>> components( + Map<String, List<String>?> g, { + Iterable<String>? startNodes, + }) { + final graph = Graph(g); + return stronglyConnectedComponents( + startNodes ?? graph.allNodes, + graph.edges, + ); + } + + test('empty result for empty graph', () { + final result = components({}); + expect(result, isEmpty); + }); + + test('single item for single node', () { + final result = components({'a': []}); + expect(result, [ + ['a'], + ]); + }); + + test('handles non-cycles', () { + final result = components({ + 'a': ['b'], + 'b': ['c'], + 'c': [], + }); + expect(result, [ + ['c'], + ['b'], + ['a'], + ]); + }); + + test('handles entire graph as cycle', () { + final result = components({ + 'a': ['b'], + 'b': ['c'], + 'c': ['d'], + 'd': ['a'], + }); + expect( + result, + [allOf(contains('a'), contains('b'), contains('c'), contains('d'))], + ); + }); + + test('includes the first passed root last in a cycle', () { + // In cases where this is used to find a topological ordering the first + // value in nodes should always come last. + final graph = { + 'a': ['b'], + 'b': ['a'], + }; + final resultFromA = components(graph, startNodes: ['a']); + final resultFromB = components(graph, startNodes: ['b']); + expect(resultFromA.single.last, 'a'); + expect(resultFromB.single.last, 'b'); + }); + + test('handles cycles in the middle', () { + final result = components({ + 'a': ['b', 'c'], + 'b': ['c', 'd'], + 'c': ['b', 'd'], + 'd': [], + }); + expect(result, [ + ['d'], + allOf(contains('b'), contains('c')), + ['a'], + ]); + }); + + test('handles self cycles', () { + final result = components({ + 'a': ['b'], + 'b': ['b'], + }); + expect(result, [ + ['b'], + ['a'], + ]); + }); + + test('valid topological ordering for disjoint subgraphs', () { + final result = components({ + 'a': ['b', 'c'], + 'b': ['b1', 'b2'], + 'c': ['c1', 'c2'], + 'b1': [], + 'b2': [], + 'c1': [], + 'c2': [], + }); + + expect( + result, + containsAllInOrder([ + ['c1'], + ['c'], + ['a'], + ]), + ); + expect( + result, + containsAllInOrder([ + ['c2'], + ['c'], + ['a'], + ]), + ); + expect( + result, + containsAllInOrder([ + ['b1'], + ['b'], + ['a'], + ]), + ); + expect( + result, + containsAllInOrder([ + ['b2'], + ['b'], + ['a'], + ]), + ); + }); + + test('handles getting null for edges', () { + final result = components({ + 'a': ['b'], + 'b': null, + }); + expect(result, [ + ['b'], + ['a'], + ]); + }); + }); + + group('custom hashCode and equals', () { + /// Run [stronglyConnectedComponents] on [g]. + List<List<String>> components( + Map<String, List<String>?> g, { + Iterable<String>? startNodes, + }) { + final graph = BadGraph(g); + + startNodes ??= graph.allNodes.map((n) => n.value); + + return stronglyConnectedComponents<X>( + startNodes.map(X.new), + graph.edges, + equals: xEquals, + hashCode: xHashCode, + ).map((list) => list.map((x) => x.value).toList()).toList(); + } + + test('empty result for empty graph', () { + final result = components({}); + expect(result, isEmpty); + }); + + test('single item for single node', () { + final result = components({'a': []}); + expect(result, [ + ['a'], + ]); + }); + + test('handles non-cycles', () { + final result = components({ + 'a': ['b'], + 'b': ['c'], + 'c': [], + }); + expect(result, [ + ['c'], + ['b'], + ['a'], + ]); + }); + + test('handles entire graph as cycle', () { + final result = components({ + 'a': ['b'], + 'b': ['c'], + 'c': ['a'], + }); + expect(result, [allOf(contains('a'), contains('b'), contains('c'))]); + }); + + test('includes the first passed root last in a cycle', () { + // In cases where this is used to find a topological ordering the first + // value in nodes should always come last. + final graph = { + 'a': ['b'], + 'b': ['a'], + }; + final resultFromA = components(graph, startNodes: ['a']); + final resultFromB = components(graph, startNodes: ['b']); + expect(resultFromA.single.last, 'a'); + expect(resultFromB.single.last, 'b'); + }); + + test('handles cycles in the middle', () { + final result = components({ + 'a': ['b', 'c'], + 'b': ['c', 'd'], + 'c': ['b', 'd'], + 'd': [], + }); + expect(result, [ + ['d'], + allOf(contains('b'), contains('c')), + ['a'], + ]); + }); + + test('handles self cycles', () { + final result = components({ + 'a': ['b'], + 'b': ['b'], + }); + expect(result, [ + ['b'], + ['a'], + ]); + }); + + test('valid topological ordering for disjoint subgraphs', () { + final result = components({ + 'a': ['b', 'c'], + 'b': ['b1', 'b2'], + 'c': ['c1', 'c2'], + 'b1': [], + 'b2': [], + 'c1': [], + 'c2': [], + }); + + expect( + result, + containsAllInOrder([ + ['c1'], + ['c'], + ['a'], + ]), + ); + expect( + result, + containsAllInOrder([ + ['c2'], + ['c'], + ['a'], + ]), + ); + expect( + result, + containsAllInOrder([ + ['b1'], + ['b'], + ['a'], + ]), + ); + expect( + result, + containsAllInOrder([ + ['b2'], + ['b'], + ['a'], + ]), + ); + }); + + test('handles getting null for edges', () { + final result = components({ + 'a': ['b'], + 'b': null, + }); + expect(result, [ + ['b'], + ['a'], + ]); + }); + }); +}
diff --git a/pkgs/graphs/test/topological_sort_test.dart b/pkgs/graphs/test/topological_sort_test.dart new file mode 100644 index 0000000..831946b --- /dev/null +++ b/pkgs/graphs/test/topological_sort_test.dart
@@ -0,0 +1,362 @@ +// Copyright (c) 2018, 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:collection'; + +import 'package:graphs/graphs.dart'; +import 'package:test/test.dart'; + +import 'utils/utils.dart'; + +void main() { + group('without secondarySort', () { + group('topologically sorts a graph', () { + test('with no nodes', () { + expect(_topologicalSort({}), isEmpty); + }); + + test('with only one node', () { + expect(_topologicalSort({1: []}), equals([1])); + }); + + test('with no edges', () { + expect( + _topologicalSort({1: [], 2: [], 3: [], 4: []}), + unorderedEquals([1, 2, 3, 4]), + ); + }); + + test('with single edges', () { + expect( + _topologicalSort({ + 1: [2], + 2: [3], + 3: [4], + 4: [], + }), + equals([1, 2, 3, 4]), + ); + }); + + test('with many edges from one node', () { + final result = _topologicalSort({ + 1: [2, 3, 4], + 2: [], + 3: [], + 4: [], + }); + expect(result.indexOf(1), lessThan(result.indexOf(2))); + expect(result.indexOf(1), lessThan(result.indexOf(3))); + expect(result.indexOf(1), lessThan(result.indexOf(4))); + }); + + test('with transitive edges', () { + final result = _topologicalSort({ + 1: [2, 4], + 2: [], + 3: [], + 4: [3], + }); + expect(result.indexOf(1), lessThan(result.indexOf(2))); + expect(result.indexOf(1), lessThan(result.indexOf(3))); + expect(result.indexOf(1), lessThan(result.indexOf(4))); + expect(result.indexOf(4), lessThan(result.indexOf(3))); + }); + + test('with diamond edges', () { + final result = _topologicalSort({ + 1: [2, 3], + 2: [4], + 3: [4], + 4: [], + }); + expect(result.indexOf(1), lessThan(result.indexOf(2))); + expect(result.indexOf(1), lessThan(result.indexOf(3))); + expect(result.indexOf(1), lessThan(result.indexOf(4))); + expect(result.indexOf(2), lessThan(result.indexOf(4))); + expect(result.indexOf(3), lessThan(result.indexOf(4))); + }); + }); + + test('respects custom equality and hash functions', () { + expect( + _topologicalSort<int>( + { + 0: [2], + 3: [4], + 5: [6], + 7: [], + }, + equals: (i, j) => (i ~/ 2) == (j ~/ 2), + hashCode: (i) => (i ~/ 2).hashCode, + ), + equals([ + 0, + anyOf([2, 3]), + anyOf([4, 5]), + anyOf([6, 7]), + ]), + ); + }); + + group('throws a CycleException for a graph with', () { + test('a one-node cycle', () { + expect( + () => _topologicalSort({ + 1: [1], + }), + throwsCycleException([1]), + ); + }); + + test('a multi-node cycle', () { + expect( + () => _topologicalSort({ + 1: [2], + 2: [3], + 3: [4], + 4: [1], + }), + throwsCycleException([4, 1, 2, 3]), + ); + }); + }); + }); + + group('with secondarySort', () { + group('topologically sorts a graph', () { + test('with no nodes', () { + expect(_topologicalSort({}, secondarySort: true), isEmpty); + }); + + test('with only one node', () { + expect(_topologicalSort({1: []}, secondarySort: true), equals([1])); + }); + + test('with no edges', () { + expect( + _topologicalSort({1: [], 2: [], 3: [], 4: []}, secondarySort: true), + unorderedEquals([1, 2, 3, 4]), + ); + }); + + test('with single edges', () { + expect( + _topologicalSort( + { + 1: [2], + 2: [3], + 3: [4], + 4: [], + }, + secondarySort: true, + ), + equals([1, 2, 3, 4]), + ); + }); + + test('with many edges from one node', () { + final result = _topologicalSort( + { + 1: [2, 3, 4], + 2: [], + 3: [], + 4: [], + }, + secondarySort: true, + ); + expect(result.indexOf(1), lessThan(result.indexOf(2))); + expect(result.indexOf(1), lessThan(result.indexOf(3))); + expect(result.indexOf(1), lessThan(result.indexOf(4))); + }); + + test('with transitive edges', () { + final result = _topologicalSort( + { + 1: [2, 4], + 2: [], + 3: [], + 4: [3], + }, + secondarySort: true, + ); + expect(result.indexOf(1), lessThan(result.indexOf(2))); + expect(result.indexOf(1), lessThan(result.indexOf(3))); + expect(result.indexOf(1), lessThan(result.indexOf(4))); + expect(result.indexOf(4), lessThan(result.indexOf(3))); + }); + + test('with diamond edges', () { + final result = _topologicalSort( + { + 1: [2, 3], + 2: [4], + 3: [4], + 4: [], + }, + secondarySort: true, + ); + expect(result.indexOf(1), lessThan(result.indexOf(2))); + expect(result.indexOf(1), lessThan(result.indexOf(3))); + expect(result.indexOf(1), lessThan(result.indexOf(4))); + expect(result.indexOf(2), lessThan(result.indexOf(4))); + expect(result.indexOf(3), lessThan(result.indexOf(4))); + }); + }); + + group('lexically sorts a graph where possible', () { + test('with no edges', () { + final result = + _topologicalSort({4: [], 3: [], 1: [], 2: []}, secondarySort: true); + expect(result, equals([1, 2, 3, 4])); + }); + + test('with one non-lexical edge', () { + final result = _topologicalSort( + { + 4: [], + 3: [1], + 1: [], + 2: [], + }, + secondarySort: true, + ); + expect( + result, + equals( + anyOf([ + [2, 3, 1, 4], + [3, 1, 2, 4], + ]), + ), + ); + }); + + test('with a non-lexical topolgical order', () { + final result = _topologicalSort( + { + 4: [3], + 3: [2], + 2: [1], + 1: [], + }, + secondarySort: true, + ); + expect(result, equals([4, 3, 2, 1])); + }); + + group('with multiple layers', () { + test('in lexical order', () { + final result = _topologicalSort( + { + 1: [2], + 2: [3], + 3: [], + 4: [5], + 5: [6], + 6: [], + }, + secondarySort: true, + ); + expect(result, equals([1, 2, 3, 4, 5, 6])); + }); + + test('in non-lexical order', () { + final result = _topologicalSort( + { + 1: [3], + 3: [5], + 4: [2], + 2: [6], + 5: [], + 6: [], + }, + secondarySort: true, + ); + expect( + result, + anyOf([ + equals([1, 3, 4, 2, 5, 6]), + equals([1, 4, 2, 3, 5, 6]), + ]), + ); + }); + }); + }); + + test('respects custom equality and hash functions', () { + expect( + _topologicalSort<int>( + { + 0: [2], + 3: [4], + 5: [6], + 7: [], + }, + equals: (i, j) => (i ~/ 2) == (j ~/ 2), + hashCode: (i) => (i ~/ 2).hashCode, + secondarySort: true, + ), + equals([ + 0, + anyOf([2, 3]), + anyOf([4, 5]), + anyOf([6, 7]), + ]), + ); + }); + + group('throws a CycleException for a graph with', () { + test('a one-node cycle', () { + expect( + () => _topologicalSort( + { + 1: [1], + }, + secondarySort: true, + ), + throwsCycleException([1]), + ); + }); + + test('a multi-node cycle', () { + expect( + () => _topologicalSort( + { + 1: [2], + 2: [3], + 3: [4], + 4: [1], + }, + secondarySort: true, + ), + throwsCycleException([4, 1, 2, 3]), + ); + }); + }); + }); +} + +/// Runs a topological sort on a graph represented a map from keys to edges. +List<T> _topologicalSort<T>( + Map<T, List<T>> graph, { + bool Function(T, T)? equals, + int Function(T)? hashCode, + bool secondarySort = false, +}) { + if (equals != null) { + graph = LinkedHashMap(equals: equals, hashCode: hashCode)..addAll(graph); + } + return topologicalSort( + graph.keys, + (node) { + expect(graph, contains(node)); + return graph[node]!; + }, + equals: equals, + hashCode: hashCode, + secondarySort: + secondarySort ? (a, b) => (a as Comparable<T>).compareTo(b) : null, + ); +}
diff --git a/pkgs/graphs/test/transitive_closure_test.dart b/pkgs/graphs/test/transitive_closure_test.dart new file mode 100644 index 0000000..f732573 --- /dev/null +++ b/pkgs/graphs/test/transitive_closure_test.dart
@@ -0,0 +1,350 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:collection'; + +import 'package:graphs/graphs.dart'; +import 'package:test/test.dart'; + +import 'utils/utils.dart'; + +void main() { + group('for an acyclic graph', () { + for (final acyclic in [true, false]) { + group('with acyclic: $acyclic', () { + group('returns the transitive closure for a graph', () { + test('with no nodes', () { + expect(_transitiveClosure<int>({}, acyclic: acyclic), isEmpty); + }); + + test('with only one node', () { + expect( + _transitiveClosure<int>({1: []}, acyclic: acyclic), + equals({1: <int>{}}), + ); + }); + + test('with no edges', () { + expect( + _transitiveClosure<int>( + {1: [], 2: [], 3: [], 4: []}, + acyclic: acyclic, + ), + equals(<int, Set<int>>{1: {}, 2: {}, 3: {}, 4: {}}), + ); + }); + + test('with single edges', () { + expect( + _transitiveClosure<int>( + { + 1: [2], + 2: [3], + 3: [4], + 4: [], + }, + acyclic: acyclic, + ), + equals({ + 1: {2, 3, 4}, + 2: {3, 4}, + 3: {4}, + 4: <int>{}, + }), + ); + }); + + test('with many edges from one node', () { + expect( + _transitiveClosure<int>( + { + 1: [2, 3, 4], + 2: [], + 3: [], + 4: [], + }, + acyclic: acyclic, + ), + equals(<int, Set<int>>{ + 1: {2, 3, 4}, + 2: {}, + 3: {}, + 4: {}, + }), + ); + }); + + test('with transitive edges', () { + expect( + _transitiveClosure<int>( + { + 1: [2, 4], + 2: [], + 3: [], + 4: [3], + }, + acyclic: acyclic, + ), + equals(<int, Set<int>>{ + 1: {2, 3, 4}, + 2: {}, + 3: {}, + 4: {3}, + }), + ); + }); + + test('with diamond edges', () { + expect( + _transitiveClosure<int>( + { + 1: [2, 3], + 2: [4], + 3: [4], + 4: [], + }, + acyclic: acyclic, + ), + equals(<int, Set<int>>{ + 1: {2, 3, 4}, + 2: {4}, + 3: {4}, + 4: {}, + }), + ); + }); + + test('with disjoint subgraphs', () { + expect( + _transitiveClosure<int>( + { + 1: [2], + 2: [3], + 3: [], + 4: [5], + 5: [6], + 6: [], + }, + acyclic: acyclic, + ), + equals(<int, Set<int>>{ + 1: {2, 3}, + 2: {3}, + 3: {}, + 4: {5, 6}, + 5: {6}, + 6: {}, + }), + ); + }); + }); + + test('respects custom equality and hash functions', () { + final result = _transitiveClosure<int>( + { + 0: [2], + 3: [4], + 5: [6], + 7: [], + }, + equals: (i, j) => (i ~/ 2) == (j ~/ 2), + hashCode: (i) => (i ~/ 2).hashCode, + ); + + expect( + result.keys, + unorderedMatches([ + 0, + anyOf([2, 3]), + anyOf([4, 5]), + anyOf([6, 7]), + ]), + ); + expect( + result[0], + equals({ + anyOf([2, 3]), + anyOf([4, 5]), + anyOf([6, 7]), + }), + ); + expect( + result[2], + equals({ + anyOf([4, 5]), + anyOf([6, 7]), + }), + ); + expect( + result[4], + equals({ + anyOf([6, 7]), + }), + ); + expect(result[6], isEmpty); + }); + }); + } + }); + + group('for a cyclic graph', () { + group('with acyclic: true throws a CycleException for a graph with', () { + test('a one-node cycle', () { + expect( + () => _transitiveClosure<int>( + { + 1: [1], + }, + acyclic: true, + ), + throwsCycleException([1]), + ); + }); + + test('a multi-node cycle', () { + expect( + () => _transitiveClosure<int>( + { + 1: [2], + 2: [3], + 3: [4], + 4: [1], + }, + acyclic: true, + ), + throwsCycleException([4, 1, 2, 3]), + ); + }); + }); + + group('returns the transitive closure for a graph', () { + test('with a single one-node component', () { + expect( + _transitiveClosure<int>({ + 1: [1], + }), + equals({ + 1: {1}, + }), + ); + }); + + test('with a single multi-node component', () { + expect( + _transitiveClosure<int>({ + 1: [2], + 2: [3], + 3: [4], + 4: [1], + }), + equals({ + 1: {1, 2, 3, 4}, + 2: {1, 2, 3, 4}, + 3: {1, 2, 3, 4}, + 4: {1, 2, 3, 4}, + }), + ); + }); + + test('with a series of multi-node components', () { + expect( + _transitiveClosure<int>({ + 1: [2], + 2: [1, 3], + 3: [4], + 4: [3, 5], + 5: [6], + 6: [5, 7], + 7: [8], + 8: [7], + }), + equals({ + 1: {1, 2, 3, 4, 5, 6, 7, 8}, + 2: {1, 2, 3, 4, 5, 6, 7, 8}, + 3: {3, 4, 5, 6, 7, 8}, + 4: {3, 4, 5, 6, 7, 8}, + 5: {5, 6, 7, 8}, + 6: {5, 6, 7, 8}, + 7: {7, 8}, + 8: {7, 8}, + }), + ); + }); + + test('with a diamond of multi-node components', () { + expect( + _transitiveClosure<int>({ + 1: [2], + 2: [1, 3, 5], + 3: [4], + 4: [3, 7], + 5: [6], + 6: [5, 7], + 7: [8], + 8: [7], + }), + equals({ + 1: {1, 2, 3, 4, 5, 6, 7, 8}, + 2: {1, 2, 3, 4, 5, 6, 7, 8}, + 3: {3, 4, 7, 8}, + 4: {3, 4, 7, 8}, + 5: {5, 6, 7, 8}, + 6: {5, 6, 7, 8}, + 7: {7, 8}, + 8: {7, 8}, + }), + ); + }); + + test('mixed single- and multi-node components', () { + expect( + _transitiveClosure<int>({ + 1: [2], + 2: [1, 3], + 3: [4], + 4: [5], + 5: [4, 6], + 6: [7], + 7: [8], + 8: [7], + }), + equals({ + 1: {1, 2, 3, 4, 5, 6, 7, 8}, + 2: {1, 2, 3, 4, 5, 6, 7, 8}, + 3: {4, 5, 6, 7, 8}, + 4: {4, 5, 6, 7, 8}, + 5: {4, 5, 6, 7, 8}, + 6: {7, 8}, + 7: {7, 8}, + 8: {7, 8}, + }), + ); + }); + }); + }); +} + +/// Returns the transitive closure of a graph represented a map from keys to +/// edges. +Map<T, Set<T>> _transitiveClosure<T extends Object>( + Map<T, List<T>> graph, { + bool Function(T, T)? equals, + int Function(T)? hashCode, + bool acyclic = false, +}) { + assert((equals == null) == (hashCode == null)); + if (equals != null) { + graph = LinkedHashMap(equals: equals, hashCode: hashCode)..addAll(graph); + } + return transitiveClosure( + graph.keys, + (node) { + expect(graph, contains(node)); + return graph[node]!; + }, + equals: equals, + hashCode: hashCode, + acyclic: acyclic, + ); +}
diff --git a/pkgs/graphs/test/utils/graph.dart b/pkgs/graphs/test/utils/graph.dart new file mode 100644 index 0000000..ffa24b5 --- /dev/null +++ b/pkgs/graphs/test/utils/graph.dart
@@ -0,0 +1,47 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:collection'; + +import 'utils.dart'; + +/// A representation of a Graph since none is specified in `lib/`. +class Graph { + final Map<String, List<String>?> _graph; + + Graph(this._graph); + + List<String> edges(String node) => _graph[node] ?? <Never>[]; + + Iterable<String> get allNodes => _graph.keys; +} + +class BadGraph { + final Map<X, List<X>?> _graph; + + BadGraph(Map<String, List<String>?> values) + : _graph = LinkedHashMap(equals: xEquals, hashCode: xHashCode) + ..addEntries( + values.entries + .map((e) => MapEntry(X(e.key), e.value?.map(X.new).toList())), + ); + + List<X> edges(X node) => _graph[node] ?? <Never>[]; + + Iterable<X> get allNodes => _graph.keys; +} + +/// A representation of a Graph where keys can asynchronously be resolved to +/// real values or to edges. +class AsyncGraph { + final Map<String, List<String>?> graph; + + AsyncGraph(this.graph); + + Future<String?> readNode(String node) async => + graph.containsKey(node) ? node : null; + + Future<Iterable<String>> edges(String key, String? node) async => + graph[key] ?? <Never>[]; +}
diff --git a/pkgs/graphs/test/utils/utils.dart b/pkgs/graphs/test/utils/utils.dart new file mode 100644 index 0000000..45a42c6 --- /dev/null +++ b/pkgs/graphs/test/utils/utils.dart
@@ -0,0 +1,37 @@ +// Copyright (c) 2018, 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:graphs/graphs.dart'; +import 'package:test/test.dart'; + +bool xEquals(X a, X b) => a.value == b.value; + +int xHashCode(X a) => a.value.hashCode; + +/// Returns a matcher that verifies that a function throws a [CycleException<T>] +/// with the given [cycle]. +Matcher throwsCycleException<T>(List<T> cycle) => throwsA( + allOf([ + isA<CycleException<T>>(), + predicate((exception) { + expect((exception as CycleException<T>).cycle, equals(cycle)); + return true; + }), + ]), + ); + +class X { + final String value; + + X(this.value); + + @override + bool operator ==(Object other) => throw UnimplementedError(); + + @override + int get hashCode => 42; + + @override + String toString() => '($value)'; +}
diff --git a/pkgs/mime/.gitignore b/pkgs/mime/.gitignore new file mode 100644 index 0000000..a433102 --- /dev/null +++ b/pkgs/mime/.gitignore
@@ -0,0 +1,5 @@ +.packages +.dart_tool/ +.pub/ +packages +pubspec.lock
diff --git a/pkgs/mime/AUTHORS b/pkgs/mime/AUTHORS new file mode 100644 index 0000000..e8063a8 --- /dev/null +++ b/pkgs/mime/AUTHORS
@@ -0,0 +1,6 @@ +# Below is a list of people and organizations that have contributed +# to the project. Names should be added to the list like so: +# +# Name/Organization <email address> + +Google Inc.
diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md new file mode 100644 index 0000000..fd5a249 --- /dev/null +++ b/pkgs/mime/CHANGELOG.md
@@ -0,0 +1,110 @@ +## 2.0.0 + +* **[Breaking]** `extensionFromMime(String mimeType)` returns `null` instead of `mimeType` for an unknown mime type. +* Update `extensionFromMime` to return a default extension when a MIME type maps to multiple extensions. + +## 1.0.6 + +* Add `topics` section to `pubspec.yaml`. +* Move to `dart-lang/tools` monorepo. + +## 1.0.5 + +* Update `video/mp4` mimeType lookup by header bytes. +* Add `image/heic` mimeType lookup by header bytes. +* Add `image/heif` mimeType lookup by header bytes. +* Add m4b mimeType lookup by extension. +* Add `text/markdown` mimeType lookup by extension. +* Require Dart 3.2.0. + +## 1.0.4 + +* Changed `.js` to `text/javascript` per + https://datatracker.ietf.org/doc/html/rfc9239. +* Added `.mjs` as `text/javascript`. +* Add `application/dicom` mimeType lookup by extension. +* Require Dart 2.18. + +## 1.0.3 + +* Add application/manifest+json lookup by extension. +* Add application/toml mimeType lookup by extension. +* Add audio/aac mimeType lookup by header bytes. +* Add audio/mpeg mimeType lookup by header bytes. +* Add audio/ogg mimeType lookup by header bytes. +* Add audio/weba mimeType lookup by header bytes. +* Add font/woff2 lookup by extension and header bytes. +* Add image/avif mimeType lookup by extension. +* Add image/heic mimeType lookup by extension. +* Add image/heif mimeType lookup by extension. +* Change audio/x-aac to audio/aac when detected by extension. + +## 1.0.2 + +* Add audio/x-aiff mimeType lookup by header bytes. +* Add audio/x-flac mimeType lookup by header bytes. +* Add audio/x-wav mimeType lookup by header bytes. +* Add audio/mp4 mimeType lookup by file path. + +## 1.0.1 + +* Add image/webp mimeType lookup by header bytes. + +## 1.0.0 + +* Stable null safety release. + +## 1.0.0-nullsafety.0 + +* Update to null safety. + +## 0.9.7 + +* Add `extensionFromMime` utility function. + +## 0.9.6+3 + +* Change the mime type for Dart source from `application/dart` to `text/x-dart`. +* Add example. +* Fix links and code in README. + +## 0.9.6+2 + +* Set max SDK version to `<3.0.0`, and adjust other dependencies. + +## 0.9.6+1 + +* Stop using deprecated constants from the SDK. + +## 0.9.6 + +* Updates to support Dart 2.0 core library changes (wave + 2.2). See [issue 31847][sdk#31847] for details. + + [sdk#31847]: https://github.com/dart-lang/sdk/issues/31847 + +## 0.9.5 + +* Add support for the WebAssembly format. + +## 0.9.4 + +* Updated Dart SDK requirement to `>= 1.8.3 <2.0.0` + +* Strong-mode clean. + +* Added support for glTF text and binary formats. + +## 0.9.3 + +* Fixed erroneous behavior for listening and when pausing/resuming + stream of parts. + +## 0.9.2 + +* Fixed erroneous behavior when pausing/canceling stream of parts but already + listened to one part. + +## 0.9.1 + +* Handle parsing of MIME multipart content with no parts.
diff --git a/pkgs/mime/CONTRIBUTING.md b/pkgs/mime/CONTRIBUTING.md new file mode 100644 index 0000000..463063a --- /dev/null +++ b/pkgs/mime/CONTRIBUTING.md
@@ -0,0 +1,37 @@ +Want to contribute? Great! First, read this page (including the small print at +the end). + +### Before you contribute +Before we can use your code, you must sign the +[Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual) +(CLA), which you can do online. The CLA is necessary mainly because you own the +copyright to your changes, even after your contribution becomes part of our +codebase, so we need your permission to use and distribute your code. We also +need to be sure of various other things—for instance that you'll tell us if you +know that your code infringes on other people's patents. You don't have to sign +the CLA until after you've submitted your code for review and a member has +approved it, but you must do it before we can put your code into our codebase. + +Before you start working on a larger contribution, you should get in touch with +us first through the issue tracker with your idea so that we can help out and +possibly guide you. Coordinating up front makes it much easier to avoid +frustration later on. + +### Code reviews +All submissions, including submissions by project members, require review. + +### File headers +All files in the project must start with the following header. + + // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file + // for details. All rights reserved. Use of this source code is governed by a + // BSD-style license that can be found in the LICENSE file. + +### The small print +Contributions made by corporations are covered by a different agreement than the +one above, the +[Software Grant and Corporate Contributor License Agreement](https://developers.google.com/open-source/cla/corporate). + +### Adding an extension / MIME type mapping +If a MIME type ends up with multiple extensions, it is recommended to define a +preferred extension in `_defaultMimeTypeMap` in [extension.dart](lib/src/extension.dart). \ No newline at end of file
diff --git a/pkgs/mime/LICENSE b/pkgs/mime/LICENSE new file mode 100644 index 0000000..dbd2843 --- /dev/null +++ b/pkgs/mime/LICENSE
@@ -0,0 +1,27 @@ +Copyright 2015, the Dart project authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google LLC nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/pkgs/mime/README.md b/pkgs/mime/README.md new file mode 100644 index 0000000..da06de6 --- /dev/null +++ b/pkgs/mime/README.md
@@ -0,0 +1,70 @@ +[](https://github.com/dart-lang/tools/actions/workflows/mime.yml) +[](https://pub.dev/packages/mime) +[](https://pub.dev/packages/mime/publisher) + +Package for working with MIME type definitions and for processing +streams of MIME multipart media types. + +## Determining the MIME type for a file + +The `MimeTypeResolver` class can be used to determine the MIME type of +a file. It supports both using the extension of the file name and +looking at magic bytes from the beginning of the file. + +There is a builtin instance of `MimeTypeResolver` accessible through +the top level function `lookupMimeType`. This builtin instance has +the most common file name extensions and magic bytes registered. + +```dart +import 'package:mime/mime.dart'; + +void main() { + print(lookupMimeType('test.html')); + // text/html + + print(lookupMimeType('test', headerBytes: [0xFF, 0xD8])); + // image/jpeg + + print(lookupMimeType('test.html', headerBytes: [0xFF, 0xD8])); + // image/jpeg +} +``` + +You can build you own resolver by creating an instance of +`MimeTypeResolver` and adding file name extensions and magic bytes +using `addExtension` and `addMagicNumber`. + +## Processing MIME multipart media types + +The class `MimeMultipartTransformer` is used to process a `Stream` of +bytes encoded using a MIME multipart media types encoding. The +transformer provides a new `Stream` of `MimeMultipart` objects each of +which have the headers and the content of each part. The content of a +part is provided as a stream of bytes. + +Below is an example showing how to process an HTTP request and print +the length of the content of each part. + +```dart +// HTTP request with content type multipart/form-data. +HttpRequest request = ...; +// Determine the boundary form the content type header +String boundary = request.headers.contentType.parameters['boundary']; + +// Process the body just calculating the length of each part. +request + .transform(new MimeMultipartTransformer(boundary)) + .map((part) => part.fold(0, (p, d) => p + d)) + .listen((length) => print('Part with length $length')); +``` + +## Determining file extension by MIME type + +The top level function `extensionFromMime` can be used to determine the +file extension of a given MIME type. + +```dart +print(extensionFromMime('text/html')); // Prints "html". +print(extensionFromMime('image/jpeg')); // Prints "jpg". +print(extensionFromMime('application/pdf')); // Prints "pdf". +```
diff --git a/pkgs/mime/analysis_options.yaml b/pkgs/mime/analysis_options.yaml new file mode 100644 index 0000000..44b61cf --- /dev/null +++ b/pkgs/mime/analysis_options.yaml
@@ -0,0 +1,34 @@ +# https://dart.dev/tools/analysis#the-analysis-options-file +include: package:dart_flutter_team_lints/analysis_options.yaml + +analyzer: + language: + strict-casts: true + strict-inference: true + strict-raw-types: true + +linter: + rules: + - avoid_bool_literals_in_conditional_expressions + - avoid_classes_with_only_static_members + - avoid_private_typedef_functions + - avoid_redundant_argument_values + - avoid_returning_this + - avoid_unused_constructor_parameters + - avoid_void_async + - cancel_subscriptions + - join_return_with_assignment + - literal_only_boolean_expressions + - missing_whitespace_between_adjacent_strings + - no_adjacent_strings_in_list + - no_runtimeType_toString + - package_api_docs + - prefer_const_declarations + - prefer_expression_function_bodies + - prefer_final_locals + - unnecessary_await_in_return + - unnecessary_breaks + - unnecessary_raw_strings + - use_if_null_to_convert_nulls_to_bools + - use_raw_strings + - use_string_buffers
diff --git a/pkgs/mime/example/example.dart b/pkgs/mime/example/example.dart new file mode 100644 index 0000000..b54f8e7 --- /dev/null +++ b/pkgs/mime/example/example.dart
@@ -0,0 +1,16 @@ +// 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 'package:mime/mime.dart'; + +void main() { + print(lookupMimeType('test.html')); + // text/html + + print(lookupMimeType('test', headerBytes: [0xFF, 0xD8])); + // image/jpeg + + print(lookupMimeType('test.html', headerBytes: [0xFF, 0xD8])); + // image/jpeg +}
diff --git a/pkgs/mime/lib/mime.dart b/pkgs/mime/lib/mime.dart new file mode 100644 index 0000000..cb45098 --- /dev/null +++ b/pkgs/mime/lib/mime.dart
@@ -0,0 +1,15 @@ +// Copyright (c) 2013, 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. + +/// Help for working with file format identifiers +/// such as `text/html` and `image/png`. +/// +/// More details, including a list of types, are in the Wikipedia article +/// [Internet media type](http://en.wikipedia.org/wiki/Internet_media_type). +library; + +export 'src/extension.dart'; +export 'src/mime_multipart_transformer.dart'; +export 'src/mime_shared.dart'; +export 'src/mime_type.dart';
diff --git a/pkgs/mime/lib/src/bound_multipart_stream.dart b/pkgs/mime/lib/src/bound_multipart_stream.dart new file mode 100644 index 0000000..03b213b --- /dev/null +++ b/pkgs/mime/lib/src/bound_multipart_stream.dart
@@ -0,0 +1,372 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:convert'; + +import 'char_code.dart' as char_code; +import 'mime_shared.dart'; + +/// Bytes for `()<>@,;:\\"/[]?={} \t`. +const _separators = { + 40, 41, 60, 62, 64, 44, 59, 58, 92, 34, 47, 91, 93, 63, 61, 123, 125, 32, 9 // +}; + +bool _isTokenChar(int byte) => + byte > 31 && byte < 128 && !_separators.contains(byte); + +int _toLowerCase(int byte) { + const delta = char_code.lowerA - char_code.upperA; + return (char_code.upperA <= byte && byte <= char_code.upperZ) + ? byte + delta + : byte; +} + +void _expectByteValue(int val1, int val2) { + if (val1 != val2) { + throw const MimeMultipartException('Failed to parse multipart mime 1'); + } +} + +void _expectWhitespace(int byte) { + if (byte != char_code.sp && byte != char_code.ht) { + throw const MimeMultipartException('Failed to parse multipart mime 2'); + } +} + +class _MimeMultipart extends MimeMultipart { + @override + final Map<String, String> headers; + final Stream<List<int>> _stream; + + _MimeMultipart(this.headers, this._stream); + + @override + StreamSubscription<List<int>> listen( + void Function(List<int> data)? onData, { + void Function()? onDone, + Function? onError, + bool? cancelOnError, + }) => + _stream.listen( + onData, + onDone: onDone, + onError: onError, + cancelOnError: cancelOnError, + ); +} + +class BoundMultipartStream { + static const int _startCode = 0; + static const int _boundaryEndingCode = 1; + static const int _boundaryEndCode = 2; + static const int _headerStartCode = 3; + static const int _headerFieldCode = 4; + static const int _headerValueStartCode = 5; + static const int _headerValueCode = 6; + static const int _headerValueFoldingOrEndingCode = 7; + static const int _headerValueFoldOrEndCode = 8; + static const int _headerEndingCode = 9; + static const int _contentCode = 10; + static const int _lastBoundaryDash2Code = 11; + static const int _lastBoundaryEndingCode = 12; + static const int _lastBoundaryEndCode = 13; + static const int _doneCode = 14; + static const int _failCode = 15; + + final List<int> _boundary; + final List<int> _headerField = []; + final List<int> _headerValue = []; + + // The following states belong to `_controller`, state changes will not be + // immediately acted upon but rather only after the current + // `_multipartController` is done. + static const int _controllerStateIdle = 0; + static const int _controllerStateActive = 1; + static const int _controllerStatePaused = 2; + static const int _controllerStateCanceled = 3; + + int _controllerState = _controllerStateIdle; + + final _controller = StreamController<MimeMultipart>(sync: true); + + Stream<MimeMultipart> get stream => _controller.stream; + + late StreamSubscription<void> _subscription; + + StreamController<List<int>>? _multipartController; + Map<String, String>? _headers; + + int _state = _startCode; + int _boundaryIndex = 2; + + /// Current index into [_buffer]. + /// + /// If index is negative then it is the index into the artificial prefix of + /// the boundary string. + int _index = 0; + List<int> _buffer = _placeholderBuffer; + + BoundMultipartStream(this._boundary, Stream<List<int>> stream) { + _controller + ..onPause = _pauseStream + ..onResume = _resumeStream + ..onCancel = () { + _controllerState = _controllerStateCanceled; + _tryPropagateControllerState(); + } + ..onListen = () { + _controllerState = _controllerStateActive; + _subscription = stream.listen((data) { + assert(_buffer == _placeholderBuffer); + _subscription.pause(); + _buffer = data; + _index = 0; + _parse(); + }, onDone: () { + if (_state != _doneCode) { + _controller + .addError(const MimeMultipartException('Bad multipart ending')); + } + _controller.close(); + }, onError: _controller.addError); + }; + } + + void _resumeStream() { + assert(_controllerState == _controllerStatePaused); + _controllerState = _controllerStateActive; + _tryPropagateControllerState(); + } + + void _pauseStream() { + _controllerState = _controllerStatePaused; + _tryPropagateControllerState(); + } + + void _tryPropagateControllerState() { + if (_multipartController == null) { + switch (_controllerState) { + case _controllerStateActive: + if (_subscription.isPaused) _subscription.resume(); + case _controllerStatePaused: + if (!_subscription.isPaused) _subscription.pause(); + case _controllerStateCanceled: + _subscription.cancel(); + default: + throw StateError('This code should never be reached.'); + } + } + } + + void _parse() { + // Number of boundary bytes to artificially place before the supplied data. + // The data to parse might be 'artificially' prefixed with a + // partial match of the boundary. + final boundaryPrefix = _boundaryIndex; + // Position where content starts. Will be null if no known content + // start exists. Will be negative of the content starts in the + // boundary prefix. Will be zero or position if the content starts + // in the current buffer. + var contentStartIndex = + _state == _contentCode && _boundaryIndex == 0 ? 0 : null; + + // Function to report content data for the current part. The data + // reported is from the current content start index up til the + // current index. As the data can be artificially prefixed with a + // prefix of the boundary both the content start index and index + // can be negative. + void reportData() { + if (contentStartIndex! < 0) { + final contentLength = boundaryPrefix + _index - _boundaryIndex; + if (contentLength <= boundaryPrefix) { + _multipartController!.add(_boundary.sublist(0, contentLength)); + } else { + _multipartController!.add(_boundary.sublist(0, boundaryPrefix)); + _multipartController! + .add(_buffer.sublist(0, contentLength - boundaryPrefix)); + } + } else { + final contentEndIndex = _index - _boundaryIndex; + _multipartController! + .add(_buffer.sublist(contentStartIndex, contentEndIndex)); + } + } + + while ( + _index < _buffer.length && _state != _failCode && _state != _doneCode) { + final byte = + _index < 0 ? _boundary[boundaryPrefix + _index] : _buffer[_index]; + switch (_state) { + case _startCode: + if (byte == _boundary[_boundaryIndex]) { + _boundaryIndex++; + if (_boundaryIndex == _boundary.length) { + _state = _boundaryEndingCode; + _boundaryIndex = 0; + } + } else { + // Restart matching of the boundary. + _index = _index - _boundaryIndex; + _boundaryIndex = 0; + } + + case _boundaryEndingCode: + if (byte == char_code.cr) { + _state = _boundaryEndCode; + } else if (byte == char_code.dash) { + _state = _lastBoundaryDash2Code; + } else { + _expectWhitespace(byte); + } + + case _boundaryEndCode: + _expectByteValue(byte, char_code.lf); + _multipartController?.close(); + if (_multipartController != null) { + _multipartController = null; + _tryPropagateControllerState(); + } + _state = _headerStartCode; + + case _headerStartCode: + _headers = <String, String>{}; + if (byte == char_code.cr) { + _state = _headerEndingCode; + } else { + // Start of new header field. + _headerField.add(_toLowerCase(byte)); + _state = _headerFieldCode; + } + + case _headerFieldCode: + if (byte == char_code.colon) { + _state = _headerValueStartCode; + } else { + if (!_isTokenChar(byte)) { + throw const MimeMultipartException('Invalid header field name'); + } + _headerField.add(_toLowerCase(byte)); + } + + case _headerValueStartCode: + if (byte == char_code.cr) { + _state = _headerValueFoldingOrEndingCode; + } else if (byte != char_code.sp && byte != char_code.ht) { + // Start of new header value. + _headerValue.add(byte); + _state = _headerValueCode; + } + + case _headerValueCode: + if (byte == char_code.cr) { + _state = _headerValueFoldingOrEndingCode; + } else { + _headerValue.add(byte); + } + + case _headerValueFoldingOrEndingCode: + _expectByteValue(byte, char_code.lf); + _state = _headerValueFoldOrEndCode; + + case _headerValueFoldOrEndCode: + if (byte == char_code.sp || byte == char_code.ht) { + _state = _headerValueStartCode; + } else { + final headerField = utf8.decode(_headerField); + final headerValue = utf8.decode(_headerValue); + _headers![headerField.toLowerCase()] = headerValue; + _headerField.clear(); + _headerValue.clear(); + if (byte == char_code.cr) { + _state = _headerEndingCode; + } else { + // Start of new header field. + _headerField.add(_toLowerCase(byte)); + _state = _headerFieldCode; + } + } + + case _headerEndingCode: + _expectByteValue(byte, char_code.lf); + _multipartController = StreamController( + sync: true, + onListen: () { + if (_subscription.isPaused) _subscription.resume(); + }, + onPause: _subscription.pause, + onResume: _subscription.resume); + _controller + .add(_MimeMultipart(_headers!, _multipartController!.stream)); + _headers = null; + _state = _contentCode; + contentStartIndex = _index + 1; + + case _contentCode: + if (byte == _boundary[_boundaryIndex]) { + _boundaryIndex++; + if (_boundaryIndex == _boundary.length) { + if (contentStartIndex != null) { + _index++; + reportData(); + _index--; + } + _multipartController!.close(); + _multipartController = null; + _tryPropagateControllerState(); + _boundaryIndex = 0; + _state = _boundaryEndingCode; + } + } else { + // Restart matching of the boundary. + _index = _index - _boundaryIndex; + contentStartIndex ??= _index; + _boundaryIndex = 0; + } + + case _lastBoundaryDash2Code: + _expectByteValue(byte, char_code.dash); + _state = _lastBoundaryEndingCode; + + case _lastBoundaryEndingCode: + if (byte == char_code.cr) { + _state = _lastBoundaryEndCode; + } else { + _expectWhitespace(byte); + } + + case _lastBoundaryEndCode: + _expectByteValue(byte, char_code.lf); + _multipartController?.close(); + if (_multipartController != null) { + _multipartController = null; + _tryPropagateControllerState(); + } + _state = _doneCode; + + default: + // Should be unreachable. + assert(false); + } + + // Move to the next byte. + _index++; + } + + // Report any known content. + if (_state == _contentCode && contentStartIndex != null) { + reportData(); + } + + // Resume if at end. + if (_index == _buffer.length) { + _buffer = _placeholderBuffer; + _index = 0; + _subscription.resume(); + } + } +} + +// Used as a placeholder instead of having a nullable buffer. +const _placeholderBuffer = <int>[];
diff --git a/pkgs/mime/lib/src/char_code.dart b/pkgs/mime/lib/src/char_code.dart new file mode 100644 index 0000000..4cca1b1 --- /dev/null +++ b/pkgs/mime/lib/src/char_code.dart
@@ -0,0 +1,13 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +const int ht = 9; +const int lf = 10; +const int cr = 13; +const int sp = 32; +const int dash = 45; +const int colon = 58; +const int upperA = 65; +const int upperZ = 90; +const int lowerA = 97;
diff --git a/pkgs/mime/lib/src/default_extension_map.dart b/pkgs/mime/lib/src/default_extension_map.dart new file mode 100644 index 0000000..287c957 --- /dev/null +++ b/pkgs/mime/lib/src/default_extension_map.dart
@@ -0,0 +1,1012 @@ +// Copyright (c) 2013, 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. + +const Map<String, String> defaultExtensionMap = <String, String>{ + '123': 'application/vnd.lotus-1-2-3', + '3dml': 'text/vnd.in3d.3dml', + '3ds': 'image/x-3ds', + '3g2': 'video/3gpp2', + '3gp': 'video/3gpp', + '7z': 'application/x-7z-compressed', + 'aab': 'application/x-authorware-bin', + 'aac': 'audio/aac', + 'aam': 'application/x-authorware-map', + 'aas': 'application/x-authorware-seg', + 'abw': 'application/x-abiword', + 'ac': 'application/pkix-attr-cert', + 'acc': 'application/vnd.americandynamics.acc', + 'ace': 'application/x-ace-compressed', + 'acu': 'application/vnd.acucobol', + 'acutc': 'application/vnd.acucorp', + 'adp': 'audio/adpcm', + 'aep': 'application/vnd.audiograph', + 'afm': 'application/x-font-type1', + 'afp': 'application/vnd.ibm.modcap', + 'ahead': 'application/vnd.ahead.space', + 'ai': 'application/postscript', + 'aif': 'audio/x-aiff', + 'aifc': 'audio/x-aiff', + 'aiff': 'audio/x-aiff', + 'air': 'application/vnd.adobe.air-application-installer-package+zip', + 'ait': 'application/vnd.dvb.ait', + 'ami': 'application/vnd.amiga.ami', + 'apk': 'application/vnd.android.package-archive', + 'appcache': 'text/cache-manifest', + 'application': 'application/x-ms-application', + 'apr': 'application/vnd.lotus-approach', + 'arc': 'application/x-freearc', + 'asc': 'application/pgp-signature', + 'asf': 'video/x-ms-asf', + 'asm': 'text/x-asm', + 'aso': 'application/vnd.accpac.simply.aso', + 'asx': 'video/x-ms-asf', + 'atc': 'application/vnd.acucorp', + 'atom': 'application/atom+xml', + 'atomcat': 'application/atomcat+xml', + 'atomsvc': 'application/atomsvc+xml', + 'atx': 'application/vnd.antix.game-component', + 'au': 'audio/basic', + 'avi': 'video/x-msvideo', + 'avif': 'image/avif', + 'aw': 'application/applixware', + 'azf': 'application/vnd.airzip.filesecure.azf', + 'azs': 'application/vnd.airzip.filesecure.azs', + 'azw': 'application/vnd.amazon.ebook', + 'bat': 'application/x-msdownload', + 'bcpio': 'application/x-bcpio', + 'bdf': 'application/x-font-bdf', + 'bdm': 'application/vnd.syncml.dm+wbxml', + 'bed': 'application/vnd.realvnc.bed', + 'bh2': 'application/vnd.fujitsu.oasysprs', + 'bin': 'application/octet-stream', + 'blb': 'application/x-blorb', + 'blorb': 'application/x-blorb', + 'bmi': 'application/vnd.bmi', + 'bmp': 'image/bmp', + 'book': 'application/vnd.framemaker', + 'box': 'application/vnd.previewsystems.box', + 'boz': 'application/x-bzip2', + 'bpk': 'application/octet-stream', + 'btif': 'image/prs.btif', + 'bz': 'application/x-bzip', + 'bz2': 'application/x-bzip2', + 'c': 'text/x-c', + 'c11amc': 'application/vnd.cluetrust.cartomobile-config', + 'c11amz': 'application/vnd.cluetrust.cartomobile-config-pkg', + 'c4d': 'application/vnd.clonk.c4group', + 'c4f': 'application/vnd.clonk.c4group', + 'c4g': 'application/vnd.clonk.c4group', + 'c4p': 'application/vnd.clonk.c4group', + 'c4u': 'application/vnd.clonk.c4group', + 'cab': 'application/vnd.ms-cab-compressed', + 'caf': 'audio/x-caf', + 'cap': 'application/vnd.tcpdump.pcap', + 'car': 'application/vnd.curl.car', + 'cat': 'application/vnd.ms-pki.seccat', + 'cb7': 'application/x-cbr', + 'cba': 'application/x-cbr', + 'cbr': 'application/x-cbr', + 'cbt': 'application/x-cbr', + 'cbz': 'application/x-cbr', + 'cc': 'text/x-c', + 'cct': 'application/x-director', + 'ccxml': 'application/ccxml+xml', + 'cdbcmsg': 'application/vnd.contact.cmsg', + 'cdf': 'application/x-netcdf', + 'cdkey': 'application/vnd.mediastation.cdkey', + 'cdmia': 'application/cdmi-capability', + 'cdmic': 'application/cdmi-container', + 'cdmid': 'application/cdmi-domain', + 'cdmio': 'application/cdmi-object', + 'cdmiq': 'application/cdmi-queue', + 'cdx': 'chemical/x-cdx', + 'cdxml': 'application/vnd.chemdraw+xml', + 'cdy': 'application/vnd.cinderella', + 'cer': 'application/pkix-cert', + 'cfs': 'application/x-cfs-compressed', + 'cgm': 'image/cgm', + 'chat': 'application/x-chat', + 'chm': 'application/vnd.ms-htmlhelp', + 'chrt': 'application/vnd.kde.kchart', + 'cif': 'chemical/x-cif', + 'cii': 'application/vnd.anser-web-certificate-issue-initiation', + 'cil': 'application/vnd.ms-artgalry', + 'cla': 'application/vnd.claymore', + 'class': 'application/java-vm', + 'clkk': 'application/vnd.crick.clicker.keyboard', + 'clkp': 'application/vnd.crick.clicker.palette', + 'clkt': 'application/vnd.crick.clicker.template', + 'clkw': 'application/vnd.crick.clicker.wordbank', + 'clkx': 'application/vnd.crick.clicker', + 'clp': 'application/x-msclip', + 'cmc': 'application/vnd.cosmocaller', + 'cmdf': 'chemical/x-cmdf', + 'cml': 'chemical/x-cml', + 'cmp': 'application/vnd.yellowriver-custom-menu', + 'cmx': 'image/x-cmx', + 'cod': 'application/vnd.rim.cod', + 'com': 'application/x-msdownload', + 'conf': 'text/plain', + 'cpio': 'application/x-cpio', + 'cpp': 'text/x-c', + 'cpt': 'application/mac-compactpro', + 'crd': 'application/x-mscardfile', + 'crl': 'application/pkix-crl', + 'crt': 'application/x-x509-ca-cert', + 'cryptonote': 'application/vnd.rig.cryptonote', + 'csh': 'application/x-csh', + 'csml': 'chemical/x-csml', + 'csp': 'application/vnd.commonspace', + 'css': 'text/css', + 'cst': 'application/x-director', + 'csv': 'text/csv', + 'cu': 'application/cu-seeme', + 'curl': 'text/vnd.curl', + 'cww': 'application/prs.cww', + 'cxt': 'application/x-director', + 'cxx': 'text/x-c', + 'dae': 'model/vnd.collada+xml', + 'daf': 'application/vnd.mobius.daf', + 'dart': 'text/x-dart', + 'dataless': 'application/vnd.fdsn.seed', + 'davmount': 'application/davmount+xml', + 'dbk': 'application/docbook+xml', + 'dcm': 'application/dicom', + 'dcr': 'application/x-director', + 'dcurl': 'text/vnd.curl.dcurl', + 'dd2': 'application/vnd.oma.dd2+xml', + 'ddd': 'application/vnd.fujixerox.ddd', + 'deb': 'application/x-debian-package', + 'def': 'text/plain', + 'deploy': 'application/octet-stream', + 'der': 'application/x-x509-ca-cert', + 'dfac': 'application/vnd.dreamfactory', + 'dgc': 'application/x-dgc-compressed', + 'dic': 'text/x-c', + 'dir': 'application/x-director', + 'dis': 'application/vnd.mobius.dis', + 'dist': 'application/octet-stream', + 'distz': 'application/octet-stream', + 'djv': 'image/vnd.djvu', + 'djvu': 'image/vnd.djvu', + 'dll': 'application/x-msdownload', + 'dmg': 'application/x-apple-diskimage', + 'dmp': 'application/vnd.tcpdump.pcap', + 'dms': 'application/octet-stream', + 'dna': 'application/vnd.dna', + 'doc': 'application/msword', + 'docm': 'application/vnd.ms-word.document.macroenabled.12', + 'docx': + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'dot': 'application/msword', + 'dotm': 'application/vnd.ms-word.template.macroenabled.12', + 'dotx': + 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', + 'dp': 'application/vnd.osgi.dp', + 'dpg': 'application/vnd.dpgraph', + 'dra': 'audio/vnd.dra', + 'dsc': 'text/prs.lines.tag', + 'dssc': 'application/dssc+der', + 'dtb': 'application/x-dtbook+xml', + 'dtd': 'application/xml-dtd', + 'dts': 'audio/vnd.dts', + 'dtshd': 'audio/vnd.dts.hd', + 'dump': 'application/octet-stream', + 'dvb': 'video/vnd.dvb.file', + 'dvi': 'application/x-dvi', + 'dwf': 'model/vnd.dwf', + 'dwg': 'image/vnd.dwg', + 'dxf': 'image/vnd.dxf', + 'dxp': 'application/vnd.spotfire.dxp', + 'dxr': 'application/x-director', + 'ecelp4800': 'audio/vnd.nuera.ecelp4800', + 'ecelp7470': 'audio/vnd.nuera.ecelp7470', + 'ecelp9600': 'audio/vnd.nuera.ecelp9600', + 'ecma': 'application/ecmascript', + 'edm': 'application/vnd.novadigm.edm', + 'edx': 'application/vnd.novadigm.edx', + 'efif': 'application/vnd.picsel', + 'ei6': 'application/vnd.pg.osasli', + 'elc': 'application/octet-stream', + 'emf': 'application/x-msmetafile', + 'eml': 'message/rfc822', + 'emma': 'application/emma+xml', + 'emz': 'application/x-msmetafile', + 'eol': 'audio/vnd.digital-winds', + 'eot': 'application/vnd.ms-fontobject', + 'eps': 'application/postscript', + 'epub': 'application/epub+zip', + 'es3': 'application/vnd.eszigno3+xml', + 'esa': 'application/vnd.osgi.subsystem', + 'esf': 'application/vnd.epson.esf', + 'et3': 'application/vnd.eszigno3+xml', + 'etx': 'text/x-setext', + 'eva': 'application/x-eva', + 'evy': 'application/x-envoy', + 'exe': 'application/x-msdownload', + 'exi': 'application/exi', + 'ext': 'application/vnd.novadigm.ext', + 'ez': 'application/andrew-inset', + 'ez2': 'application/vnd.ezpix-album', + 'ez3': 'application/vnd.ezpix-package', + 'f': 'text/x-fortran', + 'f4v': 'video/x-f4v', + 'f77': 'text/x-fortran', + 'f90': 'text/x-fortran', + 'fbs': 'image/vnd.fastbidsheet', + 'fcdt': 'application/vnd.adobe.formscentral.fcdt', + 'fcs': 'application/vnd.isac.fcs', + 'fdf': 'application/vnd.fdf', + 'fe_launch': 'application/vnd.denovo.fcselayout-link', + 'fg5': 'application/vnd.fujitsu.oasysgp', + 'fgd': 'application/x-director', + 'fh': 'image/x-freehand', + 'fh4': 'image/x-freehand', + 'fh5': 'image/x-freehand', + 'fh7': 'image/x-freehand', + 'fhc': 'image/x-freehand', + 'fig': 'application/x-xfig', + 'flac': 'audio/x-flac', + 'fli': 'video/x-fli', + 'flo': 'application/vnd.micrografx.flo', + 'flv': 'video/x-flv', + 'flw': 'application/vnd.kde.kivio', + 'flx': 'text/vnd.fmi.flexstor', + 'fly': 'text/vnd.fly', + 'fm': 'application/vnd.framemaker', + 'fnc': 'application/vnd.frogans.fnc', + 'for': 'text/x-fortran', + 'fpx': 'image/vnd.fpx', + 'frame': 'application/vnd.framemaker', + 'fsc': 'application/vnd.fsc.weblaunch', + 'fst': 'image/vnd.fst', + 'ftc': 'application/vnd.fluxtime.clip', + 'fti': 'application/vnd.anser-web-funds-transfer-initiation', + 'fvt': 'video/vnd.fvt', + 'fxp': 'application/vnd.adobe.fxp', + 'fxpl': 'application/vnd.adobe.fxp', + 'fzs': 'application/vnd.fuzzysheet', + 'g2w': 'application/vnd.geoplan', + 'g3': 'image/g3fax', + 'g3w': 'application/vnd.geospace', + 'gac': 'application/vnd.groove-account', + 'gam': 'application/x-tads', + 'gbr': 'application/rpki-ghostbusters', + 'gca': 'application/x-gca-compressed', + 'gdl': 'model/vnd.gdl', + 'geo': 'application/vnd.dynageo', + 'gex': 'application/vnd.geometry-explorer', + 'ggb': 'application/vnd.geogebra.file', + 'ggt': 'application/vnd.geogebra.tool', + 'ghf': 'application/vnd.groove-help', + 'gif': 'image/gif', + 'gim': 'application/vnd.groove-identity-message', + 'glb': 'model/gltf-binary', + 'gltf': 'model/gltf+json', + 'gml': 'application/gml+xml', + 'gmx': 'application/vnd.gmx', + 'gnumeric': 'application/x-gnumeric', + 'gph': 'application/vnd.flographit', + 'gpx': 'application/gpx+xml', + 'gqf': 'application/vnd.grafeq', + 'gqs': 'application/vnd.grafeq', + 'gram': 'application/srgs', + 'gramps': 'application/x-gramps-xml', + 'gre': 'application/vnd.geometry-explorer', + 'grv': 'application/vnd.groove-injector', + 'grxml': 'application/srgs+xml', + 'gsf': 'application/x-font-ghostscript', + 'gtar': 'application/x-gtar', + 'gtm': 'application/vnd.groove-tool-message', + 'gtw': 'model/vnd.gtw', + 'gv': 'text/vnd.graphviz', + 'gxf': 'application/gxf', + 'gxt': 'application/vnd.geonext', + 'h': 'text/x-c', + 'h261': 'video/h261', + 'h263': 'video/h263', + 'h264': 'video/h264', + 'hal': 'application/vnd.hal+xml', + 'hbci': 'application/vnd.hbci', + 'hdf': 'application/x-hdf', + 'heic': 'image/heic', + 'heif': 'image/heif', + 'hh': 'text/x-c', + 'hlp': 'application/winhlp', + 'hpgl': 'application/vnd.hp-hpgl', + 'hpid': 'application/vnd.hp-hpid', + 'hps': 'application/vnd.hp-hps', + 'hqx': 'application/mac-binhex40', + 'htke': 'application/vnd.kenameaapp', + 'htm': 'text/html', + 'html': 'text/html', + 'hvd': 'application/vnd.yamaha.hv-dic', + 'hvp': 'application/vnd.yamaha.hv-voice', + 'hvs': 'application/vnd.yamaha.hv-script', + 'i2g': 'application/vnd.intergeo', + 'icc': 'application/vnd.iccprofile', + 'ice': 'x-conference/x-cooltalk', + 'icm': 'application/vnd.iccprofile', + 'ico': 'image/x-icon', + 'ics': 'text/calendar', + 'ief': 'image/ief', + 'ifb': 'text/calendar', + 'ifm': 'application/vnd.shana.informed.formdata', + 'iges': 'model/iges', + 'igl': 'application/vnd.igloader', + 'igm': 'application/vnd.insors.igm', + 'igs': 'model/iges', + 'igx': 'application/vnd.micrografx.igx', + 'iif': 'application/vnd.shana.informed.interchange', + 'imp': 'application/vnd.accpac.simply.imp', + 'ims': 'application/vnd.ms-ims', + 'in': 'text/plain', + 'ink': 'application/inkml+xml', + 'inkml': 'application/inkml+xml', + 'install': 'application/x-install-instructions', + 'iota': 'application/vnd.astraea-software.iota', + 'ipfix': 'application/ipfix', + 'ipk': 'application/vnd.shana.informed.package', + 'irm': 'application/vnd.ibm.rights-management', + 'irp': 'application/vnd.irepository.package+xml', + 'iso': 'application/x-iso9660-image', + 'itp': 'application/vnd.shana.informed.formtemplate', + 'ivp': 'application/vnd.immervision-ivp', + 'ivu': 'application/vnd.immervision-ivu', + 'jad': 'text/vnd.sun.j2me.app-descriptor', + 'jam': 'application/vnd.jam', + 'jar': 'application/java-archive', + 'java': 'text/x-java-source', + 'jisp': 'application/vnd.jisp', + 'jlt': 'application/vnd.hp-jlyt', + 'jnlp': 'application/x-java-jnlp-file', + 'joda': 'application/vnd.joost.joda-archive', + 'jpe': 'image/jpeg', + 'jpeg': 'image/jpeg', + 'jpg': 'image/jpeg', + 'jpgm': 'video/jpm', + 'jpgv': 'video/jpeg', + 'jpm': 'video/jpm', + 'js': 'text/javascript', + 'json': 'application/json', + 'jsonml': 'application/jsonml+json', + 'kar': 'audio/midi', + 'karbon': 'application/vnd.kde.karbon', + 'kfo': 'application/vnd.kde.kformula', + 'kia': 'application/vnd.kidspiration', + 'kml': 'application/vnd.google-earth.kml+xml', + 'kmz': 'application/vnd.google-earth.kmz', + 'kne': 'application/vnd.kinar', + 'knp': 'application/vnd.kinar', + 'kon': 'application/vnd.kde.kontour', + 'kpr': 'application/vnd.kde.kpresenter', + 'kpt': 'application/vnd.kde.kpresenter', + 'kpxx': 'application/vnd.ds-keypoint', + 'ksp': 'application/vnd.kde.kspread', + 'ktr': 'application/vnd.kahootz', + 'ktx': 'image/ktx', + 'ktz': 'application/vnd.kahootz', + 'kwd': 'application/vnd.kde.kword', + 'kwt': 'application/vnd.kde.kword', + 'lasxml': 'application/vnd.las.las+xml', + 'latex': 'application/x-latex', + 'lbd': 'application/vnd.llamagraphics.life-balance.desktop', + 'lbe': 'application/vnd.llamagraphics.life-balance.exchange+xml', + 'les': 'application/vnd.hhe.lesson-player', + 'lha': 'application/x-lzh-compressed', + 'link66': 'application/vnd.route66.link66+xml', + 'list': 'text/plain', + 'list3820': 'application/vnd.ibm.modcap', + 'listafp': 'application/vnd.ibm.modcap', + 'lnk': 'application/x-ms-shortcut', + 'log': 'text/plain', + 'lostxml': 'application/lost+xml', + 'lrf': 'application/octet-stream', + 'lrm': 'application/vnd.ms-lrm', + 'ltf': 'application/vnd.frogans.ltf', + 'lvp': 'audio/vnd.lucent.voice', + 'lwp': 'application/vnd.lotus-wordpro', + 'lzh': 'application/x-lzh-compressed', + 'm13': 'application/x-msmediaview', + 'm14': 'application/x-msmediaview', + 'm1v': 'video/mpeg', + 'm21': 'application/mp21', + 'm2a': 'audio/mpeg', + 'm2v': 'video/mpeg', + 'm3a': 'audio/mpeg', + 'm3u': 'audio/x-mpegurl', + 'm3u8': 'application/vnd.apple.mpegurl', + // Source: https://datatracker.ietf.org/doc/html/rfc4337#section-2 + 'm4a': 'audio/mp4', + 'm4b': 'audio/mp4', + 'm4u': 'video/vnd.mpegurl', + 'm4v': 'video/x-m4v', + 'ma': 'application/mathematica', + 'mads': 'application/mads+xml', + 'mag': 'application/vnd.ecowin.chart', + 'maker': 'application/vnd.framemaker', + 'man': 'text/troff', + 'mar': 'application/octet-stream', + 'mathml': 'application/mathml+xml', + 'mb': 'application/mathematica', + 'mbk': 'application/vnd.mobius.mbk', + 'mbox': 'application/mbox', + 'mc1': 'application/vnd.medcalcdata', + 'mcd': 'application/vnd.mcd', + 'mcurl': 'text/vnd.curl.mcurl', + // https://www.rfc-editor.org/rfc/rfc7763 + 'md': 'text/markdown', + 'markdown': 'text/markdown', + 'mdb': 'application/x-msaccess', + 'mdi': 'image/vnd.ms-modi', + 'me': 'text/troff', + 'mesh': 'model/mesh', + 'meta4': 'application/metalink4+xml', + 'metalink': 'application/metalink+xml', + 'mets': 'application/mets+xml', + 'mfm': 'application/vnd.mfmp', + 'mft': 'application/rpki-manifest', + 'mgp': 'application/vnd.osgeo.mapguide.package', + 'mgz': 'application/vnd.proteus.magazine', + 'mid': 'audio/midi', + 'midi': 'audio/midi', + 'mie': 'application/x-mie', + 'mif': 'application/vnd.mif', + 'mime': 'message/rfc822', + 'mj2': 'video/mj2', + 'mjp2': 'video/mj2', + 'mjs': 'text/javascript', + 'mk3d': 'video/x-matroska', + 'mka': 'audio/x-matroska', + 'mks': 'video/x-matroska', + 'mkv': 'video/x-matroska', + 'mlp': 'application/vnd.dolby.mlp', + 'mmd': 'application/vnd.chipnuts.karaoke-mmd', + 'mmf': 'application/vnd.smaf', + 'mmr': 'image/vnd.fujixerox.edmics-mmr', + 'mng': 'video/x-mng', + 'mny': 'application/x-msmoney', + 'mobi': 'application/x-mobipocket-ebook', + 'mods': 'application/mods+xml', + 'mov': 'video/quicktime', + 'movie': 'video/x-sgi-movie', + 'mp2': 'audio/mpeg', + 'mp21': 'application/mp21', + 'mp2a': 'audio/mpeg', + 'mp3': 'audio/mpeg', + 'mp4': 'video/mp4', + 'mp4a': 'audio/mp4', + 'mp4s': 'application/mp4', + 'mp4v': 'video/mp4', + 'mpc': 'application/vnd.mophun.certificate', + 'mpe': 'video/mpeg', + 'mpeg': 'video/mpeg', + 'mpg': 'video/mpeg', + 'mpg4': 'video/mp4', + 'mpga': 'audio/mpeg', + 'mpkg': 'application/vnd.apple.installer+xml', + 'mpm': 'application/vnd.blueice.multipass', + 'mpn': 'application/vnd.mophun.application', + 'mpp': 'application/vnd.ms-project', + 'mpt': 'application/vnd.ms-project', + 'mpy': 'application/vnd.ibm.minipay', + 'mqy': 'application/vnd.mobius.mqy', + 'mrc': 'application/marc', + 'mrcx': 'application/marcxml+xml', + 'ms': 'text/troff', + 'mscml': 'application/mediaservercontrol+xml', + 'mseed': 'application/vnd.fdsn.mseed', + 'mseq': 'application/vnd.mseq', + 'msf': 'application/vnd.epson.msf', + 'msh': 'model/mesh', + 'msi': 'application/x-msdownload', + 'msl': 'application/vnd.mobius.msl', + 'msty': 'application/vnd.muvee.style', + 'mts': 'model/vnd.mts', + 'mus': 'application/vnd.musician', + 'musicxml': 'application/vnd.recordare.musicxml+xml', + 'mvb': 'application/x-msmediaview', + 'mwf': 'application/vnd.mfer', + 'mxf': 'application/mxf', + 'mxl': 'application/vnd.recordare.musicxml', + 'mxml': 'application/xv+xml', + 'mxs': 'application/vnd.triscape.mxs', + 'mxu': 'video/vnd.mpegurl', + 'n-gage': 'application/vnd.nokia.n-gage.symbian.install', + 'n3': 'text/n3', + 'nb': 'application/mathematica', + 'nbp': 'application/vnd.wolfram.player', + 'nc': 'application/x-netcdf', + 'ncx': 'application/x-dtbncx+xml', + 'nfo': 'text/x-nfo', + 'ngdat': 'application/vnd.nokia.n-gage.data', + 'nitf': 'application/vnd.nitf', + 'nlu': 'application/vnd.neurolanguage.nlu', + 'nml': 'application/vnd.enliven', + 'nnd': 'application/vnd.noblenet-directory', + 'nns': 'application/vnd.noblenet-sealer', + 'nnw': 'application/vnd.noblenet-web', + 'npx': 'image/vnd.net-fpx', + 'nsc': 'application/x-conference', + 'nsf': 'application/vnd.lotus-notes', + 'ntf': 'application/vnd.nitf', + 'nzb': 'application/x-nzb', + 'oa2': 'application/vnd.fujitsu.oasys2', + 'oa3': 'application/vnd.fujitsu.oasys3', + 'oas': 'application/vnd.fujitsu.oasys', + 'obd': 'application/x-msbinder', + 'obj': 'application/x-tgif', + 'oda': 'application/oda', + 'odb': 'application/vnd.oasis.opendocument.database', + 'odc': 'application/vnd.oasis.opendocument.chart', + 'odf': 'application/vnd.oasis.opendocument.formula', + 'odft': 'application/vnd.oasis.opendocument.formula-template', + 'odg': 'application/vnd.oasis.opendocument.graphics', + 'odi': 'application/vnd.oasis.opendocument.image', + 'odm': 'application/vnd.oasis.opendocument.text-master', + 'odp': 'application/vnd.oasis.opendocument.presentation', + 'ods': 'application/vnd.oasis.opendocument.spreadsheet', + 'odt': 'application/vnd.oasis.opendocument.text', + 'oga': 'audio/ogg', + 'ogg': 'audio/ogg', + 'ogv': 'video/ogg', + 'ogx': 'application/ogg', + 'omdoc': 'application/omdoc+xml', + 'onepkg': 'application/onenote', + 'onetmp': 'application/onenote', + 'onetoc': 'application/onenote', + 'onetoc2': 'application/onenote', + 'opf': 'application/oebps-package+xml', + 'opml': 'text/x-opml', + 'oprc': 'application/vnd.palm', + 'org': 'application/vnd.lotus-organizer', + 'osf': 'application/vnd.yamaha.openscoreformat', + 'osfpvg': 'application/vnd.yamaha.openscoreformat.osfpvg+xml', + 'otc': 'application/vnd.oasis.opendocument.chart-template', + 'otf': 'application/x-font-otf', + 'otg': 'application/vnd.oasis.opendocument.graphics-template', + 'oth': 'application/vnd.oasis.opendocument.text-web', + 'oti': 'application/vnd.oasis.opendocument.image-template', + 'otp': 'application/vnd.oasis.opendocument.presentation-template', + 'ots': 'application/vnd.oasis.opendocument.spreadsheet-template', + 'ott': 'application/vnd.oasis.opendocument.text-template', + 'oxps': 'application/oxps', + 'oxt': 'application/vnd.openofficeorg.extension', + 'p': 'text/x-pascal', + 'p10': 'application/pkcs10', + 'p12': 'application/x-pkcs12', + 'p7b': 'application/x-pkcs7-certificates', + 'p7c': 'application/pkcs7-mime', + 'p7m': 'application/pkcs7-mime', + 'p7r': 'application/x-pkcs7-certreqresp', + 'p7s': 'application/pkcs7-signature', + 'p8': 'application/pkcs8', + 'pas': 'text/x-pascal', + 'paw': 'application/vnd.pawaafile', + 'pbd': 'application/vnd.powerbuilder6', + 'pbm': 'image/x-portable-bitmap', + 'pcap': 'application/vnd.tcpdump.pcap', + 'pcf': 'application/x-font-pcf', + 'pcl': 'application/vnd.hp-pcl', + 'pclxl': 'application/vnd.hp-pclxl', + 'pct': 'image/x-pict', + 'pcurl': 'application/vnd.curl.pcurl', + 'pcx': 'image/x-pcx', + 'pdb': 'application/vnd.palm', + 'pdf': 'application/pdf', + 'pfa': 'application/x-font-type1', + 'pfb': 'application/x-font-type1', + 'pfm': 'application/x-font-type1', + 'pfr': 'application/font-tdpfr', + 'pfx': 'application/x-pkcs12', + 'pgm': 'image/x-portable-graymap', + 'pgn': 'application/x-chess-pgn', + 'pgp': 'application/pgp-encrypted', + 'pic': 'image/x-pict', + 'pkg': 'application/octet-stream', + 'pki': 'application/pkixcmp', + 'pkipath': 'application/pkix-pkipath', + 'plb': 'application/vnd.3gpp.pic-bw-large', + 'plc': 'application/vnd.mobius.plc', + 'plf': 'application/vnd.pocketlearn', + 'pls': 'application/pls+xml', + 'pml': 'application/vnd.ctc-posml', + 'png': 'image/png', + 'pnm': 'image/x-portable-anymap', + 'portpkg': 'application/vnd.macports.portpkg', + 'pot': 'application/vnd.ms-powerpoint', + 'potm': 'application/vnd.ms-powerpoint.template.macroenabled.12', + 'potx': + 'application/vnd.openxmlformats-officedocument.presentationml.template', + 'ppam': 'application/vnd.ms-powerpoint.addin.macroenabled.12', + 'ppd': 'application/vnd.cups-ppd', + 'ppm': 'image/x-portable-pixmap', + 'pps': 'application/vnd.ms-powerpoint', + 'ppsm': 'application/vnd.ms-powerpoint.slideshow.macroenabled.12', + 'ppsx': + 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', + 'ppt': 'application/vnd.ms-powerpoint', + 'pptm': 'application/vnd.ms-powerpoint.presentation.macroenabled.12', + 'pptx': + 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'pqa': 'application/vnd.palm', + 'prc': 'application/x-mobipocket-ebook', + 'pre': 'application/vnd.lotus-freelance', + 'prf': 'application/pics-rules', + 'ps': 'application/postscript', + 'psb': 'application/vnd.3gpp.pic-bw-small', + 'psd': 'image/vnd.adobe.photoshop', + 'psf': 'application/x-font-linux-psf', + 'pskcxml': 'application/pskc+xml', + 'ptid': 'application/vnd.pvi.ptid1', + 'pub': 'application/x-mspublisher', + 'pvb': 'application/vnd.3gpp.pic-bw-var', + 'pwn': 'application/vnd.3m.post-it-notes', + 'pya': 'audio/vnd.ms-playready.media.pya', + 'pyv': 'video/vnd.ms-playready.media.pyv', + 'qam': 'application/vnd.epson.quickanime', + 'qbo': 'application/vnd.intu.qbo', + 'qfx': 'application/vnd.intu.qfx', + 'qps': 'application/vnd.publishare-delta-tree', + 'qt': 'video/quicktime', + 'qwd': 'application/vnd.quark.quarkxpress', + 'qwt': 'application/vnd.quark.quarkxpress', + 'qxb': 'application/vnd.quark.quarkxpress', + 'qxd': 'application/vnd.quark.quarkxpress', + 'qxl': 'application/vnd.quark.quarkxpress', + 'qxt': 'application/vnd.quark.quarkxpress', + 'ra': 'audio/x-pn-realaudio', + 'ram': 'audio/x-pn-realaudio', + 'rar': 'application/x-rar-compressed', + 'ras': 'image/x-cmu-raster', + 'rcprofile': 'application/vnd.ipunplugged.rcprofile', + 'rdf': 'application/rdf+xml', + 'rdz': 'application/vnd.data-vision.rdz', + 'rep': 'application/vnd.businessobjects', + 'res': 'application/x-dtbresource+xml', + 'rgb': 'image/x-rgb', + 'rif': 'application/reginfo+xml', + 'rip': 'audio/vnd.rip', + 'ris': 'application/x-research-info-systems', + 'rl': 'application/resource-lists+xml', + 'rlc': 'image/vnd.fujixerox.edmics-rlc', + 'rld': 'application/resource-lists-diff+xml', + 'rm': 'application/vnd.rn-realmedia', + 'rmi': 'audio/midi', + 'rmp': 'audio/x-pn-realaudio-plugin', + 'rms': 'application/vnd.jcp.javame.midlet-rms', + 'rmvb': 'application/vnd.rn-realmedia-vbr', + 'rnc': 'application/relax-ng-compact-syntax', + 'roa': 'application/rpki-roa', + 'roff': 'text/troff', + 'rp9': 'application/vnd.cloanto.rp9', + 'rpss': 'application/vnd.nokia.radio-presets', + 'rpst': 'application/vnd.nokia.radio-preset', + 'rq': 'application/sparql-query', + 'rs': 'application/rls-services+xml', + 'rsd': 'application/rsd+xml', + 'rss': 'application/rss+xml', + 'rtf': 'application/rtf', + 'rtx': 'text/richtext', + 's': 'text/x-asm', + 's3m': 'audio/s3m', + 'saf': 'application/vnd.yamaha.smaf-audio', + 'sbml': 'application/sbml+xml', + 'sc': 'application/vnd.ibm.secure-container', + 'scd': 'application/x-msschedule', + 'scm': 'application/vnd.lotus-screencam', + 'scq': 'application/scvp-cv-request', + 'scs': 'application/scvp-cv-response', + 'scurl': 'text/vnd.curl.scurl', + 'sda': 'application/vnd.stardivision.draw', + 'sdc': 'application/vnd.stardivision.calc', + 'sdd': 'application/vnd.stardivision.impress', + 'sdkd': 'application/vnd.solent.sdkm+xml', + 'sdkm': 'application/vnd.solent.sdkm+xml', + 'sdp': 'application/sdp', + 'sdw': 'application/vnd.stardivision.writer', + 'see': 'application/vnd.seemail', + 'seed': 'application/vnd.fdsn.seed', + 'sema': 'application/vnd.sema', + 'semd': 'application/vnd.semd', + 'semf': 'application/vnd.semf', + 'ser': 'application/java-serialized-object', + 'setpay': 'application/set-payment-initiation', + 'setreg': 'application/set-registration-initiation', + 'sfd-hdstx': 'application/vnd.hydrostatix.sof-data', + 'sfs': 'application/vnd.spotfire.sfs', + 'sfv': 'text/x-sfv', + 'sgi': 'image/sgi', + 'sgl': 'application/vnd.stardivision.writer-global', + 'sgm': 'text/sgml', + 'sgml': 'text/sgml', + 'sh': 'application/x-sh', + 'shar': 'application/x-shar', + 'shf': 'application/shf+xml', + 'sid': 'image/x-mrsid-image', + 'sig': 'application/pgp-signature', + 'sil': 'audio/silk', + 'silo': 'model/mesh', + 'sis': 'application/vnd.symbian.install', + 'sisx': 'application/vnd.symbian.install', + 'sit': 'application/x-stuffit', + 'sitx': 'application/x-stuffitx', + 'skd': 'application/vnd.koan', + 'skm': 'application/vnd.koan', + 'skp': 'application/vnd.koan', + 'skt': 'application/vnd.koan', + 'sldm': 'application/vnd.ms-powerpoint.slide.macroenabled.12', + 'sldx': 'application/vnd.openxmlformats-officedocument.presentationml.slide', + 'slt': 'application/vnd.epson.salt', + 'sm': 'application/vnd.stepmania.stepchart', + 'smf': 'application/vnd.stardivision.math', + 'smi': 'application/smil+xml', + 'smil': 'application/smil+xml', + 'smv': 'video/x-smv', + 'smzip': 'application/vnd.stepmania.package', + 'snd': 'audio/basic', + 'snf': 'application/x-font-snf', + 'so': 'application/octet-stream', + 'spc': 'application/x-pkcs7-certificates', + 'spf': 'application/vnd.yamaha.smaf-phrase', + 'spl': 'application/x-futuresplash', + 'spot': 'text/vnd.in3d.spot', + 'spp': 'application/scvp-vp-response', + 'spq': 'application/scvp-vp-request', + 'spx': 'audio/ogg', + 'sql': 'application/x-sql', + 'src': 'application/x-wais-source', + 'srt': 'application/x-subrip', + 'sru': 'application/sru+xml', + 'srx': 'application/sparql-results+xml', + 'ssdl': 'application/ssdl+xml', + 'sse': 'application/vnd.kodak-descriptor', + 'ssf': 'application/vnd.epson.ssf', + 'ssml': 'application/ssml+xml', + 'st': 'application/vnd.sailingtracker.track', + 'stc': 'application/vnd.sun.xml.calc.template', + 'std': 'application/vnd.sun.xml.draw.template', + 'stf': 'application/vnd.wt.stf', + 'sti': 'application/vnd.sun.xml.impress.template', + 'stk': 'application/hyperstudio', + 'stl': 'application/vnd.ms-pki.stl', + 'str': 'application/vnd.pg.format', + 'stw': 'application/vnd.sun.xml.writer.template', + 'sub': 'text/vnd.dvb.subtitle', + 'sus': 'application/vnd.sus-calendar', + 'susp': 'application/vnd.sus-calendar', + 'sv4cpio': 'application/x-sv4cpio', + 'sv4crc': 'application/x-sv4crc', + 'svc': 'application/vnd.dvb.service', + 'svd': 'application/vnd.svd', + 'svg': 'image/svg+xml', + 'svgz': 'image/svg+xml', + 'swa': 'application/x-director', + 'swf': 'application/x-shockwave-flash', + 'swi': 'application/vnd.aristanetworks.swi', + 'sxc': 'application/vnd.sun.xml.calc', + 'sxd': 'application/vnd.sun.xml.draw', + 'sxg': 'application/vnd.sun.xml.writer.global', + 'sxi': 'application/vnd.sun.xml.impress', + 'sxm': 'application/vnd.sun.xml.math', + 'sxw': 'application/vnd.sun.xml.writer', + 't': 'text/troff', + 't3': 'application/x-t3vm-image', + 'taglet': 'application/vnd.mynfc', + 'tao': 'application/vnd.tao.intent-module-archive', + 'tar': 'application/x-tar', + 'tcap': 'application/vnd.3gpp2.tcap', + 'tcl': 'application/x-tcl', + 'teacher': 'application/vnd.smart.teacher', + 'tei': 'application/tei+xml', + 'teicorpus': 'application/tei+xml', + 'tex': 'application/x-tex', + 'texi': 'application/x-texinfo', + 'texinfo': 'application/x-texinfo', + 'text': 'text/plain', + 'tfi': 'application/thraud+xml', + 'tfm': 'application/x-tex-tfm', + 'tga': 'image/x-tga', + 'thmx': 'application/vnd.ms-officetheme', + 'tif': 'image/tiff', + 'tiff': 'image/tiff', + 'tmo': 'application/vnd.tmobile-livetv', + // Source: https://toml.io/en/v1.0.0#mime-type + 'toml': 'application/toml', + 'torrent': 'application/x-bittorrent', + 'tpl': 'application/vnd.groove-tool-template', + 'tpt': 'application/vnd.trid.tpt', + 'tr': 'text/troff', + 'tra': 'application/vnd.trueapp', + 'trm': 'application/x-msterminal', + 'tsd': 'application/timestamped-data', + 'tsv': 'text/tab-separated-values', + 'ttc': 'application/x-font-ttf', + 'ttf': 'application/x-font-ttf', + 'ttl': 'text/turtle', + 'twd': 'application/vnd.simtech-mindmapper', + 'twds': 'application/vnd.simtech-mindmapper', + 'txd': 'application/vnd.genomatix.tuxedo', + 'txf': 'application/vnd.mobius.txf', + 'txt': 'text/plain', + 'u32': 'application/x-authorware-bin', + 'udeb': 'application/x-debian-package', + 'ufd': 'application/vnd.ufdl', + 'ufdl': 'application/vnd.ufdl', + 'ulx': 'application/x-glulx', + 'umj': 'application/vnd.umajin', + 'unityweb': 'application/vnd.unity', + 'uoml': 'application/vnd.uoml+xml', + 'uri': 'text/uri-list', + 'uris': 'text/uri-list', + 'urls': 'text/uri-list', + 'ustar': 'application/x-ustar', + 'utz': 'application/vnd.uiq.theme', + 'uu': 'text/x-uuencode', + 'uva': 'audio/vnd.dece.audio', + 'uvd': 'application/vnd.dece.data', + 'uvf': 'application/vnd.dece.data', + 'uvg': 'image/vnd.dece.graphic', + 'uvh': 'video/vnd.dece.hd', + 'uvi': 'image/vnd.dece.graphic', + 'uvm': 'video/vnd.dece.mobile', + 'uvp': 'video/vnd.dece.pd', + 'uvs': 'video/vnd.dece.sd', + 'uvt': 'application/vnd.dece.ttml+xml', + 'uvu': 'video/vnd.uvvu.mp4', + 'uvv': 'video/vnd.dece.video', + 'uvva': 'audio/vnd.dece.audio', + 'uvvd': 'application/vnd.dece.data', + 'uvvf': 'application/vnd.dece.data', + 'uvvg': 'image/vnd.dece.graphic', + 'uvvh': 'video/vnd.dece.hd', + 'uvvi': 'image/vnd.dece.graphic', + 'uvvm': 'video/vnd.dece.mobile', + 'uvvp': 'video/vnd.dece.pd', + 'uvvs': 'video/vnd.dece.sd', + 'uvvt': 'application/vnd.dece.ttml+xml', + 'uvvu': 'video/vnd.uvvu.mp4', + 'uvvv': 'video/vnd.dece.video', + 'uvvx': 'application/vnd.dece.unspecified', + 'uvvz': 'application/vnd.dece.zip', + 'uvx': 'application/vnd.dece.unspecified', + 'uvz': 'application/vnd.dece.zip', + 'vcard': 'text/vcard', + 'vcd': 'application/x-cdlink', + 'vcf': 'text/x-vcard', + 'vcg': 'application/vnd.groove-vcard', + 'vcs': 'text/x-vcalendar', + 'vcx': 'application/vnd.vcx', + 'vis': 'application/vnd.visionary', + 'viv': 'video/vnd.vivo', + 'vob': 'video/x-ms-vob', + 'vor': 'application/vnd.stardivision.writer', + 'vox': 'application/x-authorware-bin', + 'vrml': 'model/vrml', + 'vsd': 'application/vnd.visio', + 'vsf': 'application/vnd.vsf', + 'vss': 'application/vnd.visio', + 'vst': 'application/vnd.visio', + 'vsw': 'application/vnd.visio', + 'vtu': 'model/vnd.vtu', + 'vxml': 'application/voicexml+xml', + 'w3d': 'application/x-director', + 'wad': 'application/x-doom', + 'wasm': 'application/wasm', + 'wav': 'audio/x-wav', + 'wax': 'audio/x-ms-wax', + 'wbmp': 'image/vnd.wap.wbmp', + 'wbs': 'application/vnd.criticaltools.wbs+xml', + 'wbxml': 'application/vnd.wap.wbxml', + 'wcm': 'application/vnd.ms-works', + 'wdb': 'application/vnd.ms-works', + 'wdp': 'image/vnd.ms-photo', + 'weba': 'audio/webm', + 'webm': 'video/webm', + // Source: https://w3c.github.io/manifest/#media-type-registration + 'webmanifest': 'application/manifest+json', + 'webp': 'image/webp', + 'wg': 'application/vnd.pmi.widget', + 'wgt': 'application/widget', + 'wks': 'application/vnd.ms-works', + 'wm': 'video/x-ms-wm', + 'wma': 'audio/x-ms-wma', + 'wmd': 'application/x-ms-wmd', + 'wmf': 'application/x-msmetafile', + 'wml': 'text/vnd.wap.wml', + 'wmlc': 'application/vnd.wap.wmlc', + 'wmls': 'text/vnd.wap.wmlscript', + 'wmlsc': 'application/vnd.wap.wmlscriptc', + 'wmv': 'video/x-ms-wmv', + 'wmx': 'video/x-ms-wmx', + 'wmz': 'application/x-ms-wmz', + 'woff': 'application/x-font-woff', + 'woff2': 'font/woff2', + 'wpd': 'application/vnd.wordperfect', + 'wpl': 'application/vnd.ms-wpl', + 'wps': 'application/vnd.ms-works', + 'wqd': 'application/vnd.wqd', + 'wri': 'application/x-mswrite', + 'wrl': 'model/vrml', + 'wsdl': 'application/wsdl+xml', + 'wspolicy': 'application/wspolicy+xml', + 'wtb': 'application/vnd.webturbo', + 'wvx': 'video/x-ms-wvx', + 'x32': 'application/x-authorware-bin', + 'x3d': 'model/x3d+xml', + 'x3db': 'model/x3d+binary', + 'x3dbz': 'model/x3d+binary', + 'x3dv': 'model/x3d+vrml', + 'x3dvz': 'model/x3d+vrml', + 'x3dz': 'model/x3d+xml', + 'xaml': 'application/xaml+xml', + 'xap': 'application/x-silverlight-app', + 'xar': 'application/vnd.xara', + 'xbap': 'application/x-ms-xbap', + 'xbd': 'application/vnd.fujixerox.docuworks.binder', + 'xbm': 'image/x-xbitmap', + 'xdf': 'application/xcap-diff+xml', + 'xdm': 'application/vnd.syncml.dm+xml', + 'xdp': 'application/vnd.adobe.xdp+xml', + 'xdssc': 'application/dssc+xml', + 'xdw': 'application/vnd.fujixerox.docuworks', + 'xenc': 'application/xenc+xml', + 'xer': 'application/patch-ops-error+xml', + 'xfdf': 'application/vnd.adobe.xfdf', + 'xfdl': 'application/vnd.xfdl', + 'xht': 'application/xhtml+xml', + 'xhtml': 'application/xhtml+xml', + 'xhvml': 'application/xv+xml', + 'xif': 'image/vnd.xiff', + 'xla': 'application/vnd.ms-excel', + 'xlam': 'application/vnd.ms-excel.addin.macroenabled.12', + 'xlc': 'application/vnd.ms-excel', + 'xlf': 'application/x-xliff+xml', + 'xlm': 'application/vnd.ms-excel', + 'xls': 'application/vnd.ms-excel', + 'xlsb': 'application/vnd.ms-excel.sheet.binary.macroenabled.12', + 'xlsm': 'application/vnd.ms-excel.sheet.macroenabled.12', + 'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'xlt': 'application/vnd.ms-excel', + 'xltm': 'application/vnd.ms-excel.template.macroenabled.12', + 'xltx': + 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', + 'xlw': 'application/vnd.ms-excel', + 'xm': 'audio/xm', + 'xml': 'application/xml', + 'xo': 'application/vnd.olpc-sugar', + 'xop': 'application/xop+xml', + 'xpi': 'application/x-xpinstall', + 'xpl': 'application/xproc+xml', + 'xpm': 'image/x-xpixmap', + 'xpr': 'application/vnd.is-xpr', + 'xps': 'application/vnd.ms-xpsdocument', + 'xpw': 'application/vnd.intercon.formnet', + 'xpx': 'application/vnd.intercon.formnet', + 'xsl': 'application/xml', + 'xslt': 'application/xslt+xml', + 'xsm': 'application/vnd.syncml+xml', + 'xspf': 'application/xspf+xml', + 'xul': 'application/vnd.mozilla.xul+xml', + 'xvm': 'application/xv+xml', + 'xvml': 'application/xv+xml', + 'xwd': 'image/x-xwindowdump', + 'xyz': 'chemical/x-xyz', + 'xz': 'application/x-xz', + 'yang': 'application/yang', + 'yin': 'application/yin+xml', + 'z1': 'application/x-zmachine', + 'z2': 'application/x-zmachine', + 'z3': 'application/x-zmachine', + 'z4': 'application/x-zmachine', + 'z5': 'application/x-zmachine', + 'z6': 'application/x-zmachine', + 'z7': 'application/x-zmachine', + 'z8': 'application/x-zmachine', + 'zaz': 'application/vnd.zzazz.deck+xml', + 'zip': 'application/zip', + 'zir': 'application/vnd.zul', + 'zirz': 'application/vnd.zul', + 'zmm': 'application/vnd.handheld-entertainment+xml', +};
diff --git a/pkgs/mime/lib/src/extension.dart b/pkgs/mime/lib/src/extension.dart new file mode 100644 index 0000000..293449a --- /dev/null +++ b/pkgs/mime/lib/src/extension.dart
@@ -0,0 +1,55 @@ +// 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 'default_extension_map.dart'; + +/// Default extension for recognized MIME types. +/// +/// Is the inverse of [defaultExtensionMap], and where that +/// map has multiple extensions which map to the same +/// MIME type, this map maps that MIME type to a *default* +/// extension. +/// +/// Used by [extensionFromMime]. +final Map<String, String> _defaultMimeTypeMap = { + for (var entry in defaultExtensionMap.entries) entry.value: entry.key, + 'application/msword': 'doc', + 'application/vnd.ms-excel': 'xls', + 'application/vnd.ms-powerpoint': 'ppt', + 'application/x-debian-package': 'deb', + 'application/xhtml+xml': 'xhtml', + 'application/xml': 'xml', + 'audio/x-aiff': 'aif', + 'audio/midi': 'mid', + 'audio/mp4': 'm4a', + 'audio/ogg': 'ogg', + 'image/jpeg': 'jpg', + 'image/tiff': 'tif', + 'image/svg+xml': 'svg', + 'model/vrml': 'vrml', + 'text/calendar': 'ics', + 'text/html': 'html', + 'text/javascript': 'js', + 'text/markdown': 'md', + 'text/plain': 'txt', + 'text/sgml': 'sgml', + 'text/x-asm': 'asm', + 'text/x-c': 'c', + 'text/x-pascal': 'pas', + 'video/mp4': 'mp4', + 'video/mpeg': 'mpg', + 'video/quicktime': 'mov', + 'video/x-matroska': 'mkv', +}; + +/// The default file extension for a given MIME type. +/// +/// If [mimeType] has multiple associated extensions, +/// the returned string is one of those, chosen as the default +/// extension for that MIME type. +/// +/// Returns `null` if [mimeType] is not a recognized and +/// supported MIME type. +String? extensionFromMime(String mimeType) => + _defaultMimeTypeMap[mimeType.toLowerCase()];
diff --git a/pkgs/mime/lib/src/magic_number.dart b/pkgs/mime/lib/src/magic_number.dart new file mode 100644 index 0000000..c8b5c3b --- /dev/null +++ b/pkgs/mime/lib/src/magic_number.dart
@@ -0,0 +1,407 @@ +// Copyright (c) 2013, 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. + +class MagicNumber { + final String mimeType; + final List<int> numbers; + final List<int>? mask; + + const MagicNumber(this.mimeType, this.numbers, {this.mask}); + + bool matches(List<int> header) { + if (header.length < numbers.length) return false; + + for (var i = 0; i < numbers.length; i++) { + if (mask != null) { + if ((mask![i] & numbers[i]) != (mask![i] & header[i])) return false; + } else { + if (numbers[i] != header[i]) return false; + } + } + + return true; + } +} + +const int initialMagicNumbersMaxLength = 12; + +const List<MagicNumber> initialMagicNumbers = [ + MagicNumber('application/pdf', [0x25, 0x50, 0x44, 0x46]), + MagicNumber('application/postscript', [0x25, 0x51]), + + /// AIFF is based on the EA IFF 85 Standard for Interchange Format Files. + /// -> 4 bytes have the ASCII characters 'F' 'O' 'R' 'M'. + /// -> 4 bytes indicating the size of the file + /// -> 4 bytes have the ASCII characters 'A' 'I' 'F' 'F'. + /// http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/AIFF/Docs/AIFF-1.3.pdf + MagicNumber('audio/x-aiff', [ + 0x46, + 0x4F, + 0x52, + 0x4D, + 0x00, + 0x00, + 0x00, + 0x00, + 0x41, + 0x49, + 0x46, + 0x46 + ], mask: [ + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0x00, + 0x00, + 0x00, + 0x00, + 0xFF, + 0xFF, + 0xFF, + 0xFF + ]), + + /// -> 4 bytes have the ASCII characters 'f' 'L' 'a' 'C'. + /// https://xiph.org/flac/format.html + MagicNumber('audio/x-flac', [0x66, 0x4C, 0x61, 0x43]), + + /// The WAVE file format is based on the RIFF document format. + /// -> 4 bytes have the ASCII characters 'R' 'I' 'F' 'F'. + /// -> 4 bytes indicating the size of the file + /// -> 4 bytes have the ASCII characters 'W' 'A' 'V' 'E'. + /// http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/Docs/riffmci.pdf + MagicNumber('audio/x-wav', [ + 0x52, + 0x49, + 0x46, + 0x46, + 0x00, + 0x00, + 0x00, + 0x00, + 0x57, + 0x41, + 0x56, + 0x45 + ], mask: [ + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0x00, + 0x00, + 0x00, + 0x00, + 0xFF, + 0xFF, + 0xFF, + 0xFF + ]), + MagicNumber('image/gif', [0x47, 0x49, 0x46, 0x38, 0x37, 0x61]), + MagicNumber('image/gif', [0x47, 0x49, 0x46, 0x38, 0x39, 0x61]), + MagicNumber('image/jpeg', [0xFF, 0xD8]), + MagicNumber('image/png', [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]), + MagicNumber('image/tiff', [0x49, 0x49, 0x2A, 0x00]), + MagicNumber('image/tiff', [0x4D, 0x4D, 0x00, 0x2A]), + MagicNumber('audio/aac', [0xFF, 0xF1]), + MagicNumber('audio/aac', [0xFF, 0xF9]), + MagicNumber('audio/weba', [0x1A, 0x45, 0xDF, 0xA3]), + MagicNumber('audio/mpeg', [0x49, 0x44, 0x33]), + MagicNumber('audio/mpeg', [0xFF, 0xFB]), + MagicNumber('audio/ogg', [0x4F, 0x70, 0x75]), + MagicNumber('video/3gpp', [ + 0x00, + 0x00, + 0x00, + 0x00, + 0x66, + 0x74, + 0x79, + 0x70, + 0x33, + 0x67, + 0x70, + 0x35 + ], mask: [ + 0xFF, + 0xFF, + 0xFF, + 0x00, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF + ]), + MagicNumber('video/mp4', [ + 0x00, + 0x00, + 0x00, + 0x00, + 0x66, + 0x74, + 0x79, + 0x70, + 0x61, + 0x76, + 0x63, + 0x31 + ], mask: [ + 0x00, + 0x00, + 0x00, + 0x00, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF + ]), + MagicNumber('video/mp4', [ + 0x00, + 0x00, + 0x00, + 0x00, + 0x66, + 0x74, + 0x79, + 0x70, + 0x69, + 0x73, + 0x6F, + 0x32 + ], mask: [ + 0x00, + 0x00, + 0x00, + 0x00, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF + ]), + MagicNumber('video/mp4', [ + 0x00, + 0x00, + 0x00, + 0x00, + 0x66, + 0x74, + 0x79, + 0x70, + 0x69, + 0x73, + 0x6F, + 0x6D + ], mask: [ + 0x00, + 0x00, + 0x00, + 0x00, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF + ]), + MagicNumber('video/mp4', [ + 0x00, + 0x00, + 0x00, + 0x00, + 0x66, + 0x74, + 0x79, + 0x70, + 0x6D, + 0x70, + 0x34, + 0x31 + ], mask: [ + 0x00, + 0x00, + 0x00, + 0x00, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF + ]), + MagicNumber('video/mp4', [ + 0x00, + 0x00, + 0x00, + 0x00, + 0x66, + 0x74, + 0x79, + 0x70, + 0x6D, + 0x70, + 0x34, + 0x32 + ], mask: [ + 0x00, + 0x00, + 0x00, + 0x00, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF + ]), + MagicNumber('model/gltf-binary', [0x46, 0x54, 0x6C, 0x67]), + + /// The WebP file format is based on the RIFF document format. + /// -> 4 bytes have the ASCII characters 'R' 'I' 'F' 'F'. + /// -> 4 bytes indicating the size of the file + /// -> 4 bytes have the ASCII characters 'W' 'E' 'B' 'P'. + /// https://developers.google.com/speed/webp/docs/riff_container + MagicNumber('image/webp', [ + 0x52, + 0x49, + 0x46, + 0x46, + 0x00, + 0x00, + 0x00, + 0x00, + 0x57, + 0x45, + 0x42, + 0x50 + ], mask: [ + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0x00, + 0x00, + 0x00, + 0x00, + 0xFF, + 0xFF, + 0xFF, + 0xFF + ]), + + MagicNumber('font/woff2', [0x77, 0x4f, 0x46, 0x32]), + + /// High Efficiency Image File Format (ISO/IEC 23008-12). + /// -> 4 bytes indicating the ftyp box length. + /// -> 4 bytes have the ASCII characters 'f' 't' 'y' 'p'. + /// -> 4 bytes have the ASCII characters 'h' 'e' 'i' 'c'. + /// https://www.iana.org/assignments/media-types/image/heic + MagicNumber('image/heic', [ + 0x00, + 0x00, + 0x00, + 0x00, + 0x66, + 0x74, + 0x79, + 0x70, + 0x68, + 0x65, + 0x69, + 0x63 + ], mask: [ + 0x00, + 0x00, + 0x00, + 0x00, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF + ]), + + /// -> 4 bytes indicating the ftyp box length. + /// -> 4 bytes have the ASCII characters 'f' 't' 'y' 'p'. + /// -> 4 bytes have the ASCII characters 'h' 'e' 'i' 'x'. + MagicNumber('image/heic', [ + 0x00, + 0x00, + 0x00, + 0x00, + 0x66, + 0x74, + 0x79, + 0x70, + 0x68, + 0x65, + 0x69, + 0x78 + ], mask: [ + 0x00, + 0x00, + 0x00, + 0x00, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF + ]), + + /// -> 4 bytes indicating the ftyp box length. + /// -> 4 bytes have the ASCII characters 'f' 't' 'y' 'p'. + /// -> 4 bytes have the ASCII characters 'm' 'i' 'f' '1'. + MagicNumber('image/heif', [ + 0x00, + 0x00, + 0x00, + 0x00, + 0x66, + 0x74, + 0x79, + 0x70, + 0x6D, + 0x69, + 0x66, + 0x31 + ], mask: [ + 0x00, + 0x00, + 0x00, + 0x00, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF + ]), +];
diff --git a/pkgs/mime/lib/src/mime_multipart_transformer.dart b/pkgs/mime/lib/src/mime_multipart_transformer.dart new file mode 100644 index 0000000..2648d7d --- /dev/null +++ b/pkgs/mime/lib/src/mime_multipart_transformer.dart
@@ -0,0 +1,42 @@ +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:typed_data'; + +import 'bound_multipart_stream.dart'; +import 'char_code.dart' as char_code; +import 'mime_shared.dart'; + +Uint8List _getBoundary(String boundary) { + final charCodes = boundary.codeUnits; + + final boundaryList = Uint8List(4 + charCodes.length); + // Set-up the matching boundary preceding it with CRLF and two + // dashes. + boundaryList[0] = char_code.cr; + boundaryList[1] = char_code.lf; + boundaryList[2] = char_code.dash; + boundaryList[3] = char_code.dash; + boundaryList.setRange(4, 4 + charCodes.length, charCodes); + return boundaryList; +} + +/// Parser for MIME multipart types of data as described in RFC 2046 +/// section 5.1.1. The data is transformed into [MimeMultipart] objects, each +/// of them streaming the multipart data. +class MimeMultipartTransformer + extends StreamTransformerBase<List<int>, MimeMultipart> { + final List<int> _boundary; + + /// Construct a new MIME multipart parser with the boundary + /// [boundary]. The boundary should be as specified in the content + /// type parameter, that is without the -- prefix. + MimeMultipartTransformer(String boundary) + : _boundary = _getBoundary(boundary); + + @override + Stream<MimeMultipart> bind(Stream<List<int>> stream) => + BoundMultipartStream(_boundary, stream).stream; +}
diff --git a/pkgs/mime/lib/src/mime_shared.dart b/pkgs/mime/lib/src/mime_shared.dart new file mode 100644 index 0000000..1c98971 --- /dev/null +++ b/pkgs/mime/lib/src/mime_shared.dart
@@ -0,0 +1,20 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'mime_multipart_transformer.dart'; + +class MimeMultipartException implements Exception { + final String message; + + const MimeMultipartException([this.message = '']); + + @override + String toString() => 'MimeMultipartException: $message'; +} + +/// A Mime Multipart class representing each part parsed by +/// [MimeMultipartTransformer]. The data is streamed in as it become available. +abstract class MimeMultipart extends Stream<List<int>> { + Map<String, String> get headers; +}
diff --git a/pkgs/mime/lib/src/mime_type.dart b/pkgs/mime/lib/src/mime_type.dart new file mode 100644 index 0000000..9cf9194 --- /dev/null +++ b/pkgs/mime/lib/src/mime_type.dart
@@ -0,0 +1,109 @@ +// Copyright (c) 2013, 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 'default_extension_map.dart'; +import 'magic_number.dart'; + +final MimeTypeResolver _globalResolver = MimeTypeResolver(); + +/// The maximum number of bytes needed, to match all default magic-numbers. +int get defaultMagicNumbersMaxLength => _globalResolver.magicNumbersMaxLength; + +/// Extract the extension from [path] and use that for MIME-type lookup, using +/// the default extension map. +/// +/// If no matching MIME-type was found, `null` is returned. +/// +/// If [headerBytes] is present, a match for known magic-numbers will be +/// performed first. This allows the correct mime-type to be found, even though +/// a file have been saved using the wrong file-name extension. If less than +/// [defaultMagicNumbersMaxLength] bytes was provided, some magic-numbers won't +/// be matched against. +String? lookupMimeType(String path, {List<int>? headerBytes}) => + _globalResolver.lookup(path, headerBytes: headerBytes); + +/// MIME-type resolver class, used to customize the lookup of mime-types. +class MimeTypeResolver { + final Map<String, String> _extensionMap = {}; + final List<MagicNumber> _magicNumbers = []; + final bool _useDefault; + int _magicNumbersMaxLength; + + /// Create a new empty [MimeTypeResolver]. + MimeTypeResolver.empty() + : _useDefault = false, + _magicNumbersMaxLength = 0; + + /// Create a new [MimeTypeResolver] containing the default scope. + MimeTypeResolver() + : _useDefault = true, + _magicNumbersMaxLength = initialMagicNumbersMaxLength; + + /// Get the maximum number of bytes required to match all magic numbers, when + /// performing [lookup] with headerBytes present. + int get magicNumbersMaxLength => _magicNumbersMaxLength; + + /// Extract the extension from [path] and use that for MIME-type lookup. + /// + /// If no matching MIME-type was found, `null` is returned. + /// + /// If [headerBytes] is present, a match for known magic-numbers will be + /// performed first. This allows the correct mime-type to be found, even + /// though a file have been saved using the wrong file-name extension. If less + /// than [magicNumbersMaxLength] bytes was provided, some magic-numbers won't + /// be matched against. + String? lookup(String path, {List<int>? headerBytes}) { + String? result; + if (headerBytes != null) { + result = _matchMagic(headerBytes, _magicNumbers); + if (result != null) return result; + if (_useDefault) { + result = _matchMagic(headerBytes, initialMagicNumbers); + if (result != null) return result; + } + } + final ext = _ext(path); + result = _extensionMap[ext]; + if (result != null) return result; + if (_useDefault) { + result = defaultExtensionMap[ext]; + if (result != null) return result; + } + return null; + } + + /// Add a new MIME-type mapping to the [MimeTypeResolver]. If the [extension] + /// is already present in the [MimeTypeResolver], it'll be overwritten. + void addExtension(String extension, String mimeType) { + _extensionMap[extension] = mimeType; + } + + /// Add a new magic-number mapping to the [MimeTypeResolver]. + /// + /// If [mask] is present,the [mask] is used to only perform matching on + /// selective bits. The [mask] must have the same length as [bytes]. + void addMagicNumber(List<int> bytes, String mimeType, {List<int>? mask}) { + if (mask != null && bytes.length != mask.length) { + throw ArgumentError('Bytes and mask are of different lengths'); + } + if (bytes.length > _magicNumbersMaxLength) { + _magicNumbersMaxLength = bytes.length; + } + _magicNumbers.add(MagicNumber(mimeType, bytes, mask: mask)); + } + + static String? _matchMagic( + List<int> headerBytes, List<MagicNumber> magicNumbers) { + for (var mn in magicNumbers) { + if (mn.matches(headerBytes)) return mn.mimeType; + } + return null; + } + + static String _ext(String path) { + final index = path.lastIndexOf('.'); + if (index < 0 || index + 1 >= path.length) return path; + return path.substring(index + 1).toLowerCase(); + } +}
diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml new file mode 100644 index 0000000..41b3842 --- /dev/null +++ b/pkgs/mime/pubspec.yaml
@@ -0,0 +1,18 @@ +name: mime +version: 2.0.0 +description: >- + Utilities for handling media (MIME) types, including determining a type from + a file extension and file contents. +repository: https://github.com/dart-lang/tools/tree/main/pkgs/mime +topics: + - magic-numbers + - mime + - mimetype + - multipart-form + +environment: + sdk: ^3.2.0 + +dev_dependencies: + dart_flutter_team_lints: ^3.0.0 + test: ^1.16.0
diff --git a/pkgs/mime/test/default_extension_map_test.dart b/pkgs/mime/test/default_extension_map_test.dart new file mode 100644 index 0000000..b5539dd --- /dev/null +++ b/pkgs/mime/test/default_extension_map_test.dart
@@ -0,0 +1,16 @@ +// Copyright (c) 2020, 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:mime/src/default_extension_map.dart'; +import 'package:test/test.dart'; + +void main() { + group('defaultExtensionMap', () { + test('keys are lowercase', () { + for (final key in defaultExtensionMap.keys) { + expect(key, equals(key.toLowerCase())); + } + }); + }); +}
diff --git a/pkgs/mime/test/extension_test.dart b/pkgs/mime/test/extension_test.dart new file mode 100644 index 0000000..40dae6d --- /dev/null +++ b/pkgs/mime/test/extension_test.dart
@@ -0,0 +1,33 @@ +// 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:mime/mime.dart'; +import 'package:test/test.dart'; + +void main() { + test('valid-mime-type', () { + expect(extensionFromMime('text/x-dart'), equals('dart')); + expect(extensionFromMime('text/javascript'), equals('js')); + expect(extensionFromMime('application/java-archive'), equals('jar')); + expect(extensionFromMime('application/json'), equals('json')); + expect(extensionFromMime('application/pdf'), equals('pdf')); + expect(extensionFromMime('application/vnd.ms-excel'), equals('xls')); + expect(extensionFromMime('application/xhtml+xml'), equals('xhtml')); + expect(extensionFromMime('image/jpeg'), equals('jpg')); + expect(extensionFromMime('image/png'), equals('png')); + expect(extensionFromMime('text/css'), equals('css')); + expect(extensionFromMime('text/html'), equals('html')); + expect(extensionFromMime('text/plain'), equals('txt')); + expect(extensionFromMime('text/x-c'), equals('c')); + }); + + test('invalid-mime-type', () { + expect(extensionFromMime('invalid-mime-type'), isNull); + expect(extensionFromMime('invalid/mime/type'), isNull); + }); + + test('unknown-mime-type', () { + expect(extensionFromMime('application/to-be-invented'), isNull); + }); +}
diff --git a/pkgs/mime/test/mime_multipart_transformer_test.dart b/pkgs/mime/test/mime_multipart_transformer_test.dart new file mode 100644 index 0000000..109a9bc --- /dev/null +++ b/pkgs/mime/test/mime_multipart_transformer_test.dart
@@ -0,0 +1,469 @@ +// Copyright (c) 2013, 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:math'; + +import 'package:mime/mime.dart'; +import 'package:test/test.dart'; + +void _writeInChunks( + List<int> data, int chunkSize, StreamController<List<int>> controller) { + if (chunkSize == -1) chunkSize = data.length; + + for (var pos = 0; pos < data.length; pos += chunkSize) { + final remaining = data.length - pos; + final writeLength = min(chunkSize, remaining); + controller.add(data.sublist(pos, pos + writeLength)); + } + controller.close(); +} + +enum TestMode { immediateListen, delayListen, pauseResume } + +void _runParseTest( + String message, + String boundary, + TestMode mode, [ + List<Map<String, String>>? expectedHeaders, + List<String?>? expectedParts, + bool expectError = false, +]) { + Future<void> testWrite(List<int> data, [int chunkSize = -1]) { + final controller = StreamController<List<int>>(sync: true); + + final stream = + controller.stream.transform(MimeMultipartTransformer(boundary)); + var i = 0; + final completer = Completer<void>(); + final futures = <Future<void>>[]; + stream.listen((multipart) { + final part = i++; + if (expectedHeaders != null) { + expect(multipart.headers, equals(expectedHeaders[part])); + } + switch (mode) { + case TestMode.immediateListen: + futures.add(multipart.fold<List<int>>( + [], (buffer, data) => buffer..addAll(data)).then((data) { + if (expectedParts?[part] != null) { + expect(data, equals(expectedParts?[part]!.codeUnits)); + } + })); + + case TestMode.delayListen: + futures.add( + Future( + () => multipart.fold<List<int>>( + [], + (buffer, data) => buffer..addAll(data), + ).then( + (data) { + if (expectedParts?[part] != null) { + expect(data, equals(expectedParts?[part]!.codeUnits)); + } + }, + ), + ), + ); + + case TestMode.pauseResume: + final completer = Completer<void>(); + futures.add(completer.future); + final buffer = <int>[]; + late StreamSubscription<List<int>> subscription; + subscription = multipart.listen((data) { + buffer.addAll(data); + subscription.pause(); + Future(() => subscription.resume()); + }, onDone: () { + if (expectedParts?[part] != null) { + expect(buffer, equals(expectedParts?[part]!.codeUnits)); + } + completer.complete(); + }); + addTearDown(subscription.cancel); + } + }, onError: (Object error) { + // ignore: only_throw_errors + if (!expectError) throw error; + }, onDone: () { + if (expectedParts != null) { + expect(i, equals(expectedParts.length)); + } + Future.wait(futures).then(completer.complete); + }); + + _writeInChunks(data, chunkSize, controller); + + return completer.future; + } + + Future<void> testFirstPartOnly(List<int> data, [int chunkSize = -1]) { + final completer = Completer<void>(); + final controller = StreamController<List<int>>(sync: true); + + final stream = + controller.stream.transform(MimeMultipartTransformer(boundary)); + + stream.first.then((multipart) { + if (expectedHeaders != null) { + expect(multipart.headers, equals(expectedHeaders[0])); + } + return multipart.fold<List<int>>([], (b, d) => b..addAll(d)).then( + (data) { + if (expectedParts != null && expectedParts[0] != null) { + expect(data, equals(expectedParts[0]!.codeUnits)); + } + }, + ); + }).then((_) { + completer.complete(); + }); + + _writeInChunks(data, chunkSize, controller); + + return completer.future; + } + + Future<void> testCompletePartAfterCancel(List<int> data, int parts, + [int chunkSize = -1]) { + final completer = Completer<void>(); + final controller = StreamController<List<int>>(sync: true); + final stream = + controller.stream.transform(MimeMultipartTransformer(boundary)); + late StreamSubscription<void> subscription; + var i = 0; + final futures = <Future<void>>[]; + subscription = stream.listen((multipart) { + final partIndex = i; + + if (partIndex >= parts) { + throw StateError('Expected no more parts, but got one.'); + } + + if (expectedHeaders != null) { + expect(multipart.headers, equals(expectedHeaders[partIndex])); + } + futures.add( + multipart.fold<List<int>>([], (b, d) => b..addAll(d)).then((data) { + if (expectedParts != null && expectedParts[partIndex] != null) { + expect(data, equals(expectedParts[partIndex]!.codeUnits)); + } + })); + + if (partIndex == (parts - 1)) { + subscription.cancel(); + Future.wait(futures).then(completer.complete); + } + i++; + }); + + _writeInChunks(data, chunkSize, controller); + + return completer.future; + } + + // Test parsing the data three times delivering the data in + // different chunks. + final data = message.codeUnits; + test('test', () { + expect( + Future.wait([ + testWrite(data), + testWrite(data, 10), + testWrite(data, 2), + testWrite(data, 1), + ]), + completes); + }); + + if (expectedParts!.isNotEmpty) { + test('test-first-part-only', () { + expect( + Future.wait([ + testFirstPartOnly(data), + testFirstPartOnly(data, 10), + testFirstPartOnly(data, 2), + testFirstPartOnly(data, 1), + ]), + completes); + }); + + test('test-n-parts-only', () { + var numPartsExpected = expectedParts.length - 1; + if (numPartsExpected == 0) numPartsExpected = 1; + + expect( + Future.wait([ + testCompletePartAfterCancel(data, numPartsExpected), + testCompletePartAfterCancel(data, numPartsExpected, 10), + testCompletePartAfterCancel(data, numPartsExpected, 2), + testCompletePartAfterCancel(data, numPartsExpected, 1), + ]), + completes); + }); + } +} + +void _testParse(String message, String boundary, + [List<Map<String, String>>? expectedHeaders, + List<String?>? expectedParts, + bool expectError = false]) { + _runParseTest(message, boundary, TestMode.immediateListen, expectedHeaders, + expectedParts, expectError); + _runParseTest(message, boundary, TestMode.delayListen, expectedHeaders, + expectedParts, expectError); + _runParseTest(message, boundary, TestMode.pauseResume, expectedHeaders, + expectedParts, expectError); +} + +void _testParseValid() { + // Empty message from Chrome form post. + var message = '------WebKitFormBoundaryU3FBruSkJKG0Yor1--\r\n'; + _testParse(message, '----WebKitFormBoundaryU3FBruSkJKG0Yor1', [], []); + + // Sample from Wikipedia. + message = ''' +This is a message with multiple parts in MIME format.\r +--frontier\r +Content-Type: text/plain\r +\r +This is the body of the message.\r +--frontier\r +Content-Type: application/octet-stream\r +Content-Transfer-Encoding: base64\r +\r +PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg +Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg=\r +--frontier--\r\n'''; + var headers1 = <String, String>{'content-type': 'text/plain'}; + var headers2 = <String, String>{ + 'content-type': 'application/octet-stream', + 'content-transfer-encoding': 'base64' + }; + var body1 = 'This is the body of the message.'; + var body2 = ''' +PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg +Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg='''; + _testParse(message, 'frontier', [headers1, headers2], [body1, body2]); + + // Sample from HTML 4.01 Specification. + message = ''' +\r\n--AaB03x\r +Content-Disposition: form-data; name="submit-name"\r +\r +Larry\r +--AaB03x\r +Content-Disposition: form-data; name="files"; filename="file1.txt"\r +Content-Type: text/plain\r +\r +... contents of file1.txt ...\r +--AaB03x--\r\n'''; + headers1 = <String, String>{ + 'content-disposition': 'form-data; name="submit-name"' + }; + headers2 = <String, String>{ + 'content-type': 'text/plain', + 'content-disposition': 'form-data; name="files"; filename="file1.txt"' + }; + body1 = 'Larry'; + body2 = '... contents of file1.txt ...'; + _testParse(message, 'AaB03x', [headers1, headers2], [body1, body2]); + + // Longer form from submitting the following from Chrome. + // + // <html> + // <body> + // <FORM action="http://127.0.0.1:1234/" + // enctype="multipart/form-data" + // method='post'> + // <P> + // Text: <INPUT type='text' name='text_input'> + // Password: <INPUT type='password' name='password_input'> + // Checkbox: <INPUT type='checkbox' name='checkbox_input'> + // Radio: <INPUT type='radio' name='radio_input'> + // Send <INPUT type='submit'> + // </P> + // </FORM> + // </body> + // </html> + + message = ''' +\r\n------WebKitFormBoundaryQ3cgYAmGRF8yOeYB\r +Content-Disposition: form-data; name="text_input"\r +\r +text\r +------WebKitFormBoundaryQ3cgYAmGRF8yOeYB\r +Content-Disposition: form-data; name="password_input"\r +\r +password\r +------WebKitFormBoundaryQ3cgYAmGRF8yOeYB\r +Content-Disposition: form-data; name="checkbox_input"\r +\r +on\r +------WebKitFormBoundaryQ3cgYAmGRF8yOeYB\r +Content-Disposition: form-data; name="radio_input"\r +\r +on\r +------WebKitFormBoundaryQ3cgYAmGRF8yOeYB--\r\n'''; + headers1 = <String, String>{ + 'content-disposition': 'form-data; name="text_input"' + }; + headers2 = <String, String>{ + 'content-disposition': 'form-data; name="password_input"' + }; + final headers3 = <String, String>{ + 'content-disposition': 'form-data; name="checkbox_input"' + }; + final headers4 = <String, String>{ + 'content-disposition': 'form-data; name="radio_input"' + }; + body1 = 'text'; + body2 = 'password'; + const body3 = 'on'; + const body4 = 'on'; + _testParse(message, '----WebKitFormBoundaryQ3cgYAmGRF8yOeYB', + [headers1, headers2, headers3, headers4], [body1, body2, body3, body4]); + + // Same form from Firefox. + message = ''' +\r\n-----------------------------52284550912143824192005403738\r +Content-Disposition: form-data; name="text_input"\r +\r +text\r +-----------------------------52284550912143824192005403738\r +Content-Disposition: form-data; name="password_input"\r +\r +password\r +-----------------------------52284550912143824192005403738\r +Content-Disposition: form-data; name="checkbox_input"\r +\r +on\r +-----------------------------52284550912143824192005403738\r +Content-Disposition: form-data; name="radio_input"\r +\r +on\r +-----------------------------52284550912143824192005403738--\r\n'''; + _testParse( + message, + '---------------------------52284550912143824192005403738', + [headers1, headers2, headers3, headers4], + [body1, body2, body3, body4]); + + // And Internet Explorer + message = ''' +\r\n-----------------------------7dc8f38c60326\r +Content-Disposition: form-data; name="text_input"\r +\r +text\r +-----------------------------7dc8f38c60326\r +Content-Disposition: form-data; name="password_input"\r +\r +password\r +-----------------------------7dc8f38c60326\r +Content-Disposition: form-data; name="checkbox_input"\r +\r +on\r +-----------------------------7dc8f38c60326\r +Content-Disposition: form-data; name="radio_input"\r +\r +on\r +-----------------------------7dc8f38c60326--\r\n'''; + _testParse(message, '---------------------------7dc8f38c60326', + [headers1, headers2, headers3, headers4], [body1, body2, body3, body4]); + + // Test boundary prefix inside prefix and content. + message = ''' +-\r +--\r +--b\r +--bo\r +--bou\r +--boun\r +--bound\r +--bounda\r +--boundar\r +--boundary\r +Content-Type: text/plain\r +\r +-\r +--\r +--b\r +--bo\r +--bou\r +--boun\r +--bound\r\r +--bounda\r\r\r +--boundar\r\r\r\r +--boundary\r +Content-Type: text/plain\r +\r +--boundar\r +--bounda\r +--bound\r +--boun\r +--bou\r +--bo\r +--b\r\r\r\r +--\r\r\r +-\r\r +--boundary--\r\n'''; + final headers = <String, String>{'content-type': 'text/plain'}; + body1 = ''' +-\r +--\r +--b\r +--bo\r +--bou\r +--boun\r +--bound\r\r +--bounda\r\r\r +--boundar\r\r\r'''; + body2 = ''' +--boundar\r +--bounda\r +--bound\r +--boun\r +--bou\r +--bo\r +--b\r\r\r\r +--\r\r\r +-\r'''; + _testParse(message, 'boundary', [headers, headers], [body1, body2]); + + // Without initial CRLF. + message = ''' +--xxx\r +\r +\r +Body 1\r +--xxx\r +\r +\r +Body2\r +--xxx--\r\n'''; + _testParse(message, 'xxx', null, ['\r\nBody 1', '\r\nBody2']); +} + +void _testParseInvalid() { + // Missing end boundary. + const message = ''' +\r +--xxx\r +\r +\r +Body 1\r +--xxx\r +\r +\r +Body2\r +--xxx\r\n'''; + _testParse(message, 'xxx', null, [null, null], true); +} + +void main() { + _testParseValid(); + _testParseInvalid(); +}
diff --git a/pkgs/mime/test/mime_type_test.dart b/pkgs/mime/test/mime_type_test.dart new file mode 100644 index 0000000..23cb34a --- /dev/null +++ b/pkgs/mime/test/mime_type_test.dart
@@ -0,0 +1,320 @@ +// Copyright (c) 2013, 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' as math; + +import 'package:mime/mime.dart'; +import 'package:mime/src/magic_number.dart'; +import 'package:test/test.dart'; + +void _expectMimeType(String path, String? expectedMimeType, + {List<int>? headerBytes, MimeTypeResolver? resolver}) { + String? mimeType; + if (resolver == null) { + mimeType = lookupMimeType(path, headerBytes: headerBytes); + } else { + mimeType = resolver.lookup(path, headerBytes: headerBytes); + } + + expect(mimeType, expectedMimeType); +} + +void main() { + group('global-lookup', () { + test('by-path', () { + _expectMimeType('file.dart', 'text/x-dart'); + // Test mixed-case + _expectMimeType('file.DaRT', 'text/x-dart'); + _expectMimeType('file.dcm', 'application/dicom'); + _expectMimeType('file.html', 'text/html'); + _expectMimeType('file.xhtml', 'application/xhtml+xml'); + _expectMimeType('file.jpeg', 'image/jpeg'); + _expectMimeType('file.jpg', 'image/jpeg'); + _expectMimeType('file.png', 'image/png'); + _expectMimeType('file.gif', 'image/gif'); + _expectMimeType('file.cc', 'text/x-c'); + _expectMimeType('file.c', 'text/x-c'); + _expectMimeType('file.css', 'text/css'); + _expectMimeType('file.js', 'text/javascript'); + _expectMimeType('file.mjs', 'text/javascript'); + _expectMimeType('file.ps', 'application/postscript'); + _expectMimeType('file.pdf', 'application/pdf'); + _expectMimeType('file.tiff', 'image/tiff'); + _expectMimeType('file.tif', 'image/tiff'); + _expectMimeType('file.webp', 'image/webp'); + _expectMimeType('file.mp3', 'audio/mpeg'); + _expectMimeType('file.aac', 'audio/aac'); + _expectMimeType('file.ogg', 'audio/ogg'); + _expectMimeType('file.aiff', 'audio/x-aiff'); + _expectMimeType('file.m4a', 'audio/mp4'); + _expectMimeType('file.m4b', 'audio/mp4'); + _expectMimeType('file.toml', 'application/toml'); + _expectMimeType('file.md', 'text/markdown'); + _expectMimeType('file.markdown', 'text/markdown'); + _expectMimeType('file.heif', 'image/heif'); + _expectMimeType('file.heic', 'image/heic'); + }); + + test('unknown-mime-type', () { + _expectMimeType('file.unsupported-extension', null); + }); + + test('by-header-bytes', () { + _expectMimeType('file.jpg', 'image/png', + headerBytes: [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]); + _expectMimeType('file.jpg', 'image/gif', headerBytes: [ + 0x47, + 0x49, + 0x46, + 0x38, + 0x39, + 0x61, + 0x0D, + 0x0A, + 0x1A, + 0x0A + ]); + _expectMimeType('file.gif', 'image/jpeg', headerBytes: [ + 0xFF, + 0xD8, + 0x46, + 0x38, + 0x39, + 0x61, + 0x0D, + 0x0A, + 0x1A, + 0x0A + ]); + _expectMimeType('file', 'video/3gpp', headerBytes: [ + 0x00, + 0x00, + 0x00, + 0x04, + 0x66, + 0x74, + 0x79, + 0x70, + 0x33, + 0x67, + 0x70, + 0x35 + ]); + _expectMimeType('file.mp4', 'video/mp4', headerBytes: [ + 0x00, + 0x00, + 0x00, + 0x04, + 0x66, + 0x74, + 0x79, + 0x70, + 0xFF, + 0xFF, + 0xFF, + 0xFF + ]); + _expectMimeType('file', 'video/mp4', headerBytes: [ + 0x00, + 0xF0, + 0xF0, + 0xF0, + 0x66, + 0x74, + 0x79, + 0x70, + 0x61, + 0x76, + 0x63, + 0x31 + ]); + _expectMimeType('file', 'video/mp4', headerBytes: [ + 0x00, + 0xF0, + 0xF0, + 0xF0, + 0x66, + 0x74, + 0x79, + 0x70, + 0x69, + 0x73, + 0x6F, + 0x32 + ]); + _expectMimeType('file', 'video/mp4', headerBytes: [ + 0x00, + 0xF0, + 0xF0, + 0xF0, + 0x66, + 0x74, + 0x79, + 0x70, + 0x69, + 0x73, + 0x6F, + 0x6D + ]); + _expectMimeType('file', 'video/mp4', headerBytes: [ + 0x00, + 0xF0, + 0xF0, + 0xF0, + 0x66, + 0x74, + 0x79, + 0x70, + 0x6D, + 0x70, + 0x34, + 0x31 + ]); + _expectMimeType('file', 'video/mp4', headerBytes: [ + 0x00, + 0xF0, + 0xF0, + 0xF0, + 0x66, + 0x74, + 0x79, + 0x70, + 0x6D, + 0x70, + 0x34, + 0x32 + ]); + _expectMimeType('file', 'image/webp', headerBytes: [ + 0x52, + 0x49, + 0x46, + 0x46, + 0xE2, + 0x4A, + 0x01, + 0x00, + 0x57, + 0x45, + 0x42, + 0x50 + ]); + _expectMimeType('file', 'audio/mpeg', + headerBytes: [0x49, 0x44, 0x33, 0x0D, 0x0A, 0x1A, 0x0A]); + _expectMimeType('file', 'audio/aac', + headerBytes: [0xFF, 0xF1, 0x0D, 0x0A, 0x1A, 0x0A]); + _expectMimeType('file', 'audio/ogg', + headerBytes: [0x4F, 0x70, 0x75, 0x0D, 0x0A, 0x1A, 0x0A]); + _expectMimeType('file', 'audio/x-aiff', headerBytes: [ + 0x46, + 0x4F, + 0x52, + 0x4D, + 0x04, + 0x0B, + 0xEF, + 0xF4, + 0x41, + 0x49, + 0x46, + 0x46 + ]); + _expectMimeType('file', 'audio/x-flac', + headerBytes: [0x66, 0x4C, 0x61, 0x43]); + _expectMimeType('file', 'audio/x-wav', headerBytes: [ + 0x52, + 0x49, + 0x46, + 0x46, + 0xA6, + 0x4E, + 0x70, + 0x03, + 0x57, + 0x41, + 0x56, + 0x45 + ]); + _expectMimeType('file', 'image/heic', headerBytes: [ + 0x00, + 0x00, + 0x00, + 0x18, + 0x66, + 0x74, + 0x79, + 0x70, + 0x68, + 0x65, + 0x69, + 0x63, + 0x00 + ]); + _expectMimeType('file', 'image/heic', headerBytes: [ + 0x00, + 0x00, + 0x00, + 0x18, + 0x66, + 0x74, + 0x79, + 0x70, + 0x68, + 0x65, + 0x69, + 0x78, + 0x00 + ]); + _expectMimeType('file', 'image/heif', headerBytes: [ + 0x00, + 0x00, + 0x00, + 0x18, + 0x66, + 0x74, + 0x79, + 0x70, + 0x6D, + 0x69, + 0x66, + 0x31, + 0x00 + ]); + }); + }); + + group('custom-resolver', () { + test('override-extension', () { + final resolver = MimeTypeResolver(); + resolver.addExtension('jpg', 'my-mime-type'); + _expectMimeType('file.jpg', 'my-mime-type', resolver: resolver); + }); + + test('fallthrough-extension', () { + final resolver = MimeTypeResolver(); + resolver.addExtension('jpg2', 'my-mime-type'); + _expectMimeType('file.jpg', 'image/jpeg', resolver: resolver); + }); + + test('with-mask', () { + final resolver = MimeTypeResolver.empty(); + resolver.addMagicNumber([0x01, 0x02, 0x03], 'my-mime-type', + mask: [0x01, 0xFF, 0xFE]); + _expectMimeType('file', 'my-mime-type', + headerBytes: [0x01, 0x02, 0x03], resolver: resolver); + _expectMimeType('file', null, + headerBytes: [0x01, 0x03, 0x03], resolver: resolver); + _expectMimeType('file', 'my-mime-type', + headerBytes: [0xFF, 0x02, 0x02], resolver: resolver); + }); + }); + + test('default magic number', () { + final actualMaxBytes = initialMagicNumbers.fold<int>( + 0, + (previous, magic) => math.max(previous, magic.numbers.length), + ); + + expect(initialMagicNumbersMaxLength, actualMaxBytes); + }); +}
diff --git a/pkgs/oauth2/.gitignore b/pkgs/oauth2/.gitignore new file mode 100644 index 0000000..bbe1007 --- /dev/null +++ b/pkgs/oauth2/.gitignore
@@ -0,0 +1,16 @@ +# Don’t commit the following directories created by pub. +.buildlog +.pub/ +.dart_tool/ +build/ +packages +.packages + +# Or the files created by dart2js. +*.dart.js +*.js_ +*.js.deps +*.js.map + +# Include when developing application packages. +pubspec.lock \ No newline at end of file
diff --git a/pkgs/oauth2/CHANGELOG.md b/pkgs/oauth2/CHANGELOG.md new file mode 100644 index 0000000..ff39de3 --- /dev/null +++ b/pkgs/oauth2/CHANGELOG.md
@@ -0,0 +1,135 @@ +## 2.0.4-wip + +* Require Dart 3.4 + +## 2.0.3 + +* Require `package:http` v1.0.0 +* Move to `dart-lang/tools`. + +## 2.0.2 + +* Require Dart 3.0. +* Support `package:http` 1.0.0. + +## 2.0.1 + +* Handle `expires_in` when encoded as string. +* Populate the pubspec `repository` field. +* Increase the minimum Dart SDK to `2.17.0`. + +## 2.0.0 + +* Migrate to null safety. + +## 1.6.3 + +* Added optional `codeVerifier` parameter to `AuthorizationCodeGrant` constructor. + +## 1.6.1 + +* Added fix to make sure that credentials are only refreshed once when multiple calls are made. + +## 1.6.0 + +* Added PKCE support to `AuthorizationCodeGrant`. + +## 1.5.0 + +* Added support for `clientCredentialsGrant`. + +## 1.4.0 + +* OpenID's id_token treated. + +## 1.3.0 + +* Added `onCredentialsRefreshed` option when creating `Client` objects. + +## 1.2.3 + +* Support the latest `package:http` release. + +## 1.2.2 + +* Allow the stable 2.0 SDK. + +## 1.2.1 + +* Updated SDK version to 2.0.0-dev.17.0 + +## 1.2.0 + +* Add a `getParameter()` parameter to `new AuthorizationCodeGrant()`, `new + Credentials()`, and `resourceOwnerPasswordGrant()`. This controls how the + authorization server's response is parsed for servers that don't provide the + standard JSON response. + +## 1.1.1 + +* `resourceOwnerPasswordGrant()` now properly uses its HTTP client for requests + made by the OAuth2 client it returns. + +## 1.1.0 + +* Add a `delimiter` parameter to `new AuthorizationCodeGrant()`, `new + Credentials()`, and `resourceOwnerPasswordGrant()`. This controls the + delimiter between scopes, which some authorization servers require to be + different values than the specified `' '`. + +## 1.0.2 + +* Fix all strong-mode warnings. +* Support `crypto` 1.0.0. +* Support `http_parser` 3.0.0. + +## 1.0.1 + +* Support `http_parser` 2.0.0. + +## 1.0.0 + +### Breaking changes + +* Requests that use client authentication, such as the + `AuthorizationCodeGrant`'s access token request and `Credentials`' refresh + request, now use HTTP Basic authentication by default. This form of + authentication is strongly recommended by the OAuth 2.0 spec. The new + `basicAuth` parameter may be set to `false` to force form-based authentication + for servers that require it. + +* `new AuthorizationCodeGrant()` now takes `secret` as an optional named + argument rather than a required argument. This matches the OAuth 2.0 spec, + which says that a client secret is only required for confidential clients. + +* `new Client()` and `Credentials.refresh()` now take both `identifier` and + `secret` as optional named arguments rather than required arguments. This + matches the OAuth 2.0 spec, which says that the server may choose not to + require client authentication for some flows. + +* `new Credentials()` now takes named arguments rather than optional positional + arguments. + +### Non-breaking changes + +* Added a `resourceOwnerPasswordGrant` method. + +* The `scopes` argument to `AuthorizationCodeGrant.getAuthorizationUrl()` and + `new Credentials()` and the `newScopes` argument to `Credentials.refresh` now + take an `Iterable` rather than just a `List`. + +* The `scopes` argument to `AuthorizationCodeGrant.getAuthorizationUrl()` now + defaults to `null` rather than `const []`. + +# 0.9.3 + +* Update the `http` dependency. + +* Since `http` 0.11.0 now works in non-`dart:io` contexts, `oauth2` does as + well. + +## 0.9.2 + +* Expand the dependency on the HTTP package to include 0.10.x. + +* Add a README file.
diff --git a/pkgs/oauth2/LICENSE b/pkgs/oauth2/LICENSE new file mode 100644 index 0000000..162572a --- /dev/null +++ b/pkgs/oauth2/LICENSE
@@ -0,0 +1,27 @@ +Copyright 2014, the Dart project authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google LLC nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/pkgs/oauth2/README.md b/pkgs/oauth2/README.md new file mode 100644 index 0000000..07a5976 --- /dev/null +++ b/pkgs/oauth2/README.md
@@ -0,0 +1,260 @@ +[](https://github.com/dart-lang/tools/actions/workflows/oauth2.yml) +[](https://pub.dev/packages/oauth2) +[](https://pub.dev/packages/oauth2/publisher) + +A client library for authenticating with a remote service via OAuth2 on behalf +of a user, and making authorized HTTP requests with the user's OAuth2 +credentials. + +## About OAuth2 + +OAuth2 allows a client (the program using this library) to access and manipulate +a resource that's owned by a resource owner (the end user) and lives on a remote +server. The client directs the resource owner to an authorization server +(usually but not always the same as the server that hosts the resource), where +the resource owner tells the authorization server to give the client an access +token. This token serves as proof that the client has permission to access +resources on behalf of the resource owner. + +OAuth2 provides several different methods for the client to obtain +authorization. At the time of writing, this library only supports the +[Authorization Code Grant][authorizationCodeGrantSection], +[Client Credentials Grant][clientCredentialsGrantSection] and +[Resource Owner Password Grant][resourceOwnerPasswordGrantSection] flows, but +more may be added in the future. + +## Authorization Code Grant + +**Resources:** [Class summary][authorizationCodeGrantMethod], +[OAuth documentation][authorizationCodeGrantDocs] + +```dart +import 'dart:io'; + +import 'package:oauth2/oauth2.dart' as oauth2; + +// These URLs are endpoints that are provided by the authorization +// server. They're usually included in the server's documentation of its +// OAuth2 API. +final authorizationEndpoint = + Uri.parse('http://example.com/oauth2/authorization'); +final tokenEndpoint = Uri.parse('http://example.com/oauth2/token'); + +// The authorization server will issue each client a separate client +// identifier and secret, which allows the server to tell which client +// is accessing it. Some servers may also have an anonymous +// identifier/secret pair that any client may use. +// +// Note that clients whose source code or binary executable is readily +// available may not be able to make sure the client secret is kept a +// secret. This is fine; OAuth2 servers generally won't rely on knowing +// with certainty that a client is who it claims to be. +final identifier = 'my client identifier'; +final secret = 'my client secret'; + +// This is a URL on your application's server. The authorization server +// will redirect the resource owner here once they've authorized the +// client. The redirection will include the authorization code in the +// query parameters. +final redirectUrl = Uri.parse('http://my-site.com/oauth2-redirect'); + +/// A file in which the users credentials are stored persistently. If the server +/// issues a refresh token allowing the client to refresh outdated credentials, +/// these may be valid indefinitely, meaning the user never has to +/// re-authenticate. +final credentialsFile = File('~/.myapp/credentials.json'); + +/// Either load an OAuth2 client from saved credentials or authenticate a new +/// one. +Future<oauth2.Client> createClient() async { + var exists = await credentialsFile.exists(); + + // If the OAuth2 credentials have already been saved from a previous run, we + // just want to reload them. + if (exists) { + var credentials = + oauth2.Credentials.fromJson(await credentialsFile.readAsString()); + return oauth2.Client(credentials, identifier: identifier, secret: secret); + } + + // If we don't have OAuth2 credentials yet, we need to get the resource owner + // to authorize us. We're assuming here that we're a command-line application. + var grant = oauth2.AuthorizationCodeGrant( + identifier, authorizationEndpoint, tokenEndpoint, + secret: secret); + + // A URL on the authorization server (authorizationEndpoint with some additional + // query parameters). Scopes and state can optionally be passed into this method. + var authorizationUrl = grant.getAuthorizationUrl(redirectUrl); + + // Redirect the resource owner to the authorization URL. Once the resource + // owner has authorized, they'll be redirected to `redirectUrl` with an + // authorization code. The `redirect` should cause the browser to redirect to + // another URL which should also have a listener. + // + // `redirect` and `listen` are not shown implemented here. See below for the + // details. + await redirect(authorizationUrl); + var responseUrl = await listen(redirectUrl); + + // Once the user is redirected to `redirectUrl`, pass the query parameters to + // the AuthorizationCodeGrant. It will validate them and extract the + // authorization code to create a new Client. + return await grant.handleAuthorizationResponse(responseUrl.queryParameters); +} + +void main() async { + var client = await createClient(); + + // Once you have a Client, you can use it just like any other HTTP client. + print(await client.read('http://example.com/protected-resources.txt')); + + // Once we're done with the client, save the credentials file. This ensures + // that if the credentials were automatically refreshed while using the + // client, the new credentials are available for the next run of the + // program. + await credentialsFile.writeAsString(client.credentials.toJson()); +} +``` + +<details> + <summary>Click here to learn how to implement `redirect` and `listen`.</summary> + +-------------------------------------------------------------------------------- + +There is not a universal example for implementing `redirect` and `listen`, +because different options exist for each platform. + +For Flutter apps, there's two popular approaches: + +1. Launch a browser using [url_launcher][] and listen for a redirect using + [uni_links][]. + + ```dart + if (await canLaunch(authorizationUrl.toString())) { + await launch(authorizationUrl.toString()); } + + // ------- 8< ------- + + final linksStream = getLinksStream().listen((Uri uri) async { + if (uri.toString().startsWith(redirectUrl)) { + responseUrl = uri; + } + }); + ``` + +1. Launch a WebView inside the app and listen for a redirect using + [webview_flutter][]. + + ```dart + WebView( + javascriptMode: JavascriptMode.unrestricted, + initialUrl: authorizationUrl.toString(), + navigationDelegate: (navReq) { + if (navReq.url.startsWith(redirectUrl)) { + responseUrl = Uri.parse(navReq.url); + return NavigationDecision.prevent; + } + return NavigationDecision.navigate; + }, + // ------- 8< ------- + ); + ``` + +For Dart apps, the best approach depends on the available options for accessing +a browser. In general, you'll need to launch the authorization URL through the +client's browser and listen for the redirect URL. +</details> + +## Client Credentials Grant + +**Resources:** [Method summary][clientCredentialsGrantMethod], +[OAuth documentation][clientCredentialsGrantDocs] + +```dart +// This URL is an endpoint that's provided by the authorization server. It's +// usually included in the server's documentation of its OAuth2 API. +final authorizationEndpoint = + Uri.parse('http://example.com/oauth2/authorization'); + +// The OAuth2 specification expects a client's identifier and secret +// to be sent when using the client credentials grant. +// +// Because the client credentials grant is not inherently associated with a user, +// it is up to the server in question whether the returned token allows limited +// API access. +// +// Either way, you must provide both a client identifier and a client secret: +final identifier = 'my client identifier'; +final secret = 'my client secret'; + +// Calling the top-level `clientCredentialsGrant` function will return a +// [Client] instead. +var client = await oauth2.clientCredentialsGrant( + authorizationEndpoint, identifier, secret); + +// With an authenticated client, you can make requests, and the `Bearer` token +// returned by the server during the client credentials grant will be attached +// to any request you make. +var response = + await client.read('https://example.com/api/some_resource.json'); + +// You can save the client's credentials, which consists of an access token, and +// potentially a refresh token and expiry date, to a file. This way, subsequent runs +// do not need to reauthenticate, and you can avoid saving the client identifier and +// secret. +await credentialsFile.writeAsString(client.credentials.toJson()); +``` + +## Resource Owner Password Grant + +**Resources:** [Method summary][resourceOwnerPasswordGrantMethod], +[OAuth documentation][resourceOwnerPasswordGrantDocs] + +```dart +// This URL is an endpoint that's provided by the authorization server. It's +// usually included in the server's documentation of its OAuth2 API. +final authorizationEndpoint = + Uri.parse('http://example.com/oauth2/authorization'); + +// The user should supply their own username and password. +final username = 'example user'; +final password = 'example password'; + +// The authorization server may issue each client a separate client +// identifier and secret, which allows the server to tell which client +// is accessing it. Some servers may also have an anonymous +// identifier/secret pair that any client may use. +// +// Some servers don't require the client to authenticate itself, in which case +// these should be omitted. +final identifier = 'my client identifier'; +final secret = 'my client secret'; + +// Make a request to the authorization endpoint that will produce the fully +// authenticated Client. +var client = await oauth2.resourceOwnerPasswordGrant( + authorizationEndpoint, username, password, + identifier: identifier, secret: secret); + +// Once you have the client, you can use it just like any other HTTP client. +var result = await client.read('http://example.com/protected-resources.txt'); + +// Once we're done with the client, save the credentials file. This will allow +// us to re-use the credentials and avoid storing the username and password +// directly. +File('~/.myapp/credentials.json').writeAsString(client.credentials.toJson()); +``` + +[authorizationCodeGrantDocs]: https://oauth.net/2/grant-types/authorization-code/ +[authorizationCodeGrantMethod]: https://pub.dev/documentation/oauth2/latest/oauth2/AuthorizationCodeGrant-class.html +[authorizationCodeGrantSection]: #authorization-code-grant +[clientCredentialsGrantDocs]: https://oauth.net/2/grant-types/client-credentials/ +[clientCredentialsGrantMethod]: https://pub.dev/documentation/oauth2/latest/oauth2/clientCredentialsGrant.html +[clientCredentialsGrantSection]: #client-credentials-grant +[resourceOwnerPasswordGrantDocs]: https://oauth.net/2/grant-types/password/ +[resourceOwnerPasswordGrantMethod]: https://pub.dev/documentation/oauth2/latest/oauth2/resourceOwnerPasswordGrant.html +[resourceOwnerPasswordGrantSection]: #resource-owner-password-grant +[uni_links]: https://pub.dev/packages/uni_links +[url_launcher]: https://pub.dev/packages/url_launcher +[webview_flutter]: https://pub.dev/packages/webview_flutter
diff --git a/pkgs/oauth2/analysis_options.yaml b/pkgs/oauth2/analysis_options.yaml new file mode 100644 index 0000000..e21412c --- /dev/null +++ b/pkgs/oauth2/analysis_options.yaml
@@ -0,0 +1,23 @@ +include: package:dart_flutter_team_lints/analysis_options.yaml + +analyzer: + errors: + # Too many exceptions + comment_references: ignore + language: + strict-casts: true + strict-raw-types: true + +linter: + rules: + - avoid_private_typedef_functions + - avoid_unused_constructor_parameters + - avoid_void_async + - cancel_subscriptions + - literal_only_boolean_expressions + - no_adjacent_strings_in_list + - no_runtimeType_toString + - package_api_docs + - prefer_const_declarations + - unnecessary_await_in_return + - use_string_buffers
diff --git a/pkgs/oauth2/example/main.dart b/pkgs/oauth2/example/main.dart new file mode 100644 index 0000000..68e5aa0 --- /dev/null +++ b/pkgs/oauth2/example/main.dart
@@ -0,0 +1,100 @@ +// 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:oauth2/oauth2.dart' as oauth2; + +// These URLs are endpoints that are provided by the authorization +// server. They're usually included in the server's documentation of its +// OAuth2 API. +final authorizationEndpoint = + Uri.parse('http://example.com/oauth2/authorization'); +final tokenEndpoint = Uri.parse('http://example.com/oauth2/token'); + +// The authorization server will issue each client a separate client +// identifier and secret, which allows the server to tell which client +// is accessing it. Some servers may also have an anonymous +// identifier/secret pair that any client may use. +// +// Note that clients whose source code or binary executable is readily +// available may not be able to make sure the client secret is kept a +// secret. This is fine; OAuth2 servers generally won't rely on knowing +// with certainty that a client is who it claims to be. +const identifier = 'my client identifier'; +const secret = 'my client secret'; + +// This is a URL on your application's server. The authorization server +// will redirect the resource owner here once they've authorized the +// client. The redirection will include the authorization code in the +// query parameters. +final redirectUrl = Uri.parse('http://my-site.com/oauth2-redirect'); + +/// A file in which the users credentials are stored persistently. If the server +/// issues a refresh token allowing the client to refresh outdated credentials, +/// these may be valid indefinitely, meaning the user never has to +/// re-authenticate. +final credentialsFile = File('~/.myapp/credentials.json'); + +/// Either load an OAuth2 client from saved credentials or authenticate a new +/// one. +Future<oauth2.Client> createClient() async { + var exists = await credentialsFile.exists(); + + // If the OAuth2 credentials have already been saved from a previous run, we + // just want to reload them. + if (exists) { + var credentials = + oauth2.Credentials.fromJson(await credentialsFile.readAsString()); + return oauth2.Client(credentials, identifier: identifier, secret: secret); + } + + // If we don't have OAuth2 credentials yet, we need to get the resource owner + // to authorize us. We're assuming here that we're a command-line application. + var grant = oauth2.AuthorizationCodeGrant( + identifier, authorizationEndpoint, tokenEndpoint, + secret: secret); + + // A URL on the authorization server (authorizationEndpoint with some + // additional query parameters). Scopes and state can optionally be passed + // into this method. + var authorizationUrl = grant.getAuthorizationUrl(redirectUrl); + + // Redirect the resource owner to the authorization URL. Once the resource + // owner has authorized, they'll be redirected to `redirectUrl` with an + // authorization code. The `redirect` should cause the browser to redirect to + // another URL which should also have a listener. + // + // `redirect` and `listen` are not shown implemented here. + await redirect(authorizationUrl); + var responseUrl = await listen(redirectUrl); + + // Once the user is redirected to `redirectUrl`, pass the query parameters to + // the AuthorizationCodeGrant. It will validate them and extract the + // authorization code to create a new Client. + return grant.handleAuthorizationResponse(responseUrl.queryParameters); +} + +void main() async { + var client = await createClient(); + + // Once you have a Client, you can use it just like any other HTTP client. + print(await client.read(Uri.http('example.com', 'protected-resources.txt'))); + + // Once we're done with the client, save the credentials file. This ensures + // that if the credentials were automatically refreshed while using the + // client, the new credentials are available for the next run of the + // program. + await credentialsFile.writeAsString(client.credentials.toJson()); +} + +Future<void> redirect(Uri url) async { + // Client implementation detail +} + +Future<Uri> listen(Uri url) async { + // Client implementation detail + return Uri(); +}
diff --git a/pkgs/oauth2/lib/oauth2.dart b/pkgs/oauth2/lib/oauth2.dart new file mode 100644 index 0000000..45efc5c --- /dev/null +++ b/pkgs/oauth2/lib/oauth2.dart
@@ -0,0 +1,11 @@ +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +export 'src/authorization_code_grant.dart'; +export 'src/authorization_exception.dart'; +export 'src/client.dart'; +export 'src/client_credentials_grant.dart'; +export 'src/credentials.dart'; +export 'src/expiration_exception.dart'; +export 'src/resource_owner_password_grant.dart';
diff --git a/pkgs/oauth2/lib/src/authorization_code_grant.dart b/pkgs/oauth2/lib/src/authorization_code_grant.dart new file mode 100644 index 0000000..fac56ba --- /dev/null +++ b/pkgs/oauth2/lib/src/authorization_code_grant.dart
@@ -0,0 +1,371 @@ +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:convert'; +import 'dart:math'; + +import 'package:crypto/crypto.dart'; +import 'package:http/http.dart' as http; +import 'package:http_parser/http_parser.dart'; + +import 'authorization_exception.dart'; +import 'client.dart'; +import 'credentials.dart'; +import 'handle_access_token_response.dart'; +import 'parameters.dart'; +import 'utils.dart'; + +/// A class for obtaining credentials via an [authorization code grant][]. +/// +/// This method of authorization involves sending the resource owner to the +/// authorization server where they will authorize the client. They're then +/// redirected back to your server, along with an authorization code. This is +/// used to obtain [Credentials] and create a fully-authorized [Client]. +/// +/// To use this class, you must first call [getAuthorizationUrl] to get the URL +/// to which to redirect the resource owner. Then once they've been redirected +/// back to your application, call [handleAuthorizationResponse] or +/// [handleAuthorizationCode] to process the authorization server's response and +/// construct a [Client]. +/// +/// [authorization code grant]: http://tools.ietf.org/html/draft-ietf-oauth-v2-31#section-4.1 +class AuthorizationCodeGrant { + /// The function used to parse parameters from a host's response. + final GetParameters _getParameters; + + /// The client identifier for this client. + /// + /// The authorization server will issue each client a separate client + /// identifier and secret, which allows the server to tell which client is + /// accessing it. Some servers may also have an anonymous identifier/secret + /// pair that any client may use. + /// + /// This is usually global to the program using this library. + final String identifier; + + /// The client secret for this client. + /// + /// The authorization server will issue each client a separate client + /// identifier and secret, which allows the server to tell which client is + /// accessing it. Some servers may also have an anonymous identifier/secret + /// pair that any client may use. + /// + /// This is usually global to the program using this library. + /// + /// Note that clients whose source code or binary executable is readily + /// available may not be able to make sure the client secret is kept a secret. + /// This is fine; OAuth2 servers generally won't rely on knowing with + /// certainty that a client is who it claims to be. + final String? secret; + + /// A URL provided by the authorization server that serves as the base for the + /// URL that the resource owner will be redirected to to authorize this + /// client. + /// + /// This will usually be listed in the authorization server's OAuth2 API + /// documentation. + final Uri authorizationEndpoint; + + /// A URL provided by the authorization server that this library uses to + /// obtain long-lasting credentials. + /// + /// This will usually be listed in the authorization server's OAuth2 API + /// documentation. + final Uri tokenEndpoint; + + /// Callback to be invoked whenever the credentials are refreshed. + /// + /// This will be passed as-is to the constructed [Client]. + final CredentialsRefreshedCallback? _onCredentialsRefreshed; + + /// Whether to use HTTP Basic authentication for authorizing the client. + final bool _basicAuth; + + /// A [String] used to separate scopes; defaults to `" "`. + final String _delimiter; + + /// The HTTP client used to make HTTP requests. + http.Client? _httpClient; + + /// The URL to which the resource owner will be redirected after they + /// authorize this client with the authorization server. + Uri? _redirectEndpoint; + + /// The scopes that the client is requesting access to. + List<String>? _scopes; + + /// An opaque string that users of this library may specify that will be + /// included in the response query parameters. + String? _stateString; + + /// The current state of the grant object. + _State _state = _State.initial; + + /// Allowed characters for generating the _codeVerifier + static const String _charset = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~'; + + /// The PKCE code verifier. Will be generated if one is not provided in the + /// constructor. + final String _codeVerifier; + + /// Creates a new grant. + /// + /// If [basicAuth] is `true` (the default), the client credentials are sent to + /// the server using using HTTP Basic authentication as defined in [RFC 2617]. + /// Otherwise, they're included in the request body. Note that the latter form + /// is not recommended by the OAuth 2.0 spec, and should only be used if the + /// server doesn't support Basic authentication. + /// + /// [RFC 2617]: https://tools.ietf.org/html/rfc2617 + /// + /// [httpClient] is used for all HTTP requests made by this grant, as well as + /// those of the [Client] is constructs. + /// + /// [onCredentialsRefreshed] will be called by the constructed [Client] + /// whenever the credentials are refreshed. + /// + /// [codeVerifier] String to be used as PKCE code verifier. If none is + /// provided a random codeVerifier will be generated. + /// The codeVerifier must meet requirements specified in [RFC 7636]. + /// + /// [RFC 7636]: https://tools.ietf.org/html/rfc7636#section-4.1 + /// + /// The scope strings will be separated by the provided [delimiter]. This + /// defaults to `" "`, the OAuth2 standard, but some APIs (such as Facebook's) + /// use non-standard delimiters. + /// + /// By default, this follows the OAuth2 spec and requires the server's + /// responses to be in JSON format. However, some servers return non-standard + /// response formats, which can be parsed using the [getParameters] function. + /// + /// This function is passed the `Content-Type` header of the response as well + /// as its body as a UTF-8-decoded string. It should return a map in the same + /// format as the [standard JSON response][]. + /// + /// [standard JSON response]: https://tools.ietf.org/html/rfc6749#section-5.1 + AuthorizationCodeGrant( + this.identifier, this.authorizationEndpoint, this.tokenEndpoint, + {this.secret, + String? delimiter, + bool basicAuth = true, + http.Client? httpClient, + CredentialsRefreshedCallback? onCredentialsRefreshed, + Map<String, dynamic> Function(MediaType? contentType, String body)? + getParameters, + String? codeVerifier}) + : _basicAuth = basicAuth, + _httpClient = httpClient ?? http.Client(), + _delimiter = delimiter ?? ' ', + _getParameters = getParameters ?? parseJsonParameters, + _onCredentialsRefreshed = onCredentialsRefreshed, + _codeVerifier = codeVerifier ?? _createCodeVerifier(); + + /// Returns the URL to which the resource owner should be redirected to + /// authorize this client. + /// + /// The resource owner will then be redirected to [redirect], which should + /// point to a server controlled by the client. This redirect will have + /// additional query parameters that should be passed to + /// [handleAuthorizationResponse]. + /// + /// The specific permissions being requested from the authorization server may + /// be specified via [scopes]. The scope strings are specific to the + /// authorization server and may be found in its documentation. Note that you + /// may not be granted access to every scope you request; you may check the + /// [Credentials.scopes] field of [Client.credentials] to see which scopes you + /// were granted. + /// + /// An opaque [state] string may also be passed that will be present in the + /// query parameters provided to the redirect URL. + /// + /// It is a [StateError] to call this more than once. + Uri getAuthorizationUrl(Uri redirect, + {Iterable<String>? scopes, String? state}) { + if (_state != _State.initial) { + throw StateError('The authorization URL has already been generated.'); + } + _state = _State.awaitingResponse; + + var scopeList = scopes?.toList() ?? <String>[]; + var codeChallenge = base64Url + .encode(sha256.convert(ascii.encode(_codeVerifier)).bytes) + .replaceAll('=', ''); + + _redirectEndpoint = redirect; + _scopes = scopeList; + _stateString = state; + var parameters = { + 'response_type': 'code', + 'client_id': identifier, + 'redirect_uri': redirect.toString(), + 'code_challenge': codeChallenge, + 'code_challenge_method': 'S256' + }; + + if (state != null) parameters['state'] = state; + if (scopeList.isNotEmpty) parameters['scope'] = scopeList.join(_delimiter); + + return addQueryParameters(authorizationEndpoint, parameters); + } + + /// Processes the query parameters added to a redirect from the authorization + /// server. + /// + /// Note that this "response" is not an HTTP response, but rather the data + /// passed to a server controlled by the client as query parameters on the + /// redirect URL. + /// + /// It is a [StateError] to call this more than once, to call it before + /// [getAuthorizationUrl] is called, or to call it after + /// [handleAuthorizationCode] is called. + /// + /// Throws [FormatException] if [parameters] is invalid according to the + /// OAuth2 spec or if the authorization server otherwise provides invalid + /// responses. If `state` was passed to [getAuthorizationUrl], this will throw + /// a [FormatException] if the `state` parameter doesn't match the original + /// value. + /// + /// Throws [AuthorizationException] if the authorization fails. + Future<Client> handleAuthorizationResponse( + Map<String, String> parameters) async { + if (_state == _State.initial) { + throw StateError('The authorization URL has not yet been generated.'); + } else if (_state == _State.finished) { + throw StateError('The authorization code has already been received.'); + } + _state = _State.finished; + + if (_stateString != null) { + if (!parameters.containsKey('state')) { + throw FormatException('Invalid OAuth response for ' + '"$authorizationEndpoint": parameter "state" expected to be ' + '"$_stateString", was missing.'); + } else if (parameters['state'] != _stateString) { + throw FormatException('Invalid OAuth response for ' + '"$authorizationEndpoint": parameter "state" expected to be ' + '"$_stateString", was "${parameters['state']}".'); + } + } + + if (parameters.containsKey('error')) { + var description = parameters['error_description']; + var uriString = parameters['error_uri']; + var uri = uriString == null ? null : Uri.parse(uriString); + throw AuthorizationException(parameters['error']!, description, uri); + } else if (!parameters.containsKey('code')) { + throw FormatException('Invalid OAuth response for ' + '"$authorizationEndpoint": did not contain required parameter ' + '"code".'); + } + + return _handleAuthorizationCode(parameters['code']); + } + + /// Processes an authorization code directly. + /// + /// Usually [handleAuthorizationResponse] is preferable to this method, since + /// it validates all of the query parameters. However, some authorization + /// servers allow the user to copy and paste an authorization code into a + /// command-line application, in which case this method must be used. + /// + /// It is a [StateError] to call this more than once, to call it before + /// [getAuthorizationUrl] is called, or to call it after + /// [handleAuthorizationCode] is called. + /// + /// Throws [FormatException] if the authorization server provides invalid + /// responses while retrieving credentials. + /// + /// Throws [AuthorizationException] if the authorization fails. + Future<Client> handleAuthorizationCode(String authorizationCode) async { + if (_state == _State.initial) { + throw StateError('The authorization URL has not yet been generated.'); + } else if (_state == _State.finished) { + throw StateError('The authorization code has already been received.'); + } + _state = _State.finished; + + return _handleAuthorizationCode(authorizationCode); + } + + /// This works just like [handleAuthorizationCode], except it doesn't validate + /// the state beforehand. + Future<Client> _handleAuthorizationCode(String? authorizationCode) async { + var startTime = DateTime.now(); + + var headers = <String, String>{}; + + var body = { + 'grant_type': 'authorization_code', + 'code': authorizationCode, + 'redirect_uri': _redirectEndpoint.toString(), + 'code_verifier': _codeVerifier + }; + + var secret = this.secret; + if (_basicAuth && secret != null) { + headers['Authorization'] = basicAuthHeader(identifier, secret); + } else { + // The ID is required for this request any time basic auth isn't being + // used, even if there's no actual client authentication to be done. + body['client_id'] = identifier; + if (secret != null) body['client_secret'] = secret; + } + + var response = + await _httpClient!.post(tokenEndpoint, headers: headers, body: body); + + var credentials = handleAccessTokenResponse( + response, tokenEndpoint, startTime, _scopes, _delimiter, + getParameters: _getParameters); + return Client(credentials, + identifier: identifier, + secret: secret, + basicAuth: _basicAuth, + httpClient: _httpClient, + onCredentialsRefreshed: _onCredentialsRefreshed); + } + + // Randomly generate a 128 character string to be used as the PKCE code + // verifier. + static String _createCodeVerifier() => List.generate( + 128, + (i) => _charset[Random.secure().nextInt(_charset.length)], + ).join(); + + /// Closes the grant and frees its resources. + /// + /// This will close the underlying HTTP client, which is shared by the + /// [Client] created by this grant, so it's not safe to close the grant and + /// continue using the client. + void close() { + _httpClient?.close(); + _httpClient = null; + } +} + +/// States that [AuthorizationCodeGrant] can be in. +class _State { + /// [AuthorizationCodeGrant.getAuthorizationUrl] has not yet been called for + /// this grant. + static const initial = _State('initial'); + + // [AuthorizationCodeGrant.getAuthorizationUrl] has been called but neither + // [AuthorizationCodeGrant.handleAuthorizationResponse] nor + // [AuthorizationCodeGrant.handleAuthorizationCode] has been called. + static const awaitingResponse = _State('awaiting response'); + + // [AuthorizationCodeGrant.getAuthorizationUrl] and either + // [AuthorizationCodeGrant.handleAuthorizationResponse] or + // [AuthorizationCodeGrant.handleAuthorizationCode] have been called. + static const finished = _State('finished'); + + final String _name; + + const _State(this._name); + + @override + String toString() => _name; +}
diff --git a/pkgs/oauth2/lib/src/authorization_exception.dart b/pkgs/oauth2/lib/src/authorization_exception.dart new file mode 100644 index 0000000..14a5a3c --- /dev/null +++ b/pkgs/oauth2/lib/src/authorization_exception.dart
@@ -0,0 +1,39 @@ +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// An exception raised when OAuth2 authorization fails. +class AuthorizationException implements Exception { + /// The name of the error. + /// + /// Possible names are enumerated in [the spec][]. + /// + /// [the spec]: http://tools.ietf.org/html/draft-ietf-oauth-v2-31#section-5.2 + final String error; + + /// The description of the error, provided by the server. + /// + /// May be `null` if the server provided no description. + final String? description; + + /// A URL for a page that describes the error in more detail, provided by the + /// server. + /// + /// May be `null` if the server provided no URL. + final Uri? uri; + + /// Creates an AuthorizationException. + AuthorizationException(this.error, this.description, this.uri); + + /// Provides a string description of the AuthorizationException. + @override + String toString() { + var header = 'OAuth authorization error ($error)'; + if (description != null) { + header = '$header: $description'; + } else if (uri != null) { + header = '$header: $uri'; + } + return '$header.'; + } +}
diff --git a/pkgs/oauth2/lib/src/client.dart b/pkgs/oauth2/lib/src/client.dart new file mode 100644 index 0000000..1dd2282 --- /dev/null +++ b/pkgs/oauth2/lib/src/client.dart
@@ -0,0 +1,187 @@ +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:collection/collection.dart'; +import 'package:http/http.dart' as http; +import 'package:http_parser/http_parser.dart'; + +import 'authorization_exception.dart'; +import 'credentials.dart'; +import 'expiration_exception.dart'; + +/// An OAuth2 client. +/// +/// This acts as a drop-in replacement for an [http.Client], while sending +/// OAuth2 authorization credentials along with each request. +/// +/// The client also automatically refreshes its credentials if possible. When it +/// makes a request, if its credentials are expired, it will first refresh them. +/// This means that any request may throw an [AuthorizationException] if the +/// refresh is not authorized for some reason, a [FormatException] if the +/// authorization server provides ill-formatted responses, or an +/// [ExpirationException] if the credentials are expired and can't be refreshed. +/// +/// The client will also throw an [AuthorizationException] if the resource +/// server returns a 401 response with a WWW-Authenticate header indicating that +/// the current credentials are invalid. +/// +/// If you already have a set of [Credentials], you can construct a [Client] +/// directly. However, in order to first obtain the credentials, you must +/// authorize. At the time of writing, the only authorization method this +/// library supports is [AuthorizationCodeGrant]. +class Client extends http.BaseClient { + /// The client identifier for this client. + /// + /// The authorization server will issue each client a separate client + /// identifier and secret, which allows the server to tell which client is + /// accessing it. Some servers may also have an anonymous identifier/secret + /// pair that any client may use. + /// + /// This is usually global to the program using this library. + final String? identifier; + + /// The client secret for this client. + /// + /// The authorization server will issue each client a separate client + /// identifier and secret, which allows the server to tell which client is + /// accessing it. Some servers may also have an anonymous identifier/secret + /// pair that any client may use. + /// + /// This is usually global to the program using this library. + /// + /// Note that clients whose source code or binary executable is readily + /// available may not be able to make sure the client secret is kept a secret. + /// This is fine; OAuth2 servers generally won't rely on knowing with + /// certainty that a client is who it claims to be. + final String? secret; + + /// The credentials this client uses to prove to the resource server that it's + /// authorized. + /// + /// This may change from request to request as the credentials expire and the + /// client refreshes them automatically. + Credentials get credentials => _credentials; + Credentials _credentials; + + /// Callback to be invoked whenever the credentials refreshed. + final CredentialsRefreshedCallback? _onCredentialsRefreshed; + + /// Whether to use HTTP Basic authentication for authorizing the client. + final bool _basicAuth; + + /// The underlying HTTP client. + http.Client? _httpClient; + + /// Creates a new client from a pre-existing set of credentials. + /// + /// When authorizing a client for the first time, you should use + /// [AuthorizationCodeGrant] or [resourceOwnerPasswordGrant] instead of + /// constructing a [Client] directly. + /// + /// [httpClient] is the underlying client that this forwards requests to after + /// adding authorization credentials to them. + /// + /// Throws an [ArgumentError] if [secret] is passed without [identifier]. + Client(this._credentials, + {this.identifier, + this.secret, + CredentialsRefreshedCallback? onCredentialsRefreshed, + bool basicAuth = true, + http.Client? httpClient}) + : _basicAuth = basicAuth, + _onCredentialsRefreshed = onCredentialsRefreshed, + _httpClient = httpClient ?? http.Client() { + if (identifier == null && secret != null) { + throw ArgumentError('secret may not be passed without identifier.'); + } + } + + /// Sends an HTTP request with OAuth2 authorization credentials attached. + /// + /// This will also automatically refresh this client's [Credentials] before + /// sending the request if necessary. + @override + Future<http.StreamedResponse> send(http.BaseRequest request) async { + if (credentials.isExpired) { + if (!credentials.canRefresh) throw ExpirationException(credentials); + await refreshCredentials(); + } + + request.headers['authorization'] = 'Bearer ${credentials.accessToken}'; + var response = await _httpClient!.send(request); + + if (response.statusCode != 401) return response; + if (!response.headers.containsKey('www-authenticate')) return response; + + List<AuthenticationChallenge> challenges; + try { + challenges = AuthenticationChallenge.parseHeader( + response.headers['www-authenticate']!); + } on FormatException { + return response; + } + + var challenge = challenges + .firstWhereOrNull((challenge) => challenge.scheme == 'bearer'); + if (challenge == null) return response; + + var params = challenge.parameters; + if (!params.containsKey('error')) return response; + + throw AuthorizationException(params['error']!, params['error_description'], + params['error_uri'] == null ? null : Uri.parse(params['error_uri']!)); + } + + /// A [Future] used to track whether [refreshCredentials] is running. + Future<Credentials>? _refreshingFuture; + + /// Explicitly refreshes this client's credentials. Returns this client. + /// + /// This will throw a [StateError] if the [Credentials] can't be refreshed, an + /// [AuthorizationException] if refreshing the credentials fails, or a + /// [FormatException] if the authorization server returns invalid responses. + /// + /// You may request different scopes than the default by passing in + /// [newScopes]. These must be a subset of the scopes in the + /// [Credentials.scopes] field of [Client.credentials]. + Future<Client> refreshCredentials([List<String>? newScopes]) async { + if (!credentials.canRefresh) { + var prefix = 'OAuth credentials'; + if (credentials.isExpired) prefix = '$prefix have expired and'; + throw StateError("$prefix can't be refreshed."); + } + + // To make sure that only one refresh happens when credentials are expired + // we track it using the [_refreshingFuture]. And also make sure that the + // _onCredentialsRefreshed callback is only called once. + if (_refreshingFuture == null) { + try { + _refreshingFuture = credentials.refresh( + identifier: identifier, + secret: secret, + newScopes: newScopes, + basicAuth: _basicAuth, + httpClient: _httpClient, + ); + _credentials = await _refreshingFuture!; + _onCredentialsRefreshed?.call(_credentials); + } finally { + _refreshingFuture = null; + } + } else { + await _refreshingFuture; + } + + return this; + } + + /// Closes this client and its underlying HTTP client. + @override + void close() { + _httpClient?.close(); + _httpClient = null; + } +}
diff --git a/pkgs/oauth2/lib/src/client_credentials_grant.dart b/pkgs/oauth2/lib/src/client_credentials_grant.dart new file mode 100644 index 0000000..045d1a0 --- /dev/null +++ b/pkgs/oauth2/lib/src/client_credentials_grant.dart
@@ -0,0 +1,79 @@ +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:http/http.dart' as http; +import 'package:http_parser/http_parser.dart'; + +import 'client.dart'; +import 'handle_access_token_response.dart'; +import 'utils.dart'; + +/// Obtains credentials using a [client credentials grant](https://tools.ietf.org/html/rfc6749#section-1.3.4). +/// +/// This mode of authorization uses the client's [identifier] and [secret] +/// to obtain an authorization token from the authorization server, instead +/// of sending a user through a dedicated flow. +/// +/// The client [identifier] and [secret] are required, and are +/// used to identify and authenticate your specific OAuth2 client. These are +/// usually global to the program using this library. +/// +/// The specific permissions being requested from the authorization server may +/// be specified via [scopes]. The scope strings are specific to the +/// authorization server and may be found in its documentation. Note that you +/// may not be granted access to every scope you request; you may check the +/// [Credentials.scopes] field of [Client.credentials] to see which scopes you +/// were granted. +/// +/// The scope strings will be separated by the provided [delimiter]. This +/// defaults to `" "`, the OAuth2 standard, but some APIs (such as Facebook's) +/// use non-standard delimiters. +/// +/// By default, this follows the OAuth2 spec and requires the server's responses +/// to be in JSON format. However, some servers return non-standard response +/// formats, which can be parsed using the [getParameters] function. +/// +/// This function is passed the `Content-Type` header of the response as well as +/// its body as a UTF-8-decoded string. It should return a map in the same +/// format as the [standard JSON response](https://tools.ietf.org/html/rfc6749#section-5.1) +Future<Client> clientCredentialsGrant( + Uri authorizationEndpoint, String? identifier, String? secret, + {Iterable<String>? scopes, + bool basicAuth = true, + http.Client? httpClient, + String? delimiter, + Map<String, dynamic> Function(MediaType? contentType, String body)? + getParameters}) async { + delimiter ??= ' '; + var startTime = DateTime.now(); + + var body = {'grant_type': 'client_credentials'}; + + var headers = <String, String>{}; + + if (identifier != null) { + if (basicAuth) { + headers['Authorization'] = basicAuthHeader(identifier, secret!); + } else { + body['client_id'] = identifier; + if (secret != null) body['client_secret'] = secret; + } + } + + if (scopes != null && scopes.isNotEmpty) { + body['scope'] = scopes.join(delimiter); + } + + httpClient ??= http.Client(); + var response = await httpClient.post(authorizationEndpoint, + headers: headers, body: body); + + var credentials = handleAccessTokenResponse(response, authorizationEndpoint, + startTime, scopes?.toList() ?? [], delimiter, + getParameters: getParameters); + return Client(credentials, + identifier: identifier, secret: secret, httpClient: httpClient); +}
diff --git a/pkgs/oauth2/lib/src/credentials.dart b/pkgs/oauth2/lib/src/credentials.dart new file mode 100644 index 0000000..088b482 --- /dev/null +++ b/pkgs/oauth2/lib/src/credentials.dart
@@ -0,0 +1,267 @@ +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:collection'; +import 'dart:convert'; + +import 'package:http/http.dart' as http; +import 'package:http_parser/http_parser.dart'; + +import 'handle_access_token_response.dart'; +import 'parameters.dart'; +import 'utils.dart'; + +/// Type of the callback when credentials are refreshed. +typedef CredentialsRefreshedCallback = void Function(Credentials); + +/// Credentials that prove that a client is allowed to access a resource on the +/// resource owner's behalf. +/// +/// These credentials are long-lasting and can be safely persisted across +/// multiple runs of the program. +/// +/// Many authorization servers will attach an expiration date to a set of +/// credentials, along with a token that can be used to refresh the credentials +/// once they've expired. The [http.Client] will automatically refresh its +/// credentials when necessary. It's also possible to explicitly refresh them +/// via [http.Client.refreshCredentials] or [Credentials.refresh]. +/// +/// Note that a given set of credentials can only be refreshed once, so be sure +/// to save the refreshed credentials for future use. +class Credentials { + /// A [String] used to separate scopes; defaults to `" "`. + String _delimiter; + + /// The token that is sent to the resource server to prove the authorization + /// of a client. + final String accessToken; + + /// The token that is sent to the authorization server to refresh the + /// credentials. + /// + /// This may be `null`, indicating that the credentials can't be refreshed. + final String? refreshToken; + + /// The token that is received from the authorization server to enable + /// End-Users to be Authenticated, contains Claims, represented as a + /// JSON Web Token (JWT). + /// + /// This may be `null`, indicating that the 'openid' scope was not + /// requested (or not supported). + /// + /// [spec]: https://openid.net/specs/openid-connect-core-1_0.html#IDToken + final String? idToken; + + /// The URL of the authorization server endpoint that's used to refresh the + /// credentials. + /// + /// This may be `null`, indicating that the credentials can't be refreshed. + final Uri? tokenEndpoint; + + /// The specific permissions being requested from the authorization server. + /// + /// The scope strings are specific to the authorization server and may be + /// found in its documentation. + final List<String>? scopes; + + /// The date at which these credentials will expire. + /// + /// This is likely to be a few seconds earlier than the server's idea of the + /// expiration date. + final DateTime? expiration; + + /// The function used to parse parameters from a host's response. + final GetParameters _getParameters; + + /// Whether or not these credentials have expired. + /// + /// Note that it's possible the credentials will expire shortly after this is + /// called. However, since the client's expiration date is kept a few seconds + /// earlier than the server's, there should be enough leeway to rely on this. + bool get isExpired { + var expiration = this.expiration; + return expiration != null && DateTime.now().isAfter(expiration); + } + + /// Whether it's possible to refresh these credentials. + bool get canRefresh => refreshToken != null && tokenEndpoint != null; + + /// Creates a new set of credentials. + /// + /// This class is usually not constructed directly; rather, it's accessed via + /// [Client.credentials] after a [Client] is created by + /// [AuthorizationCodeGrant]. Alternately, it may be loaded from a serialized + /// form via [Credentials.fromJson]. + /// + /// The scope strings will be separated by the provided [delimiter]. This + /// defaults to `" "`, the OAuth2 standard, but some APIs (such as Facebook's) + /// use non-standard delimiters. + /// + /// By default, this follows the OAuth2 spec and requires the server's + /// responses to be in JSON format. However, some servers return non-standard + /// response formats, which can be parsed using the [getParameters] function. + /// + /// This function is passed the `Content-Type` header of the response as well + /// as its body as a UTF-8-decoded string. It should return a map in the same + /// format as the [standard JSON response][]. + /// + /// [standard JSON response]: https://tools.ietf.org/html/rfc6749#section-5.1 + Credentials(this.accessToken, + {this.refreshToken, + this.idToken, + this.tokenEndpoint, + Iterable<String>? scopes, + this.expiration, + String? delimiter, + Map<String, dynamic> Function(MediaType? mediaType, String body)? + getParameters}) + : scopes = UnmodifiableListView( + // Explicitly type-annotate the list literal to work around + // sdk#24202. + scopes == null ? <String>[] : scopes.toList()), + _delimiter = delimiter ?? ' ', + _getParameters = getParameters ?? parseJsonParameters; + + /// Loads a set of credentials from a JSON-serialized form. + /// + /// Throws a [FormatException] if the JSON is incorrectly formatted. + factory Credentials.fromJson(String json) { + void validate(bool condition, String message) { + if (condition) return; + throw FormatException('Failed to load credentials: $message.\n\n$json'); + } + + dynamic parsed; + try { + parsed = jsonDecode(json); + } on FormatException { + validate(false, 'invalid JSON'); + } + + validate(parsed is Map, 'was not a JSON map'); + + parsed = parsed as Map; + validate(parsed.containsKey('accessToken'), + 'did not contain required field "accessToken"'); + validate( + parsed['accessToken'] is String, + 'required field "accessToken" was not a string, was ' + '${parsed["accessToken"]}', + ); + + for (var stringField in ['refreshToken', 'idToken', 'tokenEndpoint']) { + var value = parsed[stringField]; + validate(value == null || value is String, + 'field "$stringField" was not a string, was "$value"'); + } + + var scopes = parsed['scopes']; + validate(scopes == null || scopes is List, + 'field "scopes" was not a list, was "$scopes"'); + + var tokenEndpoint = parsed['tokenEndpoint']; + Uri? tokenEndpointUri; + if (tokenEndpoint != null) { + tokenEndpointUri = Uri.parse(tokenEndpoint as String); + } + + var expiration = parsed['expiration']; + DateTime? expirationDateTime; + if (expiration != null) { + validate(expiration is int, + 'field "expiration" was not an int, was "$expiration"'); + expiration = expiration as int; + expirationDateTime = DateTime.fromMillisecondsSinceEpoch(expiration); + } + + return Credentials( + parsed['accessToken'] as String, + refreshToken: parsed['refreshToken'] as String?, + idToken: parsed['idToken'] as String?, + tokenEndpoint: tokenEndpointUri, + scopes: (scopes as List).map((scope) => scope as String), + expiration: expirationDateTime, + ); + } + + /// Serializes a set of credentials to JSON. + /// + /// Nothing is guaranteed about the output except that it's valid JSON and + /// compatible with [Credentials.toJson]. + String toJson() => jsonEncode({ + 'accessToken': accessToken, + 'refreshToken': refreshToken, + 'idToken': idToken, + 'tokenEndpoint': tokenEndpoint?.toString(), + 'scopes': scopes, + 'expiration': expiration?.millisecondsSinceEpoch + }); + + /// Returns a new set of refreshed credentials. + /// + /// See [Client.identifier] and [Client.secret] for explanations of those + /// parameters. + /// + /// You may request different scopes than the default by passing in + /// [newScopes]. These must be a subset of [scopes]. + /// + /// This throws an [ArgumentError] if [secret] is passed without [identifier], + /// a [StateError] if these credentials can't be refreshed, an + /// [AuthorizationException] if refreshing the credentials fails, or a + /// [FormatException] if the authorization server returns invalid responses. + Future<Credentials> refresh( + {String? identifier, + String? secret, + Iterable<String>? newScopes, + bool basicAuth = true, + http.Client? httpClient}) async { + var scopes = this.scopes; + if (newScopes != null) scopes = newScopes.toList(); + scopes ??= []; + httpClient ??= http.Client(); + + if (identifier == null && secret != null) { + throw ArgumentError('secret may not be passed without identifier.'); + } + + var startTime = DateTime.now(); + var tokenEndpoint = this.tokenEndpoint; + if (refreshToken == null) { + throw StateError("Can't refresh credentials without a refresh " + 'token.'); + } else if (tokenEndpoint == null) { + throw StateError("Can't refresh credentials without a token " + 'endpoint.'); + } + + var headers = <String, String>{}; + + var body = {'grant_type': 'refresh_token', 'refresh_token': refreshToken}; + if (scopes.isNotEmpty) body['scope'] = scopes.join(_delimiter); + + if (basicAuth && secret != null) { + headers['Authorization'] = basicAuthHeader(identifier!, secret); + } else { + if (identifier != null) body['client_id'] = identifier; + if (secret != null) body['client_secret'] = secret; + } + + var response = + await httpClient.post(tokenEndpoint, headers: headers, body: body); + var credentials = handleAccessTokenResponse( + response, tokenEndpoint, startTime, scopes, _delimiter, + getParameters: _getParameters); + + // The authorization server may issue a new refresh token. If it doesn't, + // we should re-use the one we already have. + if (credentials.refreshToken != null) return credentials; + return Credentials(credentials.accessToken, + refreshToken: refreshToken, + idToken: credentials.idToken, + tokenEndpoint: credentials.tokenEndpoint, + scopes: credentials.scopes, + expiration: credentials.expiration); + } +}
diff --git a/pkgs/oauth2/lib/src/expiration_exception.dart b/pkgs/oauth2/lib/src/expiration_exception.dart new file mode 100644 index 0000000..d72fcf6 --- /dev/null +++ b/pkgs/oauth2/lib/src/expiration_exception.dart
@@ -0,0 +1,19 @@ +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'credentials.dart'; + +/// An exception raised when attempting to use expired OAuth2 credentials. +class ExpirationException implements Exception { + /// The expired credentials. + final Credentials credentials; + + /// Creates an ExpirationException. + ExpirationException(this.credentials); + + /// Provides a string description of the ExpirationException. + @override + String toString() => + "OAuth2 credentials have expired and can't be refreshed."; +}
diff --git a/pkgs/oauth2/lib/src/handle_access_token_response.dart b/pkgs/oauth2/lib/src/handle_access_token_response.dart new file mode 100644 index 0000000..f318e3b --- /dev/null +++ b/pkgs/oauth2/lib/src/handle_access_token_response.dart
@@ -0,0 +1,158 @@ +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:http/http.dart' as http; +import 'package:http_parser/http_parser.dart'; + +import 'authorization_exception.dart'; +import 'credentials.dart'; +import 'parameters.dart'; + +/// The amount of time to add as a "grace period" for credential expiration. +/// +/// This allows credential expiration checks to remain valid for a reasonable +/// amount of time. +const _expirationGrace = Duration(seconds: 10); + +/// Handles a response from the authorization server that contains an access +/// token. +/// +/// This response format is common across several different components of the +/// OAuth2 flow. +/// +/// By default, this follows the OAuth2 spec and requires the server's responses +/// to be in JSON format. However, some servers return non-standard response +/// formats, which can be parsed using the [getParameters] function. +/// +/// This function is passed the `Content-Type` header of the response as well as +/// its body as a UTF-8-decoded string. It should return a map in the same +/// format as the [standard JSON response][]. +/// +/// [standard JSON response]: https://tools.ietf.org/html/rfc6749#section-5.1 +Credentials handleAccessTokenResponse(http.Response response, Uri tokenEndpoint, + DateTime startTime, List<String>? scopes, String delimiter, + {Map<String, dynamic> Function(MediaType? contentType, String body)? + getParameters}) { + getParameters ??= parseJsonParameters; + + try { + if (response.statusCode != 200) { + _handleErrorResponse(response, tokenEndpoint, getParameters); + } + + var contentTypeString = response.headers['content-type']; + if (contentTypeString == null) { + throw const FormatException('Missing Content-Type string.'); + } + + var parameters = + getParameters(MediaType.parse(contentTypeString), response.body); + + for (var requiredParameter in ['access_token', 'token_type']) { + if (!parameters.containsKey(requiredParameter)) { + throw FormatException( + 'did not contain required parameter "$requiredParameter"'); + } else if (parameters[requiredParameter] is! String) { + throw FormatException( + 'required parameter "$requiredParameter" was not a string, was ' + '"${parameters[requiredParameter]}"'); + } + } + + // TODO(nweiz): support the "mac" token type + // (http://tools.ietf.org/html/draft-ietf-oauth-v2-http-mac-01) + if ((parameters['token_type'] as String).toLowerCase() != 'bearer') { + throw FormatException( + '"$tokenEndpoint": unknown token type "${parameters['token_type']}"'); + } + + var expiresIn = parameters['expires_in']; + if (expiresIn != null) { + if (expiresIn is String) { + try { + expiresIn = double.parse(expiresIn).toInt(); + } on FormatException { + throw FormatException( + 'parameter "expires_in" could not be parsed as in, was: ' + '"$expiresIn"', + ); + } + } else if (expiresIn is! int) { + throw FormatException( + 'parameter "expires_in" was not an int, was: "$expiresIn"'); + } + } + + for (var name in ['refresh_token', 'id_token', 'scope']) { + var value = parameters[name]; + if (value != null && value is! String) { + throw FormatException( + 'parameter "$name" was not a string, was "$value"'); + } + } + + var scope = parameters['scope'] as String?; + if (scope != null) scopes = scope.split(delimiter); + + var expiration = expiresIn == null + ? null + : startTime.add(Duration(seconds: expiresIn as int) - _expirationGrace); + + return Credentials( + parameters['access_token'] as String, + refreshToken: parameters['refresh_token'] as String?, + idToken: parameters['id_token'] as String?, + tokenEndpoint: tokenEndpoint, + scopes: scopes, + expiration: expiration, + ); + } on FormatException catch (e) { + throw FormatException('Invalid OAuth response for "$tokenEndpoint": ' + '${e.message}.\n\n${response.body}'); + } +} + +/// Throws the appropriate exception for an error response from the +/// authorization server. +void _handleErrorResponse( + http.Response response, Uri tokenEndpoint, GetParameters getParameters) { + // OAuth2 mandates a 400 or 401 response code for access token error + // responses. If it's not a 400 reponse, the server is either broken or + // off-spec. + if (response.statusCode != 400 && response.statusCode != 401) { + var reason = ''; + var reasonPhrase = response.reasonPhrase; + if (reasonPhrase != null && reasonPhrase.isNotEmpty) { + reason = ' $reasonPhrase'; + } + throw FormatException('OAuth request for "$tokenEndpoint" failed ' + 'with status ${response.statusCode}$reason.\n\n${response.body}'); + } + + var contentTypeString = response.headers['content-type']; + var contentType = + contentTypeString == null ? null : MediaType.parse(contentTypeString); + + var parameters = getParameters(contentType, response.body); + + if (!parameters.containsKey('error')) { + throw const FormatException('did not contain required parameter "error"'); + } else if (parameters['error'] is! String) { + throw FormatException('required parameter "error" was not a string, was ' + '"${parameters["error"]}"'); + } + + for (var name in ['error_description', 'error_uri']) { + var value = parameters[name]; + + if (value != null && value is! String) { + throw FormatException('parameter "$name" was not a string, was "$value"'); + } + } + + var uriString = parameters['error_uri'] as String?; + var uri = uriString == null ? null : Uri.parse(uriString); + var description = parameters['error_description'] as String?; + throw AuthorizationException(parameters['error'] as String, description, uri); +}
diff --git a/pkgs/oauth2/lib/src/parameters.dart b/pkgs/oauth2/lib/src/parameters.dart new file mode 100644 index 0000000..ecc6559 --- /dev/null +++ b/pkgs/oauth2/lib/src/parameters.dart
@@ -0,0 +1,33 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; + +import 'package:http_parser/http_parser.dart'; + +/// The type of a callback that parses parameters from an HTTP response. +typedef GetParameters = Map<String, dynamic> Function( + MediaType? contentType, String body); + +/// Parses parameters from a response with a JSON body, as per the +/// [OAuth2 spec][]. +/// +/// [OAuth2 spec]: https://tools.ietf.org/html/rfc6749#section-5.1 +Map<String, dynamic> parseJsonParameters(MediaType? contentType, String body) { + // The spec requires a content-type of application/json, but some endpoints + // (e.g. Dropbox) serve it as text/javascript instead. + if (contentType == null || + (contentType.mimeType != 'application/json' && + contentType.mimeType != 'text/javascript')) { + throw FormatException( + 'Content-Type was "$contentType", expected "application/json"'); + } + + var untypedParameters = jsonDecode(body); + if (untypedParameters is Map<String, dynamic>) { + return untypedParameters; + } + + throw FormatException('Parameters must be a map, was "$untypedParameters"'); +}
diff --git a/pkgs/oauth2/lib/src/resource_owner_password_grant.dart b/pkgs/oauth2/lib/src/resource_owner_password_grant.dart new file mode 100644 index 0000000..96fb503 --- /dev/null +++ b/pkgs/oauth2/lib/src/resource_owner_password_grant.dart
@@ -0,0 +1,94 @@ +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:http/http.dart' as http; +import 'package:http_parser/http_parser.dart'; + +import 'client.dart'; +import 'credentials.dart'; +import 'handle_access_token_response.dart'; +import 'utils.dart'; + +/// Obtains credentials using a [resource owner password grant](https://tools.ietf.org/html/rfc6749#section-1.3.3). +/// +/// This mode of authorization uses the user's username and password to obtain +/// an authentication token, which can then be stored. This is safer than +/// storing the username and password directly, but it should be avoided if any +/// other authorization method is available, since it requires the user to +/// provide their username and password to a third party (you). +/// +/// The client [identifier] and [secret] may be issued by the server, and are +/// used to identify and authenticate your specific OAuth2 client. These are +/// usually global to the program using this library. +/// +/// The specific permissions being requested from the authorization server may +/// be specified via [scopes]. The scope strings are specific to the +/// authorization server and may be found in its documentation. Note that you +/// may not be granted access to every scope you request; you may check the +/// [Credentials.scopes] field of [Client.credentials] to see which scopes you +/// were granted. +/// +/// The scope strings will be separated by the provided [delimiter]. This +/// defaults to `" "`, the OAuth2 standard, but some APIs (such as Facebook's) +/// use non-standard delimiters. +/// +/// By default, this follows the OAuth2 spec and requires the server's responses +/// to be in JSON format. However, some servers return non-standard response +/// formats, which can be parsed using the [getParameters] function. +/// +/// This function is passed the `Content-Type` header of the response as well as +/// its body as a UTF-8-decoded string. It should return a map in the same +/// format as the [standard JSON response][]. +/// +/// [standard JSON response]: https://tools.ietf.org/html/rfc6749#section-5.1 +Future<Client> resourceOwnerPasswordGrant( + Uri authorizationEndpoint, String username, String password, + {String? identifier, + String? secret, + Iterable<String>? scopes, + bool basicAuth = true, + CredentialsRefreshedCallback? onCredentialsRefreshed, + http.Client? httpClient, + String? delimiter, + Map<String, dynamic> Function(MediaType? contentType, String body)? + getParameters}) async { + delimiter ??= ' '; + var startTime = DateTime.now(); + + var body = { + 'grant_type': 'password', + 'username': username, + 'password': password + }; + + var headers = <String, String>{}; + + if (identifier != null) { + if (basicAuth) { + headers['Authorization'] = basicAuthHeader(identifier, secret!); + } else { + body['client_id'] = identifier; + if (secret != null) body['client_secret'] = secret; + } + } + + if (scopes != null && scopes.isNotEmpty) { + body['scope'] = scopes.join(delimiter); + } + + httpClient ??= http.Client(); + var response = await httpClient.post(authorizationEndpoint, + headers: headers, body: body); + + var credentials = handleAccessTokenResponse( + response, authorizationEndpoint, startTime, scopes?.toList(), delimiter, + getParameters: getParameters); + return Client(credentials, + identifier: identifier, + secret: secret, + httpClient: httpClient, + onCredentialsRefreshed: onCredentialsRefreshed); +}
diff --git a/pkgs/oauth2/lib/src/utils.dart b/pkgs/oauth2/lib/src/utils.dart new file mode 100644 index 0000000..2a22b9f --- /dev/null +++ b/pkgs/oauth2/lib/src/utils.dart
@@ -0,0 +1,15 @@ +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; + +/// Adds additional query parameters to [url], overwriting the original +/// parameters if a name conflict occurs. +Uri addQueryParameters(Uri url, Map<String, String> parameters) => url.replace( + queryParameters: Map.from(url.queryParameters)..addAll(parameters)); + +String basicAuthHeader(String identifier, String secret) { + var userPass = '${Uri.encodeFull(identifier)}:${Uri.encodeFull(secret)}'; + return 'Basic ${base64Encode(ascii.encode(userPass))}'; +}
diff --git a/pkgs/oauth2/pubspec.yaml b/pkgs/oauth2/pubspec.yaml new file mode 100644 index 0000000..75ded18 --- /dev/null +++ b/pkgs/oauth2/pubspec.yaml
@@ -0,0 +1,20 @@ +name: oauth2 +version: 2.0.4-wip +description: >- + A client library for authenticating with a remote service via OAuth2 on + behalf of a user, and making authorized HTTP requests with the user's + OAuth2 credentials. +repository: https://github.com/dart-lang/tools/tree/main/pkgs/oauth2 + +environment: + sdk: ^3.4.0 + +dependencies: + collection: ^1.15.0 + crypto: ^3.0.0 + http: ^1.0.0 + http_parser: ^4.0.0 + +dev_dependencies: + dart_flutter_team_lints: ^3.0.0 + test: ^1.16.0
diff --git a/pkgs/oauth2/test/authorization_code_grant_test.dart b/pkgs/oauth2/test/authorization_code_grant_test.dart new file mode 100644 index 0000000..06e88af --- /dev/null +++ b/pkgs/oauth2/test/authorization_code_grant_test.dart
@@ -0,0 +1,391 @@ +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:convert'; + +import 'package:http/http.dart' as http; +import 'package:oauth2/oauth2.dart' as oauth2; +import 'package:test/test.dart'; + +import 'utils.dart'; + +final redirectUrl = Uri.parse('http://example.com/redirect'); + +void main() { + late ExpectClient client; + late oauth2.AuthorizationCodeGrant grant; + setUp(() { + client = ExpectClient(); + grant = oauth2.AuthorizationCodeGrant( + 'identifier', + Uri.parse('https://example.com/authorization'), + Uri.parse('https://example.com/token'), + secret: 'secret', + httpClient: client); + }); + + group('.getAuthorizationUrl', () { + test('builds the correct URL', () { + expect( + grant.getAuthorizationUrl(redirectUrl).toString(), + allOf([ + startsWith('https://example.com/authorization?response_type=code'), + contains('&client_id=identifier'), + contains('&redirect_uri=http%3A%2F%2Fexample.com%2Fredirect'), + matches(r'&code_challenge=[A-Za-z0-9\+\/\-\_]{43}'), + contains('&code_challenge_method=S256') + ])); + }); + + test('builds the correct URL with scopes', () { + var authorizationUrl = grant + .getAuthorizationUrl(redirectUrl, scopes: ['scope', 'other/scope']); + expect( + authorizationUrl.toString(), + allOf([ + startsWith('https://example.com/authorization?response_type=code'), + contains('&client_id=identifier'), + contains('&redirect_uri=http%3A%2F%2Fexample.com%2Fredirect'), + matches(r'&code_challenge=[A-Za-z0-9\+\/\-\_]{43}'), + contains('&code_challenge_method=S256'), + contains('&scope=scope+other%2Fscope') + ])); + }); + + test('builds the correct URL with passed in code verifier', () { + const codeVerifier = + 'it1shei7LooGoh3looxaa4sieveijeib2zecauz2oo8aebae5aehee0ahPirewoh' + '5Bo6Maexooqui3uL2si6ahweiv7shauc1shahxooveoB3aeyahsaiye0Egh3raix'; + const expectedCodeChallenge = + 'EjfFMv8TFPd3GuNxAn5COhlWBGpfZLimHett7ypJfJ0'; + var grant = oauth2.AuthorizationCodeGrant( + 'identifier', + Uri.parse('https://example.com/authorization'), + Uri.parse('https://example.com/token'), + secret: 'secret', + httpClient: client, + codeVerifier: codeVerifier); + expect( + grant.getAuthorizationUrl(redirectUrl).toString(), + allOf([ + startsWith('https://example.com/authorization?response_type=code'), + contains('&client_id=identifier'), + contains('&redirect_uri=http%3A%2F%2Fexample.com%2Fredirect'), + contains('&code_challenge=$expectedCodeChallenge'), + contains('&code_challenge_method=S256') + ])); + }); + + test('separates scopes with the correct delimiter', () { + var grant = oauth2.AuthorizationCodeGrant( + 'identifier', + Uri.parse('https://example.com/authorization'), + Uri.parse('https://example.com/token'), + secret: 'secret', + httpClient: client, + delimiter: '_'); + var authorizationUrl = grant + .getAuthorizationUrl(redirectUrl, scopes: ['scope', 'other/scope']); + expect( + authorizationUrl.toString(), + allOf([ + startsWith('https://example.com/authorization?response_type=code'), + contains('&client_id=identifier'), + contains('&redirect_uri=http%3A%2F%2Fexample.com%2Fredirect'), + matches(r'&code_challenge=[A-Za-z0-9\+\/\-\_]{43}'), + contains('&code_challenge_method=S256'), + contains('&scope=scope_other%2Fscope') + ])); + }); + + test('builds the correct URL with state', () { + var authorizationUrl = + grant.getAuthorizationUrl(redirectUrl, state: 'state'); + expect( + authorizationUrl.toString(), + allOf([ + startsWith('https://example.com/authorization?response_type=code'), + contains('&client_id=identifier'), + contains('&redirect_uri=http%3A%2F%2Fexample.com%2Fredirect'), + matches(r'&code_challenge=[A-Za-z0-9\+\/\-\_]{43}'), + contains('&code_challenge_method=S256'), + contains('&state=state') + ])); + }); + + test('merges with existing query parameters', () { + grant = oauth2.AuthorizationCodeGrant( + 'identifier', + Uri.parse('https://example.com/authorization?query=value'), + Uri.parse('https://example.com/token'), + secret: 'secret', + httpClient: client); + + var authorizationUrl = grant.getAuthorizationUrl(redirectUrl); + expect( + authorizationUrl.toString(), + allOf([ + startsWith('https://example.com/authorization?query=value'), + contains('&response_type=code'), + contains('&client_id=identifier'), + contains('&redirect_uri=http%3A%2F%2Fexample.com%2Fredirect'), + matches(r'&code_challenge=[A-Za-z0-9\+\/\-\_]{43}'), + contains('&code_challenge_method=S256'), + ])); + }); + + test("can't be called twice", () { + grant.getAuthorizationUrl(redirectUrl); + expect(() => grant.getAuthorizationUrl(redirectUrl), throwsStateError); + }); + }); + + group('.handleAuthorizationResponse', () { + test("can't be called before .getAuthorizationUrl", () { + expect(grant.handleAuthorizationResponse({}), throwsStateError); + }); + + test("can't be called twice", () { + grant.getAuthorizationUrl(redirectUrl); + expect(grant.handleAuthorizationResponse({'code': 'auth code'}), + throwsFormatException); + expect(grant.handleAuthorizationResponse({'code': 'auth code'}), + throwsStateError); + }); + + test('must have a state parameter if the authorization URL did', () { + grant.getAuthorizationUrl(redirectUrl, state: 'state'); + expect(grant.handleAuthorizationResponse({'code': 'auth code'}), + throwsFormatException); + }); + + test('must have the same state parameter the authorization URL did', () { + grant.getAuthorizationUrl(redirectUrl, state: 'state'); + expect( + grant.handleAuthorizationResponse( + {'code': 'auth code', 'state': 'other state'}), + throwsFormatException); + }); + + test('must have a code parameter', () { + grant.getAuthorizationUrl(redirectUrl); + expect(grant.handleAuthorizationResponse({}), throwsFormatException); + }); + + test('with an error parameter throws an AuthorizationException', () { + grant.getAuthorizationUrl(redirectUrl); + expect(grant.handleAuthorizationResponse({'error': 'invalid_request'}), + throwsA(isA<oauth2.AuthorizationException>())); + }); + + test('sends an authorization code request', () { + grant.getAuthorizationUrl(redirectUrl); + client.expectRequest((request) { + expect(request.method, equals('POST')); + expect(request.url.toString(), equals(grant.tokenEndpoint.toString())); + expect( + request.bodyFields, + allOf([ + containsPair('grant_type', 'authorization_code'), + containsPair('code', 'auth code'), + containsPair('redirect_uri', redirectUrl.toString()), + containsPair( + 'code_verifier', matches(r'[A-Za-z0-9\-\.\_\~]{128}')) + ])); + expect(request.headers, + containsPair('Authorization', 'Basic aWRlbnRpZmllcjpzZWNyZXQ=')); + + return Future.value(http.Response( + jsonEncode({ + 'access_token': 'access token', + 'token_type': 'bearer', + }), + 200, + headers: {'content-type': 'application/json'})); + }); + + expect( + grant.handleAuthorizationResponse({'code': 'auth code'}).then( + (client) => client.credentials.accessToken), + completion(equals('access token'))); + }); + }); + + group('.handleAuthorizationCode', () { + test("can't be called before .getAuthorizationUrl", () { + expect(grant.handleAuthorizationCode('auth code'), throwsStateError); + }); + + test("can't be called twice", () { + grant.getAuthorizationUrl(redirectUrl); + expect(grant.handleAuthorizationCode('auth code'), throwsFormatException); + expect(grant.handleAuthorizationCode('auth code'), throwsStateError); + }); + + test('sends an authorization code request', () async { + grant.getAuthorizationUrl(redirectUrl); + client.expectRequest((request) { + expect(request.method, equals('POST')); + expect(request.url.toString(), equals(grant.tokenEndpoint.toString())); + expect( + request.bodyFields, + allOf([ + containsPair('grant_type', 'authorization_code'), + containsPair('code', 'auth code'), + containsPair('redirect_uri', redirectUrl.toString()), + containsPair( + 'code_verifier', matches(r'[A-Za-z0-9\-\.\_\~]{128}')) + ])); + expect(request.headers, + containsPair('Authorization', 'Basic aWRlbnRpZmllcjpzZWNyZXQ=')); + + return Future.value(http.Response( + jsonEncode({ + 'access_token': 'access token', + 'token_type': 'bearer', + }), + 200, + headers: {'content-type': 'application/json'})); + }); + + expect( + await grant.handleAuthorizationCode('auth code'), + isA<oauth2.Client>().having((c) => c.credentials.accessToken, + 'credentials.accessToken', 'access token')); + }); + }); + + group('with basicAuth: false', () { + setUp(() { + client = ExpectClient(); + grant = oauth2.AuthorizationCodeGrant( + 'identifier', + Uri.parse('https://example.com/authorization'), + Uri.parse('https://example.com/token'), + secret: 'secret', + basicAuth: false, + httpClient: client); + }); + + test('.handleAuthorizationResponse sends an authorization code request', + () { + grant.getAuthorizationUrl(redirectUrl); + client.expectRequest((request) { + expect(request.method, equals('POST')); + expect(request.url.toString(), equals(grant.tokenEndpoint.toString())); + expect( + request.bodyFields, + allOf([ + containsPair('grant_type', 'authorization_code'), + containsPair('code', 'auth code'), + containsPair('redirect_uri', redirectUrl.toString()), + containsPair( + 'code_verifier', matches(r'[A-Za-z0-9\-\.\_\~]{128}')), + containsPair('client_id', 'identifier'), + containsPair('client_secret', 'secret') + ])); + + return Future.value(http.Response( + jsonEncode({ + 'access_token': 'access token', + 'token_type': 'bearer', + }), + 200, + headers: {'content-type': 'application/json'})); + }); + + expect( + grant.handleAuthorizationResponse({'code': 'auth code'}).then( + (client) => client.credentials.accessToken), + completion(equals('access token'))); + }); + + test('.handleAuthorizationCode sends an authorization code request', + () async { + grant.getAuthorizationUrl(redirectUrl); + client.expectRequest((request) { + expect(request.method, equals('POST')); + expect(request.url.toString(), equals(grant.tokenEndpoint.toString())); + expect( + request.bodyFields, + allOf([ + containsPair('grant_type', 'authorization_code'), + containsPair('code', 'auth code'), + containsPair('redirect_uri', redirectUrl.toString()), + containsPair( + 'code_verifier', matches(r'[A-Za-z0-9\-\.\_\~]{128}')), + containsPair('client_id', 'identifier'), + containsPair('client_secret', 'secret') + ])); + + return Future.value(http.Response( + jsonEncode({ + 'access_token': 'access token', + 'token_type': 'bearer', + }), + 200, + headers: {'content-type': 'application/json'})); + }); + + expect( + await grant.handleAuthorizationCode('auth code'), + isA<oauth2.Client>().having((c) => c.credentials.accessToken, + 'credentials.accessToken', 'access token')); + }); + }); + + group('onCredentialsRefreshed', () { + test('is correctly propagated', () async { + var isCallbackInvoked = false; + var grant = oauth2.AuthorizationCodeGrant( + 'identifier', + Uri.parse('https://example.com/authorization'), + Uri.parse('https://example.com/token'), + secret: 'secret', + basicAuth: false, + httpClient: client, onCredentialsRefreshed: (credentials) { + isCallbackInvoked = true; + }); + + grant.getAuthorizationUrl(redirectUrl); + client.expectRequest( + (request) => Future.value( + http.Response( + jsonEncode({ + 'access_token': 'access token', + 'token_type': 'bearer', + 'expires_in': -3600, + 'refresh_token': 'refresh token', + }), + 200, + headers: {'content-type': 'application/json'}, + ), + ), + ); + + var oauth2Client = await grant.handleAuthorizationCode('auth code'); + + client.expectRequest( + (request) => Future.value( + http.Response( + jsonEncode({ + 'access_token': 'new access token', + 'token_type': 'bearer', + }), + 200, + headers: {'content-type': 'application/json'}, + ), + ), + ); + + client.expectRequest( + (request) => Future.value(http.Response('good job', 200))); + + await oauth2Client.read(Uri.parse('http://example.com/resource')); + + expect(isCallbackInvoked, equals(true)); + }); + }); +}
diff --git a/pkgs/oauth2/test/client_credentials_grant_test.dart b/pkgs/oauth2/test/client_credentials_grant_test.dart new file mode 100644 index 0000000..28de425 --- /dev/null +++ b/pkgs/oauth2/test/client_credentials_grant_test.dart
@@ -0,0 +1,113 @@ +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +@TestOn('vm') +library; + +import 'dart:convert'; + +import 'package:http/http.dart' as http; +import 'package:oauth2/oauth2.dart' as oauth2; +import 'package:test/test.dart'; + +import 'utils.dart'; + +final success = jsonEncode({ + 'access_token': '2YotnFZFEjr1zCsicMWpAA', + 'token_type': 'bearer', + 'expires_in': 3600, + 'refresh_token': 'tGzv3JOkF0XG5Qx2TlKWIA', +}); + +String auth = 'Basic Y2xpZW50OnNlY3JldA=='; +Uri authEndpoint = Uri.parse('https://example.com'); + +void main() { + late ExpectClient expectClient; + + setUp(() => expectClient = ExpectClient()); + + group('basic', () { + test('builds correct request with client when using basic auth for client', + () async { + expectClient.expectRequest((request) async { + expect(auth, equals(request.headers['authorization'])); + expect(request.bodyFields['grant_type'], equals('client_credentials')); + return http.Response(success, 200, + headers: {'content-type': 'application/json'}); + }); + + var client = await oauth2.clientCredentialsGrant( + authEndpoint, 'client', 'secret', + httpClient: expectClient); + + expect(client.credentials, isNotNull); + expect(client.credentials.accessToken, equals('2YotnFZFEjr1zCsicMWpAA')); + }); + + test('builds correct request when using query parameters for client', + () async { + expectClient.expectRequest((request) async { + expect(request.bodyFields['grant_type'], equals('client_credentials')); + expect(request.bodyFields['client_id'], equals('client')); + expect(request.bodyFields['client_secret'], equals('secret')); + return http.Response(success, 200, + headers: {'content-type': 'application/json'}); + }); + + var client = await oauth2.clientCredentialsGrant( + authEndpoint, 'client', 'secret', + basicAuth: false, httpClient: expectClient); + expect(client.credentials, isNotNull); + expect(client.credentials.accessToken, equals('2YotnFZFEjr1zCsicMWpAA')); + }); + + test('builds correct request using scope', () async { + expectClient.expectRequest((request) async { + expect(auth, equals(request.headers['authorization'])); + expect(request.bodyFields['grant_type'], equals('client_credentials')); + expect(request.bodyFields['scope'], equals('one two')); + return http.Response(success, 200, + headers: {'content-type': 'application/json'}); + }); + + var client = await oauth2.clientCredentialsGrant( + authEndpoint, 'client', 'secret', + scopes: ['one', 'two'], httpClient: expectClient); + expect(client.credentials, isNotNull); + expect(client.credentials.accessToken, equals('2YotnFZFEjr1zCsicMWpAA')); + }); + + test('builds correct request using scope with custom delimiter', () async { + expectClient.expectRequest((request) async { + expect(request.bodyFields['grant_type'], equals('client_credentials')); + expect(request.bodyFields['scope'], equals('one,two')); + return http.Response(success, 200, + headers: {'content-type': 'application/json'}); + }); + + await oauth2.clientCredentialsGrant(authEndpoint, 'client', 'secret', + scopes: ['one', 'two'], httpClient: expectClient, delimiter: ','); + }); + + test('merges with existing query parameters', () async { + var authEndpoint = Uri.parse('https://example.com?query=value'); + + expectClient.expectRequest((request) async { + expect(request.bodyFields['grant_type'], equals('client_credentials')); + expect(request.bodyFields['client_id'], equals('client')); + expect(request.bodyFields['client_secret'], equals('secret')); + expect(request.url.queryParameters['query'], equals('value')); + return http.Response(success, 200, + headers: {'content-type': 'application/json'}); + }); + + var client = await oauth2.clientCredentialsGrant( + authEndpoint, 'client', 'secret', + basicAuth: false, httpClient: expectClient); + expect(client.credentials, isNotNull); + expect(client.credentials.accessToken, equals('2YotnFZFEjr1zCsicMWpAA')); + }); + }); +}
diff --git a/pkgs/oauth2/test/client_test.dart b/pkgs/oauth2/test/client_test.dart new file mode 100644 index 0000000..3c30d36 --- /dev/null +++ b/pkgs/oauth2/test/client_test.dart
@@ -0,0 +1,287 @@ +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:convert'; + +import 'package:http/http.dart' as http; +import 'package:oauth2/oauth2.dart' as oauth2; +import 'package:test/test.dart'; + +import 'utils.dart'; + +final Uri requestUri = Uri.parse('http://example.com/resource'); + +final Uri tokenEndpoint = Uri.parse('http://example.com/token'); + +void main() { + late ExpectClient httpClient; + + setUp(() => httpClient = ExpectClient()); + + group('with expired credentials', () { + test("that can't be refreshed throws an ExpirationException on send", () { + var expiration = DateTime.now().subtract(const Duration(hours: 1)); + var credentials = + oauth2.Credentials('access token', expiration: expiration); + var client = oauth2.Client(credentials, + identifier: 'identifier', secret: 'secret', httpClient: httpClient); + + expect(client.get(requestUri), + throwsA(const TypeMatcher<oauth2.ExpirationException>())); + }); + + test( + 'that can be refreshed refreshes the credentials and sends the ' + 'request', () async { + var expiration = DateTime.now().subtract(const Duration(hours: 1)); + var credentials = oauth2.Credentials('access token', + refreshToken: 'refresh token', + tokenEndpoint: tokenEndpoint, + expiration: expiration); + var client = oauth2.Client(credentials, + identifier: 'identifier', secret: 'secret', httpClient: httpClient); + + httpClient.expectRequest((request) { + expect(request.method, equals('POST')); + expect(request.url.toString(), equals(tokenEndpoint.toString())); + return Future.value(http.Response( + jsonEncode( + {'access_token': 'new access token', 'token_type': 'bearer'}), + 200, + headers: {'content-type': 'application/json'})); + }); + + httpClient.expectRequest((request) { + expect(request.method, equals('GET')); + expect(request.url.toString(), equals(requestUri.toString())); + expect(request.headers['authorization'], + equals('Bearer new access token')); + + return Future.value(http.Response('good job', 200)); + }); + + await client.read(requestUri); + expect(client.credentials.accessToken, equals('new access token')); + }); + + test( + 'that can be refreshed refreshes only once if multiple requests are made', + () async { + var expiration = DateTime.now().subtract(const Duration(hours: 1)); + var credentials = oauth2.Credentials('access token', + refreshToken: 'refresh token', + tokenEndpoint: tokenEndpoint, + expiration: expiration); + var client = oauth2.Client(credentials, + identifier: 'identifier', secret: 'secret', httpClient: httpClient); + + httpClient.expectRequest((request) { + expect(request.method, equals('POST')); + expect(request.url.toString(), equals(tokenEndpoint.toString())); + return Future.value(http.Response( + jsonEncode( + {'access_token': 'new access token', 'token_type': 'bearer'}), + 200, + headers: {'content-type': 'application/json'})); + }); + + const numCalls = 2; + + for (var i = 0; i < numCalls; i++) { + httpClient.expectRequest((request) { + expect(request.method, equals('GET')); + expect(request.url.toString(), equals(requestUri.toString())); + expect(request.headers['authorization'], + equals('Bearer new access token')); + + return Future.value(http.Response('good job', 200)); + }); + } + + await Future.wait( + List<Future<String>>.generate( + numCalls, (_) => client.read(requestUri)), + ); + + expect(client.credentials.accessToken, equals('new access token')); + }, + ); + + test('that onCredentialsRefreshed is called', () async { + var callbackCalled = false; + + var expiration = DateTime.now().subtract(const Duration(hours: 1)); + var credentials = oauth2.Credentials('access token', + refreshToken: 'refresh token', + tokenEndpoint: tokenEndpoint, + expiration: expiration); + var client = oauth2.Client(credentials, + identifier: 'identifier', + secret: 'secret', + httpClient: httpClient, onCredentialsRefreshed: (credentials) { + callbackCalled = true; + expect(credentials.accessToken, equals('new access token')); + }); + + httpClient.expectRequest( + (request) => Future.value( + http.Response( + jsonEncode( + {'access_token': 'new access token', 'token_type': 'bearer'}, + ), + 200, + headers: {'content-type': 'application/json'}, + ), + ), + ); + + httpClient.expectRequest( + (request) => Future.value(http.Response('good job', 200))); + + await client.read(requestUri); + expect(callbackCalled, equals(true)); + }); + }); + + group('with valid credentials', () { + test('sends a request with bearer authorization', () { + var credentials = oauth2.Credentials('access token'); + var client = oauth2.Client(credentials, + identifier: 'identifier', secret: 'secret', httpClient: httpClient); + + httpClient.expectRequest((request) { + expect(request.method, equals('GET')); + expect(request.url.toString(), equals(requestUri.toString())); + expect(request.headers['authorization'], equals('Bearer access token')); + + return Future.value(http.Response('good job', 200)); + }); + + expect(client.read(requestUri), completion(equals('good job'))); + }); + + test('can manually refresh the credentials', () async { + var credentials = oauth2.Credentials('access token', + refreshToken: 'refresh token', tokenEndpoint: tokenEndpoint); + var client = oauth2.Client(credentials, + identifier: 'identifier', secret: 'secret', httpClient: httpClient); + + httpClient.expectRequest((request) { + expect(request.method, equals('POST')); + expect(request.url.toString(), equals(tokenEndpoint.toString())); + return Future.value(http.Response( + jsonEncode( + {'access_token': 'new access token', 'token_type': 'bearer'}), + 200, + headers: {'content-type': 'application/json'})); + }); + + await client.refreshCredentials(); + expect(client.credentials.accessToken, equals('new access token')); + }); + + test("without a refresh token can't manually refresh the credentials", () { + var credentials = oauth2.Credentials('access token'); + var client = oauth2.Client(credentials, + identifier: 'identifier', secret: 'secret', httpClient: httpClient); + + expect(client.refreshCredentials(), throwsA(isStateError)); + }); + }); + + group('with invalid credentials', () { + test('throws an AuthorizationException for a 401 response', () { + var credentials = oauth2.Credentials('access token'); + var client = oauth2.Client(credentials, + identifier: 'identifier', secret: 'secret', httpClient: httpClient); + + httpClient.expectRequest((request) { + expect(request.method, equals('GET')); + expect(request.url.toString(), equals(requestUri.toString())); + expect(request.headers['authorization'], equals('Bearer access token')); + + var authenticate = 'Bearer error="invalid_token", error_description=' + '"Something is terribly wrong."'; + return Future.value(http.Response('bad job', 401, + headers: {'www-authenticate': authenticate})); + }); + + expect(client.read(requestUri), + throwsA(const TypeMatcher<oauth2.AuthorizationException>())); + }); + + test('passes through a 401 response without www-authenticate', () async { + var credentials = oauth2.Credentials('access token'); + var client = oauth2.Client(credentials, + identifier: 'identifier', secret: 'secret', httpClient: httpClient); + + httpClient.expectRequest((request) { + expect(request.method, equals('GET')); + expect(request.url.toString(), equals(requestUri.toString())); + expect(request.headers['authorization'], equals('Bearer access token')); + + return Future.value(http.Response('bad job', 401)); + }); + + expect((await client.get(requestUri)).statusCode, equals(401)); + }); + + test('passes through a 401 response with invalid www-authenticate', + () async { + var credentials = oauth2.Credentials('access token'); + var client = oauth2.Client(credentials, + identifier: 'identifier', secret: 'secret', httpClient: httpClient); + + httpClient.expectRequest((request) { + expect(request.method, equals('GET')); + expect(request.url.toString(), equals(requestUri.toString())); + expect(request.headers['authorization'], equals('Bearer access token')); + + var authenticate = 'Bearer error="invalid_token" error_description=' + '"Something is terribly wrong."'; + return Future.value(http.Response('bad job', 401, + headers: {'www-authenticate': authenticate})); + }); + + expect((await client.get(requestUri)).statusCode, equals(401)); + }); + + test('passes through a 401 response with non-bearer www-authenticate', + () async { + var credentials = oauth2.Credentials('access token'); + var client = oauth2.Client(credentials, + identifier: 'identifier', secret: 'secret', httpClient: httpClient); + + httpClient.expectRequest((request) { + expect(request.method, equals('GET')); + expect(request.url.toString(), equals(requestUri.toString())); + expect(request.headers['authorization'], equals('Bearer access token')); + + return Future.value(http.Response('bad job', 401, + headers: {'www-authenticate': 'Digest'})); + }); + + expect((await client.get(requestUri)).statusCode, equals(401)); + }); + + test('passes through a 401 response with non-OAuth2 www-authenticate', + () async { + var credentials = oauth2.Credentials('access token'); + var client = oauth2.Client(credentials, + identifier: 'identifier', secret: 'secret', httpClient: httpClient); + + httpClient.expectRequest((request) { + expect(request.method, equals('GET')); + expect(request.url.toString(), equals(requestUri.toString())); + expect(request.headers['authorization'], equals('Bearer access token')); + + return Future.value(http.Response('bad job', 401, + headers: {'www-authenticate': 'Bearer'})); + }); + + expect((await client.get(requestUri)).statusCode, equals(401)); + }); + }); +}
diff --git a/pkgs/oauth2/test/credentials_test.dart b/pkgs/oauth2/test/credentials_test.dart new file mode 100644 index 0000000..d83bc7e --- /dev/null +++ b/pkgs/oauth2/test/credentials_test.dart
@@ -0,0 +1,331 @@ +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:convert'; + +import 'package:http/http.dart' as http; +import 'package:oauth2/oauth2.dart' as oauth2; +import 'package:test/test.dart'; + +import 'utils.dart'; + +final Uri tokenEndpoint = Uri.parse('http://example.com/token'); + +void main() { + late ExpectClient httpClient; + + setUp(() => httpClient = ExpectClient()); + + test('is not expired if no expiration exists', () { + var credentials = oauth2.Credentials('access token'); + expect(credentials.isExpired, isFalse); + }); + + test('is not expired if the expiration is in the future', () { + var expiration = DateTime.now().add(const Duration(hours: 1)); + var credentials = + oauth2.Credentials('access token', expiration: expiration); + expect(credentials.isExpired, isFalse); + }); + + test('is expired if the expiration is in the past', () { + var expiration = DateTime.now().subtract(const Duration(hours: 1)); + var credentials = + oauth2.Credentials('access token', expiration: expiration); + expect(credentials.isExpired, isTrue); + }); + + test("can't refresh without a refresh token", () { + var credentials = + oauth2.Credentials('access token', tokenEndpoint: tokenEndpoint); + expect(credentials.canRefresh, false); + + expect( + credentials.refresh( + identifier: 'identifier', secret: 'secret', httpClient: httpClient), + throwsStateError); + }); + + test("can't refresh without a token endpoint", () { + var credentials = + oauth2.Credentials('access token', refreshToken: 'refresh token'); + expect(credentials.canRefresh, false); + + expect( + credentials.refresh( + identifier: 'identifier', secret: 'secret', httpClient: httpClient), + throwsStateError); + }); + + test('can refresh with a refresh token and a token endpoint', () async { + var credentials = oauth2.Credentials('access token', + refreshToken: 'refresh token', + tokenEndpoint: tokenEndpoint, + scopes: ['scope1', 'scope2']); + expect(credentials.canRefresh, true); + + httpClient.expectRequest((request) { + expect(request.method, equals('POST')); + expect(request.url.toString(), equals(tokenEndpoint.toString())); + expect( + request.bodyFields, + equals({ + 'grant_type': 'refresh_token', + 'refresh_token': 'refresh token', + 'scope': 'scope1 scope2' + })); + expect( + request.headers, + containsPair('Authorization', + 'Basic aWQlQzMlQUJudCVDNCVBQmZpZXI6cyVDMyVBQmNyZXQ=')); + + return Future.value(http.Response( + jsonEncode({ + 'access_token': 'new access token', + 'token_type': 'bearer', + 'refresh_token': 'new refresh token' + }), + 200, + headers: {'content-type': 'application/json'})); + }); + + credentials = await credentials.refresh( + identifier: 'idëntÄ«fier', secret: 'sëcret', httpClient: httpClient); + expect(credentials.accessToken, equals('new access token')); + expect(credentials.refreshToken, equals('new refresh token')); + }); + + test('sets proper scope string when using custom delimiter', () async { + var credentials = oauth2.Credentials('access token', + refreshToken: 'refresh token', + tokenEndpoint: tokenEndpoint, + scopes: ['scope1', 'scope2'], + delimiter: ','); + httpClient.expectRequest((http.Request request) { + expect(request.bodyFields['scope'], equals('scope1,scope2')); + return Future.value(http.Response( + jsonEncode({ + 'access_token': 'new access token', + 'token_type': 'bearer', + 'refresh_token': 'new refresh token' + }), + 200, + headers: {'content-type': 'application/json'})); + }); + await credentials.refresh( + identifier: 'idëntÄ«fier', secret: 'sëcret', httpClient: httpClient); + }); + + test('can refresh without a client secret', () async { + var credentials = oauth2.Credentials('access token', + refreshToken: 'refresh token', + tokenEndpoint: tokenEndpoint, + scopes: ['scope1', 'scope2']); + expect(credentials.canRefresh, true); + + httpClient.expectRequest((request) { + expect(request.method, equals('POST')); + expect(request.url.toString(), equals(tokenEndpoint.toString())); + expect( + request.bodyFields, + equals({ + 'grant_type': 'refresh_token', + 'refresh_token': 'refresh token', + 'scope': 'scope1 scope2', + 'client_id': 'identifier' + })); + + return Future.value(http.Response( + jsonEncode({ + 'access_token': 'new access token', + 'token_type': 'bearer', + 'refresh_token': 'new refresh token' + }), + 200, + headers: {'content-type': 'application/json'})); + }); + + credentials = await credentials.refresh( + identifier: 'identifier', httpClient: httpClient); + expect(credentials.accessToken, equals('new access token')); + expect(credentials.refreshToken, equals('new refresh token')); + }); + + test('can refresh without client authentication', () async { + var credentials = oauth2.Credentials('access token', + refreshToken: 'refresh token', + tokenEndpoint: tokenEndpoint, + scopes: ['scope1', 'scope2']); + expect(credentials.canRefresh, true); + + httpClient.expectRequest((request) { + expect(request.method, equals('POST')); + expect(request.url.toString(), equals(tokenEndpoint.toString())); + expect( + request.bodyFields, + equals({ + 'grant_type': 'refresh_token', + 'refresh_token': 'refresh token', + 'scope': 'scope1 scope2' + })); + + return Future.value(http.Response( + jsonEncode({ + 'access_token': 'new access token', + 'token_type': 'bearer', + 'refresh_token': 'new refresh token' + }), + 200, + headers: {'content-type': 'application/json'})); + }); + + credentials = await credentials.refresh(httpClient: httpClient); + expect(credentials.accessToken, equals('new access token')); + expect(credentials.refreshToken, equals('new refresh token')); + }); + + test("uses the old refresh token if a new one isn't provided", () async { + var credentials = oauth2.Credentials('access token', + refreshToken: 'refresh token', tokenEndpoint: tokenEndpoint); + expect(credentials.canRefresh, true); + + httpClient.expectRequest((request) { + expect(request.method, equals('POST')); + expect(request.url.toString(), equals(tokenEndpoint.toString())); + expect( + request.bodyFields, + equals({ + 'grant_type': 'refresh_token', + 'refresh_token': 'refresh token' + })); + expect( + request.headers, + containsPair('Authorization', + 'Basic aWQlQzMlQUJudCVDNCVBQmZpZXI6cyVDMyVBQmNyZXQ=')); + + return Future.value(http.Response( + jsonEncode( + {'access_token': 'new access token', 'token_type': 'bearer'}), + 200, + headers: {'content-type': 'application/json'})); + }); + + credentials = await credentials.refresh( + identifier: 'idëntÄ«fier', secret: 'sëcret', httpClient: httpClient); + expect(credentials.accessToken, equals('new access token')); + expect(credentials.refreshToken, equals('refresh token')); + }); + + test('uses form-field authentication if basicAuth is false', () async { + var credentials = oauth2.Credentials('access token', + refreshToken: 'refresh token', + tokenEndpoint: tokenEndpoint, + scopes: ['scope1', 'scope2']); + expect(credentials.canRefresh, true); + + httpClient.expectRequest((request) { + expect(request.method, equals('POST')); + expect(request.url.toString(), equals(tokenEndpoint.toString())); + expect( + request.bodyFields, + equals({ + 'grant_type': 'refresh_token', + 'refresh_token': 'refresh token', + 'scope': 'scope1 scope2', + 'client_id': 'idëntÄ«fier', + 'client_secret': 'sëcret' + })); + + return Future.value(http.Response( + jsonEncode({ + 'access_token': 'new access token', + 'token_type': 'bearer', + 'refresh_token': 'new refresh token' + }), + 200, + headers: {'content-type': 'application/json'})); + }); + + credentials = await credentials.refresh( + identifier: 'idëntÄ«fier', + secret: 'sëcret', + basicAuth: false, + httpClient: httpClient); + expect(credentials.accessToken, equals('new access token')); + expect(credentials.refreshToken, equals('new refresh token')); + }); + + group('fromJson', () { + oauth2.Credentials fromMap(Map<String, dynamic> map) => + oauth2.Credentials.fromJson(jsonEncode(map)); + + test('should load the same credentials from toJson', () { + // Round the expiration down to milliseconds since epoch, since that's + // what the credentials file stores. Otherwise sub-millisecond time gets + // in the way. + var expiration = DateTime.now().subtract(const Duration(hours: 1)); + expiration = DateTime.fromMillisecondsSinceEpoch( + expiration.millisecondsSinceEpoch); + + var credentials = oauth2.Credentials('access token', + refreshToken: 'refresh token', + idToken: 'id token', + tokenEndpoint: tokenEndpoint, + scopes: ['scope1', 'scope2'], + expiration: expiration); + var reloaded = oauth2.Credentials.fromJson(credentials.toJson()); + + expect(reloaded.accessToken, equals(credentials.accessToken)); + expect(reloaded.refreshToken, equals(credentials.refreshToken)); + expect(reloaded.idToken, equals(credentials.idToken)); + expect(reloaded.tokenEndpoint.toString(), + equals(credentials.tokenEndpoint.toString())); + expect(reloaded.scopes, equals(credentials.scopes)); + expect(reloaded.expiration, equals(credentials.expiration)); + }); + + test('should throw a FormatException for invalid JSON', () { + expect( + () => oauth2.Credentials.fromJson('foo bar'), throwsFormatException); + }); + + test("should throw a FormatException for JSON that's not a map", () { + expect(() => oauth2.Credentials.fromJson('null'), throwsFormatException); + }); + + test('should throw a FormatException if there is no accessToken', () { + expect(() => fromMap({}), throwsFormatException); + }); + + test('should throw a FormatException if accessToken is not a string', () { + expect(() => fromMap({'accessToken': 12}), throwsFormatException); + }); + + test('should throw a FormatException if refreshToken is not a string', () { + expect(() => fromMap({'accessToken': 'foo', 'refreshToken': 12}), + throwsFormatException); + }); + + test('should throw a FormatException if idToken is not a string', () { + expect(() => fromMap({'accessToken': 'foo', 'idToken': 12}), + throwsFormatException); + }); + + test('should throw a FormatException if tokenEndpoint is not a string', () { + expect(() => fromMap({'accessToken': 'foo', 'tokenEndpoint': 12}), + throwsFormatException); + }); + + test('should throw a FormatException if scopes is not a list', () { + expect(() => fromMap({'accessToken': 'foo', 'scopes': 12}), + throwsFormatException); + }); + + test('should throw a FormatException if expiration is not an int', () { + expect(() => fromMap({'accessToken': 'foo', 'expiration': '12'}), + throwsFormatException); + }); + }); +}
diff --git a/pkgs/oauth2/test/handle_access_token_response_test.dart b/pkgs/oauth2/test/handle_access_token_response_test.dart new file mode 100644 index 0000000..4d7b519 --- /dev/null +++ b/pkgs/oauth2/test/handle_access_token_response_test.dart
@@ -0,0 +1,301 @@ +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; + +import 'package:http/http.dart' as http; +import 'package:oauth2/oauth2.dart' as oauth2; +import 'package:oauth2/src/handle_access_token_response.dart'; +import 'package:oauth2/src/parameters.dart'; +import 'package:test/test.dart'; + +import 'utils.dart'; + +final Uri tokenEndpoint = Uri.parse('https://example.com/token'); + +final DateTime startTime = DateTime.now(); + +oauth2.Credentials handle(http.Response response, + {GetParameters? getParameters}) => + handleAccessTokenResponse( + response, tokenEndpoint, startTime, ['scope'], ' ', + getParameters: getParameters); + +void main() { + group('an error response', () { + oauth2.Credentials handleError( + {String body = '{"error": "invalid_request"}', + int statusCode = 400, + Map<String, String> headers = const { + 'content-type': 'application/json' + }}) => + handle(http.Response(body, statusCode, headers: headers)); + + test('causes an AuthorizationException', () { + expect(handleError, throwsAuthorizationException); + }); + + test('with a 401 code causes an AuthorizationException', () { + expect(() => handleError(statusCode: 401), throwsAuthorizationException); + }); + + test('with an unexpected code causes a FormatException', () { + expect(() => handleError(statusCode: 500), throwsFormatException); + }); + + test('with no content-type causes a FormatException', () { + expect(() => handleError(headers: {}), throwsFormatException); + }); + + test('with a non-JSON content-type causes a FormatException', () { + expect(() => handleError(headers: {'content-type': 'text/plain'}), + throwsFormatException); + }); + + test('with a non-JSON, non-plain content-type causes a FormatException', + () { + expect(() => handleError(headers: {'content-type': 'image/png'}), + throwsFormatException); + }); + + test( + 'with a JSON content-type and charset causes an ' + 'AuthorizationException', () { + expect( + () => handleError( + headers: {'content-type': 'application/json; charset=UTF-8'}), + throwsAuthorizationException); + }); + + test('with invalid JSON causes a FormatException', () { + expect(() => handleError(body: 'not json'), throwsFormatException); + }); + + test('with a non-string error causes a FormatException', () { + expect(() => handleError(body: '{"error": 12}'), throwsFormatException); + }); + + test('with a non-string error_description causes a FormatException', () { + expect( + () => handleError( + body: jsonEncode( + {'error': 'invalid_request', 'error_description': 12})), + throwsFormatException); + }); + + test('with a non-string error_uri causes a FormatException', () { + expect( + () => handleError( + body: jsonEncode({'error': 'invalid_request', 'error_uri': 12})), + throwsFormatException); + }); + + test('with a string error_description causes a AuthorizationException', () { + expect( + () => handleError( + body: jsonEncode({ + 'error': 'invalid_request', + 'error_description': 'description' + })), + throwsAuthorizationException); + }); + + test('with a string error_uri causes a AuthorizationException', () { + expect( + () => handleError( + body: jsonEncode({ + 'error': 'invalid_request', + 'error_uri': 'http://example.com/error' + })), + throwsAuthorizationException); + }); + }); + + group('a success response', () { + oauth2.Credentials handleSuccess( + {String contentType = 'application/json', + Object? accessToken = 'access token', + Object? tokenType = 'bearer', + Object? expiresIn, + Object? refreshToken, + Object? scope}) { + return handle(http.Response( + jsonEncode({ + 'access_token': accessToken, + 'token_type': tokenType, + 'expires_in': expiresIn, + 'refresh_token': refreshToken, + 'scope': scope + }), + 200, + headers: {'content-type': contentType})); + } + + test('returns the correct credentials', () { + var credentials = handleSuccess(); + expect(credentials.accessToken, equals('access token')); + expect(credentials.tokenEndpoint.toString(), + equals(tokenEndpoint.toString())); + }); + + test('with no content-type causes a FormatException', () { + expect(() => handleSuccess(contentType: ''), throwsFormatException); + }); + + test('with a non-JSON content-type causes a FormatException', () { + expect(() => handleSuccess(contentType: 'text/plain'), + throwsFormatException); + }); + + test( + 'with a JSON content-type and charset returns the correct ' + 'credentials', () { + var credentials = + handleSuccess(contentType: 'application/json; charset=UTF-8'); + expect(credentials.accessToken, equals('access token')); + }); + + test('with a JavScript content-type returns the correct credentials', () { + var credentials = handleSuccess(contentType: 'text/javascript'); + expect(credentials.accessToken, equals('access token')); + }); + + test('with custom getParameters() returns the correct credentials', () { + var body = '_${jsonEncode({ + 'token_type': 'bearer', + 'access_token': 'access token' + })}'; + var credentials = handle( + http.Response(body, 200, headers: {'content-type': 'text/plain'}), + getParameters: (contentType, body) => + jsonDecode(body.substring(1)) as Map<String, dynamic>, + ); + expect(credentials.accessToken, equals('access token')); + expect(credentials.tokenEndpoint.toString(), + equals(tokenEndpoint.toString())); + }); + + test('throws a FormatException if custom getParameters rejects response', + () { + var response = http.Response( + jsonEncode({ + 'access_token': 'access token', + 'token_type': 'bearer', + 'expires_in': 24, + 'refresh_token': 'refresh token', + 'scope': 'scope', + }), + 200, + headers: {'content-type': 'foo/bar'}); + + expect( + () => handle(response, + getParameters: (contentType, body) => throw FormatException( + 'unsupported content-type: $contentType')), + throwsFormatException); + }); + + test('with a null access token throws a FormatException', () { + expect(() => handleSuccess(accessToken: null), throwsFormatException); + }); + + test('with a non-string access token throws a FormatException', () { + expect(() => handleSuccess(accessToken: 12), throwsFormatException); + }); + + test('with a null token type throws a FormatException', () { + expect(() => handleSuccess(tokenType: null), throwsFormatException); + }); + + test('with a non-string token type throws a FormatException', () { + expect(() => handleSuccess(tokenType: 12), throwsFormatException); + }); + + test('with a non-"bearer" token type throws a FormatException', () { + expect(() => handleSuccess(tokenType: 'mac'), throwsFormatException); + }); + + test('with a non-int expires-in throws a FormatException', () { + expect(() => handleSuccess(expiresIn: 'whenever'), throwsFormatException); + }); + + test( + 'with expires-in sets the expiration to ten seconds earlier than the ' + 'server says', () { + var credentials = handleSuccess(expiresIn: 100); + expect(credentials.expiration?.millisecondsSinceEpoch, + startTime.millisecondsSinceEpoch + 90 * 1000); + }); + + test('with expires-in encoded as string', () { + var credentials = handleSuccess(expiresIn: '110'); + expect(credentials.expiration?.millisecondsSinceEpoch, + startTime.millisecondsSinceEpoch + 100 * 1000); + }); + + test('with a non-string refresh token throws a FormatException', () { + expect(() => handleSuccess(refreshToken: 12), throwsFormatException); + }); + + test('with a refresh token sets the refresh token', () { + var credentials = handleSuccess(refreshToken: 'refresh me'); + expect(credentials.refreshToken, equals('refresh me')); + }); + + test('with a non-string scope throws a FormatException', () { + expect(() => handleSuccess(scope: 12), throwsFormatException); + }); + + test('with a scope sets the scopes', () { + var credentials = handleSuccess(scope: 'scope1 scope2'); + expect(credentials.scopes, equals(['scope1', 'scope2'])); + }); + + test('with a custom scope delimiter sets the scopes', () { + var response = http.Response( + jsonEncode({ + 'access_token': 'access token', + 'token_type': 'bearer', + 'expires_in': null, + 'refresh_token': null, + 'scope': 'scope1,scope2' + }), + 200, + headers: {'content-type': 'application/json'}); + var credentials = handleAccessTokenResponse( + response, tokenEndpoint, startTime, ['scope'], ','); + expect(credentials.scopes, equals(['scope1', 'scope2'])); + }); + }); + + group('a success response with a id_token', () { + oauth2.Credentials handleSuccess( + {String contentType = 'application/json', + Object? accessToken = 'access token', + Object? tokenType = 'bearer', + Object? expiresIn, + Object? idToken = 'decode me', + Object? scope}) { + return handle(http.Response( + jsonEncode({ + 'access_token': accessToken, + 'token_type': tokenType, + 'expires_in': expiresIn, + 'id_token': idToken, + 'scope': scope + }), + 200, + headers: {'content-type': contentType})); + } + + test('with a non-string id token throws a FormatException', () { + expect(() => handleSuccess(idToken: 12), throwsFormatException); + }); + + test('with a id token sets the id token', () { + var credentials = handleSuccess(idToken: 'decode me'); + expect(credentials.idToken, equals('decode me')); + }); + }); +}
diff --git a/pkgs/oauth2/test/resource_owner_password_grant_test.dart b/pkgs/oauth2/test/resource_owner_password_grant_test.dart new file mode 100644 index 0000000..7a5d9b5 --- /dev/null +++ b/pkgs/oauth2/test/resource_owner_password_grant_test.dart
@@ -0,0 +1,168 @@ +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +@TestOn('vm') +library; + +import 'dart:async'; +import 'dart:convert'; + +import 'package:http/http.dart' as http; +import 'package:oauth2/oauth2.dart' as oauth2; +import 'package:test/test.dart'; + +import 'utils.dart'; + +final success = jsonEncode({ + 'access_token': '2YotnFZFEjr1zCsicMWpAA', + 'token_type': 'bearer', + 'expires_in': 3600, + 'refresh_token': 'tGzv3JOkF0XG5Qx2TlKWIA', +}); + +String auth = 'Basic Y2xpZW50OnNlY3JldA=='; +Uri authEndpoint = Uri.parse('https://example.com'); + +void main() { + late ExpectClient expectClient; + + setUp(() => expectClient = ExpectClient()); + + group('basic', () { + test('builds correct request with client when using basic auth for client', + () async { + expectClient.expectRequest((request) async { + expect(auth, equals(request.headers['authorization'])); + expect(request.bodyFields['grant_type'], equals('password')); + expect(request.bodyFields['username'], equals('username')); + expect(request.bodyFields['password'], equals('userpass')); + return http.Response(success, 200, + headers: {'content-type': 'application/json'}); + }); + + var client = await oauth2.resourceOwnerPasswordGrant( + authEndpoint, 'username', 'userpass', + identifier: 'client', secret: 'secret', httpClient: expectClient); + + expect(client.credentials, isNotNull); + expect(client.credentials.accessToken, equals('2YotnFZFEjr1zCsicMWpAA')); + }); + + test('passes the onCredentialsRefreshed callback to the client', () async { + expectClient.expectRequest((request) async { + return http.Response( + jsonEncode({ + 'access_token': '2YotnFZFEjr1zCsicMWpAA', + 'token_type': 'bearer', + 'expires_in': -3600, + 'refresh_token': 'tGzv3JOkF0XG5Qx2TlKWIA', + }), + 200, + headers: {'content-type': 'application/json'}); + }); + + var isCallbackInvoked = false; + + var client = await oauth2.resourceOwnerPasswordGrant( + authEndpoint, 'username', 'userpass', + identifier: 'client', secret: 'secret', httpClient: expectClient, + onCredentialsRefreshed: (oauth2.Credentials credentials) { + isCallbackInvoked = true; + }); + + expectClient.expectRequest((request) { + return Future.value(http.Response( + jsonEncode( + {'access_token': 'new access token', 'token_type': 'bearer'}), + 200, + headers: {'content-type': 'application/json'})); + }); + + expectClient.expectRequest((request) { + return Future.value(http.Response('good job', 200)); + }); + + await client.read(Uri.parse('http://example.com/resource')); + expect(isCallbackInvoked, equals(true)); + }); + + test('builds correct request when using query parameters for client', + () async { + expectClient.expectRequest((request) async { + expect(request.bodyFields['grant_type'], equals('password')); + expect(request.bodyFields['client_id'], equals('client')); + expect(request.bodyFields['client_secret'], equals('secret')); + expect(request.bodyFields['username'], equals('username')); + expect(request.bodyFields['password'], equals('userpass')); + return http.Response(success, 200, + headers: {'content-type': 'application/json'}); + }); + + var client = await oauth2.resourceOwnerPasswordGrant( + authEndpoint, 'username', 'userpass', + identifier: 'client', + secret: 'secret', + basicAuth: false, + httpClient: expectClient); + expect(client.credentials, isNotNull); + expect(client.credentials.accessToken, equals('2YotnFZFEjr1zCsicMWpAA')); + }); + + test('builds correct request using scope', () async { + expectClient.expectRequest((request) async { + expect(request.bodyFields['grant_type'], equals('password')); + expect(request.bodyFields['username'], equals('username')); + expect(request.bodyFields['password'], equals('userpass')); + expect(request.bodyFields['scope'], equals('one two')); + return http.Response(success, 200, + headers: {'content-type': 'application/json'}); + }); + + var client = await oauth2.resourceOwnerPasswordGrant( + authEndpoint, 'username', 'userpass', + scopes: ['one', 'two'], httpClient: expectClient); + expect(client.credentials, isNotNull); + expect(client.credentials.accessToken, equals('2YotnFZFEjr1zCsicMWpAA')); + }); + + test('builds correct request using scope with custom delimiter', () async { + expectClient.expectRequest((request) async { + expect(request.bodyFields['grant_type'], equals('password')); + expect(request.bodyFields['username'], equals('username')); + expect(request.bodyFields['password'], equals('userpass')); + expect(request.bodyFields['scope'], equals('one,two')); + return http.Response(success, 200, + headers: {'content-type': 'application/json'}); + }); + + await oauth2.resourceOwnerPasswordGrant( + authEndpoint, 'username', 'userpass', + scopes: ['one', 'two'], httpClient: expectClient, delimiter: ','); + }); + + test('merges with existing query parameters', () async { + var authEndpoint = Uri.parse('https://example.com?query=value'); + + expectClient.expectRequest((request) async { + expect(request.bodyFields['grant_type'], equals('password')); + expect(request.bodyFields['client_id'], equals('client')); + expect(request.bodyFields['client_secret'], equals('secret')); + expect(request.bodyFields['username'], equals('username')); + expect(request.bodyFields['password'], equals('userpass')); + expect(request.url.queryParameters['query'], equals('value')); + return http.Response(success, 200, + headers: {'content-type': 'application/json'}); + }); + + var client = await oauth2.resourceOwnerPasswordGrant( + authEndpoint, 'username', 'userpass', + identifier: 'client', + secret: 'secret', + basicAuth: false, + httpClient: expectClient); + expect(client.credentials, isNotNull); + expect(client.credentials.accessToken, equals('2YotnFZFEjr1zCsicMWpAA')); + }); + }); +}
diff --git a/pkgs/oauth2/test/utils.dart b/pkgs/oauth2/test/utils.dart new file mode 100644 index 0000000..4f3b747 --- /dev/null +++ b/pkgs/oauth2/test/utils.dart
@@ -0,0 +1,49 @@ +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:collection' show Queue; + +import 'package:http/http.dart' as http; +import 'package:http/testing.dart'; +import 'package:oauth2/oauth2.dart' as oauth2; +import 'package:test/test.dart'; + +class ExpectClient extends MockClient { + final Queue<MockClientHandler> _handlers; + + ExpectClient._(super.fn) : _handlers = Queue<MockClientHandler>(); + + factory ExpectClient() { + late ExpectClient client; + client = ExpectClient._((request) => client._handleRequest(request)); + return client; + } + + void expectRequest(MockClientHandler fn) { + var completer = Completer<void>(); + expect(completer.future, completes); + + _handlers.add((request) { + completer.complete(null); + return fn(request); + }); + } + + Future<http.Response> _handleRequest(http.Request request) { + if (_handlers.isEmpty) { + return Future.value(http.Response('not found', 404)); + } else { + return _handlers.removeFirst()(request); + } + } +} + +/// A matcher for functions that throw AuthorizationException. +final Matcher throwsAuthorizationException = + throwsA(const TypeMatcher<oauth2.AuthorizationException>()); + +/// A matcher for functions that throw ExpirationException. +final Matcher throwsExpirationException = + throwsA(const TypeMatcher<oauth2.ExpirationException>());
diff --git a/pkgs/source_map_stack_trace/.gitignore b/pkgs/source_map_stack_trace/.gitignore new file mode 100644 index 0000000..f73b2f9 --- /dev/null +++ b/pkgs/source_map_stack_trace/.gitignore
@@ -0,0 +1,4 @@ +.dart_tool/ +.packages +.pub/ +pubspec.lock
diff --git a/pkgs/source_map_stack_trace/.test_config b/pkgs/source_map_stack_trace/.test_config new file mode 100644 index 0000000..531426a --- /dev/null +++ b/pkgs/source_map_stack_trace/.test_config
@@ -0,0 +1,5 @@ +{ + "test_package": { + "platforms": ["vm"] + } +} \ No newline at end of file
diff --git a/pkgs/source_map_stack_trace/AUTHORS b/pkgs/source_map_stack_trace/AUTHORS new file mode 100644 index 0000000..e8063a8 --- /dev/null +++ b/pkgs/source_map_stack_trace/AUTHORS
@@ -0,0 +1,6 @@ +# Below is a list of people and organizations that have contributed +# to the project. Names should be added to the list like so: +# +# Name/Organization <email address> + +Google Inc.
diff --git a/pkgs/source_map_stack_trace/CHANGELOG.md b/pkgs/source_map_stack_trace/CHANGELOG.md new file mode 100644 index 0000000..00c66d9 --- /dev/null +++ b/pkgs/source_map_stack_trace/CHANGELOG.md
@@ -0,0 +1,82 @@ +## 2.1.3-wip + +## 2.1.2 + +* Require Dart 3.3.0 +* Move to `dart-lang/tools` monorepo. + +## 2.1.1 + +* Populate the pubspec `repository` field. + +## 2.1.0 + +* Stable release for null safety. +* Require Dart 2.12 + +## 2.0.0 + +### Breaking Changes + +* Removed dependency on `package_resolver` and changed the apis to accept a + `Map<String, Uri>` which maps package names to the base uri to resolve the + `package:` uris for those packages. +* The `sdkRoot` argument must be an `Uri`. Use `Uri.parse` for use + cases previously passing a `String`. +* The deprecated `packageRoot` argument has been removed. + +## 1.1.5 + +* Set max SDK version to `<3.0.0`. + +## 1.1.4 + +* Support source maps that depend on the uri of the location to resolve spans + correctly. + +## 1.1.3 + +* Add a missing dependency on `path`. + +## 1.1.2 + +* Fix a typo in the previous fix. + +## 1.1.1 + +* Don't crash if the `SyncPackageResolver` has no package information at all. + +## 1.1.0 + +* `mapStackTrace()` now uses a `SyncPackageResolver` object from the + [`package_resolver` package][package_resolver] to recreate `package:` URIs. + +* **Deprecation**: the `packageRoot` parameter to `mapStackTrace` is deprecated + in favor of the `packageInfo` parameter described above. It will be removed in + a future release. + +[package_resolver]: https://pub.dartlang.org/packages/package_resolver + +## 1.0.5 + +* Add compatibility for member names that include named arguments. + +## 1.0.4 + +* Add compatibility for Dart 1.10-style name munging. + +## 1.0.3 + +* Prefer "dart:" URLs to "package:" URLs. + +## 1.0.2 + +* Fix an off-by-one bug that was causing line numbers to be slightly off. + +## 1.0.1 + +* Don't crash when mapping stack chains. + +## 1.0.0 + +* Initial release.
diff --git a/pkgs/source_map_stack_trace/LICENSE b/pkgs/source_map_stack_trace/LICENSE new file mode 100644 index 0000000..633672a --- /dev/null +++ b/pkgs/source_map_stack_trace/LICENSE
@@ -0,0 +1,27 @@ +Copyright 2015, the Dart project authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google LLC nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/pkgs/source_map_stack_trace/README.md b/pkgs/source_map_stack_trace/README.md new file mode 100644 index 0000000..9b11612 --- /dev/null +++ b/pkgs/source_map_stack_trace/README.md
@@ -0,0 +1,50 @@ +[](https://github.com/dart-lang/tools/actions/workflows/source_map_stack_trace.yml) +[](https://pub.dev/packages/source_map_stack_trace) +[](https://pub.dev/packages/source_map_stack_trace/publisher) + +`source_map_stack_trace` is a package for converting stack traces generated by +dart2js-compiled JavaScript code into readable native Dart stack traces using +source maps. For example: + +```dart +import 'package:source_map_stack_trace/source_map_stack_trace.dart'; + +void main() { + var jsTrace = // Get a StackTrace generated by dart2js. + var mapping = // Get a source map mapping the JS to the Dart source. + + // Convert jsTrace to refer to the Dart source instead. + var dartTrace = mapStackTrace(jsTrace, sourceMap); + print(dartTrace); +} +``` + +This can convert the following JavaScript trace: + +``` +expect_async_test.dart.browser_test.dart.js 2636:15 dart.wrapException +expect_async_test.dart.browser_test.dart.js 14661:15 main__closure16.call$0 +expect_async_test.dart.browser_test.dart.js 18237:26 Declarer_test__closure.call$1 +expect_async_test.dart.browser_test.dart.js 17905:23 StackZoneSpecification_registerUnaryCallback__closure.call$0 +expect_async_test.dart.browser_test.dart.js 17876:16 StackZoneSpecification._stack_zone_specification$_run$2 +expect_async_test.dart.browser_test.dart.js 17899:26 StackZoneSpecification_registerUnaryCallback_closure.call$1 +expect_async_test.dart.browser_test.dart.js 6115:16 _rootRunUnary +expect_async_test.dart.browser_test.dart.js 8576:39 _CustomZone.runUnary$2 +expect_async_test.dart.browser_test.dart.js 7135:57 _Future__propagateToListeners_handleValueCallback.call$0 +expect_async_test.dart.browser_test.dart.js 7031:147 dart._Future.static._Future__propagateToListeners +``` + +to: + +``` +dart:_internal/compiler/js_lib/js_helper.dart 1210:1 wrapException +test/frontend/expect_async_test.dart 24:5 main.<fn>.<fn> +package:test/src/backend/declarer.dart 45:48 Declarer.test.<fn>.<fn> +package:stack_trace/src/stack_zone_specification.dart 134:30 StackZoneSpecification.registerUnaryCallback.<fn>.<fn> +package:stack_trace/src/stack_zone_specification.dart 210:7 StackZoneSpecification._run +package:stack_trace/src/stack_zone_specification.dart 135:5 StackZoneSpecification.registerUnaryCallback.<fn> +dart:async/zone.dart 904:14 _rootRunUnary +dart:async/zone.dart 806:3 _CustomZone.runUnary +dart:async/future_impl.dart 486:13 _Future._propagateToListeners.handleValueCallback +dart:async/future_impl.dart 567:32 _Future._propagateToListeners +```
diff --git a/pkgs/source_map_stack_trace/analysis_options.yaml b/pkgs/source_map_stack_trace/analysis_options.yaml new file mode 100644 index 0000000..5ee158a --- /dev/null +++ b/pkgs/source_map_stack_trace/analysis_options.yaml
@@ -0,0 +1,7 @@ +# https://dart.dev/tools/analysis#the-analysis-options-file +include: package:dart_flutter_team_lints/analysis_options.yaml + +analyzer: + language: + strict-casts: true + strict-raw-types: true
diff --git a/pkgs/source_map_stack_trace/lib/source_map_stack_trace.dart b/pkgs/source_map_stack_trace/lib/source_map_stack_trace.dart new file mode 100644 index 0000000..a3925cd --- /dev/null +++ b/pkgs/source_map_stack_trace/lib/source_map_stack_trace.dart
@@ -0,0 +1,104 @@ +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:path/path.dart' as p; +import 'package:source_maps/source_maps.dart'; +import 'package:stack_trace/stack_trace.dart'; + +/// Convert [stackTrace], a stack trace generated by dart2js-compiled +/// JavaScript, to a native-looking stack trace using [sourceMap]. +/// +/// [minified] indicates whether or not the dart2js code was minified. If it +/// hasn't, this tries to clean up the stack frame member names. +/// +/// The [packageMap] maps package names to the base uri used to resolve the +/// `package:` uris for those packages. It is used to it's used to reconstruct +/// `package:` URIs for stack frames that come from packages. +/// +/// [sdkRoot] is the URI surfaced in the stack traces for SDK libraries. +/// If it's passed, stack frames from the SDK will have `dart:` URLs. +StackTrace mapStackTrace(Mapping sourceMap, StackTrace stackTrace, + {bool minified = false, Map<String, Uri>? packageMap, Uri? sdkRoot}) { + if (stackTrace is Chain) { + return Chain(stackTrace.traces.map((trace) { + return Trace.from(mapStackTrace(sourceMap, trace, + minified: minified, packageMap: packageMap, sdkRoot: sdkRoot)); + })); + } + + var sdkLib = sdkRoot == null ? null : '$sdkRoot/lib'; + + var trace = Trace.from(stackTrace); + return Trace(trace.frames.map((frame) { + var line = frame.line; + // If there's no line information, there's no way to translate this frame. + // We could return it as-is, but these lines are usually not useful anyways. + if (line == null) return null; + + // If there's no column, try using the first column of the line. + var column = frame.column ?? 0; + + // Subtract 1 because stack traces use 1-indexed lines and columns and + // source maps uses 0-indexed. + var span = + sourceMap.spanFor(line - 1, column - 1, uri: frame.uri.toString()); + + // If we can't find a source span, ignore the frame. It's probably something + // internal that the user doesn't care about. + if (span == null) return null; + + var sourceUrl = span.sourceUrl.toString(); + if (sdkLib != null && p.url.isWithin(sdkLib, sourceUrl)) { + sourceUrl = 'dart:${p.url.relative(sourceUrl, from: sdkLib)}'; + } else if (packageMap != null) { + for (var package in packageMap.keys) { + var packageUrl = packageMap[package].toString(); + if (!p.url.isWithin(packageUrl, sourceUrl)) continue; + + sourceUrl = + 'package:$package/${p.url.relative(sourceUrl, from: packageUrl)}'; + break; + } + } + + return Frame( + Uri.parse(sourceUrl), + span.start.line + 1, + span.start.column + 1, + // If the dart2js output is minified, there's no use trying to prettify + // its member names. Use the span's identifier if available, otherwise + // use the minified member name. + minified + ? (span.isIdentifier ? span.text : frame.member) + : _prettifyMember(frame.member!)); + }).whereType<Frame>()); +} + +/// Reformats a JS member name to make it look more Dart-like. +String _prettifyMember(String member) { + return member + // Get rid of the noise that Firefox sometimes adds. + .replaceAll(RegExp(r'/?<$'), '') + // Get rid of arity indicators and named arguments. + .replaceAll(RegExp(r'\$\d+(\$[a-zA-Z_0-9]+)*$'), '') + // Convert closures to <fn>. + .replaceAllMapped( + RegExp(r'(_+)closure\d*\.call$'), + // The number of underscores before "closure" indicates how nested it + // is. + (match) => '.<fn>' * match[1]!.length) + // Get rid of explicitly-generated calls. + .replaceAll(RegExp(r'\.call$'), '') + // Get rid of the top-level method prefix. + .replaceAll(RegExp(r'^dart\.'), '') + // Get rid of library namespaces. + .replaceAll(RegExp(r'[a-zA-Z_0-9]+\$'), '') + // Get rid of the static method prefix. The class name also exists in the + // invocation, so we're not getting rid of any information. + .replaceAll(RegExp(r'^[a-zA-Z_0-9]+.(static|dart).'), '') + // Convert underscores after identifiers to dots. This runs the risk of + // incorrectly converting members that contain underscores, but those are + // contrary to the style guide anyway. + .replaceAllMapped(RegExp(r'([a-zA-Z0-9]+)_'), (match) => '${match[1]!}.'); +}
diff --git a/pkgs/source_map_stack_trace/pubspec.yaml b/pkgs/source_map_stack_trace/pubspec.yaml new file mode 100644 index 0000000..d4b8c3a --- /dev/null +++ b/pkgs/source_map_stack_trace/pubspec.yaml
@@ -0,0 +1,17 @@ +name: source_map_stack_trace +version: 2.1.3-wip +description: A package for applying source maps to stack traces. +repository: https://github.com/dart-lang/tools/tree/main/pkgs/source_map_stack_trace + +environment: + sdk: ^3.3.0 + +dependencies: + path: ^1.8.0 + source_maps: ^0.10.10 + stack_trace: ^1.10.0 + +dev_dependencies: + dart_flutter_team_lints: ^3.0.0 + source_span: ^1.8.0 + test: ^1.16.0
diff --git a/pkgs/source_map_stack_trace/test/source_map_stack_trace_test.dart b/pkgs/source_map_stack_trace/test/source_map_stack_trace_test.dart new file mode 100644 index 0000000..dd4d710 --- /dev/null +++ b/pkgs/source_map_stack_trace/test/source_map_stack_trace_test.dart
@@ -0,0 +1,264 @@ +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:path/path.dart' as p; +import 'package:source_map_stack_trace/source_map_stack_trace.dart'; +import 'package:source_maps/source_maps.dart'; +import 'package:source_span/source_span.dart'; +import 'package:stack_trace/stack_trace.dart'; +import 'package:test/test.dart'; + +/// A simple [Mapping] for tests that don't need anything special. +final _simpleMapping = parseJson((SourceMapBuilder() + ..addSpan( + SourceMapSpan.identifier( + SourceLocation(1, line: 1, column: 3, sourceUrl: 'foo.dart'), + 'qux'), + SourceSpan(SourceLocation(8, line: 5, column: 0), + SourceLocation(18, line: 15, column: 0), '\n' * 10))) + .build('foo.dart.js.map')); + +final _packageMap = { + 'bar': Uri.parse('packages/bar'), + 'foo': Uri.parse('packages/foo'), +}; + +void main() { + test('maps a JS line and column to a Dart line and span', () { + var trace = Trace.parse('foo.dart.js 10:11 foo'); + var frame = _mapTrace(_simpleMapping, trace).frames.first; + expect(frame.uri, equals(Uri.parse('foo.dart'))); + + // These are +1 because stack_trace is 1-based whereas source_span is + // 0-basd. + expect(frame.line, equals(2)); + expect(frame.column, equals(4)); + }); + + test('ignores JS frames without line info', () { + var trace = Trace.parse(''' +foo.dart.js 10:11 foo +foo.dart.js bar +foo.dart.js 10:11 baz +'''); + var frames = _mapTrace(_simpleMapping, trace).frames; + + expect(frames.length, equals(2)); + expect(frames.first.member, equals('foo')); + expect(frames.last.member, equals('baz')); + }); + + test('ignores JS frames without corresponding spans', () { + var trace = Trace.parse(''' +foo.dart.js 10:11 foo +foo.dart.js 1:1 bar +foo.dart.js 10:11 baz +'''); + + var frames = _mapTrace(_simpleMapping, trace).frames; + + expect(frames.length, equals(2)); + expect(frames.first.member, equals('foo')); + expect(frames.last.member, equals('baz')); + }); + + test('include frames from JS files not covered by the source map bundle', () { + var trace = Trace.parse(''' +foo.dart.js 10:11 foo +jquery.js 10:1 foo +bar.dart.js 10:11 foo +'''); + var builder = SourceMapBuilder() + ..addSpan( + SourceMapSpan.identifier( + SourceLocation(1, + line: 1, column: 3, sourceUrl: 'packages/foo/foo.dart'), + 'qux'), + SourceSpan(SourceLocation(8, line: 5, column: 0), + SourceLocation(12, line: 9, column: 1), '\n' * 4)); + var sourceMapJson1 = builder.build('foo.dart.js.map'); + sourceMapJson1['file'] = 'foo.dart.js'; + + builder = SourceMapBuilder() + ..addSpan( + SourceMapSpan.identifier( + SourceLocation(1, + line: 1, column: 3, sourceUrl: 'packages/bar/bar.dart'), + 'qux'), + SourceSpan(SourceLocation(8, line: 5, column: 0), + SourceLocation(12, line: 9, column: 1), '\n' * 4)); + var sourceMapJson2 = builder.build('bar.dart.js.map'); + sourceMapJson2['file'] = 'bar.dart.js'; + + var bundle = [sourceMapJson1, sourceMapJson2]; + var mapping = parseJsonExtended(bundle); + var frames = _mapTrace(mapping, trace, packageMap: _packageMap).frames; + + expect(frames.length, equals(3)); + + var frame = frames[0]; + expect(frame.uri, equals(Uri.parse('package:foo/foo.dart'))); + expect(frame.line, equals(2)); + expect(frame.column, equals(4)); + + frame = frames[1]; + expect(p.basename(frame.uri.toString()), equals('jquery.js')); + expect(frame.line, equals(10)); + + frame = frames[2]; + expect(frame.uri, equals(Uri.parse('package:bar/bar.dart'))); + expect(frame.line, equals(2)); + expect(frame.column, equals(4)); + }); + + test('falls back to column 0 for unlisted column', () { + var trace = Trace.parse('foo.dart.js 10 foo'); + var builder = SourceMapBuilder() + ..addSpan( + SourceMapSpan.identifier( + SourceLocation(1, line: 1, column: 3, sourceUrl: 'foo.dart'), + 'qux'), + SourceSpan(SourceLocation(8, line: 5, column: 0), + SourceLocation(12, line: 9, column: 1), '\n' * 4)); + + var mapping = parseJson(builder.build('foo.dart.js.map')); + var frame = _mapTrace(mapping, trace).frames.first; + expect(frame.uri, equals(Uri.parse('foo.dart'))); + expect(frame.line, equals(2)); + expect(frame.column, equals(4)); + }); + + test('uses package: URIs for frames within a packageResolver.packageMap URL', + () { + var trace = Trace.parse('foo.dart.js 10 foo'); + var builder = SourceMapBuilder() + ..addSpan( + SourceMapSpan.identifier( + SourceLocation(1, + line: 1, column: 3, sourceUrl: 'packages/foo/foo.dart'), + 'qux'), + SourceSpan(SourceLocation(8, line: 5, column: 0), + SourceLocation(12, line: 9, column: 1), '\n' * 4)); + + var mapping = parseJson(builder.build('foo.dart.js.map')); + var mappedTrace = _mapTrace(mapping, trace, packageMap: _packageMap); + var frame = mappedTrace.frames.first; + expect(frame.uri, equals(Uri.parse('package:foo/foo.dart'))); + expect(frame.line, equals(2)); + expect(frame.column, equals(4)); + }); + + test('uses dart: URIs for frames within sdkRoot', () { + var trace = Trace.parse('foo.dart.js 10 foo'); + var builder = SourceMapBuilder() + ..addSpan( + SourceMapSpan.identifier( + SourceLocation(1, + line: 1, column: 3, sourceUrl: 'sdk/lib/async/foo.dart'), + 'qux'), + SourceSpan(SourceLocation(8, line: 5, column: 0), + SourceLocation(12, line: 9, column: 1), '\n' * 4)); + + var mapping = parseJson(builder.build('foo.dart.js.map')); + var frame = + _mapTrace(mapping, trace, sdkRoot: Uri.parse('sdk/')).frames.first; + expect(frame.uri, equals(Uri.parse('dart:async/foo.dart'))); + expect(frame.line, equals(2)); + expect(frame.column, equals(4)); + }); + + test('converts a stack chain', () { + var trace = Chain([ + Trace.parse('foo.dart.js 10:11 foo'), + Trace.parse('foo.dart.js 10:11 bar') + ]); + var traces = _mapChain(_simpleMapping, trace).traces; + + var frame = traces.first.frames.single; + expect(frame.uri, equals(Uri.parse('foo.dart'))); + expect(frame.member, equals('foo')); + expect(frame.line, equals(2)); + expect(frame.column, equals(4)); + + frame = traces.last.frames.single; + expect(frame.uri, equals(Uri.parse('foo.dart'))); + expect(frame.member, equals('bar')); + expect(frame.line, equals(2)); + expect(frame.column, equals(4)); + }); + + group('cleans up', () { + test('Firefox junk', () { + expect(_prettify('foo/<'), equals('foo')); + expect(_prettify('foo<'), equals('foo')); + }); + + test('arity indicators', () { + expect(_prettify(r'foo$1'), equals('foo')); + expect(_prettify(r'foo$1234'), equals('foo')); + }); + + test('named arguments', () { + expect(_prettify(r'foo$1$bar'), equals('foo')); + expect(_prettify(r'foo$123$bar$bang$qux'), equals('foo')); + }); + + test('closures', () { + expect(_prettify('foo_closure.call'), equals('foo.<fn>')); + }); + + test('nested closures', () { + expect(_prettify('foo__closure.call'), equals('foo.<fn>.<fn>')); + expect( + _prettify('foo____closure.call'), equals('foo.<fn>.<fn>.<fn>.<fn>')); + }); + + test('.call', () { + expect(_prettify('foo.call'), equals('foo')); + }); + + test('top-level functions', () { + expect(_prettify('dart.foo'), equals('foo')); + }); + + test('library namespaces', () { + expect(_prettify(r'my_library$foo'), equals('foo')); + }); + + test('static methods', () { + expect(_prettify(r'Foo.static.foo'), equals('foo')); + }); + + test('instance methods', () { + expect(_prettify(r'Foo_bar__baz'), equals('Foo.bar._baz')); + }); + + test('lots of stuff', () { + expect(_prettify(r'lib$Foo.static.lib$Foo_closure.call$0/<'), + equals('Foo.<fn>')); + }); + }); +} + +/// Like [mapStackTrace], but is guaranteed to return a [Trace] so it can be +/// inspected. +Trace _mapTrace(Mapping sourceMap, StackTrace stackTrace, + {bool minified = false, Map<String, Uri>? packageMap, Uri? sdkRoot}) { + return Trace.from(mapStackTrace(sourceMap, stackTrace, + minified: minified, packageMap: packageMap, sdkRoot: sdkRoot)); +} + +/// Like [mapStackTrace], but is guaranteed to return a [Chain] so it can be +/// inspected. +Chain _mapChain(Mapping sourceMap, StackTrace stackTrace, + {bool minified = false, Map<String, Uri>? packageMap, Uri? sdkRoot}) { + return Chain.forTrace(mapStackTrace(sourceMap, stackTrace, + minified: minified, packageMap: packageMap, sdkRoot: sdkRoot)); +} + +/// Runs the mapper's prettification logic on [member] and returns the result. +String? _prettify(String member) { + var trace = Trace([Frame(Uri.parse('foo.dart.js'), 10, 11, member)]); + return _mapTrace(_simpleMapping, trace).frames.first.member; +}
diff --git a/pkgs/unified_analytics/.gitignore b/pkgs/unified_analytics/.gitignore new file mode 100644 index 0000000..9377e38 --- /dev/null +++ b/pkgs/unified_analytics/.gitignore
@@ -0,0 +1,14 @@ +# Files and directories created by pub. +.dart_tool/ +.packages + +# Conventional directory for build outputs. +build/ + +# Omit committing pubspec.lock for library packages; see +# https://dart.dev/guides/libraries/private-files#pubspeclock. +pubspec.lock + +.vscode/ +coverage/ +*.DS_Store
diff --git a/pkgs/unified_analytics/CHANGELOG.md b/pkgs/unified_analytics/CHANGELOG.md new file mode 100644 index 0000000..86d0110 --- /dev/null +++ b/pkgs/unified_analytics/CHANGELOG.md
@@ -0,0 +1,173 @@ +## 6.1.4 + +- Fix formatting and remove dependency on `package:intl`. +- Remove direct usage of `package:path` in favor of `package:file`. +- Added `androidAppId` and `iosBundleId` to the `Event.devtoolsEvent` constructor. + +## 6.1.3 + +- Require Dart 3.4. +- Added `isWasm` parameter to the `Event.devtoolsEvent` constructor. +- Added an optional parameter `data` to the `Event.exception` constructor. + +## 6.1.2 + +- Avoid opening large telemetry log files to prevent out of memory errors. + +## 6.1.1 + +- Fixed bug where calling `Analytics.send` could result in a `FileSystemException` when unable to write to a log file. + +## 6.1.0 + +- Added new event constructor `Event.devtoolsEvent` for the single devtools event with a new enum value `DashEvent.devtoolsEvent` + +## 6.0.0 + +- Consolidate `Session` functionality into `UserProperty` to prevent race condition crash where session logic crashed before initializing `UserProperty` +- Get rid of `late` variables throughout implementation class, `AnalyticsImpl` +- Any error events (`Event.analyticsException`) encountered within package will be sent when invoking `Analytics.close`; replacing `ErrorHandler` functionality +- Exposing new method for `FakeAnalytics.sendPendingErrorEvents` to send error events on command +- Added `Event.fromJson` static method to generate instance of `Event` from JSON +- Remove unused parameters `measurementId` and `apiSecret` from the `Analytics.test` constructor +- Remove `Analytics.test` factory constructor in favor of `Analytics.fake` static method to return a `FakeAnalytics` instance +- Remove `FakeAnalytics` default constructor in favor of `Analytics.fake` + +## 5.8.8 + +- [Bug fix](https://github.com/dart-lang/tools/issues/252) rewrite the other call site for the session file + +## 5.8.7 + +- [Bug fix](https://github.com/dart-lang/tools/issues/252) to rewrite the `last_ping` key into the session json file + +## 5.8.6 + +- Refactored session handler class to use the last modified timestamp as the last ping value to prevent writing to file with each send +- Bumping intl package to 0.19.0 to fix version solving issue with flutter_tools + +## 5.8.5 + +- Fix late initialization error for `Analytics.userProperty` [bug](https://github.com/dart-lang/tools/issues/238) + +## 5.8.4 + +- Exporting all enums from [`enums.dart`](https://github.com/dart-lang/tools/blob/main/pkgs/unified_analytics/lib/src/enums.dart) through `lib/testing.dart` + +## 5.8.3 + +- [Fix bug](https://github.com/flutter/flutter/issues/143792) when parsing session json file + +## 5.8.2 + +- Added new event `Event.analyticsException` to track internal errors for this package +- Redirecting the `Analytics.test` factory to return an instance of `FakeAnalytics` +- Exposing new helper function that can be used to parse the Dart SDK version + +## 5.8.1 + +- Refactor logic for `okToSend` and `shouldShowMessage` +- Check devtools config file for legacy opt out status + +## 5.8.0 + +- Fix template string for consent message +- Add `enabledFeatures` to constructor to collect features enabled for each dash tool + +## 5.7.0 + +- Added the `Event.commandUsageValues` constructor + +## 5.6.0 + +- Added the `Event.timing` constructor + +## 5.5.0 + +- Edit to the `Event.flutterCommandResult` constructor to add `commandHasTerminal` +- Added timeout for `Analytics.setTelemetry` to prevent the clients from hanging +- Added the `Event.appleUsageEvent` constructor +- Added the `Event.exception` constructor + +## 5.4.0 + +- Added the `Event.codeSizeAnalysis` constructor + +## 5.3.0 + +- User property "host_os_version" added to provide detail version information about the host +- User property "locale" added to provide language related information +- User property "client_ide" (optional) added to provide the IDE used by the Dash tool using this package, if applicable +- Added the `Event.flutterCommandResult` constructor + +## 5.2.0 + +- Added the `Event.hotRunnerInfo` constructor + +## 5.1.0 + +- Added the `Event.flutterBuildInfo` constructor + +## 5.0.0 + +- Update to the latest version of `package:dart_flutter_team_lints` +- Using internal futures list to store send events +- Added the `Event.doctorValidatorResult` constructor + +## 4.0.1 + +- Adding constant for the NoOpAnalytics instance client ID to enable clients to reference it in tests + +## 4.0.0 + +- Enhanced `LogFileStats` data to include information about flutter channel counts and tool counts +- Added new method to suppress telemetry collection temporarily for current invocation via `analytics.suppressTelemetry()` +- Added `SurveyHandler` feature to `Analytics` instance to fetch available surveys from remote endpoint to display to users along with functionality to dismiss them +- Surveys will be disabled for any users that have been opted out +- Shipping `FakeAnalytics` for clients of this tool that need to ensure workflows are sending events in tests +- Adding getter to `Analytics` instance to fetch the client ID being sent to GA4 + +## 3.0.0 + +- Allow latest package versions for `file` and `http` +- Introducing new `Event` class that will standardize what event data can be sent with each event +- Deprecating the `sendEvent` method in favor of the `send` method + +## 2.0.0 + +- Refactoring `dateStamp` utility function to be defined in `utils.dart` instead of having static methods in `Initializer` and `ConfigHandler` +- Remove the `pddFlag` now that the revisions to the PDD have been finalized to persist data in the log file and session json file +- Opting out will now delete the contents of the CLIENT ID, session json, and log files; opting back in will regenerate them as events send +- `enableAsserts` parameter added to constructors for `Analytics` to check body of POST request for Google Analytics 4 limitations +- Now checking if write permissions are enabled for user's home directory, if not allowed, `NoOpAnalytics` returned by `Analytics` factory constructor + +## 1.1.0 + +- Added a `okToSend` getter so that clients can easily and accurately check the state of the consent mechanism. +- Initialize the config file with user opted out if user was opted out in legacy Flutter and Dart analytics + +## 1.0.1 + +- Error handling on the `analytics.sendEvent(...)` method to silently error out and return a `500` http status code to let tools using this package know Google Analytics did not receive the event (all successful requests will have a status code of `2xx` provided by Google Analytics) + +## 1.0.0 + +- Error handling functionality added to prevent malformed session json data from causing a crash +- Creating a new analytics constructor to point to a test instance of Google Analytics for developers +- Align supported tool list with PDD +- Exposing a new instance method that will need to be invoked when a client has successfully shown the consent message to the user `clientShowedMessage()` +- Adding and incrementing a tool's version will automatically use the current consent message version instead of incrementing by 1 +- Default constructor has disabled the usage of local log file and session json file until revisions have landed to the privacy document + +## 0.1.2 + +- Implemented fake Google Analytics Client for `Analytics.test(...)` constructor; marked with visible for testing annotation + +## 0.1.1 + +- Bumping intl package to 0.18.0 to fix version solving issue with flutter_tools +- LogFileStats includes more information about how many events are persisted and total count of how many times each event was sent + +## 0.1.0 + +- Initial version
diff --git a/pkgs/unified_analytics/LICENSE b/pkgs/unified_analytics/LICENSE new file mode 100644 index 0000000..ac90031 --- /dev/null +++ b/pkgs/unified_analytics/LICENSE
@@ -0,0 +1,27 @@ +Copyright 2023, the Dart project authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google LLC nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file
diff --git a/pkgs/unified_analytics/README.md b/pkgs/unified_analytics/README.md new file mode 100644 index 0000000..4263cfb --- /dev/null +++ b/pkgs/unified_analytics/README.md
@@ -0,0 +1,17 @@ +[](https://github.com/dart-lang/tools/actions/workflows/unified_analytics.yml) +[](https://pub.dev/packages/unified_analytics) +[](https://pub.dev/packages/unified_analytics/publisher) + +## What's this? + +This package is intended to be used on Dart and Flutter related +tooling only. It provides APIs to send events to Google Analytics using the +Measurement Protocol. + +This is not intended to be general purpose or consumed by the community. It is +responsible for toggling analytics collection for related tooling on each +developer's machine. + +## Using this package + +Refer to the [usage guide](USAGE_GUIDE.md).
diff --git a/pkgs/unified_analytics/USAGE_GUIDE.md b/pkgs/unified_analytics/USAGE_GUIDE.md new file mode 100644 index 0000000..ef5bbea --- /dev/null +++ b/pkgs/unified_analytics/USAGE_GUIDE.md
@@ -0,0 +1,202 @@ +This package is intended to be used on Dart and Flutter related tooling only. +It provides APIs to send events to Google Analytics using the Measurement Protocol. + +## Usage + +To get started using this package, import at the entrypoint dart file and +initialize with the required parameters. + +The example file shows an end-to-end usage guide for using this package and +can be referred to here [unified_analytics_example.dart](example/unified_analytics_example.dart). + +**IMPORTANT**: It is best practice to close the http client connection when finished +sending events, otherwise, you may notice that the dart process hangs on exit. The example below +shows how to handle closing the connection via `analytics.close()` method. + +[Link to documentation for http client's close method](https://pub.dev/documentation/http/latest/http/Client-class.html) + + +## Opting In and Out of Analytics Collection + +It will be important for each tool to expose a trivial method to +disabling or enabling analytics collection. Based on how the user interacts +with the tool, this can be done through the CLI, IDE, etc. The tool will +then pass a boolean to an API exposed by the package as shown below. + +```dart +// Begin by initializing the class +final Analytics analytics = Analytics(...); + +// The boolean below simulates the user deciding to opt-out +// of Analytics collection +final bool status = false; + +// Call the method to pass the boolean +analytics.setTelemetry(status); +``` + +## Displaying Consent Message to Users + +When a user first uses any tool with this package enabled, the tool using +this package will need to ensure that the user has seen the consent message. +The tool using this package should check with the `Analytics` instance +by invoking the `shouldShowMessage` getter. When this getter returns +`true`, this means that the user has not been enrolled into analytics +collection yet. It is at this point that the tool using this package will +invoke the `getConsentMessage` getter to return a string to share with the +user (each tool will have their own method of displaying the message +through cli stdout, popup modal, etc.). Once the message has been shown, +the tool using this package will need to confirm to the `Analytics` instance +that it has shown the message; it is at this point that the user has +officially been onboarded to analytics collection. + + + +```dart +// Begin by initializing the class near the entrypoint +final Analytics analytics = Analytics(...); + +// This conditional should always run; the first time it is run, this +// will return true since the consent message has never been shown +if (analytics.shouldShowMessage) { + + // Simulates displaying the message, this will vary from + // client to client; ie. stdout, popup in IDE, etc. + print(analytics.getConsentMessage); + + // After receiving confirmation that the message has been + // displayed, invoking the below method will successfully + // onboard the tool into the config file and allow for + // events to be sent on the next creation of the analytics + // instance + analytics.clientShowedMessage(); +} +``` + +## Checking User Opt-In Status + +Some tools may need to know if the user has opted in for Analytics +collection in order to enable additional functionality. The example below +shows how to check the status. + +```dart +// Begin by initializing the class +final Analytics analytics = Analytics(...); + +// This getter will return a boolean showing the status; +// print statement used for trivial usage example +print('This user's status: ${analytics.telemetryEnabled}'); // true if opted-in +``` + +## Checking for New Versions of Consent Message + +In the event that the package consent messaging needs has been updated, an +API has been exposed on an instance of `Analytics` that will notify the tool +using this package whether to display the message again. + +```dart +// Begin by initializing the class +// +// This is assuming that the tool has already been onboarded +// and that the user has already seen the previous version of +// the consent message +final Analytics analytics = Analytics(...); + + +// Much like the first example, if there is a new version of +// the tools message that needs to be shown, use the same work +// workflow +if (analytics.shouldShowMessage) { + + // Simulates displaying the message, this will vary from + // client to client; ie. stdout, popup in IDE, etc. + print(analytics.getConsentMessage); + + // After receiving confirmation that the message has been + // displayed, invoking the below method will successfully + // onboard the tool into the config file and allow for + // events to be sent on the next creation of the analytics + // instance + analytics.clientShowedMessage(); +} +``` + +It is important to note events will not be sent if there is a new version of +the consent message. + +## Developing Within `package:unified_analytics` + +### Adding new data classes + +#### User properties +In Google Analytics, new data fields can be collected as user properties +or events. + +User properties are key-value pairs that can be used to segment users. For example, +the Flutter channel used. To request that a new user property +be added, file an issue [using this template](https://github.com/dart-lang/tools/issues/new?template=unified_analytics_user_property.yml). + +To add a new user property, add a new property to the `UserProperty` class +in the [`user_property.dart` file](./lib/src/user_property.dart). + +#### Events +Events are actions that the user, or tool, performs. In Google Analytics, +events can have associated data. This event data is stored +in key-value pairs. + +To request new events, or event data, file an issue +[using this template](https://github.com/dart-lang/tools/issues/new?template=unified_analytics_event.yml). + +To add a new event, create a new field in the `DashEvent` enum (if necessary) in +the [`enums.dart` file](./lib/src/enums.dart). + +Then, add event data, create a new constructor for the `Event` class +in the [`event.dart` file](./lib/src/event.dart). + + +### Testing event collection + +When contributing to this package, if the developer needs to verify that +events have been sent, the developer should the use development constructor +so that the events being sent are not going into the production instance. + +```dart +final Analytics analytics = Analytics.development(...); +``` + +Reach out to maintainers to get access to the test Google Analytics endpoint. + +## Advanced Usage: Querying Locally Persisted Logs + +This package enables tools to persist the events that have been sent +to Google Analytics for logging by default. This can be very helpful if +tools would like to understand the user's activity level across all +related tooling. For example, if querying the locally persisted logs +shows that the user has not been active for N number of days, a tool that +works within an IDE can prompt the user with a survey to understand why their +level of activity has dropped. + +The snippet below shows how to invoke the query and a sample response. + +```dart +// Begin by initializing the class +final Analytics analytics = Analytics(...); + +// Printing the query results returns json formatted +// string to view; data can also be accessed through +// [LogFileStats] getters +print(analytics.logFileStats()); +``` +Refer to the `LogFileStats` instance [variables](lib/src/log_handler.dart) for details on the result. + +Explanation of the each key above + +- startDateTime: the earliest event that was sent +- minsFromStartDateTime: the number of minutes elapsed since the earliest message +- endDateTime: the latest, most recent event that was sent +- minsFromEndDateTime: the number of minutes elapsed since the latest message +- sessionCount: count of sessions; sessions have a minimum time of 30 minutes +- flutterChannelCount: count of flutter channels (can be 0 if developer is a Dart dev only) +- toolCount: count of the Dart and Flutter tools sending analytics +- recordCount: count of the total number of events in the log file +- eventCount: counts each unique event and how many times they occurred in the log file \ No newline at end of file
diff --git a/pkgs/unified_analytics/analysis_options.yaml b/pkgs/unified_analytics/analysis_options.yaml new file mode 100644 index 0000000..746ad64 --- /dev/null +++ b/pkgs/unified_analytics/analysis_options.yaml
@@ -0,0 +1,10 @@ +# This file configures the static analysis results for your project (errors, +# warnings, and lints). + +include: package:dart_flutter_team_lints/analysis_options.yaml + +linter: + rules: + - avoid_catches_without_on_clauses + - prefer_final_in_for_each + - prefer_final_locals
diff --git a/pkgs/unified_analytics/coverage_runner.sh b/pkgs/unified_analytics/coverage_runner.sh new file mode 100755 index 0000000..4043614 --- /dev/null +++ b/pkgs/unified_analytics/coverage_runner.sh
@@ -0,0 +1,11 @@ +#!/bin/sh + +# Generate `coverage/lcov.info` file +flutter test --coverage + +# Generate HTML report +# Note: on macOS you need to have lcov installed on your system (`brew install lcov`) to use this: +genhtml coverage/lcov.info -o coverage/html + +# Open the report +open coverage/html/index.html
diff --git a/pkgs/unified_analytics/example/sample_rate.dart b/pkgs/unified_analytics/example/sample_rate.dart new file mode 100644 index 0000000..51b0cdb --- /dev/null +++ b/pkgs/unified_analytics/example/sample_rate.dart
@@ -0,0 +1,90 @@ +// 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:unified_analytics/src/utils.dart'; + +/// The purpose of this example file is to demonstrate the sampling +/// rate functionality from the survey handler. +/// +/// It defines a `remoteUniqueId` that subs in for a real survey's unique +/// ID that is hosted in the remote json file. +/// +/// Begin the simulation by setting the `testSampleRate` and `iterations` +/// variables, where `iterations` simulates real users and `testSampleRate` +/// represents a fraction of how many people should be sampled. +/// +/// In this example, we have set the `testSampleRate` to `0.3`, meaning we want +/// sample 30% of users, and `iterations` to `10,000`, which simulates `10,000` +/// users. +/// +/// Running the script with predefined seed of `123` will +/// generate the below `stdout` +/// ``` +/// Test sample rate = 0.3 +/// Number of iterations = 10000 +/// --- +/// +/// Count of iterations sampled (successes) = 3046 +/// Actual sample rate = 0.3046 +/// --- +/// +/// Runtime = 8ms +/// ``` +/// +/// The actual results yielded 3,046 people selected for a rate +/// of `30.46%` which is about the `30%` defined in `testSampleRate`. +void main() { + // Seed has been set to replicate results + // + // Test with your own seed and alter other parameters + // as needed + final uuidGenerator = Uuid(123); + + // Randomly generate an ID that will simulate being used for + // a given survey + final remoteUniqueId = uuidGenerator.generateV4(); + + // Define a sampling rate that we would like to test + // + // Setting 0.3 means any generated doubles less than or + // equal to 0.3 results in a survey getting delievered + const testSampleRate = 0.3; + + // Define how many iterations to run, each iteration can + // be thought of as a developer using a dash tool + const iterations = 10000; + + // Initializing a counter that will count the number of + // iterations that were below the sampling rate + var count = 0; + + final start = DateTime.now(); + for (var i = 0; i < iterations; i++) { + // Each newly generated ID is simulating a unique + // developer's CLIENT ID that is persisted on their disk + final clientId = uuidGenerator.generateV4(); + + // Generate a double that will be compared against the sampleRate + final generatedDouble = sampleRate(remoteUniqueId, clientId); + + // Count successes if the generated double is less than our + // testing sample rate + if (generatedDouble <= testSampleRate) { + count++; + } + } + final end = DateTime.now(); + + print(''' +Test sample rate = $testSampleRate +Number of iterations = $iterations +--- + +Count of iterations sampled (successes) = $count +Actual sample rate = ${(count / iterations).toStringAsFixed(4)} +--- + +Runtime = ${end.difference(start).inMilliseconds}ms +'''); +}
diff --git a/pkgs/unified_analytics/example/serving_surveys.dart b/pkgs/unified_analytics/example/serving_surveys.dart new file mode 100644 index 0000000..d56339e --- /dev/null +++ b/pkgs/unified_analytics/example/serving_surveys.dart
@@ -0,0 +1,165 @@ +// 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:clock/clock.dart'; +import 'package:file/file.dart'; +import 'package:file/memory.dart'; + +import 'package:unified_analytics/src/constants.dart'; +import 'package:unified_analytics/src/enums.dart'; +import 'package:unified_analytics/src/survey_handler.dart'; +import 'package:unified_analytics/unified_analytics.dart'; + +/// This example code is intended to only be used as guidance for +/// clients using this package. Clients using this package should avoid +/// the use of the [Analytics.fake] static method. +/// +/// It was used in this example file so that the real [FileSystem] was swapped +/// out for a [MemoryFileSystem] so that repeated runs of this script yield +/// the same results. +void main() async { + late final MemoryFileSystem fs; + late final Analytics analytics; + late final Directory home; + // We need to initialize with a fake clock since the surveys have + // a period of time they are valid for + await withClock(Clock.fixed(DateTime(2023, 3, 3, 12, 0)), () async { + // Use a memory file system to repeatedly run this example + // file with the test instance + fs = MemoryFileSystem(style: FileSystemStyle.posix); + home = fs.directory('home'); + home.createSync(); + + // The purpose of `initialAnalytics` is so that the tool is able to + // send events after its first run; this instance won't be used below + // + // ignore: invalid_use_of_visible_for_testing_member + final initialAnalytics = Analytics.fake( + tool: DashTool.flutterTool, + homeDirectory: home, + dartVersion: 'dartVersion', + fs: fs, + platform: DevicePlatform.macos, + ); + // The below command allows `DashTool.flutterTool` to send telemetry + initialAnalytics.clientShowedMessage(); + + // ignore: invalid_use_of_visible_for_testing_member + analytics = Analytics.fake( + tool: DashTool.flutterTool, + homeDirectory: home, + dartVersion: 'dartVersion', + fs: fs, + platform: DevicePlatform.macos, + surveyHandler: FakeSurveyHandler.fromList( + dismissedSurveyFile: home + .childDirectory(kDartToolDirectoryName) + .childFile(kDismissedSurveyFileName), + initializedSurveys: [ + Survey( + uniqueId: 'uniqueId', + startDate: DateTime(2023, 1, 1), + endDate: DateTime(2023, 5, 31), + description: 'description', + snoozeForMinutes: 10, + samplingRate: 1.0, + excludeDashToolList: [], + conditionList: [], + buttonList: [ + SurveyButton( + buttonText: 'View Survey', + action: 'accept', + promptRemainsVisible: false, + url: 'http://example.com', + ), + SurveyButton( + buttonText: 'More Info', + action: 'snooze', + promptRemainsVisible: true, + url: 'http://example2.com', + ), + SurveyButton( + buttonText: 'Dismiss Survey', + action: 'dismiss', + promptRemainsVisible: false, + ) + ], + ), + ], + )); + }); + + // Each client of this package will be able to fetch all of + // the available surveys with the below method + // + // Sample rate will be applied automatically; it also won't + // fetch any surveys in the snooze period or if they have + // been dismissed + final surveyList = await analytics.fetchAvailableSurveys(); + assert(surveyList.length == 1); + + // Grab the first and only survey to simulate displaying it to a user + final survey = surveyList.first; + print('Simulating displaying the survey with a print below:'); + print('Survey id: ${survey.uniqueId}\n'); + + // Immediately after displaying the survey, the method below + // should be run so that no other clients using this tool will show + // it at the same time + // + // It will "snoozed" when the below is run as well as reported to + // Google Analytics 4 that this survey was shown + analytics.surveyShown(survey); + + // Get the file where this is persisted to show it getting updated + final persistedSurveyFile = home + .childDirectory(kDartToolDirectoryName) + .childFile(kDismissedSurveyFileName); + print('The contents of the json file ' + 'after invoking `analytics.surveyShown(survey);`'); + print('${persistedSurveyFile.readAsStringSync()}\n'); + + // Change the index below to decide which button to simulate pressing + // + // 0 - accept + // 1 - snooze + // 2 - dismiss + final selectedButtonIndex = 1; + assert([0, 1, 2].contains(selectedButtonIndex)); + + // Get the survey button by index that will need to be passed along with + // the survey to simulate an interaction with the survey + final selectedSurveyButton = survey.buttonList[selectedButtonIndex]; + print('The simulated button pressed was: ' + '"${selectedSurveyButton.buttonText}" ' + '(action = ${selectedSurveyButton.action})\n'); + + // The below method will handle whatever action the button + analytics.surveyInteracted( + survey: survey, + surveyButton: selectedSurveyButton, + ); + + // Conditional to check if there is a URl to route to + if (selectedSurveyButton.url != null) { + print('***This button also has a survey URL link ' + 'to route to at "${selectedSurveyButton.url}"***\n'); + } + + // Conditional to check what simulating a popup to stay up + if (selectedSurveyButton.promptRemainsVisible) { + print('***This button has its promptRemainsVisible field set to `true` ' + 'so this simulates what seeing a pop up again would look like***\n'); + } + + print('The contents of the json file ' + 'after invoking ' + '`analytics.surveyInteracted(survey: survey, ' + 'surveyButton: selectedSurveyButton);`'); + print('${persistedSurveyFile.readAsStringSync()}\n'); + + // Demonstrating that the survey doesn't get returned again + print('Attempting to fetch surveys again will result in an empty list'); + print(await analytics.fetchAvailableSurveys()); +}
diff --git a/pkgs/unified_analytics/example/unified_analytics_example.dart b/pkgs/unified_analytics/example/unified_analytics_example.dart new file mode 100644 index 0000000..e0ddaff --- /dev/null +++ b/pkgs/unified_analytics/example/unified_analytics_example.dart
@@ -0,0 +1,65 @@ +// 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:unified_analytics/unified_analytics.dart'; + +// Globally instantiate the analytics class at the entry +// point of the tool +// +// Development constructor used here so we don't push +// to production when running +final Analytics analytics = Analytics.development( + tool: DashTool.flutterTool, + flutterChannel: 'ey-test-channel', + flutterVersion: 'Flutter 3.6.0-7.0.pre.47', + clientIde: 'VSCode', + dartVersion: 'Dart 2.19.0', + // This can be set to true while testing to validate + // against GA4 usage limitations (character limits, etc.) + enableAsserts: false, + enabledFeatures: 'feature-1,feature-2', +); + +// Timing a process and sending the event +void main() async { + final start = DateTime.now(); + + // Each client using this package will have it's own + // method to show the message but the below is a trivial + // example of how to properly initialize the analytics instance + if (analytics.shouldShowMessage) { + // Simulates displaying the message, this will vary from + // client to client; ie. stdout, popup in IDE, etc. + print(analytics.getConsentMessage); + + // After receiving confirmation that the message has been + // displayed, invoking the below method will successfully + // onboard the tool into the config file and allow for + // events to be sent on the next creation of the analytics + // instance + // + // The rest of the example below assumes that the tool has + // already been onboarded in a previous run + analytics.clientShowedMessage(); + } + + print('Current user ${analytics.clientId} ' + 'is opted in: ${analytics.telemetryEnabled}'); + + // Example of long running process + await Future<void>.delayed(const Duration(milliseconds: 100)); + + // Calculate the metric to send + final runTime = DateTime.now().difference(start).inMilliseconds; + + // Create the event that will be sent for the hot reload time + // as an example + final hotReloadEvent = Event.hotReloadTime(timeMs: runTime); + + // Make a call to the [Analytics] api to send the data + analytics.send(hotReloadEvent); + + // Close the client connection on exit + await analytics.close(); +}
diff --git a/pkgs/unified_analytics/lib/src/analytics.dart b/pkgs/unified_analytics/lib/src/analytics.dart new file mode 100644 index 0000000..cc8b4bc --- /dev/null +++ b/pkgs/unified_analytics/lib/src/analytics.dart
@@ -0,0 +1,857 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:io' as io; + +import 'package:file/file.dart'; +import 'package:file/local.dart'; +import 'package:file/memory.dart'; +import 'package:http/http.dart'; +import 'package:meta/meta.dart'; + +import 'asserts.dart'; +import 'config_handler.dart'; +import 'constants.dart'; +import 'enums.dart'; +import 'event.dart'; +import 'ga_client.dart'; +import 'initializer.dart'; +import 'log_handler.dart'; +import 'survey_handler.dart'; +import 'user_property.dart'; +import 'utils.dart'; + +abstract class Analytics { + /// The default factory constructor that will return an implementation + /// of the [Analytics] abstract class using the [LocalFileSystem]. + /// + /// If [enableAsserts] is set to `true`, then asserts for GA4 limitations + /// will be enabled. + /// + /// [flutterChannel] and [flutterVersion] are nullable in case the client + /// using this package is unable to resolve those values. + /// + /// An optional parameter [clientIde] is also available for dart and flutter + /// tooling that are running from IDEs can be resolved. Such as "VSCode" + /// running the flutter-tool. + /// + /// [enabledFeatures] is also an optional field that can be added to collect + /// any features that are enabled for a user. For example, + /// "enable-linux-desktop,cli-animations" are two features that can be enabled + /// for the flutter-tool. + factory Analytics({ + required DashTool tool, + required String dartVersion, + String? flutterChannel, + String? flutterVersion, + String? clientIde, + String? enabledFeatures, + bool enableAsserts = false, + }) { + // Create the instance of the file system so clients don't need + // resolve on their own + const FileSystem fs = LocalFileSystem(); + + // Ensure that the home directory has permissions enabled to write + final homeDirectory = getHomeDirectory(fs); + if (homeDirectory == null || + !checkDirectoryForWritePermissions(homeDirectory)) { + return const NoOpAnalytics(); + } + + // Resolve the OS using dart:io + final DevicePlatform platform; + if (io.Platform.operatingSystem == 'linux') { + platform = DevicePlatform.linux; + } else if (io.Platform.operatingSystem == 'macos') { + platform = DevicePlatform.macos; + } else { + platform = DevicePlatform.windows; + } + + // Create the instance of the GA Client which will create + // an [http.Client] to send requests + final gaClient = GAClient( + measurementId: kGoogleAnalyticsMeasurementId, + apiSecret: kGoogleAnalyticsApiSecret, + ); + + final firstRun = runInitialization(homeDirectory: homeDirectory); + + return AnalyticsImpl( + tool: tool, + homeDirectory: homeDirectory, + flutterChannel: flutterChannel, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + platform: platform, + toolsMessageVersion: kToolsMessageVersion, + fs: fs, + gaClient: gaClient, + surveyHandler: SurveyHandler( + dismissedSurveyFile: homeDirectory + .childDirectory(kDartToolDirectoryName) + .childFile(kDismissedSurveyFileName), + ), + enableAsserts: enableAsserts, + clientIde: clientIde, + enabledFeatures: enabledFeatures, + firstRun: firstRun, + ); + } + + /// Factory constructor to return the [AnalyticsImpl] class with + /// Google Analytics credentials that point to a test instance and + /// not the production instance where live data will be sent. + /// + /// By default, [enableAsserts] is set to `true` to check against + /// GA4 limitations. + /// + /// [flutterChannel] and [flutterVersion] are nullable in case the client + /// using this package is unable to resolve those values. + factory Analytics.development({ + required DashTool tool, + required String dartVersion, + String? flutterChannel, + String? flutterVersion, + String? clientIde, + String? enabledFeatures, + bool enableAsserts = true, + }) { + // Create the instance of the file system so clients don't need + // resolve on their own + const FileSystem fs = LocalFileSystem(); + + // Ensure that the home directory has permissions enabled to write + final homeDirectory = getHomeDirectory(fs); + if (homeDirectory == null) { + throw Exception('Unable to determine the home directory, ' + 'ensure it is available in the environment'); + } + if (!checkDirectoryForWritePermissions(homeDirectory)) { + throw Exception('Permissions error on the home directory!'); + } + + // Resolve the OS using dart:io + final DevicePlatform platform; + if (io.Platform.operatingSystem == 'linux') { + platform = DevicePlatform.linux; + } else if (io.Platform.operatingSystem == 'macos') { + platform = DevicePlatform.macos; + } else { + platform = DevicePlatform.windows; + } + + // Credentials defined below for the test Google Analytics instance + const kTestMeasurementId = 'G-N1NXG28J5B'; + const kTestApiSecret = '4yT8__oER3Cd84dtx6r-_A'; + + // Create the instance of the GA Client which will create + // an [http.Client] to send requests + final gaClient = GAClient( + measurementId: kTestMeasurementId, + apiSecret: kTestApiSecret, + ); + + final firstRun = runInitialization(homeDirectory: homeDirectory); + + return AnalyticsImpl( + tool: tool, + homeDirectory: homeDirectory, + flutterChannel: flutterChannel, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + platform: platform, + toolsMessageVersion: kToolsMessageVersion, + fs: fs, + gaClient: gaClient, + surveyHandler: SurveyHandler( + dismissedSurveyFile: homeDirectory + .childDirectory(kDartToolDirectoryName) + .childFile(kDismissedSurveyFileName), + ), + enableAsserts: enableAsserts, + clientIde: clientIde, + enabledFeatures: enabledFeatures, + firstRun: firstRun, + ); + } + + /// The shared identifier for Flutter and Dart related tooling using + /// package:unified_analytics. + String get clientId; + + /// Retrieves the consent message to prompt users with on first + /// run or when the message has been updated. + String get getConsentMessage; + + /// Returns true if it is OK to send an analytics message. Do not cache, + /// as this depends on factors that can change, such as the configuration + /// file contents. + bool get okToSend; + + /// Returns a map object with all of the tools that have been parsed + /// out of the configuration file. + Map<String, ToolInfo> get parsedTools; + + /// Boolean that lets the client know if they should display the message. + bool get shouldShowMessage; + + /// Boolean indicating whether or not telemetry is enabled. + bool get telemetryEnabled; + + /// Returns a map representation of the [UserProperty] for the [Analytics] + /// instance. + /// + /// This is what will get sent to Google Analytics with every request. + Map<String, Map<String, Object?>> get userPropertyMap; + + /// Method to be invoked by the client using this package to confirm + /// that the client has shown the message and that it can be added to + /// the config file and start sending events the next time it starts up. + void clientShowedMessage(); + + /// Call this method when the tool using this package is closed. + /// + /// Prevents the tool from hanging when if there are still requests + /// that need to be sent off. + /// + /// Providing [delayDuration] in milliseconds will allow the instance + /// to wait the provided time before closing the http connection. Keeping + /// the connection open for some time will allow any pending events that + /// are waiting to be sent to the Google Analytics server. Default value + /// of 250 ms applied. + Future<void> close({int delayDuration = kDelayDuration}); + + /// Method to fetch surveys from the endpoint [kContextualSurveyUrl]. + /// + /// Any survey that is returned by this method has already passed + /// the survey conditions specified in the remote survey metadata file. + /// + /// If the method returns an empty list, then there are no surveys to be + /// shared with the user. + Future<List<Survey>> fetchAvailableSurveys(); + + /// Query the persisted event data stored on the user's machine. + /// + /// Returns null if there are no persisted logs. + LogFileStats? logFileStats(); + + /// Send preconfigured events using specific named constructors + /// on the [Event] class. + /// + /// Example + /// ```dart + /// analytics.send(Event.memory(periodSec: 123)); + /// ``` + void send(Event event); + + /// Pass a boolean to either enable or disable telemetry and make + /// the necessary changes in the persisted configuration file. + /// + /// Setting the telemetry status will also send an event to GA + /// indicating the latest status of the telemetry from [reportingBool]. + Future<void> setTelemetry(bool reportingBool); + + /// Calling this will result in telemetry collection being suppressed for + /// the current invocation. + /// + /// If you would like to permanently disable telemetry + /// collection use: + /// + /// ```dart + /// analytics.setTelemetry(false) + /// ``` + void suppressTelemetry(); + + /// Method to run after interacting with a [Survey] instance. + /// + /// Pass a [Survey] instance which can be retrieved from + /// [Analytics.fetchAvailableSurveys]. + /// + /// [surveyButton] is the button that was interacted with by the user. + void surveyInteracted({ + required Survey survey, + required SurveyButton surveyButton, + }); + + /// Method to be called after a survey has been shown to the user. + /// + /// Calling this will snooze the survey so it won't be shown immediately. + /// + /// The snooze period is defined by the [Survey.snoozeForMinutes] field. + void surveyShown(Survey survey); + + /// Returns an instance of [FakeAnalytics] which can be used in tests to check + /// for certain [Event] instances within [FakeAnalytics.sentEvents]. + @visibleForTesting + static FakeAnalytics fake({ + required DashTool tool, + required Directory homeDirectory, + required String dartVersion, + required MemoryFileSystem fs, + String? flutterChannel, + String? flutterVersion, + String? clientIde, + String? enabledFeatures, + SurveyHandler? surveyHandler, + GAClient? gaClient, + DevicePlatform platform = DevicePlatform.linux, + int toolsMessageVersion = kToolsMessageVersion, + String toolsMessage = kToolsMessage, + bool enableAsserts = true, + }) { + final firstRun = runInitialization(homeDirectory: homeDirectory); + + return FakeAnalytics._( + tool: tool, + homeDirectory: homeDirectory, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + platform: platform, + fs: fs, + surveyHandler: surveyHandler ?? + FakeSurveyHandler.fromList( + dismissedSurveyFile: homeDirectory + .childDirectory(kDartToolDirectoryName) + .childFile(kDismissedSurveyFileName), + initializedSurveys: [], + ), + gaClient: gaClient ?? const FakeGAClient(), + clientIde: clientIde, + enabledFeatures: enabledFeatures, + firstRun: firstRun, + enableAsserts: enableAsserts, + ); + } +} + +class AnalyticsImpl implements Analytics { + final DashTool tool; + final FileSystem fs; + final int toolsMessageVersion; + final ConfigHandler _configHandler; + final GAClient _gaClient; + final SurveyHandler _surveyHandler; + final File _clientIdFile; + final UserProperty _userProperty; + final LogHandler _logHandler; + + /// Tells the client if they need to show a message to the + /// user; this will return true if it is the first time the + /// package is being used for a developer or if the consent + /// message has been updated by the package. + bool _showMessage = false; + + /// When set to `true`, various assert statements will be enabled + /// to ensure usage of this class is within GA4 limitations. + final bool _enableAsserts; + + /// Telemetry suppression flag that is set via [Analytics.suppressTelemetry]. + bool _telemetrySuppressed = false; + + /// Indicates if this is the first run for a given tool. + bool _firstRun = false; + + /// The list of futures that will contain all of the send events + /// from the [GAClient]. + final _futures = <Future<Response>>[]; + + /// Internal value for the client id which will be lazily loaded. + String? _clientId; + + /// Internal collection of [Event]s that have been sent + /// for errors encountered within package:unified_analytics. + /// + /// Stores each of the events that have been sent to GA4 so that the + /// same error doesn't get sent twice. + final Set<Event> _sentErrorEvents = {}; + + AnalyticsImpl({ + required this.tool, + required Directory homeDirectory, + required String? flutterChannel, + required String? flutterVersion, + required String? clientIde, + required String? enabledFeatures, + required String dartVersion, + required DevicePlatform platform, + required this.toolsMessageVersion, + required this.fs, + required GAClient gaClient, + required SurveyHandler surveyHandler, + required bool enableAsserts, + required bool firstRun, + }) : _gaClient = gaClient, + _surveyHandler = surveyHandler, + _enableAsserts = enableAsserts, + _clientIdFile = homeDirectory + .childDirectory(kDartToolDirectoryName) + .childFile(kClientIdFileName), + _userProperty = UserProperty( + sessionFile: homeDirectory + .childDirectory(kDartToolDirectoryName) + .childFile(kSessionFileName), + flutterChannel: flutterChannel, + host: platform.label, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + tool: tool.label, + // We truncate this to a maximum of 36 characters since this can + // a very long string for some operating systems + hostOsVersion: + truncateStringToLength(io.Platform.operatingSystemVersion, 36), + locale: io.Platform.localeName, + clientIde: clientIde, + enabledFeatures: enabledFeatures, + ), + _configHandler = ConfigHandler( + homeDirectory: homeDirectory, + configFile: homeDirectory + .childDirectory(kDartToolDirectoryName) + .childFile(kConfigFileName), + ), + _logHandler = LogHandler( + logFile: homeDirectory + .childDirectory(kDartToolDirectoryName) + .childFile(kLogFileName), + ) { + // This initializer class will let the instance know + // if it was the first run; if it is, nothing will be sent + // on the first run + if (firstRun) { + _showMessage = true; + _firstRun = true; + } else { + _showMessage = false; + _firstRun = false; + } + + // Check if the tool has already been onboarded, and if it + // has, check if the latest message version is greater to + // prompt the client to show a message + // + // If the tool has not been added to the config file, then + // we will show the message as well + final currentVersion = + _configHandler.parsedTools[tool.label]?.versionNumber ?? -1; + if (currentVersion < toolsMessageVersion) { + _showMessage = true; + + // If the message version has been updated, it will be considered + // as if it was a first run and any events attempting to get sent + // will be blocked + _firstRun = true; + } + } + + @override + String get clientId { + if (!_clientIdFile.existsSync()) { + createClientIdFile(clientIdFile: _clientIdFile); + } + _clientId ??= _clientIdFile.readAsStringSync(); + + return _clientId!; + } + + @override + String get getConsentMessage { + // The command to swap in the consent message + final commandString = + tool == DashTool.flutterTool || tool == DashTool.devtools + ? 'flutter' + : 'dart'; + + return kToolsMessage + .replaceAll('{{ toolDescription }}', tool.description) + .replaceAll('{{ toolName }}', commandString); + } + + /// Checking the [telemetryEnabled] boolean reflects what the + /// config file reflects. + /// + /// Checking the [_showMessage] boolean indicates if the consent + /// message has been shown for the user, this boolean is set to `true` + /// when the tool using this package invokes the [clientShowedMessage] + /// method. + /// + /// If the user has suppressed telemetry [_telemetrySuppressed] will + /// return `true` to prevent events from being sent for current invocation. + /// + /// Checking if it is the first time a tool is running with this package + /// as indicated by [_firstRun]. + @override + bool get okToSend => + telemetryEnabled && !_showMessage && !_telemetrySuppressed && !_firstRun; + + @override + Map<String, ToolInfo> get parsedTools => _configHandler.parsedTools; + + @override + bool get shouldShowMessage => _showMessage; + + @override + bool get telemetryEnabled => _configHandler.telemetryEnabled; + + @override + Map<String, Map<String, Object?>> get userPropertyMap => + _userProperty.preparePayload(); + + @override + void clientShowedMessage() { + // Check the tool needs to be added to the config file + if (!_configHandler.parsedTools.containsKey(tool.label)) { + _configHandler.addTool( + tool: tool.label, + versionNumber: toolsMessageVersion, + ); + } + + // When the tool already exists but the consent message version + // has been updated + if (_configHandler.parsedTools[tool.label]!.versionNumber < + toolsMessageVersion) { + _configHandler.incrementToolVersion( + tool: tool.label, + newVersionNumber: toolsMessageVersion, + ); + } + _showMessage = false; + } + + @override + Future<void> close({int delayDuration = kDelayDuration}) async { + // Collect any errors encountered and send + _sendPendingErrorEvents(); + + await Future.wait(_futures).timeout( + Duration(milliseconds: delayDuration), + onTimeout: () => [], + ); + _gaClient.close(); + } + + @override + Future<List<Survey>> fetchAvailableSurveys() async { + final surveysToShow = <Survey>[]; + if (!okToSend) return surveysToShow; + + final logFileStats = _logHandler.logFileStats(); + + // Call for surveys that have already been dismissed from + // persisted survey ids on disk + final persistedSurveyMap = _surveyHandler.fetchPersistedSurveys(); + + for (final survey in await _surveyHandler.fetchSurveyList()) { + // If the survey has listed the tool running this package in the exclude + // list, it will not be returned + if (survey.excludeDashToolList.contains(tool)) continue; + + // Apply the survey's sample rate; if the generated value from + // the client id and survey's uniqueId are less, it will not get + // sent to the user + if (survey.samplingRate < sampleRate(clientId, survey.uniqueId)) { + continue; + } + + // If the survey has been permanently dismissed or has temporarily + // been snoozed, skip it + if (surveySnoozedOrDismissed(survey, persistedSurveyMap)) continue; + + // Counter to check each survey condition, if all are met, then + // this integer will be equal to the number of conditions in + // [Survey.conditionList] + var conditionsMet = 0; + if (logFileStats != null) { + for (final condition in survey.conditionList) { + // Retrieve the value from the [LogFileStats] with + // the label provided in the condtion + final logFileStatsValue = + logFileStats.getValueByString(condition.field); + + if (logFileStatsValue == null) continue; + + switch (condition.operatorString) { + case '>=': + if (logFileStatsValue >= condition.value) conditionsMet++; + case '<=': + if (logFileStatsValue <= condition.value) conditionsMet++; + case '>': + if (logFileStatsValue > condition.value) conditionsMet++; + case '<': + if (logFileStatsValue < condition.value) conditionsMet++; + case '==': + if (logFileStatsValue == condition.value) conditionsMet++; + case '!=': + if (logFileStatsValue != condition.value) conditionsMet++; + } + } + } + + if (conditionsMet == survey.conditionList.length) { + surveysToShow.add(survey); + } + } + + return surveysToShow; + } + + @override + LogFileStats? logFileStats() => _logHandler.logFileStats(); + + @override + void send(Event event) { + if (!okToSend) return; + + // Construct the body of the request + final body = generateRequestBody( + clientId: clientId, + eventName: event.eventName, + eventData: event.eventData, + userProperty: _userProperty, + ); + + if (_enableAsserts) checkBody(body); + + _logHandler.save(data: body); + + final gaClientFuture = _gaClient.sendData(body); + _futures.add(gaClientFuture); + gaClientFuture.whenComplete(() => _futures.remove(gaClientFuture)); + } + + @override + Future<void> setTelemetry(bool reportingBool) { + _configHandler.setTelemetry(reportingBool); + + // Creation of the [Event] for opting out + final collectionEvent = + Event.analyticsCollectionEnabled(status: reportingBool); + + // The body of the request that will be sent to GA4 + final Map<String, Object?> body; + + if (reportingBool) { + // Recreate the session and client id file; no need to + // recreate the log file since it will only receives events + // to persist from events sent + createClientIdFile(clientIdFile: _clientIdFile); + createSessionFile(sessionFile: _userProperty.sessionFile); + + // Reread the client ID string so an empty string is not being + // sent to GA4 since the persisted files are cleared when a user + // decides to opt out of telemetry collection + _clientId = _clientIdFile.readAsStringSync(); + + // We must construct the body at this point after we have read in the + // new client id string that was generated + body = generateRequestBody( + clientId: clientId, + eventName: collectionEvent.eventName, + eventData: collectionEvent.eventData, + userProperty: _userProperty, + ); + + _logHandler.save(data: body); + } else { + // Construct the body of the request to signal + // telemetry status toggling + body = generateRequestBody( + clientId: clientId, + eventName: collectionEvent.eventName, + eventData: collectionEvent.eventData, + userProperty: _userProperty, + ); + + // For opted out users, data in the persisted files is cleared + _userProperty.sessionFile.writeAsStringSync(''); + _logHandler.logFile.writeAsStringSync(''); + _clientIdFile.writeAsStringSync(''); + + _clientId = ''; + } + + // Pass to the google analytics client to send with a + // timeout incase http clients hang + return _gaClient.sendData(body).timeout( + const Duration(milliseconds: kDelayDuration), + onTimeout: () => Response('', 200), + ); + } + + @override + void suppressTelemetry() => _telemetrySuppressed = true; + + @override + void surveyInteracted({ + required Survey survey, + required SurveyButton surveyButton, + }) { + // Any action, except for 'snooze' will permanently dismiss a given survey + final permanentlyDismissed = surveyButton.action == 'snooze' ? false : true; + _surveyHandler.dismiss(survey, permanentlyDismissed); + send(Event.surveyAction( + surveyId: survey.uniqueId, + status: surveyButton.action, + )); + } + + @override + void surveyShown(Survey survey) { + _surveyHandler.dismiss(survey, false); + send(Event.surveyShown(surveyId: survey.uniqueId)); + } + + /// Send any pending error events, useful for tests to avoid closing + /// the connection. + /// + /// In the main implementation, [AnalyticsImpl], error events are only + /// sent on exit when [close] is invoked. This helper method can instead + /// have those error events sent immediately to help with tests that check + /// [FakeAnalytics.sentEvents]. + void _sendPendingErrorEvents() { + // Collect any errors encountered and send + final errorEvents = {..._userProperty.errorSet, ..._logHandler.errorSet}; + errorEvents + .where((event) => + event.eventName == DashEvent.analyticsException && + !_sentErrorEvents.contains(event)) + .forEach(send); + + // Ensure the same event doesn't get sent again + _sentErrorEvents.addAll(errorEvents); + + // Clear error sets + _userProperty.errorSet.clear(); + _logHandler.errorSet.clear(); + } +} + +/// This fake instance of [Analytics] is intended to be used by clients of +/// this package for testing purposes. It exposes a list [sentEvents] that +/// keeps track of all events that have been sent. +/// +/// This is useful for confirming that events are being sent for a given +/// workflow. Invoking the [send] method on this instance will not make any +/// network requests to Google Analytics. +class FakeAnalytics extends AnalyticsImpl { + /// Use this list to check for events that have been emitted when + /// invoking the send method + final List<Event> sentEvents = []; + + /// Class to use when you want to see which events were sent + FakeAnalytics._({ + required super.tool, + required super.homeDirectory, + required super.dartVersion, + required super.platform, + required super.fs, + required super.surveyHandler, + required super.firstRun, + super.flutterChannel, + super.flutterVersion, + super.clientIde, + super.enabledFeatures, + super.toolsMessageVersion = kToolsMessageVersion, + super.gaClient = const FakeGAClient(), + super.enableAsserts = true, + }); + + /// Getter to reference the private [UserProperty]. + UserProperty get userProperty => _userProperty; + + @override + void send(Event event) { + if (!okToSend) return; + + // Construct the body of the request + final body = generateRequestBody( + clientId: clientId, + eventName: event.eventName, + eventData: event.eventData, + userProperty: _userProperty, + ); + + if (_enableAsserts) checkBody(body); + + _logHandler.save(data: body); + + // Using this list to validate that events are being sent + // for internal methods in the `Analytics` instance + sentEvents.add(event); + } + + /// Public instance method to invoke private method that sends any + /// pending error events. + /// + /// If this is never invoked, any pending error events will be sent + /// when invoking the [close] method. + void sendPendingErrorEvents() => _sendPendingErrorEvents(); +} + +/// An implementation that will never send events. +/// +/// This is for clients that opt to either not send analytics, or will migrate +/// to use [AnalyticsImpl] at a later time. +class NoOpAnalytics implements Analytics { + /// The hard-coded client ID value for each NoOp instance. + static String get staticClientId => 'xxxx-xxxx'; + + @override + final String getConsentMessage = ''; + + @override + final bool okToSend = false; + + @override + final Map<String, ToolInfo> parsedTools = const <String, ToolInfo>{}; + + @override + final bool shouldShowMessage = false; + + @override + final bool telemetryEnabled = false; + + @override + final Map<String, Map<String, Object?>> userPropertyMap = + const <String, Map<String, Object?>>{}; + + const NoOpAnalytics(); + + @override + String get clientId => staticClientId; + + @override + void clientShowedMessage() {} + + @override + Future<void> close({int delayDuration = kDelayDuration}) async {} + + @override + Future<List<Survey>> fetchAvailableSurveys() async => const <Survey>[]; + + @override + LogFileStats? logFileStats() => null; + + @override + Future<Response>? send(Event event) => null; + + @override + Future<void> setTelemetry(bool reportingBool) async {} + + @override + void suppressTelemetry() {} + + @override + void surveyInteracted({ + required Survey survey, + required SurveyButton surveyButton, + }) {} + + @override + void surveyShown(Survey survey) {} +}
diff --git a/pkgs/unified_analytics/lib/src/asserts.dart b/pkgs/unified_analytics/lib/src/asserts.dart new file mode 100644 index 0000000..199f4ee --- /dev/null +++ b/pkgs/unified_analytics/lib/src/asserts.dart
@@ -0,0 +1,172 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Matches only alphabetic characters. +final RegExp alphabeticPattern = RegExp(r'^[A-Za-z]+$'); + +/// Matches strings that contain alphanumeric characters and underscores. +final RegExp alphaNumericPattern = RegExp(r'^[A-Za-z0-9_]+$'); + +/// Checks that the body of the request being sent to +/// GA4 is within the limitations. +/// +/// Limitations can be found: +/// https://developers.google.com/analytics/devguides/collection/protocol/ga4/sending-events?client_type=gtag#limitations +void checkBody(Map<String, Object?> body) { + // Ensure we have the correct top level keys + if (!body.keys.contains('client_id')) { + throw AnalyticsException('client_id missing from top level keys'); + } + if (!body.keys.contains('events')) { + throw AnalyticsException('events missing from top level keys'); + } + if (!body.keys.contains('user_properties')) { + throw AnalyticsException('user_properties missing from top level keys'); + } + + final events = body['events'] as List; + final userProperties = body['user_properties'] as Map<String, Object?>; + + // GA4 Limitation: + // Requests can have a maximum of 25 events + if (events.length > 25) { + throw AnalyticsException('25 is the max number of events'); + } + + // Checks for each event object + for (final eventMap in events.cast<Map<String, Object?>>()) { + final eventName = eventMap['name'] as String; + + // GA4 Limitation: + // Event names must be 40 characters or fewer, may only contain + // alpha-numeric characters and underscores, and must start + // with an alphabetic character + if (eventName.length > 40) { + throw AnalyticsException( + 'Limit event names to 40 chars or less\n' + 'Event name: "$eventName" is too long', + ); + } + if (!alphaNumericPattern.hasMatch(eventName)) { + throw AnalyticsException( + 'Event name can only have alphanumeric chars and underscores\n' + 'Event name: "$eventName" contains invalid characters', + ); + } + if (!alphabeticPattern.hasMatch(eventName[0])) { + throw AnalyticsException( + 'Event name first char must be alphabetic char\n' + 'Event name: "$eventName" must begin with a valid character', + ); + } + + final eventParams = eventMap['params'] as Map<String, Object?>; + + // GA4 Limitation: + // Events can have a maximum of 25 parameters + if (eventParams.length > 25) { + throw AnalyticsException( + 'Limit params for each event to less than 25\n' + 'Event: "$eventName" has too many parameters', + ); + } + + // Loop through each of the event parameters + for (final entry in eventParams.entries) { + final key = entry.key; + final value = entry.value; + + // GA4 Limitation: + // Ensure that each value for the event params is one + // of the following types: + // `String`, `int`, `double`, or `bool` + if (!(value is String || + value is int || + value is double || + value is bool)) { + throw AnalyticsException( + 'Values for event params have to be String, int, double, or bool\n' + 'Value for "$key" is not a valid type for event: "$eventName"', + ); + } + + // GA4 Limitation: + // Parameter names (including item parameters) must be 40 characters + // or fewer, may only contain alpha-numeric characters and underscores, + // and must start with an alphabetic character + if (key.length > 40) { + throw AnalyticsException( + 'Limit event param names to 40 chars or less\n' + 'The key: "$key" under the event: "$eventName" is too long', + ); + } + if (!alphaNumericPattern.hasMatch(key)) { + throw AnalyticsException( + 'Event param name can only have alphanumeric chars and underscores\n' + 'The key: "$key" under the event: "$eventName" contains ' + 'invalid characters', + ); + } + if (!alphabeticPattern.hasMatch(key[0])) { + throw AnalyticsException( + 'Event param name first char must be alphabetic char\n' + 'The key: "$key" under the event: "$eventName" must begin ' + 'in a valid character', + ); + } + + // GA4 Limitation: + // Parameter values (including item parameter values) must be 100 + // characters or fewer + if (value.runtimeType == String) { + value as String; + if (value.length > 100) { + throw AnalyticsException( + 'Limit characters in event param value to 100 chars or less\n' + 'Value for "$key" is too long, value="$value"', + ); + } + } + } + } + + // GA4 Limitation: + // Events can have a maximum of 25 user properties + if (userProperties.length > 25) { + throw AnalyticsException('Limit user properties to 25 or less'); + } + + // Checks for each user property item + for (final entry in userProperties.entries) { + final key = entry.key; + final value = entry.value as Map<String, Object?>; + + // GA4 Limitation: + // User property names must be 24 characters or fewer + if (key.length > 24) { + throw AnalyticsException('Limit user property names to 24 chars or less\n' + 'The user property key: "$key" is too long'); + } + + // GA4 Limitation: + // User property values must be 36 characters or fewer + final userPropValue = value['value']; + if (userPropValue is String && userPropValue.length > 36) { + throw AnalyticsException( + 'Limit user property values to 36 chars or less\n' + 'For the user property key "$key", the value "${value['value']}" ' + 'is too long', + ); + } + } +} + +class AnalyticsException implements Exception { + final String message; + + AnalyticsException(this.message); + + @override + String toString() => 'AnalyticsException: $message'; +}
diff --git a/pkgs/unified_analytics/lib/src/config_handler.dart b/pkgs/unified_analytics/lib/src/config_handler.dart new file mode 100644 index 0000000..8db4660 --- /dev/null +++ b/pkgs/unified_analytics/lib/src/config_handler.dart
@@ -0,0 +1,224 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; + +import 'package:clock/clock.dart'; +import 'package:convert/convert.dart'; +import 'package:file/file.dart'; + +import 'initializer.dart'; +import 'utils.dart'; + +/// The regex pattern used to parse the disable analytics line. +const String telemetryFlagPattern = r'^reporting=([0|1]) *$'; + +/// The regex pattern used to parse the tools info +/// from the configuration file. +/// +/// Example: +/// ```text +/// flutter-tool=2022-10-26,1 +/// devtools=2022-11-26,1 +/// ``` +const String toolPattern = + r'^([A-Za-z0-9]+[A-Za-z0-9_-]*)=([0-9]{4}-[0-9]{2}-[0-9]{2}),([0-9]+)$'; + +class ConfigHandler { + /// Regex pattern implementation for matching a line in the config file. + static RegExp telemetryFlagRegex = + RegExp(telemetryFlagPattern, multiLine: true); + static RegExp toolRegex = RegExp(toolPattern, multiLine: true); + + final Directory homeDirectory; + final File configFile; + + final Map<String, ToolInfo> parsedTools = <String, ToolInfo>{}; + + DateTime configFileLastModified; + + /// Reporting enabled unless specified by user + bool _telemetryEnabled = true; + + ConfigHandler({ + required this.homeDirectory, + required this.configFile, + }) : configFileLastModified = configFile.lastModifiedSync() { + // Call the method to parse the contents of the config file when + // this class is initialized + parseConfig(); + } + + /// Returns the telemetry state from the config file. + /// + /// Method will reparse the config file if it detects that the + /// last modified datetime is different from what was parsed when + /// the class was initialized. + bool get telemetryEnabled { + if (configFileLastModified.isBefore(configFile.lastModifiedSync())) { + parseConfig(); + configFileLastModified = configFile.lastModifiedSync(); + } + + return _telemetryEnabled; + } + + /// Responsibe for the creation of the configuration line + /// for the tool being passed in by the user and adding a + /// [ToolInfo] object. + void addTool({ + required String tool, + required int versionNumber, + }) { + // Create the new instance of [ToolInfo] to be added + // to the [parsedTools] map + parsedTools[tool] = ToolInfo( + lastRun: clock.now(), + versionNumber: versionNumber, + ); + + // New string to be appended to the bottom of the configuration file + // with a newline character for new tools to be added + var newTool = '$tool=$dateStamp,$versionNumber\n'; + if (!configFile.readAsStringSync().endsWith('\n')) { + newTool = '\n$newTool'; + } + configFile.writeAsStringSync(newTool, mode: FileMode.append); + configFileLastModified = configFile.lastModifiedSync(); + } + + /// Will increment the version number and update the date + /// in the config file for the provided tool name while + /// also incrementing the version number in [ToolInfo]. + void incrementToolVersion({ + required String tool, + required int newVersionNumber, + }) { + if (!parsedTools.containsKey(tool)) { + return; + } + + // Read in the config file contents and use a regex pattern to + // match the line for the current tool (ie. flutter-tools=2023-01-05,1) + final configString = configFile.readAsStringSync(); + final pattern = '^($tool)=([0-9]{4}-[0-9]{2}-[0-9]{2}),([0-9]+)\$'; + + final regex = RegExp(pattern, multiLine: true); + final matches = regex.allMatches(configString); + + // If there isn't exactly one match for the given tool, that suggests the + // file has been altered and needs to be reset + if (matches.length != 1) { + resetConfig(); + return; + } + + // Construct the new tool line for the config line and replace it + // in the original config string to prep for writing back out + final newToolString = '$tool=$dateStamp,$newVersionNumber'; + final newConfigString = configString.replaceAll(regex, newToolString); + configFile.writeAsStringSync(newConfigString); + + final toolInfo = parsedTools[tool]; + if (toolInfo == null) { + return; + } + + // Update the [ToolInfo] object for the current tool + toolInfo.lastRun = clock.now(); + toolInfo.versionNumber = newVersionNumber; + } + + /// Method responsible for reading in the config file stored on + /// user's machine and parsing out the following: all the tools that + /// have been logged in the file, the dates they were last run, and + /// determining if telemetry is enabled by parsing the file. + void parseConfig() { + // Begin with the assumption that telemetry is always enabled + _telemetryEnabled = true; + + // Read the configuration file as a string and run the two regex patterns + // on it to get information around which tools have been parsed and whether + // or not telemetry has been disabled by the user + final configString = configFile.readAsStringSync(); + + // Collect the tools logged in the configuration file + toolRegex.allMatches(configString).forEach((RegExpMatch element) { + // Extract the information relevant for the [ToolInfo] class + final tool = element.group(1) as String; + final lastRun = DateTime.parse(element.group(2) as String); + final versionNumber = int.parse(element.group(3) as String); + + // Initialize an instance of the [ToolInfo] class to store + // in the [parsedTools] map object + parsedTools[tool] = ToolInfo( + lastRun: lastRun, + versionNumber: versionNumber, + ); + }); + + // Check for lines signaling that the user has disabled analytics, + // if multiple lines are found, the more conservative value will be used + telemetryFlagRegex.allMatches(configString).forEach((RegExpMatch element) { + // Conditional for recording telemetry as being disabled + if (element.group(1) == '0') { + _telemetryEnabled = false; + } + }); + } + + /// This will reset the configuration file and clear the + /// [parsedTools] map and trigger parsing the config again. + void resetConfig() { + createConfigFile( + configFile: configFile, + homeDirectory: homeDirectory, + ); + parsedTools.clear(); + parseConfig(); + } + + /// Disables the reporting capabilities if [reportingBool] is set to `false`. + Future<void> setTelemetry(bool reportingBool) async { + final flag = reportingBool ? '1' : '0'; + final configString = await configFile.readAsString(); + + final matches = telemetryFlagRegex.allMatches(configString); + + // If there isn't exactly one match for the reporting flag, that suggests + // the file has been altered and needs to be reset + if (matches.length != 1) { + resetConfig(); + return; + } + + final newTelemetryString = 'reporting=$flag'; + + final newConfigString = + configString.replaceAll(telemetryFlagRegex, newTelemetryString); + + await configFile.writeAsString(newConfigString); + configFileLastModified = configFile.lastModifiedSync(); + + _telemetryEnabled = reportingBool; + } +} + +class ToolInfo { + DateTime lastRun; + int versionNumber; + + ToolInfo({ + required this.lastRun, + required this.versionNumber, + }); + + @override + String toString() { + return json.encode(<String, Object?>{ + 'lastRun': FixedDateTimeFormatter('YYYY-MM-DD').encode(lastRun), + 'versionNumber': versionNumber, + }); + } +}
diff --git a/pkgs/unified_analytics/lib/src/constants.dart b/pkgs/unified_analytics/lib/src/constants.dart new file mode 100644 index 0000000..fde9c21 --- /dev/null +++ b/pkgs/unified_analytics/lib/src/constants.dart
@@ -0,0 +1,119 @@ +// 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. + +/// URL endpoint for sending Google Analytics Events. +const String kAnalyticsUrl = 'https://www.google-analytics.com/mp/collect'; + +/// Name for the text file that will contain the user's randomly generated +/// client id. +const String kClientIdFileName = 'CLIENT_ID'; + +/// Name for the file where telemetry status and tools data will be stored. +const String kConfigFileName = 'dart-flutter-telemetry.config'; + +/// The string that will provide the boilerplate for the configuration file +/// stored on the user's machine. +const String kConfigString = ''' +# INTRODUCTION +# +# This is the Flutter and Dart telemetry reporting +# configuration file. +# +# Lines starting with a #" are documentation that +# the tools maintain automatically. +# +# All other lines are configuration lines. They have +# the form "name=value". If multiple lines contain +# the same configuration name with different values, +# the parser will default to a conservative value. + +# DISABLING TELEMETRY REPORTING +# +# To disable telemetry reporting, set "reporting" to +# the value "0" and to enable, set to "1": +reporting=1 + +# NOTIFICATIONS +# +# Each tool records when it last informed the user about +# analytics reporting and the privacy policy. +# +# The following tools have so far read this file: +# +# dart-tools (Dart CLI developer tool) +# devtools (DevTools debugging and performance tools) +# flutter-tools (Flutter CLI developer tool) +# +# For each one, the file may contain a configuration line +# where the name is the code in the list above, e.g. "dart-tool", +# and the value is a date in the form YYYY-MM-DD, a comma, and +# a number representing the version of the message that was +# displayed.'''; + +/// Link to contextual survey metadata file. +const String kContextualSurveyUrl = + 'https://storage.googleapis.com/flutter-uxr/surveys/contextual-survey-metadata.json'; + +/// Name of the directory where all of the files necessary for this package +/// will be located. +const String kDartToolDirectoryName = '.dart-tool'; + +/// The default time to wait before closing the http connection to allow for +/// pending events to be sent. +const int kDelayDuration = 250; + +/// Name of the file where we persist dismissed survey ids. +const String kDismissedSurveyFileName = + 'dart-flutter-telemetry-dismissed-surveys.json'; + +/// The API secret associated with the GA4 instance's Measurement Protocol. +const String kGoogleAnalyticsApiSecret = 'Ka1jc8tZSzWc_GXMWHfPHA'; + +/// The measurement ID related to the GA4 instance. +/// +/// Serves as an identifier for a web data stream. +const String kGoogleAnalyticsMeasurementId = 'G-04BXPVBCWJ'; + +/// How many data records to store in the log file. +const int kLogFileLength = 2500; + +/// The maximum allowed size of the telemetry log file. +/// +/// 25 MiB. +const int kMaxLogFileSize = 25 * (1 << 20); + +/// Filename for the log file to persist sent events on user's machine. +const String kLogFileName = 'dart-flutter-telemetry.log'; + +/// The current version of the package, should be in line with pubspec version. +const String kPackageVersion = '6.1.4'; + +/// The minimum length for a session. +const int kSessionDurationMinutes = 30; + +/// Name for the json file where the session details will be stored. +const String kSessionFileName = 'dart-flutter-telemetry-session.json'; + +/// The message that should be shown to the user. +const String kToolsMessage = ''' +The {{ toolDescription }} uses Google Analytics to report usage and diagnostic +data along with package dependencies, and crash reporting to send basic crash +reports. This data is used to help improve the Dart platform, Flutter framework, +and related tools. + +Telemetry is not sent on the very first run. To disable reporting of telemetry, +run this terminal command: + + {{ toolName }} --disable-analytics + +If you opt out of telemetry, an opt-out event will be sent, and then no further +information will be sent. This data is collected in accordance with the Google +Privacy Policy (https://policies.google.com/privacy). +'''; + +/// The version number for the message below. +/// +/// If the message below is altered, the version should be incremented so that +/// users can be prompted with the updated messaging. +const int kToolsMessageVersion = 1;
diff --git a/pkgs/unified_analytics/lib/src/enums.dart b/pkgs/unified_analytics/lib/src/enums.dart new file mode 100644 index 0000000..d67ab66 --- /dev/null +++ b/pkgs/unified_analytics/lib/src/enums.dart
@@ -0,0 +1,234 @@ +// 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. + +/// The valid dash tool labels stored in the [DashTool] enum. +List<String> get validDashTools => + DashTool.values.map((e) => e.label).toList()..sort(); + +/// Values for the event name to be sent to Google Analytics. +/// +/// The [label] for each enum value is what will be logged, the [description] +/// is here for documentation purposes. +/// +/// Set the nullable [toolOwner] parameter if the event belongs to one specific +/// tool, otherwise, if multiple tools will be sending the event, leave it null. +enum DashEvent { + // Events that can be sent by all tools; these + // events should not be tool specific; toolOwner + // not necessary for these events + + analyticsCollectionEnabled( + label: 'analytics_collection_enabled', + description: 'The opt-in status for analytics collection', + ), + analyticsException( + label: 'analytics_exception', + description: 'Errors that are encountered within package:unified_analytics', + ), + exception( + label: 'exception', + description: 'General errors to log', + ), + surveyAction( + label: 'survey_action', + description: 'Actions taken by users when shown survey', + ), + surveyShown( + label: 'survey_shown', + description: 'Survey shown to the user', + ), + timing( + label: 'timing', + description: 'Events for timing how long a process takes', + ), + + // Events for the Dart CLI + + dartCliCommandExecuted( + label: 'dart_cli_command_executed', + description: 'Information about the execution of a Dart CLI command', + toolOwner: DashTool.dartTool, + ), + pubGet( + label: 'pub_get', + description: 'Pub package resolution details', + toolOwner: DashTool.dartTool, + ), + + // Events for Flutter devtools + + devtoolsEvent( + label: 'devtools_event', + description: 'Information for various devtools events', + toolOwner: DashTool.devtools, + ), + + // Events for the Flutter CLI + + appleUsageEvent( + label: 'apple_usage_event', + description: + 'Events related to iOS/macOS workflows within the flutter tool', + toolOwner: DashTool.flutterTool, + ), + codeSizeAnalysis( + label: 'code_size_analysis', + description: 'Indicates when the "--analyize-size" command is run', + toolOwner: DashTool.flutterTool, + ), + commandUsageValues( + label: 'command_usage_values', + description: 'Contains command level custom dimensions from legacy ' + 'flutter analytics', + toolOwner: DashTool.flutterTool, + ), + doctorValidatorResult( + label: 'doctor_validator_result', + description: 'Results from a specific doctor validator', + toolOwner: DashTool.flutterTool, + ), + flutterBuildInfo( + label: 'flutter_build_info', + description: 'Information for a flutter build invocation', + toolOwner: DashTool.flutterTool, + ), + flutterCommandResult( + label: 'flutter_command_result', + description: 'Provides information about flutter commands that ran', + toolOwner: DashTool.flutterTool, + ), + hotReloadTime( + label: 'hot_reload_time', + description: 'Hot reload duration', + toolOwner: DashTool.flutterTool, + ), + hotRunnerInfo( + label: 'hot_runner_info', + description: 'Information related to the Flutter hot runner', + toolOwner: DashTool.flutterTool, + ), + + // Events for language_server below + + clientNotification( + label: 'client_notification', + description: 'Notifications sent from the client', + ), + clientRequest( + label: 'client_request', + description: 'Requests sent from the client', + ), + commandExecuted( + label: 'command_executed', + description: 'Number of times a command is executed', + ), + contextStructure( + label: 'context_structure', + description: 'Structure of the analysis contexts being analyzed', + ), + lintUsageCount( + label: 'lint_usage_count', + description: 'Number of times a given lint is enabled', + ), + memoryInfo( + label: 'memory_info', + description: 'Memory usage information', + ), + pluginRequest( + label: 'plugin_request', + description: 'Request responses from plugins', + ), + pluginUse( + label: 'plugin_use', + description: 'Information about how often a plugin was used', + ), + serverSession( + label: 'server_session', + description: 'Dart Analyzer Server session data', + ), + severityAdjustment( + label: 'severity_adjustment', + description: 'Number of times diagnostic severity is changed', + ), + ; + + final String label; + final String description; + final DashTool? toolOwner; + const DashEvent({ + required this.label, + required this.description, + this.toolOwner, + }); + + /// This takes in the string label for a given [DashEvent] and returns the + /// enum for that string label. + static DashEvent? fromLabel(String label) => + DashEvent.values.where((e) => e.label == label).firstOrNull; +} + +/// Officially-supported clients of this package as logical +/// tools, grouped by user point of view. Derived directly +/// from the PDD. +enum DashTool { + androidStudioPlugins( + label: 'android-studio-plugins', + description: 'Android Studio IDE plugins for Dart and Flutter', + ), + dartTool( + label: 'dart-tool', + description: 'Dart CLI developer tool', + ), + devtools( + label: 'devtools', + description: 'DevTools debugging and performance tools', + ), + flutterTool( + label: 'flutter-tool', + description: 'Flutter CLI developer tool', + ), + intellijPlugins( + label: 'intellij-plugins', + description: 'IntelliJ IDE plugins for Dart and Flutter', + ), + vscodePlugins( + label: 'vscode-plugins', + description: 'VS Code IDE extensions for Dart and Flutter', + ); + + /// String used as the control flag and the value of the tool key in + /// analytics. + final String label; + + /// The "notice string", a human-readable description of the logical tool + /// grouping. + final String description; + + const DashTool({ + required this.label, + required this.description, + }); + + /// This takes in the string label for a given [DashTool] and returns the + /// enum for that string label. + static DashTool fromLabel(String label) { + final tool = DashTool.values.where((t) => t.label == label).firstOrNull; + if (tool != null) return tool; + + throw Exception('The tool $label from the survey metadata file is not ' + 'a valid DashTool enum value\n' + 'Valid labels for dash tools: ${validDashTools.join(', ')}'); + } +} + +/// Enumerate options for platforms supported. +enum DevicePlatform { + windows('Windows'), + macos('macOS'), + linux('Linux'), + ; + + final String label; + const DevicePlatform(this.label); +}
diff --git a/pkgs/unified_analytics/lib/src/event.dart b/pkgs/unified_analytics/lib/src/event.dart new file mode 100644 index 0000000..a24fe0c --- /dev/null +++ b/pkgs/unified_analytics/lib/src/event.dart
@@ -0,0 +1,889 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; + +import 'enums.dart'; + +final class Event { + final DashEvent eventName; + final Map<String, Object?> eventData; + + /// Event that is emitted whenever a user has opted in + /// or out of the analytics collection. + /// + /// [status] - boolean value where `true` indicates user is opting in. + Event.analyticsCollectionEnabled({required bool status}) + : eventName = DashEvent.analyticsCollectionEnabled, + eventData = {'status': status}; + + /// Event that is emitted when an error occurs within + /// `package:unified_analytics`, tools that are using this package + /// should not use this event constructor. + /// + /// Tools using this package should instead use the more generic + /// [Event.exception] constructor. + /// + /// [workflow] - refers to what process caused the error, such as + /// "LogHandler.logFileStats". + /// + /// [error] - the name of the error, such as "FormatException". + /// + /// [description] - the description of the error being caught. + Event.analyticsException({ + required String workflow, + required String error, + String? description, + }) : eventName = DashEvent.analyticsException, + eventData = { + 'workflow': workflow, + 'error': error, + if (description != null) 'description': description, + }; + + /// This is for various workflows within the flutter tool related + /// to iOS and macOS workflows. + /// + /// [workflow] - which workflow is running, such as "assemble". + /// + /// [parameter] - subcategory of the workflow, such as "ios-archive". + /// + /// [result] - usually to indicate success or failure of the workflow. + Event.appleUsageEvent({ + required String workflow, + required String parameter, + String? result, + }) : eventName = DashEvent.appleUsageEvent, + eventData = { + 'workflow': workflow, + 'parameter': parameter, + if (result != null) 'result': result, + }; + + /// Event that is emitted periodically to report the performance of the + /// analysis server's handling of a specific kind of notification from the + /// client. + /// + /// [duration] - json encoded percentile values indicating how long it took + /// from the time the server started handling the notification until the + /// server had finished handling the notification. + /// + /// [latency] - json encoded percentile values indicating how long it took + /// from the time the notification was sent until the server started + /// handling it. + /// + /// [method] - the name of the notification method that was sent. + Event.clientNotification({ + required String duration, + required String latency, + required String method, + }) : eventName = DashEvent.clientNotification, + eventData = { + 'duration': duration, + 'latency': latency, + 'method': method, + }; + + /// Event that is emitted periodically to report the performance of the + /// analysis server's handling of a specific kind of request from the client. + /// + /// [duration] - json encoded percentile values indicating how long it took + /// from the time the server started handling the request until the server + /// had send a response. + /// + /// [latency] - json encoded percentile values indicating how long it took + /// from the time the request was sent until the server started handling + /// it. + /// + /// [method] - the name of the request method that was sent. + /// + /// If the method is `workspace/didChangeWorkspaceFolders`, then the following + /// parameters should be included: + /// + /// [added] - json encoded percentile values indicating the number of folders + /// that were added. + /// + /// [removed] - json encoded percentile values indicating the number of + /// folders that were removed. + /// + /// If the method is `initialized`, then the following parameters should be + /// included: + /// + /// [openWorkspacePaths] - json encoded percentile values indicating the + /// number of workspace paths that were opened. + /// + /// If the method is `analysis.setAnalysisRoots`, then the following + /// parameters should be included: + /// + /// [included] - json encoded percentile values indicating the number of + /// analysis roots in the included list. + /// + /// [excluded] - json encoded percentile values indicating the number of + /// analysis roots in the excluded list. + /// + /// If the method is `analysis.setPriorityFiles`, then the following + /// parameters should be included: + /// + /// [files] - json encoded percentile values indicating the number of priority + /// files. + /// + Event.clientRequest({ + required String duration, + required String latency, + required String method, + String? added, + String? excluded, + String? files, + String? included, + String? openWorkspacePaths, + String? removed, + }) : eventName = DashEvent.clientRequest, + eventData = { + if (added != null) 'added': added, + 'duration': duration, + if (excluded != null) 'excluded': excluded, + if (files != null) 'files': files, + if (included != null) 'included': included, + 'latency': latency, + 'method': method, + if (openWorkspacePaths != null) + 'openWorkspacePaths': openWorkspacePaths, + if (removed != null) 'removed': removed, + }; + + /// An event that reports when the code size measurement is run + /// via `--analyze-size`. + /// + /// [platform] - string identifier for which platform was run "ios", "apk", + /// "aab", etc. + Event.codeSizeAnalysis({required String platform}) + : eventName = DashEvent.codeSizeAnalysis, + eventData = { + 'platform': platform, + }; + + /// Event that is emitted periodically to report the number of times a given + /// command has been executed. + /// + /// [count] - the number of times the command was executed. + /// + /// [name] - the name of the command that was executed. + Event.commandExecuted({ + required int count, + required String name, + }) : eventName = DashEvent.commandExecuted, + eventData = { + 'count': count, + 'name': name, + }; + + /// Event to capture usage values for different flutter commands. + /// + /// There are several implementations of the `FlutterCommand` class within the + /// flutter-tool that pass information based on the [workflow] being ran. An + /// example of a [workflow] can be "create". The optional parameters for this + /// constructor are a superset of all the implementations of `FlutterCommand`. + /// There should never be a time where all of the parameters are passed to + /// this constructor. + Event.commandUsageValues({ + required String workflow, + required bool commandHasTerminal, + + // Assemble && build bundle implementation parameters + String? buildBundleTargetPlatform, + bool? buildBundleIsModule, + + // Build aar implementation parameters + String? buildAarProjectType, + String? buildAarTargetPlatform, + + // Build apk implementation parameters + String? buildApkTargetPlatform, + String? buildApkBuildMode, + bool? buildApkSplitPerAbi, + + // Build app bundle implementation parameters + String? buildAppBundleTargetPlatform, + String? buildAppBundleBuildMode, + + // Create implementation parameters + String? createProjectType, + String? createAndroidLanguage, + String? createIosLanguage, + + // Packages implementation parameters + int? packagesNumberPlugins, + bool? packagesProjectModule, + String? packagesAndroidEmbeddingVersion, + + // Run implementation parameters + bool? runIsEmulator, + String? runTargetName, + String? runTargetOsVersion, + String? runModeName, + bool? runProjectModule, + String? runProjectHostLanguage, + String? runAndroidEmbeddingVersion, + bool? runEnableImpeller, + String? runIOSInterfaceType, + bool? runIsTest, + }) : eventName = DashEvent.commandUsageValues, + eventData = { + 'workflow': workflow, + 'commandHasTerminal': commandHasTerminal, + if (buildBundleTargetPlatform != null) + 'buildBundleTargetPlatform': buildBundleTargetPlatform, + if (buildBundleIsModule != null) + 'buildBundleIsModule': buildBundleIsModule, + if (buildAarProjectType != null) + 'buildAarProjectType': buildAarProjectType, + if (buildAarTargetPlatform != null) + 'buildAarTargetPlatform': buildAarTargetPlatform, + if (buildApkTargetPlatform != null) + 'buildApkTargetPlatform': buildApkTargetPlatform, + if (buildApkBuildMode != null) 'buildApkBuildMode': buildApkBuildMode, + if (buildApkSplitPerAbi != null) + 'buildApkSplitPerAbi': buildApkSplitPerAbi, + if (buildAppBundleTargetPlatform != null) + 'buildAppBundleTargetPlatform': buildAppBundleTargetPlatform, + if (buildAppBundleBuildMode != null) + 'buildAppBundleBuildMode': buildAppBundleBuildMode, + if (createProjectType != null) 'createProjectType': createProjectType, + if (createAndroidLanguage != null) + 'createAndroidLanguage': createAndroidLanguage, + if (createIosLanguage != null) 'createIosLanguage': createIosLanguage, + if (packagesNumberPlugins != null) + 'packagesNumberPlugins': packagesNumberPlugins, + if (packagesProjectModule != null) + 'packagesProjectModule': packagesProjectModule, + if (packagesAndroidEmbeddingVersion != null) + 'packagesAndroidEmbeddingVersion': packagesAndroidEmbeddingVersion, + if (runIsEmulator != null) 'runIsEmulator': runIsEmulator, + if (runTargetName != null) 'runTargetName': runTargetName, + if (runTargetOsVersion != null) + 'runTargetOsVersion': runTargetOsVersion, + if (runModeName != null) 'runModeName': runModeName, + if (runProjectModule != null) 'runProjectModule': runProjectModule, + if (runProjectHostLanguage != null) + 'runProjectHostLanguage': runProjectHostLanguage, + if (runAndroidEmbeddingVersion != null) + 'runAndroidEmbeddingVersion': runAndroidEmbeddingVersion, + if (runEnableImpeller != null) 'runEnableImpeller': runEnableImpeller, + if (runIOSInterfaceType != null) + 'runIOSInterfaceType': runIOSInterfaceType, + if (runIsTest != null) 'runIsTest': runIsTest, + }; + + /// Event that is emitted on shutdown to report the structure of the analysis + /// contexts created immediately after startup. + /// + /// [contextsFromBothFiles] - the number of contexts that were created because + /// of both a package config and an analysis options file. + /// + /// [contextsFromOptionsFiles] - the number of contexts that were created + /// because of an analysis options file. + /// + /// [contextsFromPackagesFiles] - the number of contexts that were created + /// because of a package config file. + /// + /// [contextsWithoutFiles] - the number of contexts that were created because + /// of the lack of either a package config or an analysis options file. + /// + /// [immediateFileCount] - the number of files in one of the analysis + /// contexts. + /// + /// [immediateFileLineCount] - the number of lines in the immediate files. + /// + /// [numberOfContexts] - the number of analysis context created. + /// + /// [transitiveFileCount] - the number of files reachable from the files in + /// each analysis context, where files can be counted multiple times if + /// they are reachable from multiple contexts. + /// + /// [transitiveFileLineCount] - the number of lines in the transitive files, + /// where files can be counted multiple times if they are reachable from + /// multiple contexts. + /// + /// [transitiveFileUniqueCount] - the number of unique files reachable from + /// the files in each analysis context. + /// + /// [transitiveFileUniqueLineCount] - the number of lines in the unique + /// transitive files. + Event.contextStructure({ + required int contextsFromBothFiles, + required int contextsFromOptionsFiles, + required int contextsFromPackagesFiles, + required int contextsWithoutFiles, + required int immediateFileCount, + required int immediateFileLineCount, + required int numberOfContexts, + required int transitiveFileCount, + required int transitiveFileLineCount, + required int transitiveFileUniqueCount, + required int transitiveFileUniqueLineCount, + }) : eventName = DashEvent.contextStructure, + eventData = { + 'contextsFromBothFiles': contextsFromBothFiles, + 'contextsFromOptionsFiles': contextsFromOptionsFiles, + 'contextsFromPackagesFiles': contextsFromPackagesFiles, + 'contextsWithoutFiles': contextsWithoutFiles, + 'immediateFileCount': immediateFileCount, + 'immediateFileLineCount': immediateFileLineCount, + 'numberOfContexts': numberOfContexts, + 'transitiveFileCount': transitiveFileCount, + 'transitiveFileLineCount': transitiveFileLineCount, + 'transitiveFileUniqueCount': transitiveFileUniqueCount, + 'transitiveFileUniqueLineCount': transitiveFileUniqueLineCount, + }; + + /// Event that is emitted when a Dart CLI command has been executed. + /// + /// [name] - the name of the command that was executed + /// + /// [enabledExperiments] - a set of Dart language experiments enabled when + /// running the command. + /// + /// [exitCode] - the process exit code set as a result of running the command. + Event.dartCliCommandExecuted({ + required String name, + required String enabledExperiments, + int? exitCode, + }) : eventName = DashEvent.dartCliCommandExecuted, + eventData = { + 'name': name, + 'enabledExperiments': enabledExperiments, + if (exitCode != null) 'exitCode': exitCode, + }; + + /// Event that is sent from devtools for various different actions as + /// indicated by the [eventCategory]. + Event.devtoolsEvent({ + required String eventCategory, + required String label, + required int value, + + // Defaulted values + bool userInitiatedInteraction = true, + + // Optional parameters + String? g3Username, + String? userApp, + String? userBuild, + String? userPlatform, + String? devtoolsPlatform, + String? devtoolsChrome, + String? devtoolsVersion, + String? ideLaunched, + String? isExternalBuild, + String? isEmbedded, + String? ideLaunchedFeature, + String? isWasm, + + // PerformanceScreenMetrics + int? uiDurationMicros, + int? rasterDurationMicros, + int? shaderCompilationDurationMicros, + int? traceEventCount, + + // ProfilerScreenMetrics + int? cpuSampleCount, + int? cpuStackDepth, + + // MemoryScreenMetrics + int? heapDiffObjectsBefore, + int? heapDiffObjectsAfter, + int? heapObjectsTotal, + + // InspectorScreenMetrics + int? rootSetCount, + int? rowCount, + int? inspectorTreeControllerId, + + // DeepLinkScreenMetrics + String? androidAppId, + String? iosBundleId, + }) : eventName = DashEvent.devtoolsEvent, + eventData = { + 'eventCategory': eventCategory, + 'label': label, + 'value': value, + + 'userInitiatedInteraction': userInitiatedInteraction, + + // Optional parameters + if (g3Username != null) 'g3Username': g3Username, + if (userApp != null) 'userApp': userApp, + if (userBuild != null) 'userBuild': userBuild, + if (userPlatform != null) 'userPlatform': userPlatform, + if (devtoolsPlatform != null) 'devtoolsPlatform': devtoolsPlatform, + if (devtoolsChrome != null) 'devtoolsChrome': devtoolsChrome, + if (devtoolsVersion != null) 'devtoolsVersion': devtoolsVersion, + if (ideLaunched != null) 'ideLaunched': ideLaunched, + if (isExternalBuild != null) 'isExternalBuild': isExternalBuild, + if (isEmbedded != null) 'isEmbedded': isEmbedded, + if (ideLaunchedFeature != null) + 'ideLaunchedFeature': ideLaunchedFeature, + if (isWasm != null) 'isWasm': isWasm, + + // PerformanceScreenMetrics + if (uiDurationMicros != null) 'uiDurationMicros': uiDurationMicros, + if (rasterDurationMicros != null) + 'rasterDurationMicros': rasterDurationMicros, + if (shaderCompilationDurationMicros != null) + 'shaderCompilationDurationMicros': shaderCompilationDurationMicros, + if (traceEventCount != null) 'traceEventCount': traceEventCount, + + // ProfilerScreenMetrics + if (cpuSampleCount != null) 'cpuSampleCount': cpuSampleCount, + if (cpuStackDepth != null) 'cpuStackDepth': cpuStackDepth, + + // MemoryScreenMetrics + if (heapDiffObjectsBefore != null) + 'heapDiffObjectsBefore': heapDiffObjectsBefore, + if (heapDiffObjectsAfter != null) + 'heapDiffObjectsAfter': heapDiffObjectsAfter, + if (heapObjectsTotal != null) 'heapObjectsTotal': heapObjectsTotal, + + // InspectorScreenMetrics + if (rootSetCount != null) 'rootSetCount': rootSetCount, + if (rowCount != null) 'rowCount': rowCount, + if (inspectorTreeControllerId != null) + 'inspectorTreeControllerId': inspectorTreeControllerId, + // DeepLinkScreenMetrics + if (androidAppId != null) 'androidAppId': androidAppId, + if (iosBundleId != null) 'iosBundleId': iosBundleId, + }; + + /// Event that contains the results for a specific doctor validator. + /// + /// [validatorName] - the name for the doctor validator. + /// + /// [result] - the final result for a specific doctor validator. + /// + /// [partOfGroupedValidator] - `true` indicates that this validator belongs + /// to a grouped validator. + /// + /// [doctorInvocationId] - epoch formatted timestamp that can be used in + /// combination with the client ID in GA4 to group the validators that + /// ran in one doctor invocation. + /// + /// [statusInfo] - optional description of the result from the + /// doctor validator. + Event.doctorValidatorResult({ + required String validatorName, + required String result, + required bool partOfGroupedValidator, + required int doctorInvocationId, + String? statusInfo, + }) : eventName = DashEvent.doctorValidatorResult, + eventData = { + 'validatorName': validatorName, + 'result': result, + 'partOfGroupedValidator': partOfGroupedValidator, + 'doctorInvocationId': doctorInvocationId, + if (statusInfo != null) 'statusInfo': statusInfo, + }; + + /// Generic event for all dash tools to use when encountering an + /// exception that we want to log. + /// + /// [exception] - string representation of the exception that occured. + /// [data] - optional structured data to include with the exception event. + Event.exception({ + required String exception, + Map<String, Object?> data = const <String, Object?>{}, + }) : eventName = DashEvent.exception, + eventData = { + 'exception': exception, + ...data, + }; + + /// Event that is emitted from the flutter tool when a build invocation + /// has been run by the user. + /// + /// [label] - the identifier for that build event. + /// + /// [buildType] - the identifier for which platform the build event was for, + /// examples include "ios", "gradle", and "web". + /// + /// [command] - the command that was ran to kick off the build event. + /// + /// [settings] - the settings used for the build event related to + /// configuration and other relevant build information. + /// + /// [error] - short identifier used to explain the cause of the build error, + /// stacktraces should not be passed to this parameter. + Event.flutterBuildInfo({ + required String label, + required String buildType, + String? command, + String? settings, + String? error, + }) : eventName = DashEvent.flutterBuildInfo, + eventData = { + 'label': label, + 'buildType': buildType, + if (command != null) 'command': command, + if (settings != null) 'settings': settings, + if (error != null) 'error': error, + }; + + /// Provides information about which flutter command was run + /// and whether it was successful. + /// + /// [commandPath] - information about the flutter command, such as "build/apk". + /// + /// [result] - if the command failed or succeeded. + /// + /// [commandHasTerminal] - boolean indicating if the flutter command ran with + /// a terminal. + /// + /// [maxRss] - maximum resident size for a given flutter command. + Event.flutterCommandResult({ + required String commandPath, + required String result, + required bool commandHasTerminal, + int? maxRss, + }) : eventName = DashEvent.flutterCommandResult, + eventData = { + 'commandPath': commandPath, + 'result': result, + 'commandHasTerminal': commandHasTerminal, + if (maxRss != null) 'maxRss': maxRss, + }; + + // TODO: eliasyishak, remove this or replace once we have a generic + // timing event that can be used by potentially more than one DashTool + Event.hotReloadTime({required int timeMs}) + : eventName = DashEvent.hotReloadTime, + eventData = {'timeMs': timeMs}; + + /// Events to be sent for the Flutter Hot Runner. + Event.hotRunnerInfo({ + required String label, + required String targetPlatform, + required String sdkName, + required bool emulator, + required bool fullRestart, + String? reason, + int? finalLibraryCount, + int? syncedLibraryCount, + int? syncedClassesCount, + int? syncedProceduresCount, + int? syncedBytes, + int? invalidatedSourcesCount, + int? transferTimeInMs, + int? overallTimeInMs, + int? compileTimeInMs, + int? findInvalidatedTimeInMs, + int? scannedSourcesCount, + int? reassembleTimeInMs, + int? reloadVMTimeInMs, + }) : eventName = DashEvent.hotRunnerInfo, + eventData = { + 'label': label, + 'targetPlatform': targetPlatform, + 'sdkName': sdkName, + 'emulator': emulator, + 'fullRestart': fullRestart, + if (reason != null) 'reason': reason, + if (finalLibraryCount != null) 'finalLibraryCount': finalLibraryCount, + if (syncedLibraryCount != null) + 'syncedLibraryCount': syncedLibraryCount, + if (syncedClassesCount != null) + 'syncedClassesCount': syncedClassesCount, + if (syncedProceduresCount != null) + 'syncedProceduresCount': syncedProceduresCount, + if (syncedBytes != null) 'syncedBytes': syncedBytes, + if (invalidatedSourcesCount != null) + 'invalidatedSourcesCount': invalidatedSourcesCount, + if (transferTimeInMs != null) 'transferTimeInMs': transferTimeInMs, + if (overallTimeInMs != null) 'overallTimeInMs': overallTimeInMs, + if (compileTimeInMs != null) 'compileTimeInMs': compileTimeInMs, + if (findInvalidatedTimeInMs != null) + 'findInvalidatedTimeInMs': findInvalidatedTimeInMs, + if (scannedSourcesCount != null) + 'scannedSourcesCount': scannedSourcesCount, + if (reassembleTimeInMs != null) + 'reassembleTimeInMs': reassembleTimeInMs, + if (reloadVMTimeInMs != null) 'reloadVMTimeInMs': reloadVMTimeInMs, + }; + + // TODO: eliasyishak, add better dartdocs to explain each param + /// Event that is emitted periodically to report the number of times each lint + /// has been enabled. + /// + /// [count] - the number of contexts in which the lint was enabled. + /// + /// [name] - the name of the lint. + Event.lintUsageCount({ + required int count, + required String name, + }) : eventName = DashEvent.lintUsageCount, + eventData = { + 'count': count, + 'name': name, + }; + + /// Event that is emitted periodically to report the amount of memory being + /// used. + /// + /// [rss] - the resident set size in megabytes. + /// + /// If this is not the first time memory has been reported for this session, + /// then the following parameters should be included: + /// + /// [periodSec] - the number of seconds since the last memory usage data was + /// gathered. + /// + /// [mbPerSec] - the number of megabytes of memory that were added or + /// subtracted per second since the last report. + Event.memoryInfo({ + required int rss, + int? periodSec, + double? mbPerSec, + }) : eventName = DashEvent.memoryInfo, + eventData = { + 'rss': rss, + if (periodSec != null) 'periodSec': periodSec, + if (mbPerSec != null) 'mbPerSec': mbPerSec + }; + + /// Event that is emitted periodically to report the performance of plugins + /// when handling requests. + /// + /// [duration] - json encoded percentile values indicating how long it took + /// from the time the request was sent to the plugin until the response + /// was processed by the server. + /// + /// [method] - the name of the request sent to the plugin. + /// + /// [pluginId] - the id of the plugin whose performance is being reported. + Event.pluginRequest({ + required String duration, + required String method, + required String pluginId, + }) : eventName = DashEvent.pluginRequest, + eventData = { + 'duration': duration, + 'method': method, + 'pluginId': pluginId, + }; + + /// Event that is emitted periodically to report the frequency with which a + /// given plugin has been used. + /// + /// [count] - the number of times plugins usage was changed, which will always + /// be at least one. + /// + /// [enabled] - json encoded percentile values indicating the number of + /// contexts for which the plugin was enabled. + /// + /// [pluginId] - the id of the plugin associated with the data. + Event.pluginUse({ + required int count, + required String enabled, + required String pluginId, + }) : eventName = DashEvent.pluginUse, + eventData = { + 'count': count, + 'enabled': enabled, + 'pluginId': pluginId, + }; + + /// Event that is emitted when `pub get` is run. + /// + /// [packageName] - the name of the package that was resolved + /// + /// [version] - the resolved, canonicalized package version + /// + /// [dependencyType] - the kind of dependency that resulted in this package + /// being resolved (e.g., direct, transitive, or dev dependencies). + Event.pubGet({ + required String packageName, + required String version, + required String dependencyType, + }) : eventName = DashEvent.pubGet, + eventData = { + 'packageName': packageName, + 'version': version, + 'dependencyType': dependencyType, + }; + + /// Event that is emitted on shutdown to report information about the whole + /// session for which the analysis server was running. + /// + /// [clientId] - the id of the client that started the server. + /// + /// [clientVersion] - the version of the client that started the server. + /// + /// [duration] - the number of milliseconds for which the server was running. + /// + /// [flags] - the flags passed to the analysis server on startup, without any + /// argument values for flags that take values, or an empty string if + /// there were no arguments. + /// + /// [parameters] - the names of the parameters passed to the `initialize` + /// request, or an empty string if the `initialize` request was not sent + /// or if there were no parameters given. + Event.serverSession({ + required String clientId, + required String clientVersion, + required int duration, + required String flags, + required String parameters, + }) : eventName = DashEvent.serverSession, + eventData = { + 'clientId': clientId, + 'clientVersion': clientVersion, + 'duration': duration, + 'flags': flags, + 'parameters': parameters, + }; + + /// Event that is emitted periodically to report the number of times the + /// severity of a diagnostic was changed in the analysis options file. + /// + /// [diagnostic] - the name of the diagnostic whose severity was changed. + /// + /// [adjustments] - json encoded map of severities to the number of times the + /// diagnostic's severity was changed to the key. + Event.severityAdjustment({ + required String diagnostic, + required String adjustments, + }) : eventName = DashEvent.severityAdjustment, + eventData = { + 'diagnostic': diagnostic, + 'adjustments': adjustments, + }; + + /// Event that is emitted by `package:unified_analytics` when + /// the user takes action when prompted with a survey. + /// + /// [surveyId] - the unique id for a given survey. + /// + /// [status] - the string identifier for a given `SurveyButton` under the + /// `action` field. + Event.surveyAction({ + required String surveyId, + required String status, + }) : eventName = DashEvent.surveyAction, + eventData = { + 'surveyId': surveyId, + 'status': status, + }; + + /// Event that is emitted by `package:unified_analytics` when the + /// user has been shown a survey. + /// + /// [surveyId] - the unique id for a given survey. + Event.surveyShown({ + required String surveyId, + }) : eventName = DashEvent.surveyShown, + eventData = { + 'surveyId': surveyId, + }; + + /// Event that records how long a given process takes to complete. + /// + /// [workflow] - the overall process or command being run, for example + /// "build" is a possible value for the flutter tool. + /// + /// [variableName] - the specific variable being measured, for example + /// "gradle" would indicate how long it took for a gradle build under the + /// "build" [workflow]. + /// + /// [elapsedMilliseconds] - how long the process took in milliseconds. + /// + /// [label] - an optional field that can be used for further filtering, for + /// example, "success" can indicate how long a successful build in gradle + /// takes to complete. + Event.timing({ + required String workflow, + required String variableName, + required int elapsedMilliseconds, + String? label, + }) : eventName = DashEvent.timing, + eventData = { + 'workflow': workflow, + 'variableName': variableName, + 'elapsedMilliseconds': elapsedMilliseconds, + if (label != null) 'label': label, + }; + + /// Private constructor to be used when deserializing JSON into an instance + /// of [Event]. + Event._({required this.eventName, required this.eventData}); + + @override + int get hashCode => Object.hash(eventName, jsonEncode(eventData)); + + @override + bool operator ==(Object other) => + other is Event && + other.runtimeType == runtimeType && + other.eventName == eventName && + _compareEventData(other.eventData, eventData); + + /// Converts an instance of [Event] to JSON. + String toJson() => jsonEncode({ + 'eventName': eventName.label, + 'eventData': eventData, + }); + + @override + String toString() => toJson(); + + /// Utility function to take in two maps [a] and [b] and compares them + /// to ensure that they have the same keys and values + bool _compareEventData(Map<String, Object?> a, Map<String, Object?> b) { + final keySetA = a.keys.toSet(); + final keySetB = b.keys.toSet(); + final intersection = keySetA.intersection(keySetB); + + // Ensure that the keys are the same for each object + if (intersection.length != keySetA.length || + intersection.length != keySetB.length) { + return false; + } + + // Ensure that each of the key's values are the same + for (final key in a.keys) { + if (a[key] != b[key]) return false; + } + + return true; + } + + /// Returns a valid instance of [Event] if [json] follows the correct schema. + /// + /// Common use case for this static method involves clients of this package + /// that have a client-server setup where the server sends events that the + /// client creates. + static Event? fromJson(String json) { + try { + final jsonMap = jsonDecode(json) as Map<String, Object?>; + + // Ensure that eventName is a string and a valid label and + // eventData is a nested object + if (jsonMap + case { + 'eventName': final String eventName, + 'eventData': final Map<String, Object?> eventData, + }) { + final dashEvent = DashEvent.fromLabel(eventName); + if (dashEvent == null) return null; + + return Event._( + eventName: dashEvent, + eventData: eventData, + ); + } + + return null; + } on FormatException { + return null; + } + } +}
diff --git a/pkgs/unified_analytics/lib/src/ga_client.dart b/pkgs/unified_analytics/lib/src/ga_client.dart new file mode 100644 index 0000000..2c3e83e --- /dev/null +++ b/pkgs/unified_analytics/lib/src/ga_client.dart
@@ -0,0 +1,86 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; + +import 'package:http/http.dart' as http; + +import 'constants.dart'; + +class FakeGAClient implements GAClient { + const FakeGAClient(); + + @override + String get apiSecret => throw UnimplementedError(); + + @override + String get measurementId => throw UnimplementedError(); + + @override + String get postUrl => throw UnimplementedError(); + + @override + http.Client get _client => throw UnimplementedError(); + + @override + void close() {} + + @override + Future<http.Response> sendData(Map<String, Object?> body) => + Future<http.Response>.value(http.Response('', 200)); +} + +class GAClient { + final String measurementId; + final String apiSecret; + final String postUrl; + final http.Client _client; + + GAClient({ + required this.measurementId, + required this.apiSecret, + }) : postUrl = '$kAnalyticsUrl?' + 'measurement_id=$measurementId&api_secret=$apiSecret', + _client = http.Client(); + + /// Closes the http client's connection to prevent lingering requests. + void close() => _client.close(); + + /// Receive the payload in Map form and parse + /// into JSON to send to GA. + /// + /// The [http.Response] returned from this method can be + /// checked to ensure that events have been sent. A response + /// status code of `2xx` indicates a successful send event. + /// A response status code of `500` indicates an error occured on the send + /// can the error message can be found in the [http.Response.body]. + Future<http.Response> sendData(Map<String, Object?> body) async { + final uri = Uri.parse(postUrl); + + // Using a try catch all since post method can result in several + // errors; clients using this method can check the awaited status + // code to get a specific error message if the status code returned + // is a 500 error status code + try { + return await _client.post( + uri, + headers: <String, String>{ + 'Content-Type': 'application/json; charset=UTF-8', + }, + body: jsonEncode(body), + ); + // ignore: avoid_catches_without_on_clauses + } catch (error) { + return Future<http.Response>.value( + http.Response( + error.toString(), + 500, + headers: <String, String>{ + 'content-type': 'text/plain; charset=utf-8', + }, + ), + ); + } + } +}
diff --git a/pkgs/unified_analytics/lib/src/initializer.dart b/pkgs/unified_analytics/lib/src/initializer.dart new file mode 100644 index 0000000..131968b --- /dev/null +++ b/pkgs/unified_analytics/lib/src/initializer.dart
@@ -0,0 +1,118 @@ +// 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:clock/clock.dart'; +import 'package:file/file.dart'; + +import 'constants.dart'; +import 'utils.dart'; + +/// Creates the text file that will contain the client ID +/// which will be used across all related tools for analytics +/// reporting in GA. +void createClientIdFile({required File clientIdFile}) { + clientIdFile.createSync(recursive: true); + clientIdFile.writeAsStringSync(Uuid().generateV4()); +} + +/// Creates the configuration file with the default message +/// in the user's home directory. +void createConfigFile({ + required File configFile, + required Directory homeDirectory, +}) { + configFile.createSync(recursive: true); + + // If the user was previously opted out, then we will + // replace the line that assumes automatic opt in with + // an opt out from the start + if (legacyOptOut(homeDirectory: homeDirectory)) { + configFile.writeAsStringSync( + kConfigString.replaceAll('reporting=1', 'reporting=0')); + } else { + configFile.writeAsStringSync(kConfigString); + } +} + +/// Creates that file that will persist dismissed survey ids. +void createDismissedSurveyFile({required File dismissedSurveyFile}) { + dismissedSurveyFile.createSync(recursive: true); + dismissedSurveyFile.writeAsStringSync('{}'); +} + +/// Creates that log file that will store the record formatted +/// events locally on the user's machine. +void createLogFile({required File logFile}) { + logFile.createSync(recursive: true); +} + +/// Creates the session file which will contain +/// the current session id which is the current timestamp. +/// +/// It also returns the timestamp used for the session if it needs +/// to be accessed. +DateTime createSessionFile({required File sessionFile}) { + final now = clock.now(); + sessionFile.createSync(recursive: true); + writeSessionContents(sessionFile: sessionFile); + + return now; +} + +/// Performs all of the initialization checks for the required files. +/// +/// Returns `true` if the config file was created indicating it is the first +/// time this package was run on a user's machine. +/// +/// Checks for the following: +/// - Config file +/// - Client ID file +/// - Session JSON file +/// - Log file +/// - Dismissed survey JSON file +bool runInitialization({ + required Directory homeDirectory, +}) { + var firstRun = false; + final dartToolDirectory = + homeDirectory.childDirectory(kDartToolDirectoryName); + + // When the config file doesn't exist, initialize it with the default tools + // and the current date. + final configFile = dartToolDirectory.childFile(kConfigFileName); + if (!configFile.existsSync()) { + firstRun = true; + createConfigFile( + configFile: configFile, + homeDirectory: homeDirectory, + ); + } + + // Begin initialization checks for the client id. + final clientFile = dartToolDirectory.childFile(kClientIdFileName); + if (!clientFile.existsSync()) { + createClientIdFile(clientIdFile: clientFile); + } + + // Begin initialization checks for the session file. + final sessionFile = dartToolDirectory.childFile(kSessionFileName); + if (!sessionFile.existsSync()) { + createSessionFile(sessionFile: sessionFile); + } + + // Begin initialization checks for the log file to persist events locally. + final logFile = dartToolDirectory.childFile(kLogFileName); + if (!logFile.existsSync()) { + createLogFile(logFile: logFile); + } + + // Begin initialization checks for the dismissed survey file. + final dismissedSurveyFile = + dartToolDirectory.childFile(kDismissedSurveyFileName); + if (!dismissedSurveyFile.existsSync()) { + createDismissedSurveyFile(dismissedSurveyFile: dismissedSurveyFile); + } + + return firstRun; +}
diff --git a/pkgs/unified_analytics/lib/src/log_handler.dart b/pkgs/unified_analytics/lib/src/log_handler.dart new file mode 100644 index 0000000..a6ef2f5 --- /dev/null +++ b/pkgs/unified_analytics/lib/src/log_handler.dart
@@ -0,0 +1,464 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; + +import 'package:clock/clock.dart'; +import 'package:file/file.dart'; + +import 'constants.dart'; +import 'event.dart'; +import 'initializer.dart'; + +/// Data class that will be returned when analyzing the +/// persisted log file on the client's machine. +class LogFileStats { + /// The oldest timestamp in the log file. + final DateTime startDateTime; + + /// Number of minutes from [startDateTime] to now using [clock]. + final int minsFromStartDateTime; + + /// The latest timestamp in the log file. + final DateTime endDateTime; + + /// Number of minutes from [endDateTime] to now using [clock]. + final int minsFromEndDateTime; + + /// The number of unique session ids found in the log file. + final int sessionCount; + + /// The map containing all of the flutter channels and a count + /// of how many events were under each channel. + /// + /// ``` + /// { + /// 'stable': 123, + /// 'beta': 50, + /// 'master': 5, + /// } + /// ``` + final Map<String, int> flutterChannelCount; + + /// The map containing all of the tools that have sent events + /// and how many events were sent by each tool. + /// + /// ``` + /// { + /// 'flutter-tool': 500, + /// 'dart-tool': 45, + /// 'vscode-plugins': 321, + /// } + /// ``` + final Map<String, int> toolCount; + + /// The map containing all of the events in the file along with + /// how many times they have occured. + /// + /// ``` + /// { + /// 'client_request': 345, + /// 'hot_reload_time': 765, + /// 'memory_info': 90, + /// } + /// ``` + final Map<String, int> eventCount; + + /// Total number of records in the log file. + final int recordCount; + + /// Contains the data from the [LogHandler.logFileStats] method. + const LogFileStats({ + required this.startDateTime, + required this.minsFromStartDateTime, + required this.endDateTime, + required this.minsFromEndDateTime, + required this.sessionCount, + required this.flutterChannelCount, + required this.toolCount, + required this.recordCount, + required this.eventCount, + }); + + /// Pass in a string label for one of the instance variables + /// and return the integer value of that label. + /// + /// If label passed for [DateTime] instance variable, integer + /// in the form of [DateTime.millisecondsSinceEpoch] will be + /// returned. + /// + /// Returns null if the label passed does not match anything. + int? getValueByString(String label) { + // When querying counts, the label will include the + // key for the appropriate map + // + // Example: logFileStats.toolCount.flutter-tool is asking + // for the number of events sent via flutter cli + final parts = label.split('.'); + String? key; + if (parts.length >= 3) { + // Assign the first two parts of the string as the label + // ie. logFileStats.toolCount.flutter-tool -> logFileStats.toolCount + label = parts.sublist(0, 2).join('.'); + key = parts.sublist(2, parts.length).join('.'); + } + + switch (label) { + case 'logFileStats.startDateTime': + return startDateTime.millisecondsSinceEpoch; + case 'logFileStats.minsFromStartDateTime': + return minsFromStartDateTime; + case 'logFileStats.endDateTime': + return endDateTime.millisecondsSinceEpoch; + case 'logFileStats.minsFromEndDateTime': + return minsFromEndDateTime; + case 'logFileStats.sessionCount': + return sessionCount; + case 'logFileStats.recordCount': + return recordCount; + case 'logFileStats.flutterChannelCount': + if (key != null && flutterChannelCount.containsKey(key)) { + return flutterChannelCount[key]; + } + case 'logFileStats.toolCount': + if (key != null && toolCount.containsKey(key)) { + return toolCount[key]; + } + case 'logFileStats.eventCount': + if (key != null && eventCount.containsKey(key)) { + return eventCount[key]; + } + } + + return null; + } + + @override + String toString() { + const encoder = JsonEncoder.withIndent(' '); + return encoder.convert({ + 'startDateTime': startDateTime.toString(), + 'minsFromStartDateTime': minsFromStartDateTime, + 'endDateTime': endDateTime.toString(), + 'minsFromEndDateTime': minsFromEndDateTime, + 'sessionCount': sessionCount, + 'recordCount': recordCount, + 'eventCount': eventCount, + 'toolCount': toolCount, + 'flutterChannelCount': flutterChannelCount, + }); + } +} + +/// This class is responsible for writing to a log +/// file that has been initialized by the [createLogFile]. +/// +/// It will be treated as an append only log and will be limited +/// to have has many data records as specified by [kLogFileLength]. +class LogHandler { + final File logFile; + + /// Contains instances of [Event.analyticsException] that were encountered + /// during a workflow and will be sent to GA4 for collection. + final Set<Event> errorSet = {}; + + /// A log handler constructor that will delegate saving + /// logs and retrieving stats from the persisted log. + LogHandler({required this.logFile}); + + /// Get stats from the persisted log file. + /// + /// Note that some developers may only be Dart + /// developers and will not have any data for flutter + /// related metrics. + LogFileStats? logFileStats() { + // Parse each line of the log file through [LogItem], + // some returned records may be null if malformed, they will be + // removed later through `whereType<LogItem>` + final records = logFile + .readAsLinesSync() + .map((String e) { + try { + return LogItem.fromRecord(jsonDecode(e) as Map<String, Object?>); + } on FormatException catch (err) { + errorSet.add(Event.analyticsException( + workflow: 'LogFileStats.logFileStats', + error: err.runtimeType.toString(), + description: 'message: ${err.message}\nsource: ${err.source}', + )); + + return null; + // ignore: avoid_catching_errors + } on TypeError catch (err) { + errorSet.add(Event.analyticsException( + workflow: 'LogFileStats.logFileStats', + error: err.runtimeType.toString(), + )); + + return null; + } + }) + .whereType<LogItem>() + .toList(); + + if (records.isEmpty) return null; + + // Get the start and end dates for the log file + final startDateTime = records.first.localTime; + final endDateTime = records.last.localTime; + + // Map with counters for user properties + final counter = <String, Set<Object>>{ + 'sessions': <int>{}, + 'flutter_channel': <String>{}, + 'tool': <String>{}, + }; + + // Map of counters for each event + final eventCount = <String, int>{}; + final flutterChannelCount = <String, int>{}; + final toolCount = <String, int>{}; + for (final record in records) { + counter['sessions']!.add(record.sessionId); + counter['tool']!.add(record.tool); + if (record.flutterChannel != null) { + counter['flutter_channel']!.add(record.flutterChannel!); + } + + // Count each event, if it doesn't exist in the [eventCount] + // it will be added first + if (!eventCount.containsKey(record.eventName)) { + eventCount[record.eventName] = 0; + } + eventCount[record.eventName] = eventCount[record.eventName]! + 1; + + // Counting how many events were recorded for each tool + if (!toolCount.containsKey(record.tool)) { + toolCount[record.tool] = 0; + } + toolCount[record.tool] = toolCount[record.tool]! + 1; + + // Necessary to perform a null check for flutter channel because + // not all events will have information about flutter + if (record.flutterChannel != null) { + final flutterChannel = record.flutterChannel!; + if (!flutterChannelCount.containsKey(flutterChannel)) { + flutterChannelCount[flutterChannel] = 0; + } + + flutterChannelCount[flutterChannel] = + flutterChannelCount[flutterChannel]! + 1; + } + } + + final now = clock.now(); + + return LogFileStats( + startDateTime: startDateTime, + minsFromStartDateTime: now.difference(startDateTime).inMinutes, + endDateTime: endDateTime, + minsFromEndDateTime: now.difference(endDateTime).inMinutes, + sessionCount: counter['sessions']!.length, + flutterChannelCount: flutterChannelCount, + toolCount: toolCount, + eventCount: eventCount, + recordCount: records.length, + ); + } + + /// Saves the data passed in as a single line in the log file. + /// + /// This will keep the max number of records limited to equal to + /// or less than [kLogFileLength] records. + void save({required Map<String, Object?> data}) { + try { + final stat = logFile.statSync(); + List<String> records; + if (stat.size > kMaxLogFileSize) { + logFile.deleteSync(); + logFile.createSync(); + records = []; + } else { + records = logFile.readAsLinesSync(); + } + final content = '${jsonEncode(data)}\n'; + + // When the record count is less than the max, add as normal; + // else drop the oldest records until equal to max + if (records.length < kLogFileLength) { + logFile.writeAsStringSync(content, mode: FileMode.writeOnlyAppend); + } else { + records.add(content); + records = records.skip(records.length - kLogFileLength).toList(); + + logFile.writeAsStringSync(records.join('\n')); + } + } on FileSystemException { + // Logging isn't important enough to warrant raising a + // FileSystemException that will surprise consumers of this package. + } + } +} + +/// Data class for each record persisted on the client's machine. +class LogItem { + final String eventName; + final int sessionId; + final String? flutterChannel; + final String host; + final String? flutterVersion; + final String dartVersion; + final String tool; + final DateTime localTime; + final String hostOsVersion; + final String locale; + final String? clientIde; + + LogItem({ + required this.eventName, + required this.sessionId, + this.flutterChannel, + required this.host, + this.flutterVersion, + required this.dartVersion, + required this.tool, + required this.localTime, + required this.hostOsVersion, + required this.locale, + required this.clientIde, + }); + + /// Serves a parser for each record in the log file. + /// + /// Using this method guarantees that we have parsed out + /// fields that are necessary for the [LogHandler.logFileStats] + /// method. + /// + /// If the returned value is null, that indicates a malformed + /// record which can be discarded during analysis. + /// + /// Example of what a record looks like: + /// ``` + /// { + /// "client_id": "ffcea97b-db5e-4c66-98c2-3942de4fac40", + /// "events": [ + /// { + /// "name": "hot_reload_time", + /// "params": { + /// "timeMs": 135 + /// } + /// } + /// ], + /// "user_properties": { + /// "session_id": { + /// "value": 1699385899950 + /// }, + /// "flutter_channel": { + /// "value": "ey-test-channel" + /// }, + /// "host": { + /// "value": "macOS" + /// }, + /// "flutter_version": { + /// "value": "Flutter 3.6.0-7.0.pre.47" + /// }, + /// "dart_version": { + /// "value": "Dart 2.19.0" + /// }, + /// "analytics_pkg_version": { + /// "value": "5.2.0" + /// }, + /// "tool": { + /// "value": "flutter-tool" + /// }, + /// "local_time": { + /// "value": "2023-11-07 15:09:03.025559 -0500" + /// }, + /// "host_os_version": { + /// "value": "Version 14.1 (Build 23B74)" + /// }, + /// "locale": { + /// "value": "en" + /// }, + /// "clientIde": { + /// "value": "VSCode" + /// } + /// } + /// } + /// ``` + static LogItem? fromRecord(Map<String, Object?> record) { + if (!record.containsKey('user_properties') || + !record.containsKey('events')) { + return null; + } + + // Parse out values from the top level key = 'events' and return + // a map for the one event in the value + final eventProp = + (record['events']! as List<Object?>).first as Map<String, Object?>; + final eventName = eventProp['name'] as String; + + // Parse the data out of the `user_properties` value + final userProps = record['user_properties'] as Map<String, Object?>; + + // Parse out the values from the top level key = 'user_properties` + final sessionId = + (userProps['session_id']! as Map<String, Object?>)['value'] as int?; + final flutterChannel = (userProps['flutter_channel']! + as Map<String, Object?>)['value'] as String?; + final host = + (userProps['host']! as Map<String, Object?>)['value'] as String?; + final flutterVersion = (userProps['flutter_version']! + as Map<String, Object?>)['value'] as String?; + final dartVersion = (userProps['dart_version']! + as Map<String, Object?>)['value'] as String?; + final tool = + (userProps['tool']! as Map<String, Object?>)['value'] as String?; + final localTimeString = + (userProps['local_time']! as Map<String, Object?>)['value'] as String?; + final hostOsVersion = (userProps['host_os_version']! + as Map<String, Object?>)['value'] as String?; + final locale = + (userProps['locale']! as Map<String, Object?>)['value'] as String?; + final clientIde = + (userProps['client_ide']! as Map<String, Object?>)['value'] as String?; + + // If any of the above values are null, return null since that + // indicates the record is malformed; note that `flutter_version`, + // `flutter_channel`, and `client_ide` are nullable fields in the log file + final values = <Object?>[ + // Values associated with the top level key = 'events' + eventName, + + // Values associated with the top level key = 'events' + sessionId, + host, + dartVersion, + tool, + localTimeString, + hostOsVersion, + locale, + ]; + for (final value in values) { + if (value == null) return null; + } + + // Parse the local time from the string extracted + final localTime = DateTime.parse(localTimeString!).toLocal(); + + return LogItem( + eventName: eventName, + sessionId: sessionId!, + flutterChannel: flutterChannel, + host: host!, + flutterVersion: flutterVersion, + dartVersion: dartVersion!, + tool: tool!, + localTime: localTime, + hostOsVersion: hostOsVersion!, + locale: locale!, + clientIde: clientIde, + ); + } +}
diff --git a/pkgs/unified_analytics/lib/src/survey_handler.dart b/pkgs/unified_analytics/lib/src/survey_handler.dart new file mode 100644 index 0000000..7461dfc --- /dev/null +++ b/pkgs/unified_analytics/lib/src/survey_handler.dart
@@ -0,0 +1,366 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; + +import 'package:clock/clock.dart'; +import 'package:file/file.dart'; +import 'package:http/http.dart' as http; + +import 'constants.dart'; +import 'enums.dart'; +import 'initializer.dart'; +import 'log_handler.dart'; + +class Condition { + /// How to query the log file. + /// + /// + /// Example: logFileStats.recordCount refers to the + /// total record count being returned by [LogFileStats]. + final String field; + + /// String representation of operator. + /// + /// + /// Allowed values: + /// - '>=' `greater than or equal to` + /// - '<=' `less than or equal to` + /// - '>' `greater than` + /// - '<' `less then` + /// - '==' `equals` + /// - '!=' `not equal` + final String operatorString; + + /// The value we will be comparing against using the [operatorString]. + final int value; + + /// One of the conditions that need to be valid for + /// a survey to be returned to the user. + /// + /// Example of raw json: + /// ``` + /// { + /// "field": "logFileStats.recordCount", + /// "operator": ">=", + /// "value": 1000 + /// } + /// ``` + Condition( + this.field, + this.operatorString, + this.value, + ); + + Condition.fromJson(Map<String, dynamic> json) + : field = json['field'] as String, + operatorString = json['operator'] as String, + value = json['value'] as int; + + Map<String, Object?> toMap() => <String, Object?>{ + 'field': field, + 'operator': operatorString, + 'value': value, + }; + + @override + String toString() => jsonEncode(toMap()); +} + +/// Data class for the persisted survey contents. +/// +/// [uniqueId] is the identifier for each survey, [timestamp] refers +/// to when the survey was added to the persisted file. +/// +/// The boolean [snoozed] is set to `true` if the survey has been dismissed +/// temporarily by the user. When set to `false` this indicates that the survey +/// has been dismissed permanently and will not be shown to the user again. +class PersistedSurvey { + final String uniqueId; + final bool snoozed; + final DateTime timestamp; + + PersistedSurvey({ + required this.uniqueId, + required this.snoozed, + required this.timestamp, + }); + + @override + String toString() => jsonEncode({ + 'uniqueId': uniqueId, + 'snoozed': snoozed, + 'timestamp': timestamp.toString(), + }); +} + +class Survey { + final String uniqueId; + final DateTime startDate; + final DateTime endDate; + final String description; + final int snoozeForMinutes; + final double samplingRate; + final List<DashTool> excludeDashToolList; + final List<Condition> conditionList; + final List<SurveyButton> buttonList; + + /// A data class that contains the relevant information for a given + /// survey parsed from the survey's metadata file. + const Survey({ + required this.uniqueId, + required this.startDate, + required this.endDate, + required this.description, + required this.snoozeForMinutes, + required this.samplingRate, + required this.excludeDashToolList, + required this.conditionList, + required this.buttonList, + }); + + /// Parse the contents of the json metadata file hosted externally. + Survey.fromJson(Map<String, dynamic> json) + : uniqueId = json['uniqueId'] as String, + startDate = DateTime.parse(json['startDate'] as String), + endDate = DateTime.parse(json['endDate'] as String), + description = json['description'] as String, + // Handle both string and integer fields + snoozeForMinutes = json['snoozeForMinutes'] is String + ? int.parse(json['snoozeForMinutes'] as String) + : json['snoozeForMinutes'] as int, + // Handle both string and double fields + samplingRate = json['samplingRate'] is String + ? double.parse(json['samplingRate'] as String) + : json['samplingRate'] as double, + excludeDashToolList = (json['excludeDashTools'] as List<dynamic>) + .map((e) => DashTool.fromLabel(e as String)) + .toList(), + conditionList = (json['conditions'] as List<dynamic>).map((e) { + return Condition.fromJson(e as Map<String, dynamic>); + }).toList(), + buttonList = (json['buttons'] as List<dynamic>).map((e) { + return SurveyButton.fromJson(e as Map<String, dynamic>); + }).toList(); + + @override + String toString() { + const encoder = JsonEncoder.withIndent(' '); + return encoder.convert({ + 'uniqueId': uniqueId, + 'startDate': startDate.toString(), + 'endDate': endDate.toString(), + 'description': description, + 'snoozeForMinutes': snoozeForMinutes, + 'samplingRate': samplingRate, + 'conditionList': conditionList.map((e) => e.toMap()).toList(), + 'buttonList': buttonList.map((e) => e.toMap()).toList(), + }); + } +} + +class SurveyButton { + final String buttonText; + final String action; + final bool promptRemainsVisible; + final String? url; + + SurveyButton({ + required this.buttonText, + required this.action, + required this.promptRemainsVisible, + this.url, + }); + + SurveyButton.fromJson(Map<String, dynamic> json) + : buttonText = json['buttonText'] as String, + action = json['action'] as String, + promptRemainsVisible = json['promptRemainsVisible'] as bool, + url = json['url'] as String?; + + Map<String, Object?> toMap() => <String, Object?>{ + 'buttonText': buttonText, + 'action': action, + 'promptRemainsVisible': promptRemainsVisible, + 'url': url, + }; +} + +class SurveyHandler { + final File dismissedSurveyFile; + + SurveyHandler({required this.dismissedSurveyFile}); + + /// Invoking this method will persist the survey's id in + /// the local file with either a snooze or permanently dismissed + /// indicator. + /// + /// In the snoozed state, the survey will be prompted again after + /// the survey's specified snooze period. + /// + /// Each entry for a survey will have the following format: + /// ``` + /// { + /// "survey-unique-id": { + /// "status": "snoozed", // status is either snoozed or dismissed + /// "timestamp": 1690219834859 + /// } + /// } + /// ``` + void dismiss(Survey survey, bool permanently) { + final contents = _parseJsonFile(); + + // Add the new data and write back out to the file + final status = permanently ? 'dismissed' : 'snoozed'; + contents[survey.uniqueId] = { + 'status': status, + 'timestamp': clock.now().millisecondsSinceEpoch, + }; + + dismissedSurveyFile.writeAsStringSync(jsonEncode(contents)); + } + + /// Retrieve a list of strings for each [Survey] persisted on disk. + /// + /// The survey may be in a snoozed or dismissed state based on user action. + Map<String, PersistedSurvey> fetchPersistedSurveys() { + final contents = _parseJsonFile(); + + // Initialize the list of persisted surveys and add to them + // as they are being parsed + final persistedSurveys = <String, PersistedSurvey>{}; + contents.forEach((key, value) { + value as Map<String, dynamic>; + + final uniqueId = key; + final snoozed = value['status'] == 'snoozed' ? true : false; + final timestamp = + DateTime.fromMillisecondsSinceEpoch(value['timestamp'] as int); + + persistedSurveys[uniqueId] = PersistedSurvey( + uniqueId: uniqueId, + snoozed: snoozed, + timestamp: timestamp, + ); + }); + + return persistedSurveys; + } + + /// Retrieves the survey metadata file from [kContextualSurveyUrl]. + Future<List<Survey>> fetchSurveyList() async { + final List<dynamic> body; + try { + final payload = await _fetchContents(); + body = jsonDecode(payload) as List<dynamic>; + // ignore: avoid_catches_without_on_clauses + } catch (err) { + return []; + } + + final surveyList = parseSurveysFromJson(body); + + return surveyList; + } + + /// Fetches the json in string form from the remote location. + Future<String> _fetchContents() async { + final uri = Uri.parse(kContextualSurveyUrl); + final response = await http.get(uri); + return response.body; + } + + /// Method to return a Map representation of the json persisted file. + Map<String, dynamic> _parseJsonFile() { + Map<String, dynamic> contents; + try { + contents = jsonDecode(dismissedSurveyFile.readAsStringSync()) + as Map<String, dynamic>; + } on FormatException { + createDismissedSurveyFile(dismissedSurveyFile: dismissedSurveyFile); + contents = {}; + } on FileSystemException { + createDismissedSurveyFile(dismissedSurveyFile: dismissedSurveyFile); + contents = {}; + } + + return contents; + } + + /// Function to ensure that each survey is still valid by + /// checking the [Survey.startDate] and [Survey.endDate] + /// against the current [clock] now date. + static bool checkSurveyDate(Survey survey) { + final now = clock.now(); + return survey.startDate.isBefore(now) && survey.endDate.isAfter(now); + } + + /// Function that takes in a json data structure that is in + /// the form of a list and returns a list of [Survey] items. + /// + /// This will also check the survey's dates to make sure it + /// has not expired. + static List<Survey> parseSurveysFromJson(List<dynamic> body) => body + .map((element) { + // Error handling to skip any surveys from the remote location + // that fail to parse + try { + return Survey.fromJson(element as Map<String, dynamic>); + // ignore: avoid_catching_errors + } on TypeError { + return null; + } on FormatException { + return null; + } on Exception { + return null; + } + }) + .whereType<Survey>() + .where(checkSurveyDate) + .toList(); +} + +class FakeSurveyHandler extends SurveyHandler { + final List<Survey> _fakeInitializedSurveys = []; + + /// Use this class in tests if you can provide the + /// list of [Survey] objects. + /// + /// Important: the surveys in the [initializedSurveys] list + /// will have their dates checked to ensure they are valid; it is + /// recommended to use `package:clock` to set a fixed time for testing. + FakeSurveyHandler.fromList({ + required super.dismissedSurveyFile, + required List<Survey> initializedSurveys, + }) { + // We must pass the surveys from the list to the + // `checkSurveyDate` function here and not for the + // `.fromString()` constructor because the `parseSurveysFromJson` + // method already checks their date + for (final survey in initializedSurveys) { + if (SurveyHandler.checkSurveyDate(survey)) { + _fakeInitializedSurveys.add(survey); + } + } + } + + /// Use this class in tests if you can provide raw + /// json strings to simulate a response from a remote server. + FakeSurveyHandler.fromString({ + required super.dismissedSurveyFile, + required String content, + }) { + final body = jsonDecode(content) as List<dynamic>; + for (final fakeSurvey in SurveyHandler.parseSurveysFromJson(body)) { + _fakeInitializedSurveys.add(fakeSurvey); + } + } + + @override + Future<List<Survey>> fetchSurveyList() => + Future<List<Survey>>.value(_fakeInitializedSurveys); + + @override + Future<String> _fetchContents() => throw UnimplementedError(); +}
diff --git a/pkgs/unified_analytics/lib/src/user_property.dart b/pkgs/unified_analytics/lib/src/user_property.dart new file mode 100644 index 0000000..f0e177d --- /dev/null +++ b/pkgs/unified_analytics/lib/src/user_property.dart
@@ -0,0 +1,162 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; + +import 'package:clock/clock.dart'; +import 'package:file/file.dart'; + +import 'constants.dart'; +import 'event.dart'; +import 'initializer.dart'; +import 'utils.dart'; + +class UserProperty { + final String? flutterChannel; + final String host; + final String? flutterVersion; + final String dartVersion; + final String tool; + final String hostOsVersion; + final String locale; + final String? clientIde; + final String? enabledFeatures; + + final File sessionFile; + + /// Contains instances of [Event.analyticsException] that were encountered + /// during a workflow and will be sent to GA4 for collection. + final Set<Event> errorSet = {}; + + int? _sessionId; + + /// This class is intended to capture all of the user's + /// metadata when the class gets initialized as well as collecting + /// session data to send in the json payload to Google Analytics. + UserProperty({ + required this.flutterChannel, + required this.host, + required this.flutterVersion, + required this.dartVersion, + required this.tool, + required this.hostOsVersion, + required this.locale, + required this.clientIde, + required this.enabledFeatures, + required this.sessionFile, + }); + + /// This will use the data parsed from the + /// session file in the dart-tool directory + /// to get the session id if the last ping was within + /// [kSessionDurationMinutes]. + /// + /// If time since last ping exceeds the duration, then the file + /// will be updated with a new session id and that will be returned. + /// + /// Note, the file will always be updated when calling this method + /// because the last ping variable will always need to be persisted. + int? getSessionId() { + _refreshSessionData(); + final now = clock.now(); + + // Convert the epoch time from the last ping into datetime and check if we + // are within the kSessionDurationMinutes. + final lastPingDateTime = sessionFile.lastModifiedSync(); + if (now.difference(lastPingDateTime).inMinutes > kSessionDurationMinutes) { + // Update the session file with the latest session id + _sessionId = now.millisecondsSinceEpoch; + writeSessionContents(sessionFile: sessionFile); + } else { + // Update the last modified timestamp with the current timestamp so that + // we can use it for the next _lastPing calculation + sessionFile.setLastModifiedSync(now); + } + + return _sessionId; + } + + /// This method will take the data in this class and convert it into + /// a Map that is suitable for the POST request schema. + /// + /// This will call the [UserProperty] object's [UserProperty.getSessionId] + /// method which will update the session file and get a new session id + /// if necessary. + /// + /// https://developers.google.com/analytics/devguides/collection/protocol/ga4/user-properties?client_type=gtag + Map<String, Map<String, Object?>> preparePayload() { + return <String, Map<String, Object?>>{ + for (final entry in _toMap().entries) + entry.key: <String, Object?>{'value': entry.value} + }; + } + + @override + String toString() { + return jsonEncode(_toMap()); + } + + /// This will go to the session file within the dart-tool + /// directory and fetch the latest data from the session file to update + /// the class's variables. If the session file is malformed, a new + /// session file will be recreated. + /// + /// This allows the session data in this class to always be up + /// to date incase another tool is also calling this package and + /// making updates to the session file. + void _refreshSessionData() { + /// Using a nested function here to reduce verbosity + void parseContents() { + final sessionFileContents = sessionFile.readAsStringSync(); + final sessionObj = + jsonDecode(sessionFileContents) as Map<String, Object?>; + _sessionId = sessionObj['session_id'] as int; + } + + try { + // Failing to parse the contents will result in the current timestamp + // being used as the session id and will get used to recreate the file + parseContents(); + } on FormatException catch (err) { + final now = createSessionFile(sessionFile: sessionFile); + + errorSet.add(Event.analyticsException( + workflow: 'UserProperty._refreshSessionData', + error: err.runtimeType.toString(), + description: 'message: ${err.message}\nsource: ${err.source}', + )); + + // Fallback to setting the session id as the current time + _sessionId = now.millisecondsSinceEpoch; + } on FileSystemException catch (err) { + final now = createSessionFile(sessionFile: sessionFile); + + errorSet.add(Event.analyticsException( + workflow: 'UserProperty._refreshSessionData', + error: err.runtimeType.toString(), + description: err.osError?.toString(), + )); + + // Fallback to setting the session id as the current time + _sessionId = now.millisecondsSinceEpoch; + } + } + + /// Convert the data stored in this class into a map while also + /// getting the latest session id using the [UserProperty] class. + Map<String, Object?> _toMap() => <String, Object?>{ + 'session_id': getSessionId(), + 'flutter_channel': flutterChannel, + 'host': host, + 'flutter_version': flutterVersion, + 'dart_version': dartVersion, + 'analytics_pkg_version': kPackageVersion, + 'tool': tool, + 'local_time': formatDateTime(clock.now()), + 'host_os_version': hostOsVersion, + 'locale': locale, + 'client_ide': clientIde, + 'enabled_features': enabledFeatures, + }; +}
diff --git a/pkgs/unified_analytics/lib/src/utils.dart b/pkgs/unified_analytics/lib/src/utils.dart new file mode 100644 index 0000000..41848a2 --- /dev/null +++ b/pkgs/unified_analytics/lib/src/utils.dart
@@ -0,0 +1,340 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; +import 'dart:io' as io; +import 'dart:math' show Random; + +import 'package:clock/clock.dart'; +import 'package:convert/convert.dart'; +import 'package:file/file.dart'; + +import 'enums.dart'; +import 'event.dart'; +import 'survey_handler.dart'; +import 'user_property.dart'; + +/// Get a string representation of the current date in the following format: +/// ```text +/// yyyy-MM-dd (2023-01-09) +/// ``` +String get dateStamp { + return FixedDateTimeFormatter('YYYY-MM-DD').encode(clock.now()); +} + +/// Reads in a directory and returns `true` if write permissions are enabled. +/// +/// Uses the [FileStat] method `modeString()` to return a string in the form +/// of `rwxrwxrwx` where the second character in the string indicates if write +/// is enabled with a `w` or disabled with `-`. +bool checkDirectoryForWritePermissions(Directory directory) { + if (!directory.existsSync()) return false; + + final fileStat = directory.statSync(); + return fileStat.modeString()[1] == 'w'; +} + +/// Format time as 'yyyy-MM-dd HH:mm:ss Z' where Z is the difference between the +/// timezone of t and UTC formatted according to RFC 822. +String formatDateTime(DateTime t) { + final sign = t.timeZoneOffset.isNegative ? '-' : '+'; + final tzOffset = t.timeZoneOffset.abs(); + final hoursOffset = tzOffset.inHours; + final minutesOffset = + tzOffset.inMinutes - (Duration.minutesPerHour * hoursOffset); + assert(hoursOffset < 24); + assert(minutesOffset < 60); + + String twoDigits(int n) => (n >= 10) ? '$n' : '0$n'; + return '$t $sign${twoDigits(hoursOffset)}${twoDigits(minutesOffset)}'; +} + +/// Construct the Map that will be converted to json for the +/// body of the request. +/// +/// Follows the following schema: +/// +/// ``` +/// { +/// "client_id": "46cc0ba6-f604-4fd9-aa2f-8a20beb24cd4", +/// "events": [{ "name": "testing", "params": { "time_ns": 345 } }], +/// "user_properties": { +/// "session_id": { "value": 1673466750423 }, +/// "flutter_channel": { "value": "ey-test-channel" }, +/// "host": { "value": "macos" }, +/// "flutter_version": { "value": "Flutter 3.6.0-7.0.pre.47" }, +/// "dart_version": { "value": "Dart 2.19.0" }, +/// "tool": { "value": "flutter-tools" }, +/// "local_time": { "value": "2023-01-11 14:53:31.471816 -0500" } +/// } +/// } +/// ``` +/// https://developers.google.com/analytics/devguides/collection/protocol/ga4/sending-events?client_type=gtag +Map<String, Object?> generateRequestBody({ + required String clientId, + required DashEvent eventName, + required Map<String, Object?> eventData, + required UserProperty userProperty, +}) => + <String, Object?>{ + 'client_id': clientId, + 'events': <Map<String, Object?>>[ + <String, Object?>{ + 'name': eventName.label, + 'params': eventData, + } + ], + 'user_properties': userProperty.preparePayload() + }; + +/// This will use environment variables to get the user's +/// home directory where all the directory will be created that will +/// contain all of the analytics files. +Directory? getHomeDirectory(FileSystem fs) { + String? home; + final envVars = io.Platform.environment; + + if (io.Platform.isMacOS) { + home = envVars['HOME']; + } else if (io.Platform.isLinux) { + home = envVars['HOME']; + } else if (io.Platform.isWindows) { + home = envVars['AppData']; + } + + if (home == null) return null; + + return fs.directory(home); +} + +/// Returns `true` if user has opted out of legacy analytics in +/// Dart or Flutter. +/// +/// Checks legacy opt-out status for the Flutter +/// and Dart in the following locations. +/// +/// Dart: `$HOME/.dart/dartdev.json` +/// ``` +/// { +/// "firstRun": false, +/// "enabled": false, <-- THIS USER HAS OPTED OUT +/// "disclosureShown": true, +/// "clientId": "52710e60-7c70-4335-b3a4-9d922630f12a" +/// } +/// ``` +/// +/// Flutter: `$HOME/.flutter` +/// ``` +/// { +/// "firstRun": false, +/// "clientId": "4c3a3d1e-e545-47e7-b4f8-10129f6ab169", +/// "enabled": false <-- THIS USER HAS OPTED OUT +/// } +/// ``` +/// +/// Devtools: `$HOME/.flutter-devtools/.devtools` +/// ``` +/// { +/// "analyticsEnabled": false, <-- THIS USER HAS OPTED OUT +/// "isFirstRun": false, +/// "lastReleaseNotesVersion": "2.31.0", +/// "2023-Q4": { +/// "surveyActionTaken": false, +/// "surveyShownCount": 0 +/// } +/// } +/// ``` +bool legacyOptOut({required Directory homeDirectory}) { + // List of Maps for each of the config file, `key` refers to the + // key in the json file that indicates if the user has been opted + // out or not + final legacyConfigFiles = [ + ( + tool: DashTool.dartTool, + file: homeDirectory.childDirectory('.dart').childFile('dartdev.json'), + key: 'enabled', + ), + ( + tool: DashTool.flutterTool, + file: homeDirectory.childFile('.flutter'), + key: 'enabled', + ), + ( + tool: DashTool.devtools, + file: homeDirectory + .childDirectory('.flutter-devtools') + .childFile('.devtools'), + key: 'analyticsEnabled', + ), + ]; + for (final legacyConfigObj in legacyConfigFiles) { + final legacyFile = legacyConfigObj.file; + final lookupKey = legacyConfigObj.key; + + if (legacyFile.existsSync()) { + try { + final legacyFileObj = + jsonDecode(legacyFile.readAsStringSync()) as Map<String, Object?>; + if (legacyFileObj.containsKey(lookupKey) && + legacyFileObj[lookupKey] == false) { + return true; + } + } on FormatException { + // In the case of an error when parsing the json file, return true + // which will result in the user being opted out of unified_analytics + // + // A corrupted file could mean they opted out previously but for some + // reason, the file was written incorrectly + return true; + } on FileSystemException { + return true; + } + } + } + + return false; +} + +/// Helper method that can be used to resolve the Dart SDK version for clients +/// of package:unified_analytics. +/// +/// Input [versionString] for this method should be the returned string from +/// [io.Platform.version]. +/// +/// For tools that don't already have a method for resolving the Dart +/// SDK version in semver notation, this helper can be used. This uses +/// the [io.Platform.version] to parse the semver. +/// +/// Example for stable version: +/// `3.3.0 (stable) (Tue Feb 13 10:25:19 2024 +0000) on "macos_arm64"` into +/// `3.3.0`. +/// +/// Example for non-stable version: +/// `2.1.0-dev.8.0.flutter-312ae32` into `2.1.0 (build 2.1.0-dev.8.0 312ae32)`. +String parseDartSDKVersion(String versionString) { + versionString = versionString.trim(); + final justVersion = versionString.split(' ')[0]; + + // For non-stable versions, this regex will include build information + return justVersion.replaceFirstMapped(RegExp(r'(\d+\.\d+\.\d+)(.+)'), + (Match match) { + final noFlutter = match[2]!.replaceAll('.flutter-', ' '); + return '${match[1]} (build ${match[1]}$noFlutter)'.trim(); + }); +} + +/// Will use two strings to produce a double for applying a sampling +/// rate for [Survey] to be returned to the user. +double sampleRate(String string1, String string2) => + ((string1.hashCode + string2.hashCode) % 101) / 100; + +/// Function to check if a given [Survey] can be shown again +/// by checking if it was snoozed or permanently dismissed. +/// +/// If the [Survey] doesn't exist in the persisted file, then it +/// will be shown to the user. +/// +/// If the [Survey] has been permanently dismissed, we will not +/// show it to the user. +/// +/// If the [Survey] has been snoozed, we will check the timestamp +/// that it was snoozed at with the current time from [clock] +/// and if the snooze period has elapsed, then we will show it to the user. +bool surveySnoozedOrDismissed( + Survey survey, + Map<String, PersistedSurvey> persistedSurveyMap, +) { + // If this survey hasn't been persisted yet, it is okay to pass + // to the user + if (!persistedSurveyMap.containsKey(survey.uniqueId)) return false; + + final persistedSurveyObj = persistedSurveyMap[survey.uniqueId]!; + + // If the survey has been dismissed permanently, we will not show the + // survey + if (!persistedSurveyObj.snoozed) return true; + + // Find how many minutes has elapsed from the timestamp and now + final minutesElapsed = + clock.now().difference(persistedSurveyObj.timestamp).inMinutes; + + return survey.snoozeForMinutes > minutesElapsed; +} + +/// Due to some limitations for GA4, this function can be used to +/// truncate fields that we may not care about truncating, such as +/// the host os details. +/// +/// [maxLength] represents the maximum length allowed for the string. +/// +/// Example: +/// "Linux 6.2.0-1015-azure #15~22.04.1-Ubuntu SMP Fri Oct 6 13:20:44 UTC 2023" +/// +/// The above string is what is returned by [io.Platform.operatingSystemVersion] +/// for certain machines running GitHub Actions, this function will truncate +/// that value down to the maximum length at 36 characters and return the below +/// +/// Return: +/// "Linux 6.2.0-1015-azure #15~22." +/// +/// This should only be used on fields that are okay to be truncated, this +/// should not be used for parameters on the [Event] constructors. +String truncateStringToLength(String str, int maxLength) { + if (maxLength <= 0) { + throw ArgumentError( + 'The length to truncate a string must be greater than 0'); + } + + if (maxLength > str.length) return str; + + return str.substring(0, maxLength); +} + +/// Writes the JSON string payload to the provided [sessionFile]. +/// +/// The `last_ping` key:value pair has been deprecated, it remains included +/// for backward compatibility. +void writeSessionContents({required File sessionFile}) { + final now = clock.now(); + sessionFile.writeAsStringSync('{"session_id": ${now.millisecondsSinceEpoch}, ' + '"last_ping": ${now.millisecondsSinceEpoch}}'); +} + +/// A UUID generator. +/// +/// This will generate unique IDs in the format: +/// +/// f47ac10b-58cc-4372-a567-0e02b2c3d479 +/// +/// The generated uuids are 128 bit numbers encoded in a specific string format. +/// For more information, see +/// [en.wikipedia.org/wiki/Universally_unique_identifier](http://en.wikipedia.org/wiki/Universally_unique_identifier). +/// +/// This class was taken from the previous `usage` package (https://github.com/dart-lang/usage/blob/master/lib/uuid/uuid.dart). +class Uuid { + final Random _random; + + Uuid([int? seed]) : _random = Random(seed); + + /// Generate a version 4 (random) uuid. This is a uuid scheme that only uses + /// random numbers as the source of the generated uuid. + String generateV4() { + // Generate xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx / 8-4-4-4-12. + 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)}'; + } + + 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/pkgs/unified_analytics/lib/testing.dart b/pkgs/unified_analytics/lib/testing.dart new file mode 100644 index 0000000..900212f --- /dev/null +++ b/pkgs/unified_analytics/lib/testing.dart
@@ -0,0 +1,5 @@ +// 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. + +export 'src/enums.dart';
diff --git a/pkgs/unified_analytics/lib/unified_analytics.dart b/pkgs/unified_analytics/lib/unified_analytics.dart new file mode 100644 index 0000000..7cc4562 --- /dev/null +++ b/pkgs/unified_analytics/lib/unified_analytics.dart
@@ -0,0 +1,11 @@ +// 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. + +export 'src/analytics.dart' show Analytics, FakeAnalytics, NoOpAnalytics; +export 'src/config_handler.dart' show ToolInfo; +export 'src/enums.dart' show DashTool; +export 'src/event.dart' show Event; +export 'src/log_handler.dart' show LogFileStats; +export 'src/survey_handler.dart' show Survey, SurveyButton, SurveyHandler; +export 'src/utils.dart' show parseDartSDKVersion;
diff --git a/pkgs/unified_analytics/pubspec.yaml b/pkgs/unified_analytics/pubspec.yaml new file mode 100644 index 0000000..172f5b2 --- /dev/null +++ b/pkgs/unified_analytics/pubspec.yaml
@@ -0,0 +1,25 @@ +name: unified_analytics +description: >- + A package for logging analytics for all Dart and Flutter related tooling + to Google Analytics. +# LINT.IfChange +# When updating this, keep the version consistent with the changelog and the +# value in lib/src/constants.dart. +version: 6.1.4 +# LINT.ThenChange(lib/src/constants.dart) +repository: https://github.com/dart-lang/tools/tree/main/pkgs/unified_analytics + +environment: + sdk: ^3.4.0 + +dependencies: + clock: ^1.1.1 + convert: ^3.1.1 + file: '>=6.1.4 <8.0.0' + http: '>=0.13.5 <2.0.0' + meta: ^1.9.0 + +dev_dependencies: + dart_flutter_team_lints: ^3.0.0 + test: ^1.16.6 + yaml: ^3.1.1
diff --git a/pkgs/unified_analytics/test/asserts_test.dart b/pkgs/unified_analytics/test/asserts_test.dart new file mode 100644 index 0000000..9230fc6 --- /dev/null +++ b/pkgs/unified_analytics/test/asserts_test.dart
@@ -0,0 +1,413 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:test/test.dart'; +import 'package:unified_analytics/src/asserts.dart'; + +void main() { + test('Failure if client_id top level key is missing', () { + final body = <String, Object?>{}; + + final expectedErrorMessage = 'client_id missing from top level keys'; + expect( + () => checkBody(body), + throwsA(predicate( + (AnalyticsException e) => e.message == expectedErrorMessage, + expectedErrorMessage))); + }); + + test('Failure if events top level key is missing', () { + final body = <String, Object?>{'client_id': 'xxxxxxx'}; + + final expectedErrorMessage = 'events missing from top level keys'; + expect( + () => checkBody(body), + throwsA(predicate( + (AnalyticsException e) => e.message == expectedErrorMessage, + expectedErrorMessage))); + }); + + test('Failure if user_properties top level key is missing', () { + final body = <String, Object?>{'client_id': 'xxxxxxx', 'events': []}; + + final expectedErrorMessage = 'user_properties missing from top level keys'; + expect( + () => checkBody(body), + throwsA(predicate( + (AnalyticsException e) => e.message == expectedErrorMessage, + expectedErrorMessage))); + }); + + test('Failure if more than 25 events found in events list', () { + final body = <String, Object?>{ + 'client_id': 'xxxxxxx', + 'events': <Map<String, Object?>>[], + 'user_properties': <String, Object?>{} + }; + + // Add more than the 25 allowed events + for (var i = 0; i < 30; i++) { + (body['events'] as List).add({'name': i}); + } + + final expectedErrorMessage = '25 is the max number of events'; + expect( + () => checkBody(body), + throwsA(predicate( + (AnalyticsException e) => e.message == expectedErrorMessage, + expectedErrorMessage))); + }); + + test('Failure when event name is greater than 40 chars', () { + final body = <String, Object?>{ + 'client_id': 'xxxxxxx', + 'events': <Map<String, Object?>>[ + { + 'name': + 'hot_reload_timehot_reload_timehot_reload_timehot_reload_time', + 'params': {'time_ms': 133, 'count': 1999000} + } + ], + 'user_properties': <String, Object?>{} + }; + + final expectedErrorMessage = 'Limit event names to 40 chars or less\n' + 'Event name: ' + '"hot_reload_timehot_reload_timehot_reload_timehot_reload_time"' + ' is too long'; + expect( + () => checkBody(body), + throwsA(predicate( + (AnalyticsException e) => e.message == expectedErrorMessage, + expectedErrorMessage))); + }); + + test('Failure when event name has invalid chars', () { + final body = <String, Object?>{ + 'client_id': 'xxxxxxx', + 'events': <Map<String, Object?>>[ + { + 'name': 'hot_reload_time!!', + 'params': {'time_ms': 133, 'count': 1999000} + } + ], + 'user_properties': <String, Object?>{} + }; + + final expectedErrorMessage = + 'Event name can only have alphanumeric chars and underscores\n' + 'Event name: "hot_reload_time!!" contains invalid characters'; + expect( + () => checkBody(body), + throwsA(predicate( + (AnalyticsException e) => e.message == expectedErrorMessage, + expectedErrorMessage))); + }); + + test('Failure when event name does not start with alphabetic char', () { + final body = <String, Object?>{ + 'client_id': 'xxxxxxx', + 'events': <Map<String, Object?>>[ + { + 'name': '2hot_reload_time', + 'params': {'time_ms': 133, 'count': 1999000} + } + ], + 'user_properties': <String, Object?>{} + }; + + final expectedErrorMessage = + 'Event name first char must be alphabetic char\n' + 'Event name: "2hot_reload_time" must begin with a valid character'; + expect( + () => checkBody(body), + throwsA(predicate( + (AnalyticsException e) => e.message == expectedErrorMessage, + expectedErrorMessage))); + }); + + test('Failure when an event has more than 25 event params', () { + final body = <String, Object?>{ + 'client_id': 'xxxxxxx', + 'events': <Map<String, Object?>>[ + { + 'name': 'hot_reload_time', + // 'params': {...} SUBBING THIS VALUE OUT 30 Maps + } + ], + 'user_properties': <String, Object?>{} + }; + + final params = <String, Object?>{}; + for (var i = 0; i < 30; i++) { + params['$i'] = i; + } + + // Add the params to the first event in the body + ((body['events'] as List).first as Map)['params'] = params; + + final expectedErrorMessage = 'Limit params for each event to less than 25\n' + 'Event: "hot_reload_time" has too many parameters'; + expect( + () => checkBody(body), + throwsA(predicate( + (AnalyticsException e) => e.message == expectedErrorMessage, + expectedErrorMessage))); + }); + + test('Failure when an value for event params is not a supported type (list)', + () { + final body = <String, Object?>{ + 'client_id': 'xxxxxxx', + 'events': <Map<String, Object?>>[ + { + 'name': 'hot_reload_time', + 'params': { + 'time_ms': 133, + // Lists and Maps are not supported + 'count': <int>[1999000], + } + } + ], + 'user_properties': <String, Object?>{} + }; + + final expectedErrorMessage = + 'Values for event params have to be String, int, double, or bool\n' + 'Value for "count" is not a valid type for event: "hot_reload_time"'; + expect( + () => checkBody(body), + throwsA(predicate( + (AnalyticsException e) => e.message == expectedErrorMessage, + expectedErrorMessage))); + }); + + test('Failure when an value for event params is not a supported type (map)', + () { + final body = <String, Object?>{ + 'client_id': 'xxxxxxx', + 'events': <Map<String, Object?>>[ + { + 'name': 'hot_reload_time', + 'params': { + 'time_ms': 133, + // Lists and Maps are not supported + 'count': <int, int>{5: 20}, + } + } + ], + 'user_properties': <String, Object?>{} + }; + + final expectedErrorMessage = + 'Values for event params have to be String, int, double, or bool\n' + 'Value for "count" is not a valid type for event: "hot_reload_time"'; + expect( + () => checkBody(body), + throwsA(predicate( + (AnalyticsException e) => e.message == expectedErrorMessage, + expectedErrorMessage))); + }); + + test('Failure when event param name is more than 40 chars', () { + final body = <String, Object?>{ + 'client_id': 'xxxxxxx', + 'events': <Map<String, Object?>>[ + { + 'name': 'hot_reload_time', + 'params': {'time_mstime_mstime_mstime_mstime_mstime_ms': 133} + } + ], + 'user_properties': <String, Object?>{} + }; + + final expectedErrorMessage = 'Limit event param names to 40 chars or less\n' + 'The key: "time_mstime_mstime_mstime_mstime_mstime_ms" ' + 'under the event: "hot_reload_time" is too long'; + expect( + () => checkBody(body), + throwsA(predicate( + (AnalyticsException e) => e.message == expectedErrorMessage, + expectedErrorMessage))); + }); + + test('Failure for event param name that has invalid chars', () { + final body = <String, Object?>{ + 'client_id': 'xxxxxxx', + 'events': <Map<String, Object?>>[ + { + 'name': 'hot_reload_time', + 'params': {'time_ns!': 133} + } + ], + 'user_properties': <String, Object?>{} + }; + + final expectedErrorMessage = + 'Event param name can only have alphanumeric chars and underscores\n' + 'The key: "time_ns!" under the event: "hot_reload_time" contains ' + 'invalid characters'; + + expect( + () => checkBody(body), + throwsA(predicate( + (AnalyticsException e) => e.message == expectedErrorMessage, + expectedErrorMessage))); + }); + + test( + 'Failure for event param name that does not start with an alphabetic char', + () { + final body = <String, Object?>{ + 'client_id': 'xxxxxxx', + 'events': <Map<String, Object?>>[ + { + 'name': 'hot_reload_time', + 'params': {'22time_ns': 133} + } + ], + 'user_properties': <String, Object?>{} + }; + + final expectedErrorMessage = + 'Event param name first char must be alphabetic char\n' + 'The key: "22time_ns" under the event: "hot_reload_time" must begin ' + 'in a valid character'; + expect( + () => checkBody(body), + throwsA(predicate( + (AnalyticsException e) => e.message == expectedErrorMessage, + expectedErrorMessage))); + }, + ); + + test('Failure for event param values that are greater than 100 chars', () { + final body = <String, Object?>{ + 'client_id': 'xxxxxxx', + 'events': <Map<String, Object?>>[ + { + 'name': 'hot_reload_time', + 'params': { + 'time_ns': 'dsfjlksdjfajlfdsfjlks' + 'djfajlfdsfjlksdjfajlfdsfjlksdjfaj' + 'lfdsfjlksdjfajlfdsfjlksdjfajlfdsf' + 'jlksdjfajlfdsfjlksdjfajlf' + } + } + ], + 'user_properties': <String, Object?>{} + }; + + final expectedErrorMessage = + 'Limit characters in event param value to 100 chars or less\n' + 'Value for "time_ns" is too long, value="' + 'dsfjlksdjfajlfdsfjlks' + 'djfajlfdsfjlksdjfajlfdsfjlksdjfaj' + 'lfdsfjlksdjfajlfdsfjlksdjfajlfdsf' + 'jlksdjfajlfdsfjlksdjfajlf"'; + expect( + () => checkBody(body), + throwsA(predicate( + (AnalyticsException e) => e.message == expectedErrorMessage, + expectedErrorMessage))); + }); + + test('Failure when body has more than 25 user properties', () { + final body = <String, Object?>{ + 'client_id': 'xxxxxxx', + 'events': <Map<String, Object?>>[ + { + 'name': 'hot_reload_time', + 'params': {'time_ns': 123} + } + ], + 'user_properties': <String, Object?>{} + }; + + for (var i = 0; i < 30; i++) { + (body['user_properties']! as Map<String, Object?>)['$i'] = i; + } + + final expectedErrorMessage = 'Limit user properties to 25 or less'; + expect( + () => checkBody(body), + throwsA(predicate( + (AnalyticsException e) => e.message == expectedErrorMessage, + expectedErrorMessage))); + }); + + test('Failure when user properties names are greater than 24 chars', () { + final body = <String, Object?>{ + 'client_id': 'xxxxxxx', + 'events': <Map<String, Object?>>[ + { + 'name': 'hot_reload_time', + 'params': {'time_ns': 123} + } + ], + 'user_properties': <String, Object?>{ + 'testtesttesttesttesttesttest': <String, Object?>{}, // TOO LONG + } + }; + + final expectedErrorMessage = + 'Limit user property names to 24 chars or less\n' + 'The user property key: "testtesttesttesttesttesttest" is too long'; + expect( + () => checkBody(body), + throwsA(predicate( + (AnalyticsException e) => e.message == expectedErrorMessage, + expectedErrorMessage))); + }); + + test('Failure when user properties values are greater than 36 chars', () { + final body = <String, Object?>{ + 'client_id': 'xxxxxxx', + 'events': <Map<String, Object?>>[ + { + 'name': 'hot_reload_time', + 'params': {'time_ns': 123} + } + ], + 'user_properties': <String, Object?>{ + 'test': <String, Object?>{ + 'value': 'testtesttesttesttesttesttesttesttesttest' // TOO LONG + }, + } + }; + + final expectedErrorMessage = + 'Limit user property values to 36 chars or less\n' + 'For the user property key "test", the value ' + '"testtesttesttesttesttesttesttesttesttest" is too long'; + expect( + () => checkBody(body), + throwsA(predicate( + (AnalyticsException e) => e.message == expectedErrorMessage, + expectedErrorMessage))); + }); + + test('Successful body passes all asserts', () { + final body = <String, Object?>{ + 'client_id': '46cc0ba6-f604-4fd9-aa2f-8a20beb24cd4', + 'events': [ + { + 'name': 'testing', + 'params': {'time_ns': 345} + } + ], + 'user_properties': { + 'session_id': {'value': 1673466750423}, + 'flutter_channel': {'value': 'ey-test-channel'}, + 'host': {'value': 'macos'}, + 'flutter_version': {'value': 'Flutter 3.6.0-7.0.pre.47'}, + 'dart_version': {'value': 'Dart 2.19.0'}, + 'tool': {'value': 'flutter-tools'}, + 'local_time': {'value': '2023-01-11 14:53:31.471816 -0500'} + } + }; + + expect(() => checkBody(body), returnsNormally); + }); +}
diff --git a/pkgs/unified_analytics/test/error_handler_test.dart b/pkgs/unified_analytics/test/error_handler_test.dart new file mode 100644 index 0000000..39b2df8 --- /dev/null +++ b/pkgs/unified_analytics/test/error_handler_test.dart
@@ -0,0 +1,346 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:io' as io; + +import 'package:file/file.dart'; +import 'package:file/memory.dart'; +import 'package:test/test.dart'; + +import 'package:unified_analytics/src/constants.dart'; +import 'package:unified_analytics/src/enums.dart'; +import 'package:unified_analytics/unified_analytics.dart'; + +void main() { + late MemoryFileSystem fs; + late Directory home; + late FakeAnalytics initializationAnalytics; + late FakeAnalytics analytics; + late File sessionFile; + late File logFile; + + const homeDirName = 'home'; + const initialTool = DashTool.flutterTool; + const toolsMessageVersion = 1; + const toolsMessage = 'toolsMessage'; + const flutterChannel = 'flutterChannel'; + const flutterVersion = 'flutterVersion'; + const dartVersion = 'dartVersion'; + const platform = DevicePlatform.macos; + const clientIde = 'VSCode'; + + final testEvent = Event.codeSizeAnalysis(platform: 'platform'); + + setUp(() { + // Setup the filesystem with the home directory + final fsStyle = + io.Platform.isWindows ? FileSystemStyle.windows : FileSystemStyle.posix; + fs = MemoryFileSystem.test(style: fsStyle); + home = fs.directory(homeDirName); + + // This is the first analytics instance that will be used to demonstrate + // that events will not be sent with the first run of analytics + initializationAnalytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + ); + expect(initializationAnalytics.shouldShowMessage, true); + initializationAnalytics.clientShowedMessage(); + expect(initializationAnalytics.shouldShowMessage, false); + + // The main analytics instance, other instances can be spawned within tests + // to test how to instances running together work + // + // This instance should have the same parameters as the one above for + // [initializationAnalytics] + analytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + clientIde: clientIde, + ); + analytics.clientShowedMessage(); + + // The files that should have been generated that will be used for tests + sessionFile = + home.childDirectory(kDartToolDirectoryName).childFile(kSessionFileName); + logFile = + home.childDirectory(kDartToolDirectoryName).childFile(kLogFileName); + }); + + group('Session handler:', () { + test('no error when opted out already and opting in', () async { + // When we opt out from an analytics instance, we clear the contents of + // session file, as required by the privacy document. When creating a + // second instance of [Analytics], it should not detect that the file is + // empty and recreate it, it should remain opted out and no error event + // should have been sent + await analytics.setTelemetry(false); + expect(analytics.telemetryEnabled, false); + expect(sessionFile.readAsStringSync(), isEmpty); + + final secondAnalytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + clientIde: clientIde, + ); + expect(sessionFile.readAsStringSync(), isEmpty); + expect(secondAnalytics.telemetryEnabled, false); + + expect( + analytics.sentEvents.where( + (element) => element.eventName == DashEvent.analyticsException), + isEmpty, + ); + expect( + secondAnalytics.sentEvents.where( + (element) => element.eventName == DashEvent.analyticsException), + isEmpty, + ); + + await secondAnalytics.setTelemetry(true); + expect(sessionFile.readAsStringSync(), isNotEmpty, + reason: 'Toggling telemetry should bring back the session data'); + }); + test('only sends one event for FormatException', () { + // Begin with the session file empty, it should recreate the file + // and send an error event + sessionFile.writeAsStringSync(''); + expect(sessionFile.readAsStringSync(), isEmpty); + analytics.send(testEvent); + expect(sessionFile.readAsStringSync(), isNotEmpty); + + analytics.sendPendingErrorEvents(); + expect( + analytics.sentEvents.where( + (element) => element.eventName == DashEvent.analyticsException), + hasLength(1)); + + // Making the file empty again and sending an event should not send + // an additional event + sessionFile.writeAsStringSync(''); + expect(sessionFile.readAsStringSync(), isEmpty); + analytics.send(testEvent); + expect(sessionFile.readAsStringSync(), isNotEmpty); + + expect( + analytics.sentEvents.where( + (element) => element.eventName == DashEvent.analyticsException), + hasLength(1), + reason: 'We should not have added a new error event'); + }); + + test('only sends one event for FileSystemException', () { + // Deleting the session file should cause the file system exception and + // sending a new event should log the error the first time and recreate + // the file. If we delete the file again and attempt to send an event, + // the session file should get recreated without sending a second error. + sessionFile.deleteSync(); + expect(sessionFile.existsSync(), isFalse); + analytics.send(testEvent); + + analytics.sendPendingErrorEvents(); + expect( + analytics.sentEvents.where( + (element) => element.eventName == DashEvent.analyticsException), + hasLength(1), + ); + expect(sessionFile.existsSync(), isTrue); + expect(sessionFile.readAsStringSync(), isNotEmpty); + + // Remove the file again and send an event + sessionFile.deleteSync(); + expect(sessionFile.existsSync(), isFalse); + analytics.send(testEvent); + + expect( + analytics.sentEvents.where( + (element) => element.eventName == DashEvent.analyticsException), + hasLength(1), + reason: 'Only the first error event should exist', + ); + expect(sessionFile.existsSync(), isTrue); + expect(sessionFile.readAsStringSync(), isNotEmpty); + }); + + test('sends two unique errors', () { + // Begin with the session file empty, it should recreate the file + // and send an error event + sessionFile.writeAsStringSync(''); + expect(sessionFile.readAsStringSync(), isEmpty); + analytics.send(testEvent); + expect(sessionFile.readAsStringSync(), isNotEmpty); + + analytics.sendPendingErrorEvents(); + expect( + analytics.sentEvents.where( + (element) => element.eventName == DashEvent.analyticsException), + hasLength(1)); + + // Deleting the file now before sending an additional event should + // cause a different test error + sessionFile.deleteSync(); + expect(sessionFile.existsSync(), isFalse); + + analytics.send(testEvent); + expect(sessionFile.readAsStringSync(), isNotEmpty); + analytics.sendPendingErrorEvents(); + expect( + analytics.sentEvents.where( + (element) => element.eventName == DashEvent.analyticsException), + hasLength(2)); + expect(analytics.sentEvents, hasLength(4)); + + sessionFile.deleteSync(); + expect(sessionFile.existsSync(), isFalse); + + analytics.send(testEvent); + expect(sessionFile.readAsStringSync(), isNotEmpty); + expect( + analytics.sentEvents.where( + (element) => element.eventName == DashEvent.analyticsException), + hasLength(2)); + }); + }); + + group('Log handler:', () { + test('only sends one event for FormatException', () { + expect(logFile.existsSync(), isTrue); + + // Write invalid lines to the log file to have a FormatException + // thrown when trying to parse the log file + logFile.writeAsStringSync(''' +{{} +{{} +'''); + + // Send one event so that the logFileStats method returns a valid value + analytics.send(testEvent); + expect(analytics.sentEvents, hasLength(1)); + expect(logFile.readAsLinesSync(), hasLength(3)); + analytics.sendPendingErrorEvents(); + expect( + analytics.sentEvents.where( + (element) => element.eventName == DashEvent.analyticsException), + isEmpty, + ); + + // This call below will cause a FormatException while parsing the log file + final logFileStats = analytics.logFileStats(); + expect(logFileStats, isNotNull); + expect(logFileStats!.recordCount, 1, + reason: 'The error event is not counted'); + analytics.sendPendingErrorEvents(); + expect( + analytics.sentEvents.where( + (element) => element.eventName == DashEvent.analyticsException), + hasLength(1), + ); + expect(logFile.readAsLinesSync(), hasLength(4)); + }); + + test('only sends one event for TypeError', () { + expect(logFile.existsSync(), isTrue); + // Write valid json but have one of the types wrong for + // the keys so that we throw a TypeError while casting the values + // + // In the json below, we have made the session id value a string when + // it should be an integer + logFile.writeAsStringSync(''' +{"client_id":"fcd6c0d5-6582-4c36-b09e-3ecedee9145c","events":[{"name":"command_usage_values","params":{"workflow":"doctor","commandHasTerminal":true}}],"user_properties":{"session_id":{"value":"this should be a string"},"flutter_channel":{"value":"master"},"host":{"value":"macOS"},"flutter_version":{"value":"3.20.0-2.0.pre.9"},"dart_version":{"value":"3.4.0 (build 3.4.0-99.0.dev)"},"analytics_pkg_version":{"value":"5.8.1"},"tool":{"value":"flutter-tool"},"local_time":{"value":"2024-02-07 15:46:19.920784 -0500"},"host_os_version":{"value":"Version 14.3 (Build 23D56)"},"locale":{"value":"en"},"client_ide":{"value":null},"enabled_features":{"value":"enable-native-assets"}}} +'''); + expect(logFile.readAsLinesSync(), hasLength(1)); + + // Send the test event so that the LogFileStats object is not null + analytics.send(testEvent); + + final logFileStats = analytics.logFileStats(); + analytics.sendPendingErrorEvents(); + expect( + analytics.sentEvents.where( + (element) => element.eventName == DashEvent.analyticsException), + hasLength(1), + ); + expect(logFileStats, isNotNull); + expect(logFileStats!.recordCount, 1); + }); + + test('sends two unique errors', () { + expect(logFile.existsSync(), isTrue); + + // Write invalid lines to the log file to have a FormatException + // thrown when trying to parse the log file + logFile.writeAsStringSync(''' +{{} +{{} +'''); + + // Send one event so that the logFileStats method returns a valid value + analytics.send(testEvent); + expect(analytics.sentEvents, hasLength(1)); + expect(logFile.readAsLinesSync(), hasLength(3)); + analytics.sendPendingErrorEvents(); + expect( + analytics.sentEvents.where( + (element) => element.eventName == DashEvent.analyticsException), + isEmpty, + ); + + // This will cause the first error + analytics.logFileStats(); + analytics.sendPendingErrorEvents(); + expect( + analytics.sentEvents.where( + (element) => element.eventName == DashEvent.analyticsException), + hasLength(1), + ); + + // Overwrite the contents of the log file now to include something that + // will cause a TypeError by changing the expected value for session id + // from integer to a string + logFile.writeAsStringSync(''' +{"client_id":"fcd6c0d5-6582-4c36-b09e-3ecedee9145c","events":[{"name":"command_usage_values","params":{"workflow":"doctor","commandHasTerminal":true}}],"user_properties":{"session_id":{"value":"this should be a string"},"flutter_channel":{"value":"master"},"host":{"value":"macOS"},"flutter_version":{"value":"3.20.0-2.0.pre.9"},"dart_version":{"value":"3.4.0 (build 3.4.0-99.0.dev)"},"analytics_pkg_version":{"value":"5.8.1"},"tool":{"value":"flutter-tool"},"local_time":{"value":"2024-02-07 15:46:19.920784 -0500"},"host_os_version":{"value":"Version 14.3 (Build 23D56)"},"locale":{"value":"en"},"client_ide":{"value":null},"enabled_features":{"value":"enable-native-assets"}}} +'''); + expect(logFile.readAsLinesSync(), hasLength(1)); + + // This will cause the second error + analytics.logFileStats(); + analytics.sendPendingErrorEvents(); + expect( + analytics.sentEvents.where( + (element) => element.eventName == DashEvent.analyticsException), + hasLength(2), + ); + + // Attempting to cause the same error won't send another error event + analytics.logFileStats(); + analytics.sendPendingErrorEvents(); + expect( + analytics.sentEvents.where( + (element) => element.eventName == DashEvent.analyticsException), + hasLength(2), + ); + }); + }); +}
diff --git a/pkgs/unified_analytics/test/event_test.dart b/pkgs/unified_analytics/test/event_test.dart new file mode 100644 index 0000000..1e9344f --- /dev/null +++ b/pkgs/unified_analytics/test/event_test.dart
@@ -0,0 +1,702 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:mirrors'; + +import 'package:test/test.dart'; +import 'package:unified_analytics/src/enums.dart'; +import 'package:unified_analytics/unified_analytics.dart'; + +void main() { + test('Event.analyticsCollectionEnabled constructed', () { + Event generateEvent() => Event.analyticsCollectionEnabled(status: false); + + final constructedEvent = generateEvent(); + + expect(generateEvent, returnsNormally); + expect(constructedEvent.eventName, DashEvent.analyticsCollectionEnabled); + expect(constructedEvent.eventData['status'], false); + expect(constructedEvent.eventData.length, 1); + }); + + test('Event.clientNotification constructed', () { + Event generateEvent() => Event.clientNotification( + duration: 'duration', + latency: 'latency', + method: 'method', + ); + + final constructedEvent = generateEvent(); + + expect(generateEvent, returnsNormally); + expect(constructedEvent.eventName, DashEvent.clientNotification); + expect(constructedEvent.eventData['duration'], 'duration'); + expect(constructedEvent.eventData['latency'], 'latency'); + expect(constructedEvent.eventData['method'], 'method'); + expect(constructedEvent.eventData.length, 3); + }); + + test('Event.clientRequest constructed', () { + Event generateEvent() => Event.clientRequest( + duration: 'duration', + latency: 'latency', + method: 'method', + added: 'added', + excluded: 'excluded', + files: 'files', + included: 'included', + openWorkspacePaths: 'openWorkspacePaths', + removed: 'removed', + ); + + final constructedEvent = generateEvent(); + + expect(generateEvent, returnsNormally); + expect(constructedEvent.eventName, DashEvent.clientRequest); + expect(constructedEvent.eventData['duration'], 'duration'); + expect(constructedEvent.eventData['latency'], 'latency'); + expect(constructedEvent.eventData['method'], 'method'); + expect(constructedEvent.eventData['added'], 'added'); + expect(constructedEvent.eventData['excluded'], 'excluded'); + expect(constructedEvent.eventData['files'], 'files'); + expect(constructedEvent.eventData['included'], 'included'); + expect( + constructedEvent.eventData['openWorkspacePaths'], 'openWorkspacePaths'); + expect(constructedEvent.eventData['removed'], 'removed'); + expect(constructedEvent.eventData.length, 9); + }); + + test('Event.commandExecuted constructed', () { + Event generateEvent() => Event.commandExecuted( + count: 5, + name: 'name', + ); + + final constructedEvent = generateEvent(); + + expect(generateEvent, returnsNormally); + expect(constructedEvent.eventName, DashEvent.commandExecuted); + expect(constructedEvent.eventData['count'], 5); + expect(constructedEvent.eventData['name'], 'name'); + expect(constructedEvent.eventData.length, 2); + }); + + test('Event.contextStructure constructed', () { + Event generateEvent() => Event.contextStructure( + contextsFromBothFiles: 1, + contextsFromOptionsFiles: 2, + contextsFromPackagesFiles: 3, + contextsWithoutFiles: 4, + immediateFileCount: 5, + immediateFileLineCount: 6, + numberOfContexts: 7, + transitiveFileCount: 8, + transitiveFileLineCount: 9, + transitiveFileUniqueCount: 10, + transitiveFileUniqueLineCount: 11, + ); + + final constructedEvent = generateEvent(); + + expect(generateEvent, returnsNormally); + expect(constructedEvent.eventName, DashEvent.contextStructure); + expect(constructedEvent.eventData['contextsFromBothFiles'], 1); + expect(constructedEvent.eventData['contextsFromOptionsFiles'], 2); + expect(constructedEvent.eventData['contextsFromPackagesFiles'], 3); + expect(constructedEvent.eventData['contextsWithoutFiles'], 4); + expect(constructedEvent.eventData['immediateFileCount'], 5); + expect(constructedEvent.eventData['immediateFileLineCount'], 6); + expect(constructedEvent.eventData['numberOfContexts'], 7); + expect(constructedEvent.eventData['transitiveFileCount'], 8); + expect(constructedEvent.eventData['transitiveFileLineCount'], 9); + expect(constructedEvent.eventData['transitiveFileUniqueCount'], 10); + expect(constructedEvent.eventData['transitiveFileUniqueLineCount'], 11); + expect(constructedEvent.eventData.length, 11); + }); + + test('Event.dartCliCommandExecuted constructed', () { + Event generateEvent() => Event.dartCliCommandExecuted( + name: 'name', + enabledExperiments: 'enabledExperiments', + exitCode: 0, + ); + + final constructedEvent = generateEvent(); + + expect(generateEvent, returnsNormally); + expect(constructedEvent.eventName, DashEvent.dartCliCommandExecuted); + expect(constructedEvent.eventData['name'], 'name'); + expect( + constructedEvent.eventData['enabledExperiments'], 'enabledExperiments'); + expect(constructedEvent.eventData['exitCode'], 0); + expect(constructedEvent.eventData.length, 3); + }); + + test('Event.doctorValidatorResult constructed', () { + Event generateEvent() => Event.doctorValidatorResult( + validatorName: 'validatorName', + result: 'success', + partOfGroupedValidator: false, + doctorInvocationId: 123, + statusInfo: 'statusInfo', + ); + + final constructedEvent = generateEvent(); + + expect(generateEvent, returnsNormally); + expect(constructedEvent.eventName, DashEvent.doctorValidatorResult); + expect(constructedEvent.eventData['validatorName'], 'validatorName'); + expect(constructedEvent.eventData['result'], 'success'); + expect(constructedEvent.eventData['partOfGroupedValidator'], false); + expect(constructedEvent.eventData['doctorInvocationId'], 123); + expect(constructedEvent.eventData['statusInfo'], 'statusInfo'); + expect(constructedEvent.eventData.length, 5); + }); + + test('Event.hotReloadTime constructed', () { + Event generateEvent() => Event.hotReloadTime(timeMs: 500); + + final constructedEvent = generateEvent(); + + expect(generateEvent, returnsNormally); + expect(constructedEvent.eventName, DashEvent.hotReloadTime); + expect(constructedEvent.eventData['timeMs'], 500); + expect(constructedEvent.eventData.length, 1); + }); + + test('Event.lintUsageCount constructed', () { + Event generateEvent() => Event.lintUsageCount( + count: 5, + name: 'name', + ); + + final constructedEvent = generateEvent(); + + expect(generateEvent, returnsNormally); + expect(constructedEvent.eventName, DashEvent.lintUsageCount); + expect(constructedEvent.eventData['count'], 5); + expect(constructedEvent.eventData['name'], 'name'); + expect(constructedEvent.eventData.length, 2); + }); + + test('Event.memoryInfo constructed', () { + Event generateEvent() => Event.memoryInfo( + rss: 4, + periodSec: 5, + mbPerSec: 5.55, + ); + + final constructedEvent = generateEvent(); + + expect(generateEvent, returnsNormally); + expect(constructedEvent.eventName, DashEvent.memoryInfo); + expect(constructedEvent.eventData['rss'], 4); + expect(constructedEvent.eventData['periodSec'], 5); + expect(constructedEvent.eventData['mbPerSec'], 5.55); + expect(constructedEvent.eventData.length, 3); + }); + + test('Event.pluginRequest constructed', () { + Event generateEvent() => Event.pluginRequest( + duration: 'duration', + method: 'method', + pluginId: 'pluginId', + ); + + final constructedEvent = generateEvent(); + + expect(generateEvent, returnsNormally); + expect(constructedEvent.eventName, DashEvent.pluginRequest); + expect(constructedEvent.eventData['duration'], 'duration'); + expect(constructedEvent.eventData['method'], 'method'); + expect(constructedEvent.eventData['pluginId'], 'pluginId'); + expect(constructedEvent.eventData.length, 3); + }); + + test('Event.pluginUse constructed', () { + Event generateEvent() => Event.pluginUse( + count: 5, + enabled: 'enabled', + pluginId: 'pluginId', + ); + + final constructedEvent = generateEvent(); + + expect(generateEvent, returnsNormally); + expect(constructedEvent.eventName, DashEvent.pluginUse); + expect(constructedEvent.eventData['count'], 5); + expect(constructedEvent.eventData['enabled'], 'enabled'); + expect(constructedEvent.eventData['pluginId'], 'pluginId'); + expect(constructedEvent.eventData.length, 3); + }); + + test('Event.pubGet constructed', () { + Event generateEvent() => Event.pubGet( + packageName: 'packageName', + version: 'version', + dependencyType: 'dependencyType', + ); + + final constructedEvent = generateEvent(); + + expect(generateEvent, returnsNormally); + expect(constructedEvent.eventName, DashEvent.pubGet); + expect(constructedEvent.eventData['packageName'], 'packageName'); + expect(constructedEvent.eventData['version'], 'version'); + expect(constructedEvent.eventData['dependencyType'], 'dependencyType'); + expect(constructedEvent.eventData.length, 3); + }); + + test('Event.serverSession constructed', () { + Event generateEvent() => Event.serverSession( + clientId: 'clientId', + clientVersion: 'clientVersion', + duration: 5, + flags: 'flags', + parameters: 'parameters', + ); + + final constructedEvent = generateEvent(); + + expect(generateEvent, returnsNormally); + expect(constructedEvent.eventName, DashEvent.serverSession); + expect(constructedEvent.eventData['clientId'], 'clientId'); + expect(constructedEvent.eventData['clientVersion'], 'clientVersion'); + expect(constructedEvent.eventData['duration'], 5); + expect(constructedEvent.eventData['flags'], 'flags'); + expect(constructedEvent.eventData['parameters'], 'parameters'); + expect(constructedEvent.eventData.length, 5); + }); + + test('Event.severityAdjustment constructed', () { + Event generateEvent() => Event.severityAdjustment( + diagnostic: 'diagnostic', + adjustments: 'adjustments', + ); + + final constructedEvent = generateEvent(); + + expect(generateEvent, returnsNormally); + expect(constructedEvent.eventName, DashEvent.severityAdjustment); + expect(constructedEvent.eventData['diagnostic'], 'diagnostic'); + expect(constructedEvent.eventData['adjustments'], 'adjustments'); + expect(constructedEvent.eventData.length, 2); + }); + + test('Event.surveyAction constructed', () { + Event generateEvent() => Event.surveyAction( + surveyId: 'surveyId', + status: 'status', + ); + + final constructedEvent = generateEvent(); + + expect(generateEvent, returnsNormally); + expect(constructedEvent.eventName, DashEvent.surveyAction); + expect(constructedEvent.eventData['surveyId'], 'surveyId'); + expect(constructedEvent.eventData['status'], 'status'); + expect(constructedEvent.eventData.length, 2); + }); + + test('Event.surveyShown constructed', () { + Event generateEvent() => Event.surveyShown(surveyId: 'surveyId'); + + final constructedEvent = generateEvent(); + + expect(generateEvent, returnsNormally); + expect(constructedEvent.eventName, DashEvent.surveyShown); + expect(constructedEvent.eventData['surveyId'], 'surveyId'); + expect(constructedEvent.eventData.length, 1); + }); + + test('Event.flutterBuildInfo constructed', () { + Event generateEvent() => Event.flutterBuildInfo( + label: 'label', + buildType: 'buildType', + command: 'command', + settings: 'settings', + error: 'error', + ); + + final constructedEvent = generateEvent(); + + expect(generateEvent, returnsNormally); + expect(constructedEvent.eventName, DashEvent.flutterBuildInfo); + expect(constructedEvent.eventData['label'], 'label'); + expect(constructedEvent.eventData['buildType'], 'buildType'); + expect(constructedEvent.eventData['command'], 'command'); + expect(constructedEvent.eventData['settings'], 'settings'); + expect(constructedEvent.eventData['error'], 'error'); + expect(constructedEvent.eventData.length, 5); + }); + + test('Event.hotRunnerInfo constructed', () { + Event generateEvent() => Event.hotRunnerInfo( + label: 'label', + targetPlatform: 'targetPlatform', + sdkName: 'sdkName', + emulator: false, + fullRestart: true, + reason: 'reason', + finalLibraryCount: 5, + syncedLibraryCount: 6, + syncedClassesCount: 7, + syncedProceduresCount: 8, + syncedBytes: 9, + invalidatedSourcesCount: 10, + transferTimeInMs: 11, + overallTimeInMs: 12, + compileTimeInMs: 13, + findInvalidatedTimeInMs: 14, + scannedSourcesCount: 15, + reassembleTimeInMs: 16, + reloadVMTimeInMs: 17, + ); + + final constructedEvent = generateEvent(); + + expect(generateEvent, returnsNormally); + expect(constructedEvent.eventName, DashEvent.hotRunnerInfo); + expect(constructedEvent.eventData['label'], 'label'); + expect(constructedEvent.eventData['targetPlatform'], 'targetPlatform'); + expect(constructedEvent.eventData['sdkName'], 'sdkName'); + expect(constructedEvent.eventData['emulator'], false); + expect(constructedEvent.eventData['fullRestart'], true); + expect(constructedEvent.eventData['reason'], 'reason'); + expect(constructedEvent.eventData['finalLibraryCount'], 5); + expect(constructedEvent.eventData['syncedLibraryCount'], 6); + expect(constructedEvent.eventData['syncedClassesCount'], 7); + expect(constructedEvent.eventData['syncedProceduresCount'], 8); + expect(constructedEvent.eventData['syncedBytes'], 9); + expect(constructedEvent.eventData['invalidatedSourcesCount'], 10); + expect(constructedEvent.eventData['transferTimeInMs'], 11); + expect(constructedEvent.eventData['overallTimeInMs'], 12); + expect(constructedEvent.eventData['compileTimeInMs'], 13); + expect(constructedEvent.eventData['findInvalidatedTimeInMs'], 14); + expect(constructedEvent.eventData['scannedSourcesCount'], 15); + expect(constructedEvent.eventData['reassembleTimeInMs'], 16); + expect(constructedEvent.eventData['reloadVMTimeInMs'], 17); + expect(constructedEvent.eventData.length, 19); + }); + + test('Event.flutterCommandResult constructed', () { + Event generateEvent() => Event.flutterCommandResult( + commandPath: 'commandPath', + result: 'result', + commandHasTerminal: true, + maxRss: 123, + ); + + final constructedEvent = generateEvent(); + + expect(generateEvent, returnsNormally); + expect(constructedEvent.eventName, DashEvent.flutterCommandResult); + expect(constructedEvent.eventData['commandPath'], 'commandPath'); + expect(constructedEvent.eventData['result'], 'result'); + expect(constructedEvent.eventData['commandHasTerminal'], true); + expect(constructedEvent.eventData['maxRss'], 123); + expect(constructedEvent.eventData.length, 4); + }); + + test('Event.codeSizeAnalysis constructed', () { + Event generateEvent() => Event.codeSizeAnalysis(platform: 'platform'); + + final constructedEvent = generateEvent(); + + expect(generateEvent, returnsNormally); + expect(constructedEvent.eventName, DashEvent.codeSizeAnalysis); + expect(constructedEvent.eventData['platform'], 'platform'); + expect(constructedEvent.eventData.length, 1); + }); + + test('Event.appleUsageEvent constructed', () { + Event generateEvent() => Event.appleUsageEvent( + workflow: 'workflow', + parameter: 'parameter', + result: 'result', + ); + + final constructedEvent = generateEvent(); + + expect(generateEvent, returnsNormally); + expect(constructedEvent.eventName, DashEvent.appleUsageEvent); + expect(constructedEvent.eventData['workflow'], 'workflow'); + expect(constructedEvent.eventData['parameter'], 'parameter'); + expect(constructedEvent.eventData['result'], 'result'); + expect(constructedEvent.eventData.length, 3); + }); + + test('Event.exception constructed', () { + Event generateEvent() => Event.exception( + exception: 'exception', + data: {'foo': 'bar', 'baz': 1}, + ); + + final constructedEvent = generateEvent(); + + expect(generateEvent, returnsNormally); + expect(constructedEvent.eventName, DashEvent.exception); + expect(constructedEvent.eventData['exception'], 'exception'); + expect(constructedEvent.eventData['foo'], 'bar'); + expect(constructedEvent.eventData['baz'], 1); + expect(constructedEvent.eventData.length, 3); + }); + + test('Event.timing constructed', () { + Event generateEvent() => Event.timing( + workflow: 'workflow', + variableName: 'variableName', + elapsedMilliseconds: 123, + label: 'label', + ); + + final constructedEvent = generateEvent(); + + expect(generateEvent, returnsNormally); + expect(constructedEvent.eventName, DashEvent.timing); + expect(constructedEvent.eventData['workflow'], 'workflow'); + expect(constructedEvent.eventData['variableName'], 'variableName'); + expect(constructedEvent.eventData['elapsedMilliseconds'], 123); + expect(constructedEvent.eventData['label'], 'label'); + expect(constructedEvent.eventData.length, 4); + }); + + test('Event.commandUsageValues constructed', () { + Event generateEvent() => Event.commandUsageValues( + workflow: 'workflow', + commandHasTerminal: true, + buildBundleTargetPlatform: 'buildBundleTargetPlatform', + buildBundleIsModule: true, + buildAarProjectType: 'buildAarProjectType', + buildAarTargetPlatform: 'buildAarTargetPlatform', + buildApkTargetPlatform: 'buildApkTargetPlatform', + buildApkBuildMode: 'buildApkBuildMode', + buildApkSplitPerAbi: true, + buildAppBundleTargetPlatform: 'buildAppBundleTargetPlatform', + buildAppBundleBuildMode: 'buildAppBundleBuildMode', + createProjectType: 'createProjectType', + createAndroidLanguage: 'createAndroidLanguage', + createIosLanguage: 'createIosLanguage', + packagesNumberPlugins: 123, + packagesProjectModule: true, + packagesAndroidEmbeddingVersion: 'packagesAndroidEmbeddingVersion', + runIsEmulator: true, + runTargetName: 'runTargetName', + runTargetOsVersion: 'runTargetOsVersion', + runModeName: 'runModeName', + runProjectModule: true, + runProjectHostLanguage: 'runProjectHostLanguage', + runAndroidEmbeddingVersion: 'runAndroidEmbeddingVersion', + runEnableImpeller: true, + runIOSInterfaceType: 'runIOSInterfaceType', + runIsTest: true, + ); + + final constructedEvent = generateEvent(); + + expect(generateEvent, returnsNormally); + expect(constructedEvent.eventName, DashEvent.commandUsageValues); + expect(constructedEvent.eventData['workflow'], 'workflow'); + expect(constructedEvent.eventData['buildBundleTargetPlatform'], + 'buildBundleTargetPlatform'); + expect(constructedEvent.eventData['buildBundleIsModule'], true); + expect(constructedEvent.eventData['buildAarProjectType'], + 'buildAarProjectType'); + expect(constructedEvent.eventData['buildAarTargetPlatform'], + 'buildAarTargetPlatform'); + expect(constructedEvent.eventData['buildApkTargetPlatform'], + 'buildApkTargetPlatform'); + expect( + constructedEvent.eventData['buildApkBuildMode'], 'buildApkBuildMode'); + expect(constructedEvent.eventData['buildApkSplitPerAbi'], true); + expect(constructedEvent.eventData['buildAppBundleTargetPlatform'], + 'buildAppBundleTargetPlatform'); + expect(constructedEvent.eventData['buildAppBundleBuildMode'], + 'buildAppBundleBuildMode'); + expect( + constructedEvent.eventData['createProjectType'], 'createProjectType'); + expect(constructedEvent.eventData['createAndroidLanguage'], + 'createAndroidLanguage'); + expect( + constructedEvent.eventData['createIosLanguage'], 'createIosLanguage'); + expect(constructedEvent.eventData['packagesNumberPlugins'], 123); + expect(constructedEvent.eventData['packagesProjectModule'], true); + expect(constructedEvent.eventData['packagesAndroidEmbeddingVersion'], + 'packagesAndroidEmbeddingVersion'); + expect(constructedEvent.eventData['runIsEmulator'], true); + expect(constructedEvent.eventData['runTargetName'], 'runTargetName'); + expect( + constructedEvent.eventData['runTargetOsVersion'], 'runTargetOsVersion'); + expect(constructedEvent.eventData['runModeName'], 'runModeName'); + expect(constructedEvent.eventData['runProjectModule'], true); + expect(constructedEvent.eventData['runProjectHostLanguage'], + 'runProjectHostLanguage'); + expect(constructedEvent.eventData['runAndroidEmbeddingVersion'], + 'runAndroidEmbeddingVersion'); + expect(constructedEvent.eventData['runEnableImpeller'], true); + expect(constructedEvent.eventData['runIOSInterfaceType'], + 'runIOSInterfaceType'); + expect(constructedEvent.eventData.length, 27); + }); + + test('Event.analyticsException constructed', () { + Event generateEvent() => Event.analyticsException( + workflow: 'workflow', + error: 'error', + description: 'description', + ); + + final constructedEvent = generateEvent(); + + expect(generateEvent, returnsNormally); + expect(constructedEvent.eventName, DashEvent.analyticsException); + expect(constructedEvent.eventData['workflow'], 'workflow'); + expect(constructedEvent.eventData['error'], 'error'); + expect(constructedEvent.eventData['description'], 'description'); + expect(constructedEvent.eventData.length, 3); + }); + + test('Event.devtoolsEvent constructed', () { + Event generateEvent() => Event.devtoolsEvent( + eventCategory: 'eventCategory', + label: 'label', + value: 1, + userInitiatedInteraction: true, + g3Username: 'g3Username', + userApp: 'userApp', + userBuild: 'userBuild', + userPlatform: 'userPlatform', + devtoolsPlatform: 'devtoolsPlatform', + devtoolsChrome: 'devtoolsChrome', + devtoolsVersion: 'devtoolsVersion', + ideLaunched: 'ideLaunched', + isExternalBuild: 'isExternalBuild', + isEmbedded: 'isEmbedded', + ideLaunchedFeature: 'ideLaunchedFeature', + isWasm: 'true', + uiDurationMicros: 123, + rasterDurationMicros: 123, + shaderCompilationDurationMicros: 123, + traceEventCount: 123, + cpuSampleCount: 123, + cpuStackDepth: 123, + heapDiffObjectsBefore: 123, + heapDiffObjectsAfter: 123, + heapObjectsTotal: 123, + rootSetCount: 123, + rowCount: 123, + inspectorTreeControllerId: 123, + androidAppId: 'androidAppId', + iosBundleId: 'iosBundleId', + ); + + final constructedEvent = generateEvent(); + + expect(generateEvent, returnsNormally); + expect(constructedEvent.eventData['eventCategory'], 'eventCategory'); + expect(constructedEvent.eventData['label'], 'label'); + expect(constructedEvent.eventData['value'], 1); + expect(constructedEvent.eventData['userInitiatedInteraction'], true); + expect(constructedEvent.eventData['g3Username'], 'g3Username'); + expect(constructedEvent.eventData['userApp'], 'userApp'); + expect(constructedEvent.eventData['userBuild'], 'userBuild'); + expect(constructedEvent.eventData['userPlatform'], 'userPlatform'); + expect(constructedEvent.eventData['devtoolsPlatform'], 'devtoolsPlatform'); + expect(constructedEvent.eventData['devtoolsChrome'], 'devtoolsChrome'); + expect(constructedEvent.eventData['devtoolsVersion'], 'devtoolsVersion'); + expect(constructedEvent.eventData['ideLaunched'], 'ideLaunched'); + expect(constructedEvent.eventData['isExternalBuild'], 'isExternalBuild'); + expect(constructedEvent.eventData['isEmbedded'], 'isEmbedded'); + expect( + constructedEvent.eventData['ideLaunchedFeature'], 'ideLaunchedFeature'); + expect(constructedEvent.eventData['isWasm'], 'true'); + + expect(constructedEvent.eventData['uiDurationMicros'], 123); + expect(constructedEvent.eventData['rasterDurationMicros'], 123); + expect(constructedEvent.eventData['shaderCompilationDurationMicros'], 123); + expect(constructedEvent.eventData['traceEventCount'], 123); + expect(constructedEvent.eventData['cpuSampleCount'], 123); + expect(constructedEvent.eventData['cpuStackDepth'], 123); + expect(constructedEvent.eventData['heapDiffObjectsBefore'], 123); + expect(constructedEvent.eventData['heapDiffObjectsAfter'], 123); + expect(constructedEvent.eventData['heapObjectsTotal'], 123); + expect(constructedEvent.eventData['rootSetCount'], 123); + expect(constructedEvent.eventData['rowCount'], 123); + expect(constructedEvent.eventData['inspectorTreeControllerId'], 123); + expect(constructedEvent.eventData['androidAppId'], 'androidAppId'); + expect(constructedEvent.eventData['iosBundleId'], 'iosBundleId'); + expect(constructedEvent.eventData.length, 30); + }); + + test('Confirm all constructors were checked', () { + var constructorCount = 0; + for (final declaration in reflectClass(Event).declarations.keys) { + // Count public constructors but omit private constructors + if (declaration.toString().contains('Event.') && + !declaration.toString().contains('Event._')) { + constructorCount++; + } + } + + // Change this integer below if your PR either adds or removes + // an Event constructor + final eventsAccountedForInTests = 27; + expect(eventsAccountedForInTests, constructorCount, + reason: 'If you added or removed an event constructor, ' + 'ensure you have updated ' + '`pkgs/unified_analytics/test/event_test.dart` ' + 'to reflect the changes made'); + }); + + test('Serializing event to json successful', () { + final event = Event.analyticsException( + workflow: 'workflow', + error: 'error', + description: 'description', + ); + + final expectedResult = '{"eventName":"analytics_exception",' + '"eventData":{"workflow":"workflow",' + '"error":"error",' + '"description":"description"}}'; + + expect(event.toJson(), expectedResult); + }); + + test('Deserializing string to event successful', () { + final eventJson = '{"eventName":"analytics_exception",' + '"eventData":{"workflow":"workflow",' + '"error":"error",' + '"description":"description"}}'; + + final eventConstructed = Event.fromJson(eventJson); + expect(eventConstructed, isNotNull); + eventConstructed!; + + expect(eventConstructed.eventName, DashEvent.analyticsException); + expect(eventConstructed.eventData, { + 'workflow': 'workflow', + 'error': 'error', + 'description': 'description', + }); + }); + + test('Deserializing string to event unsuccessful for invalid eventName', () { + final eventJson = '{"eventName":"NOT_VALID_NAME",' + '"eventData":{"workflow":"workflow",' + '"error":"error",' + '"description":"description"}}'; + + final eventConstructed = Event.fromJson(eventJson); + expect(eventConstructed, isNull); + }); + + test('Deserializing string to event unsuccessful for invalid eventData', () { + final eventJson = '{"eventName":"analytics_exception",' + '"eventData": "not_valid_event_data"}'; + + final eventConstructed = Event.fromJson(eventJson); + expect(eventConstructed, isNull); + }); +}
diff --git a/pkgs/unified_analytics/test/events_with_fake_test.dart b/pkgs/unified_analytics/test/events_with_fake_test.dart new file mode 100644 index 0000000..9794275 --- /dev/null +++ b/pkgs/unified_analytics/test/events_with_fake_test.dart
@@ -0,0 +1,146 @@ +// 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:clock/clock.dart'; +import 'package:file/file.dart'; +import 'package:file/memory.dart'; +import 'package:test/test.dart'; + +import 'package:unified_analytics/src/constants.dart'; +import 'package:unified_analytics/src/enums.dart'; +import 'package:unified_analytics/src/survey_handler.dart'; +import 'package:unified_analytics/unified_analytics.dart'; + +void main() { + // The fake analytics instance can be used to ensure events + // are being sent when invoking methods on the `Analytics` instance + + late FakeAnalytics fakeAnalytics; + late MemoryFileSystem fs; + late Directory homeDirectory; + late File dismissedSurveyFile; + + /// Survey to load into the fake instance to fetch + /// + /// The 1.0 sample rate means that this will always show + /// up from the method to fetch available surveys + final testSurvey = Survey( + uniqueId: 'uniqueId', + startDate: DateTime(2022, 1, 1), + endDate: DateTime(2022, 12, 31), + description: 'description', + snoozeForMinutes: 10, + samplingRate: 1.0, // 100% sample rate + excludeDashToolList: [], + conditionList: <Condition>[], + buttonList: [ + SurveyButton( + buttonText: 'buttonText', + action: 'accept', + promptRemainsVisible: false, + ), + SurveyButton( + buttonText: 'buttonText', + action: 'dismiss', + promptRemainsVisible: false, + ), + ], + ); + + setUp(() async { + fs = MemoryFileSystem.test(style: FileSystemStyle.posix); + homeDirectory = fs.directory('home'); + dismissedSurveyFile = homeDirectory + .childDirectory(kDartToolDirectoryName) + .childFile(kDismissedSurveyFileName); + + final initialAnalytics = Analytics.fake( + tool: DashTool.flutterTool, + homeDirectory: homeDirectory, + dartVersion: 'dartVersion', + toolsMessageVersion: 1, + fs: fs, + platform: DevicePlatform.macos, + ); + initialAnalytics.clientShowedMessage(); + + // Recreate a second instance since events cannot be sent on + // the first run + withClock(Clock.fixed(DateTime(2022, 3, 3)), () { + final toolsMessageVersion = kToolsMessageVersion; + fakeAnalytics = Analytics.fake( + tool: DashTool.flutterTool, + homeDirectory: homeDirectory, + dartVersion: 'dartVersion', + platform: DevicePlatform.macos, + fs: fs, + toolsMessageVersion: toolsMessageVersion, + surveyHandler: FakeSurveyHandler.fromList( + dismissedSurveyFile: dismissedSurveyFile, + initializedSurveys: [testSurvey], + ), + ); + }); + }); + + test('event sent when survey shown', () async { + final surveyList = await fakeAnalytics.fetchAvailableSurveys(); + expect(surveyList.length, 1); + expect(fakeAnalytics.sentEvents.length, 0); + + final survey = surveyList.first; + expect(survey.uniqueId, 'uniqueId'); + + // Simulate the survey being shown + fakeAnalytics.surveyShown(survey); + + expect(fakeAnalytics.sentEvents.length, 1); + expect(fakeAnalytics.sentEvents.last.eventName, DashEvent.surveyShown); + expect(fakeAnalytics.sentEvents.last.eventData, {'surveyId': 'uniqueId'}); + }); + + test('event sent when survey accepted', () async { + final surveyList = await fakeAnalytics.fetchAvailableSurveys(); + expect(surveyList.length, 1); + expect(fakeAnalytics.sentEvents.length, 0); + + final survey = surveyList.first; + expect(survey.uniqueId, 'uniqueId'); + + // Simulate the survey being shown + // + // The first button is the accept button + fakeAnalytics.surveyInteracted( + survey: survey, + surveyButton: survey.buttonList.first, + ); + + expect(fakeAnalytics.sentEvents.length, 1); + expect(fakeAnalytics.sentEvents.last.eventName, DashEvent.surveyAction); + expect(fakeAnalytics.sentEvents.last.eventData, + {'surveyId': 'uniqueId', 'status': 'accept'}); + }); + + test('event sent when survey rejected', () async { + final surveyList = await fakeAnalytics.fetchAvailableSurveys(); + expect(surveyList.length, 1); + expect(fakeAnalytics.sentEvents.length, 0); + + final survey = surveyList.first; + expect(survey.uniqueId, 'uniqueId'); + + // Simulate the survey being shown + // + // The last button is the reject button + fakeAnalytics.surveyInteracted( + survey: survey, + surveyButton: survey.buttonList.last, + ); + + expect(fakeAnalytics.sentEvents.length, 1); + expect(fakeAnalytics.sentEvents.last.eventName, DashEvent.surveyAction); + expect(fakeAnalytics.sentEvents.last.eventData, + {'surveyId': 'uniqueId', 'status': 'dismiss'}); + }); +}
diff --git a/pkgs/unified_analytics/test/legacy_analytics_test.dart b/pkgs/unified_analytics/test/legacy_analytics_test.dart new file mode 100644 index 0000000..36acee9 --- /dev/null +++ b/pkgs/unified_analytics/test/legacy_analytics_test.dart
@@ -0,0 +1,325 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:io' as io; + +import 'package:file/file.dart'; +import 'package:file/memory.dart'; +import 'package:test/test.dart'; + +import 'package:unified_analytics/src/enums.dart'; +import 'package:unified_analytics/unified_analytics.dart'; + +void main() { + late MemoryFileSystem fs; + late Directory home; + late Analytics analytics; + + const homeDirName = 'home'; + const initialTool = DashTool.flutterTool; + const toolsMessageVersion = 1; + const toolsMessage = 'toolsMessage'; + const flutterChannel = 'flutterChannel'; + const flutterVersion = 'flutterVersion'; + const dartVersion = 'dartVersion'; + const platform = DevicePlatform.macos; + + setUp(() { + // Setup the filesystem with the home directory + final fsStyle = + io.Platform.isWindows ? FileSystemStyle.windows : FileSystemStyle.posix; + fs = MemoryFileSystem.test(style: fsStyle); + home = fs.directory(homeDirName); + }); + + test('Honor legacy dart analytics opt out', () { + // Create the file for the dart legacy opt out + final dartLegacyConfigFile = + home.childDirectory('.dart').childFile('dartdev.json'); + dartLegacyConfigFile.createSync(recursive: true); + dartLegacyConfigFile.writeAsStringSync(''' +{ + "firstRun": false, + "enabled": false, + "disclosureShown": true, + "clientId": "52710e60-7c70-4335-b3a4-9d922630f12a" +} +'''); + + // The main analytics instance, other instances can be spawned within tests + // to test how to instances running together work + analytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + ); + + expect(analytics.telemetryEnabled, false); + }); + + test('Telemetry enabled if legacy dart analytics is enabled', () { + // Create the file for the dart legacy opt out + final dartLegacyConfigFile = + home.childDirectory('.dart').childFile('dartdev.json'); + dartLegacyConfigFile.createSync(recursive: true); + dartLegacyConfigFile.writeAsStringSync(''' +{ + "firstRun": false, + "enabled": true, + "disclosureShown": true, + "clientId": "52710e60-7c70-4335-b3a4-9d922630f12a" +} +'''); + + // The main analytics instance, other instances can be spawned within tests + // to test how to instances running together work + analytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + ); + + expect(analytics.telemetryEnabled, true); + }); + + test('Honor legacy flutter analytics opt out', () { + // Create the file for the flutter legacy opt out + final flutterLegacyConfigFile = + home.childDirectory('.dart').childFile('dartdev.json'); + flutterLegacyConfigFile.createSync(recursive: true); + flutterLegacyConfigFile.writeAsStringSync(''' +{ + "firstRun": false, + "clientId": "4c3a3d1e-e545-47e7-b4f8-10129f6ab169", + "enabled": false +} +'''); + + // The main analytics instance, other instances can be spawned within tests + // to test how to instances running together work + analytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + ); + + expect(analytics.telemetryEnabled, false); + }); + + test('Telemetry enabled if legacy flutter analytics is enabled', () { + // Create the file for the flutter legacy opt out + final flutterLegacyConfigFile = + home.childDirectory('.dart').childFile('dartdev.json'); + flutterLegacyConfigFile.createSync(recursive: true); + flutterLegacyConfigFile.writeAsStringSync(''' +{ + "firstRun": false, + "clientId": "4c3a3d1e-e545-47e7-b4f8-10129f6ab169", + "enabled": true +} +'''); + + // The main analytics instance, other instances can be spawned within tests + // to test how to instances running together work + analytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + ); + + expect(analytics.telemetryEnabled, true); + }); + + test('Honor legacy devtools analytics opt out', () { + // Create the file for the devtools legacy opt out + final devtoolsLegacyConfigFile = + home.childDirectory('.flutter-devtools').childFile('.devtools'); + devtoolsLegacyConfigFile.createSync(recursive: true); + devtoolsLegacyConfigFile.writeAsStringSync(''' +{ + "analyticsEnabled": false, + "isFirstRun": false, + "lastReleaseNotesVersion": "2.31.0", + "2023-Q4": { + "surveyActionTaken": false, + "surveyShownCount": 0 + } +} +'''); + + // The main analytics instance, other instances can be spawned within tests + // to test how to instances running together work + analytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + ); + + expect(analytics.telemetryEnabled, false); + }); + + test('Telemetry enabled if legacy devtools analytics is enabled', () { + // Create the file for the devtools legacy opt out + final devtoolsLegacyConfigFile = + home.childDirectory('.flutter-devtools').childFile('.devtools'); + devtoolsLegacyConfigFile.createSync(recursive: true); + devtoolsLegacyConfigFile.writeAsStringSync(''' +{ + "analyticsEnabled": true, + "isFirstRun": false, + "lastReleaseNotesVersion": "2.31.0", + "2023-Q4": { + "surveyActionTaken": false, + "surveyShownCount": 0 + } +} +'''); + + // The main analytics instance, other instances can be spawned within tests + // to test how to instances running together work + analytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + ); + + expect(analytics.telemetryEnabled, true); + }); + + test('Telemetry disabled if dart config file corrupted', () { + // Create the file for the dart legacy opt out with text that + // is not valid JSON + final dartLegacyConfigFile = + home.childDirectory('.dart').childFile('dartdev.json'); + dartLegacyConfigFile.createSync(recursive: true); + dartLegacyConfigFile.writeAsStringSync(''' +NOT VALID JSON +{ + "firstRun": false, + "clientId": "4c3a3d1e-e545-47e7-b4f8-10129f6ab169", + "enabled": true +} +'''); + + // The main analytics instance, other instances can be spawned within tests + // to test how to instances running together work + analytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + ); + + expect(analytics.telemetryEnabled, false); + }); + + test('Telemetry disabled if devtools config file corrupted', () { + // Create the file for the devtools legacy opt out with text that + // is not valid JSON + final devtoolsLegacyConfigFile = + home.childDirectory('.flutter-devtools').childFile('.devtools'); + devtoolsLegacyConfigFile.createSync(recursive: true); + devtoolsLegacyConfigFile.writeAsStringSync(''' +NOT VALID JSON +{ + "analyticsEnabled": true, + "isFirstRun": false, + "lastReleaseNotesVersion": "2.31.0", + "2023-Q4": { + "surveyActionTaken": false, + "surveyShownCount": 0 + } +} +'''); + + // The main analytics instance, other instances can be spawned within tests + // to test how to instances running together work + analytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + ); + + expect(analytics.telemetryEnabled, false); + }); + + test('Telemetry disabled if flutter config file corrupted', () { + // Create the file for the flutter legacy opt out with text that + // is not valid JSON + final fluttterLegacyConfigFile = + home.childDirectory('.dart').childFile('dartdev.json'); + fluttterLegacyConfigFile.createSync(recursive: true); + fluttterLegacyConfigFile.writeAsStringSync(''' +NOT VALID JSON +{ + "firstRun": false, + "clientId": "4c3a3d1e-e545-47e7-b4f8-10129f6ab169", + "enabled": true +} +'''); + + // The main analytics instance, other instances can be spawned within tests + // to test how to instances running together work + analytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + ); + + expect(analytics.telemetryEnabled, false); + }); +}
diff --git a/pkgs/unified_analytics/test/log_handler_test.dart b/pkgs/unified_analytics/test/log_handler_test.dart new file mode 100644 index 0000000..db14d96 --- /dev/null +++ b/pkgs/unified_analytics/test/log_handler_test.dart
@@ -0,0 +1,381 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; + +import 'package:file/file.dart'; +import 'package:file/memory.dart'; +import 'package:test/fake.dart'; +import 'package:test/test.dart'; + +import 'package:unified_analytics/src/constants.dart'; +import 'package:unified_analytics/src/enums.dart'; +import 'package:unified_analytics/src/log_handler.dart'; +import 'package:unified_analytics/src/utils.dart'; +import 'package:unified_analytics/unified_analytics.dart'; + +void main() { + late FakeAnalytics analytics; + late Directory homeDirectory; + late MemoryFileSystem fs; + late File logFile; + + final testEvent = Event.hotReloadTime(timeMs: 10); + + setUp(() { + fs = MemoryFileSystem.test(style: FileSystemStyle.posix); + homeDirectory = fs.directory('home'); + logFile = homeDirectory + .childDirectory(kDartToolDirectoryName) + .childFile(kLogFileName); + + // Create the initialization analytics instance to onboard the tool + final initializationAnalytics = Analytics.fake( + tool: DashTool.flutterTool, + homeDirectory: homeDirectory, + dartVersion: 'dartVersion', + fs: fs, + platform: DevicePlatform.macos, + ); + initializationAnalytics.clientShowedMessage(); + + // This instance is free to send events since the instance above + // has confirmed that the client has shown the message + analytics = Analytics.fake( + tool: DashTool.flutterTool, + homeDirectory: homeDirectory, + dartVersion: 'dartVersion', + fs: fs, + platform: DevicePlatform.macos, + ); + }); + + test('Ensure that log file is created', () { + expect(logFile.existsSync(), true); + }); + + test('LogFileStats is null before events are sent', () { + expect(analytics.logFileStats(), isNull); + }); + + test('LogFileStats returns valid response after sent events', () async { + final countOfEventsToSend = 10; + + for (var i = 0; i < countOfEventsToSend; i++) { + analytics.send(testEvent); + } + + expect(analytics.logFileStats(), isNotNull); + expect(logFile.readAsLinesSync().length, countOfEventsToSend); + expect(analytics.logFileStats()!.recordCount, countOfEventsToSend); + }); + + test('The only record in the log file is malformed', () async { + // Write invalid json for the only log record + logFile.writeAsStringSync('{{\n'); + + expect(logFile.readAsLinesSync().length, 1); + final logFileStats = analytics.logFileStats(); + expect(logFileStats, isNull, + reason: 'Null should be returned since only ' + 'one record is in there and it is malformed'); + + analytics.sendPendingErrorEvents(); + expect( + analytics.sentEvents, + contains( + Event.analyticsException( + workflow: 'LogFileStats.logFileStats', + error: 'FormatException', + description: 'message: Unexpected character\nsource: {{', + ), + )); + }); + + test('The first record is malformed, but rest are valid', () async { + // Write invalid json for the only log record + logFile.writeAsStringSync('{{\n'); + + final countOfEventsToSend = 10; + + for (var i = 0; i < countOfEventsToSend; i++) { + analytics.send(testEvent); + } + expect(logFile.readAsLinesSync().length, countOfEventsToSend + 1); + final logFileStats = analytics.logFileStats(); + + expect(logFileStats, isNotNull); + expect(logFileStats!.recordCount, countOfEventsToSend); + }); + + test('Several records are malformed', () async { + final countOfMalformedRecords = 4; + for (var i = 0; i < countOfMalformedRecords; i++) { + final currentContents = logFile.readAsStringSync(); + logFile.writeAsStringSync('$currentContents{{\n'); + } + + final countOfEventsToSend = 10; + + for (var i = 0; i < countOfEventsToSend; i++) { + analytics.send(testEvent); + } + + expect(logFile.readAsLinesSync().length, + countOfEventsToSend + countOfMalformedRecords); + final logFileStats = analytics.logFileStats(); + + analytics.sendPendingErrorEvents(); + expect(logFile.readAsLinesSync().length, + countOfEventsToSend + countOfMalformedRecords + 1, + reason: + 'There should have been on error event sent when getting stats'); + + expect(logFileStats, isNotNull); + expect(logFileStats!.recordCount, countOfEventsToSend); + }); + + test('Valid json but invalid keys', () { + // The second line here is missing the "events" top level + // key which should cause an error for that record only + // + // Important to note that this won't actually cause a FormatException + // like the other malformed records, instead the LogItem.fromRecord + // constructor will return null if all the keys are not available + final contents = ''' +{"client_id":"ffcea97b-db5e-4c66-98c2-3942de4fac40","events":[{"name":"hot_reload_time","params":{"timeMs":136}}],"user_properties":{"session_id":{"value":1699385899950},"flutter_channel":{"value":"ey-test-channel"},"host":{"value":"macOS"},"flutter_version":{"value":"Flutter 3.6.0-7.0.pre.47"},"dart_version":{"value":"Dart 2.19.0"},"analytics_pkg_version":{"value":"5.2.0"},"tool":{"value":"flutter-tool"},"local_time":{"value":"2023-11-07 15:37:26.685761 -0500"},"host_os_version":{"value":"Version 14.1 (Build 23B74)"},"locale":{"value":"en"},"client_ide":{"value":"VSCode"}}} +{"client_id":"ffcea97b-db5e-4c66-98c2-3942de4fac40","WRONG_EVENT_KEY":[{"name":"hot_reload_time","params":{"timeMs":136}}],"user_properties":{"session_id":{"value":1699385899950},"flutter_channel":{"value":"ey-test-channel"},"host":{"value":"macOS"},"flutter_version":{"value":"Flutter 3.6.0-7.0.pre.47"},"dart_version":{"value":"Dart 2.19.0"},"analytics_pkg_version":{"value":"5.2.0"},"tool":{"value":"flutter-tool"},"local_time":{"value":"2023-11-07 15:37:26.685761 -0500"},"host_os_version":{"value":"Version 14.1 (Build 23B74)"},"locale":{"value":"en"},"client_ide":{"value":"VSCode"}}} +{"client_id":"ffcea97b-db5e-4c66-98c2-3942de4fac40","events":[{"name":"hot_reload_time","params":{"timeMs":136}}],"user_properties":{"session_id":{"value":1699385899950},"flutter_channel":{"value":"ey-test-channel"},"host":{"value":"macOS"},"flutter_version":{"value":"Flutter 3.6.0-7.0.pre.47"},"dart_version":{"value":"Dart 2.19.0"},"analytics_pkg_version":{"value":"5.2.0"},"tool":{"value":"flutter-tool"},"local_time":{"value":"2023-11-07 15:37:26.685761 -0500"},"host_os_version":{"value":"Version 14.1 (Build 23B74)"},"locale":{"value":"en"},"client_ide":{"value":"VSCode"}}} +'''; + logFile.writeAsStringSync(contents); + + final logFileStats = analytics.logFileStats(); + + expect(logFile.readAsLinesSync().length, 3); + expect(logFileStats, isNotNull); + expect(logFileStats!.recordCount, 2); + }); + + test('Malformed record gets phased out after several events', () async { + // Write invalid json for the only log record + logFile.writeAsStringSync('{{\n'); + + // Send the max number of events minus two so that we have + // one malformed record on top of the logs and the rest + // are valid log records + // + // We need to account for the event that is sent when + // calling [logFileStats()] fails and sends an instance + // of [Event.analyticsException] + final recordsToSendInitially = kLogFileLength - 2; + for (var i = 0; i < recordsToSendInitially; i++) { + analytics.send(testEvent); + } + final logFileStats = analytics.logFileStats(); + analytics.sendPendingErrorEvents(); + expect(analytics.sentEvents.last.eventName, DashEvent.analyticsException, + reason: 'Calling for the stats should have caused an error'); + expect(logFile.readAsLinesSync().length, kLogFileLength); + expect(logFileStats, isNotNull); + expect(logFileStats!.recordCount, recordsToSendInitially, + reason: 'The first record should be malformed'); + expect(logFile.readAsLinesSync()[0].trim(), '{{'); + + // Sending one more event should flush out the malformed record + analytics.send(testEvent); + + final secondLogFileStats = analytics.logFileStats(); + expect(analytics.sentEvents.last, testEvent); + expect(secondLogFileStats, isNotNull); + expect(secondLogFileStats!.recordCount, kLogFileLength); + expect(logFile.readAsLinesSync()[0].trim(), isNot('{{')); + }); + + test( + 'Catches and discards any FileSystemException raised from attempting ' + 'to write to the log file', () async { + final logFilePath = 'log.txt'; + final fs = MemoryFileSystem.test(opHandle: (context, operation) { + if (context == logFilePath && operation == FileSystemOp.write) { + throw FileSystemException( + 'writeFrom failed', + logFilePath, + const OSError('No space left on device', 28), + ); + } + }); + final logFile = fs.file(logFilePath); + logFile.createSync(); + final logHandler = LogHandler(logFile: logFile); + + logHandler.save(data: {}); + }); + + test('deletes log file larger than kMaxLogFileSize', () async { + var deletedLargeLogFile = false; + var wroteDataToLogFile = false; + const data = <String, Object?>{}; + final logFile = _FakeFile('log.txt') + .._deleteSyncImpl = (() => deletedLargeLogFile = true) + .._createSyncImpl = () {} + .._statSyncImpl = (() => _FakeFileStat(kMaxLogFileSize + 1)) + .._writeAsStringSync = (contents, {mode = FileMode.append}) { + expect(contents.trim(), data.toString()); + expect(mode, FileMode.writeOnlyAppend); + wroteDataToLogFile = true; + }; + final logHandler = LogHandler(logFile: logFile); + + logHandler.save(data: data); + expect(deletedLargeLogFile, isTrue); + expect(wroteDataToLogFile, isTrue); + }); + + test('does not delete log file if smaller than kMaxLogFileSize', () async { + var wroteDataToLogFile = false; + const data = <String, Object?>{}; + final logFile = _FakeFile('log.txt') + .._deleteSyncImpl = + (() => fail('called logFile.deleteSync() when file was less than ' + 'kMaxLogFileSize')) + .._createSyncImpl = () {} + .._readAsLinesSyncImpl = (() => ['three', 'previous', 'lines']) + .._statSyncImpl = (() => _FakeFileStat(kMaxLogFileSize - 1)) + .._writeAsStringSync = (contents, {mode = FileMode.append}) { + expect(contents.trim(), data.toString()); + expect(mode, FileMode.writeOnlyAppend); + wroteDataToLogFile = true; + }; + final logHandler = LogHandler(logFile: logFile); + + logHandler.save(data: data); + expect(wroteDataToLogFile, isTrue); + }); + + test('Catching cast errors for each log record silently', () async { + // Write a json array to the log file which will cause + // a cast error when parsing each line + logFile.writeAsStringSync('[{}, 1, 2, 3]\n'); + + final logFileStats = analytics.logFileStats(); + expect(logFileStats, isNull); + + // Ensure it will work as expected after writing correct logs + final countOfEventsToSend = 10; + for (var i = 0; i < countOfEventsToSend; i++) { + analytics.send(testEvent); + } + analytics.sendPendingErrorEvents(); + final secondLogFileStats = analytics.logFileStats(); + + expect(secondLogFileStats, isNotNull); + expect(secondLogFileStats!.recordCount, countOfEventsToSend + 1, + reason: 'Plus one for the error event that is sent ' + 'from the first logFileStats call'); + }); + + test( + 'truncateStringToLength returns same string when ' + 'max length greater than string length', () { + final testString = 'Version 14.1 (Build 23B74)'; + final maxLength = 100; + + expect(testString.length < maxLength, true); + + String runTruncateString() => truncateStringToLength(testString, maxLength); + + expect(runTruncateString, returnsNormally); + + final newString = runTruncateString(); + expect(newString, testString); + }); + + test( + 'truncateStringToLength returns truncated string when ' + 'max length less than string length', () { + final testString = 'Version 14.1 (Build 23B74)'; + final maxLength = 10; + + expect(testString.length > maxLength, true); + + String runTruncateString() => truncateStringToLength(testString, maxLength); + + expect(runTruncateString, returnsNormally); + + final newString = runTruncateString(); + expect(newString.length, maxLength); + expect(newString, 'Version 14'); + }); + + test('truncateStringToLength handle errors for invalid max length', () { + final testString = 'Version 14.1 (Build 23B74)'; + var maxLength = 0; + String runTruncateString() => truncateStringToLength(testString, maxLength); + + expect(runTruncateString, throwsArgumentError); + + maxLength = -1; + expect(runTruncateString, throwsArgumentError); + }); + + test('truncateStringToLength same string when max length is the same', () { + final testString = 'Version 14.1 (Build 23B74)'; + final maxLength = testString.length; + + String runTruncateString() => truncateStringToLength(testString, maxLength); + expect(runTruncateString, returnsNormally); + + final newString = runTruncateString(); + expect(newString.length, maxLength); + expect(newString, testString); + }); +} + +class _FakeFileStat extends Fake implements FileStat { + _FakeFileStat(this.size); + + @override + final int size; +} + +class _FakeFile extends Fake implements File { + _FakeFile(this.path); + + List<String> Function()? _readAsLinesSyncImpl; + + @override + List<String> readAsLinesSync({Encoding encoding = utf8}) => + _readAsLinesSyncImpl!(); + + @override + final String path; + + FileStat Function()? _statSyncImpl; + + @override + FileStat statSync() => _statSyncImpl!(); + + void Function()? _deleteSyncImpl; + + @override + void deleteSync({bool recursive = false}) => _deleteSyncImpl!(); + + void Function()? _createSyncImpl; + + @override + void createSync({bool recursive = false, bool exclusive = false}) { + return _createSyncImpl!(); + } + + void Function(String contents, {FileMode mode})? _writeAsStringSync; + + @override + void writeAsStringSync( + String contents, { + FileMode mode = FileMode.write, + Encoding encoding = utf8, + bool flush = false, + }) => + _writeAsStringSync!(contents, mode: mode); +}
diff --git a/pkgs/unified_analytics/test/no_op_analytics_test.dart b/pkgs/unified_analytics/test/no_op_analytics_test.dart new file mode 100644 index 0000000..66c1ef6 --- /dev/null +++ b/pkgs/unified_analytics/test/no_op_analytics_test.dart
@@ -0,0 +1,103 @@ +// 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:file/file.dart'; +import 'package:test/fake.dart'; +import 'package:test/test.dart'; + +import 'package:unified_analytics/src/utils.dart'; +import 'package:unified_analytics/unified_analytics.dart'; + +void main() { + final testEvent = Event.hotReloadTime(timeMs: 50); + + test('NoOpAnalytics.telemetryEnabled is always false', () async { + final analytics = const NoOpAnalytics(); + + expect(analytics.telemetryEnabled, isFalse); + await analytics.setTelemetry(true); + expect(analytics.telemetryEnabled, isFalse); + }); + + test('NoOpAnalytics.shouldShowMessage is always false', () async { + final analytics = const NoOpAnalytics(); + + expect(analytics.shouldShowMessage, isFalse); + analytics.clientShowedMessage(); + expect(analytics.shouldShowMessage, isFalse); + }); + + test('NoOpAnalytics.sendEvent() always returns null', () async { + final analytics = const NoOpAnalytics(); + + await analytics.setTelemetry(true); + analytics.clientShowedMessage(); + expect( + analytics.send(testEvent), + isNull, + ); + }); + + test('NoOpAnalytics.logFileStats() always returns null', () async { + final analytics = const NoOpAnalytics(); + + expect(analytics.logFileStats(), isNull); + + await analytics.setTelemetry(true); + analytics.clientShowedMessage(); + await analytics.send(testEvent); + + expect(analytics.logFileStats(), isNull); + }); + + test('Home directory without write permissions', () { + final home = FakeDirectory(writeEnabled: false); + + expect(checkDirectoryForWritePermissions(home), false); + }); + + test('Home directory with write permissions', () { + final home = FakeDirectory(writeEnabled: true); + + expect(checkDirectoryForWritePermissions(home), true); + }); + + test('Fetching the client id', () { + final analytics = const NoOpAnalytics(); + expect(analytics.clientId, 'xxxx-xxxx'); + }); +} + +class FakeDirectory extends Fake implements Directory { + final String _fakeModeString; + + /// This fake directory class allows you to pass the permissions for + /// the user level, the group and global permissions will default to + /// being denied as indicated by the last 6 characters in the mode string. + FakeDirectory({ + required bool writeEnabled, + bool readEnabled = true, + bool executeEnabled = true, + }) : _fakeModeString = '${readEnabled ? "r" : "-"}' + '${writeEnabled ? "w" : "-"}' + '${executeEnabled ? "x" : "-"}' + '------' { + assert(_fakeModeString.length == 9); + } + + @override + bool existsSync() => true; + + @override + FileStat statSync() => FakeFileStat(_fakeModeString); +} + +class FakeFileStat extends Fake implements FileStat { + final String _fakeModeString; + + FakeFileStat(this._fakeModeString); + + @override + String modeString() => _fakeModeString; +}
diff --git a/pkgs/unified_analytics/test/suppression_test.dart b/pkgs/unified_analytics/test/suppression_test.dart new file mode 100644 index 0000000..05fab15 --- /dev/null +++ b/pkgs/unified_analytics/test/suppression_test.dart
@@ -0,0 +1,132 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:io' as io; + +import 'package:file/file.dart'; +import 'package:file/memory.dart'; +import 'package:test/test.dart'; +import 'package:unified_analytics/src/enums.dart'; +import 'package:unified_analytics/unified_analytics.dart'; + +void main() { + late MemoryFileSystem fs; + late Directory home; + late Analytics initializationAnalytics; + late Analytics analytics; + + const homeDirName = 'home'; + const initialTool = DashTool.flutterTool; + const toolsMessageVersion = 1; + const toolsMessage = 'toolsMessage'; + const flutterChannel = 'flutterChannel'; + const flutterVersion = 'flutterVersion'; + const dartVersion = 'dartVersion'; + const platform = DevicePlatform.macos; + + final testEvent = Event.hotReloadTime(timeMs: 50); + + setUp(() { + // Setup the filesystem with the home directory + final fsStyle = + io.Platform.isWindows ? FileSystemStyle.windows : FileSystemStyle.posix; + fs = MemoryFileSystem.test(style: fsStyle); + home = fs.directory(homeDirName); + + // This is the first analytics instance that will be used to demonstrate + // that events will not be sent with the first run of analytics + initializationAnalytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + ); + initializationAnalytics.clientShowedMessage(); + + // The main analytics instance, other instances can be spawned within tests + // to test how to instances running together work + // + // This instance should have the same parameters as the one above for + // [initializationAnalytics] + analytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + ); + analytics.clientShowedMessage(); + }); + + test('Suppression works as expected', () async { + analytics.suppressTelemetry(); + analytics.send(testEvent); + + final logFileStats = analytics.logFileStats(); + + expect(logFileStats, isNull, + reason: 'Returns null because no records have been recorded'); + }); + + test('Second instance is not suppressed', () async { + analytics.suppressTelemetry(); + analytics.send(testEvent); + + final logFileStats = analytics.logFileStats(); + + expect(logFileStats, isNull, + reason: 'Returns null because no records have been recorded'); + + // The newly created instance will not be suppressed + final secondAnalytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + ); + + // Using a new event here to differentiate from the first one + final newEvent = Event.commandExecuted(count: 2, name: 'commandName'); + secondAnalytics.send(newEvent); + + // Both instances of `Analytics` should now have data retrieved + // from `LogFileStats()` even though only the second instance + // was the instance to send an event + final secondLogFileStats = analytics.logFileStats()!; + final thirdLogFileStats = secondAnalytics.logFileStats()!; + + // Series of checks for each parameter in logFileStats + expect(secondLogFileStats.startDateTime, thirdLogFileStats.startDateTime); + expect(secondLogFileStats.minsFromStartDateTime, + thirdLogFileStats.minsFromStartDateTime); + expect(secondLogFileStats.endDateTime, thirdLogFileStats.endDateTime); + expect(secondLogFileStats.minsFromEndDateTime, + thirdLogFileStats.minsFromEndDateTime); + expect(secondLogFileStats.sessionCount, thirdLogFileStats.sessionCount); + expect(secondLogFileStats.flutterChannelCount, + thirdLogFileStats.flutterChannelCount); + expect(secondLogFileStats.toolCount, thirdLogFileStats.toolCount); + expect(secondLogFileStats.recordCount, thirdLogFileStats.recordCount); + expect(secondLogFileStats.eventCount, thirdLogFileStats.eventCount); + + // Ensure the correct data is in the object + expect(secondLogFileStats.eventCount.containsKey(newEvent.eventName.label), + true); + expect(secondLogFileStats.eventCount[newEvent.eventName.label], 1); + }); +}
diff --git a/pkgs/unified_analytics/test/survey_handler_test.dart b/pkgs/unified_analytics/test/survey_handler_test.dart new file mode 100644 index 0000000..3d8c8dd --- /dev/null +++ b/pkgs/unified_analytics/test/survey_handler_test.dart
@@ -0,0 +1,1229 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; + +import 'package:clock/clock.dart'; +import 'package:file/file.dart'; +import 'package:file/memory.dart'; +import 'package:test/test.dart'; + +import 'package:unified_analytics/src/constants.dart'; +import 'package:unified_analytics/src/enums.dart'; +import 'package:unified_analytics/src/survey_handler.dart'; +import 'package:unified_analytics/src/utils.dart'; +import 'package:unified_analytics/unified_analytics.dart'; + +void main() { + final testEvent = Event.hotReloadTime(timeMs: 10); + + group('Unit testing function sampleRate:', () { + // Set a string that can be used in place of a survey's unique ID + final iterations = 1000; + final uuid = Uuid(123); + final uniqueSurveyId = uuid.generateV4(); + + // Set how much the actual sampled rate can be (allowing 5% of variability) + final marginOfError = 0.05; + + test('Unit testing the sampleRate method', () { + // These strings had a predetermined output from the utility function + final string1 = 'string1'; + final string2 = 'string2'; + expect(sampleRate(string1, string2), 0.40); + }); + + test('Simulating with various sample rates', () { + final sampleRateToTestList = [ + 0.10, + 0.25, + 0.50, + 0.75, + 0.80, + 0.95, + ]; + for (final sampleRateToTest in sampleRateToTestList) { + var count = 0; + for (var i = 0; i < iterations; i++) { + // Regenerate the client id to simulate a unique user + final generatedClientId = uuid.generateV4(); + if (sampleRate(uniqueSurveyId, generatedClientId) <= + sampleRateToTest) { + count += 1; + } + } + + final actualSampledRate = count / iterations; + final actualMarginOfError = + (sampleRateToTest - actualSampledRate).abs(); + + expect(actualMarginOfError < marginOfError, true, + reason: 'Failed on sample rate = $sampleRateToTest with' + ' actual rate $actualMarginOfError ' + 'and a margin of error = $marginOfError'); + } + }); + }); + + group('Unit testing function checkSurveyDate:', () { + final date = DateTime(2023, 5, 1); + // Two surveys created, one that is within the survey date + // range, and one that is not + final validSurvey = Survey( + uniqueId: 'uniqueId', + startDate: DateTime(2023, 1, 1), + endDate: DateTime(2023, 12, 31), + description: 'description', + snoozeForMinutes: 10, + samplingRate: 1.0, + excludeDashToolList: [], + conditionList: <Condition>[], + buttonList: [], + ); + final invalidSurvey = Survey( + uniqueId: 'uniqueId', + startDate: DateTime(2022, 1, 1), + endDate: DateTime(2022, 12, 31), + description: 'description', + snoozeForMinutes: 10, + samplingRate: 1.0, + excludeDashToolList: [], + conditionList: <Condition>[], + buttonList: [], + ); + + test('expired survey', () { + final clock = Clock.fixed(date); + withClock(clock, () { + expect(SurveyHandler.checkSurveyDate(invalidSurvey), false); + }); + }); + + test('valid survey', () { + final clock = Clock.fixed(date); + withClock(clock, () { + expect(SurveyHandler.checkSurveyDate(validSurvey), true); + }); + }); + }); + + group('Unit testing function parseSurveysFromJson', () { + final validContents = ''' +[ + { + "uniqueId": "xxxxx", + "startDate": "2023-06-01T09:00:00-07:00", + "endDate": "2023-06-30T09:00:00-07:00", + "description": "xxxxxxx", + "snoozeForMinutes": "10", + "samplingRate": "1.0", + "excludeDashTools": [], + "conditions": [ + { + "field": "logFileStats.recordCount", + "operator": ">=", + "value": 1000 + }, + { + "field": "logFileStats.toolCount.flutter-tool", + "operator": "<", + "value": 3 + } + ], + "buttons": [ + { + "buttonText": "Take Survey", + "action": "accept", + "url": "https://google.qualtrics.com/jfe/form/SV_5gsB2EuG324y2", + "promptRemainsVisible": false + } + ] + } +] +'''; + + // The value for the condition is not a valid integer + final invalidConditionValueContents = ''' +[ + { + "uniqueId": "xxxxx", + "startDate": "2023-06-01T09:00:00-07:00", + "endDate": "2023-06-30T09:00:00-07:00", + "description": "xxxxxxx", + "snoozeForMinutes": "10", + "samplingRate": "1.0", + "excludeDashTools": [], + "conditions": [ + { + "field": "logFileStats.recordCount", + "operator": ">=", + "value": "1000xxxx" + } + ], + "buttons": [ + { + "buttonText": "Take Survey", + "action": "accept", + "url": "https://google.qualtrics.com/jfe/form/SV_5gsB2EuG324y2", + "promptRemainsVisible": false + } + ] + } +] +'''; + + // Using a dash tool in the excludeDashTools array that is not a valid + // DashTool label + final invalidDashToolContents = ''' +[ + { + "uniqueId": "xxxxx", + "startDate": "2023-06-01T09:00:00-07:00", + "endDate": "2023-06-30T09:00:00-07:00", + "description": "xxxxxxx", + "snoozeForMinutes": "10", + "samplingRate": "1.0", + "excludeDashTools": [ + "not-a-valid-dash-tool" + ], + "conditions": [ + { + "field": "logFileStats.recordCount", + "operator": ">=", + "value": 1000 + }, + { + "field": "logFileStats.toolCount.flutter-tool", + "operator": "<", + "value": 3 + } + ], + "buttons": [ + { + "buttonText": "Take Survey", + "action": "accept", + "url": "https://google.qualtrics.com/jfe/form/SV_5gsB2EuG324y2", + "promptRemainsVisible": false + } + ] + } +] +'''; + + test('valid json', () { + withClock(Clock.fixed(DateTime(2023, 6, 15)), () { + final parsedSurveys = SurveyHandler.parseSurveysFromJson( + jsonDecode(validContents) as List); + + expect(parsedSurveys.length, 1); + expect(parsedSurveys.first.conditionList.length, 2); + + final firstCondition = parsedSurveys.first.conditionList.first; + final secondCondition = parsedSurveys.first.conditionList[1]; + + expect(firstCondition.field, 'logFileStats.recordCount'); + expect(firstCondition.operatorString, '>='); + expect(firstCondition.value, 1000); + + expect(secondCondition.field, 'logFileStats.toolCount.flutter-tool'); + expect(secondCondition.operatorString, '<'); + expect(secondCondition.value, 3); + + expect(parsedSurveys.first.buttonList.length, 1); + expect( + parsedSurveys.first.buttonList.first.promptRemainsVisible, false); + }); + }); + + test('invalid condition json', () { + withClock(Clock.fixed(DateTime(2023, 6, 15)), () { + final parsedSurveys = SurveyHandler.parseSurveysFromJson( + jsonDecode(invalidConditionValueContents) as List); + + expect(parsedSurveys.length, 0, + reason: 'The condition value is not a ' + 'proper integer so it should error returning no surveys'); + }); + }); + + test('invalid dash tool json', () { + withClock(Clock.fixed(DateTime(2023, 6, 15)), () { + final parsedSurveys = SurveyHandler.parseSurveysFromJson( + jsonDecode(invalidDashToolContents) as List); + + expect(parsedSurveys.length, 0, + reason: 'The dash tool in the exclude array is not valid ' + 'so it should error returning no surveys'); + }); + }); + }); + + group('Testing with FakeSurveyHandler', () { + late Analytics analytics; + late Directory homeDirectory; + late MemoryFileSystem fs; + late File clientIdFile; + late File dismissedSurveyFile; + + setUp(() { + fs = MemoryFileSystem.test(style: FileSystemStyle.posix); + homeDirectory = fs.directory('home'); + + // Write the client ID file out so that we don't get + // a randomly assigned id for this test generated within + // the analytics constructor + clientIdFile = homeDirectory + .childDirectory(kDartToolDirectoryName) + .childFile(kClientIdFileName); + clientIdFile.createSync(recursive: true); + clientIdFile.writeAsStringSync('string1'); + + // Assign the json file that will hold the persisted surveys + dismissedSurveyFile = homeDirectory + .childDirectory(kDartToolDirectoryName) + .childFile(kDismissedSurveyFileName); + + // Setup two tools to be onboarded with this package so + // that we can simulate two different tools interacting with + // surveys + // + // This is especially useful when testing the "excludeDashTools" array + // to prevent certain tools from getting a survey from this package + final initialAnalyticsFlutter = Analytics.fake( + tool: DashTool.flutterTool, + homeDirectory: homeDirectory, + dartVersion: 'dartVersion', + fs: fs, + platform: DevicePlatform.macos, + ); + final initialAnalyticsDart = Analytics.fake( + tool: DashTool.dartTool, + homeDirectory: homeDirectory, + dartVersion: 'dartVersion', + fs: fs, + platform: DevicePlatform.macos, + ); + initialAnalyticsFlutter.clientShowedMessage(); + initialAnalyticsDart.clientShowedMessage(); + }); + + test('returns valid survey', () async { + await withClock(Clock.fixed(DateTime(2023, 3, 3)), () async { + analytics = Analytics.fake( + tool: DashTool.flutterTool, + homeDirectory: homeDirectory, + dartVersion: 'dartVersion', + fs: fs, + platform: DevicePlatform.macos, + surveyHandler: FakeSurveyHandler.fromList( + dismissedSurveyFile: dismissedSurveyFile, + initializedSurveys: <Survey>[ + Survey( + uniqueId: 'uniqueId', + startDate: DateTime(2023, 1, 1), + endDate: DateTime(2023, 12, 31), + description: 'description', + snoozeForMinutes: 10, + samplingRate: 1.0, + excludeDashToolList: [], + conditionList: <Condition>[ + Condition('logFileStats.recordCount', '>=', 50), + Condition('logFileStats.toolCount.flutter-tool', '>', 0), + ], + buttonList: [ + SurveyButton( + buttonText: 'buttonText', + action: 'accept', + url: 'http://example.com', + promptRemainsVisible: false, + ), + ], + ), + ], + ), + ); + + // Simulate 60 events to send so that the first condition is satisified + for (var i = 0; i < 60; i++) { + analytics.send(testEvent); + } + + final fetchedSurveys = await analytics.fetchAvailableSurveys(); + + expect(fetchedSurveys.length, 1); + + final survey = fetchedSurveys.first; + expect(survey.conditionList.length, 2); + expect(survey.buttonList.length, 1); + }); + }); + + test('does not return expired survey', () async { + await withClock(Clock.fixed(DateTime(2023, 3, 3)), () async { + analytics = Analytics.fake( + tool: DashTool.flutterTool, + homeDirectory: homeDirectory, + dartVersion: 'dartVersion', + fs: fs, + platform: DevicePlatform.macos, + surveyHandler: FakeSurveyHandler.fromList( + dismissedSurveyFile: dismissedSurveyFile, + initializedSurveys: <Survey>[ + Survey( + uniqueId: 'uniqueId', + startDate: DateTime(2022, 1, 1), + endDate: DateTime(2022, 12, 31), + description: 'description', + snoozeForMinutes: 10, + samplingRate: 1.0, + excludeDashToolList: [], + conditionList: <Condition>[ + Condition('logFileStats.recordCount', '>=', 50), + Condition('logFileStats.toolCount.flutter-tool', '>', 0), + ], + buttonList: [], + ), + ], + ), + ); + + // Simulate 60 events to send so that the first condition is satisified + for (var i = 0; i < 60; i++) { + analytics.send(testEvent); + } + + final fetchedSurveys = await analytics.fetchAvailableSurveys(); + + expect(fetchedSurveys.length, 0); + }); + }); + + test('does not return survey if opted out of telemetry', () async { + await withClock(Clock.fixed(DateTime(2023, 3, 3)), () async { + analytics = Analytics.fake( + tool: DashTool.flutterTool, + homeDirectory: homeDirectory, + dartVersion: 'dartVersion', + fs: fs, + platform: DevicePlatform.macos, + surveyHandler: FakeSurveyHandler.fromList( + dismissedSurveyFile: dismissedSurveyFile, + initializedSurveys: <Survey>[ + Survey( + uniqueId: 'uniqueId', + startDate: DateTime(2023, 1, 1), + endDate: DateTime(2023, 12, 31), + description: 'description', + snoozeForMinutes: 10, + samplingRate: 1.0, + excludeDashToolList: [], + conditionList: <Condition>[ + Condition('logFileStats.recordCount', '>=', 50), + Condition('logFileStats.toolCount.flutter-tool', '>', 0), + ], + buttonList: [], + ), + ], + ), + ); + + // Simulate 60 events to send so that the first condition is satisified + for (var i = 0; i < 60; i++) { + analytics.send(testEvent); + } + + await analytics.setTelemetry(false); + expect(analytics.okToSend, false); + + final fetchedSurveys = await analytics.fetchAvailableSurveys(); + + expect(fetchedSurveys.length, 0); + }); + }); + + test('returns valid survey from json', () async { + await withClock(Clock.fixed(DateTime(2023, 3, 3)), () async { + analytics = Analytics.fake( + tool: DashTool.flutterTool, + homeDirectory: homeDirectory, + dartVersion: 'dartVersion', + fs: fs, + platform: DevicePlatform.macos, + surveyHandler: FakeSurveyHandler.fromString( + dismissedSurveyFile: dismissedSurveyFile, content: ''' +[ + { + "uniqueId": "uniqueId123", + "startDate": "2023-01-01T09:00:00-07:00", + "endDate": "2023-12-31T09:00:00-07:00", + "description": "description123", + "snoozeForMinutes": "10", + "samplingRate": "1.0", + "excludeDashTools": [], + "conditions": [ + { + "field": "logFileStats.recordCount", + "operator": ">=", + "value": 50 + } + ], + "buttons": [ + { + "buttonText": "Take Survey", + "action": "accept", + "url": "https://google.qualtrics.com/jfe/form/SV_5gsB2EuG324y2", + "promptRemainsVisible": false + }, + { + "buttonText": "Dismiss", + "action": "dismiss", + "url": null, + "promptRemainsVisible": false + }, + { + "buttonText": "More Info", + "action": "snooze", + "url": "https://docs.flutter.dev/reference/crash-reporting", + "promptRemainsVisible": true + } + ] + } +] +'''), + ); + + // Simulate 60 events to send so that the first condition is satisified + for (var i = 0; i < 60; i++) { + analytics.send(testEvent); + } + + final fetchedSurveys = await analytics.fetchAvailableSurveys(); + + expect(fetchedSurveys.length, 1); + + final survey = fetchedSurveys.first; + expect(survey.uniqueId, 'uniqueId123'); + expect(survey.startDate.year, 2023); + expect(survey.startDate.month, 1); + expect(survey.startDate.day, 1); + expect(survey.endDate.year, 2023); + expect(survey.endDate.month, 12); + expect(survey.endDate.day, 31); + expect(survey.description, 'description123'); + expect(survey.snoozeForMinutes, 10); + expect(survey.samplingRate, 1.0); + expect(survey.conditionList.length, 1); + + final condition = survey.conditionList.first; + expect(condition.field, 'logFileStats.recordCount'); + expect(condition.operatorString, '>='); + expect(condition.value, 50); + + final buttonList = survey.buttonList; + expect(buttonList.length, 3); + expect(buttonList.first.buttonText, 'Take Survey'); + expect(buttonList.first.action, 'accept'); + expect(buttonList.first.url, + 'https://google.qualtrics.com/jfe/form/SV_5gsB2EuG324y2'); + expect(buttonList.first.promptRemainsVisible, false); + + expect(buttonList.elementAt(1).buttonText, 'Dismiss'); + expect(buttonList.elementAt(1).action, 'dismiss'); + expect(buttonList.elementAt(1).url, isNull); + expect(buttonList.elementAt(1).promptRemainsVisible, false); + + expect(buttonList.last.buttonText, 'More Info'); + expect(buttonList.last.action, 'snooze'); + expect(buttonList.last.url, + 'https://docs.flutter.dev/reference/crash-reporting'); + expect(buttonList.last.promptRemainsVisible, true); + }); + }); + + test('no survey returned from malformed json', () async { + // The date is not valid for the start date + await withClock(Clock.fixed(DateTime(2023, 3, 3)), () async { + analytics = Analytics.fake( + tool: DashTool.flutterTool, + homeDirectory: homeDirectory, + dartVersion: 'dartVersion', + fs: fs, + platform: DevicePlatform.macos, + surveyHandler: FakeSurveyHandler.fromString( + dismissedSurveyFile: dismissedSurveyFile, content: ''' +[ + { + "uniqueId": "uniqueId123", + "startDate": "NOT A REAL DATE", + "endDate": "2023-07-30T09:00:00-07:00", + "description": "Help improve Flutter's release builds with this 3-question survey!", + "snoozeForMinutes": "7200", + "samplingRate": "0.1", + "excludeDashTools": [], + "conditions": [ + { + "field": "logFileStats.recordCount", + "operator": ">=", + "value": 50 + } + ], + "buttons": [ + { + "buttonText": "Take Survey", + "action": "accept", + "url": "https://google.qualtrics.com/jfe/form/SV_5gsB2EuG5Et5Yy2", + "promptRemainsVisible": false + }, + { + "buttonText": "Dismiss", + "action": "dismiss", + "url": null, + "promptRemainsVisible": false + }, + { + "buttonText": "More Info", + "action": "snooze", + "url": "https://docs.flutter.dev/reference/crash-reporting", + "promptRemainsVisible": false + } + ] + } +] +'''), + ); + + // Simulate 60 events to send so that the first condition is satisified + for (var i = 0; i < 60; i++) { + analytics.send(testEvent); + } + + final fetchedSurveys = await analytics.fetchAvailableSurveys(); + + expect(fetchedSurveys.length, 0); + }); + }); + + test('returns two valid survey from json', () async { + await withClock(Clock.fixed(DateTime(2023, 3, 3)), () async { + analytics = Analytics.fake( + tool: DashTool.flutterTool, + homeDirectory: homeDirectory, + dartVersion: 'dartVersion', + fs: fs, + platform: DevicePlatform.macos, + surveyHandler: FakeSurveyHandler.fromString( + dismissedSurveyFile: dismissedSurveyFile, content: ''' +[ + { + "uniqueId": "12345", + "startDate": "2023-01-01T09:00:00-07:00", + "endDate": "2023-12-31T09:00:00-07:00", + "description": "xxxxxxx", + "snoozeForMinutes": "10", + "samplingRate": "1.0", + "excludeDashTools": [], + "conditions": [ + { + "field": "logFileStats.recordCount", + "operator": ">=", + "value": 50 + } + ], + "buttons": [] + }, + { + "uniqueId": "67890", + "startDate": "2023-01-01T09:00:00-07:00", + "endDate": "2023-12-31T09:00:00-07:00", + "description": "xxxxxxx", + "snoozeForMinutes": "10", + "samplingRate": "1.0", + "excludeDashTools": [], + "conditions": [ + { + "field": "logFileStats.recordCount", + "operator": ">=", + "value": 50 + } + ], + "buttons": [ + { + "buttonText": "More Info", + "action": "snooze", + "url": "https://docs.flutter.dev/reference/crash-reporting", + "promptRemainsVisible": true + } + ] + } +] +'''), + ); + + // Simulate 60 events to send so that the first condition is satisified + for (var i = 0; i < 60; i++) { + analytics.send(testEvent); + } + + final fetchedSurveys = await analytics.fetchAvailableSurveys(); + + expect(fetchedSurveys.length, 2); + + final firstSurvey = fetchedSurveys.first; + final secondSurvey = fetchedSurveys.last; + + expect(firstSurvey.uniqueId, '12345'); + expect(secondSurvey.uniqueId, '67890'); + + final secondSurveyButtons = secondSurvey.buttonList; + expect(secondSurveyButtons.length, 1); + expect(secondSurveyButtons.first.buttonText, 'More Info'); + expect(secondSurveyButtons.first.action, 'snooze'); + expect(secondSurveyButtons.first.url, + 'https://docs.flutter.dev/reference/crash-reporting'); + expect(secondSurveyButtons.first.promptRemainsVisible, true); + }); + }); + + test('valid survey not returned if opted out', () async { + await withClock(Clock.fixed(DateTime(2023, 3, 3)), () async { + analytics = Analytics.fake( + tool: DashTool.flutterTool, + homeDirectory: homeDirectory, + dartVersion: 'dartVersion', + fs: fs, + platform: DevicePlatform.macos, + surveyHandler: FakeSurveyHandler.fromList( + dismissedSurveyFile: dismissedSurveyFile, + initializedSurveys: <Survey>[ + Survey( + uniqueId: 'uniqueId', + startDate: DateTime(2023, 1, 1), + endDate: DateTime(2023, 12, 31), + description: 'description', + snoozeForMinutes: 10, + samplingRate: 1.0, + excludeDashToolList: [], + conditionList: <Condition>[ + Condition('logFileStats.recordCount', '>=', 50), + Condition('logFileStats.toolCount.flutter-tool', '>', 0), + ], + buttonList: [], + ), + ], + ), + ); + + // Simulate 60 events to send so that the first condition is satisified + for (var i = 0; i < 60; i++) { + analytics.send(testEvent); + } + + // Setting to false will prevent anything from getting returned + await analytics.setTelemetry(false); + var fetchedSurveys = await analytics.fetchAvailableSurveys(); + expect(fetchedSurveys.length, 0); + + // Setting telemetry back to true should enable the surveys to get + // returned again; we will also need to send the fake events again + // because on opt out, the log file will get cleared and one of + // the conditions for the fake survey loaded is that we need + // at least 50 records for one of the conditions + await analytics.setTelemetry(true); + for (var i = 0; i < 60; i++) { + analytics.send(testEvent); + } + fetchedSurveys = await analytics.fetchAvailableSurveys(); + expect(fetchedSurveys.length, 1); + }); + }); + + test('Sampling rate correctly returns a valid survey', () async { + // This test will use a predefined client ID string of `string1` + // which has been set in the setup along with a predefined + // string for the survey ID of `string2` to get a sample rate value + // + // The combination of `string1` and `string2` will return 0.40 + // from the sampleRate utility function so we have set the threshold + // to be 0.6 which should return surveys + await withClock(Clock.fixed(DateTime(2023, 3, 3)), () async { + final survey = Survey( + uniqueId: 'string2', + startDate: DateTime(2023, 1, 1), + endDate: DateTime(2023, 12, 31), + description: 'description', + snoozeForMinutes: 10, + samplingRate: 0.6, + excludeDashToolList: [], + conditionList: <Condition>[ + Condition('logFileStats.recordCount', '>=', 50), + Condition('logFileStats.toolCount.flutter-tool', '>', 0), + ], + buttonList: [], + ); + analytics = Analytics.fake( + tool: DashTool.flutterTool, + homeDirectory: homeDirectory, + dartVersion: 'dartVersion', + fs: fs, + platform: DevicePlatform.macos, + surveyHandler: FakeSurveyHandler.fromList( + dismissedSurveyFile: dismissedSurveyFile, + initializedSurveys: <Survey>[survey], + ), + ); + + // Simulate 60 events to send so that the first condition is satisified + for (var i = 0; i < 60; i++) { + analytics.send(testEvent); + } + + final fetchedSurveys = await analytics.fetchAvailableSurveys(); + + expect(survey.samplingRate, 0.6); + expect(fetchedSurveys.length, 1); + }); + }); + + test('Sampling rate filters out a survey', () async { + // We will reduce the survey's sampling rate to be 0.3 which is + // less than value returned from the predefined client ID and + // survey sample + await withClock(Clock.fixed(DateTime(2023, 3, 3)), () async { + final survey = Survey( + uniqueId: 'string2', + startDate: DateTime(2023, 1, 1), + endDate: DateTime(2023, 12, 31), + description: 'description', + snoozeForMinutes: 10, + samplingRate: 0.15, + excludeDashToolList: [], + conditionList: <Condition>[ + Condition('logFileStats.recordCount', '>=', 50), + Condition('logFileStats.toolCount.flutter-tool', '>', 0), + ], + buttonList: [], + ); + analytics = Analytics.fake( + tool: DashTool.flutterTool, + homeDirectory: homeDirectory, + dartVersion: 'dartVersion', + fs: fs, + platform: DevicePlatform.macos, + surveyHandler: FakeSurveyHandler.fromList( + dismissedSurveyFile: dismissedSurveyFile, + initializedSurveys: <Survey>[survey], + ), + ); + + // Simulate 60 events to send so that the first condition is satisified + for (var i = 0; i < 60; i++) { + analytics.send(testEvent); + } + + final fetchedSurveys = await analytics.fetchAvailableSurveys(); + + expect(survey.samplingRate, 0.15); + expect(fetchedSurveys.length, 0); + }); + }); + + test('Snoozing survey is successful with snooze timeout from survey', + () async { + expect(dismissedSurveyFile.readAsStringSync(), '{}', + reason: 'Should be an empty object'); + + // Initialize the survey class that we will use for this test + final minutesToSnooze = 30; + final surveyToLoad = Survey( + uniqueId: 'uniqueId', + startDate: DateTime(2023, 1, 1), + endDate: DateTime(2023, 12, 31), + description: 'description', + snoozeForMinutes: + minutesToSnooze, // Initialized survey with `minutesToSnooze` + samplingRate: 1.0, + excludeDashToolList: [], + conditionList: <Condition>[], + buttonList: [], + ); + + await withClock(Clock.fixed(DateTime(2023, 3, 3, 12, 0)), () async { + analytics = Analytics.fake( + tool: DashTool.flutterTool, + homeDirectory: homeDirectory, + dartVersion: 'dartVersion', + fs: fs, + platform: DevicePlatform.macos, + surveyHandler: FakeSurveyHandler.fromList( + dismissedSurveyFile: dismissedSurveyFile, + initializedSurveys: <Survey>[surveyToLoad], + ), + ); + + final fetchedSurveys = await analytics.fetchAvailableSurveys(); + expect(fetchedSurveys.length, 1); + + final survey = fetchedSurveys.first; + expect(survey.snoozeForMinutes, minutesToSnooze); + + // We will snooze the survey now and it should not show up + // if we fetch surveys again before the minutes to snooze time + // has finished + analytics.surveyShown(survey); + }); + + // This analytics instance will be simulated to be shortly after the first + // snooze, but before the snooze period has elapsed + await withClock(Clock.fixed(DateTime(2023, 3, 3, 12, 15)), () async { + analytics = Analytics.fake( + tool: DashTool.flutterTool, + homeDirectory: homeDirectory, + dartVersion: 'dartVersion', + fs: fs, + platform: DevicePlatform.macos, + surveyHandler: FakeSurveyHandler.fromList( + dismissedSurveyFile: dismissedSurveyFile, + initializedSurveys: <Survey>[surveyToLoad], + ), + ); + + final fetchedSurveys = await analytics.fetchAvailableSurveys(); + expect(fetchedSurveys.length, 0, + reason: 'The snooze period has not elapsed yet'); + }); + + // This analytics instance will be simulated to be after the snooze period + await withClock(Clock.fixed(DateTime(2023, 3, 3, 12, 35)), () async { + analytics = Analytics.fake( + tool: DashTool.flutterTool, + homeDirectory: homeDirectory, + dartVersion: 'dartVersion', + fs: fs, + platform: DevicePlatform.macos, + surveyHandler: FakeSurveyHandler.fromList( + dismissedSurveyFile: dismissedSurveyFile, + initializedSurveys: <Survey>[surveyToLoad], + ), + ); + + final fetchedSurveys = await analytics.fetchAvailableSurveys(); + expect(fetchedSurveys.length, 1, + reason: 'The snooze period has elapsed'); + }); + }); + + test('Dimissing permanently is successful', () async { + final minutesToSnooze = 10; + final surveyToLoad = Survey( + uniqueId: 'uniqueId', + startDate: DateTime(2023, 1, 1), + endDate: DateTime(2023, 12, 31), + description: 'description', + snoozeForMinutes: minutesToSnooze, + samplingRate: 1.0, + excludeDashToolList: [], + conditionList: <Condition>[], + buttonList: [ + SurveyButton( + buttonText: 'buttonText', + action: 'accept', + promptRemainsVisible: false, + ), + SurveyButton( + buttonText: 'buttonText', + action: 'dismiss', + promptRemainsVisible: false, + ), + ], + ); + + await withClock(Clock.fixed(DateTime(2023, 3, 3, 12, 0)), () async { + analytics = Analytics.fake( + tool: DashTool.flutterTool, + homeDirectory: homeDirectory, + dartVersion: 'dartVersion', + fs: fs, + platform: DevicePlatform.macos, + surveyHandler: FakeSurveyHandler.fromList( + dismissedSurveyFile: dismissedSurveyFile, + initializedSurveys: <Survey>[surveyToLoad], + ), + ); + + final fetchedSurveys = await analytics.fetchAvailableSurveys(); + expect(fetchedSurveys.length, 1); + + // Dismissing permanently will ensure that this survey is not + // shown again + final survey = fetchedSurveys.first; + analytics.surveyInteracted( + survey: survey, + surveyButton: survey.buttonList.first, + ); + }); + + // Moving out a week + await withClock(Clock.fixed(DateTime(2023, 3, 10, 12, 0)), () async { + analytics = Analytics.fake( + tool: DashTool.flutterTool, + homeDirectory: homeDirectory, + dartVersion: 'dartVersion', + fs: fs, + platform: DevicePlatform.macos, + surveyHandler: FakeSurveyHandler.fromList( + dismissedSurveyFile: dismissedSurveyFile, + initializedSurveys: <Survey>[surveyToLoad], + ), + ); + + final fetchedSurveys = await analytics.fetchAvailableSurveys(); + expect(fetchedSurveys.length, 0); + }); + }); + + test('malformed persisted json file for surveys', () async { + // When the survey handler encounters an error when parsing the + // persisted json file, it will reset it using the static method + // under the [Initializer] class and reset it to be an empty json object + final minutesToSnooze = 10; + final surveyToLoad = Survey( + uniqueId: 'uniqueId', + startDate: DateTime(2023, 1, 1), + endDate: DateTime(2023, 12, 31), + description: 'description', + snoozeForMinutes: minutesToSnooze, + samplingRate: 1.0, + excludeDashToolList: [], + conditionList: <Condition>[], + buttonList: [ + SurveyButton( + buttonText: 'buttonText', + action: 'accept', + promptRemainsVisible: false, + ), + SurveyButton( + buttonText: 'buttonText', + action: 'dismiss', + promptRemainsVisible: false, + ), + ], + ); + + await withClock(Clock.fixed(DateTime(2023, 3, 3, 12, 0)), () async { + analytics = Analytics.fake( + tool: DashTool.flutterTool, + homeDirectory: homeDirectory, + dartVersion: 'dartVersion', + fs: fs, + platform: DevicePlatform.macos, + surveyHandler: FakeSurveyHandler.fromList( + dismissedSurveyFile: dismissedSurveyFile, + initializedSurveys: <Survey>[surveyToLoad], + ), + ); + + final fetchedSurveys = await analytics.fetchAvailableSurveys(); + expect(fetchedSurveys.length, 1); + + // Dismissing permanently will ensure that this survey is not + // shown again + final survey = fetchedSurveys.first; + expect(survey.buttonList.length, 2); + analytics.surveyInteracted( + survey: survey, + surveyButton: survey.buttonList.first, + ); + }); + + // Purposefully write invalid json into the persisted file + dismissedSurveyFile.writeAsStringSync('{'); + + // Moving out a week + await withClock(Clock.fixed(DateTime(2023, 3, 10, 12, 0)), () async { + analytics = Analytics.fake( + tool: DashTool.flutterTool, + homeDirectory: homeDirectory, + dartVersion: 'dartVersion', + fs: fs, + platform: DevicePlatform.macos, + surveyHandler: FakeSurveyHandler.fromList( + dismissedSurveyFile: dismissedSurveyFile, + initializedSurveys: <Survey>[surveyToLoad], + ), + ); + + final fetchedSurveys = await analytics.fetchAvailableSurveys(); + expect(fetchedSurveys.length, 1); + }); + }); + + test('persisted json file goes missing handled', () async { + // If the persisted json file with the dismissed surveys is missing + // there should be error handling to recreate the file again with + // an empty json object + final minutesToSnooze = 10; + final surveyToLoad = Survey( + uniqueId: 'uniqueId', + startDate: DateTime(2023, 1, 1), + endDate: DateTime(2023, 12, 31), + description: 'description', + snoozeForMinutes: minutesToSnooze, + samplingRate: 1.0, + excludeDashToolList: [], + conditionList: <Condition>[], + buttonList: [ + SurveyButton( + buttonText: 'buttonText', + action: 'accept', + promptRemainsVisible: false, + ), + SurveyButton( + buttonText: 'buttonText', + action: 'dismiss', + promptRemainsVisible: false, + ), + ], + ); + + await withClock(Clock.fixed(DateTime(2023, 3, 3, 12, 0)), () async { + analytics = Analytics.fake( + tool: DashTool.flutterTool, + homeDirectory: homeDirectory, + dartVersion: 'dartVersion', + fs: fs, + platform: DevicePlatform.macos, + surveyHandler: FakeSurveyHandler.fromList( + dismissedSurveyFile: dismissedSurveyFile, + initializedSurveys: <Survey>[surveyToLoad], + ), + ); + + final fetchedSurveys = await analytics.fetchAvailableSurveys(); + expect(fetchedSurveys.length, 1); + + // Dismissing permanently will ensure that this survey is not + // shown again + final survey = fetchedSurveys.first; + expect(survey.buttonList.length, 2); + analytics.surveyInteracted( + survey: survey, + surveyButton: survey.buttonList.first, + ); + }); + + // Moving out a week + await withClock(Clock.fixed(DateTime(2023, 3, 10, 12, 0)), () async { + analytics = Analytics.fake( + tool: DashTool.flutterTool, + homeDirectory: homeDirectory, + dartVersion: 'dartVersion', + fs: fs, + platform: DevicePlatform.macos, + surveyHandler: FakeSurveyHandler.fromList( + dismissedSurveyFile: dismissedSurveyFile, + initializedSurveys: <Survey>[surveyToLoad], + ), + ); + + // Purposefully delete the file + dismissedSurveyFile.deleteSync(); + + final fetchedSurveys = await analytics.fetchAvailableSurveys(); + expect(fetchedSurveys.length, 1); + }); + }); + + test('Filtering out with excludeDashTool array', () async { + await withClock(Clock.fixed(DateTime(2023, 3, 3)), () async { + analytics = Analytics.fake( + tool: DashTool.flutterTool, + homeDirectory: homeDirectory, + dartVersion: 'dartVersion', + fs: fs, + platform: DevicePlatform.macos, + surveyHandler: FakeSurveyHandler.fromList( + dismissedSurveyFile: dismissedSurveyFile, + initializedSurveys: <Survey>[ + Survey( + uniqueId: 'uniqueId', + startDate: DateTime(2023, 1, 1), + endDate: DateTime(2023, 12, 31), + description: 'description', + snoozeForMinutes: 10, + samplingRate: 1.0, + // This should be the same as the tool in the + // Analytics constructor above + excludeDashToolList: [ + DashTool.flutterTool, + ], + conditionList: [], + buttonList: [ + SurveyButton( + buttonText: 'buttonText', + action: 'accept', + url: 'http://example.com', + promptRemainsVisible: false, + ), + ], + ), + ], + ), + ); + + final fetchedSurveys = await analytics.fetchAvailableSurveys(); + + expect(fetchedSurveys.length, 0); + }); + }); + + test( + 'Filter from excludeDashTool array does not ' + 'apply for different tool', () async { + await withClock(Clock.fixed(DateTime(2023, 3, 3)), () async { + analytics = Analytics.fake( + tool: DashTool.flutterTool, + homeDirectory: homeDirectory, + dartVersion: 'dartVersion', + fs: fs, + platform: DevicePlatform.macos, + surveyHandler: FakeSurveyHandler.fromList( + dismissedSurveyFile: dismissedSurveyFile, + initializedSurveys: <Survey>[ + Survey( + uniqueId: 'uniqueId', + startDate: DateTime(2023, 1, 1), + endDate: DateTime(2023, 12, 31), + description: 'description', + snoozeForMinutes: 10, + samplingRate: 1.0, + // This should be different from the tool in the + // Analytics constructor above + excludeDashToolList: [ + DashTool.devtools, + ], + conditionList: [], + buttonList: [ + SurveyButton( + buttonText: 'buttonText', + action: 'accept', + url: 'http://example.com', + promptRemainsVisible: false, + ), + ], + ), + ], + ), + ); + + final fetchedSurveys = await analytics.fetchAvailableSurveys(); + + expect(fetchedSurveys.length, 1); + + final survey = fetchedSurveys.first; + expect(survey.excludeDashToolList.length, 1); + expect(survey.excludeDashToolList.contains(DashTool.devtools), true); + }); + }); + }); +}
diff --git a/pkgs/unified_analytics/test/unified_analytics_test.dart b/pkgs/unified_analytics/test/unified_analytics_test.dart new file mode 100644 index 0000000..2e78df4 --- /dev/null +++ b/pkgs/unified_analytics/test/unified_analytics_test.dart
@@ -0,0 +1,1275 @@ +// 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. + +// ignore_for_file: lines_longer_than_80_chars, avoid_dynamic_calls + +import 'dart:convert'; +import 'dart:io' as io; +import 'dart:math'; + +import 'package:clock/clock.dart'; +import 'package:file/file.dart'; +import 'package:file/memory.dart'; +import 'package:test/test.dart'; +import 'package:unified_analytics/src/constants.dart'; +import 'package:unified_analytics/src/enums.dart'; +import 'package:unified_analytics/src/utils.dart'; +import 'package:unified_analytics/unified_analytics.dart'; +import 'package:yaml/yaml.dart'; + +void main() { + late MemoryFileSystem fs; + late Directory home; + late Directory dartToolDirectory; + late Analytics initializationAnalytics; + late FakeAnalytics analytics; + late File clientIdFile; + late File sessionFile; + late File configFile; + late File logFile; + late File dismissedSurveyFile; + + const homeDirName = 'home'; + const initialTool = DashTool.flutterTool; + const secondTool = DashTool.dartTool; + const toolsMessageVersion = 1; + const toolsMessage = 'toolsMessage'; + const flutterChannel = 'flutterChannel'; + const flutterVersion = 'flutterVersion'; + const dartVersion = 'dartVersion'; + const platform = DevicePlatform.macos; + const clientIde = 'VSCode'; + + final testEvent = Event.hotReloadTime(timeMs: 50); + + setUp(() { + // Setup the filesystem with the home directory + final fsStyle = + io.Platform.isWindows ? FileSystemStyle.windows : FileSystemStyle.posix; + fs = MemoryFileSystem.test(style: fsStyle); + home = fs.directory(homeDirName); + dartToolDirectory = home.childDirectory(kDartToolDirectoryName); + + // This is the first analytics instance that will be used to demonstrate + // that events will not be sent with the first run of analytics + initializationAnalytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + ); + expect(initializationAnalytics.shouldShowMessage, true); + initializationAnalytics.clientShowedMessage(); + expect(initializationAnalytics.shouldShowMessage, false); + + // The main analytics instance, other instances can be spawned within tests + // to test how to instances running together work + // + // This instance should have the same parameters as the one above for + // [initializationAnalytics] + analytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + clientIde: clientIde, + ); + analytics.clientShowedMessage(); + + // The 5 files that should have been generated + clientIdFile = home + .childDirectory(kDartToolDirectoryName) + .childFile(kClientIdFileName); + sessionFile = + home.childDirectory(kDartToolDirectoryName).childFile(kSessionFileName); + configFile = + home.childDirectory(kDartToolDirectoryName).childFile(kConfigFileName); + logFile = + home.childDirectory(kDartToolDirectoryName).childFile(kLogFileName); + dismissedSurveyFile = home + .childDirectory(kDartToolDirectoryName) + .childFile(kDismissedSurveyFileName); + }); + + test('Initializer properly sets up on first run', () { + expect(dartToolDirectory.existsSync(), true, + reason: 'The directory should have been created'); + expect(clientIdFile.existsSync(), true, + reason: 'The $kClientIdFileName file was not found'); + expect(sessionFile.existsSync(), true, + reason: 'The $kSessionFileName file was not found'); + expect(configFile.existsSync(), true, + reason: 'The $kConfigFileName was not found'); + expect(logFile.existsSync(), true, + reason: 'The $kLogFileName file was not found'); + expect(dismissedSurveyFile.existsSync(), true, + reason: 'The $dismissedSurveyFile file was not found'); + expect(dartToolDirectory.listSync().length, equals(5), + reason: + 'There should only be 5 files in the $kDartToolDirectoryName directory'); + expect(configFile.readAsLinesSync().length, + kConfigString.split('\n').length + 1, + reason: 'The number of lines should equal lines in constant value + 1 ' + 'for the initialized tool'); + }); + + test('Resetting session file when data is malformed', () { + // Purposefully write content to the session file that + // can't be decoded as an integer + sessionFile.writeAsStringSync('contents'); + + // Define the initial time to start + final start = DateTime(1995, 3, 3, 12, 0); + + // Set the clock to the start value defined above + withClock(Clock.fixed(start), () { + final timestamp = clock.now().millisecondsSinceEpoch.toString(); + expect(sessionFile.readAsStringSync(), 'contents'); + analytics.userProperty.preparePayload(); + expect(sessionFile.readAsStringSync(), + '{"session_id": $timestamp, "last_ping": $timestamp}'); + + analytics.sendPendingErrorEvents(); + + // Attempting to fetch the session id when malformed should also + // send an error event while parsing + final lastEvent = analytics.sentEvents.last; + expect(lastEvent, isNotNull); + expect(lastEvent.eventName, DashEvent.analyticsException); + expect( + lastEvent.eventData['workflow']!, 'UserProperty._refreshSessionData'); + expect(lastEvent.eventData['error']!, 'FormatException'); + }); + }); + + test('Handles malformed session file on startup', () { + // Ensure that we are able to send an error message on startup if + // we encounter an error while parsing the contents of the session file + // for session data + sessionFile.writeAsStringSync('not a valid session id'); + + analytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + clientIde: clientIde, + ); + analytics.clientShowedMessage(); + + // Invoking a send command should reset the session file to a good state + // + // Having it reformat the session file before any send event happens will just + // add additional work on startup + analytics.send(testEvent); + + analytics.sendPendingErrorEvents(); + final errorEvent = analytics.sentEvents + .where((element) => element.eventName == DashEvent.analyticsException) + .firstOrNull; + expect(errorEvent, isNotNull); + expect( + errorEvent!.eventData['workflow'], 'UserProperty._refreshSessionData'); + expect(errorEvent.eventData['error'], 'FormatException'); + expect(errorEvent.eventData['description'], + 'message: Unexpected character\nsource: not a valid session id'); + }); + + test('Resetting session file when file is removed', () { + // Purposefully write delete the file + sessionFile.deleteSync(); + + // Define the initial time to start + final start = DateTime(1995, 3, 3, 12, 0); + + // Set the clock to the start value defined above + withClock(Clock.fixed(start), () { + final timestamp = clock.now().millisecondsSinceEpoch.toString(); + expect(sessionFile.existsSync(), false); + analytics.userProperty.preparePayload(); + expect(sessionFile.readAsStringSync(), + '{"session_id": $timestamp, "last_ping": $timestamp}'); + + analytics.sendPendingErrorEvents(); + + // Attempting to fetch the session id when malformed should also + // send an error event while parsing + final lastEvent = analytics.sentEvents.last; + expect(lastEvent, isNotNull); + expect(lastEvent.eventName, DashEvent.analyticsException); + expect( + lastEvent.eventData['workflow']!, 'UserProperty._refreshSessionData'); + expect(lastEvent.eventData['error']!, 'FileSystemException'); + }); + }); + + test('New tool is successfully added to config file', () { + // Create a new instance of the analytics class with the new tool + final secondAnalytics = Analytics.fake( + tool: secondTool, + homeDirectory: home, + flutterChannel: 'ey-test-channel', + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: 'Flutter 3.6.0-7.0.pre.47', + dartVersion: 'Dart 2.19.0', + fs: fs, + platform: platform, + ); + secondAnalytics.clientShowedMessage(); + + expect(secondAnalytics.parsedTools.length, equals(2), + reason: 'There should be only 2 tools that have ' + 'been parsed into the config file'); + expect(secondAnalytics.parsedTools.containsKey(initialTool.label), true, + reason: 'The first tool: ${initialTool.label} should be in the map'); + expect(secondAnalytics.parsedTools.containsKey(secondTool.label), true, + reason: 'The second tool: $secondAnalytics should be in the map'); + expect(configFile.readAsStringSync().startsWith(kConfigString), true, + reason: + 'The config file should have the same message from the constants file'); + }); + + test('First time analytics run will not send events, second time will', () { + // Send an event with the first analytics class; this should result + // in no logs in the log file which keeps track of all the events + // that have been sent + initializationAnalytics.send(testEvent); + initializationAnalytics.send(testEvent); + + // Use the second instance of analytics defined in setUp() to send the actual + // events to simulate the second time the tool ran + analytics.send(testEvent); + + expect(logFile.readAsLinesSync().length, 1, + reason: 'The second analytics instance should have logged an event'); + }); + + test('Toggling telemetry boolean through Analytics class api', () async { + final originalClientId = clientIdFile.readAsStringSync(); + + expect(analytics.telemetryEnabled, true, + reason: 'Telemetry should be enabled by default ' + 'when initialized for the first time'); + // Use the API to disable analytics + expect(logFile.readAsLinesSync().length, 0); + await analytics.setTelemetry(false); + expect(analytics.telemetryEnabled, false, + reason: 'Analytics telemetry should be disabled'); + expect(logFile.readAsLinesSync().length, 0, + reason: 'Log file should have been cleared after opting out'); + expect(clientIdFile.readAsStringSync().length, 0, + reason: 'CLIENT ID file gets cleared on opt out'); + expect(sessionFile.readAsStringSync().length, 0, + reason: 'Session file gets cleared on opt out'); + + // Toggle it back to being enabled + await analytics.setTelemetry(true); + expect(analytics.telemetryEnabled, true, + reason: 'Analytics telemetry should be enabled'); + expect(logFile.readAsLinesSync().length, 1, + reason: 'There should only one event since it was cleared on opt out'); + expect(clientIdFile.readAsStringSync().length, greaterThan(0), + reason: 'CLIENT ID file gets regenerated on opt in'); + expect(sessionFile.readAsStringSync().length, greaterThan(0), + reason: 'Session file gets regenerated on opt in'); + + // Extract the last log item to check for the keys + final lastLogItem = + jsonDecode(logFile.readAsLinesSync().last) as Map<String, Object?>; + expect((lastLogItem['events'] as List).last['name'], + 'analytics_collection_enabled', + reason: 'Check on event name'); + expect((lastLogItem['events'] as List).last['params']['status'], true, + reason: 'Status should be false'); + expect((lastLogItem['client_id'] as String).isNotEmpty, true); + expect(originalClientId != lastLogItem['client_id'], true, + reason: 'When opting in again, the client id should be regenerated'); + }); + + test('Confirm client id is not empty string after opting in', () async { + await analytics.setTelemetry(false); + expect(logFile.readAsLinesSync().length, 0, + reason: 'Log file should have been cleared after opting out'); + expect(clientIdFile.readAsStringSync().length, 0, + reason: 'CLIENT ID file gets cleared on opt out'); + + // Start up a second instance to simulate starting another + // command being run + final secondAnalytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + ); + + // Setting telemetry back on will emit a new event + // where the client id string should not be empty + await secondAnalytics.setTelemetry(true); + expect(analytics.telemetryEnabled, true, + reason: 'Analytics telemetry should be enabled'); + expect(logFile.readAsLinesSync().length, 1, + reason: 'There should only one event since it was cleared on opt out'); + expect(clientIdFile.readAsStringSync().length, greaterThan(0), + reason: 'CLIENT ID file gets regenerated on opt in'); + + // Extract the last log item to check for the keys + final lastLogItem = + jsonDecode(logFile.readAsLinesSync().last) as Map<String, Object?>; + expect((lastLogItem['client_id'] as String).isNotEmpty, true, + reason: 'The client id should have been regenerated and ' + 'emitted in the opt in event'); + }); + + test( + 'Telemetry has been disabled by one ' + 'tool and second tool correctly shows telemetry is disabled', () async { + expect(analytics.telemetryEnabled, true, + reason: 'Analytics telemetry should be enabled on initialization'); + // Use the API to disable analytics + await analytics.setTelemetry(false); + expect(analytics.telemetryEnabled, false, + reason: 'Analytics telemetry should be disabled'); + + // Initialize a second analytics class, which simulates a second tool + // Create a new instance of the analytics class with the new tool + final secondAnalytics = Analytics.fake( + tool: secondTool, + homeDirectory: home, + flutterChannel: 'ey-test-channel', + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: 'Flutter 3.6.0-7.0.pre.47', + dartVersion: 'Dart 2.19.0', + fs: fs, + platform: platform, + ); + secondAnalytics.clientShowedMessage(); + + expect(secondAnalytics.telemetryEnabled, false, + reason: 'Analytics telemetry should be disabled by the first class ' + 'and the second class should show telemetry is disabled'); + }); + + test( + 'Two concurrent instances are running ' + 'and reflect an accurate up to date telemetry status', () async { + // Initialize a second analytics class, which simulates a second tool + final secondAnalytics = Analytics.fake( + tool: secondTool, + homeDirectory: home, + flutterChannel: 'ey-test-channel', + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: 'Flutter 3.6.0-7.0.pre.47', + dartVersion: 'Dart 2.19.0', + fs: fs, + platform: platform, + ); + secondAnalytics.clientShowedMessage(); + + expect(analytics.telemetryEnabled, true, + reason: 'Telemetry should be enabled on initialization for ' + 'first analytics instance'); + expect(secondAnalytics.telemetryEnabled, true, + reason: 'Telemetry should be enabled on initialization for ' + 'second analytics instance'); + + // Use the API to disable analytics on the first instance + await analytics.setTelemetry(false); + expect(analytics.telemetryEnabled, false, + reason: 'Analytics telemetry should be disabled on first instance'); + + expect(secondAnalytics.telemetryEnabled, false, + reason: 'Analytics telemetry should be disabled by the first class ' + 'and the second class should show telemetry is disabled' + ' by checking the timestamp on the config file'); + }); + + test('New line character is added if missing', () { + String currentConfigFileString; + + expect(configFile.readAsStringSync().endsWith('\n'), true, + reason: 'When initialized, the tool should correctly ' + 'add a trailing new line character'); + + // Remove the trailing new line character before initializing a second + // analytics class; the new class should correctly format the config file + currentConfigFileString = configFile.readAsStringSync(); + currentConfigFileString = currentConfigFileString.substring( + 0, currentConfigFileString.length - 1); + + // Write back out to the config file to be processed again + configFile.writeAsStringSync(currentConfigFileString); + + expect(configFile.readAsStringSync().endsWith('\n'), false, + reason: 'The trailing new line should be missing'); + + // Initialize a second analytics class, which simulates a second tool + // which should correct the missing trailing new line character + final secondAnalytics = Analytics.fake( + tool: secondTool, + homeDirectory: home, + flutterChannel: 'ey-test-channel', + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: 'Flutter 3.6.0-7.0.pre.47', + dartVersion: 'Dart 2.19.0', + fs: fs, + platform: platform, + ); + secondAnalytics.clientShowedMessage(); + + expect(secondAnalytics.telemetryEnabled, true); + + expect(configFile.readAsStringSync().endsWith('\n'), true, + reason: 'The second analytics class will correct ' + 'the missing new line character'); + }); + + test('Incrementing the version for a tool is successful', () { + expect(analytics.parsedTools[initialTool.label]?.versionNumber, + toolsMessageVersion, + reason: 'On initialization, the first version number should ' + 'be what is set in the setup method'); + + // Initialize a second analytics class for the same tool as + // the first analytics instance except with a newer version for + // the tools message and version + final secondAnalytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion + 1, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + ); + expect(secondAnalytics.shouldShowMessage, true); + expect(secondAnalytics.okToSend, false); + secondAnalytics.clientShowedMessage(); + expect(secondAnalytics.shouldShowMessage, false); + expect(secondAnalytics.okToSend, false, + reason: 'New version for the message will be treated as a first run'); + + expect(secondAnalytics.parsedTools[initialTool.label]?.versionNumber, + toolsMessageVersion + 1, + reason: + 'The second analytics instance should have incremented the version'); + }); + + test( + 'Config file resets when there is not exactly one match for the reporting flag', + () async { + // Write to the config file a string that is not formatted correctly + // (ie. there is more than one match for the reporting flag) + configFile.writeAsStringSync(''' +# INTRODUCTION +# +# This is the Flutter and Dart telemetry reporting +# configuration file. +# +# Lines starting with a #" are documentation that +# the tools maintain automatically. +# +# All other lines are configuration lines. They have +# the form "name=value". If multiple lines contain +# the same configuration name with different values, +# the parser will default to a conservative value. + +# DISABLING TELEMETRY REPORTING +# +# To disable telemetry reporting, set "reporting" to +# the value "0" and to enable, set to "1": +reporting=1 +reporting=1 + +# NOTIFICATIONS +# +# Each tool records when it last informed the user about +# analytics reporting and the privacy policy. +# +# The following tools have so far read this file: +# +# dart-tools (Dart CLI developer tool) +# devtools (DevTools debugging and performance tools) +# flutter-tools (Flutter CLI developer tool) +# +# For each one, the file may contain a configuration line +# where the name is the code in the list above, e.g. "dart-tool", +# and the value is a date in the form YYYY-MM-DD, a comma, and +# a number representing the version of the message that was +# displayed.'''); + + // Disable telemetry which should result in a reset of the config file + await analytics.setTelemetry(false); + + expect(configFile.readAsStringSync().startsWith(kConfigString), true, + reason: 'The tool should have reset the config file ' + 'because it was not formatted correctly'); + }); + + test('Config file resets when there is not exactly one match for the tool', + () { + // Write to the config file a string that is not formatted correctly + // (ie. there is more than one match for the reporting flag) + configFile.writeAsStringSync(''' +# INTRODUCTION +# +# This is the Flutter and Dart telemetry reporting +# configuration file. +# +# Lines starting with a #" are documentation that +# the tools maintain automatically. +# +# All other lines are configuration lines. They have +# the form "name=value". If multiple lines contain +# the same configuration name with different values, +# the parser will default to a conservative value. + +# DISABLING TELEMETRY REPORTING +# +# To disable telemetry reporting, set "reporting" to +# the value "0" and to enable, set to "1": +reporting=1 + +# NOTIFICATIONS +# +# Each tool records when it last informed the user about +# analytics reporting and the privacy policy. +# +# The following tools have so far read this file: +# +# dart-tools (Dart CLI developer tool) +# devtools (DevTools debugging and performance tools) +# flutter-tools (Flutter CLI developer tool) +# +# For each one, the file may contain a configuration line +# where the name is the code in the list above, e.g. "dart-tool", +# and the value is a date in the form YYYY-MM-DD, a comma, and +# a number representing the version of the message that was +# displayed. +${initialTool.label}=$dateStamp,$toolsMessageVersion +${initialTool.label}=$dateStamp,$toolsMessageVersion +'''); + + // Initialize a second analytics class for the same tool as + // the first analytics instance except with a newer version for + // the tools message and version + // + // This second instance should reset the config file when it goes + // to increment the version in the file + final secondAnalytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion + 1, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + ); + secondAnalytics.clientShowedMessage(); + + expect( + configFile.readAsStringSync(), + kConfigString, + reason: 'The config file should have been reset completely ' + 'due to a malformed file that contained two lines for the same tool', + ); + + // Creating a third instance after the second instance + // has reset the config file should include the newly added + // tool again with its incremented version number + final thirdAnalytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion + 1, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + ); + thirdAnalytics.clientShowedMessage(); + + expect( + configFile.readAsStringSync().endsWith( + '# displayed.\n${initialTool.label}=$dateStamp,${toolsMessageVersion + 1}\n'), + true, + reason: 'The config file ends with the correctly formatted ending ' + 'after removing the duplicate lines for a given tool', + ); + expect( + thirdAnalytics.parsedTools[initialTool.label]?.versionNumber, + toolsMessageVersion + 1, + reason: 'The new version should have been incremented', + ); + }); + + test('Check that UserProperty class has all the necessary keys', () { + const userPropertyKeys = <String>[ + 'session_id', + 'flutter_channel', + 'host', + 'flutter_version', + 'dart_version', + 'analytics_pkg_version', + 'tool', + 'local_time', + 'host_os_version', + 'locale', + 'client_ide', + 'enabled_features', + ]; + expect(analytics.userPropertyMap.keys.length, userPropertyKeys.length, + reason: 'There should only be ${userPropertyKeys.length} keys'); + for (final key in userPropertyKeys) { + expect(analytics.userPropertyMap.keys.contains(key), true, + reason: 'The $key variable is required'); + } + }); + + test('The minimum session duration should be at least 30 minutes', () { + expect(kSessionDurationMinutes < 30, false, + reason: 'Session is less than 30 minutes'); + }); + + test( + 'The session id stays the same when duration' + ' is less than the constraint', () { + // For this test, we will need control clock time so we will delete + // the [dartToolDirectory] and all of its contents and reconstruct a + // new [Analytics] instance at a specific time + dartToolDirectory.deleteSync(recursive: true); + expect(dartToolDirectory.existsSync(), false, + reason: 'The directory should have been cleared'); + + // Define the initial time to start + final start = DateTime(1995, 3, 3, 12, 0); + + // Set the clock to the start value defined above + withClock(Clock.fixed(start), () { + // This class will be constructed at a fixed time + final secondAnalytics = Analytics.fake( + tool: secondTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: 'Flutter 3.6.0-7.0.pre.47', + dartVersion: 'Dart 2.19.0', + fs: fs, + platform: platform, + ); + secondAnalytics.clientShowedMessage(); + + expect(secondAnalytics.userPropertyMap['session_id']?['value'], + start.millisecondsSinceEpoch); + expect(sessionFile.lastModifiedSync().millisecondsSinceEpoch, + start.millisecondsSinceEpoch); + }); + + // Add time to the start time that is less than the duration + final end = start.add(const Duration(minutes: kSessionDurationMinutes - 1)); + + // Use a new clock to ensure that the session id didn't change + withClock(Clock.fixed(end), () { + // A new instance will need to be created since the second + // instance in the previous block is scoped - this new instance + // should not reset the files generated by the second instance + final thirdAnalytics = Analytics.fake( + tool: secondTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: 'Flutter 3.6.0-7.0.pre.47', + dartVersion: 'Dart 2.19.0', + fs: fs, + platform: platform, + ); + thirdAnalytics.clientShowedMessage(); + + // Calling the send event method will result in the session file + // getting updated but because we use the `Analytics.fake()` constructor + // no events will be sent + thirdAnalytics.send(testEvent); + + expect(thirdAnalytics.userPropertyMap['session_id']?['value'], + start.millisecondsSinceEpoch, + reason: 'The session id should not have changed since it was made ' + 'within the duration'); + expect(sessionFile.lastModifiedSync().millisecondsSinceEpoch, + end.millisecondsSinceEpoch, + reason: 'The last modified value should have been updated'); + }); + }); + + test('The session id is refreshed once event is sent after duration', () { + // For this test, we will need control clock time so we will delete + // the [dartToolDirectory] and all of its contents and reconstruct a + // new [Analytics] instance at a specific time + dartToolDirectory.deleteSync(recursive: true); + expect(dartToolDirectory.existsSync(), false, + reason: 'The directory should have been cleared'); + + // Define the initial time to start + final start = DateTime(1995, 3, 3, 12, 0); + + // Set the clock to the start value defined above + withClock(Clock.fixed(start), () { + // This class will be constructed at a fixed time + final secondAnalytics = Analytics.fake( + tool: secondTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: 'Flutter 3.6.0-7.0.pre.47', + dartVersion: 'Dart 2.19.0', + fs: fs, + platform: platform, + ); + secondAnalytics.clientShowedMessage(); + + expect(secondAnalytics.userPropertyMap['session_id']?['value'], + start.millisecondsSinceEpoch); + expect(sessionFile.lastModifiedSync().millisecondsSinceEpoch, + start.millisecondsSinceEpoch); + + secondAnalytics.send(testEvent); + expect(sessionFile.readAsStringSync(), + '{"session_id": ${start.millisecondsSinceEpoch}, "last_ping": ${start.millisecondsSinceEpoch}}'); + }); + + // Add time to the start time that is less than the duration + final end = start.add(const Duration(minutes: kSessionDurationMinutes + 1)); + + // Use a new clock to ensure that the session id didn't change + withClock(Clock.fixed(end), () { + // A new instance will need to be created since the second + // instance in the previous block is scoped - this new instance + // should not reset the files generated by the second instance + final thirdAnalytics = Analytics.fake( + tool: secondTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: 'Flutter 3.6.0-7.0.pre.47', + dartVersion: 'Dart 2.19.0', + fs: fs, + platform: platform, + ); + thirdAnalytics.clientShowedMessage(); + + // Calling the send event method will result in the session file + // getting updated but because we use the `Analytics.fake()` constructor + // no events will be sent + thirdAnalytics.send(testEvent); + + expect(thirdAnalytics.userPropertyMap['session_id']?['value'], + end.millisecondsSinceEpoch, + reason: 'The session id should have changed since it was made ' + 'outside the duration'); + expect(sessionFile.lastModifiedSync().millisecondsSinceEpoch, + end.millisecondsSinceEpoch, + reason: 'The last modified value should have been updated'); + expect(sessionFile.readAsStringSync(), + '{"session_id": ${end.millisecondsSinceEpoch}, "last_ping": ${end.millisecondsSinceEpoch}}'); + }); + }); + + test('Validate the available enum types for DevicePlatform', () { + expect(DevicePlatform.values.length, 3, + reason: 'There should only be 3 supported device platforms'); + expect(DevicePlatform.values.contains(DevicePlatform.windows), true); + expect(DevicePlatform.values.contains(DevicePlatform.macos), true); + expect(DevicePlatform.values.contains(DevicePlatform.linux), true); + }); + + test('Validate the request body', () { + // Sample map for event data + final eventData = <String, dynamic>{ + 'time': 5, + 'command': 'run', + }; + + final Map<String, dynamic> body = generateRequestBody( + clientId: Uuid().generateV4(), + eventName: DashEvent.hotReloadTime, + eventData: eventData, + userProperty: analytics.userProperty, + ); + + // Checks for the top level keys + expect(body.containsKey('client_id'), true, + reason: '"client_id" is required at the top level'); + expect(body.containsKey('events'), true, + reason: '"events" is required at the top level'); + expect(body.containsKey('user_properties'), true, + reason: '"user_properties" is required at the top level'); + + // Regex for the client id + final clientIdPattern = RegExp( + r'^[0-9a-z]{8}\-[0-9a-z]{4}\-[0-9a-z]{4}\-[0-9a-z]{4}\-[0-9a-z]{12}$'); + + // Checks for the top level values + expect(body['client_id'].runtimeType, String, + reason: 'The client id must be a string'); + expect(clientIdPattern.hasMatch(body['client_id'] as String), true, + reason: 'The client id is not properly formatted, ie ' + '46cc0ba6-f604-4fd9-aa2f-8a20beb24cd4'); + expect( + (body['events'][0] as Map<String, dynamic>).containsKey('name'), true, + reason: 'Each event in the events array needs a name'); + expect( + (body['events'][0] as Map<String, dynamic>).containsKey('params'), true, + reason: 'Each event in the events array needs a params key'); + }); + + test('Check that log file is correctly persisting events sent', () { + final int numberOfEvents = max((kLogFileLength * 0.1).floor(), 5); + + for (var i = 0; i < numberOfEvents; i++) { + analytics.send(testEvent); + } + + expect(logFile.readAsLinesSync().length, numberOfEvents, + reason: 'The number of events should be $numberOfEvents'); + + // Add the max number of events to confirm it does not exceed the max + for (var i = 0; i < kLogFileLength; i++) { + analytics.send(testEvent); + } + + expect(logFile.readAsLinesSync().length, kLogFileLength, + reason: 'The number of events should be capped at $kLogFileLength'); + }); + + test('Check the query on the log file works as expected', () { + // Define a new clock so that we can check the output of the + // log file stats method explicitly + final start = DateTime(1995, 3, 3, 12, 0); + final firstClock = Clock.fixed(start); + + // Run with the simulated clock for the initial events + withClock(firstClock, () { + expect(analytics.logFileStats(), isNull, + reason: 'The result for the log file stats should be null when ' + 'there are no logs'); + analytics.send(testEvent); + + final firstQuery = analytics.logFileStats()!; + expect(firstQuery.sessionCount, 1, + reason: + 'There should only be one session after the initial send event'); + expect(firstQuery.flutterChannelCount, {'flutterChannel': 1}, + reason: 'There should only be one flutter channel logged'); + expect(firstQuery.toolCount, {'flutter-tool': 1}, + reason: 'There should only be one tool logged'); + }); + + // Define a new clock that is outside of the session duration + final secondClock = + start.add(const Duration(minutes: kSessionDurationMinutes + 1)); + + // Use the new clock to send an event that will change the session identifier + withClock(Clock.fixed(secondClock), () { + analytics.send(testEvent); + + final secondQuery = analytics.logFileStats()!; + + // Construct the expected response for the second query + expect(secondQuery.startDateTime, DateTime(1995, 3, 3, 12, 0)); + expect(secondQuery.minsFromStartDateTime, 31); + expect(secondQuery.endDateTime, DateTime(1995, 3, 3, 12, 31)); + expect(secondQuery.minsFromEndDateTime, 0); + expect(secondQuery.sessionCount, 2); + expect(secondQuery.flutterChannelCount, {'flutterChannel': 2}); + expect(secondQuery.toolCount, {'flutter-tool': 2}); + expect(secondQuery.recordCount, 2); + expect(secondQuery.eventCount, {'hot_reload_time': 2}); + }); + }); + + test('Check that the log file shows two different tools being used', () { + // Use a for loop two initialize the second analytics instance + // twice to account for no events being sent on the first instance + // run for a given tool + Analytics? secondAnalytics; + for (var i = 0; i < 2; i++) { + secondAnalytics = Analytics.fake( + tool: secondTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: 'Flutter 3.6.0-7.0.pre.47', + dartVersion: 'Dart 2.19.0', + fs: fs, + platform: platform, + ); + secondAnalytics.clientShowedMessage(); + } + + // Send events with both instances of the classes + analytics.send(testEvent); + secondAnalytics!.send(testEvent); + + // Query the log file stats to verify that there are two tools + final query = analytics.logFileStats()!; + + expect(query.toolCount, {'flutter-tool': 1, 'dart-tool': 1}, + reason: 'There should have been two tools in the persisted logs'); + }); + + test('Check that log data missing some keys results in null for stats', () { + // The following string represents a log item that is malformed (missing the `tool` key) + const malformedLog = '{"client_id":"d40133a0-7ea6-4347-b668-ffae94bb8774",' + '"events":[{"name":"hot_reload_time","params":{"time_ns":345}}],' + '"user_properties":{' + '"session_id":{"value":1675193534342},' + '"flutter_channel":{"value":"ey-test-channel"},' + '"host":{"value":"macOS"},' + '"flutter_version":{"value":"Flutter 3.6.0-7.0.pre.47"},' + '"dart_version":{"value":"Dart 2.19.0"},' + // '"tool":{"value":"flutter-tools"},' NEEDS REMAIN REMOVED + '"local_time":{"value":"2023-01-31 14:32:14.592898 -0500"}}}'; + + logFile.writeAsStringSync(malformedLog); + final query = analytics.logFileStats(); + + expect(query, isNull, + reason: + 'The query should be null because `tool` is missing under `user_properties`'); + }); + + test('Malformed local_time string should result in null for stats', () { + // The following string represents a log item that is malformed (missing the `tool` key) + const malformedLog = '{"client_id":"d40133a0-7ea6-4347-b668-ffae94bb8774",' + '"events":[{"name":"hot_reload_time","params":{"time_ns":345}}],' + '"user_properties":{' + '"session_id":{"value":1675193534342},' + '"flutter_channel":{"value":"ey-test-channel"},' + '"host":{"value":"macOS"},' + '"flutter_version":{"value":"Flutter 3.6.0-7.0.pre.47"},' + '"dart_version":{"value":"Dart 2.19.0"},' + '"tool":{"value":"flutter-tools"},' + '"local_time":{"value":"2023-xx-31 14:32:14.592898 -0500"}}}'; // PURPOSEFULLY MALFORMED + + logFile.writeAsStringSync(malformedLog); + final query = analytics.logFileStats(); + + expect(query, isNull, + reason: + 'The query should be null because the `local_time` value is malformed'); + }); + + test('Version is the same in the change log, pubspec, and constants.dart', + () { + // Parse the contents of the pubspec.yaml + final pubspecYamlString = io.File('pubspec.yaml').readAsStringSync(); + + // Parse into a yaml document to extract the version number + final doc = loadYaml(pubspecYamlString) as YamlMap; + final version = doc['version'] as String; + + expect(version, kPackageVersion, + reason: 'The package version in the pubspec and ' + 'constants.dart need to match\n' + 'Pubspec: $version && constants.dart: $kPackageVersion\n\n' + 'Make sure both are the same'); + + // Parse the contents of the change log file + final changeLogFirstLineString = + io.File('CHANGELOG.md').readAsLinesSync().first; + expect(changeLogFirstLineString.substring(3), kPackageVersion, + reason: 'The CHANGELOG.md file needs the first line to ' + 'be the same version as the pubspec and constants.dart'); + }); + + test('Null values for flutter parameters is reflected properly in log file', + () { + // Because we are using the `MemoryFileSystem.test` constructor, + // we don't have a real clock in the filesystem, and because we + // are checking the last modified timestamp for the session file + // to determine if we need to update the session id, manually setting + // that timestamp will ensure we are not updating session id when it + // first gets created + sessionFile.setLastModifiedSync(DateTime.now()); + + // Use a for loop two initialize the second analytics instance + // twice to account for no events being sent on the first instance + // run for a given tool + Analytics? secondAnalytics; + for (var i = 0; i < 2; i++) { + secondAnalytics = Analytics.fake( + tool: secondTool, + homeDirectory: home, + // flutterChannel: flutterChannel, THIS NEEDS TO REMAIN REMOVED + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: 'Flutter 3.6.0-7.0.pre.47', + dartVersion: 'Dart 2.19.0', + fs: fs, + platform: platform, + ); + secondAnalytics.clientShowedMessage(); + } + + // Send an event and check that the query stats reflects what is expected + secondAnalytics!.send(testEvent); + + // Query the log file stats to verify that there are two tools + final query = analytics.logFileStats()!; + + expect(query.toolCount, {'dart-tool': 1}, + reason: 'There should have only been on tool that sent events'); + expect(query.flutterChannelCount.isEmpty, true, + reason: + 'The instance does not have flutter information so it should be 0'); + + // Sending a query with the first analytics instance which has flutter information + // available should reflect in the query that there is 1 flutter channel present + analytics.send(testEvent); + final query2 = analytics.logFileStats()!; + + expect(query2.toolCount, {'dart-tool': 1, 'flutter-tool': 1}, + reason: 'Two different analytics instances have ' + 'been initialized and sent events'); + expect(query2.sessionCount, query.sessionCount, + reason: 'The session should have remained the same'); + expect(query2.flutterChannelCount, {'flutterChannel': 1}, + reason: 'The first instance has flutter information initialized'); + }); + + group('Testing against Google Analytics limitations:', () { + // Link to limitations documentation + // https://developers.google.com/analytics/devguides/collection/protocol/ga4/sending-events?client_type=gtag#limitations + // + // Only the limitations specified below have been added, the other + // are not able to be validated because it will vary by each tool + // + // 1. Events can have a maximum of 25 user properties + // 2. User property names must be 24 characters or fewer + // 3. (Only for `tool` name) User property values must be 36 characters or fewer + // 4. Event names must be 40 characters or fewer, may only contain alpha-numeric + // characters and underscores, and must start with an alphabetic character + test('max 25 user properties per event', () { + final Map<String, Object> userPropPayload = + analytics.userProperty.preparePayload(); + const maxUserPropKeys = 25; + + expect(userPropPayload.keys.length < maxUserPropKeys, true, + reason: 'There are too many keys in the UserProperty payload'); + }); + + test('max 24 characters for user prop keys', () { + final Map<String, Object> userPropPayload = + analytics.userProperty.preparePayload(); + const maxUserPropLength = 24; + + var userPropLengthValid = true; + final invalidUserProps = <String>[]; + for (final key in userPropPayload.keys) { + if (key.length > maxUserPropLength) { + userPropLengthValid = false; + invalidUserProps.add(key); + } + } + expect(userPropLengthValid, true, + reason: + 'The max length for each user prop is $maxUserPropLength chars\n' + 'The below keys are too long:\n$invalidUserProps'); + }); + + test('max 36 characters for user prop values (only `tool` key)', () { + // Checks item 3 + // All tools must be under 36 characters (and enforce each tool + // begins with a letter) + final toolLabelPattern = RegExp(r'^[a-zA-Z][a-zA-Z\_-]{0,35}$'); + var toolLengthValid = true; + final invalidTools = <DashTool>[]; + for (final tool in DashTool.values) { + if (!toolLabelPattern.hasMatch(tool.label)) { + toolLengthValid = false; + invalidTools.add(tool); + } + } + + expect(toolLengthValid, true, + reason: + 'All tool labels must be under 36 characters and begin with a letter\n' + 'The following are invalid\n$invalidTools'); + }); + + test('max 40 characters for event names', () { + // Check that each event name is less than 40 chars and starts with + // an alphabetic character; the entire string has to be alphanumeric + // and underscores + final eventLabelPattern = RegExp(r'^[a-zA-Z]{1}[a-zA-Z0-9\_]{0,39}$'); + var eventValid = true; + final invalidEvents = <DashEvent>[]; + for (final event in DashEvent.values) { + if (!eventLabelPattern.hasMatch(event.label)) { + eventValid = false; + invalidEvents.add(event); + } + } + + expect(eventValid, true, + reason: 'All event labels should have letters and underscores ' + 'as a delimiter if needed; invalid events below\n$invalidEvents'); + }); + }); + + test('Confirm credentials for GA', () { + expect(kGoogleAnalyticsApiSecret, 'Ka1jc8tZSzWc_GXMWHfPHA'); + expect(kGoogleAnalyticsMeasurementId, 'G-04BXPVBCWJ'); + }); + + test('Consent message is formatted correctly for the flutter tool', () { + // Retrieve the consent message for flutter tools + final consentMessage = analytics.getConsentMessage; + + expect(consentMessage, equalsIgnoringWhitespace(r''' +The Flutter CLI developer tool uses Google Analytics to report usage and diagnostic +data along with package dependencies, and crash reporting to send basic crash +reports. This data is used to help improve the Dart platform, Flutter framework, +and related tools. + +Telemetry is not sent on the very first run. To disable reporting of telemetry, +run this terminal command: + + flutter --disable-analytics + +If you opt out of telemetry, an opt-out event will be sent, and then no further +information will be sent. This data is collected in accordance with the Google +Privacy Policy (https://policies.google.com/privacy). +''')); + }); + + test('Consent message is formatted correctly for any tool other than flutter', + () { + // Create a new instance of the analytics class with the new tool + final secondAnalytics = Analytics.fake( + tool: secondTool, + homeDirectory: home, + flutterChannel: 'ey-test-channel', + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: 'Flutter 3.6.0-7.0.pre.47', + dartVersion: 'Dart 2.19.0', + fs: fs, + platform: platform, + ); + + // Retrieve the consent message for flutter tools + final consentMessage = secondAnalytics.getConsentMessage; + + expect(consentMessage, equalsIgnoringWhitespace(r''' +The Dart CLI developer tool uses Google Analytics to report usage and diagnostic +data along with package dependencies, and crash reporting to send basic crash +reports. This data is used to help improve the Dart platform, Flutter framework, +and related tools. + +Telemetry is not sent on the very first run. To disable reporting of telemetry, +run this terminal command: + + dart --disable-analytics + +If you opt out of telemetry, an opt-out event will be sent, and then no further +information will be sent. This data is collected in accordance with the Google +Privacy Policy (https://policies.google.com/privacy). +''')); + }); + + test('Equality operator works for identical events', () { + final eventOne = Event.clientRequest( + duration: 'duration', + latency: 'latency', + method: 'method', + ); + final eventTwo = Event.clientRequest( + duration: 'duration', + latency: 'latency', + method: 'method', + ); + + expect(eventOne == eventTwo, true); + }); + + test('Equality operator works for non-identical events', () { + final eventOne = Event.clientRequest( + duration: 'duration', + latency: 'latency', + method: 'method', + added: 'DIFFERENT FROM EVENT TWO', + ); + final eventTwo = Event.clientRequest( + duration: 'duration', + latency: 'latency', + method: 'method', + ); + + expect(eventOne == eventTwo, false); + }); + + test('Find a match for an event in a list of events', () { + final eventList = [ + Event.analyticsCollectionEnabled(status: true), + Event.memoryInfo(rss: 500), + Event.clientRequest( + duration: 'duration', latency: 'latency', method: 'method'), + ]; + + final eventToMatch = Event.memoryInfo(rss: 500); + + expect(eventList.contains(eventToMatch), true); + expect(eventList.where((element) => element == eventToMatch).length, 1); + }); + + group('Unit tests for util dartSDKVersion', () { + test('parses correctly for non-stable version', () { + final originalVersion = + '3.4.0-148.0.dev (dev) (Thu Feb 15 12:05:45 2024 -0800) on "macos_arm64"'; + + expect(parseDartSDKVersion(originalVersion), + '3.4.0 (build 3.4.0-148.0.dev)'); + }); + + test('parses correctly for stable version', () { + final originalVersion = + '3.3.0 (stable) (Tue Feb 13 10:25:19 2024 +0000) on "macos_arm64"'; + + expect(parseDartSDKVersion(originalVersion), '3.3.0'); + }); + }); +}
diff --git a/pkgs/unified_analytics/test/workflow_test.dart b/pkgs/unified_analytics/test/workflow_test.dart new file mode 100644 index 0000000..3a623a0 --- /dev/null +++ b/pkgs/unified_analytics/test/workflow_test.dart
@@ -0,0 +1,382 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:io' as io; + +import 'package:file/file.dart'; +import 'package:file/memory.dart'; +import 'package:test/test.dart'; +import 'package:unified_analytics/src/constants.dart'; +import 'package:unified_analytics/src/enums.dart'; +import 'package:unified_analytics/src/utils.dart'; +import 'package:unified_analytics/unified_analytics.dart'; + +void main() { + late MemoryFileSystem fs; + late Directory home; + late Directory dartToolDirectory; + late File clientIdFile; + late File sessionFile; + late File configFile; + late File logFile; + late File dismissedSurveyFile; + + const homeDirName = 'home'; + const initialTool = DashTool.flutterTool; + const secondTool = DashTool.dartTool; + const toolsMessageVersion = 1; + const toolsMessage = 'toolsMessage'; + const flutterChannel = 'flutterChannel'; + const flutterVersion = 'flutterVersion'; + const dartVersion = 'dartVersion'; + const platform = DevicePlatform.macos; + + final testEvent = Event.hotReloadTime(timeMs: 50); + + setUp(() { + // Setup the filesystem with the home directory + final fsStyle = + io.Platform.isWindows ? FileSystemStyle.windows : FileSystemStyle.posix; + fs = MemoryFileSystem.test(style: fsStyle); + home = fs.directory(homeDirName); + dartToolDirectory = home.childDirectory(kDartToolDirectoryName); + + // The 3 files that should have been generated + clientIdFile = home + .childDirectory(kDartToolDirectoryName) + .childFile(kClientIdFileName); + sessionFile = + home.childDirectory(kDartToolDirectoryName).childFile(kSessionFileName); + configFile = + home.childDirectory(kDartToolDirectoryName).childFile(kConfigFileName); + logFile = + home.childDirectory(kDartToolDirectoryName).childFile(kLogFileName); + dismissedSurveyFile = home + .childDirectory(kDartToolDirectoryName) + .childFile(kDismissedSurveyFileName); + }); + + test('Confirm workflow for first run', () { + final firstAnalytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + ); + + expect(firstAnalytics.shouldShowMessage, true); + expect(firstAnalytics.okToSend, false); + + firstAnalytics.clientShowedMessage(); + expect(firstAnalytics.shouldShowMessage, false); + expect(firstAnalytics.okToSend, false, + reason: 'On the first run, we should not be ok ' + 'to send any events, even if the user accepts'); + }); + + test('Confirm workflow for updated tools message version + new tool', () { + // Helper function to check the state of the instance + void checkAnalyticsInstance(Analytics instance) { + expect(instance.shouldShowMessage, true); + expect(instance.okToSend, false); + + instance.clientShowedMessage(); + expect(instance.shouldShowMessage, false); + expect(instance.okToSend, false, + reason: 'On the first run, we should not be ok ' + 'to send any events, even if the user accepts'); + } + + final firstAnalytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + ); + + checkAnalyticsInstance(firstAnalytics); + + // Instance where we increment the version of the message + final secondAnalytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion + 1, // Incrementing version + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + ); + + // Running the same checks for the second instance, it should + // behave the same as if it was a first run + checkAnalyticsInstance(secondAnalytics); + + // Instance for a different tool with the incremented version + final thirdAnalytics = Analytics.fake( + tool: secondTool, // Different tool + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion + 1, // Incrementing version + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + ); + + // The instance with a new tool getting onboarded should be + // treated the same as the 2 previous instances + checkAnalyticsInstance(thirdAnalytics); + }); + + test('Confirm workflow for checking tools into the config file', () { + final firstAnalytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + ); + + // Host of assertions to ensure all required artifacts + // are created + expect(dartToolDirectory.existsSync(), true, + reason: 'The directory should have been created'); + expect(clientIdFile.existsSync(), true, + reason: 'The $kClientIdFileName file was not found'); + expect(sessionFile.existsSync(), true, + reason: 'The $kSessionFileName file was not found'); + expect(configFile.existsSync(), true, + reason: 'The $kConfigFileName was not found'); + expect(logFile.existsSync(), true, + reason: 'The $kLogFileName file was not found'); + expect(dismissedSurveyFile.existsSync(), true, + reason: 'The $dismissedSurveyFile file was not found'); + expect( + dartToolDirectory.listSync().length, + equals(5), + reason: 'There should only be 5 files in the $kDartToolDirectoryName ' + 'directory', + ); + expect(configFile.readAsStringSync(), kConfigString); + + expect(firstAnalytics.shouldShowMessage, true); + + // Attempting to send a message with this instance should be + // blocked because it has not invoked `clientShowedMessage()` + // and it is the first run + // + // Even after invoking the method, it should be prevented from + // sending a message because it is the first time the tool was + // run in this instance + firstAnalytics.send(testEvent); + expect(logFile.readAsLinesSync().length, 0); + firstAnalytics.clientShowedMessage(); + + // Attempt to send two events, both should be blocked because it is + // part of the first instance + firstAnalytics.send(testEvent); + firstAnalytics.send(testEvent); + expect(logFile.readAsLinesSync().length, 0); + + // Creating a second analytics instance from the same tool now should + // allow for events to be sent + final secondAnalytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + ); + + expect(secondAnalytics.shouldShowMessage, false); + secondAnalytics.send(testEvent); + expect(logFile.readAsLinesSync().length, 1, + reason: 'Events will be blocked until invoking method ' + 'ensuring client has seen message'); + + secondAnalytics.send(testEvent); + secondAnalytics.send(testEvent); + expect(logFile.readAsLinesSync().length, 3); + + // Next, we will want to confirm that the message should be showing when + // a new analytics instance has been created with a newer version for + // message that should be shown + // + // In this case, it should be treated as a new tool being added for the + // first time and all events should be blocked + + // Delete the log file to reset the counter of events sent + logFile.deleteSync(); + final thirdAnalytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion + 1, // Incrementing version + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + ); + + expect(logFile.existsSync(), true, + reason: 'The $kLogFileName file was not found'); + expect(thirdAnalytics.shouldShowMessage, true, + reason: 'New version number should require showing message'); + thirdAnalytics.send(testEvent); + expect(logFile.readAsLinesSync().length, 0); + thirdAnalytics.clientShowedMessage(); + + // Attempt to send two events, both should be blocked because it is + // part of the third instance which has a new version for the consent + // message which will be treated as a new tool being onboarded + thirdAnalytics.send(testEvent); + thirdAnalytics.send(testEvent); + expect(logFile.readAsLinesSync().length, 0); + + // The fourth instance of the analytics class with the consent message + // version incremented should now be able to send messages + final fourthAnalytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion + 1, // Incrementing version + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + ); + + expect(fourthAnalytics.shouldShowMessage, false); + fourthAnalytics.send(testEvent); + expect(logFile.readAsLinesSync().length, 1, + reason: 'Events will be blocked until invoking method ' + 'ensuring client has seen message'); + + fourthAnalytics.send(testEvent); + fourthAnalytics.send(testEvent); + expect(logFile.readAsLinesSync().length, 3); + }); + + test('Disable second instance if first one did not show message', () { + final firstAnalytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + ); + + expect(firstAnalytics.shouldShowMessage, true); + + final secondAnalytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + ); + + expect(secondAnalytics.shouldShowMessage, true); + + secondAnalytics.clientShowedMessage(); + + final thirdAnalytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + ); + + expect(thirdAnalytics.shouldShowMessage, false); + }); + + test('Passing large version number gets logged in config', () { + final firstVersion = toolsMessageVersion + 3; + final secondAnalytics = Analytics.fake( + tool: secondTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: firstVersion, + toolsMessage: toolsMessage, + flutterVersion: 'Flutter 3.6.0-7.0.pre.47', + dartVersion: 'Dart 2.19.0', + fs: fs, + platform: platform, + ); + secondAnalytics.clientShowedMessage(); + + expect( + configFile + .readAsStringSync() + .endsWith('${secondTool.label}=$dateStamp,$firstVersion\n'), + true); + + // Create a new instane of the secondTool with an even + // bigger version + final secondVersion = firstVersion + 3; + final thirdAnalytics = Analytics.fake( + tool: secondTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: secondVersion, + toolsMessage: toolsMessage, + flutterVersion: 'Flutter 3.6.0-7.0.pre.47', + dartVersion: 'Dart 2.19.0', + fs: fs, + platform: platform, + ); + + expect( + configFile + .readAsStringSync() + .endsWith('${secondTool.label}=$dateStamp,$firstVersion\n'), + true); + + // After invoking this method, it will get updated + // in the config with the next version + thirdAnalytics.clientShowedMessage(); + + expect( + configFile + .readAsStringSync() + .endsWith('${secondTool.label}=$dateStamp,$secondVersion\n'), + true); + }); +}