@mnaoumov/obsidian-dev-toolkit 0.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +15 -1
- package/bundlers/esbuild/package.json +6 -0
- package/bundlers/esbuild-impl/copy-to-obsidian-plugins-folder-plugin/package.json +6 -0
- package/bundlers/esbuild-impl/dependency/package.json +6 -0
- package/bundlers/esbuild-impl/fix-source-maps-plugin/package.json +6 -0
- package/bundlers/esbuild-impl/index/package.json +6 -0
- package/bundlers/esbuild-impl/obsidian-plugin-builder/package.json +6 -0
- package/bundlers/esbuild-impl/package.json +6 -0
- package/bundlers/esbuild-impl/preprocess-plugin/package.json +6 -0
- package/bundlers/esbuild-impl/rename-css-plugin/package.json +6 -0
- package/bundlers/index/package.json +6 -0
- package/bundlers/package.json +6 -0
- package/dist/demo-vault-helper/main.js +1264 -0
- package/dist/demo-vault-helper/manifest.json +9 -0
- package/dist/integration-test-plugin/main.js +54167 -0
- package/dist/integration-test-plugin/manifest.json +8 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/copy-to-obsidian-plugins-folder-plugin.cjs +322 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/copy-to-obsidian-plugins-folder-plugin.d.cts +38 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/dependency.cjs +240 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/dependency.d.cts +20 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/fix-source-maps-plugin.cjs +213 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/fix-source-maps-plugin.d.cts +34 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/index.cjs +179 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/index.d.cts +7 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/obsidian-plugin-builder.cjs +362 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/obsidian-plugin-builder.d.cts +98 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/preprocess-plugin.cjs +234 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/preprocess-plugin.d.cts +30 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/rename-css-plugin.cjs +171 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/rename-css-plugin.d.cts +14 -0
- package/dist/lib/cjs/bundlers/esbuild.cjs +164 -0
- package/dist/lib/cjs/bundlers/esbuild.d.cts +11 -0
- package/dist/lib/cjs/bundlers/index.cjs +167 -0
- package/dist/lib/cjs/bundlers/index.d.cts +3 -0
- package/dist/lib/cjs/demo-vault-app-json.cjs +186 -0
- package/dist/lib/cjs/demo-vault-app-json.d.cts +93 -0
- package/dist/lib/cjs/demo-vault-buttons.cjs +567 -0
- package/dist/lib/cjs/demo-vault-buttons.d.cts +259 -0
- package/dist/lib/cjs/demo-vault-coverage.cjs +713 -0
- package/dist/lib/cjs/demo-vault-coverage.d.cts +533 -0
- package/dist/lib/cjs/demo-vault.cjs +296 -0
- package/dist/lib/cjs/demo-vault.d.cts +33 -0
- package/dist/lib/cjs/formatters/dprint.cjs +160 -0
- package/dist/lib/cjs/formatters/dprint.d.cts +15 -0
- package/dist/lib/cjs/formatters/index.cjs +164 -0
- package/dist/lib/cjs/formatters/index.d.cts +2 -0
- package/dist/lib/cjs/index.cjs +194 -0
- package/dist/lib/cjs/index.d.cts +16 -0
- package/dist/lib/cjs/integration-test-setup.cjs +129 -0
- package/dist/lib/cjs/integration-test-setup.d.cts +33 -0
- package/dist/lib/cjs/integration-test-vitest-global-setup.cjs +163 -0
- package/dist/lib/cjs/integration-test-vitest-global-setup.d.cts +39 -0
- package/dist/lib/cjs/jest-setup.cjs +134 -0
- package/dist/lib/cjs/jest-setup.d.cts +13 -0
- package/dist/lib/cjs/linters/eslint-config.cjs +403 -0
- package/dist/lib/cjs/linters/eslint-config.d.cts +25 -0
- package/dist/lib/cjs/linters/eslint-rules/index.cjs +200 -0
- package/dist/lib/cjs/linters/eslint-rules/index.d.cts +14 -0
- package/dist/lib/cjs/linters/eslint-rules/manifest-description.cjs +255 -0
- package/dist/lib/cjs/linters/eslint-rules/manifest-description.d.cts +54 -0
- package/dist/lib/cjs/linters/eslint-rules/manifest-helpers.cjs +218 -0
- package/dist/lib/cjs/linters/eslint-rules/manifest-helpers.d.cts +141 -0
- package/dist/lib/cjs/linters/eslint-rules/manifest-id.cjs +215 -0
- package/dist/lib/cjs/linters/eslint-rules/manifest-id.d.cts +32 -0
- package/dist/lib/cjs/linters/eslint-rules/manifest-name.cjs +216 -0
- package/dist/lib/cjs/linters/eslint-rules/manifest-name.d.cts +30 -0
- package/dist/lib/cjs/linters/eslint-rules/manifest-schema.cjs +316 -0
- package/dist/lib/cjs/linters/eslint-rules/manifest-schema.d.cts +45 -0
- package/dist/lib/cjs/linters/eslint-rules/no-local-obsidian-internals.cjs +259 -0
- package/dist/lib/cjs/linters/eslint-rules/no-local-obsidian-internals.d.cts +10 -0
- package/dist/lib/cjs/linters/eslint-rules/no-over-cap-wait-in-eval-in-obsidian.cjs +657 -0
- package/dist/lib/cjs/linters/eslint-rules/no-over-cap-wait-in-eval-in-obsidian.d.cts +10 -0
- package/dist/lib/cjs/linters/eslint-rules/no-untrusted-input-events.cjs +247 -0
- package/dist/lib/cjs/linters/eslint-rules/no-untrusted-input-events.d.cts +10 -0
- package/dist/lib/cjs/linters/eslint-rules/obsidian-dev-utils-plugin.cjs +181 -0
- package/dist/lib/cjs/linters/eslint-rules/obsidian-dev-utils-plugin.d.cts +13 -0
- package/dist/lib/cjs/linters/eslint-rules/plugin-name-as-code-in-ui.cjs +263 -0
- package/dist/lib/cjs/linters/eslint-rules/plugin-name-as-code-in-ui.d.cts +30 -0
- package/dist/lib/cjs/linters/eslint-rules/plugin-name-as-code.cjs +215 -0
- package/dist/lib/cjs/linters/eslint-rules/plugin-name-as-code.d.cts +29 -0
- package/dist/lib/cjs/linters/eslint-rules/require-component-suffix.cjs +278 -0
- package/dist/lib/cjs/linters/eslint-rules/require-component-suffix.d.cts +18 -0
- package/dist/lib/cjs/linters/eslint-rules/require-plugin-api-contract-schemas.cjs +306 -0
- package/dist/lib/cjs/linters/eslint-rules/require-plugin-api-contract-schemas.d.cts +10 -0
- package/dist/lib/cjs/linters/eslint.cjs +160 -0
- package/dist/lib/cjs/linters/eslint.d.cts +15 -0
- package/dist/lib/cjs/linters/index.cjs +185 -0
- package/dist/lib/cjs/linters/index.d.cts +9 -0
- package/dist/lib/cjs/linters/markdownlint-cli2-config.cjs +171 -0
- package/dist/lib/cjs/linters/markdownlint-cli2-config.d.cts +12 -0
- package/dist/lib/cjs/linters/markdownlint-rules/index.cjs +164 -0
- package/dist/lib/cjs/linters/markdownlint-rules/index.d.cts +2 -0
- package/dist/lib/cjs/linters/markdownlint-rules/plugin-name-as-code.cjs +246 -0
- package/dist/lib/cjs/linters/markdownlint-rules/plugin-name-as-code.d.cts +32 -0
- package/dist/lib/cjs/linters/markdownlint.cjs +160 -0
- package/dist/lib/cjs/linters/markdownlint.d.cts +15 -0
- package/dist/lib/cjs/linters/obsidianmd-rule-custom-message.cjs +176 -0
- package/dist/lib/cjs/linters/obsidianmd-rule-custom-message.d.cts +40 -0
- package/dist/lib/cjs/linters/plugin-names.cjs +249 -0
- package/dist/lib/cjs/linters/plugin-names.d.cts +81 -0
- package/dist/lib/cjs/obsidian-plugin-repo-paths.cjs +216 -0
- package/dist/lib/cjs/obsidian-plugin-repo-paths.d.cts +253 -0
- package/dist/lib/cjs/setup.cjs +163 -0
- package/dist/lib/cjs/setup.d.cts +21 -0
- package/dist/lib/cjs/templates.cjs +172 -0
- package/dist/lib/cjs/templates.d.cts +13 -0
- package/dist/lib/cjs/test-runners/index.cjs +170 -0
- package/dist/lib/cjs/test-runners/index.d.cts +4 -0
- package/dist/lib/cjs/test-runners/integration-test-plugin.cjs +211 -0
- package/dist/lib/cjs/test-runners/integration-test-plugin.d.cts +44 -0
- package/dist/lib/cjs/test-runners/performance-eval-cap.cjs +157 -0
- package/dist/lib/cjs/test-runners/performance-eval-cap.d.cts +27 -0
- package/dist/lib/cjs/test-runners/stale-build-global-setup.cjs +217 -0
- package/dist/lib/cjs/test-runners/stale-build-global-setup.d.cts +86 -0
- package/dist/lib/cjs/test-runners/vitest-config.cjs +484 -0
- package/dist/lib/cjs/test-runners/vitest-config.d.cts +200 -0
- package/dist/lib/cjs/version.cjs +262 -0
- package/dist/lib/cjs/version.d.cts +92 -0
- package/dist/lib/cjs/vitest-setup.cjs +134 -0
- package/dist/lib/cjs/vitest-setup.d.cts +11 -0
- package/dist/lib/esm/bundlers/esbuild-impl/copy-to-obsidian-plugins-folder-plugin.d.mts +38 -0
- package/dist/lib/esm/bundlers/esbuild-impl/copy-to-obsidian-plugins-folder-plugin.mjs +218 -0
- package/dist/lib/esm/bundlers/esbuild-impl/dependency.d.mts +20 -0
- package/dist/lib/esm/bundlers/esbuild-impl/dependency.mjs +130 -0
- package/dist/lib/esm/bundlers/esbuild-impl/fix-source-maps-plugin.d.mts +34 -0
- package/dist/lib/esm/bundlers/esbuild-impl/fix-source-maps-plugin.mjs +108 -0
- package/dist/lib/esm/bundlers/esbuild-impl/index.d.mts +7 -0
- package/dist/lib/esm/bundlers/esbuild-impl/index.mjs +56 -0
- package/dist/lib/esm/bundlers/esbuild-impl/obsidian-plugin-builder.d.mts +98 -0
- package/dist/lib/esm/bundlers/esbuild-impl/obsidian-plugin-builder.mjs +247 -0
- package/dist/lib/esm/bundlers/esbuild-impl/preprocess-plugin.d.mts +30 -0
- package/dist/lib/esm/bundlers/esbuild-impl/preprocess-plugin.mjs +126 -0
- package/dist/lib/esm/bundlers/esbuild-impl/rename-css-plugin.d.mts +14 -0
- package/dist/lib/esm/bundlers/esbuild-impl/rename-css-plugin.mjs +63 -0
- package/dist/lib/esm/bundlers/esbuild.d.mts +11 -0
- package/dist/lib/esm/bundlers/esbuild.mjs +58 -0
- package/dist/lib/esm/bundlers/index.d.mts +3 -0
- package/dist/lib/esm/bundlers/index.mjs +48 -0
- package/dist/lib/esm/demo-vault-app-json.d.mts +93 -0
- package/dist/lib/esm/demo-vault-app-json.mjs +75 -0
- package/dist/lib/esm/demo-vault-buttons.d.mts +259 -0
- package/dist/lib/esm/demo-vault-buttons.mjs +452 -0
- package/dist/lib/esm/demo-vault-coverage.d.mts +533 -0
- package/dist/lib/esm/demo-vault-coverage.mjs +619 -0
- package/dist/lib/esm/demo-vault.d.mts +33 -0
- package/dist/lib/esm/demo-vault.mjs +197 -0
- package/dist/lib/esm/formatters/dprint.d.mts +15 -0
- package/dist/lib/esm/formatters/dprint.mjs +52 -0
- package/dist/lib/esm/formatters/index.d.mts +2 -0
- package/dist/lib/esm/formatters/index.mjs +46 -0
- package/dist/lib/esm/index.d.mts +16 -0
- package/dist/lib/esm/index.mjs +66 -0
- package/dist/lib/esm/integration-test-setup.d.mts +33 -0
- package/dist/lib/esm/integration-test-setup.mjs +44 -0
- package/dist/lib/esm/integration-test-vitest-global-setup.d.mts +39 -0
- package/dist/lib/esm/integration-test-vitest-global-setup.mjs +57 -0
- package/dist/lib/esm/jest-setup.d.mts +13 -0
- package/dist/lib/esm/jest-setup.mjs +53 -0
- package/dist/lib/esm/linters/eslint-config.d.mts +25 -0
- package/dist/lib/esm/linters/eslint-config.mjs +290 -0
- package/dist/lib/esm/linters/eslint-rules/index.d.mts +14 -0
- package/dist/lib/esm/linters/eslint-rules/index.mjs +70 -0
- package/dist/lib/esm/linters/eslint-rules/manifest-description.d.mts +54 -0
- package/dist/lib/esm/linters/eslint-rules/manifest-description.mjs +146 -0
- package/dist/lib/esm/linters/eslint-rules/manifest-helpers.d.mts +141 -0
- package/dist/lib/esm/linters/eslint-rules/manifest-helpers.mjs +90 -0
- package/dist/lib/esm/linters/eslint-rules/manifest-id.d.mts +32 -0
- package/dist/lib/esm/linters/eslint-rules/manifest-id.mjs +109 -0
- package/dist/lib/esm/linters/eslint-rules/manifest-name.d.mts +30 -0
- package/dist/lib/esm/linters/eslint-rules/manifest-name.mjs +110 -0
- package/dist/lib/esm/linters/eslint-rules/manifest-schema.d.mts +45 -0
- package/dist/lib/esm/linters/eslint-rules/manifest-schema.mjs +212 -0
- package/dist/lib/esm/linters/eslint-rules/no-local-obsidian-internals.d.mts +10 -0
- package/dist/lib/esm/linters/eslint-rules/no-local-obsidian-internals.mjs +150 -0
- package/dist/lib/esm/linters/eslint-rules/no-over-cap-wait-in-eval-in-obsidian.d.mts +10 -0
- package/dist/lib/esm/linters/eslint-rules/no-over-cap-wait-in-eval-in-obsidian.mjs +551 -0
- package/dist/lib/esm/linters/eslint-rules/no-untrusted-input-events.d.mts +10 -0
- package/dist/lib/esm/linters/eslint-rules/no-untrusted-input-events.mjs +138 -0
- package/dist/lib/esm/linters/eslint-rules/obsidian-dev-utils-plugin.d.mts +13 -0
- package/dist/lib/esm/linters/eslint-rules/obsidian-dev-utils-plugin.mjs +73 -0
- package/dist/lib/esm/linters/eslint-rules/plugin-name-as-code-in-ui.d.mts +30 -0
- package/dist/lib/esm/linters/eslint-rules/plugin-name-as-code-in-ui.mjs +157 -0
- package/dist/lib/esm/linters/eslint-rules/plugin-name-as-code.d.mts +29 -0
- package/dist/lib/esm/linters/eslint-rules/plugin-name-as-code.mjs +108 -0
- package/dist/lib/esm/linters/eslint-rules/require-component-suffix.d.mts +18 -0
- package/dist/lib/esm/linters/eslint-rules/require-component-suffix.mjs +167 -0
- package/dist/lib/esm/linters/eslint-rules/require-plugin-api-contract-schemas.d.mts +10 -0
- package/dist/lib/esm/linters/eslint-rules/require-plugin-api-contract-schemas.mjs +197 -0
- package/dist/lib/esm/linters/eslint.d.mts +15 -0
- package/dist/lib/esm/linters/eslint.mjs +52 -0
- package/dist/lib/esm/linters/index.d.mts +9 -0
- package/dist/lib/esm/linters/index.mjs +60 -0
- package/dist/lib/esm/linters/markdownlint-cli2-config.d.mts +12 -0
- package/dist/lib/esm/linters/markdownlint-cli2-config.mjs +66 -0
- package/dist/lib/esm/linters/markdownlint-rules/index.d.mts +2 -0
- package/dist/lib/esm/linters/markdownlint-rules/index.mjs +46 -0
- package/dist/lib/esm/linters/markdownlint-rules/plugin-name-as-code.d.mts +32 -0
- package/dist/lib/esm/linters/markdownlint-rules/plugin-name-as-code.mjs +130 -0
- package/dist/lib/esm/linters/markdownlint.d.mts +15 -0
- package/dist/lib/esm/linters/markdownlint.mjs +52 -0
- package/dist/lib/esm/linters/obsidianmd-rule-custom-message.d.mts +40 -0
- package/dist/lib/esm/linters/obsidianmd-rule-custom-message.mjs +67 -0
- package/dist/lib/esm/linters/plugin-names.d.mts +81 -0
- package/dist/lib/esm/linters/plugin-names.mjs +141 -0
- package/dist/lib/esm/obsidian-plugin-repo-paths.d.mts +253 -0
- package/dist/lib/esm/obsidian-plugin-repo-paths.mjs +108 -0
- package/dist/lib/esm/setup.d.mts +21 -0
- package/dist/lib/esm/setup.mjs +55 -0
- package/dist/lib/esm/templates.d.mts +13 -0
- package/dist/lib/esm/templates.mjs +57 -0
- package/dist/lib/esm/test-runners/index.d.mts +4 -0
- package/dist/lib/esm/test-runners/index.mjs +50 -0
- package/dist/lib/esm/test-runners/integration-test-plugin.d.mts +44 -0
- package/dist/lib/esm/test-runners/integration-test-plugin.mjs +94 -0
- package/dist/lib/esm/test-runners/performance-eval-cap.d.mts +27 -0
- package/dist/lib/esm/test-runners/performance-eval-cap.mjs +48 -0
- package/dist/lib/esm/test-runners/stale-build-global-setup.d.mts +86 -0
- package/dist/lib/esm/test-runners/stale-build-global-setup.mjs +115 -0
- package/dist/lib/esm/test-runners/vitest-config.d.mts +200 -0
- package/dist/lib/esm/test-runners/vitest-config.mjs +369 -0
- package/dist/lib/esm/version.d.mts +92 -0
- package/dist/lib/esm/version.mjs +160 -0
- package/dist/lib/esm/vitest-setup.d.mts +11 -0
- package/dist/lib/esm/vitest-setup.mjs +53 -0
- package/dist/templates/.markdownlint-cli2.mjs +4 -0
- package/dist/templates/.nano-staged.mjs +4 -0
- package/dist/templates/commitlint.config.ts +3 -0
- package/dist/templates/dprint.json +26 -0
- package/dist/templates/eslint.config.mts +3 -0
- package/dist/templates/scripts/build/build-clean.ts +4 -0
- package/dist/templates/scripts/build/build-compile-svelte.ts +4 -0
- package/dist/templates/scripts/build/build-compile-typescript.ts +4 -0
- package/dist/templates/scripts/build/build-compile.ts +4 -0
- package/dist/templates/scripts/build/build-templates.ts +4 -0
- package/dist/templates/scripts/bundlers/esbuild/build.ts +4 -0
- package/dist/templates/scripts/bundlers/esbuild/dev.ts +4 -0
- package/dist/templates/scripts/commitlint-config.ts +3 -0
- package/dist/templates/scripts/eslint-config.ts +10 -0
- package/dist/templates/scripts/formatters/dprint/format-check.ts +8 -0
- package/dist/templates/scripts/formatters/dprint/format.ts +8 -0
- package/dist/templates/scripts/gate/gate.ts +10 -0
- package/dist/templates/scripts/linters/cspell/spellcheck.ts +8 -0
- package/dist/templates/scripts/linters/eslint/lint-fix.ts +8 -0
- package/dist/templates/scripts/linters/eslint/lint.ts +8 -0
- package/dist/templates/scripts/linters/markdownlint/lint-md-fix.ts +8 -0
- package/dist/templates/scripts/linters/markdownlint/lint-md.ts +8 -0
- package/dist/templates/scripts/linters/over-exposure/find-overexposed-fix.ts +25 -0
- package/dist/templates/scripts/linters/over-exposure/find-overexposed.ts +15 -0
- package/dist/templates/scripts/markdownlint-cli2-config.ts +3 -0
- package/dist/templates/scripts/nano-staged-config.ts +3 -0
- package/dist/templates/scripts/test-runners/vitest/test-coverage.ts +4 -0
- package/dist/templates/scripts/test-runners/vitest/test-watch.ts +4 -0
- package/dist/templates/scripts/test-runners/vitest/test.ts +4 -0
- package/dist/templates/scripts/version/version.ts +10 -0
- package/dist/templates/scripts/vitest-config.ts +3 -0
- package/dist/templates/vitest.config.ts +3 -0
- package/formatters/dprint/package.json +6 -0
- package/formatters/index/package.json +6 -0
- package/formatters/package.json +6 -0
- package/linters/eslint/package.json +6 -0
- package/linters/eslint-config/package.json +6 -0
- package/linters/eslint-rules/index/package.json +6 -0
- package/linters/eslint-rules/manifest-description/package.json +6 -0
- package/linters/eslint-rules/manifest-helpers/package.json +6 -0
- package/linters/eslint-rules/manifest-id/package.json +6 -0
- package/linters/eslint-rules/manifest-name/package.json +6 -0
- package/linters/eslint-rules/manifest-schema/package.json +6 -0
- package/linters/eslint-rules/no-local-obsidian-internals/package.json +6 -0
- package/linters/eslint-rules/no-over-cap-wait-in-eval-in-obsidian/package.json +6 -0
- package/linters/eslint-rules/no-untrusted-input-events/package.json +6 -0
- package/linters/eslint-rules/obsidian-dev-utils-plugin/package.json +6 -0
- package/linters/eslint-rules/package.json +6 -0
- package/linters/eslint-rules/plugin-name-as-code/package.json +6 -0
- package/linters/eslint-rules/plugin-name-as-code-in-ui/package.json +6 -0
- package/linters/eslint-rules/require-component-suffix/package.json +6 -0
- package/linters/eslint-rules/require-plugin-api-contract-schemas/package.json +6 -0
- package/linters/index/package.json +6 -0
- package/linters/markdownlint/package.json +6 -0
- package/linters/markdownlint-cli2-config/package.json +6 -0
- package/linters/markdownlint-rules/index/package.json +6 -0
- package/linters/markdownlint-rules/package.json +6 -0
- package/linters/markdownlint-rules/plugin-name-as-code/package.json +6 -0
- package/linters/obsidianmd-rule-custom-message/package.json +6 -0
- package/linters/package.json +6 -0
- package/linters/plugin-names/package.json +6 -0
- package/package.json +302 -13
- package/test-runners/index/package.json +6 -0
- package/test-runners/integration-test-plugin/package.json +6 -0
- package/test-runners/package.json +6 -0
- package/test-runners/performance-eval-cap/package.json +6 -0
- package/test-runners/stale-build-global-setup/package.json +6 -0
- package/test-runners/vitest-config/package.json +6 -0
|
@@ -0,0 +1,657 @@
|
|
|
1
|
+
/*
|
|
2
|
+
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
|
3
|
+
if you want to view the source, please visit the github repository of this plugin
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
(function () {
|
|
7
|
+
function ensureDisposeSymbols(symbolConstructor = Symbol) {
|
|
8
|
+
symbolConstructor.asyncDispose ??= symbolConstructor.for("Symbol.asyncDispose");
|
|
9
|
+
symbolConstructor.dispose ??= symbolConstructor.for("Symbol.dispose");
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function ensureBrowserProcess() {
|
|
13
|
+
const browserProcess = {
|
|
14
|
+
browser: true,
|
|
15
|
+
cwd() {
|
|
16
|
+
return "/";
|
|
17
|
+
},
|
|
18
|
+
env: {},
|
|
19
|
+
platform: "android"
|
|
20
|
+
};
|
|
21
|
+
const existingProcess = globalThis.process;
|
|
22
|
+
if (!existingProcess) {
|
|
23
|
+
globalThis.process = browserProcess;
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (existingProcess.versions?.node) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const existingProcessRecord = existingProcess;
|
|
30
|
+
for (const [key, value] of Object.entries(browserProcess)) {
|
|
31
|
+
existingProcessRecord[key] ??= value;
|
|
32
|
+
}
|
|
33
|
+
existingProcessRecord["browser"] = true;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function keepName($unknown) {
|
|
37
|
+
return $unknown;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
(function initCjs() {
|
|
41
|
+
const globalThisRecord = globalThis;
|
|
42
|
+
ensureDisposeSymbols();
|
|
43
|
+
globalThisRecord["__name"] ??= keepName;
|
|
44
|
+
globalThisRecord["__extractDefault"] ??= extractDefault;
|
|
45
|
+
ensureBrowserProcess();
|
|
46
|
+
function extractDefault(module) {
|
|
47
|
+
return module && module.__esModule && "default" in module ? module.default : module;
|
|
48
|
+
}
|
|
49
|
+
})();
|
|
50
|
+
})();
|
|
51
|
+
(function patchObsidianRequire() {
|
|
52
|
+
const originalRequire = require;
|
|
53
|
+
if (!originalRequire || originalRequire.__isPatched) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
require = Object.assign(
|
|
58
|
+
(id) => requirePatched(id),
|
|
59
|
+
originalRequire,
|
|
60
|
+
{
|
|
61
|
+
__isPatched: true
|
|
62
|
+
}
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
function extractDefault(module) {
|
|
66
|
+
return module && module.__esModule && 'default' in module ? module.default : module;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const OBSIDIAN_BUILT_IN_MODULE_NAMES = new Set([
|
|
70
|
+
'@codemirror/autocomplete',
|
|
71
|
+
'@codemirror/collab',
|
|
72
|
+
'@codemirror/commands',
|
|
73
|
+
'@codemirror/language',
|
|
74
|
+
'@codemirror/lint',
|
|
75
|
+
'@codemirror/search',
|
|
76
|
+
'@codemirror/state',
|
|
77
|
+
'@codemirror/text',
|
|
78
|
+
'@codemirror/view',
|
|
79
|
+
'@lezer/common',
|
|
80
|
+
'@lezer/highlight',
|
|
81
|
+
'@lezer/lr',
|
|
82
|
+
'obsidian']
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
const DEPRECATED_OBSIDIAN_BUILT_IN_MODULE_NAMES = new Set([
|
|
86
|
+
'@codemirror/closebrackets',
|
|
87
|
+
'@codemirror/comment',
|
|
88
|
+
'@codemirror/fold',
|
|
89
|
+
'@codemirror/gutter',
|
|
90
|
+
'@codemirror/highlight',
|
|
91
|
+
'@codemirror/history',
|
|
92
|
+
'@codemirror/matchbrackets',
|
|
93
|
+
'@codemirror/panel',
|
|
94
|
+
'@codemirror/rangeset',
|
|
95
|
+
'@codemirror/rectangular-selection',
|
|
96
|
+
'@codemirror/stream-parser',
|
|
97
|
+
'@codemirror/tooltip']
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
function requirePatched(id) {
|
|
101
|
+
if (OBSIDIAN_BUILT_IN_MODULE_NAMES.has(id) || DEPRECATED_OBSIDIAN_BUILT_IN_MODULE_NAMES.has(id)) {
|
|
102
|
+
return originalRequire?.(id);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated, obsidianmd/no-global-this -- Need access to app. Actively use globalThis.
|
|
106
|
+
if (globalThis.app.isMobile) {
|
|
107
|
+
if (id === 'process' || id === 'node:process') {
|
|
108
|
+
// eslint-disable-next-line no-console -- Valid usage.
|
|
109
|
+
console.debug(`The most likely you can safely ignore this error. Module not found: ${id}. Fake process object is returned instead.`);
|
|
110
|
+
|
|
111
|
+
return process;
|
|
112
|
+
}
|
|
113
|
+
} else {
|
|
114
|
+
const module = originalRequire?.(id);
|
|
115
|
+
if (module) {
|
|
116
|
+
return extractDefault(module);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// eslint-disable-next-line no-console -- Valid usage.
|
|
121
|
+
console.debug(`The most likely you can safely ignore this error. Module not found: ${id}. Empty object is returned instead.`);
|
|
122
|
+
return {};
|
|
123
|
+
}
|
|
124
|
+
})();
|
|
125
|
+
|
|
126
|
+
"use strict";
|
|
127
|
+
var __defProp = Object.defineProperty;
|
|
128
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
129
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
130
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
131
|
+
var __export = (target, all) => {
|
|
132
|
+
for (var name in all)
|
|
133
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
134
|
+
};
|
|
135
|
+
var __copyProps = (to, from, except, desc) => {
|
|
136
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
137
|
+
for (let key of __getOwnPropNames(from))
|
|
138
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
139
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
140
|
+
}
|
|
141
|
+
return to;
|
|
142
|
+
};
|
|
143
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
144
|
+
var no_over_cap_wait_in_eval_in_obsidian_exports = {};
|
|
145
|
+
__export(no_over_cap_wait_in_eval_in_obsidian_exports, {
|
|
146
|
+
MESSAGE_ID: () => MESSAGE_ID,
|
|
147
|
+
noOverCapWaitInEvalInObsidian: () => noOverCapWaitInEvalInObsidian
|
|
148
|
+
});
|
|
149
|
+
module.exports = __toCommonJS(no_over_cap_wait_in_eval_in_obsidian_exports);
|
|
150
|
+
var import_ts_estree_node = require('@mnaoumov/typescript-dev-toolkit/linters/eslint-rules/ts-estree-node');
|
|
151
|
+
var import_obsidian_integration_testing = require('obsidian-integration-testing');
|
|
152
|
+
var import_performance_eval_cap = require('../../test-runners/performance-eval-cap.cjs');
|
|
153
|
+
const MESSAGE_ID = "noOverCapWaitInEvalInObsidian";
|
|
154
|
+
const WAIT_UNTIL_DEFAULT_TIMEOUT_IN_MILLISECONDS = 5e3;
|
|
155
|
+
const INPUT_PROPERTY_NAME = "input";
|
|
156
|
+
const SLEEP_CALLEE_NAME = "sleep";
|
|
157
|
+
const TIMEOUT_PROPERTY_NAME = "timeoutInMilliseconds";
|
|
158
|
+
const WAIT_UNTIL_CALLEE_NAME = "waitUntil";
|
|
159
|
+
const CLOCK_OBJECT_NAMES = /* @__PURE__ */ new Set(["Date", "performance"]);
|
|
160
|
+
const NOW_METHOD_NAME = "now";
|
|
161
|
+
const CLOSURE_NAMES_BY_CALLEE_NAME = /* @__PURE__ */ new Map([
|
|
162
|
+
["evalInObsidian", ["callback"]],
|
|
163
|
+
["pollInObsidian", ["poll", "start"]]
|
|
164
|
+
]);
|
|
165
|
+
const noOverCapWaitInEvalInObsidian = {
|
|
166
|
+
create(context) {
|
|
167
|
+
const options = context.options[0];
|
|
168
|
+
const defaultCapInMilliseconds = context.filename.endsWith(import_performance_eval_cap.DESKTOP_PERFORMANCE_TEST_FILE_SUFFIX) ? import_performance_eval_cap.PERFORMANCE_EVAL_CAP_IN_MILLISECONDS : import_obsidian_integration_testing.DEFAULT_EVAL_CAP_IN_MILLISECONDS;
|
|
169
|
+
const capInMilliseconds = options?.capInMilliseconds ?? defaultCapInMilliseconds;
|
|
170
|
+
const callGraph = {
|
|
171
|
+
callCountByCalleeNodeByCallerNode: /* @__PURE__ */ new Map(),
|
|
172
|
+
stateByClosureNode: /* @__PURE__ */ new Map(),
|
|
173
|
+
waitInMillisecondsByFunctionNode: /* @__PURE__ */ new Map()
|
|
174
|
+
};
|
|
175
|
+
function addCall(target, calleeNode, callCount) {
|
|
176
|
+
const state = readClosureState(target);
|
|
177
|
+
state.functionNodes.add(calleeNode);
|
|
178
|
+
const callCountByCalleeNode = callGraph.callCountByCalleeNodeByCallerNode.get(target.functionNode) ?? /* @__PURE__ */ new Map();
|
|
179
|
+
callGraph.callCountByCalleeNodeByCallerNode.set(target.functionNode, callCountByCalleeNode);
|
|
180
|
+
callCountByCalleeNode.set(calleeNode, (callCountByCalleeNode.get(calleeNode) ?? 0) + callCount);
|
|
181
|
+
}
|
|
182
|
+
function addWait(target, waitInMilliseconds) {
|
|
183
|
+
readClosureState(target);
|
|
184
|
+
const runningTotalInMilliseconds = callGraph.waitInMillisecondsByFunctionNode.get(target.functionNode) ?? 0;
|
|
185
|
+
callGraph.waitInMillisecondsByFunctionNode.set(target.functionNode, runningTotalInMilliseconds + waitInMilliseconds);
|
|
186
|
+
}
|
|
187
|
+
function chargeHelperCall(callNode, target) {
|
|
188
|
+
const helperNode = readCalledHelperNode(callNode, target.closure, context);
|
|
189
|
+
if (!helperNode) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
addCall(target, helperNode, readLoopMultiplier(callNode, target, context));
|
|
193
|
+
}
|
|
194
|
+
function chargeLoopDeadline(node) {
|
|
195
|
+
const loopNode = (0, import_ts_estree_node.toTSESTreeNode)(node);
|
|
196
|
+
const target = findChargeTarget(loopNode);
|
|
197
|
+
if (!target) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
const deadlineInMilliseconds = readLoopDeadlineInMilliseconds(loopNode, target.closure, context);
|
|
201
|
+
if (deadlineInMilliseconds === null) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
addWait(target, deadlineInMilliseconds * readLoopMultiplier(loopNode, target, context));
|
|
205
|
+
}
|
|
206
|
+
function chargeWaitCall(callNode, target) {
|
|
207
|
+
const budgetExpression = readWaitBudgetExpression(callNode);
|
|
208
|
+
if (budgetExpression === void 0) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
const waitInMilliseconds = budgetExpression === null ? WAIT_UNTIL_DEFAULT_TIMEOUT_IN_MILLISECONDS : resolveNumber(budgetExpression, target.closure, context);
|
|
212
|
+
if (waitInMilliseconds === null) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
addWait(target, waitInMilliseconds * readLoopMultiplier(callNode, target, context));
|
|
216
|
+
}
|
|
217
|
+
function readClosureState(target) {
|
|
218
|
+
const state = callGraph.stateByClosureNode.get(target.closure.closureNode) ?? {
|
|
219
|
+
closureNode: target.closure.closureNode,
|
|
220
|
+
functionNodes: /* @__PURE__ */ new Set(),
|
|
221
|
+
reportNode: target.closure.reportNode
|
|
222
|
+
};
|
|
223
|
+
callGraph.stateByClosureNode.set(target.closure.closureNode, state);
|
|
224
|
+
state.functionNodes.add(target.functionNode);
|
|
225
|
+
return state;
|
|
226
|
+
}
|
|
227
|
+
return {
|
|
228
|
+
"CallExpression"(node) {
|
|
229
|
+
const callNode = (0, import_ts_estree_node.toTSESTreeNode)(node);
|
|
230
|
+
const target = findChargeTarget(callNode);
|
|
231
|
+
if (!target) {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
chargeWaitCall(callNode, target);
|
|
235
|
+
chargeHelperCall(callNode, target);
|
|
236
|
+
},
|
|
237
|
+
DoWhileStatement: chargeLoopDeadline,
|
|
238
|
+
ForStatement: chargeLoopDeadline,
|
|
239
|
+
"Program:exit"() {
|
|
240
|
+
for (const state of callGraph.stateByClosureNode.values()) {
|
|
241
|
+
const totalInMilliseconds = readClosureWaitInMilliseconds(state, callGraph);
|
|
242
|
+
if (totalInMilliseconds < capInMilliseconds) {
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
context.report({
|
|
246
|
+
data: {
|
|
247
|
+
capInMilliseconds: String(capInMilliseconds),
|
|
248
|
+
totalInMilliseconds: String(totalInMilliseconds)
|
|
249
|
+
},
|
|
250
|
+
messageId: MESSAGE_ID,
|
|
251
|
+
node: state.reportNode
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
},
|
|
255
|
+
WhileStatement: chargeLoopDeadline
|
|
256
|
+
};
|
|
257
|
+
},
|
|
258
|
+
meta: {
|
|
259
|
+
docs: {
|
|
260
|
+
description: "Disallow an in-Obsidian closure declaring more waiting than the transport's script-timeout cap allows"
|
|
261
|
+
},
|
|
262
|
+
messages: {
|
|
263
|
+
[MESSAGE_ID]: "This closure declares {{ totalInMilliseconds }} ms of waiting, at or over the transport's {{ capInMilliseconds }} ms cap, so it can only ever die as a bare `script timeout`: wait in Node instead, with a short DOM-reading `pollInObsidian` `poll`, an `until` evaluated in Node, and the long budget in `timeoutInMilliseconds`."
|
|
264
|
+
},
|
|
265
|
+
schema: [{
|
|
266
|
+
additionalProperties: false,
|
|
267
|
+
properties: {
|
|
268
|
+
capInMilliseconds: {
|
|
269
|
+
minimum: 1,
|
|
270
|
+
type: "integer"
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
type: "object"
|
|
274
|
+
}],
|
|
275
|
+
type: "problem"
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
function collectReachableFunctionNodes(functionNode, callGraph, reachableNodes) {
|
|
279
|
+
if (reachableNodes.has(functionNode)) {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
reachableNodes.add(functionNode);
|
|
283
|
+
for (const calleeNode of callGraph.callCountByCalleeNodeByCallerNode.get(functionNode)?.keys() ?? []) {
|
|
284
|
+
collectReachableFunctionNodes(calleeNode, callGraph, reachableNodes);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
function findChargeTarget(node) {
|
|
288
|
+
let innermostFunctionNode;
|
|
289
|
+
let currentNode = node.parent;
|
|
290
|
+
while (currentNode) {
|
|
291
|
+
const closure = readEvalClosure(currentNode);
|
|
292
|
+
if (closure) {
|
|
293
|
+
return {
|
|
294
|
+
closure,
|
|
295
|
+
functionNode: innermostFunctionNode ?? closure.closureNode
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
if (!innermostFunctionNode && isFunctionNode(currentNode)) {
|
|
299
|
+
innermostFunctionNode = currentNode;
|
|
300
|
+
}
|
|
301
|
+
currentNode = currentNode.parent;
|
|
302
|
+
}
|
|
303
|
+
return null;
|
|
304
|
+
}
|
|
305
|
+
function findVariable(scope, name) {
|
|
306
|
+
let currentScope = scope;
|
|
307
|
+
while (currentScope) {
|
|
308
|
+
const variable = currentScope.variables.find((candidate) => candidate.name === name);
|
|
309
|
+
if (variable) {
|
|
310
|
+
return variable;
|
|
311
|
+
}
|
|
312
|
+
currentScope = currentScope.upper;
|
|
313
|
+
}
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
function isAssignmentExpression(node) {
|
|
317
|
+
return node.type === "AssignmentExpression";
|
|
318
|
+
}
|
|
319
|
+
function isBinaryExpression(node) {
|
|
320
|
+
return node.type === "BinaryExpression";
|
|
321
|
+
}
|
|
322
|
+
function isCallExpression(node) {
|
|
323
|
+
return node.type === "CallExpression";
|
|
324
|
+
}
|
|
325
|
+
function isClosureFunction(node) {
|
|
326
|
+
return node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression";
|
|
327
|
+
}
|
|
328
|
+
function isDeclaredInsideClosure(functionNode, closure) {
|
|
329
|
+
let currentNode = functionNode.parent;
|
|
330
|
+
while (currentNode) {
|
|
331
|
+
if (currentNode === closure.closureNode) {
|
|
332
|
+
return true;
|
|
333
|
+
}
|
|
334
|
+
currentNode = currentNode.parent;
|
|
335
|
+
}
|
|
336
|
+
return false;
|
|
337
|
+
}
|
|
338
|
+
function isForStatement(node) {
|
|
339
|
+
return node.type === "ForStatement";
|
|
340
|
+
}
|
|
341
|
+
function isFunctionNode(node) {
|
|
342
|
+
return isClosureFunction(node) || node.type === "FunctionDeclaration";
|
|
343
|
+
}
|
|
344
|
+
function isIdentifier(node) {
|
|
345
|
+
return node.type === "Identifier";
|
|
346
|
+
}
|
|
347
|
+
function isLogicalAndExpression(node) {
|
|
348
|
+
return node.type === "LogicalExpression" && node.operator === "&&";
|
|
349
|
+
}
|
|
350
|
+
function isLoopStatement(node) {
|
|
351
|
+
return node.type === "WhileStatement" || node.type === "DoWhileStatement" || isForStatement(node);
|
|
352
|
+
}
|
|
353
|
+
function isMemberExpression(node) {
|
|
354
|
+
return node.type === "MemberExpression";
|
|
355
|
+
}
|
|
356
|
+
function isNumericLiteral(node) {
|
|
357
|
+
return node.type === "Literal" && typeof node.value === "number";
|
|
358
|
+
}
|
|
359
|
+
function isObjectExpression(node) {
|
|
360
|
+
return node.type === "ObjectExpression";
|
|
361
|
+
}
|
|
362
|
+
function isObjectPattern(node) {
|
|
363
|
+
return node.type === "ObjectPattern";
|
|
364
|
+
}
|
|
365
|
+
function isProperty(node) {
|
|
366
|
+
return node.type === "Property";
|
|
367
|
+
}
|
|
368
|
+
function isUpdateExpression(node) {
|
|
369
|
+
return node.type === "UpdateExpression";
|
|
370
|
+
}
|
|
371
|
+
function isVariableDeclaration(node) {
|
|
372
|
+
return node.type === "VariableDeclaration";
|
|
373
|
+
}
|
|
374
|
+
function isVariableDeclarator(node) {
|
|
375
|
+
return node.type === "VariableDeclarator";
|
|
376
|
+
}
|
|
377
|
+
function readBoundExpression(node, closure, context) {
|
|
378
|
+
const variable = findVariable(context.sourceCode.getScope(node), node.name);
|
|
379
|
+
if (!variable) {
|
|
380
|
+
return null;
|
|
381
|
+
}
|
|
382
|
+
for (const definition of variable.defs) {
|
|
383
|
+
const definitionNode = (0, import_ts_estree_node.toTSESTreeNode)(definition.node);
|
|
384
|
+
if (isVariableDeclarator(definitionNode) && definitionNode.init) {
|
|
385
|
+
return definitionNode.init;
|
|
386
|
+
}
|
|
387
|
+
if (definitionNode === closure.closureNode) {
|
|
388
|
+
const inputKey = readParameterInputKey(closure.closureNode, node.name);
|
|
389
|
+
return inputKey === null ? null : readInputPropertyValue(closure.paramsNode, inputKey);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
return null;
|
|
393
|
+
}
|
|
394
|
+
function readCalledHelperNode(callNode, closure, context) {
|
|
395
|
+
const calleeNode = callNode.callee;
|
|
396
|
+
if (!isIdentifier(calleeNode)) {
|
|
397
|
+
return null;
|
|
398
|
+
}
|
|
399
|
+
const variable = findVariable(context.sourceCode.getScope(calleeNode), calleeNode.name);
|
|
400
|
+
if (!variable) {
|
|
401
|
+
return null;
|
|
402
|
+
}
|
|
403
|
+
for (const definition of variable.defs) {
|
|
404
|
+
const functionNode = readDefinitionFunctionNode((0, import_ts_estree_node.toTSESTreeNode)(definition.node));
|
|
405
|
+
if (functionNode && isDeclaredInsideClosure(functionNode, closure)) {
|
|
406
|
+
return functionNode;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
return null;
|
|
410
|
+
}
|
|
411
|
+
function readCallGraphWaitInMilliseconds(functionNode, callGraph, visitedNodes) {
|
|
412
|
+
if (visitedNodes.has(functionNode)) {
|
|
413
|
+
return 0;
|
|
414
|
+
}
|
|
415
|
+
visitedNodes.add(functionNode);
|
|
416
|
+
let totalInMilliseconds = callGraph.waitInMillisecondsByFunctionNode.get(functionNode) ?? 0;
|
|
417
|
+
for (const [calleeNode, callCount] of callGraph.callCountByCalleeNodeByCallerNode.get(functionNode) ?? []) {
|
|
418
|
+
totalInMilliseconds += callCount * readCallGraphWaitInMilliseconds(calleeNode, callGraph, visitedNodes);
|
|
419
|
+
}
|
|
420
|
+
visitedNodes.delete(functionNode);
|
|
421
|
+
return totalInMilliseconds;
|
|
422
|
+
}
|
|
423
|
+
function readClockName(node) {
|
|
424
|
+
if (!isCallExpression(node) || node.arguments.length > 0) {
|
|
425
|
+
return null;
|
|
426
|
+
}
|
|
427
|
+
const calleeNode = node.callee;
|
|
428
|
+
if (!isMemberExpression(calleeNode) || calleeNode.computed) {
|
|
429
|
+
return null;
|
|
430
|
+
}
|
|
431
|
+
const objectNode = calleeNode.object;
|
|
432
|
+
const propertyNode = calleeNode.property;
|
|
433
|
+
return !isIdentifier(objectNode) || !isIdentifier(propertyNode) || propertyNode.name !== NOW_METHOD_NAME || !CLOCK_OBJECT_NAMES.has(objectNode.name) ? null : objectNode.name;
|
|
434
|
+
}
|
|
435
|
+
function readClosureNames(callNode) {
|
|
436
|
+
return isIdentifier(callNode.callee) ? CLOSURE_NAMES_BY_CALLEE_NAME.get(callNode.callee.name) ?? null : null;
|
|
437
|
+
}
|
|
438
|
+
function readClosureWaitInMilliseconds(state, callGraph) {
|
|
439
|
+
const reachableNodes = /* @__PURE__ */ new Set();
|
|
440
|
+
collectReachableFunctionNodes(state.closureNode, callGraph, reachableNodes);
|
|
441
|
+
let totalInMilliseconds = readCallGraphWaitInMilliseconds(state.closureNode, callGraph, /* @__PURE__ */ new Set());
|
|
442
|
+
for (const functionNode of state.functionNodes) {
|
|
443
|
+
const ownWaitInMilliseconds = callGraph.waitInMillisecondsByFunctionNode.get(functionNode);
|
|
444
|
+
if (ownWaitInMilliseconds === void 0 || reachableNodes.has(functionNode)) {
|
|
445
|
+
continue;
|
|
446
|
+
}
|
|
447
|
+
totalInMilliseconds += ownWaitInMilliseconds;
|
|
448
|
+
}
|
|
449
|
+
return totalInMilliseconds;
|
|
450
|
+
}
|
|
451
|
+
function readConjuncts(node) {
|
|
452
|
+
return isLogicalAndExpression(node) ? [...readConjuncts(node.left), ...readConjuncts(node.right)] : [node];
|
|
453
|
+
}
|
|
454
|
+
function readDeadlineGuardInMilliseconds(node, closure, context) {
|
|
455
|
+
if (!isBinaryExpression(node)) {
|
|
456
|
+
return null;
|
|
457
|
+
}
|
|
458
|
+
const isClockOnLeft = node.operator === "<" || node.operator === "<=";
|
|
459
|
+
if (!isClockOnLeft && node.operator !== ">" && node.operator !== ">=") {
|
|
460
|
+
return null;
|
|
461
|
+
}
|
|
462
|
+
const clockName = readClockName(isClockOnLeft ? node.left : node.right);
|
|
463
|
+
const deadlineNode = isClockOnLeft ? node.right : node.left;
|
|
464
|
+
if (clockName === null || !isIdentifier(deadlineNode)) {
|
|
465
|
+
return null;
|
|
466
|
+
}
|
|
467
|
+
const boundNode = readBoundExpression(deadlineNode, closure, context);
|
|
468
|
+
return !boundNode || !isBinaryExpression(boundNode) || boundNode.operator !== "+" || readClockName(boundNode.left) !== clockName ? null : resolveNumber(boundNode.right, closure, context);
|
|
469
|
+
}
|
|
470
|
+
function readDefinitionFunctionNode(definitionNode) {
|
|
471
|
+
if (isFunctionNode(definitionNode)) {
|
|
472
|
+
return definitionNode;
|
|
473
|
+
}
|
|
474
|
+
if (!isVariableDeclarator(definitionNode) || !definitionNode.init) {
|
|
475
|
+
return null;
|
|
476
|
+
}
|
|
477
|
+
const initNode = definitionNode.init;
|
|
478
|
+
return isFunctionNode(initNode) ? initNode : null;
|
|
479
|
+
}
|
|
480
|
+
function readEvalClosure(node) {
|
|
481
|
+
if (!isClosureFunction(node)) {
|
|
482
|
+
return null;
|
|
483
|
+
}
|
|
484
|
+
const propertyNode = node.parent;
|
|
485
|
+
if (!isProperty(propertyNode)) {
|
|
486
|
+
return null;
|
|
487
|
+
}
|
|
488
|
+
const paramsNode = propertyNode.parent;
|
|
489
|
+
if (!isObjectExpression(paramsNode) || !isIdentifier(propertyNode.key)) {
|
|
490
|
+
return null;
|
|
491
|
+
}
|
|
492
|
+
const callNode = paramsNode.parent;
|
|
493
|
+
if (!isCallExpression(callNode) || callNode.arguments[0] !== paramsNode) {
|
|
494
|
+
return null;
|
|
495
|
+
}
|
|
496
|
+
const closureNames = readClosureNames(callNode);
|
|
497
|
+
return closureNames?.includes(propertyNode.key.name) ? {
|
|
498
|
+
closureNode: node,
|
|
499
|
+
paramsNode,
|
|
500
|
+
reportNode: propertyNode
|
|
501
|
+
} : null;
|
|
502
|
+
}
|
|
503
|
+
function readInputPropertyValue(paramsNode, keyName) {
|
|
504
|
+
const inputProperty = paramsNode.properties.find(
|
|
505
|
+
(property) => isProperty(property) && isIdentifier(property.key) && property.key.name === INPUT_PROPERTY_NAME
|
|
506
|
+
);
|
|
507
|
+
const inputNode = inputProperty?.value;
|
|
508
|
+
if (!inputNode || !isObjectExpression(inputNode)) {
|
|
509
|
+
return null;
|
|
510
|
+
}
|
|
511
|
+
const valueProperty = inputNode.properties.find(
|
|
512
|
+
(property) => isProperty(property) && isIdentifier(property.key) && property.key.name === keyName
|
|
513
|
+
);
|
|
514
|
+
return valueProperty?.value ?? null;
|
|
515
|
+
}
|
|
516
|
+
function readLoopDeadlineInMilliseconds(loopNode, closure, context) {
|
|
517
|
+
if (!loopNode.test) {
|
|
518
|
+
return null;
|
|
519
|
+
}
|
|
520
|
+
for (const conjunct of readConjuncts(loopNode.test)) {
|
|
521
|
+
const deadlineInMilliseconds = readDeadlineGuardInMilliseconds(conjunct, closure, context);
|
|
522
|
+
if (deadlineInMilliseconds !== null) {
|
|
523
|
+
return deadlineInMilliseconds;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
return null;
|
|
527
|
+
}
|
|
528
|
+
function readLoopExclusiveBound(testNode, counterName, closure, context) {
|
|
529
|
+
for (const conjunct of readConjuncts(testNode)) {
|
|
530
|
+
if (!isBinaryExpression(conjunct) || conjunct.operator !== "<" && conjunct.operator !== "<=") {
|
|
531
|
+
continue;
|
|
532
|
+
}
|
|
533
|
+
const counterNode = conjunct.left;
|
|
534
|
+
if (!isIdentifier(counterNode) || counterNode.name !== counterName) {
|
|
535
|
+
continue;
|
|
536
|
+
}
|
|
537
|
+
const boundValue = resolveNumber(conjunct.right, closure, context);
|
|
538
|
+
if (boundValue === null) {
|
|
539
|
+
continue;
|
|
540
|
+
}
|
|
541
|
+
return conjunct.operator === "<" ? boundValue : boundValue + 1;
|
|
542
|
+
}
|
|
543
|
+
return null;
|
|
544
|
+
}
|
|
545
|
+
function readLoopIterationCount(loopNode, closure, context) {
|
|
546
|
+
if (!isForStatement(loopNode) || !loopNode.test || !loopNode.init || !isVariableDeclaration(loopNode.init)) {
|
|
547
|
+
return null;
|
|
548
|
+
}
|
|
549
|
+
const declaratorNodes = loopNode.init.declarations;
|
|
550
|
+
const declaratorNode = declaratorNodes.length === 1 ? declaratorNodes[0] : void 0;
|
|
551
|
+
if (!declaratorNode?.init || !isIdentifier(declaratorNode.id)) {
|
|
552
|
+
return null;
|
|
553
|
+
}
|
|
554
|
+
const startValue = resolveNumber(declaratorNode.init, closure, context);
|
|
555
|
+
const stepSize = readLoopStepSize(loopNode.update, declaratorNode.id, closure, context);
|
|
556
|
+
const boundValue = readLoopExclusiveBound(loopNode.test, declaratorNode.id.name, closure, context);
|
|
557
|
+
if (startValue === null || stepSize === null || stepSize <= 0 || boundValue === null) {
|
|
558
|
+
return null;
|
|
559
|
+
}
|
|
560
|
+
const span = boundValue - startValue;
|
|
561
|
+
return span > 0 ? Math.ceil(span / stepSize) : 0;
|
|
562
|
+
}
|
|
563
|
+
function readLoopMultiplier(node, target, context) {
|
|
564
|
+
const closure = target.closure;
|
|
565
|
+
let multiplier = 1;
|
|
566
|
+
let currentNode = node.parent;
|
|
567
|
+
while (currentNode && currentNode !== target.functionNode) {
|
|
568
|
+
if (isLoopStatement(currentNode) && readLoopDeadlineInMilliseconds(currentNode, closure, context) === null) {
|
|
569
|
+
const iterationCount = readLoopIterationCount(currentNode, closure, context);
|
|
570
|
+
if (iterationCount !== null) {
|
|
571
|
+
multiplier *= iterationCount;
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
currentNode = currentNode.parent;
|
|
575
|
+
}
|
|
576
|
+
return multiplier;
|
|
577
|
+
}
|
|
578
|
+
function readLoopStepSize(updateNode, counterNode, closure, context) {
|
|
579
|
+
if (!updateNode) {
|
|
580
|
+
return null;
|
|
581
|
+
}
|
|
582
|
+
if (isUpdateExpression(updateNode)) {
|
|
583
|
+
const argumentNode = updateNode.argument;
|
|
584
|
+
return updateNode.operator === "++" && isIdentifier(argumentNode) && argumentNode.name === counterNode.name ? 1 : null;
|
|
585
|
+
}
|
|
586
|
+
if (!isAssignmentExpression(updateNode) || updateNode.operator !== "+=") {
|
|
587
|
+
return null;
|
|
588
|
+
}
|
|
589
|
+
const targetNode = updateNode.left;
|
|
590
|
+
return !isIdentifier(targetNode) || targetNode.name !== counterNode.name ? null : resolveNumber(updateNode.right, closure, context);
|
|
591
|
+
}
|
|
592
|
+
function readParameterInputKey(closureNode, localName) {
|
|
593
|
+
for (const parameterNode of closureNode.params) {
|
|
594
|
+
if (!isObjectPattern(parameterNode)) {
|
|
595
|
+
continue;
|
|
596
|
+
}
|
|
597
|
+
for (const property of parameterNode.properties) {
|
|
598
|
+
if (!isProperty(property) || property.computed || !isIdentifier(property.key) || !isIdentifier(property.value)) {
|
|
599
|
+
continue;
|
|
600
|
+
}
|
|
601
|
+
if (property.value.name === localName) {
|
|
602
|
+
return property.key.name;
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
return null;
|
|
607
|
+
}
|
|
608
|
+
function readWaitBudgetExpression(callNode) {
|
|
609
|
+
if (!isIdentifier(callNode.callee)) {
|
|
610
|
+
return void 0;
|
|
611
|
+
}
|
|
612
|
+
const calleeName = callNode.callee.name;
|
|
613
|
+
if (calleeName === SLEEP_CALLEE_NAME) {
|
|
614
|
+
return callNode.arguments[0] ?? void 0;
|
|
615
|
+
}
|
|
616
|
+
if (calleeName !== WAIT_UNTIL_CALLEE_NAME) {
|
|
617
|
+
return void 0;
|
|
618
|
+
}
|
|
619
|
+
const paramsNode = callNode.arguments[0];
|
|
620
|
+
if (!paramsNode || !isObjectExpression(paramsNode)) {
|
|
621
|
+
return void 0;
|
|
622
|
+
}
|
|
623
|
+
const timeoutProperty = paramsNode.properties.find(
|
|
624
|
+
(property) => isProperty(property) && isIdentifier(property.key) && property.key.name === TIMEOUT_PROPERTY_NAME
|
|
625
|
+
);
|
|
626
|
+
return timeoutProperty?.value ?? null;
|
|
627
|
+
}
|
|
628
|
+
function resolveNumber(node, closure, context) {
|
|
629
|
+
const visitedNodes = /* @__PURE__ */ new Set();
|
|
630
|
+
let currentNode = node;
|
|
631
|
+
while (!visitedNodes.has(currentNode)) {
|
|
632
|
+
visitedNodes.add(currentNode);
|
|
633
|
+
if (isNumericLiteral(currentNode)) {
|
|
634
|
+
return currentNode.value;
|
|
635
|
+
}
|
|
636
|
+
if (isBinaryExpression(currentNode) && currentNode.operator === "*") {
|
|
637
|
+
const leftValue = resolveNumber(currentNode.left, closure, context);
|
|
638
|
+
const rightValue = resolveNumber(currentNode.right, closure, context);
|
|
639
|
+
return leftValue === null || rightValue === null ? null : leftValue * rightValue;
|
|
640
|
+
}
|
|
641
|
+
if (!isIdentifier(currentNode)) {
|
|
642
|
+
return null;
|
|
643
|
+
}
|
|
644
|
+
const boundNode = readBoundExpression(currentNode, closure, context);
|
|
645
|
+
if (!boundNode) {
|
|
646
|
+
return null;
|
|
647
|
+
}
|
|
648
|
+
currentNode = boundNode;
|
|
649
|
+
}
|
|
650
|
+
return null;
|
|
651
|
+
}
|
|
652
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
653
|
+
0 && (module.exports = {
|
|
654
|
+
MESSAGE_ID,
|
|
655
|
+
noOverCapWaitInEvalInObsidian
|
|
656
|
+
});
|
|
657
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpbnRlcnMvZXNsaW50LXJ1bGVzL25vLW92ZXItY2FwLXdhaXQtaW4tZXZhbC1pbi1vYnNpZGlhbi50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBAZmlsZVxuICpcbiAqIEVTTGludCBydWxlOiBuby1vdmVyLWNhcC13YWl0LWluLWV2YWwtaW4tb2JzaWRpYW5cbiAqXG4gKiBSZXBvcnRzIGFuIGBldmFsSW5PYnNpZGlhbmAgLyBgcG9sbEluT2JzaWRpYW5gIGNsb3N1cmUgdGhhdCBkZWNsYXJlcyBtb3JlIHdhaXRpbmdcbiAqIHRoYW4gdGhlIHRyYW5zcG9ydCBjYW4gZXZlciBob25vdXIuXG4gKlxuICogQSBzaW5nbGUgY2xvc3VyZSBpcyBldmFsdWF0ZWQgdGhyb3VnaCBvbmUgdHJhbnNwb3J0IGNhbGwsIGFuZCB0aGF0IGNhbGwgaXMgY2FwcGVkIGF0XG4gKiByb3VnaGx5IDMwIHNlY29uZHMgXHUyMDE0IEFwcGl1bSBzdXJmYWNlcyB0aGUgY2FwIGFzIGEgYmFyZSBgV2ViRHJpdmVyRXJyb3I6IHNjcmlwdCB0aW1lb3V0YFxuICogbmFtaW5nIG9ubHkgYEFwcGl1bVRyYW5zcG9ydC5ldmFsdWF0ZWAsIENEUCBhcyBhIGNvbW1hbmQgdGltZW91dC4gTmVpdGhlciBuYW1lcyB0aGUgd2FpdFxuICogdGhhdCBhY3R1YWxseSBibGV3IHRoZSBidWRnZXQsIHNvIHRoZSBmYWlsdXJlIHJlYWRzIGFzIGEgYnJva2VuIGRldmljZSByYXRoZXIgdGhhbiBhcyBhXG4gKiBjbG9zdXJlIGFza2luZyBmb3IgbW9yZSB0aW1lIHRoYW4gZXhpc3RzLiBUaGF0IG1pc2RpYWdub3NpcyBjb3N0IHR3byBkYXlzLlxuICpcbiAqIFRoZSBjYXAgdGhlIHJ1bGUgYXNzdW1lcyB3aGVuIGBjYXBJbk1pbGxpc2Vjb25kc2AgaXMgbm90IGNvbmZpZ3VyZWQgaXNcbiAqIGBERUZBVUxUX0VWQUxfQ0FQX0lOX01JTExJU0VDT05EU2AsIGltcG9ydGVkIGZyb20gYG9ic2lkaWFuLWludGVncmF0aW9uLXRlc3RpbmdgIFx1MjAxNCB0aGUgc2FtZSBjb25zdGFudFxuICogYm90aCBvZiBpdHMgdHJhbnNwb3J0cyBlbmZvcmNlLCBzbyB0aGUgcnVsZSBjYW5ub3QgZHJpZnQgZnJvbSB0aGUgdGhpbmcgaXQgaXMgcHJlZGljdGluZy4gVGhhdCBpbXBvcnRcbiAqIGlzIHdoeSB0aGUgaGFybmVzcyBpcyBhIHJlcXVpcmVkIHBlZXIgb2YgdGhpcyBsaWJyYXJ5IHJhdGhlciB0aGFuIGFuIG9wdGlvbmFsIG9uZTogdGhlIHNoYXJlZCBFU0xpbnRcbiAqIGNvbmZpZyBsb2FkcyB0aGlzIHJ1bGUsIHNvIGV2ZXJ5IGNvbnN1bWluZyByZXBvIHJlc29sdmVzIGl0IGF0IGxpbnQgdGltZS5cbiAqXG4gKiBPTkUgS0lORCBPRiBGSUxFIERFRkFVTFRTIEhJR0hFUjogYSBgKi5kZXNrdG9wLXBlcmZvcm1hbmNlLmludGVncmF0aW9uLnRlc3QudHNgIGlzIG1lYXN1cmVkIGFnYWluc3RcbiAqIGBQRVJGT1JNQU5DRV9FVkFMX0NBUF9JTl9NSUxMSVNFQ09ORFNgICg2MDAgMDAwKSwgdGhlIHBlci1ldmFsIGNhcCB0aGUgc2hhcmVkIHZpdGVzdCBjb25maWcgZ2l2ZXMgdGhlXG4gKiBgaW50ZWdyYXRpb24tdGVzdHM6ZGVza3RvcC1wZXJmb3JtYW5jZWAgcHJvamVjdCwgaW1wb3J0ZWQgZnJvbSB0aGF0IHNhbWUgbW9kdWxlIHJhdGhlciB0aGFuIHJlc3RhdGVkLlxuICogVGhhdCByYWlzZSBpcyBhIGRlbGliZXJhdGUgQlVER0VUOiBhIHBlcmYgc3VpdGUncyBtZWFzdXJlbWVudCBpcyBvbmUgbG9uZyBpbi1wYWdlIGV2YWx1YXRpb24sIGFuZCBpdHNcbiAqIGZpbGVzIHJ1biBvbiBubyBvdGhlciBwcm9qZWN0LiBFdmVyeSBvdGhlciBmaWxlIGtlZXBzIHRoZSBzaW5nbGUgdHJhbnNwb3J0IGRlZmF1bHQsIGFuZCB0aGF0IGlzIHRoZVxuICogY29udmVudGlvbiByYXRoZXIgdGhhbiBhIGdhcDogYSByZXBvIHRoYXQgcmFpc2VzIGl0cyBvd24gZGVza3RvcCBgY29tbWFuZFRpbWVvdXRJbk1pbGxpc2Vjb25kc2AgaXNcbiAqIHNldHRpbmcgYSBiYWNrc3RvcCwgTk9UIGEgYnVkZ2V0IGEgY2xvc3VyZSBtYXkgc3BlbmQsIHNvIHRoZSBydWxlIGRvZXMgbm90IHJlYWQgdGhhdCByYWlzZSBhbmQga2VlcHNcbiAqIGVuZm9yY2luZyAzMCAwMDAgYWdhaW5zdCBpdC4gQSBjcm9zcy1wbGF0Zm9ybSBzdWl0ZSBjb3VsZCBub3Qgc3BlbmQgaXQgYW55d2F5OiBBcHBpdW0gY2FwcyBldmVyeVxuICogY2xvc3VyZSBhdCAzMCAwMDAgd2hhdGV2ZXIgYSBkZXNrdG9wIHJhaXNlIHNheXMuIEFuIGV4cGxpY2l0IGBjYXBJbk1pbGxpc2Vjb25kc2Agc3RpbGwgb3ZlcnJpZGVzIGJvdGhcbiAqIGRlZmF1bHRzLCBmb3IgZXZlcnkgZmlsZSB0aGUgcnVsZSBpcyBjb25maWd1cmVkIG9uLlxuICpcbiAqIEEgY2xvc3VyZSBkZWNsYXJpbmcgYSAzMCAwMDAgbXMgYHdhaXRVbnRpbGAsIG9yIHR3byAyMCAwMDAgbXMgb25lcywgdGhlcmVmb3JlIGNhbm5vdFxuICogc3VjY2VlZCBvbiBhbnkgbWFjaGluZSBzbG93IGVub3VnaCB0byBuZWVkIHRoZSB0aW1lIGl0IGFza3MgZm9yLiBUaGUgZml4IGlzIHRvIG1vdmUgdGhlXG4gKiB3YWl0aW5nIHRvIE5vZGU6IGBwb2xsSW5PYnNpZGlhbmAgcnVucyBhIFNIT1JUIERPTS1yZWFkaW5nIGBwb2xsYCBjbG9zdXJlIHJlcGVhdGVkbHksXG4gKiBldmFsdWF0ZXMgYHVudGlsYCBpbiBOb2RlLCBhbmQgY2FycmllcyB0aGUgbG9uZyBidWRnZXQgaW4gYHRpbWVvdXRJbk1pbGxpc2Vjb25kc2AsIHNvIG5vXG4gKiBzaW5nbGUgdHJhbnNwb3J0IGNhbGwgaXMgZXZlciBsb25nLlxuICpcbiAqIFdIQVQgQ09VTlRTIHRvd2FyZCBhIGNsb3N1cmUncyBidWRnZXQsIHN1bW1lZCBsZXhpY2FsbHk6IGV2ZXJ5IGB3YWl0VW50aWxgIGluc2lkZSBpdCBcdTIwMTRcbiAqIHRha2luZyB0aGUgaGVscGVyJ3MgZG9jdW1lbnRlZCA1IDAwMCBtcyBkZWZhdWx0IHdoZW4gYHRpbWVvdXRJbk1pbGxpc2Vjb25kc2AgaXMgb21pdHRlZCxcbiAqIHdoaWNoIGlzIHdoYXQgbWFrZXMgc2V2ZXJhbCBzbWFsbCBzaWJsaW5nIHdhaXRzIGFkZCB1cCBob25lc3RseSBcdTIwMTQgcGx1cyBldmVyeSBgc2xlZXAobilgXG4gKiBzZXR0bGUuIFdhaXRzIGluc2lkZSBhIGhlbHBlciBkZWNsYXJlZCB3aXRoaW4gdGhlIGNsb3N1cmUgY291bnQgdG9vOyB0aGUgZW5jbG9zaW5nXG4gKiBjbG9zdXJlIGlzIGZvdW5kIGJ5IHdhbGtpbmcgb3V0d2FyZHMsIHNvIGEgbmVzdGVkIGZ1bmN0aW9uIGF0dHJpYnV0ZXMgdG8gdGhlIGNsb3N1cmUgaXRcbiAqIHJ1bnMgaW5zaWRlIC0tIG9uY2UgcGVyIENBTEwgU0lURSwgcGVyIHRoZSBIRUxQRVJTIHBhcmFncmFwaCBiZWxvdy5cbiAqXG4gKiBXSEFUIERPRVMgTk9ULiBBIGJ1ZGdldCB0aGF0IGNhbm5vdCBiZSByZXNvbHZlZCB0byBhIG51bWJlciBjb250cmlidXRlcyBub3RoaW5nIGFuZCBpc1xuICogbmV2ZXIgcmVwb3J0ZWQgKG93bmVyLCAyMDI2LTA5LTA5KS4gU2NvcGUgYW5hbHlzaXMgcmVzb2x2ZXMgdGhlIHNoYXBlcyB0aGF0IGFjdHVhbGx5XG4gKiBvY2N1ciBcdTIwMTQgYSBsaXRlcmFsLCBhIGBjb25zdGAgaW4gYW55IGVuY2xvc2luZyBzY29wZSwgYW5kIGEgZGVzdHJ1Y3R1cmVkIGNhbGxiYWNrXG4gKiBwYXJhbWV0ZXIgZm9sbG93ZWQgYmFjayB0aHJvdWdoIHRoZSBjYWxsJ3Mgb3duIGBpbnB1dGAgb2JqZWN0IFx1MjAxNCBhbmQgcmVzb2x2aW5nIHRocm91Z2hcbiAqIHNjb3BlIHJhdGhlciB0aGFuIGJ5IHJlZ2V4IGlzIHRoZSB3aG9sZSByZWFzb24gdGhpcyBpcyBhIHJ1bGUgYW5kIG5vdCBhIHNjcmlwdC4gQnV0IGFcbiAqIHZhbHVlIGFycml2aW5nIGZyb20gYSBjYWxsZXIgKGBvcHRpb25zLnRpbWVvdXQgPz8gREVGQVVMVGAsIHRocmVhZGVkIHRocm91Z2ggYVxuICogcGFyYW1ldGVyKSB3b3VsZCBuZWVkIGFuYWx5c2lzIGFjcm9zcyBjYWxsIGJvdW5kYXJpZXMsIGFuZCByZXBvcnRpbmcgZXZlcnkgc3VjaCBzaXRlIHdvdWxkXG4gKiBtYWtlIGVhY2ggbGVnaXRpbWF0ZWx5IHBhcmFtZXRlcml6ZWQgaGVscGVyIHJlZCBhY3Jvc3MgdGhpcnR5IHJlcG9zLlxuICpcbiAqIExPT1BTIHdlcmUgb25jZSBvdXQgb2Ygc2NvcGUgd2hvbGVzYWxlLCBvbiB0aGUgcmVhc29uaW5nIHRoYXQgYSBgc2xlZXBgIGluIGEgYHdoaWxlYCBoYXMgbm9cbiAqIHN0YXRpY2FsbHkgZGVjbGFyZWQgY2VpbGluZy4gVGhhdCBpcyB0cnVlIG9mIGB3aGlsZSAodHJ1ZSlgIGFuZCBmYWxzZSBvZiB0aGUgbG9vcCB0aGVzZVxuICogc3VpdGVzIGFjdHVhbGx5IHdyaXRlLCB3aGljaCBkZWNsYXJlcyBpdHMgY2VpbGluZyBhcyBwbGFpbmx5IGFzIGFueSBsaXRlcmFsIHRpbWVvdXQgXHUyMDE0IGFuZFxuICogbGVhdmluZyB0aGVtIGFsbCBvdXQgaGlkIDIyIG92ZXItY2FwIGNsb3N1cmVzIGFjcm9zcyBzaXggcmVwb3MsIG9uZSBvZiB0aGVtIHRlbiB0aW1lcyBvdmVyLlxuICogVHdvIHNoYXBlcyBhcmUgcmVhZCBub3csIGJvdGggdGhyb3VnaCB0aGUgc2FtZSBzY29wZSB3YWxrIGEgYnVkZ2V0IHVzZXM6XG4gKlxuICogLSBBIERFQURMSU5FIGxvb3AgXHUyMDE0IGBjb25zdCBkZWFkbGluZSA9IERhdGUubm93KCkgKyBCVURHRVRgLCBndWFyZGVkIGJ5IGBEYXRlLm5vdygpIDwgZGVhZGxpbmVgIFx1MjAxNFxuICogICBjYW5ub3QgcnVuIGxvbmdlciB0aGFuIGBCVURHRVRgIHdoYXRldmVyIGl0cyBwb2xsIGludGVydmFsLCBzbyBgQlVER0VUYCBpcyBjaGFyZ2VkIHRvIHRoZVxuICogICBjbG9zdXJlIE9OQ0UgcGVyIGxvb3AsIG9uIHRvcCBvZiB0aGUgc2luZ2xlIGl0ZXJhdGlvbiBpdHMgaW5uZXIgd2FpdHMgYXJlIGFscmVhZHkgY2hhcmdlZFxuICogICAoYSBwb2xsIHRoYXQgc3RhcnRzIGp1c3QgdW5kZXIgdGhlIGRlYWRsaW5lIHN0aWxsIHJ1bnMgdG8gY29tcGxldGlvbiwgc28gdGhlIHN1bSBvZiB0aGUgdHdvXG4gKiAgIGlzIHRoZSBob25lc3Qgd29yc3QgY2FzZSByYXRoZXIgdGhhbiBhIGRvdWJsZSBjb3VudCkuIGBwZXJmb3JtYW5jZS5ub3coKWAgY291bnRzIGFzIHdlbGwgYXNcbiAqICAgYERhdGUubm93KClgOiBhIGBwZXJmb3JtYW5jZWAtd3JpdHRlbiBkZWFkbGluZSByZWFkIGFzIHVuYm91bmRlZCBpcyB3aHkgb25lIDI0NSAwMjUgbXNcbiAqICAgY2xvc3VyZSB3YXMgYWJzZW50IGZyb20gZXZlcnkgcm9zdGVyIHByb2R1Y2VkIGJlZm9yZSB0aGlzLlxuICogLSBBIENPVU5USU5HIGBmb3JgIFx1MjAxNCBgZm9yIChsZXQgYXR0ZW1wdCA9IDA7IGF0dGVtcHQgPCBBVFRFTVBUUzsgYXR0ZW1wdCsrKWAgXHUyMDE0IG11bHRpcGxpZXMgZXZlcnlcbiAqICAgd2FpdCBpbnNpZGUgaXQgYnkgaXRzIGl0ZXJhdGlvbiBjb3VudCwgcmVhZCBmcm9tIHRoZSBsb29wJ3Mgb3duIHN0YXJ0LCBib3VuZCBhbmQgc3RlcC5cbiAqXG4gKiBFaXRoZXIgY2VpbGluZyBtYXkgYmUgT05FIENPTkpVTkNUIG9mIGEgY29tcG91bmQgdGVzdCAoYHdoaWxlIChjb3VudCA8IGV4cGVjdGVkICYmIERhdGUubm93KCkgPCBkZWFkbGluZSlgLFxuICogYGZvciAobGV0IGF0dGVtcHQgPSAwOyBhdHRlbXB0IDwgQVRURU1QVFMgJiYgIWlzT3BlbjsgYXR0ZW1wdCsrKWApLCB3aGljaCBpcyBob3cgYm90aCBhcmUgYWN0dWFsbHlcbiAqIHdyaXR0ZW46IGEgcHJvZ3Jlc3MgY29uZGl0aW9uIGJlc2lkZSB0aGUgZ3VhcmQgZG9lcyBub3QgcmVtb3ZlIHRoZSBjZWlsaW5nIHRoZSBvdGhlciBjb25qdW5jdCBkZWNsYXJlcy5cbiAqXG4gKiBBbnl0aGluZyBlbHNlIGtlZXBzIHRoZSBvbGQgcGVyLWl0ZXJhdGlvbiBjaGFyZ2UgcmF0aGVyIHRoYW4gYSBndWVzcyBcdTIwMTQgYHdoaWxlICh0cnVlKWAsIGEgYGZvclx1MjAyNm9mYCxcbiAqIGEgYm91bmQgb3IgZGVhZGxpbmUgdGhhdCBkb2VzIG5vdCByZXNvbHZlIFx1MjAxNCB3aGljaCBpcyB3aGF0IGtlZXBzIGEgZ2VudWluZWx5IHVuYm91bmRlZCBsb29wIHNpbGVudC5cbiAqXG4gKiBBIEhFTFBFUiBkZWNsYXJlZCBpbnNpZGUgdGhlIGNsb3N1cmUgaXMgY2hhcmdlZCBvbmNlIHBlciBDQUxMIFNJVEUsIHdoaWNoIGlzIGhvdyBtYW55IHRpbWVzIGl0cyB3YWl0aW5nXG4gKiBhY3R1YWxseSBydW5zLiBJdHMgb3duIHdhaXRzIGFyZSBzdW1tZWQgb25jZSBhbmQgbXVsdGlwbGllZCBieSB0aGUgY2FsbHMgdGhhdCByZWFjaCBpdCwgZWFjaCBjYWxsXG4gKiBjYXJyeWluZyB0aGUgY291bnRpbmcgbG9vcHMgaXQgaXMgaXRzZWxmIHdyaXR0ZW4gaW5zaWRlIFx1MjAxNCBzbyBhIGxvY2FsIGB3YWl0VW50aWwoY2hlY2spYCBvZlxuICogYGZvciAoYXR0ZW1wdCA8IDQwKSBhd2FpdCBzbGVlcCgyNTApYCBjYWxsZWQgdGhyZWUgdGltZXMgZGVjbGFyZXMgMzAgMDAwIG1zIHJhdGhlciB0aGFuIHRoZSAxMCAwMDAgbXMgYVxuICogc2luZ2xlIGF0dHJpYnV0aW9uIHJlcG9ydGVkLiBUaHJlZSBib3VuZHMga2VlcCB0aGF0IGhvbmVzdDpcbiAqXG4gKiAtIEEgaGVscGVyIGRlY2xhcmVkIE9VVFNJREUgdGhlIGNsb3N1cmUgc3RheXMgb3V0IG9mIHNjb3BlLCBmb3IgdGhlIHNhbWUgcmVhc29uIGEgYnVkZ2V0IGFycml2aW5nIGZyb21cbiAqICAgYSBjYWxsZXIgaXM6IHJlYWRpbmcgaXQgbmVlZHMgYW5hbHlzaXMgYWNyb3NzIGNhbGwgYm91bmRhcmllcywgYW5kIHdpZGVuaW5nIHRoZXJlIHdvdWxkIG1ha2UgZXZlcnlcbiAqICAgbGVnaXRpbWF0ZWx5IHBhcmFtZXRlcml6ZWQgaGVscGVyIGluIGV2ZXJ5IGNvbnN1bWluZyByZXBvIHJlZC5cbiAqIC0gUkVDVVJTSU9OIHRlcm1pbmF0ZXMgYnkgY2hhcmdpbmcgYSByZS1lbnRlcmVkIGhlbHBlciBub3RoaW5nLCBzbyBuZWl0aGVyIGEgc2VsZi1jYWxsIG5vciBhIG11dHVhbGx5XG4gKiAgIHJlY3Vyc2l2ZSBwYWlyIGlzIGNoYXJnZWQgZm9yZXZlci4gQSByZWN1cnNpdmUgY2FsbCBjb250cmlidXRlcyB0aGUgc2lsZW5jZSBhbiB1bmJvdW5kZWQgbG9vcCBkb2VzLlxuICogLSBBIGhlbHBlciB0aGUgY2xvc3VyZSBuZXZlciBSRUFDSEVTIFx1MjAxNCBkZWFkLCBvciBjYWxsZWQgdGhyb3VnaCBzb21ldGhpbmcgdGhpcyBydWxlIGNhbm5vdCByZXNvbHZlLCBzdWNoXG4gKiAgIGFzIGEgYmFyZSByZWZlcmVuY2UgaGFuZGVkIHRvIGBmb3JFYWNoYCBcdTIwMTQga2VlcHMgdGhlIGZsYXQgc2luZ2xlIGNoYXJnZSBpdCBoYXMgYWx3YXlzIGhhZC4gU28gbm9cbiAqICAgY2xvc3VyZSB0aGlzIHJ1bGUgcmVwb3J0cyB0b2RheSBmYWxscyBzaWxlbnQgYmVjYXVzZSBhIGNhbGwgc2l0ZSBjb3VsZCBub3QgYmUgcmVhZC5cbiAqXG4gKiBXaGF0IHRoZSBwZXItY2FsbC1zaXRlIGNvdW50IGRvZXMgTk9UIGZpeCBpcyBhIEJSQU5DSFkgaGVscGVyOiBhbiBgaWZgIC8gYGVsc2VgIGlzIHN1bW1lZCBsZXhpY2FsbHkgbGlrZVxuICogYW55IHR3byBzaWJsaW5nIHdhaXRzLCBzbyBib3RoIGFybXMgYXJlIGNoYXJnZWQgYXQgZXZlcnkgY2FsbCBzaXRlLiBBIGhlbHBlciB3aG9zZSB0d28gZGlyZWN0aW9ucyB3YWl0XG4gKiBkaWZmZXJlbnRseSBpcyB0aGVyZWZvcmUgYmV0dGVyIHdyaXR0ZW4gYXMgdHdvIGhlbHBlcnMsIHdoaWNoIGlzIHdoYXQgdGhpcyByZXBvJ3Mgb3duXG4gKiBgc3JjL29ic2lkaWFuL2NvbXBvbmVudHMvc3ludGF4LWhpZ2hsaWdodGluZy1jb21wb25lbnQub2JzaWRpYW4uaW50ZWdyYXRpb24udGVzdC50c2Agbm93IGRvZXMuXG4gKlxuICogTm90IGV2ZXJ5IG92ZXItY2FwIGNsb3N1cmUgY2FuIGJlY29tZSBhIGBwb2xsYCAvIGB1bnRpbGAgcGFpciwgc28gdGhlIHJ1bGUgaXMgbWVhbnQgdG8gYmVcbiAqIGRpc2FibGVkIFx1MjAxNCB3aXRoIGEgcmVhc29uIFx1MjAxNCBhdCB0aGUgc2l0ZXMgdGhhdCBoYXZlIG9uZS4gYHJlcXVpcmUtZGVzY3JpcHRpb25gIG1ha2VzIHRoYXRcbiAqIHJlYXNvbiBtYW5kYXRvcnksIHdoaWNoIGlzIHRoZSBwb2ludDogaXQgdHVybnMgYW4gaW52aXNpYmxlIGFzc3VtcHRpb24gaW50byBhIHdyaXR0ZW4gb25lLlxuICpcbiAqIEEgQ0xPU1VSRSBERUxJQkVSQVRFTFkgTEVGVCBVTkRFUiBUSEUgQ0FQIFNBWVMgU08sIGluIGEgY29tbWVudCBvcGVuaW5nIHdpdGggdGhlIGV4YWN0IGxpbmVcbiAqXG4gKiAgICAgVW5kZXIgdGhlIHRyYW5zcG9ydCdzIH4zMHMgcGVyLWNsb3N1cmUgY2FwLCBub3QgYXQgaXQuXG4gKlxuICogYW5kIHRoZW4gc2F5aW5nLCBmb3IgdGhhdCBjbG9zdXJlLCB3aGF0IHRoZSBidWRnZXQgaXMgbWFkZSBvZiBhbmQgd2h5IGl0IHN0YXlzLiBUaGlzIHJ1bGUgaXMgc2lsZW50XG4gKiBvbiBzdWNoIGEgY2xvc3VyZSBieSBjb25zdHJ1Y3Rpb24gXHUyMDE0IGl0IGlzIHVuZGVyIHRoZSBjYXAgXHUyMDE0IHNvIHdpdGhvdXQgdGhlIGxpbmUgdGhlcmUgaXMgbm8gd2F5IHRvIHRlbGxcbiAqIGEgYnVkZ2V0IHNvbWVib2R5IHJlYWQgYW5kIGtlcHQgZnJvbSBvbmUgbm9ib2R5IGhhcyBsb29rZWQgYXQsIGFuZCBhIHN3ZWVwIHJ1biB3aXRoIGEgbG93ZXJcbiAqIGBjYXBJbk1pbGxpc2Vjb25kc2AgcmUtb3BlbnMgdGhlIHNhbWUgZGVjaXNpb25zIGV2ZXJ5IHRpbWUuIFRoZSBsaW5lIGlzIHRoZSB3aG9sZSBvZiB0aGUgY29udmVudGlvbixcbiAqIHdoaWNoIGlzIHdoYXQgbGV0cyBzdWNoIGEgc3dlZXAgc3VidHJhY3QgdGhlIGNsb3N1cmVzIGFscmVhZHkgcmVhZCBhbmQgZHJpdmUgdGhlIHJlbWFpbmRlciB0byB6ZXJvLlxuICpcbiAqIFR3byBwbGFjZW1lbnRzLCBiZWNhdXNlIGEgY2VpbGluZyBsaXZlcyBpbiB0d28gcGxhY2VzLiBBIGNvbW1lbnQgSU5TSURFIHRoZSBjbG9zdXJlLCBvdmVyIHRoYXRcbiAqIGNsb3N1cmUncyBvd24gY2VpbGluZyBjb25zdGFudCwgc3BlYWtzIGZvciB0aGF0IGNsb3N1cmUgYWxvbmU7IG9uZSBhdCBNT0RVTEUgc2NvcGUsIG92ZXIgYSBjb25zdGFudFxuICogdGhlIHdob2xlIGZpbGUgc2hhcmVzLCBzcGVha3MgZm9yIGV2ZXJ5IGNsb3N1cmUgaW4gdGhlIGZpbGUuIEEgY2xvc3VyZSB3aXRoIG5vIGNlaWxpbmcgY29uc3RhbnQgYXRcbiAqIGFsbCBcdTIwMTQgc2V2ZXJhbCBgd2FpdFVudGlsYCBjYWxscyB0YWtpbmcgdGhlIGRvY3VtZW50ZWQgZGVmYXVsdCBcdTIwMTQgdGFrZXMgdGhlIGluLWNsb3N1cmUgZm9ybSBhdCB0aGUgdG9wXG4gKiBvZiBpdHMgYm9keS5cbiAqXG4gKiBTYXlpbmcgaXQgaXMgTk9UIHRoZSBzYW1lIGFzIGNsZWFyaW5nIGl0LiBBIGJ1ZGdldCB1bmRlciB0aGUgY2FwIGlzIG5vdCBhIGRlZmVjdCwgYW5kIFwicmVhZCwgYW5kIGxlZnRcbiAqIGFzIGl0IGlzXCIgaXMgYSBjb3JyZWN0IG91dGNvbWU6IHRpZ2h0ZW5pbmcgYSBjZWlsaW5nIHRvIGJyaW5nIGEgbnVtYmVyIGRvd24gaXMgaG93IGEgc3VpdGUgc3RhcnRzXG4gKiBmYWlsaW5nIGxlZ2l0aW1hdGVseSBvbiBhIGNvbGQgbWFjaGluZS5cbiAqL1xuaW1wb3J0IHR5cGUgeyBUU0VTVHJlZSB9IGZyb20gJ0B0eXBlc2NyaXB0LWVzbGludC91dGlscyc7XG5pbXBvcnQgdHlwZSB7XG4gIFJ1bGUsXG4gIFNjb3BlXG59IGZyb20gJ2VzbGludCc7XG5cbmltcG9ydCB7IHRvVFNFU1RyZWVOb2RlIH0gZnJvbSAnQG1uYW91bW92L3R5cGVzY3JpcHQtZGV2LXRvb2xraXQvbGludGVycy9lc2xpbnQtcnVsZXMvdHMtZXN0cmVlLW5vZGUnO1xuaW1wb3J0IHsgREVGQVVMVF9FVkFMX0NBUF9JTl9NSUxMSVNFQ09ORFMgfSBmcm9tICdvYnNpZGlhbi1pbnRlZ3JhdGlvbi10ZXN0aW5nJztcblxuaW1wb3J0IHtcbiAgREVTS1RPUF9QRVJGT1JNQU5DRV9URVNUX0ZJTEVfU1VGRklYLFxuICBQRVJGT1JNQU5DRV9FVkFMX0NBUF9JTl9NSUxMSVNFQ09ORFNcbn0gZnJvbSAnLi4vLi4vdGVzdC1ydW5uZXJzL3BlcmZvcm1hbmNlLWV2YWwtY2FwLnRzJztcblxuLyoqXG4gKiBNZXNzYWdlIElEIHJlcG9ydGVkIHdoZW4gYW4gaW4tT2JzaWRpYW4gY2xvc3VyZSBkZWNsYXJlcyBtb3JlIHdhaXRpbmcgdGhhbiB0aGUgdHJhbnNwb3J0J3MgY2FwIGFsbG93cy5cbiAqL1xuZXhwb3J0IGNvbnN0IE1FU1NBR0VfSUQgPSAnbm9PdmVyQ2FwV2FpdEluRXZhbEluT2JzaWRpYW4nO1xuXG4vKipcbiAqIFRoZSBidWRnZXQgYSBgd2FpdFVudGlsYCB0YWtlcyB3aGVuIGl0IG9taXRzIGB0aW1lb3V0SW5NaWxsaXNlY29uZHNgLCBwZXIgYFdhaXRVbnRpbFBhcmFtc2AuXG4gKi9cbmNvbnN0IFdBSVRfVU5USUxfREVGQVVMVF9USU1FT1VUX0lOX01JTExJU0VDT05EUyA9IDUwMDA7XG5cbmNvbnN0IElOUFVUX1BST1BFUlRZX05BTUUgPSAnaW5wdXQnO1xuY29uc3QgU0xFRVBfQ0FMTEVFX05BTUUgPSAnc2xlZXAnO1xuY29uc3QgVElNRU9VVF9QUk9QRVJUWV9OQU1FID0gJ3RpbWVvdXRJbk1pbGxpc2Vjb25kcyc7XG5jb25zdCBXQUlUX1VOVElMX0NBTExFRV9OQU1FID0gJ3dhaXRVbnRpbCc7XG5cbi8qKlxuICogVGhlIGNsb2NrcyBhIGRlYWRsaW5lIG1heSBiZSB0YWtlbiBmcm9tLiBCb3RoIG9jY3VyIGluIHRoZXNlIHN1aXRlcywgYW5kIGEgcnVsZSB0aGF0IGtuZXcgb25seSBgRGF0ZWBcbiAqIHJlYWQgZXZlcnkgYHBlcmZvcm1hbmNlYC13cml0dGVuIGRlYWRsaW5lIGFzIHVuYm91bmRlZC5cbiAqL1xuY29uc3QgQ0xPQ0tfT0JKRUNUX05BTUVTID0gbmV3IFNldChbJ0RhdGUnLCAncGVyZm9ybWFuY2UnXSk7XG5cbmNvbnN0IE5PV19NRVRIT0RfTkFNRSA9ICdub3cnO1xuXG4vKipcbiAqIFdoaWNoIHByb3BlcnRpZXMgb2YgZWFjaCBoZWxwZXIncyBwYXJhbWV0ZXIgb2JqZWN0IGhvbGQgYSBjbG9zdXJlIHRoYXQgcnVucyBJTlNJREUgT2JzaWRpYW4sIGFuZCBpc1xuICogdGhlcmVmb3JlIHN1YmplY3QgdG8gdGhlIGNhcC4gYHBvbGxJbk9ic2lkaWFuYCdzIGB1bnRpbGAgaXMgZGVsaWJlcmF0ZWx5IGFic2VudDogaXQgaXMgZXZhbHVhdGVkIGluXG4gKiBOb2RlLCB3aGljaCBpcyB0aGUgZW50aXJlIHBvaW50IG9mIGNvbnZlcnRpbmcgdG8gaXQuXG4gKi9cbmNvbnN0IENMT1NVUkVfTkFNRVNfQllfQ0FMTEVFX05BTUUgPSBuZXcgTWFwPHN0cmluZywgcmVhZG9ubHkgc3RyaW5nW10+KFtcbiAgWydldmFsSW5PYnNpZGlhbicsIFsnY2FsbGJhY2snXV0sXG4gIFsncG9sbEluT2JzaWRpYW4nLCBbJ3BvbGwnLCAnc3RhcnQnXV1cbl0pO1xuXG4vKipcbiAqIEV2ZXJ5dGhpbmcgb25lIGZpbGUgYWNjdW11bGF0ZWQsIGtleWVkIGJ5IHRoZSBmdW5jdGlvbiBlYWNoIGNoYXJnZSB3YXMgd3JpdHRlbiBpbnNpZGUuXG4gKlxuICogQSB3YWl0IGlzIGNoYXJnZWQgdG8gdGhlIGlubmVybW9zdCBmdW5jdGlvbiBpdCBpcyB3cml0dGVuIGluIHJhdGhlciB0aGFuIHN0cmFpZ2h0IHRvIHRoZSBjbG9zdXJlLCBhbmQgYVxuICogY2FsbCB0byBhIGhlbHBlciB0aGUgY2xvc3VyZSBkZWNsYXJlcyBpcyByZWNvcmRlZCBhcyBhbiBlZGdlLCBzbyBhIGNsb3N1cmUncyB0b3RhbCBpcyBpdHMgb3duIHdhaXRpbmdcbiAqIHBsdXMgZWFjaCBoZWxwZXIncyB3YWl0aW5nIG11bHRpcGxpZWQgYnkgdGhlIGNhbGxzIHRoYXQgYWN0dWFsbHkgcmVhY2ggaXQuXG4gKi9cbmludGVyZmFjZSBDYWxsR3JhcGgge1xuICAvKipcbiAgICogSG93IG1hbnkgdGltZXMgZWFjaCBmdW5jdGlvbiBjYWxscyBlYWNoIGhlbHBlciBkZWNsYXJlZCBpbnNpZGUgdGhlIHNhbWUgY2xvc3VyZS5cbiAgICovXG4gIHJlYWRvbmx5IGNhbGxDb3VudEJ5Q2FsbGVlTm9kZUJ5Q2FsbGVyTm9kZTogTWFwPEhlbHBlckZ1bmN0aW9uLCBNYXA8SGVscGVyRnVuY3Rpb24sIG51bWJlcj4+O1xuXG4gIC8qKlxuICAgKiBUaGUgY2xvc3VyZXMgc2VlbiBzbyBmYXIsIGJ5IHRoZSBmdW5jdGlvbiBub2RlIGVhY2ggb25lIGlzIHdyaXR0ZW4gYXMuXG4gICAqL1xuICByZWFkb25seSBzdGF0ZUJ5Q2xvc3VyZU5vZGU6IE1hcDxDbG9zdXJlRnVuY3Rpb24sIENsb3N1cmVTdGF0ZT47XG5cbiAgLyoqXG4gICAqIFRoZSB3YWl0aW5nIHdyaXR0ZW4gRElSRUNUTFkgaW5zaWRlIGVhY2ggZnVuY3Rpb24sIGV4Y2x1ZGluZyB3aGF0ZXZlciB0aGUgaGVscGVycyBpdCBjYWxscyBkZWNsYXJlLlxuICAgKi9cbiAgcmVhZG9ubHkgd2FpdEluTWlsbGlzZWNvbmRzQnlGdW5jdGlvbk5vZGU6IE1hcDxIZWxwZXJGdW5jdGlvbiwgbnVtYmVyPjtcbn1cblxuLyoqXG4gKiBUaGUgcnVsZSdzIHNpbmdsZSBvcHRpb24gb2JqZWN0LlxuICovXG5pbnRlcmZhY2UgQ2FwT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBUaGUgYnVkZ2V0IGF0IG9yIG92ZXIgd2hpY2ggYSBjbG9zdXJlIGlzIHJlcG9ydGVkLCBpbiBtaWxsaXNlY29uZHMuXG4gICAqL1xuICByZWFkb25seSBjYXBJbk1pbGxpc2Vjb25kcz86IG51bWJlcjtcbn1cblxuLyoqXG4gKiBUaGUgZnVuY3Rpb24gYSBjaGFyZ2UgaXMgYXR0cmlidXRlZCB0bywgdG9nZXRoZXIgd2l0aCB0aGUgaW4tT2JzaWRpYW4gY2xvc3VyZSBpdCB1bHRpbWF0ZWx5IHJ1bnMgaW5zaWRlLlxuICovXG5pbnRlcmZhY2UgQ2hhcmdlVGFyZ2V0IHtcbiAgLyoqXG4gICAqIFRoZSBjbG9zdXJlIHRoZSBjaGFyZ2UgcnVucyBpbnNpZGUsIGNhcnJpZWQgc28gYSBidWRnZXQgdGhyZWFkZWQgdGhyb3VnaCBpdHMgY2FsbCBzdGlsbCByZXNvbHZlcy5cbiAgICovXG4gIHJlYWRvbmx5IGNsb3N1cmU6IEV2YWxDbG9zdXJlO1xuXG4gIC8qKlxuICAgKiBUaGUgaW5uZXJtb3N0IGZ1bmN0aW9uIHRoZSBjaGFyZ2UgaXMgd3JpdHRlbiBpbjogdGhlIGNsb3N1cmUgaXRzZWxmLCBvciBhIGhlbHBlciBkZWNsYXJlZCB3aXRoaW4gaXQuXG4gICAqL1xuICByZWFkb25seSBmdW5jdGlvbk5vZGU6IEhlbHBlckZ1bmN0aW9uO1xufVxuXG4vKipcbiAqIEEgZnVuY3Rpb24gd3JpdHRlbiBhcyBhbiBvYmplY3QgcHJvcGVydHksIHdoaWNoIGlzIHRoZSBvbmx5IGZvcm0gZWl0aGVyIGhlbHBlcidzIGNsb3N1cmVzIHRha2UuXG4gKi9cbnR5cGUgQ2xvc3VyZUZ1bmN0aW9uID0gVFNFU1RyZWUuQXJyb3dGdW5jdGlvbkV4cHJlc3Npb24gfCBUU0VTVHJlZS5GdW5jdGlvbkV4cHJlc3Npb247XG5cbi8qKlxuICogT25lIGluLU9ic2lkaWFuIGNsb3N1cmUncyBhY2N1bXVsYXRlZCBjaGFyZ2VzLlxuICovXG5pbnRlcmZhY2UgQ2xvc3VyZVN0YXRlIHtcbiAgLyoqXG4gICAqIFRoZSBjbG9zdXJlJ3Mgb3duIGZ1bmN0aW9uIG5vZGUsIHRoZSByb290IGV2ZXJ5IHJlYWNoYWJsZSBoZWxwZXIgaXMgY291bnRlZCBmcm9tLlxuICAgKi9cbiAgcmVhZG9ubHkgY2xvc3VyZU5vZGU6IENsb3N1cmVGdW5jdGlvbjtcblxuICAvKipcbiAgICogRXZlcnkgZnVuY3Rpb24gY2hhcmdlZCBpbnNpZGUgdGhpcyBjbG9zdXJlOiB0aGUgY2xvc3VyZSBpdHNlbGYsIGFuZCBlYWNoIGhlbHBlciBpdCBkZWNsYXJlcy5cbiAgICovXG4gIHJlYWRvbmx5IGZ1bmN0aW9uTm9kZXM6IFNldDxIZWxwZXJGdW5jdGlvbj47XG5cbiAgLyoqXG4gICAqIFRoZSBwcm9wZXJ0eSB0aGUgY2xvc3VyZSBpcyB3cml0dGVuIGFzLCByZXBvcnRlZCBvbi5cbiAgICovXG4gIHJlYWRvbmx5IHJlcG9ydE5vZGU6IFRTRVNUcmVlLk5vZGU7XG59XG5cbi8qKlxuICogQW4gaW4tT2JzaWRpYW4gY2xvc3VyZSwgdG9nZXRoZXIgd2l0aCB0aGUgY2FsbCBpdCBiZWxvbmdzIHRvIChuZWVkZWQgdG8gcmVzb2x2ZSBhIGJ1ZGdldCB0aHJlYWRlZFxuICogdGhyb3VnaCB0aGF0IGNhbGwncyBgaW5wdXRgKSBhbmQgdGhlIG5vZGUgdG8gcmVwb3J0IG9uLlxuICovXG5pbnRlcmZhY2UgRXZhbENsb3N1cmUge1xuICAvKipcbiAgICogVGhlIGNsb3N1cmUncyBmdW5jdGlvbiBub2RlLCB3aGljaCBpZGVudGlmaWVzIHRoZSBjbG9zdXJlIGFjcm9zcyBzaWJsaW5nIHdhaXRzIGFuZCBjYXJyaWVzIHRoZVxuICAgKiBwYXJhbWV0ZXIgcGF0dGVybiBhIGJ1ZGdldCB0aHJlYWRlZCB0aHJvdWdoIGBpbnB1dGAgaXMgZGVzdHJ1Y3R1cmVkIGJ5LlxuICAgKi9cbiAgcmVhZG9ubHkgY2xvc3VyZU5vZGU6IENsb3N1cmVGdW5jdGlvbjtcblxuICAvKipcbiAgICogVGhlIGhlbHBlcidzIHBhcmFtZXRlciBvYmplY3QsIGNhcnJpZWQgc28gYSBidWRnZXQgdGhyZWFkZWQgdGhyb3VnaCBgaW5wdXRgIGlzIHJlYWQgZnJvbSB0aGUgb2JqZWN0XG4gICAqIHRoZSBjbG9zdXJlIHdhcyBhbHJlYWR5IGZvdW5kIGluIHJhdGhlciB0aGFuIHJlLWRlcml2ZWQgZnJvbSB0aGUgY2FsbC5cbiAgICovXG4gIHJlYWRvbmx5IHBhcmFtc05vZGU6IFRTRVNUcmVlLk9iamVjdEV4cHJlc3Npb247XG5cbiAgLyoqXG4gICAqIFRoZSBwcm9wZXJ0eSB0aGUgY2xvc3VyZSBpcyB3cml0dGVuIGFzLCByZXBvcnRlZCBvbiBzbyB0aGUgbWVzc2FnZSBwb2ludHMgYXQgYGNhbGxiYWNrYCAvIGBwb2xsYFxuICAgKiByYXRoZXIgdGhhbiBhdCB3aGljaGV2ZXIgd2FpdCBoYXBwZW5lZCB0byBjb21lIGZpcnN0LlxuICAgKi9cbiAgcmVhZG9ubHkgcmVwb3J0Tm9kZTogVFNFU1RyZWUuTm9kZTtcbn1cblxuLyoqXG4gKiBBIGZ1bmN0aW9uIHdhaXRpbmcgY2FuIGJlIGNoYXJnZWQgdG86IGFuIGluLU9ic2lkaWFuIGNsb3N1cmUsIG9yIGEgaGVscGVyIGRlY2xhcmVkIGluc2lkZSBvbmUgXHUyMDE0IHdoaWNoIGFcbiAqIGBmdW5jdGlvbmAgZGVjbGFyYXRpb24gaXMgYXMgcmVhZGlseSBhcyBhbiBhcnJvdyBvciBhIGZ1bmN0aW9uIGV4cHJlc3Npb24uXG4gKi9cbnR5cGUgSGVscGVyRnVuY3Rpb24gPSBDbG9zdXJlRnVuY3Rpb24gfCBUU0VTVHJlZS5GdW5jdGlvbkRlY2xhcmF0aW9uO1xuXG4vKipcbiAqIEEgbG9vcCB3aG9zZSBvd24gdGVzdCBjYW4gZGVjbGFyZSBhIGNlaWxpbmcuIGBmb3JcdTIwMjZvZmAgLyBgZm9yXHUyMDI2aW5gIGFyZSBkZWxpYmVyYXRlbHkgYWJzZW50OiBuZWl0aGVyXG4gKiBkZWNsYXJlcyBvbmUgc3RhdGljYWxseSwgc28gYm90aCBrZWVwIHRoZSBwZXItaXRlcmF0aW9uIGNoYXJnZSBldmVyeSB1bnNpemVkIGxvb3AgZ2V0cy5cbiAqL1xudHlwZSBMb29wU3RhdGVtZW50ID0gVFNFU1RyZWUuRG9XaGlsZVN0YXRlbWVudCB8IFRTRVNUcmVlLkZvclN0YXRlbWVudCB8IFRTRVNUcmVlLldoaWxlU3RhdGVtZW50O1xuXG4vKipcbiAqIEVTTGludCBydWxlIGRpc2FsbG93aW5nIGFuIGluLU9ic2lkaWFuIGNsb3N1cmUgd2hvc2UgZGVjbGFyZWQgd2FpdGluZyBleGNlZWRzIHRoZSB0cmFuc3BvcnQncyBzY3JpcHQtdGltZW91dCBjYXAuXG4gKi9cbmV4cG9ydCBjb25zdCBub092ZXJDYXBXYWl0SW5FdmFsSW5PYnNpZGlhbjogUnVsZS5SdWxlTW9kdWxlID0ge1xuICBjcmVhdGUoY29udGV4dCkge1xuICAgIGNvbnN0IG9wdGlvbnMgPSBjb250ZXh0Lm9wdGlvbnNbMF0gYXMgQ2FwT3B0aW9ucyB8IHVuZGVmaW5lZDtcbiAgICBjb25zdCBkZWZhdWx0Q2FwSW5NaWxsaXNlY29uZHMgPSBjb250ZXh0LmZpbGVuYW1lLmVuZHNXaXRoKERFU0tUT1BfUEVSRk9STUFOQ0VfVEVTVF9GSUxFX1NVRkZJWClcbiAgICAgID8gUEVSRk9STUFOQ0VfRVZBTF9DQVBfSU5fTUlMTElTRUNPTkRTXG4gICAgICA6IERFRkFVTFRfRVZBTF9DQVBfSU5fTUlMTElTRUNPTkRTO1xuICAgIGNvbnN0IGNhcEluTWlsbGlzZWNvbmRzID0gb3B0aW9ucz8uY2FwSW5NaWxsaXNlY29uZHMgPz8gZGVmYXVsdENhcEluTWlsbGlzZWNvbmRzO1xuICAgIGNvbnN0IGNhbGxHcmFwaDogQ2FsbEdyYXBoID0ge1xuICAgICAgY2FsbENvdW50QnlDYWxsZWVOb2RlQnlDYWxsZXJOb2RlOiBuZXcgTWFwPEhlbHBlckZ1bmN0aW9uLCBNYXA8SGVscGVyRnVuY3Rpb24sIG51bWJlcj4+KCksXG4gICAgICBzdGF0ZUJ5Q2xvc3VyZU5vZGU6IG5ldyBNYXA8Q2xvc3VyZUZ1bmN0aW9uLCBDbG9zdXJlU3RhdGU+KCksXG4gICAgICB3YWl0SW5NaWxsaXNlY29uZHNCeUZ1bmN0aW9uTm9kZTogbmV3IE1hcDxIZWxwZXJGdW5jdGlvbiwgbnVtYmVyPigpXG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlY29yZHMgdGhhdCBvbmUgZnVuY3Rpb24gY2FsbHMgYSBoZWxwZXIgZGVjbGFyZWQgaW5zaWRlIHRoZSBzYW1lIGNsb3N1cmUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdGFyZ2V0IC0gVGhlIGZ1bmN0aW9uIHRoZSBjYWxsIGlzIHdyaXR0ZW4gaW4uXG4gICAgICogQHBhcmFtIGNhbGxlZU5vZGUgLSBUaGUgaGVscGVyIGJlaW5nIGNhbGxlZC5cbiAgICAgKiBAcGFyYW0gY2FsbENvdW50IC0gSG93IG1hbnkgdGltZXMgdGhlIGNhbGwgcnVucywgYXMgdGhlIHByb2R1Y3Qgb2YgaXRzIGVuY2xvc2luZyBjb3VudGluZyBsb29wcy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhZGRDYWxsKHRhcmdldDogQ2hhcmdlVGFyZ2V0LCBjYWxsZWVOb2RlOiBIZWxwZXJGdW5jdGlvbiwgY2FsbENvdW50OiBudW1iZXIpOiB2b2lkIHtcbiAgICAgIGNvbnN0IHN0YXRlID0gcmVhZENsb3N1cmVTdGF0ZSh0YXJnZXQpO1xuICAgICAgc3RhdGUuZnVuY3Rpb25Ob2Rlcy5hZGQoY2FsbGVlTm9kZSk7XG5cbiAgICAgIGNvbnN0IGNhbGxDb3VudEJ5Q2FsbGVlTm9kZSA9IGNhbGxHcmFwaC5jYWxsQ291bnRCeUNhbGxlZU5vZGVCeUNhbGxlck5vZGUuZ2V0KHRhcmdldC5mdW5jdGlvbk5vZGUpXG4gICAgICAgID8/IG5ldyBNYXA8SGVscGVyRnVuY3Rpb24sIG51bWJlcj4oKTtcbiAgICAgIGNhbGxHcmFwaC5jYWxsQ291bnRCeUNhbGxlZU5vZGVCeUNhbGxlck5vZGUuc2V0KHRhcmdldC5mdW5jdGlvbk5vZGUsIGNhbGxDb3VudEJ5Q2FsbGVlTm9kZSk7XG4gICAgICBjYWxsQ291bnRCeUNhbGxlZU5vZGUuc2V0KGNhbGxlZU5vZGUsIChjYWxsQ291bnRCeUNhbGxlZU5vZGUuZ2V0KGNhbGxlZU5vZGUpID8/IDApICsgY2FsbENvdW50KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIHdhaXRpbmcgdG8gdGhlIHJ1bm5pbmcgdG90YWwgb2YgdGhlIGZ1bmN0aW9uIGl0IHdhcyB3cml0dGVuIGluLlxuICAgICAqXG4gICAgICogQHBhcmFtIHRhcmdldCAtIFRoZSBmdW5jdGlvbiB0byBjaGFyZ2UuXG4gICAgICogQHBhcmFtIHdhaXRJbk1pbGxpc2Vjb25kcyAtIFRoZSB3YWl0aW5nIHRvIGFkZC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhZGRXYWl0KHRhcmdldDogQ2hhcmdlVGFyZ2V0LCB3YWl0SW5NaWxsaXNlY29uZHM6IG51bWJlcik6IHZvaWQge1xuICAgICAgcmVhZENsb3N1cmVTdGF0ZSh0YXJnZXQpO1xuICAgICAgY29uc3QgcnVubmluZ1RvdGFsSW5NaWxsaXNlY29uZHMgPSBjYWxsR3JhcGgud2FpdEluTWlsbGlzZWNvbmRzQnlGdW5jdGlvbk5vZGUuZ2V0KHRhcmdldC5mdW5jdGlvbk5vZGUpID8/IDA7XG4gICAgICBjYWxsR3JhcGgud2FpdEluTWlsbGlzZWNvbmRzQnlGdW5jdGlvbk5vZGUuc2V0KHRhcmdldC5mdW5jdGlvbk5vZGUsIHJ1bm5pbmdUb3RhbEluTWlsbGlzZWNvbmRzICsgd2FpdEluTWlsbGlzZWNvbmRzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZWNvcmRzIGEgY2FsbCB0byBhIGhlbHBlciB0aGUgY2xvc3VyZSBkZWNsYXJlcywgc28gaXRzIHdhaXRpbmcgaXMgY291bnRlZCBvbmNlIHBlciBjYWxsIHNpdGUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gY2FsbE5vZGUgLSBUaGUgY2FsbCBleHByZXNzaW9uLlxuICAgICAqIEBwYXJhbSB0YXJnZXQgLSBUaGUgZnVuY3Rpb24gdGhlIGNhbGwgaXMgd3JpdHRlbiBpbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjaGFyZ2VIZWxwZXJDYWxsKGNhbGxOb2RlOiBUU0VTVHJlZS5DYWxsRXhwcmVzc2lvbiwgdGFyZ2V0OiBDaGFyZ2VUYXJnZXQpOiB2b2lkIHtcbiAgICAgIGNvbnN0IGhlbHBlck5vZGUgPSByZWFkQ2FsbGVkSGVscGVyTm9kZShjYWxsTm9kZSwgdGFyZ2V0LmNsb3N1cmUsIGNvbnRleHQpO1xuICAgICAgaWYgKCFoZWxwZXJOb2RlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgYWRkQ2FsbCh0YXJnZXQsIGhlbHBlck5vZGUsIHJlYWRMb29wTXVsdGlwbGllcihjYWxsTm9kZSwgdGFyZ2V0LCBjb250ZXh0KSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hhcmdlcyBhIGRlYWRsaW5lLWJvdW5kZWQgbG9vcCBpdHMgd2hvbGUgZGVhZGxpbmUsIG9uY2UuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gbm9kZSAtIFRoZSBsb29wIHN0YXRlbWVudC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjaGFyZ2VMb29wRGVhZGxpbmUobm9kZTogUnVsZS5Ob2RlKTogdm9pZCB7XG4gICAgICBjb25zdCBsb29wTm9kZSA9IHRvVFNFU1RyZWVOb2RlKG5vZGUpIGFzIExvb3BTdGF0ZW1lbnQ7XG5cbiAgICAgIGNvbnN0IHRhcmdldCA9IGZpbmRDaGFyZ2VUYXJnZXQobG9vcE5vZGUpO1xuICAgICAgaWYgKCF0YXJnZXQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBkZWFkbGluZUluTWlsbGlzZWNvbmRzID0gcmVhZExvb3BEZWFkbGluZUluTWlsbGlzZWNvbmRzKGxvb3BOb2RlLCB0YXJnZXQuY2xvc3VyZSwgY29udGV4dCk7XG4gICAgICBpZiAoZGVhZGxpbmVJbk1pbGxpc2Vjb25kcyA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGFkZFdhaXQodGFyZ2V0LCBkZWFkbGluZUluTWlsbGlzZWNvbmRzICogcmVhZExvb3BNdWx0aXBsaWVyKGxvb3BOb2RlLCB0YXJnZXQsIGNvbnRleHQpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGFyZ2VzIGEgd2FpdCBjYWxsIHRoZSBidWRnZXQgaXQgZGVjbGFyZXMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gY2FsbE5vZGUgLSBUaGUgY2FsbCBleHByZXNzaW9uLlxuICAgICAqIEBwYXJhbSB0YXJnZXQgLSBUaGUgZnVuY3Rpb24gdGhlIGNhbGwgaXMgd3JpdHRlbiBpbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjaGFyZ2VXYWl0Q2FsbChjYWxsTm9kZTogVFNFU1RyZWUuQ2FsbEV4cHJlc3Npb24sIHRhcmdldDogQ2hhcmdlVGFyZ2V0KTogdm9pZCB7XG4gICAgICBjb25zdCBidWRnZXRFeHByZXNzaW9uID0gcmVhZFdhaXRCdWRnZXRFeHByZXNzaW9uKGNhbGxOb2RlKTtcbiAgICAgIGlmIChidWRnZXRFeHByZXNzaW9uID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB3YWl0SW5NaWxsaXNlY29uZHMgPSBidWRnZXRFeHByZXNzaW9uID09PSBudWxsXG4gICAgICAgID8gV0FJVF9VTlRJTF9ERUZBVUxUX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTXG4gICAgICAgIDogcmVzb2x2ZU51bWJlcihidWRnZXRFeHByZXNzaW9uLCB0YXJnZXQuY2xvc3VyZSwgY29udGV4dCk7XG4gICAgICBpZiAod2FpdEluTWlsbGlzZWNvbmRzID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgYWRkV2FpdCh0YXJnZXQsIHdhaXRJbk1pbGxpc2Vjb25kcyAqIHJlYWRMb29wTXVsdGlwbGllcihjYWxsTm9kZSwgdGFyZ2V0LCBjb250ZXh0KSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVnaXN0ZXJzIHRoZSBjbG9zdXJlIGEgY2hhcmdlIGJlbG9uZ3MgdG8sIGFuZCB0aGUgZnVuY3Rpb24gdGhlIGNoYXJnZSB3YXMgd3JpdHRlbiBpbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB0YXJnZXQgLSBUaGUgZnVuY3Rpb24gYmVpbmcgY2hhcmdlZC5cbiAgICAgKiBAcmV0dXJucyBUaGF0IGNsb3N1cmUncyBhY2N1bXVsYXRlZCBzdGF0ZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiByZWFkQ2xvc3VyZVN0YXRlKHRhcmdldDogQ2hhcmdlVGFyZ2V0KTogQ2xvc3VyZVN0YXRlIHtcbiAgICAgIGNvbnN0IHN0YXRlID0gY2FsbEdyYXBoLnN0YXRlQnlDbG9zdXJlTm9kZS5nZXQodGFyZ2V0LmNsb3N1cmUuY2xvc3VyZU5vZGUpID8/IHtcbiAgICAgICAgY2xvc3VyZU5vZGU6IHRhcmdldC5jbG9zdXJlLmNsb3N1cmVOb2RlLFxuICAgICAgICBmdW5jdGlvbk5vZGVzOiBuZXcgU2V0PEhlbHBlckZ1bmN0aW9uPigpLFxuICAgICAgICByZXBvcnROb2RlOiB0YXJnZXQuY2xvc3VyZS5yZXBvcnROb2RlXG4gICAgICB9O1xuICAgICAgY2FsbEdyYXBoLnN0YXRlQnlDbG9zdXJlTm9kZS5zZXQodGFyZ2V0LmNsb3N1cmUuY2xvc3VyZU5vZGUsIHN0YXRlKTtcbiAgICAgIHN0YXRlLmZ1bmN0aW9uTm9kZXMuYWRkKHRhcmdldC5mdW5jdGlvbk5vZGUpO1xuICAgICAgcmV0dXJuIHN0YXRlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAnQ2FsbEV4cHJlc3Npb24nKG5vZGU6IFJ1bGUuTm9kZSk6IHZvaWQge1xuICAgICAgICBjb25zdCBjYWxsTm9kZSA9IHRvVFNFU1RyZWVOb2RlKG5vZGUpIGFzIFRTRVNUcmVlLkNhbGxFeHByZXNzaW9uO1xuXG4gICAgICAgIGNvbnN0IHRhcmdldCA9IGZpbmRDaGFyZ2VUYXJnZXQoY2FsbE5vZGUpO1xuICAgICAgICBpZiAoIXRhcmdldCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNoYXJnZVdhaXRDYWxsKGNhbGxOb2RlLCB0YXJnZXQpO1xuICAgICAgICBjaGFyZ2VIZWxwZXJDYWxsKGNhbGxOb2RlLCB0YXJnZXQpO1xuICAgICAgfSxcbiAgICAgIERvV2hpbGVTdGF0ZW1lbnQ6IGNoYXJnZUxvb3BEZWFkbGluZSxcbiAgICAgIEZvclN0YXRlbWVudDogY2hhcmdlTG9vcERlYWRsaW5lLFxuICAgICAgJ1Byb2dyYW06ZXhpdCcoKTogdm9pZCB7XG4gICAgICAgIGZvciAoY29uc3Qgc3RhdGUgb2YgY2FsbEdyYXBoLnN0YXRlQnlDbG9zdXJlTm9kZS52YWx1ZXMoKSkge1xuICAgICAgICAgIGNvbnN0IHRvdGFsSW5NaWxsaXNlY29uZHMgPSByZWFkQ2xvc3VyZVdhaXRJbk1pbGxpc2Vjb25kcyhzdGF0ZSwgY2FsbEdyYXBoKTtcbiAgICAgICAgICBpZiAodG90YWxJbk1pbGxpc2Vjb25kcyA8IGNhcEluTWlsbGlzZWNvbmRzKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb250ZXh0LnJlcG9ydCh7XG4gICAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICAgIGNhcEluTWlsbGlzZWNvbmRzOiBTdHJpbmcoY2FwSW5NaWxsaXNlY29uZHMpLFxuICAgICAgICAgICAgICB0b3RhbEluTWlsbGlzZWNvbmRzOiBTdHJpbmcodG90YWxJbk1pbGxpc2Vjb25kcylcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBtZXNzYWdlSWQ6IE1FU1NBR0VfSUQsXG4gICAgICAgICAgICBub2RlOiBzdGF0ZS5yZXBvcnROb2RlXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBXaGlsZVN0YXRlbWVudDogY2hhcmdlTG9vcERlYWRsaW5lXG4gICAgfTtcbiAgfSxcbiAgbWV0YToge1xuICAgIGRvY3M6IHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnRGlzYWxsb3cgYW4gaW4tT2JzaWRpYW4gY2xvc3VyZSBkZWNsYXJpbmcgbW9yZSB3YWl0aW5nIHRoYW4gdGhlIHRyYW5zcG9ydFxcJ3Mgc2NyaXB0LXRpbWVvdXQgY2FwIGFsbG93cydcbiAgICB9LFxuICAgIG1lc3NhZ2VzOiB7XG4gICAgICBbTUVTU0FHRV9JRF06ICdUaGlzIGNsb3N1cmUgZGVjbGFyZXMge3sgdG90YWxJbk1pbGxpc2Vjb25kcyB9fSBtcyBvZiB3YWl0aW5nLCBhdCBvciBvdmVyIHRoZSB0cmFuc3BvcnRcXCdzIHt7IGNhcEluTWlsbGlzZWNvbmRzIH19IG1zIGNhcCwgc28gaXQgY2FuIG9ubHkgZXZlciBkaWUgYXMgYSBiYXJlIGBzY3JpcHQgdGltZW91dGA6IHdhaXQgaW4gTm9kZSBpbnN0ZWFkLCB3aXRoIGEgc2hvcnQgRE9NLXJlYWRpbmcgYHBvbGxJbk9ic2lkaWFuYCBgcG9sbGAsIGFuIGB1bnRpbGAgZXZhbHVhdGVkIGluIE5vZGUsIGFuZCB0aGUgbG9uZyBidWRnZXQgaW4gYHRpbWVvdXRJbk1pbGxpc2Vjb25kc2AuJ1xuICAgIH0sXG4gICAgc2NoZW1hOiBbe1xuICAgICAgYWRkaXRpb25hbFByb3BlcnRpZXM6IGZhbHNlLFxuICAgICAgcHJvcGVydGllczoge1xuICAgICAgICBjYXBJbk1pbGxpc2Vjb25kczoge1xuICAgICAgICAgIG1pbmltdW06IDEsXG4gICAgICAgICAgdHlwZTogJ2ludGVnZXInXG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICB0eXBlOiAnb2JqZWN0J1xuICAgIH1dLFxuICAgIHR5cGU6ICdwcm9ibGVtJ1xuICB9XG59O1xuXG4vKipcbiAqIENvbGxlY3RzIGV2ZXJ5IGhlbHBlciByZWFjaGFibGUgZnJvbSBhIGZ1bmN0aW9uIGJ5IGZvbGxvd2luZyB0aGUgY2FsbHMgcmVjb3JkZWQgZm9yIGl0cyBjbG9zdXJlLlxuICpcbiAqIEEgaGVscGVyIE5PVCBpbiB0aGUgYW5zd2VyIGlzIG9uZSBubyBjYWxsIHNpdGUgY2FuIHJlYWNoLCB3aGljaCBpcyB3aGF0IHRoZSBmbGF0IGZhbGxiYWNrIGNoYXJnZSBpc1xuICoga2V5ZWQgb2ZmOiBpdCBpcyBlaXRoZXIgZGVhZCwgb3IgY2FsbGVkIHRocm91Z2ggc29tZXRoaW5nIHRoaXMgcnVsZSBjYW5ub3QgcmVhZC5cbiAqXG4gKiBAcGFyYW0gZnVuY3Rpb25Ob2RlIC0gVGhlIGZ1bmN0aW9uIHRvIHN0YXJ0IGZyb20uXG4gKiBAcGFyYW0gY2FsbEdyYXBoIC0gVGhlIGZpbGUncyBhY2N1bXVsYXRlZCBjaGFyZ2VzLlxuICogQHBhcmFtIHJlYWNoYWJsZU5vZGVzIC0gVGhlIHNldCB0byBjb2xsZWN0IGludG8sIHdoaWNoIGRvdWJsZXMgYXMgdGhlIHZpc2l0ZWQgc2V0LlxuICovXG5mdW5jdGlvbiBjb2xsZWN0UmVhY2hhYmxlRnVuY3Rpb25Ob2RlcyhmdW5jdGlvbk5vZGU6IEhlbHBlckZ1bmN0aW9uLCBjYWxsR3JhcGg6IENhbGxHcmFwaCwgcmVhY2hhYmxlTm9kZXM6IFNldDxIZWxwZXJGdW5jdGlvbj4pOiB2b2lkIHtcbiAgaWYgKHJlYWNoYWJsZU5vZGVzLmhhcyhmdW5jdGlvbk5vZGUpKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcmVhY2hhYmxlTm9kZXMuYWRkKGZ1bmN0aW9uTm9kZSk7XG5cbiAgZm9yIChjb25zdCBjYWxsZWVOb2RlIG9mIGNhbGxHcmFwaC5jYWxsQ291bnRCeUNhbGxlZU5vZGVCeUNhbGxlck5vZGUuZ2V0KGZ1bmN0aW9uTm9kZSk/LmtleXMoKSA/PyBbXSkge1xuICAgIGNvbGxlY3RSZWFjaGFibGVGdW5jdGlvbk5vZGVzKGNhbGxlZU5vZGUsIGNhbGxHcmFwaCwgcmVhY2hhYmxlTm9kZXMpO1xuICB9XG59XG5cbi8qKlxuICogRmluZHMgdGhlIGZ1bmN0aW9uIGEgbm9kZSdzIHdhaXRpbmcgaXMgY2hhcmdlZCB0bywgd2Fsa2luZyBvdXR3YXJkcy5cbiAqXG4gKiBUaGUgd2FsayBkb2VzIG5vdCBzdG9wIGF0IHRoZSBmaXJzdCBlbmNsb3NpbmcgZnVuY3Rpb246IGEgd2FpdCBpbnNpZGUgYSBoZWxwZXIgZGVjbGFyZWQgd2l0aGluIHRoZVxuICogY2FsbGJhY2sgc3RpbGwgcnVucyBpbnNpZGUgdGhlIGNhbGxiYWNrLCBzbyBpdCBrZWVwcyBnb2luZyB1bnRpbCBpdCByZWFjaGVzIGEgZnVuY3Rpb24gdGhhdCBJUyBvbmUgb2ZcbiAqIHRoZSBoZWxwZXIncyBpbi1PYnNpZGlhbiBjbG9zdXJlcy4gV2hhdCBpdCBSRU1FTUJFUlMgb24gdGhlIHdheSBpcyB0aGUgaW5uZXJtb3N0IGZ1bmN0aW9uIGl0IHBhc3NlZCwgc29cbiAqIGEgaGVscGVyJ3Mgd2FpdGluZyBpcyBhY2N1bXVsYXRlZCBhZ2FpbnN0IHRoZSBoZWxwZXIgYW5kIGNoYXJnZWQgdG8gdGhlIGNsb3N1cmUgb25jZSBwZXIgY2FsbCBzaXRlLlxuICpcbiAqIEBwYXJhbSBub2RlIC0gVGhlIG5vZGUgdG8gc3RhcnQgZnJvbS5cbiAqIEByZXR1cm5zIFRoZSBjaGFyZ2UgdGFyZ2V0LCBvciBgbnVsbGAgd2hlbiB0aGUgbm9kZSBkb2VzIG5vdCBydW4gaW5zaWRlIGFuIGluLU9ic2lkaWFuIGNsb3N1cmUuXG4gKi9cbmZ1bmN0aW9uIGZpbmRDaGFyZ2VUYXJnZXQobm9kZTogVFNFU1RyZWUuTm9kZSk6IENoYXJnZVRhcmdldCB8IG51bGwge1xuICBsZXQgaW5uZXJtb3N0RnVuY3Rpb25Ob2RlOiBIZWxwZXJGdW5jdGlvbiB8IHVuZGVmaW5lZDtcbiAgbGV0IGN1cnJlbnROb2RlOiBUU0VTVHJlZS5Ob2RlIHwgdW5kZWZpbmVkID0gbm9kZS5wYXJlbnQ7XG5cbiAgd2hpbGUgKGN1cnJlbnROb2RlKSB7XG4gICAgY29uc3QgY2xvc3VyZSA9IHJlYWRFdmFsQ2xvc3VyZShjdXJyZW50Tm9kZSk7XG4gICAgaWYgKGNsb3N1cmUpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNsb3N1cmUsXG4gICAgICAgIGZ1bmN0aW9uTm9kZTogaW5uZXJtb3N0RnVuY3Rpb25Ob2RlID8/IGNsb3N1cmUuY2xvc3VyZU5vZGVcbiAgICAgIH07XG4gICAgfVxuXG4gICAgaWYgKCFpbm5lcm1vc3RGdW5jdGlvbk5vZGUgJiYgaXNGdW5jdGlvbk5vZGUoY3VycmVudE5vZGUpKSB7XG4gICAgICBpbm5lcm1vc3RGdW5jdGlvbk5vZGUgPSBjdXJyZW50Tm9kZTtcbiAgICB9XG5cbiAgICBjdXJyZW50Tm9kZSA9IGN1cnJlbnROb2RlLnBhcmVudDtcbiAgfVxuXG4gIHJldHVybiBudWxsO1xufVxuXG4vKipcbiAqIEZpbmRzIGEgdmFyaWFibGUgYnkgbmFtZSwgd2Fsa2luZyBvdXR3YXJkcyBmcm9tIHRoZSBnaXZlbiBzY29wZS5cbiAqXG4gKiBAcGFyYW0gc2NvcGUgLSBUaGUgc2NvcGUgdG8gc3RhcnQgZnJvbS5cbiAqIEBwYXJhbSBuYW1lIC0gVGhlIHZhcmlhYmxlJ3MgbmFtZS5cbiAqIEByZXR1cm5zIFRoZSB2YXJpYWJsZSwgb3IgYG51bGxgIHdoZW4gbm90aGluZyBpbiBzY29wZSBkZWNsYXJlcyB0aGF0IG5hbWUuXG4gKi9cbmZ1bmN0aW9uIGZpbmRWYXJpYWJsZShzY29wZTogU2NvcGUuU2NvcGUsIG5hbWU6IHN0cmluZyk6IG51bGwgfCBTY29wZS5WYXJpYWJsZSB7XG4gIGxldCBjdXJyZW50U2NvcGU6IG51bGwgfCBTY29wZS5TY29wZSA9IHNjb3BlO1xuXG4gIHdoaWxlIChjdXJyZW50U2NvcGUpIHtcbiAgICBjb25zdCB2YXJpYWJsZSA9IGN1cnJlbnRTY29wZS52YXJpYWJsZXMuZmluZCgoY2FuZGlkYXRlKSA9PiBjYW5kaWRhdGUubmFtZSA9PT0gbmFtZSk7XG4gICAgaWYgKHZhcmlhYmxlKSB7XG4gICAgICByZXR1cm4gdmFyaWFibGU7XG4gICAgfVxuICAgIGN1cnJlbnRTY29wZSA9IGN1cnJlbnRTY29wZS51cHBlcjtcbiAgfVxuXG4gIHJldHVybiBudWxsO1xufVxuXG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIGEgbm9kZSBpcyBhbiBhc3NpZ25tZW50IGV4cHJlc3Npb24uXG4gKlxuICogQHBhcmFtIG5vZGUgLSBUaGUgbm9kZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIGB0cnVlYCBpZiB0aGUgbm9kZSBpcyBhbiBgQXNzaWdubWVudEV4cHJlc3Npb25gLlxuICovXG5mdW5jdGlvbiBpc0Fzc2lnbm1lbnRFeHByZXNzaW9uKG5vZGU6IFRTRVNUcmVlLk5vZGUpOiBub2RlIGlzIFRTRVNUcmVlLkFzc2lnbm1lbnRFeHByZXNzaW9uIHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnNhZmUtZW51bS1jb21wYXJpc29uIC0tIEFTVCBub2RlIHR5cGUgc3RyaW5nIGxpdGVyYWxzIG1hdGNoIHRoZSBUU0VTVHJlZSBlbnVtIHZhbHVlcy5cbiAgcmV0dXJuIG5vZGUudHlwZSA9PT0gJ0Fzc2lnbm1lbnRFeHByZXNzaW9uJztcbn1cblxuLyoqXG4gKiBDaGVja3Mgd2hldGhlciBhIG5vZGUgaXMgYSBiaW5hcnkgZXhwcmVzc2lvbi5cbiAqXG4gKiBAcGFyYW0gbm9kZSAtIFRoZSBub2RlIHRvIGNoZWNrLlxuICogQHJldHVybnMgYHRydWVgIGlmIHRoZSBub2RlIGlzIGEgYEJpbmFyeUV4cHJlc3Npb25gLlxuICovXG5mdW5jdGlvbiBpc0JpbmFyeUV4cHJlc3Npb24obm9kZTogVFNFU1RyZWUuTm9kZSk6IG5vZGUgaXMgVFNFU1RyZWUuQmluYXJ5RXhwcmVzc2lvbiB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5zYWZlLWVudW0tY29tcGFyaXNvbiAtLSBBU1Qgbm9kZSB0eXBlIHN0cmluZyBsaXRlcmFscyBtYXRjaCB0aGUgVFNFU1RyZWUgZW51bSB2YWx1ZXMuXG4gIHJldHVybiBub2RlLnR5cGUgPT09ICdCaW5hcnlFeHByZXNzaW9uJztcbn1cblxuLyoqXG4gKiBDaGVja3Mgd2hldGhlciBhIG5vZGUgaXMgYSBjYWxsIGV4cHJlc3Npb24uXG4gKlxuICogQHBhcmFtIG5vZGUgLSBUaGUgbm9kZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIGB0cnVlYCBpZiB0aGUgbm9kZSBpcyBhIGBDYWxsRXhwcmVzc2lvbmAuXG4gKi9cbmZ1bmN0aW9uIGlzQ2FsbEV4cHJlc3Npb24obm9kZTogVFNFU1RyZWUuTm9kZSk6IG5vZGUgaXMgVFNFU1RyZWUuQ2FsbEV4cHJlc3Npb24ge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVuc2FmZS1lbnVtLWNvbXBhcmlzb24gLS0gQVNUIG5vZGUgdHlwZSBzdHJpbmcgbGl0ZXJhbHMgbWF0Y2ggdGhlIFRTRVNUcmVlIGVudW0gdmFsdWVzLlxuICByZXR1cm4gbm9kZS50eXBlID09PSAnQ2FsbEV4cHJlc3Npb24nO1xufVxuXG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIGEgbm9kZSBpcyBhIGZ1bmN0aW9uIHdyaXR0ZW4gYXMgYW4gb2JqZWN0IHByb3BlcnR5J3MgdmFsdWUuXG4gKlxuICogQHBhcmFtIG5vZGUgLSBUaGUgbm9kZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIGB0cnVlYCBpZiB0aGUgbm9kZSBpcyBhIGBGdW5jdGlvbkV4cHJlc3Npb25gIG9yIGFuIGBBcnJvd0Z1bmN0aW9uRXhwcmVzc2lvbmAuXG4gKi9cbmZ1bmN0aW9uIGlzQ2xvc3VyZUZ1bmN0aW9uKG5vZGU6IFRTRVNUcmVlLk5vZGUpOiBub2RlIGlzIENsb3N1cmVGdW5jdGlvbiB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5zYWZlLWVudW0tY29tcGFyaXNvbiAtLSBBU1Qgbm9kZSB0eXBlIHN0cmluZyBsaXRlcmFscyBtYXRjaCB0aGUgVFNFU1RyZWUgZW51bSB2YWx1ZXMuXG4gIHJldHVybiBub2RlLnR5cGUgPT09ICdGdW5jdGlvbkV4cHJlc3Npb24nIHx8IG5vZGUudHlwZSA9PT0gJ0Fycm93RnVuY3Rpb25FeHByZXNzaW9uJztcbn1cblxuLyoqXG4gKiBDaGVja3Mgd2hldGhlciBhIGZ1bmN0aW9uIGlzIGRlY2xhcmVkIHNvbWV3aGVyZSBpbnNpZGUgYW4gaW4tT2JzaWRpYW4gY2xvc3VyZS5cbiAqXG4gKiBBIGhlbHBlciBkZWNsYXJlZCBPVVRTSURFIHRoZSBjbG9zdXJlIGFuc3dlcnMgYGZhbHNlYCwgd2hpY2ggaXMgd2hhdCBrZWVwcyB0aGlzIHJ1bGUncyBhbmFseXNpcyBpbnNpZGVcbiAqIG9uZSBjbG9zdXJlIHJhdGhlciB0aGFuIGZvbGxvd2luZyBjYWxscyBhY3Jvc3MgYm91bmRhcmllcyBpdCBkZWxpYmVyYXRlbHkgZGVjbGluZXMgdG8gcmVhZC5cbiAqXG4gKiBAcGFyYW0gZnVuY3Rpb25Ob2RlIC0gVGhlIGZ1bmN0aW9uIHRvIGNoZWNrLlxuICogQHBhcmFtIGNsb3N1cmUgLSBUaGUgY2xvc3VyZSB0byBjaGVjayBhZ2FpbnN0LlxuICogQHJldHVybnMgYHRydWVgIHdoZW4gdGhlIGZ1bmN0aW9uIGlzIGRlY2xhcmVkIGxleGljYWxseSBpbnNpZGUgdGhlIGNsb3N1cmUuXG4gKi9cbmZ1bmN0aW9uIGlzRGVjbGFyZWRJbnNpZGVDbG9zdXJlKGZ1bmN0aW9uTm9kZTogSGVscGVyRnVuY3Rpb24sIGNsb3N1cmU6IEV2YWxDbG9zdXJlKTogYm9vbGVhbiB7XG4gIGxldCBjdXJyZW50Tm9kZTogVFNFU1RyZWUuTm9kZSB8IHVuZGVmaW5lZCA9IGZ1bmN0aW9uTm9kZS5wYXJlbnQ7XG5cbiAgd2hpbGUgKGN1cnJlbnROb2RlKSB7XG4gICAgaWYgKGN1cnJlbnROb2RlID09PSBjbG9zdXJlLmNsb3N1cmVOb2RlKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgY3VycmVudE5vZGUgPSBjdXJyZW50Tm9kZS5wYXJlbnQ7XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgYSBub2RlIGlzIGEgY291bnRpbmcgYGZvcmAgc3RhdGVtZW50LlxuICpcbiAqIEBwYXJhbSBub2RlIC0gVGhlIG5vZGUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyBgdHJ1ZWAgaWYgdGhlIG5vZGUgaXMgYSBgRm9yU3RhdGVtZW50YC5cbiAqL1xuZnVuY3Rpb24gaXNGb3JTdGF0ZW1lbnQobm9kZTogVFNFU1RyZWUuTm9kZSk6IG5vZGUgaXMgVFNFU1RyZWUuRm9yU3RhdGVtZW50IHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnNhZmUtZW51bS1jb21wYXJpc29uIC0tIEFTVCBub2RlIHR5cGUgc3RyaW5nIGxpdGVyYWxzIG1hdGNoIHRoZSBUU0VTVHJlZSBlbnVtIHZhbHVlcy5cbiAgcmV0dXJuIG5vZGUudHlwZSA9PT0gJ0ZvclN0YXRlbWVudCc7XG59XG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgYSBub2RlIGlzIGEgZnVuY3Rpb24gd2FpdGluZyBjYW4gYmUgY2hhcmdlZCB0by5cbiAqXG4gKiBBIGBmdW5jdGlvbmAgZGVjbGFyYXRpb24gY291bnRzIGFzIHdlbGwgYXMgdGhlIHR3byBleHByZXNzaW9uIGZvcm1zLCBiZWNhdXNlIHRoYXQgaXMgaG93IHRoZXNlIHN1aXRlc1xuICogd3JpdGUgYSBsb2NhbCByZXRyeSBoZWxwZXIuXG4gKlxuICogQHBhcmFtIG5vZGUgLSBUaGUgbm9kZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIGB0cnVlYCBpZiB0aGUgbm9kZSBpcyBhIGBGdW5jdGlvbkRlY2xhcmF0aW9uYCwgYSBgRnVuY3Rpb25FeHByZXNzaW9uYCBvciBhbiBgQXJyb3dGdW5jdGlvbkV4cHJlc3Npb25gLlxuICovXG5mdW5jdGlvbiBpc0Z1bmN0aW9uTm9kZShub2RlOiBUU0VTVHJlZS5Ob2RlKTogbm9kZSBpcyBIZWxwZXJGdW5jdGlvbiB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5zYWZlLWVudW0tY29tcGFyaXNvbiAtLSBBU1Qgbm9kZSB0eXBlIHN0cmluZyBsaXRlcmFscyBtYXRjaCB0aGUgVFNFU1RyZWUgZW51bSB2YWx1ZXMuXG4gIHJldHVybiBpc0Nsb3N1cmVGdW5jdGlvbihub2RlKSB8fCBub2RlLnR5cGUgPT09ICdGdW5jdGlvbkRlY2xhcmF0aW9uJztcbn1cblxuLyoqXG4gKiBDaGVja3Mgd2hldGhlciBhIG5vZGUgaXMgYW4gaWRlbnRpZmllci5cbiAqXG4gKiBAcGFyYW0gbm9kZSAtIFRoZSBub2RlIHRvIGNoZWNrLlxuICogQHJldHVybnMgYHRydWVgIGlmIHRoZSBub2RlIGlzIGFuIGBJZGVudGlmaWVyYC5cbiAqL1xuZnVuY3Rpb24gaXNJZGVudGlmaWVyKG5vZGU6IFRTRVNUcmVlLk5vZGUpOiBub2RlIGlzIFRTRVNUcmVlLklkZW50aWZpZXIge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVuc2FmZS1lbnVtLWNvbXBhcmlzb24gLS0gQVNUIG5vZGUgdHlwZSBzdHJpbmcgbGl0ZXJhbHMgbWF0Y2ggdGhlIFRTRVNUcmVlIGVudW0gdmFsdWVzLlxuICByZXR1cm4gbm9kZS50eXBlID09PSAnSWRlbnRpZmllcic7XG59XG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgYSBub2RlIGlzIGFuIGAmJmAgY2hhaW4sIHdob3NlIGNvbmp1bmN0cyBhIGNlaWxpbmcgbWF5IGJlIGRlY2xhcmVkIGluIG9uZSBvZi5cbiAqXG4gKiBAcGFyYW0gbm9kZSAtIFRoZSBub2RlIHRvIGNoZWNrLlxuICogQHJldHVybnMgYHRydWVgIGlmIHRoZSBub2RlIGlzIGEgYExvZ2ljYWxFeHByZXNzaW9uYCB3aXRoIHRoZSBgJiZgIG9wZXJhdG9yLlxuICovXG5mdW5jdGlvbiBpc0xvZ2ljYWxBbmRFeHByZXNzaW9uKG5vZGU6IFRTRVNUcmVlLk5vZGUpOiBub2RlIGlzIFRTRVNUcmVlLkxvZ2ljYWxFeHByZXNzaW9uIHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnNhZmUtZW51bS1jb21wYXJpc29uIC0tIEFTVCBub2RlIHR5cGUgc3RyaW5nIGxpdGVyYWxzIG1hdGNoIHRoZSBUU0VTVHJlZSBlbnVtIHZhbHVlcy5cbiAgcmV0dXJuIG5vZGUudHlwZSA9PT0gJ0xvZ2ljYWxFeHByZXNzaW9uJyAmJiBub2RlLm9wZXJhdG9yID09PSAnJiYnO1xufVxuXG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIGEgbm9kZSBpcyBhIGxvb3Agd2hvc2Ugb3duIHRlc3QgY2FuIGRlY2xhcmUgYSBjZWlsaW5nLlxuICpcbiAqIEBwYXJhbSBub2RlIC0gVGhlIG5vZGUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyBgdHJ1ZWAgaWYgdGhlIG5vZGUgaXMgYSBgV2hpbGVTdGF0ZW1lbnRgLCBhIGBEb1doaWxlU3RhdGVtZW50YCBvciBhIGBGb3JTdGF0ZW1lbnRgLlxuICovXG5mdW5jdGlvbiBpc0xvb3BTdGF0ZW1lbnQobm9kZTogVFNFU1RyZWUuTm9kZSk6IG5vZGUgaXMgTG9vcFN0YXRlbWVudCB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5zYWZlLWVudW0tY29tcGFyaXNvbiAtLSBBU1Qgbm9kZSB0eXBlIHN0cmluZyBsaXRlcmFscyBtYXRjaCB0aGUgVFNFU1RyZWUgZW51bSB2YWx1ZXMuXG4gIHJldHVybiBub2RlLnR5cGUgPT09ICdXaGlsZVN0YXRlbWVudCcgfHwgbm9kZS50eXBlID09PSAnRG9XaGlsZVN0YXRlbWVudCcgfHwgaXNGb3JTdGF0ZW1lbnQobm9kZSk7XG59XG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgYSBub2RlIGlzIGEgbWVtYmVyIGV4cHJlc3Npb24uXG4gKlxuICogQHBhcmFtIG5vZGUgLSBUaGUgbm9kZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIGB0cnVlYCBpZiB0aGUgbm9kZSBpcyBhIGBNZW1iZXJFeHByZXNzaW9uYC5cbiAqL1xuZnVuY3Rpb24gaXNNZW1iZXJFeHByZXNzaW9uKG5vZGU6IFRTRVNUcmVlLk5vZGUpOiBub2RlIGlzIFRTRVNUcmVlLk1lbWJlckV4cHJlc3Npb24ge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVuc2FmZS1lbnVtLWNvbXBhcmlzb24gLS0gQVNUIG5vZGUgdHlwZSBzdHJpbmcgbGl0ZXJhbHMgbWF0Y2ggdGhlIFRTRVNUcmVlIGVudW0gdmFsdWVzLlxuICByZXR1cm4gbm9kZS50eXBlID09PSAnTWVtYmVyRXhwcmVzc2lvbic7XG59XG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgYSBub2RlIGlzIGEgbnVtZXJpYyBsaXRlcmFsLlxuICpcbiAqIEBwYXJhbSBub2RlIC0gVGhlIG5vZGUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyBgdHJ1ZWAgaWYgdGhlIG5vZGUgaXMgYSBgTGl0ZXJhbGAgaG9sZGluZyBhIG51bWJlci5cbiAqL1xuZnVuY3Rpb24gaXNOdW1lcmljTGl0ZXJhbChub2RlOiBUU0VTVHJlZS5Ob2RlKTogbm9kZSBpcyBUU0VTVHJlZS5OdW1iZXJMaXRlcmFsIHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnNhZmUtZW51bS1jb21wYXJpc29uIC0tIEFTVCBub2RlIHR5cGUgc3RyaW5nIGxpdGVyYWxzIG1hdGNoIHRoZSBUU0VTVHJlZSBlbnVtIHZhbHVlcy5cbiAgcmV0dXJuIG5vZGUudHlwZSA9PT0gJ0xpdGVyYWwnICYmIHR5cGVvZiBub2RlLnZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuLyoqXG4gKiBDaGVja3Mgd2hldGhlciBhIG5vZGUgaXMgYW4gb2JqZWN0IGxpdGVyYWwuXG4gKlxuICogQHBhcmFtIG5vZGUgLSBUaGUgbm9kZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIGB0cnVlYCBpZiB0aGUgbm9kZSBpcyBhbiBgT2JqZWN0RXhwcmVzc2lvbmAuXG4gKi9cbmZ1bmN0aW9uIGlzT2JqZWN0RXhwcmVzc2lvbihub2RlOiBUU0VTVHJlZS5Ob2RlKTogbm9kZSBpcyBUU0VTVHJlZS5PYmplY3RFeHByZXNzaW9uIHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnNhZmUtZW51bS1jb21wYXJpc29uIC0tIEFTVCBub2RlIHR5cGUgc3RyaW5nIGxpdGVyYWxzIG1hdGNoIHRoZSBUU0VTVHJlZSBlbnVtIHZhbHVlcy5cbiAgcmV0dXJuIG5vZGUudHlwZSA9PT0gJ09iamVjdEV4cHJlc3Npb24nO1xufVxuXG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIGEgbm9kZSBpcyBhbiBvYmplY3QgZGVzdHJ1Y3R1cmluZyBwYXR0ZXJuLlxuICpcbiAqIEBwYXJhbSBub2RlIC0gVGhlIG5vZGUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyBgdHJ1ZWAgaWYgdGhlIG5vZGUgaXMgYW4gYE9iamVjdFBhdHRlcm5gLlxuICovXG5mdW5jdGlvbiBpc09iamVjdFBhdHRlcm4obm9kZTogVFNFU1RyZWUuTm9kZSk6IG5vZGUgaXMgVFNFU1RyZWUuT2JqZWN0UGF0dGVybiB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5zYWZlLWVudW0tY29tcGFyaXNvbiAtLSBBU1Qgbm9kZSB0eXBlIHN0cmluZyBsaXRlcmFscyBtYXRjaCB0aGUgVFNFU1RyZWUgZW51bSB2YWx1ZXMuXG4gIHJldHVybiBub2RlLnR5cGUgPT09ICdPYmplY3RQYXR0ZXJuJztcbn1cblxuLyoqXG4gKiBDaGVja3Mgd2hldGhlciBhIG5vZGUgaXMgYW4gb2JqZWN0LWxpdGVyYWwgb3Igb2JqZWN0LXBhdHRlcm4gcHJvcGVydHkuXG4gKlxuICogQHBhcmFtIG5vZGUgLSBUaGUgbm9kZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIGB0cnVlYCBpZiB0aGUgbm9kZSBpcyBhIGBQcm9wZXJ0eWAuXG4gKi9cbmZ1bmN0aW9uIGlzUHJvcGVydHkobm9kZTogVFNFU1RyZWUuTm9kZSk6IG5vZGUgaXMgVFNFU1RyZWUuUHJvcGVydHkge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVuc2FmZS1lbnVtLWNvbXBhcmlzb24gLS0gQVNUIG5vZGUgdHlwZSBzdHJpbmcgbGl0ZXJhbHMgbWF0Y2ggdGhlIFRTRVNUcmVlIGVudW0gdmFsdWVzLlxuICByZXR1cm4gbm9kZS50eXBlID09PSAnUHJvcGVydHknO1xufVxuXG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIGEgbm9kZSBpcyBhbiB1cGRhdGUgZXhwcmVzc2lvbi5cbiAqXG4gKiBAcGFyYW0gbm9kZSAtIFRoZSBub2RlIHRvIGNoZWNrLlxuICogQHJldHVybnMgYHRydWVgIGlmIHRoZSBub2RlIGlzIGFuIGBVcGRhdGVFeHByZXNzaW9uYC5cbiAqL1xuZnVuY3Rpb24gaXNVcGRhdGVFeHByZXNzaW9uKG5vZGU6IFRTRVNUcmVlLk5vZGUpOiBub2RlIGlzIFRTRVNUcmVlLlVwZGF0ZUV4cHJlc3Npb24ge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVuc2FmZS1lbnVtLWNvbXBhcmlzb24gLS0gQVNUIG5vZGUgdHlwZSBzdHJpbmcgbGl0ZXJhbHMgbWF0Y2ggdGhlIFRTRVNUcmVlIGVudW0gdmFsdWVzLlxuICByZXR1cm4gbm9kZS50eXBlID09PSAnVXBkYXRlRXhwcmVzc2lvbic7XG59XG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgYSBub2RlIGlzIGEgdmFyaWFibGUgZGVjbGFyYXRpb24uXG4gKlxuICogQHBhcmFtIG5vZGUgLSBUaGUgbm9kZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIGB0cnVlYCBpZiB0aGUgbm9kZSBpcyBhIGBWYXJpYWJsZURlY2xhcmF0aW9uYC5cbiAqL1xuZnVuY3Rpb24gaXNWYXJpYWJsZURlY2xhcmF0aW9uKG5vZGU6IFRTRVNUcmVlLk5vZGUpOiBub2RlIGlzIFRTRVNUcmVlLlZhcmlhYmxlRGVjbGFyYXRpb24ge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVuc2FmZS1lbnVtLWNvbXBhcmlzb24gLS0gQVNUIG5vZGUgdHlwZSBzdHJpbmcgbGl0ZXJhbHMgbWF0Y2ggdGhlIFRTRVNUcmVlIGVudW0gdmFsdWVzLlxuICByZXR1cm4gbm9kZS50eXBlID09PSAnVmFyaWFibGVEZWNsYXJhdGlvbic7XG59XG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgYSBub2RlIGlzIGEgdmFyaWFibGUgZGVjbGFyYXRvci5cbiAqXG4gKiBAcGFyYW0gbm9kZSAtIFRoZSBub2RlIHRvIGNoZWNrLlxuICogQHJldHVybnMgYHRydWVgIGlmIHRoZSBub2RlIGlzIGEgYFZhcmlhYmxlRGVjbGFyYXRvcmAuXG4gKi9cbmZ1bmN0aW9uIGlzVmFyaWFibGVEZWNsYXJhdG9yKG5vZGU6IFRTRVNUcmVlLk5vZGUpOiBub2RlIGlzIFRTRVNUcmVlLlZhcmlhYmxlRGVjbGFyYXRvciB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5zYWZlLWVudW0tY29tcGFyaXNvbiAtLSBBU1Qgbm9kZSB0eXBlIHN0cmluZyBsaXRlcmFscyBtYXRjaCB0aGUgVFNFU1RyZWUgZW51bSB2YWx1ZXMuXG4gIHJldHVybiBub2RlLnR5cGUgPT09ICdWYXJpYWJsZURlY2xhcmF0b3InO1xufVxuXG4vKipcbiAqIFJlYWRzIHRoZSBleHByZXNzaW9uIGFuIGlkZW50aWZpZXIgaXMgYm91bmQgdG8uXG4gKlxuICogQSBgY29uc3RgIGFuc3dlcnMgd2l0aCBpdHMgaW5pdGlhbGl6ZXI7IGEgZGVzdHJ1Y3R1cmVkIHBhcmFtZXRlciBvZiBUSElTIGNsb3N1cmUgYW5zd2VycyB3aXRoIHdoYXQgdGhlXG4gKiBjYWxsJ3Mgb3duIGBpbnB1dGAgc3VwcGxpZXMgZm9yIHRoZSBrZXkgaXQgd2FzIGRlc3RydWN0dXJlZCBieSwgd2hpY2ggaXMgaG93IGEgYnVkZ2V0IHdyaXR0ZW4gb25jZSBhdFxuICogdGhlIGNhbGwgc2l0ZSByZWFjaGVzIGEgY2xvc3VyZSB0aGF0IGNhbiBjbG9zZSBvdmVyIG5vdGhpbmcuXG4gKlxuICogQHBhcmFtIG5vZGUgLSBUaGUgaWRlbnRpZmllciB0byByZXNvbHZlLlxuICogQHBhcmFtIGNsb3N1cmUgLSBUaGUgY2xvc3VyZSB0aGUgaWRlbnRpZmllciB3YXMgd3JpdHRlbiBpbnNpZGUuXG4gKiBAcGFyYW0gY29udGV4dCAtIFRoZSBydWxlIGNvbnRleHQsIHVzZWQgdG8gcmVzb2x2ZSB0aGUgaWRlbnRpZmllciB0aHJvdWdoIHNjb3BlLlxuICogQHJldHVybnMgVGhlIGV4cHJlc3Npb24gaXQgaXMgYm91bmQgdG8sIG9yIGBudWxsYCB3aGVuIG5vdGhpbmcgc3RhdGljYWxseSBiaW5kcyBpdC5cbiAqL1xuZnVuY3Rpb24gcmVhZEJvdW5kRXhwcmVzc2lvbihub2RlOiBUU0VTVHJlZS5JZGVudGlmaWVyLCBjbG9zdXJlOiBFdmFsQ2xvc3VyZSwgY29udGV4dDogUnVsZS5SdWxlQ29udGV4dCk6IG51bGwgfCBUU0VTVHJlZS5Ob2RlIHtcbiAgY29uc3QgdmFyaWFibGUgPSBmaW5kVmFyaWFibGUoY29udGV4dC5zb3VyY2VDb2RlLmdldFNjb3BlKG5vZGUpLCBub2RlLm5hbWUpO1xuICBpZiAoIXZhcmlhYmxlKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBmb3IgKGNvbnN0IGRlZmluaXRpb24gb2YgdmFyaWFibGUuZGVmcykge1xuICAgIGNvbnN0IGRlZmluaXRpb25Ob2RlID0gdG9UU0VTVHJlZU5vZGUoZGVmaW5pdGlvbi5ub2RlKTtcblxuICAgIGlmIChpc1ZhcmlhYmxlRGVjbGFyYXRvcihkZWZpbml0aW9uTm9kZSkgJiYgZGVmaW5pdGlvbk5vZGUuaW5pdCkge1xuICAgICAgcmV0dXJuIGRlZmluaXRpb25Ob2RlLmluaXQ7XG4gICAgfVxuXG4gICAgaWYgKGRlZmluaXRpb25Ob2RlID09PSBjbG9zdXJlLmNsb3N1cmVOb2RlKSB7XG4gICAgICBjb25zdCBpbnB1dEtleSA9IHJlYWRQYXJhbWV0ZXJJbnB1dEtleShjbG9zdXJlLmNsb3N1cmVOb2RlLCBub2RlLm5hbWUpO1xuICAgICAgcmV0dXJuIGlucHV0S2V5ID09PSBudWxsID8gbnVsbCA6IHJlYWRJbnB1dFByb3BlcnR5VmFsdWUoY2xvc3VyZS5wYXJhbXNOb2RlLCBpbnB1dEtleSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG51bGw7XG59XG5cbi8qKlxuICogUmVhZHMgdGhlIGhlbHBlciBhIGNhbGwgbmFtZXMsIHdoZW4gdGhhdCBoZWxwZXIgaXMgZGVjbGFyZWQgaW5zaWRlIHRoZSBnaXZlbiBjbG9zdXJlLlxuICpcbiAqIEJvdGggZm9ybXMgdGhlc2Ugc3VpdGVzIHdyaXRlIGFyZSByZXNvbHZlZCB0aHJvdWdoIHRoZSBzYW1lIHNjb3BlIHdhbGsgYSBidWRnZXQgdXNlczogYSBgZnVuY3Rpb25gXG4gKiBkZWNsYXJhdGlvbiwgYW5kIGEgYGNvbnN0YCBib3VuZCB0byBhbiBhcnJvdyBvciBhIGZ1bmN0aW9uIGV4cHJlc3Npb24uXG4gKlxuICogQHBhcmFtIGNhbGxOb2RlIC0gVGhlIGNhbGwgZXhwcmVzc2lvbi5cbiAqIEBwYXJhbSBjbG9zdXJlIC0gVGhlIGluLU9ic2lkaWFuIGNsb3N1cmUgdGhlIGNhbGwgcnVucyBpbnNpZGUuXG4gKiBAcGFyYW0gY29udGV4dCAtIFRoZSBydWxlIGNvbnRleHQsIHVzZWQgdG8gcmVzb2x2ZSB0aGUgY2FsbGVlIHRocm91Z2ggc2NvcGUuXG4gKiBAcmV0dXJucyBUaGUgaGVscGVyJ3MgZnVuY3Rpb24gbm9kZSwgb3IgYG51bGxgIHdoZW4gdGhlIGNhbGxlZSBpcyBub3QgYSBoZWxwZXIgb2YgdGhpcyBjbG9zdXJlLlxuICovXG5mdW5jdGlvbiByZWFkQ2FsbGVkSGVscGVyTm9kZShjYWxsTm9kZTogVFNFU1RyZWUuQ2FsbEV4cHJlc3Npb24sIGNsb3N1cmU6IEV2YWxDbG9zdXJlLCBjb250ZXh0OiBSdWxlLlJ1bGVDb250ZXh0KTogSGVscGVyRnVuY3Rpb24gfCBudWxsIHtcbiAgY29uc3QgY2FsbGVlTm9kZSA9IGNhbGxOb2RlLmNhbGxlZSBhcyBUU0VTVHJlZS5Ob2RlO1xuICBpZiAoIWlzSWRlbnRpZmllcihjYWxsZWVOb2RlKSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgdmFyaWFibGUgPSBmaW5kVmFyaWFibGUoY29udGV4dC5zb3VyY2VDb2RlLmdldFNjb3BlKGNhbGxlZU5vZGUpLCBjYWxsZWVOb2RlLm5hbWUpO1xuICBpZiAoIXZhcmlhYmxlKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBmb3IgKGNvbnN0IGRlZmluaXRpb24gb2YgdmFyaWFibGUuZGVmcykge1xuICAgIGNvbnN0IGZ1bmN0aW9uTm9kZSA9IHJlYWREZWZpbml0aW9uRnVuY3Rpb25Ob2RlKHRvVFNFU1RyZWVOb2RlKGRlZmluaXRpb24ubm9kZSkpO1xuICAgIGlmIChmdW5jdGlvbk5vZGUgJiYgaXNEZWNsYXJlZEluc2lkZUNsb3N1cmUoZnVuY3Rpb25Ob2RlLCBjbG9zdXJlKSkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uTm9kZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gbnVsbDtcbn1cblxuLyoqXG4gKiBTdW1zIGEgZnVuY3Rpb24ncyBvd24gd2FpdGluZyBwbHVzIHRoYXQgb2YgZXZlcnkgaGVscGVyIGl0IGNhbGxzLCBtdWx0aXBsaWVkIGJ5IHRoZSBjYWxscyB0aGF0IHJlYWNoIGl0LlxuICpcbiAqIEEgZnVuY3Rpb24gYWxyZWFkeSBvbiB0aGUgc3RhY2sgY29udHJpYnV0ZXMgTk9USElORywgd2hpY2ggaXMgd2hhdCB0ZXJtaW5hdGVzIGRpcmVjdCBhbmQgbXV0dWFsXG4gKiByZWN1cnNpb24gXHUyMDE0IHRoZSBzYW1lIHNpbGVuY2UgYW4gdW5ib3VuZGVkIGxvb3AgZ2V0cywgcmF0aGVyIHRoYW4gYSBndWVzcyBhdCBob3cgb2Z0ZW4gaXQgcmVwZWF0cy4gVGhlXG4gKiBzdGFjayBpcyB1bndvdW5kIG9uIHRoZSB3YXkgb3V0LCBzbyBhIGhlbHBlciByZWFjaGVkIGRvd24gdHdvIGRpZmZlcmVudCBwYXRocyBpcyBjb3VudGVkIG9uIGJvdGguXG4gKlxuICogQHBhcmFtIGZ1bmN0aW9uTm9kZSAtIFRoZSBmdW5jdGlvbiB0byB0b3RhbC5cbiAqIEBwYXJhbSBjYWxsR3JhcGggLSBUaGUgZmlsZSdzIGFjY3VtdWxhdGVkIGNoYXJnZXMuXG4gKiBAcGFyYW0gdmlzaXRlZE5vZGVzIC0gVGhlIGZ1bmN0aW9ucyBjdXJyZW50bHkgYmVpbmcgdG90YWxsZWQsIHdoaWNoIGlzIHRoZSByZWN1cnNpb24gc3RhY2suXG4gKiBAcmV0dXJucyBUaGUgd2FpdGluZywgaW4gbWlsbGlzZWNvbmRzLlxuICovXG5mdW5jdGlvbiByZWFkQ2FsbEdyYXBoV2FpdEluTWlsbGlzZWNvbmRzKGZ1bmN0aW9uTm9kZTogSGVscGVyRnVuY3Rpb24sIGNhbGxHcmFwaDogQ2FsbEdyYXBoLCB2aXNpdGVkTm9kZXM6IFNldDxIZWxwZXJGdW5jdGlvbj4pOiBudW1iZXIge1xuICBpZiAodmlzaXRlZE5vZGVzLmhhcyhmdW5jdGlvbk5vZGUpKSB7XG4gICAgcmV0dXJuIDA7XG4gIH1cblxuICB2aXNpdGVkTm9kZXMuYWRkKGZ1bmN0aW9uTm9kZSk7XG5cbiAgbGV0IHRvdGFsSW5NaWxsaXNlY29uZHMgPSBjYWxsR3JhcGgud2FpdEluTWlsbGlzZWNvbmRzQnlGdW5jdGlvbk5vZGUuZ2V0KGZ1bmN0aW9uTm9kZSkgPz8gMDtcbiAgZm9yIChjb25zdCBbY2FsbGVlTm9kZSwgY2FsbENvdW50XSBvZiBjYWxsR3JhcGguY2FsbENvdW50QnlDYWxsZWVOb2RlQnlDYWxsZXJOb2RlLmdldChmdW5jdGlvbk5vZGUpID8/IFtdKSB7XG4gICAgdG90YWxJbk1pbGxpc2Vjb25kcyArPSBjYWxsQ291bnQgKiByZWFkQ2FsbEdyYXBoV2FpdEluTWlsbGlzZWNvbmRzKGNhbGxlZU5vZGUsIGNhbGxHcmFwaCwgdmlzaXRlZE5vZGVzKTtcbiAgfVxuXG4gIHZpc2l0ZWROb2Rlcy5kZWxldGUoZnVuY3Rpb25Ob2RlKTtcbiAgcmV0dXJuIHRvdGFsSW5NaWxsaXNlY29uZHM7XG59XG5cbi8qKlxuICogUmVhZHMgdGhlIGNsb2NrIGEgbm9kZSByZWFkcyB0aGUgY3VycmVudCB0aW1lIGZyb20sIGlmIHRoYXQgaXMgd2hhdCBpdCBkb2VzLlxuICpcbiAqIEBwYXJhbSBub2RlIC0gVGhlIG5vZGUgdG8gaW5zcGVjdC5cbiAqIEByZXR1cm5zIFRoZSBjbG9jayBvYmplY3QncyBuYW1lIChgRGF0ZWAgb3IgYHBlcmZvcm1hbmNlYCksIG9yIGBudWxsYCB3aGVuIHRoZSBub2RlIGlzIG5vdCBhIGNsb2NrIHJlYWRpbmcuXG4gKi9cbmZ1bmN0aW9uIHJlYWRDbG9ja05hbWUobm9kZTogVFNFU1RyZWUuTm9kZSk6IG51bGwgfCBzdHJpbmcge1xuICBpZiAoIWlzQ2FsbEV4cHJlc3Npb24obm9kZSkgfHwgbm9kZS5hcmd1bWVudHMubGVuZ3RoID4gMCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgY2FsbGVlTm9kZSA9IG5vZGUuY2FsbGVlIGFzIFRTRVNUcmVlLk5vZGU7XG4gIGlmICghaXNNZW1iZXJFeHByZXNzaW9uKGNhbGxlZU5vZGUpIHx8IGNhbGxlZU5vZGUuY29tcHV0ZWQpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IG9iamVjdE5vZGUgPSBjYWxsZWVOb2RlLm9iamVjdCBhcyBUU0VTVHJlZS5Ob2RlO1xuICBjb25zdCBwcm9wZXJ0eU5vZGUgPSBjYWxsZWVOb2RlLnByb3BlcnR5IGFzIFRTRVNUcmVlLk5vZGU7XG4gIHJldHVybiAhaXNJZGVudGlmaWVyKG9iamVjdE5vZGUpIHx8ICFpc0lkZW50aWZpZXIocHJvcGVydHlOb2RlKSB8fCBwcm9wZXJ0eU5vZGUubmFtZSAhPT0gTk9XX01FVEhPRF9OQU1FIHx8ICFDTE9DS19PQkpFQ1RfTkFNRVMuaGFzKG9iamVjdE5vZGUubmFtZSkgPyBudWxsIDogb2JqZWN0Tm9kZS5uYW1lO1xufVxuXG4vKipcbiAqIFJlYWRzIHRoZSBjbG9zdXJlIHByb3BlcnR5IG5hbWVzIGEgY2FsbCdzIHBhcmFtZXRlciBvYmplY3QgbWF5IGNhcnJ5LCBieSB0aGUgaGVscGVyIGl0IGNhbGxzLlxuICpcbiAqIEBwYXJhbSBjYWxsTm9kZSAtIFRoZSBjYWxsIGV4cHJlc3Npb24uXG4gKiBAcmV0dXJucyBUaGUgaW4tT2JzaWRpYW4gY2xvc3VyZSBwcm9wZXJ0eSBuYW1lcywgb3IgYG51bGxgIHdoZW4gdGhlIGNhbGxlZSBpcyBub3Qgb25lIG9mIHRoZSBoZWxwZXJzLlxuICovXG5mdW5jdGlvbiByZWFkQ2xvc3VyZU5hbWVzKGNhbGxOb2RlOiBUU0VTVHJlZS5DYWxsRXhwcmVzc2lvbik6IG51bGwgfCByZWFkb25seSBzdHJpbmdbXSB7XG4gIHJldHVybiBpc0lkZW50aWZpZXIoY2FsbE5vZGUuY2FsbGVlKSA/IENMT1NVUkVfTkFNRVNfQllfQ0FMTEVFX05BTUUuZ2V0KGNhbGxOb2RlLmNhbGxlZS5uYW1lKSA/PyBudWxsIDogbnVsbDtcbn1cblxuLyoqXG4gKiBSZWFkcyBvbmUgY2xvc3VyZSdzIHdob2xlIGRlY2xhcmVkIHdhaXRpbmcuXG4gKlxuICogRXZlcnl0aGluZyB0aGUgY2xvc3VyZSBjYW4gUkVBQ0ggaXMgdG90YWxsZWQgdGhyb3VnaCB0aGUgY2FsbCBncmFwaCwgb25jZSBwZXIgY2FsbCBzaXRlLiBFdmVyeXRoaW5nIGl0XG4gKiBjYW5ub3QgXHUyMDE0IGEgaGVscGVyIG5vdGhpbmcgY2FsbHMsIG9yIG9uZSBjYWxsZWQgdGhyb3VnaCBhIHJlZmVyZW5jZSB0aGlzIHJ1bGUgY2Fubm90IGZvbGxvdyBcdTIwMTQga2VlcHMgdGhlXG4gKiBmbGF0IHNpbmdsZSBjaGFyZ2UgYSBsZXhpY2FsIGF0dHJpYnV0aW9uIGFsd2F5cyBnYXZlIGl0LCBzbyBubyBjbG9zdXJlIHJlcG9ydGVkIGJlZm9yZSB0aGlzIHJ1bGUgY291bnRlZFxuICogY2FsbCBzaXRlcyBmYWxscyBzaWxlbnQgbm93IHRoYXQgaXQgZG9lcy5cbiAqXG4gKiBAcGFyYW0gc3RhdGUgLSBUaGUgY2xvc3VyZSdzIGFjY3VtdWxhdGVkIGNoYXJnZXMuXG4gKiBAcGFyYW0gY2FsbEdyYXBoIC0gVGhlIGZpbGUncyBhY2N1bXVsYXRlZCBjaGFyZ2VzLlxuICogQHJldHVybnMgVGhlIHdhaXRpbmcgdGhlIGNsb3N1cmUgZGVjbGFyZXMsIGluIG1pbGxpc2Vjb25kcy5cbiAqL1xuZnVuY3Rpb24gcmVhZENsb3N1cmVXYWl0SW5NaWxsaXNlY29uZHMoc3RhdGU6IENsb3N1cmVTdGF0ZSwgY2FsbEdyYXBoOiBDYWxsR3JhcGgpOiBudW1iZXIge1xuICBjb25zdCByZWFjaGFibGVOb2RlcyA9IG5ldyBTZXQ8SGVscGVyRnVuY3Rpb24+KCk7XG4gIGNvbGxlY3RSZWFjaGFibGVGdW5jdGlvbk5vZGVzKHN0YXRlLmNsb3N1cmVOb2RlLCBjYWxsR3JhcGgsIHJlYWNoYWJsZU5vZGVzKTtcblxuICBsZXQgdG90YWxJbk1pbGxpc2Vjb25kcyA9IHJlYWRDYWxsR3JhcGhXYWl0SW5NaWxsaXNlY29uZHMoc3RhdGUuY2xvc3VyZU5vZGUsIGNhbGxHcmFwaCwgbmV3IFNldDxIZWxwZXJGdW5jdGlvbj4oKSk7XG5cbiAgZm9yIChjb25zdCBmdW5jdGlvbk5vZGUgb2Ygc3RhdGUuZnVuY3Rpb25Ob2Rlcykge1xuICAgIGNvbnN0IG93bldhaXRJbk1pbGxpc2Vjb25kcyA9IGNhbGxHcmFwaC53YWl0SW5NaWxsaXNlY29uZHNCeUZ1bmN0aW9uTm9kZS5nZXQoZnVuY3Rpb25Ob2RlKTtcbiAgICBpZiAob3duV2FpdEluTWlsbGlzZWNvbmRzID09PSB1bmRlZmluZWQgfHwgcmVhY2hhYmxlTm9kZXMuaGFzKGZ1bmN0aW9uTm9kZSkpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIHRvdGFsSW5NaWxsaXNlY29uZHMgKz0gb3duV2FpdEluTWlsbGlzZWNvbmRzO1xuICB9XG5cbiAgcmV0dXJuIHRvdGFsSW5NaWxsaXNlY29uZHM7XG59XG5cbi8qKlxuICogRmxhdHRlbnMgYW4gYCYmYCBjaGFpbiBpbnRvIHRoZSBjb25kaXRpb25zIGl0IGlzIGJ1aWx0IGZyb20uXG4gKlxuICogQSB0ZXN0IHRoYXQgaXMgbm90IGFuIGAmJmAgY2hhaW4gYW5zd2VycyB3aXRoIGl0c2VsZiwgc28gYSBjYWxsZXIgbmV2ZXIgc3BlY2lhbC1jYXNlcyB0aGUgc2ltcGxlIGZvcm0uXG4gKlxuICogQHBhcmFtIG5vZGUgLSBUaGUgZXhwcmVzc2lvbiB0byBmbGF0dGVuLlxuICogQHJldHVybnMgRXZlcnkgY29uanVuY3QsIGxlZnQgdG8gcmlnaHQuXG4gKi9cbmZ1bmN0aW9uIHJlYWRDb25qdW5jdHMobm9kZTogVFNFU1RyZWUuRXhwcmVzc2lvbik6IFRTRVNUcmVlLkV4cHJlc3Npb25bXSB7XG4gIHJldHVybiBpc0xvZ2ljYWxBbmRFeHByZXNzaW9uKG5vZGUpID8gWy4uLnJlYWRDb25qdW5jdHMobm9kZS5sZWZ0KSwgLi4ucmVhZENvbmp1bmN0cyhub2RlLnJpZ2h0KV0gOiBbbm9kZV07XG59XG5cbi8qKlxuICogUmVhZHMgdGhlIGNlaWxpbmcgYSBzaW5nbGUgYGNsb2NrLm5vdygpIDwgZGVhZGxpbmVgIGNvbXBhcmlzb24gZGVjbGFyZXMuXG4gKlxuICogQm90aCBvcGVyYW5kIG9yZGVycyBhcmUgcmVhZCwgc2luY2UgYGRlYWRsaW5lID4gY2xvY2subm93KClgIGlzIHRoZSBzYW1lIGd1YXJkIHdyaXR0ZW4gdGhlIG90aGVyIHdheVxuICogcm91bmQuIFRoZSBiaW5kaW5nIG11c3QgdGFrZSBpdHMgdGltZSBmcm9tIHRoZSBTQU1FIGNsb2NrIGFzIHRoZSBndWFyZDogYSBjb21wYXJpc29uIGFjcm9zcyB0aGUgdHdvXG4gKiBtZWFzdXJlcyBub3RoaW5nLCBhbmQgZGVjbGluaW5nIGl0IGlzIHRoZSBzaWxlbmNlIGFueSB1bnJlc29sdmFibGUgdmFsdWUgYWxyZWFkeSBnZXRzLlxuICpcbiAqIEBwYXJhbSBub2RlIC0gVGhlIGNvbmRpdGlvbiB0byBpbnNwZWN0LlxuICogQHBhcmFtIGNsb3N1cmUgLSBUaGUgaW4tT2JzaWRpYW4gY2xvc3VyZSB0aGUgbG9vcCBydW5zIGluc2lkZS5cbiAqIEBwYXJhbSBjb250ZXh0IC0gVGhlIHJ1bGUgY29udGV4dCwgdXNlZCB0byByZXNvbHZlIHRoZSBkZWFkbGluZSB0aHJvdWdoIHNjb3BlLlxuICogQHJldHVybnMgVGhlIGNlaWxpbmcgaW4gbWlsbGlzZWNvbmRzLCBvciBgbnVsbGAgd2hlbiB0aGUgY29uZGl0aW9uIGRlY2xhcmVzIG5vbmUuXG4gKi9cbmZ1bmN0aW9uIHJlYWREZWFkbGluZUd1YXJkSW5NaWxsaXNlY29uZHMobm9kZTogVFNFU1RyZWUuTm9kZSwgY2xvc3VyZTogRXZhbENsb3N1cmUsIGNvbnRleHQ6IFJ1bGUuUnVsZUNvbnRleHQpOiBudWxsIHwgbnVtYmVyIHtcbiAgaWYgKCFpc0JpbmFyeUV4cHJlc3Npb24obm9kZSkpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IGlzQ2xvY2tPbkxlZnQgPSBub2RlLm9wZXJhdG9yID09PSAnPCcgfHwgbm9kZS5vcGVyYXRvciA9PT0gJzw9JztcbiAgaWYgKCFpc0Nsb2NrT25MZWZ0ICYmIG5vZGUub3BlcmF0b3IgIT09ICc+JyAmJiBub2RlLm9wZXJhdG9yICE9PSAnPj0nKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCBjbG9ja05hbWUgPSByZWFkQ2xvY2tOYW1lKGlzQ2xvY2tPbkxlZnQgPyBub2RlLmxlZnQgOiBub2RlLnJpZ2h0KTtcbiAgY29uc3QgZGVhZGxpbmVOb2RlID0gKGlzQ2xvY2tPbkxlZnQgPyBub2RlLnJpZ2h0IDogbm9kZS5sZWZ0KSBhcyBUU0VTVHJlZS5Ob2RlO1xuICBpZiAoY2xvY2tOYW1lID09PSBudWxsIHx8ICFpc0lkZW50aWZpZXIoZGVhZGxpbmVOb2RlKSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgYm91bmROb2RlID0gcmVhZEJvdW5kRXhwcmVzc2lvbihkZWFkbGluZU5vZGUsIGNsb3N1cmUsIGNvbnRleHQpO1xuICByZXR1cm4gIWJvdW5kTm9kZSB8fCAhaXNCaW5hcnlFeHByZXNzaW9uKGJvdW5kTm9kZSkgfHwgYm91bmROb2RlLm9wZXJhdG9yICE9PSAnKycgfHwgKHJlYWRDbG9ja05hbWUoYm91bmROb2RlLmxlZnQpICE9PSBjbG9ja05hbWUpID8gbnVsbCA6IHJlc29sdmVOdW1iZXIoYm91bmROb2RlLnJpZ2h0LCBjbG9zdXJlLCBjb250ZXh0KTtcbn1cblxuLyoqXG4gKiBSZWFkcyB0aGUgZnVuY3Rpb24gYSBzY29wZSBkZWZpbml0aW9uIGRlY2xhcmVzLCBpZiBpdCBkZWNsYXJlcyBvbmUuXG4gKlxuICogQHBhcmFtIGRlZmluaXRpb25Ob2RlIC0gVGhlIG5vZGUgYSB2YXJpYWJsZSdzIGRlZmluaXRpb24gcG9pbnRzIGF0LlxuICogQHJldHVybnMgVGhlIGZ1bmN0aW9uIGl0IGRlY2xhcmVzLCBvciBgbnVsbGAgd2hlbiB0aGUgbmFtZSBpcyBib3VuZCB0byBhbnl0aGluZyBlbHNlLlxuICovXG5mdW5jdGlvbiByZWFkRGVmaW5pdGlvbkZ1bmN0aW9uTm9kZShkZWZpbml0aW9uTm9kZTogVFNFU1RyZWUuTm9kZSk6IEhlbHBlckZ1bmN0aW9uIHwgbnVsbCB7XG4gIGlmIChpc0Z1bmN0aW9uTm9kZShkZWZpbml0aW9uTm9kZSkpIHtcbiAgICByZXR1cm4gZGVmaW5pdGlvbk5vZGU7XG4gIH1cblxuICBpZiAoIWlzVmFyaWFibGVEZWNsYXJhdG9yKGRlZmluaXRpb25Ob2RlKSB8fCAhZGVmaW5pdGlvbk5vZGUuaW5pdCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgaW5pdE5vZGUgPSBkZWZpbml0aW9uTm9kZS5pbml0IGFzIFRTRVNUcmVlLk5vZGU7XG4gIHJldHVybiBpc0Z1bmN0aW9uTm9kZShpbml0Tm9kZSkgPyBpbml0Tm9kZSA6IG51bGw7XG59XG5cbi8qKlxuICogUmVhZHMgdGhlIGluLU9ic2lkaWFuIGNsb3N1cmUgYSBmdW5jdGlvbiBub2RlIGlzLCBpZiBpdCBpcyBvbmUuXG4gKlxuICogQSBjbG9zdXJlIHF1YWxpZmllcyB3aGVuIGl0IGlzIHRoZSB2YWx1ZSBvZiBhIGBjYWxsYmFja2AgLyBgcG9sbGAgLyBgc3RhcnRgIHByb3BlcnR5IG9mIHRoZSBvYmplY3RcbiAqIGxpdGVyYWwgcGFzc2VkIGFzIHRoZSBoZWxwZXIncyBmaXJzdCBhcmd1bWVudCBcdTIwMTQgd2hpY2ggY292ZXJzIGJvdGggdGhlIG1ldGhvZCBzaG9ydGhhbmRcbiAqIChgYXN5bmMgY2FsbGJhY2soeyBcdTIwMjYgfSkgeyBcdTIwMjYgfWApIGFuZCBhbiBhcnJvdyAoYGNhbGxiYWNrOiBhc3luYyAoeyBcdTIwMjYgfSkgPT4geyBcdTIwMjYgfWApLlxuICpcbiAqIEBwYXJhbSBub2RlIC0gVGhlIG5vZGUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyBUaGUgY2xvc3VyZSwgb3IgYG51bGxgIHdoZW4gdGhlIG5vZGUgaXMgbm90IGFuIGluLU9ic2lkaWFuIGNsb3N1cmUuXG4gKi9cbmZ1bmN0aW9uIHJlYWRFdmFsQ2xvc3VyZShub2RlOiBUU0VTVHJlZS5Ob2RlKTogRXZhbENsb3N1cmUgfCBudWxsIHtcbiAgaWYgKCFpc0Nsb3N1cmVGdW5jdGlvbihub2RlKSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgcHJvcGVydHlOb2RlID0gbm9kZS5wYXJlbnQ7XG4gIGlmICghaXNQcm9wZXJ0eShwcm9wZXJ0eU5vZGUpKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvKlxuICAgKiBUaGUgb2JqZWN0IGNoZWNrIGNvbWVzIEJFRk9SRSB0aGUga2V5IGNoZWNrIGJlY2F1c2UgYSBmdW5jdGlvbiBjYW4gcmVhY2ggYSBwcm9wZXJ0eSB0aHJvdWdoIGl0c1xuICAgKiBDT01QVVRFRCBLRVkgYXMgd2VsbCBhcyB0aHJvdWdoIGl0cyB2YWx1ZSAtLSBgeyBbKCkgPT4gJ2EnXTogMSB9YCBpcyBsZWdhbCAtLSBhbmQgYSBkZXN0cnVjdHVyaW5nXG4gICAqIHBhdHRlcm4gY2FuIGNhcnJ5IG9uZSB0b28uIE5laXRoZXIgaXMgYSBoZWxwZXIgY2FsbCdzIHBhcmFtZXRlciBvYmplY3QuXG4gICAqL1xuICBjb25zdCBwYXJhbXNOb2RlID0gcHJvcGVydHlOb2RlLnBhcmVudDtcbiAgaWYgKCFpc09iamVjdEV4cHJlc3Npb24ocGFyYW1zTm9kZSkgfHwgIWlzSWRlbnRpZmllcihwcm9wZXJ0eU5vZGUua2V5KSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgY2FsbE5vZGUgPSBwYXJhbXNOb2RlLnBhcmVudDtcbiAgaWYgKCFpc0NhbGxFeHByZXNzaW9uKGNhbGxOb2RlKSB8fCBjYWxsTm9kZS5hcmd1bWVudHNbMF0gIT09IHBhcmFtc05vZGUpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IGNsb3N1cmVOYW1lcyA9IHJlYWRDbG9zdXJlTmFtZXMoY2FsbE5vZGUpO1xuICByZXR1cm4gY2xvc3VyZU5hbWVzPy5pbmNsdWRlcyhwcm9wZXJ0eU5vZGUua2V5Lm5hbWUpXG4gICAgPyB7XG4gICAgICBjbG9zdXJlTm9kZTogbm9kZSxcbiAgICAgIHBhcmFtc05vZGUsXG4gICAgICByZXBvcnROb2RlOiBwcm9wZXJ0eU5vZGVcbiAgICB9XG4gICAgOiBudWxsO1xufVxuXG4vKipcbiAqIFJlYWRzIHRoZSB2YWx1ZSBhIGNhbGwncyBvd24gYGlucHV0YCBvYmplY3Qgc3VwcGxpZXMgZm9yIG9uZSBrZXkuXG4gKlxuICogVGhpcyBpcyBob3cgYSBidWRnZXQgZGVjbGFyZWQgb25jZSBhdCB0aGUgY2FsbCBzaXRlIHJlYWNoZXMgdGhlIGNsb3N1cmUsIHdoaWNoIGNhbm5vdCBjbG9zZSBvdmVyXG4gKiBhbnl0aGluZzogYGlucHV0OiB7IHNldHRsZVRpbWVvdXRJbk1pbGxpc2Vjb25kczogU0VUVExFIH1gIGFycml2ZXMgZGVzdHJ1Y3R1cmVkIGluIHRoZSBjYWxsYmFjaydzXG4gKiBwYXJhbWV0ZXIgb2JqZWN0LlxuICpcbiAqIEBwYXJhbSBwYXJhbXNOb2RlIC0gVGhlIGhlbHBlcidzIHBhcmFtZXRlciBvYmplY3QuXG4gKiBAcGFyYW0ga2V5TmFtZSAtIFRoZSBgaW5wdXRgIHByb3BlcnR5IHRvIHJlYWQuXG4gKiBAcmV0dXJucyBUaGUgZXhwcmVzc2lvbiBzdXBwbHlpbmcgdGhhdCBrZXksIG9yIGBudWxsYCB3aGVuIHRoZSBjYWxsJ3MgYGlucHV0YCBkb2VzIG5vdCBkZWNsYXJlIGl0LlxuICovXG5mdW5jdGlvbiByZWFkSW5wdXRQcm9wZXJ0eVZhbHVlKHBhcmFtc05vZGU6IFRTRVNUcmVlLk9iamVjdEV4cHJlc3Npb24sIGtleU5hbWU6IHN0cmluZyk6IG51bGwgfCBUU0VTVHJlZS5Ob2RlIHtcbiAgY29uc3QgaW5wdXRQcm9wZXJ0eSA9IHBhcmFtc05vZGUucHJvcGVydGllcy5maW5kKChwcm9wZXJ0eSkgPT5cbiAgICBpc1Byb3BlcnR5KHByb3BlcnR5IGFzIFRTRVNUcmVlLk5vZGUpXG4gICAgJiYgaXNJZGVudGlmaWVyKChwcm9wZXJ0eSBhcyBUU0VTVHJlZS5Qcm9wZXJ0eSkua2V5IGFzIFRTRVNUcmVlLk5vZGUpXG4gICAgJiYgKChwcm9wZXJ0eSBhcyBUU0VTVHJlZS5Qcm9wZXJ0eSkua2V5IGFzIFRTRVNUcmVlLklkZW50aWZpZXIpLm5hbWUgPT09IElOUFVUX1BST1BFUlRZX05BTUVcbiAgKSBhcyBUU0VTVHJlZS5Qcm9wZXJ0eSB8IHVuZGVmaW5lZDtcblxuICBjb25zdCBpbnB1dE5vZGUgPSBpbnB1dFByb3BlcnR5Py52YWx1ZSBhcyBUU0VTVHJlZS5Ob2RlIHwgdW5kZWZpbmVkO1xuICBpZiAoIWlucHV0Tm9kZSB8fCAhaXNPYmplY3RFeHByZXNzaW9uKGlucHV0Tm9kZSkpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IHZhbHVlUHJvcGVydHkgPSBpbnB1dE5vZGUucHJvcGVydGllcy5maW5kKChwcm9wZXJ0eSkgPT5cbiAgICBpc1Byb3BlcnR5KHByb3BlcnR5IGFzIFRTRVNUcmVlLk5vZGUpXG4gICAgJiYgaXNJZGVudGlmaWVyKChwcm9wZXJ0eSBhcyBUU0VTVHJlZS5Qcm9wZXJ0eSkua2V5IGFzIFRTRVNUcmVlLk5vZGUpXG4gICAgJiYgKChwcm9wZXJ0eSBhcyBUU0VTVHJlZS5Qcm9wZXJ0eSkua2V5IGFzIFRTRVNUcmVlLklkZW50aWZpZXIpLm5hbWUgPT09IGtleU5hbWVcbiAgKSBhcyBUU0VTVHJlZS5Qcm9wZXJ0eSB8IHVuZGVmaW5lZDtcblxuICByZXR1cm4gKHZhbHVlUHJvcGVydHk/LnZhbHVlIGFzIFRTRVNUcmVlLk5vZGUgfCB1bmRlZmluZWQpID8/IG51bGw7XG59XG5cbi8qKlxuICogUmVhZHMgdGhlIHdob2xlLWxvb3AgY2VpbGluZyBhIGNsb2NrIGRlYWRsaW5lIGRlY2xhcmVzLCBpbiBtaWxsaXNlY29uZHMuXG4gKlxuICogVGhlIGd1YXJkIGlzIGxvb2tlZCBmb3IgYW1vbmcgdGhlIHRlc3QncyBgJiZgIGNvbmp1bmN0cyByYXRoZXIgdGhhbiBhcyB0aGUgd2hvbGUgdGVzdCwgYmVjYXVzZSB0aGVcbiAqIGxvb3BzIHRoYXQgY2Fycnkgb25lIHBhaXIgaXQgd2l0aCBhIHByb2dyZXNzIGNvbmRpdGlvbiBcdTIwMTQgYHdoaWxlIChjb3VudCA8IGV4cGVjdGVkICYmIERhdGUubm93KCkgPCBkZWFkbGluZSlgXG4gKiBcdTIwMTQgYW5kIGEgY29tcG91bmQgdGVzdCBtdXN0IG5vdCByZW1vdmUgYSBjZWlsaW5nIG9uZSBvZiBpdHMgY29uanVuY3RzIHBsYWlubHkgZGVjbGFyZXMuXG4gKlxuICogQHBhcmFtIGxvb3BOb2RlIC0gVGhlIGxvb3AgdG8gaW5zcGVjdC5cbiAqIEBwYXJhbSBjbG9zdXJlIC0gVGhlIGluLU9ic2lkaWFuIGNsb3N1cmUgdGhlIGxvb3AgcnVucyBpbnNpZGUuXG4gKiBAcGFyYW0gY29udGV4dCAtIFRoZSBydWxlIGNvbnRleHQsIHVzZWQgdG8gcmVzb2x2ZSB0aGUgZGVhZGxpbmUgdGhyb3VnaCBzY29wZS5cbiAqIEByZXR1cm5zIFRoZSBjZWlsaW5nIGluIG1pbGxpc2Vjb25kcywgb3IgYG51bGxgIHdoZW4gdGhlIGxvb3AgZGVjbGFyZXMgbm9uZS5cbiAqL1xuZnVuY3Rpb24gcmVhZExvb3BEZWFkbGluZUluTWlsbGlzZWNvbmRzKGxvb3BOb2RlOiBMb29wU3RhdGVtZW50LCBjbG9zdXJlOiBFdmFsQ2xvc3VyZSwgY29udGV4dDogUnVsZS5SdWxlQ29udGV4dCk6IG51bGwgfCBudW1iZXIge1xuICBpZiAoIWxvb3BOb2RlLnRlc3QpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGZvciAoY29uc3QgY29uanVuY3Qgb2YgcmVhZENvbmp1bmN0cyhsb29wTm9kZS50ZXN0KSkge1xuICAgIGNvbnN0IGRlYWRsaW5lSW5NaWxsaXNlY29uZHMgPSByZWFkRGVhZGxpbmVHdWFyZEluTWlsbGlzZWNvbmRzKGNvbmp1bmN0LCBjbG9zdXJlLCBjb250ZXh0KTtcbiAgICBpZiAoZGVhZGxpbmVJbk1pbGxpc2Vjb25kcyAhPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIGRlYWRsaW5lSW5NaWxsaXNlY29uZHM7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG51bGw7XG59XG5cbi8qKlxuICogUmVhZHMgdGhlIGZpcnN0IHZhbHVlIGEgbG9vcCdzIHRlc3Qgd2lsbCBub3QgbGV0IGl0cyBjb3VudGVyIHJlYWNoLlxuICpcbiAqIEFuIGluY2x1c2l2ZSBib3VuZCBhbnN3ZXJzIG9uZSBoaWdoZXIgdGhhbiBpdCBpcyB3cml0dGVuLCBzbyBhIGNhbGxlciB3b3JrcyBpbiBvbmUgY3VycmVuY3kgcmF0aGVyIHRoYW5cbiAqIGNhcnJ5aW5nIHRoZSBvcGVyYXRvciBhbG9uZyB3aXRoIHRoZSBudW1iZXIuIFRoZSB0ZXN0IGlzIHJlYWQgYXMgYCYmYCBjb25qdW5jdHMgZm9yIHRoZSBzYW1lIHJlYXNvbiBhXG4gKiBkZWFkbGluZSBndWFyZCBpczogYGF0dGVtcHQgPCBBVFRFTVBUUyAmJiAhaXNPcGVuYCBzdGlsbCBjYW5ub3QgcnVuIG1vcmUgdGhhbiBgQVRURU1QVFNgIHRpbWVzLlxuICpcbiAqIEBwYXJhbSB0ZXN0Tm9kZSAtIFRoZSBsb29wJ3MgdGVzdC5cbiAqIEBwYXJhbSBjb3VudGVyTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBjb3VudGVyIHRoZSBsb29wIGFkdmFuY2VzLlxuICogQHBhcmFtIGNsb3N1cmUgLSBUaGUgaW4tT2JzaWRpYW4gY2xvc3VyZSB0aGUgbG9vcCBydW5zIGluc2lkZS5cbiAqIEBwYXJhbSBjb250ZXh0IC0gVGhlIHJ1bGUgY29udGV4dCwgdXNlZCB0byByZXNvbHZlIHRoZSBib3VuZCB0aHJvdWdoIHNjb3BlLlxuICogQHJldHVybnMgVGhlIGV4Y2x1c2l2ZSBib3VuZCwgb3IgYG51bGxgIHdoZW4gbm8gY29uanVuY3QgYm91bmRzIHRoYXQgY291bnRlciBieSBhIHJlc29sdmFibGUgbnVtYmVyLlxuICovXG5mdW5jdGlvbiByZWFkTG9vcEV4Y2x1c2l2ZUJvdW5kKFxuICB0ZXN0Tm9kZTogVFNFU1RyZWUuRXhwcmVzc2lvbixcbiAgY291bnRlck5hbWU6IHN0cmluZyxcbiAgY2xvc3VyZTogRXZhbENsb3N1cmUsXG4gIGNvbnRleHQ6IFJ1bGUuUnVsZUNvbnRleHRcbik6IG51bGwgfCBudW1iZXIge1xuICBmb3IgKGNvbnN0IGNvbmp1bmN0IG9mIHJlYWRDb25qdW5jdHModGVzdE5vZGUpKSB7XG4gICAgaWYgKCFpc0JpbmFyeUV4cHJlc3Npb24oY29uanVuY3QpIHx8IChjb25qdW5jdC5vcGVyYXRvciAhPT0gJzwnICYmIGNvbmp1bmN0Lm9wZXJhdG9yICE9PSAnPD0nKSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgY29uc3QgY291bnRlck5vZGUgPSBjb25qdW5jdC5sZWZ0IGFzIFRTRVNUcmVlLk5vZGU7XG4gICAgaWYgKCFpc0lkZW50aWZpZXIoY291bnRlck5vZGUpIHx8IGNvdW50ZXJOb2RlLm5hbWUgIT09IGNvdW50ZXJOYW1lKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBjb25zdCBib3VuZFZhbHVlID0gcmVzb2x2ZU51bWJlcihjb25qdW5jdC5yaWdodCwgY2xvc3VyZSwgY29udGV4dCk7XG4gICAgaWYgKGJvdW5kVmFsdWUgPT09IG51bGwpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIHJldHVybiBjb25qdW5jdC5vcGVyYXRvciA9PT0gJzwnID8gYm91bmRWYWx1ZSA6IGJvdW5kVmFsdWUgKyAxO1xuICB9XG5cbiAgcmV0dXJuIG51bGw7XG59XG5cbi8qKlxuICogUmVhZHMgaG93IG1hbnkgdGltZXMgYSBjb3VudGluZyBgZm9yYCBydW5zLlxuICpcbiAqIFRoZSBib3VuZCBpcyByZWFkIGZyb20gdGhlIHNhbWUgYCYmYCBjb25qdW5jdHMgYSBkZWFkbGluZSBpcywgZm9yIHRoZSBzYW1lIHJlYXNvbjpcbiAqIGBhdHRlbXB0IDwgQVRURU1QVFMgJiYgIWlzT3BlbmAgc3RpbGwgY2Fubm90IHJ1biBtb3JlIHRoYW4gYEFUVEVNUFRTYCB0aW1lcy4gVGhlIFNURVAgaXMgcmVhZCByYXRoZXJcbiAqIHRoYW4gcHJlc3VtZWQgdG8gYmUgb25lLCBvciBhIGBmb3IgKGxldCBlbGFwc2VkID0gMDsgZWxhcHNlZCA8IEJVREdFVDsgZWxhcHNlZCArPSBJTlRFUlZBTClgIHBvbGwgd291bGRcbiAqIGJlIGNvdW50ZWQgYEJVREdFVGAgdGltZXMuXG4gKlxuICogQHBhcmFtIGxvb3BOb2RlIC0gVGhlIGxvb3AgdG8gaW5zcGVjdC5cbiAqIEBwYXJhbSBjbG9zdXJlIC0gVGhlIGluLU9ic2lkaWFuIGNsb3N1cmUgdGhlIGxvb3AgcnVucyBpbnNpZGUuXG4gKiBAcGFyYW0gY29udGV4dCAtIFRoZSBydWxlIGNvbnRleHQsIHVzZWQgdG8gcmVzb2x2ZSB0aGUgc3RhcnQsIGJvdW5kIGFuZCBzdGVwIHRocm91Z2ggc2NvcGUuXG4gKiBAcmV0dXJucyBUaGUgaXRlcmF0aW9uIGNvdW50LCBvciBgbnVsbGAgd2hlbiBpdCBpcyBub3Qgc3RhdGljYWxseSBrbm93YWJsZS5cbiAqL1xuZnVuY3Rpb24gcmVhZExvb3BJdGVyYXRpb25Db3VudChsb29wTm9kZTogTG9vcFN0YXRlbWVudCwgY2xvc3VyZTogRXZhbENsb3N1cmUsIGNvbnRleHQ6IFJ1bGUuUnVsZUNvbnRleHQpOiBudWxsIHwgbnVtYmVyIHtcbiAgaWYgKCFpc0ZvclN0YXRlbWVudChsb29wTm9kZSkgfHwgIWxvb3BOb2RlLnRlc3QgfHwgIWxvb3BOb2RlLmluaXQgfHwgIWlzVmFyaWFibGVEZWNsYXJhdGlvbihsb29wTm9kZS5pbml0KSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgZGVjbGFyYXRvck5vZGVzID0gbG9vcE5vZGUuaW5pdC5kZWNsYXJhdGlvbnM7XG4gIGNvbnN0IGRlY2xhcmF0b3JOb2RlID0gZGVjbGFyYXRvck5vZGVzLmxlbmd0aCA9PT0gMSA/IGRlY2xhcmF0b3JOb2Rlc1swXSA6IHVuZGVmaW5lZDtcbiAgaWYgKCFkZWNsYXJhdG9yTm9kZT8uaW5pdCB8fCAhaXNJZGVudGlmaWVyKGRlY2xhcmF0b3JOb2RlLmlkKSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3Qgc3RhcnRWYWx1ZSA9IHJlc29sdmVOdW1iZXIoZGVjbGFyYXRvck5vZGUuaW5pdCwgY2xvc3VyZSwgY29udGV4dCk7XG4gIGNvbnN0IHN0ZXBTaXplID0gcmVhZExvb3BTdGVwU2l6ZShsb29wTm9kZS51cGRhdGUsIGRlY2xhcmF0b3JOb2RlLmlkLCBjbG9zdXJlLCBjb250ZXh0KTtcbiAgY29uc3QgYm91bmRWYWx1ZSA9IHJlYWRMb29wRXhjbHVzaXZlQm91bmQobG9vcE5vZGUudGVzdCwgZGVjbGFyYXRvck5vZGUuaWQubmFtZSwgY2xvc3VyZSwgY29udGV4dCk7XG4gIGlmIChzdGFydFZhbHVlID09PSBudWxsIHx8IHN0ZXBTaXplID09PSBudWxsIHx8IHN0ZXBTaXplIDw9IDAgfHwgYm91bmRWYWx1ZSA9PT0gbnVsbCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3Qgc3BhbiA9IGJvdW5kVmFsdWUgLSBzdGFydFZhbHVlO1xuICByZXR1cm4gc3BhbiA+IDAgPyBNYXRoLmNlaWwoc3BhbiAvIHN0ZXBTaXplKSA6IDA7XG59XG5cbi8qKlxuICogUmVhZHMgaG93IG1hbnkgdGltZXMgc29tZXRoaW5nIHdyaXR0ZW4gYXQgYSBub2RlIGFjdHVhbGx5IHJ1bnMsIGFzIHRoZSBwcm9kdWN0IG9mIGl0cyBlbmNsb3NpbmcgbG9vcHMuXG4gKlxuICogQSBsb29wIHRoYXQgaXMgbm90IHN0YXRpY2FsbHkgY291bnRhYmxlIGNvbnRyaWJ1dGVzIGEgZmFjdG9yIG9mIE9ORSByYXRoZXIgdGhhbiBkaXNxdWFsaWZ5aW5nIHRoZSBzdW06XG4gKiB0aGF0IGlzIHRoZSBwZXItaXRlcmF0aW9uIGNoYXJnZSB0aGlzIHJ1bGUgaGFzIGFsd2F5cyBtYWRlLCBhbmQgaXQgaXMgd2hhdCBrZWVwcyBhbiB1bmJvdW5kZWRcbiAqIGB3aGlsZSAodHJ1ZSlgIHNpbGVudCBpbnN0ZWFkIG9mIGd1ZXNzZWQgYXQuIEEgREVBRExJTkUtYm91bmRlZCBsb29wIGNvbnRyaWJ1dGVzIG9uZSBhcyB3ZWxsLCBiZWNhdXNlXG4gKiBpdHMgd2hvbGUtbG9vcCBjZWlsaW5nIGlzIGNoYXJnZWQgc2VwYXJhdGVseSBhbmQgbXVsdGlwbHlpbmcgdG9vIHdvdWxkIGNvdW50IHRoZSBzYW1lIHdhaXRpbmcgdHdpY2UuXG4gKlxuICogVGhlIHdhbGsgc3RvcHMgYXQgdGhlIGZ1bmN0aW9uIHRoZSBub2RlIGlzIENIQVJHRUQgdG8sIG5vdCBhdCB0aGUgY2xvc3VyZSwgc28gdGhlIGxvb3BzIGFyb3VuZCBhIGhlbHBlcidzXG4gKiBvd24gd2FpdHMgYW5kIHRoZSBsb29wcyBhcm91bmQgZWFjaCBjYWxsIHRvIHRoYXQgaGVscGVyIGFyZSBjb3VudGVkIG9uY2UgZWFjaCByYXRoZXIgdGhhbiB0d2ljZS5cbiAqXG4gKiBAcGFyYW0gbm9kZSAtIFRoZSBub2RlIHRvIGNvdW50IHRoZSBydW5zIG9mLlxuICogQHBhcmFtIHRhcmdldCAtIFRoZSBmdW5jdGlvbiB0aGUgbm9kZSBpcyBjaGFyZ2VkIHRvLlxuICogQHBhcmFtIGNvbnRleHQgLSBUaGUgcnVsZSBjb250ZXh0LCB1c2VkIHRvIHJlc29sdmUgbG9vcCBib3VuZHMgdGhyb3VnaCBzY29wZS5cbiAqIEByZXR1cm5zIFRoZSBtdWx0aXBsaWVyLCBuZXZlciBsZXNzIHRoYW4gb25lLlxuICovXG5mdW5jdGlvbiByZWFkTG9vcE11bHRpcGxpZXIobm9kZTogVFNFU1RyZWUuTm9kZSwgdGFyZ2V0OiBDaGFyZ2VUYXJnZXQsIGNvbnRleHQ6IFJ1bGUuUnVsZUNvbnRleHQpOiBudW1iZXIge1xuICBjb25zdCBjbG9zdXJlID0gdGFyZ2V0LmNsb3N1cmU7XG4gIGxldCBtdWx0aXBsaWVyID0gMTtcbiAgbGV0IGN1cnJlbnROb2RlOiBUU0VTVHJlZS5Ob2RlIHwgdW5kZWZpbmVkID0gbm9kZS5wYXJlbnQ7XG5cbiAgd2hpbGUgKGN1cnJlbnROb2RlICYmIGN1cnJlbnROb2RlICE9PSB0YXJnZXQuZnVuY3Rpb25Ob2RlKSB7XG4gICAgaWYgKGlzTG9vcFN0YXRlbWVudChjdXJyZW50Tm9kZSkgJiYgcmVhZExvb3BEZWFkbGluZUluTWlsbGlzZWNvbmRzKGN1cnJlbnROb2RlLCBjbG9zdXJlLCBjb250ZXh0KSA9PT0gbnVsbCkge1xuICAgICAgY29uc3QgaXRlcmF0aW9uQ291bnQgPSByZWFkTG9vcEl0ZXJhdGlvbkNvdW50KGN1cnJlbnROb2RlLCBjbG9zdXJlLCBjb250ZXh0KTtcbiAgICAgIGlmIChpdGVyYXRpb25Db3VudCAhPT0gbnVsbCkge1xuICAgICAgICBtdWx0aXBsaWVyICo9IGl0ZXJhdGlvbkNvdW50O1xuICAgICAgfVxuICAgIH1cbiAgICBjdXJyZW50Tm9kZSA9IGN1cnJlbnROb2RlLnBhcmVudDtcbiAgfVxuXG4gIHJldHVybiBtdWx0aXBsaWVyO1xufVxuXG4vKipcbiAqIFJlYWRzIGhvdyBmYXIgYSBjb3VudGluZyBsb29wJ3MgdmFyaWFibGUgYWR2YW5jZXMgZWFjaCBpdGVyYXRpb24uXG4gKlxuICogQHBhcmFtIHVwZGF0ZU5vZGUgLSBUaGUgbG9vcCdzIHVwZGF0ZSBleHByZXNzaW9uLlxuICogQHBhcmFtIGNvdW50ZXJOb2RlIC0gVGhlIGlkZW50aWZpZXIgdGhlIGxvb3AgY291bnRzIG9uLlxuICogQHBhcmFtIGNsb3N1cmUgLSBUaGUgaW4tT2JzaWRpYW4gY2xvc3VyZSB0aGUgbG9vcCBydW5zIGluc2lkZS5cbiAqIEBwYXJhbSBjb250ZXh0IC0gVGhlIHJ1bGUgY29udGV4dCwgdXNlZCB0byByZXNvbHZlIGEgbm9uLWxpdGVyYWwgc3RlcCB0aHJvdWdoIHNjb3BlLlxuICogQHJldHVybnMgVGhlIHN0ZXAsIG9yIGBudWxsYCB3aGVuIHRoZSB1cGRhdGUgaXMgbm90IGEgcGxhaW4gYWR2YW5jZSBvZiB0aGUgbG9vcCdzIG93biBjb3VudGVyLlxuICovXG5mdW5jdGlvbiByZWFkTG9vcFN0ZXBTaXplKFxuICB1cGRhdGVOb2RlOiBudWxsIHwgVFNFU1RyZWUuRXhwcmVzc2lvbixcbiAgY291bnRlck5vZGU6IFRTRVNUcmVlLklkZW50aWZpZXIsXG4gIGNsb3N1cmU6IEV2YWxDbG9zdXJlLFxuICBjb250ZXh0OiBSdWxlLlJ1bGVDb250ZXh0XG4pOiBudWxsIHwgbnVtYmVyIHtcbiAgaWYgKCF1cGRhdGVOb2RlKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBpZiAoaXNVcGRhdGVFeHByZXNzaW9uKHVwZGF0ZU5vZGUpKSB7XG4gICAgY29uc3QgYXJndW1lbnROb2RlID0gdXBkYXRlTm9kZS5hcmd1bWVudCBhcyBUU0VTVHJlZS5Ob2RlO1xuICAgIHJldHVybiB1cGRhdGVOb2RlLm9wZXJhdG9yID09PSAnKysnICYmIGlzSWRlbnRpZmllcihhcmd1bWVudE5vZGUpICYmIGFyZ3VtZW50Tm9kZS5uYW1lID09PSBjb3VudGVyTm9kZS5uYW1lID8gMSA6IG51bGw7XG4gIH1cblxuICBpZiAoIWlzQXNzaWdubWVudEV4cHJlc3Npb24odXBkYXRlTm9kZSkgfHwgdXBkYXRlTm9kZS5vcGVyYXRvciAhPT0gJys9Jykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgdGFyZ2V0Tm9kZSA9IHVwZGF0ZU5vZGUubGVmdCBhcyBUU0VTVHJlZS5Ob2RlO1xuICByZXR1cm4gIWlzSWRlbnRpZmllcih0YXJnZXROb2RlKSB8fCB0YXJnZXROb2RlLm5hbWUgIT09IGNvdW50ZXJOb2RlLm5hbWUgPyBudWxsIDogcmVzb2x2ZU51bWJlcih1cGRhdGVOb2RlLnJpZ2h0LCBjbG9zdXJlLCBjb250ZXh0KTtcbn1cblxuLyoqXG4gKiBSZWFkcyB0aGUgYGlucHV0YCBrZXkgYSBkZXN0cnVjdHVyZWQgY2xvc3VyZSBwYXJhbWV0ZXIgaXMgYm91bmQgZnJvbS5cbiAqXG4gKiBUaGUgYmluZGluZyBtYXkgYmUgcmVuYW1lZCAoYHRpbWVvdXRJbk1pbGxpc2Vjb25kczogdGltZW91dGApLCBzbyB0aGUgS0VZIGlzIHdoYXQgdGhlIGNhbGwncyBgaW5wdXRgXG4gKiBpcyBsb29rZWQgdXAgYnksIG5ldmVyIHRoZSBsb2NhbCBuYW1lLlxuICpcbiAqIEBwYXJhbSBjbG9zdXJlTm9kZSAtIFRoZSBjbG9zdXJlIHdob3NlIHBhcmFtZXRlcnMgdG8gcmVhZC5cbiAqIEBwYXJhbSBsb2NhbE5hbWUgLSBUaGUgbmFtZSB0aGUgYnVkZ2V0IGlzIGJvdW5kIHRvIGluc2lkZSB0aGUgY2xvc3VyZS5cbiAqIEByZXR1cm5zIFRoZSBgaW5wdXRgIGtleSwgb3IgYG51bGxgIHdoZW4gdGhlIG5hbWUgaXMgbm90IGJvdW5kIGJ5IGEgcGxhaW4gZGVzdHJ1Y3R1cmVkIHByb3BlcnR5LlxuICovXG5mdW5jdGlvbiByZWFkUGFyYW1ldGVySW5wdXRLZXkoY2xvc3VyZU5vZGU6IENsb3N1cmVGdW5jdGlvbiwgbG9jYWxOYW1lOiBzdHJpbmcpOiBudWxsIHwgc3RyaW5nIHtcbiAgZm9yIChjb25zdCBwYXJhbWV0ZXJOb2RlIG9mIGNsb3N1cmVOb2RlLnBhcmFtcykge1xuICAgIGlmICghaXNPYmplY3RQYXR0ZXJuKHBhcmFtZXRlck5vZGUpKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IHByb3BlcnR5IG9mIHBhcmFtZXRlck5vZGUucHJvcGVydGllcykge1xuICAgICAgaWYgKCFpc1Byb3BlcnR5KHByb3BlcnR5KSB8fCBwcm9wZXJ0eS5jb21wdXRlZCB8fCAhaXNJZGVudGlmaWVyKHByb3BlcnR5LmtleSkgfHwgIWlzSWRlbnRpZmllcihwcm9wZXJ0eS52YWx1ZSkpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChwcm9wZXJ0eS52YWx1ZS5uYW1lID09PSBsb2NhbE5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHByb3BlcnR5LmtleS5uYW1lO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBudWxsO1xufVxuXG4vKipcbiAqIFJlYWRzIHRoZSBleHByZXNzaW9uIGNhcnJ5aW5nIGEgd2FpdCBjYWxsJ3MgZGVjbGFyZWQgYnVkZ2V0LlxuICpcbiAqIEBwYXJhbSBjYWxsTm9kZSAtIFRoZSBjYWxsIGV4cHJlc3Npb24gdG8gaW5zcGVjdC5cbiAqIEByZXR1cm5zIFRoZSBleHByZXNzaW9uIHRvIHJlc29sdmU7IGBudWxsYCBmb3IgYSBgd2FpdFVudGlsYCB0aGF0IG9taXRzIGl0cyB0aW1lb3V0LCB3aGljaCB0YWtlcyB0aGVcbiAqIGhlbHBlcidzIGRlZmF1bHQ7IG9yIGB1bmRlZmluZWRgIHdoZW4gdGhlIGNhbGwgaXMgbm90IGEgd2FpdCBhdCBhbGwuXG4gKi9cbmZ1bmN0aW9uIHJlYWRXYWl0QnVkZ2V0RXhwcmVzc2lvbihjYWxsTm9kZTogVFNFU1RyZWUuQ2FsbEV4cHJlc3Npb24pOiBudWxsIHwgVFNFU1RyZWUuTm9kZSB8IHVuZGVmaW5lZCB7XG4gIGlmICghaXNJZGVudGlmaWVyKGNhbGxOb2RlLmNhbGxlZSkpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgY29uc3QgY2FsbGVlTmFtZSA9IGNhbGxOb2RlLmNhbGxlZS5uYW1lO1xuXG4gIGlmIChjYWxsZWVOYW1lID09PSBTTEVFUF9DQUxMRUVfTkFNRSkge1xuICAgIHJldHVybiAoY2FsbE5vZGUuYXJndW1lbnRzWzBdKSA/PyB1bmRlZmluZWQ7XG4gIH1cblxuICBpZiAoY2FsbGVlTmFtZSAhPT0gV0FJVF9VTlRJTF9DQUxMRUVfTkFNRSkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBjb25zdCBwYXJhbXNOb2RlID0gY2FsbE5vZGUuYXJndW1lbnRzWzBdIGFzIFRTRVNUcmVlLk5vZGUgfCB1bmRlZmluZWQ7XG4gIGlmICghcGFyYW1zTm9kZSB8fCAhaXNPYmplY3RFeHByZXNzaW9uKHBhcmFtc05vZGUpKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIGNvbnN0IHRpbWVvdXRQcm9wZXJ0eSA9IHBhcmFtc05vZGUucHJvcGVydGllcy5maW5kKChwcm9wZXJ0eSkgPT5cbiAgICBpc1Byb3BlcnR5KHByb3BlcnR5IGFzIFRTRVNUcmVlLk5vZGUpXG4gICAgJiYgaXNJZGVudGlmaWVyKChwcm9wZXJ0eSBhcyBUU0VTVHJlZS5Qcm9wZXJ0eSkua2V5IGFzIFRTRVNUcmVlLk5vZGUpXG4gICAgJiYgKChwcm9wZXJ0eSBhcyBUU0VTVHJlZS5Qcm9wZXJ0eSkua2V5IGFzIFRTRVNUcmVlLklkZW50aWZpZXIpLm5hbWUgPT09IFRJTUVPVVRfUFJPUEVSVFlfTkFNRVxuICApIGFzIFRTRVNUcmVlLlByb3BlcnR5IHwgdW5kZWZpbmVkO1xuXG4gIHJldHVybiAodGltZW91dFByb3BlcnR5Py52YWx1ZSkgPz8gbnVsbDtcbn1cblxuLyoqXG4gKiBSZXNvbHZlcyBhbiBleHByZXNzaW9uIHRvIGEgbnVtYmVyLCB0aHJvdWdoIHNjb3BlLlxuICpcbiAqIEV2ZXJ5IG51bWJlciB0aGUgcnVsZSByZWFkcyBjb21lcyB0aHJvdWdoIGhlcmUgXHUyMDE0IGEgd2FpdCdzIGJ1ZGdldCwgYSBsb29wJ3MgZGVhZGxpbmUsIGFuZCBhIGNvdW50aW5nXG4gKiBsb29wJ3Mgc3RhcnQsIGJvdW5kIGFuZCBzdGVwIFx1MjAxNCB3aGljaCBpcyB3aHkgaXQgaXMgbmFtZWQgZm9yIHdoYXQgaXQgcmVzb2x2ZXMgcmF0aGVyIHRoYW4gZm9yXG4gKiBtaWxsaXNlY29uZHMuXG4gKlxuICogSGFuZGxlcyBhIG51bWVyaWMgbGl0ZXJhbCwgYSBsaXRlcmFsLW9ubHkgcHJvZHVjdCAoYDYwICogMTAwMGApLCBhbiBpZGVudGlmaWVyIGJvdW5kIHRvIGVpdGhlciBpbiBhbnlcbiAqIGVuY2xvc2luZyBzY29wZSwgYW5kIGEgZGVzdHJ1Y3R1cmVkIGNsb3N1cmUgcGFyYW1ldGVyIGZvbGxvd2VkIGJhY2sgdGhyb3VnaCB0aGUgY2FsbCdzIG93biBgaW5wdXRgLlxuICogQW55dGhpbmcgZWxzZSBpcyB1bnJlc29sdmFibGUgYW5kIGFuc3dlcnMgYG51bGxgLCB3aGljaCB0aGUgY2FsbGVyIHRyZWF0cyBhcyBjb250cmlidXRpbmcgbm90aGluZy5cbiAqXG4gKiBFYWNoIGlkZW50aWZpZXIgaXMgcmVzb2x2ZWQgZnJvbSBJVFMgT1dOIHNjb3BlIHJhdGhlciB0aGFuIGZyb20gdGhlIHdhaXQncywgc28gYSB2YWx1ZSBzdXBwbGllZCBieSB0aGVcbiAqIGNhbGwncyBgaW5wdXRgIHJlc29sdmVzIGF0IHRoZSBjYWxsIHNpdGUgXHUyMDE0IHdoZXJlIGl0IHdhcyB3cml0dGVuIFx1MjAxNCBhbmQgaXMgbm90IGNhcHR1cmVkIGJ5IGEgc2FtZS1uYW1lZFxuICogYmluZGluZyB0aGF0IGhhcHBlbnMgdG8gZXhpc3QgaW5zaWRlIHRoZSBjbG9zdXJlLlxuICpcbiAqIEBwYXJhbSBub2RlIC0gVGhlIGV4cHJlc3Npb24gdG8gcmVzb2x2ZS5cbiAqIEBwYXJhbSBjbG9zdXJlIC0gVGhlIGNsb3N1cmUgdGhlIGV4cHJlc3Npb24gd2FzIHdyaXR0ZW4gaW5zaWRlLlxuICogQHBhcmFtIGNvbnRleHQgLSBUaGUgcnVsZSBjb250ZXh0LCB1c2VkIHRvIHJlc29sdmUgaWRlbnRpZmllcnMgdGhyb3VnaCBzY29wZS5cbiAqIEByZXR1cm5zIFRoZSBudW1iZXIsIG9yIGBudWxsYCB3aGVuIGl0IGNhbm5vdCBiZSByZXNvbHZlZCBzdGF0aWNhbGx5LlxuICovXG5mdW5jdGlvbiByZXNvbHZlTnVtYmVyKG5vZGU6IFRTRVNUcmVlLk5vZGUsIGNsb3N1cmU6IEV2YWxDbG9zdXJlLCBjb250ZXh0OiBSdWxlLlJ1bGVDb250ZXh0KTogbnVsbCB8IG51bWJlciB7XG4gIGNvbnN0IHZpc2l0ZWROb2RlcyA9IG5ldyBTZXQ8VFNFU1RyZWUuTm9kZT4oKTtcbiAgbGV0IGN1cnJlbnROb2RlID0gbm9kZTtcblxuICB3aGlsZSAoIXZpc2l0ZWROb2Rlcy5oYXMoY3VycmVudE5vZGUpKSB7XG4gICAgdmlzaXRlZE5vZGVzLmFkZChjdXJyZW50Tm9kZSk7XG5cbiAgICBpZiAoaXNOdW1lcmljTGl0ZXJhbChjdXJyZW50Tm9kZSkpIHtcbiAgICAgIHJldHVybiBjdXJyZW50Tm9kZS52YWx1ZTtcbiAgICB9XG5cbiAgICBpZiAoaXNCaW5hcnlFeHByZXNzaW9uKGN1cnJlbnROb2RlKSAmJiBjdXJyZW50Tm9kZS5vcGVyYXRvciA9PT0gJyonKSB7XG4gICAgICBjb25zdCBsZWZ0VmFsdWUgPSByZXNvbHZlTnVtYmVyKGN1cnJlbnROb2RlLmxlZnQsIGNsb3N1cmUsIGNvbnRleHQpO1xuICAgICAgY29uc3QgcmlnaHRWYWx1ZSA9IHJlc29sdmVOdW1iZXIoY3VycmVudE5vZGUucmlnaHQsIGNsb3N1cmUsIGNvbnRleHQpO1xuXG4gICAgICByZXR1cm4gbGVmdFZhbHVlID09PSBudWxsIHx8IHJpZ2h0VmFsdWUgPT09IG51bGwgPyBudWxsIDogbGVmdFZhbHVlICogcmlnaHRWYWx1ZTtcbiAgICB9XG5cbiAgICBpZiAoIWlzSWRlbnRpZmllcihjdXJyZW50Tm9kZSkpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IGJvdW5kTm9kZSA9IHJlYWRCb3VuZEV4cHJlc3Npb24oY3VycmVudE5vZGUsIGNsb3N1cmUsIGNvbnRleHQpO1xuICAgIGlmICghYm91bmROb2RlKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBjdXJyZW50Tm9kZSA9IGJvdW5kTm9kZTtcbiAgfVxuXG4gIHJldHVybiBudWxsO1xufVxuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUE4SEEsNEJBQStCO0FBQy9CLDBDQUFpRDtBQUVqRCxrQ0FHTztBQUtBLE1BQU0sYUFBYTtBQUsxQixNQUFNLDZDQUE2QztBQUVuRCxNQUFNLHNCQUFzQjtBQUM1QixNQUFNLG9CQUFvQjtBQUMxQixNQUFNLHdCQUF3QjtBQUM5QixNQUFNLHlCQUF5QjtBQU0vQixNQUFNLHFCQUFxQixvQkFBSSxJQUFJLENBQUMsUUFBUSxhQUFhLENBQUM7QUFFMUQsTUFBTSxrQkFBa0I7QUFPeEIsTUFBTSwrQkFBK0Isb0JBQUksSUFBK0I7QUFBQSxFQUN0RSxDQUFDLGtCQUFrQixDQUFDLFVBQVUsQ0FBQztBQUFBLEVBQy9CLENBQUMsa0JBQWtCLENBQUMsUUFBUSxPQUFPLENBQUM7QUFDdEMsQ0FBQztBQW1ITSxNQUFNLGdDQUFpRDtBQUFBLEVBQzVELE9BQU8sU0FBUztBQUNkLFVBQU0sVUFBVSxRQUFRLFFBQVEsQ0FBQztBQUNqQyxVQUFNLDJCQUEyQixRQUFRLFNBQVMsU0FBUyxnRUFB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
|