diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 76ea14f1a3c..ce34d8f804a 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -7,25 +7,46 @@ body: - type: markdown attributes: value: | - ***Please note: No bug reports are currently being accepted for Wails v3*** - ***Please note: No bug reports are currently being accepted for Wails v3*** - ***Please note: No bug reports are currently being accepted for Wails v3*** Before submitting this issue, please do the following: - Do a web search for your error. This usually leads to a much better understanding of the issue. - - Prove that the error is indeed a Wails bug and not an application bug, with a specific set of steps to reproduce. + - Prove that the error is indeed a Wails bug and not an application bug, with a specific set of steps to reproduce. - Search the issue tracker using [this link](https://github.com/wailsapp/wails/issues?q=is%3Aissue+). - Search the [discussion forums](https://github.com/wailsapp/wails/discussions?discussions_q=type+your+issue+here). - - Read the [Troubleshooting Guide](https://wails.io/docs/next/guides/troubleshooting). + - For v3, check the [FAQ](https://v3.wails.io/faq/) and the [feedback guide](https://v3.wails.io/feedback/). For v2, read the [Troubleshooting Guide](https://wails.io/docs/guides/troubleshooting). - Create a [Minimal Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example) and link to it in the issue. - - If your issue is related to TypeScript generation, please open a ticket and create a PR with a failing test case. - TS tests can be found [here](https://github.com/wailsapp/wails/tree/master/v2/internal/binding/binding_test). Remember to add - your test to the `binding_test.go` file. - - Try to fix it yourself. Keep a list of things you have done to fix the problem. + - If your issue is related to the bindings or TypeScript generation, please open a ticket and create a PR with a failing test case. + For v3, the binding generator tests live [here](https://github.com/wailsapp/wails/tree/master/v3/internal/generator). + For v2 only, TS tests can be found [here](https://github.com/wailsapp/wails/tree/master/v2/internal/binding/binding_test). Remember to add your test to the `binding_test.go` file. + - Try to fix it yourself. Keep a list of things you have done to fix the problem. If after doing all the above, the problem remains, please continue with this ticket providing *all* the information requested. Bug reports that do not follow these steps will likely be closed, so please help us to help you. + - type: dropdown + id: version_family + attributes: + label: Wails version family + description: Which major version of Wails are you using? + options: + - v3 + - v2 + validations: + required: true + - type: dropdown + id: operating-system + attributes: + label: Operating System + description: Which operating system does the bug occur on? + options: + - Windows + - macOS + - Linux + - iOS (experimental) + - Android (experimental) + - Multiple / Other + validations: + required: true - type: textarea id: description attributes: @@ -75,7 +96,7 @@ body: id: systemdetails attributes: label: System Details - description: Please add the output of `wails doctor`. + description: Please add the output of `wails3 doctor` (for v2 projects, use `wails doctor`). render: shell validations: required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index e3632ecaae8..299ec7c4441 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,7 +1,7 @@ -blank_issues_enabled: true +blank_issues_enabled: false contact_links: - name: Discord Chat - url: https://discord.gg/BrRSWTaxVK + url: https://discord.gg/JDdSxwjhGf about: Ask questions and discuss with other Wails users in real time. - name: GitHub Community Discussions diff --git a/.github/ISSUE_TEMPLATE/documentation.yml b/.github/ISSUE_TEMPLATE/documentation.yml index c1259587b66..997fb40f83d 100644 --- a/.github/ISSUE_TEMPLATE/documentation.yml +++ b/.github/ISSUE_TEMPLATE/documentation.yml @@ -20,7 +20,7 @@ body: attributes: label: Have you read the Documentation Contribution Guidelines? options: - - label: I have read the [Documentation Contribution Guidelines](https://wails.io/community-guide#ways-of-contributing). + - label: I have read the [Documentation Contribution Guidelines](https://v3.wails.io/contributing/). required: true - type: textarea diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index b346c0bdc99..67d5ab0167e 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -8,7 +8,7 @@ body: attributes: value: | Before opening a feature request, please check the [Roadmap](https://github.com/wailsapp/wails/discussions/1484) to see if it has already been requested. - ***Please note: No new feature requests are being accepted for Wails v1*** + ***Please note: Enhancements should be discussed in [Ideas](https://github.com/wailsapp/wails/discussions/categories/ideas) on GitHub Discussions or on [Discord](https://discord.gg/JDdSxwjhGf) before opening a feature request. Substantial new functionality should be submitted as a [Wails Enhancement Proposal (WEP)](https://github.com/wailsapp/wails/blob/master/v3/wep/README.md). See the [feedback guide](https://v3.wails.io/feedback/) for details.*** - type: textarea attributes: diff --git a/.github/file-labeler.yml b/.github/file-labeler.yml index 69494cbae0d..d709c68139c 100644 --- a/.github/file-labeler.yml +++ b/.github/file-labeler.yml @@ -1,44 +1,63 @@ -# File path specific labels +# File path specific labels (actions/labeler v5 configuration format) v2-only: - - 'v2/**/*' + - changed-files: + - any-glob-to-any-file: + - 'v2/**/*' v3-alpha: - - 'v3/**/*' + - changed-files: + - any-glob-to-any-file: + - 'v3/**/*' windows: - - '**/*_windows.go' - - 'v2/internal/frontend/desktop/windows/**/*' + - changed-files: + - any-glob-to-any-file: + - '**/*_windows.go' + - 'v2/internal/frontend/desktop/windows/**/*' macos: - - '**/*_darwin.go' - - 'v2/internal/frontend/desktop/darwin/**/*' + - changed-files: + - any-glob-to-any-file: + - '**/*_darwin.go' + - 'v2/internal/frontend/desktop/darwin/**/*' linux: - - '**/*_linux.go' - - 'v2/internal/frontend/desktop/linux/**/*' + - changed-files: + - any-glob-to-any-file: + - '**/*_linux.go' + - 'v2/internal/frontend/desktop/linux/**/*' cli: - - 'v2/cmd/**/*' - - 'v3/cmd/**/*' - - '**/cli/**/*' - - '**/commands/**/*' - + - changed-files: + - any-glob-to-any-file: + - 'v2/cmd/**/*' + - 'v3/cmd/**/*' + - '**/cli/**/*' + - '**/commands/**/*' + documentation: - - '**/*.md' - - 'docs/**/*' - - 'website/**/*' - - 'mkdocs-website/**/*' + - changed-files: + - any-glob-to-any-file: + - '**/*.md' + - 'docs/**/*' + - 'website/**/*' + - 'mkdocs-website/**/*' templates: - - '**/templates/**/*' - - '**/template/**/*' + - changed-files: + - any-glob-to-any-file: + - '**/templates/**/*' + - '**/template/**/*' runtime: - - '**/runtime/**/*' - - 'v2/internal/runtime/**/*' - - 'v3/internal/runtime/**/*' - -bindings: - - 'v2/internal/binding/**/*' - - 'v3/internal/generator/**/*' + - changed-files: + - any-glob-to-any-file: + - '**/runtime/**/*' + - 'v2/internal/runtime/**/*' + - 'v3/internal/runtime/**/*' +bindings: + - changed-files: + - any-glob-to-any-file: + - 'v2/internal/binding/**/*' + - 'v3/internal/generator/**/*' diff --git a/.github/stale.yml b/.github/stale.yml deleted file mode 100644 index d8bcc83ec8c..00000000000 --- a/.github/stale.yml +++ /dev/null @@ -1,36 +0,0 @@ -# Number of days of inactivity before an issue becomes stale -daysUntilStale: 45 -# Number of days of inactivity before a stale issue is closed -daysUntilClose: 10 -# Issues with these labels will never be considered stale -exemptLabels: - - pinned - - security - - onhold - - inprogress - - "Selected For Development" - - bug - - enhancement - - v3-alpha - - high-priority -# Label to use when marking an issue as stale -staleLabel: "stale" -# Comment to post when marking an issue as stale. Set to `false` to disable -markComment: > - This issue has been automatically marked as stale because it has not had - recent activity. It will be closed if no further activity occurs within the next 10 days. - - If this issue is still relevant, please add a comment to keep it open. - Thank you for your contributions. -# Comment to post when closing a stale issue. Set to `false` to disable -closeComment: > - This issue has been automatically closed due to lack of activity. - Please feel free to reopen it if it's still relevant. -exemptMilestones: true -exemptAssignees: true -# Only mark issues (not PRs) -only: issues -# Exempt issues created before a certain date -exemptCreatedBefore: "2024-01-01T00:00:00Z" -# Starts checking issues only after the specified date -startDate: "2025-06-01T00:00:00Z" diff --git a/.github/workflows/auto-changelog-v3.yml b/.github/workflows/auto-changelog-v3.yml index 92ac295e83d..ef11f08a4b6 100644 --- a/.github/workflows/auto-changelog-v3.yml +++ b/.github/workflows/auto-changelog-v3.yml @@ -13,7 +13,7 @@ on: jobs: auto-changelog: - if: github.event.pull_request.merged == true || github.event_name == 'workflow_dispatch' + if: github.repository == 'wailsapp/wails' && (github.event.pull_request.merged == true || github.event_name == 'workflow_dispatch') runs-on: ubuntu-latest env: GOWORK: "off" diff --git a/.github/workflows/build-and-test-v3.yml b/.github/workflows/build-and-test-v3.yml index 14b2fb5f4a2..82dfa8d1bf8 100644 --- a/.github/workflows/build-and-test-v3.yml +++ b/.github/workflows/build-and-test-v3.yml @@ -7,9 +7,6 @@ on: - master paths: - 'v3/**' - - 'webview2/**' - - 'go.work' - - 'go.work.sum' - '.github/workflows/build-and-test-v3.yml' pull_request_review: types: [submitted] @@ -126,8 +123,6 @@ jobs: cache: true cache-dependency-path: | v3/go.sum - webview2/go.sum - go.work.sum - name: Install Task uses: arduino/setup-task@v2 @@ -237,8 +232,6 @@ jobs: cache: true cache-dependency-path: | v3/go.sum - webview2/go.sum - go.work.sum - name: Install Task uses: arduino/setup-task@v2 @@ -274,9 +267,6 @@ jobs: # Replace @wailsio/runtime version with local tarball npm pkg set dependencies.@wailsio/runtime="file://$RUNTIME_TGZ" cd .. - # Register the generated project in the workspace so Go 1.25 workspace - # mode does not reject packages in a module not listed in go.work. - go work use . wails3 build # GTK3 legacy template builds are covered by the Go example compilation tests above. diff --git a/.github/workflows/changelog-v3.yml b/.github/workflows/changelog-v3.yml index c6b1603d0a5..48c644c68d5 100644 --- a/.github/workflows/changelog-v3.yml +++ b/.github/workflows/changelog-v3.yml @@ -15,6 +15,7 @@ on: jobs: validate: runs-on: ubuntu-latest + if: github.repository == 'wailsapp/wails' env: GOWORK: "off" permissions: diff --git a/.github/workflows/cross-compile-test-v3.yml b/.github/workflows/cross-compile-test-v3.yml index fd774bef49b..bd2c42a0a3f 100644 --- a/.github/workflows/cross-compile-test-v3.yml +++ b/.github/workflows/cross-compile-test-v3.yml @@ -7,9 +7,6 @@ on: - master paths: - 'v3/**' - - 'webview2/**' - - 'go.work' - - 'go.work.sum' - '.github/workflows/cross-compile-test-v3.yml' workflow_dispatch: inputs: @@ -82,8 +79,6 @@ jobs: cache: true cache-dependency-path: | v3/go.sum - webview2/go.sum - go.work.sum - name: Install Task uses: arduino/setup-task@v2 diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml new file mode 100644 index 00000000000..b402be4ef00 --- /dev/null +++ b/.github/workflows/labeler.yml @@ -0,0 +1,36 @@ +name: Auto Labeler + +on: + issues: + types: [opened, edited] + pull_request_target: + +jobs: + issue-labeler: + name: Label issues + if: github.event_name == 'issues' + runs-on: ubuntu-latest + permissions: + contents: read + issues: write + steps: + - uses: github/issue-labeler@v3.4 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + configuration-path: .github/issue-labeler.yml + enable-versioned-regex: 0 + include-title: 1 + + pr-labeler: + name: Label pull requests + if: github.event_name == 'pull_request_target' + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + steps: + - uses: actions/labeler@v5 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + configuration-path: .github/file-labeler.yml + sync-labels: false diff --git a/.github/workflows/nightly-release-v3.yml b/.github/workflows/nightly-release-v3.yml index 13a17606e71..0cab4e525f5 100644 --- a/.github/workflows/nightly-release-v3.yml +++ b/.github/workflows/nightly-release-v3.yml @@ -19,6 +19,7 @@ on: jobs: nightly-release: runs-on: ubuntu-latest + if: github.repository == 'wailsapp/wails' env: GOWORK: "off" diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml index 180b211d1fa..86b405ec61c 100644 --- a/.github/workflows/publish-npm.yml +++ b/.github/workflows/publish-npm.yml @@ -3,6 +3,9 @@ on: branches: ['master'] paths: - 'v3/internal/runtime/desktop/@wailsio/runtime/**' + # Self-heal: if bundle bytes ever change on master without a matching + # source change, this rebuild overwrites them with source-derived output. + - 'v3/internal/assetserver/bundledassets/**' - '.github/workflows/publish-npm.yml' workflow_dispatch: @@ -13,7 +16,7 @@ concurrency: jobs: detect: name: Detect committed changes - if: github.event_name != 'workflow_dispatch' + if: github.repository == 'wailsapp/wails' && github.event_name != 'workflow_dispatch' outputs: changed: ${{ steps.package-json-changes.outputs.any_modified == 'true' || steps.source-changes.outputs.any_modified == 'true' }} runs-on: ubuntu-latest @@ -43,6 +46,7 @@ jobs: v3/internal/runtime/desktop/@wailsio/compiled/main.js v3/internal/runtime/desktop/@wailsio/runtime/tsconfig.json v3/internal/runtime/desktop/@wailsio/runtime/src/** + v3/internal/assetserver/bundledassets/** v3/pkg/events/events.txt v3/tasks/events/** @@ -50,7 +54,8 @@ jobs: name: Rebuild and publish needs: [detect] if: >- - !failure() && !cancelled() + github.repository == 'wailsapp/wails' + && !failure() && !cancelled() && (github.event_name == 'workflow_dispatch' || needs.detect.outputs.changed == 'true') runs-on: ubuntu-latest permissions: @@ -147,7 +152,20 @@ jobs: echo "Files committed back to master:" git status --short git commit -m "[skip ci] Publish @wailsio/runtime ${{ steps.bump-version.outputs.version }}" - git push + # master moves while this job runs (nightly release, auto-changelog + # commits), so a bare push races and gets rejected — which aborts the + # job before `npm publish` and leaves npm stale. Rebase and retry; + # a real conflict still fails loudly without publishing. + for attempt in 1 2 3 4 5; do + if git push; then + exit 0 + fi + echo "push rejected (attempt ${attempt}); rebasing onto current master" + git pull --rebase origin master + sleep $(( attempt * 5 )) + done + echo "::error::could not push the version bump after 5 attempts" + exit 1 - name: Publish npm package (Trusted Publishing / OIDC) # No NODE_AUTH_TOKEN/NPM_TOKEN: npm exchanges the GitHub OIDC token for a diff --git a/.github/workflows/release-v3.yml b/.github/workflows/release-v3.yml index 586a808345b..f8dd3832053 100644 --- a/.github/workflows/release-v3.yml +++ b/.github/workflows/release-v3.yml @@ -15,6 +15,16 @@ on: required: false default: true type: boolean + allow_unsigned_macos: + description: 'Publish unsigned, un-notarized macOS binaries (only if the Apple secrets are not configured yet)' + required: false + default: false + type: boolean + draft: + description: 'Create the release as a draft (use this to rehearse the release without publishing anything)' + required: false + default: false + type: boolean env: GO_VERSION: '1.25' @@ -25,9 +35,90 @@ permissions: contents: read jobs: + # ── Preflight: fail in seconds, not ten minutes into a build ───────────────── + # + # Everything here is a condition that would otherwise surface late and + # confusingly: a missing Apple secret shows up as an opaque `security import` + # error after three platforms have already built, and a version.txt that + # disagrees with the tag ships a binary that misreports itself with no error + # at all. + preflight: + name: Preflight + runs-on: ubuntu-latest + outputs: + tag: ${{ steps.meta.outputs.tag }} + pre_release: ${{ steps.meta.outputs.pre_release }} + sign_macos: ${{ steps.signing.outputs.sign_macos }} + steps: + - name: Resolve tag and pre-release flag + id: meta + run: | + if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then + TAG="${{ inputs.tag }}" + PRE="${{ inputs.pre_release }}" + else + TAG="${{ github.ref_name }}" + # Tags with a hyphen suffix (v3.0.0-beta.1) are pre-releases. + if [[ "$TAG" == *"-"* ]]; then PRE=true; else PRE=false; fi + fi + echo "tag=$TAG" >> "$GITHUB_OUTPUT" + echo "pre_release=$PRE" >> "$GITHUB_OUTPUT" + echo "Releasing $TAG (pre-release: $PRE)" + + - uses: actions/checkout@v4 + with: + ref: ${{ steps.meta.outputs.tag }} + + - name: Version file agrees with the tag + run: | + TAG="${{ steps.meta.outputs.tag }}" + FILE_VERSION="$(tr -d '[:space:]' < v3/internal/version/version.txt)" + # version.txt is embedded into the binary, so it is what `wails3 + # version` reports. If it disagrees with the tag, the release ships a + # binary that lies about which version it is, silently. + if [[ "$FILE_VERSION" != "$TAG" ]]; then + echo "::error::v3/internal/version/version.txt says '$FILE_VERSION' but the tag is '$TAG'." + echo "::error::The tagged commit must carry the matching version. Re-tag after bumping it." + exit 1 + fi + echo "version.txt matches the tag: $FILE_VERSION" + + - name: Apple signing credentials present + id: signing + env: + APPLE_SIGNING_CERT: ${{ secrets.APPLE_SIGNING_CERT }} + APPLE_CERT_PASSWORD: ${{ secrets.APPLE_CERT_PASSWORD }} + APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} + APPLE_NOTARIZE_USER: ${{ secrets.APPLE_NOTARIZE_USER }} + APPLE_NOTARIZE_PASSWORD: ${{ secrets.APPLE_NOTARIZE_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + run: | + MISSING=() + for name in APPLE_SIGNING_CERT APPLE_CERT_PASSWORD APPLE_SIGNING_IDENTITY \ + APPLE_NOTARIZE_USER APPLE_NOTARIZE_PASSWORD APPLE_TEAM_ID; do + [[ -z "${!name}" ]] && MISSING+=("$name") + done + + if [[ ${#MISSING[@]} -eq 0 ]]; then + echo "sign_macos=true" >> "$GITHUB_OUTPUT" + echo "All Apple signing secrets are configured." + exit 0 + fi + + if [[ "${{ inputs.allow_unsigned_macos }}" == "true" ]]; then + echo "sign_macos=false" >> "$GITHUB_OUTPUT" + echo "::warning::Missing Apple secrets (${MISSING[*]}). Publishing UNSIGNED macOS binaries because allow_unsigned_macos was set." + exit 0 + fi + + echo "::error::Missing repository secrets: ${MISSING[*]}" + echo "::error::macOS binaries cannot be signed or notarized without them. Configure them," + echo "::error::or re-run with allow_unsigned_macos=true to publish unsigned macOS binaries." + exit 1 # ── Linux binaries (native runners, CGO_ENABLED=0 for static binaries) ────── build-linux: name: Build Linux / ${{ matrix.arch }} + needs: preflight runs-on: ${{ matrix.runner }} strategy: fail-fast: false @@ -40,10 +131,9 @@ jobs: steps: - uses: actions/checkout@v4 with: - # On workflow_dispatch build the requested tag; on tag push inputs.tag - # is empty so github.ref (the tag) is used. Prevents building from the - # branch tip and publishing it under an unrelated tag. - ref: ${{ inputs.tag || github.ref }} + # Preflight resolved the tag for both trigger paths and proved it + # exists, so every job builds the same, verified source. + ref: ${{ needs.preflight.outputs.tag }} - uses: actions/setup-go@v5 with: @@ -73,14 +163,14 @@ jobs: # ── Windows binary ──────────────────────────────────────────────────────────── build-windows: name: Build Windows / amd64 + needs: preflight runs-on: windows-latest steps: - uses: actions/checkout@v4 with: - # On workflow_dispatch build the requested tag; on tag push inputs.tag - # is empty so github.ref (the tag) is used. Prevents building from the - # branch tip and publishing it under an unrelated tag. - ref: ${{ inputs.tag || github.ref }} + # Preflight resolved the tag for both trigger paths and proved it + # exists, so every job builds the same, verified source. + ref: ${{ needs.preflight.outputs.tag }} - uses: actions/setup-go@v5 with: @@ -105,14 +195,14 @@ jobs: # ── macOS: build amd64 + arm64, create universal binary, sign, notarize ────── build-sign-macos: name: Build, Sign & Notarize macOS + needs: preflight runs-on: macos-latest steps: - uses: actions/checkout@v4 with: - # On workflow_dispatch build the requested tag; on tag push inputs.tag - # is empty so github.ref (the tag) is used. Prevents building from the - # branch tip and publishing it under an unrelated tag. - ref: ${{ inputs.tag || github.ref }} + # Preflight resolved the tag for both trigger paths and proved it + # exists, so every job builds the same, verified source. + ref: ${{ needs.preflight.outputs.tag }} - uses: actions/setup-go@v5 with: @@ -141,6 +231,7 @@ jobs: run: lipo -create -output wails3-darwin-universal wails3-darwin-amd64 wails3-darwin-arm64 - name: Import signing certificate + if: needs.preflight.outputs.sign_macos == 'true' env: APPLE_SIGNING_CERT: ${{ secrets.APPLE_SIGNING_CERT }} APPLE_CERT_PASSWORD: ${{ secrets.APPLE_CERT_PASSWORD }} @@ -166,6 +257,7 @@ jobs: security list-keychain -d user -s "$KEYCHAIN_PATH" - name: Sign binaries + if: needs.preflight.outputs.sign_macos == 'true' env: APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} run: | @@ -179,6 +271,7 @@ jobs: done - name: Notarize macOS binaries + if: needs.preflight.outputs.sign_macos == 'true' env: APPLE_NOTARIZE_USER: ${{ secrets.APPLE_NOTARIZE_USER }} APPLE_NOTARIZE_PASSWORD: ${{ secrets.APPLE_NOTARIZE_PASSWORD }} @@ -206,29 +299,13 @@ jobs: # ── Create GitHub Release and attach all binaries ──────────────────────────── release: name: Publish Release - needs: [build-linux, build-windows, build-sign-macos] + needs: [preflight, build-linux, build-windows, build-sign-macos] runs-on: ubuntu-latest permissions: contents: write + id-token: write # OIDC identity for the provenance attestation + attestations: write steps: - - name: Determine release tag and pre-release flag - id: meta - run: | - if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then - TAG="${{ github.event.inputs.tag }}" - PRE="${{ github.event.inputs.pre_release }}" - else - TAG="${{ github.ref_name }}" - # Treat tags with a hyphen suffix (e.g. v3.0.0-beta.1) as pre-releases - if [[ "$TAG" == *"-"* ]]; then - PRE=true - else - PRE=false - fi - fi - echo "tag=$TAG" >> "$GITHUB_OUTPUT" - echo "pre_release=$PRE" >> "$GITHUB_OUTPUT" - - name: Download all artifacts uses: actions/download-artifact@v4 with: @@ -238,11 +315,29 @@ jobs: - name: List artifacts run: ls -lh dist/ + - name: Generate checksums + working-directory: dist + run: | + # Users have no way to verify a download without these, and generating + # them anywhere other than the job that publishes the binaries defeats + # the point. + sha256sum -- * > SHA256SUMS + cat SHA256SUMS + + - name: Attest build provenance + uses: actions/attest-build-provenance@v4 + with: + # Signed statement of which source, builder and workflow produced each + # binary. The npm package already ships provenance; the binaries + # lagging behind it is an inconsistency users can see. + subject-path: 'dist/wails3-*' + - name: Create or update GitHub Release env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - TAG: ${{ steps.meta.outputs.tag }} - PRE: ${{ steps.meta.outputs.pre_release }} + TAG: ${{ needs.preflight.outputs.tag }} + PRE: ${{ needs.preflight.outputs.pre_release }} + DRAFT: ${{ inputs.draft }} run: | FLAGS=( --repo "${{ github.repository }}" @@ -250,6 +345,10 @@ jobs: --generate-notes ) [[ "$PRE" == "true" ]] && FLAGS+=(--prerelease) + # A draft release is visible only to maintainers and can be deleted, + # which is what makes rehearsing the whole path possible without + # publishing anything. + [[ "$DRAFT" == "true" ]] && FLAGS+=(--draft) # Fail fast if the tag does not exist. Otherwise `gh release create` # would create the tag at an arbitrary commit and publish a release diff --git a/.github/workflows/verify-runtime-assets.yml b/.github/workflows/verify-runtime-assets.yml new file mode 100644 index 00000000000..5832a3c6383 --- /dev/null +++ b/.github/workflows/verify-runtime-assets.yml @@ -0,0 +1,81 @@ +name: Verify Runtime Assets + +# The bundled runtime (v3/internal/assetserver/bundledassets) is go:embed'ed +# into every Wails v3 application, and minified JS cannot be reviewed by eye. +# This check treats those files as an internal build product: any PR that +# touches them, or the source they are built from, must contain exactly the +# bytes a clean rebuild of that PR's source produces. Runs with a read-only +# token and no secrets, so building untrusted PR source here is safe. +# +# The job runs on every PR (and self-skips when no runtime paths changed) so +# it can be marked as a required status check without wedging unrelated PRs. + +on: + pull_request: + branches: [master] + +permissions: + contents: read + +concurrency: + group: verify-runtime-assets-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + verify: + name: Bundled runtime matches source + runs-on: ubuntu-latest + steps: + - name: Checkout PR merge result + uses: actions/checkout@v4 + with: + fetch-depth: 2 + + - name: Detect runtime asset or source changes + id: changed + run: | + # HEAD is the PR merge commit; HEAD^1 is the base branch tip. + if git diff --name-only HEAD^1 HEAD -- \ + 'v3/internal/assetserver/bundledassets' \ + 'v3/internal/runtime' | grep -q .; then + echo "relevant=true" >> "$GITHUB_OUTPUT" + else + echo "relevant=false" >> "$GITHUB_OUTPUT" + echo "No bundled-runtime or runtime-source changes; nothing to verify." + fi + + - name: Use Node.js 22 + if: steps.changed.outputs.relevant == 'true' + uses: actions/setup-node@v4 + with: + node-version: "22" + + - name: Install Task + if: steps.changed.outputs.relevant == 'true' + uses: arduino/setup-task@v2 + with: + version: 3.x + repo-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Install runtime dependencies (lockfile-exact) + if: steps.changed.outputs.relevant == 'true' + working-directory: v3/internal/runtime/desktop/@wailsio/runtime + run: npm ci + + - name: Rebuild bundled runtime from PR source + if: steps.changed.outputs.relevant == 'true' + working-directory: v3 + run: task runtime:build:assets + + - name: Verify committed bundles match the rebuild + if: steps.changed.outputs.relevant == 'true' + run: | + if ! git diff --exit-code -- v3/internal/assetserver/bundledassets; then + echo "::error::Committed bundled runtime does not match a clean rebuild of this PR's source." + echo "::error::Never hand-edit v3/internal/assetserver/bundledassets. To regenerate:" + echo "::error:: cd v3/internal/runtime/desktop/@wailsio/runtime && npm ci" + echo "::error:: cd ../../../.. && task runtime:build:assets # from the v3 directory" + echo "::error::then commit the result." + exit 1 + fi + echo "Bundled runtime matches its source." diff --git a/.gitignore b/.gitignore index 61efe756b07..c1b4664c5dc 100644 --- a/.gitignore +++ b/.gitignore @@ -95,3 +95,7 @@ v2/cmd/wails/internal/commands/initialise/templates/testtemplates/ # Ignore local iOS test app /v3/testiosapp/ + +# Local Go workspaces are a per-developer concern, not part of the source +go.work +go.work.sum diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000000..3259accfbc4 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,132 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances + of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official email address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +coc@wails.io. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 97c95dbcdd6..816973ad4ef 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -15,7 +15,7 @@ Thanks for your interest in contributing! Wails has two active tracks. Pick the - Docs: [v3.wails.io](https://v3.wails.io/). - Detailed contributor guide: [v3.wails.io/contributing](https://v3.wails.io/contributing/). - Changelog: v3 entries are added automatically from your PR on merge. To control the wording, add your own entry to `v3/UNRELEASED_CHANGELOG.md` and the automation will use it instead. -- **Enhancements require prior discussion** on [Discord](https://discord.gg/JDdSxwjhGf) — see the [feedback guide](https://v3.wails.io/getting-started/feedback/). +- **Enhancements require prior discussion** in [Ideas](https://github.com/wailsapp/wails/discussions/categories/ideas) on GitHub Discussions (see the [feedback guide](https://v3.wails.io/feedback/)). Substantial new functionality goes through the [Wails Enhancement Proposal (WEP) process](v3/wep/README.md). ## Pull request checklist diff --git a/docs/src/assets/windows-native-non-client-regions/wails-app-region.mp4 b/docs/src/assets/windows-native-non-client-regions/wails-app-region.mp4 new file mode 100644 index 00000000000..c399b404ea4 Binary files /dev/null and b/docs/src/assets/windows-native-non-client-regions/wails-app-region.mp4 differ diff --git a/docs/src/content/docs/changelog.mdx b/docs/src/content/docs/changelog.mdx index 8d2d3f5dbc1..5425ac6628a 100644 --- a/docs/src/content/docs/changelog.mdx +++ b/docs/src/content/docs/changelog.mdx @@ -31,6 +31,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 */ ## [Unreleased] +## v3.0.0-alpha2.117 - 2026-07-08 + +## Added +- Implement custom hit-test logic for non-client regions on Windows in [PR](https://github.com/wailsapp/wails/pull/5462) by @savely-krasovsky + +## Changed +- Configure WebView2 monitor-scale detection based on UseVisualHosting in [PR](https://github.com/wailsapp/wails/pull/5761) by @wayneforrest + +## v3.0.0-alpha2.116 - 2026-07-07 + +## Added +- Update FAQ documentation to focus on Wails v3 features and guidance in [PR](https://github.com/wailsapp/wails/pull/5763) by @taliesin-ai + +## v3.0.0-alpha2.115 - 2026-07-06 + +## Fixed +- Fix `Menu.Update()` not rebuilding the native menu on GTK4 Linux (#5659, independently diagnosed and fixed by @puneetdixit200 in #5539) +- Fix crash enumerating macOS screens on display change by copying screen id/name strings and snapshotting the count (#5565, independently diagnosed and fixed by @x-haose in #5584) +- Fix crash on Windows when `WM_ERASEBKGND` paints a solid background during a minimise/restore transition where `GetClientRect` returns nil (guard reported by @sinspired in #5636) +- Fix frontend bindings error always parses as text by @mbaklor in #5690 +- Fix Windows build failure when using the `server` build tag, caused by Windows GUI files missing the `!server` build constraint that the macOS and Linux equivalents already have (#5680) + ## v3.0.0-alpha2.114 - 2026-07-05 ## Added diff --git a/docs/src/content/docs/contributing.mdx b/docs/src/content/docs/contributing.mdx index 841c3028298..607b24a1197 100644 --- a/docs/src/content/docs/contributing.mdx +++ b/docs/src/content/docs/contributing.mdx @@ -38,6 +38,18 @@ Contribute code through pull requests: - Performance improvements - Tests +### 4. Propose an Enhancement (WEP) + +Substantial new functionality goes through the Wails Enhancement Proposal (WEP) process. It keeps feature development transparent and ensures every accepted proposal has community support and an implementor. In short: + +1. Optionally float your idea in the [Ideas](https://github.com/wailsapp/wails/discussions/categories/ideas) category on GitHub Discussions or on [Discord](https://discord.gg/JDdSxwjhGf) to gauge interest. +2. Copy [`v3/wep/WEP_TEMPLATE.md`](https://github.com/wailsapp/wails/blob/master/v3/wep/WEP_TEMPLATE.md) to `v3/wep/proposals//proposal.md` and fill in every section. +3. Open a draft pull request titled `[WEP] ` containing only the proposal. The PR is the official place to discuss it. +4. Gather feedback and support (comments and thumbs-up reactions on the PR). Allow at least two weeks for discussion, and agree on who will implement the proposal. +5. Mark the PR ready for review. The maintainers make the final decision: accepted proposals are assigned a WEP number and merged. + +The full process is documented in [`v3/wep/README.md`](https://github.com/wailsapp/wails/blob/master/v3/wep/README.md). + ## Getting Started ### Fork and Clone @@ -241,7 +253,7 @@ npm run dev ### Code of Conduct -Be respectful, inclusive, and professional. We're all here to build great software together. +Be respectful, inclusive, and professional. We're all here to build great software together. See the [Code of Conduct](https://github.com/wailsapp/wails/blob/master/CODE_OF_CONDUCT.md) for details. ## Recognition diff --git a/docs/src/content/docs/features/bindings/methods.mdx b/docs/src/content/docs/features/bindings/methods.mdx index 986f9847dfe..1997a6ae78b 100644 --- a/docs/src/content/docs/features/bindings/methods.mdx +++ b/docs/src/content/docs/features/bindings/methods.mdx @@ -400,6 +400,8 @@ func (d *DatabaseService) GetUser(id int) (*User, error) { ### JavaScript Side +When a bound method fails, the returned promise rejects with a JavaScript `Error` object: + ```javascript import { GetUser } from './bindings/changeme/databaseservice' @@ -407,15 +409,104 @@ try { const user = await GetUser(123) console.log("User:", user) } catch (error) { - console.error("Error:", error) - // Error: "user 123 not found" + console.error(error.message) + // "user 123 not found" +} +``` + +The runtime throws a different error type depending on what went wrong: + +| Error type | Thrown when | +|----------------|------------------------------------------------------------------------------------------------| +| `TypeError` | The call has the wrong number of arguments, or an argument cannot be converted to the Go type | +| `RuntimeError` | The method returned an error, or panicked while running | +| `Error` | Any other failure, for example a call to a method that does not exist | + +Every error provides: +- `name`: the error type from the table above +- `message`: the message of the Go error +- `cause`: the Go error serialised as JSON, where available. If the method returned multiple errors, `cause` is an array with one entry per error. + +The `RuntimeError` class is exported by the `@wailsio/runtime` package, so you can distinguish errors returned by your Go code from other failures: + +```javascript +import { Call } from '@wailsio/runtime' +import { GetUser } from './bindings/changeme/databaseservice' + +try { + const user = await GetUser(123) +} catch (error) { + if (error instanceof Call.RuntimeError) { + // GetUser returned an error + } else { + // The call itself failed + } +} +``` + +:::note +In earlier versions of the runtime, every failed call rejected with a plain `Error` whose message contained the raw JSON of the underlying error. +::: + +### Structured Error Data + +Returning a custom error type from Go makes its JSON form available on the `cause` property of the thrown error: + +```go +type ValidationError struct { + Field string `json:"field"` + Reason string `json:"reason"` +} + +func (e *ValidationError) Error() string { + return fmt.Sprintf("%s: %s", e.Field, e.Reason) +} + +func (s *UserService) UpdateEmail(id int, email string) error { + if !strings.Contains(email, "@") { + return &ValidationError{Field: "email", Reason: "invalid email address"} + } + // ... + return nil +} +``` + +```javascript +import { UpdateEmail } from './bindings/changeme/userservice' + +try { + await UpdateEmail(1, "not-an-email") +} catch (error) { + console.log(error.message) // "email: invalid email address" + console.log(error.cause) // { field: "email", reason: "invalid email address" } } ``` -**Error types:** -- Go `error` → JavaScript exception -- Error message preserved -- Stack trace available +Errors are serialised with the standard `encoding/json` package, so only exported fields are included. Errors created with `errors.New` or `fmt.Errorf` have no exported fields and serialise as an empty object. + +For full control over how errors are serialised, provide a `MarshalError` function in the service options: + +```go +app := application.New(application.Options{ + Services: []application.Service{ + application.NewServiceWithOptions(&UserService{}, application.ServiceOptions{ + MarshalError: func(err error) []byte { + var validationErr *ValidationError + if errors.As(err, &validationErr) { + data, _ := json.Marshal(map[string]string{ + "type": "validation", + "field": validationErr.Field, + }) + return data + } + return nil // fall back to the default serialisation + }, + }), + }, +}) +``` + +`MarshalError` must return valid JSON, or `nil` to fall back to the default serialisation. ## Performance diff --git a/docs/src/content/docs/features/windows/basics.mdx b/docs/src/content/docs/features/windows/basics.mdx index 55a3f623096..0d5bd935f2d 100644 --- a/docs/src/content/docs/features/windows/basics.mdx +++ b/docs/src/content/docs/features/windows/basics.mdx @@ -403,7 +403,7 @@ mainWindow.AttachModal(childWindow) There is no per-window `SetIcon` — the application icon is set on the app via `app.SetIcon([]byte)` (or for a Linux-specific window icon, the `application.LinuxWindow.Icon` field at window creation). **Snap Assist:** - Shows Windows 11 snap layout options for the window. + Shows Windows 11 snap layout options through the system shortcut path. For a custom HTML maximize button with native hover Snap Layouts, use [Native Non-Client Regions on Windows](/features/windows/frameless#native-non-client-regions-on-windows) instead. **Taskbar flashing:** Useful for notifications when window is minimised. diff --git a/docs/src/content/docs/features/windows/frameless.mdx b/docs/src/content/docs/features/windows/frameless.mdx index 0a22a7b763a..aadea7f314e 100644 --- a/docs/src/content/docs/features/windows/frameless.mdx +++ b/docs/src/content/docs/features/windows/frameless.mdx @@ -6,6 +6,7 @@ sidebar: --- import { Tabs, TabItem, Card, CardGrid } from "@astrojs/starlight/components"; +import wailsAppRegionVideo from "../../../../assets/windows-native-non-client-regions/wails-app-region.mp4"; ## Frameless Windows @@ -173,6 +174,156 @@ document.querySelector('.maximize').addEventListener('click', () => Window.Maxim document.querySelector('.close').addEventListener('click', () => Window.Close()) ``` +## Native Non-Client Regions on Windows + +Windows can treat parts of a custom title bar as native non-client areas. This lets you draw the title bar and caption buttons with any HTML/CSS design while keeping native Windows behavior: the caption area drags the window, the maximize button can show Windows 11 Snap Assist / Snap Layouts, and the minimize, maximize, and close buttons receive native hit testing and mouse state. + +The video below shows a custom HTML/CSS title bar using native Windows hit testing, including Windows 11 Snap Assist / Snap Layouts on a custom maximize button. + +<video src={wailsAppRegionVideo} controls muted playsInline></video> + +Wails supports two Windows-specific mechanisms: + +- `app-region` through WebView2's native non-client region support +- `--wails-non-client-region` through Wails runtime tracking for custom caption buttons + +### Choosing a Mode + +:::caution[Experimental] +`WebView2CompositionHosting` changes how the window hosts and interacts with WebView2 under the hood. Instead of the default HWND-hosted WebView2 controller, Wails uses composition controller hosting and forwards input explicitly. This mode may have rendering, input, focus, or WebView2 Runtime compatibility issues. Enable it only when you need native custom caption-button behavior, and test your app carefully on the Windows and WebView2 Runtime versions you support. +::: + +Choose based on what you need from Windows: + +- Use `NonClientRegionSupport` for simple native app dragging with WebView2's `app-region: drag` and `app-region: no-drag`. +- Use `WebView2CompositionHosting` when your custom minimize, maximize, and close buttons should behave like native Windows caption buttons. +- Enable both when the same window needs WebView2-native `app-region` support and Wails-managed custom caption-button regions. + +`NonClientRegionSupport` is the lightweight native alternative to Wails' `--wails-draggable` tracking. You mark draggable and non-draggable areas with CSS, WebView2 decides which pixels belong to the caption, and Wails asks WebView2 for the native region when hit testing. + +That is the full scope of this mode today. It does not make custom minimize, maximize, or close buttons behave like native Windows caption buttons, and it does not enable Windows 11 Snap Assist / Snap Layouts for a custom maximize button. Use it when you need simple native app dragging without the extra machinery of `--wails-draggable`. + +`WebView2CompositionHosting` is for custom caption buttons with native behavior. Wails tracks DOM rectangles marked with `--wails-non-client-region`, maps them to Windows hit-test values such as `HTMINBUTTON`, `HTMAXBUTTON`, and `HTCLOSE`, and forwards mouse input back into the composition-hosted WebView2 surface. That is what allows a custom maximize button to participate in Windows 11 Snap Assist / Snap Layouts while keeping any visual design you choose. + +Put another way: `NonClientRegionSupport` is WebView2-native CSS region support. `WebView2CompositionHosting` is Wails taking responsibility for host-owned composition and custom non-client hit testing. + +### WebView2 app-region + +Enable WebView2's native non-client region support for the window: + +```go +window := app.Window.NewWithOptions(application.WebviewWindowOptions{ + Frameless: true, + Windows: application.WindowsWindow{ + NonClientRegionSupport: true, + }, +}) +``` + +Then mark draggable areas with the CSS `app-region` property: + +```css +.titlebar { + app-region: drag; +} + +.titlebar button, +.titlebar input, +.titlebar select, +.titlebar textarea { + app-region: no-drag; +} +``` + +Use this when you only need native caption dragging and your title bar controls are handled with normal frontend clicks. + +The limitation of this mode is that it is constrained by WebView2's own non-client region support. In current WebView2 releases, that means drag and no-drag regions only. It is not intended to model fully custom frontend caption buttons with distinct native minimize, maximize, and close roles. + +### Custom Caption Buttons with Native Behavior + +For custom minimize, maximize, and close buttons that should behave like system caption buttons, enable composition hosting: + +:::caution[Experimental] +`WebView2CompositionHosting` uses WebView2 composition controller hosting with DirectComposition. See [Choosing a Mode](#choosing-a-mode) before enabling it. +::: + +```go +window := app.Window.NewWithOptions(application.WebviewWindowOptions{ + Frameless: true, + Windows: application.WindowsWindow{ + WebView2CompositionHosting: true, + }, +}) +``` + +Then mark each frontend region with `--wails-non-client-region`: + +```html +<div class="titlebar"> + <div class="title">My Application</div> + <div class="window-controls"> + <button class="window-button minimize" aria-label="Minimize"></button> + <button class="window-button maximize" aria-label="Maximize"></button> + <button class="window-button close" aria-label="Close"></button> + </div> +</div> +``` + +```css +.titlebar { + --wails-non-client-region: caption; + height: 40px; +} + +.window-controls { + display: flex; + height: 100%; +} + +.window-button { + width: 46px; + border: 0; + background: transparent; +} + +.window-button.minimize { + --wails-non-client-region: minimize; +} + +.window-button.maximize { + --wails-non-client-region: maximize; +} + +.window-button.close { + --wails-non-client-region: close; +} +``` + +Supported `--wails-non-client-region` values: + +- `caption` - draggable caption area +- `minimize` - native minimize button hit target +- `maximize` - native maximize button hit target, including Windows 11 Snap Assist / Snap Layouts hover behavior +- `close` - native close button hit target + +The Wails runtime observes DOM, style, size, scroll, and viewport changes, then sends region snapshots to the native window. Region geometry is measured in CSS pixels and converted to physical pixels for Windows hit testing. + +The visual design remains entirely yours. The regions only tell Windows what each rectangle means; the button shape, icon, color, spacing, hover styling, and layout still come from your frontend. + +### Combining Both + +You can enable both options when you want WebView2 `app-region` support and Wails-managed caption button regions in the same window: + +```go +window := app.Window.NewWithOptions(application.WebviewWindowOptions{ + Frameless: true, + Windows: application.WindowsWindow{ + NonClientRegionSupport: true, + WebView2CompositionHosting: true, + }, +}) +``` + ## System Buttons ### Implementing Close/Minimise/Maximise @@ -358,6 +509,7 @@ body { // Trigger Windows 11 Snap Assist window.SnapAssist() ``` + This triggers Snap Layouts through the Windows hotkey path. For a custom HTML maximize button with native hover Snap Layouts, use [Native Non-Client Regions on Windows](#native-non-client-regions-on-windows) instead. **Custom title bar height:** Windows automatically detects drag regions from CSS. diff --git a/docs/src/content/docs/features/windows/options.mdx b/docs/src/content/docs/features/windows/options.mdx index 0595e951f00..9319acb5b8d 100644 --- a/docs/src/content/docs/features/windows/options.mdx +++ b/docs/src/content/docs/features/windows/options.mdx @@ -948,6 +948,8 @@ Windows: application.WindowsWindow{ BackdropType: application.Auto, CustomTheme: application.ThemeSettings{}, DisableFramelessWindowDecorations: false, + NonClientRegionSupport: false, + WebView2CompositionHosting: false, }, ``` @@ -973,6 +975,15 @@ There are no `WindowsBackdropTypeMica`-style constants — use `application.Mica **DisableFramelessWindowDecorations** (`bool`) - Disable default frameless decorations (Aero shadow, rounded corners). +**NonClientRegionSupport** (`bool`) +- Enables WebView2-native `app-region: drag` / `app-region: no-drag` support for frameless custom title bars. +- This is for simple native app dragging only. It does not provide native custom caption-button behavior or Windows 11 Snap Assist / Snap Layouts for custom maximize buttons. + +**WebView2CompositionHosting** (`bool`) +- Enables Wails-managed `--wails-non-client-region` support for custom caption buttons with native Windows behavior, including Windows 11 Snap Assist / Snap Layouts on custom maximize buttons. +- Experimental. This hosts WebView2 through `ICoreWebView2CompositionController` and DirectComposition instead of the default HWND-hosted controller. +- Can be combined with `NonClientRegionSupport` when a window needs both WebView2-native `app-region` support and Wails-managed custom caption-button regions. + **Example:** ```go @@ -982,6 +993,17 @@ Windows: application.WindowsWindow{ }, ``` +**Example - Custom Windows title bar regions:** + +```go +Windows: application.WindowsWindow{ + NonClientRegionSupport: true, + WebView2CompositionHosting: true, +}, +``` + +See [Frameless Windows](/features/windows/frameless#native-non-client-regions-on-windows) for the detailed behavior, tradeoffs, and matching CSS. + ### Linux Options (per-window) The per-window struct is `application.LinuxWindow` — **not** `LinuxOptions`. diff --git a/docs/src/content/docs/feedback.mdx b/docs/src/content/docs/feedback.mdx index c56de054982..6c426d759db 100644 --- a/docs/src/content/docs/feedback.mdx +++ b/docs/src/content/docs/feedback.mdx @@ -47,6 +47,7 @@ discussions before creating new ones. Here are the different ways to contribute: - Clearly describe the feature and the problem it solves. - Feel free to also discuss ideas in the [#v3](https://discord.gg/bdj28QNHmT) channel on Discord. + - Substantial new functionality goes through the [Wails Enhancement Proposal (WEP) process](https://github.com/wailsapp/wails/blob/master/v3/wep/README.md), a structured proposal that is discussed with the community on its pull request before being accepted for implementation. See the [contributing guide](/contributing/#4-propose-an-enhancement-wep) for a summary. </TabItem> diff --git a/go.work b/go.work deleted file mode 100644 index 1fbc5f094c4..00000000000 --- a/go.work +++ /dev/null @@ -1,5 +0,0 @@ -go 1.25.0 - -use ( - ./v3 -) diff --git a/go.work.sum b/go.work.sum deleted file mode 100644 index 91461c0a1f5..00000000000 --- a/go.work.sum +++ /dev/null @@ -1,41 +0,0 @@ -cyphar.com/go-pathrs v0.2.1/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc= -github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= -github.com/bits-and-blooms/bitset v1.24.4/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= -github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= -github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= -github.com/caarlos0/go-version v0.2.2/go.mod h1:X+rI5VAtJDpcjCjeEIXpxGa5+rTcgur1FK66wS0/944= -github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= -github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= -github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= -github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/muesli/mango v0.2.0/go.mod h1:5XFpbC8jY5UUv89YQciiXNlbi+iJgt29VDC5xbzrLL4= -github.com/muesli/mango-cobra v1.3.0/go.mod h1:Cj1ZrBu3806Qw7UjxnAUgE+7tllUBj1NCLQDwwGx19E= -github.com/muesli/mango-pflag v0.1.0/go.mod h1:YEQomTxaCUp8PrbhFh10UfbhbQrM/xJ4i2PB8VTLLW0= -github.com/muesli/roff v0.1.0/go.mod h1:pjAHQM9hdUUwm/krAfrLGgJkXJ+YuhtsfZ42kieB2Ig= -github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= -github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= -github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= -github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= -github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= -github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= -github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= -github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= -golang.org/x/telemetry v0.0.0-20260409153401-be6f6cb8b1fa/go.mod h1:kHjTxDEnAu6/Nl9lDkzjWpR+bmKfxeiRuSDlsMb70gE= -golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= -golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -mvdan.cc/editorconfig v0.3.0/go.mod h1:NcJHuDtNOTEJ6251indKiWuzK6+VcrMuLzGMLKBFupQ= diff --git a/v2/cmd/wails/internal/version.txt b/v2/cmd/wails/internal/version.txt index a5db00c8c11..311f78b667b 100644 --- a/v2/cmd/wails/internal/version.txt +++ b/v2/cmd/wails/internal/version.txt @@ -1 +1 @@ -v2.12.0 \ No newline at end of file +v2.13.0 \ No newline at end of file diff --git a/v3/examples/mac-window-tabs/Taskfile.yml b/v3/examples/mac-window-tabs/Taskfile.yml index bba79236acc..6a06761e83a 100644 --- a/v3/examples/mac-window-tabs/Taskfile.yml +++ b/v3/examples/mac-window-tabs/Taskfile.yml @@ -8,12 +8,12 @@ includes: # This example is a standalone Go module (its own go.mod, with a `replace` # pointing at the local Wails checkout because MacWindowTabbingMode is not in a -# published release yet). It physically lives under v3/, which is a member of -# the repo's root go.work. An active workspace would shadow this module: binding -# generation would find 0 services and `go mod tidy` would target v3 instead. -# Force workspace mode off so the example always builds as itself. This is -# inherited by the wails3 dev/build subprocess tree and is a harmless no-op -# outside the monorepo, where there is no go.work. +# published release yet). It physically lives under v3/, so any go.work that +# covers v3 would shadow this module: binding generation would find 0 services +# and `go mod tidy` would target v3 instead. The repo no longer ships a +# workspace file, but contributors often create one locally, so force workspace +# mode off and the example always builds as itself. This is inherited by the +# wails3 dev/build subprocess tree and is a harmless no-op everywhere else. env: GOWORK: "off" diff --git a/v3/examples/mac-window-tabs/build/Taskfile.yml b/v3/examples/mac-window-tabs/build/Taskfile.yml index 9322dc9c3be..b09e92f7560 100644 --- a/v3/examples/mac-window-tabs/build/Taskfile.yml +++ b/v3/examples/mac-window-tabs/build/Taskfile.yml @@ -1,9 +1,10 @@ version: '3' # See the note in ../Taskfile.yml: this example is a standalone module nested -# under v3/, so an active go.work would shadow it. Force workspace mode off here -# too, so the Go-tooling tasks (go mod tidy, generate bindings, go build) behave -# correctly even when invoked directly rather than via the root dev/build tasks. +# under v3/, so a local go.work covering v3 would shadow it. Force workspace +# mode off here too, so the Go-tooling tasks (go mod tidy, generate bindings, +# go build) behave correctly even when invoked directly rather than via the +# root dev/build tasks. env: GOWORK: "off" diff --git a/v3/internal/assetserver/bundledassets/runtime.debug.js b/v3/internal/assetserver/bundledassets/runtime.debug.js index 3b9b9b4918b..4cf80000d7d 100644 --- a/v3/internal/assetserver/bundledassets/runtime.debug.js +++ b/v3/internal/assetserver/bundledassets/runtime.debug.js @@ -82,6 +82,17 @@ function runtimeURL() { return window.location.origin + "/wails/runtime"; } var CHUNK_THRESHOLD = 512 * 1024; +var RuntimeError = class extends Error { + /** + * Constructs a new RuntimeError instance. + * @param message - The error message. + * @param options - Options to be forwarded to the Error constructor. + */ + constructor(message, options) { + super(message, options); + this.name = "RuntimeError"; + } +}; var objectNames = Object.freeze({ Call: 0, Clipboard: 1, @@ -138,6 +149,26 @@ async function runtimeCallWithID(objectID, method, windowName, args) { response = await fetch(url, { method: "POST", headers, body: bodyStr }); } if (!response.ok) { + const ct = response.headers.get("Content-Type"); + if (ct == null ? void 0 : ct.includes("application/json")) { + const json = await response.json(); + let err; + switch (json.kind) { + case "ReferenceError": + err = new ReferenceError(json.message); + break; + case "TypeError": + err = new TypeError(json.message); + break; + case "RuntimeError": + err = new RuntimeError(json.message); + break; + default: + err = new Error(json.message); + } + err.cause = json.cause; + throw err; + } throw new Error(await response.text()); } if (((_b = (_a3 = response.headers.get("Content-Type")) == null ? void 0 : _a3.indexOf("application/json")) != null ? _b : -1) !== -1) { @@ -322,6 +353,7 @@ __export(create_exports, { Any: () => Any, Array: () => Array2, ByteSlice: () => ByteSlice, + DateFromTime: () => DateFromTime, Events: () => Events, Map: () => Map2, Nullable: () => Nullable, @@ -387,6 +419,9 @@ function Struct(createField) { return source; }; } +function DateFromTime(source) { + return new Date(source); +} var Events = {}; // desktop/@wailsio/runtime/src/event_types.ts @@ -573,7 +608,8 @@ var Types = Object.freeze({ WindowWillUseStandardFrame: "mac:WindowWillUseStandardFrame", WindowZoomIn: "mac:WindowZoomIn", WindowZoomOut: "mac:WindowZoomOut", - WindowZoomReset: "mac:WindowZoomReset" + WindowZoomReset: "mac:WindowZoomReset", + WebViewWebContentProcessDidTerminate: "mac:WebViewWebContentProcessDidTerminate" }), Linux: Object.freeze({ ApplicationStartup: "linux:ApplicationStartup", @@ -1281,8 +1317,8 @@ var _Window = class _Window { * Gathers information about the drop target element and sends it back to the Go backend. * * @param filenames - An array of file paths (strings) that were dropped. - * @param x - The x-coordinate of the drop event (CSS pixels). - * @param y - The y-coordinate of the drop event (CSS pixels). + * @param x - The x-coordinate of the drop event, in logical (CSS) pixels relative to the webview. + * @param y - The y-coordinate of the drop event, in logical (CSS) pixels relative to the webview. */ HandlePlatformFileDrop(filenames, x, y) { var _a3, _b; @@ -1875,6 +1911,9 @@ function primaryDown(event) { } } if (resizeEdge) { + if (event.type !== "mousedown") { + return; + } canResize = true; return; } @@ -1955,6 +1994,164 @@ function onMouseMove(event) { else setResize(); } +// desktop/@wailsio/runtime/src/appregion.ts +var regionProperty = "--wails-non-client-region"; +var runtimeConfigReadyEvent = "wails:runtime-config-ready"; +var validRegions = /* @__PURE__ */ new Set(["caption", "minimize", "maximize", "close"]); +if (hasDOM) { + window._wails = window._wails || {}; +} +var updatePending = false; +var lastPayload = ""; +var observedElements = /* @__PURE__ */ new Set(); +var resizeObserver; +var trackingStarted = false; +function normaliseRegionKind(value) { + const region = value.trim().toLowerCase(); + if (validRegions.has(region)) { + return region; + } + return void 0; +} +function nonClientRegionForElement(element) { + if (!(element instanceof HTMLElement)) { + return void 0; + } + const style = window.getComputedStyle(element); + const region = normaliseRegionKind(style.getPropertyValue(regionProperty)); + if (!region) { + return void 0; + } + const parent = element.parentElement; + if (parent) { + const parentStyle = window.getComputedStyle(parent); + if (normaliseRegionKind(parentStyle.getPropertyValue(regionProperty)) === region) { + return void 0; + } + } + return region; +} +function isVisible(element) { + const style = window.getComputedStyle(element); + return style.display !== "none" && style.visibility !== "hidden" && style.contentVisibility !== "hidden"; +} +function elementRegion(element) { + if (!(element instanceof HTMLElement)) { + return void 0; + } + const kind = nonClientRegionForElement(element); + if (!kind || !isVisible(element)) { + return void 0; + } + const rect = element.getBoundingClientRect(); + if (rect.width <= 0 || rect.height <= 0) { + return void 0; + } + const scale = window.devicePixelRatio || 1; + const left = Math.floor(rect.left * scale); + const top = Math.floor(rect.top * scale); + const right = Math.ceil(rect.right * scale); + const bottom = Math.ceil(rect.bottom * scale); + if (right <= left || bottom <= top) { + return void 0; + } + return { kind, left, top, right, bottom }; +} +function regionElements() { + const elements = []; + if (document.documentElement) { + elements.push(document.documentElement); + } + if (document.body) { + elements.push(document.body); + for (const element of document.body.querySelectorAll("*")) { + elements.push(element); + } + } + return elements; +} +function observeRegionElements(elements) { + if (typeof ResizeObserver === "undefined") { + return; + } + resizeObserver != null ? resizeObserver : resizeObserver = new ResizeObserver(scheduleUpdate); + const nextElements = new Set(elements); + for (const element of observedElements) { + if (!nextElements.has(element)) { + resizeObserver.unobserve(element); + } + } + for (const element of nextElements) { + if (!observedElements.has(element)) { + resizeObserver.observe(element); + } + } + observedElements = nextElements; +} +function updateNonClientRegions() { + updatePending = false; + const elements = regionElements(); + const regions = []; + const activeElements = []; + for (const element of elements) { + const region = elementRegion(element); + if (region) { + regions.push(region); + activeElements.push(element); + } + } + observeRegionElements(activeElements); + const payload = JSON.stringify({ version: 1, regions }); + if (payload === lastPayload) { + return; + } + lastPayload = payload; + invoke("wails:non-client-region:" + payload); +} +function scheduleUpdate() { + if (updatePending) { + return; + } + updatePending = true; + window.requestAnimationFrame(updateNonClientRegions); +} +function startNonClientRegionTracking() { + var _a3, _b; + if (trackingStarted) { + return; + } + trackingStarted = true; + scheduleUpdate(); + const mutationObserver = new MutationObserver(scheduleUpdate); + mutationObserver.observe(document.documentElement, { + attributes: true, + childList: true, + subtree: true + }); + window.addEventListener("resize", scheduleUpdate); + window.addEventListener("scroll", scheduleUpdate, true); + (_a3 = window.visualViewport) == null ? void 0 : _a3.addEventListener("resize", scheduleUpdate); + (_b = window.visualViewport) == null ? void 0 : _b.addEventListener("scroll", scheduleUpdate); +} +function tryStartNonClientRegionTracking() { + var _a3, _b; + const os = (_a3 = window._wails.environment) == null ? void 0 : _a3.OS; + if (os === void 0) { + return false; + } + const enabled = (_b = window._wails.flags) == null ? void 0 : _b.nonClientRegionTracking; + if (os === "windows") { + if (enabled === true) { + whenReady(startNonClientRegionTracking); + } + return true; + } + return true; +} +if (hasDOM && !tryStartNonClientRegionTracking()) { + window.addEventListener(runtimeConfigReadyEvent, tryStartNonClientRegionTracking, { once: true }); +} + // desktop/@wailsio/runtime/src/application.ts var application_exports = {}; __export(application_exports, { @@ -2788,17 +2985,6 @@ var cancelCall = newRuntimeCaller(objectNames.CancelCall); var callResponses = /* @__PURE__ */ new Map(); var CallBinding = 0; var CancelMethod = 0; -var RuntimeError = class extends Error { - /** - * Constructs a new RuntimeError instance. - * @param message - The error message. - * @param options - Options to be forwarded to the Error constructor. - */ - constructor(message, options) { - super(message, options); - this.name = "RuntimeError"; - } -}; function generateID() { let result; do { @@ -3056,4 +3242,4 @@ export { objectNames, setTransport }; -//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2luZGV4LnRzIiwgIi4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy93bWwudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2Jyb3dzZXIudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL25hbm9pZC50cyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvZW52aXJvbm1lbnQudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3J1bnRpbWUudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2RpYWxvZ3MudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2V2ZW50cy50cyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvbGlzdGVuZXIudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2NyZWF0ZS50cyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvZXZlbnRfdHlwZXMudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3V0aWxzLnRzIiwgIi4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy93aW5kb3cudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL2NvbXBpbGVkL21haW4uanMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3N5c3RlbS50cyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvY29udGV4dG1lbnUudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2ZsYWdzLnRzIiwgIi4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9kcmFnLnRzIiwgIi4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9hcHBsaWNhdGlvbi50cyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvY2FsbHMudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2NhbGxhYmxlLnRzIiwgIi4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9jYW5jZWxsYWJsZS50cyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvY2xpcGJvYXJkLnRzIiwgIi4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9zY3JlZW5zLnRzIiwgIi4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9pb3MudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2FuZHJvaWQudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3VwZGF0ZXIudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vLyBTZXR1cFxuaW1wb3J0IHsgaGFzRE9NIH0gZnJvbSBcIi4vZW52aXJvbm1lbnQuanNcIjtcblxuaWYgKGhhc0RPTSkge1xuICAgIHdpbmRvdy5fd2FpbHMgPSB3aW5kb3cuX3dhaWxzIHx8IHt9O1xufVxuXG5pbXBvcnQgXCIuL2NvbnRleHRtZW51LmpzXCI7XG5pbXBvcnQgXCIuL2RyYWcuanNcIjtcblxuLy8gUmUtZXhwb3J0IHB1YmxpYyBBUElcbmltcG9ydCAqIGFzIEFwcGxpY2F0aW9uIGZyb20gXCIuL2FwcGxpY2F0aW9uLmpzXCI7XG5pbXBvcnQgKiBhcyBCcm93c2VyIGZyb20gXCIuL2Jyb3dzZXIuanNcIjtcbmltcG9ydCAqIGFzIENhbGwgZnJvbSBcIi4vY2FsbHMuanNcIjtcbmltcG9ydCAqIGFzIENsaXBib2FyZCBmcm9tIFwiLi9jbGlwYm9hcmQuanNcIjtcbmltcG9ydCAqIGFzIENyZWF0ZSBmcm9tIFwiLi9jcmVhdGUuanNcIjtcbmltcG9ydCAqIGFzIERpYWxvZ3MgZnJvbSBcIi4vZGlhbG9ncy5qc1wiO1xuaW1wb3J0ICogYXMgRXZlbnRzIGZyb20gXCIuL2V2ZW50cy5qc1wiO1xuaW1wb3J0ICogYXMgRmxhZ3MgZnJvbSBcIi4vZmxhZ3MuanNcIjtcbmltcG9ydCAqIGFzIFNjcmVlbnMgZnJvbSBcIi4vc2NyZWVucy5qc1wiO1xuaW1wb3J0ICogYXMgU3lzdGVtIGZyb20gXCIuL3N5c3RlbS5qc1wiO1xuaW1wb3J0ICogYXMgSU9TIGZyb20gXCIuL2lvcy5qc1wiO1xuaW1wb3J0ICogYXMgQW5kcm9pZCBmcm9tIFwiLi9hbmRyb2lkLmpzXCI7XG5pbXBvcnQgKiBhcyBVcGRhdGVyIGZyb20gXCIuL3VwZGF0ZXIuanNcIjtcbmltcG9ydCBXaW5kb3csIHsgaGFuZGxlRHJhZ0VudGVyLCBoYW5kbGVEcmFnTGVhdmUsIGhhbmRsZURyYWdPdmVyIH0gZnJvbSBcIi4vd2luZG93LmpzXCI7XG5pbXBvcnQgKiBhcyBXTUwgZnJvbSBcIi4vd21sLmpzXCI7XG5cbmV4cG9ydCB7XG4gICAgQXBwbGljYXRpb24sXG4gICAgQnJvd3NlcixcbiAgICBDYWxsLFxuICAgIENsaXBib2FyZCxcbiAgICBEaWFsb2dzLFxuICAgIEV2ZW50cyxcbiAgICBGbGFncyxcbiAgICBTY3JlZW5zLFxuICAgIFN5c3RlbSxcbiAgICBJT1MsXG4gICAgQW5kcm9pZCxcbiAgICBVcGRhdGVyLFxuICAgIFdpbmRvdyxcbiAgICBXTUxcbn07XG5cbi8qKlxuICogQW4gaW50ZXJuYWwgdXRpbGl0eSBjb25zdW1lZCBieSB0aGUgYmluZGluZyBnZW5lcmF0b3IuXG4gKlxuICogQGlnbm9yZVxuICovXG5leHBvcnQgeyBDcmVhdGUgfTtcblxuZXhwb3J0ICogZnJvbSBcIi4vY2FuY2VsbGFibGUuanNcIjtcblxuLy8gRXhwb3J0IHRyYW5zcG9ydCBpbnRlcmZhY2VzIGFuZCB1dGlsaXRpZXNcbmV4cG9ydCB7XG4gICAgc2V0VHJhbnNwb3J0LFxuICAgIGdldFRyYW5zcG9ydCxcbiAgICB0eXBlIFJ1bnRpbWVUcmFuc3BvcnQsXG4gICAgb2JqZWN0TmFtZXMsXG4gICAgY2xpZW50SWQsXG59IGZyb20gXCIuL3J1bnRpbWUuanNcIjtcblxuaW1wb3J0IHsgY2xpZW50SWQgfSBmcm9tIFwiLi9ydW50aW1lLmpzXCI7XG5cbi8vIE5vdGlmeSBiYWNrZW5kXG5pZiAoaGFzRE9NKSB7XG4gICAgd2luZG93Ll93YWlscy5pbnZva2UgPSBTeXN0ZW0uaW52b2tlO1xuICAgIHdpbmRvdy5fd2FpbHMuY2xpZW50SWQgPSBjbGllbnRJZDtcbn1cblxuLy8gUmVnaXN0ZXIgcGxhdGZvcm0gaGFuZGxlcnMgKGludGVybmFsIEFQSSlcbi8vIE5vdGU6IFdpbmRvdyBpcyB0aGUgdGhpc1dpbmRvdyBpbnN0YW5jZSAoZGVmYXVsdCBleHBvcnQgZnJvbSB3aW5kb3cudHMpXG4vLyBCaW5kaW5nIGVuc3VyZXMgJ3RoaXMnIGNvcnJlY3RseSByZWZlcnMgdG8gdGhlIGN1cnJlbnQgd2luZG93IGluc3RhbmNlXG5pZiAoaGFzRE9NKSB7XG4gICAgd2luZG93Ll93YWlscy5oYW5kbGVQbGF0Zm9ybUZpbGVEcm9wID0gV2luZG93LkhhbmRsZVBsYXRmb3JtRmlsZURyb3AuYmluZChXaW5kb3cpO1xufVxuXG4vLyBMaW51eC1zcGVjaWZpYyBkcmFnIGhhbmRsZXJzIChHVEsgaW50ZXJjZXB0cyBET00gZHJhZyBldmVudHMpXG5pZiAoaGFzRE9NKSB7XG4gICAgd2luZG93Ll93YWlscy5oYW5kbGVEcmFnRW50ZXIgPSBoYW5kbGVEcmFnRW50ZXI7XG4gICAgd2luZG93Ll93YWlscy5oYW5kbGVEcmFnTGVhdmUgPSBoYW5kbGVEcmFnTGVhdmU7XG4gICAgd2luZG93Ll93YWlscy5oYW5kbGVEcmFnT3ZlciA9IGhhbmRsZURyYWdPdmVyO1xufVxuXG5pZiAoaGFzRE9NKSB7XG4gICAgU3lzdGVtLmludm9rZShcIndhaWxzOnJ1bnRpbWU6cmVhZHlcIik7XG59XG5cbi8qKlxuICogTG9hZHMgYSBzY3JpcHQgZnJvbSB0aGUgZ2l2ZW4gVVJMIGlmIGl0IGV4aXN0cy5cbiAqIFVzZXMgSEVBRCByZXF1ZXN0IHRvIGNoZWNrIGV4aXN0ZW5jZSwgdGhlbiBpbmplY3RzIGEgc2NyaXB0IHRhZy5cbiAqIFNpbGVudGx5IGlnbm9yZXMgaWYgdGhlIHNjcmlwdCBkb2Vzbid0IGV4aXN0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gbG9hZE9wdGlvbmFsU2NyaXB0KHVybDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIGZldGNoKHVybCwgeyBtZXRob2Q6ICdIRUFEJyB9KVxuICAgICAgICAudGhlbihyZXNwb25zZSA9PiB7XG4gICAgICAgICAgICBpZiAocmVzcG9uc2Uub2spIHtcbiAgICAgICAgICAgICAgICAvLyBWZXJpZnkgdGhlIHJlc3BvbnNlIGlzIGFjdHVhbGx5IEphdmFTY3JpcHQgYW5kIG5vdCBhbiBIVE1MIGZhbGxiYWNrXG4gICAgICAgICAgICAgICAgLy8gKGUuZy4gVml0ZSBkZXYgc2VydmVyIHJldHVybnMgaW5kZXguaHRtbCBmb3IgdW5rbm93biByb3V0ZXMpXG4gICAgICAgICAgICAgICAgY29uc3QgY29udGVudFR5cGUgPSAocmVzcG9uc2UuaGVhZGVycy5nZXQoJ2NvbnRlbnQtdHlwZScpIHx8ICcnKS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgICAgIGlmIChjb250ZW50VHlwZS5pbmNsdWRlcygnamF2YXNjcmlwdCcpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHNjcmlwdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NjcmlwdCcpO1xuICAgICAgICAgICAgICAgICAgICBzY3JpcHQuc3JjID0gdXJsO1xuICAgICAgICAgICAgICAgICAgICBkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKHNjcmlwdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goKCkgPT4ge30pOyAvLyBTaWxlbnRseSBpZ25vcmUgLSBzY3JpcHQgaXMgb3B0aW9uYWxcbn1cblxuLy8gTG9hZCBjdXN0b20uanMgaWYgYXZhaWxhYmxlICh1c2VkIGJ5IHNlcnZlciBtb2RlIGZvciBXZWJTb2NrZXQgZXZlbnRzLCBldGMuKVxuaWYgKGhhc0RPTSkge1xuICAgIGxvYWRPcHRpb25hbFNjcmlwdCgnL3dhaWxzL2N1c3RvbS5qcycpO1xufVxuIiwgIi8qXG4gXyAgICAgX18gICAgIF8gX19cbnwgfCAgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG5pbXBvcnQgeyBPcGVuVVJMIH0gZnJvbSBcIi4vYnJvd3Nlci5qc1wiO1xuaW1wb3J0IHsgUXVlc3Rpb24gfSBmcm9tIFwiLi9kaWFsb2dzLmpzXCI7XG5pbXBvcnQgeyBFbWl0IH0gZnJvbSBcIi4vZXZlbnRzLmpzXCI7XG5pbXBvcnQgeyBjYW5BYm9ydExpc3RlbmVycywgd2hlblJlYWR5IH0gZnJvbSBcIi4vdXRpbHMuanNcIjtcbmltcG9ydCBXaW5kb3cgZnJvbSBcIi4vd2luZG93LmpzXCI7XG5cbi8qKlxuICogU2VuZHMgYW4gZXZlbnQgd2l0aCB0aGUgZ2l2ZW4gbmFtZSBhbmQgb3B0aW9uYWwgZGF0YS5cbiAqXG4gKiBAcGFyYW0gZXZlbnROYW1lIC0gLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdG8gc2VuZC5cbiAqIEBwYXJhbSBbZGF0YT1udWxsXSAtIC0gT3B0aW9uYWwgZGF0YSB0byBzZW5kIGFsb25nIHdpdGggdGhlIGV2ZW50LlxuICovXG5mdW5jdGlvbiBzZW5kRXZlbnQoZXZlbnROYW1lOiBzdHJpbmcsIGRhdGE6IGFueSA9IG51bGwpOiB2b2lkIHtcbiAgICBFbWl0KGV2ZW50TmFtZSwgZGF0YSk7XG59XG5cbi8qKlxuICogQ2FsbHMgYSBtZXRob2Qgb24gYSBzcGVjaWZpZWQgd2luZG93LlxuICpcbiAqIEBwYXJhbSB3aW5kb3dOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHdpbmRvdyB0byBjYWxsIHRoZSBtZXRob2Qgb24uXG4gKiBAcGFyYW0gbWV0aG9kTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBtZXRob2QgdG8gY2FsbC5cbiAqL1xuZnVuY3Rpb24gY2FsbFdpbmRvd01ldGhvZCh3aW5kb3dOYW1lOiBzdHJpbmcsIG1ldGhvZE5hbWU6IHN0cmluZykge1xuICAgIGNvbnN0IHRhcmdldFdpbmRvdyA9IFdpbmRvdy5HZXQod2luZG93TmFtZSk7XG4gICAgY29uc3QgbWV0aG9kID0gKHRhcmdldFdpbmRvdyBhcyBhbnkpW21ldGhvZE5hbWVdO1xuXG4gICAgaWYgKHR5cGVvZiBtZXRob2QgIT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICBjb25zb2xlLmVycm9yKGBXaW5kb3cgbWV0aG9kICcke21ldGhvZE5hbWV9JyBub3QgZm91bmRgKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICAgIG1ldGhvZC5jYWxsKHRhcmdldFdpbmRvdyk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zb2xlLmVycm9yKGBFcnJvciBjYWxsaW5nIHdpbmRvdyBtZXRob2QgJyR7bWV0aG9kTmFtZX0nOiBgLCBlKTtcbiAgICB9XG59XG5cbi8qKlxuICogUmVzcG9uZHMgdG8gYSB0cmlnZ2VyaW5nIGV2ZW50IGJ5IHJ1bm5pbmcgYXBwcm9wcmlhdGUgV01MIGFjdGlvbnMgZm9yIHRoZSBjdXJyZW50IHRhcmdldC5cbiAqL1xuZnVuY3Rpb24gb25XTUxUcmlnZ2VyZWQoZXY6IEV2ZW50KTogdm9pZCB7XG4gICAgY29uc3QgZWxlbWVudCA9IGV2LmN1cnJlbnRUYXJnZXQgYXMgRWxlbWVudDtcblxuICAgIGZ1bmN0aW9uIHJ1bkVmZmVjdChjaG9pY2UgPSBcIlllc1wiKSB7XG4gICAgICAgIGlmIChjaG9pY2UgIT09IFwiWWVzXCIpXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgY29uc3QgZXZlbnRUeXBlID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3dtbC1ldmVudCcpIHx8IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCdkYXRhLXdtbC1ldmVudCcpO1xuICAgICAgICBjb25zdCB0YXJnZXRXaW5kb3cgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLXRhcmdldC13aW5kb3cnKSB8fCBlbGVtZW50LmdldEF0dHJpYnV0ZSgnZGF0YS13bWwtdGFyZ2V0LXdpbmRvdycpIHx8IFwiXCI7XG4gICAgICAgIGNvbnN0IHdpbmRvd01ldGhvZCA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtd2luZG93JykgfHwgZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ2RhdGEtd21sLXdpbmRvdycpO1xuICAgICAgICBjb25zdCB1cmwgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLW9wZW51cmwnKSB8fCBlbGVtZW50LmdldEF0dHJpYnV0ZSgnZGF0YS13bWwtb3BlbnVybCcpO1xuXG4gICAgICAgIGlmIChldmVudFR5cGUgIT09IG51bGwpXG4gICAgICAgICAgICBzZW5kRXZlbnQoZXZlbnRUeXBlKTtcbiAgICAgICAgaWYgKHdpbmRvd01ldGhvZCAhPT0gbnVsbClcbiAgICAgICAgICAgIGNhbGxXaW5kb3dNZXRob2QodGFyZ2V0V2luZG93LCB3aW5kb3dNZXRob2QpO1xuICAgICAgICBpZiAodXJsICE9PSBudWxsKVxuICAgICAgICAgICAgdm9pZCBPcGVuVVJMKHVybCk7XG4gICAgfVxuXG4gICAgY29uc3QgY29uZmlybSA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtY29uZmlybScpIHx8IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCdkYXRhLXdtbC1jb25maXJtJyk7XG5cbiAgICBpZiAoY29uZmlybSkge1xuICAgICAgICBRdWVzdGlvbih7XG4gICAgICAgICAgICBUaXRsZTogXCJDb25maXJtXCIsXG4gICAgICAgICAgICBNZXNzYWdlOiBjb25maXJtLFxuICAgICAgICAgICAgRGV0YWNoZWQ6IGZhbHNlLFxuICAgICAgICAgICAgQnV0dG9uczogW1xuICAgICAgICAgICAgICAgIHsgTGFiZWw6IFwiWWVzXCIgfSxcbiAgICAgICAgICAgICAgICB7IExhYmVsOiBcIk5vXCIsIElzRGVmYXVsdDogdHJ1ZSB9XG4gICAgICAgICAgICBdXG4gICAgICAgIH0pLnRoZW4ocnVuRWZmZWN0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBydW5FZmZlY3QoKTtcbiAgICB9XG59XG5cbi8vIFByaXZhdGUgZmllbGQgbmFtZXMuXG5jb25zdCBjb250cm9sbGVyU3ltID0gU3ltYm9sKFwiY29udHJvbGxlclwiKTtcbmNvbnN0IHRyaWdnZXJNYXBTeW0gPSBTeW1ib2woXCJ0cmlnZ2VyTWFwXCIpO1xuY29uc3QgZWxlbWVudENvdW50U3ltID0gU3ltYm9sKFwiZWxlbWVudENvdW50XCIpO1xuXG4vKipcbiAqIEFib3J0Q29udHJvbGxlclJlZ2lzdHJ5IGRvZXMgbm90IGFjdHVhbGx5IHJlbWVtYmVyIGFjdGl2ZSBldmVudCBsaXN0ZW5lcnM6IGluc3RlYWRcbiAqIGl0IHRpZXMgdGhlbSB0byBhbiBBYm9ydFNpZ25hbCBhbmQgdXNlcyBhbiBBYm9ydENvbnRyb2xsZXIgdG8gcmVtb3ZlIHRoZW0gYWxsIGF0IG9uY2UuXG4gKi9cbmNsYXNzIEFib3J0Q29udHJvbGxlclJlZ2lzdHJ5IHtcbiAgICAvLyBQcml2YXRlIGZpZWxkcy5cbiAgICBbY29udHJvbGxlclN5bV06IEFib3J0Q29udHJvbGxlcjtcblxuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzW2NvbnRyb2xsZXJTeW1dID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYW4gb3B0aW9ucyBvYmplY3QgZm9yIGFkZEV2ZW50TGlzdGVuZXIgdGhhdCB0aWVzIHRoZSBsaXN0ZW5lclxuICAgICAqIHRvIHRoZSBBYm9ydFNpZ25hbCBmcm9tIHRoZSBjdXJyZW50IEFib3J0Q29udHJvbGxlci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBlbGVtZW50IC0gQW4gSFRNTCBlbGVtZW50XG4gICAgICogQHBhcmFtIHRyaWdnZXJzIC0gVGhlIGxpc3Qgb2YgYWN0aXZlIFdNTCB0cmlnZ2VyIGV2ZW50cyBmb3IgdGhlIHNwZWNpZmllZCBlbGVtZW50c1xuICAgICAqL1xuICAgIHNldChlbGVtZW50OiBFbGVtZW50LCB0cmlnZ2Vyczogc3RyaW5nW10pOiBBZGRFdmVudExpc3RlbmVyT3B0aW9ucyB7XG4gICAgICAgIHJldHVybiB7IHNpZ25hbDogdGhpc1tjb250cm9sbGVyU3ltXS5zaWduYWwgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGFsbCByZWdpc3RlcmVkIGV2ZW50IGxpc3RlbmVycyBhbmQgcmVzZXRzIHRoZSByZWdpc3RyeS5cbiAgICAgKi9cbiAgICByZXNldCgpOiB2b2lkIHtcbiAgICAgICAgdGhpc1tjb250cm9sbGVyU3ltXS5hYm9ydCgpO1xuICAgICAgICB0aGlzW2NvbnRyb2xsZXJTeW1dID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBXZWFrTWFwUmVnaXN0cnkgbWFwcyBhY3RpdmUgdHJpZ2dlciBldmVudHMgdG8gZWFjaCBET00gZWxlbWVudCB0aHJvdWdoIGEgV2Vha01hcC5cbiAqIFRoaXMgZW5zdXJlcyB0aGF0IHRoZSBtYXBwaW5nIHJlbWFpbnMgcHJpdmF0ZSB0byB0aGlzIG1vZHVsZSwgd2hpbGUgc3RpbGwgYWxsb3dpbmcgZ2FyYmFnZVxuICogY29sbGVjdGlvbiBvZiB0aGUgaW52b2x2ZWQgZWxlbWVudHMuXG4gKi9cbmNsYXNzIFdlYWtNYXBSZWdpc3RyeSB7XG4gICAgLyoqIFN0b3JlcyB0aGUgY3VycmVudCBlbGVtZW50LXRvLXRyaWdnZXIgbWFwcGluZy4gKi9cbiAgICBbdHJpZ2dlck1hcFN5bV06IFdlYWtNYXA8RWxlbWVudCwgc3RyaW5nW10+O1xuICAgIC8qKiBDb3VudHMgdGhlIG51bWJlciBvZiBlbGVtZW50cyB3aXRoIGFjdGl2ZSBXTUwgdHJpZ2dlcnMuICovXG4gICAgW2VsZW1lbnRDb3VudFN5bV06IG51bWJlcjtcblxuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzW3RyaWdnZXJNYXBTeW1dID0gbmV3IFdlYWtNYXAoKTtcbiAgICAgICAgdGhpc1tlbGVtZW50Q291bnRTeW1dID0gMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIGFjdGl2ZSB0cmlnZ2VycyBmb3IgdGhlIHNwZWNpZmllZCBlbGVtZW50LlxuICAgICAqXG4gICAgICogQHBhcmFtIGVsZW1lbnQgLSBBbiBIVE1MIGVsZW1lbnRcbiAgICAgKiBAcGFyYW0gdHJpZ2dlcnMgLSBUaGUgbGlzdCBvZiBhY3RpdmUgV01MIHRyaWdnZXIgZXZlbnRzIGZvciB0aGUgc3BlY2lmaWVkIGVsZW1lbnRcbiAgICAgKi9cbiAgICBzZXQoZWxlbWVudDogRWxlbWVudCwgdHJpZ2dlcnM6IHN0cmluZ1tdKTogQWRkRXZlbnRMaXN0ZW5lck9wdGlvbnMge1xuICAgICAgICBpZiAoIXRoaXNbdHJpZ2dlck1hcFN5bV0uaGFzKGVsZW1lbnQpKSB7IHRoaXNbZWxlbWVudENvdW50U3ltXSsrOyB9XG4gICAgICAgIHRoaXNbdHJpZ2dlck1hcFN5bV0uc2V0KGVsZW1lbnQsIHRyaWdnZXJzKTtcbiAgICAgICAgcmV0dXJuIHt9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYWxsIHJlZ2lzdGVyZWQgZXZlbnQgbGlzdGVuZXJzLlxuICAgICAqL1xuICAgIHJlc2V0KCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpc1tlbGVtZW50Q291bnRTeW1dIDw9IDApXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgZm9yIChjb25zdCBlbGVtZW50IG9mIGRvY3VtZW50LmJvZHkucXVlcnlTZWxlY3RvckFsbCgnKicpKSB7XG4gICAgICAgICAgICBpZiAodGhpc1tlbGVtZW50Q291bnRTeW1dIDw9IDApXG4gICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgIGNvbnN0IHRyaWdnZXJzID0gdGhpc1t0cmlnZ2VyTWFwU3ltXS5nZXQoZWxlbWVudCk7XG4gICAgICAgICAgICBpZiAodHJpZ2dlcnMgIT0gbnVsbCkgeyB0aGlzW2VsZW1lbnRDb3VudFN5bV0tLTsgfVxuXG4gICAgICAgICAgICBmb3IgKGNvbnN0IHRyaWdnZXIgb2YgdHJpZ2dlcnMgfHwgW10pXG4gICAgICAgICAgICAgICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKHRyaWdnZXIsIG9uV01MVHJpZ2dlcmVkKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXNbdHJpZ2dlck1hcFN5bV0gPSBuZXcgV2Vha01hcCgpO1xuICAgICAgICB0aGlzW2VsZW1lbnRDb3VudFN5bV0gPSAwO1xuICAgIH1cbn1cblxuY29uc3QgdHJpZ2dlclJlZ2lzdHJ5ID0gY2FuQWJvcnRMaXN0ZW5lcnMoKSA/IG5ldyBBYm9ydENvbnRyb2xsZXJSZWdpc3RyeSgpIDogbmV3IFdlYWtNYXBSZWdpc3RyeSgpO1xuXG4vKipcbiAqIEFkZHMgZXZlbnQgbGlzdGVuZXJzIHRvIHRoZSBzcGVjaWZpZWQgZWxlbWVudC5cbiAqL1xuZnVuY3Rpb24gYWRkV01MTGlzdGVuZXJzKGVsZW1lbnQ6IEVsZW1lbnQpOiB2b2lkIHtcbiAgICBjb25zdCB0cmlnZ2VyUmVnRXhwID0gL1xcUysvZztcbiAgICBjb25zdCB0cmlnZ2VyQXR0ciA9IChlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLXRyaWdnZXInKSB8fCBlbGVtZW50LmdldEF0dHJpYnV0ZSgnZGF0YS13bWwtdHJpZ2dlcicpIHx8IFwiY2xpY2tcIik7XG4gICAgY29uc3QgdHJpZ2dlcnM6IHN0cmluZ1tdID0gW107XG5cbiAgICBsZXQgbWF0Y2g7XG4gICAgd2hpbGUgKChtYXRjaCA9IHRyaWdnZXJSZWdFeHAuZXhlYyh0cmlnZ2VyQXR0cikpICE9PSBudWxsKVxuICAgICAgICB0cmlnZ2Vycy5wdXNoKG1hdGNoWzBdKTtcblxuICAgIGNvbnN0IG9wdGlvbnMgPSB0cmlnZ2VyUmVnaXN0cnkuc2V0KGVsZW1lbnQsIHRyaWdnZXJzKTtcbiAgICBmb3IgKGNvbnN0IHRyaWdnZXIgb2YgdHJpZ2dlcnMpXG4gICAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcih0cmlnZ2VyLCBvbldNTFRyaWdnZXJlZCwgb3B0aW9ucyk7XG59XG5cbi8qKlxuICogU2NoZWR1bGVzIGFuIGF1dG9tYXRpYyByZWxvYWQgb2YgV01MIHRvIGJlIHBlcmZvcm1lZCBhcyBzb29uIGFzIHRoZSBkb2N1bWVudCBpcyBmdWxseSBsb2FkZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFbmFibGUoKTogdm9pZCB7XG4gICAgd2hlblJlYWR5KFJlbG9hZCk7XG59XG5cbi8qKlxuICogUmVsb2FkcyB0aGUgV01MIHBhZ2UgYnkgYWRkaW5nIG5lY2Vzc2FyeSBldmVudCBsaXN0ZW5lcnMgYW5kIGJyb3dzZXIgbGlzdGVuZXJzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gUmVsb2FkKCk6IHZvaWQge1xuICAgIHRyaWdnZXJSZWdpc3RyeS5yZXNldCgpO1xuICAgIGRvY3VtZW50LmJvZHkucXVlcnlTZWxlY3RvckFsbCgnW3dtbC1ldmVudF0sIFt3bWwtd2luZG93XSwgW3dtbC1vcGVudXJsXSwgW2RhdGEtd21sLWV2ZW50XSwgW2RhdGEtd21sLXdpbmRvd10sIFtkYXRhLXdtbC1vcGVudXJsXScpLmZvckVhY2goYWRkV01MTGlzdGVuZXJzKTtcbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuaW1wb3J0IHsgbmV3UnVudGltZUNhbGxlciwgb2JqZWN0TmFtZXMgfSBmcm9tIFwiLi9ydW50aW1lLmpzXCI7XG5cbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyKG9iamVjdE5hbWVzLkJyb3dzZXIpO1xuXG5jb25zdCBCcm93c2VyT3BlblVSTCA9IDA7XG5cbi8qKlxuICogT3BlbiBhIGJyb3dzZXIgd2luZG93IHRvIHRoZSBnaXZlbiBVUkwuXG4gKlxuICogQHBhcmFtIHVybCAtIFRoZSBVUkwgdG8gb3BlblxuICovXG5leHBvcnQgZnVuY3Rpb24gT3BlblVSTCh1cmw6IHN0cmluZyB8IFVSTCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBjYWxsKEJyb3dzZXJPcGVuVVJMLCB7dXJsOiB1cmwudG9TdHJpbmcoKX0pO1xufVxuIiwgIi8vIFNvdXJjZTogaHR0cHM6Ly9naXRodWIuY29tL2FpL25hbm9pZFxuXG4vLyBUaGUgTUlUIExpY2Vuc2UgKE1JVClcbi8vXG4vLyBDb3B5cmlnaHQgMjAxNyBBbmRyZXkgU2l0bmlrIDxhbmRyZXlAc2l0bmlrLnJ1PlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHkgb2Zcbi8vIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW5cbi8vIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG9cbi8vIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGwgY29waWVzIG9mXG4vLyB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sXG4vLyAgICAgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gICAgIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluIGFsbFxuLy8gY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyAgICAgVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuLy8gSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1Ncbi8vIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUlxuLy8gQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSXG4vLyBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTlxuLy8gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxuLy8gVGhpcyBhbHBoYWJldCB1c2VzIGBBLVphLXowLTlfLWAgc3ltYm9scy5cbi8vIFRoZSBvcmRlciBvZiBjaGFyYWN0ZXJzIGlzIG9wdGltaXplZCBmb3IgYmV0dGVyIGd6aXAgYW5kIGJyb3RsaSBjb21wcmVzc2lvbi5cbi8vIFJlZmVyZW5jZXMgdG8gdGhlIHNhbWUgZmlsZSAod29ya3MgYm90aCBmb3IgZ3ppcCBhbmQgYnJvdGxpKTpcbi8vIGAndXNlYCwgYGFuZG9tYCwgYW5kIGByaWN0J2Bcbi8vIFJlZmVyZW5jZXMgdG8gdGhlIGJyb3RsaSBkZWZhdWx0IGRpY3Rpb25hcnk6XG4vLyBgLTI2VGAsIGAxOTgzYCwgYDQwcHhgLCBgNzVweGAsIGBidXNoYCwgYGphY2tgLCBgbWluZGAsIGB2ZXJ5YCwgYW5kIGB3b2xmYFxuY29uc3QgdXJsQWxwaGFiZXQgPVxuICAgICd1c2VhbmRvbS0yNlQxOTgzNDBQWDc1cHhKQUNLVkVSWU1JTkRCVVNIV09MRl9HUVpiZmdoamtscXZ3eXpyaWN0J1xuXG5leHBvcnQgZnVuY3Rpb24gbmFub2lkKHNpemU6IG51bWJlciA9IDIxKTogc3RyaW5nIHtcbiAgICBsZXQgaWQgPSAnJ1xuICAgIC8vIEEgY29tcGFjdCBhbHRlcm5hdGl2ZSBmb3IgYGZvciAodmFyIGkgPSAwOyBpIDwgc3RlcDsgaSsrKWAuXG4gICAgbGV0IGkgPSBzaXplIHwgMFxuICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgLy8gYHwgMGAgaXMgbW9yZSBjb21wYWN0IGFuZCBmYXN0ZXIgdGhhbiBgTWF0aC5mbG9vcigpYC5cbiAgICAgICAgaWQgKz0gdXJsQWxwaGFiZXRbKE1hdGgucmFuZG9tKCkgKiA2NCkgfCAwXVxuICAgIH1cbiAgICByZXR1cm4gaWRcbn1cbiIsICIvKlxuIF8gICAgIF9fICAgICBfIF9fXG58IHwgIC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoqXG4gKiBUcnVlIHdoZW4gcnVubmluZyBpbnNpZGUgYSBicm93c2VyL3dlYnZpZXcgd2l0aCBhIERPTSBhdmFpbGFibGUuXG4gKiBGYWxzZSB1bmRlciBzZXJ2ZXItc2lkZSByZW5kZXJpbmcgKGUuZy4gYG5leHQgYnVpbGRgIHByZXJlbmRlcmluZyksXG4gKiB3aGVyZSBhcHBsaWNhdGlvbiBjb2RlIG1heSBpbXBvcnQgdGhlIHJ1bnRpbWUgbW9kdWxlIGV2ZW4gdGhvdWdoIG5vXG4gKiBXYWlscyBBUElzIGNhbiBhY3R1YWxseSBiZSB1c2VkICgjNDY3OSkuIE1vZHVsZXMgbXVzdCBub3QgdG91Y2hcbiAqIGB3aW5kb3dgL2Bkb2N1bWVudGAgYXQgaW1wb3J0IHRpbWUgZXhjZXB0IGJlaGluZCB0aGlzIGd1YXJkLlxuICovXG5leHBvcnQgY29uc3QgaGFzRE9NID0gdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiAmJiB0eXBlb2YgZG9jdW1lbnQgIT09IFwidW5kZWZpbmVkXCI7XG4iLCAiLypcbiBfICAgICBfXyAgICAgXyBfX1xufCB8ICAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbmltcG9ydCB7IG5hbm9pZCB9IGZyb20gXCIuL25hbm9pZC5qc1wiO1xuaW1wb3J0IHsgaGFzRE9NIH0gZnJvbSBcIi4vZW52aXJvbm1lbnQuanNcIjtcblxuLy8gUmVzb2x2ZWQgbGF6aWx5OiB3aW5kb3cgZG9lcyBub3QgZXhpc3Qgd2hlbiB0aGUgbW9kdWxlIGlzIGltcG9ydGVkIGR1cmluZ1xuLy8gc2VydmVyLXNpZGUgcmVuZGVyaW5nICgjNDY3OSksIGFuZCBub3RoaW5nIGNhbiBjYWxsIHRoZSBydW50aW1lIHRoZXJlLlxuZnVuY3Rpb24gcnVudGltZVVSTCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB3aW5kb3cubG9jYXRpb24ub3JpZ2luICsgXCIvd2FpbHMvcnVudGltZVwiO1xufVxuXG4vLyBTdGF5IHVuZGVyIFdlYlZpZXcyJ3MgfjJNQiByZXF1ZXN0IGJvZHkgYnVmZmVyaW5nIGxpbWl0IGluIFdlYlJlc291cmNlUmVxdWVzdGVkLlxuY29uc3QgQ0hVTktfVEhSRVNIT0xEID0gNTEyICogMTAyNDtcblxuLy8gUmUtZXhwb3J0IG5hbm9pZCBmb3IgY3VzdG9tIHRyYW5zcG9ydCBpbXBsZW1lbnRhdGlvbnNcbmV4cG9ydCB7IG5hbm9pZCB9O1xuXG4vLyBPYmplY3QgTmFtZXNcbmV4cG9ydCBjb25zdCBvYmplY3ROYW1lcyA9IE9iamVjdC5mcmVlemUoe1xuICAgIENhbGw6IDAsXG4gICAgQ2xpcGJvYXJkOiAxLFxuICAgIEFwcGxpY2F0aW9uOiAyLFxuICAgIEV2ZW50czogMyxcbiAgICBDb250ZXh0TWVudTogNCxcbiAgICBEaWFsb2c6IDUsXG4gICAgV2luZG93OiA2LFxuICAgIFNjcmVlbnM6IDcsXG4gICAgU3lzdGVtOiA4LFxuICAgIEJyb3dzZXI6IDksXG4gICAgQ2FuY2VsQ2FsbDogMTAsXG4gICAgSU9TOiAxMSxcbiAgICBBbmRyb2lkOiAxMixcbn0pO1xuZXhwb3J0IGxldCBjbGllbnRJZCA9IG5hbm9pZCgpO1xuXG4vKipcbiAqIFJ1bnRpbWVUcmFuc3BvcnQgZGVmaW5lcyB0aGUgaW50ZXJmYWNlIGZvciBjdXN0b20gSVBDIHRyYW5zcG9ydCBpbXBsZW1lbnRhdGlvbnMuXG4gKiBJbXBsZW1lbnQgdGhpcyBpbnRlcmZhY2UgdG8gdXNlIFdlYlNvY2tldHMsIGN1c3RvbSBwcm90b2NvbHMsIG9yIGFueSBvdGhlclxuICogdHJhbnNwb3J0IG1lY2hhbmlzbSBpbnN0ZWFkIG9mIHRoZSBkZWZhdWx0IEhUVFAgZmV0Y2guXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUnVudGltZVRyYW5zcG9ydCB7XG4gICAgLyoqXG4gICAgICogU2VuZCBhIHJ1bnRpbWUgY2FsbCBhbmQgcmV0dXJuIHRoZSByZXNwb25zZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBvYmplY3RJRCAtIFRoZSBXYWlscyBvYmplY3QgSUQgKDA9Q2FsbCwgMT1DbGlwYm9hcmQsIGV0Yy4pXG4gICAgICogQHBhcmFtIG1ldGhvZCAtIFRoZSBtZXRob2QgSUQgdG8gY2FsbFxuICAgICAqIEBwYXJhbSB3aW5kb3dOYW1lIC0gT3B0aW9uYWwgd2luZG93IG5hbWVcbiAgICAgKiBAcGFyYW0gYXJncyAtIEFyZ3VtZW50cyB0byBwYXNzICh3aWxsIGJlIEpTT04gc3RyaW5naWZpZWQgaWYgcHJlc2VudClcbiAgICAgKiBAcmV0dXJucyBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgcmVzcG9uc2UgZGF0YVxuICAgICAqL1xuICAgIGNhbGwob2JqZWN0SUQ6IG51bWJlciwgbWV0aG9kOiBudW1iZXIsIHdpbmRvd05hbWU6IHN0cmluZywgYXJnczogYW55KTogUHJvbWlzZTxhbnk+O1xufVxuXG4vKipcbiAqIEN1c3RvbSB0cmFuc3BvcnQgaW1wbGVtZW50YXRpb24gKGNhbiBiZSBzZXQgYnkgdXNlcilcbiAqL1xubGV0IGN1c3RvbVRyYW5zcG9ydDogUnVudGltZVRyYW5zcG9ydCB8IG51bGwgPSBudWxsO1xuXG4vKipcbiAqIFNldCBhIGN1c3RvbSB0cmFuc3BvcnQgZm9yIGFsbCBXYWlscyBydW50aW1lIGNhbGxzLlxuICogVGhpcyBhbGxvd3MgeW91IHRvIHJlcGxhY2UgdGhlIGRlZmF1bHQgSFRUUCBmZXRjaCB0cmFuc3BvcnQgd2l0aFxuICogV2ViU29ja2V0cywgY3VzdG9tIHByb3RvY29scywgb3IgYW55IG90aGVyIG1lY2hhbmlzbS5cbiAqXG4gKiBAcGFyYW0gdHJhbnNwb3J0IC0gWW91ciBjdXN0b20gdHJhbnNwb3J0IGltcGxlbWVudGF0aW9uXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGltcG9ydCB7IHNldFRyYW5zcG9ydCB9IGZyb20gJy93YWlscy9ydW50aW1lLmpzJztcbiAqXG4gKiBjb25zdCB3c1RyYW5zcG9ydCA9IHtcbiAqICAgY2FsbDogYXN5bmMgKG9iamVjdElELCBtZXRob2QsIHdpbmRvd05hbWUsIGFyZ3MpID0+IHtcbiAqICAgICAvLyBZb3VyIFdlYlNvY2tldCBpbXBsZW1lbnRhdGlvblxuICogICB9XG4gKiB9O1xuICpcbiAqIHNldFRyYW5zcG9ydCh3c1RyYW5zcG9ydCk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldFRyYW5zcG9ydCh0cmFuc3BvcnQ6IFJ1bnRpbWVUcmFuc3BvcnQgfCBudWxsKTogdm9pZCB7XG4gICAgY3VzdG9tVHJhbnNwb3J0ID0gdHJhbnNwb3J0O1xufVxuXG4vKipcbiAqIEdldCB0aGUgY3VycmVudCB0cmFuc3BvcnQgKHVzZWZ1bCBmb3IgZXh0ZW5kaW5nL3dyYXBwaW5nKVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0VHJhbnNwb3J0KCk6IFJ1bnRpbWVUcmFuc3BvcnQgfCBudWxsIHtcbiAgICByZXR1cm4gY3VzdG9tVHJhbnNwb3J0O1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgcnVudGltZSBjYWxsZXIgd2l0aCBzcGVjaWZpZWQgSUQuXG4gKlxuICogQHBhcmFtIG9iamVjdCAtIFRoZSBvYmplY3QgdG8gaW52b2tlIHRoZSBtZXRob2Qgb24uXG4gKiBAcGFyYW0gd2luZG93TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB3aW5kb3cuXG4gKiBAcmV0dXJuIFRoZSBuZXcgcnVudGltZSBjYWxsZXIgZnVuY3Rpb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBuZXdSdW50aW1lQ2FsbGVyKG9iamVjdDogbnVtYmVyLCB3aW5kb3dOYW1lOiBzdHJpbmcgPSAnJykge1xuICAgIHJldHVybiBmdW5jdGlvbiAobWV0aG9kOiBudW1iZXIsIGFyZ3M6IGFueSA9IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIHJ1bnRpbWVDYWxsV2l0aElEKG9iamVjdCwgbWV0aG9kLCB3aW5kb3dOYW1lLCBhcmdzKTtcbiAgICB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBydW50aW1lQ2FsbFdpdGhJRChvYmplY3RJRDogbnVtYmVyLCBtZXRob2Q6IG51bWJlciwgd2luZG93TmFtZTogc3RyaW5nLCBhcmdzOiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgIC8vIFVzZSBjdXN0b20gdHJhbnNwb3J0IGlmIGF2YWlsYWJsZVxuICAgIGlmIChjdXN0b21UcmFuc3BvcnQpIHtcbiAgICAgICAgcmV0dXJuIGN1c3RvbVRyYW5zcG9ydC5jYWxsKG9iamVjdElELCBtZXRob2QsIHdpbmRvd05hbWUsIGFyZ3MpO1xuICAgIH1cblxuICAgIC8vIERlZmF1bHQgSFRUUCBmZXRjaCB0cmFuc3BvcnRcbiAgICBsZXQgdXJsID0gbmV3IFVSTChydW50aW1lVVJMKCkpO1xuXG4gICAgbGV0IGJvZHk6IHsgb2JqZWN0OiBudW1iZXI7IG1ldGhvZDogbnVtYmVyLCBhcmdzPzogYW55IH0gPSB7XG4gICAgICBvYmplY3Q6IG9iamVjdElELFxuICAgICAgbWV0aG9kXG4gICAgfVxuICAgIGlmIChhcmdzICE9PSBudWxsICYmIGFyZ3MgIT09IHVuZGVmaW5lZCkge1xuICAgICAgYm9keS5hcmdzID0gYXJncztcbiAgICB9XG5cbiAgICBsZXQgaGVhZGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcbiAgICAgICAgW1wieC13YWlscy1jbGllbnQtaWRcIl06IGNsaWVudElkLFxuICAgICAgICBbXCJDb250ZW50LVR5cGVcIl06IFwiYXBwbGljYXRpb24vanNvblwiXG4gICAgfVxuICAgIGlmICh3aW5kb3dOYW1lKSB7XG4gICAgICAgIGhlYWRlcnNbXCJ4LXdhaWxzLXdpbmRvdy1uYW1lXCJdID0gd2luZG93TmFtZTtcbiAgICB9XG5cbiAgICBjb25zdCBib2R5U3RyID0gSlNPTi5zdHJpbmdpZnkoYm9keSk7XG4gICAgbGV0IHJlc3BvbnNlOiBSZXNwb25zZTtcbiAgICBpZiAoYm9keVN0ci5sZW5ndGggPiBDSFVOS19USFJFU0hPTEQpIHtcbiAgICAgICAgcmVzcG9uc2UgPSBhd2FpdCBzZW5kQ2h1bmtlZCh1cmwsIGhlYWRlcnMsIGJvZHlTdHIpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc3BvbnNlID0gYXdhaXQgZmV0Y2godXJsLCB7IG1ldGhvZDogJ1BPU1QnLCBoZWFkZXJzLCBib2R5OiBib2R5U3RyIH0pO1xuICAgIH1cbiAgICBpZiAoIXJlc3BvbnNlLm9rKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihhd2FpdCByZXNwb25zZS50ZXh0KCkpO1xuICAgIH1cblxuICAgIGlmICgocmVzcG9uc2UuaGVhZGVycy5nZXQoXCJDb250ZW50LVR5cGVcIik/LmluZGV4T2YoXCJhcHBsaWNhdGlvbi9qc29uXCIpID8/IC0xKSAhPT0gLTEpIHtcbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gcmVzcG9uc2UudGV4dCgpO1xuICAgIH1cbn1cblxuLy8gc2VuZENodW5rZWQgc3BsaXRzIGEgbGFyZ2Ugc2VyaWFsaXNlZCByZXF1ZXN0IGJvZHkgaW50byBDSFVOS19USFJFU0hPTEQtc2l6ZWRcbi8vIGJ5dGUgY2h1bmtzIGFuZCBzZW5kcyB0aGVtIHNlcmlhbGx5LiAgRW5jb2RpbmcgdG8gVVRGLTggYnl0ZXMgYmVmb3JlIHNsaWNpbmdcbi8vIHByZXZlbnRzIGNvcnJ1cHRpb24gb2Ygbm9uLUJNUCBjaGFyYWN0ZXJzIChzdXJyb2dhdGUgcGFpcnMpIHRoYXQgd291bGQgb2NjdXJcbi8vIHdoZW4gc3BsaXR0aW5nIGF0IEphdmFTY3JpcHQgc3RyaW5nIGluZGljZXMuICBUaGUgR28gdHJhbnNwb3J0IGFzc2VtYmxlcyB0aGVcbi8vIHJhdyBieXRlcyBiZWZvcmUgcHJvY2Vzc2luZy4gIE9ubHkgdGhlIGZpbmFsIGNodW5rJ3MgcmVzcG9uc2UgY2FycmllcyB0aGUgUlBDIHJlc3VsdC5cbmFzeW5jIGZ1bmN0aW9uIHNlbmRDaHVua2VkKHVybDogVVJMLCBoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+LCBib2R5U3RyOiBzdHJpbmcpOiBQcm9taXNlPFJlc3BvbnNlPiB7XG4gICAgY29uc3QgY2h1bmtJZCA9IG5hbm9pZCgpO1xuICAgIGNvbnN0IGJvZHlCeXRlcyA9IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShib2R5U3RyKTtcbiAgICBjb25zdCB0b3RhbENodW5rcyA9IE1hdGguY2VpbChib2R5Qnl0ZXMubGVuZ3RoIC8gQ0hVTktfVEhSRVNIT0xEKTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdG90YWxDaHVua3MgLSAxOyBpKyspIHtcbiAgICAgICAgY29uc3QgY2h1bmsgPSBib2R5Qnl0ZXMuc3ViYXJyYXkoaSAqIENIVU5LX1RIUkVTSE9MRCwgKGkgKyAxKSAqIENIVU5LX1RIUkVTSE9MRCk7XG4gICAgICAgIGNvbnN0IHJlc3AgPSBhd2FpdCBmZXRjaCh1cmwsIHtcbiAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICAgICAgIC4uLmhlYWRlcnMsXG4gICAgICAgICAgICAgICAgJ3gtd2FpbHMtY2h1bmstaWQnOiBjaHVua0lkLFxuICAgICAgICAgICAgICAgICd4LXdhaWxzLWNodW5rLWluZGV4JzogU3RyaW5nKGkpLFxuICAgICAgICAgICAgICAgICd4LXdhaWxzLWNodW5rLXRvdGFsJzogU3RyaW5nKHRvdGFsQ2h1bmtzKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBib2R5OiBjaHVuayxcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICghcmVzcC5vaykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGF3YWl0IHJlc3AudGV4dCgpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmZXRjaCh1cmwsIHtcbiAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICAgIC4uLmhlYWRlcnMsXG4gICAgICAgICAgICAneC13YWlscy1jaHVuay1pZCc6IGNodW5rSWQsXG4gICAgICAgICAgICAneC13YWlscy1jaHVuay1pbmRleCc6IFN0cmluZyh0b3RhbENodW5rcyAtIDEpLFxuICAgICAgICAgICAgJ3gtd2FpbHMtY2h1bmstdG90YWwnOiBTdHJpbmcodG90YWxDaHVua3MpLFxuICAgICAgICB9LFxuICAgICAgICBib2R5OiBib2R5Qnl0ZXMuc3ViYXJyYXkoKHRvdGFsQ2h1bmtzIC0gMSkgKiBDSFVOS19USFJFU0hPTEQpLFxuICAgIH0pO1xufVxuXG4vKipcbiAqIEFuZHJvaWQgV2ViVmlldyBjYW5ub3QgZGVsaXZlciBmZXRjaCgpIFBPU1QgYm9kaWVzIHRvXG4gKiBzaG91bGRJbnRlcmNlcHRSZXF1ZXN0LCBzbyB0aGUgZGVmYXVsdCBIVFRQIHRyYW5zcG9ydCBjYW5ub3QgcmVhY2ggR28uXG4gKiBXaGVuIHRoZSBBbmRyb2lkIEphdmFzY3JpcHRJbnRlcmZhY2UgYnJpZGdlICh3aW5kb3cud2FpbHMpIGlzIHByZXNlbnQsXG4gKiByb3V0ZSBydW50aW1lIGNhbGxzIHRocm91Z2ggaXQgaW5zdGVhZC4gUmVzcG9uc2VzIGFycml2ZSB2aWFcbiAqIHdpbmRvdy5fd2FpbHNBbmRyb2lkQ2FsbGJhY2ssIGludm9rZWQgYnkgdGhlIEphdmEgc2lkZS5cbiAqL1xuaW50ZXJmYWNlIEFuZHJvaWRKU0JyaWRnZSB7XG4gICAgaW52b2tlQXN5bmMoY2FsbGJhY2tJRDogc3RyaW5nLCBwYXlsb2FkOiBzdHJpbmcpOiB2b2lkO1xufVxuXG5jb25zdCBhbmRyb2lkQnJpZGdlOiBBbmRyb2lkSlNCcmlkZ2UgfCBudWxsID0gaGFzRE9NICYmXG4gICAgdHlwZW9mICh3aW5kb3cgYXMgYW55KS53YWlscz8uaW52b2tlQXN5bmMgPT09IFwiZnVuY3Rpb25cIiA/ICh3aW5kb3cgYXMgYW55KS53YWlscyA6IG51bGw7XG5cbmlmIChhbmRyb2lkQnJpZGdlKSB7XG4gICAgY29uc3QgcGVuZGluZyA9IG5ldyBNYXA8c3RyaW5nLCB7IHJlc29sdmU6ICh2YWx1ZTogYW55KSA9PiB2b2lkOyByZWplY3Q6IChyZWFzb246IGFueSkgPT4gdm9pZCB9PigpO1xuXG4gICAgKHdpbmRvdyBhcyBhbnkpLl93YWlsc0FuZHJvaWRDYWxsYmFjayA9IChpZDogc3RyaW5nLCByZXNwb25zZTogc3RyaW5nIHwgbnVsbCwgZXJyb3I6IHN0cmluZyB8IG51bGwpID0+IHtcbiAgICAgICAgY29uc3QgcHJvbWlzZSA9IHBlbmRpbmcuZ2V0KGlkKTtcbiAgICAgICAgaWYgKCFwcm9taXNlKSByZXR1cm47XG4gICAgICAgIHBlbmRpbmcuZGVsZXRlKGlkKTtcbiAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICBwcm9taXNlLnJlamVjdChuZXcgRXJyb3IoZXJyb3IpKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgZW52ZWxvcGUgPSBKU09OLnBhcnNlKHJlc3BvbnNlID8/IFwie31cIik7XG4gICAgICAgICAgICBpZiAoIWVudmVsb3BlLm9rKSB7XG4gICAgICAgICAgICAgICAgcHJvbWlzZS5yZWplY3QobmV3IEVycm9yKGVudmVsb3BlLmVycm9yID8/IFwidW5rbm93biBydW50aW1lIGNhbGwgZXJyb3JcIikpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHByb21pc2UucmVzb2x2ZShcInRleHRcIiBpbiBlbnZlbG9wZSA/IGVudmVsb3BlLnRleHQgOiBlbnZlbG9wZS5kYXRhKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgcHJvbWlzZS5yZWplY3QoZSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgY3VzdG9tVHJhbnNwb3J0ID0ge1xuICAgICAgICBjYWxsKG9iamVjdElEOiBudW1iZXIsIG1ldGhvZDogbnVtYmVyLCB3aW5kb3dOYW1lOiBzdHJpbmcsIGFyZ3M6IGFueSk6IFByb21pc2U8YW55PiB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGlkID0gbmFub2lkKCk7XG4gICAgICAgICAgICAgICAgcGVuZGluZy5zZXQoaWQsIHsgcmVzb2x2ZSwgcmVqZWN0IH0pO1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGFuZHJvaWRCcmlkZ2UuaW52b2tlQXN5bmMoaWQsIEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdDogb2JqZWN0SUQsXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRob2Q6IG1ldGhvZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHdpbmRvd05hbWU6IHdpbmRvd05hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICBhcmdzOiBhcmdzID8/IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICBjbGllbnRJZDogY2xpZW50SWQsXG4gICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIERvbid0IGxlYWsgdGhlIHBlbmRpbmcgZW50cnkgaWYgZGlzcGF0Y2ggdGhyb3dzIHN5bmNocm9ub3VzbHlcbiAgICAgICAgICAgICAgICAgICAgcGVuZGluZy5kZWxldGUoaWQpO1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgfTtcbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuaW1wb3J0IHtuZXdSdW50aW1lQ2FsbGVyLCBvYmplY3ROYW1lc30gZnJvbSBcIi4vcnVudGltZS5qc1wiO1xuXG4vLyBzZXR1cFxuaW1wb3J0IHsgaGFzRE9NIH0gZnJvbSBcIi4vZW52aXJvbm1lbnQuanNcIjtcblxuaWYgKGhhc0RPTSkge1xuICAgIHdpbmRvdy5fd2FpbHMgPSB3aW5kb3cuX3dhaWxzIHx8IHt9O1xufVxuXG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcihvYmplY3ROYW1lcy5EaWFsb2cpO1xuXG4vLyBEZWZpbmUgY29uc3RhbnRzIGZyb20gdGhlIGBtZXRob2RzYCBvYmplY3QgaW4gVGl0bGUgQ2FzZVxuY29uc3QgRGlhbG9nSW5mbyA9IDA7XG5jb25zdCBEaWFsb2dXYXJuaW5nID0gMTtcbmNvbnN0IERpYWxvZ0Vycm9yID0gMjtcbmNvbnN0IERpYWxvZ1F1ZXN0aW9uID0gMztcbmNvbnN0IERpYWxvZ09wZW5GaWxlID0gNDtcbmNvbnN0IERpYWxvZ1NhdmVGaWxlID0gNTtcblxuZXhwb3J0IGludGVyZmFjZSBPcGVuRmlsZURpYWxvZ09wdGlvbnMge1xuICAgIC8qKiBJbmRpY2F0ZXMgaWYgZGlyZWN0b3JpZXMgY2FuIGJlIGNob3Nlbi4gKi9cbiAgICBDYW5DaG9vc2VEaXJlY3Rvcmllcz86IGJvb2xlYW47XG4gICAgLyoqIEluZGljYXRlcyBpZiBmaWxlcyBjYW4gYmUgY2hvc2VuLiAqL1xuICAgIENhbkNob29zZUZpbGVzPzogYm9vbGVhbjtcbiAgICAvKiogSW5kaWNhdGVzIGlmIGRpcmVjdG9yaWVzIGNhbiBiZSBjcmVhdGVkLiAqL1xuICAgIENhbkNyZWF0ZURpcmVjdG9yaWVzPzogYm9vbGVhbjtcbiAgICAvKiogSW5kaWNhdGVzIGlmIGhpZGRlbiBmaWxlcyBzaG91bGQgYmUgc2hvd24uICovXG4gICAgU2hvd0hpZGRlbkZpbGVzPzogYm9vbGVhbjtcbiAgICAvKiogSW5kaWNhdGVzIGlmIGFsaWFzZXMgc2hvdWxkIGJlIHJlc29sdmVkLiAqL1xuICAgIFJlc29sdmVzQWxpYXNlcz86IGJvb2xlYW47XG4gICAgLyoqIEluZGljYXRlcyBpZiBtdWx0aXBsZSBzZWxlY3Rpb24gaXMgYWxsb3dlZC4gKi9cbiAgICBBbGxvd3NNdWx0aXBsZVNlbGVjdGlvbj86IGJvb2xlYW47XG4gICAgLyoqIEluZGljYXRlcyBpZiB0aGUgZXh0ZW5zaW9uIHNob3VsZCBiZSBoaWRkZW4uICovXG4gICAgSGlkZUV4dGVuc2lvbj86IGJvb2xlYW47XG4gICAgLyoqIEluZGljYXRlcyBpZiBoaWRkZW4gZXh0ZW5zaW9ucyBjYW4gYmUgc2VsZWN0ZWQuICovXG4gICAgQ2FuU2VsZWN0SGlkZGVuRXh0ZW5zaW9uPzogYm9vbGVhbjtcbiAgICAvKiogSW5kaWNhdGVzIGlmIGZpbGUgcGFja2FnZXMgc2hvdWxkIGJlIHRyZWF0ZWQgYXMgZGlyZWN0b3JpZXMuICovXG4gICAgVHJlYXRzRmlsZVBhY2thZ2VzQXNEaXJlY3Rvcmllcz86IGJvb2xlYW47XG4gICAgLyoqIEluZGljYXRlcyBpZiBvdGhlciBmaWxlIHR5cGVzIGFyZSBhbGxvd2VkLiAqL1xuICAgIEFsbG93c090aGVyRmlsZXR5cGVzPzogYm9vbGVhbjtcbiAgICAvKiogQXJyYXkgb2YgZmlsZSBmaWx0ZXJzLiAqL1xuICAgIEZpbHRlcnM/OiBGaWxlRmlsdGVyW107XG4gICAgLyoqIFRpdGxlIG9mIHRoZSBkaWFsb2cuICovXG4gICAgVGl0bGU/OiBzdHJpbmc7XG4gICAgLyoqIE1lc3NhZ2UgdG8gc2hvdyBpbiB0aGUgZGlhbG9nLiAqL1xuICAgIE1lc3NhZ2U/OiBzdHJpbmc7XG4gICAgLyoqIFRleHQgdG8gZGlzcGxheSBvbiB0aGUgYnV0dG9uLiAqL1xuICAgIEJ1dHRvblRleHQ/OiBzdHJpbmc7XG4gICAgLyoqIERpcmVjdG9yeSB0byBvcGVuIGluIHRoZSBkaWFsb2cuICovXG4gICAgRGlyZWN0b3J5Pzogc3RyaW5nO1xuICAgIC8qKiBJbmRpY2F0ZXMgaWYgdGhlIGRpYWxvZyBzaG91bGQgYXBwZWFyIGRldGFjaGVkIGZyb20gdGhlIG1haW4gd2luZG93LiAqL1xuICAgIERldGFjaGVkPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTYXZlRmlsZURpYWxvZ09wdGlvbnMge1xuICAgIC8qKiBEZWZhdWx0IGZpbGVuYW1lIHRvIHVzZSBpbiB0aGUgZGlhbG9nLiAqL1xuICAgIEZpbGVuYW1lPzogc3RyaW5nO1xuICAgIC8qKiBJbmRpY2F0ZXMgaWYgZGlyZWN0b3JpZXMgY2FuIGJlIGNob3Nlbi4gKi9cbiAgICBDYW5DaG9vc2VEaXJlY3Rvcmllcz86IGJvb2xlYW47XG4gICAgLyoqIEluZGljYXRlcyBpZiBmaWxlcyBjYW4gYmUgY2hvc2VuLiAqL1xuICAgIENhbkNob29zZUZpbGVzPzogYm9vbGVhbjtcbiAgICAvKiogSW5kaWNhdGVzIGlmIGRpcmVjdG9yaWVzIGNhbiBiZSBjcmVhdGVkLiAqL1xuICAgIENhbkNyZWF0ZURpcmVjdG9yaWVzPzogYm9vbGVhbjtcbiAgICAvKiogSW5kaWNhdGVzIGlmIGhpZGRlbiBmaWxlcyBzaG91bGQgYmUgc2hvd24uICovXG4gICAgU2hvd0hpZGRlbkZpbGVzPzogYm9vbGVhbjtcbiAgICAvKiogSW5kaWNhdGVzIGlmIGFsaWFzZXMgc2hvdWxkIGJlIHJlc29sdmVkLiAqL1xuICAgIFJlc29sdmVzQWxpYXNlcz86IGJvb2xlYW47XG4gICAgLyoqIEluZGljYXRlcyBpZiB0aGUgZXh0ZW5zaW9uIHNob3VsZCBiZSBoaWRkZW4uICovXG4gICAgSGlkZUV4dGVuc2lvbj86IGJvb2xlYW47XG4gICAgLyoqIEluZGljYXRlcyBpZiBoaWRkZW4gZXh0ZW5zaW9ucyBjYW4gYmUgc2VsZWN0ZWQuICovXG4gICAgQ2FuU2VsZWN0SGlkZGVuRXh0ZW5zaW9uPzogYm9vbGVhbjtcbiAgICAvKiogSW5kaWNhdGVzIGlmIGZpbGUgcGFja2FnZXMgc2hvdWxkIGJlIHRyZWF0ZWQgYXMgZGlyZWN0b3JpZXMuICovXG4gICAgVHJlYXRzRmlsZVBhY2thZ2VzQXNEaXJlY3Rvcmllcz86IGJvb2xlYW47XG4gICAgLyoqIEluZGljYXRlcyBpZiBvdGhlciBmaWxlIHR5cGVzIGFyZSBhbGxvd2VkLiAqL1xuICAgIEFsbG93c090aGVyRmlsZXR5cGVzPzogYm9vbGVhbjtcbiAgICAvKiogQXJyYXkgb2YgZmlsZSBmaWx0ZXJzLiAqL1xuICAgIEZpbHRlcnM/OiBGaWxlRmlsdGVyW107XG4gICAgLyoqIFRpdGxlIG9mIHRoZSBkaWFsb2cuICovXG4gICAgVGl0bGU/OiBzdHJpbmc7XG4gICAgLyoqIE1lc3NhZ2UgdG8gc2hvdyBpbiB0aGUgZGlhbG9nLiAqL1xuICAgIE1lc3NhZ2U/OiBzdHJpbmc7XG4gICAgLyoqIFRleHQgdG8gZGlzcGxheSBvbiB0aGUgYnV0dG9uLiAqL1xuICAgIEJ1dHRvblRleHQ/OiBzdHJpbmc7XG4gICAgLyoqIERpcmVjdG9yeSB0byBvcGVuIGluIHRoZSBkaWFsb2cuICovXG4gICAgRGlyZWN0b3J5Pzogc3RyaW5nO1xuICAgIC8qKiBJbmRpY2F0ZXMgaWYgdGhlIGRpYWxvZyBzaG91bGQgYXBwZWFyIGRldGFjaGVkIGZyb20gdGhlIG1haW4gd2luZG93LiAqL1xuICAgIERldGFjaGVkPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBNZXNzYWdlRGlhbG9nT3B0aW9ucyB7XG4gICAgLyoqIFRoZSB0aXRsZSBvZiB0aGUgZGlhbG9nIHdpbmRvdy4gKi9cbiAgICBUaXRsZT86IHN0cmluZztcbiAgICAvKiogVGhlIG1haW4gbWVzc2FnZSB0byBzaG93IGluIHRoZSBkaWFsb2cuICovXG4gICAgTWVzc2FnZT86IHN0cmluZztcbiAgICAvKiogQXJyYXkgb2YgYnV0dG9uIG9wdGlvbnMgdG8gc2hvdyBpbiB0aGUgZGlhbG9nLiAqL1xuICAgIEJ1dHRvbnM/OiBCdXR0b25bXTtcbiAgICAvKiogVHJ1ZSBpZiB0aGUgZGlhbG9nIHNob3VsZCBhcHBlYXIgZGV0YWNoZWQgZnJvbSB0aGUgbWFpbiB3aW5kb3cgKGlmIGFwcGxpY2FibGUpLiAqL1xuICAgIERldGFjaGVkPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBCdXR0b24ge1xuICAgIC8qKiBUZXh0IHRoYXQgYXBwZWFycyB3aXRoaW4gdGhlIGJ1dHRvbi4gKi9cbiAgICBMYWJlbD86IHN0cmluZztcbiAgICAvKiogVHJ1ZSBpZiB0aGUgYnV0dG9uIHNob3VsZCBjYW5jZWwgYW4gb3BlcmF0aW9uIHdoZW4gY2xpY2tlZC4gKi9cbiAgICBJc0NhbmNlbD86IGJvb2xlYW47XG4gICAgLyoqIFRydWUgaWYgdGhlIGJ1dHRvbiBzaG91bGQgYmUgdGhlIGRlZmF1bHQgYWN0aW9uIHdoZW4gdGhlIHVzZXIgcHJlc3NlcyBlbnRlci4gKi9cbiAgICBJc0RlZmF1bHQ/OiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEZpbGVGaWx0ZXIge1xuICAgIC8qKiBEaXNwbGF5IG5hbWUgZm9yIHRoZSBmaWx0ZXIsIGl0IGNvdWxkIGJlIFwiVGV4dCBGaWxlc1wiLCBcIkltYWdlc1wiIGV0Yy4gKi9cbiAgICBEaXNwbGF5TmFtZT86IHN0cmluZztcbiAgICAvKiogUGF0dGVybiB0byBtYXRjaCBmb3IgdGhlIGZpbHRlciwgZS5nLiBcIioudHh0OyoubWRcIiBmb3IgdGV4dCBtYXJrZG93biBmaWxlcy4gKi9cbiAgICBQYXR0ZXJuPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFByZXNlbnRzIGEgZGlhbG9nIG9mIHNwZWNpZmllZCB0eXBlIHdpdGggdGhlIGdpdmVuIG9wdGlvbnMuXG4gKlxuICogQHBhcmFtIHR5cGUgLSBEaWFsb2cgdHlwZS5cbiAqIEBwYXJhbSBvcHRpb25zIC0gT3B0aW9ucyBmb3IgdGhlIGRpYWxvZy5cbiAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggcmVzdWx0IG9mIGRpYWxvZy5cbiAqL1xuZnVuY3Rpb24gZGlhbG9nKHR5cGU6IG51bWJlciwgb3B0aW9uczogTWVzc2FnZURpYWxvZ09wdGlvbnMgfCBPcGVuRmlsZURpYWxvZ09wdGlvbnMgfCBTYXZlRmlsZURpYWxvZ09wdGlvbnMgPSB7fSk6IFByb21pc2U8YW55PiB7XG4gICAgcmV0dXJuIGNhbGwodHlwZSwgb3B0aW9ucyk7XG59XG5cbi8qKlxuICogUHJlc2VudHMgYW4gaW5mbyBkaWFsb2cuXG4gKlxuICogQHBhcmFtIG9wdGlvbnMgLSBEaWFsb2cgb3B0aW9uc1xuICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgbGFiZWwgb2YgdGhlIGNob3NlbiBidXR0b24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJbmZvKG9wdGlvbnM6IE1lc3NhZ2VEaWFsb2dPcHRpb25zKTogUHJvbWlzZTxzdHJpbmc+IHsgcmV0dXJuIGRpYWxvZyhEaWFsb2dJbmZvLCBvcHRpb25zKTsgfVxuXG4vKipcbiAqIFByZXNlbnRzIGEgd2FybmluZyBkaWFsb2cuXG4gKlxuICogQHBhcmFtIG9wdGlvbnMgLSBEaWFsb2cgb3B0aW9ucy5cbiAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIGxhYmVsIG9mIHRoZSBjaG9zZW4gYnV0dG9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gV2FybmluZyhvcHRpb25zOiBNZXNzYWdlRGlhbG9nT3B0aW9ucyk6IFByb21pc2U8c3RyaW5nPiB7IHJldHVybiBkaWFsb2coRGlhbG9nV2FybmluZywgb3B0aW9ucyk7IH1cblxuLyoqXG4gKiBQcmVzZW50cyBhbiBlcnJvciBkaWFsb2cuXG4gKlxuICogQHBhcmFtIG9wdGlvbnMgLSBEaWFsb2cgb3B0aW9ucy5cbiAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIGxhYmVsIG9mIHRoZSBjaG9zZW4gYnV0dG9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gRXJyb3Iob3B0aW9uczogTWVzc2FnZURpYWxvZ09wdGlvbnMpOiBQcm9taXNlPHN0cmluZz4geyByZXR1cm4gZGlhbG9nKERpYWxvZ0Vycm9yLCBvcHRpb25zKTsgfVxuXG4vKipcbiAqIFByZXNlbnRzIGEgcXVlc3Rpb24gZGlhbG9nLlxuICpcbiAqIEBwYXJhbSBvcHRpb25zIC0gRGlhbG9nIG9wdGlvbnMuXG4gKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBsYWJlbCBvZiB0aGUgY2hvc2VuIGJ1dHRvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFF1ZXN0aW9uKG9wdGlvbnM6IE1lc3NhZ2VEaWFsb2dPcHRpb25zKTogUHJvbWlzZTxzdHJpbmc+IHsgcmV0dXJuIGRpYWxvZyhEaWFsb2dRdWVzdGlvbiwgb3B0aW9ucyk7IH1cblxuLyoqXG4gKiBQcmVzZW50cyBhIGZpbGUgc2VsZWN0aW9uIGRpYWxvZyB0byBwaWNrIG9uZSBvciBtb3JlIGZpbGVzIHRvIG9wZW4uXG4gKlxuICogQHBhcmFtIG9wdGlvbnMgLSBEaWFsb2cgb3B0aW9ucy5cbiAqIEByZXR1cm5zIFNlbGVjdGVkIGZpbGUgb3IgbGlzdCBvZiBmaWxlcywgb3IgYSBibGFuayBzdHJpbmcvZW1wdHkgbGlzdCBpZiBubyBmaWxlIGhhcyBiZWVuIHNlbGVjdGVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gT3BlbkZpbGUob3B0aW9uczogT3BlbkZpbGVEaWFsb2dPcHRpb25zICYgeyBBbGxvd3NNdWx0aXBsZVNlbGVjdGlvbjogdHJ1ZSB9KTogUHJvbWlzZTxzdHJpbmdbXT47XG5leHBvcnQgZnVuY3Rpb24gT3BlbkZpbGUob3B0aW9uczogT3BlbkZpbGVEaWFsb2dPcHRpb25zICYgeyBBbGxvd3NNdWx0aXBsZVNlbGVjdGlvbj86IGZhbHNlIHwgdW5kZWZpbmVkIH0pOiBQcm9taXNlPHN0cmluZz47XG5leHBvcnQgZnVuY3Rpb24gT3BlbkZpbGUob3B0aW9uczogT3BlbkZpbGVEaWFsb2dPcHRpb25zKTogUHJvbWlzZTxzdHJpbmcgfCBzdHJpbmdbXT47XG5leHBvcnQgZnVuY3Rpb24gT3BlbkZpbGUob3B0aW9uczogT3BlbkZpbGVEaWFsb2dPcHRpb25zKTogUHJvbWlzZTxzdHJpbmcgfCBzdHJpbmdbXT4geyByZXR1cm4gZGlhbG9nKERpYWxvZ09wZW5GaWxlLCBvcHRpb25zKSA/PyBbXTsgfVxuXG4vKipcbiAqIFByZXNlbnRzIGEgZmlsZSBzZWxlY3Rpb24gZGlhbG9nIHRvIHBpY2sgYSBmaWxlIHRvIHNhdmUuXG4gKlxuICogQHBhcmFtIG9wdGlvbnMgLSBEaWFsb2cgb3B0aW9ucy5cbiAqIEByZXR1cm5zIFNlbGVjdGVkIGZpbGUsIG9yIGEgYmxhbmsgc3RyaW5nIGlmIG5vIGZpbGUgaGFzIGJlZW4gc2VsZWN0ZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTYXZlRmlsZShvcHRpb25zOiBTYXZlRmlsZURpYWxvZ09wdGlvbnMpOiBQcm9taXNlPHN0cmluZz4geyByZXR1cm4gZGlhbG9nKERpYWxvZ1NhdmVGaWxlLCBvcHRpb25zKTsgfVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG5pbXBvcnQgeyBuZXdSdW50aW1lQ2FsbGVyLCBvYmplY3ROYW1lcyB9IGZyb20gXCIuL3J1bnRpbWUuanNcIjtcbmltcG9ydCB7IGV2ZW50TGlzdGVuZXJzLCBMaXN0ZW5lciwgbGlzdGVuZXJPZmYgfSBmcm9tIFwiLi9saXN0ZW5lci5qc1wiO1xuaW1wb3J0IHsgRXZlbnRzIGFzIENyZWF0ZSB9IGZyb20gXCIuL2NyZWF0ZS5qc1wiO1xuaW1wb3J0IHsgVHlwZXMgfSBmcm9tIFwiLi9ldmVudF90eXBlcy5qc1wiO1xuXG4vLyBTZXR1cFxuaW1wb3J0IHsgaGFzRE9NIH0gZnJvbSBcIi4vZW52aXJvbm1lbnQuanNcIjtcblxuaWYgKGhhc0RPTSkge1xuICAgIHdpbmRvdy5fd2FpbHMgPSB3aW5kb3cuX3dhaWxzIHx8IHt9O1xuICAgIHdpbmRvdy5fd2FpbHMuZGlzcGF0Y2hXYWlsc0V2ZW50ID0gZGlzcGF0Y2hXYWlsc0V2ZW50O1xufVxuXG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcihvYmplY3ROYW1lcy5FdmVudHMpO1xuY29uc3QgRW1pdE1ldGhvZCA9IDA7XG5cbmV4cG9ydCAqIGZyb20gXCIuL2V2ZW50X3R5cGVzLmpzXCI7XG5cbi8qKlxuICogQSB0YWJsZSBvZiBkYXRhIHR5cGVzIGZvciBhbGwga25vd24gZXZlbnRzLlxuICogV2lsbCBiZSBtb25rZXktcGF0Y2hlZCBieSB0aGUgYmluZGluZyBnZW5lcmF0b3IuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ3VzdG9tRXZlbnRzIHt9XG5cbi8qKlxuICogRWl0aGVyIGEga25vd24gZXZlbnQgbmFtZSBvciBhbiBhcmJpdHJhcnkgc3RyaW5nLlxuICovXG5leHBvcnQgdHlwZSBXYWlsc0V2ZW50TmFtZTxFIGV4dGVuZHMga2V5b2YgQ3VzdG9tRXZlbnRzID0ga2V5b2YgQ3VzdG9tRXZlbnRzPiA9IEUgfCAoc3RyaW5nICYge30pO1xuXG4vKipcbiAqIFVuaW9uIG9mIGFsbCBrbm93biBzeXN0ZW0gZXZlbnQgbmFtZXMuXG4gKi9cbnR5cGUgU3lzdGVtRXZlbnROYW1lID0ge1xuICAgIFtLIGluIGtleW9mICh0eXBlb2YgVHlwZXMpXTogKHR5cGVvZiBUeXBlcylbS11ba2V5b2YgKCh0eXBlb2YgVHlwZXMpW0tdKV1cbn0gZXh0ZW5kcyAoaW5mZXIgTSkgPyBNW2tleW9mIE1dIDogbmV2ZXI7XG5cbi8qKlxuICogVGhlIGRhdGEgdHlwZSBhc3NvY2lhdGVkIHRvIGEgZ2l2ZW4gZXZlbnQuXG4gKi9cbmV4cG9ydCB0eXBlIFdhaWxzRXZlbnREYXRhPEUgZXh0ZW5kcyBXYWlsc0V2ZW50TmFtZSA9IFdhaWxzRXZlbnROYW1lPiA9XG4gICAgRSBleHRlbmRzIGtleW9mIEN1c3RvbUV2ZW50cyA/IEN1c3RvbUV2ZW50c1tFXSA6IChFIGV4dGVuZHMgU3lzdGVtRXZlbnROYW1lID8gdm9pZCA6IGFueSk7XG5cbi8qKlxuICogVGhlIHR5cGUgb2YgaGFuZGxlcnMgZm9yIGEgZ2l2ZW4gZXZlbnQuXG4gKi9cbmV4cG9ydCB0eXBlIFdhaWxzRXZlbnRDYWxsYmFjazxFIGV4dGVuZHMgV2FpbHNFdmVudE5hbWUgPSBXYWlsc0V2ZW50TmFtZT4gPSAoZXY6IFdhaWxzRXZlbnQ8RT4pID0+IHZvaWQ7XG5cbi8qKlxuICogUmVwcmVzZW50cyBhIHN5c3RlbSBldmVudCBvciBhIGN1c3RvbSBldmVudCBlbWl0dGVkIHRocm91Z2ggd2FpbHMtcHJvdmlkZWQgZmFjaWxpdGllcy5cbiAqL1xuZXhwb3J0IGNsYXNzIFdhaWxzRXZlbnQ8RSBleHRlbmRzIFdhaWxzRXZlbnROYW1lID0gV2FpbHNFdmVudE5hbWU+IHtcbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgZXZlbnQuXG4gICAgICovXG4gICAgbmFtZTogRTtcblxuICAgIC8qKlxuICAgICAqIE9wdGlvbmFsIGRhdGEgYXNzb2NpYXRlZCB3aXRoIHRoZSBlbWl0dGVkIGV2ZW50LlxuICAgICAqL1xuICAgIGRhdGE6IFdhaWxzRXZlbnREYXRhPEU+O1xuXG4gICAgLyoqXG4gICAgICogTmFtZSBvZiB0aGUgb3JpZ2luYXRpbmcgd2luZG93LiBPbWl0dGVkIGZvciBhcHBsaWNhdGlvbiBldmVudHMuXG4gICAgICogV2lsbCBiZSBvdmVycmlkZGVuIGlmIHNldCBtYW51YWxseS5cbiAgICAgKi9cbiAgICBzZW5kZXI/OiBzdHJpbmc7XG5cbiAgICBjb25zdHJ1Y3RvcihuYW1lOiBFLCBkYXRhOiBXYWlsc0V2ZW50RGF0YTxFPik7XG4gICAgY29uc3RydWN0b3IobmFtZTogV2FpbHNFdmVudERhdGE8RT4gZXh0ZW5kcyBudWxsIHwgdm9pZCA/IEUgOiBuZXZlcilcbiAgICBjb25zdHJ1Y3RvcihuYW1lOiBFLCBkYXRhPzogYW55KSB7XG4gICAgICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gICAgICAgIHRoaXMuZGF0YSA9IGRhdGEgPz8gbnVsbDtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGRpc3BhdGNoV2FpbHNFdmVudChldmVudDogYW55KSB7XG4gICAgbGV0IGxpc3RlbmVycyA9IGV2ZW50TGlzdGVuZXJzLmdldChldmVudC5uYW1lKTtcbiAgICBpZiAoIWxpc3RlbmVycykge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbGV0IHdhaWxzRXZlbnQgPSBuZXcgV2FpbHNFdmVudChcbiAgICAgICAgZXZlbnQubmFtZSxcbiAgICAgICAgKGV2ZW50Lm5hbWUgaW4gQ3JlYXRlKSA/IENyZWF0ZVtldmVudC5uYW1lXShldmVudC5kYXRhKSA6IGV2ZW50LmRhdGFcbiAgICApO1xuICAgIGlmICgnc2VuZGVyJyBpbiBldmVudCkge1xuICAgICAgICB3YWlsc0V2ZW50LnNlbmRlciA9IGV2ZW50LnNlbmRlcjtcbiAgICB9XG5cbiAgICAvLyBEaXNwYXRjaCB0byBhIHNuYXBzaG90LCB0aGVuIHJlbW92ZSBhbGwgZXhwaXJlZCBsaXN0ZW5lcnMgaW4gYSBzaW5nbGVcbiAgICAvLyBwb3N0LWRpc3BhdGNoIGZpbHRlciBvZiB0aGUgbGl2ZSBtYXAuXG4gICAgLy8gLSBXcml0aW5nIHRoZSBzbmFwc2hvdCBiYWNrIHdob2xlc2FsZSB3b3VsZCB1bmRvIHN1YnNjcmlwdGlvbiBjaGFuZ2VzXG4gICAgLy8gICBtYWRlIGluc2lkZSBhIGhhbmRsZXIgKCM0MzkzKS5cbiAgICAvLyAtIENhbGxpbmcgbGlzdGVuZXJPZmYoKSBwZXIgZXhwaXJlZCBsaXN0ZW5lciBpbnNpZGUgdGhlIGxvb3AgaXMgTyhuXHUwMEIyKVxuICAgIC8vICAgd2hlbiBtYW55IGxpc3RlbmVycyBleHBpcmUgb24gdGhlIHNhbWUgZXZlbnQuXG4gICAgLy8gRmlsdGVyaW5nIHRoZSBsaXZlIGFycmF5IG9uY2UgYWZ0ZXIgZGlzcGF0Y2ggaXMgTyhuKSBhbmQgc3RpbGwgaG9ub3Vyc1xuICAgIC8vIGFueSBsaXN0ZW5lcnMgYWRkZWQgb3IgcmVtb3ZlZCBieSBoYW5kbGVycyBkdXJpbmcgZGlzcGF0Y2guXG4gICAgY29uc3QgZXhwaXJlZCA9IG5ldyBTZXQ8TGlzdGVuZXI+KCk7XG4gICAgZm9yIChjb25zdCBsaXN0ZW5lciBvZiBsaXN0ZW5lcnMuc2xpY2UoKSkge1xuICAgICAgICBpZiAobGlzdGVuZXIuZGlzcGF0Y2god2FpbHNFdmVudCkpIHtcbiAgICAgICAgICAgIGV4cGlyZWQuYWRkKGxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoZXhwaXJlZC5zaXplID4gMCkge1xuICAgICAgICBjb25zdCBsaXZlID0gZXZlbnRMaXN0ZW5lcnMuZ2V0KGV2ZW50Lm5hbWUpO1xuICAgICAgICBpZiAobGl2ZSkge1xuICAgICAgICAgICAgY29uc3QgcmVtYWluaW5nID0gbGl2ZS5maWx0ZXIobCA9PiAhZXhwaXJlZC5oYXMobCkpO1xuICAgICAgICAgICAgaWYgKHJlbWFpbmluZy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICBldmVudExpc3RlbmVycy5kZWxldGUoZXZlbnQubmFtZSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGV2ZW50TGlzdGVuZXJzLnNldChldmVudC5uYW1lLCByZW1haW5pbmcpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG4vKipcbiAqIFJlZ2lzdGVyIGEgY2FsbGJhY2sgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIG11bHRpcGxlIHRpbWVzIGZvciBhIHNwZWNpZmljIGV2ZW50LlxuICpcbiAqIEBwYXJhbSBldmVudE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdG8gcmVnaXN0ZXIgdGhlIGNhbGxiYWNrIGZvci5cbiAqIEBwYXJhbSBjYWxsYmFjayAtIFRoZSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBjYWxsZWQgd2hlbiB0aGUgZXZlbnQgaXMgdHJpZ2dlcmVkLlxuICogQHBhcmFtIG1heENhbGxiYWNrcyAtIFRoZSBtYXhpbXVtIG51bWJlciBvZiB0aW1lcyB0aGUgY2FsbGJhY2sgY2FuIGJlIGNhbGxlZCBmb3IgdGhlIGV2ZW50LiBPbmNlIHRoZSBtYXhpbXVtIG51bWJlciBpcyByZWFjaGVkLCB0aGUgY2FsbGJhY2sgd2lsbCBubyBsb25nZXIgYmUgY2FsbGVkLlxuICogQHJldHVybnMgQSBmdW5jdGlvbiB0aGF0LCB3aGVuIGNhbGxlZCwgd2lsbCB1bnJlZ2lzdGVyIHRoZSBjYWxsYmFjayBmcm9tIHRoZSBldmVudC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIE9uTXVsdGlwbGU8RSBleHRlbmRzIFdhaWxzRXZlbnROYW1lID0gV2FpbHNFdmVudE5hbWU+KGV2ZW50TmFtZTogRSwgY2FsbGJhY2s6IFdhaWxzRXZlbnRDYWxsYmFjazxFPiwgbWF4Q2FsbGJhY2tzOiBudW1iZXIpIHtcbiAgICBsZXQgbGlzdGVuZXJzID0gZXZlbnRMaXN0ZW5lcnMuZ2V0KGV2ZW50TmFtZSkgfHwgW107XG4gICAgY29uc3QgdGhpc0xpc3RlbmVyID0gbmV3IExpc3RlbmVyKGV2ZW50TmFtZSwgY2FsbGJhY2ssIG1heENhbGxiYWNrcyk7XG4gICAgbGlzdGVuZXJzLnB1c2godGhpc0xpc3RlbmVyKTtcbiAgICBldmVudExpc3RlbmVycy5zZXQoZXZlbnROYW1lLCBsaXN0ZW5lcnMpO1xuICAgIHJldHVybiAoKSA9PiBsaXN0ZW5lck9mZih0aGlzTGlzdGVuZXIpO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVycyBhIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIHdoZW4gdGhlIHNwZWNpZmllZCBldmVudCBvY2N1cnMuXG4gKlxuICogQHBhcmFtIGV2ZW50TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byByZWdpc3RlciB0aGUgY2FsbGJhY2sgZm9yLlxuICogQHBhcmFtIGNhbGxiYWNrIC0gVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudCBpcyB0cmlnZ2VyZWQuXG4gKiBAcmV0dXJucyBBIGZ1bmN0aW9uIHRoYXQsIHdoZW4gY2FsbGVkLCB3aWxsIHVucmVnaXN0ZXIgdGhlIGNhbGxiYWNrIGZyb20gdGhlIGV2ZW50LlxuICovXG5leHBvcnQgZnVuY3Rpb24gT248RSBleHRlbmRzIFdhaWxzRXZlbnROYW1lID0gV2FpbHNFdmVudE5hbWU+KGV2ZW50TmFtZTogRSwgY2FsbGJhY2s6IFdhaWxzRXZlbnRDYWxsYmFjazxFPik6ICgpID0+IHZvaWQge1xuICAgIHJldHVybiBPbk11bHRpcGxlKGV2ZW50TmFtZSwgY2FsbGJhY2ssIC0xKTtcbn1cblxuLyoqXG4gKiBSZWdpc3RlcnMgYSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCBvbmx5IG9uY2UgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gKlxuICogQHBhcmFtIGV2ZW50TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byByZWdpc3RlciB0aGUgY2FsbGJhY2sgZm9yLlxuICogQHBhcmFtIGNhbGxiYWNrIC0gVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudCBpcyB0cmlnZ2VyZWQuXG4gKiBAcmV0dXJucyBBIGZ1bmN0aW9uIHRoYXQsIHdoZW4gY2FsbGVkLCB3aWxsIHVucmVnaXN0ZXIgdGhlIGNhbGxiYWNrIGZyb20gdGhlIGV2ZW50LlxuICovXG5leHBvcnQgZnVuY3Rpb24gT25jZTxFIGV4dGVuZHMgV2FpbHNFdmVudE5hbWUgPSBXYWlsc0V2ZW50TmFtZT4oZXZlbnROYW1lOiBFLCBjYWxsYmFjazogV2FpbHNFdmVudENhbGxiYWNrPEU+KTogKCkgPT4gdm9pZCB7XG4gICAgcmV0dXJuIE9uTXVsdGlwbGUoZXZlbnROYW1lLCBjYWxsYmFjaywgMSk7XG59XG5cbi8qKlxuICogUmVtb3ZlcyBldmVudCBsaXN0ZW5lcnMgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnQgbmFtZXMuXG4gKlxuICogQHBhcmFtIGV2ZW50TmFtZXMgLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnRzIHRvIHJlbW92ZSBsaXN0ZW5lcnMgZm9yLlxuICovXG5leHBvcnQgZnVuY3Rpb24gT2ZmKC4uLmV2ZW50TmFtZXM6IFtXYWlsc0V2ZW50TmFtZSwgLi4uV2FpbHNFdmVudE5hbWVbXV0pOiB2b2lkIHtcbiAgICBldmVudE5hbWVzLmZvckVhY2goZXZlbnROYW1lID0+IGV2ZW50TGlzdGVuZXJzLmRlbGV0ZShldmVudE5hbWUpKTtcbn1cblxuLyoqXG4gKiBSZW1vdmVzIGFsbCBldmVudCBsaXN0ZW5lcnMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBPZmZBbGwoKTogdm9pZCB7XG4gICAgZXZlbnRMaXN0ZW5lcnMuY2xlYXIoKTtcbn1cblxuLyoqXG4gKiBFbWl0cyBhbiBldmVudC5cbiAqXG4gKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCB3aWxsIGJlIGZ1bGZpbGxlZCBvbmNlIHRoZSBldmVudCBoYXMgYmVlbiBlbWl0dGVkLiAgUmVzb2x2ZXMgdG8gdHJ1ZSBpZiB0aGUgZXZlbnQgd2FzIGNhbmNlbGxlZC5cbiAqIEBwYXJhbSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIGVtaXRcbiAqIEBwYXJhbSBkYXRhIC0gVGhlIGRhdGEgdGhhdCB3aWxsIGJlIHNlbnQgd2l0aCB0aGUgZXZlbnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEVtaXQ8RSBleHRlbmRzIFdhaWxzRXZlbnROYW1lID0gV2FpbHNFdmVudE5hbWU+KG5hbWU6IEUsIGRhdGE6IFdhaWxzRXZlbnREYXRhPEU+KTogUHJvbWlzZTxib29sZWFuPlxuZXhwb3J0IGZ1bmN0aW9uIEVtaXQ8RSBleHRlbmRzIFdhaWxzRXZlbnROYW1lID0gV2FpbHNFdmVudE5hbWU+KG5hbWU6IFdhaWxzRXZlbnREYXRhPEU+IGV4dGVuZHMgbnVsbCB8IHZvaWQgPyBFIDogbmV2ZXIpOiBQcm9taXNlPGJvb2xlYW4+XG5leHBvcnQgZnVuY3Rpb24gRW1pdDxFIGV4dGVuZHMgV2FpbHNFdmVudE5hbWUgPSBXYWlsc0V2ZW50TmFtZT4obmFtZTogV2FpbHNFdmVudERhdGE8RT4sIGRhdGE/OiBhbnkpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICByZXR1cm4gY2FsbChFbWl0TWV0aG9kLCAgbmV3IFdhaWxzRXZlbnQobmFtZSwgZGF0YSkpXG59XG5cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLy8gVGhlIGZvbGxvd2luZyB1dGlsaXRpZXMgaGF2ZSBiZWVuIGZhY3RvcmVkIG91dCBvZiAuL2V2ZW50cy50c1xuLy8gZm9yIHRlc3RpbmcgcHVycG9zZXMuXG5cbmV4cG9ydCBjb25zdCBldmVudExpc3RlbmVycyA9IG5ldyBNYXA8c3RyaW5nLCBMaXN0ZW5lcltdPigpO1xuXG5leHBvcnQgY2xhc3MgTGlzdGVuZXIge1xuICAgIGV2ZW50TmFtZTogc3RyaW5nO1xuICAgIGNhbGxiYWNrOiAoZGF0YTogYW55KSA9PiB2b2lkO1xuICAgIG1heENhbGxiYWNrczogbnVtYmVyO1xuXG4gICAgY29uc3RydWN0b3IoZXZlbnROYW1lOiBzdHJpbmcsIGNhbGxiYWNrOiAoZGF0YTogYW55KSA9PiB2b2lkLCBtYXhDYWxsYmFja3M6IG51bWJlcikge1xuICAgICAgICB0aGlzLmV2ZW50TmFtZSA9IGV2ZW50TmFtZTtcbiAgICAgICAgdGhpcy5jYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgICAgICB0aGlzLm1heENhbGxiYWNrcyA9IG1heENhbGxiYWNrcyB8fCAtMTtcbiAgICB9XG5cbiAgICBkaXNwYXRjaChkYXRhOiBhbnkpOiBib29sZWFuIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHRoaXMuY2FsbGJhY2soZGF0YSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMubWF4Q2FsbGJhY2tzID09PSAtMSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICB0aGlzLm1heENhbGxiYWNrcyAtPSAxO1xuICAgICAgICByZXR1cm4gdGhpcy5tYXhDYWxsYmFja3MgPT09IDA7XG4gICAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gbGlzdGVuZXJPZmYobGlzdGVuZXI6IExpc3RlbmVyKTogdm9pZCB7XG4gICAgbGV0IGxpc3RlbmVycyA9IGV2ZW50TGlzdGVuZXJzLmdldChsaXN0ZW5lci5ldmVudE5hbWUpO1xuICAgIGlmICghbGlzdGVuZXJzKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsaXN0ZW5lcnMgPSBsaXN0ZW5lcnMuZmlsdGVyKGwgPT4gbCAhPT0gbGlzdGVuZXIpO1xuICAgIGlmIChsaXN0ZW5lcnMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGV2ZW50TGlzdGVuZXJzLmRlbGV0ZShsaXN0ZW5lci5ldmVudE5hbWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGV2ZW50TGlzdGVuZXJzLnNldChsaXN0ZW5lci5ldmVudE5hbWUsIGxpc3RlbmVycyk7XG4gICAgfVxufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKipcbiAqIEFueSBpcyBhIGR1bW15IGNyZWF0aW9uIGZ1bmN0aW9uIGZvciBzaW1wbGUgb3IgdW5rbm93biB0eXBlcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEFueTxUID0gYW55Pihzb3VyY2U6IGFueSk6IFQge1xuICAgIHJldHVybiBzb3VyY2U7XG59XG5cbi8qKlxuICogQnl0ZVNsaWNlIGlzIGEgY3JlYXRpb24gZnVuY3Rpb24gdGhhdCByZXBsYWNlc1xuICogbnVsbCBzdHJpbmdzIHdpdGggZW1wdHkgc3RyaW5ncy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEJ5dGVTbGljZShzb3VyY2U6IGFueSk6IHN0cmluZyB7XG4gICAgcmV0dXJuICgoc291cmNlID09IG51bGwpID8gXCJcIiA6IHNvdXJjZSk7XG59XG5cbi8qKlxuICogQXJyYXkgdGFrZXMgYSBjcmVhdGlvbiBmdW5jdGlvbiBmb3IgYW4gYXJiaXRyYXJ5IHR5cGVcbiAqIGFuZCByZXR1cm5zIGFuIGluLXBsYWNlIGNyZWF0aW9uIGZ1bmN0aW9uIGZvciBhbiBhcnJheVxuICogd2hvc2UgZWxlbWVudHMgYXJlIG9mIHRoYXQgdHlwZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEFycmF5PFQgPSBhbnk+KGVsZW1lbnQ6IChzb3VyY2U6IGFueSkgPT4gVCk6IChzb3VyY2U6IGFueSkgPT4gVFtdIHtcbiAgICBpZiAoZWxlbWVudCA9PT0gQW55KSB7XG4gICAgICAgIHJldHVybiAoc291cmNlKSA9PiAoc291cmNlID09PSBudWxsID8gW10gOiBzb3VyY2UpO1xuICAgIH1cblxuICAgIHJldHVybiAoc291cmNlKSA9PiB7XG4gICAgICAgIGlmIChzb3VyY2UgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNvdXJjZS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgc291cmNlW2ldID0gZWxlbWVudChzb3VyY2VbaV0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzb3VyY2U7XG4gICAgfTtcbn1cblxuLyoqXG4gKiBNYXAgdGFrZXMgY3JlYXRpb24gZnVuY3Rpb25zIGZvciB0d28gYXJiaXRyYXJ5IHR5cGVzXG4gKiBhbmQgcmV0dXJucyBhbiBpbi1wbGFjZSBjcmVhdGlvbiBmdW5jdGlvbiBmb3IgYW4gb2JqZWN0XG4gKiB3aG9zZSBrZXlzIGFuZCB2YWx1ZXMgYXJlIG9mIHRob3NlIHR5cGVzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gTWFwPEsgZXh0ZW5kcyBQcm9wZXJ0eUtleSA9IGFueSwgViA9IGFueT4oa2V5OiAoc291cmNlOiBhbnkpID0+IEssIHZhbHVlOiAoc291cmNlOiBhbnkpID0+IFYpOiAoc291cmNlOiBhbnkpID0+IFJlY29yZDxLLCBWPiB7XG4gICAgaWYgKHZhbHVlID09PSBBbnkpIHtcbiAgICAgICAgcmV0dXJuIChzb3VyY2UpID0+IChzb3VyY2UgPT09IG51bGwgPyB7fSA6IHNvdXJjZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIChzb3VyY2UpID0+IHtcbiAgICAgICAgaWYgKHNvdXJjZSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICB9XG4gICAgICAgIGZvciAoY29uc3Qga2V5IGluIHNvdXJjZSkge1xuICAgICAgICAgICAgc291cmNlW2tleV0gPSB2YWx1ZShzb3VyY2Vba2V5XSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNvdXJjZTtcbiAgICB9O1xufVxuXG4vKipcbiAqIE51bGxhYmxlIHRha2VzIGEgY3JlYXRpb24gZnVuY3Rpb24gZm9yIGFuIGFyYml0cmFyeSB0eXBlXG4gKiBhbmQgcmV0dXJucyBhIGNyZWF0aW9uIGZ1bmN0aW9uIGZvciBhIG51bGxhYmxlIHZhbHVlIG9mIHRoYXQgdHlwZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIE51bGxhYmxlPFQgPSBhbnk+KGVsZW1lbnQ6IChzb3VyY2U6IGFueSkgPT4gVCk6IChzb3VyY2U6IGFueSkgPT4gKFQgfCBudWxsKSB7XG4gICAgaWYgKGVsZW1lbnQgPT09IEFueSkge1xuICAgICAgICByZXR1cm4gQW55O1xuICAgIH1cblxuICAgIHJldHVybiAoc291cmNlKSA9PiAoc291cmNlID09PSBudWxsID8gbnVsbCA6IGVsZW1lbnQoc291cmNlKSk7XG59XG5cbi8qKlxuICogU3RydWN0IHRha2VzIGFuIG9iamVjdCBtYXBwaW5nIGZpZWxkIG5hbWVzIHRvIGNyZWF0aW9uIGZ1bmN0aW9uc1xuICogYW5kIHJldHVybnMgYW4gaW4tcGxhY2UgY3JlYXRpb24gZnVuY3Rpb24gZm9yIGEgc3RydWN0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gU3RydWN0KGNyZWF0ZUZpZWxkOiBSZWNvcmQ8c3RyaW5nLCAoc291cmNlOiBhbnkpID0+IGFueT4pOlxuICAgIDxVIGV4dGVuZHMgUmVjb3JkPHN0cmluZywgYW55PiA9IGFueT4oc291cmNlOiBhbnkpID0+IFVcbntcbiAgICBsZXQgYWxsQW55ID0gdHJ1ZTtcbiAgICBmb3IgKGNvbnN0IG5hbWUgaW4gY3JlYXRlRmllbGQpIHtcbiAgICAgICAgaWYgKGNyZWF0ZUZpZWxkW25hbWVdICE9PSBBbnkpIHtcbiAgICAgICAgICAgIGFsbEFueSA9IGZhbHNlO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKGFsbEFueSkge1xuICAgICAgICByZXR1cm4gQW55O1xuICAgIH1cblxuICAgIHJldHVybiAoc291cmNlKSA9PiB7XG4gICAgICAgIGZvciAoY29uc3QgbmFtZSBpbiBjcmVhdGVGaWVsZCkge1xuICAgICAgICAgICAgaWYgKG5hbWUgaW4gc291cmNlKSB7XG4gICAgICAgICAgICAgICAgc291cmNlW25hbWVdID0gY3JlYXRlRmllbGRbbmFtZV0oc291cmNlW25hbWVdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc291cmNlO1xuICAgIH07XG59XG5cbi8qKlxuICogTWFwcyBrbm93biBldmVudCBuYW1lcyB0byBjcmVhdGlvbiBmdW5jdGlvbnMgZm9yIHRoZWlyIGRhdGEgdHlwZXMuXG4gKiBXaWxsIGJlIG1vbmtleS1wYXRjaGVkIGJ5IHRoZSBiaW5kaW5nIGdlbmVyYXRvci5cbiAqL1xuZXhwb3J0IGNvbnN0IEV2ZW50czogUmVjb3JkPHN0cmluZywgKHNvdXJjZTogYW55KSA9PiBhbnk+ID0ge307XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbi8vIEN5bmh5cmNod3lkIHkgZmZlaWwgaG9uIHluIGF3dG9tYXRpZy4gUEVJRElXQ0ggXHUwMEMyIE1PRElXTFxuLy8gVGhpcyBmaWxlIGlzIGF1dG9tYXRpY2FsbHkgZ2VuZXJhdGVkLiBETyBOT1QgRURJVFxuXG5leHBvcnQgY29uc3QgVHlwZXMgPSBPYmplY3QuZnJlZXplKHtcblx0V2luZG93czogT2JqZWN0LmZyZWV6ZSh7XG5cdFx0QVBNUG93ZXJTZXR0aW5nQ2hhbmdlOiBcIndpbmRvd3M6QVBNUG93ZXJTZXR0aW5nQ2hhbmdlXCIsXG5cdFx0QVBNUG93ZXJTdGF0dXNDaGFuZ2U6IFwid2luZG93czpBUE1Qb3dlclN0YXR1c0NoYW5nZVwiLFxuXHRcdEFQTVJlc3VtZUF1dG9tYXRpYzogXCJ3aW5kb3dzOkFQTVJlc3VtZUF1dG9tYXRpY1wiLFxuXHRcdEFQTVJlc3VtZVN1c3BlbmQ6IFwid2luZG93czpBUE1SZXN1bWVTdXNwZW5kXCIsXG5cdFx0QVBNU3VzcGVuZDogXCJ3aW5kb3dzOkFQTVN1c3BlbmRcIixcblx0XHRBcHBsaWNhdGlvblN0YXJ0ZWQ6IFwid2luZG93czpBcHBsaWNhdGlvblN0YXJ0ZWRcIixcblx0XHRTeXN0ZW1UaGVtZUNoYW5nZWQ6IFwid2luZG93czpTeXN0ZW1UaGVtZUNoYW5nZWRcIixcblx0XHRXZWJWaWV3TmF2aWdhdGlvbkNvbXBsZXRlZDogXCJ3aW5kb3dzOldlYlZpZXdOYXZpZ2F0aW9uQ29tcGxldGVkXCIsXG5cdFx0V2luZG93QWN0aXZlOiBcIndpbmRvd3M6V2luZG93QWN0aXZlXCIsXG5cdFx0V2luZG93QmFja2dyb3VuZEVyYXNlOiBcIndpbmRvd3M6V2luZG93QmFja2dyb3VuZEVyYXNlXCIsXG5cdFx0V2luZG93Q2xpY2tBY3RpdmU6IFwid2luZG93czpXaW5kb3dDbGlja0FjdGl2ZVwiLFxuXHRcdFdpbmRvd0Nsb3Npbmc6IFwid2luZG93czpXaW5kb3dDbG9zaW5nXCIsXG5cdFx0V2luZG93RGlkTW92ZTogXCJ3aW5kb3dzOldpbmRvd0RpZE1vdmVcIixcblx0XHRXaW5kb3dEaWRSZXNpemU6IFwid2luZG93czpXaW5kb3dEaWRSZXNpemVcIixcblx0XHRXaW5kb3dEUElDaGFuZ2VkOiBcIndpbmRvd3M6V2luZG93RFBJQ2hhbmdlZFwiLFxuXHRcdFdpbmRvd0RyYWdEcm9wOiBcIndpbmRvd3M6V2luZG93RHJhZ0Ryb3BcIixcblx0XHRXaW5kb3dEcmFnRW50ZXI6IFwid2luZG93czpXaW5kb3dEcmFnRW50ZXJcIixcblx0XHRXaW5kb3dEcmFnTGVhdmU6IFwid2luZG93czpXaW5kb3dEcmFnTGVhdmVcIixcblx0XHRXaW5kb3dEcmFnT3ZlcjogXCJ3aW5kb3dzOldpbmRvd0RyYWdPdmVyXCIsXG5cdFx0V2luZG93RW5kTW92ZTogXCJ3aW5kb3dzOldpbmRvd0VuZE1vdmVcIixcblx0XHRXaW5kb3dFbmRSZXNpemU6IFwid2luZG93czpXaW5kb3dFbmRSZXNpemVcIixcblx0XHRXaW5kb3dGdWxsc2NyZWVuOiBcIndpbmRvd3M6V2luZG93RnVsbHNjcmVlblwiLFxuXHRcdFdpbmRvd0hpZGU6IFwid2luZG93czpXaW5kb3dIaWRlXCIsXG5cdFx0V2luZG93SW5hY3RpdmU6IFwid2luZG93czpXaW5kb3dJbmFjdGl2ZVwiLFxuXHRcdFdpbmRvd0tleURvd246IFwid2luZG93czpXaW5kb3dLZXlEb3duXCIsXG5cdFx0V2luZG93S2V5VXA6IFwid2luZG93czpXaW5kb3dLZXlVcFwiLFxuXHRcdFdpbmRvd0tpbGxGb2N1czogXCJ3aW5kb3dzOldpbmRvd0tpbGxGb2N1c1wiLFxuXHRcdFdpbmRvd05vbkNsaWVudEhpdDogXCJ3aW5kb3dzOldpbmRvd05vbkNsaWVudEhpdFwiLFxuXHRcdFdpbmRvd05vbkNsaWVudE1vdXNlRG93bjogXCJ3aW5kb3dzOldpbmRvd05vbkNsaWVudE1vdXNlRG93blwiLFxuXHRcdFdpbmRvd05vbkNsaWVudE1vdXNlTGVhdmU6IFwid2luZG93czpXaW5kb3dOb25DbGllbnRNb3VzZUxlYXZlXCIsXG5cdFx0V2luZG93Tm9uQ2xpZW50TW91c2VNb3ZlOiBcIndpbmRvd3M6V2luZG93Tm9uQ2xpZW50TW91c2VNb3ZlXCIsXG5cdFx0V2luZG93Tm9uQ2xpZW50TW91c2VVcDogXCJ3aW5kb3dzOldpbmRvd05vbkNsaWVudE1vdXNlVXBcIixcblx0XHRXaW5kb3dQYWludDogXCJ3aW5kb3dzOldpbmRvd1BhaW50XCIsXG5cdFx0V2luZG93UmVzdG9yZTogXCJ3aW5kb3dzOldpbmRvd1Jlc3RvcmVcIixcblx0XHRXaW5kb3dTZXRGb2N1czogXCJ3aW5kb3dzOldpbmRvd1NldEZvY3VzXCIsXG5cdFx0V2luZG93U2hvdzogXCJ3aW5kb3dzOldpbmRvd1Nob3dcIixcblx0XHRXaW5kb3dTdGFydE1vdmU6IFwid2luZG93czpXaW5kb3dTdGFydE1vdmVcIixcblx0XHRXaW5kb3dTdGFydFJlc2l6ZTogXCJ3aW5kb3dzOldpbmRvd1N0YXJ0UmVzaXplXCIsXG5cdFx0V2luZG93VW5GdWxsc2NyZWVuOiBcIndpbmRvd3M6V2luZG93VW5GdWxsc2NyZWVuXCIsXG5cdFx0V2luZG93Wk9yZGVyQ2hhbmdlZDogXCJ3aW5kb3dzOldpbmRvd1pPcmRlckNoYW5nZWRcIixcblx0XHRXaW5kb3dNaW5pbWlzZTogXCJ3aW5kb3dzOldpbmRvd01pbmltaXNlXCIsXG5cdFx0V2luZG93VW5NaW5pbWlzZTogXCJ3aW5kb3dzOldpbmRvd1VuTWluaW1pc2VcIixcblx0XHRXaW5kb3dNYXhpbWlzZTogXCJ3aW5kb3dzOldpbmRvd01heGltaXNlXCIsXG5cdFx0V2luZG93VW5NYXhpbWlzZTogXCJ3aW5kb3dzOldpbmRvd1VuTWF4aW1pc2VcIixcblx0fSksXG5cdE1hYzogT2JqZWN0LmZyZWV6ZSh7XG5cdFx0QXBwbGljYXRpb25EaWRCZWNvbWVBY3RpdmU6IFwibWFjOkFwcGxpY2F0aW9uRGlkQmVjb21lQWN0aXZlXCIsXG5cdFx0QXBwbGljYXRpb25EaWRDaGFuZ2VCYWNraW5nUHJvcGVydGllczogXCJtYWM6QXBwbGljYXRpb25EaWRDaGFuZ2VCYWNraW5nUHJvcGVydGllc1wiLFxuXHRcdEFwcGxpY2F0aW9uRGlkQ2hhbmdlRWZmZWN0aXZlQXBwZWFyYW5jZTogXCJtYWM6QXBwbGljYXRpb25EaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlXCIsXG5cdFx0QXBwbGljYXRpb25EaWRDaGFuZ2VJY29uOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZUljb25cIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZU9jY2x1c2lvblN0YXRlOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZU9jY2x1c2lvblN0YXRlXCIsXG5cdFx0QXBwbGljYXRpb25EaWRDaGFuZ2VTY3JlZW5QYXJhbWV0ZXJzOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZVNjcmVlblBhcmFtZXRlcnNcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZVN0YXR1c0JhckZyYW1lOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZVN0YXR1c0JhckZyYW1lXCIsXG5cdFx0QXBwbGljYXRpb25EaWRDaGFuZ2VTdGF0dXNCYXJPcmllbnRhdGlvbjogXCJtYWM6QXBwbGljYXRpb25EaWRDaGFuZ2VTdGF0dXNCYXJPcmllbnRhdGlvblwiLFxuXHRcdEFwcGxpY2F0aW9uRGlkQ2hhbmdlVGhlbWU6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlVGhlbWVcIixcblx0XHRBcHBsaWNhdGlvbkRpZEZpbmlzaExhdW5jaGluZzogXCJtYWM6QXBwbGljYXRpb25EaWRGaW5pc2hMYXVuY2hpbmdcIixcblx0XHRBcHBsaWNhdGlvbkRpZEhpZGU6IFwibWFjOkFwcGxpY2F0aW9uRGlkSGlkZVwiLFxuXHRcdEFwcGxpY2F0aW9uRGlkUmVzaWduQWN0aXZlOiBcIm1hYzpBcHBsaWNhdGlvbkRpZFJlc2lnbkFjdGl2ZVwiLFxuXHRcdEFwcGxpY2F0aW9uRGlkVW5oaWRlOiBcIm1hYzpBcHBsaWNhdGlvbkRpZFVuaGlkZVwiLFxuXHRcdEFwcGxpY2F0aW9uRGlkVXBkYXRlOiBcIm1hYzpBcHBsaWNhdGlvbkRpZFVwZGF0ZVwiLFxuXHRcdEFwcGxpY2F0aW9uRGlkV2FrZTogXCJtYWM6QXBwbGljYXRpb25EaWRXYWtlXCIsXG5cdFx0QXBwbGljYXRpb25TY3JlZW5zRGlkU2xlZXA6IFwibWFjOkFwcGxpY2F0aW9uU2NyZWVuc0RpZFNsZWVwXCIsXG5cdFx0QXBwbGljYXRpb25TY3JlZW5zRGlkV2FrZTogXCJtYWM6QXBwbGljYXRpb25TY3JlZW5zRGlkV2FrZVwiLFxuXHRcdEFwcGxpY2F0aW9uU2hvdWxkSGFuZGxlUmVvcGVuOiBcIm1hYzpBcHBsaWNhdGlvblNob3VsZEhhbmRsZVJlb3BlblwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbEJlY29tZUFjdGl2ZTogXCJtYWM6QXBwbGljYXRpb25XaWxsQmVjb21lQWN0aXZlXCIsXG5cdFx0QXBwbGljYXRpb25XaWxsRmluaXNoTGF1bmNoaW5nOiBcIm1hYzpBcHBsaWNhdGlvbldpbGxGaW5pc2hMYXVuY2hpbmdcIixcblx0XHRBcHBsaWNhdGlvbldpbGxIaWRlOiBcIm1hYzpBcHBsaWNhdGlvbldpbGxIaWRlXCIsXG5cdFx0QXBwbGljYXRpb25XaWxsUmVzaWduQWN0aXZlOiBcIm1hYzpBcHBsaWNhdGlvbldpbGxSZXNpZ25BY3RpdmVcIixcblx0XHRBcHBsaWNhdGlvbldpbGxTbGVlcDogXCJtYWM6QXBwbGljYXRpb25XaWxsU2xlZXBcIixcblx0XHRBcHBsaWNhdGlvbldpbGxUZXJtaW5hdGU6IFwibWFjOkFwcGxpY2F0aW9uV2lsbFRlcm1pbmF0ZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbFVuaGlkZTogXCJtYWM6QXBwbGljYXRpb25XaWxsVW5oaWRlXCIsXG5cdFx0QXBwbGljYXRpb25XaWxsVXBkYXRlOiBcIm1hYzpBcHBsaWNhdGlvbldpbGxVcGRhdGVcIixcblx0XHRNZW51RGlkQWRkSXRlbTogXCJtYWM6TWVudURpZEFkZEl0ZW1cIixcblx0XHRNZW51RGlkQmVnaW5UcmFja2luZzogXCJtYWM6TWVudURpZEJlZ2luVHJhY2tpbmdcIixcblx0XHRNZW51RGlkQ2xvc2U6IFwibWFjOk1lbnVEaWRDbG9zZVwiLFxuXHRcdE1lbnVEaWREaXNwbGF5SXRlbTogXCJtYWM6TWVudURpZERpc3BsYXlJdGVtXCIsXG5cdFx0TWVudURpZEVuZFRyYWNraW5nOiBcIm1hYzpNZW51RGlkRW5kVHJhY2tpbmdcIixcblx0XHRNZW51RGlkSGlnaGxpZ2h0SXRlbTogXCJtYWM6TWVudURpZEhpZ2hsaWdodEl0ZW1cIixcblx0XHRNZW51RGlkT3BlbjogXCJtYWM6TWVudURpZE9wZW5cIixcblx0XHRNZW51RGlkUG9wVXA6IFwibWFjOk1lbnVEaWRQb3BVcFwiLFxuXHRcdE1lbnVEaWRSZW1vdmVJdGVtOiBcIm1hYzpNZW51RGlkUmVtb3ZlSXRlbVwiLFxuXHRcdE1lbnVEaWRTZW5kQWN0aW9uOiBcIm1hYzpNZW51RGlkU2VuZEFjdGlvblwiLFxuXHRcdE1lbnVEaWRTZW5kQWN0aW9uVG9JdGVtOiBcIm1hYzpNZW51RGlkU2VuZEFjdGlvblRvSXRlbVwiLFxuXHRcdE1lbnVEaWRVcGRhdGU6IFwibWFjOk1lbnVEaWRVcGRhdGVcIixcblx0XHRNZW51V2lsbEFkZEl0ZW06IFwibWFjOk1lbnVXaWxsQWRkSXRlbVwiLFxuXHRcdE1lbnVXaWxsQmVnaW5UcmFja2luZzogXCJtYWM6TWVudVdpbGxCZWdpblRyYWNraW5nXCIsXG5cdFx0TWVudVdpbGxEaXNwbGF5SXRlbTogXCJtYWM6TWVudVdpbGxEaXNwbGF5SXRlbVwiLFxuXHRcdE1lbnVXaWxsRW5kVHJhY2tpbmc6IFwibWFjOk1lbnVXaWxsRW5kVHJhY2tpbmdcIixcblx0XHRNZW51V2lsbEhpZ2hsaWdodEl0ZW06IFwibWFjOk1lbnVXaWxsSGlnaGxpZ2h0SXRlbVwiLFxuXHRcdE1lbnVXaWxsT3BlbjogXCJtYWM6TWVudVdpbGxPcGVuXCIsXG5cdFx0TWVudVdpbGxQb3BVcDogXCJtYWM6TWVudVdpbGxQb3BVcFwiLFxuXHRcdE1lbnVXaWxsUmVtb3ZlSXRlbTogXCJtYWM6TWVudVdpbGxSZW1vdmVJdGVtXCIsXG5cdFx0TWVudVdpbGxTZW5kQWN0aW9uOiBcIm1hYzpNZW51V2lsbFNlbmRBY3Rpb25cIixcblx0XHRNZW51V2lsbFNlbmRBY3Rpb25Ub0l0ZW06IFwibWFjOk1lbnVXaWxsU2VuZEFjdGlvblRvSXRlbVwiLFxuXHRcdE1lbnVXaWxsVXBkYXRlOiBcIm1hYzpNZW51V2lsbFVwZGF0ZVwiLFxuXHRcdFdlYlZpZXdEaWRDb21taXROYXZpZ2F0aW9uOiBcIm1hYzpXZWJWaWV3RGlkQ29tbWl0TmF2aWdhdGlvblwiLFxuXHRcdFdlYlZpZXdEaWRGaW5pc2hOYXZpZ2F0aW9uOiBcIm1hYzpXZWJWaWV3RGlkRmluaXNoTmF2aWdhdGlvblwiLFxuXHRcdFdlYlZpZXdEaWRSZWNlaXZlU2VydmVyUmVkaXJlY3RGb3JQcm92aXNpb25hbE5hdmlnYXRpb246IFwibWFjOldlYlZpZXdEaWRSZWNlaXZlU2VydmVyUmVkaXJlY3RGb3JQcm92aXNpb25hbE5hdmlnYXRpb25cIixcblx0XHRXZWJWaWV3RGlkU3RhcnRQcm92aXNpb25hbE5hdmlnYXRpb246IFwibWFjOldlYlZpZXdEaWRTdGFydFByb3Zpc2lvbmFsTmF2aWdhdGlvblwiLFxuXHRcdFdpbmRvd0RpZEJlY29tZUtleTogXCJtYWM6V2luZG93RGlkQmVjb21lS2V5XCIsXG5cdFx0V2luZG93RGlkQmVjb21lTWFpbjogXCJtYWM6V2luZG93RGlkQmVjb21lTWFpblwiLFxuXHRcdFdpbmRvd0RpZEJlZ2luU2hlZXQ6IFwibWFjOldpbmRvd0RpZEJlZ2luU2hlZXRcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VBbHBoYTogXCJtYWM6V2luZG93RGlkQ2hhbmdlQWxwaGFcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VCYWNraW5nTG9jYXRpb246IFwibWFjOldpbmRvd0RpZENoYW5nZUJhY2tpbmdMb2NhdGlvblwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VCYWNraW5nUHJvcGVydGllc1wiLFxuXHRcdFdpbmRvd0RpZENoYW5nZUNvbGxlY3Rpb25CZWhhdmlvcjogXCJtYWM6V2luZG93RGlkQ2hhbmdlQ29sbGVjdGlvbkJlaGF2aW9yXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlRWZmZWN0aXZlQXBwZWFyYW5jZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlRWZmZWN0aXZlQXBwZWFyYW5jZVwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZU9jY2x1c2lvblN0YXRlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VPY2NsdXNpb25TdGF0ZVwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZU9yZGVyaW5nTW9kZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlT3JkZXJpbmdNb2RlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU2NyZWVuOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VTY3JlZW5cIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTY3JlZW5QYXJhbWV0ZXJzOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VTY3JlZW5QYXJhbWV0ZXJzXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU2NyZWVuUHJvZmlsZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU2NyZWVuUHJvZmlsZVwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZVNjcmVlblNwYWNlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VTY3JlZW5TcGFjZVwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZVNjcmVlblNwYWNlUHJvcGVydGllczogXCJtYWM6V2luZG93RGlkQ2hhbmdlU2NyZWVuU3BhY2VQcm9wZXJ0aWVzXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU2hhcmluZ1R5cGU6IFwibWFjOldpbmRvd0RpZENoYW5nZVNoYXJpbmdUeXBlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU3BhY2U6IFwibWFjOldpbmRvd0RpZENoYW5nZVNwYWNlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU3BhY2VPcmRlcmluZ01vZGU6IFwibWFjOldpbmRvd0RpZENoYW5nZVNwYWNlT3JkZXJpbmdNb2RlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlVGl0bGU6IFwibWFjOldpbmRvd0RpZENoYW5nZVRpdGxlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlVG9vbGJhcjogXCJtYWM6V2luZG93RGlkQ2hhbmdlVG9vbGJhclwiLFxuXHRcdFdpbmRvd0RpZERlbWluaWF0dXJpemU6IFwibWFjOldpbmRvd0RpZERlbWluaWF0dXJpemVcIixcblx0XHRXaW5kb3dEaWRFbmRTaGVldDogXCJtYWM6V2luZG93RGlkRW5kU2hlZXRcIixcblx0XHRXaW5kb3dEaWRFbnRlckZ1bGxTY3JlZW46IFwibWFjOldpbmRvd0RpZEVudGVyRnVsbFNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZEVudGVyVmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd0RpZEVudGVyVmVyc2lvbkJyb3dzZXJcIixcblx0XHRXaW5kb3dEaWRFeGl0RnVsbFNjcmVlbjogXCJtYWM6V2luZG93RGlkRXhpdEZ1bGxTY3JlZW5cIixcblx0XHRXaW5kb3dEaWRFeGl0VmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd0RpZEV4aXRWZXJzaW9uQnJvd3NlclwiLFxuXHRcdFdpbmRvd0RpZEV4cG9zZTogXCJtYWM6V2luZG93RGlkRXhwb3NlXCIsXG5cdFx0V2luZG93RGlkRm9jdXM6IFwibWFjOldpbmRvd0RpZEZvY3VzXCIsXG5cdFx0V2luZG93RGlkTWluaWF0dXJpemU6IFwibWFjOldpbmRvd0RpZE1pbmlhdHVyaXplXCIsXG5cdFx0V2luZG93RGlkTW92ZTogXCJtYWM6V2luZG93RGlkTW92ZVwiLFxuXHRcdFdpbmRvd0RpZE9yZGVyT2ZmU2NyZWVuOiBcIm1hYzpXaW5kb3dEaWRPcmRlck9mZlNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZE9yZGVyT25TY3JlZW46IFwibWFjOldpbmRvd0RpZE9yZGVyT25TY3JlZW5cIixcblx0XHRXaW5kb3dEaWRSZXNpZ25LZXk6IFwibWFjOldpbmRvd0RpZFJlc2lnbktleVwiLFxuXHRcdFdpbmRvd0RpZFJlc2lnbk1haW46IFwibWFjOldpbmRvd0RpZFJlc2lnbk1haW5cIixcblx0XHRXaW5kb3dEaWRSZXNpemU6IFwibWFjOldpbmRvd0RpZFJlc2l6ZVwiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZTogXCJtYWM6V2luZG93RGlkVXBkYXRlXCIsXG5cdFx0V2luZG93RGlkVXBkYXRlQWxwaGE6IFwibWFjOldpbmRvd0RpZFVwZGF0ZUFscGhhXCIsXG5cdFx0V2luZG93RGlkVXBkYXRlQ29sbGVjdGlvbkJlaGF2aW9yOiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVDb2xsZWN0aW9uUHJvcGVydGllczogXCJtYWM6V2luZG93RGlkVXBkYXRlQ29sbGVjdGlvblByb3BlcnRpZXNcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVTaGFkb3c6IFwibWFjOldpbmRvd0RpZFVwZGF0ZVNoYWRvd1wiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZVRpdGxlOiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVUaXRsZVwiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZVRvb2xiYXI6IFwibWFjOldpbmRvd0RpZFVwZGF0ZVRvb2xiYXJcIixcblx0XHRXaW5kb3dEaWRab29tOiBcIm1hYzpXaW5kb3dEaWRab29tXCIsXG5cdFx0V2luZG93RmlsZURyYWdnaW5nRW50ZXJlZDogXCJtYWM6V2luZG93RmlsZURyYWdnaW5nRW50ZXJlZFwiLFxuXHRcdFdpbmRvd0ZpbGVEcmFnZ2luZ0V4aXRlZDogXCJtYWM6V2luZG93RmlsZURyYWdnaW5nRXhpdGVkXCIsXG5cdFx0V2luZG93RmlsZURyYWdnaW5nUGVyZm9ybWVkOiBcIm1hYzpXaW5kb3dGaWxlRHJhZ2dpbmdQZXJmb3JtZWRcIixcblx0XHRXaW5kb3dIaWRlOiBcIm1hYzpXaW5kb3dIaWRlXCIsXG5cdFx0V2luZG93TWF4aW1pc2U6IFwibWFjOldpbmRvd01heGltaXNlXCIsXG5cdFx0V2luZG93VW5NYXhpbWlzZTogXCJtYWM6V2luZG93VW5NYXhpbWlzZVwiLFxuXHRcdFdpbmRvd01pbmltaXNlOiBcIm1hYzpXaW5kb3dNaW5pbWlzZVwiLFxuXHRcdFdpbmRvd1VuTWluaW1pc2U6IFwibWFjOldpbmRvd1VuTWluaW1pc2VcIixcblx0XHRXaW5kb3dTaG91bGRDbG9zZTogXCJtYWM6V2luZG93U2hvdWxkQ2xvc2VcIixcblx0XHRXaW5kb3dTaG93OiBcIm1hYzpXaW5kb3dTaG93XCIsXG5cdFx0V2luZG93V2lsbEJlY29tZUtleTogXCJtYWM6V2luZG93V2lsbEJlY29tZUtleVwiLFxuXHRcdFdpbmRvd1dpbGxCZWNvbWVNYWluOiBcIm1hYzpXaW5kb3dXaWxsQmVjb21lTWFpblwiLFxuXHRcdFdpbmRvd1dpbGxCZWdpblNoZWV0OiBcIm1hYzpXaW5kb3dXaWxsQmVnaW5TaGVldFwiLFxuXHRcdFdpbmRvd1dpbGxDaGFuZ2VPcmRlcmluZ01vZGU6IFwibWFjOldpbmRvd1dpbGxDaGFuZ2VPcmRlcmluZ01vZGVcIixcblx0XHRXaW5kb3dXaWxsQ2xvc2U6IFwibWFjOldpbmRvd1dpbGxDbG9zZVwiLFxuXHRcdFdpbmRvd1dpbGxEZW1pbmlhdHVyaXplOiBcIm1hYzpXaW5kb3dXaWxsRGVtaW5pYXR1cml6ZVwiLFxuXHRcdFdpbmRvd1dpbGxFbnRlckZ1bGxTY3JlZW46IFwibWFjOldpbmRvd1dpbGxFbnRlckZ1bGxTY3JlZW5cIixcblx0XHRXaW5kb3dXaWxsRW50ZXJWZXJzaW9uQnJvd3NlcjogXCJtYWM6V2luZG93V2lsbEVudGVyVmVyc2lvbkJyb3dzZXJcIixcblx0XHRXaW5kb3dXaWxsRXhpdEZ1bGxTY3JlZW46IFwibWFjOldpbmRvd1dpbGxFeGl0RnVsbFNjcmVlblwiLFxuXHRcdFdpbmRvd1dpbGxFeGl0VmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd1dpbGxFeGl0VmVyc2lvbkJyb3dzZXJcIixcblx0XHRXaW5kb3dXaWxsRm9jdXM6IFwibWFjOldpbmRvd1dpbGxGb2N1c1wiLFxuXHRcdFdpbmRvd1dpbGxNaW5pYXR1cml6ZTogXCJtYWM6V2luZG93V2lsbE1pbmlhdHVyaXplXCIsXG5cdFx0V2luZG93V2lsbE1vdmU6IFwibWFjOldpbmRvd1dpbGxNb3ZlXCIsXG5cdFx0V2luZG93V2lsbE9yZGVyT2ZmU2NyZWVuOiBcIm1hYzpXaW5kb3dXaWxsT3JkZXJPZmZTY3JlZW5cIixcblx0XHRXaW5kb3dXaWxsT3JkZXJPblNjcmVlbjogXCJtYWM6V2luZG93V2lsbE9yZGVyT25TY3JlZW5cIixcblx0XHRXaW5kb3dXaWxsUmVzaWduTWFpbjogXCJtYWM6V2luZG93V2lsbFJlc2lnbk1haW5cIixcblx0XHRXaW5kb3dXaWxsUmVzaXplOiBcIm1hYzpXaW5kb3dXaWxsUmVzaXplXCIsXG5cdFx0V2luZG93V2lsbFVuZm9jdXM6IFwibWFjOldpbmRvd1dpbGxVbmZvY3VzXCIsXG5cdFx0V2luZG93V2lsbFVwZGF0ZTogXCJtYWM6V2luZG93V2lsbFVwZGF0ZVwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVBbHBoYTogXCJtYWM6V2luZG93V2lsbFVwZGF0ZUFscGhhXCIsXG5cdFx0V2luZG93V2lsbFVwZGF0ZUNvbGxlY3Rpb25CZWhhdmlvcjogXCJtYWM6V2luZG93V2lsbFVwZGF0ZUNvbGxlY3Rpb25CZWhhdmlvclwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVDb2xsZWN0aW9uUHJvcGVydGllczogXCJtYWM6V2luZG93V2lsbFVwZGF0ZUNvbGxlY3Rpb25Qcm9wZXJ0aWVzXCIsXG5cdFx0V2luZG93V2lsbFVwZGF0ZVNoYWRvdzogXCJtYWM6V2luZG93V2lsbFVwZGF0ZVNoYWRvd1wiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVUaXRsZTogXCJtYWM6V2luZG93V2lsbFVwZGF0ZVRpdGxlXCIsXG5cdFx0V2luZG93V2lsbFVwZGF0ZVRvb2xiYXI6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVUb29sYmFyXCIsXG5cdFx0V2luZG93V2lsbFVwZGF0ZVZpc2liaWxpdHk6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVWaXNpYmlsaXR5XCIsXG5cdFx0V2luZG93V2lsbFVzZVN0YW5kYXJkRnJhbWU6IFwibWFjOldpbmRvd1dpbGxVc2VTdGFuZGFyZEZyYW1lXCIsXG5cdFx0V2luZG93Wm9vbUluOiBcIm1hYzpXaW5kb3dab29tSW5cIixcblx0XHRXaW5kb3dab29tT3V0OiBcIm1hYzpXaW5kb3dab29tT3V0XCIsXG5cdFx0V2luZG93Wm9vbVJlc2V0OiBcIm1hYzpXaW5kb3dab29tUmVzZXRcIixcblx0fSksXG5cdExpbnV4OiBPYmplY3QuZnJlZXplKHtcblx0XHRBcHBsaWNhdGlvblN0YXJ0dXA6IFwibGludXg6QXBwbGljYXRpb25TdGFydHVwXCIsXG5cdFx0U3lzdGVtRGlkV2FrZTogXCJsaW51eDpTeXN0ZW1EaWRXYWtlXCIsXG5cdFx0U3lzdGVtVGhlbWVDaGFuZ2VkOiBcImxpbnV4OlN5c3RlbVRoZW1lQ2hhbmdlZFwiLFxuXHRcdFN5c3RlbVdpbGxTbGVlcDogXCJsaW51eDpTeXN0ZW1XaWxsU2xlZXBcIixcblx0XHRXaW5kb3dEZWxldGVFdmVudDogXCJsaW51eDpXaW5kb3dEZWxldGVFdmVudFwiLFxuXHRcdFdpbmRvd0RpZE1vdmU6IFwibGludXg6V2luZG93RGlkTW92ZVwiLFxuXHRcdFdpbmRvd0RpZFJlc2l6ZTogXCJsaW51eDpXaW5kb3dEaWRSZXNpemVcIixcblx0XHRXaW5kb3dGb2N1c0luOiBcImxpbnV4OldpbmRvd0ZvY3VzSW5cIixcblx0XHRXaW5kb3dGb2N1c091dDogXCJsaW51eDpXaW5kb3dGb2N1c091dFwiLFxuXHRcdFdpbmRvd0xvYWRTdGFydGVkOiBcImxpbnV4OldpbmRvd0xvYWRTdGFydGVkXCIsXG5cdFx0V2luZG93TG9hZFJlZGlyZWN0ZWQ6IFwibGludXg6V2luZG93TG9hZFJlZGlyZWN0ZWRcIixcblx0XHRXaW5kb3dMb2FkQ29tbWl0dGVkOiBcImxpbnV4OldpbmRvd0xvYWRDb21taXR0ZWRcIixcblx0XHRXaW5kb3dMb2FkRmluaXNoZWQ6IFwibGludXg6V2luZG93TG9hZEZpbmlzaGVkXCIsXG5cdH0pLFxuXHRpT1M6IE9iamVjdC5mcmVlemUoe1xuXHRcdEFwcGxpY2F0aW9uRGlkQmVjb21lQWN0aXZlOiBcImlvczpBcHBsaWNhdGlvbkRpZEJlY29tZUFjdGl2ZVwiLFxuXHRcdEFwcGxpY2F0aW9uRGlkRW50ZXJCYWNrZ3JvdW5kOiBcImlvczpBcHBsaWNhdGlvbkRpZEVudGVyQmFja2dyb3VuZFwiLFxuXHRcdEFwcGxpY2F0aW9uRGlkRmluaXNoTGF1bmNoaW5nOiBcImlvczpBcHBsaWNhdGlvbkRpZEZpbmlzaExhdW5jaGluZ1wiLFxuXHRcdEFwcGxpY2F0aW9uRGlkUmVjZWl2ZU1lbW9yeVdhcm5pbmc6IFwiaW9zOkFwcGxpY2F0aW9uRGlkUmVjZWl2ZU1lbW9yeVdhcm5pbmdcIixcblx0XHRBcHBsaWNhdGlvbldpbGxFbnRlckZvcmVncm91bmQ6IFwiaW9zOkFwcGxpY2F0aW9uV2lsbEVudGVyRm9yZWdyb3VuZFwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbFJlc2lnbkFjdGl2ZTogXCJpb3M6QXBwbGljYXRpb25XaWxsUmVzaWduQWN0aXZlXCIsXG5cdFx0QXBwbGljYXRpb25XaWxsVGVybWluYXRlOiBcImlvczpBcHBsaWNhdGlvbldpbGxUZXJtaW5hdGVcIixcblx0XHRXaW5kb3dEaWRMb2FkOiBcImlvczpXaW5kb3dEaWRMb2FkXCIsXG5cdFx0V2luZG93V2lsbEFwcGVhcjogXCJpb3M6V2luZG93V2lsbEFwcGVhclwiLFxuXHRcdFdpbmRvd0RpZEFwcGVhcjogXCJpb3M6V2luZG93RGlkQXBwZWFyXCIsXG5cdFx0V2luZG93V2lsbERpc2FwcGVhcjogXCJpb3M6V2luZG93V2lsbERpc2FwcGVhclwiLFxuXHRcdFdpbmRvd0RpZERpc2FwcGVhcjogXCJpb3M6V2luZG93RGlkRGlzYXBwZWFyXCIsXG5cdFx0V2luZG93U2FmZUFyZWFJbnNldHNDaGFuZ2VkOiBcImlvczpXaW5kb3dTYWZlQXJlYUluc2V0c0NoYW5nZWRcIixcblx0XHRXaW5kb3dPcmllbnRhdGlvbkNoYW5nZWQ6IFwiaW9zOldpbmRvd09yaWVudGF0aW9uQ2hhbmdlZFwiLFxuXHRcdFdpbmRvd1RvdWNoQmVnYW46IFwiaW9zOldpbmRvd1RvdWNoQmVnYW5cIixcblx0XHRXaW5kb3dUb3VjaE1vdmVkOiBcImlvczpXaW5kb3dUb3VjaE1vdmVkXCIsXG5cdFx0V2luZG93VG91Y2hFbmRlZDogXCJpb3M6V2luZG93VG91Y2hFbmRlZFwiLFxuXHRcdFdpbmRvd1RvdWNoQ2FuY2VsbGVkOiBcImlvczpXaW5kb3dUb3VjaENhbmNlbGxlZFwiLFxuXHRcdFdlYlZpZXdEaWRTdGFydE5hdmlnYXRpb246IFwiaW9zOldlYlZpZXdEaWRTdGFydE5hdmlnYXRpb25cIixcblx0XHRXZWJWaWV3RGlkRmluaXNoTmF2aWdhdGlvbjogXCJpb3M6V2ViVmlld0RpZEZpbmlzaE5hdmlnYXRpb25cIixcblx0XHRXZWJWaWV3RGlkRmFpbE5hdmlnYXRpb246IFwiaW9zOldlYlZpZXdEaWRGYWlsTmF2aWdhdGlvblwiLFxuXHRcdFdlYlZpZXdEZWNpZGVQb2xpY3lGb3JOYXZpZ2F0aW9uQWN0aW9uOiBcImlvczpXZWJWaWV3RGVjaWRlUG9saWN5Rm9yTmF2aWdhdGlvbkFjdGlvblwiLFxuXHRcdEJhdHRlcnlDaGFuZ2VkOiBcImlvczpCYXR0ZXJ5Q2hhbmdlZFwiLFxuXHRcdE5ldHdvcmtDaGFuZ2VkOiBcImlvczpOZXR3b3JrQ2hhbmdlZFwiLFxuXHRcdFRoZW1lQ2hhbmdlZDogXCJpb3M6VGhlbWVDaGFuZ2VkXCIsXG5cdFx0U2NyZWVuTG9ja2VkOiBcImlvczpTY3JlZW5Mb2NrZWRcIixcblx0XHRTY3JlZW5VbmxvY2tlZDogXCJpb3M6U2NyZWVuVW5sb2NrZWRcIixcblx0fSksXG5cdEFuZHJvaWQ6IE9iamVjdC5mcmVlemUoe1xuXHRcdEFjdGl2aXR5Q3JlYXRlZDogXCJhbmRyb2lkOkFjdGl2aXR5Q3JlYXRlZFwiLFxuXHRcdEFjdGl2aXR5U3RhcnRlZDogXCJhbmRyb2lkOkFjdGl2aXR5U3RhcnRlZFwiLFxuXHRcdEFjdGl2aXR5UmVzdW1lZDogXCJhbmRyb2lkOkFjdGl2aXR5UmVzdW1lZFwiLFxuXHRcdEFjdGl2aXR5UGF1c2VkOiBcImFuZHJvaWQ6QWN0aXZpdHlQYXVzZWRcIixcblx0XHRBY3Rpdml0eVN0b3BwZWQ6IFwiYW5kcm9pZDpBY3Rpdml0eVN0b3BwZWRcIixcblx0XHRBY3Rpdml0eURlc3Ryb3llZDogXCJhbmRyb2lkOkFjdGl2aXR5RGVzdHJveWVkXCIsXG5cdFx0QXBwbGljYXRpb25Mb3dNZW1vcnk6IFwiYW5kcm9pZDpBcHBsaWNhdGlvbkxvd01lbW9yeVwiLFxuXHRcdFdlYlZpZXdQYWdlU3RhcnRlZDogXCJhbmRyb2lkOldlYlZpZXdQYWdlU3RhcnRlZFwiLFxuXHRcdFdlYlZpZXdQYWdlRmluaXNoZWQ6IFwiYW5kcm9pZDpXZWJWaWV3UGFnZUZpbmlzaGVkXCIsXG5cdFx0QmF0dGVyeUNoYW5nZWQ6IFwiYW5kcm9pZDpCYXR0ZXJ5Q2hhbmdlZFwiLFxuXHRcdE5ldHdvcmtDaGFuZ2VkOiBcImFuZHJvaWQ6TmV0d29ya0NoYW5nZWRcIixcblx0XHRUaGVtZUNoYW5nZWQ6IFwiYW5kcm9pZDpUaGVtZUNoYW5nZWRcIixcblx0XHRTY3JlZW5Mb2NrZWQ6IFwiYW5kcm9pZDpTY3JlZW5Mb2NrZWRcIixcblx0XHRTY3JlZW5VbmxvY2tlZDogXCJhbmRyb2lkOlNjcmVlblVubG9ja2VkXCIsXG5cdH0pLFxuXHRDb21tb246IE9iamVjdC5mcmVlemUoe1xuXHRcdEFwcGxpY2F0aW9uT3BlbmVkV2l0aEZpbGU6IFwiY29tbW9uOkFwcGxpY2F0aW9uT3BlbmVkV2l0aEZpbGVcIixcblx0XHRBcHBsaWNhdGlvblN0YXJ0ZWQ6IFwiY29tbW9uOkFwcGxpY2F0aW9uU3RhcnRlZFwiLFxuXHRcdEFwcGxpY2F0aW9uTGF1bmNoZWRXaXRoVXJsOiBcImNvbW1vbjpBcHBsaWNhdGlvbkxhdW5jaGVkV2l0aFVybFwiLFxuXHRcdFRoZW1lQ2hhbmdlZDogXCJjb21tb246VGhlbWVDaGFuZ2VkXCIsXG5cdFx0U3lzdGVtRGlkV2FrZTogXCJjb21tb246U3lzdGVtRGlkV2FrZVwiLFxuXHRcdFN5c3RlbVdpbGxTbGVlcDogXCJjb21tb246U3lzdGVtV2lsbFNsZWVwXCIsXG5cdFx0V2luZG93Q2xvc2luZzogXCJjb21tb246V2luZG93Q2xvc2luZ1wiLFxuXHRcdFdpbmRvd0RpZE1vdmU6IFwiY29tbW9uOldpbmRvd0RpZE1vdmVcIixcblx0XHRXaW5kb3dEaWRSZXNpemU6IFwiY29tbW9uOldpbmRvd0RpZFJlc2l6ZVwiLFxuXHRcdFdpbmRvd0RQSUNoYW5nZWQ6IFwiY29tbW9uOldpbmRvd0RQSUNoYW5nZWRcIixcblx0XHRXaW5kb3dGaWxlc0Ryb3BwZWQ6IFwiY29tbW9uOldpbmRvd0ZpbGVzRHJvcHBlZFwiLFxuXHRcdFdpbmRvd0ZvY3VzOiBcImNvbW1vbjpXaW5kb3dGb2N1c1wiLFxuXHRcdFdpbmRvd0Z1bGxzY3JlZW46IFwiY29tbW9uOldpbmRvd0Z1bGxzY3JlZW5cIixcblx0XHRXaW5kb3dIaWRlOiBcImNvbW1vbjpXaW5kb3dIaWRlXCIsXG5cdFx0V2luZG93TG9zdEZvY3VzOiBcImNvbW1vbjpXaW5kb3dMb3N0Rm9jdXNcIixcblx0XHRXaW5kb3dNYXhpbWlzZTogXCJjb21tb246V2luZG93TWF4aW1pc2VcIixcblx0XHRXaW5kb3dNaW5pbWlzZTogXCJjb21tb246V2luZG93TWluaW1pc2VcIixcblx0XHRXaW5kb3dUb2dnbGVGcmFtZWxlc3M6IFwiY29tbW9uOldpbmRvd1RvZ2dsZUZyYW1lbGVzc1wiLFxuXHRcdFdpbmRvd1Jlc3RvcmU6IFwiY29tbW9uOldpbmRvd1Jlc3RvcmVcIixcblx0XHRXaW5kb3dSdW50aW1lUmVhZHk6IFwiY29tbW9uOldpbmRvd1J1bnRpbWVSZWFkeVwiLFxuXHRcdFdpbmRvd1Nob3c6IFwiY29tbW9uOldpbmRvd1Nob3dcIixcblx0XHRXaW5kb3dVbkZ1bGxzY3JlZW46IFwiY29tbW9uOldpbmRvd1VuRnVsbHNjcmVlblwiLFxuXHRcdFdpbmRvd1VuTWF4aW1pc2U6IFwiY29tbW9uOldpbmRvd1VuTWF4aW1pc2VcIixcblx0XHRXaW5kb3dVbk1pbmltaXNlOiBcImNvbW1vbjpXaW5kb3dVbk1pbmltaXNlXCIsXG5cdFx0V2luZG93Wm9vbTogXCJjb21tb246V2luZG93Wm9vbVwiLFxuXHRcdFdpbmRvd1pvb21JbjogXCJjb21tb246V2luZG93Wm9vbUluXCIsXG5cdFx0V2luZG93Wm9vbU91dDogXCJjb21tb246V2luZG93Wm9vbU91dFwiLFxuXHRcdFdpbmRvd1pvb21SZXNldDogXCJjb21tb246V2luZG93Wm9vbVJlc2V0XCIsXG5cdFx0QmF0dGVyeUNoYW5nZWQ6IFwiY29tbW9uOkJhdHRlcnlDaGFuZ2VkXCIsXG5cdFx0TmV0d29ya0NoYW5nZWQ6IFwiY29tbW9uOk5ldHdvcmtDaGFuZ2VkXCIsXG5cdFx0U2NyZWVuTG9ja2VkOiBcImNvbW1vbjpTY3JlZW5Mb2NrZWRcIixcblx0XHRTY3JlZW5VbmxvY2tlZDogXCJjb21tb246U2NyZWVuVW5sb2NrZWRcIixcblx0XHRMb3dNZW1vcnk6IFwiY29tbW9uOkxvd01lbW9yeVwiLFxuXHR9KSxcbn0pO1xuIiwgIi8qXG4gXyAgICAgX18gICAgIF8gX19cbnwgfCAgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKipcbiAqIExvZ3MgYSBtZXNzYWdlIHRvIHRoZSBjb25zb2xlIHdpdGggY3VzdG9tIGZvcm1hdHRpbmcuXG4gKlxuICogQHBhcmFtIG1lc3NhZ2UgLSBUaGUgbWVzc2FnZSB0byBiZSBsb2dnZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWJ1Z0xvZyhtZXNzYWdlOiBhbnkpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmVcbiAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgJyVjIHdhaWxzMyAlYyAnICsgbWVzc2FnZSArICcgJyxcbiAgICAgICAgJ2JhY2tncm91bmQ6ICNhYTAwMDA7IGNvbG9yOiAjZmZmOyBib3JkZXItcmFkaXVzOiAzcHggMHB4IDBweCAzcHg7IHBhZGRpbmc6IDFweDsgZm9udC1zaXplOiAwLjdyZW0nLFxuICAgICAgICAnYmFja2dyb3VuZDogIzAwOTkwMDsgY29sb3I6ICNmZmY7IGJvcmRlci1yYWRpdXM6IDBweCAzcHggM3B4IDBweDsgcGFkZGluZzogMXB4OyBmb250LXNpemU6IDAuN3JlbSdcbiAgICApO1xufVxuXG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIHRoZSB3ZWJ2aWV3IHN1cHBvcnRzIHRoZSB7QGxpbmsgTW91c2VFdmVudCNidXR0b25zfSBwcm9wZXJ0eS5cbiAqIExvb2tpbmcgYXQgeW91IG1hY09TIEhpZ2ggU2llcnJhIVxuICovXG5leHBvcnQgZnVuY3Rpb24gY2FuVHJhY2tCdXR0b25zKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAobmV3IE1vdXNlRXZlbnQoJ21vdXNlZG93bicpKS5idXR0b25zID09PSAwO1xufVxuXG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIHRoZSBicm93c2VyIHN1cHBvcnRzIHJlbW92aW5nIGxpc3RlbmVycyBieSB0cmlnZ2VyaW5nIGFuIEFib3J0U2lnbmFsXG4gKiAoc2VlIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9FdmVudFRhcmdldC9hZGRFdmVudExpc3RlbmVyI3NpZ25hbCkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjYW5BYm9ydExpc3RlbmVycygpIHtcbiAgICBpZiAoIUV2ZW50VGFyZ2V0IHx8ICFBYm9ydFNpZ25hbCB8fCAhQWJvcnRDb250cm9sbGVyKVxuICAgICAgICByZXR1cm4gZmFsc2U7XG5cbiAgICBsZXQgcmVzdWx0ID0gdHJ1ZTtcblxuICAgIGNvbnN0IHRhcmdldCA9IG5ldyBFdmVudFRhcmdldCgpO1xuICAgIGNvbnN0IGNvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG4gICAgdGFyZ2V0LmFkZEV2ZW50TGlzdGVuZXIoJ3Rlc3QnLCAoKSA9PiB7IHJlc3VsdCA9IGZhbHNlOyB9LCB7IHNpZ25hbDogY29udHJvbGxlci5zaWduYWwgfSk7XG4gICAgY29udHJvbGxlci5hYm9ydCgpO1xuICAgIHRhcmdldC5kaXNwYXRjaEV2ZW50KG5ldyBDdXN0b21FdmVudCgndGVzdCcpKTtcblxuICAgIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKlxuICogUmVzb2x2ZXMgdGhlIGNsb3Nlc3QgSFRNTEVsZW1lbnQgYW5jZXN0b3Igb2YgYW4gZXZlbnQncyB0YXJnZXQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBldmVudFRhcmdldChldmVudDogRXZlbnQpOiBIVE1MRWxlbWVudCB7XG4gICAgaWYgKGV2ZW50LnRhcmdldCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSB7XG4gICAgICAgIHJldHVybiBldmVudC50YXJnZXQ7XG4gICAgfSBlbHNlIGlmICghKGV2ZW50LnRhcmdldCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSAmJiBldmVudC50YXJnZXQgaW5zdGFuY2VvZiBOb2RlKSB7XG4gICAgICAgIHJldHVybiBldmVudC50YXJnZXQucGFyZW50RWxlbWVudCA/PyBkb2N1bWVudC5ib2R5O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBkb2N1bWVudC5ib2R5O1xuICAgIH1cbn1cblxuLyoqKlxuIFRoaXMgdGVjaG5pcXVlIGZvciBwcm9wZXIgbG9hZCBkZXRlY3Rpb24gaXMgdGFrZW4gZnJvbSBIVE1YOlxuXG4gQlNEIDItQ2xhdXNlIExpY2Vuc2VcblxuIENvcHlyaWdodCAoYykgMjAyMCwgQmlnIFNreSBTb2Z0d2FyZVxuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG5cbiBSZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXRcbiBtb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcblxuIDEuIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSwgdGhpc1xuIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxuXG4gMi4gUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLFxuIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlIGRvY3VtZW50YXRpb25cbiBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi5cblxuIFRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIENPUFlSSUdIVCBIT0xERVJTIEFORCBDT05UUklCVVRPUlMgXCJBUyBJU1wiXG4gQU5EIEFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRVxuIElNUExJRUQgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRVxuIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQgSE9MREVSIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEVcbiBGT1IgQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTFxuIERBTUFHRVMgKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SXG4gU0VSVklDRVM7IExPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVJcbiBDQVVTRUQgQU5EIE9OIEFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLFxuIE9SIFRPUlQgKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFXG4gT0YgVEhJUyBTT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS5cblxuICoqKi9cblxubGV0IGlzUmVhZHkgPSBmYWxzZTtcbmltcG9ydCB7IGhhc0RPTSB9IGZyb20gXCIuL2Vudmlyb25tZW50LmpzXCI7XG5cbmlmIChoYXNET00pIHtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJywgKCkgPT4geyBpc1JlYWR5ID0gdHJ1ZSB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHdoZW5SZWFkeShjYWxsYmFjazogKCkgPT4gdm9pZCkge1xuICAgIGlmIChpc1JlYWR5IHx8IGRvY3VtZW50LnJlYWR5U3RhdGUgPT09ICdjb21wbGV0ZScpIHtcbiAgICAgICAgY2FsbGJhY2soKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJywgY2FsbGJhY2spO1xuICAgIH1cbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuaW1wb3J0IHtuZXdSdW50aW1lQ2FsbGVyLCBvYmplY3ROYW1lc30gZnJvbSBcIi4vcnVudGltZS5qc1wiO1xuaW1wb3J0IHR5cGUgeyBTY3JlZW4gfSBmcm9tIFwiLi9zY3JlZW5zLmpzXCI7XG5cbi8vIERyb3AgdGFyZ2V0IGNvbnN0YW50c1xuY29uc3QgRFJPUF9UQVJHRVRfQVRUUklCVVRFID0gJ2RhdGEtZmlsZS1kcm9wLXRhcmdldCc7XG5jb25zdCBEUk9QX1RBUkdFVF9BQ1RJVkVfQ0xBU1MgPSAnZmlsZS1kcm9wLXRhcmdldC1hY3RpdmUnO1xubGV0IGN1cnJlbnREcm9wVGFyZ2V0OiBFbGVtZW50IHwgbnVsbCA9IG51bGw7XG5cbmNvbnN0IFBvc2l0aW9uTWV0aG9kICAgICAgICAgICAgICAgICAgICA9IDA7XG5jb25zdCBDZW50ZXJNZXRob2QgICAgICAgICAgICAgICAgICAgICAgPSAxO1xuY29uc3QgQ2xvc2VNZXRob2QgICAgICAgICAgICAgICAgICAgICAgID0gMjtcbmNvbnN0IERpc2FibGVTaXplQ29uc3RyYWludHNNZXRob2QgICAgICA9IDM7XG5jb25zdCBFbmFibGVTaXplQ29uc3RyYWludHNNZXRob2QgICAgICAgPSA0O1xuY29uc3QgRm9jdXNNZXRob2QgICAgICAgICAgICAgICAgICAgICAgID0gNTtcbmNvbnN0IEZvcmNlUmVsb2FkTWV0aG9kICAgICAgICAgICAgICAgICA9IDY7XG5jb25zdCBGdWxsc2NyZWVuTWV0aG9kICAgICAgICAgICAgICAgICAgPSA3O1xuY29uc3QgR2V0U2NyZWVuTWV0aG9kICAgICAgICAgICAgICAgICAgID0gODtcbmNvbnN0IEdldFpvb21NZXRob2QgICAgICAgICAgICAgICAgICAgICA9IDk7XG5jb25zdCBIZWlnaHRNZXRob2QgICAgICAgICAgICAgICAgICAgICAgPSAxMDtcbmNvbnN0IEhpZGVNZXRob2QgICAgICAgICAgICAgICAgICAgICAgICA9IDExO1xuY29uc3QgSXNGb2N1c2VkTWV0aG9kICAgICAgICAgICAgICAgICAgID0gMTI7XG5jb25zdCBJc0Z1bGxzY3JlZW5NZXRob2QgICAgICAgICAgICAgICAgPSAxMztcbmNvbnN0IElzTWF4aW1pc2VkTWV0aG9kICAgICAgICAgICAgICAgICA9IDE0O1xuY29uc3QgSXNNaW5pbWlzZWRNZXRob2QgICAgICAgICAgICAgICAgID0gMTU7XG5jb25zdCBNYXhpbWlzZU1ldGhvZCAgICAgICAgICAgICAgICAgICAgPSAxNjtcbmNvbnN0IE1pbmltaXNlTWV0aG9kICAgICAgICAgICAgICAgICAgICA9IDE3O1xuY29uc3QgTmFtZU1ldGhvZCAgICAgICAgICAgICAgICAgICAgICAgID0gMTg7XG5jb25zdCBPcGVuRGV2VG9vbHNNZXRob2QgICAgICAgICAgICAgICAgPSAxOTtcbmNvbnN0IFJlbGF0aXZlUG9zaXRpb25NZXRob2QgICAgICAgICAgICA9IDIwO1xuY29uc3QgUmVsb2FkTWV0aG9kICAgICAgICAgICAgICAgICAgICAgID0gMjE7XG5jb25zdCBSZXNpemFibGVNZXRob2QgICAgICAgICAgICAgICAgICAgPSAyMjtcbmNvbnN0IFJlc3RvcmVNZXRob2QgICAgICAgICAgICAgICAgICAgICA9IDIzO1xuY29uc3QgU2V0UG9zaXRpb25NZXRob2QgICAgICAgICAgICAgICAgID0gMjQ7XG5jb25zdCBTZXRBbHdheXNPblRvcE1ldGhvZCAgICAgICAgICAgICAgPSAyNTtcbmNvbnN0IFNldEJhY2tncm91bmRDb2xvdXJNZXRob2QgICAgICAgICA9IDI2O1xuY29uc3QgU2V0RnJhbWVsZXNzTWV0aG9kICAgICAgICAgICAgICAgID0gMjc7XG5jb25zdCBTZXRGdWxsc2NyZWVuQnV0dG9uRW5hYmxlZE1ldGhvZCAgPSAyODtcbmNvbnN0IFNldE1heFNpemVNZXRob2QgICAgICAgICAgICAgICAgICA9IDI5O1xuY29uc3QgU2V0TWluU2l6ZU1ldGhvZCAgICAgICAgICAgICAgICAgID0gMzA7XG5jb25zdCBTZXRSZWxhdGl2ZVBvc2l0aW9uTWV0aG9kICAgICAgICAgPSAzMTtcbmNvbnN0IFNldFJlc2l6YWJsZU1ldGhvZCAgICAgICAgICAgICAgICA9IDMyO1xuY29uc3QgU2V0U2l6ZU1ldGhvZCAgICAgICAgICAgICAgICAgICAgID0gMzM7XG5jb25zdCBTZXRUaXRsZU1ldGhvZCAgICAgICAgICAgICAgICAgICAgPSAzNDtcbmNvbnN0IFNldFpvb21NZXRob2QgICAgICAgICAgICAgICAgICAgICA9IDM1O1xuY29uc3QgU2hvd01ldGhvZCAgICAgICAgICAgICAgICAgICAgICAgID0gMzY7XG5jb25zdCBTaXplTWV0aG9kICAgICAgICAgICAgICAgICAgICAgICAgPSAzNztcbmNvbnN0IFRvZ2dsZUZ1bGxzY3JlZW5NZXRob2QgICAgICAgICAgICA9IDM4O1xuY29uc3QgVG9nZ2xlTWF4aW1pc2VNZXRob2QgICAgICAgICAgICAgID0gMzk7XG5jb25zdCBUb2dnbGVGcmFtZWxlc3NNZXRob2QgICAgICAgICAgICAgPSA0MDsgXG5jb25zdCBVbkZ1bGxzY3JlZW5NZXRob2QgICAgICAgICAgICAgICAgPSA0MTtcbmNvbnN0IFVuTWF4aW1pc2VNZXRob2QgICAgICAgICAgICAgICAgICA9IDQyO1xuY29uc3QgVW5NaW5pbWlzZU1ldGhvZCAgICAgICAgICAgICAgICAgID0gNDM7XG5jb25zdCBXaWR0aE1ldGhvZCAgICAgICAgICAgICAgICAgICAgICAgPSA0NDtcbmNvbnN0IFpvb21NZXRob2QgICAgICAgICAgICAgICAgICAgICAgICA9IDQ1O1xuY29uc3QgWm9vbUluTWV0aG9kICAgICAgICAgICAgICAgICAgICAgID0gNDY7XG5jb25zdCBab29tT3V0TWV0aG9kICAgICAgICAgICAgICAgICAgICAgPSA0NztcbmNvbnN0IFpvb21SZXNldE1ldGhvZCAgICAgICAgICAgICAgICAgICA9IDQ4O1xuY29uc3QgU25hcEFzc2lzdE1ldGhvZCAgICAgICAgICAgICAgICAgID0gNDk7XG5jb25zdCBGaWxlc0Ryb3BwZWQgICAgICAgICAgICAgICAgICAgICAgPSA1MDtcbmNvbnN0IFByaW50TWV0aG9kICAgICAgICAgICAgICAgICAgICAgICA9IDUxO1xuY29uc3QgU2V0U2NyZWVuTWV0aG9kICAgICAgICAgICAgICAgICAgID0gNTI7XG5cbi8qKlxuICogRmluZHMgdGhlIG5lYXJlc3QgZHJvcCB0YXJnZXQgZWxlbWVudCBieSB3YWxraW5nIHVwIHRoZSBET00gdHJlZS5cbiAqL1xuZnVuY3Rpb24gZ2V0RHJvcFRhcmdldEVsZW1lbnQoZWxlbWVudDogRWxlbWVudCB8IG51bGwpOiBFbGVtZW50IHwgbnVsbCB7XG4gICAgaWYgKCFlbGVtZW50KSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICByZXR1cm4gZWxlbWVudC5jbG9zZXN0KGBbJHtEUk9QX1RBUkdFVF9BVFRSSUJVVEV9XWApO1xufVxuXG4vKipcbiAqIENoZWNrIGlmIHdlIGNhbiB1c2UgV2ViVmlldzIncyBwb3N0TWVzc2FnZVdpdGhBZGRpdGlvbmFsT2JqZWN0cyAoV2luZG93cylcbiAqIEFsc28gY2hlY2tzIHRoYXQgRW5hYmxlRmlsZURyb3AgaXMgdHJ1ZSBmb3IgdGhpcyB3aW5kb3cuXG4gKi9cbmZ1bmN0aW9uIGNhblJlc29sdmVGaWxlUGF0aHMoKTogYm9vbGVhbiB7XG4gICAgLy8gTXVzdCBoYXZlIFdlYlZpZXcyJ3MgcG9zdE1lc3NhZ2VXaXRoQWRkaXRpb25hbE9iamVjdHMgQVBJIChXaW5kb3dzIG9ubHkpXG4gICAgaWYgKCh3aW5kb3cgYXMgYW55KS5jaHJvbWU/LndlYnZpZXc/LnBvc3RNZXNzYWdlV2l0aEFkZGl0aW9uYWxPYmplY3RzID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICAvLyBNdXN0IGhhdmUgRW5hYmxlRmlsZURyb3Agc2V0IHRvIHRydWUgZm9yIHRoaXMgd2luZG93XG4gICAgLy8gVGhpcyBmbGFnIGlzIHNldCBieSB0aGUgR28gYmFja2VuZCBkdXJpbmcgcnVudGltZSBpbml0aWFsaXphdGlvblxuICAgIHJldHVybiAod2luZG93IGFzIGFueSkuX3dhaWxzPy5mbGFncz8uZW5hYmxlRmlsZURyb3AgPT09IHRydWU7XG59XG5cbi8qKlxuICogU2VuZCBmaWxlIGRyb3AgdG8gYmFja2VuZCB2aWEgV2ViVmlldzIgKFdpbmRvd3Mgb25seSlcbiAqL1xuZnVuY3Rpb24gcmVzb2x2ZUZpbGVQYXRocyh4OiBudW1iZXIsIHk6IG51bWJlciwgZmlsZXM6IEZpbGVbXSk6IHZvaWQge1xuICAgIGlmICgod2luZG93IGFzIGFueSkuY2hyb21lPy53ZWJ2aWV3Py5wb3N0TWVzc2FnZVdpdGhBZGRpdGlvbmFsT2JqZWN0cykge1xuICAgICAgICAod2luZG93IGFzIGFueSkuY2hyb21lLndlYnZpZXcucG9zdE1lc3NhZ2VXaXRoQWRkaXRpb25hbE9iamVjdHMoYGZpbGU6ZHJvcDoke3h9OiR7eX1gLCBmaWxlcyk7XG4gICAgfVxufVxuXG4vLyBOYXRpdmUgZHJhZyBzdGF0ZSAoTGludXgvbWFjT1MgaW50ZXJjZXB0IERPTSBkcmFnIGV2ZW50cylcbmxldCBuYXRpdmVEcmFnQWN0aXZlID0gZmFsc2U7XG5cbi8qKlxuICogQ2xlYW5zIHVwIG5hdGl2ZSBkcmFnIHN0YXRlIGFuZCBob3ZlciBlZmZlY3RzLlxuICogQ2FsbGVkIG9uIGRyb3Agb3Igd2hlbiBkcmFnIGxlYXZlcyB0aGUgd2luZG93LlxuICovXG5mdW5jdGlvbiBjbGVhbnVwTmF0aXZlRHJhZygpOiB2b2lkIHtcbiAgICBuYXRpdmVEcmFnQWN0aXZlID0gZmFsc2U7XG4gICAgaWYgKGN1cnJlbnREcm9wVGFyZ2V0KSB7XG4gICAgICAgIGN1cnJlbnREcm9wVGFyZ2V0LmNsYXNzTGlzdC5yZW1vdmUoRFJPUF9UQVJHRVRfQUNUSVZFX0NMQVNTKTtcbiAgICAgICAgY3VycmVudERyb3BUYXJnZXQgPSBudWxsO1xuICAgIH1cbn1cblxuLyoqXG4gKiBDYWxsZWQgZnJvbSBHbyB3aGVuIGEgZmlsZSBkcmFnIGVudGVycyB0aGUgd2luZG93IG9uIExpbnV4L21hY09TLlxuICovXG5mdW5jdGlvbiBoYW5kbGVEcmFnRW50ZXIoKTogdm9pZCB7XG4gICAgLy8gQ2hlY2sgaWYgZmlsZSBkcm9wcyBhcmUgZW5hYmxlZCBmb3IgdGhpcyB3aW5kb3dcbiAgICBpZiAoKHdpbmRvdyBhcyBhbnkpLl93YWlscz8uZmxhZ3M/LmVuYWJsZUZpbGVEcm9wID09PSBmYWxzZSkge1xuICAgICAgICByZXR1cm47IC8vIEZpbGUgZHJvcHMgZGlzYWJsZWQsIGRvbid0IGFjdGl2YXRlIGRyYWcgc3RhdGVcbiAgICB9XG4gICAgbmF0aXZlRHJhZ0FjdGl2ZSA9IHRydWU7XG59XG5cbi8qKlxuICogQ2FsbGVkIGZyb20gR28gd2hlbiBhIGZpbGUgZHJhZyBsZWF2ZXMgdGhlIHdpbmRvdyBvbiBMaW51eC9tYWNPUy5cbiAqL1xuZnVuY3Rpb24gaGFuZGxlRHJhZ0xlYXZlKCk6IHZvaWQge1xuICAgIGNsZWFudXBOYXRpdmVEcmFnKCk7XG59XG5cbi8qKlxuICogQ2FsbGVkIGZyb20gR28gZHVyaW5nIGZpbGUgZHJhZyB0byB1cGRhdGUgaG92ZXIgc3RhdGUgb24gTGludXgvbWFjT1MuXG4gKiBAcGFyYW0geCAtIFggY29vcmRpbmF0ZSBpbiBDU1MgcGl4ZWxzXG4gKiBAcGFyYW0geSAtIFkgY29vcmRpbmF0ZSBpbiBDU1MgcGl4ZWxzXG4gKi9cbmZ1bmN0aW9uIGhhbmRsZURyYWdPdmVyKHg6IG51bWJlciwgeTogbnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKCFuYXRpdmVEcmFnQWN0aXZlKSByZXR1cm47XG4gICAgXG4gICAgLy8gQ2hlY2sgaWYgZmlsZSBkcm9wcyBhcmUgZW5hYmxlZCBmb3IgdGhpcyB3aW5kb3dcbiAgICBpZiAoKHdpbmRvdyBhcyBhbnkpLl93YWlscz8uZmxhZ3M/LmVuYWJsZUZpbGVEcm9wID09PSBmYWxzZSkge1xuICAgICAgICByZXR1cm47IC8vIEZpbGUgZHJvcHMgZGlzYWJsZWQsIGRvbid0IHNob3cgaG92ZXIgZWZmZWN0c1xuICAgIH1cbiAgICBcbiAgICBjb25zdCB0YXJnZXRFbGVtZW50ID0gZG9jdW1lbnQuZWxlbWVudEZyb21Qb2ludCh4LCB5KTtcbiAgICBjb25zdCBkcm9wVGFyZ2V0ID0gZ2V0RHJvcFRhcmdldEVsZW1lbnQodGFyZ2V0RWxlbWVudCk7XG4gICAgXG4gICAgaWYgKGN1cnJlbnREcm9wVGFyZ2V0ICYmIGN1cnJlbnREcm9wVGFyZ2V0ICE9PSBkcm9wVGFyZ2V0KSB7XG4gICAgICAgIGN1cnJlbnREcm9wVGFyZ2V0LmNsYXNzTGlzdC5yZW1vdmUoRFJPUF9UQVJHRVRfQUNUSVZFX0NMQVNTKTtcbiAgICB9XG4gICAgXG4gICAgaWYgKGRyb3BUYXJnZXQpIHtcbiAgICAgICAgZHJvcFRhcmdldC5jbGFzc0xpc3QuYWRkKERST1BfVEFSR0VUX0FDVElWRV9DTEFTUyk7XG4gICAgICAgIGN1cnJlbnREcm9wVGFyZ2V0ID0gZHJvcFRhcmdldDtcbiAgICB9IGVsc2Uge1xuICAgICAgICBjdXJyZW50RHJvcFRhcmdldCA9IG51bGw7XG4gICAgfVxufVxuXG5cblxuLy8gRXhwb3J0IHRoZSBoYW5kbGVycyBmb3IgdXNlIGJ5IEdvIHZpYSBpbmRleC50c1xuZXhwb3J0IHsgaGFuZGxlRHJhZ0VudGVyLCBoYW5kbGVEcmFnTGVhdmUsIGhhbmRsZURyYWdPdmVyIH07XG5cbi8qKlxuICogQSByZWNvcmQgZGVzY3JpYmluZyB0aGUgcG9zaXRpb24gb2YgYSB3aW5kb3cuXG4gKi9cbmludGVyZmFjZSBQb3NpdGlvbiB7XG4gICAgLyoqIFRoZSBob3Jpem9udGFsIHBvc2l0aW9uIG9mIHRoZSB3aW5kb3cuICovXG4gICAgeDogbnVtYmVyO1xuICAgIC8qKiBUaGUgdmVydGljYWwgcG9zaXRpb24gb2YgdGhlIHdpbmRvdy4gKi9cbiAgICB5OiBudW1iZXI7XG59XG5cbi8qKlxuICogQSByZWNvcmQgZGVzY3JpYmluZyB0aGUgc2l6ZSBvZiBhIHdpbmRvdy5cbiAqL1xuaW50ZXJmYWNlIFNpemUge1xuICAgIC8qKiBUaGUgd2lkdGggb2YgdGhlIHdpbmRvdy4gKi9cbiAgICB3aWR0aDogbnVtYmVyO1xuICAgIC8qKiBUaGUgaGVpZ2h0IG9mIHRoZSB3aW5kb3cuICovXG4gICAgaGVpZ2h0OiBudW1iZXI7XG59XG5cbi8vIFByaXZhdGUgZmllbGQgbmFtZXMuXG5jb25zdCBjYWxsZXJTeW0gPSBTeW1ib2woXCJjYWxsZXJcIik7XG5cbmNsYXNzIFdpbmRvdyB7XG4gICAgLy8gUHJpdmF0ZSBmaWVsZHMuXG4gICAgcHJpdmF0ZSBbY2FsbGVyU3ltXTogKG1lc3NhZ2U6IG51bWJlciwgYXJncz86IGFueSkgPT4gUHJvbWlzZTxhbnk+O1xuXG4gICAgLyoqXG4gICAgICogSW5pdGlhbGlzZXMgYSB3aW5kb3cgb2JqZWN0IHdpdGggdGhlIHNwZWNpZmllZCBuYW1lLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB0YXJnZXQgd2luZG93LlxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKG5hbWU6IHN0cmluZyA9ICcnKSB7XG4gICAgICAgIHRoaXNbY2FsbGVyU3ltXSA9IG5ld1J1bnRpbWVDYWxsZXIob2JqZWN0TmFtZXMuV2luZG93LCBuYW1lKVxuXG4gICAgICAgIC8vIGJpbmQgaW5zdGFuY2UgbWV0aG9kIHRvIG1ha2UgdGhlbSBlYXNpbHkgdXNhYmxlIGluIGV2ZW50IGhhbmRsZXJzXG4gICAgICAgIGZvciAoY29uc3QgbWV0aG9kIG9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKFdpbmRvdy5wcm90b3R5cGUpKSB7XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgbWV0aG9kICE9PSBcImNvbnN0cnVjdG9yXCJcbiAgICAgICAgICAgICAgICAmJiB0eXBlb2YgKHRoaXMgYXMgYW55KVttZXRob2RdID09PSBcImZ1bmN0aW9uXCJcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICh0aGlzIGFzIGFueSlbbWV0aG9kXSA9ICh0aGlzIGFzIGFueSlbbWV0aG9kXS5iaW5kKHRoaXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgc3BlY2lmaWVkIHdpbmRvdy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHdpbmRvdyB0byBnZXQuXG4gICAgICogQHJldHVybnMgVGhlIGNvcnJlc3BvbmRpbmcgd2luZG93IG9iamVjdC5cbiAgICAgKi9cbiAgICBHZXQobmFtZTogc3RyaW5nKTogV2luZG93IHtcbiAgICAgICAgcmV0dXJuIG5ldyBXaW5kb3cobmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgYWJzb2x1dGUgcG9zaXRpb24gb2YgdGhlIHdpbmRvdy5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIFRoZSBjdXJyZW50IGFic29sdXRlIHBvc2l0aW9uIG9mIHRoZSB3aW5kb3cuXG4gICAgICovXG4gICAgUG9zaXRpb24oKTogUHJvbWlzZTxQb3NpdGlvbj4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFBvc2l0aW9uTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDZW50ZXJzIHRoZSB3aW5kb3cgb24gdGhlIHNjcmVlbi5cbiAgICAgKi9cbiAgICBDZW50ZXIoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oQ2VudGVyTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDbG9zZXMgdGhlIHdpbmRvdy5cbiAgICAgKi9cbiAgICBDbG9zZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShDbG9zZU1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGlzYWJsZXMgbWluL21heCBzaXplIGNvbnN0cmFpbnRzLlxuICAgICAqL1xuICAgIERpc2FibGVTaXplQ29uc3RyYWludHMoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oRGlzYWJsZVNpemVDb25zdHJhaW50c01ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRW5hYmxlcyBtaW4vbWF4IHNpemUgY29uc3RyYWludHMuXG4gICAgICovXG4gICAgRW5hYmxlU2l6ZUNvbnN0cmFpbnRzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKEVuYWJsZVNpemVDb25zdHJhaW50c01ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRm9jdXNlcyB0aGUgd2luZG93LlxuICAgICAqL1xuICAgIEZvY3VzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKEZvY3VzTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGb3JjZXMgdGhlIHdpbmRvdyB0byByZWxvYWQgdGhlIHBhZ2UgYXNzZXRzLlxuICAgICAqL1xuICAgIEZvcmNlUmVsb2FkKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKEZvcmNlUmVsb2FkTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTd2l0Y2hlcyB0aGUgd2luZG93IHRvIGZ1bGxzY3JlZW4gbW9kZS5cbiAgICAgKi9cbiAgICBGdWxsc2NyZWVuKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKEZ1bGxzY3JlZW5NZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHNjcmVlbiB0aGF0IHRoZSB3aW5kb3cgaXMgb24uXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBUaGUgc2NyZWVuIHRoZSB3aW5kb3cgaXMgY3VycmVudGx5IG9uLlxuICAgICAqL1xuICAgIEdldFNjcmVlbigpOiBQcm9taXNlPFNjcmVlbj4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKEdldFNjcmVlbk1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgY3VycmVudCB6b29tIGxldmVsIG9mIHRoZSB3aW5kb3cuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBUaGUgY3VycmVudCB6b29tIGxldmVsLlxuICAgICAqL1xuICAgIEdldFpvb20oKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShHZXRab29tTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBoZWlnaHQgb2YgdGhlIHdpbmRvdy5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIFRoZSBjdXJyZW50IGhlaWdodCBvZiB0aGUgd2luZG93LlxuICAgICAqL1xuICAgIEhlaWdodCgpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKEhlaWdodE1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGlkZXMgdGhlIHdpbmRvdy5cbiAgICAgKi9cbiAgICBIaWRlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKEhpZGVNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgd2luZG93IGlzIGZvY3VzZWQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBXaGV0aGVyIHRoZSB3aW5kb3cgaXMgY3VycmVudGx5IGZvY3VzZWQuXG4gICAgICovXG4gICAgSXNGb2N1c2VkKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKElzRm9jdXNlZE1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0cnVlIGlmIHRoZSB3aW5kb3cgaXMgZnVsbHNjcmVlbi5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIFdoZXRoZXIgdGhlIHdpbmRvdyBpcyBjdXJyZW50bHkgZnVsbHNjcmVlbi5cbiAgICAgKi9cbiAgICBJc0Z1bGxzY3JlZW4oKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oSXNGdWxsc2NyZWVuTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRydWUgaWYgdGhlIHdpbmRvdyBpcyBtYXhpbWlzZWQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBXaGV0aGVyIHRoZSB3aW5kb3cgaXMgY3VycmVudGx5IG1heGltaXNlZC5cbiAgICAgKi9cbiAgICBJc01heGltaXNlZCgpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShJc01heGltaXNlZE1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0cnVlIGlmIHRoZSB3aW5kb3cgaXMgbWluaW1pc2VkLlxuICAgICAqXG4gICAgICogQHJldHVybnMgV2hldGhlciB0aGUgd2luZG93IGlzIGN1cnJlbnRseSBtaW5pbWlzZWQuXG4gICAgICovXG4gICAgSXNNaW5pbWlzZWQoKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oSXNNaW5pbWlzZWRNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1heGltaXNlcyB0aGUgd2luZG93LlxuICAgICAqL1xuICAgIE1heGltaXNlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKE1heGltaXNlTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNaW5pbWlzZXMgdGhlIHdpbmRvdy5cbiAgICAgKi9cbiAgICBNaW5pbWlzZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShNaW5pbWlzZU1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgbmFtZSBvZiB0aGUgd2luZG93LlxuICAgICAqXG4gICAgICogQHJldHVybnMgVGhlIG5hbWUgb2YgdGhlIHdpbmRvdy5cbiAgICAgKi9cbiAgICBOYW1lKCk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oTmFtZU1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogT3BlbnMgdGhlIGRldmVsb3BtZW50IHRvb2xzIHBhbmUuXG4gICAgICovXG4gICAgT3BlbkRldlRvb2xzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKE9wZW5EZXZUb29sc01ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgcmVsYXRpdmUgcG9zaXRpb24gb2YgdGhlIHdpbmRvdyB0byB0aGUgc2NyZWVuLlxuICAgICAqXG4gICAgICogQHJldHVybnMgVGhlIGN1cnJlbnQgcmVsYXRpdmUgcG9zaXRpb24gb2YgdGhlIHdpbmRvdy5cbiAgICAgKi9cbiAgICBSZWxhdGl2ZVBvc2l0aW9uKCk6IFByb21pc2U8UG9zaXRpb24+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShSZWxhdGl2ZVBvc2l0aW9uTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZWxvYWRzIHRoZSBwYWdlIGFzc2V0cy5cbiAgICAgKi9cbiAgICBSZWxvYWQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oUmVsb2FkTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRydWUgaWYgdGhlIHdpbmRvdyBpcyByZXNpemFibGUuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBXaGV0aGVyIHRoZSB3aW5kb3cgaXMgY3VycmVudGx5IHJlc2l6YWJsZS5cbiAgICAgKi9cbiAgICBSZXNpemFibGUoKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oUmVzaXphYmxlTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXN0b3JlcyB0aGUgd2luZG93IHRvIGl0cyBwcmV2aW91cyBzdGF0ZSBpZiBpdCB3YXMgcHJldmlvdXNseSBtaW5pbWlzZWQsIG1heGltaXNlZCBvciBmdWxsc2NyZWVuLlxuICAgICAqL1xuICAgIFJlc3RvcmUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oUmVzdG9yZU1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgYWJzb2x1dGUgcG9zaXRpb24gb2YgdGhlIHdpbmRvdy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB4IC0gVGhlIGRlc2lyZWQgaG9yaXpvbnRhbCBhYnNvbHV0ZSBwb3NpdGlvbiBvZiB0aGUgd2luZG93LlxuICAgICAqIEBwYXJhbSB5IC0gVGhlIGRlc2lyZWQgdmVydGljYWwgYWJzb2x1dGUgcG9zaXRpb24gb2YgdGhlIHdpbmRvdy5cbiAgICAgKi9cbiAgICBTZXRQb3NpdGlvbih4OiBudW1iZXIsIHk6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFNldFBvc2l0aW9uTWV0aG9kLCB7IHgsIHkgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgd2luZG93IHRvIGJlIGFsd2F5cyBvbiB0b3AuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gYWx3YXlzT25Ub3AgLSBXaGV0aGVyIHRoZSB3aW5kb3cgc2hvdWxkIHN0YXkgb24gdG9wLlxuICAgICAqL1xuICAgIFNldEFsd2F5c09uVG9wKGFsd2F5c09uVG9wOiBib29sZWFuKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oU2V0QWx3YXlzT25Ub3BNZXRob2QsIHsgYWx3YXlzT25Ub3AgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgYmFja2dyb3VuZCBjb2xvdXIgb2YgdGhlIHdpbmRvdy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSByIC0gVGhlIGRlc2lyZWQgcmVkIGNvbXBvbmVudCBvZiB0aGUgd2luZG93IGJhY2tncm91bmQuXG4gICAgICogQHBhcmFtIGcgLSBUaGUgZGVzaXJlZCBncmVlbiBjb21wb25lbnQgb2YgdGhlIHdpbmRvdyBiYWNrZ3JvdW5kLlxuICAgICAqIEBwYXJhbSBiIC0gVGhlIGRlc2lyZWQgYmx1ZSBjb21wb25lbnQgb2YgdGhlIHdpbmRvdyBiYWNrZ3JvdW5kLlxuICAgICAqIEBwYXJhbSBhIC0gVGhlIGRlc2lyZWQgYWxwaGEgY29tcG9uZW50IG9mIHRoZSB3aW5kb3cgYmFja2dyb3VuZC5cbiAgICAgKi9cbiAgICBTZXRCYWNrZ3JvdW5kQ29sb3VyKHI6IG51bWJlciwgZzogbnVtYmVyLCBiOiBudW1iZXIsIGE6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFNldEJhY2tncm91bmRDb2xvdXJNZXRob2QsIHsgciwgZywgYiwgYSB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIHRoZSB3aW5kb3cgZnJhbWUgYW5kIHRpdGxlIGJhci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBmcmFtZWxlc3MgLSBXaGV0aGVyIHRoZSB3aW5kb3cgc2hvdWxkIGJlIGZyYW1lbGVzcy5cbiAgICAgKi9cbiAgICBTZXRGcmFtZWxlc3MoZnJhbWVsZXNzOiBib29sZWFuKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oU2V0RnJhbWVsZXNzTWV0aG9kLCB7IGZyYW1lbGVzcyB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEaXNhYmxlcyB0aGUgc3lzdGVtIGZ1bGxzY3JlZW4gYnV0dG9uLlxuICAgICAqXG4gICAgICogQHBhcmFtIGVuYWJsZWQgLSBXaGV0aGVyIHRoZSBmdWxsc2NyZWVuIGJ1dHRvbiBzaG91bGQgYmUgZW5hYmxlZC5cbiAgICAgKi9cbiAgICBTZXRGdWxsc2NyZWVuQnV0dG9uRW5hYmxlZChlbmFibGVkOiBib29sZWFuKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oU2V0RnVsbHNjcmVlbkJ1dHRvbkVuYWJsZWRNZXRob2QsIHsgZW5hYmxlZCB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBtYXhpbXVtIHNpemUgb2YgdGhlIHdpbmRvdy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB3aWR0aCAtIFRoZSBkZXNpcmVkIG1heGltdW0gd2lkdGggb2YgdGhlIHdpbmRvdy5cbiAgICAgKiBAcGFyYW0gaGVpZ2h0IC0gVGhlIGRlc2lyZWQgbWF4aW11bSBoZWlnaHQgb2YgdGhlIHdpbmRvdy5cbiAgICAgKi9cbiAgICBTZXRNYXhTaXplKHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oU2V0TWF4U2l6ZU1ldGhvZCwgeyB3aWR0aCwgaGVpZ2h0IH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIG1pbmltdW0gc2l6ZSBvZiB0aGUgd2luZG93LlxuICAgICAqXG4gICAgICogQHBhcmFtIHdpZHRoIC0gVGhlIGRlc2lyZWQgbWluaW11bSB3aWR0aCBvZiB0aGUgd2luZG93LlxuICAgICAqIEBwYXJhbSBoZWlnaHQgLSBUaGUgZGVzaXJlZCBtaW5pbXVtIGhlaWdodCBvZiB0aGUgd2luZG93LlxuICAgICAqL1xuICAgIFNldE1pblNpemUod2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShTZXRNaW5TaXplTWV0aG9kLCB7IHdpZHRoLCBoZWlnaHQgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgcmVsYXRpdmUgcG9zaXRpb24gb2YgdGhlIHdpbmRvdyB0byB0aGUgc2NyZWVuLlxuICAgICAqXG4gICAgICogQHBhcmFtIHggLSBUaGUgZGVzaXJlZCBob3Jpem9udGFsIHJlbGF0aXZlIHBvc2l0aW9uIG9mIHRoZSB3aW5kb3cuXG4gICAgICogQHBhcmFtIHkgLSBUaGUgZGVzaXJlZCB2ZXJ0aWNhbCByZWxhdGl2ZSBwb3NpdGlvbiBvZiB0aGUgd2luZG93LlxuICAgICAqL1xuICAgIFNldFJlbGF0aXZlUG9zaXRpb24oeDogbnVtYmVyLCB5OiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShTZXRSZWxhdGl2ZVBvc2l0aW9uTWV0aG9kLCB7IHgsIHkgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB3aGV0aGVyIHRoZSB3aW5kb3cgaXMgcmVzaXphYmxlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHJlc2l6YWJsZSAtIFdoZXRoZXIgdGhlIHdpbmRvdyBzaG91bGQgYmUgcmVzaXphYmxlLlxuICAgICAqL1xuICAgIFNldFJlc2l6YWJsZShyZXNpemFibGU6IGJvb2xlYW4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShTZXRSZXNpemFibGVNZXRob2QsIHsgcmVzaXphYmxlIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHNpemUgb2YgdGhlIHdpbmRvdy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB3aWR0aCAtIFRoZSBkZXNpcmVkIHdpZHRoIG9mIHRoZSB3aW5kb3cuXG4gICAgICogQHBhcmFtIGhlaWdodCAtIFRoZSBkZXNpcmVkIGhlaWdodCBvZiB0aGUgd2luZG93LlxuICAgICAqL1xuICAgIFNldFNpemUod2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShTZXRTaXplTWV0aG9kLCB7IHdpZHRoLCBoZWlnaHQgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgdGl0bGUgb2YgdGhlIHdpbmRvdy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB0aXRsZSAtIFRoZSBkZXNpcmVkIHRpdGxlIG9mIHRoZSB3aW5kb3cuXG4gICAgICovXG4gICAgU2V0VGl0bGUodGl0bGU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFNldFRpdGxlTWV0aG9kLCB7IHRpdGxlIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHpvb20gbGV2ZWwgb2YgdGhlIHdpbmRvdy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB6b29tIC0gVGhlIGRlc2lyZWQgem9vbSBsZXZlbC5cbiAgICAgKi9cbiAgICBTZXRab29tKHpvb206IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFNldFpvb21NZXRob2QsIHsgem9vbSB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTaG93cyB0aGUgd2luZG93LlxuICAgICAqL1xuICAgIFNob3coKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oU2hvd01ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgc2l6ZSBvZiB0aGUgd2luZG93LlxuICAgICAqXG4gICAgICogQHJldHVybnMgVGhlIGN1cnJlbnQgc2l6ZSBvZiB0aGUgd2luZG93LlxuICAgICAqL1xuICAgIFNpemUoKTogUHJvbWlzZTxTaXplPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oU2l6ZU1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVG9nZ2xlcyB0aGUgd2luZG93IGJldHdlZW4gZnVsbHNjcmVlbiBhbmQgbm9ybWFsLlxuICAgICAqL1xuICAgIFRvZ2dsZUZ1bGxzY3JlZW4oKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oVG9nZ2xlRnVsbHNjcmVlbk1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVG9nZ2xlcyB0aGUgd2luZG93IGJldHdlZW4gbWF4aW1pc2VkIGFuZCBub3JtYWwuXG4gICAgICovXG4gICAgVG9nZ2xlTWF4aW1pc2UoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oVG9nZ2xlTWF4aW1pc2VNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRvZ2dsZXMgdGhlIHdpbmRvdyBiZXR3ZWVuIGZyYW1lbGVzcyBhbmQgbm9ybWFsLlxuICAgICAqL1xuICAgIFRvZ2dsZUZyYW1lbGVzcygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShUb2dnbGVGcmFtZWxlc3NNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVuLWZ1bGxzY3JlZW5zIHRoZSB3aW5kb3cuXG4gICAgICovXG4gICAgVW5GdWxsc2NyZWVuKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFVuRnVsbHNjcmVlbk1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVW4tbWF4aW1pc2VzIHRoZSB3aW5kb3cuXG4gICAgICovXG4gICAgVW5NYXhpbWlzZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShVbk1heGltaXNlTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVbi1taW5pbWlzZXMgdGhlIHdpbmRvdy5cbiAgICAgKi9cbiAgICBVbk1pbmltaXNlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFVuTWluaW1pc2VNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHdpZHRoIG9mIHRoZSB3aW5kb3cuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBUaGUgY3VycmVudCB3aWR0aCBvZiB0aGUgd2luZG93LlxuICAgICAqL1xuICAgIFdpZHRoKCk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oV2lkdGhNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFpvb21zIHRoZSB3aW5kb3cuXG4gICAgICovXG4gICAgWm9vbSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShab29tTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbmNyZWFzZXMgdGhlIHpvb20gbGV2ZWwgb2YgdGhlIHdlYnZpZXcgY29udGVudC5cbiAgICAgKi9cbiAgICBab29tSW4oKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oWm9vbUluTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEZWNyZWFzZXMgdGhlIHpvb20gbGV2ZWwgb2YgdGhlIHdlYnZpZXcgY29udGVudC5cbiAgICAgKi9cbiAgICBab29tT3V0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFpvb21PdXRNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc2V0cyB0aGUgem9vbSBsZXZlbCBvZiB0aGUgd2VidmlldyBjb250ZW50LlxuICAgICAqL1xuICAgIFpvb21SZXNldCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShab29tUmVzZXRNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXMgZmlsZSBkcm9wcyBvcmlnaW5hdGluZyBmcm9tIHBsYXRmb3JtLXNwZWNpZmljIGNvZGUgKGUuZy4sIG1hY09TL0xpbnV4IG5hdGl2ZSBkcmFnLWFuZC1kcm9wKS5cbiAgICAgKiBHYXRoZXJzIGluZm9ybWF0aW9uIGFib3V0IHRoZSBkcm9wIHRhcmdldCBlbGVtZW50IGFuZCBzZW5kcyBpdCBiYWNrIHRvIHRoZSBHbyBiYWNrZW5kLlxuICAgICAqXG4gICAgICogQHBhcmFtIGZpbGVuYW1lcyAtIEFuIGFycmF5IG9mIGZpbGUgcGF0aHMgKHN0cmluZ3MpIHRoYXQgd2VyZSBkcm9wcGVkLlxuICAgICAqIEBwYXJhbSB4IC0gVGhlIHgtY29vcmRpbmF0ZSBvZiB0aGUgZHJvcCBldmVudCAoQ1NTIHBpeGVscykuXG4gICAgICogQHBhcmFtIHkgLSBUaGUgeS1jb29yZGluYXRlIG9mIHRoZSBkcm9wIGV2ZW50IChDU1MgcGl4ZWxzKS5cbiAgICAgKi9cbiAgICBIYW5kbGVQbGF0Zm9ybUZpbGVEcm9wKGZpbGVuYW1lczogc3RyaW5nW10sIHg6IG51bWJlciwgeTogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIC8vIENoZWNrIGlmIGZpbGUgZHJvcHMgYXJlIGVuYWJsZWQgZm9yIHRoaXMgd2luZG93XG4gICAgICAgIGlmICgod2luZG93IGFzIGFueSkuX3dhaWxzPy5mbGFncz8uZW5hYmxlRmlsZURyb3AgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICByZXR1cm47IC8vIEZpbGUgZHJvcHMgZGlzYWJsZWQsIGlnbm9yZSB0aGUgZHJvcFxuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICBjb25zdCBlbGVtZW50ID0gZG9jdW1lbnQuZWxlbWVudEZyb21Qb2ludCh4LCB5KTtcbiAgICAgICAgY29uc3QgZHJvcFRhcmdldCA9IGdldERyb3BUYXJnZXRFbGVtZW50KGVsZW1lbnQpO1xuXG4gICAgICAgIGlmICghZHJvcFRhcmdldCkge1xuICAgICAgICAgICAgLy8gRHJvcCB3YXMgbm90IG9uIGEgZGVzaWduYXRlZCBkcm9wIHRhcmdldCAtIGlnbm9yZVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZWxlbWVudERldGFpbHMgPSB7XG4gICAgICAgICAgICBpZDogZHJvcFRhcmdldC5pZCxcbiAgICAgICAgICAgIGNsYXNzTGlzdDogQXJyYXkuZnJvbShkcm9wVGFyZ2V0LmNsYXNzTGlzdCksXG4gICAgICAgICAgICBhdHRyaWJ1dGVzOiB7fSBhcyB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9LFxuICAgICAgICB9O1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRyb3BUYXJnZXQuYXR0cmlidXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29uc3QgYXR0ciA9IGRyb3BUYXJnZXQuYXR0cmlidXRlc1tpXTtcbiAgICAgICAgICAgIGVsZW1lbnREZXRhaWxzLmF0dHJpYnV0ZXNbYXR0ci5uYW1lXSA9IGF0dHIudmFsdWU7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBwYXlsb2FkID0ge1xuICAgICAgICAgICAgZmlsZW5hbWVzLFxuICAgICAgICAgICAgeCxcbiAgICAgICAgICAgIHksXG4gICAgICAgICAgICBlbGVtZW50RGV0YWlscyxcbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzW2NhbGxlclN5bV0oRmlsZXNEcm9wcGVkLCBwYXlsb2FkKTtcbiAgICAgICAgXG4gICAgICAgIC8vIENsZWFuIHVwIG5hdGl2ZSBkcmFnIHN0YXRlIGFmdGVyIGRyb3BcbiAgICAgICAgY2xlYW51cE5hdGl2ZURyYWcoKTtcbiAgICB9XG4gIFxuICAgIC8qKlxuICAgICAqIE1vdmVzIHRoZSB3aW5kb3cgdG8gdGhlIGNlbnRlciBvZiB0aGUgc3BlY2lmaWVkIHNjcmVlbidzIHdvcmsgYXJlYS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBzY3JlZW5JRCAtIFRoZSBJRCBvZiB0aGUgdGFyZ2V0IHNjcmVlbi5cbiAgICAgKi9cbiAgICBTZXRTY3JlZW4oc2NyZWVuSUQ6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFNldFNjcmVlbk1ldGhvZCwgeyBzY3JlZW5JRCB9KTtcbiAgICB9XG5cbiAgICAvKiBUcmlnZ2VycyBXaW5kb3dzIDExIFNuYXAgQXNzaXN0IGZlYXR1cmUgKFdpbmRvd3Mgb25seSkuXG4gICAgICogVGhpcyBpcyBlcXVpdmFsZW50IHRvIHByZXNzaW5nIFdpbitaIGFuZCBzaG93cyBzbmFwIGxheW91dCBvcHRpb25zLlxuICAgICAqL1xuICAgIFNuYXBBc3Npc3QoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oU25hcEFzc2lzdE1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogT3BlbnMgdGhlIHByaW50IGRpYWxvZyBmb3IgdGhlIHdpbmRvdy5cbiAgICAgKi9cbiAgICBQcmludCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShQcmludE1ldGhvZCk7XG4gICAgfVxufVxuXG4vKipcbiAqIFRoZSB3aW5kb3cgd2l0aGluIHdoaWNoIHRoZSBzY3JpcHQgaXMgcnVubmluZy5cbiAqL1xuY29uc3QgdGhpc1dpbmRvdyA9IG5ldyBXaW5kb3coJycpO1xuXG4vKipcbiAqIFNldHMgdXAgZ2xvYmFsIGRyYWcgYW5kIGRyb3AgZXZlbnQgbGlzdGVuZXJzIGZvciBmaWxlIGRyb3BzLlxuICogSGFuZGxlcyB2aXN1YWwgZmVlZGJhY2sgKGhvdmVyIHN0YXRlKSBhbmQgZmlsZSBkcm9wIHByb2Nlc3NpbmcuXG4gKi9cbmZ1bmN0aW9uIHNldHVwRHJvcFRhcmdldExpc3RlbmVycygpIHtcbiAgICBjb25zdCBkb2NFbGVtZW50ID0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50O1xuICAgIGxldCBkcmFnRW50ZXJDb3VudGVyID0gMDtcblxuICAgIGRvY0VsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignZHJhZ2VudGVyJywgKGV2ZW50KSA9PiB7XG4gICAgICAgIGlmICghZXZlbnQuZGF0YVRyYW5zZmVyPy50eXBlcy5pbmNsdWRlcygnRmlsZXMnKSkge1xuICAgICAgICAgICAgcmV0dXJuOyAvLyBPbmx5IGhhbmRsZSBmaWxlIGRyYWdzLCBsZXQgb3RoZXIgZHJhZ3MgcGFzcyB0aHJvdWdoXG4gICAgICAgIH1cbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTsgLy8gQWx3YXlzIHByZXZlbnQgZGVmYXVsdCB0byBzdG9wIGJyb3dzZXIgbmF2aWdhdGlvblxuICAgICAgICAvLyBPbiBXaW5kb3dzLCBjaGVjayBpZiBmaWxlIGRyb3BzIGFyZSBlbmFibGVkIGZvciB0aGlzIHdpbmRvd1xuICAgICAgICBpZiAoKHdpbmRvdyBhcyBhbnkpLl93YWlscz8uZmxhZ3M/LmVuYWJsZUZpbGVEcm9wID09PSBmYWxzZSkge1xuICAgICAgICAgICAgZXZlbnQuZGF0YVRyYW5zZmVyLmRyb3BFZmZlY3QgPSAnbm9uZSc7IC8vIFNob3cgXCJubyBkcm9wXCIgY3Vyc29yXG4gICAgICAgICAgICByZXR1cm47IC8vIEZpbGUgZHJvcHMgZGlzYWJsZWQsIGRvbid0IHNob3cgaG92ZXIgZWZmZWN0c1xuICAgICAgICB9XG4gICAgICAgIGRyYWdFbnRlckNvdW50ZXIrKztcbiAgICAgICAgXG4gICAgICAgIGNvbnN0IHRhcmdldEVsZW1lbnQgPSBkb2N1bWVudC5lbGVtZW50RnJvbVBvaW50KGV2ZW50LmNsaWVudFgsIGV2ZW50LmNsaWVudFkpO1xuICAgICAgICBjb25zdCBkcm9wVGFyZ2V0ID0gZ2V0RHJvcFRhcmdldEVsZW1lbnQodGFyZ2V0RWxlbWVudCk7XG5cbiAgICAgICAgLy8gVXBkYXRlIGhvdmVyIHN0YXRlXG4gICAgICAgIGlmIChjdXJyZW50RHJvcFRhcmdldCAmJiBjdXJyZW50RHJvcFRhcmdldCAhPT0gZHJvcFRhcmdldCkge1xuICAgICAgICAgICAgY3VycmVudERyb3BUYXJnZXQuY2xhc3NMaXN0LnJlbW92ZShEUk9QX1RBUkdFVF9BQ1RJVkVfQ0xBU1MpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRyb3BUYXJnZXQpIHtcbiAgICAgICAgICAgIGRyb3BUYXJnZXQuY2xhc3NMaXN0LmFkZChEUk9QX1RBUkdFVF9BQ1RJVkVfQ0xBU1MpO1xuICAgICAgICAgICAgZXZlbnQuZGF0YVRyYW5zZmVyLmRyb3BFZmZlY3QgPSAnY29weSc7XG4gICAgICAgICAgICBjdXJyZW50RHJvcFRhcmdldCA9IGRyb3BUYXJnZXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBldmVudC5kYXRhVHJhbnNmZXIuZHJvcEVmZmVjdCA9ICdub25lJztcbiAgICAgICAgICAgIGN1cnJlbnREcm9wVGFyZ2V0ID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH0sIGZhbHNlKTtcblxuICAgIGRvY0VsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignZHJhZ292ZXInLCAoZXZlbnQpID0+IHtcbiAgICAgICAgaWYgKCFldmVudC5kYXRhVHJhbnNmZXI/LnR5cGVzLmluY2x1ZGVzKCdGaWxlcycpKSB7XG4gICAgICAgICAgICByZXR1cm47IC8vIE9ubHkgaGFuZGxlIGZpbGUgZHJhZ3NcbiAgICAgICAgfVxuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpOyAvLyBBbHdheXMgcHJldmVudCBkZWZhdWx0IHRvIHN0b3AgYnJvd3NlciBuYXZpZ2F0aW9uXG4gICAgICAgIC8vIE9uIFdpbmRvd3MsIGNoZWNrIGlmIGZpbGUgZHJvcHMgYXJlIGVuYWJsZWQgZm9yIHRoaXMgd2luZG93XG4gICAgICAgIGlmICgod2luZG93IGFzIGFueSkuX3dhaWxzPy5mbGFncz8uZW5hYmxlRmlsZURyb3AgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICBldmVudC5kYXRhVHJhbnNmZXIuZHJvcEVmZmVjdCA9ICdub25lJzsgLy8gU2hvdyBcIm5vIGRyb3BcIiBjdXJzb3JcbiAgICAgICAgICAgIHJldHVybjsgLy8gRmlsZSBkcm9wcyBkaXNhYmxlZCwgZG9uJ3Qgc2hvdyBob3ZlciBlZmZlY3RzXG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIC8vIFVwZGF0ZSBkcm9wIHRhcmdldCBhcyBjdXJzb3IgbW92ZXNcbiAgICAgICAgY29uc3QgdGFyZ2V0RWxlbWVudCA9IGRvY3VtZW50LmVsZW1lbnRGcm9tUG9pbnQoZXZlbnQuY2xpZW50WCwgZXZlbnQuY2xpZW50WSk7XG4gICAgICAgIGNvbnN0IGRyb3BUYXJnZXQgPSBnZXREcm9wVGFyZ2V0RWxlbWVudCh0YXJnZXRFbGVtZW50KTtcbiAgICAgICAgXG4gICAgICAgIGlmIChjdXJyZW50RHJvcFRhcmdldCAmJiBjdXJyZW50RHJvcFRhcmdldCAhPT0gZHJvcFRhcmdldCkge1xuICAgICAgICAgICAgY3VycmVudERyb3BUYXJnZXQuY2xhc3NMaXN0LnJlbW92ZShEUk9QX1RBUkdFVF9BQ1RJVkVfQ0xBU1MpO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICBpZiAoZHJvcFRhcmdldCkge1xuICAgICAgICAgICAgaWYgKCFkcm9wVGFyZ2V0LmNsYXNzTGlzdC5jb250YWlucyhEUk9QX1RBUkdFVF9BQ1RJVkVfQ0xBU1MpKSB7XG4gICAgICAgICAgICAgICAgZHJvcFRhcmdldC5jbGFzc0xpc3QuYWRkKERST1BfVEFSR0VUX0FDVElWRV9DTEFTUyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBldmVudC5kYXRhVHJhbnNmZXIuZHJvcEVmZmVjdCA9ICdjb3B5JztcbiAgICAgICAgICAgIGN1cnJlbnREcm9wVGFyZ2V0ID0gZHJvcFRhcmdldDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGV2ZW50LmRhdGFUcmFuc2Zlci5kcm9wRWZmZWN0ID0gJ25vbmUnO1xuICAgICAgICAgICAgY3VycmVudERyb3BUYXJnZXQgPSBudWxsO1xuICAgICAgICB9XG4gICAgfSwgZmFsc2UpO1xuXG4gICAgZG9jRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdkcmFnbGVhdmUnLCAoZXZlbnQpID0+IHtcbiAgICAgICAgaWYgKCFldmVudC5kYXRhVHJhbnNmZXI/LnR5cGVzLmluY2x1ZGVzKCdGaWxlcycpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTsgLy8gQWx3YXlzIHByZXZlbnQgZGVmYXVsdCB0byBzdG9wIGJyb3dzZXIgbmF2aWdhdGlvblxuICAgICAgICAvLyBPbiBXaW5kb3dzLCBjaGVjayBpZiBmaWxlIGRyb3BzIGFyZSBlbmFibGVkIGZvciB0aGlzIHdpbmRvd1xuICAgICAgICBpZiAoKHdpbmRvdyBhcyBhbnkpLl93YWlscz8uZmxhZ3M/LmVuYWJsZUZpbGVEcm9wID09PSBmYWxzZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICAvLyBPbiBMaW51eC9XZWJLaXRHVEsgYW5kIG1hY09TLCBkcmFnbGVhdmUgZmlyZXMgaW1tZWRpYXRlbHkgd2l0aCByZWxhdGVkVGFyZ2V0PW51bGwgd2hlbiBuYXRpdmVcbiAgICAgICAgLy8gZHJhZyBoYW5kbGluZyBpcyBpbnZvbHZlZC4gSWdub3JlIHRoZXNlIHNwdXJpb3VzIGV2ZW50cyAtIHdlJ2xsIGNsZWFuIHVwIG9uIGRyb3AgaW5zdGVhZC5cbiAgICAgICAgaWYgKGV2ZW50LnJlbGF0ZWRUYXJnZXQgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgZHJhZ0VudGVyQ291bnRlci0tO1xuICAgICAgICBcbiAgICAgICAgaWYgKGRyYWdFbnRlckNvdW50ZXIgPT09IDAgfHwgXG4gICAgICAgICAgICAoY3VycmVudERyb3BUYXJnZXQgJiYgIWN1cnJlbnREcm9wVGFyZ2V0LmNvbnRhaW5zKGV2ZW50LnJlbGF0ZWRUYXJnZXQgYXMgTm9kZSkpKSB7XG4gICAgICAgICAgICBpZiAoY3VycmVudERyb3BUYXJnZXQpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50RHJvcFRhcmdldC5jbGFzc0xpc3QucmVtb3ZlKERST1BfVEFSR0VUX0FDVElWRV9DTEFTUyk7XG4gICAgICAgICAgICAgICAgY3VycmVudERyb3BUYXJnZXQgPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZHJhZ0VudGVyQ291bnRlciA9IDA7XG4gICAgICAgIH1cbiAgICB9LCBmYWxzZSk7XG5cbiAgICBkb2NFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2Ryb3AnLCAoZXZlbnQpID0+IHtcbiAgICAgICAgaWYgKCFldmVudC5kYXRhVHJhbnNmZXI/LnR5cGVzLmluY2x1ZGVzKCdGaWxlcycpKSB7XG4gICAgICAgICAgICByZXR1cm47IC8vIE9ubHkgaGFuZGxlIGZpbGUgZHJvcHNcbiAgICAgICAgfVxuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpOyAvLyBBbHdheXMgcHJldmVudCBkZWZhdWx0IHRvIHN0b3AgYnJvd3NlciBuYXZpZ2F0aW9uXG4gICAgICAgIC8vIE9uIFdpbmRvd3MsIGNoZWNrIGlmIGZpbGUgZHJvcHMgYXJlIGVuYWJsZWQgZm9yIHRoaXMgd2luZG93XG4gICAgICAgIGlmICgod2luZG93IGFzIGFueSkuX3dhaWxzPy5mbGFncz8uZW5hYmxlRmlsZURyb3AgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZHJhZ0VudGVyQ291bnRlciA9IDA7XG4gICAgICAgIFxuICAgICAgICBpZiAoY3VycmVudERyb3BUYXJnZXQpIHtcbiAgICAgICAgICAgIGN1cnJlbnREcm9wVGFyZ2V0LmNsYXNzTGlzdC5yZW1vdmUoRFJPUF9UQVJHRVRfQUNUSVZFX0NMQVNTKTtcbiAgICAgICAgICAgIGN1cnJlbnREcm9wVGFyZ2V0ID0gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE9uIFdpbmRvd3MsIGhhbmRsZSBmaWxlIGRyb3BzIHZpYSBKYXZhU2NyaXB0XG4gICAgICAgIC8vIE9uIG1hY09TL0xpbnV4LCBuYXRpdmUgY29kZSB3aWxsIGNhbGwgSGFuZGxlUGxhdGZvcm1GaWxlRHJvcFxuICAgICAgICBpZiAoY2FuUmVzb2x2ZUZpbGVQYXRocygpKSB7XG4gICAgICAgICAgICBjb25zdCBmaWxlczogRmlsZVtdID0gW107XG4gICAgICAgICAgICBpZiAoZXZlbnQuZGF0YVRyYW5zZmVyLml0ZW1zKSB7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBpdGVtIG9mIGV2ZW50LmRhdGFUcmFuc2Zlci5pdGVtcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXRlbS5raW5kID09PSAnZmlsZScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZpbGUgPSBpdGVtLmdldEFzRmlsZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZpbGUpIGZpbGVzLnB1c2goZmlsZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGV2ZW50LmRhdGFUcmFuc2Zlci5maWxlcykge1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZmlsZSBvZiBldmVudC5kYXRhVHJhbnNmZXIuZmlsZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgZmlsZXMucHVzaChmaWxlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGlmIChmaWxlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZUZpbGVQYXRocyhldmVudC5jbGllbnRYLCBldmVudC5jbGllbnRZLCBmaWxlcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LCBmYWxzZSk7XG59XG5cbi8vIEluaXRpYWxpemUgbGlzdGVuZXJzIHdoZW4gdGhlIHNjcmlwdCBsb2Fkc1xuaWYgKHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgJiYgdHlwZW9mIGRvY3VtZW50ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgc2V0dXBEcm9wVGFyZ2V0TGlzdGVuZXJzKCk7XG59XG5cbmV4cG9ydCBkZWZhdWx0IHRoaXNXaW5kb3c7XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbmltcG9ydCAqIGFzIFJ1bnRpbWUgZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjXCI7XG5cbi8vIE5PVEU6IHRoZSBmb2xsb3dpbmcgbWV0aG9kcyBNVVNUIGJlIGltcG9ydGVkIGV4cGxpY2l0bHkgYmVjYXVzZSBvZiBob3cgZXNidWlsZCBpbmplY3Rpb24gd29ya3NcbmltcG9ydCB7IEVuYWJsZSBhcyBFbmFibGVXTUwgfSBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvd21sXCI7XG5pbXBvcnQgeyBkZWJ1Z0xvZyB9IGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyYy91dGlsc1wiO1xuXG53aW5kb3cud2FpbHMgPSBSdW50aW1lO1xuRW5hYmxlV01MKCk7XG5cbmlmIChERUJVRykge1xuICAgIGRlYnVnTG9nKFwiV2FpbHMgUnVudGltZSBMb2FkZWRcIilcbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuaW1wb3J0IHsgbmV3UnVudGltZUNhbGxlciwgb2JqZWN0TmFtZXMgfSBmcm9tIFwiLi9ydW50aW1lLmpzXCI7XG5cbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyKG9iamVjdE5hbWVzLlN5c3RlbSk7XG5cbmNvbnN0IFN5c3RlbUlzRGFya01vZGUgPSAwO1xuY29uc3QgU3lzdGVtRW52aXJvbm1lbnQgPSAxO1xuY29uc3QgU3lzdGVtQ2FwYWJpbGl0aWVzID0gMjtcblxuY29uc3QgX2ludm9rZSA9IChmdW5jdGlvbiAoKSB7XG4gICAgdHJ5IHtcbiAgICAgICAgLy8gV2luZG93cyBXZWJWaWV3MlxuICAgICAgICBpZiAoKHdpbmRvdyBhcyBhbnkpLmNocm9tZT8ud2Vidmlldz8ucG9zdE1lc3NhZ2UpIHtcbiAgICAgICAgICAgIHJldHVybiAod2luZG93IGFzIGFueSkuY2hyb21lLndlYnZpZXcucG9zdE1lc3NhZ2UuYmluZCgod2luZG93IGFzIGFueSkuY2hyb21lLndlYnZpZXcpO1xuICAgICAgICB9XG4gICAgICAgIC8vIG1hY09TL2lPUyBXS1dlYlZpZXdcbiAgICAgICAgZWxzZSBpZiAoKHdpbmRvdyBhcyBhbnkpLndlYmtpdD8ubWVzc2FnZUhhbmRsZXJzPy5bJ2V4dGVybmFsJ10/LnBvc3RNZXNzYWdlKSB7XG4gICAgICAgICAgICByZXR1cm4gKHdpbmRvdyBhcyBhbnkpLndlYmtpdC5tZXNzYWdlSGFuZGxlcnNbJ2V4dGVybmFsJ10ucG9zdE1lc3NhZ2UuYmluZCgod2luZG93IGFzIGFueSkud2Via2l0Lm1lc3NhZ2VIYW5kbGVyc1snZXh0ZXJuYWwnXSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQW5kcm9pZCBXZWJWaWV3IC0gdXNlcyBhZGRKYXZhc2NyaXB0SW50ZXJmYWNlIHdoaWNoIGV4cG9zZXMgd2luZG93LndhaWxzLmludm9rZVxuICAgICAgICBlbHNlIGlmICgod2luZG93IGFzIGFueSkud2FpbHM/Lmludm9rZSkge1xuICAgICAgICAgICAgcmV0dXJuIChtc2c6IGFueSkgPT4gKHdpbmRvdyBhcyBhbnkpLndhaWxzLmludm9rZSh0eXBlb2YgbXNnID09PSAnc3RyaW5nJyA/IG1zZyA6IEpTT04uc3RyaW5naWZ5KG1zZykpO1xuICAgICAgICB9XG4gICAgfSBjYXRjaChlKSB7fVxuXG4gICAgY29uc29sZS53YXJuKCdcXG4lY1x1MjZBMFx1RkUwRiBCcm93c2VyIEVudmlyb25tZW50IERldGVjdGVkICVjXFxuXFxuJWNPbmx5IFVJIHByZXZpZXdzIGFyZSBhdmFpbGFibGUgaW4gdGhlIGJyb3dzZXIuIEZvciBmdWxsIGZ1bmN0aW9uYWxpdHksIHBsZWFzZSBydW4gdGhlIGFwcGxpY2F0aW9uIGluIGRlc2t0b3AgbW9kZS5cXG5Nb3JlIGluZm9ybWF0aW9uIGF0OiBodHRwczovL3YzLndhaWxzLmlvL2xlYXJuL2J1aWxkLyN1c2luZy1hLWJyb3dzZXItZm9yLWRldmVsb3BtZW50XFxuJyxcbiAgICAgICAgJ2JhY2tncm91bmQ6ICNmZmZmZmY7IGNvbG9yOiAjMDAwMDAwOyBmb250LXdlaWdodDogYm9sZDsgcGFkZGluZzogNHB4IDhweDsgYm9yZGVyLXJhZGl1czogNHB4OyBib3JkZXI6IDJweCBzb2xpZCAjMDAwMDAwOycsXG4gICAgICAgICdiYWNrZ3JvdW5kOiB0cmFuc3BhcmVudDsnLFxuICAgICAgICAnY29sb3I6ICNmZmZmZmY7IGZvbnQtc3R5bGU6IGl0YWxpYzsgZm9udC13ZWlnaHQ6IGJvbGQ7Jyk7XG4gICAgcmV0dXJuIG51bGw7XG59KSgpO1xuXG5leHBvcnQgZnVuY3Rpb24gaW52b2tlKG1zZzogYW55KTogdm9pZCB7XG4gICAgX2ludm9rZT8uKG1zZyk7XG59XG5cbi8qKlxuICogUmV0cmlldmVzIHRoZSBzeXN0ZW0gZGFyayBtb2RlIHN0YXR1cy5cbiAqXG4gKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhIGJvb2xlYW4gdmFsdWUgaW5kaWNhdGluZyBpZiB0aGUgc3lzdGVtIGlzIGluIGRhcmsgbW9kZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzRGFya01vZGUoKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIGNhbGwoU3lzdGVtSXNEYXJrTW9kZSk7XG59XG5cbi8qKlxuICogRmV0Y2hlcyB0aGUgY2FwYWJpbGl0aWVzIG9mIHRoZSBhcHBsaWNhdGlvbiBmcm9tIHRoZSBzZXJ2ZXIuXG4gKlxuICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIGNhcGFiaWxpdGllcy5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIENhcGFiaWxpdGllcygpOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+IHtcbiAgICByZXR1cm4gY2FsbChTeXN0ZW1DYXBhYmlsaXRpZXMpO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE9TSW5mbyB7XG4gICAgLyoqIFRoZSBicmFuZGluZyBvZiB0aGUgT1MuICovXG4gICAgQnJhbmRpbmc6IHN0cmluZztcbiAgICAvKiogVGhlIElEIG9mIHRoZSBPUy4gKi9cbiAgICBJRDogc3RyaW5nO1xuICAgIC8qKiBUaGUgbmFtZSBvZiB0aGUgT1MuICovXG4gICAgTmFtZTogc3RyaW5nO1xuICAgIC8qKiBUaGUgdmVyc2lvbiBvZiB0aGUgT1MuICovXG4gICAgVmVyc2lvbjogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEVudmlyb25tZW50SW5mbyB7XG4gICAgLyoqIFRoZSBhcmNoaXRlY3R1cmUgb2YgdGhlIHN5c3RlbS4gKi9cbiAgICBBcmNoOiBzdHJpbmc7XG4gICAgLyoqIFRydWUgaWYgdGhlIGFwcGxpY2F0aW9uIGlzIHJ1bm5pbmcgaW4gZGVidWcgbW9kZSwgb3RoZXJ3aXNlIGZhbHNlLiAqL1xuICAgIERlYnVnOiBib29sZWFuO1xuICAgIC8qKiBUaGUgb3BlcmF0aW5nIHN5c3RlbSBpbiB1c2UuICovXG4gICAgT1M6IHN0cmluZztcbiAgICAvKiogRGV0YWlscyBvZiB0aGUgb3BlcmF0aW5nIHN5c3RlbS4gKi9cbiAgICBPU0luZm86IE9TSW5mbztcbiAgICAvKiogQWRkaXRpb25hbCBwbGF0Zm9ybSBpbmZvcm1hdGlvbi4gKi9cbiAgICBQbGF0Zm9ybUluZm86IFJlY29yZDxzdHJpbmcsIGFueT47XG59XG5cbi8qKlxuICogUmV0cmlldmVzIGVudmlyb25tZW50IGRldGFpbHMuXG4gKlxuICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gb2JqZWN0IGNvbnRhaW5pbmcgT1MgYW5kIHN5c3RlbSBhcmNoaXRlY3R1cmUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFbnZpcm9ubWVudCgpOiBQcm9taXNlPEVudmlyb25tZW50SW5mbz4ge1xuICAgIHJldHVybiBjYWxsKFN5c3RlbUVudmlyb25tZW50KTtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgdGhlIGN1cnJlbnQgb3BlcmF0aW5nIHN5c3RlbSBpcyBXaW5kb3dzLlxuICpcbiAqIEByZXR1cm4gVHJ1ZSBpZiB0aGUgb3BlcmF0aW5nIHN5c3RlbSBpcyBXaW5kb3dzLCBvdGhlcndpc2UgZmFsc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJc1dpbmRvd3MoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICh3aW5kb3cgYXMgYW55KS5fd2FpbHM/LmVudmlyb25tZW50Py5PUyA9PT0gXCJ3aW5kb3dzXCI7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IG9wZXJhdGluZyBzeXN0ZW0gaXMgTGludXguXG4gKlxuICogQHJldHVybnMgUmV0dXJucyB0cnVlIGlmIHRoZSBjdXJyZW50IG9wZXJhdGluZyBzeXN0ZW0gaXMgTGludXgsIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzTGludXgoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICh3aW5kb3cgYXMgYW55KS5fd2FpbHM/LmVudmlyb25tZW50Py5PUyA9PT0gXCJsaW51eFwiO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiB0aGUgY3VycmVudCBlbnZpcm9ubWVudCBpcyBhIG1hY09TIG9wZXJhdGluZyBzeXN0ZW0uXG4gKlxuICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgZW52aXJvbm1lbnQgaXMgbWFjT1MsIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzTWFjKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAod2luZG93IGFzIGFueSkuX3dhaWxzPy5lbnZpcm9ubWVudD8uT1MgPT09IFwiZGFyd2luXCI7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IG9wZXJhdGluZyBzeXN0ZW0gaXMgaU9TLlxuICpcbiAqIEByZXR1cm5zIFRydWUgaWYgdGhlIG9wZXJhdGluZyBzeXN0ZW0gaXMgaU9TLCBvdGhlcndpc2UgZmFsc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJc0lPUygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gKHdpbmRvdyBhcyBhbnkpLl93YWlscz8uZW52aXJvbm1lbnQ/Lk9TID09PSBcImlvc1wiO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiB0aGUgY3VycmVudCBvcGVyYXRpbmcgc3lzdGVtIGlzIEFuZHJvaWQuXG4gKlxuICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgb3BlcmF0aW5nIHN5c3RlbSBpcyBBbmRyb2lkLCBvdGhlcndpc2UgZmFsc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJc0FuZHJvaWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICh3aW5kb3cgYXMgYW55KS5fd2FpbHM/LmVudmlyb25tZW50Py5PUyA9PT0gXCJhbmRyb2lkXCI7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBhcHAgaXMgcnVubmluZyBvbiBhIG1vYmlsZSBPUyAoaU9TIG9yIEFuZHJvaWQpLlxuICpcbiAqIEByZXR1cm5zIFRydWUgb24gaU9TIG9yIEFuZHJvaWQsIG90aGVyd2lzZSBmYWxzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzTW9iaWxlKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBJc0lPUygpIHx8IElzQW5kcm9pZCgpO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiB0aGUgYXBwIGlzIHJ1bm5pbmcgb24gYSBkZXNrdG9wIE9TIChtYWNPUywgV2luZG93cyBvciBMaW51eCkuXG4gKlxuICogQHJldHVybnMgVHJ1ZSBvbiBtYWNPUywgV2luZG93cyBvciBMaW51eCwgb3RoZXJ3aXNlIGZhbHNlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gSXNEZXNrdG9wKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBJc01hYygpIHx8IElzV2luZG93cygpIHx8IElzTGludXgoKTtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgdGhlIGN1cnJlbnQgZW52aXJvbm1lbnQgYXJjaGl0ZWN0dXJlIGlzIEFNRDY0LlxuICpcbiAqIEByZXR1cm5zIFRydWUgaWYgdGhlIGN1cnJlbnQgZW52aXJvbm1lbnQgYXJjaGl0ZWN0dXJlIGlzIEFNRDY0LCBmYWxzZSBvdGhlcndpc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJc0FNRDY0KCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAod2luZG93IGFzIGFueSkuX3dhaWxzPy5lbnZpcm9ubWVudD8uQXJjaCA9PT0gXCJhbWQ2NFwiO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiB0aGUgY3VycmVudCBhcmNoaXRlY3R1cmUgaXMgQVJNLlxuICpcbiAqIEByZXR1cm5zIFRydWUgaWYgdGhlIGN1cnJlbnQgYXJjaGl0ZWN0dXJlIGlzIEFSTSwgZmFsc2Ugb3RoZXJ3aXNlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gSXNBUk0oKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICh3aW5kb3cgYXMgYW55KS5fd2FpbHM/LmVudmlyb25tZW50Py5BcmNoID09PSBcImFybVwiO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiB0aGUgY3VycmVudCBlbnZpcm9ubWVudCBpcyBBUk02NCBhcmNoaXRlY3R1cmUuXG4gKlxuICogQHJldHVybnMgUmV0dXJucyB0cnVlIGlmIHRoZSBlbnZpcm9ubWVudCBpcyBBUk02NCBhcmNoaXRlY3R1cmUsIG90aGVyd2lzZSByZXR1cm5zIGZhbHNlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gSXNBUk02NCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gKHdpbmRvdyBhcyBhbnkpLl93YWlscz8uZW52aXJvbm1lbnQ/LkFyY2ggPT09IFwiYXJtNjRcIjtcbn1cblxuLyoqXG4gKiBSZXBvcnRzIHdoZXRoZXIgdGhlIGFwcCBpcyBiZWluZyBydW4gaW4gZGVidWcgbW9kZS5cbiAqXG4gKiBAcmV0dXJucyBUcnVlIGlmIHRoZSBhcHAgaXMgYmVpbmcgcnVuIGluIGRlYnVnIG1vZGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJc0RlYnVnKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBCb29sZWFuKCh3aW5kb3cgYXMgYW55KS5fd2FpbHM/LmVudmlyb25tZW50Py5EZWJ1Zyk7XG59XG5cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuaW1wb3J0IHsgbmV3UnVudGltZUNhbGxlciwgb2JqZWN0TmFtZXMgfSBmcm9tIFwiLi9ydW50aW1lLmpzXCI7XG5pbXBvcnQgeyBJc0RlYnVnIH0gZnJvbSBcIi4vc3lzdGVtLmpzXCI7XG5pbXBvcnQgeyBldmVudFRhcmdldCB9IGZyb20gXCIuL3V0aWxzLmpzXCI7XG5cbi8vIHNldHVwXG5pbXBvcnQgeyBoYXNET00gfSBmcm9tIFwiLi9lbnZpcm9ubWVudC5qc1wiO1xuXG5pZiAoaGFzRE9NKSB7XG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2NvbnRleHRtZW51JywgY29udGV4dE1lbnVIYW5kbGVyKTtcbn1cblxuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXIob2JqZWN0TmFtZXMuQ29udGV4dE1lbnUpO1xuXG5jb25zdCBDb250ZXh0TWVudU9wZW4gPSAwO1xuXG5mdW5jdGlvbiBvcGVuQ29udGV4dE1lbnUoaWQ6IHN0cmluZywgeDogbnVtYmVyLCB5OiBudW1iZXIsIGRhdGE6IGFueSk6IHZvaWQge1xuICAgIHZvaWQgY2FsbChDb250ZXh0TWVudU9wZW4sIHtpZCwgeCwgeSwgZGF0YX0pO1xufVxuXG5mdW5jdGlvbiBjb250ZXh0TWVudUhhbmRsZXIoZXZlbnQ6IE1vdXNlRXZlbnQpIHtcbiAgICBjb25zdCB0YXJnZXQgPSBldmVudFRhcmdldChldmVudCk7XG5cbiAgICAvLyBDaGVjayBmb3IgY3VzdG9tIGNvbnRleHQgbWVudVxuICAgIGNvbnN0IGN1c3RvbUNvbnRleHRNZW51ID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUodGFyZ2V0KS5nZXRQcm9wZXJ0eVZhbHVlKFwiLS1jdXN0b20tY29udGV4dG1lbnVcIikudHJpbSgpO1xuXG4gICAgaWYgKGN1c3RvbUNvbnRleHRNZW51KSB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGNvbnN0IGRhdGEgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZSh0YXJnZXQpLmdldFByb3BlcnR5VmFsdWUoXCItLWN1c3RvbS1jb250ZXh0bWVudS1kYXRhXCIpO1xuICAgICAgICBvcGVuQ29udGV4dE1lbnUoY3VzdG9tQ29udGV4dE1lbnUsIGV2ZW50LmNsaWVudFgsIGV2ZW50LmNsaWVudFksIGRhdGEpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHByb2Nlc3NEZWZhdWx0Q29udGV4dE1lbnUoZXZlbnQsIHRhcmdldCk7XG4gICAgfVxufVxuXG5cbi8qXG4tLWRlZmF1bHQtY29udGV4dG1lbnU6IGF1dG87IChkZWZhdWx0KSB3aWxsIHNob3cgdGhlIGRlZmF1bHQgY29udGV4dCBtZW51IGlmIGNvbnRlbnRFZGl0YWJsZSBpcyB0cnVlIE9SIHRleHQgaGFzIGJlZW4gc2VsZWN0ZWQgT1IgZWxlbWVudCBpcyBpbnB1dCBvciB0ZXh0YXJlYVxuLS1kZWZhdWx0LWNvbnRleHRtZW51OiBzaG93OyB3aWxsIGFsd2F5cyBzaG93IHRoZSBkZWZhdWx0IGNvbnRleHQgbWVudVxuLS1kZWZhdWx0LWNvbnRleHRtZW51OiBoaWRlOyB3aWxsIGFsd2F5cyBoaWRlIHRoZSBkZWZhdWx0IGNvbnRleHQgbWVudVxuXG5UaGlzIHJ1bGUgaXMgaW5oZXJpdGVkIGxpa2Ugbm9ybWFsIENTUyBydWxlcywgc28gbmVzdGluZyB3b3JrcyBhcyBleHBlY3RlZFxuKi9cbmZ1bmN0aW9uIHByb2Nlc3NEZWZhdWx0Q29udGV4dE1lbnUoZXZlbnQ6IE1vdXNlRXZlbnQsIHRhcmdldDogSFRNTEVsZW1lbnQpIHtcbiAgICAvLyBEZWJ1ZyBidWlsZHMgYWx3YXlzIHNob3cgdGhlIG1lbnVcbiAgICBpZiAoSXNEZWJ1ZygpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBQcm9jZXNzIGRlZmF1bHQgY29udGV4dCBtZW51XG4gICAgc3dpdGNoICh3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZSh0YXJnZXQpLmdldFByb3BlcnR5VmFsdWUoXCItLWRlZmF1bHQtY29udGV4dG1lbnVcIikudHJpbSgpKSB7XG4gICAgICAgIGNhc2UgJ3Nob3cnOlxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBjYXNlICdoaWRlJzpcbiAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgaWYgY29udGVudEVkaXRhYmxlIGlzIHRydWVcbiAgICBpZiAodGFyZ2V0LmlzQ29udGVudEVkaXRhYmxlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBDaGVjayBpZiB0ZXh0IGhhcyBiZWVuIHNlbGVjdGVkXG4gICAgY29uc3Qgc2VsZWN0aW9uID0gd2luZG93LmdldFNlbGVjdGlvbigpO1xuICAgIGNvbnN0IGhhc1NlbGVjdGlvbiA9IHNlbGVjdGlvbiAmJiBzZWxlY3Rpb24udG9TdHJpbmcoKS5sZW5ndGggPiAwO1xuICAgIGlmIChoYXNTZWxlY3Rpb24pIHtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZWxlY3Rpb24ucmFuZ2VDb3VudDsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCByYW5nZSA9IHNlbGVjdGlvbi5nZXRSYW5nZUF0KGkpO1xuICAgICAgICAgICAgY29uc3QgcmVjdHMgPSByYW5nZS5nZXRDbGllbnRSZWN0cygpO1xuICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCByZWN0cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlY3QgPSByZWN0c1tqXTtcbiAgICAgICAgICAgICAgICBpZiAoZG9jdW1lbnQuZWxlbWVudEZyb21Qb2ludChyZWN0LmxlZnQsIHJlY3QudG9wKSA9PT0gdGFyZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBDaGVjayBpZiB0YWcgaXMgaW5wdXQgb3IgdGV4dGFyZWEuXG4gICAgaWYgKHRhcmdldCBpbnN0YW5jZW9mIEhUTUxJbnB1dEVsZW1lbnQgfHwgdGFyZ2V0IGluc3RhbmNlb2YgSFRNTFRleHRBcmVhRWxlbWVudCkge1xuICAgICAgICBpZiAoaGFzU2VsZWN0aW9uIHx8ICghdGFyZ2V0LnJlYWRPbmx5ICYmICF0YXJnZXQuZGlzYWJsZWQpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBoaWRlIGRlZmF1bHQgY29udGV4dCBtZW51XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoqXG4gKiBSZXRyaWV2ZXMgdGhlIHZhbHVlIGFzc29jaWF0ZWQgd2l0aCB0aGUgc3BlY2lmaWVkIGtleSBmcm9tIHRoZSBmbGFnIG1hcC5cbiAqXG4gKiBAcGFyYW0ga2V5IC0gVGhlIGtleSB0byByZXRyaWV2ZSB0aGUgdmFsdWUgZm9yLlxuICogQHJldHVybiBUaGUgdmFsdWUgYXNzb2NpYXRlZCB3aXRoIHRoZSBzcGVjaWZpZWQga2V5LlxuICovXG5leHBvcnQgZnVuY3Rpb24gR2V0RmxhZyhrZXk6IHN0cmluZyk6IGFueSB7XG4gICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIHdpbmRvdy5fd2FpbHMuZmxhZ3Nba2V5XTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIlVuYWJsZSB0byByZXRyaWV2ZSBmbGFnICdcIiArIGtleSArIFwiJzogXCIgKyBlLCB7IGNhdXNlOiBlIH0pO1xuICAgIH1cbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuaW1wb3J0IHsgaW52b2tlLCBJc1dpbmRvd3MsIElzTGludXggfSBmcm9tIFwiLi9zeXN0ZW0uanNcIjtcbmltcG9ydCB7IEdldEZsYWcgfSBmcm9tIFwiLi9mbGFncy5qc1wiO1xuaW1wb3J0IHsgY2FuVHJhY2tCdXR0b25zLCBldmVudFRhcmdldCB9IGZyb20gXCIuL3V0aWxzLmpzXCI7XG5cbi8vIFNldHVwXG5sZXQgY2FuRHJhZyA9IGZhbHNlO1xubGV0IGRyYWdnaW5nID0gZmFsc2U7XG5cbmxldCByZXNpemFibGUgPSBmYWxzZTtcbmxldCBjYW5SZXNpemUgPSBmYWxzZTtcbmxldCByZXNpemluZyA9IGZhbHNlO1xubGV0IHJlc2l6ZUVkZ2U6IHN0cmluZyA9IFwiXCI7XG5sZXQgZGVmYXVsdEN1cnNvciA9IFwiYXV0b1wiO1xuXG5sZXQgYnV0dG9ucyA9IDA7XG5pbXBvcnQgeyBoYXNET00gfSBmcm9tIFwiLi9lbnZpcm9ubWVudC5qc1wiO1xuXG5sZXQgYnV0dG9uc1RyYWNrZWQgPSBmYWxzZTtcblxuaWYgKGhhc0RPTSkge1xuICAgIGJ1dHRvbnNUcmFja2VkID0gY2FuVHJhY2tCdXR0b25zKCk7XG4gICAgd2luZG93Ll93YWlscyA9IHdpbmRvdy5fd2FpbHMgfHwge307XG4gICAgd2luZG93Ll93YWlscy5zZXRSZXNpemFibGUgPSAodmFsdWU6IGJvb2xlYW4pOiB2b2lkID0+IHtcbiAgICAgICAgcmVzaXphYmxlID0gdmFsdWU7XG4gICAgICAgIGlmICghcmVzaXphYmxlKSB7XG4gICAgICAgICAgICAvLyBTdG9wIHJlc2l6aW5nIGlmIGluIHByb2dyZXNzLlxuICAgICAgICAgICAgY2FuUmVzaXplID0gcmVzaXppbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIHNldFJlc2l6ZSgpO1xuICAgICAgICB9XG4gICAgfTtcbn1cblxuLy8gRGVmZXIgYXR0YWNoaW5nIG1vdXNlIGxpc3RlbmVycyB1bnRpbCB3ZSBrbm93IHdlJ3JlIG5vdCBvbiBtb2JpbGUuXG5sZXQgZHJhZ0luaXREb25lID0gZmFsc2U7XG5mdW5jdGlvbiBpc01vYmlsZSgpOiBib29sZWFuIHtcbiAgICBjb25zdCBvcyA9ICh3aW5kb3cgYXMgYW55KS5fd2FpbHM/LmVudmlyb25tZW50Py5PUztcbiAgICBpZiAob3MgPT09IFwiaW9zXCIgfHwgb3MgPT09IFwiYW5kcm9pZFwiKSByZXR1cm4gdHJ1ZTtcbiAgICAvLyBGYWxsYmFjayBoZXVyaXN0aWMgaWYgZW52aXJvbm1lbnQgbm90IHlldCBzZXRcbiAgICBjb25zdCB1YSA9IG5hdmlnYXRvci51c2VyQWdlbnQgfHwgbmF2aWdhdG9yLnZlbmRvciB8fCAod2luZG93IGFzIGFueSkub3BlcmEgfHwgXCJcIjtcbiAgICByZXR1cm4gL2FuZHJvaWR8aXBob25lfGlwYWR8aXBvZHxpZW1vYmlsZXx3cGRlc2t0b3AvaS50ZXN0KHVhKTtcbn1cbmZ1bmN0aW9uIHRyeUluaXREcmFnSGFuZGxlcnMoKTogdm9pZCB7XG4gICAgaWYgKGRyYWdJbml0RG9uZSkgcmV0dXJuO1xuICAgIGlmIChpc01vYmlsZSgpKSByZXR1cm47XG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIHVwZGF0ZSwgeyBjYXB0dXJlOiB0cnVlIH0pO1xuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCB1cGRhdGUsIHsgY2FwdHVyZTogdHJ1ZSB9KTtcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIHVwZGF0ZSwgeyBjYXB0dXJlOiB0cnVlIH0pO1xuICAgIGZvciAoY29uc3QgZXYgb2YgWydjbGljaycsICdjb250ZXh0bWVudScsICdkYmxjbGljayddKSB7XG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKGV2LCBzdXBwcmVzc0V2ZW50LCB7IGNhcHR1cmU6IHRydWUgfSk7XG4gICAgfVxuICAgIGRyYWdJbml0RG9uZSA9IHRydWU7XG59XG5pZiAoaGFzRE9NKSB7XG4gICAgLy8gQXR0ZW1wdCBpbW1lZGlhdGUgaW5pdCAoaW4gY2FzZSBlbnZpcm9ubWVudCBhbHJlYWR5IHByZXNlbnQpXG4gICAgdHJ5SW5pdERyYWdIYW5kbGVycygpO1xuICAgIC8vIEFsc28gYXR0ZW1wdCBvbiBET00gcmVhZHlcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJywgdHJ5SW5pdERyYWdIYW5kbGVycywgeyBvbmNlOiB0cnVlIH0pO1xuICAgIC8vIEFzIGEgbGFzdCByZXNvcnQsIHBvbGwgZm9yIGVudmlyb25tZW50IGZvciBhIHNob3J0IHBlcmlvZFxuICAgIGxldCBkcmFnRW52UG9sbHMgPSAwO1xuICAgIGNvbnN0IGRyYWdFbnZQb2xsID0gd2luZG93LnNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgaWYgKGRyYWdJbml0RG9uZSkgeyB3aW5kb3cuY2xlYXJJbnRlcnZhbChkcmFnRW52UG9sbCk7IHJldHVybjsgfVxuICAgICAgICB0cnlJbml0RHJhZ0hhbmRsZXJzKCk7XG4gICAgICAgIGlmICgrK2RyYWdFbnZQb2xscyA+IDEwMCkgeyB3aW5kb3cuY2xlYXJJbnRlcnZhbChkcmFnRW52UG9sbCk7IH1cbiAgICB9LCA1MCk7XG59XG5cbmZ1bmN0aW9uIHN1cHByZXNzRXZlbnQoZXZlbnQ6IEV2ZW50KSB7XG4gICAgLy8gU3VwcHJlc3MgY2xpY2sgZXZlbnRzIHdoaWxlIHJlc2l6aW5nIG9yIGRyYWdnaW5nLlxuICAgIGlmIChkcmFnZ2luZyB8fCByZXNpemluZykge1xuICAgICAgICBldmVudC5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcbiAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgfVxufVxuXG4vLyBVc2UgY29uc3RhbnRzIHRvIGF2b2lkIGNvbXBhcmluZyBzdHJpbmdzIG11bHRpcGxlIHRpbWVzLlxuY29uc3QgTW91c2VEb3duID0gMDtcbmNvbnN0IE1vdXNlVXAgICA9IDE7XG5jb25zdCBNb3VzZU1vdmUgPSAyO1xuXG5mdW5jdGlvbiB1cGRhdGUoZXZlbnQ6IE1vdXNlRXZlbnQpIHtcbiAgICAvLyBXaW5kb3dzIHN1cHByZXNzZXMgbW91c2UgZXZlbnRzIGF0IHRoZSBlbmQgb2YgZHJhZ2dpbmcgb3IgcmVzaXppbmcsXG4gICAgLy8gc28gd2UgbmVlZCB0byBiZSBzbWFydCBhbmQgc3ludGhlc2l6ZSBidXR0b24gZXZlbnRzLlxuXG4gICAgbGV0IGV2ZW50VHlwZTogbnVtYmVyLCBldmVudEJ1dHRvbnMgPSBldmVudC5idXR0b25zO1xuICAgIHN3aXRjaCAoZXZlbnQudHlwZSkge1xuICAgICAgICBjYXNlICdtb3VzZWRvd24nOlxuICAgICAgICAgICAgZXZlbnRUeXBlID0gTW91c2VEb3duO1xuICAgICAgICAgICAgaWYgKCFidXR0b25zVHJhY2tlZCkgeyBldmVudEJ1dHRvbnMgPSBidXR0b25zIHwgKDEgPDwgZXZlbnQuYnV0dG9uKTsgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ21vdXNldXAnOlxuICAgICAgICAgICAgZXZlbnRUeXBlID0gTW91c2VVcDtcbiAgICAgICAgICAgIGlmICghYnV0dG9uc1RyYWNrZWQpIHsgZXZlbnRCdXR0b25zID0gYnV0dG9ucyAmIH4oMSA8PCBldmVudC5idXR0b24pOyB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIGV2ZW50VHlwZSA9IE1vdXNlTW92ZTtcbiAgICAgICAgICAgIGlmICghYnV0dG9uc1RyYWNrZWQpIHsgZXZlbnRCdXR0b25zID0gYnV0dG9uczsgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgbGV0IHJlbGVhc2VkID0gYnV0dG9ucyAmIH5ldmVudEJ1dHRvbnM7XG4gICAgbGV0IHByZXNzZWQgPSBldmVudEJ1dHRvbnMgJiB+YnV0dG9ucztcblxuICAgIGJ1dHRvbnMgPSBldmVudEJ1dHRvbnM7XG5cbiAgICAvLyBTeW50aGVzaXplIGEgcmVsZWFzZS1wcmVzcyBzZXF1ZW5jZSBpZiB3ZSBkZXRlY3QgYSBwcmVzcyBvZiBhbiBhbHJlYWR5IHByZXNzZWQgYnV0dG9uLlxuICAgIGlmIChldmVudFR5cGUgPT09IE1vdXNlRG93biAmJiAhKHByZXNzZWQgJiBldmVudC5idXR0b24pKSB7XG4gICAgICAgIHJlbGVhc2VkIHw9ICgxIDw8IGV2ZW50LmJ1dHRvbik7XG4gICAgICAgIHByZXNzZWQgfD0gKDEgPDwgZXZlbnQuYnV0dG9uKTtcbiAgICB9XG5cbiAgICAvLyBTdXBwcmVzcyBhbGwgYnV0dG9uIGV2ZW50cyBkdXJpbmcgZHJhZ2dpbmcgYW5kIHJlc2l6aW5nLFxuICAgIC8vIHVubGVzcyB0aGlzIGlzIGEgbW91c2V1cCBldmVudCB0aGF0IGlzIGVuZGluZyBhIGRyYWcgYWN0aW9uLlxuICAgIGlmIChcbiAgICAgICAgZXZlbnRUeXBlICE9PSBNb3VzZU1vdmUgLy8gRmFzdCBwYXRoIGZvciBtb3VzZW1vdmVcbiAgICAgICAgJiYgcmVzaXppbmdcbiAgICAgICAgfHwgKFxuICAgICAgICAgICAgZHJhZ2dpbmdcbiAgICAgICAgICAgICYmIChcbiAgICAgICAgICAgICAgICBldmVudFR5cGUgPT09IE1vdXNlRG93blxuICAgICAgICAgICAgICAgIHx8IGV2ZW50LmJ1dHRvbiAhPT0gMFxuICAgICAgICAgICAgKVxuICAgICAgICApXG4gICAgKSB7XG4gICAgICAgIGV2ZW50LnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xuICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG5cbiAgICAvLyBIYW5kbGUgcmVsZWFzZXNcbiAgICBpZiAocmVsZWFzZWQgJiAxKSB7IHByaW1hcnlVcChldmVudCk7IH1cbiAgICAvLyBIYW5kbGUgcHJlc3Nlc1xuICAgIGlmIChwcmVzc2VkICYgMSkgeyBwcmltYXJ5RG93bihldmVudCk7IH1cblxuICAgIC8vIEhhbmRsZSBtb3VzZW1vdmVcbiAgICBpZiAoZXZlbnRUeXBlID09PSBNb3VzZU1vdmUpIHsgb25Nb3VzZU1vdmUoZXZlbnQpOyB9O1xufVxuXG5mdW5jdGlvbiBwcmltYXJ5RG93bihldmVudDogTW91c2VFdmVudCk6IHZvaWQge1xuICAgIC8vIFJlc2V0IHJlYWRpbmVzcyBzdGF0ZS5cbiAgICBjYW5EcmFnID0gZmFsc2U7XG4gICAgY2FuUmVzaXplID0gZmFsc2U7XG5cbiAgICAvLyBJZ25vcmUgcmVwZWF0ZWQgY2xpY2tzIG9uIG1hY09TIGFuZCBMaW51eC5cbiAgICBpZiAoIUlzV2luZG93cygpKSB7XG4gICAgICAgIGlmIChldmVudC50eXBlID09PSAnbW91c2Vkb3duJyAmJiBldmVudC5idXR0b24gPT09IDAgJiYgZXZlbnQuZGV0YWlsICE9PSAxKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAocmVzaXplRWRnZSkge1xuICAgICAgICAvLyBSZWFkeSB0byByZXNpemUgaWYgdGhlIHByaW1hcnkgYnV0dG9uIHdhcyBwcmVzc2VkIGZvciB0aGUgZmlyc3QgdGltZS5cbiAgICAgICAgY2FuUmVzaXplID0gdHJ1ZTtcbiAgICAgICAgLy8gRG8gbm90IHN0YXJ0IGRyYWcgb3BlcmF0aW9ucyB3aGVuIG9uIHJlc2l6ZSBlZGdlcy5cbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFJldHJpZXZlIHRhcmdldCBlbGVtZW50XG4gICAgY29uc3QgdGFyZ2V0ID0gZXZlbnRUYXJnZXQoZXZlbnQpO1xuXG4gICAgLy8gUmVhZHkgdG8gZHJhZyBpZiB0aGUgcHJpbWFyeSBidXR0b24gd2FzIHByZXNzZWQgZm9yIHRoZSBmaXJzdCB0aW1lIG9uIGEgZHJhZ2dhYmxlIGVsZW1lbnQuXG4gICAgLy8gSWdub3JlIGNsaWNrcyBvbiB0aGUgc2Nyb2xsYmFyLlxuICAgIGNvbnN0IHN0eWxlID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUodGFyZ2V0KTtcbiAgICBjYW5EcmFnID0gKFxuICAgICAgICBzdHlsZS5nZXRQcm9wZXJ0eVZhbHVlKFwiLS13YWlscy1kcmFnZ2FibGVcIikudHJpbSgpID09PSBcImRyYWdcIlxuICAgICAgICAmJiAoXG4gICAgICAgICAgICBldmVudC5vZmZzZXRYIC0gcGFyc2VGbG9hdChzdHlsZS5wYWRkaW5nTGVmdCkgPCB0YXJnZXQuY2xpZW50V2lkdGhcbiAgICAgICAgICAgICYmIGV2ZW50Lm9mZnNldFkgLSBwYXJzZUZsb2F0KHN0eWxlLnBhZGRpbmdUb3ApIDwgdGFyZ2V0LmNsaWVudEhlaWdodFxuICAgICAgICApXG4gICAgKTtcbn1cblxuZnVuY3Rpb24gcHJpbWFyeVVwKGV2ZW50OiBNb3VzZUV2ZW50KSB7XG4gICAgLy8gU3RvcCBkcmFnZ2luZyBhbmQgcmVzaXppbmcuXG4gICAgY2FuRHJhZyA9IGZhbHNlO1xuICAgIGRyYWdnaW5nID0gZmFsc2U7XG4gICAgY2FuUmVzaXplID0gZmFsc2U7XG4gICAgcmVzaXppbmcgPSBmYWxzZTtcbn1cblxuY29uc3QgY3Vyc29yRm9yRWRnZSA9IE9iamVjdC5mcmVlemUoe1xuICAgIFwic2UtcmVzaXplXCI6IFwibndzZS1yZXNpemVcIixcbiAgICBcInN3LXJlc2l6ZVwiOiBcIm5lc3ctcmVzaXplXCIsXG4gICAgXCJudy1yZXNpemVcIjogXCJud3NlLXJlc2l6ZVwiLFxuICAgIFwibmUtcmVzaXplXCI6IFwibmVzdy1yZXNpemVcIixcbiAgICBcInctcmVzaXplXCI6IFwiZXctcmVzaXplXCIsXG4gICAgXCJuLXJlc2l6ZVwiOiBcIm5zLXJlc2l6ZVwiLFxuICAgIFwicy1yZXNpemVcIjogXCJucy1yZXNpemVcIixcbiAgICBcImUtcmVzaXplXCI6IFwiZXctcmVzaXplXCIsXG59KVxuXG5mdW5jdGlvbiBzZXRSZXNpemUoZWRnZT86IGtleW9mIHR5cGVvZiBjdXJzb3JGb3JFZGdlKTogdm9pZCB7XG4gICAgaWYgKGVkZ2UpIHtcbiAgICAgICAgaWYgKCFyZXNpemVFZGdlKSB7IGRlZmF1bHRDdXJzb3IgPSBkb2N1bWVudC5ib2R5LnN0eWxlLmN1cnNvcjsgfVxuICAgICAgICBkb2N1bWVudC5ib2R5LnN0eWxlLmN1cnNvciA9IGN1cnNvckZvckVkZ2VbZWRnZV07XG4gICAgfSBlbHNlIGlmICghZWRnZSAmJiByZXNpemVFZGdlKSB7XG4gICAgICAgIGRvY3VtZW50LmJvZHkuc3R5bGUuY3Vyc29yID0gZGVmYXVsdEN1cnNvcjtcbiAgICB9XG5cbiAgICByZXNpemVFZGdlID0gZWRnZSB8fCBcIlwiO1xufVxuXG5mdW5jdGlvbiBvbk1vdXNlTW92ZShldmVudDogTW91c2VFdmVudCk6IHZvaWQge1xuICAgIGlmIChjYW5SZXNpemUgJiYgcmVzaXplRWRnZSkge1xuICAgICAgICAvLyBTdGFydCByZXNpemluZy5cbiAgICAgICAgcmVzaXppbmcgPSB0cnVlO1xuICAgICAgICBpbnZva2UoXCJ3YWlsczpyZXNpemU6XCIgKyByZXNpemVFZGdlKTtcbiAgICB9IGVsc2UgaWYgKGNhbkRyYWcpIHtcbiAgICAgICAgLy8gU3RhcnQgZHJhZ2dpbmcuXG4gICAgICAgIGRyYWdnaW5nID0gdHJ1ZTtcbiAgICAgICAgaW52b2tlKFwid2FpbHM6ZHJhZ1wiKTtcbiAgICB9XG5cbiAgICBpZiAoZHJhZ2dpbmcgfHwgcmVzaXppbmcpIHtcbiAgICAgICAgLy8gRWl0aGVyIGRyYWcgb3IgcmVzaXplIGlzIG9uZ29pbmcsXG4gICAgICAgIC8vIHJlc2V0IHJlYWRpbmVzcyBhbmQgc3RvcCBwcm9jZXNzaW5nLlxuICAgICAgICBjYW5EcmFnID0gY2FuUmVzaXplID0gZmFsc2U7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIXJlc2l6YWJsZSB8fCAoIUlzV2luZG93cygpICYmICEoSXNMaW51eCgpICYmIEdldEZsYWcoXCJmcmFtZWxlc3NcIikpKSkge1xuICAgICAgICBpZiAocmVzaXplRWRnZSkgeyBzZXRSZXNpemUoKTsgfVxuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgcmVzaXplSGFuZGxlSGVpZ2h0ID0gR2V0RmxhZyhcInN5c3RlbS5yZXNpemVIYW5kbGVIZWlnaHRcIikgfHwgNTtcbiAgICBjb25zdCByZXNpemVIYW5kbGVXaWR0aCA9IEdldEZsYWcoXCJzeXN0ZW0ucmVzaXplSGFuZGxlV2lkdGhcIikgfHwgNTtcblxuICAgIC8vIEV4dHJhIHBpeGVscyBmb3IgdGhlIGNvcm5lciBhcmVhcy5cbiAgICBjb25zdCBjb3JuZXJFeHRyYSA9IEdldEZsYWcoXCJyZXNpemVDb3JuZXJFeHRyYVwiKSB8fCAxMDtcblxuICAgIC8vIFdoZW4gYSBzY3JvbGxiYXIgaXMgcHJlc2VudCBhdCB0aGUgd2luZG93IGVkZ2UgaXQgY29uc3VtZXMgbW91c2UgZXZlbnRzIGluIHRoYXQgc3RyaXAuXG4gICAgLy8gU2hpZnQgdGhlIGVmZmVjdGl2ZSBjb250ZW50IGVkZ2UgaW53YXJkIHNvIHRoZSByZXNpemUgem9uZSBzaXRzIGp1c3QgYmVmb3JlIHRoZSBzY3JvbGxiYXIuXG4gICAgY29uc3Qgc2Nyb2xsYmFyV2lkdGggPSBNYXRoLm1heCgwLCB3aW5kb3cuaW5uZXJXaWR0aCAtIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRXaWR0aCk7XG4gICAgY29uc3Qgc2Nyb2xsYmFySGVpZ2h0ID0gTWF0aC5tYXgoMCwgd2luZG93LmlubmVySGVpZ2h0IC0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudEhlaWdodCk7XG4gICAgY29uc3QgcmlnaHRDb250ZW50RWRnZSA9IHdpbmRvdy5pbm5lcldpZHRoIC0gc2Nyb2xsYmFyV2lkdGg7XG4gICAgY29uc3QgYm90dG9tQ29udGVudEVkZ2UgPSB3aW5kb3cuaW5uZXJIZWlnaHQgLSBzY3JvbGxiYXJIZWlnaHQ7XG5cbiAgICBjb25zdCByaWdodEJvcmRlciA9IGV2ZW50LmNsaWVudFggPCByaWdodENvbnRlbnRFZGdlICYmIChyaWdodENvbnRlbnRFZGdlIC0gZXZlbnQuY2xpZW50WCkgPCByZXNpemVIYW5kbGVXaWR0aDtcbiAgICBjb25zdCBsZWZ0Qm9yZGVyID0gZXZlbnQuY2xpZW50WCA8IHJlc2l6ZUhhbmRsZVdpZHRoO1xuICAgIGNvbnN0IHRvcEJvcmRlciA9IGV2ZW50LmNsaWVudFkgPCByZXNpemVIYW5kbGVIZWlnaHQ7XG4gICAgY29uc3QgYm90dG9tQm9yZGVyID0gZXZlbnQuY2xpZW50WSA8IGJvdHRvbUNvbnRlbnRFZGdlICYmIChib3R0b21Db250ZW50RWRnZSAtIGV2ZW50LmNsaWVudFkpIDwgcmVzaXplSGFuZGxlSGVpZ2h0O1xuXG4gICAgLy8gQWRqdXN0IGZvciBjb3JuZXIgYXJlYXMuXG4gICAgY29uc3QgcmlnaHRDb3JuZXIgPSBldmVudC5jbGllbnRYIDwgcmlnaHRDb250ZW50RWRnZSAmJiAocmlnaHRDb250ZW50RWRnZSAtIGV2ZW50LmNsaWVudFgpIDwgKHJlc2l6ZUhhbmRsZVdpZHRoICsgY29ybmVyRXh0cmEpO1xuICAgIGNvbnN0IGxlZnRDb3JuZXIgPSBldmVudC5jbGllbnRYIDwgKHJlc2l6ZUhhbmRsZVdpZHRoICsgY29ybmVyRXh0cmEpO1xuICAgIGNvbnN0IHRvcENvcm5lciA9IGV2ZW50LmNsaWVudFkgPCAocmVzaXplSGFuZGxlSGVpZ2h0ICsgY29ybmVyRXh0cmEpO1xuICAgIGNvbnN0IGJvdHRvbUNvcm5lciA9IGV2ZW50LmNsaWVudFkgPCBib3R0b21Db250ZW50RWRnZSAmJiAoYm90dG9tQ29udGVudEVkZ2UgLSBldmVudC5jbGllbnRZKSA8IChyZXNpemVIYW5kbGVIZWlnaHQgKyBjb3JuZXJFeHRyYSk7XG5cbiAgICBpZiAoIWxlZnRDb3JuZXIgJiYgIXRvcENvcm5lciAmJiAhYm90dG9tQ29ybmVyICYmICFyaWdodENvcm5lcikge1xuICAgICAgICAvLyBPcHRpbWlzYXRpb246IG91dCBvZiBhbGwgY29ybmVyIGFyZWFzIGltcGxpZXMgb3V0IG9mIGJvcmRlcnMuXG4gICAgICAgIHNldFJlc2l6ZSgpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgY29ybmVycy5cbiAgICBlbHNlIGlmIChyaWdodENvcm5lciAmJiBib3R0b21Db3JuZXIpIHNldFJlc2l6ZShcInNlLXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmIChsZWZ0Q29ybmVyICYmIGJvdHRvbUNvcm5lcikgc2V0UmVzaXplKFwic3ctcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKGxlZnRDb3JuZXIgJiYgdG9wQ29ybmVyKSBzZXRSZXNpemUoXCJudy1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAodG9wQ29ybmVyICYmIHJpZ2h0Q29ybmVyKSBzZXRSZXNpemUoXCJuZS1yZXNpemVcIik7XG4gICAgLy8gRGV0ZWN0IGJvcmRlcnMuXG4gICAgZWxzZSBpZiAobGVmdEJvcmRlcikgc2V0UmVzaXplKFwidy1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAodG9wQm9yZGVyKSBzZXRSZXNpemUoXCJuLXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmIChib3R0b21Cb3JkZXIpIHNldFJlc2l6ZShcInMtcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKHJpZ2h0Qm9yZGVyKSBzZXRSZXNpemUoXCJlLXJlc2l6ZVwiKTtcbiAgICAvLyBPdXQgb2YgYm9yZGVyIGFyZWEuXG4gICAgZWxzZSBzZXRSZXNpemUoKTtcbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuaW1wb3J0IHsgbmV3UnVudGltZUNhbGxlciwgb2JqZWN0TmFtZXMgfSBmcm9tIFwiLi9ydW50aW1lLmpzXCI7XG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcihvYmplY3ROYW1lcy5BcHBsaWNhdGlvbik7XG5cbmNvbnN0IEhpZGVNZXRob2QgPSAwO1xuY29uc3QgU2hvd01ldGhvZCA9IDE7XG5jb25zdCBRdWl0TWV0aG9kID0gMjtcblxuLyoqXG4gKiBIaWRlcyBhIGNlcnRhaW4gbWV0aG9kIGJ5IGNhbGxpbmcgdGhlIEhpZGVNZXRob2QgZnVuY3Rpb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBIaWRlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBjYWxsKEhpZGVNZXRob2QpO1xufVxuXG4vKipcbiAqIENhbGxzIHRoZSBTaG93TWV0aG9kIGFuZCByZXR1cm5zIHRoZSByZXN1bHQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTaG93KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBjYWxsKFNob3dNZXRob2QpO1xufVxuXG4vKipcbiAqIENhbGxzIHRoZSBRdWl0TWV0aG9kIHRvIHRlcm1pbmF0ZSB0aGUgcHJvZ3JhbS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFF1aXQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIGNhbGwoUXVpdE1ldGhvZCk7XG59XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbmltcG9ydCB7IENhbmNlbGxhYmxlUHJvbWlzZSwgdHlwZSBDYW5jZWxsYWJsZVByb21pc2VXaXRoUmVzb2x2ZXJzIH0gZnJvbSBcIi4vY2FuY2VsbGFibGUuanNcIjtcbmltcG9ydCB7IG5ld1J1bnRpbWVDYWxsZXIsIG9iamVjdE5hbWVzIH0gZnJvbSBcIi4vcnVudGltZS5qc1wiO1xuaW1wb3J0IHsgbmFub2lkIH0gZnJvbSBcIi4vbmFub2lkLmpzXCI7XG5cbi8vIFNldHVwXG5pbXBvcnQgeyBoYXNET00gfSBmcm9tIFwiLi9lbnZpcm9ubWVudC5qc1wiO1xuXG5pZiAoaGFzRE9NKSB7XG4gICAgd2luZG93Ll93YWlscyA9IHdpbmRvdy5fd2FpbHMgfHwge307XG59XG5cbnR5cGUgUHJvbWlzZVJlc29sdmVycyA9IE9taXQ8Q2FuY2VsbGFibGVQcm9taXNlV2l0aFJlc29sdmVyczxhbnk+LCBcInByb21pc2VcIiB8IFwib25jYW5jZWxsZWRcIj5cblxuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXIob2JqZWN0TmFtZXMuQ2FsbCk7XG5jb25zdCBjYW5jZWxDYWxsID0gbmV3UnVudGltZUNhbGxlcihvYmplY3ROYW1lcy5DYW5jZWxDYWxsKTtcbmNvbnN0IGNhbGxSZXNwb25zZXMgPSBuZXcgTWFwPHN0cmluZywgUHJvbWlzZVJlc29sdmVycz4oKTtcblxuY29uc3QgQ2FsbEJpbmRpbmcgPSAwO1xuY29uc3QgQ2FuY2VsTWV0aG9kID0gMFxuXG4vKipcbiAqIEhvbGRzIGFsbCByZXF1aXJlZCBpbmZvcm1hdGlvbiBmb3IgYSBiaW5kaW5nIGNhbGwuXG4gKiBNYXkgcHJvdmlkZSBlaXRoZXIgYSBtZXRob2QgSUQgb3IgYSBtZXRob2QgbmFtZSwgYnV0IG5vdCBib3RoLlxuICovXG5leHBvcnQgdHlwZSBDYWxsT3B0aW9ucyA9IHtcbiAgICAvKiogVGhlIG51bWVyaWMgSUQgb2YgdGhlIGJvdW5kIG1ldGhvZCB0byBjYWxsLiAqL1xuICAgIG1ldGhvZElEOiBudW1iZXI7XG4gICAgLyoqIFRoZSBmdWxseSBxdWFsaWZpZWQgbmFtZSBvZiB0aGUgYm91bmQgbWV0aG9kIHRvIGNhbGwuICovXG4gICAgbWV0aG9kTmFtZT86IG5ldmVyO1xuICAgIC8qKiBBcmd1bWVudHMgdG8gYmUgcGFzc2VkIGludG8gdGhlIGJvdW5kIG1ldGhvZC4gKi9cbiAgICBhcmdzOiBhbnlbXTtcbn0gfCB7XG4gICAgLyoqIFRoZSBudW1lcmljIElEIG9mIHRoZSBib3VuZCBtZXRob2QgdG8gY2FsbC4gKi9cbiAgICBtZXRob2RJRD86IG5ldmVyO1xuICAgIC8qKiBUaGUgZnVsbHkgcXVhbGlmaWVkIG5hbWUgb2YgdGhlIGJvdW5kIG1ldGhvZCB0byBjYWxsLiAqL1xuICAgIG1ldGhvZE5hbWU6IHN0cmluZztcbiAgICAvKiogQXJndW1lbnRzIHRvIGJlIHBhc3NlZCBpbnRvIHRoZSBib3VuZCBtZXRob2QuICovXG4gICAgYXJnczogYW55W107XG59O1xuXG4vKipcbiAqIEV4Y2VwdGlvbiBjbGFzcyB0aGF0IHdpbGwgYmUgdGhyb3duIGluIGNhc2UgdGhlIGJvdW5kIG1ldGhvZCByZXR1cm5zIGFuIGVycm9yLlxuICogVGhlIHZhbHVlIG9mIHRoZSB7QGxpbmsgUnVudGltZUVycm9yI25hbWV9IHByb3BlcnR5IGlzIFwiUnVudGltZUVycm9yXCIuXG4gKi9cbmV4cG9ydCBjbGFzcyBSdW50aW1lRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gICAgLyoqXG4gICAgICogQ29uc3RydWN0cyBhIG5ldyBSdW50aW1lRXJyb3IgaW5zdGFuY2UuXG4gICAgICogQHBhcmFtIG1lc3NhZ2UgLSBUaGUgZXJyb3IgbWVzc2FnZS5cbiAgICAgKiBAcGFyYW0gb3B0aW9ucyAtIE9wdGlvbnMgdG8gYmUgZm9yd2FyZGVkIHRvIHRoZSBFcnJvciBjb25zdHJ1Y3Rvci5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihtZXNzYWdlPzogc3RyaW5nLCBvcHRpb25zPzogRXJyb3JPcHRpb25zKSB7XG4gICAgICAgIHN1cGVyKG1lc3NhZ2UsIG9wdGlvbnMpO1xuICAgICAgICB0aGlzLm5hbWUgPSBcIlJ1bnRpbWVFcnJvclwiO1xuICAgIH1cbn1cblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSB1bmlxdWUgSUQgdXNpbmcgdGhlIG5hbm9pZCBsaWJyYXJ5LlxuICpcbiAqIEByZXR1cm5zIEEgdW5pcXVlIElEIHRoYXQgZG9lcyBub3QgZXhpc3QgaW4gdGhlIGNhbGxSZXNwb25zZXMgc2V0LlxuICovXG5mdW5jdGlvbiBnZW5lcmF0ZUlEKCk6IHN0cmluZyB7XG4gICAgbGV0IHJlc3VsdDtcbiAgICBkbyB7XG4gICAgICAgIHJlc3VsdCA9IG5hbm9pZCgpO1xuICAgIH0gd2hpbGUgKGNhbGxSZXNwb25zZXMuaGFzKHJlc3VsdCkpO1xuICAgIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKlxuICogQ2FsbCBhIGJvdW5kIG1ldGhvZCBhY2NvcmRpbmcgdG8gdGhlIGdpdmVuIGNhbGwgb3B0aW9ucy5cbiAqXG4gKiBJbiBjYXNlIG9mIGZhaWx1cmUsIHRoZSByZXR1cm5lZCBwcm9taXNlIHdpbGwgcmVqZWN0IHdpdGggYW4gZXhjZXB0aW9uXG4gKiBhbW9uZyBSZWZlcmVuY2VFcnJvciAodW5rbm93biBtZXRob2QpLCBUeXBlRXJyb3IgKHdyb25nIGFyZ3VtZW50IGNvdW50IG9yIHR5cGUpLFxuICoge0BsaW5rIFJ1bnRpbWVFcnJvcn0gKG1ldGhvZCByZXR1cm5lZCBhbiBlcnJvciksIG9yIG90aGVyIChuZXR3b3JrIG9yIGludGVybmFsIGVycm9ycykuXG4gKiBUaGUgZXhjZXB0aW9uIG1pZ2h0IGhhdmUgYSBcImNhdXNlXCIgZmllbGQgd2l0aCB0aGUgdmFsdWUgcmV0dXJuZWRcbiAqIGJ5IHRoZSBhcHBsaWNhdGlvbi0gb3Igc2VydmljZS1sZXZlbCBlcnJvciBtYXJzaGFsaW5nIGZ1bmN0aW9ucy5cbiAqXG4gKiBAcGFyYW0gb3B0aW9ucyAtIEEgbWV0aG9kIGNhbGwgZGVzY3JpcHRvci5cbiAqIEByZXR1cm5zIFRoZSByZXN1bHQgb2YgdGhlIGNhbGwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBDYWxsKG9wdGlvbnM6IENhbGxPcHRpb25zKTogQ2FuY2VsbGFibGVQcm9taXNlPGFueT4ge1xuICAgIGNvbnN0IGlkID0gZ2VuZXJhdGVJRCgpO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gQ2FuY2VsbGFibGVQcm9taXNlLndpdGhSZXNvbHZlcnM8YW55PigpO1xuICAgIGNhbGxSZXNwb25zZXMuc2V0KGlkLCB7IHJlc29sdmU6IHJlc3VsdC5yZXNvbHZlLCByZWplY3Q6IHJlc3VsdC5yZWplY3QgfSk7XG5cbiAgICBjb25zdCByZXF1ZXN0ID0gY2FsbChDYWxsQmluZGluZywgT2JqZWN0LmFzc2lnbih7IFwiY2FsbC1pZFwiOiBpZCB9LCBvcHRpb25zKSk7XG4gICAgbGV0IHJ1bm5pbmcgPSB0cnVlO1xuXG4gICAgcmVxdWVzdC50aGVuKChyZXMpID0+IHtcbiAgICAgICAgcnVubmluZyA9IGZhbHNlO1xuICAgICAgICBjYWxsUmVzcG9uc2VzLmRlbGV0ZShpZCk7XG4gICAgICAgIHJlc3VsdC5yZXNvbHZlKHJlcyk7XG4gICAgfSwgKGVycikgPT4ge1xuICAgICAgICBydW5uaW5nID0gZmFsc2U7XG4gICAgICAgIGNhbGxSZXNwb25zZXMuZGVsZXRlKGlkKTtcbiAgICAgICAgcmVzdWx0LnJlamVjdChlcnIpO1xuICAgIH0pO1xuXG4gICAgY29uc3QgY2FuY2VsID0gKCkgPT4ge1xuICAgICAgICBjYWxsUmVzcG9uc2VzLmRlbGV0ZShpZCk7XG4gICAgICAgIHJldHVybiBjYW5jZWxDYWxsKENhbmNlbE1ldGhvZCwge1wiY2FsbC1pZFwiOiBpZH0pLmNhdGNoKChlcnIpID0+IHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciB3aGlsZSByZXF1ZXN0aW5nIGJpbmRpbmcgY2FsbCBjYW5jZWxsYXRpb246XCIsIGVycik7XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICByZXN1bHQub25jYW5jZWxsZWQgPSAoKSA9PiB7XG4gICAgICAgIGlmIChydW5uaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gY2FuY2VsKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gcmVxdWVzdC50aGVuKGNhbmNlbCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIHJlc3VsdC5wcm9taXNlO1xufVxuXG4vKipcbiAqIENhbGxzIGEgYm91bmQgbWV0aG9kIGJ5IG5hbWUgd2l0aCB0aGUgc3BlY2lmaWVkIGFyZ3VtZW50cy5cbiAqIFNlZSB7QGxpbmsgQ2FsbH0gZm9yIGRldGFpbHMuXG4gKlxuICogQHBhcmFtIG1ldGhvZE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgbWV0aG9kIGluIHRoZSBmb3JtYXQgJ3BhY2thZ2Uuc3RydWN0Lm1ldGhvZCcuXG4gKiBAcGFyYW0gYXJncyAtIFRoZSBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgbWV0aG9kLlxuICogQHJldHVybnMgVGhlIHJlc3VsdCBvZiB0aGUgbWV0aG9kIGNhbGwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBCeU5hbWUobWV0aG9kTmFtZTogc3RyaW5nLCAuLi5hcmdzOiBhbnlbXSk6IENhbmNlbGxhYmxlUHJvbWlzZTxhbnk+IHtcbiAgICByZXR1cm4gQ2FsbCh7IG1ldGhvZE5hbWUsIGFyZ3MgfSk7XG59XG5cbi8qKlxuICogQ2FsbHMgYSBtZXRob2QgYnkgaXRzIG51bWVyaWMgSUQgd2l0aCB0aGUgc3BlY2lmaWVkIGFyZ3VtZW50cy5cbiAqIFNlZSB7QGxpbmsgQ2FsbH0gZm9yIGRldGFpbHMuXG4gKlxuICogQHBhcmFtIG1ldGhvZElEIC0gVGhlIElEIG9mIHRoZSBtZXRob2QgdG8gY2FsbC5cbiAqIEBwYXJhbSBhcmdzIC0gVGhlIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBtZXRob2QuXG4gKiBAcmV0dXJuIFRoZSByZXN1bHQgb2YgdGhlIG1ldGhvZCBjYWxsLlxuICovXG5leHBvcnQgZnVuY3Rpb24gQnlJRChtZXRob2RJRDogbnVtYmVyLCAuLi5hcmdzOiBhbnlbXSk6IENhbmNlbGxhYmxlUHJvbWlzZTxhbnk+IHtcbiAgICByZXR1cm4gQ2FsbCh7IG1ldGhvZElELCBhcmdzIH0pO1xufVxuIiwgIi8vIFNvdXJjZTogaHR0cHM6Ly9naXRodWIuY29tL2luc3BlY3QtanMvaXMtY2FsbGFibGVcblxuLy8gVGhlIE1JVCBMaWNlbnNlIChNSVQpXG4vL1xuLy8gQ29weXJpZ2h0IChjKSAyMDE1IEpvcmRhbiBIYXJiYW5kXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuLy8gb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbFxuLy8gaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xuLy8gdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuLy8gY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4vLyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluIGFsbFxuLy8gY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4vLyBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbi8vIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuLy8gQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuLy8gTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbi8vIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFXG4vLyBTT0ZUV0FSRS5cblxudmFyIGZuVG9TdHIgPSBGdW5jdGlvbi5wcm90b3R5cGUudG9TdHJpbmc7XG52YXIgcmVmbGVjdEFwcGx5OiB0eXBlb2YgUmVmbGVjdC5hcHBseSB8IGZhbHNlIHwgbnVsbCA9IHR5cGVvZiBSZWZsZWN0ID09PSAnb2JqZWN0JyAmJiBSZWZsZWN0ICE9PSBudWxsICYmIFJlZmxlY3QuYXBwbHk7XG52YXIgYmFkQXJyYXlMaWtlOiBhbnk7XG52YXIgaXNDYWxsYWJsZU1hcmtlcjogYW55O1xuaWYgKHR5cGVvZiByZWZsZWN0QXBwbHkgPT09ICdmdW5jdGlvbicgJiYgdHlwZW9mIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHRyeSB7XG4gICAgICAgIGJhZEFycmF5TGlrZSA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh7fSwgJ2xlbmd0aCcsIHtcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHRocm93IGlzQ2FsbGFibGVNYXJrZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBpc0NhbGxhYmxlTWFya2VyID0ge307XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby10aHJvdy1saXRlcmFsXG4gICAgICAgIHJlZmxlY3RBcHBseShmdW5jdGlvbiAoKSB7IHRocm93IDQyOyB9LCBudWxsLCBiYWRBcnJheUxpa2UpO1xuICAgIH0gY2F0Y2ggKF8pIHtcbiAgICAgICAgaWYgKF8gIT09IGlzQ2FsbGFibGVNYXJrZXIpIHtcbiAgICAgICAgICAgIHJlZmxlY3RBcHBseSA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9XG59IGVsc2Uge1xuICAgIHJlZmxlY3RBcHBseSA9IG51bGw7XG59XG5cbnZhciBjb25zdHJ1Y3RvclJlZ2V4ID0gL15cXHMqY2xhc3NcXGIvO1xudmFyIGlzRVM2Q2xhc3NGbiA9IGZ1bmN0aW9uIGlzRVM2Q2xhc3NGdW5jdGlvbih2YWx1ZTogYW55KTogYm9vbGVhbiB7XG4gICAgdHJ5IHtcbiAgICAgICAgdmFyIGZuU3RyID0gZm5Ub1N0ci5jYWxsKHZhbHVlKTtcbiAgICAgICAgcmV0dXJuIGNvbnN0cnVjdG9yUmVnZXgudGVzdChmblN0cik7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7IC8vIG5vdCBhIGZ1bmN0aW9uXG4gICAgfVxufTtcblxudmFyIHRyeUZ1bmN0aW9uT2JqZWN0ID0gZnVuY3Rpb24gdHJ5RnVuY3Rpb25Ub1N0cih2YWx1ZTogYW55KTogYm9vbGVhbiB7XG4gICAgdHJ5IHtcbiAgICAgICAgaWYgKGlzRVM2Q2xhc3NGbih2YWx1ZSkpIHsgcmV0dXJuIGZhbHNlOyB9XG4gICAgICAgIGZuVG9TdHIuY2FsbCh2YWx1ZSk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbn07XG52YXIgdG9TdHIgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nO1xudmFyIG9iamVjdENsYXNzID0gJ1tvYmplY3QgT2JqZWN0XSc7XG52YXIgZm5DbGFzcyA9ICdbb2JqZWN0IEZ1bmN0aW9uXSc7XG52YXIgZ2VuQ2xhc3MgPSAnW29iamVjdCBHZW5lcmF0b3JGdW5jdGlvbl0nO1xudmFyIGRkYUNsYXNzID0gJ1tvYmplY3QgSFRNTEFsbENvbGxlY3Rpb25dJzsgLy8gSUUgMTFcbnZhciBkZGFDbGFzczIgPSAnW29iamVjdCBIVE1MIGRvY3VtZW50LmFsbCBjbGFzc10nO1xudmFyIGRkYUNsYXNzMyA9ICdbb2JqZWN0IEhUTUxDb2xsZWN0aW9uXSc7IC8vIElFIDktMTBcbnZhciBoYXNUb1N0cmluZ1RhZyA9IHR5cGVvZiBTeW1ib2wgPT09ICdmdW5jdGlvbicgJiYgISFTeW1ib2wudG9TdHJpbmdUYWc7IC8vIGJldHRlcjogdXNlIGBoYXMtdG9zdHJpbmd0YWdgXG5cbnZhciBpc0lFNjggPSAhKDAgaW4gWyxdKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1zcGFyc2UtYXJyYXlzLCBjb21tYS1zcGFjaW5nXG5cbnZhciBpc0REQTogKHZhbHVlOiBhbnkpID0+IGJvb2xlYW4gPSBmdW5jdGlvbiBpc0RvY3VtZW50RG90QWxsKCkgeyByZXR1cm4gZmFsc2U7IH07XG5pZiAodHlwZW9mIGRvY3VtZW50ID09PSAnb2JqZWN0Jykge1xuICAgIC8vIEZpcmVmb3ggMyBjYW5vbmljYWxpemVzIEREQSB0byB1bmRlZmluZWQgd2hlbiBpdCdzIG5vdCBhY2Nlc3NlZCBkaXJlY3RseVxuICAgIHZhciBhbGwgPSBkb2N1bWVudC5hbGw7XG4gICAgaWYgKHRvU3RyLmNhbGwoYWxsKSA9PT0gdG9TdHIuY2FsbChkb2N1bWVudC5hbGwpKSB7XG4gICAgICAgIGlzRERBID0gZnVuY3Rpb24gaXNEb2N1bWVudERvdEFsbCh2YWx1ZSkge1xuICAgICAgICAgICAgLyogZ2xvYmFscyBkb2N1bWVudDogZmFsc2UgKi9cbiAgICAgICAgICAgIC8vIGluIElFIDYtOCwgdHlwZW9mIGRvY3VtZW50LmFsbCBpcyBcIm9iamVjdFwiIGFuZCBpdCdzIHRydXRoeVxuICAgICAgICAgICAgaWYgKChpc0lFNjggfHwgIXZhbHVlKSAmJiAodHlwZW9mIHZhbHVlID09PSAndW5kZWZpbmVkJyB8fCB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSkge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBzdHIgPSB0b1N0ci5jYWxsKHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0ciA9PT0gZGRhQ2xhc3NcbiAgICAgICAgICAgICAgICAgICAgICAgIHx8IHN0ciA9PT0gZGRhQ2xhc3MyXG4gICAgICAgICAgICAgICAgICAgICAgICB8fCBzdHIgPT09IGRkYUNsYXNzMyAvLyBvcGVyYSAxMi4xNlxuICAgICAgICAgICAgICAgICAgICAgICAgfHwgc3RyID09PSBvYmplY3RDbGFzcyAvLyBJRSA2LThcbiAgICAgICAgICAgICAgICAgICAgKSAmJiB2YWx1ZSgnJykgPT0gbnVsbDsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBlcWVxZXFcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7IC8qKi8gfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9O1xuICAgIH1cbn1cblxuZnVuY3Rpb24gaXNDYWxsYWJsZVJlZkFwcGx5PFQ+KHZhbHVlOiBUIHwgdW5rbm93bik6IHZhbHVlIGlzICguLi5hcmdzOiBhbnlbXSkgPT4gYW55ICB7XG4gICAgaWYgKGlzRERBKHZhbHVlKSkgeyByZXR1cm4gdHJ1ZTsgfVxuICAgIGlmICghdmFsdWUpIHsgcmV0dXJuIGZhbHNlOyB9XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ2Z1bmN0aW9uJyAmJiB0eXBlb2YgdmFsdWUgIT09ICdvYmplY3QnKSB7IHJldHVybiBmYWxzZTsgfVxuICAgIHRyeSB7XG4gICAgICAgIChyZWZsZWN0QXBwbHkgYXMgYW55KSh2YWx1ZSwgbnVsbCwgYmFkQXJyYXlMaWtlKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGlmIChlICE9PSBpc0NhbGxhYmxlTWFya2VyKSB7IHJldHVybiBmYWxzZTsgfVxuICAgIH1cbiAgICByZXR1cm4gIWlzRVM2Q2xhc3NGbih2YWx1ZSkgJiYgdHJ5RnVuY3Rpb25PYmplY3QodmFsdWUpO1xufVxuXG5mdW5jdGlvbiBpc0NhbGxhYmxlTm9SZWZBcHBseTxUPih2YWx1ZTogVCB8IHVua25vd24pOiB2YWx1ZSBpcyAoLi4uYXJnczogYW55W10pID0+IGFueSB7XG4gICAgaWYgKGlzRERBKHZhbHVlKSkgeyByZXR1cm4gdHJ1ZTsgfVxuICAgIGlmICghdmFsdWUpIHsgcmV0dXJuIGZhbHNlOyB9XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ2Z1bmN0aW9uJyAmJiB0eXBlb2YgdmFsdWUgIT09ICdvYmplY3QnKSB7IHJldHVybiBmYWxzZTsgfVxuICAgIGlmIChoYXNUb1N0cmluZ1RhZykgeyByZXR1cm4gdHJ5RnVuY3Rpb25PYmplY3QodmFsdWUpOyB9XG4gICAgaWYgKGlzRVM2Q2xhc3NGbih2YWx1ZSkpIHsgcmV0dXJuIGZhbHNlOyB9XG4gICAgdmFyIHN0ckNsYXNzID0gdG9TdHIuY2FsbCh2YWx1ZSk7XG4gICAgaWYgKHN0ckNsYXNzICE9PSBmbkNsYXNzICYmIHN0ckNsYXNzICE9PSBnZW5DbGFzcyAmJiAhKC9eXFxbb2JqZWN0IEhUTUwvKS50ZXN0KHN0ckNsYXNzKSkgeyByZXR1cm4gZmFsc2U7IH1cbiAgICByZXR1cm4gdHJ5RnVuY3Rpb25PYmplY3QodmFsdWUpO1xufTtcblxuZXhwb3J0IGRlZmF1bHQgcmVmbGVjdEFwcGx5ID8gaXNDYWxsYWJsZVJlZkFwcGx5IDogaXNDYWxsYWJsZU5vUmVmQXBwbHk7XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbmltcG9ydCBpc0NhbGxhYmxlIGZyb20gXCIuL2NhbGxhYmxlLmpzXCI7XG5cbi8qKlxuICogRXhjZXB0aW9uIGNsYXNzIHRoYXQgd2lsbCBiZSB1c2VkIGFzIHJlamVjdGlvbiByZWFzb25cbiAqIGluIGNhc2UgYSB7QGxpbmsgQ2FuY2VsbGFibGVQcm9taXNlfSBpcyBjYW5jZWxsZWQgc3VjY2Vzc2Z1bGx5LlxuICpcbiAqIFRoZSB2YWx1ZSBvZiB0aGUge0BsaW5rIG5hbWV9IHByb3BlcnR5IGlzIHRoZSBzdHJpbmcgYFwiQ2FuY2VsRXJyb3JcImAuXG4gKiBUaGUgdmFsdWUgb2YgdGhlIHtAbGluayBjYXVzZX0gcHJvcGVydHkgaXMgdGhlIGNhdXNlIHBhc3NlZCB0byB0aGUgY2FuY2VsIG1ldGhvZCwgaWYgYW55LlxuICovXG5leHBvcnQgY2xhc3MgQ2FuY2VsRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gICAgLyoqXG4gICAgICogQ29uc3RydWN0cyBhIG5ldyBgQ2FuY2VsRXJyb3JgIGluc3RhbmNlLlxuICAgICAqIEBwYXJhbSBtZXNzYWdlIC0gVGhlIGVycm9yIG1lc3NhZ2UuXG4gICAgICogQHBhcmFtIG9wdGlvbnMgLSBPcHRpb25zIHRvIGJlIGZvcndhcmRlZCB0byB0aGUgRXJyb3IgY29uc3RydWN0b3IuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IobWVzc2FnZT86IHN0cmluZywgb3B0aW9ucz86IEVycm9yT3B0aW9ucykge1xuICAgICAgICBzdXBlcihtZXNzYWdlLCBvcHRpb25zKTtcbiAgICAgICAgdGhpcy5uYW1lID0gXCJDYW5jZWxFcnJvclwiO1xuICAgIH1cbn1cblxuLyoqXG4gKiBFeGNlcHRpb24gY2xhc3MgdGhhdCB3aWxsIGJlIHJlcG9ydGVkIGFzIGFuIHVuaGFuZGxlZCByZWplY3Rpb25cbiAqIGluIGNhc2UgYSB7QGxpbmsgQ2FuY2VsbGFibGVQcm9taXNlfSByZWplY3RzIGFmdGVyIGJlaW5nIGNhbmNlbGxlZCxcbiAqIG9yIHdoZW4gdGhlIGBvbmNhbmNlbGxlZGAgY2FsbGJhY2sgdGhyb3dzIG9yIHJlamVjdHMuXG4gKlxuICogVGhlIHZhbHVlIG9mIHRoZSB7QGxpbmsgbmFtZX0gcHJvcGVydHkgaXMgdGhlIHN0cmluZyBgXCJDYW5jZWxsZWRSZWplY3Rpb25FcnJvclwiYC5cbiAqIFRoZSB2YWx1ZSBvZiB0aGUge0BsaW5rIGNhdXNlfSBwcm9wZXJ0eSBpcyB0aGUgcmVhc29uIHRoZSBwcm9taXNlIHJlamVjdGVkIHdpdGguXG4gKlxuICogQmVjYXVzZSB0aGUgb3JpZ2luYWwgcHJvbWlzZSB3YXMgY2FuY2VsbGVkLFxuICogYSB3cmFwcGVyIHByb21pc2Ugd2lsbCBiZSBwYXNzZWQgdG8gdGhlIHVuaGFuZGxlZCByZWplY3Rpb24gbGlzdGVuZXIgaW5zdGVhZC5cbiAqIFRoZSB7QGxpbmsgcHJvbWlzZX0gcHJvcGVydHkgaG9sZHMgYSByZWZlcmVuY2UgdG8gdGhlIG9yaWdpbmFsIHByb21pc2UuXG4gKi9cbmV4cG9ydCBjbGFzcyBDYW5jZWxsZWRSZWplY3Rpb25FcnJvciBleHRlbmRzIEVycm9yIHtcbiAgICAvKipcbiAgICAgKiBIb2xkcyBhIHJlZmVyZW5jZSB0byB0aGUgcHJvbWlzZSB0aGF0IHdhcyBjYW5jZWxsZWQgYW5kIHRoZW4gcmVqZWN0ZWQuXG4gICAgICovXG4gICAgcHJvbWlzZTogQ2FuY2VsbGFibGVQcm9taXNlPHVua25vd24+O1xuXG4gICAgLyoqXG4gICAgICogQ29uc3RydWN0cyBhIG5ldyBgQ2FuY2VsbGVkUmVqZWN0aW9uRXJyb3JgIGluc3RhbmNlLlxuICAgICAqIEBwYXJhbSBwcm9taXNlIC0gVGhlIHByb21pc2UgdGhhdCBjYXVzZWQgdGhlIGVycm9yIG9yaWdpbmFsbHkuXG4gICAgICogQHBhcmFtIHJlYXNvbiAtIFRoZSByZWplY3Rpb24gcmVhc29uLlxuICAgICAqIEBwYXJhbSBpbmZvIC0gQW4gb3B0aW9uYWwgaW5mb3JtYXRpdmUgbWVzc2FnZSBzcGVjaWZ5aW5nIHRoZSBjaXJjdW1zdGFuY2VzIGluIHdoaWNoIHRoZSBlcnJvciB3YXMgdGhyb3duLlxuICAgICAqICAgICAgICAgICAgICAgRGVmYXVsdHMgdG8gdGhlIHN0cmluZyBgXCJVbmhhbmRsZWQgcmVqZWN0aW9uIGluIGNhbmNlbGxlZCBwcm9taXNlLlwiYC5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcihwcm9taXNlOiBDYW5jZWxsYWJsZVByb21pc2U8dW5rbm93bj4sIHJlYXNvbj86IGFueSwgaW5mbz86IHN0cmluZykge1xuICAgICAgICBzdXBlcigoaW5mbyA/PyBcIlVuaGFuZGxlZCByZWplY3Rpb24gaW4gY2FuY2VsbGVkIHByb21pc2UuXCIpICsgXCIgUmVhc29uOiBcIiArIGVycm9yTWVzc2FnZShyZWFzb24pLCB7IGNhdXNlOiByZWFzb24gfSk7XG4gICAgICAgIHRoaXMucHJvbWlzZSA9IHByb21pc2U7XG4gICAgICAgIHRoaXMubmFtZSA9IFwiQ2FuY2VsbGVkUmVqZWN0aW9uRXJyb3JcIjtcbiAgICB9XG59XG5cbnR5cGUgQ2FuY2VsbGFibGVQcm9taXNlUmVzb2x2ZXI8VD4gPSAodmFsdWU6IFQgfCBQcm9taXNlTGlrZTxUPiB8IENhbmNlbGxhYmxlUHJvbWlzZUxpa2U8VD4pID0+IHZvaWQ7XG50eXBlIENhbmNlbGxhYmxlUHJvbWlzZVJlamVjdG9yID0gKHJlYXNvbj86IGFueSkgPT4gdm9pZDtcbnR5cGUgQ2FuY2VsbGFibGVQcm9taXNlQ2FuY2VsbGVyID0gKGNhdXNlPzogYW55KSA9PiB2b2lkIHwgUHJvbWlzZUxpa2U8dm9pZD47XG50eXBlIENhbmNlbGxhYmxlUHJvbWlzZUV4ZWN1dG9yPFQ+ID0gKHJlc29sdmU6IENhbmNlbGxhYmxlUHJvbWlzZVJlc29sdmVyPFQ+LCByZWplY3Q6IENhbmNlbGxhYmxlUHJvbWlzZVJlamVjdG9yKSA9PiB2b2lkO1xuXG5leHBvcnQgaW50ZXJmYWNlIENhbmNlbGxhYmxlUHJvbWlzZUxpa2U8VD4ge1xuICAgIHRoZW48VFJlc3VsdDEgPSBULCBUUmVzdWx0MiA9IG5ldmVyPihvbmZ1bGZpbGxlZD86ICgodmFsdWU6IFQpID0+IFRSZXN1bHQxIHwgUHJvbWlzZUxpa2U8VFJlc3VsdDE+IHwgQ2FuY2VsbGFibGVQcm9taXNlTGlrZTxUUmVzdWx0MT4pIHwgdW5kZWZpbmVkIHwgbnVsbCwgb25yZWplY3RlZD86ICgocmVhc29uOiBhbnkpID0+IFRSZXN1bHQyIHwgUHJvbWlzZUxpa2U8VFJlc3VsdDI+IHwgQ2FuY2VsbGFibGVQcm9taXNlTGlrZTxUUmVzdWx0Mj4pIHwgdW5kZWZpbmVkIHwgbnVsbCk6IENhbmNlbGxhYmxlUHJvbWlzZUxpa2U8VFJlc3VsdDEgfCBUUmVzdWx0Mj47XG4gICAgY2FuY2VsKGNhdXNlPzogYW55KTogdm9pZCB8IFByb21pc2VMaWtlPHZvaWQ+O1xufVxuXG4vKipcbiAqIFdyYXBzIGEgY2FuY2VsbGFibGUgcHJvbWlzZSBhbG9uZyB3aXRoIGl0cyByZXNvbHV0aW9uIG1ldGhvZHMuXG4gKiBUaGUgYG9uY2FuY2VsbGVkYCBmaWVsZCB3aWxsIGJlIG51bGwgaW5pdGlhbGx5IGJ1dCBtYXkgYmUgc2V0IHRvIHByb3ZpZGUgYSBjdXN0b20gY2FuY2VsbGF0aW9uIGZ1bmN0aW9uLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIENhbmNlbGxhYmxlUHJvbWlzZVdpdGhSZXNvbHZlcnM8VD4ge1xuICAgIHByb21pc2U6IENhbmNlbGxhYmxlUHJvbWlzZTxUPjtcbiAgICByZXNvbHZlOiBDYW5jZWxsYWJsZVByb21pc2VSZXNvbHZlcjxUPjtcbiAgICByZWplY3Q6IENhbmNlbGxhYmxlUHJvbWlzZVJlamVjdG9yO1xuICAgIG9uY2FuY2VsbGVkOiBDYW5jZWxsYWJsZVByb21pc2VDYW5jZWxsZXIgfCBudWxsO1xufVxuXG5pbnRlcmZhY2UgQ2FuY2VsbGFibGVQcm9taXNlU3RhdGUge1xuICAgIHJlYWRvbmx5IHJvb3Q6IENhbmNlbGxhYmxlUHJvbWlzZVN0YXRlO1xuICAgIHJlc29sdmluZzogYm9vbGVhbjtcbiAgICBzZXR0bGVkOiBib29sZWFuO1xuICAgIHJlYXNvbj86IENhbmNlbEVycm9yO1xufVxuXG4vLyBQcml2YXRlIGZpZWxkIG5hbWVzLlxuY29uc3QgYmFycmllclN5bSA9IFN5bWJvbChcImJhcnJpZXJcIik7XG5jb25zdCBjYW5jZWxJbXBsU3ltID0gU3ltYm9sKFwiY2FuY2VsSW1wbFwiKTtcbmNvbnN0IHNwZWNpZXM6IHR5cGVvZiBTeW1ib2wuc3BlY2llcyA9IFN5bWJvbC5zcGVjaWVzID8/IFN5bWJvbChcInNwZWNpZXNQb2x5ZmlsbFwiKTtcblxuLyoqXG4gKiBBIHByb21pc2Ugd2l0aCBhbiBhdHRhY2hlZCBtZXRob2QgZm9yIGNhbmNlbGxpbmcgbG9uZy1ydW5uaW5nIG9wZXJhdGlvbnMgKHNlZSB7QGxpbmsgQ2FuY2VsbGFibGVQcm9taXNlI2NhbmNlbH0pLlxuICogQ2FuY2VsbGF0aW9uIGNhbiBvcHRpb25hbGx5IGJlIGJvdW5kIHRvIGFuIHtAbGluayBBYm9ydFNpZ25hbH1cbiAqIGZvciBiZXR0ZXIgY29tcG9zYWJpbGl0eSAoc2VlIHtAbGluayBDYW5jZWxsYWJsZVByb21pc2UjY2FuY2VsT259KS5cbiAqXG4gKiBDYW5jZWxsaW5nIGEgcGVuZGluZyBwcm9taXNlIHdpbGwgcmVzdWx0IGluIGFuIGltbWVkaWF0ZSByZWplY3Rpb25cbiAqIHdpdGggYW4gaW5zdGFuY2Ugb2Yge0BsaW5rIENhbmNlbEVycm9yfSBhcyByZWFzb24sXG4gKiBidXQgd2hvZXZlciBzdGFydGVkIHRoZSBwcm9taXNlIHdpbGwgYmUgcmVzcG9uc2libGVcbiAqIGZvciBhY3R1YWxseSBhYm9ydGluZyB0aGUgdW5kZXJseWluZyBvcGVyYXRpb24uXG4gKiBUbyB0aGlzIHB1cnBvc2UsIHRoZSBjb25zdHJ1Y3RvciBhbmQgYWxsIGNoYWluaW5nIG1ldGhvZHNcbiAqIGFjY2VwdCBvcHRpb25hbCBjYW5jZWxsYXRpb24gY2FsbGJhY2tzLlxuICpcbiAqIElmIGEgYENhbmNlbGxhYmxlUHJvbWlzZWAgc3RpbGwgcmVzb2x2ZXMgYWZ0ZXIgaGF2aW5nIGJlZW4gY2FuY2VsbGVkLFxuICogdGhlIHJlc3VsdCB3aWxsIGJlIGRpc2NhcmRlZC4gSWYgaXQgcmVqZWN0cywgdGhlIHJlYXNvblxuICogd2lsbCBiZSByZXBvcnRlZCBhcyBhbiB1bmhhbmRsZWQgcmVqZWN0aW9uLFxuICogd3JhcHBlZCBpbiBhIHtAbGluayBDYW5jZWxsZWRSZWplY3Rpb25FcnJvcn0gaW5zdGFuY2UuXG4gKiBUbyBmYWNpbGl0YXRlIHRoZSBoYW5kbGluZyBvZiBjYW5jZWxsYXRpb24gcmVxdWVzdHMsXG4gKiBjYW5jZWxsZWQgYENhbmNlbGxhYmxlUHJvbWlzZWBzIHdpbGwgX25vdF8gcmVwb3J0IHVuaGFuZGxlZCBgQ2FuY2VsRXJyb3Jgc1xuICogd2hvc2UgYGNhdXNlYCBmaWVsZCBpcyB0aGUgc2FtZSBhcyB0aGUgb25lIHdpdGggd2hpY2ggdGhlIGN1cnJlbnQgcHJvbWlzZSB3YXMgY2FuY2VsbGVkLlxuICpcbiAqIEFsbCB1c3VhbCBwcm9taXNlIG1ldGhvZHMgYXJlIGRlZmluZWQgYW5kIHJldHVybiBhIGBDYW5jZWxsYWJsZVByb21pc2VgXG4gKiB3aG9zZSBjYW5jZWwgbWV0aG9kIHdpbGwgY2FuY2VsIHRoZSBwYXJlbnQgb3BlcmF0aW9uIGFzIHdlbGwsIHByb3BhZ2F0aW5nIHRoZSBjYW5jZWxsYXRpb24gcmVhc29uXG4gKiB1cHdhcmRzIHRocm91Z2ggcHJvbWlzZSBjaGFpbnMuXG4gKiBDb252ZXJzZWx5LCBjYW5jZWxsaW5nIGEgcHJvbWlzZSB3aWxsIG5vdCBhdXRvbWF0aWNhbGx5IGNhbmNlbCBkZXBlbmRlbnQgcHJvbWlzZXMgZG93bnN0cmVhbTpcbiAqIGBgYHRzXG4gKiBsZXQgcm9vdCA9IG5ldyBDYW5jZWxsYWJsZVByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4geyAuLi4gfSk7XG4gKiBsZXQgY2hpbGQxID0gcm9vdC50aGVuKCgpID0+IHsgLi4uIH0pO1xuICogbGV0IGNoaWxkMiA9IGNoaWxkMS50aGVuKCgpID0+IHsgLi4uIH0pO1xuICogbGV0IGNoaWxkMyA9IHJvb3QuY2F0Y2goKCkgPT4geyAuLi4gfSk7XG4gKiBjaGlsZDEuY2FuY2VsKCk7IC8vIENhbmNlbHMgY2hpbGQxIGFuZCByb290LCBidXQgbm90IGNoaWxkMiBvciBjaGlsZDNcbiAqIGBgYFxuICogQ2FuY2VsbGluZyBhIHByb21pc2UgdGhhdCBoYXMgYWxyZWFkeSBzZXR0bGVkIGlzIHNhZmUgYW5kIGhhcyBubyBjb25zZXF1ZW5jZS5cbiAqXG4gKiBUaGUgYGNhbmNlbGAgbWV0aG9kIHJldHVybnMgYSBwcm9taXNlIHRoYXQgX2Fsd2F5cyBmdWxmaWxsc19cbiAqIGFmdGVyIHRoZSB3aG9sZSBjaGFpbiBoYXMgcHJvY2Vzc2VkIHRoZSBjYW5jZWwgcmVxdWVzdFxuICogYW5kIGFsbCBhdHRhY2hlZCBjYWxsYmFja3MgdXAgdG8gdGhhdCBtb21lbnQgaGF2ZSBydW4uXG4gKlxuICogQWxsIEVTMjAyNCBwcm9taXNlIG1ldGhvZHMgKHN0YXRpYyBhbmQgaW5zdGFuY2UpIGFyZSBkZWZpbmVkIG9uIENhbmNlbGxhYmxlUHJvbWlzZSxcbiAqIGJ1dCBhY3R1YWwgYXZhaWxhYmlsaXR5IG1heSB2YXJ5IHdpdGggT1Mvd2VidmlldyB2ZXJzaW9uLlxuICpcbiAqIEluIGxpbmUgd2l0aCB0aGUgcHJvcG9zYWwgYXQgaHR0cHM6Ly9naXRodWIuY29tL3RjMzkvcHJvcG9zYWwtcm0tYnVpbHRpbi1zdWJjbGFzc2luZyxcbiAqIGBDYW5jZWxsYWJsZVByb21pc2VgIGRvZXMgbm90IHN1cHBvcnQgdHJhbnNwYXJlbnQgc3ViY2xhc3NpbmcuXG4gKiBFeHRlbmRlcnMgc2hvdWxkIHRha2UgY2FyZSB0byBwcm92aWRlIHRoZWlyIG93biBtZXRob2QgaW1wbGVtZW50YXRpb25zLlxuICogVGhpcyBtaWdodCBiZSByZWNvbnNpZGVyZWQgaW4gY2FzZSB0aGUgcHJvcG9zYWwgaXMgcmV0aXJlZC5cbiAqXG4gKiBDYW5jZWxsYWJsZVByb21pc2UgaXMgYSB3cmFwcGVyIGFyb3VuZCB0aGUgRE9NIFByb21pc2Ugb2JqZWN0XG4gKiBhbmQgaXMgY29tcGxpYW50IHdpdGggdGhlIFtQcm9taXNlcy9BKyBzcGVjaWZpY2F0aW9uXShodHRwczovL3Byb21pc2VzYXBsdXMuY29tLylcbiAqIChpdCBwYXNzZXMgdGhlIFtjb21wbGlhbmNlIHN1aXRlXShodHRwczovL2dpdGh1Yi5jb20vcHJvbWlzZXMtYXBsdXMvcHJvbWlzZXMtdGVzdHMpKVxuICogaWYgc28gaXMgdGhlIHVuZGVybHlpbmcgaW1wbGVtZW50YXRpb24uXG4gKi9cbmV4cG9ydCBjbGFzcyBDYW5jZWxsYWJsZVByb21pc2U8VD4gZXh0ZW5kcyBQcm9taXNlPFQ+IGltcGxlbWVudHMgUHJvbWlzZUxpa2U8VD4sIENhbmNlbGxhYmxlUHJvbWlzZUxpa2U8VD4ge1xuICAgIC8vIFByaXZhdGUgZmllbGRzLlxuICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICBwcml2YXRlIFtiYXJyaWVyU3ltXSE6IFBhcnRpYWw8UHJvbWlzZVdpdGhSZXNvbHZlcnM8dm9pZD4+IHwgbnVsbDtcbiAgICAvKiogQGludGVybmFsICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBbY2FuY2VsSW1wbFN5bV0hOiAocmVhc29uOiBDYW5jZWxFcnJvcikgPT4gdm9pZCB8IFByb21pc2VMaWtlPHZvaWQ+O1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyBgQ2FuY2VsbGFibGVQcm9taXNlYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBleGVjdXRvciAtIEEgY2FsbGJhY2sgdXNlZCB0byBpbml0aWFsaXplIHRoZSBwcm9taXNlLiBUaGlzIGNhbGxiYWNrIGlzIHBhc3NlZCB0d28gYXJndW1lbnRzOlxuICAgICAqICAgICAgICAgICAgICAgICAgIGEgYHJlc29sdmVgIGNhbGxiYWNrIHVzZWQgdG8gcmVzb2x2ZSB0aGUgcHJvbWlzZSB3aXRoIGEgdmFsdWVcbiAgICAgKiAgICAgICAgICAgICAgICAgICBvciB0aGUgcmVzdWx0IG9mIGFub3RoZXIgcHJvbWlzZSAocG9zc2libHkgY2FuY2VsbGFibGUpLFxuICAgICAqICAgICAgICAgICAgICAgICAgIGFuZCBhIGByZWplY3RgIGNhbGxiYWNrIHVzZWQgdG8gcmVqZWN0IHRoZSBwcm9taXNlIHdpdGggYSBwcm92aWRlZCByZWFzb24gb3IgZXJyb3IuXG4gICAgICogICAgICAgICAgICAgICAgICAgSWYgdGhlIHZhbHVlIHByb3ZpZGVkIHRvIHRoZSBgcmVzb2x2ZWAgY2FsbGJhY2sgaXMgYSB0aGVuYWJsZSBfYW5kXyBjYW5jZWxsYWJsZSBvYmplY3RcbiAgICAgKiAgICAgICAgICAgICAgICAgICAoaXQgaGFzIGEgYHRoZW5gIF9hbmRfIGEgYGNhbmNlbGAgbWV0aG9kKSxcbiAgICAgKiAgICAgICAgICAgICAgICAgICBjYW5jZWxsYXRpb24gcmVxdWVzdHMgd2lsbCBiZSBmb3J3YXJkZWQgdG8gdGhhdCBvYmplY3QgYW5kIHRoZSBvbmNhbmNlbGxlZCB3aWxsIG5vdCBiZSBpbnZva2VkIGFueW1vcmUuXG4gICAgICogICAgICAgICAgICAgICAgICAgSWYgYW55IG9uZSBvZiB0aGUgdHdvIGNhbGxiYWNrcyBpcyBjYWxsZWQgX2FmdGVyXyB0aGUgcHJvbWlzZSBoYXMgYmVlbiBjYW5jZWxsZWQsXG4gICAgICogICAgICAgICAgICAgICAgICAgdGhlIHByb3ZpZGVkIHZhbHVlcyB3aWxsIGJlIGNhbmNlbGxlZCBhbmQgcmVzb2x2ZWQgYXMgdXN1YWwsXG4gICAgICogICAgICAgICAgICAgICAgICAgYnV0IHRoZWlyIHJlc3VsdHMgd2lsbCBiZSBkaXNjYXJkZWQuXG4gICAgICogICAgICAgICAgICAgICAgICAgSG93ZXZlciwgaWYgdGhlIHJlc29sdXRpb24gcHJvY2VzcyB1bHRpbWF0ZWx5IGVuZHMgdXAgaW4gYSByZWplY3Rpb25cbiAgICAgKiAgICAgICAgICAgICAgICAgICB0aGF0IGlzIG5vdCBkdWUgdG8gY2FuY2VsbGF0aW9uLCB0aGUgcmVqZWN0aW9uIHJlYXNvblxuICAgICAqICAgICAgICAgICAgICAgICAgIHdpbGwgYmUgd3JhcHBlZCBpbiBhIHtAbGluayBDYW5jZWxsZWRSZWplY3Rpb25FcnJvcn1cbiAgICAgKiAgICAgICAgICAgICAgICAgICBhbmQgYnViYmxlZCB1cCBhcyBhbiB1bmhhbmRsZWQgcmVqZWN0aW9uLlxuICAgICAqIEBwYXJhbSBvbmNhbmNlbGxlZCAtIEl0IGlzIHRoZSBjYWxsZXIncyByZXNwb25zaWJpbGl0eSB0byBlbnN1cmUgdGhhdCBhbnkgb3BlcmF0aW9uXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgc3RhcnRlZCBieSB0aGUgZXhlY3V0b3IgaXMgcHJvcGVybHkgaGFsdGVkIHVwb24gY2FuY2VsbGF0aW9uLlxuICAgICAqICAgICAgICAgICAgICAgICAgICAgIFRoaXMgb3B0aW9uYWwgY2FsbGJhY2sgY2FuIGJlIHVzZWQgdG8gdGhhdCBwdXJwb3NlLlxuICAgICAqICAgICAgICAgICAgICAgICAgICAgIEl0IHdpbGwgYmUgY2FsbGVkIF9zeW5jaHJvbm91c2x5XyB3aXRoIGEgY2FuY2VsbGF0aW9uIGNhdXNlXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgd2hlbiBjYW5jZWxsYXRpb24gaXMgcmVxdWVzdGVkLCBfYWZ0ZXJfIHRoZSBwcm9taXNlIGhhcyBhbHJlYWR5IHJlamVjdGVkXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgd2l0aCBhIHtAbGluayBDYW5jZWxFcnJvcn0sIGJ1dCBfYmVmb3JlX1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgIGFueSB7QGxpbmsgdGhlbn0ve0BsaW5rIGNhdGNofS97QGxpbmsgZmluYWxseX0gY2FsbGJhY2sgcnVucy5cbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICBJZiB0aGUgY2FsbGJhY2sgcmV0dXJucyBhIHRoZW5hYmxlLCB0aGUgcHJvbWlzZSByZXR1cm5lZCBmcm9tIHtAbGluayBjYW5jZWx9XG4gICAgICogICAgICAgICAgICAgICAgICAgICAgd2lsbCBvbmx5IGZ1bGZpbGwgYWZ0ZXIgdGhlIGZvcm1lciBoYXMgc2V0dGxlZC5cbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICBVbmhhbmRsZWQgZXhjZXB0aW9ucyBvciByZWplY3Rpb25zIGZyb20gdGhlIGNhbGxiYWNrIHdpbGwgYmUgd3JhcHBlZFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgIGluIGEge0BsaW5rIENhbmNlbGxlZFJlamVjdGlvbkVycm9yfSBhbmQgYnViYmxlZCB1cCBhcyB1bmhhbmRsZWQgcmVqZWN0aW9ucy5cbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICBJZiB0aGUgYHJlc29sdmVgIGNhbGxiYWNrIGlzIGNhbGxlZCBiZWZvcmUgY2FuY2VsbGF0aW9uIHdpdGggYSBjYW5jZWxsYWJsZSBwcm9taXNlLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgIGNhbmNlbGxhdGlvbiByZXF1ZXN0cyBvbiB0aGlzIHByb21pc2Ugd2lsbCBiZSBkaXZlcnRlZCB0byB0aGF0IHByb21pc2UsXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgYW5kIHRoZSBvcmlnaW5hbCBgb25jYW5jZWxsZWRgIGNhbGxiYWNrIHdpbGwgYmUgZGlzY2FyZGVkLlxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGV4ZWN1dG9yOiBDYW5jZWxsYWJsZVByb21pc2VFeGVjdXRvcjxUPiwgb25jYW5jZWxsZWQ/OiBDYW5jZWxsYWJsZVByb21pc2VDYW5jZWxsZXIpIHtcbiAgICAgICAgbGV0IHJlc29sdmUhOiAodmFsdWU6IFQgfCBQcm9taXNlTGlrZTxUPikgPT4gdm9pZDtcbiAgICAgICAgbGV0IHJlamVjdCE6IChyZWFzb24/OiBhbnkpID0+IHZvaWQ7XG4gICAgICAgIHN1cGVyKChyZXMsIHJlaikgPT4geyByZXNvbHZlID0gcmVzOyByZWplY3QgPSByZWo7IH0pO1xuXG4gICAgICAgIGlmICgodGhpcy5jb25zdHJ1Y3RvciBhcyBhbnkpW3NwZWNpZXNdICE9PSBQcm9taXNlKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2FuY2VsbGFibGVQcm9taXNlIGRvZXMgbm90IHN1cHBvcnQgdHJhbnNwYXJlbnQgc3ViY2xhc3NpbmcuIFBsZWFzZSByZWZyYWluIGZyb20gb3ZlcnJpZGluZyB0aGUgW1N5bWJvbC5zcGVjaWVzXSBzdGF0aWMgcHJvcGVydHkuXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHByb21pc2U6IENhbmNlbGxhYmxlUHJvbWlzZVdpdGhSZXNvbHZlcnM8VD4gPSB7XG4gICAgICAgICAgICBwcm9taXNlOiB0aGlzLFxuICAgICAgICAgICAgcmVzb2x2ZSxcbiAgICAgICAgICAgIHJlamVjdCxcbiAgICAgICAgICAgIGdldCBvbmNhbmNlbGxlZCgpIHsgcmV0dXJuIG9uY2FuY2VsbGVkID8/IG51bGw7IH0sXG4gICAgICAgICAgICBzZXQgb25jYW5jZWxsZWQoY2IpIHsgb25jYW5jZWxsZWQgPSBjYiA/PyB1bmRlZmluZWQ7IH1cbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBzdGF0ZTogQ2FuY2VsbGFibGVQcm9taXNlU3RhdGUgPSB7XG4gICAgICAgICAgICBnZXQgcm9vdCgpIHsgcmV0dXJuIHN0YXRlOyB9LFxuICAgICAgICAgICAgcmVzb2x2aW5nOiBmYWxzZSxcbiAgICAgICAgICAgIHNldHRsZWQ6IGZhbHNlXG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gU2V0dXAgY2FuY2VsbGF0aW9uIHN5c3RlbS5cbiAgICAgICAgdm9pZCBPYmplY3QuZGVmaW5lUHJvcGVydGllcyh0aGlzLCB7XG4gICAgICAgICAgICBbYmFycmllclN5bV06IHtcbiAgICAgICAgICAgICAgICBjb25maWd1cmFibGU6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICAgICAgICAgIHZhbHVlOiBudWxsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgW2NhbmNlbEltcGxTeW1dOiB7XG4gICAgICAgICAgICAgICAgY29uZmlndXJhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgdmFsdWU6IGNhbmNlbGxlckZvcihwcm9taXNlLCBzdGF0ZSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gUnVuIHRoZSBhY3R1YWwgZXhlY3V0b3IuXG4gICAgICAgIGNvbnN0IHJlamVjdG9yID0gcmVqZWN0b3JGb3IocHJvbWlzZSwgc3RhdGUpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgZXhlY3V0b3IocmVzb2x2ZXJGb3IocHJvbWlzZSwgc3RhdGUpLCByZWplY3Rvcik7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgaWYgKHN0YXRlLnJlc29sdmluZykge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiVW5oYW5kbGVkIGV4Y2VwdGlvbiBpbiBDYW5jZWxsYWJsZVByb21pc2UgZXhlY3V0b3IuXCIsIGVycik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlamVjdG9yKGVycik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDYW5jZWxzIGltbWVkaWF0ZWx5IHRoZSBleGVjdXRpb24gb2YgdGhlIG9wZXJhdGlvbiBhc3NvY2lhdGVkIHdpdGggdGhpcyBwcm9taXNlLlxuICAgICAqIFRoZSBwcm9taXNlIHJlamVjdHMgd2l0aCBhIHtAbGluayBDYW5jZWxFcnJvcn0gaW5zdGFuY2UgYXMgcmVhc29uLFxuICAgICAqIHdpdGggdGhlIHtAbGluayBDYW5jZWxFcnJvciNjYXVzZX0gcHJvcGVydHkgc2V0IHRvIHRoZSBnaXZlbiBhcmd1bWVudCwgaWYgYW55LlxuICAgICAqXG4gICAgICogSGFzIG5vIGVmZmVjdCBpZiBjYWxsZWQgYWZ0ZXIgdGhlIHByb21pc2UgaGFzIGFscmVhZHkgc2V0dGxlZDtcbiAgICAgKiByZXBlYXRlZCBjYWxscyBpbiBwYXJ0aWN1bGFyIGFyZSBzYWZlLCBidXQgb25seSB0aGUgZmlyc3Qgb25lXG4gICAgICogd2lsbCBzZXQgdGhlIGNhbmNlbGxhdGlvbiBjYXVzZS5cbiAgICAgKlxuICAgICAqIFRoZSBgQ2FuY2VsRXJyb3JgIGV4Y2VwdGlvbiBfbmVlZCBub3RfIGJlIGhhbmRsZWQgZXhwbGljaXRseSBfb24gdGhlIHByb21pc2VzIHRoYXQgYXJlIGJlaW5nIGNhbmNlbGxlZDpfXG4gICAgICogY2FuY2VsbGluZyBhIHByb21pc2Ugd2l0aCBubyBhdHRhY2hlZCByZWplY3Rpb24gaGFuZGxlciBkb2VzIG5vdCB0cmlnZ2VyIGFuIHVuaGFuZGxlZCByZWplY3Rpb24gZXZlbnQuXG4gICAgICogVGhlcmVmb3JlLCB0aGUgZm9sbG93aW5nIGlkaW9tcyBhcmUgYWxsIGVxdWFsbHkgY29ycmVjdDpcbiAgICAgKiBgYGB0c1xuICAgICAqIG5ldyBDYW5jZWxsYWJsZVByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4geyAuLi4gfSkuY2FuY2VsKCk7XG4gICAgICogbmV3IENhbmNlbGxhYmxlUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7IC4uLiB9KS50aGVuKC4uLikuY2FuY2VsKCk7XG4gICAgICogbmV3IENhbmNlbGxhYmxlUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7IC4uLiB9KS50aGVuKC4uLikuY2F0Y2goLi4uKS5jYW5jZWwoKTtcbiAgICAgKiBgYGBcbiAgICAgKiBXaGVuZXZlciBzb21lIGNhbmNlbGxlZCBwcm9taXNlIGluIGEgY2hhaW4gcmVqZWN0cyB3aXRoIGEgYENhbmNlbEVycm9yYFxuICAgICAqIHdpdGggdGhlIHNhbWUgY2FuY2VsbGF0aW9uIGNhdXNlIGFzIGl0c2VsZiwgdGhlIGVycm9yIHdpbGwgYmUgZGlzY2FyZGVkIHNpbGVudGx5LlxuICAgICAqIEhvd2V2ZXIsIHRoZSBgQ2FuY2VsRXJyb3JgIF93aWxsIHN0aWxsIGJlIGRlbGl2ZXJlZF8gdG8gYWxsIGF0dGFjaGVkIHJlamVjdGlvbiBoYW5kbGVyc1xuICAgICAqIGFkZGVkIGJ5IHtAbGluayB0aGVufSBhbmQgcmVsYXRlZCBtZXRob2RzOlxuICAgICAqIGBgYHRzXG4gICAgICogbGV0IGNhbmNlbGxhYmxlID0gbmV3IENhbmNlbGxhYmxlUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7IC4uLiB9KTtcbiAgICAgKiBjYW5jZWxsYWJsZS50aGVuKCgpID0+IHsgLi4uIH0pLmNhdGNoKGNvbnNvbGUubG9nKTtcbiAgICAgKiBjYW5jZWxsYWJsZS5jYW5jZWwoKTsgLy8gQSBDYW5jZWxFcnJvciBpcyBwcmludGVkIHRvIHRoZSBjb25zb2xlLlxuICAgICAqIGBgYFxuICAgICAqIElmIHRoZSBgQ2FuY2VsRXJyb3JgIGlzIG5vdCBoYW5kbGVkIGRvd25zdHJlYW0gYnkgdGhlIHRpbWUgaXQgcmVhY2hlc1xuICAgICAqIGEgX25vbi1jYW5jZWxsZWRfIHByb21pc2UsIGl0IF93aWxsXyB0cmlnZ2VyIGFuIHVuaGFuZGxlZCByZWplY3Rpb24gZXZlbnQsXG4gICAgICoganVzdCBsaWtlIG5vcm1hbCByZWplY3Rpb25zIHdvdWxkOlxuICAgICAqIGBgYHRzXG4gICAgICogbGV0IGNhbmNlbGxhYmxlID0gbmV3IENhbmNlbGxhYmxlUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7IC4uLiB9KTtcbiAgICAgKiBsZXQgY2hhaW5lZCA9IGNhbmNlbGxhYmxlLnRoZW4oKCkgPT4geyAuLi4gfSkudGhlbigoKSA9PiB7IC4uLiB9KTsgLy8gTm8gY2F0Y2guLi5cbiAgICAgKiBjYW5jZWxsYWJsZS5jYW5jZWwoKTsgLy8gVW5oYW5kbGVkIHJlamVjdGlvbiBldmVudCBvbiBjaGFpbmVkIVxuICAgICAqIGBgYFxuICAgICAqIFRoZXJlZm9yZSwgaXQgaXMgaW1wb3J0YW50IHRvIGVpdGhlciBjYW5jZWwgd2hvbGUgcHJvbWlzZSBjaGFpbnMgZnJvbSB0aGVpciB0YWlsLFxuICAgICAqIGFzIHNob3duIGluIHRoZSBjb3JyZWN0IGlkaW9tcyBhYm92ZSwgb3IgdGFrZSBjYXJlIG9mIGhhbmRsaW5nIGVycm9ycyBldmVyeXdoZXJlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBjYW5jZWxsYWJsZSBwcm9taXNlIHRoYXQgX2Z1bGZpbGxzXyBhZnRlciB0aGUgY2FuY2VsIGNhbGxiYWNrIChpZiBhbnkpXG4gICAgICogYW5kIGFsbCBoYW5kbGVycyBhdHRhY2hlZCB1cCB0byB0aGUgY2FsbCB0byBjYW5jZWwgaGF2ZSBydW4uXG4gICAgICogSWYgdGhlIGNhbmNlbCBjYWxsYmFjayByZXR1cm5zIGEgdGhlbmFibGUsIHRoZSBwcm9taXNlIHJldHVybmVkIGJ5IGBjYW5jZWxgXG4gICAgICogd2lsbCBhbHNvIHdhaXQgZm9yIHRoYXQgdGhlbmFibGUgdG8gc2V0dGxlLlxuICAgICAqIFRoaXMgZW5hYmxlcyBjYWxsZXJzIHRvIHdhaXQgZm9yIHRoZSBjYW5jZWxsZWQgb3BlcmF0aW9uIHRvIHRlcm1pbmF0ZVxuICAgICAqIHdpdGhvdXQgYmVpbmcgZm9yY2VkIHRvIGhhbmRsZSBwb3RlbnRpYWwgZXJyb3JzIGF0IHRoZSBjYWxsIHNpdGUuXG4gICAgICogYGBgdHNcbiAgICAgKiBjYW5jZWxsYWJsZS5jYW5jZWwoKS50aGVuKCgpID0+IHtcbiAgICAgKiAgICAgLy8gQ2xlYW51cCBmaW5pc2hlZCwgaXQncyBzYWZlIHRvIGRvIHNvbWV0aGluZyBlbHNlLlxuICAgICAqIH0sIChlcnIpID0+IHtcbiAgICAgKiAgICAgLy8gVW5yZWFjaGFibGU6IHRoZSBwcm9taXNlIHJldHVybmVkIGZyb20gY2FuY2VsIHdpbGwgbmV2ZXIgcmVqZWN0LlxuICAgICAqIH0pO1xuICAgICAqIGBgYFxuICAgICAqIE5vdGUgdGhhdCB0aGUgcmV0dXJuZWQgcHJvbWlzZSB3aWxsIF9ub3RfIGhhbmRsZSBpbXBsaWNpdGx5IGFueSByZWplY3Rpb25cbiAgICAgKiB0aGF0IG1pZ2h0IGhhdmUgb2NjdXJyZWQgYWxyZWFkeSBpbiB0aGUgY2FuY2VsbGVkIGNoYWluLlxuICAgICAqIEl0IHdpbGwganVzdCB0cmFjayB3aGV0aGVyIHJlZ2lzdGVyZWQgaGFuZGxlcnMgaGF2ZSBiZWVuIGV4ZWN1dGVkIG9yIG5vdC5cbiAgICAgKiBUaGVyZWZvcmUsIHVuaGFuZGxlZCByZWplY3Rpb25zIHdpbGwgbmV2ZXIgYmUgc2lsZW50bHkgaGFuZGxlZCBieSBjYWxsaW5nIGNhbmNlbC5cbiAgICAgKi9cbiAgICBjYW5jZWwoY2F1c2U/OiBhbnkpOiBDYW5jZWxsYWJsZVByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gbmV3IENhbmNlbGxhYmxlUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4ge1xuICAgICAgICAgICAgLy8gSU5WQVJJQU5UOiB0aGUgcmVzdWx0IG9mIHRoaXNbY2FuY2VsSW1wbFN5bV0gYW5kIHRoZSBiYXJyaWVyIGRvIG5vdCBldmVyIHJlamVjdC5cbiAgICAgICAgICAgIC8vIFVuZm9ydHVuYXRlbHkgbWFjT1MgSGlnaCBTaWVycmEgZG9lcyBub3Qgc3VwcG9ydCBQcm9taXNlLmFsbFNldHRsZWQuXG4gICAgICAgICAgICBQcm9taXNlLmFsbChbXG4gICAgICAgICAgICAgICAgdGhpc1tjYW5jZWxJbXBsU3ltXShuZXcgQ2FuY2VsRXJyb3IoXCJQcm9taXNlIGNhbmNlbGxlZC5cIiwgeyBjYXVzZSB9KSksXG4gICAgICAgICAgICAgICAgY3VycmVudEJhcnJpZXIodGhpcylcbiAgICAgICAgICAgIF0pLnRoZW4oKCkgPT4gcmVzb2x2ZSgpLCAoKSA9PiByZXNvbHZlKCkpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBCaW5kcyBwcm9taXNlIGNhbmNlbGxhdGlvbiB0byB0aGUgYWJvcnQgZXZlbnQgb2YgdGhlIGdpdmVuIHtAbGluayBBYm9ydFNpZ25hbH0uXG4gICAgICogSWYgdGhlIHNpZ25hbCBoYXMgYWxyZWFkeSBhYm9ydGVkLCB0aGUgcHJvbWlzZSB3aWxsIGJlIGNhbmNlbGxlZCBpbW1lZGlhdGVseS5cbiAgICAgKiBXaGVuIGVpdGhlciBjb25kaXRpb24gaXMgdmVyaWZpZWQsIHRoZSBjYW5jZWxsYXRpb24gY2F1c2Ugd2lsbCBiZSBzZXRcbiAgICAgKiB0byB0aGUgc2lnbmFsJ3MgYWJvcnQgcmVhc29uIChzZWUge0BsaW5rIEFib3J0U2lnbmFsI3JlYXNvbn0pLlxuICAgICAqXG4gICAgICogSGFzIG5vIGVmZmVjdCBpZiBjYWxsZWQgKG9yIGlmIHRoZSBzaWduYWwgYWJvcnRzKSBfYWZ0ZXJfIHRoZSBwcm9taXNlIGhhcyBhbHJlYWR5IHNldHRsZWQuXG4gICAgICogT25seSB0aGUgZmlyc3Qgc2lnbmFsIHRvIGFib3J0IHdpbGwgc2V0IHRoZSBjYW5jZWxsYXRpb24gY2F1c2UuXG4gICAgICpcbiAgICAgKiBGb3IgbW9yZSBkZXRhaWxzIGFib3V0IHRoZSBjYW5jZWxsYXRpb24gcHJvY2VzcyxcbiAgICAgKiBzZWUge0BsaW5rIGNhbmNlbH0gYW5kIHRoZSBgQ2FuY2VsbGFibGVQcm9taXNlYCBjb25zdHJ1Y3Rvci5cbiAgICAgKlxuICAgICAqIFRoaXMgbWV0aG9kIGVuYWJsZXMgYGF3YWl0YGluZyBjYW5jZWxsYWJsZSBwcm9taXNlcyB3aXRob3V0IGhhdmluZ1xuICAgICAqIHRvIHN0b3JlIHRoZW0gZm9yIGZ1dHVyZSBjYW5jZWxsYXRpb24sIGUuZy46XG4gICAgICogYGBgdHNcbiAgICAgKiBhd2FpdCBsb25nUnVubmluZ09wZXJhdGlvbigpLmNhbmNlbE9uKHNpZ25hbCk7XG4gICAgICogYGBgXG4gICAgICogaW5zdGVhZCBvZjpcbiAgICAgKiBgYGB0c1xuICAgICAqIGxldCBwcm9taXNlVG9CZUNhbmNlbGxlZCA9IGxvbmdSdW5uaW5nT3BlcmF0aW9uKCk7XG4gICAgICogYXdhaXQgcHJvbWlzZVRvQmVDYW5jZWxsZWQ7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBUaGlzIHByb21pc2UsIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAgICovXG4gICAgY2FuY2VsT24oc2lnbmFsOiBBYm9ydFNpZ25hbCk6IENhbmNlbGxhYmxlUHJvbWlzZTxUPiB7XG4gICAgICAgIGlmIChzaWduYWwuYWJvcnRlZCkge1xuICAgICAgICAgICAgdm9pZCB0aGlzLmNhbmNlbChzaWduYWwucmVhc29uKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2lnbmFsLmFkZEV2ZW50TGlzdGVuZXIoJ2Fib3J0JywgKCkgPT4gdm9pZCB0aGlzLmNhbmNlbChzaWduYWwucmVhc29uKSwge2NhcHR1cmU6IHRydWV9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEF0dGFjaGVzIGNhbGxiYWNrcyBmb3IgdGhlIHJlc29sdXRpb24gYW5kL29yIHJlamVjdGlvbiBvZiB0aGUgYENhbmNlbGxhYmxlUHJvbWlzZWAuXG4gICAgICpcbiAgICAgKiBUaGUgb3B0aW9uYWwgYG9uY2FuY2VsbGVkYCBhcmd1bWVudCB3aWxsIGJlIGludm9rZWQgd2hlbiB0aGUgcmV0dXJuZWQgcHJvbWlzZSBpcyBjYW5jZWxsZWQsXG4gICAgICogd2l0aCB0aGUgc2FtZSBzZW1hbnRpY3MgYXMgdGhlIGBvbmNhbmNlbGxlZGAgYXJndW1lbnQgb2YgdGhlIGNvbnN0cnVjdG9yLlxuICAgICAqIFdoZW4gdGhlIHBhcmVudCBwcm9taXNlIHJlamVjdHMgb3IgaXMgY2FuY2VsbGVkLCB0aGUgYG9ucmVqZWN0ZWRgIGNhbGxiYWNrIHdpbGwgcnVuLFxuICAgICAqIF9ldmVuIGFmdGVyIHRoZSByZXR1cm5lZCBwcm9taXNlIGhhcyBiZWVuIGNhbmNlbGxlZDpfXG4gICAgICogaW4gdGhhdCBjYXNlLCBzaG91bGQgaXQgcmVqZWN0IG9yIHRocm93LCB0aGUgcmVhc29uIHdpbGwgYmUgd3JhcHBlZFxuICAgICAqIGluIGEge0BsaW5rIENhbmNlbGxlZFJlamVjdGlvbkVycm9yfSBhbmQgYnViYmxlZCB1cCBhcyBhbiB1bmhhbmRsZWQgcmVqZWN0aW9uLlxuICAgICAqXG4gICAgICogQHBhcmFtIG9uZnVsZmlsbGVkIFRoZSBjYWxsYmFjayB0byBleGVjdXRlIHdoZW4gdGhlIFByb21pc2UgaXMgcmVzb2x2ZWQuXG4gICAgICogQHBhcmFtIG9ucmVqZWN0ZWQgVGhlIGNhbGxiYWNrIHRvIGV4ZWN1dGUgd2hlbiB0aGUgUHJvbWlzZSBpcyByZWplY3RlZC5cbiAgICAgKiBAcmV0dXJucyBBIGBDYW5jZWxsYWJsZVByb21pc2VgIGZvciB0aGUgY29tcGxldGlvbiBvZiB3aGljaGV2ZXIgY2FsbGJhY2sgaXMgZXhlY3V0ZWQuXG4gICAgICogVGhlIHJldHVybmVkIHByb21pc2UgaXMgaG9va2VkIHVwIHRvIHByb3BhZ2F0ZSBjYW5jZWxsYXRpb24gcmVxdWVzdHMgdXAgdGhlIGNoYWluLCBidXQgbm90IGRvd246XG4gICAgICpcbiAgICAgKiAgIC0gaWYgdGhlIHBhcmVudCBwcm9taXNlIGlzIGNhbmNlbGxlZCwgdGhlIGBvbnJlamVjdGVkYCBoYW5kbGVyIHdpbGwgYmUgaW52b2tlZCB3aXRoIGEgYENhbmNlbEVycm9yYFxuICAgICAqICAgICBhbmQgdGhlIHJldHVybmVkIHByb21pc2UgX3dpbGwgcmVzb2x2ZSByZWd1bGFybHlfIHdpdGggaXRzIHJlc3VsdDtcbiAgICAgKiAgIC0gY29udmVyc2VseSwgaWYgdGhlIHJldHVybmVkIHByb21pc2UgaXMgY2FuY2VsbGVkLCBfdGhlIHBhcmVudCBwcm9taXNlIGlzIGNhbmNlbGxlZCB0b287X1xuICAgICAqICAgICB0aGUgYG9ucmVqZWN0ZWRgIGhhbmRsZXIgd2lsbCBzdGlsbCBiZSBpbnZva2VkIHdpdGggdGhlIHBhcmVudCdzIGBDYW5jZWxFcnJvcmAsXG4gICAgICogICAgIGJ1dCBpdHMgcmVzdWx0IHdpbGwgYmUgZGlzY2FyZGVkXG4gICAgICogICAgIGFuZCB0aGUgcmV0dXJuZWQgcHJvbWlzZSB3aWxsIHJlamVjdCB3aXRoIGEgYENhbmNlbEVycm9yYCBhcyB3ZWxsLlxuICAgICAqXG4gICAgICogVGhlIHByb21pc2UgcmV0dXJuZWQgZnJvbSB7QGxpbmsgY2FuY2VsfSB3aWxsIGZ1bGZpbGwgb25seSBhZnRlciBhbGwgYXR0YWNoZWQgaGFuZGxlcnNcbiAgICAgKiB1cCB0aGUgZW50aXJlIHByb21pc2UgY2hhaW4gaGF2ZSBiZWVuIHJ1bi5cbiAgICAgKlxuICAgICAqIElmIGVpdGhlciBjYWxsYmFjayByZXR1cm5zIGEgY2FuY2VsbGFibGUgcHJvbWlzZSxcbiAgICAgKiBjYW5jZWxsYXRpb24gcmVxdWVzdHMgd2lsbCBiZSBkaXZlcnRlZCB0byBpdCxcbiAgICAgKiBhbmQgdGhlIHNwZWNpZmllZCBgb25jYW5jZWxsZWRgIGNhbGxiYWNrIHdpbGwgYmUgZGlzY2FyZGVkLlxuICAgICAqL1xuICAgIHRoZW48VFJlc3VsdDEgPSBULCBUUmVzdWx0MiA9IG5ldmVyPihvbmZ1bGZpbGxlZD86ICgodmFsdWU6IFQpID0+IFRSZXN1bHQxIHwgUHJvbWlzZUxpa2U8VFJlc3VsdDE+IHwgQ2FuY2VsbGFibGVQcm9taXNlTGlrZTxUUmVzdWx0MT4pIHwgdW5kZWZpbmVkIHwgbnVsbCwgb25yZWplY3RlZD86ICgocmVhc29uOiBhbnkpID0+IFRSZXN1bHQyIHwgUHJvbWlzZUxpa2U8VFJlc3VsdDI+IHwgQ2FuY2VsbGFibGVQcm9taXNlTGlrZTxUUmVzdWx0Mj4pIHwgdW5kZWZpbmVkIHwgbnVsbCwgb25jYW5jZWxsZWQ/OiBDYW5jZWxsYWJsZVByb21pc2VDYW5jZWxsZXIpOiBDYW5jZWxsYWJsZVByb21pc2U8VFJlc3VsdDEgfCBUUmVzdWx0Mj4ge1xuICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgQ2FuY2VsbGFibGVQcm9taXNlKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbmNlbGxhYmxlUHJvbWlzZS5wcm90b3R5cGUudGhlbiBjYWxsZWQgb24gYW4gaW52YWxpZCBvYmplY3QuXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gTk9URTogVHlwZVNjcmlwdCdzIGJ1aWx0LWluIHR5cGUgZm9yIHRoZW4gaXMgYnJva2VuLFxuICAgICAgICAvLyBhcyBpdCBhbGxvd3Mgc3BlY2lmeWluZyBhbiBhcmJpdHJhcnkgVFJlc3VsdDEgIT0gVCBldmVuIHdoZW4gb25mdWxmaWxsZWQgaXMgbm90IGEgZnVuY3Rpb24uXG4gICAgICAgIC8vIFdlIGNhbm5vdCBmaXggaXQgaWYgd2Ugd2FudCB0byBDYW5jZWxsYWJsZVByb21pc2UgdG8gaW1wbGVtZW50IFByb21pc2VMaWtlPFQ+LlxuXG4gICAgICAgIGlmICghaXNDYWxsYWJsZShvbmZ1bGZpbGxlZCkpIHsgb25mdWxmaWxsZWQgPSBpZGVudGl0eSBhcyBhbnk7IH1cbiAgICAgICAgaWYgKCFpc0NhbGxhYmxlKG9ucmVqZWN0ZWQpKSB7IG9ucmVqZWN0ZWQgPSB0aHJvd2VyOyB9XG5cbiAgICAgICAgaWYgKG9uZnVsZmlsbGVkID09PSBpZGVudGl0eSAmJiBvbnJlamVjdGVkID09IHRocm93ZXIpIHtcbiAgICAgICAgICAgIC8vIFNob3J0Y3V0IGZvciB0cml2aWFsIGFyZ3VtZW50cy5cbiAgICAgICAgICAgIHJldHVybiBuZXcgQ2FuY2VsbGFibGVQcm9taXNlKChyZXNvbHZlKSA9PiByZXNvbHZlKHRoaXMgYXMgYW55KSk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBiYXJyaWVyOiBQYXJ0aWFsPFByb21pc2VXaXRoUmVzb2x2ZXJzPHZvaWQ+PiA9IHt9O1xuICAgICAgICB0aGlzW2JhcnJpZXJTeW1dID0gYmFycmllcjtcblxuICAgICAgICByZXR1cm4gbmV3IENhbmNlbGxhYmxlUHJvbWlzZTxUUmVzdWx0MSB8IFRSZXN1bHQyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB2b2lkIHN1cGVyLnRoZW4oXG4gICAgICAgICAgICAgICAgKHZhbHVlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzW2JhcnJpZXJTeW1dID09PSBiYXJyaWVyKSB7IHRoaXNbYmFycmllclN5bV0gPSBudWxsOyB9XG4gICAgICAgICAgICAgICAgICAgIGJhcnJpZXIucmVzb2x2ZT8uKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUob25mdWxmaWxsZWQhKHZhbHVlKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIChyZWFzb24/KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzW2JhcnJpZXJTeW1dID09PSBiYXJyaWVyKSB7IHRoaXNbYmFycmllclN5bV0gPSBudWxsOyB9XG4gICAgICAgICAgICAgICAgICAgIGJhcnJpZXIucmVzb2x2ZT8uKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUob25yZWplY3RlZCEocmVhc29uKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICB9LCBhc3luYyAoY2F1c2U/KSA9PiB7XG4gICAgICAgICAgICAvL2NhbmNlbGxlZCA9IHRydWU7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHJldHVybiBvbmNhbmNlbGxlZD8uKGNhdXNlKTtcbiAgICAgICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5jYW5jZWwoY2F1c2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBdHRhY2hlcyBhIGNhbGxiYWNrIGZvciBvbmx5IHRoZSByZWplY3Rpb24gb2YgdGhlIFByb21pc2UuXG4gICAgICpcbiAgICAgKiBUaGUgb3B0aW9uYWwgYG9uY2FuY2VsbGVkYCBhcmd1bWVudCB3aWxsIGJlIGludm9rZWQgd2hlbiB0aGUgcmV0dXJuZWQgcHJvbWlzZSBpcyBjYW5jZWxsZWQsXG4gICAgICogd2l0aCB0aGUgc2FtZSBzZW1hbnRpY3MgYXMgdGhlIGBvbmNhbmNlbGxlZGAgYXJndW1lbnQgb2YgdGhlIGNvbnN0cnVjdG9yLlxuICAgICAqIFdoZW4gdGhlIHBhcmVudCBwcm9taXNlIHJlamVjdHMgb3IgaXMgY2FuY2VsbGVkLCB0aGUgYG9ucmVqZWN0ZWRgIGNhbGxiYWNrIHdpbGwgcnVuLFxuICAgICAqIF9ldmVuIGFmdGVyIHRoZSByZXR1cm5lZCBwcm9taXNlIGhhcyBiZWVuIGNhbmNlbGxlZDpfXG4gICAgICogaW4gdGhhdCBjYXNlLCBzaG91bGQgaXQgcmVqZWN0IG9yIHRocm93LCB0aGUgcmVhc29uIHdpbGwgYmUgd3JhcHBlZFxuICAgICAqIGluIGEge0BsaW5rIENhbmNlbGxlZFJlamVjdGlvbkVycm9yfSBhbmQgYnViYmxlZCB1cCBhcyBhbiB1bmhhbmRsZWQgcmVqZWN0aW9uLlxuICAgICAqXG4gICAgICogSXQgaXMgZXF1aXZhbGVudCB0b1xuICAgICAqIGBgYHRzXG4gICAgICogY2FuY2VsbGFibGVQcm9taXNlLnRoZW4odW5kZWZpbmVkLCBvbnJlamVjdGVkLCBvbmNhbmNlbGxlZCk7XG4gICAgICogYGBgXG4gICAgICogYW5kIHRoZSBzYW1lIGNhdmVhdHMgYXBwbHkuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgZm9yIHRoZSBjb21wbGV0aW9uIG9mIHRoZSBjYWxsYmFjay5cbiAgICAgKiBDYW5jZWxsYXRpb24gcmVxdWVzdHMgb24gdGhlIHJldHVybmVkIHByb21pc2VcbiAgICAgKiB3aWxsIHByb3BhZ2F0ZSB1cCB0aGUgY2hhaW4gdG8gdGhlIHBhcmVudCBwcm9taXNlLFxuICAgICAqIGJ1dCBub3QgaW4gdGhlIG90aGVyIGRpcmVjdGlvbi5cbiAgICAgKlxuICAgICAqIFRoZSBwcm9taXNlIHJldHVybmVkIGZyb20ge0BsaW5rIGNhbmNlbH0gd2lsbCBmdWxmaWxsIG9ubHkgYWZ0ZXIgYWxsIGF0dGFjaGVkIGhhbmRsZXJzXG4gICAgICogdXAgdGhlIGVudGlyZSBwcm9taXNlIGNoYWluIGhhdmUgYmVlbiBydW4uXG4gICAgICpcbiAgICAgKiBJZiBgb25yZWplY3RlZGAgcmV0dXJucyBhIGNhbmNlbGxhYmxlIHByb21pc2UsXG4gICAgICogY2FuY2VsbGF0aW9uIHJlcXVlc3RzIHdpbGwgYmUgZGl2ZXJ0ZWQgdG8gaXQsXG4gICAgICogYW5kIHRoZSBzcGVjaWZpZWQgYG9uY2FuY2VsbGVkYCBjYWxsYmFjayB3aWxsIGJlIGRpc2NhcmRlZC5cbiAgICAgKiBTZWUge0BsaW5rIHRoZW59IGZvciBtb3JlIGRldGFpbHMuXG4gICAgICovXG4gICAgY2F0Y2g8VFJlc3VsdCA9IG5ldmVyPihvbnJlamVjdGVkPzogKChyZWFzb246IGFueSkgPT4gKFByb21pc2VMaWtlPFRSZXN1bHQ+IHwgVFJlc3VsdCkpIHwgdW5kZWZpbmVkIHwgbnVsbCwgb25jYW5jZWxsZWQ/OiBDYW5jZWxsYWJsZVByb21pc2VDYW5jZWxsZXIpOiBDYW5jZWxsYWJsZVByb21pc2U8VCB8IFRSZXN1bHQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMudGhlbih1bmRlZmluZWQsIG9ucmVqZWN0ZWQsIG9uY2FuY2VsbGVkKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBdHRhY2hlcyBhIGNhbGxiYWNrIHRoYXQgaXMgaW52b2tlZCB3aGVuIHRoZSBDYW5jZWxsYWJsZVByb21pc2UgaXMgc2V0dGxlZCAoZnVsZmlsbGVkIG9yIHJlamVjdGVkKS4gVGhlXG4gICAgICogcmVzb2x2ZWQgdmFsdWUgY2Fubm90IGJlIGFjY2Vzc2VkIG9yIG1vZGlmaWVkIGZyb20gdGhlIGNhbGxiYWNrLlxuICAgICAqIFRoZSByZXR1cm5lZCBwcm9taXNlIHdpbGwgc2V0dGxlIGluIHRoZSBzYW1lIHN0YXRlIGFzIHRoZSBvcmlnaW5hbCBvbmVcbiAgICAgKiBhZnRlciB0aGUgcHJvdmlkZWQgY2FsbGJhY2sgaGFzIGNvbXBsZXRlZCBleGVjdXRpb24sXG4gICAgICogdW5sZXNzIHRoZSBjYWxsYmFjayB0aHJvd3Mgb3IgcmV0dXJucyBhIHJlamVjdGluZyBwcm9taXNlLFxuICAgICAqIGluIHdoaWNoIGNhc2UgdGhlIHJldHVybmVkIHByb21pc2Ugd2lsbCByZWplY3QgYXMgd2VsbC5cbiAgICAgKlxuICAgICAqIFRoZSBvcHRpb25hbCBgb25jYW5jZWxsZWRgIGFyZ3VtZW50IHdpbGwgYmUgaW52b2tlZCB3aGVuIHRoZSByZXR1cm5lZCBwcm9taXNlIGlzIGNhbmNlbGxlZCxcbiAgICAgKiB3aXRoIHRoZSBzYW1lIHNlbWFudGljcyBhcyB0aGUgYG9uY2FuY2VsbGVkYCBhcmd1bWVudCBvZiB0aGUgY29uc3RydWN0b3IuXG4gICAgICogT25jZSB0aGUgcGFyZW50IHByb21pc2Ugc2V0dGxlcywgdGhlIGBvbmZpbmFsbHlgIGNhbGxiYWNrIHdpbGwgcnVuLFxuICAgICAqIF9ldmVuIGFmdGVyIHRoZSByZXR1cm5lZCBwcm9taXNlIGhhcyBiZWVuIGNhbmNlbGxlZDpfXG4gICAgICogaW4gdGhhdCBjYXNlLCBzaG91bGQgaXQgcmVqZWN0IG9yIHRocm93LCB0aGUgcmVhc29uIHdpbGwgYmUgd3JhcHBlZFxuICAgICAqIGluIGEge0BsaW5rIENhbmNlbGxlZFJlamVjdGlvbkVycm9yfSBhbmQgYnViYmxlZCB1cCBhcyBhbiB1bmhhbmRsZWQgcmVqZWN0aW9uLlxuICAgICAqXG4gICAgICogVGhpcyBtZXRob2QgaXMgaW1wbGVtZW50ZWQgaW4gdGVybXMgb2Yge0BsaW5rIHRoZW59IGFuZCB0aGUgc2FtZSBjYXZlYXRzIGFwcGx5LlxuICAgICAqIEl0IGlzIHBvbHlmaWxsZWQsIGhlbmNlIGF2YWlsYWJsZSBpbiBldmVyeSBPUy93ZWJ2aWV3IHZlcnNpb24uXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgZm9yIHRoZSBjb21wbGV0aW9uIG9mIHRoZSBjYWxsYmFjay5cbiAgICAgKiBDYW5jZWxsYXRpb24gcmVxdWVzdHMgb24gdGhlIHJldHVybmVkIHByb21pc2VcbiAgICAgKiB3aWxsIHByb3BhZ2F0ZSB1cCB0aGUgY2hhaW4gdG8gdGhlIHBhcmVudCBwcm9taXNlLFxuICAgICAqIGJ1dCBub3QgaW4gdGhlIG90aGVyIGRpcmVjdGlvbi5cbiAgICAgKlxuICAgICAqIFRoZSBwcm9taXNlIHJldHVybmVkIGZyb20ge0BsaW5rIGNhbmNlbH0gd2lsbCBmdWxmaWxsIG9ubHkgYWZ0ZXIgYWxsIGF0dGFjaGVkIGhhbmRsZXJzXG4gICAgICogdXAgdGhlIGVudGlyZSBwcm9taXNlIGNoYWluIGhhdmUgYmVlbiBydW4uXG4gICAgICpcbiAgICAgKiBJZiBgb25maW5hbGx5YCByZXR1cm5zIGEgY2FuY2VsbGFibGUgcHJvbWlzZSxcbiAgICAgKiBjYW5jZWxsYXRpb24gcmVxdWVzdHMgd2lsbCBiZSBkaXZlcnRlZCB0byBpdCxcbiAgICAgKiBhbmQgdGhlIHNwZWNpZmllZCBgb25jYW5jZWxsZWRgIGNhbGxiYWNrIHdpbGwgYmUgZGlzY2FyZGVkLlxuICAgICAqIFNlZSB7QGxpbmsgdGhlbn0gZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgKi9cbiAgICBmaW5hbGx5KG9uZmluYWxseT86ICgoKSA9PiB2b2lkKSB8IHVuZGVmaW5lZCB8IG51bGwsIG9uY2FuY2VsbGVkPzogQ2FuY2VsbGFibGVQcm9taXNlQ2FuY2VsbGVyKTogQ2FuY2VsbGFibGVQcm9taXNlPFQ+IHtcbiAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIENhbmNlbGxhYmxlUHJvbWlzZSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5jZWxsYWJsZVByb21pc2UucHJvdG90eXBlLmZpbmFsbHkgY2FsbGVkIG9uIGFuIGludmFsaWQgb2JqZWN0LlwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghaXNDYWxsYWJsZShvbmZpbmFsbHkpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy50aGVuKG9uZmluYWxseSwgb25maW5hbGx5LCBvbmNhbmNlbGxlZCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy50aGVuKFxuICAgICAgICAgICAgKHZhbHVlKSA9PiBDYW5jZWxsYWJsZVByb21pc2UucmVzb2x2ZShvbmZpbmFsbHkoKSkudGhlbigoKSA9PiB2YWx1ZSksXG4gICAgICAgICAgICAocmVhc29uPykgPT4gQ2FuY2VsbGFibGVQcm9taXNlLnJlc29sdmUob25maW5hbGx5KCkpLnRoZW4oKCkgPT4geyB0aHJvdyByZWFzb247IH0pLFxuICAgICAgICAgICAgb25jYW5jZWxsZWQsXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogV2UgdXNlIHRoZSBgW1N5bWJvbC5zcGVjaWVzXWAgc3RhdGljIHByb3BlcnR5LCBpZiBhdmFpbGFibGUsXG4gICAgICogdG8gZGlzYWJsZSB0aGUgYnVpbHQtaW4gYXV0b21hdGljIHN1YmNsYXNzaW5nIGZlYXR1cmVzIGZyb20ge0BsaW5rIFByb21pc2V9LlxuICAgICAqIEl0IGlzIGNyaXRpY2FsIGZvciBwZXJmb3JtYW5jZSByZWFzb25zIHRoYXQgZXh0ZW5kZXJzIGRvIG5vdCBvdmVycmlkZSB0aGlzLlxuICAgICAqIE9uY2UgdGhlIHByb3Bvc2FsIGF0IGh0dHBzOi8vZ2l0aHViLmNvbS90YzM5L3Byb3Bvc2FsLXJtLWJ1aWx0aW4tc3ViY2xhc3NpbmdcbiAgICAgKiBpcyBlaXRoZXIgYWNjZXB0ZWQgb3IgcmV0aXJlZCwgdGhpcyBpbXBsZW1lbnRhdGlvbiB3aWxsIGhhdmUgdG8gYmUgcmV2aXNlZCBhY2NvcmRpbmdseS5cbiAgICAgKlxuICAgICAqIEBpZ25vcmVcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0IFtzcGVjaWVzXSgpIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIENhbmNlbGxhYmxlUHJvbWlzZSB0aGF0IGlzIHJlc29sdmVkIHdpdGggYW4gYXJyYXkgb2YgcmVzdWx0c1xuICAgICAqIHdoZW4gYWxsIG9mIHRoZSBwcm92aWRlZCBQcm9taXNlcyByZXNvbHZlLCBvciByZWplY3RlZCB3aGVuIGFueSBQcm9taXNlIGlzIHJlamVjdGVkLlxuICAgICAqXG4gICAgICogRXZlcnkgb25lIG9mIHRoZSBwcm92aWRlZCBvYmplY3RzIHRoYXQgaXMgYSB0aGVuYWJsZSBfYW5kXyBjYW5jZWxsYWJsZSBvYmplY3RcbiAgICAgKiB3aWxsIGJlIGNhbmNlbGxlZCB3aGVuIHRoZSByZXR1cm5lZCBwcm9taXNlIGlzIGNhbmNlbGxlZCwgd2l0aCB0aGUgc2FtZSBjYXVzZS5cbiAgICAgKlxuICAgICAqIEBncm91cCBTdGF0aWMgTWV0aG9kc1xuICAgICAqL1xuICAgIHN0YXRpYyBhbGw8VD4odmFsdWVzOiBJdGVyYWJsZTxUIHwgUHJvbWlzZUxpa2U8VD4+KTogQ2FuY2VsbGFibGVQcm9taXNlPEF3YWl0ZWQ8VD5bXT47XG4gICAgc3RhdGljIGFsbDxUIGV4dGVuZHMgcmVhZG9ubHkgdW5rbm93bltdIHwgW10+KHZhbHVlczogVCk6IENhbmNlbGxhYmxlUHJvbWlzZTx7IC1yZWFkb25seSBbUCBpbiBrZXlvZiBUXTogQXdhaXRlZDxUW1BdPjsgfT47XG4gICAgc3RhdGljIGFsbDxUIGV4dGVuZHMgSXRlcmFibGU8dW5rbm93bj4gfCBBcnJheUxpa2U8dW5rbm93bj4+KHZhbHVlczogVCk6IENhbmNlbGxhYmxlUHJvbWlzZTx1bmtub3duPiB7XG4gICAgICAgIGxldCBjb2xsZWN0ZWQgPSBBcnJheS5mcm9tKHZhbHVlcyk7XG4gICAgICAgIGNvbnN0IHByb21pc2UgPSBjb2xsZWN0ZWQubGVuZ3RoID09PSAwXG4gICAgICAgICAgICA/IENhbmNlbGxhYmxlUHJvbWlzZS5yZXNvbHZlKGNvbGxlY3RlZClcbiAgICAgICAgICAgIDogbmV3IENhbmNlbGxhYmxlUHJvbWlzZTx1bmtub3duPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICAgICAgdm9pZCBQcm9taXNlLmFsbChjb2xsZWN0ZWQpLnRoZW4ocmVzb2x2ZSwgcmVqZWN0KTtcbiAgICAgICAgICAgIH0sIChjYXVzZT8pOiBQcm9taXNlPHZvaWQ+ID0+IGNhbmNlbEFsbChwcm9taXNlLCBjb2xsZWN0ZWQsIGNhdXNlKSk7XG4gICAgICAgIHJldHVybiBwcm9taXNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBDYW5jZWxsYWJsZVByb21pc2UgdGhhdCBpcyByZXNvbHZlZCB3aXRoIGFuIGFycmF5IG9mIHJlc3VsdHNcbiAgICAgKiB3aGVuIGFsbCBvZiB0aGUgcHJvdmlkZWQgUHJvbWlzZXMgcmVzb2x2ZSBvciByZWplY3QuXG4gICAgICpcbiAgICAgKiBFdmVyeSBvbmUgb2YgdGhlIHByb3ZpZGVkIG9iamVjdHMgdGhhdCBpcyBhIHRoZW5hYmxlIF9hbmRfIGNhbmNlbGxhYmxlIG9iamVjdFxuICAgICAqIHdpbGwgYmUgY2FuY2VsbGVkIHdoZW4gdGhlIHJldHVybmVkIHByb21pc2UgaXMgY2FuY2VsbGVkLCB3aXRoIHRoZSBzYW1lIGNhdXNlLlxuICAgICAqXG4gICAgICogQGdyb3VwIFN0YXRpYyBNZXRob2RzXG4gICAgICovXG4gICAgc3RhdGljIGFsbFNldHRsZWQ8VD4odmFsdWVzOiBJdGVyYWJsZTxUIHwgUHJvbWlzZUxpa2U8VD4+KTogQ2FuY2VsbGFibGVQcm9taXNlPFByb21pc2VTZXR0bGVkUmVzdWx0PEF3YWl0ZWQ8VD4+W10+O1xuICAgIHN0YXRpYyBhbGxTZXR0bGVkPFQgZXh0ZW5kcyByZWFkb25seSB1bmtub3duW10gfCBbXT4odmFsdWVzOiBUKTogQ2FuY2VsbGFibGVQcm9taXNlPHsgLXJlYWRvbmx5IFtQIGluIGtleW9mIFRdOiBQcm9taXNlU2V0dGxlZFJlc3VsdDxBd2FpdGVkPFRbUF0+PjsgfT47XG4gICAgc3RhdGljIGFsbFNldHRsZWQ8VCBleHRlbmRzIEl0ZXJhYmxlPHVua25vd24+IHwgQXJyYXlMaWtlPHVua25vd24+Pih2YWx1ZXM6IFQpOiBDYW5jZWxsYWJsZVByb21pc2U8dW5rbm93bj4ge1xuICAgICAgICBsZXQgY29sbGVjdGVkID0gQXJyYXkuZnJvbSh2YWx1ZXMpO1xuICAgICAgICBjb25zdCBwcm9taXNlID0gY29sbGVjdGVkLmxlbmd0aCA9PT0gMFxuICAgICAgICAgICAgPyBDYW5jZWxsYWJsZVByb21pc2UucmVzb2x2ZShjb2xsZWN0ZWQpXG4gICAgICAgICAgICA6IG5ldyBDYW5jZWxsYWJsZVByb21pc2U8dW5rbm93bj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgICAgIHZvaWQgUHJvbWlzZS5hbGxTZXR0bGVkKGNvbGxlY3RlZCkudGhlbihyZXNvbHZlLCByZWplY3QpO1xuICAgICAgICAgICAgfSwgKGNhdXNlPyk6IFByb21pc2U8dm9pZD4gPT4gY2FuY2VsQWxsKHByb21pc2UsIGNvbGxlY3RlZCwgY2F1c2UpKTtcbiAgICAgICAgcmV0dXJuIHByb21pc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGFueSBmdW5jdGlvbiByZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGlzIGZ1bGZpbGxlZCBieSB0aGUgZmlyc3QgZ2l2ZW4gcHJvbWlzZSB0byBiZSBmdWxmaWxsZWQsXG4gICAgICogb3IgcmVqZWN0ZWQgd2l0aCBhbiBBZ2dyZWdhdGVFcnJvciBjb250YWluaW5nIGFuIGFycmF5IG9mIHJlamVjdGlvbiByZWFzb25zXG4gICAgICogaWYgYWxsIG9mIHRoZSBnaXZlbiBwcm9taXNlcyBhcmUgcmVqZWN0ZWQuXG4gICAgICogSXQgcmVzb2x2ZXMgYWxsIGVsZW1lbnRzIG9mIHRoZSBwYXNzZWQgaXRlcmFibGUgdG8gcHJvbWlzZXMgYXMgaXQgcnVucyB0aGlzIGFsZ29yaXRobS5cbiAgICAgKlxuICAgICAqIEV2ZXJ5IG9uZSBvZiB0aGUgcHJvdmlkZWQgb2JqZWN0cyB0aGF0IGlzIGEgdGhlbmFibGUgX2FuZF8gY2FuY2VsbGFibGUgb2JqZWN0XG4gICAgICogd2lsbCBiZSBjYW5jZWxsZWQgd2hlbiB0aGUgcmV0dXJuZWQgcHJvbWlzZSBpcyBjYW5jZWxsZWQsIHdpdGggdGhlIHNhbWUgY2F1c2UuXG4gICAgICpcbiAgICAgKiBAZ3JvdXAgU3RhdGljIE1ldGhvZHNcbiAgICAgKi9cbiAgICBzdGF0aWMgYW55PFQ+KHZhbHVlczogSXRlcmFibGU8VCB8IFByb21pc2VMaWtlPFQ+Pik6IENhbmNlbGxhYmxlUHJvbWlzZTxBd2FpdGVkPFQ+PjtcbiAgICBzdGF0aWMgYW55PFQgZXh0ZW5kcyByZWFkb25seSB1bmtub3duW10gfCBbXT4odmFsdWVzOiBUKTogQ2FuY2VsbGFibGVQcm9taXNlPEF3YWl0ZWQ8VFtudW1iZXJdPj47XG4gICAgc3RhdGljIGFueTxUIGV4dGVuZHMgSXRlcmFibGU8dW5rbm93bj4gfCBBcnJheUxpa2U8dW5rbm93bj4+KHZhbHVlczogVCk6IENhbmNlbGxhYmxlUHJvbWlzZTx1bmtub3duPiB7XG4gICAgICAgIGxldCBjb2xsZWN0ZWQgPSBBcnJheS5mcm9tKHZhbHVlcyk7XG4gICAgICAgIGNvbnN0IHByb21pc2UgPSBjb2xsZWN0ZWQubGVuZ3RoID09PSAwXG4gICAgICAgICAgICA/IENhbmNlbGxhYmxlUHJvbWlzZS5yZXNvbHZlKGNvbGxlY3RlZClcbiAgICAgICAgICAgIDogbmV3IENhbmNlbGxhYmxlUHJvbWlzZTx1bmtub3duPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICAgICAgdm9pZCBQcm9taXNlLmFueShjb2xsZWN0ZWQpLnRoZW4ocmVzb2x2ZSwgcmVqZWN0KTtcbiAgICAgICAgICAgIH0sIChjYXVzZT8pOiBQcm9taXNlPHZvaWQ+ID0+IGNhbmNlbEFsbChwcm9taXNlLCBjb2xsZWN0ZWQsIGNhdXNlKSk7XG4gICAgICAgIHJldHVybiBwcm9taXNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBQcm9taXNlIHRoYXQgaXMgcmVzb2x2ZWQgb3IgcmVqZWN0ZWQgd2hlbiBhbnkgb2YgdGhlIHByb3ZpZGVkIFByb21pc2VzIGFyZSByZXNvbHZlZCBvciByZWplY3RlZC5cbiAgICAgKlxuICAgICAqIEV2ZXJ5IG9uZSBvZiB0aGUgcHJvdmlkZWQgb2JqZWN0cyB0aGF0IGlzIGEgdGhlbmFibGUgX2FuZF8gY2FuY2VsbGFibGUgb2JqZWN0XG4gICAgICogd2lsbCBiZSBjYW5jZWxsZWQgd2hlbiB0aGUgcmV0dXJuZWQgcHJvbWlzZSBpcyBjYW5jZWxsZWQsIHdpdGggdGhlIHNhbWUgY2F1c2UuXG4gICAgICpcbiAgICAgKiBAZ3JvdXAgU3RhdGljIE1ldGhvZHNcbiAgICAgKi9cbiAgICBzdGF0aWMgcmFjZTxUPih2YWx1ZXM6IEl0ZXJhYmxlPFQgfCBQcm9taXNlTGlrZTxUPj4pOiBDYW5jZWxsYWJsZVByb21pc2U8QXdhaXRlZDxUPj47XG4gICAgc3RhdGljIHJhY2U8VCBleHRlbmRzIHJlYWRvbmx5IHVua25vd25bXSB8IFtdPih2YWx1ZXM6IFQpOiBDYW5jZWxsYWJsZVByb21pc2U8QXdhaXRlZDxUW251bWJlcl0+PjtcbiAgICBzdGF0aWMgcmFjZTxUIGV4dGVuZHMgSXRlcmFibGU8dW5rbm93bj4gfCBBcnJheUxpa2U8dW5rbm93bj4+KHZhbHVlczogVCk6IENhbmNlbGxhYmxlUHJvbWlzZTx1bmtub3duPiB7XG4gICAgICAgIGxldCBjb2xsZWN0ZWQgPSBBcnJheS5mcm9tKHZhbHVlcyk7XG4gICAgICAgIGNvbnN0IHByb21pc2UgPSBuZXcgQ2FuY2VsbGFibGVQcm9taXNlPHVua25vd24+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHZvaWQgUHJvbWlzZS5yYWNlKGNvbGxlY3RlZCkudGhlbihyZXNvbHZlLCByZWplY3QpO1xuICAgICAgICB9LCAoY2F1c2U/KTogUHJvbWlzZTx2b2lkPiA9PiBjYW5jZWxBbGwocHJvbWlzZSwgY29sbGVjdGVkLCBjYXVzZSkpO1xuICAgICAgICByZXR1cm4gcHJvbWlzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IGNhbmNlbGxlZCBDYW5jZWxsYWJsZVByb21pc2UgZm9yIHRoZSBwcm92aWRlZCBjYXVzZS5cbiAgICAgKlxuICAgICAqIEBncm91cCBTdGF0aWMgTWV0aG9kc1xuICAgICAqL1xuICAgIHN0YXRpYyBjYW5jZWw8VCA9IG5ldmVyPihjYXVzZT86IGFueSk6IENhbmNlbGxhYmxlUHJvbWlzZTxUPiB7XG4gICAgICAgIGNvbnN0IHAgPSBuZXcgQ2FuY2VsbGFibGVQcm9taXNlPFQ+KCgpID0+IHt9KTtcbiAgICAgICAgcC5jYW5jZWwoY2F1c2UpO1xuICAgICAgICByZXR1cm4gcDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IENhbmNlbGxhYmxlUHJvbWlzZSB0aGF0IGNhbmNlbHNcbiAgICAgKiBhZnRlciB0aGUgc3BlY2lmaWVkIHRpbWVvdXQsIHdpdGggdGhlIHByb3ZpZGVkIGNhdXNlLlxuICAgICAqXG4gICAgICogSWYgdGhlIHtAbGluayBBYm9ydFNpZ25hbC50aW1lb3V0fSBmYWN0b3J5IG1ldGhvZCBpcyBhdmFpbGFibGUsXG4gICAgICogaXQgaXMgdXNlZCB0byBiYXNlIHRoZSB0aW1lb3V0IG9uIF9hY3RpdmVfIHRpbWUgcmF0aGVyIHRoYW4gX2VsYXBzZWRfIHRpbWUuXG4gICAgICogT3RoZXJ3aXNlLCBgdGltZW91dGAgZmFsbHMgYmFjayB0byB7QGxpbmsgc2V0VGltZW91dH0uXG4gICAgICpcbiAgICAgKiBAZ3JvdXAgU3RhdGljIE1ldGhvZHNcbiAgICAgKi9cbiAgICBzdGF0aWMgdGltZW91dDxUID0gbmV2ZXI+KG1pbGxpc2Vjb25kczogbnVtYmVyLCBjYXVzZT86IGFueSk6IENhbmNlbGxhYmxlUHJvbWlzZTxUPiB7XG4gICAgICAgIGNvbnN0IHByb21pc2UgPSBuZXcgQ2FuY2VsbGFibGVQcm9taXNlPFQ+KCgpID0+IHt9KTtcbiAgICAgICAgaWYgKEFib3J0U2lnbmFsICYmIHR5cGVvZiBBYm9ydFNpZ25hbCA9PT0gJ2Z1bmN0aW9uJyAmJiBBYm9ydFNpZ25hbC50aW1lb3V0ICYmIHR5cGVvZiBBYm9ydFNpZ25hbC50aW1lb3V0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICBBYm9ydFNpZ25hbC50aW1lb3V0KG1pbGxpc2Vjb25kcykuYWRkRXZlbnRMaXN0ZW5lcignYWJvcnQnLCAoKSA9PiB2b2lkIHByb21pc2UuY2FuY2VsKGNhdXNlKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHZvaWQgcHJvbWlzZS5jYW5jZWwoY2F1c2UpLCBtaWxsaXNlY29uZHMpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBwcm9taXNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgQ2FuY2VsbGFibGVQcm9taXNlIHRoYXQgcmVzb2x2ZXMgYWZ0ZXIgdGhlIHNwZWNpZmllZCB0aW1lb3V0LlxuICAgICAqIFRoZSByZXR1cm5lZCBwcm9taXNlIGNhbiBiZSBjYW5jZWxsZWQgd2l0aG91dCBjb25zZXF1ZW5jZXMuXG4gICAgICpcbiAgICAgKiBAZ3JvdXAgU3RhdGljIE1ldGhvZHNcbiAgICAgKi9cbiAgICBzdGF0aWMgc2xlZXAobWlsbGlzZWNvbmRzOiBudW1iZXIpOiBDYW5jZWxsYWJsZVByb21pc2U8dm9pZD47XG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyBDYW5jZWxsYWJsZVByb21pc2UgdGhhdCByZXNvbHZlcyBhZnRlclxuICAgICAqIHRoZSBzcGVjaWZpZWQgdGltZW91dCwgd2l0aCB0aGUgcHJvdmlkZWQgdmFsdWUuXG4gICAgICogVGhlIHJldHVybmVkIHByb21pc2UgY2FuIGJlIGNhbmNlbGxlZCB3aXRob3V0IGNvbnNlcXVlbmNlcy5cbiAgICAgKlxuICAgICAqIEBncm91cCBTdGF0aWMgTWV0aG9kc1xuICAgICAqL1xuICAgIHN0YXRpYyBzbGVlcDxUPihtaWxsaXNlY29uZHM6IG51bWJlciwgdmFsdWU6IFQpOiBDYW5jZWxsYWJsZVByb21pc2U8VD47XG4gICAgc3RhdGljIHNsZWVwPFQgPSB2b2lkPihtaWxsaXNlY29uZHM6IG51bWJlciwgdmFsdWU/OiBUKTogQ2FuY2VsbGFibGVQcm9taXNlPFQ+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBDYW5jZWxsYWJsZVByb21pc2U8VD4oKHJlc29sdmUpID0+IHtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gcmVzb2x2ZSh2YWx1ZSEpLCBtaWxsaXNlY29uZHMpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IHJlamVjdGVkIENhbmNlbGxhYmxlUHJvbWlzZSBmb3IgdGhlIHByb3ZpZGVkIHJlYXNvbi5cbiAgICAgKlxuICAgICAqIEBncm91cCBTdGF0aWMgTWV0aG9kc1xuICAgICAqL1xuICAgIHN0YXRpYyByZWplY3Q8VCA9IG5ldmVyPihyZWFzb24/OiBhbnkpOiBDYW5jZWxsYWJsZVByb21pc2U8VD4ge1xuICAgICAgICByZXR1cm4gbmV3IENhbmNlbGxhYmxlUHJvbWlzZTxUPigoXywgcmVqZWN0KSA9PiByZWplY3QocmVhc29uKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyByZXNvbHZlZCBDYW5jZWxsYWJsZVByb21pc2UuXG4gICAgICpcbiAgICAgKiBAZ3JvdXAgU3RhdGljIE1ldGhvZHNcbiAgICAgKi9cbiAgICBzdGF0aWMgcmVzb2x2ZSgpOiBDYW5jZWxsYWJsZVByb21pc2U8dm9pZD47XG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyByZXNvbHZlZCBDYW5jZWxsYWJsZVByb21pc2UgZm9yIHRoZSBwcm92aWRlZCB2YWx1ZS5cbiAgICAgKlxuICAgICAqIEBncm91cCBTdGF0aWMgTWV0aG9kc1xuICAgICAqL1xuICAgIHN0YXRpYyByZXNvbHZlPFQ+KHZhbHVlOiBUKTogQ2FuY2VsbGFibGVQcm9taXNlPEF3YWl0ZWQ8VD4+O1xuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgcmVzb2x2ZWQgQ2FuY2VsbGFibGVQcm9taXNlIGZvciB0aGUgcHJvdmlkZWQgdmFsdWUuXG4gICAgICpcbiAgICAgKiBAZ3JvdXAgU3RhdGljIE1ldGhvZHNcbiAgICAgKi9cbiAgICBzdGF0aWMgcmVzb2x2ZTxUPih2YWx1ZTogVCB8IFByb21pc2VMaWtlPFQ+KTogQ2FuY2VsbGFibGVQcm9taXNlPEF3YWl0ZWQ8VD4+O1xuICAgIHN0YXRpYyByZXNvbHZlPFQgPSB2b2lkPih2YWx1ZT86IFQgfCBQcm9taXNlTGlrZTxUPik6IENhbmNlbGxhYmxlUHJvbWlzZTxBd2FpdGVkPFQ+PiB7XG4gICAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIENhbmNlbGxhYmxlUHJvbWlzZSkge1xuICAgICAgICAgICAgLy8gT3B0aW1pc2UgZm9yIGNhbmNlbGxhYmxlIHByb21pc2VzLlxuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXcgQ2FuY2VsbGFibGVQcm9taXNlPGFueT4oKHJlc29sdmUpID0+IHJlc29sdmUodmFsdWUpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IENhbmNlbGxhYmxlUHJvbWlzZSBhbmQgcmV0dXJucyBpdCBpbiBhbiBvYmplY3QsIGFsb25nIHdpdGggaXRzIHJlc29sdmUgYW5kIHJlamVjdCBmdW5jdGlvbnNcbiAgICAgKiBhbmQgYSBnZXR0ZXIvc2V0dGVyIGZvciB0aGUgY2FuY2VsbGF0aW9uIGNhbGxiYWNrLlxuICAgICAqXG4gICAgICogVGhpcyBtZXRob2QgaXMgcG9seWZpbGxlZCwgaGVuY2UgYXZhaWxhYmxlIGluIGV2ZXJ5IE9TL3dlYnZpZXcgdmVyc2lvbi5cbiAgICAgKlxuICAgICAqIEBncm91cCBTdGF0aWMgTWV0aG9kc1xuICAgICAqL1xuICAgIHN0YXRpYyB3aXRoUmVzb2x2ZXJzPFQ+KCk6IENhbmNlbGxhYmxlUHJvbWlzZVdpdGhSZXNvbHZlcnM8VD4ge1xuICAgICAgICBsZXQgcmVzdWx0OiBDYW5jZWxsYWJsZVByb21pc2VXaXRoUmVzb2x2ZXJzPFQ+ID0geyBvbmNhbmNlbGxlZDogbnVsbCB9IGFzIGFueTtcbiAgICAgICAgcmVzdWx0LnByb21pc2UgPSBuZXcgQ2FuY2VsbGFibGVQcm9taXNlPFQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHJlc3VsdC5yZXNvbHZlID0gcmVzb2x2ZTtcbiAgICAgICAgICAgIHJlc3VsdC5yZWplY3QgPSByZWplY3Q7XG4gICAgICAgIH0sIChjYXVzZT86IGFueSkgPT4geyByZXN1bHQub25jYW5jZWxsZWQ/LihjYXVzZSk7IH0pO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgY2FsbGJhY2sgdGhhdCBpbXBsZW1lbnRzIHRoZSBjYW5jZWxsYXRpb24gYWxnb3JpdGhtIGZvciB0aGUgZ2l2ZW4gY2FuY2VsbGFibGUgcHJvbWlzZS5cbiAqIFRoZSBwcm9taXNlIHJldHVybmVkIGZyb20gdGhlIHJlc3VsdGluZyBmdW5jdGlvbiBkb2VzIG5vdCByZWplY3QuXG4gKi9cbmZ1bmN0aW9uIGNhbmNlbGxlckZvcjxUPihwcm9taXNlOiBDYW5jZWxsYWJsZVByb21pc2VXaXRoUmVzb2x2ZXJzPFQ+LCBzdGF0ZTogQ2FuY2VsbGFibGVQcm9taXNlU3RhdGUpIHtcbiAgICBsZXQgY2FuY2VsbGF0aW9uUHJvbWlzZTogdm9pZCB8IFByb21pc2VMaWtlPHZvaWQ+ID0gdW5kZWZpbmVkO1xuXG4gICAgcmV0dXJuIChyZWFzb246IENhbmNlbEVycm9yKTogdm9pZCB8IFByb21pc2VMaWtlPHZvaWQ+ID0+IHtcbiAgICAgICAgaWYgKCFzdGF0ZS5zZXR0bGVkKSB7XG4gICAgICAgICAgICBzdGF0ZS5zZXR0bGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHN0YXRlLnJlYXNvbiA9IHJlYXNvbjtcbiAgICAgICAgICAgIHByb21pc2UucmVqZWN0KHJlYXNvbik7XG5cbiAgICAgICAgICAgIC8vIEF0dGFjaCBhbiBlcnJvciBoYW5kbGVyIHRoYXQgaWdub3JlcyB0aGlzIHNwZWNpZmljIHJlamVjdGlvbiByZWFzb24gYW5kIG5vdGhpbmcgZWxzZS5cbiAgICAgICAgICAgIC8vIEluIHRoZW9yeSwgYSBzYW5lIHVuZGVybHlpbmcgaW1wbGVtZW50YXRpb24gYXQgdGhpcyBwb2ludFxuICAgICAgICAgICAgLy8gc2hvdWxkIGFsd2F5cyByZWplY3Qgd2l0aCBvdXIgY2FuY2VsbGF0aW9uIHJlYXNvbixcbiAgICAgICAgICAgIC8vIGhlbmNlIHRoZSBoYW5kbGVyIHdpbGwgbmV2ZXIgdGhyb3cuXG4gICAgICAgICAgICB2b2lkIFByb21pc2UucHJvdG90eXBlLnRoZW4uY2FsbChwcm9taXNlLnByb21pc2UsIHVuZGVmaW5lZCwgKGVycikgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnIgIT09IHJlYXNvbikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiByZWFzb24gaXMgbm90IHNldCwgdGhlIHByb21pc2UgcmVzb2x2ZWQgcmVndWxhcmx5LCBoZW5jZSB3ZSBtdXN0IG5vdCBjYWxsIG9uY2FuY2VsbGVkLlxuICAgICAgICAvLyBJZiBvbmNhbmNlbGxlZCBpcyB1bnNldCwgbm8gbmVlZCB0byBnbyBhbnkgZnVydGhlci5cbiAgICAgICAgaWYgKCFzdGF0ZS5yZWFzb24gfHwgIXByb21pc2Uub25jYW5jZWxsZWQpIHsgcmV0dXJuOyB9XG5cbiAgICAgICAgY2FuY2VsbGF0aW9uUHJvbWlzZSA9IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlKSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHJlc29sdmUocHJvbWlzZS5vbmNhbmNlbGxlZCEoc3RhdGUucmVhc29uIS5jYXVzZSkpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgUHJvbWlzZS5yZWplY3QobmV3IENhbmNlbGxlZFJlamVjdGlvbkVycm9yKHByb21pc2UucHJvbWlzZSwgZXJyLCBcIlVuaGFuZGxlZCBleGNlcHRpb24gaW4gb25jYW5jZWxsZWQgY2FsbGJhY2suXCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSkuY2F0Y2goKHJlYXNvbj8pID0+IHtcbiAgICAgICAgICAgIFByb21pc2UucmVqZWN0KG5ldyBDYW5jZWxsZWRSZWplY3Rpb25FcnJvcihwcm9taXNlLnByb21pc2UsIHJlYXNvbiwgXCJVbmhhbmRsZWQgcmVqZWN0aW9uIGluIG9uY2FuY2VsbGVkIGNhbGxiYWNrLlwiKSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIFVuc2V0IG9uY2FuY2VsbGVkIHRvIHByZXZlbnQgcmVwZWF0ZWQgY2FsbHMuXG4gICAgICAgIHByb21pc2Uub25jYW5jZWxsZWQgPSBudWxsO1xuXG4gICAgICAgIHJldHVybiBjYW5jZWxsYXRpb25Qcm9taXNlO1xuICAgIH1cbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgY2FsbGJhY2sgdGhhdCBpbXBsZW1lbnRzIHRoZSByZXNvbHV0aW9uIGFsZ29yaXRobSBmb3IgdGhlIGdpdmVuIGNhbmNlbGxhYmxlIHByb21pc2UuXG4gKi9cbmZ1bmN0aW9uIHJlc29sdmVyRm9yPFQ+KHByb21pc2U6IENhbmNlbGxhYmxlUHJvbWlzZVdpdGhSZXNvbHZlcnM8VD4sIHN0YXRlOiBDYW5jZWxsYWJsZVByb21pc2VTdGF0ZSk6IENhbmNlbGxhYmxlUHJvbWlzZVJlc29sdmVyPFQ+IHtcbiAgICByZXR1cm4gKHZhbHVlKSA9PiB7XG4gICAgICAgIGlmIChzdGF0ZS5yZXNvbHZpbmcpIHsgcmV0dXJuOyB9XG4gICAgICAgIHN0YXRlLnJlc29sdmluZyA9IHRydWU7XG5cbiAgICAgICAgaWYgKHZhbHVlID09PSBwcm9taXNlLnByb21pc2UpIHtcbiAgICAgICAgICAgIGlmIChzdGF0ZS5zZXR0bGVkKSB7IHJldHVybjsgfVxuICAgICAgICAgICAgc3RhdGUuc2V0dGxlZCA9IHRydWU7XG4gICAgICAgICAgICBwcm9taXNlLnJlamVjdChuZXcgVHlwZUVycm9yKFwiQSBwcm9taXNlIGNhbm5vdCBiZSByZXNvbHZlZCB3aXRoIGl0c2VsZi5cIikpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHZhbHVlICE9IG51bGwgJiYgKHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIHZhbHVlID09PSAnZnVuY3Rpb24nKSkge1xuICAgICAgICAgICAgbGV0IHRoZW46IGFueTtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdGhlbiA9ICh2YWx1ZSBhcyBhbnkpLnRoZW47XG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICBzdGF0ZS5zZXR0bGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBwcm9taXNlLnJlamVjdChlcnIpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGlzQ2FsbGFibGUodGhlbikpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgY2FuY2VsID0gKHZhbHVlIGFzIGFueSkuY2FuY2VsO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNDYWxsYWJsZShjYW5jZWwpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBvbmNhbmNlbGxlZCA9IChjYXVzZT86IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJlZmxlY3QuYXBwbHkoY2FuY2VsLCB2YWx1ZSwgW2NhdXNlXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXRlLnJlYXNvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIGFscmVhZHkgY2FuY2VsbGVkLCBwcm9wYWdhdGUgY2FuY2VsbGF0aW9uLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZSBwcm9taXNlIHJldHVybmVkIGZyb20gdGhlIGNhbmNlbGxlciBhbGdvcml0aG0gZG9lcyBub3QgcmVqZWN0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gc28gaXQgY2FuIGJlIGRpc2NhcmRlZCBzYWZlbHkuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdm9pZCBjYW5jZWxsZXJGb3IoeyAuLi5wcm9taXNlLCBvbmNhbmNlbGxlZCB9LCBzdGF0ZSkoc3RhdGUucmVhc29uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvbWlzZS5vbmNhbmNlbGxlZCA9IG9uY2FuY2VsbGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBjYXRjaCB7fVxuXG4gICAgICAgICAgICAgICAgY29uc3QgbmV3U3RhdGU6IENhbmNlbGxhYmxlUHJvbWlzZVN0YXRlID0ge1xuICAgICAgICAgICAgICAgICAgICByb290OiBzdGF0ZS5yb290LFxuICAgICAgICAgICAgICAgICAgICByZXNvbHZpbmc6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBnZXQgc2V0dGxlZCgpIHsgcmV0dXJuIHRoaXMucm9vdC5zZXR0bGVkIH0sXG4gICAgICAgICAgICAgICAgICAgIHNldCBzZXR0bGVkKHZhbHVlKSB7IHRoaXMucm9vdC5zZXR0bGVkID0gdmFsdWU7IH0sXG4gICAgICAgICAgICAgICAgICAgIGdldCByZWFzb24oKSB7IHJldHVybiB0aGlzLnJvb3QucmVhc29uIH1cbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgY29uc3QgcmVqZWN0b3IgPSByZWplY3RvckZvcihwcm9taXNlLCBuZXdTdGF0ZSk7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgUmVmbGVjdC5hcHBseSh0aGVuLCB2YWx1ZSwgW3Jlc29sdmVyRm9yKHByb21pc2UsIG5ld1N0YXRlKSwgcmVqZWN0b3JdKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0b3IoZXJyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuOyAvLyBJTVBPUlRBTlQhXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc3RhdGUuc2V0dGxlZCkgeyByZXR1cm47IH1cbiAgICAgICAgc3RhdGUuc2V0dGxlZCA9IHRydWU7XG4gICAgICAgIHByb21pc2UucmVzb2x2ZSh2YWx1ZSk7XG4gICAgfTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgY2FsbGJhY2sgdGhhdCBpbXBsZW1lbnRzIHRoZSByZWplY3Rpb24gYWxnb3JpdGhtIGZvciB0aGUgZ2l2ZW4gY2FuY2VsbGFibGUgcHJvbWlzZS5cbiAqL1xuZnVuY3Rpb24gcmVqZWN0b3JGb3I8VD4ocHJvbWlzZTogQ2FuY2VsbGFibGVQcm9taXNlV2l0aFJlc29sdmVyczxUPiwgc3RhdGU6IENhbmNlbGxhYmxlUHJvbWlzZVN0YXRlKTogQ2FuY2VsbGFibGVQcm9taXNlUmVqZWN0b3Ige1xuICAgIHJldHVybiAocmVhc29uPykgPT4ge1xuICAgICAgICBpZiAoc3RhdGUucmVzb2x2aW5nKSB7IHJldHVybjsgfVxuICAgICAgICBzdGF0ZS5yZXNvbHZpbmcgPSB0cnVlO1xuXG4gICAgICAgIGlmIChzdGF0ZS5zZXR0bGVkKSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmIChyZWFzb24gaW5zdGFuY2VvZiBDYW5jZWxFcnJvciAmJiBzdGF0ZS5yZWFzb24gaW5zdGFuY2VvZiBDYW5jZWxFcnJvciAmJiBPYmplY3QuaXMocmVhc29uLmNhdXNlLCBzdGF0ZS5yZWFzb24uY2F1c2UpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFN3YWxsb3cgbGF0ZSByZWplY3Rpb25zIHRoYXQgYXJlIENhbmNlbEVycm9ycyB3aG9zZSBjYW5jZWxsYXRpb24gY2F1c2UgaXMgdGhlIHNhbWUgYXMgb3Vycy5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2gge31cblxuICAgICAgICAgICAgdm9pZCBQcm9taXNlLnJlamVjdChuZXcgQ2FuY2VsbGVkUmVqZWN0aW9uRXJyb3IocHJvbWlzZS5wcm9taXNlLCByZWFzb24pKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHN0YXRlLnNldHRsZWQgPSB0cnVlO1xuICAgICAgICAgICAgcHJvbWlzZS5yZWplY3QocmVhc29uKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuLyoqXG4gKiBDYW5jZWxzIGFsbCB2YWx1ZXMgaW4gYW4gYXJyYXkgdGhhdCBsb29rIGxpa2UgY2FuY2VsbGFibGUgdGhlbmFibGVzLlxuICogUmV0dXJucyBhIHByb21pc2UgdGhhdCBmdWxmaWxscyBvbmNlIGFsbCBjYW5jZWxsYXRpb24gcHJvY2VkdXJlcyBmb3IgdGhlIGdpdmVuIHZhbHVlcyBoYXZlIHNldHRsZWQuXG4gKi9cbmZ1bmN0aW9uIGNhbmNlbEFsbChwYXJlbnQ6IENhbmNlbGxhYmxlUHJvbWlzZTx1bmtub3duPiwgdmFsdWVzOiBhbnlbXSwgY2F1c2U/OiBhbnkpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCByZXN1bHRzOiBQcm9taXNlPHZvaWQ+W10gPSBbXTtcblxuICAgIGZvciAoY29uc3QgdmFsdWUgb2YgdmFsdWVzKSB7XG4gICAgICAgIGxldCBjYW5jZWw6IENhbmNlbGxhYmxlUHJvbWlzZUNhbmNlbGxlcjtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmICghaXNDYWxsYWJsZSh2YWx1ZS50aGVuKSkgeyBjb250aW51ZTsgfVxuICAgICAgICAgICAgY2FuY2VsID0gdmFsdWUuY2FuY2VsO1xuICAgICAgICAgICAgaWYgKCFpc0NhbGxhYmxlKGNhbmNlbCkpIHsgY29udGludWU7IH1cbiAgICAgICAgfSBjYXRjaCB7IGNvbnRpbnVlOyB9XG5cbiAgICAgICAgbGV0IHJlc3VsdDogdm9pZCB8IFByb21pc2VMaWtlPHZvaWQ+O1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgcmVzdWx0ID0gUmVmbGVjdC5hcHBseShjYW5jZWwsIHZhbHVlLCBbY2F1c2VdKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBQcm9taXNlLnJlamVjdChuZXcgQ2FuY2VsbGVkUmVqZWN0aW9uRXJyb3IocGFyZW50LCBlcnIsIFwiVW5oYW5kbGVkIGV4Y2VwdGlvbiBpbiBjYW5jZWwgbWV0aG9kLlwiKSk7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghcmVzdWx0KSB7IGNvbnRpbnVlOyB9XG4gICAgICAgIHJlc3VsdHMucHVzaChcbiAgICAgICAgICAgIChyZXN1bHQgaW5zdGFuY2VvZiBQcm9taXNlICA/IHJlc3VsdCA6IFByb21pc2UucmVzb2x2ZShyZXN1bHQpKS5jYXRjaCgocmVhc29uPykgPT4ge1xuICAgICAgICAgICAgICAgIFByb21pc2UucmVqZWN0KG5ldyBDYW5jZWxsZWRSZWplY3Rpb25FcnJvcihwYXJlbnQsIHJlYXNvbiwgXCJVbmhhbmRsZWQgcmVqZWN0aW9uIGluIGNhbmNlbCBtZXRob2QuXCIpKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFByb21pc2UuYWxsKHJlc3VsdHMpIGFzIGFueTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGl0cyBhcmd1bWVudC5cbiAqL1xuZnVuY3Rpb24gaWRlbnRpdHk8VD4oeDogVCk6IFQge1xuICAgIHJldHVybiB4O1xufVxuXG4vKipcbiAqIFRocm93cyBpdHMgYXJndW1lbnQuXG4gKi9cbmZ1bmN0aW9uIHRocm93ZXIocmVhc29uPzogYW55KTogbmV2ZXIge1xuICAgIHRocm93IHJlYXNvbjtcbn1cblxuLyoqXG4gKiBBdHRlbXB0cyB2YXJpb3VzIHN0cmF0ZWdpZXMgdG8gY29udmVydCBhbiBlcnJvciB0byBhIHN0cmluZy5cbiAqL1xuZnVuY3Rpb24gZXJyb3JNZXNzYWdlKGVycjogYW55KTogc3RyaW5nIHtcbiAgICB0cnkge1xuICAgICAgICBpZiAoZXJyIGluc3RhbmNlb2YgRXJyb3IgfHwgdHlwZW9mIGVyciAhPT0gJ29iamVjdCcgfHwgZXJyLnRvU3RyaW5nICE9PSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gXCJcIiArIGVycjtcbiAgICAgICAgfVxuICAgIH0gY2F0Y2gge31cblxuICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShlcnIpO1xuICAgIH0gY2F0Y2gge31cblxuICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoZXJyKTtcbiAgICB9IGNhdGNoIHt9XG5cbiAgICByZXR1cm4gXCI8Y291bGQgbm90IGNvbnZlcnQgZXJyb3IgdG8gc3RyaW5nPlwiO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIGN1cnJlbnQgYmFycmllciBwcm9taXNlIGZvciB0aGUgZ2l2ZW4gY2FuY2VsbGFibGUgcHJvbWlzZS4gSWYgbmVjZXNzYXJ5LCBpbml0aWFsaXNlcyB0aGUgYmFycmllci5cbiAqL1xuZnVuY3Rpb24gY3VycmVudEJhcnJpZXI8VD4ocHJvbWlzZTogQ2FuY2VsbGFibGVQcm9taXNlPFQ+KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgbGV0IHB3cjogUGFydGlhbDxQcm9taXNlV2l0aFJlc29sdmVyczx2b2lkPj4gPSBwcm9taXNlW2JhcnJpZXJTeW1dID8/IHt9O1xuICAgIGlmICghKCdwcm9taXNlJyBpbiBwd3IpKSB7XG4gICAgICAgIE9iamVjdC5hc3NpZ24ocHdyLCBwcm9taXNlV2l0aFJlc29sdmVyczx2b2lkPigpKTtcbiAgICB9XG4gICAgaWYgKHByb21pc2VbYmFycmllclN5bV0gPT0gbnVsbCkge1xuICAgICAgICBwd3IucmVzb2x2ZSEoKTtcbiAgICAgICAgcHJvbWlzZVtiYXJyaWVyU3ltXSA9IHB3cjtcbiAgICB9XG4gICAgcmV0dXJuIHB3ci5wcm9taXNlITtcbn1cblxuLy8gUG9seWZpbGwgUHJvbWlzZS53aXRoUmVzb2x2ZXJzLlxubGV0IHByb21pc2VXaXRoUmVzb2x2ZXJzID0gUHJvbWlzZS53aXRoUmVzb2x2ZXJzO1xuaWYgKHByb21pc2VXaXRoUmVzb2x2ZXJzICYmIHR5cGVvZiBwcm9taXNlV2l0aFJlc29sdmVycyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHByb21pc2VXaXRoUmVzb2x2ZXJzID0gcHJvbWlzZVdpdGhSZXNvbHZlcnMuYmluZChQcm9taXNlKTtcbn0gZWxzZSB7XG4gICAgcHJvbWlzZVdpdGhSZXNvbHZlcnMgPSBmdW5jdGlvbiA8VD4oKTogUHJvbWlzZVdpdGhSZXNvbHZlcnM8VD4ge1xuICAgICAgICBsZXQgcmVzb2x2ZSE6ICh2YWx1ZTogVCB8IFByb21pc2VMaWtlPFQ+KSA9PiB2b2lkO1xuICAgICAgICBsZXQgcmVqZWN0ITogKHJlYXNvbj86IGFueSkgPT4gdm9pZDtcbiAgICAgICAgY29uc3QgcHJvbWlzZSA9IG5ldyBQcm9taXNlPFQ+KChyZXMsIHJlaikgPT4geyByZXNvbHZlID0gcmVzOyByZWplY3QgPSByZWo7IH0pO1xuICAgICAgICByZXR1cm4geyBwcm9taXNlLCByZXNvbHZlLCByZWplY3QgfTtcbiAgICB9XG59XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbmltcG9ydCB7bmV3UnVudGltZUNhbGxlciwgb2JqZWN0TmFtZXN9IGZyb20gXCIuL3J1bnRpbWUuanNcIjtcblxuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXIob2JqZWN0TmFtZXMuQ2xpcGJvYXJkKTtcblxuY29uc3QgQ2xpcGJvYXJkU2V0VGV4dCA9IDA7XG5jb25zdCBDbGlwYm9hcmRUZXh0ID0gMTtcblxuLyoqXG4gKiBTZXRzIHRoZSB0ZXh0IHRvIHRoZSBDbGlwYm9hcmQuXG4gKlxuICogQHBhcmFtIHRleHQgLSBUaGUgdGV4dCB0byBiZSBzZXQgdG8gdGhlIENsaXBib2FyZC5cbiAqIEByZXR1cm4gQSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgb3BlcmF0aW9uIGlzIHN1Y2Nlc3NmdWwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTZXRUZXh0KHRleHQ6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBjYWxsKENsaXBib2FyZFNldFRleHQsIHt0ZXh0fSk7XG59XG5cbi8qKlxuICogR2V0IHRoZSBDbGlwYm9hcmQgdGV4dFxuICpcbiAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIHRleHQgZnJvbSB0aGUgQ2xpcGJvYXJkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gVGV4dCgpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIHJldHVybiBjYWxsKENsaXBib2FyZFRleHQpO1xufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG5leHBvcnQgaW50ZXJmYWNlIFNpemUge1xuICAgIC8qKiBUaGUgd2lkdGggb2YgYSByZWN0YW5ndWxhciBhcmVhLiAqL1xuICAgIFdpZHRoOiBudW1iZXI7XG4gICAgLyoqIFRoZSBoZWlnaHQgb2YgYSByZWN0YW5ndWxhciBhcmVhLiAqL1xuICAgIEhlaWdodDogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJlY3Qge1xuICAgIC8qKiBUaGUgWCBjb29yZGluYXRlIG9mIHRoZSBvcmlnaW4uICovXG4gICAgWDogbnVtYmVyO1xuICAgIC8qKiBUaGUgWSBjb29yZGluYXRlIG9mIHRoZSBvcmlnaW4uICovXG4gICAgWTogbnVtYmVyO1xuICAgIC8qKiBUaGUgd2lkdGggb2YgdGhlIHJlY3RhbmdsZS4gKi9cbiAgICBXaWR0aDogbnVtYmVyO1xuICAgIC8qKiBUaGUgaGVpZ2h0IG9mIHRoZSByZWN0YW5nbGUuICovXG4gICAgSGVpZ2h0OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2NyZWVuIHtcbiAgICAvKiogVW5pcXVlIGlkZW50aWZpZXIgZm9yIHRoZSBzY3JlZW4uICovXG4gICAgSUQ6IHN0cmluZztcbiAgICAvKiogSHVtYW4tcmVhZGFibGUgbmFtZSBvZiB0aGUgc2NyZWVuLiAqL1xuICAgIE5hbWU6IHN0cmluZztcbiAgICAvKiogVGhlIHNjYWxlIGZhY3RvciBvZiB0aGUgc2NyZWVuIChEUEkvOTYpLiAxID0gc3RhbmRhcmQgRFBJLCAyID0gSGlEUEkgKFJldGluYSksIGV0Yy4gKi9cbiAgICBTY2FsZUZhY3RvcjogbnVtYmVyO1xuICAgIC8qKiBUaGUgWCBjb29yZGluYXRlIG9mIHRoZSBzY3JlZW4uICovXG4gICAgWDogbnVtYmVyO1xuICAgIC8qKiBUaGUgWSBjb29yZGluYXRlIG9mIHRoZSBzY3JlZW4uICovXG4gICAgWTogbnVtYmVyO1xuICAgIC8qKiBDb250YWlucyB0aGUgd2lkdGggYW5kIGhlaWdodCBvZiB0aGUgc2NyZWVuLiAqL1xuICAgIFNpemU6IFNpemU7XG4gICAgLyoqIENvbnRhaW5zIHRoZSBib3VuZHMgb2YgdGhlIHNjcmVlbiBpbiB0ZXJtcyBvZiBYLCBZLCBXaWR0aCwgYW5kIEhlaWdodC4gKi9cbiAgICBCb3VuZHM6IFJlY3Q7XG4gICAgLyoqIENvbnRhaW5zIHRoZSBwaHlzaWNhbCBib3VuZHMgb2YgdGhlIHNjcmVlbiBpbiB0ZXJtcyBvZiBYLCBZLCBXaWR0aCwgYW5kIEhlaWdodCAoYmVmb3JlIHNjYWxpbmcpLiAqL1xuICAgIFBoeXNpY2FsQm91bmRzOiBSZWN0O1xuICAgIC8qKiBDb250YWlucyB0aGUgYXJlYSBvZiB0aGUgc2NyZWVuIHRoYXQgaXMgYWN0dWFsbHkgdXNhYmxlIChleGNsdWRpbmcgdGFza2JhciBhbmQgb3RoZXIgc3lzdGVtIFVJKS4gKi9cbiAgICBXb3JrQXJlYTogUmVjdDtcbiAgICAvKiogQ29udGFpbnMgdGhlIHBoeXNpY2FsIFdvcmtBcmVhIG9mIHRoZSBzY3JlZW4gKGJlZm9yZSBzY2FsaW5nKS4gKi9cbiAgICBQaHlzaWNhbFdvcmtBcmVhOiBSZWN0O1xuICAgIC8qKiBUcnVlIGlmIHRoaXMgaXMgdGhlIHByaW1hcnkgbW9uaXRvciBzZWxlY3RlZCBieSB0aGUgdXNlciBpbiB0aGUgb3BlcmF0aW5nIHN5c3RlbS4gKi9cbiAgICBJc1ByaW1hcnk6IGJvb2xlYW47XG4gICAgLyoqIFRoZSByb3RhdGlvbiBvZiB0aGUgc2NyZWVuLiAqL1xuICAgIFJvdGF0aW9uOiBudW1iZXI7XG59XG5cbmltcG9ydCB7IG5ld1J1bnRpbWVDYWxsZXIsIG9iamVjdE5hbWVzIH0gZnJvbSBcIi4vcnVudGltZS5qc1wiO1xuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXIob2JqZWN0TmFtZXMuU2NyZWVucyk7XG5cbmNvbnN0IGdldEFsbCA9IDA7XG5jb25zdCBnZXRQcmltYXJ5ID0gMTtcbmNvbnN0IGdldEN1cnJlbnQgPSAyO1xuY29uc3QgZ2V0QnlJRCA9IDM7XG5jb25zdCBnZXRCeUluZGV4ID0gNDtcblxuLyoqXG4gKiBHZXRzIGFsbCBzY3JlZW5zLlxuICpcbiAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGFuIGFycmF5IG9mIFNjcmVlbiBvYmplY3RzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gR2V0QWxsKCk6IFByb21pc2U8U2NyZWVuW10+IHtcbiAgICByZXR1cm4gY2FsbChnZXRBbGwpO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIHByaW1hcnkgc2NyZWVuLlxuICpcbiAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBwcmltYXJ5IHNjcmVlbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEdldFByaW1hcnkoKTogUHJvbWlzZTxTY3JlZW4+IHtcbiAgICByZXR1cm4gY2FsbChnZXRQcmltYXJ5KTtcbn1cblxuLyoqXG4gKiBHZXRzIHRoZSBjdXJyZW50IGFjdGl2ZSBzY3JlZW4uXG4gKlxuICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgY3VycmVudCBhY3RpdmUgc2NyZWVuLlxuICovXG5leHBvcnQgZnVuY3Rpb24gR2V0Q3VycmVudCgpOiBQcm9taXNlPFNjcmVlbj4ge1xuICAgIHJldHVybiBjYWxsKGdldEN1cnJlbnQpO1xufVxuXG4vKipcbiAqIEdldHMgYSBzY3JlZW4gYnkgaXRzIHVuaXF1ZSBkaXNwbGF5IElELlxuICpcbiAqIEBwYXJhbSBpZCAtIFRoZSB1bmlxdWUgaWRlbnRpZmllciBvZiB0aGUgc2NyZWVuLlxuICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIG1hdGNoaW5nIFNjcmVlbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEdldEJ5SUQoaWQ6IHN0cmluZyk6IFByb21pc2U8U2NyZWVuPiB7XG4gICAgcmV0dXJuIGNhbGwoZ2V0QnlJRCwgeyBpZCB9KTtcbn1cblxuLyoqXG4gKiBHZXRzIGEgc2NyZWVuIGJ5IGl0cyBpbmRleCBpbiB0aGUgc2NyZWVuIGxpc3QuXG4gKlxuICogQHBhcmFtIGluZGV4IC0gVGhlIHplcm8tYmFzZWQgaW5kZXggb2YgdGhlIHNjcmVlbi5cbiAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBtYXRjaGluZyBTY3JlZW4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBHZXRCeUluZGV4KGluZGV4OiBudW1iZXIpOiBQcm9taXNlPFNjcmVlbj4ge1xuICAgIHJldHVybiBjYWxsKGdldEJ5SW5kZXgsIHsgaW5kZXggfSk7XG59XG4iLCAiLypcbiBfICAgICBfXyAgICAgXyBfX1xufCB8ICAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbmltcG9ydCB7IG5ld1J1bnRpbWVDYWxsZXIsIG9iamVjdE5hbWVzIH0gZnJvbSBcIi4vcnVudGltZS5qc1wiO1xuXG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcihvYmplY3ROYW1lcy5JT1MpO1xuXG4vLyBNZXRob2QgSURzXG5jb25zdCBIYXB0aWNzSW1wYWN0ID0gMDtcbmNvbnN0IERldmljZUluZm8gPSAxO1xuXG5leHBvcnQgbmFtZXNwYWNlIEhhcHRpY3Mge1xuICAgIGV4cG9ydCB0eXBlIEltcGFjdFN0eWxlID0gXCJsaWdodFwifFwibWVkaXVtXCJ8XCJoZWF2eVwifFwic29mdFwifFwicmlnaWRcIjtcbiAgICBleHBvcnQgZnVuY3Rpb24gSW1wYWN0KHN0eWxlOiBJbXBhY3RTdHlsZSA9IFwibWVkaXVtXCIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIGNhbGwoSGFwdGljc0ltcGFjdCwgeyBzdHlsZSB9KTtcbiAgICB9XG59XG5cbmV4cG9ydCBuYW1lc3BhY2UgRGV2aWNlIHtcbiAgICBleHBvcnQgaW50ZXJmYWNlIEluZm8ge1xuICAgICAgICBtb2RlbDogc3RyaW5nO1xuICAgICAgICBzeXN0ZW1OYW1lOiBzdHJpbmc7XG4gICAgICAgIHN5c3RlbVZlcnNpb246IHN0cmluZztcbiAgICAgICAgaXNTaW11bGF0b3I6IGJvb2xlYW47XG4gICAgfVxuICAgIGV4cG9ydCBmdW5jdGlvbiBJbmZvKCk6IFByb21pc2U8SW5mbz4ge1xuICAgICAgICByZXR1cm4gY2FsbChEZXZpY2VJbmZvKTtcbiAgICB9XG59XG4iLCAiLypcbiBfICAgICBfXyAgICAgXyBfX1xufCB8ICAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbmltcG9ydCB7IG5ld1J1bnRpbWVDYWxsZXIsIG9iamVjdE5hbWVzIH0gZnJvbSBcIi4vcnVudGltZS5qc1wiO1xuXG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcihvYmplY3ROYW1lcy5BbmRyb2lkKTtcblxuLy8gTWV0aG9kIElEcyAobXVzdCBtYXRjaCBtZXNzYWdlcHJvY2Vzc29yX2FuZHJvaWQuZ28pXG5jb25zdCBIYXB0aWNzVmlicmF0ZSA9IDA7XG5jb25zdCBEZXZpY2VJbmZvID0gMTtcbmNvbnN0IFRvYXN0U2hvdyA9IDI7XG5cbmV4cG9ydCBuYW1lc3BhY2UgSGFwdGljcyB7XG4gICAgLyoqIFZpYnJhdGUgdGhlIGRldmljZSBmb3IgdGhlIGdpdmVuIGR1cmF0aW9uIGluIG1pbGxpc2Vjb25kcy4gKi9cbiAgICBleHBvcnQgZnVuY3Rpb24gVmlicmF0ZShkdXJhdGlvbk1zOiBudW1iZXIgPSAxMDApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIGNhbGwoSGFwdGljc1ZpYnJhdGUsIHsgZHVyYXRpb246IGR1cmF0aW9uTXMgfSk7XG4gICAgfVxufVxuXG5leHBvcnQgbmFtZXNwYWNlIERldmljZSB7XG4gICAgZXhwb3J0IGludGVyZmFjZSBJbmZvIHtcbiAgICAgICAgcGxhdGZvcm06IHN0cmluZztcbiAgICAgICAgbWFudWZhY3R1cmVyOiBzdHJpbmc7XG4gICAgICAgIGJyYW5kOiBzdHJpbmc7XG4gICAgICAgIG1vZGVsOiBzdHJpbmc7XG4gICAgICAgIGRldmljZTogc3RyaW5nO1xuICAgICAgICB2ZXJzaW9uOiBzdHJpbmc7XG4gICAgICAgIHNka0ludDogbnVtYmVyO1xuICAgIH1cbiAgICAvKiogUmV0dXJuIGluZm9ybWF0aW9uIGFib3V0IHRoZSBBbmRyb2lkIGRldmljZS4gKi9cbiAgICBleHBvcnQgZnVuY3Rpb24gSW5mbygpOiBQcm9taXNlPEluZm8+IHtcbiAgICAgICAgcmV0dXJuIGNhbGwoRGV2aWNlSW5mbyk7XG4gICAgfVxufVxuXG5leHBvcnQgbmFtZXNwYWNlIFRvYXN0IHtcbiAgICAvKiogU2hvdyBhIHNob3J0IEFuZHJvaWQgdG9hc3QgbWVzc2FnZS4gKi9cbiAgICBleHBvcnQgZnVuY3Rpb24gU2hvdyhtZXNzYWdlOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIGNhbGwoVG9hc3RTaG93LCB7IG1lc3NhZ2UgfSk7XG4gICAgfVxufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKipcbiAqIFVwZGF0ZXIgZXZlbnQgbmFtZSBjb25zdGFudHMuXG4gKlxuICogVXNlIHRoZXNlIGluc3RlYWQgb2YgaGFyZC1jb2Rpbmcgc3RyaW5nIGxpdGVyYWxzIHdoZW4gc3Vic2NyaWJpbmcgdG9cbiAqIHVwZGF0ZXIgZXZlbnRzIGZyb20gSmF2YVNjcmlwdDpcbiAqXG4gKiAgICAgaW1wb3J0IHsgRXZlbnRzLCBVcGRhdGVyIH0gZnJvbSBcIkB3YWlsc2lvL3J1bnRpbWVcIjtcbiAqXG4gKiAgICAgRXZlbnRzLk9uKFVwZGF0ZXIuRXZlbnRzLlVwZGF0ZUF2YWlsYWJsZSwgKGUpID0+IHtcbiAqICAgICAgICAgY29uc29sZS5sb2coXCJ1cGRhdGUgZm91bmQ6XCIsIGUuZGF0YS52ZXJzaW9uKTtcbiAqICAgICB9KTtcbiAqXG4gKiAgICAgRXZlbnRzLk9uKFVwZGF0ZXIuRXZlbnRzLkRvd25sb2FkUHJvZ3Jlc3MsIChlKSA9PiB7XG4gKiAgICAgICAgIGNvbnN0IHAgPSBlLmRhdGE7XG4gKiAgICAgICAgIGNvbnNvbGUubG9nKGAke3Aud3JpdHRlbn0gLyAke3AudG90YWx9IGJ5dGVzYCk7XG4gKiAgICAgfSk7XG4gKlxuICogTWlycm9ycyB0aGUgR28tc2lkZSBjb25zdGFudHMgaW4gYHBrZy91cGRhdGVyL2V2ZW50cy5nb2AgYW5kIHRoZVxuICogdXNlci1hY3Rpb24gY29uc3RhbnRzIGluIGBwa2cvdXBkYXRlci93aW5kb3dfbGlmZWN5Y2xlLmdvYC4gQW55XG4gKiBjaGFuZ2VzIGhlcmUgbXVzdCBzdGF5IGluIHN5bmMgd2l0aCB0aG9zZSBmaWxlcyBcdTIwMTQgdGhlcmUncyBhblxuICogaW50ZWdyYXRpb24gdGVzdCB0aGF0IGFzc2VydHMgdGhlIHN0cmluZ3MgbWF0Y2guXG4gKi9cbmV4cG9ydCBjb25zdCBFdmVudHMgPSBPYmplY3QuZnJlZXplKHtcbiAgICAvKiogQSBDaGVjayByb3VuZC10cmlwIGlzIHN0YXJ0aW5nLiBQYXlsb2FkOiBudWxsLiAqL1xuICAgIENoZWNrU3RhcnRlZDogXCJ3YWlsczp1cGRhdGVyOmNoZWNrLXN0YXJ0ZWRcIixcbiAgICAvKiogQ2hlY2sgZm91bmQgYSBuZXdlciByZWxlYXNlLiBQYXlsb2FkOiBSZWxlYXNlLiAqL1xuICAgIFVwZGF0ZUF2YWlsYWJsZTogXCJ3YWlsczp1cGRhdGVyOnVwZGF0ZS1hdmFpbGFibGVcIixcbiAgICAvKiogQ2hlY2sgY29uZmlybWVkIHRoZSBjYWxsZXIgaXMgdXAgdG8gZGF0ZS4gUGF5bG9hZDogbnVsbC4gKi9cbiAgICBOb1VwZGF0ZTogXCJ3YWlsczp1cGRhdGVyOm5vLXVwZGF0ZVwiLFxuICAgIC8qKiBEb3dubG9hZCBpcyBzdGFydGluZy4gUGF5bG9hZDogUmVsZWFzZS4gKi9cbiAgICBEb3dubG9hZFN0YXJ0ZWQ6IFwid2FpbHM6dXBkYXRlcjpkb3dubG9hZC1zdGFydGVkXCIsXG4gICAgLyoqIFBlcmlvZGljIHByb2dyZXNzIHRpY2sgZHVyaW5nIGRvd25sb2FkICh+MTAgSHopLiBQYXlsb2FkOiBQcm9ncmVzcy4gKi9cbiAgICBEb3dubG9hZFByb2dyZXNzOiBcIndhaWxzOnVwZGF0ZXI6ZG93bmxvYWQtcHJvZ3Jlc3NcIixcbiAgICAvKiogQWxsIGJ5dGVzIGFyZSBvbiBkaXNrLCBidXQgdmVyaWZpY2F0aW9uIGhhcyBub3QgeWV0IHN0YXJ0ZWQuIFBheWxvYWQ6IFJlbGVhc2UuICovXG4gICAgRG93bmxvYWRDb21wbGV0ZTogXCJ3YWlsczp1cGRhdGVyOmRvd25sb2FkLWNvbXBsZXRlXCIsXG4gICAgLyoqIFNpZ25hdHVyZSAvIGRpZ2VzdCB2ZXJpZmljYXRpb24gaGFzIHN0YXJ0ZWQuIFBheWxvYWQ6IFJlbGVhc2UuICovXG4gICAgVmVyaWZ5aW5nOiBcIndhaWxzOnVwZGF0ZXI6dmVyaWZ5aW5nXCIsXG4gICAgLyoqIFRoZSBVcGRhdGVyIGlzIHN3YXBwaW5nIHRoZSBiaW5hcnkgaW50byBwbGFjZS4gUGF5bG9hZDogUmVsZWFzZS4gKi9cbiAgICBJbnN0YWxsaW5nOiBcIndhaWxzOnVwZGF0ZXI6aW5zdGFsbGluZ1wiLFxuICAgIC8qKiBVcGRhdGUgaXMgc3RhZ2VkIGFuZCBhIHJlc3RhcnQgaXMgcGVuZGluZy4gUGF5bG9hZDogUmVsZWFzZS4gKi9cbiAgICBVcGRhdGVSZWFkeTogXCJ3YWlsczp1cGRhdGVyOnVwZGF0ZS1yZWFkeVwiLFxuICAgIC8qKiBTb21ldGhpbmcgZmFpbGVkLiBQYXlsb2FkOiBFcnJvckluZm8geyBzdGFnZSwgbWVzc2FnZSwgcHJvdmlkZXIgfS4gKi9cbiAgICBFcnJvcjogXCJ3YWlsczp1cGRhdGVyOmVycm9yXCIsXG4gICAgLyoqIEhvc3Qtc2lkZSBjb250ZXh0IGRlbGl2ZXJlZCBvbmNlIHBlciBzZXNzaW9uLiBQYXlsb2FkOiBNZXRhIHsgY3VycmVudFZlcnNpb24sIHNraXBwZWRWZXJzaW9uIH0uICovXG4gICAgTWV0YTogXCJ3YWlsczp1cGRhdGVyOm1ldGFcIixcblxuICAgIC8qKiBTdWItbmFtZXNwYWNlOiB1c2VyLWFjdGlvbiBldmVudHMgdGhhdCB0aGUgVUkgZW1pdHMgQkFDSyB0byB0aGUgaG9zdC4gKi9cbiAgICBVc2VyOiBPYmplY3QuZnJlZXplKHtcbiAgICAgICAgLyoqIFVzZXIgY2xpY2tlZCBJbnN0YWxsIG9uIGFuIEF2YWlsYWJsZSB1cGRhdGUuICovXG4gICAgICAgIEluc3RhbGw6IFwid2FpbHM6dXBkYXRlcjp1c2VyOmluc3RhbGxcIixcbiAgICAgICAgLyoqIFVzZXIgY2xpY2tlZCBSZXN0YXJ0ICYgQXBwbHkgb24gYSBSZWFkeSB1cGRhdGUuICovXG4gICAgICAgIFJlc3RhcnQ6IFwid2FpbHM6dXBkYXRlcjp1c2VyOnJlc3RhcnRcIixcbiAgICAgICAgLyoqIFVzZXIgY2xpY2tlZCBTa2lwIFRoaXMgVmVyc2lvbi4gKi9cbiAgICAgICAgU2tpcDogXCJ3YWlsczp1cGRhdGVyOnVzZXI6c2tpcFwiLFxuICAgICAgICAvKiogVXNlciBjbGlja2VkIFJlbWluZCBNZSBMYXRlci4gKi9cbiAgICAgICAgUmVtaW5kOiBcIndhaWxzOnVwZGF0ZXI6dXNlcjpyZW1pbmRcIixcbiAgICAgICAgLyoqIFVzZXIgY2xpY2tlZCBDbG9zZSAvIENhbmNlbC4gKi9cbiAgICAgICAgQ2FuY2VsOiBcIndhaWxzOnVwZGF0ZXI6dXNlcjpjYW5jZWxcIixcbiAgICB9KSxcblxuICAgIC8qKiBTdWItbmFtZXNwYWNlOiBmcmFtZXdvcmstaW50ZXJuYWwgZXZlbnRzIHRoZSBVSSBlbWl0cyB0byBjb29yZGluYXRlXG4gICAgICogIHdpdGggdGhlIGhvc3QuIE1vc3QgYXBwIGNvZGUgY2FuIGlnbm9yZSB0aGVzZS4gKi9cbiAgICBXaW5kb3c6IE9iamVjdC5mcmVlemUoe1xuICAgICAgICAvKiogVGhlIHdpbmRvdyBmaW5pc2hlZCBsb2FkaW5nIGFuZCBhc2tzIHRoZSBob3N0IHRvIHJlcGxheSBjdXJyZW50IHN0YXRlLiAqL1xuICAgICAgICBSZWFkeTogXCJ3YWlsczp1cGRhdGVyOndpbmRvdzpyZWFkeVwiLFxuICAgIH0pLFxufSk7XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFB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QTFCL0RELElBQUksUUFBUTtBQUNSLFNBQU8sU0FBUyxPQUFPLFVBQVUsQ0FBQztBQUN0QztBQTREQSxJQUFJLFFBQVE7QUFDUixTQUFPLE9BQU8sU0FBZ0I7QUFDOUIsU0FBTyxPQUFPLFdBQVc7QUFDN0I7QUFLQSxJQUFJLFFBQVE7QUFDUixTQUFPLE9BQU8seUJBQXlCLGVBQU8sdUJBQXVCLEtBQUssY0FBTTtBQUNwRjtBQUdBLElBQUksUUFBUTtBQUNSLFNBQU8sT0FBTyxrQkFBa0I7QUFDaEMsU0FBTyxPQUFPLGtCQUFrQjtBQUNoQyxTQUFPLE9BQU8saUJBQWlCO0FBQ25DO0FBRUEsSUFBSSxRQUFRO0FBQ1IsRUFBTyxPQUFPLHFCQUFxQjtBQUN2QztBQU9PLFNBQVMsbUJBQW1CLEtBQTRCO0FBQzNELFNBQU8sTUFBTSxLQUFLLEVBQUUsUUFBUSxPQUFPLENBQUMsRUFDL0IsS0FBSyxjQUFZO0FBQ2QsUUFBSSxTQUFTLElBQUk7QUFHYixZQUFNLGVBQWUsU0FBUyxRQUFRLElBQUksY0FBYyxLQUFLLElBQUksWUFBWTtBQUM3RSxVQUFJLFlBQVksU0FBUyxZQUFZLEdBQUc7QUFDcEMsY0FBTSxTQUFTLFNBQVMsY0FBYyxRQUFRO0FBQzlDLGVBQU8sTUFBTTtBQUNiLGlCQUFTLEtBQUssWUFBWSxNQUFNO0FBQUEsTUFDcEM7QUFBQSxJQUNKO0FBQUEsRUFDSixDQUFDLEVBQ0EsTUFBTSxNQUFNO0FBQUEsRUFBQyxDQUFDO0FBQ3ZCO0FBR0EsSUFBSSxRQUFRO0FBQ1IscUJBQW1CLGtCQUFrQjtBQUN6QzsiLAogICJuYW1lcyI6IFsiX2EiLCAiRXJyb3IiLCAiY2FsbCIsICJFcnJvciIsICJfYSIsICJBcnJheSIsICJNYXAiLCAiQXJyYXkiLCAiTWFwIiwgImtleSIsICJjYWxsIiwgIl9hIiwgIl9hIiwgInJlc2l6YWJsZSIsICJfYSIsICJjYWxsIiwgIl9hIiwgImNhbGwiLCAiX2EiLCAiY2FsbCIsICJIaWRlTWV0aG9kIiwgIlNob3dNZXRob2QiLCAiaXNEb2N1bWVudERvdEFsbCIsICJfYSIsICJyZWFzb24iLCAidmFsdWUiLCAiY2FsbCIsICJjYWxsIiwgImNhbGwiLCAiY2FsbCIsICJIYXB0aWNzIiwgIkRldmljZSIsICJJbmZvIiwgIkRldmljZSIsICJIYXB0aWNzIiwgImNhbGwiLCAiRGV2aWNlSW5mbyIsICJIYXB0aWNzIiwgIkRldmljZSIsICJJbmZvIiwgIlRvYXN0IiwgIlNob3ciLCAiRXZlbnRzIiwgIkV2ZW50cyJdCn0K +//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2luZGV4LnRzIiwgIi4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy93bWwudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2Jyb3dzZXIudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL25hbm9pZC50cyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvZW52aXJvbm1lbnQudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3J1bnRpbWUudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2RpYWxvZ3MudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2V2ZW50cy50cyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvbGlzdGVuZXIudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2NyZWF0ZS50cyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvZXZlbnRfdHlwZXMudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3V0aWxzLnRzIiwgIi4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy93aW5kb3cudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL2NvbXBpbGVkL21haW4uanMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3N5c3RlbS50cyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvY29udGV4dG1lbnUudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2ZsYWdzLnRzIiwgIi4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9kcmFnLnRzIiwgIi4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9hcHByZWdpb24udHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2FwcGxpY2F0aW9uLnRzIiwgIi4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9jYWxscy50cyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvY2FsbGFibGUudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2NhbmNlbGxhYmxlLnRzIiwgIi4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9jbGlwYm9hcmQudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3NjcmVlbnMudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2lvcy50cyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvYW5kcm9pZC50cyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvdXBkYXRlci50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbi8vIFNldHVwXG5pbXBvcnQgeyBoYXNET00gfSBmcm9tIFwiLi9lbnZpcm9ubWVudC5qc1wiO1xuXG5pZiAoaGFzRE9NKSB7XG4gICAgd2luZG93Ll93YWlscyA9IHdpbmRvdy5fd2FpbHMgfHwge307XG59XG5cbmltcG9ydCBcIi4vY29udGV4dG1lbnUuanNcIjtcbmltcG9ydCBcIi4vZHJhZy5qc1wiO1xuaW1wb3J0IFwiLi9hcHByZWdpb24uanNcIjtcblxuLy8gUmUtZXhwb3J0IHB1YmxpYyBBUElcbmltcG9ydCAqIGFzIEFwcGxpY2F0aW9uIGZyb20gXCIuL2FwcGxpY2F0aW9uLmpzXCI7XG5pbXBvcnQgKiBhcyBCcm93c2VyIGZyb20gXCIuL2Jyb3dzZXIuanNcIjtcbmltcG9ydCAqIGFzIENhbGwgZnJvbSBcIi4vY2FsbHMuanNcIjtcbmltcG9ydCAqIGFzIENsaXBib2FyZCBmcm9tIFwiLi9jbGlwYm9hcmQuanNcIjtcbmltcG9ydCAqIGFzIENyZWF0ZSBmcm9tIFwiLi9jcmVhdGUuanNcIjtcbmltcG9ydCAqIGFzIERpYWxvZ3MgZnJvbSBcIi4vZGlhbG9ncy5qc1wiO1xuaW1wb3J0ICogYXMgRXZlbnRzIGZyb20gXCIuL2V2ZW50cy5qc1wiO1xuaW1wb3J0ICogYXMgRmxhZ3MgZnJvbSBcIi4vZmxhZ3MuanNcIjtcbmltcG9ydCAqIGFzIFNjcmVlbnMgZnJvbSBcIi4vc2NyZWVucy5qc1wiO1xuaW1wb3J0ICogYXMgU3lzdGVtIGZyb20gXCIuL3N5c3RlbS5qc1wiO1xuaW1wb3J0ICogYXMgSU9TIGZyb20gXCIuL2lvcy5qc1wiO1xuaW1wb3J0ICogYXMgQW5kcm9pZCBmcm9tIFwiLi9hbmRyb2lkLmpzXCI7XG5pbXBvcnQgKiBhcyBVcGRhdGVyIGZyb20gXCIuL3VwZGF0ZXIuanNcIjtcbmltcG9ydCBXaW5kb3csIHsgaGFuZGxlRHJhZ0VudGVyLCBoYW5kbGVEcmFnTGVhdmUsIGhhbmRsZURyYWdPdmVyIH0gZnJvbSBcIi4vd2luZG93LmpzXCI7XG5pbXBvcnQgKiBhcyBXTUwgZnJvbSBcIi4vd21sLmpzXCI7XG5cbmV4cG9ydCB7XG4gICAgQXBwbGljYXRpb24sXG4gICAgQnJvd3NlcixcbiAgICBDYWxsLFxuICAgIENsaXBib2FyZCxcbiAgICBEaWFsb2dzLFxuICAgIEV2ZW50cyxcbiAgICBGbGFncyxcbiAgICBTY3JlZW5zLFxuICAgIFN5c3RlbSxcbiAgICBJT1MsXG4gICAgQW5kcm9pZCxcbiAgICBVcGRhdGVyLFxuICAgIFdpbmRvdyxcbiAgICBXTUxcbn07XG5cbi8qKlxuICogQW4gaW50ZXJuYWwgdXRpbGl0eSBjb25zdW1lZCBieSB0aGUgYmluZGluZyBnZW5lcmF0b3IuXG4gKlxuICogQGlnbm9yZVxuICovXG5leHBvcnQgeyBDcmVhdGUgfTtcblxuZXhwb3J0ICogZnJvbSBcIi4vY2FuY2VsbGFibGUuanNcIjtcblxuLy8gRXhwb3J0IHRyYW5zcG9ydCBpbnRlcmZhY2VzIGFuZCB1dGlsaXRpZXNcbmV4cG9ydCB7XG4gICAgc2V0VHJhbnNwb3J0LFxuICAgIGdldFRyYW5zcG9ydCxcbiAgICB0eXBlIFJ1bnRpbWVUcmFuc3BvcnQsXG4gICAgb2JqZWN0TmFtZXMsXG4gICAgY2xpZW50SWQsXG59IGZyb20gXCIuL3J1bnRpbWUuanNcIjtcblxuaW1wb3J0IHsgY2xpZW50SWQgfSBmcm9tIFwiLi9ydW50aW1lLmpzXCI7XG5cbi8vIE5vdGlmeSBiYWNrZW5kXG5pZiAoaGFzRE9NKSB7XG4gICAgd2luZG93Ll93YWlscy5pbnZva2UgPSBTeXN0ZW0uaW52b2tlO1xuICAgIHdpbmRvdy5fd2FpbHMuY2xpZW50SWQgPSBjbGllbnRJZDtcbn1cblxuLy8gUmVnaXN0ZXIgcGxhdGZvcm0gaGFuZGxlcnMgKGludGVybmFsIEFQSSlcbi8vIE5vdGU6IFdpbmRvdyBpcyB0aGUgdGhpc1dpbmRvdyBpbnN0YW5jZSAoZGVmYXVsdCBleHBvcnQgZnJvbSB3aW5kb3cudHMpXG4vLyBCaW5kaW5nIGVuc3VyZXMgJ3RoaXMnIGNvcnJlY3RseSByZWZlcnMgdG8gdGhlIGN1cnJlbnQgd2luZG93IGluc3RhbmNlXG5pZiAoaGFzRE9NKSB7XG4gICAgd2luZG93Ll93YWlscy5oYW5kbGVQbGF0Zm9ybUZpbGVEcm9wID0gV2luZG93LkhhbmRsZVBsYXRmb3JtRmlsZURyb3AuYmluZChXaW5kb3cpO1xufVxuXG4vLyBMaW51eC1zcGVjaWZpYyBkcmFnIGhhbmRsZXJzIChHVEsgaW50ZXJjZXB0cyBET00gZHJhZyBldmVudHMpXG5pZiAoaGFzRE9NKSB7XG4gICAgd2luZG93Ll93YWlscy5oYW5kbGVEcmFnRW50ZXIgPSBoYW5kbGVEcmFnRW50ZXI7XG4gICAgd2luZG93Ll93YWlscy5oYW5kbGVEcmFnTGVhdmUgPSBoYW5kbGVEcmFnTGVhdmU7XG4gICAgd2luZG93Ll93YWlscy5oYW5kbGVEcmFnT3ZlciA9IGhhbmRsZURyYWdPdmVyO1xufVxuXG5pZiAoaGFzRE9NKSB7XG4gICAgU3lzdGVtLmludm9rZShcIndhaWxzOnJ1bnRpbWU6cmVhZHlcIik7XG59XG5cbi8qKlxuICogTG9hZHMgYSBzY3JpcHQgZnJvbSB0aGUgZ2l2ZW4gVVJMIGlmIGl0IGV4aXN0cy5cbiAqIFVzZXMgSEVBRCByZXF1ZXN0IHRvIGNoZWNrIGV4aXN0ZW5jZSwgdGhlbiBpbmplY3RzIGEgc2NyaXB0IHRhZy5cbiAqIFNpbGVudGx5IGlnbm9yZXMgaWYgdGhlIHNjcmlwdCBkb2Vzbid0IGV4aXN0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gbG9hZE9wdGlvbmFsU2NyaXB0KHVybDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIGZldGNoKHVybCwgeyBtZXRob2Q6ICdIRUFEJyB9KVxuICAgICAgICAudGhlbihyZXNwb25zZSA9PiB7XG4gICAgICAgICAgICBpZiAocmVzcG9uc2Uub2spIHtcbiAgICAgICAgICAgICAgICAvLyBWZXJpZnkgdGhlIHJlc3BvbnNlIGlzIGFjdHVhbGx5IEphdmFTY3JpcHQgYW5kIG5vdCBhbiBIVE1MIGZhbGxiYWNrXG4gICAgICAgICAgICAgICAgLy8gKGUuZy4gVml0ZSBkZXYgc2VydmVyIHJldHVybnMgaW5kZXguaHRtbCBmb3IgdW5rbm93biByb3V0ZXMpXG4gICAgICAgICAgICAgICAgY29uc3QgY29udGVudFR5cGUgPSAocmVzcG9uc2UuaGVhZGVycy5nZXQoJ2NvbnRlbnQtdHlwZScpIHx8ICcnKS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgICAgIGlmIChjb250ZW50VHlwZS5pbmNsdWRlcygnamF2YXNjcmlwdCcpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHNjcmlwdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NjcmlwdCcpO1xuICAgICAgICAgICAgICAgICAgICBzY3JpcHQuc3JjID0gdXJsO1xuICAgICAgICAgICAgICAgICAgICBkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKHNjcmlwdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goKCkgPT4ge30pOyAvLyBTaWxlbnRseSBpZ25vcmUgLSBzY3JpcHQgaXMgb3B0aW9uYWxcbn1cblxuLy8gTG9hZCBjdXN0b20uanMgaWYgYXZhaWxhYmxlICh1c2VkIGJ5IHNlcnZlciBtb2RlIGZvciBXZWJTb2NrZXQgZXZlbnRzLCBldGMuKVxuaWYgKGhhc0RPTSkge1xuICAgIGxvYWRPcHRpb25hbFNjcmlwdCgnL3dhaWxzL2N1c3RvbS5qcycpO1xufVxuIiwgIi8qXG4gXyAgICAgX18gICAgIF8gX19cbnwgfCAgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG5pbXBvcnQgeyBPcGVuVVJMIH0gZnJvbSBcIi4vYnJvd3Nlci5qc1wiO1xuaW1wb3J0IHsgUXVlc3Rpb24gfSBmcm9tIFwiLi9kaWFsb2dzLmpzXCI7XG5pbXBvcnQgeyBFbWl0IH0gZnJvbSBcIi4vZXZlbnRzLmpzXCI7XG5pbXBvcnQgeyBjYW5BYm9ydExpc3RlbmVycywgd2hlblJlYWR5IH0gZnJvbSBcIi4vdXRpbHMuanNcIjtcbmltcG9ydCBXaW5kb3cgZnJvbSBcIi4vd2luZG93LmpzXCI7XG5cbi8qKlxuICogU2VuZHMgYW4gZXZlbnQgd2l0aCB0aGUgZ2l2ZW4gbmFtZSBhbmQgb3B0aW9uYWwgZGF0YS5cbiAqXG4gKiBAcGFyYW0gZXZlbnROYW1lIC0gLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdG8gc2VuZC5cbiAqIEBwYXJhbSBbZGF0YT1udWxsXSAtIC0gT3B0aW9uYWwgZGF0YSB0byBzZW5kIGFsb25nIHdpdGggdGhlIGV2ZW50LlxuICovXG5mdW5jdGlvbiBzZW5kRXZlbnQoZXZlbnROYW1lOiBzdHJpbmcsIGRhdGE6IGFueSA9IG51bGwpOiB2b2lkIHtcbiAgICBFbWl0KGV2ZW50TmFtZSwgZGF0YSk7XG59XG5cbi8qKlxuICogQ2FsbHMgYSBtZXRob2Qgb24gYSBzcGVjaWZpZWQgd2luZG93LlxuICpcbiAqIEBwYXJhbSB3aW5kb3dOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHdpbmRvdyB0byBjYWxsIHRoZSBtZXRob2Qgb24uXG4gKiBAcGFyYW0gbWV0aG9kTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBtZXRob2QgdG8gY2FsbC5cbiAqL1xuZnVuY3Rpb24gY2FsbFdpbmRvd01ldGhvZCh3aW5kb3dOYW1lOiBzdHJpbmcsIG1ldGhvZE5hbWU6IHN0cmluZykge1xuICAgIGNvbnN0IHRhcmdldFdpbmRvdyA9IFdpbmRvdy5HZXQod2luZG93TmFtZSk7XG4gICAgY29uc3QgbWV0aG9kID0gKHRhcmdldFdpbmRvdyBhcyBhbnkpW21ldGhvZE5hbWVdO1xuXG4gICAgaWYgKHR5cGVvZiBtZXRob2QgIT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICBjb25zb2xlLmVycm9yKGBXaW5kb3cgbWV0aG9kICcke21ldGhvZE5hbWV9JyBub3QgZm91bmRgKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICAgIG1ldGhvZC5jYWxsKHRhcmdldFdpbmRvdyk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zb2xlLmVycm9yKGBFcnJvciBjYWxsaW5nIHdpbmRvdyBtZXRob2QgJyR7bWV0aG9kTmFtZX0nOiBgLCBlKTtcbiAgICB9XG59XG5cbi8qKlxuICogUmVzcG9uZHMgdG8gYSB0cmlnZ2VyaW5nIGV2ZW50IGJ5IHJ1bm5pbmcgYXBwcm9wcmlhdGUgV01MIGFjdGlvbnMgZm9yIHRoZSBjdXJyZW50IHRhcmdldC5cbiAqL1xuZnVuY3Rpb24gb25XTUxUcmlnZ2VyZWQoZXY6IEV2ZW50KTogdm9pZCB7XG4gICAgY29uc3QgZWxlbWVudCA9IGV2LmN1cnJlbnRUYXJnZXQgYXMgRWxlbWVudDtcblxuICAgIGZ1bmN0aW9uIHJ1bkVmZmVjdChjaG9pY2UgPSBcIlllc1wiKSB7XG4gICAgICAgIGlmIChjaG9pY2UgIT09IFwiWWVzXCIpXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgY29uc3QgZXZlbnRUeXBlID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3dtbC1ldmVudCcpIHx8IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCdkYXRhLXdtbC1ldmVudCcpO1xuICAgICAgICBjb25zdCB0YXJnZXRXaW5kb3cgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLXRhcmdldC13aW5kb3cnKSB8fCBlbGVtZW50LmdldEF0dHJpYnV0ZSgnZGF0YS13bWwtdGFyZ2V0LXdpbmRvdycpIHx8IFwiXCI7XG4gICAgICAgIGNvbnN0IHdpbmRvd01ldGhvZCA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtd2luZG93JykgfHwgZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ2RhdGEtd21sLXdpbmRvdycpO1xuICAgICAgICBjb25zdCB1cmwgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLW9wZW51cmwnKSB8fCBlbGVtZW50LmdldEF0dHJpYnV0ZSgnZGF0YS13bWwtb3BlbnVybCcpO1xuXG4gICAgICAgIGlmIChldmVudFR5cGUgIT09IG51bGwpXG4gICAgICAgICAgICBzZW5kRXZlbnQoZXZlbnRUeXBlKTtcbiAgICAgICAgaWYgKHdpbmRvd01ldGhvZCAhPT0gbnVsbClcbiAgICAgICAgICAgIGNhbGxXaW5kb3dNZXRob2QodGFyZ2V0V2luZG93LCB3aW5kb3dNZXRob2QpO1xuICAgICAgICBpZiAodXJsICE9PSBudWxsKVxuICAgICAgICAgICAgdm9pZCBPcGVuVVJMKHVybCk7XG4gICAgfVxuXG4gICAgY29uc3QgY29uZmlybSA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtY29uZmlybScpIHx8IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCdkYXRhLXdtbC1jb25maXJtJyk7XG5cbiAgICBpZiAoY29uZmlybSkge1xuICAgICAgICBRdWVzdGlvbih7XG4gICAgICAgICAgICBUaXRsZTogXCJDb25maXJtXCIsXG4gICAgICAgICAgICBNZXNzYWdlOiBjb25maXJtLFxuICAgICAgICAgICAgRGV0YWNoZWQ6IGZhbHNlLFxuICAgICAgICAgICAgQnV0dG9uczogW1xuICAgICAgICAgICAgICAgIHsgTGFiZWw6IFwiWWVzXCIgfSxcbiAgICAgICAgICAgICAgICB7IExhYmVsOiBcIk5vXCIsIElzRGVmYXVsdDogdHJ1ZSB9XG4gICAgICAgICAgICBdXG4gICAgICAgIH0pLnRoZW4ocnVuRWZmZWN0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBydW5FZmZlY3QoKTtcbiAgICB9XG59XG5cbi8vIFByaXZhdGUgZmllbGQgbmFtZXMuXG5jb25zdCBjb250cm9sbGVyU3ltID0gU3ltYm9sKFwiY29udHJvbGxlclwiKTtcbmNvbnN0IHRyaWdnZXJNYXBTeW0gPSBTeW1ib2woXCJ0cmlnZ2VyTWFwXCIpO1xuY29uc3QgZWxlbWVudENvdW50U3ltID0gU3ltYm9sKFwiZWxlbWVudENvdW50XCIpO1xuXG4vKipcbiAqIEFib3J0Q29udHJvbGxlclJlZ2lzdHJ5IGRvZXMgbm90IGFjdHVhbGx5IHJlbWVtYmVyIGFjdGl2ZSBldmVudCBsaXN0ZW5lcnM6IGluc3RlYWRcbiAqIGl0IHRpZXMgdGhlbSB0byBhbiBBYm9ydFNpZ25hbCBhbmQgdXNlcyBhbiBBYm9ydENvbnRyb2xsZXIgdG8gcmVtb3ZlIHRoZW0gYWxsIGF0IG9uY2UuXG4gKi9cbmNsYXNzIEFib3J0Q29udHJvbGxlclJlZ2lzdHJ5IHtcbiAgICAvLyBQcml2YXRlIGZpZWxkcy5cbiAgICBbY29udHJvbGxlclN5bV06IEFib3J0Q29udHJvbGxlcjtcblxuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzW2NvbnRyb2xsZXJTeW1dID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYW4gb3B0aW9ucyBvYmplY3QgZm9yIGFkZEV2ZW50TGlzdGVuZXIgdGhhdCB0aWVzIHRoZSBsaXN0ZW5lclxuICAgICAqIHRvIHRoZSBBYm9ydFNpZ25hbCBmcm9tIHRoZSBjdXJyZW50IEFib3J0Q29udHJvbGxlci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBlbGVtZW50IC0gQW4gSFRNTCBlbGVtZW50XG4gICAgICogQHBhcmFtIHRyaWdnZXJzIC0gVGhlIGxpc3Qgb2YgYWN0aXZlIFdNTCB0cmlnZ2VyIGV2ZW50cyBmb3IgdGhlIHNwZWNpZmllZCBlbGVtZW50c1xuICAgICAqL1xuICAgIHNldChlbGVtZW50OiBFbGVtZW50LCB0cmlnZ2Vyczogc3RyaW5nW10pOiBBZGRFdmVudExpc3RlbmVyT3B0aW9ucyB7XG4gICAgICAgIHJldHVybiB7IHNpZ25hbDogdGhpc1tjb250cm9sbGVyU3ltXS5zaWduYWwgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGFsbCByZWdpc3RlcmVkIGV2ZW50IGxpc3RlbmVycyBhbmQgcmVzZXRzIHRoZSByZWdpc3RyeS5cbiAgICAgKi9cbiAgICByZXNldCgpOiB2b2lkIHtcbiAgICAgICAgdGhpc1tjb250cm9sbGVyU3ltXS5hYm9ydCgpO1xuICAgICAgICB0aGlzW2NvbnRyb2xsZXJTeW1dID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBXZWFrTWFwUmVnaXN0cnkgbWFwcyBhY3RpdmUgdHJpZ2dlciBldmVudHMgdG8gZWFjaCBET00gZWxlbWVudCB0aHJvdWdoIGEgV2Vha01hcC5cbiAqIFRoaXMgZW5zdXJlcyB0aGF0IHRoZSBtYXBwaW5nIHJlbWFpbnMgcHJpdmF0ZSB0byB0aGlzIG1vZHVsZSwgd2hpbGUgc3RpbGwgYWxsb3dpbmcgZ2FyYmFnZVxuICogY29sbGVjdGlvbiBvZiB0aGUgaW52b2x2ZWQgZWxlbWVudHMuXG4gKi9cbmNsYXNzIFdlYWtNYXBSZWdpc3RyeSB7XG4gICAgLyoqIFN0b3JlcyB0aGUgY3VycmVudCBlbGVtZW50LXRvLXRyaWdnZXIgbWFwcGluZy4gKi9cbiAgICBbdHJpZ2dlck1hcFN5bV06IFdlYWtNYXA8RWxlbWVudCwgc3RyaW5nW10+O1xuICAgIC8qKiBDb3VudHMgdGhlIG51bWJlciBvZiBlbGVtZW50cyB3aXRoIGFjdGl2ZSBXTUwgdHJpZ2dlcnMuICovXG4gICAgW2VsZW1lbnRDb3VudFN5bV06IG51bWJlcjtcblxuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzW3RyaWdnZXJNYXBTeW1dID0gbmV3IFdlYWtNYXAoKTtcbiAgICAgICAgdGhpc1tlbGVtZW50Q291bnRTeW1dID0gMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIGFjdGl2ZSB0cmlnZ2VycyBmb3IgdGhlIHNwZWNpZmllZCBlbGVtZW50LlxuICAgICAqXG4gICAgICogQHBhcmFtIGVsZW1lbnQgLSBBbiBIVE1MIGVsZW1lbnRcbiAgICAgKiBAcGFyYW0gdHJpZ2dlcnMgLSBUaGUgbGlzdCBvZiBhY3RpdmUgV01MIHRyaWdnZXIgZXZlbnRzIGZvciB0aGUgc3BlY2lmaWVkIGVsZW1lbnRcbiAgICAgKi9cbiAgICBzZXQoZWxlbWVudDogRWxlbWVudCwgdHJpZ2dlcnM6IHN0cmluZ1tdKTogQWRkRXZlbnRMaXN0ZW5lck9wdGlvbnMge1xuICAgICAgICBpZiAoIXRoaXNbdHJpZ2dlck1hcFN5bV0uaGFzKGVsZW1lbnQpKSB7IHRoaXNbZWxlbWVudENvdW50U3ltXSsrOyB9XG4gICAgICAgIHRoaXNbdHJpZ2dlck1hcFN5bV0uc2V0KGVsZW1lbnQsIHRyaWdnZXJzKTtcbiAgICAgICAgcmV0dXJuIHt9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYWxsIHJlZ2lzdGVyZWQgZXZlbnQgbGlzdGVuZXJzLlxuICAgICAqL1xuICAgIHJlc2V0KCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpc1tlbGVtZW50Q291bnRTeW1dIDw9IDApXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgZm9yIChjb25zdCBlbGVtZW50IG9mIGRvY3VtZW50LmJvZHkucXVlcnlTZWxlY3RvckFsbCgnKicpKSB7XG4gICAgICAgICAgICBpZiAodGhpc1tlbGVtZW50Q291bnRTeW1dIDw9IDApXG4gICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgIGNvbnN0IHRyaWdnZXJzID0gdGhpc1t0cmlnZ2VyTWFwU3ltXS5nZXQoZWxlbWVudCk7XG4gICAgICAgICAgICBpZiAodHJpZ2dlcnMgIT0gbnVsbCkgeyB0aGlzW2VsZW1lbnRDb3VudFN5bV0tLTsgfVxuXG4gICAgICAgICAgICBmb3IgKGNvbnN0IHRyaWdnZXIgb2YgdHJpZ2dlcnMgfHwgW10pXG4gICAgICAgICAgICAgICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKHRyaWdnZXIsIG9uV01MVHJpZ2dlcmVkKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXNbdHJpZ2dlck1hcFN5bV0gPSBuZXcgV2Vha01hcCgpO1xuICAgICAgICB0aGlzW2VsZW1lbnRDb3VudFN5bV0gPSAwO1xuICAgIH1cbn1cblxuY29uc3QgdHJpZ2dlclJlZ2lzdHJ5ID0gY2FuQWJvcnRMaXN0ZW5lcnMoKSA/IG5ldyBBYm9ydENvbnRyb2xsZXJSZWdpc3RyeSgpIDogbmV3IFdlYWtNYXBSZWdpc3RyeSgpO1xuXG4vKipcbiAqIEFkZHMgZXZlbnQgbGlzdGVuZXJzIHRvIHRoZSBzcGVjaWZpZWQgZWxlbWVudC5cbiAqL1xuZnVuY3Rpb24gYWRkV01MTGlzdGVuZXJzKGVsZW1lbnQ6IEVsZW1lbnQpOiB2b2lkIHtcbiAgICBjb25zdCB0cmlnZ2VyUmVnRXhwID0gL1xcUysvZztcbiAgICBjb25zdCB0cmlnZ2VyQXR0ciA9IChlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLXRyaWdnZXInKSB8fCBlbGVtZW50LmdldEF0dHJpYnV0ZSgnZGF0YS13bWwtdHJpZ2dlcicpIHx8IFwiY2xpY2tcIik7XG4gICAgY29uc3QgdHJpZ2dlcnM6IHN0cmluZ1tdID0gW107XG5cbiAgICBsZXQgbWF0Y2g7XG4gICAgd2hpbGUgKChtYXRjaCA9IHRyaWdnZXJSZWdFeHAuZXhlYyh0cmlnZ2VyQXR0cikpICE9PSBudWxsKVxuICAgICAgICB0cmlnZ2Vycy5wdXNoKG1hdGNoWzBdKTtcblxuICAgIGNvbnN0IG9wdGlvbnMgPSB0cmlnZ2VyUmVnaXN0cnkuc2V0KGVsZW1lbnQsIHRyaWdnZXJzKTtcbiAgICBmb3IgKGNvbnN0IHRyaWdnZXIgb2YgdHJpZ2dlcnMpXG4gICAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcih0cmlnZ2VyLCBvbldNTFRyaWdnZXJlZCwgb3B0aW9ucyk7XG59XG5cbi8qKlxuICogU2NoZWR1bGVzIGFuIGF1dG9tYXRpYyByZWxvYWQgb2YgV01MIHRvIGJlIHBlcmZvcm1lZCBhcyBzb29uIGFzIHRoZSBkb2N1bWVudCBpcyBmdWxseSBsb2FkZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFbmFibGUoKTogdm9pZCB7XG4gICAgd2hlblJlYWR5KFJlbG9hZCk7XG59XG5cbi8qKlxuICogUmVsb2FkcyB0aGUgV01MIHBhZ2UgYnkgYWRkaW5nIG5lY2Vzc2FyeSBldmVudCBsaXN0ZW5lcnMgYW5kIGJyb3dzZXIgbGlzdGVuZXJzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gUmVsb2FkKCk6IHZvaWQge1xuICAgIHRyaWdnZXJSZWdpc3RyeS5yZXNldCgpO1xuICAgIGRvY3VtZW50LmJvZHkucXVlcnlTZWxlY3RvckFsbCgnW3dtbC1ldmVudF0sIFt3bWwtd2luZG93XSwgW3dtbC1vcGVudXJsXSwgW2RhdGEtd21sLWV2ZW50XSwgW2RhdGEtd21sLXdpbmRvd10sIFtkYXRhLXdtbC1vcGVudXJsXScpLmZvckVhY2goYWRkV01MTGlzdGVuZXJzKTtcbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuaW1wb3J0IHsgbmV3UnVudGltZUNhbGxlciwgb2JqZWN0TmFtZXMgfSBmcm9tIFwiLi9ydW50aW1lLmpzXCI7XG5cbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyKG9iamVjdE5hbWVzLkJyb3dzZXIpO1xuXG5jb25zdCBCcm93c2VyT3BlblVSTCA9IDA7XG5cbi8qKlxuICogT3BlbiBhIGJyb3dzZXIgd2luZG93IHRvIHRoZSBnaXZlbiBVUkwuXG4gKlxuICogQHBhcmFtIHVybCAtIFRoZSBVUkwgdG8gb3BlblxuICovXG5leHBvcnQgZnVuY3Rpb24gT3BlblVSTCh1cmw6IHN0cmluZyB8IFVSTCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBjYWxsKEJyb3dzZXJPcGVuVVJMLCB7dXJsOiB1cmwudG9TdHJpbmcoKX0pO1xufVxuIiwgIi8vIFNvdXJjZTogaHR0cHM6Ly9naXRodWIuY29tL2FpL25hbm9pZFxuXG4vLyBUaGUgTUlUIExpY2Vuc2UgKE1JVClcbi8vXG4vLyBDb3B5cmlnaHQgMjAxNyBBbmRyZXkgU2l0bmlrIDxhbmRyZXlAc2l0bmlrLnJ1PlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHkgb2Zcbi8vIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW5cbi8vIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG9cbi8vIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGwgY29waWVzIG9mXG4vLyB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sXG4vLyAgICAgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gICAgIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluIGFsbFxuLy8gY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyAgICAgVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuLy8gSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1Ncbi8vIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUlxuLy8gQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSXG4vLyBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTlxuLy8gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxuLy8gVGhpcyBhbHBoYWJldCB1c2VzIGBBLVphLXowLTlfLWAgc3ltYm9scy5cbi8vIFRoZSBvcmRlciBvZiBjaGFyYWN0ZXJzIGlzIG9wdGltaXplZCBmb3IgYmV0dGVyIGd6aXAgYW5kIGJyb3RsaSBjb21wcmVzc2lvbi5cbi8vIFJlZmVyZW5jZXMgdG8gdGhlIHNhbWUgZmlsZSAod29ya3MgYm90aCBmb3IgZ3ppcCBhbmQgYnJvdGxpKTpcbi8vIGAndXNlYCwgYGFuZG9tYCwgYW5kIGByaWN0J2Bcbi8vIFJlZmVyZW5jZXMgdG8gdGhlIGJyb3RsaSBkZWZhdWx0IGRpY3Rpb25hcnk6XG4vLyBgLTI2VGAsIGAxOTgzYCwgYDQwcHhgLCBgNzVweGAsIGBidXNoYCwgYGphY2tgLCBgbWluZGAsIGB2ZXJ5YCwgYW5kIGB3b2xmYFxuY29uc3QgdXJsQWxwaGFiZXQgPVxuICAgICd1c2VhbmRvbS0yNlQxOTgzNDBQWDc1cHhKQUNLVkVSWU1JTkRCVVNIV09MRl9HUVpiZmdoamtscXZ3eXpyaWN0J1xuXG5leHBvcnQgZnVuY3Rpb24gbmFub2lkKHNpemU6IG51bWJlciA9IDIxKTogc3RyaW5nIHtcbiAgICBsZXQgaWQgPSAnJ1xuICAgIC8vIEEgY29tcGFjdCBhbHRlcm5hdGl2ZSBmb3IgYGZvciAodmFyIGkgPSAwOyBpIDwgc3RlcDsgaSsrKWAuXG4gICAgbGV0IGkgPSBzaXplIHwgMFxuICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgLy8gYHwgMGAgaXMgbW9yZSBjb21wYWN0IGFuZCBmYXN0ZXIgdGhhbiBgTWF0aC5mbG9vcigpYC5cbiAgICAgICAgaWQgKz0gdXJsQWxwaGFiZXRbKE1hdGgucmFuZG9tKCkgKiA2NCkgfCAwXVxuICAgIH1cbiAgICByZXR1cm4gaWRcbn1cbiIsICIvKlxuIF8gICAgIF9fICAgICBfIF9fXG58IHwgIC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoqXG4gKiBUcnVlIHdoZW4gcnVubmluZyBpbnNpZGUgYSBicm93c2VyL3dlYnZpZXcgd2l0aCBhIERPTSBhdmFpbGFibGUuXG4gKiBGYWxzZSB1bmRlciBzZXJ2ZXItc2lkZSByZW5kZXJpbmcgKGUuZy4gYG5leHQgYnVpbGRgIHByZXJlbmRlcmluZyksXG4gKiB3aGVyZSBhcHBsaWNhdGlvbiBjb2RlIG1heSBpbXBvcnQgdGhlIHJ1bnRpbWUgbW9kdWxlIGV2ZW4gdGhvdWdoIG5vXG4gKiBXYWlscyBBUElzIGNhbiBhY3R1YWxseSBiZSB1c2VkICgjNDY3OSkuIE1vZHVsZXMgbXVzdCBub3QgdG91Y2hcbiAqIGB3aW5kb3dgL2Bkb2N1bWVudGAgYXQgaW1wb3J0IHRpbWUgZXhjZXB0IGJlaGluZCB0aGlzIGd1YXJkLlxuICovXG5leHBvcnQgY29uc3QgaGFzRE9NID0gdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiAmJiB0eXBlb2YgZG9jdW1lbnQgIT09IFwidW5kZWZpbmVkXCI7XG4iLCAiLypcbiBfICAgICBfXyAgICAgXyBfX1xufCB8ICAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbmltcG9ydCB7IG5hbm9pZCB9IGZyb20gXCIuL25hbm9pZC5qc1wiO1xuaW1wb3J0IHsgaGFzRE9NIH0gZnJvbSBcIi4vZW52aXJvbm1lbnQuanNcIjtcblxuLy8gUmVzb2x2ZWQgbGF6aWx5OiB3aW5kb3cgZG9lcyBub3QgZXhpc3Qgd2hlbiB0aGUgbW9kdWxlIGlzIGltcG9ydGVkIGR1cmluZ1xuLy8gc2VydmVyLXNpZGUgcmVuZGVyaW5nICgjNDY3OSksIGFuZCBub3RoaW5nIGNhbiBjYWxsIHRoZSBydW50aW1lIHRoZXJlLlxuZnVuY3Rpb24gcnVudGltZVVSTCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB3aW5kb3cubG9jYXRpb24ub3JpZ2luICsgXCIvd2FpbHMvcnVudGltZVwiO1xufVxuXG4vLyBTdGF5IHVuZGVyIFdlYlZpZXcyJ3MgfjJNQiByZXF1ZXN0IGJvZHkgYnVmZmVyaW5nIGxpbWl0IGluIFdlYlJlc291cmNlUmVxdWVzdGVkLlxuY29uc3QgQ0hVTktfVEhSRVNIT0xEID0gNTEyICogMTAyNDtcblxuLy8gUmUtZXhwb3J0IG5hbm9pZCBmb3IgY3VzdG9tIHRyYW5zcG9ydCBpbXBsZW1lbnRhdGlvbnNcbmV4cG9ydCB7IG5hbm9pZCB9O1xuXG50eXBlIENhbGxFcnJvclR5cGUgPSB7XG4gICAgbWVzc2FnZTogc3RyaW5nLFxuICAgIGNhdXNlPzogdW5rbm93bixcbiAgICBraW5kOiBcIlJlZmVyZW5jZUVycm9yXCIgfCBcIlR5cGVFcnJvclwiIHwgXCJSdW50aW1lRXJyb3JcIlxufVxuXG4vKipcbiAqIEV4Y2VwdGlvbiBjbGFzcyB0aGF0IHdpbGwgYmUgdGhyb3duIGluIGNhc2UgdGhlIGJvdW5kIG1ldGhvZCByZXR1cm5zIGFuIGVycm9yLlxuICogVGhlIHZhbHVlIG9mIHRoZSB7QGxpbmsgUnVudGltZUVycm9yI25hbWV9IHByb3BlcnR5IGlzIFwiUnVudGltZUVycm9yXCIuXG4gKi9cbmV4cG9ydCBjbGFzcyBSdW50aW1lRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gICAgLyoqXG4gICAgICogQ29uc3RydWN0cyBhIG5ldyBSdW50aW1lRXJyb3IgaW5zdGFuY2UuXG4gICAgICogQHBhcmFtIG1lc3NhZ2UgLSBUaGUgZXJyb3IgbWVzc2FnZS5cbiAgICAgKiBAcGFyYW0gb3B0aW9ucyAtIE9wdGlvbnMgdG8gYmUgZm9yd2FyZGVkIHRvIHRoZSBFcnJvciBjb25zdHJ1Y3Rvci5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihtZXNzYWdlPzogc3RyaW5nLCBvcHRpb25zPzogRXJyb3JPcHRpb25zKSB7XG4gICAgICAgIHN1cGVyKG1lc3NhZ2UsIG9wdGlvbnMpO1xuICAgICAgICB0aGlzLm5hbWUgPSBcIlJ1bnRpbWVFcnJvclwiO1xuICAgIH1cbn1cblxuLy8gT2JqZWN0IE5hbWVzXG5leHBvcnQgY29uc3Qgb2JqZWN0TmFtZXMgPSBPYmplY3QuZnJlZXplKHtcbiAgICBDYWxsOiAwLFxuICAgIENsaXBib2FyZDogMSxcbiAgICBBcHBsaWNhdGlvbjogMixcbiAgICBFdmVudHM6IDMsXG4gICAgQ29udGV4dE1lbnU6IDQsXG4gICAgRGlhbG9nOiA1LFxuICAgIFdpbmRvdzogNixcbiAgICBTY3JlZW5zOiA3LFxuICAgIFN5c3RlbTogOCxcbiAgICBCcm93c2VyOiA5LFxuICAgIENhbmNlbENhbGw6IDEwLFxuICAgIElPUzogMTEsXG4gICAgQW5kcm9pZDogMTIsXG59KTtcbmV4cG9ydCBsZXQgY2xpZW50SWQgPSBuYW5vaWQoKTtcblxuLyoqXG4gKiBSdW50aW1lVHJhbnNwb3J0IGRlZmluZXMgdGhlIGludGVyZmFjZSBmb3IgY3VzdG9tIElQQyB0cmFuc3BvcnQgaW1wbGVtZW50YXRpb25zLlxuICogSW1wbGVtZW50IHRoaXMgaW50ZXJmYWNlIHRvIHVzZSBXZWJTb2NrZXRzLCBjdXN0b20gcHJvdG9jb2xzLCBvciBhbnkgb3RoZXJcbiAqIHRyYW5zcG9ydCBtZWNoYW5pc20gaW5zdGVhZCBvZiB0aGUgZGVmYXVsdCBIVFRQIGZldGNoLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJ1bnRpbWVUcmFuc3BvcnQge1xuICAgIC8qKlxuICAgICAqIFNlbmQgYSBydW50aW1lIGNhbGwgYW5kIHJldHVybiB0aGUgcmVzcG9uc2UuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gb2JqZWN0SUQgLSBUaGUgV2FpbHMgb2JqZWN0IElEICgwPUNhbGwsIDE9Q2xpcGJvYXJkLCBldGMuKVxuICAgICAqIEBwYXJhbSBtZXRob2QgLSBUaGUgbWV0aG9kIElEIHRvIGNhbGxcbiAgICAgKiBAcGFyYW0gd2luZG93TmFtZSAtIE9wdGlvbmFsIHdpbmRvdyBuYW1lXG4gICAgICogQHBhcmFtIGFyZ3MgLSBBcmd1bWVudHMgdG8gcGFzcyAod2lsbCBiZSBKU09OIHN0cmluZ2lmaWVkIGlmIHByZXNlbnQpXG4gICAgICogQHJldHVybnMgUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIHJlc3BvbnNlIGRhdGFcbiAgICAgKi9cbiAgICBjYWxsKG9iamVjdElEOiBudW1iZXIsIG1ldGhvZDogbnVtYmVyLCB3aW5kb3dOYW1lOiBzdHJpbmcsIGFyZ3M6IGFueSk6IFByb21pc2U8YW55Pjtcbn1cblxuLyoqXG4gKiBDdXN0b20gdHJhbnNwb3J0IGltcGxlbWVudGF0aW9uIChjYW4gYmUgc2V0IGJ5IHVzZXIpXG4gKi9cbmxldCBjdXN0b21UcmFuc3BvcnQ6IFJ1bnRpbWVUcmFuc3BvcnQgfCBudWxsID0gbnVsbDtcblxuLyoqXG4gKiBTZXQgYSBjdXN0b20gdHJhbnNwb3J0IGZvciBhbGwgV2FpbHMgcnVudGltZSBjYWxscy5cbiAqIFRoaXMgYWxsb3dzIHlvdSB0byByZXBsYWNlIHRoZSBkZWZhdWx0IEhUVFAgZmV0Y2ggdHJhbnNwb3J0IHdpdGhcbiAqIFdlYlNvY2tldHMsIGN1c3RvbSBwcm90b2NvbHMsIG9yIGFueSBvdGhlciBtZWNoYW5pc20uXG4gKlxuICogQHBhcmFtIHRyYW5zcG9ydCAtIFlvdXIgY3VzdG9tIHRyYW5zcG9ydCBpbXBsZW1lbnRhdGlvblxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBpbXBvcnQgeyBzZXRUcmFuc3BvcnQgfSBmcm9tICcvd2FpbHMvcnVudGltZS5qcyc7XG4gKlxuICogY29uc3Qgd3NUcmFuc3BvcnQgPSB7XG4gKiAgIGNhbGw6IGFzeW5jIChvYmplY3RJRCwgbWV0aG9kLCB3aW5kb3dOYW1lLCBhcmdzKSA9PiB7XG4gKiAgICAgLy8gWW91ciBXZWJTb2NrZXQgaW1wbGVtZW50YXRpb25cbiAqICAgfVxuICogfTtcbiAqXG4gKiBzZXRUcmFuc3BvcnQod3NUcmFuc3BvcnQpO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRUcmFuc3BvcnQodHJhbnNwb3J0OiBSdW50aW1lVHJhbnNwb3J0IHwgbnVsbCk6IHZvaWQge1xuICAgIGN1c3RvbVRyYW5zcG9ydCA9IHRyYW5zcG9ydDtcbn1cblxuLyoqXG4gKiBHZXQgdGhlIGN1cnJlbnQgdHJhbnNwb3J0ICh1c2VmdWwgZm9yIGV4dGVuZGluZy93cmFwcGluZylcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFRyYW5zcG9ydCgpOiBSdW50aW1lVHJhbnNwb3J0IHwgbnVsbCB7XG4gICAgcmV0dXJuIGN1c3RvbVRyYW5zcG9ydDtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IHJ1bnRpbWUgY2FsbGVyIHdpdGggc3BlY2lmaWVkIElELlxuICpcbiAqIEBwYXJhbSBvYmplY3QgLSBUaGUgb2JqZWN0IHRvIGludm9rZSB0aGUgbWV0aG9kIG9uLlxuICogQHBhcmFtIHdpbmRvd05hbWUgLSBUaGUgbmFtZSBvZiB0aGUgd2luZG93LlxuICogQHJldHVybiBUaGUgbmV3IHJ1bnRpbWUgY2FsbGVyIGZ1bmN0aW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbmV3UnVudGltZUNhbGxlcihvYmplY3Q6IG51bWJlciwgd2luZG93TmFtZTogc3RyaW5nID0gJycpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKG1ldGhvZDogbnVtYmVyLCBhcmdzOiBhbnkgPSBudWxsKSB7XG4gICAgICAgIHJldHVybiBydW50aW1lQ2FsbFdpdGhJRChvYmplY3QsIG1ldGhvZCwgd2luZG93TmFtZSwgYXJncyk7XG4gICAgfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gcnVudGltZUNhbGxXaXRoSUQob2JqZWN0SUQ6IG51bWJlciwgbWV0aG9kOiBudW1iZXIsIHdpbmRvd05hbWU6IHN0cmluZywgYXJnczogYW55KTogUHJvbWlzZTxhbnk+IHtcbiAgICAvLyBVc2UgY3VzdG9tIHRyYW5zcG9ydCBpZiBhdmFpbGFibGVcbiAgICBpZiAoY3VzdG9tVHJhbnNwb3J0KSB7XG4gICAgICAgIHJldHVybiBjdXN0b21UcmFuc3BvcnQuY2FsbChvYmplY3RJRCwgbWV0aG9kLCB3aW5kb3dOYW1lLCBhcmdzKTtcbiAgICB9XG5cbiAgICAvLyBEZWZhdWx0IEhUVFAgZmV0Y2ggdHJhbnNwb3J0XG4gICAgbGV0IHVybCA9IG5ldyBVUkwocnVudGltZVVSTCgpKTtcblxuICAgIGxldCBib2R5OiB7IG9iamVjdDogbnVtYmVyOyBtZXRob2Q6IG51bWJlciwgYXJncz86IGFueSB9ID0ge1xuICAgICAgb2JqZWN0OiBvYmplY3RJRCxcbiAgICAgIG1ldGhvZFxuICAgIH1cbiAgICBpZiAoYXJncyAhPT0gbnVsbCAmJiBhcmdzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGJvZHkuYXJncyA9IGFyZ3M7XG4gICAgfVxuXG4gICAgbGV0IGhlYWRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gICAgICAgIFtcIngtd2FpbHMtY2xpZW50LWlkXCJdOiBjbGllbnRJZCxcbiAgICAgICAgW1wiQ29udGVudC1UeXBlXCJdOiBcImFwcGxpY2F0aW9uL2pzb25cIlxuICAgIH1cbiAgICBpZiAod2luZG93TmFtZSkge1xuICAgICAgICBoZWFkZXJzW1wieC13YWlscy13aW5kb3ctbmFtZVwiXSA9IHdpbmRvd05hbWU7XG4gICAgfVxuXG4gICAgY29uc3QgYm9keVN0ciA9IEpTT04uc3RyaW5naWZ5KGJvZHkpO1xuICAgIGxldCByZXNwb25zZTogUmVzcG9uc2U7XG4gICAgaWYgKGJvZHlTdHIubGVuZ3RoID4gQ0hVTktfVEhSRVNIT0xEKSB7XG4gICAgICAgIHJlc3BvbnNlID0gYXdhaXQgc2VuZENodW5rZWQodXJsLCBoZWFkZXJzLCBib2R5U3RyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXNwb25zZSA9IGF3YWl0IGZldGNoKHVybCwgeyBtZXRob2Q6ICdQT1NUJywgaGVhZGVycywgYm9keTogYm9keVN0ciB9KTtcbiAgICB9XG4gICAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgICAgY29uc3QgY3QgPSByZXNwb25zZS5oZWFkZXJzLmdldChcIkNvbnRlbnQtVHlwZVwiKTtcbiAgICAgIGlmIChjdD8uaW5jbHVkZXMoXCJhcHBsaWNhdGlvbi9qc29uXCIpKSB7XG4gICAgICAgICAgY29uc3QganNvbjogQ2FsbEVycm9yVHlwZSA9IGF3YWl0IHJlc3BvbnNlLmpzb24oKTtcbiAgICAgICAgICBsZXQgZXJyO1xuICAgICAgICAgIHN3aXRjaCAoanNvbi5raW5kKSB7XG4gICAgICAgICAgICAgIGNhc2UgXCJSZWZlcmVuY2VFcnJvclwiOiBlcnIgPSBuZXcgUmVmZXJlbmNlRXJyb3IoanNvbi5tZXNzYWdlKTsgYnJlYWs7XG4gICAgICAgICAgICAgIGNhc2UgXCJUeXBlRXJyb3JcIjogICAgICBlcnIgPSBuZXcgVHlwZUVycm9yKGpzb24ubWVzc2FnZSk7IGJyZWFrO1xuICAgICAgICAgICAgICBjYXNlIFwiUnVudGltZUVycm9yXCI6ICAgZXJyID0gbmV3IFJ1bnRpbWVFcnJvcihqc29uLm1lc3NhZ2UpOyBicmVhaztcbiAgICAgICAgICAgICAgZGVmYXVsdDogICAgICAgICAgICAgICBlcnIgPSBuZXcgRXJyb3IoanNvbi5tZXNzYWdlKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZXJyLmNhdXNlID0ganNvbi5jYXVzZTtcbiAgICAgICAgICB0aHJvdyBlcnJcbiAgICAgIH1cbiAgICAgIHRocm93IG5ldyBFcnJvcihhd2FpdCByZXNwb25zZS50ZXh0KCkpO1xuICAgIH1cblxuICAgIGlmICgocmVzcG9uc2UuaGVhZGVycy5nZXQoXCJDb250ZW50LVR5cGVcIik/LmluZGV4T2YoXCJhcHBsaWNhdGlvbi9qc29uXCIpID8/IC0xKSAhPT0gLTEpIHtcbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gcmVzcG9uc2UudGV4dCgpO1xuICAgIH1cbn1cblxuLy8gc2VuZENodW5rZWQgc3BsaXRzIGEgbGFyZ2Ugc2VyaWFsaXNlZCByZXF1ZXN0IGJvZHkgaW50byBDSFVOS19USFJFU0hPTEQtc2l6ZWRcbi8vIGJ5dGUgY2h1bmtzIGFuZCBzZW5kcyB0aGVtIHNlcmlhbGx5LiAgRW5jb2RpbmcgdG8gVVRGLTggYnl0ZXMgYmVmb3JlIHNsaWNpbmdcbi8vIHByZXZlbnRzIGNvcnJ1cHRpb24gb2Ygbm9uLUJNUCBjaGFyYWN0ZXJzIChzdXJyb2dhdGUgcGFpcnMpIHRoYXQgd291bGQgb2NjdXJcbi8vIHdoZW4gc3BsaXR0aW5nIGF0IEphdmFTY3JpcHQgc3RyaW5nIGluZGljZXMuICBUaGUgR28gdHJhbnNwb3J0IGFzc2VtYmxlcyB0aGVcbi8vIHJhdyBieXRlcyBiZWZvcmUgcHJvY2Vzc2luZy4gIE9ubHkgdGhlIGZpbmFsIGNodW5rJ3MgcmVzcG9uc2UgY2FycmllcyB0aGUgUlBDIHJlc3VsdC5cbmFzeW5jIGZ1bmN0aW9uIHNlbmRDaHVua2VkKHVybDogVVJMLCBoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+LCBib2R5U3RyOiBzdHJpbmcpOiBQcm9taXNlPFJlc3BvbnNlPiB7XG4gICAgY29uc3QgY2h1bmtJZCA9IG5hbm9pZCgpO1xuICAgIGNvbnN0IGJvZHlCeXRlcyA9IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShib2R5U3RyKTtcbiAgICBjb25zdCB0b3RhbENodW5rcyA9IE1hdGguY2VpbChib2R5Qnl0ZXMubGVuZ3RoIC8gQ0hVTktfVEhSRVNIT0xEKTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdG90YWxDaHVua3MgLSAxOyBpKyspIHtcbiAgICAgICAgY29uc3QgY2h1bmsgPSBib2R5Qnl0ZXMuc3ViYXJyYXkoaSAqIENIVU5LX1RIUkVTSE9MRCwgKGkgKyAxKSAqIENIVU5LX1RIUkVTSE9MRCk7XG4gICAgICAgIGNvbnN0IHJlc3AgPSBhd2FpdCBmZXRjaCh1cmwsIHtcbiAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICAgICAgIC4uLmhlYWRlcnMsXG4gICAgICAgICAgICAgICAgJ3gtd2FpbHMtY2h1bmstaWQnOiBjaHVua0lkLFxuICAgICAgICAgICAgICAgICd4LXdhaWxzLWNodW5rLWluZGV4JzogU3RyaW5nKGkpLFxuICAgICAgICAgICAgICAgICd4LXdhaWxzLWNodW5rLXRvdGFsJzogU3RyaW5nKHRvdGFsQ2h1bmtzKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBib2R5OiBjaHVuayxcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICghcmVzcC5vaykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGF3YWl0IHJlc3AudGV4dCgpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmZXRjaCh1cmwsIHtcbiAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICAgIC4uLmhlYWRlcnMsXG4gICAgICAgICAgICAneC13YWlscy1jaHVuay1pZCc6IGNodW5rSWQsXG4gICAgICAgICAgICAneC13YWlscy1jaHVuay1pbmRleCc6IFN0cmluZyh0b3RhbENodW5rcyAtIDEpLFxuICAgICAgICAgICAgJ3gtd2FpbHMtY2h1bmstdG90YWwnOiBTdHJpbmcodG90YWxDaHVua3MpLFxuICAgICAgICB9LFxuICAgICAgICBib2R5OiBib2R5Qnl0ZXMuc3ViYXJyYXkoKHRvdGFsQ2h1bmtzIC0gMSkgKiBDSFVOS19USFJFU0hPTEQpLFxuICAgIH0pO1xufVxuXG4vKipcbiAqIEFuZHJvaWQgV2ViVmlldyBjYW5ub3QgZGVsaXZlciBmZXRjaCgpIFBPU1QgYm9kaWVzIHRvXG4gKiBzaG91bGRJbnRlcmNlcHRSZXF1ZXN0LCBzbyB0aGUgZGVmYXVsdCBIVFRQIHRyYW5zcG9ydCBjYW5ub3QgcmVhY2ggR28uXG4gKiBXaGVuIHRoZSBBbmRyb2lkIEphdmFzY3JpcHRJbnRlcmZhY2UgYnJpZGdlICh3aW5kb3cud2FpbHMpIGlzIHByZXNlbnQsXG4gKiByb3V0ZSBydW50aW1lIGNhbGxzIHRocm91Z2ggaXQgaW5zdGVhZC4gUmVzcG9uc2VzIGFycml2ZSB2aWFcbiAqIHdpbmRvdy5fd2FpbHNBbmRyb2lkQ2FsbGJhY2ssIGludm9rZWQgYnkgdGhlIEphdmEgc2lkZS5cbiAqL1xuaW50ZXJmYWNlIEFuZHJvaWRKU0JyaWRnZSB7XG4gICAgaW52b2tlQXN5bmMoY2FsbGJhY2tJRDogc3RyaW5nLCBwYXlsb2FkOiBzdHJpbmcpOiB2b2lkO1xufVxuXG5jb25zdCBhbmRyb2lkQnJpZGdlOiBBbmRyb2lkSlNCcmlkZ2UgfCBudWxsID0gaGFzRE9NICYmXG4gICAgdHlwZW9mICh3aW5kb3cgYXMgYW55KS53YWlscz8uaW52b2tlQXN5bmMgPT09IFwiZnVuY3Rpb25cIiA/ICh3aW5kb3cgYXMgYW55KS53YWlscyA6IG51bGw7XG5cbmlmIChhbmRyb2lkQnJpZGdlKSB7XG4gICAgY29uc3QgcGVuZGluZyA9IG5ldyBNYXA8c3RyaW5nLCB7IHJlc29sdmU6ICh2YWx1ZTogYW55KSA9PiB2b2lkOyByZWplY3Q6IChyZWFzb246IGFueSkgPT4gdm9pZCB9PigpO1xuXG4gICAgKHdpbmRvdyBhcyBhbnkpLl93YWlsc0FuZHJvaWRDYWxsYmFjayA9IChpZDogc3RyaW5nLCByZXNwb25zZTogc3RyaW5nIHwgbnVsbCwgZXJyb3I6IHN0cmluZyB8IG51bGwpID0+IHtcbiAgICAgICAgY29uc3QgcHJvbWlzZSA9IHBlbmRpbmcuZ2V0KGlkKTtcbiAgICAgICAgaWYgKCFwcm9taXNlKSByZXR1cm47XG4gICAgICAgIHBlbmRpbmcuZGVsZXRlKGlkKTtcbiAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICBwcm9taXNlLnJlamVjdChuZXcgRXJyb3IoZXJyb3IpKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgZW52ZWxvcGUgPSBKU09OLnBhcnNlKHJlc3BvbnNlID8/IFwie31cIik7XG4gICAgICAgICAgICBpZiAoIWVudmVsb3BlLm9rKSB7XG4gICAgICAgICAgICAgICAgcHJvbWlzZS5yZWplY3QobmV3IEVycm9yKGVudmVsb3BlLmVycm9yID8/IFwidW5rbm93biBydW50aW1lIGNhbGwgZXJyb3JcIikpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHByb21pc2UucmVzb2x2ZShcInRleHRcIiBpbiBlbnZlbG9wZSA/IGVudmVsb3BlLnRleHQgOiBlbnZlbG9wZS5kYXRhKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgcHJvbWlzZS5yZWplY3QoZSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgY3VzdG9tVHJhbnNwb3J0ID0ge1xuICAgICAgICBjYWxsKG9iamVjdElEOiBudW1iZXIsIG1ldGhvZDogbnVtYmVyLCB3aW5kb3dOYW1lOiBzdHJpbmcsIGFyZ3M6IGFueSk6IFByb21pc2U8YW55PiB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGlkID0gbmFub2lkKCk7XG4gICAgICAgICAgICAgICAgcGVuZGluZy5zZXQoaWQsIHsgcmVzb2x2ZSwgcmVqZWN0IH0pO1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGFuZHJvaWRCcmlkZ2UuaW52b2tlQXN5bmMoaWQsIEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdDogb2JqZWN0SUQsXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRob2Q6IG1ldGhvZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHdpbmRvd05hbWU6IHdpbmRvd05hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICBhcmdzOiBhcmdzID8/IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICBjbGllbnRJZDogY2xpZW50SWQsXG4gICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIERvbid0IGxlYWsgdGhlIHBlbmRpbmcgZW50cnkgaWYgZGlzcGF0Y2ggdGhyb3dzIHN5bmNocm9ub3VzbHlcbiAgICAgICAgICAgICAgICAgICAgcGVuZGluZy5kZWxldGUoaWQpO1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgfTtcbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuaW1wb3J0IHtuZXdSdW50aW1lQ2FsbGVyLCBvYmplY3ROYW1lc30gZnJvbSBcIi4vcnVudGltZS5qc1wiO1xuXG4vLyBzZXR1cFxuaW1wb3J0IHsgaGFzRE9NIH0gZnJvbSBcIi4vZW52aXJvbm1lbnQuanNcIjtcblxuaWYgKGhhc0RPTSkge1xuICAgIHdpbmRvdy5fd2FpbHMgPSB3aW5kb3cuX3dhaWxzIHx8IHt9O1xufVxuXG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcihvYmplY3ROYW1lcy5EaWFsb2cpO1xuXG4vLyBEZWZpbmUgY29uc3RhbnRzIGZyb20gdGhlIGBtZXRob2RzYCBvYmplY3QgaW4gVGl0bGUgQ2FzZVxuY29uc3QgRGlhbG9nSW5mbyA9IDA7XG5jb25zdCBEaWFsb2dXYXJuaW5nID0gMTtcbmNvbnN0IERpYWxvZ0Vycm9yID0gMjtcbmNvbnN0IERpYWxvZ1F1ZXN0aW9uID0gMztcbmNvbnN0IERpYWxvZ09wZW5GaWxlID0gNDtcbmNvbnN0IERpYWxvZ1NhdmVGaWxlID0gNTtcblxuZXhwb3J0IGludGVyZmFjZSBPcGVuRmlsZURpYWxvZ09wdGlvbnMge1xuICAgIC8qKiBJbmRpY2F0ZXMgaWYgZGlyZWN0b3JpZXMgY2FuIGJlIGNob3Nlbi4gKi9cbiAgICBDYW5DaG9vc2VEaXJlY3Rvcmllcz86IGJvb2xlYW47XG4gICAgLyoqIEluZGljYXRlcyBpZiBmaWxlcyBjYW4gYmUgY2hvc2VuLiAqL1xuICAgIENhbkNob29zZUZpbGVzPzogYm9vbGVhbjtcbiAgICAvKiogSW5kaWNhdGVzIGlmIGRpcmVjdG9yaWVzIGNhbiBiZSBjcmVhdGVkLiAqL1xuICAgIENhbkNyZWF0ZURpcmVjdG9yaWVzPzogYm9vbGVhbjtcbiAgICAvKiogSW5kaWNhdGVzIGlmIGhpZGRlbiBmaWxlcyBzaG91bGQgYmUgc2hvd24uICovXG4gICAgU2hvd0hpZGRlbkZpbGVzPzogYm9vbGVhbjtcbiAgICAvKiogSW5kaWNhdGVzIGlmIGFsaWFzZXMgc2hvdWxkIGJlIHJlc29sdmVkLiAqL1xuICAgIFJlc29sdmVzQWxpYXNlcz86IGJvb2xlYW47XG4gICAgLyoqIEluZGljYXRlcyBpZiBtdWx0aXBsZSBzZWxlY3Rpb24gaXMgYWxsb3dlZC4gKi9cbiAgICBBbGxvd3NNdWx0aXBsZVNlbGVjdGlvbj86IGJvb2xlYW47XG4gICAgLyoqIEluZGljYXRlcyBpZiB0aGUgZXh0ZW5zaW9uIHNob3VsZCBiZSBoaWRkZW4uICovXG4gICAgSGlkZUV4dGVuc2lvbj86IGJvb2xlYW47XG4gICAgLyoqIEluZGljYXRlcyBpZiBoaWRkZW4gZXh0ZW5zaW9ucyBjYW4gYmUgc2VsZWN0ZWQuICovXG4gICAgQ2FuU2VsZWN0SGlkZGVuRXh0ZW5zaW9uPzogYm9vbGVhbjtcbiAgICAvKiogSW5kaWNhdGVzIGlmIGZpbGUgcGFja2FnZXMgc2hvdWxkIGJlIHRyZWF0ZWQgYXMgZGlyZWN0b3JpZXMuICovXG4gICAgVHJlYXRzRmlsZVBhY2thZ2VzQXNEaXJlY3Rvcmllcz86IGJvb2xlYW47XG4gICAgLyoqIEluZGljYXRlcyBpZiBvdGhlciBmaWxlIHR5cGVzIGFyZSBhbGxvd2VkLiAqL1xuICAgIEFsbG93c090aGVyRmlsZXR5cGVzPzogYm9vbGVhbjtcbiAgICAvKiogQXJyYXkgb2YgZmlsZSBmaWx0ZXJzLiAqL1xuICAgIEZpbHRlcnM/OiBGaWxlRmlsdGVyW107XG4gICAgLyoqIFRpdGxlIG9mIHRoZSBkaWFsb2cuICovXG4gICAgVGl0bGU/OiBzdHJpbmc7XG4gICAgLyoqIE1lc3NhZ2UgdG8gc2hvdyBpbiB0aGUgZGlhbG9nLiAqL1xuICAgIE1lc3NhZ2U/OiBzdHJpbmc7XG4gICAgLyoqIFRleHQgdG8gZGlzcGxheSBvbiB0aGUgYnV0dG9uLiAqL1xuICAgIEJ1dHRvblRleHQ/OiBzdHJpbmc7XG4gICAgLyoqIERpcmVjdG9yeSB0byBvcGVuIGluIHRoZSBkaWFsb2cuICovXG4gICAgRGlyZWN0b3J5Pzogc3RyaW5nO1xuICAgIC8qKiBJbmRpY2F0ZXMgaWYgdGhlIGRpYWxvZyBzaG91bGQgYXBwZWFyIGRldGFjaGVkIGZyb20gdGhlIG1haW4gd2luZG93LiAqL1xuICAgIERldGFjaGVkPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTYXZlRmlsZURpYWxvZ09wdGlvbnMge1xuICAgIC8qKiBEZWZhdWx0IGZpbGVuYW1lIHRvIHVzZSBpbiB0aGUgZGlhbG9nLiAqL1xuICAgIEZpbGVuYW1lPzogc3RyaW5nO1xuICAgIC8qKiBJbmRpY2F0ZXMgaWYgZGlyZWN0b3JpZXMgY2FuIGJlIGNob3Nlbi4gKi9cbiAgICBDYW5DaG9vc2VEaXJlY3Rvcmllcz86IGJvb2xlYW47XG4gICAgLyoqIEluZGljYXRlcyBpZiBmaWxlcyBjYW4gYmUgY2hvc2VuLiAqL1xuICAgIENhbkNob29zZUZpbGVzPzogYm9vbGVhbjtcbiAgICAvKiogSW5kaWNhdGVzIGlmIGRpcmVjdG9yaWVzIGNhbiBiZSBjcmVhdGVkLiAqL1xuICAgIENhbkNyZWF0ZURpcmVjdG9yaWVzPzogYm9vbGVhbjtcbiAgICAvKiogSW5kaWNhdGVzIGlmIGhpZGRlbiBmaWxlcyBzaG91bGQgYmUgc2hvd24uICovXG4gICAgU2hvd0hpZGRlbkZpbGVzPzogYm9vbGVhbjtcbiAgICAvKiogSW5kaWNhdGVzIGlmIGFsaWFzZXMgc2hvdWxkIGJlIHJlc29sdmVkLiAqL1xuICAgIFJlc29sdmVzQWxpYXNlcz86IGJvb2xlYW47XG4gICAgLyoqIEluZGljYXRlcyBpZiB0aGUgZXh0ZW5zaW9uIHNob3VsZCBiZSBoaWRkZW4uICovXG4gICAgSGlkZUV4dGVuc2lvbj86IGJvb2xlYW47XG4gICAgLyoqIEluZGljYXRlcyBpZiBoaWRkZW4gZXh0ZW5zaW9ucyBjYW4gYmUgc2VsZWN0ZWQuICovXG4gICAgQ2FuU2VsZWN0SGlkZGVuRXh0ZW5zaW9uPzogYm9vbGVhbjtcbiAgICAvKiogSW5kaWNhdGVzIGlmIGZpbGUgcGFja2FnZXMgc2hvdWxkIGJlIHRyZWF0ZWQgYXMgZGlyZWN0b3JpZXMuICovXG4gICAgVHJlYXRzRmlsZVBhY2thZ2VzQXNEaXJlY3Rvcmllcz86IGJvb2xlYW47XG4gICAgLyoqIEluZGljYXRlcyBpZiBvdGhlciBmaWxlIHR5cGVzIGFyZSBhbGxvd2VkLiAqL1xuICAgIEFsbG93c090aGVyRmlsZXR5cGVzPzogYm9vbGVhbjtcbiAgICAvKiogQXJyYXkgb2YgZmlsZSBmaWx0ZXJzLiAqL1xuICAgIEZpbHRlcnM/OiBGaWxlRmlsdGVyW107XG4gICAgLyoqIFRpdGxlIG9mIHRoZSBkaWFsb2cuICovXG4gICAgVGl0bGU/OiBzdHJpbmc7XG4gICAgLyoqIE1lc3NhZ2UgdG8gc2hvdyBpbiB0aGUgZGlhbG9nLiAqL1xuICAgIE1lc3NhZ2U/OiBzdHJpbmc7XG4gICAgLyoqIFRleHQgdG8gZGlzcGxheSBvbiB0aGUgYnV0dG9uLiAqL1xuICAgIEJ1dHRvblRleHQ/OiBzdHJpbmc7XG4gICAgLyoqIERpcmVjdG9yeSB0byBvcGVuIGluIHRoZSBkaWFsb2cuICovXG4gICAgRGlyZWN0b3J5Pzogc3RyaW5nO1xuICAgIC8qKiBJbmRpY2F0ZXMgaWYgdGhlIGRpYWxvZyBzaG91bGQgYXBwZWFyIGRldGFjaGVkIGZyb20gdGhlIG1haW4gd2luZG93LiAqL1xuICAgIERldGFjaGVkPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBNZXNzYWdlRGlhbG9nT3B0aW9ucyB7XG4gICAgLyoqIFRoZSB0aXRsZSBvZiB0aGUgZGlhbG9nIHdpbmRvdy4gKi9cbiAgICBUaXRsZT86IHN0cmluZztcbiAgICAvKiogVGhlIG1haW4gbWVzc2FnZSB0byBzaG93IGluIHRoZSBkaWFsb2cuICovXG4gICAgTWVzc2FnZT86IHN0cmluZztcbiAgICAvKiogQXJyYXkgb2YgYnV0dG9uIG9wdGlvbnMgdG8gc2hvdyBpbiB0aGUgZGlhbG9nLiAqL1xuICAgIEJ1dHRvbnM/OiBCdXR0b25bXTtcbiAgICAvKiogVHJ1ZSBpZiB0aGUgZGlhbG9nIHNob3VsZCBhcHBlYXIgZGV0YWNoZWQgZnJvbSB0aGUgbWFpbiB3aW5kb3cgKGlmIGFwcGxpY2FibGUpLiAqL1xuICAgIERldGFjaGVkPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBCdXR0b24ge1xuICAgIC8qKiBUZXh0IHRoYXQgYXBwZWFycyB3aXRoaW4gdGhlIGJ1dHRvbi4gKi9cbiAgICBMYWJlbD86IHN0cmluZztcbiAgICAvKiogVHJ1ZSBpZiB0aGUgYnV0dG9uIHNob3VsZCBjYW5jZWwgYW4gb3BlcmF0aW9uIHdoZW4gY2xpY2tlZC4gKi9cbiAgICBJc0NhbmNlbD86IGJvb2xlYW47XG4gICAgLyoqIFRydWUgaWYgdGhlIGJ1dHRvbiBzaG91bGQgYmUgdGhlIGRlZmF1bHQgYWN0aW9uIHdoZW4gdGhlIHVzZXIgcHJlc3NlcyBlbnRlci4gKi9cbiAgICBJc0RlZmF1bHQ/OiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEZpbGVGaWx0ZXIge1xuICAgIC8qKiBEaXNwbGF5IG5hbWUgZm9yIHRoZSBmaWx0ZXIsIGl0IGNvdWxkIGJlIFwiVGV4dCBGaWxlc1wiLCBcIkltYWdlc1wiIGV0Yy4gKi9cbiAgICBEaXNwbGF5TmFtZT86IHN0cmluZztcbiAgICAvKiogUGF0dGVybiB0byBtYXRjaCBmb3IgdGhlIGZpbHRlciwgZS5nLiBcIioudHh0OyoubWRcIiBmb3IgdGV4dCBtYXJrZG93biBmaWxlcy4gKi9cbiAgICBQYXR0ZXJuPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFByZXNlbnRzIGEgZGlhbG9nIG9mIHNwZWNpZmllZCB0eXBlIHdpdGggdGhlIGdpdmVuIG9wdGlvbnMuXG4gKlxuICogQHBhcmFtIHR5cGUgLSBEaWFsb2cgdHlwZS5cbiAqIEBwYXJhbSBvcHRpb25zIC0gT3B0aW9ucyBmb3IgdGhlIGRpYWxvZy5cbiAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggcmVzdWx0IG9mIGRpYWxvZy5cbiAqL1xuZnVuY3Rpb24gZGlhbG9nKHR5cGU6IG51bWJlciwgb3B0aW9uczogTWVzc2FnZURpYWxvZ09wdGlvbnMgfCBPcGVuRmlsZURpYWxvZ09wdGlvbnMgfCBTYXZlRmlsZURpYWxvZ09wdGlvbnMgPSB7fSk6IFByb21pc2U8YW55PiB7XG4gICAgcmV0dXJuIGNhbGwodHlwZSwgb3B0aW9ucyk7XG59XG5cbi8qKlxuICogUHJlc2VudHMgYW4gaW5mbyBkaWFsb2cuXG4gKlxuICogQHBhcmFtIG9wdGlvbnMgLSBEaWFsb2cgb3B0aW9uc1xuICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgbGFiZWwgb2YgdGhlIGNob3NlbiBidXR0b24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJbmZvKG9wdGlvbnM6IE1lc3NhZ2VEaWFsb2dPcHRpb25zKTogUHJvbWlzZTxzdHJpbmc+IHsgcmV0dXJuIGRpYWxvZyhEaWFsb2dJbmZvLCBvcHRpb25zKTsgfVxuXG4vKipcbiAqIFByZXNlbnRzIGEgd2FybmluZyBkaWFsb2cuXG4gKlxuICogQHBhcmFtIG9wdGlvbnMgLSBEaWFsb2cgb3B0aW9ucy5cbiAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIGxhYmVsIG9mIHRoZSBjaG9zZW4gYnV0dG9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gV2FybmluZyhvcHRpb25zOiBNZXNzYWdlRGlhbG9nT3B0aW9ucyk6IFByb21pc2U8c3RyaW5nPiB7IHJldHVybiBkaWFsb2coRGlhbG9nV2FybmluZywgb3B0aW9ucyk7IH1cblxuLyoqXG4gKiBQcmVzZW50cyBhbiBlcnJvciBkaWFsb2cuXG4gKlxuICogQHBhcmFtIG9wdGlvbnMgLSBEaWFsb2cgb3B0aW9ucy5cbiAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIGxhYmVsIG9mIHRoZSBjaG9zZW4gYnV0dG9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gRXJyb3Iob3B0aW9uczogTWVzc2FnZURpYWxvZ09wdGlvbnMpOiBQcm9taXNlPHN0cmluZz4geyByZXR1cm4gZGlhbG9nKERpYWxvZ0Vycm9yLCBvcHRpb25zKTsgfVxuXG4vKipcbiAqIFByZXNlbnRzIGEgcXVlc3Rpb24gZGlhbG9nLlxuICpcbiAqIEBwYXJhbSBvcHRpb25zIC0gRGlhbG9nIG9wdGlvbnMuXG4gKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBsYWJlbCBvZiB0aGUgY2hvc2VuIGJ1dHRvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFF1ZXN0aW9uKG9wdGlvbnM6IE1lc3NhZ2VEaWFsb2dPcHRpb25zKTogUHJvbWlzZTxzdHJpbmc+IHsgcmV0dXJuIGRpYWxvZyhEaWFsb2dRdWVzdGlvbiwgb3B0aW9ucyk7IH1cblxuLyoqXG4gKiBQcmVzZW50cyBhIGZpbGUgc2VsZWN0aW9uIGRpYWxvZyB0byBwaWNrIG9uZSBvciBtb3JlIGZpbGVzIHRvIG9wZW4uXG4gKlxuICogQHBhcmFtIG9wdGlvbnMgLSBEaWFsb2cgb3B0aW9ucy5cbiAqIEByZXR1cm5zIFNlbGVjdGVkIGZpbGUgb3IgbGlzdCBvZiBmaWxlcywgb3IgYSBibGFuayBzdHJpbmcvZW1wdHkgbGlzdCBpZiBubyBmaWxlIGhhcyBiZWVuIHNlbGVjdGVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gT3BlbkZpbGUob3B0aW9uczogT3BlbkZpbGVEaWFsb2dPcHRpb25zICYgeyBBbGxvd3NNdWx0aXBsZVNlbGVjdGlvbjogdHJ1ZSB9KTogUHJvbWlzZTxzdHJpbmdbXT47XG5leHBvcnQgZnVuY3Rpb24gT3BlbkZpbGUob3B0aW9uczogT3BlbkZpbGVEaWFsb2dPcHRpb25zICYgeyBBbGxvd3NNdWx0aXBsZVNlbGVjdGlvbj86IGZhbHNlIHwgdW5kZWZpbmVkIH0pOiBQcm9taXNlPHN0cmluZz47XG5leHBvcnQgZnVuY3Rpb24gT3BlbkZpbGUob3B0aW9uczogT3BlbkZpbGVEaWFsb2dPcHRpb25zKTogUHJvbWlzZTxzdHJpbmcgfCBzdHJpbmdbXT47XG5leHBvcnQgZnVuY3Rpb24gT3BlbkZpbGUob3B0aW9uczogT3BlbkZpbGVEaWFsb2dPcHRpb25zKTogUHJvbWlzZTxzdHJpbmcgfCBzdHJpbmdbXT4geyByZXR1cm4gZGlhbG9nKERpYWxvZ09wZW5GaWxlLCBvcHRpb25zKSA/PyBbXTsgfVxuXG4vKipcbiAqIFByZXNlbnRzIGEgZmlsZSBzZWxlY3Rpb24gZGlhbG9nIHRvIHBpY2sgYSBmaWxlIHRvIHNhdmUuXG4gKlxuICogQHBhcmFtIG9wdGlvbnMgLSBEaWFsb2cgb3B0aW9ucy5cbiAqIEByZXR1cm5zIFNlbGVjdGVkIGZpbGUsIG9yIGEgYmxhbmsgc3RyaW5nIGlmIG5vIGZpbGUgaGFzIGJlZW4gc2VsZWN0ZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTYXZlRmlsZShvcHRpb25zOiBTYXZlRmlsZURpYWxvZ09wdGlvbnMpOiBQcm9taXNlPHN0cmluZz4geyByZXR1cm4gZGlhbG9nKERpYWxvZ1NhdmVGaWxlLCBvcHRpb25zKTsgfVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG5pbXBvcnQgeyBuZXdSdW50aW1lQ2FsbGVyLCBvYmplY3ROYW1lcyB9IGZyb20gXCIuL3J1bnRpbWUuanNcIjtcbmltcG9ydCB7IGV2ZW50TGlzdGVuZXJzLCBMaXN0ZW5lciwgbGlzdGVuZXJPZmYgfSBmcm9tIFwiLi9saXN0ZW5lci5qc1wiO1xuaW1wb3J0IHsgRXZlbnRzIGFzIENyZWF0ZSB9IGZyb20gXCIuL2NyZWF0ZS5qc1wiO1xuaW1wb3J0IHsgVHlwZXMgfSBmcm9tIFwiLi9ldmVudF90eXBlcy5qc1wiO1xuXG4vLyBTZXR1cFxuaW1wb3J0IHsgaGFzRE9NIH0gZnJvbSBcIi4vZW52aXJvbm1lbnQuanNcIjtcblxuaWYgKGhhc0RPTSkge1xuICAgIHdpbmRvdy5fd2FpbHMgPSB3aW5kb3cuX3dhaWxzIHx8IHt9O1xuICAgIHdpbmRvdy5fd2FpbHMuZGlzcGF0Y2hXYWlsc0V2ZW50ID0gZGlzcGF0Y2hXYWlsc0V2ZW50O1xufVxuXG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcihvYmplY3ROYW1lcy5FdmVudHMpO1xuY29uc3QgRW1pdE1ldGhvZCA9IDA7XG5cbmV4cG9ydCAqIGZyb20gXCIuL2V2ZW50X3R5cGVzLmpzXCI7XG5cbi8qKlxuICogQSB0YWJsZSBvZiBkYXRhIHR5cGVzIGZvciBhbGwga25vd24gZXZlbnRzLlxuICogV2lsbCBiZSBtb25rZXktcGF0Y2hlZCBieSB0aGUgYmluZGluZyBnZW5lcmF0b3IuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ3VzdG9tRXZlbnRzIHt9XG5cbi8qKlxuICogRWl0aGVyIGEga25vd24gZXZlbnQgbmFtZSBvciBhbiBhcmJpdHJhcnkgc3RyaW5nLlxuICovXG5leHBvcnQgdHlwZSBXYWlsc0V2ZW50TmFtZTxFIGV4dGVuZHMga2V5b2YgQ3VzdG9tRXZlbnRzID0ga2V5b2YgQ3VzdG9tRXZlbnRzPiA9IEUgfCAoc3RyaW5nICYge30pO1xuXG4vKipcbiAqIFVuaW9uIG9mIGFsbCBrbm93biBzeXN0ZW0gZXZlbnQgbmFtZXMuXG4gKi9cbnR5cGUgU3lzdGVtRXZlbnROYW1lID0ge1xuICAgIFtLIGluIGtleW9mICh0eXBlb2YgVHlwZXMpXTogKHR5cGVvZiBUeXBlcylbS11ba2V5b2YgKCh0eXBlb2YgVHlwZXMpW0tdKV1cbn0gZXh0ZW5kcyAoaW5mZXIgTSkgPyBNW2tleW9mIE1dIDogbmV2ZXI7XG5cbi8qKlxuICogVGhlIGRhdGEgdHlwZSBhc3NvY2lhdGVkIHRvIGEgZ2l2ZW4gZXZlbnQuXG4gKi9cbmV4cG9ydCB0eXBlIFdhaWxzRXZlbnREYXRhPEUgZXh0ZW5kcyBXYWlsc0V2ZW50TmFtZSA9IFdhaWxzRXZlbnROYW1lPiA9XG4gICAgRSBleHRlbmRzIGtleW9mIEN1c3RvbUV2ZW50cyA/IEN1c3RvbUV2ZW50c1tFXSA6IChFIGV4dGVuZHMgU3lzdGVtRXZlbnROYW1lID8gdm9pZCA6IGFueSk7XG5cbi8qKlxuICogVGhlIHR5cGUgb2YgaGFuZGxlcnMgZm9yIGEgZ2l2ZW4gZXZlbnQuXG4gKi9cbmV4cG9ydCB0eXBlIFdhaWxzRXZlbnRDYWxsYmFjazxFIGV4dGVuZHMgV2FpbHNFdmVudE5hbWUgPSBXYWlsc0V2ZW50TmFtZT4gPSAoZXY6IFdhaWxzRXZlbnQ8RT4pID0+IHZvaWQ7XG5cbi8qKlxuICogUmVwcmVzZW50cyBhIHN5c3RlbSBldmVudCBvciBhIGN1c3RvbSBldmVudCBlbWl0dGVkIHRocm91Z2ggd2FpbHMtcHJvdmlkZWQgZmFjaWxpdGllcy5cbiAqL1xuZXhwb3J0IGNsYXNzIFdhaWxzRXZlbnQ8RSBleHRlbmRzIFdhaWxzRXZlbnROYW1lID0gV2FpbHNFdmVudE5hbWU+IHtcbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgZXZlbnQuXG4gICAgICovXG4gICAgbmFtZTogRTtcblxuICAgIC8qKlxuICAgICAqIE9wdGlvbmFsIGRhdGEgYXNzb2NpYXRlZCB3aXRoIHRoZSBlbWl0dGVkIGV2ZW50LlxuICAgICAqL1xuICAgIGRhdGE6IFdhaWxzRXZlbnREYXRhPEU+O1xuXG4gICAgLyoqXG4gICAgICogTmFtZSBvZiB0aGUgb3JpZ2luYXRpbmcgd2luZG93LiBPbWl0dGVkIGZvciBhcHBsaWNhdGlvbiBldmVudHMuXG4gICAgICogV2lsbCBiZSBvdmVycmlkZGVuIGlmIHNldCBtYW51YWxseS5cbiAgICAgKi9cbiAgICBzZW5kZXI/OiBzdHJpbmc7XG5cbiAgICBjb25zdHJ1Y3RvcihuYW1lOiBFLCBkYXRhOiBXYWlsc0V2ZW50RGF0YTxFPik7XG4gICAgY29uc3RydWN0b3IobmFtZTogV2FpbHNFdmVudERhdGE8RT4gZXh0ZW5kcyBudWxsIHwgdm9pZCA/IEUgOiBuZXZlcilcbiAgICBjb25zdHJ1Y3RvcihuYW1lOiBFLCBkYXRhPzogYW55KSB7XG4gICAgICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gICAgICAgIHRoaXMuZGF0YSA9IGRhdGEgPz8gbnVsbDtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGRpc3BhdGNoV2FpbHNFdmVudChldmVudDogYW55KSB7XG4gICAgbGV0IGxpc3RlbmVycyA9IGV2ZW50TGlzdGVuZXJzLmdldChldmVudC5uYW1lKTtcbiAgICBpZiAoIWxpc3RlbmVycykge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbGV0IHdhaWxzRXZlbnQgPSBuZXcgV2FpbHNFdmVudChcbiAgICAgICAgZXZlbnQubmFtZSxcbiAgICAgICAgKGV2ZW50Lm5hbWUgaW4gQ3JlYXRlKSA/IENyZWF0ZVtldmVudC5uYW1lXShldmVudC5kYXRhKSA6IGV2ZW50LmRhdGFcbiAgICApO1xuICAgIGlmICgnc2VuZGVyJyBpbiBldmVudCkge1xuICAgICAgICB3YWlsc0V2ZW50LnNlbmRlciA9IGV2ZW50LnNlbmRlcjtcbiAgICB9XG5cbiAgICAvLyBEaXNwYXRjaCB0byBhIHNuYXBzaG90LCB0aGVuIHJlbW92ZSBhbGwgZXhwaXJlZCBsaXN0ZW5lcnMgaW4gYSBzaW5nbGVcbiAgICAvLyBwb3N0LWRpc3BhdGNoIGZpbHRlciBvZiB0aGUgbGl2ZSBtYXAuXG4gICAgLy8gLSBXcml0aW5nIHRoZSBzbmFwc2hvdCBiYWNrIHdob2xlc2FsZSB3b3VsZCB1bmRvIHN1YnNjcmlwdGlvbiBjaGFuZ2VzXG4gICAgLy8gICBtYWRlIGluc2lkZSBhIGhhbmRsZXIgKCM0MzkzKS5cbiAgICAvLyAtIENhbGxpbmcgbGlzdGVuZXJPZmYoKSBwZXIgZXhwaXJlZCBsaXN0ZW5lciBpbnNpZGUgdGhlIGxvb3AgaXMgTyhuXHUwMEIyKVxuICAgIC8vICAgd2hlbiBtYW55IGxpc3RlbmVycyBleHBpcmUgb24gdGhlIHNhbWUgZXZlbnQuXG4gICAgLy8gRmlsdGVyaW5nIHRoZSBsaXZlIGFycmF5IG9uY2UgYWZ0ZXIgZGlzcGF0Y2ggaXMgTyhuKSBhbmQgc3RpbGwgaG9ub3Vyc1xuICAgIC8vIGFueSBsaXN0ZW5lcnMgYWRkZWQgb3IgcmVtb3ZlZCBieSBoYW5kbGVycyBkdXJpbmcgZGlzcGF0Y2guXG4gICAgY29uc3QgZXhwaXJlZCA9IG5ldyBTZXQ8TGlzdGVuZXI+KCk7XG4gICAgZm9yIChjb25zdCBsaXN0ZW5lciBvZiBsaXN0ZW5lcnMuc2xpY2UoKSkge1xuICAgICAgICBpZiAobGlzdGVuZXIuZGlzcGF0Y2god2FpbHNFdmVudCkpIHtcbiAgICAgICAgICAgIGV4cGlyZWQuYWRkKGxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoZXhwaXJlZC5zaXplID4gMCkge1xuICAgICAgICBjb25zdCBsaXZlID0gZXZlbnRMaXN0ZW5lcnMuZ2V0KGV2ZW50Lm5hbWUpO1xuICAgICAgICBpZiAobGl2ZSkge1xuICAgICAgICAgICAgY29uc3QgcmVtYWluaW5nID0gbGl2ZS5maWx0ZXIobCA9PiAhZXhwaXJlZC5oYXMobCkpO1xuICAgICAgICAgICAgaWYgKHJlbWFpbmluZy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICBldmVudExpc3RlbmVycy5kZWxldGUoZXZlbnQubmFtZSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGV2ZW50TGlzdGVuZXJzLnNldChldmVudC5uYW1lLCByZW1haW5pbmcpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG4vKipcbiAqIFJlZ2lzdGVyIGEgY2FsbGJhY2sgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIG11bHRpcGxlIHRpbWVzIGZvciBhIHNwZWNpZmljIGV2ZW50LlxuICpcbiAqIEBwYXJhbSBldmVudE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdG8gcmVnaXN0ZXIgdGhlIGNhbGxiYWNrIGZvci5cbiAqIEBwYXJhbSBjYWxsYmFjayAtIFRoZSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBjYWxsZWQgd2hlbiB0aGUgZXZlbnQgaXMgdHJpZ2dlcmVkLlxuICogQHBhcmFtIG1heENhbGxiYWNrcyAtIFRoZSBtYXhpbXVtIG51bWJlciBvZiB0aW1lcyB0aGUgY2FsbGJhY2sgY2FuIGJlIGNhbGxlZCBmb3IgdGhlIGV2ZW50LiBPbmNlIHRoZSBtYXhpbXVtIG51bWJlciBpcyByZWFjaGVkLCB0aGUgY2FsbGJhY2sgd2lsbCBubyBsb25nZXIgYmUgY2FsbGVkLlxuICogQHJldHVybnMgQSBmdW5jdGlvbiB0aGF0LCB3aGVuIGNhbGxlZCwgd2lsbCB1bnJlZ2lzdGVyIHRoZSBjYWxsYmFjayBmcm9tIHRoZSBldmVudC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIE9uTXVsdGlwbGU8RSBleHRlbmRzIFdhaWxzRXZlbnROYW1lID0gV2FpbHNFdmVudE5hbWU+KGV2ZW50TmFtZTogRSwgY2FsbGJhY2s6IFdhaWxzRXZlbnRDYWxsYmFjazxFPiwgbWF4Q2FsbGJhY2tzOiBudW1iZXIpIHtcbiAgICBsZXQgbGlzdGVuZXJzID0gZXZlbnRMaXN0ZW5lcnMuZ2V0KGV2ZW50TmFtZSkgfHwgW107XG4gICAgY29uc3QgdGhpc0xpc3RlbmVyID0gbmV3IExpc3RlbmVyKGV2ZW50TmFtZSwgY2FsbGJhY2ssIG1heENhbGxiYWNrcyk7XG4gICAgbGlzdGVuZXJzLnB1c2godGhpc0xpc3RlbmVyKTtcbiAgICBldmVudExpc3RlbmVycy5zZXQoZXZlbnROYW1lLCBsaXN0ZW5lcnMpO1xuICAgIHJldHVybiAoKSA9PiBsaXN0ZW5lck9mZih0aGlzTGlzdGVuZXIpO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVycyBhIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIHdoZW4gdGhlIHNwZWNpZmllZCBldmVudCBvY2N1cnMuXG4gKlxuICogQHBhcmFtIGV2ZW50TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byByZWdpc3RlciB0aGUgY2FsbGJhY2sgZm9yLlxuICogQHBhcmFtIGNhbGxiYWNrIC0gVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudCBpcyB0cmlnZ2VyZWQuXG4gKiBAcmV0dXJucyBBIGZ1bmN0aW9uIHRoYXQsIHdoZW4gY2FsbGVkLCB3aWxsIHVucmVnaXN0ZXIgdGhlIGNhbGxiYWNrIGZyb20gdGhlIGV2ZW50LlxuICovXG5leHBvcnQgZnVuY3Rpb24gT248RSBleHRlbmRzIFdhaWxzRXZlbnROYW1lID0gV2FpbHNFdmVudE5hbWU+KGV2ZW50TmFtZTogRSwgY2FsbGJhY2s6IFdhaWxzRXZlbnRDYWxsYmFjazxFPik6ICgpID0+IHZvaWQge1xuICAgIHJldHVybiBPbk11bHRpcGxlKGV2ZW50TmFtZSwgY2FsbGJhY2ssIC0xKTtcbn1cblxuLyoqXG4gKiBSZWdpc3RlcnMgYSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCBvbmx5IG9uY2UgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gKlxuICogQHBhcmFtIGV2ZW50TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byByZWdpc3RlciB0aGUgY2FsbGJhY2sgZm9yLlxuICogQHBhcmFtIGNhbGxiYWNrIC0gVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudCBpcyB0cmlnZ2VyZWQuXG4gKiBAcmV0dXJucyBBIGZ1bmN0aW9uIHRoYXQsIHdoZW4gY2FsbGVkLCB3aWxsIHVucmVnaXN0ZXIgdGhlIGNhbGxiYWNrIGZyb20gdGhlIGV2ZW50LlxuICovXG5leHBvcnQgZnVuY3Rpb24gT25jZTxFIGV4dGVuZHMgV2FpbHNFdmVudE5hbWUgPSBXYWlsc0V2ZW50TmFtZT4oZXZlbnROYW1lOiBFLCBjYWxsYmFjazogV2FpbHNFdmVudENhbGxiYWNrPEU+KTogKCkgPT4gdm9pZCB7XG4gICAgcmV0dXJuIE9uTXVsdGlwbGUoZXZlbnROYW1lLCBjYWxsYmFjaywgMSk7XG59XG5cbi8qKlxuICogUmVtb3ZlcyBldmVudCBsaXN0ZW5lcnMgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnQgbmFtZXMuXG4gKlxuICogQHBhcmFtIGV2ZW50TmFtZXMgLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnRzIHRvIHJlbW92ZSBsaXN0ZW5lcnMgZm9yLlxuICovXG5leHBvcnQgZnVuY3Rpb24gT2ZmKC4uLmV2ZW50TmFtZXM6IFtXYWlsc0V2ZW50TmFtZSwgLi4uV2FpbHNFdmVudE5hbWVbXV0pOiB2b2lkIHtcbiAgICBldmVudE5hbWVzLmZvckVhY2goZXZlbnROYW1lID0+IGV2ZW50TGlzdGVuZXJzLmRlbGV0ZShldmVudE5hbWUpKTtcbn1cblxuLyoqXG4gKiBSZW1vdmVzIGFsbCBldmVudCBsaXN0ZW5lcnMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBPZmZBbGwoKTogdm9pZCB7XG4gICAgZXZlbnRMaXN0ZW5lcnMuY2xlYXIoKTtcbn1cblxuLyoqXG4gKiBFbWl0cyBhbiBldmVudC5cbiAqXG4gKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCB3aWxsIGJlIGZ1bGZpbGxlZCBvbmNlIHRoZSBldmVudCBoYXMgYmVlbiBlbWl0dGVkLiAgUmVzb2x2ZXMgdG8gdHJ1ZSBpZiB0aGUgZXZlbnQgd2FzIGNhbmNlbGxlZC5cbiAqIEBwYXJhbSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIGVtaXRcbiAqIEBwYXJhbSBkYXRhIC0gVGhlIGRhdGEgdGhhdCB3aWxsIGJlIHNlbnQgd2l0aCB0aGUgZXZlbnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEVtaXQ8RSBleHRlbmRzIFdhaWxzRXZlbnROYW1lID0gV2FpbHNFdmVudE5hbWU+KG5hbWU6IEUsIGRhdGE6IFdhaWxzRXZlbnREYXRhPEU+KTogUHJvbWlzZTxib29sZWFuPlxuZXhwb3J0IGZ1bmN0aW9uIEVtaXQ8RSBleHRlbmRzIFdhaWxzRXZlbnROYW1lID0gV2FpbHNFdmVudE5hbWU+KG5hbWU6IFdhaWxzRXZlbnREYXRhPEU+IGV4dGVuZHMgbnVsbCB8IHZvaWQgPyBFIDogbmV2ZXIpOiBQcm9taXNlPGJvb2xlYW4+XG5leHBvcnQgZnVuY3Rpb24gRW1pdDxFIGV4dGVuZHMgV2FpbHNFdmVudE5hbWUgPSBXYWlsc0V2ZW50TmFtZT4obmFtZTogV2FpbHNFdmVudERhdGE8RT4sIGRhdGE/OiBhbnkpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICByZXR1cm4gY2FsbChFbWl0TWV0aG9kLCAgbmV3IFdhaWxzRXZlbnQobmFtZSwgZGF0YSkpXG59XG5cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLy8gVGhlIGZvbGxvd2luZyB1dGlsaXRpZXMgaGF2ZSBiZWVuIGZhY3RvcmVkIG91dCBvZiAuL2V2ZW50cy50c1xuLy8gZm9yIHRlc3RpbmcgcHVycG9zZXMuXG5cbmV4cG9ydCBjb25zdCBldmVudExpc3RlbmVycyA9IG5ldyBNYXA8c3RyaW5nLCBMaXN0ZW5lcltdPigpO1xuXG5leHBvcnQgY2xhc3MgTGlzdGVuZXIge1xuICAgIGV2ZW50TmFtZTogc3RyaW5nO1xuICAgIGNhbGxiYWNrOiAoZGF0YTogYW55KSA9PiB2b2lkO1xuICAgIG1heENhbGxiYWNrczogbnVtYmVyO1xuXG4gICAgY29uc3RydWN0b3IoZXZlbnROYW1lOiBzdHJpbmcsIGNhbGxiYWNrOiAoZGF0YTogYW55KSA9PiB2b2lkLCBtYXhDYWxsYmFja3M6IG51bWJlcikge1xuICAgICAgICB0aGlzLmV2ZW50TmFtZSA9IGV2ZW50TmFtZTtcbiAgICAgICAgdGhpcy5jYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgICAgICB0aGlzLm1heENhbGxiYWNrcyA9IG1heENhbGxiYWNrcyB8fCAtMTtcbiAgICB9XG5cbiAgICBkaXNwYXRjaChkYXRhOiBhbnkpOiBib29sZWFuIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHRoaXMuY2FsbGJhY2soZGF0YSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMubWF4Q2FsbGJhY2tzID09PSAtMSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICB0aGlzLm1heENhbGxiYWNrcyAtPSAxO1xuICAgICAgICByZXR1cm4gdGhpcy5tYXhDYWxsYmFja3MgPT09IDA7XG4gICAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gbGlzdGVuZXJPZmYobGlzdGVuZXI6IExpc3RlbmVyKTogdm9pZCB7XG4gICAgbGV0IGxpc3RlbmVycyA9IGV2ZW50TGlzdGVuZXJzLmdldChsaXN0ZW5lci5ldmVudE5hbWUpO1xuICAgIGlmICghbGlzdGVuZXJzKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsaXN0ZW5lcnMgPSBsaXN0ZW5lcnMuZmlsdGVyKGwgPT4gbCAhPT0gbGlzdGVuZXIpO1xuICAgIGlmIChsaXN0ZW5lcnMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGV2ZW50TGlzdGVuZXJzLmRlbGV0ZShsaXN0ZW5lci5ldmVudE5hbWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGV2ZW50TGlzdGVuZXJzLnNldChsaXN0ZW5lci5ldmVudE5hbWUsIGxpc3RlbmVycyk7XG4gICAgfVxufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKipcbiAqIEFueSBpcyBhIGR1bW15IGNyZWF0aW9uIGZ1bmN0aW9uIGZvciBzaW1wbGUgb3IgdW5rbm93biB0eXBlcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEFueTxUID0gYW55Pihzb3VyY2U6IGFueSk6IFQge1xuICAgIHJldHVybiBzb3VyY2U7XG59XG5cbi8qKlxuICogQnl0ZVNsaWNlIGlzIGEgY3JlYXRpb24gZnVuY3Rpb24gdGhhdCByZXBsYWNlc1xuICogbnVsbCBzdHJpbmdzIHdpdGggZW1wdHkgc3RyaW5ncy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEJ5dGVTbGljZShzb3VyY2U6IGFueSk6IHN0cmluZyB7XG4gICAgcmV0dXJuICgoc291cmNlID09IG51bGwpID8gXCJcIiA6IHNvdXJjZSk7XG59XG5cbi8qKlxuICogQXJyYXkgdGFrZXMgYSBjcmVhdGlvbiBmdW5jdGlvbiBmb3IgYW4gYXJiaXRyYXJ5IHR5cGVcbiAqIGFuZCByZXR1cm5zIGFuIGluLXBsYWNlIGNyZWF0aW9uIGZ1bmN0aW9uIGZvciBhbiBhcnJheVxuICogd2hvc2UgZWxlbWVudHMgYXJlIG9mIHRoYXQgdHlwZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEFycmF5PFQgPSBhbnk+KGVsZW1lbnQ6IChzb3VyY2U6IGFueSkgPT4gVCk6IChzb3VyY2U6IGFueSkgPT4gVFtdIHtcbiAgICBpZiAoZWxlbWVudCA9PT0gQW55KSB7XG4gICAgICAgIHJldHVybiAoc291cmNlKSA9PiAoc291cmNlID09PSBudWxsID8gW10gOiBzb3VyY2UpO1xuICAgIH1cblxuICAgIHJldHVybiAoc291cmNlKSA9PiB7XG4gICAgICAgIGlmIChzb3VyY2UgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNvdXJjZS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgc291cmNlW2ldID0gZWxlbWVudChzb3VyY2VbaV0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzb3VyY2U7XG4gICAgfTtcbn1cblxuLyoqXG4gKiBNYXAgdGFrZXMgY3JlYXRpb24gZnVuY3Rpb25zIGZvciB0d28gYXJiaXRyYXJ5IHR5cGVzXG4gKiBhbmQgcmV0dXJucyBhbiBpbi1wbGFjZSBjcmVhdGlvbiBmdW5jdGlvbiBmb3IgYW4gb2JqZWN0XG4gKiB3aG9zZSBrZXlzIGFuZCB2YWx1ZXMgYXJlIG9mIHRob3NlIHR5cGVzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gTWFwPEsgZXh0ZW5kcyBQcm9wZXJ0eUtleSA9IGFueSwgViA9IGFueT4oa2V5OiAoc291cmNlOiBhbnkpID0+IEssIHZhbHVlOiAoc291cmNlOiBhbnkpID0+IFYpOiAoc291cmNlOiBhbnkpID0+IFJlY29yZDxLLCBWPiB7XG4gICAgaWYgKHZhbHVlID09PSBBbnkpIHtcbiAgICAgICAgcmV0dXJuIChzb3VyY2UpID0+IChzb3VyY2UgPT09IG51bGwgPyB7fSA6IHNvdXJjZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIChzb3VyY2UpID0+IHtcbiAgICAgICAgaWYgKHNvdXJjZSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICB9XG4gICAgICAgIGZvciAoY29uc3Qga2V5IGluIHNvdXJjZSkge1xuICAgICAgICAgICAgc291cmNlW2tleV0gPSB2YWx1ZShzb3VyY2Vba2V5XSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNvdXJjZTtcbiAgICB9O1xufVxuXG4vKipcbiAqIE51bGxhYmxlIHRha2VzIGEgY3JlYXRpb24gZnVuY3Rpb24gZm9yIGFuIGFyYml0cmFyeSB0eXBlXG4gKiBhbmQgcmV0dXJucyBhIGNyZWF0aW9uIGZ1bmN0aW9uIGZvciBhIG51bGxhYmxlIHZhbHVlIG9mIHRoYXQgdHlwZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIE51bGxhYmxlPFQgPSBhbnk+KGVsZW1lbnQ6IChzb3VyY2U6IGFueSkgPT4gVCk6IChzb3VyY2U6IGFueSkgPT4gKFQgfCBudWxsKSB7XG4gICAgaWYgKGVsZW1lbnQgPT09IEFueSkge1xuICAgICAgICByZXR1cm4gQW55O1xuICAgIH1cblxuICAgIHJldHVybiAoc291cmNlKSA9PiAoc291cmNlID09PSBudWxsID8gbnVsbCA6IGVsZW1lbnQoc291cmNlKSk7XG59XG5cbi8qKlxuICogU3RydWN0IHRha2VzIGFuIG9iamVjdCBtYXBwaW5nIGZpZWxkIG5hbWVzIHRvIGNyZWF0aW9uIGZ1bmN0aW9uc1xuICogYW5kIHJldHVybnMgYW4gaW4tcGxhY2UgY3JlYXRpb24gZnVuY3Rpb24gZm9yIGEgc3RydWN0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gU3RydWN0KGNyZWF0ZUZpZWxkOiBSZWNvcmQ8c3RyaW5nLCAoc291cmNlOiBhbnkpID0+IGFueT4pOlxuICAgIDxVIGV4dGVuZHMgUmVjb3JkPHN0cmluZywgYW55PiA9IGFueT4oc291cmNlOiBhbnkpID0+IFVcbntcbiAgICBsZXQgYWxsQW55ID0gdHJ1ZTtcbiAgICBmb3IgKGNvbnN0IG5hbWUgaW4gY3JlYXRlRmllbGQpIHtcbiAgICAgICAgaWYgKGNyZWF0ZUZpZWxkW25hbWVdICE9PSBBbnkpIHtcbiAgICAgICAgICAgIGFsbEFueSA9IGZhbHNlO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKGFsbEFueSkge1xuICAgICAgICByZXR1cm4gQW55O1xuICAgIH1cblxuICAgIHJldHVybiAoc291cmNlKSA9PiB7XG4gICAgICAgIGZvciAoY29uc3QgbmFtZSBpbiBjcmVhdGVGaWVsZCkge1xuICAgICAgICAgICAgaWYgKG5hbWUgaW4gc291cmNlKSB7XG4gICAgICAgICAgICAgICAgc291cmNlW25hbWVdID0gY3JlYXRlRmllbGRbbmFtZV0oc291cmNlW25hbWVdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc291cmNlO1xuICAgIH07XG59XG5cbi8qKlxuICogRGF0ZUZyb21UaW1lIGlzIGEgY3JlYXRpb24gZnVuY3Rpb24gdGhhdCBjb252ZXJ0cyBSRkMzMzM5IHN0cmluZ3NcbiAqIChmcm9tIEdvJ3MgdGltZS5UaW1lIEpTT04gbWFyc2hhbGluZykgdG8gSmF2YVNjcmlwdCBEYXRlIG9iamVjdHMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBEYXRlRnJvbVRpbWUoc291cmNlOiBhbnkpOiBEYXRlIHtcbiAgICByZXR1cm4gbmV3IERhdGUoc291cmNlKTtcbn1cblxuLyoqXG4gKiBNYXBzIGtub3duIGV2ZW50IG5hbWVzIHRvIGNyZWF0aW9uIGZ1bmN0aW9ucyBmb3IgdGhlaXIgZGF0YSB0eXBlcy5cbiAqIFdpbGwgYmUgbW9ua2V5LXBhdGNoZWQgYnkgdGhlIGJpbmRpbmcgZ2VuZXJhdG9yLlxuICovXG5leHBvcnQgY29uc3QgRXZlbnRzOiBSZWNvcmQ8c3RyaW5nLCAoc291cmNlOiBhbnkpID0+IGFueT4gPSB7fTtcbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLy8gQ3luaHlyY2h3eWQgeSBmZmVpbCBob24geW4gYXd0b21hdGlnLiBQRUlESVdDSCBcdTAwQzIgTU9ESVdMXG4vLyBUaGlzIGZpbGUgaXMgYXV0b21hdGljYWxseSBnZW5lcmF0ZWQuIERPIE5PVCBFRElUXG5cbmV4cG9ydCBjb25zdCBUeXBlcyA9IE9iamVjdC5mcmVlemUoe1xuXHRXaW5kb3dzOiBPYmplY3QuZnJlZXplKHtcblx0XHRBUE1Qb3dlclNldHRpbmdDaGFuZ2U6IFwid2luZG93czpBUE1Qb3dlclNldHRpbmdDaGFuZ2VcIixcblx0XHRBUE1Qb3dlclN0YXR1c0NoYW5nZTogXCJ3aW5kb3dzOkFQTVBvd2VyU3RhdHVzQ2hhbmdlXCIsXG5cdFx0QVBNUmVzdW1lQXV0b21hdGljOiBcIndpbmRvd3M6QVBNUmVzdW1lQXV0b21hdGljXCIsXG5cdFx0QVBNUmVzdW1lU3VzcGVuZDogXCJ3aW5kb3dzOkFQTVJlc3VtZVN1c3BlbmRcIixcblx0XHRBUE1TdXNwZW5kOiBcIndpbmRvd3M6QVBNU3VzcGVuZFwiLFxuXHRcdEFwcGxpY2F0aW9uU3RhcnRlZDogXCJ3aW5kb3dzOkFwcGxpY2F0aW9uU3RhcnRlZFwiLFxuXHRcdFN5c3RlbVRoZW1lQ2hhbmdlZDogXCJ3aW5kb3dzOlN5c3RlbVRoZW1lQ2hhbmdlZFwiLFxuXHRcdFdlYlZpZXdOYXZpZ2F0aW9uQ29tcGxldGVkOiBcIndpbmRvd3M6V2ViVmlld05hdmlnYXRpb25Db21wbGV0ZWRcIixcblx0XHRXaW5kb3dBY3RpdmU6IFwid2luZG93czpXaW5kb3dBY3RpdmVcIixcblx0XHRXaW5kb3dCYWNrZ3JvdW5kRXJhc2U6IFwid2luZG93czpXaW5kb3dCYWNrZ3JvdW5kRXJhc2VcIixcblx0XHRXaW5kb3dDbGlja0FjdGl2ZTogXCJ3aW5kb3dzOldpbmRvd0NsaWNrQWN0aXZlXCIsXG5cdFx0V2luZG93Q2xvc2luZzogXCJ3aW5kb3dzOldpbmRvd0Nsb3NpbmdcIixcblx0XHRXaW5kb3dEaWRNb3ZlOiBcIndpbmRvd3M6V2luZG93RGlkTW92ZVwiLFxuXHRcdFdpbmRvd0RpZFJlc2l6ZTogXCJ3aW5kb3dzOldpbmRvd0RpZFJlc2l6ZVwiLFxuXHRcdFdpbmRvd0RQSUNoYW5nZWQ6IFwid2luZG93czpXaW5kb3dEUElDaGFuZ2VkXCIsXG5cdFx0V2luZG93RHJhZ0Ryb3A6IFwid2luZG93czpXaW5kb3dEcmFnRHJvcFwiLFxuXHRcdFdpbmRvd0RyYWdFbnRlcjogXCJ3aW5kb3dzOldpbmRvd0RyYWdFbnRlclwiLFxuXHRcdFdpbmRvd0RyYWdMZWF2ZTogXCJ3aW5kb3dzOldpbmRvd0RyYWdMZWF2ZVwiLFxuXHRcdFdpbmRvd0RyYWdPdmVyOiBcIndpbmRvd3M6V2luZG93RHJhZ092ZXJcIixcblx0XHRXaW5kb3dFbmRNb3ZlOiBcIndpbmRvd3M6V2luZG93RW5kTW92ZVwiLFxuXHRcdFdpbmRvd0VuZFJlc2l6ZTogXCJ3aW5kb3dzOldpbmRvd0VuZFJlc2l6ZVwiLFxuXHRcdFdpbmRvd0Z1bGxzY3JlZW46IFwid2luZG93czpXaW5kb3dGdWxsc2NyZWVuXCIsXG5cdFx0V2luZG93SGlkZTogXCJ3aW5kb3dzOldpbmRvd0hpZGVcIixcblx0XHRXaW5kb3dJbmFjdGl2ZTogXCJ3aW5kb3dzOldpbmRvd0luYWN0aXZlXCIsXG5cdFx0V2luZG93S2V5RG93bjogXCJ3aW5kb3dzOldpbmRvd0tleURvd25cIixcblx0XHRXaW5kb3dLZXlVcDogXCJ3aW5kb3dzOldpbmRvd0tleVVwXCIsXG5cdFx0V2luZG93S2lsbEZvY3VzOiBcIndpbmRvd3M6V2luZG93S2lsbEZvY3VzXCIsXG5cdFx0V2luZG93Tm9uQ2xpZW50SGl0OiBcIndpbmRvd3M6V2luZG93Tm9uQ2xpZW50SGl0XCIsXG5cdFx0V2luZG93Tm9uQ2xpZW50TW91c2VEb3duOiBcIndpbmRvd3M6V2luZG93Tm9uQ2xpZW50TW91c2VEb3duXCIsXG5cdFx0V2luZG93Tm9uQ2xpZW50TW91c2VMZWF2ZTogXCJ3aW5kb3dzOldpbmRvd05vbkNsaWVudE1vdXNlTGVhdmVcIixcblx0XHRXaW5kb3dOb25DbGllbnRNb3VzZU1vdmU6IFwid2luZG93czpXaW5kb3dOb25DbGllbnRNb3VzZU1vdmVcIixcblx0XHRXaW5kb3dOb25DbGllbnRNb3VzZVVwOiBcIndpbmRvd3M6V2luZG93Tm9uQ2xpZW50TW91c2VVcFwiLFxuXHRcdFdpbmRvd1BhaW50OiBcIndpbmRvd3M6V2luZG93UGFpbnRcIixcblx0XHRXaW5kb3dSZXN0b3JlOiBcIndpbmRvd3M6V2luZG93UmVzdG9yZVwiLFxuXHRcdFdpbmRvd1NldEZvY3VzOiBcIndpbmRvd3M6V2luZG93U2V0Rm9jdXNcIixcblx0XHRXaW5kb3dTaG93OiBcIndpbmRvd3M6V2luZG93U2hvd1wiLFxuXHRcdFdpbmRvd1N0YXJ0TW92ZTogXCJ3aW5kb3dzOldpbmRvd1N0YXJ0TW92ZVwiLFxuXHRcdFdpbmRvd1N0YXJ0UmVzaXplOiBcIndpbmRvd3M6V2luZG93U3RhcnRSZXNpemVcIixcblx0XHRXaW5kb3dVbkZ1bGxzY3JlZW46IFwid2luZG93czpXaW5kb3dVbkZ1bGxzY3JlZW5cIixcblx0XHRXaW5kb3daT3JkZXJDaGFuZ2VkOiBcIndpbmRvd3M6V2luZG93Wk9yZGVyQ2hhbmdlZFwiLFxuXHRcdFdpbmRvd01pbmltaXNlOiBcIndpbmRvd3M6V2luZG93TWluaW1pc2VcIixcblx0XHRXaW5kb3dVbk1pbmltaXNlOiBcIndpbmRvd3M6V2luZG93VW5NaW5pbWlzZVwiLFxuXHRcdFdpbmRvd01heGltaXNlOiBcIndpbmRvd3M6V2luZG93TWF4aW1pc2VcIixcblx0XHRXaW5kb3dVbk1heGltaXNlOiBcIndpbmRvd3M6V2luZG93VW5NYXhpbWlzZVwiLFxuXHR9KSxcblx0TWFjOiBPYmplY3QuZnJlZXplKHtcblx0XHRBcHBsaWNhdGlvbkRpZEJlY29tZUFjdGl2ZTogXCJtYWM6QXBwbGljYXRpb25EaWRCZWNvbWVBY3RpdmVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzXCIsXG5cdFx0QXBwbGljYXRpb25EaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZUVmZmVjdGl2ZUFwcGVhcmFuY2VcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZUljb246IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlSWNvblwiLFxuXHRcdEFwcGxpY2F0aW9uRGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGU6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZVNjcmVlblBhcmFtZXRlcnM6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlU2NyZWVuUGFyYW1ldGVyc1wiLFxuXHRcdEFwcGxpY2F0aW9uRGlkQ2hhbmdlU3RhdHVzQmFyRnJhbWU6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlU3RhdHVzQmFyRnJhbWVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZVN0YXR1c0Jhck9yaWVudGF0aW9uOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZVN0YXR1c0Jhck9yaWVudGF0aW9uXCIsXG5cdFx0QXBwbGljYXRpb25EaWRDaGFuZ2VUaGVtZTogXCJtYWM6QXBwbGljYXRpb25EaWRDaGFuZ2VUaGVtZVwiLFxuXHRcdEFwcGxpY2F0aW9uRGlkRmluaXNoTGF1bmNoaW5nOiBcIm1hYzpBcHBsaWNhdGlvbkRpZEZpbmlzaExhdW5jaGluZ1wiLFxuXHRcdEFwcGxpY2F0aW9uRGlkSGlkZTogXCJtYWM6QXBwbGljYXRpb25EaWRIaWRlXCIsXG5cdFx0QXBwbGljYXRpb25EaWRSZXNpZ25BY3RpdmU6IFwibWFjOkFwcGxpY2F0aW9uRGlkUmVzaWduQWN0aXZlXCIsXG5cdFx0QXBwbGljYXRpb25EaWRVbmhpZGU6IFwibWFjOkFwcGxpY2F0aW9uRGlkVW5oaWRlXCIsXG5cdFx0QXBwbGljYXRpb25EaWRVcGRhdGU6IFwibWFjOkFwcGxpY2F0aW9uRGlkVXBkYXRlXCIsXG5cdFx0QXBwbGljYXRpb25EaWRXYWtlOiBcIm1hYzpBcHBsaWNhdGlvbkRpZFdha2VcIixcblx0XHRBcHBsaWNhdGlvblNjcmVlbnNEaWRTbGVlcDogXCJtYWM6QXBwbGljYXRpb25TY3JlZW5zRGlkU2xlZXBcIixcblx0XHRBcHBsaWNhdGlvblNjcmVlbnNEaWRXYWtlOiBcIm1hYzpBcHBsaWNhdGlvblNjcmVlbnNEaWRXYWtlXCIsXG5cdFx0QXBwbGljYXRpb25TaG91bGRIYW5kbGVSZW9wZW46IFwibWFjOkFwcGxpY2F0aW9uU2hvdWxkSGFuZGxlUmVvcGVuXCIsXG5cdFx0QXBwbGljYXRpb25XaWxsQmVjb21lQWN0aXZlOiBcIm1hYzpBcHBsaWNhdGlvbldpbGxCZWNvbWVBY3RpdmVcIixcblx0XHRBcHBsaWNhdGlvbldpbGxGaW5pc2hMYXVuY2hpbmc6IFwibWFjOkFwcGxpY2F0aW9uV2lsbEZpbmlzaExhdW5jaGluZ1wiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbEhpZGU6IFwibWFjOkFwcGxpY2F0aW9uV2lsbEhpZGVcIixcblx0XHRBcHBsaWNhdGlvbldpbGxSZXNpZ25BY3RpdmU6IFwibWFjOkFwcGxpY2F0aW9uV2lsbFJlc2lnbkFjdGl2ZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbFNsZWVwOiBcIm1hYzpBcHBsaWNhdGlvbldpbGxTbGVlcFwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbFRlcm1pbmF0ZTogXCJtYWM6QXBwbGljYXRpb25XaWxsVGVybWluYXRlXCIsXG5cdFx0QXBwbGljYXRpb25XaWxsVW5oaWRlOiBcIm1hYzpBcHBsaWNhdGlvbldpbGxVbmhpZGVcIixcblx0XHRBcHBsaWNhdGlvbldpbGxVcGRhdGU6IFwibWFjOkFwcGxpY2F0aW9uV2lsbFVwZGF0ZVwiLFxuXHRcdE1lbnVEaWRBZGRJdGVtOiBcIm1hYzpNZW51RGlkQWRkSXRlbVwiLFxuXHRcdE1lbnVEaWRCZWdpblRyYWNraW5nOiBcIm1hYzpNZW51RGlkQmVnaW5UcmFja2luZ1wiLFxuXHRcdE1lbnVEaWRDbG9zZTogXCJtYWM6TWVudURpZENsb3NlXCIsXG5cdFx0TWVudURpZERpc3BsYXlJdGVtOiBcIm1hYzpNZW51RGlkRGlzcGxheUl0ZW1cIixcblx0XHRNZW51RGlkRW5kVHJhY2tpbmc6IFwibWFjOk1lbnVEaWRFbmRUcmFja2luZ1wiLFxuXHRcdE1lbnVEaWRIaWdobGlnaHRJdGVtOiBcIm1hYzpNZW51RGlkSGlnaGxpZ2h0SXRlbVwiLFxuXHRcdE1lbnVEaWRPcGVuOiBcIm1hYzpNZW51RGlkT3BlblwiLFxuXHRcdE1lbnVEaWRQb3BVcDogXCJtYWM6TWVudURpZFBvcFVwXCIsXG5cdFx0TWVudURpZFJlbW92ZUl0ZW06IFwibWFjOk1lbnVEaWRSZW1vdmVJdGVtXCIsXG5cdFx0TWVudURpZFNlbmRBY3Rpb246IFwibWFjOk1lbnVEaWRTZW5kQWN0aW9uXCIsXG5cdFx0TWVudURpZFNlbmRBY3Rpb25Ub0l0ZW06IFwibWFjOk1lbnVEaWRTZW5kQWN0aW9uVG9JdGVtXCIsXG5cdFx0TWVudURpZFVwZGF0ZTogXCJtYWM6TWVudURpZFVwZGF0ZVwiLFxuXHRcdE1lbnVXaWxsQWRkSXRlbTogXCJtYWM6TWVudVdpbGxBZGRJdGVtXCIsXG5cdFx0TWVudVdpbGxCZWdpblRyYWNraW5nOiBcIm1hYzpNZW51V2lsbEJlZ2luVHJhY2tpbmdcIixcblx0XHRNZW51V2lsbERpc3BsYXlJdGVtOiBcIm1hYzpNZW51V2lsbERpc3BsYXlJdGVtXCIsXG5cdFx0TWVudVdpbGxFbmRUcmFja2luZzogXCJtYWM6TWVudVdpbGxFbmRUcmFja2luZ1wiLFxuXHRcdE1lbnVXaWxsSGlnaGxpZ2h0SXRlbTogXCJtYWM6TWVudVdpbGxIaWdobGlnaHRJdGVtXCIsXG5cdFx0TWVudVdpbGxPcGVuOiBcIm1hYzpNZW51V2lsbE9wZW5cIixcblx0XHRNZW51V2lsbFBvcFVwOiBcIm1hYzpNZW51V2lsbFBvcFVwXCIsXG5cdFx0TWVudVdpbGxSZW1vdmVJdGVtOiBcIm1hYzpNZW51V2lsbFJlbW92ZUl0ZW1cIixcblx0XHRNZW51V2lsbFNlbmRBY3Rpb246IFwibWFjOk1lbnVXaWxsU2VuZEFjdGlvblwiLFxuXHRcdE1lbnVXaWxsU2VuZEFjdGlvblRvSXRlbTogXCJtYWM6TWVudVdpbGxTZW5kQWN0aW9uVG9JdGVtXCIsXG5cdFx0TWVudVdpbGxVcGRhdGU6IFwibWFjOk1lbnVXaWxsVXBkYXRlXCIsXG5cdFx0V2ViVmlld0RpZENvbW1pdE5hdmlnYXRpb246IFwibWFjOldlYlZpZXdEaWRDb21taXROYXZpZ2F0aW9uXCIsXG5cdFx0V2ViVmlld0RpZEZpbmlzaE5hdmlnYXRpb246IFwibWFjOldlYlZpZXdEaWRGaW5pc2hOYXZpZ2F0aW9uXCIsXG5cdFx0V2ViVmlld0RpZFJlY2VpdmVTZXJ2ZXJSZWRpcmVjdEZvclByb3Zpc2lvbmFsTmF2aWdhdGlvbjogXCJtYWM6V2ViVmlld0RpZFJlY2VpdmVTZXJ2ZXJSZWRpcmVjdEZvclByb3Zpc2lvbmFsTmF2aWdhdGlvblwiLFxuXHRcdFdlYlZpZXdEaWRTdGFydFByb3Zpc2lvbmFsTmF2aWdhdGlvbjogXCJtYWM6V2ViVmlld0RpZFN0YXJ0UHJvdmlzaW9uYWxOYXZpZ2F0aW9uXCIsXG5cdFx0V2luZG93RGlkQmVjb21lS2V5OiBcIm1hYzpXaW5kb3dEaWRCZWNvbWVLZXlcIixcblx0XHRXaW5kb3dEaWRCZWNvbWVNYWluOiBcIm1hYzpXaW5kb3dEaWRCZWNvbWVNYWluXCIsXG5cdFx0V2luZG93RGlkQmVnaW5TaGVldDogXCJtYWM6V2luZG93RGlkQmVnaW5TaGVldFwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZUFscGhhOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VBbHBoYVwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZUJhY2tpbmdMb2NhdGlvbjogXCJtYWM6V2luZG93RGlkQ2hhbmdlQmFja2luZ0xvY2F0aW9uXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlQmFja2luZ1Byb3BlcnRpZXM6IFwibWFjOldpbmRvd0RpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlQ29sbGVjdGlvbkJlaGF2aW9yOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGU6IFwibWFjOldpbmRvd0RpZENoYW5nZU9jY2x1c2lvblN0YXRlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlT3JkZXJpbmdNb2RlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VPcmRlcmluZ01vZGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTY3JlZW46IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZVNjcmVlblBhcmFtZXRlcnM6IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblBhcmFtZXRlcnNcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTY3JlZW5Qcm9maWxlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VTY3JlZW5Qcm9maWxlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU2NyZWVuU3BhY2U6IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblNwYWNlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU2NyZWVuU3BhY2VQcm9wZXJ0aWVzOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VTY3JlZW5TcGFjZVByb3BlcnRpZXNcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTaGFyaW5nVHlwZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU2hhcmluZ1R5cGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTcGFjZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU3BhY2VcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTcGFjZU9yZGVyaW5nTW9kZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU3BhY2VPcmRlcmluZ01vZGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VUaXRsZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlVGl0bGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VUb29sYmFyOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VUb29sYmFyXCIsXG5cdFx0V2luZG93RGlkRGVtaW5pYXR1cml6ZTogXCJtYWM6V2luZG93RGlkRGVtaW5pYXR1cml6ZVwiLFxuXHRcdFdpbmRvd0RpZEVuZFNoZWV0OiBcIm1hYzpXaW5kb3dEaWRFbmRTaGVldFwiLFxuXHRcdFdpbmRvd0RpZEVudGVyRnVsbFNjcmVlbjogXCJtYWM6V2luZG93RGlkRW50ZXJGdWxsU2NyZWVuXCIsXG5cdFx0V2luZG93RGlkRW50ZXJWZXJzaW9uQnJvd3NlcjogXCJtYWM6V2luZG93RGlkRW50ZXJWZXJzaW9uQnJvd3NlclwiLFxuXHRcdFdpbmRvd0RpZEV4aXRGdWxsU2NyZWVuOiBcIm1hYzpXaW5kb3dEaWRFeGl0RnVsbFNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZEV4aXRWZXJzaW9uQnJvd3NlcjogXCJtYWM6V2luZG93RGlkRXhpdFZlcnNpb25Ccm93c2VyXCIsXG5cdFx0V2luZG93RGlkRXhwb3NlOiBcIm1hYzpXaW5kb3dEaWRFeHBvc2VcIixcblx0XHRXaW5kb3dEaWRGb2N1czogXCJtYWM6V2luZG93RGlkRm9jdXNcIixcblx0XHRXaW5kb3dEaWRNaW5pYXR1cml6ZTogXCJtYWM6V2luZG93RGlkTWluaWF0dXJpemVcIixcblx0XHRXaW5kb3dEaWRNb3ZlOiBcIm1hYzpXaW5kb3dEaWRNb3ZlXCIsXG5cdFx0V2luZG93RGlkT3JkZXJPZmZTY3JlZW46IFwibWFjOldpbmRvd0RpZE9yZGVyT2ZmU2NyZWVuXCIsXG5cdFx0V2luZG93RGlkT3JkZXJPblNjcmVlbjogXCJtYWM6V2luZG93RGlkT3JkZXJPblNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZFJlc2lnbktleTogXCJtYWM6V2luZG93RGlkUmVzaWduS2V5XCIsXG5cdFx0V2luZG93RGlkUmVzaWduTWFpbjogXCJtYWM6V2luZG93RGlkUmVzaWduTWFpblwiLFxuXHRcdFdpbmRvd0RpZFJlc2l6ZTogXCJtYWM6V2luZG93RGlkUmVzaXplXCIsXG5cdFx0V2luZG93RGlkVXBkYXRlOiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVBbHBoYTogXCJtYWM6V2luZG93RGlkVXBkYXRlQWxwaGFcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3I6IFwibWFjOldpbmRvd0RpZFVwZGF0ZUNvbGxlY3Rpb25CZWhhdmlvclwiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZUNvbGxlY3Rpb25Qcm9wZXJ0aWVzOiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVDb2xsZWN0aW9uUHJvcGVydGllc1wiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZVNoYWRvdzogXCJtYWM6V2luZG93RGlkVXBkYXRlU2hhZG93XCIsXG5cdFx0V2luZG93RGlkVXBkYXRlVGl0bGU6IFwibWFjOldpbmRvd0RpZFVwZGF0ZVRpdGxlXCIsXG5cdFx0V2luZG93RGlkVXBkYXRlVG9vbGJhcjogXCJtYWM6V2luZG93RGlkVXBkYXRlVG9vbGJhclwiLFxuXHRcdFdpbmRvd0RpZFpvb206IFwibWFjOldpbmRvd0RpZFpvb21cIixcblx0XHRXaW5kb3dGaWxlRHJhZ2dpbmdFbnRlcmVkOiBcIm1hYzpXaW5kb3dGaWxlRHJhZ2dpbmdFbnRlcmVkXCIsXG5cdFx0V2luZG93RmlsZURyYWdnaW5nRXhpdGVkOiBcIm1hYzpXaW5kb3dGaWxlRHJhZ2dpbmdFeGl0ZWRcIixcblx0XHRXaW5kb3dGaWxlRHJhZ2dpbmdQZXJmb3JtZWQ6IFwibWFjOldpbmRvd0ZpbGVEcmFnZ2luZ1BlcmZvcm1lZFwiLFxuXHRcdFdpbmRvd0hpZGU6IFwibWFjOldpbmRvd0hpZGVcIixcblx0XHRXaW5kb3dNYXhpbWlzZTogXCJtYWM6V2luZG93TWF4aW1pc2VcIixcblx0XHRXaW5kb3dVbk1heGltaXNlOiBcIm1hYzpXaW5kb3dVbk1heGltaXNlXCIsXG5cdFx0V2luZG93TWluaW1pc2U6IFwibWFjOldpbmRvd01pbmltaXNlXCIsXG5cdFx0V2luZG93VW5NaW5pbWlzZTogXCJtYWM6V2luZG93VW5NaW5pbWlzZVwiLFxuXHRcdFdpbmRvd1Nob3VsZENsb3NlOiBcIm1hYzpXaW5kb3dTaG91bGRDbG9zZVwiLFxuXHRcdFdpbmRvd1Nob3c6IFwibWFjOldpbmRvd1Nob3dcIixcblx0XHRXaW5kb3dXaWxsQmVjb21lS2V5OiBcIm1hYzpXaW5kb3dXaWxsQmVjb21lS2V5XCIsXG5cdFx0V2luZG93V2lsbEJlY29tZU1haW46IFwibWFjOldpbmRvd1dpbGxCZWNvbWVNYWluXCIsXG5cdFx0V2luZG93V2lsbEJlZ2luU2hlZXQ6IFwibWFjOldpbmRvd1dpbGxCZWdpblNoZWV0XCIsXG5cdFx0V2luZG93V2lsbENoYW5nZU9yZGVyaW5nTW9kZTogXCJtYWM6V2luZG93V2lsbENoYW5nZU9yZGVyaW5nTW9kZVwiLFxuXHRcdFdpbmRvd1dpbGxDbG9zZTogXCJtYWM6V2luZG93V2lsbENsb3NlXCIsXG5cdFx0V2luZG93V2lsbERlbWluaWF0dXJpemU6IFwibWFjOldpbmRvd1dpbGxEZW1pbmlhdHVyaXplXCIsXG5cdFx0V2luZG93V2lsbEVudGVyRnVsbFNjcmVlbjogXCJtYWM6V2luZG93V2lsbEVudGVyRnVsbFNjcmVlblwiLFxuXHRcdFdpbmRvd1dpbGxFbnRlclZlcnNpb25Ccm93c2VyOiBcIm1hYzpXaW5kb3dXaWxsRW50ZXJWZXJzaW9uQnJvd3NlclwiLFxuXHRcdFdpbmRvd1dpbGxFeGl0RnVsbFNjcmVlbjogXCJtYWM6V2luZG93V2lsbEV4aXRGdWxsU2NyZWVuXCIsXG5cdFx0V2luZG93V2lsbEV4aXRWZXJzaW9uQnJvd3NlcjogXCJtYWM6V2luZG93V2lsbEV4aXRWZXJzaW9uQnJvd3NlclwiLFxuXHRcdFdpbmRvd1dpbGxGb2N1czogXCJtYWM6V2luZG93V2lsbEZvY3VzXCIsXG5cdFx0V2luZG93V2lsbE1pbmlhdHVyaXplOiBcIm1hYzpXaW5kb3dXaWxsTWluaWF0dXJpemVcIixcblx0XHRXaW5kb3dXaWxsTW92ZTogXCJtYWM6V2luZG93V2lsbE1vdmVcIixcblx0XHRXaW5kb3dXaWxsT3JkZXJPZmZTY3JlZW46IFwibWFjOldpbmRvd1dpbGxPcmRlck9mZlNjcmVlblwiLFxuXHRcdFdpbmRvd1dpbGxPcmRlck9uU2NyZWVuOiBcIm1hYzpXaW5kb3dXaWxsT3JkZXJPblNjcmVlblwiLFxuXHRcdFdpbmRvd1dpbGxSZXNpZ25NYWluOiBcIm1hYzpXaW5kb3dXaWxsUmVzaWduTWFpblwiLFxuXHRcdFdpbmRvd1dpbGxSZXNpemU6IFwibWFjOldpbmRvd1dpbGxSZXNpemVcIixcblx0XHRXaW5kb3dXaWxsVW5mb2N1czogXCJtYWM6V2luZG93V2lsbFVuZm9jdXNcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlOiBcIm1hYzpXaW5kb3dXaWxsVXBkYXRlXCIsXG5cdFx0V2luZG93V2lsbFVwZGF0ZUFscGhhOiBcIm1hYzpXaW5kb3dXaWxsVXBkYXRlQWxwaGFcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlQ29sbGVjdGlvbkJlaGF2aW9yOiBcIm1hYzpXaW5kb3dXaWxsVXBkYXRlQ29sbGVjdGlvbkJlaGF2aW9yXCIsXG5cdFx0V2luZG93V2lsbFVwZGF0ZUNvbGxlY3Rpb25Qcm9wZXJ0aWVzOiBcIm1hYzpXaW5kb3dXaWxsVXBkYXRlQ29sbGVjdGlvblByb3BlcnRpZXNcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlU2hhZG93OiBcIm1hYzpXaW5kb3dXaWxsVXBkYXRlU2hhZG93XCIsXG5cdFx0V2luZG93V2lsbFVwZGF0ZVRpdGxlOiBcIm1hYzpXaW5kb3dXaWxsVXBkYXRlVGl0bGVcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlVG9vbGJhcjogXCJtYWM6V2luZG93V2lsbFVwZGF0ZVRvb2xiYXJcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlVmlzaWJpbGl0eTogXCJtYWM6V2luZG93V2lsbFVwZGF0ZVZpc2liaWxpdHlcIixcblx0XHRXaW5kb3dXaWxsVXNlU3RhbmRhcmRGcmFtZTogXCJtYWM6V2luZG93V2lsbFVzZVN0YW5kYXJkRnJhbWVcIixcblx0XHRXaW5kb3dab29tSW46IFwibWFjOldpbmRvd1pvb21JblwiLFxuXHRcdFdpbmRvd1pvb21PdXQ6IFwibWFjOldpbmRvd1pvb21PdXRcIixcblx0XHRXaW5kb3dab29tUmVzZXQ6IFwibWFjOldpbmRvd1pvb21SZXNldFwiLFxuXHRcdFdlYlZpZXdXZWJDb250ZW50UHJvY2Vzc0RpZFRlcm1pbmF0ZTogXCJtYWM6V2ViVmlld1dlYkNvbnRlbnRQcm9jZXNzRGlkVGVybWluYXRlXCIsXG5cdH0pLFxuXHRMaW51eDogT2JqZWN0LmZyZWV6ZSh7XG5cdFx0QXBwbGljYXRpb25TdGFydHVwOiBcImxpbnV4OkFwcGxpY2F0aW9uU3RhcnR1cFwiLFxuXHRcdFN5c3RlbURpZFdha2U6IFwibGludXg6U3lzdGVtRGlkV2FrZVwiLFxuXHRcdFN5c3RlbVRoZW1lQ2hhbmdlZDogXCJsaW51eDpTeXN0ZW1UaGVtZUNoYW5nZWRcIixcblx0XHRTeXN0ZW1XaWxsU2xlZXA6IFwibGludXg6U3lzdGVtV2lsbFNsZWVwXCIsXG5cdFx0V2luZG93RGVsZXRlRXZlbnQ6IFwibGludXg6V2luZG93RGVsZXRlRXZlbnRcIixcblx0XHRXaW5kb3dEaWRNb3ZlOiBcImxpbnV4OldpbmRvd0RpZE1vdmVcIixcblx0XHRXaW5kb3dEaWRSZXNpemU6IFwibGludXg6V2luZG93RGlkUmVzaXplXCIsXG5cdFx0V2luZG93Rm9jdXNJbjogXCJsaW51eDpXaW5kb3dGb2N1c0luXCIsXG5cdFx0V2luZG93Rm9jdXNPdXQ6IFwibGludXg6V2luZG93Rm9jdXNPdXRcIixcblx0XHRXaW5kb3dMb2FkU3RhcnRlZDogXCJsaW51eDpXaW5kb3dMb2FkU3RhcnRlZFwiLFxuXHRcdFdpbmRvd0xvYWRSZWRpcmVjdGVkOiBcImxpbnV4OldpbmRvd0xvYWRSZWRpcmVjdGVkXCIsXG5cdFx0V2luZG93TG9hZENvbW1pdHRlZDogXCJsaW51eDpXaW5kb3dMb2FkQ29tbWl0dGVkXCIsXG5cdFx0V2luZG93TG9hZEZpbmlzaGVkOiBcImxpbnV4OldpbmRvd0xvYWRGaW5pc2hlZFwiLFxuXHR9KSxcblx0aU9TOiBPYmplY3QuZnJlZXplKHtcblx0XHRBcHBsaWNhdGlvbkRpZEJlY29tZUFjdGl2ZTogXCJpb3M6QXBwbGljYXRpb25EaWRCZWNvbWVBY3RpdmVcIixcblx0XHRBcHBsaWNhdGlvbkRpZEVudGVyQmFja2dyb3VuZDogXCJpb3M6QXBwbGljYXRpb25EaWRFbnRlckJhY2tncm91bmRcIixcblx0XHRBcHBsaWNhdGlvbkRpZEZpbmlzaExhdW5jaGluZzogXCJpb3M6QXBwbGljYXRpb25EaWRGaW5pc2hMYXVuY2hpbmdcIixcblx0XHRBcHBsaWNhdGlvbkRpZFJlY2VpdmVNZW1vcnlXYXJuaW5nOiBcImlvczpBcHBsaWNhdGlvbkRpZFJlY2VpdmVNZW1vcnlXYXJuaW5nXCIsXG5cdFx0QXBwbGljYXRpb25XaWxsRW50ZXJGb3JlZ3JvdW5kOiBcImlvczpBcHBsaWNhdGlvbldpbGxFbnRlckZvcmVncm91bmRcIixcblx0XHRBcHBsaWNhdGlvbldpbGxSZXNpZ25BY3RpdmU6IFwiaW9zOkFwcGxpY2F0aW9uV2lsbFJlc2lnbkFjdGl2ZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbFRlcm1pbmF0ZTogXCJpb3M6QXBwbGljYXRpb25XaWxsVGVybWluYXRlXCIsXG5cdFx0V2luZG93RGlkTG9hZDogXCJpb3M6V2luZG93RGlkTG9hZFwiLFxuXHRcdFdpbmRvd1dpbGxBcHBlYXI6IFwiaW9zOldpbmRvd1dpbGxBcHBlYXJcIixcblx0XHRXaW5kb3dEaWRBcHBlYXI6IFwiaW9zOldpbmRvd0RpZEFwcGVhclwiLFxuXHRcdFdpbmRvd1dpbGxEaXNhcHBlYXI6IFwiaW9zOldpbmRvd1dpbGxEaXNhcHBlYXJcIixcblx0XHRXaW5kb3dEaWREaXNhcHBlYXI6IFwiaW9zOldpbmRvd0RpZERpc2FwcGVhclwiLFxuXHRcdFdpbmRvd1NhZmVBcmVhSW5zZXRzQ2hhbmdlZDogXCJpb3M6V2luZG93U2FmZUFyZWFJbnNldHNDaGFuZ2VkXCIsXG5cdFx0V2luZG93T3JpZW50YXRpb25DaGFuZ2VkOiBcImlvczpXaW5kb3dPcmllbnRhdGlvbkNoYW5nZWRcIixcblx0XHRXaW5kb3dUb3VjaEJlZ2FuOiBcImlvczpXaW5kb3dUb3VjaEJlZ2FuXCIsXG5cdFx0V2luZG93VG91Y2hNb3ZlZDogXCJpb3M6V2luZG93VG91Y2hNb3ZlZFwiLFxuXHRcdFdpbmRvd1RvdWNoRW5kZWQ6IFwiaW9zOldpbmRvd1RvdWNoRW5kZWRcIixcblx0XHRXaW5kb3dUb3VjaENhbmNlbGxlZDogXCJpb3M6V2luZG93VG91Y2hDYW5jZWxsZWRcIixcblx0XHRXZWJWaWV3RGlkU3RhcnROYXZpZ2F0aW9uOiBcImlvczpXZWJWaWV3RGlkU3RhcnROYXZpZ2F0aW9uXCIsXG5cdFx0V2ViVmlld0RpZEZpbmlzaE5hdmlnYXRpb246IFwiaW9zOldlYlZpZXdEaWRGaW5pc2hOYXZpZ2F0aW9uXCIsXG5cdFx0V2ViVmlld0RpZEZhaWxOYXZpZ2F0aW9uOiBcImlvczpXZWJWaWV3RGlkRmFpbE5hdmlnYXRpb25cIixcblx0XHRXZWJWaWV3RGVjaWRlUG9saWN5Rm9yTmF2aWdhdGlvbkFjdGlvbjogXCJpb3M6V2ViVmlld0RlY2lkZVBvbGljeUZvck5hdmlnYXRpb25BY3Rpb25cIixcblx0XHRCYXR0ZXJ5Q2hhbmdlZDogXCJpb3M6QmF0dGVyeUNoYW5nZWRcIixcblx0XHROZXR3b3JrQ2hhbmdlZDogXCJpb3M6TmV0d29ya0NoYW5nZWRcIixcblx0XHRUaGVtZUNoYW5nZWQ6IFwiaW9zOlRoZW1lQ2hhbmdlZFwiLFxuXHRcdFNjcmVlbkxvY2tlZDogXCJpb3M6U2NyZWVuTG9ja2VkXCIsXG5cdFx0U2NyZWVuVW5sb2NrZWQ6IFwiaW9zOlNjcmVlblVubG9ja2VkXCIsXG5cdH0pLFxuXHRBbmRyb2lkOiBPYmplY3QuZnJlZXplKHtcblx0XHRBY3Rpdml0eUNyZWF0ZWQ6IFwiYW5kcm9pZDpBY3Rpdml0eUNyZWF0ZWRcIixcblx0XHRBY3Rpdml0eVN0YXJ0ZWQ6IFwiYW5kcm9pZDpBY3Rpdml0eVN0YXJ0ZWRcIixcblx0XHRBY3Rpdml0eVJlc3VtZWQ6IFwiYW5kcm9pZDpBY3Rpdml0eVJlc3VtZWRcIixcblx0XHRBY3Rpdml0eVBhdXNlZDogXCJhbmRyb2lkOkFjdGl2aXR5UGF1c2VkXCIsXG5cdFx0QWN0aXZpdHlTdG9wcGVkOiBcImFuZHJvaWQ6QWN0aXZpdHlTdG9wcGVkXCIsXG5cdFx0QWN0aXZpdHlEZXN0cm95ZWQ6IFwiYW5kcm9pZDpBY3Rpdml0eURlc3Ryb3llZFwiLFxuXHRcdEFwcGxpY2F0aW9uTG93TWVtb3J5OiBcImFuZHJvaWQ6QXBwbGljYXRpb25Mb3dNZW1vcnlcIixcblx0XHRXZWJWaWV3UGFnZVN0YXJ0ZWQ6IFwiYW5kcm9pZDpXZWJWaWV3UGFnZVN0YXJ0ZWRcIixcblx0XHRXZWJWaWV3UGFnZUZpbmlzaGVkOiBcImFuZHJvaWQ6V2ViVmlld1BhZ2VGaW5pc2hlZFwiLFxuXHRcdEJhdHRlcnlDaGFuZ2VkOiBcImFuZHJvaWQ6QmF0dGVyeUNoYW5nZWRcIixcblx0XHROZXR3b3JrQ2hhbmdlZDogXCJhbmRyb2lkOk5ldHdvcmtDaGFuZ2VkXCIsXG5cdFx0VGhlbWVDaGFuZ2VkOiBcImFuZHJvaWQ6VGhlbWVDaGFuZ2VkXCIsXG5cdFx0U2NyZWVuTG9ja2VkOiBcImFuZHJvaWQ6U2NyZWVuTG9ja2VkXCIsXG5cdFx0U2NyZWVuVW5sb2NrZWQ6IFwiYW5kcm9pZDpTY3JlZW5VbmxvY2tlZFwiLFxuXHR9KSxcblx0Q29tbW9uOiBPYmplY3QuZnJlZXplKHtcblx0XHRBcHBsaWNhdGlvbk9wZW5lZFdpdGhGaWxlOiBcImNvbW1vbjpBcHBsaWNhdGlvbk9wZW5lZFdpdGhGaWxlXCIsXG5cdFx0QXBwbGljYXRpb25TdGFydGVkOiBcImNvbW1vbjpBcHBsaWNhdGlvblN0YXJ0ZWRcIixcblx0XHRBcHBsaWNhdGlvbkxhdW5jaGVkV2l0aFVybDogXCJjb21tb246QXBwbGljYXRpb25MYXVuY2hlZFdpdGhVcmxcIixcblx0XHRUaGVtZUNoYW5nZWQ6IFwiY29tbW9uOlRoZW1lQ2hhbmdlZFwiLFxuXHRcdFN5c3RlbURpZFdha2U6IFwiY29tbW9uOlN5c3RlbURpZFdha2VcIixcblx0XHRTeXN0ZW1XaWxsU2xlZXA6IFwiY29tbW9uOlN5c3RlbVdpbGxTbGVlcFwiLFxuXHRcdFdpbmRvd0Nsb3Npbmc6IFwiY29tbW9uOldpbmRvd0Nsb3NpbmdcIixcblx0XHRXaW5kb3dEaWRNb3ZlOiBcImNvbW1vbjpXaW5kb3dEaWRNb3ZlXCIsXG5cdFx0V2luZG93RGlkUmVzaXplOiBcImNvbW1vbjpXaW5kb3dEaWRSZXNpemVcIixcblx0XHRXaW5kb3dEUElDaGFuZ2VkOiBcImNvbW1vbjpXaW5kb3dEUElDaGFuZ2VkXCIsXG5cdFx0V2luZG93RmlsZXNEcm9wcGVkOiBcImNvbW1vbjpXaW5kb3dGaWxlc0Ryb3BwZWRcIixcblx0XHRXaW5kb3dGb2N1czogXCJjb21tb246V2luZG93Rm9jdXNcIixcblx0XHRXaW5kb3dGdWxsc2NyZWVuOiBcImNvbW1vbjpXaW5kb3dGdWxsc2NyZWVuXCIsXG5cdFx0V2luZG93SGlkZTogXCJjb21tb246V2luZG93SGlkZVwiLFxuXHRcdFdpbmRvd0xvc3RGb2N1czogXCJjb21tb246V2luZG93TG9zdEZvY3VzXCIsXG5cdFx0V2luZG93TWF4aW1pc2U6IFwiY29tbW9uOldpbmRvd01heGltaXNlXCIsXG5cdFx0V2luZG93TWluaW1pc2U6IFwiY29tbW9uOldpbmRvd01pbmltaXNlXCIsXG5cdFx0V2luZG93VG9nZ2xlRnJhbWVsZXNzOiBcImNvbW1vbjpXaW5kb3dUb2dnbGVGcmFtZWxlc3NcIixcblx0XHRXaW5kb3dSZXN0b3JlOiBcImNvbW1vbjpXaW5kb3dSZXN0b3JlXCIsXG5cdFx0V2luZG93UnVudGltZVJlYWR5OiBcImNvbW1vbjpXaW5kb3dSdW50aW1lUmVhZHlcIixcblx0XHRXaW5kb3dTaG93OiBcImNvbW1vbjpXaW5kb3dTaG93XCIsXG5cdFx0V2luZG93VW5GdWxsc2NyZWVuOiBcImNvbW1vbjpXaW5kb3dVbkZ1bGxzY3JlZW5cIixcblx0XHRXaW5kb3dVbk1heGltaXNlOiBcImNvbW1vbjpXaW5kb3dVbk1heGltaXNlXCIsXG5cdFx0V2luZG93VW5NaW5pbWlzZTogXCJjb21tb246V2luZG93VW5NaW5pbWlzZVwiLFxuXHRcdFdpbmRvd1pvb206IFwiY29tbW9uOldpbmRvd1pvb21cIixcblx0XHRXaW5kb3dab29tSW46IFwiY29tbW9uOldpbmRvd1pvb21JblwiLFxuXHRcdFdpbmRvd1pvb21PdXQ6IFwiY29tbW9uOldpbmRvd1pvb21PdXRcIixcblx0XHRXaW5kb3dab29tUmVzZXQ6IFwiY29tbW9uOldpbmRvd1pvb21SZXNldFwiLFxuXHRcdEJhdHRlcnlDaGFuZ2VkOiBcImNvbW1vbjpCYXR0ZXJ5Q2hhbmdlZFwiLFxuXHRcdE5ldHdvcmtDaGFuZ2VkOiBcImNvbW1vbjpOZXR3b3JrQ2hhbmdlZFwiLFxuXHRcdFNjcmVlbkxvY2tlZDogXCJjb21tb246U2NyZWVuTG9ja2VkXCIsXG5cdFx0U2NyZWVuVW5sb2NrZWQ6IFwiY29tbW9uOlNjcmVlblVubG9ja2VkXCIsXG5cdFx0TG93TWVtb3J5OiBcImNvbW1vbjpMb3dNZW1vcnlcIixcblx0fSksXG59KTtcbiIsICIvKlxuIF8gICAgIF9fICAgICBfIF9fXG58IHwgIC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoqXG4gKiBMb2dzIGEgbWVzc2FnZSB0byB0aGUgY29uc29sZSB3aXRoIGN1c3RvbSBmb3JtYXR0aW5nLlxuICpcbiAqIEBwYXJhbSBtZXNzYWdlIC0gVGhlIG1lc3NhZ2UgdG8gYmUgbG9nZ2VkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVidWdMb2cobWVzc2FnZTogYW55KSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG4gICAgY29uc29sZS5sb2coXG4gICAgICAgICclYyB3YWlsczMgJWMgJyArIG1lc3NhZ2UgKyAnICcsXG4gICAgICAgICdiYWNrZ3JvdW5kOiAjYWEwMDAwOyBjb2xvcjogI2ZmZjsgYm9yZGVyLXJhZGl1czogM3B4IDBweCAwcHggM3B4OyBwYWRkaW5nOiAxcHg7IGZvbnQtc2l6ZTogMC43cmVtJyxcbiAgICAgICAgJ2JhY2tncm91bmQ6ICMwMDk5MDA7IGNvbG9yOiAjZmZmOyBib3JkZXItcmFkaXVzOiAwcHggM3B4IDNweCAwcHg7IHBhZGRpbmc6IDFweDsgZm9udC1zaXplOiAwLjdyZW0nXG4gICAgKTtcbn1cblxuLyoqXG4gKiBDaGVja3Mgd2hldGhlciB0aGUgd2VidmlldyBzdXBwb3J0cyB0aGUge0BsaW5rIE1vdXNlRXZlbnQjYnV0dG9uc30gcHJvcGVydHkuXG4gKiBMb29raW5nIGF0IHlvdSBtYWNPUyBIaWdoIFNpZXJyYSFcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNhblRyYWNrQnV0dG9ucygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gKG5ldyBNb3VzZUV2ZW50KCdtb3VzZWRvd24nKSkuYnV0dG9ucyA9PT0gMDtcbn1cblxuLyoqXG4gKiBDaGVja3Mgd2hldGhlciB0aGUgYnJvd3NlciBzdXBwb3J0cyByZW1vdmluZyBsaXN0ZW5lcnMgYnkgdHJpZ2dlcmluZyBhbiBBYm9ydFNpZ25hbFxuICogKHNlZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvRXZlbnRUYXJnZXQvYWRkRXZlbnRMaXN0ZW5lciNzaWduYWwpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY2FuQWJvcnRMaXN0ZW5lcnMoKSB7XG4gICAgaWYgKCFFdmVudFRhcmdldCB8fCAhQWJvcnRTaWduYWwgfHwgIUFib3J0Q29udHJvbGxlcilcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuXG4gICAgbGV0IHJlc3VsdCA9IHRydWU7XG5cbiAgICBjb25zdCB0YXJnZXQgPSBuZXcgRXZlbnRUYXJnZXQoKTtcbiAgICBjb25zdCBjb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICAgIHRhcmdldC5hZGRFdmVudExpc3RlbmVyKCd0ZXN0JywgKCkgPT4geyByZXN1bHQgPSBmYWxzZTsgfSwgeyBzaWduYWw6IGNvbnRyb2xsZXIuc2lnbmFsIH0pO1xuICAgIGNvbnRyb2xsZXIuYWJvcnQoKTtcbiAgICB0YXJnZXQuZGlzcGF0Y2hFdmVudChuZXcgQ3VzdG9tRXZlbnQoJ3Rlc3QnKSk7XG5cbiAgICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKipcbiAqIFJlc29sdmVzIHRoZSBjbG9zZXN0IEhUTUxFbGVtZW50IGFuY2VzdG9yIG9mIGFuIGV2ZW50J3MgdGFyZ2V0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gZXZlbnRUYXJnZXQoZXZlbnQ6IEV2ZW50KTogSFRNTEVsZW1lbnQge1xuICAgIGlmIChldmVudC50YXJnZXQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgICAgICByZXR1cm4gZXZlbnQudGFyZ2V0O1xuICAgIH0gZWxzZSBpZiAoIShldmVudC50YXJnZXQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkgJiYgZXZlbnQudGFyZ2V0IGluc3RhbmNlb2YgTm9kZSkge1xuICAgICAgICByZXR1cm4gZXZlbnQudGFyZ2V0LnBhcmVudEVsZW1lbnQgPz8gZG9jdW1lbnQuYm9keTtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gZG9jdW1lbnQuYm9keTtcbiAgICB9XG59XG5cbi8qKipcbiBUaGlzIHRlY2huaXF1ZSBmb3IgcHJvcGVyIGxvYWQgZGV0ZWN0aW9uIGlzIHRha2VuIGZyb20gSFRNWDpcblxuIEJTRCAyLUNsYXVzZSBMaWNlbnNlXG5cbiBDb3B5cmlnaHQgKGMpIDIwMjAsIEJpZyBTa3kgU29mdHdhcmVcbiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuXG4gUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0XG4gbW9kaWZpY2F0aW9uLCBhcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6XG5cbiAxLiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsIHRoaXNcbiBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci5cblxuIDIuIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcbiB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uXG4gYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uXG5cbiBUSElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTIFwiQVMgSVNcIlxuIEFORCBBTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEVcbiBJTVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkVcbiBESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQ09QWVJJR0hUIEhPTERFUiBPUiBDT05UUklCVVRPUlMgQkUgTElBQkxFXG4gRk9SIEFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUxcbiBEQU1BR0VTIChJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUlxuIFNFUlZJQ0VTOyBMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKSBIT1dFVkVSXG4gQ0FVU0VEIEFORCBPTiBBTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSxcbiBPUiBUT1JUIChJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRVxuIE9GIFRISVMgU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuXG5cbiAqKiovXG5cbmxldCBpc1JlYWR5ID0gZmFsc2U7XG5pbXBvcnQgeyBoYXNET00gfSBmcm9tIFwiLi9lbnZpcm9ubWVudC5qc1wiO1xuXG5pZiAoaGFzRE9NKSB7XG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsICgpID0+IHsgaXNSZWFkeSA9IHRydWUgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3aGVuUmVhZHkoY2FsbGJhY2s6ICgpID0+IHZvaWQpIHtcbiAgICBpZiAoaXNSZWFkeSB8fCBkb2N1bWVudC5yZWFkeVN0YXRlID09PSAnY29tcGxldGUnKSB7XG4gICAgICAgIGNhbGxiYWNrKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsIGNhbGxiYWNrKTtcbiAgICB9XG59XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbmltcG9ydCB7bmV3UnVudGltZUNhbGxlciwgb2JqZWN0TmFtZXN9IGZyb20gXCIuL3J1bnRpbWUuanNcIjtcbmltcG9ydCB0eXBlIHsgU2NyZWVuIH0gZnJvbSBcIi4vc2NyZWVucy5qc1wiO1xuXG4vLyBEcm9wIHRhcmdldCBjb25zdGFudHNcbmNvbnN0IERST1BfVEFSR0VUX0FUVFJJQlVURSA9ICdkYXRhLWZpbGUtZHJvcC10YXJnZXQnO1xuY29uc3QgRFJPUF9UQVJHRVRfQUNUSVZFX0NMQVNTID0gJ2ZpbGUtZHJvcC10YXJnZXQtYWN0aXZlJztcbmxldCBjdXJyZW50RHJvcFRhcmdldDogRWxlbWVudCB8IG51bGwgPSBudWxsO1xuXG5jb25zdCBQb3NpdGlvbk1ldGhvZCAgICAgICAgICAgICAgICAgICAgPSAwO1xuY29uc3QgQ2VudGVyTWV0aG9kICAgICAgICAgICAgICAgICAgICAgID0gMTtcbmNvbnN0IENsb3NlTWV0aG9kICAgICAgICAgICAgICAgICAgICAgICA9IDI7XG5jb25zdCBEaXNhYmxlU2l6ZUNvbnN0cmFpbnRzTWV0aG9kICAgICAgPSAzO1xuY29uc3QgRW5hYmxlU2l6ZUNvbnN0cmFpbnRzTWV0aG9kICAgICAgID0gNDtcbmNvbnN0IEZvY3VzTWV0aG9kICAgICAgICAgICAgICAgICAgICAgICA9IDU7XG5jb25zdCBGb3JjZVJlbG9hZE1ldGhvZCAgICAgICAgICAgICAgICAgPSA2O1xuY29uc3QgRnVsbHNjcmVlbk1ldGhvZCAgICAgICAgICAgICAgICAgID0gNztcbmNvbnN0IEdldFNjcmVlbk1ldGhvZCAgICAgICAgICAgICAgICAgICA9IDg7XG5jb25zdCBHZXRab29tTWV0aG9kICAgICAgICAgICAgICAgICAgICAgPSA5O1xuY29uc3QgSGVpZ2h0TWV0aG9kICAgICAgICAgICAgICAgICAgICAgID0gMTA7XG5jb25zdCBIaWRlTWV0aG9kICAgICAgICAgICAgICAgICAgICAgICAgPSAxMTtcbmNvbnN0IElzRm9jdXNlZE1ldGhvZCAgICAgICAgICAgICAgICAgICA9IDEyO1xuY29uc3QgSXNGdWxsc2NyZWVuTWV0aG9kICAgICAgICAgICAgICAgID0gMTM7XG5jb25zdCBJc01heGltaXNlZE1ldGhvZCAgICAgICAgICAgICAgICAgPSAxNDtcbmNvbnN0IElzTWluaW1pc2VkTWV0aG9kICAgICAgICAgICAgICAgICA9IDE1O1xuY29uc3QgTWF4aW1pc2VNZXRob2QgICAgICAgICAgICAgICAgICAgID0gMTY7XG5jb25zdCBNaW5pbWlzZU1ldGhvZCAgICAgICAgICAgICAgICAgICAgPSAxNztcbmNvbnN0IE5hbWVNZXRob2QgICAgICAgICAgICAgICAgICAgICAgICA9IDE4O1xuY29uc3QgT3BlbkRldlRvb2xzTWV0aG9kICAgICAgICAgICAgICAgID0gMTk7XG5jb25zdCBSZWxhdGl2ZVBvc2l0aW9uTWV0aG9kICAgICAgICAgICAgPSAyMDtcbmNvbnN0IFJlbG9hZE1ldGhvZCAgICAgICAgICAgICAgICAgICAgICA9IDIxO1xuY29uc3QgUmVzaXphYmxlTWV0aG9kICAgICAgICAgICAgICAgICAgID0gMjI7XG5jb25zdCBSZXN0b3JlTWV0aG9kICAgICAgICAgICAgICAgICAgICAgPSAyMztcbmNvbnN0IFNldFBvc2l0aW9uTWV0aG9kICAgICAgICAgICAgICAgICA9IDI0O1xuY29uc3QgU2V0QWx3YXlzT25Ub3BNZXRob2QgICAgICAgICAgICAgID0gMjU7XG5jb25zdCBTZXRCYWNrZ3JvdW5kQ29sb3VyTWV0aG9kICAgICAgICAgPSAyNjtcbmNvbnN0IFNldEZyYW1lbGVzc01ldGhvZCAgICAgICAgICAgICAgICA9IDI3O1xuY29uc3QgU2V0RnVsbHNjcmVlbkJ1dHRvbkVuYWJsZWRNZXRob2QgID0gMjg7XG5jb25zdCBTZXRNYXhTaXplTWV0aG9kICAgICAgICAgICAgICAgICAgPSAyOTtcbmNvbnN0IFNldE1pblNpemVNZXRob2QgICAgICAgICAgICAgICAgICA9IDMwO1xuY29uc3QgU2V0UmVsYXRpdmVQb3NpdGlvbk1ldGhvZCAgICAgICAgID0gMzE7XG5jb25zdCBTZXRSZXNpemFibGVNZXRob2QgICAgICAgICAgICAgICAgPSAzMjtcbmNvbnN0IFNldFNpemVNZXRob2QgICAgICAgICAgICAgICAgICAgICA9IDMzO1xuY29uc3QgU2V0VGl0bGVNZXRob2QgICAgICAgICAgICAgICAgICAgID0gMzQ7XG5jb25zdCBTZXRab29tTWV0aG9kICAgICAgICAgICAgICAgICAgICAgPSAzNTtcbmNvbnN0IFNob3dNZXRob2QgICAgICAgICAgICAgICAgICAgICAgICA9IDM2O1xuY29uc3QgU2l6ZU1ldGhvZCAgICAgICAgICAgICAgICAgICAgICAgID0gMzc7XG5jb25zdCBUb2dnbGVGdWxsc2NyZWVuTWV0aG9kICAgICAgICAgICAgPSAzODtcbmNvbnN0IFRvZ2dsZU1heGltaXNlTWV0aG9kICAgICAgICAgICAgICA9IDM5O1xuY29uc3QgVG9nZ2xlRnJhbWVsZXNzTWV0aG9kICAgICAgICAgICAgID0gNDA7IFxuY29uc3QgVW5GdWxsc2NyZWVuTWV0aG9kICAgICAgICAgICAgICAgID0gNDE7XG5jb25zdCBVbk1heGltaXNlTWV0aG9kICAgICAgICAgICAgICAgICAgPSA0MjtcbmNvbnN0IFVuTWluaW1pc2VNZXRob2QgICAgICAgICAgICAgICAgICA9IDQzO1xuY29uc3QgV2lkdGhNZXRob2QgICAgICAgICAgICAgICAgICAgICAgID0gNDQ7XG5jb25zdCBab29tTWV0aG9kICAgICAgICAgICAgICAgICAgICAgICAgPSA0NTtcbmNvbnN0IFpvb21Jbk1ldGhvZCAgICAgICAgICAgICAgICAgICAgICA9IDQ2O1xuY29uc3QgWm9vbU91dE1ldGhvZCAgICAgICAgICAgICAgICAgICAgID0gNDc7XG5jb25zdCBab29tUmVzZXRNZXRob2QgICAgICAgICAgICAgICAgICAgPSA0ODtcbmNvbnN0IFNuYXBBc3Npc3RNZXRob2QgICAgICAgICAgICAgICAgICA9IDQ5O1xuY29uc3QgRmlsZXNEcm9wcGVkICAgICAgICAgICAgICAgICAgICAgID0gNTA7XG5jb25zdCBQcmludE1ldGhvZCAgICAgICAgICAgICAgICAgICAgICAgPSA1MTtcbmNvbnN0IFNldFNjcmVlbk1ldGhvZCAgICAgICAgICAgICAgICAgICA9IDUyO1xuXG4vKipcbiAqIEZpbmRzIHRoZSBuZWFyZXN0IGRyb3AgdGFyZ2V0IGVsZW1lbnQgYnkgd2Fsa2luZyB1cCB0aGUgRE9NIHRyZWUuXG4gKi9cbmZ1bmN0aW9uIGdldERyb3BUYXJnZXRFbGVtZW50KGVsZW1lbnQ6IEVsZW1lbnQgfCBudWxsKTogRWxlbWVudCB8IG51bGwge1xuICAgIGlmICghZWxlbWVudCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuIGVsZW1lbnQuY2xvc2VzdChgWyR7RFJPUF9UQVJHRVRfQVRUUklCVVRFfV1gKTtcbn1cblxuLyoqXG4gKiBDaGVjayBpZiB3ZSBjYW4gdXNlIFdlYlZpZXcyJ3MgcG9zdE1lc3NhZ2VXaXRoQWRkaXRpb25hbE9iamVjdHMgKFdpbmRvd3MpXG4gKiBBbHNvIGNoZWNrcyB0aGF0IEVuYWJsZUZpbGVEcm9wIGlzIHRydWUgZm9yIHRoaXMgd2luZG93LlxuICovXG5mdW5jdGlvbiBjYW5SZXNvbHZlRmlsZVBhdGhzKCk6IGJvb2xlYW4ge1xuICAgIC8vIE11c3QgaGF2ZSBXZWJWaWV3MidzIHBvc3RNZXNzYWdlV2l0aEFkZGl0aW9uYWxPYmplY3RzIEFQSSAoV2luZG93cyBvbmx5KVxuICAgIGlmICgod2luZG93IGFzIGFueSkuY2hyb21lPy53ZWJ2aWV3Py5wb3N0TWVzc2FnZVdpdGhBZGRpdGlvbmFsT2JqZWN0cyA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgLy8gTXVzdCBoYXZlIEVuYWJsZUZpbGVEcm9wIHNldCB0byB0cnVlIGZvciB0aGlzIHdpbmRvd1xuICAgIC8vIFRoaXMgZmxhZyBpcyBzZXQgYnkgdGhlIEdvIGJhY2tlbmQgZHVyaW5nIHJ1bnRpbWUgaW5pdGlhbGl6YXRpb25cbiAgICByZXR1cm4gKHdpbmRvdyBhcyBhbnkpLl93YWlscz8uZmxhZ3M/LmVuYWJsZUZpbGVEcm9wID09PSB0cnVlO1xufVxuXG4vKipcbiAqIFNlbmQgZmlsZSBkcm9wIHRvIGJhY2tlbmQgdmlhIFdlYlZpZXcyIChXaW5kb3dzIG9ubHkpXG4gKi9cbmZ1bmN0aW9uIHJlc29sdmVGaWxlUGF0aHMoeDogbnVtYmVyLCB5OiBudW1iZXIsIGZpbGVzOiBGaWxlW10pOiB2b2lkIHtcbiAgICBpZiAoKHdpbmRvdyBhcyBhbnkpLmNocm9tZT8ud2Vidmlldz8ucG9zdE1lc3NhZ2VXaXRoQWRkaXRpb25hbE9iamVjdHMpIHtcbiAgICAgICAgKHdpbmRvdyBhcyBhbnkpLmNocm9tZS53ZWJ2aWV3LnBvc3RNZXNzYWdlV2l0aEFkZGl0aW9uYWxPYmplY3RzKGBmaWxlOmRyb3A6JHt4fToke3l9YCwgZmlsZXMpO1xuICAgIH1cbn1cblxuLy8gTmF0aXZlIGRyYWcgc3RhdGUgKExpbnV4L21hY09TIGludGVyY2VwdCBET00gZHJhZyBldmVudHMpXG5sZXQgbmF0aXZlRHJhZ0FjdGl2ZSA9IGZhbHNlO1xuXG4vKipcbiAqIENsZWFucyB1cCBuYXRpdmUgZHJhZyBzdGF0ZSBhbmQgaG92ZXIgZWZmZWN0cy5cbiAqIENhbGxlZCBvbiBkcm9wIG9yIHdoZW4gZHJhZyBsZWF2ZXMgdGhlIHdpbmRvdy5cbiAqL1xuZnVuY3Rpb24gY2xlYW51cE5hdGl2ZURyYWcoKTogdm9pZCB7XG4gICAgbmF0aXZlRHJhZ0FjdGl2ZSA9IGZhbHNlO1xuICAgIGlmIChjdXJyZW50RHJvcFRhcmdldCkge1xuICAgICAgICBjdXJyZW50RHJvcFRhcmdldC5jbGFzc0xpc3QucmVtb3ZlKERST1BfVEFSR0VUX0FDVElWRV9DTEFTUyk7XG4gICAgICAgIGN1cnJlbnREcm9wVGFyZ2V0ID0gbnVsbDtcbiAgICB9XG59XG5cbi8qKlxuICogQ2FsbGVkIGZyb20gR28gd2hlbiBhIGZpbGUgZHJhZyBlbnRlcnMgdGhlIHdpbmRvdyBvbiBMaW51eC9tYWNPUy5cbiAqL1xuZnVuY3Rpb24gaGFuZGxlRHJhZ0VudGVyKCk6IHZvaWQge1xuICAgIC8vIENoZWNrIGlmIGZpbGUgZHJvcHMgYXJlIGVuYWJsZWQgZm9yIHRoaXMgd2luZG93XG4gICAgaWYgKCh3aW5kb3cgYXMgYW55KS5fd2FpbHM/LmZsYWdzPy5lbmFibGVGaWxlRHJvcCA9PT0gZmFsc2UpIHtcbiAgICAgICAgcmV0dXJuOyAvLyBGaWxlIGRyb3BzIGRpc2FibGVkLCBkb24ndCBhY3RpdmF0ZSBkcmFnIHN0YXRlXG4gICAgfVxuICAgIG5hdGl2ZURyYWdBY3RpdmUgPSB0cnVlO1xufVxuXG4vKipcbiAqIENhbGxlZCBmcm9tIEdvIHdoZW4gYSBmaWxlIGRyYWcgbGVhdmVzIHRoZSB3aW5kb3cgb24gTGludXgvbWFjT1MuXG4gKi9cbmZ1bmN0aW9uIGhhbmRsZURyYWdMZWF2ZSgpOiB2b2lkIHtcbiAgICBjbGVhbnVwTmF0aXZlRHJhZygpO1xufVxuXG4vKipcbiAqIENhbGxlZCBmcm9tIEdvIGR1cmluZyBmaWxlIGRyYWcgdG8gdXBkYXRlIGhvdmVyIHN0YXRlIG9uIExpbnV4L21hY09TLlxuICogQHBhcmFtIHggLSBYIGNvb3JkaW5hdGUgaW4gQ1NTIHBpeGVsc1xuICogQHBhcmFtIHkgLSBZIGNvb3JkaW5hdGUgaW4gQ1NTIHBpeGVsc1xuICovXG5mdW5jdGlvbiBoYW5kbGVEcmFnT3Zlcih4OiBudW1iZXIsIHk6IG51bWJlcik6IHZvaWQge1xuICAgIGlmICghbmF0aXZlRHJhZ0FjdGl2ZSkgcmV0dXJuO1xuICAgIFxuICAgIC8vIENoZWNrIGlmIGZpbGUgZHJvcHMgYXJlIGVuYWJsZWQgZm9yIHRoaXMgd2luZG93XG4gICAgaWYgKCh3aW5kb3cgYXMgYW55KS5fd2FpbHM/LmZsYWdzPy5lbmFibGVGaWxlRHJvcCA9PT0gZmFsc2UpIHtcbiAgICAgICAgcmV0dXJuOyAvLyBGaWxlIGRyb3BzIGRpc2FibGVkLCBkb24ndCBzaG93IGhvdmVyIGVmZmVjdHNcbiAgICB9XG4gICAgXG4gICAgY29uc3QgdGFyZ2V0RWxlbWVudCA9IGRvY3VtZW50LmVsZW1lbnRGcm9tUG9pbnQoeCwgeSk7XG4gICAgY29uc3QgZHJvcFRhcmdldCA9IGdldERyb3BUYXJnZXRFbGVtZW50KHRhcmdldEVsZW1lbnQpO1xuICAgIFxuICAgIGlmIChjdXJyZW50RHJvcFRhcmdldCAmJiBjdXJyZW50RHJvcFRhcmdldCAhPT0gZHJvcFRhcmdldCkge1xuICAgICAgICBjdXJyZW50RHJvcFRhcmdldC5jbGFzc0xpc3QucmVtb3ZlKERST1BfVEFSR0VUX0FDVElWRV9DTEFTUyk7XG4gICAgfVxuICAgIFxuICAgIGlmIChkcm9wVGFyZ2V0KSB7XG4gICAgICAgIGRyb3BUYXJnZXQuY2xhc3NMaXN0LmFkZChEUk9QX1RBUkdFVF9BQ1RJVkVfQ0xBU1MpO1xuICAgICAgICBjdXJyZW50RHJvcFRhcmdldCA9IGRyb3BUYXJnZXQ7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgY3VycmVudERyb3BUYXJnZXQgPSBudWxsO1xuICAgIH1cbn1cblxuXG5cbi8vIEV4cG9ydCB0aGUgaGFuZGxlcnMgZm9yIHVzZSBieSBHbyB2aWEgaW5kZXgudHNcbmV4cG9ydCB7IGhhbmRsZURyYWdFbnRlciwgaGFuZGxlRHJhZ0xlYXZlLCBoYW5kbGVEcmFnT3ZlciB9O1xuXG4vKipcbiAqIEEgcmVjb3JkIGRlc2NyaWJpbmcgdGhlIHBvc2l0aW9uIG9mIGEgd2luZG93LlxuICovXG5pbnRlcmZhY2UgUG9zaXRpb24ge1xuICAgIC8qKiBUaGUgaG9yaXpvbnRhbCBwb3NpdGlvbiBvZiB0aGUgd2luZG93LiAqL1xuICAgIHg6IG51bWJlcjtcbiAgICAvKiogVGhlIHZlcnRpY2FsIHBvc2l0aW9uIG9mIHRoZSB3aW5kb3cuICovXG4gICAgeTogbnVtYmVyO1xufVxuXG4vKipcbiAqIEEgcmVjb3JkIGRlc2NyaWJpbmcgdGhlIHNpemUgb2YgYSB3aW5kb3cuXG4gKi9cbmludGVyZmFjZSBTaXplIHtcbiAgICAvKiogVGhlIHdpZHRoIG9mIHRoZSB3aW5kb3cuICovXG4gICAgd2lkdGg6IG51bWJlcjtcbiAgICAvKiogVGhlIGhlaWdodCBvZiB0aGUgd2luZG93LiAqL1xuICAgIGhlaWdodDogbnVtYmVyO1xufVxuXG4vLyBQcml2YXRlIGZpZWxkIG5hbWVzLlxuY29uc3QgY2FsbGVyU3ltID0gU3ltYm9sKFwiY2FsbGVyXCIpO1xuXG5jbGFzcyBXaW5kb3cge1xuICAgIC8vIFByaXZhdGUgZmllbGRzLlxuICAgIHByaXZhdGUgW2NhbGxlclN5bV06IChtZXNzYWdlOiBudW1iZXIsIGFyZ3M/OiBhbnkpID0+IFByb21pc2U8YW55PjtcblxuICAgIC8qKlxuICAgICAqIEluaXRpYWxpc2VzIGEgd2luZG93IG9iamVjdCB3aXRoIHRoZSBzcGVjaWZpZWQgbmFtZS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdGFyZ2V0IHdpbmRvdy5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihuYW1lOiBzdHJpbmcgPSAnJykge1xuICAgICAgICB0aGlzW2NhbGxlclN5bV0gPSBuZXdSdW50aW1lQ2FsbGVyKG9iamVjdE5hbWVzLldpbmRvdywgbmFtZSlcblxuICAgICAgICAvLyBiaW5kIGluc3RhbmNlIG1ldGhvZCB0byBtYWtlIHRoZW0gZWFzaWx5IHVzYWJsZSBpbiBldmVudCBoYW5kbGVyc1xuICAgICAgICBmb3IgKGNvbnN0IG1ldGhvZCBvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhXaW5kb3cucHJvdG90eXBlKSkge1xuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgIG1ldGhvZCAhPT0gXCJjb25zdHJ1Y3RvclwiXG4gICAgICAgICAgICAgICAgJiYgdHlwZW9mICh0aGlzIGFzIGFueSlbbWV0aG9kXSA9PT0gXCJmdW5jdGlvblwiXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAodGhpcyBhcyBhbnkpW21ldGhvZF0gPSAodGhpcyBhcyBhbnkpW21ldGhvZF0uYmluZCh0aGlzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHNwZWNpZmllZCB3aW5kb3cuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB3aW5kb3cgdG8gZ2V0LlxuICAgICAqIEByZXR1cm5zIFRoZSBjb3JyZXNwb25kaW5nIHdpbmRvdyBvYmplY3QuXG4gICAgICovXG4gICAgR2V0KG5hbWU6IHN0cmluZyk6IFdpbmRvdyB7XG4gICAgICAgIHJldHVybiBuZXcgV2luZG93KG5hbWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGFic29sdXRlIHBvc2l0aW9uIG9mIHRoZSB3aW5kb3cuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBUaGUgY3VycmVudCBhYnNvbHV0ZSBwb3NpdGlvbiBvZiB0aGUgd2luZG93LlxuICAgICAqL1xuICAgIFBvc2l0aW9uKCk6IFByb21pc2U8UG9zaXRpb24+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShQb3NpdGlvbk1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2VudGVycyB0aGUgd2luZG93IG9uIHRoZSBzY3JlZW4uXG4gICAgICovXG4gICAgQ2VudGVyKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKENlbnRlck1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2xvc2VzIHRoZSB3aW5kb3cuXG4gICAgICovXG4gICAgQ2xvc2UoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oQ2xvc2VNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERpc2FibGVzIG1pbi9tYXggc2l6ZSBjb25zdHJhaW50cy5cbiAgICAgKi9cbiAgICBEaXNhYmxlU2l6ZUNvbnN0cmFpbnRzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKERpc2FibGVTaXplQ29uc3RyYWludHNNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEVuYWJsZXMgbWluL21heCBzaXplIGNvbnN0cmFpbnRzLlxuICAgICAqL1xuICAgIEVuYWJsZVNpemVDb25zdHJhaW50cygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShFbmFibGVTaXplQ29uc3RyYWludHNNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZvY3VzZXMgdGhlIHdpbmRvdy5cbiAgICAgKi9cbiAgICBGb2N1cygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShGb2N1c01ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRm9yY2VzIHRoZSB3aW5kb3cgdG8gcmVsb2FkIHRoZSBwYWdlIGFzc2V0cy5cbiAgICAgKi9cbiAgICBGb3JjZVJlbG9hZCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShGb3JjZVJlbG9hZE1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3dpdGNoZXMgdGhlIHdpbmRvdyB0byBmdWxsc2NyZWVuIG1vZGUuXG4gICAgICovXG4gICAgRnVsbHNjcmVlbigpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShGdWxsc2NyZWVuTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBzY3JlZW4gdGhhdCB0aGUgd2luZG93IGlzIG9uLlxuICAgICAqXG4gICAgICogQHJldHVybnMgVGhlIHNjcmVlbiB0aGUgd2luZG93IGlzIGN1cnJlbnRseSBvbi5cbiAgICAgKi9cbiAgICBHZXRTY3JlZW4oKTogUHJvbWlzZTxTY3JlZW4+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShHZXRTY3JlZW5NZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGN1cnJlbnQgem9vbSBsZXZlbCBvZiB0aGUgd2luZG93LlxuICAgICAqXG4gICAgICogQHJldHVybnMgVGhlIGN1cnJlbnQgem9vbSBsZXZlbC5cbiAgICAgKi9cbiAgICBHZXRab29tKCk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oR2V0Wm9vbU1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgaGVpZ2h0IG9mIHRoZSB3aW5kb3cuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBUaGUgY3VycmVudCBoZWlnaHQgb2YgdGhlIHdpbmRvdy5cbiAgICAgKi9cbiAgICBIZWlnaHQoKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShIZWlnaHRNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhpZGVzIHRoZSB3aW5kb3cuXG4gICAgICovXG4gICAgSGlkZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShIaWRlTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRydWUgaWYgdGhlIHdpbmRvdyBpcyBmb2N1c2VkLlxuICAgICAqXG4gICAgICogQHJldHVybnMgV2hldGhlciB0aGUgd2luZG93IGlzIGN1cnJlbnRseSBmb2N1c2VkLlxuICAgICAqL1xuICAgIElzRm9jdXNlZCgpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShJc0ZvY3VzZWRNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgd2luZG93IGlzIGZ1bGxzY3JlZW4uXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBXaGV0aGVyIHRoZSB3aW5kb3cgaXMgY3VycmVudGx5IGZ1bGxzY3JlZW4uXG4gICAgICovXG4gICAgSXNGdWxsc2NyZWVuKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKElzRnVsbHNjcmVlbk1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0cnVlIGlmIHRoZSB3aW5kb3cgaXMgbWF4aW1pc2VkLlxuICAgICAqXG4gICAgICogQHJldHVybnMgV2hldGhlciB0aGUgd2luZG93IGlzIGN1cnJlbnRseSBtYXhpbWlzZWQuXG4gICAgICovXG4gICAgSXNNYXhpbWlzZWQoKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oSXNNYXhpbWlzZWRNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgd2luZG93IGlzIG1pbmltaXNlZC5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIFdoZXRoZXIgdGhlIHdpbmRvdyBpcyBjdXJyZW50bHkgbWluaW1pc2VkLlxuICAgICAqL1xuICAgIElzTWluaW1pc2VkKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKElzTWluaW1pc2VkTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNYXhpbWlzZXMgdGhlIHdpbmRvdy5cbiAgICAgKi9cbiAgICBNYXhpbWlzZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShNYXhpbWlzZU1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWluaW1pc2VzIHRoZSB3aW5kb3cuXG4gICAgICovXG4gICAgTWluaW1pc2UoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oTWluaW1pc2VNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIG5hbWUgb2YgdGhlIHdpbmRvdy5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIFRoZSBuYW1lIG9mIHRoZSB3aW5kb3cuXG4gICAgICovXG4gICAgTmFtZSgpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKE5hbWVNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE9wZW5zIHRoZSBkZXZlbG9wbWVudCB0b29scyBwYW5lLlxuICAgICAqL1xuICAgIE9wZW5EZXZUb29scygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShPcGVuRGV2VG9vbHNNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHJlbGF0aXZlIHBvc2l0aW9uIG9mIHRoZSB3aW5kb3cgdG8gdGhlIHNjcmVlbi5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIFRoZSBjdXJyZW50IHJlbGF0aXZlIHBvc2l0aW9uIG9mIHRoZSB3aW5kb3cuXG4gICAgICovXG4gICAgUmVsYXRpdmVQb3NpdGlvbigpOiBQcm9taXNlPFBvc2l0aW9uPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oUmVsYXRpdmVQb3NpdGlvbk1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVsb2FkcyB0aGUgcGFnZSBhc3NldHMuXG4gICAgICovXG4gICAgUmVsb2FkKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFJlbG9hZE1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0cnVlIGlmIHRoZSB3aW5kb3cgaXMgcmVzaXphYmxlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgV2hldGhlciB0aGUgd2luZG93IGlzIGN1cnJlbnRseSByZXNpemFibGUuXG4gICAgICovXG4gICAgUmVzaXphYmxlKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFJlc2l6YWJsZU1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVzdG9yZXMgdGhlIHdpbmRvdyB0byBpdHMgcHJldmlvdXMgc3RhdGUgaWYgaXQgd2FzIHByZXZpb3VzbHkgbWluaW1pc2VkLCBtYXhpbWlzZWQgb3IgZnVsbHNjcmVlbi5cbiAgICAgKi9cbiAgICBSZXN0b3JlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFJlc3RvcmVNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIGFic29sdXRlIHBvc2l0aW9uIG9mIHRoZSB3aW5kb3cuXG4gICAgICpcbiAgICAgKiBAcGFyYW0geCAtIFRoZSBkZXNpcmVkIGhvcml6b250YWwgYWJzb2x1dGUgcG9zaXRpb24gb2YgdGhlIHdpbmRvdy5cbiAgICAgKiBAcGFyYW0geSAtIFRoZSBkZXNpcmVkIHZlcnRpY2FsIGFic29sdXRlIHBvc2l0aW9uIG9mIHRoZSB3aW5kb3cuXG4gICAgICovXG4gICAgU2V0UG9zaXRpb24oeDogbnVtYmVyLCB5OiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShTZXRQb3NpdGlvbk1ldGhvZCwgeyB4LCB5IH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHdpbmRvdyB0byBiZSBhbHdheXMgb24gdG9wLlxuICAgICAqXG4gICAgICogQHBhcmFtIGFsd2F5c09uVG9wIC0gV2hldGhlciB0aGUgd2luZG93IHNob3VsZCBzdGF5IG9uIHRvcC5cbiAgICAgKi9cbiAgICBTZXRBbHdheXNPblRvcChhbHdheXNPblRvcDogYm9vbGVhbik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFNldEFsd2F5c09uVG9wTWV0aG9kLCB7IGFsd2F5c09uVG9wIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIGJhY2tncm91bmQgY29sb3VyIG9mIHRoZSB3aW5kb3cuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gciAtIFRoZSBkZXNpcmVkIHJlZCBjb21wb25lbnQgb2YgdGhlIHdpbmRvdyBiYWNrZ3JvdW5kLlxuICAgICAqIEBwYXJhbSBnIC0gVGhlIGRlc2lyZWQgZ3JlZW4gY29tcG9uZW50IG9mIHRoZSB3aW5kb3cgYmFja2dyb3VuZC5cbiAgICAgKiBAcGFyYW0gYiAtIFRoZSBkZXNpcmVkIGJsdWUgY29tcG9uZW50IG9mIHRoZSB3aW5kb3cgYmFja2dyb3VuZC5cbiAgICAgKiBAcGFyYW0gYSAtIFRoZSBkZXNpcmVkIGFscGhhIGNvbXBvbmVudCBvZiB0aGUgd2luZG93IGJhY2tncm91bmQuXG4gICAgICovXG4gICAgU2V0QmFja2dyb3VuZENvbG91cihyOiBudW1iZXIsIGc6IG51bWJlciwgYjogbnVtYmVyLCBhOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShTZXRCYWNrZ3JvdW5kQ29sb3VyTWV0aG9kLCB7IHIsIGcsIGIsIGEgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0aGUgd2luZG93IGZyYW1lIGFuZCB0aXRsZSBiYXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZnJhbWVsZXNzIC0gV2hldGhlciB0aGUgd2luZG93IHNob3VsZCBiZSBmcmFtZWxlc3MuXG4gICAgICovXG4gICAgU2V0RnJhbWVsZXNzKGZyYW1lbGVzczogYm9vbGVhbik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFNldEZyYW1lbGVzc01ldGhvZCwgeyBmcmFtZWxlc3MgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGlzYWJsZXMgdGhlIHN5c3RlbSBmdWxsc2NyZWVuIGJ1dHRvbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBlbmFibGVkIC0gV2hldGhlciB0aGUgZnVsbHNjcmVlbiBidXR0b24gc2hvdWxkIGJlIGVuYWJsZWQuXG4gICAgICovXG4gICAgU2V0RnVsbHNjcmVlbkJ1dHRvbkVuYWJsZWQoZW5hYmxlZDogYm9vbGVhbik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFNldEZ1bGxzY3JlZW5CdXR0b25FbmFibGVkTWV0aG9kLCB7IGVuYWJsZWQgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgbWF4aW11bSBzaXplIG9mIHRoZSB3aW5kb3cuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gd2lkdGggLSBUaGUgZGVzaXJlZCBtYXhpbXVtIHdpZHRoIG9mIHRoZSB3aW5kb3cuXG4gICAgICogQHBhcmFtIGhlaWdodCAtIFRoZSBkZXNpcmVkIG1heGltdW0gaGVpZ2h0IG9mIHRoZSB3aW5kb3cuXG4gICAgICovXG4gICAgU2V0TWF4U2l6ZSh3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFNldE1heFNpemVNZXRob2QsIHsgd2lkdGgsIGhlaWdodCB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBtaW5pbXVtIHNpemUgb2YgdGhlIHdpbmRvdy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB3aWR0aCAtIFRoZSBkZXNpcmVkIG1pbmltdW0gd2lkdGggb2YgdGhlIHdpbmRvdy5cbiAgICAgKiBAcGFyYW0gaGVpZ2h0IC0gVGhlIGRlc2lyZWQgbWluaW11bSBoZWlnaHQgb2YgdGhlIHdpbmRvdy5cbiAgICAgKi9cbiAgICBTZXRNaW5TaXplKHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oU2V0TWluU2l6ZU1ldGhvZCwgeyB3aWR0aCwgaGVpZ2h0IH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHJlbGF0aXZlIHBvc2l0aW9uIG9mIHRoZSB3aW5kb3cgdG8gdGhlIHNjcmVlbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB4IC0gVGhlIGRlc2lyZWQgaG9yaXpvbnRhbCByZWxhdGl2ZSBwb3NpdGlvbiBvZiB0aGUgd2luZG93LlxuICAgICAqIEBwYXJhbSB5IC0gVGhlIGRlc2lyZWQgdmVydGljYWwgcmVsYXRpdmUgcG9zaXRpb24gb2YgdGhlIHdpbmRvdy5cbiAgICAgKi9cbiAgICBTZXRSZWxhdGl2ZVBvc2l0aW9uKHg6IG51bWJlciwgeTogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oU2V0UmVsYXRpdmVQb3NpdGlvbk1ldGhvZCwgeyB4LCB5IH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgd2hldGhlciB0aGUgd2luZG93IGlzIHJlc2l6YWJsZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSByZXNpemFibGUgLSBXaGV0aGVyIHRoZSB3aW5kb3cgc2hvdWxkIGJlIHJlc2l6YWJsZS5cbiAgICAgKi9cbiAgICBTZXRSZXNpemFibGUocmVzaXphYmxlOiBib29sZWFuKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oU2V0UmVzaXphYmxlTWV0aG9kLCB7IHJlc2l6YWJsZSB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBzaXplIG9mIHRoZSB3aW5kb3cuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gd2lkdGggLSBUaGUgZGVzaXJlZCB3aWR0aCBvZiB0aGUgd2luZG93LlxuICAgICAqIEBwYXJhbSBoZWlnaHQgLSBUaGUgZGVzaXJlZCBoZWlnaHQgb2YgdGhlIHdpbmRvdy5cbiAgICAgKi9cbiAgICBTZXRTaXplKHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oU2V0U2l6ZU1ldGhvZCwgeyB3aWR0aCwgaGVpZ2h0IH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHRpdGxlIG9mIHRoZSB3aW5kb3cuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdGl0bGUgLSBUaGUgZGVzaXJlZCB0aXRsZSBvZiB0aGUgd2luZG93LlxuICAgICAqL1xuICAgIFNldFRpdGxlKHRpdGxlOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShTZXRUaXRsZU1ldGhvZCwgeyB0aXRsZSB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSB6b29tIGxldmVsIG9mIHRoZSB3aW5kb3cuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gem9vbSAtIFRoZSBkZXNpcmVkIHpvb20gbGV2ZWwuXG4gICAgICovXG4gICAgU2V0Wm9vbSh6b29tOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShTZXRab29tTWV0aG9kLCB7IHpvb20gfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2hvd3MgdGhlIHdpbmRvdy5cbiAgICAgKi9cbiAgICBTaG93KCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFNob3dNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHNpemUgb2YgdGhlIHdpbmRvdy5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIFRoZSBjdXJyZW50IHNpemUgb2YgdGhlIHdpbmRvdy5cbiAgICAgKi9cbiAgICBTaXplKCk6IFByb21pc2U8U2l6ZT4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFNpemVNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRvZ2dsZXMgdGhlIHdpbmRvdyBiZXR3ZWVuIGZ1bGxzY3JlZW4gYW5kIG5vcm1hbC5cbiAgICAgKi9cbiAgICBUb2dnbGVGdWxsc2NyZWVuKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFRvZ2dsZUZ1bGxzY3JlZW5NZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRvZ2dsZXMgdGhlIHdpbmRvdyBiZXR3ZWVuIG1heGltaXNlZCBhbmQgbm9ybWFsLlxuICAgICAqL1xuICAgIFRvZ2dsZU1heGltaXNlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFRvZ2dsZU1heGltaXNlTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUb2dnbGVzIHRoZSB3aW5kb3cgYmV0d2VlbiBmcmFtZWxlc3MgYW5kIG5vcm1hbC5cbiAgICAgKi9cbiAgICBUb2dnbGVGcmFtZWxlc3MoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oVG9nZ2xlRnJhbWVsZXNzTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVbi1mdWxsc2NyZWVucyB0aGUgd2luZG93LlxuICAgICAqL1xuICAgIFVuRnVsbHNjcmVlbigpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShVbkZ1bGxzY3JlZW5NZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVuLW1heGltaXNlcyB0aGUgd2luZG93LlxuICAgICAqL1xuICAgIFVuTWF4aW1pc2UoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oVW5NYXhpbWlzZU1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVW4tbWluaW1pc2VzIHRoZSB3aW5kb3cuXG4gICAgICovXG4gICAgVW5NaW5pbWlzZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShVbk1pbmltaXNlTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSB3aWR0aCBvZiB0aGUgd2luZG93LlxuICAgICAqXG4gICAgICogQHJldHVybnMgVGhlIGN1cnJlbnQgd2lkdGggb2YgdGhlIHdpbmRvdy5cbiAgICAgKi9cbiAgICBXaWR0aCgpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFdpZHRoTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBab29tcyB0aGUgd2luZG93LlxuICAgICAqL1xuICAgIFpvb20oKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oWm9vbU1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW5jcmVhc2VzIHRoZSB6b29tIGxldmVsIG9mIHRoZSB3ZWJ2aWV3IGNvbnRlbnQuXG4gICAgICovXG4gICAgWm9vbUluKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFpvb21Jbk1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGVjcmVhc2VzIHRoZSB6b29tIGxldmVsIG9mIHRoZSB3ZWJ2aWV3IGNvbnRlbnQuXG4gICAgICovXG4gICAgWm9vbU91dCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShab29tT3V0TWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXNldHMgdGhlIHpvb20gbGV2ZWwgb2YgdGhlIHdlYnZpZXcgY29udGVudC5cbiAgICAgKi9cbiAgICBab29tUmVzZXQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oWm9vbVJlc2V0TWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVzIGZpbGUgZHJvcHMgb3JpZ2luYXRpbmcgZnJvbSBwbGF0Zm9ybS1zcGVjaWZpYyBjb2RlIChlLmcuLCBtYWNPUy9MaW51eCBuYXRpdmUgZHJhZy1hbmQtZHJvcCkuXG4gICAgICogR2F0aGVycyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgZHJvcCB0YXJnZXQgZWxlbWVudCBhbmQgc2VuZHMgaXQgYmFjayB0byB0aGUgR28gYmFja2VuZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBmaWxlbmFtZXMgLSBBbiBhcnJheSBvZiBmaWxlIHBhdGhzIChzdHJpbmdzKSB0aGF0IHdlcmUgZHJvcHBlZC5cbiAgICAgKiBAcGFyYW0geCAtIFRoZSB4LWNvb3JkaW5hdGUgb2YgdGhlIGRyb3AgZXZlbnQsIGluIGxvZ2ljYWwgKENTUykgcGl4ZWxzIHJlbGF0aXZlIHRvIHRoZSB3ZWJ2aWV3LlxuICAgICAqIEBwYXJhbSB5IC0gVGhlIHktY29vcmRpbmF0ZSBvZiB0aGUgZHJvcCBldmVudCwgaW4gbG9naWNhbCAoQ1NTKSBwaXhlbHMgcmVsYXRpdmUgdG8gdGhlIHdlYnZpZXcuXG4gICAgICovXG4gICAgSGFuZGxlUGxhdGZvcm1GaWxlRHJvcChmaWxlbmFtZXM6IHN0cmluZ1tdLCB4OiBudW1iZXIsIHk6IG51bWJlcik6IHZvaWQge1xuICAgICAgICAvLyBDaGVjayBpZiBmaWxlIGRyb3BzIGFyZSBlbmFibGVkIGZvciB0aGlzIHdpbmRvd1xuICAgICAgICBpZiAoKHdpbmRvdyBhcyBhbnkpLl93YWlscz8uZmxhZ3M/LmVuYWJsZUZpbGVEcm9wID09PSBmYWxzZSkge1xuICAgICAgICAgICAgcmV0dXJuOyAvLyBGaWxlIGRyb3BzIGRpc2FibGVkLCBpZ25vcmUgdGhlIGRyb3BcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgY29uc3QgZWxlbWVudCA9IGRvY3VtZW50LmVsZW1lbnRGcm9tUG9pbnQoeCwgeSk7XG4gICAgICAgIGNvbnN0IGRyb3BUYXJnZXQgPSBnZXREcm9wVGFyZ2V0RWxlbWVudChlbGVtZW50KTtcblxuICAgICAgICBpZiAoIWRyb3BUYXJnZXQpIHtcbiAgICAgICAgICAgIC8vIERyb3Agd2FzIG5vdCBvbiBhIGRlc2lnbmF0ZWQgZHJvcCB0YXJnZXQgLSBpZ25vcmVcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGVsZW1lbnREZXRhaWxzID0ge1xuICAgICAgICAgICAgaWQ6IGRyb3BUYXJnZXQuaWQsXG4gICAgICAgICAgICBjbGFzc0xpc3Q6IEFycmF5LmZyb20oZHJvcFRhcmdldC5jbGFzc0xpc3QpLFxuICAgICAgICAgICAgYXR0cmlidXRlczoge30gYXMgeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSxcbiAgICAgICAgfTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkcm9wVGFyZ2V0LmF0dHJpYnV0ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IGF0dHIgPSBkcm9wVGFyZ2V0LmF0dHJpYnV0ZXNbaV07XG4gICAgICAgICAgICBlbGVtZW50RGV0YWlscy5hdHRyaWJ1dGVzW2F0dHIubmFtZV0gPSBhdHRyLnZhbHVlO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcGF5bG9hZCA9IHtcbiAgICAgICAgICAgIGZpbGVuYW1lcyxcbiAgICAgICAgICAgIHgsXG4gICAgICAgICAgICB5LFxuICAgICAgICAgICAgZWxlbWVudERldGFpbHMsXG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpc1tjYWxsZXJTeW1dKEZpbGVzRHJvcHBlZCwgcGF5bG9hZCk7XG4gICAgICAgIFxuICAgICAgICAvLyBDbGVhbiB1cCBuYXRpdmUgZHJhZyBzdGF0ZSBhZnRlciBkcm9wXG4gICAgICAgIGNsZWFudXBOYXRpdmVEcmFnKCk7XG4gICAgfVxuICBcbiAgICAvKipcbiAgICAgKiBNb3ZlcyB0aGUgd2luZG93IHRvIHRoZSBjZW50ZXIgb2YgdGhlIHNwZWNpZmllZCBzY3JlZW4ncyB3b3JrIGFyZWEuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gc2NyZWVuSUQgLSBUaGUgSUQgb2YgdGhlIHRhcmdldCBzY3JlZW4uXG4gICAgICovXG4gICAgU2V0U2NyZWVuKHNjcmVlbklEOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShTZXRTY3JlZW5NZXRob2QsIHsgc2NyZWVuSUQgfSk7XG4gICAgfVxuXG4gICAgLyogVHJpZ2dlcnMgV2luZG93cyAxMSBTbmFwIEFzc2lzdCBmZWF0dXJlIChXaW5kb3dzIG9ubHkpLlxuICAgICAqIFRoaXMgaXMgZXF1aXZhbGVudCB0byBwcmVzc2luZyBXaW4rWiBhbmQgc2hvd3Mgc25hcCBsYXlvdXQgb3B0aW9ucy5cbiAgICAgKi9cbiAgICBTbmFwQXNzaXN0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFNuYXBBc3Npc3RNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE9wZW5zIHRoZSBwcmludCBkaWFsb2cgZm9yIHRoZSB3aW5kb3cuXG4gICAgICovXG4gICAgUHJpbnQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oUHJpbnRNZXRob2QpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBUaGUgd2luZG93IHdpdGhpbiB3aGljaCB0aGUgc2NyaXB0IGlzIHJ1bm5pbmcuXG4gKi9cbmNvbnN0IHRoaXNXaW5kb3cgPSBuZXcgV2luZG93KCcnKTtcblxuLyoqXG4gKiBTZXRzIHVwIGdsb2JhbCBkcmFnIGFuZCBkcm9wIGV2ZW50IGxpc3RlbmVycyBmb3IgZmlsZSBkcm9wcy5cbiAqIEhhbmRsZXMgdmlzdWFsIGZlZWRiYWNrIChob3ZlciBzdGF0ZSkgYW5kIGZpbGUgZHJvcCBwcm9jZXNzaW5nLlxuICovXG5mdW5jdGlvbiBzZXR1cERyb3BUYXJnZXRMaXN0ZW5lcnMoKSB7XG4gICAgY29uc3QgZG9jRWxlbWVudCA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudDtcbiAgICBsZXQgZHJhZ0VudGVyQ291bnRlciA9IDA7XG5cbiAgICBkb2NFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2RyYWdlbnRlcicsIChldmVudCkgPT4ge1xuICAgICAgICBpZiAoIWV2ZW50LmRhdGFUcmFuc2Zlcj8udHlwZXMuaW5jbHVkZXMoJ0ZpbGVzJykpIHtcbiAgICAgICAgICAgIHJldHVybjsgLy8gT25seSBoYW5kbGUgZmlsZSBkcmFncywgbGV0IG90aGVyIGRyYWdzIHBhc3MgdGhyb3VnaFxuICAgICAgICB9XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7IC8vIEFsd2F5cyBwcmV2ZW50IGRlZmF1bHQgdG8gc3RvcCBicm93c2VyIG5hdmlnYXRpb25cbiAgICAgICAgLy8gT24gV2luZG93cywgY2hlY2sgaWYgZmlsZSBkcm9wcyBhcmUgZW5hYmxlZCBmb3IgdGhpcyB3aW5kb3dcbiAgICAgICAgaWYgKCh3aW5kb3cgYXMgYW55KS5fd2FpbHM/LmZsYWdzPy5lbmFibGVGaWxlRHJvcCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIGV2ZW50LmRhdGFUcmFuc2Zlci5kcm9wRWZmZWN0ID0gJ25vbmUnOyAvLyBTaG93IFwibm8gZHJvcFwiIGN1cnNvclxuICAgICAgICAgICAgcmV0dXJuOyAvLyBGaWxlIGRyb3BzIGRpc2FibGVkLCBkb24ndCBzaG93IGhvdmVyIGVmZmVjdHNcbiAgICAgICAgfVxuICAgICAgICBkcmFnRW50ZXJDb3VudGVyKys7XG4gICAgICAgIFxuICAgICAgICBjb25zdCB0YXJnZXRFbGVtZW50ID0gZG9jdW1lbnQuZWxlbWVudEZyb21Qb2ludChldmVudC5jbGllbnRYLCBldmVudC5jbGllbnRZKTtcbiAgICAgICAgY29uc3QgZHJvcFRhcmdldCA9IGdldERyb3BUYXJnZXRFbGVtZW50KHRhcmdldEVsZW1lbnQpO1xuXG4gICAgICAgIC8vIFVwZGF0ZSBob3ZlciBzdGF0ZVxuICAgICAgICBpZiAoY3VycmVudERyb3BUYXJnZXQgJiYgY3VycmVudERyb3BUYXJnZXQgIT09IGRyb3BUYXJnZXQpIHtcbiAgICAgICAgICAgIGN1cnJlbnREcm9wVGFyZ2V0LmNsYXNzTGlzdC5yZW1vdmUoRFJPUF9UQVJHRVRfQUNUSVZFX0NMQVNTKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChkcm9wVGFyZ2V0KSB7XG4gICAgICAgICAgICBkcm9wVGFyZ2V0LmNsYXNzTGlzdC5hZGQoRFJPUF9UQVJHRVRfQUNUSVZFX0NMQVNTKTtcbiAgICAgICAgICAgIGV2ZW50LmRhdGFUcmFuc2Zlci5kcm9wRWZmZWN0ID0gJ2NvcHknO1xuICAgICAgICAgICAgY3VycmVudERyb3BUYXJnZXQgPSBkcm9wVGFyZ2V0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZXZlbnQuZGF0YVRyYW5zZmVyLmRyb3BFZmZlY3QgPSAnbm9uZSc7XG4gICAgICAgICAgICBjdXJyZW50RHJvcFRhcmdldCA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9LCBmYWxzZSk7XG5cbiAgICBkb2NFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2RyYWdvdmVyJywgKGV2ZW50KSA9PiB7XG4gICAgICAgIGlmICghZXZlbnQuZGF0YVRyYW5zZmVyPy50eXBlcy5pbmNsdWRlcygnRmlsZXMnKSkge1xuICAgICAgICAgICAgcmV0dXJuOyAvLyBPbmx5IGhhbmRsZSBmaWxlIGRyYWdzXG4gICAgICAgIH1cbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTsgLy8gQWx3YXlzIHByZXZlbnQgZGVmYXVsdCB0byBzdG9wIGJyb3dzZXIgbmF2aWdhdGlvblxuICAgICAgICAvLyBPbiBXaW5kb3dzLCBjaGVjayBpZiBmaWxlIGRyb3BzIGFyZSBlbmFibGVkIGZvciB0aGlzIHdpbmRvd1xuICAgICAgICBpZiAoKHdpbmRvdyBhcyBhbnkpLl93YWlscz8uZmxhZ3M/LmVuYWJsZUZpbGVEcm9wID09PSBmYWxzZSkge1xuICAgICAgICAgICAgZXZlbnQuZGF0YVRyYW5zZmVyLmRyb3BFZmZlY3QgPSAnbm9uZSc7IC8vIFNob3cgXCJubyBkcm9wXCIgY3Vyc29yXG4gICAgICAgICAgICByZXR1cm47IC8vIEZpbGUgZHJvcHMgZGlzYWJsZWQsIGRvbid0IHNob3cgaG92ZXIgZWZmZWN0c1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICAvLyBVcGRhdGUgZHJvcCB0YXJnZXQgYXMgY3Vyc29yIG1vdmVzXG4gICAgICAgIGNvbnN0IHRhcmdldEVsZW1lbnQgPSBkb2N1bWVudC5lbGVtZW50RnJvbVBvaW50KGV2ZW50LmNsaWVudFgsIGV2ZW50LmNsaWVudFkpO1xuICAgICAgICBjb25zdCBkcm9wVGFyZ2V0ID0gZ2V0RHJvcFRhcmdldEVsZW1lbnQodGFyZ2V0RWxlbWVudCk7XG4gICAgICAgIFxuICAgICAgICBpZiAoY3VycmVudERyb3BUYXJnZXQgJiYgY3VycmVudERyb3BUYXJnZXQgIT09IGRyb3BUYXJnZXQpIHtcbiAgICAgICAgICAgIGN1cnJlbnREcm9wVGFyZ2V0LmNsYXNzTGlzdC5yZW1vdmUoRFJPUF9UQVJHRVRfQUNUSVZFX0NMQVNTKTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgaWYgKGRyb3BUYXJnZXQpIHtcbiAgICAgICAgICAgIGlmICghZHJvcFRhcmdldC5jbGFzc0xpc3QuY29udGFpbnMoRFJPUF9UQVJHRVRfQUNUSVZFX0NMQVNTKSkge1xuICAgICAgICAgICAgICAgIGRyb3BUYXJnZXQuY2xhc3NMaXN0LmFkZChEUk9QX1RBUkdFVF9BQ1RJVkVfQ0xBU1MpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZXZlbnQuZGF0YVRyYW5zZmVyLmRyb3BFZmZlY3QgPSAnY29weSc7XG4gICAgICAgICAgICBjdXJyZW50RHJvcFRhcmdldCA9IGRyb3BUYXJnZXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBldmVudC5kYXRhVHJhbnNmZXIuZHJvcEVmZmVjdCA9ICdub25lJztcbiAgICAgICAgICAgIGN1cnJlbnREcm9wVGFyZ2V0ID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH0sIGZhbHNlKTtcblxuICAgIGRvY0VsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignZHJhZ2xlYXZlJywgKGV2ZW50KSA9PiB7XG4gICAgICAgIGlmICghZXZlbnQuZGF0YVRyYW5zZmVyPy50eXBlcy5pbmNsdWRlcygnRmlsZXMnKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7IC8vIEFsd2F5cyBwcmV2ZW50IGRlZmF1bHQgdG8gc3RvcCBicm93c2VyIG5hdmlnYXRpb25cbiAgICAgICAgLy8gT24gV2luZG93cywgY2hlY2sgaWYgZmlsZSBkcm9wcyBhcmUgZW5hYmxlZCBmb3IgdGhpcyB3aW5kb3dcbiAgICAgICAgaWYgKCh3aW5kb3cgYXMgYW55KS5fd2FpbHM/LmZsYWdzPy5lbmFibGVGaWxlRHJvcCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgLy8gT24gTGludXgvV2ViS2l0R1RLIGFuZCBtYWNPUywgZHJhZ2xlYXZlIGZpcmVzIGltbWVkaWF0ZWx5IHdpdGggcmVsYXRlZFRhcmdldD1udWxsIHdoZW4gbmF0aXZlXG4gICAgICAgIC8vIGRyYWcgaGFuZGxpbmcgaXMgaW52b2x2ZWQuIElnbm9yZSB0aGVzZSBzcHVyaW91cyBldmVudHMgLSB3ZSdsbCBjbGVhbiB1cCBvbiBkcm9wIGluc3RlYWQuXG4gICAgICAgIGlmIChldmVudC5yZWxhdGVkVGFyZ2V0ID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIGRyYWdFbnRlckNvdW50ZXItLTtcbiAgICAgICAgXG4gICAgICAgIGlmIChkcmFnRW50ZXJDb3VudGVyID09PSAwIHx8IFxuICAgICAgICAgICAgKGN1cnJlbnREcm9wVGFyZ2V0ICYmICFjdXJyZW50RHJvcFRhcmdldC5jb250YWlucyhldmVudC5yZWxhdGVkVGFyZ2V0IGFzIE5vZGUpKSkge1xuICAgICAgICAgICAgaWYgKGN1cnJlbnREcm9wVGFyZ2V0KSB7XG4gICAgICAgICAgICAgICAgY3VycmVudERyb3BUYXJnZXQuY2xhc3NMaXN0LnJlbW92ZShEUk9QX1RBUkdFVF9BQ1RJVkVfQ0xBU1MpO1xuICAgICAgICAgICAgICAgIGN1cnJlbnREcm9wVGFyZ2V0ID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRyYWdFbnRlckNvdW50ZXIgPSAwO1xuICAgICAgICB9XG4gICAgfSwgZmFsc2UpO1xuXG4gICAgZG9jRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdkcm9wJywgKGV2ZW50KSA9PiB7XG4gICAgICAgIGlmICghZXZlbnQuZGF0YVRyYW5zZmVyPy50eXBlcy5pbmNsdWRlcygnRmlsZXMnKSkge1xuICAgICAgICAgICAgcmV0dXJuOyAvLyBPbmx5IGhhbmRsZSBmaWxlIGRyb3BzXG4gICAgICAgIH1cbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTsgLy8gQWx3YXlzIHByZXZlbnQgZGVmYXVsdCB0byBzdG9wIGJyb3dzZXIgbmF2aWdhdGlvblxuICAgICAgICAvLyBPbiBXaW5kb3dzLCBjaGVjayBpZiBmaWxlIGRyb3BzIGFyZSBlbmFibGVkIGZvciB0aGlzIHdpbmRvd1xuICAgICAgICBpZiAoKHdpbmRvdyBhcyBhbnkpLl93YWlscz8uZmxhZ3M/LmVuYWJsZUZpbGVEcm9wID09PSBmYWxzZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGRyYWdFbnRlckNvdW50ZXIgPSAwO1xuICAgICAgICBcbiAgICAgICAgaWYgKGN1cnJlbnREcm9wVGFyZ2V0KSB7XG4gICAgICAgICAgICBjdXJyZW50RHJvcFRhcmdldC5jbGFzc0xpc3QucmVtb3ZlKERST1BfVEFSR0VUX0FDVElWRV9DTEFTUyk7XG4gICAgICAgICAgICBjdXJyZW50RHJvcFRhcmdldCA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBPbiBXaW5kb3dzLCBoYW5kbGUgZmlsZSBkcm9wcyB2aWEgSmF2YVNjcmlwdFxuICAgICAgICAvLyBPbiBtYWNPUy9MaW51eCwgbmF0aXZlIGNvZGUgd2lsbCBjYWxsIEhhbmRsZVBsYXRmb3JtRmlsZURyb3BcbiAgICAgICAgaWYgKGNhblJlc29sdmVGaWxlUGF0aHMoKSkge1xuICAgICAgICAgICAgY29uc3QgZmlsZXM6IEZpbGVbXSA9IFtdO1xuICAgICAgICAgICAgaWYgKGV2ZW50LmRhdGFUcmFuc2Zlci5pdGVtcykge1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgaXRlbSBvZiBldmVudC5kYXRhVHJhbnNmZXIuaXRlbXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGl0ZW0ua2luZCA9PT0gJ2ZpbGUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmaWxlID0gaXRlbS5nZXRBc0ZpbGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmaWxlKSBmaWxlcy5wdXNoKGZpbGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChldmVudC5kYXRhVHJhbnNmZXIuZmlsZXMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGZpbGUgb2YgZXZlbnQuZGF0YVRyYW5zZmVyLmZpbGVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGZpbGVzLnB1c2goZmlsZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgXG4gICAgICAgICAgICBpZiAoZmlsZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIHJlc29sdmVGaWxlUGF0aHMoZXZlbnQuY2xpZW50WCwgZXZlbnQuY2xpZW50WSwgZmlsZXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSwgZmFsc2UpO1xufVxuXG4vLyBJbml0aWFsaXplIGxpc3RlbmVycyB3aGVuIHRoZSBzY3JpcHQgbG9hZHNcbmlmICh0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiICYmIHR5cGVvZiBkb2N1bWVudCAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgIHNldHVwRHJvcFRhcmdldExpc3RlbmVycygpO1xufVxuXG5leHBvcnQgZGVmYXVsdCB0aGlzV2luZG93O1xuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG5pbXBvcnQgKiBhcyBSdW50aW1lIGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyY1wiO1xuXG4vLyBOT1RFOiB0aGUgZm9sbG93aW5nIG1ldGhvZHMgTVVTVCBiZSBpbXBvcnRlZCBleHBsaWNpdGx5IGJlY2F1c2Ugb2YgaG93IGVzYnVpbGQgaW5qZWN0aW9uIHdvcmtzXG5pbXBvcnQgeyBFbmFibGUgYXMgRW5hYmxlV01MIH0gZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3dtbFwiO1xuaW1wb3J0IHsgZGVidWdMb2cgfSBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvdXRpbHNcIjtcblxud2luZG93LndhaWxzID0gUnVudGltZTtcbkVuYWJsZVdNTCgpO1xuXG5pZiAoREVCVUcpIHtcbiAgICBkZWJ1Z0xvZyhcIldhaWxzIFJ1bnRpbWUgTG9hZGVkXCIpXG59XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbmltcG9ydCB7IG5ld1J1bnRpbWVDYWxsZXIsIG9iamVjdE5hbWVzIH0gZnJvbSBcIi4vcnVudGltZS5qc1wiO1xuXG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcihvYmplY3ROYW1lcy5TeXN0ZW0pO1xuXG5jb25zdCBTeXN0ZW1Jc0RhcmtNb2RlID0gMDtcbmNvbnN0IFN5c3RlbUVudmlyb25tZW50ID0gMTtcbmNvbnN0IFN5c3RlbUNhcGFiaWxpdGllcyA9IDI7XG5cbmNvbnN0IF9pbnZva2UgPSAoZnVuY3Rpb24gKCkge1xuICAgIHRyeSB7XG4gICAgICAgIC8vIFdpbmRvd3MgV2ViVmlldzJcbiAgICAgICAgaWYgKCh3aW5kb3cgYXMgYW55KS5jaHJvbWU/LndlYnZpZXc/LnBvc3RNZXNzYWdlKSB7XG4gICAgICAgICAgICByZXR1cm4gKHdpbmRvdyBhcyBhbnkpLmNocm9tZS53ZWJ2aWV3LnBvc3RNZXNzYWdlLmJpbmQoKHdpbmRvdyBhcyBhbnkpLmNocm9tZS53ZWJ2aWV3KTtcbiAgICAgICAgfVxuICAgICAgICAvLyBtYWNPUy9pT1MgV0tXZWJWaWV3XG4gICAgICAgIGVsc2UgaWYgKCh3aW5kb3cgYXMgYW55KS53ZWJraXQ/Lm1lc3NhZ2VIYW5kbGVycz8uWydleHRlcm5hbCddPy5wb3N0TWVzc2FnZSkge1xuICAgICAgICAgICAgcmV0dXJuICh3aW5kb3cgYXMgYW55KS53ZWJraXQubWVzc2FnZUhhbmRsZXJzWydleHRlcm5hbCddLnBvc3RNZXNzYWdlLmJpbmQoKHdpbmRvdyBhcyBhbnkpLndlYmtpdC5tZXNzYWdlSGFuZGxlcnNbJ2V4dGVybmFsJ10pO1xuICAgICAgICB9XG4gICAgICAgIC8vIEFuZHJvaWQgV2ViVmlldyAtIHVzZXMgYWRkSmF2YXNjcmlwdEludGVyZmFjZSB3aGljaCBleHBvc2VzIHdpbmRvdy53YWlscy5pbnZva2VcbiAgICAgICAgZWxzZSBpZiAoKHdpbmRvdyBhcyBhbnkpLndhaWxzPy5pbnZva2UpIHtcbiAgICAgICAgICAgIHJldHVybiAobXNnOiBhbnkpID0+ICh3aW5kb3cgYXMgYW55KS53YWlscy5pbnZva2UodHlwZW9mIG1zZyA9PT0gJ3N0cmluZycgPyBtc2cgOiBKU09OLnN0cmluZ2lmeShtc2cpKTtcbiAgICAgICAgfVxuICAgIH0gY2F0Y2goZSkge31cblxuICAgIGNvbnNvbGUud2FybignXFxuJWNcdTI2QTBcdUZFMEYgQnJvd3NlciBFbnZpcm9ubWVudCBEZXRlY3RlZCAlY1xcblxcbiVjT25seSBVSSBwcmV2aWV3cyBhcmUgYXZhaWxhYmxlIGluIHRoZSBicm93c2VyLiBGb3IgZnVsbCBmdW5jdGlvbmFsaXR5LCBwbGVhc2UgcnVuIHRoZSBhcHBsaWNhdGlvbiBpbiBkZXNrdG9wIG1vZGUuXFxuTW9yZSBpbmZvcm1hdGlvbiBhdDogaHR0cHM6Ly92My53YWlscy5pby9sZWFybi9idWlsZC8jdXNpbmctYS1icm93c2VyLWZvci1kZXZlbG9wbWVudFxcbicsXG4gICAgICAgICdiYWNrZ3JvdW5kOiAjZmZmZmZmOyBjb2xvcjogIzAwMDAwMDsgZm9udC13ZWlnaHQ6IGJvbGQ7IHBhZGRpbmc6IDRweCA4cHg7IGJvcmRlci1yYWRpdXM6IDRweDsgYm9yZGVyOiAycHggc29saWQgIzAwMDAwMDsnLFxuICAgICAgICAnYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7JyxcbiAgICAgICAgJ2NvbG9yOiAjZmZmZmZmOyBmb250LXN0eWxlOiBpdGFsaWM7IGZvbnQtd2VpZ2h0OiBib2xkOycpO1xuICAgIHJldHVybiBudWxsO1xufSkoKTtcblxuZXhwb3J0IGZ1bmN0aW9uIGludm9rZShtc2c6IGFueSk6IHZvaWQge1xuICAgIF9pbnZva2U/Lihtc2cpO1xufVxuXG4vKipcbiAqIFJldHJpZXZlcyB0aGUgc3lzdGVtIGRhcmsgbW9kZSBzdGF0dXMuXG4gKlxuICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYSBib29sZWFuIHZhbHVlIGluZGljYXRpbmcgaWYgdGhlIHN5c3RlbSBpcyBpbiBkYXJrIG1vZGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJc0RhcmtNb2RlKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIHJldHVybiBjYWxsKFN5c3RlbUlzRGFya01vZGUpO1xufVxuXG4vKipcbiAqIEZldGNoZXMgdGhlIGNhcGFiaWxpdGllcyBvZiB0aGUgYXBwbGljYXRpb24gZnJvbSB0aGUgc2VydmVyLlxuICpcbiAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGFuIG9iamVjdCBjb250YWluaW5nIHRoZSBjYXBhYmlsaXRpZXMuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBDYXBhYmlsaXRpZXMoKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+PiB7XG4gICAgcmV0dXJuIGNhbGwoU3lzdGVtQ2FwYWJpbGl0aWVzKTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPU0luZm8ge1xuICAgIC8qKiBUaGUgYnJhbmRpbmcgb2YgdGhlIE9TLiAqL1xuICAgIEJyYW5kaW5nOiBzdHJpbmc7XG4gICAgLyoqIFRoZSBJRCBvZiB0aGUgT1MuICovXG4gICAgSUQ6IHN0cmluZztcbiAgICAvKiogVGhlIG5hbWUgb2YgdGhlIE9TLiAqL1xuICAgIE5hbWU6IHN0cmluZztcbiAgICAvKiogVGhlIHZlcnNpb24gb2YgdGhlIE9TLiAqL1xuICAgIFZlcnNpb246IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFbnZpcm9ubWVudEluZm8ge1xuICAgIC8qKiBUaGUgYXJjaGl0ZWN0dXJlIG9mIHRoZSBzeXN0ZW0uICovXG4gICAgQXJjaDogc3RyaW5nO1xuICAgIC8qKiBUcnVlIGlmIHRoZSBhcHBsaWNhdGlvbiBpcyBydW5uaW5nIGluIGRlYnVnIG1vZGUsIG90aGVyd2lzZSBmYWxzZS4gKi9cbiAgICBEZWJ1ZzogYm9vbGVhbjtcbiAgICAvKiogVGhlIG9wZXJhdGluZyBzeXN0ZW0gaW4gdXNlLiAqL1xuICAgIE9TOiBzdHJpbmc7XG4gICAgLyoqIERldGFpbHMgb2YgdGhlIG9wZXJhdGluZyBzeXN0ZW0uICovXG4gICAgT1NJbmZvOiBPU0luZm87XG4gICAgLyoqIEFkZGl0aW9uYWwgcGxhdGZvcm0gaW5mb3JtYXRpb24uICovXG4gICAgUGxhdGZvcm1JbmZvOiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xufVxuXG4vKipcbiAqIFJldHJpZXZlcyBlbnZpcm9ubWVudCBkZXRhaWxzLlxuICpcbiAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGFuIG9iamVjdCBjb250YWluaW5nIE9TIGFuZCBzeXN0ZW0gYXJjaGl0ZWN0dXJlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gRW52aXJvbm1lbnQoKTogUHJvbWlzZTxFbnZpcm9ubWVudEluZm8+IHtcbiAgICByZXR1cm4gY2FsbChTeXN0ZW1FbnZpcm9ubWVudCk7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IG9wZXJhdGluZyBzeXN0ZW0gaXMgV2luZG93cy5cbiAqXG4gKiBAcmV0dXJuIFRydWUgaWYgdGhlIG9wZXJhdGluZyBzeXN0ZW0gaXMgV2luZG93cywgb3RoZXJ3aXNlIGZhbHNlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gSXNXaW5kb3dzKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAod2luZG93IGFzIGFueSkuX3dhaWxzPy5lbnZpcm9ubWVudD8uT1MgPT09IFwid2luZG93c1wiO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiB0aGUgY3VycmVudCBvcGVyYXRpbmcgc3lzdGVtIGlzIExpbnV4LlxuICpcbiAqIEByZXR1cm5zIFJldHVybnMgdHJ1ZSBpZiB0aGUgY3VycmVudCBvcGVyYXRpbmcgc3lzdGVtIGlzIExpbnV4LCBmYWxzZSBvdGhlcndpc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJc0xpbnV4KCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAod2luZG93IGFzIGFueSkuX3dhaWxzPy5lbnZpcm9ubWVudD8uT1MgPT09IFwibGludXhcIjtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgdGhlIGN1cnJlbnQgZW52aXJvbm1lbnQgaXMgYSBtYWNPUyBvcGVyYXRpbmcgc3lzdGVtLlxuICpcbiAqIEByZXR1cm5zIFRydWUgaWYgdGhlIGVudmlyb25tZW50IGlzIG1hY09TLCBmYWxzZSBvdGhlcndpc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJc01hYygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gKHdpbmRvdyBhcyBhbnkpLl93YWlscz8uZW52aXJvbm1lbnQ/Lk9TID09PSBcImRhcndpblwiO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiB0aGUgY3VycmVudCBvcGVyYXRpbmcgc3lzdGVtIGlzIGlPUy5cbiAqXG4gKiBAcmV0dXJucyBUcnVlIGlmIHRoZSBvcGVyYXRpbmcgc3lzdGVtIGlzIGlPUywgb3RoZXJ3aXNlIGZhbHNlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gSXNJT1MoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICh3aW5kb3cgYXMgYW55KS5fd2FpbHM/LmVudmlyb25tZW50Py5PUyA9PT0gXCJpb3NcIjtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgdGhlIGN1cnJlbnQgb3BlcmF0aW5nIHN5c3RlbSBpcyBBbmRyb2lkLlxuICpcbiAqIEByZXR1cm5zIFRydWUgaWYgdGhlIG9wZXJhdGluZyBzeXN0ZW0gaXMgQW5kcm9pZCwgb3RoZXJ3aXNlIGZhbHNlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gSXNBbmRyb2lkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAod2luZG93IGFzIGFueSkuX3dhaWxzPy5lbnZpcm9ubWVudD8uT1MgPT09IFwiYW5kcm9pZFwiO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiB0aGUgYXBwIGlzIHJ1bm5pbmcgb24gYSBtb2JpbGUgT1MgKGlPUyBvciBBbmRyb2lkKS5cbiAqXG4gKiBAcmV0dXJucyBUcnVlIG9uIGlPUyBvciBBbmRyb2lkLCBvdGhlcndpc2UgZmFsc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJc01vYmlsZSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gSXNJT1MoKSB8fCBJc0FuZHJvaWQoKTtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgdGhlIGFwcCBpcyBydW5uaW5nIG9uIGEgZGVza3RvcCBPUyAobWFjT1MsIFdpbmRvd3Mgb3IgTGludXgpLlxuICpcbiAqIEByZXR1cm5zIFRydWUgb24gbWFjT1MsIFdpbmRvd3Mgb3IgTGludXgsIG90aGVyd2lzZSBmYWxzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzRGVza3RvcCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gSXNNYWMoKSB8fCBJc1dpbmRvd3MoKSB8fCBJc0xpbnV4KCk7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IGVudmlyb25tZW50IGFyY2hpdGVjdHVyZSBpcyBBTUQ2NC5cbiAqXG4gKiBAcmV0dXJucyBUcnVlIGlmIHRoZSBjdXJyZW50IGVudmlyb25tZW50IGFyY2hpdGVjdHVyZSBpcyBBTUQ2NCwgZmFsc2Ugb3RoZXJ3aXNlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gSXNBTUQ2NCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gKHdpbmRvdyBhcyBhbnkpLl93YWlscz8uZW52aXJvbm1lbnQ/LkFyY2ggPT09IFwiYW1kNjRcIjtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgdGhlIGN1cnJlbnQgYXJjaGl0ZWN0dXJlIGlzIEFSTS5cbiAqXG4gKiBAcmV0dXJucyBUcnVlIGlmIHRoZSBjdXJyZW50IGFyY2hpdGVjdHVyZSBpcyBBUk0sIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzQVJNKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAod2luZG93IGFzIGFueSkuX3dhaWxzPy5lbnZpcm9ubWVudD8uQXJjaCA9PT0gXCJhcm1cIjtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgdGhlIGN1cnJlbnQgZW52aXJvbm1lbnQgaXMgQVJNNjQgYXJjaGl0ZWN0dXJlLlxuICpcbiAqIEByZXR1cm5zIFJldHVybnMgdHJ1ZSBpZiB0aGUgZW52aXJvbm1lbnQgaXMgQVJNNjQgYXJjaGl0ZWN0dXJlLCBvdGhlcndpc2UgcmV0dXJucyBmYWxzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzQVJNNjQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICh3aW5kb3cgYXMgYW55KS5fd2FpbHM/LmVudmlyb25tZW50Py5BcmNoID09PSBcImFybTY0XCI7XG59XG5cbi8qKlxuICogUmVwb3J0cyB3aGV0aGVyIHRoZSBhcHAgaXMgYmVpbmcgcnVuIGluIGRlYnVnIG1vZGUuXG4gKlxuICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgYXBwIGlzIGJlaW5nIHJ1biBpbiBkZWJ1ZyBtb2RlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gSXNEZWJ1ZygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gQm9vbGVhbigod2luZG93IGFzIGFueSkuX3dhaWxzPy5lbnZpcm9ubWVudD8uRGVidWcpO1xufVxuXG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbmltcG9ydCB7IG5ld1J1bnRpbWVDYWxsZXIsIG9iamVjdE5hbWVzIH0gZnJvbSBcIi4vcnVudGltZS5qc1wiO1xuaW1wb3J0IHsgSXNEZWJ1ZyB9IGZyb20gXCIuL3N5c3RlbS5qc1wiO1xuaW1wb3J0IHsgZXZlbnRUYXJnZXQgfSBmcm9tIFwiLi91dGlscy5qc1wiO1xuXG4vLyBzZXR1cFxuaW1wb3J0IHsgaGFzRE9NIH0gZnJvbSBcIi4vZW52aXJvbm1lbnQuanNcIjtcblxuaWYgKGhhc0RPTSkge1xuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdjb250ZXh0bWVudScsIGNvbnRleHRNZW51SGFuZGxlcik7XG59XG5cbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyKG9iamVjdE5hbWVzLkNvbnRleHRNZW51KTtcblxuY29uc3QgQ29udGV4dE1lbnVPcGVuID0gMDtcblxuZnVuY3Rpb24gb3BlbkNvbnRleHRNZW51KGlkOiBzdHJpbmcsIHg6IG51bWJlciwgeTogbnVtYmVyLCBkYXRhOiBhbnkpOiB2b2lkIHtcbiAgICB2b2lkIGNhbGwoQ29udGV4dE1lbnVPcGVuLCB7aWQsIHgsIHksIGRhdGF9KTtcbn1cblxuZnVuY3Rpb24gY29udGV4dE1lbnVIYW5kbGVyKGV2ZW50OiBNb3VzZUV2ZW50KSB7XG4gICAgY29uc3QgdGFyZ2V0ID0gZXZlbnRUYXJnZXQoZXZlbnQpO1xuXG4gICAgLy8gQ2hlY2sgZm9yIGN1c3RvbSBjb250ZXh0IG1lbnVcbiAgICBjb25zdCBjdXN0b21Db250ZXh0TWVudSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKHRhcmdldCkuZ2V0UHJvcGVydHlWYWx1ZShcIi0tY3VzdG9tLWNvbnRleHRtZW51XCIpLnRyaW0oKTtcblxuICAgIGlmIChjdXN0b21Db250ZXh0TWVudSkge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBjb25zdCBkYXRhID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUodGFyZ2V0KS5nZXRQcm9wZXJ0eVZhbHVlKFwiLS1jdXN0b20tY29udGV4dG1lbnUtZGF0YVwiKTtcbiAgICAgICAgb3BlbkNvbnRleHRNZW51KGN1c3RvbUNvbnRleHRNZW51LCBldmVudC5jbGllbnRYLCBldmVudC5jbGllbnRZLCBkYXRhKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBwcm9jZXNzRGVmYXVsdENvbnRleHRNZW51KGV2ZW50LCB0YXJnZXQpO1xuICAgIH1cbn1cblxuXG4vKlxuLS1kZWZhdWx0LWNvbnRleHRtZW51OiBhdXRvOyAoZGVmYXVsdCkgd2lsbCBzaG93IHRoZSBkZWZhdWx0IGNvbnRleHQgbWVudSBpZiBjb250ZW50RWRpdGFibGUgaXMgdHJ1ZSBPUiB0ZXh0IGhhcyBiZWVuIHNlbGVjdGVkIE9SIGVsZW1lbnQgaXMgaW5wdXQgb3IgdGV4dGFyZWFcbi0tZGVmYXVsdC1jb250ZXh0bWVudTogc2hvdzsgd2lsbCBhbHdheXMgc2hvdyB0aGUgZGVmYXVsdCBjb250ZXh0IG1lbnVcbi0tZGVmYXVsdC1jb250ZXh0bWVudTogaGlkZTsgd2lsbCBhbHdheXMgaGlkZSB0aGUgZGVmYXVsdCBjb250ZXh0IG1lbnVcblxuVGhpcyBydWxlIGlzIGluaGVyaXRlZCBsaWtlIG5vcm1hbCBDU1MgcnVsZXMsIHNvIG5lc3Rpbmcgd29ya3MgYXMgZXhwZWN0ZWRcbiovXG5mdW5jdGlvbiBwcm9jZXNzRGVmYXVsdENvbnRleHRNZW51KGV2ZW50OiBNb3VzZUV2ZW50LCB0YXJnZXQ6IEhUTUxFbGVtZW50KSB7XG4gICAgLy8gRGVidWcgYnVpbGRzIGFsd2F5cyBzaG93IHRoZSBtZW51XG4gICAgaWYgKElzRGVidWcoKSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gUHJvY2VzcyBkZWZhdWx0IGNvbnRleHQgbWVudVxuICAgIHN3aXRjaCAod2luZG93LmdldENvbXB1dGVkU3R5bGUodGFyZ2V0KS5nZXRQcm9wZXJ0eVZhbHVlKFwiLS1kZWZhdWx0LWNvbnRleHRtZW51XCIpLnRyaW0oKSkge1xuICAgICAgICBjYXNlICdzaG93JzpcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgY2FzZSAnaGlkZSc6XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIENoZWNrIGlmIGNvbnRlbnRFZGl0YWJsZSBpcyB0cnVlXG4gICAgaWYgKHRhcmdldC5pc0NvbnRlbnRFZGl0YWJsZSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgaWYgdGV4dCBoYXMgYmVlbiBzZWxlY3RlZFxuICAgIGNvbnN0IHNlbGVjdGlvbiA9IHdpbmRvdy5nZXRTZWxlY3Rpb24oKTtcbiAgICBjb25zdCBoYXNTZWxlY3Rpb24gPSBzZWxlY3Rpb24gJiYgc2VsZWN0aW9uLnRvU3RyaW5nKCkubGVuZ3RoID4gMDtcbiAgICBpZiAoaGFzU2VsZWN0aW9uKSB7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2VsZWN0aW9uLnJhbmdlQ291bnQ7IGkrKykge1xuICAgICAgICAgICAgY29uc3QgcmFuZ2UgPSBzZWxlY3Rpb24uZ2V0UmFuZ2VBdChpKTtcbiAgICAgICAgICAgIGNvbnN0IHJlY3RzID0gcmFuZ2UuZ2V0Q2xpZW50UmVjdHMoKTtcbiAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgcmVjdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCByZWN0ID0gcmVjdHNbal07XG4gICAgICAgICAgICAgICAgaWYgKGRvY3VtZW50LmVsZW1lbnRGcm9tUG9pbnQocmVjdC5sZWZ0LCByZWN0LnRvcCkgPT09IHRhcmdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgaWYgdGFnIGlzIGlucHV0IG9yIHRleHRhcmVhLlxuICAgIGlmICh0YXJnZXQgaW5zdGFuY2VvZiBIVE1MSW5wdXRFbGVtZW50IHx8IHRhcmdldCBpbnN0YW5jZW9mIEhUTUxUZXh0QXJlYUVsZW1lbnQpIHtcbiAgICAgICAgaWYgKGhhc1NlbGVjdGlvbiB8fCAoIXRhcmdldC5yZWFkT25seSAmJiAhdGFyZ2V0LmRpc2FibGVkKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gaGlkZSBkZWZhdWx0IGNvbnRleHQgbWVudVxuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG59XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbi8qKlxuICogUmV0cmlldmVzIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIHNwZWNpZmllZCBrZXkgZnJvbSB0aGUgZmxhZyBtYXAuXG4gKlxuICogQHBhcmFtIGtleSAtIFRoZSBrZXkgdG8gcmV0cmlldmUgdGhlIHZhbHVlIGZvci5cbiAqIEByZXR1cm4gVGhlIHZhbHVlIGFzc29jaWF0ZWQgd2l0aCB0aGUgc3BlY2lmaWVkIGtleS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEdldEZsYWcoa2V5OiBzdHJpbmcpOiBhbnkge1xuICAgIHRyeSB7XG4gICAgICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmZsYWdzW2tleV07XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmFibGUgdG8gcmV0cmlldmUgZmxhZyAnXCIgKyBrZXkgKyBcIic6IFwiICsgZSwgeyBjYXVzZTogZSB9KTtcbiAgICB9XG59XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbmltcG9ydCB7IGludm9rZSwgSXNXaW5kb3dzLCBJc0xpbnV4IH0gZnJvbSBcIi4vc3lzdGVtLmpzXCI7XG5pbXBvcnQgeyBHZXRGbGFnIH0gZnJvbSBcIi4vZmxhZ3MuanNcIjtcbmltcG9ydCB7IGNhblRyYWNrQnV0dG9ucywgZXZlbnRUYXJnZXQgfSBmcm9tIFwiLi91dGlscy5qc1wiO1xuXG4vLyBTZXR1cFxubGV0IGNhbkRyYWcgPSBmYWxzZTtcbmxldCBkcmFnZ2luZyA9IGZhbHNlO1xuXG5sZXQgcmVzaXphYmxlID0gZmFsc2U7XG5sZXQgY2FuUmVzaXplID0gZmFsc2U7XG5sZXQgcmVzaXppbmcgPSBmYWxzZTtcbmxldCByZXNpemVFZGdlOiBzdHJpbmcgPSBcIlwiO1xubGV0IGRlZmF1bHRDdXJzb3IgPSBcImF1dG9cIjtcblxubGV0IGJ1dHRvbnMgPSAwO1xuaW1wb3J0IHsgaGFzRE9NIH0gZnJvbSBcIi4vZW52aXJvbm1lbnQuanNcIjtcblxubGV0IGJ1dHRvbnNUcmFja2VkID0gZmFsc2U7XG5cbmlmIChoYXNET00pIHtcbiAgICBidXR0b25zVHJhY2tlZCA9IGNhblRyYWNrQnV0dG9ucygpO1xuICAgIHdpbmRvdy5fd2FpbHMgPSB3aW5kb3cuX3dhaWxzIHx8IHt9O1xuICAgIHdpbmRvdy5fd2FpbHMuc2V0UmVzaXphYmxlID0gKHZhbHVlOiBib29sZWFuKTogdm9pZCA9PiB7XG4gICAgICAgIHJlc2l6YWJsZSA9IHZhbHVlO1xuICAgICAgICBpZiAoIXJlc2l6YWJsZSkge1xuICAgICAgICAgICAgLy8gU3RvcCByZXNpemluZyBpZiBpbiBwcm9ncmVzcy5cbiAgICAgICAgICAgIGNhblJlc2l6ZSA9IHJlc2l6aW5nID0gZmFsc2U7XG4gICAgICAgICAgICBzZXRSZXNpemUoKTtcbiAgICAgICAgfVxuICAgIH07XG59XG5cbi8vIERlZmVyIGF0dGFjaGluZyBtb3VzZSBsaXN0ZW5lcnMgdW50aWwgd2Uga25vdyB3ZSdyZSBub3Qgb24gbW9iaWxlLlxubGV0IGRyYWdJbml0RG9uZSA9IGZhbHNlO1xuZnVuY3Rpb24gaXNNb2JpbGUoKTogYm9vbGVhbiB7XG4gICAgY29uc3Qgb3MgPSAod2luZG93IGFzIGFueSkuX3dhaWxzPy5lbnZpcm9ubWVudD8uT1M7XG4gICAgaWYgKG9zID09PSBcImlvc1wiIHx8IG9zID09PSBcImFuZHJvaWRcIikgcmV0dXJuIHRydWU7XG4gICAgLy8gRmFsbGJhY2sgaGV1cmlzdGljIGlmIGVudmlyb25tZW50IG5vdCB5ZXQgc2V0XG4gICAgY29uc3QgdWEgPSBuYXZpZ2F0b3IudXNlckFnZW50IHx8IG5hdmlnYXRvci52ZW5kb3IgfHwgKHdpbmRvdyBhcyBhbnkpLm9wZXJhIHx8IFwiXCI7XG4gICAgcmV0dXJuIC9hbmRyb2lkfGlwaG9uZXxpcGFkfGlwb2R8aWVtb2JpbGV8d3BkZXNrdG9wL2kudGVzdCh1YSk7XG59XG5mdW5jdGlvbiB0cnlJbml0RHJhZ0hhbmRsZXJzKCk6IHZvaWQge1xuICAgIGlmIChkcmFnSW5pdERvbmUpIHJldHVybjtcbiAgICBpZiAoaXNNb2JpbGUoKSkgcmV0dXJuO1xuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCB1cGRhdGUsIHsgY2FwdHVyZTogdHJ1ZSB9KTtcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgdXBkYXRlLCB7IGNhcHR1cmU6IHRydWUgfSk7XG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB1cGRhdGUsIHsgY2FwdHVyZTogdHJ1ZSB9KTtcbiAgICBmb3IgKGNvbnN0IGV2IG9mIFsnY2xpY2snLCAnY29udGV4dG1lbnUnLCAnZGJsY2xpY2snXSkge1xuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihldiwgc3VwcHJlc3NFdmVudCwgeyBjYXB0dXJlOiB0cnVlIH0pO1xuICAgIH1cbiAgICBkcmFnSW5pdERvbmUgPSB0cnVlO1xufVxuaWYgKGhhc0RPTSkge1xuICAgIC8vIEF0dGVtcHQgaW1tZWRpYXRlIGluaXQgKGluIGNhc2UgZW52aXJvbm1lbnQgYWxyZWFkeSBwcmVzZW50KVxuICAgIHRyeUluaXREcmFnSGFuZGxlcnMoKTtcbiAgICAvLyBBbHNvIGF0dGVtcHQgb24gRE9NIHJlYWR5XG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsIHRyeUluaXREcmFnSGFuZGxlcnMsIHsgb25jZTogdHJ1ZSB9KTtcbiAgICAvLyBBcyBhIGxhc3QgcmVzb3J0LCBwb2xsIGZvciBlbnZpcm9ubWVudCBmb3IgYSBzaG9ydCBwZXJpb2RcbiAgICBsZXQgZHJhZ0VudlBvbGxzID0gMDtcbiAgICBjb25zdCBkcmFnRW52UG9sbCA9IHdpbmRvdy5zZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICAgIGlmIChkcmFnSW5pdERvbmUpIHsgd2luZG93LmNsZWFySW50ZXJ2YWwoZHJhZ0VudlBvbGwpOyByZXR1cm47IH1cbiAgICAgICAgdHJ5SW5pdERyYWdIYW5kbGVycygpO1xuICAgICAgICBpZiAoKytkcmFnRW52UG9sbHMgPiAxMDApIHsgd2luZG93LmNsZWFySW50ZXJ2YWwoZHJhZ0VudlBvbGwpOyB9XG4gICAgfSwgNTApO1xufVxuXG5mdW5jdGlvbiBzdXBwcmVzc0V2ZW50KGV2ZW50OiBFdmVudCkge1xuICAgIC8vIFN1cHByZXNzIGNsaWNrIGV2ZW50cyB3aGlsZSByZXNpemluZyBvciBkcmFnZ2luZy5cbiAgICBpZiAoZHJhZ2dpbmcgfHwgcmVzaXppbmcpIHtcbiAgICAgICAgZXZlbnQuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG4gICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cbn1cblxuLy8gVXNlIGNvbnN0YW50cyB0byBhdm9pZCBjb21wYXJpbmcgc3RyaW5ncyBtdWx0aXBsZSB0aW1lcy5cbmNvbnN0IE1vdXNlRG93biA9IDA7XG5jb25zdCBNb3VzZVVwICAgPSAxO1xuY29uc3QgTW91c2VNb3ZlID0gMjtcblxuZnVuY3Rpb24gdXBkYXRlKGV2ZW50OiBNb3VzZUV2ZW50KSB7XG4gICAgLy8gV2luZG93cyBzdXBwcmVzc2VzIG1vdXNlIGV2ZW50cyBhdCB0aGUgZW5kIG9mIGRyYWdnaW5nIG9yIHJlc2l6aW5nLFxuICAgIC8vIHNvIHdlIG5lZWQgdG8gYmUgc21hcnQgYW5kIHN5bnRoZXNpemUgYnV0dG9uIGV2ZW50cy5cblxuICAgIGxldCBldmVudFR5cGU6IG51bWJlciwgZXZlbnRCdXR0b25zID0gZXZlbnQuYnV0dG9ucztcbiAgICBzd2l0Y2ggKGV2ZW50LnR5cGUpIHtcbiAgICAgICAgY2FzZSAnbW91c2Vkb3duJzpcbiAgICAgICAgICAgIGV2ZW50VHlwZSA9IE1vdXNlRG93bjtcbiAgICAgICAgICAgIGlmICghYnV0dG9uc1RyYWNrZWQpIHsgZXZlbnRCdXR0b25zID0gYnV0dG9ucyB8ICgxIDw8IGV2ZW50LmJ1dHRvbik7IH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdtb3VzZXVwJzpcbiAgICAgICAgICAgIGV2ZW50VHlwZSA9IE1vdXNlVXA7XG4gICAgICAgICAgICBpZiAoIWJ1dHRvbnNUcmFja2VkKSB7IGV2ZW50QnV0dG9ucyA9IGJ1dHRvbnMgJiB+KDEgPDwgZXZlbnQuYnV0dG9uKTsgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBldmVudFR5cGUgPSBNb3VzZU1vdmU7XG4gICAgICAgICAgICBpZiAoIWJ1dHRvbnNUcmFja2VkKSB7IGV2ZW50QnV0dG9ucyA9IGJ1dHRvbnM7IH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIGxldCByZWxlYXNlZCA9IGJ1dHRvbnMgJiB+ZXZlbnRCdXR0b25zO1xuICAgIGxldCBwcmVzc2VkID0gZXZlbnRCdXR0b25zICYgfmJ1dHRvbnM7XG5cbiAgICBidXR0b25zID0gZXZlbnRCdXR0b25zO1xuXG4gICAgLy8gU3ludGhlc2l6ZSBhIHJlbGVhc2UtcHJlc3Mgc2VxdWVuY2UgaWYgd2UgZGV0ZWN0IGEgcHJlc3Mgb2YgYW4gYWxyZWFkeSBwcmVzc2VkIGJ1dHRvbi5cbiAgICBpZiAoZXZlbnRUeXBlID09PSBNb3VzZURvd24gJiYgIShwcmVzc2VkICYgZXZlbnQuYnV0dG9uKSkge1xuICAgICAgICByZWxlYXNlZCB8PSAoMSA8PCBldmVudC5idXR0b24pO1xuICAgICAgICBwcmVzc2VkIHw9ICgxIDw8IGV2ZW50LmJ1dHRvbik7XG4gICAgfVxuXG4gICAgLy8gU3VwcHJlc3MgYWxsIGJ1dHRvbiBldmVudHMgZHVyaW5nIGRyYWdnaW5nIGFuZCByZXNpemluZyxcbiAgICAvLyB1bmxlc3MgdGhpcyBpcyBhIG1vdXNldXAgZXZlbnQgdGhhdCBpcyBlbmRpbmcgYSBkcmFnIGFjdGlvbi5cbiAgICBpZiAoXG4gICAgICAgIGV2ZW50VHlwZSAhPT0gTW91c2VNb3ZlIC8vIEZhc3QgcGF0aCBmb3IgbW91c2Vtb3ZlXG4gICAgICAgICYmIHJlc2l6aW5nXG4gICAgICAgIHx8IChcbiAgICAgICAgICAgIGRyYWdnaW5nXG4gICAgICAgICAgICAmJiAoXG4gICAgICAgICAgICAgICAgZXZlbnRUeXBlID09PSBNb3VzZURvd25cbiAgICAgICAgICAgICAgICB8fCBldmVudC5idXR0b24gIT09IDBcbiAgICAgICAgICAgIClcbiAgICAgICAgKVxuICAgICkge1xuICAgICAgICBldmVudC5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcbiAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgfVxuXG4gICAgLy8gSGFuZGxlIHJlbGVhc2VzXG4gICAgaWYgKHJlbGVhc2VkICYgMSkgeyBwcmltYXJ5VXAoZXZlbnQpOyB9XG4gICAgLy8gSGFuZGxlIHByZXNzZXNcbiAgICBpZiAocHJlc3NlZCAmIDEpIHsgcHJpbWFyeURvd24oZXZlbnQpOyB9XG5cbiAgICAvLyBIYW5kbGUgbW91c2Vtb3ZlXG4gICAgaWYgKGV2ZW50VHlwZSA9PT0gTW91c2VNb3ZlKSB7IG9uTW91c2VNb3ZlKGV2ZW50KTsgfTtcbn1cblxuZnVuY3Rpb24gcHJpbWFyeURvd24oZXZlbnQ6IE1vdXNlRXZlbnQpOiB2b2lkIHtcbiAgICAvLyBSZXNldCByZWFkaW5lc3Mgc3RhdGUuXG4gICAgY2FuRHJhZyA9IGZhbHNlO1xuICAgIGNhblJlc2l6ZSA9IGZhbHNlO1xuXG4gICAgLy8gSWdub3JlIHJlcGVhdGVkIGNsaWNrcyBvbiBtYWNPUyBhbmQgTGludXguXG4gICAgaWYgKCFJc1dpbmRvd3MoKSkge1xuICAgICAgICBpZiAoZXZlbnQudHlwZSA9PT0gJ21vdXNlZG93bicgJiYgZXZlbnQuYnV0dG9uID09PSAwICYmIGV2ZW50LmRldGFpbCAhPT0gMSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHJlc2l6ZUVkZ2UpIHtcbiAgICAgICAgLy8gRG8gbm90IGFybSBlZGdlIHJlc2l6ZSBmcm9tIHN5bnRoZXNpemVkIHByZXNzZXMgb2JzZXJ2ZWQgb24gbW92ZS91cDpcbiAgICAgICAgLy8gZW50ZXJpbmcgdGhlIHdpbmRvdyB3aXRoIHRoZSBwcmltYXJ5IGJ1dHRvbiBhbHJlYWR5IGhlbGQgc2hvdWxkIG5vdFxuICAgICAgICAvLyBzdGVhbCBhbm90aGVyIGdlc3R1cmUgaW50byBhIHJlc2l6ZS5cbiAgICAgICAgaWYgKGV2ZW50LnR5cGUgIT09ICdtb3VzZWRvd24nKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZWFkeSB0byByZXNpemUgaWYgdGhlIHByaW1hcnkgYnV0dG9uIHdhcyBwcmVzc2VkIGZvciB0aGUgZmlyc3QgdGltZS5cbiAgICAgICAgY2FuUmVzaXplID0gdHJ1ZTtcbiAgICAgICAgLy8gRG8gbm90IHN0YXJ0IGRyYWcgb3BlcmF0aW9ucyB3aGVuIG9uIHJlc2l6ZSBlZGdlcy5cbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFJldHJpZXZlIHRhcmdldCBlbGVtZW50XG4gICAgY29uc3QgdGFyZ2V0ID0gZXZlbnRUYXJnZXQoZXZlbnQpO1xuXG4gICAgLy8gUmVhZHkgdG8gZHJhZyBpZiB0aGUgcHJpbWFyeSBidXR0b24gd2FzIHByZXNzZWQgZm9yIHRoZSBmaXJzdCB0aW1lIG9uIGEgZHJhZ2dhYmxlIGVsZW1lbnQuXG4gICAgLy8gSWdub3JlIGNsaWNrcyBvbiB0aGUgc2Nyb2xsYmFyLlxuICAgIGNvbnN0IHN0eWxlID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUodGFyZ2V0KTtcbiAgICBjYW5EcmFnID0gKFxuICAgICAgICBzdHlsZS5nZXRQcm9wZXJ0eVZhbHVlKFwiLS13YWlscy1kcmFnZ2FibGVcIikudHJpbSgpID09PSBcImRyYWdcIlxuICAgICAgICAmJiAoXG4gICAgICAgICAgICBldmVudC5vZmZzZXRYIC0gcGFyc2VGbG9hdChzdHlsZS5wYWRkaW5nTGVmdCkgPCB0YXJnZXQuY2xpZW50V2lkdGhcbiAgICAgICAgICAgICYmIGV2ZW50Lm9mZnNldFkgLSBwYXJzZUZsb2F0KHN0eWxlLnBhZGRpbmdUb3ApIDwgdGFyZ2V0LmNsaWVudEhlaWdodFxuICAgICAgICApXG4gICAgKTtcbn1cblxuZnVuY3Rpb24gcHJpbWFyeVVwKGV2ZW50OiBNb3VzZUV2ZW50KSB7XG4gICAgLy8gU3RvcCBkcmFnZ2luZyBhbmQgcmVzaXppbmcuXG4gICAgY2FuRHJhZyA9IGZhbHNlO1xuICAgIGRyYWdnaW5nID0gZmFsc2U7XG4gICAgY2FuUmVzaXplID0gZmFsc2U7XG4gICAgcmVzaXppbmcgPSBmYWxzZTtcbn1cblxuY29uc3QgY3Vyc29yRm9yRWRnZSA9IE9iamVjdC5mcmVlemUoe1xuICAgIFwic2UtcmVzaXplXCI6IFwibndzZS1yZXNpemVcIixcbiAgICBcInN3LXJlc2l6ZVwiOiBcIm5lc3ctcmVzaXplXCIsXG4gICAgXCJudy1yZXNpemVcIjogXCJud3NlLXJlc2l6ZVwiLFxuICAgIFwibmUtcmVzaXplXCI6IFwibmVzdy1yZXNpemVcIixcbiAgICBcInctcmVzaXplXCI6IFwiZXctcmVzaXplXCIsXG4gICAgXCJuLXJlc2l6ZVwiOiBcIm5zLXJlc2l6ZVwiLFxuICAgIFwicy1yZXNpemVcIjogXCJucy1yZXNpemVcIixcbiAgICBcImUtcmVzaXplXCI6IFwiZXctcmVzaXplXCIsXG59KVxuXG5mdW5jdGlvbiBzZXRSZXNpemUoZWRnZT86IGtleW9mIHR5cGVvZiBjdXJzb3JGb3JFZGdlKTogdm9pZCB7XG4gICAgaWYgKGVkZ2UpIHtcbiAgICAgICAgaWYgKCFyZXNpemVFZGdlKSB7IGRlZmF1bHRDdXJzb3IgPSBkb2N1bWVudC5ib2R5LnN0eWxlLmN1cnNvcjsgfVxuICAgICAgICBkb2N1bWVudC5ib2R5LnN0eWxlLmN1cnNvciA9IGN1cnNvckZvckVkZ2VbZWRnZV07XG4gICAgfSBlbHNlIGlmICghZWRnZSAmJiByZXNpemVFZGdlKSB7XG4gICAgICAgIGRvY3VtZW50LmJvZHkuc3R5bGUuY3Vyc29yID0gZGVmYXVsdEN1cnNvcjtcbiAgICB9XG5cbiAgICByZXNpemVFZGdlID0gZWRnZSB8fCBcIlwiO1xufVxuXG5mdW5jdGlvbiBvbk1vdXNlTW92ZShldmVudDogTW91c2VFdmVudCk6IHZvaWQge1xuICAgIGlmIChjYW5SZXNpemUgJiYgcmVzaXplRWRnZSkge1xuICAgICAgICAvLyBTdGFydCByZXNpemluZy5cbiAgICAgICAgcmVzaXppbmcgPSB0cnVlO1xuICAgICAgICBpbnZva2UoXCJ3YWlsczpyZXNpemU6XCIgKyByZXNpemVFZGdlKTtcbiAgICB9IGVsc2UgaWYgKGNhbkRyYWcpIHtcbiAgICAgICAgLy8gU3RhcnQgZHJhZ2dpbmcuXG4gICAgICAgIGRyYWdnaW5nID0gdHJ1ZTtcbiAgICAgICAgaW52b2tlKFwid2FpbHM6ZHJhZ1wiKTtcbiAgICB9XG5cbiAgICBpZiAoZHJhZ2dpbmcgfHwgcmVzaXppbmcpIHtcbiAgICAgICAgLy8gRWl0aGVyIGRyYWcgb3IgcmVzaXplIGlzIG9uZ29pbmcsXG4gICAgICAgIC8vIHJlc2V0IHJlYWRpbmVzcyBhbmQgc3RvcCBwcm9jZXNzaW5nLlxuICAgICAgICBjYW5EcmFnID0gY2FuUmVzaXplID0gZmFsc2U7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIXJlc2l6YWJsZSB8fCAoIUlzV2luZG93cygpICYmICEoSXNMaW51eCgpICYmIEdldEZsYWcoXCJmcmFtZWxlc3NcIikpKSkge1xuICAgICAgICBpZiAocmVzaXplRWRnZSkgeyBzZXRSZXNpemUoKTsgfVxuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgcmVzaXplSGFuZGxlSGVpZ2h0ID0gR2V0RmxhZyhcInN5c3RlbS5yZXNpemVIYW5kbGVIZWlnaHRcIikgfHwgNTtcbiAgICBjb25zdCByZXNpemVIYW5kbGVXaWR0aCA9IEdldEZsYWcoXCJzeXN0ZW0ucmVzaXplSGFuZGxlV2lkdGhcIikgfHwgNTtcblxuICAgIC8vIEV4dHJhIHBpeGVscyBmb3IgdGhlIGNvcm5lciBhcmVhcy5cbiAgICBjb25zdCBjb3JuZXJFeHRyYSA9IEdldEZsYWcoXCJyZXNpemVDb3JuZXJFeHRyYVwiKSB8fCAxMDtcblxuICAgIC8vIFdoZW4gYSBzY3JvbGxiYXIgaXMgcHJlc2VudCBhdCB0aGUgd2luZG93IGVkZ2UgaXQgY29uc3VtZXMgbW91c2UgZXZlbnRzIGluIHRoYXQgc3RyaXAuXG4gICAgLy8gU2hpZnQgdGhlIGVmZmVjdGl2ZSBjb250ZW50IGVkZ2UgaW53YXJkIHNvIHRoZSByZXNpemUgem9uZSBzaXRzIGp1c3QgYmVmb3JlIHRoZSBzY3JvbGxiYXIuXG4gICAgY29uc3Qgc2Nyb2xsYmFyV2lkdGggPSBNYXRoLm1heCgwLCB3aW5kb3cuaW5uZXJXaWR0aCAtIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRXaWR0aCk7XG4gICAgY29uc3Qgc2Nyb2xsYmFySGVpZ2h0ID0gTWF0aC5tYXgoMCwgd2luZG93LmlubmVySGVpZ2h0IC0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudEhlaWdodCk7XG4gICAgY29uc3QgcmlnaHRDb250ZW50RWRnZSA9IHdpbmRvdy5pbm5lcldpZHRoIC0gc2Nyb2xsYmFyV2lkdGg7XG4gICAgY29uc3QgYm90dG9tQ29udGVudEVkZ2UgPSB3aW5kb3cuaW5uZXJIZWlnaHQgLSBzY3JvbGxiYXJIZWlnaHQ7XG5cbiAgICBjb25zdCByaWdodEJvcmRlciA9IGV2ZW50LmNsaWVudFggPCByaWdodENvbnRlbnRFZGdlICYmIChyaWdodENvbnRlbnRFZGdlIC0gZXZlbnQuY2xpZW50WCkgPCByZXNpemVIYW5kbGVXaWR0aDtcbiAgICBjb25zdCBsZWZ0Qm9yZGVyID0gZXZlbnQuY2xpZW50WCA8IHJlc2l6ZUhhbmRsZVdpZHRoO1xuICAgIGNvbnN0IHRvcEJvcmRlciA9IGV2ZW50LmNsaWVudFkgPCByZXNpemVIYW5kbGVIZWlnaHQ7XG4gICAgY29uc3QgYm90dG9tQm9yZGVyID0gZXZlbnQuY2xpZW50WSA8IGJvdHRvbUNvbnRlbnRFZGdlICYmIChib3R0b21Db250ZW50RWRnZSAtIGV2ZW50LmNsaWVudFkpIDwgcmVzaXplSGFuZGxlSGVpZ2h0O1xuXG4gICAgLy8gQWRqdXN0IGZvciBjb3JuZXIgYXJlYXMuXG4gICAgY29uc3QgcmlnaHRDb3JuZXIgPSBldmVudC5jbGllbnRYIDwgcmlnaHRDb250ZW50RWRnZSAmJiAocmlnaHRDb250ZW50RWRnZSAtIGV2ZW50LmNsaWVudFgpIDwgKHJlc2l6ZUhhbmRsZVdpZHRoICsgY29ybmVyRXh0cmEpO1xuICAgIGNvbnN0IGxlZnRDb3JuZXIgPSBldmVudC5jbGllbnRYIDwgKHJlc2l6ZUhhbmRsZVdpZHRoICsgY29ybmVyRXh0cmEpO1xuICAgIGNvbnN0IHRvcENvcm5lciA9IGV2ZW50LmNsaWVudFkgPCAocmVzaXplSGFuZGxlSGVpZ2h0ICsgY29ybmVyRXh0cmEpO1xuICAgIGNvbnN0IGJvdHRvbUNvcm5lciA9IGV2ZW50LmNsaWVudFkgPCBib3R0b21Db250ZW50RWRnZSAmJiAoYm90dG9tQ29udGVudEVkZ2UgLSBldmVudC5jbGllbnRZKSA8IChyZXNpemVIYW5kbGVIZWlnaHQgKyBjb3JuZXJFeHRyYSk7XG5cbiAgICBpZiAoIWxlZnRDb3JuZXIgJiYgIXRvcENvcm5lciAmJiAhYm90dG9tQ29ybmVyICYmICFyaWdodENvcm5lcikge1xuICAgICAgICAvLyBPcHRpbWlzYXRpb246IG91dCBvZiBhbGwgY29ybmVyIGFyZWFzIGltcGxpZXMgb3V0IG9mIGJvcmRlcnMuXG4gICAgICAgIHNldFJlc2l6ZSgpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgY29ybmVycy5cbiAgICBlbHNlIGlmIChyaWdodENvcm5lciAmJiBib3R0b21Db3JuZXIpIHNldFJlc2l6ZShcInNlLXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmIChsZWZ0Q29ybmVyICYmIGJvdHRvbUNvcm5lcikgc2V0UmVzaXplKFwic3ctcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKGxlZnRDb3JuZXIgJiYgdG9wQ29ybmVyKSBzZXRSZXNpemUoXCJudy1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAodG9wQ29ybmVyICYmIHJpZ2h0Q29ybmVyKSBzZXRSZXNpemUoXCJuZS1yZXNpemVcIik7XG4gICAgLy8gRGV0ZWN0IGJvcmRlcnMuXG4gICAgZWxzZSBpZiAobGVmdEJvcmRlcikgc2V0UmVzaXplKFwidy1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAodG9wQm9yZGVyKSBzZXRSZXNpemUoXCJuLXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmIChib3R0b21Cb3JkZXIpIHNldFJlc2l6ZShcInMtcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKHJpZ2h0Qm9yZGVyKSBzZXRSZXNpemUoXCJlLXJlc2l6ZVwiKTtcbiAgICAvLyBPdXQgb2YgYm9yZGVyIGFyZWEuXG4gICAgZWxzZSBzZXRSZXNpemUoKTtcbn1cbiIsICIvKlxuIF8gICAgIF9fICAgIF8gX19cbnwgfCAgIC8gL19fXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbmltcG9ydCB7IGludm9rZSB9IGZyb20gXCIuL3N5c3RlbS5qc1wiO1xuaW1wb3J0IHsgd2hlblJlYWR5IH0gZnJvbSBcIi4vdXRpbHMuanNcIjtcbmltcG9ydCB7IGhhc0RPTSB9IGZyb20gXCIuL2Vudmlyb25tZW50LmpzXCI7XG5cbnR5cGUgTm9uQ2xpZW50UmVnaW9uS2luZCA9IFwiY2FwdGlvblwiIHwgXCJtaW5pbWl6ZVwiIHwgXCJtYXhpbWl6ZVwiIHwgXCJjbG9zZVwiO1xuXG5pbnRlcmZhY2UgTm9uQ2xpZW50UmVnaW9uIHtcbiAgICBraW5kOiBOb25DbGllbnRSZWdpb25LaW5kO1xuICAgIGxlZnQ6IG51bWJlcjtcbiAgICB0b3A6IG51bWJlcjtcbiAgICByaWdodDogbnVtYmVyO1xuICAgIGJvdHRvbTogbnVtYmVyO1xufVxuXG4vKlxuLS13YWlscy1ub24tY2xpZW50LXJlZ2lvbjogY2FwdGlvbjsgIG1hcmtzIGFuIGFyZWEgdGhhdCBjYW4gZHJhZyB0aGUgd2luZG93XG4tLXdhaWxzLW5vbi1jbGllbnQtcmVnaW9uOiBtaW5pbWl6ZTsgbWFya3MgYSBjdXN0b20gbWluaW1pemUgYnV0dG9uXG4tLXdhaWxzLW5vbi1jbGllbnQtcmVnaW9uOiBtYXhpbWl6ZTsgbWFya3MgYSBjdXN0b20gbWF4aW1pemUgYnV0dG9uXG4tLXdhaWxzLW5vbi1jbGllbnQtcmVnaW9uOiBjbG9zZTsgICAgbWFya3MgYSBjdXN0b20gY2xvc2UgYnV0dG9uXG4qL1xuY29uc3QgcmVnaW9uUHJvcGVydHkgPSBcIi0td2FpbHMtbm9uLWNsaWVudC1yZWdpb25cIjtcbmNvbnN0IHJ1bnRpbWVDb25maWdSZWFkeUV2ZW50ID0gXCJ3YWlsczpydW50aW1lLWNvbmZpZy1yZWFkeVwiO1xuY29uc3QgdmFsaWRSZWdpb25zID0gbmV3IFNldDxOb25DbGllbnRSZWdpb25LaW5kPihbXCJjYXB0aW9uXCIsIFwibWluaW1pemVcIiwgXCJtYXhpbWl6ZVwiLCBcImNsb3NlXCJdKTtcblxuLy8gU2V0dXBcbmlmIChoYXNET00pIHtcbiAgICB3aW5kb3cuX3dhaWxzID0gd2luZG93Ll93YWlscyB8fCB7fTtcbn1cblxubGV0IHVwZGF0ZVBlbmRpbmcgPSBmYWxzZTtcbmxldCBsYXN0UGF5bG9hZCA9IFwiXCI7XG5sZXQgb2JzZXJ2ZWRFbGVtZW50cyA9IG5ldyBTZXQ8RWxlbWVudD4oKTtcbmxldCByZXNpemVPYnNlcnZlcjogUmVzaXplT2JzZXJ2ZXIgfCB1bmRlZmluZWQ7XG5sZXQgdHJhY2tpbmdTdGFydGVkID0gZmFsc2U7XG5cbmZ1bmN0aW9uIG5vcm1hbGlzZVJlZ2lvbktpbmQodmFsdWU6IHN0cmluZyk6IE5vbkNsaWVudFJlZ2lvbktpbmQgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IHJlZ2lvbiA9IHZhbHVlLnRyaW0oKS50b0xvd2VyQ2FzZSgpO1xuICAgIGlmICh2YWxpZFJlZ2lvbnMuaGFzKHJlZ2lvbiBhcyBOb25DbGllbnRSZWdpb25LaW5kKSkge1xuICAgICAgICByZXR1cm4gcmVnaW9uIGFzIE5vbkNsaWVudFJlZ2lvbktpbmQ7XG4gICAgfVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbmZ1bmN0aW9uIG5vbkNsaWVudFJlZ2lvbkZvckVsZW1lbnQoZWxlbWVudDogRWxlbWVudCk6IE5vbkNsaWVudFJlZ2lvbktpbmQgfCB1bmRlZmluZWQge1xuICAgIGlmICghKGVsZW1lbnQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkpIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBjb25zdCBzdHlsZSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGVsZW1lbnQpO1xuICAgIGNvbnN0IHJlZ2lvbiA9IG5vcm1hbGlzZVJlZ2lvbktpbmQoc3R5bGUuZ2V0UHJvcGVydHlWYWx1ZShyZWdpb25Qcm9wZXJ0eSkpO1xuICAgIGlmICghcmVnaW9uKSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgY29uc3QgcGFyZW50ID0gZWxlbWVudC5wYXJlbnRFbGVtZW50O1xuICAgIGlmIChwYXJlbnQpIHtcbiAgICAgICAgY29uc3QgcGFyZW50U3R5bGUgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShwYXJlbnQpO1xuICAgICAgICAvLyBUaGUgQ1NTIHByb3BlcnR5IGlzIGluaGVyaXRlZC4gT25seSByZXBvcnQgdGhlIG91dGVybW9zdCBlbGVtZW50IGZvclxuICAgICAgICAvLyBlYWNoIGNvbnRpZ3VvdXMgcmVnaW9uIHNvIG5hdGl2ZSBoaXQgdGVzdGluZyBzZWVzIHN0YWJsZSByZWN0YW5nbGVzLlxuICAgICAgICBpZiAobm9ybWFsaXNlUmVnaW9uS2luZChwYXJlbnRTdHlsZS5nZXRQcm9wZXJ0eVZhbHVlKHJlZ2lvblByb3BlcnR5KSkgPT09IHJlZ2lvbikge1xuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZWdpb247XG59XG5cbmZ1bmN0aW9uIGlzVmlzaWJsZShlbGVtZW50OiBIVE1MRWxlbWVudCk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHN0eWxlID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZWxlbWVudCk7XG4gICAgcmV0dXJuIHN0eWxlLmRpc3BsYXkgIT09IFwibm9uZVwiICYmXG4gICAgICAgIHN0eWxlLnZpc2liaWxpdHkgIT09IFwiaGlkZGVuXCIgJiZcbiAgICAgICAgc3R5bGUuY29udGVudFZpc2liaWxpdHkgIT09IFwiaGlkZGVuXCI7XG59XG5cbmZ1bmN0aW9uIGVsZW1lbnRSZWdpb24oZWxlbWVudDogRWxlbWVudCk6IE5vbkNsaWVudFJlZ2lvbiB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCEoZWxlbWVudCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSkge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGNvbnN0IGtpbmQgPSBub25DbGllbnRSZWdpb25Gb3JFbGVtZW50KGVsZW1lbnQpO1xuICAgIGlmICgha2luZCB8fCAhaXNWaXNpYmxlKGVsZW1lbnQpKSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgY29uc3QgcmVjdCA9IGVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgaWYgKHJlY3Qud2lkdGggPD0gMCB8fCByZWN0LmhlaWdodCA8PSAwKSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLy8gTmF0aXZlIGhpdCB0ZXN0aW5nIHJ1bnMgaW4gcGh5c2ljYWwgcGl4ZWxzLCB3aGlsZSBET00gZ2VvbWV0cnkgaXMgaW4gQ1NTIHBpeGVscy5cbiAgICBjb25zdCBzY2FsZSA9IHdpbmRvdy5kZXZpY2VQaXhlbFJhdGlvIHx8IDE7XG4gICAgY29uc3QgbGVmdCA9IE1hdGguZmxvb3IocmVjdC5sZWZ0ICogc2NhbGUpO1xuICAgIGNvbnN0IHRvcCA9IE1hdGguZmxvb3IocmVjdC50b3AgKiBzY2FsZSk7XG4gICAgY29uc3QgcmlnaHQgPSBNYXRoLmNlaWwocmVjdC5yaWdodCAqIHNjYWxlKTtcbiAgICBjb25zdCBib3R0b20gPSBNYXRoLmNlaWwocmVjdC5ib3R0b20gKiBzY2FsZSk7XG5cbiAgICBpZiAocmlnaHQgPD0gbGVmdCB8fCBib3R0b20gPD0gdG9wKSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHsga2luZCwgbGVmdCwgdG9wLCByaWdodCwgYm90dG9tIH07XG59XG5cbmZ1bmN0aW9uIHJlZ2lvbkVsZW1lbnRzKCk6IEVsZW1lbnRbXSB7XG4gICAgY29uc3QgZWxlbWVudHM6IEVsZW1lbnRbXSA9IFtdO1xuXG4gICAgaWYgKGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCkge1xuICAgICAgICBlbGVtZW50cy5wdXNoKGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCk7XG4gICAgfVxuICAgIGlmIChkb2N1bWVudC5ib2R5KSB7XG4gICAgICAgIGVsZW1lbnRzLnB1c2goZG9jdW1lbnQuYm9keSk7XG4gICAgICAgIC8vIEFwcGVuZCB2aWEgYSBsb29wOiBzcHJlYWRpbmcgYSBodWdlIE5vZGVMaXN0IGludG8gcHVzaCgpIG92ZXJmbG93c1xuICAgICAgICAvLyB0aGUgZW5naW5lJ3MgYXJndW1lbnQgbGltaXQgb24gdmVyeSBsYXJnZSBkb2N1bWVudHMuXG4gICAgICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiBkb2N1bWVudC5ib2R5LnF1ZXJ5U2VsZWN0b3JBbGwoXCIqXCIpKSB7XG4gICAgICAgICAgICBlbGVtZW50cy5wdXNoKGVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGVsZW1lbnRzO1xufVxuXG5mdW5jdGlvbiBvYnNlcnZlUmVnaW9uRWxlbWVudHMoZWxlbWVudHM6IEVsZW1lbnRbXSk6IHZvaWQge1xuICAgIGlmICh0eXBlb2YgUmVzaXplT2JzZXJ2ZXIgPT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFRyYWNrIHNpemUgY2hhbmdlcyBvbmx5IGZvciBhY3RpdmUgcmVnaW9uIGVsZW1lbnRzLiBET00gc3RydWN0dXJlIGFuZCBzdHlsZVxuICAgIC8vIGNoYW5nZXMgYXJlIGNvdmVyZWQgYnkgTXV0YXRpb25PYnNlcnZlciBpbiBzdGFydE5vbkNsaWVudFJlZ2lvblRyYWNraW5nKCkuXG4gICAgcmVzaXplT2JzZXJ2ZXIgPz89IG5ldyBSZXNpemVPYnNlcnZlcihzY2hlZHVsZVVwZGF0ZSk7XG4gICAgY29uc3QgbmV4dEVsZW1lbnRzID0gbmV3IFNldChlbGVtZW50cyk7XG5cbiAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2Ygb2JzZXJ2ZWRFbGVtZW50cykge1xuICAgICAgICBpZiAoIW5leHRFbGVtZW50cy5oYXMoZWxlbWVudCkpIHtcbiAgICAgICAgICAgIHJlc2l6ZU9ic2VydmVyLnVub2JzZXJ2ZShlbGVtZW50KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiBuZXh0RWxlbWVudHMpIHtcbiAgICAgICAgaWYgKCFvYnNlcnZlZEVsZW1lbnRzLmhhcyhlbGVtZW50KSkge1xuICAgICAgICAgICAgcmVzaXplT2JzZXJ2ZXIub2JzZXJ2ZShlbGVtZW50KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIG9ic2VydmVkRWxlbWVudHMgPSBuZXh0RWxlbWVudHM7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZU5vbkNsaWVudFJlZ2lvbnMoKTogdm9pZCB7XG4gICAgdXBkYXRlUGVuZGluZyA9IGZhbHNlO1xuXG4gICAgY29uc3QgZWxlbWVudHMgPSByZWdpb25FbGVtZW50cygpO1xuICAgIGNvbnN0IHJlZ2lvbnM6IE5vbkNsaWVudFJlZ2lvbltdID0gW107XG4gICAgY29uc3QgYWN0aXZlRWxlbWVudHM6IEVsZW1lbnRbXSA9IFtdO1xuXG4gICAgZm9yIChjb25zdCBlbGVtZW50IG9mIGVsZW1lbnRzKSB7XG4gICAgICAgIGNvbnN0IHJlZ2lvbiA9IGVsZW1lbnRSZWdpb24oZWxlbWVudCk7XG4gICAgICAgIGlmIChyZWdpb24pIHtcbiAgICAgICAgICAgIHJlZ2lvbnMucHVzaChyZWdpb24pO1xuICAgICAgICAgICAgYWN0aXZlRWxlbWVudHMucHVzaChlbGVtZW50KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIG9ic2VydmVSZWdpb25FbGVtZW50cyhhY3RpdmVFbGVtZW50cyk7XG5cbiAgICBjb25zdCBwYXlsb2FkID0gSlNPTi5zdHJpbmdpZnkoeyB2ZXJzaW9uOiAxLCByZWdpb25zIH0pO1xuICAgIGlmIChwYXlsb2FkID09PSBsYXN0UGF5bG9hZCkge1xuICAgICAgICAvLyBBdm9pZCBzZW5kaW5nIGR1cGxpY2F0ZSBuYXRpdmUgbWVzc2FnZXMgZHVyaW5nIHJlc2l6ZSBvciBzdHlsZSBjaHVybi5cbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGxhc3RQYXlsb2FkID0gcGF5bG9hZDtcbiAgICBpbnZva2UoXCJ3YWlsczpub24tY2xpZW50LXJlZ2lvbjpcIiArIHBheWxvYWQpO1xufVxuXG5mdW5jdGlvbiBzY2hlZHVsZVVwZGF0ZSgpOiB2b2lkIHtcbiAgICBpZiAodXBkYXRlUGVuZGluZykge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gQmF0Y2ggcmVnaW9uIHVwZGF0ZXMgdG8gYW5pbWF0aW9uIGZyYW1lcyBzbyBsYXlvdXQgaXMgbWVhc3VyZWQgb25jZSBwZXIgZnJhbWUuXG4gICAgdXBkYXRlUGVuZGluZyA9IHRydWU7XG4gICAgd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZSh1cGRhdGVOb25DbGllbnRSZWdpb25zKTtcbn1cblxuZnVuY3Rpb24gc3RhcnROb25DbGllbnRSZWdpb25UcmFja2luZygpOiB2b2lkIHtcbiAgICBpZiAodHJhY2tpbmdTdGFydGVkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0cmFja2luZ1N0YXJ0ZWQgPSB0cnVlO1xuICAgIC8vIFNlbmQgYW4gaW5pdGlhbCBlbXB0eSBvciBwb3B1bGF0ZWQgcmVnaW9uIGxpc3Qgb25jZSB0aGUgRE9NIGlzIHJlYWR5LlxuICAgIHNjaGVkdWxlVXBkYXRlKCk7XG5cbiAgICBjb25zdCBtdXRhdGlvbk9ic2VydmVyID0gbmV3IE11dGF0aW9uT2JzZXJ2ZXIoc2NoZWR1bGVVcGRhdGUpO1xuICAgIG11dGF0aW9uT2JzZXJ2ZXIub2JzZXJ2ZShkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQsIHtcbiAgICAgICAgYXR0cmlidXRlczogdHJ1ZSxcbiAgICAgICAgY2hpbGRMaXN0OiB0cnVlLFxuICAgICAgICBzdWJ0cmVlOiB0cnVlLFxuICAgIH0pO1xuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoXCJyZXNpemVcIiwgc2NoZWR1bGVVcGRhdGUpO1xuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKFwic2Nyb2xsXCIsIHNjaGVkdWxlVXBkYXRlLCB0cnVlKTtcbiAgICB3aW5kb3cudmlzdWFsVmlld3BvcnQ/LmFkZEV2ZW50TGlzdGVuZXIoXCJyZXNpemVcIiwgc2NoZWR1bGVVcGRhdGUpO1xuICAgIHdpbmRvdy52aXN1YWxWaWV3cG9ydD8uYWRkRXZlbnRMaXN0ZW5lcihcInNjcm9sbFwiLCBzY2hlZHVsZVVwZGF0ZSk7XG59XG5cbmZ1bmN0aW9uIHRyeVN0YXJ0Tm9uQ2xpZW50UmVnaW9uVHJhY2tpbmcoKTogYm9vbGVhbiB7XG4gICAgY29uc3Qgb3MgPSB3aW5kb3cuX3dhaWxzLmVudmlyb25tZW50Py5PUztcbiAgICBpZiAob3MgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgZW5hYmxlZCA9IHdpbmRvdy5fd2FpbHMuZmxhZ3M/Lm5vbkNsaWVudFJlZ2lvblRyYWNraW5nO1xuICAgIGlmIChvcyA9PT0gXCJ3aW5kb3dzXCIpIHtcbiAgICAgICAgaWYgKGVuYWJsZWQgPT09IHRydWUpIHtcbiAgICAgICAgICAgIHdoZW5SZWFkeShzdGFydE5vbkNsaWVudFJlZ2lvblRyYWNraW5nKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxuaWYgKGhhc0RPTSAmJiAhdHJ5U3RhcnROb25DbGllbnRSZWdpb25UcmFja2luZygpKSB7XG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIocnVudGltZUNvbmZpZ1JlYWR5RXZlbnQsIHRyeVN0YXJ0Tm9uQ2xpZW50UmVnaW9uVHJhY2tpbmcsIHsgb25jZTogdHJ1ZSB9KTtcbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuaW1wb3J0IHsgbmV3UnVudGltZUNhbGxlciwgb2JqZWN0TmFtZXMgfSBmcm9tIFwiLi9ydW50aW1lLmpzXCI7XG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcihvYmplY3ROYW1lcy5BcHBsaWNhdGlvbik7XG5cbmNvbnN0IEhpZGVNZXRob2QgPSAwO1xuY29uc3QgU2hvd01ldGhvZCA9IDE7XG5jb25zdCBRdWl0TWV0aG9kID0gMjtcblxuLyoqXG4gKiBIaWRlcyBhIGNlcnRhaW4gbWV0aG9kIGJ5IGNhbGxpbmcgdGhlIEhpZGVNZXRob2QgZnVuY3Rpb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBIaWRlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBjYWxsKEhpZGVNZXRob2QpO1xufVxuXG4vKipcbiAqIENhbGxzIHRoZSBTaG93TWV0aG9kIGFuZCByZXR1cm5zIHRoZSByZXN1bHQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTaG93KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBjYWxsKFNob3dNZXRob2QpO1xufVxuXG4vKipcbiAqIENhbGxzIHRoZSBRdWl0TWV0aG9kIHRvIHRlcm1pbmF0ZSB0aGUgcHJvZ3JhbS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFF1aXQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIGNhbGwoUXVpdE1ldGhvZCk7XG59XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbmltcG9ydCB7IENhbmNlbGxhYmxlUHJvbWlzZSwgdHlwZSBDYW5jZWxsYWJsZVByb21pc2VXaXRoUmVzb2x2ZXJzIH0gZnJvbSBcIi4vY2FuY2VsbGFibGUuanNcIjtcbmltcG9ydCB7IG5ld1J1bnRpbWVDYWxsZXIsIG9iamVjdE5hbWVzIH0gZnJvbSBcIi4vcnVudGltZS5qc1wiO1xuaW1wb3J0IHsgbmFub2lkIH0gZnJvbSBcIi4vbmFub2lkLmpzXCI7XG5cbi8vIFNldHVwXG5pbXBvcnQgeyBoYXNET00gfSBmcm9tIFwiLi9lbnZpcm9ubWVudC5qc1wiO1xuXG5pZiAoaGFzRE9NKSB7XG4gICAgd2luZG93Ll93YWlscyA9IHdpbmRvdy5fd2FpbHMgfHwge307XG59XG5cbnR5cGUgUHJvbWlzZVJlc29sdmVycyA9IE9taXQ8Q2FuY2VsbGFibGVQcm9taXNlV2l0aFJlc29sdmVyczxhbnk+LCBcInByb21pc2VcIiB8IFwib25jYW5jZWxsZWRcIj5cblxuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXIob2JqZWN0TmFtZXMuQ2FsbCk7XG5jb25zdCBjYW5jZWxDYWxsID0gbmV3UnVudGltZUNhbGxlcihvYmplY3ROYW1lcy5DYW5jZWxDYWxsKTtcbmNvbnN0IGNhbGxSZXNwb25zZXMgPSBuZXcgTWFwPHN0cmluZywgUHJvbWlzZVJlc29sdmVycz4oKTtcblxuY29uc3QgQ2FsbEJpbmRpbmcgPSAwO1xuY29uc3QgQ2FuY2VsTWV0aG9kID0gMFxuXG4vKipcbiAqIEhvbGRzIGFsbCByZXF1aXJlZCBpbmZvcm1hdGlvbiBmb3IgYSBiaW5kaW5nIGNhbGwuXG4gKiBNYXkgcHJvdmlkZSBlaXRoZXIgYSBtZXRob2QgSUQgb3IgYSBtZXRob2QgbmFtZSwgYnV0IG5vdCBib3RoLlxuICovXG5leHBvcnQgdHlwZSBDYWxsT3B0aW9ucyA9IHtcbiAgICAvKiogVGhlIG51bWVyaWMgSUQgb2YgdGhlIGJvdW5kIG1ldGhvZCB0byBjYWxsLiAqL1xuICAgIG1ldGhvZElEOiBudW1iZXI7XG4gICAgLyoqIFRoZSBmdWxseSBxdWFsaWZpZWQgbmFtZSBvZiB0aGUgYm91bmQgbWV0aG9kIHRvIGNhbGwuICovXG4gICAgbWV0aG9kTmFtZT86IG5ldmVyO1xuICAgIC8qKiBBcmd1bWVudHMgdG8gYmUgcGFzc2VkIGludG8gdGhlIGJvdW5kIG1ldGhvZC4gKi9cbiAgICBhcmdzOiBhbnlbXTtcbn0gfCB7XG4gICAgLyoqIFRoZSBudW1lcmljIElEIG9mIHRoZSBib3VuZCBtZXRob2QgdG8gY2FsbC4gKi9cbiAgICBtZXRob2RJRD86IG5ldmVyO1xuICAgIC8qKiBUaGUgZnVsbHkgcXVhbGlmaWVkIG5hbWUgb2YgdGhlIGJvdW5kIG1ldGhvZCB0byBjYWxsLiAqL1xuICAgIG1ldGhvZE5hbWU6IHN0cmluZztcbiAgICAvKiogQXJndW1lbnRzIHRvIGJlIHBhc3NlZCBpbnRvIHRoZSBib3VuZCBtZXRob2QuICovXG4gICAgYXJnczogYW55W107XG59O1xuXG4vLyBydW50aW1lLmpzIG5lZWRzIHRvIHVzZSBSdW50aW1lRXJyb3IgaW50ZXJuYWxseSB0byBwcm9wZXJseSBwYXJzZSBhbmQgcmV0dXJuXG4vLyBlcnJvcnMgZm9yIGJpbmRpbmcgY2FsbHMsIHNvIGl0IGhhZCB0byBtb3ZlIHRoZXJlLiBFeHBvcnRpbmcgaGVyZSBhZ2FpbiB0b1xuLy8ga2VlcCBmcm9tIGJyZWFraW5nIHRoZSBwdWJsaWMgQ2FsbCBpbnRlcmZhY2UuXG5leHBvcnQgeyBSdW50aW1lRXJyb3IgfSBmcm9tIFwiLi9ydW50aW1lLmpzXCI7XG5cbi8qKlxuICogR2VuZXJhdGVzIGEgdW5pcXVlIElEIHVzaW5nIHRoZSBuYW5vaWQgbGlicmFyeS5cbiAqXG4gKiBAcmV0dXJucyBBIHVuaXF1ZSBJRCB0aGF0IGRvZXMgbm90IGV4aXN0IGluIHRoZSBjYWxsUmVzcG9uc2VzIHNldC5cbiAqL1xuZnVuY3Rpb24gZ2VuZXJhdGVJRCgpOiBzdHJpbmcge1xuICAgIGxldCByZXN1bHQ7XG4gICAgZG8ge1xuICAgICAgICByZXN1bHQgPSBuYW5vaWQoKTtcbiAgICB9IHdoaWxlIChjYWxsUmVzcG9uc2VzLmhhcyhyZXN1bHQpKTtcbiAgICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKipcbiAqIENhbGwgYSBib3VuZCBtZXRob2QgYWNjb3JkaW5nIHRvIHRoZSBnaXZlbiBjYWxsIG9wdGlvbnMuXG4gKlxuICogSW4gY2FzZSBvZiBmYWlsdXJlLCB0aGUgcmV0dXJuZWQgcHJvbWlzZSB3aWxsIHJlamVjdCB3aXRoIGFuIGV4Y2VwdGlvblxuICogYW1vbmcgUmVmZXJlbmNlRXJyb3IgKHVua25vd24gbWV0aG9kKSwgVHlwZUVycm9yICh3cm9uZyBhcmd1bWVudCBjb3VudCBvciB0eXBlKSxcbiAqIHtAbGluayBSdW50aW1lRXJyb3J9IChtZXRob2QgcmV0dXJuZWQgYW4gZXJyb3IpLCBvciBvdGhlciAobmV0d29yayBvciBpbnRlcm5hbCBlcnJvcnMpLlxuICogVGhlIGV4Y2VwdGlvbiBtaWdodCBoYXZlIGEgXCJjYXVzZVwiIGZpZWxkIHdpdGggdGhlIHZhbHVlIHJldHVybmVkXG4gKiBieSB0aGUgYXBwbGljYXRpb24tIG9yIHNlcnZpY2UtbGV2ZWwgZXJyb3IgbWFyc2hhbGluZyBmdW5jdGlvbnMuXG4gKlxuICogQHBhcmFtIG9wdGlvbnMgLSBBIG1ldGhvZCBjYWxsIGRlc2NyaXB0b3IuXG4gKiBAcmV0dXJucyBUaGUgcmVzdWx0IG9mIHRoZSBjYWxsLlxuICovXG5leHBvcnQgZnVuY3Rpb24gQ2FsbChvcHRpb25zOiBDYWxsT3B0aW9ucyk6IENhbmNlbGxhYmxlUHJvbWlzZTxhbnk+IHtcbiAgICBjb25zdCBpZCA9IGdlbmVyYXRlSUQoKTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IENhbmNlbGxhYmxlUHJvbWlzZS53aXRoUmVzb2x2ZXJzPGFueT4oKTtcbiAgICBjYWxsUmVzcG9uc2VzLnNldChpZCwgeyByZXNvbHZlOiByZXN1bHQucmVzb2x2ZSwgcmVqZWN0OiByZXN1bHQucmVqZWN0IH0pO1xuXG4gICAgY29uc3QgcmVxdWVzdCA9IGNhbGwoQ2FsbEJpbmRpbmcsIE9iamVjdC5hc3NpZ24oeyBcImNhbGwtaWRcIjogaWQgfSwgb3B0aW9ucykpO1xuICAgIGxldCBydW5uaW5nID0gdHJ1ZTtcblxuICAgIHJlcXVlc3QudGhlbigocmVzKSA9PiB7XG4gICAgICAgIHJ1bm5pbmcgPSBmYWxzZTtcbiAgICAgICAgY2FsbFJlc3BvbnNlcy5kZWxldGUoaWQpO1xuICAgICAgICByZXN1bHQucmVzb2x2ZShyZXMpO1xuICAgIH0sIChlcnIpID0+IHtcbiAgICAgICAgcnVubmluZyA9IGZhbHNlO1xuICAgICAgICBjYWxsUmVzcG9uc2VzLmRlbGV0ZShpZCk7XG4gICAgICAgIHJlc3VsdC5yZWplY3QoZXJyKTtcbiAgICB9KTtcblxuICAgIGNvbnN0IGNhbmNlbCA9ICgpID0+IHtcbiAgICAgICAgY2FsbFJlc3BvbnNlcy5kZWxldGUoaWQpO1xuICAgICAgICByZXR1cm4gY2FuY2VsQ2FsbChDYW5jZWxNZXRob2QsIHtcImNhbGwtaWRcIjogaWR9KS5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3Igd2hpbGUgcmVxdWVzdGluZyBiaW5kaW5nIGNhbGwgY2FuY2VsbGF0aW9uOlwiLCBlcnIpO1xuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgcmVzdWx0Lm9uY2FuY2VsbGVkID0gKCkgPT4ge1xuICAgICAgICBpZiAocnVubmluZykge1xuICAgICAgICAgICAgcmV0dXJuIGNhbmNlbCgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHJlcXVlc3QudGhlbihjYW5jZWwpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiByZXN1bHQucHJvbWlzZTtcbn1cblxuLyoqXG4gKiBDYWxscyBhIGJvdW5kIG1ldGhvZCBieSBuYW1lIHdpdGggdGhlIHNwZWNpZmllZCBhcmd1bWVudHMuXG4gKiBTZWUge0BsaW5rIENhbGx9IGZvciBkZXRhaWxzLlxuICpcbiAqIEBwYXJhbSBtZXRob2ROYW1lIC0gVGhlIG5hbWUgb2YgdGhlIG1ldGhvZCBpbiB0aGUgZm9ybWF0ICdwYWNrYWdlLnN0cnVjdC5tZXRob2QnLlxuICogQHBhcmFtIGFyZ3MgLSBUaGUgYXJndW1lbnRzIHRvIHBhc3MgdG8gdGhlIG1ldGhvZC5cbiAqIEByZXR1cm5zIFRoZSByZXN1bHQgb2YgdGhlIG1ldGhvZCBjYWxsLlxuICovXG5leHBvcnQgZnVuY3Rpb24gQnlOYW1lKG1ldGhvZE5hbWU6IHN0cmluZywgLi4uYXJnczogYW55W10pOiBDYW5jZWxsYWJsZVByb21pc2U8YW55PiB7XG4gICAgcmV0dXJuIENhbGwoeyBtZXRob2ROYW1lLCBhcmdzIH0pO1xufVxuXG4vKipcbiAqIENhbGxzIGEgbWV0aG9kIGJ5IGl0cyBudW1lcmljIElEIHdpdGggdGhlIHNwZWNpZmllZCBhcmd1bWVudHMuXG4gKiBTZWUge0BsaW5rIENhbGx9IGZvciBkZXRhaWxzLlxuICpcbiAqIEBwYXJhbSBtZXRob2RJRCAtIFRoZSBJRCBvZiB0aGUgbWV0aG9kIHRvIGNhbGwuXG4gKiBAcGFyYW0gYXJncyAtIFRoZSBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgbWV0aG9kLlxuICogQHJldHVybiBUaGUgcmVzdWx0IG9mIHRoZSBtZXRob2QgY2FsbC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEJ5SUQobWV0aG9kSUQ6IG51bWJlciwgLi4uYXJnczogYW55W10pOiBDYW5jZWxsYWJsZVByb21pc2U8YW55PiB7XG4gICAgcmV0dXJuIENhbGwoeyBtZXRob2RJRCwgYXJncyB9KTtcbn1cbiIsICIvLyBTb3VyY2U6IGh0dHBzOi8vZ2l0aHViLmNvbS9pbnNwZWN0LWpzL2lzLWNhbGxhYmxlXG5cbi8vIFRoZSBNSVQgTGljZW5zZSAoTUlUKVxuLy9cbi8vIENvcHlyaWdodCAoYykgMjAxNSBKb3JkYW4gSGFyYmFuZFxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbi8vIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWxcbi8vIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHNcbi8vIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGxcbi8vIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuLy8gZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpbiBhbGxcbi8vIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuLy8gSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4vLyBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbi8vIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbi8vIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4vLyBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRVxuLy8gU09GVFdBUkUuXG5cbnZhciBmblRvU3RyID0gRnVuY3Rpb24ucHJvdG90eXBlLnRvU3RyaW5nO1xudmFyIHJlZmxlY3RBcHBseTogdHlwZW9mIFJlZmxlY3QuYXBwbHkgfCBmYWxzZSB8IG51bGwgPSB0eXBlb2YgUmVmbGVjdCA9PT0gJ29iamVjdCcgJiYgUmVmbGVjdCAhPT0gbnVsbCAmJiBSZWZsZWN0LmFwcGx5O1xudmFyIGJhZEFycmF5TGlrZTogYW55O1xudmFyIGlzQ2FsbGFibGVNYXJrZXI6IGFueTtcbmlmICh0eXBlb2YgcmVmbGVjdEFwcGx5ID09PSAnZnVuY3Rpb24nICYmIHR5cGVvZiBPYmplY3QuZGVmaW5lUHJvcGVydHkgPT09ICdmdW5jdGlvbicpIHtcbiAgICB0cnkge1xuICAgICAgICBiYWRBcnJheUxpa2UgPSBPYmplY3QuZGVmaW5lUHJvcGVydHkoe30sICdsZW5ndGgnLCB7XG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBpc0NhbGxhYmxlTWFya2VyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgaXNDYWxsYWJsZU1hcmtlciA9IHt9O1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdGhyb3ctbGl0ZXJhbFxuICAgICAgICByZWZsZWN0QXBwbHkoZnVuY3Rpb24gKCkgeyB0aHJvdyA0MjsgfSwgbnVsbCwgYmFkQXJyYXlMaWtlKTtcbiAgICB9IGNhdGNoIChfKSB7XG4gICAgICAgIGlmIChfICE9PSBpc0NhbGxhYmxlTWFya2VyKSB7XG4gICAgICAgICAgICByZWZsZWN0QXBwbHkgPSBudWxsO1xuICAgICAgICB9XG4gICAgfVxufSBlbHNlIHtcbiAgICByZWZsZWN0QXBwbHkgPSBudWxsO1xufVxuXG52YXIgY29uc3RydWN0b3JSZWdleCA9IC9eXFxzKmNsYXNzXFxiLztcbnZhciBpc0VTNkNsYXNzRm4gPSBmdW5jdGlvbiBpc0VTNkNsYXNzRnVuY3Rpb24odmFsdWU6IGFueSk6IGJvb2xlYW4ge1xuICAgIHRyeSB7XG4gICAgICAgIHZhciBmblN0ciA9IGZuVG9TdHIuY2FsbCh2YWx1ZSk7XG4gICAgICAgIHJldHVybiBjb25zdHJ1Y3RvclJlZ2V4LnRlc3QoZm5TdHIpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlOyAvLyBub3QgYSBmdW5jdGlvblxuICAgIH1cbn07XG5cbnZhciB0cnlGdW5jdGlvbk9iamVjdCA9IGZ1bmN0aW9uIHRyeUZ1bmN0aW9uVG9TdHIodmFsdWU6IGFueSk6IGJvb2xlYW4ge1xuICAgIHRyeSB7XG4gICAgICAgIGlmIChpc0VTNkNsYXNzRm4odmFsdWUpKSB7IHJldHVybiBmYWxzZTsgfVxuICAgICAgICBmblRvU3RyLmNhbGwodmFsdWUpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG59O1xudmFyIHRvU3RyID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZztcbnZhciBvYmplY3RDbGFzcyA9ICdbb2JqZWN0IE9iamVjdF0nO1xudmFyIGZuQ2xhc3MgPSAnW29iamVjdCBGdW5jdGlvbl0nO1xudmFyIGdlbkNsYXNzID0gJ1tvYmplY3QgR2VuZXJhdG9yRnVuY3Rpb25dJztcbnZhciBkZGFDbGFzcyA9ICdbb2JqZWN0IEhUTUxBbGxDb2xsZWN0aW9uXSc7IC8vIElFIDExXG52YXIgZGRhQ2xhc3MyID0gJ1tvYmplY3QgSFRNTCBkb2N1bWVudC5hbGwgY2xhc3NdJztcbnZhciBkZGFDbGFzczMgPSAnW29iamVjdCBIVE1MQ29sbGVjdGlvbl0nOyAvLyBJRSA5LTEwXG52YXIgaGFzVG9TdHJpbmdUYWcgPSB0eXBlb2YgU3ltYm9sID09PSAnZnVuY3Rpb24nICYmICEhU3ltYm9sLnRvU3RyaW5nVGFnOyAvLyBiZXR0ZXI6IHVzZSBgaGFzLXRvc3RyaW5ndGFnYFxuXG52YXIgaXNJRTY4ID0gISgwIGluIFssXSk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tc3BhcnNlLWFycmF5cywgY29tbWEtc3BhY2luZ1xuXG52YXIgaXNEREE6ICh2YWx1ZTogYW55KSA9PiBib29sZWFuID0gZnVuY3Rpb24gaXNEb2N1bWVudERvdEFsbCgpIHsgcmV0dXJuIGZhbHNlOyB9O1xuaWYgKHR5cGVvZiBkb2N1bWVudCA9PT0gJ29iamVjdCcpIHtcbiAgICAvLyBGaXJlZm94IDMgY2Fub25pY2FsaXplcyBEREEgdG8gdW5kZWZpbmVkIHdoZW4gaXQncyBub3QgYWNjZXNzZWQgZGlyZWN0bHlcbiAgICB2YXIgYWxsID0gZG9jdW1lbnQuYWxsO1xuICAgIGlmICh0b1N0ci5jYWxsKGFsbCkgPT09IHRvU3RyLmNhbGwoZG9jdW1lbnQuYWxsKSkge1xuICAgICAgICBpc0REQSA9IGZ1bmN0aW9uIGlzRG9jdW1lbnREb3RBbGwodmFsdWUpIHtcbiAgICAgICAgICAgIC8qIGdsb2JhbHMgZG9jdW1lbnQ6IGZhbHNlICovXG4gICAgICAgICAgICAvLyBpbiBJRSA2LTgsIHR5cGVvZiBkb2N1bWVudC5hbGwgaXMgXCJvYmplY3RcIiBhbmQgaXQncyB0cnV0aHlcbiAgICAgICAgICAgIGlmICgoaXNJRTY4IHx8ICF2YWx1ZSkgJiYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3VuZGVmaW5lZCcgfHwgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JykpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgc3RyID0gdG9TdHIuY2FsbCh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgICAgICAgICBzdHIgPT09IGRkYUNsYXNzXG4gICAgICAgICAgICAgICAgICAgICAgICB8fCBzdHIgPT09IGRkYUNsYXNzMlxuICAgICAgICAgICAgICAgICAgICAgICAgfHwgc3RyID09PSBkZGFDbGFzczMgLy8gb3BlcmEgMTIuMTZcbiAgICAgICAgICAgICAgICAgICAgICAgIHx8IHN0ciA9PT0gb2JqZWN0Q2xhc3MgLy8gSUUgNi04XG4gICAgICAgICAgICAgICAgICAgICkgJiYgdmFsdWUoJycpID09IG51bGw7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgZXFlcWVxXG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkgeyAvKiovIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGlzQ2FsbGFibGVSZWZBcHBseTxUPih2YWx1ZTogVCB8IHVua25vd24pOiB2YWx1ZSBpcyAoLi4uYXJnczogYW55W10pID0+IGFueSAge1xuICAgIGlmIChpc0REQSh2YWx1ZSkpIHsgcmV0dXJuIHRydWU7IH1cbiAgICBpZiAoIXZhbHVlKSB7IHJldHVybiBmYWxzZTsgfVxuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdmdW5jdGlvbicgJiYgdHlwZW9mIHZhbHVlICE9PSAnb2JqZWN0JykgeyByZXR1cm4gZmFsc2U7IH1cbiAgICB0cnkge1xuICAgICAgICAocmVmbGVjdEFwcGx5IGFzIGFueSkodmFsdWUsIG51bGwsIGJhZEFycmF5TGlrZSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoZSAhPT0gaXNDYWxsYWJsZU1hcmtlcikgeyByZXR1cm4gZmFsc2U7IH1cbiAgICB9XG4gICAgcmV0dXJuICFpc0VTNkNsYXNzRm4odmFsdWUpICYmIHRyeUZ1bmN0aW9uT2JqZWN0KHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaXNDYWxsYWJsZU5vUmVmQXBwbHk8VD4odmFsdWU6IFQgfCB1bmtub3duKTogdmFsdWUgaXMgKC4uLmFyZ3M6IGFueVtdKSA9PiBhbnkge1xuICAgIGlmIChpc0REQSh2YWx1ZSkpIHsgcmV0dXJuIHRydWU7IH1cbiAgICBpZiAoIXZhbHVlKSB7IHJldHVybiBmYWxzZTsgfVxuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdmdW5jdGlvbicgJiYgdHlwZW9mIHZhbHVlICE9PSAnb2JqZWN0JykgeyByZXR1cm4gZmFsc2U7IH1cbiAgICBpZiAoaGFzVG9TdHJpbmdUYWcpIHsgcmV0dXJuIHRyeUZ1bmN0aW9uT2JqZWN0KHZhbHVlKTsgfVxuICAgIGlmIChpc0VTNkNsYXNzRm4odmFsdWUpKSB7IHJldHVybiBmYWxzZTsgfVxuICAgIHZhciBzdHJDbGFzcyA9IHRvU3RyLmNhbGwodmFsdWUpO1xuICAgIGlmIChzdHJDbGFzcyAhPT0gZm5DbGFzcyAmJiBzdHJDbGFzcyAhPT0gZ2VuQ2xhc3MgJiYgISgvXlxcW29iamVjdCBIVE1MLykudGVzdChzdHJDbGFzcykpIHsgcmV0dXJuIGZhbHNlOyB9XG4gICAgcmV0dXJuIHRyeUZ1bmN0aW9uT2JqZWN0KHZhbHVlKTtcbn07XG5cbmV4cG9ydCBkZWZhdWx0IHJlZmxlY3RBcHBseSA/IGlzQ2FsbGFibGVSZWZBcHBseSA6IGlzQ2FsbGFibGVOb1JlZkFwcGx5O1xuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG5pbXBvcnQgaXNDYWxsYWJsZSBmcm9tIFwiLi9jYWxsYWJsZS5qc1wiO1xuXG4vKipcbiAqIEV4Y2VwdGlvbiBjbGFzcyB0aGF0IHdpbGwgYmUgdXNlZCBhcyByZWplY3Rpb24gcmVhc29uXG4gKiBpbiBjYXNlIGEge0BsaW5rIENhbmNlbGxhYmxlUHJvbWlzZX0gaXMgY2FuY2VsbGVkIHN1Y2Nlc3NmdWxseS5cbiAqXG4gKiBUaGUgdmFsdWUgb2YgdGhlIHtAbGluayBuYW1lfSBwcm9wZXJ0eSBpcyB0aGUgc3RyaW5nIGBcIkNhbmNlbEVycm9yXCJgLlxuICogVGhlIHZhbHVlIG9mIHRoZSB7QGxpbmsgY2F1c2V9IHByb3BlcnR5IGlzIHRoZSBjYXVzZSBwYXNzZWQgdG8gdGhlIGNhbmNlbCBtZXRob2QsIGlmIGFueS5cbiAqL1xuZXhwb3J0IGNsYXNzIENhbmNlbEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICAgIC8qKlxuICAgICAqIENvbnN0cnVjdHMgYSBuZXcgYENhbmNlbEVycm9yYCBpbnN0YW5jZS5cbiAgICAgKiBAcGFyYW0gbWVzc2FnZSAtIFRoZSBlcnJvciBtZXNzYWdlLlxuICAgICAqIEBwYXJhbSBvcHRpb25zIC0gT3B0aW9ucyB0byBiZSBmb3J3YXJkZWQgdG8gdGhlIEVycm9yIGNvbnN0cnVjdG9yLlxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKG1lc3NhZ2U/OiBzdHJpbmcsIG9wdGlvbnM/OiBFcnJvck9wdGlvbnMpIHtcbiAgICAgICAgc3VwZXIobWVzc2FnZSwgb3B0aW9ucyk7XG4gICAgICAgIHRoaXMubmFtZSA9IFwiQ2FuY2VsRXJyb3JcIjtcbiAgICB9XG59XG5cbi8qKlxuICogRXhjZXB0aW9uIGNsYXNzIHRoYXQgd2lsbCBiZSByZXBvcnRlZCBhcyBhbiB1bmhhbmRsZWQgcmVqZWN0aW9uXG4gKiBpbiBjYXNlIGEge0BsaW5rIENhbmNlbGxhYmxlUHJvbWlzZX0gcmVqZWN0cyBhZnRlciBiZWluZyBjYW5jZWxsZWQsXG4gKiBvciB3aGVuIHRoZSBgb25jYW5jZWxsZWRgIGNhbGxiYWNrIHRocm93cyBvciByZWplY3RzLlxuICpcbiAqIFRoZSB2YWx1ZSBvZiB0aGUge0BsaW5rIG5hbWV9IHByb3BlcnR5IGlzIHRoZSBzdHJpbmcgYFwiQ2FuY2VsbGVkUmVqZWN0aW9uRXJyb3JcImAuXG4gKiBUaGUgdmFsdWUgb2YgdGhlIHtAbGluayBjYXVzZX0gcHJvcGVydHkgaXMgdGhlIHJlYXNvbiB0aGUgcHJvbWlzZSByZWplY3RlZCB3aXRoLlxuICpcbiAqIEJlY2F1c2UgdGhlIG9yaWdpbmFsIHByb21pc2Ugd2FzIGNhbmNlbGxlZCxcbiAqIGEgd3JhcHBlciBwcm9taXNlIHdpbGwgYmUgcGFzc2VkIHRvIHRoZSB1bmhhbmRsZWQgcmVqZWN0aW9uIGxpc3RlbmVyIGluc3RlYWQuXG4gKiBUaGUge0BsaW5rIHByb21pc2V9IHByb3BlcnR5IGhvbGRzIGEgcmVmZXJlbmNlIHRvIHRoZSBvcmlnaW5hbCBwcm9taXNlLlxuICovXG5leHBvcnQgY2xhc3MgQ2FuY2VsbGVkUmVqZWN0aW9uRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gICAgLyoqXG4gICAgICogSG9sZHMgYSByZWZlcmVuY2UgdG8gdGhlIHByb21pc2UgdGhhdCB3YXMgY2FuY2VsbGVkIGFuZCB0aGVuIHJlamVjdGVkLlxuICAgICAqL1xuICAgIHByb21pc2U6IENhbmNlbGxhYmxlUHJvbWlzZTx1bmtub3duPjtcblxuICAgIC8qKlxuICAgICAqIENvbnN0cnVjdHMgYSBuZXcgYENhbmNlbGxlZFJlamVjdGlvbkVycm9yYCBpbnN0YW5jZS5cbiAgICAgKiBAcGFyYW0gcHJvbWlzZSAtIFRoZSBwcm9taXNlIHRoYXQgY2F1c2VkIHRoZSBlcnJvciBvcmlnaW5hbGx5LlxuICAgICAqIEBwYXJhbSByZWFzb24gLSBUaGUgcmVqZWN0aW9uIHJlYXNvbi5cbiAgICAgKiBAcGFyYW0gaW5mbyAtIEFuIG9wdGlvbmFsIGluZm9ybWF0aXZlIG1lc3NhZ2Ugc3BlY2lmeWluZyB0aGUgY2lyY3Vtc3RhbmNlcyBpbiB3aGljaCB0aGUgZXJyb3Igd2FzIHRocm93bi5cbiAgICAgKiAgICAgICAgICAgICAgIERlZmF1bHRzIHRvIHRoZSBzdHJpbmcgYFwiVW5oYW5kbGVkIHJlamVjdGlvbiBpbiBjYW5jZWxsZWQgcHJvbWlzZS5cImAuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IocHJvbWlzZTogQ2FuY2VsbGFibGVQcm9taXNlPHVua25vd24+LCByZWFzb24/OiBhbnksIGluZm8/OiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoKGluZm8gPz8gXCJVbmhhbmRsZWQgcmVqZWN0aW9uIGluIGNhbmNlbGxlZCBwcm9taXNlLlwiKSArIFwiIFJlYXNvbjogXCIgKyBlcnJvck1lc3NhZ2UocmVhc29uKSwgeyBjYXVzZTogcmVhc29uIH0pO1xuICAgICAgICB0aGlzLnByb21pc2UgPSBwcm9taXNlO1xuICAgICAgICB0aGlzLm5hbWUgPSBcIkNhbmNlbGxlZFJlamVjdGlvbkVycm9yXCI7XG4gICAgfVxufVxuXG50eXBlIENhbmNlbGxhYmxlUHJvbWlzZVJlc29sdmVyPFQ+ID0gKHZhbHVlOiBUIHwgUHJvbWlzZUxpa2U8VD4gfCBDYW5jZWxsYWJsZVByb21pc2VMaWtlPFQ+KSA9PiB2b2lkO1xudHlwZSBDYW5jZWxsYWJsZVByb21pc2VSZWplY3RvciA9IChyZWFzb24/OiBhbnkpID0+IHZvaWQ7XG50eXBlIENhbmNlbGxhYmxlUHJvbWlzZUNhbmNlbGxlciA9IChjYXVzZT86IGFueSkgPT4gdm9pZCB8IFByb21pc2VMaWtlPHZvaWQ+O1xudHlwZSBDYW5jZWxsYWJsZVByb21pc2VFeGVjdXRvcjxUPiA9IChyZXNvbHZlOiBDYW5jZWxsYWJsZVByb21pc2VSZXNvbHZlcjxUPiwgcmVqZWN0OiBDYW5jZWxsYWJsZVByb21pc2VSZWplY3RvcikgPT4gdm9pZDtcblxuZXhwb3J0IGludGVyZmFjZSBDYW5jZWxsYWJsZVByb21pc2VMaWtlPFQ+IHtcbiAgICB0aGVuPFRSZXN1bHQxID0gVCwgVFJlc3VsdDIgPSBuZXZlcj4ob25mdWxmaWxsZWQ/OiAoKHZhbHVlOiBUKSA9PiBUUmVzdWx0MSB8IFByb21pc2VMaWtlPFRSZXN1bHQxPiB8IENhbmNlbGxhYmxlUHJvbWlzZUxpa2U8VFJlc3VsdDE+KSB8IHVuZGVmaW5lZCB8IG51bGwsIG9ucmVqZWN0ZWQ/OiAoKHJlYXNvbjogYW55KSA9PiBUUmVzdWx0MiB8IFByb21pc2VMaWtlPFRSZXN1bHQyPiB8IENhbmNlbGxhYmxlUHJvbWlzZUxpa2U8VFJlc3VsdDI+KSB8IHVuZGVmaW5lZCB8IG51bGwpOiBDYW5jZWxsYWJsZVByb21pc2VMaWtlPFRSZXN1bHQxIHwgVFJlc3VsdDI+O1xuICAgIGNhbmNlbChjYXVzZT86IGFueSk6IHZvaWQgfCBQcm9taXNlTGlrZTx2b2lkPjtcbn1cblxuLyoqXG4gKiBXcmFwcyBhIGNhbmNlbGxhYmxlIHByb21pc2UgYWxvbmcgd2l0aCBpdHMgcmVzb2x1dGlvbiBtZXRob2RzLlxuICogVGhlIGBvbmNhbmNlbGxlZGAgZmllbGQgd2lsbCBiZSBudWxsIGluaXRpYWxseSBidXQgbWF5IGJlIHNldCB0byBwcm92aWRlIGEgY3VzdG9tIGNhbmNlbGxhdGlvbiBmdW5jdGlvbi5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDYW5jZWxsYWJsZVByb21pc2VXaXRoUmVzb2x2ZXJzPFQ+IHtcbiAgICBwcm9taXNlOiBDYW5jZWxsYWJsZVByb21pc2U8VD47XG4gICAgcmVzb2x2ZTogQ2FuY2VsbGFibGVQcm9taXNlUmVzb2x2ZXI8VD47XG4gICAgcmVqZWN0OiBDYW5jZWxsYWJsZVByb21pc2VSZWplY3RvcjtcbiAgICBvbmNhbmNlbGxlZDogQ2FuY2VsbGFibGVQcm9taXNlQ2FuY2VsbGVyIHwgbnVsbDtcbn1cblxuaW50ZXJmYWNlIENhbmNlbGxhYmxlUHJvbWlzZVN0YXRlIHtcbiAgICByZWFkb25seSByb290OiBDYW5jZWxsYWJsZVByb21pc2VTdGF0ZTtcbiAgICByZXNvbHZpbmc6IGJvb2xlYW47XG4gICAgc2V0dGxlZDogYm9vbGVhbjtcbiAgICByZWFzb24/OiBDYW5jZWxFcnJvcjtcbn1cblxuLy8gUHJpdmF0ZSBmaWVsZCBuYW1lcy5cbmNvbnN0IGJhcnJpZXJTeW0gPSBTeW1ib2woXCJiYXJyaWVyXCIpO1xuY29uc3QgY2FuY2VsSW1wbFN5bSA9IFN5bWJvbChcImNhbmNlbEltcGxcIik7XG5jb25zdCBzcGVjaWVzOiB0eXBlb2YgU3ltYm9sLnNwZWNpZXMgPSBTeW1ib2wuc3BlY2llcyA/PyBTeW1ib2woXCJzcGVjaWVzUG9seWZpbGxcIik7XG5cbi8qKlxuICogQSBwcm9taXNlIHdpdGggYW4gYXR0YWNoZWQgbWV0aG9kIGZvciBjYW5jZWxsaW5nIGxvbmctcnVubmluZyBvcGVyYXRpb25zIChzZWUge0BsaW5rIENhbmNlbGxhYmxlUHJvbWlzZSNjYW5jZWx9KS5cbiAqIENhbmNlbGxhdGlvbiBjYW4gb3B0aW9uYWxseSBiZSBib3VuZCB0byBhbiB7QGxpbmsgQWJvcnRTaWduYWx9XG4gKiBmb3IgYmV0dGVyIGNvbXBvc2FiaWxpdHkgKHNlZSB7QGxpbmsgQ2FuY2VsbGFibGVQcm9taXNlI2NhbmNlbE9ufSkuXG4gKlxuICogQ2FuY2VsbGluZyBhIHBlbmRpbmcgcHJvbWlzZSB3aWxsIHJlc3VsdCBpbiBhbiBpbW1lZGlhdGUgcmVqZWN0aW9uXG4gKiB3aXRoIGFuIGluc3RhbmNlIG9mIHtAbGluayBDYW5jZWxFcnJvcn0gYXMgcmVhc29uLFxuICogYnV0IHdob2V2ZXIgc3RhcnRlZCB0aGUgcHJvbWlzZSB3aWxsIGJlIHJlc3BvbnNpYmxlXG4gKiBmb3IgYWN0dWFsbHkgYWJvcnRpbmcgdGhlIHVuZGVybHlpbmcgb3BlcmF0aW9uLlxuICogVG8gdGhpcyBwdXJwb3NlLCB0aGUgY29uc3RydWN0b3IgYW5kIGFsbCBjaGFpbmluZyBtZXRob2RzXG4gKiBhY2NlcHQgb3B0aW9uYWwgY2FuY2VsbGF0aW9uIGNhbGxiYWNrcy5cbiAqXG4gKiBJZiBhIGBDYW5jZWxsYWJsZVByb21pc2VgIHN0aWxsIHJlc29sdmVzIGFmdGVyIGhhdmluZyBiZWVuIGNhbmNlbGxlZCxcbiAqIHRoZSByZXN1bHQgd2lsbCBiZSBkaXNjYXJkZWQuIElmIGl0IHJlamVjdHMsIHRoZSByZWFzb25cbiAqIHdpbGwgYmUgcmVwb3J0ZWQgYXMgYW4gdW5oYW5kbGVkIHJlamVjdGlvbixcbiAqIHdyYXBwZWQgaW4gYSB7QGxpbmsgQ2FuY2VsbGVkUmVqZWN0aW9uRXJyb3J9IGluc3RhbmNlLlxuICogVG8gZmFjaWxpdGF0ZSB0aGUgaGFuZGxpbmcgb2YgY2FuY2VsbGF0aW9uIHJlcXVlc3RzLFxuICogY2FuY2VsbGVkIGBDYW5jZWxsYWJsZVByb21pc2VgcyB3aWxsIF9ub3RfIHJlcG9ydCB1bmhhbmRsZWQgYENhbmNlbEVycm9yYHNcbiAqIHdob3NlIGBjYXVzZWAgZmllbGQgaXMgdGhlIHNhbWUgYXMgdGhlIG9uZSB3aXRoIHdoaWNoIHRoZSBjdXJyZW50IHByb21pc2Ugd2FzIGNhbmNlbGxlZC5cbiAqXG4gKiBBbGwgdXN1YWwgcHJvbWlzZSBtZXRob2RzIGFyZSBkZWZpbmVkIGFuZCByZXR1cm4gYSBgQ2FuY2VsbGFibGVQcm9taXNlYFxuICogd2hvc2UgY2FuY2VsIG1ldGhvZCB3aWxsIGNhbmNlbCB0aGUgcGFyZW50IG9wZXJhdGlvbiBhcyB3ZWxsLCBwcm9wYWdhdGluZyB0aGUgY2FuY2VsbGF0aW9uIHJlYXNvblxuICogdXB3YXJkcyB0aHJvdWdoIHByb21pc2UgY2hhaW5zLlxuICogQ29udmVyc2VseSwgY2FuY2VsbGluZyBhIHByb21pc2Ugd2lsbCBub3QgYXV0b21hdGljYWxseSBjYW5jZWwgZGVwZW5kZW50IHByb21pc2VzIGRvd25zdHJlYW06XG4gKiBgYGB0c1xuICogbGV0IHJvb3QgPSBuZXcgQ2FuY2VsbGFibGVQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHsgLi4uIH0pO1xuICogbGV0IGNoaWxkMSA9IHJvb3QudGhlbigoKSA9PiB7IC4uLiB9KTtcbiAqIGxldCBjaGlsZDIgPSBjaGlsZDEudGhlbigoKSA9PiB7IC4uLiB9KTtcbiAqIGxldCBjaGlsZDMgPSByb290LmNhdGNoKCgpID0+IHsgLi4uIH0pO1xuICogY2hpbGQxLmNhbmNlbCgpOyAvLyBDYW5jZWxzIGNoaWxkMSBhbmQgcm9vdCwgYnV0IG5vdCBjaGlsZDIgb3IgY2hpbGQzXG4gKiBgYGBcbiAqIENhbmNlbGxpbmcgYSBwcm9taXNlIHRoYXQgaGFzIGFscmVhZHkgc2V0dGxlZCBpcyBzYWZlIGFuZCBoYXMgbm8gY29uc2VxdWVuY2UuXG4gKlxuICogVGhlIGBjYW5jZWxgIG1ldGhvZCByZXR1cm5zIGEgcHJvbWlzZSB0aGF0IF9hbHdheXMgZnVsZmlsbHNfXG4gKiBhZnRlciB0aGUgd2hvbGUgY2hhaW4gaGFzIHByb2Nlc3NlZCB0aGUgY2FuY2VsIHJlcXVlc3RcbiAqIGFuZCBhbGwgYXR0YWNoZWQgY2FsbGJhY2tzIHVwIHRvIHRoYXQgbW9tZW50IGhhdmUgcnVuLlxuICpcbiAqIEFsbCBFUzIwMjQgcHJvbWlzZSBtZXRob2RzIChzdGF0aWMgYW5kIGluc3RhbmNlKSBhcmUgZGVmaW5lZCBvbiBDYW5jZWxsYWJsZVByb21pc2UsXG4gKiBidXQgYWN0dWFsIGF2YWlsYWJpbGl0eSBtYXkgdmFyeSB3aXRoIE9TL3dlYnZpZXcgdmVyc2lvbi5cbiAqXG4gKiBJbiBsaW5lIHdpdGggdGhlIHByb3Bvc2FsIGF0IGh0dHBzOi8vZ2l0aHViLmNvbS90YzM5L3Byb3Bvc2FsLXJtLWJ1aWx0aW4tc3ViY2xhc3NpbmcsXG4gKiBgQ2FuY2VsbGFibGVQcm9taXNlYCBkb2VzIG5vdCBzdXBwb3J0IHRyYW5zcGFyZW50IHN1YmNsYXNzaW5nLlxuICogRXh0ZW5kZXJzIHNob3VsZCB0YWtlIGNhcmUgdG8gcHJvdmlkZSB0aGVpciBvd24gbWV0aG9kIGltcGxlbWVudGF0aW9ucy5cbiAqIFRoaXMgbWlnaHQgYmUgcmVjb25zaWRlcmVkIGluIGNhc2UgdGhlIHByb3Bvc2FsIGlzIHJldGlyZWQuXG4gKlxuICogQ2FuY2VsbGFibGVQcm9taXNlIGlzIGEgd3JhcHBlciBhcm91bmQgdGhlIERPTSBQcm9taXNlIG9iamVjdFxuICogYW5kIGlzIGNvbXBsaWFudCB3aXRoIHRoZSBbUHJvbWlzZXMvQSsgc3BlY2lmaWNhdGlvbl0oaHR0cHM6Ly9wcm9taXNlc2FwbHVzLmNvbS8pXG4gKiAoaXQgcGFzc2VzIHRoZSBbY29tcGxpYW5jZSBzdWl0ZV0oaHR0cHM6Ly9naXRodWIuY29tL3Byb21pc2VzLWFwbHVzL3Byb21pc2VzLXRlc3RzKSlcbiAqIGlmIHNvIGlzIHRoZSB1bmRlcmx5aW5nIGltcGxlbWVudGF0aW9uLlxuICovXG5leHBvcnQgY2xhc3MgQ2FuY2VsbGFibGVQcm9taXNlPFQ+IGV4dGVuZHMgUHJvbWlzZTxUPiBpbXBsZW1lbnRzIFByb21pc2VMaWtlPFQ+LCBDYW5jZWxsYWJsZVByb21pc2VMaWtlPFQ+IHtcbiAgICAvLyBQcml2YXRlIGZpZWxkcy5cbiAgICAvKiogQGludGVybmFsICovXG4gICAgcHJpdmF0ZSBbYmFycmllclN5bV0hOiBQYXJ0aWFsPFByb21pc2VXaXRoUmVzb2x2ZXJzPHZvaWQ+PiB8IG51bGw7XG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgW2NhbmNlbEltcGxTeW1dITogKHJlYXNvbjogQ2FuY2VsRXJyb3IpID0+IHZvaWQgfCBQcm9taXNlTGlrZTx2b2lkPjtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgYENhbmNlbGxhYmxlUHJvbWlzZWAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZXhlY3V0b3IgLSBBIGNhbGxiYWNrIHVzZWQgdG8gaW5pdGlhbGl6ZSB0aGUgcHJvbWlzZS4gVGhpcyBjYWxsYmFjayBpcyBwYXNzZWQgdHdvIGFyZ3VtZW50czpcbiAgICAgKiAgICAgICAgICAgICAgICAgICBhIGByZXNvbHZlYCBjYWxsYmFjayB1c2VkIHRvIHJlc29sdmUgdGhlIHByb21pc2Ugd2l0aCBhIHZhbHVlXG4gICAgICogICAgICAgICAgICAgICAgICAgb3IgdGhlIHJlc3VsdCBvZiBhbm90aGVyIHByb21pc2UgKHBvc3NpYmx5IGNhbmNlbGxhYmxlKSxcbiAgICAgKiAgICAgICAgICAgICAgICAgICBhbmQgYSBgcmVqZWN0YCBjYWxsYmFjayB1c2VkIHRvIHJlamVjdCB0aGUgcHJvbWlzZSB3aXRoIGEgcHJvdmlkZWQgcmVhc29uIG9yIGVycm9yLlxuICAgICAqICAgICAgICAgICAgICAgICAgIElmIHRoZSB2YWx1ZSBwcm92aWRlZCB0byB0aGUgYHJlc29sdmVgIGNhbGxiYWNrIGlzIGEgdGhlbmFibGUgX2FuZF8gY2FuY2VsbGFibGUgb2JqZWN0XG4gICAgICogICAgICAgICAgICAgICAgICAgKGl0IGhhcyBhIGB0aGVuYCBfYW5kXyBhIGBjYW5jZWxgIG1ldGhvZCksXG4gICAgICogICAgICAgICAgICAgICAgICAgY2FuY2VsbGF0aW9uIHJlcXVlc3RzIHdpbGwgYmUgZm9yd2FyZGVkIHRvIHRoYXQgb2JqZWN0IGFuZCB0aGUgb25jYW5jZWxsZWQgd2lsbCBub3QgYmUgaW52b2tlZCBhbnltb3JlLlxuICAgICAqICAgICAgICAgICAgICAgICAgIElmIGFueSBvbmUgb2YgdGhlIHR3byBjYWxsYmFja3MgaXMgY2FsbGVkIF9hZnRlcl8gdGhlIHByb21pc2UgaGFzIGJlZW4gY2FuY2VsbGVkLFxuICAgICAqICAgICAgICAgICAgICAgICAgIHRoZSBwcm92aWRlZCB2YWx1ZXMgd2lsbCBiZSBjYW5jZWxsZWQgYW5kIHJlc29sdmVkIGFzIHVzdWFsLFxuICAgICAqICAgICAgICAgICAgICAgICAgIGJ1dCB0aGVpciByZXN1bHRzIHdpbGwgYmUgZGlzY2FyZGVkLlxuICAgICAqICAgICAgICAgICAgICAgICAgIEhvd2V2ZXIsIGlmIHRoZSByZXNvbHV0aW9uIHByb2Nlc3MgdWx0aW1hdGVseSBlbmRzIHVwIGluIGEgcmVqZWN0aW9uXG4gICAgICogICAgICAgICAgICAgICAgICAgdGhhdCBpcyBub3QgZHVlIHRvIGNhbmNlbGxhdGlvbiwgdGhlIHJlamVjdGlvbiByZWFzb25cbiAgICAgKiAgICAgICAgICAgICAgICAgICB3aWxsIGJlIHdyYXBwZWQgaW4gYSB7QGxpbmsgQ2FuY2VsbGVkUmVqZWN0aW9uRXJyb3J9XG4gICAgICogICAgICAgICAgICAgICAgICAgYW5kIGJ1YmJsZWQgdXAgYXMgYW4gdW5oYW5kbGVkIHJlamVjdGlvbi5cbiAgICAgKiBAcGFyYW0gb25jYW5jZWxsZWQgLSBJdCBpcyB0aGUgY2FsbGVyJ3MgcmVzcG9uc2liaWxpdHkgdG8gZW5zdXJlIHRoYXQgYW55IG9wZXJhdGlvblxuICAgICAqICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0ZWQgYnkgdGhlIGV4ZWN1dG9yIGlzIHByb3Blcmx5IGhhbHRlZCB1cG9uIGNhbmNlbGxhdGlvbi5cbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICBUaGlzIG9wdGlvbmFsIGNhbGxiYWNrIGNhbiBiZSB1c2VkIHRvIHRoYXQgcHVycG9zZS5cbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICBJdCB3aWxsIGJlIGNhbGxlZCBfc3luY2hyb25vdXNseV8gd2l0aCBhIGNhbmNlbGxhdGlvbiBjYXVzZVxuICAgICAqICAgICAgICAgICAgICAgICAgICAgIHdoZW4gY2FuY2VsbGF0aW9uIGlzIHJlcXVlc3RlZCwgX2FmdGVyXyB0aGUgcHJvbWlzZSBoYXMgYWxyZWFkeSByZWplY3RlZFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgIHdpdGggYSB7QGxpbmsgQ2FuY2VsRXJyb3J9LCBidXQgX2JlZm9yZV9cbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICBhbnkge0BsaW5rIHRoZW59L3tAbGluayBjYXRjaH0ve0BsaW5rIGZpbmFsbHl9IGNhbGxiYWNrIHJ1bnMuXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgSWYgdGhlIGNhbGxiYWNrIHJldHVybnMgYSB0aGVuYWJsZSwgdGhlIHByb21pc2UgcmV0dXJuZWQgZnJvbSB7QGxpbmsgY2FuY2VsfVxuICAgICAqICAgICAgICAgICAgICAgICAgICAgIHdpbGwgb25seSBmdWxmaWxsIGFmdGVyIHRoZSBmb3JtZXIgaGFzIHNldHRsZWQuXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgVW5oYW5kbGVkIGV4Y2VwdGlvbnMgb3IgcmVqZWN0aW9ucyBmcm9tIHRoZSBjYWxsYmFjayB3aWxsIGJlIHdyYXBwZWRcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICBpbiBhIHtAbGluayBDYW5jZWxsZWRSZWplY3Rpb25FcnJvcn0gYW5kIGJ1YmJsZWQgdXAgYXMgdW5oYW5kbGVkIHJlamVjdGlvbnMuXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgSWYgdGhlIGByZXNvbHZlYCBjYWxsYmFjayBpcyBjYWxsZWQgYmVmb3JlIGNhbmNlbGxhdGlvbiB3aXRoIGEgY2FuY2VsbGFibGUgcHJvbWlzZSxcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICBjYW5jZWxsYXRpb24gcmVxdWVzdHMgb24gdGhpcyBwcm9taXNlIHdpbGwgYmUgZGl2ZXJ0ZWQgdG8gdGhhdCBwcm9taXNlLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgIGFuZCB0aGUgb3JpZ2luYWwgYG9uY2FuY2VsbGVkYCBjYWxsYmFjayB3aWxsIGJlIGRpc2NhcmRlZC5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihleGVjdXRvcjogQ2FuY2VsbGFibGVQcm9taXNlRXhlY3V0b3I8VD4sIG9uY2FuY2VsbGVkPzogQ2FuY2VsbGFibGVQcm9taXNlQ2FuY2VsbGVyKSB7XG4gICAgICAgIGxldCByZXNvbHZlITogKHZhbHVlOiBUIHwgUHJvbWlzZUxpa2U8VD4pID0+IHZvaWQ7XG4gICAgICAgIGxldCByZWplY3QhOiAocmVhc29uPzogYW55KSA9PiB2b2lkO1xuICAgICAgICBzdXBlcigocmVzLCByZWopID0+IHsgcmVzb2x2ZSA9IHJlczsgcmVqZWN0ID0gcmVqOyB9KTtcblxuICAgICAgICBpZiAoKHRoaXMuY29uc3RydWN0b3IgYXMgYW55KVtzcGVjaWVzXSAhPT0gUHJvbWlzZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbmNlbGxhYmxlUHJvbWlzZSBkb2VzIG5vdCBzdXBwb3J0IHRyYW5zcGFyZW50IHN1YmNsYXNzaW5nLiBQbGVhc2UgcmVmcmFpbiBmcm9tIG92ZXJyaWRpbmcgdGhlIFtTeW1ib2wuc3BlY2llc10gc3RhdGljIHByb3BlcnR5LlwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBwcm9taXNlOiBDYW5jZWxsYWJsZVByb21pc2VXaXRoUmVzb2x2ZXJzPFQ+ID0ge1xuICAgICAgICAgICAgcHJvbWlzZTogdGhpcyxcbiAgICAgICAgICAgIHJlc29sdmUsXG4gICAgICAgICAgICByZWplY3QsXG4gICAgICAgICAgICBnZXQgb25jYW5jZWxsZWQoKSB7IHJldHVybiBvbmNhbmNlbGxlZCA/PyBudWxsOyB9LFxuICAgICAgICAgICAgc2V0IG9uY2FuY2VsbGVkKGNiKSB7IG9uY2FuY2VsbGVkID0gY2IgPz8gdW5kZWZpbmVkOyB9XG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3Qgc3RhdGU6IENhbmNlbGxhYmxlUHJvbWlzZVN0YXRlID0ge1xuICAgICAgICAgICAgZ2V0IHJvb3QoKSB7IHJldHVybiBzdGF0ZTsgfSxcbiAgICAgICAgICAgIHJlc29sdmluZzogZmFsc2UsXG4gICAgICAgICAgICBzZXR0bGVkOiBmYWxzZVxuICAgICAgICB9O1xuXG4gICAgICAgIC8vIFNldHVwIGNhbmNlbGxhdGlvbiBzeXN0ZW0uXG4gICAgICAgIHZvaWQgT2JqZWN0LmRlZmluZVByb3BlcnRpZXModGhpcywge1xuICAgICAgICAgICAgW2JhcnJpZXJTeW1dOiB7XG4gICAgICAgICAgICAgICAgY29uZmlndXJhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICB2YWx1ZTogbnVsbFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFtjYW5jZWxJbXBsU3ltXToge1xuICAgICAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgd3JpdGFibGU6IGZhbHNlLFxuICAgICAgICAgICAgICAgIHZhbHVlOiBjYW5jZWxsZXJGb3IocHJvbWlzZSwgc3RhdGUpXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIFJ1biB0aGUgYWN0dWFsIGV4ZWN1dG9yLlxuICAgICAgICBjb25zdCByZWplY3RvciA9IHJlamVjdG9yRm9yKHByb21pc2UsIHN0YXRlKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGV4ZWN1dG9yKHJlc29sdmVyRm9yKHByb21pc2UsIHN0YXRlKSwgcmVqZWN0b3IpO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGlmIChzdGF0ZS5yZXNvbHZpbmcpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIlVuaGFuZGxlZCBleGNlcHRpb24gaW4gQ2FuY2VsbGFibGVQcm9taXNlIGV4ZWN1dG9yLlwiLCBlcnIpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZWplY3RvcihlcnIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2FuY2VscyBpbW1lZGlhdGVseSB0aGUgZXhlY3V0aW9uIG9mIHRoZSBvcGVyYXRpb24gYXNzb2NpYXRlZCB3aXRoIHRoaXMgcHJvbWlzZS5cbiAgICAgKiBUaGUgcHJvbWlzZSByZWplY3RzIHdpdGggYSB7QGxpbmsgQ2FuY2VsRXJyb3J9IGluc3RhbmNlIGFzIHJlYXNvbixcbiAgICAgKiB3aXRoIHRoZSB7QGxpbmsgQ2FuY2VsRXJyb3IjY2F1c2V9IHByb3BlcnR5IHNldCB0byB0aGUgZ2l2ZW4gYXJndW1lbnQsIGlmIGFueS5cbiAgICAgKlxuICAgICAqIEhhcyBubyBlZmZlY3QgaWYgY2FsbGVkIGFmdGVyIHRoZSBwcm9taXNlIGhhcyBhbHJlYWR5IHNldHRsZWQ7XG4gICAgICogcmVwZWF0ZWQgY2FsbHMgaW4gcGFydGljdWxhciBhcmUgc2FmZSwgYnV0IG9ubHkgdGhlIGZpcnN0IG9uZVxuICAgICAqIHdpbGwgc2V0IHRoZSBjYW5jZWxsYXRpb24gY2F1c2UuXG4gICAgICpcbiAgICAgKiBUaGUgYENhbmNlbEVycm9yYCBleGNlcHRpb24gX25lZWQgbm90XyBiZSBoYW5kbGVkIGV4cGxpY2l0bHkgX29uIHRoZSBwcm9taXNlcyB0aGF0IGFyZSBiZWluZyBjYW5jZWxsZWQ6X1xuICAgICAqIGNhbmNlbGxpbmcgYSBwcm9taXNlIHdpdGggbm8gYXR0YWNoZWQgcmVqZWN0aW9uIGhhbmRsZXIgZG9lcyBub3QgdHJpZ2dlciBhbiB1bmhhbmRsZWQgcmVqZWN0aW9uIGV2ZW50LlxuICAgICAqIFRoZXJlZm9yZSwgdGhlIGZvbGxvd2luZyBpZGlvbXMgYXJlIGFsbCBlcXVhbGx5IGNvcnJlY3Q6XG4gICAgICogYGBgdHNcbiAgICAgKiBuZXcgQ2FuY2VsbGFibGVQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHsgLi4uIH0pLmNhbmNlbCgpO1xuICAgICAqIG5ldyBDYW5jZWxsYWJsZVByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4geyAuLi4gfSkudGhlbiguLi4pLmNhbmNlbCgpO1xuICAgICAqIG5ldyBDYW5jZWxsYWJsZVByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4geyAuLi4gfSkudGhlbiguLi4pLmNhdGNoKC4uLikuY2FuY2VsKCk7XG4gICAgICogYGBgXG4gICAgICogV2hlbmV2ZXIgc29tZSBjYW5jZWxsZWQgcHJvbWlzZSBpbiBhIGNoYWluIHJlamVjdHMgd2l0aCBhIGBDYW5jZWxFcnJvcmBcbiAgICAgKiB3aXRoIHRoZSBzYW1lIGNhbmNlbGxhdGlvbiBjYXVzZSBhcyBpdHNlbGYsIHRoZSBlcnJvciB3aWxsIGJlIGRpc2NhcmRlZCBzaWxlbnRseS5cbiAgICAgKiBIb3dldmVyLCB0aGUgYENhbmNlbEVycm9yYCBfd2lsbCBzdGlsbCBiZSBkZWxpdmVyZWRfIHRvIGFsbCBhdHRhY2hlZCByZWplY3Rpb24gaGFuZGxlcnNcbiAgICAgKiBhZGRlZCBieSB7QGxpbmsgdGhlbn0gYW5kIHJlbGF0ZWQgbWV0aG9kczpcbiAgICAgKiBgYGB0c1xuICAgICAqIGxldCBjYW5jZWxsYWJsZSA9IG5ldyBDYW5jZWxsYWJsZVByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4geyAuLi4gfSk7XG4gICAgICogY2FuY2VsbGFibGUudGhlbigoKSA9PiB7IC4uLiB9KS5jYXRjaChjb25zb2xlLmxvZyk7XG4gICAgICogY2FuY2VsbGFibGUuY2FuY2VsKCk7IC8vIEEgQ2FuY2VsRXJyb3IgaXMgcHJpbnRlZCB0byB0aGUgY29uc29sZS5cbiAgICAgKiBgYGBcbiAgICAgKiBJZiB0aGUgYENhbmNlbEVycm9yYCBpcyBub3QgaGFuZGxlZCBkb3duc3RyZWFtIGJ5IHRoZSB0aW1lIGl0IHJlYWNoZXNcbiAgICAgKiBhIF9ub24tY2FuY2VsbGVkXyBwcm9taXNlLCBpdCBfd2lsbF8gdHJpZ2dlciBhbiB1bmhhbmRsZWQgcmVqZWN0aW9uIGV2ZW50LFxuICAgICAqIGp1c3QgbGlrZSBub3JtYWwgcmVqZWN0aW9ucyB3b3VsZDpcbiAgICAgKiBgYGB0c1xuICAgICAqIGxldCBjYW5jZWxsYWJsZSA9IG5ldyBDYW5jZWxsYWJsZVByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4geyAuLi4gfSk7XG4gICAgICogbGV0IGNoYWluZWQgPSBjYW5jZWxsYWJsZS50aGVuKCgpID0+IHsgLi4uIH0pLnRoZW4oKCkgPT4geyAuLi4gfSk7IC8vIE5vIGNhdGNoLi4uXG4gICAgICogY2FuY2VsbGFibGUuY2FuY2VsKCk7IC8vIFVuaGFuZGxlZCByZWplY3Rpb24gZXZlbnQgb24gY2hhaW5lZCFcbiAgICAgKiBgYGBcbiAgICAgKiBUaGVyZWZvcmUsIGl0IGlzIGltcG9ydGFudCB0byBlaXRoZXIgY2FuY2VsIHdob2xlIHByb21pc2UgY2hhaW5zIGZyb20gdGhlaXIgdGFpbCxcbiAgICAgKiBhcyBzaG93biBpbiB0aGUgY29ycmVjdCBpZGlvbXMgYWJvdmUsIG9yIHRha2UgY2FyZSBvZiBoYW5kbGluZyBlcnJvcnMgZXZlcnl3aGVyZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgY2FuY2VsbGFibGUgcHJvbWlzZSB0aGF0IF9mdWxmaWxsc18gYWZ0ZXIgdGhlIGNhbmNlbCBjYWxsYmFjayAoaWYgYW55KVxuICAgICAqIGFuZCBhbGwgaGFuZGxlcnMgYXR0YWNoZWQgdXAgdG8gdGhlIGNhbGwgdG8gY2FuY2VsIGhhdmUgcnVuLlxuICAgICAqIElmIHRoZSBjYW5jZWwgY2FsbGJhY2sgcmV0dXJucyBhIHRoZW5hYmxlLCB0aGUgcHJvbWlzZSByZXR1cm5lZCBieSBgY2FuY2VsYFxuICAgICAqIHdpbGwgYWxzbyB3YWl0IGZvciB0aGF0IHRoZW5hYmxlIHRvIHNldHRsZS5cbiAgICAgKiBUaGlzIGVuYWJsZXMgY2FsbGVycyB0byB3YWl0IGZvciB0aGUgY2FuY2VsbGVkIG9wZXJhdGlvbiB0byB0ZXJtaW5hdGVcbiAgICAgKiB3aXRob3V0IGJlaW5nIGZvcmNlZCB0byBoYW5kbGUgcG90ZW50aWFsIGVycm9ycyBhdCB0aGUgY2FsbCBzaXRlLlxuICAgICAqIGBgYHRzXG4gICAgICogY2FuY2VsbGFibGUuY2FuY2VsKCkudGhlbigoKSA9PiB7XG4gICAgICogICAgIC8vIENsZWFudXAgZmluaXNoZWQsIGl0J3Mgc2FmZSB0byBkbyBzb21ldGhpbmcgZWxzZS5cbiAgICAgKiB9LCAoZXJyKSA9PiB7XG4gICAgICogICAgIC8vIFVucmVhY2hhYmxlOiB0aGUgcHJvbWlzZSByZXR1cm5lZCBmcm9tIGNhbmNlbCB3aWxsIG5ldmVyIHJlamVjdC5cbiAgICAgKiB9KTtcbiAgICAgKiBgYGBcbiAgICAgKiBOb3RlIHRoYXQgdGhlIHJldHVybmVkIHByb21pc2Ugd2lsbCBfbm90XyBoYW5kbGUgaW1wbGljaXRseSBhbnkgcmVqZWN0aW9uXG4gICAgICogdGhhdCBtaWdodCBoYXZlIG9jY3VycmVkIGFscmVhZHkgaW4gdGhlIGNhbmNlbGxlZCBjaGFpbi5cbiAgICAgKiBJdCB3aWxsIGp1c3QgdHJhY2sgd2hldGhlciByZWdpc3RlcmVkIGhhbmRsZXJzIGhhdmUgYmVlbiBleGVjdXRlZCBvciBub3QuXG4gICAgICogVGhlcmVmb3JlLCB1bmhhbmRsZWQgcmVqZWN0aW9ucyB3aWxsIG5ldmVyIGJlIHNpbGVudGx5IGhhbmRsZWQgYnkgY2FsbGluZyBjYW5jZWwuXG4gICAgICovXG4gICAgY2FuY2VsKGNhdXNlPzogYW55KTogQ2FuY2VsbGFibGVQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBDYW5jZWxsYWJsZVByb21pc2U8dm9pZD4oKHJlc29sdmUpID0+IHtcbiAgICAgICAgICAgIC8vIElOVkFSSUFOVDogdGhlIHJlc3VsdCBvZiB0aGlzW2NhbmNlbEltcGxTeW1dIGFuZCB0aGUgYmFycmllciBkbyBub3QgZXZlciByZWplY3QuXG4gICAgICAgICAgICAvLyBVbmZvcnR1bmF0ZWx5IG1hY09TIEhpZ2ggU2llcnJhIGRvZXMgbm90IHN1cHBvcnQgUHJvbWlzZS5hbGxTZXR0bGVkLlxuICAgICAgICAgICAgUHJvbWlzZS5hbGwoW1xuICAgICAgICAgICAgICAgIHRoaXNbY2FuY2VsSW1wbFN5bV0obmV3IENhbmNlbEVycm9yKFwiUHJvbWlzZSBjYW5jZWxsZWQuXCIsIHsgY2F1c2UgfSkpLFxuICAgICAgICAgICAgICAgIGN1cnJlbnRCYXJyaWVyKHRoaXMpXG4gICAgICAgICAgICBdKS50aGVuKCgpID0+IHJlc29sdmUoKSwgKCkgPT4gcmVzb2x2ZSgpKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQmluZHMgcHJvbWlzZSBjYW5jZWxsYXRpb24gdG8gdGhlIGFib3J0IGV2ZW50IG9mIHRoZSBnaXZlbiB7QGxpbmsgQWJvcnRTaWduYWx9LlxuICAgICAqIElmIHRoZSBzaWduYWwgaGFzIGFscmVhZHkgYWJvcnRlZCwgdGhlIHByb21pc2Ugd2lsbCBiZSBjYW5jZWxsZWQgaW1tZWRpYXRlbHkuXG4gICAgICogV2hlbiBlaXRoZXIgY29uZGl0aW9uIGlzIHZlcmlmaWVkLCB0aGUgY2FuY2VsbGF0aW9uIGNhdXNlIHdpbGwgYmUgc2V0XG4gICAgICogdG8gdGhlIHNpZ25hbCdzIGFib3J0IHJlYXNvbiAoc2VlIHtAbGluayBBYm9ydFNpZ25hbCNyZWFzb259KS5cbiAgICAgKlxuICAgICAqIEhhcyBubyBlZmZlY3QgaWYgY2FsbGVkIChvciBpZiB0aGUgc2lnbmFsIGFib3J0cykgX2FmdGVyXyB0aGUgcHJvbWlzZSBoYXMgYWxyZWFkeSBzZXR0bGVkLlxuICAgICAqIE9ubHkgdGhlIGZpcnN0IHNpZ25hbCB0byBhYm9ydCB3aWxsIHNldCB0aGUgY2FuY2VsbGF0aW9uIGNhdXNlLlxuICAgICAqXG4gICAgICogRm9yIG1vcmUgZGV0YWlscyBhYm91dCB0aGUgY2FuY2VsbGF0aW9uIHByb2Nlc3MsXG4gICAgICogc2VlIHtAbGluayBjYW5jZWx9IGFuZCB0aGUgYENhbmNlbGxhYmxlUHJvbWlzZWAgY29uc3RydWN0b3IuXG4gICAgICpcbiAgICAgKiBUaGlzIG1ldGhvZCBlbmFibGVzIGBhd2FpdGBpbmcgY2FuY2VsbGFibGUgcHJvbWlzZXMgd2l0aG91dCBoYXZpbmdcbiAgICAgKiB0byBzdG9yZSB0aGVtIGZvciBmdXR1cmUgY2FuY2VsbGF0aW9uLCBlLmcuOlxuICAgICAqIGBgYHRzXG4gICAgICogYXdhaXQgbG9uZ1J1bm5pbmdPcGVyYXRpb24oKS5jYW5jZWxPbihzaWduYWwpO1xuICAgICAqIGBgYFxuICAgICAqIGluc3RlYWQgb2Y6XG4gICAgICogYGBgdHNcbiAgICAgKiBsZXQgcHJvbWlzZVRvQmVDYW5jZWxsZWQgPSBsb25nUnVubmluZ09wZXJhdGlvbigpO1xuICAgICAqIGF3YWl0IHByb21pc2VUb0JlQ2FuY2VsbGVkO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogQHJldHVybnMgVGhpcyBwcm9taXNlLCBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgICAqL1xuICAgIGNhbmNlbE9uKHNpZ25hbDogQWJvcnRTaWduYWwpOiBDYW5jZWxsYWJsZVByb21pc2U8VD4ge1xuICAgICAgICBpZiAoc2lnbmFsLmFib3J0ZWQpIHtcbiAgICAgICAgICAgIHZvaWQgdGhpcy5jYW5jZWwoc2lnbmFsLnJlYXNvbilcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNpZ25hbC5hZGRFdmVudExpc3RlbmVyKCdhYm9ydCcsICgpID0+IHZvaWQgdGhpcy5jYW5jZWwoc2lnbmFsLnJlYXNvbiksIHtjYXB0dXJlOiB0cnVlfSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBdHRhY2hlcyBjYWxsYmFja3MgZm9yIHRoZSByZXNvbHV0aW9uIGFuZC9vciByZWplY3Rpb24gb2YgdGhlIGBDYW5jZWxsYWJsZVByb21pc2VgLlxuICAgICAqXG4gICAgICogVGhlIG9wdGlvbmFsIGBvbmNhbmNlbGxlZGAgYXJndW1lbnQgd2lsbCBiZSBpbnZva2VkIHdoZW4gdGhlIHJldHVybmVkIHByb21pc2UgaXMgY2FuY2VsbGVkLFxuICAgICAqIHdpdGggdGhlIHNhbWUgc2VtYW50aWNzIGFzIHRoZSBgb25jYW5jZWxsZWRgIGFyZ3VtZW50IG9mIHRoZSBjb25zdHJ1Y3Rvci5cbiAgICAgKiBXaGVuIHRoZSBwYXJlbnQgcHJvbWlzZSByZWplY3RzIG9yIGlzIGNhbmNlbGxlZCwgdGhlIGBvbnJlamVjdGVkYCBjYWxsYmFjayB3aWxsIHJ1bixcbiAgICAgKiBfZXZlbiBhZnRlciB0aGUgcmV0dXJuZWQgcHJvbWlzZSBoYXMgYmVlbiBjYW5jZWxsZWQ6X1xuICAgICAqIGluIHRoYXQgY2FzZSwgc2hvdWxkIGl0IHJlamVjdCBvciB0aHJvdywgdGhlIHJlYXNvbiB3aWxsIGJlIHdyYXBwZWRcbiAgICAgKiBpbiBhIHtAbGluayBDYW5jZWxsZWRSZWplY3Rpb25FcnJvcn0gYW5kIGJ1YmJsZWQgdXAgYXMgYW4gdW5oYW5kbGVkIHJlamVjdGlvbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBvbmZ1bGZpbGxlZCBUaGUgY2FsbGJhY2sgdG8gZXhlY3V0ZSB3aGVuIHRoZSBQcm9taXNlIGlzIHJlc29sdmVkLlxuICAgICAqIEBwYXJhbSBvbnJlamVjdGVkIFRoZSBjYWxsYmFjayB0byBleGVjdXRlIHdoZW4gdGhlIFByb21pc2UgaXMgcmVqZWN0ZWQuXG4gICAgICogQHJldHVybnMgQSBgQ2FuY2VsbGFibGVQcm9taXNlYCBmb3IgdGhlIGNvbXBsZXRpb24gb2Ygd2hpY2hldmVyIGNhbGxiYWNrIGlzIGV4ZWN1dGVkLlxuICAgICAqIFRoZSByZXR1cm5lZCBwcm9taXNlIGlzIGhvb2tlZCB1cCB0byBwcm9wYWdhdGUgY2FuY2VsbGF0aW9uIHJlcXVlc3RzIHVwIHRoZSBjaGFpbiwgYnV0IG5vdCBkb3duOlxuICAgICAqXG4gICAgICogICAtIGlmIHRoZSBwYXJlbnQgcHJvbWlzZSBpcyBjYW5jZWxsZWQsIHRoZSBgb25yZWplY3RlZGAgaGFuZGxlciB3aWxsIGJlIGludm9rZWQgd2l0aCBhIGBDYW5jZWxFcnJvcmBcbiAgICAgKiAgICAgYW5kIHRoZSByZXR1cm5lZCBwcm9taXNlIF93aWxsIHJlc29sdmUgcmVndWxhcmx5XyB3aXRoIGl0cyByZXN1bHQ7XG4gICAgICogICAtIGNvbnZlcnNlbHksIGlmIHRoZSByZXR1cm5lZCBwcm9taXNlIGlzIGNhbmNlbGxlZCwgX3RoZSBwYXJlbnQgcHJvbWlzZSBpcyBjYW5jZWxsZWQgdG9vO19cbiAgICAgKiAgICAgdGhlIGBvbnJlamVjdGVkYCBoYW5kbGVyIHdpbGwgc3RpbGwgYmUgaW52b2tlZCB3aXRoIHRoZSBwYXJlbnQncyBgQ2FuY2VsRXJyb3JgLFxuICAgICAqICAgICBidXQgaXRzIHJlc3VsdCB3aWxsIGJlIGRpc2NhcmRlZFxuICAgICAqICAgICBhbmQgdGhlIHJldHVybmVkIHByb21pc2Ugd2lsbCByZWplY3Qgd2l0aCBhIGBDYW5jZWxFcnJvcmAgYXMgd2VsbC5cbiAgICAgKlxuICAgICAqIFRoZSBwcm9taXNlIHJldHVybmVkIGZyb20ge0BsaW5rIGNhbmNlbH0gd2lsbCBmdWxmaWxsIG9ubHkgYWZ0ZXIgYWxsIGF0dGFjaGVkIGhhbmRsZXJzXG4gICAgICogdXAgdGhlIGVudGlyZSBwcm9taXNlIGNoYWluIGhhdmUgYmVlbiBydW4uXG4gICAgICpcbiAgICAgKiBJZiBlaXRoZXIgY2FsbGJhY2sgcmV0dXJucyBhIGNhbmNlbGxhYmxlIHByb21pc2UsXG4gICAgICogY2FuY2VsbGF0aW9uIHJlcXVlc3RzIHdpbGwgYmUgZGl2ZXJ0ZWQgdG8gaXQsXG4gICAgICogYW5kIHRoZSBzcGVjaWZpZWQgYG9uY2FuY2VsbGVkYCBjYWxsYmFjayB3aWxsIGJlIGRpc2NhcmRlZC5cbiAgICAgKi9cbiAgICB0aGVuPFRSZXN1bHQxID0gVCwgVFJlc3VsdDIgPSBuZXZlcj4ob25mdWxmaWxsZWQ/OiAoKHZhbHVlOiBUKSA9PiBUUmVzdWx0MSB8IFByb21pc2VMaWtlPFRSZXN1bHQxPiB8IENhbmNlbGxhYmxlUHJvbWlzZUxpa2U8VFJlc3VsdDE+KSB8IHVuZGVmaW5lZCB8IG51bGwsIG9ucmVqZWN0ZWQ/OiAoKHJlYXNvbjogYW55KSA9PiBUUmVzdWx0MiB8IFByb21pc2VMaWtlPFRSZXN1bHQyPiB8IENhbmNlbGxhYmxlUHJvbWlzZUxpa2U8VFJlc3VsdDI+KSB8IHVuZGVmaW5lZCB8IG51bGwsIG9uY2FuY2VsbGVkPzogQ2FuY2VsbGFibGVQcm9taXNlQ2FuY2VsbGVyKTogQ2FuY2VsbGFibGVQcm9taXNlPFRSZXN1bHQxIHwgVFJlc3VsdDI+IHtcbiAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIENhbmNlbGxhYmxlUHJvbWlzZSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5jZWxsYWJsZVByb21pc2UucHJvdG90eXBlLnRoZW4gY2FsbGVkIG9uIGFuIGludmFsaWQgb2JqZWN0LlwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE5PVEU6IFR5cGVTY3JpcHQncyBidWlsdC1pbiB0eXBlIGZvciB0aGVuIGlzIGJyb2tlbixcbiAgICAgICAgLy8gYXMgaXQgYWxsb3dzIHNwZWNpZnlpbmcgYW4gYXJiaXRyYXJ5IFRSZXN1bHQxICE9IFQgZXZlbiB3aGVuIG9uZnVsZmlsbGVkIGlzIG5vdCBhIGZ1bmN0aW9uLlxuICAgICAgICAvLyBXZSBjYW5ub3QgZml4IGl0IGlmIHdlIHdhbnQgdG8gQ2FuY2VsbGFibGVQcm9taXNlIHRvIGltcGxlbWVudCBQcm9taXNlTGlrZTxUPi5cblxuICAgICAgICBpZiAoIWlzQ2FsbGFibGUob25mdWxmaWxsZWQpKSB7IG9uZnVsZmlsbGVkID0gaWRlbnRpdHkgYXMgYW55OyB9XG4gICAgICAgIGlmICghaXNDYWxsYWJsZShvbnJlamVjdGVkKSkgeyBvbnJlamVjdGVkID0gdGhyb3dlcjsgfVxuXG4gICAgICAgIGlmIChvbmZ1bGZpbGxlZCA9PT0gaWRlbnRpdHkgJiYgb25yZWplY3RlZCA9PSB0aHJvd2VyKSB7XG4gICAgICAgICAgICAvLyBTaG9ydGN1dCBmb3IgdHJpdmlhbCBhcmd1bWVudHMuXG4gICAgICAgICAgICByZXR1cm4gbmV3IENhbmNlbGxhYmxlUHJvbWlzZSgocmVzb2x2ZSkgPT4gcmVzb2x2ZSh0aGlzIGFzIGFueSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgYmFycmllcjogUGFydGlhbDxQcm9taXNlV2l0aFJlc29sdmVyczx2b2lkPj4gPSB7fTtcbiAgICAgICAgdGhpc1tiYXJyaWVyU3ltXSA9IGJhcnJpZXI7XG5cbiAgICAgICAgcmV0dXJuIG5ldyBDYW5jZWxsYWJsZVByb21pc2U8VFJlc3VsdDEgfCBUUmVzdWx0Mj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdm9pZCBzdXBlci50aGVuKFxuICAgICAgICAgICAgICAgICh2YWx1ZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAodGhpc1tiYXJyaWVyU3ltXSA9PT0gYmFycmllcikgeyB0aGlzW2JhcnJpZXJTeW1dID0gbnVsbDsgfVxuICAgICAgICAgICAgICAgICAgICBiYXJyaWVyLnJlc29sdmU/LigpO1xuXG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKG9uZnVsZmlsbGVkISh2YWx1ZSkpO1xuICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAocmVhc29uPykgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAodGhpc1tiYXJyaWVyU3ltXSA9PT0gYmFycmllcikgeyB0aGlzW2JhcnJpZXJTeW1dID0gbnVsbDsgfVxuICAgICAgICAgICAgICAgICAgICBiYXJyaWVyLnJlc29sdmU/LigpO1xuXG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKG9ucmVqZWN0ZWQhKHJlYXNvbikpO1xuICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSwgYXN5bmMgKGNhdXNlPykgPT4ge1xuICAgICAgICAgICAgLy9jYW5jZWxsZWQgPSB0cnVlO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gb25jYW5jZWxsZWQ/LihjYXVzZSk7XG4gICAgICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuY2FuY2VsKGNhdXNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQXR0YWNoZXMgYSBjYWxsYmFjayBmb3Igb25seSB0aGUgcmVqZWN0aW9uIG9mIHRoZSBQcm9taXNlLlxuICAgICAqXG4gICAgICogVGhlIG9wdGlvbmFsIGBvbmNhbmNlbGxlZGAgYXJndW1lbnQgd2lsbCBiZSBpbnZva2VkIHdoZW4gdGhlIHJldHVybmVkIHByb21pc2UgaXMgY2FuY2VsbGVkLFxuICAgICAqIHdpdGggdGhlIHNhbWUgc2VtYW50aWNzIGFzIHRoZSBgb25jYW5jZWxsZWRgIGFyZ3VtZW50IG9mIHRoZSBjb25zdHJ1Y3Rvci5cbiAgICAgKiBXaGVuIHRoZSBwYXJlbnQgcHJvbWlzZSByZWplY3RzIG9yIGlzIGNhbmNlbGxlZCwgdGhlIGBvbnJlamVjdGVkYCBjYWxsYmFjayB3aWxsIHJ1bixcbiAgICAgKiBfZXZlbiBhZnRlciB0aGUgcmV0dXJuZWQgcHJvbWlzZSBoYXMgYmVlbiBjYW5jZWxsZWQ6X1xuICAgICAqIGluIHRoYXQgY2FzZSwgc2hvdWxkIGl0IHJlamVjdCBvciB0aHJvdywgdGhlIHJlYXNvbiB3aWxsIGJlIHdyYXBwZWRcbiAgICAgKiBpbiBhIHtAbGluayBDYW5jZWxsZWRSZWplY3Rpb25FcnJvcn0gYW5kIGJ1YmJsZWQgdXAgYXMgYW4gdW5oYW5kbGVkIHJlamVjdGlvbi5cbiAgICAgKlxuICAgICAqIEl0IGlzIGVxdWl2YWxlbnQgdG9cbiAgICAgKiBgYGB0c1xuICAgICAqIGNhbmNlbGxhYmxlUHJvbWlzZS50aGVuKHVuZGVmaW5lZCwgb25yZWplY3RlZCwgb25jYW5jZWxsZWQpO1xuICAgICAqIGBgYFxuICAgICAqIGFuZCB0aGUgc2FtZSBjYXZlYXRzIGFwcGx5LlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlIGZvciB0aGUgY29tcGxldGlvbiBvZiB0aGUgY2FsbGJhY2suXG4gICAgICogQ2FuY2VsbGF0aW9uIHJlcXVlc3RzIG9uIHRoZSByZXR1cm5lZCBwcm9taXNlXG4gICAgICogd2lsbCBwcm9wYWdhdGUgdXAgdGhlIGNoYWluIHRvIHRoZSBwYXJlbnQgcHJvbWlzZSxcbiAgICAgKiBidXQgbm90IGluIHRoZSBvdGhlciBkaXJlY3Rpb24uXG4gICAgICpcbiAgICAgKiBUaGUgcHJvbWlzZSByZXR1cm5lZCBmcm9tIHtAbGluayBjYW5jZWx9IHdpbGwgZnVsZmlsbCBvbmx5IGFmdGVyIGFsbCBhdHRhY2hlZCBoYW5kbGVyc1xuICAgICAqIHVwIHRoZSBlbnRpcmUgcHJvbWlzZSBjaGFpbiBoYXZlIGJlZW4gcnVuLlxuICAgICAqXG4gICAgICogSWYgYG9ucmVqZWN0ZWRgIHJldHVybnMgYSBjYW5jZWxsYWJsZSBwcm9taXNlLFxuICAgICAqIGNhbmNlbGxhdGlvbiByZXF1ZXN0cyB3aWxsIGJlIGRpdmVydGVkIHRvIGl0LFxuICAgICAqIGFuZCB0aGUgc3BlY2lmaWVkIGBvbmNhbmNlbGxlZGAgY2FsbGJhY2sgd2lsbCBiZSBkaXNjYXJkZWQuXG4gICAgICogU2VlIHtAbGluayB0aGVufSBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqL1xuICAgIGNhdGNoPFRSZXN1bHQgPSBuZXZlcj4ob25yZWplY3RlZD86ICgocmVhc29uOiBhbnkpID0+IChQcm9taXNlTGlrZTxUUmVzdWx0PiB8IFRSZXN1bHQpKSB8IHVuZGVmaW5lZCB8IG51bGwsIG9uY2FuY2VsbGVkPzogQ2FuY2VsbGFibGVQcm9taXNlQ2FuY2VsbGVyKTogQ2FuY2VsbGFibGVQcm9taXNlPFQgfCBUUmVzdWx0PiB7XG4gICAgICAgIHJldHVybiB0aGlzLnRoZW4odW5kZWZpbmVkLCBvbnJlamVjdGVkLCBvbmNhbmNlbGxlZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQXR0YWNoZXMgYSBjYWxsYmFjayB0aGF0IGlzIGludm9rZWQgd2hlbiB0aGUgQ2FuY2VsbGFibGVQcm9taXNlIGlzIHNldHRsZWQgKGZ1bGZpbGxlZCBvciByZWplY3RlZCkuIFRoZVxuICAgICAqIHJlc29sdmVkIHZhbHVlIGNhbm5vdCBiZSBhY2Nlc3NlZCBvciBtb2RpZmllZCBmcm9tIHRoZSBjYWxsYmFjay5cbiAgICAgKiBUaGUgcmV0dXJuZWQgcHJvbWlzZSB3aWxsIHNldHRsZSBpbiB0aGUgc2FtZSBzdGF0ZSBhcyB0aGUgb3JpZ2luYWwgb25lXG4gICAgICogYWZ0ZXIgdGhlIHByb3ZpZGVkIGNhbGxiYWNrIGhhcyBjb21wbGV0ZWQgZXhlY3V0aW9uLFxuICAgICAqIHVubGVzcyB0aGUgY2FsbGJhY2sgdGhyb3dzIG9yIHJldHVybnMgYSByZWplY3RpbmcgcHJvbWlzZSxcbiAgICAgKiBpbiB3aGljaCBjYXNlIHRoZSByZXR1cm5lZCBwcm9taXNlIHdpbGwgcmVqZWN0IGFzIHdlbGwuXG4gICAgICpcbiAgICAgKiBUaGUgb3B0aW9uYWwgYG9uY2FuY2VsbGVkYCBhcmd1bWVudCB3aWxsIGJlIGludm9rZWQgd2hlbiB0aGUgcmV0dXJuZWQgcHJvbWlzZSBpcyBjYW5jZWxsZWQsXG4gICAgICogd2l0aCB0aGUgc2FtZSBzZW1hbnRpY3MgYXMgdGhlIGBvbmNhbmNlbGxlZGAgYXJndW1lbnQgb2YgdGhlIGNvbnN0cnVjdG9yLlxuICAgICAqIE9uY2UgdGhlIHBhcmVudCBwcm9taXNlIHNldHRsZXMsIHRoZSBgb25maW5hbGx5YCBjYWxsYmFjayB3aWxsIHJ1bixcbiAgICAgKiBfZXZlbiBhZnRlciB0aGUgcmV0dXJuZWQgcHJvbWlzZSBoYXMgYmVlbiBjYW5jZWxsZWQ6X1xuICAgICAqIGluIHRoYXQgY2FzZSwgc2hvdWxkIGl0IHJlamVjdCBvciB0aHJvdywgdGhlIHJlYXNvbiB3aWxsIGJlIHdyYXBwZWRcbiAgICAgKiBpbiBhIHtAbGluayBDYW5jZWxsZWRSZWplY3Rpb25FcnJvcn0gYW5kIGJ1YmJsZWQgdXAgYXMgYW4gdW5oYW5kbGVkIHJlamVjdGlvbi5cbiAgICAgKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGltcGxlbWVudGVkIGluIHRlcm1zIG9mIHtAbGluayB0aGVufSBhbmQgdGhlIHNhbWUgY2F2ZWF0cyBhcHBseS5cbiAgICAgKiBJdCBpcyBwb2x5ZmlsbGVkLCBoZW5jZSBhdmFpbGFibGUgaW4gZXZlcnkgT1Mvd2VidmlldyB2ZXJzaW9uLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlIGZvciB0aGUgY29tcGxldGlvbiBvZiB0aGUgY2FsbGJhY2suXG4gICAgICogQ2FuY2VsbGF0aW9uIHJlcXVlc3RzIG9uIHRoZSByZXR1cm5lZCBwcm9taXNlXG4gICAgICogd2lsbCBwcm9wYWdhdGUgdXAgdGhlIGNoYWluIHRvIHRoZSBwYXJlbnQgcHJvbWlzZSxcbiAgICAgKiBidXQgbm90IGluIHRoZSBvdGhlciBkaXJlY3Rpb24uXG4gICAgICpcbiAgICAgKiBUaGUgcHJvbWlzZSByZXR1cm5lZCBmcm9tIHtAbGluayBjYW5jZWx9IHdpbGwgZnVsZmlsbCBvbmx5IGFmdGVyIGFsbCBhdHRhY2hlZCBoYW5kbGVyc1xuICAgICAqIHVwIHRoZSBlbnRpcmUgcHJvbWlzZSBjaGFpbiBoYXZlIGJlZW4gcnVuLlxuICAgICAqXG4gICAgICogSWYgYG9uZmluYWxseWAgcmV0dXJucyBhIGNhbmNlbGxhYmxlIHByb21pc2UsXG4gICAgICogY2FuY2VsbGF0aW9uIHJlcXVlc3RzIHdpbGwgYmUgZGl2ZXJ0ZWQgdG8gaXQsXG4gICAgICogYW5kIHRoZSBzcGVjaWZpZWQgYG9uY2FuY2VsbGVkYCBjYWxsYmFjayB3aWxsIGJlIGRpc2NhcmRlZC5cbiAgICAgKiBTZWUge0BsaW5rIHRoZW59IGZvciBtb3JlIGRldGFpbHMuXG4gICAgICovXG4gICAgZmluYWxseShvbmZpbmFsbHk/OiAoKCkgPT4gdm9pZCkgfCB1bmRlZmluZWQgfCBudWxsLCBvbmNhbmNlbGxlZD86IENhbmNlbGxhYmxlUHJvbWlzZUNhbmNlbGxlcik6IENhbmNlbGxhYmxlUHJvbWlzZTxUPiB7XG4gICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBDYW5jZWxsYWJsZVByb21pc2UpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2FuY2VsbGFibGVQcm9taXNlLnByb3RvdHlwZS5maW5hbGx5IGNhbGxlZCBvbiBhbiBpbnZhbGlkIG9iamVjdC5cIik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWlzQ2FsbGFibGUob25maW5hbGx5KSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudGhlbihvbmZpbmFsbHksIG9uZmluYWxseSwgb25jYW5jZWxsZWQpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMudGhlbihcbiAgICAgICAgICAgICh2YWx1ZSkgPT4gQ2FuY2VsbGFibGVQcm9taXNlLnJlc29sdmUob25maW5hbGx5KCkpLnRoZW4oKCkgPT4gdmFsdWUpLFxuICAgICAgICAgICAgKHJlYXNvbj8pID0+IENhbmNlbGxhYmxlUHJvbWlzZS5yZXNvbHZlKG9uZmluYWxseSgpKS50aGVuKCgpID0+IHsgdGhyb3cgcmVhc29uOyB9KSxcbiAgICAgICAgICAgIG9uY2FuY2VsbGVkLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdlIHVzZSB0aGUgYFtTeW1ib2wuc3BlY2llc11gIHN0YXRpYyBwcm9wZXJ0eSwgaWYgYXZhaWxhYmxlLFxuICAgICAqIHRvIGRpc2FibGUgdGhlIGJ1aWx0LWluIGF1dG9tYXRpYyBzdWJjbGFzc2luZyBmZWF0dXJlcyBmcm9tIHtAbGluayBQcm9taXNlfS5cbiAgICAgKiBJdCBpcyBjcml0aWNhbCBmb3IgcGVyZm9ybWFuY2UgcmVhc29ucyB0aGF0IGV4dGVuZGVycyBkbyBub3Qgb3ZlcnJpZGUgdGhpcy5cbiAgICAgKiBPbmNlIHRoZSBwcm9wb3NhbCBhdCBodHRwczovL2dpdGh1Yi5jb20vdGMzOS9wcm9wb3NhbC1ybS1idWlsdGluLXN1YmNsYXNzaW5nXG4gICAgICogaXMgZWl0aGVyIGFjY2VwdGVkIG9yIHJldGlyZWQsIHRoaXMgaW1wbGVtZW50YXRpb24gd2lsbCBoYXZlIHRvIGJlIHJldmlzZWQgYWNjb3JkaW5nbHkuXG4gICAgICpcbiAgICAgKiBAaWdub3JlXG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgc3RhdGljIGdldCBbc3BlY2llc10oKSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBDYW5jZWxsYWJsZVByb21pc2UgdGhhdCBpcyByZXNvbHZlZCB3aXRoIGFuIGFycmF5IG9mIHJlc3VsdHNcbiAgICAgKiB3aGVuIGFsbCBvZiB0aGUgcHJvdmlkZWQgUHJvbWlzZXMgcmVzb2x2ZSwgb3IgcmVqZWN0ZWQgd2hlbiBhbnkgUHJvbWlzZSBpcyByZWplY3RlZC5cbiAgICAgKlxuICAgICAqIEV2ZXJ5IG9uZSBvZiB0aGUgcHJvdmlkZWQgb2JqZWN0cyB0aGF0IGlzIGEgdGhlbmFibGUgX2FuZF8gY2FuY2VsbGFibGUgb2JqZWN0XG4gICAgICogd2lsbCBiZSBjYW5jZWxsZWQgd2hlbiB0aGUgcmV0dXJuZWQgcHJvbWlzZSBpcyBjYW5jZWxsZWQsIHdpdGggdGhlIHNhbWUgY2F1c2UuXG4gICAgICpcbiAgICAgKiBAZ3JvdXAgU3RhdGljIE1ldGhvZHNcbiAgICAgKi9cbiAgICBzdGF0aWMgYWxsPFQ+KHZhbHVlczogSXRlcmFibGU8VCB8IFByb21pc2VMaWtlPFQ+Pik6IENhbmNlbGxhYmxlUHJvbWlzZTxBd2FpdGVkPFQ+W10+O1xuICAgIHN0YXRpYyBhbGw8VCBleHRlbmRzIHJlYWRvbmx5IHVua25vd25bXSB8IFtdPih2YWx1ZXM6IFQpOiBDYW5jZWxsYWJsZVByb21pc2U8eyAtcmVhZG9ubHkgW1AgaW4ga2V5b2YgVF06IEF3YWl0ZWQ8VFtQXT47IH0+O1xuICAgIHN0YXRpYyBhbGw8VCBleHRlbmRzIEl0ZXJhYmxlPHVua25vd24+IHwgQXJyYXlMaWtlPHVua25vd24+Pih2YWx1ZXM6IFQpOiBDYW5jZWxsYWJsZVByb21pc2U8dW5rbm93bj4ge1xuICAgICAgICBsZXQgY29sbGVjdGVkID0gQXJyYXkuZnJvbSh2YWx1ZXMpO1xuICAgICAgICBjb25zdCBwcm9taXNlID0gY29sbGVjdGVkLmxlbmd0aCA9PT0gMFxuICAgICAgICAgICAgPyBDYW5jZWxsYWJsZVByb21pc2UucmVzb2x2ZShjb2xsZWN0ZWQpXG4gICAgICAgICAgICA6IG5ldyBDYW5jZWxsYWJsZVByb21pc2U8dW5rbm93bj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgICAgIHZvaWQgUHJvbWlzZS5hbGwoY29sbGVjdGVkKS50aGVuKHJlc29sdmUsIHJlamVjdCk7XG4gICAgICAgICAgICB9LCAoY2F1c2U/KTogUHJvbWlzZTx2b2lkPiA9PiBjYW5jZWxBbGwocHJvbWlzZSwgY29sbGVjdGVkLCBjYXVzZSkpO1xuICAgICAgICByZXR1cm4gcHJvbWlzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgQ2FuY2VsbGFibGVQcm9taXNlIHRoYXQgaXMgcmVzb2x2ZWQgd2l0aCBhbiBhcnJheSBvZiByZXN1bHRzXG4gICAgICogd2hlbiBhbGwgb2YgdGhlIHByb3ZpZGVkIFByb21pc2VzIHJlc29sdmUgb3IgcmVqZWN0LlxuICAgICAqXG4gICAgICogRXZlcnkgb25lIG9mIHRoZSBwcm92aWRlZCBvYmplY3RzIHRoYXQgaXMgYSB0aGVuYWJsZSBfYW5kXyBjYW5jZWxsYWJsZSBvYmplY3RcbiAgICAgKiB3aWxsIGJlIGNhbmNlbGxlZCB3aGVuIHRoZSByZXR1cm5lZCBwcm9taXNlIGlzIGNhbmNlbGxlZCwgd2l0aCB0aGUgc2FtZSBjYXVzZS5cbiAgICAgKlxuICAgICAqIEBncm91cCBTdGF0aWMgTWV0aG9kc1xuICAgICAqL1xuICAgIHN0YXRpYyBhbGxTZXR0bGVkPFQ+KHZhbHVlczogSXRlcmFibGU8VCB8IFByb21pc2VMaWtlPFQ+Pik6IENhbmNlbGxhYmxlUHJvbWlzZTxQcm9taXNlU2V0dGxlZFJlc3VsdDxBd2FpdGVkPFQ+PltdPjtcbiAgICBzdGF0aWMgYWxsU2V0dGxlZDxUIGV4dGVuZHMgcmVhZG9ubHkgdW5rbm93bltdIHwgW10+KHZhbHVlczogVCk6IENhbmNlbGxhYmxlUHJvbWlzZTx7IC1yZWFkb25seSBbUCBpbiBrZXlvZiBUXTogUHJvbWlzZVNldHRsZWRSZXN1bHQ8QXdhaXRlZDxUW1BdPj47IH0+O1xuICAgIHN0YXRpYyBhbGxTZXR0bGVkPFQgZXh0ZW5kcyBJdGVyYWJsZTx1bmtub3duPiB8IEFycmF5TGlrZTx1bmtub3duPj4odmFsdWVzOiBUKTogQ2FuY2VsbGFibGVQcm9taXNlPHVua25vd24+IHtcbiAgICAgICAgbGV0IGNvbGxlY3RlZCA9IEFycmF5LmZyb20odmFsdWVzKTtcbiAgICAgICAgY29uc3QgcHJvbWlzZSA9IGNvbGxlY3RlZC5sZW5ndGggPT09IDBcbiAgICAgICAgICAgID8gQ2FuY2VsbGFibGVQcm9taXNlLnJlc29sdmUoY29sbGVjdGVkKVxuICAgICAgICAgICAgOiBuZXcgQ2FuY2VsbGFibGVQcm9taXNlPHVua25vd24+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgICAgICB2b2lkIFByb21pc2UuYWxsU2V0dGxlZChjb2xsZWN0ZWQpLnRoZW4ocmVzb2x2ZSwgcmVqZWN0KTtcbiAgICAgICAgICAgIH0sIChjYXVzZT8pOiBQcm9taXNlPHZvaWQ+ID0+IGNhbmNlbEFsbChwcm9taXNlLCBjb2xsZWN0ZWQsIGNhdXNlKSk7XG4gICAgICAgIHJldHVybiBwcm9taXNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBhbnkgZnVuY3Rpb24gcmV0dXJucyBhIHByb21pc2UgdGhhdCBpcyBmdWxmaWxsZWQgYnkgdGhlIGZpcnN0IGdpdmVuIHByb21pc2UgdG8gYmUgZnVsZmlsbGVkLFxuICAgICAqIG9yIHJlamVjdGVkIHdpdGggYW4gQWdncmVnYXRlRXJyb3IgY29udGFpbmluZyBhbiBhcnJheSBvZiByZWplY3Rpb24gcmVhc29uc1xuICAgICAqIGlmIGFsbCBvZiB0aGUgZ2l2ZW4gcHJvbWlzZXMgYXJlIHJlamVjdGVkLlxuICAgICAqIEl0IHJlc29sdmVzIGFsbCBlbGVtZW50cyBvZiB0aGUgcGFzc2VkIGl0ZXJhYmxlIHRvIHByb21pc2VzIGFzIGl0IHJ1bnMgdGhpcyBhbGdvcml0aG0uXG4gICAgICpcbiAgICAgKiBFdmVyeSBvbmUgb2YgdGhlIHByb3ZpZGVkIG9iamVjdHMgdGhhdCBpcyBhIHRoZW5hYmxlIF9hbmRfIGNhbmNlbGxhYmxlIG9iamVjdFxuICAgICAqIHdpbGwgYmUgY2FuY2VsbGVkIHdoZW4gdGhlIHJldHVybmVkIHByb21pc2UgaXMgY2FuY2VsbGVkLCB3aXRoIHRoZSBzYW1lIGNhdXNlLlxuICAgICAqXG4gICAgICogQGdyb3VwIFN0YXRpYyBNZXRob2RzXG4gICAgICovXG4gICAgc3RhdGljIGFueTxUPih2YWx1ZXM6IEl0ZXJhYmxlPFQgfCBQcm9taXNlTGlrZTxUPj4pOiBDYW5jZWxsYWJsZVByb21pc2U8QXdhaXRlZDxUPj47XG4gICAgc3RhdGljIGFueTxUIGV4dGVuZHMgcmVhZG9ubHkgdW5rbm93bltdIHwgW10+KHZhbHVlczogVCk6IENhbmNlbGxhYmxlUHJvbWlzZTxBd2FpdGVkPFRbbnVtYmVyXT4+O1xuICAgIHN0YXRpYyBhbnk8VCBleHRlbmRzIEl0ZXJhYmxlPHVua25vd24+IHwgQXJyYXlMaWtlPHVua25vd24+Pih2YWx1ZXM6IFQpOiBDYW5jZWxsYWJsZVByb21pc2U8dW5rbm93bj4ge1xuICAgICAgICBsZXQgY29sbGVjdGVkID0gQXJyYXkuZnJvbSh2YWx1ZXMpO1xuICAgICAgICBjb25zdCBwcm9taXNlID0gY29sbGVjdGVkLmxlbmd0aCA9PT0gMFxuICAgICAgICAgICAgPyBDYW5jZWxsYWJsZVByb21pc2UucmVzb2x2ZShjb2xsZWN0ZWQpXG4gICAgICAgICAgICA6IG5ldyBDYW5jZWxsYWJsZVByb21pc2U8dW5rbm93bj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgICAgIHZvaWQgUHJvbWlzZS5hbnkoY29sbGVjdGVkKS50aGVuKHJlc29sdmUsIHJlamVjdCk7XG4gICAgICAgICAgICB9LCAoY2F1c2U/KTogUHJvbWlzZTx2b2lkPiA9PiBjYW5jZWxBbGwocHJvbWlzZSwgY29sbGVjdGVkLCBjYXVzZSkpO1xuICAgICAgICByZXR1cm4gcHJvbWlzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgUHJvbWlzZSB0aGF0IGlzIHJlc29sdmVkIG9yIHJlamVjdGVkIHdoZW4gYW55IG9mIHRoZSBwcm92aWRlZCBQcm9taXNlcyBhcmUgcmVzb2x2ZWQgb3IgcmVqZWN0ZWQuXG4gICAgICpcbiAgICAgKiBFdmVyeSBvbmUgb2YgdGhlIHByb3ZpZGVkIG9iamVjdHMgdGhhdCBpcyBhIHRoZW5hYmxlIF9hbmRfIGNhbmNlbGxhYmxlIG9iamVjdFxuICAgICAqIHdpbGwgYmUgY2FuY2VsbGVkIHdoZW4gdGhlIHJldHVybmVkIHByb21pc2UgaXMgY2FuY2VsbGVkLCB3aXRoIHRoZSBzYW1lIGNhdXNlLlxuICAgICAqXG4gICAgICogQGdyb3VwIFN0YXRpYyBNZXRob2RzXG4gICAgICovXG4gICAgc3RhdGljIHJhY2U8VD4odmFsdWVzOiBJdGVyYWJsZTxUIHwgUHJvbWlzZUxpa2U8VD4+KTogQ2FuY2VsbGFibGVQcm9taXNlPEF3YWl0ZWQ8VD4+O1xuICAgIHN0YXRpYyByYWNlPFQgZXh0ZW5kcyByZWFkb25seSB1bmtub3duW10gfCBbXT4odmFsdWVzOiBUKTogQ2FuY2VsbGFibGVQcm9taXNlPEF3YWl0ZWQ8VFtudW1iZXJdPj47XG4gICAgc3RhdGljIHJhY2U8VCBleHRlbmRzIEl0ZXJhYmxlPHVua25vd24+IHwgQXJyYXlMaWtlPHVua25vd24+Pih2YWx1ZXM6IFQpOiBDYW5jZWxsYWJsZVByb21pc2U8dW5rbm93bj4ge1xuICAgICAgICBsZXQgY29sbGVjdGVkID0gQXJyYXkuZnJvbSh2YWx1ZXMpO1xuICAgICAgICBjb25zdCBwcm9taXNlID0gbmV3IENhbmNlbGxhYmxlUHJvbWlzZTx1bmtub3duPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB2b2lkIFByb21pc2UucmFjZShjb2xsZWN0ZWQpLnRoZW4ocmVzb2x2ZSwgcmVqZWN0KTtcbiAgICAgICAgfSwgKGNhdXNlPyk6IFByb21pc2U8dm9pZD4gPT4gY2FuY2VsQWxsKHByb21pc2UsIGNvbGxlY3RlZCwgY2F1c2UpKTtcbiAgICAgICAgcmV0dXJuIHByb21pc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyBjYW5jZWxsZWQgQ2FuY2VsbGFibGVQcm9taXNlIGZvciB0aGUgcHJvdmlkZWQgY2F1c2UuXG4gICAgICpcbiAgICAgKiBAZ3JvdXAgU3RhdGljIE1ldGhvZHNcbiAgICAgKi9cbiAgICBzdGF0aWMgY2FuY2VsPFQgPSBuZXZlcj4oY2F1c2U/OiBhbnkpOiBDYW5jZWxsYWJsZVByb21pc2U8VD4ge1xuICAgICAgICBjb25zdCBwID0gbmV3IENhbmNlbGxhYmxlUHJvbWlzZTxUPigoKSA9PiB7fSk7XG4gICAgICAgIHAuY2FuY2VsKGNhdXNlKTtcbiAgICAgICAgcmV0dXJuIHA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyBDYW5jZWxsYWJsZVByb21pc2UgdGhhdCBjYW5jZWxzXG4gICAgICogYWZ0ZXIgdGhlIHNwZWNpZmllZCB0aW1lb3V0LCB3aXRoIHRoZSBwcm92aWRlZCBjYXVzZS5cbiAgICAgKlxuICAgICAqIElmIHRoZSB7QGxpbmsgQWJvcnRTaWduYWwudGltZW91dH0gZmFjdG9yeSBtZXRob2QgaXMgYXZhaWxhYmxlLFxuICAgICAqIGl0IGlzIHVzZWQgdG8gYmFzZSB0aGUgdGltZW91dCBvbiBfYWN0aXZlXyB0aW1lIHJhdGhlciB0aGFuIF9lbGFwc2VkXyB0aW1lLlxuICAgICAqIE90aGVyd2lzZSwgYHRpbWVvdXRgIGZhbGxzIGJhY2sgdG8ge0BsaW5rIHNldFRpbWVvdXR9LlxuICAgICAqXG4gICAgICogQGdyb3VwIFN0YXRpYyBNZXRob2RzXG4gICAgICovXG4gICAgc3RhdGljIHRpbWVvdXQ8VCA9IG5ldmVyPihtaWxsaXNlY29uZHM6IG51bWJlciwgY2F1c2U/OiBhbnkpOiBDYW5jZWxsYWJsZVByb21pc2U8VD4ge1xuICAgICAgICBjb25zdCBwcm9taXNlID0gbmV3IENhbmNlbGxhYmxlUHJvbWlzZTxUPigoKSA9PiB7fSk7XG4gICAgICAgIGlmIChBYm9ydFNpZ25hbCAmJiB0eXBlb2YgQWJvcnRTaWduYWwgPT09ICdmdW5jdGlvbicgJiYgQWJvcnRTaWduYWwudGltZW91dCAmJiB0eXBlb2YgQWJvcnRTaWduYWwudGltZW91dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgQWJvcnRTaWduYWwudGltZW91dChtaWxsaXNlY29uZHMpLmFkZEV2ZW50TGlzdGVuZXIoJ2Fib3J0JywgKCkgPT4gdm9pZCBwcm9taXNlLmNhbmNlbChjYXVzZSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB2b2lkIHByb21pc2UuY2FuY2VsKGNhdXNlKSwgbWlsbGlzZWNvbmRzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcHJvbWlzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IENhbmNlbGxhYmxlUHJvbWlzZSB0aGF0IHJlc29sdmVzIGFmdGVyIHRoZSBzcGVjaWZpZWQgdGltZW91dC5cbiAgICAgKiBUaGUgcmV0dXJuZWQgcHJvbWlzZSBjYW4gYmUgY2FuY2VsbGVkIHdpdGhvdXQgY29uc2VxdWVuY2VzLlxuICAgICAqXG4gICAgICogQGdyb3VwIFN0YXRpYyBNZXRob2RzXG4gICAgICovXG4gICAgc3RhdGljIHNsZWVwKG1pbGxpc2Vjb25kczogbnVtYmVyKTogQ2FuY2VsbGFibGVQcm9taXNlPHZvaWQ+O1xuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgQ2FuY2VsbGFibGVQcm9taXNlIHRoYXQgcmVzb2x2ZXMgYWZ0ZXJcbiAgICAgKiB0aGUgc3BlY2lmaWVkIHRpbWVvdXQsIHdpdGggdGhlIHByb3ZpZGVkIHZhbHVlLlxuICAgICAqIFRoZSByZXR1cm5lZCBwcm9taXNlIGNhbiBiZSBjYW5jZWxsZWQgd2l0aG91dCBjb25zZXF1ZW5jZXMuXG4gICAgICpcbiAgICAgKiBAZ3JvdXAgU3RhdGljIE1ldGhvZHNcbiAgICAgKi9cbiAgICBzdGF0aWMgc2xlZXA8VD4obWlsbGlzZWNvbmRzOiBudW1iZXIsIHZhbHVlOiBUKTogQ2FuY2VsbGFibGVQcm9taXNlPFQ+O1xuICAgIHN0YXRpYyBzbGVlcDxUID0gdm9pZD4obWlsbGlzZWNvbmRzOiBudW1iZXIsIHZhbHVlPzogVCk6IENhbmNlbGxhYmxlUHJvbWlzZTxUPiB7XG4gICAgICAgIHJldHVybiBuZXcgQ2FuY2VsbGFibGVQcm9taXNlPFQ+KChyZXNvbHZlKSA9PiB7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHJlc29sdmUodmFsdWUhKSwgbWlsbGlzZWNvbmRzKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyByZWplY3RlZCBDYW5jZWxsYWJsZVByb21pc2UgZm9yIHRoZSBwcm92aWRlZCByZWFzb24uXG4gICAgICpcbiAgICAgKiBAZ3JvdXAgU3RhdGljIE1ldGhvZHNcbiAgICAgKi9cbiAgICBzdGF0aWMgcmVqZWN0PFQgPSBuZXZlcj4ocmVhc29uPzogYW55KTogQ2FuY2VsbGFibGVQcm9taXNlPFQ+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBDYW5jZWxsYWJsZVByb21pc2U8VD4oKF8sIHJlamVjdCkgPT4gcmVqZWN0KHJlYXNvbikpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgcmVzb2x2ZWQgQ2FuY2VsbGFibGVQcm9taXNlLlxuICAgICAqXG4gICAgICogQGdyb3VwIFN0YXRpYyBNZXRob2RzXG4gICAgICovXG4gICAgc3RhdGljIHJlc29sdmUoKTogQ2FuY2VsbGFibGVQcm9taXNlPHZvaWQ+O1xuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgcmVzb2x2ZWQgQ2FuY2VsbGFibGVQcm9taXNlIGZvciB0aGUgcHJvdmlkZWQgdmFsdWUuXG4gICAgICpcbiAgICAgKiBAZ3JvdXAgU3RhdGljIE1ldGhvZHNcbiAgICAgKi9cbiAgICBzdGF0aWMgcmVzb2x2ZTxUPih2YWx1ZTogVCk6IENhbmNlbGxhYmxlUHJvbWlzZTxBd2FpdGVkPFQ+PjtcbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IHJlc29sdmVkIENhbmNlbGxhYmxlUHJvbWlzZSBmb3IgdGhlIHByb3ZpZGVkIHZhbHVlLlxuICAgICAqXG4gICAgICogQGdyb3VwIFN0YXRpYyBNZXRob2RzXG4gICAgICovXG4gICAgc3RhdGljIHJlc29sdmU8VD4odmFsdWU6IFQgfCBQcm9taXNlTGlrZTxUPik6IENhbmNlbGxhYmxlUHJvbWlzZTxBd2FpdGVkPFQ+PjtcbiAgICBzdGF0aWMgcmVzb2x2ZTxUID0gdm9pZD4odmFsdWU/OiBUIHwgUHJvbWlzZUxpa2U8VD4pOiBDYW5jZWxsYWJsZVByb21pc2U8QXdhaXRlZDxUPj4ge1xuICAgICAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBDYW5jZWxsYWJsZVByb21pc2UpIHtcbiAgICAgICAgICAgIC8vIE9wdGltaXNlIGZvciBjYW5jZWxsYWJsZSBwcm9taXNlcy5cbiAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IENhbmNlbGxhYmxlUHJvbWlzZTxhbnk+KChyZXNvbHZlKSA9PiByZXNvbHZlKHZhbHVlKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyBDYW5jZWxsYWJsZVByb21pc2UgYW5kIHJldHVybnMgaXQgaW4gYW4gb2JqZWN0LCBhbG9uZyB3aXRoIGl0cyByZXNvbHZlIGFuZCByZWplY3QgZnVuY3Rpb25zXG4gICAgICogYW5kIGEgZ2V0dGVyL3NldHRlciBmb3IgdGhlIGNhbmNlbGxhdGlvbiBjYWxsYmFjay5cbiAgICAgKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIHBvbHlmaWxsZWQsIGhlbmNlIGF2YWlsYWJsZSBpbiBldmVyeSBPUy93ZWJ2aWV3IHZlcnNpb24uXG4gICAgICpcbiAgICAgKiBAZ3JvdXAgU3RhdGljIE1ldGhvZHNcbiAgICAgKi9cbiAgICBzdGF0aWMgd2l0aFJlc29sdmVyczxUPigpOiBDYW5jZWxsYWJsZVByb21pc2VXaXRoUmVzb2x2ZXJzPFQ+IHtcbiAgICAgICAgbGV0IHJlc3VsdDogQ2FuY2VsbGFibGVQcm9taXNlV2l0aFJlc29sdmVyczxUPiA9IHsgb25jYW5jZWxsZWQ6IG51bGwgfSBhcyBhbnk7XG4gICAgICAgIHJlc3VsdC5wcm9taXNlID0gbmV3IENhbmNlbGxhYmxlUHJvbWlzZTxUPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICByZXN1bHQucmVzb2x2ZSA9IHJlc29sdmU7XG4gICAgICAgICAgICByZXN1bHQucmVqZWN0ID0gcmVqZWN0O1xuICAgICAgICB9LCAoY2F1c2U/OiBhbnkpID0+IHsgcmVzdWx0Lm9uY2FuY2VsbGVkPy4oY2F1c2UpOyB9KTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG59XG5cbi8qKlxuICogUmV0dXJucyBhIGNhbGxiYWNrIHRoYXQgaW1wbGVtZW50cyB0aGUgY2FuY2VsbGF0aW9uIGFsZ29yaXRobSBmb3IgdGhlIGdpdmVuIGNhbmNlbGxhYmxlIHByb21pc2UuXG4gKiBUaGUgcHJvbWlzZSByZXR1cm5lZCBmcm9tIHRoZSByZXN1bHRpbmcgZnVuY3Rpb24gZG9lcyBub3QgcmVqZWN0LlxuICovXG5mdW5jdGlvbiBjYW5jZWxsZXJGb3I8VD4ocHJvbWlzZTogQ2FuY2VsbGFibGVQcm9taXNlV2l0aFJlc29sdmVyczxUPiwgc3RhdGU6IENhbmNlbGxhYmxlUHJvbWlzZVN0YXRlKSB7XG4gICAgbGV0IGNhbmNlbGxhdGlvblByb21pc2U6IHZvaWQgfCBQcm9taXNlTGlrZTx2b2lkPiA9IHVuZGVmaW5lZDtcblxuICAgIHJldHVybiAocmVhc29uOiBDYW5jZWxFcnJvcik6IHZvaWQgfCBQcm9taXNlTGlrZTx2b2lkPiA9PiB7XG4gICAgICAgIGlmICghc3RhdGUuc2V0dGxlZCkge1xuICAgICAgICAgICAgc3RhdGUuc2V0dGxlZCA9IHRydWU7XG4gICAgICAgICAgICBzdGF0ZS5yZWFzb24gPSByZWFzb247XG4gICAgICAgICAgICBwcm9taXNlLnJlamVjdChyZWFzb24pO1xuXG4gICAgICAgICAgICAvLyBBdHRhY2ggYW4gZXJyb3IgaGFuZGxlciB0aGF0IGlnbm9yZXMgdGhpcyBzcGVjaWZpYyByZWplY3Rpb24gcmVhc29uIGFuZCBub3RoaW5nIGVsc2UuXG4gICAgICAgICAgICAvLyBJbiB0aGVvcnksIGEgc2FuZSB1bmRlcmx5aW5nIGltcGxlbWVudGF0aW9uIGF0IHRoaXMgcG9pbnRcbiAgICAgICAgICAgIC8vIHNob3VsZCBhbHdheXMgcmVqZWN0IHdpdGggb3VyIGNhbmNlbGxhdGlvbiByZWFzb24sXG4gICAgICAgICAgICAvLyBoZW5jZSB0aGUgaGFuZGxlciB3aWxsIG5ldmVyIHRocm93LlxuICAgICAgICAgICAgdm9pZCBQcm9taXNlLnByb3RvdHlwZS50aGVuLmNhbGwocHJvbWlzZS5wcm9taXNlLCB1bmRlZmluZWQsIChlcnIpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyICE9PSByZWFzb24pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSWYgcmVhc29uIGlzIG5vdCBzZXQsIHRoZSBwcm9taXNlIHJlc29sdmVkIHJlZ3VsYXJseSwgaGVuY2Ugd2UgbXVzdCBub3QgY2FsbCBvbmNhbmNlbGxlZC5cbiAgICAgICAgLy8gSWYgb25jYW5jZWxsZWQgaXMgdW5zZXQsIG5vIG5lZWQgdG8gZ28gYW55IGZ1cnRoZXIuXG4gICAgICAgIGlmICghc3RhdGUucmVhc29uIHx8ICFwcm9taXNlLm9uY2FuY2VsbGVkKSB7IHJldHVybjsgfVxuXG4gICAgICAgIGNhbmNlbGxhdGlvblByb21pc2UgPSBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICByZXNvbHZlKHByb21pc2Uub25jYW5jZWxsZWQhKHN0YXRlLnJlYXNvbiEuY2F1c2UpKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIFByb21pc2UucmVqZWN0KG5ldyBDYW5jZWxsZWRSZWplY3Rpb25FcnJvcihwcm9taXNlLnByb21pc2UsIGVyciwgXCJVbmhhbmRsZWQgZXhjZXB0aW9uIGluIG9uY2FuY2VsbGVkIGNhbGxiYWNrLlwiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pLmNhdGNoKChyZWFzb24/KSA9PiB7XG4gICAgICAgICAgICBQcm9taXNlLnJlamVjdChuZXcgQ2FuY2VsbGVkUmVqZWN0aW9uRXJyb3IocHJvbWlzZS5wcm9taXNlLCByZWFzb24sIFwiVW5oYW5kbGVkIHJlamVjdGlvbiBpbiBvbmNhbmNlbGxlZCBjYWxsYmFjay5cIikpO1xuICAgICAgICB9KTtcblxuICAgICAgICAvLyBVbnNldCBvbmNhbmNlbGxlZCB0byBwcmV2ZW50IHJlcGVhdGVkIGNhbGxzLlxuICAgICAgICBwcm9taXNlLm9uY2FuY2VsbGVkID0gbnVsbDtcblxuICAgICAgICByZXR1cm4gY2FuY2VsbGF0aW9uUHJvbWlzZTtcbiAgICB9XG59XG5cbi8qKlxuICogUmV0dXJucyBhIGNhbGxiYWNrIHRoYXQgaW1wbGVtZW50cyB0aGUgcmVzb2x1dGlvbiBhbGdvcml0aG0gZm9yIHRoZSBnaXZlbiBjYW5jZWxsYWJsZSBwcm9taXNlLlxuICovXG5mdW5jdGlvbiByZXNvbHZlckZvcjxUPihwcm9taXNlOiBDYW5jZWxsYWJsZVByb21pc2VXaXRoUmVzb2x2ZXJzPFQ+LCBzdGF0ZTogQ2FuY2VsbGFibGVQcm9taXNlU3RhdGUpOiBDYW5jZWxsYWJsZVByb21pc2VSZXNvbHZlcjxUPiB7XG4gICAgcmV0dXJuICh2YWx1ZSkgPT4ge1xuICAgICAgICBpZiAoc3RhdGUucmVzb2x2aW5nKSB7IHJldHVybjsgfVxuICAgICAgICBzdGF0ZS5yZXNvbHZpbmcgPSB0cnVlO1xuXG4gICAgICAgIGlmICh2YWx1ZSA9PT0gcHJvbWlzZS5wcm9taXNlKSB7XG4gICAgICAgICAgICBpZiAoc3RhdGUuc2V0dGxlZCkgeyByZXR1cm47IH1cbiAgICAgICAgICAgIHN0YXRlLnNldHRsZWQgPSB0cnVlO1xuICAgICAgICAgICAgcHJvbWlzZS5yZWplY3QobmV3IFR5cGVFcnJvcihcIkEgcHJvbWlzZSBjYW5ub3QgYmUgcmVzb2x2ZWQgd2l0aCBpdHNlbGYuXCIpKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh2YWx1ZSAhPSBudWxsICYmICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnIHx8IHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJykpIHtcbiAgICAgICAgICAgIGxldCB0aGVuOiBhbnk7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHRoZW4gPSAodmFsdWUgYXMgYW55KS50aGVuO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgc3RhdGUuc2V0dGxlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgcHJvbWlzZS5yZWplY3QoZXJyKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChpc0NhbGxhYmxlKHRoZW4pKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGNhbmNlbCA9ICh2YWx1ZSBhcyBhbnkpLmNhbmNlbDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzQ2FsbGFibGUoY2FuY2VsKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb25jYW5jZWxsZWQgPSAoY2F1c2U/OiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBSZWZsZWN0LmFwcGx5KGNhbmNlbCwgdmFsdWUsIFtjYXVzZV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0ZS5yZWFzb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiBhbHJlYWR5IGNhbmNlbGxlZCwgcHJvcGFnYXRlIGNhbmNlbGxhdGlvbi5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGUgcHJvbWlzZSByZXR1cm5lZCBmcm9tIHRoZSBjYW5jZWxsZXIgYWxnb3JpdGhtIGRvZXMgbm90IHJlamVjdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNvIGl0IGNhbiBiZSBkaXNjYXJkZWQgc2FmZWx5LlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZvaWQgY2FuY2VsbGVyRm9yKHsgLi4ucHJvbWlzZSwgb25jYW5jZWxsZWQgfSwgc3RhdGUpKHN0YXRlLnJlYXNvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb21pc2Uub25jYW5jZWxsZWQgPSBvbmNhbmNlbGxlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gY2F0Y2gge31cblxuICAgICAgICAgICAgICAgIGNvbnN0IG5ld1N0YXRlOiBDYW5jZWxsYWJsZVByb21pc2VTdGF0ZSA9IHtcbiAgICAgICAgICAgICAgICAgICAgcm9vdDogc3RhdGUucm9vdCxcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2aW5nOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgZ2V0IHNldHRsZWQoKSB7IHJldHVybiB0aGlzLnJvb3Quc2V0dGxlZCB9LFxuICAgICAgICAgICAgICAgICAgICBzZXQgc2V0dGxlZCh2YWx1ZSkgeyB0aGlzLnJvb3Quc2V0dGxlZCA9IHZhbHVlOyB9LFxuICAgICAgICAgICAgICAgICAgICBnZXQgcmVhc29uKCkgeyByZXR1cm4gdGhpcy5yb290LnJlYXNvbiB9XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIGNvbnN0IHJlamVjdG9yID0gcmVqZWN0b3JGb3IocHJvbWlzZSwgbmV3U3RhdGUpO1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIFJlZmxlY3QuYXBwbHkodGhlbiwgdmFsdWUsIFtyZXNvbHZlckZvcihwcm9taXNlLCBuZXdTdGF0ZSksIHJlamVjdG9yXSk7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdG9yKGVycik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybjsgLy8gSU1QT1JUQU5UIVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHN0YXRlLnNldHRsZWQpIHsgcmV0dXJuOyB9XG4gICAgICAgIHN0YXRlLnNldHRsZWQgPSB0cnVlO1xuICAgICAgICBwcm9taXNlLnJlc29sdmUodmFsdWUpO1xuICAgIH07XG59XG5cbi8qKlxuICogUmV0dXJucyBhIGNhbGxiYWNrIHRoYXQgaW1wbGVtZW50cyB0aGUgcmVqZWN0aW9uIGFsZ29yaXRobSBmb3IgdGhlIGdpdmVuIGNhbmNlbGxhYmxlIHByb21pc2UuXG4gKi9cbmZ1bmN0aW9uIHJlamVjdG9yRm9yPFQ+KHByb21pc2U6IENhbmNlbGxhYmxlUHJvbWlzZVdpdGhSZXNvbHZlcnM8VD4sIHN0YXRlOiBDYW5jZWxsYWJsZVByb21pc2VTdGF0ZSk6IENhbmNlbGxhYmxlUHJvbWlzZVJlamVjdG9yIHtcbiAgICByZXR1cm4gKHJlYXNvbj8pID0+IHtcbiAgICAgICAgaWYgKHN0YXRlLnJlc29sdmluZykgeyByZXR1cm47IH1cbiAgICAgICAgc3RhdGUucmVzb2x2aW5nID0gdHJ1ZTtcblxuICAgICAgICBpZiAoc3RhdGUuc2V0dGxlZCkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAocmVhc29uIGluc3RhbmNlb2YgQ2FuY2VsRXJyb3IgJiYgc3RhdGUucmVhc29uIGluc3RhbmNlb2YgQ2FuY2VsRXJyb3IgJiYgT2JqZWN0LmlzKHJlYXNvbi5jYXVzZSwgc3RhdGUucmVhc29uLmNhdXNlKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBTd2FsbG93IGxhdGUgcmVqZWN0aW9ucyB0aGF0IGFyZSBDYW5jZWxFcnJvcnMgd2hvc2UgY2FuY2VsbGF0aW9uIGNhdXNlIGlzIHRoZSBzYW1lIGFzIG91cnMuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGNhdGNoIHt9XG5cbiAgICAgICAgICAgIHZvaWQgUHJvbWlzZS5yZWplY3QobmV3IENhbmNlbGxlZFJlamVjdGlvbkVycm9yKHByb21pc2UucHJvbWlzZSwgcmVhc29uKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzdGF0ZS5zZXR0bGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHByb21pc2UucmVqZWN0KHJlYXNvbik7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8qKlxuICogQ2FuY2VscyBhbGwgdmFsdWVzIGluIGFuIGFycmF5IHRoYXQgbG9vayBsaWtlIGNhbmNlbGxhYmxlIHRoZW5hYmxlcy5cbiAqIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgb25jZSBhbGwgY2FuY2VsbGF0aW9uIHByb2NlZHVyZXMgZm9yIHRoZSBnaXZlbiB2YWx1ZXMgaGF2ZSBzZXR0bGVkLlxuICovXG5mdW5jdGlvbiBjYW5jZWxBbGwocGFyZW50OiBDYW5jZWxsYWJsZVByb21pc2U8dW5rbm93bj4sIHZhbHVlczogYW55W10sIGNhdXNlPzogYW55KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgcmVzdWx0czogUHJvbWlzZTx2b2lkPltdID0gW107XG5cbiAgICBmb3IgKGNvbnN0IHZhbHVlIG9mIHZhbHVlcykge1xuICAgICAgICBsZXQgY2FuY2VsOiBDYW5jZWxsYWJsZVByb21pc2VDYW5jZWxsZXI7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAoIWlzQ2FsbGFibGUodmFsdWUudGhlbikpIHsgY29udGludWU7IH1cbiAgICAgICAgICAgIGNhbmNlbCA9IHZhbHVlLmNhbmNlbDtcbiAgICAgICAgICAgIGlmICghaXNDYWxsYWJsZShjYW5jZWwpKSB7IGNvbnRpbnVlOyB9XG4gICAgICAgIH0gY2F0Y2ggeyBjb250aW51ZTsgfVxuXG4gICAgICAgIGxldCByZXN1bHQ6IHZvaWQgfCBQcm9taXNlTGlrZTx2b2lkPjtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHJlc3VsdCA9IFJlZmxlY3QuYXBwbHkoY2FuY2VsLCB2YWx1ZSwgW2NhdXNlXSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgUHJvbWlzZS5yZWplY3QobmV3IENhbmNlbGxlZFJlamVjdGlvbkVycm9yKHBhcmVudCwgZXJyLCBcIlVuaGFuZGxlZCBleGNlcHRpb24gaW4gY2FuY2VsIG1ldGhvZC5cIikpO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXJlc3VsdCkgeyBjb250aW51ZTsgfVxuICAgICAgICByZXN1bHRzLnB1c2goXG4gICAgICAgICAgICAocmVzdWx0IGluc3RhbmNlb2YgUHJvbWlzZSAgPyByZXN1bHQgOiBQcm9taXNlLnJlc29sdmUocmVzdWx0KSkuY2F0Y2goKHJlYXNvbj8pID0+IHtcbiAgICAgICAgICAgICAgICBQcm9taXNlLnJlamVjdChuZXcgQ2FuY2VsbGVkUmVqZWN0aW9uRXJyb3IocGFyZW50LCByZWFzb24sIFwiVW5oYW5kbGVkIHJlamVjdGlvbiBpbiBjYW5jZWwgbWV0aG9kLlwiKSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiBQcm9taXNlLmFsbChyZXN1bHRzKSBhcyBhbnk7XG59XG5cbi8qKlxuICogUmV0dXJucyBpdHMgYXJndW1lbnQuXG4gKi9cbmZ1bmN0aW9uIGlkZW50aXR5PFQ+KHg6IFQpOiBUIHtcbiAgICByZXR1cm4geDtcbn1cblxuLyoqXG4gKiBUaHJvd3MgaXRzIGFyZ3VtZW50LlxuICovXG5mdW5jdGlvbiB0aHJvd2VyKHJlYXNvbj86IGFueSk6IG5ldmVyIHtcbiAgICB0aHJvdyByZWFzb247XG59XG5cbi8qKlxuICogQXR0ZW1wdHMgdmFyaW91cyBzdHJhdGVnaWVzIHRvIGNvbnZlcnQgYW4gZXJyb3IgdG8gYSBzdHJpbmcuXG4gKi9cbmZ1bmN0aW9uIGVycm9yTWVzc2FnZShlcnI6IGFueSk6IHN0cmluZyB7XG4gICAgdHJ5IHtcbiAgICAgICAgaWYgKGVyciBpbnN0YW5jZW9mIEVycm9yIHx8IHR5cGVvZiBlcnIgIT09ICdvYmplY3QnIHx8IGVyci50b1N0cmluZyAhPT0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIFwiXCIgKyBlcnI7XG4gICAgICAgIH1cbiAgICB9IGNhdGNoIHt9XG5cbiAgICB0cnkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoZXJyKTtcbiAgICB9IGNhdGNoIHt9XG5cbiAgICB0cnkge1xuICAgICAgICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGVycik7XG4gICAgfSBjYXRjaCB7fVxuXG4gICAgcmV0dXJuIFwiPGNvdWxkIG5vdCBjb252ZXJ0IGVycm9yIHRvIHN0cmluZz5cIjtcbn1cblxuLyoqXG4gKiBHZXRzIHRoZSBjdXJyZW50IGJhcnJpZXIgcHJvbWlzZSBmb3IgdGhlIGdpdmVuIGNhbmNlbGxhYmxlIHByb21pc2UuIElmIG5lY2Vzc2FyeSwgaW5pdGlhbGlzZXMgdGhlIGJhcnJpZXIuXG4gKi9cbmZ1bmN0aW9uIGN1cnJlbnRCYXJyaWVyPFQ+KHByb21pc2U6IENhbmNlbGxhYmxlUHJvbWlzZTxUPik6IFByb21pc2U8dm9pZD4ge1xuICAgIGxldCBwd3I6IFBhcnRpYWw8UHJvbWlzZVdpdGhSZXNvbHZlcnM8dm9pZD4+ID0gcHJvbWlzZVtiYXJyaWVyU3ltXSA/PyB7fTtcbiAgICBpZiAoISgncHJvbWlzZScgaW4gcHdyKSkge1xuICAgICAgICBPYmplY3QuYXNzaWduKHB3ciwgcHJvbWlzZVdpdGhSZXNvbHZlcnM8dm9pZD4oKSk7XG4gICAgfVxuICAgIGlmIChwcm9taXNlW2JhcnJpZXJTeW1dID09IG51bGwpIHtcbiAgICAgICAgcHdyLnJlc29sdmUhKCk7XG4gICAgICAgIHByb21pc2VbYmFycmllclN5bV0gPSBwd3I7XG4gICAgfVxuICAgIHJldHVybiBwd3IucHJvbWlzZSE7XG59XG5cbi8vIFBvbHlmaWxsIFByb21pc2Uud2l0aFJlc29sdmVycy5cbmxldCBwcm9taXNlV2l0aFJlc29sdmVycyA9IFByb21pc2Uud2l0aFJlc29sdmVycztcbmlmIChwcm9taXNlV2l0aFJlc29sdmVycyAmJiB0eXBlb2YgcHJvbWlzZVdpdGhSZXNvbHZlcnMgPT09ICdmdW5jdGlvbicpIHtcbiAgICBwcm9taXNlV2l0aFJlc29sdmVycyA9IHByb21pc2VXaXRoUmVzb2x2ZXJzLmJpbmQoUHJvbWlzZSk7XG59IGVsc2Uge1xuICAgIHByb21pc2VXaXRoUmVzb2x2ZXJzID0gZnVuY3Rpb24gPFQ+KCk6IFByb21pc2VXaXRoUmVzb2x2ZXJzPFQ+IHtcbiAgICAgICAgbGV0IHJlc29sdmUhOiAodmFsdWU6IFQgfCBQcm9taXNlTGlrZTxUPikgPT4gdm9pZDtcbiAgICAgICAgbGV0IHJlamVjdCE6IChyZWFzb24/OiBhbnkpID0+IHZvaWQ7XG4gICAgICAgIGNvbnN0IHByb21pc2UgPSBuZXcgUHJvbWlzZTxUPigocmVzLCByZWopID0+IHsgcmVzb2x2ZSA9IHJlczsgcmVqZWN0ID0gcmVqOyB9KTtcbiAgICAgICAgcmV0dXJuIHsgcHJvbWlzZSwgcmVzb2x2ZSwgcmVqZWN0IH07XG4gICAgfVxufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXIsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lLmpzXCI7XG5cbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyKG9iamVjdE5hbWVzLkNsaXBib2FyZCk7XG5cbmNvbnN0IENsaXBib2FyZFNldFRleHQgPSAwO1xuY29uc3QgQ2xpcGJvYXJkVGV4dCA9IDE7XG5cbi8qKlxuICogU2V0cyB0aGUgdGV4dCB0byB0aGUgQ2xpcGJvYXJkLlxuICpcbiAqIEBwYXJhbSB0ZXh0IC0gVGhlIHRleHQgdG8gYmUgc2V0IHRvIHRoZSBDbGlwYm9hcmQuXG4gKiBAcmV0dXJuIEEgUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIG9wZXJhdGlvbiBpcyBzdWNjZXNzZnVsLlxuICovXG5leHBvcnQgZnVuY3Rpb24gU2V0VGV4dCh0ZXh0OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gY2FsbChDbGlwYm9hcmRTZXRUZXh0LCB7dGV4dH0pO1xufVxuXG4vKipcbiAqIEdldCB0aGUgQ2xpcGJvYXJkIHRleHRcbiAqXG4gKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSB0ZXh0IGZyb20gdGhlIENsaXBib2FyZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFRleHQoKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICByZXR1cm4gY2FsbChDbGlwYm9hcmRUZXh0KTtcbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuZXhwb3J0IGludGVyZmFjZSBTaXplIHtcbiAgICAvKiogVGhlIHdpZHRoIG9mIGEgcmVjdGFuZ3VsYXIgYXJlYS4gKi9cbiAgICBXaWR0aDogbnVtYmVyO1xuICAgIC8qKiBUaGUgaGVpZ2h0IG9mIGEgcmVjdGFuZ3VsYXIgYXJlYS4gKi9cbiAgICBIZWlnaHQ6IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZWN0IHtcbiAgICAvKiogVGhlIFggY29vcmRpbmF0ZSBvZiB0aGUgb3JpZ2luLiAqL1xuICAgIFg6IG51bWJlcjtcbiAgICAvKiogVGhlIFkgY29vcmRpbmF0ZSBvZiB0aGUgb3JpZ2luLiAqL1xuICAgIFk6IG51bWJlcjtcbiAgICAvKiogVGhlIHdpZHRoIG9mIHRoZSByZWN0YW5nbGUuICovXG4gICAgV2lkdGg6IG51bWJlcjtcbiAgICAvKiogVGhlIGhlaWdodCBvZiB0aGUgcmVjdGFuZ2xlLiAqL1xuICAgIEhlaWdodDogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNjcmVlbiB7XG4gICAgLyoqIFVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGUgc2NyZWVuLiAqL1xuICAgIElEOiBzdHJpbmc7XG4gICAgLyoqIEh1bWFuLXJlYWRhYmxlIG5hbWUgb2YgdGhlIHNjcmVlbi4gKi9cbiAgICBOYW1lOiBzdHJpbmc7XG4gICAgLyoqIFRoZSBzY2FsZSBmYWN0b3Igb2YgdGhlIHNjcmVlbiAoRFBJLzk2KS4gMSA9IHN0YW5kYXJkIERQSSwgMiA9IEhpRFBJIChSZXRpbmEpLCBldGMuICovXG4gICAgU2NhbGVGYWN0b3I6IG51bWJlcjtcbiAgICAvKiogVGhlIFggY29vcmRpbmF0ZSBvZiB0aGUgc2NyZWVuLiAqL1xuICAgIFg6IG51bWJlcjtcbiAgICAvKiogVGhlIFkgY29vcmRpbmF0ZSBvZiB0aGUgc2NyZWVuLiAqL1xuICAgIFk6IG51bWJlcjtcbiAgICAvKiogQ29udGFpbnMgdGhlIHdpZHRoIGFuZCBoZWlnaHQgb2YgdGhlIHNjcmVlbi4gKi9cbiAgICBTaXplOiBTaXplO1xuICAgIC8qKiBDb250YWlucyB0aGUgYm91bmRzIG9mIHRoZSBzY3JlZW4gaW4gdGVybXMgb2YgWCwgWSwgV2lkdGgsIGFuZCBIZWlnaHQuICovXG4gICAgQm91bmRzOiBSZWN0O1xuICAgIC8qKiBDb250YWlucyB0aGUgcGh5c2ljYWwgYm91bmRzIG9mIHRoZSBzY3JlZW4gaW4gdGVybXMgb2YgWCwgWSwgV2lkdGgsIGFuZCBIZWlnaHQgKGJlZm9yZSBzY2FsaW5nKS4gKi9cbiAgICBQaHlzaWNhbEJvdW5kczogUmVjdDtcbiAgICAvKiogQ29udGFpbnMgdGhlIGFyZWEgb2YgdGhlIHNjcmVlbiB0aGF0IGlzIGFjdHVhbGx5IHVzYWJsZSAoZXhjbHVkaW5nIHRhc2tiYXIgYW5kIG90aGVyIHN5c3RlbSBVSSkuICovXG4gICAgV29ya0FyZWE6IFJlY3Q7XG4gICAgLyoqIENvbnRhaW5zIHRoZSBwaHlzaWNhbCBXb3JrQXJlYSBvZiB0aGUgc2NyZWVuIChiZWZvcmUgc2NhbGluZykuICovXG4gICAgUGh5c2ljYWxXb3JrQXJlYTogUmVjdDtcbiAgICAvKiogVHJ1ZSBpZiB0aGlzIGlzIHRoZSBwcmltYXJ5IG1vbml0b3Igc2VsZWN0ZWQgYnkgdGhlIHVzZXIgaW4gdGhlIG9wZXJhdGluZyBzeXN0ZW0uICovXG4gICAgSXNQcmltYXJ5OiBib29sZWFuO1xuICAgIC8qKiBUaGUgcm90YXRpb24gb2YgdGhlIHNjcmVlbi4gKi9cbiAgICBSb3RhdGlvbjogbnVtYmVyO1xufVxuXG5pbXBvcnQgeyBuZXdSdW50aW1lQ2FsbGVyLCBvYmplY3ROYW1lcyB9IGZyb20gXCIuL3J1bnRpbWUuanNcIjtcbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyKG9iamVjdE5hbWVzLlNjcmVlbnMpO1xuXG5jb25zdCBnZXRBbGwgPSAwO1xuY29uc3QgZ2V0UHJpbWFyeSA9IDE7XG5jb25zdCBnZXRDdXJyZW50ID0gMjtcbmNvbnN0IGdldEJ5SUQgPSAzO1xuY29uc3QgZ2V0QnlJbmRleCA9IDQ7XG5cbi8qKlxuICogR2V0cyBhbGwgc2NyZWVucy5cbiAqXG4gKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBhcnJheSBvZiBTY3JlZW4gb2JqZWN0cy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEdldEFsbCgpOiBQcm9taXNlPFNjcmVlbltdPiB7XG4gICAgcmV0dXJuIGNhbGwoZ2V0QWxsKTtcbn1cblxuLyoqXG4gKiBHZXRzIHRoZSBwcmltYXJ5IHNjcmVlbi5cbiAqXG4gKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgcHJpbWFyeSBzY3JlZW4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBHZXRQcmltYXJ5KCk6IFByb21pc2U8U2NyZWVuPiB7XG4gICAgcmV0dXJuIGNhbGwoZ2V0UHJpbWFyeSk7XG59XG5cbi8qKlxuICogR2V0cyB0aGUgY3VycmVudCBhY3RpdmUgc2NyZWVuLlxuICpcbiAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIGN1cnJlbnQgYWN0aXZlIHNjcmVlbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEdldEN1cnJlbnQoKTogUHJvbWlzZTxTY3JlZW4+IHtcbiAgICByZXR1cm4gY2FsbChnZXRDdXJyZW50KTtcbn1cblxuLyoqXG4gKiBHZXRzIGEgc2NyZWVuIGJ5IGl0cyB1bmlxdWUgZGlzcGxheSBJRC5cbiAqXG4gKiBAcGFyYW0gaWQgLSBUaGUgdW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIHNjcmVlbi5cbiAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBtYXRjaGluZyBTY3JlZW4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBHZXRCeUlEKGlkOiBzdHJpbmcpOiBQcm9taXNlPFNjcmVlbj4ge1xuICAgIHJldHVybiBjYWxsKGdldEJ5SUQsIHsgaWQgfSk7XG59XG5cbi8qKlxuICogR2V0cyBhIHNjcmVlbiBieSBpdHMgaW5kZXggaW4gdGhlIHNjcmVlbiBsaXN0LlxuICpcbiAqIEBwYXJhbSBpbmRleCAtIFRoZSB6ZXJvLWJhc2VkIGluZGV4IG9mIHRoZSBzY3JlZW4uXG4gKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgbWF0Y2hpbmcgU2NyZWVuLlxuICovXG5leHBvcnQgZnVuY3Rpb24gR2V0QnlJbmRleChpbmRleDogbnVtYmVyKTogUHJvbWlzZTxTY3JlZW4+IHtcbiAgICByZXR1cm4gY2FsbChnZXRCeUluZGV4LCB7IGluZGV4IH0pO1xufVxuIiwgIi8qXG4gXyAgICAgX18gICAgIF8gX19cbnwgfCAgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG5pbXBvcnQgeyBuZXdSdW50aW1lQ2FsbGVyLCBvYmplY3ROYW1lcyB9IGZyb20gXCIuL3J1bnRpbWUuanNcIjtcblxuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXIob2JqZWN0TmFtZXMuSU9TKTtcblxuLy8gTWV0aG9kIElEc1xuY29uc3QgSGFwdGljc0ltcGFjdCA9IDA7XG5jb25zdCBEZXZpY2VJbmZvID0gMTtcblxuZXhwb3J0IG5hbWVzcGFjZSBIYXB0aWNzIHtcbiAgICBleHBvcnQgdHlwZSBJbXBhY3RTdHlsZSA9IFwibGlnaHRcInxcIm1lZGl1bVwifFwiaGVhdnlcInxcInNvZnRcInxcInJpZ2lkXCI7XG4gICAgZXhwb3J0IGZ1bmN0aW9uIEltcGFjdChzdHlsZTogSW1wYWN0U3R5bGUgPSBcIm1lZGl1bVwiKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBjYWxsKEhhcHRpY3NJbXBhY3QsIHsgc3R5bGUgfSk7XG4gICAgfVxufVxuXG5leHBvcnQgbmFtZXNwYWNlIERldmljZSB7XG4gICAgZXhwb3J0IGludGVyZmFjZSBJbmZvIHtcbiAgICAgICAgbW9kZWw6IHN0cmluZztcbiAgICAgICAgc3lzdGVtTmFtZTogc3RyaW5nO1xuICAgICAgICBzeXN0ZW1WZXJzaW9uOiBzdHJpbmc7XG4gICAgICAgIGlzU2ltdWxhdG9yOiBib29sZWFuO1xuICAgIH1cbiAgICBleHBvcnQgZnVuY3Rpb24gSW5mbygpOiBQcm9taXNlPEluZm8+IHtcbiAgICAgICAgcmV0dXJuIGNhbGwoRGV2aWNlSW5mbyk7XG4gICAgfVxufVxuIiwgIi8qXG4gXyAgICAgX18gICAgIF8gX19cbnwgfCAgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG5pbXBvcnQgeyBuZXdSdW50aW1lQ2FsbGVyLCBvYmplY3ROYW1lcyB9IGZyb20gXCIuL3J1bnRpbWUuanNcIjtcblxuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXIob2JqZWN0TmFtZXMuQW5kcm9pZCk7XG5cbi8vIE1ldGhvZCBJRHMgKG11c3QgbWF0Y2ggbWVzc2FnZXByb2Nlc3Nvcl9hbmRyb2lkLmdvKVxuY29uc3QgSGFwdGljc1ZpYnJhdGUgPSAwO1xuY29uc3QgRGV2aWNlSW5mbyA9IDE7XG5jb25zdCBUb2FzdFNob3cgPSAyO1xuXG5leHBvcnQgbmFtZXNwYWNlIEhhcHRpY3Mge1xuICAgIC8qKiBWaWJyYXRlIHRoZSBkZXZpY2UgZm9yIHRoZSBnaXZlbiBkdXJhdGlvbiBpbiBtaWxsaXNlY29uZHMuICovXG4gICAgZXhwb3J0IGZ1bmN0aW9uIFZpYnJhdGUoZHVyYXRpb25NczogbnVtYmVyID0gMTAwKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBjYWxsKEhhcHRpY3NWaWJyYXRlLCB7IGR1cmF0aW9uOiBkdXJhdGlvbk1zIH0pO1xuICAgIH1cbn1cblxuZXhwb3J0IG5hbWVzcGFjZSBEZXZpY2Uge1xuICAgIGV4cG9ydCBpbnRlcmZhY2UgSW5mbyB7XG4gICAgICAgIHBsYXRmb3JtOiBzdHJpbmc7XG4gICAgICAgIG1hbnVmYWN0dXJlcjogc3RyaW5nO1xuICAgICAgICBicmFuZDogc3RyaW5nO1xuICAgICAgICBtb2RlbDogc3RyaW5nO1xuICAgICAgICBkZXZpY2U6IHN0cmluZztcbiAgICAgICAgdmVyc2lvbjogc3RyaW5nO1xuICAgICAgICBzZGtJbnQ6IG51bWJlcjtcbiAgICB9XG4gICAgLyoqIFJldHVybiBpbmZvcm1hdGlvbiBhYm91dCB0aGUgQW5kcm9pZCBkZXZpY2UuICovXG4gICAgZXhwb3J0IGZ1bmN0aW9uIEluZm8oKTogUHJvbWlzZTxJbmZvPiB7XG4gICAgICAgIHJldHVybiBjYWxsKERldmljZUluZm8pO1xuICAgIH1cbn1cblxuZXhwb3J0IG5hbWVzcGFjZSBUb2FzdCB7XG4gICAgLyoqIFNob3cgYSBzaG9ydCBBbmRyb2lkIHRvYXN0IG1lc3NhZ2UuICovXG4gICAgZXhwb3J0IGZ1bmN0aW9uIFNob3cobWVzc2FnZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBjYWxsKFRvYXN0U2hvdywgeyBtZXNzYWdlIH0pO1xuICAgIH1cbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoqXG4gKiBVcGRhdGVyIGV2ZW50IG5hbWUgY29uc3RhbnRzLlxuICpcbiAqIFVzZSB0aGVzZSBpbnN0ZWFkIG9mIGhhcmQtY29kaW5nIHN0cmluZyBsaXRlcmFscyB3aGVuIHN1YnNjcmliaW5nIHRvXG4gKiB1cGRhdGVyIGV2ZW50cyBmcm9tIEphdmFTY3JpcHQ6XG4gKlxuICogICAgIGltcG9ydCB7IEV2ZW50cywgVXBkYXRlciB9IGZyb20gXCJAd2FpbHNpby9ydW50aW1lXCI7XG4gKlxuICogICAgIEV2ZW50cy5PbihVcGRhdGVyLkV2ZW50cy5VcGRhdGVBdmFpbGFibGUsIChlKSA9PiB7XG4gKiAgICAgICAgIGNvbnNvbGUubG9nKFwidXBkYXRlIGZvdW5kOlwiLCBlLmRhdGEudmVyc2lvbik7XG4gKiAgICAgfSk7XG4gKlxuICogICAgIEV2ZW50cy5PbihVcGRhdGVyLkV2ZW50cy5Eb3dubG9hZFByb2dyZXNzLCAoZSkgPT4ge1xuICogICAgICAgICBjb25zdCBwID0gZS5kYXRhO1xuICogICAgICAgICBjb25zb2xlLmxvZyhgJHtwLndyaXR0ZW59IC8gJHtwLnRvdGFsfSBieXRlc2ApO1xuICogICAgIH0pO1xuICpcbiAqIE1pcnJvcnMgdGhlIEdvLXNpZGUgY29uc3RhbnRzIGluIGBwa2cvdXBkYXRlci9ldmVudHMuZ29gIGFuZCB0aGVcbiAqIHVzZXItYWN0aW9uIGNvbnN0YW50cyBpbiBgcGtnL3VwZGF0ZXIvd2luZG93X2xpZmVjeWNsZS5nb2AuIEFueVxuICogY2hhbmdlcyBoZXJlIG11c3Qgc3RheSBpbiBzeW5jIHdpdGggdGhvc2UgZmlsZXMgXHUyMDE0IHRoZXJlJ3MgYW5cbiAqIGludGVncmF0aW9uIHRlc3QgdGhhdCBhc3NlcnRzIHRoZSBzdHJpbmdzIG1hdGNoLlxuICovXG5leHBvcnQgY29uc3QgRXZlbnRzID0gT2JqZWN0LmZyZWV6ZSh7XG4gICAgLyoqIEEgQ2hlY2sgcm91bmQtdHJpcCBpcyBzdGFydGluZy4gUGF5bG9hZDogbnVsbC4gKi9cbiAgICBDaGVja1N0YXJ0ZWQ6IFwid2FpbHM6dXBkYXRlcjpjaGVjay1zdGFydGVkXCIsXG4gICAgLyoqIENoZWNrIGZvdW5kIGEgbmV3ZXIgcmVsZWFzZS4gUGF5bG9hZDogUmVsZWFzZS4gKi9cbiAgICBVcGRhdGVBdmFpbGFibGU6IFwid2FpbHM6dXBkYXRlcjp1cGRhdGUtYXZhaWxhYmxlXCIsXG4gICAgLyoqIENoZWNrIGNvbmZpcm1lZCB0aGUgY2FsbGVyIGlzIHVwIHRvIGRhdGUuIFBheWxvYWQ6IG51bGwuICovXG4gICAgTm9VcGRhdGU6IFwid2FpbHM6dXBkYXRlcjpuby11cGRhdGVcIixcbiAgICAvKiogRG93bmxvYWQgaXMgc3RhcnRpbmcuIFBheWxvYWQ6IFJlbGVhc2UuICovXG4gICAgRG93bmxvYWRTdGFydGVkOiBcIndhaWxzOnVwZGF0ZXI6ZG93bmxvYWQtc3RhcnRlZFwiLFxuICAgIC8qKiBQZXJpb2RpYyBwcm9ncmVzcyB0aWNrIGR1cmluZyBkb3dubG9hZCAofjEwIEh6KS4gUGF5bG9hZDogUHJvZ3Jlc3MuICovXG4gICAgRG93bmxvYWRQcm9ncmVzczogXCJ3YWlsczp1cGRhdGVyOmRvd25sb2FkLXByb2dyZXNzXCIsXG4gICAgLyoqIEFsbCBieXRlcyBhcmUgb24gZGlzaywgYnV0IHZlcmlmaWNhdGlvbiBoYXMgbm90IHlldCBzdGFydGVkLiBQYXlsb2FkOiBSZWxlYXNlLiAqL1xuICAgIERvd25sb2FkQ29tcGxldGU6IFwid2FpbHM6dXBkYXRlcjpkb3dubG9hZC1jb21wbGV0ZVwiLFxuICAgIC8qKiBTaWduYXR1cmUgLyBkaWdlc3QgdmVyaWZpY2F0aW9uIGhhcyBzdGFydGVkLiBQYXlsb2FkOiBSZWxlYXNlLiAqL1xuICAgIFZlcmlmeWluZzogXCJ3YWlsczp1cGRhdGVyOnZlcmlmeWluZ1wiLFxuICAgIC8qKiBUaGUgVXBkYXRlciBpcyBzd2FwcGluZyB0aGUgYmluYXJ5IGludG8gcGxhY2UuIFBheWxvYWQ6IFJlbGVhc2UuICovXG4gICAgSW5zdGFsbGluZzogXCJ3YWlsczp1cGRhdGVyOmluc3RhbGxpbmdcIixcbiAgICAvKiogVXBkYXRlIGlzIHN0YWdlZCBhbmQgYSByZXN0YXJ0IGlzIHBlbmRpbmcuIFBheWxvYWQ6IFJlbGVhc2UuICovXG4gICAgVXBkYXRlUmVhZHk6IFwid2FpbHM6dXBkYXRlcjp1cGRhdGUtcmVhZHlcIixcbiAgICAvKiogU29tZXRoaW5nIGZhaWxlZC4gUGF5bG9hZDogRXJyb3JJbmZvIHsgc3RhZ2UsIG1lc3NhZ2UsIHByb3ZpZGVyIH0uICovXG4gICAgRXJyb3I6IFwid2FpbHM6dXBkYXRlcjplcnJvclwiLFxuICAgIC8qKiBIb3N0LXNpZGUgY29udGV4dCBkZWxpdmVyZWQgb25jZSBwZXIgc2Vzc2lvbi4gUGF5bG9hZDogTWV0YSB7IGN1cnJlbnRWZXJzaW9uLCBza2lwcGVkVmVyc2lvbiB9LiAqL1xuICAgIE1ldGE6IFwid2FpbHM6dXBkYXRlcjptZXRhXCIsXG5cbiAgICAvKiogU3ViLW5hbWVzcGFjZTogdXNlci1hY3Rpb24gZXZlbnRzIHRoYXQgdGhlIFVJIGVtaXRzIEJBQ0sgdG8gdGhlIGhvc3QuICovXG4gICAgVXNlcjogT2JqZWN0LmZyZWV6ZSh7XG4gICAgICAgIC8qKiBVc2VyIGNsaWNrZWQgSW5zdGFsbCBvbiBhbiBBdmFpbGFibGUgdXBkYXRlLiAqL1xuICAgICAgICBJbnN0YWxsOiBcIndhaWxzOnVwZGF0ZXI6dXNlcjppbnN0YWxsXCIsXG4gICAgICAgIC8qKiBVc2VyIGNsaWNrZWQgUmVzdGFydCAmIEFwcGx5IG9uIGEgUmVhZHkgdXBkYXRlLiAqL1xuICAgICAgICBSZXN0YXJ0OiBcIndhaWxzOnVwZGF0ZXI6dXNlcjpyZXN0YXJ0XCIsXG4gICAgICAgIC8qKiBVc2VyIGNsaWNrZWQgU2tpcCBUaGlzIFZlcnNpb24uICovXG4gICAgICAgIFNraXA6IFwid2FpbHM6dXBkYXRlcjp1c2VyOnNraXBcIixcbiAgICAgICAgLyoqIFVzZXIgY2xpY2tlZCBSZW1pbmQgTWUgTGF0ZXIuICovXG4gICAgICAgIFJlbWluZDogXCJ3YWlsczp1cGRhdGVyOnVzZXI6cmVtaW5kXCIsXG4gICAgICAgIC8qKiBVc2VyIGNsaWNrZWQgQ2xvc2UgLyBDYW5jZWwuICovXG4gICAgICAgIENhbmNlbDogXCJ3YWlsczp1cGRhdGVyOnVzZXI6Y2FuY2VsXCIsXG4gICAgfSksXG5cbiAgICAvKiogU3ViLW5hbWVzcGFjZTogZnJhbWV3b3JrLWludGVybmFsIGV2ZW50cyB0aGUgVUkgZW1pdHMgdG8gY29vcmRpbmF0ZVxuICAgICAqICB3aXRoIHRoZSBob3N0LiBNb3N0IGFwcCBjb2RlIGNhbiBpZ25vcmUgdGhlc2UuICovXG4gICAgV2luZG93OiBPYmplY3QuZnJlZXplKHtcbiAgICAgICAgLyoqIFRoZSB3aW5kb3cgZmluaXNoZWQgbG9hZGluZyBhbmQgYXNrcyB0aGUgaG9zdCB0byByZXBsYXkgY3VycmVudCBzdGF0ZS4gKi9cbiAgICAgICAgUmVhZHk6IFwid2FpbHM6dXBkYXRlcjp3aW5kb3c6cmVhZHlcIixcbiAgICB9KSxcbn0pO1xuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7OztBQ0FBO0FBQUE7QUFBQTtBQUFBO0FBQUE7OztBQ0FBO0FBQUE7QUFBQTtBQUFBOzs7QUM2QkEsSUFBTSxjQUNGO0FBRUcsU0FBUyxPQUFPLE9BQWUsSUFBWTtBQUM5QyxNQUFJLEtBQUs7QUFFVCxNQUFJLElBQUksT0FBTztBQUNmLFNBQU8sS0FBSztBQUVSLFVBQU0sWUFBYSxLQUFLLE9BQU8sSUFBSSxLQUFNLENBQUM7QUFBQSxFQUM5QztBQUNBLFNBQU87QUFDWDs7O0FDeEJPLElBQU0sU0FBUyxPQUFPLFdBQVcsZUFBZSxPQUFPLGFBQWE7OztBQ0YzRSxTQUFTLGFBQXFCO0FBQzFCLFNBQU8sT0FBTyxTQUFTLFNBQVM7QUFDcEM7QUFHQSxJQUFNLGtCQUFrQixNQUFNO0FBZXZCLElBQU0sZUFBTixjQUEyQixNQUFNO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBTXBDLFlBQVksU0FBa0IsU0FBd0I7QUFDbEQsVUFBTSxTQUFTLE9BQU87QUFDdEIsU0FBSyxPQUFPO0FBQUEsRUFDaEI7QUFDSjtBQUdPLElBQU0sY0FBYyxPQUFPLE9BQU87QUFBQSxFQUNyQyxNQUFNO0FBQUEsRUFDTixXQUFXO0FBQUEsRUFDWCxhQUFhO0FBQUEsRUFDYixRQUFRO0FBQUEsRUFDUixhQUFhO0FBQUEsRUFDYixRQUFRO0FBQUEsRUFDUixRQUFRO0FBQUEsRUFDUixTQUFTO0FBQUEsRUFDVCxRQUFRO0FBQUEsRUFDUixTQUFTO0FBQUEsRUFDVCxZQUFZO0FBQUEsRUFDWixLQUFLO0FBQUEsRUFDTCxTQUFTO0FBQ2IsQ0FBQztBQUNNLElBQUksV0FBVyxPQUFPO0FBdUI3QixJQUFJLGtCQUEyQztBQXNCeEMsU0FBUyxhQUFhLFdBQTBDO0FBQ25FLG9CQUFrQjtBQUN0QjtBQUtPLFNBQVMsZUFBd0M7QUFDcEQsU0FBTztBQUNYO0FBU08sU0FBUyxpQkFBaUIsUUFBZ0IsYUFBcUIsSUFBSTtBQUN0RSxTQUFPLFNBQVUsUUFBZ0IsT0FBWSxNQUFNO0FBQy9DLFdBQU8sa0JBQWtCLFFBQVEsUUFBUSxZQUFZLElBQUk7QUFBQSxFQUM3RDtBQUNKO0FBRUEsZUFBZSxrQkFBa0IsVUFBa0IsUUFBZ0IsWUFBb0IsTUFBeUI7QUFwSWhILE1BQUFBLEtBQUE7QUFzSUksTUFBSSxpQkFBaUI7QUFDakIsV0FBTyxnQkFBZ0IsS0FBSyxVQUFVLFFBQVEsWUFBWSxJQUFJO0FBQUEsRUFDbEU7QUFHQSxNQUFJLE1BQU0sSUFBSSxJQUFJLFdBQVcsQ0FBQztBQUU5QixNQUFJLE9BQXVEO0FBQUEsSUFDekQsUUFBUTtBQUFBLElBQ1I7QUFBQSxFQUNGO0FBQ0EsTUFBSSxTQUFTLFFBQVEsU0FBUyxRQUFXO0FBQ3ZDLFNBQUssT0FBTztBQUFBLEVBQ2Q7QUFFQSxNQUFJLFVBQWtDO0FBQUEsSUFDbEMsQ0FBQyxtQkFBbUIsR0FBRztBQUFBLElBQ3ZCLENBQUMsY0FBYyxHQUFHO0FBQUEsRUFDdEI7QUFDQSxNQUFJLFlBQVk7QUFDWixZQUFRLHFCQUFxQixJQUFJO0FBQUEsRUFDckM7QUFFQSxRQUFNLFVBQVUsS0FBSyxVQUFVLElBQUk7QUFDbkMsTUFBSTtBQUNKLE1BQUksUUFBUSxTQUFTLGlCQUFpQjtBQUNsQyxlQUFXLE1BQU0sWUFBWSxLQUFLLFNBQVMsT0FBTztBQUFBLEVBQ3RELE9BQU87QUFDSCxlQUFXLE1BQU0sTUFBTSxLQUFLLEVBQUUsUUFBUSxRQUFRLFNBQVMsTUFBTSxRQUFRLENBQUM7QUFBQSxFQUMxRTtBQUNBLE1BQUksQ0FBQyxTQUFTLElBQUk7QUFDaEIsVUFBTSxLQUFLLFNBQVMsUUFBUSxJQUFJLGNBQWM7QUFDOUMsUUFBSSx5QkFBSSxTQUFTLHFCQUFxQjtBQUNsQyxZQUFNLE9BQXNCLE1BQU0sU0FBUyxLQUFLO0FBQ2hELFVBQUk7QUFDSixjQUFRLEtBQUssTUFBTTtBQUFBLFFBQ2YsS0FBSztBQUFrQixnQkFBTSxJQUFJLGVBQWUsS0FBSyxPQUFPO0FBQUc7QUFBQSxRQUMvRCxLQUFLO0FBQWtCLGdCQUFNLElBQUksVUFBVSxLQUFLLE9BQU87QUFBRztBQUFBLFFBQzFELEtBQUs7QUFBa0IsZ0JBQU0sSUFBSSxhQUFhLEtBQUssT0FBTztBQUFHO0FBQUEsUUFDN0Q7QUFBdUIsZ0JBQU0sSUFBSSxNQUFNLEtBQUssT0FBTztBQUFBLE1BQ3ZEO0FBQ0EsVUFBSSxRQUFRLEtBQUs7QUFDakIsWUFBTTtBQUFBLElBQ1Y7QUFDQSxVQUFNLElBQUksTUFBTSxNQUFNLFNBQVMsS0FBSyxDQUFDO0FBQUEsRUFDdkM7QUFFQSxRQUFLLE1BQUFBLE1BQUEsU0FBUyxRQUFRLElBQUksY0FBYyxNQUFuQyxnQkFBQUEsSUFBc0MsUUFBUSx3QkFBOUMsWUFBcUUsUUFBUSxJQUFJO0FBQ2xGLFdBQU8sU0FBUyxLQUFLO0FBQUEsRUFDekIsT0FBTztBQUNILFdBQU8sU0FBUyxLQUFLO0FBQUEsRUFDekI7QUFDSjtBQU9BLGVBQWUsWUFBWSxLQUFVLFNBQWlDLFNBQW9DO0FBQ3RHLFFBQU0sVUFBVSxPQUFPO0FBQ3ZCLFFBQU0sWUFBWSxJQUFJLFlBQVksRUFBRSxPQUFPLE9BQU87QUFDbEQsUUFBTSxjQUFjLEtBQUssS0FBSyxVQUFVLFNBQVMsZUFBZTtBQUVoRSxXQUFTLElBQUksR0FBRyxJQUFJLGNBQWMsR0FBRyxLQUFLO0FBQ3RDLFVBQU0sUUFBUSxVQUFVLFNBQVMsSUFBSSxrQkFBa0IsSUFBSSxLQUFLLGVBQWU7QUFDL0UsVUFBTSxPQUFPLE1BQU0sTUFBTSxLQUFLO0FBQUEsTUFDMUIsUUFBUTtBQUFBLE1BQ1IsU0FBUyxpQ0FDRixVQURFO0FBQUEsUUFFTCxvQkFBb0I7QUFBQSxRQUNwQix1QkFBdUIsT0FBTyxDQUFDO0FBQUEsUUFDL0IsdUJBQXVCLE9BQU8sV0FBVztBQUFBLE1BQzdDO0FBQUEsTUFDQSxNQUFNO0FBQUEsSUFDVixDQUFDO0FBQ0QsUUFBSSxDQUFDLEtBQUssSUFBSTtBQUNWLFlBQU0sSUFBSSxNQUFNLE1BQU0sS0FBSyxLQUFLLENBQUM7QUFBQSxJQUNyQztBQUFBLEVBQ0o7QUFFQSxTQUFPLE1BQU0sS0FBSztBQUFBLElBQ2QsUUFBUTtBQUFBLElBQ1IsU0FBUyxpQ0FDRixVQURFO0FBQUEsTUFFTCxvQkFBb0I7QUFBQSxNQUNwQix1QkFBdUIsT0FBTyxjQUFjLENBQUM7QUFBQSxNQUM3Qyx1QkFBdUIsT0FBTyxXQUFXO0FBQUEsSUFDN0M7QUFBQSxJQUNBLE1BQU0sVUFBVSxVQUFVLGNBQWMsS0FBSyxlQUFlO0FBQUEsRUFDaEUsQ0FBQztBQUNMO0FBak9BO0FBOE9BLElBQU0sZ0JBQXdDLFVBQzFDLFNBQVEsWUFBZSxVQUFmLG1CQUFzQixpQkFBZ0IsYUFBYyxPQUFlLFFBQVE7QUFFdkYsSUFBSSxlQUFlO0FBQ2YsUUFBTSxVQUFVLG9CQUFJLElBQThFO0FBRWxHLEVBQUMsT0FBZSx3QkFBd0IsQ0FBQyxJQUFZLFVBQXlCLFVBQXlCO0FBcFAzRyxRQUFBQTtBQXFQUSxVQUFNLFVBQVUsUUFBUSxJQUFJLEVBQUU7QUFDOUIsUUFBSSxDQUFDLFFBQVM7QUFDZCxZQUFRLE9BQU8sRUFBRTtBQUNqQixRQUFJLE9BQU87QUFDUCxjQUFRLE9BQU8sSUFBSSxNQUFNLEtBQUssQ0FBQztBQUMvQjtBQUFBLElBQ0o7QUFDQSxRQUFJO0FBQ0EsWUFBTSxXQUFXLEtBQUssTUFBTSw4QkFBWSxJQUFJO0FBQzVDLFVBQUksQ0FBQyxTQUFTLElBQUk7QUFDZCxnQkFBUSxPQUFPLElBQUksT0FBTUEsTUFBQSxTQUFTLFVBQVQsT0FBQUEsTUFBa0IsNEJBQTRCLENBQUM7QUFDeEU7QUFBQSxNQUNKO0FBQ0EsY0FBUSxRQUFRLFVBQVUsV0FBVyxTQUFTLE9BQU8sU0FBUyxJQUFJO0FBQUEsSUFDdEUsU0FBUyxHQUFHO0FBQ1IsY0FBUSxPQUFPLENBQUM7QUFBQSxJQUNwQjtBQUFBLEVBQ0o7QUFFQSxvQkFBa0I7QUFBQSxJQUNkLEtBQUssVUFBa0IsUUFBZ0IsWUFBb0IsTUFBeUI7QUFDaEYsYUFBTyxJQUFJLFFBQVEsQ0FBQyxTQUFTLFdBQVc7QUFDcEMsY0FBTSxLQUFLLE9BQU87QUFDbEIsZ0JBQVEsSUFBSSxJQUFJLEVBQUUsU0FBUyxPQUFPLENBQUM7QUFDbkMsWUFBSTtBQUNBLHdCQUFjLFlBQVksSUFBSSxLQUFLLFVBQVU7QUFBQSxZQUN6QyxRQUFRO0FBQUEsWUFDUjtBQUFBLFlBQ0E7QUFBQSxZQUNBLE1BQU0sc0JBQVE7QUFBQSxZQUNkO0FBQUEsVUFDSixDQUFDLENBQUM7QUFBQSxRQUNOLFNBQVMsR0FBRztBQUVSLGtCQUFRLE9BQU8sRUFBRTtBQUNqQixpQkFBTyxDQUFDO0FBQUEsUUFDWjtBQUFBLE1BQ0osQ0FBQztBQUFBLElBQ0w7QUFBQSxFQUNKO0FBQ0o7OztBSGpSQSxJQUFNLE9BQU8saUJBQWlCLFlBQVksT0FBTztBQUVqRCxJQUFNLGlCQUFpQjtBQU9oQixTQUFTLFFBQVEsS0FBa0M7QUFDdEQsU0FBTyxLQUFLLGdCQUFnQixFQUFDLEtBQUssSUFBSSxTQUFTLEVBQUMsQ0FBQztBQUNyRDs7O0FJdkJBO0FBQUE7QUFBQSxlQUFBQztBQUFBLEVBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBZUEsSUFBSSxRQUFRO0FBQ1IsU0FBTyxTQUFTLE9BQU8sVUFBVSxDQUFDO0FBQ3RDO0FBRUEsSUFBTUMsUUFBTyxpQkFBaUIsWUFBWSxNQUFNO0FBR2hELElBQU0sYUFBYTtBQUNuQixJQUFNLGdCQUFnQjtBQUN0QixJQUFNLGNBQWM7QUFDcEIsSUFBTSxpQkFBaUI7QUFDdkIsSUFBTSxpQkFBaUI7QUFDdkIsSUFBTSxpQkFBaUI7QUEwR3ZCLFNBQVMsT0FBTyxNQUFjLFVBQWdGLENBQUMsR0FBaUI7QUFDNUgsU0FBT0EsTUFBSyxNQUFNLE9BQU87QUFDN0I7QUFRTyxTQUFTLEtBQUssU0FBZ0Q7QUFBRSxTQUFPLE9BQU8sWUFBWSxPQUFPO0FBQUc7QUFRcEcsU0FBUyxRQUFRLFNBQWdEO0FBQUUsU0FBTyxPQUFPLGVBQWUsT0FBTztBQUFHO0FBUTFHLFNBQVNDLE9BQU0sU0FBZ0Q7QUFBRSxTQUFPLE9BQU8sYUFBYSxPQUFPO0FBQUc7QUFRdEcsU0FBUyxTQUFTLFNBQWdEO0FBQUUsU0FBTyxPQUFPLGdCQUFnQixPQUFPO0FBQUc7QUFXNUcsU0FBUyxTQUFTLFNBQTREO0FBbExyRixNQUFBQztBQWtMdUYsVUFBT0EsTUFBQSxPQUFPLGdCQUFnQixPQUFPLE1BQTlCLE9BQUFBLE1BQW1DLENBQUM7QUFBRztBQVE5SCxTQUFTLFNBQVMsU0FBaUQ7QUFBRSxTQUFPLE9BQU8sZ0JBQWdCLE9BQU87QUFBRzs7O0FDMUxwSDtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBOzs7QUNhTyxJQUFNLGlCQUFpQixvQkFBSSxJQUF3QjtBQUVuRCxJQUFNLFdBQU4sTUFBZTtBQUFBLEVBS2xCLFlBQVksV0FBbUIsVUFBK0IsY0FBc0I7QUFDaEYsU0FBSyxZQUFZO0FBQ2pCLFNBQUssV0FBVztBQUNoQixTQUFLLGVBQWUsZ0JBQWdCO0FBQUEsRUFDeEM7QUFBQSxFQUVBLFNBQVMsTUFBb0I7QUFDekIsUUFBSTtBQUNBLFdBQUssU0FBUyxJQUFJO0FBQUEsSUFDdEIsU0FBUyxLQUFLO0FBQ1YsY0FBUSxNQUFNLEdBQUc7QUFBQSxJQUNyQjtBQUVBLFFBQUksS0FBSyxpQkFBaUIsR0FBSSxRQUFPO0FBQ3JDLFNBQUssZ0JBQWdCO0FBQ3JCLFdBQU8sS0FBSyxpQkFBaUI7QUFBQSxFQUNqQztBQUNKO0FBRU8sU0FBUyxZQUFZLFVBQTBCO0FBQ2xELE1BQUksWUFBWSxlQUFlLElBQUksU0FBUyxTQUFTO0FBQ3JELE1BQUksQ0FBQyxXQUFXO0FBQ1o7QUFBQSxFQUNKO0FBRUEsY0FBWSxVQUFVLE9BQU8sT0FBSyxNQUFNLFFBQVE7QUFDaEQsTUFBSSxVQUFVLFdBQVcsR0FBRztBQUN4QixtQkFBZSxPQUFPLFNBQVMsU0FBUztBQUFBLEVBQzVDLE9BQU87QUFDSCxtQkFBZSxJQUFJLFNBQVMsV0FBVyxTQUFTO0FBQUEsRUFDcEQ7QUFDSjs7O0FDbkRBO0FBQUE7QUFBQTtBQUFBLGVBQUFDO0FBQUEsRUFBQTtBQUFBO0FBQUE7QUFBQSxhQUFBQztBQUFBLEVBQUE7QUFBQTtBQUFBO0FBYU8sU0FBUyxJQUFhLFFBQWdCO0FBQ3pDLFNBQU87QUFDWDtBQU1PLFNBQVMsVUFBVSxRQUFxQjtBQUMzQyxTQUFTLFVBQVUsT0FBUSxLQUFLO0FBQ3BDO0FBT08sU0FBU0MsT0FBZSxTQUFtRDtBQUM5RSxNQUFJLFlBQVksS0FBSztBQUNqQixXQUFPLENBQUMsV0FBWSxXQUFXLE9BQU8sQ0FBQyxJQUFJO0FBQUEsRUFDL0M7QUFFQSxTQUFPLENBQUMsV0FBVztBQUNmLFFBQUksV0FBVyxNQUFNO0FBQ2pCLGFBQU8sQ0FBQztBQUFBLElBQ1o7QUFDQSxhQUFTLElBQUksR0FBRyxJQUFJLE9BQU8sUUFBUSxLQUFLO0FBQ3BDLGFBQU8sQ0FBQyxJQUFJLFFBQVEsT0FBTyxDQUFDLENBQUM7QUFBQSxJQUNqQztBQUNBLFdBQU87QUFBQSxFQUNYO0FBQ0o7QUFPTyxTQUFTQyxLQUEwQyxLQUF5QixPQUEwRDtBQUN6SSxNQUFJLFVBQVUsS0FBSztBQUNmLFdBQU8sQ0FBQyxXQUFZLFdBQVcsT0FBTyxDQUFDLElBQUk7QUFBQSxFQUMvQztBQUVBLFNBQU8sQ0FBQyxXQUFXO0FBQ2YsUUFBSSxXQUFXLE1BQU07QUFDakIsYUFBTyxDQUFDO0FBQUEsSUFDWjtBQUNBLGVBQVdDLFFBQU8sUUFBUTtBQUN0QixhQUFPQSxJQUFHLElBQUksTUFBTSxPQUFPQSxJQUFHLENBQUM7QUFBQSxJQUNuQztBQUNBLFdBQU87QUFBQSxFQUNYO0FBQ0o7QUFNTyxTQUFTLFNBQWtCLFNBQTBEO0FBQ3hGLE1BQUksWUFBWSxLQUFLO0FBQ2pCLFdBQU87QUFBQSxFQUNYO0FBRUEsU0FBTyxDQUFDLFdBQVksV0FBVyxPQUFPLE9BQU8sUUFBUSxNQUFNO0FBQy9EO0FBTU8sU0FBUyxPQUFPLGFBRXZCO0FBQ0ksTUFBSSxTQUFTO0FBQ2IsYUFBVyxRQUFRLGFBQWE7QUFDNUIsUUFBSSxZQUFZLElBQUksTUFBTSxLQUFLO0FBQzNCLGVBQVM7QUFDVDtBQUFBLElBQ0o7QUFBQSxFQUNKO0FBQ0EsTUFBSSxRQUFRO0FBQ1IsV0FBTztBQUFBLEVBQ1g7QUFFQSxTQUFPLENBQUMsV0FBVztBQUNmLGVBQVcsUUFBUSxhQUFhO0FBQzVCLFVBQUksUUFBUSxRQUFRO0FBQ2hCLGVBQU8sSUFBSSxJQUFJLFlBQVksSUFBSSxFQUFFLE9BQU8sSUFBSSxDQUFDO0FBQUEsTUFDakQ7QUFBQSxJQUNKO0FBQ0EsV0FBTztBQUFBLEVBQ1g7QUFDSjtBQU1PLFNBQVMsYUFBYSxRQUFtQjtBQUM1QyxTQUFPLElBQUksS0FBSyxNQUFNO0FBQzFCO0FBTU8sSUFBTSxTQUErQyxDQUFDOzs7QUMxR3RELElBQU0sUUFBUSxPQUFPLE9BQU87QUFBQSxFQUNsQyxTQUFTLE9BQU8sT0FBTztBQUFBLElBQ3RCLHVCQUF1QjtBQUFBLElBQ3ZCLHNCQUFzQjtBQUFBLElBQ3RCLG9CQUFvQjtBQUFBLElBQ3BCLGtCQUFrQjtBQUFBLElBQ2xCLFlBQVk7QUFBQSxJQUNaLG9CQUFvQjtBQUFBLElBQ3BCLG9CQUFvQjtBQUFBLElBQ3BCLDRCQUE0QjtBQUFBLElBQzVCLGNBQWM7QUFBQSxJQUNkLHVCQUF1QjtBQUFBLElBQ3ZCLG1CQUFtQjtBQUFBLElBQ25CLGVBQWU7QUFBQSxJQUNmLGVBQWU7QUFBQSxJQUNmLGlCQUFpQjtBQUFBLElBQ2pCLGtCQUFrQjtBQUFBLElBQ2xCLGdCQUFnQjtBQUFBLElBQ2hCLGlCQUFpQjtBQUFBLElBQ2pCLGlCQUFpQjtBQUFBLElBQ2pCLGdCQUFnQjtBQUFBLElBQ2hCLGVBQWU7QUFBQSxJQUNmLGlCQUFpQjtBQUFBLElBQ2pCLGtCQUFrQjtBQUFBLElBQ2xCLFlBQVk7QUFBQSxJQUNaLGdCQUFnQjtBQUFBLElBQ2hCLGVBQWU7QUFBQSxJQUNmLGFBQWE7QUFBQSxJQUNiLGlCQUFpQjtBQUFBLElBQ2pCLG9CQUFvQjtBQUFBLElBQ3BCLDBCQUEwQjtBQUFBLElBQzFCLDJCQUEyQjtBQUFBLElBQzNCLDBCQUEwQjtBQUFBLElBQzFCLHdCQUF3QjtBQUFBLElBQ3hCLGFBQWE7QUFBQSxJQUNiLGVBQWU7QUFBQSxJQUNmLGdCQUFnQjtBQUFBLElBQ2hCLFlBQVk7QUFBQSxJQUNaLGlCQUFpQjtBQUFBLElBQ2pCLG1CQUFtQjtBQUFBLElBQ25CLG9CQUFvQjtBQUFBLElBQ3BCLHFCQUFxQjtBQUFBLElBQ3JCLGdCQUFnQjtBQUFBLElBQ2hCLGtCQUFrQjtBQUFBLElBQ2xCLGdCQUFnQjtBQUFBLElBQ2hCLGtCQUFrQjtBQUFBLEVBQ25CLENBQUM7QUFBQSxFQUNELEtBQUssT0FBTyxPQUFPO0FBQUEsSUFDbEIsNEJBQTRCO0FBQUEsSUFDNUIsdUNBQXVDO0FBQUEsSUFDdkMseUNBQXlDO0FBQUEsSUFDekMsMEJBQTBCO0FBQUEsSUFDMUIsb0NBQW9DO0FBQUEsSUFDcEMsc0NBQXNDO0FBQUEsSUFDdEMsb0NBQW9DO0FBQUEsSUFDcEMsMENBQTBDO0FBQUEsSUFDMUMsMkJBQTJCO0FBQUEsSUFDM0IsK0JBQStCO0FBQUEsSUFDL0Isb0JBQW9CO0FBQUEsSUFDcEIsNEJBQTRCO0FBQUEsSUFDNUIsc0JBQXNCO0FBQUEsSUFDdEIsc0JBQXNCO0FBQUEsSUFDdEIsb0JBQW9CO0FBQUEsSUFDcEIsNEJBQTRCO0FBQUEsSUFDNUIsMkJBQTJCO0FBQUEsSUFDM0IsK0JBQStCO0FBQUEsSUFDL0IsNkJBQTZCO0FBQUEsSUFDN0IsZ0NBQWdDO0FBQUEsSUFDaEMscUJBQXFCO0FBQUEsSUFDckIsNkJBQTZCO0FBQUEsSUFDN0Isc0JBQXNCO0FBQUEsSUFDdEIsMEJBQTBCO0FBQUEsSUFDMUIsdUJBQXVCO0FBQUEsSUFDdkIsdUJBQXVCO0FBQUEsSUFDdkIsZ0JBQWdCO0FBQUEsSUFDaEIsc0JBQXNCO0FBQUEsSUFDdEIsY0FBYztBQUFBLElBQ2Qsb0JBQW9CO0FBQUEsSUFDcEIsb0JBQW9CO0FBQUEsSUFDcEIsc0JBQXNCO0FBQUEsSUFDdEIsYUFBYTtBQUFBLElBQ2IsY0FBYztBQUFBLElBQ2QsbUJBQW1CO0FBQUEsSUFDbkIsbUJBQW1CO0FBQUEsSUFDbkIseUJBQXlCO0FBQUEsSUFDekIsZUFBZTtBQUFBLElBQ2YsaUJBQWlCO0FBQUEsSUFDakIsdUJBQXVCO0FBQUEsSUFDdkIscUJBQXFCO0FBQUEsSUFDckIscUJBQXFCO0FBQUEsSUFDckIsdUJBQXVCO0FBQUEsSUFDdkIsY0FBYztBQUFBLElBQ2QsZUFBZTtBQUFBLElBQ2Ysb0JBQW9CO0FBQUEsSUFDcEIsb0JBQW9CO0FBQUEsSUFDcEIsMEJBQTBCO0FBQUEsSUFDMUIsZ0JBQWdCO0FBQUEsSUFDaEIsNEJBQTRCO0FBQUEsSUFDNUIsNEJBQTRCO0FBQUEsSUFDNUIseURBQXlEO0FBQUEsSUFDekQsc0NBQXNDO0FBQUEsSUFDdEMsb0JBQW9CO0FBQUEsSUFDcEIscUJBQXFCO0FBQUEsSUFDckIscUJBQXFCO0FBQUEsSUFDckIsc0JBQXNCO0FBQUEsSUFDdEIsZ0NBQWdDO0FBQUEsSUFDaEMsa0NBQWtDO0FBQUEsSUFDbEMsbUNBQW1DO0FBQUEsSUFDbkMsb0NBQW9DO0FBQUEsSUFDcEMsK0JBQStCO0FBQUEsSUFDL0IsNkJBQTZCO0FBQUEsSUFDN0IsdUJBQXVCO0FBQUEsSUFDdkIsaUNBQWlDO0FBQUEsSUFDakMsOEJBQThCO0FBQUEsSUFDOUIsNEJBQTRCO0FBQUEsSUFDNUIsc0NBQXNDO0FBQUEsSUFDdEMsNEJBQTRCO0FBQUEsSUFDNUIsc0JBQXNCO0FBQUEsSUFDdEIsa0NBQWtDO0FBQUEsSUFDbEMsc0JBQXNCO0FBQUEsSUFDdEIsd0JBQXdCO0FBQUEsSUFDeEIsd0JBQXdCO0FBQUEsSUFDeEIsbUJBQW1CO0FBQUEsSUFDbkIsMEJBQTBCO0FBQUEsSUFDMUIsOEJBQThCO0FBQUEsSUFDOUIseUJBQXlCO0FBQUEsSUFDekIsNkJBQTZCO0FBQUEsSUFDN0IsaUJBQWlCO0FBQUEsSUFDakIsZ0JBQWdCO0FBQUEsSUFDaEIsc0JBQXNCO0FBQUEsSUFDdEIsZUFBZTtBQUFBLElBQ2YseUJBQXlCO0FBQUEsSUFDekIsd0JBQXdCO0FBQUEsSUFDeEIsb0JBQW9CO0FBQUEsSUFDcEIscUJBQXFCO0FBQUEsSUFDckIsaUJBQWlCO0FBQUEsSUFDakIsaUJBQWlCO0FBQUEsSUFDakIsc0JBQXNCO0FBQUEsSUFDdEIsbUNBQW1DO0FB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QUNMLENBQUM7OztBM0IvREQsSUFBSSxRQUFRO0FBQ1IsU0FBTyxTQUFTLE9BQU8sVUFBVSxDQUFDO0FBQ3RDO0FBNkRBLElBQUksUUFBUTtBQUNSLFNBQU8sT0FBTyxTQUFnQjtBQUM5QixTQUFPLE9BQU8sV0FBVztBQUM3QjtBQUtBLElBQUksUUFBUTtBQUNSLFNBQU8sT0FBTyx5QkFBeUIsZUFBTyx1QkFBdUIsS0FBSyxjQUFNO0FBQ3BGO0FBR0EsSUFBSSxRQUFRO0FBQ1IsU0FBTyxPQUFPLGtCQUFrQjtBQUNoQyxTQUFPLE9BQU8sa0JBQWtCO0FBQ2hDLFNBQU8sT0FBTyxpQkFBaUI7QUFDbkM7QUFFQSxJQUFJLFFBQVE7QUFDUixFQUFPLE9BQU8scUJBQXFCO0FBQ3ZDO0FBT08sU0FBUyxtQkFBbUIsS0FBNEI7QUFDM0QsU0FBTyxNQUFNLEtBQUssRUFBRSxRQUFRLE9BQU8sQ0FBQyxFQUMvQixLQUFLLGNBQVk7QUFDZCxRQUFJLFNBQVMsSUFBSTtBQUdiLFlBQU0sZUFBZSxTQUFTLFFBQVEsSUFBSSxjQUFjLEtBQUssSUFBSSxZQUFZO0FBQzdFLFVBQUksWUFBWSxTQUFTLFlBQVksR0FBRztBQUNwQyxjQUFNLFNBQVMsU0FBUyxjQUFjLFFBQVE7QUFDOUMsZUFBTyxNQUFNO0FBQ2IsaUJBQVMsS0FBSyxZQUFZLE1BQU07QUFBQSxNQUNwQztBQUFBLElBQ0o7QUFBQSxFQUNKLENBQUMsRUFDQSxNQUFNLE1BQU07QUFBQSxFQUFDLENBQUM7QUFDdkI7QUFHQSxJQUFJLFFBQVE7QUFDUixxQkFBbUIsa0JBQWtCO0FBQ3pDOyIsCiAgIm5hbWVzIjogWyJfYSIsICJFcnJvciIsICJjYWxsIiwgIkVycm9yIiwgIl9hIiwgIkFycmF5IiwgIk1hcCIsICJBcnJheSIsICJNYXAiLCAia2V5IiwgImNhbGwiLCAiX2EiLCAiX2EiLCAicmVzaXphYmxlIiwgIl9hIiwgImNhbGwiLCAiX2EiLCAiY2FsbCIsICJfYSIsICJfYSIsICJjYWxsIiwgIkhpZGVNZXRob2QiLCAiU2hvd01ldGhvZCIsICJpc0RvY3VtZW50RG90QWxsIiwgIl9hIiwgInJlYXNvbiIsICJ2YWx1ZSIsICJjYWxsIiwgImNhbGwiLCAiY2FsbCIsICJjYWxsIiwgIkhhcHRpY3MiLCAiRGV2aWNlIiwgIkluZm8iLCAiRGV2aWNlIiwgIkhhcHRpY3MiLCAiY2FsbCIsICJEZXZpY2VJbmZvIiwgIkhhcHRpY3MiLCAiRGV2aWNlIiwgIkluZm8iLCAiVG9hc3QiLCAiU2hvdyIsICJFdmVudHMiLCAiRXZlbnRzIl0KfQo= diff --git a/v3/internal/assetserver/bundledassets/runtime.js b/v3/internal/assetserver/bundledassets/runtime.js index cb897597d2c..217a6359e93 100644 --- a/v3/internal/assetserver/bundledassets/runtime.js +++ b/v3/internal/assetserver/bundledassets/runtime.js @@ -1 +1 @@ -var ln=Object.defineProperty,zn=Object.defineProperties;var Hn=Object.getOwnPropertyDescriptors;var an=Object.getOwnPropertySymbols;var Vn=Object.prototype.hasOwnProperty,Zn=Object.prototype.propertyIsEnumerable;var sn=(n,e,i)=>e in n?ln(n,e,{enumerable:!0,configurable:!0,writable:!0,value:i}):n[e]=i,N=(n,e)=>{for(var i in e||(e={}))Vn.call(e,i)&&sn(n,i,e[i]);if(an)for(var i of an(e))Zn.call(e,i)&&sn(n,i,e[i]);return n},j=(n,e)=>zn(n,Hn(e));var p=(n,e)=>{for(var i in e)ln(n,i,{get:e[i],enumerable:!0})};var Te={};p(Te,{Android:()=>on,Application:()=>Ne,Browser:()=>we,Call:()=>Ge,CancelError:()=>B,CancellablePromise:()=>Y,CancelledRejectionError:()=>D,Clipboard:()=>Ye,Create:()=>ge,Dialogs:()=>fe,Events:()=>be,Flags:()=>Re,IOS:()=>qe,Screens:()=>Xe,System:()=>Ae,Updater:()=>rn,WML:()=>Se,Window:()=>A,clientId:()=>x,getTransport:()=>un,loadOptionalScript:()=>jn,objectNames:()=>c,setTransport:()=>mn});var Se={};p(Se,{Enable:()=>Pe,Reload:()=>Pn});var we={};p(we,{OpenURL:()=>ue});var _n="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";function M(n=21){let e="",i=n|0;for(;i--;)e+=_n[Math.random()*64|0];return e}var w=typeof window<"u"&&typeof document<"u";function Kn(){return window.location.origin+"/wails/runtime"}var z=512*1024;var c=Object.freeze({Call:0,Clipboard:1,Application:2,Events:3,ContextMenu:4,Dialog:5,Window:6,Screens:7,System:8,Browser:9,CancelCall:10,IOS:11,Android:12}),x=M(),H=null;function mn(n){H=n}function un(){return H}function u(n,e=""){return function(i,t=null){return Gn(n,i,e,t)}}async function Gn(n,e,i,t){var f,y;if(H)return H.call(n,e,i,t);let o=new URL(Kn()),a={object:n,method:e};t!=null&&(a.args=t);let r={"x-wails-client-id":x,"Content-Type":"application/json"};i&&(r["x-wails-window-name"]=i);let l=JSON.stringify(a),d;if(l.length>z?d=await Yn(o,r,l):d=await fetch(o,{method:"POST",headers:r,body:l}),!d.ok)throw new Error(await d.text());return((y=(f=d.headers.get("Content-Type"))==null?void 0:f.indexOf("application/json"))!=null?y:-1)!==-1?d.json():d.text()}async function Yn(n,e,i){let t=M(),o=new TextEncoder().encode(i),a=Math.ceil(o.length/z);for(let r=0;r<a-1;r++){let l=o.subarray(r*z,(r+1)*z),d=await fetch(n,{method:"POST",headers:j(N({},e),{"x-wails-chunk-id":t,"x-wails-chunk-index":String(r),"x-wails-chunk-total":String(a)}),body:l});if(!d.ok)throw new Error(await d.text())}return fetch(n,{method:"POST",headers:j(N({},e),{"x-wails-chunk-id":t,"x-wails-chunk-index":String(a-1),"x-wails-chunk-total":String(a)}),body:o.subarray((a-1)*z)})}var cn,dn=w&&typeof((cn=window.wails)==null?void 0:cn.invokeAsync)=="function"?window.wails:null;if(dn){let n=new Map;window._wailsAndroidCallback=(e,i,t)=>{var a;let o=n.get(e);if(o){if(n.delete(e),t){o.reject(new Error(t));return}try{let r=JSON.parse(i!=null?i:"{}");if(!r.ok){o.reject(new Error((a=r.error)!=null?a:"unknown runtime call error"));return}o.resolve("text"in r?r.text:r.data)}catch(r){o.reject(r)}}},H={call(e,i,t,o){return new Promise((a,r)=>{let l=M();n.set(l,{resolve:a,reject:r});try{dn.invokeAsync(l,JSON.stringify({object:e,method:i,windowName:t,args:o!=null?o:null,clientId:x}))}catch(d){n.delete(l),r(d)}})}}}var Xn=u(c.Browser),Jn=0;function ue(n){return Xn(Jn,{url:n.toString()})}var fe={};p(fe,{Error:()=>ai,Info:()=>oi,OpenFile:()=>si,Question:()=>pe,SaveFile:()=>li,Warning:()=>ri});w&&(window._wails=window._wails||{});var Qn=u(c.Dialog),qn=0,$n=1,ei=2,ni=3,ii=4,ti=5;function E(n,e={}){return Qn(n,e)}function oi(n){return E(qn,n)}function ri(n){return E($n,n)}function ai(n){return E(ei,n)}function pe(n){return E(ni,n)}function si(n){var e;return(e=E(ii,n))!=null?e:[]}function li(n){return E(ti,n)}var be={};p(be,{Emit:()=>We,Off:()=>yi,OffAll:()=>vi,On:()=>Wi,OnMultiple:()=>he,Once:()=>bi,Types:()=>pi,WailsEvent:()=>V});var g=new Map,q=class{constructor(e,i,t){this.eventName=e,this.callback=i,this.maxCallbacks=t||-1}dispatch(e){try{this.callback(e)}catch(i){}return this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0)}};function wn(n){let e=g.get(n.eventName);e&&(e=e.filter(i=>i!==n),e.length===0?g.delete(n.eventName):g.set(n.eventName,e))}var ge={};p(ge,{Any:()=>C,Array:()=>ci,ByteSlice:()=>di,Events:()=>$,Map:()=>mi,Nullable:()=>ui,Struct:()=>wi});function C(n){return n}function di(n){return n==null?"":n}function ci(n){return n===C?e=>e===null?[]:e:e=>{if(e===null)return[];for(let i=0;i<e.length;i++)e[i]=n(e[i]);return e}}function mi(n,e){return e===C?i=>i===null?{}:i:i=>{if(i===null)return{};for(let t in i)i[t]=e(i[t]);return i}}function ui(n){return n===C?C:e=>e===null?null:n(e)}function wi(n){let e=!0;for(let i in n)if(n[i]!==C){e=!1;break}return e?C:i=>{for(let t in n)t in i&&(i[t]=n[t](i[t]));return i}}var $={};var pi=Object.freeze({Windows:Object.freeze({APMPowerSettingChange:"windows:APMPowerSettingChange",APMPowerStatusChange:"windows:APMPowerStatusChange",APMResumeAutomatic:"windows:APMResumeAutomatic",APMResumeSuspend:"windows:APMResumeSuspend",APMSuspend:"windows:APMSuspend",ApplicationStarted:"windows:ApplicationStarted",SystemThemeChanged:"windows:SystemThemeChanged",WebViewNavigationCompleted:"windows:WebViewNavigationCompleted",WindowActive:"windows:WindowActive",WindowBackgroundErase:"windows:WindowBackgroundErase",WindowClickActive:"windows:WindowClickActive",WindowClosing:"windows:WindowClosing",WindowDidMove:"windows:WindowDidMove",WindowDidResize:"windows:WindowDidResize",WindowDPIChanged:"windows:WindowDPIChanged",WindowDragDrop:"windows:WindowDragDrop",WindowDragEnter:"windows:WindowDragEnter",WindowDragLeave:"windows:WindowDragLeave",WindowDragOver:"windows:WindowDragOver",WindowEndMove:"windows:WindowEndMove",WindowEndResize:"windows:WindowEndResize",WindowFullscreen:"windows:WindowFullscreen",WindowHide:"windows:WindowHide",WindowInactive:"windows:WindowInactive",WindowKeyDown:"windows:WindowKeyDown",WindowKeyUp:"windows:WindowKeyUp",WindowKillFocus:"windows:WindowKillFocus",WindowNonClientHit:"windows:WindowNonClientHit",WindowNonClientMouseDown:"windows:WindowNonClientMouseDown",WindowNonClientMouseLeave:"windows:WindowNonClientMouseLeave",WindowNonClientMouseMove:"windows:WindowNonClientMouseMove",WindowNonClientMouseUp:"windows:WindowNonClientMouseUp",WindowPaint:"windows:WindowPaint",WindowRestore:"windows:WindowRestore",WindowSetFocus:"windows:WindowSetFocus",WindowShow:"windows:WindowShow",WindowStartMove:"windows:WindowStartMove",WindowStartResize:"windows:WindowStartResize",WindowUnFullscreen:"windows:WindowUnFullscreen",WindowZOrderChanged:"windows:WindowZOrderChanged",WindowMinimise:"windows:WindowMinimise",WindowUnMinimise:"windows:WindowUnMinimise",WindowMaximise:"windows:WindowMaximise",WindowUnMaximise:"windows:WindowUnMaximise"}),Mac:Object.freeze({ApplicationDidBecomeActive:"mac:ApplicationDidBecomeActive",ApplicationDidChangeBackingProperties:"mac:ApplicationDidChangeBackingProperties",ApplicationDidChangeEffectiveAppearance:"mac:ApplicationDidChangeEffectiveAppearance",ApplicationDidChangeIcon:"mac:ApplicationDidChangeIcon",ApplicationDidChangeOcclusionState:"mac:ApplicationDidChangeOcclusionState",ApplicationDidChangeScreenParameters:"mac:ApplicationDidChangeScreenParameters",ApplicationDidChangeStatusBarFrame:"mac:ApplicationDidChangeStatusBarFrame",ApplicationDidChangeStatusBarOrientation:"mac:ApplicationDidChangeStatusBarOrientation",ApplicationDidChangeTheme:"mac:ApplicationDidChangeTheme",ApplicationDidFinishLaunching:"mac:ApplicationDidFinishLaunching",ApplicationDidHide:"mac:ApplicationDidHide",ApplicationDidResignActive:"mac:ApplicationDidResignActive",ApplicationDidUnhide:"mac:ApplicationDidUnhide",ApplicationDidUpdate:"mac:ApplicationDidUpdate",ApplicationDidWake:"mac:ApplicationDidWake",ApplicationScreensDidSleep:"mac:ApplicationScreensDidSleep",ApplicationScreensDidWake:"mac:ApplicationScreensDidWake",ApplicationShouldHandleReopen:"mac:ApplicationShouldHandleReopen",ApplicationWillBecomeActive:"mac:ApplicationWillBecomeActive",ApplicationWillFinishLaunching:"mac:ApplicationWillFinishLaunching",ApplicationWillHide:"mac:ApplicationWillHide",ApplicationWillResignActive:"mac:ApplicationWillResignActive",ApplicationWillSleep:"mac:ApplicationWillSleep",ApplicationWillTerminate:"mac:ApplicationWillTerminate",ApplicationWillUnhide:"mac:ApplicationWillUnhide",ApplicationWillUpdate:"mac:ApplicationWillUpdate",MenuDidAddItem:"mac:MenuDidAddItem",MenuDidBeginTracking:"mac:MenuDidBeginTracking",MenuDidClose:"mac:MenuDidClose",MenuDidDisplayItem:"mac:MenuDidDisplayItem",MenuDidEndTracking:"mac:MenuDidEndTracking",MenuDidHighlightItem:"mac:MenuDidHighlightItem",MenuDidOpen:"mac:MenuDidOpen",MenuDidPopUp:"mac:MenuDidPopUp",MenuDidRemoveItem:"mac:MenuDidRemoveItem",MenuDidSendAction:"mac:MenuDidSendAction",MenuDidSendActionToItem:"mac:MenuDidSendActionToItem",MenuDidUpdate:"mac:MenuDidUpdate",MenuWillAddItem:"mac:MenuWillAddItem",MenuWillBeginTracking:"mac:MenuWillBeginTracking",MenuWillDisplayItem:"mac:MenuWillDisplayItem",MenuWillEndTracking:"mac:MenuWillEndTracking",MenuWillHighlightItem:"mac:MenuWillHighlightItem",MenuWillOpen:"mac:MenuWillOpen",MenuWillPopUp:"mac:MenuWillPopUp",MenuWillRemoveItem:"mac:MenuWillRemoveItem",MenuWillSendAction:"mac:MenuWillSendAction",MenuWillSendActionToItem:"mac:MenuWillSendActionToItem",MenuWillUpdate:"mac:MenuWillUpdate",WebViewDidCommitNavigation:"mac:WebViewDidCommitNavigation",WebViewDidFinishNavigation:"mac:WebViewDidFinishNavigation",WebViewDidReceiveServerRedirectForProvisionalNavigation:"mac:WebViewDidReceiveServerRedirectForProvisionalNavigation",WebViewDidStartProvisionalNavigation:"mac:WebViewDidStartProvisionalNavigation",WindowDidBecomeKey:"mac:WindowDidBecomeKey",WindowDidBecomeMain:"mac:WindowDidBecomeMain",WindowDidBeginSheet:"mac:WindowDidBeginSheet",WindowDidChangeAlpha:"mac:WindowDidChangeAlpha",WindowDidChangeBackingLocation:"mac:WindowDidChangeBackingLocation",WindowDidChangeBackingProperties:"mac:WindowDidChangeBackingProperties",WindowDidChangeCollectionBehavior:"mac:WindowDidChangeCollectionBehavior",WindowDidChangeEffectiveAppearance:"mac:WindowDidChangeEffectiveAppearance",WindowDidChangeOcclusionState:"mac:WindowDidChangeOcclusionState",WindowDidChangeOrderingMode:"mac:WindowDidChangeOrderingMode",WindowDidChangeScreen:"mac:WindowDidChangeScreen",WindowDidChangeScreenParameters:"mac:WindowDidChangeScreenParameters",WindowDidChangeScreenProfile:"mac:WindowDidChangeScreenProfile",WindowDidChangeScreenSpace:"mac:WindowDidChangeScreenSpace",WindowDidChangeScreenSpaceProperties:"mac:WindowDidChangeScreenSpaceProperties",WindowDidChangeSharingType:"mac:WindowDidChangeSharingType",WindowDidChangeSpace:"mac:WindowDidChangeSpace",WindowDidChangeSpaceOrderingMode:"mac:WindowDidChangeSpaceOrderingMode",WindowDidChangeTitle:"mac:WindowDidChangeTitle",WindowDidChangeToolbar:"mac:WindowDidChangeToolbar",WindowDidDeminiaturize:"mac:WindowDidDeminiaturize",WindowDidEndSheet:"mac:WindowDidEndSheet",WindowDidEnterFullScreen:"mac:WindowDidEnterFullScreen",WindowDidEnterVersionBrowser:"mac:WindowDidEnterVersionBrowser",WindowDidExitFullScreen:"mac:WindowDidExitFullScreen",WindowDidExitVersionBrowser:"mac:WindowDidExitVersionBrowser",WindowDidExpose:"mac:WindowDidExpose",WindowDidFocus:"mac:WindowDidFocus",WindowDidMiniaturize:"mac:WindowDidMiniaturize",WindowDidMove:"mac:WindowDidMove",WindowDidOrderOffScreen:"mac:WindowDidOrderOffScreen",WindowDidOrderOnScreen:"mac:WindowDidOrderOnScreen",WindowDidResignKey:"mac:WindowDidResignKey",WindowDidResignMain:"mac:WindowDidResignMain",WindowDidResize:"mac:WindowDidResize",WindowDidUpdate:"mac:WindowDidUpdate",WindowDidUpdateAlpha:"mac:WindowDidUpdateAlpha",WindowDidUpdateCollectionBehavior:"mac:WindowDidUpdateCollectionBehavior",WindowDidUpdateCollectionProperties:"mac:WindowDidUpdateCollectionProperties",WindowDidUpdateShadow:"mac:WindowDidUpdateShadow",WindowDidUpdateTitle:"mac:WindowDidUpdateTitle",WindowDidUpdateToolbar:"mac:WindowDidUpdateToolbar",WindowDidZoom:"mac:WindowDidZoom",WindowFileDraggingEntered:"mac:WindowFileDraggingEntered",WindowFileDraggingExited:"mac:WindowFileDraggingExited",WindowFileDraggingPerformed:"mac:WindowFileDraggingPerformed",WindowHide:"mac:WindowHide",WindowMaximise:"mac:WindowMaximise",WindowUnMaximise:"mac:WindowUnMaximise",WindowMinimise:"mac:WindowMinimise",WindowUnMinimise:"mac:WindowUnMinimise",WindowShouldClose:"mac:WindowShouldClose",WindowShow:"mac:WindowShow",WindowWillBecomeKey:"mac:WindowWillBecomeKey",WindowWillBecomeMain:"mac:WindowWillBecomeMain",WindowWillBeginSheet:"mac:WindowWillBeginSheet",WindowWillChangeOrderingMode:"mac:WindowWillChangeOrderingMode",WindowWillClose:"mac:WindowWillClose",WindowWillDeminiaturize:"mac:WindowWillDeminiaturize",WindowWillEnterFullScreen:"mac:WindowWillEnterFullScreen",WindowWillEnterVersionBrowser:"mac:WindowWillEnterVersionBrowser",WindowWillExitFullScreen:"mac:WindowWillExitFullScreen",WindowWillExitVersionBrowser:"mac:WindowWillExitVersionBrowser",WindowWillFocus:"mac:WindowWillFocus",WindowWillMiniaturize:"mac:WindowWillMiniaturize",WindowWillMove:"mac:WindowWillMove",WindowWillOrderOffScreen:"mac:WindowWillOrderOffScreen",WindowWillOrderOnScreen:"mac:WindowWillOrderOnScreen",WindowWillResignMain:"mac:WindowWillResignMain",WindowWillResize:"mac:WindowWillResize",WindowWillUnfocus:"mac:WindowWillUnfocus",WindowWillUpdate:"mac:WindowWillUpdate",WindowWillUpdateAlpha:"mac:WindowWillUpdateAlpha",WindowWillUpdateCollectionBehavior:"mac:WindowWillUpdateCollectionBehavior",WindowWillUpdateCollectionProperties:"mac:WindowWillUpdateCollectionProperties",WindowWillUpdateShadow:"mac:WindowWillUpdateShadow",WindowWillUpdateTitle:"mac:WindowWillUpdateTitle",WindowWillUpdateToolbar:"mac:WindowWillUpdateToolbar",WindowWillUpdateVisibility:"mac:WindowWillUpdateVisibility",WindowWillUseStandardFrame:"mac:WindowWillUseStandardFrame",WindowZoomIn:"mac:WindowZoomIn",WindowZoomOut:"mac:WindowZoomOut",WindowZoomReset:"mac:WindowZoomReset"}),Linux:Object.freeze({ApplicationStartup:"linux:ApplicationStartup",SystemDidWake:"linux:SystemDidWake",SystemThemeChanged:"linux:SystemThemeChanged",SystemWillSleep:"linux:SystemWillSleep",WindowDeleteEvent:"linux:WindowDeleteEvent",WindowDidMove:"linux:WindowDidMove",WindowDidResize:"linux:WindowDidResize",WindowFocusIn:"linux:WindowFocusIn",WindowFocusOut:"linux:WindowFocusOut",WindowLoadStarted:"linux:WindowLoadStarted",WindowLoadRedirected:"linux:WindowLoadRedirected",WindowLoadCommitted:"linux:WindowLoadCommitted",WindowLoadFinished:"linux:WindowLoadFinished"}),iOS:Object.freeze({ApplicationDidBecomeActive:"ios:ApplicationDidBecomeActive",ApplicationDidEnterBackground:"ios:ApplicationDidEnterBackground",ApplicationDidFinishLaunching:"ios:ApplicationDidFinishLaunching",ApplicationDidReceiveMemoryWarning:"ios:ApplicationDidReceiveMemoryWarning",ApplicationWillEnterForeground:"ios:ApplicationWillEnterForeground",ApplicationWillResignActive:"ios:ApplicationWillResignActive",ApplicationWillTerminate:"ios:ApplicationWillTerminate",WindowDidLoad:"ios:WindowDidLoad",WindowWillAppear:"ios:WindowWillAppear",WindowDidAppear:"ios:WindowDidAppear",WindowWillDisappear:"ios:WindowWillDisappear",WindowDidDisappear:"ios:WindowDidDisappear",WindowSafeAreaInsetsChanged:"ios:WindowSafeAreaInsetsChanged",WindowOrientationChanged:"ios:WindowOrientationChanged",WindowTouchBegan:"ios:WindowTouchBegan",WindowTouchMoved:"ios:WindowTouchMoved",WindowTouchEnded:"ios:WindowTouchEnded",WindowTouchCancelled:"ios:WindowTouchCancelled",WebViewDidStartNavigation:"ios:WebViewDidStartNavigation",WebViewDidFinishNavigation:"ios:WebViewDidFinishNavigation",WebViewDidFailNavigation:"ios:WebViewDidFailNavigation",WebViewDecidePolicyForNavigationAction:"ios:WebViewDecidePolicyForNavigationAction",BatteryChanged:"ios:BatteryChanged",NetworkChanged:"ios:NetworkChanged",ThemeChanged:"ios:ThemeChanged",ScreenLocked:"ios:ScreenLocked",ScreenUnlocked:"ios:ScreenUnlocked"}),Android:Object.freeze({ActivityCreated:"android:ActivityCreated",ActivityStarted:"android:ActivityStarted",ActivityResumed:"android:ActivityResumed",ActivityPaused:"android:ActivityPaused",ActivityStopped:"android:ActivityStopped",ActivityDestroyed:"android:ActivityDestroyed",ApplicationLowMemory:"android:ApplicationLowMemory",WebViewPageStarted:"android:WebViewPageStarted",WebViewPageFinished:"android:WebViewPageFinished",BatteryChanged:"android:BatteryChanged",NetworkChanged:"android:NetworkChanged",ThemeChanged:"android:ThemeChanged",ScreenLocked:"android:ScreenLocked",ScreenUnlocked:"android:ScreenUnlocked"}),Common:Object.freeze({ApplicationOpenedWithFile:"common:ApplicationOpenedWithFile",ApplicationStarted:"common:ApplicationStarted",ApplicationLaunchedWithUrl:"common:ApplicationLaunchedWithUrl",ThemeChanged:"common:ThemeChanged",SystemDidWake:"common:SystemDidWake",SystemWillSleep:"common:SystemWillSleep",WindowClosing:"common:WindowClosing",WindowDidMove:"common:WindowDidMove",WindowDidResize:"common:WindowDidResize",WindowDPIChanged:"common:WindowDPIChanged",WindowFilesDropped:"common:WindowFilesDropped",WindowFocus:"common:WindowFocus",WindowFullscreen:"common:WindowFullscreen",WindowHide:"common:WindowHide",WindowLostFocus:"common:WindowLostFocus",WindowMaximise:"common:WindowMaximise",WindowMinimise:"common:WindowMinimise",WindowToggleFrameless:"common:WindowToggleFrameless",WindowRestore:"common:WindowRestore",WindowRuntimeReady:"common:WindowRuntimeReady",WindowShow:"common:WindowShow",WindowUnFullscreen:"common:WindowUnFullscreen",WindowUnMaximise:"common:WindowUnMaximise",WindowUnMinimise:"common:WindowUnMinimise",WindowZoom:"common:WindowZoom",WindowZoomIn:"common:WindowZoomIn",WindowZoomOut:"common:WindowZoomOut",WindowZoomReset:"common:WindowZoomReset",BatteryChanged:"common:BatteryChanged",NetworkChanged:"common:NetworkChanged",ScreenLocked:"common:ScreenLocked",ScreenUnlocked:"common:ScreenUnlocked",LowMemory:"common:LowMemory"})});w&&(window._wails=window._wails||{},window._wails.dispatchWailsEvent=hi);var fi=u(c.Events),gi=0,V=class{constructor(e,i){this.name=e,this.data=i!=null?i:null}};function hi(n){let e=g.get(n.name);if(!e)return;let i=new V(n.name,n.name in $?$[n.name](n.data):n.data);"sender"in n&&(i.sender=n.sender);let t=new Set;for(let o of e.slice())o.dispatch(i)&&t.add(o);if(t.size>0){let o=g.get(n.name);if(o){let a=o.filter(r=>!t.has(r));a.length===0?g.delete(n.name):g.set(n.name,a)}}}function he(n,e,i){let t=g.get(n)||[],o=new q(n,e,i);return t.push(o),g.set(n,t),()=>wn(o)}function Wi(n,e){return he(n,e,-1)}function bi(n,e){return he(n,e,1)}function yi(...n){n.forEach(e=>g.delete(e))}function vi(){g.clear()}function We(n,e){return fi(gi,new V(n,e))}function pn(){return new MouseEvent("mousedown").buttons===0}function fn(){if(!EventTarget||!AbortSignal||!AbortController)return!1;let n=!0,e=new EventTarget,i=new AbortController;return e.addEventListener("test",()=>{n=!1},{signal:i.signal}),i.abort(),e.dispatchEvent(new CustomEvent("test")),n}function ee(n){var e;return n.target instanceof HTMLElement?n.target:!(n.target instanceof HTMLElement)&&n.target instanceof Node&&(e=n.target.parentElement)!=null?e:document.body}var gn=!1;w&&document.addEventListener("DOMContentLoaded",()=>{gn=!0});function hn(n){gn||document.readyState==="complete"?n():document.addEventListener("DOMContentLoaded",n)}var Di="data-file-drop-target",W="file-drop-target-active",m=null,Ci=0,Pi=1,Si=2,Ti=3,Mi=4,xi=5,Ei=6,Ai=7,Ri=8,ki=9,Oi=10,Fi=11,Li=12,Ii=13,Ui=14,Bi=15,Ni=16,ji=17,zi=18,Hi=19,Vi=20,Zi=21,_i=22,Ki=23,Gi=24,Yi=25,Xi=26,Ji=27,Qi=28,qi=29,$i=30,et=31,nt=32,it=33,tt=34,ot=35,rt=36,at=37,st=38,lt=39,dt=40,ct=41,mt=42,ut=43,wt=44,pt=45,ft=46,gt=47,ht=48,Wt=49,bt=50,yt=51,vt=52;function ne(n){return n?n.closest("[".concat(Di,"]")):null}function Dt(){var n,e,i,t;return((e=(n=window.chrome)==null?void 0:n.webview)==null?void 0:e.postMessageWithAdditionalObjects)==null?!1:((t=(i=window._wails)==null?void 0:i.flags)==null?void 0:t.enableFileDrop)===!0}function Ct(n,e,i){var t,o;(o=(t=window.chrome)==null?void 0:t.webview)!=null&&o.postMessageWithAdditionalObjects&&window.chrome.webview.postMessageWithAdditionalObjects("file:drop:".concat(n,":").concat(e),i)}var ve=!1;function Wn(){ve=!1,m&&(m.classList.remove(W),m=null)}function bn(){var n,e;((e=(n=window._wails)==null?void 0:n.flags)==null?void 0:e.enableFileDrop)!==!1&&(ve=!0)}function yn(){Wn()}function vn(n,e){var o,a;if(!ve||((a=(o=window._wails)==null?void 0:o.flags)==null?void 0:a.enableFileDrop)===!1)return;let i=document.elementFromPoint(n,e),t=ne(i);m&&m!==t&&m.classList.remove(W),t?(t.classList.add(W),m=t):m=null}var s=Symbol("caller"),ie=class ie{constructor(e=""){this[s]=u(c.Window,e);for(let i of Object.getOwnPropertyNames(ie.prototype))i!=="constructor"&&typeof this[i]=="function"&&(this[i]=this[i].bind(this))}Get(e){return new ie(e)}Position(){return this[s](Ci)}Center(){return this[s](Pi)}Close(){return this[s](Si)}DisableSizeConstraints(){return this[s](Ti)}EnableSizeConstraints(){return this[s](Mi)}Focus(){return this[s](xi)}ForceReload(){return this[s](Ei)}Fullscreen(){return this[s](Ai)}GetScreen(){return this[s](Ri)}GetZoom(){return this[s](ki)}Height(){return this[s](Oi)}Hide(){return this[s](Fi)}IsFocused(){return this[s](Li)}IsFullscreen(){return this[s](Ii)}IsMaximised(){return this[s](Ui)}IsMinimised(){return this[s](Bi)}Maximise(){return this[s](Ni)}Minimise(){return this[s](ji)}Name(){return this[s](zi)}OpenDevTools(){return this[s](Hi)}RelativePosition(){return this[s](Vi)}Reload(){return this[s](Zi)}Resizable(){return this[s](_i)}Restore(){return this[s](Ki)}SetPosition(e,i){return this[s](Gi,{x:e,y:i})}SetAlwaysOnTop(e){return this[s](Yi,{alwaysOnTop:e})}SetBackgroundColour(e,i,t,o){return this[s](Xi,{r:e,g:i,b:t,a:o})}SetFrameless(e){return this[s](Ji,{frameless:e})}SetFullscreenButtonEnabled(e){return this[s](Qi,{enabled:e})}SetMaxSize(e,i){return this[s](qi,{width:e,height:i})}SetMinSize(e,i){return this[s]($i,{width:e,height:i})}SetRelativePosition(e,i){return this[s](et,{x:e,y:i})}SetResizable(e){return this[s](nt,{resizable:e})}SetSize(e,i){return this[s](it,{width:e,height:i})}SetTitle(e){return this[s](tt,{title:e})}SetZoom(e){return this[s](ot,{zoom:e})}Show(){return this[s](rt)}Size(){return this[s](at)}ToggleFullscreen(){return this[s](st)}ToggleMaximise(){return this[s](lt)}ToggleFrameless(){return this[s](dt)}UnFullscreen(){return this[s](ct)}UnMaximise(){return this[s](mt)}UnMinimise(){return this[s](ut)}Width(){return this[s](wt)}Zoom(){return this[s](pt)}ZoomIn(){return this[s](ft)}ZoomOut(){return this[s](gt)}ZoomReset(){return this[s](ht)}HandlePlatformFileDrop(e,i,t){var d,f;if(((f=(d=window._wails)==null?void 0:d.flags)==null?void 0:f.enableFileDrop)===!1)return;let o=document.elementFromPoint(i,t),a=ne(o);if(!a)return;let r={id:a.id,classList:Array.from(a.classList),attributes:{}};for(let y=0;y<a.attributes.length;y++){let Q=a.attributes[y];r.attributes[Q.name]=Q.value}let l={filenames:e,x:i,y:t,elementDetails:r};this[s](bt,l),Wn()}SetScreen(e){return this[s](vt,{screenID:e})}SnapAssist(){return this[s](Wt)}Print(){return this[s](yt)}},ye=ie,Pt=new ye("");function St(){let n=document.documentElement,e=0;n.addEventListener("dragenter",i=>{var a,r,l;if(!((a=i.dataTransfer)!=null&&a.types.includes("Files")))return;if(i.preventDefault(),((l=(r=window._wails)==null?void 0:r.flags)==null?void 0:l.enableFileDrop)===!1){i.dataTransfer.dropEffect="none";return}e++;let t=document.elementFromPoint(i.clientX,i.clientY),o=ne(t);m&&m!==o&&m.classList.remove(W),o?(o.classList.add(W),i.dataTransfer.dropEffect="copy",m=o):(i.dataTransfer.dropEffect="none",m=null)},!1),n.addEventListener("dragover",i=>{var a,r,l;if(!((a=i.dataTransfer)!=null&&a.types.includes("Files")))return;if(i.preventDefault(),((l=(r=window._wails)==null?void 0:r.flags)==null?void 0:l.enableFileDrop)===!1){i.dataTransfer.dropEffect="none";return}let t=document.elementFromPoint(i.clientX,i.clientY),o=ne(t);m&&m!==o&&m.classList.remove(W),o?(o.classList.contains(W)||o.classList.add(W),i.dataTransfer.dropEffect="copy",m=o):(i.dataTransfer.dropEffect="none",m=null)},!1),n.addEventListener("dragleave",i=>{var t,o,a;(t=i.dataTransfer)!=null&&t.types.includes("Files")&&(i.preventDefault(),((a=(o=window._wails)==null?void 0:o.flags)==null?void 0:a.enableFileDrop)!==!1&&i.relatedTarget!==null&&(e--,(e===0||m&&!m.contains(i.relatedTarget))&&(m&&(m.classList.remove(W),m=null),e=0)))},!1),n.addEventListener("drop",i=>{var t,o,a;if((t=i.dataTransfer)!=null&&t.types.includes("Files")&&(i.preventDefault(),((a=(o=window._wails)==null?void 0:o.flags)==null?void 0:a.enableFileDrop)!==!1&&(e=0,m&&(m.classList.remove(W),m=null),Dt()))){let r=[];if(i.dataTransfer.items){for(let l of i.dataTransfer.items)if(l.kind==="file"){let d=l.getAsFile();d&&r.push(d)}}else if(i.dataTransfer.files)for(let l of i.dataTransfer.files)r.push(l);r.length>0&&Ct(i.clientX,i.clientY,r)}},!1)}typeof window<"u"&&typeof document<"u"&&St();var A=Pt;function Tt(n,e=null){We(n,e)}function Mt(n,e){let i=A.Get(n),t=i[e];if(typeof t=="function")try{t.call(i)}catch(o){}}function Dn(n){let e=n.currentTarget;function i(o="Yes"){if(o!=="Yes")return;let a=e.getAttribute("wml-event")||e.getAttribute("data-wml-event"),r=e.getAttribute("wml-target-window")||e.getAttribute("data-wml-target-window")||"",l=e.getAttribute("wml-window")||e.getAttribute("data-wml-window"),d=e.getAttribute("wml-openurl")||e.getAttribute("data-wml-openurl");a!==null&&Tt(a),l!==null&&Mt(r,l),d!==null&&ue(d)}let t=e.getAttribute("wml-confirm")||e.getAttribute("data-wml-confirm");t?pe({Title:"Confirm",Message:t,Detached:!1,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(i):i()}var Z=Symbol("controller"),R=Symbol("triggerMap"),P=Symbol("elementCount"),De=class{constructor(){this[Z]=new AbortController}set(e,i){return{signal:this[Z].signal}}reset(){this[Z].abort(),this[Z]=new AbortController}},Ce=class{constructor(){this[R]=new WeakMap,this[P]=0}set(e,i){return this[R].has(e)||this[P]++,this[R].set(e,i),{}}reset(){if(!(this[P]<=0)){for(let e of document.body.querySelectorAll("*")){if(this[P]<=0)break;let i=this[R].get(e);i!=null&&this[P]--;for(let t of i||[])e.removeEventListener(t,Dn)}this[R]=new WeakMap,this[P]=0}}},Cn=fn()?new De:new Ce;function xt(n){let e=/\S+/g,i=n.getAttribute("wml-trigger")||n.getAttribute("data-wml-trigger")||"click",t=[],o;for(;(o=e.exec(i))!==null;)t.push(o[0]);let a=Cn.set(n,t);for(let r of t)n.addEventListener(r,Dn,a)}function Pe(){hn(Pn)}function Pn(){Cn.reset(),document.body.querySelectorAll("[wml-event], [wml-window], [wml-openurl], [data-wml-event], [data-wml-window], [data-wml-openurl]").forEach(xt)}window.wails=Te;Pe();var Ae={};p(Ae,{Capabilities:()=>Ot,Environment:()=>Ft,IsAMD64:()=>Ut,IsARM:()=>Bt,IsARM64:()=>Nt,IsAndroid:()=>Mn,IsDarkMode:()=>kt,IsDebug:()=>Ee,IsDesktop:()=>It,IsIOS:()=>Tn,IsLinux:()=>te,IsMac:()=>Sn,IsMobile:()=>Lt,IsWindows:()=>_,invoke:()=>S});var xe=u(c.System),Et=0,At=1,Rt=2,Me=(function(){var n,e,i,t,o,a;try{if((e=(n=window.chrome)==null?void 0:n.webview)!=null&&e.postMessage)return window.chrome.webview.postMessage.bind(window.chrome.webview);if((o=(t=(i=window.webkit)==null?void 0:i.messageHandlers)==null?void 0:t.external)!=null&&o.postMessage)return window.webkit.messageHandlers.external.postMessage.bind(window.webkit.messageHandlers.external);if((a=window.wails)!=null&&a.invoke)return r=>window.wails.invoke(typeof r=="string"?r:JSON.stringify(r))}catch(r){}return null})();function S(n){Me==null||Me(n)}function kt(){return xe(Et)}async function Ot(){return xe(Rt)}function Ft(){return xe(At)}function _(){var n,e;return((e=(n=window._wails)==null?void 0:n.environment)==null?void 0:e.OS)==="windows"}function te(){var n,e;return((e=(n=window._wails)==null?void 0:n.environment)==null?void 0:e.OS)==="linux"}function Sn(){var n,e;return((e=(n=window._wails)==null?void 0:n.environment)==null?void 0:e.OS)==="darwin"}function Tn(){var n,e;return((e=(n=window._wails)==null?void 0:n.environment)==null?void 0:e.OS)==="ios"}function Mn(){var n,e;return((e=(n=window._wails)==null?void 0:n.environment)==null?void 0:e.OS)==="android"}function Lt(){return Tn()||Mn()}function It(){return Sn()||_()||te()}function Ut(){var n,e;return((e=(n=window._wails)==null?void 0:n.environment)==null?void 0:e.Arch)==="amd64"}function Bt(){var n,e;return((e=(n=window._wails)==null?void 0:n.environment)==null?void 0:e.Arch)==="arm"}function Nt(){var n,e;return((e=(n=window._wails)==null?void 0:n.environment)==null?void 0:e.Arch)==="arm64"}function Ee(){var n,e;return!!((e=(n=window._wails)==null?void 0:n.environment)!=null&&e.Debug)}w&&window.addEventListener("contextmenu",Vt);var jt=u(c.ContextMenu),zt=0;function Ht(n,e,i,t){jt(zt,{id:n,x:e,y:i,data:t})}function Vt(n){let e=ee(n),i=window.getComputedStyle(e).getPropertyValue("--custom-contextmenu").trim();if(i){n.preventDefault();let t=window.getComputedStyle(e).getPropertyValue("--custom-contextmenu-data");Ht(i,n.clientX,n.clientY,t)}else Zt(n,e)}function Zt(n,e){if(Ee())return;switch(window.getComputedStyle(e).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":n.preventDefault();return}if(e.isContentEditable)return;let i=window.getSelection(),t=i&&i.toString().length>0;if(t)for(let o=0;o<i.rangeCount;o++){let r=i.getRangeAt(o).getClientRects();for(let l=0;l<r.length;l++){let d=r[l];if(document.elementFromPoint(d.left,d.top)===e)return}}(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement)&&(t||!e.readOnly&&!e.disabled)||n.preventDefault()}var Re={};p(Re,{GetFlag:()=>k});function k(n){try{return window._wails.flags[n]}catch(e){throw new Error("Unable to retrieve flag '"+n+"': "+e,{cause:e})}}var K=!1,G=!1,Ie=!1,F=!1,L=!1,T="",xn="auto",O=0,oe=!1;w&&(oe=pn(),window._wails=window._wails||{},window._wails.setResizable=n=>{Ie=n,Ie||(F=L=!1,h())});var Ue=!1;function _t(){var i,t;let n=(t=(i=window._wails)==null?void 0:i.environment)==null?void 0:t.OS;if(n==="ios"||n==="android")return!0;let e=navigator.userAgent||navigator.vendor||window.opera||"";return/android|iphone|ipad|ipod|iemobile|wpdesktop/i.test(e)}function ke(){if(!Ue&&!_t()){window.addEventListener("mousedown",Le,{capture:!0}),window.addEventListener("mousemove",Le,{capture:!0}),window.addEventListener("mouseup",Le,{capture:!0});for(let n of["click","contextmenu","dblclick"])window.addEventListener(n,Kt,{capture:!0});Ue=!0}}if(w){ke(),document.addEventListener("DOMContentLoaded",ke,{once:!0});let n=0,e=window.setInterval(()=>{if(Ue){window.clearInterval(e);return}ke(),++n>100&&window.clearInterval(e)},50)}function Kt(n){(G||L)&&(n.stopImmediatePropagation(),n.stopPropagation(),n.preventDefault())}var Oe=0,Gt=1,Fe=2;function Le(n){let e,i=n.buttons;switch(n.type){case"mousedown":e=Oe,oe||(i=O|1<<n.button);break;case"mouseup":e=Gt,oe||(i=O&~(1<<n.button));break;default:e=Fe,oe||(i=O);break}let t=O&~i,o=i&~O;O=i,e===Oe&&!(o&n.button)&&(t|=1<<n.button,o|=1<<n.button),(e!==Fe&&L||G&&(e===Oe||n.button!==0))&&(n.stopImmediatePropagation(),n.stopPropagation(),n.preventDefault()),t&1&&Xt(n),o&1&&Yt(n),e===Fe&&Qt(n)}function Yt(n){if(K=!1,F=!1,!_()&&n.type==="mousedown"&&n.button===0&&n.detail!==1)return;if(T){F=!0;return}let e=ee(n),i=window.getComputedStyle(e);K=i.getPropertyValue("--wails-draggable").trim()==="drag"&&n.offsetX-parseFloat(i.paddingLeft)<e.clientWidth&&n.offsetY-parseFloat(i.paddingTop)<e.clientHeight}function Xt(n){K=!1,G=!1,F=!1,L=!1}var Jt=Object.freeze({"se-resize":"nwse-resize","sw-resize":"nesw-resize","nw-resize":"nwse-resize","ne-resize":"nesw-resize","w-resize":"ew-resize","n-resize":"ns-resize","s-resize":"ns-resize","e-resize":"ew-resize"});function h(n){n?(T||(xn=document.body.style.cursor),document.body.style.cursor=Jt[n]):!n&&T&&(document.body.style.cursor=xn),T=n||""}function Qt(n){if(F&&T?(L=!0,S("wails:resize:"+T)):K&&(G=!0,S("wails:drag")),G||L){K=F=!1;return}if(!Ie||!_()&&!(te()&&k("frameless"))){T&&h();return}let e=k("system.resizeHandleHeight")||5,i=k("system.resizeHandleWidth")||5,t=k("resizeCornerExtra")||10,o=Math.max(0,window.innerWidth-document.documentElement.clientWidth),a=Math.max(0,window.innerHeight-document.documentElement.clientHeight),r=window.innerWidth-o,l=window.innerHeight-a,d=n.clientX<r&&r-n.clientX<i,f=n.clientX<i,y=n.clientY<e,Q=n.clientY<l&&l-n.clientY<e,le=n.clientX<r&&r-n.clientX<i+t,de=n.clientX<i+t,ce=n.clientY<e+t,me=n.clientY<l&&l-n.clientY<e+t;!de&&!ce&&!me&&!le?h():le&&me?h("se-resize"):de&&me?h("sw-resize"):de&&ce?h("nw-resize"):ce&&le?h("ne-resize"):f?h("w-resize"):y?h("n-resize"):Q?h("s-resize"):d?h("e-resize"):h()}var Ne={};p(Ne,{Hide:()=>no,Quit:()=>to,Show:()=>io});var Be=u(c.Application),qt=0,$t=1,eo=2;function no(){return Be(qt)}function io(){return Be($t)}function to(){return Be(eo)}var Ge={};p(Ge,{ByID:()=>Po,ByName:()=>Co,Call:()=>Ke,RuntimeError:()=>_e});var An=Function.prototype.toString,I=typeof Reflect=="object"&&Reflect!==null&&Reflect.apply,je,re;if(typeof I=="function"&&typeof Object.defineProperty=="function")try{je=Object.defineProperty({},"length",{get:function(){throw re}}),re={},I(function(){throw 42},null,je)}catch(n){n!==re&&(I=null)}else I=null;var oo=/^\s*class\b/,He=function(e){try{var i=An.call(e);return oo.test(i)}catch(t){return!1}},ze=function(e){try{return He(e)?!1:(An.call(e),!0)}catch(i){return!1}},ae=Object.prototype.toString,ro="[object Object]",ao="[object Function]",so="[object GeneratorFunction]",lo="[object HTMLAllCollection]",co="[object HTML document.all class]",mo="[object HTMLCollection]",uo=typeof Symbol=="function"&&!!Symbol.toStringTag,wo=!(0 in[,]),Ve=function(){return!1};typeof document=="object"&&(En=document.all,ae.call(En)===ae.call(document.all)&&(Ve=function(e){if((wo||!e)&&(typeof e>"u"||typeof e=="object"))try{var i=ae.call(e);return(i===lo||i===co||i===mo||i===ro)&&e("")==null}catch(t){}return!1}));var En;function po(n){if(Ve(n))return!0;if(!n||typeof n!="function"&&typeof n!="object")return!1;try{I(n,null,je)}catch(e){if(e!==re)return!1}return!He(n)&&ze(n)}function fo(n){if(Ve(n))return!0;if(!n||typeof n!="function"&&typeof n!="object")return!1;if(uo)return ze(n);if(He(n))return!1;var e=ae.call(n);return e!==ao&&e!==so&&!/^\[object HTML/.test(e)?!1:ze(n)}var v=I?po:fo;var B=class extends Error{constructor(e,i){super(e,i),this.name="CancelError"}},D=class extends Error{constructor(e,i,t){super((t!=null?t:"Unhandled rejection in cancelled promise.")+" Reason: "+go(i),{cause:i}),this.promise=e,this.name="CancelledRejectionError"}},b=Symbol("barrier"),Ze=Symbol("cancelImpl"),Fn,Rn=(Fn=Symbol.species)!=null?Fn:Symbol("speciesPolyfill"),Y=class n extends Promise{constructor(e,i){let t,o;if(super((d,f)=>{t=d,o=f}),this.constructor[Rn]!==Promise)throw new TypeError("CancellablePromise does not support transparent subclassing. Please refrain from overriding the [Symbol.species] static property.");let a={promise:this,resolve:t,reject:o,get oncancelled(){return i!=null?i:null},set oncancelled(d){i=d!=null?d:void 0}},r={get root(){return r},resolving:!1,settled:!1};Object.defineProperties(this,{[b]:{configurable:!1,enumerable:!1,writable:!0,value:null},[Ze]:{configurable:!1,enumerable:!1,writable:!1,value:Ln(a,r)}});let l=Un(a,r);try{e(In(a,r),l)}catch(d){r.resolving||l(d)}}cancel(e){return new n(i=>{Promise.all([this[Ze](new B("Promise cancelled.",{cause:e})),ho(this)]).then(()=>i(),()=>i())})}cancelOn(e){return e.aborted?this.cancel(e.reason):e.addEventListener("abort",()=>{this.cancel(e.reason)},{capture:!0}),this}then(e,i,t){if(!(this instanceof n))throw new TypeError("CancellablePromise.prototype.then called on an invalid object.");if(v(e)||(e=kn),v(i)||(i=On),e===kn&&i==On)return new n(a=>a(this));let o={};return this[b]=o,new n((a,r)=>{super.then(l=>{var d;this[b]===o&&(this[b]=null),(d=o.resolve)==null||d.call(o);try{a(e(l))}catch(f){r(f)}},l=>{var d;this[b]===o&&(this[b]=null),(d=o.resolve)==null||d.call(o);try{a(i(l))}catch(f){r(f)}})},async a=>{try{return t==null?void 0:t(a)}finally{await this.cancel(a)}})}catch(e,i){return this.then(void 0,e,i)}finally(e,i){if(!(this instanceof n))throw new TypeError("CancellablePromise.prototype.finally called on an invalid object.");return v(e)?this.then(t=>n.resolve(e()).then(()=>t),t=>n.resolve(e()).then(()=>{throw t}),i):this.then(e,e,i)}static get[(b,Ze,Rn)](){return Promise}static all(e){let i=Array.from(e),t=i.length===0?n.resolve(i):new n((o,a)=>{Promise.all(i).then(o,a)},o=>se(t,i,o));return t}static allSettled(e){let i=Array.from(e),t=i.length===0?n.resolve(i):new n((o,a)=>{Promise.allSettled(i).then(o,a)},o=>se(t,i,o));return t}static any(e){let i=Array.from(e),t=i.length===0?n.resolve(i):new n((o,a)=>{Promise.any(i).then(o,a)},o=>se(t,i,o));return t}static race(e){let i=Array.from(e),t=new n((o,a)=>{Promise.race(i).then(o,a)},o=>se(t,i,o));return t}static cancel(e){let i=new n(()=>{});return i.cancel(e),i}static timeout(e,i){let t=new n(()=>{});return AbortSignal&&typeof AbortSignal=="function"&&AbortSignal.timeout&&typeof AbortSignal.timeout=="function"?AbortSignal.timeout(e).addEventListener("abort",()=>{t.cancel(i)}):setTimeout(()=>{t.cancel(i)},e),t}static sleep(e,i){return new n(t=>{setTimeout(()=>t(i),e)})}static reject(e){return new n((i,t)=>t(e))}static resolve(e){return e instanceof n?e:new n(i=>i(e))}static withResolvers(){let e={oncancelled:null};return e.promise=new n((i,t)=>{e.resolve=i,e.reject=t},i=>{var t;(t=e.oncancelled)==null||t.call(e,i)}),e}};function Ln(n,e){let i;return t=>{if(e.settled||(e.settled=!0,e.reason=t,n.reject(t),Promise.prototype.then.call(n.promise,void 0,o=>{if(o!==t)throw o})),!(!e.reason||!n.oncancelled))return i=new Promise(o=>{try{o(n.oncancelled(e.reason.cause))}catch(a){Promise.reject(new D(n.promise,a,"Unhandled exception in oncancelled callback."))}}).catch(o=>{Promise.reject(new D(n.promise,o,"Unhandled rejection in oncancelled callback."))}),n.oncancelled=null,i}}function In(n,e){return i=>{if(!e.resolving){if(e.resolving=!0,i===n.promise){if(e.settled)return;e.settled=!0,n.reject(new TypeError("A promise cannot be resolved with itself."));return}if(i!=null&&(typeof i=="object"||typeof i=="function")){let t;try{t=i.then}catch(o){e.settled=!0,n.reject(o);return}if(v(t)){try{let r=i.cancel;if(v(r)){let l=d=>{Reflect.apply(r,i,[d])};e.reason?Ln(j(N({},n),{oncancelled:l}),e)(e.reason):n.oncancelled=l}}catch(r){}let o={root:e.root,resolving:!1,get settled(){return this.root.settled},set settled(r){this.root.settled=r},get reason(){return this.root.reason}},a=Un(n,o);try{Reflect.apply(t,i,[In(n,o),a])}catch(r){a(r)}return}}e.settled||(e.settled=!0,n.resolve(i))}}}function Un(n,e){return i=>{if(!e.resolving)if(e.resolving=!0,e.settled){try{if(i instanceof B&&e.reason instanceof B&&Object.is(i.cause,e.reason.cause))return}catch(t){}Promise.reject(new D(n.promise,i))}else e.settled=!0,n.reject(i)}}function se(n,e,i){let t=[];for(let o of e){let a;try{if(!v(o.then)||(a=o.cancel,!v(a)))continue}catch(l){continue}let r;try{r=Reflect.apply(a,o,[i])}catch(l){Promise.reject(new D(n,l,"Unhandled exception in cancel method."));continue}r&&t.push((r instanceof Promise?r:Promise.resolve(r)).catch(l=>{Promise.reject(new D(n,l,"Unhandled rejection in cancel method."))}))}return Promise.all(t)}function kn(n){return n}function On(n){throw n}function go(n){try{if(n instanceof Error||typeof n!="object"||n.toString!==Object.prototype.toString)return""+n}catch(e){}try{return JSON.stringify(n)}catch(e){}try{return Object.prototype.toString.call(n)}catch(e){}return"<could not convert error to string>"}function ho(n){var i;let e=(i=n[b])!=null?i:{};return"promise"in e||Object.assign(e,U()),n[b]==null&&(e.resolve(),n[b]=e),e.promise}var U=Promise.withResolvers;U&&typeof U=="function"?U=U.bind(Promise):U=function(){let n,e;return{promise:new Promise((t,o)=>{n=t,e=o}),resolve:n,reject:e}};w&&(window._wails=window._wails||{});var Wo=u(c.Call),bo=u(c.CancelCall),X=new Map,yo=0,vo=0,_e=class extends Error{constructor(e,i){super(e,i),this.name="RuntimeError"}};function Do(){let n;do n=M();while(X.has(n));return n}function Ke(n){let e=Do(),i=Y.withResolvers();X.set(e,{resolve:i.resolve,reject:i.reject});let t=Wo(yo,Object.assign({"call-id":e},n)),o=!0;t.then(r=>{o=!1,X.delete(e),i.resolve(r)},r=>{o=!1,X.delete(e),i.reject(r)});let a=()=>(X.delete(e),bo(vo,{"call-id":e}).catch(r=>{}));return i.oncancelled=()=>o?a():t.then(a),i.promise}function Co(n,...e){return Ke({methodName:n,args:e})}function Po(n,...e){return Ke({methodID:n,args:e})}var Ye={};p(Ye,{SetText:()=>Mo,Text:()=>xo});var Bn=u(c.Clipboard),So=0,To=1;function Mo(n){return Bn(So,{text:n})}function xo(){return Bn(To)}var Xe={};p(Xe,{GetAll:()=>Fo,GetByID:()=>Uo,GetByIndex:()=>Bo,GetCurrent:()=>Io,GetPrimary:()=>Lo});var J=u(c.Screens),Eo=0,Ao=1,Ro=2,ko=3,Oo=4;function Fo(){return J(Eo)}function Lo(){return J(Ao)}function Io(){return J(Ro)}function Uo(n){return J(ko,{id:n})}function Bo(n){return J(Oo,{index:n})}var qe={};p(qe,{Device:()=>Qe,Haptics:()=>Je});var Nn=u(c.IOS),No=0,jo=1,Je;(e=>{function n(i="medium"){return Nn(No,{style:i})}e.Impact=n})(Je||(Je={}));var Qe;(e=>{function n(){return Nn(jo)}e.Info=n})(Qe||(Qe={}));var on={};p(on,{Device:()=>en,Haptics:()=>$e,Toast:()=>nn});var tn=u(c.Android),zo=0,Ho=1,Vo=2,$e;(e=>{function n(i=100){return tn(zo,{duration:i})}e.Vibrate=n})($e||($e={}));var en;(e=>{function n(){return tn(Ho)}e.Info=n})(en||(en={}));var nn;(e=>{function n(i){return tn(Vo,{message:i})}e.Show=n})(nn||(nn={}));var rn={};p(rn,{Events:()=>Zo});var Zo=Object.freeze({CheckStarted:"wails:updater:check-started",UpdateAvailable:"wails:updater:update-available",NoUpdate:"wails:updater:no-update",DownloadStarted:"wails:updater:download-started",DownloadProgress:"wails:updater:download-progress",DownloadComplete:"wails:updater:download-complete",Verifying:"wails:updater:verifying",Installing:"wails:updater:installing",UpdateReady:"wails:updater:update-ready",Error:"wails:updater:error",Meta:"wails:updater:meta",User:Object.freeze({Install:"wails:updater:user:install",Restart:"wails:updater:user:restart",Skip:"wails:updater:user:skip",Remind:"wails:updater:user:remind",Cancel:"wails:updater:user:cancel"}),Window:Object.freeze({Ready:"wails:updater:window:ready"})});w&&(window._wails=window._wails||{});w&&(window._wails.invoke=S,window._wails.clientId=x);w&&(window._wails.handlePlatformFileDrop=A.HandlePlatformFileDrop.bind(A));w&&(window._wails.handleDragEnter=bn,window._wails.handleDragLeave=yn,window._wails.handleDragOver=vn);w&&S("wails:runtime:ready");function jn(n){return fetch(n,{method:"HEAD"}).then(e=>{if(e.ok&&(e.headers.get("content-type")||"").toLowerCase().includes("javascript")){let t=document.createElement("script");t.src=n,document.head.appendChild(t)}}).catch(()=>{})}w&&jn("/wails/custom.js");export{on as Android,Ne as Application,we as Browser,Ge as Call,B as CancelError,Y as CancellablePromise,D as CancelledRejectionError,Ye as Clipboard,ge as Create,fe as Dialogs,be as Events,Re as Flags,qe as IOS,Xe as Screens,Ae as System,rn as Updater,Se as WML,A as Window,x as clientId,un as getTransport,jn as loadOptionalScript,c as objectNames,mn as setTransport}; +var wn=Object.defineProperty,Jn=Object.defineProperties;var qn=Object.getOwnPropertyDescriptors;var mn=Object.getOwnPropertySymbols;var Qn=Object.prototype.hasOwnProperty,$n=Object.prototype.propertyIsEnumerable;var un=(n,e,i)=>e in n?wn(n,e,{enumerable:!0,configurable:!0,writable:!0,value:i}):n[e]=i,V=(n,e)=>{for(var i in e||(e={}))Qn.call(e,i)&&un(n,i,e[i]);if(mn)for(var i of mn(e))$n.call(e,i)&&un(n,i,e[i]);return n},Z=(n,e)=>Jn(n,qn(e));var p=(n,e)=>{for(var i in e)wn(n,i,{get:e[i],enumerable:!0})};var Ae={};p(Ae,{Android:()=>dn,Application:()=>Ke,Browser:()=>he,Call:()=>Qe,CancelError:()=>H,CancellablePromise:()=>ee,CancelledRejectionError:()=>T,Clipboard:()=>$e,Create:()=>ye,Dialogs:()=>be,Events:()=>De,Flags:()=>Le,IOS:()=>on,Screens:()=>en,System:()=>Fe,Updater:()=>cn,WML:()=>xe,Window:()=>F,clientId:()=>k,getTransport:()=>hn,loadOptionalScript:()=>Xn,objectNames:()=>c,setTransport:()=>gn});var xe={};p(xe,{Enable:()=>Ee,Reload:()=>En});var he={};p(he,{OpenURL:()=>ge});var ei="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";function R(n=21){let e="",i=n|0;for(;i--;)e+=ei[Math.random()*64|0];return e}var u=typeof window<"u"&&typeof document<"u";function ni(){return window.location.origin+"/wails/runtime"}var K=512*1024;var _=class extends Error{constructor(e,i){super(e,i),this.name="RuntimeError"}},c=Object.freeze({Call:0,Clipboard:1,Application:2,Events:3,ContextMenu:4,Dialog:5,Window:6,Screens:7,System:8,Browser:9,CancelCall:10,IOS:11,Android:12}),k=R(),G=null;function gn(n){G=n}function hn(){return G}function w(n,e=""){return function(i,t=null){return ii(n,i,e,t)}}async function ii(n,e,i,t){var f,D;if(G)return G.call(n,e,i,t);let o=new URL(ni()),r={object:n,method:e};t!=null&&(r.args=t);let a={"x-wails-client-id":k,"Content-Type":"application/json"};i&&(a["x-wails-window-name"]=i);let l=JSON.stringify(r),d;if(l.length>K?d=await ti(o,a,l):d=await fetch(o,{method:"POST",headers:a,body:l}),!d.ok){let S=d.headers.get("Content-Type");if(S!=null&&S.includes("application/json")){let W=await d.json(),b;switch(W.kind){case"ReferenceError":b=new ReferenceError(W.message);break;case"TypeError":b=new TypeError(W.message);break;case"RuntimeError":b=new _(W.message);break;default:b=new Error(W.message)}throw b.cause=W.cause,b}throw new Error(await d.text())}return((D=(f=d.headers.get("Content-Type"))==null?void 0:f.indexOf("application/json"))!=null?D:-1)!==-1?d.json():d.text()}async function ti(n,e,i){let t=R(),o=new TextEncoder().encode(i),r=Math.ceil(o.length/K);for(let a=0;a<r-1;a++){let l=o.subarray(a*K,(a+1)*K),d=await fetch(n,{method:"POST",headers:Z(V({},e),{"x-wails-chunk-id":t,"x-wails-chunk-index":String(a),"x-wails-chunk-total":String(r)}),body:l});if(!d.ok)throw new Error(await d.text())}return fetch(n,{method:"POST",headers:Z(V({},e),{"x-wails-chunk-id":t,"x-wails-chunk-index":String(r-1),"x-wails-chunk-total":String(r)}),body:o.subarray((r-1)*K)})}var fn,pn=u&&typeof((fn=window.wails)==null?void 0:fn.invokeAsync)=="function"?window.wails:null;if(pn){let n=new Map;window._wailsAndroidCallback=(e,i,t)=>{var r;let o=n.get(e);if(o){if(n.delete(e),t){o.reject(new Error(t));return}try{let a=JSON.parse(i!=null?i:"{}");if(!a.ok){o.reject(new Error((r=a.error)!=null?r:"unknown runtime call error"));return}o.resolve("text"in a?a.text:a.data)}catch(a){o.reject(a)}}},G={call(e,i,t,o){return new Promise((r,a)=>{let l=R();n.set(l,{resolve:r,reject:a});try{pn.invokeAsync(l,JSON.stringify({object:e,method:i,windowName:t,args:o!=null?o:null,clientId:k}))}catch(d){n.delete(l),a(d)}})}}}var oi=w(c.Browser),ri=0;function ge(n){return oi(ri,{url:n.toString()})}var be={};p(be,{Error:()=>fi,Info:()=>wi,OpenFile:()=>gi,Question:()=>We,SaveFile:()=>hi,Warning:()=>pi});u&&(window._wails=window._wails||{});var ai=w(c.Dialog),si=0,li=1,di=2,ci=3,mi=4,ui=5;function O(n,e={}){return ai(n,e)}function wi(n){return O(si,n)}function pi(n){return O(li,n)}function fi(n){return O(di,n)}function We(n){return O(ci,n)}function gi(n){var e;return(e=O(mi,n))!=null?e:[]}function hi(n){return O(ui,n)}var De={};p(De,{Emit:()=>Ce,Off:()=>Ai,OffAll:()=>Ri,On:()=>Ei,OnMultiple:()=>ve,Once:()=>xi,Types:()=>Si,WailsEvent:()=>Y});var g=new Map,te=class{constructor(e,i,t){this.eventName=e,this.callback=i,this.maxCallbacks=t||-1}dispatch(e){try{this.callback(e)}catch(i){}return this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0)}};function Wn(n){let e=g.get(n.eventName);e&&(e=e.filter(i=>i!==n),e.length===0?g.delete(n.eventName):g.set(n.eventName,e))}var ye={};p(ye,{Any:()=>M,Array:()=>bi,ByteSlice:()=>Wi,DateFromTime:()=>Di,Events:()=>oe,Map:()=>yi,Nullable:()=>vi,Struct:()=>Ci});function M(n){return n}function Wi(n){return n==null?"":n}function bi(n){return n===M?e=>e===null?[]:e:e=>{if(e===null)return[];for(let i=0;i<e.length;i++)e[i]=n(e[i]);return e}}function yi(n,e){return e===M?i=>i===null?{}:i:i=>{if(i===null)return{};for(let t in i)i[t]=e(i[t]);return i}}function vi(n){return n===M?M:e=>e===null?null:n(e)}function Ci(n){let e=!0;for(let i in n)if(n[i]!==M){e=!1;break}return e?M:i=>{for(let t in n)t in i&&(i[t]=n[t](i[t]));return i}}function Di(n){return new Date(n)}var oe={};var Si=Object.freeze({Windows:Object.freeze({APMPowerSettingChange:"windows:APMPowerSettingChange",APMPowerStatusChange:"windows:APMPowerStatusChange",APMResumeAutomatic:"windows:APMResumeAutomatic",APMResumeSuspend:"windows:APMResumeSuspend",APMSuspend:"windows:APMSuspend",ApplicationStarted:"windows:ApplicationStarted",SystemThemeChanged:"windows:SystemThemeChanged",WebViewNavigationCompleted:"windows:WebViewNavigationCompleted",WindowActive:"windows:WindowActive",WindowBackgroundErase:"windows:WindowBackgroundErase",WindowClickActive:"windows:WindowClickActive",WindowClosing:"windows:WindowClosing",WindowDidMove:"windows:WindowDidMove",WindowDidResize:"windows:WindowDidResize",WindowDPIChanged:"windows:WindowDPIChanged",WindowDragDrop:"windows:WindowDragDrop",WindowDragEnter:"windows:WindowDragEnter",WindowDragLeave:"windows:WindowDragLeave",WindowDragOver:"windows:WindowDragOver",WindowEndMove:"windows:WindowEndMove",WindowEndResize:"windows:WindowEndResize",WindowFullscreen:"windows:WindowFullscreen",WindowHide:"windows:WindowHide",WindowInactive:"windows:WindowInactive",WindowKeyDown:"windows:WindowKeyDown",WindowKeyUp:"windows:WindowKeyUp",WindowKillFocus:"windows:WindowKillFocus",WindowNonClientHit:"windows:WindowNonClientHit",WindowNonClientMouseDown:"windows:WindowNonClientMouseDown",WindowNonClientMouseLeave:"windows:WindowNonClientMouseLeave",WindowNonClientMouseMove:"windows:WindowNonClientMouseMove",WindowNonClientMouseUp:"windows:WindowNonClientMouseUp",WindowPaint:"windows:WindowPaint",WindowRestore:"windows:WindowRestore",WindowSetFocus:"windows:WindowSetFocus",WindowShow:"windows:WindowShow",WindowStartMove:"windows:WindowStartMove",WindowStartResize:"windows:WindowStartResize",WindowUnFullscreen:"windows:WindowUnFullscreen",WindowZOrderChanged:"windows:WindowZOrderChanged",WindowMinimise:"windows:WindowMinimise",WindowUnMinimise:"windows:WindowUnMinimise",WindowMaximise:"windows:WindowMaximise",WindowUnMaximise:"windows:WindowUnMaximise"}),Mac:Object.freeze({ApplicationDidBecomeActive:"mac:ApplicationDidBecomeActive",ApplicationDidChangeBackingProperties:"mac:ApplicationDidChangeBackingProperties",ApplicationDidChangeEffectiveAppearance:"mac:ApplicationDidChangeEffectiveAppearance",ApplicationDidChangeIcon:"mac:ApplicationDidChangeIcon",ApplicationDidChangeOcclusionState:"mac:ApplicationDidChangeOcclusionState",ApplicationDidChangeScreenParameters:"mac:ApplicationDidChangeScreenParameters",ApplicationDidChangeStatusBarFrame:"mac:ApplicationDidChangeStatusBarFrame",ApplicationDidChangeStatusBarOrientation:"mac:ApplicationDidChangeStatusBarOrientation",ApplicationDidChangeTheme:"mac:ApplicationDidChangeTheme",ApplicationDidFinishLaunching:"mac:ApplicationDidFinishLaunching",ApplicationDidHide:"mac:ApplicationDidHide",ApplicationDidResignActive:"mac:ApplicationDidResignActive",ApplicationDidUnhide:"mac:ApplicationDidUnhide",ApplicationDidUpdate:"mac:ApplicationDidUpdate",ApplicationDidWake:"mac:ApplicationDidWake",ApplicationScreensDidSleep:"mac:ApplicationScreensDidSleep",ApplicationScreensDidWake:"mac:ApplicationScreensDidWake",ApplicationShouldHandleReopen:"mac:ApplicationShouldHandleReopen",ApplicationWillBecomeActive:"mac:ApplicationWillBecomeActive",ApplicationWillFinishLaunching:"mac:ApplicationWillFinishLaunching",ApplicationWillHide:"mac:ApplicationWillHide",ApplicationWillResignActive:"mac:ApplicationWillResignActive",ApplicationWillSleep:"mac:ApplicationWillSleep",ApplicationWillTerminate:"mac:ApplicationWillTerminate",ApplicationWillUnhide:"mac:ApplicationWillUnhide",ApplicationWillUpdate:"mac:ApplicationWillUpdate",MenuDidAddItem:"mac:MenuDidAddItem",MenuDidBeginTracking:"mac:MenuDidBeginTracking",MenuDidClose:"mac:MenuDidClose",MenuDidDisplayItem:"mac:MenuDidDisplayItem",MenuDidEndTracking:"mac:MenuDidEndTracking",MenuDidHighlightItem:"mac:MenuDidHighlightItem",MenuDidOpen:"mac:MenuDidOpen",MenuDidPopUp:"mac:MenuDidPopUp",MenuDidRemoveItem:"mac:MenuDidRemoveItem",MenuDidSendAction:"mac:MenuDidSendAction",MenuDidSendActionToItem:"mac:MenuDidSendActionToItem",MenuDidUpdate:"mac:MenuDidUpdate",MenuWillAddItem:"mac:MenuWillAddItem",MenuWillBeginTracking:"mac:MenuWillBeginTracking",MenuWillDisplayItem:"mac:MenuWillDisplayItem",MenuWillEndTracking:"mac:MenuWillEndTracking",MenuWillHighlightItem:"mac:MenuWillHighlightItem",MenuWillOpen:"mac:MenuWillOpen",MenuWillPopUp:"mac:MenuWillPopUp",MenuWillRemoveItem:"mac:MenuWillRemoveItem",MenuWillSendAction:"mac:MenuWillSendAction",MenuWillSendActionToItem:"mac:MenuWillSendActionToItem",MenuWillUpdate:"mac:MenuWillUpdate",WebViewDidCommitNavigation:"mac:WebViewDidCommitNavigation",WebViewDidFinishNavigation:"mac:WebViewDidFinishNavigation",WebViewDidReceiveServerRedirectForProvisionalNavigation:"mac:WebViewDidReceiveServerRedirectForProvisionalNavigation",WebViewDidStartProvisionalNavigation:"mac:WebViewDidStartProvisionalNavigation",WindowDidBecomeKey:"mac:WindowDidBecomeKey",WindowDidBecomeMain:"mac:WindowDidBecomeMain",WindowDidBeginSheet:"mac:WindowDidBeginSheet",WindowDidChangeAlpha:"mac:WindowDidChangeAlpha",WindowDidChangeBackingLocation:"mac:WindowDidChangeBackingLocation",WindowDidChangeBackingProperties:"mac:WindowDidChangeBackingProperties",WindowDidChangeCollectionBehavior:"mac:WindowDidChangeCollectionBehavior",WindowDidChangeEffectiveAppearance:"mac:WindowDidChangeEffectiveAppearance",WindowDidChangeOcclusionState:"mac:WindowDidChangeOcclusionState",WindowDidChangeOrderingMode:"mac:WindowDidChangeOrderingMode",WindowDidChangeScreen:"mac:WindowDidChangeScreen",WindowDidChangeScreenParameters:"mac:WindowDidChangeScreenParameters",WindowDidChangeScreenProfile:"mac:WindowDidChangeScreenProfile",WindowDidChangeScreenSpace:"mac:WindowDidChangeScreenSpace",WindowDidChangeScreenSpaceProperties:"mac:WindowDidChangeScreenSpaceProperties",WindowDidChangeSharingType:"mac:WindowDidChangeSharingType",WindowDidChangeSpace:"mac:WindowDidChangeSpace",WindowDidChangeSpaceOrderingMode:"mac:WindowDidChangeSpaceOrderingMode",WindowDidChangeTitle:"mac:WindowDidChangeTitle",WindowDidChangeToolbar:"mac:WindowDidChangeToolbar",WindowDidDeminiaturize:"mac:WindowDidDeminiaturize",WindowDidEndSheet:"mac:WindowDidEndSheet",WindowDidEnterFullScreen:"mac:WindowDidEnterFullScreen",WindowDidEnterVersionBrowser:"mac:WindowDidEnterVersionBrowser",WindowDidExitFullScreen:"mac:WindowDidExitFullScreen",WindowDidExitVersionBrowser:"mac:WindowDidExitVersionBrowser",WindowDidExpose:"mac:WindowDidExpose",WindowDidFocus:"mac:WindowDidFocus",WindowDidMiniaturize:"mac:WindowDidMiniaturize",WindowDidMove:"mac:WindowDidMove",WindowDidOrderOffScreen:"mac:WindowDidOrderOffScreen",WindowDidOrderOnScreen:"mac:WindowDidOrderOnScreen",WindowDidResignKey:"mac:WindowDidResignKey",WindowDidResignMain:"mac:WindowDidResignMain",WindowDidResize:"mac:WindowDidResize",WindowDidUpdate:"mac:WindowDidUpdate",WindowDidUpdateAlpha:"mac:WindowDidUpdateAlpha",WindowDidUpdateCollectionBehavior:"mac:WindowDidUpdateCollectionBehavior",WindowDidUpdateCollectionProperties:"mac:WindowDidUpdateCollectionProperties",WindowDidUpdateShadow:"mac:WindowDidUpdateShadow",WindowDidUpdateTitle:"mac:WindowDidUpdateTitle",WindowDidUpdateToolbar:"mac:WindowDidUpdateToolbar",WindowDidZoom:"mac:WindowDidZoom",WindowFileDraggingEntered:"mac:WindowFileDraggingEntered",WindowFileDraggingExited:"mac:WindowFileDraggingExited",WindowFileDraggingPerformed:"mac:WindowFileDraggingPerformed",WindowHide:"mac:WindowHide",WindowMaximise:"mac:WindowMaximise",WindowUnMaximise:"mac:WindowUnMaximise",WindowMinimise:"mac:WindowMinimise",WindowUnMinimise:"mac:WindowUnMinimise",WindowShouldClose:"mac:WindowShouldClose",WindowShow:"mac:WindowShow",WindowWillBecomeKey:"mac:WindowWillBecomeKey",WindowWillBecomeMain:"mac:WindowWillBecomeMain",WindowWillBeginSheet:"mac:WindowWillBeginSheet",WindowWillChangeOrderingMode:"mac:WindowWillChangeOrderingMode",WindowWillClose:"mac:WindowWillClose",WindowWillDeminiaturize:"mac:WindowWillDeminiaturize",WindowWillEnterFullScreen:"mac:WindowWillEnterFullScreen",WindowWillEnterVersionBrowser:"mac:WindowWillEnterVersionBrowser",WindowWillExitFullScreen:"mac:WindowWillExitFullScreen",WindowWillExitVersionBrowser:"mac:WindowWillExitVersionBrowser",WindowWillFocus:"mac:WindowWillFocus",WindowWillMiniaturize:"mac:WindowWillMiniaturize",WindowWillMove:"mac:WindowWillMove",WindowWillOrderOffScreen:"mac:WindowWillOrderOffScreen",WindowWillOrderOnScreen:"mac:WindowWillOrderOnScreen",WindowWillResignMain:"mac:WindowWillResignMain",WindowWillResize:"mac:WindowWillResize",WindowWillUnfocus:"mac:WindowWillUnfocus",WindowWillUpdate:"mac:WindowWillUpdate",WindowWillUpdateAlpha:"mac:WindowWillUpdateAlpha",WindowWillUpdateCollectionBehavior:"mac:WindowWillUpdateCollectionBehavior",WindowWillUpdateCollectionProperties:"mac:WindowWillUpdateCollectionProperties",WindowWillUpdateShadow:"mac:WindowWillUpdateShadow",WindowWillUpdateTitle:"mac:WindowWillUpdateTitle",WindowWillUpdateToolbar:"mac:WindowWillUpdateToolbar",WindowWillUpdateVisibility:"mac:WindowWillUpdateVisibility",WindowWillUseStandardFrame:"mac:WindowWillUseStandardFrame",WindowZoomIn:"mac:WindowZoomIn",WindowZoomOut:"mac:WindowZoomOut",WindowZoomReset:"mac:WindowZoomReset",WebViewWebContentProcessDidTerminate:"mac:WebViewWebContentProcessDidTerminate"}),Linux:Object.freeze({ApplicationStartup:"linux:ApplicationStartup",SystemDidWake:"linux:SystemDidWake",SystemThemeChanged:"linux:SystemThemeChanged",SystemWillSleep:"linux:SystemWillSleep",WindowDeleteEvent:"linux:WindowDeleteEvent",WindowDidMove:"linux:WindowDidMove",WindowDidResize:"linux:WindowDidResize",WindowFocusIn:"linux:WindowFocusIn",WindowFocusOut:"linux:WindowFocusOut",WindowLoadStarted:"linux:WindowLoadStarted",WindowLoadRedirected:"linux:WindowLoadRedirected",WindowLoadCommitted:"linux:WindowLoadCommitted",WindowLoadFinished:"linux:WindowLoadFinished"}),iOS:Object.freeze({ApplicationDidBecomeActive:"ios:ApplicationDidBecomeActive",ApplicationDidEnterBackground:"ios:ApplicationDidEnterBackground",ApplicationDidFinishLaunching:"ios:ApplicationDidFinishLaunching",ApplicationDidReceiveMemoryWarning:"ios:ApplicationDidReceiveMemoryWarning",ApplicationWillEnterForeground:"ios:ApplicationWillEnterForeground",ApplicationWillResignActive:"ios:ApplicationWillResignActive",ApplicationWillTerminate:"ios:ApplicationWillTerminate",WindowDidLoad:"ios:WindowDidLoad",WindowWillAppear:"ios:WindowWillAppear",WindowDidAppear:"ios:WindowDidAppear",WindowWillDisappear:"ios:WindowWillDisappear",WindowDidDisappear:"ios:WindowDidDisappear",WindowSafeAreaInsetsChanged:"ios:WindowSafeAreaInsetsChanged",WindowOrientationChanged:"ios:WindowOrientationChanged",WindowTouchBegan:"ios:WindowTouchBegan",WindowTouchMoved:"ios:WindowTouchMoved",WindowTouchEnded:"ios:WindowTouchEnded",WindowTouchCancelled:"ios:WindowTouchCancelled",WebViewDidStartNavigation:"ios:WebViewDidStartNavigation",WebViewDidFinishNavigation:"ios:WebViewDidFinishNavigation",WebViewDidFailNavigation:"ios:WebViewDidFailNavigation",WebViewDecidePolicyForNavigationAction:"ios:WebViewDecidePolicyForNavigationAction",BatteryChanged:"ios:BatteryChanged",NetworkChanged:"ios:NetworkChanged",ThemeChanged:"ios:ThemeChanged",ScreenLocked:"ios:ScreenLocked",ScreenUnlocked:"ios:ScreenUnlocked"}),Android:Object.freeze({ActivityCreated:"android:ActivityCreated",ActivityStarted:"android:ActivityStarted",ActivityResumed:"android:ActivityResumed",ActivityPaused:"android:ActivityPaused",ActivityStopped:"android:ActivityStopped",ActivityDestroyed:"android:ActivityDestroyed",ApplicationLowMemory:"android:ApplicationLowMemory",WebViewPageStarted:"android:WebViewPageStarted",WebViewPageFinished:"android:WebViewPageFinished",BatteryChanged:"android:BatteryChanged",NetworkChanged:"android:NetworkChanged",ThemeChanged:"android:ThemeChanged",ScreenLocked:"android:ScreenLocked",ScreenUnlocked:"android:ScreenUnlocked"}),Common:Object.freeze({ApplicationOpenedWithFile:"common:ApplicationOpenedWithFile",ApplicationStarted:"common:ApplicationStarted",ApplicationLaunchedWithUrl:"common:ApplicationLaunchedWithUrl",ThemeChanged:"common:ThemeChanged",SystemDidWake:"common:SystemDidWake",SystemWillSleep:"common:SystemWillSleep",WindowClosing:"common:WindowClosing",WindowDidMove:"common:WindowDidMove",WindowDidResize:"common:WindowDidResize",WindowDPIChanged:"common:WindowDPIChanged",WindowFilesDropped:"common:WindowFilesDropped",WindowFocus:"common:WindowFocus",WindowFullscreen:"common:WindowFullscreen",WindowHide:"common:WindowHide",WindowLostFocus:"common:WindowLostFocus",WindowMaximise:"common:WindowMaximise",WindowMinimise:"common:WindowMinimise",WindowToggleFrameless:"common:WindowToggleFrameless",WindowRestore:"common:WindowRestore",WindowRuntimeReady:"common:WindowRuntimeReady",WindowShow:"common:WindowShow",WindowUnFullscreen:"common:WindowUnFullscreen",WindowUnMaximise:"common:WindowUnMaximise",WindowUnMinimise:"common:WindowUnMinimise",WindowZoom:"common:WindowZoom",WindowZoomIn:"common:WindowZoomIn",WindowZoomOut:"common:WindowZoomOut",WindowZoomReset:"common:WindowZoomReset",BatteryChanged:"common:BatteryChanged",NetworkChanged:"common:NetworkChanged",ScreenLocked:"common:ScreenLocked",ScreenUnlocked:"common:ScreenUnlocked",LowMemory:"common:LowMemory"})});u&&(window._wails=window._wails||{},window._wails.dispatchWailsEvent=Mi);var Pi=w(c.Events),Ti=0,Y=class{constructor(e,i){this.name=e,this.data=i!=null?i:null}};function Mi(n){let e=g.get(n.name);if(!e)return;let i=new Y(n.name,n.name in oe?oe[n.name](n.data):n.data);"sender"in n&&(i.sender=n.sender);let t=new Set;for(let o of e.slice())o.dispatch(i)&&t.add(o);if(t.size>0){let o=g.get(n.name);if(o){let r=o.filter(a=>!t.has(a));r.length===0?g.delete(n.name):g.set(n.name,r)}}}function ve(n,e,i){let t=g.get(n)||[],o=new te(n,e,i);return t.push(o),g.set(n,t),()=>Wn(o)}function Ei(n,e){return ve(n,e,-1)}function xi(n,e){return ve(n,e,1)}function Ai(...n){n.forEach(e=>g.delete(e))}function Ri(){g.clear()}function Ce(n,e){return Pi(Ti,new Y(n,e))}function bn(){return new MouseEvent("mousedown").buttons===0}function yn(){if(!EventTarget||!AbortSignal||!AbortController)return!1;let n=!0,e=new EventTarget,i=new AbortController;return e.addEventListener("test",()=>{n=!1},{signal:i.signal}),i.abort(),e.dispatchEvent(new CustomEvent("test")),n}function re(n){var e;return n.target instanceof HTMLElement?n.target:!(n.target instanceof HTMLElement)&&n.target instanceof Node&&(e=n.target.parentElement)!=null?e:document.body}var vn=!1;u&&document.addEventListener("DOMContentLoaded",()=>{vn=!0});function ae(n){vn||document.readyState==="complete"?n():document.addEventListener("DOMContentLoaded",n)}var ki="data-file-drop-target",y="file-drop-target-active",m=null,Oi=0,Fi=1,Li=2,Ii=3,Ni=4,Ui=5,zi=6,Bi=7,ji=8,Hi=9,Vi=10,Zi=11,Ki=12,_i=13,Gi=14,Yi=15,Xi=16,Ji=17,qi=18,Qi=19,$i=20,et=21,nt=22,it=23,tt=24,ot=25,rt=26,at=27,st=28,lt=29,dt=30,ct=31,mt=32,ut=33,wt=34,pt=35,ft=36,gt=37,ht=38,Wt=39,bt=40,yt=41,vt=42,Ct=43,Dt=44,St=45,Pt=46,Tt=47,Mt=48,Et=49,xt=50,At=51,Rt=52;function se(n){return n?n.closest("[".concat(ki,"]")):null}function kt(){var n,e,i,t;return((e=(n=window.chrome)==null?void 0:n.webview)==null?void 0:e.postMessageWithAdditionalObjects)==null?!1:((t=(i=window._wails)==null?void 0:i.flags)==null?void 0:t.enableFileDrop)===!0}function Ot(n,e,i){var t,o;(o=(t=window.chrome)==null?void 0:t.webview)!=null&&o.postMessageWithAdditionalObjects&&window.chrome.webview.postMessageWithAdditionalObjects("file:drop:".concat(n,":").concat(e),i)}var Pe=!1;function Cn(){Pe=!1,m&&(m.classList.remove(y),m=null)}function Dn(){var n,e;((e=(n=window._wails)==null?void 0:n.flags)==null?void 0:e.enableFileDrop)!==!1&&(Pe=!0)}function Sn(){Cn()}function Pn(n,e){var o,r;if(!Pe||((r=(o=window._wails)==null?void 0:o.flags)==null?void 0:r.enableFileDrop)===!1)return;let i=document.elementFromPoint(n,e),t=se(i);m&&m!==t&&m.classList.remove(y),t?(t.classList.add(y),m=t):m=null}var s=Symbol("caller"),le=class le{constructor(e=""){this[s]=w(c.Window,e);for(let i of Object.getOwnPropertyNames(le.prototype))i!=="constructor"&&typeof this[i]=="function"&&(this[i]=this[i].bind(this))}Get(e){return new le(e)}Position(){return this[s](Oi)}Center(){return this[s](Fi)}Close(){return this[s](Li)}DisableSizeConstraints(){return this[s](Ii)}EnableSizeConstraints(){return this[s](Ni)}Focus(){return this[s](Ui)}ForceReload(){return this[s](zi)}Fullscreen(){return this[s](Bi)}GetScreen(){return this[s](ji)}GetZoom(){return this[s](Hi)}Height(){return this[s](Vi)}Hide(){return this[s](Zi)}IsFocused(){return this[s](Ki)}IsFullscreen(){return this[s](_i)}IsMaximised(){return this[s](Gi)}IsMinimised(){return this[s](Yi)}Maximise(){return this[s](Xi)}Minimise(){return this[s](Ji)}Name(){return this[s](qi)}OpenDevTools(){return this[s](Qi)}RelativePosition(){return this[s]($i)}Reload(){return this[s](et)}Resizable(){return this[s](nt)}Restore(){return this[s](it)}SetPosition(e,i){return this[s](tt,{x:e,y:i})}SetAlwaysOnTop(e){return this[s](ot,{alwaysOnTop:e})}SetBackgroundColour(e,i,t,o){return this[s](rt,{r:e,g:i,b:t,a:o})}SetFrameless(e){return this[s](at,{frameless:e})}SetFullscreenButtonEnabled(e){return this[s](st,{enabled:e})}SetMaxSize(e,i){return this[s](lt,{width:e,height:i})}SetMinSize(e,i){return this[s](dt,{width:e,height:i})}SetRelativePosition(e,i){return this[s](ct,{x:e,y:i})}SetResizable(e){return this[s](mt,{resizable:e})}SetSize(e,i){return this[s](ut,{width:e,height:i})}SetTitle(e){return this[s](wt,{title:e})}SetZoom(e){return this[s](pt,{zoom:e})}Show(){return this[s](ft)}Size(){return this[s](gt)}ToggleFullscreen(){return this[s](ht)}ToggleMaximise(){return this[s](Wt)}ToggleFrameless(){return this[s](bt)}UnFullscreen(){return this[s](yt)}UnMaximise(){return this[s](vt)}UnMinimise(){return this[s](Ct)}Width(){return this[s](Dt)}Zoom(){return this[s](St)}ZoomIn(){return this[s](Pt)}ZoomOut(){return this[s](Tt)}ZoomReset(){return this[s](Mt)}HandlePlatformFileDrop(e,i,t){var d,f;if(((f=(d=window._wails)==null?void 0:d.flags)==null?void 0:f.enableFileDrop)===!1)return;let o=document.elementFromPoint(i,t),r=se(o);if(!r)return;let a={id:r.id,classList:Array.from(r.classList),attributes:{}};for(let D=0;D<r.attributes.length;D++){let S=r.attributes[D];a.attributes[S.name]=S.value}let l={filenames:e,x:i,y:t,elementDetails:a};this[s](xt,l),Cn()}SetScreen(e){return this[s](Rt,{screenID:e})}SnapAssist(){return this[s](Et)}Print(){return this[s](At)}},Se=le,Ft=new Se("");function Lt(){let n=document.documentElement,e=0;n.addEventListener("dragenter",i=>{var r,a,l;if(!((r=i.dataTransfer)!=null&&r.types.includes("Files")))return;if(i.preventDefault(),((l=(a=window._wails)==null?void 0:a.flags)==null?void 0:l.enableFileDrop)===!1){i.dataTransfer.dropEffect="none";return}e++;let t=document.elementFromPoint(i.clientX,i.clientY),o=se(t);m&&m!==o&&m.classList.remove(y),o?(o.classList.add(y),i.dataTransfer.dropEffect="copy",m=o):(i.dataTransfer.dropEffect="none",m=null)},!1),n.addEventListener("dragover",i=>{var r,a,l;if(!((r=i.dataTransfer)!=null&&r.types.includes("Files")))return;if(i.preventDefault(),((l=(a=window._wails)==null?void 0:a.flags)==null?void 0:l.enableFileDrop)===!1){i.dataTransfer.dropEffect="none";return}let t=document.elementFromPoint(i.clientX,i.clientY),o=se(t);m&&m!==o&&m.classList.remove(y),o?(o.classList.contains(y)||o.classList.add(y),i.dataTransfer.dropEffect="copy",m=o):(i.dataTransfer.dropEffect="none",m=null)},!1),n.addEventListener("dragleave",i=>{var t,o,r;(t=i.dataTransfer)!=null&&t.types.includes("Files")&&(i.preventDefault(),((r=(o=window._wails)==null?void 0:o.flags)==null?void 0:r.enableFileDrop)!==!1&&i.relatedTarget!==null&&(e--,(e===0||m&&!m.contains(i.relatedTarget))&&(m&&(m.classList.remove(y),m=null),e=0)))},!1),n.addEventListener("drop",i=>{var t,o,r;if((t=i.dataTransfer)!=null&&t.types.includes("Files")&&(i.preventDefault(),((r=(o=window._wails)==null?void 0:o.flags)==null?void 0:r.enableFileDrop)!==!1&&(e=0,m&&(m.classList.remove(y),m=null),kt()))){let a=[];if(i.dataTransfer.items){for(let l of i.dataTransfer.items)if(l.kind==="file"){let d=l.getAsFile();d&&a.push(d)}}else if(i.dataTransfer.files)for(let l of i.dataTransfer.files)a.push(l);a.length>0&&Ot(i.clientX,i.clientY,a)}},!1)}typeof window<"u"&&typeof document<"u"&&Lt();var F=Ft;function It(n,e=null){Ce(n,e)}function Nt(n,e){let i=F.Get(n),t=i[e];if(typeof t=="function")try{t.call(i)}catch(o){}}function Tn(n){let e=n.currentTarget;function i(o="Yes"){if(o!=="Yes")return;let r=e.getAttribute("wml-event")||e.getAttribute("data-wml-event"),a=e.getAttribute("wml-target-window")||e.getAttribute("data-wml-target-window")||"",l=e.getAttribute("wml-window")||e.getAttribute("data-wml-window"),d=e.getAttribute("wml-openurl")||e.getAttribute("data-wml-openurl");r!==null&&It(r),l!==null&&Nt(a,l),d!==null&&ge(d)}let t=e.getAttribute("wml-confirm")||e.getAttribute("data-wml-confirm");t?We({Title:"Confirm",Message:t,Detached:!1,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(i):i()}var X=Symbol("controller"),L=Symbol("triggerMap"),E=Symbol("elementCount"),Te=class{constructor(){this[X]=new AbortController}set(e,i){return{signal:this[X].signal}}reset(){this[X].abort(),this[X]=new AbortController}},Me=class{constructor(){this[L]=new WeakMap,this[E]=0}set(e,i){return this[L].has(e)||this[E]++,this[L].set(e,i),{}}reset(){if(!(this[E]<=0)){for(let e of document.body.querySelectorAll("*")){if(this[E]<=0)break;let i=this[L].get(e);i!=null&&this[E]--;for(let t of i||[])e.removeEventListener(t,Tn)}this[L]=new WeakMap,this[E]=0}}},Mn=yn()?new Te:new Me;function Ut(n){let e=/\S+/g,i=n.getAttribute("wml-trigger")||n.getAttribute("data-wml-trigger")||"click",t=[],o;for(;(o=e.exec(i))!==null;)t.push(o[0]);let r=Mn.set(n,t);for(let a of t)n.addEventListener(a,Tn,r)}function Ee(){ae(En)}function En(){Mn.reset(),document.body.querySelectorAll("[wml-event], [wml-window], [wml-openurl], [data-wml-event], [data-wml-window], [data-wml-openurl]").forEach(Ut)}window.wails=Ae;Ee();var Fe={};p(Fe,{Capabilities:()=>Vt,Environment:()=>Zt,IsAMD64:()=>Gt,IsARM:()=>Yt,IsARM64:()=>Xt,IsAndroid:()=>Rn,IsDarkMode:()=>Ht,IsDebug:()=>Oe,IsDesktop:()=>_t,IsIOS:()=>An,IsLinux:()=>de,IsMac:()=>xn,IsMobile:()=>Kt,IsWindows:()=>J,invoke:()=>C});var ke=w(c.System),zt=0,Bt=1,jt=2,Re=(function(){var n,e,i,t,o,r;try{if((e=(n=window.chrome)==null?void 0:n.webview)!=null&&e.postMessage)return window.chrome.webview.postMessage.bind(window.chrome.webview);if((o=(t=(i=window.webkit)==null?void 0:i.messageHandlers)==null?void 0:t.external)!=null&&o.postMessage)return window.webkit.messageHandlers.external.postMessage.bind(window.webkit.messageHandlers.external);if((r=window.wails)!=null&&r.invoke)return a=>window.wails.invoke(typeof a=="string"?a:JSON.stringify(a))}catch(a){}return null})();function C(n){Re==null||Re(n)}function Ht(){return ke(zt)}async function Vt(){return ke(jt)}function Zt(){return ke(Bt)}function J(){var n,e;return((e=(n=window._wails)==null?void 0:n.environment)==null?void 0:e.OS)==="windows"}function de(){var n,e;return((e=(n=window._wails)==null?void 0:n.environment)==null?void 0:e.OS)==="linux"}function xn(){var n,e;return((e=(n=window._wails)==null?void 0:n.environment)==null?void 0:e.OS)==="darwin"}function An(){var n,e;return((e=(n=window._wails)==null?void 0:n.environment)==null?void 0:e.OS)==="ios"}function Rn(){var n,e;return((e=(n=window._wails)==null?void 0:n.environment)==null?void 0:e.OS)==="android"}function Kt(){return An()||Rn()}function _t(){return xn()||J()||de()}function Gt(){var n,e;return((e=(n=window._wails)==null?void 0:n.environment)==null?void 0:e.Arch)==="amd64"}function Yt(){var n,e;return((e=(n=window._wails)==null?void 0:n.environment)==null?void 0:e.Arch)==="arm"}function Xt(){var n,e;return((e=(n=window._wails)==null?void 0:n.environment)==null?void 0:e.Arch)==="arm64"}function Oe(){var n,e;return!!((e=(n=window._wails)==null?void 0:n.environment)!=null&&e.Debug)}u&&window.addEventListener("contextmenu",$t);var Jt=w(c.ContextMenu),qt=0;function Qt(n,e,i,t){Jt(qt,{id:n,x:e,y:i,data:t})}function $t(n){let e=re(n),i=window.getComputedStyle(e).getPropertyValue("--custom-contextmenu").trim();if(i){n.preventDefault();let t=window.getComputedStyle(e).getPropertyValue("--custom-contextmenu-data");Qt(i,n.clientX,n.clientY,t)}else eo(n,e)}function eo(n,e){if(Oe())return;switch(window.getComputedStyle(e).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":n.preventDefault();return}if(e.isContentEditable)return;let i=window.getSelection(),t=i&&i.toString().length>0;if(t)for(let o=0;o<i.rangeCount;o++){let a=i.getRangeAt(o).getClientRects();for(let l=0;l<a.length;l++){let d=a[l];if(document.elementFromPoint(d.left,d.top)===e)return}}(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement)&&(t||!e.readOnly&&!e.disabled)||n.preventDefault()}var Le={};p(Le,{GetFlag:()=>I});function I(n){try{return window._wails.flags[n]}catch(e){throw new Error("Unable to retrieve flag '"+n+"': "+e,{cause:e})}}var q=!1,Q=!1,Be=!1,U=!1,z=!1,x="",kn="auto",N=0,ce=!1;u&&(ce=bn(),window._wails=window._wails||{},window._wails.setResizable=n=>{Be=n,Be||(U=z=!1,h())});var je=!1;function no(){var i,t;let n=(t=(i=window._wails)==null?void 0:i.environment)==null?void 0:t.OS;if(n==="ios"||n==="android")return!0;let e=navigator.userAgent||navigator.vendor||window.opera||"";return/android|iphone|ipad|ipod|iemobile|wpdesktop/i.test(e)}function Ie(){if(!je&&!no()){window.addEventListener("mousedown",ze,{capture:!0}),window.addEventListener("mousemove",ze,{capture:!0}),window.addEventListener("mouseup",ze,{capture:!0});for(let n of["click","contextmenu","dblclick"])window.addEventListener(n,io,{capture:!0});je=!0}}if(u){Ie(),document.addEventListener("DOMContentLoaded",Ie,{once:!0});let n=0,e=window.setInterval(()=>{if(je){window.clearInterval(e);return}Ie(),++n>100&&window.clearInterval(e)},50)}function io(n){(Q||z)&&(n.stopImmediatePropagation(),n.stopPropagation(),n.preventDefault())}var Ne=0,to=1,Ue=2;function ze(n){let e,i=n.buttons;switch(n.type){case"mousedown":e=Ne,ce||(i=N|1<<n.button);break;case"mouseup":e=to,ce||(i=N&~(1<<n.button));break;default:e=Ue,ce||(i=N);break}let t=N&~i,o=i&~N;N=i,e===Ne&&!(o&n.button)&&(t|=1<<n.button,o|=1<<n.button),(e!==Ue&&z||Q&&(e===Ne||n.button!==0))&&(n.stopImmediatePropagation(),n.stopPropagation(),n.preventDefault()),t&1&&ro(n),o&1&&oo(n),e===Ue&&so(n)}function oo(n){if(q=!1,U=!1,!J()&&n.type==="mousedown"&&n.button===0&&n.detail!==1)return;if(x){if(n.type!=="mousedown")return;U=!0;return}let e=re(n),i=window.getComputedStyle(e);q=i.getPropertyValue("--wails-draggable").trim()==="drag"&&n.offsetX-parseFloat(i.paddingLeft)<e.clientWidth&&n.offsetY-parseFloat(i.paddingTop)<e.clientHeight}function ro(n){q=!1,Q=!1,U=!1,z=!1}var ao=Object.freeze({"se-resize":"nwse-resize","sw-resize":"nesw-resize","nw-resize":"nwse-resize","ne-resize":"nesw-resize","w-resize":"ew-resize","n-resize":"ns-resize","s-resize":"ns-resize","e-resize":"ew-resize"});function h(n){n?(x||(kn=document.body.style.cursor),document.body.style.cursor=ao[n]):!n&&x&&(document.body.style.cursor=kn),x=n||""}function so(n){if(U&&x?(z=!0,C("wails:resize:"+x)):q&&(Q=!0,C("wails:drag")),Q||z){q=U=!1;return}if(!Be||!J()&&!(de()&&I("frameless"))){x&&h();return}let e=I("system.resizeHandleHeight")||5,i=I("system.resizeHandleWidth")||5,t=I("resizeCornerExtra")||10,o=Math.max(0,window.innerWidth-document.documentElement.clientWidth),r=Math.max(0,window.innerHeight-document.documentElement.clientHeight),a=window.innerWidth-o,l=window.innerHeight-r,d=n.clientX<a&&a-n.clientX<i,f=n.clientX<i,D=n.clientY<e,S=n.clientY<l&&l-n.clientY<e,W=n.clientX<a&&a-n.clientX<i+t,b=n.clientX<i+t,pe=n.clientY<e+t,fe=n.clientY<l&&l-n.clientY<e+t;!b&&!pe&&!fe&&!W?h():W&&fe?h("se-resize"):b&&fe?h("sw-resize"):b&&pe?h("nw-resize"):pe&&W?h("ne-resize"):f?h("w-resize"):D?h("n-resize"):S?h("s-resize"):d?h("e-resize"):h()}var On="--wails-non-client-region",lo="wails:runtime-config-ready",co=new Set(["caption","minimize","maximize","close"]);u&&(window._wails=window._wails||{});var Ve=!1,Fn="",He=new Set,$,Ln=!1;function In(n){let e=n.trim().toLowerCase();if(co.has(e))return e}function mo(n){if(!(n instanceof HTMLElement))return;let e=window.getComputedStyle(n),i=In(e.getPropertyValue(On));if(!i)return;let t=n.parentElement;if(t){let o=window.getComputedStyle(t);if(In(o.getPropertyValue(On))===i)return}return i}function uo(n){let e=window.getComputedStyle(n);return e.display!=="none"&&e.visibility!=="hidden"&&e.contentVisibility!=="hidden"}function wo(n){if(!(n instanceof HTMLElement))return;let e=mo(n);if(!e||!uo(n))return;let i=n.getBoundingClientRect();if(i.width<=0||i.height<=0)return;let t=window.devicePixelRatio||1,o=Math.floor(i.left*t),r=Math.floor(i.top*t),a=Math.ceil(i.right*t),l=Math.ceil(i.bottom*t);if(!(a<=o||l<=r))return{kind:e,left:o,top:r,right:a,bottom:l}}function po(){let n=[];if(document.documentElement&&n.push(document.documentElement),document.body){n.push(document.body);for(let e of document.body.querySelectorAll("*"))n.push(e)}return n}function fo(n){if(typeof ResizeObserver>"u")return;$!=null||($=new ResizeObserver(A));let e=new Set(n);for(let i of He)e.has(i)||$.unobserve(i);for(let i of e)He.has(i)||$.observe(i);He=e}function go(){Ve=!1;let n=po(),e=[],i=[];for(let o of n){let r=wo(o);r&&(e.push(r),i.push(o))}fo(i);let t=JSON.stringify({version:1,regions:e});t!==Fn&&(Fn=t,C("wails:non-client-region:"+t))}function A(){Ve||(Ve=!0,window.requestAnimationFrame(go))}function ho(){var e,i;if(Ln)return;Ln=!0,A(),new MutationObserver(A).observe(document.documentElement,{attributes:!0,childList:!0,subtree:!0}),window.addEventListener("resize",A),window.addEventListener("scroll",A,!0),(e=window.visualViewport)==null||e.addEventListener("resize",A),(i=window.visualViewport)==null||i.addEventListener("scroll",A)}function Nn(){var i,t;let n=(i=window._wails.environment)==null?void 0:i.OS;if(n===void 0)return!1;let e=(t=window._wails.flags)==null?void 0:t.nonClientRegionTracking;return n==="windows"&&e===!0&&ae(ho),!0}u&&!Nn()&&window.addEventListener(lo,Nn,{once:!0});var Ke={};p(Ke,{Hide:()=>vo,Quit:()=>Do,Show:()=>Co});var Ze=w(c.Application),Wo=0,bo=1,yo=2;function vo(){return Ze(Wo)}function Co(){return Ze(bo)}function Do(){return Ze(yo)}var Qe={};p(Qe,{ByID:()=>Vo,ByName:()=>Ho,Call:()=>qe,RuntimeError:()=>_});var zn=Function.prototype.toString,B=typeof Reflect=="object"&&Reflect!==null&&Reflect.apply,_e,me;if(typeof B=="function"&&typeof Object.defineProperty=="function")try{_e=Object.defineProperty({},"length",{get:function(){throw me}}),me={},B(function(){throw 42},null,_e)}catch(n){n!==me&&(B=null)}else B=null;var So=/^\s*class\b/,Ye=function(e){try{var i=zn.call(e);return So.test(i)}catch(t){return!1}},Ge=function(e){try{return Ye(e)?!1:(zn.call(e),!0)}catch(i){return!1}},ue=Object.prototype.toString,Po="[object Object]",To="[object Function]",Mo="[object GeneratorFunction]",Eo="[object HTMLAllCollection]",xo="[object HTML document.all class]",Ao="[object HTMLCollection]",Ro=typeof Symbol=="function"&&!!Symbol.toStringTag,ko=!(0 in[,]),Xe=function(){return!1};typeof document=="object"&&(Un=document.all,ue.call(Un)===ue.call(document.all)&&(Xe=function(e){if((ko||!e)&&(typeof e>"u"||typeof e=="object"))try{var i=ue.call(e);return(i===Eo||i===xo||i===Ao||i===Po)&&e("")==null}catch(t){}return!1}));var Un;function Oo(n){if(Xe(n))return!0;if(!n||typeof n!="function"&&typeof n!="object")return!1;try{B(n,null,_e)}catch(e){if(e!==me)return!1}return!Ye(n)&&Ge(n)}function Fo(n){if(Xe(n))return!0;if(!n||typeof n!="function"&&typeof n!="object")return!1;if(Ro)return Ge(n);if(Ye(n))return!1;var e=ue.call(n);return e!==To&&e!==Mo&&!/^\[object HTML/.test(e)?!1:Ge(n)}var P=B?Oo:Fo;var H=class extends Error{constructor(e,i){super(e,i),this.name="CancelError"}},T=class extends Error{constructor(e,i,t){super((t!=null?t:"Unhandled rejection in cancelled promise.")+" Reason: "+Lo(i),{cause:i}),this.promise=e,this.name="CancelledRejectionError"}},v=Symbol("barrier"),Je=Symbol("cancelImpl"),Vn,Bn=(Vn=Symbol.species)!=null?Vn:Symbol("speciesPolyfill"),ee=class n extends Promise{constructor(e,i){let t,o;if(super((d,f)=>{t=d,o=f}),this.constructor[Bn]!==Promise)throw new TypeError("CancellablePromise does not support transparent subclassing. Please refrain from overriding the [Symbol.species] static property.");let r={promise:this,resolve:t,reject:o,get oncancelled(){return i!=null?i:null},set oncancelled(d){i=d!=null?d:void 0}},a={get root(){return a},resolving:!1,settled:!1};Object.defineProperties(this,{[v]:{configurable:!1,enumerable:!1,writable:!0,value:null},[Je]:{configurable:!1,enumerable:!1,writable:!1,value:Zn(r,a)}});let l=_n(r,a);try{e(Kn(r,a),l)}catch(d){a.resolving||l(d)}}cancel(e){return new n(i=>{Promise.all([this[Je](new H("Promise cancelled.",{cause:e})),Io(this)]).then(()=>i(),()=>i())})}cancelOn(e){return e.aborted?this.cancel(e.reason):e.addEventListener("abort",()=>{this.cancel(e.reason)},{capture:!0}),this}then(e,i,t){if(!(this instanceof n))throw new TypeError("CancellablePromise.prototype.then called on an invalid object.");if(P(e)||(e=jn),P(i)||(i=Hn),e===jn&&i==Hn)return new n(r=>r(this));let o={};return this[v]=o,new n((r,a)=>{super.then(l=>{var d;this[v]===o&&(this[v]=null),(d=o.resolve)==null||d.call(o);try{r(e(l))}catch(f){a(f)}},l=>{var d;this[v]===o&&(this[v]=null),(d=o.resolve)==null||d.call(o);try{r(i(l))}catch(f){a(f)}})},async r=>{try{return t==null?void 0:t(r)}finally{await this.cancel(r)}})}catch(e,i){return this.then(void 0,e,i)}finally(e,i){if(!(this instanceof n))throw new TypeError("CancellablePromise.prototype.finally called on an invalid object.");return P(e)?this.then(t=>n.resolve(e()).then(()=>t),t=>n.resolve(e()).then(()=>{throw t}),i):this.then(e,e,i)}static get[(v,Je,Bn)](){return Promise}static all(e){let i=Array.from(e),t=i.length===0?n.resolve(i):new n((o,r)=>{Promise.all(i).then(o,r)},o=>we(t,i,o));return t}static allSettled(e){let i=Array.from(e),t=i.length===0?n.resolve(i):new n((o,r)=>{Promise.allSettled(i).then(o,r)},o=>we(t,i,o));return t}static any(e){let i=Array.from(e),t=i.length===0?n.resolve(i):new n((o,r)=>{Promise.any(i).then(o,r)},o=>we(t,i,o));return t}static race(e){let i=Array.from(e),t=new n((o,r)=>{Promise.race(i).then(o,r)},o=>we(t,i,o));return t}static cancel(e){let i=new n(()=>{});return i.cancel(e),i}static timeout(e,i){let t=new n(()=>{});return AbortSignal&&typeof AbortSignal=="function"&&AbortSignal.timeout&&typeof AbortSignal.timeout=="function"?AbortSignal.timeout(e).addEventListener("abort",()=>{t.cancel(i)}):setTimeout(()=>{t.cancel(i)},e),t}static sleep(e,i){return new n(t=>{setTimeout(()=>t(i),e)})}static reject(e){return new n((i,t)=>t(e))}static resolve(e){return e instanceof n?e:new n(i=>i(e))}static withResolvers(){let e={oncancelled:null};return e.promise=new n((i,t)=>{e.resolve=i,e.reject=t},i=>{var t;(t=e.oncancelled)==null||t.call(e,i)}),e}};function Zn(n,e){let i;return t=>{if(e.settled||(e.settled=!0,e.reason=t,n.reject(t),Promise.prototype.then.call(n.promise,void 0,o=>{if(o!==t)throw o})),!(!e.reason||!n.oncancelled))return i=new Promise(o=>{try{o(n.oncancelled(e.reason.cause))}catch(r){Promise.reject(new T(n.promise,r,"Unhandled exception in oncancelled callback."))}}).catch(o=>{Promise.reject(new T(n.promise,o,"Unhandled rejection in oncancelled callback."))}),n.oncancelled=null,i}}function Kn(n,e){return i=>{if(!e.resolving){if(e.resolving=!0,i===n.promise){if(e.settled)return;e.settled=!0,n.reject(new TypeError("A promise cannot be resolved with itself."));return}if(i!=null&&(typeof i=="object"||typeof i=="function")){let t;try{t=i.then}catch(o){e.settled=!0,n.reject(o);return}if(P(t)){try{let a=i.cancel;if(P(a)){let l=d=>{Reflect.apply(a,i,[d])};e.reason?Zn(Z(V({},n),{oncancelled:l}),e)(e.reason):n.oncancelled=l}}catch(a){}let o={root:e.root,resolving:!1,get settled(){return this.root.settled},set settled(a){this.root.settled=a},get reason(){return this.root.reason}},r=_n(n,o);try{Reflect.apply(t,i,[Kn(n,o),r])}catch(a){r(a)}return}}e.settled||(e.settled=!0,n.resolve(i))}}}function _n(n,e){return i=>{if(!e.resolving)if(e.resolving=!0,e.settled){try{if(i instanceof H&&e.reason instanceof H&&Object.is(i.cause,e.reason.cause))return}catch(t){}Promise.reject(new T(n.promise,i))}else e.settled=!0,n.reject(i)}}function we(n,e,i){let t=[];for(let o of e){let r;try{if(!P(o.then)||(r=o.cancel,!P(r)))continue}catch(l){continue}let a;try{a=Reflect.apply(r,o,[i])}catch(l){Promise.reject(new T(n,l,"Unhandled exception in cancel method."));continue}a&&t.push((a instanceof Promise?a:Promise.resolve(a)).catch(l=>{Promise.reject(new T(n,l,"Unhandled rejection in cancel method."))}))}return Promise.all(t)}function jn(n){return n}function Hn(n){throw n}function Lo(n){try{if(n instanceof Error||typeof n!="object"||n.toString!==Object.prototype.toString)return""+n}catch(e){}try{return JSON.stringify(n)}catch(e){}try{return Object.prototype.toString.call(n)}catch(e){}return"<could not convert error to string>"}function Io(n){var i;let e=(i=n[v])!=null?i:{};return"promise"in e||Object.assign(e,j()),n[v]==null&&(e.resolve(),n[v]=e),e.promise}var j=Promise.withResolvers;j&&typeof j=="function"?j=j.bind(Promise):j=function(){let n,e;return{promise:new Promise((t,o)=>{n=t,e=o}),resolve:n,reject:e}};u&&(window._wails=window._wails||{});var No=w(c.Call),Uo=w(c.CancelCall),ne=new Map,zo=0,Bo=0;function jo(){let n;do n=R();while(ne.has(n));return n}function qe(n){let e=jo(),i=ee.withResolvers();ne.set(e,{resolve:i.resolve,reject:i.reject});let t=No(zo,Object.assign({"call-id":e},n)),o=!0;t.then(a=>{o=!1,ne.delete(e),i.resolve(a)},a=>{o=!1,ne.delete(e),i.reject(a)});let r=()=>(ne.delete(e),Uo(Bo,{"call-id":e}).catch(a=>{}));return i.oncancelled=()=>o?r():t.then(r),i.promise}function Ho(n,...e){return qe({methodName:n,args:e})}function Vo(n,...e){return qe({methodID:n,args:e})}var $e={};p($e,{SetText:()=>_o,Text:()=>Go});var Gn=w(c.Clipboard),Zo=0,Ko=1;function _o(n){return Gn(Zo,{text:n})}function Go(){return Gn(Ko)}var en={};p(en,{GetAll:()=>$o,GetByID:()=>ir,GetByIndex:()=>tr,GetCurrent:()=>nr,GetPrimary:()=>er});var ie=w(c.Screens),Yo=0,Xo=1,Jo=2,qo=3,Qo=4;function $o(){return ie(Yo)}function er(){return ie(Xo)}function nr(){return ie(Jo)}function ir(n){return ie(qo,{id:n})}function tr(n){return ie(Qo,{index:n})}var on={};p(on,{Device:()=>tn,Haptics:()=>nn});var Yn=w(c.IOS),or=0,rr=1,nn;(e=>{function n(i="medium"){return Yn(or,{style:i})}e.Impact=n})(nn||(nn={}));var tn;(e=>{function n(){return Yn(rr)}e.Info=n})(tn||(tn={}));var dn={};p(dn,{Device:()=>an,Haptics:()=>rn,Toast:()=>sn});var ln=w(c.Android),ar=0,sr=1,lr=2,rn;(e=>{function n(i=100){return ln(ar,{duration:i})}e.Vibrate=n})(rn||(rn={}));var an;(e=>{function n(){return ln(sr)}e.Info=n})(an||(an={}));var sn;(e=>{function n(i){return ln(lr,{message:i})}e.Show=n})(sn||(sn={}));var cn={};p(cn,{Events:()=>dr});var dr=Object.freeze({CheckStarted:"wails:updater:check-started",UpdateAvailable:"wails:updater:update-available",NoUpdate:"wails:updater:no-update",DownloadStarted:"wails:updater:download-started",DownloadProgress:"wails:updater:download-progress",DownloadComplete:"wails:updater:download-complete",Verifying:"wails:updater:verifying",Installing:"wails:updater:installing",UpdateReady:"wails:updater:update-ready",Error:"wails:updater:error",Meta:"wails:updater:meta",User:Object.freeze({Install:"wails:updater:user:install",Restart:"wails:updater:user:restart",Skip:"wails:updater:user:skip",Remind:"wails:updater:user:remind",Cancel:"wails:updater:user:cancel"}),Window:Object.freeze({Ready:"wails:updater:window:ready"})});u&&(window._wails=window._wails||{});u&&(window._wails.invoke=C,window._wails.clientId=k);u&&(window._wails.handlePlatformFileDrop=F.HandlePlatformFileDrop.bind(F));u&&(window._wails.handleDragEnter=Dn,window._wails.handleDragLeave=Sn,window._wails.handleDragOver=Pn);u&&C("wails:runtime:ready");function Xn(n){return fetch(n,{method:"HEAD"}).then(e=>{if(e.ok&&(e.headers.get("content-type")||"").toLowerCase().includes("javascript")){let t=document.createElement("script");t.src=n,document.head.appendChild(t)}}).catch(()=>{})}u&&Xn("/wails/custom.js");export{dn as Android,Ke as Application,he as Browser,Qe as Call,H as CancelError,ee as CancellablePromise,T as CancelledRejectionError,$e as Clipboard,ye as Create,be as Dialogs,De as Events,Le as Flags,on as IOS,en as Screens,Fe as System,cn as Updater,xe as WML,F as Window,k as clientId,hn as getTransport,Xn as loadOptionalScript,c as objectNames,gn as setTransport}; diff --git a/v3/internal/runtime/Taskfile.yaml b/v3/internal/runtime/Taskfile.yaml index 4a2a2ccf3af..c871d03fa12 100644 --- a/v3/internal/runtime/Taskfile.yaml +++ b/v3/internal/runtime/Taskfile.yaml @@ -2,9 +2,15 @@ version: "3" +vars: + ESBUILD: desktop/@wailsio/runtime/node_modules/.bin/esbuild + tasks: install-deps: internal: true + # once: build:debug and build:production dep on this in parallel; two + # concurrent npm installs in the same directory corrupt node_modules. + run: once dir: desktop/@wailsio/runtime sources: - package.json @@ -27,13 +33,17 @@ tasks: build:debug: internal: true + deps: + - install-deps cmds: - - npx esbuild@latest desktop/@wailsio/runtime/src/index.ts --inject:desktop/compiled/main.js --format=esm --target=safari11 --bundle --ignore-annotations --tree-shaking=true --sourcemap=inline --outfile=../assetserver/bundledassets/runtime.debug.js --define:DEBUG=true + - "{{.ESBUILD}} desktop/@wailsio/runtime/src/index.ts --inject:desktop/compiled/main.js --format=esm --target=safari11 --bundle --ignore-annotations --tree-shaking=true --sourcemap=inline --outfile=../assetserver/bundledassets/runtime.debug.js --define:DEBUG=true" build:production: internal: true + deps: + - install-deps cmds: - - npx esbuild@latest desktop/@wailsio/runtime/src/index.ts --inject:desktop/compiled/main.js --format=esm --target=safari11 --bundle --ignore-annotations --tree-shaking=true --minify --outfile=../assetserver/bundledassets/runtime.js --define:DEBUG=false --drop:console + - "{{.ESBUILD}} desktop/@wailsio/runtime/src/index.ts --inject:desktop/compiled/main.js --format=esm --target=safari11 --bundle --ignore-annotations --tree-shaking=true --minify --outfile=../assetserver/bundledassets/runtime.js --define:DEBUG=false --drop:console" build:docs: internal: true @@ -51,6 +61,12 @@ tasks: cmds: - npm run build:docs:md + build:assets: + desc: Rebuild only the embedded runtime bundles (bundledassets); CI verifies PR bundles against this exact output. + deps: + - build:debug + - build:production + build:runtime: internal: true deps: diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/assets/hierarchy.js b/v3/internal/runtime/desktop/@wailsio/runtime/docs/assets/hierarchy.js index 846a32cf3aa..5240fa47cd8 100644 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/assets/hierarchy.js +++ b/v3/internal/runtime/desktop/@wailsio/runtime/docs/assets/hierarchy.js @@ -1 +1 @@ -window.hierarchyData = "eJylj7EKg0AQRP9l6otB0ajXpk2RXkQuuuLhesLdpRL/PWiIpDAhkGZZdpidNxPsOHoHWcSZyJOoFLDUMtVej8ZBToizZRo1ECTOytTErG5MVzsO2tFF9wSBXpsGMkpOAnfLkNDGk21VTe64bwo6PzAEalbOQcK75rB8OWzORew0N5YMZJGG5SyQhl9pNpIwyl4ka8AuxkeE52EWyJPoLe/3ytW6G8VV8GfleX4AEQ+NYw==" \ No newline at end of file +window.hierarchyData = "eJylj80KwjAQhN9lzrFSsT/m6tWDdyklpisGtwkk8VTy7tKKxUMVwcuy7DA73wzwzsUAedrWYleUjYCnC5OOxtkAOWBbj9OqniCxV1YTszozHb3rTaCDuREEbsZ2kJuiFLh7hoSxkfxFaQrrZVN2jT1DQLMKARIxdKvxy2p2juLVcOfJQp6qvEkCVf6VZibJN/WLZApYxPiI8DwkgV1RvuX9Xrmddqu4zf6snNIDGWeNaw==" \ No newline at end of file diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/classes/Call.RuntimeError.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/classes/Call.RuntimeError.html index 1b8b335865c..44ea423dcf5 100644 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/classes/Call.RuntimeError.html +++ b/v3/internal/runtime/desktop/@wailsio/runtime/docs/classes/Call.RuntimeError.html @@ -1,6 +1,6 @@ <!DOCTYPE html><html class="default" lang="en" data-base="../"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>RuntimeError | @wailsio/runtime
@wailsio/runtime
    Preparing search index...

    Class RuntimeError

    Exception class that will be thrown in case the bound method returns an error. The value of the RuntimeError#name property is "RuntimeError".

    -

    Hierarchy

    Index

    Constructors

    Hierarchy

    Index

    Constructors

    Properties

    cause? message name @@ -12,7 +12,7 @@

    Constructors

    • Constructs a new RuntimeError instance.

      Parameters

      • Optionalmessage: string

        The error message.

      • Optionaloptions: ErrorOptions

        Options to be forwarded to the Error constructor.

        -

      Returns RuntimeError

    Properties

    cause?: unknown
    message: string
    name: string
    stack?: string
    stackTraceLimit: number

    The Error.stackTraceLimit property specifies the number of stack frames +

    Returns RuntimeError

    Properties

    cause?: unknown
    message: string
    name: string
    stack?: string
    stackTraceLimit: number

    The Error.stackTraceLimit property specifies the number of stack frames collected by a stack trace (whether generated by new Error().stack or Error.captureStackTrace(obj)).

    The default value is 10 but may be set to any valid JavaScript number. Changes diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/classes/_internal_.Window.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/classes/_internal_.Window.html index 88b140ec613..fd2b1aa40ba 100644 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/classes/_internal_.Window.html +++ b/v3/internal/runtime/desktop/@wailsio/runtime/docs/classes/_internal_.Window.html @@ -69,8 +69,8 @@

    • Handles file drops originating from platform-specific code (e.g., macOS/Linux native drag-and-drop). Gathers information about the drop target element and sends it back to the Go backend.

      Parameters

      • filenames: string[]

        An array of file paths (strings) that were dropped.

        -
      • x: number

        The x-coordinate of the drop event (CSS pixels).

        -
      • y: number

        The y-coordinate of the drop event (CSS pixels).

        +
      • x: number

        The x-coordinate of the drop event, in logical (CSS) pixels relative to the webview.

        +
      • y: number

        The y-coordinate of the drop event, in logical (CSS) pixels relative to the webview.

      Returns void

    • Hides the window.

      diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Call.ByID.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Call.ByID.html index ecbc6cfa64a..d666003938b 100644 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Call.ByID.html +++ b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Call.ByID.html @@ -3,4 +3,4 @@

      Parameters

      • methodID: number

        The ID of the method to call.

      • ...args: any[]

        The arguments to pass to the method.

      Returns CancellablePromise<any>

      The result of the method call.

      -
    +
    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Call.ByName.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Call.ByName.html index 73f3660d1ae..3063a66efeb 100644 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Call.ByName.html +++ b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Call.ByName.html @@ -3,4 +3,4 @@

    Parameters

    Returns CancellablePromise<any>

    The result of the method call.

    -
    +
    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Call.Call.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Call.Call.html index c533a4537a5..b676d1b7f41 100644 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Call.Call.html +++ b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Call.Call.html @@ -6,4 +6,4 @@ by the application- or service-level error marshaling functions.

    Parameters

    Returns CancellablePromise<any>

    The result of the call.

    -
    +
    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/getTransport.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/getTransport.html index e0069b934d5..9d2e24f1a20 100644 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/getTransport.html +++ b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/getTransport.html @@ -1,2 +1,2 @@ getTransport | @wailsio/runtime
    @wailsio/runtime
      Preparing search index...

      Function getTransport

      +

      Returns RuntimeTransport | null

      diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/setTransport.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/setTransport.html index d6aef327174..a1618820b29 100644 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/setTransport.html +++ b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/setTransport.html @@ -5,4 +5,4 @@

      Returns void

      import { setTransport } from '/wails/runtime.js';

      const wsTransport = {
      call: async (objectID, method, windowName, args) => {
      // Your WebSocket implementation
      }
      };

      setTransport(wsTransport);
      -
      +
      diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/hierarchy.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/hierarchy.html index 280f8921da6..dde2eb5948a 100644 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/hierarchy.html +++ b/v3/internal/runtime/desktop/@wailsio/runtime/docs/hierarchy.html @@ -1 +1 @@ -@wailsio/runtime
      @wailsio/runtime
        Preparing search index...
        +@wailsio/runtime
        @wailsio/runtime
          Preparing search index...
          diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/RuntimeTransport.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/RuntimeTransport.html index 695ed07bf80..f92ec78f6ad 100644 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/RuntimeTransport.html +++ b/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/RuntimeTransport.html @@ -1,11 +1,11 @@ RuntimeTransport | @wailsio/runtime
          @wailsio/runtime
            Preparing search index...

            Interface RuntimeTransport

            RuntimeTransport defines the interface for custom IPC transport implementations. Implement this interface to use WebSockets, custom protocols, or any other transport mechanism instead of the default HTTP fetch.

            -
            interface RuntimeTransport {
                call(
                    objectID: number,
                    method: number,
                    windowName: string,
                    args: any,
                ): Promise<any>;
            }
            Index

            Methods

            interface RuntimeTransport {
                call(
                    objectID: number,
                    method: number,
                    windowName: string,
                    args: any,
                ): Promise<any>;
            }
            Index

            Methods

            Methods

            • Send a runtime call and return the response.

              Parameters

              • objectID: number

                The Wails object ID (0=Call, 1=Clipboard, etc.)

              • method: number

                The method ID to call

              • windowName: string

                Optional window name

              • args: any

                Arguments to pass (will be JSON stringified if present)

              Returns Promise<any>

              Promise that resolves with the response data

              -
            +
            diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/variables/Events.Types.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/variables/Events.Types.html index 6c808e97f30..61d84b5b349 100644 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/variables/Events.Types.html +++ b/v3/internal/runtime/desktop/@wailsio/runtime/docs/variables/Events.Types.html @@ -1 +1 @@ -Types | @wailsio/runtime
            @wailsio/runtime
              Preparing search index...

              Variable TypesConst

              Types: Readonly<
                  {
                      Android: Readonly<
                          {
                              ActivityCreated: "android:ActivityCreated";
                              ActivityDestroyed: "android:ActivityDestroyed";
                              ActivityPaused: "android:ActivityPaused";
                              ActivityResumed: "android:ActivityResumed";
                              ActivityStarted: "android:ActivityStarted";
                              ActivityStopped: "android:ActivityStopped";
                              ApplicationLowMemory: "android:ApplicationLowMemory";
                              BatteryChanged: "android:BatteryChanged";
                              NetworkChanged: "android:NetworkChanged";
                              ScreenLocked: "android:ScreenLocked";
                              ScreenUnlocked: "android:ScreenUnlocked";
                              ThemeChanged: "android:ThemeChanged";
                              WebViewPageFinished: "android:WebViewPageFinished";
                              WebViewPageStarted: "android:WebViewPageStarted";
                          },
                      >;
                      Common: Readonly<
                          {
                              ApplicationLaunchedWithUrl: "common:ApplicationLaunchedWithUrl";
                              ApplicationOpenedWithFile: "common:ApplicationOpenedWithFile";
                              ApplicationStarted: "common:ApplicationStarted";
                              BatteryChanged: "common:BatteryChanged";
                              LowMemory: "common:LowMemory";
                              NetworkChanged: "common:NetworkChanged";
                              ScreenLocked: "common:ScreenLocked";
                              ScreenUnlocked: "common:ScreenUnlocked";
                              SystemDidWake: "common:SystemDidWake";
                              SystemWillSleep: "common:SystemWillSleep";
                              ThemeChanged: "common:ThemeChanged";
                              WindowClosing: "common:WindowClosing";
                              WindowDidMove: "common:WindowDidMove";
                              WindowDidResize: "common:WindowDidResize";
                              WindowDPIChanged: "common:WindowDPIChanged";
                              WindowFilesDropped: "common:WindowFilesDropped";
                              WindowFocus: "common:WindowFocus";
                              WindowFullscreen: "common:WindowFullscreen";
                              WindowHide: "common:WindowHide";
                              WindowLostFocus: "common:WindowLostFocus";
                              WindowMaximise: "common:WindowMaximise";
                              WindowMinimise: "common:WindowMinimise";
                              WindowRestore: "common:WindowRestore";
                              WindowRuntimeReady: "common:WindowRuntimeReady";
                              WindowShow: "common:WindowShow";
                              WindowToggleFrameless: "common:WindowToggleFrameless";
                              WindowUnFullscreen: "common:WindowUnFullscreen";
                              WindowUnMaximise: "common:WindowUnMaximise";
                              WindowUnMinimise: "common:WindowUnMinimise";
                              WindowZoom: "common:WindowZoom";
                              WindowZoomIn: "common:WindowZoomIn";
                              WindowZoomOut: "common:WindowZoomOut";
                              WindowZoomReset: "common:WindowZoomReset";
                          },
                      >;
                      iOS: Readonly<
                          {
                              ApplicationDidBecomeActive: "ios:ApplicationDidBecomeActive";
                              ApplicationDidEnterBackground: "ios:ApplicationDidEnterBackground";
                              ApplicationDidFinishLaunching: "ios:ApplicationDidFinishLaunching";
                              ApplicationDidReceiveMemoryWarning: "ios:ApplicationDidReceiveMemoryWarning";
                              ApplicationWillEnterForeground: "ios:ApplicationWillEnterForeground";
                              ApplicationWillResignActive: "ios:ApplicationWillResignActive";
                              ApplicationWillTerminate: "ios:ApplicationWillTerminate";
                              BatteryChanged: "ios:BatteryChanged";
                              NetworkChanged: "ios:NetworkChanged";
                              ScreenLocked: "ios:ScreenLocked";
                              ScreenUnlocked: "ios:ScreenUnlocked";
                              ThemeChanged: "ios:ThemeChanged";
                              WebViewDecidePolicyForNavigationAction: "ios:WebViewDecidePolicyForNavigationAction";
                              WebViewDidFailNavigation: "ios:WebViewDidFailNavigation";
                              WebViewDidFinishNavigation: "ios:WebViewDidFinishNavigation";
                              WebViewDidStartNavigation: "ios:WebViewDidStartNavigation";
                              WindowDidAppear: "ios:WindowDidAppear";
                              WindowDidDisappear: "ios:WindowDidDisappear";
                              WindowDidLoad: "ios:WindowDidLoad";
                              WindowOrientationChanged: "ios:WindowOrientationChanged";
                              WindowSafeAreaInsetsChanged: "ios:WindowSafeAreaInsetsChanged";
                              WindowTouchBegan: "ios:WindowTouchBegan";
                              WindowTouchCancelled: "ios:WindowTouchCancelled";
                              WindowTouchEnded: "ios:WindowTouchEnded";
                              WindowTouchMoved: "ios:WindowTouchMoved";
                              WindowWillAppear: "ios:WindowWillAppear";
                              WindowWillDisappear: "ios:WindowWillDisappear";
                          },
                      >;
                      Linux: Readonly<
                          {
                              ApplicationStartup: "linux:ApplicationStartup";
                              SystemDidWake: "linux:SystemDidWake";
                              SystemThemeChanged: "linux:SystemThemeChanged";
                              SystemWillSleep: "linux:SystemWillSleep";
                              WindowDeleteEvent: "linux:WindowDeleteEvent";
                              WindowDidMove: "linux:WindowDidMove";
                              WindowDidResize: "linux:WindowDidResize";
                              WindowFocusIn: "linux:WindowFocusIn";
                              WindowFocusOut: "linux:WindowFocusOut";
                              WindowLoadCommitted: "linux:WindowLoadCommitted";
                              WindowLoadFinished: "linux:WindowLoadFinished";
                              WindowLoadRedirected: "linux:WindowLoadRedirected";
                              WindowLoadStarted: "linux:WindowLoadStarted";
                          },
                      >;
                      Mac: Readonly<
                          {
                              ApplicationDidBecomeActive: "mac:ApplicationDidBecomeActive";
                              ApplicationDidChangeBackingProperties: "mac:ApplicationDidChangeBackingProperties";
                              ApplicationDidChangeEffectiveAppearance: "mac:ApplicationDidChangeEffectiveAppearance";
                              ApplicationDidChangeIcon: "mac:ApplicationDidChangeIcon";
                              ApplicationDidChangeOcclusionState: "mac:ApplicationDidChangeOcclusionState";
                              ApplicationDidChangeScreenParameters: "mac:ApplicationDidChangeScreenParameters";
                              ApplicationDidChangeStatusBarFrame: "mac:ApplicationDidChangeStatusBarFrame";
                              ApplicationDidChangeStatusBarOrientation: "mac:ApplicationDidChangeStatusBarOrientation";
                              ApplicationDidChangeTheme: "mac:ApplicationDidChangeTheme";
                              ApplicationDidFinishLaunching: "mac:ApplicationDidFinishLaunching";
                              ApplicationDidHide: "mac:ApplicationDidHide";
                              ApplicationDidResignActive: "mac:ApplicationDidResignActive";
                              ApplicationDidUnhide: "mac:ApplicationDidUnhide";
                              ApplicationDidUpdate: "mac:ApplicationDidUpdate";
                              ApplicationDidWake: "mac:ApplicationDidWake";
                              ApplicationScreensDidSleep: "mac:ApplicationScreensDidSleep";
                              ApplicationScreensDidWake: "mac:ApplicationScreensDidWake";
                              ApplicationShouldHandleReopen: "mac:ApplicationShouldHandleReopen";
                              ApplicationWillBecomeActive: "mac:ApplicationWillBecomeActive";
                              ApplicationWillFinishLaunching: "mac:ApplicationWillFinishLaunching";
                              ApplicationWillHide: "mac:ApplicationWillHide";
                              ApplicationWillResignActive: "mac:ApplicationWillResignActive";
                              ApplicationWillSleep: "mac:ApplicationWillSleep";
                              ApplicationWillTerminate: "mac:ApplicationWillTerminate";
                              ApplicationWillUnhide: "mac:ApplicationWillUnhide";
                              ApplicationWillUpdate: "mac:ApplicationWillUpdate";
                              MenuDidAddItem: "mac:MenuDidAddItem";
                              MenuDidBeginTracking: "mac:MenuDidBeginTracking";
                              MenuDidClose: "mac:MenuDidClose";
                              MenuDidDisplayItem: "mac:MenuDidDisplayItem";
                              MenuDidEndTracking: "mac:MenuDidEndTracking";
                              MenuDidHighlightItem: "mac:MenuDidHighlightItem";
                              MenuDidOpen: "mac:MenuDidOpen";
                              MenuDidPopUp: "mac:MenuDidPopUp";
                              MenuDidRemoveItem: "mac:MenuDidRemoveItem";
                              MenuDidSendAction: "mac:MenuDidSendAction";
                              MenuDidSendActionToItem: "mac:MenuDidSendActionToItem";
                              MenuDidUpdate: "mac:MenuDidUpdate";
                              MenuWillAddItem: "mac:MenuWillAddItem";
                              MenuWillBeginTracking: "mac:MenuWillBeginTracking";
                              MenuWillDisplayItem: "mac:MenuWillDisplayItem";
                              MenuWillEndTracking: "mac:MenuWillEndTracking";
                              MenuWillHighlightItem: "mac:MenuWillHighlightItem";
                              MenuWillOpen: "mac:MenuWillOpen";
                              MenuWillPopUp: "mac:MenuWillPopUp";
                              MenuWillRemoveItem: "mac:MenuWillRemoveItem";
                              MenuWillSendAction: "mac:MenuWillSendAction";
                              MenuWillSendActionToItem: "mac:MenuWillSendActionToItem";
                              MenuWillUpdate: "mac:MenuWillUpdate";
                              WebViewDidCommitNavigation: "mac:WebViewDidCommitNavigation";
                              WebViewDidFinishNavigation: "mac:WebViewDidFinishNavigation";
                              WebViewDidReceiveServerRedirectForProvisionalNavigation: "mac:WebViewDidReceiveServerRedirectForProvisionalNavigation";
                              WebViewDidStartProvisionalNavigation: "mac:WebViewDidStartProvisionalNavigation";
                              WindowDidBecomeKey: "mac:WindowDidBecomeKey";
                              WindowDidBecomeMain: "mac:WindowDidBecomeMain";
                              WindowDidBeginSheet: "mac:WindowDidBeginSheet";
                              WindowDidChangeAlpha: "mac:WindowDidChangeAlpha";
                              WindowDidChangeBackingLocation: "mac:WindowDidChangeBackingLocation";
                              WindowDidChangeBackingProperties: "mac:WindowDidChangeBackingProperties";
                              WindowDidChangeCollectionBehavior: "mac:WindowDidChangeCollectionBehavior";
                              WindowDidChangeEffectiveAppearance: "mac:WindowDidChangeEffectiveAppearance";
                              WindowDidChangeOcclusionState: "mac:WindowDidChangeOcclusionState";
                              WindowDidChangeOrderingMode: "mac:WindowDidChangeOrderingMode";
                              WindowDidChangeScreen: "mac:WindowDidChangeScreen";
                              WindowDidChangeScreenParameters: "mac:WindowDidChangeScreenParameters";
                              WindowDidChangeScreenProfile: "mac:WindowDidChangeScreenProfile";
                              WindowDidChangeScreenSpace: "mac:WindowDidChangeScreenSpace";
                              WindowDidChangeScreenSpaceProperties: "mac:WindowDidChangeScreenSpaceProperties";
                              WindowDidChangeSharingType: "mac:WindowDidChangeSharingType";
                              WindowDidChangeSpace: "mac:WindowDidChangeSpace";
                              WindowDidChangeSpaceOrderingMode: "mac:WindowDidChangeSpaceOrderingMode";
                              WindowDidChangeTitle: "mac:WindowDidChangeTitle";
                              WindowDidChangeToolbar: "mac:WindowDidChangeToolbar";
                              WindowDidDeminiaturize: "mac:WindowDidDeminiaturize";
                              WindowDidEndSheet: "mac:WindowDidEndSheet";
                              WindowDidEnterFullScreen: "mac:WindowDidEnterFullScreen";
                              WindowDidEnterVersionBrowser: "mac:WindowDidEnterVersionBrowser";
                              WindowDidExitFullScreen: "mac:WindowDidExitFullScreen";
                              WindowDidExitVersionBrowser: "mac:WindowDidExitVersionBrowser";
                              WindowDidExpose: "mac:WindowDidExpose";
                              WindowDidFocus: "mac:WindowDidFocus";
                              WindowDidMiniaturize: "mac:WindowDidMiniaturize";
                              WindowDidMove: "mac:WindowDidMove";
                              WindowDidOrderOffScreen: "mac:WindowDidOrderOffScreen";
                              WindowDidOrderOnScreen: "mac:WindowDidOrderOnScreen";
                              WindowDidResignKey: "mac:WindowDidResignKey";
                              WindowDidResignMain: "mac:WindowDidResignMain";
                              WindowDidResize: "mac:WindowDidResize";
                              WindowDidUpdate: "mac:WindowDidUpdate";
                              WindowDidUpdateAlpha: "mac:WindowDidUpdateAlpha";
                              WindowDidUpdateCollectionBehavior: "mac:WindowDidUpdateCollectionBehavior";
                              WindowDidUpdateCollectionProperties: "mac:WindowDidUpdateCollectionProperties";
                              WindowDidUpdateShadow: "mac:WindowDidUpdateShadow";
                              WindowDidUpdateTitle: "mac:WindowDidUpdateTitle";
                              WindowDidUpdateToolbar: "mac:WindowDidUpdateToolbar";
                              WindowDidZoom: "mac:WindowDidZoom";
                              WindowFileDraggingEntered: "mac:WindowFileDraggingEntered";
                              WindowFileDraggingExited: "mac:WindowFileDraggingExited";
                              WindowFileDraggingPerformed: "mac:WindowFileDraggingPerformed";
                              WindowHide: "mac:WindowHide";
                              WindowMaximise: "mac:WindowMaximise";
                              WindowMinimise: "mac:WindowMinimise";
                              WindowShouldClose: "mac:WindowShouldClose";
                              WindowShow: "mac:WindowShow";
                              WindowUnMaximise: "mac:WindowUnMaximise";
                              WindowUnMinimise: "mac:WindowUnMinimise";
                              WindowWillBecomeKey: "mac:WindowWillBecomeKey";
                              WindowWillBecomeMain: "mac:WindowWillBecomeMain";
                              WindowWillBeginSheet: "mac:WindowWillBeginSheet";
                              WindowWillChangeOrderingMode: "mac:WindowWillChangeOrderingMode";
                              WindowWillClose: "mac:WindowWillClose";
                              WindowWillDeminiaturize: "mac:WindowWillDeminiaturize";
                              WindowWillEnterFullScreen: "mac:WindowWillEnterFullScreen";
                              WindowWillEnterVersionBrowser: "mac:WindowWillEnterVersionBrowser";
                              WindowWillExitFullScreen: "mac:WindowWillExitFullScreen";
                              WindowWillExitVersionBrowser: "mac:WindowWillExitVersionBrowser";
                              WindowWillFocus: "mac:WindowWillFocus";
                              WindowWillMiniaturize: "mac:WindowWillMiniaturize";
                              WindowWillMove: "mac:WindowWillMove";
                              WindowWillOrderOffScreen: "mac:WindowWillOrderOffScreen";
                              WindowWillOrderOnScreen: "mac:WindowWillOrderOnScreen";
                              WindowWillResignMain: "mac:WindowWillResignMain";
                              WindowWillResize: "mac:WindowWillResize";
                              WindowWillUnfocus: "mac:WindowWillUnfocus";
                              WindowWillUpdate: "mac:WindowWillUpdate";
                              WindowWillUpdateAlpha: "mac:WindowWillUpdateAlpha";
                              WindowWillUpdateCollectionBehavior: "mac:WindowWillUpdateCollectionBehavior";
                              WindowWillUpdateCollectionProperties: "mac:WindowWillUpdateCollectionProperties";
                              WindowWillUpdateShadow: "mac:WindowWillUpdateShadow";
                              WindowWillUpdateTitle: "mac:WindowWillUpdateTitle";
                              WindowWillUpdateToolbar: "mac:WindowWillUpdateToolbar";
                              WindowWillUpdateVisibility: "mac:WindowWillUpdateVisibility";
                              WindowWillUseStandardFrame: "mac:WindowWillUseStandardFrame";
                              WindowZoomIn: "mac:WindowZoomIn";
                              WindowZoomOut: "mac:WindowZoomOut";
                              WindowZoomReset: "mac:WindowZoomReset";
                          },
                      >;
                      Windows: Readonly<
                          {
                              APMPowerSettingChange: "windows:APMPowerSettingChange";
                              APMPowerStatusChange: "windows:APMPowerStatusChange";
                              APMResumeAutomatic: "windows:APMResumeAutomatic";
                              APMResumeSuspend: "windows:APMResumeSuspend";
                              APMSuspend: "windows:APMSuspend";
                              ApplicationStarted: "windows:ApplicationStarted";
                              SystemThemeChanged: "windows:SystemThemeChanged";
                              WebViewNavigationCompleted: "windows:WebViewNavigationCompleted";
                              WindowActive: "windows:WindowActive";
                              WindowBackgroundErase: "windows:WindowBackgroundErase";
                              WindowClickActive: "windows:WindowClickActive";
                              WindowClosing: "windows:WindowClosing";
                              WindowDidMove: "windows:WindowDidMove";
                              WindowDidResize: "windows:WindowDidResize";
                              WindowDPIChanged: "windows:WindowDPIChanged";
                              WindowDragDrop: "windows:WindowDragDrop";
                              WindowDragEnter: "windows:WindowDragEnter";
                              WindowDragLeave: "windows:WindowDragLeave";
                              WindowDragOver: "windows:WindowDragOver";
                              WindowEndMove: "windows:WindowEndMove";
                              WindowEndResize: "windows:WindowEndResize";
                              WindowFullscreen: "windows:WindowFullscreen";
                              WindowHide: "windows:WindowHide";
                              WindowInactive: "windows:WindowInactive";
                              WindowKeyDown: "windows:WindowKeyDown";
                              WindowKeyUp: "windows:WindowKeyUp";
                              WindowKillFocus: "windows:WindowKillFocus";
                              WindowMaximise: "windows:WindowMaximise";
                              WindowMinimise: "windows:WindowMinimise";
                              WindowNonClientHit: "windows:WindowNonClientHit";
                              WindowNonClientMouseDown: "windows:WindowNonClientMouseDown";
                              WindowNonClientMouseLeave: "windows:WindowNonClientMouseLeave";
                              WindowNonClientMouseMove: "windows:WindowNonClientMouseMove";
                              WindowNonClientMouseUp: "windows:WindowNonClientMouseUp";
                              WindowPaint: "windows:WindowPaint";
                              WindowRestore: "windows:WindowRestore";
                              WindowSetFocus: "windows:WindowSetFocus";
                              WindowShow: "windows:WindowShow";
                              WindowStartMove: "windows:WindowStartMove";
                              WindowStartResize: "windows:WindowStartResize";
                              WindowUnFullscreen: "windows:WindowUnFullscreen";
                              WindowUnMaximise: "windows:WindowUnMaximise";
                              WindowUnMinimise: "windows:WindowUnMinimise";
                              WindowZOrderChanged: "windows:WindowZOrderChanged";
                          },
                      >;
                  },
              > = ...
              +Types | @wailsio/runtime
              @wailsio/runtime
                Preparing search index...

                Variable TypesConst

                Types: Readonly<
                    {
                        Android: Readonly<
                            {
                                ActivityCreated: "android:ActivityCreated";
                                ActivityDestroyed: "android:ActivityDestroyed";
                                ActivityPaused: "android:ActivityPaused";
                                ActivityResumed: "android:ActivityResumed";
                                ActivityStarted: "android:ActivityStarted";
                                ActivityStopped: "android:ActivityStopped";
                                ApplicationLowMemory: "android:ApplicationLowMemory";
                                BatteryChanged: "android:BatteryChanged";
                                NetworkChanged: "android:NetworkChanged";
                                ScreenLocked: "android:ScreenLocked";
                                ScreenUnlocked: "android:ScreenUnlocked";
                                ThemeChanged: "android:ThemeChanged";
                                WebViewPageFinished: "android:WebViewPageFinished";
                                WebViewPageStarted: "android:WebViewPageStarted";
                            },
                        >;
                        Common: Readonly<
                            {
                                ApplicationLaunchedWithUrl: "common:ApplicationLaunchedWithUrl";
                                ApplicationOpenedWithFile: "common:ApplicationOpenedWithFile";
                                ApplicationStarted: "common:ApplicationStarted";
                                BatteryChanged: "common:BatteryChanged";
                                LowMemory: "common:LowMemory";
                                NetworkChanged: "common:NetworkChanged";
                                ScreenLocked: "common:ScreenLocked";
                                ScreenUnlocked: "common:ScreenUnlocked";
                                SystemDidWake: "common:SystemDidWake";
                                SystemWillSleep: "common:SystemWillSleep";
                                ThemeChanged: "common:ThemeChanged";
                                WindowClosing: "common:WindowClosing";
                                WindowDidMove: "common:WindowDidMove";
                                WindowDidResize: "common:WindowDidResize";
                                WindowDPIChanged: "common:WindowDPIChanged";
                                WindowFilesDropped: "common:WindowFilesDropped";
                                WindowFocus: "common:WindowFocus";
                                WindowFullscreen: "common:WindowFullscreen";
                                WindowHide: "common:WindowHide";
                                WindowLostFocus: "common:WindowLostFocus";
                                WindowMaximise: "common:WindowMaximise";
                                WindowMinimise: "common:WindowMinimise";
                                WindowRestore: "common:WindowRestore";
                                WindowRuntimeReady: "common:WindowRuntimeReady";
                                WindowShow: "common:WindowShow";
                                WindowToggleFrameless: "common:WindowToggleFrameless";
                                WindowUnFullscreen: "common:WindowUnFullscreen";
                                WindowUnMaximise: "common:WindowUnMaximise";
                                WindowUnMinimise: "common:WindowUnMinimise";
                                WindowZoom: "common:WindowZoom";
                                WindowZoomIn: "common:WindowZoomIn";
                                WindowZoomOut: "common:WindowZoomOut";
                                WindowZoomReset: "common:WindowZoomReset";
                            },
                        >;
                        iOS: Readonly<
                            {
                                ApplicationDidBecomeActive: "ios:ApplicationDidBecomeActive";
                                ApplicationDidEnterBackground: "ios:ApplicationDidEnterBackground";
                                ApplicationDidFinishLaunching: "ios:ApplicationDidFinishLaunching";
                                ApplicationDidReceiveMemoryWarning: "ios:ApplicationDidReceiveMemoryWarning";
                                ApplicationWillEnterForeground: "ios:ApplicationWillEnterForeground";
                                ApplicationWillResignActive: "ios:ApplicationWillResignActive";
                                ApplicationWillTerminate: "ios:ApplicationWillTerminate";
                                BatteryChanged: "ios:BatteryChanged";
                                NetworkChanged: "ios:NetworkChanged";
                                ScreenLocked: "ios:ScreenLocked";
                                ScreenUnlocked: "ios:ScreenUnlocked";
                                ThemeChanged: "ios:ThemeChanged";
                                WebViewDecidePolicyForNavigationAction: "ios:WebViewDecidePolicyForNavigationAction";
                                WebViewDidFailNavigation: "ios:WebViewDidFailNavigation";
                                WebViewDidFinishNavigation: "ios:WebViewDidFinishNavigation";
                                WebViewDidStartNavigation: "ios:WebViewDidStartNavigation";
                                WindowDidAppear: "ios:WindowDidAppear";
                                WindowDidDisappear: "ios:WindowDidDisappear";
                                WindowDidLoad: "ios:WindowDidLoad";
                                WindowOrientationChanged: "ios:WindowOrientationChanged";
                                WindowSafeAreaInsetsChanged: "ios:WindowSafeAreaInsetsChanged";
                                WindowTouchBegan: "ios:WindowTouchBegan";
                                WindowTouchCancelled: "ios:WindowTouchCancelled";
                                WindowTouchEnded: "ios:WindowTouchEnded";
                                WindowTouchMoved: "ios:WindowTouchMoved";
                                WindowWillAppear: "ios:WindowWillAppear";
                                WindowWillDisappear: "ios:WindowWillDisappear";
                            },
                        >;
                        Linux: Readonly<
                            {
                                ApplicationStartup: "linux:ApplicationStartup";
                                SystemDidWake: "linux:SystemDidWake";
                                SystemThemeChanged: "linux:SystemThemeChanged";
                                SystemWillSleep: "linux:SystemWillSleep";
                                WindowDeleteEvent: "linux:WindowDeleteEvent";
                                WindowDidMove: "linux:WindowDidMove";
                                WindowDidResize: "linux:WindowDidResize";
                                WindowFocusIn: "linux:WindowFocusIn";
                                WindowFocusOut: "linux:WindowFocusOut";
                                WindowLoadCommitted: "linux:WindowLoadCommitted";
                                WindowLoadFinished: "linux:WindowLoadFinished";
                                WindowLoadRedirected: "linux:WindowLoadRedirected";
                                WindowLoadStarted: "linux:WindowLoadStarted";
                            },
                        >;
                        Mac: Readonly<
                            {
                                ApplicationDidBecomeActive: "mac:ApplicationDidBecomeActive";
                                ApplicationDidChangeBackingProperties: "mac:ApplicationDidChangeBackingProperties";
                                ApplicationDidChangeEffectiveAppearance: "mac:ApplicationDidChangeEffectiveAppearance";
                                ApplicationDidChangeIcon: "mac:ApplicationDidChangeIcon";
                                ApplicationDidChangeOcclusionState: "mac:ApplicationDidChangeOcclusionState";
                                ApplicationDidChangeScreenParameters: "mac:ApplicationDidChangeScreenParameters";
                                ApplicationDidChangeStatusBarFrame: "mac:ApplicationDidChangeStatusBarFrame";
                                ApplicationDidChangeStatusBarOrientation: "mac:ApplicationDidChangeStatusBarOrientation";
                                ApplicationDidChangeTheme: "mac:ApplicationDidChangeTheme";
                                ApplicationDidFinishLaunching: "mac:ApplicationDidFinishLaunching";
                                ApplicationDidHide: "mac:ApplicationDidHide";
                                ApplicationDidResignActive: "mac:ApplicationDidResignActive";
                                ApplicationDidUnhide: "mac:ApplicationDidUnhide";
                                ApplicationDidUpdate: "mac:ApplicationDidUpdate";
                                ApplicationDidWake: "mac:ApplicationDidWake";
                                ApplicationScreensDidSleep: "mac:ApplicationScreensDidSleep";
                                ApplicationScreensDidWake: "mac:ApplicationScreensDidWake";
                                ApplicationShouldHandleReopen: "mac:ApplicationShouldHandleReopen";
                                ApplicationWillBecomeActive: "mac:ApplicationWillBecomeActive";
                                ApplicationWillFinishLaunching: "mac:ApplicationWillFinishLaunching";
                                ApplicationWillHide: "mac:ApplicationWillHide";
                                ApplicationWillResignActive: "mac:ApplicationWillResignActive";
                                ApplicationWillSleep: "mac:ApplicationWillSleep";
                                ApplicationWillTerminate: "mac:ApplicationWillTerminate";
                                ApplicationWillUnhide: "mac:ApplicationWillUnhide";
                                ApplicationWillUpdate: "mac:ApplicationWillUpdate";
                                MenuDidAddItem: "mac:MenuDidAddItem";
                                MenuDidBeginTracking: "mac:MenuDidBeginTracking";
                                MenuDidClose: "mac:MenuDidClose";
                                MenuDidDisplayItem: "mac:MenuDidDisplayItem";
                                MenuDidEndTracking: "mac:MenuDidEndTracking";
                                MenuDidHighlightItem: "mac:MenuDidHighlightItem";
                                MenuDidOpen: "mac:MenuDidOpen";
                                MenuDidPopUp: "mac:MenuDidPopUp";
                                MenuDidRemoveItem: "mac:MenuDidRemoveItem";
                                MenuDidSendAction: "mac:MenuDidSendAction";
                                MenuDidSendActionToItem: "mac:MenuDidSendActionToItem";
                                MenuDidUpdate: "mac:MenuDidUpdate";
                                MenuWillAddItem: "mac:MenuWillAddItem";
                                MenuWillBeginTracking: "mac:MenuWillBeginTracking";
                                MenuWillDisplayItem: "mac:MenuWillDisplayItem";
                                MenuWillEndTracking: "mac:MenuWillEndTracking";
                                MenuWillHighlightItem: "mac:MenuWillHighlightItem";
                                MenuWillOpen: "mac:MenuWillOpen";
                                MenuWillPopUp: "mac:MenuWillPopUp";
                                MenuWillRemoveItem: "mac:MenuWillRemoveItem";
                                MenuWillSendAction: "mac:MenuWillSendAction";
                                MenuWillSendActionToItem: "mac:MenuWillSendActionToItem";
                                MenuWillUpdate: "mac:MenuWillUpdate";
                                WebViewDidCommitNavigation: "mac:WebViewDidCommitNavigation";
                                WebViewDidFinishNavigation: "mac:WebViewDidFinishNavigation";
                                WebViewDidReceiveServerRedirectForProvisionalNavigation: "mac:WebViewDidReceiveServerRedirectForProvisionalNavigation";
                                WebViewDidStartProvisionalNavigation: "mac:WebViewDidStartProvisionalNavigation";
                                WebViewWebContentProcessDidTerminate: "mac:WebViewWebContentProcessDidTerminate";
                                WindowDidBecomeKey: "mac:WindowDidBecomeKey";
                                WindowDidBecomeMain: "mac:WindowDidBecomeMain";
                                WindowDidBeginSheet: "mac:WindowDidBeginSheet";
                                WindowDidChangeAlpha: "mac:WindowDidChangeAlpha";
                                WindowDidChangeBackingLocation: "mac:WindowDidChangeBackingLocation";
                                WindowDidChangeBackingProperties: "mac:WindowDidChangeBackingProperties";
                                WindowDidChangeCollectionBehavior: "mac:WindowDidChangeCollectionBehavior";
                                WindowDidChangeEffectiveAppearance: "mac:WindowDidChangeEffectiveAppearance";
                                WindowDidChangeOcclusionState: "mac:WindowDidChangeOcclusionState";
                                WindowDidChangeOrderingMode: "mac:WindowDidChangeOrderingMode";
                                WindowDidChangeScreen: "mac:WindowDidChangeScreen";
                                WindowDidChangeScreenParameters: "mac:WindowDidChangeScreenParameters";
                                WindowDidChangeScreenProfile: "mac:WindowDidChangeScreenProfile";
                                WindowDidChangeScreenSpace: "mac:WindowDidChangeScreenSpace";
                                WindowDidChangeScreenSpaceProperties: "mac:WindowDidChangeScreenSpaceProperties";
                                WindowDidChangeSharingType: "mac:WindowDidChangeSharingType";
                                WindowDidChangeSpace: "mac:WindowDidChangeSpace";
                                WindowDidChangeSpaceOrderingMode: "mac:WindowDidChangeSpaceOrderingMode";
                                WindowDidChangeTitle: "mac:WindowDidChangeTitle";
                                WindowDidChangeToolbar: "mac:WindowDidChangeToolbar";
                                WindowDidDeminiaturize: "mac:WindowDidDeminiaturize";
                                WindowDidEndSheet: "mac:WindowDidEndSheet";
                                WindowDidEnterFullScreen: "mac:WindowDidEnterFullScreen";
                                WindowDidEnterVersionBrowser: "mac:WindowDidEnterVersionBrowser";
                                WindowDidExitFullScreen: "mac:WindowDidExitFullScreen";
                                WindowDidExitVersionBrowser: "mac:WindowDidExitVersionBrowser";
                                WindowDidExpose: "mac:WindowDidExpose";
                                WindowDidFocus: "mac:WindowDidFocus";
                                WindowDidMiniaturize: "mac:WindowDidMiniaturize";
                                WindowDidMove: "mac:WindowDidMove";
                                WindowDidOrderOffScreen: "mac:WindowDidOrderOffScreen";
                                WindowDidOrderOnScreen: "mac:WindowDidOrderOnScreen";
                                WindowDidResignKey: "mac:WindowDidResignKey";
                                WindowDidResignMain: "mac:WindowDidResignMain";
                                WindowDidResize: "mac:WindowDidResize";
                                WindowDidUpdate: "mac:WindowDidUpdate";
                                WindowDidUpdateAlpha: "mac:WindowDidUpdateAlpha";
                                WindowDidUpdateCollectionBehavior: "mac:WindowDidUpdateCollectionBehavior";
                                WindowDidUpdateCollectionProperties: "mac:WindowDidUpdateCollectionProperties";
                                WindowDidUpdateShadow: "mac:WindowDidUpdateShadow";
                                WindowDidUpdateTitle: "mac:WindowDidUpdateTitle";
                                WindowDidUpdateToolbar: "mac:WindowDidUpdateToolbar";
                                WindowDidZoom: "mac:WindowDidZoom";
                                WindowFileDraggingEntered: "mac:WindowFileDraggingEntered";
                                WindowFileDraggingExited: "mac:WindowFileDraggingExited";
                                WindowFileDraggingPerformed: "mac:WindowFileDraggingPerformed";
                                WindowHide: "mac:WindowHide";
                                WindowMaximise: "mac:WindowMaximise";
                                WindowMinimise: "mac:WindowMinimise";
                                WindowShouldClose: "mac:WindowShouldClose";
                                WindowShow: "mac:WindowShow";
                                WindowUnMaximise: "mac:WindowUnMaximise";
                                WindowUnMinimise: "mac:WindowUnMinimise";
                                WindowWillBecomeKey: "mac:WindowWillBecomeKey";
                                WindowWillBecomeMain: "mac:WindowWillBecomeMain";
                                WindowWillBeginSheet: "mac:WindowWillBeginSheet";
                                WindowWillChangeOrderingMode: "mac:WindowWillChangeOrderingMode";
                                WindowWillClose: "mac:WindowWillClose";
                                WindowWillDeminiaturize: "mac:WindowWillDeminiaturize";
                                WindowWillEnterFullScreen: "mac:WindowWillEnterFullScreen";
                                WindowWillEnterVersionBrowser: "mac:WindowWillEnterVersionBrowser";
                                WindowWillExitFullScreen: "mac:WindowWillExitFullScreen";
                                WindowWillExitVersionBrowser: "mac:WindowWillExitVersionBrowser";
                                WindowWillFocus: "mac:WindowWillFocus";
                                WindowWillMiniaturize: "mac:WindowWillMiniaturize";
                                WindowWillMove: "mac:WindowWillMove";
                                WindowWillOrderOffScreen: "mac:WindowWillOrderOffScreen";
                                WindowWillOrderOnScreen: "mac:WindowWillOrderOnScreen";
                                WindowWillResignMain: "mac:WindowWillResignMain";
                                WindowWillResize: "mac:WindowWillResize";
                                WindowWillUnfocus: "mac:WindowWillUnfocus";
                                WindowWillUpdate: "mac:WindowWillUpdate";
                                WindowWillUpdateAlpha: "mac:WindowWillUpdateAlpha";
                                WindowWillUpdateCollectionBehavior: "mac:WindowWillUpdateCollectionBehavior";
                                WindowWillUpdateCollectionProperties: "mac:WindowWillUpdateCollectionProperties";
                                WindowWillUpdateShadow: "mac:WindowWillUpdateShadow";
                                WindowWillUpdateTitle: "mac:WindowWillUpdateTitle";
                                WindowWillUpdateToolbar: "mac:WindowWillUpdateToolbar";
                                WindowWillUpdateVisibility: "mac:WindowWillUpdateVisibility";
                                WindowWillUseStandardFrame: "mac:WindowWillUseStandardFrame";
                                WindowZoomIn: "mac:WindowZoomIn";
                                WindowZoomOut: "mac:WindowZoomOut";
                                WindowZoomReset: "mac:WindowZoomReset";
                            },
                        >;
                        Windows: Readonly<
                            {
                                APMPowerSettingChange: "windows:APMPowerSettingChange";
                                APMPowerStatusChange: "windows:APMPowerStatusChange";
                                APMResumeAutomatic: "windows:APMResumeAutomatic";
                                APMResumeSuspend: "windows:APMResumeSuspend";
                                APMSuspend: "windows:APMSuspend";
                                ApplicationStarted: "windows:ApplicationStarted";
                                SystemThemeChanged: "windows:SystemThemeChanged";
                                WebViewNavigationCompleted: "windows:WebViewNavigationCompleted";
                                WindowActive: "windows:WindowActive";
                                WindowBackgroundErase: "windows:WindowBackgroundErase";
                                WindowClickActive: "windows:WindowClickActive";
                                WindowClosing: "windows:WindowClosing";
                                WindowDidMove: "windows:WindowDidMove";
                                WindowDidResize: "windows:WindowDidResize";
                                WindowDPIChanged: "windows:WindowDPIChanged";
                                WindowDragDrop: "windows:WindowDragDrop";
                                WindowDragEnter: "windows:WindowDragEnter";
                                WindowDragLeave: "windows:WindowDragLeave";
                                WindowDragOver: "windows:WindowDragOver";
                                WindowEndMove: "windows:WindowEndMove";
                                WindowEndResize: "windows:WindowEndResize";
                                WindowFullscreen: "windows:WindowFullscreen";
                                WindowHide: "windows:WindowHide";
                                WindowInactive: "windows:WindowInactive";
                                WindowKeyDown: "windows:WindowKeyDown";
                                WindowKeyUp: "windows:WindowKeyUp";
                                WindowKillFocus: "windows:WindowKillFocus";
                                WindowMaximise: "windows:WindowMaximise";
                                WindowMinimise: "windows:WindowMinimise";
                                WindowNonClientHit: "windows:WindowNonClientHit";
                                WindowNonClientMouseDown: "windows:WindowNonClientMouseDown";
                                WindowNonClientMouseLeave: "windows:WindowNonClientMouseLeave";
                                WindowNonClientMouseMove: "windows:WindowNonClientMouseMove";
                                WindowNonClientMouseUp: "windows:WindowNonClientMouseUp";
                                WindowPaint: "windows:WindowPaint";
                                WindowRestore: "windows:WindowRestore";
                                WindowSetFocus: "windows:WindowSetFocus";
                                WindowShow: "windows:WindowShow";
                                WindowStartMove: "windows:WindowStartMove";
                                WindowStartResize: "windows:WindowStartResize";
                                WindowUnFullscreen: "windows:WindowUnFullscreen";
                                WindowUnMaximise: "windows:WindowUnMaximise";
                                WindowUnMinimise: "windows:WindowUnMinimise";
                                WindowZOrderChanged: "windows:WindowZOrderChanged";
                            },
                        >;
                    },
                > = ...
                diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/variables/clientId.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/variables/clientId.html index b8623df0e1c..79907791766 100644 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/variables/clientId.html +++ b/v3/internal/runtime/desktop/@wailsio/runtime/docs/variables/clientId.html @@ -1 +1 @@ -clientId | @wailsio/runtime
                @wailsio/runtime
                  Preparing search index...

                  Variable clientId

                  clientId: string = ...
                  +clientId | @wailsio/runtime
                  @wailsio/runtime
                    Preparing search index...

                    Variable clientId

                    clientId: string = ...
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/variables/objectNames.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/variables/objectNames.html index 6e2cd5d357b..c8f1e7b95f0 100644 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/variables/objectNames.html +++ b/v3/internal/runtime/desktop/@wailsio/runtime/docs/variables/objectNames.html @@ -1 +1 @@ -objectNames | @wailsio/runtime
                    @wailsio/runtime
                      Preparing search index...

                      Variable objectNamesConst

                      objectNames: Readonly<
                          {
                              Android: 12;
                              Application: 2;
                              Browser: 9;
                              Call: 0;
                              CancelCall: 10;
                              Clipboard: 1;
                              ContextMenu: 4;
                              Dialog: 5;
                              Events: 3;
                              IOS: 11;
                              Screens: 7;
                              System: 8;
                              Window: 6;
                          },
                      > = ...
                      +objectNames | @wailsio/runtime
                      @wailsio/runtime
                        Preparing search index...

                        Variable objectNamesConst

                        objectNames: Readonly<
                            {
                                Android: 12;
                                Application: 2;
                                Browser: 9;
                                Call: 0;
                                CancelCall: 10;
                                Clipboard: 1;
                                ContextMenu: 4;
                                Dialog: 5;
                                Events: 3;
                                IOS: 11;
                                Screens: 7;
                                System: 8;
                                Window: 6;
                            },
                        > = ...
                        diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/package-lock.json b/v3/internal/runtime/desktop/@wailsio/runtime/package-lock.json index c12ca8e5e2d..5acda88d971 100644 --- a/v3/internal/runtime/desktop/@wailsio/runtime/package-lock.json +++ b/v3/internal/runtime/desktop/@wailsio/runtime/package-lock.json @@ -1,14 +1,15 @@ { "name": "@wailsio/runtime", - "version": "3.0.0-alpha.95", + "version": "3.0.0-alpha.97", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@wailsio/runtime", - "version": "3.0.0-alpha.95", + "version": "3.0.0-alpha.97", "license": "MIT", "devDependencies": { + "esbuild": "0.28.1", "happy-dom": "^20.9.0", "promises-aplus-tests": "2.1.2", "rimraf": "^6.0.1", @@ -55,6 +56,448 @@ "tslib": "^2.4.0" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@gerrit0/mini-shiki": { "version": "3.23.0", "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-3.23.0.tgz", @@ -1032,6 +1475,48 @@ "dev": true, "license": "MIT" }, + "node_modules/esbuild": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" + } + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/package.json b/v3/internal/runtime/desktop/@wailsio/runtime/package.json index 50ca01b8fe5..ec1ed4a5eee 100644 --- a/v3/internal/runtime/desktop/@wailsio/runtime/package.json +++ b/v3/internal/runtime/desktop/@wailsio/runtime/package.json @@ -1,7 +1,7 @@ { "name": "@wailsio/runtime", "type": "module", - "version": "3.0.0-alpha.95", + "version": "3.0.0-alpha.97", "description": "Wails Runtime", "types": "types/index.d.ts", "exports": { @@ -31,6 +31,7 @@ ], "sideEffects": [ "./dist/index.js", + "./dist/appregion.js", "./dist/contextmenu.js", "./dist/drag.js" ], @@ -48,6 +49,7 @@ "prepack": "npm run build" }, "devDependencies": { + "esbuild": "0.28.1", "happy-dom": "^20.9.0", "promises-aplus-tests": "2.1.2", "rimraf": "^6.0.1", diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/appregion.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/appregion.ts new file mode 100644 index 00000000000..7f284546aed --- /dev/null +++ b/v3/internal/runtime/desktop/@wailsio/runtime/src/appregion.ts @@ -0,0 +1,235 @@ +/* + _ __ _ __ +| | / /___(_) /____ +| | /| / / __ `/ / / ___/ +| |/ |/ / /_/ / / (__ ) +|__/|__/\__,_/_/_/____/ +The electron alternative for Go +(c) Lea Anthony 2019-present +*/ + +import { invoke } from "./system.js"; +import { whenReady } from "./utils.js"; +import { hasDOM } from "./environment.js"; + +type NonClientRegionKind = "caption" | "minimize" | "maximize" | "close"; + +interface NonClientRegion { + kind: NonClientRegionKind; + left: number; + top: number; + right: number; + bottom: number; +} + +/* +--wails-non-client-region: caption; marks an area that can drag the window +--wails-non-client-region: minimize; marks a custom minimize button +--wails-non-client-region: maximize; marks a custom maximize button +--wails-non-client-region: close; marks a custom close button +*/ +const regionProperty = "--wails-non-client-region"; +const runtimeConfigReadyEvent = "wails:runtime-config-ready"; +const validRegions = new Set(["caption", "minimize", "maximize", "close"]); + +// Setup +if (hasDOM) { + window._wails = window._wails || {}; +} + +let updatePending = false; +let lastPayload = ""; +let observedElements = new Set(); +let resizeObserver: ResizeObserver | undefined; +let trackingStarted = false; + +function normaliseRegionKind(value: string): NonClientRegionKind | undefined { + const region = value.trim().toLowerCase(); + if (validRegions.has(region as NonClientRegionKind)) { + return region as NonClientRegionKind; + } + return undefined; +} + +function nonClientRegionForElement(element: Element): NonClientRegionKind | undefined { + if (!(element instanceof HTMLElement)) { + return undefined; + } + + const style = window.getComputedStyle(element); + const region = normaliseRegionKind(style.getPropertyValue(regionProperty)); + if (!region) { + return undefined; + } + + const parent = element.parentElement; + if (parent) { + const parentStyle = window.getComputedStyle(parent); + // The CSS property is inherited. Only report the outermost element for + // each contiguous region so native hit testing sees stable rectangles. + if (normaliseRegionKind(parentStyle.getPropertyValue(regionProperty)) === region) { + return undefined; + } + } + + return region; +} + +function isVisible(element: HTMLElement): boolean { + const style = window.getComputedStyle(element); + return style.display !== "none" && + style.visibility !== "hidden" && + style.contentVisibility !== "hidden"; +} + +function elementRegion(element: Element): NonClientRegion | undefined { + if (!(element instanceof HTMLElement)) { + return undefined; + } + + const kind = nonClientRegionForElement(element); + if (!kind || !isVisible(element)) { + return undefined; + } + + const rect = element.getBoundingClientRect(); + if (rect.width <= 0 || rect.height <= 0) { + return undefined; + } + + // Native hit testing runs in physical pixels, while DOM geometry is in CSS pixels. + const scale = window.devicePixelRatio || 1; + const left = Math.floor(rect.left * scale); + const top = Math.floor(rect.top * scale); + const right = Math.ceil(rect.right * scale); + const bottom = Math.ceil(rect.bottom * scale); + + if (right <= left || bottom <= top) { + return undefined; + } + + return { kind, left, top, right, bottom }; +} + +function regionElements(): Element[] { + const elements: Element[] = []; + + if (document.documentElement) { + elements.push(document.documentElement); + } + if (document.body) { + elements.push(document.body); + // Append via a loop: spreading a huge NodeList into push() overflows + // the engine's argument limit on very large documents. + for (const element of document.body.querySelectorAll("*")) { + elements.push(element); + } + } + + return elements; +} + +function observeRegionElements(elements: Element[]): void { + if (typeof ResizeObserver === "undefined") { + return; + } + + // Track size changes only for active region elements. DOM structure and style + // changes are covered by MutationObserver in startNonClientRegionTracking(). + resizeObserver ??= new ResizeObserver(scheduleUpdate); + const nextElements = new Set(elements); + + for (const element of observedElements) { + if (!nextElements.has(element)) { + resizeObserver.unobserve(element); + } + } + + for (const element of nextElements) { + if (!observedElements.has(element)) { + resizeObserver.observe(element); + } + } + + observedElements = nextElements; +} + +function updateNonClientRegions(): void { + updatePending = false; + + const elements = regionElements(); + const regions: NonClientRegion[] = []; + const activeElements: Element[] = []; + + for (const element of elements) { + const region = elementRegion(element); + if (region) { + regions.push(region); + activeElements.push(element); + } + } + + observeRegionElements(activeElements); + + const payload = JSON.stringify({ version: 1, regions }); + if (payload === lastPayload) { + // Avoid sending duplicate native messages during resize or style churn. + return; + } + + lastPayload = payload; + invoke("wails:non-client-region:" + payload); +} + +function scheduleUpdate(): void { + if (updatePending) { + return; + } + + // Batch region updates to animation frames so layout is measured once per frame. + updatePending = true; + window.requestAnimationFrame(updateNonClientRegions); +} + +function startNonClientRegionTracking(): void { + if (trackingStarted) { + return; + } + + trackingStarted = true; + // Send an initial empty or populated region list once the DOM is ready. + scheduleUpdate(); + + const mutationObserver = new MutationObserver(scheduleUpdate); + mutationObserver.observe(document.documentElement, { + attributes: true, + childList: true, + subtree: true, + }); + + window.addEventListener("resize", scheduleUpdate); + window.addEventListener("scroll", scheduleUpdate, true); + window.visualViewport?.addEventListener("resize", scheduleUpdate); + window.visualViewport?.addEventListener("scroll", scheduleUpdate); +} + +function tryStartNonClientRegionTracking(): boolean { + const os = window._wails.environment?.OS; + if (os === undefined) { + return false; + } + + const enabled = window._wails.flags?.nonClientRegionTracking; + if (os === "windows") { + if (enabled === true) { + whenReady(startNonClientRegionTracking); + } + return true; + } + + return true; +} + +if (hasDOM && !tryStartNonClientRegionTracking()) { + window.addEventListener(runtimeConfigReadyEvent, tryStartNonClientRegionTracking, { once: true }); +} diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/calls.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/calls.ts index d6e245d8713..4dc39fbbcd6 100644 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/calls.ts +++ b/v3/internal/runtime/desktop/@wailsio/runtime/src/calls.ts @@ -48,21 +48,10 @@ export type CallOptions = { args: any[]; }; -/** - * Exception class that will be thrown in case the bound method returns an error. - * The value of the {@link RuntimeError#name} property is "RuntimeError". - */ -export class RuntimeError extends Error { - /** - * Constructs a new RuntimeError instance. - * @param message - The error message. - * @param options - Options to be forwarded to the Error constructor. - */ - constructor(message?: string, options?: ErrorOptions) { - super(message, options); - this.name = "RuntimeError"; - } -} +// runtime.js needs to use RuntimeError internally to properly parse and return +// errors for binding calls, so it had to move there. Exporting here again to +// keep from breaking the public Call interface. +export { RuntimeError } from "./runtime.js"; /** * Generates a unique ID using the nanoid library. diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/drag.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/drag.ts index db12127267d..f21b942355c 100644 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/drag.ts +++ b/v3/internal/runtime/desktop/@wailsio/runtime/src/drag.ts @@ -159,6 +159,13 @@ function primaryDown(event: MouseEvent): void { } if (resizeEdge) { + // Do not arm edge resize from synthesized presses observed on move/up: + // entering the window with the primary button already held should not + // steal another gesture into a resize. + if (event.type !== 'mousedown') { + return; + } + // Ready to resize if the primary button was pressed for the first time. canResize = true; // Do not start drag operations when on resize edges. diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts index f07e0cce471..bb18c181b0e 100644 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts +++ b/v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts @@ -17,6 +17,7 @@ if (hasDOM) { import "./contextmenu.js"; import "./drag.js"; +import "./appregion.js"; // Re-export public API import * as Application from "./application.js"; diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts index f48c701ec3d..7704f563b2b 100644 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts +++ b/v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts @@ -23,6 +23,28 @@ const CHUNK_THRESHOLD = 512 * 1024; // Re-export nanoid for custom transport implementations export { nanoid }; +type CallErrorType = { + message: string, + cause?: unknown, + kind: "ReferenceError" | "TypeError" | "RuntimeError" +} + +/** + * Exception class that will be thrown in case the bound method returns an error. + * The value of the {@link RuntimeError#name} property is "RuntimeError". + */ +export class RuntimeError extends Error { + /** + * Constructs a new RuntimeError instance. + * @param message - The error message. + * @param options - Options to be forwarded to the Error constructor. + */ + constructor(message?: string, options?: ErrorOptions) { + super(message, options); + this.name = "RuntimeError"; + } +} + // Object Names export const objectNames = Object.freeze({ Call: 0, @@ -141,7 +163,20 @@ async function runtimeCallWithID(objectID: number, method: number, windowName: s response = await fetch(url, { method: 'POST', headers, body: bodyStr }); } if (!response.ok) { - throw new Error(await response.text()); + const ct = response.headers.get("Content-Type"); + if (ct?.includes("application/json")) { + const json: CallErrorType = await response.json(); + let err; + switch (json.kind) { + case "ReferenceError": err = new ReferenceError(json.message); break; + case "TypeError": err = new TypeError(json.message); break; + case "RuntimeError": err = new RuntimeError(json.message); break; + default: err = new Error(json.message); + } + err.cause = json.cause; + throw err + } + throw new Error(await response.text()); } if ((response.headers.get("Content-Type")?.indexOf("application/json") ?? -1) !== -1) { diff --git a/v3/internal/runtime/runtime.go b/v3/internal/runtime/runtime.go index d35ff05524c..bbd165fc539 100644 --- a/v3/internal/runtime/runtime.go +++ b/v3/internal/runtime/runtime.go @@ -7,6 +7,7 @@ import ( ) var runtimeInit = `window._wails=window._wails||{};window._wails.flags=window._wails.flags||{};window.wails=window.wails||{};` +var runtimeConfigReady = `Promise.resolve().then(function(){window.dispatchEvent(new Event("wails:runtime-config-ready"));});` func Core(flags map[string]any) string { flagsStr := "" @@ -17,5 +18,5 @@ func Core(flags map[string]any) string { } } - return runtimeInit + flagsStr + invoke + environment + return runtimeInit + flagsStr + invoke + environment + runtimeConfigReady } diff --git a/v3/internal/webview2/pkg/edge/COREWEBVIEW2_MOUSE_EVENT_KIND.go b/v3/internal/webview2/pkg/edge/COREWEBVIEW2_MOUSE_EVENT_KIND.go new file mode 100644 index 00000000000..e610931b2f9 --- /dev/null +++ b/v3/internal/webview2/pkg/edge/COREWEBVIEW2_MOUSE_EVENT_KIND.go @@ -0,0 +1,26 @@ +//go:build windows + +package edge + +type COREWEBVIEW2_MOUSE_EVENT_KIND uint32 + +const ( + COREWEBVIEW2_MOUSE_EVENT_KIND_HORIZONTAL_WHEEL = 526 + COREWEBVIEW2_MOUSE_EVENT_KIND_LEFT_BUTTON_DOUBLE_CLICK = 515 + COREWEBVIEW2_MOUSE_EVENT_KIND_LEFT_BUTTON_DOWN = 513 + COREWEBVIEW2_MOUSE_EVENT_KIND_LEFT_BUTTON_UP = 514 + COREWEBVIEW2_MOUSE_EVENT_KIND_LEAVE = 675 + COREWEBVIEW2_MOUSE_EVENT_KIND_MIDDLE_BUTTON_DOUBLE_CLICK = 521 + COREWEBVIEW2_MOUSE_EVENT_KIND_MIDDLE_BUTTON_DOWN = 519 + COREWEBVIEW2_MOUSE_EVENT_KIND_MIDDLE_BUTTON_UP = 520 + COREWEBVIEW2_MOUSE_EVENT_KIND_MOVE = 512 + COREWEBVIEW2_MOUSE_EVENT_KIND_RIGHT_BUTTON_DOUBLE_CLICK = 518 + COREWEBVIEW2_MOUSE_EVENT_KIND_RIGHT_BUTTON_DOWN = 516 + COREWEBVIEW2_MOUSE_EVENT_KIND_RIGHT_BUTTON_UP = 517 + COREWEBVIEW2_MOUSE_EVENT_KIND_WHEEL = 522 + COREWEBVIEW2_MOUSE_EVENT_KIND_X_BUTTON_DOUBLE_CLICK = 525 + COREWEBVIEW2_MOUSE_EVENT_KIND_X_BUTTON_DOWN = 523 + COREWEBVIEW2_MOUSE_EVENT_KIND_X_BUTTON_UP = 524 + COREWEBVIEW2_MOUSE_EVENT_KIND_NON_CLIENT_RIGHT_BUTTON_DOWN = 164 + COREWEBVIEW2_MOUSE_EVENT_KIND_NON_CLIENT_RIGHT_BUTTON_UP = 165 +) diff --git a/v3/internal/webview2/pkg/edge/COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS.go b/v3/internal/webview2/pkg/edge/COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS.go new file mode 100644 index 00000000000..363edbae068 --- /dev/null +++ b/v3/internal/webview2/pkg/edge/COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS.go @@ -0,0 +1,16 @@ +//go:build windows + +package edge + +type COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS uint32 + +const ( + COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS_NONE COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS = 0 + COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS_LEFT_BUTTON COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS = 1 + COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS_RIGHT_BUTTON COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS = 2 + COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS_SHIFT COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS = 4 + COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS_CONTROL COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS = 8 + COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS_MIDDLE_BUTTON COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS = 16 + COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS_X_BUTTON1 COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS = 32 + COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS_X_BUTTON2 COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS = 64 +) diff --git a/v3/internal/webview2/pkg/edge/COREWEBVIEW2_NON_CLIENT_REGION_KIND.go b/v3/internal/webview2/pkg/edge/COREWEBVIEW2_NON_CLIENT_REGION_KIND.go new file mode 100644 index 00000000000..2cda60b0253 --- /dev/null +++ b/v3/internal/webview2/pkg/edge/COREWEBVIEW2_NON_CLIENT_REGION_KIND.go @@ -0,0 +1,14 @@ +//go:build windows + +package edge + +type COREWEBVIEW2_NON_CLIENT_REGION_KIND uint32 + +const ( + COREWEBVIEW2_NON_CLIENT_REGION_KIND_NOWHERE = 0 + COREWEBVIEW2_NON_CLIENT_REGION_KIND_CLIENT = 1 + COREWEBVIEW2_NON_CLIENT_REGION_KIND_CAPTION = 2 + COREWEBVIEW2_NON_CLIENT_REGION_KIND_MINIMIZE = 8 + COREWEBVIEW2_NON_CLIENT_REGION_KIND_MAXIMIZE = 9 + COREWEBVIEW2_NON_CLIENT_REGION_KIND_CLOSE = 20 +) diff --git a/v3/internal/webview2/pkg/edge/ICoreWebView2CompositionController.go b/v3/internal/webview2/pkg/edge/ICoreWebView2CompositionController.go new file mode 100644 index 00000000000..60295f90b3a --- /dev/null +++ b/v3/internal/webview2/pkg/edge/ICoreWebView2CompositionController.go @@ -0,0 +1,109 @@ +//go:build windows + +package edge + +import ( + "syscall" + "unsafe" +) + +type ICoreWebView2CompositionControllerVtbl struct { + _IUnknownVtbl + GetRootVisualTarget ComProc + PutRootVisualTarget ComProc + SendMouseInput ComProc + SendPointerInput ComProc + GetCursor ComProc + GetSystemCursorId ComProc + AddCursorChanged ComProc + RemoveCursorChanged ComProc +} + +type ICoreWebView2CompositionController struct { + Vtbl *ICoreWebView2CompositionControllerVtbl +} + +func (i *ICoreWebView2CompositionController) AddRef() uintptr { + ret, _, _ := i.Vtbl.AddRef.Call(uintptr(unsafe.Pointer(i))) + + return ret +} + +func (i *ICoreWebView2CompositionController) Release() uintptr { + ret, _, _ := i.Vtbl.Release.Call(uintptr(unsafe.Pointer(i))) + + return ret +} + +func (i *ICoreWebView2CompositionController) GetICoreWebView2Controller() *ICoreWebView2Controller { + var result *ICoreWebView2Controller + + iidICoreWebView2Controller := NewGUID("{4D00C0D1-9434-4EB6-8078-8697A560334F}") + _, _, _ = i.Vtbl.QueryInterface.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(iidICoreWebView2Controller)), + uintptr(unsafe.Pointer(&result))) + + return result +} + +func (i *ICoreWebView2CompositionController) PutRootVisualTarget(target *IUnknown) error { + hr, _, _ := i.Vtbl.PutRootVisualTarget.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(target)), + ) + if int32(hr) < 0 { + return syscall.Errno(hr) + } + return nil +} + +func (i *ICoreWebView2CompositionController) SendMouseInput(eventKind COREWEBVIEW2_MOUSE_EVENT_KIND, virtualKeys COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS, mouseData uint32, point POINT) error { + hr, _, _ := i.Vtbl.SendMouseInput.Call( + uintptr(unsafe.Pointer(i)), + uintptr(eventKind), + uintptr(virtualKeys), + uintptr(mouseData), + point.uintptr(), + ) + if int32(hr) < 0 { + return syscall.Errno(hr) + } + return nil +} + +func (i *ICoreWebView2CompositionController) GetCursor() (HCURSOR, error) { + var cursor HCURSOR + hr, _, _ := i.Vtbl.GetCursor.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&cursor)), + ) + if int32(hr) < 0 { + return 0, syscall.Errno(hr) + } + return cursor, nil +} + +func (i *ICoreWebView2CompositionController) GetSystemCursorId() (uint32, error) { + var cursorID uint32 + hr, _, _ := i.Vtbl.GetSystemCursorId.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&cursorID)), + ) + if int32(hr) < 0 { + return 0, syscall.Errno(hr) + } + return cursorID, nil +} + +func (i *ICoreWebView2CompositionController) AddCursorChanged(eventHandler *iCoreWebView2CursorChangedEventHandler, token *_EventRegistrationToken) error { + hr, _, _ := i.Vtbl.AddCursorChanged.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(eventHandler)), + uintptr(unsafe.Pointer(token)), + ) + if int32(hr) < 0 { + return syscall.Errno(hr) + } + return nil +} diff --git a/v3/internal/webview2/pkg/edge/ICoreWebView2CompositionController4.go b/v3/internal/webview2/pkg/edge/ICoreWebView2CompositionController4.go new file mode 100644 index 00000000000..3b710281ede --- /dev/null +++ b/v3/internal/webview2/pkg/edge/ICoreWebView2CompositionController4.go @@ -0,0 +1,73 @@ +//go:build windows + +package edge + +import ( + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +type ICoreWebView2CompositionController4Vtbl struct { + _IUnknownVtbl + GetRootVisualTarget ComProc + PutRootVisualTarget ComProc + SendMouseInput ComProc + SendPointerInput ComProc + GetCursor ComProc + GetSystemCursorId ComProc + AddCursorChanged ComProc + RemoveCursorChanged ComProc + GetUIAProvider ComProc + DragEnter ComProc + DragLeave ComProc + DragOver ComProc + Drop ComProc + GetNonClientRegionAtPoint ComProc + QueryNonClientRegion ComProc + AddNonClientRegionChanged ComProc + RemoveNonClientRegionChanged ComProc +} + +type ICoreWebView2CompositionController4 struct { + Vtbl *ICoreWebView2CompositionController4Vtbl +} + +func (i *ICoreWebView2CompositionController4) AddRef() uintptr { + ret, _, _ := i.Vtbl.AddRef.Call(uintptr(unsafe.Pointer(i))) + + return ret +} + +func (i *ICoreWebView2CompositionController4) Release() uintptr { + ret, _, _ := i.Vtbl.Release.Call(uintptr(unsafe.Pointer(i))) + + return ret +} + +func (i *ICoreWebView2CompositionController) GetICoreWebView2CompositionController4() *ICoreWebView2CompositionController4 { + var result *ICoreWebView2CompositionController4 + + iidICoreWebView2CompositionController4 := NewGUID("{7C367B9B-3D2B-450F-9E58-D61A20F486AA}") + _, _, _ = i.Vtbl.QueryInterface.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(iidICoreWebView2CompositionController4)), + uintptr(unsafe.Pointer(&result))) + + return result +} + +func (i *ICoreWebView2CompositionController4) GetNonClientRegionAtPoint(point POINT) (COREWEBVIEW2_NON_CLIENT_REGION_KIND, error) { + var value COREWEBVIEW2_NON_CLIENT_REGION_KIND + + hr, _, _ := i.Vtbl.GetNonClientRegionAtPoint.Call( + uintptr(unsafe.Pointer(i)), + point.uintptr(), + uintptr(unsafe.Pointer(&value)), + ) + if windows.Handle(hr) != windows.S_OK { + return 0, syscall.Errno(hr) + } + return value, nil +} diff --git a/v3/internal/webview2/pkg/edge/ICoreWebView2Controller.go b/v3/internal/webview2/pkg/edge/ICoreWebView2Controller.go index 08038b0b9fb..1625efb84a4 100644 --- a/v3/internal/webview2/pkg/edge/ICoreWebView2Controller.go +++ b/v3/internal/webview2/pkg/edge/ICoreWebView2Controller.go @@ -150,6 +150,14 @@ func (i *ICoreWebView2Controller) NotifyParentWindowPositionChanged() error { return nil } +func (i *ICoreWebView2Controller) Close() error { + hr, _, _ := i.vtbl.Close.Call(uintptr(unsafe.Pointer(i))) + if windows.Handle(hr) != windows.S_OK { + return windows.Errno(hr) + } + return nil +} + func (i *ICoreWebView2Controller) PutZoomFactor(zoomFactor float64) error { // put_ZoomFactor takes the double BY VALUE; the per-arch appendDoubleArg // helpers pass it correctly for the target ABI. diff --git a/v3/internal/webview2/pkg/edge/ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler.go b/v3/internal/webview2/pkg/edge/ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler.go new file mode 100644 index 00000000000..b9ac1587d1a --- /dev/null +++ b/v3/internal/webview2/pkg/edge/ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler.go @@ -0,0 +1,50 @@ +//go:build windows + +package edge + +type iCoreWebView2CreateCoreWebView2CompositionControllerCompletedHandlerVtbl struct { + _IUnknownVtbl + Invoke ComProc +} + +type iCoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler struct { + vtbl *iCoreWebView2CreateCoreWebView2CompositionControllerCompletedHandlerVtbl + impl iCoreWebView2CreateCoreWebView2CompositionControllerCompletedHandlerImpl +} + +func iCoreWebView2CreateCoreWebView2CompositionControllerCompletedHandlerIUnknownQueryInterface(this *iCoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler, refiid, object uintptr) uintptr { + return this.impl.QueryInterface(refiid, object) +} + +func iCoreWebView2CreateCoreWebView2CompositionControllerCompletedHandlerIUnknownAddRef(this *iCoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler) uintptr { + return this.impl.AddRef() +} + +func iCoreWebView2CreateCoreWebView2CompositionControllerCompletedHandlerIUnknownRelease(this *iCoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler) uintptr { + return this.impl.Release() +} + +func iCoreWebView2CreateCoreWebView2CompositionControllerCompletedHandlerInvoke(this *iCoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler, errorCode uintptr, result *ICoreWebView2CompositionController) uintptr { + return this.impl.CreateCoreWebView2CompositionControllerCompleted(errorCode, result) +} + +type iCoreWebView2CreateCoreWebView2CompositionControllerCompletedHandlerImpl interface { + _IUnknownImpl + CreateCoreWebView2CompositionControllerCompleted(errorCode uintptr, result *ICoreWebView2CompositionController) uintptr +} + +var iCoreWebView2CreateCoreWebView2CompositionControllerCompletedHandlerFn = iCoreWebView2CreateCoreWebView2CompositionControllerCompletedHandlerVtbl{ + _IUnknownVtbl{ + NewComProc(iCoreWebView2CreateCoreWebView2CompositionControllerCompletedHandlerIUnknownQueryInterface), + NewComProc(iCoreWebView2CreateCoreWebView2CompositionControllerCompletedHandlerIUnknownAddRef), + NewComProc(iCoreWebView2CreateCoreWebView2CompositionControllerCompletedHandlerIUnknownRelease), + }, + NewComProc(iCoreWebView2CreateCoreWebView2CompositionControllerCompletedHandlerInvoke), +} + +func newICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler(impl iCoreWebView2CreateCoreWebView2CompositionControllerCompletedHandlerImpl) *iCoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler { + return &iCoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler{ + vtbl: &iCoreWebView2CreateCoreWebView2CompositionControllerCompletedHandlerFn, + impl: impl, + } +} diff --git a/v3/internal/webview2/pkg/edge/ICoreWebView2CursorChangedEventHandler.go b/v3/internal/webview2/pkg/edge/ICoreWebView2CursorChangedEventHandler.go new file mode 100644 index 00000000000..7c816d36639 --- /dev/null +++ b/v3/internal/webview2/pkg/edge/ICoreWebView2CursorChangedEventHandler.go @@ -0,0 +1,50 @@ +//go:build windows + +package edge + +type iCoreWebView2CursorChangedEventHandlerVtbl struct { + _IUnknownVtbl + Invoke ComProc +} + +type iCoreWebView2CursorChangedEventHandler struct { + vtbl *iCoreWebView2CursorChangedEventHandlerVtbl + impl iCoreWebView2CursorChangedEventHandlerImpl +} + +func iCoreWebView2CursorChangedEventHandlerIUnknownQueryInterface(this *iCoreWebView2CursorChangedEventHandler, refiid, object uintptr) uintptr { + return this.impl.QueryInterface(refiid, object) +} + +func iCoreWebView2CursorChangedEventHandlerIUnknownAddRef(this *iCoreWebView2CursorChangedEventHandler) uintptr { + return this.impl.AddRef() +} + +func iCoreWebView2CursorChangedEventHandlerIUnknownRelease(this *iCoreWebView2CursorChangedEventHandler) uintptr { + return this.impl.Release() +} + +func iCoreWebView2CursorChangedEventHandlerInvoke(this *iCoreWebView2CursorChangedEventHandler, sender *ICoreWebView2CompositionController, args *IUnknown) uintptr { + return this.impl.CursorChanged(sender, args) +} + +type iCoreWebView2CursorChangedEventHandlerImpl interface { + _IUnknownImpl + CursorChanged(sender *ICoreWebView2CompositionController, args *IUnknown) uintptr +} + +var iCoreWebView2CursorChangedEventHandlerFn = iCoreWebView2CursorChangedEventHandlerVtbl{ + _IUnknownVtbl{ + NewComProc(iCoreWebView2CursorChangedEventHandlerIUnknownQueryInterface), + NewComProc(iCoreWebView2CursorChangedEventHandlerIUnknownAddRef), + NewComProc(iCoreWebView2CursorChangedEventHandlerIUnknownRelease), + }, + NewComProc(iCoreWebView2CursorChangedEventHandlerInvoke), +} + +func newICoreWebView2CursorChangedEventHandler(impl iCoreWebView2CursorChangedEventHandlerImpl) *iCoreWebView2CursorChangedEventHandler { + return &iCoreWebView2CursorChangedEventHandler{ + vtbl: &iCoreWebView2CursorChangedEventHandlerFn, + impl: impl, + } +} diff --git a/v3/internal/webview2/pkg/edge/ICoreWebView2Environment3.go b/v3/internal/webview2/pkg/edge/ICoreWebView2Environment3.go new file mode 100644 index 00000000000..992278ee4c7 --- /dev/null +++ b/v3/internal/webview2/pkg/edge/ICoreWebView2Environment3.go @@ -0,0 +1,63 @@ +//go:build windows + +package edge + +import ( + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +type iCoreWebView2Environment3Vtbl struct { + _IUnknownVtbl + CreateCoreWebView2Controller ComProc + CreateWebResourceResponse ComProc + GetBrowserVersionString ComProc + AddNewBrowserVersionAvailable ComProc + RemoveNewBrowserVersionAvailable ComProc + CreateWebResourceRequest ComProc + CreateCoreWebView2CompositionController ComProc + CreateCoreWebView2PointerInfo ComProc +} + +type ICoreWebView2Environment3 struct { + vtbl *iCoreWebView2Environment3Vtbl +} + +func (e *ICoreWebView2Environment3) AddRef() uintptr { + ret, _, _ := e.vtbl.AddRef.Call(uintptr(unsafe.Pointer(e))) + + return ret +} + +func (e *ICoreWebView2Environment3) Release() uintptr { + ret, _, _ := e.vtbl.Release.Call(uintptr(unsafe.Pointer(e))) + + return ret +} + +func (e *ICoreWebView2Environment) GetICoreWebView2Environment3() *ICoreWebView2Environment3 { + var result *ICoreWebView2Environment3 + + iidICoreWebView2Environment3 := NewGUID("{80a22ae3-be7c-4ce2-afe1-5a50056cdeeb}") + _, _, _ = e.vtbl.QueryInterface.Call( + uintptr(unsafe.Pointer(e)), + uintptr(unsafe.Pointer(iidICoreWebView2Environment3)), + uintptr(unsafe.Pointer(&result))) + + return result +} + +func (e *ICoreWebView2Environment3) CreateCoreWebView2CompositionController(parentWindow uintptr, handler *iCoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler) error { + hr, _, _ := e.vtbl.CreateCoreWebView2CompositionController.Call( + uintptr(unsafe.Pointer(e)), + parentWindow, + uintptr(unsafe.Pointer(handler)), + ) + if windows.Handle(hr) != windows.S_OK { + return syscall.Errno(hr) + } + + return nil +} diff --git a/v3/internal/webview2/pkg/edge/ICoreWebView2NavigationStartingEventHandler.go b/v3/internal/webview2/pkg/edge/ICoreWebView2NavigationStartingEventHandler.go new file mode 100644 index 00000000000..7cf3c32b9f6 --- /dev/null +++ b/v3/internal/webview2/pkg/edge/ICoreWebView2NavigationStartingEventHandler.go @@ -0,0 +1,58 @@ +//go:build windows + +package edge + +import "unsafe" + +type _ICoreWebView2NavigationStartingEventHandlerVtbl struct { + _IUnknownVtbl + Invoke ComProc +} + +type ICoreWebView2NavigationStartingEventHandler struct { + vtbl *_ICoreWebView2NavigationStartingEventHandlerVtbl + impl _ICoreWebView2NavigationStartingEventHandlerImpl +} + +func (i *ICoreWebView2NavigationStartingEventHandler) AddRef() uintptr { + ret, _, _ := i.vtbl.AddRef.Call(uintptr(unsafe.Pointer(i))) + + return ret +} + +func _ICoreWebView2NavigationStartingEventHandlerIUnknownQueryInterface(this *ICoreWebView2NavigationStartingEventHandler, refiid, object uintptr) uintptr { + return this.impl.QueryInterface(refiid, object) +} + +func _ICoreWebView2NavigationStartingEventHandlerIUnknownAddRef(this *ICoreWebView2NavigationStartingEventHandler) uintptr { + return this.impl.AddRef() +} + +func _ICoreWebView2NavigationStartingEventHandlerIUnknownRelease(this *ICoreWebView2NavigationStartingEventHandler) uintptr { + return this.impl.Release() +} + +func _ICoreWebView2NavigationStartingEventHandlerInvoke(this *ICoreWebView2NavigationStartingEventHandler, sender *ICoreWebView2, args *IUnknown) uintptr { + return this.impl.NavigationStarting(sender, args) +} + +type _ICoreWebView2NavigationStartingEventHandlerImpl interface { + _IUnknownImpl + NavigationStarting(sender *ICoreWebView2, args *IUnknown) uintptr +} + +var _ICoreWebView2NavigationStartingEventHandlerFn = _ICoreWebView2NavigationStartingEventHandlerVtbl{ + _IUnknownVtbl{ + NewComProc(_ICoreWebView2NavigationStartingEventHandlerIUnknownQueryInterface), + NewComProc(_ICoreWebView2NavigationStartingEventHandlerIUnknownAddRef), + NewComProc(_ICoreWebView2NavigationStartingEventHandlerIUnknownRelease), + }, + NewComProc(_ICoreWebView2NavigationStartingEventHandlerInvoke), +} + +func newICoreWebView2NavigationStartingEventHandler(impl _ICoreWebView2NavigationStartingEventHandlerImpl) *ICoreWebView2NavigationStartingEventHandler { + return &ICoreWebView2NavigationStartingEventHandler{ + vtbl: &_ICoreWebView2NavigationStartingEventHandlerFn, + impl: impl, + } +} diff --git a/v3/internal/webview2/pkg/edge/ICoreWebView2Settings9.go b/v3/internal/webview2/pkg/edge/ICoreWebView2Settings9.go new file mode 100644 index 00000000000..e80ba2e0950 --- /dev/null +++ b/v3/internal/webview2/pkg/edge/ICoreWebView2Settings9.go @@ -0,0 +1,95 @@ +//go:build windows + +package edge + +import ( + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +type ICoreWebView2Settings9Vtbl struct { + _IUnknownVtbl + GetIsScriptEnabled ComProc + PutIsScriptEnabled ComProc + GetIsWebMessageEnabled ComProc + PutIsWebMessageEnabled ComProc + GetAreDefaultScriptDialogsEnabled ComProc + PutAreDefaultScriptDialogsEnabled ComProc + GetIsStatusBarEnabled ComProc + PutIsStatusBarEnabled ComProc + GetAreDevToolsEnabled ComProc + PutAreDevToolsEnabled ComProc + GetAreDefaultContextMenusEnabled ComProc + PutAreDefaultContextMenusEnabled ComProc + GetAreHostObjectsAllowed ComProc + PutAreHostObjectsAllowed ComProc + GetIsZoomControlEnabled ComProc + PutIsZoomControlEnabled ComProc + GetIsBuiltInErrorPageEnabled ComProc + PutIsBuiltInErrorPageEnabled ComProc + GetUserAgent ComProc + PutUserAgent ComProc + GetAreBrowserAcceleratorKeysEnabled ComProc + PutAreBrowserAcceleratorKeysEnabled ComProc + GetIsPasswordAutosaveEnabled ComProc + PutIsPasswordAutosaveEnabled ComProc + GetIsGeneralAutofillEnabled ComProc + PutIsGeneralAutofillEnabled ComProc + GetIsPinchZoomEnabled ComProc + PutIsPinchZoomEnabled ComProc + GetIsSwipeNavigationEnabled ComProc + PutIsSwipeNavigationEnabled ComProc + GetHiddenPdfToolbarItems ComProc + PutHiddenPdfToolbarItems ComProc + GetIsReputationCheckingRequired ComProc + PutIsReputationCheckingRequired ComProc + GetIsNonClientRegionSupportEnabled ComProc + PutIsNonClientRegionSupportEnabled ComProc +} + +type ICoreWebView2Settings9 struct { + Vtbl *ICoreWebView2Settings9Vtbl +} + +func (i *ICoreWebView2Settings9) AddRef() uintptr { + refCounter, _, _ := i.Vtbl.AddRef.Call(uintptr(unsafe.Pointer(i))) + return refCounter +} + +func (i *ICoreWebViewSettings) GetICoreWebView2Settings9() *ICoreWebView2Settings9 { + var result *ICoreWebView2Settings9 + + iidICoreWebView2Settings9 := NewGUID("{0528a73b-e92d-49f4-927a-e547dddaa37d}") + _, _, _ = i.vtbl.QueryInterface.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(iidICoreWebView2Settings9)), + uintptr(unsafe.Pointer(&result))) + + return result +} + +func (i *ICoreWebView2Settings9) GetIsNonClientRegionSupportEnabled() (bool, error) { + var value int32 + + hr, _, _ := i.Vtbl.GetIsNonClientRegionSupportEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&value)), + ) + if windows.Handle(hr) != windows.S_OK { + return false, syscall.Errno(hr) + } + return value != 0, nil +} + +func (i *ICoreWebView2Settings9) PutIsNonClientRegionSupportEnabled(value bool) error { + hr, _, _ := i.Vtbl.PutIsNonClientRegionSupportEnabled.Call( + uintptr(unsafe.Pointer(i)), + uintptr(boolToInt(value)), + ) + if windows.Handle(hr) != windows.S_OK { + return syscall.Errno(hr) + } + return nil +} diff --git a/v3/internal/webview2/pkg/edge/IDCompositionDevice.go b/v3/internal/webview2/pkg/edge/IDCompositionDevice.go new file mode 100644 index 00000000000..f6910df3098 --- /dev/null +++ b/v3/internal/webview2/pkg/edge/IDCompositionDevice.go @@ -0,0 +1,86 @@ +//go:build windows + +package edge + +import ( + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +var procDCompositionCreateDevice2 = windows.NewLazySystemDLL("dcomp.dll").NewProc("DCompositionCreateDevice2") + +type iDCompositionDeviceVtbl struct { + _IUnknownVtbl + Commit ComProc + WaitForCommitCompletion ComProc + GetFrameStatistics ComProc + CreateTargetForHwnd ComProc + CreateVisual ComProc +} + +type iDCompositionDevice struct { + vtbl *iDCompositionDeviceVtbl +} + +func (d *iDCompositionDevice) AddRef() uintptr { + ret, _, _ := d.vtbl.AddRef.Call(uintptr(unsafe.Pointer(d))) + + return ret +} + +func (d *iDCompositionDevice) Release() uintptr { + ret, _, _ := d.vtbl.Release.Call(uintptr(unsafe.Pointer(d))) + + return ret +} + +func dCompositionCreateDevice2() (*iDCompositionDevice, error) { + var device *iDCompositionDevice + iidIDCompositionDevice := NewGUID("{C37EA93A-E7AA-450D-B16F-9746CB0407F3}") + + hr, _, _ := procDCompositionCreateDevice2.Call( + 0, + uintptr(unsafe.Pointer(iidIDCompositionDevice)), + uintptr(unsafe.Pointer(&device)), + ) + if windows.Handle(hr) != windows.S_OK { + return nil, syscall.Errno(hr) + } + return device, nil +} + +func (d *iDCompositionDevice) CreateTargetForHwnd(hwnd uintptr, topmost bool) (*iDCompositionTarget, error) { + var target *iDCompositionTarget + hr, _, _ := d.vtbl.CreateTargetForHwnd.Call( + uintptr(unsafe.Pointer(d)), + hwnd, + uintptr(boolToInt(topmost)), + uintptr(unsafe.Pointer(&target)), + ) + if windows.Handle(hr) != windows.S_OK { + return nil, syscall.Errno(hr) + } + return target, nil +} + +func (d *iDCompositionDevice) CreateVisual() (*iDCompositionVisual, error) { + var visual *iDCompositionVisual + hr, _, _ := d.vtbl.CreateVisual.Call( + uintptr(unsafe.Pointer(d)), + uintptr(unsafe.Pointer(&visual)), + ) + if windows.Handle(hr) != windows.S_OK { + return nil, syscall.Errno(hr) + } + return visual, nil +} + +func (d *iDCompositionDevice) Commit() error { + hr, _, _ := d.vtbl.Commit.Call(uintptr(unsafe.Pointer(d))) + if windows.Handle(hr) != windows.S_OK { + return syscall.Errno(hr) + } + return nil +} diff --git a/v3/internal/webview2/pkg/edge/IDCompositionTarget.go b/v3/internal/webview2/pkg/edge/IDCompositionTarget.go new file mode 100644 index 00000000000..b5b1c131408 --- /dev/null +++ b/v3/internal/webview2/pkg/edge/IDCompositionTarget.go @@ -0,0 +1,42 @@ +//go:build windows + +package edge + +import ( + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +type iDCompositionTargetVtbl struct { + _IUnknownVtbl + SetRoot ComProc +} + +type iDCompositionTarget struct { + vtbl *iDCompositionTargetVtbl +} + +func (t *iDCompositionTarget) AddRef() uintptr { + ret, _, _ := t.vtbl.AddRef.Call(uintptr(unsafe.Pointer(t))) + + return ret +} + +func (t *iDCompositionTarget) Release() uintptr { + ret, _, _ := t.vtbl.Release.Call(uintptr(unsafe.Pointer(t))) + + return ret +} + +func (t *iDCompositionTarget) SetRoot(visual *iDCompositionVisual) error { + hr, _, _ := t.vtbl.SetRoot.Call( + uintptr(unsafe.Pointer(t)), + uintptr(unsafe.Pointer(visual)), + ) + if windows.Handle(hr) != windows.S_OK { + return syscall.Errno(hr) + } + return nil +} diff --git a/v3/internal/webview2/pkg/edge/IDCompositionVisual.go b/v3/internal/webview2/pkg/edge/IDCompositionVisual.go new file mode 100644 index 00000000000..9e7444ab18d --- /dev/null +++ b/v3/internal/webview2/pkg/edge/IDCompositionVisual.go @@ -0,0 +1,25 @@ +//go:build windows + +package edge + +import "unsafe" + +type iDCompositionVisualVtbl struct { + _IUnknownVtbl +} + +type iDCompositionVisual struct { + vtbl *iDCompositionVisualVtbl +} + +func (v *iDCompositionVisual) AddRef() uintptr { + ret, _, _ := v.vtbl.AddRef.Call(uintptr(unsafe.Pointer(v))) + + return ret +} + +func (v *iDCompositionVisual) Release() uintptr { + ret, _, _ := v.vtbl.Release.Call(uintptr(unsafe.Pointer(v))) + + return ret +} diff --git a/v3/internal/webview2/pkg/edge/chromium.go b/v3/internal/webview2/pkg/edge/chromium.go index 2440d3e417a..7b3d39b02b7 100644 --- a/v3/internal/webview2/pkg/edge/chromium.go +++ b/v3/internal/webview2/pkg/edge/chromium.go @@ -56,26 +56,34 @@ type Chromium struct { } controller *ICoreWebView2Controller + compositionController *ICoreWebView2CompositionController + compositionController4 *ICoreWebView2CompositionController4 webview *ICoreWebView2 inited uintptr envCompleted *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler controllerCompleted *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler + compositionControllerCompleted *iCoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler webMessageReceived *iCoreWebView2WebMessageReceivedEventHandler containsFullScreenElementChanged *ICoreWebView2ContainsFullScreenElementChangedEventHandler permissionRequested *iCoreWebView2PermissionRequestedEventHandler webResourceRequested *iCoreWebView2WebResourceRequestedEventHandler acceleratorKeyPressed *ICoreWebView2AcceleratorKeyPressedEventHandler + cursorChanged *iCoreWebView2CursorChangedEventHandler + navigationStarting *ICoreWebView2NavigationStartingEventHandler navigationCompleted *ICoreWebView2NavigationCompletedEventHandler processFailed *ICoreWebView2ProcessFailedEventHandler environment *ICoreWebView2Environment webview2RuntimeVersion string + compositionHost *compositionHost // Settings - Debug bool - DataPath string - BrowserPath string - AdditionalBrowserArgs []string + Debug bool + DataPath string + BrowserPath string + AdditionalBrowserArgs []string + NonClientRegionSupportEnabled bool + CompositionControllerEnabled bool // permissions permissions map[CoreWebView2PermissionKind]CoreWebView2PermissionState @@ -85,10 +93,12 @@ type Chromium struct { MessageCallback func(message string, sender *ICoreWebView2, args *ICoreWebView2WebMessageReceivedEventArgs) MessageWithAdditionalObjectsCallback func(message string, sender *ICoreWebView2, args *ICoreWebView2WebMessageReceivedEventArgs) WebResourceRequestedCallback func(request *ICoreWebView2WebResourceRequest, args *ICoreWebView2WebResourceRequestedEventArgs) + NavigationStartingCallback func(sender *ICoreWebView2) NavigationCompletedCallback func(sender *ICoreWebView2, args *ICoreWebView2NavigationCompletedEventArgs) ProcessFailedCallback func(sender *ICoreWebView2, args *ICoreWebView2ProcessFailedEventArgs) ContainsFullScreenElementChangedCallback func(sender *ICoreWebView2, args *ICoreWebView2ContainsFullScreenElementChangedEventArgs) AcceleratorKeyCallback func(uint) bool + CursorChangedCallback func(cursor HCURSOR, systemCursorID uint32) // Error handling globalErrorCallback func(error) @@ -115,10 +125,13 @@ func NewChromium() *Chromium { */ e.envCompleted = newICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler(e) e.controllerCompleted = newICoreWebView2CreateCoreWebView2ControllerCompletedHandler(e) + e.compositionControllerCompleted = newICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler(e) e.webMessageReceived = newICoreWebView2WebMessageReceivedEventHandler(e) e.permissionRequested = newICoreWebView2PermissionRequestedEventHandler(e) e.webResourceRequested = newICoreWebView2WebResourceRequestedEventHandler(e) e.acceleratorKeyPressed = newICoreWebView2AcceleratorKeyPressedEventHandler(e) + e.cursorChanged = newICoreWebView2CursorChangedEventHandler(e) + e.navigationStarting = newICoreWebView2NavigationStartingEventHandler(e) e.navigationCompleted = newICoreWebView2NavigationCompletedEventHandler(e) e.processFailed = newICoreWebView2ProcessFailedEventHandler(e) e.containsFullScreenElementChanged = newICoreWebView2ContainsFullScreenElementChangedEventHandler(e) @@ -158,6 +171,12 @@ func (e *Chromium) SetErrorCallback(callback func(error)) { } } +func (e *Chromium) SetCursorChangedCallback(callback func(cursor HCURSOR, systemCursorID uint32)) { + if callback != nil { + e.CursorChangedCallback = callback + } +} + func (e *Chromium) Embed(hwnd uintptr) bool { var err error @@ -328,10 +347,18 @@ func (e *Chromium) EnvironmentCompleted(res uintptr, env *ICoreWebView2Environme log.Printf("[WebView2] Environment created successfully\n") - env.vtbl.AddRef.Call(uintptr(unsafe.Pointer(env))) + env.AddRef() e.environment = env - err := env.CreateCoreWebView2Controller(e.hwnd, e.controllerCompleted) + var err error + if !e.CompositionControllerEnabled { + err = env.CreateCoreWebView2Controller(e.hwnd, e.controllerCompleted) + } else { + err = e.createCoreWebView2CompositionController(env) + if err != nil { + err = e.fallbackToCoreWebView2Controller(fmt.Errorf("composition controller setup failed: %w", err)) + } + } if err != nil { e.errorCallback(err) } @@ -343,29 +370,130 @@ func (e *Chromium) CreateCoreWebView2ControllerCompleted(res uintptr, controller e.errorCallback(fmt.Errorf("error creating controller with %08x: %s", res, syscall.Errno(res))) } + return e.initializeController(controller) +} + +func (e *Chromium) createCoreWebView2CompositionController(env *ICoreWebView2Environment) error { + env3 := env.GetICoreWebView2Environment3() + if env3 == nil { + return UnsupportedCapabilityError + } + defer env3.Release() + + host, err := newCompositionHost(e.hwnd) + if err != nil { + return err + } + e.compositionHost = host + + return env3.CreateCoreWebView2CompositionController(e.hwnd, e.compositionControllerCompleted) +} + +func (e *Chromium) CreateCoreWebView2CompositionControllerCompleted(res uintptr, compositionController *ICoreWebView2CompositionController) uintptr { + if int32(res) < 0 { + if err := e.fallbackToCoreWebView2Controller(fmt.Errorf("error creating composition controller with %08x: %s", res, syscall.Errno(res))); err != nil { + e.errorCallback(err) + } + return 0 + } + + if compositionController == nil { + if err := e.fallbackToCoreWebView2Controller(fmt.Errorf("composition controller completed without a controller")); err != nil { + e.errorCallback(err) + } + return 0 + } + + compositionController.AddRef() + e.compositionController = compositionController + e.compositionController4 = compositionController.GetICoreWebView2CompositionController4() + + if err := e.compositionHost.attachController(e.compositionController); err != nil { + if fallbackErr := e.fallbackToCoreWebView2Controller(fmt.Errorf("attaching composition controller failed: %w", err)); fallbackErr != nil { + e.errorCallback(fallbackErr) + } + return 0 + } + + controller := compositionController.GetICoreWebView2Controller() + if controller == nil { + if err := e.fallbackToCoreWebView2Controller(fmt.Errorf("error getting controller from composition controller")); err != nil { + e.errorCallback(err) + } + return 0 + } + + return e.initializeController(controller) +} + +func (e *Chromium) fallbackToCoreWebView2Controller(reason error) error { + log.Printf("[WebView2] Composition hosting unavailable, falling back to HWND controller: %v\n", reason) + + e.releaseCompositionController() + e.releaseCompositionHost() + e.CompositionControllerEnabled = false + + if e.environment == nil { + return fmt.Errorf("cannot fall back to WebView2 HWND controller without an environment: %w", reason) + } + if err := e.environment.CreateCoreWebView2Controller(e.hwnd, e.controllerCompleted); err != nil { + return fmt.Errorf("composition hosting failed (%v), and HWND controller fallback failed: %w", reason, err) + } + return nil +} + +func (e *Chromium) releaseCompositionController() { + if e.compositionController4 != nil { + e.compositionController4.Release() + e.compositionController4 = nil + } + if e.compositionController != nil { + if controller := e.compositionController.GetICoreWebView2Controller(); controller != nil { + _ = controller.Close() + controller.Release() + } + e.compositionController.Release() + e.compositionController = nil + } +} + +func (e *Chromium) releaseCompositionHost() { + if e.compositionHost != nil { + e.compositionHost.release() + e.compositionHost = nil + } +} + +func (e *Chromium) initializeController(controller *ICoreWebView2Controller) uintptr { var err error - controller.vtbl.AddRef.Call(uintptr(unsafe.Pointer(controller))) + controller.AddRef() e.controller = controller - // Try to get ICoreWebView2Controller3 interface for better performance + // Try to get ICoreWebView2Controller3 interface for better performance. + // Keep composition-hosted WebViews on WebView2-managed scale detection: + // the DirectComposition surface is owned by WebView2, and manually + // reasserting RasterizationScale during monitor transitions can leave that + // surface black after DPI increases. if controller3 := e.controller.GetICoreWebView2Controller3(); controller3 != nil { - // Use raw pixels mode for better performance during resize - if err := controller3.PutBoundsMode(COREWEBVIEW2_BOUNDS_MODE_USE_RAW_PIXELS); err != nil { - e.errorCallback(err) - } + if !e.CompositionControllerEnabled { + // Use raw pixels mode for better performance during resize. + if err := controller3.PutBoundsMode(COREWEBVIEW2_BOUNDS_MODE_USE_RAW_PIXELS); err != nil { + e.errorCallback(err) + } - // ShouldDetectMonitorScaleChanges is deliberately left at its default - // (enabled): WebView2 tracks monitor DPI changes and updates its own - // rasterization scale. This module previously disabled it and left the - // scale to the host's WM_DPICHANGED handling, but an externally - // written scale races the browser process's internal display - // bookkeeping during a mixed-DPI monitor cross — the browser can land - // on a degenerate scale(0,0) compositor transform, which kills the - // GPU process on every frame until the browser process itself exits - // (wailsapp/wails#5732). Detection stays on so the scale has exactly - // one writer, on the code path every mainstream embedder exercises; - // bounds remain raw pixels, which is orthogonal. + // ShouldDetectMonitorScaleChanges is deliberately left at its default + // (enabled): WebView2 tracks monitor DPI changes and updates its own + // rasterization scale. This module previously disabled it and left the + // scale to the host's WM_DPICHANGED handling, but an externally + // written scale races the browser process's internal display + // bookkeeping during a mixed-DPI monitor cross — the browser can land + // on a degenerate scale(0,0) compositor transform, which kills the + // GPU process on every frame until the browser process itself exits + // (wailsapp/wails#5732). Detection stays on so the scale has exactly + // one writer, on the code path every mainstream embedder exercises; + // bounds remain raw pixels, which is orthogonal. + } } var token _EventRegistrationToken e.webview, err = e.controller.GetCoreWebView2() @@ -373,7 +501,14 @@ func (e *Chromium) CreateCoreWebView2ControllerCompleted(res uintptr, controller e.errorCallback(err) } - e.webview.vtbl.AddRef.Call(uintptr(unsafe.Pointer(e.webview))) + e.webview.AddRef() + if e.NonClientRegionSupportEnabled { + if err := e.PutIsNonClientRegionSupportEnabled(true); err != nil { + if !errors.Is(err, UnsupportedCapabilityError) { + e.errorCallback(err) + } + } + } err = e.webview.AddWebMessageReceived(e.webMessageReceived, &token) if err != nil { e.errorCallback(err) @@ -386,6 +521,10 @@ func (e *Chromium) CreateCoreWebView2ControllerCompleted(res uintptr, controller if err != nil { e.errorCallback(err) } + err = e.webview.AddNavigationStarting(e.navigationStarting, &token) + if err != nil { + e.errorCallback(err) + } err = e.webview.AddNavigationCompleted(e.navigationCompleted, &token) if err != nil { e.errorCallback(err) @@ -398,11 +537,16 @@ func (e *Chromium) CreateCoreWebView2ControllerCompleted(res uintptr, controller if err != nil { e.errorCallback(err) } - err = e.controller.AddAcceleratorKeyPressed(e.acceleratorKeyPressed, &token) if err != nil { e.errorCallback(err) } + if e.compositionController != nil { + err = e.compositionController.AddCursorChanged(e.cursorChanged, &token) + if err != nil { + e.errorCallback(err) + } + } atomic.StoreUintptr(&e.inited, 1) @@ -416,6 +560,27 @@ func (e *Chromium) ContainsFullScreenElementChanged(sender *ICoreWebView2, args return 0 } +func (e *Chromium) CursorChanged(sender *ICoreWebView2CompositionController, _ *IUnknown) uintptr { + if e.CursorChangedCallback == nil { + return 0 + } + + cursor, err := sender.GetCursor() + if err != nil { + e.errorCallback(err) + return 0 + } + + systemCursorID, err := sender.GetSystemCursorId() + if err != nil { + e.errorCallback(err) + return 0 + } + + e.CursorChangedCallback(cursor, systemCursorID) + return 0 +} + func (e *Chromium) MessageReceived(sender *ICoreWebView2, args *ICoreWebView2WebMessageReceivedEventArgs) uintptr { message, err := args.TryGetWebMessageAsString() if err != nil { @@ -581,6 +746,13 @@ func boolToInt(input bool) int { return 0 } +func (e *Chromium) NavigationStarting(sender *ICoreWebView2, _ *IUnknown) uintptr { + if e.NavigationStartingCallback != nil { + e.NavigationStartingCallback(sender) + } + return 0 +} + func (e *Chromium) NavigationCompleted(sender *ICoreWebView2, args *ICoreWebView2NavigationCompletedEventArgs) uintptr { if e.NavigationCompletedCallback != nil { e.NavigationCompletedCallback(sender, args) @@ -595,6 +767,19 @@ func (e *Chromium) ProcessFailed(sender *ICoreWebView2, args *ICoreWebView2Proce return 0 } +func (e *Chromium) Bounds() *Rect { + if e == nil || e.controller == nil { + return nil + } + + rect, err := e.controller.GetBounds() + if err != nil { + e.errorCallback(err) + return nil + } + return rect +} + func (e *Chromium) NotifyParentWindowPositionChanged() error { //It looks like the wndproc function is called before the controller initialization is complete. //Because of this the controller is nil @@ -643,6 +828,16 @@ func (e *Chromium) HasCapability(c Capability) bool { return HasCapability(e.webview2RuntimeVersion, c) } +func (e *Chromium) CompositionControllerReady() bool { + return e != nil && e.compositionController != nil +} + +func (e *Chromium) NonClientRegionHitTestReady() bool { + return e != nil && + e.compositionController4 != nil && + HasCapability(e.webview2RuntimeVersion, NonClientRegion) +} + func (e *Chromium) GetIsSwipeNavigationEnabled() (bool, error) { if !HasCapability(e.webview2RuntimeVersion, SwipeNavigation) { return false, UnsupportedCapabilityError @@ -711,6 +906,46 @@ func (e *Chromium) PutIsSwipeNavigationEnabled(enabled bool) error { return nil } +func (e *Chromium) PutIsNonClientRegionSupportEnabled(enabled bool) error { + if !HasCapability(e.webview2RuntimeVersion, NonClientRegion) { + return UnsupportedCapabilityError + } + webview2Settings, err := e.webview.GetSettings() + if err != nil { + return err + } + webview2Settings9 := webview2Settings.GetICoreWebView2Settings9() + if webview2Settings9 == nil { + return UnsupportedCapabilityError + } + return webview2Settings9.PutIsNonClientRegionSupportEnabled(enabled) +} + +func (e *Chromium) GetNonClientRegionAtPoint(x, y int32) (COREWEBVIEW2_NON_CLIENT_REGION_KIND, bool, error) { + if !e.NonClientRegionHitTestReady() { + return COREWEBVIEW2_NON_CLIENT_REGION_KIND_NOWHERE, false, nil + } + + region, err := e.compositionController4.GetNonClientRegionAtPoint(POINT{X: x, Y: y}) + if err != nil { + return COREWEBVIEW2_NON_CLIENT_REGION_KIND_NOWHERE, false, err + } + return region, true, nil +} + +func (e *Chromium) SendMouseInput( + eventKind COREWEBVIEW2_MOUSE_EVENT_KIND, + virtualKeys COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS, + mouseData uint32, + x, y int, +) error { + if !e.CompositionControllerReady() { + return errors.New("webview2 composition controller is not initialized") + } + + return e.compositionController.SendMouseInput(eventKind, virtualKeys, mouseData, POINT{X: int32(x), Y: int32(y)}) +} + func (e *Chromium) AllowExternalDrag(allow bool) error { if !HasCapability(e.webview2RuntimeVersion, AllowExternalDrop) { return UnsupportedCapabilityError diff --git a/v3/internal/webview2/pkg/edge/com.go b/v3/internal/webview2/pkg/edge/com.go index 72cb64d9d12..43b1807f9ba 100644 --- a/v3/internal/webview2/pkg/edge/com.go +++ b/v3/internal/webview2/pkg/edge/com.go @@ -39,6 +39,11 @@ type IUnknownImpl interface { type POINT struct { X, Y int32 } + +func (p POINT) uintptr() uintptr { + return uintptr(uint32(p.X)) | uintptr(uint64(uint32(p.Y))<<32) +} + type RECT struct { Left int32 Top int32 diff --git a/v3/internal/webview2/pkg/edge/composition_host.go b/v3/internal/webview2/pkg/edge/composition_host.go new file mode 100644 index 00000000000..7d91d96e37d --- /dev/null +++ b/v3/internal/webview2/pkg/edge/composition_host.go @@ -0,0 +1,68 @@ +//go:build windows + +package edge + +import ( + "errors" + "unsafe" +) + +type compositionHost struct { + device *iDCompositionDevice + target *iDCompositionTarget + visual *iDCompositionVisual +} + +func newCompositionHost(hwnd uintptr) (*compositionHost, error) { + device, err := dCompositionCreateDevice2() + if err != nil { + return nil, err + } + target, err := device.CreateTargetForHwnd(hwnd, true) + if err != nil { + device.Release() + return nil, err + } + visual, err := device.CreateVisual() + if err != nil { + target.Release() + device.Release() + return nil, err + } + return &compositionHost{ + device: device, + target: target, + visual: visual, + }, nil +} + +func (h *compositionHost) attachController(controller *ICoreWebView2CompositionController) error { + if h == nil || h.device == nil || h.target == nil || h.visual == nil || controller == nil { + return errors.New("direct composition host is not initialized") + } + if err := controller.PutRootVisualTarget((*IUnknown)(unsafe.Pointer(h.visual))); err != nil { + return err + } + if err := h.target.SetRoot(h.visual); err != nil { + return err + } + return h.device.Commit() +} + +func (h *compositionHost) release() { + if h == nil { + return + } + if h.visual != nil { + h.visual.Release() + h.visual = nil + } + if h.target != nil { + h.target.Release() + h.target = nil + } + if h.device != nil { + h.device.Release() + h.device = nil + } +} diff --git a/v3/internal/webview2/pkg/edge/corewebview2.go b/v3/internal/webview2/pkg/edge/corewebview2.go index d99d2825954..4c0cf013c55 100644 --- a/v3/internal/webview2/pkg/edge/corewebview2.go +++ b/v3/internal/webview2/pkg/edge/corewebview2.go @@ -209,6 +209,19 @@ func (i *ICoreWebView2) AddContainsFullScreenElementChanged(eventHandler *ICoreW return nil } +func (i *ICoreWebView2) AddNavigationStarting(eventHandler *ICoreWebView2NavigationStartingEventHandler, token *_EventRegistrationToken) error { + hr, _, _ := i.vtbl.AddNavigationStarting.Call( + uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(eventHandler)), + uintptr(unsafe.Pointer(token)), + ) + if windows.Handle(hr) != windows.S_OK { + return windows.Errno(hr) + } + + return nil +} + func (i *ICoreWebView2) AddNavigationCompleted(eventHandler *ICoreWebView2NavigationCompletedEventHandler, token *_EventRegistrationToken) error { hr, _, _ := i.vtbl.AddNavigationCompleted.Call( uintptr(unsafe.Pointer(i)), @@ -434,6 +447,18 @@ type ICoreWebView2Environment struct { vtbl *iCoreWebView2EnvironmentVtbl } +func (e *ICoreWebView2Environment) AddRef() uintptr { + ret, _, _ := e.vtbl.AddRef.Call(uintptr(unsafe.Pointer(e))) + + return ret +} + +func (e *ICoreWebView2Environment) Release() uintptr { + ret, _, _ := e.vtbl.Release.Call(uintptr(unsafe.Pointer(e))) + + return ret +} + // CreateCoreWebView2Controller asynchronously creates a new WebView. func (e *ICoreWebView2Environment) CreateCoreWebView2Controller(parentWindow uintptr, handler *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler) error { hr, _, _ := e.vtbl.CreateCoreWebView2Controller.Call( diff --git a/v3/pkg/application/application_server.go b/v3/pkg/application/application_server.go index c7ed9696ac2..353f2cabe94 100644 --- a/v3/pkg/application/application_server.go +++ b/v3/pkg/application/application_server.go @@ -533,37 +533,38 @@ func (w *serverWebviewWindow) startDrag() error { func (w *serverWebviewWindow) startResize(border string) error { return errors.New("resize not available in server mode") } -func (w *serverWebviewWindow) print() error { return errors.New("print not available in server mode") } -func (w *serverWebviewWindow) setEnabled(enabled bool) {} -func (w *serverWebviewWindow) physicalBounds() Rect { return Rect{} } -func (w *serverWebviewWindow) setPhysicalBounds(bounds Rect) {} -func (w *serverWebviewWindow) bounds() Rect { return Rect{} } -func (w *serverWebviewWindow) setBounds(bounds Rect) {} -func (w *serverWebviewWindow) position() (int, int) { return 0, 0 } -func (w *serverWebviewWindow) setPosition(x int, y int) {} -func (w *serverWebviewWindow) centerOnScreen(_ *Screen) {} -func (w *serverWebviewWindow) relativePosition() (int, int) { return 0, 0 } -func (w *serverWebviewWindow) setRelativePosition(x int, y int) {} -func (w *serverWebviewWindow) flash(enabled bool) {} -func (w *serverWebviewWindow) handleKeyEvent(acceleratorString string) {} -func (w *serverWebviewWindow) getBorderSizes() *LRTB { return &LRTB{} } -func (w *serverWebviewWindow) setMinimiseButtonState(state ButtonState) {} -func (w *serverWebviewWindow) setMaximiseButtonState(state ButtonState) {} -func (w *serverWebviewWindow) setCloseButtonState(state ButtonState) {} -func (w *serverWebviewWindow) setFullscreenButtonState(state ButtonState) {} -func (w *serverWebviewWindow) isIgnoreMouseEvents() bool { return false } -func (w *serverWebviewWindow) setIgnoreMouseEvents(ignore bool) {} -func (w *serverWebviewWindow) cut() {} -func (w *serverWebviewWindow) copy() {} -func (w *serverWebviewWindow) paste() {} -func (w *serverWebviewWindow) undo() {} -func (w *serverWebviewWindow) delete() {} -func (w *serverWebviewWindow) selectAll() {} -func (w *serverWebviewWindow) redo() {} -func (w *serverWebviewWindow) showMenuBar() {} -func (w *serverWebviewWindow) hideMenuBar() {} -func (w *serverWebviewWindow) toggleMenuBar() {} -func (w *serverWebviewWindow) setMenu(menu *Menu) {} -func (w *serverWebviewWindow) snapAssist() {} -func (w *serverWebviewWindow) attachModal(modalWindow *WebviewWindow) {} -func (w *serverWebviewWindow) setContentProtection(enabled bool) {} +func (w *serverWebviewWindow) print() error { return errors.New("print not available in server mode") } +func (w *serverWebviewWindow) setEnabled(enabled bool) {} +func (w *serverWebviewWindow) physicalBounds() Rect { return Rect{} } +func (w *serverWebviewWindow) setPhysicalBounds(bounds Rect) {} +func (w *serverWebviewWindow) bounds() Rect { return Rect{} } +func (w *serverWebviewWindow) setBounds(bounds Rect) {} +func (w *serverWebviewWindow) position() (int, int) { return 0, 0 } +func (w *serverWebviewWindow) setPosition(x int, y int) {} +func (w *serverWebviewWindow) centerOnScreen(_ *Screen) {} +func (w *serverWebviewWindow) relativePosition() (int, int) { return 0, 0 } +func (w *serverWebviewWindow) setRelativePosition(x int, y int) {} +func (w *serverWebviewWindow) flash(enabled bool) {} +func (w *serverWebviewWindow) handleKeyEvent(acceleratorString string) {} +func (w *serverWebviewWindow) getBorderSizes() *LRTB { return &LRTB{} } +func (w *serverWebviewWindow) setMinimiseButtonState(state ButtonState) {} +func (w *serverWebviewWindow) setMaximiseButtonState(state ButtonState) {} +func (w *serverWebviewWindow) setCloseButtonState(state ButtonState) {} +func (w *serverWebviewWindow) setFullscreenButtonState(state ButtonState) {} +func (w *serverWebviewWindow) isIgnoreMouseEvents() bool { return false } +func (w *serverWebviewWindow) setIgnoreMouseEvents(ignore bool) {} +func (w *serverWebviewWindow) cut() {} +func (w *serverWebviewWindow) copy() {} +func (w *serverWebviewWindow) paste() {} +func (w *serverWebviewWindow) undo() {} +func (w *serverWebviewWindow) delete() {} +func (w *serverWebviewWindow) selectAll() {} +func (w *serverWebviewWindow) redo() {} +func (w *serverWebviewWindow) showMenuBar() {} +func (w *serverWebviewWindow) hideMenuBar() {} +func (w *serverWebviewWindow) toggleMenuBar() {} +func (w *serverWebviewWindow) setMenu(menu *Menu) {} +func (w *serverWebviewWindow) snapAssist() {} +func (w *serverWebviewWindow) attachModal(modalWindow *WebviewWindow) {} +func (w *serverWebviewWindow) setContentProtection(enabled bool) {} +func (w *serverWebviewWindow) setNonClientHitTestRegions([]nonClientHitTestRegion) {} diff --git a/v3/pkg/application/clipboard_windows.go b/v3/pkg/application/clipboard_windows.go index 507eac3da3e..e8c76bda423 100644 --- a/v3/pkg/application/clipboard_windows.go +++ b/v3/pkg/application/clipboard_windows.go @@ -1,4 +1,4 @@ -//go:build windows +//go:build windows && !server package application diff --git a/v3/pkg/application/dialogs_windows.go b/v3/pkg/application/dialogs_windows.go index 789c6278ffd..1185117e1f4 100644 --- a/v3/pkg/application/dialogs_windows.go +++ b/v3/pkg/application/dialogs_windows.go @@ -1,4 +1,4 @@ -//go:build windows +//go:build windows && !server package application diff --git a/v3/pkg/application/events_common_windows.go b/v3/pkg/application/events_common_windows.go index f0bcd4d84e8..66db1ba3df4 100644 --- a/v3/pkg/application/events_common_windows.go +++ b/v3/pkg/application/events_common_windows.go @@ -1,4 +1,4 @@ -//go:build windows +//go:build windows && !server package application diff --git a/v3/pkg/application/icon_windows.go b/v3/pkg/application/icon_windows.go new file mode 100644 index 00000000000..e6f17dda2fa --- /dev/null +++ b/v3/pkg/application/icon_windows.go @@ -0,0 +1,22 @@ +//go:build windows + +package application + +import ( + "fmt" + + "github.com/wailsapp/wails/v3/pkg/w32" +) + +// NewIconFromResource loads an icon from an embedded Windows resource. It is +// available in both desktop and server builds so that services which only need +// the icon helper (e.g. notifications) compile under the `server` tag, matching +// the behaviour on macOS and Linux. +func NewIconFromResource(instance w32.HINSTANCE, resId uint16) (w32.HICON, error) { + var err error + var result w32.HICON + if result = w32.LoadIconWithResourceID(instance, resId); result == 0 { + err = fmt.Errorf("cannot load icon from resource with id %v", resId) + } + return result, err +} diff --git a/v3/pkg/application/keys_windows.go b/v3/pkg/application/keys_windows.go index 8011a837dfd..a299e432483 100644 --- a/v3/pkg/application/keys_windows.go +++ b/v3/pkg/application/keys_windows.go @@ -1,4 +1,4 @@ -//go:build windows +//go:build windows && !server package application diff --git a/v3/pkg/application/mainthread_windows.go b/v3/pkg/application/mainthread_windows.go index ddee96339f8..575450a027d 100644 --- a/v3/pkg/application/mainthread_windows.go +++ b/v3/pkg/application/mainthread_windows.go @@ -1,4 +1,4 @@ -//go:build windows +//go:build windows && !server package application diff --git a/v3/pkg/application/menuitem_windows.go b/v3/pkg/application/menuitem_windows.go index c7c6f5f7a36..633c757929e 100644 --- a/v3/pkg/application/menuitem_windows.go +++ b/v3/pkg/application/menuitem_windows.go @@ -1,4 +1,4 @@ -//go:build windows +//go:build windows && !server package application diff --git a/v3/pkg/application/popupmenu_windows.go b/v3/pkg/application/popupmenu_windows.go index 75bd951cae1..4280d6d1f01 100644 --- a/v3/pkg/application/popupmenu_windows.go +++ b/v3/pkg/application/popupmenu_windows.go @@ -1,3 +1,5 @@ +//go:build windows && !server + package application import ( diff --git a/v3/pkg/application/screen_windows.go b/v3/pkg/application/screen_windows.go index 772618d4b97..1f70dd56974 100644 --- a/v3/pkg/application/screen_windows.go +++ b/v3/pkg/application/screen_windows.go @@ -1,4 +1,4 @@ -//go:build windows +//go:build windows && !server package application diff --git a/v3/pkg/application/single_instance_windows.go b/v3/pkg/application/single_instance_windows.go index b92b2749a8e..6940c301c37 100644 --- a/v3/pkg/application/single_instance_windows.go +++ b/v3/pkg/application/single_instance_windows.go @@ -1,4 +1,4 @@ -//go:build windows +//go:build windows && !server package application diff --git a/v3/pkg/application/systemtray_windows.go b/v3/pkg/application/systemtray_windows.go index a692ea42014..695b20c29da 100644 --- a/v3/pkg/application/systemtray_windows.go +++ b/v3/pkg/application/systemtray_windows.go @@ -1,4 +1,4 @@ -//go:build windows +//go:build windows && !server package application diff --git a/v3/pkg/application/webview_window.go b/v3/pkg/application/webview_window.go index 224bab96f6d..bbeabae6aa0 100644 --- a/v3/pkg/application/webview_window.go +++ b/v3/pkg/application/webview_window.go @@ -1,6 +1,7 @@ package application import ( + "encoding/json" "fmt" "runtime" "slices" @@ -9,8 +10,6 @@ import ( "sync/atomic" "unsafe" - "encoding/json" - "github.com/wailsapp/wails/v3/internal/assetserver" "github.com/wailsapp/wails/v3/internal/optional" "github.com/wailsapp/wails/v3/pkg/events" @@ -116,9 +115,33 @@ type ( snapAssist() setContentProtection(enabled bool) attachModal(modalWindow *WebviewWindow) + setNonClientHitTestRegions([]nonClientHitTestRegion) + } + + nonClientHitTestKind string + + // nonClientHitTestRegion is a frontend-owned client-area rectangle in physical pixels. + nonClientHitTestRegion struct { + Kind nonClientHitTestKind `json:"kind,omitempty"` + Left int `json:"left"` + Top int `json:"top"` + Right int `json:"right"` + Bottom int `json:"bottom"` + } + + nonClientHitTestRegionsMessage struct { + Version int `json:"version,omitempty"` + Regions []nonClientHitTestRegion `json:"regions"` } ) +const ( + nonClientHitTestKindCaption nonClientHitTestKind = "caption" + nonClientHitTestKindMinimize nonClientHitTestKind = "minimize" + nonClientHitTestKindMaximize nonClientHitTestKind = "maximize" + nonClientHitTestKindClose nonClientHitTestKind = "close" +) + type WindowEvent struct { ctx *WindowEventContext cancelled atomic.Bool @@ -774,6 +797,9 @@ func (w *WebviewWindow) HandleMessage(message string) { w.Error("%w", err) } } + case strings.HasPrefix(message, "wails:non-client-region:"): + message = strings.Replace(message, "wails:non-client-region:", "", 1) + w.handleNonClientRegionMessage(message) case message == "wails:runtime:ready": w.emit(events.Common.WindowRuntimeReady) w.pendingJSMutex.Lock() @@ -815,6 +841,46 @@ func (w *WebviewWindow) HandleMessage(message string) { } } +func (w *WebviewWindow) handleNonClientRegionMessage(payload string) { + var message nonClientHitTestRegionsMessage + if err := json.Unmarshal([]byte(payload), &message); err != nil { + w.Error("failed to parse non-client regions: %w", err) + return + } + + regions := make([]nonClientHitTestRegion, 0, len(message.Regions)) + for i, region := range message.Regions { + normalised, err := normaliseNonClientHitTestRegion(region) + if err != nil { + w.Error("region %d: %w", i, err) + continue + } + regions = append(regions, normalised) + } + + InvokeSync(func() { + w.impl.setNonClientHitTestRegions(regions) + }) +} + +func normaliseNonClientHitTestRegion(region nonClientHitTestRegion) (nonClientHitTestRegion, error) { + if region.Right <= region.Left || region.Bottom <= region.Top { + return nonClientHitTestRegion{}, fmt.Errorf("invalid rectangle") + } + + kind := nonClientHitTestKind(strings.ToLower(string(region.Kind))) + switch kind { + case nonClientHitTestKindCaption, + nonClientHitTestKindMinimize, + nonClientHitTestKindMaximize, + nonClientHitTestKindClose: + region.Kind = kind + return region, nil + default: + return nonClientHitTestRegion{}, fmt.Errorf("unknown region kind %q", region.Kind) + } +} + func (w *WebviewWindow) startResize(border string) error { if w.impl == nil || w.isDestroyed() { return nil diff --git a/v3/pkg/application/webview_window_android.go b/v3/pkg/application/webview_window_android.go index b94dd87f8da..a7e77d917b0 100644 --- a/v3/pkg/application/webview_window_android.go +++ b/v3/pkg/application/webview_window_android.go @@ -341,6 +341,9 @@ func (w *androidWebviewWindow) setContentProtection(_ bool) { // Android content protection - could be implemented with FLAG_SECURE } +func (w *androidWebviewWindow) setNonClientHitTestRegions([]nonClientHitTestRegion) { +} + func (w *androidWebviewWindow) setHTML(_ string) { // Not supported: the WebView always loads from the asset server } diff --git a/v3/pkg/application/webview_window_darwin.go b/v3/pkg/application/webview_window_darwin.go index fd4278fd402..6f2995a162a 100644 --- a/v3/pkg/application/webview_window_darwin.go +++ b/v3/pkg/application/webview_window_darwin.go @@ -1759,6 +1759,9 @@ func (w *macosWebviewWindow) setContentProtection(enabled bool) { C.setContentProtection(w.nsWindow, C.bool(enabled)) } +func (w *macosWebviewWindow) setNonClientHitTestRegions([]nonClientHitTestRegion) { +} + func (w *macosWebviewWindow) attachModal(modalWindow *WebviewWindow) { if modalWindow == nil || modalWindow.impl == nil || modalWindow.isDestroyed() { return diff --git a/v3/pkg/application/webview_window_darwin_drag.m b/v3/pkg/application/webview_window_darwin_drag.m index 3dc2cf9ea1f..9adcf4632cb 100644 --- a/v3/pkg/application/webview_window_darwin_drag.m +++ b/v3/pkg/application/webview_window_darwin_drag.m @@ -22,6 +22,13 @@ - (instancetype)initWithFrame:(NSRect)frameRect { return self; } +// Pass mouse events through to the WKWebView underneath so CSS :hover, +// mousemove, and cursor updates work. Drag-and-drop delivery uses +// registerForDraggedTypes + geometry, not hitTest, so file drop is unaffected. +- (NSView *)hitTest:(NSPoint)point { + return nil; +} + // draggingEntered: - (NSDragOperation)draggingEntered:(id)sender { NSPasteboard *pasteboard = [sender draggingPasteboard]; diff --git a/v3/pkg/application/webview_window_ios.go b/v3/pkg/application/webview_window_ios.go index b77923d365c..5453b707f8d 100644 --- a/v3/pkg/application/webview_window_ios.go +++ b/v3/pkg/application/webview_window_ios.go @@ -390,6 +390,9 @@ func (w *iosWebviewWindow) setContentProtection(_ bool) { // iOS content protection - could be implemented with UIScreen captured notifications } +func (w *iosWebviewWindow) setNonClientHitTestRegions([]nonClientHitTestRegion) { +} + func (w *iosWebviewWindow) setHTML(html string) { if w.nativeHandle == nil || html == "" { return diff --git a/v3/pkg/application/webview_window_linux.go b/v3/pkg/application/webview_window_linux.go index 09903796b3d..e6288f43cac 100644 --- a/v3/pkg/application/webview_window_linux.go +++ b/v3/pkg/application/webview_window_linux.go @@ -466,3 +466,5 @@ func (w *linuxWebviewWindow) hideMenuBar() {} func (w *linuxWebviewWindow) toggleMenuBar() {} func (w *linuxWebviewWindow) snapAssist() {} // No-op on Linux func (w *linuxWebviewWindow) setContentProtection(enabled bool) {} +func (w *linuxWebviewWindow) setNonClientHitTestRegions([]nonClientHitTestRegion) { +} diff --git a/v3/pkg/application/webview_window_options.go b/v3/pkg/application/webview_window_options.go index 78f5b721519..0baa9a4bd9e 100644 --- a/v3/pkg/application/webview_window_options.go +++ b/v3/pkg/application/webview_window_options.go @@ -344,6 +344,21 @@ type WindowsWindow struct { // Default: false WindowMaskDraggable bool + // NonClientRegionSupport enables WebView2's native non-client region support + // for this window when the installed WebView2 Runtime supports it. This is + // primarily intended to make app-region: drag style custom titlebars work + // with native non-client hit testing. + // Default: false + NonClientRegionSupport bool + + // WebView2CompositionHosting creates WebView2 with visual hosting using + // ICoreWebView2CompositionController and DirectComposition instead of the + // HWND-hosted controller. This is intended for custom host-owned non-client + // hit-testing, for example manual caption-button regions rendered in web + // content and resolved through GetNonClientRegionAtPoint / SendMouseInput. + // Default: false + WebView2CompositionHosting bool + // WindowDidMoveDebounceMS is the amount of time to debounce the WindowDidMove event // when moving the window // Default: 0 diff --git a/v3/pkg/application/webview_window_windows.go b/v3/pkg/application/webview_window_windows.go index d5173253315..c3f1a78b642 100644 --- a/v3/pkg/application/webview_window_windows.go +++ b/v3/pkg/application/webview_window_windows.go @@ -1,4 +1,4 @@ -//go:build windows +//go:build windows && !server package application @@ -70,11 +70,8 @@ type windowsWebviewWindow struct { // Track whether content protection has been applied to the native window yet contentProtectionApplied bool - // resizeBorder* is the width/height of the resize border in pixels. - resizeBorderWidth int32 - resizeBorderHeight int32 - focusingChromium bool - onceDo sync.Once + focusingChromium bool + onceDo sync.Once // Window move debouncer moveDebouncer func(func()) @@ -89,6 +86,14 @@ type windowsWebviewWindow struct { // cannot be used for this because keyboard snap (Win+Left) bypasses those messages. lastSizeWParam uintptr + nonClientHitTest nonClientHitTestState + // Tracks the caption button currently pressed through forwarded non-client input. + // Once capture is active, Windows reports movement as normal client mouse input, + // so we need this state to keep WebView hover/pressed transitions native-like. + activeNonClientButton uintptr + activeNonClientButtonHovered bool + compositionCursor w32.HCURSOR + // lastKnownDPI is the window's DPI the last time it was in a non-minimised // state. It is used on the un-minimise path to decide whether the WebView2 // rasterization scale actually needs resyncing: when the DPI is unchanged @@ -362,6 +367,21 @@ func (w *windowsWebviewWindow) framelessWithDecorations() bool { return w.parent.options.Frameless && !w.parent.options.Windows.DisableFramelessWindowDecorations } +func (w *windowsWebviewWindow) extendFrameIntoClientArea(extend bool) error { + if !extend || !w.chromium.CompositionControllerEnabled { + return w32.ExtendFrameIntoClientArea(w.hwnd, extend) + } + + // Leave the top edge unextended for composition-hosted non-client regions so + // the Windows 11 Snap Layout flyout does not cover custom HTMAXBUTTON areas. + return w32.ExtendFrameIntoClientAreaWithMargins(w.hwnd, w32.MARGINS{ + CxLeftWidth: 1, + CxRightWidth: 1, + CyTopHeight: 0, + CyBottomHeight: 1, + }) +} + func (w *windowsWebviewWindow) run() { options := w.parent.options @@ -371,6 +391,9 @@ func (w *windowsWebviewWindow) run() { w.showRequested = !options.Hidden w.chromium = edge.NewChromium() + w.chromium.NonClientRegionSupportEnabled = options.Windows.NonClientRegionSupport + w.chromium.CompositionControllerEnabled = options.Windows.WebView2CompositionHosting + w.chromium.SetCursorChangedCallback(w.applyCompositionCursor) if globalApplication.options.ErrorHandler != nil { w.chromium.SetErrorCallback(globalApplication.options.ErrorHandler) } @@ -967,7 +990,7 @@ func (w *windowsWebviewWindow) fullscreen() { return } if w.framelessWithDecorations() { - err := w32.ExtendFrameIntoClientArea(w.hwnd, false) + err := w.extendFrameIntoClientArea(false) if err != nil { globalApplication.handleFatalError(err) } @@ -1017,7 +1040,7 @@ func (w *windowsWebviewWindow) unfullscreen() { return } if w.framelessWithDecorations() { - err := w32.ExtendFrameIntoClientArea(w.hwnd, true) + err := w.extendFrameIntoClientArea(true) if err != nil { globalApplication.handleFatalError(err) } @@ -1345,9 +1368,7 @@ func (w *windowsWebviewWindow) setFrameless(b bool) { func newWindowImpl(parent *WebviewWindow) *windowsWebviewWindow { result := &windowsWebviewWindow{ - parent: parent, - resizeBorderWidth: int32(w32.GetSystemMetrics(w32.SM_CXSIZEFRAME)), - resizeBorderHeight: int32(w32.GetSystemMetrics(w32.SM_CYSIZEFRAME)), + parent: parent, // Initialize visibility tracking fields showRequested: false, visibilityTimeout: nil, @@ -1569,6 +1590,16 @@ func (w *windowsWebviewWindow) WndProc(msg uint32, wparam, lparam uintptr) uintp return w32.HTCLIENT } + if w.parent.options.Windows.WebView2CompositionHosting && w.chromium != nil && w.chromium.CompositionControllerReady() { + if result, handled := w.routeNonClientInput(msg, wparam, lparam); handled { + return result + } + + if w.routeCompositionMouseInput(msg, wparam, lparam) { + return 0 + } + } + switch msg { case w32.WM_ACTIVATE: if int(wparam&0xffff) == w32.WA_INACTIVE { @@ -1587,7 +1618,7 @@ func (w *windowsWebviewWindow) WndProc(msg uint32, wparam, lparam uintptr) uintp // As a result we have hidden the titlebar but still have the default window frame styling. // See: https://docs.microsoft.com/en-us/windows/win32/api/dwmapi/nf-dwmapi-dwmextendframeintoclientarea#remarks if w.framelessWithDecorations() { - err := w32.ExtendFrameIntoClientArea(w.hwnd, true) + err := w.extendFrameIntoClientArea(true) if err != nil { globalApplication.handleFatalError(err) } @@ -1615,7 +1646,11 @@ func (w *windowsWebviewWindow) WndProc(msg uint32, wparam, lparam uintptr) uintp // Now do the actual close w.chromium.ShuttingDown() return w32.DefWindowProc(w.hwnd, w32.WM_CLOSE, 0, 0) - + case w32.WM_SETCURSOR: + if w.compositionCursor != 0 && w32.LOWORD(uint32(lparam)) == w32.HTCLIENT { + w32.SetCursor(w.compositionCursor) + return 1 + } case w32.WM_KILLFOCUS: if w.focusingChromium { return 0 @@ -1666,11 +1701,16 @@ func (w *windowsWebviewWindow) WndProc(msg uint32, wparam, lparam uintptr) uintp if w.parent.options.BackgroundType == BackgroundTypeSolid { col := w.parent.options.BackgroundColour hdc := w32.HDC(wparam) - rc := w32.GetClientRect(w.hwnd) - colorRef := w32.COLORREF(uint32(col.Red) | uint32(col.Green)<<8 | uint32(col.Blue)<<16) - hbrush := w32.CreateSolidBrush(colorRef) - w32.FillRect(hdc, rc, hbrush) - w32.DeleteObject(w32.HGDIOBJ(hbrush)) + // GetClientRect can legitimately return nil for a window in a + // transient state (minimise/restore transitions are especially + // prone to triggering it). FillRect with a nil rect crashes, so it + // must be checked before painting. + if rc := w32.GetClientRect(w.hwnd); rc != nil { + colorRef := w32.COLORREF(uint32(col.Red) | uint32(col.Green)<<8 | uint32(col.Blue)<<16) + hbrush := w32.CreateSolidBrush(colorRef) + w32.FillRect(hdc, rc, hbrush) + w32.DeleteObject(w32.HGDIOBJ(hbrush)) + } } return 1 // WM_UAHDRAWMENUITEM is handled by MenuBarWndProc at the top of this function @@ -1873,7 +1913,7 @@ func (w *windowsWebviewWindow) WndProc(msg uint32, wparam, lparam uintptr) uintp // For frameless windows with decorations, re-extend the frame into client area // to ensure proper window frame styling after DPI change. if w.framelessWithDecorations() { - if err := w32.ExtendFrameIntoClientArea(w.hwnd, true); err != nil { + if err := w.extendFrameIntoClientArea(true); err != nil { globalApplication.handleFatalError(err) } } @@ -1887,11 +1927,11 @@ func (w *windowsWebviewWindow) WndProc(msg uint32, wparam, lparam uintptr) uintp // DPI changes manually — but only while non-minimised. When detection // was re-enabled in setupChromium, the resync below is a no-op (Edge // owns the scale) and only lastKnownDPI tracking runs. - // While minimised the window sits off its restore - // monitor, so GetDpiForWindow can report a different monitor's DPI, which - // would push a wrong scale - // onto the controller (one the restore-time DPI gate then won't correct, - // since DPI == lastKnownDPI) and would make a COM call into a possibly + // While minimised the window sits off its restore monitor, so + // GetDpiForWindow can report a different monitor's DPI, which would + // push a wrong scale onto the controller (one the restore-time DPI gate + // then won't correct, since DPI == lastKnownDPI) and would make a COM + // call into a possibly // suspended controller (#5605). A genuine DPI difference is instead // caught on restore by resyncWebviewDPIAfterUnminimiseIfDPIChanged. if !w.isMinimizing { @@ -1963,7 +2003,7 @@ func (w *windowsWebviewWindow) WndProc(msg uint32, wparam, lparam uintptr) uintp // As a result we have hidden the titlebar but still have the default window frame styling. // See: https://docs.microsoft.com/en-us/windows/win32/api/dwmapi/nf-dwmapi-dwmextendframeintoclientarea#remarks if w.framelessWithDecorations() { - err := w32.ExtendFrameIntoClientArea(w.hwnd, true) + err := w.extendFrameIntoClientArea(true) if err != nil { globalApplication.handleFatalError(err) } @@ -2040,10 +2080,9 @@ func (w *windowsWebviewWindow) WndProc(msg uint32, wparam, lparam uintptr) uintp // resyncWebviewRasterizationScale re-asserts the window's actual DPI on the // WebView2 controller and reports whether the scale was out of sync. Wails -// runs WebView2 in raw-pixels bounds mode with ShouldDetectMonitorScaleChanges -// disabled, so keeping the rasterization scale in step with the window's DPI -// is the application's responsibility. It is a no-op when the controller is -// unavailable or already in sync. +// keeps this as a fallback for controllers where monitor-scale detection could +// not be re-enabled; when WebView2 owns monitor scale detection, the host-side +// resync stands down. func (w *windowsWebviewWindow) resyncWebviewRasterizationScale() bool { // With monitor-scale detection re-enabled (setupChromium), WebView2 owns // the rasterization scale and updates it on monitor crossings itself. A @@ -2373,33 +2412,65 @@ func (w *windowsWebviewWindow) setupChromium() { chromium.MessageWithAdditionalObjectsCallback = w.processMessageWithAdditionalObjects chromium.WebResourceRequestedCallback = w.processRequest chromium.ContainsFullScreenElementChangedCallback = w.fullscreenChanged + chromium.NavigationStartingCallback = w.navigationStarting chromium.NavigationCompletedCallback = w.navigationCompleted chromium.AcceleratorKeyCallback = w.processKeyBinding chromium.Embed(w.hwnd) - // Ensure automatic monitor-scale detection is on. Published webview2 - // module versions up to v1.0.27 disable ShouldDetectMonitorScaleChanges - // at controller creation (the in-repo module no longer does), leaving - // rasterization-scale updates entirely to the host's WM_DPICHANGED - // handling. In that - // host-managed mode, dragging the window across a mixed-DPI monitor - // boundary can make the embedded browser compute a degenerate - // scale(0,0) transform (ui/gfx/geometry/transform.cc NOTREACHED - // "is not invertible"); the resulting compositor frame is rejected by - // the viz process as a malformed Mojo message, which kills the GPU - // process, and after enough repeat kills the browser process gives up - // ("GPU process isn't usable. Goodbye.") taking the controller with - // it. Detection-on is the WebView2 default and keeps monitor-cross - // scale updates inside Edge, where that path is actually exercised; - // bounds stay raw-pixels. While detection is on, the host-side - // WM_DPICHANGED / un-minimise scale resyncs stand down (see + // Configure who owns the WebView2 rasterization scale on a monitor-DPI + // change. Two hosting modes need opposite answers: + // + // Windowed (HWND-child) hosting — the default: enable automatic + // monitor-scale detection. Published webview2 module versions up to + // v1.0.27 disabled ShouldDetectMonitorScaleChanges at controller creation + // (the in-repo module no longer does), leaving rasterization-scale updates + // entirely to the host's WM_DPICHANGED handling. In that host-managed mode, + // dragging the window across a mixed-DPI monitor boundary can make the + // embedded browser compute a degenerate scale(0,0) transform + // (ui/gfx/geometry/transform.cc NOTREACHED "is not invertible"); the + // resulting compositor frame is rejected by the viz process as a malformed + // Mojo message, which kills the GPU process, and after enough repeat kills + // the browser process gives up ("GPU process isn't usable. Goodbye.") + // taking the controller with it. Detection-on is the WebView2 default and + // keeps monitor-cross scale updates inside Edge, where that path is + // actually exercised; bounds stay raw-pixels. While detection is on, the + // host-side WM_DPICHANGED / un-minimise scale resyncs stand down (see // monitorScaleDetectionOn) so the scale has exactly one writer. + // + // Visual hosting (UseVisualHosting -> COREWEBVIEW2_HOSTING_MODE_WINDOW_TO_VISUAL): + // the content is a DirectComposition visual, decoupled from the child HWND + // that automatic detection tracks. Across a mixed-DPI boundary detection + // then reads the wrong monitor and settles the visual on a stale scale, so + // the whole UI renders shrunk. There the host must own the scale via + // resyncWebviewRasterizationScale (correct per WebView2Feedback #3665, and + // reliable now that the by-value PutRasterizationScale bug is fixed). The + // module leaves detection at its platform default (enabled), so visual + // hosting must disable it *explicitly* — merely skipping the enable would + // leave detection on AND the host resync running, i.e. two writers racing, + // which is the scale(0,0) crash above. With detection off the host owns the + // scale via resyncWebviewRasterizationScale. + // + // Whichever mode: monitorScaleDetectionOn is set from the controller's + // *actual* ShouldDetectMonitorScaleChanges after the Put, never from the + // value we asked for. A failed Put can leave detection at its platform + // default (enabled) while we intended off; keying the flag off intent would + // then run the host resync against a detecting Edge — the exact two-writer + // race this guards against. The host stands down whenever detection is on so + // the rasterization scale keeps exactly one writer. if controller := chromium.GetController(); controller != nil { if c3 := controller.GetICoreWebView2Controller3(); c3 != nil { - if err := c3.PutShouldDetectMonitorScaleChanges(true); err != nil { - globalApplication.error("webview2: enable monitor scale detection: %v", err) + wantDetection := !globalApplication.options.Windows.UseVisualHosting + if err := c3.PutShouldDetectMonitorScaleChanges(wantDetection); err != nil { + globalApplication.error("webview2: set monitor scale detection to %v: %v", wantDetection, err) + } + if on, err := c3.GetShouldDetectMonitorScaleChanges(); err == nil { + w.monitorScaleDetectionOn = on } else { + // Can't confirm the state: assume detection may be on and stand + // the host resync down. A cosmetic stale scale beats risking the + // two-writer GPU-process crash. + globalApplication.error("webview2: query monitor scale detection: %v", err) w.monitorScaleDetectionOn = true } } @@ -2561,17 +2632,24 @@ func (w *windowsWebviewWindow) flash(enabled bool) { w32.FlashWindow(w.hwnd, enabled) } +func (w *windowsWebviewWindow) navigationStarting(_ *edge.ICoreWebView2) { + w.setNonClientHitTestRegions(nil) +} + func (w *windowsWebviewWindow) navigationCompleted( sender *edge.ICoreWebView2, args *edge.ICoreWebView2NavigationCompletedEventArgs, ) { - // Install the runtime core - w.execJS(runtime.Core(globalApplication.impl.GetFlags(globalApplication.options))) - - // Set the EnableFileDrop flag for this window (Windows-specific) - // The JS runtime checks this before processing file drops - w.execJS(fmt.Sprintf("window._wails.flags.enableFileDrop = %v;", w.parent.options.EnableFileDrop)) + // Inject runtime core and window-specific flags together so side-effect + // runtime modules see a consistent _wails configuration at startup. + js := runtime.Core(globalApplication.impl.GetFlags(globalApplication.options)) + js += fmt.Sprintf( + "window._wails.flags.enableFileDrop = %v; window._wails.flags.nonClientRegionTracking = %v;", + w.parent.options.EnableFileDrop, + w.parent.options.Windows.WebView2CompositionHosting, + ) + w.execJS(js) // EmitEvent DomReady ApplicationEvent windowEvents <- &windowEvent{EventID: uint(events.Windows.WebViewNavigationCompleted), WindowID: w.parent.id} @@ -2808,15 +2886,6 @@ func (w *windowsWebviewWindow) disableRedrawWithCallback(callback func()) { } -func NewIconFromResource(instance w32.HINSTANCE, resId uint16) (w32.HICON, error) { - var err error - var result w32.HICON - if result = w32.LoadIconWithResourceID(instance, resId); result == 0 { - err = fmt.Errorf("cannot load icon from resource with id %v", resId) - } - return result, err -} - func (w *windowsWebviewWindow) setMinimiseButtonState(state ButtonState) { switch state { case ButtonDisabled, ButtonHidden: diff --git a/v3/pkg/application/webview_window_windows_devtools.go b/v3/pkg/application/webview_window_windows_devtools.go index 096bda5b556..ba8dba23d8f 100644 --- a/v3/pkg/application/webview_window_windows_devtools.go +++ b/v3/pkg/application/webview_window_windows_devtools.go @@ -1,4 +1,4 @@ -//go:build windows && (!production || devtools) +//go:build windows && !server && (!production || devtools) package application diff --git a/v3/pkg/application/webview_window_windows_nonclient.go b/v3/pkg/application/webview_window_windows_nonclient.go new file mode 100644 index 00000000000..d434e41d10d --- /dev/null +++ b/v3/pkg/application/webview_window_windows_nonclient.go @@ -0,0 +1,535 @@ +//go:build windows + +package application + +import ( + "slices" + "sync" + "unsafe" + + "github.com/wailsapp/wails/v3/pkg/w32" + "github.com/wailsapp/wails/v3/internal/webview2/pkg/edge" +) + +type nonClientHitTestState struct { + mu sync.RWMutex + regions []nonClientHitTestRegion +} + +func (s *nonClientHitTestState) set(regions []nonClientHitTestRegion) { + s.mu.Lock() + if len(regions) == 0 { + s.regions = nil + } else { + s.regions = slices.Clone(regions) + } + s.mu.Unlock() +} + +func (s *nonClientHitTestState) snapshot() []nonClientHitTestRegion { + s.mu.RLock() + defer s.mu.RUnlock() + if len(s.regions) == 0 { + return nil + } + return append([]nonClientHitTestRegion(nil), s.regions...) +} + +func (w *windowsWebviewWindow) setNonClientHitTestRegions(regions []nonClientHitTestRegion) { + w.nonClientHitTest.set(regions) +} + +func (w *windowsWebviewWindow) applyCompositionCursor(cursor edge.HCURSOR, systemCursorID uint32) { + hcursor := w32.HCURSOR(cursor) + if hcursor == 0 && systemCursorID != 0 { + hcursor = w32.LoadCursorWithResourceID(0, uint16(systemCursorID)) + } + if hcursor == 0 { + return + } + + w.compositionCursor = hcursor + w32.SetCursor(hcursor) +} + +func (w *windowsWebviewWindow) routeNonClientInput(msg uint32, wparam, lparam uintptr) (uintptr, bool) { + switch msg { + case w32.WM_NCHITTEST: + if hitTest, handled := w32.DwmDefWindowProc(w.hwnd, msg, wparam, lparam); handled { + if hitTest != w32.HTCLIENT && hitTest != w32.HTNOWHERE { + return hitTest, true + } + } + + screenX := int(w32.GET_X_LPARAM(lparam)) + screenY := int(w32.GET_Y_LPARAM(lparam)) + + if hitTest, ok := w.resizeBorderHitTest(screenX, screenY); ok { + return hitTest, true + } + + return w.nonClientHitTestFromScreen(screenX, screenY) + case w32.WM_NCMOUSEMOVE: + screenX := int(w32.GET_X_LPARAM(lparam)) + screenY := int(w32.GET_Y_LPARAM(lparam)) + + hitTest, ok := w.nonClientHitTestFromScreen(screenX, screenY) + if !ok || hitTest != wparam { + return 0, false + } + + w.trackCompositionMouseLeave(true) + + clientX, clientY, ok := w32.ScreenToClient( + w.hwnd, + int(w32.GET_X_LPARAM(lparam)), + int(w32.GET_Y_LPARAM(lparam)), + ) + if !ok { + return 0, false + } + + _ = w.chromium.SendMouseInput( + edge.COREWEBVIEW2_MOUSE_EVENT_KIND_MOVE, + edge.COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS_NONE, + 0, + clientX, + clientY, + ) + + return w32.DwmDefWindowProc(w.hwnd, msg, wparam, lparam) + case w32.WM_NCMOUSELEAVE: + // Windows can emit a spurious NCMOUSELEAVE right after a forwarded + // non-client button press. Suppress it until the captured mouse move + // path below can decide whether the pointer really left the active button. + if w32.GetCapture() == w.hwnd && w.activeNonClientButton != 0 { + return 0, true + } + + _ = w.chromium.SendMouseInput( + edge.COREWEBVIEW2_MOUSE_EVENT_KIND_LEAVE, + edge.COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS_NONE, + 0, + 0, + 0, + ) + case w32.WM_NCLBUTTONDOWN, w32.WM_NCLBUTTONUP, w32.WM_NCLBUTTONDBLCLK: + switch wparam { + case w32.HTMINBUTTON, w32.HTMAXBUTTON, w32.HTCLOSE: + default: + return 0, false + } + + if w.forwardFrontendNonClientButtonInput(msg, wparam, lparam) { + return 0, true + } + case w32.WM_NCRBUTTONUP: + if wparam != w32.HTCAPTION && wparam != w32.HTSYSMENU { + return 0, false + } + + screenX := int(w32.GET_X_LPARAM(lparam)) + screenY := int(w32.GET_Y_LPARAM(lparam)) + + if hitTest, ok := w.nonClientHitTestFromScreen(screenX, screenY); !ok || hitTest != w32.HTCAPTION { + return 0, false + } + + if w.showCaptionSystemMenu(screenX, screenY) { + return 0, true + } + } + + return 0, false +} + +func (w *windowsWebviewWindow) nonClientHitTestFromScreen(screenX, screenY int) (uintptr, bool) { + regions := w.nonClientHitTest.snapshot() + // Later frontend regions should win when rectangles overlap, matching the + // DOM/CSS order used to collect them (for example caption buttons over a + // caption drag area). + for i := len(regions) - 1; i >= 0; i-- { + r := regions[i] + + left, top := w32.ClientToScreen(w.hwnd, r.Left, r.Top) + right, bottom := w32.ClientToScreen(w.hwnd, r.Right, r.Bottom) + + // outside app + if screenX < left || screenX >= right || screenY < top || screenY >= bottom { + continue + } + + switch r.Kind { + case nonClientHitTestKindMaximize: + return w32.HTMAXBUTTON, true + case nonClientHitTestKindCaption: + return w32.HTCAPTION, true + case nonClientHitTestKindMinimize: + return w32.HTMINBUTTON, true + case nonClientHitTestKindClose: + return w32.HTCLOSE, true + } + } + + // fallback to default non-client region hit test (app-region) + if !w.chromium.NonClientRegionSupportEnabled { + return 0, false + } + + clientX, clientY, ok := w32.ScreenToClient(w.hwnd, screenX, screenY) + if !ok { + return 0, false + } + + region, handled, err := w.chromium.GetNonClientRegionAtPoint(int32(clientX), int32(clientY)) + if err != nil || !handled { + return 0, false + } + + switch region { + case edge.COREWEBVIEW2_NON_CLIENT_REGION_KIND_CAPTION: + return w32.HTCAPTION, true + case edge.COREWEBVIEW2_NON_CLIENT_REGION_KIND_MINIMIZE: + return w32.HTMINBUTTON, true + case edge.COREWEBVIEW2_NON_CLIENT_REGION_KIND_MAXIMIZE: + return w32.HTMAXBUTTON, true + case edge.COREWEBVIEW2_NON_CLIENT_REGION_KIND_CLOSE: + return w32.HTCLOSE, true + case edge.COREWEBVIEW2_NON_CLIENT_REGION_KIND_CLIENT, + edge.COREWEBVIEW2_NON_CLIENT_REGION_KIND_NOWHERE: + return 0, false + default: + return 0, false + } +} + +func (w *windowsWebviewWindow) resizeBorderHitTest(screenX, screenY int) (uintptr, bool) { + if w.parent.options.DisableResize || w.isMaximised() || w.isFullscreen() { + return 0, false + } + + rect := w32.GetWindowRect(w.hwnd) + width := int(rect.Right - rect.Left) + height := int(rect.Bottom - rect.Top) + if width <= 0 || height <= 0 { + return 0, false + } + + x := screenX - int(rect.Left) + y := screenY - int(rect.Top) + if x < 0 || y < 0 || x >= width || y >= height { + return 0, false + } + + dpi, _ := w.DPI() + borderX := systemMetricForDPI(w32.SM_CXSIZEFRAME, dpi) + systemMetricForDPI(w32.SM_CXPADDEDBORDER, dpi) + if borderX < 1 { + borderX = 1 + } + borderY := systemMetricForDPI(w32.SM_CYSIZEFRAME, dpi) + systemMetricForDPI(w32.SM_CXPADDEDBORDER, dpi) + if borderY < 1 { + borderY = 1 + } + + left := x < borderX + right := x >= width-borderX + top := y < borderY + bottom := y >= height-borderY + + switch { + case top && left: + return w32.HTTOPLEFT, true + case top && right: + return w32.HTTOPRIGHT, true + case bottom && left: + return w32.HTBOTTOMLEFT, true + case bottom && right: + return w32.HTBOTTOMRIGHT, true + case top: + return w32.HTTOP, true + case bottom: + return w32.HTBOTTOM, true + case left: + return w32.HTLEFT, true + case right: + return w32.HTRIGHT, true + default: + return 0, false + } +} + +func systemMetricForDPI(index int, dpi w32.UINT) int { + if dpi != 0 && w32.HasGetSystemMetricsForDpiFunc() { + return w32.GetSystemMetricsForDpi(index, dpi) + } + return w32.GetSystemMetrics(index) +} + +func (w *windowsWebviewWindow) forwardFrontendNonClientButtonInput(msg uint32, wparam, lparam uintptr) bool { + screenX := int(w32.GET_X_LPARAM(lparam)) + screenY := int(w32.GET_Y_LPARAM(lparam)) + + hitTest, ok := w.nonClientHitTestFromScreen(screenX, screenY) + if !ok || hitTest != wparam { + return false + } + + clientX, clientY, ok := w32.ScreenToClient(w.hwnd, screenX, screenY) + if !ok { + return false + } + + eventKind, virtualKeys, ok := nonClientLeftButtonMouseEvent(msg) + if !ok { + return false + } + + if err := w.chromium.SendMouseInput( + eventKind, + virtualKeys, + 0, + clientX, + clientY, + ); err != nil { + return false + } + + // Remember which caption button started the press. During capture, Windows + // sends movement as WM_MOUSEMOVE, so later moves must be compared against + // this original hit-test rather than any caption button under the cursor. + if msg == w32.WM_NCLBUTTONDOWN || msg == w32.WM_NCLBUTTONDBLCLK { + w.activeNonClientButton = wparam + w.activeNonClientButtonHovered = true + } + + w.updateCompositionMouseCapture(msg) + + return true +} + +func (w *windowsWebviewWindow) showCaptionSystemMenu(screenX, screenY int) bool { + menu := w32.GetSystemMenu(w.hwnd, false) + if menu == 0 { + return false + } + + w32.SetForegroundWindow(w.hwnd) + command := w32.TrackPopupMenuCommand( + menu, + w32.TPM_LEFTALIGN|w32.TPM_TOPALIGN|w32.TPM_RIGHTBUTTON, + int32(screenX), + int32(screenY), + w.hwnd, + nil, + ) + w32.PostMessage(w.hwnd, w32.WM_NULL, 0, 0) + if command == 0 { + return true + } + + w32.SendMessage(w.hwnd, w32.WM_SYSCOMMAND, command, 0) + return true +} + +func (w *windowsWebviewWindow) routeCompositionMouseInput(msg uint32, wparam, lparam uintptr) bool { + eventKind, ok := webviewCompositionMouseEventKind(msg) + if !ok { + return false + } + + if msg == w32.WM_MOUSEMOVE { + w.trackCompositionMouseLeave(false) + } + + clientX, clientY, ok := w.compositionMouseClientPoint(msg, lparam) + if !ok { + return false + } + + var mouseData uint32 + switch msg { + case w32.WM_MOUSEWHEEL, w32.WM_MOUSEHWHEEL: + mouseData = uint32(int16(wparam >> 16)) + case w32.WM_XBUTTONDOWN, w32.WM_XBUTTONUP, w32.WM_XBUTTONDBLCLK: + mouseData = uint32(wparam >> 16) + } + + // While a forwarded caption button owns capture, WebView still receives + // normal mouse moves. Only forward those moves while the cursor remains over + // the same button; otherwise synthesize leave so pressed styling is cleared. + if msg == w32.WM_MOUSEMOVE && w.activeNonClientButton != 0 && w32.GetCapture() == w.hwnd { + if !w.updateActiveNonClientButtonHover() { + return true + } + } + + if err := w.chromium.SendMouseInput( + eventKind, + edge.COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS(uint32(wparam)&0xffff), + mouseData, + clientX, + clientY, + ); err != nil { + return false + } + + w.updateCompositionMouseCapture(msg) + + return true +} + +func (w *windowsWebviewWindow) trackCompositionMouseLeave(nonClient bool) { + flags := uint32(w32.TME_LEAVE) + if nonClient { + flags |= w32.TME_NONCLIENT + } + + w32.TrackMouseEvent(&w32.TRACKMOUSEEVENT{ + CbSize: uint32(unsafe.Sizeof(w32.TRACKMOUSEEVENT{})), + DwFlags: flags, + HwndTrack: w.hwnd, + }) +} + +func (w *windowsWebviewWindow) compositionMouseClientPoint(msg uint32, lparam uintptr) (int, int, bool) { + switch msg { + case w32.WM_MOUSELEAVE: + return 0, 0, true + case w32.WM_MOUSEWHEEL, w32.WM_MOUSEHWHEEL: + return w32.ScreenToClient(w.hwnd, int(w32.GET_X_LPARAM(lparam)), int(w32.GET_Y_LPARAM(lparam))) + default: + return int(w32.GET_X_LPARAM(lparam)), int(w32.GET_Y_LPARAM(lparam)), true + } +} + +func (w *windowsWebviewWindow) updateCompositionMouseCapture(msg uint32) { + if isCompositionMouseButtonDown(msg) { + if w32.GetCapture() != w.hwnd { + w32.SetCapture(w.hwnd) + } + return + } + + if isCompositionMouseButtonUp(msg) && w32.GetCapture() == w.hwnd { + w32.ReleaseCapture() + + // Button release ends the synthetic caption-button interaction. + w.activeNonClientButton = 0 + w.activeNonClientButtonHovered = false + } +} + +// updateActiveNonClientButtonHover returns whether the current move should be +// forwarded to WebView. It sends a single LEAVE when capture moves off the +// originally pressed caption button, matching native caption-button behavior. +func (w *windowsWebviewWindow) updateActiveNonClientButtonHover() bool { + screenX, screenY, ok := w32.GetCursorPos() + if !ok { + return true + } + + hitTest, ok := w.nonClientHitTestFromScreen(screenX, screenY) + hovered := ok && hitTest == w.activeNonClientButton + if hovered { + w.activeNonClientButtonHovered = true + return true + } + + if w.activeNonClientButtonHovered { + _ = w.chromium.SendMouseInput( + edge.COREWEBVIEW2_MOUSE_EVENT_KIND_LEAVE, + edge.COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS_NONE, + 0, + 0, + 0, + ) + w.activeNonClientButtonHovered = false + } + + return false +} + +func nonClientLeftButtonMouseEvent(msg uint32) (edge.COREWEBVIEW2_MOUSE_EVENT_KIND, edge.COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS, bool) { + switch msg { + case w32.WM_NCLBUTTONDOWN: + return edge.COREWEBVIEW2_MOUSE_EVENT_KIND_LEFT_BUTTON_DOWN, + edge.COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS_LEFT_BUTTON, + true + case w32.WM_NCLBUTTONUP: + return edge.COREWEBVIEW2_MOUSE_EVENT_KIND_LEFT_BUTTON_UP, + edge.COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS_NONE, + true + case w32.WM_NCLBUTTONDBLCLK: + return edge.COREWEBVIEW2_MOUSE_EVENT_KIND_LEFT_BUTTON_DOUBLE_CLICK, + edge.COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS_LEFT_BUTTON, + true + default: + return 0, 0, false + } +} + +func isCompositionMouseButtonDown(msg uint32) bool { + switch msg { + case w32.WM_LBUTTONDOWN, + w32.WM_NCLBUTTONDOWN, + w32.WM_NCLBUTTONDBLCLK, + w32.WM_RBUTTONDOWN, + w32.WM_MBUTTONDOWN, + w32.WM_XBUTTONDOWN: + return true + default: + return false + } +} + +func isCompositionMouseButtonUp(msg uint32) bool { + switch msg { + case w32.WM_LBUTTONUP, + w32.WM_NCLBUTTONUP, + w32.WM_RBUTTONUP, + w32.WM_MBUTTONUP, + w32.WM_XBUTTONUP: + return true + default: + return false + } +} + +func webviewCompositionMouseEventKind(msg uint32) (edge.COREWEBVIEW2_MOUSE_EVENT_KIND, bool) { + switch msg { + case w32.WM_MOUSELEAVE: + return edge.COREWEBVIEW2_MOUSE_EVENT_KIND_LEAVE, true + case w32.WM_MOUSEMOVE: + return edge.COREWEBVIEW2_MOUSE_EVENT_KIND_MOVE, true + case w32.WM_LBUTTONDOWN: + return edge.COREWEBVIEW2_MOUSE_EVENT_KIND_LEFT_BUTTON_DOWN, true + case w32.WM_LBUTTONUP: + return edge.COREWEBVIEW2_MOUSE_EVENT_KIND_LEFT_BUTTON_UP, true + case w32.WM_LBUTTONDBLCLK: + return edge.COREWEBVIEW2_MOUSE_EVENT_KIND_LEFT_BUTTON_DOUBLE_CLICK, true + case w32.WM_RBUTTONDOWN: + return edge.COREWEBVIEW2_MOUSE_EVENT_KIND_RIGHT_BUTTON_DOWN, true + case w32.WM_RBUTTONUP: + return edge.COREWEBVIEW2_MOUSE_EVENT_KIND_RIGHT_BUTTON_UP, true + case w32.WM_RBUTTONDBLCLK: + return edge.COREWEBVIEW2_MOUSE_EVENT_KIND_RIGHT_BUTTON_DOUBLE_CLICK, true + case w32.WM_MBUTTONDOWN: + return edge.COREWEBVIEW2_MOUSE_EVENT_KIND_MIDDLE_BUTTON_DOWN, true + case w32.WM_MBUTTONUP: + return edge.COREWEBVIEW2_MOUSE_EVENT_KIND_MIDDLE_BUTTON_UP, true + case w32.WM_MBUTTONDBLCLK: + return edge.COREWEBVIEW2_MOUSE_EVENT_KIND_MIDDLE_BUTTON_DOUBLE_CLICK, true + case w32.WM_XBUTTONDOWN: + return edge.COREWEBVIEW2_MOUSE_EVENT_KIND_X_BUTTON_DOWN, true + case w32.WM_XBUTTONUP: + return edge.COREWEBVIEW2_MOUSE_EVENT_KIND_X_BUTTON_UP, true + case w32.WM_XBUTTONDBLCLK: + return edge.COREWEBVIEW2_MOUSE_EVENT_KIND_X_BUTTON_DOUBLE_CLICK, true + case w32.WM_MOUSEWHEEL: + return edge.COREWEBVIEW2_MOUSE_EVENT_KIND_WHEEL, true + case w32.WM_MOUSEHWHEEL: + return edge.COREWEBVIEW2_MOUSE_EVENT_KIND_HORIZONTAL_WHEEL, true + default: + return 0, false + } +} diff --git a/v3/pkg/application/webview_window_windows_production.go b/v3/pkg/application/webview_window_windows_production.go index 4ca89c1ea5d..289a339ded3 100644 --- a/v3/pkg/application/webview_window_windows_production.go +++ b/v3/pkg/application/webview_window_windows_production.go @@ -1,4 +1,4 @@ -//go:build windows && production && !devtools +//go:build windows && !server && production && !devtools package application diff --git a/v3/pkg/events/events.go b/v3/pkg/events/events.go index f24a85fb5cb..d09ae67ecee 100644 --- a/v3/pkg/events/events.go +++ b/v3/pkg/events/events.go @@ -1,601 +1,601 @@ package events type ApplicationEventType uint -type WindowEventType uint +type WindowEventType uint var Common = newCommonEvents() type commonEvents struct { - ApplicationOpenedWithFile ApplicationEventType - ApplicationStarted ApplicationEventType + ApplicationOpenedWithFile ApplicationEventType + ApplicationStarted ApplicationEventType ApplicationLaunchedWithUrl ApplicationEventType - ThemeChanged ApplicationEventType - SystemDidWake ApplicationEventType - SystemWillSleep ApplicationEventType - WindowClosing WindowEventType - WindowDidMove WindowEventType - WindowDidResize WindowEventType - WindowDPIChanged WindowEventType - WindowFilesDropped WindowEventType - WindowFocus WindowEventType - WindowFullscreen WindowEventType - WindowHide WindowEventType - WindowLostFocus WindowEventType - WindowMaximise WindowEventType - WindowMinimise WindowEventType - WindowToggleFrameless WindowEventType - WindowRestore WindowEventType - WindowRuntimeReady WindowEventType - WindowShow WindowEventType - WindowUnFullscreen WindowEventType - WindowUnMaximise WindowEventType - WindowUnMinimise WindowEventType - WindowZoom WindowEventType - WindowZoomIn WindowEventType - WindowZoomOut WindowEventType - WindowZoomReset WindowEventType - BatteryChanged ApplicationEventType - NetworkChanged ApplicationEventType - ScreenLocked ApplicationEventType - ScreenUnlocked ApplicationEventType - LowMemory ApplicationEventType + ThemeChanged ApplicationEventType + SystemDidWake ApplicationEventType + SystemWillSleep ApplicationEventType + WindowClosing WindowEventType + WindowDidMove WindowEventType + WindowDidResize WindowEventType + WindowDPIChanged WindowEventType + WindowFilesDropped WindowEventType + WindowFocus WindowEventType + WindowFullscreen WindowEventType + WindowHide WindowEventType + WindowLostFocus WindowEventType + WindowMaximise WindowEventType + WindowMinimise WindowEventType + WindowToggleFrameless WindowEventType + WindowRestore WindowEventType + WindowRuntimeReady WindowEventType + WindowShow WindowEventType + WindowUnFullscreen WindowEventType + WindowUnMaximise WindowEventType + WindowUnMinimise WindowEventType + WindowZoom WindowEventType + WindowZoomIn WindowEventType + WindowZoomOut WindowEventType + WindowZoomReset WindowEventType + BatteryChanged ApplicationEventType + NetworkChanged ApplicationEventType + ScreenLocked ApplicationEventType + ScreenUnlocked ApplicationEventType + LowMemory ApplicationEventType } func newCommonEvents() commonEvents { return commonEvents{ - ApplicationOpenedWithFile: 1024, - ApplicationStarted: 1025, + ApplicationOpenedWithFile: 1024, + ApplicationStarted: 1025, ApplicationLaunchedWithUrl: 1026, - ThemeChanged: 1027, - SystemDidWake: 1028, - SystemWillSleep: 1029, - WindowClosing: 1030, - WindowDidMove: 1031, - WindowDidResize: 1032, - WindowDPIChanged: 1033, - WindowFilesDropped: 1034, - WindowFocus: 1035, - WindowFullscreen: 1036, - WindowHide: 1037, - WindowLostFocus: 1038, - WindowMaximise: 1039, - WindowMinimise: 1040, - WindowToggleFrameless: 1041, - WindowRestore: 1042, - WindowRuntimeReady: 1043, - WindowShow: 1044, - WindowUnFullscreen: 1045, - WindowUnMaximise: 1046, - WindowUnMinimise: 1047, - WindowZoom: 1048, - WindowZoomIn: 1049, - WindowZoomOut: 1050, - WindowZoomReset: 1051, - BatteryChanged: 1287, - NetworkChanged: 1288, - ScreenLocked: 1289, - ScreenUnlocked: 1290, - LowMemory: 1291, + ThemeChanged: 1027, + SystemDidWake: 1028, + SystemWillSleep: 1029, + WindowClosing: 1030, + WindowDidMove: 1031, + WindowDidResize: 1032, + WindowDPIChanged: 1033, + WindowFilesDropped: 1034, + WindowFocus: 1035, + WindowFullscreen: 1036, + WindowHide: 1037, + WindowLostFocus: 1038, + WindowMaximise: 1039, + WindowMinimise: 1040, + WindowToggleFrameless: 1041, + WindowRestore: 1042, + WindowRuntimeReady: 1043, + WindowShow: 1044, + WindowUnFullscreen: 1045, + WindowUnMaximise: 1046, + WindowUnMinimise: 1047, + WindowZoom: 1048, + WindowZoomIn: 1049, + WindowZoomOut: 1050, + WindowZoomReset: 1051, + BatteryChanged: 1287, + NetworkChanged: 1288, + ScreenLocked: 1289, + ScreenUnlocked: 1290, + LowMemory: 1291, } } var Linux = newLinuxEvents() type linuxEvents struct { - ApplicationStartup ApplicationEventType - SystemDidWake ApplicationEventType - SystemThemeChanged ApplicationEventType - SystemWillSleep ApplicationEventType - WindowDeleteEvent WindowEventType - WindowDidMove WindowEventType - WindowDidResize WindowEventType - WindowFocusIn WindowEventType - WindowFocusOut WindowEventType - WindowLoadStarted WindowEventType + ApplicationStartup ApplicationEventType + SystemDidWake ApplicationEventType + SystemThemeChanged ApplicationEventType + SystemWillSleep ApplicationEventType + WindowDeleteEvent WindowEventType + WindowDidMove WindowEventType + WindowDidResize WindowEventType + WindowFocusIn WindowEventType + WindowFocusOut WindowEventType + WindowLoadStarted WindowEventType WindowLoadRedirected WindowEventType - WindowLoadCommitted WindowEventType - WindowLoadFinished WindowEventType + WindowLoadCommitted WindowEventType + WindowLoadFinished WindowEventType } func newLinuxEvents() linuxEvents { return linuxEvents{ - ApplicationStartup: 1052, - SystemDidWake: 1053, - SystemThemeChanged: 1054, - SystemWillSleep: 1055, - WindowDeleteEvent: 1056, - WindowDidMove: 1057, - WindowDidResize: 1058, - WindowFocusIn: 1059, - WindowFocusOut: 1060, - WindowLoadStarted: 1061, + ApplicationStartup: 1052, + SystemDidWake: 1053, + SystemThemeChanged: 1054, + SystemWillSleep: 1055, + WindowDeleteEvent: 1056, + WindowDidMove: 1057, + WindowDidResize: 1058, + WindowFocusIn: 1059, + WindowFocusOut: 1060, + WindowLoadStarted: 1061, WindowLoadRedirected: 1062, - WindowLoadCommitted: 1063, - WindowLoadFinished: 1064, + WindowLoadCommitted: 1063, + WindowLoadFinished: 1064, } } var Mac = newMacEvents() type macEvents struct { - ApplicationDidBecomeActive ApplicationEventType - ApplicationDidChangeBackingProperties ApplicationEventType - ApplicationDidChangeEffectiveAppearance ApplicationEventType - ApplicationDidChangeIcon ApplicationEventType - ApplicationDidChangeOcclusionState ApplicationEventType - ApplicationDidChangeScreenParameters ApplicationEventType - ApplicationDidChangeStatusBarFrame ApplicationEventType - ApplicationDidChangeStatusBarOrientation ApplicationEventType - ApplicationDidChangeTheme ApplicationEventType - ApplicationDidFinishLaunching ApplicationEventType - ApplicationDidHide ApplicationEventType - ApplicationDidResignActive ApplicationEventType - ApplicationDidUnhide ApplicationEventType - ApplicationDidUpdate ApplicationEventType - ApplicationDidWake ApplicationEventType - ApplicationScreensDidSleep ApplicationEventType - ApplicationScreensDidWake ApplicationEventType - ApplicationShouldHandleReopen ApplicationEventType - ApplicationWillBecomeActive ApplicationEventType - ApplicationWillFinishLaunching ApplicationEventType - ApplicationWillHide ApplicationEventType - ApplicationWillResignActive ApplicationEventType - ApplicationWillSleep ApplicationEventType - ApplicationWillTerminate ApplicationEventType - ApplicationWillUnhide ApplicationEventType - ApplicationWillUpdate ApplicationEventType - MenuDidAddItem ApplicationEventType - MenuDidBeginTracking ApplicationEventType - MenuDidClose ApplicationEventType - MenuDidDisplayItem ApplicationEventType - MenuDidEndTracking ApplicationEventType - MenuDidHighlightItem ApplicationEventType - MenuDidOpen ApplicationEventType - MenuDidPopUp ApplicationEventType - MenuDidRemoveItem ApplicationEventType - MenuDidSendAction ApplicationEventType - MenuDidSendActionToItem ApplicationEventType - MenuDidUpdate ApplicationEventType - MenuWillAddItem ApplicationEventType - MenuWillBeginTracking ApplicationEventType - MenuWillDisplayItem ApplicationEventType - MenuWillEndTracking ApplicationEventType - MenuWillHighlightItem ApplicationEventType - MenuWillOpen ApplicationEventType - MenuWillPopUp ApplicationEventType - MenuWillRemoveItem ApplicationEventType - MenuWillSendAction ApplicationEventType - MenuWillSendActionToItem ApplicationEventType - MenuWillUpdate ApplicationEventType - WebViewDidCommitNavigation WindowEventType - WebViewDidFinishNavigation WindowEventType + ApplicationDidBecomeActive ApplicationEventType + ApplicationDidChangeBackingProperties ApplicationEventType + ApplicationDidChangeEffectiveAppearance ApplicationEventType + ApplicationDidChangeIcon ApplicationEventType + ApplicationDidChangeOcclusionState ApplicationEventType + ApplicationDidChangeScreenParameters ApplicationEventType + ApplicationDidChangeStatusBarFrame ApplicationEventType + ApplicationDidChangeStatusBarOrientation ApplicationEventType + ApplicationDidChangeTheme ApplicationEventType + ApplicationDidFinishLaunching ApplicationEventType + ApplicationDidHide ApplicationEventType + ApplicationDidResignActive ApplicationEventType + ApplicationDidUnhide ApplicationEventType + ApplicationDidUpdate ApplicationEventType + ApplicationDidWake ApplicationEventType + ApplicationScreensDidSleep ApplicationEventType + ApplicationScreensDidWake ApplicationEventType + ApplicationShouldHandleReopen ApplicationEventType + ApplicationWillBecomeActive ApplicationEventType + ApplicationWillFinishLaunching ApplicationEventType + ApplicationWillHide ApplicationEventType + ApplicationWillResignActive ApplicationEventType + ApplicationWillSleep ApplicationEventType + ApplicationWillTerminate ApplicationEventType + ApplicationWillUnhide ApplicationEventType + ApplicationWillUpdate ApplicationEventType + MenuDidAddItem ApplicationEventType + MenuDidBeginTracking ApplicationEventType + MenuDidClose ApplicationEventType + MenuDidDisplayItem ApplicationEventType + MenuDidEndTracking ApplicationEventType + MenuDidHighlightItem ApplicationEventType + MenuDidOpen ApplicationEventType + MenuDidPopUp ApplicationEventType + MenuDidRemoveItem ApplicationEventType + MenuDidSendAction ApplicationEventType + MenuDidSendActionToItem ApplicationEventType + MenuDidUpdate ApplicationEventType + MenuWillAddItem ApplicationEventType + MenuWillBeginTracking ApplicationEventType + MenuWillDisplayItem ApplicationEventType + MenuWillEndTracking ApplicationEventType + MenuWillHighlightItem ApplicationEventType + MenuWillOpen ApplicationEventType + MenuWillPopUp ApplicationEventType + MenuWillRemoveItem ApplicationEventType + MenuWillSendAction ApplicationEventType + MenuWillSendActionToItem ApplicationEventType + MenuWillUpdate ApplicationEventType + WebViewDidCommitNavigation WindowEventType + WebViewDidFinishNavigation WindowEventType WebViewDidReceiveServerRedirectForProvisionalNavigation WindowEventType - WebViewDidStartProvisionalNavigation WindowEventType - WindowDidBecomeKey WindowEventType - WindowDidBecomeMain WindowEventType - WindowDidBeginSheet WindowEventType - WindowDidChangeAlpha WindowEventType - WindowDidChangeBackingLocation WindowEventType - WindowDidChangeBackingProperties WindowEventType - WindowDidChangeCollectionBehavior WindowEventType - WindowDidChangeEffectiveAppearance WindowEventType - WindowDidChangeOcclusionState WindowEventType - WindowDidChangeOrderingMode WindowEventType - WindowDidChangeScreen WindowEventType - WindowDidChangeScreenParameters WindowEventType - WindowDidChangeScreenProfile WindowEventType - WindowDidChangeScreenSpace WindowEventType - WindowDidChangeScreenSpaceProperties WindowEventType - WindowDidChangeSharingType WindowEventType - WindowDidChangeSpace WindowEventType - WindowDidChangeSpaceOrderingMode WindowEventType - WindowDidChangeTitle WindowEventType - WindowDidChangeToolbar WindowEventType - WindowDidDeminiaturize WindowEventType - WindowDidEndSheet WindowEventType - WindowDidEnterFullScreen WindowEventType - WindowDidEnterVersionBrowser WindowEventType - WindowDidExitFullScreen WindowEventType - WindowDidExitVersionBrowser WindowEventType - WindowDidExpose WindowEventType - WindowDidFocus WindowEventType - WindowDidMiniaturize WindowEventType - WindowDidMove WindowEventType - WindowDidOrderOffScreen WindowEventType - WindowDidOrderOnScreen WindowEventType - WindowDidResignKey WindowEventType - WindowDidResignMain WindowEventType - WindowDidResize WindowEventType - WindowDidUpdate WindowEventType - WindowDidUpdateAlpha WindowEventType - WindowDidUpdateCollectionBehavior WindowEventType - WindowDidUpdateCollectionProperties WindowEventType - WindowDidUpdateShadow WindowEventType - WindowDidUpdateTitle WindowEventType - WindowDidUpdateToolbar WindowEventType - WindowDidZoom WindowEventType - WindowFileDraggingEntered WindowEventType - WindowFileDraggingExited WindowEventType - WindowFileDraggingPerformed WindowEventType - WindowHide WindowEventType - WindowMaximise WindowEventType - WindowUnMaximise WindowEventType - WindowMinimise WindowEventType - WindowUnMinimise WindowEventType - WindowShouldClose WindowEventType - WindowShow WindowEventType - WindowWillBecomeKey WindowEventType - WindowWillBecomeMain WindowEventType - WindowWillBeginSheet WindowEventType - WindowWillChangeOrderingMode WindowEventType - WindowWillClose WindowEventType - WindowWillDeminiaturize WindowEventType - WindowWillEnterFullScreen WindowEventType - WindowWillEnterVersionBrowser WindowEventType - WindowWillExitFullScreen WindowEventType - WindowWillExitVersionBrowser WindowEventType - WindowWillFocus WindowEventType - WindowWillMiniaturize WindowEventType - WindowWillMove WindowEventType - WindowWillOrderOffScreen WindowEventType - WindowWillOrderOnScreen WindowEventType - WindowWillResignMain WindowEventType - WindowWillResize WindowEventType - WindowWillUnfocus WindowEventType - WindowWillUpdate WindowEventType - WindowWillUpdateAlpha WindowEventType - WindowWillUpdateCollectionBehavior WindowEventType - WindowWillUpdateCollectionProperties WindowEventType - WindowWillUpdateShadow WindowEventType - WindowWillUpdateTitle WindowEventType - WindowWillUpdateToolbar WindowEventType - WindowWillUpdateVisibility WindowEventType - WindowWillUseStandardFrame WindowEventType - WindowZoomIn WindowEventType - WindowZoomOut WindowEventType - WindowZoomReset WindowEventType - WebViewWebContentProcessDidTerminate WindowEventType + WebViewDidStartProvisionalNavigation WindowEventType + WindowDidBecomeKey WindowEventType + WindowDidBecomeMain WindowEventType + WindowDidBeginSheet WindowEventType + WindowDidChangeAlpha WindowEventType + WindowDidChangeBackingLocation WindowEventType + WindowDidChangeBackingProperties WindowEventType + WindowDidChangeCollectionBehavior WindowEventType + WindowDidChangeEffectiveAppearance WindowEventType + WindowDidChangeOcclusionState WindowEventType + WindowDidChangeOrderingMode WindowEventType + WindowDidChangeScreen WindowEventType + WindowDidChangeScreenParameters WindowEventType + WindowDidChangeScreenProfile WindowEventType + WindowDidChangeScreenSpace WindowEventType + WindowDidChangeScreenSpaceProperties WindowEventType + WindowDidChangeSharingType WindowEventType + WindowDidChangeSpace WindowEventType + WindowDidChangeSpaceOrderingMode WindowEventType + WindowDidChangeTitle WindowEventType + WindowDidChangeToolbar WindowEventType + WindowDidDeminiaturize WindowEventType + WindowDidEndSheet WindowEventType + WindowDidEnterFullScreen WindowEventType + WindowDidEnterVersionBrowser WindowEventType + WindowDidExitFullScreen WindowEventType + WindowDidExitVersionBrowser WindowEventType + WindowDidExpose WindowEventType + WindowDidFocus WindowEventType + WindowDidMiniaturize WindowEventType + WindowDidMove WindowEventType + WindowDidOrderOffScreen WindowEventType + WindowDidOrderOnScreen WindowEventType + WindowDidResignKey WindowEventType + WindowDidResignMain WindowEventType + WindowDidResize WindowEventType + WindowDidUpdate WindowEventType + WindowDidUpdateAlpha WindowEventType + WindowDidUpdateCollectionBehavior WindowEventType + WindowDidUpdateCollectionProperties WindowEventType + WindowDidUpdateShadow WindowEventType + WindowDidUpdateTitle WindowEventType + WindowDidUpdateToolbar WindowEventType + WindowDidZoom WindowEventType + WindowFileDraggingEntered WindowEventType + WindowFileDraggingExited WindowEventType + WindowFileDraggingPerformed WindowEventType + WindowHide WindowEventType + WindowMaximise WindowEventType + WindowUnMaximise WindowEventType + WindowMinimise WindowEventType + WindowUnMinimise WindowEventType + WindowShouldClose WindowEventType + WindowShow WindowEventType + WindowWillBecomeKey WindowEventType + WindowWillBecomeMain WindowEventType + WindowWillBeginSheet WindowEventType + WindowWillChangeOrderingMode WindowEventType + WindowWillClose WindowEventType + WindowWillDeminiaturize WindowEventType + WindowWillEnterFullScreen WindowEventType + WindowWillEnterVersionBrowser WindowEventType + WindowWillExitFullScreen WindowEventType + WindowWillExitVersionBrowser WindowEventType + WindowWillFocus WindowEventType + WindowWillMiniaturize WindowEventType + WindowWillMove WindowEventType + WindowWillOrderOffScreen WindowEventType + WindowWillOrderOnScreen WindowEventType + WindowWillResignMain WindowEventType + WindowWillResize WindowEventType + WindowWillUnfocus WindowEventType + WindowWillUpdate WindowEventType + WindowWillUpdateAlpha WindowEventType + WindowWillUpdateCollectionBehavior WindowEventType + WindowWillUpdateCollectionProperties WindowEventType + WindowWillUpdateShadow WindowEventType + WindowWillUpdateTitle WindowEventType + WindowWillUpdateToolbar WindowEventType + WindowWillUpdateVisibility WindowEventType + WindowWillUseStandardFrame WindowEventType + WindowZoomIn WindowEventType + WindowZoomOut WindowEventType + WindowZoomReset WindowEventType + WebViewWebContentProcessDidTerminate WindowEventType } func newMacEvents() macEvents { return macEvents{ - ApplicationDidBecomeActive: 1065, - ApplicationDidChangeBackingProperties: 1066, - ApplicationDidChangeEffectiveAppearance: 1067, - ApplicationDidChangeIcon: 1068, - ApplicationDidChangeOcclusionState: 1069, - ApplicationDidChangeScreenParameters: 1070, - ApplicationDidChangeStatusBarFrame: 1071, + ApplicationDidBecomeActive: 1065, + ApplicationDidChangeBackingProperties: 1066, + ApplicationDidChangeEffectiveAppearance: 1067, + ApplicationDidChangeIcon: 1068, + ApplicationDidChangeOcclusionState: 1069, + ApplicationDidChangeScreenParameters: 1070, + ApplicationDidChangeStatusBarFrame: 1071, ApplicationDidChangeStatusBarOrientation: 1072, - ApplicationDidChangeTheme: 1073, - ApplicationDidFinishLaunching: 1074, - ApplicationDidHide: 1075, - ApplicationDidResignActive: 1076, - ApplicationDidUnhide: 1077, - ApplicationDidUpdate: 1078, - ApplicationDidWake: 1079, - ApplicationScreensDidSleep: 1080, - ApplicationScreensDidWake: 1081, - ApplicationShouldHandleReopen: 1082, - ApplicationWillBecomeActive: 1083, - ApplicationWillFinishLaunching: 1084, - ApplicationWillHide: 1085, - ApplicationWillResignActive: 1086, - ApplicationWillSleep: 1087, - ApplicationWillTerminate: 1088, - ApplicationWillUnhide: 1089, - ApplicationWillUpdate: 1090, - MenuDidAddItem: 1091, - MenuDidBeginTracking: 1092, - MenuDidClose: 1093, - MenuDidDisplayItem: 1094, - MenuDidEndTracking: 1095, - MenuDidHighlightItem: 1096, - MenuDidOpen: 1097, - MenuDidPopUp: 1098, - MenuDidRemoveItem: 1099, - MenuDidSendAction: 1100, - MenuDidSendActionToItem: 1101, - MenuDidUpdate: 1102, - MenuWillAddItem: 1103, - MenuWillBeginTracking: 1104, - MenuWillDisplayItem: 1105, - MenuWillEndTracking: 1106, - MenuWillHighlightItem: 1107, - MenuWillOpen: 1108, - MenuWillPopUp: 1109, - MenuWillRemoveItem: 1110, - MenuWillSendAction: 1111, - MenuWillSendActionToItem: 1112, - MenuWillUpdate: 1113, - WebViewDidCommitNavigation: 1114, - WebViewDidFinishNavigation: 1115, + ApplicationDidChangeTheme: 1073, + ApplicationDidFinishLaunching: 1074, + ApplicationDidHide: 1075, + ApplicationDidResignActive: 1076, + ApplicationDidUnhide: 1077, + ApplicationDidUpdate: 1078, + ApplicationDidWake: 1079, + ApplicationScreensDidSleep: 1080, + ApplicationScreensDidWake: 1081, + ApplicationShouldHandleReopen: 1082, + ApplicationWillBecomeActive: 1083, + ApplicationWillFinishLaunching: 1084, + ApplicationWillHide: 1085, + ApplicationWillResignActive: 1086, + ApplicationWillSleep: 1087, + ApplicationWillTerminate: 1088, + ApplicationWillUnhide: 1089, + ApplicationWillUpdate: 1090, + MenuDidAddItem: 1091, + MenuDidBeginTracking: 1092, + MenuDidClose: 1093, + MenuDidDisplayItem: 1094, + MenuDidEndTracking: 1095, + MenuDidHighlightItem: 1096, + MenuDidOpen: 1097, + MenuDidPopUp: 1098, + MenuDidRemoveItem: 1099, + MenuDidSendAction: 1100, + MenuDidSendActionToItem: 1101, + MenuDidUpdate: 1102, + MenuWillAddItem: 1103, + MenuWillBeginTracking: 1104, + MenuWillDisplayItem: 1105, + MenuWillEndTracking: 1106, + MenuWillHighlightItem: 1107, + MenuWillOpen: 1108, + MenuWillPopUp: 1109, + MenuWillRemoveItem: 1110, + MenuWillSendAction: 1111, + MenuWillSendActionToItem: 1112, + MenuWillUpdate: 1113, + WebViewDidCommitNavigation: 1114, + WebViewDidFinishNavigation: 1115, WebViewDidReceiveServerRedirectForProvisionalNavigation: 1116, - WebViewDidStartProvisionalNavigation: 1117, - WindowDidBecomeKey: 1118, - WindowDidBecomeMain: 1119, - WindowDidBeginSheet: 1120, - WindowDidChangeAlpha: 1121, - WindowDidChangeBackingLocation: 1122, - WindowDidChangeBackingProperties: 1123, - WindowDidChangeCollectionBehavior: 1124, - WindowDidChangeEffectiveAppearance: 1125, - WindowDidChangeOcclusionState: 1126, - WindowDidChangeOrderingMode: 1127, - WindowDidChangeScreen: 1128, - WindowDidChangeScreenParameters: 1129, - WindowDidChangeScreenProfile: 1130, - WindowDidChangeScreenSpace: 1131, - WindowDidChangeScreenSpaceProperties: 1132, - WindowDidChangeSharingType: 1133, - WindowDidChangeSpace: 1134, - WindowDidChangeSpaceOrderingMode: 1135, - WindowDidChangeTitle: 1136, - WindowDidChangeToolbar: 1137, - WindowDidDeminiaturize: 1138, - WindowDidEndSheet: 1139, - WindowDidEnterFullScreen: 1140, - WindowDidEnterVersionBrowser: 1141, - WindowDidExitFullScreen: 1142, - WindowDidExitVersionBrowser: 1143, - WindowDidExpose: 1144, - WindowDidFocus: 1145, - WindowDidMiniaturize: 1146, - WindowDidMove: 1147, - WindowDidOrderOffScreen: 1148, - WindowDidOrderOnScreen: 1149, - WindowDidResignKey: 1150, - WindowDidResignMain: 1151, - WindowDidResize: 1152, - WindowDidUpdate: 1153, - WindowDidUpdateAlpha: 1154, - WindowDidUpdateCollectionBehavior: 1155, - WindowDidUpdateCollectionProperties: 1156, - WindowDidUpdateShadow: 1157, - WindowDidUpdateTitle: 1158, - WindowDidUpdateToolbar: 1159, - WindowDidZoom: 1160, - WindowFileDraggingEntered: 1161, - WindowFileDraggingExited: 1162, - WindowFileDraggingPerformed: 1163, - WindowHide: 1164, - WindowMaximise: 1165, - WindowUnMaximise: 1166, - WindowMinimise: 1167, - WindowUnMinimise: 1168, - WindowShouldClose: 1169, - WindowShow: 1170, - WindowWillBecomeKey: 1171, - WindowWillBecomeMain: 1172, - WindowWillBeginSheet: 1173, - WindowWillChangeOrderingMode: 1174, - WindowWillClose: 1175, - WindowWillDeminiaturize: 1176, - WindowWillEnterFullScreen: 1177, - WindowWillEnterVersionBrowser: 1178, - WindowWillExitFullScreen: 1179, - WindowWillExitVersionBrowser: 1180, - WindowWillFocus: 1181, - WindowWillMiniaturize: 1182, - WindowWillMove: 1183, - WindowWillOrderOffScreen: 1184, - WindowWillOrderOnScreen: 1185, - WindowWillResignMain: 1186, - WindowWillResize: 1187, - WindowWillUnfocus: 1188, - WindowWillUpdate: 1189, - WindowWillUpdateAlpha: 1190, - WindowWillUpdateCollectionBehavior: 1191, - WindowWillUpdateCollectionProperties: 1192, - WindowWillUpdateShadow: 1193, - WindowWillUpdateTitle: 1194, - WindowWillUpdateToolbar: 1195, - WindowWillUpdateVisibility: 1196, - WindowWillUseStandardFrame: 1197, - WindowZoomIn: 1198, - WindowZoomOut: 1199, - WindowZoomReset: 1200, - WebViewWebContentProcessDidTerminate: 1267, + WebViewDidStartProvisionalNavigation: 1117, + WindowDidBecomeKey: 1118, + WindowDidBecomeMain: 1119, + WindowDidBeginSheet: 1120, + WindowDidChangeAlpha: 1121, + WindowDidChangeBackingLocation: 1122, + WindowDidChangeBackingProperties: 1123, + WindowDidChangeCollectionBehavior: 1124, + WindowDidChangeEffectiveAppearance: 1125, + WindowDidChangeOcclusionState: 1126, + WindowDidChangeOrderingMode: 1127, + WindowDidChangeScreen: 1128, + WindowDidChangeScreenParameters: 1129, + WindowDidChangeScreenProfile: 1130, + WindowDidChangeScreenSpace: 1131, + WindowDidChangeScreenSpaceProperties: 1132, + WindowDidChangeSharingType: 1133, + WindowDidChangeSpace: 1134, + WindowDidChangeSpaceOrderingMode: 1135, + WindowDidChangeTitle: 1136, + WindowDidChangeToolbar: 1137, + WindowDidDeminiaturize: 1138, + WindowDidEndSheet: 1139, + WindowDidEnterFullScreen: 1140, + WindowDidEnterVersionBrowser: 1141, + WindowDidExitFullScreen: 1142, + WindowDidExitVersionBrowser: 1143, + WindowDidExpose: 1144, + WindowDidFocus: 1145, + WindowDidMiniaturize: 1146, + WindowDidMove: 1147, + WindowDidOrderOffScreen: 1148, + WindowDidOrderOnScreen: 1149, + WindowDidResignKey: 1150, + WindowDidResignMain: 1151, + WindowDidResize: 1152, + WindowDidUpdate: 1153, + WindowDidUpdateAlpha: 1154, + WindowDidUpdateCollectionBehavior: 1155, + WindowDidUpdateCollectionProperties: 1156, + WindowDidUpdateShadow: 1157, + WindowDidUpdateTitle: 1158, + WindowDidUpdateToolbar: 1159, + WindowDidZoom: 1160, + WindowFileDraggingEntered: 1161, + WindowFileDraggingExited: 1162, + WindowFileDraggingPerformed: 1163, + WindowHide: 1164, + WindowMaximise: 1165, + WindowUnMaximise: 1166, + WindowMinimise: 1167, + WindowUnMinimise: 1168, + WindowShouldClose: 1169, + WindowShow: 1170, + WindowWillBecomeKey: 1171, + WindowWillBecomeMain: 1172, + WindowWillBeginSheet: 1173, + WindowWillChangeOrderingMode: 1174, + WindowWillClose: 1175, + WindowWillDeminiaturize: 1176, + WindowWillEnterFullScreen: 1177, + WindowWillEnterVersionBrowser: 1178, + WindowWillExitFullScreen: 1179, + WindowWillExitVersionBrowser: 1180, + WindowWillFocus: 1181, + WindowWillMiniaturize: 1182, + WindowWillMove: 1183, + WindowWillOrderOffScreen: 1184, + WindowWillOrderOnScreen: 1185, + WindowWillResignMain: 1186, + WindowWillResize: 1187, + WindowWillUnfocus: 1188, + WindowWillUpdate: 1189, + WindowWillUpdateAlpha: 1190, + WindowWillUpdateCollectionBehavior: 1191, + WindowWillUpdateCollectionProperties: 1192, + WindowWillUpdateShadow: 1193, + WindowWillUpdateTitle: 1194, + WindowWillUpdateToolbar: 1195, + WindowWillUpdateVisibility: 1196, + WindowWillUseStandardFrame: 1197, + WindowZoomIn: 1198, + WindowZoomOut: 1199, + WindowZoomReset: 1200, + WebViewWebContentProcessDidTerminate: 1267, } } var Windows = newWindowsEvents() type windowsEvents struct { - APMPowerSettingChange ApplicationEventType - APMPowerStatusChange ApplicationEventType - APMResumeAutomatic ApplicationEventType - APMResumeSuspend ApplicationEventType - APMSuspend ApplicationEventType - ApplicationStarted ApplicationEventType - SystemThemeChanged ApplicationEventType + APMPowerSettingChange ApplicationEventType + APMPowerStatusChange ApplicationEventType + APMResumeAutomatic ApplicationEventType + APMResumeSuspend ApplicationEventType + APMSuspend ApplicationEventType + ApplicationStarted ApplicationEventType + SystemThemeChanged ApplicationEventType WebViewNavigationCompleted WindowEventType - WindowActive WindowEventType - WindowBackgroundErase WindowEventType - WindowClickActive WindowEventType - WindowClosing WindowEventType - WindowDidMove WindowEventType - WindowDidResize WindowEventType - WindowDPIChanged WindowEventType - WindowDragDrop WindowEventType - WindowDragEnter WindowEventType - WindowDragLeave WindowEventType - WindowDragOver WindowEventType - WindowEndMove WindowEventType - WindowEndResize WindowEventType - WindowFullscreen WindowEventType - WindowHide WindowEventType - WindowInactive WindowEventType - WindowKeyDown WindowEventType - WindowKeyUp WindowEventType - WindowKillFocus WindowEventType - WindowNonClientHit WindowEventType - WindowNonClientMouseDown WindowEventType - WindowNonClientMouseLeave WindowEventType - WindowNonClientMouseMove WindowEventType - WindowNonClientMouseUp WindowEventType - WindowPaint WindowEventType - WindowRestore WindowEventType - WindowSetFocus WindowEventType - WindowShow WindowEventType - WindowStartMove WindowEventType - WindowStartResize WindowEventType - WindowUnFullscreen WindowEventType - WindowZOrderChanged WindowEventType - WindowMinimise WindowEventType - WindowUnMinimise WindowEventType - WindowMaximise WindowEventType - WindowUnMaximise WindowEventType + WindowActive WindowEventType + WindowBackgroundErase WindowEventType + WindowClickActive WindowEventType + WindowClosing WindowEventType + WindowDidMove WindowEventType + WindowDidResize WindowEventType + WindowDPIChanged WindowEventType + WindowDragDrop WindowEventType + WindowDragEnter WindowEventType + WindowDragLeave WindowEventType + WindowDragOver WindowEventType + WindowEndMove WindowEventType + WindowEndResize WindowEventType + WindowFullscreen WindowEventType + WindowHide WindowEventType + WindowInactive WindowEventType + WindowKeyDown WindowEventType + WindowKeyUp WindowEventType + WindowKillFocus WindowEventType + WindowNonClientHit WindowEventType + WindowNonClientMouseDown WindowEventType + WindowNonClientMouseLeave WindowEventType + WindowNonClientMouseMove WindowEventType + WindowNonClientMouseUp WindowEventType + WindowPaint WindowEventType + WindowRestore WindowEventType + WindowSetFocus WindowEventType + WindowShow WindowEventType + WindowStartMove WindowEventType + WindowStartResize WindowEventType + WindowUnFullscreen WindowEventType + WindowZOrderChanged WindowEventType + WindowMinimise WindowEventType + WindowUnMinimise WindowEventType + WindowMaximise WindowEventType + WindowUnMaximise WindowEventType } func newWindowsEvents() windowsEvents { return windowsEvents{ - APMPowerSettingChange: 1201, - APMPowerStatusChange: 1202, - APMResumeAutomatic: 1203, - APMResumeSuspend: 1204, - APMSuspend: 1205, - ApplicationStarted: 1206, - SystemThemeChanged: 1207, + APMPowerSettingChange: 1201, + APMPowerStatusChange: 1202, + APMResumeAutomatic: 1203, + APMResumeSuspend: 1204, + APMSuspend: 1205, + ApplicationStarted: 1206, + SystemThemeChanged: 1207, WebViewNavigationCompleted: 1208, - WindowActive: 1209, - WindowBackgroundErase: 1210, - WindowClickActive: 1211, - WindowClosing: 1212, - WindowDidMove: 1213, - WindowDidResize: 1214, - WindowDPIChanged: 1215, - WindowDragDrop: 1216, - WindowDragEnter: 1217, - WindowDragLeave: 1218, - WindowDragOver: 1219, - WindowEndMove: 1220, - WindowEndResize: 1221, - WindowFullscreen: 1222, - WindowHide: 1223, - WindowInactive: 1224, - WindowKeyDown: 1225, - WindowKeyUp: 1226, - WindowKillFocus: 1227, - WindowNonClientHit: 1228, - WindowNonClientMouseDown: 1229, - WindowNonClientMouseLeave: 1230, - WindowNonClientMouseMove: 1231, - WindowNonClientMouseUp: 1232, - WindowPaint: 1233, - WindowRestore: 1234, - WindowSetFocus: 1235, - WindowShow: 1236, - WindowStartMove: 1237, - WindowStartResize: 1238, - WindowUnFullscreen: 1239, - WindowZOrderChanged: 1240, - WindowMinimise: 1241, - WindowUnMinimise: 1242, - WindowMaximise: 1243, - WindowUnMaximise: 1244, + WindowActive: 1209, + WindowBackgroundErase: 1210, + WindowClickActive: 1211, + WindowClosing: 1212, + WindowDidMove: 1213, + WindowDidResize: 1214, + WindowDPIChanged: 1215, + WindowDragDrop: 1216, + WindowDragEnter: 1217, + WindowDragLeave: 1218, + WindowDragOver: 1219, + WindowEndMove: 1220, + WindowEndResize: 1221, + WindowFullscreen: 1222, + WindowHide: 1223, + WindowInactive: 1224, + WindowKeyDown: 1225, + WindowKeyUp: 1226, + WindowKillFocus: 1227, + WindowNonClientHit: 1228, + WindowNonClientMouseDown: 1229, + WindowNonClientMouseLeave: 1230, + WindowNonClientMouseMove: 1231, + WindowNonClientMouseUp: 1232, + WindowPaint: 1233, + WindowRestore: 1234, + WindowSetFocus: 1235, + WindowShow: 1236, + WindowStartMove: 1237, + WindowStartResize: 1238, + WindowUnFullscreen: 1239, + WindowZOrderChanged: 1240, + WindowMinimise: 1241, + WindowUnMinimise: 1242, + WindowMaximise: 1243, + WindowUnMaximise: 1244, } } var IOS = newIOSEvents() type iosEvents struct { - ApplicationDidBecomeActive ApplicationEventType - ApplicationDidEnterBackground ApplicationEventType - ApplicationDidFinishLaunching ApplicationEventType - ApplicationDidReceiveMemoryWarning ApplicationEventType - ApplicationWillEnterForeground ApplicationEventType - ApplicationWillResignActive ApplicationEventType - ApplicationWillTerminate ApplicationEventType - WindowDidLoad WindowEventType - WindowWillAppear WindowEventType - WindowDidAppear WindowEventType - WindowWillDisappear WindowEventType - WindowDidDisappear WindowEventType - WindowSafeAreaInsetsChanged WindowEventType - WindowOrientationChanged WindowEventType - WindowTouchBegan WindowEventType - WindowTouchMoved WindowEventType - WindowTouchEnded WindowEventType - WindowTouchCancelled WindowEventType - WebViewDidStartNavigation WindowEventType - WebViewDidFinishNavigation WindowEventType - WebViewDidFailNavigation WindowEventType + ApplicationDidBecomeActive ApplicationEventType + ApplicationDidEnterBackground ApplicationEventType + ApplicationDidFinishLaunching ApplicationEventType + ApplicationDidReceiveMemoryWarning ApplicationEventType + ApplicationWillEnterForeground ApplicationEventType + ApplicationWillResignActive ApplicationEventType + ApplicationWillTerminate ApplicationEventType + WindowDidLoad WindowEventType + WindowWillAppear WindowEventType + WindowDidAppear WindowEventType + WindowWillDisappear WindowEventType + WindowDidDisappear WindowEventType + WindowSafeAreaInsetsChanged WindowEventType + WindowOrientationChanged WindowEventType + WindowTouchBegan WindowEventType + WindowTouchMoved WindowEventType + WindowTouchEnded WindowEventType + WindowTouchCancelled WindowEventType + WebViewDidStartNavigation WindowEventType + WebViewDidFinishNavigation WindowEventType + WebViewDidFailNavigation WindowEventType WebViewDecidePolicyForNavigationAction WindowEventType - BatteryChanged ApplicationEventType - NetworkChanged ApplicationEventType - ThemeChanged ApplicationEventType - ScreenLocked ApplicationEventType - ScreenUnlocked ApplicationEventType + BatteryChanged ApplicationEventType + NetworkChanged ApplicationEventType + ThemeChanged ApplicationEventType + ScreenLocked ApplicationEventType + ScreenUnlocked ApplicationEventType } func newIOSEvents() iosEvents { return iosEvents{ - ApplicationDidBecomeActive: 1245, - ApplicationDidEnterBackground: 1246, - ApplicationDidFinishLaunching: 1247, - ApplicationDidReceiveMemoryWarning: 1248, - ApplicationWillEnterForeground: 1249, - ApplicationWillResignActive: 1250, - ApplicationWillTerminate: 1251, - WindowDidLoad: 1252, - WindowWillAppear: 1253, - WindowDidAppear: 1254, - WindowWillDisappear: 1255, - WindowDidDisappear: 1256, - WindowSafeAreaInsetsChanged: 1257, - WindowOrientationChanged: 1258, - WindowTouchBegan: 1259, - WindowTouchMoved: 1260, - WindowTouchEnded: 1261, - WindowTouchCancelled: 1262, - WebViewDidStartNavigation: 1263, - WebViewDidFinishNavigation: 1264, - WebViewDidFailNavigation: 1265, + ApplicationDidBecomeActive: 1245, + ApplicationDidEnterBackground: 1246, + ApplicationDidFinishLaunching: 1247, + ApplicationDidReceiveMemoryWarning: 1248, + ApplicationWillEnterForeground: 1249, + ApplicationWillResignActive: 1250, + ApplicationWillTerminate: 1251, + WindowDidLoad: 1252, + WindowWillAppear: 1253, + WindowDidAppear: 1254, + WindowWillDisappear: 1255, + WindowDidDisappear: 1256, + WindowSafeAreaInsetsChanged: 1257, + WindowOrientationChanged: 1258, + WindowTouchBegan: 1259, + WindowTouchMoved: 1260, + WindowTouchEnded: 1261, + WindowTouchCancelled: 1262, + WebViewDidStartNavigation: 1263, + WebViewDidFinishNavigation: 1264, + WebViewDidFailNavigation: 1265, WebViewDecidePolicyForNavigationAction: 1266, - BatteryChanged: 1277, - NetworkChanged: 1278, - ThemeChanged: 1279, - ScreenLocked: 1280, - ScreenUnlocked: 1281, + BatteryChanged: 1277, + NetworkChanged: 1278, + ThemeChanged: 1279, + ScreenLocked: 1280, + ScreenUnlocked: 1281, } } var Android = newAndroidEvents() type androidEvents struct { - ActivityCreated ApplicationEventType - ActivityStarted ApplicationEventType - ActivityResumed ApplicationEventType - ActivityPaused ApplicationEventType - ActivityStopped ApplicationEventType - ActivityDestroyed ApplicationEventType + ActivityCreated ApplicationEventType + ActivityStarted ApplicationEventType + ActivityResumed ApplicationEventType + ActivityPaused ApplicationEventType + ActivityStopped ApplicationEventType + ActivityDestroyed ApplicationEventType ApplicationLowMemory ApplicationEventType - WebViewPageStarted WindowEventType - WebViewPageFinished WindowEventType - BatteryChanged ApplicationEventType - NetworkChanged ApplicationEventType - ThemeChanged ApplicationEventType - ScreenLocked ApplicationEventType - ScreenUnlocked ApplicationEventType + WebViewPageStarted WindowEventType + WebViewPageFinished WindowEventType + BatteryChanged ApplicationEventType + NetworkChanged ApplicationEventType + ThemeChanged ApplicationEventType + ScreenLocked ApplicationEventType + ScreenUnlocked ApplicationEventType } func newAndroidEvents() androidEvents { return androidEvents{ - ActivityCreated: 1268, - ActivityStarted: 1269, - ActivityResumed: 1270, - ActivityPaused: 1271, - ActivityStopped: 1272, - ActivityDestroyed: 1273, + ActivityCreated: 1268, + ActivityStarted: 1269, + ActivityResumed: 1270, + ActivityPaused: 1271, + ActivityStopped: 1272, + ActivityDestroyed: 1273, ApplicationLowMemory: 1274, - WebViewPageStarted: 1275, - WebViewPageFinished: 1276, - BatteryChanged: 1282, - NetworkChanged: 1283, - ThemeChanged: 1284, - ScreenLocked: 1285, - ScreenUnlocked: 1286, + WebViewPageStarted: 1275, + WebViewPageFinished: 1276, + BatteryChanged: 1282, + NetworkChanged: 1283, + ThemeChanged: 1284, + ScreenLocked: 1285, + ScreenUnlocked: 1286, } } @@ -873,4 +873,3 @@ var eventToJS = map[uint]string{ 1290: "common:ScreenUnlocked", 1291: "common:LowMemory", } - diff --git a/v3/pkg/w32/dwmapi.go b/v3/pkg/w32/dwmapi.go index 1b911efc316..d66d17c7013 100644 --- a/v3/pkg/w32/dwmapi.go +++ b/v3/pkg/w32/dwmapi.go @@ -13,6 +13,7 @@ var ( procDwmSetWindowAttribute = moddwmapi.NewProc("DwmSetWindowAttribute") procDwmGetWindowAttribute = moddwmapi.NewProc("DwmGetWindowAttribute") procDwmExtendFrameIntoClientArea = moddwmapi.NewProc("DwmExtendFrameIntoClientArea") + procDwmDefWindowProc = moddwmapi.NewProc("DwmDefWindowProc") ) func DwmSetWindowAttribute(hwnd HWND, dwAttribute DWMWINDOWATTRIBUTE, pvAttribute unsafe.Pointer, cbAttribute uintptr) HRESULT { @@ -33,6 +34,18 @@ func DwmGetWindowAttribute(hwnd HWND, dwAttribute DWMWINDOWATTRIBUTE, pvAttribut return HRESULT(ret) } +func DwmDefWindowProc(hwnd HWND, msg uint32, wparam, lparam uintptr) (uintptr, bool) { + var result uintptr + ret, _, _ := procDwmDefWindowProc.Call( + hwnd, + uintptr(msg), + wparam, + lparam, + uintptr(unsafe.Pointer(&result)), + ) + return result, ret != 0 +} + func dwmExtendFrameIntoClientArea(hwnd uintptr, margins *MARGINS) error { ret, _, _ := procDwmExtendFrameIntoClientArea.Call( hwnd, diff --git a/v3/pkg/w32/user32.go b/v3/pkg/w32/user32.go index 33696f67b99..203d5154688 100644 --- a/v3/pkg/w32/user32.go +++ b/v3/pkg/w32/user32.go @@ -52,9 +52,13 @@ var ( procScreenToClient = moduser32.NewProc("ScreenToClient") procCallWindowProc = moduser32.NewProc("CallWindowProcW") procSetWindowLong = moduser32.NewProc("SetWindowLongW") - procSetWindowLongPtr = moduser32.NewProc("SetWindowLongW") + // Wails v3 does not support 32-bit Windows. On 32-bit Windows these Ptr + // APIs are C macros over SetWindowLongW/GetWindowLongW and are not exported + // from user32.dll, so keep the real 64-bit exports here instead of adding a + // 386 fallback. + procSetWindowLongPtr = moduser32.NewProc("SetWindowLongPtrW") procGetWindowLong = moduser32.NewProc("GetWindowLongW") - procGetWindowLongPtr = moduser32.NewProc("GetWindowLongW") + procGetWindowLongPtr = moduser32.NewProc("GetWindowLongPtrW") procEnableWindow = moduser32.NewProc("EnableWindow") procIsWindowEnabled = moduser32.NewProc("IsWindowEnabled") procIsWindowVisible = moduser32.NewProc("IsWindowVisible") @@ -67,12 +71,14 @@ var ( procGetClientRect = moduser32.NewProc("GetClientRect") procGetDC = moduser32.NewProc("GetDC") procReleaseDC = moduser32.NewProc("ReleaseDC") + procGetCapture = moduser32.NewProc("GetCapture") procSetCapture = moduser32.NewProc("SetCapture") procReleaseCapture = moduser32.NewProc("ReleaseCapture") procGetWindowThreadProcessId = moduser32.NewProc("GetWindowThreadProcessId") procMessageBox = moduser32.NewProc("MessageBoxW") procMessageBoxIndirect = moduser32.NewProc("MessageBoxIndirectW") procGetSystemMetrics = moduser32.NewProc("GetSystemMetrics") + procGetSystemMetricsForDpi = moduser32.NewProc("GetSystemMetricsForDpi") procPostThreadMessageW = moduser32.NewProc("PostThreadMessageW") procRegisterHotKey = moduser32.NewProc("RegisterHotKey") procUnregisterHotKey = moduser32.NewProc("UnregisterHotKey") @@ -785,6 +791,11 @@ func SetCapture(hwnd HWND) HWND { return HWND(ret) } +func GetCapture() HWND { + ret, _, _ := procGetCapture.Call() + return HWND(ret) +} + func ReleaseCapture() bool { ret, _, _ := procReleaseCapture.Call() @@ -825,6 +836,18 @@ func GetSystemMetrics(index int) int { return int(ret) } +func HasGetSystemMetricsForDpiFunc() bool { + return procGetSystemMetricsForDpi.Find() == nil +} + +func GetSystemMetricsForDpi(index int, dpi UINT) int { + ret, _, _ := procGetSystemMetricsForDpi.Call( + uintptr(index), + uintptr(dpi)) + + return int(ret) +} + func GetSysColorBrush(nIndex int) HBRUSH { ret, _, _ := procGetSysColorBrush.Call(1, uintptr(nIndex), @@ -1550,6 +1573,18 @@ func TrackPopupMenu(hmenu HMENU, flags uint32, x, y int32, reserved int32, hwnd return ret != 0 } +func TrackPopupMenuCommand(hmenu HMENU, flags uint32, x, y int32, hwnd HWND, prcRect *RECT) uintptr { + ret, _, _ := procTrackPopupMenu.Call( + uintptr(hmenu), + uintptr(flags|TPM_RETURNCMD), + uintptr(x), + uintptr(y), + 0, + uintptr(hwnd), + uintptr(unsafe.Pointer(prcRect))) + return ret +} + // KeybdEvent synthesizes a keystroke. The system can use such a synthesized keystroke to generate a WM_KEYUP or WM_KEYDOWN message. // bVk: Virtual-key code // bScan: Hardware scan code diff --git a/v3/pkg/w32/window.go b/v3/pkg/w32/window.go index c26ec414d1e..fff2d93f2b6 100644 --- a/v3/pkg/w32/window.go +++ b/v3/pkg/w32/window.go @@ -43,6 +43,7 @@ var Fatal func(error) const ( GCLP_HBRBACKGROUND int32 = -10 + GCLP_HCURSOR int32 = -12 GCLP_HICON int32 = -14 ) @@ -63,8 +64,12 @@ func ExtendFrameIntoClientArea(hwnd uintptr, extend bool) error { // are shown if transparent ant translucent. var margins MARGINS if extend { - margins = MARGINS{1, 1, 1, 1} // Only extend 1 pixel to have the default frame styling but no caption buttons + margins = MARGINS{1, 1, 1, 1} } + return ExtendFrameIntoClientAreaWithMargins(hwnd, margins) +} + +func ExtendFrameIntoClientAreaWithMargins(hwnd uintptr, margins MARGINS) error { if err := dwmExtendFrameIntoClientArea(hwnd, &margins); err != nil { return fmt.Errorf("DwmExtendFrameIntoClientArea failed: %s", err) } @@ -114,6 +119,10 @@ func SetApplicationIcon(hwnd uintptr, icon HICON) { setClassLongPtr(hwnd, GCLP_HICON, icon) } +func SetClassCursor(hwnd uintptr, cursor HCURSOR) { + setClassLongPtr(hwnd, GCLP_HCURSOR, cursor) +} + func SetBackgroundColour(hwnd uintptr, r, g, b uint8) { col := uint32(r) | uint32(g)<<8 | uint32(b)<<16 hbrush, _, _ := procCreateSolidBrush.Call(uintptr(col)) @@ -192,7 +201,7 @@ func MustStringToUTF16uintptr(input string) uintptr { } // MustStringToUTF16 converts s to UTF-16 encoding, stripping any embedded NULs and panicking on error. -// +// // The returned slice is suitable for Windows API calls that expect a UTF-16 encoded string. func MustStringToUTF16(input string) []uint16 { input = stripNulls(input) @@ -339,6 +348,11 @@ func EnableCloseButton(hwnd HWND) error { return nil } +func GetSystemMenu(hwnd HWND, revert bool) HMENU { + ret, _, _ := getSystemMenu.Call(hwnd, uintptr(BoolToBOOL(revert))) + return HMENU(ret) +} + func FindWindowW(className, windowName *uint16) HWND { ret, _, _ := findWindow.Call( uintptr(unsafe.Pointer(className)), @@ -374,4 +388,4 @@ func SendMessageToWindow(hwnd HWND, msg string) { func GetMenu(hwnd HWND) HMENU { ret, _, _ := getMenuProc.Call(hwnd) return ret -} \ No newline at end of file +} diff --git a/v3/wep/README.md b/v3/wep/README.md index 63ea57c980a..55be7bfad90 100644 --- a/v3/wep/README.md +++ b/v3/wep/README.md @@ -11,10 +11,20 @@ Following this structured approach ensures transparency, community involvement, **NOTE**: This process is for proposing new functionality. For bug fixes, documentation improvements, and other minor changes, please follow the standard PR process. +## Do I Need a WEP? + +Not every change needs a proposal. As a rule of thumb: + +- **WEP required**: new public API, changes to existing API behaviour, breaking changes, new cross-platform functionality, or anything involving significant platform-specific work. +- **No WEP needed**: bug fixes, documentation, small additive options, internal refactoring. Use the standard PR process. + +If you are unsure, ask in the [Ideas](https://github.com/wailsapp/wails/discussions/categories/ideas) category on GitHub Discussions or on [Discord](https://discord.gg/JDdSxwjhGf). + ## Submission of Proposal ### 1. Idea Initiation +- **Gauge Interest (optional)**: Before writing a proposal, consider floating the idea in the [Ideas](https://github.com/wailsapp/wails/discussions/categories/ideas) category on GitHub Discussions or on [Discord](https://discord.gg/JDdSxwjhGf). It can catch overlap with existing plans before you invest time in a write-up. - **Document Your Idea**: - Create a new directory: `v3/wep/proposals/` with the name of your proposal. - Copy the WEP template located in `v3/wep/WEP_TEMPLATE.md` into `v3/wep/proposals//proposal.md`. @@ -30,9 +40,9 @@ Following this structured approach ensures transparency, community involvement, ### 3. Community Discussion -- **Share Your Proposal**: Present your proposal to the Wails community. Try to get support for the proposal to increase the chances of acceptance. If you are on the discord server, create a post in the [`#enhancement-proposals`](https://discord.gg/TA8kbQds95) channel. -- **Gather Feedback**: Refine your proposal based on community input. All feedback should be added as comments in the PR. -- **Show Support**: Agreement with the proposal should be indicated by adding a thumbs-up emoji to the PR. The more thumbs-up emojis, the more likely the proposal will be accepted. +- **Share Your Proposal**: The PR is the official place to discuss the proposal. Present it to the Wails community and try to get support for it to increase the chances of acceptance. If you are on the discord server, share it in the [`#enhancement-proposals`](https://discord.gg/TA8kbQds95) channel. +- **Gather Feedback**: Refine your proposal based on community input. All feedback should be added as comments on the PR so the discussion stays with the document. +- **Show Support**: Agreement with the proposal should be indicated by adding a thumbs-up reaction to the PR. The more support a proposal has, the more likely it is to be accepted. - **Iterate**: Make changes to the proposal based on feedback. - **Agree on an Implementor**: To avoid stagnant proposals, we require someone agree to implement it. This could be the proposer. - **Ready for Review**: Once the proposal is ready for review, change the PR status to `Ready for Review`. @@ -41,11 +51,20 @@ A minimum of 2 weeks should be given for community feedback and discussion. ### 4. Final Decision -- **Decision**: The Wails maintainers will make a final decision on the proposal based on community feedback and the proposal's merits. - - If accepted, the proposal will be assigned a WEP number and the PR merged. - - If rejected, the reasons will be provided in the PR comments. +- **Decision**: The Wails maintainers will make a final decision on the proposal based on community feedback and the proposal's merits. The decision is recorded as a comment on the PR in this format: + + ``` + **Decision**: Accepted / Rejected + **Decided by**: @maintainer(s) + **Rationale**: A short explanation of the decision. + ``` + +- **If accepted**: + - The proposal is assigned the next WEP number and its directory renamed to `NNNN-`. + - The proposal's status is updated to `Accepted`, it is added to the [WEP Index](#wep-index), and the PR is merged. +- **If rejected**: The PR is closed and the proposal recorded in the [WEP Index](#wep-index) with a link to the decision, so the outcome is easy to find if the idea comes up again. -*NOTE*: If a proposal has not met the required support or has been inactive for more than a month, it may be closed. +*NOTE*: If a proposal has not met the required support or has been inactive for more than a month, it may be closed as `Withdrawn`. ## Implementation of Proposal @@ -66,4 +85,16 @@ Once a proposal has been accepted and an implementation plan has been decided, t - **Review of PR**: Address any review comments. - **Merge**: The PR will be merged after satisfactory review. +- **Update the Status**: When the implementation PR merges, update the proposal's status to `Implemented` and add the implementation PR to the [WEP Index](#wep-index). + +*NOTE*: Acceptance requires a committed implementor. If implementation has not started within 3 months of acceptance, the proposal is marked as up for grabs in the WEP Index and anyone may take it on. + +## WEP Index + +| WEP | Title | Status | Proposal | Implementation | +|-----|-------|--------|----------|----------------| +| [0001](proposals/0001-titlebar-buttons/proposal.md) | Customising Window Controls | Implemented | [#3508](https://github.com/wailsapp/wails/pull/3508) | [#3508](https://github.com/wailsapp/wails/pull/3508) | + +**Statuses**: `Draft` (under discussion), `Accepted` (approved, awaiting implementation), `Implemented` (shipped), `Rejected` (declined), `Withdrawn` (closed by the author or for inactivity). + The WEP process ensures structured and collaborative enhancement of Wails. Adhere to this guide to contribute effectively to the project's growth. \ No newline at end of file diff --git a/v3/wep/WEP_TEMPLATE.md b/v3/wep/WEP_TEMPLATE.md index c822c236177..dc2140ede72 100644 --- a/v3/wep/WEP_TEMPLATE.md +++ b/v3/wep/WEP_TEMPLATE.md @@ -2,8 +2,12 @@ ## Title +**WEP Number**: (leave blank, assigned on acceptance) +**Status**: Draft **Author**: [Your Name] -**Created**: [YYYY-MM-DD] +**Created**: [YYYY-MM-DD] +**Discussion**: [optional link to any prior discussion of the idea] +**Implementor**: [who has agreed to implement this, may be the author] ## Summary @@ -21,6 +25,13 @@ Provide a detailed description of the proposed feature, including: - Implementation steps - Potential impact on existing functionality +## Platform Considerations + +Describe how the feature behaves on each platform (Windows, macOS, Linux, and mobile where relevant). Include: + +- Platform-specific behaviour, limitations or API differences +- Any platform where the feature is unsupported, and why + ## Pros/Cons List the pros and cons of the proposed solution. diff --git a/v3/wep/proposals/titlebar-buttons/proposal.md b/v3/wep/proposals/0001-titlebar-buttons/proposal.md similarity index 94% rename from v3/wep/proposals/titlebar-buttons/proposal.md rename to v3/wep/proposals/0001-titlebar-buttons/proposal.md index 8bd6b8c4fdc..c699f8d1c2d 100644 --- a/v3/wep/proposals/titlebar-buttons/proposal.md +++ b/v3/wep/proposals/0001-titlebar-buttons/proposal.md @@ -2,8 +2,12 @@ ## Customising Window Controls in Wails -**Author**: Lea Anthony -**Created**: 2024-05-20 +**WEP Number**: 0001 +**Status**: Implemented +**Author**: Lea Anthony +**Created**: 2024-05-20 +**Proposal**: [#3508](https://github.com/wailsapp/wails/pull/3508) +**Implementor**: Lea Anthony ## Summary diff --git a/website/i18n/en/docusaurus-plugin-content-docs/version-v2.13.0.json b/website/i18n/en/docusaurus-plugin-content-docs/version-v2.13.0.json new file mode 100644 index 00000000000..a665611f119 --- /dev/null +++ b/website/i18n/en/docusaurus-plugin-content-docs/version-v2.13.0.json @@ -0,0 +1,38 @@ +{ + "version.label": { + "message": "v2.13.0", + "description": "The label for version v2.13.0" + }, + "sidebar.docs.category.Getting Started": { + "message": "Getting Started", + "description": "The label for category 'Getting Started' in sidebar 'docs'" + }, + "sidebar.docs.category.Reference": { + "message": "Reference", + "description": "The label for category 'Reference' in sidebar 'docs'" + }, + "sidebar.docs.category.Runtime": { + "message": "Runtime", + "description": "The label for category 'Runtime' in sidebar 'docs'" + }, + "sidebar.docs.category.Community": { + "message": "Community", + "description": "The label for category 'Community' in sidebar 'docs'" + }, + "sidebar.docs.category.Showcase": { + "message": "Showcase", + "description": "The label for category 'Showcase' in sidebar 'docs'" + }, + "sidebar.docs.category.Guides": { + "message": "Guides", + "description": "The label for category 'Guides' in sidebar 'docs'" + }, + "sidebar.docs.category.Tutorials": { + "message": "Tutorials", + "description": "The label for category 'Tutorials' in sidebar 'docs'" + }, + "sidebar.docs.link.Contributing": { + "message": "Contributing", + "description": "The label for link 'Contributing' in sidebar 'docs', linking to '/community-guide#ways-of-contributing'" + } +} diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0.json b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0.json new file mode 100644 index 00000000000..f9fa85bae9c --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0.json @@ -0,0 +1,38 @@ +{ + "version.label": { + "message": "Prochaine version 🚧", + "description": "The label for version current" + }, + "sidebar.docs.category.Getting Started": { + "message": "Pour démarrer", + "description": "The label for category Getting Started in sidebar docs" + }, + "sidebar.docs.category.Reference": { + "message": "Références", + "description": "The label for category Reference in sidebar docs" + }, + "sidebar.docs.category.Runtime": { + "message": "Exécution", + "description": "The label for category Runtime in sidebar docs" + }, + "sidebar.docs.category.Community": { + "message": "Communauté", + "description": "The label for category Community in sidebar docs" + }, + "sidebar.docs.category.Showcase": { + "message": "Galerie", + "description": "The label for category Showcase in sidebar docs" + }, + "sidebar.docs.category.Guides": { + "message": "Guides", + "description": "The label for category Guides in sidebar docs" + }, + "sidebar.docs.category.Tutorials": { + "message": "Tutoriels", + "description": "The label for category Tutorials in sidebar docs" + }, + "sidebar.docs.link.Contributing": { + "message": "Contribuer", + "description": "The label for link Contributing in sidebar docs, linking to /community-guide#ways-of-contributing" + } +} diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/links.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/links.mdx new file mode 100644 index 00000000000..d6b742435e4 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/links.mdx @@ -0,0 +1,26 @@ +--- +sidebar_position: 2 +--- + +# Liens + +Cette page sert de liste pour les liens liés à la communauté. Veuillez soumettre une PR (cliquez sur `Modifier cette page` en bas) pour soumettre des liens. + +## Awesome Wails + +La [liste définitive](https://github.com/wailsapp/awesome-wails) de liens relatifs à Wails. + +## Canaux de support + +- [Serveur Discord Wails](https://discord.gg/JDdSxwjhGf) +- [Github Issues](https://github.com/wailsapp/wails/issues) +- [canal de discussion sur la bêta v2](https://github.com/wailsapp/wails/discussions/828) + +## Réseaux sociaux + +- [Twitter](https://twitter.com/wailsapp) +- [Groupe QQ pour la communauté chinoise de Wails](https://qm.qq.com/cgi-bin/qm/qr?k=PmIURne5hFGNd7QWzW5qd6FV-INEjNJv&jump_from=webapi) - Numéro de groupe : 1067173054 + +## Autres tutoriels et articles + +- [Construction d'un Panneau d'Affichage](https://blog.customct.com/building-bulletin-board) diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/bulletinboard.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/bulletinboard.mdx new file mode 100644 index 00000000000..2c56a2e836c --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/bulletinboard.mdx @@ -0,0 +1,10 @@ +# BulletinBoard + +```mdx-code-block +

                        + +
                        +

                        +``` + +L'application [BulletinBoard](https://github.com/raguay/BulletinBoard) est un panneau de messages versitaux pour les messages statiques ou les boîtes de dialogue pour obtenir des informations de l'utilisateur pour un script. Il a une TUI pour créer de nouvelles boîtes de dialogue qui peuvent être utilisées pour obtenir des informations de l'utilisateur. Son design est de rester en fonctionnement sur votre système et de montrer les informations au besoin, puis de se cacher. J'ai un processus pour surveiller un fichier sur mon système et pour envoyer le contenu à BulletinBoard une fois modifié. Cela fonctionne très bien avec mes workflows. Il y a auss un [workflow Alfred](https://github.com/raguay/MyAlfred/blob/master/Alfred%205/EmailIt.alfredworkflow) pour envoyer les informations au programme. Le workflow fonctionne aussi avec [EmailIt](https://github.com/raguay/EmailIt). diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/cfntracker.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/cfntracker.mdx new file mode 100644 index 00000000000..7b9dd1164e5 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/cfntracker.mdx @@ -0,0 +1,37 @@ +# CFN Tracker + +```mdx-code-block +

                        + +
                        +

                        +``` + +[CFN Tracker](https://github.com/williamsjokvist/cfn-tracker) - Suivez les matchs en direct de n'importe quel profil CFN Street +Fighter 6 ou V. Allez sur +[le site web](https://cfn.williamsjokvist.se/) pour commencer. + +## Fonctionnalités + +- Suivi des matchs en temps réel +- Affichage des logs et des statistiques des matchs +- Prise en charge de l'affichage des statistiques en direct à OBS via la source Browser +- Support de SF6 et SFV +- Possibilité pour les utilisateurs de créer leurs propres thèmes OBS avec du CSS + +### Technologies principales utilisées aux côtés de Wails + +- [Task](https://github.com/go-task/task) - encapsuler le CLI Wails pour rendre + des commandes communes faciles à utiliser +- [React](https://github.com/facebook/react) - choisi pour son écosystème riche + (radix, framer-motion) +- [Bun](https://github.com/oven-sh/bun) - utilisé pour sa résolution de dépendance + rapide et temps de compilation +- [Rod](https://github.com/go-rod/rod) - Outil d'automatisation du navigateur sans fenêtre pour les modifications d'authentification et de sondage +- [SQLite](https://github.com/mattn/go-sqlite3) - utilisé pour stocker des matches, + sessions et profils +- [Server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) - Stream HTTP pour suivant les mises à jour et envoyant les modifications aux sources OBS +- [i18next](https://github.com/i18next/) - avec le connecteur backend pour servir les objets de localisation + depuis Go +- [xstate](https://github.com/statelyai/xstate) - des machines à états pour le processus d'authentification + et le suivi diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/emailit.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/emailit.mdx new file mode 100644 index 00000000000..ac64e25acce --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/emailit.mdx @@ -0,0 +1,10 @@ +# EmailIt + +```mdx-code-block +

                        + +
                        +

                        +``` + +[EmailIt](https://github.com/raguay/EmailIt/) est un programme Wails 2 qui est un expéditeur de courrier électronique basé sur le markdown uniquement avec neuf blocs-notes, pour manipuler le texte et les modèles. Il a également un terminal pour exécuter des scripts dans EmailIt sur les fichiers de votre système. Les scripts et modèles peuvent être utilisés depuis la ligne de commande elle-même ou avec les extensions Alfred, Keyboard Maestro, Dropzone ou PopClip. Il supporte également les scripts et thèmes téléchargés sous GitHub. La documentation n'est pas complète, mais le programme fonctionne. Il est construit en utilisant Wails2 et Svelte, et le téléchargement est une application macOS universelle. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/encrypteasy.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/encrypteasy.mdx new file mode 100644 index 00000000000..7f4bd7a634a --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/encrypteasy.mdx @@ -0,0 +1,12 @@ +# EncryptEasy + +```mdx-code-block +

                        + +
                        +

                        +``` + +**[EncryptEasy](https://www.encrypteasy.app) est un outil de chiffrement PGP simple et facile à utiliser, qui gère toutes vos clés et celles de vos contacts. Le chiffrement devrait être simple. Développé avec Wails.** + +Chiffrer les messages à l'aide de PGP est la norme de l'industrie. Tout le monde a une clé privée et publique. Votre clé privée, eh bien, doit être privée afin que vous seul puissiez lire les messages. Votre clé publique est distribuée à toute personne qui veut vous envoyer des messages secrets, chiffrés. Gérer les clés, chiffrer les messages et déchiffrer les messages devrait être une expérience agréable. EncryptEasy a pour but de vous simplifier la tâche. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/espstudio.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/espstudio.mdx new file mode 100644 index 00000000000..3f9f1ab344d --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/espstudio.mdx @@ -0,0 +1,12 @@ +# ESP Studio + +```mdx-code-block +

                        + +
                        +

                        +``` + +[ESP Studio](https://github.com/torabian/esp-studio) - Cross platform, Desktop, Cloud, et logiciel embarqué pour contrôler les appareils ESP/Arduino, et construire des workflows et contrôles de systèmes IOT diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/filehound.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/filehound.mdx new file mode 100644 index 00000000000..7522afa6ecf --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/filehound.mdx @@ -0,0 +1,16 @@ +# Utilitaire d'exportation FileHound + +```mdx-code-block +

                        + +
                        +

                        +``` + +[L'utilitaire d'exportation FileHound](https://www.filehound.co.uk/) est une plate-forme de gestion de documents cloud conçue pour la conservation sécurisée de fichiers, l'automatisation des processus métier et les capacités de SmartCapture. + +L'utilitaire d'exportation FileHound permet aux administrateurs FileHound d'exécuter des tâches sécurisées d'extraction de documents et de données à des fins alternatives de sauvegarde et de récupération. Cette application téléchargera tous les documents et/ou métadonnées enregistrés dans FileHound en fonction des filtres que vous avez choisis. Les métadonnées seront exportées dans les formats JSON et XML. + +Backend construit avec: Go 1.15 Wails 1.11.0 go-sqlite3 1.14.6 go-linq 3.2 + +Frontend avec: Vue 2.6.11 Vuex 3.4.0 TypeScript Tailwind 1.9.6 diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/grpcmd-gui.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/grpcmd-gui.mdx new file mode 100644 index 00000000000..213124a89a3 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/grpcmd-gui.mdx @@ -0,0 +1,10 @@ +# grpcmd-gui + +```mdx-code-block +

                        + +
                        +

                        +``` + +[grpcmd-gui](https://grpc.md/gui) est une application et un client API Desktop cross-plateform moderne pour le développement et le test d'appels gRPC. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/hiposter.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/hiposter.mdx new file mode 100644 index 00000000000..21fd4b11743 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/hiposter.mdx @@ -0,0 +1,10 @@ +# hiposter + +```mdx-code-block +

                        + +
                        +

                        +``` + +[hiposter](https://github.com/obity/hiposter) est un outil client de test d'API http simple et efficace. Basé sur les Wails, Go et sveltejs. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/kafka-king.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/kafka-king.mdx new file mode 100644 index 00000000000..8d40f82371c --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/kafka-king.mdx @@ -0,0 +1,23 @@ +# Kafka-King + +```mdx-code-block +

                        + +
                        +

                        +``` + +[Kafka-King](https://github.com/Bronya0/Kafka-King) est un client GUI kafka qui supporte différents systèmes et est compact et facile à utiliser. +Ceci est fait avec Wails+vue3 + +# Liste des fonctionalités de Kafka-King + +- [x] Voir la liste des nœuds du cluster, prendre en charge la configuration dynamique des éléments de broker et de la configuration des éléments +- [x] Supporte les clients consommateurs, consomme le sujet, la taille et le délai spécifiés selon le groupe spécifié, et affiche les informations du message dans différentes dimensions dans un tableau +- [x] Supporte PLAIN, SSL, SASL, kerberos, sasl_plaintext, etc. +- [x] Créer des topics (support les batches), supprimer des topics, spécifier des replicas, des partitions +- [x] Statistiques de support du nombre total de messages, du nombre total de soumissions et du retard de consommation pour chaque topic basée sur les groupes de consommateurs +- [x] Prise en charge de la visualisation des rubriques Informations détaillées (offset) de la partition, et support l'ajout de partitions supplémentaires +- [x] Supporte la simulation de producteurs, d'envoi de messages par batch, la définition de headers, partitions +- [x] Health check +- [x] Support de la visualisation des groupes de consommateurs, Consommateur- …… diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/mchat.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/mchat.mdx new file mode 100644 index 00000000000..15a908bf401 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/mchat.mdx @@ -0,0 +1,10 @@ +# Mchat + +```mdx-code-block +

                        + +
                        +

                        +``` + +[Page officielle](https://marcio199226.github.io/mchat-site/public/) Chat chiffré de end2end entièrement anonyme. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/minecraftupdater.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/minecraftupdater.mdx new file mode 100644 index 00000000000..5966e75fa63 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/minecraftupdater.mdx @@ -0,0 +1,14 @@ +# Minecraft Updater + +```mdx-code-block +

                        + +
                        +

                        +``` + +[Minecraft Updater](https://github.com/Gurkengewuerz/MinecraftModUpdater) est un outil utilitaire pour mettre à jour et synchroniser les mods Minecraft pour votre base d'utilisateurs. Il a été conçu en utilisant Wails2 et React avec [antd](https://ant.design/) comme framework frontend. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/minesweeper-xp.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/minesweeper-xp.mdx new file mode 100644 index 00000000000..425505b1a83 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/minesweeper-xp.mdx @@ -0,0 +1,10 @@ +# Minesweeper XP + +```mdx-code-block +

                        + +
                        +

                        +``` + +[Minesweeper-XP](https://git.new/Minesweeper-XP) vous permet de vivre l'expérience du Démineur XP (+ 98 et 3.1) sur macOS, Windows et Linux ! diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/modalfilemanager.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/modalfilemanager.mdx new file mode 100644 index 00000000000..fe644bd7bb5 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/modalfilemanager.mdx @@ -0,0 +1,14 @@ +# Modal File Manager + +```mdx-code-block +

                        + +
                        +

                        +``` + +[Modal File Manager](https://github.com/raguay/ModalFileManager) est un gestionnaire de fichiers à double volet utilisant des technologies web. Mon design original était basé sur NW.js et peut être trouvé [ici](https://github.com/raguay/ModalFileManager-NWjs). Cette version utilise le même code frontend basé sur Svelte (mais il a été grandement modifié depuis le départ de NW.js), mais le backend est une implémentation de [Wails 2](https://wails.io/). En utilisant cette implémentation, je n'utilise plus la ligne de commande `rm`, `cp`, etc. , mais une installation de git doit être présente sur le système pour télécharger des thèmes et des extensions. Il est entièrement codé en utilisant Go et fonctionne beaucoup plus rapidement que les versions précédentes. + +Ce gestionnaire de fichiers est conçu autour du même principe que Vim: l'état est contrôlé par des actions via le clavier. Le nombre d'états n'est pas fixe, mais très programmable. Par conséquent, un nombre infini de configurations de clavier qui peuvent être créées et utilisées. C'est la principale différence par rapport aux autres gestionnaires de fichiers. Il y a des thèmes et des extensions disponibles à télécharger à partir de GitHub. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/mollywallet.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/mollywallet.mdx new file mode 100644 index 00000000000..70a6cd1f44d --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/mollywallet.mdx @@ -0,0 +1,10 @@ +# Molley Wallet + +```mdx-code-block +

                        + +
                        +

                        +``` + +[Molly Wallet](https://github.com/grvlle/constellation_wallet/) le portefeuille officiel $DAG du Constellation Network. Cela permettra aux utilisateurs d'interagir avec le réseau Hypergraph de différentes manières, sans se limiter à la production de transactions en $DAG. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/october.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/october.mdx new file mode 100644 index 00000000000..5a9789d8711 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/october.mdx @@ -0,0 +1,14 @@ +# October + +```mdx-code-block +

                        + +
                        +

                        +``` + +[Octobre](https://october.utf9k.net) est une petite application Wails qui rend vraiment facile d'extraire les surlignements de [Kobo eReaders](https://en.wikipedia.org/wiki/Kobo_eReader) puis de les transférer vers [Readwise](https://readwise.io). + +Il a une taille relativement petite avec toutes les versions de la plate-forme pesant en moins de 10 Mo, et c'est sans activer la [compression UPX](https://upx.github.io/)! + +En revanche, les précédentes tentatives de l'auteur avec Electron ont rapidement gonflé à plusieurs centaines de mégaoctets. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/optimus.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/optimus.mdx new file mode 100644 index 00000000000..41744234d37 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/optimus.mdx @@ -0,0 +1,10 @@ +# Optimus + +```mdx-code-block +

                        + +
                        +

                        +``` + +[Optimus](https://github.com/splode/optimus) est une application d'optimisation d'image de bureau. Il supporte la conversion et la compression entre les formats d’images WebP, JPEG et PNG. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/portfall.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/portfall.mdx new file mode 100644 index 00000000000..acdc682becf --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/portfall.mdx @@ -0,0 +1,10 @@ +# Portfall + +```mdx-code-block +

                        + +
                        +

                        +``` + +[Portfall](https://github.com/rekon-oss/portfall) - Un portail de redirection de port k8 pour un accès facile à toutes les interfaces de votre instance diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/resizem.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/resizem.mdx new file mode 100644 index 00000000000..a3b560683f3 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/resizem.mdx @@ -0,0 +1,10 @@ +# Resizem + +```mdx-code-block +

                        + +
                        +

                        +``` + +[Resizem](https://github.com/barats/resizem) - est une application conçue pour le traitement d'images en bloc. Il est particulièrement utile pour les utilisateurs qui ont besoin de redimensionner, de convertir et de gérer un grand nombre de fichiers image à la fois. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/restic-browser.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/restic-browser.mdx new file mode 100644 index 00000000000..b6597166852 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/restic-browser.mdx @@ -0,0 +1,12 @@ +# Restic Browser + +```mdx-code-block +

                        + +
                        +

                        +``` + +[Restic-Browser](https://github.com/emuell/restic-browser) - Une interface de sauvegarde simple et multiplateforme [restic](https://github.com/restic/restic) pour la navigation et la restauration de dépôts restic. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/riftshare.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/riftshare.mdx new file mode 100644 index 00000000000..e47b2397e63 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/riftshare.mdx @@ -0,0 +1,21 @@ +# RiftShare + +```mdx-code-block +

                        + +
                        +

                        +``` + +Partage de fichiers facile, sécurisé et gratuit pour tout le monde. Apprenez-en plus sur [Riftshare.app](https://riftshare.app) + +## Fonctionnalités + +- Partage facile et sécurisé de fichiers entre ordinateurs à la fois sur le réseau local et via Internet +- Supporte l'envoi de fichiers ou de répertoires de manière sécurisée par le protocole [magic wormhole](https://magic-wormhole.readthedocs.io/en/latest/) +- Compatible avec toutes les autres applications utilisant magic wormhole (magic-wormhole or wormhole-william CLI, wormhole-gui, etc.) +- Compression automatique de plusieurs fichiers sélectionnés à envoyer en même temps +- Animations complètes, barre de progression et support d'annulation pour l'envoi et la réception +- Sélection de fichier natif au système d'exploitation +- Ouvrir les fichiers en un seul clic une fois reçus +- Mise à jour automatique - ne vous inquiétez pas d'avoir la dernière version! diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/scriptbar.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/scriptbar.mdx new file mode 100644 index 00000000000..d7215d66126 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/scriptbar.mdx @@ -0,0 +1,10 @@ +# ScriptBar + +```mdx-code-block +

                        + +
                        +

                        +``` + +[ScriptBar](https://GitHub.com/raguay/ScriptBarApp) est un programme pour afficher la sortie de scripts ou d'un serveur [Node-Red](https://nodered.org). Il exécute des scripts définis dans le programme EmailIt et affiche la sortie. Des scripts de xBar ou TextBar peuvent être utilisés. Actuellement sur les scripts TextBar fonctionnent bien. Il affiche également la sortie des scripts sur votre système. ScriptBar ne les met pas dans la barre de menus, mais les a tous dans une fenêtre convenable pour une visualisation facile. Vous pouvez avoir plusieurs onglets pour voir plusieurs choses différentes. Vous pouvez également conserver les liens vers vos sites Web les plus visités. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/snippetexpander.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/snippetexpander.mdx new file mode 100644 index 00000000000..a0445182638 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/snippetexpander.mdx @@ -0,0 +1,27 @@ +# Snippet Expander + +```mdx-code-block +

                        + +
                        + Screenshot of Snippet Expander's Select Snippet window +

                        +

                        + +
                        + Screenshot of Snippet Expander's Add Snippet screen +

                        +

                        + +
                        + Screenshot of Snippet Expander's Search & Paste window +

                        +``` + +[Snippet Expander](https://snippetexpander.org) est "Votre petit assistant de snippets extensibles", pour Linux. + +Snippet Expander comprend une application GUI construite avec Wails pour gérer les modules de texte et les paramètres, avec le mode Recherche & Coller pour sélectionner et coller rapidement un snippet. + +L'interface Wails, le CLI go-lang et le daemon vala-lang d'auto expansion de Wails communiquent tous avec un daemon go-lang via D-Bus. Le daemon fait la majorité du travail, gère la base de données des snippets et des paramètres communs, et fournit des services pour l'expansion et le collage des snippets, etc. + +Consultez le [code source](https://git.sr.ht/~ianmjones/snippetexpander/tree/trunk/item/cmd/snippetexpandergui/app.go#L38) pour voir comment l'application Wails envoie des messages de l'interface utilisateur vers le backend qui sont ensuite envoyés au daemon, et s'abonne à un événement D-Bus pour surveiller les changements de snippets via une autre instance de l'application ou CLI et les afficher instantanément dans l'interface utilisateur via un événement Wails. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/surge.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/surge.mdx new file mode 100644 index 00000000000..b5917484303 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/surge.mdx @@ -0,0 +1,10 @@ +# Surge + +```mdx-code-block +

                        + +
                        +

                        +``` + +[Surge](https://getsurge.io/) est une application de partage de fichiers p2p conçue pour utiliser les technologies blockchain afin d'activer les transferts de fichiers 100 % anonymes. Surge est chiffré de bout en bout, décentralisé et open source. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/tinyrdm.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/tinyrdm.mdx new file mode 100644 index 00000000000..5390d57fbde --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/tinyrdm.mdx @@ -0,0 +1,11 @@ +# Tiny RDM + +```mdx-code-block +

                        + + +
                        +

                        +``` + +L'application [Tiny RDM](https://redis.tinycraft.cc/) est une interface Redis moderne et open-source. Il possède une interface utilisateur magnifique, une gestion de base de données Redis intuitive et compatible avec Windows, Mac et Linux. Il fournit des opérations visuelles de données de clé-valeur, supporte diverses options de décodage et de visualisation des données, possède une console intégrée pour exécuter des commandes, des requêtes de log lentes et plus encore. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/wailsterm.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/wailsterm.mdx new file mode 100644 index 00000000000..e7ae7d3ec19 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/wailsterm.mdx @@ -0,0 +1,10 @@ +# WailsTerm + +```mdx-code-block +

                        + +
                        +

                        +``` + +[WailsTerm](https://github.com/rlshukhov/wailsterm) est une simple application de terminal translucide propulsée par Wails et Xterm.js. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/wally.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/wally.mdx new file mode 100644 index 00000000000..ba2a7fccc45 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/wally.mdx @@ -0,0 +1,10 @@ +# Wally + +```mdx-code-block +

                        + +
                        +

                        +``` + +[Wally](https://ergodox-ez.com/pages/wally) est le flasheur officiel du firmware pour les claviers [Ergodox](https://ergodox-ez.com/). C'est un excellent exemple de ce que vous pouvez réaliser avec Wails : la capacité de combiner la puissance de Go et les riches outils graphiques du monde du développement web. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/warmine.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/warmine.mdx new file mode 100644 index 00000000000..2e427433069 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/warmine.mdx @@ -0,0 +1,19 @@ +# Lanceur Minecraft pour WarMine + +```mdx-code-block +

                        + + +
                        +

                        +``` + +[Lanceur Minecraft pour WarMine](https://warmine.ru/) est une application Wails qui vous permet facilement de rejoindre le serveur de jeu contenant les mods, ainsi que la gestion de vos comptes de jeu. + +Le Launcher télécharge les fichiers du jeu, vérifie leur intégrité et lance le jeu avec une large gamme d'options de personnalisation. + +Le frontend est écrit en Svelte, le lanceur entier tient dans 9Mo et prend en charge Windows 7-11. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/wombat.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/wombat.mdx new file mode 100644 index 00000000000..c431f691952 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/wombat.mdx @@ -0,0 +1,10 @@ +# Wombat + +```mdx-code-block +

                        + +
                        +

                        +``` + +[Wombat](https://github.com/rogchap/wombat) est un client gRPC multi-plateforme. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/ytd.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/ytd.mdx new file mode 100644 index 00000000000..4f5bd993cb1 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/showcase/ytd.mdx @@ -0,0 +1,10 @@ +# Ytd + +```mdx-code-block +

                        + +
                        +

                        +``` + +[Ytd](https://github.com/marcio199226/ytd/tree/v2-wails) est une application pour télécharger des pistes depuis youtube, créer des listes de lecture hors ligne et les partager avec vos amis, vos amis seront en mesure de lire vos playlists ou de les télécharger pour l'écoute hors ligne, a un lecteur intégré. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/templates.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/templates.mdx new file mode 100644 index 00000000000..49a3c7684e4 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/community/templates.mdx @@ -0,0 +1,76 @@ +--- +sidebar_position: 1 +--- + +# Modèles + +Cette page sert de liste pour les modèles supportés par la communauté. Veuillez soumettre une PR (cliquez sur `Modifier cette page` en bas) pour inclure vos modèles. Pour construire votre propre modèle, veuillez consulter le guide [Modèles](../guides/templates.mdx). + +Pour utiliser ces modèles, exécutez `wails init -n "Votre nom de projet" -t [le lien ci-dessous[@version]]` + +S'il n'y a pas de suffixe de version, la branche principale du modèle de code sera alors utilisé par défaut. S'il y a un suffixe de version, le modèle de code correspondant au tag de cette version sera utilisé. + +Exemple : `wails init -n "Votre nom de projet" -t https://github.com/misitebao/wails-template-vue` + +:::warning Attention + +**Le projet Wails n'entretient pas, et n'est pas responsable des modèles de tierces parties!** + +Si vous n'êtes pas sûr d'un modèle, inspectez `package.json` et `wails.json` pour savoir quels scripts sont exécutés et quels paquets sont installés. + +::: + +## Vue + +- [wails-template-vue](https://github.com/misitebao/wails-template-vue) - Modèle de Wails basé sur Vue (TypeScript intégré, thème sombre, internationalisation, routage de page unique, TailwindCSS) +- [wails-template-quasar-js](https://github.com/sgosiaco/wails-template-quasar-js) - Un modèle utilisant JavaScript + Quasar V2 (Vue 3, Vite, Sass, Pinia, ESLint, Prettier) +- [wails-template-quasar-ts](https://github.com/sgosiaco/wails-template-quasar-ts) - Un modèle utilisant TypeScript + Quasar V2 (Vue 3, Vite, Sass, Pinia, ESLint, Prettier, Composition API avec <script setup>) +- [wails-template-naive](https://github.com/tk103331/wails-template-naive) - Modèle Wails basé sur Naive UI (Librairie de composants Vue 3) +- [wails-template-tdesign-js](https://github.com/tongque0/wails-template-tdesign-js) - Modèle Wails basé sur TDesign UI (une librairie Vue 3 UI de Tencent), utilisant Vite, Pinia, Vue Router, ESLint, et Prettier. + +## Angular + +- [wails-template-angular](https://github.com/mateothegreat/wails-template-angular) - Modèle Angular 15+ prêt à être utilisé en production. +- [wails-angular-template](https://github.com/TAINCER/wails-angular-template) - Angular avec TypeScript, Sass, rechargement à chaud, découpage dynamique de code et i18n + +## React + +- [wails-react-template](https://github.com/AlienRecall/wails-react-template) - Un modèle utilisant reactjs +- [wails-react-template](https://github.com/flin7/wails-react-template) - Un modèle minimal pour React qui supporte le développement en direct +- [wails-template-nextjs](https://github.com/LGiki/wails-template-nextjs) - Un modèle utilisant Next.js et TypeScript +- [wails-template-nextjs-app-router](https://github.com/thisisvk-in/wails-template-nextjs-app-router) - Un modèle utilisant Next.js et TypeScript avec un routeur +- [wails-vite-react-ts-tailwind-template](https://github.com/hotafrika/wails-vite-react-ts-tailwind-template) - Un modèle pour React + TypeScript + Vite + TailwindCSS +- [wails-vite-react-ts-tailwind-shadcnui-template](https://github.com/Mahcks/wails-vite-react-tailwind-shadcnui-ts) - Un modèle avec Vite, React, TypeScript, TailwindCSS, et shadcn/ui +- [wails-nextjs-tailwind-template](https://github.com/kairo913/wails-nextjs-tailwind-template) - Un modèle utilisant Next.js et Typescript avec TailwindCSS + +## Svelte + +- [wails-svelte-template](https://github.com/raitonoberu/wails-svelte-template) - Un modèle utilisant Svelte +- [wails-vite-svelte-template](https://github.com/BillBuilt/wails-vite-svelte-template) - Un modèle utilisant Svelte et Vite +- [wails-vite-svelte-ts-tailwind-template](https://github.com/xvertile/wails-vite-svelte-tailwind-template) - Un modèle utilisant Wails, Svelte, Vite, TypeScript et TailwindCSS v3 +- [wails-vite-svelte-tailwind-template](https://github.com/BillBuilt/wails-vite-svelte-tailwind-template) - Un modèle utilisant Svelte et Vite avec TailwindCSS v3 +- [wails-svelte-tailwind-vite-template](https://github.com/PylotLight/wails-vite-svelte-tailwind-template/tree/master) - Un modèle mis à jour en utilisant Svelte v4.2.0 et Vite avec TailwindCSS v3.3.3 +- [wails-sveltekit-template](https://github.com/h8gi/wails-sveltekit-template) - Un modèle utilisant SvelteKit + +## Solid + +- [wails-template-vite-solid-ts](https://github.com/xijaja/wails-template-solid-ts) - Un modèle utilisant Solid + Ts + Vite +- [wails-template-vite-solid-ts](https://github.com/xijaja/wails-template-solid-js) - Un modèle utilisant Solid + Js + Vite + +## Elm + +- [wails-elm-template](https://github.com/benjamin-thomas/wails-elm-template) - Développez votre application GUI avec de la programmation fonctionnelle et une configuration de développement en direct :tada: :rocket: +- [wails-template-elm-tailwind](https://github.com/rnice01/wails-template-elm-tailwind) - Combine les puissances :muscle: d'Elm + Tailwind CSS + Wails ! Rechargement automatique pris en charge. + +## HTMX + +- [wails-htmx-templ-chi-tailwind](https://github.com/PylotLight/wails-hmtx-templ-template) - Utilisez une combinaison unique de htmx pour interactivité, et de templ pour créer des composants et des formes + +## Pure JavaScript (Vanilla) + +- [wails-pure-js-template](https://github.com/KiddoV/wails-pure-js-template) - Un modèle avec rien que du JavaScript, du HTML et du CSS de base + + +## Lit (Composants web) + +- [wails-lit-shoelace-esbuild-template](https://github.com/Braincompiler/wails-lit-shoelace-esbuild-template) - Modèle Wails fournissant une interface avec lit, une bibliothèque de composants Shoelace, ainsi que prettier et typescript préconfigurés. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/gettingstarted/building.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/gettingstarted/building.mdx new file mode 100644 index 00000000000..4de31450bc2 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/gettingstarted/building.mdx @@ -0,0 +1,26 @@ +--- +sidebar_position: 6 +--- + +# Compiler votre projet + +À partir du répertoire du projet, exécutez `wails build`. Cela compilera votre projet et sauvegardera le binaire prêt à la production dans le répertoire `build/bin`. + +:::info Linux +Si vous utilisez une distribution Linux qui n'a pas webkit2gtk-4. (comme Ubuntu 24.04), vous devrez ajouter `-tags webkit2_41`. +::: + +Si vous exécutez le binaire, vous devriez voir l'application par défaut : + +```mdx-code-block +
                        + +
                        +
                        +``` + +Pour plus de détails sur les options de compilation, veuillez vous référer à la [documentation du CLI](../reference/cli.mdx#build). diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/gettingstarted/development.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/gettingstarted/development.mdx new file mode 100644 index 00000000000..307029141d4 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/gettingstarted/development.mdx @@ -0,0 +1,16 @@ +--- +sidebar_position: 5 +--- + +# Développez votre application + +Vous pouvez exécuter votre application en mode développement en exécutant `wails dev` à partir du répertoire de votre projet. Cela fera les choses suivantes : + +- Construire votre application et l'exécuter +- Lier votre code Go au frontend pour qu'il puisse être appelé à partir de JavaScript +- En utilisant la puissance de [Vite](https://vitejs.dev/), surveillera les modifications dans vos fichiers Go et reconstruira / ré-exécutera en cas de changement +- Mettra en place un [serveur web](http://localhost:34115) qui servira votre application via un navigateur. Cela vous permet d'utiliser les extensions de votre navigateur préféré. Vous pouvez même appeler votre code Go depuis la console + +Pour commencer, exécutez `wails dev` dans le répertoire du projet. Plus d'informations à ce sujet peuvent être trouvées [ici](../reference/cli.mdx#dev). + +Prochainement : Tutoriel diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/gettingstarted/firstproject.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/gettingstarted/firstproject.mdx new file mode 100644 index 00000000000..02e9f955b98 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/gettingstarted/firstproject.mdx @@ -0,0 +1,128 @@ +--- +sidebar_position: 2 +--- + +# Créer un projet + +## Génération de projet + +Maintenant que le CLI est installé, vous pouvez générer un nouveau projet en utilisant la commande `wails init`. + +Choisissez votre framework favori : + +```mdx-code-block +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + + + + Générer un projet Svelte utilisant JavaScript avec:

                        + + wails init -n myproject -t svelte + +Si vous préférez utiliser TypeScript:
                        + + wails init -n myproject -t svelte-ts + +
                        + + Générer un projet React utilisant JavaScript avec :

                        + + wails init -n myproject -t react + +Si vous préférez utiliser TypeScript:
                        + + wails init -n myproject -t react-ts + +
                        + + Générer un projet Vue utilisant JavaScript avec:

                        + + wails init -n myproject -t vue + +Si vous préférez TypeScript:
                        + + wails init -n myproject -t vue-ts + +
                        + + Générer un projet Preact utilisant JavaScript avec:

                        + + wails init -n myproject -t preact + +Si vous préférez TypeScript:
                        + + wails init -n myproject -t preact-ts + +
                        + + Générer un projet Lit utilisant JavaScript avec:

                        + + wails init -n myproject -t lit + +Si vous préférez TypeScript:
                        + + wails init -n myproject -t lit-ts + +
                        + + Générer un projet Vanilla utilisant JavaScript avec :

                        + + wails init -n myproject -t vanilla + +Si vous préférez TypeScript:
                        + + wails init -n myproject -t vanilla-ts + +
                        +
                        +``` + +
                        + +Il y a aussi [des modèles créés par la communauté](../community/templates.mdx) qui sont disponibles et qui offrent différentes possibilités. + +Pour voir les autres options disponibles, vous pouvez exécuter `wails init -help`. Plus de détails peuvent être trouvés dans la [documentation du CLI](../reference/cli.mdx#init). + +## Structure du projet + +Les projets Wails ont la structure suivante: + +``` +. +├── build/ +│ ├── appicon.png +│ ├── darwin/ +│ └── windows/ +├── frontend/ +├── go.mod +├── go.sum +├── main.go +└── wails.json +``` + +### Récapitulatif de la structure du projet + +- `/main.go` - L'application principale +- `/frontend/` - Fichiers de la partie frontend +- `/build/` - Répertoire de construction du projet +- `/build/appicon.png` - L'icône de l'application +- `/build/darwin/` - Fichiers spécifiques pour Mac +- `/build/windows/` - Fichiers spécifiques pour Windows +- `/wails.json` - La configuration du projet +- `/go.mod` - Le fichier du module Go +- `/go.sum` - Le checksum du fichier du module Go + +Le répertoire `frontend` n'a rien de spécifique à Wails et n'importe quel outil de frontend peut être utilisé. + +Le répertoire `build` est utilisé pendant le processus de compilation. Ces fichiers peuvent être mis à jour pour personnaliser vos builds. Si fichiers sont supprimés du répertoire de compilation, les versions par défaut seront régénérées. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/gettingstarted/installation.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/gettingstarted/installation.mdx new file mode 100644 index 00000000000..1420ffcbe40 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/gettingstarted/installation.mdx @@ -0,0 +1,92 @@ +--- +sidebar_position: 1 +--- + +# Installation + +## Plates-formes Prises en charge + +- Windows 10/11 AMD64/ARM64 +- MacOS 10.15+ AMD64 pour le développement, MacOS 10.13+ pour la publication +- MacOS 11.0+ ARM64 +- Linux AMD64/ARM64 + +## Dépendances + +Wails a un certain nombre de dépendances communes qui sont nécessaires avant l'installation : + +- Go 1.21+ (macOS 15+ requiert Go 1.23.3+) +- NPM (Node 15+) + +### Go + +Télécharger Go à partir de la [Page de téléchargement](https://go.dev/dl/). + +Assurez-vous que vous suivez les instructions officielles de [l'installation de Go](https://go.dev/doc/install). Vous devrez également vous assurer que votre variable d'environnement `PATH` inclut également le chemin vers votre répertoire `~/go/bin`. Redémarrez votre terminal et effectuez les vérifications suivantes : + +- Vérifiez que Go est installé correctement : `go version` +- Vérifiez que "~/go/bin" est dans votre variable PATH : `echo $PATH | grep go/bin` + +### NPM + +Téléchargez le NPM à partir de la [page de téléchargement de Node](https://nodejs.org/en/download/). Il est préférable d'utiliser la dernière version car c'est avec celle-là que nous effectuons nos tests. + +Exécutez `npm --version` pour vérifier. + +## Dépendances spécifiques aux plateformes + +Vous devrez également installer des dépendances spécifiques liés à la plateforme que vous utilisez : + +```mdx-code-block +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + + + + Wails a besoin que les outils de command line xocde soient installés. Cela peut être fait + en exécutant xcode-select --install. + + + Wails a besoin que WebView2 runtime soit installé. Certaines installations de Windows auront déjà installé cette fonctionnalité. Vous pouvez vérifier en utilisant la commande wails doctor. + + + Linux a besoin de gcc comme outil de compilation en plus de libgtk3 et libwebkit. Plutôt que de lister une tonne de commandes pour différentes distributions, Wails peut essayer de déterminer ce que sont les commandes d'installation pour votre distribution. Exécutez wails doctor après l'installation pour voir de quelles dépendances vous avez besoin. Si votre gestionnaire de distribution/paquet n'est pas pris en charge, veuillez consulter le guide Ajouter une distribution Linux. +
                        Note :
                        + Si vous utilisez la dernière version de Linux (exemple : Ubuntu 24. 4) et qu'il ne supporte pas libwebkit2gtk-4. -dev, alors vous pourriez rencontrer un problème dans le wails doctor: libwebkit introuvable. Pour résoudre ce problème, vous pouvez installer libwebkit2gtk-4.1-dev et pendant votre compilation, utilisez le tag -tags webkit2_41. +
                        +
                        +``` + +## Dépendances optionnelles + +- [UPX](https://upx.github.io/) pour compresser vos applications. +- [NSIS](https://wails.io/docs/guides/windows-installer/) pour générer des installateurs Windows. + +## Installer Wails + +Exécutez `go go install github.com/wailsapp/wails/v2/cmd/wails@latest` pour installer le CLI. + +Note: Si vous obtenez une erreur similaire à ceci: + +```shell +....\Go\pkg\mod\github.com\wailsapp\wails\v2@v2.1.0\pkg\templates\templates.go:28:12: pattern all:ides/*: no matching files found +``` +vérifiez que vous avez installé Go 1.18+ : +```shell +go version +``` + +## Vérification du système + +Exécuter `wails doctor` qui vérifiera si vous avez les bonnes dépendances installées. Si ce n'est pas le cas, il vous conseillera sur ce qui manque et vous aidera à corriger tout problème. + +## La commande `wails` semble manquer ? + +Si votre système signale que la commande `wails` est manquante, assurez-vous que vous avez suivi le guide d'installation correctement. Normalement, cela signifie que le répertoire `go/bin` du répertoire racine de votre utilisateur n'est pas dans la variable d'environnement `PATH` . Vous devrez également normalement fermer et réouvrir toutes les commandes ouvertes afin que les modifications apportées à l'environnement par l'installateur soient reflétées dans l'invite de commande. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/angular.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/angular.mdx new file mode 100644 index 00000000000..1fe2f199ffe --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/angular.mdx @@ -0,0 +1,14 @@ +# Angular + +Bien que Wails n'ait pas de modèle Angular, il est possible d'utiliser Angular avec Wails. + +## Dev Mode + +Pour que le mode développeur fonctionne avec Angular, vous devez ajouter ce qui suit à votre fichier `wails.json`: + +```json + "frontend:build": "npx ng build", + "frontend:install": "npm install", + "frontend:dev:watcher": "npx ng serve", + "frontend:dev:serverUrl": "http://localhost:4200", +``` \ No newline at end of file diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/application-development.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/application-development.mdx new file mode 100644 index 00000000000..a3418349426 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/application-development.mdx @@ -0,0 +1,273 @@ +# Développement d'applications + +Il n'y a pas de règles gravées dans le marbre pour le développement d'applications avec Wails, mais il y a quelques lignes directrices de base. + +## Configuration de l'application + +Le modèle utilisé par défaut défini que `main.go` est utilisé pour configurer et démarrer l'application, tandis que `app.go` est utilisé pour définir la logique de l'application. + +Le fichier `app.go` va définir une structure qui a 2 méthodes qui agissent comme crochets dans l'application principale: + +```go title="app.go" +type App struct { + ctx context.Context +} + +func NewApp() *App { + return &App{} +} + +func (a *App) startup(ctx context.Context) { + a.ctx = ctx +} + +func (a *App) shutdown(ctx context.Context) { +} +``` + +- La méthode startup est appelée d-s que Wails a donné les ressources nécessaires et qu'il est dans un bon état pour créer les ressources, mettre en place les event listeners et tout ce dont l'application peut avoir besoin pour démarrer. Il est donné un `context.Context` qui est généralement sauvegardé dans un champ struct. Ce contexte est nécessaire pour appeler le [runtime](../reference/runtime/intro.mdx). Si cette méthode renvoie une erreur, l'application se fermera. En mode développement, l'erreur sera affichée dans la console. + +- La méthode d'arrêt sera appelée par Wails à la fin du processus d'arrêt. C'est un bon endroit pour vider la mémoire et effectuer toutes les tâches d'arrêt. + +Le fichier `main.go` consiste généralement en un seul appel à `wails.Run()`, qui accepte la configuration de l'application. Le modèle utilisé par les templates fait qu'avant l'appel à `wails.Run()`, une instance du struct que l'on a définie dans `app.go` est créée et instanciée dans une variable appelée `app`. Cette configuration est l'endroit où nous ajoutons nos callbacks : + +```go {3,9,10} title="main.go" +func main() { + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: app.startup, + OnShutdown: app.shutdown, + }) + if err != nil { + log.Fatal(err) + } +} + +``` + +Plus d'informations sur les crochets du cycle de vie des applications peuvent être trouvées [ici](../howdoesitwork.mdx#application-lifecycle-callbacks). + +## Méthodes de liaison + +Il est probable que vous vouliez appeler les méthodes Go depuis le frontend. Cela se fait normalement en ajoutant des méthodes publiques à le struct déjà défini dans `app.go`: + +```go {16-18} title="app.go" +type App struct { + ctx context.Context +} + +func NewApp() *App { + return &App{} +} + +func (a *App) startup(ctx context.Context) { + a.ctx = ctx +} + +func (a *App) shutdown(ctx context.Context) { +} + +func (a *App) Greet(name string) string { + return fmt.Sprintf("Hello %s!", name) +} +``` + +Dans la configuration principale de l'application, le paramètre `Bind` est l'endroit où nous pouvons dire à Wails ce que nous voulons lier : + +```go {11-13} title="main.go" +func main() { + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: app.startup, + OnShutdown: app.shutdown, + Bind: []interface{}{ + app, + }, + }) + if err != nil { + log.Fatal(err) + } +} + +``` + +Cela liera toutes les méthodes publiques de notre structure `App` (cela ne liera jamais les méthodes de démarrage et d'arrêt du système). + +### Traiter avec le contexte lors de la liaison de plusieurs structures + +Si vous voulez lier des méthodes pour des structures multiples, mais que vous voulez que chaque struct conserve une référence au contexte pour que vous puissiez utiliser les fonctions d'exécution... Un bon choix est de passer le contexte de la méthode `OnStartup` à vos instances struct : + +```go +func main() { + + app := NewApp() + otherStruct := NewOtherStruct() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: func(ctx context.Context){ + app.SetContext(ctx) + otherStruct.SetContext(ctx) + }, + OnShutdown: app.shutdown, + Bind: []interface{}{ + app, + otherStruct + }, + }) + if err != nil { + log.Fatal(err) + } +} +``` + +Vous pouvez également utiliser des énums dans vos structures et avoir des modèles pour elles dans le frontend. Dans ce cas, vous devriez créer un tableau qui contiendra toutes les valeurs possibles de l'énumération, définir le type de l'énumération et lier le tout à l'application: + +```go {16-18} title="app.go" +type Weekday string + +const ( + Sunday Weekday = "Sunday" + Monday Weekday = "Monday" + Tuesday Weekday = "Tuesday" + Wednesday Weekday = "Wednesday" + Thursday Weekday = "Thursday" + Friday Weekday = "Friday" + Saturday Weekday = "Saturday" +) + +var AllWeekdays = []struct { + Value Weekday + TSName string +}{ + {Sunday, "SUNDAY"}, + {Monday, "MONDAY"}, + {Tuesday, "TUESDAY"}, + {Wednesday, "WEDNESDAY"}, + {Thursday, "THURSDAY"}, + {Friday, "FRIDAY"}, + {Saturday, "SATURDAY"}, +} +``` + +Dans la configuration principale de l'application, le paramètre `EnumBind` est l'endroit où nous pouvons dire à Wails ce que nous voulons lier : + +```go {11-13} title="main.go" +func main() { + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: app.startup, + OnShutdown: app.shutdown, + Bind: []interface{}{ + app, + }, + EnumBind: []interface{}{ + AllWeekdays, + }, + }) + if err != nil { + log.Fatal(err) + } +} + +``` + +Ceci ajoutera des enums manquants à votre fichier `model.ts`. + +Plus d'informations à sur Binding peuvent être trouvées [ici](../howdoesitwork.mdx#method-binding). + +## Menu de l’application + +Wails prend en charge l'ajout d'un menu à votre application. Ceci est fait en passant un [Menu](../reference/menus.mdx#menu) structuré à la configuration de l'application. Il est courant d'utiliser une méthode qui renvoie un Menu, et encore plus courant pour que cela soit une méthode sur la struct de l'`app` qui soit utilisée pour les hooks du cycle de vie. + +```go {11} title="main.go" +func main() { + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: app.startup, + OnShutdown: app.shutdown, + Menu: app.menu(), + Bind: []interface{}{ + app, + }, + }) + if err != nil { + log.Fatal(err) + } +} + +``` + +## Ressources + +La grande chose à propos de la façon dont Wails v2 gère les ressources pour le frontend, est que ce n'est pas le cas! La seule chose que vous devez donner à Wails est un `embed.FS`. C'est à vous de décider comment vous y arrivez. Vous pouvez utiliser les fichiers html/css/js vanilla comme dans le modèle vanilla. Vous pourriez avoir un système de compilation compliqué, peu importe. + +Quand la commande `wails dev` est exécutée, elle vérifiera le fichier de projet `wails.json` à la racine du projet. Il y a 2 clés dans le fichier du projet qui sont lues : + +- "frontend:install" +- "frontend:build" + +Le premier, si fourni, sera exécuté dans le répertoire `frontend` pour installer les modules. Le second, si fourni, sera exécuté dans le répertoire `frontend` pour construire le projet frontend. + +Si ces 2 clés ne sont pas fournies, alors Wails ne fait absolument rien avec le frontend. Il n'attend que `embed.FS`. + +### AssetsHandler + +Une application Wails v2 peut éventuellement définir un `http.Handler` dans `options.app`, qui permet de se connecter à l'AssetServer pour créer des fichiers à la volée ou traiter les requêtes POST/PUT. Les requêtes GET sont toujours traitées d'abord par le `assets` FS. Si le FS ne trouve pas le fichier demandé, la requête sera transmise au `http.Handler`. Toute requête autre que GET sera traitée directement par le `AssetsHandler` si spécifié. Il est également possible d'utiliser l'`AssetsHandler` uniquement en spécifiant `nil` dans l'option `Assets`. + +## Serveur de développement embarqué + +Exécuter `wails dev` démarrera le serveur de développement intégré qui démarrera un observateur de fichiers dans votre répertoire de projet. Par par défaut, si un fichier change, wails vérifie s'il s'agit d'un fichier d'application (par défaut: `.go`, configurable avec l'option `-e`). Si c'est le cas, il reconstruira votre application et la relancera. Si le fichier modifié se trouvait dans les actifs, il lancera un rechargement après un court laps de temps. + +Le serveur de développement utilise une technique appelée "debouncing", ce qui signifie qu'il ne se recharge pas tout de suite, comme il peut y avoir plusieurs fichiers modifiés en un court laps de temps. Lorsqu'un déclencheur se produit, il attend un temps défini avant d'émettre un rechargement. Si un autre déclencheur se produit, le temps d'attente se réinitialise avant un prochain rechargement. Par défaut, cette période est définie à `100ms`. Si cette valeur ne fonctionne pas pour votre projet, elle peut être configurée en utilisant l'option `-debounce`. Si elle est utilisée, cette valeur sera enregistrée dans la configuration de votre projet et deviendra la valeur par défaut. + +## Serveur de développement externe + +Certains frameworks sont fournis avec leur propre serveur de rechargement en direct, cependant ils ne seront pas en mesure de tirer parti des liaisons Wails Go. Dans ce scénario, il est préférable d'exécuter un script qui va surveiller le projet dans dossier build, dossier que Wails surveille aussi. Pour un exemple, voir le modèle svelte par défaut qui utilise [rollup](https://rollupjs.org/guide/en/). + +### Créer une application React + +Le processus pour créer un projet Reactest un peu plus compliqué. Afin de prendre en charge le rechargement du frontend en direct, la configuration suivante doit être ajoutée à votre `wails.json`: + +```json + "frontend:dev:watcher": "yarn start", + "frontend:dev:serverUrl": "http://localhost:3000", +``` + +La commande `frontend:dev:watcher` démarrera le serveur de développement React (hébergé sur le port `3000` typiquement). La commande `frontend:dev:serverUrl` demande ensuite à Wails d'exposer les ressources depuis le serveur de développement lors du chargement du frontend, plutôt que depuis le dossier de construction. En plus de ce qui précède, le fichier `index.html` doit être mis à jour avec les éléments suivants : + +```html + + + + + +``` + +Ceci est nécessaire, car la commande watcher qui reconstruit le frontend empêche Wails de les injecter. Ça contourne le problème en assurant les scripts sont toujours injectés. Avec cette configuration, `wails dev` peut être exécuté, ce qui construira le frontend et le backend de manière appropriée avec le rechargement à chaud activé. De plus, lorsque vous accédez à l'application à partir d'un navigateur, les outils de développement de React peuvent maintenant être utilisés sur une version non minifiée de l'application pour le débogage. Enfin, pour des compilations plus rapides, `wails dev -s` peut être exécuté pour passer la construction par défaut du frontend par Wails car c'est une étape inutile. + +## Module Go + +Les modèles Wails par défaut génèrent un fichier `go.mod` qui contient le nom de module "changeme". Vous devriez changer ceci pour quelque chose de plus approprié après la génération du projet. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/crossplatform-build.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/crossplatform-build.mdx new file mode 100644 index 00000000000..d933270205c --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/crossplatform-build.mdx @@ -0,0 +1,66 @@ +# Construction cross-plateforme avec Github Actions + +Pour construire un projet Wails pour toutes les plateformes disponibles, vous devez créer un build de l'application pour chaque système d'exploitation. Une méthode efficace pour y parvenir est d'utiliser GitHub Actions. + +Une action qui facilite la création d'une application Wails est disponible sur : +https://github.com/dAppServer/wails-build-action + +Dans le cas où l'action existante ne répond pas à vos exigences, vous ne pouvez sélectionner que les étapes nécessaires à partir de la source : +https://github.com/dAppServer/wails-build-action/blob/main/action.yml + +Voici un exemple complet qui démontre la construction d'une application lors de la création d'une nouvelle balise Git et qui la téléversera ensuite sur les artefacts Actions : + +```yaml +name: Wails build + +on: + push: + tags: + # Matche n'importe quel nouveau tag + - '*' + +env: + # Nécessaire pour la plupart des environnement, car des soucis de build peuvent arriver à cause de soucis de mémoire + NODE_OPTIONS: "--max-old-space-size=4096" + +jobs: + build: + strategy: + # Afin d'éviter que l'échec du build d'une plateforme n'impacte les autres + fail-fast: false + matrix: + build: + - name: 'App' + platform: 'linux/amd64' + os: 'ubuntu-latest' + - name: 'App' + platform: 'windows/amd64' + os: 'windows-latest' + - name: 'App' + platform: 'darwin/universal' + os: 'macos-latest' + + runs-on: ${{ matrix.build.os }} + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: recursive + + - name: Build wails + uses: dAppServer/wails-build-action@v2.2 + id: build + with: + build-name: ${{ matrix.build.name }} + build-platform: ${{ matrix.build.platform }} + package: false + go-version: '1.20' +``` + +Cet exemple offre des opportunités pour diverses améliorations, comprenant : + +- Mise en cache des dépendances +- Signature de code +- Envoi vers des plateformes comme S3, Supabase, etc. +- Injection de secrets en tant que variables d'environnement +- Utiliser des variables d'environnement comme variables de compilation (telles que la variable de version extraite de la balise Git actuelle) diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/custom-protocol-schemes.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/custom-protocol-schemes.mdx new file mode 100644 index 00000000000..bc44dcc4d02 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/custom-protocol-schemes.mdx @@ -0,0 +1,203 @@ +# Association de schéma de protocole personnalisé + +La fonction d'association de fichiers vous permet d'associer des types de fichiers spécifiques à votre application afin que lorsque les utilisateurs ouvrent ces fichiers, +votre application est lancée pour les gérer. Cela peut être particulièrement utile pour connecter votre application de bureau à votre application web. +Dans ce guide, nous allons parcourir les étapes pour implémenter l'association de fichiers dans l'application Wails. + +## Configurer une association de schémas de protocoles personnalisés : + +Pour configurer l'association de fichiers, vous devez modifier le fichier wails.json de votre application. +Dans la section "info", ajoutez une section "fileAssociations" spécifiant les types de fichiers auxquels votre application doit être associée. + +Par exemple : + +```json +{ + "info": { + "protocols": [ + { + "scheme": "myapp", + "description": "My App Protocol", + "role": "Editor" + } + ] + } +} +``` + +| Propriété | Description | +| :----------- | :------------------------------------------------------------------------------------------------ | +| scheme | Le schéma de protocole personnalisé. ex: myapp | +| description | Windows seulement. La description. | +| role | macOS uniquement. Rôle de l'application par rapport au type. Correspond au rôle CFBundleTypeRole. | + +## Spécificités par platefome : + +### MacOS + +Lorsque vous ouvrez un fichier (ou des fichiers) avec votre application, le système lancera votre application et appellera la fonction `OnFileOpen` dans votre application Wails. Exemple: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + Mac: &mac.Options{ + OnUrlOpen: func(url string) { println(url) }, + }, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` + +### Windows + +L'association de fichiers dans Windows n'est prise en charge qu'avec l'installateur NSIS. Pendant l'installation, l'installateur créera une entrée de registre +pour vos associations de fichiers. Lorsque vous ouvrez un fichier avec votre application, une nouvelle instance d'application est lancée et le chemin d'accès est passé à +comme argument à votre application. Pour gérer cela, vous devez analyser les arguments de la ligne de commande dans votre application. Exemple: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +Vous pouvez également activer le verrouillage par instance unique pour votre application. Dans ce cas, lorsque vous ouvrez un fichier avec votre application, la nouvelle instance d'application n'est pas lancée +et les arguments sont passés à l'instance déjà en cours d'exécution. Consultez le guide de verrouillage de l'instance unique pour plus de détails. Exemple: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` + +### Linux + +Actuellement, Wails ne prend pas en charge l'association de fichiers pour Linux. Vous devez donc créer des associations de fichiers manuellement. +Par exemple, si vous distribuez votre application en tant que package .deb, vous pouvez créer des associations de fichiers en ajoutant les fichiers requis dans votre bundle. +Vous pouvez utiliser [nfpm](https://nfpm.goreleaser.com/) pour créer un package .deb pour votre application. + +1. Créez un fichier .desktop pour votre application et spécifiez des associations de fichiers là-bas (notez que `%u` est important dans Executive). Exemple: + +```ini +[Desktop Entry] +Categories=Office +Exec=/usr/bin/wails-open-file %u +Icon=wails-open-file.png +Name=wails-open-file +Terminal=false +Type=Application +MimeType=x-scheme-handler/myapp; +``` + +2. Préparez les scripts postInstall/postRemove pour votre paquet. Exemple: + +```sh +# recharger la base de données du bureau pour charger l'application dans la liste des applications disponibles +update-desktop-database /usr/share/applications +``` + +3. Configurez nfpm pour utiliser vos scripts et fichiers. Exemple: + +```yaml +name: "wails-open-file" +arch: "arm64" +platform: "linux" +version: "1.0.0" +section: "default" +priority: "extra" +maintainer: "FooBarCorp " +description: "Sample Package" +vendor: "FooBarCorp" +homepage: "http://example.com" +license: "MIT" +contents: +- src: ../bin/wails-open-file + dst: /usr/bin/wails-open-file +- src: ./main.desktop + dst: /usr/share/applications/wails-open-file.desktop +- src: ../appicon.svg + dst: /usr/share/icons/hicolor/scalable/apps/wails-open-file.svg +# copy icons to Yaru theme as well. For some reason Ubuntu didn't pick up fileicons from hicolor theme +- src: ../appicon.svg + dst: /usr/share/icons/Yaru/scalable/apps/wails-open-file.svg +scripts: + postinstall: ./postInstall.sh + postremove: ./postRemove.sh +``` + +6. Construisez votre paquet .deb en utilisant nfpm: + +```sh +nfpm pkg --packager deb --target . +``` + +7. Maintenant que votre paquet est installé, votre application sera associée aux types de fichiers qui ont été spécifiés. Lorsque vous ouvrez un fichier avec votre application, une nouvelle instance est lancée et le chemin du fichier est passé en argument à votre application. + Pour gérer cela, vous devez analyser les arguments de la ligne de commande dans votre application. Exemple: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +Vous pouvez également activer le verrouillage par instance unique pour votre application. Dans ce cas, lorsque vous ouvrez un fichier avec votre application, la nouvelle instance d'application n'est pas lancée +et les arguments sont passés à l'instance déjà en cours d'exécution. Consultez le guide de verrouillage de l'instance unique pour plus de détails. Exemple: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/dynamic-assets.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/dynamic-assets.mdx new file mode 100644 index 00000000000..f1098b09cb0 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/dynamic-assets.mdx @@ -0,0 +1,142 @@ +# Ressources dynamiques + +:::info + +Cela ne fonctionne pas avec la v5.0.0+ vite et wails v2 en raison des changements dans vite. Des changements sont prévus dans la v3 pour prendre en charge des fonctionnalités similaires sous la v5.0.0+. Si vous avez besoin de cette fonctionnalité, restez avec la v4.0.0+. Regardez l'[issue 3240](https://github.com/wailsapp/wails/issues/3240) pour les détails + +::: + +Si vous voulez charger ou générer des ressources pour votre frontend de manière dynamique, vous pouvez y parvenir en utilisant l'option [AssetsHandler](../reference/options#assetshandler). Le AssetsHandler est un générique`http.Handler` qui sera appelé pour toute requête non GET sur le serveur d'assets et pour les requêtes GET qui ne peuvent pas être servies car l'asset n'est pas trouvé. + +En installant un AssetsHandler personnalisé, vous pouvez servir vos propres ressources en utilisant un serveur de ressources personnalisé. + +## Exemple + +Dans notre exemple de projet, nous allons créer un gestionnaire de ressources simple qui chargera les fichiers à partir du disque: + +```go title=main.go {17-36,49} +package main + +import ( + "embed" + "fmt" + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" + "net/http" + "os" + "strings" +) + +//go:embed all:frontend/dist +var assets embed.FS + +type FileLoader struct { + http.Handler +} + +func NewFileLoader() *FileLoader { + return &FileLoader{} +} + +func (h *FileLoader) ServeHTTP(res http.ResponseWriter, req *http.Request) { + var err error + requestedFilename := strings.TrimPrefix(req.URL.Path, "/") + println("Requesting file:", requestedFilename) + fileData, err := os.ReadFile(requestedFilename) + if err != nil { + res.WriteHeader(http.StatusBadRequest) + res.Write([]byte(fmt.Sprintf("Could not load file %s", requestedFilename))) + } + + res.Write(fileData) +} + +func main() { + // Create an instance of the app structure + app := NewApp() + + // Create application with options + err := wails.Run(&options.App{ + Title: "helloworld", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + Handler: NewFileLoader(), + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 255}, + OnStartup: app.startup, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err) + } +} +``` + +Lorsque nous exécutons l'application en mode dev en utilisant `wails dev`, nous verrons la sortie suivante : + +``` +DEB | [ExternalAssetHandler] Loading 'http://localhost:3001/favicon.ico' +DEB | [ExternalAssetHandler] Loading 'http://localhost:3001/favicon.ico' failed, using AssetHandler +Requesting file: favicon.ico +``` + +Comme vous pouvez le voir, le gestionnaire d'actifs est appelé lorsque le serveur d'assets par défaut est incapable de servir le fichier `favicon.ico`. + +Si vous faites un clic droit sur l'application principale et sélectionnez "inspecter" pour afficher les devtools, vous pouvez tester cette fonctionnalité en tapant ce qui suit dans la console : + +``` +let response = await fetch('does-not-exist.txt'); +``` + +Cela générera une erreur dans les devtools. Nous pouvons voir que l'erreur est ce que nous attendons est retourné par notre gestionnaire de ressources personnalisées : + +```mdx-code-block +

                        + +

                        +``` + +Cependant, si nous demandons `go.mod`, nous verrons la sortie suivante : + +```mdx-code-block +

                        + +

                        +``` + +Cette technique peut être utilisée pour charger des images directement dans la page. Si nous avons mis à jour notre modèle vanilla par défaut et a remplacé l'image du logo : + +```html + +``` + +avec : + +```html + +``` + +Nous verrions ensuite ce qui suit: + +```mdx-code-block +

                        + +

                        +``` + +:::warning + +Exposer votre système de fichiers de cette manière est un risque de sécurité. Il est recommandé de gérer correctement l'accès à votre système de fichiers. + +::: diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/file-association.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/file-association.mdx new file mode 100644 index 00000000000..973a4d21758 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/file-association.mdx @@ -0,0 +1,243 @@ +# Associations de fichiers + +La fonction d'association de fichiers vous permet d'associer des types de fichiers spécifiques à votre application afin que lorsque les utilisateurs ouvrent ces fichiers, +votre application est lancée pour les gérer. Cela peut être particulièrement utile pour les éditeurs de texte, les visualisateurs d'images ou n'importe quelle application +qui fonctionne avec des formats de fichiers spécifiques. Dans ce guide, nous allons parcourir les étapes pour implémenter l'association de fichiers dans l'application Wails. + +## Configurer l'association de fichiers : + +Pour configurer l'association de fichiers, vous devez modifier le fichier wails.json de votre application. +Dans la section "info", ajoutez une section "fileAssociations" spécifiant les types de fichiers auxquels votre application doit être associée. + +Par exemple : + +```json +{ + "info": { + "fileAssociations": [ + { + "ext": "wails", + "name": "Wails", + "description": "Wails Application File", + "iconName": "wailsFileIcon", + "role": "Editor" + }, + { + "ext": "jpg", + "name": "JPEG", + "description": "Image File", + "iconName": "jpegFileIcon", + "role": "Editor" + } + ] + } +} +``` + +| Propriété | Description | +| :----------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| ext | L'extension. ex: png | +| name | Le nom de l'extension. ex: PNG File | +| iconName | Le nom de l'icône sans extension. Les icônes doivent être situées dans le dossier de build. Des icônes appropriées seront générées à partir du fichier .png pour macOS et Windows | +| description | Windows seulement. La description. Il est affiché dans la colonne `Type` dans l'explorateur Windows. | +| role | macOS uniquement. Rôle de l'application par rapport au type. Correspond au rôle CFBundleTypeRole. | + +## Spécificités par platefome : + +### MacOS + +Lorsque vous ouvrez un fichier (ou des fichiers) avec votre application, le système lancera votre application et appellera la fonction `OnFileOpen` dans votre application Wails. Exemple: + +```go title="main.go" +func main() { + // Création d'une application avec des options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + Mac: &mac.Options{ + OnFileOpen: func(filePaths []string) { println(filestring) }, + }, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` + +### Windows + +L'association de fichiers dans Windows n'est prise en charge qu'avec l'installateur NSS. Pendant l'installation, l'installateur créera une entrée de registre +pour vos associations de fichiers. Lorsque vous ouvrez un fichier avec votre application, une nouvelle instance d'application est lancée et le chemin d'accès est passé à +comme argument à votre application. Pour gérer cela, vous devez analyser les arguments de la ligne de commande dans votre application. Exemple: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +Vous pouvez également activer le verrouillage par instance unique pour votre application. Dans ce cas, lorsque vous ouvrez un fichier avec votre application, la nouvelle instance d'application n'est pas lancée +et les arguments sont passés à l'instance déjà en cours d'exécution. Consultez le guide de verrouillage de l'instance unique pour plus de détails. Exemple: + +```go title="main.go" +func main() { + // Création d'une application avec des options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` + +### Linux + +Actuellement, Wails ne prend pas en charge l'association de fichiers pour Linux. Vous devez donc créer des associations de fichiers manuellement. +Par exemple, si vous distribuez votre application en tant que package .deb, vous pouvez créer des associations de fichiers en ajoutant les fichiers requis dans votre bundle. +Vous pouvez utiliser [nfpm](https://nfpm.goreleaser.com/) pour créer un package .deb pour votre application. + +1. Créez un fichier .desktop pour votre application et spécifiez des associations de fichiers là-bas. Exemple: + +```ini +[Desktop Entry] +Categories=Office +Exec=/usr/bin/wails-open-file %u +Icon=wails-open-file.png +Name=wails-open-file +Terminal=false +Type=Application +MimeType=application/x-wails;application/x-test +``` + +2. Créer un fichier de type MIME. Exemple: + +```xml + + + + Wails Application File + + + +``` + +3. Créez des icônes pour vos types de fichiers. Les icônes SVG sont recommandées. +4. Préparez les scripts postInstall/postRemove pour votre paquet. Exemple: + +```sh +# Recharge les types MIME pour enregistrer votre association de fichiers +update-mime-database /usr/share/mime +# Recharge la base de données du bureau afin de rendre disponible votre application dans les choix possibles +update-desktop-database /usr/share/applications +# Mise à jour des icônes +update-icon-caches /usr/share/icons/* +``` + +5. Configurez nfpm pour utiliser vos scripts et fichiers. Exemple: + +```yaml +name: "wails-open-file" +arch: "arm64" +platform: "linux" +version: "1.0.0" +section: "default" +priority: "extra" +maintainer: "FooBarCorp " +description: "Sample Package" +vendor: "FooBarCorp" +homepage: "http://example.com" +license: "MIT" +contents: +- src: ../bin/wails-open-file + dst: /usr/bin/wails-open-file +- src: ./main.desktop + dst: /usr/share/applications/wails-open-file.desktop +- src: ./application-wails-mime.xml + dst: /usr/share/mime/packages/application-x-wails.xml +- src: ./application-test-mime.xml + dst: /usr/share/mime/packages/application-x-test.xml +- src: ../appicon.svg + dst: /usr/share/icons/hicolor/scalable/apps/wails-open-file.svg +- src: ../wailsFileIcon.svg + dst: /usr/share/icons/hicolor/scalable/mimetypes/application-x-wails.svg +- src: ../testFileIcon.svg + dst: /usr/share/icons/hicolor/scalable/mimetypes/application-x-test.svg +# copy icons to Yaru theme as well. For some reason Ubuntu didn't pick up fileicons from hicolor theme +- src: ../appicon.svg + dst: /usr/share/icons/Yaru/scalable/apps/wails-open-file.svg +- src: ../wailsFileIcon.svg + dst: /usr/share/icons/Yaru/scalable/mimetypes/application-x-wails.svg +- src: ../testFileIcon.svg + dst: /usr/share/icons/Yaru/scalable/mimetypes/application-x-test.svg +scripts: + postinstall: ./postInstall.sh + postremove: ./postRemove.sh +``` + +6. Construisez votre paquet .deb en utilisant nfpm: + +```sh +nfpm pkg --packager deb --target . +``` + +7. Maintenant que votre paquet est installé, votre application sera associée aux types de fichiers qui ont été spécifiés. Lorsque vous ouvrez un fichier avec votre application, une nouvelle instance est lancée et le chemin du fichier est passé en argument à votre application. + Pour gérer cela, vous devez analyser les arguments de la ligne de commande dans votre application. Exemple: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +Vous pouvez également activer le verrouillage par instance unique pour votre application. Dans ce cas, lorsque vous ouvrez un fichier avec votre application, la nouvelle instance d'application n'est pas lancée +et les arguments sont passés à l'instance déjà en cours d'exécution. Consultez le guide de verrouillage de l'instance unique pour plus de détails. Exemple: + +```go title="main.go" +func main() { + // Création d'une application avec des options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/frameless.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/frameless.mdx new file mode 100644 index 00000000000..bbeb338f1b6 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/frameless.mdx @@ -0,0 +1,87 @@ +# Applications sans cadre + +Wails prend en charge la création d'applications qui n'ont pas de cadres. Ceci peut être réalisé en utilisant le champ [frameless](../reference/options.mdx#frameless) dans [Application Options](../reference/options.mdx#application-options). + +Wails offre une solution simple pour faire glisser la fenêtre: N'importe quel élément HTML qui a le style CSS `--wails-draggable:drag` agira comme une "poignée de glisser". Cette propriété s'applique à tous les éléments enfants. Si vous devez indiquer qu'un élément imbriqué ne doit pas glisser, alors utilisez l'attribut '--wails-draggable:no-drag' sur cet élément. + +```html + + + + + + + +
                        + + +
                        +
                        + + + + +``` + +Pour certains projets, l'utilisation d'une variable CSS peut ne pas être possible en raison du style dynamique. Dans ce cas, vous pouvez utiliser les options `CSSDragProperty` et `CSSDragValue` pour définir une propriété et une valeur qui seront utilisées pour indiquer régions glissables : + +```go title=main.go +package main + +import ( + "embed" + + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" +) + +//go:embed all:frontend/dist +var assets embed.FS + +func main() { + // Create an instance of the app structure + app := NewApp() + + // Create application with options + err := wails.Run(&options.App{ + Title: "alwaysontop", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Frameless: true, + CSSDragProperty: "widows", + CSSDragValue: "1", + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err) + } +} +``` + +```html title=index.html + + + + + + alwaysontop + + +
                        + + + +``` + +:::info Plein écran + +Si vous autorisez votre application à être en plein écran, cette fonctionnalité de glissement sera désactivée. + +::: diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/frontend.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/frontend.mdx new file mode 100644 index 00000000000..ea101019ad8 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/frontend.mdx @@ -0,0 +1,72 @@ +# Frontend + +## Injection de script + +Quand Wails sert votre fichier `index.html`, par défaut, il injectera 2 entrées de script dans la balise `` pour charger `/wails/ipc.js` et `/wails/runtime.js`. Ces fichiers installent respectivement les bindings et les runtime. + +Le code ci-dessous montre où ils sont injectés par défaut : + +```html + + + injection example + + + + + + + +
                        Please enter your name below 👇
                        +
                        + + +
                        + + + + +``` + +### Remplacer l'injection de script par défaut + +Pour fournir plus de flexibilité aux développeurs, il y a une balise meta qui peut être utilisée pour personnaliser ce comportement: + +```html + +``` + +Les options sont les suivantes : + +| Valeur | Description | +| ------------------- | -------------------------------------------------------------- | +| noautoinjectruntime | Pour désactiver l'injection automatique de `/wails/runtime.js` | +| noautoinjectipc | Pour désactiver l'injection automatique de `/wails/ipc.js` | +| noautoinject | Pour désactiver l'injection automatique de tous les scripts | + +Plusieurs options peuvent être utilisées à condition qu'elles soient séparées par des virgules. + +Ce code est parfaitement valide et fonctionne de la même manière que la version avec l'auto-injection : + +```html + + + injection example + + + + + + +
                        Please enter your name below 👇
                        +
                        + + +
                        + + + + + + +``` diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/ides.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/ides.mdx new file mode 100644 index 00000000000..887937954a2 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/ides.mdx @@ -0,0 +1,127 @@ +# IDEs + +Wails vise à fournir une grande expérience de développement. À cet effet, nous supportons maintenant la génération d'une configuration spécifique IDE pour fournir une configuration plus souple du projet. + +Actuellement, nous prenons en charge [Visual Studio Code](https://code.visualstudio.com/) et [Goland](https://www.jetbrains.com/go/). + +## Visual Studio Code + +```mdx-code-block +

                        + +

                        +``` + +Lors de la génération d'un projet en utilisant l'option `-ide vscode` , les fichiers IDE seront créés à côté des autres fichiers du projet. Ces fichiers sont placés dans le répertoire `.vscode` et fournissent la configuration correcte pour déboguer votre application. + +Les 2 fichiers générés sont `tasks.json` et `launch.json`. Ci-dessous se trouvent les fichiers générés par défaut : + +```json title="tasks.json" +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "type": "shell", + "options": { + "cwd": "${workspaceFolder}" + }, + "command": "go", + "args": [ + "build", + "-tags", + "dev", + "-gcflags", + "all=-N -l", + "-o", + "build/bin/myproject.exe" + ] + } + ] +} +``` + +```json title="launch.json" +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Wails: Debug myproject", + "type": "go", + "request": "launch", + "mode": "exec", + "program": "${workspaceFolder}/build/bin/myproject.exe", + "preLaunchTask": "build", + "cwd": "${workspaceFolder}", + "env": {} + } + ] +} +``` + +### Configuration des étapes d'installation et de construction + +Le fichier `tasks.json` est simple pour le projet par défaut car il n'y a pas d'étapes `npm install` ou `npm build` nécessaire. Pour les projets qui ont une étape de construction en frontend comme avec Svelte, nous devrions modifier `tasks.json` pour ajouter les étapes d'installation et de construction suivantes : + +```json title="tasks.json" +{ + "version": "2.0.0", + "tasks": [ + { + "label": "npm install", + "type": "npm", + "script": "install", + "options": { + "cwd": "${workspaceFolder}/frontend" + }, + "presentation": { + "clear": true, + "panel": "shared", + "showReuseMessage": false + }, + "problemMatcher": [] + }, + { + "label": "npm run build", + "type": "npm", + "script": "build", + "options": { + "cwd": "${workspaceFolder}/frontend" + }, + "presentation": { + "clear": true, + "panel": "shared", + "showReuseMessage": false + }, + "problemMatcher": [] + }, + { + "label": "build", + "type": "shell", + "options": { + "cwd": "${workspaceFolder}" + }, + "command": "go", + "args": [ + "build", + "-tags", + "dev", + "-gcflags", + "all=-N -l", + "-o", + "build/bin/vscode.exe" + ], + "dependsOn": ["npm install", "npm run build"] + } + ] +} +``` + +:::info Améliorations futures + +Dans le futur, nous espérons générer un `tasks.json` qui inclut les étapes d'installation et de construction automatiquement. + +::: diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/linux-distro-support.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/linux-distro-support.mdx new file mode 100644 index 00000000000..6bd2002fce7 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/linux-distro-support.mdx @@ -0,0 +1,103 @@ +# Prise en charge des distributions Linux + +## Vue d'ensemble + +Wails offre le support de Linux, mais fournir des instructions d'installation pour toutes les distributions disponibles est une tâche impossible. À la place, Wails essaie de déterminer si les paquets dont vous avez besoin pour développer des applications sont disponibles via le gestionnaire de paquets de votre système. Actuellement, nous supportons les gestionnaires de paquets suivants : + +- apt +- dnf +- emerge +- eopkg +- nixpkgs +- pacman +- zypper + +## Ajout des noms de paquets + +Il peut y avoir des cas où votre distribution de linux utilise un des gestionnaires de paquets pris en charge mais le nom du paquet est différent. Par exemple, vous pouvez utiliser un dérivé Ubuntu, mais le nom du paquet pour gtk peut être différent. Wails tente de trouver le paquet correct en itérant une liste de noms de paquets. La liste des paquets est stockée dans un fichier spécifique dans le dossier `v2/internal/system/packagemanager` . Dans notre exemple, ce serait `v2/internal/system/packagemanager/apt.go`. + +Dans ce fichier, la liste des paquets est définie par la méthode `Packages()`: + +```go +func (a *Apt) Packages() packagemap { + return packagemap{ + "libgtk-3": []*Package{ + {Name: "libgtk-3-dev", SystemPackage: true, Library: true}, + }, + "libwebkit": []*Package{ + {Name: "libwebkit2gtk-4.0-dev", SystemPackage: true, Library: true}, + }, + "gcc": []*Package{ + {Name: "build-essential", SystemPackage: true}, + }, + "pkg-config": []*Package{ + {Name: "pkg-config", SystemPackage: true}, + }, + "npm": []*Package{ + {Name: "npm", SystemPackage: true}, + }, + "docker": []*Package{ + {Name: "docker.io", SystemPackage: true, Optional: true}, + }, + } +} +``` + +Supposons que dans notre distribution linux, `libgtk-3` est empaqueté sous le nom `lib-gtk3-dev`. Nous pourrions ajouter le support de ce paquet en ajoutant la ligne suivante : + +```go {5} +func (a *Apt) Packages() packagemap { + return packagemap{ + "libgtk-3": []*Package{ + {Name: "libgtk-3-dev", SystemPackage: true, Library: true}, + {Name: "lib-gtk3-dev", SystemPackage: true, Library: true}, + }, + "libwebkit": []*Package{ + {Name: "libwebkit2gtk-4.0-dev", SystemPackage: true, Library: true}, + }, + "gcc": []*Package{ + {Name: "build-essential", SystemPackage: true}, + }, + "pkg-config": []*Package{ + {Name: "pkg-config", SystemPackage: true}, + }, + "npm": []*Package{ + {Name: "npm", SystemPackage: true}, + }, + "docker": []*Package{ + {Name: "docker.io", SystemPackage: true, Optional: true}, + }, + } +} +``` + +## Ajout de nouveaux gestionnaires de paquets + +Pour ajouter un nouveau gestionnaire de paquets, effectuez les étapes suivantes : + +- Créez un nouveau fichier dans `v2/internal/system/packagemanager` appelé `.go`, où `` est le nom du gestionnaire de paquets. +- Définit une structure conforme à l'interface du gestionnaire de paquets définie dans `pm.go`: + +```go +type PackageManager interface { + Name() string + Packages() packagemap + PackageInstalled(*Package) (bool, error) + PackageAvailable(*Package) (bool, error) + InstallCommand(*Package) string +} +``` + +- `Name()` doit retourner le nom du gestionnaire de paquets +- `Packages()` doit retourner une `packagemap`, qui fournit des noms de fichiers candidats pour les dépendances +- `PackageInstalled()` devrait retourner `true` si le paquet donné est installé +- `PackageAvailable()` devrait retourner `true` si le paquet donné n'est pas installé mais disponible pour l'installation +- `InstallCommand()` doit retourner la commande exacte pour installer le nom du paquet donné + +Jetez un coup d'œil au code des autres gestionnaires de paquets pour avoir une idée de comment cela fonctionne. + +:::info Rappel + +Si vous ajoutez le support d'un nouveau gestionnaire de paquets, n'oubliez pas de mettre également à jour cette page ! + +::: diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/linux.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/linux.mdx new file mode 100644 index 00000000000..6df9f0fe0d2 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.13.0/guides/linux.mdx @@ -0,0 +1,70 @@ +# Linux + +Cette page a divers guides liés au développement d'applications Wails pour Linux. + +## Le tag vidéo ne déclenche pas l'événement "ended" + +Lorsque vous utilisez un tag vidéo, l'événement "terminé" n'est pas déclenché lorsque la vidéo est finie. Ceci est un bogue dans WebkitGTK, cependant vous pouvez utiliser le contournement suivant pour le corriger : + +```js +videoTag.addEventListener("timeupdate", (event) => { + if (event.target.duration - event.target.currentTime < 0.2) { + let ended = new Event("ended"); + event.target.dispatchEvent(ended); + } +}); +``` + +Source : [Lyimmi](https://github.com/Lyimmi) sur le [forum de discussion](https://github.com/wailsapp/wails/issues/1729#issuecomment-1212291275) + +## Erreur GStreamer lors de l'utilisation d'éléments audio ou vidéo + +Si vous voyez l'erreur suivante lorsque vous incluez les éléments `