+
## New!
-> ### ✦ [**K.G.One Music Studio is available now.**](https://github.com/KGAudioLab/K.G.One) ✦
+> ### ✦ [K.G.One Music Studio is available now.](https://github.com/KGAudioLab/K.G.One) ✦
> [**K.G.One Music Studio**](https://github.com/KGAudioLab/K.G.One) is a fully local, open-source integrated platform built around **K.G.Studio** (this project). It bundles [ACE-Step 1.5](https://github.com/ace-step/ACE-Step-1.5) for full-song generation, [Foundation-1](https://huggingface.co/RoyalCities/Foundation-1) for audio clip and MIDI loop generation, and [python-audio-separator (UVR5)](https://github.com/nomadkaraoke/python-audio-separator) for stem separation — bringing GPU-accelerated AI music generation directly into your browser-based production workflow.
## What is K.G.Studio?
@@ -19,10 +23,12 @@ K.G.Studio is a lightweight, modern DAW that runs entirely in the browser with *
-> Note: Full-Song Generation Feature, Audio Clip Generation Feature, and Stem Separation Feature requires [**K.G.One Music Studio**](https://github.com/KGAudioLab/K.G.One) integration.
+> Note: Full-Song Generation Feature and Audio Clip Generation Feature requires [**K.G.One Music Studio**](https://github.com/KGAudioLab/K.G.One) integration.
## Latest Updates
+- **2026.05.15**: Added **browser-embedded AI models** — two AI models now run entirely in the browser with no external service, no API key, and no K.G.One server required. The **K.G.Studio Musician Assistant** gains a new **Local LLM (Browser)** provider powered by **Gemma 4 E4B** via LiteRT-LM with WebGPU acceleration; the model is downloaded once and cached in OPFS for instant subsequent launches, with configurable context length (32 k / 64 k / 128 k tokens) and live inference performance statistics. **Stem separation** now also runs locally through a browser-embedded **UVR-MDX-NET-Inst_HQ_3** ONNX model with WebGPU acceleration — open the **Music Generator** panel (✦ button), download the model once, and separate vocals from instruments entirely on-device. Both features require a WebGPU-capable browser (Chrome 113+ or Edge 113+) and a secure context (HTTPS or localhost). Recommended hardware: a GPU with at least 8 GB VRAM or a system with at least 16 GB unified RAM.
+
- **2026.05.10**: Added **staff notation (sheet music) view** — the piano roll now offers a full standard notation mode. Switch between Piano Roll and Sheet Music views using the toggle in the piano roll toolbar. In sheet music mode, notes are engraved via VexFlow with automatic clef selection (treble or bass) based on the active instrument, key signature rendering, automatic beam grouping, ties across bar lines, and configurable quantization for note-value resolution. Enable **Track Scope** to render all MIDI regions on the track as a continuous score rather than a single isolated region.
- **2026.05.09**: Added **audio recording** — record directly from your microphone into an audio track. A live waveform preview grows in real time as you record, and the region is committed to the timeline as a standard audio region when you stop. Added **audio I/O device selection** in Settings so you can choose your preferred microphone input and audio output device.
@@ -47,8 +53,6 @@ K.G.Studio is a lightweight, modern DAW that runs entirely in the browser with *
This project investigates how AI-human collaboration can enhance creative music-making, from intelligent harmony suggestions to automated editing tasks. As an experimental platform, expect frequent changes, evolving features, and occasional instability as we push the boundaries of what's possible in AI-assisted music production.
-### Start using the app online: [K.G.Studio (kgaudiolab.github.io/kgstudio)](https://kgaudiolab.github.io/kgstudio)
-
## Demo Videos
@@ -329,15 +333,17 @@ Feature priorities might change.
- [X] Recording
- [X] Event List
- [X] Add support for OpenAI's open source models (`gpt-oss-20b` and `gpt-oss-120b`)
+- [X] Stuff notation
+- [X] K.G.One Music Studio integration
+- [X] Browser-embedded AI models (on-device LLM via Gemma 4 E4B; on-device stem separation via UVR-MDX-NET-Inst_HQ_3)
### Post 1.0
-- [ ] Stuff notation
+- [ ] EQ
- [ ] Filters and effects
- [ ] Virtual MIDI device output
- [ ] Enhanced AI Music Assistant Agent
-
## Help Needed
We're looking for contributors to help make K.G.Studio even better! Whether you're a developer, musician, or designer, your expertise can make a real difference.
@@ -385,4 +391,4 @@ Licensed under the Apache License, Version 2.0, with additional terms (see `LICE
- No patent applications using this software or assets
- Attribution required when used in public/commercial products (“Powered by K.G.Studio”)
-Third‑party notices (e.g., FluidR3_GM SoundFont, midi‑js‑soundfonts, VexFlow, and prompt structure notes) are included in `LICENSE`.
+Third‑party notices (e.g., FluidR3_GM SoundFont, midi‑js‑soundfonts, VexFlow, prompt structure notes, Gemma 4 E4B, UVR-MDX-NET-Inst_HQ_3, and MediaPipe) are included in `LICENSE`.
diff --git a/package-lock.json b/package-lock.json
index 3ce903b..7a0f770 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,18 +1,20 @@
{
"name": "K.G.Studio",
- "version": "0.15.0-build.20260510",
+ "version": "0.16.0-build.20260510",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "K.G.Studio",
- "version": "0.15.0-build.20260510",
+ "version": "0.16.0-build.20260510",
"dependencies": {
"@breezystack/lamejs": "^1.2.7",
"class-transformer": "^0.5.1",
"fft.js": "^4.0.4",
"idb": "^8.0.3",
"jszip": "^3.10.1",
+ "katex": "^0.16.46",
+ "onnxruntime-web": "^1.26.0",
"openai": "^6.33.0",
"react": "^19.1.0",
"react-dom": "^19.1.0",
@@ -20,7 +22,9 @@
"react-markdown": "^10.1.0",
"react-syntax-highlighter": "^15.6.1",
"reflect-metadata": "^0.2.2",
+ "rehype-katex": "^7.0.1",
"remark-gfm": "^4.0.1",
+ "remark-math": "^6.0.0",
"tone": "^15.1.22",
"vexflow": "^5.0.0",
"zustand": "^5.0.6"
@@ -1628,6 +1632,70 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@protobufjs/aspromise": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
+ "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/base64": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
+ "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/codegen": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz",
+ "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/eventemitter": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
+ "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/fetch": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
+ "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.1",
+ "@protobufjs/inquire": "^1.1.0"
+ }
+ },
+ "node_modules/@protobufjs/float": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
+ "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/inquire": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.1.tgz",
+ "integrity": "sha512-mnzgDV26ueAvk7rsbt9L7bE0SuAoqyuys/sMMrmVcN5x9VsxpcG3rqAUSgDyLp0UZlmNfIbQ4fHfCtreVBk8Ew==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/path": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
+ "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/pool": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
+ "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/utf8": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.1.tgz",
+ "integrity": "sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==",
+ "license": "BSD-3-Clause"
+ },
"node_modules/@rolldown/pluginutils": {
"version": "1.0.0-beta.19",
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.19.tgz",
@@ -2604,6 +2672,11 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/katex": {
+ "version": "0.16.8",
+ "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.8.tgz",
+ "integrity": "sha512-trgaNyfU+Xh2Tc+ABIb44a5AYUpicB3uwirOioeOkNPPbmgRNtcWyDeeFRzjPZENO9Vq8gvVqfhaaXWLlevVwg=="
+ },
"node_modules/@types/mdast": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
@@ -2630,7 +2703,6 @@
"version": "22.18.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.0.tgz",
"integrity": "sha512-m5ObIqwsUp6BZzyiy4RdZpzWGub9bqLJMvZDD0QMXhxjqMHMENlj+SqF5QxoUwaQNFe+8kz8XM8ZQhqkQPTgMQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~6.21.0"
@@ -3681,6 +3753,14 @@
"url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/commander": {
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
+ "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
"node_modules/compare-func": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz",
@@ -4138,7 +4218,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
"integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
- "dev": true,
"license": "BSD-2-Clause",
"engines": {
"node": ">=0.12"
@@ -4802,6 +4881,12 @@
"node": ">=16"
}
},
+ "node_modules/flatbuffers": {
+ "version": "25.9.23",
+ "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-25.9.23.tgz",
+ "integrity": "sha512-MI1qs7Lo4Syw0EOzUl0xjs2lsoeqFku44KpngfIduHBYvzm8h2+7K8YMQh1JtVVVrUvhLpNwqVi4DERegUJhPQ==",
+ "license": "Apache-2.0"
+ },
"node_modules/flatted": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
@@ -5087,6 +5172,12 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/guid-typescript": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/guid-typescript/-/guid-typescript-1.0.9.tgz",
+ "integrity": "sha512-Y8T4vYhEfwJOTbouREvG+3XDsjr8E3kIr7uf+JZ0BYloFsttiHU0WfvANVsR7TxNUJa/WpCnw/Ino/p+DeBhBQ==",
+ "license": "ISC"
+ },
"node_modules/handlebars": {
"version": "4.7.8",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
@@ -5142,6 +5233,139 @@
"node": ">= 0.4"
}
},
+ "node_modules/hast-util-from-dom": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-5.0.1.tgz",
+ "integrity": "sha512-N+LqofjR2zuzTjCPzyDUdSshy4Ma6li7p/c3pA78uTwzFgENbgbUrm2ugwsOdcjI1muO+o6Dgzp9p8WHtn/39Q==",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "hastscript": "^9.0.0",
+ "web-namespaces": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-from-dom/node_modules/hast-util-parse-selector": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz",
+ "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==",
+ "dependencies": {
+ "@types/hast": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-from-dom/node_modules/hastscript": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz",
+ "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "comma-separated-tokens": "^2.0.0",
+ "hast-util-parse-selector": "^4.0.0",
+ "property-information": "^7.0.0",
+ "space-separated-tokens": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-from-html": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz",
+ "integrity": "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "devlop": "^1.1.0",
+ "hast-util-from-parse5": "^8.0.0",
+ "parse5": "^7.0.0",
+ "vfile": "^6.0.0",
+ "vfile-message": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-from-html-isomorphic": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-2.0.0.tgz",
+ "integrity": "sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw==",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "hast-util-from-dom": "^5.0.0",
+ "hast-util-from-html": "^2.0.0",
+ "unist-util-remove-position": "^5.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-from-parse5": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz",
+ "integrity": "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/unist": "^3.0.0",
+ "devlop": "^1.0.0",
+ "hastscript": "^9.0.0",
+ "property-information": "^7.0.0",
+ "vfile": "^6.0.0",
+ "vfile-location": "^5.0.0",
+ "web-namespaces": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-from-parse5/node_modules/hast-util-parse-selector": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz",
+ "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==",
+ "dependencies": {
+ "@types/hast": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-from-parse5/node_modules/hastscript": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz",
+ "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "comma-separated-tokens": "^2.0.0",
+ "hast-util-parse-selector": "^4.0.0",
+ "property-information": "^7.0.0",
+ "space-separated-tokens": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-is-element": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz",
+ "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==",
+ "dependencies": {
+ "@types/hast": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/hast-util-parse-selector": {
"version": "2.2.5",
"resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz",
@@ -5179,6 +5403,21 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/hast-util-to-text": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz",
+ "integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/unist": "^3.0.0",
+ "hast-util-is-element": "^3.0.0",
+ "unist-util-find-after": "^5.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/hast-util-whitespace": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz",
@@ -5962,6 +6201,21 @@
"setimmediate": "^1.0.5"
}
},
+ "node_modules/katex": {
+ "version": "0.16.46",
+ "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.46.tgz",
+ "integrity": "sha512-WHy4Coo+bGZyH7NwJKHkS04YFsFcarWbAEOAC3EMndzdN6VSZqklLLIgfxzyaW9jDoeGYJX9SWbJPKpecox0Uw==",
+ "funding": [
+ "https://opencollective.com/katex",
+ "https://github.com/sponsors/katex"
+ ],
+ "dependencies": {
+ "commander": "^8.3.0"
+ },
+ "bin": {
+ "katex": "cli.js"
+ }
+ },
"node_modules/keyv": {
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
@@ -6121,6 +6375,12 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/long": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
+ "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
+ "license": "Apache-2.0"
+ },
"node_modules/longest-streak": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz",
@@ -6447,6 +6707,24 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/mdast-util-math": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-math/-/mdast-util-math-3.0.0.tgz",
+ "integrity": "sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "devlop": "^1.0.0",
+ "longest-streak": "^3.0.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.1.0",
+ "unist-util-remove-position": "^5.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/mdast-util-mdx-expression": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz",
@@ -6949,6 +7227,24 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/micromark-extension-math": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz",
+ "integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==",
+ "dependencies": {
+ "@types/katex": "^0.16.0",
+ "devlop": "^1.0.0",
+ "katex": "^0.16.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/micromark-factory-destination": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz",
@@ -10920,6 +11216,26 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/onnxruntime-common": {
+ "version": "1.26.0",
+ "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.26.0.tgz",
+ "integrity": "sha512-qVyMR4lcWgbkc4getFV+GQijsTnbg/siteoqcDwa3sI/LxbrMSNw4ePyvCq/ymdQaRomCA7YuWmhzsswxvymdw==",
+ "license": "MIT"
+ },
+ "node_modules/onnxruntime-web": {
+ "version": "1.26.0",
+ "resolved": "https://registry.npmjs.org/onnxruntime-web/-/onnxruntime-web-1.26.0.tgz",
+ "integrity": "sha512-LbRr/8zZt2xilI2smrVQGGKINo0U46i8qJp+UXyMBGfqN7KjnH1BiwCwLwyNIVV4i9CKFv7Sf4PwLKWnT8/bEA==",
+ "license": "MIT",
+ "dependencies": {
+ "flatbuffers": "^25.1.24",
+ "guid-typescript": "^1.0.9",
+ "long": "^5.2.3",
+ "onnxruntime-common": "1.26.0",
+ "platform": "^1.3.6",
+ "protobufjs": "^7.2.4"
+ }
+ },
"node_modules/openai": {
"version": "6.33.0",
"resolved": "https://registry.npmjs.org/openai/-/openai-6.33.0.tgz",
@@ -11137,7 +11453,6 @@
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
"integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"entities": "^6.0.0"
@@ -11341,6 +11656,12 @@
"node": ">=4"
}
},
+ "node_modules/platform": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz",
+ "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==",
+ "license": "MIT"
+ },
"node_modules/postcss": {
"version": "8.5.6",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
@@ -11442,6 +11763,30 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/protobufjs": {
+ "version": "7.5.7",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.7.tgz",
+ "integrity": "sha512-NGnrxS/nLKUo5nkbVQxlC71sB4hdfImdYIbFeSCidxtwATx0AHRPcANSLd0q5Bb2BkoSWo2iisQhGg5/r+ihbA==",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.5",
+ "@protobufjs/eventemitter": "^1.1.0",
+ "@protobufjs/fetch": "^1.1.0",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/inquire": "^1.1.1",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.1",
+ "@types/node": ">=13.7.0",
+ "long": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
@@ -12007,6 +12352,24 @@
"node": ">=14"
}
},
+ "node_modules/rehype-katex": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/rehype-katex/-/rehype-katex-7.0.1.tgz",
+ "integrity": "sha512-OiM2wrZ/wuhKkigASodFoo8wimG3H12LWQaH8qSPVJn9apWKFSH3YOCtbKpBorTVw/eI7cuT21XBbvwEswbIOA==",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/katex": "^0.16.0",
+ "hast-util-from-html-isomorphic": "^2.0.0",
+ "hast-util-to-text": "^4.0.0",
+ "katex": "^0.16.0",
+ "unist-util-visit-parents": "^6.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/remark-gfm": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz",
@@ -12025,6 +12388,21 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/remark-math": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/remark-math/-/remark-math-6.0.0.tgz",
+ "integrity": "sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA==",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "mdast-util-math": "^3.0.0",
+ "micromark-extension-math": "^3.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/remark-parse": {
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz",
@@ -13531,7 +13909,6 @@
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
- "dev": true,
"license": "MIT"
},
"node_modules/unicorn-magic": {
@@ -13582,6 +13959,19 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/unist-util-find-after": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz",
+ "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-is": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/unist-util-is": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz",
@@ -13608,6 +13998,19 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/unist-util-remove-position": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz",
+ "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-visit": "^5.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/unist-util-stringify-position": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz",
@@ -13755,6 +14158,19 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/vfile-location": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz",
+ "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/vfile-message": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz",
@@ -13994,6 +14410,15 @@
"node": ">=18"
}
},
+ "node_modules/web-namespaces": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz",
+ "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/webidl-conversions": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
diff --git a/package.json b/package.json
index 8ab1ffb..013f336 100644
--- a/package.json
+++ b/package.json
@@ -19,6 +19,8 @@
"fft.js": "^4.0.4",
"idb": "^8.0.3",
"jszip": "^3.10.1",
+ "katex": "^0.16.46",
+ "onnxruntime-web": "^1.26.0",
"openai": "^6.33.0",
"react": "^19.1.0",
"react-dom": "^19.1.0",
@@ -26,7 +28,9 @@
"react-markdown": "^10.1.0",
"react-syntax-highlighter": "^15.6.1",
"reflect-metadata": "^0.2.2",
+ "rehype-katex": "^7.0.1",
"remark-gfm": "^4.0.1",
+ "remark-math": "^6.0.0",
"tone": "^15.1.22",
"vexflow": "^5.0.0",
"zustand": "^5.0.6"
diff --git a/public/chat/welcome_local_llm.md b/public/chat/welcome_local_llm.md
new file mode 100644
index 0000000..724767a
--- /dev/null
+++ b/public/chat/welcome_local_llm.md
@@ -0,0 +1,21 @@
+## Local LLM Mode
+
+Welcome to **K.G.Studio Musician Assistant** in local LLM mode.
+
+- No external API calls are required. Everything runs directly in your browser, with no extra API cost.
+- This mode uses **Gemma 4 E4B** through **LiteRT-LM** with **WebGPU** acceleration.
+- Recommended hardware: a GPU with at least **8 GB VRAM** or a system with at least **16 GB unified RAM**.
+- Performance is more limited than larger cloud-hosted models, especially on harder planning, editing, and multi-step tasks.
+
+### Recommended Workflow
+- Keep requests small and focused.
+- Guide the model step by step toward the final goal.
+- Work on smaller music regions instead of large full-song edits.
+- Prefer simpler music arrangements when possible.
+- Start a new conversation for each standalone task.
+
+### Use an External LLM Instead
+- If you want a larger cloud or self-hosted model, open **Settings -> General -> LLM Provider** and switch away from **Local LLM (Browser)**.
+- For a cloud model, you can use **OpenAI**, or choose **OpenAI Compatible** and enter a provider such as OpenRouter.
+- For a self-hosted model, choose **OpenAI Compatible** and enter your server's **Base URL** and **Model**.
+- After switching providers, start a new conversation so the chat uses the new model cleanly.
diff --git a/public/config.json b/public/config.json
index df321dc..88226c1 100644
--- a/public/config.json
+++ b/public/config.json
@@ -1,7 +1,7 @@
{
"general": {
"language": "en_us",
- "llm_provider": "openai",
+ "llm_provider": "local_browser",
"persist_api_keys_non_localhost": false,
"openai": {
"api_key": "",
@@ -25,6 +25,9 @@
"api_key": "",
"base_url": "",
"model": ""
+ },
+ "local_browser": {
+ "context_length": 32768
},
"soundfont": {
"base_url": "https://cdn.jsdelivr.net/npm/soundfont-for-samplers/FluidR3_GM/"
@@ -66,7 +69,7 @@
}
},
"editor": {
- "playhead_update_frequency": 10,
+ "playhead_update_frequency": 30,
"spectrogram_height_resolution": 3
},
"chatbox": {
diff --git a/public/mediapipe/genai_bundle.mjs b/public/mediapipe/genai_bundle.mjs
new file mode 100644
index 0000000..50e2f1a
--- /dev/null
+++ b/public/mediapipe/genai_bundle.mjs
@@ -0,0 +1,2 @@
+var t="undefined"!=typeof self?self:{};function e(e,n){t:{for(var r=["CLOSURE_FLAGS"],i=t,o=0;o>6|192;else{if(e>=55296&&e<=57343){if(e<=56319&&i=56320&&o<=57343){e=1024*(e-55296)+o-56320+65536,r[n++]=e>>18|240,r[n++]=e>>12&63|128,r[n++]=e>>6&63|128,r[n++]=63&e|128;continue}i--}e=65533}r[n++]=e>>12|224,r[n++]=e>>6&63|128}r[n++]=63&e|128}}t=n===r.length?r:r.subarray(0,n)}return t}var o,s=e(610401301,!1),a=e(748402147,!0);function u(){var e=t.navigator;return e&&(e=e.userAgent)?e:""}const c=t.navigator;o=c&&c.userAgentData||null;const l={};let h=null;function f(t){const e=t.length;let n=3*e/4;n%3?n=Math.floor(n):-1!="=.".indexOf(t[e-1])&&(n=-1!="=.".indexOf(t[e-2])?n-2:n-1);const r=new Uint8Array(n);let i=0;return function(t,e){function n(e){for(;r>4),64!=i&&(e(r<<4&240|i>>2),64!=o&&e(i<<6&192|o))}}(t,(function(t){r[i++]=t})),i!==n?r.subarray(0,i):r}function d(){if(!h){h={};var t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split(""),e=["+/=","+/","-_=","-_.","-_"];for(let n=0;n<5;n++){const r=t.concat(e[n].split(""));l[n]=r;for(let t=0;t0)&&(-1!=u().indexOf("Trident")||-1!=u().indexOf("MSIE")))&&"function"==typeof btoa;const g=/[-_.]/g,_={"-":"+",_:"/",".":"="};function y(t){return _[t]||""}function w(t){if(!m)return f(t);t=g.test(t)?t.replace(g,y):t,t=atob(t);const e=new Uint8Array(t.length);for(let n=0;n=n||(r[e]=i+1,L(e=Error(),"incident"),function(e){t.setTimeout((()=>{throw e}),0)}(e))}}function j(){return"function"==typeof BigInt}var k="function"==typeof Symbol&&"symbol"==typeof Symbol();function U(t,e,n=!1){return"function"==typeof Symbol&&"symbol"==typeof Symbol()?n&&Symbol.for&&t?Symbol.for(t):null!=t?Symbol(t):Symbol():e}var x=U("jas",void 0,!0),B=U(void 0,"1oa"),N=U(void 0,"0ubsb"),F=U(void 0,"0actk"),R=U("m_m","pa",!0);const D={ha:{value:0,configurable:!0,writable:!0,enumerable:!1}},C=Object.defineProperties,M=k?x:"ha";var V;const G=[];function z(t,e){k||M in t||C(t,D),t[M]|=e}function W(t,e){k||M in t||C(t,D),t[M]=e}W(G,7),V=Object.freeze(G);var H={};function $(t,e){return void 0===e?t.i!==q&&!!(2&(0|t.m[M])):!!(2&e)&&t.i!==q}const q={};var K=Object.freeze({});function Y(t){return t.oa=!0,t}var J=Y((t=>"number"==typeof t)),X=Y((t=>"string"==typeof t)),Q=Y((t=>"boolean"==typeof t)),Z="function"==typeof t.BigInt&&"bigint"==typeof t.BigInt(0),tt=Y((t=>Z?t>=nt&&t<=it:"-"===t[0]?ot(t,et):ot(t,rt)));const et=Number.MIN_SAFE_INTEGER.toString(),nt=Z?BigInt(Number.MIN_SAFE_INTEGER):void 0,rt=Number.MAX_SAFE_INTEGER.toString(),it=Z?BigInt(Number.MAX_SAFE_INTEGER):void 0;function ot(t,e){if(t.length>e.length)return!1;if(t.lengthi)return!1;if(r>>0;at=e,ut=(t-e)/4294967296>>>0}function lt(t){if(t<0){ct(-t);const[e,n]=mt(at,ut);at=e>>>0,ut=n>>>0}else ct(t)}function ht(t,e){const n=4294967296*e+(t>>>0);return Number.isSafeInteger(n)?n:ft(t,e)}function ft(t,e){if(t>>>=0,(e>>>=0)<=2097151)var n=""+(4294967296*e+t);else j()?n=""+(BigInt(e)<>>24|e<<8))+6710656*(e=e>>16&65535),n+=8147497*e,e*=2,t>=1e7&&(n+=t/1e7>>>0,t%=1e7),n>=1e7&&(e+=n/1e7>>>0,n%=1e7),n=e+dt(n)+dt(t));return n}function dt(t){return t=String(t),"0000000".slice(t.length)+t}function pt(t){if(t.length<16)lt(Number(t));else if(j())t=BigInt(t),at=Number(t&BigInt(4294967295))>>>0,ut=Number(t>>BigInt(32)&BigInt(4294967295));else{const e=+("-"===t[0]);ut=at=0;const n=t.length;for(let r=e,i=(n-e)%6+e;i<=n;r=i,i+=6){const e=Number(t.slice(r,i));ut*=1e6,at=1e6*at+e,at>=4294967296&&(ut+=Math.trunc(at/4294967296),ut>>>=0,at>>>=0)}if(e){const[t,e]=mt(at,ut);at=t,ut=e}}}function mt(t,e){return e=~e,t?t=1+~t:e+=1,[t,e]}function gt(t){return Array.prototype.slice.call(t)}const _t="function"==typeof BigInt?BigInt.asIntN:void 0,yt="function"==typeof BigInt?BigInt.asUintN:void 0,wt=Number.isSafeInteger,vt=Number.isFinite,bt=Math.trunc;function St(t){if(null!=t&&"number"!=typeof t)throw Error(`Value of float/double field must be a number, found ${typeof t}: ${t}`);return t}function Et(t){return null==t||"number"==typeof t?t:"NaN"===t||"Infinity"===t||"-Infinity"===t?Number(t):void 0}function At(t){if(null!=t&&"boolean"!=typeof t){var e=typeof t;throw Error(`Expected boolean but got ${"object"!=e?e:t?Array.isArray(t)?"array":e:"null"}: ${t}`)}return t}function It(t){return null==t||"boolean"==typeof t?t:"number"==typeof t?!!t:void 0}const Tt=/^-?([1-9][0-9]*|0)(\.[0-9]+)?$/;function Lt(t){switch(typeof t){case"bigint":return!0;case"number":return vt(t);case"string":return Tt.test(t);default:return!1}}function Pt(t){if("number"!=typeof t)throw P("int32");if(!vt(t))throw P("int32");return 0|t}function Ot(t){return null==t?t:Pt(t)}function jt(t){if(null==t)return t;if("string"==typeof t&&t)t=+t;else if("number"!=typeof t)return;return vt(t)?0|t:void 0}function kt(t){if(null==t)return t;if("string"==typeof t&&t)t=+t;else if("number"!=typeof t)return;return vt(t)?t>>>0:void 0}function Ut(t){return null==t||"string"==typeof t?t:void 0}function xt(t,e,n){if(null!=t&&t[R]===H)return t;if(Array.isArray(t)){var r=0|t[M];return(n=r|32&n|2&n)!==r&&W(t,n),new e(t)}}function Bt(t,e,n,r){var i=void 0!==r;r=!!r;const o=[];var s=t.length;let a,u=4294967295,c=!1;const l=!!(64&e),h=l?128&e?0:-1:void 0;for(1&e||(a=s&&t[s-1],null!=a&&"object"==typeof a&&a.constructor===Object?u=--s:a=void 0,!l||128&e||i||(c=!0,u=u-h+h)),e=void 0,i=0;i=u){const t=i-h;(e??={})[t]=s}else o[i]=s}if(a)for(let i in a){if(null==(t=a[i])||null==(t=n(t,r)))continue;let c;s=+i,l&&!Number.isNaN(s)&&(c=s+h)>2];o=n[(3&o)<<4|s>>4],s=n[(15&s)<<2|a>>6],a=n[63&a],r[c++]=u+o+s+a}switch(u=0,a=i,e.length-t){case 2:a=n[(15&(u=e[t+1]))<<2]||i;case 1:e=e[t],r[c]=n[e>>2]+n[(3&e)<<4|u>>4]+a+i}e=r.join("")}t=t.i=e}return t}return}return t}let Ft,Rt;function Dt(t){return Bt(t=t.m,0|t[M],Nt)}function Ct(t,e,n,r=0){if(null==t){var i=32;n?(t=[n],i|=128):t=[],e&&(i=-16760833&i|(1023&e)<<14)}else{if(!Array.isArray(t))throw Error("narr");if(i=0|t[M],a&&1&i)throw Error("rfarr");if(2048&i&&!(2&i)&&function(){if(a)throw Error("carr");O(F,5)}(),256&i)throw Error("farr");if(64&i)return(i|r)!==i&&W(t,i|r),t;if(n&&(i|=128,n!==t[0]))throw Error("mid");t:{i|=64;var o=(n=t).length;if(o){var s=o-1;const t=n[s];if(null!=t&&"object"==typeof t&&t.constructor===Object){if((s-=e=128&i?0:-1)>=1024)throw Error("pvtlmt");for(var u in t)(o=+u)1024)throw Error("spvt");i=-16760833&i|(1023&u)<<14}}}return W(t,64|i|r),t}function Mt(t,e){if("object"!=typeof t)return t;if(Array.isArray(t)){var n=0|t[M];return 0===t.length&&1&n?t=void 0:2&n||(!e||4096&n||16&n?t=Gt(t,n,!1,e&&!(16&n)):(z(t,34),4&n&&Object.freeze(t))),t}return null!=t&&t[R]===H?$(t,n=0|(e=t.m)[M])?t:$t(t,e,n)?Vt(t,e):Gt(e,n):t instanceof E?t:void 0}function Vt(t,e,n){return t=new t.constructor(e),n&&(t.i=q),t.o=q,t}function Gt(t,e,n,r){return r??=!!(34&e),t=Bt(t,e,Mt,r),r=32,n&&(r|=2),W(t,e=16769217&e|r),t}function zt(t){if(t.i!==q)return!1;var e=t.m;return z(e=Gt(e,0|e[M]),2048),t.m=e,t.i=void 0,t.o=void 0,!0}function Wt(t){if(!zt(t)&&$(t,0|t.m[M]))throw Error()}function Ht(t,e){void 0===e&&(e=0|t[M]),32&e&&!(4096&e)&&W(t,4096|e)}function $t(t,e,n){return!!(2&n)||!(!(32&n)||4096&n)&&(W(e,2|n),t.i=q,!0)}function qt(t,e,n){if(null!==(t=Kt(t.m,e,void 0,n)))return t}function Kt(t,e,n,r){if(-1===e)return null;const i=e+(n?0:-1),o=t.length-1;let s,a;if(!(o<1+(n?0:-1))){if(i>=o)if(s=t[o],null!=s&&"object"==typeof s&&s.constructor===Object)n=s[e],a=!0;else{if(i!==o)return;n=s}else n=t[i];if(r&&null!=n){if(null==(r=r(n)))return r;if(!Object.is(r,n))return a?s[e]=r:t[i]=r,r}return n}}function Yt(t,e,n){Wt(t),Jt(t=t.m,0|t[M],e,n)}function Jt(t,e,n,r,i){const o=n+(i?0:-1);var s=t.length-1;if(s>=1+(i?0:-1)&&o>=s){const i=t[s];if(null!=i&&"object"==typeof i&&i.constructor===Object)return i[n]=r,e}return o<=s?(t[o]=r,e):(void 0!==r&&(n>=(s=(e??=0|t[M])>>14&1023||536870912)?null!=r&&(t[s+(i?0:-1)]={[n]:r}):t[o]=r),e)}function Xt(t,e,n,r,i){let o=t.m,s=0|o[M];r=$(t,s)?1:r,i=!!i||3===r,2===r&&zt(t)&&(o=t.m,s=0|o[M]);let a=(t=Zt(o,e))===V?7:0|t[M],u=te(a,s);var c=!(4&u);if(c){4&u&&(t=gt(t),a=0,u=ce(u,s),s=Jt(o,s,e,t));let r=0,i=0;for(;r{const r=xt(t,n,e);return i=r!==t&&null!=r,r}))))return i&&!$(r)&&Ht(t,e),r}(r,i,e,n),null==e)return e;if(i=0|r[M],!$(t,i)){var o,s=e;const a=s.m,u=0|a[M];(o=$(s,u)?$t(s,a,u)?Vt(s,a,!0):new s.constructor(Gt(a,u,!1)):s)!==e&&(zt(t)&&(r=t.m,i=0|r[M]),i=Jt(r,i,n,e=o),Ht(r,i))}return e}function ae(t){return null==t&&(t=void 0),t}function ue(t,e,n){return Yt(t,e,n=ae(n)),n&&!$(n)&&Ht(t.m),t}function ce(t,e){return-273&(2&e?2|t:-3&t)}function le(t,e,n,r){var i=r;Wt(t);var o=r=t.m,s=0|r[M];const a=$(t,s)?1:2;2===a&&zt(t)&&(s=0|(o=t.m)[M]);let u=(t=Zt(o,e))===V?7:0|t[M];var c=te(u,s);const l=!(4&c);if(l){var h=t,f=s;const e=!!(2&c);e&&(f|=2);let r=!e,i=!0,o=0,a=0;for(;o>>=0}Yt(t,e,n)}function pe(t,e,n){if(null!=n&&"string"!=typeof n)throw Error();re(t,e,n,"")}function me(t,e,n){if(Wt(t),e=(t=Xt(t,e,Ut,2,!0)).push,"string"!=typeof n)throw Error();e.call(t,n)}var ge=class{constructor(t,e,n){if(this.buffer=t,n&&!e)throw Error()}};function _e(t){if("string"==typeof t)return new ge(w(t),!0);if(Array.isArray(t))return new ge(new Uint8Array(t),!0);if(t.constructor===Uint8Array)return new ge(t,!1);if(t.constructor===ArrayBuffer)return t=new Uint8Array(t),new ge(t,!1);if(t.constructor===E){T(b);var e=t.i;return e=(null==(e=null==e||v(e)?e:"string"==typeof e?w(e):null)?e:t.i=e)||new Uint8Array(0),new ge(e,!0,t)}if(t instanceof Uint8Array)return t=t.constructor===Uint8Array?t:new Uint8Array(t.buffer,t.byteOffset,t.byteLength),new ge(t,!1);throw Error()}function ye(t){return t?/^\d+$/.test(t)?(pt(t),new we(at,ut)):null:ve||=new we(0,0)}var we=class{constructor(t,e){this.j=t>>>0,this.i=e>>>0}};let ve;function be(t){return t?/^-?\d+$/.test(t)?(pt(t),new Se(at,ut)):null:Ee||=new Se(0,0)}var Se=class{constructor(t,e){this.j=t>>>0,this.i=e>>>0}};let Ee;function Ae(t,e,n){for(;n>0||e>127;)t.i.push(127&e|128),e=(e>>>7|n<<25)>>>0,n>>>=7;t.i.push(e)}function Ie(t,e){for(;e>127;)t.i.push(127&e|128),e>>>=7;t.i.push(e)}function Te(t,e){if(e>=0)Ie(t,e);else{for(let n=0;n<9;n++)t.i.push(127&e|128),e>>=7;t.i.push(1)}}function Le(t,e){0!==e.length&&(t.l.push(e),t.j+=e.length)}function Pe(t,e,n){Ie(t.i,8*e+n)}function Oe(t,e){return Pe(t,e,2),e=t.i.end(),Le(t,e),e.push(t.j),e}function je(t,e){var n=e.pop();for(n=t.j+t.i.length()-n;n>127;)e.push(127&n|128),n>>>=7,t.j++;e.push(n),t.j++}function ke(t,e,n){Pe(t,e,2),Ie(t.i,n.length),Le(t,t.i.end()),Le(t,n)}function Ue(){const t=class{constructor(){throw Error()}};return Object.setPrototypeOf(t,t.prototype),t}var xe=Ue(),Be=Ue(),Ne=Ue(),Fe=Ue(),Re=Ue(),De=Ue(),Ce=Ue(),Me=Ue(),Ve=Ue(),Ge=Ue(),ze=class{constructor(t,e){this.m=Ct(t,e,void 0,2048)}toJSON(){return Dt(this)}};ze.prototype[R]=H,ze.prototype.toString=function(){return this.m.toString()};var We=class{constructor(t,e){this.i=t,t=xe,this.j=!!t&&e===t||!1}};function He(t,e,n,r,i){null!=(e=Ze(e,r))&&(n=Oe(t,n),i(e,t),je(t,n))}const $e=new We(He,xe),qe=new We(He,xe);var Ke=Symbol(),Ye=Symbol();let Je,Xe;function Qe(t){var e=tn,n=en,r=t[Ke];if(r)return r;(r={}).na=t,r.W=function(t){switch(typeof t){case"boolean":return Ft||=[0,void 0,!0];case"number":return t>0?void 0:0===t?Rt||=[0,void 0]:[-t,void 0];case"string":return[0,t];case"object":return t}}(t[0]);var i=t[1];let o=1;i&&i.constructor===Object&&(r.ca=i,"function"==typeof(i=t[++o])&&(r.ia=!0,Je??=i,Xe??=t[o+1],i=t[o+=2]));const s={};for(;i&&Array.isArray(i)&&i.length&&"number"==typeof i[0]&&i[0]>0;){for(var a=0;as(t,e,n,o||=Qe(r).W,i||=nn(r))}function nn(t){let e=t[Ye];if(!e){const n=Qe(t);e=(t,e)=>rn(t,e,n),t[Ye]=e}return e}function rn(t,e,n){!function(t,e,n){const r=128&e?0:-1,i=t.length;var o;(o=!!i)&&(o=null!=(o=t[i-1])&&"object"==typeof o&&o.constructor===Object);const s=i+(o?-1:0);for(e=128&e?1:0;e{if(null!=r){var i=function(t,e){var n=t[e];if(n)return n;if((n=t.ca)&&(n=n[e])){var r=(n=Array.isArray(n)?n[0]instanceof We?n:[qe,n]:[n,void 0])[0].i;if(n=n[1]){const e=nn(n),i=Qe(n).W;n=t.ia?Xe(i,e):(t,n,o)=>r(t,n,o,i,e)}else n=r;return t[e]=n}}(n,t);i?i(e,r,t):t<500||O(N,3)}}))}var on,sn=0,an=sn;if(X(an)){if(!/^\s*(?:-?[1-9]\d*|0)?\s*$/.test(an))throw Error(String(an))}else if((on=J(an))&&(on=!Number.isSafeInteger(an)),on)throw Error(String(an));function un(t,e){if(Array.isArray(e)){var n=0|e[M];if(4&n)return e;for(var r=0,i=0;r>>0&255),t.i.push(e>>>8&255),t.i.push(e>>>16&255),t.i.push(e>>>24&255))}function hn(t,e,n){null!=(e=jt(e))&&null!=e&&(Pe(t,n,0),Te(t.i,e))}function fn(t,e,n){null!=(e=It(e))&&(Pe(t,n,0),t.i.i.push(e?1:0))}function dn(t,e,n){null!=(e=Ut(e))&&ke(t,n,i(e))}function pn(t,e,n,r,i){null!=(e=Ze(e,r))&&(n=Oe(t,n),i(e,t),je(t,n))}function mn(t,e,n){null!=(e=kt(e))&&null!=e&&(Pe(t,n,0),Ie(t.i,e))}function gn(t,e,n){null!=(e=jt(e))&&(e=parseInt(e,10),Pe(t,n,0),Te(t.i,e))}Z||(sn=Q(sn)?sn?"1":"0":X(sn)?sn.trim()||"0":String(sn));var _n,yn=cn(ln,Me),wn=cn(ln,Me),vn=cn((function(t,e,n){if(e=function(t){if(null==t)return t;var e=typeof t;if("bigint"===e)return String(_t(64,t));if(Lt(t)){if("string"===e){if(e=bt(Number(t)),wt(e))t=String(e);else if(-1!==(e=t.indexOf("."))&&(t=t.substring(0,e)),e=t.length,!("-"===t[0]?e<20||20===e&&t<="-9223372036854775808":e<19||19===e&&t<="9223372036854775807"))if(pt(t),t=at,2147483648&(e=ut))if(j())t=""+(BigInt(0|e)<>>0));else{const[n,r]=mt(t,e);t="-"+ft(n,r)}else t=ft(t,e);return t}if("number"===e){if(t=bt(t),!wt(t)){lt(t),e=at;var n=ut;(t=2147483648&n)&&(n=~n>>>0,0==(e=1+~e>>>0)&&(n=n+1>>>0)),t="number"==typeof(e=ht(e,n))?t?-e:e:t?"-"+e:e}return t}}}(e),null!=e){if("string"==typeof e)be(e);if(null!=e)switch(Pe(t,n,0),typeof e){case"number":t=t.i,lt(e),Ae(t,at,ut);break;case"bigint":n=BigInt.asUintN(64,e),n=new Se(Number(n&BigInt(4294967295)),Number(n>>BigInt(32))),Ae(t.i,n.j,n.i);break;default:n=be(e),Ae(t.i,n.j,n.i)}}}),De),bn=cn((function(t,e,n){if(e=function(t){if(null==t)return t;var e=typeof t;if("bigint"===e)return String(yt(64,t));if(Lt(t)){if("string"===e)return e=bt(Number(t)),wt(e)&&e>=0?t=String(e):(-1!==(e=t.indexOf("."))&&(t=t.substring(0,e)),(e="-"!==t[0]&&((e=t.length)<20||20===e&&t<="18446744073709551615"))||(pt(t),t=ft(at,ut))),t;if("number"===e)return(t=bt(t))>=0&&wt(t)||(lt(t),t=ht(at,ut)),t}}(e),null!=e){if("string"==typeof e)ye(e);if(null!=e)switch(Pe(t,n,0),typeof e){case"number":t=t.i,lt(e),Ae(t,at,ut);break;case"bigint":n=BigInt.asUintN(64,e),n=new we(Number(n&BigInt(4294967295)),Number(n>>BigInt(32))),Ae(t.i,n.j,n.i);break;default:n=ye(e),Ae(t.i,n.j,n.i)}}}),Ce),Sn=cn(hn,Fe);_n=new We((function(t,e,n){if(null!=(e=un(jt,e))&&e.length){n=Oe(t,n);for(let n=0;nt;t=Gn.createPolicy("goog#html",{createHTML:e,createScript:e,createScriptURL:e})}catch(t){}return t}()),t=(e=Vn)?e.createScriptURL(t):t,new class{constructor(t){this.i=t}toString(){return this.i+""}}(t)}function Wn(t,...e){if(0===e.length)return zn(t[0]);let n=t[0];for(let r=0;r{if(e.cache.length>0)r.enqueue(e.cache.shift());else{var{value:i,done:o}=await t.read();i&&(n.active&&n.cache.push(i),e.active&&r.enqueue(i)),o&&r.close()}})),await i},cancel(){e.active=!1,e.cache.length=0,n.active||t.cancel()}})}var n={cache:[],active:!0};const r={cache:[],active:!0};let i=Promise.resolve();const o=e(n,r);return n=e(r,n),[o.getReader(),n.getReader()]}async function ar(t,e){const n=new Uint8Array(e);let r=0;for(;r{const e=(new TextEncoder).encode("TFL3").length;return t=await ar(t,e+4),"TFL3"===new TextDecoder("utf-8").decode(t.subarray(4,e+4))}],[1,async t=>80===(t=await ar(t,6))[4]&&75===t[5]]];function cr(){var t=navigator;return"undefined"!=typeof OffscreenCanvas&&(!function(t=navigator){return(t=t.userAgent).includes("Safari")&&!t.includes("Chrome")}(t)||!!((t=t.userAgent.match(/Version\/([\d]+).*Safari/))&&t.length>=1&&Number(t[1])>=17))}async function lr(t){if("function"!=typeof importScripts){const e=document.createElement("script");return e.src=t.toString(),e.crossOrigin="anonymous",new Promise(((t,n)=>{e.addEventListener("load",(()=>{t()}),!1),e.addEventListener("error",(t=>{n(t)}),!1),document.body.appendChild(e)}))}try{importScripts(t.toString())}catch(e){if(!(e instanceof TypeError))throw e;await self.import(t.toString())}}function hr(t,e,n){t.o||console.error("No wasm multistream support detected: ensure dependency inclusion of :gl_graph_runner_internal_multi_input target"),n(e=t.h.stringToNewUTF8(e)),t.h._free(e)}function fr(t,e,n){t.o||console.error("No wasm multistream support detected: ensure dependency inclusion of :gl_graph_runner_internal_multi_input target");const r=new Uint32Array(e.length);for(let n=0;n>2),n(e);for(const e of r)t.h._free(e);t.h._free(e)}function dr(t,e,n){t.h.simpleListeners=t.h.simpleListeners||{},t.h.simpleListeners[e]=n}function pr(t,e,n){let r=[];t.h.simpleListeners=t.h.simpleListeners||{},t.h.simpleListeners[e]=(t,e,i)=>{e?(n(r,i),r=[]):r.push(t)}}const mr=(gr=class{constructor(t,e){this.l=!0,this.h=t,this.i=null,this.j=0,this.o="function"==typeof this.h._addIntToInputStream,void 0!==e?this.h.canvas=e:cr()?this.h.canvas=new OffscreenCanvas(1,1):(console.warn("OffscreenCanvas not supported and GraphRunner constructor glCanvas parameter is undefined. Creating backup canvas."),this.h.canvas=document.createElement("canvas"))}async initializeGraph(t){const e=await(await fetch(t)).arrayBuffer();t=!(t.endsWith(".pbtxt")||t.endsWith(".textproto")),this.setGraph(new Uint8Array(e),t)}setGraphFromString(t){this.setGraph((new TextEncoder).encode(t),!1)}setGraph(t,e){const n=t.length,r=this.h._malloc(n);this.h.HEAPU8.set(t,r),e?this.h._changeBinaryGraph(n,r):this.h._changeTextGraph(n,r),this.h._free(r)}configureAudio(t,e,n,r,i){this.h._configureAudio||console.warn('Attempting to use configureAudio without support for input audio. Is build dep ":gl_graph_runner_audio" missing?'),hr(this,r||"input_audio",(r=>{hr(this,i=i||"audio_header",(i=>{this.h._configureAudio(r,i,t,e??0,n)}))}))}setAutoResizeCanvas(t){this.l=t}setAutoRenderToScreen(t){this.h._setAutoRenderToScreen(t)}setGpuBufferVerticalFlip(t){this.h.gpuOriginForWebTexturesIsBottomLeft=t}attachErrorListener(t){this.h.errorListener=t}attachEmptyPacketListener(t,e){this.h.emptyPacketListeners=this.h.emptyPacketListeners||{},this.h.emptyPacketListeners[t]=e}addAudioToStream(t,e,n){this.addAudioToStreamWithShape(t,0,0,e,n)}addAudioToStreamWithShape(t,e,n,r,i){const o=4*t.length;this.j!==o&&(this.i&&this.h._free(this.i),this.i=this.h._malloc(o),this.j=o),this.h.HEAPF32.set(t,this.i/4),hr(this,r,(t=>{this.h._addAudioToInputStream(this.i,e,n,t,i)}))}addGpuBufferToStream(t,e,n){hr(this,e,(e=>{if(!this.h.canvas)throw Error("No OpenGL canvas configured.");e?this.h._bindTextureToStream(e):this.h._bindTextureToCanvas();const r=this.h.canvas.getContext("webgl2")||this.h.canvas.getContext("webgl");if(!r)throw Error("Failed to obtain WebGL context from the provided canvas. `getContext()` should only be invoked with `webgl` or `webgl2`.");this.h.gpuOriginForWebTexturesIsBottomLeft&&r.pixelStorei(r.UNPACK_FLIP_Y_WEBGL,!0),r.texImage2D(r.TEXTURE_2D,0,r.RGBA,r.RGBA,r.UNSIGNED_BYTE,t),this.h.gpuOriginForWebTexturesIsBottomLeft&&r.pixelStorei(r.UNPACK_FLIP_Y_WEBGL,!1);const[i,o]=void 0!==t.videoWidth?[t.videoWidth,t.videoHeight]:void 0!==t.naturalWidth?[t.naturalWidth,t.naturalHeight]:void 0!==t.displayWidth?[t.displayWidth,t.displayHeight]:[t.width,t.height];!this.l||i===this.h.canvas.width&&o===this.h.canvas.height||(this.h.canvas.width=i,this.h.canvas.height=o);const[s,a]=[i,o];this.h._addBoundTextureToStream(e,s,a,n)}))}addBoolToStream(t,e,n){hr(this,e,(e=>{this.h._addBoolToInputStream(t,e,n)}))}addDoubleToStream(t,e,n){hr(this,e,(e=>{this.h._addDoubleToInputStream(t,e,n)}))}addFloatToStream(t,e,n){hr(this,e,(e=>{this.h._addFloatToInputStream(t,e,n)}))}addIntToStream(t,e,n){hr(this,e,(e=>{this.h._addIntToInputStream(t,e,n)}))}addUintToStream(t,e,n){hr(this,e,(e=>{this.h._addUintToInputStream(t,e,n)}))}addStringToStream(t,e,n){hr(this,e,(e=>{hr(this,t,(t=>{this.h._addStringToInputStream(t,e,n)}))}))}addStringRecordToStream(t,e,n){hr(this,e,(e=>{fr(this,Object.keys(t),(r=>{fr(this,Object.values(t),(i=>{this.h._addFlatHashMapToInputStream(r,i,Object.keys(t).length,e,n)}))}))}))}addProtoToStream(t,e,n,r){hr(this,n,(n=>{hr(this,e,(e=>{const i=this.h._malloc(t.length);this.h.HEAPU8.set(t,i),this.h._addProtoToInputStream(i,t.length,e,n,r),this.h._free(i)}))}))}addEmptyPacketToStream(t,e){hr(this,t,(t=>{this.h._addEmptyPacketToInputStream(t,e)}))}addBoolVectorToStream(t,e,n){hr(this,e,(e=>{const r=this.h._allocateBoolVector(t.length);if(!r)throw Error("Unable to allocate new bool vector on heap.");for(const e of t)this.h._addBoolVectorEntry(r,e);this.h._addBoolVectorToInputStream(r,e,n)}))}addDoubleVectorToStream(t,e,n){hr(this,e,(e=>{const r=this.h._allocateDoubleVector(t.length);if(!r)throw Error("Unable to allocate new double vector on heap.");for(const e of t)this.h._addDoubleVectorEntry(r,e);this.h._addDoubleVectorToInputStream(r,e,n)}))}addFloatVectorToStream(t,e,n){hr(this,e,(e=>{const r=this.h._allocateFloatVector(t.length);if(!r)throw Error("Unable to allocate new float vector on heap.");for(const e of t)this.h._addFloatVectorEntry(r,e);this.h._addFloatVectorToInputStream(r,e,n)}))}addIntVectorToStream(t,e,n){hr(this,e,(e=>{const r=this.h._allocateIntVector(t.length);if(!r)throw Error("Unable to allocate new int vector on heap.");for(const e of t)this.h._addIntVectorEntry(r,e);this.h._addIntVectorToInputStream(r,e,n)}))}addUintVectorToStream(t,e,n){hr(this,e,(e=>{const r=this.h._allocateUintVector(t.length);if(!r)throw Error("Unable to allocate new unsigned int vector on heap.");for(const e of t)this.h._addUintVectorEntry(r,e);this.h._addUintVectorToInputStream(r,e,n)}))}addStringVectorToStream(t,e,n){hr(this,e,(e=>{const r=this.h._allocateStringVector(t.length);if(!r)throw Error("Unable to allocate new string vector on heap.");for(const e of t)hr(this,e,(t=>{this.h._addStringVectorEntry(r,t)}));this.h._addStringVectorToInputStream(r,e,n)}))}addBoolToInputSidePacket(t,e){hr(this,e,(e=>{this.h._addBoolToInputSidePacket(t,e)}))}addDoubleToInputSidePacket(t,e){hr(this,e,(e=>{this.h._addDoubleToInputSidePacket(t,e)}))}addFloatToInputSidePacket(t,e){hr(this,e,(e=>{this.h._addFloatToInputSidePacket(t,e)}))}addIntToInputSidePacket(t,e){hr(this,e,(e=>{this.h._addIntToInputSidePacket(t,e)}))}addUintToInputSidePacket(t,e){hr(this,e,(e=>{this.h._addUintToInputSidePacket(t,e)}))}addStringToInputSidePacket(t,e){hr(this,e,(e=>{hr(this,t,(t=>{this.h._addStringToInputSidePacket(t,e)}))}))}addProtoToInputSidePacket(t,e,n){hr(this,n,(n=>{hr(this,e,(e=>{const r=this.h._malloc(t.length);this.h.HEAPU8.set(t,r),this.h._addProtoToInputSidePacket(r,t.length,e,n),this.h._free(r)}))}))}addBoolVectorToInputSidePacket(t,e){hr(this,e,(e=>{const n=this.h._allocateBoolVector(t.length);if(!n)throw Error("Unable to allocate new bool vector on heap.");for(const e of t)this.h._addBoolVectorEntry(n,e);this.h._addBoolVectorToInputSidePacket(n,e)}))}addDoubleVectorToInputSidePacket(t,e){hr(this,e,(e=>{const n=this.h._allocateDoubleVector(t.length);if(!n)throw Error("Unable to allocate new double vector on heap.");for(const e of t)this.h._addDoubleVectorEntry(n,e);this.h._addDoubleVectorToInputSidePacket(n,e)}))}addFloatVectorToInputSidePacket(t,e){hr(this,e,(e=>{const n=this.h._allocateFloatVector(t.length);if(!n)throw Error("Unable to allocate new float vector on heap.");for(const e of t)this.h._addFloatVectorEntry(n,e);this.h._addFloatVectorToInputSidePacket(n,e)}))}addIntVectorToInputSidePacket(t,e){hr(this,e,(e=>{const n=this.h._allocateIntVector(t.length);if(!n)throw Error("Unable to allocate new int vector on heap.");for(const e of t)this.h._addIntVectorEntry(n,e);this.h._addIntVectorToInputSidePacket(n,e)}))}addUintVectorToInputSidePacket(t,e){hr(this,e,(e=>{const n=this.h._allocateUintVector(t.length);if(!n)throw Error("Unable to allocate new unsigned int vector on heap.");for(const e of t)this.h._addUintVectorEntry(n,e);this.h._addUintVectorToInputSidePacket(n,e)}))}addStringVectorToInputSidePacket(t,e){hr(this,e,(e=>{const n=this.h._allocateStringVector(t.length);if(!n)throw Error("Unable to allocate new string vector on heap.");for(const e of t)hr(this,e,(t=>{this.h._addStringVectorEntry(n,t)}));this.h._addStringVectorToInputSidePacket(n,e)}))}attachBoolListener(t,e){dr(this,t,e),hr(this,t,(t=>{this.h._attachBoolListener(t)}))}attachBoolVectorListener(t,e){pr(this,t,e),hr(this,t,(t=>{this.h._attachBoolVectorListener(t)}))}attachIntListener(t,e){dr(this,t,e),hr(this,t,(t=>{this.h._attachIntListener(t)}))}attachIntVectorListener(t,e){pr(this,t,e),hr(this,t,(t=>{this.h._attachIntVectorListener(t)}))}attachUintListener(t,e){dr(this,t,e),hr(this,t,(t=>{this.h._attachUintListener(t)}))}attachUintVectorListener(t,e){pr(this,t,e),hr(this,t,(t=>{this.h._attachUintVectorListener(t)}))}attachDoubleListener(t,e){dr(this,t,e),hr(this,t,(t=>{this.h._attachDoubleListener(t)}))}attachDoubleVectorListener(t,e){pr(this,t,e),hr(this,t,(t=>{this.h._attachDoubleVectorListener(t)}))}attachFloatListener(t,e){dr(this,t,e),hr(this,t,(t=>{this.h._attachFloatListener(t)}))}attachFloatVectorListener(t,e){pr(this,t,e),hr(this,t,(t=>{this.h._attachFloatVectorListener(t)}))}attachStringListener(t,e){dr(this,t,e),hr(this,t,(t=>{this.h._attachStringListener(t)}))}attachStringVectorListener(t,e){pr(this,t,e),hr(this,t,(t=>{this.h._attachStringVectorListener(t)}))}attachProtoListener(t,e,n){dr(this,t,e),hr(this,t,(t=>{this.h._attachProtoListener(t,n||!1)}))}attachProtoVectorListener(t,e,n){pr(this,t,e),hr(this,t,(t=>{this.h._attachProtoVectorListener(t,n||!1)}))}attachAudioListener(t,e,n){this.h._attachAudioListener||console.warn('Attempting to use attachAudioListener without support for output audio. Is build dep ":gl_graph_runner_audio_out" missing?'),dr(this,t,((t,n)=>{t=new Float32Array(t.buffer,t.byteOffset,t.length/4),e(t,n)})),hr(this,t,(t=>{this.h._attachAudioListener(t,n||!1)}))}finishProcessing(){this.h._waitUntilIdle()}closeGraph(){this.h._closeGraph(),this.h.simpleListeners=void 0,this.h.emptyPacketListeners=void 0}},class extends gr{ka(){this.h._registerModelResourcesGraphService()}});var gr;async function _r(t,e){const n=await(async(t,e,n)=>{var r=ri;if(t&&await lr(t),!self.ModuleFactory)throw Error("ModuleFactory not set.");if(e&&(await lr(e),!self.ModuleFactory))throw Error("ModuleFactory not set.");return self.Module&&n&&((t=self.Module).locateFile=n.locateFile,n.mainScriptUrlOrBlob&&(t.mainScriptUrlOrBlob=n.mainScriptUrlOrBlob)),n=await self.ModuleFactory(self.Module||n),self.ModuleFactory=self.Module=void 0,new r(n,null)})(t.wasmLoaderPath,t.assetLoaderPath,{locateFile:e=>e.endsWith(".wasm")?t.wasmBinaryPath.toString():t.assetBinaryPath&&e.endsWith(".data")?t.assetBinaryPath.toString():e});return await n.N(e),n}async function yr(t,e){return _r(t,e)}function wr(t){try{const e=t.J.length;if(1===e)throw Error(t.J[0].message);if(e>1)throw Error("Encountered multiple errors: "+t.J.map((t=>t.message)).join(", "))}finally{t.J=[]}}function vr(t,e){t.I=Math.max(t.I,e)}var br=class{constructor(t){this.j=t,this.J=[],this.I=0,this.j.setAutoRenderToScreen(!1)}setGraph(t,e){this.j.attachErrorListener(((t,e)=>{this.J.push(Error(e))})),this.j.ka(),this.j.setGraph(t,e),wr(this)}finishProcessing(){this.j.finishProcessing(),wr(this)}close(){this.j.closeGraph()}};br.prototype.close=br.prototype.close;var Sr=class extends ze{constructor(t){super(t)}j(){return jt(qt(this,2))??0}};function Er(t,e){ue(t,1,e)}var Ar=class extends ze{constructor(t){super(t)}},Ir=[0,Fn,An,wn,-1,Sn];function Tr(t,e,n,r){if(void 0!==t.data){var i=new Uint8Array(t.data.buffer,e,n);return 1===r&&function(t,e,n){t.i.push([e,n]),t.i.sort(((t,e)=>t[0]-e[0])),e=0;for(const[r,i]of t.i){const t=i;(n=r)<=e&&(e=Math.max(e,n+t))}e===t.length&&(t.data=void 0)}(t,e,n),i}}Sr.prototype.l=Rn(Ir);class Lr{constructor(t){this.i=[],this.data=t,this.length=t.length}}function Pr(t,e){return new jr((async()=>{const{value:e,done:n}=await t.read();return n?void 0:e}),e)}async function Or(t,e,n,r,i){if(2===i)return t.i=[],t.j=()=>Promise.resolve(void 0),setTimeout((()=>{t.l()}),0),Promise.resolve(0);for(;t.size>>0;let s=0;for(let a=0;a=u.length){n-=u.length;continue}const c=Math.min(r,u.length-n);if(void 0===(n=Tr(u,n,c,i)))throw Error("Data has already been released.");if(e.HEAPU8.set(n,o+s),n=0,s+=c,0===(r-=c))break}if(0!==r)throw Error("Data not found.");return Promise.resolve(o)}var jr=class{constructor(t,e){this.i=[],this.j=t,this.l=e}get size(){let t=0;for(let e=0;e>>0,this.o=this.h.HEAPU8,this.i=!!this.j}get offset(){if(!this.i)throw Error("WasmFileReference has been freed.");return this.j}get size(){if(!this.i)throw Error("WasmFileReference has been freed.");return this.l}set(t,e){this.o.set(t,this.j+(e??0))}},Fr=class extends ze{constructor(t){super(t)}};Fr.prototype.j=Rn([0,jn,2,En,An,Ln]);var Rr=class extends ze{constructor(t){super(t)}},Dr=class extends ze{constructor(t){super(t)}},Cr=class extends ze{constructor(t){super(t)}},Mr=class extends ze{constructor(t){super(t)}},Vr=[0,An,-6,1,An,1,[0,Ln,Fn,-2],[0,Ln,wn],Fn,-2,[0,Ln,-1,Fn,wn,Nn,Sn,Tn,-1],1,Ln,An,Sn,-1,[0,Fn,An],Ln,-1,yn,An,-5,yn,-1,[0,Sn,yn],Sn,Tn,[0,Sn,-2],yn,[0,An],[0,An,-4],Tn,Sn,-2,Tn,-1,wn,yn,Tn,An,-1,1,Ln,An],Gr=[0,jn,-2],zr=[0,[4,6],Vr,An,1,In,En,kn,On,Gr,Sn,[0,[0,An,-1,Un,[0,An,[0,An,-1],-1,[0,Fn,-1],Ln],Ln,-2,An,-1],[0,An,-1,Ln],Vr,Ln,An,[0,An],-1],Pn,-3,[0,An,Ln],Vr,[0,Gr,-2],_n];Mr.prototype.j=Rn([0,jn,8,[0,Ln,-6],1,An,1,An,[0,Un,[0,jn,bn,-1,Fn],zr,An],[0,An,Ln,-3],1,Fn,1,zr,1,An,5,Fn,_n,1,Ir,Ln,An,Ln]);var Wr=class extends ze{constructor(t){super(t)}},Hr=class extends ze{constructor(t){super(t)}},$r=[2,4];Hr.prototype.j=Rn([0,$r,An,kn,An,xn,[0,1,jn]]);const qr=function(t){return class extends t{constructor(){super(...arguments),this.P=!1,this.F=this.H=0}M(){if(this.P)throw Error("Cannot process because LLM inference engine is currently loading or processing.");this.P=!0}L(){this.P=!1}async createLlmInferenceEngine(t,e){this.M();try{const n=Pr(t,(()=>{}));await this.h.createLlmInferenceEngine(he(e,2)??512,se(e,Sr,3)?.j()??40,It(qt(e,6))??!1??!1,he(e,7)??0,It(qt(e,8))??!1??!1,((t,e,r)=>Or(n,this.h,t,e,r)))}finally{this.L()}}async ba(t,e){this.M();try{await this.ma(t),await this.h.ccall("CreateLlmInferenceEngineConverted","void",["number","number","boolean"],[he(e,2)??512,se(e,Sr,3)?.j()??40,It(qt(e,6))??!1??!1],{async:!0})}finally{this.L()}}V(){this.M();try{const t=this.h;t.ccall("DeleteLlmInferenceEngine","void",[],[],{async:!1}),this.H&&(t._FreeSession(this.H),this.F===this.H&&(this.F=0),this.H=0),this.F&&(t._FreeSession(this.F),this.F=0)}finally{this.L()}}async R(t,e,n){this.M();try{const r=[],i=this.h;i._userProgressListener=(t,e)=>{t&&r.push(t),n&&n(t,e)};const o=e.l(),s=o.length,a=this.h._malloc(s);this.h.HEAPU8.set(o,a);const u=t.some(Ur),c=t.some(kr);i.ccallNum=i.ccall;const l=await i.ccallNum("MakeSessionForPredict","number",["number","number","boolean","boolean"],[a,s,c,u],{async:!0});e=[];for(const n of t)if("string"==typeof n)hr(this,n,(t=>{i._AddTextQueryChunk(l,t)}));else if(kr(n)){const{image:t,width:r,height:o}=await this.fa(n.imageSource),s="undefined"!=typeof OffscreenCanvas?new OffscreenCanvas(r,o):document.createElement("canvas");s.width=r,s.height=o;const a=s.getContext("2d");a.drawImage(t,0,0);const u=a.getImageData(0,0,r,o),c=this.h._malloc(u.width*u.height*4);this.h.HEAPU8.set(u.data,c),i._AddImageQueryChunk(l,c,u.width,u.height),e.push(c)}else{if(!Ur(n))throw Error("Unsupported PromptPart type in query.");{const t=await this.ea(n.audioSource),r=this.h._malloc(t.audioSamples.byteLength);this.h.HEAPF32.set(t.audioSamples,r/4),i._AddAudioQueryChunk(l,t.audioSampleRateHz,r,t.audioSamples.length),e.push(r)}}await i.ccall("PredictSession","void",["number"],[l],{async:!0}),t=!0,c&&0===this.F&&(this.F=l,t=!1),u&&0===this.H&&(this.H=l,t=!1),t&&i._FreeSession(l);for(const t of e)this.h._free(t);return e.length=0,n&&n("",!0),this.h._free(a),i._userProgressListener=void 0,r.join("")}finally{this.L()}}S(t){this.M();let e=0,n="";for(const r of t)"string"==typeof r?n+=r:kr(r)?e+=260:Ur(r)&&console.warn("sizeInTokens is not yet implemented for audio; audio tokens will not be counted");try{let t;return hr(this,n,(e=>{t=this.h._GetSizeInTokens(e)})),e+t}finally{this.L()}}async ma(t){t=await async function(t){const e=[];for(var n=0;;){const{done:r,value:i}=await t.read();if(r)break;e.push(i),n+=i.length}if(0===e.length)return new Uint8Array(0);if(1===e.length)return e[0];t=new Uint8Array(n),n=0;for(const r of e)t.set(r,n),n+=r.length;return t}(t);try{this.h.FS_unlink("llm.task")}catch{}this.h.FS_createDataFile("/","llm.task",t,!0,!1,!1)}async fa(t){if("string"==typeof t){const e=new Image;e.src=t,e.crossOrigin="Anonymous";try{await e.decode()}catch{throw Error(`Image from URL ${t} failed to load`)}return{image:e,width:e.naturalWidth,height:e.naturalHeight}}if(t instanceof HTMLImageElement){try{await t.decode()}catch{throw Error("Image from HTMLImageElement failed to load")}return{image:t,width:t.naturalWidth,height:t.naturalHeight}}return t instanceof HTMLVideoElement?{image:t,width:t.videoWidth,height:t.videoHeight}:t instanceof VideoFrame?{image:t,width:t.displayWidth,height:t.displayHeight}:{image:t,width:t.width,height:t.height}}async ea(t){if("string"==typeof t){const e=await fetch(t);if(!e.ok)throw Error(`Audio fetch for ${t} had error: ${e.status}`);return t=await e.arrayBuffer(),{audioSamples:(t=await new AudioContext({sampleRate:16e3}).decodeAudioData(t)).getChannelData(0),audioSampleRateHz:t.sampleRate}}return"object"==typeof t&&null!=t&&"audioSamples"in t&&"audioSampleRateHz"in t?t:{audioSamples:t.getChannelData(0),audioSampleRateHz:t.sampleRate}}}}(function(t){const e=class extends t{static async la(t,n){let r;n||=await e.X();const i=[];for(const e of t?.requiredFeatures??[])n.features.has(e)?i.push(e):console.warn(`WebGPU feature ${e} is not supported.`);t={...t,requiredFeatures:i};try{r=await n.requestDevice(t)}catch(t){throw console.error("Unable to initialize WebGPU with the requested features."),t}return(t=r).adapterInfo||(t.adapterInfo=n.info),r}static async X(t){if(!(t=await navigator.gpu.requestAdapter(t)))throw Error("Unable to request adapter from navigator.gpu; Ensure WebGPU is enabled.");return t}ga(t){if(e)"undefined"!=typeof HTMLCanvasElement&&e instanceof HTMLCanvasElement&&(e.id="canvas_webgpu");else var e=new OffscreenCanvas(1,1);e.getContext("webgpu").configure({device:t,format:navigator.gpu.getPreferredCanvasFormat()}),this.h.preinitializedWebGPUDevice=t}aa(){return this.h.ccall("closeGraph","void",[],[],{async:!0})}};return e}(function(t){return class extends t{addStreamingReaderToInputSidePacket(t,e){this.h.addStreamingReaderToInputSidePacket(((e,n,r)=>Or(t,this.h,e,n,r)),e)}}}(function(t){return class extends t{Y(t,e){hr(this,"lora_model_ref_in",(n=>{this.h._addRawDataSpanToInputStream(t.offset,t.size,n,e)}))}}}(class extends mr{}))));class Kr extends qr{}var Yr=class{constructor(t){this.j=t,this.i=Jr,Jr++}},Jr=1;class Xr{constructor(){let t,e;this.promise=new Promise(((n,r)=>{t=n,e=r})),this.resolve=t,this.reject=e}}function Qr(t){return 1===t?1:t+t%2}async function Zr(){const t=await Kr.X({powerPreference:"high-performance"});var e=t.limits.maxBufferSize;const n=t.limits.maxStorageBufferBindingSize;return e<524550144&&console.warn(`This WebGPU device is unable to execute most LLM tasks, because the required maxBufferSize is usually at least 524550144, but your device only supports maxBufferSize of ${e}`),n<524550144&&console.warn(`The WebGPU device is unable to execute LLM tasks, because the required maxStorageBufferBindingSize is usually at least 524550144, but your device only supports maxStorageBufferBindingSize of ${n}`),e={requiredFeatures:["shader-f16"],requiredLimits:{maxStorageBufferBindingSize:n,maxBufferSize:e,maxStorageBuffersPerShaderStage:t.limits.maxStorageBuffersPerShaderStage}},t.features.has("subgroups")&&(console.warn("Experimental Chromium WGSL subgroup support detected. Enabling this feature in the inference engine."),e.requiredFeatures=["shader-f16","subgroups"]),Kr.la(e,t)}function ti(t){if(t.D.length>0){const e=[...t.D];if(t.D.length=0,!t.o)throw e;t.o.reject(e),t.o=void 0}}function ei(t){const e=function(t){const e=new Zn;me(e,10,"text_in"),me(e,10,"token_cost_in"),me(e,10,"lora_model_id_to_apply_in"),me(e,10,"lora_model_ref_in"),me(e,10,"lora_model_id_to_load_in"),me(e,16,"streaming_reader"),me(e,15,"text_out"),me(e,15,"text_end"),me(e,15,"token_cost_out");var n=new Kn;pe(n,2,"TokenizerInputBuildCalculator"),me(n,3,"PROMPT:text_in"),me(n,3,"LORA_ID:lora_model_id_to_apply_in"),me(n,4,"prompt"),Qn(e,n),pe(n=new Kn,2,"ModelDataCalculator"),me(n,6,"MODEL_DATA:__side_packet_1"),me(n,6,"MODEL_TYPE:model_type"),me(n,5,"READ_DATA_FN:streaming_reader"),me(n,3,"LORA_MODEL_SPAN:lora_model_ref_in"),me(n,3,"LORA_MODEL_ID:lora_model_id_to_load_in"),me(n,4,"LORA_DATA:lora_model_data"),Qn(e,n),pe(n=new Kn,2,"Gpt2UnicodeMappingCalculator"),me(n,5,"MODEL_TYPE:model_type"),me(n,6,"BYTES_TO_UNICODE_MAPPING:tokenizer_mapping"),Qn(e,n),pe(n=new Cn,1,"type.googleapis.com/odml.infra.proto.TokenizerCalculatorOptions");var r=new Hr,i=he(t.i,2);fe(r,1,i),pe(i=new Wr,2,"spm_vocab_model"),i=ae(i);t:{Wt(r);var o=r.m,s=0|o[M];if(null==i){var a=ie(o);if(4!==oe(a,o,s))break t;a.set($r,0)}else{const t=ie(a=o),e=oe(t,a,s);4!==e&&(e&&(s=Jt(a,s,e)),t.set($r,4))}Jt(o,s,4,i)}return i&&!$(i)&&Ht(r.m),fe(r,3,2),Dn(n,r.j()),pe(r=new Kn,2,"TokenizerCalculator"),le(r,8,Cn,n),me(r,5,"MODEL_DATA:__side_packet_1"),me(r,3,"PROMPT_AND_INPUT_OPTIONS:prompt"),me(r,5,"BYTES_TO_UNICODE_MAPPING:tokenizer_mapping"),me(r,6,"PROCESSOR_GETTER:__input_side_1"),me(r,4,"IDS_AND_INPUT_OPTIONS:__stream_0"),Qn(e,r),pe(n=new Cn,1,"type.googleapis.com/odml.infra.proto.LlmGpuCalculatorOptions"),fe(r=new Mr,12,3),pe(r,1,"llm.tflite"),fe(r,14,0),i=Qr(he(t.i,5)),fe(r,22,i),i=se(t.i,Sr,3),ue(r,31,i),re(i=new Rr,1,At(!0),!1),null!=It(qt(t.i,6))&&(It(qt(t.i,6))??!1)&&re(i,1,At(!1),!1),re(i,2,At(!0),!1),re(i,5,At(!0),!1),ue(r,10,i),i=Xt(t.i,4,jt,void 0===K?2:4),ne(r,29,i),i=new Cr,fe(o=new Dr,1,1),a=he(t.i,2),fe(o,2,a),ue(i,1,o),ue(r,20,i),Dn(n,r.j()),pe(r=new Kn,2,"LlmGpuCalculator"),le(r,8,Cn,n),me(r,3,"IDS_AND_INPUT_OPTIONS:__stream_0"),me(r,3,"FINISH:finish"),me(r,3,"LORA_DATA:lora_model_data"),me(r,5,"MODEL_DATA:__side_packet_1"),me(r,4,"DECODED_IDS:__stream_3"),me(r,4,"OUTPUT_END:__stream_4"),pe(n=new $n,1,"FINISH"),re(n,2,At(!0),!1),le(r,13,$n,n),Qn(e,r),pe(n=new Kn,2,"IsPacketPresentCalculator"),me(n,3,"__stream_4"),me(n,4,"text_end"),Qn(e,n),pe(n=new Cn,1,"type.googleapis.com/odml.infra.proto.DetokenizerCalculatorOptions"),r=new Fr,t=Qr(he(t.i,5)),fe(r,5,t),me(r,4,""),me(r,4,"<|endoftext|>"),Dn(n,r.j()),pe(t=new Kn,2,"DetokenizerCalculator"),le(t,8,Cn,n),me(t,3,"IDS_AND_INPUT_OPTIONS:__stream_3"),me(t,5,"PROCESSOR_GETTER:__input_side_1"),me(t,5,"BYTES_TO_UNICODE_MAPPING:tokenizer_mapping"),me(t,5,"MODEL_DATA:__side_packet_1"),me(t,4,"FINISH_AND_INPUT_OPTIONS:finish"),me(t,4,"WORDS:text_out"),Qn(e,t),pe(t=new Kn,2,"TokenCostCalculator"),me(t,3,"PROMPT:token_cost_in"),me(t,5,"PROCESSOR_GETTER:__input_side_1"),me(t,5,"BYTES_TO_UNICODE_MAPPING:tokenizer_mapping"),me(t,4,"NUM_TOKENS:token_cost_out"),Qn(e,t),e}(t);t.j.attachStringVectorListener("text_out",((e,n)=>{e=function(t,e){return null==t||0===t.length?[]:t.map((t=>(t=(t=t.replaceAll("▁"," ")).replaceAll("<0x0A>","\n"),e&&(t=t.trimStart()),t.split("\\[eod\\]",1)[0])))}(e,0===t.G.length),e.forEach(((e,n)=>{nhe(t.i,5)&&e.pop(),t.A(e,!1)):t.A(e[0],!1)),vr(t,n)})),t.j.attachEmptyPacketListener("text_out",(e=>{vr(t,e)})),t.j.attachBoolListener("text_end",((e,n)=>{vr(t,n);try{ti(t)}catch(e){throw t.l=!1,e}if(t.o&&(t.o.resolve(t.G.map((t=>t.join("")))),t.o=void 0),t.A)if(t.B){for(e=[],n=0;n{t.l=!1,t.B=void 0,vr(t,e),ti(t),t.o&&(t.o.resolve(t.G.map((t=>t.join("")))),t.o=void 0)})),t.j.attachIntListener("token_cost_out",((e,n)=>{t.T=e,vr(t,n)})),t.U&&t.j.addStreamingReaderToInputSidePacket(t.U,"streaming_reader");const n=e.j();return t.C?.removeEventListener("uncapturederror",t.K),t.j.aa().then((()=>{t.C?.addEventListener("uncapturederror",t.K),t.D.length=0,t.setGraph(new Uint8Array(n),!0),t.finishProcessing()}))}function ni(t,e,n,r){if(t.A="function"==typeof n?n:r,(r=(e=Array.isArray(e)?e:[e]).filter((t=>kr(t))).length)>0&&(null==kt(qt(t.i,7))||he(t.i,7)Ur(t))).length)>0&&(null==It(qt(t.i,8))||!It(qt(t.i,8))))throw Error(`supportAudio was not enabled, but the query included ${r} audio chunks.`);if(t.v){if(t.B&&he(t.i,5)>1)throw Error("Multi-response generation is not supported for converted LLM models (.task format) yet, nor is it supported for multimodality. Please use the .bin format without multimodality or request only one response.");if(n instanceof Yr)throw Error("LoRA is not supported for converted LLM models (.task format) yet, nor is it supported for multimodality. Please use the .bin format without multimodality to use LoRA.");return t.j.h.LLM_CANCEL_FLAG=void 0,t.j.R(e,t.u,((e,n)=>{0===t.D.length&&t.A&&(t.B?t.A([e],n):t.A(e,n))})).then((e=>(ti(t),[e])))}if(t.l)throw Error("Previous invocation or loading is still ongoing.");for(t.l=!0,t.j.h.LLM_CANCEL_FLAG=void 0,t.G.length=0,r=0;r{if((t=t.error).message.match(/exceeds the max buffer size limit/))throw Error(`Failed to run this LLM model because it requires a buffer size that exceeds the maximum size your device supports, but you could try a smaller LLM model or different device.\nWebGPU throws: "${t.message}"`);if(t.message.match(/is larger than the maximum storage buffer binding size/))throw Error(`Failed to run this LLM model because it requires a storage buffer binding size that exceeds the maximum size your device supports, but you could try a smaller LLM model or different device.\nWebGPU throws: "${t.message}"`);this.D.push(t)},this.i=new Ar,Er(this.i,new tr),this.u=new Sr,ue(this.i,3,this.u),de(this.i,2,512),t=this.u,!vt(2))throw P("enum");re(t,1,2,0),fe(this.u,2,40),re(this.u,3,St(1),0),Yt(this.u,5,Ot(0)),re(this.u,4,St(.8),0),de(this.i,5,1)}async N(t){if(this.l)throw Error("Cannot set options while loading or processing.");if(t.baseOptions?.modelAssetPath&&t.baseOptions?.modelAssetBuffer)throw Error("Cannot set both baseOptions.modelAssetPath and baseOptions.modelAssetBuffer");let e;const n=new Promise((t=>{e=t}));if(t.baseOptions?.modelAssetPath){var r=await fetch(t.baseOptions.modelAssetPath.toString());if(!r.ok)throw Error(`Failed to fetch model: ${t.baseOptions.modelAssetPath} (${r.status})`);if(!r.body)throw Error(`Failed to fetch model: ${t.baseOptions.modelAssetPath} (no body)`);r=r.body.getReader()}else t.baseOptions?.modelAssetBuffer instanceof Uint8Array?r=function(t){return new ReadableStream({start(){},async pull(e){e.enqueue(t),e.close()}})}(t.baseOptions.modelAssetBuffer).getReader():t.baseOptions?.modelAssetBuffer instanceof ReadableStreamDefaultReader?(r=t.baseOptions.modelAssetBuffer,t.baseOptions.modelAssetBuffer=void 0):e();if(!r)throw Error("No model asset provided.");{const[n,s]=sr(r);this.O=1===await async function(t){const e=[];let n;for(const[i,o]of ur){const s=i;var r=o;[t,n]=sr(t),r=await r(n),await n.cancel(),r&&e.push(s)}if(await t.cancel(),0===e.length)throw Error("No model format matched.");if(1===e.length)return e[0];throw Error(`Multiple model formats matched: ${e}`)}(s);var i="maxNumImages"in t&&t.maxNumImages?t.maxNumImages:0;de(this.i,7,i);var o="supportAudio"in t&&!!t.supportAudio;Yt(this.i,8,At(o)),this.O||i>0||o?(this.v=!0,r=n):(this.v=!1,this.U=Pr(n,e))}if(t.baseOptions?.gpuOptions?.device&&(this.C&&this.C.removeEventListener("uncapturederror",this.K),this.C=t.baseOptions.gpuOptions.device,this.j.ga(this.C),this.C.addEventListener("uncapturederror",this.K)),"maxTokens"in t&&de(this.i,2,t.maxTokens??512),"topK"in t&&fe(this.u,2,t.topK??40),"temperature"in t&&re(this.u,4,St(t.temperature??.8),0),"randomSeed"in t&&Yt(this.u,5,Ot(t.randomSeed??0)),"loraRanks"in t&&function(t,e){ne(t,4,e)}(this.i,t.loraRanks??[]),"numResponses"in t){if((i=t.numResponses??1)<1)throw Error("'numResponses' must be at least 1.");if(this.v&&i>1)throw Error("'numResponses > 1' is not supported for converted LLM models yet, and is also not supported with multimodality.");de(this.i,5,i),o=se(this.i,Sr,3),i>1&&o&&(o.j()<=1||(qt(o,4,Et)??0)<=0)&&console.warn("To generate multiple responses, it is expected topK > 1 and temperature > 0; otherwise, all the generated responses may be the same.")}return"forceF32"in t&&void 0!==t.forceF32&&Yt(this.i,6,At(t.forceF32)),this.v?(this.j.V(),this.O?this.j.ba(r,this.i).then((()=>{ti(this)})):this.j.createLlmInferenceEngine(r,this.i).then((()=>{ti(this)}))):(this.l=!0,t=ei(this).then((()=>{})),Promise.all([n,t]).then((()=>{this.l=!1,ti(this)})))}get baseOptions(){return se(this.i,tr,1)}set baseOptions(t){Er(this.i,t)}get isIdle(){return!this.l&&!this.o}R(t,e,n){return he(this.i,5)>1&&console.warn("'numResponses' is set larger than 1 and this function only returns the first response, so we recommend either using 'generateResponses()' to obtain multiple responses, or else setting 'numResponses' to 1 for better performance."),this.B=!1,ni(this,t,e,n).then((t=>t[0]))}da(t,e,n){return this.B=!0,ni(this,t,e,n)}S(t){if(t=Array.isArray(t)?t:[t],this.v)return this.j.S(t);if(this.l)throw Error("Previous invocation or loading is still ongoing.");if(t.some(kr))throw Error("sizeInTokens requires maxNumImages > 0 for images.");if(t.some(Ur))throw Error("sizeInTokens requires supportAudio for audio.");return t=t.join(""),this.l=!0,this.T=void 0,this.j.addStringToStream(t,"token_cost_in",this.I+1),this.finishProcessing(),this.l=!1,this.T}Z(){const t=this.j.h;(this.v||this.l)&&(t.LLM_CANCEL_FLAG=1)}async ja(t){if(this.v)throw Error("LoRA is not supported for converted LLM models (.task format) yet, nor is it supported for multimodality. Please use the old format (.bin) without multimodality to use LoRA.");if(this.l)throw Error("Cannot load LoRA model while loading or processing.");if(this.l=!0,t instanceof Uint8Array){var e=new Nr(this.j.h,t.length);e.set(t),t=e}else t=t instanceof Blob?await async function(t,e){return xr(t,e.stream(),e.size)}(this.j.h,t):await async function(t,e){e=await fetch(e.toString());const n=Number(e.headers.get("content-length"));if(!e.body)throw Error("Response body is not available.");if(!n)throw Error("File size is 0.");return xr(t,e.body,n)}(this.j.h,t);e=new Yr(this);const n=this.I+1;return this.j.Y(t,n),this.j.addUintToStream(e.i,"lora_model_id_to_load_in",n),this.finishProcessing(),Br(t),vr(this,n),this.l=!1,e}close(){this.v&&this.j.V(),this.C?.removeEventListener("uncapturederror",this.K),super.close()}};ri.prototype.loadLoraModel=ri.prototype.ja,ri.prototype.cancelProcessing=ri.prototype.Z,ri.prototype.sizeInTokens=ri.prototype.S,ri.prototype.generateResponses=ri.prototype.da,ri.prototype.generateResponse=ri.prototype.R,ri.prototype.setOptions=ri.prototype.N,ri.createWebGpuDevice=Zr,ri.createFromModelPath=async function(t,e){return yr(t,e={baseOptions:{gpuOptions:{device:await Zr()},modelAssetPath:e}})},ri.createFromModelBuffer=async function(t,e){return yr(t,e={baseOptions:{gpuOptions:{device:await Zr()},modelAssetBuffer:e}})},ri.createFromOptions=async function(t,e){if(!e.baseOptions?.gpuOptions?.device){const t=await Zr();e.baseOptions=e.baseOptions??{},e.baseOptions.gpuOptions=e?.baseOptions?.gpuOptions??{},e.baseOptions.gpuOptions.device=t}return yr(t,e)};export{or as FilesetResolver,ri as LlmInference,br as TaskRunner};
+//# sourceMappingURL=genai_bundle_mjs.js.map
diff --git a/public/mediapipe/wasm/genai_wasm_internal.js b/public/mediapipe/wasm/genai_wasm_internal.js
new file mode 100644
index 0000000..c43175d
--- /dev/null
+++ b/public/mediapipe/wasm/genai_wasm_internal.js
@@ -0,0 +1,9035 @@
+// This code implements the `-sMODULARIZE` settings by taking the generated
+// JS program code (INNER_JS_CODE) and wrapping it in a factory function.
+
+// Single threaded MINIMAL_RUNTIME programs do not need access to
+// document.currentScript, so a simple export declaration is enough.
+var ModuleFactory = (() => {
+ // When MODULARIZE this JS may be executed later,
+ // after document.currentScript is gone, so we save it.
+ // In EXPORT_ES6 mode we can just use 'import.meta.url'.
+ var _scriptName = globalThis.document?.currentScript?.src;
+ return async function(moduleArg = {}) {
+ var moduleRtn;
+
+// include: shell.js
+// include: minimum_runtime_check.js
+// end include: minimum_runtime_check.js
+// The Module object: Our interface to the outside world. We import
+// and export values on it. There are various ways Module can be used:
+// 1. Not defined. We create it here
+// 2. A function parameter, function(moduleArg) => Promise
+// 3. pre-run appended it, var Module = {}; ..generated code..
+// 4. External script tag defines var Module.
+// We need to check if Module already exists (e.g. case 3 above).
+// Substitution will be replaced with actual code on later stage of the build,
+// this way Closure Compiler will not mangle it (e.g. case 4. above).
+// Note that if you want to run closure, and also to use Module
+// after the generated code, you will need to define var Module = {};
+// before the code. Then that object will be used in the code, and you
+// can continue to use Module afterwards as well.
+var Module = moduleArg;
+
+// Determine the runtime environment we are in. You can customize this by
+// setting the ENVIRONMENT setting at compile time (see settings.js).
+// Attempt to auto-detect the environment
+var ENVIRONMENT_IS_WEB = !!globalThis.window;
+
+var ENVIRONMENT_IS_WORKER = !!globalThis.WorkerGlobalScope;
+
+// N.b. Electron.js environment is simultaneously a NODE-environment, but
+// also a web environment.
+var ENVIRONMENT_IS_NODE = globalThis.process?.versions?.node && globalThis.process?.type != "renderer";
+
+// --pre-jses are emitted after the Module integration code, so that they can
+// refer to Module (if they choose; they can also define Module)
+var arguments_ = [];
+
+var thisProgram = "./this.program";
+
+var quit_ = (status, toThrow) => {
+ throw toThrow;
+};
+
+if (typeof __filename != "undefined") {
+ // Node
+ _scriptName = __filename;
+} else if (ENVIRONMENT_IS_WORKER) {
+ _scriptName = self.location.href;
+}
+
+// `/` should be present at the end if `scriptDirectory` is not empty
+var scriptDirectory = "";
+
+function locateFile(path) {
+ if (Module["locateFile"]) {
+ return Module["locateFile"](path, scriptDirectory);
+ }
+ return scriptDirectory + path;
+}
+
+// Hooks that are implemented differently in different runtime environments.
+var readAsync, readBinary;
+
+if (ENVIRONMENT_IS_NODE) {
+ // These modules will usually be used on Node.js. Load them eagerly to avoid
+ // the complexity of lazy-loading.
+ var fs = require("node:fs");
+ scriptDirectory = __dirname + "/";
+ // include: node_shell_read.js
+ readBinary = filename => {
+ // We need to re-wrap `file://` strings to URLs.
+ filename = isFileURI(filename) ? new URL(filename) : filename;
+ var ret = fs.readFileSync(filename);
+ return ret;
+ };
+ readAsync = async (filename, binary = true) => {
+ // See the comment in the `readBinary` function.
+ filename = isFileURI(filename) ? new URL(filename) : filename;
+ var ret = fs.readFileSync(filename, binary ? undefined : "utf8");
+ return ret;
+ };
+ // end include: node_shell_read.js
+ if (process.argv.length > 1) {
+ thisProgram = process.argv[1].replace(/\\/g, "/");
+ }
+ arguments_ = process.argv.slice(2);
+ quit_ = (status, toThrow) => {
+ process.exitCode = status;
+ throw toThrow;
+ };
+} else // Note that this includes Node.js workers when relevant (pthreads is enabled).
+// Node.js workers are detected as a combination of ENVIRONMENT_IS_WORKER and
+// ENVIRONMENT_IS_NODE.
+if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
+ try {
+ scriptDirectory = new URL(".", _scriptName).href;
+ } catch {}
+ {
+ // include: web_or_worker_shell_read.js
+ if (ENVIRONMENT_IS_WORKER) {
+ readBinary = url => {
+ var xhr = new XMLHttpRequest;
+ xhr.open("GET", url, false);
+ xhr.responseType = "arraybuffer";
+ xhr.send(null);
+ return new Uint8Array(/** @type{!ArrayBuffer} */ (xhr.response));
+ };
+ }
+ readAsync = async url => {
+ // Fetch has some additional restrictions over XHR, like it can't be used on a file:// url.
+ // See https://github.com/github/fetch/pull/92#issuecomment-140665932
+ // Cordova or Electron apps are typically loaded from a file:// url.
+ // So use XHR on webview if URL is a file URL.
+ if (isFileURI(url)) {
+ return new Promise((resolve, reject) => {
+ var xhr = new XMLHttpRequest;
+ xhr.open("GET", url, true);
+ xhr.responseType = "arraybuffer";
+ xhr.onload = () => {
+ if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) {
+ // file URLs can return 0
+ resolve(xhr.response);
+ return;
+ }
+ reject(xhr.status);
+ };
+ xhr.onerror = reject;
+ xhr.send(null);
+ });
+ }
+ var response = await fetch(url, {
+ credentials: "same-origin"
+ });
+ if (response.ok) {
+ return response.arrayBuffer();
+ }
+ throw new Error(response.status + " : " + response.url);
+ };
+ }
+} else {}
+
+var out = console.log.bind(console);
+
+var err = console.error.bind(console);
+
+// end include: shell.js
+// include: preamble.js
+// === Preamble library stuff ===
+// Documentation for the public APIs defined in this file must be updated in:
+// site/source/docs/api_reference/preamble.js.rst
+// A prebuilt local version of the documentation is available at:
+// site/build/text/docs/api_reference/preamble.js.txt
+// You can also build docs locally as HTML or other formats in site/
+// An online HTML version (which may be of a different version of Emscripten)
+// is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html
+var wasmBinary;
+
+// Wasm globals
+//========================================
+// Runtime essentials
+//========================================
+// whether we are quitting the application. no code should run after this.
+// set in exit() and abort()
+var ABORT = false;
+
+// set by exit() and abort(). Passed to 'onExit' handler.
+// NOTE: This is also used as the process return code in shell environments
+// but only when noExitRuntime is false.
+var EXITSTATUS;
+
+// In STRICT mode, we only define assert() when ASSERTIONS is set. i.e. we
+// don't define it at all in release modes. This matches the behaviour of
+// MINIMAL_RUNTIME.
+// TODO(sbc): Make this the default even without STRICT enabled.
+/** @type {function(*, string=)} */ function assert(condition, text) {
+ if (!condition) {
+ // This build was created without ASSERTIONS defined. `assert()` should not
+ // ever be called in this configuration but in case there are callers in
+ // the wild leave this simple abort() implementation here for now.
+ abort(text);
+ }
+}
+
+/**
+ * Indicates whether filename is delivered via file protocol (as opposed to http/https)
+ * @noinline
+ */ var isFileURI = filename => filename.startsWith("file://");
+
+// include: runtime_common.js
+// include: runtime_stack_check.js
+// end include: runtime_stack_check.js
+// include: runtime_exceptions.js
+// end include: runtime_exceptions.js
+// include: runtime_debug.js
+// end include: runtime_debug.js
+var readyPromiseResolve, readyPromiseReject;
+
+// Memory management
+var /** @type {!Int8Array} */ HEAP8, /** @type {!Uint8Array} */ HEAPU8, /** @type {!Int16Array} */ HEAP16, /** @type {!Uint16Array} */ HEAPU16, /** @type {!Int32Array} */ HEAP32, /** @type {!Uint32Array} */ HEAPU32, /** @type {!Float32Array} */ HEAPF32, /** @type {!Float64Array} */ HEAPF64;
+
+var runtimeInitialized = false;
+
+function updateMemoryViews() {
+ var b = wasmMemory.buffer;
+ HEAP8 = new Int8Array(b);
+ HEAP16 = new Int16Array(b);
+ Module["HEAPU8"] = HEAPU8 = new Uint8Array(b);
+ HEAPU16 = new Uint16Array(b);
+ HEAP32 = new Int32Array(b);
+ Module["HEAPU32"] = HEAPU32 = new Uint32Array(b);
+ Module["HEAPF32"] = HEAPF32 = new Float32Array(b);
+ Module["HEAPF64"] = HEAPF64 = new Float64Array(b);
+}
+
+// include: memoryprofiler.js
+// end include: memoryprofiler.js
+// end include: runtime_common.js
+function preRun() {
+ if (Module["preRun"]) {
+ if (typeof Module["preRun"] == "function") Module["preRun"] = [ Module["preRun"] ];
+ while (Module["preRun"].length) {
+ addOnPreRun(Module["preRun"].shift());
+ }
+ }
+ // Begin ATPRERUNS hooks
+ callRuntimeCallbacks(onPreRuns);
+}
+
+function initRuntime() {
+ runtimeInitialized = true;
+ // Begin ATINITS hooks
+ if (!Module["noFSInit"] && !FS.initialized) FS.init();
+ TTY.init();
+ // End ATINITS hooks
+ wasmExports["tc"]();
+ // Begin ATPOSTCTORS hooks
+ FS.ignorePermissions = false;
+}
+
+function postRun() {
+ // PThreads reuse the runtime from the main thread.
+ if (Module["postRun"]) {
+ if (typeof Module["postRun"] == "function") Module["postRun"] = [ Module["postRun"] ];
+ while (Module["postRun"].length) {
+ addOnPostRun(Module["postRun"].shift());
+ }
+ }
+ // Begin ATPOSTRUNS hooks
+ callRuntimeCallbacks(onPostRuns);
+}
+
+/** @param {string|number=} what */ function abort(what) {
+ Module["onAbort"]?.(what);
+ what = "Aborted(" + what + ")";
+ // TODO(sbc): Should we remove printing and leave it up to whoever
+ // catches the exception?
+ err(what);
+ ABORT = true;
+ what += ". Build with -sASSERTIONS for more info.";
+ // Use a wasm runtime error, because a JS error might be seen as a foreign
+ // exception, which means we'd run destructors on it. We need the error to
+ // simply make the program stop.
+ // FIXME This approach does not work in Wasm EH because it currently does not assume
+ // all RuntimeErrors are from traps; it decides whether a RuntimeError is from
+ // a trap or not based on a hidden field within the object. So at the moment
+ // we don't have a way of throwing a wasm trap from JS. TODO Make a JS API that
+ // allows this in the wasm spec.
+ // Suppress closure compiler warning here. Closure compiler's builtin extern
+ // definition for WebAssembly.RuntimeError claims it takes no arguments even
+ // though it can.
+ // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure gets fixed.
+ /** @suppress {checkTypes} */ var e = new WebAssembly.RuntimeError(what);
+ readyPromiseReject?.(e);
+ // Throw the error whether or not MODULARIZE is set because abort is used
+ // in code paths apart from instantiation where an exception is expected
+ // to be thrown when abort is called.
+ throw e;
+}
+
+var wasmBinaryFile;
+
+function findWasmBinary() {
+ return locateFile("genai_wasm_internal.wasm");
+}
+
+function getBinarySync(file) {
+ if (file == wasmBinaryFile && wasmBinary) {
+ return new Uint8Array(wasmBinary);
+ }
+ if (readBinary) {
+ return readBinary(file);
+ }
+ // Throwing a plain string here, even though it not normally advisable since
+ // this gets turning into an `abort` in instantiateArrayBuffer.
+ throw "both async and sync fetching of the wasm failed";
+}
+
+async function getWasmBinary(binaryFile) {
+ // If we don't have the binary yet, load it asynchronously using readAsync.
+ if (!wasmBinary) {
+ // Fetch the binary using readAsync
+ try {
+ var response = await readAsync(binaryFile);
+ return new Uint8Array(response);
+ } catch {}
+ }
+ // Otherwise, getBinarySync should be able to get it synchronously
+ return getBinarySync(binaryFile);
+}
+
+async function instantiateArrayBuffer(binaryFile, imports) {
+ try {
+ var binary = await getWasmBinary(binaryFile);
+ var instance = await WebAssembly.instantiate(binary, imports);
+ return instance;
+ } catch (reason) {
+ err(`failed to asynchronously prepare wasm: ${reason}`);
+ abort(reason);
+ }
+}
+
+async function instantiateAsync(binary, binaryFile, imports) {
+ if (!binary && !isFileURI(binaryFile) && !ENVIRONMENT_IS_NODE) {
+ try {
+ var response = fetch(binaryFile, {
+ credentials: "same-origin"
+ });
+ var instantiationResult = await WebAssembly.instantiateStreaming(response, imports);
+ return instantiationResult;
+ } catch (reason) {
+ // We expect the most common failure cause to be a bad MIME type for the binary,
+ // in which case falling back to ArrayBuffer instantiation should work.
+ err(`wasm streaming compile failed: ${reason}`);
+ err("falling back to ArrayBuffer instantiation");
+ }
+ }
+ return instantiateArrayBuffer(binaryFile, imports);
+}
+
+function getWasmImports() {
+ // prepare imports
+ var imports = {
+ "a": wasmImports
+ };
+ return imports;
+}
+
+// Create the wasm instance.
+// Receives the wasm imports, returns the exports.
+async function createWasm() {
+ // Load the wasm module and create an instance of using native support in the JS engine.
+ // handle a generated wasm instance, receiving its exports and
+ // performing other necessary setup
+ /** @param {WebAssembly.Module=} module*/ function receiveInstance(instance, module) {
+ wasmExports = instance.exports;
+ wasmExports = Asyncify.instrumentWasmExports(wasmExports);
+ wasmExports = applySignatureConversions(wasmExports);
+ assignWasmExports(wasmExports);
+ updateMemoryViews();
+ return wasmExports;
+ }
+ // Prefer streaming instantiation if available.
+ function receiveInstantiationResult(result) {
+ // 'result' is a ResultObject object which has both the module and instance.
+ // receiveInstance() will swap in the exports (to Module.asm) so they can be called
+ // TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193, the above line no longer optimizes out down to the following line.
+ // When the regression is fixed, can restore the above PTHREADS-enabled path.
+ return receiveInstance(result["instance"]);
+ }
+ var info = getWasmImports();
+ // User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback
+ // to manually instantiate the Wasm module themselves. This allows pages to
+ // run the instantiation parallel to any other async startup actions they are
+ // performing.
+ // Also pthreads and wasm workers initialize the wasm instance through this
+ // path.
+ if (Module["instantiateWasm"]) {
+ return new Promise((resolve, reject) => {
+ Module["instantiateWasm"](info, (inst, mod) => {
+ resolve(receiveInstance(inst, mod));
+ });
+ });
+ }
+ wasmBinaryFile ??= findWasmBinary();
+ var result = await instantiateAsync(wasmBinary, wasmBinaryFile, info);
+ var exports = receiveInstantiationResult(result);
+ return exports;
+}
+
+// Globals used by JS i64 conversions (see makeSetValue)
+var tempDouble;
+
+var tempI64;
+
+// end include: preamble.js
+// Begin JS library code
+var handleException = e => {
+ // Certain exception types we do not treat as errors since they are used for
+ // internal control flow.
+ // 1. ExitStatus, which is thrown by exit()
+ // 2. "unwind", which is thrown by emscripten_unwind_to_js_event_loop() and others
+ // that wish to return to JS event loop.
+ if (e instanceof ExitStatus || e == "unwind") {
+ return EXITSTATUS;
+ }
+ quit_(1, e);
+};
+
+class ExitStatus {
+ name="ExitStatus";
+ constructor(status) {
+ this.message = `Program terminated with exit(${status})`;
+ this.status = status;
+ }
+}
+
+var runtimeKeepaliveCounter = 0;
+
+var keepRuntimeAlive = () => noExitRuntime || runtimeKeepaliveCounter > 0;
+
+var _proc_exit = code => {
+ EXITSTATUS = code;
+ if (!keepRuntimeAlive()) {
+ Module["onExit"]?.(code);
+ ABORT = true;
+ }
+ quit_(code, new ExitStatus(code));
+};
+
+/** @param {boolean|number=} implicit */ var exitJS = (status, implicit) => {
+ EXITSTATUS = status;
+ _proc_exit(status);
+};
+
+var _exit = exitJS;
+
+var maybeExit = () => {
+ if (!keepRuntimeAlive()) {
+ try {
+ _exit(EXITSTATUS);
+ } catch (e) {
+ handleException(e);
+ }
+ }
+};
+
+var callUserCallback = func => {
+ if (ABORT) {
+ return;
+ }
+ try {
+ return func();
+ } catch (e) {
+ handleException(e);
+ } finally {
+ maybeExit();
+ }
+};
+
+function getFullscreenElement() {
+ return document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.webkitCurrentFullScreenElement || document.msFullscreenElement;
+}
+
+/** @param {number=} timeout */ var safeSetTimeout = (func, timeout) => setTimeout(() => {
+ callUserCallback(func);
+}, timeout);
+
+var warnOnce = text => {
+ warnOnce.shown ||= {};
+ if (!warnOnce.shown[text]) {
+ warnOnce.shown[text] = 1;
+ if (ENVIRONMENT_IS_NODE) text = "warning: " + text;
+ err(text);
+ }
+};
+
+var preloadPlugins = [];
+
+var Browser = {
+ useWebGL: false,
+ isFullscreen: false,
+ pointerLock: false,
+ moduleContextCreatedCallbacks: [],
+ workers: [],
+ preloadedImages: {},
+ preloadedAudios: {},
+ getCanvas: () => Module["canvas"],
+ init() {
+ if (Browser.initted) return;
+ Browser.initted = true;
+ // Support for plugins that can process preloaded files. You can add more of these to
+ // your app by creating and appending to preloadPlugins.
+ // Each plugin is asked if it can handle a file based on the file's name. If it can,
+ // it is given the file's raw data. When it is done, it calls a callback with the file's
+ // (possibly modified) data. For example, a plugin might decompress a file, or it
+ // might create some side data structure for use later (like an Image element, etc.).
+ var imagePlugin = {};
+ imagePlugin["canHandle"] = name => !Module["noImageDecoding"] && /\.(jpg|jpeg|png|bmp|webp)$/i.test(name);
+ imagePlugin["handle"] = async (byteArray, name) => {
+ var b = new Blob([ byteArray ], {
+ type: Browser.getMimetype(name)
+ });
+ if (b.size !== byteArray.length) {
+ // Safari bug #118630
+ // Safari's Blob can only take an ArrayBuffer
+ b = new Blob([ (new Uint8Array(byteArray)).buffer ], {
+ type: Browser.getMimetype(name)
+ });
+ }
+ var url = URL.createObjectURL(b);
+ return new Promise((resolve, reject) => {
+ var img = new Image;
+ img.onload = () => {
+ var canvas = /** @type {!HTMLCanvasElement} */ (document.createElement("canvas"));
+ canvas.width = img.width;
+ canvas.height = img.height;
+ var ctx = canvas.getContext("2d");
+ ctx.drawImage(img, 0, 0);
+ Browser.preloadedImages[name] = canvas;
+ URL.revokeObjectURL(url);
+ resolve(byteArray);
+ };
+ img.onerror = event => {
+ err(`Image ${url} could not be decoded`);
+ reject();
+ };
+ img.src = url;
+ });
+ };
+ preloadPlugins.push(imagePlugin);
+ var audioPlugin = {};
+ audioPlugin["canHandle"] = name => !Module["noAudioDecoding"] && name.slice(-4) in {
+ ".ogg": 1,
+ ".wav": 1,
+ ".mp3": 1
+ };
+ audioPlugin["handle"] = async (byteArray, name) => new Promise((resolve, reject) => {
+ var done = false;
+ function finish(audio) {
+ if (done) return;
+ done = true;
+ Browser.preloadedAudios[name] = audio;
+ resolve(byteArray);
+ }
+ var b = new Blob([ byteArray ], {
+ type: Browser.getMimetype(name)
+ });
+ var url = URL.createObjectURL(b);
+ // XXX we never revoke this!
+ var audio = new Audio;
+ audio.addEventListener("canplaythrough", () => finish(audio), false);
+ // use addEventListener due to chromium bug 124926
+ audio.onerror = event => {
+ if (done) return;
+ err(`warning: browser could not fully decode audio ${name}, trying slower base64 approach`);
+ function encode64(data) {
+ var BASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ var PAD = "=";
+ var ret = "";
+ var leftchar = 0;
+ var leftbits = 0;
+ for (var i = 0; i < data.length; i++) {
+ leftchar = (leftchar << 8) | data[i];
+ leftbits += 8;
+ while (leftbits >= 6) {
+ var curr = (leftchar >> (leftbits - 6)) & 63;
+ leftbits -= 6;
+ ret += BASE[curr];
+ }
+ }
+ if (leftbits == 2) {
+ ret += BASE[(leftchar & 3) << 4];
+ ret += PAD + PAD;
+ } else if (leftbits == 4) {
+ ret += BASE[(leftchar & 15) << 2];
+ ret += PAD;
+ }
+ return ret;
+ }
+ audio.src = "data:audio/x-" + name.slice(-3) + ";base64," + encode64(byteArray);
+ finish(audio);
+ };
+ audio.src = url;
+ // workaround for chrome bug 124926 - we do not always get oncanplaythrough or onerror
+ safeSetTimeout(() => {
+ finish(audio);
+ }, 1e4);
+ });
+ preloadPlugins.push(audioPlugin);
+ // Canvas event setup
+ function pointerLockChange() {
+ var canvas = Browser.getCanvas();
+ Browser.pointerLock = document.pointerLockElement === canvas;
+ }
+ var canvas = Browser.getCanvas();
+ if (canvas) {
+ // forced aspect ratio can be enabled by defining 'forcedAspectRatio' on Module
+ // Module['forcedAspectRatio'] = 4 / 3;
+ document.addEventListener("pointerlockchange", pointerLockChange, false);
+ if (Module["elementPointerLock"]) {
+ canvas.addEventListener("click", ev => {
+ if (!Browser.pointerLock && Browser.getCanvas().requestPointerLock) {
+ Browser.getCanvas().requestPointerLock();
+ ev.preventDefault();
+ }
+ }, false);
+ }
+ }
+ },
+ createContext(/** @type {HTMLCanvasElement} */ canvas, useWebGL, setInModule, webGLContextAttributes) {
+ if (useWebGL && Module["ctx"] && canvas == Browser.getCanvas()) return Module["ctx"];
+ // no need to recreate GL context if it's already been created for this canvas.
+ var ctx;
+ var contextHandle;
+ if (useWebGL) {
+ // For GLES2/desktop GL compatibility, adjust a few defaults to be different to WebGL defaults, so that they align better with the desktop defaults.
+ var contextAttributes = {
+ antialias: false,
+ alpha: false,
+ majorVersion: (typeof WebGL2RenderingContext != "undefined") ? 2 : 1
+ };
+ if (webGLContextAttributes) {
+ for (var attribute in webGLContextAttributes) {
+ contextAttributes[attribute] = webGLContextAttributes[attribute];
+ }
+ }
+ // This check of existence of GL is here to satisfy Closure compiler, which yells if variable GL is referenced below but GL object is not
+ // actually compiled in because application is not doing any GL operations. TODO: Ideally if GL is not being used, this function
+ // Browser.createContext() should not even be emitted.
+ if (typeof GL != "undefined") {
+ contextHandle = GL.createContext(canvas, contextAttributes);
+ if (contextHandle) {
+ ctx = GL.getContext(contextHandle).GLctx;
+ }
+ }
+ } else {
+ ctx = canvas.getContext("2d");
+ }
+ if (!ctx) return null;
+ if (setInModule) {
+ Module["ctx"] = ctx;
+ if (useWebGL) GL.makeContextCurrent(contextHandle);
+ Browser.useWebGL = useWebGL;
+ Browser.moduleContextCreatedCallbacks.forEach(callback => callback());
+ Browser.init();
+ }
+ return ctx;
+ },
+ fullscreenHandlersInstalled: false,
+ lockPointer: undefined,
+ resizeCanvas: undefined,
+ requestFullscreen(lockPointer, resizeCanvas) {
+ Browser.lockPointer = lockPointer;
+ Browser.resizeCanvas = resizeCanvas;
+ if (typeof Browser.lockPointer == "undefined") Browser.lockPointer = true;
+ if (typeof Browser.resizeCanvas == "undefined") Browser.resizeCanvas = false;
+ var canvas = Browser.getCanvas();
+ function fullscreenChange() {
+ Browser.isFullscreen = false;
+ var canvasContainer = canvas.parentNode;
+ if (getFullscreenElement() === canvasContainer) {
+ canvas.exitFullscreen = Browser.exitFullscreen;
+ if (Browser.lockPointer) canvas.requestPointerLock();
+ Browser.isFullscreen = true;
+ if (Browser.resizeCanvas) {
+ Browser.setFullscreenCanvasSize();
+ } else {
+ Browser.updateCanvasDimensions(canvas);
+ }
+ } else {
+ // remove the full screen specific parent of the canvas again to restore the HTML structure from before going full screen
+ canvasContainer.parentNode.insertBefore(canvas, canvasContainer);
+ canvasContainer.parentNode.removeChild(canvasContainer);
+ if (Browser.resizeCanvas) {
+ Browser.setWindowedCanvasSize();
+ } else {
+ Browser.updateCanvasDimensions(canvas);
+ }
+ }
+ Module["onFullScreen"]?.(Browser.isFullscreen);
+ Module["onFullscreen"]?.(Browser.isFullscreen);
+ }
+ if (!Browser.fullscreenHandlersInstalled) {
+ Browser.fullscreenHandlersInstalled = true;
+ document.addEventListener("fullscreenchange", fullscreenChange, false);
+ document.addEventListener("mozfullscreenchange", fullscreenChange, false);
+ document.addEventListener("webkitfullscreenchange", fullscreenChange, false);
+ document.addEventListener("MSFullscreenChange", fullscreenChange, false);
+ }
+ // create a new parent to ensure the canvas has no siblings. this allows browsers to optimize full screen performance when its parent is the full screen root
+ var canvasContainer = document.createElement("div");
+ canvas.parentNode.insertBefore(canvasContainer, canvas);
+ canvasContainer.appendChild(canvas);
+ // use parent of canvas as full screen root to allow aspect ratio correction (Firefox stretches the root to screen size)
+ canvasContainer.requestFullscreen = canvasContainer["requestFullscreen"] || canvasContainer["mozRequestFullScreen"] || canvasContainer["msRequestFullscreen"] || (canvasContainer["webkitRequestFullscreen"] ? () => canvasContainer["webkitRequestFullscreen"](Element["ALLOW_KEYBOARD_INPUT"]) : null) || (canvasContainer["webkitRequestFullScreen"] ? () => canvasContainer["webkitRequestFullScreen"](Element["ALLOW_KEYBOARD_INPUT"]) : null);
+ canvasContainer.requestFullscreen();
+ },
+ exitFullscreen() {
+ // This is workaround for chrome. Trying to exit from fullscreen
+ // not in fullscreen state will cause "TypeError: Document not active"
+ // in chrome. See https://github.com/emscripten-core/emscripten/pull/8236
+ if (!Browser.isFullscreen) {
+ return false;
+ }
+ var CFS = document["exitFullscreen"] || document["cancelFullScreen"] || document["mozCancelFullScreen"] || document["msExitFullscreen"] || document["webkitCancelFullScreen"] || (() => {});
+ CFS.apply(document, []);
+ return true;
+ },
+ safeSetTimeout(func, timeout) {
+ // Legacy function, this is used by the SDL2 port so we need to keep it
+ // around at least until that is updated.
+ // See https://github.com/libsdl-org/SDL/pull/6304
+ return safeSetTimeout(func, timeout);
+ },
+ getMimetype(name) {
+ return {
+ "jpg": "image/jpeg",
+ "jpeg": "image/jpeg",
+ "png": "image/png",
+ "bmp": "image/bmp",
+ "ogg": "audio/ogg",
+ "wav": "audio/wav",
+ "mp3": "audio/mpeg"
+ }[name.slice(name.lastIndexOf(".") + 1)];
+ },
+ getUserMedia(func) {
+ window.getUserMedia ||= navigator["getUserMedia"] || navigator["mozGetUserMedia"];
+ window.getUserMedia(func);
+ },
+ getMovementX(event) {
+ return event["movementX"] || event["mozMovementX"] || event["webkitMovementX"] || 0;
+ },
+ getMovementY(event) {
+ return event["movementY"] || event["mozMovementY"] || event["webkitMovementY"] || 0;
+ },
+ getMouseWheelDelta(event) {
+ var delta = 0;
+ switch (event.type) {
+ case "DOMMouseScroll":
+ // 3 lines make up a step
+ delta = event.detail / 3;
+ break;
+
+ case "mousewheel":
+ // 120 units make up a step
+ delta = event.wheelDelta / 120;
+ break;
+
+ case "wheel":
+ delta = event.deltaY;
+ switch (event.deltaMode) {
+ case 0:
+ // DOM_DELTA_PIXEL: 100 pixels make up a step
+ delta /= 100;
+ break;
+
+ case 1:
+ // DOM_DELTA_LINE: 3 lines make up a step
+ delta /= 3;
+ break;
+
+ case 2:
+ // DOM_DELTA_PAGE: A page makes up 80 steps
+ delta *= 80;
+ break;
+
+ default:
+ abort("unrecognized mouse wheel delta mode: " + event.deltaMode);
+ }
+ break;
+
+ default:
+ abort("unrecognized mouse wheel event: " + event.type);
+ }
+ return delta;
+ },
+ mouseX: 0,
+ mouseY: 0,
+ mouseMovementX: 0,
+ mouseMovementY: 0,
+ touches: {},
+ lastTouches: {},
+ calculateMouseCoords(pageX, pageY) {
+ // Calculate the movement based on the changes
+ // in the coordinates.
+ var canvas = Browser.getCanvas();
+ var rect = canvas.getBoundingClientRect();
+ // Neither .scrollX or .pageXOffset are defined in a spec, but
+ // we prefer .scrollX because it is currently in a spec draft.
+ // (see: http://www.w3.org/TR/2013/WD-cssom-view-20131217/)
+ var scrollX = ((typeof window.scrollX != "undefined") ? window.scrollX : window.pageXOffset);
+ var scrollY = ((typeof window.scrollY != "undefined") ? window.scrollY : window.pageYOffset);
+ var adjustedX = pageX - (scrollX + rect.left);
+ var adjustedY = pageY - (scrollY + rect.top);
+ // the canvas might be CSS-scaled compared to its backbuffer;
+ // SDL-using content will want mouse coordinates in terms
+ // of backbuffer units.
+ adjustedX = adjustedX * (canvas.width / rect.width);
+ adjustedY = adjustedY * (canvas.height / rect.height);
+ return {
+ x: adjustedX,
+ y: adjustedY
+ };
+ },
+ setMouseCoords(pageX, pageY) {
+ const {x, y} = Browser.calculateMouseCoords(pageX, pageY);
+ Browser.mouseMovementX = x - Browser.mouseX;
+ Browser.mouseMovementY = y - Browser.mouseY;
+ Browser.mouseX = x;
+ Browser.mouseY = y;
+ },
+ calculateMouseEvent(event) {
+ // event should be mousemove, mousedown or mouseup
+ if (Browser.pointerLock) {
+ // When the pointer is locked, calculate the coordinates
+ // based on the movement of the mouse.
+ // Workaround for Firefox bug 764498
+ if (event.type != "mousemove" && ("mozMovementX" in event)) {
+ Browser.mouseMovementX = Browser.mouseMovementY = 0;
+ } else {
+ Browser.mouseMovementX = Browser.getMovementX(event);
+ Browser.mouseMovementY = Browser.getMovementY(event);
+ }
+ // add the mouse delta to the current absolute mouse position
+ Browser.mouseX += Browser.mouseMovementX;
+ Browser.mouseY += Browser.mouseMovementY;
+ } else {
+ if (event.type === "touchstart" || event.type === "touchend" || event.type === "touchmove") {
+ var touch = event.touch;
+ if (touch === undefined) {
+ return;
+ }
+ var coords = Browser.calculateMouseCoords(touch.pageX, touch.pageY);
+ if (event.type === "touchstart") {
+ Browser.lastTouches[touch.identifier] = coords;
+ Browser.touches[touch.identifier] = coords;
+ } else if (event.type === "touchend" || event.type === "touchmove") {
+ var last = Browser.touches[touch.identifier];
+ last ||= coords;
+ Browser.lastTouches[touch.identifier] = last;
+ Browser.touches[touch.identifier] = coords;
+ }
+ return;
+ }
+ Browser.setMouseCoords(event.pageX, event.pageY);
+ }
+ },
+ resizeListeners: [],
+ updateResizeListeners() {
+ var canvas = Browser.getCanvas();
+ Browser.resizeListeners.forEach(listener => listener(canvas.width, canvas.height));
+ },
+ setCanvasSize(width, height, noUpdates) {
+ var canvas = Browser.getCanvas();
+ Browser.updateCanvasDimensions(canvas, width, height);
+ if (!noUpdates) Browser.updateResizeListeners();
+ },
+ windowedWidth: 0,
+ windowedHeight: 0,
+ setFullscreenCanvasSize() {
+ // check if SDL is available
+ if (typeof SDL != "undefined") {
+ var flags = HEAPU32[((SDL.screen) >>> 2) >>> 0];
+ flags = flags | 8388608;
+ // set SDL_FULLSCREEN flag
+ HEAP32[((SDL.screen) >>> 2) >>> 0] = flags;
+ }
+ Browser.updateCanvasDimensions(Browser.getCanvas());
+ Browser.updateResizeListeners();
+ },
+ setWindowedCanvasSize() {
+ // check if SDL is available
+ if (typeof SDL != "undefined") {
+ var flags = HEAPU32[((SDL.screen) >>> 2) >>> 0];
+ flags = flags & ~8388608;
+ // clear SDL_FULLSCREEN flag
+ HEAP32[((SDL.screen) >>> 2) >>> 0] = flags;
+ }
+ Browser.updateCanvasDimensions(Browser.getCanvas());
+ Browser.updateResizeListeners();
+ },
+ updateCanvasDimensions(canvas, wNative, hNative) {
+ if (wNative && hNative) {
+ canvas.widthNative = wNative;
+ canvas.heightNative = hNative;
+ } else {
+ wNative = canvas.widthNative;
+ hNative = canvas.heightNative;
+ }
+ var w = wNative;
+ var h = hNative;
+ if (Module["forcedAspectRatio"] > 0) {
+ if (w / h < Module["forcedAspectRatio"]) {
+ w = Math.round(h * Module["forcedAspectRatio"]);
+ } else {
+ h = Math.round(w / Module["forcedAspectRatio"]);
+ }
+ }
+ if ((getFullscreenElement() === canvas.parentNode) && (typeof screen != "undefined")) {
+ var factor = Math.min(screen.width / w, screen.height / h);
+ w = Math.round(w * factor);
+ h = Math.round(h * factor);
+ }
+ if (Browser.resizeCanvas) {
+ if (canvas.width != w) canvas.width = w;
+ if (canvas.height != h) canvas.height = h;
+ if (typeof canvas.style != "undefined") {
+ canvas.style.removeProperty("width");
+ canvas.style.removeProperty("height");
+ }
+ } else {
+ if (canvas.width != wNative) canvas.width = wNative;
+ if (canvas.height != hNative) canvas.height = hNative;
+ if (typeof canvas.style != "undefined") {
+ if (w != wNative || h != hNative) {
+ canvas.style.setProperty("width", w + "px", "important");
+ canvas.style.setProperty("height", h + "px", "important");
+ } else {
+ canvas.style.removeProperty("width");
+ canvas.style.removeProperty("height");
+ }
+ }
+ }
+ }
+};
+
+var callRuntimeCallbacks = callbacks => {
+ while (callbacks.length > 0) {
+ // Pass the module as the first argument.
+ callbacks.shift()(Module);
+ }
+};
+
+var onPostRuns = [];
+
+var addOnPostRun = cb => onPostRuns.push(cb);
+
+var onPreRuns = [];
+
+var addOnPreRun = cb => onPreRuns.push(cb);
+
+var dynCalls = {};
+
+var dynCallLegacy = (sig, ptr, args) => {
+ sig = sig.replace(/p/g, "i");
+ var f = dynCalls[sig];
+ return f(ptr, ...args);
+};
+
+var dynCall = (sig, ptr, args = [], promising = false) => {
+ var rtn = dynCallLegacy(sig, ptr, args);
+ function convert(rtn) {
+ return sig[0] == "p" ? rtn >>> 0 : rtn;
+ }
+ return convert(rtn);
+};
+
+var noExitRuntime = true;
+
+var stackRestore = val => __emscripten_stack_restore(val);
+
+var stackSave = () => _emscripten_stack_get_current();
+
+class ExceptionInfo {
+ // excPtr - Thrown object pointer to wrap. Metadata pointer is calculated from it.
+ constructor(excPtr) {
+ this.excPtr = excPtr;
+ this.ptr = excPtr - 24;
+ }
+ set_type(type) {
+ HEAPU32[(((this.ptr) + (4)) >>> 2) >>> 0] = type;
+ }
+ get_type() {
+ return HEAPU32[(((this.ptr) + (4)) >>> 2) >>> 0];
+ }
+ set_destructor(destructor) {
+ HEAPU32[(((this.ptr) + (8)) >>> 2) >>> 0] = destructor;
+ }
+ get_destructor() {
+ return HEAPU32[(((this.ptr) + (8)) >>> 2) >>> 0];
+ }
+ set_caught(caught) {
+ caught = caught ? 1 : 0;
+ HEAP8[(this.ptr) + (12) >>> 0] = caught;
+ }
+ get_caught() {
+ return HEAP8[(this.ptr) + (12) >>> 0] != 0;
+ }
+ set_rethrown(rethrown) {
+ rethrown = rethrown ? 1 : 0;
+ HEAP8[(this.ptr) + (13) >>> 0] = rethrown;
+ }
+ get_rethrown() {
+ return HEAP8[(this.ptr) + (13) >>> 0] != 0;
+ }
+ // Initialize native structure fields. Should be called once after allocated.
+ init(type, destructor) {
+ this.set_adjusted_ptr(0);
+ this.set_type(type);
+ this.set_destructor(destructor);
+ }
+ set_adjusted_ptr(adjustedPtr) {
+ HEAPU32[(((this.ptr) + (16)) >>> 2) >>> 0] = adjustedPtr;
+ }
+ get_adjusted_ptr() {
+ return HEAPU32[(((this.ptr) + (16)) >>> 2) >>> 0];
+ }
+}
+
+var exceptionLast = 0;
+
+var uncaughtExceptionCount = 0;
+
+var convertI32PairToI53Checked = (lo, hi) => ((hi + 2097152) >>> 0 < 4194305 - !!lo) ? (lo >>> 0) + hi * 4294967296 : NaN;
+
+function ___cxa_throw(ptr, type, destructor) {
+ ptr >>>= 0;
+ type >>>= 0;
+ destructor >>>= 0;
+ var info = new ExceptionInfo(ptr);
+ // Initialize ExceptionInfo content after it was allocated in __cxa_allocate_exception.
+ info.init(type, destructor);
+ exceptionLast = ptr;
+ uncaughtExceptionCount++;
+ throw exceptionLast;
+}
+
+function __Unwind_RaiseException(ex) {
+ ex >>>= 0;
+ err("Warning: _Unwind_RaiseException is not correctly implemented");
+ return ___cxa_throw(ex, 0, 0);
+}
+
+var PATH = {
+ isAbs: path => path.charAt(0) === "/",
+ splitPath: filename => {
+ var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
+ return splitPathRe.exec(filename).slice(1);
+ },
+ normalizeArray: (parts, allowAboveRoot) => {
+ // if the path tries to go above the root, `up` ends up > 0
+ var up = 0;
+ for (var i = parts.length - 1; i >= 0; i--) {
+ var last = parts[i];
+ if (last === ".") {
+ parts.splice(i, 1);
+ } else if (last === "..") {
+ parts.splice(i, 1);
+ up++;
+ } else if (up) {
+ parts.splice(i, 1);
+ up--;
+ }
+ }
+ // if the path is allowed to go above the root, restore leading ..s
+ if (allowAboveRoot) {
+ for (;up; up--) {
+ parts.unshift("..");
+ }
+ }
+ return parts;
+ },
+ normalize: path => {
+ var isAbsolute = PATH.isAbs(path), trailingSlash = path.slice(-1) === "/";
+ // Normalize the path
+ path = PATH.normalizeArray(path.split("/").filter(p => !!p), !isAbsolute).join("/");
+ if (!path && !isAbsolute) {
+ path = ".";
+ }
+ if (path && trailingSlash) {
+ path += "/";
+ }
+ return (isAbsolute ? "/" : "") + path;
+ },
+ dirname: path => {
+ var result = PATH.splitPath(path), root = result[0], dir = result[1];
+ if (!root && !dir) {
+ // No dirname whatsoever
+ return ".";
+ }
+ if (dir) {
+ // It has a dirname, strip trailing slash
+ dir = dir.slice(0, -1);
+ }
+ return root + dir;
+ },
+ basename: path => path && path.match(/([^\/]+|\/)\/*$/)[1],
+ join: (...paths) => PATH.normalize(paths.join("/")),
+ join2: (l, r) => PATH.normalize(l + "/" + r)
+};
+
+var initRandomFill = () => {
+ // This block is not needed on v19+ since crypto.getRandomValues is builtin
+ if (ENVIRONMENT_IS_NODE) {
+ var nodeCrypto = require("node:crypto");
+ return view => nodeCrypto.randomFillSync(view);
+ }
+ return view => crypto.getRandomValues(view);
+};
+
+var randomFill = view => {
+ // Lazily init on the first invocation.
+ (randomFill = initRandomFill())(view);
+};
+
+var PATH_FS = {
+ resolve: (...args) => {
+ var resolvedPath = "", resolvedAbsolute = false;
+ for (var i = args.length - 1; i >= -1 && !resolvedAbsolute; i--) {
+ var path = (i >= 0) ? args[i] : FS.cwd();
+ // Skip empty and invalid entries
+ if (typeof path != "string") {
+ throw new TypeError("Arguments to path.resolve must be strings");
+ } else if (!path) {
+ return "";
+ }
+ resolvedPath = path + "/" + resolvedPath;
+ resolvedAbsolute = PATH.isAbs(path);
+ }
+ // At this point the path should be resolved to a full absolute path, but
+ // handle relative paths to be safe (might happen when process.cwd() fails)
+ resolvedPath = PATH.normalizeArray(resolvedPath.split("/").filter(p => !!p), !resolvedAbsolute).join("/");
+ return ((resolvedAbsolute ? "/" : "") + resolvedPath) || ".";
+ },
+ relative: (from, to) => {
+ from = PATH_FS.resolve(from).slice(1);
+ to = PATH_FS.resolve(to).slice(1);
+ function trim(arr) {
+ var start = 0;
+ for (;start < arr.length; start++) {
+ if (arr[start] !== "") break;
+ }
+ var end = arr.length - 1;
+ for (;end >= 0; end--) {
+ if (arr[end] !== "") break;
+ }
+ if (start > end) return [];
+ return arr.slice(start, end - start + 1);
+ }
+ var fromParts = trim(from.split("/"));
+ var toParts = trim(to.split("/"));
+ var length = Math.min(fromParts.length, toParts.length);
+ var samePartsLength = length;
+ for (var i = 0; i < length; i++) {
+ if (fromParts[i] !== toParts[i]) {
+ samePartsLength = i;
+ break;
+ }
+ }
+ var outputParts = [];
+ for (var i = samePartsLength; i < fromParts.length; i++) {
+ outputParts.push("..");
+ }
+ outputParts = outputParts.concat(toParts.slice(samePartsLength));
+ return outputParts.join("/");
+ }
+};
+
+var UTF8Decoder = new TextDecoder;
+
+var findStringEnd = (heapOrArray, idx, maxBytesToRead, ignoreNul) => {
+ var maxIdx = idx + maxBytesToRead;
+ if (ignoreNul) return maxIdx;
+ // TextDecoder needs to know the byte length in advance, it doesn't stop on
+ // null terminator by itself.
+ // As a tiny code save trick, compare idx against maxIdx using a negation,
+ // so that maxBytesToRead=undefined/NaN means Infinity.
+ while (heapOrArray[idx] && !(idx >= maxIdx)) ++idx;
+ return idx;
+};
+
+/**
+ * Given a pointer 'idx' to a null-terminated UTF8-encoded string in the given
+ * array that contains uint8 values, returns a copy of that string as a
+ * Javascript String object.
+ * heapOrArray is either a regular array, or a JavaScript typed array view.
+ * @param {number=} idx
+ * @param {number=} maxBytesToRead
+ * @param {boolean=} ignoreNul - If true, the function will not stop on a NUL character.
+ * @return {string}
+ */ var UTF8ArrayToString = (heapOrArray, idx = 0, maxBytesToRead, ignoreNul) => {
+ idx >>>= 0;
+ var endPtr = findStringEnd(heapOrArray, idx, maxBytesToRead, ignoreNul);
+ return UTF8Decoder.decode(heapOrArray.buffer ? heapOrArray.subarray(idx, endPtr) : new Uint8Array(heapOrArray.slice(idx, endPtr)));
+};
+
+var FS_stdin_getChar_buffer = [];
+
+var lengthBytesUTF8 = str => {
+ var len = 0;
+ for (var i = 0; i < str.length; ++i) {
+ // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code
+ // unit, not a Unicode code point of the character! So decode
+ // UTF16->UTF32->UTF8.
+ // See http://unicode.org/faq/utf_bom.html#utf16-3
+ var c = str.charCodeAt(i);
+ // possibly a lead surrogate
+ if (c <= 127) {
+ len++;
+ } else if (c <= 2047) {
+ len += 2;
+ } else if (c >= 55296 && c <= 57343) {
+ len += 4;
+ ++i;
+ } else {
+ len += 3;
+ }
+ }
+ return len;
+};
+
+var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
+ outIdx >>>= 0;
+ // Parameter maxBytesToWrite is not optional. Negative values, 0, null,
+ // undefined and false each don't write out any bytes.
+ if (!(maxBytesToWrite > 0)) return 0;
+ var startIdx = outIdx;
+ var endIdx = outIdx + maxBytesToWrite - 1;
+ // -1 for string null terminator.
+ for (var i = 0; i < str.length; ++i) {
+ // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description
+ // and https://www.ietf.org/rfc/rfc2279.txt
+ // and https://tools.ietf.org/html/rfc3629
+ var u = str.codePointAt(i);
+ if (u <= 127) {
+ if (outIdx >= endIdx) break;
+ heap[outIdx++ >>> 0] = u;
+ } else if (u <= 2047) {
+ if (outIdx + 1 >= endIdx) break;
+ heap[outIdx++ >>> 0] = 192 | (u >> 6);
+ heap[outIdx++ >>> 0] = 128 | (u & 63);
+ } else if (u <= 65535) {
+ if (outIdx + 2 >= endIdx) break;
+ heap[outIdx++ >>> 0] = 224 | (u >> 12);
+ heap[outIdx++ >>> 0] = 128 | ((u >> 6) & 63);
+ heap[outIdx++ >>> 0] = 128 | (u & 63);
+ } else {
+ if (outIdx + 3 >= endIdx) break;
+ heap[outIdx++ >>> 0] = 240 | (u >> 18);
+ heap[outIdx++ >>> 0] = 128 | ((u >> 12) & 63);
+ heap[outIdx++ >>> 0] = 128 | ((u >> 6) & 63);
+ heap[outIdx++ >>> 0] = 128 | (u & 63);
+ // Gotcha: if codePoint is over 0xFFFF, it is represented as a surrogate pair in UTF-16.
+ // We need to manually skip over the second code unit for correct iteration.
+ i++;
+ }
+ }
+ // Null-terminate the pointer to the buffer.
+ heap[outIdx >>> 0] = 0;
+ return outIdx - startIdx;
+};
+
+/** @type {function(string, boolean=, number=)} */ var intArrayFromString = (stringy, dontAddNull, length) => {
+ var len = length > 0 ? length : lengthBytesUTF8(stringy) + 1;
+ var u8array = new Array(len);
+ var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length);
+ if (dontAddNull) u8array.length = numBytesWritten;
+ return u8array;
+};
+
+var FS_stdin_getChar = () => {
+ if (!FS_stdin_getChar_buffer.length) {
+ var result = null;
+ if (ENVIRONMENT_IS_NODE) {
+ // we will read data by chunks of BUFSIZE
+ var BUFSIZE = 256;
+ var buf = Buffer.alloc(BUFSIZE);
+ var bytesRead = 0;
+ // For some reason we must suppress a closure warning here, even though
+ // fd definitely exists on process.stdin, and is even the proper way to
+ // get the fd of stdin,
+ // https://github.com/nodejs/help/issues/2136#issuecomment-523649904
+ // This started to happen after moving this logic out of library_tty.js,
+ // so it is related to the surrounding code in some unclear manner.
+ /** @suppress {missingProperties} */ var fd = process.stdin.fd;
+ try {
+ bytesRead = fs.readSync(fd, buf, 0, BUFSIZE);
+ } catch (e) {
+ // Cross-platform differences: on Windows, reading EOF throws an
+ // exception, but on other OSes, reading EOF returns 0. Uniformize
+ // behavior by treating the EOF exception to return 0.
+ if (e.toString().includes("EOF")) bytesRead = 0; else throw e;
+ }
+ if (bytesRead > 0) {
+ result = buf.slice(0, bytesRead).toString("utf-8");
+ }
+ } else if (globalThis.window?.prompt) {
+ // Browser.
+ result = window.prompt("Input: ");
+ // returns null on cancel
+ if (result !== null) {
+ result += "\n";
+ }
+ } else {}
+ if (!result) {
+ return null;
+ }
+ FS_stdin_getChar_buffer = intArrayFromString(result, true);
+ }
+ return FS_stdin_getChar_buffer.shift();
+};
+
+var TTY = {
+ ttys: [],
+ init() {},
+ shutdown() {},
+ register(dev, ops) {
+ TTY.ttys[dev] = {
+ input: [],
+ output: [],
+ ops
+ };
+ FS.registerDevice(dev, TTY.stream_ops);
+ },
+ stream_ops: {
+ open(stream) {
+ var tty = TTY.ttys[stream.node.rdev];
+ if (!tty) {
+ throw new FS.ErrnoError(43);
+ }
+ stream.tty = tty;
+ stream.seekable = false;
+ },
+ close(stream) {
+ // flush any pending line data
+ stream.tty.ops.fsync(stream.tty);
+ },
+ fsync(stream) {
+ stream.tty.ops.fsync(stream.tty);
+ },
+ read(stream, buffer, offset, length, pos) {
+ if (!stream.tty || !stream.tty.ops.get_char) {
+ throw new FS.ErrnoError(60);
+ }
+ var bytesRead = 0;
+ for (var i = 0; i < length; i++) {
+ var result;
+ try {
+ result = stream.tty.ops.get_char(stream.tty);
+ } catch (e) {
+ throw new FS.ErrnoError(29);
+ }
+ if (result === undefined && bytesRead === 0) {
+ throw new FS.ErrnoError(6);
+ }
+ if (result === null || result === undefined) break;
+ bytesRead++;
+ buffer[offset + i] = result;
+ }
+ if (bytesRead) {
+ stream.node.atime = Date.now();
+ }
+ return bytesRead;
+ },
+ write(stream, buffer, offset, length, pos) {
+ if (!stream.tty || !stream.tty.ops.put_char) {
+ throw new FS.ErrnoError(60);
+ }
+ try {
+ for (var i = 0; i < length; i++) {
+ stream.tty.ops.put_char(stream.tty, buffer[offset + i]);
+ }
+ } catch (e) {
+ throw new FS.ErrnoError(29);
+ }
+ if (length) {
+ stream.node.mtime = stream.node.ctime = Date.now();
+ }
+ return i;
+ }
+ },
+ default_tty_ops: {
+ get_char(tty) {
+ return FS_stdin_getChar();
+ },
+ put_char(tty, val) {
+ if (val === null || val === 10) {
+ out(UTF8ArrayToString(tty.output));
+ tty.output = [];
+ } else {
+ if (val != 0) tty.output.push(val);
+ }
+ },
+ fsync(tty) {
+ if (tty.output?.length > 0) {
+ out(UTF8ArrayToString(tty.output));
+ tty.output = [];
+ }
+ },
+ ioctl_tcgets(tty) {
+ // typical setting
+ 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(tty, optional_actions, data) {
+ // currently just ignore
+ return 0;
+ },
+ ioctl_tiocgwinsz(tty) {
+ return [ 24, 80 ];
+ }
+ },
+ default_tty1_ops: {
+ put_char(tty, val) {
+ if (val === null || val === 10) {
+ err(UTF8ArrayToString(tty.output));
+ tty.output = [];
+ } else {
+ if (val != 0) tty.output.push(val);
+ }
+ },
+ fsync(tty) {
+ if (tty.output?.length > 0) {
+ err(UTF8ArrayToString(tty.output));
+ tty.output = [];
+ }
+ }
+ }
+};
+
+var zeroMemory = (ptr, size) => HEAPU8.fill(0, ptr, ptr + size);
+
+var alignMemory = (size, alignment) => Math.ceil(size / alignment) * alignment;
+
+var mmapAlloc = size => {
+ size = alignMemory(size, 65536);
+ var ptr = _emscripten_builtin_memalign(65536, size);
+ if (ptr) zeroMemory(ptr, size);
+ return ptr;
+};
+
+var MEMFS = {
+ ops_table: null,
+ mount(mount) {
+ return MEMFS.createNode(null, "/", 16895, 0);
+ },
+ createNode(parent, name, mode, dev) {
+ if (FS.isBlkdev(mode) || FS.isFIFO(mode)) {
+ // not supported
+ throw new FS.ErrnoError(63);
+ }
+ MEMFS.ops_table ||= {
+ dir: {
+ node: {
+ getattr: MEMFS.node_ops.getattr,
+ setattr: MEMFS.node_ops.setattr,
+ lookup: MEMFS.node_ops.lookup,
+ mknod: MEMFS.node_ops.mknod,
+ rename: MEMFS.node_ops.rename,
+ unlink: MEMFS.node_ops.unlink,
+ rmdir: MEMFS.node_ops.rmdir,
+ readdir: MEMFS.node_ops.readdir,
+ symlink: MEMFS.node_ops.symlink
+ },
+ stream: {
+ llseek: MEMFS.stream_ops.llseek
+ }
+ },
+ file: {
+ node: {
+ getattr: MEMFS.node_ops.getattr,
+ setattr: MEMFS.node_ops.setattr
+ },
+ stream: {
+ llseek: MEMFS.stream_ops.llseek,
+ read: MEMFS.stream_ops.read,
+ write: MEMFS.stream_ops.write,
+ mmap: MEMFS.stream_ops.mmap,
+ msync: MEMFS.stream_ops.msync
+ }
+ },
+ link: {
+ node: {
+ getattr: MEMFS.node_ops.getattr,
+ setattr: MEMFS.node_ops.setattr,
+ readlink: MEMFS.node_ops.readlink
+ },
+ stream: {}
+ },
+ chrdev: {
+ node: {
+ getattr: MEMFS.node_ops.getattr,
+ setattr: MEMFS.node_ops.setattr
+ },
+ stream: FS.chrdev_stream_ops
+ }
+ };
+ var node = FS.createNode(parent, name, mode, dev);
+ if (FS.isDir(node.mode)) {
+ node.node_ops = MEMFS.ops_table.dir.node;
+ node.stream_ops = MEMFS.ops_table.dir.stream;
+ node.contents = {};
+ } else if (FS.isFile(node.mode)) {
+ node.node_ops = MEMFS.ops_table.file.node;
+ node.stream_ops = MEMFS.ops_table.file.stream;
+ node.usedBytes = 0;
+ // The actual number of bytes used in the typed array, as opposed to contents.length which gives the whole capacity.
+ // When the byte data of the file is populated, this will point to either a typed array, or a normal JS array. Typed arrays are preferred
+ // for performance, and used by default. However, typed arrays are not resizable like normal JS arrays are, so there is a small disk size
+ // penalty involved for appending file writes that continuously grow a file similar to std::vector capacity vs used -scheme.
+ node.contents = null;
+ } else if (FS.isLink(node.mode)) {
+ node.node_ops = MEMFS.ops_table.link.node;
+ node.stream_ops = MEMFS.ops_table.link.stream;
+ } else if (FS.isChrdev(node.mode)) {
+ node.node_ops = MEMFS.ops_table.chrdev.node;
+ node.stream_ops = MEMFS.ops_table.chrdev.stream;
+ }
+ node.atime = node.mtime = node.ctime = Date.now();
+ // add the new node to the parent
+ if (parent) {
+ parent.contents[name] = node;
+ parent.atime = parent.mtime = parent.ctime = node.atime;
+ }
+ return node;
+ },
+ getFileDataAsTypedArray(node) {
+ if (!node.contents) return new Uint8Array(0);
+ if (node.contents.subarray) return node.contents.subarray(0, node.usedBytes);
+ // Make sure to not return excess unused bytes.
+ return new Uint8Array(node.contents);
+ },
+ expandFileStorage(node, newCapacity) {
+ var prevCapacity = node.contents ? node.contents.length : 0;
+ if (prevCapacity >= newCapacity) return;
+ // No need to expand, the storage was already large enough.
+ // Don't expand strictly to the given requested limit if it's only a very small increase, but instead geometrically grow capacity.
+ // For small filesizes (<1MB), perform size*2 geometric increase, but for large sizes, do a much more conservative size*1.125 increase to
+ // avoid overshooting the allocation cap by a very large margin.
+ var CAPACITY_DOUBLING_MAX = 1024 * 1024;
+ newCapacity = Math.max(newCapacity, (prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2 : 1.125)) >>> 0);
+ if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256);
+ // At minimum allocate 256b for each file when expanding.
+ var oldContents = node.contents;
+ node.contents = new Uint8Array(newCapacity);
+ // Allocate new storage.
+ if (node.usedBytes > 0) node.contents.set(oldContents.subarray(0, node.usedBytes), 0);
+ },
+ resizeFileStorage(node, newSize) {
+ if (node.usedBytes == newSize) return;
+ if (newSize == 0) {
+ node.contents = null;
+ // Fully decommit when requesting a resize to zero.
+ node.usedBytes = 0;
+ } else {
+ var oldContents = node.contents;
+ node.contents = new Uint8Array(newSize);
+ // Allocate new storage.
+ if (oldContents) {
+ node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes)));
+ }
+ node.usedBytes = newSize;
+ }
+ },
+ node_ops: {
+ getattr(node) {
+ var attr = {};
+ // device numbers reuse inode numbers.
+ attr.dev = FS.isChrdev(node.mode) ? node.id : 1;
+ attr.ino = node.id;
+ attr.mode = node.mode;
+ attr.nlink = 1;
+ attr.uid = 0;
+ attr.gid = 0;
+ attr.rdev = node.rdev;
+ if (FS.isDir(node.mode)) {
+ attr.size = 4096;
+ } else if (FS.isFile(node.mode)) {
+ attr.size = node.usedBytes;
+ } else if (FS.isLink(node.mode)) {
+ attr.size = node.link.length;
+ } else {
+ attr.size = 0;
+ }
+ attr.atime = new Date(node.atime);
+ attr.mtime = new Date(node.mtime);
+ attr.ctime = new Date(node.ctime);
+ // NOTE: In our implementation, st_blocks = Math.ceil(st_size/st_blksize),
+ // but this is not required by the standard.
+ attr.blksize = 4096;
+ attr.blocks = Math.ceil(attr.size / attr.blksize);
+ return attr;
+ },
+ setattr(node, attr) {
+ for (const key of [ "mode", "atime", "mtime", "ctime" ]) {
+ if (attr[key] != null) {
+ node[key] = attr[key];
+ }
+ }
+ if (attr.size !== undefined) {
+ MEMFS.resizeFileStorage(node, attr.size);
+ }
+ },
+ lookup(parent, name) {
+ // This error may happen quite a bit. To avoid overhead we reuse it (and
+ // suffer a lack of stack info).
+ if (!MEMFS.doesNotExistError) {
+ MEMFS.doesNotExistError = new FS.ErrnoError(44);
+ /** @suppress {checkTypes} */ MEMFS.doesNotExistError.stack = "";
+ }
+ throw MEMFS.doesNotExistError;
+ },
+ mknod(parent, name, mode, dev) {
+ return MEMFS.createNode(parent, name, mode, dev);
+ },
+ rename(old_node, new_dir, new_name) {
+ var new_node;
+ try {
+ new_node = FS.lookupNode(new_dir, new_name);
+ } catch (e) {}
+ if (new_node) {
+ if (FS.isDir(old_node.mode)) {
+ // if we're overwriting a directory at new_name, make sure it's empty.
+ for (var i in new_node.contents) {
+ throw new FS.ErrnoError(55);
+ }
+ }
+ FS.hashRemoveNode(new_node);
+ }
+ // do the internal rewiring
+ delete old_node.parent.contents[old_node.name];
+ new_dir.contents[new_name] = old_node;
+ old_node.name = new_name;
+ new_dir.ctime = new_dir.mtime = old_node.parent.ctime = old_node.parent.mtime = Date.now();
+ },
+ unlink(parent, name) {
+ delete parent.contents[name];
+ parent.ctime = parent.mtime = Date.now();
+ },
+ rmdir(parent, name) {
+ var node = FS.lookupNode(parent, name);
+ for (var i in node.contents) {
+ throw new FS.ErrnoError(55);
+ }
+ delete parent.contents[name];
+ parent.ctime = parent.mtime = Date.now();
+ },
+ readdir(node) {
+ return [ ".", "..", ...Object.keys(node.contents) ];
+ },
+ symlink(parent, newname, oldpath) {
+ var node = MEMFS.createNode(parent, newname, 511 | 40960, 0);
+ node.link = oldpath;
+ return node;
+ },
+ readlink(node) {
+ if (!FS.isLink(node.mode)) {
+ throw new FS.ErrnoError(28);
+ }
+ return node.link;
+ }
+ },
+ stream_ops: {
+ read(stream, buffer, offset, length, position) {
+ var contents = stream.node.contents;
+ if (position >= stream.node.usedBytes) return 0;
+ var size = Math.min(stream.node.usedBytes - position, length);
+ if (size > 8 && contents.subarray) {
+ // non-trivial, and typed array
+ buffer.set(contents.subarray(position, position + size), offset);
+ } else {
+ for (var i = 0; i < size; i++) buffer[offset + i] = contents[position + i];
+ }
+ return size;
+ },
+ write(stream, buffer, offset, length, position, canOwn) {
+ // If the buffer is located in main memory (HEAP), and if
+ // memory can grow, we can't hold on to references of the
+ // memory buffer, as they may get invalidated. That means we
+ // need to copy its contents.
+ if (buffer.buffer === HEAP8.buffer) {
+ canOwn = false;
+ }
+ if (!length) return 0;
+ var node = stream.node;
+ node.mtime = node.ctime = Date.now();
+ if (buffer.subarray && (!node.contents || node.contents.subarray)) {
+ // This write is from a typed array to a typed array?
+ if (canOwn) {
+ node.contents = buffer.subarray(offset, offset + length);
+ node.usedBytes = length;
+ return length;
+ } else if (node.usedBytes === 0 && position === 0) {
+ // If this is a simple first write to an empty file, do a fast set since we don't need to care about old data.
+ node.contents = buffer.slice(offset, offset + length);
+ node.usedBytes = length;
+ return length;
+ } else if (position + length <= node.usedBytes) {
+ // Writing to an already allocated and used subrange of the file?
+ node.contents.set(buffer.subarray(offset, offset + length), position);
+ return length;
+ }
+ }
+ // Appending to an existing file and we need to reallocate, or source data did not come as a typed array.
+ MEMFS.expandFileStorage(node, position + length);
+ if (node.contents.subarray && buffer.subarray) {
+ // Use typed array write which is available.
+ node.contents.set(buffer.subarray(offset, offset + length), position);
+ } else {
+ for (var i = 0; i < length; i++) {
+ node.contents[position + i] = buffer[offset + i];
+ }
+ }
+ node.usedBytes = Math.max(node.usedBytes, position + length);
+ return length;
+ },
+ llseek(stream, offset, whence) {
+ var position = offset;
+ if (whence === 1) {
+ position += stream.position;
+ } else if (whence === 2) {
+ if (FS.isFile(stream.node.mode)) {
+ position += stream.node.usedBytes;
+ }
+ }
+ if (position < 0) {
+ throw new FS.ErrnoError(28);
+ }
+ return position;
+ },
+ mmap(stream, length, position, prot, flags) {
+ if (!FS.isFile(stream.node.mode)) {
+ throw new FS.ErrnoError(43);
+ }
+ var ptr;
+ var allocated;
+ var contents = stream.node.contents;
+ // Only make a new copy when MAP_PRIVATE is specified.
+ if (!(flags & 2) && contents && contents.buffer === HEAP8.buffer) {
+ // We can't emulate MAP_SHARED when the file is not backed by the
+ // buffer we're mapping to (e.g. the HEAP buffer).
+ allocated = false;
+ ptr = contents.byteOffset;
+ } else {
+ allocated = true;
+ ptr = mmapAlloc(length);
+ if (!ptr) {
+ throw new FS.ErrnoError(48);
+ }
+ if (contents) {
+ // Try to avoid unnecessary slices.
+ if (position > 0 || position + length < contents.length) {
+ if (contents.subarray) {
+ contents = contents.subarray(position, position + length);
+ } else {
+ contents = Array.prototype.slice.call(contents, position, position + length);
+ }
+ }
+ HEAP8.set(contents, ptr >>> 0);
+ }
+ }
+ return {
+ ptr,
+ allocated
+ };
+ },
+ msync(stream, buffer, offset, length, mmapFlags) {
+ MEMFS.stream_ops.write(stream, buffer, 0, length, offset, false);
+ // should we check if bytesWritten and length are the same?
+ return 0;
+ }
+ }
+};
+
+var FS_modeStringToFlags = str => {
+ var flagModes = {
+ "r": 0,
+ "r+": 2,
+ "w": 512 | 64 | 1,
+ "w+": 512 | 64 | 2,
+ "a": 1024 | 64 | 1,
+ "a+": 1024 | 64 | 2
+ };
+ var flags = flagModes[str];
+ if (typeof flags == "undefined") {
+ throw new Error(`Unknown file open mode: ${str}`);
+ }
+ return flags;
+};
+
+var FS_getMode = (canRead, canWrite) => {
+ var mode = 0;
+ if (canRead) mode |= 292 | 73;
+ if (canWrite) mode |= 146;
+ return mode;
+};
+
+var asyncLoad = async url => {
+ var arrayBuffer = await readAsync(url);
+ return new Uint8Array(arrayBuffer);
+};
+
+var FS_createDataFile = (...args) => FS.createDataFile(...args);
+
+var getUniqueRunDependency = id => id;
+
+var runDependencies = 0;
+
+var dependenciesFulfilled = null;
+
+var removeRunDependency = id => {
+ runDependencies--;
+ Module["monitorRunDependencies"]?.(runDependencies);
+ if (runDependencies == 0) {
+ if (dependenciesFulfilled) {
+ var callback = dependenciesFulfilled;
+ dependenciesFulfilled = null;
+ callback();
+ }
+ }
+};
+
+var addRunDependency = id => {
+ runDependencies++;
+ Module["monitorRunDependencies"]?.(runDependencies);
+};
+
+var FS_handledByPreloadPlugin = async (byteArray, fullname) => {
+ // Ensure plugins are ready.
+ if (typeof Browser != "undefined") Browser.init();
+ for (var plugin of preloadPlugins) {
+ if (plugin["canHandle"](fullname)) {
+ return plugin["handle"](byteArray, fullname);
+ }
+ }
+ // If no plugin handled this file then return the original/unmodified
+ // byteArray.
+ return byteArray;
+};
+
+var FS_preloadFile = async (parent, name, url, canRead, canWrite, dontCreateFile, canOwn, preFinish) => {
+ // TODO we should allow people to just pass in a complete filename instead
+ // of parent and name being that we just join them anyways
+ var fullname = name ? PATH_FS.resolve(PATH.join2(parent, name)) : parent;
+ var dep = getUniqueRunDependency(`cp ${fullname}`);
+ // might have several active requests for the same fullname
+ addRunDependency(dep);
+ try {
+ var byteArray = url;
+ if (typeof url == "string") {
+ byteArray = await asyncLoad(url);
+ }
+ byteArray = await FS_handledByPreloadPlugin(byteArray, fullname);
+ preFinish?.();
+ if (!dontCreateFile) {
+ FS_createDataFile(parent, name, byteArray, canRead, canWrite, canOwn);
+ }
+ } finally {
+ removeRunDependency(dep);
+ }
+};
+
+var FS_createPreloadedFile = (parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) => {
+ FS_preloadFile(parent, name, url, canRead, canWrite, dontCreateFile, canOwn, preFinish).then(onload).catch(onerror);
+};
+
+var FS = {
+ root: null,
+ mounts: [],
+ devices: {},
+ streams: [],
+ nextInode: 1,
+ nameTable: null,
+ currentPath: "/",
+ initialized: false,
+ ignorePermissions: true,
+ filesystems: null,
+ syncFSRequests: 0,
+ ErrnoError: class {
+ name="ErrnoError";
+ // We set the `name` property to be able to identify `FS.ErrnoError`
+ // - the `name` is a standard ECMA-262 property of error objects. Kind of good to have it anyway.
+ // - when using PROXYFS, an error can come from an underlying FS
+ // as different FS objects have their own FS.ErrnoError each,
+ // the test `err instanceof FS.ErrnoError` won't detect an error coming from another filesystem, causing bugs.
+ // we'll use the reliable test `err.name == "ErrnoError"` instead
+ constructor(errno) {
+ this.errno = errno;
+ }
+ },
+ FSStream: class {
+ shared={};
+ get object() {
+ return this.node;
+ }
+ set object(val) {
+ this.node = val;
+ }
+ get isRead() {
+ return (this.flags & 2097155) !== 1;
+ }
+ get isWrite() {
+ return (this.flags & 2097155) !== 0;
+ }
+ get isAppend() {
+ return (this.flags & 1024);
+ }
+ get flags() {
+ return this.shared.flags;
+ }
+ set flags(val) {
+ this.shared.flags = val;
+ }
+ get position() {
+ return this.shared.position;
+ }
+ set position(val) {
+ this.shared.position = val;
+ }
+ },
+ FSNode: class {
+ node_ops={};
+ stream_ops={};
+ readMode=292 | 73;
+ writeMode=146;
+ mounted=null;
+ constructor(parent, name, mode, rdev) {
+ if (!parent) {
+ parent = this;
+ }
+ this.parent = parent;
+ this.mount = parent.mount;
+ this.id = FS.nextInode++;
+ this.name = name;
+ this.mode = mode;
+ this.rdev = rdev;
+ this.atime = this.mtime = this.ctime = Date.now();
+ }
+ get read() {
+ return (this.mode & this.readMode) === this.readMode;
+ }
+ set read(val) {
+ val ? this.mode |= this.readMode : this.mode &= ~this.readMode;
+ }
+ get write() {
+ return (this.mode & this.writeMode) === this.writeMode;
+ }
+ set write(val) {
+ val ? this.mode |= this.writeMode : this.mode &= ~this.writeMode;
+ }
+ get isFolder() {
+ return FS.isDir(this.mode);
+ }
+ get isDevice() {
+ return FS.isChrdev(this.mode);
+ }
+ },
+ lookupPath(path, opts = {}) {
+ if (!path) {
+ throw new FS.ErrnoError(44);
+ }
+ opts.follow_mount ??= true;
+ if (!PATH.isAbs(path)) {
+ path = FS.cwd() + "/" + path;
+ }
+ // limit max consecutive symlinks to 40 (SYMLOOP_MAX).
+ linkloop: for (var nlinks = 0; nlinks < 40; nlinks++) {
+ // split the absolute path
+ var parts = path.split("/").filter(p => !!p);
+ // start at the root
+ var current = FS.root;
+ var current_path = "/";
+ for (var i = 0; i < parts.length; i++) {
+ var islast = (i === parts.length - 1);
+ if (islast && opts.parent) {
+ // stop resolving
+ break;
+ }
+ if (parts[i] === ".") {
+ continue;
+ }
+ if (parts[i] === "..") {
+ current_path = PATH.dirname(current_path);
+ if (FS.isRoot(current)) {
+ path = current_path + "/" + parts.slice(i + 1).join("/");
+ // We're making progress here, don't let many consecutive ..'s
+ // lead to ELOOP
+ nlinks--;
+ continue linkloop;
+ } else {
+ current = current.parent;
+ }
+ continue;
+ }
+ current_path = PATH.join2(current_path, parts[i]);
+ try {
+ current = FS.lookupNode(current, parts[i]);
+ } catch (e) {
+ // if noent_okay is true, suppress a ENOENT in the last component
+ // and return an object with an undefined node. This is needed for
+ // resolving symlinks in the path when creating a file.
+ if ((e?.errno === 44) && islast && opts.noent_okay) {
+ return {
+ path: current_path
+ };
+ }
+ throw e;
+ }
+ // jump to the mount's root node if this is a mountpoint
+ if (FS.isMountpoint(current) && (!islast || opts.follow_mount)) {
+ current = current.mounted.root;
+ }
+ // by default, lookupPath will not follow a symlink if it is the final path component.
+ // setting opts.follow = true will override this behavior.
+ if (FS.isLink(current.mode) && (!islast || opts.follow)) {
+ if (!current.node_ops.readlink) {
+ throw new FS.ErrnoError(52);
+ }
+ var link = current.node_ops.readlink(current);
+ if (!PATH.isAbs(link)) {
+ link = PATH.dirname(current_path) + "/" + link;
+ }
+ path = link + "/" + parts.slice(i + 1).join("/");
+ continue linkloop;
+ }
+ }
+ return {
+ path: current_path,
+ node: current
+ };
+ }
+ throw new FS.ErrnoError(32);
+ },
+ getPath(node) {
+ var path;
+ while (true) {
+ if (FS.isRoot(node)) {
+ var mount = node.mount.mountpoint;
+ if (!path) return mount;
+ return mount[mount.length - 1] !== "/" ? `${mount}/${path}` : mount + path;
+ }
+ path = path ? `${node.name}/${path}` : node.name;
+ node = node.parent;
+ }
+ },
+ hashName(parentid, name) {
+ var hash = 0;
+ for (var i = 0; i < name.length; i++) {
+ hash = ((hash << 5) - hash + name.charCodeAt(i)) | 0;
+ }
+ return ((parentid + hash) >>> 0) % FS.nameTable.length;
+ },
+ hashAddNode(node) {
+ var hash = FS.hashName(node.parent.id, node.name);
+ node.name_next = FS.nameTable[hash];
+ FS.nameTable[hash] = node;
+ },
+ hashRemoveNode(node) {
+ var hash = FS.hashName(node.parent.id, node.name);
+ if (FS.nameTable[hash] === node) {
+ FS.nameTable[hash] = node.name_next;
+ } else {
+ var current = FS.nameTable[hash];
+ while (current) {
+ if (current.name_next === node) {
+ current.name_next = node.name_next;
+ break;
+ }
+ current = current.name_next;
+ }
+ }
+ },
+ lookupNode(parent, name) {
+ var errCode = FS.mayLookup(parent);
+ if (errCode) {
+ throw new FS.ErrnoError(errCode);
+ }
+ var hash = FS.hashName(parent.id, name);
+ for (var node = FS.nameTable[hash]; node; node = node.name_next) {
+ var nodeName = node.name;
+ if (node.parent.id === parent.id && nodeName === name) {
+ return node;
+ }
+ }
+ // if we failed to find it in the cache, call into the VFS
+ return FS.lookup(parent, name);
+ },
+ createNode(parent, name, mode, rdev) {
+ var node = new FS.FSNode(parent, name, mode, rdev);
+ FS.hashAddNode(node);
+ return node;
+ },
+ destroyNode(node) {
+ FS.hashRemoveNode(node);
+ },
+ isRoot(node) {
+ return node === node.parent;
+ },
+ isMountpoint(node) {
+ return !!node.mounted;
+ },
+ isFile(mode) {
+ return (mode & 61440) === 32768;
+ },
+ isDir(mode) {
+ return (mode & 61440) === 16384;
+ },
+ isLink(mode) {
+ return (mode & 61440) === 40960;
+ },
+ isChrdev(mode) {
+ return (mode & 61440) === 8192;
+ },
+ isBlkdev(mode) {
+ return (mode & 61440) === 24576;
+ },
+ isFIFO(mode) {
+ return (mode & 61440) === 4096;
+ },
+ isSocket(mode) {
+ return (mode & 49152) === 49152;
+ },
+ flagsToPermissionString(flag) {
+ var perms = [ "r", "w", "rw" ][flag & 3];
+ if ((flag & 512)) {
+ perms += "w";
+ }
+ return perms;
+ },
+ nodePermissions(node, perms) {
+ if (FS.ignorePermissions) {
+ return 0;
+ }
+ // return 0 if any user, group or owner bits are set.
+ if (perms.includes("r") && !(node.mode & 292)) {
+ return 2;
+ }
+ if (perms.includes("w") && !(node.mode & 146)) {
+ return 2;
+ }
+ if (perms.includes("x") && !(node.mode & 73)) {
+ return 2;
+ }
+ return 0;
+ },
+ mayLookup(dir) {
+ if (!FS.isDir(dir.mode)) return 54;
+ var errCode = FS.nodePermissions(dir, "x");
+ if (errCode) return errCode;
+ if (!dir.node_ops.lookup) return 2;
+ return 0;
+ },
+ mayCreate(dir, name) {
+ if (!FS.isDir(dir.mode)) {
+ return 54;
+ }
+ try {
+ var node = FS.lookupNode(dir, name);
+ return 20;
+ } catch (e) {}
+ return FS.nodePermissions(dir, "wx");
+ },
+ mayDelete(dir, name, isdir) {
+ var node;
+ try {
+ node = FS.lookupNode(dir, name);
+ } catch (e) {
+ return e.errno;
+ }
+ var errCode = FS.nodePermissions(dir, "wx");
+ if (errCode) {
+ return errCode;
+ }
+ if (isdir) {
+ if (!FS.isDir(node.mode)) {
+ return 54;
+ }
+ if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) {
+ return 10;
+ }
+ } else if (FS.isDir(node.mode)) {
+ return 31;
+ }
+ return 0;
+ },
+ mayOpen(node, flags) {
+ if (!node) {
+ return 44;
+ }
+ if (FS.isLink(node.mode)) {
+ return 32;
+ }
+ var mode = FS.flagsToPermissionString(flags);
+ if (FS.isDir(node.mode)) {
+ // opening for write
+ // TODO: check for O_SEARCH? (== search for dir only)
+ if (mode !== "r" || (flags & (512 | 64))) {
+ return 31;
+ }
+ }
+ return FS.nodePermissions(node, mode);
+ },
+ checkOpExists(op, err) {
+ if (!op) {
+ throw new FS.ErrnoError(err);
+ }
+ return op;
+ },
+ MAX_OPEN_FDS: 4096,
+ nextfd() {
+ for (var fd = 0; fd <= FS.MAX_OPEN_FDS; fd++) {
+ if (!FS.streams[fd]) {
+ return fd;
+ }
+ }
+ throw new FS.ErrnoError(33);
+ },
+ getStreamChecked(fd) {
+ var stream = FS.getStream(fd);
+ if (!stream) {
+ throw new FS.ErrnoError(8);
+ }
+ return stream;
+ },
+ getStream: fd => FS.streams[fd],
+ createStream(stream, fd = -1) {
+ // clone it, so we can return an instance of FSStream
+ stream = Object.assign(new FS.FSStream, stream);
+ if (fd == -1) {
+ fd = FS.nextfd();
+ }
+ stream.fd = fd;
+ FS.streams[fd] = stream;
+ return stream;
+ },
+ closeStream(fd) {
+ FS.streams[fd] = null;
+ },
+ dupStream(origStream, fd = -1) {
+ var stream = FS.createStream(origStream, fd);
+ stream.stream_ops?.dup?.(stream);
+ return stream;
+ },
+ doSetAttr(stream, node, attr) {
+ var setattr = stream?.stream_ops.setattr;
+ var arg = setattr ? stream : node;
+ setattr ??= node.node_ops.setattr;
+ FS.checkOpExists(setattr, 63);
+ setattr(arg, attr);
+ },
+ chrdev_stream_ops: {
+ open(stream) {
+ var device = FS.getDevice(stream.node.rdev);
+ // override node's stream ops with the device's
+ stream.stream_ops = device.stream_ops;
+ // forward the open call
+ stream.stream_ops.open?.(stream);
+ },
+ llseek() {
+ throw new FS.ErrnoError(70);
+ }
+ },
+ major: dev => ((dev) >> 8),
+ minor: dev => ((dev) & 255),
+ makedev: (ma, mi) => ((ma) << 8 | (mi)),
+ registerDevice(dev, ops) {
+ FS.devices[dev] = {
+ stream_ops: ops
+ };
+ },
+ getDevice: dev => FS.devices[dev],
+ getMounts(mount) {
+ var mounts = [];
+ var check = [ mount ];
+ while (check.length) {
+ var m = check.pop();
+ mounts.push(m);
+ check.push(...m.mounts);
+ }
+ return mounts;
+ },
+ syncfs(populate, callback) {
+ if (typeof populate == "function") {
+ callback = populate;
+ populate = false;
+ }
+ FS.syncFSRequests++;
+ if (FS.syncFSRequests > 1) {
+ err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`);
+ }
+ var mounts = FS.getMounts(FS.root.mount);
+ var completed = 0;
+ function doCallback(errCode) {
+ FS.syncFSRequests--;
+ return callback(errCode);
+ }
+ function done(errCode) {
+ if (errCode) {
+ if (!done.errored) {
+ done.errored = true;
+ return doCallback(errCode);
+ }
+ return;
+ }
+ if (++completed >= mounts.length) {
+ doCallback(null);
+ }
+ }
+ // sync all mounts
+ for (var mount of mounts) {
+ if (mount.type.syncfs) {
+ mount.type.syncfs(mount, populate, done);
+ } else {
+ done(null);
+ }
+ }
+ },
+ mount(type, opts, mountpoint) {
+ var root = mountpoint === "/";
+ var pseudo = !mountpoint;
+ var node;
+ if (root && FS.root) {
+ throw new FS.ErrnoError(10);
+ } else if (!root && !pseudo) {
+ var lookup = FS.lookupPath(mountpoint, {
+ follow_mount: false
+ });
+ mountpoint = lookup.path;
+ // use the absolute path
+ node = lookup.node;
+ if (FS.isMountpoint(node)) {
+ throw new FS.ErrnoError(10);
+ }
+ if (!FS.isDir(node.mode)) {
+ throw new FS.ErrnoError(54);
+ }
+ }
+ var mount = {
+ type,
+ opts,
+ mountpoint,
+ mounts: []
+ };
+ // create a root node for the fs
+ var mountRoot = type.mount(mount);
+ mountRoot.mount = mount;
+ mount.root = mountRoot;
+ if (root) {
+ FS.root = mountRoot;
+ } else if (node) {
+ // set as a mountpoint
+ node.mounted = mount;
+ // add the new mount to the current mount's children
+ if (node.mount) {
+ node.mount.mounts.push(mount);
+ }
+ }
+ return mountRoot;
+ },
+ unmount(mountpoint) {
+ var lookup = FS.lookupPath(mountpoint, {
+ follow_mount: false
+ });
+ if (!FS.isMountpoint(lookup.node)) {
+ throw new FS.ErrnoError(28);
+ }
+ // destroy the nodes for this mount, and all its child mounts
+ var node = lookup.node;
+ var mount = node.mounted;
+ var mounts = FS.getMounts(mount);
+ for (var [hash, current] of Object.entries(FS.nameTable)) {
+ while (current) {
+ var next = current.name_next;
+ if (mounts.includes(current.mount)) {
+ FS.destroyNode(current);
+ }
+ current = next;
+ }
+ }
+ // no longer a mountpoint
+ node.mounted = null;
+ // remove this mount from the child mounts
+ var idx = node.mount.mounts.indexOf(mount);
+ node.mount.mounts.splice(idx, 1);
+ },
+ lookup(parent, name) {
+ return parent.node_ops.lookup(parent, name);
+ },
+ mknod(path, mode, dev) {
+ var lookup = FS.lookupPath(path, {
+ parent: true
+ });
+ var parent = lookup.node;
+ var name = PATH.basename(path);
+ if (!name) {
+ throw new FS.ErrnoError(28);
+ }
+ if (name === "." || name === "..") {
+ throw new FS.ErrnoError(20);
+ }
+ var errCode = FS.mayCreate(parent, name);
+ if (errCode) {
+ throw new FS.ErrnoError(errCode);
+ }
+ if (!parent.node_ops.mknod) {
+ throw new FS.ErrnoError(63);
+ }
+ return parent.node_ops.mknod(parent, name, mode, dev);
+ },
+ statfs(path) {
+ return FS.statfsNode(FS.lookupPath(path, {
+ follow: true
+ }).node);
+ },
+ statfsStream(stream) {
+ // We keep a separate statfsStream function because noderawfs overrides
+ // it. In noderawfs, stream.node is sometimes null. Instead, we need to
+ // look at stream.path.
+ return FS.statfsNode(stream.node);
+ },
+ statfsNode(node) {
+ // NOTE: None of the defaults here are true. We're just returning safe and
+ // sane values. Currently nodefs and rawfs replace these defaults,
+ // other file systems leave them alone.
+ var rtn = {
+ bsize: 4096,
+ frsize: 4096,
+ blocks: 1e6,
+ bfree: 5e5,
+ bavail: 5e5,
+ files: FS.nextInode,
+ ffree: FS.nextInode - 1,
+ fsid: 42,
+ flags: 2,
+ namelen: 255
+ };
+ if (node.node_ops.statfs) {
+ Object.assign(rtn, node.node_ops.statfs(node.mount.opts.root));
+ }
+ return rtn;
+ },
+ create(path, mode = 438) {
+ mode &= 4095;
+ mode |= 32768;
+ return FS.mknod(path, mode, 0);
+ },
+ mkdir(path, mode = 511) {
+ mode &= 511 | 512;
+ mode |= 16384;
+ return FS.mknod(path, mode, 0);
+ },
+ mkdirTree(path, mode) {
+ var dirs = path.split("/");
+ var d = "";
+ for (var dir of dirs) {
+ if (!dir) continue;
+ if (d || PATH.isAbs(path)) d += "/";
+ d += dir;
+ try {
+ FS.mkdir(d, mode);
+ } catch (e) {
+ if (e.errno != 20) throw e;
+ }
+ }
+ },
+ mkdev(path, mode, dev) {
+ if (typeof dev == "undefined") {
+ dev = mode;
+ mode = 438;
+ }
+ mode |= 8192;
+ return FS.mknod(path, mode, dev);
+ },
+ symlink(oldpath, newpath) {
+ if (!PATH_FS.resolve(oldpath)) {
+ throw new FS.ErrnoError(44);
+ }
+ var lookup = FS.lookupPath(newpath, {
+ parent: true
+ });
+ var parent = lookup.node;
+ if (!parent) {
+ throw new FS.ErrnoError(44);
+ }
+ var newname = PATH.basename(newpath);
+ var errCode = FS.mayCreate(parent, newname);
+ if (errCode) {
+ throw new FS.ErrnoError(errCode);
+ }
+ if (!parent.node_ops.symlink) {
+ throw new FS.ErrnoError(63);
+ }
+ return parent.node_ops.symlink(parent, newname, oldpath);
+ },
+ rename(old_path, new_path) {
+ var old_dirname = PATH.dirname(old_path);
+ var new_dirname = PATH.dirname(new_path);
+ var old_name = PATH.basename(old_path);
+ var new_name = PATH.basename(new_path);
+ // parents must exist
+ var lookup, old_dir, new_dir;
+ // let the errors from non existent directories percolate up
+ lookup = FS.lookupPath(old_path, {
+ parent: true
+ });
+ old_dir = lookup.node;
+ lookup = FS.lookupPath(new_path, {
+ parent: true
+ });
+ new_dir = lookup.node;
+ if (!old_dir || !new_dir) throw new FS.ErrnoError(44);
+ // need to be part of the same mount
+ if (old_dir.mount !== new_dir.mount) {
+ throw new FS.ErrnoError(75);
+ }
+ // source must exist
+ var old_node = FS.lookupNode(old_dir, old_name);
+ // old path should not be an ancestor of the new path
+ var relative = PATH_FS.relative(old_path, new_dirname);
+ if (relative.charAt(0) !== ".") {
+ throw new FS.ErrnoError(28);
+ }
+ // new path should not be an ancestor of the old path
+ relative = PATH_FS.relative(new_path, old_dirname);
+ if (relative.charAt(0) !== ".") {
+ throw new FS.ErrnoError(55);
+ }
+ // see if the new path already exists
+ var new_node;
+ try {
+ new_node = FS.lookupNode(new_dir, new_name);
+ } catch (e) {}
+ // early out if nothing needs to change
+ if (old_node === new_node) {
+ return;
+ }
+ // we'll need to delete the old entry
+ var isdir = FS.isDir(old_node.mode);
+ var errCode = FS.mayDelete(old_dir, old_name, isdir);
+ if (errCode) {
+ throw new FS.ErrnoError(errCode);
+ }
+ // need delete permissions if we'll be overwriting.
+ // need create permissions if new doesn't already exist.
+ errCode = new_node ? FS.mayDelete(new_dir, new_name, isdir) : FS.mayCreate(new_dir, new_name);
+ if (errCode) {
+ throw new FS.ErrnoError(errCode);
+ }
+ if (!old_dir.node_ops.rename) {
+ throw new FS.ErrnoError(63);
+ }
+ if (FS.isMountpoint(old_node) || (new_node && FS.isMountpoint(new_node))) {
+ throw new FS.ErrnoError(10);
+ }
+ // if we are going to change the parent, check write permissions
+ if (new_dir !== old_dir) {
+ errCode = FS.nodePermissions(old_dir, "w");
+ if (errCode) {
+ throw new FS.ErrnoError(errCode);
+ }
+ }
+ // remove the node from the lookup hash
+ FS.hashRemoveNode(old_node);
+ // do the underlying fs rename
+ try {
+ old_dir.node_ops.rename(old_node, new_dir, new_name);
+ // update old node (we do this here to avoid each backend
+ // needing to)
+ old_node.parent = new_dir;
+ } catch (e) {
+ throw e;
+ } finally {
+ // add the node back to the hash (in case node_ops.rename
+ // changed its name)
+ FS.hashAddNode(old_node);
+ }
+ },
+ rmdir(path) {
+ var lookup = FS.lookupPath(path, {
+ parent: true
+ });
+ var parent = lookup.node;
+ var name = PATH.basename(path);
+ var node = FS.lookupNode(parent, name);
+ var errCode = FS.mayDelete(parent, name, true);
+ if (errCode) {
+ throw new FS.ErrnoError(errCode);
+ }
+ if (!parent.node_ops.rmdir) {
+ throw new FS.ErrnoError(63);
+ }
+ if (FS.isMountpoint(node)) {
+ throw new FS.ErrnoError(10);
+ }
+ parent.node_ops.rmdir(parent, name);
+ FS.destroyNode(node);
+ },
+ readdir(path) {
+ var lookup = FS.lookupPath(path, {
+ follow: true
+ });
+ var node = lookup.node;
+ var readdir = FS.checkOpExists(node.node_ops.readdir, 54);
+ return readdir(node);
+ },
+ unlink(path) {
+ var lookup = FS.lookupPath(path, {
+ parent: true
+ });
+ var parent = lookup.node;
+ if (!parent) {
+ throw new FS.ErrnoError(44);
+ }
+ var name = PATH.basename(path);
+ var node = FS.lookupNode(parent, name);
+ var errCode = FS.mayDelete(parent, name, false);
+ if (errCode) {
+ // According to POSIX, we should map EISDIR to EPERM, but
+ // we instead do what Linux does (and we must, as we use
+ // the musl linux libc).
+ throw new FS.ErrnoError(errCode);
+ }
+ if (!parent.node_ops.unlink) {
+ throw new FS.ErrnoError(63);
+ }
+ if (FS.isMountpoint(node)) {
+ throw new FS.ErrnoError(10);
+ }
+ parent.node_ops.unlink(parent, name);
+ FS.destroyNode(node);
+ },
+ readlink(path) {
+ var lookup = FS.lookupPath(path);
+ var link = lookup.node;
+ if (!link) {
+ throw new FS.ErrnoError(44);
+ }
+ if (!link.node_ops.readlink) {
+ throw new FS.ErrnoError(28);
+ }
+ return link.node_ops.readlink(link);
+ },
+ stat(path, dontFollow) {
+ var lookup = FS.lookupPath(path, {
+ follow: !dontFollow
+ });
+ var node = lookup.node;
+ var getattr = FS.checkOpExists(node.node_ops.getattr, 63);
+ return getattr(node);
+ },
+ fstat(fd) {
+ var stream = FS.getStreamChecked(fd);
+ var node = stream.node;
+ var getattr = stream.stream_ops.getattr;
+ var arg = getattr ? stream : node;
+ getattr ??= node.node_ops.getattr;
+ FS.checkOpExists(getattr, 63);
+ return getattr(arg);
+ },
+ lstat(path) {
+ return FS.stat(path, true);
+ },
+ doChmod(stream, node, mode, dontFollow) {
+ FS.doSetAttr(stream, node, {
+ mode: (mode & 4095) | (node.mode & ~4095),
+ ctime: Date.now(),
+ dontFollow
+ });
+ },
+ chmod(path, mode, dontFollow) {
+ var node;
+ if (typeof path == "string") {
+ var lookup = FS.lookupPath(path, {
+ follow: !dontFollow
+ });
+ node = lookup.node;
+ } else {
+ node = path;
+ }
+ FS.doChmod(null, node, mode, dontFollow);
+ },
+ lchmod(path, mode) {
+ FS.chmod(path, mode, true);
+ },
+ fchmod(fd, mode) {
+ var stream = FS.getStreamChecked(fd);
+ FS.doChmod(stream, stream.node, mode, false);
+ },
+ doChown(stream, node, dontFollow) {
+ FS.doSetAttr(stream, node, {
+ timestamp: Date.now(),
+ dontFollow
+ });
+ },
+ chown(path, uid, gid, dontFollow) {
+ var node;
+ if (typeof path == "string") {
+ var lookup = FS.lookupPath(path, {
+ follow: !dontFollow
+ });
+ node = lookup.node;
+ } else {
+ node = path;
+ }
+ FS.doChown(null, node, dontFollow);
+ },
+ lchown(path, uid, gid) {
+ FS.chown(path, uid, gid, true);
+ },
+ fchown(fd, uid, gid) {
+ var stream = FS.getStreamChecked(fd);
+ FS.doChown(stream, stream.node, false);
+ },
+ doTruncate(stream, node, len) {
+ if (FS.isDir(node.mode)) {
+ throw new FS.ErrnoError(31);
+ }
+ if (!FS.isFile(node.mode)) {
+ throw new FS.ErrnoError(28);
+ }
+ var errCode = FS.nodePermissions(node, "w");
+ if (errCode) {
+ throw new FS.ErrnoError(errCode);
+ }
+ FS.doSetAttr(stream, node, {
+ size: len,
+ timestamp: Date.now()
+ });
+ },
+ truncate(path, len) {
+ if (len < 0) {
+ throw new FS.ErrnoError(28);
+ }
+ var node;
+ if (typeof path == "string") {
+ var lookup = FS.lookupPath(path, {
+ follow: true
+ });
+ node = lookup.node;
+ } else {
+ node = path;
+ }
+ FS.doTruncate(null, node, len);
+ },
+ ftruncate(fd, len) {
+ var stream = FS.getStreamChecked(fd);
+ if (len < 0 || (stream.flags & 2097155) === 0) {
+ throw new FS.ErrnoError(28);
+ }
+ FS.doTruncate(stream, stream.node, len);
+ },
+ utime(path, atime, mtime) {
+ var lookup = FS.lookupPath(path, {
+ follow: true
+ });
+ var node = lookup.node;
+ var setattr = FS.checkOpExists(node.node_ops.setattr, 63);
+ setattr(node, {
+ atime,
+ mtime
+ });
+ },
+ open(path, flags, mode = 438) {
+ if (path === "") {
+ throw new FS.ErrnoError(44);
+ }
+ flags = typeof flags == "string" ? FS_modeStringToFlags(flags) : flags;
+ if ((flags & 64)) {
+ mode = (mode & 4095) | 32768;
+ } else {
+ mode = 0;
+ }
+ var node;
+ var isDirPath;
+ if (typeof path == "object") {
+ node = path;
+ } else {
+ isDirPath = path.endsWith("/");
+ // noent_okay makes it so that if the final component of the path
+ // doesn't exist, lookupPath returns `node: undefined`. `path` will be
+ // updated to point to the target of all symlinks.
+ var lookup = FS.lookupPath(path, {
+ follow: !(flags & 131072),
+ noent_okay: true
+ });
+ node = lookup.node;
+ path = lookup.path;
+ }
+ // perhaps we need to create the node
+ var created = false;
+ if ((flags & 64)) {
+ if (node) {
+ // if O_CREAT and O_EXCL are set, error out if the node already exists
+ if ((flags & 128)) {
+ throw new FS.ErrnoError(20);
+ }
+ } else if (isDirPath) {
+ throw new FS.ErrnoError(31);
+ } else {
+ // node doesn't exist, try to create it
+ // Ignore the permission bits here to ensure we can `open` this new
+ // file below. We use chmod below to apply the permissions once the
+ // file is open.
+ node = FS.mknod(path, mode | 511, 0);
+ created = true;
+ }
+ }
+ if (!node) {
+ throw new FS.ErrnoError(44);
+ }
+ // can't truncate a device
+ if (FS.isChrdev(node.mode)) {
+ flags &= ~512;
+ }
+ // if asked only for a directory, then this must be one
+ if ((flags & 65536) && !FS.isDir(node.mode)) {
+ throw new FS.ErrnoError(54);
+ }
+ // check permissions, if this is not a file we just created now (it is ok to
+ // create and write to a file with read-only permissions; it is read-only
+ // for later use)
+ if (!created) {
+ var errCode = FS.mayOpen(node, flags);
+ if (errCode) {
+ throw new FS.ErrnoError(errCode);
+ }
+ }
+ // do truncation if necessary
+ if ((flags & 512) && !created) {
+ FS.truncate(node, 0);
+ }
+ // we've already handled these, don't pass down to the underlying vfs
+ flags &= ~(128 | 512 | 131072);
+ // register the stream with the filesystem
+ var stream = FS.createStream({
+ node,
+ path: FS.getPath(node),
+ // we want the absolute path to the node
+ flags,
+ seekable: true,
+ position: 0,
+ stream_ops: node.stream_ops,
+ // used by the file family libc calls (fopen, fwrite, ferror, etc.)
+ ungotten: [],
+ error: false
+ });
+ // call the new stream's open function
+ if (stream.stream_ops.open) {
+ stream.stream_ops.open(stream);
+ }
+ if (created) {
+ FS.chmod(node, mode & 511);
+ }
+ return stream;
+ },
+ close(stream) {
+ if (FS.isClosed(stream)) {
+ throw new FS.ErrnoError(8);
+ }
+ if (stream.getdents) stream.getdents = null;
+ // free readdir state
+ try {
+ if (stream.stream_ops.close) {
+ stream.stream_ops.close(stream);
+ }
+ } catch (e) {
+ throw e;
+ } finally {
+ FS.closeStream(stream.fd);
+ }
+ stream.fd = null;
+ },
+ isClosed(stream) {
+ return stream.fd === null;
+ },
+ llseek(stream, offset, whence) {
+ if (FS.isClosed(stream)) {
+ throw new FS.ErrnoError(8);
+ }
+ if (!stream.seekable || !stream.stream_ops.llseek) {
+ throw new FS.ErrnoError(70);
+ }
+ if (whence != 0 && whence != 1 && whence != 2) {
+ throw new FS.ErrnoError(28);
+ }
+ stream.position = stream.stream_ops.llseek(stream, offset, whence);
+ stream.ungotten = [];
+ return stream.position;
+ },
+ read(stream, buffer, offset, length, position) {
+ if (length < 0 || position < 0) {
+ throw new FS.ErrnoError(28);
+ }
+ if (FS.isClosed(stream)) {
+ throw new FS.ErrnoError(8);
+ }
+ if ((stream.flags & 2097155) === 1) {
+ throw new FS.ErrnoError(8);
+ }
+ if (FS.isDir(stream.node.mode)) {
+ throw new FS.ErrnoError(31);
+ }
+ if (!stream.stream_ops.read) {
+ throw new FS.ErrnoError(28);
+ }
+ var seeking = typeof position != "undefined";
+ if (!seeking) {
+ position = stream.position;
+ } else if (!stream.seekable) {
+ throw new FS.ErrnoError(70);
+ }
+ var bytesRead = stream.stream_ops.read(stream, buffer, offset, length, position);
+ if (!seeking) stream.position += bytesRead;
+ return bytesRead;
+ },
+ write(stream, buffer, offset, length, position, canOwn) {
+ if (length < 0 || position < 0) {
+ throw new FS.ErrnoError(28);
+ }
+ if (FS.isClosed(stream)) {
+ throw new FS.ErrnoError(8);
+ }
+ if ((stream.flags & 2097155) === 0) {
+ throw new FS.ErrnoError(8);
+ }
+ if (FS.isDir(stream.node.mode)) {
+ throw new FS.ErrnoError(31);
+ }
+ if (!stream.stream_ops.write) {
+ throw new FS.ErrnoError(28);
+ }
+ if (stream.seekable && stream.flags & 1024) {
+ // seek to the end before writing in append mode
+ FS.llseek(stream, 0, 2);
+ }
+ var seeking = typeof position != "undefined";
+ if (!seeking) {
+ position = stream.position;
+ } else if (!stream.seekable) {
+ throw new FS.ErrnoError(70);
+ }
+ var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn);
+ if (!seeking) stream.position += bytesWritten;
+ return bytesWritten;
+ },
+ mmap(stream, length, position, prot, flags) {
+ // User requests writing to file (prot & PROT_WRITE != 0).
+ // Checking if we have permissions to write to the file unless
+ // MAP_PRIVATE flag is set. According to POSIX spec it is possible
+ // to write to file opened in read-only mode with MAP_PRIVATE flag,
+ // as all modifications will be visible only in the memory of
+ // the current process.
+ if ((prot & 2) !== 0 && (flags & 2) === 0 && (stream.flags & 2097155) !== 2) {
+ throw new FS.ErrnoError(2);
+ }
+ if ((stream.flags & 2097155) === 1) {
+ throw new FS.ErrnoError(2);
+ }
+ if (!stream.stream_ops.mmap) {
+ throw new FS.ErrnoError(43);
+ }
+ if (!length) {
+ throw new FS.ErrnoError(28);
+ }
+ return stream.stream_ops.mmap(stream, length, position, prot, flags);
+ },
+ msync(stream, buffer, offset, length, mmapFlags) {
+ if (!stream.stream_ops.msync) {
+ return 0;
+ }
+ return stream.stream_ops.msync(stream, buffer, offset, length, mmapFlags);
+ },
+ ioctl(stream, cmd, arg) {
+ if (!stream.stream_ops.ioctl) {
+ throw new FS.ErrnoError(59);
+ }
+ return stream.stream_ops.ioctl(stream, cmd, arg);
+ },
+ readFile(path, opts = {}) {
+ opts.flags = opts.flags || 0;
+ opts.encoding = opts.encoding || "binary";
+ if (opts.encoding !== "utf8" && opts.encoding !== "binary") {
+ abort(`Invalid encoding type "${opts.encoding}"`);
+ }
+ var stream = FS.open(path, opts.flags);
+ var stat = FS.stat(path);
+ var length = stat.size;
+ var buf = new Uint8Array(length);
+ FS.read(stream, buf, 0, length, 0);
+ if (opts.encoding === "utf8") {
+ buf = UTF8ArrayToString(buf);
+ }
+ FS.close(stream);
+ return buf;
+ },
+ writeFile(path, data, opts = {}) {
+ opts.flags = opts.flags || 577;
+ var stream = FS.open(path, opts.flags, opts.mode);
+ if (typeof data == "string") {
+ data = new Uint8Array(intArrayFromString(data, true));
+ }
+ if (ArrayBuffer.isView(data)) {
+ FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn);
+ } else {
+ abort("Unsupported data type");
+ }
+ FS.close(stream);
+ },
+ cwd: () => FS.currentPath,
+ chdir(path) {
+ var lookup = FS.lookupPath(path, {
+ follow: true
+ });
+ if (lookup.node === null) {
+ throw new FS.ErrnoError(44);
+ }
+ if (!FS.isDir(lookup.node.mode)) {
+ throw new FS.ErrnoError(54);
+ }
+ var errCode = FS.nodePermissions(lookup.node, "x");
+ if (errCode) {
+ throw new FS.ErrnoError(errCode);
+ }
+ FS.currentPath = lookup.path;
+ },
+ createDefaultDirectories() {
+ FS.mkdir("/tmp");
+ FS.mkdir("/home");
+ FS.mkdir("/home/web_user");
+ },
+ createDefaultDevices() {
+ // create /dev
+ FS.mkdir("/dev");
+ // setup /dev/null
+ FS.registerDevice(FS.makedev(1, 3), {
+ read: () => 0,
+ write: (stream, buffer, offset, length, pos) => length,
+ llseek: () => 0
+ });
+ FS.mkdev("/dev/null", FS.makedev(1, 3));
+ // setup /dev/tty and /dev/tty1
+ // stderr needs to print output using err() rather than out()
+ // so we register a second tty just for it.
+ TTY.register(FS.makedev(5, 0), TTY.default_tty_ops);
+ TTY.register(FS.makedev(6, 0), TTY.default_tty1_ops);
+ FS.mkdev("/dev/tty", FS.makedev(5, 0));
+ FS.mkdev("/dev/tty1", FS.makedev(6, 0));
+ // setup /dev/[u]random
+ // use a buffer to avoid overhead of individual crypto calls per byte
+ var randomBuffer = new Uint8Array(1024), randomLeft = 0;
+ var randomByte = () => {
+ if (randomLeft === 0) {
+ randomFill(randomBuffer);
+ randomLeft = randomBuffer.byteLength;
+ }
+ return randomBuffer[--randomLeft];
+ };
+ FS.createDevice("/dev", "random", randomByte);
+ FS.createDevice("/dev", "urandom", randomByte);
+ // we're not going to emulate the actual shm device,
+ // just create the tmp dirs that reside in it commonly
+ FS.mkdir("/dev/shm");
+ FS.mkdir("/dev/shm/tmp");
+ },
+ createSpecialDirectories() {
+ // create /proc/self/fd which allows /proc/self/fd/6 => readlink gives the
+ // name of the stream for fd 6 (see test_unistd_ttyname)
+ FS.mkdir("/proc");
+ var proc_self = FS.mkdir("/proc/self");
+ FS.mkdir("/proc/self/fd");
+ FS.mount({
+ mount() {
+ var node = FS.createNode(proc_self, "fd", 16895, 73);
+ node.stream_ops = {
+ llseek: MEMFS.stream_ops.llseek
+ };
+ node.node_ops = {
+ lookup(parent, name) {
+ var fd = +name;
+ var stream = FS.getStreamChecked(fd);
+ var ret = {
+ parent: null,
+ mount: {
+ mountpoint: "fake"
+ },
+ node_ops: {
+ readlink: () => stream.path
+ },
+ id: fd + 1
+ };
+ ret.parent = ret;
+ // make it look like a simple root node
+ return ret;
+ },
+ readdir() {
+ return Array.from(FS.streams.entries()).filter(([k, v]) => v).map(([k, v]) => k.toString());
+ }
+ };
+ return node;
+ }
+ }, {}, "/proc/self/fd");
+ },
+ createStandardStreams(input, output, error) {
+ // TODO deprecate the old functionality of a single
+ // input / output callback and that utilizes FS.createDevice
+ // and instead require a unique set of stream ops
+ // by default, we symlink the standard streams to the
+ // default tty devices. however, if the standard streams
+ // have been overwritten we create a unique device for
+ // them instead.
+ if (input) {
+ FS.createDevice("/dev", "stdin", input);
+ } else {
+ FS.symlink("/dev/tty", "/dev/stdin");
+ }
+ if (output) {
+ FS.createDevice("/dev", "stdout", null, output);
+ } else {
+ FS.symlink("/dev/tty", "/dev/stdout");
+ }
+ if (error) {
+ FS.createDevice("/dev", "stderr", null, error);
+ } else {
+ FS.symlink("/dev/tty1", "/dev/stderr");
+ }
+ // open default streams for the stdin, stdout and stderr devices
+ var stdin = FS.open("/dev/stdin", 0);
+ var stdout = FS.open("/dev/stdout", 1);
+ var stderr = FS.open("/dev/stderr", 1);
+ },
+ staticInit() {
+ FS.nameTable = new Array(4096);
+ FS.mount(MEMFS, {}, "/");
+ FS.createDefaultDirectories();
+ FS.createDefaultDevices();
+ FS.createSpecialDirectories();
+ FS.filesystems = {
+ "MEMFS": MEMFS
+ };
+ },
+ init(input, output, error) {
+ FS.initialized = true;
+ // Allow Module.stdin etc. to provide defaults, if none explicitly passed to us here
+ input ??= Module["stdin"];
+ output ??= Module["stdout"];
+ error ??= Module["stderr"];
+ FS.createStandardStreams(input, output, error);
+ },
+ quit() {
+ FS.initialized = false;
+ // force-flush all streams, so we get musl std streams printed out
+ // close all of our streams
+ for (var stream of FS.streams) {
+ if (stream) {
+ FS.close(stream);
+ }
+ }
+ },
+ findObject(path, dontResolveLastLink) {
+ var ret = FS.analyzePath(path, dontResolveLastLink);
+ if (!ret.exists) {
+ return null;
+ }
+ return ret.object;
+ },
+ analyzePath(path, dontResolveLastLink) {
+ // operate from within the context of the symlink's target
+ try {
+ var lookup = FS.lookupPath(path, {
+ follow: !dontResolveLastLink
+ });
+ path = lookup.path;
+ } catch (e) {}
+ var ret = {
+ isRoot: false,
+ exists: false,
+ error: 0,
+ name: null,
+ path: null,
+ object: null,
+ parentExists: false,
+ parentPath: null,
+ parentObject: null
+ };
+ try {
+ var lookup = FS.lookupPath(path, {
+ parent: true
+ });
+ ret.parentExists = true;
+ ret.parentPath = lookup.path;
+ ret.parentObject = lookup.node;
+ ret.name = PATH.basename(path);
+ lookup = FS.lookupPath(path, {
+ follow: !dontResolveLastLink
+ });
+ ret.exists = true;
+ ret.path = lookup.path;
+ ret.object = lookup.node;
+ ret.name = lookup.node.name;
+ ret.isRoot = lookup.path === "/";
+ } catch (e) {
+ ret.error = e.errno;
+ }
+ return ret;
+ },
+ createPath(parent, path, canRead, canWrite) {
+ parent = typeof parent == "string" ? parent : FS.getPath(parent);
+ var parts = path.split("/").reverse();
+ while (parts.length) {
+ var part = parts.pop();
+ if (!part) continue;
+ var current = PATH.join2(parent, part);
+ try {
+ FS.mkdir(current);
+ } catch (e) {
+ if (e.errno != 20) throw e;
+ }
+ parent = current;
+ }
+ return current;
+ },
+ createFile(parent, name, properties, canRead, canWrite) {
+ var path = PATH.join2(typeof parent == "string" ? parent : FS.getPath(parent), name);
+ var mode = FS_getMode(canRead, canWrite);
+ return FS.create(path, mode);
+ },
+ createDataFile(parent, name, data, canRead, canWrite, canOwn) {
+ var path = name;
+ if (parent) {
+ parent = typeof parent == "string" ? parent : FS.getPath(parent);
+ path = name ? PATH.join2(parent, name) : parent;
+ }
+ var mode = FS_getMode(canRead, canWrite);
+ var node = FS.create(path, mode);
+ if (data) {
+ if (typeof data == "string") {
+ var arr = new Array(data.length);
+ for (var i = 0, len = data.length; i < len; ++i) arr[i] = data.charCodeAt(i);
+ data = arr;
+ }
+ // make sure we can write to the file
+ FS.chmod(node, mode | 146);
+ var stream = FS.open(node, 577);
+ FS.write(stream, data, 0, data.length, 0, canOwn);
+ FS.close(stream);
+ FS.chmod(node, mode);
+ }
+ },
+ createDevice(parent, name, input, output) {
+ var path = PATH.join2(typeof parent == "string" ? parent : FS.getPath(parent), name);
+ var mode = FS_getMode(!!input, !!output);
+ FS.createDevice.major ??= 64;
+ var dev = FS.makedev(FS.createDevice.major++, 0);
+ // Create a fake device that a set of stream ops to emulate
+ // the old behavior.
+ FS.registerDevice(dev, {
+ open(stream) {
+ stream.seekable = false;
+ },
+ close(stream) {
+ // flush any pending line data
+ if (output?.buffer?.length) {
+ output(10);
+ }
+ },
+ read(stream, buffer, offset, length, pos) {
+ var bytesRead = 0;
+ for (var i = 0; i < length; i++) {
+ var result;
+ try {
+ result = input();
+ } catch (e) {
+ throw new FS.ErrnoError(29);
+ }
+ if (result === undefined && bytesRead === 0) {
+ throw new FS.ErrnoError(6);
+ }
+ if (result === null || result === undefined) break;
+ bytesRead++;
+ buffer[offset + i] = result;
+ }
+ if (bytesRead) {
+ stream.node.atime = Date.now();
+ }
+ return bytesRead;
+ },
+ write(stream, buffer, offset, length, pos) {
+ for (var i = 0; i < length; i++) {
+ try {
+ output(buffer[offset + i]);
+ } catch (e) {
+ throw new FS.ErrnoError(29);
+ }
+ }
+ if (length) {
+ stream.node.mtime = stream.node.ctime = Date.now();
+ }
+ return i;
+ }
+ });
+ return FS.mkdev(path, mode, dev);
+ },
+ forceLoadFile(obj) {
+ if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true;
+ if (globalThis.XMLHttpRequest) {
+ abort("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.");
+ } else {
+ // Command-line.
+ try {
+ obj.contents = readBinary(obj.url);
+ } catch (e) {
+ throw new FS.ErrnoError(29);
+ }
+ }
+ },
+ createLazyFile(parent, name, url, canRead, canWrite) {
+ // Lazy chunked Uint8Array (implements get and length from Uint8Array).
+ // Actual getting is abstracted away for eventual reuse.
+ class LazyUint8Array {
+ lengthKnown=false;
+ chunks=[];
+ // Loaded chunks. Index is the chunk number
+ get(idx) {
+ if (idx > this.length - 1 || idx < 0) {
+ return undefined;
+ }
+ var chunkOffset = idx % this.chunkSize;
+ var chunkNum = (idx / this.chunkSize) | 0;
+ return this.getter(chunkNum)[chunkOffset];
+ }
+ setDataGetter(getter) {
+ this.getter = getter;
+ }
+ cacheLength() {
+ // Find length
+ var xhr = new XMLHttpRequest;
+ xhr.open("HEAD", url, false);
+ xhr.send(null);
+ if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) abort("Couldn't load " + url + ". Status: " + xhr.status);
+ var datalength = Number(xhr.getResponseHeader("Content-length"));
+ var header;
+ var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes";
+ var usesGzip = (header = xhr.getResponseHeader("Content-Encoding")) && header === "gzip";
+ var chunkSize = 1024 * 1024;
+ // Chunk size in bytes
+ if (!hasByteServing) chunkSize = datalength;
+ // Function to get a range from the remote URL.
+ var doXHR = (from, to) => {
+ if (from > to) abort("invalid range (" + from + ", " + to + ") or no bytes requested!");
+ if (to > datalength - 1) abort("only " + datalength + " bytes available! programmer error!");
+ // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available.
+ var xhr = new XMLHttpRequest;
+ xhr.open("GET", url, false);
+ if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to);
+ // Some hints to the browser that we want binary data.
+ xhr.responseType = "arraybuffer";
+ if (xhr.overrideMimeType) {
+ xhr.overrideMimeType("text/plain; charset=x-user-defined");
+ }
+ xhr.send(null);
+ if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) abort("Couldn't load " + url + ". Status: " + xhr.status);
+ if (xhr.response !== undefined) {
+ return new Uint8Array(/** @type{Array} */ (xhr.response || []));
+ }
+ return intArrayFromString(xhr.responseText || "", true);
+ };
+ var lazyArray = this;
+ lazyArray.setDataGetter(chunkNum => {
+ var start = chunkNum * chunkSize;
+ var end = (chunkNum + 1) * chunkSize - 1;
+ // including this byte
+ end = Math.min(end, datalength - 1);
+ // if datalength-1 is selected, this is the last block
+ if (typeof lazyArray.chunks[chunkNum] == "undefined") {
+ lazyArray.chunks[chunkNum] = doXHR(start, end);
+ }
+ if (typeof lazyArray.chunks[chunkNum] == "undefined") abort("doXHR failed!");
+ return lazyArray.chunks[chunkNum];
+ });
+ if (usesGzip || !datalength) {
+ // if the server uses gzip or doesn't supply the length, we have to download the whole file to get the (uncompressed) length
+ chunkSize = datalength = 1;
+ // this will force getter(0)/doXHR do download the whole file
+ datalength = this.getter(0).length;
+ chunkSize = datalength;
+ out("LazyFiles on gzip forces download of the whole file when length is accessed");
+ }
+ this._length = datalength;
+ this._chunkSize = chunkSize;
+ this.lengthKnown = true;
+ }
+ get length() {
+ if (!this.lengthKnown) {
+ this.cacheLength();
+ }
+ return this._length;
+ }
+ get chunkSize() {
+ if (!this.lengthKnown) {
+ this.cacheLength();
+ }
+ return this._chunkSize;
+ }
+ }
+ if (globalThis.XMLHttpRequest) {
+ if (!ENVIRONMENT_IS_WORKER) abort("Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc");
+ var lazyArray = new LazyUint8Array;
+ var properties = {
+ isDevice: false,
+ contents: lazyArray
+ };
+ } else {
+ var properties = {
+ isDevice: false,
+ url
+ };
+ }
+ var node = FS.createFile(parent, name, properties, canRead, canWrite);
+ // This is a total hack, but I want to get this lazy file code out of the
+ // core of MEMFS. If we want to keep this lazy file concept I feel it should
+ // be its own thin LAZYFS proxying calls to MEMFS.
+ if (properties.contents) {
+ node.contents = properties.contents;
+ } else if (properties.url) {
+ node.contents = null;
+ node.url = properties.url;
+ }
+ // Add a function that defers querying the file size until it is asked the first time.
+ Object.defineProperties(node, {
+ usedBytes: {
+ get: function() {
+ return this.contents.length;
+ }
+ }
+ });
+ // override each stream op with one that tries to force load the lazy file first
+ var stream_ops = {};
+ for (const [key, fn] of Object.entries(node.stream_ops)) {
+ stream_ops[key] = (...args) => {
+ FS.forceLoadFile(node);
+ return fn(...args);
+ };
+ }
+ function writeChunks(stream, buffer, offset, length, position) {
+ var contents = stream.node.contents;
+ if (position >= contents.length) return 0;
+ var size = Math.min(contents.length - position, length);
+ if (contents.slice) {
+ // normal array
+ for (var i = 0; i < size; i++) {
+ buffer[offset + i] = contents[position + i];
+ }
+ } else {
+ for (var i = 0; i < size; i++) {
+ // LazyUint8Array from sync binary XHR
+ buffer[offset + i] = contents.get(position + i);
+ }
+ }
+ return size;
+ }
+ // use a custom read function
+ stream_ops.read = (stream, buffer, offset, length, position) => {
+ FS.forceLoadFile(node);
+ return writeChunks(stream, buffer, offset, length, position);
+ };
+ // use a custom mmap function
+ stream_ops.mmap = (stream, length, position, prot, flags) => {
+ FS.forceLoadFile(node);
+ var ptr = mmapAlloc(length);
+ if (!ptr) {
+ throw new FS.ErrnoError(48);
+ }
+ writeChunks(stream, HEAP8, ptr, length, position);
+ return {
+ ptr,
+ allocated: true
+ };
+ };
+ node.stream_ops = stream_ops;
+ return node;
+ }
+};
+
+/**
+ * Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the
+ * emscripten HEAP, returns a copy of that string as a Javascript String object.
+ *
+ * @param {number} ptr
+ * @param {number=} maxBytesToRead - An optional length that specifies the
+ * maximum number of bytes to read. You can omit this parameter to scan the
+ * string until the first 0 byte. If maxBytesToRead is passed, and the string
+ * at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the
+ * string will cut short at that byte index.
+ * @param {boolean=} ignoreNul - If true, the function will not stop on a NUL character.
+ * @return {string}
+ */ var UTF8ToString = (ptr, maxBytesToRead, ignoreNul) => {
+ ptr >>>= 0;
+ if (!ptr) return "";
+ var end = findStringEnd(HEAPU8, ptr, maxBytesToRead, ignoreNul);
+ return UTF8Decoder.decode(HEAPU8.subarray(ptr >>> 0, end >>> 0));
+};
+
+var SYSCALLS = {
+ calculateAt(dirfd, path, allowEmpty) {
+ if (PATH.isAbs(path)) {
+ return path;
+ }
+ // relative path
+ var dir;
+ if (dirfd === -100) {
+ dir = FS.cwd();
+ } else {
+ var dirstream = SYSCALLS.getStreamFromFD(dirfd);
+ dir = dirstream.path;
+ }
+ if (path.length == 0) {
+ if (!allowEmpty) {
+ throw new FS.ErrnoError(44);
+ }
+ return dir;
+ }
+ return dir + "/" + path;
+ },
+ writeStat(buf, stat) {
+ HEAPU32[((buf) >>> 2) >>> 0] = stat.dev;
+ HEAPU32[(((buf) + (4)) >>> 2) >>> 0] = stat.mode;
+ HEAPU32[(((buf) + (8)) >>> 2) >>> 0] = stat.nlink;
+ HEAPU32[(((buf) + (12)) >>> 2) >>> 0] = stat.uid;
+ HEAPU32[(((buf) + (16)) >>> 2) >>> 0] = stat.gid;
+ HEAPU32[(((buf) + (20)) >>> 2) >>> 0] = stat.rdev;
+ (tempI64 = [ stat.size >>> 0, (tempDouble = stat.size, (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0) ],
+ HEAP32[(((buf) + (24)) >>> 2) >>> 0] = tempI64[0], HEAP32[(((buf) + (28)) >>> 2) >>> 0] = tempI64[1]);
+ HEAP32[(((buf) + (32)) >>> 2) >>> 0] = 4096;
+ HEAP32[(((buf) + (36)) >>> 2) >>> 0] = stat.blocks;
+ var atime = stat.atime.getTime();
+ var mtime = stat.mtime.getTime();
+ var ctime = stat.ctime.getTime();
+ (tempI64 = [ Math.floor(atime / 1e3) >>> 0, (tempDouble = Math.floor(atime / 1e3),
+ (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0) ],
+ HEAP32[(((buf) + (40)) >>> 2) >>> 0] = tempI64[0], HEAP32[(((buf) + (44)) >>> 2) >>> 0] = tempI64[1]);
+ HEAPU32[(((buf) + (48)) >>> 2) >>> 0] = (atime % 1e3) * 1e3 * 1e3;
+ (tempI64 = [ Math.floor(mtime / 1e3) >>> 0, (tempDouble = Math.floor(mtime / 1e3),
+ (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0) ],
+ HEAP32[(((buf) + (56)) >>> 2) >>> 0] = tempI64[0], HEAP32[(((buf) + (60)) >>> 2) >>> 0] = tempI64[1]);
+ HEAPU32[(((buf) + (64)) >>> 2) >>> 0] = (mtime % 1e3) * 1e3 * 1e3;
+ (tempI64 = [ Math.floor(ctime / 1e3) >>> 0, (tempDouble = Math.floor(ctime / 1e3),
+ (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0) ],
+ HEAP32[(((buf) + (72)) >>> 2) >>> 0] = tempI64[0], HEAP32[(((buf) + (76)) >>> 2) >>> 0] = tempI64[1]);
+ HEAPU32[(((buf) + (80)) >>> 2) >>> 0] = (ctime % 1e3) * 1e3 * 1e3;
+ (tempI64 = [ stat.ino >>> 0, (tempDouble = stat.ino, (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0) ],
+ HEAP32[(((buf) + (88)) >>> 2) >>> 0] = tempI64[0], HEAP32[(((buf) + (92)) >>> 2) >>> 0] = tempI64[1]);
+ return 0;
+ },
+ writeStatFs(buf, stats) {
+ HEAPU32[(((buf) + (4)) >>> 2) >>> 0] = stats.bsize;
+ HEAPU32[(((buf) + (60)) >>> 2) >>> 0] = stats.bsize;
+ (tempI64 = [ stats.blocks >>> 0, (tempDouble = stats.blocks, (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0) ],
+ HEAP32[(((buf) + (8)) >>> 2) >>> 0] = tempI64[0], HEAP32[(((buf) + (12)) >>> 2) >>> 0] = tempI64[1]);
+ (tempI64 = [ stats.bfree >>> 0, (tempDouble = stats.bfree, (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0) ],
+ HEAP32[(((buf) + (16)) >>> 2) >>> 0] = tempI64[0], HEAP32[(((buf) + (20)) >>> 2) >>> 0] = tempI64[1]);
+ (tempI64 = [ stats.bavail >>> 0, (tempDouble = stats.bavail, (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0) ],
+ HEAP32[(((buf) + (24)) >>> 2) >>> 0] = tempI64[0], HEAP32[(((buf) + (28)) >>> 2) >>> 0] = tempI64[1]);
+ (tempI64 = [ stats.files >>> 0, (tempDouble = stats.files, (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0) ],
+ HEAP32[(((buf) + (32)) >>> 2) >>> 0] = tempI64[0], HEAP32[(((buf) + (36)) >>> 2) >>> 0] = tempI64[1]);
+ (tempI64 = [ stats.ffree >>> 0, (tempDouble = stats.ffree, (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0) ],
+ HEAP32[(((buf) + (40)) >>> 2) >>> 0] = tempI64[0], HEAP32[(((buf) + (44)) >>> 2) >>> 0] = tempI64[1]);
+ HEAPU32[(((buf) + (48)) >>> 2) >>> 0] = stats.fsid;
+ HEAPU32[(((buf) + (64)) >>> 2) >>> 0] = stats.flags;
+ // ST_NOSUID
+ HEAPU32[(((buf) + (56)) >>> 2) >>> 0] = stats.namelen;
+ },
+ doMsync(addr, stream, len, flags, offset) {
+ if (!FS.isFile(stream.node.mode)) {
+ throw new FS.ErrnoError(43);
+ }
+ if (flags & 2) {
+ // MAP_PRIVATE calls need not to be synced back to underlying fs
+ return 0;
+ }
+ var buffer = HEAPU8.slice(addr, addr + len);
+ FS.msync(stream, buffer, offset, len, flags);
+ },
+ getStreamFromFD(fd) {
+ var stream = FS.getStreamChecked(fd);
+ return stream;
+ },
+ varargs: undefined,
+ getStr(ptr) {
+ var ret = UTF8ToString(ptr);
+ return ret;
+ }
+};
+
+function ___syscall_dup(fd) {
+ try {
+ var old = SYSCALLS.getStreamFromFD(fd);
+ return FS.dupStream(old).fd;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+function ___syscall_faccessat(dirfd, path, amode, flags) {
+ path >>>= 0;
+ try {
+ path = SYSCALLS.getStr(path);
+ path = SYSCALLS.calculateAt(dirfd, path);
+ if (amode & ~7) {
+ // need a valid mode
+ return -28;
+ }
+ var lookup = FS.lookupPath(path, {
+ follow: true
+ });
+ var node = lookup.node;
+ if (!node) {
+ return -44;
+ }
+ var perms = "";
+ if (amode & 4) perms += "r";
+ if (amode & 2) perms += "w";
+ if (amode & 1) perms += "x";
+ if (perms && FS.nodePermissions(node, perms)) {
+ return -2;
+ }
+ return 0;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+var syscallGetVarargI = () => {
+ // the `+` prepended here is necessary to convince the JSCompiler that varargs is indeed a number.
+ var ret = HEAP32[((+SYSCALLS.varargs) >>> 2) >>> 0];
+ SYSCALLS.varargs += 4;
+ return ret;
+};
+
+var syscallGetVarargP = syscallGetVarargI;
+
+function ___syscall_fcntl64(fd, cmd, varargs) {
+ varargs >>>= 0;
+ SYSCALLS.varargs = varargs;
+ try {
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ switch (cmd) {
+ case 0:
+ {
+ var arg = syscallGetVarargI();
+ if (arg < 0) {
+ return -28;
+ }
+ while (FS.streams[arg]) {
+ arg++;
+ }
+ var newStream;
+ newStream = FS.dupStream(stream, arg);
+ return newStream.fd;
+ }
+
+ case 1:
+ case 2:
+ return 0;
+
+ // FD_CLOEXEC makes no sense for a single process.
+ case 3:
+ return stream.flags;
+
+ case 4:
+ {
+ var arg = syscallGetVarargI();
+ stream.flags |= arg;
+ return 0;
+ }
+
+ case 12:
+ {
+ var arg = syscallGetVarargP();
+ var offset = 0;
+ // We're always unlocked.
+ HEAP16[(((arg) + (offset)) >>> 1) >>> 0] = 2;
+ return 0;
+ }
+
+ case 13:
+ case 14:
+ // Pretend that the locking is successful. These are process-level locks,
+ // and Emscripten programs are a single process. If we supported linking a
+ // filesystem between programs, we'd need to do more here.
+ // See https://github.com/emscripten-core/emscripten/issues/23697
+ return 0;
+ }
+ return -28;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+function ___syscall_fstat64(fd, buf) {
+ buf >>>= 0;
+ try {
+ return SYSCALLS.writeStat(buf, FS.fstat(fd));
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+function ___syscall_ftruncate64(fd, length_low, length_high) {
+ var length = convertI32PairToI53Checked(length_low, length_high);
+ try {
+ if (isNaN(length)) return -61;
+ FS.ftruncate(fd, length);
+ return 0;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+var stringToUTF8 = (str, outPtr, maxBytesToWrite) => stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
+
+function ___syscall_getcwd(buf, size) {
+ buf >>>= 0;
+ size >>>= 0;
+ try {
+ if (size === 0) return -28;
+ var cwd = FS.cwd();
+ var cwdLengthInBytes = lengthBytesUTF8(cwd) + 1;
+ if (size < cwdLengthInBytes) return -68;
+ stringToUTF8(cwd, buf, size);
+ return cwdLengthInBytes;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+function ___syscall_getdents64(fd, dirp, count) {
+ dirp >>>= 0;
+ count >>>= 0;
+ try {
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ stream.getdents ||= FS.readdir(stream.path);
+ var struct_size = 280;
+ var pos = 0;
+ var off = FS.llseek(stream, 0, 1);
+ var startIdx = Math.floor(off / struct_size);
+ var endIdx = Math.min(stream.getdents.length, startIdx + Math.floor(count / struct_size));
+ for (var idx = startIdx; idx < endIdx; idx++) {
+ var id;
+ var type;
+ var name = stream.getdents[idx];
+ if (name === ".") {
+ id = stream.node.id;
+ type = 4;
+ } else if (name === "..") {
+ var lookup = FS.lookupPath(stream.path, {
+ parent: true
+ });
+ id = lookup.node.id;
+ type = 4;
+ } else {
+ var child;
+ try {
+ child = FS.lookupNode(stream.node, name);
+ } catch (e) {
+ // If the entry is not a directory, file, or symlink, nodefs
+ // lookupNode will raise EINVAL. Skip these and continue.
+ if (e?.errno === 28) {
+ continue;
+ }
+ throw e;
+ }
+ id = child.id;
+ type = FS.isChrdev(child.mode) ? 2 : // character device.
+ FS.isDir(child.mode) ? 4 : // directory
+ FS.isLink(child.mode) ? 10 : // symbolic link.
+ 8;
+ }
+ (tempI64 = [ id >>> 0, (tempDouble = id, (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0) ],
+ HEAP32[((dirp + pos) >>> 2) >>> 0] = tempI64[0], HEAP32[(((dirp + pos) + (4)) >>> 2) >>> 0] = tempI64[1]);
+ (tempI64 = [ (idx + 1) * struct_size >>> 0, (tempDouble = (idx + 1) * struct_size,
+ (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0) ],
+ HEAP32[(((dirp + pos) + (8)) >>> 2) >>> 0] = tempI64[0], HEAP32[(((dirp + pos) + (12)) >>> 2) >>> 0] = tempI64[1]);
+ HEAP16[(((dirp + pos) + (16)) >>> 1) >>> 0] = 280;
+ HEAP8[(dirp + pos) + (18) >>> 0] = type;
+ stringToUTF8(name, dirp + pos + 19, 256);
+ pos += struct_size;
+ }
+ FS.llseek(stream, idx * struct_size, 0);
+ return pos;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+function ___syscall_ioctl(fd, op, varargs) {
+ varargs >>>= 0;
+ SYSCALLS.varargs = varargs;
+ try {
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ switch (op) {
+ case 21509:
+ {
+ if (!stream.tty) return -59;
+ return 0;
+ }
+
+ case 21505:
+ {
+ if (!stream.tty) return -59;
+ if (stream.tty.ops.ioctl_tcgets) {
+ var termios = stream.tty.ops.ioctl_tcgets(stream);
+ var argp = syscallGetVarargP();
+ HEAP32[((argp) >>> 2) >>> 0] = termios.c_iflag || 0;
+ HEAP32[(((argp) + (4)) >>> 2) >>> 0] = termios.c_oflag || 0;
+ HEAP32[(((argp) + (8)) >>> 2) >>> 0] = termios.c_cflag || 0;
+ HEAP32[(((argp) + (12)) >>> 2) >>> 0] = termios.c_lflag || 0;
+ for (var i = 0; i < 32; i++) {
+ HEAP8[(argp + i) + (17) >>> 0] = termios.c_cc[i] || 0;
+ }
+ return 0;
+ }
+ return 0;
+ }
+
+ case 21510:
+ case 21511:
+ case 21512:
+ {
+ if (!stream.tty) return -59;
+ return 0;
+ }
+
+ case 21506:
+ case 21507:
+ case 21508:
+ {
+ if (!stream.tty) return -59;
+ if (stream.tty.ops.ioctl_tcsets) {
+ var argp = syscallGetVarargP();
+ var c_iflag = HEAP32[((argp) >>> 2) >>> 0];
+ var c_oflag = HEAP32[(((argp) + (4)) >>> 2) >>> 0];
+ var c_cflag = HEAP32[(((argp) + (8)) >>> 2) >>> 0];
+ var c_lflag = HEAP32[(((argp) + (12)) >>> 2) >>> 0];
+ var c_cc = [];
+ for (var i = 0; i < 32; i++) {
+ c_cc.push(HEAP8[(argp + i) + (17) >>> 0]);
+ }
+ return stream.tty.ops.ioctl_tcsets(stream.tty, op, {
+ c_iflag,
+ c_oflag,
+ c_cflag,
+ c_lflag,
+ c_cc
+ });
+ }
+ return 0;
+ }
+
+ case 21519:
+ {
+ if (!stream.tty) return -59;
+ var argp = syscallGetVarargP();
+ HEAP32[((argp) >>> 2) >>> 0] = 0;
+ return 0;
+ }
+
+ case 21520:
+ {
+ if (!stream.tty) return -59;
+ return -28;
+ }
+
+ case 21537:
+ case 21531:
+ {
+ var argp = syscallGetVarargP();
+ return FS.ioctl(stream, op, argp);
+ }
+
+ case 21523:
+ {
+ // TODO: in theory we should write to the winsize struct that gets
+ // passed in, but for now musl doesn't read anything on it
+ if (!stream.tty) return -59;
+ if (stream.tty.ops.ioctl_tiocgwinsz) {
+ var winsize = stream.tty.ops.ioctl_tiocgwinsz(stream.tty);
+ var argp = syscallGetVarargP();
+ HEAP16[((argp) >>> 1) >>> 0] = winsize[0];
+ HEAP16[(((argp) + (2)) >>> 1) >>> 0] = winsize[1];
+ }
+ return 0;
+ }
+
+ case 21524:
+ {
+ // TODO: technically, this ioctl call should change the window size.
+ // but, since emscripten doesn't have any concept of a terminal window
+ // yet, we'll just silently throw it away as we do TIOCGWINSZ
+ if (!stream.tty) return -59;
+ return 0;
+ }
+
+ case 21515:
+ {
+ if (!stream.tty) return -59;
+ return 0;
+ }
+
+ default:
+ return -28;
+ }
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+function ___syscall_lstat64(path, buf) {
+ path >>>= 0;
+ buf >>>= 0;
+ try {
+ path = SYSCALLS.getStr(path);
+ return SYSCALLS.writeStat(buf, FS.lstat(path));
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+function ___syscall_mkdirat(dirfd, path, mode) {
+ path >>>= 0;
+ try {
+ path = SYSCALLS.getStr(path);
+ path = SYSCALLS.calculateAt(dirfd, path);
+ FS.mkdir(path, mode, 0);
+ return 0;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+function ___syscall_newfstatat(dirfd, path, buf, flags) {
+ path >>>= 0;
+ buf >>>= 0;
+ try {
+ path = SYSCALLS.getStr(path);
+ var nofollow = flags & 256;
+ var allowEmpty = flags & 4096;
+ flags = flags & (~6400);
+ path = SYSCALLS.calculateAt(dirfd, path, allowEmpty);
+ return SYSCALLS.writeStat(buf, nofollow ? FS.lstat(path) : FS.stat(path));
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+function ___syscall_openat(dirfd, path, flags, varargs) {
+ path >>>= 0;
+ varargs >>>= 0;
+ SYSCALLS.varargs = varargs;
+ try {
+ path = SYSCALLS.getStr(path);
+ path = SYSCALLS.calculateAt(dirfd, path);
+ var mode = varargs ? syscallGetVarargI() : 0;
+ return FS.open(path, flags, mode).fd;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+function ___syscall_stat64(path, buf) {
+ path >>>= 0;
+ buf >>>= 0;
+ try {
+ path = SYSCALLS.getStr(path);
+ return SYSCALLS.writeStat(buf, FS.stat(path));
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+var __abort_js = () => abort("");
+
+function __embind_register_bigint(primitiveType, name, size, minRange, maxRange) {
+ primitiveType >>>= 0;
+ name >>>= 0;
+ size >>>= 0;
+}
+
+var AsciiToString = ptr => {
+ ptr >>>= 0;
+ var str = "";
+ while (1) {
+ var ch = HEAPU8[ptr++ >>> 0];
+ if (!ch) return str;
+ str += String.fromCharCode(ch);
+ }
+};
+
+var awaitingDependencies = {};
+
+var registeredTypes = {};
+
+var typeDependencies = {};
+
+var BindingError = class BindingError extends Error {
+ constructor(message) {
+ super(message);
+ this.name = "BindingError";
+ }
+};
+
+var throwBindingError = message => {
+ throw new BindingError(message);
+};
+
+/** @param {Object=} options */ function sharedRegisterType(rawType, registeredInstance, options = {}) {
+ var name = registeredInstance.name;
+ if (!rawType) {
+ throwBindingError(`type "${name}" must have a positive integer typeid pointer`);
+ }
+ if (registeredTypes.hasOwnProperty(rawType)) {
+ if (options.ignoreDuplicateRegistrations) {
+ return;
+ } else {
+ throwBindingError(`Cannot register type '${name}' twice`);
+ }
+ }
+ registeredTypes[rawType] = registeredInstance;
+ delete typeDependencies[rawType];
+ if (awaitingDependencies.hasOwnProperty(rawType)) {
+ var callbacks = awaitingDependencies[rawType];
+ delete awaitingDependencies[rawType];
+ callbacks.forEach(cb => cb());
+ }
+}
+
+/** @param {Object=} options */ function registerType(rawType, registeredInstance, options = {}) {
+ return sharedRegisterType(rawType, registeredInstance, options);
+}
+
+/** @suppress {globalThis} */ function __embind_register_bool(rawType, name, trueValue, falseValue) {
+ rawType >>>= 0;
+ name >>>= 0;
+ name = AsciiToString(name);
+ registerType(rawType, {
+ name,
+ fromWireType: function(wt) {
+ // ambiguous emscripten ABI: sometimes return values are
+ // true or false, and sometimes integers (0 or 1)
+ return !!wt;
+ },
+ toWireType: function(destructors, o) {
+ return o ? trueValue : falseValue;
+ },
+ readValueFromPointer: function(pointer) {
+ return this.fromWireType(HEAPU8[pointer >>> 0]);
+ },
+ destructorFunction: null
+ });
+}
+
+var emval_freelist = [];
+
+var emval_handles = [ 0, 1, , 1, null, 1, true, 1, false, 1 ];
+
+function __emval_decref(handle) {
+ handle >>>= 0;
+ if (handle > 9 && 0 === --emval_handles[handle + 1]) {
+ emval_handles[handle] = undefined;
+ emval_freelist.push(handle);
+ }
+}
+
+var Emval = {
+ toValue: handle => {
+ if (!handle) {
+ throwBindingError(`Cannot use deleted val. handle = ${handle}`);
+ }
+ return emval_handles[handle];
+ },
+ toHandle: value => {
+ switch (value) {
+ case undefined:
+ return 2;
+
+ case null:
+ return 4;
+
+ case true:
+ return 6;
+
+ case false:
+ return 8;
+
+ default:
+ {
+ const handle = emval_freelist.pop() || emval_handles.length;
+ emval_handles[handle] = value;
+ emval_handles[handle + 1] = 1;
+ return handle;
+ }
+ }
+ }
+};
+
+/** @suppress {globalThis} */ function readPointer(pointer) {
+ return this.fromWireType(HEAPU32[((pointer) >>> 2) >>> 0]);
+}
+
+var EmValType = {
+ name: "emscripten::val",
+ fromWireType: handle => {
+ var rv = Emval.toValue(handle);
+ __emval_decref(handle);
+ return rv;
+ },
+ toWireType: (destructors, value) => Emval.toHandle(value),
+ readValueFromPointer: readPointer,
+ destructorFunction: null
+};
+
+function __embind_register_emval(rawType) {
+ rawType >>>= 0;
+ return registerType(rawType, EmValType);
+}
+
+var floatReadValueFromPointer = (name, width) => {
+ switch (width) {
+ case 4:
+ return function(pointer) {
+ return this.fromWireType(HEAPF32[((pointer) >>> 2) >>> 0]);
+ };
+
+ case 8:
+ return function(pointer) {
+ return this.fromWireType(HEAPF64[((pointer) >>> 3) >>> 0]);
+ };
+
+ default:
+ throw new TypeError(`invalid float width (${width}): ${name}`);
+ }
+};
+
+var __embind_register_float = function(rawType, name, size) {
+ rawType >>>= 0;
+ name >>>= 0;
+ size >>>= 0;
+ name = AsciiToString(name);
+ registerType(rawType, {
+ name,
+ fromWireType: value => value,
+ toWireType: (destructors, value) => value,
+ readValueFromPointer: floatReadValueFromPointer(name, size),
+ destructorFunction: null
+ });
+};
+
+var createNamedFunction = (name, func) => Object.defineProperty(func, "name", {
+ value: name
+});
+
+var runDestructors = destructors => {
+ while (destructors.length) {
+ var ptr = destructors.pop();
+ var del = destructors.pop();
+ del(ptr);
+ }
+};
+
+function usesDestructorStack(argTypes) {
+ // Skip return value at index 0 - it's not deleted here.
+ for (var i = 1; i < argTypes.length; ++i) {
+ // The type does not define a destructor function - must use dynamic stack
+ if (argTypes[i] !== null && argTypes[i].destructorFunction === undefined) {
+ return true;
+ }
+ }
+ return false;
+}
+
+var runAndAbortIfError = func => {
+ try {
+ return func();
+ } catch (e) {
+ abort(e);
+ }
+};
+
+var runtimeKeepalivePush = () => {
+ runtimeKeepaliveCounter += 1;
+};
+
+var runtimeKeepalivePop = () => {
+ runtimeKeepaliveCounter -= 1;
+};
+
+var Asyncify = {
+ instrumentWasmImports(imports) {
+ var importPattern = /^(ReadBufferDataJs|WaitUntilCompletedJs|WaitUntilPipelineCreatedJs|invoke_.*|__asyncjs__.*)$/;
+ for (let [x, original] of Object.entries(imports)) {
+ if (typeof original == "function") {
+ let isAsyncifyImport = original.isAsync || importPattern.test(x);
+ }
+ }
+ },
+ instrumentFunction(original) {
+ var wrapper = (...args) => {
+ Asyncify.exportCallStack.push(original);
+ try {
+ return original(...args);
+ } finally {
+ if (!ABORT) {
+ var top = Asyncify.exportCallStack.pop();
+ Asyncify.maybeStopUnwind();
+ }
+ }
+ };
+ Asyncify.funcWrappers.set(original, wrapper);
+ return wrapper;
+ },
+ instrumentWasmExports(exports) {
+ var ret = {};
+ for (let [x, original] of Object.entries(exports)) {
+ if (typeof original == "function") {
+ var wrapper = Asyncify.instrumentFunction(original);
+ ret[x] = wrapper;
+ } else {
+ ret[x] = original;
+ }
+ }
+ return ret;
+ },
+ State: {
+ Normal: 0,
+ Unwinding: 1,
+ Rewinding: 2,
+ Disabled: 3
+ },
+ state: 0,
+ StackSize: 4096,
+ currData: null,
+ handleSleepReturnValue: 0,
+ exportCallStack: [],
+ callstackFuncToId: new Map,
+ callStackIdToFunc: new Map,
+ funcWrappers: new Map,
+ callStackId: 0,
+ asyncPromiseHandlers: null,
+ sleepCallbacks: [],
+ getCallStackId(func) {
+ if (!Asyncify.callstackFuncToId.has(func)) {
+ var id = Asyncify.callStackId++;
+ Asyncify.callstackFuncToId.set(func, id);
+ Asyncify.callStackIdToFunc.set(id, func);
+ }
+ return Asyncify.callstackFuncToId.get(func);
+ },
+ maybeStopUnwind() {
+ if (Asyncify.currData && Asyncify.state === Asyncify.State.Unwinding && Asyncify.exportCallStack.length === 0) {
+ // We just finished unwinding.
+ // Be sure to set the state before calling any other functions to avoid
+ // possible infinite recursion here (For example in debug pthread builds
+ // the dbg() function itself can call back into WebAssembly to get the
+ // current pthread_self() pointer).
+ Asyncify.state = Asyncify.State.Normal;
+ // Keep the runtime alive so that a re-wind can be done later.
+ runAndAbortIfError(_asyncify_stop_unwind);
+ if (typeof Fibers != "undefined") {
+ Fibers.trampoline();
+ }
+ }
+ },
+ whenDone() {
+ return new Promise((resolve, reject) => {
+ Asyncify.asyncPromiseHandlers = {
+ resolve,
+ reject
+ };
+ });
+ },
+ allocateData() {
+ // An asyncify data structure has three fields:
+ // 0 current stack pos
+ // 4 max stack pos
+ // 8 id of function at bottom of the call stack (callStackIdToFunc[id] == wasm func)
+ // The Asyncify ABI only interprets the first two fields, the rest is for the runtime.
+ // We also embed a stack in the same memory region here, right next to the structure.
+ // This struct is also defined as asyncify_data_t in emscripten/fiber.h
+ var ptr = _malloc(12 + Asyncify.StackSize);
+ Asyncify.setDataHeader(ptr, ptr + 12, Asyncify.StackSize);
+ Asyncify.setDataRewindFunc(ptr);
+ return ptr;
+ },
+ setDataHeader(ptr, stack, stackSize) {
+ HEAPU32[((ptr) >>> 2) >>> 0] = stack;
+ HEAPU32[(((ptr) + (4)) >>> 2) >>> 0] = stack + stackSize;
+ },
+ setDataRewindFunc(ptr) {
+ var bottomOfCallStack = Asyncify.exportCallStack[0];
+ var rewindId = Asyncify.getCallStackId(bottomOfCallStack);
+ HEAP32[(((ptr) + (8)) >>> 2) >>> 0] = rewindId;
+ },
+ getDataRewindFunc(ptr) {
+ var id = HEAP32[(((ptr) + (8)) >>> 2) >>> 0];
+ var func = Asyncify.callStackIdToFunc.get(id);
+ return func;
+ },
+ doRewind(ptr) {
+ var original = Asyncify.getDataRewindFunc(ptr);
+ var func = Asyncify.funcWrappers.get(original);
+ // Once we have rewound and the stack we no longer need to artificially
+ // keep the runtime alive.
+ return callUserCallback(func);
+ },
+ handleSleep(startAsync) {
+ if (ABORT) return;
+ if (Asyncify.state === Asyncify.State.Normal) {
+ // Prepare to sleep. Call startAsync, and see what happens:
+ // if the code decided to call our callback synchronously,
+ // then no async operation was in fact begun, and we don't
+ // need to do anything.
+ var reachedCallback = false;
+ var reachedAfterCallback = false;
+ startAsync((handleSleepReturnValue = 0) => {
+ if (ABORT) return;
+ Asyncify.handleSleepReturnValue = handleSleepReturnValue;
+ reachedCallback = true;
+ if (!reachedAfterCallback) {
+ // We are happening synchronously, so no need for async.
+ return;
+ }
+ Asyncify.state = Asyncify.State.Rewinding;
+ runAndAbortIfError(() => _asyncify_start_rewind(Asyncify.currData));
+ if (typeof MainLoop != "undefined" && MainLoop.func) {
+ MainLoop.resume();
+ }
+ var asyncWasmReturnValue, isError = false;
+ try {
+ asyncWasmReturnValue = Asyncify.doRewind(Asyncify.currData);
+ } catch (err) {
+ asyncWasmReturnValue = err;
+ isError = true;
+ }
+ // Track whether the return value was handled by any promise handlers.
+ var handled = false;
+ if (!Asyncify.currData) {
+ // All asynchronous execution has finished.
+ // `asyncWasmReturnValue` now contains the final
+ // return value of the exported async WASM function.
+ // Note: `asyncWasmReturnValue` is distinct from
+ // `Asyncify.handleSleepReturnValue`.
+ // `Asyncify.handleSleepReturnValue` contains the return
+ // value of the last C function to have executed
+ // `Asyncify.handleSleep()`, whereas `asyncWasmReturnValue`
+ // contains the return value of the exported WASM function
+ // that may have called C functions that
+ // call `Asyncify.handleSleep()`.
+ var asyncPromiseHandlers = Asyncify.asyncPromiseHandlers;
+ if (asyncPromiseHandlers) {
+ Asyncify.asyncPromiseHandlers = null;
+ (isError ? asyncPromiseHandlers.reject : asyncPromiseHandlers.resolve)(asyncWasmReturnValue);
+ handled = true;
+ }
+ }
+ if (isError && !handled) {
+ // If there was an error and it was not handled by now, we have no choice but to
+ // rethrow that error into the global scope where it can be caught only by
+ // `onerror` or `onunhandledpromiserejection`.
+ throw asyncWasmReturnValue;
+ }
+ });
+ reachedAfterCallback = true;
+ if (!reachedCallback) {
+ // A true async operation was begun; start a sleep.
+ Asyncify.state = Asyncify.State.Unwinding;
+ // TODO: reuse, don't alloc/free every sleep
+ Asyncify.currData = Asyncify.allocateData();
+ if (typeof MainLoop != "undefined" && MainLoop.func) {
+ MainLoop.pause();
+ }
+ runAndAbortIfError(() => _asyncify_start_unwind(Asyncify.currData));
+ }
+ } else if (Asyncify.state === Asyncify.State.Rewinding) {
+ // Stop a resume.
+ Asyncify.state = Asyncify.State.Normal;
+ runAndAbortIfError(_asyncify_stop_rewind);
+ _free(Asyncify.currData);
+ Asyncify.currData = null;
+ // Call all sleep callbacks now that the sleep-resume is all done.
+ Asyncify.sleepCallbacks.forEach(callUserCallback);
+ } else {
+ abort(`invalid state: ${Asyncify.state}`);
+ }
+ return Asyncify.handleSleepReturnValue;
+ },
+ handleAsync: startAsync => Asyncify.handleSleep(async wakeUp => {
+ // TODO: add error handling as a second param when handleSleep implements it.
+ wakeUp(await startAsync());
+ })
+};
+
+function craftInvokerFunction(humanName, argTypes, classType, cppInvokerFunc, cppTargetFunc, /** boolean= */ isAsync) {
+ // humanName: a human-readable string name for the function to be generated.
+ // argTypes: An array that contains the embind type objects for all types in the function signature.
+ // argTypes[0] is the type object for the function return value.
+ // argTypes[1] is the type object for function this object/class type, or null if not crafting an invoker for a class method.
+ // argTypes[2...] are the actual function parameters.
+ // classType: The embind type object for the class to be bound, or null if this is not a method of a class.
+ // cppInvokerFunc: JS Function object to the C++-side function that interops into C++ code.
+ // cppTargetFunc: Function pointer (an integer to FUNCTION_TABLE) to the target C++ function the cppInvokerFunc will end up calling.
+ // isAsync: Optional. If true, returns an async function. Async bindings are only supported with JSPI.
+ var argCount = argTypes.length;
+ if (argCount < 2) {
+ throwBindingError("argTypes array size mismatch! Must at least get return value and 'this' types!");
+ }
+ var isClassMethodFunc = (argTypes[1] !== null && classType !== null);
+ // Free functions with signature "void function()" do not need an invoker that marshalls between wire types.
+ // TODO: This omits argument count check - enable only at -O3 or similar.
+ // if (ENABLE_UNSAFE_OPTS && argCount == 2 && argTypes[0].name == "void" && !isClassMethodFunc) {
+ // return FUNCTION_TABLE[fn];
+ // }
+ // Determine if we need to use a dynamic stack to store the destructors for the function parameters.
+ // TODO: Remove this completely once all function invokers are being dynamically generated.
+ var needsDestructorStack = usesDestructorStack(argTypes);
+ var returns = !argTypes[0].isVoid;
+ var expectedArgCount = argCount - 2;
+ var argsWired = new Array(expectedArgCount);
+ var invokerFuncArgs = [];
+ var destructors = [];
+ var invokerFn = function(...args) {
+ destructors.length = 0;
+ var thisWired;
+ invokerFuncArgs.length = isClassMethodFunc ? 2 : 1;
+ invokerFuncArgs[0] = cppTargetFunc;
+ if (isClassMethodFunc) {
+ thisWired = argTypes[1].toWireType(destructors, this);
+ invokerFuncArgs[1] = thisWired;
+ }
+ for (var i = 0; i < expectedArgCount; ++i) {
+ argsWired[i] = argTypes[i + 2].toWireType(destructors, args[i]);
+ invokerFuncArgs.push(argsWired[i]);
+ }
+ var rv = cppInvokerFunc(...invokerFuncArgs);
+ function onDone(rv) {
+ if (needsDestructorStack) {
+ runDestructors(destructors);
+ } else {
+ for (var i = isClassMethodFunc ? 1 : 2; i < argTypes.length; i++) {
+ var param = i === 1 ? thisWired : argsWired[i - 2];
+ if (argTypes[i].destructorFunction !== null) {
+ argTypes[i].destructorFunction(param);
+ }
+ }
+ }
+ if (returns) {
+ return argTypes[0].fromWireType(rv);
+ }
+ }
+ if (Asyncify.currData) {
+ return Asyncify.whenDone().then(onDone);
+ }
+ return onDone(rv);
+ };
+ return createNamedFunction(humanName, invokerFn);
+}
+
+var ensureOverloadTable = (proto, methodName, humanName) => {
+ if (undefined === proto[methodName].overloadTable) {
+ var prevFunc = proto[methodName];
+ // Inject an overload resolver function that routes to the appropriate overload based on the number of arguments.
+ proto[methodName] = function(...args) {
+ // TODO This check can be removed in -O3 level "unsafe" optimizations.
+ if (!proto[methodName].overloadTable.hasOwnProperty(args.length)) {
+ throwBindingError(`Function '${humanName}' called with an invalid number of arguments (${args.length}) - expects one of (${proto[methodName].overloadTable})!`);
+ }
+ return proto[methodName].overloadTable[args.length].apply(this, args);
+ };
+ // Move the previous function into the overload table.
+ proto[methodName].overloadTable = [];
+ proto[methodName].overloadTable[prevFunc.argCount] = prevFunc;
+ }
+};
+
+/** @param {number=} numArguments */ var exposePublicSymbol = (name, value, numArguments) => {
+ if (Module.hasOwnProperty(name)) {
+ if (undefined === numArguments || (undefined !== Module[name].overloadTable && undefined !== Module[name].overloadTable[numArguments])) {
+ throwBindingError(`Cannot register public name '${name}' twice`);
+ }
+ // We are exposing a function with the same name as an existing function. Create an overload table and a function selector
+ // that routes between the two.
+ ensureOverloadTable(Module, name, name);
+ if (Module[name].overloadTable.hasOwnProperty(numArguments)) {
+ throwBindingError(`Cannot register multiple overloads of a function with the same number of arguments (${numArguments})!`);
+ }
+ // Add the new function into the overload table.
+ Module[name].overloadTable[numArguments] = value;
+ } else {
+ Module[name] = value;
+ Module[name].argCount = numArguments;
+ }
+};
+
+var heap32VectorToArray = (count, firstElement) => {
+ var array = [];
+ for (var i = 0; i < count; i++) {
+ // TODO(https://github.com/emscripten-core/emscripten/issues/17310):
+ // Find a way to hoist the `>> 2` or `>> 3` out of this loop.
+ array.push(HEAPU32[(((firstElement) + (i * 4)) >>> 2) >>> 0]);
+ }
+ return array;
+};
+
+var InternalError = class InternalError extends Error {
+ constructor(message) {
+ super(message);
+ this.name = "InternalError";
+ }
+};
+
+var throwInternalError = message => {
+ throw new InternalError(message);
+};
+
+/** @param {number=} numArguments */ var replacePublicSymbol = (name, value, numArguments) => {
+ if (!Module.hasOwnProperty(name)) {
+ throwInternalError("Replacing nonexistent public symbol");
+ }
+ // If there's an overload table for this symbol, replace the symbol in the overload table instead.
+ if (undefined !== Module[name].overloadTable && undefined !== numArguments) {
+ Module[name].overloadTable[numArguments] = value;
+ } else {
+ Module[name] = value;
+ Module[name].argCount = numArguments;
+ }
+};
+
+var getDynCaller = (sig, ptr, promising = false) => (...args) => dynCall(sig, ptr, args, promising);
+
+var embind__requireFunction = (signature, rawFunction, isAsync = false) => {
+ signature = AsciiToString(signature);
+ function makeDynCaller() {
+ return getDynCaller(signature, rawFunction);
+ }
+ var fp = makeDynCaller();
+ if (typeof fp != "function") {
+ throwBindingError(`unknown function pointer with signature ${signature}: ${rawFunction}`);
+ }
+ return fp;
+};
+
+class UnboundTypeError extends Error {}
+
+var getTypeName = type => {
+ var ptr = ___getTypeName(type);
+ var rv = AsciiToString(ptr);
+ _free(ptr);
+ return rv;
+};
+
+var throwUnboundTypeError = (message, types) => {
+ var unboundTypes = [];
+ var seen = {};
+ function visit(type) {
+ if (seen[type]) {
+ return;
+ }
+ if (registeredTypes[type]) {
+ return;
+ }
+ if (typeDependencies[type]) {
+ typeDependencies[type].forEach(visit);
+ return;
+ }
+ unboundTypes.push(type);
+ seen[type] = true;
+ }
+ types.forEach(visit);
+ throw new UnboundTypeError(`${message}: ` + unboundTypes.map(getTypeName).join([ ", " ]));
+};
+
+var whenDependentTypesAreResolved = (myTypes, dependentTypes, getTypeConverters) => {
+ myTypes.forEach(type => typeDependencies[type] = dependentTypes);
+ function onComplete(typeConverters) {
+ var myTypeConverters = getTypeConverters(typeConverters);
+ if (myTypeConverters.length !== myTypes.length) {
+ throwInternalError("Mismatched type converter count");
+ }
+ for (var i = 0; i < myTypes.length; ++i) {
+ registerType(myTypes[i], myTypeConverters[i]);
+ }
+ }
+ var typeConverters = new Array(dependentTypes.length);
+ var unregisteredTypes = [];
+ var registered = 0;
+ for (let [i, dt] of dependentTypes.entries()) {
+ if (registeredTypes.hasOwnProperty(dt)) {
+ typeConverters[i] = registeredTypes[dt];
+ } else {
+ unregisteredTypes.push(dt);
+ if (!awaitingDependencies.hasOwnProperty(dt)) {
+ awaitingDependencies[dt] = [];
+ }
+ awaitingDependencies[dt].push(() => {
+ typeConverters[i] = registeredTypes[dt];
+ ++registered;
+ if (registered === unregisteredTypes.length) {
+ onComplete(typeConverters);
+ }
+ });
+ }
+ }
+ if (0 === unregisteredTypes.length) {
+ onComplete(typeConverters);
+ }
+};
+
+var getFunctionName = signature => {
+ signature = signature.trim();
+ const argsIndex = signature.indexOf("(");
+ if (argsIndex === -1) return signature;
+ return signature.slice(0, argsIndex);
+};
+
+function __embind_register_function(name, argCount, rawArgTypesAddr, signature, rawInvoker, fn, isAsync, isNonnullReturn) {
+ name >>>= 0;
+ rawArgTypesAddr >>>= 0;
+ signature >>>= 0;
+ rawInvoker >>>= 0;
+ fn >>>= 0;
+ var argTypes = heap32VectorToArray(argCount, rawArgTypesAddr);
+ name = AsciiToString(name);
+ name = getFunctionName(name);
+ rawInvoker = embind__requireFunction(signature, rawInvoker, isAsync);
+ exposePublicSymbol(name, function() {
+ throwUnboundTypeError(`Cannot call ${name} due to unbound types`, argTypes);
+ }, argCount - 1);
+ whenDependentTypesAreResolved([], argTypes, argTypes => {
+ var invokerArgsArray = [ argTypes[0], null ].concat(argTypes.slice(1));
+ replacePublicSymbol(name, craftInvokerFunction(name, invokerArgsArray, null, rawInvoker, fn, isAsync), argCount - 1);
+ return [];
+ });
+}
+
+var integerReadValueFromPointer = (name, width, signed) => {
+ // integers are quite common, so generate very specialized functions
+ switch (width) {
+ case 1:
+ return signed ? pointer => HEAP8[pointer >>> 0] : pointer => HEAPU8[pointer >>> 0];
+
+ case 2:
+ return signed ? pointer => HEAP16[((pointer) >>> 1) >>> 0] : pointer => HEAPU16[((pointer) >>> 1) >>> 0];
+
+ case 4:
+ return signed ? pointer => HEAP32[((pointer) >>> 2) >>> 0] : pointer => HEAPU32[((pointer) >>> 2) >>> 0];
+
+ default:
+ throw new TypeError(`invalid integer width (${width}): ${name}`);
+ }
+};
+
+/** @suppress {globalThis} */ var __embind_register_integer = function(primitiveType, name, size, minRange, maxRange) {
+ primitiveType >>>= 0;
+ name >>>= 0;
+ size >>>= 0;
+ name = AsciiToString(name);
+ const isUnsignedType = minRange === 0;
+ let fromWireType = value => value;
+ if (isUnsignedType) {
+ var bitshift = 32 - 8 * size;
+ fromWireType = value => (value << bitshift) >>> bitshift;
+ maxRange = fromWireType(maxRange);
+ }
+ registerType(primitiveType, {
+ name,
+ fromWireType,
+ toWireType: (destructors, value) => value,
+ readValueFromPointer: integerReadValueFromPointer(name, size, minRange !== 0),
+ destructorFunction: null
+ });
+};
+
+function __embind_register_memory_view(rawType, dataTypeIndex, name) {
+ rawType >>>= 0;
+ name >>>= 0;
+ var typeMapping = [ Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array ];
+ var TA = typeMapping[dataTypeIndex];
+ function decodeMemoryView(handle) {
+ var size = HEAPU32[((handle) >>> 2) >>> 0];
+ var data = HEAPU32[(((handle) + (4)) >>> 2) >>> 0];
+ return new TA(HEAP8.buffer, data, size);
+ }
+ name = AsciiToString(name);
+ registerType(rawType, {
+ name,
+ fromWireType: decodeMemoryView,
+ readValueFromPointer: decodeMemoryView
+ }, {
+ ignoreDuplicateRegistrations: true
+ });
+}
+
+function __embind_register_std_string(rawType, name) {
+ rawType >>>= 0;
+ name >>>= 0;
+ name = AsciiToString(name);
+ var stdStringIsUTF8 = true;
+ registerType(rawType, {
+ name,
+ // For some method names we use string keys here since they are part of
+ // the public/external API and/or used by the runtime-generated code.
+ fromWireType(value) {
+ var length = HEAPU32[((value) >>> 2) >>> 0];
+ var payload = value + 4;
+ var str;
+ if (stdStringIsUTF8) {
+ str = UTF8ToString(payload, length, true);
+ } else {
+ str = "";
+ for (var i = 0; i < length; ++i) {
+ str += String.fromCharCode(HEAPU8[payload + i >>> 0]);
+ }
+ }
+ _free(value);
+ return str;
+ },
+ toWireType(destructors, value) {
+ if (value instanceof ArrayBuffer) {
+ value = new Uint8Array(value);
+ }
+ var length;
+ var valueIsOfTypeString = (typeof value == "string");
+ // We accept `string` or array views with single byte elements
+ if (!(valueIsOfTypeString || (ArrayBuffer.isView(value) && value.BYTES_PER_ELEMENT == 1))) {
+ throwBindingError("Cannot pass non-string to std::string");
+ }
+ if (stdStringIsUTF8 && valueIsOfTypeString) {
+ length = lengthBytesUTF8(value);
+ } else {
+ length = value.length;
+ }
+ // assumes POINTER_SIZE alignment
+ var base = _malloc(4 + length + 1);
+ var ptr = base + 4;
+ HEAPU32[((base) >>> 2) >>> 0] = length;
+ if (valueIsOfTypeString) {
+ if (stdStringIsUTF8) {
+ stringToUTF8(value, ptr, length + 1);
+ } else {
+ for (var i = 0; i < length; ++i) {
+ var charCode = value.charCodeAt(i);
+ if (charCode > 255) {
+ _free(base);
+ throwBindingError("String has UTF-16 code units that do not fit in 8 bits");
+ }
+ HEAPU8[ptr + i >>> 0] = charCode;
+ }
+ }
+ } else {
+ HEAPU8.set(value, ptr >>> 0);
+ }
+ if (destructors !== null) {
+ destructors.push(_free, base);
+ }
+ return base;
+ },
+ readValueFromPointer: readPointer,
+ destructorFunction(ptr) {
+ _free(ptr);
+ }
+ });
+}
+
+var UTF16Decoder = new TextDecoder("utf-16le");
+
+var UTF16ToString = (ptr, maxBytesToRead, ignoreNul) => {
+ var idx = ((ptr) >>> 1);
+ var endIdx = findStringEnd(HEAPU16, idx, maxBytesToRead / 2, ignoreNul);
+ return UTF16Decoder.decode(HEAPU16.subarray(idx >>> 0, endIdx >>> 0));
+};
+
+var stringToUTF16 = (str, outPtr, maxBytesToWrite) => {
+ // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed.
+ maxBytesToWrite ??= 2147483647;
+ if (maxBytesToWrite < 2) return 0;
+ maxBytesToWrite -= 2;
+ // Null terminator.
+ var startPtr = outPtr;
+ var numCharsToWrite = (maxBytesToWrite < str.length * 2) ? (maxBytesToWrite / 2) : str.length;
+ for (var i = 0; i < numCharsToWrite; ++i) {
+ // charCodeAt returns a UTF-16 encoded code unit, so it can be directly written to the HEAP.
+ var codeUnit = str.charCodeAt(i);
+ // possibly a lead surrogate
+ HEAP16[((outPtr) >>> 1) >>> 0] = codeUnit;
+ outPtr += 2;
+ }
+ // Null-terminate the pointer to the HEAP.
+ HEAP16[((outPtr) >>> 1) >>> 0] = 0;
+ return outPtr - startPtr;
+};
+
+var lengthBytesUTF16 = str => str.length * 2;
+
+var UTF32ToString = (ptr, maxBytesToRead, ignoreNul) => {
+ var str = "";
+ var startIdx = ((ptr) >>> 2);
+ // If maxBytesToRead is not passed explicitly, it will be undefined, and this
+ // will always evaluate to true. This saves on code size.
+ for (var i = 0; !(i >= maxBytesToRead / 4); i++) {
+ var utf32 = HEAPU32[startIdx + i >>> 0];
+ if (!utf32 && !ignoreNul) break;
+ str += String.fromCodePoint(utf32);
+ }
+ return str;
+};
+
+var stringToUTF32 = (str, outPtr, maxBytesToWrite) => {
+ outPtr >>>= 0;
+ // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed.
+ maxBytesToWrite ??= 2147483647;
+ if (maxBytesToWrite < 4) return 0;
+ var startPtr = outPtr;
+ var endPtr = startPtr + maxBytesToWrite - 4;
+ for (var i = 0; i < str.length; ++i) {
+ var codePoint = str.codePointAt(i);
+ // Gotcha: if codePoint is over 0xFFFF, it is represented as a surrogate pair in UTF-16.
+ // We need to manually skip over the second code unit for correct iteration.
+ if (codePoint > 65535) {
+ i++;
+ }
+ HEAP32[((outPtr) >>> 2) >>> 0] = codePoint;
+ outPtr += 4;
+ if (outPtr + 4 > endPtr) break;
+ }
+ // Null-terminate the pointer to the HEAP.
+ HEAP32[((outPtr) >>> 2) >>> 0] = 0;
+ return outPtr - startPtr;
+};
+
+var lengthBytesUTF32 = str => {
+ var len = 0;
+ for (var i = 0; i < str.length; ++i) {
+ var codePoint = str.codePointAt(i);
+ // Gotcha: if codePoint is over 0xFFFF, it is represented as a surrogate pair in UTF-16.
+ // We need to manually skip over the second code unit for correct iteration.
+ if (codePoint > 65535) {
+ i++;
+ }
+ len += 4;
+ }
+ return len;
+};
+
+function __embind_register_std_wstring(rawType, charSize, name) {
+ rawType >>>= 0;
+ charSize >>>= 0;
+ name >>>= 0;
+ name = AsciiToString(name);
+ var decodeString, encodeString, lengthBytesUTF;
+ if (charSize === 2) {
+ decodeString = UTF16ToString;
+ encodeString = stringToUTF16;
+ lengthBytesUTF = lengthBytesUTF16;
+ } else {
+ decodeString = UTF32ToString;
+ encodeString = stringToUTF32;
+ lengthBytesUTF = lengthBytesUTF32;
+ }
+ registerType(rawType, {
+ name,
+ fromWireType: value => {
+ // Code mostly taken from _embind_register_std_string fromWireType
+ var length = HEAPU32[((value) >>> 2) >>> 0];
+ var str = decodeString(value + 4, length * charSize, true);
+ _free(value);
+ return str;
+ },
+ toWireType: (destructors, value) => {
+ if (!(typeof value == "string")) {
+ throwBindingError(`Cannot pass non-string to C++ string type ${name}`);
+ }
+ // assumes POINTER_SIZE alignment
+ var length = lengthBytesUTF(value);
+ var ptr = _malloc(4 + length + charSize);
+ HEAPU32[((ptr) >>> 2) >>> 0] = length / charSize;
+ encodeString(value, ptr + 4, length + charSize);
+ if (destructors !== null) {
+ destructors.push(_free, ptr);
+ }
+ return ptr;
+ },
+ readValueFromPointer: readPointer,
+ destructorFunction(ptr) {
+ _free(ptr);
+ }
+ });
+}
+
+var __embind_register_void = function(rawType, name) {
+ rawType >>>= 0;
+ name >>>= 0;
+ name = AsciiToString(name);
+ registerType(rawType, {
+ isVoid: true,
+ // void return values can be optimized out sometimes
+ name,
+ fromWireType: () => undefined,
+ // TODO: assert if anything else is given?
+ toWireType: (destructors, o) => undefined
+ });
+};
+
+var emval_methodCallers = [];
+
+var emval_addMethodCaller = caller => {
+ var id = emval_methodCallers.length;
+ emval_methodCallers.push(caller);
+ return id;
+};
+
+var requireRegisteredType = (rawType, humanName) => {
+ var impl = registeredTypes[rawType];
+ if (undefined === impl) {
+ throwBindingError(`${humanName} has unknown type ${getTypeName(rawType)}`);
+ }
+ return impl;
+};
+
+var emval_lookupTypes = (argCount, argTypes) => {
+ var a = new Array(argCount);
+ for (var i = 0; i < argCount; ++i) {
+ a[i] = requireRegisteredType(HEAPU32[(((argTypes) + (i * 4)) >>> 2) >>> 0], `parameter ${i}`);
+ }
+ return a;
+};
+
+var emval_returnValue = (toReturnWire, destructorsRef, handle) => {
+ var destructors = [];
+ var result = toReturnWire(destructors, handle);
+ if (destructors.length) {
+ // void, primitives and any other types w/o destructors don't need to allocate a handle
+ HEAPU32[((destructorsRef) >>> 2) >>> 0] = Emval.toHandle(destructors);
+ }
+ return result;
+};
+
+var emval_symbols = {};
+
+var getStringOrSymbol = address => {
+ var symbol = emval_symbols[address];
+ if (symbol === undefined) {
+ return AsciiToString(address);
+ }
+ return symbol;
+};
+
+var __emval_create_invoker = function(argCount, argTypesPtr, kind) {
+ argTypesPtr >>>= 0;
+ var GenericWireTypeSize = 8;
+ var [retType, ...argTypes] = emval_lookupTypes(argCount, argTypesPtr);
+ var toReturnWire = retType.toWireType.bind(retType);
+ var argFromPtr = argTypes.map(type => type.readValueFromPointer.bind(type));
+ argCount--;
+ // remove the extracted return type
+ var argN = new Array(argCount);
+ var invokerFunction = (handle, methodName, destructorsRef, args) => {
+ var offset = 0;
+ for (var i = 0; i < argCount; ++i) {
+ argN[i] = argFromPtr[i](args + offset);
+ offset += GenericWireTypeSize;
+ }
+ var rv;
+ switch (kind) {
+ case 0:
+ rv = Emval.toValue(handle).apply(null, argN);
+ break;
+
+ case 2:
+ rv = Reflect.construct(Emval.toValue(handle), argN);
+ break;
+
+ case 3:
+ // no-op, just return the argument
+ rv = argN[0];
+ break;
+
+ case 1:
+ rv = Emval.toValue(handle)[getStringOrSymbol(methodName)](...argN);
+ break;
+ }
+ return emval_returnValue(toReturnWire, destructorsRef, rv);
+ };
+ var functionName = `methodCaller<(${argTypes.map(t => t.name)}) => ${retType.name}>`;
+ return emval_addMethodCaller(createNamedFunction(functionName, invokerFunction));
+};
+
+function __emval_incref(handle) {
+ handle >>>= 0;
+ if (handle > 9) {
+ emval_handles[handle + 1] += 1;
+ }
+}
+
+function __emval_invoke(caller, handle, methodName, destructorsRef, args) {
+ caller >>>= 0;
+ handle >>>= 0;
+ methodName >>>= 0;
+ destructorsRef >>>= 0;
+ args >>>= 0;
+ return emval_methodCallers[caller](handle, methodName, destructorsRef, args);
+}
+
+function __emval_run_destructors(handle) {
+ handle >>>= 0;
+ var destructors = Emval.toValue(handle);
+ runDestructors(destructors);
+ __emval_decref(handle);
+}
+
+function __gmtime_js(time_low, time_high, tmPtr) {
+ var time = convertI32PairToI53Checked(time_low, time_high);
+ tmPtr >>>= 0;
+ var date = new Date(time * 1e3);
+ HEAP32[((tmPtr) >>> 2) >>> 0] = date.getUTCSeconds();
+ HEAP32[(((tmPtr) + (4)) >>> 2) >>> 0] = date.getUTCMinutes();
+ HEAP32[(((tmPtr) + (8)) >>> 2) >>> 0] = date.getUTCHours();
+ HEAP32[(((tmPtr) + (12)) >>> 2) >>> 0] = date.getUTCDate();
+ HEAP32[(((tmPtr) + (16)) >>> 2) >>> 0] = date.getUTCMonth();
+ HEAP32[(((tmPtr) + (20)) >>> 2) >>> 0] = date.getUTCFullYear() - 1900;
+ HEAP32[(((tmPtr) + (24)) >>> 2) >>> 0] = date.getUTCDay();
+ var start = Date.UTC(date.getUTCFullYear(), 0, 1, 0, 0, 0, 0);
+ var yday = ((date.getTime() - start) / (1e3 * 60 * 60 * 24)) | 0;
+ HEAP32[(((tmPtr) + (28)) >>> 2) >>> 0] = yday;
+}
+
+var isLeapYear = year => year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
+
+var MONTH_DAYS_LEAP_CUMULATIVE = [ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 ];
+
+var MONTH_DAYS_REGULAR_CUMULATIVE = [ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 ];
+
+var ydayFromDate = date => {
+ var leap = isLeapYear(date.getFullYear());
+ var monthDaysCumulative = (leap ? MONTH_DAYS_LEAP_CUMULATIVE : MONTH_DAYS_REGULAR_CUMULATIVE);
+ var yday = monthDaysCumulative[date.getMonth()] + date.getDate() - 1;
+ // -1 since it's days since Jan 1
+ return yday;
+};
+
+function __localtime_js(time_low, time_high, tmPtr) {
+ var time = convertI32PairToI53Checked(time_low, time_high);
+ tmPtr >>>= 0;
+ var date = new Date(time * 1e3);
+ HEAP32[((tmPtr) >>> 2) >>> 0] = date.getSeconds();
+ HEAP32[(((tmPtr) + (4)) >>> 2) >>> 0] = date.getMinutes();
+ HEAP32[(((tmPtr) + (8)) >>> 2) >>> 0] = date.getHours();
+ HEAP32[(((tmPtr) + (12)) >>> 2) >>> 0] = date.getDate();
+ HEAP32[(((tmPtr) + (16)) >>> 2) >>> 0] = date.getMonth();
+ HEAP32[(((tmPtr) + (20)) >>> 2) >>> 0] = date.getFullYear() - 1900;
+ HEAP32[(((tmPtr) + (24)) >>> 2) >>> 0] = date.getDay();
+ var yday = ydayFromDate(date) | 0;
+ HEAP32[(((tmPtr) + (28)) >>> 2) >>> 0] = yday;
+ HEAP32[(((tmPtr) + (36)) >>> 2) >>> 0] = -(date.getTimezoneOffset() * 60);
+ // Attention: DST is in December in South, and some regions don't have DST at all.
+ var start = new Date(date.getFullYear(), 0, 1);
+ var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset();
+ var winterOffset = start.getTimezoneOffset();
+ var dst = (summerOffset != winterOffset && date.getTimezoneOffset() == Math.min(winterOffset, summerOffset)) | 0;
+ HEAP32[(((tmPtr) + (32)) >>> 2) >>> 0] = dst;
+}
+
+var setTempRet0 = val => __emscripten_tempret_set(val);
+
+var __mktime_js = function(tmPtr) {
+ tmPtr >>>= 0;
+ var ret = (() => {
+ var date = new Date(HEAP32[(((tmPtr) + (20)) >>> 2) >>> 0] + 1900, HEAP32[(((tmPtr) + (16)) >>> 2) >>> 0], HEAP32[(((tmPtr) + (12)) >>> 2) >>> 0], HEAP32[(((tmPtr) + (8)) >>> 2) >>> 0], HEAP32[(((tmPtr) + (4)) >>> 2) >>> 0], HEAP32[((tmPtr) >>> 2) >>> 0], 0);
+ // There's an ambiguous hour when the time goes back; the tm_isdst field is
+ // used to disambiguate it. Date() basically guesses, so we fix it up if it
+ // guessed wrong, or fill in tm_isdst with the guess if it's -1.
+ var dst = HEAP32[(((tmPtr) + (32)) >>> 2) >>> 0];
+ var guessedOffset = date.getTimezoneOffset();
+ var start = new Date(date.getFullYear(), 0, 1);
+ var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset();
+ var winterOffset = start.getTimezoneOffset();
+ var dstOffset = Math.min(winterOffset, summerOffset);
+ // DST is in December in South
+ if (dst < 0) {
+ // Attention: some regions don't have DST at all.
+ HEAP32[(((tmPtr) + (32)) >>> 2) >>> 0] = Number(summerOffset != winterOffset && dstOffset == guessedOffset);
+ } else if ((dst > 0) != (dstOffset == guessedOffset)) {
+ var nonDstOffset = Math.max(winterOffset, summerOffset);
+ var trueOffset = dst > 0 ? dstOffset : nonDstOffset;
+ // Don't try setMinutes(date.getMinutes() + ...) -- it's messed up.
+ date.setTime(date.getTime() + (trueOffset - guessedOffset) * 6e4);
+ }
+ HEAP32[(((tmPtr) + (24)) >>> 2) >>> 0] = date.getDay();
+ var yday = ydayFromDate(date) | 0;
+ HEAP32[(((tmPtr) + (28)) >>> 2) >>> 0] = yday;
+ // To match expected behavior, update fields from date
+ HEAP32[((tmPtr) >>> 2) >>> 0] = date.getSeconds();
+ HEAP32[(((tmPtr) + (4)) >>> 2) >>> 0] = date.getMinutes();
+ HEAP32[(((tmPtr) + (8)) >>> 2) >>> 0] = date.getHours();
+ HEAP32[(((tmPtr) + (12)) >>> 2) >>> 0] = date.getDate();
+ HEAP32[(((tmPtr) + (16)) >>> 2) >>> 0] = date.getMonth();
+ HEAP32[(((tmPtr) + (20)) >>> 2) >>> 0] = date.getYear();
+ var timeMs = date.getTime();
+ if (isNaN(timeMs)) {
+ return -1;
+ }
+ // Return time in microseconds
+ return timeMs / 1e3;
+ })();
+ return (setTempRet0((tempDouble = ret, (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0)),
+ ret >>> 0);
+};
+
+function __mmap_js(len, prot, flags, fd, offset_low, offset_high, allocated, addr) {
+ len >>>= 0;
+ var offset = convertI32PairToI53Checked(offset_low, offset_high);
+ allocated >>>= 0;
+ addr >>>= 0;
+ try {
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ var res = FS.mmap(stream, len, offset, prot, flags);
+ var ptr = res.ptr;
+ HEAP32[((allocated) >>> 2) >>> 0] = res.allocated;
+ HEAPU32[((addr) >>> 2) >>> 0] = ptr;
+ return 0;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+function __munmap_js(addr, len, prot, flags, fd, offset_low, offset_high) {
+ addr >>>= 0;
+ len >>>= 0;
+ var offset = convertI32PairToI53Checked(offset_low, offset_high);
+ try {
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ if (prot & 2) {
+ SYSCALLS.doMsync(addr, stream, len, flags, offset);
+ }
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+var __tzset_js = function(timezone, daylight, std_name, dst_name) {
+ timezone >>>= 0;
+ daylight >>>= 0;
+ std_name >>>= 0;
+ dst_name >>>= 0;
+ // TODO: Use (malleable) environment variables instead of system settings.
+ var currentYear = (new Date).getFullYear();
+ var winter = new Date(currentYear, 0, 1);
+ var summer = new Date(currentYear, 6, 1);
+ var winterOffset = winter.getTimezoneOffset();
+ var summerOffset = summer.getTimezoneOffset();
+ // Local standard timezone offset. Local standard time is not adjusted for
+ // daylight savings. This code uses the fact that getTimezoneOffset returns
+ // a greater value during Standard Time versus Daylight Saving Time (DST).
+ // Thus it determines the expected output during Standard Time, and it
+ // compares whether the output of the given date the same (Standard) or less
+ // (DST).
+ var stdTimezoneOffset = Math.max(winterOffset, summerOffset);
+ // timezone is specified as seconds west of UTC ("The external variable
+ // `timezone` shall be set to the difference, in seconds, between
+ // Coordinated Universal Time (UTC) and local standard time."), the same
+ // as returned by stdTimezoneOffset.
+ // See http://pubs.opengroup.org/onlinepubs/009695399/functions/tzset.html
+ HEAPU32[((timezone) >>> 2) >>> 0] = stdTimezoneOffset * 60;
+ HEAP32[((daylight) >>> 2) >>> 0] = Number(winterOffset != summerOffset);
+ var extractZone = timezoneOffset => {
+ // Why inverse sign?
+ // Read here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset
+ var sign = timezoneOffset >= 0 ? "-" : "+";
+ var absOffset = Math.abs(timezoneOffset);
+ var hours = String(Math.floor(absOffset / 60)).padStart(2, "0");
+ var minutes = String(absOffset % 60).padStart(2, "0");
+ return `UTC${sign}${hours}${minutes}`;
+ };
+ var winterName = extractZone(winterOffset);
+ var summerName = extractZone(summerOffset);
+ if (summerOffset < winterOffset) {
+ // Northern hemisphere
+ stringToUTF8(winterName, std_name, 17);
+ stringToUTF8(summerName, dst_name, 17);
+ } else {
+ stringToUTF8(winterName, dst_name, 17);
+ stringToUTF8(summerName, std_name, 17);
+ }
+};
+
+var _emscripten_get_now = () => performance.now();
+
+var _emscripten_date_now = () => Date.now();
+
+var nowIsMonotonic = 1;
+
+var checkWasiClock = clock_id => clock_id >= 0 && clock_id <= 3;
+
+function _clock_time_get(clk_id, ignored_precision_low, ignored_precision_high, ptime) {
+ var ignored_precision = convertI32PairToI53Checked(ignored_precision_low, ignored_precision_high);
+ ptime >>>= 0;
+ if (!checkWasiClock(clk_id)) {
+ return 28;
+ }
+ var now;
+ // all wasi clocks but realtime are monotonic
+ if (clk_id === 0) {
+ now = _emscripten_date_now();
+ } else if (nowIsMonotonic) {
+ now = _emscripten_get_now();
+ } else {
+ return 52;
+ }
+ // "now" is in ms, and wasi times are in ns.
+ var nsec = Math.round(now * 1e3 * 1e3);
+ (tempI64 = [ nsec >>> 0, (tempDouble = nsec, (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0) ],
+ HEAP32[((ptime) >>> 2) >>> 0] = tempI64[0], HEAP32[(((ptime) + (4)) >>> 2) >>> 0] = tempI64[1]);
+ return 0;
+}
+
+var readEmAsmArgsArray = [];
+
+var readEmAsmArgs = (sigPtr, buf) => {
+ readEmAsmArgsArray.length = 0;
+ var ch;
+ // Most arguments are i32s, so shift the buffer pointer so it is a plain
+ // index into HEAP32.
+ while (ch = HEAPU8[sigPtr++ >>> 0]) {
+ // Floats are always passed as doubles, so all types except for 'i'
+ // are 8 bytes and require alignment.
+ var wide = (ch != 105);
+ wide &= (ch != 112);
+ buf += wide && (buf % 8) ? 4 : 0;
+ readEmAsmArgsArray.push(// Special case for pointers under wasm64 or CAN_ADDRESS_2GB mode.
+ ch == 112 ? HEAPU32[((buf) >>> 2) >>> 0] : ch == 105 ? HEAP32[((buf) >>> 2) >>> 0] : HEAPF64[((buf) >>> 3) >>> 0]);
+ buf += wide ? 8 : 4;
+ }
+ return readEmAsmArgsArray;
+};
+
+var runEmAsmFunction = (code, sigPtr, argbuf) => {
+ var args = readEmAsmArgs(sigPtr, argbuf);
+ return ASM_CONSTS[code](...args);
+};
+
+function _emscripten_asm_const_int(code, sigPtr, argbuf) {
+ code >>>= 0;
+ sigPtr >>>= 0;
+ argbuf >>>= 0;
+ return runEmAsmFunction(code, sigPtr, argbuf);
+}
+
+function _emscripten_errn(str, len) {
+ str >>>= 0;
+ len >>>= 0;
+ return err(UTF8ToString(str, len));
+}
+
+var getHeapMax = () => // Stay one Wasm page short of 4GB: while e.g. Chrome is able to allocate
+// full 4GB Wasm memories, the size will wrap back to 0 bytes in Wasm side
+// for any code that deals with heap sizes, which would require special
+// casing all heap size related code to treat 0 specially.
+4294901760;
+
+function _emscripten_get_heap_max() {
+ return getHeapMax();
+}
+
+var _emscripten_has_asyncify = () => 1;
+
+function _emscripten_outn(str, len) {
+ str >>>= 0;
+ len >>>= 0;
+ return out(UTF8ToString(str, len));
+}
+
+var UNWIND_CACHE = {};
+
+var stringToNewUTF8 = str => {
+ var size = lengthBytesUTF8(str) + 1;
+ var ret = _malloc(size);
+ if (ret) stringToUTF8(str, ret, size);
+ return ret;
+};
+
+/** @returns {number} */ var convertFrameToPC = frame => {
+ var match;
+ if (match = /\bwasm-function\[\d+\]:(0x[0-9a-f]+)/.exec(frame)) {
+ // Wasm engines give the binary offset directly, so we use that as return address
+ return +match[1];
+ } else if (match = /:(\d+):\d+(?:\)|$)/.exec(frame)) {
+ // If we are in js, we can use the js line number as the "return address".
+ // This should work for wasm2js. We tag the high bit to distinguish this
+ // from wasm addresses.
+ return 2147483648 | +match[1];
+ }
+ // return 0 if we can't find any
+ return 0;
+};
+
+var saveInUnwindCache = callstack => {
+ for (var line of callstack) {
+ var pc = convertFrameToPC(line);
+ if (pc) {
+ UNWIND_CACHE[pc] = line;
+ }
+ }
+};
+
+var jsStackTrace = () => (new Error).stack.toString();
+
+function _emscripten_stack_snapshot() {
+ var callstack = jsStackTrace().split("\n");
+ if (callstack[0] == "Error") {
+ callstack.shift();
+ }
+ saveInUnwindCache(callstack);
+ // Caches the stack snapshot so that emscripten_stack_unwind_buffer() can
+ // unwind from this spot.
+ UNWIND_CACHE.last_addr = convertFrameToPC(callstack[3]);
+ UNWIND_CACHE.last_stack = callstack;
+ return UNWIND_CACHE.last_addr;
+}
+
+function _emscripten_pc_get_function(pc) {
+ pc >>>= 0;
+ var frame = UNWIND_CACHE[pc];
+ if (!frame) return 0;
+ var name;
+ var match;
+ // First try to match foo.wasm.sym files explcitly. e.g.
+ // at test_return_address.wasm.main (wasm://wasm/test_return_address.wasm-0012cc2a:wasm-function[26]:0x9f3
+ // Then match JS symbols which don't include that module name:
+ // at invokeEntryPoint (.../test_return_address.js:1500:42)
+ // Finally match firefox format:
+ // Object._main@http://server.com:4324:12'
+ if (match = /^\s+at .*\.wasm\.(.*) \(.*\)$/.exec(frame)) {
+ name = match[1];
+ } else if (match = /^\s+at (.*) \(.*\)$/.exec(frame)) {
+ name = match[1];
+ } else if (match = /^(.+?)@/.exec(frame)) {
+ name = match[1];
+ } else {
+ return 0;
+ }
+ _free(_emscripten_pc_get_function.ret ?? 0);
+ _emscripten_pc_get_function.ret = stringToNewUTF8(name);
+ return _emscripten_pc_get_function.ret;
+}
+
+var growMemory = size => {
+ var oldHeapSize = wasmMemory.buffer.byteLength;
+ var pages = ((size - oldHeapSize + 65535) / 65536) | 0;
+ try {
+ // round size grow request up to wasm page size (fixed 64KB per spec)
+ wasmMemory.grow(pages);
+ // .grow() takes a delta compared to the previous size
+ updateMemoryViews();
+ return 1;
+ } catch (e) {}
+};
+
+function _emscripten_resize_heap(requestedSize) {
+ requestedSize >>>= 0;
+ var oldSize = HEAPU8.length;
+ // With multithreaded builds, races can happen (another thread might increase the size
+ // in between), so return a failure, and let the caller retry.
+ // Memory resize rules:
+ // 1. Always increase heap size to at least the requested size, rounded up
+ // to next page multiple.
+ // 2a. If MEMORY_GROWTH_LINEAR_STEP == -1, excessively resize the heap
+ // geometrically: increase the heap size according to
+ // MEMORY_GROWTH_GEOMETRIC_STEP factor (default +20%), At most
+ // overreserve by MEMORY_GROWTH_GEOMETRIC_CAP bytes (default 96MB).
+ // 2b. If MEMORY_GROWTH_LINEAR_STEP != -1, excessively resize the heap
+ // linearly: increase the heap size by at least
+ // MEMORY_GROWTH_LINEAR_STEP bytes.
+ // 3. Max size for the heap is capped at 2048MB-WASM_PAGE_SIZE, or by
+ // MAXIMUM_MEMORY, or by ASAN limit, depending on which is smallest
+ // 4. If we were unable to allocate as much memory, it may be due to
+ // over-eager decision to excessively reserve due to (3) above.
+ // Hence if an allocation fails, cut down on the amount of excess
+ // growth, in an attempt to succeed to perform a smaller allocation.
+ // A limit is set for how much we can grow. We should not exceed that
+ // (the wasm binary specifies it, so if we tried, we'd fail anyhow).
+ var maxHeapSize = getHeapMax();
+ if (requestedSize > maxHeapSize) {
+ return false;
+ }
+ // Loop through potential heap size increases. If we attempt a too eager
+ // reservation that fails, cut down on the attempted size and reserve a
+ // smaller bump instead. (max 3 times, chosen somewhat arbitrarily)
+ for (var cutDown = 1; cutDown <= 4; cutDown *= 2) {
+ var overGrownHeapSize = oldSize * (1 + .2 / cutDown);
+ // ensure geometric growth
+ // but limit overreserving (default to capping at +96MB overgrowth at most)
+ overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296);
+ var newSize = Math.min(maxHeapSize, alignMemory(Math.max(requestedSize, overGrownHeapSize), 65536));
+ var replacement = growMemory(newSize);
+ if (replacement) {
+ return true;
+ }
+ }
+ return false;
+}
+
+function _emscripten_stack_unwind_buffer(addr, buffer, count) {
+ addr >>>= 0;
+ buffer >>>= 0;
+ var stack;
+ if (UNWIND_CACHE.last_addr == addr) {
+ stack = UNWIND_CACHE.last_stack;
+ } else {
+ stack = jsStackTrace().split("\n");
+ if (stack[0] == "Error") {
+ stack.shift();
+ }
+ saveInUnwindCache(stack);
+ }
+ var offset = 3;
+ while (stack[offset] && convertFrameToPC(stack[offset]) != addr) {
+ ++offset;
+ }
+ for (var i = 0; i < count && stack[i + offset]; ++i) {
+ HEAP32[(((buffer) + (i * 4)) >>> 2) >>> 0] = convertFrameToPC(stack[i + offset]);
+ }
+ return i;
+}
+
+var GLctx;
+
+var webgl_enable_ANGLE_instanced_arrays = ctx => {
+ // Extension available in WebGL 1 from Firefox 26 and Google Chrome 30 onwards. Core feature in WebGL 2.
+ var ext = ctx.getExtension("ANGLE_instanced_arrays");
+ // Because this extension is a core function in WebGL 2, assign the extension entry points in place of
+ // where the core functions will reside in WebGL 2. This way the calling code can call these without
+ // having to dynamically branch depending if running against WebGL 1 or WebGL 2.
+ if (ext) {
+ ctx["vertexAttribDivisor"] = (index, divisor) => ext["vertexAttribDivisorANGLE"](index, divisor);
+ ctx["drawArraysInstanced"] = (mode, first, count, primcount) => ext["drawArraysInstancedANGLE"](mode, first, count, primcount);
+ ctx["drawElementsInstanced"] = (mode, count, type, indices, primcount) => ext["drawElementsInstancedANGLE"](mode, count, type, indices, primcount);
+ return 1;
+ }
+};
+
+var webgl_enable_OES_vertex_array_object = ctx => {
+ // Extension available in WebGL 1 from Firefox 25 and WebKit 536.28/desktop Safari 6.0.3 onwards. Core feature in WebGL 2.
+ var ext = ctx.getExtension("OES_vertex_array_object");
+ if (ext) {
+ ctx["createVertexArray"] = () => ext["createVertexArrayOES"]();
+ ctx["deleteVertexArray"] = vao => ext["deleteVertexArrayOES"](vao);
+ ctx["bindVertexArray"] = vao => ext["bindVertexArrayOES"](vao);
+ ctx["isVertexArray"] = vao => ext["isVertexArrayOES"](vao);
+ return 1;
+ }
+};
+
+var webgl_enable_WEBGL_draw_buffers = ctx => {
+ // Extension available in WebGL 1 from Firefox 28 onwards. Core feature in WebGL 2.
+ var ext = ctx.getExtension("WEBGL_draw_buffers");
+ if (ext) {
+ ctx["drawBuffers"] = (n, bufs) => ext["drawBuffersWEBGL"](n, bufs);
+ return 1;
+ }
+};
+
+var webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance = ctx => // Closure is expected to be allowed to minify the '.dibvbi' property, so not accessing it quoted.
+!!(ctx.dibvbi = ctx.getExtension("WEBGL_draw_instanced_base_vertex_base_instance"));
+
+var webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance = ctx => !!(ctx.mdibvbi = ctx.getExtension("WEBGL_multi_draw_instanced_base_vertex_base_instance"));
+
+var webgl_enable_EXT_polygon_offset_clamp = ctx => !!(ctx.extPolygonOffsetClamp = ctx.getExtension("EXT_polygon_offset_clamp"));
+
+var webgl_enable_EXT_clip_control = ctx => !!(ctx.extClipControl = ctx.getExtension("EXT_clip_control"));
+
+var webgl_enable_WEBGL_polygon_mode = ctx => !!(ctx.webglPolygonMode = ctx.getExtension("WEBGL_polygon_mode"));
+
+var webgl_enable_WEBGL_multi_draw = ctx => // Closure is expected to be allowed to minify the '.multiDrawWebgl' property, so not accessing it quoted.
+!!(ctx.multiDrawWebgl = ctx.getExtension("WEBGL_multi_draw"));
+
+var getEmscriptenSupportedExtensions = ctx => {
+ // Restrict the list of advertised extensions to those that we actually
+ // support.
+ var supportedExtensions = [ // WebGL 1 extensions
+ "ANGLE_instanced_arrays", "EXT_blend_minmax", "EXT_disjoint_timer_query", "EXT_frag_depth", "EXT_shader_texture_lod", "EXT_sRGB", "OES_element_index_uint", "OES_fbo_render_mipmap", "OES_standard_derivatives", "OES_texture_float", "OES_texture_half_float", "OES_texture_half_float_linear", "OES_vertex_array_object", "WEBGL_color_buffer_float", "WEBGL_depth_texture", "WEBGL_draw_buffers", // WebGL 2 extensions
+ "EXT_color_buffer_float", "EXT_conservative_depth", "EXT_disjoint_timer_query_webgl2", "EXT_texture_norm16", "NV_shader_noperspective_interpolation", "WEBGL_clip_cull_distance", // WebGL 1 and WebGL 2 extensions
+ "EXT_clip_control", "EXT_color_buffer_half_float", "EXT_depth_clamp", "EXT_float_blend", "EXT_polygon_offset_clamp", "EXT_texture_compression_bptc", "EXT_texture_compression_rgtc", "EXT_texture_filter_anisotropic", "KHR_parallel_shader_compile", "OES_texture_float_linear", "WEBGL_blend_func_extended", "WEBGL_compressed_texture_astc", "WEBGL_compressed_texture_etc", "WEBGL_compressed_texture_etc1", "WEBGL_compressed_texture_s3tc", "WEBGL_compressed_texture_s3tc_srgb", "WEBGL_debug_renderer_info", "WEBGL_debug_shaders", "WEBGL_lose_context", "WEBGL_multi_draw", "WEBGL_polygon_mode" ];
+ // .getSupportedExtensions() can return null if context is lost, so coerce to empty array.
+ return (ctx.getSupportedExtensions() || []).filter(ext => supportedExtensions.includes(ext));
+};
+
+var registerPreMainLoop = f => {
+ // Does nothing unless $MainLoop is included/used.
+ typeof MainLoop != "undefined" && MainLoop.preMainLoop.push(f);
+};
+
+var GL = {
+ counter: 1,
+ buffers: [],
+ mappedBuffers: {},
+ programs: [],
+ framebuffers: [],
+ renderbuffers: [],
+ textures: [],
+ shaders: [],
+ vaos: [],
+ contexts: [],
+ offscreenCanvases: {},
+ queries: [],
+ samplers: [],
+ transformFeedbacks: [],
+ syncs: [],
+ byteSizeByTypeRoot: 5120,
+ byteSizeByType: [ 1, 1, 2, 2, 4, 4, 4, 2, 3, 4, 8 ],
+ stringCache: {},
+ stringiCache: {},
+ unpackAlignment: 4,
+ unpackRowLength: 0,
+ recordError: errorCode => {
+ if (!GL.lastError) {
+ GL.lastError = errorCode;
+ }
+ },
+ getNewId: table => {
+ var ret = GL.counter++;
+ for (var i = table.length; i < ret; i++) {
+ table[i] = null;
+ }
+ // Skip over any non-null elements that might have been created by
+ // glBindBuffer.
+ while (table[ret]) {
+ ret = GL.counter++;
+ }
+ return ret;
+ },
+ genObject: (n, buffers, createFunction, objectTable) => {
+ for (var i = 0; i < n; i++) {
+ var buffer = GLctx[createFunction]();
+ var id = buffer && GL.getNewId(objectTable);
+ if (buffer) {
+ buffer.name = id;
+ objectTable[id] = buffer;
+ } else {
+ GL.recordError(1282);
+ }
+ HEAP32[(((buffers) + (i * 4)) >>> 2) >>> 0] = id;
+ }
+ },
+ MAX_TEMP_BUFFER_SIZE: 2097152,
+ numTempVertexBuffersPerSize: 64,
+ log2ceilLookup: i => 32 - Math.clz32(i === 0 ? 0 : i - 1),
+ generateTempBuffers: (quads, context) => {
+ var largestIndex = GL.log2ceilLookup(GL.MAX_TEMP_BUFFER_SIZE);
+ context.tempVertexBufferCounters1 = [];
+ context.tempVertexBufferCounters2 = [];
+ context.tempVertexBufferCounters1.length = context.tempVertexBufferCounters2.length = largestIndex + 1;
+ context.tempVertexBuffers1 = [];
+ context.tempVertexBuffers2 = [];
+ context.tempVertexBuffers1.length = context.tempVertexBuffers2.length = largestIndex + 1;
+ context.tempIndexBuffers = [];
+ context.tempIndexBuffers.length = largestIndex + 1;
+ for (var i = 0; i <= largestIndex; ++i) {
+ context.tempIndexBuffers[i] = null;
+ // Created on-demand
+ context.tempVertexBufferCounters1[i] = context.tempVertexBufferCounters2[i] = 0;
+ var ringbufferLength = GL.numTempVertexBuffersPerSize;
+ context.tempVertexBuffers1[i] = [];
+ context.tempVertexBuffers2[i] = [];
+ var ringbuffer1 = context.tempVertexBuffers1[i];
+ var ringbuffer2 = context.tempVertexBuffers2[i];
+ ringbuffer1.length = ringbuffer2.length = ringbufferLength;
+ for (var j = 0; j < ringbufferLength; ++j) {
+ ringbuffer1[j] = ringbuffer2[j] = null;
+ }
+ }
+ if (quads) {
+ // GL_QUAD indexes can be precalculated
+ context.tempQuadIndexBuffer = GLctx.createBuffer();
+ context.GLctx.bindBuffer(34963, context.tempQuadIndexBuffer);
+ var numIndexes = GL.MAX_TEMP_BUFFER_SIZE >> 1;
+ var quadIndexes = new Uint16Array(numIndexes);
+ var i = 0, v = 0;
+ while (1) {
+ quadIndexes[i++] = v;
+ if (i >= numIndexes) break;
+ quadIndexes[i++] = v + 1;
+ if (i >= numIndexes) break;
+ quadIndexes[i++] = v + 2;
+ if (i >= numIndexes) break;
+ quadIndexes[i++] = v;
+ if (i >= numIndexes) break;
+ quadIndexes[i++] = v + 2;
+ if (i >= numIndexes) break;
+ quadIndexes[i++] = v + 3;
+ if (i >= numIndexes) break;
+ v += 4;
+ }
+ context.GLctx.bufferData(34963, quadIndexes, 35044);
+ context.GLctx.bindBuffer(34963, null);
+ }
+ },
+ getTempVertexBuffer: sizeBytes => {
+ var idx = GL.log2ceilLookup(sizeBytes);
+ var ringbuffer = GL.currentContext.tempVertexBuffers1[idx];
+ var nextFreeBufferIndex = GL.currentContext.tempVertexBufferCounters1[idx];
+ GL.currentContext.tempVertexBufferCounters1[idx] = (GL.currentContext.tempVertexBufferCounters1[idx] + 1) & (GL.numTempVertexBuffersPerSize - 1);
+ var vbo = ringbuffer[nextFreeBufferIndex];
+ if (vbo) {
+ return vbo;
+ }
+ var prevVBO = GLctx.getParameter(34964);
+ ringbuffer[nextFreeBufferIndex] = GLctx.createBuffer();
+ GLctx.bindBuffer(34962, ringbuffer[nextFreeBufferIndex]);
+ GLctx.bufferData(34962, 1 << idx, 35048);
+ GLctx.bindBuffer(34962, prevVBO);
+ return ringbuffer[nextFreeBufferIndex];
+ },
+ getTempIndexBuffer: sizeBytes => {
+ var idx = GL.log2ceilLookup(sizeBytes);
+ var ibo = GL.currentContext.tempIndexBuffers[idx];
+ if (ibo) {
+ return ibo;
+ }
+ var prevIBO = GLctx.getParameter(34965);
+ GL.currentContext.tempIndexBuffers[idx] = GLctx.createBuffer();
+ GLctx.bindBuffer(34963, GL.currentContext.tempIndexBuffers[idx]);
+ GLctx.bufferData(34963, 1 << idx, 35048);
+ GLctx.bindBuffer(34963, prevIBO);
+ return GL.currentContext.tempIndexBuffers[idx];
+ },
+ newRenderingFrameStarted: () => {
+ if (!GL.currentContext) {
+ return;
+ }
+ var vb = GL.currentContext.tempVertexBuffers1;
+ GL.currentContext.tempVertexBuffers1 = GL.currentContext.tempVertexBuffers2;
+ GL.currentContext.tempVertexBuffers2 = vb;
+ vb = GL.currentContext.tempVertexBufferCounters1;
+ GL.currentContext.tempVertexBufferCounters1 = GL.currentContext.tempVertexBufferCounters2;
+ GL.currentContext.tempVertexBufferCounters2 = vb;
+ var largestIndex = GL.log2ceilLookup(GL.MAX_TEMP_BUFFER_SIZE);
+ for (var i = 0; i <= largestIndex; ++i) {
+ GL.currentContext.tempVertexBufferCounters1[i] = 0;
+ }
+ },
+ getSource: (shader, count, string, length) => {
+ var source = "";
+ for (var i = 0; i < count; ++i) {
+ var len = length ? HEAPU32[(((length) + (i * 4)) >>> 2) >>> 0] : undefined;
+ source += UTF8ToString(HEAPU32[(((string) + (i * 4)) >>> 2) >>> 0], len);
+ }
+ return source;
+ },
+ calcBufLength: (size, type, stride, count) => {
+ if (stride > 0) {
+ return count * stride;
+ }
+ var typeSize = GL.byteSizeByType[type - GL.byteSizeByTypeRoot];
+ return size * typeSize * count;
+ },
+ usedTempBuffers: [],
+ preDrawHandleClientVertexAttribBindings: count => {
+ GL.resetBufferBinding = false;
+ // TODO: initial pass to detect ranges we need to upload, might not need
+ // an upload per attrib
+ for (var i = 0; i < GL.currentContext.maxVertexAttribs; ++i) {
+ var cb = GL.currentContext.clientBuffers[i];
+ if (!cb.clientside || !cb.enabled) continue;
+ GL.resetBufferBinding = true;
+ var size = GL.calcBufLength(cb.size, cb.type, cb.stride, count);
+ var buf = GL.getTempVertexBuffer(size);
+ GLctx.bindBuffer(34962, buf);
+ GLctx.bufferSubData(34962, 0, HEAPU8.subarray(cb.ptr >>> 0, cb.ptr + size >>> 0));
+ cb.vertexAttribPointerAdaptor.call(GLctx, i, cb.size, cb.type, cb.normalized, cb.stride, 0);
+ }
+ },
+ postDrawHandleClientVertexAttribBindings: () => {
+ if (GL.resetBufferBinding) {
+ GLctx.bindBuffer(34962, GL.buffers[GLctx.currentArrayBufferBinding]);
+ }
+ },
+ createContext: (/** @type {HTMLCanvasElement} */ canvas, webGLContextAttributes) => {
+ // BUG: Workaround Safari WebGL issue: After successfully acquiring WebGL
+ // context on a canvas, calling .getContext() will always return that
+ // context independent of which 'webgl' or 'webgl2'
+ // context version was passed. See:
+ // https://webkit.org/b/222758
+ // and:
+ // https://github.com/emscripten-core/emscripten/issues/13295.
+ // TODO: Once the bug is fixed and shipped in Safari, adjust the Safari
+ // version field in above check.
+ if (!canvas.getContextSafariWebGL2Fixed) {
+ canvas.getContextSafariWebGL2Fixed = canvas.getContext;
+ /** @type {function(this:HTMLCanvasElement, string, (Object|null)=): (Object|null)} */ function fixedGetContext(ver, attrs) {
+ var gl = canvas.getContextSafariWebGL2Fixed(ver, attrs);
+ return ((ver == "webgl") == (gl instanceof WebGLRenderingContext)) ? gl : null;
+ }
+ canvas.getContext = fixedGetContext;
+ }
+ var ctx = (webGLContextAttributes.majorVersion > 1) ? canvas.getContext("webgl2", webGLContextAttributes) : canvas.getContext("webgl", webGLContextAttributes);
+ if (!ctx) return 0;
+ var handle = GL.registerContext(ctx, webGLContextAttributes);
+ return handle;
+ },
+ registerContext: (ctx, webGLContextAttributes) => {
+ // without pthreads a context is just an integer ID
+ var handle = GL.getNewId(GL.contexts);
+ var context = {
+ handle,
+ attributes: webGLContextAttributes,
+ version: webGLContextAttributes.majorVersion,
+ GLctx: ctx
+ };
+ // Store the created context object so that we can access the context
+ // given a canvas without having to pass the parameters again.
+ if (ctx.canvas) ctx.canvas.GLctxObject = context;
+ GL.contexts[handle] = context;
+ if (typeof webGLContextAttributes.enableExtensionsByDefault == "undefined" || webGLContextAttributes.enableExtensionsByDefault) {
+ GL.initExtensions(context);
+ }
+ context.maxVertexAttribs = context.GLctx.getParameter(34921);
+ context.clientBuffers = [];
+ for (var i = 0; i < context.maxVertexAttribs; i++) {
+ context.clientBuffers[i] = {
+ enabled: false,
+ clientside: false,
+ size: 0,
+ type: 0,
+ normalized: 0,
+ stride: 0,
+ ptr: 0,
+ vertexAttribPointerAdaptor: null
+ };
+ }
+ GL.generateTempBuffers(false, context);
+ return handle;
+ },
+ makeContextCurrent: contextHandle => {
+ // Active Emscripten GL layer context object.
+ GL.currentContext = GL.contexts[contextHandle];
+ // Active WebGL context object.
+ Module["ctx"] = GLctx = GL.currentContext?.GLctx;
+ return !(contextHandle && !GLctx);
+ },
+ getContext: contextHandle => GL.contexts[contextHandle],
+ deleteContext: contextHandle => {
+ if (GL.currentContext === GL.contexts[contextHandle]) {
+ GL.currentContext = null;
+ }
+ if (typeof JSEvents == "object") {
+ // Release all JS event handlers on the DOM element that the GL context is
+ // associated with since the context is now deleted.
+ JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas);
+ }
+ // Make sure the canvas object no longer refers to the context object so
+ // there are no GC surprises.
+ if (GL.contexts[contextHandle]?.GLctx.canvas) {
+ GL.contexts[contextHandle].GLctx.canvas.GLctxObject = undefined;
+ }
+ GL.contexts[contextHandle] = null;
+ },
+ initExtensions: context => {
+ // If this function is called without a specific context object, init the
+ // extensions of the currently active context.
+ context ||= GL.currentContext;
+ if (context.initExtensionsDone) return;
+ context.initExtensionsDone = true;
+ var GLctx = context.GLctx;
+ // Detect the presence of a few extensions manually, since the GL interop
+ // layer itself will need to know if they exist.
+ // Extensions that are available in both WebGL 1 and WebGL 2
+ webgl_enable_WEBGL_multi_draw(GLctx);
+ webgl_enable_EXT_polygon_offset_clamp(GLctx);
+ webgl_enable_EXT_clip_control(GLctx);
+ webgl_enable_WEBGL_polygon_mode(GLctx);
+ // Extensions that are only available in WebGL 1 (the calls will be no-ops
+ // if called on a WebGL 2 context active)
+ webgl_enable_ANGLE_instanced_arrays(GLctx);
+ webgl_enable_OES_vertex_array_object(GLctx);
+ webgl_enable_WEBGL_draw_buffers(GLctx);
+ // Extensions that are available from WebGL >= 2 (no-op if called on a WebGL 1 context active)
+ webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(GLctx);
+ webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance(GLctx);
+ // On WebGL 2, EXT_disjoint_timer_query is replaced with an alternative
+ // that's based on core APIs, and exposes only the queryCounterEXT()
+ // entrypoint.
+ if (context.version >= 2) {
+ GLctx.disjointTimerQueryExt = GLctx.getExtension("EXT_disjoint_timer_query_webgl2");
+ }
+ // However, Firefox exposes the WebGL 1 version on WebGL 2 as well and
+ // thus we look for the WebGL 1 version again if the WebGL 2 version
+ // isn't present. https://bugzil.la/1328882
+ if (context.version < 2 || !GLctx.disjointTimerQueryExt) {
+ GLctx.disjointTimerQueryExt = GLctx.getExtension("EXT_disjoint_timer_query");
+ }
+ for (var ext of getEmscriptenSupportedExtensions(GLctx)) {
+ // WEBGL_lose_context, WEBGL_debug_renderer_info and WEBGL_debug_shaders
+ // are not enabled by default.
+ if (!ext.includes("lose_context") && !ext.includes("debug")) {
+ // Call .getExtension() to enable that extension permanently.
+ GLctx.getExtension(ext);
+ }
+ }
+ }
+};
+
+var webglPowerPreferences = [ "default", "low-power", "high-performance" ];
+
+/** @type {Object} */ var specialHTMLTargets = [ 0, globalThis.document ?? 0, globalThis.window ?? 0 ];
+
+var findEventTarget = target => {
+ // The sensible "default" target varies between events, but use window as the default
+ // since DOM events mostly can default to that. Specific callback registrations
+ // override their own defaults.
+ if (!target) return window;
+ if (typeof target == "number") target = specialHTMLTargets[target] || UTF8ToString(target);
+ if (target === "#window") return window; else if (target === "#document") return document; else if (target === "#screen") return screen; else if (target === "#canvas") return Module["canvas"]; else if (typeof target == "string") return globalThis.document?.getElementById(target);
+ return target;
+};
+
+var findCanvasEventTarget = target => {
+ if (typeof target == "number") target = UTF8ToString(target);
+ if (!target || target === "#canvas") {
+ if (typeof GL != "undefined" && GL.offscreenCanvases["canvas"]) return GL.offscreenCanvases["canvas"];
+ // TODO: Remove this line, target '#canvas' should refer only to Module['canvas'], not to GL.offscreenCanvases['canvas'] - but need stricter tests to be able to remove this line.
+ return Module["canvas"];
+ }
+ if (typeof GL != "undefined" && GL.offscreenCanvases[target]) return GL.offscreenCanvases[target];
+ return findEventTarget(target);
+};
+
+function _emscripten_webgl_do_create_context(target, attributes) {
+ target >>>= 0;
+ attributes >>>= 0;
+ var attr32 = ((attributes) >>> 2);
+ var powerPreference = HEAP32[attr32 + (8 >> 2) >>> 0];
+ var contextAttributes = {
+ "alpha": !!HEAP8[attributes + 0 >>> 0],
+ "depth": !!HEAP8[attributes + 1 >>> 0],
+ "stencil": !!HEAP8[attributes + 2 >>> 0],
+ "antialias": !!HEAP8[attributes + 3 >>> 0],
+ "premultipliedAlpha": !!HEAP8[attributes + 4 >>> 0],
+ "preserveDrawingBuffer": !!HEAP8[attributes + 5 >>> 0],
+ "powerPreference": webglPowerPreferences[powerPreference],
+ "failIfMajorPerformanceCaveat": !!HEAP8[attributes + 12 >>> 0],
+ // The following are not predefined WebGL context attributes in the WebGL specification, so the property names can be minified by Closure.
+ majorVersion: HEAP32[attr32 + (16 >> 2) >>> 0],
+ minorVersion: HEAP32[attr32 + (20 >> 2) >>> 0],
+ enableExtensionsByDefault: HEAP8[attributes + 24 >>> 0],
+ explicitSwapControl: HEAP8[attributes + 25 >>> 0],
+ proxyContextToMainThread: HEAP32[attr32 + (28 >> 2) >>> 0],
+ renderViaOffscreenBackBuffer: HEAP8[attributes + 32 >>> 0]
+ };
+ var canvas = findCanvasEventTarget(target);
+ if (!canvas) {
+ return 0;
+ }
+ if (contextAttributes.explicitSwapControl) {
+ return 0;
+ }
+ var contextHandle = GL.createContext(canvas, contextAttributes);
+ return contextHandle;
+}
+
+var _emscripten_webgl_create_context = _emscripten_webgl_do_create_context;
+
+function _emscripten_webgl_destroy_context(contextHandle) {
+ contextHandle >>>= 0;
+ if (GL.currentContext == contextHandle) GL.currentContext = 0;
+ GL.deleteContext(contextHandle);
+}
+
+function _emscripten_webgl_get_context_attributes(c, a) {
+ c >>>= 0;
+ a >>>= 0;
+ if (!a) return -5;
+ c = GL.contexts[c];
+ if (!c) return -3;
+ var t = c.GLctx?.getContextAttributes();
+ if (!t) return -3;
+ HEAP8[a >>> 0] = t.alpha;
+ HEAP8[(a) + (1) >>> 0] = t.depth;
+ HEAP8[(a) + (2) >>> 0] = t.stencil;
+ HEAP8[(a) + (3) >>> 0] = t.antialias;
+ HEAP8[(a) + (4) >>> 0] = t.premultipliedAlpha;
+ HEAP8[(a) + (5) >>> 0] = t.preserveDrawingBuffer;
+ var power = t["powerPreference"] && webglPowerPreferences.indexOf(t["powerPreference"]);
+ HEAP32[(((a) + (8)) >>> 2) >>> 0] = power;
+ HEAP8[(a) + (12) >>> 0] = t.failIfMajorPerformanceCaveat;
+ HEAP32[(((a) + (16)) >>> 2) >>> 0] = c.version;
+ HEAP32[(((a) + (20)) >>> 2) >>> 0] = 0;
+ HEAP8[(a) + (24) >>> 0] = c.attributes.enableExtensionsByDefault;
+ return 0;
+}
+
+function _emscripten_webgl_do_get_current_context() {
+ return GL.currentContext ? GL.currentContext.handle : 0;
+}
+
+var _emscripten_webgl_get_current_context = _emscripten_webgl_do_get_current_context;
+
+function _emscripten_webgl_make_context_current(contextHandle) {
+ contextHandle >>>= 0;
+ var success = GL.makeContextCurrent(contextHandle);
+ return success ? 0 : -5;
+}
+
+var stackAlloc = sz => __emscripten_stack_alloc(sz);
+
+var stringToUTF8OnStack = str => {
+ var size = lengthBytesUTF8(str) + 1;
+ var ret = stackAlloc(size);
+ stringToUTF8(str, ret, size);
+ return ret;
+};
+
+var writeI53ToI64 = (ptr, num) => {
+ HEAPU32[((ptr) >>> 2) >>> 0] = num;
+ var lower = HEAPU32[((ptr) >>> 2) >>> 0];
+ HEAPU32[(((ptr) + (4)) >>> 2) >>> 0] = (num - lower) / 4294967296;
+};
+
+var readI53FromI64 = ptr => HEAPU32[((ptr) >>> 2) >>> 0] + HEAP32[(((ptr) + (4)) >>> 2) >>> 0] * 4294967296;
+
+var WebGPU = {
+ Internals: {
+ jsObjects: [],
+ jsObjectInsert: (ptr, jsObject) => {
+ ptr >>>= 0;
+ WebGPU.Internals.jsObjects[ptr] = jsObject;
+ },
+ bufferOnUnmaps: [],
+ futures: [],
+ futureInsert: (futureId, promise) => {
+ WebGPU.Internals.futures[futureId] = new Promise(resolve => promise.finally(() => resolve(futureId)));
+ }
+ },
+ getJsObject: ptr => {
+ if (!ptr) return undefined;
+ ptr >>>= 0;
+ return WebGPU.Internals.jsObjects[ptr];
+ },
+ importJsAdapter: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateAdapter(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsBindGroup: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateBindGroup(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsBindGroupLayout: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateBindGroupLayout(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsBuffer: (buffer, parentPtr = 0) => {
+ // At the moment, we do not allow importing pending buffers.
+ assert(buffer.mapState === "unmapped");
+ var bufferPtr = _emwgpuImportBuffer(parentPtr);
+ WebGPU.Internals.jsObjectInsert(bufferPtr, buffer);
+ return bufferPtr;
+ },
+ importJsCommandBuffer: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateCommandBuffer(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsCommandEncoder: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateCommandEncoder(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsComputePassEncoder: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateComputePassEncoder(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsComputePipeline: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateComputePipeline(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsDevice: (device, parentPtr = 0) => {
+ var queuePtr = _emwgpuCreateQueue(parentPtr);
+ var devicePtr = _emwgpuCreateDevice(parentPtr, queuePtr);
+ WebGPU.Internals.jsObjectInsert(queuePtr, device.queue);
+ WebGPU.Internals.jsObjectInsert(devicePtr, device);
+ return devicePtr;
+ },
+ importJsExternalTexture: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateExternalTexture(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsPipelineLayout: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreatePipelineLayout(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsQuerySet: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateQuerySet(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsQueue: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateQueue(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsRenderBundle: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateRenderBundle(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsRenderBundleEncoder: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateRenderBundleEncoder(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsRenderPassEncoder: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateRenderPassEncoder(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsRenderPipeline: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateRenderPipeline(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsSampler: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateSampler(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsShaderModule: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateShaderModule(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsSurface: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateSurface(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsTexture: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateTexture(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsTextureView: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateTextureView(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ errorCallback: (callback, type, message, userdata) => {
+ var sp = stackSave();
+ var messagePtr = stringToUTF8OnStack(message);
+ ((a1, a2, a3) => dynCall_viii(callback, a1, a2, a3))(type, messagePtr, userdata);
+ stackRestore(sp);
+ },
+ iterateExtensions: (root, handlers) => {
+ for (var ptr = HEAPU32[((root) >>> 2) >>> 0]; ptr; ptr = HEAPU32[((ptr) >>> 2) >>> 0]) {
+ var sType = HEAP32[(((ptr) + (4)) >>> 2) >>> 0];
+ // This will crash if there's no handler indicating either a bogus
+ // sType, or one we haven't implemented yet.
+ var handler = handlers[sType](ptr);
+ }
+ },
+ setStringView: (ptr, data, length) => {
+ HEAPU32[((ptr) >>> 2) >>> 0] = data;
+ HEAPU32[(((ptr) + (4)) >>> 2) >>> 0] = length;
+ },
+ makeStringFromStringView: stringViewPtr => {
+ var ptr = HEAPU32[((stringViewPtr) >>> 2) >>> 0];
+ var length = HEAPU32[(((stringViewPtr) + (4)) >>> 2) >>> 0];
+ // UTF8ToString stops at the first null terminator character in the
+ // string regardless of the length.
+ return UTF8ToString(ptr, length);
+ },
+ makeStringFromOptionalStringView: stringViewPtr => {
+ var ptr = HEAPU32[((stringViewPtr) >>> 2) >>> 0];
+ var length = HEAPU32[(((stringViewPtr) + (4)) >>> 2) >>> 0];
+ // If we don't have a valid string pointer, just return undefined when
+ // optional.
+ if (!ptr) {
+ if (length === 0) {
+ return "";
+ }
+ return undefined;
+ }
+ // UTF8ToString stops at the first null terminator character in the
+ // string regardless of the length.
+ return UTF8ToString(ptr, length);
+ },
+ makeColor: ptr => ({
+ "r": HEAPF64[((ptr) >>> 3) >>> 0],
+ "g": HEAPF64[(((ptr) + (8)) >>> 3) >>> 0],
+ "b": HEAPF64[(((ptr) + (16)) >>> 3) >>> 0],
+ "a": HEAPF64[(((ptr) + (24)) >>> 3) >>> 0]
+ }),
+ makeExtent3D: ptr => ({
+ "width": HEAPU32[((ptr) >>> 2) >>> 0],
+ "height": HEAPU32[(((ptr) + (4)) >>> 2) >>> 0],
+ "depthOrArrayLayers": HEAPU32[(((ptr) + (8)) >>> 2) >>> 0]
+ }),
+ makeOrigin3D: ptr => ({
+ "x": HEAPU32[((ptr) >>> 2) >>> 0],
+ "y": HEAPU32[(((ptr) + (4)) >>> 2) >>> 0],
+ "z": HEAPU32[(((ptr) + (8)) >>> 2) >>> 0]
+ }),
+ makeTexelCopyTextureInfo: ptr => ({
+ "texture": WebGPU.getJsObject(HEAPU32[((ptr) >>> 2) >>> 0]),
+ "mipLevel": HEAPU32[(((ptr) + (4)) >>> 2) >>> 0],
+ "origin": WebGPU.makeOrigin3D(ptr + 8),
+ "aspect": WebGPU.TextureAspect[HEAP32[(((ptr) + (20)) >>> 2) >>> 0]]
+ }),
+ makeTexelCopyBufferLayout: ptr => {
+ var bytesPerRow = HEAPU32[(((ptr) + (8)) >>> 2) >>> 0];
+ var rowsPerImage = HEAPU32[(((ptr) + (12)) >>> 2) >>> 0];
+ return {
+ "offset": readI53FromI64(ptr),
+ "bytesPerRow": bytesPerRow === 4294967295 ? undefined : bytesPerRow,
+ "rowsPerImage": rowsPerImage === 4294967295 ? undefined : rowsPerImage
+ };
+ },
+ makeTexelCopyBufferInfo: ptr => {
+ var layoutPtr = ptr + 0;
+ var bufferCopyView = WebGPU.makeTexelCopyBufferLayout(layoutPtr);
+ bufferCopyView["buffer"] = WebGPU.getJsObject(HEAPU32[(((ptr) + (16)) >>> 2) >>> 0]);
+ return bufferCopyView;
+ },
+ makePassTimestampWrites: ptr => {
+ if (ptr === 0) return undefined;
+ return {
+ "querySet": WebGPU.getJsObject(HEAPU32[(((ptr) + (4)) >>> 2) >>> 0]),
+ "beginningOfPassWriteIndex": HEAPU32[(((ptr) + (8)) >>> 2) >>> 0],
+ "endOfPassWriteIndex": HEAPU32[(((ptr) + (12)) >>> 2) >>> 0]
+ };
+ },
+ makePipelineConstants: (constantCount, constantsPtr) => {
+ if (!constantCount) return;
+ var constants = {};
+ for (var i = 0; i < constantCount; ++i) {
+ var entryPtr = constantsPtr + 24 * i;
+ var key = WebGPU.makeStringFromStringView(entryPtr + 4);
+ constants[key] = HEAPF64[(((entryPtr) + (16)) >>> 3) >>> 0];
+ }
+ return constants;
+ },
+ makePipelineLayout: layoutPtr => {
+ if (!layoutPtr) return "auto";
+ return WebGPU.getJsObject(layoutPtr);
+ },
+ makeComputeState: ptr => {
+ if (!ptr) return undefined;
+ var desc = {
+ "module": WebGPU.getJsObject(HEAPU32[(((ptr) + (4)) >>> 2) >>> 0]),
+ "constants": WebGPU.makePipelineConstants(HEAPU32[(((ptr) + (16)) >>> 2) >>> 0], HEAPU32[(((ptr) + (20)) >>> 2) >>> 0]),
+ "entryPoint": WebGPU.makeStringFromOptionalStringView(ptr + 8)
+ };
+ return desc;
+ },
+ makeComputePipelineDesc: descriptor => {
+ var desc = {
+ "label": WebGPU.makeStringFromOptionalStringView(descriptor + 4),
+ "layout": WebGPU.makePipelineLayout(HEAPU32[(((descriptor) + (12)) >>> 2) >>> 0]),
+ "compute": WebGPU.makeComputeState(descriptor + 16)
+ };
+ return desc;
+ },
+ makeRenderPipelineDesc: descriptor => {
+ function makePrimitiveState(psPtr) {
+ if (!psPtr) return undefined;
+ return {
+ "topology": WebGPU.PrimitiveTopology[HEAP32[(((psPtr) + (4)) >>> 2) >>> 0]],
+ "stripIndexFormat": WebGPU.IndexFormat[HEAP32[(((psPtr) + (8)) >>> 2) >>> 0]],
+ "frontFace": WebGPU.FrontFace[HEAP32[(((psPtr) + (12)) >>> 2) >>> 0]],
+ "cullMode": WebGPU.CullMode[HEAP32[(((psPtr) + (16)) >>> 2) >>> 0]],
+ "unclippedDepth": !!(HEAPU32[(((psPtr) + (20)) >>> 2) >>> 0])
+ };
+ }
+ function makeBlendComponent(bdPtr) {
+ if (!bdPtr) return undefined;
+ return {
+ "operation": WebGPU.BlendOperation[HEAP32[((bdPtr) >>> 2) >>> 0]],
+ "srcFactor": WebGPU.BlendFactor[HEAP32[(((bdPtr) + (4)) >>> 2) >>> 0]],
+ "dstFactor": WebGPU.BlendFactor[HEAP32[(((bdPtr) + (8)) >>> 2) >>> 0]]
+ };
+ }
+ function makeBlendState(bsPtr) {
+ if (!bsPtr) return undefined;
+ return {
+ "alpha": makeBlendComponent(bsPtr + 12),
+ "color": makeBlendComponent(bsPtr + 0)
+ };
+ }
+ function makeColorState(csPtr) {
+ var format = WebGPU.TextureFormat[HEAP32[(((csPtr) + (4)) >>> 2) >>> 0]];
+ return format ? {
+ "format": format,
+ "blend": makeBlendState(HEAPU32[(((csPtr) + (8)) >>> 2) >>> 0]),
+ "writeMask": HEAPU32[(((csPtr) + (16)) >>> 2) >>> 0]
+ } : undefined;
+ }
+ function makeColorStates(count, csArrayPtr) {
+ var states = [];
+ for (var i = 0; i < count; ++i) {
+ states.push(makeColorState(csArrayPtr + 24 * i));
+ }
+ return states;
+ }
+ function makeStencilStateFace(ssfPtr) {
+ return {
+ "compare": WebGPU.CompareFunction[HEAP32[((ssfPtr) >>> 2) >>> 0]],
+ "failOp": WebGPU.StencilOperation[HEAP32[(((ssfPtr) + (4)) >>> 2) >>> 0]],
+ "depthFailOp": WebGPU.StencilOperation[HEAP32[(((ssfPtr) + (8)) >>> 2) >>> 0]],
+ "passOp": WebGPU.StencilOperation[HEAP32[(((ssfPtr) + (12)) >>> 2) >>> 0]]
+ };
+ }
+ function makeDepthStencilState(dssPtr) {
+ if (!dssPtr) return undefined;
+ return {
+ "format": WebGPU.TextureFormat[HEAP32[(((dssPtr) + (4)) >>> 2) >>> 0]],
+ "depthWriteEnabled": !!(HEAPU32[(((dssPtr) + (8)) >>> 2) >>> 0]),
+ "depthCompare": WebGPU.CompareFunction[HEAP32[(((dssPtr) + (12)) >>> 2) >>> 0]],
+ "stencilFront": makeStencilStateFace(dssPtr + 16),
+ "stencilBack": makeStencilStateFace(dssPtr + 32),
+ "stencilReadMask": HEAPU32[(((dssPtr) + (48)) >>> 2) >>> 0],
+ "stencilWriteMask": HEAPU32[(((dssPtr) + (52)) >>> 2) >>> 0],
+ "depthBias": HEAP32[(((dssPtr) + (56)) >>> 2) >>> 0],
+ "depthBiasSlopeScale": HEAPF32[(((dssPtr) + (60)) >>> 2) >>> 0],
+ "depthBiasClamp": HEAPF32[(((dssPtr) + (64)) >>> 2) >>> 0]
+ };
+ }
+ function makeVertexAttribute(vaPtr) {
+ return {
+ "format": WebGPU.VertexFormat[HEAP32[(((vaPtr) + (4)) >>> 2) >>> 0]],
+ "offset": readI53FromI64((vaPtr) + (8)),
+ "shaderLocation": HEAPU32[(((vaPtr) + (16)) >>> 2) >>> 0]
+ };
+ }
+ function makeVertexAttributes(count, vaArrayPtr) {
+ var vas = [];
+ for (var i = 0; i < count; ++i) {
+ vas.push(makeVertexAttribute(vaArrayPtr + i * 24));
+ }
+ return vas;
+ }
+ function makeVertexBuffer(vbPtr) {
+ if (!vbPtr) return undefined;
+ var stepMode = WebGPU.VertexStepMode[HEAP32[(((vbPtr) + (4)) >>> 2) >>> 0]];
+ var attributeCount = HEAPU32[(((vbPtr) + (16)) >>> 2) >>> 0];
+ if (!stepMode && !attributeCount) {
+ return null;
+ }
+ return {
+ "arrayStride": readI53FromI64((vbPtr) + (8)),
+ "stepMode": stepMode,
+ "attributes": makeVertexAttributes(attributeCount, HEAPU32[(((vbPtr) + (20)) >>> 2) >>> 0])
+ };
+ }
+ function makeVertexBuffers(count, vbArrayPtr) {
+ if (!count) return undefined;
+ var vbs = [];
+ for (var i = 0; i < count; ++i) {
+ vbs.push(makeVertexBuffer(vbArrayPtr + i * 24));
+ }
+ return vbs;
+ }
+ function makeVertexState(viPtr) {
+ if (!viPtr) return undefined;
+ var desc = {
+ "module": WebGPU.getJsObject(HEAPU32[(((viPtr) + (4)) >>> 2) >>> 0]),
+ "constants": WebGPU.makePipelineConstants(HEAPU32[(((viPtr) + (16)) >>> 2) >>> 0], HEAPU32[(((viPtr) + (20)) >>> 2) >>> 0]),
+ "buffers": makeVertexBuffers(HEAPU32[(((viPtr) + (24)) >>> 2) >>> 0], HEAPU32[(((viPtr) + (28)) >>> 2) >>> 0]),
+ "entryPoint": WebGPU.makeStringFromOptionalStringView(viPtr + 8)
+ };
+ return desc;
+ }
+ function makeMultisampleState(msPtr) {
+ if (!msPtr) return undefined;
+ return {
+ "count": HEAPU32[(((msPtr) + (4)) >>> 2) >>> 0],
+ "mask": HEAPU32[(((msPtr) + (8)) >>> 2) >>> 0],
+ "alphaToCoverageEnabled": !!(HEAPU32[(((msPtr) + (12)) >>> 2) >>> 0])
+ };
+ }
+ function makeFragmentState(fsPtr) {
+ if (!fsPtr) return undefined;
+ var desc = {
+ "module": WebGPU.getJsObject(HEAPU32[(((fsPtr) + (4)) >>> 2) >>> 0]),
+ "constants": WebGPU.makePipelineConstants(HEAPU32[(((fsPtr) + (16)) >>> 2) >>> 0], HEAPU32[(((fsPtr) + (20)) >>> 2) >>> 0]),
+ "targets": makeColorStates(HEAPU32[(((fsPtr) + (24)) >>> 2) >>> 0], HEAPU32[(((fsPtr) + (28)) >>> 2) >>> 0]),
+ "entryPoint": WebGPU.makeStringFromOptionalStringView(fsPtr + 8)
+ };
+ return desc;
+ }
+ var desc = {
+ "label": WebGPU.makeStringFromOptionalStringView(descriptor + 4),
+ "layout": WebGPU.makePipelineLayout(HEAPU32[(((descriptor) + (12)) >>> 2) >>> 0]),
+ "vertex": makeVertexState(descriptor + 16),
+ "primitive": makePrimitiveState(descriptor + 48),
+ "depthStencil": makeDepthStencilState(HEAPU32[(((descriptor) + (72)) >>> 2) >>> 0]),
+ "multisample": makeMultisampleState(descriptor + 76),
+ "fragment": makeFragmentState(HEAPU32[(((descriptor) + (92)) >>> 2) >>> 0])
+ };
+ return desc;
+ },
+ fillLimitStruct: (limits, limitsOutPtr) => {
+ var nextInChainPtr = HEAPU32[((limitsOutPtr) >>> 2) >>> 0];
+ function setLimitValueU32(name, basePtr, limitOffset, fallbackValue = 0) {
+ var limitValue = limits[name] ?? fallbackValue;
+ HEAPU32[(((basePtr) + (limitOffset)) >>> 2) >>> 0] = limitValue;
+ }
+ function setLimitValueU64(name, basePtr, limitOffset, fallbackValue = 0) {
+ var limitValue = limits[name] ?? fallbackValue;
+ // Limits are integer-valued JS `Number`s, so they fit in 'i53'.
+ writeI53ToI64((basePtr) + (limitOffset), limitValue);
+ }
+ setLimitValueU32("maxTextureDimension1D", limitsOutPtr, 4);
+ setLimitValueU32("maxTextureDimension2D", limitsOutPtr, 8);
+ setLimitValueU32("maxTextureDimension3D", limitsOutPtr, 12);
+ setLimitValueU32("maxTextureArrayLayers", limitsOutPtr, 16);
+ setLimitValueU32("maxBindGroups", limitsOutPtr, 20);
+ setLimitValueU32("maxBindGroupsPlusVertexBuffers", limitsOutPtr, 24);
+ setLimitValueU32("maxBindingsPerBindGroup", limitsOutPtr, 28);
+ setLimitValueU32("maxDynamicUniformBuffersPerPipelineLayout", limitsOutPtr, 32);
+ setLimitValueU32("maxDynamicStorageBuffersPerPipelineLayout", limitsOutPtr, 36);
+ setLimitValueU32("maxSampledTexturesPerShaderStage", limitsOutPtr, 40);
+ setLimitValueU32("maxSamplersPerShaderStage", limitsOutPtr, 44);
+ setLimitValueU32("maxStorageBuffersPerShaderStage", limitsOutPtr, 48);
+ setLimitValueU32("maxStorageTexturesPerShaderStage", limitsOutPtr, 52);
+ setLimitValueU32("maxUniformBuffersPerShaderStage", limitsOutPtr, 56);
+ setLimitValueU32("minUniformBufferOffsetAlignment", limitsOutPtr, 80);
+ setLimitValueU32("minStorageBufferOffsetAlignment", limitsOutPtr, 84);
+ setLimitValueU64("maxUniformBufferBindingSize", limitsOutPtr, 64);
+ setLimitValueU64("maxStorageBufferBindingSize", limitsOutPtr, 72);
+ setLimitValueU32("maxVertexBuffers", limitsOutPtr, 88);
+ setLimitValueU64("maxBufferSize", limitsOutPtr, 96);
+ setLimitValueU32("maxVertexAttributes", limitsOutPtr, 104);
+ setLimitValueU32("maxVertexBufferArrayStride", limitsOutPtr, 108);
+ setLimitValueU32("maxInterStageShaderVariables", limitsOutPtr, 112);
+ setLimitValueU32("maxColorAttachments", limitsOutPtr, 116);
+ setLimitValueU32("maxColorAttachmentBytesPerSample", limitsOutPtr, 120);
+ setLimitValueU32("maxComputeWorkgroupStorageSize", limitsOutPtr, 124);
+ setLimitValueU32("maxComputeInvocationsPerWorkgroup", limitsOutPtr, 128);
+ setLimitValueU32("maxComputeWorkgroupSizeX", limitsOutPtr, 132);
+ setLimitValueU32("maxComputeWorkgroupSizeY", limitsOutPtr, 136);
+ setLimitValueU32("maxComputeWorkgroupSizeZ", limitsOutPtr, 140);
+ setLimitValueU32("maxComputeWorkgroupsPerDimension", limitsOutPtr, 144);
+ // Note this limit is new and won't be present in all browsers for a while. Fall back to 0.
+ setLimitValueU32("maxImmediateSize", limitsOutPtr, 148);
+ if (nextInChainPtr !== 0) {
+ var sType = HEAP32[(((nextInChainPtr) + (4)) >>> 2) >>> 0];
+ var compatibilityModeLimitsPtr = nextInChainPtr;
+ // Note these limits are new and won't be present in all browsers for a while. Fall back to exposing the PerShaderStage limit.
+ setLimitValueU32("maxStorageBuffersInVertexStage", compatibilityModeLimitsPtr, 8, limits.maxStorageBuffersPerShaderStage);
+ setLimitValueU32("maxStorageBuffersInFragmentStage", compatibilityModeLimitsPtr, 16, limits.maxStorageBuffersPerShaderStage);
+ setLimitValueU32("maxStorageTexturesInVertexStage", compatibilityModeLimitsPtr, 12, limits.maxStorageTexturesPerShaderStage);
+ setLimitValueU32("maxStorageTexturesInFragmentStage", compatibilityModeLimitsPtr, 20, limits.maxStorageTexturesPerShaderStage);
+ }
+ },
+ fillAdapterInfoStruct: (info, infoStruct) => {
+ // Populate subgroup limits.
+ HEAPU32[(((infoStruct) + (52)) >>> 2) >>> 0] = info.subgroupMinSize;
+ HEAPU32[(((infoStruct) + (56)) >>> 2) >>> 0] = info.subgroupMaxSize;
+ // Append all the strings together to condense into a single malloc.
+ var strs = info.vendor + info.architecture + info.device + info.description;
+ var strPtr = stringToNewUTF8(strs);
+ var vendorLen = lengthBytesUTF8(info.vendor);
+ WebGPU.setStringView(infoStruct + 4, strPtr, vendorLen);
+ strPtr += vendorLen;
+ var architectureLen = lengthBytesUTF8(info.architecture);
+ WebGPU.setStringView(infoStruct + 12, strPtr, architectureLen);
+ strPtr += architectureLen;
+ var deviceLen = lengthBytesUTF8(info.device);
+ WebGPU.setStringView(infoStruct + 20, strPtr, deviceLen);
+ strPtr += deviceLen;
+ var descriptionLen = lengthBytesUTF8(info.description);
+ WebGPU.setStringView(infoStruct + 28, strPtr, descriptionLen);
+ strPtr += descriptionLen;
+ HEAP32[(((infoStruct) + (36)) >>> 2) >>> 0] = 2;
+ var adapterType = info.isFallbackAdapter ? 3 : 4;
+ HEAP32[(((infoStruct) + (40)) >>> 2) >>> 0] = adapterType;
+ HEAPU32[(((infoStruct) + (44)) >>> 2) >>> 0] = 0;
+ HEAPU32[(((infoStruct) + (48)) >>> 2) >>> 0] = 0;
+ },
+ AddressMode: [ , "clamp-to-edge", "repeat", "mirror-repeat" ],
+ BlendFactor: [ , "zero", "one", "src", "one-minus-src", "src-alpha", "one-minus-src-alpha", "dst", "one-minus-dst", "dst-alpha", "one-minus-dst-alpha", "src-alpha-saturated", "constant", "one-minus-constant", "src1", "one-minus-src1", "src1-alpha", "one-minus-src1-alpha" ],
+ BlendOperation: [ , "add", "subtract", "reverse-subtract", "min", "max" ],
+ BufferBindingType: [ , , "uniform", "storage", "read-only-storage" ],
+ BufferMapState: [ , "unmapped", "pending", "mapped" ],
+ CompareFunction: [ , "never", "less", "equal", "less-equal", "greater", "not-equal", "greater-equal", "always" ],
+ CompilationInfoRequestStatus: [ , "success", "callback-cancelled" ],
+ ComponentSwizzle: [ , "0", "1", "r", "g", "b", "a" ],
+ CompositeAlphaMode: [ , "opaque", "premultiplied", "unpremultiplied", "inherit" ],
+ CullMode: [ , "none", "front", "back" ],
+ ErrorFilter: [ , "validation", "out-of-memory", "internal" ],
+ FeatureLevel: [ , "compatibility", "core" ],
+ FeatureName: {
+ 1: "core-features-and-limits",
+ 2: "depth-clip-control",
+ 3: "depth32float-stencil8",
+ 4: "texture-compression-bc",
+ 5: "texture-compression-bc-sliced-3d",
+ 6: "texture-compression-etc2",
+ 7: "texture-compression-astc",
+ 8: "texture-compression-astc-sliced-3d",
+ 9: "timestamp-query",
+ 10: "indirect-first-instance",
+ 11: "shader-f16",
+ 12: "rg11b10ufloat-renderable",
+ 13: "bgra8unorm-storage",
+ 14: "float32-filterable",
+ 15: "float32-blendable",
+ 16: "clip-distances",
+ 17: "dual-source-blending",
+ 18: "subgroups",
+ 19: "texture-formats-tier1",
+ 20: "texture-formats-tier2",
+ 21: "primitive-index",
+ 22: "texture-component-swizzle",
+ 327692: "chromium-experimental-unorm16-texture-formats",
+ 327729: "chromium-experimental-multi-draw-indirect"
+ },
+ FilterMode: [ , "nearest", "linear" ],
+ FrontFace: [ , "ccw", "cw" ],
+ IndexFormat: [ , "uint16", "uint32" ],
+ InstanceFeatureName: [ , "timed-wait-any", "shader-source-spirv", "multiple-devices-per-adapter" ],
+ LoadOp: [ , "load", "clear" ],
+ MipmapFilterMode: [ , "nearest", "linear" ],
+ OptionalBool: [ "false", "true" ],
+ PowerPreference: [ , "low-power", "high-performance" ],
+ PredefinedColorSpace: [ , "srgb", "display-p3" ],
+ PrimitiveTopology: [ , "point-list", "line-list", "line-strip", "triangle-list", "triangle-strip" ],
+ QueryType: [ , "occlusion", "timestamp" ],
+ SamplerBindingType: [ , , "filtering", "non-filtering", "comparison" ],
+ Status: [ , "success", "error" ],
+ StencilOperation: [ , "keep", "zero", "replace", "invert", "increment-clamp", "decrement-clamp", "increment-wrap", "decrement-wrap" ],
+ StorageTextureAccess: [ , , "write-only", "read-only", "read-write" ],
+ StoreOp: [ , "store", "discard" ],
+ SurfaceGetCurrentTextureStatus: [ , "success-optimal", "success-suboptimal", "timeout", "outdated", "lost", "error" ],
+ TextureAspect: [ , "all", "stencil-only", "depth-only" ],
+ TextureDimension: [ , "1d", "2d", "3d" ],
+ TextureFormat: [ , "r8unorm", "r8snorm", "r8uint", "r8sint", "r16unorm", "r16snorm", "r16uint", "r16sint", "r16float", "rg8unorm", "rg8snorm", "rg8uint", "rg8sint", "r32float", "r32uint", "r32sint", "rg16unorm", "rg16snorm", "rg16uint", "rg16sint", "rg16float", "rgba8unorm", "rgba8unorm-srgb", "rgba8snorm", "rgba8uint", "rgba8sint", "bgra8unorm", "bgra8unorm-srgb", "rgb10a2uint", "rgb10a2unorm", "rg11b10ufloat", "rgb9e5ufloat", "rg32float", "rg32uint", "rg32sint", "rgba16unorm", "rgba16snorm", "rgba16uint", "rgba16sint", "rgba16float", "rgba32float", "rgba32uint", "rgba32sint", "stencil8", "depth16unorm", "depth24plus", "depth24plus-stencil8", "depth32float", "depth32float-stencil8", "bc1-rgba-unorm", "bc1-rgba-unorm-srgb", "bc2-rgba-unorm", "bc2-rgba-unorm-srgb", "bc3-rgba-unorm", "bc3-rgba-unorm-srgb", "bc4-r-unorm", "bc4-r-snorm", "bc5-rg-unorm", "bc5-rg-snorm", "bc6h-rgb-ufloat", "bc6h-rgb-float", "bc7-rgba-unorm", "bc7-rgba-unorm-srgb", "etc2-rgb8unorm", "etc2-rgb8unorm-srgb", "etc2-rgb8a1unorm", "etc2-rgb8a1unorm-srgb", "etc2-rgba8unorm", "etc2-rgba8unorm-srgb", "eac-r11unorm", "eac-r11snorm", "eac-rg11unorm", "eac-rg11snorm", "astc-4x4-unorm", "astc-4x4-unorm-srgb", "astc-5x4-unorm", "astc-5x4-unorm-srgb", "astc-5x5-unorm", "astc-5x5-unorm-srgb", "astc-6x5-unorm", "astc-6x5-unorm-srgb", "astc-6x6-unorm", "astc-6x6-unorm-srgb", "astc-8x5-unorm", "astc-8x5-unorm-srgb", "astc-8x6-unorm", "astc-8x6-unorm-srgb", "astc-8x8-unorm", "astc-8x8-unorm-srgb", "astc-10x5-unorm", "astc-10x5-unorm-srgb", "astc-10x6-unorm", "astc-10x6-unorm-srgb", "astc-10x8-unorm", "astc-10x8-unorm-srgb", "astc-10x10-unorm", "astc-10x10-unorm-srgb", "astc-12x10-unorm", "astc-12x10-unorm-srgb", "astc-12x12-unorm", "astc-12x12-unorm-srgb" ],
+ TextureSampleType: [ , , "float", "unfilterable-float", "depth", "sint", "uint" ],
+ TextureViewDimension: [ , "1d", "2d", "2d-array", "cube", "cube-array", "3d" ],
+ ToneMappingMode: [ , "standard", "extended" ],
+ VertexFormat: [ , "uint8", "uint8x2", "uint8x4", "sint8", "sint8x2", "sint8x4", "unorm8", "unorm8x2", "unorm8x4", "snorm8", "snorm8x2", "snorm8x4", "uint16", "uint16x2", "uint16x4", "sint16", "sint16x2", "sint16x4", "unorm16", "unorm16x2", "unorm16x4", "snorm16", "snorm16x2", "snorm16x4", "float16", "float16x2", "float16x4", "float32", "float32x2", "float32x3", "float32x4", "uint32", "uint32x2", "uint32x3", "uint32x4", "sint32", "sint32x2", "sint32x3", "sint32x4", "unorm10-10-10-2", "unorm8x4-bgra" ],
+ VertexStepMode: [ , "vertex", "instance" ],
+ WGSLLanguageFeatureName: [ , "readonly_and_readwrite_storage_textures", "packed_4x8_integer_dot_product", "unrestricted_pointer_parameters", "pointer_composite_access", "uniform_buffer_standard_layout", "subgroup_id", "texture_and_sampler_let", "subgroup_uniformity", "texture_formats_tier1" ]
+};
+
+function _emscripten_webgpu_get_device() {
+ if (WebGPU.preinitializedDeviceId === undefined) {
+ WebGPU.preinitializedDeviceId = WebGPU.importJsDevice(Module["preinitializedWebGPUDevice"]);
+ // Some users depend on this keeping the device alive, so we add an
+ // additional reference when we first initialize it.
+ _wgpuDeviceAddRef(WebGPU.preinitializedDeviceId);
+ }
+ _wgpuDeviceAddRef(WebGPU.preinitializedDeviceId);
+ return WebGPU.preinitializedDeviceId;
+}
+
+function _emwgpuBufferDestroy(bufferPtr) {
+ bufferPtr >>>= 0;
+ var buffer = WebGPU.getJsObject(bufferPtr);
+ var onUnmap = WebGPU.Internals.bufferOnUnmaps[bufferPtr];
+ if (onUnmap) {
+ for (var i = 0; i < onUnmap.length; ++i) {
+ onUnmap[i]();
+ }
+ delete WebGPU.Internals.bufferOnUnmaps[bufferPtr];
+ }
+ buffer.destroy();
+}
+
+function _emwgpuBufferGetMappedRange(bufferPtr, offset, size) {
+ bufferPtr >>>= 0;
+ offset >>>= 0;
+ size >>>= 0;
+ var buffer = WebGPU.getJsObject(bufferPtr);
+ if (size == 4294967295) size = undefined;
+ var mapped;
+ try {
+ mapped = buffer.getMappedRange(offset, size);
+ } catch (ex) {
+ return 0;
+ }
+ var data = _memalign(16, mapped.byteLength);
+ HEAPU8.fill(0, data, mapped.byteLength);
+ WebGPU.Internals.bufferOnUnmaps[bufferPtr].push(() => {
+ new Uint8Array(mapped).set(HEAPU8.subarray(data >>> 0, data + mapped.byteLength >>> 0));
+ _free(data);
+ });
+ return data;
+}
+
+function _emwgpuBufferUnmap(bufferPtr) {
+ bufferPtr >>>= 0;
+ var buffer = WebGPU.getJsObject(bufferPtr);
+ var onUnmap = WebGPU.Internals.bufferOnUnmaps[bufferPtr];
+ if (!onUnmap) {
+ // Already unmapped
+ return;
+ }
+ for (var i = 0; i < onUnmap.length; ++i) {
+ onUnmap[i]();
+ }
+ delete WebGPU.Internals.bufferOnUnmaps[bufferPtr];
+ buffer.unmap();
+}
+
+function _emwgpuBufferWriteMappedRange(bufferPtr, offset, data, size) {
+ bufferPtr >>>= 0;
+ offset >>>= 0;
+ data >>>= 0;
+ size >>>= 0;
+ var buffer = WebGPU.getJsObject(bufferPtr);
+ var mapped;
+ try {
+ mapped = buffer.getMappedRange(offset, size);
+ } catch (ex) {
+ return 2;
+ }
+ new Uint8Array(mapped).set(HEAPU8.subarray(data >>> 0, data + size >>> 0));
+ return 1;
+}
+
+function _emwgpuDelete(ptr) {
+ ptr >>>= 0;
+ delete WebGPU.Internals.jsObjects[ptr];
+}
+
+function _emwgpuDeviceCreateBuffer(devicePtr, descriptor, bufferPtr) {
+ devicePtr >>>= 0;
+ descriptor >>>= 0;
+ bufferPtr >>>= 0;
+ var mappedAtCreation = !!(HEAPU32[(((descriptor) + (32)) >>> 2) >>> 0]);
+ var desc = {
+ "label": WebGPU.makeStringFromOptionalStringView(descriptor + 4),
+ "usage": HEAPU32[(((descriptor) + (16)) >>> 2) >>> 0],
+ "size": readI53FromI64((descriptor) + (24)),
+ "mappedAtCreation": mappedAtCreation
+ };
+ var device = WebGPU.getJsObject(devicePtr);
+ var buffer;
+ try {
+ buffer = device.createBuffer(desc);
+ } catch (ex) {
+ // The only exception should be RangeError if mapping at creation ran out of memory.
+ return false;
+ }
+ WebGPU.Internals.jsObjectInsert(bufferPtr, buffer);
+ if (mappedAtCreation) {
+ WebGPU.Internals.bufferOnUnmaps[bufferPtr] = [];
+ }
+ return true;
+}
+
+var _emwgpuDeviceCreateComputePipelineAsync = function(devicePtr, futureId_low, futureId_high, descriptor, pipelinePtr) {
+ devicePtr >>>= 0;
+ var futureId = convertI32PairToI53Checked(futureId_low, futureId_high);
+ descriptor >>>= 0;
+ pipelinePtr >>>= 0;
+ var desc = WebGPU.makeComputePipelineDesc(descriptor);
+ var device = WebGPU.getJsObject(devicePtr);
+ // createComputePipelineAsync
+ WebGPU.Internals.futureInsert(futureId, device.createComputePipelineAsync(desc).then(pipeline => {
+ // createComputePipelineAsync fulfilled
+ callUserCallback(() => {
+ WebGPU.Internals.jsObjectInsert(pipelinePtr, pipeline);
+ _emwgpuOnCreateComputePipelineCompleted(futureId, 1, pipelinePtr, 0);
+ });
+ }, pipelineError => {
+ // createComputePipelineAsync rejected
+ callUserCallback(() => {
+ var sp = stackSave();
+ var messagePtr = stringToUTF8OnStack(pipelineError.message);
+ var status = pipelineError.reason === "validation" ? 3 : pipelineError.reason === "internal" ? 4 : 0;
+ _emwgpuOnCreateComputePipelineCompleted(futureId, status, pipelinePtr, messagePtr);
+ stackRestore(sp);
+ });
+ }));
+};
+
+function _emwgpuDeviceCreateShaderModule(devicePtr, descriptor, shaderModulePtr) {
+ devicePtr >>>= 0;
+ descriptor >>>= 0;
+ shaderModulePtr >>>= 0;
+ var nextInChainPtr = HEAPU32[((descriptor) >>> 2) >>> 0];
+ var sType = HEAP32[(((nextInChainPtr) + (4)) >>> 2) >>> 0];
+ var desc = {
+ "label": WebGPU.makeStringFromOptionalStringView(descriptor + 4),
+ "code": ""
+ };
+ switch (sType) {
+ case 2:
+ {
+ desc["code"] = WebGPU.makeStringFromStringView(nextInChainPtr + 8);
+ break;
+ }
+ }
+ var device = WebGPU.getJsObject(devicePtr);
+ WebGPU.Internals.jsObjectInsert(shaderModulePtr, device.createShaderModule(desc));
+}
+
+var _emwgpuDeviceDestroy = devicePtr => {
+ const device = WebGPU.getJsObject(devicePtr);
+ // Remove the onuncapturederror handler which holds a pointer to the WGPUDevice.
+ device.onuncapturederror = null;
+ device.destroy();
+};
+
+var _emwgpuQueueOnSubmittedWorkDone = function(queuePtr, futureId_low, futureId_high) {
+ queuePtr >>>= 0;
+ var futureId = convertI32PairToI53Checked(futureId_low, futureId_high);
+ var queue = WebGPU.getJsObject(queuePtr);
+ // onSubmittedWorkDone
+ WebGPU.Internals.futureInsert(futureId, queue.onSubmittedWorkDone().then(() => {
+ // onSubmittedWorkDone fulfilled (assumed not to reject)
+ callUserCallback(() => {
+ _emwgpuOnWorkDoneCompleted(futureId, 1);
+ });
+ }));
+};
+
+var _emwgpuWaitAny = function(futurePtr, futureCount, timeoutMSPtr) {
+ futurePtr >>>= 0;
+ futureCount >>>= 0;
+ timeoutMSPtr >>>= 0;
+ return Asyncify.handleAsync(async () => {
+ var promises = [];
+ if (timeoutMSPtr) {
+ var timeoutMS = HEAP32[((timeoutMSPtr) >>> 2) >>> 0];
+ promises.length = futureCount + 1;
+ promises[futureCount] = new Promise(resolve => setTimeout(resolve, timeoutMS, 0));
+ } else {
+ promises.length = futureCount;
+ }
+ for (var i = 0; i < futureCount; ++i) {
+ // If any FutureID is not tracked, it means it must be done.
+ var futureId = readI53FromI64((futurePtr + i * 8));
+ if (!(futureId in WebGPU.Internals.futures)) {
+ return futureId;
+ }
+ promises[i] = WebGPU.Internals.futures[futureId];
+ }
+ const firstResolvedFuture = await Promise.race(promises);
+ delete WebGPU.Internals.futures[firstResolvedFuture];
+ return firstResolvedFuture;
+ });
+};
+
+_emwgpuWaitAny.isAsync = true;
+
+var ENV = {};
+
+var getExecutableName = () => thisProgram || "./this.program";
+
+var getEnvStrings = () => {
+ if (!getEnvStrings.strings) {
+ // Default values.
+ // Browser language detection #8751
+ var lang = (globalThis.navigator?.language ?? "C").replace("-", "_") + ".UTF-8";
+ var env = {
+ "USER": "web_user",
+ "LOGNAME": "web_user",
+ "PATH": "/",
+ "PWD": "/",
+ "HOME": "/home/web_user",
+ "LANG": lang,
+ "_": getExecutableName()
+ };
+ // Apply the user-provided values, if any.
+ for (var x in ENV) {
+ // x is a key in ENV; if ENV[x] is undefined, that means it was
+ // explicitly set to be so. We allow user code to do that to
+ // force variables with default values to remain unset.
+ if (ENV[x] === undefined) delete env[x]; else env[x] = ENV[x];
+ }
+ var strings = [];
+ for (var x in env) {
+ strings.push(`${x}=${env[x]}`);
+ }
+ getEnvStrings.strings = strings;
+ }
+ return getEnvStrings.strings;
+};
+
+function _environ_get(__environ, environ_buf) {
+ __environ >>>= 0;
+ environ_buf >>>= 0;
+ var bufSize = 0;
+ var envp = 0;
+ for (var string of getEnvStrings()) {
+ var ptr = environ_buf + bufSize;
+ HEAPU32[(((__environ) + (envp)) >>> 2) >>> 0] = ptr;
+ bufSize += stringToUTF8(string, ptr, Infinity) + 1;
+ envp += 4;
+ }
+ return 0;
+}
+
+function _environ_sizes_get(penviron_count, penviron_buf_size) {
+ penviron_count >>>= 0;
+ penviron_buf_size >>>= 0;
+ var strings = getEnvStrings();
+ HEAPU32[((penviron_count) >>> 2) >>> 0] = strings.length;
+ var bufSize = 0;
+ for (var string of strings) {
+ bufSize += lengthBytesUTF8(string) + 1;
+ }
+ HEAPU32[((penviron_buf_size) >>> 2) >>> 0] = bufSize;
+ return 0;
+}
+
+function _fd_close(fd) {
+ try {
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ FS.close(stream);
+ return 0;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return e.errno;
+ }
+}
+
+/** @param {number=} offset */ var doReadv = (stream, iov, iovcnt, offset) => {
+ var ret = 0;
+ for (var i = 0; i < iovcnt; i++) {
+ var ptr = HEAPU32[((iov) >>> 2) >>> 0];
+ var len = HEAPU32[(((iov) + (4)) >>> 2) >>> 0];
+ iov += 8;
+ var curr = FS.read(stream, HEAP8, ptr, len, offset);
+ if (curr < 0) return -1;
+ ret += curr;
+ if (curr < len) break;
+ // nothing more to read
+ if (typeof offset != "undefined") {
+ offset += curr;
+ }
+ }
+ return ret;
+};
+
+function _fd_pread(fd, iov, iovcnt, offset_low, offset_high, pnum) {
+ iov >>>= 0;
+ iovcnt >>>= 0;
+ var offset = convertI32PairToI53Checked(offset_low, offset_high);
+ pnum >>>= 0;
+ try {
+ if (isNaN(offset)) return 61;
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ var num = doReadv(stream, iov, iovcnt, offset);
+ HEAPU32[((pnum) >>> 2) >>> 0] = num;
+ return 0;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return e.errno;
+ }
+}
+
+function _fd_read(fd, iov, iovcnt, pnum) {
+ iov >>>= 0;
+ iovcnt >>>= 0;
+ pnum >>>= 0;
+ try {
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ var num = doReadv(stream, iov, iovcnt);
+ HEAPU32[((pnum) >>> 2) >>> 0] = num;
+ return 0;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return e.errno;
+ }
+}
+
+function _fd_seek(fd, offset_low, offset_high, whence, newOffset) {
+ var offset = convertI32PairToI53Checked(offset_low, offset_high);
+ newOffset >>>= 0;
+ try {
+ if (isNaN(offset)) return 61;
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ FS.llseek(stream, offset, whence);
+ (tempI64 = [ stream.position >>> 0, (tempDouble = stream.position, (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0) ],
+ HEAP32[((newOffset) >>> 2) >>> 0] = tempI64[0], HEAP32[(((newOffset) + (4)) >>> 2) >>> 0] = tempI64[1]);
+ if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null;
+ // reset readdir state
+ return 0;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return e.errno;
+ }
+}
+
+/** @param {number=} offset */ var doWritev = (stream, iov, iovcnt, offset) => {
+ var ret = 0;
+ for (var i = 0; i < iovcnt; i++) {
+ var ptr = HEAPU32[((iov) >>> 2) >>> 0];
+ var len = HEAPU32[(((iov) + (4)) >>> 2) >>> 0];
+ iov += 8;
+ var curr = FS.write(stream, HEAP8, ptr, len, offset);
+ if (curr < 0) return -1;
+ ret += curr;
+ if (curr < len) {
+ // No more space to write.
+ break;
+ }
+ if (typeof offset != "undefined") {
+ offset += curr;
+ }
+ }
+ return ret;
+};
+
+function _fd_write(fd, iov, iovcnt, pnum) {
+ iov >>>= 0;
+ iovcnt >>>= 0;
+ pnum >>>= 0;
+ try {
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ var num = doWritev(stream, iov, iovcnt);
+ HEAPU32[((pnum) >>> 2) >>> 0] = num;
+ return 0;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return e.errno;
+ }
+}
+
+var _emscripten_glActiveTexture = x0 => GLctx.activeTexture(x0);
+
+var _glActiveTexture = _emscripten_glActiveTexture;
+
+var _emscripten_glAttachShader = (program, shader) => {
+ GLctx.attachShader(GL.programs[program], GL.shaders[shader]);
+};
+
+var _glAttachShader = _emscripten_glAttachShader;
+
+function _emscripten_glBindAttribLocation(program, index, name) {
+ name >>>= 0;
+ GLctx.bindAttribLocation(GL.programs[program], index, UTF8ToString(name));
+}
+
+var _glBindAttribLocation = _emscripten_glBindAttribLocation;
+
+var _emscripten_glBindBuffer = (target, buffer) => {
+ // Calling glBindBuffer with an unknown buffer will implicitly create a
+ // new one. Here we bypass `GL.counter` and directly using the ID passed
+ // in.
+ if (buffer && !GL.buffers[buffer]) {
+ var b = GLctx.createBuffer();
+ b.name = buffer;
+ GL.buffers[buffer] = b;
+ }
+ if (target == 34962) {
+ GLctx.currentArrayBufferBinding = buffer;
+ } else if (target == 34963) {
+ GLctx.currentElementArrayBufferBinding = buffer;
+ }
+ if (target == 35051) {
+ // In WebGL 2 glReadPixels entry point, we need to use a different WebGL 2
+ // API function call when a buffer is bound to
+ // GL_PIXEL_PACK_BUFFER_BINDING point, so must keep track whether that
+ // binding point is non-null to know what is the proper API function to
+ // call.
+ GLctx.currentPixelPackBufferBinding = buffer;
+ } else if (target == 35052) {
+ // In WebGL 2 gl(Compressed)Tex(Sub)Image[23]D entry points, we need to
+ // use a different WebGL 2 API function call when a buffer is bound to
+ // GL_PIXEL_UNPACK_BUFFER_BINDING point, so must keep track whether that
+ // binding point is non-null to know what is the proper API function to
+ // call.
+ GLctx.currentPixelUnpackBufferBinding = buffer;
+ }
+ GLctx.bindBuffer(target, GL.buffers[buffer]);
+};
+
+var _glBindBuffer = _emscripten_glBindBuffer;
+
+var _emscripten_glBindFramebuffer = (target, framebuffer) => {
+ GLctx.bindFramebuffer(target, GL.framebuffers[framebuffer]);
+};
+
+var _glBindFramebuffer = _emscripten_glBindFramebuffer;
+
+var _emscripten_glBindTexture = (target, texture) => {
+ GLctx.bindTexture(target, GL.textures[texture]);
+};
+
+var _glBindTexture = _emscripten_glBindTexture;
+
+function _emscripten_glBufferData(target, size, data, usage) {
+ size >>>= 0;
+ data >>>= 0;
+ // N.b. here first form specifies a heap subarray, second form an integer
+ // size, so the ?: code here is polymorphic. It is advised to avoid
+ // randomly mixing both uses in calling code, to avoid any potential JS
+ // engine JIT issues.
+ GLctx.bufferData(target, data ? HEAPU8.subarray(data >>> 0, data + size >>> 0) : size, usage);
+}
+
+var _glBufferData = _emscripten_glBufferData;
+
+var convertI32PairToI53 = (lo, hi) => (lo >>> 0) + hi * 4294967296;
+
+function _emscripten_glClientWaitSync(sync, flags, timeout_low, timeout_high) {
+ sync >>>= 0;
+ // WebGL2 vs GLES3 differences: in GLES3, the timeout parameter is a uint64, where 0xFFFFFFFFFFFFFFFFULL means GL_TIMEOUT_IGNORED.
+ // In JS, there's no 64-bit value types, so instead timeout is taken to be signed, and GL_TIMEOUT_IGNORED is given value -1.
+ // Inherently the value accepted in the timeout is lossy, and can't take in arbitrary u64 bit pattern (but most likely doesn't matter)
+ // See https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.15
+ var timeout = convertI32PairToI53(timeout_low, timeout_high);
+ return GLctx.clientWaitSync(GL.syncs[sync], flags, timeout);
+}
+
+var _glClientWaitSync = _emscripten_glClientWaitSync;
+
+var _emscripten_glCompileShader = shader => {
+ GLctx.compileShader(GL.shaders[shader]);
+};
+
+var _glCompileShader = _emscripten_glCompileShader;
+
+var _emscripten_glCreateProgram = () => {
+ var id = GL.getNewId(GL.programs);
+ var program = GLctx.createProgram();
+ // Store additional information needed for each shader program:
+ program.name = id;
+ // Lazy cache results of
+ // glGetProgramiv(GL_ACTIVE_UNIFORM_MAX_LENGTH/GL_ACTIVE_ATTRIBUTE_MAX_LENGTH/GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH)
+ program.maxUniformLength = program.maxAttributeLength = program.maxUniformBlockNameLength = 0;
+ program.uniformIdCounter = 1;
+ GL.programs[id] = program;
+ return id;
+};
+
+var _glCreateProgram = _emscripten_glCreateProgram;
+
+var _emscripten_glCreateShader = shaderType => {
+ var id = GL.getNewId(GL.shaders);
+ GL.shaders[id] = GLctx.createShader(shaderType);
+ return id;
+};
+
+var _glCreateShader = _emscripten_glCreateShader;
+
+function _emscripten_glDeleteFramebuffers(n, framebuffers) {
+ framebuffers >>>= 0;
+ for (var i = 0; i < n; ++i) {
+ var id = HEAP32[(((framebuffers) + (i * 4)) >>> 2) >>> 0];
+ var framebuffer = GL.framebuffers[id];
+ if (!framebuffer) continue;
+ // GL spec: "glDeleteFramebuffers silently ignores 0s and names that do not correspond to existing framebuffer objects".
+ GLctx.deleteFramebuffer(framebuffer);
+ framebuffer.name = 0;
+ GL.framebuffers[id] = null;
+ }
+}
+
+var _glDeleteFramebuffers = _emscripten_glDeleteFramebuffers;
+
+var _emscripten_glDeleteProgram = id => {
+ if (!id) return;
+ var program = GL.programs[id];
+ if (!program) {
+ // glDeleteProgram actually signals an error when deleting a nonexisting
+ // object, unlike some other GL delete functions.
+ GL.recordError(1281);
+ return;
+ }
+ GLctx.deleteProgram(program);
+ program.name = 0;
+ GL.programs[id] = null;
+};
+
+var _glDeleteProgram = _emscripten_glDeleteProgram;
+
+var _emscripten_glDeleteShader = id => {
+ if (!id) return;
+ var shader = GL.shaders[id];
+ if (!shader) {
+ // glDeleteShader actually signals an error when deleting a nonexisting
+ // object, unlike some other GL delete functions.
+ GL.recordError(1281);
+ return;
+ }
+ GLctx.deleteShader(shader);
+ GL.shaders[id] = null;
+};
+
+var _glDeleteShader = _emscripten_glDeleteShader;
+
+function _emscripten_glDeleteSync(id) {
+ id >>>= 0;
+ if (!id) return;
+ var sync = GL.syncs[id];
+ if (!sync) {
+ // glDeleteSync signals an error when deleting a nonexisting object, unlike some other GL delete functions.
+ GL.recordError(1281);
+ return;
+ }
+ GLctx.deleteSync(sync);
+ sync.name = 0;
+ GL.syncs[id] = null;
+}
+
+var _glDeleteSync = _emscripten_glDeleteSync;
+
+function _emscripten_glDeleteTextures(n, textures) {
+ textures >>>= 0;
+ for (var i = 0; i < n; i++) {
+ var id = HEAP32[(((textures) + (i * 4)) >>> 2) >>> 0];
+ var texture = GL.textures[id];
+ // GL spec: "glDeleteTextures silently ignores 0s and names that do not
+ // correspond to existing textures".
+ if (!texture) continue;
+ GLctx.deleteTexture(texture);
+ texture.name = 0;
+ GL.textures[id] = null;
+ }
+}
+
+var _glDeleteTextures = _emscripten_glDeleteTextures;
+
+var _emscripten_glDetachShader = (program, shader) => {
+ GLctx.detachShader(GL.programs[program], GL.shaders[shader]);
+};
+
+var _glDetachShader = _emscripten_glDetachShader;
+
+var _emscripten_glDisableVertexAttribArray = index => {
+ var cb = GL.currentContext.clientBuffers[index];
+ cb.enabled = false;
+ GLctx.disableVertexAttribArray(index);
+};
+
+var _glDisableVertexAttribArray = _emscripten_glDisableVertexAttribArray;
+
+var _emscripten_glDrawArrays = (mode, first, count) => {
+ // bind any client-side buffers
+ GL.preDrawHandleClientVertexAttribBindings(first + count);
+ GLctx.drawArrays(mode, first, count);
+ GL.postDrawHandleClientVertexAttribBindings();
+};
+
+var _glDrawArrays = _emscripten_glDrawArrays;
+
+var _emscripten_glEnableVertexAttribArray = index => {
+ var cb = GL.currentContext.clientBuffers[index];
+ cb.enabled = true;
+ GLctx.enableVertexAttribArray(index);
+};
+
+var _glEnableVertexAttribArray = _emscripten_glEnableVertexAttribArray;
+
+function _emscripten_glFenceSync(condition, flags) {
+ var sync = GLctx.fenceSync(condition, flags);
+ if (sync) {
+ var id = GL.getNewId(GL.syncs);
+ sync.name = id;
+ GL.syncs[id] = sync;
+ return id;
+ }
+ return 0;
+}
+
+var _glFenceSync = _emscripten_glFenceSync;
+
+var _emscripten_glFinish = () => GLctx.finish();
+
+var _glFinish = _emscripten_glFinish;
+
+var _emscripten_glFramebufferTexture2D = (target, attachment, textarget, texture, level) => {
+ GLctx.framebufferTexture2D(target, attachment, textarget, GL.textures[texture], level);
+};
+
+var _glFramebufferTexture2D = _emscripten_glFramebufferTexture2D;
+
+function _emscripten_glGenBuffers(n, buffers) {
+ buffers >>>= 0;
+ GL.genObject(n, buffers, "createBuffer", GL.buffers);
+}
+
+var _glGenBuffers = _emscripten_glGenBuffers;
+
+function _emscripten_glGenFramebuffers(n, ids) {
+ ids >>>= 0;
+ GL.genObject(n, ids, "createFramebuffer", GL.framebuffers);
+}
+
+var _glGenFramebuffers = _emscripten_glGenFramebuffers;
+
+function _emscripten_glGenTextures(n, textures) {
+ textures >>>= 0;
+ GL.genObject(n, textures, "createTexture", GL.textures);
+}
+
+var _glGenTextures = _emscripten_glGenTextures;
+
+var _emscripten_glGetError = () => {
+ var error = GLctx.getError() || GL.lastError;
+ GL.lastError = 0;
+ return error;
+};
+
+var _glGetError = _emscripten_glGetError;
+
+var webglGetExtensions = () => {
+ var exts = getEmscriptenSupportedExtensions(GLctx);
+ exts = exts.concat(exts.map(e => "GL_" + e));
+ return exts;
+};
+
+var emscriptenWebGLGet = (name_, p, type) => {
+ // Guard against user passing a null pointer.
+ // Note that GLES2 spec does not say anything about how passing a null
+ // pointer should be treated. Testing on desktop core GL 3, the application
+ // crashes on glGetIntegerv to a null pointer, but better to report an error
+ // instead of doing anything random.
+ if (!p) {
+ GL.recordError(1281);
+ return;
+ }
+ var ret = undefined;
+ switch (name_) {
+ // Handle a few trivial GLES values
+ case 36346:
+ // GL_SHADER_COMPILER
+ ret = 1;
+ break;
+
+ case 36344:
+ // GL_SHADER_BINARY_FORMATS
+ if (type != 0 && type != 1) {
+ GL.recordError(1280);
+ }
+ // Do not write anything to the out pointer, since no binary formats are
+ // supported.
+ return;
+
+ case 34814:
+ // GL_NUM_PROGRAM_BINARY_FORMATS
+ case 36345:
+ // GL_NUM_SHADER_BINARY_FORMATS
+ ret = 0;
+ break;
+
+ case 34466:
+ // GL_NUM_COMPRESSED_TEXTURE_FORMATS
+ // WebGL doesn't have GL_NUM_COMPRESSED_TEXTURE_FORMATS (it's obsolete
+ // since GL_COMPRESSED_TEXTURE_FORMATS returns a JS array that can be
+ // queried for length), so implement it ourselves to allow C++ GLES2
+ // code to get the length.
+ var formats = GLctx.getParameter(34467);
+ ret = formats ? formats.length : 0;
+ break;
+
+ case 33309:
+ // GL_NUM_EXTENSIONS
+ if (GL.currentContext.version < 2) {
+ // Calling GLES3/WebGL2 function with a GLES2/WebGL1 context
+ GL.recordError(1282);
+ return;
+ }
+ ret = webglGetExtensions().length;
+ break;
+
+ case 33307:
+ // GL_MAJOR_VERSION
+ case 33308:
+ // GL_MINOR_VERSION
+ if (GL.currentContext.version < 2) {
+ GL.recordError(1280);
+ // GL_INVALID_ENUM
+ return;
+ }
+ ret = name_ == 33307 ? 3 : 0;
+ // return version 3.0
+ break;
+ }
+ if (ret === undefined) {
+ var result = GLctx.getParameter(name_);
+ switch (typeof result) {
+ case "number":
+ ret = result;
+ break;
+
+ case "boolean":
+ ret = result ? 1 : 0;
+ break;
+
+ case "string":
+ GL.recordError(1280);
+ // GL_INVALID_ENUM
+ return;
+
+ case "object":
+ if (result === null) {
+ // null is a valid result for some (e.g., which buffer is bound -
+ // perhaps nothing is bound), but otherwise can mean an invalid
+ // name_, which we need to report as an error
+ switch (name_) {
+ case 34964:
+ // ARRAY_BUFFER_BINDING
+ case 35725:
+ // CURRENT_PROGRAM
+ case 34965:
+ // ELEMENT_ARRAY_BUFFER_BINDING
+ case 36006:
+ // FRAMEBUFFER_BINDING or DRAW_FRAMEBUFFER_BINDING
+ case 36007:
+ // RENDERBUFFER_BINDING
+ case 32873:
+ // TEXTURE_BINDING_2D
+ case 34229:
+ // WebGL 2 GL_VERTEX_ARRAY_BINDING, or WebGL 1 extension OES_vertex_array_object GL_VERTEX_ARRAY_BINDING_OES
+ case 36662:
+ // COPY_READ_BUFFER_BINDING or COPY_READ_BUFFER
+ case 36663:
+ // COPY_WRITE_BUFFER_BINDING or COPY_WRITE_BUFFER
+ case 35053:
+ // PIXEL_PACK_BUFFER_BINDING
+ case 35055:
+ // PIXEL_UNPACK_BUFFER_BINDING
+ case 36010:
+ // READ_FRAMEBUFFER_BINDING
+ case 35097:
+ // SAMPLER_BINDING
+ case 35869:
+ // TEXTURE_BINDING_2D_ARRAY
+ case 32874:
+ // TEXTURE_BINDING_3D
+ case 36389:
+ // TRANSFORM_FEEDBACK_BINDING
+ case 35983:
+ // TRANSFORM_FEEDBACK_BUFFER_BINDING
+ case 35368:
+ // UNIFORM_BUFFER_BINDING
+ case 34068:
+ {
+ // TEXTURE_BINDING_CUBE_MAP
+ ret = 0;
+ break;
+ }
+
+ default:
+ {
+ GL.recordError(1280);
+ // GL_INVALID_ENUM
+ return;
+ }
+ }
+ } else if (result instanceof Float32Array || result instanceof Uint32Array || result instanceof Int32Array || result instanceof Array) {
+ for (var i = 0; i < result.length; ++i) {
+ switch (type) {
+ case 0:
+ HEAP32[(((p) + (i * 4)) >>> 2) >>> 0] = result[i];
+ break;
+
+ case 2:
+ HEAPF32[(((p) + (i * 4)) >>> 2) >>> 0] = result[i];
+ break;
+
+ case 4:
+ HEAP8[(p) + (i) >>> 0] = result[i] ? 1 : 0;
+ break;
+ }
+ }
+ return;
+ } else {
+ try {
+ ret = result.name | 0;
+ } catch (e) {
+ GL.recordError(1280);
+ // GL_INVALID_ENUM
+ err(`GL_INVALID_ENUM in glGet${type}v: Unknown object returned from WebGL getParameter(${name_})! (error: ${e})`);
+ return;
+ }
+ }
+ break;
+
+ default:
+ GL.recordError(1280);
+ // GL_INVALID_ENUM
+ err(`GL_INVALID_ENUM in glGet${type}v: Native code calling glGet${type}v(${name_}) and it returns ${result} of type ${typeof (result)}!`);
+ return;
+ }
+ }
+ switch (type) {
+ case 1:
+ writeI53ToI64(p, ret);
+ break;
+
+ case 0:
+ HEAP32[((p) >>> 2) >>> 0] = ret;
+ break;
+
+ case 2:
+ HEAPF32[((p) >>> 2) >>> 0] = ret;
+ break;
+
+ case 4:
+ HEAP8[p >>> 0] = ret ? 1 : 0;
+ break;
+ }
+};
+
+function _emscripten_glGetIntegerv(name_, p) {
+ p >>>= 0;
+ return emscriptenWebGLGet(name_, p, 0);
+}
+
+var _glGetIntegerv = _emscripten_glGetIntegerv;
+
+function _emscripten_glGetString(name_) {
+ var ret = GL.stringCache[name_];
+ if (!ret) {
+ switch (name_) {
+ case 7939:
+ ret = stringToNewUTF8(webglGetExtensions().join(" "));
+ break;
+
+ case 7936:
+ case 7937:
+ case 37445:
+ case 37446:
+ var s = GLctx.getParameter(name_);
+ if (!s) {
+ GL.recordError(1280);
+ }
+ ret = s ? stringToNewUTF8(s) : 0;
+ break;
+
+ case 7938:
+ var webGLVersion = GLctx.getParameter(7938);
+ // return GLES version string corresponding to the version of the WebGL context
+ var glVersion = `OpenGL ES 2.0 (${webGLVersion})`;
+ if (GL.currentContext.version >= 2) glVersion = `OpenGL ES 3.0 (${webGLVersion})`;
+ ret = stringToNewUTF8(glVersion);
+ break;
+
+ case 35724:
+ var glslVersion = GLctx.getParameter(35724);
+ // extract the version number 'N.M' from the string 'WebGL GLSL ES N.M ...'
+ var ver_re = /^WebGL GLSL ES ([0-9]\.[0-9][0-9]?)(?:$| .*)/;
+ var ver_num = glslVersion.match(ver_re);
+ if (ver_num !== null) {
+ if (ver_num[1].length == 3) ver_num[1] = ver_num[1] + "0";
+ // ensure minor version has 2 digits
+ glslVersion = `OpenGL ES GLSL ES ${ver_num[1]} (${glslVersion})`;
+ }
+ ret = stringToNewUTF8(glslVersion);
+ break;
+
+ default:
+ GL.recordError(1280);
+ }
+ GL.stringCache[name_] = ret;
+ }
+ return ret;
+}
+
+var _glGetString = _emscripten_glGetString;
+
+/** @suppress {checkTypes} */ var jstoi_q = str => parseInt(str);
+
+/** @noinline */ var webglGetLeftBracePos = name => name.slice(-1) == "]" && name.lastIndexOf("[");
+
+var webglPrepareUniformLocationsBeforeFirstUse = program => {
+ var uniformLocsById = program.uniformLocsById, // Maps GLuint -> WebGLUniformLocation
+ uniformSizeAndIdsByName = program.uniformSizeAndIdsByName, // Maps name -> [uniform array length, GLuint]
+ i, j;
+ // On the first time invocation of glGetUniformLocation on this shader program:
+ // initialize cache data structures and discover which uniforms are arrays.
+ if (!uniformLocsById) {
+ // maps GLint integer locations to WebGLUniformLocations
+ program.uniformLocsById = uniformLocsById = {};
+ // maps integer locations back to uniform name strings, so that we can lazily fetch uniform array locations
+ program.uniformArrayNamesById = {};
+ var numActiveUniforms = GLctx.getProgramParameter(program, 35718);
+ for (i = 0; i < numActiveUniforms; ++i) {
+ var u = GLctx.getActiveUniform(program, i);
+ var nm = u.name;
+ var sz = u.size;
+ var lb = webglGetLeftBracePos(nm);
+ var arrayName = lb > 0 ? nm.slice(0, lb) : nm;
+ // Assign a new location.
+ var id = program.uniformIdCounter;
+ program.uniformIdCounter += sz;
+ // Eagerly get the location of the uniformArray[0] base element.
+ // The remaining indices >0 will be left for lazy evaluation to
+ // improve performance. Those may never be needed to fetch, if the
+ // application fills arrays always in full starting from the first
+ // element of the array.
+ uniformSizeAndIdsByName[arrayName] = [ sz, id ];
+ // Store placeholder integers in place that highlight that these
+ // >0 index locations are array indices pending population.
+ for (j = 0; j < sz; ++j) {
+ uniformLocsById[id] = j;
+ program.uniformArrayNamesById[id++] = arrayName;
+ }
+ }
+ }
+};
+
+function _emscripten_glGetUniformLocation(program, name) {
+ name >>>= 0;
+ name = UTF8ToString(name);
+ if (program = GL.programs[program]) {
+ webglPrepareUniformLocationsBeforeFirstUse(program);
+ var uniformLocsById = program.uniformLocsById;
+ // Maps GLuint -> WebGLUniformLocation
+ var arrayIndex = 0;
+ var uniformBaseName = name;
+ // Invariant: when populating integer IDs for uniform locations, we must
+ // maintain the precondition that arrays reside in contiguous addresses,
+ // i.e. for a 'vec4 colors[10];', colors[4] must be at location
+ // colors[0]+4. However, user might call glGetUniformLocation(program,
+ // "colors") for an array, so we cannot discover based on the user input
+ // arguments whether the uniform we are dealing with is an array. The only
+ // way to discover which uniforms are arrays is to enumerate over all the
+ // active uniforms in the program.
+ var leftBrace = webglGetLeftBracePos(name);
+ // If user passed an array accessor "[index]", parse the array index off the accessor.
+ if (leftBrace > 0) {
+ arrayIndex = jstoi_q(name.slice(leftBrace + 1)) >>> 0;
+ // "index]", coerce parseInt(']') with >>>0 to treat "foo[]" as "foo[0]" and foo[-1] as unsigned out-of-bounds.
+ uniformBaseName = name.slice(0, leftBrace);
+ }
+ // Have we cached the location of this uniform before?
+ // A pair [array length, GLint of the uniform location]
+ var sizeAndId = program.uniformSizeAndIdsByName[uniformBaseName];
+ // If a uniform with this name exists, and if its index is within the
+ // array limits (if it's even an array), query the WebGLlocation, or
+ // return an existing cached location.
+ if (sizeAndId && arrayIndex < sizeAndId[0]) {
+ arrayIndex += sizeAndId[1];
+ // Add the base location of the uniform to the array index offset.
+ if ((uniformLocsById[arrayIndex] = uniformLocsById[arrayIndex] || GLctx.getUniformLocation(program, name))) {
+ return arrayIndex;
+ }
+ }
+ } else {
+ // N.b. we are currently unable to distinguish between GL program IDs that
+ // never existed vs GL program IDs that have been deleted, so report
+ // GL_INVALID_VALUE in both cases.
+ GL.recordError(1281);
+ }
+ return -1;
+}
+
+var _glGetUniformLocation = _emscripten_glGetUniformLocation;
+
+var _emscripten_glLinkProgram = program => {
+ program = GL.programs[program];
+ GLctx.linkProgram(program);
+ // Invalidate earlier computed uniform->ID mappings, those have now become stale
+ program.uniformLocsById = 0;
+ // Mark as null-like so that glGetUniformLocation() knows to populate this again.
+ program.uniformSizeAndIdsByName = {};
+};
+
+var _glLinkProgram = _emscripten_glLinkProgram;
+
+var _emscripten_glPixelStorei = (pname, param) => {
+ if (pname == 3317) {
+ GL.unpackAlignment = param;
+ } else if (pname == 3314) {
+ GL.unpackRowLength = param;
+ }
+ GLctx.pixelStorei(pname, param);
+};
+
+var _glPixelStorei = _emscripten_glPixelStorei;
+
+var computeUnpackAlignedImageSize = (width, height, sizePerPixel) => {
+ function roundedToNextMultipleOf(x, y) {
+ return (x + y - 1) & -y;
+ }
+ var plainRowSize = (GL.unpackRowLength || width) * sizePerPixel;
+ var alignedRowSize = roundedToNextMultipleOf(plainRowSize, GL.unpackAlignment);
+ return height * alignedRowSize;
+};
+
+var colorChannelsInGlTextureFormat = format => {
+ // Micro-optimizations for size: map format to size by subtracting smallest
+ // enum value (0x1902) from all values first. Also omit the most common
+ // size value (1) from the list, which is assumed by formats not on the
+ // list.
+ var colorChannels = {
+ // 0x1902 /* GL_DEPTH_COMPONENT */ - 0x1902: 1,
+ // 0x1906 /* GL_ALPHA */ - 0x1902: 1,
+ 5: 3,
+ 6: 4,
+ // 0x1909 /* GL_LUMINANCE */ - 0x1902: 1,
+ 8: 2,
+ 29502: 3,
+ 29504: 4,
+ // 0x1903 /* GL_RED */ - 0x1902: 1,
+ 26917: 2,
+ 26918: 2,
+ // 0x8D94 /* GL_RED_INTEGER */ - 0x1902: 1,
+ 29846: 3,
+ 29847: 4
+ };
+ return colorChannels[format - 6402] || 1;
+};
+
+var heapObjectForWebGLType = type => {
+ // Micro-optimization for size: Subtract lowest GL enum number (0x1400/* GL_BYTE */) from type to compare
+ // smaller values for the heap, for shorter generated code size.
+ // Also the type HEAPU16 is not tested for explicitly, but any unrecognized type will return out HEAPU16.
+ // (since most types are HEAPU16)
+ type -= 5120;
+ if (type == 0) return HEAP8;
+ if (type == 1) return HEAPU8;
+ if (type == 2) return HEAP16;
+ if (type == 4) return HEAP32;
+ if (type == 6) return HEAPF32;
+ if (type == 5 || type == 28922 || type == 28520 || type == 30779 || type == 30782) return HEAPU32;
+ return HEAPU16;
+};
+
+var toTypedArrayIndex = (pointer, heap) => pointer >>> (31 - Math.clz32(heap.BYTES_PER_ELEMENT));
+
+var emscriptenWebGLGetTexPixelData = (type, format, width, height, pixels, internalFormat) => {
+ var heap = heapObjectForWebGLType(type);
+ var sizePerPixel = colorChannelsInGlTextureFormat(format) * heap.BYTES_PER_ELEMENT;
+ var bytes = computeUnpackAlignedImageSize(width, height, sizePerPixel);
+ return heap.subarray(toTypedArrayIndex(pixels, heap) >>> 0, toTypedArrayIndex(pixels + bytes, heap) >>> 0);
+};
+
+function _emscripten_glReadPixels(x, y, width, height, format, type, pixels) {
+ pixels >>>= 0;
+ if (GL.currentContext.version >= 2) {
+ if (GLctx.currentPixelPackBufferBinding) {
+ GLctx.readPixels(x, y, width, height, format, type, pixels);
+ return;
+ }
+ }
+ var pixelData = emscriptenWebGLGetTexPixelData(type, format, width, height, pixels, format);
+ if (!pixelData) {
+ GL.recordError(1280);
+ return;
+ }
+ GLctx.readPixels(x, y, width, height, format, type, pixelData);
+}
+
+var _glReadPixels = _emscripten_glReadPixels;
+
+function _emscripten_glShaderSource(shader, count, string, length) {
+ string >>>= 0;
+ length >>>= 0;
+ var source = GL.getSource(shader, count, string, length);
+ GLctx.shaderSource(GL.shaders[shader], source);
+}
+
+var _glShaderSource = _emscripten_glShaderSource;
+
+function _emscripten_glTexImage2D(target, level, internalFormat, width, height, border, format, type, pixels) {
+ pixels >>>= 0;
+ if (GL.currentContext.version >= 2) {
+ if (GLctx.currentPixelUnpackBufferBinding) {
+ GLctx.texImage2D(target, level, internalFormat, width, height, border, format, type, pixels);
+ return;
+ }
+ }
+ var pixelData = pixels ? emscriptenWebGLGetTexPixelData(type, format, width, height, pixels, internalFormat) : null;
+ GLctx.texImage2D(target, level, internalFormat, width, height, border, format, type, pixelData);
+}
+
+var _glTexImage2D = _emscripten_glTexImage2D;
+
+var _emscripten_glTexParameteri = (x0, x1, x2) => GLctx.texParameteri(x0, x1, x2);
+
+var _glTexParameteri = _emscripten_glTexParameteri;
+
+var _emscripten_glTexStorage2D = (x0, x1, x2, x3, x4) => GLctx.texStorage2D(x0, x1, x2, x3, x4);
+
+var _glTexStorage2D = _emscripten_glTexStorage2D;
+
+var webglGetUniformLocation = location => {
+ var p = GLctx.currentProgram;
+ if (p) {
+ var webglLoc = p.uniformLocsById[location];
+ // p.uniformLocsById[location] stores either an integer, or a
+ // WebGLUniformLocation.
+ // If an integer, we have not yet bound the location, so do it now. The
+ // integer value specifies the array index we should bind to.
+ if (typeof webglLoc == "number") {
+ p.uniformLocsById[location] = webglLoc = GLctx.getUniformLocation(p, p.uniformArrayNamesById[location] + (webglLoc > 0 ? `[${webglLoc}]` : ""));
+ }
+ // Else an already cached WebGLUniformLocation, return it.
+ return webglLoc;
+ } else {
+ GL.recordError(1282);
+ }
+};
+
+var _emscripten_glUniform1i = (location, v0) => {
+ GLctx.uniform1i(webglGetUniformLocation(location), v0);
+};
+
+var _glUniform1i = _emscripten_glUniform1i;
+
+var _emscripten_glUseProgram = program => {
+ program = GL.programs[program];
+ GLctx.useProgram(program);
+ // Record the currently active program so that we can access the uniform
+ // mapping table of that program.
+ GLctx.currentProgram = program;
+};
+
+var _glUseProgram = _emscripten_glUseProgram;
+
+function _emscripten_glVertexAttribPointer(index, size, type, normalized, stride, ptr) {
+ ptr >>>= 0;
+ var cb = GL.currentContext.clientBuffers[index];
+ if (!GLctx.currentArrayBufferBinding) {
+ cb.size = size;
+ cb.type = type;
+ cb.normalized = normalized;
+ cb.stride = stride;
+ cb.ptr = ptr;
+ cb.clientside = true;
+ cb.vertexAttribPointerAdaptor = function(index, size, type, normalized, stride, ptr) {
+ this.vertexAttribPointer(index, size, type, normalized, stride, ptr);
+ };
+ return;
+ }
+ cb.clientside = false;
+ GLctx.vertexAttribPointer(index, size, type, !!normalized, stride, ptr);
+}
+
+var _glVertexAttribPointer = _emscripten_glVertexAttribPointer;
+
+var _emscripten_glViewport = (x0, x1, x2, x3) => GLctx.viewport(x0, x1, x2, x3);
+
+var _glViewport = _emscripten_glViewport;
+
+function _random_get(buffer, size) {
+ buffer >>>= 0;
+ size >>>= 0;
+ try {
+ randomFill(HEAPU8.subarray(buffer >>> 0, buffer + size >>> 0));
+ return 0;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return e.errno;
+ }
+}
+
+var _wgpuBufferGetSize = function(bufferPtr) {
+ bufferPtr >>>= 0;
+ var ret = (() => {
+ var buffer = WebGPU.getJsObject(bufferPtr);
+ // 64-bit
+ return buffer.size;
+ })();
+ return (setTempRet0((tempDouble = ret, (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0)),
+ ret >>> 0);
+};
+
+var _wgpuBufferGetUsage = function(bufferPtr) {
+ bufferPtr >>>= 0;
+ var ret = (() => {
+ var buffer = WebGPU.getJsObject(bufferPtr);
+ return buffer.usage;
+ })();
+ return (setTempRet0((tempDouble = ret, (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0)),
+ ret >>> 0);
+};
+
+function _wgpuCommandEncoderBeginComputePass(encoderPtr, descriptor) {
+ encoderPtr >>>= 0;
+ descriptor >>>= 0;
+ var desc;
+ if (descriptor) {
+ desc = {
+ "label": WebGPU.makeStringFromOptionalStringView(descriptor + 4),
+ "timestampWrites": WebGPU.makePassTimestampWrites(HEAPU32[(((descriptor) + (12)) >>> 2) >>> 0])
+ };
+ }
+ var commandEncoder = WebGPU.getJsObject(encoderPtr);
+ var ptr = _emwgpuCreateComputePassEncoder(0);
+ WebGPU.Internals.jsObjectInsert(ptr, commandEncoder.beginComputePass(desc));
+ return ptr;
+}
+
+function _wgpuCommandEncoderCopyBufferToBuffer(encoderPtr, srcPtr, srcOffset_low, srcOffset_high, dstPtr, dstOffset_low, dstOffset_high, size_low, size_high) {
+ encoderPtr >>>= 0;
+ srcPtr >>>= 0;
+ var srcOffset = convertI32PairToI53Checked(srcOffset_low, srcOffset_high);
+ dstPtr >>>= 0;
+ var dstOffset = convertI32PairToI53Checked(dstOffset_low, dstOffset_high);
+ var size = convertI32PairToI53Checked(size_low, size_high);
+ var commandEncoder = WebGPU.getJsObject(encoderPtr);
+ var src = WebGPU.getJsObject(srcPtr);
+ var dst = WebGPU.getJsObject(dstPtr);
+ commandEncoder.copyBufferToBuffer(src, srcOffset, dst, dstOffset, size);
+}
+
+function _wgpuCommandEncoderCopyTextureToBuffer(encoderPtr, srcPtr, dstPtr, copySizePtr) {
+ encoderPtr >>>= 0;
+ srcPtr >>>= 0;
+ dstPtr >>>= 0;
+ copySizePtr >>>= 0;
+ var commandEncoder = WebGPU.getJsObject(encoderPtr);
+ var copySize = WebGPU.makeExtent3D(copySizePtr);
+ commandEncoder.copyTextureToBuffer(WebGPU.makeTexelCopyTextureInfo(srcPtr), WebGPU.makeTexelCopyBufferInfo(dstPtr), copySize);
+}
+
+function _wgpuCommandEncoderCopyTextureToTexture(encoderPtr, srcPtr, dstPtr, copySizePtr) {
+ encoderPtr >>>= 0;
+ srcPtr >>>= 0;
+ dstPtr >>>= 0;
+ copySizePtr >>>= 0;
+ var commandEncoder = WebGPU.getJsObject(encoderPtr);
+ var copySize = WebGPU.makeExtent3D(copySizePtr);
+ commandEncoder.copyTextureToTexture(WebGPU.makeTexelCopyTextureInfo(srcPtr), WebGPU.makeTexelCopyTextureInfo(dstPtr), copySize);
+}
+
+function _wgpuCommandEncoderFinish(encoderPtr, descriptor) {
+ encoderPtr >>>= 0;
+ descriptor >>>= 0;
+ // TODO: Use the descriptor.
+ var commandEncoder = WebGPU.getJsObject(encoderPtr);
+ var ptr = _emwgpuCreateCommandBuffer(0);
+ WebGPU.Internals.jsObjectInsert(ptr, commandEncoder.finish());
+ return ptr;
+}
+
+function _wgpuCommandEncoderResolveQuerySet(encoderPtr, querySetPtr, firstQuery, queryCount, destinationPtr, destinationOffset_low, destinationOffset_high) {
+ encoderPtr >>>= 0;
+ querySetPtr >>>= 0;
+ destinationPtr >>>= 0;
+ var destinationOffset = convertI32PairToI53Checked(destinationOffset_low, destinationOffset_high);
+ var commandEncoder = WebGPU.getJsObject(encoderPtr);
+ var querySet = WebGPU.getJsObject(querySetPtr);
+ var destination = WebGPU.getJsObject(destinationPtr);
+ commandEncoder.resolveQuerySet(querySet, firstQuery, queryCount, destination, destinationOffset);
+}
+
+function _wgpuComputePassEncoderDispatchWorkgroups(passPtr, x, y, z) {
+ passPtr >>>= 0;
+ var pass = WebGPU.getJsObject(passPtr);
+ pass.dispatchWorkgroups(x, y, z);
+}
+
+function _wgpuComputePassEncoderEnd(passPtr) {
+ passPtr >>>= 0;
+ var pass = WebGPU.getJsObject(passPtr);
+ pass.end();
+}
+
+function _wgpuComputePassEncoderSetBindGroup(passPtr, groupIndex, groupPtr, dynamicOffsetCount, dynamicOffsetsPtr) {
+ passPtr >>>= 0;
+ groupPtr >>>= 0;
+ dynamicOffsetCount >>>= 0;
+ dynamicOffsetsPtr >>>= 0;
+ var pass = WebGPU.getJsObject(passPtr);
+ var group = WebGPU.getJsObject(groupPtr);
+ if (dynamicOffsetCount == 0) {
+ pass.setBindGroup(groupIndex, group);
+ } else {
+ pass.setBindGroup(groupIndex, group, HEAPU32, ((dynamicOffsetsPtr) >>> 2), dynamicOffsetCount);
+ }
+}
+
+function _wgpuComputePassEncoderSetPipeline(passPtr, pipelinePtr) {
+ passPtr >>>= 0;
+ pipelinePtr >>>= 0;
+ var pass = WebGPU.getJsObject(passPtr);
+ var pipeline = WebGPU.getJsObject(pipelinePtr);
+ pass.setPipeline(pipeline);
+}
+
+var _wgpuDeviceCreateBindGroup = function(devicePtr, descriptor) {
+ devicePtr >>>= 0;
+ descriptor >>>= 0;
+ function makeEntry(entryPtr) {
+ var bufferPtr = HEAPU32[(((entryPtr) + (8)) >>> 2) >>> 0];
+ var samplerPtr = HEAPU32[(((entryPtr) + (32)) >>> 2) >>> 0];
+ var textureViewPtr = HEAPU32[(((entryPtr) + (36)) >>> 2) >>> 0];
+ var externalTexturePtr = 0;
+ WebGPU.iterateExtensions(entryPtr, {
+ 14: ptr => {
+ externalTexturePtr = HEAPU32[(((ptr) + (8)) >>> 2) >>> 0];
+ }
+ });
+ var resource;
+ if (bufferPtr) {
+ // Note the sentinel UINT64_MAX will be read as -1.
+ var size = readI53FromI64((entryPtr) + (24));
+ if (size == -1) size = undefined;
+ resource = {
+ "buffer": WebGPU.getJsObject(bufferPtr),
+ "offset": readI53FromI64((entryPtr) + (16)),
+ "size": size
+ };
+ } else {
+ resource = WebGPU.getJsObject(samplerPtr || textureViewPtr || externalTexturePtr);
+ }
+ return {
+ "binding": HEAPU32[(((entryPtr) + (4)) >>> 2) >>> 0],
+ "resource": resource
+ };
+ }
+ function makeEntries(count, entriesPtrs) {
+ var entries = [];
+ for (var i = 0; i < count; ++i) {
+ entries.push(makeEntry(entriesPtrs + 40 * i));
+ }
+ return entries;
+ }
+ var desc = {
+ "label": WebGPU.makeStringFromOptionalStringView(descriptor + 4),
+ "layout": WebGPU.getJsObject(HEAPU32[(((descriptor) + (12)) >>> 2) >>> 0]),
+ "entries": makeEntries(HEAPU32[(((descriptor) + (16)) >>> 2) >>> 0], HEAPU32[(((descriptor) + (20)) >>> 2) >>> 0])
+ };
+ var device = WebGPU.getJsObject(devicePtr);
+ var ptr = _emwgpuCreateBindGroup(0);
+ WebGPU.Internals.jsObjectInsert(ptr, device.createBindGroup(desc));
+ return ptr;
+};
+
+function _wgpuDeviceCreateBindGroupLayout(devicePtr, descriptor) {
+ devicePtr >>>= 0;
+ descriptor >>>= 0;
+ function makeBufferEntry(substructPtr) {
+ var typeInt = HEAPU32[(((substructPtr) + (4)) >>> 2) >>> 0];
+ if (!typeInt) return undefined;
+ return {
+ "type": WebGPU.BufferBindingType[typeInt],
+ "hasDynamicOffset": !!(HEAPU32[(((substructPtr) + (8)) >>> 2) >>> 0]),
+ "minBindingSize": readI53FromI64((substructPtr) + (16))
+ };
+ }
+ function makeSamplerEntry(substructPtr) {
+ var typeInt = HEAPU32[(((substructPtr) + (4)) >>> 2) >>> 0];
+ if (!typeInt) return undefined;
+ return {
+ "type": WebGPU.SamplerBindingType[typeInt]
+ };
+ }
+ function makeTextureEntry(substructPtr) {
+ var sampleTypeInt = HEAPU32[(((substructPtr) + (4)) >>> 2) >>> 0];
+ if (!sampleTypeInt) return undefined;
+ return {
+ "sampleType": WebGPU.TextureSampleType[sampleTypeInt],
+ "viewDimension": WebGPU.TextureViewDimension[HEAP32[(((substructPtr) + (8)) >>> 2) >>> 0]],
+ "multisampled": !!(HEAPU32[(((substructPtr) + (12)) >>> 2) >>> 0])
+ };
+ }
+ function makeStorageTextureEntry(substructPtr) {
+ var accessInt = HEAPU32[(((substructPtr) + (4)) >>> 2) >>> 0];
+ if (!accessInt) return undefined;
+ return {
+ "access": WebGPU.StorageTextureAccess[accessInt],
+ "format": WebGPU.TextureFormat[HEAP32[(((substructPtr) + (8)) >>> 2) >>> 0]],
+ "viewDimension": WebGPU.TextureViewDimension[HEAP32[(((substructPtr) + (12)) >>> 2) >>> 0]]
+ };
+ }
+ function makeEntry(entryPtr) {
+ var entry = {
+ "binding": HEAPU32[(((entryPtr) + (4)) >>> 2) >>> 0],
+ "visibility": HEAPU32[(((entryPtr) + (8)) >>> 2) >>> 0],
+ "buffer": makeBufferEntry(entryPtr + 24),
+ "sampler": makeSamplerEntry(entryPtr + 48),
+ "texture": makeTextureEntry(entryPtr + 56),
+ "storageTexture": makeStorageTextureEntry(entryPtr + 72)
+ };
+ WebGPU.iterateExtensions(entryPtr, {
+ 13: ptr => {
+ entry["externalTexture"] = {};
+ }
+ });
+ return entry;
+ }
+ function makeEntries(count, entriesPtrs) {
+ var entries = [];
+ for (var i = 0; i < count; ++i) {
+ entries.push(makeEntry(entriesPtrs + 88 * i));
+ }
+ return entries;
+ }
+ var desc = {
+ "label": WebGPU.makeStringFromOptionalStringView(descriptor + 4),
+ "entries": makeEntries(HEAPU32[(((descriptor) + (12)) >>> 2) >>> 0], HEAPU32[(((descriptor) + (16)) >>> 2) >>> 0])
+ };
+ var device = WebGPU.getJsObject(devicePtr);
+ var ptr = _emwgpuCreateBindGroupLayout(0);
+ WebGPU.Internals.jsObjectInsert(ptr, device.createBindGroupLayout(desc));
+ return ptr;
+}
+
+function _wgpuDeviceCreateCommandEncoder(devicePtr, descriptor) {
+ devicePtr >>>= 0;
+ descriptor >>>= 0;
+ var desc;
+ if (descriptor) {
+ desc = {
+ "label": WebGPU.makeStringFromOptionalStringView(descriptor + 4)
+ };
+ }
+ var device = WebGPU.getJsObject(devicePtr);
+ var ptr = _emwgpuCreateCommandEncoder(0);
+ WebGPU.Internals.jsObjectInsert(ptr, device.createCommandEncoder(desc));
+ return ptr;
+}
+
+function _wgpuDeviceCreateComputePipeline(devicePtr, descriptor) {
+ devicePtr >>>= 0;
+ descriptor >>>= 0;
+ var desc = WebGPU.makeComputePipelineDesc(descriptor);
+ var device = WebGPU.getJsObject(devicePtr);
+ var ptr = _emwgpuCreateComputePipeline(0);
+ WebGPU.Internals.jsObjectInsert(ptr, device.createComputePipeline(desc));
+ return ptr;
+}
+
+function _wgpuDeviceCreatePipelineLayout(devicePtr, descriptor) {
+ devicePtr >>>= 0;
+ descriptor >>>= 0;
+ var bglCount = HEAPU32[(((descriptor) + (12)) >>> 2) >>> 0];
+ var bglPtr = HEAPU32[(((descriptor) + (16)) >>> 2) >>> 0];
+ var bgls = [];
+ for (var i = 0; i < bglCount; ++i) {
+ bgls.push(WebGPU.getJsObject(HEAPU32[(((bglPtr) + (4 * i)) >>> 2) >>> 0]));
+ }
+ var desc = {
+ "label": WebGPU.makeStringFromOptionalStringView(descriptor + 4),
+ "bindGroupLayouts": bgls
+ };
+ var device = WebGPU.getJsObject(devicePtr);
+ var ptr = _emwgpuCreatePipelineLayout(0);
+ WebGPU.Internals.jsObjectInsert(ptr, device.createPipelineLayout(desc));
+ return ptr;
+}
+
+function _wgpuDeviceCreateQuerySet(devicePtr, descriptor) {
+ devicePtr >>>= 0;
+ descriptor >>>= 0;
+ var desc = {
+ "type": WebGPU.QueryType[HEAP32[(((descriptor) + (12)) >>> 2) >>> 0]],
+ "count": HEAPU32[(((descriptor) + (16)) >>> 2) >>> 0]
+ };
+ var device = WebGPU.getJsObject(devicePtr);
+ var ptr = _emwgpuCreateQuerySet(0);
+ WebGPU.Internals.jsObjectInsert(ptr, device.createQuerySet(desc));
+ return ptr;
+}
+
+function _wgpuDeviceCreateTexture(devicePtr, descriptor) {
+ devicePtr >>>= 0;
+ descriptor >>>= 0;
+ var nextInChainPtr = HEAPU32[((descriptor) >>> 2) >>> 0];
+ var textureBindingViewDimension;
+ if (nextInChainPtr !== 0) {
+ var sType = HEAP32[(((nextInChainPtr) + (4)) >>> 2) >>> 0];
+ var textureBindingViewDimensionDescriptor = nextInChainPtr;
+ textureBindingViewDimension = WebGPU.TextureViewDimension[HEAP32[(((textureBindingViewDimensionDescriptor) + (8)) >>> 2) >>> 0]];
+ }
+ var desc = {
+ "label": WebGPU.makeStringFromOptionalStringView(descriptor + 4),
+ "size": WebGPU.makeExtent3D(descriptor + 28),
+ "mipLevelCount": HEAPU32[(((descriptor) + (44)) >>> 2) >>> 0],
+ "sampleCount": HEAPU32[(((descriptor) + (48)) >>> 2) >>> 0],
+ "dimension": WebGPU.TextureDimension[HEAP32[(((descriptor) + (24)) >>> 2) >>> 0]],
+ "format": WebGPU.TextureFormat[HEAP32[(((descriptor) + (40)) >>> 2) >>> 0]],
+ "usage": HEAPU32[(((descriptor) + (16)) >>> 2) >>> 0],
+ "textureBindingViewDimension": textureBindingViewDimension
+ };
+ var viewFormatCount = HEAPU32[(((descriptor) + (52)) >>> 2) >>> 0];
+ if (viewFormatCount) {
+ var viewFormatsPtr = HEAPU32[(((descriptor) + (56)) >>> 2) >>> 0];
+ // viewFormatsPtr pointer to an array of TextureFormat which is an enum of size uint32_t
+ desc["viewFormats"] = Array.from(HEAP32.subarray((((viewFormatsPtr) >>> 2)) >>> 0, ((viewFormatsPtr + viewFormatCount * 4) >>> 2) >>> 0), format => WebGPU.TextureFormat[format]);
+ }
+ var device = WebGPU.getJsObject(devicePtr);
+ var ptr = _emwgpuCreateTexture(0);
+ WebGPU.Internals.jsObjectInsert(ptr, device.createTexture(desc));
+ return ptr;
+}
+
+function _wgpuDeviceGetAdapterInfo(devicePtr, adapterInfo) {
+ devicePtr >>>= 0;
+ adapterInfo >>>= 0;
+ var device = WebGPU.getJsObject(devicePtr);
+ WebGPU.fillAdapterInfoStruct(device.adapterInfo, adapterInfo);
+ return 1;
+}
+
+function _wgpuDeviceGetLimits(devicePtr, limitsOutPtr) {
+ devicePtr >>>= 0;
+ limitsOutPtr >>>= 0;
+ var device = WebGPU.getJsObject(devicePtr);
+ WebGPU.fillLimitStruct(device.limits, limitsOutPtr);
+ return 1;
+}
+
+function _wgpuDeviceHasFeature(devicePtr, featureEnumValue) {
+ devicePtr >>>= 0;
+ var device = WebGPU.getJsObject(devicePtr);
+ return device.features.has(WebGPU.FeatureName[featureEnumValue]);
+}
+
+var _wgpuQueueSubmit = function(queuePtr, commandCount, commands) {
+ queuePtr >>>= 0;
+ commandCount >>>= 0;
+ commands >>>= 0;
+ var queue = WebGPU.getJsObject(queuePtr);
+ var cmds = Array.from(HEAP32.subarray((((commands) >>> 2)) >>> 0, ((commands + commandCount * 4) >>> 2) >>> 0), id => WebGPU.getJsObject(id));
+ queue.submit(cmds);
+};
+
+function _wgpuQueueWriteBuffer(queuePtr, bufferPtr, bufferOffset_low, bufferOffset_high, data, size) {
+ queuePtr >>>= 0;
+ bufferPtr >>>= 0;
+ var bufferOffset = convertI32PairToI53Checked(bufferOffset_low, bufferOffset_high);
+ data >>>= 0;
+ size >>>= 0;
+ var queue = WebGPU.getJsObject(queuePtr);
+ var buffer = WebGPU.getJsObject(bufferPtr);
+ // There is a size limitation for ArrayBufferView. Work around by passing in a subarray
+ // instead of the whole heap. crbug.com/1201109
+ var subarray = HEAPU8.subarray(data >>> 0, data + size >>> 0);
+ queue.writeBuffer(buffer, bufferOffset, subarray, 0, size);
+}
+
+function _wgpuQueueWriteTexture(queuePtr, destinationPtr, data, dataSize, dataLayoutPtr, writeSizePtr) {
+ queuePtr >>>= 0;
+ destinationPtr >>>= 0;
+ data >>>= 0;
+ dataSize >>>= 0;
+ dataLayoutPtr >>>= 0;
+ writeSizePtr >>>= 0;
+ var queue = WebGPU.getJsObject(queuePtr);
+ var destination = WebGPU.makeTexelCopyTextureInfo(destinationPtr);
+ var dataLayout = WebGPU.makeTexelCopyBufferLayout(dataLayoutPtr);
+ var writeSize = WebGPU.makeExtent3D(writeSizePtr);
+ // This subarray isn't strictly necessary, but helps work around an issue
+ // where Chromium makes a copy of the entire heap. crbug.com/1134457
+ var subarray = HEAPU8.subarray(data >>> 0, data + dataSize >>> 0);
+ queue.writeTexture(destination, subarray, dataLayout, writeSize);
+}
+
+function _wgpuTextureCreateView(texturePtr, descriptor) {
+ texturePtr >>>= 0;
+ descriptor >>>= 0;
+ var desc;
+ if (descriptor) {
+ var swizzle;
+ var nextInChainPtr = HEAPU32[((descriptor) >>> 2) >>> 0];
+ if (nextInChainPtr !== 0) {
+ var sType = HEAP32[(((nextInChainPtr) + (4)) >>> 2) >>> 0];
+ var swizzleDescriptor = nextInChainPtr;
+ var swizzlePtr = swizzleDescriptor + 8;
+ var r = WebGPU.ComponentSwizzle[HEAP32[((swizzlePtr) >>> 2) >>> 0]] || "r";
+ var g = WebGPU.ComponentSwizzle[HEAP32[(((swizzlePtr) + (4)) >>> 2) >>> 0]] || "g";
+ var b = WebGPU.ComponentSwizzle[HEAP32[(((swizzlePtr) + (8)) >>> 2) >>> 0]] || "b";
+ var a = WebGPU.ComponentSwizzle[HEAP32[(((swizzlePtr) + (12)) >>> 2) >>> 0]] || "a";
+ swizzle = `${r}${g}${b}${a}`;
+ }
+ var mipLevelCount = HEAPU32[(((descriptor) + (24)) >>> 2) >>> 0];
+ var arrayLayerCount = HEAPU32[(((descriptor) + (32)) >>> 2) >>> 0];
+ desc = {
+ "label": WebGPU.makeStringFromOptionalStringView(descriptor + 4),
+ "format": WebGPU.TextureFormat[HEAP32[(((descriptor) + (12)) >>> 2) >>> 0]],
+ "dimension": WebGPU.TextureViewDimension[HEAP32[(((descriptor) + (16)) >>> 2) >>> 0]],
+ "baseMipLevel": HEAPU32[(((descriptor) + (20)) >>> 2) >>> 0],
+ "mipLevelCount": mipLevelCount === 4294967295 ? undefined : mipLevelCount,
+ "baseArrayLayer": HEAPU32[(((descriptor) + (28)) >>> 2) >>> 0],
+ "arrayLayerCount": arrayLayerCount === 4294967295 ? undefined : arrayLayerCount,
+ "aspect": WebGPU.TextureAspect[HEAP32[(((descriptor) + (36)) >>> 2) >>> 0]],
+ "usage": HEAPU32[(((descriptor) + (40)) >>> 2) >>> 0],
+ "swizzle": swizzle
+ };
+ }
+ var texture = WebGPU.getJsObject(texturePtr);
+ var ptr = _emwgpuCreateTextureView(0);
+ WebGPU.Internals.jsObjectInsert(ptr, texture.createView(desc));
+ return ptr;
+}
+
+function _wgpuTextureDestroy(texturePtr) {
+ texturePtr >>>= 0;
+ WebGPU.getJsObject(texturePtr).destroy();
+}
+
+function _wgpuTextureGetDepthOrArrayLayers(texturePtr) {
+ texturePtr >>>= 0;
+ var texture = WebGPU.getJsObject(texturePtr);
+ return texture.depthOrArrayLayers;
+}
+
+function _wgpuTextureGetFormat(texturePtr) {
+ texturePtr >>>= 0;
+ var texture = WebGPU.getJsObject(texturePtr);
+ // Should return the enum integer instead of string.
+ return WebGPU.TextureFormat.indexOf(texture.format);
+}
+
+function _wgpuTextureGetHeight(texturePtr) {
+ texturePtr >>>= 0;
+ var texture = WebGPU.getJsObject(texturePtr);
+ return texture.height;
+}
+
+function _wgpuTextureGetWidth(texturePtr) {
+ texturePtr >>>= 0;
+ var texture = WebGPU.getJsObject(texturePtr);
+ return texture.width;
+}
+
+var getCFunc = ident => {
+ var func = Module["_" + ident];
+ // closure exported function
+ return func;
+};
+
+var writeArrayToMemory = (array, buffer) => {
+ HEAP8.set(array, buffer >>> 0);
+};
+
+/**
+ * @param {string|null=} returnType
+ * @param {Array=} argTypes
+ * @param {Array=} args
+ * @param {Object=} opts
+ */ var ccall = (ident, returnType, argTypes, args, opts) => {
+ // For fast lookup of conversion functions
+ var toC = {
+ "string": str => {
+ var ret = 0;
+ if (str !== null && str !== undefined && str !== 0) {
+ // null string
+ ret = stringToUTF8OnStack(str);
+ }
+ return ret;
+ },
+ "array": arr => {
+ var ret = stackAlloc(arr.length);
+ writeArrayToMemory(arr, ret);
+ return ret;
+ }
+ };
+ function convertReturnValue(ret) {
+ if (returnType === "string") {
+ return UTF8ToString(ret);
+ }
+ if (returnType === "pointer") return ret >>> 0;
+ if (returnType === "boolean") return Boolean(ret);
+ return ret;
+ }
+ var func = getCFunc(ident);
+ var cArgs = [];
+ var stack = 0;
+ if (args) {
+ for (var i = 0; i < args.length; i++) {
+ var converter = toC[argTypes[i]];
+ if (converter) {
+ if (stack === 0) stack = stackSave();
+ cArgs[i] = converter(args[i]);
+ } else {
+ cArgs[i] = args[i];
+ }
+ }
+ }
+ // Data for a previous async operation that was in flight before us.
+ var previousAsync = Asyncify.currData;
+ var ret = func(...cArgs);
+ function onDone(ret) {
+ runtimeKeepalivePop();
+ if (stack !== 0) stackRestore(stack);
+ return convertReturnValue(ret);
+ }
+ var asyncMode = opts?.async;
+ // Keep the runtime alive through all calls. Note that this call might not be
+ // async, but for simplicity we push and pop in all calls.
+ runtimeKeepalivePush();
+ if (Asyncify.currData != previousAsync) {
+ // This is a new async operation. The wasm is paused and has unwound its stack.
+ // We need to return a Promise that resolves the return value
+ // once the stack is rewound and execution finishes.
+ return Asyncify.whenDone().then(onDone);
+ }
+ ret = onDone(ret);
+ // If this is an async ccall, ensure we return a promise
+ if (asyncMode) return Promise.resolve(ret);
+ return ret;
+};
+
+var FS_createPath = (...args) => FS.createPath(...args);
+
+var FS_unlink = (...args) => FS.unlink(...args);
+
+var FS_createLazyFile = (...args) => FS.createLazyFile(...args);
+
+var FS_createDevice = (...args) => FS.createDevice(...args);
+
+FS.createPreloadedFile = FS_createPreloadedFile;
+
+FS.preloadFile = FS_preloadFile;
+
+FS.staticInit();
+
+// Signal GL rendering layer that processing of a new frame is about to
+// start. This helps it optimize VBO double-buffering and reduce GPU stalls.
+registerPreMainLoop(() => GL.newRenderingFrameStarted());
+
+// End JS library code
+// include: postlibrary.js
+// This file is included after the automatically-generated JS library code
+// but before the wasm module is created.
+{
+ // Begin ATMODULES hooks
+ if (Module["preloadPlugins"]) preloadPlugins = Module["preloadPlugins"];
+ if (Module["noExitRuntime"]) noExitRuntime = Module["noExitRuntime"];
+ if (Module["print"]) out = Module["print"];
+ if (Module["printErr"]) err = Module["printErr"];
+ if (Module["wasmBinary"]) wasmBinary = Module["wasmBinary"];
+ // End ATMODULES hooks
+ if (Module["arguments"]) arguments_ = Module["arguments"];
+ if (Module["thisProgram"]) thisProgram = Module["thisProgram"];
+ if (Module["preInit"]) {
+ if (typeof Module["preInit"] == "function") Module["preInit"] = [ Module["preInit"] ];
+ while (Module["preInit"].length > 0) {
+ Module["preInit"].shift()();
+ }
+ }
+}
+
+// Begin runtime exports
+Module["addRunDependency"] = addRunDependency;
+
+Module["removeRunDependency"] = removeRunDependency;
+
+Module["ccall"] = ccall;
+
+Module["stringToNewUTF8"] = stringToNewUTF8;
+
+Module["FS_preloadFile"] = FS_preloadFile;
+
+Module["FS_unlink"] = FS_unlink;
+
+Module["FS_createPath"] = FS_createPath;
+
+Module["FS_createDevice"] = FS_createDevice;
+
+Module["FS_createDataFile"] = FS_createDataFile;
+
+Module["FS_createLazyFile"] = FS_createLazyFile;
+
+// End runtime exports
+// Begin JS library exports
+// End JS library exports
+// end include: postlibrary.js
+var ASM_CONSTS = {
+ 2019768: () => !!Module["preinitializedWebGPUDevice"],
+ 2019819: () => {
+ const retVal = Module.LLM_CANCEL_FLAG;
+ Module.LLM_CANCEL_FLAG = undefined;
+ return retVal || 0;
+ },
+ 2019918: $0 => {
+ const device = WebGPU.getJsObject($0);
+ return device.features.has("subgroups");
+ },
+ 2020002: () => !!Module["preinitializedWebGPUDevice"],
+ 2020053: () => {
+ specialHTMLTargets["#canvas"] = Module.canvas;
+ }
+};
+
+function __asyncjs__InvokeReadDataFn(fn, offset, size, mode) {
+ return Asyncify.handleAsync(async () => await Emval.toValue(fn)(offset, size, mode));
+}
+
+function JsProgressListener(text, done) {
+ Module._userProgressListener(UTF8ToString(text), done);
+}
+
+function DefaultErrorReporter(message) {
+ throw new Error(UTF8ToString(message));
+}
+
+function ThrowError(val_handle) {
+ const error = Emval.toValue(val_handle);
+ throw error;
+}
+
+function JsOnEmptyPacketListener(output_stream_name, timestamp) {
+ Module._wrapEmptyPacketListenerOutput(output_stream_name, timestamp);
+}
+
+function JsOnVectorFinishedListener(output_stream_name, timestamp) {
+ Module._wrapSimpleListenerOutput(output_stream_name, undefined, true, timestamp);
+}
+
+function JsOnSimpleListenerBool(output_stream_name, out_data, timestamp) {
+ Module._wrapSimpleListenerOutput(output_stream_name, out_data, timestamp);
+}
+
+function JsOnVectorListenerBool(output_stream_name, out_data, timestamp) {
+ Module._wrapSimpleListenerOutput(output_stream_name, out_data, false, timestamp);
+}
+
+function JsOnSimpleListenerInt(output_stream_name, out_data, timestamp) {
+ Module._wrapSimpleListenerOutput(output_stream_name, out_data, timestamp);
+}
+
+function JsOnVectorListenerInt(output_stream_name, out_data, timestamp) {
+ Module._wrapSimpleListenerOutput(output_stream_name, out_data, false, timestamp);
+}
+
+function JsOnSimpleListenerUint(output_stream_name, out_data, timestamp) {
+ Module._wrapSimpleListenerOutput(output_stream_name, out_data, timestamp);
+}
+
+function JsOnVectorListenerUint(output_stream_name, out_data, timestamp) {
+ Module._wrapSimpleListenerOutput(output_stream_name, out_data, false, timestamp);
+}
+
+function JsOnSimpleListenerDouble(output_stream_name, out_data, timestamp) {
+ Module._wrapSimpleListenerOutput(output_stream_name, out_data, timestamp);
+}
+
+function JsOnVectorListenerDouble(output_stream_name, out_data, timestamp) {
+ Module._wrapSimpleListenerOutput(output_stream_name, out_data, false, timestamp);
+}
+
+function JsOnSimpleListenerFloat(output_stream_name, out_data, timestamp) {
+ Module._wrapSimpleListenerOutput(output_stream_name, out_data, timestamp);
+}
+
+function JsOnVectorListenerFloat(output_stream_name, out_data, timestamp) {
+ Module._wrapSimpleListenerOutput(output_stream_name, out_data, false, timestamp);
+}
+
+function JsOnSimpleListenerString(output_stream_name, out_data, timestamp) {
+ Module._wrapSimpleListenerOutput(output_stream_name, UTF8ToString(out_data), timestamp);
+}
+
+function JsOnVectorListenerString(output_stream_name, out_data, timestamp) {
+ Module._wrapSimpleListenerOutput(output_stream_name, UTF8ToString(out_data), false, timestamp);
+}
+
+function JsOnVectorListenerProto(output_stream_name, proto_ptr, proto_size, make_deep_copy, timestamp) {
+ const newProtoArray = make_deep_copy ? Module.HEAPU8.slice(proto_ptr, proto_ptr + proto_size) : new Uint8Array(Module.HEAPU8.buffer, proto_ptr, proto_size);
+ Module._wrapSimpleListenerOutput(output_stream_name, newProtoArray, false, timestamp);
+}
+
+function JsWrapSimpleListeners() {
+ if (!Module._wrapSimpleListenerOutput) {
+ Module._wrapSimpleListenerOutput = (outputStreamName, ...args) => {
+ if (Module.simpleListeners) {
+ const streamName = UTF8ToString(outputStreamName);
+ if (Module.simpleListeners[streamName]) {
+ Module.simpleListeners[streamName](...args);
+ }
+ }
+ };
+ }
+ if (!Module._wrapEmptyPacketListenerOutput) {
+ Module._wrapEmptyPacketListenerOutput = (outputStreamName, timestamp) => {
+ if (Module.emptyPacketListeners) {
+ const streamName = UTF8ToString(outputStreamName);
+ if (Module.emptyPacketListeners[streamName]) {
+ Module.emptyPacketListeners[streamName](timestamp);
+ }
+ }
+ };
+ }
+}
+
+function JsOnSimpleListenerBinaryArray(output_stream_name, binary_ptr, binary_size, make_deep_copy, timestamp) {
+ const newProtoArray = make_deep_copy ? Module.HEAPU8.slice(binary_ptr, binary_ptr + binary_size) : new Uint8Array(Module.HEAPU8.buffer, binary_ptr, binary_size);
+ Module._wrapSimpleListenerOutput(output_stream_name, newProtoArray, timestamp);
+}
+
+function __asyncjs__CallReadDataFn(fn, offset, size, mode) {
+ return Asyncify.handleAsync(async () => await Emval.toValue(fn)(offset, size, mode));
+}
+
+function __asyncjs__mediapipe_map_buffer_jspi(buffer_handle, data) {
+ return Asyncify.handleAsync(async () => {
+ const buffer = WebGPU.getJsObject(buffer_handle);
+ if ("mapSync" in buffer) {
+ buffer.mapSync(GPUMapMode.READ);
+ } else {
+ await buffer.mapAsync(GPUMapMode.READ);
+ }
+ const mapped = buffer.getMappedRange();
+ HEAPU8.set(new Uint8Array(mapped), data >>> 0);
+ buffer.unmap();
+ });
+}
+
+function JsGetDeviceMinSubgroupSize(deviceId) {
+ const device = WebGPU.getJsObject(deviceId);
+ return device.adapterInfo.subgroupMinSize || device.limits.minSubgroupSize;
+}
+
+function JsGetDeviceMaxSubgroupSize(deviceId) {
+ const device = WebGPU.getJsObject(deviceId);
+ return device.adapterInfo.subgroupMaxSize || device.limits.maxSubgroupSize;
+}
+
+function __asyncjs__ReadBufferDataJs(buffer_handle, data_ptr) {
+ return Asyncify.handleAsync(async () => {
+ const gpuReadBuffer = WebGPU.getJsObject(buffer_handle);
+ await gpuReadBuffer.mapAsync(GPUMapMode.READ);
+ const arrayBuffer = gpuReadBuffer.getMappedRange();
+ const u8view = new Uint8Array(arrayBuffer);
+ HEAPU8.set(u8view, data_ptr >>> 0 >>> 0);
+ gpuReadBuffer.unmap();
+ });
+}
+
+function GetAdapterArchitecture() {
+ const device = Module["preinitializedWebGPUDevice"];
+ const architecture = device.adapterInfo ? device.adapterInfo.architecture : "Unknown";
+ return stringToNewUTF8(architecture);
+}
+
+function GetAdapterDescription() {
+ const device = Module["preinitializedWebGPUDevice"];
+ const description = device.adapterInfo ? device.adapterInfo.description : "Unknown";
+ return stringToNewUTF8(description);
+}
+
+function GetAdapterDeviceName() {
+ const device = Module["preinitializedWebGPUDevice"];
+ const deviceName = device.adapterInfo ? device.adapterInfo.device : "Unknown";
+ return stringToNewUTF8(deviceName);
+}
+
+function GetAdapterVendor() {
+ const device = Module["preinitializedWebGPUDevice"];
+ const vendor = device.adapterInfo ? device.adapterInfo.vendor : "Unknown";
+ return stringToNewUTF8(vendor);
+}
+
+function hardware_concurrency() {
+ var concurrency = 1;
+ try {
+ concurrency = self.navigator.hardwareConcurrency;
+ } catch (e) {}
+ return concurrency;
+}
+
+function JsWrapErrorListener(code, message) {
+ if (Module.errorListener) {
+ const stringMessage = UTF8ToString(message);
+ Module.errorListener(code, stringMessage);
+ }
+}
+
+function UseBottomLeftGpuOrigin() {
+ return (Module && Module.gpuOriginForWebTexturesIsBottomLeft);
+}
+
+function custom_emscripten_dbgn(str, len) {
+ if (typeof (dbg) !== "undefined") {
+ dbg(UTF8ToString(str, len));
+ } else {
+ if (typeof (custom_dbg) === "undefined") {
+ function custom_dbg(text) {
+ console.warn.apply(console, arguments);
+ }
+ }
+ custom_dbg(UTF8ToString(str, len));
+ }
+}
+
+// Imports from the Wasm binary.
+var _free, _CreateLlmInferenceEngineConverted, _DeleteLlmInferenceEngine, _MakeSessionForPredict, _AddTextQueryChunk, _AddImageQueryChunk, _AddAudioQueryChunk, _malloc, _PredictSession, _FreeSession, _GetSizeInTokens, _wgpuDeviceAddRef, _registerModelResourcesGraphService, _bindTextureToStream, _addBoundTextureToStream, _addDoubleToInputStream, _addFloatToInputStream, _addBoolToInputStream, _addIntToInputStream, _addUintToInputStream, _addStringToInputStream, _addRawDataSpanToInputStream, _allocateBoolVector, _allocateFloatVector, _allocateDoubleVector, _allocateIntVector, _allocateUintVector, _allocateStringVector, _addBoolVectorEntry, _addFloatVectorEntry, _addDoubleVectorEntry, _addIntVectorEntry, _addUintVectorEntry, _addStringVectorEntry, _addBoolVectorToInputStream, _addFloatVectorToInputStream, _addDoubleVectorToInputStream, _addIntVectorToInputStream, _addUintVectorToInputStream, _addStringVectorToInputStream, _addFlatHashMapToInputStream, _addProtoToInputStream, _addEmptyPacketToInputStream, _addBoolToInputSidePacket, _addDoubleToInputSidePacket, _addFloatToInputSidePacket, _addIntToInputSidePacket, _addUintToInputSidePacket, _addStringToInputSidePacket, _addRawDataSpanToInputSidePacket, _addProtoToInputSidePacket, _addBoolVectorToInputSidePacket, _addDoubleVectorToInputSidePacket, _addFloatVectorToInputSidePacket, _addIntVectorToInputSidePacket, _addUintVectorToInputSidePacket, _addStringVectorToInputSidePacket, _attachBoolListener, _attachBoolVectorListener, _attachDoubleListener, _attachDoubleVectorListener, _attachFloatListener, _attachFloatVectorListener, _attachIntListener, _attachIntVectorListener, _attachUintListener, _attachUintVectorListener, _attachStringListener, _attachStringVectorListener, _attachProtoListener, _attachProtoVectorListener, _getGraphConfig, ___getTypeName, _emwgpuCreateBindGroup, _emwgpuCreateBindGroupLayout, _emwgpuCreateCommandBuffer, _emwgpuCreateCommandEncoder, _emwgpuCreateComputePassEncoder, _emwgpuCreateComputePipeline, _emwgpuCreateExternalTexture, _emwgpuCreatePipelineLayout, _emwgpuCreateQuerySet, _emwgpuCreateRenderBundle, _emwgpuCreateRenderBundleEncoder, _emwgpuCreateRenderPassEncoder, _emwgpuCreateRenderPipeline, _emwgpuCreateSampler, _emwgpuCreateSurface, _emwgpuCreateTexture, _emwgpuCreateTextureView, _emwgpuCreateAdapter, _emwgpuImportBuffer, _emwgpuCreateDevice, _emwgpuCreateQueue, _emwgpuCreateShaderModule, _emwgpuOnCreateComputePipelineCompleted, _emwgpuOnWorkDoneCompleted, _clearSubgraphs, _pushBinarySubgraph, _pushTextSubgraph, _changeBinaryGraph, _changeTextGraph, _processGl, _process, _bindTextureToCanvas, _requestShaderRefreshOnGraphChange, _waitUntilIdle, _closeGraph, _setAutoRenderToScreen, _emscripten_builtin_memalign, _memalign, __emscripten_tempret_set, __emscripten_stack_restore, __emscripten_stack_alloc, _emscripten_stack_get_current, dynCall_vii, dynCall_viiiiiii, dynCall_viiiiii, dynCall_v, dynCall_ii, dynCall_vi, dynCall_iiiii, dynCall_iii, dynCall_viii, dynCall_i, dynCall_ji, dynCall_iiii, dynCall_viiii, dynCall_viiiii, dynCall_jii, dynCall_iiiijij, dynCall_ff, dynCall_did, dynCall_iiiiiii, dynCall_iiiiii, dynCall_iiiiiiiiiii, dynCall_iiiiiiiiiiii, dynCall_viji, dynCall_vijiii, dynCall_iiiiiiiii, dynCall_viiiiiiii, dynCall_iiiif, dynCall_viiiiiiiiiiiiiii, dynCall_viff, dynCall_viiffii, dynCall_viiffi, dynCall_viiiiiiiiii, dynCall_fi, dynCall_viiffff, dynCall_viiiiij, dynCall_vij, dynCall_viiiiiffii, dynCall_vif, dynCall_ddd, dynCall_dddd, dynCall_idd, dynCall_di, dynCall_jiiiijiiiii, dynCall_viiij, dynCall_viid, dynCall_vidd, dynCall_vifd, dynCall_viiiiiiiiiii, dynCall_iiif, dynCall_jiii, dynCall_viijj, dynCall_iiiiiiii, dynCall_iiiiiiiiii, dynCall_iij, dynCall_iiiijj, dynCall_viiijjj, dynCall_fff, dynCall_viifii, dynCall_fii, dynCall_jjj, dynCall_fiii, dynCall_viiiiiiiii, dynCall_viiiffii, dynCall_iiiiiffi, dynCall_viiiiiff, dynCall_viiiiiiiiiiiii, dynCall_viiiiiiiiiiii, dynCall_viiiiiiiiiiiiiiiii, dynCall_iifff, dynCall_iiff, dynCall_iiifiii, dynCall_iiffi, dynCall_iiffii, dynCall_viiiiiiiiiiiiii, dynCall_iif, dynCall_viijii, dynCall_iiiji, dynCall_viiif, dynCall_viiifiii, dynCall_fiif, dynCall_iiiifi, dynCall_iiiifiii, dynCall_iiifi, dynCall_viiiif, dynCall_viiiifii, dynCall_dii, dynCall_vifi, dynCall_vidi, dynCall_viiiji, dynCall_viiji, dynCall_vijjj, dynCall_vj, dynCall_viij, dynCall_jiji, dynCall_iidiiii, dynCall_iiiiij, dynCall_iiiiid, dynCall_iiiiijj, dynCall_iiiiiijj, _asyncify_start_unwind, _asyncify_stop_unwind, _asyncify_start_rewind, _asyncify_stop_rewind, memory, _kVersionStampBuildChangelistStr, _kVersionStampCitcSnapshotStr, _kVersionStampCitcWorkspaceIdStr, _kVersionStampSourceUriStr, _kVersionStampBuildClientStr, _kVersionStampBuildClientMintStatusStr, _kVersionStampBuildCompilerStr, _kVersionStampBuildDateTimePstStr, _kVersionStampBuildDepotPathStr, _kVersionStampBuildIdStr, _kVersionStampBuildInfoStr, _kVersionStampBuildLabelStr, _kVersionStampBuildTargetStr, _kVersionStampBuildTimestampStr, _kVersionStampBuildToolStr, _kVersionStampG3BuildTargetStr, _kVersionStampVerifiableStr, _kVersionStampBuildFdoTypeStr, _kVersionStampBuildBaselineChangelistStr, _kVersionStampBuildLtoTypeStr, _kVersionStampBuildPropellerTypeStr, _kVersionStampBuildPghoTypeStr, _kVersionStampBuildUsernameStr, _kVersionStampBuildHostnameStr, _kVersionStampBuildDirectoryStr, _kVersionStampBuildChangelistInt, _kVersionStampCitcSnapshotInt, _kVersionStampBuildClientMintStatusInt, _kVersionStampBuildTimestampInt, _kVersionStampVerifiableInt, _kVersionStampBuildCoverageEnabledInt, _kVersionStampBuildBaselineChangelistInt, _kVersionStampPrecookedTimestampStr, _kVersionStampPrecookedClientInfoStr, __indirect_function_table, wasmMemory;
+
+function assignWasmExports(wasmExports) {
+ _free = Module["_free"] = wasmExports["ad"];
+ _CreateLlmInferenceEngineConverted = Module["_CreateLlmInferenceEngineConverted"] = wasmExports["bd"];
+ _DeleteLlmInferenceEngine = Module["_DeleteLlmInferenceEngine"] = wasmExports["cd"];
+ _MakeSessionForPredict = Module["_MakeSessionForPredict"] = wasmExports["dd"];
+ _AddTextQueryChunk = Module["_AddTextQueryChunk"] = wasmExports["ed"];
+ _AddImageQueryChunk = Module["_AddImageQueryChunk"] = wasmExports["fd"];
+ _AddAudioQueryChunk = Module["_AddAudioQueryChunk"] = wasmExports["gd"];
+ _malloc = Module["_malloc"] = wasmExports["hd"];
+ _PredictSession = Module["_PredictSession"] = wasmExports["id"];
+ _FreeSession = Module["_FreeSession"] = wasmExports["jd"];
+ _GetSizeInTokens = Module["_GetSizeInTokens"] = wasmExports["kd"];
+ _wgpuDeviceAddRef = wasmExports["ld"];
+ _registerModelResourcesGraphService = Module["_registerModelResourcesGraphService"] = wasmExports["md"];
+ _bindTextureToStream = Module["_bindTextureToStream"] = wasmExports["nd"];
+ _addBoundTextureToStream = Module["_addBoundTextureToStream"] = wasmExports["od"];
+ _addDoubleToInputStream = Module["_addDoubleToInputStream"] = wasmExports["pd"];
+ _addFloatToInputStream = Module["_addFloatToInputStream"] = wasmExports["qd"];
+ _addBoolToInputStream = Module["_addBoolToInputStream"] = wasmExports["rd"];
+ _addIntToInputStream = Module["_addIntToInputStream"] = wasmExports["sd"];
+ _addUintToInputStream = Module["_addUintToInputStream"] = wasmExports["td"];
+ _addStringToInputStream = Module["_addStringToInputStream"] = wasmExports["ud"];
+ _addRawDataSpanToInputStream = Module["_addRawDataSpanToInputStream"] = wasmExports["vd"];
+ _allocateBoolVector = Module["_allocateBoolVector"] = wasmExports["wd"];
+ _allocateFloatVector = Module["_allocateFloatVector"] = wasmExports["xd"];
+ _allocateDoubleVector = Module["_allocateDoubleVector"] = wasmExports["yd"];
+ _allocateIntVector = Module["_allocateIntVector"] = wasmExports["zd"];
+ _allocateUintVector = Module["_allocateUintVector"] = wasmExports["Ad"];
+ _allocateStringVector = Module["_allocateStringVector"] = wasmExports["Bd"];
+ _addBoolVectorEntry = Module["_addBoolVectorEntry"] = wasmExports["Cd"];
+ _addFloatVectorEntry = Module["_addFloatVectorEntry"] = wasmExports["Dd"];
+ _addDoubleVectorEntry = Module["_addDoubleVectorEntry"] = wasmExports["Ed"];
+ _addIntVectorEntry = Module["_addIntVectorEntry"] = wasmExports["Fd"];
+ _addUintVectorEntry = Module["_addUintVectorEntry"] = wasmExports["Gd"];
+ _addStringVectorEntry = Module["_addStringVectorEntry"] = wasmExports["Hd"];
+ _addBoolVectorToInputStream = Module["_addBoolVectorToInputStream"] = wasmExports["Id"];
+ _addFloatVectorToInputStream = Module["_addFloatVectorToInputStream"] = wasmExports["Jd"];
+ _addDoubleVectorToInputStream = Module["_addDoubleVectorToInputStream"] = wasmExports["Kd"];
+ _addIntVectorToInputStream = Module["_addIntVectorToInputStream"] = wasmExports["Ld"];
+ _addUintVectorToInputStream = Module["_addUintVectorToInputStream"] = wasmExports["Md"];
+ _addStringVectorToInputStream = Module["_addStringVectorToInputStream"] = wasmExports["Nd"];
+ _addFlatHashMapToInputStream = Module["_addFlatHashMapToInputStream"] = wasmExports["Od"];
+ _addProtoToInputStream = Module["_addProtoToInputStream"] = wasmExports["Pd"];
+ _addEmptyPacketToInputStream = Module["_addEmptyPacketToInputStream"] = wasmExports["Qd"];
+ _addBoolToInputSidePacket = Module["_addBoolToInputSidePacket"] = wasmExports["Rd"];
+ _addDoubleToInputSidePacket = Module["_addDoubleToInputSidePacket"] = wasmExports["Sd"];
+ _addFloatToInputSidePacket = Module["_addFloatToInputSidePacket"] = wasmExports["Td"];
+ _addIntToInputSidePacket = Module["_addIntToInputSidePacket"] = wasmExports["Ud"];
+ _addUintToInputSidePacket = Module["_addUintToInputSidePacket"] = wasmExports["Vd"];
+ _addStringToInputSidePacket = Module["_addStringToInputSidePacket"] = wasmExports["Wd"];
+ _addRawDataSpanToInputSidePacket = Module["_addRawDataSpanToInputSidePacket"] = wasmExports["Xd"];
+ _addProtoToInputSidePacket = Module["_addProtoToInputSidePacket"] = wasmExports["Yd"];
+ _addBoolVectorToInputSidePacket = Module["_addBoolVectorToInputSidePacket"] = wasmExports["Zd"];
+ _addDoubleVectorToInputSidePacket = Module["_addDoubleVectorToInputSidePacket"] = wasmExports["_d"];
+ _addFloatVectorToInputSidePacket = Module["_addFloatVectorToInputSidePacket"] = wasmExports["$d"];
+ _addIntVectorToInputSidePacket = Module["_addIntVectorToInputSidePacket"] = wasmExports["ae"];
+ _addUintVectorToInputSidePacket = Module["_addUintVectorToInputSidePacket"] = wasmExports["be"];
+ _addStringVectorToInputSidePacket = Module["_addStringVectorToInputSidePacket"] = wasmExports["ce"];
+ _attachBoolListener = Module["_attachBoolListener"] = wasmExports["de"];
+ _attachBoolVectorListener = Module["_attachBoolVectorListener"] = wasmExports["ee"];
+ _attachDoubleListener = Module["_attachDoubleListener"] = wasmExports["fe"];
+ _attachDoubleVectorListener = Module["_attachDoubleVectorListener"] = wasmExports["ge"];
+ _attachFloatListener = Module["_attachFloatListener"] = wasmExports["he"];
+ _attachFloatVectorListener = Module["_attachFloatVectorListener"] = wasmExports["ie"];
+ _attachIntListener = Module["_attachIntListener"] = wasmExports["je"];
+ _attachIntVectorListener = Module["_attachIntVectorListener"] = wasmExports["ke"];
+ _attachUintListener = Module["_attachUintListener"] = wasmExports["le"];
+ _attachUintVectorListener = Module["_attachUintVectorListener"] = wasmExports["me"];
+ _attachStringListener = Module["_attachStringListener"] = wasmExports["ne"];
+ _attachStringVectorListener = Module["_attachStringVectorListener"] = wasmExports["oe"];
+ _attachProtoListener = Module["_attachProtoListener"] = wasmExports["pe"];
+ _attachProtoVectorListener = Module["_attachProtoVectorListener"] = wasmExports["qe"];
+ _getGraphConfig = Module["_getGraphConfig"] = wasmExports["re"];
+ ___getTypeName = wasmExports["se"];
+ _emwgpuCreateBindGroup = wasmExports["te"];
+ _emwgpuCreateBindGroupLayout = wasmExports["ue"];
+ _emwgpuCreateCommandBuffer = wasmExports["ve"];
+ _emwgpuCreateCommandEncoder = wasmExports["we"];
+ _emwgpuCreateComputePassEncoder = wasmExports["xe"];
+ _emwgpuCreateComputePipeline = wasmExports["ye"];
+ _emwgpuCreateExternalTexture = wasmExports["ze"];
+ _emwgpuCreatePipelineLayout = wasmExports["Ae"];
+ _emwgpuCreateQuerySet = wasmExports["Be"];
+ _emwgpuCreateRenderBundle = wasmExports["Ce"];
+ _emwgpuCreateRenderBundleEncoder = wasmExports["De"];
+ _emwgpuCreateRenderPassEncoder = wasmExports["Ee"];
+ _emwgpuCreateRenderPipeline = wasmExports["Fe"];
+ _emwgpuCreateSampler = wasmExports["Ge"];
+ _emwgpuCreateSurface = wasmExports["He"];
+ _emwgpuCreateTexture = wasmExports["Ie"];
+ _emwgpuCreateTextureView = wasmExports["Je"];
+ _emwgpuCreateAdapter = wasmExports["Ke"];
+ _emwgpuImportBuffer = wasmExports["Le"];
+ _emwgpuCreateDevice = wasmExports["Me"];
+ _emwgpuCreateQueue = wasmExports["Ne"];
+ _emwgpuCreateShaderModule = wasmExports["Oe"];
+ _emwgpuOnCreateComputePipelineCompleted = wasmExports["Pe"];
+ _emwgpuOnWorkDoneCompleted = wasmExports["Qe"];
+ _clearSubgraphs = Module["_clearSubgraphs"] = wasmExports["Re"];
+ _pushBinarySubgraph = Module["_pushBinarySubgraph"] = wasmExports["Se"];
+ _pushTextSubgraph = Module["_pushTextSubgraph"] = wasmExports["Te"];
+ _changeBinaryGraph = Module["_changeBinaryGraph"] = wasmExports["Ue"];
+ _changeTextGraph = Module["_changeTextGraph"] = wasmExports["Ve"];
+ _processGl = Module["_processGl"] = wasmExports["We"];
+ _process = Module["_process"] = wasmExports["Xe"];
+ _bindTextureToCanvas = Module["_bindTextureToCanvas"] = wasmExports["Ye"];
+ _requestShaderRefreshOnGraphChange = Module["_requestShaderRefreshOnGraphChange"] = wasmExports["Ze"];
+ _waitUntilIdle = Module["_waitUntilIdle"] = wasmExports["_e"];
+ _closeGraph = Module["_closeGraph"] = wasmExports["$e"];
+ _setAutoRenderToScreen = Module["_setAutoRenderToScreen"] = wasmExports["af"];
+ _emscripten_builtin_memalign = wasmExports["bf"];
+ _memalign = wasmExports["cf"];
+ __emscripten_tempret_set = wasmExports["df"];
+ __emscripten_stack_restore = wasmExports["ef"];
+ __emscripten_stack_alloc = wasmExports["ff"];
+ _emscripten_stack_get_current = wasmExports["gf"];
+ dynCall_vii = dynCalls["vii"] = wasmExports["hf"];
+ dynCall_viiiiiii = dynCalls["viiiiiii"] = wasmExports["jf"];
+ dynCall_viiiiii = dynCalls["viiiiii"] = wasmExports["kf"];
+ dynCall_v = dynCalls["v"] = wasmExports["lf"];
+ dynCall_ii = dynCalls["ii"] = wasmExports["mf"];
+ dynCall_vi = dynCalls["vi"] = wasmExports["nf"];
+ dynCall_iiiii = dynCalls["iiiii"] = wasmExports["of"];
+ dynCall_iii = dynCalls["iii"] = wasmExports["pf"];
+ dynCall_viii = dynCalls["viii"] = wasmExports["qf"];
+ dynCall_i = dynCalls["i"] = wasmExports["rf"];
+ dynCall_ji = dynCalls["ji"] = wasmExports["sf"];
+ dynCall_iiii = dynCalls["iiii"] = wasmExports["tf"];
+ dynCall_viiii = dynCalls["viiii"] = wasmExports["uf"];
+ dynCall_viiiii = dynCalls["viiiii"] = wasmExports["vf"];
+ dynCall_jii = dynCalls["jii"] = wasmExports["wf"];
+ dynCall_iiiijij = dynCalls["iiiijij"] = wasmExports["xf"];
+ dynCall_ff = dynCalls["ff"] = wasmExports["yf"];
+ dynCall_did = dynCalls["did"] = wasmExports["zf"];
+ dynCall_iiiiiii = dynCalls["iiiiiii"] = wasmExports["Af"];
+ dynCall_iiiiii = dynCalls["iiiiii"] = wasmExports["Bf"];
+ dynCall_iiiiiiiiiii = dynCalls["iiiiiiiiiii"] = wasmExports["Cf"];
+ dynCall_iiiiiiiiiiii = dynCalls["iiiiiiiiiiii"] = wasmExports["Df"];
+ dynCall_viji = dynCalls["viji"] = wasmExports["Ef"];
+ dynCall_vijiii = dynCalls["vijiii"] = wasmExports["Ff"];
+ dynCall_iiiiiiiii = dynCalls["iiiiiiiii"] = wasmExports["Gf"];
+ dynCall_viiiiiiii = dynCalls["viiiiiiii"] = wasmExports["Hf"];
+ dynCall_iiiif = dynCalls["iiiif"] = wasmExports["If"];
+ dynCall_viiiiiiiiiiiiiii = dynCalls["viiiiiiiiiiiiiii"] = wasmExports["Jf"];
+ dynCall_viff = dynCalls["viff"] = wasmExports["Kf"];
+ dynCall_viiffii = dynCalls["viiffii"] = wasmExports["Lf"];
+ dynCall_viiffi = dynCalls["viiffi"] = wasmExports["Mf"];
+ dynCall_viiiiiiiiii = dynCalls["viiiiiiiiii"] = wasmExports["Nf"];
+ dynCall_fi = dynCalls["fi"] = wasmExports["Of"];
+ dynCall_viiffff = dynCalls["viiffff"] = wasmExports["Pf"];
+ dynCall_viiiiij = dynCalls["viiiiij"] = wasmExports["Qf"];
+ dynCall_vij = dynCalls["vij"] = wasmExports["Rf"];
+ dynCall_viiiiiffii = dynCalls["viiiiiffii"] = wasmExports["Sf"];
+ dynCall_vif = dynCalls["vif"] = wasmExports["Tf"];
+ dynCall_ddd = dynCalls["ddd"] = wasmExports["Uf"];
+ dynCall_dddd = dynCalls["dddd"] = wasmExports["Vf"];
+ dynCall_idd = dynCalls["idd"] = wasmExports["Wf"];
+ dynCall_di = dynCalls["di"] = wasmExports["Xf"];
+ dynCall_jiiiijiiiii = dynCalls["jiiiijiiiii"] = wasmExports["Yf"];
+ dynCall_viiij = dynCalls["viiij"] = wasmExports["Zf"];
+ dynCall_viid = dynCalls["viid"] = wasmExports["_f"];
+ dynCall_vidd = dynCalls["vidd"] = wasmExports["$f"];
+ dynCall_vifd = dynCalls["vifd"] = wasmExports["ag"];
+ dynCall_viiiiiiiiiii = dynCalls["viiiiiiiiiii"] = wasmExports["bg"];
+ dynCall_iiif = dynCalls["iiif"] = wasmExports["cg"];
+ dynCall_jiii = dynCalls["jiii"] = wasmExports["dg"];
+ dynCall_viijj = dynCalls["viijj"] = wasmExports["eg"];
+ dynCall_iiiiiiii = dynCalls["iiiiiiii"] = wasmExports["fg"];
+ dynCall_iiiiiiiiii = dynCalls["iiiiiiiiii"] = wasmExports["gg"];
+ dynCall_iij = dynCalls["iij"] = wasmExports["hg"];
+ dynCall_iiiijj = dynCalls["iiiijj"] = wasmExports["ig"];
+ dynCall_viiijjj = dynCalls["viiijjj"] = wasmExports["jg"];
+ dynCall_fff = dynCalls["fff"] = wasmExports["kg"];
+ dynCall_viifii = dynCalls["viifii"] = wasmExports["lg"];
+ dynCall_fii = dynCalls["fii"] = wasmExports["mg"];
+ dynCall_jjj = dynCalls["jjj"] = wasmExports["ng"];
+ dynCall_fiii = dynCalls["fiii"] = wasmExports["og"];
+ dynCall_viiiiiiiii = dynCalls["viiiiiiiii"] = wasmExports["pg"];
+ dynCall_viiiffii = dynCalls["viiiffii"] = wasmExports["qg"];
+ dynCall_iiiiiffi = dynCalls["iiiiiffi"] = wasmExports["rg"];
+ dynCall_viiiiiff = dynCalls["viiiiiff"] = wasmExports["sg"];
+ dynCall_viiiiiiiiiiiii = dynCalls["viiiiiiiiiiiii"] = wasmExports["tg"];
+ dynCall_viiiiiiiiiiii = dynCalls["viiiiiiiiiiii"] = wasmExports["ug"];
+ dynCall_viiiiiiiiiiiiiiiii = dynCalls["viiiiiiiiiiiiiiiii"] = wasmExports["vg"];
+ dynCall_iifff = dynCalls["iifff"] = wasmExports["wg"];
+ dynCall_iiff = dynCalls["iiff"] = wasmExports["xg"];
+ dynCall_iiifiii = dynCalls["iiifiii"] = wasmExports["yg"];
+ dynCall_iiffi = dynCalls["iiffi"] = wasmExports["zg"];
+ dynCall_iiffii = dynCalls["iiffii"] = wasmExports["Ag"];
+ dynCall_viiiiiiiiiiiiii = dynCalls["viiiiiiiiiiiiii"] = wasmExports["Bg"];
+ dynCall_iif = dynCalls["iif"] = wasmExports["Cg"];
+ dynCall_viijii = dynCalls["viijii"] = wasmExports["Dg"];
+ dynCall_iiiji = dynCalls["iiiji"] = wasmExports["Eg"];
+ dynCall_viiif = dynCalls["viiif"] = wasmExports["Fg"];
+ dynCall_viiifiii = dynCalls["viiifiii"] = wasmExports["Gg"];
+ dynCall_fiif = dynCalls["fiif"] = wasmExports["Hg"];
+ dynCall_iiiifi = dynCalls["iiiifi"] = wasmExports["Ig"];
+ dynCall_iiiifiii = dynCalls["iiiifiii"] = wasmExports["Jg"];
+ dynCall_iiifi = dynCalls["iiifi"] = wasmExports["Kg"];
+ dynCall_viiiif = dynCalls["viiiif"] = wasmExports["Lg"];
+ dynCall_viiiifii = dynCalls["viiiifii"] = wasmExports["Mg"];
+ dynCall_dii = dynCalls["dii"] = wasmExports["Ng"];
+ dynCall_vifi = dynCalls["vifi"] = wasmExports["Og"];
+ dynCall_vidi = dynCalls["vidi"] = wasmExports["Pg"];
+ dynCall_viiiji = dynCalls["viiiji"] = wasmExports["Qg"];
+ dynCall_viiji = dynCalls["viiji"] = wasmExports["Rg"];
+ dynCall_vijjj = dynCalls["vijjj"] = wasmExports["Sg"];
+ dynCall_vj = dynCalls["vj"] = wasmExports["Tg"];
+ dynCall_viij = dynCalls["viij"] = wasmExports["Ug"];
+ dynCall_jiji = dynCalls["jiji"] = wasmExports["Vg"];
+ dynCall_iidiiii = dynCalls["iidiiii"] = wasmExports["Wg"];
+ dynCall_iiiiij = dynCalls["iiiiij"] = wasmExports["Xg"];
+ dynCall_iiiiid = dynCalls["iiiiid"] = wasmExports["Yg"];
+ dynCall_iiiiijj = dynCalls["iiiiijj"] = wasmExports["Zg"];
+ dynCall_iiiiiijj = dynCalls["iiiiiijj"] = wasmExports["_g"];
+ _asyncify_start_unwind = wasmExports["$g"];
+ _asyncify_stop_unwind = wasmExports["ah"];
+ _asyncify_start_rewind = wasmExports["bh"];
+ _asyncify_stop_rewind = wasmExports["ch"];
+ memory = wasmMemory = wasmExports["sc"];
+ _kVersionStampBuildChangelistStr = Module["_kVersionStampBuildChangelistStr"] = (wasmExports["uc"].value) >>> 0;
+ _kVersionStampCitcSnapshotStr = Module["_kVersionStampCitcSnapshotStr"] = (wasmExports["vc"].value) >>> 0;
+ _kVersionStampCitcWorkspaceIdStr = Module["_kVersionStampCitcWorkspaceIdStr"] = (wasmExports["wc"].value) >>> 0;
+ _kVersionStampSourceUriStr = Module["_kVersionStampSourceUriStr"] = (wasmExports["xc"].value) >>> 0;
+ _kVersionStampBuildClientStr = Module["_kVersionStampBuildClientStr"] = (wasmExports["yc"].value) >>> 0;
+ _kVersionStampBuildClientMintStatusStr = Module["_kVersionStampBuildClientMintStatusStr"] = (wasmExports["zc"].value) >>> 0;
+ _kVersionStampBuildCompilerStr = Module["_kVersionStampBuildCompilerStr"] = (wasmExports["Ac"].value) >>> 0;
+ _kVersionStampBuildDateTimePstStr = Module["_kVersionStampBuildDateTimePstStr"] = (wasmExports["Bc"].value) >>> 0;
+ _kVersionStampBuildDepotPathStr = Module["_kVersionStampBuildDepotPathStr"] = (wasmExports["Cc"].value) >>> 0;
+ _kVersionStampBuildIdStr = Module["_kVersionStampBuildIdStr"] = (wasmExports["Dc"].value) >>> 0;
+ _kVersionStampBuildInfoStr = Module["_kVersionStampBuildInfoStr"] = (wasmExports["Ec"].value) >>> 0;
+ _kVersionStampBuildLabelStr = Module["_kVersionStampBuildLabelStr"] = (wasmExports["Fc"].value) >>> 0;
+ _kVersionStampBuildTargetStr = Module["_kVersionStampBuildTargetStr"] = (wasmExports["Gc"].value) >>> 0;
+ _kVersionStampBuildTimestampStr = Module["_kVersionStampBuildTimestampStr"] = (wasmExports["Hc"].value) >>> 0;
+ _kVersionStampBuildToolStr = Module["_kVersionStampBuildToolStr"] = (wasmExports["Ic"].value) >>> 0;
+ _kVersionStampG3BuildTargetStr = Module["_kVersionStampG3BuildTargetStr"] = (wasmExports["Jc"].value) >>> 0;
+ _kVersionStampVerifiableStr = Module["_kVersionStampVerifiableStr"] = (wasmExports["Kc"].value) >>> 0;
+ _kVersionStampBuildFdoTypeStr = Module["_kVersionStampBuildFdoTypeStr"] = (wasmExports["Lc"].value) >>> 0;
+ _kVersionStampBuildBaselineChangelistStr = Module["_kVersionStampBuildBaselineChangelistStr"] = (wasmExports["Mc"].value) >>> 0;
+ _kVersionStampBuildLtoTypeStr = Module["_kVersionStampBuildLtoTypeStr"] = (wasmExports["Nc"].value) >>> 0;
+ _kVersionStampBuildPropellerTypeStr = Module["_kVersionStampBuildPropellerTypeStr"] = (wasmExports["Oc"].value) >>> 0;
+ _kVersionStampBuildPghoTypeStr = Module["_kVersionStampBuildPghoTypeStr"] = (wasmExports["Pc"].value) >>> 0;
+ _kVersionStampBuildUsernameStr = Module["_kVersionStampBuildUsernameStr"] = (wasmExports["Qc"].value) >>> 0;
+ _kVersionStampBuildHostnameStr = Module["_kVersionStampBuildHostnameStr"] = (wasmExports["Rc"].value) >>> 0;
+ _kVersionStampBuildDirectoryStr = Module["_kVersionStampBuildDirectoryStr"] = (wasmExports["Sc"].value) >>> 0;
+ _kVersionStampBuildChangelistInt = Module["_kVersionStampBuildChangelistInt"] = (wasmExports["Tc"].value) >>> 0;
+ _kVersionStampCitcSnapshotInt = Module["_kVersionStampCitcSnapshotInt"] = (wasmExports["Uc"].value) >>> 0;
+ _kVersionStampBuildClientMintStatusInt = Module["_kVersionStampBuildClientMintStatusInt"] = (wasmExports["Vc"].value) >>> 0;
+ _kVersionStampBuildTimestampInt = Module["_kVersionStampBuildTimestampInt"] = (wasmExports["Wc"].value) >>> 0;
+ _kVersionStampVerifiableInt = Module["_kVersionStampVerifiableInt"] = (wasmExports["Xc"].value) >>> 0;
+ _kVersionStampBuildCoverageEnabledInt = Module["_kVersionStampBuildCoverageEnabledInt"] = (wasmExports["Yc"].value) >>> 0;
+ _kVersionStampBuildBaselineChangelistInt = Module["_kVersionStampBuildBaselineChangelistInt"] = (wasmExports["Zc"].value) >>> 0;
+ _kVersionStampPrecookedTimestampStr = Module["_kVersionStampPrecookedTimestampStr"] = (wasmExports["_c"].value) >>> 0;
+ _kVersionStampPrecookedClientInfoStr = Module["_kVersionStampPrecookedClientInfoStr"] = (wasmExports["$c"].value) >>> 0;
+ __indirect_function_table = wasmExports["__indirect_function_table"];
+}
+
+var wasmImports = {
+ /** @export */ qc: DefaultErrorReporter,
+ /** @export */ pc: GetAdapterArchitecture,
+ /** @export */ oc: GetAdapterDescription,
+ /** @export */ nc: GetAdapterDeviceName,
+ /** @export */ mc: GetAdapterVendor,
+ /** @export */ kc: JsGetDeviceMaxSubgroupSize,
+ /** @export */ jc: JsGetDeviceMinSubgroupSize,
+ /** @export */ ic: JsOnEmptyPacketListener,
+ /** @export */ ma: JsOnSimpleListenerBinaryArray,
+ /** @export */ hc: JsOnSimpleListenerBool,
+ /** @export */ gc: JsOnSimpleListenerDouble,
+ /** @export */ fc: JsOnSimpleListenerFloat,
+ /** @export */ ec: JsOnSimpleListenerInt,
+ /** @export */ dc: JsOnSimpleListenerString,
+ /** @export */ cc: JsOnSimpleListenerUint,
+ /** @export */ p: JsOnVectorFinishedListener,
+ /** @export */ bc: JsOnVectorListenerBool,
+ /** @export */ ac: JsOnVectorListenerDouble,
+ /** @export */ $b: JsOnVectorListenerFloat,
+ /** @export */ _b: JsOnVectorListenerInt,
+ /** @export */ Zb: JsOnVectorListenerProto,
+ /** @export */ Yb: JsOnVectorListenerString,
+ /** @export */ Xb: JsOnVectorListenerUint,
+ /** @export */ la: JsProgressListener,
+ /** @export */ K: JsWrapErrorListener,
+ /** @export */ g: JsWrapSimpleListeners,
+ /** @export */ Wb: ThrowError,
+ /** @export */ ka: UseBottomLeftGpuOrigin,
+ /** @export */ Vb: __Unwind_RaiseException,
+ /** @export */ rc: __asyncjs__CallReadDataFn,
+ /** @export */ lc: __asyncjs__InvokeReadDataFn,
+ /** @export */ J: __asyncjs__ReadBufferDataJs,
+ /** @export */ Ea: __asyncjs__mediapipe_map_buffer_jspi,
+ /** @export */ Ub: ___syscall_dup,
+ /** @export */ Tb: ___syscall_faccessat,
+ /** @export */ ja: ___syscall_fcntl64,
+ /** @export */ Sb: ___syscall_fstat64,
+ /** @export */ Va: ___syscall_ftruncate64,
+ /** @export */ Rb: ___syscall_getcwd,
+ /** @export */ Qb: ___syscall_getdents64,
+ /** @export */ Pb: ___syscall_ioctl,
+ /** @export */ Ob: ___syscall_lstat64,
+ /** @export */ Nb: ___syscall_mkdirat,
+ /** @export */ Mb: ___syscall_newfstatat,
+ /** @export */ ia: ___syscall_openat,
+ /** @export */ Lb: ___syscall_stat64,
+ /** @export */ Gb: __abort_js,
+ /** @export */ Ra: __embind_register_bigint,
+ /** @export */ Fb: __embind_register_bool,
+ /** @export */ Eb: __embind_register_emval,
+ /** @export */ ga: __embind_register_float,
+ /** @export */ x: __embind_register_function,
+ /** @export */ n: __embind_register_integer,
+ /** @export */ e: __embind_register_memory_view,
+ /** @export */ Db: __embind_register_std_string,
+ /** @export */ I: __embind_register_std_wstring,
+ /** @export */ Cb: __embind_register_void,
+ /** @export */ fa: __emval_create_invoker,
+ /** @export */ l: __emval_decref,
+ /** @export */ o: __emval_incref,
+ /** @export */ ea: __emval_invoke,
+ /** @export */ da: __emval_run_destructors,
+ /** @export */ Qa: __gmtime_js,
+ /** @export */ Pa: __localtime_js,
+ /** @export */ Oa: __mktime_js,
+ /** @export */ Na: __mmap_js,
+ /** @export */ Ma: __munmap_js,
+ /** @export */ Bb: __tzset_js,
+ /** @export */ Ua: _clock_time_get,
+ /** @export */ Ab: custom_emscripten_dbgn,
+ /** @export */ s: _emscripten_asm_const_int,
+ /** @export */ H: _emscripten_errn,
+ /** @export */ zb: _emscripten_get_heap_max,
+ /** @export */ d: _emscripten_get_now,
+ /** @export */ ca: _emscripten_has_asyncify,
+ /** @export */ yb: _emscripten_outn,
+ /** @export */ xb: _emscripten_pc_get_function,
+ /** @export */ wb: _emscripten_resize_heap,
+ /** @export */ ba: _emscripten_stack_snapshot,
+ /** @export */ vb: _emscripten_stack_unwind_buffer,
+ /** @export */ ub: _emscripten_webgl_create_context,
+ /** @export */ tb: _emscripten_webgl_destroy_context,
+ /** @export */ sb: _emscripten_webgl_get_context_attributes,
+ /** @export */ r: _emscripten_webgl_get_current_context,
+ /** @export */ rb: _emscripten_webgl_make_context_current,
+ /** @export */ aa: _emscripten_webgpu_get_device,
+ /** @export */ qb: _emwgpuBufferDestroy,
+ /** @export */ pb: _emwgpuBufferGetMappedRange,
+ /** @export */ ob: _emwgpuBufferUnmap,
+ /** @export */ nb: _emwgpuBufferWriteMappedRange,
+ /** @export */ f: _emwgpuDelete,
+ /** @export */ mb: _emwgpuDeviceCreateBuffer,
+ /** @export */ La: _emwgpuDeviceCreateComputePipelineAsync,
+ /** @export */ lb: _emwgpuDeviceCreateShaderModule,
+ /** @export */ kb: _emwgpuDeviceDestroy,
+ /** @export */ Ka: _emwgpuQueueOnSubmittedWorkDone,
+ /** @export */ jb: _emwgpuWaitAny,
+ /** @export */ Kb: _environ_get,
+ /** @export */ Jb: _environ_sizes_get,
+ /** @export */ ib: _exit,
+ /** @export */ z: _fd_close,
+ /** @export */ Ta: _fd_pread,
+ /** @export */ ha: _fd_read,
+ /** @export */ Sa: _fd_seek,
+ /** @export */ y: _fd_write,
+ /** @export */ G: _glActiveTexture,
+ /** @export */ $: _glAttachShader,
+ /** @export */ hb: _glBindAttribLocation,
+ /** @export */ m: _glBindBuffer,
+ /** @export */ w: _glBindFramebuffer,
+ /** @export */ k: _glBindTexture,
+ /** @export */ F: _glBufferData,
+ /** @export */ q: _glClientWaitSync,
+ /** @export */ gb: _glCompileShader,
+ /** @export */ fb: _glCreateProgram,
+ /** @export */ eb: _glCreateShader,
+ /** @export */ _: _glDeleteFramebuffers,
+ /** @export */ db: _glDeleteProgram,
+ /** @export */ Z: _glDeleteShader,
+ /** @export */ v: _glDeleteSync,
+ /** @export */ Y: _glDeleteTextures,
+ /** @export */ X: _glDetachShader,
+ /** @export */ W: _glDisableVertexAttribArray,
+ /** @export */ cb: _glDrawArrays,
+ /** @export */ V: _glEnableVertexAttribArray,
+ /** @export */ U: _glFenceSync,
+ /** @export */ u: _glFinish,
+ /** @export */ E: _glFramebufferTexture2D,
+ /** @export */ T: _glGenBuffers,
+ /** @export */ bb: _glGenFramebuffers,
+ /** @export */ D: _glGenTextures,
+ /** @export */ t: _glGetError,
+ /** @export */ S: _glGetIntegerv,
+ /** @export */ C: _glGetString,
+ /** @export */ ab: _glGetUniformLocation,
+ /** @export */ $a: _glLinkProgram,
+ /** @export */ B: _glPixelStorei,
+ /** @export */ R: _glReadPixels,
+ /** @export */ _a: _glShaderSource,
+ /** @export */ Za: _glTexImage2D,
+ /** @export */ j: _glTexParameteri,
+ /** @export */ Q: _glTexStorage2D,
+ /** @export */ Ya: _glUniform1i,
+ /** @export */ Xa: _glUseProgram,
+ /** @export */ P: _glVertexAttribPointer,
+ /** @export */ Wa: _glViewport,
+ /** @export */ A: hardware_concurrency,
+ /** @export */ Ib: _proc_exit,
+ /** @export */ Hb: _random_get,
+ /** @export */ Ja: _wgpuBufferGetSize,
+ /** @export */ Ia: _wgpuBufferGetUsage,
+ /** @export */ i: _wgpuCommandEncoderBeginComputePass,
+ /** @export */ Ha: _wgpuCommandEncoderCopyBufferToBuffer,
+ /** @export */ O: _wgpuCommandEncoderCopyTextureToBuffer,
+ /** @export */ Da: _wgpuCommandEncoderCopyTextureToTexture,
+ /** @export */ c: _wgpuCommandEncoderFinish,
+ /** @export */ Ga: _wgpuCommandEncoderResolveQuerySet,
+ /** @export */ N: _wgpuComputePassEncoderDispatchWorkgroups,
+ /** @export */ h: _wgpuComputePassEncoderEnd,
+ /** @export */ Ca: _wgpuComputePassEncoderSetBindGroup,
+ /** @export */ M: _wgpuComputePassEncoderSetPipeline,
+ /** @export */ Ba: _wgpuDeviceCreateBindGroup,
+ /** @export */ Aa: _wgpuDeviceCreateBindGroupLayout,
+ /** @export */ b: _wgpuDeviceCreateCommandEncoder,
+ /** @export */ za: _wgpuDeviceCreateComputePipeline,
+ /** @export */ ya: _wgpuDeviceCreatePipelineLayout,
+ /** @export */ xa: _wgpuDeviceCreateQuerySet,
+ /** @export */ wa: _wgpuDeviceCreateTexture,
+ /** @export */ L: _wgpuDeviceGetAdapterInfo,
+ /** @export */ va: _wgpuDeviceGetLimits,
+ /** @export */ ua: _wgpuDeviceHasFeature,
+ /** @export */ a: _wgpuQueueSubmit,
+ /** @export */ Fa: _wgpuQueueWriteBuffer,
+ /** @export */ ta: _wgpuQueueWriteTexture,
+ /** @export */ sa: _wgpuTextureCreateView,
+ /** @export */ ra: _wgpuTextureDestroy,
+ /** @export */ qa: _wgpuTextureGetDepthOrArrayLayers,
+ /** @export */ pa: _wgpuTextureGetFormat,
+ /** @export */ oa: _wgpuTextureGetHeight,
+ /** @export */ na: _wgpuTextureGetWidth
+};
+
+// Argument name here must shadow the `wasmExports` global so
+// that it is recognised by metadce and minify-import-export-names
+// passes.
+function applySignatureConversions(wasmExports) {
+ // First, make a copy of the incoming exports object
+ wasmExports = Object.assign({}, wasmExports);
+ var makeWrapper_pp = f => a0 => f(a0) >>> 0;
+ var makeWrapper_ppp = f => (a0, a1) => f(a0, a1) >>> 0;
+ var makeWrapper_p = f => () => f() >>> 0;
+ wasmExports["hd"] = makeWrapper_pp(wasmExports["hd"]);
+ wasmExports["se"] = makeWrapper_pp(wasmExports["se"]);
+ wasmExports["bf"] = makeWrapper_ppp(wasmExports["bf"]);
+ wasmExports["cf"] = makeWrapper_ppp(wasmExports["cf"]);
+ wasmExports["ff"] = makeWrapper_pp(wasmExports["ff"]);
+ wasmExports["gf"] = makeWrapper_p(wasmExports["gf"]);
+ return wasmExports;
+}
+
+// include: postamble.js
+// === Auto-generated postamble setup entry stuff ===
+function run() {
+ if (runDependencies > 0) {
+ dependenciesFulfilled = run;
+ return;
+ }
+ preRun();
+ // a preRun added a dependency, run will be called later
+ if (runDependencies > 0) {
+ dependenciesFulfilled = run;
+ return;
+ }
+ function doRun() {
+ // run may have just been called through dependencies being fulfilled just in this very frame,
+ // or while the async setStatus time below was happening
+ Module["calledRun"] = true;
+ if (ABORT) return;
+ initRuntime();
+ readyPromiseResolve?.(Module);
+ Module["onRuntimeInitialized"]?.();
+ postRun();
+ }
+ if (Module["setStatus"]) {
+ Module["setStatus"]("Running...");
+ setTimeout(() => {
+ setTimeout(() => Module["setStatus"](""), 1);
+ doRun();
+ }, 1);
+ } else {
+ doRun();
+ }
+}
+
+var wasmExports;
+
+// In modularize mode the generated code is within a factory function so we
+// can use await here (since it's not top-level-await).
+wasmExports = await (createWasm());
+
+run();
+
+// end include: postamble.js
+// include: postamble_modularize.js
+// In MODULARIZE mode we wrap the generated code in a factory function
+// and return either the Module itself, or a promise of the module.
+// We assign to the `moduleRtn` global here and configure closure to see
+// this as an extern so it won't get minified.
+if (runtimeInitialized) {
+ moduleRtn = Module;
+} else {
+ // Set up the promise that indicates the Module is initialized
+ moduleRtn = new Promise((resolve, reject) => {
+ readyPromiseResolve = resolve;
+ readyPromiseReject = reject;
+ });
+}
+
+
+ return moduleRtn;
+ };
+})();
+
+// Export using a UMD style export, or ES6 exports if selected
+if (typeof exports === 'object' && typeof module === 'object') {
+ module.exports = ModuleFactory;
+ // This default export looks redundant, but it allows TS to import this
+ // commonjs style module.
+ module.exports.default = ModuleFactory;
+} else if (typeof define === 'function' && define['amd'])
+ define([], () => ModuleFactory);
+
diff --git a/public/mediapipe/wasm/genai_wasm_internal.wasm b/public/mediapipe/wasm/genai_wasm_internal.wasm
new file mode 100644
index 0000000..6de050b
Binary files /dev/null and b/public/mediapipe/wasm/genai_wasm_internal.wasm differ
diff --git a/public/mediapipe/wasm/genai_wasm_module_internal.js b/public/mediapipe/wasm/genai_wasm_module_internal.js
new file mode 100644
index 0000000..9f8921c
--- /dev/null
+++ b/public/mediapipe/wasm/genai_wasm_module_internal.js
@@ -0,0 +1,9031 @@
+// This code implements the `-sMODULARIZE` settings by taking the generated
+// JS program code (INNER_JS_CODE) and wrapping it in a factory function.
+
+// When targeting node and ES6 we use `await import ..` in the generated code
+// so the outer function needs to be marked as async.
+async function ModuleFactory(moduleArg = {}) {
+ var moduleRtn;
+
+// include: shell.js
+// include: minimum_runtime_check.js
+// end include: minimum_runtime_check.js
+// The Module object: Our interface to the outside world. We import
+// and export values on it. There are various ways Module can be used:
+// 1. Not defined. We create it here
+// 2. A function parameter, function(moduleArg) => Promise
+// 3. pre-run appended it, var Module = {}; ..generated code..
+// 4. External script tag defines var Module.
+// We need to check if Module already exists (e.g. case 3 above).
+// Substitution will be replaced with actual code on later stage of the build,
+// this way Closure Compiler will not mangle it (e.g. case 4. above).
+// Note that if you want to run closure, and also to use Module
+// after the generated code, you will need to define var Module = {};
+// before the code. Then that object will be used in the code, and you
+// can continue to use Module afterwards as well.
+var Module = moduleArg;
+
+// Determine the runtime environment we are in. You can customize this by
+// setting the ENVIRONMENT setting at compile time (see settings.js).
+// Attempt to auto-detect the environment
+var ENVIRONMENT_IS_WEB = !!globalThis.window;
+
+var ENVIRONMENT_IS_WORKER = !!globalThis.WorkerGlobalScope;
+
+// N.b. Electron.js environment is simultaneously a NODE-environment, but
+// also a web environment.
+var ENVIRONMENT_IS_NODE = globalThis.process?.versions?.node && globalThis.process?.type != "renderer";
+
+if (ENVIRONMENT_IS_NODE) {
+ // When building an ES module `require` is not normally available.
+ // We need to use `createRequire()` to construct the require()` function.
+ const {createRequire} = await import("node:module");
+ /** @suppress{duplicate} */ var require = createRequire(import.meta.url);
+}
+
+// --pre-jses are emitted after the Module integration code, so that they can
+// refer to Module (if they choose; they can also define Module)
+var arguments_ = [];
+
+var thisProgram = "./this.program";
+
+var quit_ = (status, toThrow) => {
+ throw toThrow;
+};
+
+var _scriptName = import.meta.url;
+
+// `/` should be present at the end if `scriptDirectory` is not empty
+var scriptDirectory = "";
+
+function locateFile(path) {
+ if (Module["locateFile"]) {
+ return Module["locateFile"](path, scriptDirectory);
+ }
+ return scriptDirectory + path;
+}
+
+// Hooks that are implemented differently in different runtime environments.
+var readAsync, readBinary;
+
+if (ENVIRONMENT_IS_NODE) {
+ // These modules will usually be used on Node.js. Load them eagerly to avoid
+ // the complexity of lazy-loading.
+ var fs = require("node:fs");
+ if (_scriptName.startsWith("file:")) {
+ scriptDirectory = require("node:path").dirname(require("node:url").fileURLToPath(_scriptName)) + "/";
+ }
+ // include: node_shell_read.js
+ readBinary = filename => {
+ // We need to re-wrap `file://` strings to URLs.
+ filename = isFileURI(filename) ? new URL(filename) : filename;
+ var ret = fs.readFileSync(filename);
+ return ret;
+ };
+ readAsync = async (filename, binary = true) => {
+ // See the comment in the `readBinary` function.
+ filename = isFileURI(filename) ? new URL(filename) : filename;
+ var ret = fs.readFileSync(filename, binary ? undefined : "utf8");
+ return ret;
+ };
+ // end include: node_shell_read.js
+ if (process.argv.length > 1) {
+ thisProgram = process.argv[1].replace(/\\/g, "/");
+ }
+ arguments_ = process.argv.slice(2);
+ quit_ = (status, toThrow) => {
+ process.exitCode = status;
+ throw toThrow;
+ };
+} else // Note that this includes Node.js workers when relevant (pthreads is enabled).
+// Node.js workers are detected as a combination of ENVIRONMENT_IS_WORKER and
+// ENVIRONMENT_IS_NODE.
+if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
+ try {
+ scriptDirectory = new URL(".", _scriptName).href;
+ } catch {}
+ {
+ // include: web_or_worker_shell_read.js
+ if (ENVIRONMENT_IS_WORKER) {
+ readBinary = url => {
+ var xhr = new XMLHttpRequest;
+ xhr.open("GET", url, false);
+ xhr.responseType = "arraybuffer";
+ xhr.send(null);
+ return new Uint8Array(/** @type{!ArrayBuffer} */ (xhr.response));
+ };
+ }
+ readAsync = async url => {
+ // Fetch has some additional restrictions over XHR, like it can't be used on a file:// url.
+ // See https://github.com/github/fetch/pull/92#issuecomment-140665932
+ // Cordova or Electron apps are typically loaded from a file:// url.
+ // So use XHR on webview if URL is a file URL.
+ if (isFileURI(url)) {
+ return new Promise((resolve, reject) => {
+ var xhr = new XMLHttpRequest;
+ xhr.open("GET", url, true);
+ xhr.responseType = "arraybuffer";
+ xhr.onload = () => {
+ if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) {
+ // file URLs can return 0
+ resolve(xhr.response);
+ return;
+ }
+ reject(xhr.status);
+ };
+ xhr.onerror = reject;
+ xhr.send(null);
+ });
+ }
+ var response = await fetch(url, {
+ credentials: "same-origin"
+ });
+ if (response.ok) {
+ return response.arrayBuffer();
+ }
+ throw new Error(response.status + " : " + response.url);
+ };
+ }
+} else {}
+
+var out = console.log.bind(console);
+
+var err = console.error.bind(console);
+
+// end include: shell.js
+// include: preamble.js
+// === Preamble library stuff ===
+// Documentation for the public APIs defined in this file must be updated in:
+// site/source/docs/api_reference/preamble.js.rst
+// A prebuilt local version of the documentation is available at:
+// site/build/text/docs/api_reference/preamble.js.txt
+// You can also build docs locally as HTML or other formats in site/
+// An online HTML version (which may be of a different version of Emscripten)
+// is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html
+var wasmBinary;
+
+// Wasm globals
+//========================================
+// Runtime essentials
+//========================================
+// whether we are quitting the application. no code should run after this.
+// set in exit() and abort()
+var ABORT = false;
+
+// set by exit() and abort(). Passed to 'onExit' handler.
+// NOTE: This is also used as the process return code in shell environments
+// but only when noExitRuntime is false.
+var EXITSTATUS;
+
+// In STRICT mode, we only define assert() when ASSERTIONS is set. i.e. we
+// don't define it at all in release modes. This matches the behaviour of
+// MINIMAL_RUNTIME.
+// TODO(sbc): Make this the default even without STRICT enabled.
+/** @type {function(*, string=)} */ function assert(condition, text) {
+ if (!condition) {
+ // This build was created without ASSERTIONS defined. `assert()` should not
+ // ever be called in this configuration but in case there are callers in
+ // the wild leave this simple abort() implementation here for now.
+ abort(text);
+ }
+}
+
+/**
+ * Indicates whether filename is delivered via file protocol (as opposed to http/https)
+ * @noinline
+ */ var isFileURI = filename => filename.startsWith("file://");
+
+// include: runtime_common.js
+// include: runtime_stack_check.js
+// end include: runtime_stack_check.js
+// include: runtime_exceptions.js
+// end include: runtime_exceptions.js
+// include: runtime_debug.js
+// end include: runtime_debug.js
+var readyPromiseResolve, readyPromiseReject;
+
+// Memory management
+var /** @type {!Int8Array} */ HEAP8, /** @type {!Uint8Array} */ HEAPU8, /** @type {!Int16Array} */ HEAP16, /** @type {!Uint16Array} */ HEAPU16, /** @type {!Int32Array} */ HEAP32, /** @type {!Uint32Array} */ HEAPU32, /** @type {!Float32Array} */ HEAPF32, /** @type {!Float64Array} */ HEAPF64;
+
+var runtimeInitialized = false;
+
+function updateMemoryViews() {
+ var b = wasmMemory.buffer;
+ HEAP8 = new Int8Array(b);
+ HEAP16 = new Int16Array(b);
+ Module["HEAPU8"] = HEAPU8 = new Uint8Array(b);
+ HEAPU16 = new Uint16Array(b);
+ HEAP32 = new Int32Array(b);
+ Module["HEAPU32"] = HEAPU32 = new Uint32Array(b);
+ Module["HEAPF32"] = HEAPF32 = new Float32Array(b);
+ Module["HEAPF64"] = HEAPF64 = new Float64Array(b);
+}
+
+// include: memoryprofiler.js
+// end include: memoryprofiler.js
+// end include: runtime_common.js
+function preRun() {
+ if (Module["preRun"]) {
+ if (typeof Module["preRun"] == "function") Module["preRun"] = [ Module["preRun"] ];
+ while (Module["preRun"].length) {
+ addOnPreRun(Module["preRun"].shift());
+ }
+ }
+ // Begin ATPRERUNS hooks
+ callRuntimeCallbacks(onPreRuns);
+}
+
+function initRuntime() {
+ runtimeInitialized = true;
+ // Begin ATINITS hooks
+ if (!Module["noFSInit"] && !FS.initialized) FS.init();
+ TTY.init();
+ // End ATINITS hooks
+ wasmExports["tc"]();
+ // Begin ATPOSTCTORS hooks
+ FS.ignorePermissions = false;
+}
+
+function postRun() {
+ // PThreads reuse the runtime from the main thread.
+ if (Module["postRun"]) {
+ if (typeof Module["postRun"] == "function") Module["postRun"] = [ Module["postRun"] ];
+ while (Module["postRun"].length) {
+ addOnPostRun(Module["postRun"].shift());
+ }
+ }
+ // Begin ATPOSTRUNS hooks
+ callRuntimeCallbacks(onPostRuns);
+}
+
+/** @param {string|number=} what */ function abort(what) {
+ Module["onAbort"]?.(what);
+ what = "Aborted(" + what + ")";
+ // TODO(sbc): Should we remove printing and leave it up to whoever
+ // catches the exception?
+ err(what);
+ ABORT = true;
+ what += ". Build with -sASSERTIONS for more info.";
+ // Use a wasm runtime error, because a JS error might be seen as a foreign
+ // exception, which means we'd run destructors on it. We need the error to
+ // simply make the program stop.
+ // FIXME This approach does not work in Wasm EH because it currently does not assume
+ // all RuntimeErrors are from traps; it decides whether a RuntimeError is from
+ // a trap or not based on a hidden field within the object. So at the moment
+ // we don't have a way of throwing a wasm trap from JS. TODO Make a JS API that
+ // allows this in the wasm spec.
+ // Suppress closure compiler warning here. Closure compiler's builtin extern
+ // definition for WebAssembly.RuntimeError claims it takes no arguments even
+ // though it can.
+ // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure gets fixed.
+ /** @suppress {checkTypes} */ var e = new WebAssembly.RuntimeError(what);
+ readyPromiseReject?.(e);
+ // Throw the error whether or not MODULARIZE is set because abort is used
+ // in code paths apart from instantiation where an exception is expected
+ // to be thrown when abort is called.
+ throw e;
+}
+
+var wasmBinaryFile;
+
+function findWasmBinary() {
+ if (Module["locateFile"]) {
+ return locateFile("genai_wasm_module_internal.wasm");
+ }
+ // Use bundler-friendly `new URL(..., import.meta.url)` pattern; works in browsers too.
+ return new URL("genai_wasm_module_internal.wasm", import.meta.url).href;
+}
+
+function getBinarySync(file) {
+ if (file == wasmBinaryFile && wasmBinary) {
+ return new Uint8Array(wasmBinary);
+ }
+ if (readBinary) {
+ return readBinary(file);
+ }
+ // Throwing a plain string here, even though it not normally advisable since
+ // this gets turning into an `abort` in instantiateArrayBuffer.
+ throw "both async and sync fetching of the wasm failed";
+}
+
+async function getWasmBinary(binaryFile) {
+ // If we don't have the binary yet, load it asynchronously using readAsync.
+ if (!wasmBinary) {
+ // Fetch the binary using readAsync
+ try {
+ var response = await readAsync(binaryFile);
+ return new Uint8Array(response);
+ } catch {}
+ }
+ // Otherwise, getBinarySync should be able to get it synchronously
+ return getBinarySync(binaryFile);
+}
+
+async function instantiateArrayBuffer(binaryFile, imports) {
+ try {
+ var binary = await getWasmBinary(binaryFile);
+ var instance = await WebAssembly.instantiate(binary, imports);
+ return instance;
+ } catch (reason) {
+ err(`failed to asynchronously prepare wasm: ${reason}`);
+ abort(reason);
+ }
+}
+
+async function instantiateAsync(binary, binaryFile, imports) {
+ if (!binary && !isFileURI(binaryFile) && !ENVIRONMENT_IS_NODE) {
+ try {
+ var response = fetch(binaryFile, {
+ credentials: "same-origin"
+ });
+ var instantiationResult = await WebAssembly.instantiateStreaming(response, imports);
+ return instantiationResult;
+ } catch (reason) {
+ // We expect the most common failure cause to be a bad MIME type for the binary,
+ // in which case falling back to ArrayBuffer instantiation should work.
+ err(`wasm streaming compile failed: ${reason}`);
+ err("falling back to ArrayBuffer instantiation");
+ }
+ }
+ return instantiateArrayBuffer(binaryFile, imports);
+}
+
+function getWasmImports() {
+ // prepare imports
+ var imports = {
+ "a": wasmImports
+ };
+ return imports;
+}
+
+// Create the wasm instance.
+// Receives the wasm imports, returns the exports.
+async function createWasm() {
+ // Load the wasm module and create an instance of using native support in the JS engine.
+ // handle a generated wasm instance, receiving its exports and
+ // performing other necessary setup
+ /** @param {WebAssembly.Module=} module*/ function receiveInstance(instance, module) {
+ wasmExports = instance.exports;
+ wasmExports = Asyncify.instrumentWasmExports(wasmExports);
+ wasmExports = applySignatureConversions(wasmExports);
+ assignWasmExports(wasmExports);
+ updateMemoryViews();
+ return wasmExports;
+ }
+ // Prefer streaming instantiation if available.
+ function receiveInstantiationResult(result) {
+ // 'result' is a ResultObject object which has both the module and instance.
+ // receiveInstance() will swap in the exports (to Module.asm) so they can be called
+ // TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193, the above line no longer optimizes out down to the following line.
+ // When the regression is fixed, can restore the above PTHREADS-enabled path.
+ return receiveInstance(result["instance"]);
+ }
+ var info = getWasmImports();
+ // User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback
+ // to manually instantiate the Wasm module themselves. This allows pages to
+ // run the instantiation parallel to any other async startup actions they are
+ // performing.
+ // Also pthreads and wasm workers initialize the wasm instance through this
+ // path.
+ if (Module["instantiateWasm"]) {
+ return new Promise((resolve, reject) => {
+ Module["instantiateWasm"](info, (inst, mod) => {
+ resolve(receiveInstance(inst, mod));
+ });
+ });
+ }
+ wasmBinaryFile ??= findWasmBinary();
+ var result = await instantiateAsync(wasmBinary, wasmBinaryFile, info);
+ var exports = receiveInstantiationResult(result);
+ return exports;
+}
+
+// Globals used by JS i64 conversions (see makeSetValue)
+var tempDouble;
+
+var tempI64;
+
+// end include: preamble.js
+// Begin JS library code
+var handleException = e => {
+ // Certain exception types we do not treat as errors since they are used for
+ // internal control flow.
+ // 1. ExitStatus, which is thrown by exit()
+ // 2. "unwind", which is thrown by emscripten_unwind_to_js_event_loop() and others
+ // that wish to return to JS event loop.
+ if (e instanceof ExitStatus || e == "unwind") {
+ return EXITSTATUS;
+ }
+ quit_(1, e);
+};
+
+class ExitStatus {
+ name="ExitStatus";
+ constructor(status) {
+ this.message = `Program terminated with exit(${status})`;
+ this.status = status;
+ }
+}
+
+var runtimeKeepaliveCounter = 0;
+
+var keepRuntimeAlive = () => noExitRuntime || runtimeKeepaliveCounter > 0;
+
+var _proc_exit = code => {
+ EXITSTATUS = code;
+ if (!keepRuntimeAlive()) {
+ Module["onExit"]?.(code);
+ ABORT = true;
+ }
+ quit_(code, new ExitStatus(code));
+};
+
+/** @param {boolean|number=} implicit */ var exitJS = (status, implicit) => {
+ EXITSTATUS = status;
+ _proc_exit(status);
+};
+
+var _exit = exitJS;
+
+var maybeExit = () => {
+ if (!keepRuntimeAlive()) {
+ try {
+ _exit(EXITSTATUS);
+ } catch (e) {
+ handleException(e);
+ }
+ }
+};
+
+var callUserCallback = func => {
+ if (ABORT) {
+ return;
+ }
+ try {
+ return func();
+ } catch (e) {
+ handleException(e);
+ } finally {
+ maybeExit();
+ }
+};
+
+function getFullscreenElement() {
+ return document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.webkitCurrentFullScreenElement || document.msFullscreenElement;
+}
+
+/** @param {number=} timeout */ var safeSetTimeout = (func, timeout) => setTimeout(() => {
+ callUserCallback(func);
+}, timeout);
+
+var warnOnce = text => {
+ warnOnce.shown ||= {};
+ if (!warnOnce.shown[text]) {
+ warnOnce.shown[text] = 1;
+ if (ENVIRONMENT_IS_NODE) text = "warning: " + text;
+ err(text);
+ }
+};
+
+var preloadPlugins = [];
+
+var Browser = {
+ useWebGL: false,
+ isFullscreen: false,
+ pointerLock: false,
+ moduleContextCreatedCallbacks: [],
+ workers: [],
+ preloadedImages: {},
+ preloadedAudios: {},
+ getCanvas: () => Module["canvas"],
+ init() {
+ if (Browser.initted) return;
+ Browser.initted = true;
+ // Support for plugins that can process preloaded files. You can add more of these to
+ // your app by creating and appending to preloadPlugins.
+ // Each plugin is asked if it can handle a file based on the file's name. If it can,
+ // it is given the file's raw data. When it is done, it calls a callback with the file's
+ // (possibly modified) data. For example, a plugin might decompress a file, or it
+ // might create some side data structure for use later (like an Image element, etc.).
+ var imagePlugin = {};
+ imagePlugin["canHandle"] = name => !Module["noImageDecoding"] && /\.(jpg|jpeg|png|bmp|webp)$/i.test(name);
+ imagePlugin["handle"] = async (byteArray, name) => {
+ var b = new Blob([ byteArray ], {
+ type: Browser.getMimetype(name)
+ });
+ if (b.size !== byteArray.length) {
+ // Safari bug #118630
+ // Safari's Blob can only take an ArrayBuffer
+ b = new Blob([ (new Uint8Array(byteArray)).buffer ], {
+ type: Browser.getMimetype(name)
+ });
+ }
+ var url = URL.createObjectURL(b);
+ return new Promise((resolve, reject) => {
+ var img = new Image;
+ img.onload = () => {
+ var canvas = /** @type {!HTMLCanvasElement} */ (document.createElement("canvas"));
+ canvas.width = img.width;
+ canvas.height = img.height;
+ var ctx = canvas.getContext("2d");
+ ctx.drawImage(img, 0, 0);
+ Browser.preloadedImages[name] = canvas;
+ URL.revokeObjectURL(url);
+ resolve(byteArray);
+ };
+ img.onerror = event => {
+ err(`Image ${url} could not be decoded`);
+ reject();
+ };
+ img.src = url;
+ });
+ };
+ preloadPlugins.push(imagePlugin);
+ var audioPlugin = {};
+ audioPlugin["canHandle"] = name => !Module["noAudioDecoding"] && name.slice(-4) in {
+ ".ogg": 1,
+ ".wav": 1,
+ ".mp3": 1
+ };
+ audioPlugin["handle"] = async (byteArray, name) => new Promise((resolve, reject) => {
+ var done = false;
+ function finish(audio) {
+ if (done) return;
+ done = true;
+ Browser.preloadedAudios[name] = audio;
+ resolve(byteArray);
+ }
+ var b = new Blob([ byteArray ], {
+ type: Browser.getMimetype(name)
+ });
+ var url = URL.createObjectURL(b);
+ // XXX we never revoke this!
+ var audio = new Audio;
+ audio.addEventListener("canplaythrough", () => finish(audio), false);
+ // use addEventListener due to chromium bug 124926
+ audio.onerror = event => {
+ if (done) return;
+ err(`warning: browser could not fully decode audio ${name}, trying slower base64 approach`);
+ function encode64(data) {
+ var BASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ var PAD = "=";
+ var ret = "";
+ var leftchar = 0;
+ var leftbits = 0;
+ for (var i = 0; i < data.length; i++) {
+ leftchar = (leftchar << 8) | data[i];
+ leftbits += 8;
+ while (leftbits >= 6) {
+ var curr = (leftchar >> (leftbits - 6)) & 63;
+ leftbits -= 6;
+ ret += BASE[curr];
+ }
+ }
+ if (leftbits == 2) {
+ ret += BASE[(leftchar & 3) << 4];
+ ret += PAD + PAD;
+ } else if (leftbits == 4) {
+ ret += BASE[(leftchar & 15) << 2];
+ ret += PAD;
+ }
+ return ret;
+ }
+ audio.src = "data:audio/x-" + name.slice(-3) + ";base64," + encode64(byteArray);
+ finish(audio);
+ };
+ audio.src = url;
+ // workaround for chrome bug 124926 - we do not always get oncanplaythrough or onerror
+ safeSetTimeout(() => {
+ finish(audio);
+ }, 1e4);
+ });
+ preloadPlugins.push(audioPlugin);
+ // Canvas event setup
+ function pointerLockChange() {
+ var canvas = Browser.getCanvas();
+ Browser.pointerLock = document.pointerLockElement === canvas;
+ }
+ var canvas = Browser.getCanvas();
+ if (canvas) {
+ // forced aspect ratio can be enabled by defining 'forcedAspectRatio' on Module
+ // Module['forcedAspectRatio'] = 4 / 3;
+ document.addEventListener("pointerlockchange", pointerLockChange, false);
+ if (Module["elementPointerLock"]) {
+ canvas.addEventListener("click", ev => {
+ if (!Browser.pointerLock && Browser.getCanvas().requestPointerLock) {
+ Browser.getCanvas().requestPointerLock();
+ ev.preventDefault();
+ }
+ }, false);
+ }
+ }
+ },
+ createContext(/** @type {HTMLCanvasElement} */ canvas, useWebGL, setInModule, webGLContextAttributes) {
+ if (useWebGL && Module["ctx"] && canvas == Browser.getCanvas()) return Module["ctx"];
+ // no need to recreate GL context if it's already been created for this canvas.
+ var ctx;
+ var contextHandle;
+ if (useWebGL) {
+ // For GLES2/desktop GL compatibility, adjust a few defaults to be different to WebGL defaults, so that they align better with the desktop defaults.
+ var contextAttributes = {
+ antialias: false,
+ alpha: false,
+ majorVersion: (typeof WebGL2RenderingContext != "undefined") ? 2 : 1
+ };
+ if (webGLContextAttributes) {
+ for (var attribute in webGLContextAttributes) {
+ contextAttributes[attribute] = webGLContextAttributes[attribute];
+ }
+ }
+ // This check of existence of GL is here to satisfy Closure compiler, which yells if variable GL is referenced below but GL object is not
+ // actually compiled in because application is not doing any GL operations. TODO: Ideally if GL is not being used, this function
+ // Browser.createContext() should not even be emitted.
+ if (typeof GL != "undefined") {
+ contextHandle = GL.createContext(canvas, contextAttributes);
+ if (contextHandle) {
+ ctx = GL.getContext(contextHandle).GLctx;
+ }
+ }
+ } else {
+ ctx = canvas.getContext("2d");
+ }
+ if (!ctx) return null;
+ if (setInModule) {
+ Module["ctx"] = ctx;
+ if (useWebGL) GL.makeContextCurrent(contextHandle);
+ Browser.useWebGL = useWebGL;
+ Browser.moduleContextCreatedCallbacks.forEach(callback => callback());
+ Browser.init();
+ }
+ return ctx;
+ },
+ fullscreenHandlersInstalled: false,
+ lockPointer: undefined,
+ resizeCanvas: undefined,
+ requestFullscreen(lockPointer, resizeCanvas) {
+ Browser.lockPointer = lockPointer;
+ Browser.resizeCanvas = resizeCanvas;
+ if (typeof Browser.lockPointer == "undefined") Browser.lockPointer = true;
+ if (typeof Browser.resizeCanvas == "undefined") Browser.resizeCanvas = false;
+ var canvas = Browser.getCanvas();
+ function fullscreenChange() {
+ Browser.isFullscreen = false;
+ var canvasContainer = canvas.parentNode;
+ if (getFullscreenElement() === canvasContainer) {
+ canvas.exitFullscreen = Browser.exitFullscreen;
+ if (Browser.lockPointer) canvas.requestPointerLock();
+ Browser.isFullscreen = true;
+ if (Browser.resizeCanvas) {
+ Browser.setFullscreenCanvasSize();
+ } else {
+ Browser.updateCanvasDimensions(canvas);
+ }
+ } else {
+ // remove the full screen specific parent of the canvas again to restore the HTML structure from before going full screen
+ canvasContainer.parentNode.insertBefore(canvas, canvasContainer);
+ canvasContainer.parentNode.removeChild(canvasContainer);
+ if (Browser.resizeCanvas) {
+ Browser.setWindowedCanvasSize();
+ } else {
+ Browser.updateCanvasDimensions(canvas);
+ }
+ }
+ Module["onFullScreen"]?.(Browser.isFullscreen);
+ Module["onFullscreen"]?.(Browser.isFullscreen);
+ }
+ if (!Browser.fullscreenHandlersInstalled) {
+ Browser.fullscreenHandlersInstalled = true;
+ document.addEventListener("fullscreenchange", fullscreenChange, false);
+ document.addEventListener("mozfullscreenchange", fullscreenChange, false);
+ document.addEventListener("webkitfullscreenchange", fullscreenChange, false);
+ document.addEventListener("MSFullscreenChange", fullscreenChange, false);
+ }
+ // create a new parent to ensure the canvas has no siblings. this allows browsers to optimize full screen performance when its parent is the full screen root
+ var canvasContainer = document.createElement("div");
+ canvas.parentNode.insertBefore(canvasContainer, canvas);
+ canvasContainer.appendChild(canvas);
+ // use parent of canvas as full screen root to allow aspect ratio correction (Firefox stretches the root to screen size)
+ canvasContainer.requestFullscreen = canvasContainer["requestFullscreen"] || canvasContainer["mozRequestFullScreen"] || canvasContainer["msRequestFullscreen"] || (canvasContainer["webkitRequestFullscreen"] ? () => canvasContainer["webkitRequestFullscreen"](Element["ALLOW_KEYBOARD_INPUT"]) : null) || (canvasContainer["webkitRequestFullScreen"] ? () => canvasContainer["webkitRequestFullScreen"](Element["ALLOW_KEYBOARD_INPUT"]) : null);
+ canvasContainer.requestFullscreen();
+ },
+ exitFullscreen() {
+ // This is workaround for chrome. Trying to exit from fullscreen
+ // not in fullscreen state will cause "TypeError: Document not active"
+ // in chrome. See https://github.com/emscripten-core/emscripten/pull/8236
+ if (!Browser.isFullscreen) {
+ return false;
+ }
+ var CFS = document["exitFullscreen"] || document["cancelFullScreen"] || document["mozCancelFullScreen"] || document["msExitFullscreen"] || document["webkitCancelFullScreen"] || (() => {});
+ CFS.apply(document, []);
+ return true;
+ },
+ safeSetTimeout(func, timeout) {
+ // Legacy function, this is used by the SDL2 port so we need to keep it
+ // around at least until that is updated.
+ // See https://github.com/libsdl-org/SDL/pull/6304
+ return safeSetTimeout(func, timeout);
+ },
+ getMimetype(name) {
+ return {
+ "jpg": "image/jpeg",
+ "jpeg": "image/jpeg",
+ "png": "image/png",
+ "bmp": "image/bmp",
+ "ogg": "audio/ogg",
+ "wav": "audio/wav",
+ "mp3": "audio/mpeg"
+ }[name.slice(name.lastIndexOf(".") + 1)];
+ },
+ getUserMedia(func) {
+ window.getUserMedia ||= navigator["getUserMedia"] || navigator["mozGetUserMedia"];
+ window.getUserMedia(func);
+ },
+ getMovementX(event) {
+ return event["movementX"] || event["mozMovementX"] || event["webkitMovementX"] || 0;
+ },
+ getMovementY(event) {
+ return event["movementY"] || event["mozMovementY"] || event["webkitMovementY"] || 0;
+ },
+ getMouseWheelDelta(event) {
+ var delta = 0;
+ switch (event.type) {
+ case "DOMMouseScroll":
+ // 3 lines make up a step
+ delta = event.detail / 3;
+ break;
+
+ case "mousewheel":
+ // 120 units make up a step
+ delta = event.wheelDelta / 120;
+ break;
+
+ case "wheel":
+ delta = event.deltaY;
+ switch (event.deltaMode) {
+ case 0:
+ // DOM_DELTA_PIXEL: 100 pixels make up a step
+ delta /= 100;
+ break;
+
+ case 1:
+ // DOM_DELTA_LINE: 3 lines make up a step
+ delta /= 3;
+ break;
+
+ case 2:
+ // DOM_DELTA_PAGE: A page makes up 80 steps
+ delta *= 80;
+ break;
+
+ default:
+ abort("unrecognized mouse wheel delta mode: " + event.deltaMode);
+ }
+ break;
+
+ default:
+ abort("unrecognized mouse wheel event: " + event.type);
+ }
+ return delta;
+ },
+ mouseX: 0,
+ mouseY: 0,
+ mouseMovementX: 0,
+ mouseMovementY: 0,
+ touches: {},
+ lastTouches: {},
+ calculateMouseCoords(pageX, pageY) {
+ // Calculate the movement based on the changes
+ // in the coordinates.
+ var canvas = Browser.getCanvas();
+ var rect = canvas.getBoundingClientRect();
+ // Neither .scrollX or .pageXOffset are defined in a spec, but
+ // we prefer .scrollX because it is currently in a spec draft.
+ // (see: http://www.w3.org/TR/2013/WD-cssom-view-20131217/)
+ var scrollX = ((typeof window.scrollX != "undefined") ? window.scrollX : window.pageXOffset);
+ var scrollY = ((typeof window.scrollY != "undefined") ? window.scrollY : window.pageYOffset);
+ var adjustedX = pageX - (scrollX + rect.left);
+ var adjustedY = pageY - (scrollY + rect.top);
+ // the canvas might be CSS-scaled compared to its backbuffer;
+ // SDL-using content will want mouse coordinates in terms
+ // of backbuffer units.
+ adjustedX = adjustedX * (canvas.width / rect.width);
+ adjustedY = adjustedY * (canvas.height / rect.height);
+ return {
+ x: adjustedX,
+ y: adjustedY
+ };
+ },
+ setMouseCoords(pageX, pageY) {
+ const {x, y} = Browser.calculateMouseCoords(pageX, pageY);
+ Browser.mouseMovementX = x - Browser.mouseX;
+ Browser.mouseMovementY = y - Browser.mouseY;
+ Browser.mouseX = x;
+ Browser.mouseY = y;
+ },
+ calculateMouseEvent(event) {
+ // event should be mousemove, mousedown or mouseup
+ if (Browser.pointerLock) {
+ // When the pointer is locked, calculate the coordinates
+ // based on the movement of the mouse.
+ // Workaround for Firefox bug 764498
+ if (event.type != "mousemove" && ("mozMovementX" in event)) {
+ Browser.mouseMovementX = Browser.mouseMovementY = 0;
+ } else {
+ Browser.mouseMovementX = Browser.getMovementX(event);
+ Browser.mouseMovementY = Browser.getMovementY(event);
+ }
+ // add the mouse delta to the current absolute mouse position
+ Browser.mouseX += Browser.mouseMovementX;
+ Browser.mouseY += Browser.mouseMovementY;
+ } else {
+ if (event.type === "touchstart" || event.type === "touchend" || event.type === "touchmove") {
+ var touch = event.touch;
+ if (touch === undefined) {
+ return;
+ }
+ var coords = Browser.calculateMouseCoords(touch.pageX, touch.pageY);
+ if (event.type === "touchstart") {
+ Browser.lastTouches[touch.identifier] = coords;
+ Browser.touches[touch.identifier] = coords;
+ } else if (event.type === "touchend" || event.type === "touchmove") {
+ var last = Browser.touches[touch.identifier];
+ last ||= coords;
+ Browser.lastTouches[touch.identifier] = last;
+ Browser.touches[touch.identifier] = coords;
+ }
+ return;
+ }
+ Browser.setMouseCoords(event.pageX, event.pageY);
+ }
+ },
+ resizeListeners: [],
+ updateResizeListeners() {
+ var canvas = Browser.getCanvas();
+ Browser.resizeListeners.forEach(listener => listener(canvas.width, canvas.height));
+ },
+ setCanvasSize(width, height, noUpdates) {
+ var canvas = Browser.getCanvas();
+ Browser.updateCanvasDimensions(canvas, width, height);
+ if (!noUpdates) Browser.updateResizeListeners();
+ },
+ windowedWidth: 0,
+ windowedHeight: 0,
+ setFullscreenCanvasSize() {
+ // check if SDL is available
+ if (typeof SDL != "undefined") {
+ var flags = HEAPU32[((SDL.screen) >>> 2) >>> 0];
+ flags = flags | 8388608;
+ // set SDL_FULLSCREEN flag
+ HEAP32[((SDL.screen) >>> 2) >>> 0] = flags;
+ }
+ Browser.updateCanvasDimensions(Browser.getCanvas());
+ Browser.updateResizeListeners();
+ },
+ setWindowedCanvasSize() {
+ // check if SDL is available
+ if (typeof SDL != "undefined") {
+ var flags = HEAPU32[((SDL.screen) >>> 2) >>> 0];
+ flags = flags & ~8388608;
+ // clear SDL_FULLSCREEN flag
+ HEAP32[((SDL.screen) >>> 2) >>> 0] = flags;
+ }
+ Browser.updateCanvasDimensions(Browser.getCanvas());
+ Browser.updateResizeListeners();
+ },
+ updateCanvasDimensions(canvas, wNative, hNative) {
+ if (wNative && hNative) {
+ canvas.widthNative = wNative;
+ canvas.heightNative = hNative;
+ } else {
+ wNative = canvas.widthNative;
+ hNative = canvas.heightNative;
+ }
+ var w = wNative;
+ var h = hNative;
+ if (Module["forcedAspectRatio"] > 0) {
+ if (w / h < Module["forcedAspectRatio"]) {
+ w = Math.round(h * Module["forcedAspectRatio"]);
+ } else {
+ h = Math.round(w / Module["forcedAspectRatio"]);
+ }
+ }
+ if ((getFullscreenElement() === canvas.parentNode) && (typeof screen != "undefined")) {
+ var factor = Math.min(screen.width / w, screen.height / h);
+ w = Math.round(w * factor);
+ h = Math.round(h * factor);
+ }
+ if (Browser.resizeCanvas) {
+ if (canvas.width != w) canvas.width = w;
+ if (canvas.height != h) canvas.height = h;
+ if (typeof canvas.style != "undefined") {
+ canvas.style.removeProperty("width");
+ canvas.style.removeProperty("height");
+ }
+ } else {
+ if (canvas.width != wNative) canvas.width = wNative;
+ if (canvas.height != hNative) canvas.height = hNative;
+ if (typeof canvas.style != "undefined") {
+ if (w != wNative || h != hNative) {
+ canvas.style.setProperty("width", w + "px", "important");
+ canvas.style.setProperty("height", h + "px", "important");
+ } else {
+ canvas.style.removeProperty("width");
+ canvas.style.removeProperty("height");
+ }
+ }
+ }
+ }
+};
+
+var callRuntimeCallbacks = callbacks => {
+ while (callbacks.length > 0) {
+ // Pass the module as the first argument.
+ callbacks.shift()(Module);
+ }
+};
+
+var onPostRuns = [];
+
+var addOnPostRun = cb => onPostRuns.push(cb);
+
+var onPreRuns = [];
+
+var addOnPreRun = cb => onPreRuns.push(cb);
+
+var dynCalls = {};
+
+var dynCallLegacy = (sig, ptr, args) => {
+ sig = sig.replace(/p/g, "i");
+ var f = dynCalls[sig];
+ return f(ptr, ...args);
+};
+
+var dynCall = (sig, ptr, args = [], promising = false) => {
+ var rtn = dynCallLegacy(sig, ptr, args);
+ function convert(rtn) {
+ return sig[0] == "p" ? rtn >>> 0 : rtn;
+ }
+ return convert(rtn);
+};
+
+var noExitRuntime = true;
+
+var stackRestore = val => __emscripten_stack_restore(val);
+
+var stackSave = () => _emscripten_stack_get_current();
+
+class ExceptionInfo {
+ // excPtr - Thrown object pointer to wrap. Metadata pointer is calculated from it.
+ constructor(excPtr) {
+ this.excPtr = excPtr;
+ this.ptr = excPtr - 24;
+ }
+ set_type(type) {
+ HEAPU32[(((this.ptr) + (4)) >>> 2) >>> 0] = type;
+ }
+ get_type() {
+ return HEAPU32[(((this.ptr) + (4)) >>> 2) >>> 0];
+ }
+ set_destructor(destructor) {
+ HEAPU32[(((this.ptr) + (8)) >>> 2) >>> 0] = destructor;
+ }
+ get_destructor() {
+ return HEAPU32[(((this.ptr) + (8)) >>> 2) >>> 0];
+ }
+ set_caught(caught) {
+ caught = caught ? 1 : 0;
+ HEAP8[(this.ptr) + (12) >>> 0] = caught;
+ }
+ get_caught() {
+ return HEAP8[(this.ptr) + (12) >>> 0] != 0;
+ }
+ set_rethrown(rethrown) {
+ rethrown = rethrown ? 1 : 0;
+ HEAP8[(this.ptr) + (13) >>> 0] = rethrown;
+ }
+ get_rethrown() {
+ return HEAP8[(this.ptr) + (13) >>> 0] != 0;
+ }
+ // Initialize native structure fields. Should be called once after allocated.
+ init(type, destructor) {
+ this.set_adjusted_ptr(0);
+ this.set_type(type);
+ this.set_destructor(destructor);
+ }
+ set_adjusted_ptr(adjustedPtr) {
+ HEAPU32[(((this.ptr) + (16)) >>> 2) >>> 0] = adjustedPtr;
+ }
+ get_adjusted_ptr() {
+ return HEAPU32[(((this.ptr) + (16)) >>> 2) >>> 0];
+ }
+}
+
+var exceptionLast = 0;
+
+var uncaughtExceptionCount = 0;
+
+var convertI32PairToI53Checked = (lo, hi) => ((hi + 2097152) >>> 0 < 4194305 - !!lo) ? (lo >>> 0) + hi * 4294967296 : NaN;
+
+function ___cxa_throw(ptr, type, destructor) {
+ ptr >>>= 0;
+ type >>>= 0;
+ destructor >>>= 0;
+ var info = new ExceptionInfo(ptr);
+ // Initialize ExceptionInfo content after it was allocated in __cxa_allocate_exception.
+ info.init(type, destructor);
+ exceptionLast = ptr;
+ uncaughtExceptionCount++;
+ throw exceptionLast;
+}
+
+function __Unwind_RaiseException(ex) {
+ ex >>>= 0;
+ err("Warning: _Unwind_RaiseException is not correctly implemented");
+ return ___cxa_throw(ex, 0, 0);
+}
+
+var PATH = {
+ isAbs: path => path.charAt(0) === "/",
+ splitPath: filename => {
+ var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
+ return splitPathRe.exec(filename).slice(1);
+ },
+ normalizeArray: (parts, allowAboveRoot) => {
+ // if the path tries to go above the root, `up` ends up > 0
+ var up = 0;
+ for (var i = parts.length - 1; i >= 0; i--) {
+ var last = parts[i];
+ if (last === ".") {
+ parts.splice(i, 1);
+ } else if (last === "..") {
+ parts.splice(i, 1);
+ up++;
+ } else if (up) {
+ parts.splice(i, 1);
+ up--;
+ }
+ }
+ // if the path is allowed to go above the root, restore leading ..s
+ if (allowAboveRoot) {
+ for (;up; up--) {
+ parts.unshift("..");
+ }
+ }
+ return parts;
+ },
+ normalize: path => {
+ var isAbsolute = PATH.isAbs(path), trailingSlash = path.slice(-1) === "/";
+ // Normalize the path
+ path = PATH.normalizeArray(path.split("/").filter(p => !!p), !isAbsolute).join("/");
+ if (!path && !isAbsolute) {
+ path = ".";
+ }
+ if (path && trailingSlash) {
+ path += "/";
+ }
+ return (isAbsolute ? "/" : "") + path;
+ },
+ dirname: path => {
+ var result = PATH.splitPath(path), root = result[0], dir = result[1];
+ if (!root && !dir) {
+ // No dirname whatsoever
+ return ".";
+ }
+ if (dir) {
+ // It has a dirname, strip trailing slash
+ dir = dir.slice(0, -1);
+ }
+ return root + dir;
+ },
+ basename: path => path && path.match(/([^\/]+|\/)\/*$/)[1],
+ join: (...paths) => PATH.normalize(paths.join("/")),
+ join2: (l, r) => PATH.normalize(l + "/" + r)
+};
+
+var initRandomFill = () => {
+ // This block is not needed on v19+ since crypto.getRandomValues is builtin
+ if (ENVIRONMENT_IS_NODE) {
+ var nodeCrypto = require("node:crypto");
+ return view => nodeCrypto.randomFillSync(view);
+ }
+ return view => crypto.getRandomValues(view);
+};
+
+var randomFill = view => {
+ // Lazily init on the first invocation.
+ (randomFill = initRandomFill())(view);
+};
+
+var PATH_FS = {
+ resolve: (...args) => {
+ var resolvedPath = "", resolvedAbsolute = false;
+ for (var i = args.length - 1; i >= -1 && !resolvedAbsolute; i--) {
+ var path = (i >= 0) ? args[i] : FS.cwd();
+ // Skip empty and invalid entries
+ if (typeof path != "string") {
+ throw new TypeError("Arguments to path.resolve must be strings");
+ } else if (!path) {
+ return "";
+ }
+ resolvedPath = path + "/" + resolvedPath;
+ resolvedAbsolute = PATH.isAbs(path);
+ }
+ // At this point the path should be resolved to a full absolute path, but
+ // handle relative paths to be safe (might happen when process.cwd() fails)
+ resolvedPath = PATH.normalizeArray(resolvedPath.split("/").filter(p => !!p), !resolvedAbsolute).join("/");
+ return ((resolvedAbsolute ? "/" : "") + resolvedPath) || ".";
+ },
+ relative: (from, to) => {
+ from = PATH_FS.resolve(from).slice(1);
+ to = PATH_FS.resolve(to).slice(1);
+ function trim(arr) {
+ var start = 0;
+ for (;start < arr.length; start++) {
+ if (arr[start] !== "") break;
+ }
+ var end = arr.length - 1;
+ for (;end >= 0; end--) {
+ if (arr[end] !== "") break;
+ }
+ if (start > end) return [];
+ return arr.slice(start, end - start + 1);
+ }
+ var fromParts = trim(from.split("/"));
+ var toParts = trim(to.split("/"));
+ var length = Math.min(fromParts.length, toParts.length);
+ var samePartsLength = length;
+ for (var i = 0; i < length; i++) {
+ if (fromParts[i] !== toParts[i]) {
+ samePartsLength = i;
+ break;
+ }
+ }
+ var outputParts = [];
+ for (var i = samePartsLength; i < fromParts.length; i++) {
+ outputParts.push("..");
+ }
+ outputParts = outputParts.concat(toParts.slice(samePartsLength));
+ return outputParts.join("/");
+ }
+};
+
+var UTF8Decoder = new TextDecoder;
+
+var findStringEnd = (heapOrArray, idx, maxBytesToRead, ignoreNul) => {
+ var maxIdx = idx + maxBytesToRead;
+ if (ignoreNul) return maxIdx;
+ // TextDecoder needs to know the byte length in advance, it doesn't stop on
+ // null terminator by itself.
+ // As a tiny code save trick, compare idx against maxIdx using a negation,
+ // so that maxBytesToRead=undefined/NaN means Infinity.
+ while (heapOrArray[idx] && !(idx >= maxIdx)) ++idx;
+ return idx;
+};
+
+/**
+ * Given a pointer 'idx' to a null-terminated UTF8-encoded string in the given
+ * array that contains uint8 values, returns a copy of that string as a
+ * Javascript String object.
+ * heapOrArray is either a regular array, or a JavaScript typed array view.
+ * @param {number=} idx
+ * @param {number=} maxBytesToRead
+ * @param {boolean=} ignoreNul - If true, the function will not stop on a NUL character.
+ * @return {string}
+ */ var UTF8ArrayToString = (heapOrArray, idx = 0, maxBytesToRead, ignoreNul) => {
+ idx >>>= 0;
+ var endPtr = findStringEnd(heapOrArray, idx, maxBytesToRead, ignoreNul);
+ return UTF8Decoder.decode(heapOrArray.buffer ? heapOrArray.subarray(idx, endPtr) : new Uint8Array(heapOrArray.slice(idx, endPtr)));
+};
+
+var FS_stdin_getChar_buffer = [];
+
+var lengthBytesUTF8 = str => {
+ var len = 0;
+ for (var i = 0; i < str.length; ++i) {
+ // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code
+ // unit, not a Unicode code point of the character! So decode
+ // UTF16->UTF32->UTF8.
+ // See http://unicode.org/faq/utf_bom.html#utf16-3
+ var c = str.charCodeAt(i);
+ // possibly a lead surrogate
+ if (c <= 127) {
+ len++;
+ } else if (c <= 2047) {
+ len += 2;
+ } else if (c >= 55296 && c <= 57343) {
+ len += 4;
+ ++i;
+ } else {
+ len += 3;
+ }
+ }
+ return len;
+};
+
+var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
+ outIdx >>>= 0;
+ // Parameter maxBytesToWrite is not optional. Negative values, 0, null,
+ // undefined and false each don't write out any bytes.
+ if (!(maxBytesToWrite > 0)) return 0;
+ var startIdx = outIdx;
+ var endIdx = outIdx + maxBytesToWrite - 1;
+ // -1 for string null terminator.
+ for (var i = 0; i < str.length; ++i) {
+ // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description
+ // and https://www.ietf.org/rfc/rfc2279.txt
+ // and https://tools.ietf.org/html/rfc3629
+ var u = str.codePointAt(i);
+ if (u <= 127) {
+ if (outIdx >= endIdx) break;
+ heap[outIdx++ >>> 0] = u;
+ } else if (u <= 2047) {
+ if (outIdx + 1 >= endIdx) break;
+ heap[outIdx++ >>> 0] = 192 | (u >> 6);
+ heap[outIdx++ >>> 0] = 128 | (u & 63);
+ } else if (u <= 65535) {
+ if (outIdx + 2 >= endIdx) break;
+ heap[outIdx++ >>> 0] = 224 | (u >> 12);
+ heap[outIdx++ >>> 0] = 128 | ((u >> 6) & 63);
+ heap[outIdx++ >>> 0] = 128 | (u & 63);
+ } else {
+ if (outIdx + 3 >= endIdx) break;
+ heap[outIdx++ >>> 0] = 240 | (u >> 18);
+ heap[outIdx++ >>> 0] = 128 | ((u >> 12) & 63);
+ heap[outIdx++ >>> 0] = 128 | ((u >> 6) & 63);
+ heap[outIdx++ >>> 0] = 128 | (u & 63);
+ // Gotcha: if codePoint is over 0xFFFF, it is represented as a surrogate pair in UTF-16.
+ // We need to manually skip over the second code unit for correct iteration.
+ i++;
+ }
+ }
+ // Null-terminate the pointer to the buffer.
+ heap[outIdx >>> 0] = 0;
+ return outIdx - startIdx;
+};
+
+/** @type {function(string, boolean=, number=)} */ var intArrayFromString = (stringy, dontAddNull, length) => {
+ var len = length > 0 ? length : lengthBytesUTF8(stringy) + 1;
+ var u8array = new Array(len);
+ var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length);
+ if (dontAddNull) u8array.length = numBytesWritten;
+ return u8array;
+};
+
+var FS_stdin_getChar = () => {
+ if (!FS_stdin_getChar_buffer.length) {
+ var result = null;
+ if (ENVIRONMENT_IS_NODE) {
+ // we will read data by chunks of BUFSIZE
+ var BUFSIZE = 256;
+ var buf = Buffer.alloc(BUFSIZE);
+ var bytesRead = 0;
+ // For some reason we must suppress a closure warning here, even though
+ // fd definitely exists on process.stdin, and is even the proper way to
+ // get the fd of stdin,
+ // https://github.com/nodejs/help/issues/2136#issuecomment-523649904
+ // This started to happen after moving this logic out of library_tty.js,
+ // so it is related to the surrounding code in some unclear manner.
+ /** @suppress {missingProperties} */ var fd = process.stdin.fd;
+ try {
+ bytesRead = fs.readSync(fd, buf, 0, BUFSIZE);
+ } catch (e) {
+ // Cross-platform differences: on Windows, reading EOF throws an
+ // exception, but on other OSes, reading EOF returns 0. Uniformize
+ // behavior by treating the EOF exception to return 0.
+ if (e.toString().includes("EOF")) bytesRead = 0; else throw e;
+ }
+ if (bytesRead > 0) {
+ result = buf.slice(0, bytesRead).toString("utf-8");
+ }
+ } else if (globalThis.window?.prompt) {
+ // Browser.
+ result = window.prompt("Input: ");
+ // returns null on cancel
+ if (result !== null) {
+ result += "\n";
+ }
+ } else {}
+ if (!result) {
+ return null;
+ }
+ FS_stdin_getChar_buffer = intArrayFromString(result, true);
+ }
+ return FS_stdin_getChar_buffer.shift();
+};
+
+var TTY = {
+ ttys: [],
+ init() {},
+ shutdown() {},
+ register(dev, ops) {
+ TTY.ttys[dev] = {
+ input: [],
+ output: [],
+ ops
+ };
+ FS.registerDevice(dev, TTY.stream_ops);
+ },
+ stream_ops: {
+ open(stream) {
+ var tty = TTY.ttys[stream.node.rdev];
+ if (!tty) {
+ throw new FS.ErrnoError(43);
+ }
+ stream.tty = tty;
+ stream.seekable = false;
+ },
+ close(stream) {
+ // flush any pending line data
+ stream.tty.ops.fsync(stream.tty);
+ },
+ fsync(stream) {
+ stream.tty.ops.fsync(stream.tty);
+ },
+ read(stream, buffer, offset, length, pos) {
+ if (!stream.tty || !stream.tty.ops.get_char) {
+ throw new FS.ErrnoError(60);
+ }
+ var bytesRead = 0;
+ for (var i = 0; i < length; i++) {
+ var result;
+ try {
+ result = stream.tty.ops.get_char(stream.tty);
+ } catch (e) {
+ throw new FS.ErrnoError(29);
+ }
+ if (result === undefined && bytesRead === 0) {
+ throw new FS.ErrnoError(6);
+ }
+ if (result === null || result === undefined) break;
+ bytesRead++;
+ buffer[offset + i] = result;
+ }
+ if (bytesRead) {
+ stream.node.atime = Date.now();
+ }
+ return bytesRead;
+ },
+ write(stream, buffer, offset, length, pos) {
+ if (!stream.tty || !stream.tty.ops.put_char) {
+ throw new FS.ErrnoError(60);
+ }
+ try {
+ for (var i = 0; i < length; i++) {
+ stream.tty.ops.put_char(stream.tty, buffer[offset + i]);
+ }
+ } catch (e) {
+ throw new FS.ErrnoError(29);
+ }
+ if (length) {
+ stream.node.mtime = stream.node.ctime = Date.now();
+ }
+ return i;
+ }
+ },
+ default_tty_ops: {
+ get_char(tty) {
+ return FS_stdin_getChar();
+ },
+ put_char(tty, val) {
+ if (val === null || val === 10) {
+ out(UTF8ArrayToString(tty.output));
+ tty.output = [];
+ } else {
+ if (val != 0) tty.output.push(val);
+ }
+ },
+ fsync(tty) {
+ if (tty.output?.length > 0) {
+ out(UTF8ArrayToString(tty.output));
+ tty.output = [];
+ }
+ },
+ ioctl_tcgets(tty) {
+ // typical setting
+ 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(tty, optional_actions, data) {
+ // currently just ignore
+ return 0;
+ },
+ ioctl_tiocgwinsz(tty) {
+ return [ 24, 80 ];
+ }
+ },
+ default_tty1_ops: {
+ put_char(tty, val) {
+ if (val === null || val === 10) {
+ err(UTF8ArrayToString(tty.output));
+ tty.output = [];
+ } else {
+ if (val != 0) tty.output.push(val);
+ }
+ },
+ fsync(tty) {
+ if (tty.output?.length > 0) {
+ err(UTF8ArrayToString(tty.output));
+ tty.output = [];
+ }
+ }
+ }
+};
+
+var zeroMemory = (ptr, size) => HEAPU8.fill(0, ptr, ptr + size);
+
+var alignMemory = (size, alignment) => Math.ceil(size / alignment) * alignment;
+
+var mmapAlloc = size => {
+ size = alignMemory(size, 65536);
+ var ptr = _emscripten_builtin_memalign(65536, size);
+ if (ptr) zeroMemory(ptr, size);
+ return ptr;
+};
+
+var MEMFS = {
+ ops_table: null,
+ mount(mount) {
+ return MEMFS.createNode(null, "/", 16895, 0);
+ },
+ createNode(parent, name, mode, dev) {
+ if (FS.isBlkdev(mode) || FS.isFIFO(mode)) {
+ // not supported
+ throw new FS.ErrnoError(63);
+ }
+ MEMFS.ops_table ||= {
+ dir: {
+ node: {
+ getattr: MEMFS.node_ops.getattr,
+ setattr: MEMFS.node_ops.setattr,
+ lookup: MEMFS.node_ops.lookup,
+ mknod: MEMFS.node_ops.mknod,
+ rename: MEMFS.node_ops.rename,
+ unlink: MEMFS.node_ops.unlink,
+ rmdir: MEMFS.node_ops.rmdir,
+ readdir: MEMFS.node_ops.readdir,
+ symlink: MEMFS.node_ops.symlink
+ },
+ stream: {
+ llseek: MEMFS.stream_ops.llseek
+ }
+ },
+ file: {
+ node: {
+ getattr: MEMFS.node_ops.getattr,
+ setattr: MEMFS.node_ops.setattr
+ },
+ stream: {
+ llseek: MEMFS.stream_ops.llseek,
+ read: MEMFS.stream_ops.read,
+ write: MEMFS.stream_ops.write,
+ mmap: MEMFS.stream_ops.mmap,
+ msync: MEMFS.stream_ops.msync
+ }
+ },
+ link: {
+ node: {
+ getattr: MEMFS.node_ops.getattr,
+ setattr: MEMFS.node_ops.setattr,
+ readlink: MEMFS.node_ops.readlink
+ },
+ stream: {}
+ },
+ chrdev: {
+ node: {
+ getattr: MEMFS.node_ops.getattr,
+ setattr: MEMFS.node_ops.setattr
+ },
+ stream: FS.chrdev_stream_ops
+ }
+ };
+ var node = FS.createNode(parent, name, mode, dev);
+ if (FS.isDir(node.mode)) {
+ node.node_ops = MEMFS.ops_table.dir.node;
+ node.stream_ops = MEMFS.ops_table.dir.stream;
+ node.contents = {};
+ } else if (FS.isFile(node.mode)) {
+ node.node_ops = MEMFS.ops_table.file.node;
+ node.stream_ops = MEMFS.ops_table.file.stream;
+ node.usedBytes = 0;
+ // The actual number of bytes used in the typed array, as opposed to contents.length which gives the whole capacity.
+ // When the byte data of the file is populated, this will point to either a typed array, or a normal JS array. Typed arrays are preferred
+ // for performance, and used by default. However, typed arrays are not resizable like normal JS arrays are, so there is a small disk size
+ // penalty involved for appending file writes that continuously grow a file similar to std::vector capacity vs used -scheme.
+ node.contents = null;
+ } else if (FS.isLink(node.mode)) {
+ node.node_ops = MEMFS.ops_table.link.node;
+ node.stream_ops = MEMFS.ops_table.link.stream;
+ } else if (FS.isChrdev(node.mode)) {
+ node.node_ops = MEMFS.ops_table.chrdev.node;
+ node.stream_ops = MEMFS.ops_table.chrdev.stream;
+ }
+ node.atime = node.mtime = node.ctime = Date.now();
+ // add the new node to the parent
+ if (parent) {
+ parent.contents[name] = node;
+ parent.atime = parent.mtime = parent.ctime = node.atime;
+ }
+ return node;
+ },
+ getFileDataAsTypedArray(node) {
+ if (!node.contents) return new Uint8Array(0);
+ if (node.contents.subarray) return node.contents.subarray(0, node.usedBytes);
+ // Make sure to not return excess unused bytes.
+ return new Uint8Array(node.contents);
+ },
+ expandFileStorage(node, newCapacity) {
+ var prevCapacity = node.contents ? node.contents.length : 0;
+ if (prevCapacity >= newCapacity) return;
+ // No need to expand, the storage was already large enough.
+ // Don't expand strictly to the given requested limit if it's only a very small increase, but instead geometrically grow capacity.
+ // For small filesizes (<1MB), perform size*2 geometric increase, but for large sizes, do a much more conservative size*1.125 increase to
+ // avoid overshooting the allocation cap by a very large margin.
+ var CAPACITY_DOUBLING_MAX = 1024 * 1024;
+ newCapacity = Math.max(newCapacity, (prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2 : 1.125)) >>> 0);
+ if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256);
+ // At minimum allocate 256b for each file when expanding.
+ var oldContents = node.contents;
+ node.contents = new Uint8Array(newCapacity);
+ // Allocate new storage.
+ if (node.usedBytes > 0) node.contents.set(oldContents.subarray(0, node.usedBytes), 0);
+ },
+ resizeFileStorage(node, newSize) {
+ if (node.usedBytes == newSize) return;
+ if (newSize == 0) {
+ node.contents = null;
+ // Fully decommit when requesting a resize to zero.
+ node.usedBytes = 0;
+ } else {
+ var oldContents = node.contents;
+ node.contents = new Uint8Array(newSize);
+ // Allocate new storage.
+ if (oldContents) {
+ node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes)));
+ }
+ node.usedBytes = newSize;
+ }
+ },
+ node_ops: {
+ getattr(node) {
+ var attr = {};
+ // device numbers reuse inode numbers.
+ attr.dev = FS.isChrdev(node.mode) ? node.id : 1;
+ attr.ino = node.id;
+ attr.mode = node.mode;
+ attr.nlink = 1;
+ attr.uid = 0;
+ attr.gid = 0;
+ attr.rdev = node.rdev;
+ if (FS.isDir(node.mode)) {
+ attr.size = 4096;
+ } else if (FS.isFile(node.mode)) {
+ attr.size = node.usedBytes;
+ } else if (FS.isLink(node.mode)) {
+ attr.size = node.link.length;
+ } else {
+ attr.size = 0;
+ }
+ attr.atime = new Date(node.atime);
+ attr.mtime = new Date(node.mtime);
+ attr.ctime = new Date(node.ctime);
+ // NOTE: In our implementation, st_blocks = Math.ceil(st_size/st_blksize),
+ // but this is not required by the standard.
+ attr.blksize = 4096;
+ attr.blocks = Math.ceil(attr.size / attr.blksize);
+ return attr;
+ },
+ setattr(node, attr) {
+ for (const key of [ "mode", "atime", "mtime", "ctime" ]) {
+ if (attr[key] != null) {
+ node[key] = attr[key];
+ }
+ }
+ if (attr.size !== undefined) {
+ MEMFS.resizeFileStorage(node, attr.size);
+ }
+ },
+ lookup(parent, name) {
+ // This error may happen quite a bit. To avoid overhead we reuse it (and
+ // suffer a lack of stack info).
+ if (!MEMFS.doesNotExistError) {
+ MEMFS.doesNotExistError = new FS.ErrnoError(44);
+ /** @suppress {checkTypes} */ MEMFS.doesNotExistError.stack = "";
+ }
+ throw MEMFS.doesNotExistError;
+ },
+ mknod(parent, name, mode, dev) {
+ return MEMFS.createNode(parent, name, mode, dev);
+ },
+ rename(old_node, new_dir, new_name) {
+ var new_node;
+ try {
+ new_node = FS.lookupNode(new_dir, new_name);
+ } catch (e) {}
+ if (new_node) {
+ if (FS.isDir(old_node.mode)) {
+ // if we're overwriting a directory at new_name, make sure it's empty.
+ for (var i in new_node.contents) {
+ throw new FS.ErrnoError(55);
+ }
+ }
+ FS.hashRemoveNode(new_node);
+ }
+ // do the internal rewiring
+ delete old_node.parent.contents[old_node.name];
+ new_dir.contents[new_name] = old_node;
+ old_node.name = new_name;
+ new_dir.ctime = new_dir.mtime = old_node.parent.ctime = old_node.parent.mtime = Date.now();
+ },
+ unlink(parent, name) {
+ delete parent.contents[name];
+ parent.ctime = parent.mtime = Date.now();
+ },
+ rmdir(parent, name) {
+ var node = FS.lookupNode(parent, name);
+ for (var i in node.contents) {
+ throw new FS.ErrnoError(55);
+ }
+ delete parent.contents[name];
+ parent.ctime = parent.mtime = Date.now();
+ },
+ readdir(node) {
+ return [ ".", "..", ...Object.keys(node.contents) ];
+ },
+ symlink(parent, newname, oldpath) {
+ var node = MEMFS.createNode(parent, newname, 511 | 40960, 0);
+ node.link = oldpath;
+ return node;
+ },
+ readlink(node) {
+ if (!FS.isLink(node.mode)) {
+ throw new FS.ErrnoError(28);
+ }
+ return node.link;
+ }
+ },
+ stream_ops: {
+ read(stream, buffer, offset, length, position) {
+ var contents = stream.node.contents;
+ if (position >= stream.node.usedBytes) return 0;
+ var size = Math.min(stream.node.usedBytes - position, length);
+ if (size > 8 && contents.subarray) {
+ // non-trivial, and typed array
+ buffer.set(contents.subarray(position, position + size), offset);
+ } else {
+ for (var i = 0; i < size; i++) buffer[offset + i] = contents[position + i];
+ }
+ return size;
+ },
+ write(stream, buffer, offset, length, position, canOwn) {
+ // If the buffer is located in main memory (HEAP), and if
+ // memory can grow, we can't hold on to references of the
+ // memory buffer, as they may get invalidated. That means we
+ // need to copy its contents.
+ if (buffer.buffer === HEAP8.buffer) {
+ canOwn = false;
+ }
+ if (!length) return 0;
+ var node = stream.node;
+ node.mtime = node.ctime = Date.now();
+ if (buffer.subarray && (!node.contents || node.contents.subarray)) {
+ // This write is from a typed array to a typed array?
+ if (canOwn) {
+ node.contents = buffer.subarray(offset, offset + length);
+ node.usedBytes = length;
+ return length;
+ } else if (node.usedBytes === 0 && position === 0) {
+ // If this is a simple first write to an empty file, do a fast set since we don't need to care about old data.
+ node.contents = buffer.slice(offset, offset + length);
+ node.usedBytes = length;
+ return length;
+ } else if (position + length <= node.usedBytes) {
+ // Writing to an already allocated and used subrange of the file?
+ node.contents.set(buffer.subarray(offset, offset + length), position);
+ return length;
+ }
+ }
+ // Appending to an existing file and we need to reallocate, or source data did not come as a typed array.
+ MEMFS.expandFileStorage(node, position + length);
+ if (node.contents.subarray && buffer.subarray) {
+ // Use typed array write which is available.
+ node.contents.set(buffer.subarray(offset, offset + length), position);
+ } else {
+ for (var i = 0; i < length; i++) {
+ node.contents[position + i] = buffer[offset + i];
+ }
+ }
+ node.usedBytes = Math.max(node.usedBytes, position + length);
+ return length;
+ },
+ llseek(stream, offset, whence) {
+ var position = offset;
+ if (whence === 1) {
+ position += stream.position;
+ } else if (whence === 2) {
+ if (FS.isFile(stream.node.mode)) {
+ position += stream.node.usedBytes;
+ }
+ }
+ if (position < 0) {
+ throw new FS.ErrnoError(28);
+ }
+ return position;
+ },
+ mmap(stream, length, position, prot, flags) {
+ if (!FS.isFile(stream.node.mode)) {
+ throw new FS.ErrnoError(43);
+ }
+ var ptr;
+ var allocated;
+ var contents = stream.node.contents;
+ // Only make a new copy when MAP_PRIVATE is specified.
+ if (!(flags & 2) && contents && contents.buffer === HEAP8.buffer) {
+ // We can't emulate MAP_SHARED when the file is not backed by the
+ // buffer we're mapping to (e.g. the HEAP buffer).
+ allocated = false;
+ ptr = contents.byteOffset;
+ } else {
+ allocated = true;
+ ptr = mmapAlloc(length);
+ if (!ptr) {
+ throw new FS.ErrnoError(48);
+ }
+ if (contents) {
+ // Try to avoid unnecessary slices.
+ if (position > 0 || position + length < contents.length) {
+ if (contents.subarray) {
+ contents = contents.subarray(position, position + length);
+ } else {
+ contents = Array.prototype.slice.call(contents, position, position + length);
+ }
+ }
+ HEAP8.set(contents, ptr >>> 0);
+ }
+ }
+ return {
+ ptr,
+ allocated
+ };
+ },
+ msync(stream, buffer, offset, length, mmapFlags) {
+ MEMFS.stream_ops.write(stream, buffer, 0, length, offset, false);
+ // should we check if bytesWritten and length are the same?
+ return 0;
+ }
+ }
+};
+
+var FS_modeStringToFlags = str => {
+ var flagModes = {
+ "r": 0,
+ "r+": 2,
+ "w": 512 | 64 | 1,
+ "w+": 512 | 64 | 2,
+ "a": 1024 | 64 | 1,
+ "a+": 1024 | 64 | 2
+ };
+ var flags = flagModes[str];
+ if (typeof flags == "undefined") {
+ throw new Error(`Unknown file open mode: ${str}`);
+ }
+ return flags;
+};
+
+var FS_getMode = (canRead, canWrite) => {
+ var mode = 0;
+ if (canRead) mode |= 292 | 73;
+ if (canWrite) mode |= 146;
+ return mode;
+};
+
+var asyncLoad = async url => {
+ var arrayBuffer = await readAsync(url);
+ return new Uint8Array(arrayBuffer);
+};
+
+var FS_createDataFile = (...args) => FS.createDataFile(...args);
+
+var getUniqueRunDependency = id => id;
+
+var runDependencies = 0;
+
+var dependenciesFulfilled = null;
+
+var removeRunDependency = id => {
+ runDependencies--;
+ Module["monitorRunDependencies"]?.(runDependencies);
+ if (runDependencies == 0) {
+ if (dependenciesFulfilled) {
+ var callback = dependenciesFulfilled;
+ dependenciesFulfilled = null;
+ callback();
+ }
+ }
+};
+
+var addRunDependency = id => {
+ runDependencies++;
+ Module["monitorRunDependencies"]?.(runDependencies);
+};
+
+var FS_handledByPreloadPlugin = async (byteArray, fullname) => {
+ // Ensure plugins are ready.
+ if (typeof Browser != "undefined") Browser.init();
+ for (var plugin of preloadPlugins) {
+ if (plugin["canHandle"](fullname)) {
+ return plugin["handle"](byteArray, fullname);
+ }
+ }
+ // If no plugin handled this file then return the original/unmodified
+ // byteArray.
+ return byteArray;
+};
+
+var FS_preloadFile = async (parent, name, url, canRead, canWrite, dontCreateFile, canOwn, preFinish) => {
+ // TODO we should allow people to just pass in a complete filename instead
+ // of parent and name being that we just join them anyways
+ var fullname = name ? PATH_FS.resolve(PATH.join2(parent, name)) : parent;
+ var dep = getUniqueRunDependency(`cp ${fullname}`);
+ // might have several active requests for the same fullname
+ addRunDependency(dep);
+ try {
+ var byteArray = url;
+ if (typeof url == "string") {
+ byteArray = await asyncLoad(url);
+ }
+ byteArray = await FS_handledByPreloadPlugin(byteArray, fullname);
+ preFinish?.();
+ if (!dontCreateFile) {
+ FS_createDataFile(parent, name, byteArray, canRead, canWrite, canOwn);
+ }
+ } finally {
+ removeRunDependency(dep);
+ }
+};
+
+var FS_createPreloadedFile = (parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) => {
+ FS_preloadFile(parent, name, url, canRead, canWrite, dontCreateFile, canOwn, preFinish).then(onload).catch(onerror);
+};
+
+var FS = {
+ root: null,
+ mounts: [],
+ devices: {},
+ streams: [],
+ nextInode: 1,
+ nameTable: null,
+ currentPath: "/",
+ initialized: false,
+ ignorePermissions: true,
+ filesystems: null,
+ syncFSRequests: 0,
+ ErrnoError: class {
+ name="ErrnoError";
+ // We set the `name` property to be able to identify `FS.ErrnoError`
+ // - the `name` is a standard ECMA-262 property of error objects. Kind of good to have it anyway.
+ // - when using PROXYFS, an error can come from an underlying FS
+ // as different FS objects have their own FS.ErrnoError each,
+ // the test `err instanceof FS.ErrnoError` won't detect an error coming from another filesystem, causing bugs.
+ // we'll use the reliable test `err.name == "ErrnoError"` instead
+ constructor(errno) {
+ this.errno = errno;
+ }
+ },
+ FSStream: class {
+ shared={};
+ get object() {
+ return this.node;
+ }
+ set object(val) {
+ this.node = val;
+ }
+ get isRead() {
+ return (this.flags & 2097155) !== 1;
+ }
+ get isWrite() {
+ return (this.flags & 2097155) !== 0;
+ }
+ get isAppend() {
+ return (this.flags & 1024);
+ }
+ get flags() {
+ return this.shared.flags;
+ }
+ set flags(val) {
+ this.shared.flags = val;
+ }
+ get position() {
+ return this.shared.position;
+ }
+ set position(val) {
+ this.shared.position = val;
+ }
+ },
+ FSNode: class {
+ node_ops={};
+ stream_ops={};
+ readMode=292 | 73;
+ writeMode=146;
+ mounted=null;
+ constructor(parent, name, mode, rdev) {
+ if (!parent) {
+ parent = this;
+ }
+ this.parent = parent;
+ this.mount = parent.mount;
+ this.id = FS.nextInode++;
+ this.name = name;
+ this.mode = mode;
+ this.rdev = rdev;
+ this.atime = this.mtime = this.ctime = Date.now();
+ }
+ get read() {
+ return (this.mode & this.readMode) === this.readMode;
+ }
+ set read(val) {
+ val ? this.mode |= this.readMode : this.mode &= ~this.readMode;
+ }
+ get write() {
+ return (this.mode & this.writeMode) === this.writeMode;
+ }
+ set write(val) {
+ val ? this.mode |= this.writeMode : this.mode &= ~this.writeMode;
+ }
+ get isFolder() {
+ return FS.isDir(this.mode);
+ }
+ get isDevice() {
+ return FS.isChrdev(this.mode);
+ }
+ },
+ lookupPath(path, opts = {}) {
+ if (!path) {
+ throw new FS.ErrnoError(44);
+ }
+ opts.follow_mount ??= true;
+ if (!PATH.isAbs(path)) {
+ path = FS.cwd() + "/" + path;
+ }
+ // limit max consecutive symlinks to 40 (SYMLOOP_MAX).
+ linkloop: for (var nlinks = 0; nlinks < 40; nlinks++) {
+ // split the absolute path
+ var parts = path.split("/").filter(p => !!p);
+ // start at the root
+ var current = FS.root;
+ var current_path = "/";
+ for (var i = 0; i < parts.length; i++) {
+ var islast = (i === parts.length - 1);
+ if (islast && opts.parent) {
+ // stop resolving
+ break;
+ }
+ if (parts[i] === ".") {
+ continue;
+ }
+ if (parts[i] === "..") {
+ current_path = PATH.dirname(current_path);
+ if (FS.isRoot(current)) {
+ path = current_path + "/" + parts.slice(i + 1).join("/");
+ // We're making progress here, don't let many consecutive ..'s
+ // lead to ELOOP
+ nlinks--;
+ continue linkloop;
+ } else {
+ current = current.parent;
+ }
+ continue;
+ }
+ current_path = PATH.join2(current_path, parts[i]);
+ try {
+ current = FS.lookupNode(current, parts[i]);
+ } catch (e) {
+ // if noent_okay is true, suppress a ENOENT in the last component
+ // and return an object with an undefined node. This is needed for
+ // resolving symlinks in the path when creating a file.
+ if ((e?.errno === 44) && islast && opts.noent_okay) {
+ return {
+ path: current_path
+ };
+ }
+ throw e;
+ }
+ // jump to the mount's root node if this is a mountpoint
+ if (FS.isMountpoint(current) && (!islast || opts.follow_mount)) {
+ current = current.mounted.root;
+ }
+ // by default, lookupPath will not follow a symlink if it is the final path component.
+ // setting opts.follow = true will override this behavior.
+ if (FS.isLink(current.mode) && (!islast || opts.follow)) {
+ if (!current.node_ops.readlink) {
+ throw new FS.ErrnoError(52);
+ }
+ var link = current.node_ops.readlink(current);
+ if (!PATH.isAbs(link)) {
+ link = PATH.dirname(current_path) + "/" + link;
+ }
+ path = link + "/" + parts.slice(i + 1).join("/");
+ continue linkloop;
+ }
+ }
+ return {
+ path: current_path,
+ node: current
+ };
+ }
+ throw new FS.ErrnoError(32);
+ },
+ getPath(node) {
+ var path;
+ while (true) {
+ if (FS.isRoot(node)) {
+ var mount = node.mount.mountpoint;
+ if (!path) return mount;
+ return mount[mount.length - 1] !== "/" ? `${mount}/${path}` : mount + path;
+ }
+ path = path ? `${node.name}/${path}` : node.name;
+ node = node.parent;
+ }
+ },
+ hashName(parentid, name) {
+ var hash = 0;
+ for (var i = 0; i < name.length; i++) {
+ hash = ((hash << 5) - hash + name.charCodeAt(i)) | 0;
+ }
+ return ((parentid + hash) >>> 0) % FS.nameTable.length;
+ },
+ hashAddNode(node) {
+ var hash = FS.hashName(node.parent.id, node.name);
+ node.name_next = FS.nameTable[hash];
+ FS.nameTable[hash] = node;
+ },
+ hashRemoveNode(node) {
+ var hash = FS.hashName(node.parent.id, node.name);
+ if (FS.nameTable[hash] === node) {
+ FS.nameTable[hash] = node.name_next;
+ } else {
+ var current = FS.nameTable[hash];
+ while (current) {
+ if (current.name_next === node) {
+ current.name_next = node.name_next;
+ break;
+ }
+ current = current.name_next;
+ }
+ }
+ },
+ lookupNode(parent, name) {
+ var errCode = FS.mayLookup(parent);
+ if (errCode) {
+ throw new FS.ErrnoError(errCode);
+ }
+ var hash = FS.hashName(parent.id, name);
+ for (var node = FS.nameTable[hash]; node; node = node.name_next) {
+ var nodeName = node.name;
+ if (node.parent.id === parent.id && nodeName === name) {
+ return node;
+ }
+ }
+ // if we failed to find it in the cache, call into the VFS
+ return FS.lookup(parent, name);
+ },
+ createNode(parent, name, mode, rdev) {
+ var node = new FS.FSNode(parent, name, mode, rdev);
+ FS.hashAddNode(node);
+ return node;
+ },
+ destroyNode(node) {
+ FS.hashRemoveNode(node);
+ },
+ isRoot(node) {
+ return node === node.parent;
+ },
+ isMountpoint(node) {
+ return !!node.mounted;
+ },
+ isFile(mode) {
+ return (mode & 61440) === 32768;
+ },
+ isDir(mode) {
+ return (mode & 61440) === 16384;
+ },
+ isLink(mode) {
+ return (mode & 61440) === 40960;
+ },
+ isChrdev(mode) {
+ return (mode & 61440) === 8192;
+ },
+ isBlkdev(mode) {
+ return (mode & 61440) === 24576;
+ },
+ isFIFO(mode) {
+ return (mode & 61440) === 4096;
+ },
+ isSocket(mode) {
+ return (mode & 49152) === 49152;
+ },
+ flagsToPermissionString(flag) {
+ var perms = [ "r", "w", "rw" ][flag & 3];
+ if ((flag & 512)) {
+ perms += "w";
+ }
+ return perms;
+ },
+ nodePermissions(node, perms) {
+ if (FS.ignorePermissions) {
+ return 0;
+ }
+ // return 0 if any user, group or owner bits are set.
+ if (perms.includes("r") && !(node.mode & 292)) {
+ return 2;
+ }
+ if (perms.includes("w") && !(node.mode & 146)) {
+ return 2;
+ }
+ if (perms.includes("x") && !(node.mode & 73)) {
+ return 2;
+ }
+ return 0;
+ },
+ mayLookup(dir) {
+ if (!FS.isDir(dir.mode)) return 54;
+ var errCode = FS.nodePermissions(dir, "x");
+ if (errCode) return errCode;
+ if (!dir.node_ops.lookup) return 2;
+ return 0;
+ },
+ mayCreate(dir, name) {
+ if (!FS.isDir(dir.mode)) {
+ return 54;
+ }
+ try {
+ var node = FS.lookupNode(dir, name);
+ return 20;
+ } catch (e) {}
+ return FS.nodePermissions(dir, "wx");
+ },
+ mayDelete(dir, name, isdir) {
+ var node;
+ try {
+ node = FS.lookupNode(dir, name);
+ } catch (e) {
+ return e.errno;
+ }
+ var errCode = FS.nodePermissions(dir, "wx");
+ if (errCode) {
+ return errCode;
+ }
+ if (isdir) {
+ if (!FS.isDir(node.mode)) {
+ return 54;
+ }
+ if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) {
+ return 10;
+ }
+ } else if (FS.isDir(node.mode)) {
+ return 31;
+ }
+ return 0;
+ },
+ mayOpen(node, flags) {
+ if (!node) {
+ return 44;
+ }
+ if (FS.isLink(node.mode)) {
+ return 32;
+ }
+ var mode = FS.flagsToPermissionString(flags);
+ if (FS.isDir(node.mode)) {
+ // opening for write
+ // TODO: check for O_SEARCH? (== search for dir only)
+ if (mode !== "r" || (flags & (512 | 64))) {
+ return 31;
+ }
+ }
+ return FS.nodePermissions(node, mode);
+ },
+ checkOpExists(op, err) {
+ if (!op) {
+ throw new FS.ErrnoError(err);
+ }
+ return op;
+ },
+ MAX_OPEN_FDS: 4096,
+ nextfd() {
+ for (var fd = 0; fd <= FS.MAX_OPEN_FDS; fd++) {
+ if (!FS.streams[fd]) {
+ return fd;
+ }
+ }
+ throw new FS.ErrnoError(33);
+ },
+ getStreamChecked(fd) {
+ var stream = FS.getStream(fd);
+ if (!stream) {
+ throw new FS.ErrnoError(8);
+ }
+ return stream;
+ },
+ getStream: fd => FS.streams[fd],
+ createStream(stream, fd = -1) {
+ // clone it, so we can return an instance of FSStream
+ stream = Object.assign(new FS.FSStream, stream);
+ if (fd == -1) {
+ fd = FS.nextfd();
+ }
+ stream.fd = fd;
+ FS.streams[fd] = stream;
+ return stream;
+ },
+ closeStream(fd) {
+ FS.streams[fd] = null;
+ },
+ dupStream(origStream, fd = -1) {
+ var stream = FS.createStream(origStream, fd);
+ stream.stream_ops?.dup?.(stream);
+ return stream;
+ },
+ doSetAttr(stream, node, attr) {
+ var setattr = stream?.stream_ops.setattr;
+ var arg = setattr ? stream : node;
+ setattr ??= node.node_ops.setattr;
+ FS.checkOpExists(setattr, 63);
+ setattr(arg, attr);
+ },
+ chrdev_stream_ops: {
+ open(stream) {
+ var device = FS.getDevice(stream.node.rdev);
+ // override node's stream ops with the device's
+ stream.stream_ops = device.stream_ops;
+ // forward the open call
+ stream.stream_ops.open?.(stream);
+ },
+ llseek() {
+ throw new FS.ErrnoError(70);
+ }
+ },
+ major: dev => ((dev) >> 8),
+ minor: dev => ((dev) & 255),
+ makedev: (ma, mi) => ((ma) << 8 | (mi)),
+ registerDevice(dev, ops) {
+ FS.devices[dev] = {
+ stream_ops: ops
+ };
+ },
+ getDevice: dev => FS.devices[dev],
+ getMounts(mount) {
+ var mounts = [];
+ var check = [ mount ];
+ while (check.length) {
+ var m = check.pop();
+ mounts.push(m);
+ check.push(...m.mounts);
+ }
+ return mounts;
+ },
+ syncfs(populate, callback) {
+ if (typeof populate == "function") {
+ callback = populate;
+ populate = false;
+ }
+ FS.syncFSRequests++;
+ if (FS.syncFSRequests > 1) {
+ err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`);
+ }
+ var mounts = FS.getMounts(FS.root.mount);
+ var completed = 0;
+ function doCallback(errCode) {
+ FS.syncFSRequests--;
+ return callback(errCode);
+ }
+ function done(errCode) {
+ if (errCode) {
+ if (!done.errored) {
+ done.errored = true;
+ return doCallback(errCode);
+ }
+ return;
+ }
+ if (++completed >= mounts.length) {
+ doCallback(null);
+ }
+ }
+ // sync all mounts
+ for (var mount of mounts) {
+ if (mount.type.syncfs) {
+ mount.type.syncfs(mount, populate, done);
+ } else {
+ done(null);
+ }
+ }
+ },
+ mount(type, opts, mountpoint) {
+ var root = mountpoint === "/";
+ var pseudo = !mountpoint;
+ var node;
+ if (root && FS.root) {
+ throw new FS.ErrnoError(10);
+ } else if (!root && !pseudo) {
+ var lookup = FS.lookupPath(mountpoint, {
+ follow_mount: false
+ });
+ mountpoint = lookup.path;
+ // use the absolute path
+ node = lookup.node;
+ if (FS.isMountpoint(node)) {
+ throw new FS.ErrnoError(10);
+ }
+ if (!FS.isDir(node.mode)) {
+ throw new FS.ErrnoError(54);
+ }
+ }
+ var mount = {
+ type,
+ opts,
+ mountpoint,
+ mounts: []
+ };
+ // create a root node for the fs
+ var mountRoot = type.mount(mount);
+ mountRoot.mount = mount;
+ mount.root = mountRoot;
+ if (root) {
+ FS.root = mountRoot;
+ } else if (node) {
+ // set as a mountpoint
+ node.mounted = mount;
+ // add the new mount to the current mount's children
+ if (node.mount) {
+ node.mount.mounts.push(mount);
+ }
+ }
+ return mountRoot;
+ },
+ unmount(mountpoint) {
+ var lookup = FS.lookupPath(mountpoint, {
+ follow_mount: false
+ });
+ if (!FS.isMountpoint(lookup.node)) {
+ throw new FS.ErrnoError(28);
+ }
+ // destroy the nodes for this mount, and all its child mounts
+ var node = lookup.node;
+ var mount = node.mounted;
+ var mounts = FS.getMounts(mount);
+ for (var [hash, current] of Object.entries(FS.nameTable)) {
+ while (current) {
+ var next = current.name_next;
+ if (mounts.includes(current.mount)) {
+ FS.destroyNode(current);
+ }
+ current = next;
+ }
+ }
+ // no longer a mountpoint
+ node.mounted = null;
+ // remove this mount from the child mounts
+ var idx = node.mount.mounts.indexOf(mount);
+ node.mount.mounts.splice(idx, 1);
+ },
+ lookup(parent, name) {
+ return parent.node_ops.lookup(parent, name);
+ },
+ mknod(path, mode, dev) {
+ var lookup = FS.lookupPath(path, {
+ parent: true
+ });
+ var parent = lookup.node;
+ var name = PATH.basename(path);
+ if (!name) {
+ throw new FS.ErrnoError(28);
+ }
+ if (name === "." || name === "..") {
+ throw new FS.ErrnoError(20);
+ }
+ var errCode = FS.mayCreate(parent, name);
+ if (errCode) {
+ throw new FS.ErrnoError(errCode);
+ }
+ if (!parent.node_ops.mknod) {
+ throw new FS.ErrnoError(63);
+ }
+ return parent.node_ops.mknod(parent, name, mode, dev);
+ },
+ statfs(path) {
+ return FS.statfsNode(FS.lookupPath(path, {
+ follow: true
+ }).node);
+ },
+ statfsStream(stream) {
+ // We keep a separate statfsStream function because noderawfs overrides
+ // it. In noderawfs, stream.node is sometimes null. Instead, we need to
+ // look at stream.path.
+ return FS.statfsNode(stream.node);
+ },
+ statfsNode(node) {
+ // NOTE: None of the defaults here are true. We're just returning safe and
+ // sane values. Currently nodefs and rawfs replace these defaults,
+ // other file systems leave them alone.
+ var rtn = {
+ bsize: 4096,
+ frsize: 4096,
+ blocks: 1e6,
+ bfree: 5e5,
+ bavail: 5e5,
+ files: FS.nextInode,
+ ffree: FS.nextInode - 1,
+ fsid: 42,
+ flags: 2,
+ namelen: 255
+ };
+ if (node.node_ops.statfs) {
+ Object.assign(rtn, node.node_ops.statfs(node.mount.opts.root));
+ }
+ return rtn;
+ },
+ create(path, mode = 438) {
+ mode &= 4095;
+ mode |= 32768;
+ return FS.mknod(path, mode, 0);
+ },
+ mkdir(path, mode = 511) {
+ mode &= 511 | 512;
+ mode |= 16384;
+ return FS.mknod(path, mode, 0);
+ },
+ mkdirTree(path, mode) {
+ var dirs = path.split("/");
+ var d = "";
+ for (var dir of dirs) {
+ if (!dir) continue;
+ if (d || PATH.isAbs(path)) d += "/";
+ d += dir;
+ try {
+ FS.mkdir(d, mode);
+ } catch (e) {
+ if (e.errno != 20) throw e;
+ }
+ }
+ },
+ mkdev(path, mode, dev) {
+ if (typeof dev == "undefined") {
+ dev = mode;
+ mode = 438;
+ }
+ mode |= 8192;
+ return FS.mknod(path, mode, dev);
+ },
+ symlink(oldpath, newpath) {
+ if (!PATH_FS.resolve(oldpath)) {
+ throw new FS.ErrnoError(44);
+ }
+ var lookup = FS.lookupPath(newpath, {
+ parent: true
+ });
+ var parent = lookup.node;
+ if (!parent) {
+ throw new FS.ErrnoError(44);
+ }
+ var newname = PATH.basename(newpath);
+ var errCode = FS.mayCreate(parent, newname);
+ if (errCode) {
+ throw new FS.ErrnoError(errCode);
+ }
+ if (!parent.node_ops.symlink) {
+ throw new FS.ErrnoError(63);
+ }
+ return parent.node_ops.symlink(parent, newname, oldpath);
+ },
+ rename(old_path, new_path) {
+ var old_dirname = PATH.dirname(old_path);
+ var new_dirname = PATH.dirname(new_path);
+ var old_name = PATH.basename(old_path);
+ var new_name = PATH.basename(new_path);
+ // parents must exist
+ var lookup, old_dir, new_dir;
+ // let the errors from non existent directories percolate up
+ lookup = FS.lookupPath(old_path, {
+ parent: true
+ });
+ old_dir = lookup.node;
+ lookup = FS.lookupPath(new_path, {
+ parent: true
+ });
+ new_dir = lookup.node;
+ if (!old_dir || !new_dir) throw new FS.ErrnoError(44);
+ // need to be part of the same mount
+ if (old_dir.mount !== new_dir.mount) {
+ throw new FS.ErrnoError(75);
+ }
+ // source must exist
+ var old_node = FS.lookupNode(old_dir, old_name);
+ // old path should not be an ancestor of the new path
+ var relative = PATH_FS.relative(old_path, new_dirname);
+ if (relative.charAt(0) !== ".") {
+ throw new FS.ErrnoError(28);
+ }
+ // new path should not be an ancestor of the old path
+ relative = PATH_FS.relative(new_path, old_dirname);
+ if (relative.charAt(0) !== ".") {
+ throw new FS.ErrnoError(55);
+ }
+ // see if the new path already exists
+ var new_node;
+ try {
+ new_node = FS.lookupNode(new_dir, new_name);
+ } catch (e) {}
+ // early out if nothing needs to change
+ if (old_node === new_node) {
+ return;
+ }
+ // we'll need to delete the old entry
+ var isdir = FS.isDir(old_node.mode);
+ var errCode = FS.mayDelete(old_dir, old_name, isdir);
+ if (errCode) {
+ throw new FS.ErrnoError(errCode);
+ }
+ // need delete permissions if we'll be overwriting.
+ // need create permissions if new doesn't already exist.
+ errCode = new_node ? FS.mayDelete(new_dir, new_name, isdir) : FS.mayCreate(new_dir, new_name);
+ if (errCode) {
+ throw new FS.ErrnoError(errCode);
+ }
+ if (!old_dir.node_ops.rename) {
+ throw new FS.ErrnoError(63);
+ }
+ if (FS.isMountpoint(old_node) || (new_node && FS.isMountpoint(new_node))) {
+ throw new FS.ErrnoError(10);
+ }
+ // if we are going to change the parent, check write permissions
+ if (new_dir !== old_dir) {
+ errCode = FS.nodePermissions(old_dir, "w");
+ if (errCode) {
+ throw new FS.ErrnoError(errCode);
+ }
+ }
+ // remove the node from the lookup hash
+ FS.hashRemoveNode(old_node);
+ // do the underlying fs rename
+ try {
+ old_dir.node_ops.rename(old_node, new_dir, new_name);
+ // update old node (we do this here to avoid each backend
+ // needing to)
+ old_node.parent = new_dir;
+ } catch (e) {
+ throw e;
+ } finally {
+ // add the node back to the hash (in case node_ops.rename
+ // changed its name)
+ FS.hashAddNode(old_node);
+ }
+ },
+ rmdir(path) {
+ var lookup = FS.lookupPath(path, {
+ parent: true
+ });
+ var parent = lookup.node;
+ var name = PATH.basename(path);
+ var node = FS.lookupNode(parent, name);
+ var errCode = FS.mayDelete(parent, name, true);
+ if (errCode) {
+ throw new FS.ErrnoError(errCode);
+ }
+ if (!parent.node_ops.rmdir) {
+ throw new FS.ErrnoError(63);
+ }
+ if (FS.isMountpoint(node)) {
+ throw new FS.ErrnoError(10);
+ }
+ parent.node_ops.rmdir(parent, name);
+ FS.destroyNode(node);
+ },
+ readdir(path) {
+ var lookup = FS.lookupPath(path, {
+ follow: true
+ });
+ var node = lookup.node;
+ var readdir = FS.checkOpExists(node.node_ops.readdir, 54);
+ return readdir(node);
+ },
+ unlink(path) {
+ var lookup = FS.lookupPath(path, {
+ parent: true
+ });
+ var parent = lookup.node;
+ if (!parent) {
+ throw new FS.ErrnoError(44);
+ }
+ var name = PATH.basename(path);
+ var node = FS.lookupNode(parent, name);
+ var errCode = FS.mayDelete(parent, name, false);
+ if (errCode) {
+ // According to POSIX, we should map EISDIR to EPERM, but
+ // we instead do what Linux does (and we must, as we use
+ // the musl linux libc).
+ throw new FS.ErrnoError(errCode);
+ }
+ if (!parent.node_ops.unlink) {
+ throw new FS.ErrnoError(63);
+ }
+ if (FS.isMountpoint(node)) {
+ throw new FS.ErrnoError(10);
+ }
+ parent.node_ops.unlink(parent, name);
+ FS.destroyNode(node);
+ },
+ readlink(path) {
+ var lookup = FS.lookupPath(path);
+ var link = lookup.node;
+ if (!link) {
+ throw new FS.ErrnoError(44);
+ }
+ if (!link.node_ops.readlink) {
+ throw new FS.ErrnoError(28);
+ }
+ return link.node_ops.readlink(link);
+ },
+ stat(path, dontFollow) {
+ var lookup = FS.lookupPath(path, {
+ follow: !dontFollow
+ });
+ var node = lookup.node;
+ var getattr = FS.checkOpExists(node.node_ops.getattr, 63);
+ return getattr(node);
+ },
+ fstat(fd) {
+ var stream = FS.getStreamChecked(fd);
+ var node = stream.node;
+ var getattr = stream.stream_ops.getattr;
+ var arg = getattr ? stream : node;
+ getattr ??= node.node_ops.getattr;
+ FS.checkOpExists(getattr, 63);
+ return getattr(arg);
+ },
+ lstat(path) {
+ return FS.stat(path, true);
+ },
+ doChmod(stream, node, mode, dontFollow) {
+ FS.doSetAttr(stream, node, {
+ mode: (mode & 4095) | (node.mode & ~4095),
+ ctime: Date.now(),
+ dontFollow
+ });
+ },
+ chmod(path, mode, dontFollow) {
+ var node;
+ if (typeof path == "string") {
+ var lookup = FS.lookupPath(path, {
+ follow: !dontFollow
+ });
+ node = lookup.node;
+ } else {
+ node = path;
+ }
+ FS.doChmod(null, node, mode, dontFollow);
+ },
+ lchmod(path, mode) {
+ FS.chmod(path, mode, true);
+ },
+ fchmod(fd, mode) {
+ var stream = FS.getStreamChecked(fd);
+ FS.doChmod(stream, stream.node, mode, false);
+ },
+ doChown(stream, node, dontFollow) {
+ FS.doSetAttr(stream, node, {
+ timestamp: Date.now(),
+ dontFollow
+ });
+ },
+ chown(path, uid, gid, dontFollow) {
+ var node;
+ if (typeof path == "string") {
+ var lookup = FS.lookupPath(path, {
+ follow: !dontFollow
+ });
+ node = lookup.node;
+ } else {
+ node = path;
+ }
+ FS.doChown(null, node, dontFollow);
+ },
+ lchown(path, uid, gid) {
+ FS.chown(path, uid, gid, true);
+ },
+ fchown(fd, uid, gid) {
+ var stream = FS.getStreamChecked(fd);
+ FS.doChown(stream, stream.node, false);
+ },
+ doTruncate(stream, node, len) {
+ if (FS.isDir(node.mode)) {
+ throw new FS.ErrnoError(31);
+ }
+ if (!FS.isFile(node.mode)) {
+ throw new FS.ErrnoError(28);
+ }
+ var errCode = FS.nodePermissions(node, "w");
+ if (errCode) {
+ throw new FS.ErrnoError(errCode);
+ }
+ FS.doSetAttr(stream, node, {
+ size: len,
+ timestamp: Date.now()
+ });
+ },
+ truncate(path, len) {
+ if (len < 0) {
+ throw new FS.ErrnoError(28);
+ }
+ var node;
+ if (typeof path == "string") {
+ var lookup = FS.lookupPath(path, {
+ follow: true
+ });
+ node = lookup.node;
+ } else {
+ node = path;
+ }
+ FS.doTruncate(null, node, len);
+ },
+ ftruncate(fd, len) {
+ var stream = FS.getStreamChecked(fd);
+ if (len < 0 || (stream.flags & 2097155) === 0) {
+ throw new FS.ErrnoError(28);
+ }
+ FS.doTruncate(stream, stream.node, len);
+ },
+ utime(path, atime, mtime) {
+ var lookup = FS.lookupPath(path, {
+ follow: true
+ });
+ var node = lookup.node;
+ var setattr = FS.checkOpExists(node.node_ops.setattr, 63);
+ setattr(node, {
+ atime,
+ mtime
+ });
+ },
+ open(path, flags, mode = 438) {
+ if (path === "") {
+ throw new FS.ErrnoError(44);
+ }
+ flags = typeof flags == "string" ? FS_modeStringToFlags(flags) : flags;
+ if ((flags & 64)) {
+ mode = (mode & 4095) | 32768;
+ } else {
+ mode = 0;
+ }
+ var node;
+ var isDirPath;
+ if (typeof path == "object") {
+ node = path;
+ } else {
+ isDirPath = path.endsWith("/");
+ // noent_okay makes it so that if the final component of the path
+ // doesn't exist, lookupPath returns `node: undefined`. `path` will be
+ // updated to point to the target of all symlinks.
+ var lookup = FS.lookupPath(path, {
+ follow: !(flags & 131072),
+ noent_okay: true
+ });
+ node = lookup.node;
+ path = lookup.path;
+ }
+ // perhaps we need to create the node
+ var created = false;
+ if ((flags & 64)) {
+ if (node) {
+ // if O_CREAT and O_EXCL are set, error out if the node already exists
+ if ((flags & 128)) {
+ throw new FS.ErrnoError(20);
+ }
+ } else if (isDirPath) {
+ throw new FS.ErrnoError(31);
+ } else {
+ // node doesn't exist, try to create it
+ // Ignore the permission bits here to ensure we can `open` this new
+ // file below. We use chmod below to apply the permissions once the
+ // file is open.
+ node = FS.mknod(path, mode | 511, 0);
+ created = true;
+ }
+ }
+ if (!node) {
+ throw new FS.ErrnoError(44);
+ }
+ // can't truncate a device
+ if (FS.isChrdev(node.mode)) {
+ flags &= ~512;
+ }
+ // if asked only for a directory, then this must be one
+ if ((flags & 65536) && !FS.isDir(node.mode)) {
+ throw new FS.ErrnoError(54);
+ }
+ // check permissions, if this is not a file we just created now (it is ok to
+ // create and write to a file with read-only permissions; it is read-only
+ // for later use)
+ if (!created) {
+ var errCode = FS.mayOpen(node, flags);
+ if (errCode) {
+ throw new FS.ErrnoError(errCode);
+ }
+ }
+ // do truncation if necessary
+ if ((flags & 512) && !created) {
+ FS.truncate(node, 0);
+ }
+ // we've already handled these, don't pass down to the underlying vfs
+ flags &= ~(128 | 512 | 131072);
+ // register the stream with the filesystem
+ var stream = FS.createStream({
+ node,
+ path: FS.getPath(node),
+ // we want the absolute path to the node
+ flags,
+ seekable: true,
+ position: 0,
+ stream_ops: node.stream_ops,
+ // used by the file family libc calls (fopen, fwrite, ferror, etc.)
+ ungotten: [],
+ error: false
+ });
+ // call the new stream's open function
+ if (stream.stream_ops.open) {
+ stream.stream_ops.open(stream);
+ }
+ if (created) {
+ FS.chmod(node, mode & 511);
+ }
+ return stream;
+ },
+ close(stream) {
+ if (FS.isClosed(stream)) {
+ throw new FS.ErrnoError(8);
+ }
+ if (stream.getdents) stream.getdents = null;
+ // free readdir state
+ try {
+ if (stream.stream_ops.close) {
+ stream.stream_ops.close(stream);
+ }
+ } catch (e) {
+ throw e;
+ } finally {
+ FS.closeStream(stream.fd);
+ }
+ stream.fd = null;
+ },
+ isClosed(stream) {
+ return stream.fd === null;
+ },
+ llseek(stream, offset, whence) {
+ if (FS.isClosed(stream)) {
+ throw new FS.ErrnoError(8);
+ }
+ if (!stream.seekable || !stream.stream_ops.llseek) {
+ throw new FS.ErrnoError(70);
+ }
+ if (whence != 0 && whence != 1 && whence != 2) {
+ throw new FS.ErrnoError(28);
+ }
+ stream.position = stream.stream_ops.llseek(stream, offset, whence);
+ stream.ungotten = [];
+ return stream.position;
+ },
+ read(stream, buffer, offset, length, position) {
+ if (length < 0 || position < 0) {
+ throw new FS.ErrnoError(28);
+ }
+ if (FS.isClosed(stream)) {
+ throw new FS.ErrnoError(8);
+ }
+ if ((stream.flags & 2097155) === 1) {
+ throw new FS.ErrnoError(8);
+ }
+ if (FS.isDir(stream.node.mode)) {
+ throw new FS.ErrnoError(31);
+ }
+ if (!stream.stream_ops.read) {
+ throw new FS.ErrnoError(28);
+ }
+ var seeking = typeof position != "undefined";
+ if (!seeking) {
+ position = stream.position;
+ } else if (!stream.seekable) {
+ throw new FS.ErrnoError(70);
+ }
+ var bytesRead = stream.stream_ops.read(stream, buffer, offset, length, position);
+ if (!seeking) stream.position += bytesRead;
+ return bytesRead;
+ },
+ write(stream, buffer, offset, length, position, canOwn) {
+ if (length < 0 || position < 0) {
+ throw new FS.ErrnoError(28);
+ }
+ if (FS.isClosed(stream)) {
+ throw new FS.ErrnoError(8);
+ }
+ if ((stream.flags & 2097155) === 0) {
+ throw new FS.ErrnoError(8);
+ }
+ if (FS.isDir(stream.node.mode)) {
+ throw new FS.ErrnoError(31);
+ }
+ if (!stream.stream_ops.write) {
+ throw new FS.ErrnoError(28);
+ }
+ if (stream.seekable && stream.flags & 1024) {
+ // seek to the end before writing in append mode
+ FS.llseek(stream, 0, 2);
+ }
+ var seeking = typeof position != "undefined";
+ if (!seeking) {
+ position = stream.position;
+ } else if (!stream.seekable) {
+ throw new FS.ErrnoError(70);
+ }
+ var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn);
+ if (!seeking) stream.position += bytesWritten;
+ return bytesWritten;
+ },
+ mmap(stream, length, position, prot, flags) {
+ // User requests writing to file (prot & PROT_WRITE != 0).
+ // Checking if we have permissions to write to the file unless
+ // MAP_PRIVATE flag is set. According to POSIX spec it is possible
+ // to write to file opened in read-only mode with MAP_PRIVATE flag,
+ // as all modifications will be visible only in the memory of
+ // the current process.
+ if ((prot & 2) !== 0 && (flags & 2) === 0 && (stream.flags & 2097155) !== 2) {
+ throw new FS.ErrnoError(2);
+ }
+ if ((stream.flags & 2097155) === 1) {
+ throw new FS.ErrnoError(2);
+ }
+ if (!stream.stream_ops.mmap) {
+ throw new FS.ErrnoError(43);
+ }
+ if (!length) {
+ throw new FS.ErrnoError(28);
+ }
+ return stream.stream_ops.mmap(stream, length, position, prot, flags);
+ },
+ msync(stream, buffer, offset, length, mmapFlags) {
+ if (!stream.stream_ops.msync) {
+ return 0;
+ }
+ return stream.stream_ops.msync(stream, buffer, offset, length, mmapFlags);
+ },
+ ioctl(stream, cmd, arg) {
+ if (!stream.stream_ops.ioctl) {
+ throw new FS.ErrnoError(59);
+ }
+ return stream.stream_ops.ioctl(stream, cmd, arg);
+ },
+ readFile(path, opts = {}) {
+ opts.flags = opts.flags || 0;
+ opts.encoding = opts.encoding || "binary";
+ if (opts.encoding !== "utf8" && opts.encoding !== "binary") {
+ abort(`Invalid encoding type "${opts.encoding}"`);
+ }
+ var stream = FS.open(path, opts.flags);
+ var stat = FS.stat(path);
+ var length = stat.size;
+ var buf = new Uint8Array(length);
+ FS.read(stream, buf, 0, length, 0);
+ if (opts.encoding === "utf8") {
+ buf = UTF8ArrayToString(buf);
+ }
+ FS.close(stream);
+ return buf;
+ },
+ writeFile(path, data, opts = {}) {
+ opts.flags = opts.flags || 577;
+ var stream = FS.open(path, opts.flags, opts.mode);
+ if (typeof data == "string") {
+ data = new Uint8Array(intArrayFromString(data, true));
+ }
+ if (ArrayBuffer.isView(data)) {
+ FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn);
+ } else {
+ abort("Unsupported data type");
+ }
+ FS.close(stream);
+ },
+ cwd: () => FS.currentPath,
+ chdir(path) {
+ var lookup = FS.lookupPath(path, {
+ follow: true
+ });
+ if (lookup.node === null) {
+ throw new FS.ErrnoError(44);
+ }
+ if (!FS.isDir(lookup.node.mode)) {
+ throw new FS.ErrnoError(54);
+ }
+ var errCode = FS.nodePermissions(lookup.node, "x");
+ if (errCode) {
+ throw new FS.ErrnoError(errCode);
+ }
+ FS.currentPath = lookup.path;
+ },
+ createDefaultDirectories() {
+ FS.mkdir("/tmp");
+ FS.mkdir("/home");
+ FS.mkdir("/home/web_user");
+ },
+ createDefaultDevices() {
+ // create /dev
+ FS.mkdir("/dev");
+ // setup /dev/null
+ FS.registerDevice(FS.makedev(1, 3), {
+ read: () => 0,
+ write: (stream, buffer, offset, length, pos) => length,
+ llseek: () => 0
+ });
+ FS.mkdev("/dev/null", FS.makedev(1, 3));
+ // setup /dev/tty and /dev/tty1
+ // stderr needs to print output using err() rather than out()
+ // so we register a second tty just for it.
+ TTY.register(FS.makedev(5, 0), TTY.default_tty_ops);
+ TTY.register(FS.makedev(6, 0), TTY.default_tty1_ops);
+ FS.mkdev("/dev/tty", FS.makedev(5, 0));
+ FS.mkdev("/dev/tty1", FS.makedev(6, 0));
+ // setup /dev/[u]random
+ // use a buffer to avoid overhead of individual crypto calls per byte
+ var randomBuffer = new Uint8Array(1024), randomLeft = 0;
+ var randomByte = () => {
+ if (randomLeft === 0) {
+ randomFill(randomBuffer);
+ randomLeft = randomBuffer.byteLength;
+ }
+ return randomBuffer[--randomLeft];
+ };
+ FS.createDevice("/dev", "random", randomByte);
+ FS.createDevice("/dev", "urandom", randomByte);
+ // we're not going to emulate the actual shm device,
+ // just create the tmp dirs that reside in it commonly
+ FS.mkdir("/dev/shm");
+ FS.mkdir("/dev/shm/tmp");
+ },
+ createSpecialDirectories() {
+ // create /proc/self/fd which allows /proc/self/fd/6 => readlink gives the
+ // name of the stream for fd 6 (see test_unistd_ttyname)
+ FS.mkdir("/proc");
+ var proc_self = FS.mkdir("/proc/self");
+ FS.mkdir("/proc/self/fd");
+ FS.mount({
+ mount() {
+ var node = FS.createNode(proc_self, "fd", 16895, 73);
+ node.stream_ops = {
+ llseek: MEMFS.stream_ops.llseek
+ };
+ node.node_ops = {
+ lookup(parent, name) {
+ var fd = +name;
+ var stream = FS.getStreamChecked(fd);
+ var ret = {
+ parent: null,
+ mount: {
+ mountpoint: "fake"
+ },
+ node_ops: {
+ readlink: () => stream.path
+ },
+ id: fd + 1
+ };
+ ret.parent = ret;
+ // make it look like a simple root node
+ return ret;
+ },
+ readdir() {
+ return Array.from(FS.streams.entries()).filter(([k, v]) => v).map(([k, v]) => k.toString());
+ }
+ };
+ return node;
+ }
+ }, {}, "/proc/self/fd");
+ },
+ createStandardStreams(input, output, error) {
+ // TODO deprecate the old functionality of a single
+ // input / output callback and that utilizes FS.createDevice
+ // and instead require a unique set of stream ops
+ // by default, we symlink the standard streams to the
+ // default tty devices. however, if the standard streams
+ // have been overwritten we create a unique device for
+ // them instead.
+ if (input) {
+ FS.createDevice("/dev", "stdin", input);
+ } else {
+ FS.symlink("/dev/tty", "/dev/stdin");
+ }
+ if (output) {
+ FS.createDevice("/dev", "stdout", null, output);
+ } else {
+ FS.symlink("/dev/tty", "/dev/stdout");
+ }
+ if (error) {
+ FS.createDevice("/dev", "stderr", null, error);
+ } else {
+ FS.symlink("/dev/tty1", "/dev/stderr");
+ }
+ // open default streams for the stdin, stdout and stderr devices
+ var stdin = FS.open("/dev/stdin", 0);
+ var stdout = FS.open("/dev/stdout", 1);
+ var stderr = FS.open("/dev/stderr", 1);
+ },
+ staticInit() {
+ FS.nameTable = new Array(4096);
+ FS.mount(MEMFS, {}, "/");
+ FS.createDefaultDirectories();
+ FS.createDefaultDevices();
+ FS.createSpecialDirectories();
+ FS.filesystems = {
+ "MEMFS": MEMFS
+ };
+ },
+ init(input, output, error) {
+ FS.initialized = true;
+ // Allow Module.stdin etc. to provide defaults, if none explicitly passed to us here
+ input ??= Module["stdin"];
+ output ??= Module["stdout"];
+ error ??= Module["stderr"];
+ FS.createStandardStreams(input, output, error);
+ },
+ quit() {
+ FS.initialized = false;
+ // force-flush all streams, so we get musl std streams printed out
+ // close all of our streams
+ for (var stream of FS.streams) {
+ if (stream) {
+ FS.close(stream);
+ }
+ }
+ },
+ findObject(path, dontResolveLastLink) {
+ var ret = FS.analyzePath(path, dontResolveLastLink);
+ if (!ret.exists) {
+ return null;
+ }
+ return ret.object;
+ },
+ analyzePath(path, dontResolveLastLink) {
+ // operate from within the context of the symlink's target
+ try {
+ var lookup = FS.lookupPath(path, {
+ follow: !dontResolveLastLink
+ });
+ path = lookup.path;
+ } catch (e) {}
+ var ret = {
+ isRoot: false,
+ exists: false,
+ error: 0,
+ name: null,
+ path: null,
+ object: null,
+ parentExists: false,
+ parentPath: null,
+ parentObject: null
+ };
+ try {
+ var lookup = FS.lookupPath(path, {
+ parent: true
+ });
+ ret.parentExists = true;
+ ret.parentPath = lookup.path;
+ ret.parentObject = lookup.node;
+ ret.name = PATH.basename(path);
+ lookup = FS.lookupPath(path, {
+ follow: !dontResolveLastLink
+ });
+ ret.exists = true;
+ ret.path = lookup.path;
+ ret.object = lookup.node;
+ ret.name = lookup.node.name;
+ ret.isRoot = lookup.path === "/";
+ } catch (e) {
+ ret.error = e.errno;
+ }
+ return ret;
+ },
+ createPath(parent, path, canRead, canWrite) {
+ parent = typeof parent == "string" ? parent : FS.getPath(parent);
+ var parts = path.split("/").reverse();
+ while (parts.length) {
+ var part = parts.pop();
+ if (!part) continue;
+ var current = PATH.join2(parent, part);
+ try {
+ FS.mkdir(current);
+ } catch (e) {
+ if (e.errno != 20) throw e;
+ }
+ parent = current;
+ }
+ return current;
+ },
+ createFile(parent, name, properties, canRead, canWrite) {
+ var path = PATH.join2(typeof parent == "string" ? parent : FS.getPath(parent), name);
+ var mode = FS_getMode(canRead, canWrite);
+ return FS.create(path, mode);
+ },
+ createDataFile(parent, name, data, canRead, canWrite, canOwn) {
+ var path = name;
+ if (parent) {
+ parent = typeof parent == "string" ? parent : FS.getPath(parent);
+ path = name ? PATH.join2(parent, name) : parent;
+ }
+ var mode = FS_getMode(canRead, canWrite);
+ var node = FS.create(path, mode);
+ if (data) {
+ if (typeof data == "string") {
+ var arr = new Array(data.length);
+ for (var i = 0, len = data.length; i < len; ++i) arr[i] = data.charCodeAt(i);
+ data = arr;
+ }
+ // make sure we can write to the file
+ FS.chmod(node, mode | 146);
+ var stream = FS.open(node, 577);
+ FS.write(stream, data, 0, data.length, 0, canOwn);
+ FS.close(stream);
+ FS.chmod(node, mode);
+ }
+ },
+ createDevice(parent, name, input, output) {
+ var path = PATH.join2(typeof parent == "string" ? parent : FS.getPath(parent), name);
+ var mode = FS_getMode(!!input, !!output);
+ FS.createDevice.major ??= 64;
+ var dev = FS.makedev(FS.createDevice.major++, 0);
+ // Create a fake device that a set of stream ops to emulate
+ // the old behavior.
+ FS.registerDevice(dev, {
+ open(stream) {
+ stream.seekable = false;
+ },
+ close(stream) {
+ // flush any pending line data
+ if (output?.buffer?.length) {
+ output(10);
+ }
+ },
+ read(stream, buffer, offset, length, pos) {
+ var bytesRead = 0;
+ for (var i = 0; i < length; i++) {
+ var result;
+ try {
+ result = input();
+ } catch (e) {
+ throw new FS.ErrnoError(29);
+ }
+ if (result === undefined && bytesRead === 0) {
+ throw new FS.ErrnoError(6);
+ }
+ if (result === null || result === undefined) break;
+ bytesRead++;
+ buffer[offset + i] = result;
+ }
+ if (bytesRead) {
+ stream.node.atime = Date.now();
+ }
+ return bytesRead;
+ },
+ write(stream, buffer, offset, length, pos) {
+ for (var i = 0; i < length; i++) {
+ try {
+ output(buffer[offset + i]);
+ } catch (e) {
+ throw new FS.ErrnoError(29);
+ }
+ }
+ if (length) {
+ stream.node.mtime = stream.node.ctime = Date.now();
+ }
+ return i;
+ }
+ });
+ return FS.mkdev(path, mode, dev);
+ },
+ forceLoadFile(obj) {
+ if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true;
+ if (globalThis.XMLHttpRequest) {
+ abort("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.");
+ } else {
+ // Command-line.
+ try {
+ obj.contents = readBinary(obj.url);
+ } catch (e) {
+ throw new FS.ErrnoError(29);
+ }
+ }
+ },
+ createLazyFile(parent, name, url, canRead, canWrite) {
+ // Lazy chunked Uint8Array (implements get and length from Uint8Array).
+ // Actual getting is abstracted away for eventual reuse.
+ class LazyUint8Array {
+ lengthKnown=false;
+ chunks=[];
+ // Loaded chunks. Index is the chunk number
+ get(idx) {
+ if (idx > this.length - 1 || idx < 0) {
+ return undefined;
+ }
+ var chunkOffset = idx % this.chunkSize;
+ var chunkNum = (idx / this.chunkSize) | 0;
+ return this.getter(chunkNum)[chunkOffset];
+ }
+ setDataGetter(getter) {
+ this.getter = getter;
+ }
+ cacheLength() {
+ // Find length
+ var xhr = new XMLHttpRequest;
+ xhr.open("HEAD", url, false);
+ xhr.send(null);
+ if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) abort("Couldn't load " + url + ". Status: " + xhr.status);
+ var datalength = Number(xhr.getResponseHeader("Content-length"));
+ var header;
+ var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes";
+ var usesGzip = (header = xhr.getResponseHeader("Content-Encoding")) && header === "gzip";
+ var chunkSize = 1024 * 1024;
+ // Chunk size in bytes
+ if (!hasByteServing) chunkSize = datalength;
+ // Function to get a range from the remote URL.
+ var doXHR = (from, to) => {
+ if (from > to) abort("invalid range (" + from + ", " + to + ") or no bytes requested!");
+ if (to > datalength - 1) abort("only " + datalength + " bytes available! programmer error!");
+ // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available.
+ var xhr = new XMLHttpRequest;
+ xhr.open("GET", url, false);
+ if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to);
+ // Some hints to the browser that we want binary data.
+ xhr.responseType = "arraybuffer";
+ if (xhr.overrideMimeType) {
+ xhr.overrideMimeType("text/plain; charset=x-user-defined");
+ }
+ xhr.send(null);
+ if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) abort("Couldn't load " + url + ". Status: " + xhr.status);
+ if (xhr.response !== undefined) {
+ return new Uint8Array(/** @type{Array} */ (xhr.response || []));
+ }
+ return intArrayFromString(xhr.responseText || "", true);
+ };
+ var lazyArray = this;
+ lazyArray.setDataGetter(chunkNum => {
+ var start = chunkNum * chunkSize;
+ var end = (chunkNum + 1) * chunkSize - 1;
+ // including this byte
+ end = Math.min(end, datalength - 1);
+ // if datalength-1 is selected, this is the last block
+ if (typeof lazyArray.chunks[chunkNum] == "undefined") {
+ lazyArray.chunks[chunkNum] = doXHR(start, end);
+ }
+ if (typeof lazyArray.chunks[chunkNum] == "undefined") abort("doXHR failed!");
+ return lazyArray.chunks[chunkNum];
+ });
+ if (usesGzip || !datalength) {
+ // if the server uses gzip or doesn't supply the length, we have to download the whole file to get the (uncompressed) length
+ chunkSize = datalength = 1;
+ // this will force getter(0)/doXHR do download the whole file
+ datalength = this.getter(0).length;
+ chunkSize = datalength;
+ out("LazyFiles on gzip forces download of the whole file when length is accessed");
+ }
+ this._length = datalength;
+ this._chunkSize = chunkSize;
+ this.lengthKnown = true;
+ }
+ get length() {
+ if (!this.lengthKnown) {
+ this.cacheLength();
+ }
+ return this._length;
+ }
+ get chunkSize() {
+ if (!this.lengthKnown) {
+ this.cacheLength();
+ }
+ return this._chunkSize;
+ }
+ }
+ if (globalThis.XMLHttpRequest) {
+ if (!ENVIRONMENT_IS_WORKER) abort("Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc");
+ var lazyArray = new LazyUint8Array;
+ var properties = {
+ isDevice: false,
+ contents: lazyArray
+ };
+ } else {
+ var properties = {
+ isDevice: false,
+ url
+ };
+ }
+ var node = FS.createFile(parent, name, properties, canRead, canWrite);
+ // This is a total hack, but I want to get this lazy file code out of the
+ // core of MEMFS. If we want to keep this lazy file concept I feel it should
+ // be its own thin LAZYFS proxying calls to MEMFS.
+ if (properties.contents) {
+ node.contents = properties.contents;
+ } else if (properties.url) {
+ node.contents = null;
+ node.url = properties.url;
+ }
+ // Add a function that defers querying the file size until it is asked the first time.
+ Object.defineProperties(node, {
+ usedBytes: {
+ get: function() {
+ return this.contents.length;
+ }
+ }
+ });
+ // override each stream op with one that tries to force load the lazy file first
+ var stream_ops = {};
+ for (const [key, fn] of Object.entries(node.stream_ops)) {
+ stream_ops[key] = (...args) => {
+ FS.forceLoadFile(node);
+ return fn(...args);
+ };
+ }
+ function writeChunks(stream, buffer, offset, length, position) {
+ var contents = stream.node.contents;
+ if (position >= contents.length) return 0;
+ var size = Math.min(contents.length - position, length);
+ if (contents.slice) {
+ // normal array
+ for (var i = 0; i < size; i++) {
+ buffer[offset + i] = contents[position + i];
+ }
+ } else {
+ for (var i = 0; i < size; i++) {
+ // LazyUint8Array from sync binary XHR
+ buffer[offset + i] = contents.get(position + i);
+ }
+ }
+ return size;
+ }
+ // use a custom read function
+ stream_ops.read = (stream, buffer, offset, length, position) => {
+ FS.forceLoadFile(node);
+ return writeChunks(stream, buffer, offset, length, position);
+ };
+ // use a custom mmap function
+ stream_ops.mmap = (stream, length, position, prot, flags) => {
+ FS.forceLoadFile(node);
+ var ptr = mmapAlloc(length);
+ if (!ptr) {
+ throw new FS.ErrnoError(48);
+ }
+ writeChunks(stream, HEAP8, ptr, length, position);
+ return {
+ ptr,
+ allocated: true
+ };
+ };
+ node.stream_ops = stream_ops;
+ return node;
+ }
+};
+
+/**
+ * Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the
+ * emscripten HEAP, returns a copy of that string as a Javascript String object.
+ *
+ * @param {number} ptr
+ * @param {number=} maxBytesToRead - An optional length that specifies the
+ * maximum number of bytes to read. You can omit this parameter to scan the
+ * string until the first 0 byte. If maxBytesToRead is passed, and the string
+ * at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the
+ * string will cut short at that byte index.
+ * @param {boolean=} ignoreNul - If true, the function will not stop on a NUL character.
+ * @return {string}
+ */ var UTF8ToString = (ptr, maxBytesToRead, ignoreNul) => {
+ ptr >>>= 0;
+ if (!ptr) return "";
+ var end = findStringEnd(HEAPU8, ptr, maxBytesToRead, ignoreNul);
+ return UTF8Decoder.decode(HEAPU8.subarray(ptr >>> 0, end >>> 0));
+};
+
+var SYSCALLS = {
+ calculateAt(dirfd, path, allowEmpty) {
+ if (PATH.isAbs(path)) {
+ return path;
+ }
+ // relative path
+ var dir;
+ if (dirfd === -100) {
+ dir = FS.cwd();
+ } else {
+ var dirstream = SYSCALLS.getStreamFromFD(dirfd);
+ dir = dirstream.path;
+ }
+ if (path.length == 0) {
+ if (!allowEmpty) {
+ throw new FS.ErrnoError(44);
+ }
+ return dir;
+ }
+ return dir + "/" + path;
+ },
+ writeStat(buf, stat) {
+ HEAPU32[((buf) >>> 2) >>> 0] = stat.dev;
+ HEAPU32[(((buf) + (4)) >>> 2) >>> 0] = stat.mode;
+ HEAPU32[(((buf) + (8)) >>> 2) >>> 0] = stat.nlink;
+ HEAPU32[(((buf) + (12)) >>> 2) >>> 0] = stat.uid;
+ HEAPU32[(((buf) + (16)) >>> 2) >>> 0] = stat.gid;
+ HEAPU32[(((buf) + (20)) >>> 2) >>> 0] = stat.rdev;
+ (tempI64 = [ stat.size >>> 0, (tempDouble = stat.size, (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0) ],
+ HEAP32[(((buf) + (24)) >>> 2) >>> 0] = tempI64[0], HEAP32[(((buf) + (28)) >>> 2) >>> 0] = tempI64[1]);
+ HEAP32[(((buf) + (32)) >>> 2) >>> 0] = 4096;
+ HEAP32[(((buf) + (36)) >>> 2) >>> 0] = stat.blocks;
+ var atime = stat.atime.getTime();
+ var mtime = stat.mtime.getTime();
+ var ctime = stat.ctime.getTime();
+ (tempI64 = [ Math.floor(atime / 1e3) >>> 0, (tempDouble = Math.floor(atime / 1e3),
+ (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0) ],
+ HEAP32[(((buf) + (40)) >>> 2) >>> 0] = tempI64[0], HEAP32[(((buf) + (44)) >>> 2) >>> 0] = tempI64[1]);
+ HEAPU32[(((buf) + (48)) >>> 2) >>> 0] = (atime % 1e3) * 1e3 * 1e3;
+ (tempI64 = [ Math.floor(mtime / 1e3) >>> 0, (tempDouble = Math.floor(mtime / 1e3),
+ (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0) ],
+ HEAP32[(((buf) + (56)) >>> 2) >>> 0] = tempI64[0], HEAP32[(((buf) + (60)) >>> 2) >>> 0] = tempI64[1]);
+ HEAPU32[(((buf) + (64)) >>> 2) >>> 0] = (mtime % 1e3) * 1e3 * 1e3;
+ (tempI64 = [ Math.floor(ctime / 1e3) >>> 0, (tempDouble = Math.floor(ctime / 1e3),
+ (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0) ],
+ HEAP32[(((buf) + (72)) >>> 2) >>> 0] = tempI64[0], HEAP32[(((buf) + (76)) >>> 2) >>> 0] = tempI64[1]);
+ HEAPU32[(((buf) + (80)) >>> 2) >>> 0] = (ctime % 1e3) * 1e3 * 1e3;
+ (tempI64 = [ stat.ino >>> 0, (tempDouble = stat.ino, (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0) ],
+ HEAP32[(((buf) + (88)) >>> 2) >>> 0] = tempI64[0], HEAP32[(((buf) + (92)) >>> 2) >>> 0] = tempI64[1]);
+ return 0;
+ },
+ writeStatFs(buf, stats) {
+ HEAPU32[(((buf) + (4)) >>> 2) >>> 0] = stats.bsize;
+ HEAPU32[(((buf) + (60)) >>> 2) >>> 0] = stats.bsize;
+ (tempI64 = [ stats.blocks >>> 0, (tempDouble = stats.blocks, (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0) ],
+ HEAP32[(((buf) + (8)) >>> 2) >>> 0] = tempI64[0], HEAP32[(((buf) + (12)) >>> 2) >>> 0] = tempI64[1]);
+ (tempI64 = [ stats.bfree >>> 0, (tempDouble = stats.bfree, (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0) ],
+ HEAP32[(((buf) + (16)) >>> 2) >>> 0] = tempI64[0], HEAP32[(((buf) + (20)) >>> 2) >>> 0] = tempI64[1]);
+ (tempI64 = [ stats.bavail >>> 0, (tempDouble = stats.bavail, (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0) ],
+ HEAP32[(((buf) + (24)) >>> 2) >>> 0] = tempI64[0], HEAP32[(((buf) + (28)) >>> 2) >>> 0] = tempI64[1]);
+ (tempI64 = [ stats.files >>> 0, (tempDouble = stats.files, (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0) ],
+ HEAP32[(((buf) + (32)) >>> 2) >>> 0] = tempI64[0], HEAP32[(((buf) + (36)) >>> 2) >>> 0] = tempI64[1]);
+ (tempI64 = [ stats.ffree >>> 0, (tempDouble = stats.ffree, (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0) ],
+ HEAP32[(((buf) + (40)) >>> 2) >>> 0] = tempI64[0], HEAP32[(((buf) + (44)) >>> 2) >>> 0] = tempI64[1]);
+ HEAPU32[(((buf) + (48)) >>> 2) >>> 0] = stats.fsid;
+ HEAPU32[(((buf) + (64)) >>> 2) >>> 0] = stats.flags;
+ // ST_NOSUID
+ HEAPU32[(((buf) + (56)) >>> 2) >>> 0] = stats.namelen;
+ },
+ doMsync(addr, stream, len, flags, offset) {
+ if (!FS.isFile(stream.node.mode)) {
+ throw new FS.ErrnoError(43);
+ }
+ if (flags & 2) {
+ // MAP_PRIVATE calls need not to be synced back to underlying fs
+ return 0;
+ }
+ var buffer = HEAPU8.slice(addr, addr + len);
+ FS.msync(stream, buffer, offset, len, flags);
+ },
+ getStreamFromFD(fd) {
+ var stream = FS.getStreamChecked(fd);
+ return stream;
+ },
+ varargs: undefined,
+ getStr(ptr) {
+ var ret = UTF8ToString(ptr);
+ return ret;
+ }
+};
+
+function ___syscall_dup(fd) {
+ try {
+ var old = SYSCALLS.getStreamFromFD(fd);
+ return FS.dupStream(old).fd;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+function ___syscall_faccessat(dirfd, path, amode, flags) {
+ path >>>= 0;
+ try {
+ path = SYSCALLS.getStr(path);
+ path = SYSCALLS.calculateAt(dirfd, path);
+ if (amode & ~7) {
+ // need a valid mode
+ return -28;
+ }
+ var lookup = FS.lookupPath(path, {
+ follow: true
+ });
+ var node = lookup.node;
+ if (!node) {
+ return -44;
+ }
+ var perms = "";
+ if (amode & 4) perms += "r";
+ if (amode & 2) perms += "w";
+ if (amode & 1) perms += "x";
+ if (perms && FS.nodePermissions(node, perms)) {
+ return -2;
+ }
+ return 0;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+var syscallGetVarargI = () => {
+ // the `+` prepended here is necessary to convince the JSCompiler that varargs is indeed a number.
+ var ret = HEAP32[((+SYSCALLS.varargs) >>> 2) >>> 0];
+ SYSCALLS.varargs += 4;
+ return ret;
+};
+
+var syscallGetVarargP = syscallGetVarargI;
+
+function ___syscall_fcntl64(fd, cmd, varargs) {
+ varargs >>>= 0;
+ SYSCALLS.varargs = varargs;
+ try {
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ switch (cmd) {
+ case 0:
+ {
+ var arg = syscallGetVarargI();
+ if (arg < 0) {
+ return -28;
+ }
+ while (FS.streams[arg]) {
+ arg++;
+ }
+ var newStream;
+ newStream = FS.dupStream(stream, arg);
+ return newStream.fd;
+ }
+
+ case 1:
+ case 2:
+ return 0;
+
+ // FD_CLOEXEC makes no sense for a single process.
+ case 3:
+ return stream.flags;
+
+ case 4:
+ {
+ var arg = syscallGetVarargI();
+ stream.flags |= arg;
+ return 0;
+ }
+
+ case 12:
+ {
+ var arg = syscallGetVarargP();
+ var offset = 0;
+ // We're always unlocked.
+ HEAP16[(((arg) + (offset)) >>> 1) >>> 0] = 2;
+ return 0;
+ }
+
+ case 13:
+ case 14:
+ // Pretend that the locking is successful. These are process-level locks,
+ // and Emscripten programs are a single process. If we supported linking a
+ // filesystem between programs, we'd need to do more here.
+ // See https://github.com/emscripten-core/emscripten/issues/23697
+ return 0;
+ }
+ return -28;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+function ___syscall_fstat64(fd, buf) {
+ buf >>>= 0;
+ try {
+ return SYSCALLS.writeStat(buf, FS.fstat(fd));
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+function ___syscall_ftruncate64(fd, length_low, length_high) {
+ var length = convertI32PairToI53Checked(length_low, length_high);
+ try {
+ if (isNaN(length)) return -61;
+ FS.ftruncate(fd, length);
+ return 0;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+var stringToUTF8 = (str, outPtr, maxBytesToWrite) => stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
+
+function ___syscall_getcwd(buf, size) {
+ buf >>>= 0;
+ size >>>= 0;
+ try {
+ if (size === 0) return -28;
+ var cwd = FS.cwd();
+ var cwdLengthInBytes = lengthBytesUTF8(cwd) + 1;
+ if (size < cwdLengthInBytes) return -68;
+ stringToUTF8(cwd, buf, size);
+ return cwdLengthInBytes;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+function ___syscall_getdents64(fd, dirp, count) {
+ dirp >>>= 0;
+ count >>>= 0;
+ try {
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ stream.getdents ||= FS.readdir(stream.path);
+ var struct_size = 280;
+ var pos = 0;
+ var off = FS.llseek(stream, 0, 1);
+ var startIdx = Math.floor(off / struct_size);
+ var endIdx = Math.min(stream.getdents.length, startIdx + Math.floor(count / struct_size));
+ for (var idx = startIdx; idx < endIdx; idx++) {
+ var id;
+ var type;
+ var name = stream.getdents[idx];
+ if (name === ".") {
+ id = stream.node.id;
+ type = 4;
+ } else if (name === "..") {
+ var lookup = FS.lookupPath(stream.path, {
+ parent: true
+ });
+ id = lookup.node.id;
+ type = 4;
+ } else {
+ var child;
+ try {
+ child = FS.lookupNode(stream.node, name);
+ } catch (e) {
+ // If the entry is not a directory, file, or symlink, nodefs
+ // lookupNode will raise EINVAL. Skip these and continue.
+ if (e?.errno === 28) {
+ continue;
+ }
+ throw e;
+ }
+ id = child.id;
+ type = FS.isChrdev(child.mode) ? 2 : // character device.
+ FS.isDir(child.mode) ? 4 : // directory
+ FS.isLink(child.mode) ? 10 : // symbolic link.
+ 8;
+ }
+ (tempI64 = [ id >>> 0, (tempDouble = id, (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0) ],
+ HEAP32[((dirp + pos) >>> 2) >>> 0] = tempI64[0], HEAP32[(((dirp + pos) + (4)) >>> 2) >>> 0] = tempI64[1]);
+ (tempI64 = [ (idx + 1) * struct_size >>> 0, (tempDouble = (idx + 1) * struct_size,
+ (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0) ],
+ HEAP32[(((dirp + pos) + (8)) >>> 2) >>> 0] = tempI64[0], HEAP32[(((dirp + pos) + (12)) >>> 2) >>> 0] = tempI64[1]);
+ HEAP16[(((dirp + pos) + (16)) >>> 1) >>> 0] = 280;
+ HEAP8[(dirp + pos) + (18) >>> 0] = type;
+ stringToUTF8(name, dirp + pos + 19, 256);
+ pos += struct_size;
+ }
+ FS.llseek(stream, idx * struct_size, 0);
+ return pos;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+function ___syscall_ioctl(fd, op, varargs) {
+ varargs >>>= 0;
+ SYSCALLS.varargs = varargs;
+ try {
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ switch (op) {
+ case 21509:
+ {
+ if (!stream.tty) return -59;
+ return 0;
+ }
+
+ case 21505:
+ {
+ if (!stream.tty) return -59;
+ if (stream.tty.ops.ioctl_tcgets) {
+ var termios = stream.tty.ops.ioctl_tcgets(stream);
+ var argp = syscallGetVarargP();
+ HEAP32[((argp) >>> 2) >>> 0] = termios.c_iflag || 0;
+ HEAP32[(((argp) + (4)) >>> 2) >>> 0] = termios.c_oflag || 0;
+ HEAP32[(((argp) + (8)) >>> 2) >>> 0] = termios.c_cflag || 0;
+ HEAP32[(((argp) + (12)) >>> 2) >>> 0] = termios.c_lflag || 0;
+ for (var i = 0; i < 32; i++) {
+ HEAP8[(argp + i) + (17) >>> 0] = termios.c_cc[i] || 0;
+ }
+ return 0;
+ }
+ return 0;
+ }
+
+ case 21510:
+ case 21511:
+ case 21512:
+ {
+ if (!stream.tty) return -59;
+ return 0;
+ }
+
+ case 21506:
+ case 21507:
+ case 21508:
+ {
+ if (!stream.tty) return -59;
+ if (stream.tty.ops.ioctl_tcsets) {
+ var argp = syscallGetVarargP();
+ var c_iflag = HEAP32[((argp) >>> 2) >>> 0];
+ var c_oflag = HEAP32[(((argp) + (4)) >>> 2) >>> 0];
+ var c_cflag = HEAP32[(((argp) + (8)) >>> 2) >>> 0];
+ var c_lflag = HEAP32[(((argp) + (12)) >>> 2) >>> 0];
+ var c_cc = [];
+ for (var i = 0; i < 32; i++) {
+ c_cc.push(HEAP8[(argp + i) + (17) >>> 0]);
+ }
+ return stream.tty.ops.ioctl_tcsets(stream.tty, op, {
+ c_iflag,
+ c_oflag,
+ c_cflag,
+ c_lflag,
+ c_cc
+ });
+ }
+ return 0;
+ }
+
+ case 21519:
+ {
+ if (!stream.tty) return -59;
+ var argp = syscallGetVarargP();
+ HEAP32[((argp) >>> 2) >>> 0] = 0;
+ return 0;
+ }
+
+ case 21520:
+ {
+ if (!stream.tty) return -59;
+ return -28;
+ }
+
+ case 21537:
+ case 21531:
+ {
+ var argp = syscallGetVarargP();
+ return FS.ioctl(stream, op, argp);
+ }
+
+ case 21523:
+ {
+ // TODO: in theory we should write to the winsize struct that gets
+ // passed in, but for now musl doesn't read anything on it
+ if (!stream.tty) return -59;
+ if (stream.tty.ops.ioctl_tiocgwinsz) {
+ var winsize = stream.tty.ops.ioctl_tiocgwinsz(stream.tty);
+ var argp = syscallGetVarargP();
+ HEAP16[((argp) >>> 1) >>> 0] = winsize[0];
+ HEAP16[(((argp) + (2)) >>> 1) >>> 0] = winsize[1];
+ }
+ return 0;
+ }
+
+ case 21524:
+ {
+ // TODO: technically, this ioctl call should change the window size.
+ // but, since emscripten doesn't have any concept of a terminal window
+ // yet, we'll just silently throw it away as we do TIOCGWINSZ
+ if (!stream.tty) return -59;
+ return 0;
+ }
+
+ case 21515:
+ {
+ if (!stream.tty) return -59;
+ return 0;
+ }
+
+ default:
+ return -28;
+ }
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+function ___syscall_lstat64(path, buf) {
+ path >>>= 0;
+ buf >>>= 0;
+ try {
+ path = SYSCALLS.getStr(path);
+ return SYSCALLS.writeStat(buf, FS.lstat(path));
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+function ___syscall_mkdirat(dirfd, path, mode) {
+ path >>>= 0;
+ try {
+ path = SYSCALLS.getStr(path);
+ path = SYSCALLS.calculateAt(dirfd, path);
+ FS.mkdir(path, mode, 0);
+ return 0;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+function ___syscall_newfstatat(dirfd, path, buf, flags) {
+ path >>>= 0;
+ buf >>>= 0;
+ try {
+ path = SYSCALLS.getStr(path);
+ var nofollow = flags & 256;
+ var allowEmpty = flags & 4096;
+ flags = flags & (~6400);
+ path = SYSCALLS.calculateAt(dirfd, path, allowEmpty);
+ return SYSCALLS.writeStat(buf, nofollow ? FS.lstat(path) : FS.stat(path));
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+function ___syscall_openat(dirfd, path, flags, varargs) {
+ path >>>= 0;
+ varargs >>>= 0;
+ SYSCALLS.varargs = varargs;
+ try {
+ path = SYSCALLS.getStr(path);
+ path = SYSCALLS.calculateAt(dirfd, path);
+ var mode = varargs ? syscallGetVarargI() : 0;
+ return FS.open(path, flags, mode).fd;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+function ___syscall_stat64(path, buf) {
+ path >>>= 0;
+ buf >>>= 0;
+ try {
+ path = SYSCALLS.getStr(path);
+ return SYSCALLS.writeStat(buf, FS.stat(path));
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+var __abort_js = () => abort("");
+
+function __embind_register_bigint(primitiveType, name, size, minRange, maxRange) {
+ primitiveType >>>= 0;
+ name >>>= 0;
+ size >>>= 0;
+}
+
+var AsciiToString = ptr => {
+ ptr >>>= 0;
+ var str = "";
+ while (1) {
+ var ch = HEAPU8[ptr++ >>> 0];
+ if (!ch) return str;
+ str += String.fromCharCode(ch);
+ }
+};
+
+var awaitingDependencies = {};
+
+var registeredTypes = {};
+
+var typeDependencies = {};
+
+var BindingError = class BindingError extends Error {
+ constructor(message) {
+ super(message);
+ this.name = "BindingError";
+ }
+};
+
+var throwBindingError = message => {
+ throw new BindingError(message);
+};
+
+/** @param {Object=} options */ function sharedRegisterType(rawType, registeredInstance, options = {}) {
+ var name = registeredInstance.name;
+ if (!rawType) {
+ throwBindingError(`type "${name}" must have a positive integer typeid pointer`);
+ }
+ if (registeredTypes.hasOwnProperty(rawType)) {
+ if (options.ignoreDuplicateRegistrations) {
+ return;
+ } else {
+ throwBindingError(`Cannot register type '${name}' twice`);
+ }
+ }
+ registeredTypes[rawType] = registeredInstance;
+ delete typeDependencies[rawType];
+ if (awaitingDependencies.hasOwnProperty(rawType)) {
+ var callbacks = awaitingDependencies[rawType];
+ delete awaitingDependencies[rawType];
+ callbacks.forEach(cb => cb());
+ }
+}
+
+/** @param {Object=} options */ function registerType(rawType, registeredInstance, options = {}) {
+ return sharedRegisterType(rawType, registeredInstance, options);
+}
+
+/** @suppress {globalThis} */ function __embind_register_bool(rawType, name, trueValue, falseValue) {
+ rawType >>>= 0;
+ name >>>= 0;
+ name = AsciiToString(name);
+ registerType(rawType, {
+ name,
+ fromWireType: function(wt) {
+ // ambiguous emscripten ABI: sometimes return values are
+ // true or false, and sometimes integers (0 or 1)
+ return !!wt;
+ },
+ toWireType: function(destructors, o) {
+ return o ? trueValue : falseValue;
+ },
+ readValueFromPointer: function(pointer) {
+ return this.fromWireType(HEAPU8[pointer >>> 0]);
+ },
+ destructorFunction: null
+ });
+}
+
+var emval_freelist = [];
+
+var emval_handles = [ 0, 1, , 1, null, 1, true, 1, false, 1 ];
+
+function __emval_decref(handle) {
+ handle >>>= 0;
+ if (handle > 9 && 0 === --emval_handles[handle + 1]) {
+ emval_handles[handle] = undefined;
+ emval_freelist.push(handle);
+ }
+}
+
+var Emval = {
+ toValue: handle => {
+ if (!handle) {
+ throwBindingError(`Cannot use deleted val. handle = ${handle}`);
+ }
+ return emval_handles[handle];
+ },
+ toHandle: value => {
+ switch (value) {
+ case undefined:
+ return 2;
+
+ case null:
+ return 4;
+
+ case true:
+ return 6;
+
+ case false:
+ return 8;
+
+ default:
+ {
+ const handle = emval_freelist.pop() || emval_handles.length;
+ emval_handles[handle] = value;
+ emval_handles[handle + 1] = 1;
+ return handle;
+ }
+ }
+ }
+};
+
+/** @suppress {globalThis} */ function readPointer(pointer) {
+ return this.fromWireType(HEAPU32[((pointer) >>> 2) >>> 0]);
+}
+
+var EmValType = {
+ name: "emscripten::val",
+ fromWireType: handle => {
+ var rv = Emval.toValue(handle);
+ __emval_decref(handle);
+ return rv;
+ },
+ toWireType: (destructors, value) => Emval.toHandle(value),
+ readValueFromPointer: readPointer,
+ destructorFunction: null
+};
+
+function __embind_register_emval(rawType) {
+ rawType >>>= 0;
+ return registerType(rawType, EmValType);
+}
+
+var floatReadValueFromPointer = (name, width) => {
+ switch (width) {
+ case 4:
+ return function(pointer) {
+ return this.fromWireType(HEAPF32[((pointer) >>> 2) >>> 0]);
+ };
+
+ case 8:
+ return function(pointer) {
+ return this.fromWireType(HEAPF64[((pointer) >>> 3) >>> 0]);
+ };
+
+ default:
+ throw new TypeError(`invalid float width (${width}): ${name}`);
+ }
+};
+
+var __embind_register_float = function(rawType, name, size) {
+ rawType >>>= 0;
+ name >>>= 0;
+ size >>>= 0;
+ name = AsciiToString(name);
+ registerType(rawType, {
+ name,
+ fromWireType: value => value,
+ toWireType: (destructors, value) => value,
+ readValueFromPointer: floatReadValueFromPointer(name, size),
+ destructorFunction: null
+ });
+};
+
+var createNamedFunction = (name, func) => Object.defineProperty(func, "name", {
+ value: name
+});
+
+var runDestructors = destructors => {
+ while (destructors.length) {
+ var ptr = destructors.pop();
+ var del = destructors.pop();
+ del(ptr);
+ }
+};
+
+function usesDestructorStack(argTypes) {
+ // Skip return value at index 0 - it's not deleted here.
+ for (var i = 1; i < argTypes.length; ++i) {
+ // The type does not define a destructor function - must use dynamic stack
+ if (argTypes[i] !== null && argTypes[i].destructorFunction === undefined) {
+ return true;
+ }
+ }
+ return false;
+}
+
+var runAndAbortIfError = func => {
+ try {
+ return func();
+ } catch (e) {
+ abort(e);
+ }
+};
+
+var runtimeKeepalivePush = () => {
+ runtimeKeepaliveCounter += 1;
+};
+
+var runtimeKeepalivePop = () => {
+ runtimeKeepaliveCounter -= 1;
+};
+
+var Asyncify = {
+ instrumentWasmImports(imports) {
+ var importPattern = /^(ReadBufferDataJs|WaitUntilCompletedJs|WaitUntilPipelineCreatedJs|invoke_.*|__asyncjs__.*)$/;
+ for (let [x, original] of Object.entries(imports)) {
+ if (typeof original == "function") {
+ let isAsyncifyImport = original.isAsync || importPattern.test(x);
+ }
+ }
+ },
+ instrumentFunction(original) {
+ var wrapper = (...args) => {
+ Asyncify.exportCallStack.push(original);
+ try {
+ return original(...args);
+ } finally {
+ if (!ABORT) {
+ var top = Asyncify.exportCallStack.pop();
+ Asyncify.maybeStopUnwind();
+ }
+ }
+ };
+ Asyncify.funcWrappers.set(original, wrapper);
+ return wrapper;
+ },
+ instrumentWasmExports(exports) {
+ var ret = {};
+ for (let [x, original] of Object.entries(exports)) {
+ if (typeof original == "function") {
+ var wrapper = Asyncify.instrumentFunction(original);
+ ret[x] = wrapper;
+ } else {
+ ret[x] = original;
+ }
+ }
+ return ret;
+ },
+ State: {
+ Normal: 0,
+ Unwinding: 1,
+ Rewinding: 2,
+ Disabled: 3
+ },
+ state: 0,
+ StackSize: 4096,
+ currData: null,
+ handleSleepReturnValue: 0,
+ exportCallStack: [],
+ callstackFuncToId: new Map,
+ callStackIdToFunc: new Map,
+ funcWrappers: new Map,
+ callStackId: 0,
+ asyncPromiseHandlers: null,
+ sleepCallbacks: [],
+ getCallStackId(func) {
+ if (!Asyncify.callstackFuncToId.has(func)) {
+ var id = Asyncify.callStackId++;
+ Asyncify.callstackFuncToId.set(func, id);
+ Asyncify.callStackIdToFunc.set(id, func);
+ }
+ return Asyncify.callstackFuncToId.get(func);
+ },
+ maybeStopUnwind() {
+ if (Asyncify.currData && Asyncify.state === Asyncify.State.Unwinding && Asyncify.exportCallStack.length === 0) {
+ // We just finished unwinding.
+ // Be sure to set the state before calling any other functions to avoid
+ // possible infinite recursion here (For example in debug pthread builds
+ // the dbg() function itself can call back into WebAssembly to get the
+ // current pthread_self() pointer).
+ Asyncify.state = Asyncify.State.Normal;
+ // Keep the runtime alive so that a re-wind can be done later.
+ runAndAbortIfError(_asyncify_stop_unwind);
+ if (typeof Fibers != "undefined") {
+ Fibers.trampoline();
+ }
+ }
+ },
+ whenDone() {
+ return new Promise((resolve, reject) => {
+ Asyncify.asyncPromiseHandlers = {
+ resolve,
+ reject
+ };
+ });
+ },
+ allocateData() {
+ // An asyncify data structure has three fields:
+ // 0 current stack pos
+ // 4 max stack pos
+ // 8 id of function at bottom of the call stack (callStackIdToFunc[id] == wasm func)
+ // The Asyncify ABI only interprets the first two fields, the rest is for the runtime.
+ // We also embed a stack in the same memory region here, right next to the structure.
+ // This struct is also defined as asyncify_data_t in emscripten/fiber.h
+ var ptr = _malloc(12 + Asyncify.StackSize);
+ Asyncify.setDataHeader(ptr, ptr + 12, Asyncify.StackSize);
+ Asyncify.setDataRewindFunc(ptr);
+ return ptr;
+ },
+ setDataHeader(ptr, stack, stackSize) {
+ HEAPU32[((ptr) >>> 2) >>> 0] = stack;
+ HEAPU32[(((ptr) + (4)) >>> 2) >>> 0] = stack + stackSize;
+ },
+ setDataRewindFunc(ptr) {
+ var bottomOfCallStack = Asyncify.exportCallStack[0];
+ var rewindId = Asyncify.getCallStackId(bottomOfCallStack);
+ HEAP32[(((ptr) + (8)) >>> 2) >>> 0] = rewindId;
+ },
+ getDataRewindFunc(ptr) {
+ var id = HEAP32[(((ptr) + (8)) >>> 2) >>> 0];
+ var func = Asyncify.callStackIdToFunc.get(id);
+ return func;
+ },
+ doRewind(ptr) {
+ var original = Asyncify.getDataRewindFunc(ptr);
+ var func = Asyncify.funcWrappers.get(original);
+ // Once we have rewound and the stack we no longer need to artificially
+ // keep the runtime alive.
+ return callUserCallback(func);
+ },
+ handleSleep(startAsync) {
+ if (ABORT) return;
+ if (Asyncify.state === Asyncify.State.Normal) {
+ // Prepare to sleep. Call startAsync, and see what happens:
+ // if the code decided to call our callback synchronously,
+ // then no async operation was in fact begun, and we don't
+ // need to do anything.
+ var reachedCallback = false;
+ var reachedAfterCallback = false;
+ startAsync((handleSleepReturnValue = 0) => {
+ if (ABORT) return;
+ Asyncify.handleSleepReturnValue = handleSleepReturnValue;
+ reachedCallback = true;
+ if (!reachedAfterCallback) {
+ // We are happening synchronously, so no need for async.
+ return;
+ }
+ Asyncify.state = Asyncify.State.Rewinding;
+ runAndAbortIfError(() => _asyncify_start_rewind(Asyncify.currData));
+ if (typeof MainLoop != "undefined" && MainLoop.func) {
+ MainLoop.resume();
+ }
+ var asyncWasmReturnValue, isError = false;
+ try {
+ asyncWasmReturnValue = Asyncify.doRewind(Asyncify.currData);
+ } catch (err) {
+ asyncWasmReturnValue = err;
+ isError = true;
+ }
+ // Track whether the return value was handled by any promise handlers.
+ var handled = false;
+ if (!Asyncify.currData) {
+ // All asynchronous execution has finished.
+ // `asyncWasmReturnValue` now contains the final
+ // return value of the exported async WASM function.
+ // Note: `asyncWasmReturnValue` is distinct from
+ // `Asyncify.handleSleepReturnValue`.
+ // `Asyncify.handleSleepReturnValue` contains the return
+ // value of the last C function to have executed
+ // `Asyncify.handleSleep()`, whereas `asyncWasmReturnValue`
+ // contains the return value of the exported WASM function
+ // that may have called C functions that
+ // call `Asyncify.handleSleep()`.
+ var asyncPromiseHandlers = Asyncify.asyncPromiseHandlers;
+ if (asyncPromiseHandlers) {
+ Asyncify.asyncPromiseHandlers = null;
+ (isError ? asyncPromiseHandlers.reject : asyncPromiseHandlers.resolve)(asyncWasmReturnValue);
+ handled = true;
+ }
+ }
+ if (isError && !handled) {
+ // If there was an error and it was not handled by now, we have no choice but to
+ // rethrow that error into the global scope where it can be caught only by
+ // `onerror` or `onunhandledpromiserejection`.
+ throw asyncWasmReturnValue;
+ }
+ });
+ reachedAfterCallback = true;
+ if (!reachedCallback) {
+ // A true async operation was begun; start a sleep.
+ Asyncify.state = Asyncify.State.Unwinding;
+ // TODO: reuse, don't alloc/free every sleep
+ Asyncify.currData = Asyncify.allocateData();
+ if (typeof MainLoop != "undefined" && MainLoop.func) {
+ MainLoop.pause();
+ }
+ runAndAbortIfError(() => _asyncify_start_unwind(Asyncify.currData));
+ }
+ } else if (Asyncify.state === Asyncify.State.Rewinding) {
+ // Stop a resume.
+ Asyncify.state = Asyncify.State.Normal;
+ runAndAbortIfError(_asyncify_stop_rewind);
+ _free(Asyncify.currData);
+ Asyncify.currData = null;
+ // Call all sleep callbacks now that the sleep-resume is all done.
+ Asyncify.sleepCallbacks.forEach(callUserCallback);
+ } else {
+ abort(`invalid state: ${Asyncify.state}`);
+ }
+ return Asyncify.handleSleepReturnValue;
+ },
+ handleAsync: startAsync => Asyncify.handleSleep(async wakeUp => {
+ // TODO: add error handling as a second param when handleSleep implements it.
+ wakeUp(await startAsync());
+ })
+};
+
+function craftInvokerFunction(humanName, argTypes, classType, cppInvokerFunc, cppTargetFunc, /** boolean= */ isAsync) {
+ // humanName: a human-readable string name for the function to be generated.
+ // argTypes: An array that contains the embind type objects for all types in the function signature.
+ // argTypes[0] is the type object for the function return value.
+ // argTypes[1] is the type object for function this object/class type, or null if not crafting an invoker for a class method.
+ // argTypes[2...] are the actual function parameters.
+ // classType: The embind type object for the class to be bound, or null if this is not a method of a class.
+ // cppInvokerFunc: JS Function object to the C++-side function that interops into C++ code.
+ // cppTargetFunc: Function pointer (an integer to FUNCTION_TABLE) to the target C++ function the cppInvokerFunc will end up calling.
+ // isAsync: Optional. If true, returns an async function. Async bindings are only supported with JSPI.
+ var argCount = argTypes.length;
+ if (argCount < 2) {
+ throwBindingError("argTypes array size mismatch! Must at least get return value and 'this' types!");
+ }
+ var isClassMethodFunc = (argTypes[1] !== null && classType !== null);
+ // Free functions with signature "void function()" do not need an invoker that marshalls between wire types.
+ // TODO: This omits argument count check - enable only at -O3 or similar.
+ // if (ENABLE_UNSAFE_OPTS && argCount == 2 && argTypes[0].name == "void" && !isClassMethodFunc) {
+ // return FUNCTION_TABLE[fn];
+ // }
+ // Determine if we need to use a dynamic stack to store the destructors for the function parameters.
+ // TODO: Remove this completely once all function invokers are being dynamically generated.
+ var needsDestructorStack = usesDestructorStack(argTypes);
+ var returns = !argTypes[0].isVoid;
+ var expectedArgCount = argCount - 2;
+ var argsWired = new Array(expectedArgCount);
+ var invokerFuncArgs = [];
+ var destructors = [];
+ var invokerFn = function(...args) {
+ destructors.length = 0;
+ var thisWired;
+ invokerFuncArgs.length = isClassMethodFunc ? 2 : 1;
+ invokerFuncArgs[0] = cppTargetFunc;
+ if (isClassMethodFunc) {
+ thisWired = argTypes[1].toWireType(destructors, this);
+ invokerFuncArgs[1] = thisWired;
+ }
+ for (var i = 0; i < expectedArgCount; ++i) {
+ argsWired[i] = argTypes[i + 2].toWireType(destructors, args[i]);
+ invokerFuncArgs.push(argsWired[i]);
+ }
+ var rv = cppInvokerFunc(...invokerFuncArgs);
+ function onDone(rv) {
+ if (needsDestructorStack) {
+ runDestructors(destructors);
+ } else {
+ for (var i = isClassMethodFunc ? 1 : 2; i < argTypes.length; i++) {
+ var param = i === 1 ? thisWired : argsWired[i - 2];
+ if (argTypes[i].destructorFunction !== null) {
+ argTypes[i].destructorFunction(param);
+ }
+ }
+ }
+ if (returns) {
+ return argTypes[0].fromWireType(rv);
+ }
+ }
+ if (Asyncify.currData) {
+ return Asyncify.whenDone().then(onDone);
+ }
+ return onDone(rv);
+ };
+ return createNamedFunction(humanName, invokerFn);
+}
+
+var ensureOverloadTable = (proto, methodName, humanName) => {
+ if (undefined === proto[methodName].overloadTable) {
+ var prevFunc = proto[methodName];
+ // Inject an overload resolver function that routes to the appropriate overload based on the number of arguments.
+ proto[methodName] = function(...args) {
+ // TODO This check can be removed in -O3 level "unsafe" optimizations.
+ if (!proto[methodName].overloadTable.hasOwnProperty(args.length)) {
+ throwBindingError(`Function '${humanName}' called with an invalid number of arguments (${args.length}) - expects one of (${proto[methodName].overloadTable})!`);
+ }
+ return proto[methodName].overloadTable[args.length].apply(this, args);
+ };
+ // Move the previous function into the overload table.
+ proto[methodName].overloadTable = [];
+ proto[methodName].overloadTable[prevFunc.argCount] = prevFunc;
+ }
+};
+
+/** @param {number=} numArguments */ var exposePublicSymbol = (name, value, numArguments) => {
+ if (Module.hasOwnProperty(name)) {
+ if (undefined === numArguments || (undefined !== Module[name].overloadTable && undefined !== Module[name].overloadTable[numArguments])) {
+ throwBindingError(`Cannot register public name '${name}' twice`);
+ }
+ // We are exposing a function with the same name as an existing function. Create an overload table and a function selector
+ // that routes between the two.
+ ensureOverloadTable(Module, name, name);
+ if (Module[name].overloadTable.hasOwnProperty(numArguments)) {
+ throwBindingError(`Cannot register multiple overloads of a function with the same number of arguments (${numArguments})!`);
+ }
+ // Add the new function into the overload table.
+ Module[name].overloadTable[numArguments] = value;
+ } else {
+ Module[name] = value;
+ Module[name].argCount = numArguments;
+ }
+};
+
+var heap32VectorToArray = (count, firstElement) => {
+ var array = [];
+ for (var i = 0; i < count; i++) {
+ // TODO(https://github.com/emscripten-core/emscripten/issues/17310):
+ // Find a way to hoist the `>> 2` or `>> 3` out of this loop.
+ array.push(HEAPU32[(((firstElement) + (i * 4)) >>> 2) >>> 0]);
+ }
+ return array;
+};
+
+var InternalError = class InternalError extends Error {
+ constructor(message) {
+ super(message);
+ this.name = "InternalError";
+ }
+};
+
+var throwInternalError = message => {
+ throw new InternalError(message);
+};
+
+/** @param {number=} numArguments */ var replacePublicSymbol = (name, value, numArguments) => {
+ if (!Module.hasOwnProperty(name)) {
+ throwInternalError("Replacing nonexistent public symbol");
+ }
+ // If there's an overload table for this symbol, replace the symbol in the overload table instead.
+ if (undefined !== Module[name].overloadTable && undefined !== numArguments) {
+ Module[name].overloadTable[numArguments] = value;
+ } else {
+ Module[name] = value;
+ Module[name].argCount = numArguments;
+ }
+};
+
+var getDynCaller = (sig, ptr, promising = false) => (...args) => dynCall(sig, ptr, args, promising);
+
+var embind__requireFunction = (signature, rawFunction, isAsync = false) => {
+ signature = AsciiToString(signature);
+ function makeDynCaller() {
+ return getDynCaller(signature, rawFunction);
+ }
+ var fp = makeDynCaller();
+ if (typeof fp != "function") {
+ throwBindingError(`unknown function pointer with signature ${signature}: ${rawFunction}`);
+ }
+ return fp;
+};
+
+class UnboundTypeError extends Error {}
+
+var getTypeName = type => {
+ var ptr = ___getTypeName(type);
+ var rv = AsciiToString(ptr);
+ _free(ptr);
+ return rv;
+};
+
+var throwUnboundTypeError = (message, types) => {
+ var unboundTypes = [];
+ var seen = {};
+ function visit(type) {
+ if (seen[type]) {
+ return;
+ }
+ if (registeredTypes[type]) {
+ return;
+ }
+ if (typeDependencies[type]) {
+ typeDependencies[type].forEach(visit);
+ return;
+ }
+ unboundTypes.push(type);
+ seen[type] = true;
+ }
+ types.forEach(visit);
+ throw new UnboundTypeError(`${message}: ` + unboundTypes.map(getTypeName).join([ ", " ]));
+};
+
+var whenDependentTypesAreResolved = (myTypes, dependentTypes, getTypeConverters) => {
+ myTypes.forEach(type => typeDependencies[type] = dependentTypes);
+ function onComplete(typeConverters) {
+ var myTypeConverters = getTypeConverters(typeConverters);
+ if (myTypeConverters.length !== myTypes.length) {
+ throwInternalError("Mismatched type converter count");
+ }
+ for (var i = 0; i < myTypes.length; ++i) {
+ registerType(myTypes[i], myTypeConverters[i]);
+ }
+ }
+ var typeConverters = new Array(dependentTypes.length);
+ var unregisteredTypes = [];
+ var registered = 0;
+ for (let [i, dt] of dependentTypes.entries()) {
+ if (registeredTypes.hasOwnProperty(dt)) {
+ typeConverters[i] = registeredTypes[dt];
+ } else {
+ unregisteredTypes.push(dt);
+ if (!awaitingDependencies.hasOwnProperty(dt)) {
+ awaitingDependencies[dt] = [];
+ }
+ awaitingDependencies[dt].push(() => {
+ typeConverters[i] = registeredTypes[dt];
+ ++registered;
+ if (registered === unregisteredTypes.length) {
+ onComplete(typeConverters);
+ }
+ });
+ }
+ }
+ if (0 === unregisteredTypes.length) {
+ onComplete(typeConverters);
+ }
+};
+
+var getFunctionName = signature => {
+ signature = signature.trim();
+ const argsIndex = signature.indexOf("(");
+ if (argsIndex === -1) return signature;
+ return signature.slice(0, argsIndex);
+};
+
+function __embind_register_function(name, argCount, rawArgTypesAddr, signature, rawInvoker, fn, isAsync, isNonnullReturn) {
+ name >>>= 0;
+ rawArgTypesAddr >>>= 0;
+ signature >>>= 0;
+ rawInvoker >>>= 0;
+ fn >>>= 0;
+ var argTypes = heap32VectorToArray(argCount, rawArgTypesAddr);
+ name = AsciiToString(name);
+ name = getFunctionName(name);
+ rawInvoker = embind__requireFunction(signature, rawInvoker, isAsync);
+ exposePublicSymbol(name, function() {
+ throwUnboundTypeError(`Cannot call ${name} due to unbound types`, argTypes);
+ }, argCount - 1);
+ whenDependentTypesAreResolved([], argTypes, argTypes => {
+ var invokerArgsArray = [ argTypes[0], null ].concat(argTypes.slice(1));
+ replacePublicSymbol(name, craftInvokerFunction(name, invokerArgsArray, null, rawInvoker, fn, isAsync), argCount - 1);
+ return [];
+ });
+}
+
+var integerReadValueFromPointer = (name, width, signed) => {
+ // integers are quite common, so generate very specialized functions
+ switch (width) {
+ case 1:
+ return signed ? pointer => HEAP8[pointer >>> 0] : pointer => HEAPU8[pointer >>> 0];
+
+ case 2:
+ return signed ? pointer => HEAP16[((pointer) >>> 1) >>> 0] : pointer => HEAPU16[((pointer) >>> 1) >>> 0];
+
+ case 4:
+ return signed ? pointer => HEAP32[((pointer) >>> 2) >>> 0] : pointer => HEAPU32[((pointer) >>> 2) >>> 0];
+
+ default:
+ throw new TypeError(`invalid integer width (${width}): ${name}`);
+ }
+};
+
+/** @suppress {globalThis} */ var __embind_register_integer = function(primitiveType, name, size, minRange, maxRange) {
+ primitiveType >>>= 0;
+ name >>>= 0;
+ size >>>= 0;
+ name = AsciiToString(name);
+ const isUnsignedType = minRange === 0;
+ let fromWireType = value => value;
+ if (isUnsignedType) {
+ var bitshift = 32 - 8 * size;
+ fromWireType = value => (value << bitshift) >>> bitshift;
+ maxRange = fromWireType(maxRange);
+ }
+ registerType(primitiveType, {
+ name,
+ fromWireType,
+ toWireType: (destructors, value) => value,
+ readValueFromPointer: integerReadValueFromPointer(name, size, minRange !== 0),
+ destructorFunction: null
+ });
+};
+
+function __embind_register_memory_view(rawType, dataTypeIndex, name) {
+ rawType >>>= 0;
+ name >>>= 0;
+ var typeMapping = [ Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array ];
+ var TA = typeMapping[dataTypeIndex];
+ function decodeMemoryView(handle) {
+ var size = HEAPU32[((handle) >>> 2) >>> 0];
+ var data = HEAPU32[(((handle) + (4)) >>> 2) >>> 0];
+ return new TA(HEAP8.buffer, data, size);
+ }
+ name = AsciiToString(name);
+ registerType(rawType, {
+ name,
+ fromWireType: decodeMemoryView,
+ readValueFromPointer: decodeMemoryView
+ }, {
+ ignoreDuplicateRegistrations: true
+ });
+}
+
+function __embind_register_std_string(rawType, name) {
+ rawType >>>= 0;
+ name >>>= 0;
+ name = AsciiToString(name);
+ var stdStringIsUTF8 = true;
+ registerType(rawType, {
+ name,
+ // For some method names we use string keys here since they are part of
+ // the public/external API and/or used by the runtime-generated code.
+ fromWireType(value) {
+ var length = HEAPU32[((value) >>> 2) >>> 0];
+ var payload = value + 4;
+ var str;
+ if (stdStringIsUTF8) {
+ str = UTF8ToString(payload, length, true);
+ } else {
+ str = "";
+ for (var i = 0; i < length; ++i) {
+ str += String.fromCharCode(HEAPU8[payload + i >>> 0]);
+ }
+ }
+ _free(value);
+ return str;
+ },
+ toWireType(destructors, value) {
+ if (value instanceof ArrayBuffer) {
+ value = new Uint8Array(value);
+ }
+ var length;
+ var valueIsOfTypeString = (typeof value == "string");
+ // We accept `string` or array views with single byte elements
+ if (!(valueIsOfTypeString || (ArrayBuffer.isView(value) && value.BYTES_PER_ELEMENT == 1))) {
+ throwBindingError("Cannot pass non-string to std::string");
+ }
+ if (stdStringIsUTF8 && valueIsOfTypeString) {
+ length = lengthBytesUTF8(value);
+ } else {
+ length = value.length;
+ }
+ // assumes POINTER_SIZE alignment
+ var base = _malloc(4 + length + 1);
+ var ptr = base + 4;
+ HEAPU32[((base) >>> 2) >>> 0] = length;
+ if (valueIsOfTypeString) {
+ if (stdStringIsUTF8) {
+ stringToUTF8(value, ptr, length + 1);
+ } else {
+ for (var i = 0; i < length; ++i) {
+ var charCode = value.charCodeAt(i);
+ if (charCode > 255) {
+ _free(base);
+ throwBindingError("String has UTF-16 code units that do not fit in 8 bits");
+ }
+ HEAPU8[ptr + i >>> 0] = charCode;
+ }
+ }
+ } else {
+ HEAPU8.set(value, ptr >>> 0);
+ }
+ if (destructors !== null) {
+ destructors.push(_free, base);
+ }
+ return base;
+ },
+ readValueFromPointer: readPointer,
+ destructorFunction(ptr) {
+ _free(ptr);
+ }
+ });
+}
+
+var UTF16Decoder = new TextDecoder("utf-16le");
+
+var UTF16ToString = (ptr, maxBytesToRead, ignoreNul) => {
+ var idx = ((ptr) >>> 1);
+ var endIdx = findStringEnd(HEAPU16, idx, maxBytesToRead / 2, ignoreNul);
+ return UTF16Decoder.decode(HEAPU16.subarray(idx >>> 0, endIdx >>> 0));
+};
+
+var stringToUTF16 = (str, outPtr, maxBytesToWrite) => {
+ // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed.
+ maxBytesToWrite ??= 2147483647;
+ if (maxBytesToWrite < 2) return 0;
+ maxBytesToWrite -= 2;
+ // Null terminator.
+ var startPtr = outPtr;
+ var numCharsToWrite = (maxBytesToWrite < str.length * 2) ? (maxBytesToWrite / 2) : str.length;
+ for (var i = 0; i < numCharsToWrite; ++i) {
+ // charCodeAt returns a UTF-16 encoded code unit, so it can be directly written to the HEAP.
+ var codeUnit = str.charCodeAt(i);
+ // possibly a lead surrogate
+ HEAP16[((outPtr) >>> 1) >>> 0] = codeUnit;
+ outPtr += 2;
+ }
+ // Null-terminate the pointer to the HEAP.
+ HEAP16[((outPtr) >>> 1) >>> 0] = 0;
+ return outPtr - startPtr;
+};
+
+var lengthBytesUTF16 = str => str.length * 2;
+
+var UTF32ToString = (ptr, maxBytesToRead, ignoreNul) => {
+ var str = "";
+ var startIdx = ((ptr) >>> 2);
+ // If maxBytesToRead is not passed explicitly, it will be undefined, and this
+ // will always evaluate to true. This saves on code size.
+ for (var i = 0; !(i >= maxBytesToRead / 4); i++) {
+ var utf32 = HEAPU32[startIdx + i >>> 0];
+ if (!utf32 && !ignoreNul) break;
+ str += String.fromCodePoint(utf32);
+ }
+ return str;
+};
+
+var stringToUTF32 = (str, outPtr, maxBytesToWrite) => {
+ outPtr >>>= 0;
+ // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed.
+ maxBytesToWrite ??= 2147483647;
+ if (maxBytesToWrite < 4) return 0;
+ var startPtr = outPtr;
+ var endPtr = startPtr + maxBytesToWrite - 4;
+ for (var i = 0; i < str.length; ++i) {
+ var codePoint = str.codePointAt(i);
+ // Gotcha: if codePoint is over 0xFFFF, it is represented as a surrogate pair in UTF-16.
+ // We need to manually skip over the second code unit for correct iteration.
+ if (codePoint > 65535) {
+ i++;
+ }
+ HEAP32[((outPtr) >>> 2) >>> 0] = codePoint;
+ outPtr += 4;
+ if (outPtr + 4 > endPtr) break;
+ }
+ // Null-terminate the pointer to the HEAP.
+ HEAP32[((outPtr) >>> 2) >>> 0] = 0;
+ return outPtr - startPtr;
+};
+
+var lengthBytesUTF32 = str => {
+ var len = 0;
+ for (var i = 0; i < str.length; ++i) {
+ var codePoint = str.codePointAt(i);
+ // Gotcha: if codePoint is over 0xFFFF, it is represented as a surrogate pair in UTF-16.
+ // We need to manually skip over the second code unit for correct iteration.
+ if (codePoint > 65535) {
+ i++;
+ }
+ len += 4;
+ }
+ return len;
+};
+
+function __embind_register_std_wstring(rawType, charSize, name) {
+ rawType >>>= 0;
+ charSize >>>= 0;
+ name >>>= 0;
+ name = AsciiToString(name);
+ var decodeString, encodeString, lengthBytesUTF;
+ if (charSize === 2) {
+ decodeString = UTF16ToString;
+ encodeString = stringToUTF16;
+ lengthBytesUTF = lengthBytesUTF16;
+ } else {
+ decodeString = UTF32ToString;
+ encodeString = stringToUTF32;
+ lengthBytesUTF = lengthBytesUTF32;
+ }
+ registerType(rawType, {
+ name,
+ fromWireType: value => {
+ // Code mostly taken from _embind_register_std_string fromWireType
+ var length = HEAPU32[((value) >>> 2) >>> 0];
+ var str = decodeString(value + 4, length * charSize, true);
+ _free(value);
+ return str;
+ },
+ toWireType: (destructors, value) => {
+ if (!(typeof value == "string")) {
+ throwBindingError(`Cannot pass non-string to C++ string type ${name}`);
+ }
+ // assumes POINTER_SIZE alignment
+ var length = lengthBytesUTF(value);
+ var ptr = _malloc(4 + length + charSize);
+ HEAPU32[((ptr) >>> 2) >>> 0] = length / charSize;
+ encodeString(value, ptr + 4, length + charSize);
+ if (destructors !== null) {
+ destructors.push(_free, ptr);
+ }
+ return ptr;
+ },
+ readValueFromPointer: readPointer,
+ destructorFunction(ptr) {
+ _free(ptr);
+ }
+ });
+}
+
+var __embind_register_void = function(rawType, name) {
+ rawType >>>= 0;
+ name >>>= 0;
+ name = AsciiToString(name);
+ registerType(rawType, {
+ isVoid: true,
+ // void return values can be optimized out sometimes
+ name,
+ fromWireType: () => undefined,
+ // TODO: assert if anything else is given?
+ toWireType: (destructors, o) => undefined
+ });
+};
+
+var emval_methodCallers = [];
+
+var emval_addMethodCaller = caller => {
+ var id = emval_methodCallers.length;
+ emval_methodCallers.push(caller);
+ return id;
+};
+
+var requireRegisteredType = (rawType, humanName) => {
+ var impl = registeredTypes[rawType];
+ if (undefined === impl) {
+ throwBindingError(`${humanName} has unknown type ${getTypeName(rawType)}`);
+ }
+ return impl;
+};
+
+var emval_lookupTypes = (argCount, argTypes) => {
+ var a = new Array(argCount);
+ for (var i = 0; i < argCount; ++i) {
+ a[i] = requireRegisteredType(HEAPU32[(((argTypes) + (i * 4)) >>> 2) >>> 0], `parameter ${i}`);
+ }
+ return a;
+};
+
+var emval_returnValue = (toReturnWire, destructorsRef, handle) => {
+ var destructors = [];
+ var result = toReturnWire(destructors, handle);
+ if (destructors.length) {
+ // void, primitives and any other types w/o destructors don't need to allocate a handle
+ HEAPU32[((destructorsRef) >>> 2) >>> 0] = Emval.toHandle(destructors);
+ }
+ return result;
+};
+
+var emval_symbols = {};
+
+var getStringOrSymbol = address => {
+ var symbol = emval_symbols[address];
+ if (symbol === undefined) {
+ return AsciiToString(address);
+ }
+ return symbol;
+};
+
+var __emval_create_invoker = function(argCount, argTypesPtr, kind) {
+ argTypesPtr >>>= 0;
+ var GenericWireTypeSize = 8;
+ var [retType, ...argTypes] = emval_lookupTypes(argCount, argTypesPtr);
+ var toReturnWire = retType.toWireType.bind(retType);
+ var argFromPtr = argTypes.map(type => type.readValueFromPointer.bind(type));
+ argCount--;
+ // remove the extracted return type
+ var argN = new Array(argCount);
+ var invokerFunction = (handle, methodName, destructorsRef, args) => {
+ var offset = 0;
+ for (var i = 0; i < argCount; ++i) {
+ argN[i] = argFromPtr[i](args + offset);
+ offset += GenericWireTypeSize;
+ }
+ var rv;
+ switch (kind) {
+ case 0:
+ rv = Emval.toValue(handle).apply(null, argN);
+ break;
+
+ case 2:
+ rv = Reflect.construct(Emval.toValue(handle), argN);
+ break;
+
+ case 3:
+ // no-op, just return the argument
+ rv = argN[0];
+ break;
+
+ case 1:
+ rv = Emval.toValue(handle)[getStringOrSymbol(methodName)](...argN);
+ break;
+ }
+ return emval_returnValue(toReturnWire, destructorsRef, rv);
+ };
+ var functionName = `methodCaller<(${argTypes.map(t => t.name)}) => ${retType.name}>`;
+ return emval_addMethodCaller(createNamedFunction(functionName, invokerFunction));
+};
+
+function __emval_incref(handle) {
+ handle >>>= 0;
+ if (handle > 9) {
+ emval_handles[handle + 1] += 1;
+ }
+}
+
+function __emval_invoke(caller, handle, methodName, destructorsRef, args) {
+ caller >>>= 0;
+ handle >>>= 0;
+ methodName >>>= 0;
+ destructorsRef >>>= 0;
+ args >>>= 0;
+ return emval_methodCallers[caller](handle, methodName, destructorsRef, args);
+}
+
+function __emval_run_destructors(handle) {
+ handle >>>= 0;
+ var destructors = Emval.toValue(handle);
+ runDestructors(destructors);
+ __emval_decref(handle);
+}
+
+function __gmtime_js(time_low, time_high, tmPtr) {
+ var time = convertI32PairToI53Checked(time_low, time_high);
+ tmPtr >>>= 0;
+ var date = new Date(time * 1e3);
+ HEAP32[((tmPtr) >>> 2) >>> 0] = date.getUTCSeconds();
+ HEAP32[(((tmPtr) + (4)) >>> 2) >>> 0] = date.getUTCMinutes();
+ HEAP32[(((tmPtr) + (8)) >>> 2) >>> 0] = date.getUTCHours();
+ HEAP32[(((tmPtr) + (12)) >>> 2) >>> 0] = date.getUTCDate();
+ HEAP32[(((tmPtr) + (16)) >>> 2) >>> 0] = date.getUTCMonth();
+ HEAP32[(((tmPtr) + (20)) >>> 2) >>> 0] = date.getUTCFullYear() - 1900;
+ HEAP32[(((tmPtr) + (24)) >>> 2) >>> 0] = date.getUTCDay();
+ var start = Date.UTC(date.getUTCFullYear(), 0, 1, 0, 0, 0, 0);
+ var yday = ((date.getTime() - start) / (1e3 * 60 * 60 * 24)) | 0;
+ HEAP32[(((tmPtr) + (28)) >>> 2) >>> 0] = yday;
+}
+
+var isLeapYear = year => year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
+
+var MONTH_DAYS_LEAP_CUMULATIVE = [ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 ];
+
+var MONTH_DAYS_REGULAR_CUMULATIVE = [ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 ];
+
+var ydayFromDate = date => {
+ var leap = isLeapYear(date.getFullYear());
+ var monthDaysCumulative = (leap ? MONTH_DAYS_LEAP_CUMULATIVE : MONTH_DAYS_REGULAR_CUMULATIVE);
+ var yday = monthDaysCumulative[date.getMonth()] + date.getDate() - 1;
+ // -1 since it's days since Jan 1
+ return yday;
+};
+
+function __localtime_js(time_low, time_high, tmPtr) {
+ var time = convertI32PairToI53Checked(time_low, time_high);
+ tmPtr >>>= 0;
+ var date = new Date(time * 1e3);
+ HEAP32[((tmPtr) >>> 2) >>> 0] = date.getSeconds();
+ HEAP32[(((tmPtr) + (4)) >>> 2) >>> 0] = date.getMinutes();
+ HEAP32[(((tmPtr) + (8)) >>> 2) >>> 0] = date.getHours();
+ HEAP32[(((tmPtr) + (12)) >>> 2) >>> 0] = date.getDate();
+ HEAP32[(((tmPtr) + (16)) >>> 2) >>> 0] = date.getMonth();
+ HEAP32[(((tmPtr) + (20)) >>> 2) >>> 0] = date.getFullYear() - 1900;
+ HEAP32[(((tmPtr) + (24)) >>> 2) >>> 0] = date.getDay();
+ var yday = ydayFromDate(date) | 0;
+ HEAP32[(((tmPtr) + (28)) >>> 2) >>> 0] = yday;
+ HEAP32[(((tmPtr) + (36)) >>> 2) >>> 0] = -(date.getTimezoneOffset() * 60);
+ // Attention: DST is in December in South, and some regions don't have DST at all.
+ var start = new Date(date.getFullYear(), 0, 1);
+ var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset();
+ var winterOffset = start.getTimezoneOffset();
+ var dst = (summerOffset != winterOffset && date.getTimezoneOffset() == Math.min(winterOffset, summerOffset)) | 0;
+ HEAP32[(((tmPtr) + (32)) >>> 2) >>> 0] = dst;
+}
+
+var setTempRet0 = val => __emscripten_tempret_set(val);
+
+var __mktime_js = function(tmPtr) {
+ tmPtr >>>= 0;
+ var ret = (() => {
+ var date = new Date(HEAP32[(((tmPtr) + (20)) >>> 2) >>> 0] + 1900, HEAP32[(((tmPtr) + (16)) >>> 2) >>> 0], HEAP32[(((tmPtr) + (12)) >>> 2) >>> 0], HEAP32[(((tmPtr) + (8)) >>> 2) >>> 0], HEAP32[(((tmPtr) + (4)) >>> 2) >>> 0], HEAP32[((tmPtr) >>> 2) >>> 0], 0);
+ // There's an ambiguous hour when the time goes back; the tm_isdst field is
+ // used to disambiguate it. Date() basically guesses, so we fix it up if it
+ // guessed wrong, or fill in tm_isdst with the guess if it's -1.
+ var dst = HEAP32[(((tmPtr) + (32)) >>> 2) >>> 0];
+ var guessedOffset = date.getTimezoneOffset();
+ var start = new Date(date.getFullYear(), 0, 1);
+ var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset();
+ var winterOffset = start.getTimezoneOffset();
+ var dstOffset = Math.min(winterOffset, summerOffset);
+ // DST is in December in South
+ if (dst < 0) {
+ // Attention: some regions don't have DST at all.
+ HEAP32[(((tmPtr) + (32)) >>> 2) >>> 0] = Number(summerOffset != winterOffset && dstOffset == guessedOffset);
+ } else if ((dst > 0) != (dstOffset == guessedOffset)) {
+ var nonDstOffset = Math.max(winterOffset, summerOffset);
+ var trueOffset = dst > 0 ? dstOffset : nonDstOffset;
+ // Don't try setMinutes(date.getMinutes() + ...) -- it's messed up.
+ date.setTime(date.getTime() + (trueOffset - guessedOffset) * 6e4);
+ }
+ HEAP32[(((tmPtr) + (24)) >>> 2) >>> 0] = date.getDay();
+ var yday = ydayFromDate(date) | 0;
+ HEAP32[(((tmPtr) + (28)) >>> 2) >>> 0] = yday;
+ // To match expected behavior, update fields from date
+ HEAP32[((tmPtr) >>> 2) >>> 0] = date.getSeconds();
+ HEAP32[(((tmPtr) + (4)) >>> 2) >>> 0] = date.getMinutes();
+ HEAP32[(((tmPtr) + (8)) >>> 2) >>> 0] = date.getHours();
+ HEAP32[(((tmPtr) + (12)) >>> 2) >>> 0] = date.getDate();
+ HEAP32[(((tmPtr) + (16)) >>> 2) >>> 0] = date.getMonth();
+ HEAP32[(((tmPtr) + (20)) >>> 2) >>> 0] = date.getYear();
+ var timeMs = date.getTime();
+ if (isNaN(timeMs)) {
+ return -1;
+ }
+ // Return time in microseconds
+ return timeMs / 1e3;
+ })();
+ return (setTempRet0((tempDouble = ret, (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0)),
+ ret >>> 0);
+};
+
+function __mmap_js(len, prot, flags, fd, offset_low, offset_high, allocated, addr) {
+ len >>>= 0;
+ var offset = convertI32PairToI53Checked(offset_low, offset_high);
+ allocated >>>= 0;
+ addr >>>= 0;
+ try {
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ var res = FS.mmap(stream, len, offset, prot, flags);
+ var ptr = res.ptr;
+ HEAP32[((allocated) >>> 2) >>> 0] = res.allocated;
+ HEAPU32[((addr) >>> 2) >>> 0] = ptr;
+ return 0;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+function __munmap_js(addr, len, prot, flags, fd, offset_low, offset_high) {
+ addr >>>= 0;
+ len >>>= 0;
+ var offset = convertI32PairToI53Checked(offset_low, offset_high);
+ try {
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ if (prot & 2) {
+ SYSCALLS.doMsync(addr, stream, len, flags, offset);
+ }
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return -e.errno;
+ }
+}
+
+var __tzset_js = function(timezone, daylight, std_name, dst_name) {
+ timezone >>>= 0;
+ daylight >>>= 0;
+ std_name >>>= 0;
+ dst_name >>>= 0;
+ // TODO: Use (malleable) environment variables instead of system settings.
+ var currentYear = (new Date).getFullYear();
+ var winter = new Date(currentYear, 0, 1);
+ var summer = new Date(currentYear, 6, 1);
+ var winterOffset = winter.getTimezoneOffset();
+ var summerOffset = summer.getTimezoneOffset();
+ // Local standard timezone offset. Local standard time is not adjusted for
+ // daylight savings. This code uses the fact that getTimezoneOffset returns
+ // a greater value during Standard Time versus Daylight Saving Time (DST).
+ // Thus it determines the expected output during Standard Time, and it
+ // compares whether the output of the given date the same (Standard) or less
+ // (DST).
+ var stdTimezoneOffset = Math.max(winterOffset, summerOffset);
+ // timezone is specified as seconds west of UTC ("The external variable
+ // `timezone` shall be set to the difference, in seconds, between
+ // Coordinated Universal Time (UTC) and local standard time."), the same
+ // as returned by stdTimezoneOffset.
+ // See http://pubs.opengroup.org/onlinepubs/009695399/functions/tzset.html
+ HEAPU32[((timezone) >>> 2) >>> 0] = stdTimezoneOffset * 60;
+ HEAP32[((daylight) >>> 2) >>> 0] = Number(winterOffset != summerOffset);
+ var extractZone = timezoneOffset => {
+ // Why inverse sign?
+ // Read here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset
+ var sign = timezoneOffset >= 0 ? "-" : "+";
+ var absOffset = Math.abs(timezoneOffset);
+ var hours = String(Math.floor(absOffset / 60)).padStart(2, "0");
+ var minutes = String(absOffset % 60).padStart(2, "0");
+ return `UTC${sign}${hours}${minutes}`;
+ };
+ var winterName = extractZone(winterOffset);
+ var summerName = extractZone(summerOffset);
+ if (summerOffset < winterOffset) {
+ // Northern hemisphere
+ stringToUTF8(winterName, std_name, 17);
+ stringToUTF8(summerName, dst_name, 17);
+ } else {
+ stringToUTF8(winterName, dst_name, 17);
+ stringToUTF8(summerName, std_name, 17);
+ }
+};
+
+var _emscripten_get_now = () => performance.now();
+
+var _emscripten_date_now = () => Date.now();
+
+var nowIsMonotonic = 1;
+
+var checkWasiClock = clock_id => clock_id >= 0 && clock_id <= 3;
+
+function _clock_time_get(clk_id, ignored_precision_low, ignored_precision_high, ptime) {
+ var ignored_precision = convertI32PairToI53Checked(ignored_precision_low, ignored_precision_high);
+ ptime >>>= 0;
+ if (!checkWasiClock(clk_id)) {
+ return 28;
+ }
+ var now;
+ // all wasi clocks but realtime are monotonic
+ if (clk_id === 0) {
+ now = _emscripten_date_now();
+ } else if (nowIsMonotonic) {
+ now = _emscripten_get_now();
+ } else {
+ return 52;
+ }
+ // "now" is in ms, and wasi times are in ns.
+ var nsec = Math.round(now * 1e3 * 1e3);
+ (tempI64 = [ nsec >>> 0, (tempDouble = nsec, (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0) ],
+ HEAP32[((ptime) >>> 2) >>> 0] = tempI64[0], HEAP32[(((ptime) + (4)) >>> 2) >>> 0] = tempI64[1]);
+ return 0;
+}
+
+var readEmAsmArgsArray = [];
+
+var readEmAsmArgs = (sigPtr, buf) => {
+ readEmAsmArgsArray.length = 0;
+ var ch;
+ // Most arguments are i32s, so shift the buffer pointer so it is a plain
+ // index into HEAP32.
+ while (ch = HEAPU8[sigPtr++ >>> 0]) {
+ // Floats are always passed as doubles, so all types except for 'i'
+ // are 8 bytes and require alignment.
+ var wide = (ch != 105);
+ wide &= (ch != 112);
+ buf += wide && (buf % 8) ? 4 : 0;
+ readEmAsmArgsArray.push(// Special case for pointers under wasm64 or CAN_ADDRESS_2GB mode.
+ ch == 112 ? HEAPU32[((buf) >>> 2) >>> 0] : ch == 105 ? HEAP32[((buf) >>> 2) >>> 0] : HEAPF64[((buf) >>> 3) >>> 0]);
+ buf += wide ? 8 : 4;
+ }
+ return readEmAsmArgsArray;
+};
+
+var runEmAsmFunction = (code, sigPtr, argbuf) => {
+ var args = readEmAsmArgs(sigPtr, argbuf);
+ return ASM_CONSTS[code](...args);
+};
+
+function _emscripten_asm_const_int(code, sigPtr, argbuf) {
+ code >>>= 0;
+ sigPtr >>>= 0;
+ argbuf >>>= 0;
+ return runEmAsmFunction(code, sigPtr, argbuf);
+}
+
+function _emscripten_errn(str, len) {
+ str >>>= 0;
+ len >>>= 0;
+ return err(UTF8ToString(str, len));
+}
+
+var getHeapMax = () => // Stay one Wasm page short of 4GB: while e.g. Chrome is able to allocate
+// full 4GB Wasm memories, the size will wrap back to 0 bytes in Wasm side
+// for any code that deals with heap sizes, which would require special
+// casing all heap size related code to treat 0 specially.
+4294901760;
+
+function _emscripten_get_heap_max() {
+ return getHeapMax();
+}
+
+var _emscripten_has_asyncify = () => 1;
+
+function _emscripten_outn(str, len) {
+ str >>>= 0;
+ len >>>= 0;
+ return out(UTF8ToString(str, len));
+}
+
+var UNWIND_CACHE = {};
+
+var stringToNewUTF8 = str => {
+ var size = lengthBytesUTF8(str) + 1;
+ var ret = _malloc(size);
+ if (ret) stringToUTF8(str, ret, size);
+ return ret;
+};
+
+/** @returns {number} */ var convertFrameToPC = frame => {
+ var match;
+ if (match = /\bwasm-function\[\d+\]:(0x[0-9a-f]+)/.exec(frame)) {
+ // Wasm engines give the binary offset directly, so we use that as return address
+ return +match[1];
+ } else if (match = /:(\d+):\d+(?:\)|$)/.exec(frame)) {
+ // If we are in js, we can use the js line number as the "return address".
+ // This should work for wasm2js. We tag the high bit to distinguish this
+ // from wasm addresses.
+ return 2147483648 | +match[1];
+ }
+ // return 0 if we can't find any
+ return 0;
+};
+
+var saveInUnwindCache = callstack => {
+ for (var line of callstack) {
+ var pc = convertFrameToPC(line);
+ if (pc) {
+ UNWIND_CACHE[pc] = line;
+ }
+ }
+};
+
+var jsStackTrace = () => (new Error).stack.toString();
+
+function _emscripten_stack_snapshot() {
+ var callstack = jsStackTrace().split("\n");
+ if (callstack[0] == "Error") {
+ callstack.shift();
+ }
+ saveInUnwindCache(callstack);
+ // Caches the stack snapshot so that emscripten_stack_unwind_buffer() can
+ // unwind from this spot.
+ UNWIND_CACHE.last_addr = convertFrameToPC(callstack[3]);
+ UNWIND_CACHE.last_stack = callstack;
+ return UNWIND_CACHE.last_addr;
+}
+
+function _emscripten_pc_get_function(pc) {
+ pc >>>= 0;
+ var frame = UNWIND_CACHE[pc];
+ if (!frame) return 0;
+ var name;
+ var match;
+ // First try to match foo.wasm.sym files explcitly. e.g.
+ // at test_return_address.wasm.main (wasm://wasm/test_return_address.wasm-0012cc2a:wasm-function[26]:0x9f3
+ // Then match JS symbols which don't include that module name:
+ // at invokeEntryPoint (.../test_return_address.js:1500:42)
+ // Finally match firefox format:
+ // Object._main@http://server.com:4324:12'
+ if (match = /^\s+at .*\.wasm\.(.*) \(.*\)$/.exec(frame)) {
+ name = match[1];
+ } else if (match = /^\s+at (.*) \(.*\)$/.exec(frame)) {
+ name = match[1];
+ } else if (match = /^(.+?)@/.exec(frame)) {
+ name = match[1];
+ } else {
+ return 0;
+ }
+ _free(_emscripten_pc_get_function.ret ?? 0);
+ _emscripten_pc_get_function.ret = stringToNewUTF8(name);
+ return _emscripten_pc_get_function.ret;
+}
+
+var growMemory = size => {
+ var oldHeapSize = wasmMemory.buffer.byteLength;
+ var pages = ((size - oldHeapSize + 65535) / 65536) | 0;
+ try {
+ // round size grow request up to wasm page size (fixed 64KB per spec)
+ wasmMemory.grow(pages);
+ // .grow() takes a delta compared to the previous size
+ updateMemoryViews();
+ return 1;
+ } catch (e) {}
+};
+
+function _emscripten_resize_heap(requestedSize) {
+ requestedSize >>>= 0;
+ var oldSize = HEAPU8.length;
+ // With multithreaded builds, races can happen (another thread might increase the size
+ // in between), so return a failure, and let the caller retry.
+ // Memory resize rules:
+ // 1. Always increase heap size to at least the requested size, rounded up
+ // to next page multiple.
+ // 2a. If MEMORY_GROWTH_LINEAR_STEP == -1, excessively resize the heap
+ // geometrically: increase the heap size according to
+ // MEMORY_GROWTH_GEOMETRIC_STEP factor (default +20%), At most
+ // overreserve by MEMORY_GROWTH_GEOMETRIC_CAP bytes (default 96MB).
+ // 2b. If MEMORY_GROWTH_LINEAR_STEP != -1, excessively resize the heap
+ // linearly: increase the heap size by at least
+ // MEMORY_GROWTH_LINEAR_STEP bytes.
+ // 3. Max size for the heap is capped at 2048MB-WASM_PAGE_SIZE, or by
+ // MAXIMUM_MEMORY, or by ASAN limit, depending on which is smallest
+ // 4. If we were unable to allocate as much memory, it may be due to
+ // over-eager decision to excessively reserve due to (3) above.
+ // Hence if an allocation fails, cut down on the amount of excess
+ // growth, in an attempt to succeed to perform a smaller allocation.
+ // A limit is set for how much we can grow. We should not exceed that
+ // (the wasm binary specifies it, so if we tried, we'd fail anyhow).
+ var maxHeapSize = getHeapMax();
+ if (requestedSize > maxHeapSize) {
+ return false;
+ }
+ // Loop through potential heap size increases. If we attempt a too eager
+ // reservation that fails, cut down on the attempted size and reserve a
+ // smaller bump instead. (max 3 times, chosen somewhat arbitrarily)
+ for (var cutDown = 1; cutDown <= 4; cutDown *= 2) {
+ var overGrownHeapSize = oldSize * (1 + .2 / cutDown);
+ // ensure geometric growth
+ // but limit overreserving (default to capping at +96MB overgrowth at most)
+ overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296);
+ var newSize = Math.min(maxHeapSize, alignMemory(Math.max(requestedSize, overGrownHeapSize), 65536));
+ var replacement = growMemory(newSize);
+ if (replacement) {
+ return true;
+ }
+ }
+ return false;
+}
+
+function _emscripten_stack_unwind_buffer(addr, buffer, count) {
+ addr >>>= 0;
+ buffer >>>= 0;
+ var stack;
+ if (UNWIND_CACHE.last_addr == addr) {
+ stack = UNWIND_CACHE.last_stack;
+ } else {
+ stack = jsStackTrace().split("\n");
+ if (stack[0] == "Error") {
+ stack.shift();
+ }
+ saveInUnwindCache(stack);
+ }
+ var offset = 3;
+ while (stack[offset] && convertFrameToPC(stack[offset]) != addr) {
+ ++offset;
+ }
+ for (var i = 0; i < count && stack[i + offset]; ++i) {
+ HEAP32[(((buffer) + (i * 4)) >>> 2) >>> 0] = convertFrameToPC(stack[i + offset]);
+ }
+ return i;
+}
+
+var GLctx;
+
+var webgl_enable_ANGLE_instanced_arrays = ctx => {
+ // Extension available in WebGL 1 from Firefox 26 and Google Chrome 30 onwards. Core feature in WebGL 2.
+ var ext = ctx.getExtension("ANGLE_instanced_arrays");
+ // Because this extension is a core function in WebGL 2, assign the extension entry points in place of
+ // where the core functions will reside in WebGL 2. This way the calling code can call these without
+ // having to dynamically branch depending if running against WebGL 1 or WebGL 2.
+ if (ext) {
+ ctx["vertexAttribDivisor"] = (index, divisor) => ext["vertexAttribDivisorANGLE"](index, divisor);
+ ctx["drawArraysInstanced"] = (mode, first, count, primcount) => ext["drawArraysInstancedANGLE"](mode, first, count, primcount);
+ ctx["drawElementsInstanced"] = (mode, count, type, indices, primcount) => ext["drawElementsInstancedANGLE"](mode, count, type, indices, primcount);
+ return 1;
+ }
+};
+
+var webgl_enable_OES_vertex_array_object = ctx => {
+ // Extension available in WebGL 1 from Firefox 25 and WebKit 536.28/desktop Safari 6.0.3 onwards. Core feature in WebGL 2.
+ var ext = ctx.getExtension("OES_vertex_array_object");
+ if (ext) {
+ ctx["createVertexArray"] = () => ext["createVertexArrayOES"]();
+ ctx["deleteVertexArray"] = vao => ext["deleteVertexArrayOES"](vao);
+ ctx["bindVertexArray"] = vao => ext["bindVertexArrayOES"](vao);
+ ctx["isVertexArray"] = vao => ext["isVertexArrayOES"](vao);
+ return 1;
+ }
+};
+
+var webgl_enable_WEBGL_draw_buffers = ctx => {
+ // Extension available in WebGL 1 from Firefox 28 onwards. Core feature in WebGL 2.
+ var ext = ctx.getExtension("WEBGL_draw_buffers");
+ if (ext) {
+ ctx["drawBuffers"] = (n, bufs) => ext["drawBuffersWEBGL"](n, bufs);
+ return 1;
+ }
+};
+
+var webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance = ctx => // Closure is expected to be allowed to minify the '.dibvbi' property, so not accessing it quoted.
+!!(ctx.dibvbi = ctx.getExtension("WEBGL_draw_instanced_base_vertex_base_instance"));
+
+var webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance = ctx => !!(ctx.mdibvbi = ctx.getExtension("WEBGL_multi_draw_instanced_base_vertex_base_instance"));
+
+var webgl_enable_EXT_polygon_offset_clamp = ctx => !!(ctx.extPolygonOffsetClamp = ctx.getExtension("EXT_polygon_offset_clamp"));
+
+var webgl_enable_EXT_clip_control = ctx => !!(ctx.extClipControl = ctx.getExtension("EXT_clip_control"));
+
+var webgl_enable_WEBGL_polygon_mode = ctx => !!(ctx.webglPolygonMode = ctx.getExtension("WEBGL_polygon_mode"));
+
+var webgl_enable_WEBGL_multi_draw = ctx => // Closure is expected to be allowed to minify the '.multiDrawWebgl' property, so not accessing it quoted.
+!!(ctx.multiDrawWebgl = ctx.getExtension("WEBGL_multi_draw"));
+
+var getEmscriptenSupportedExtensions = ctx => {
+ // Restrict the list of advertised extensions to those that we actually
+ // support.
+ var supportedExtensions = [ // WebGL 1 extensions
+ "ANGLE_instanced_arrays", "EXT_blend_minmax", "EXT_disjoint_timer_query", "EXT_frag_depth", "EXT_shader_texture_lod", "EXT_sRGB", "OES_element_index_uint", "OES_fbo_render_mipmap", "OES_standard_derivatives", "OES_texture_float", "OES_texture_half_float", "OES_texture_half_float_linear", "OES_vertex_array_object", "WEBGL_color_buffer_float", "WEBGL_depth_texture", "WEBGL_draw_buffers", // WebGL 2 extensions
+ "EXT_color_buffer_float", "EXT_conservative_depth", "EXT_disjoint_timer_query_webgl2", "EXT_texture_norm16", "NV_shader_noperspective_interpolation", "WEBGL_clip_cull_distance", // WebGL 1 and WebGL 2 extensions
+ "EXT_clip_control", "EXT_color_buffer_half_float", "EXT_depth_clamp", "EXT_float_blend", "EXT_polygon_offset_clamp", "EXT_texture_compression_bptc", "EXT_texture_compression_rgtc", "EXT_texture_filter_anisotropic", "KHR_parallel_shader_compile", "OES_texture_float_linear", "WEBGL_blend_func_extended", "WEBGL_compressed_texture_astc", "WEBGL_compressed_texture_etc", "WEBGL_compressed_texture_etc1", "WEBGL_compressed_texture_s3tc", "WEBGL_compressed_texture_s3tc_srgb", "WEBGL_debug_renderer_info", "WEBGL_debug_shaders", "WEBGL_lose_context", "WEBGL_multi_draw", "WEBGL_polygon_mode" ];
+ // .getSupportedExtensions() can return null if context is lost, so coerce to empty array.
+ return (ctx.getSupportedExtensions() || []).filter(ext => supportedExtensions.includes(ext));
+};
+
+var registerPreMainLoop = f => {
+ // Does nothing unless $MainLoop is included/used.
+ typeof MainLoop != "undefined" && MainLoop.preMainLoop.push(f);
+};
+
+var GL = {
+ counter: 1,
+ buffers: [],
+ mappedBuffers: {},
+ programs: [],
+ framebuffers: [],
+ renderbuffers: [],
+ textures: [],
+ shaders: [],
+ vaos: [],
+ contexts: [],
+ offscreenCanvases: {},
+ queries: [],
+ samplers: [],
+ transformFeedbacks: [],
+ syncs: [],
+ byteSizeByTypeRoot: 5120,
+ byteSizeByType: [ 1, 1, 2, 2, 4, 4, 4, 2, 3, 4, 8 ],
+ stringCache: {},
+ stringiCache: {},
+ unpackAlignment: 4,
+ unpackRowLength: 0,
+ recordError: errorCode => {
+ if (!GL.lastError) {
+ GL.lastError = errorCode;
+ }
+ },
+ getNewId: table => {
+ var ret = GL.counter++;
+ for (var i = table.length; i < ret; i++) {
+ table[i] = null;
+ }
+ // Skip over any non-null elements that might have been created by
+ // glBindBuffer.
+ while (table[ret]) {
+ ret = GL.counter++;
+ }
+ return ret;
+ },
+ genObject: (n, buffers, createFunction, objectTable) => {
+ for (var i = 0; i < n; i++) {
+ var buffer = GLctx[createFunction]();
+ var id = buffer && GL.getNewId(objectTable);
+ if (buffer) {
+ buffer.name = id;
+ objectTable[id] = buffer;
+ } else {
+ GL.recordError(1282);
+ }
+ HEAP32[(((buffers) + (i * 4)) >>> 2) >>> 0] = id;
+ }
+ },
+ MAX_TEMP_BUFFER_SIZE: 2097152,
+ numTempVertexBuffersPerSize: 64,
+ log2ceilLookup: i => 32 - Math.clz32(i === 0 ? 0 : i - 1),
+ generateTempBuffers: (quads, context) => {
+ var largestIndex = GL.log2ceilLookup(GL.MAX_TEMP_BUFFER_SIZE);
+ context.tempVertexBufferCounters1 = [];
+ context.tempVertexBufferCounters2 = [];
+ context.tempVertexBufferCounters1.length = context.tempVertexBufferCounters2.length = largestIndex + 1;
+ context.tempVertexBuffers1 = [];
+ context.tempVertexBuffers2 = [];
+ context.tempVertexBuffers1.length = context.tempVertexBuffers2.length = largestIndex + 1;
+ context.tempIndexBuffers = [];
+ context.tempIndexBuffers.length = largestIndex + 1;
+ for (var i = 0; i <= largestIndex; ++i) {
+ context.tempIndexBuffers[i] = null;
+ // Created on-demand
+ context.tempVertexBufferCounters1[i] = context.tempVertexBufferCounters2[i] = 0;
+ var ringbufferLength = GL.numTempVertexBuffersPerSize;
+ context.tempVertexBuffers1[i] = [];
+ context.tempVertexBuffers2[i] = [];
+ var ringbuffer1 = context.tempVertexBuffers1[i];
+ var ringbuffer2 = context.tempVertexBuffers2[i];
+ ringbuffer1.length = ringbuffer2.length = ringbufferLength;
+ for (var j = 0; j < ringbufferLength; ++j) {
+ ringbuffer1[j] = ringbuffer2[j] = null;
+ }
+ }
+ if (quads) {
+ // GL_QUAD indexes can be precalculated
+ context.tempQuadIndexBuffer = GLctx.createBuffer();
+ context.GLctx.bindBuffer(34963, context.tempQuadIndexBuffer);
+ var numIndexes = GL.MAX_TEMP_BUFFER_SIZE >> 1;
+ var quadIndexes = new Uint16Array(numIndexes);
+ var i = 0, v = 0;
+ while (1) {
+ quadIndexes[i++] = v;
+ if (i >= numIndexes) break;
+ quadIndexes[i++] = v + 1;
+ if (i >= numIndexes) break;
+ quadIndexes[i++] = v + 2;
+ if (i >= numIndexes) break;
+ quadIndexes[i++] = v;
+ if (i >= numIndexes) break;
+ quadIndexes[i++] = v + 2;
+ if (i >= numIndexes) break;
+ quadIndexes[i++] = v + 3;
+ if (i >= numIndexes) break;
+ v += 4;
+ }
+ context.GLctx.bufferData(34963, quadIndexes, 35044);
+ context.GLctx.bindBuffer(34963, null);
+ }
+ },
+ getTempVertexBuffer: sizeBytes => {
+ var idx = GL.log2ceilLookup(sizeBytes);
+ var ringbuffer = GL.currentContext.tempVertexBuffers1[idx];
+ var nextFreeBufferIndex = GL.currentContext.tempVertexBufferCounters1[idx];
+ GL.currentContext.tempVertexBufferCounters1[idx] = (GL.currentContext.tempVertexBufferCounters1[idx] + 1) & (GL.numTempVertexBuffersPerSize - 1);
+ var vbo = ringbuffer[nextFreeBufferIndex];
+ if (vbo) {
+ return vbo;
+ }
+ var prevVBO = GLctx.getParameter(34964);
+ ringbuffer[nextFreeBufferIndex] = GLctx.createBuffer();
+ GLctx.bindBuffer(34962, ringbuffer[nextFreeBufferIndex]);
+ GLctx.bufferData(34962, 1 << idx, 35048);
+ GLctx.bindBuffer(34962, prevVBO);
+ return ringbuffer[nextFreeBufferIndex];
+ },
+ getTempIndexBuffer: sizeBytes => {
+ var idx = GL.log2ceilLookup(sizeBytes);
+ var ibo = GL.currentContext.tempIndexBuffers[idx];
+ if (ibo) {
+ return ibo;
+ }
+ var prevIBO = GLctx.getParameter(34965);
+ GL.currentContext.tempIndexBuffers[idx] = GLctx.createBuffer();
+ GLctx.bindBuffer(34963, GL.currentContext.tempIndexBuffers[idx]);
+ GLctx.bufferData(34963, 1 << idx, 35048);
+ GLctx.bindBuffer(34963, prevIBO);
+ return GL.currentContext.tempIndexBuffers[idx];
+ },
+ newRenderingFrameStarted: () => {
+ if (!GL.currentContext) {
+ return;
+ }
+ var vb = GL.currentContext.tempVertexBuffers1;
+ GL.currentContext.tempVertexBuffers1 = GL.currentContext.tempVertexBuffers2;
+ GL.currentContext.tempVertexBuffers2 = vb;
+ vb = GL.currentContext.tempVertexBufferCounters1;
+ GL.currentContext.tempVertexBufferCounters1 = GL.currentContext.tempVertexBufferCounters2;
+ GL.currentContext.tempVertexBufferCounters2 = vb;
+ var largestIndex = GL.log2ceilLookup(GL.MAX_TEMP_BUFFER_SIZE);
+ for (var i = 0; i <= largestIndex; ++i) {
+ GL.currentContext.tempVertexBufferCounters1[i] = 0;
+ }
+ },
+ getSource: (shader, count, string, length) => {
+ var source = "";
+ for (var i = 0; i < count; ++i) {
+ var len = length ? HEAPU32[(((length) + (i * 4)) >>> 2) >>> 0] : undefined;
+ source += UTF8ToString(HEAPU32[(((string) + (i * 4)) >>> 2) >>> 0], len);
+ }
+ return source;
+ },
+ calcBufLength: (size, type, stride, count) => {
+ if (stride > 0) {
+ return count * stride;
+ }
+ var typeSize = GL.byteSizeByType[type - GL.byteSizeByTypeRoot];
+ return size * typeSize * count;
+ },
+ usedTempBuffers: [],
+ preDrawHandleClientVertexAttribBindings: count => {
+ GL.resetBufferBinding = false;
+ // TODO: initial pass to detect ranges we need to upload, might not need
+ // an upload per attrib
+ for (var i = 0; i < GL.currentContext.maxVertexAttribs; ++i) {
+ var cb = GL.currentContext.clientBuffers[i];
+ if (!cb.clientside || !cb.enabled) continue;
+ GL.resetBufferBinding = true;
+ var size = GL.calcBufLength(cb.size, cb.type, cb.stride, count);
+ var buf = GL.getTempVertexBuffer(size);
+ GLctx.bindBuffer(34962, buf);
+ GLctx.bufferSubData(34962, 0, HEAPU8.subarray(cb.ptr >>> 0, cb.ptr + size >>> 0));
+ cb.vertexAttribPointerAdaptor.call(GLctx, i, cb.size, cb.type, cb.normalized, cb.stride, 0);
+ }
+ },
+ postDrawHandleClientVertexAttribBindings: () => {
+ if (GL.resetBufferBinding) {
+ GLctx.bindBuffer(34962, GL.buffers[GLctx.currentArrayBufferBinding]);
+ }
+ },
+ createContext: (/** @type {HTMLCanvasElement} */ canvas, webGLContextAttributes) => {
+ // BUG: Workaround Safari WebGL issue: After successfully acquiring WebGL
+ // context on a canvas, calling .getContext() will always return that
+ // context independent of which 'webgl' or 'webgl2'
+ // context version was passed. See:
+ // https://webkit.org/b/222758
+ // and:
+ // https://github.com/emscripten-core/emscripten/issues/13295.
+ // TODO: Once the bug is fixed and shipped in Safari, adjust the Safari
+ // version field in above check.
+ if (!canvas.getContextSafariWebGL2Fixed) {
+ canvas.getContextSafariWebGL2Fixed = canvas.getContext;
+ /** @type {function(this:HTMLCanvasElement, string, (Object|null)=): (Object|null)} */ function fixedGetContext(ver, attrs) {
+ var gl = canvas.getContextSafariWebGL2Fixed(ver, attrs);
+ return ((ver == "webgl") == (gl instanceof WebGLRenderingContext)) ? gl : null;
+ }
+ canvas.getContext = fixedGetContext;
+ }
+ var ctx = (webGLContextAttributes.majorVersion > 1) ? canvas.getContext("webgl2", webGLContextAttributes) : canvas.getContext("webgl", webGLContextAttributes);
+ if (!ctx) return 0;
+ var handle = GL.registerContext(ctx, webGLContextAttributes);
+ return handle;
+ },
+ registerContext: (ctx, webGLContextAttributes) => {
+ // without pthreads a context is just an integer ID
+ var handle = GL.getNewId(GL.contexts);
+ var context = {
+ handle,
+ attributes: webGLContextAttributes,
+ version: webGLContextAttributes.majorVersion,
+ GLctx: ctx
+ };
+ // Store the created context object so that we can access the context
+ // given a canvas without having to pass the parameters again.
+ if (ctx.canvas) ctx.canvas.GLctxObject = context;
+ GL.contexts[handle] = context;
+ if (typeof webGLContextAttributes.enableExtensionsByDefault == "undefined" || webGLContextAttributes.enableExtensionsByDefault) {
+ GL.initExtensions(context);
+ }
+ context.maxVertexAttribs = context.GLctx.getParameter(34921);
+ context.clientBuffers = [];
+ for (var i = 0; i < context.maxVertexAttribs; i++) {
+ context.clientBuffers[i] = {
+ enabled: false,
+ clientside: false,
+ size: 0,
+ type: 0,
+ normalized: 0,
+ stride: 0,
+ ptr: 0,
+ vertexAttribPointerAdaptor: null
+ };
+ }
+ GL.generateTempBuffers(false, context);
+ return handle;
+ },
+ makeContextCurrent: contextHandle => {
+ // Active Emscripten GL layer context object.
+ GL.currentContext = GL.contexts[contextHandle];
+ // Active WebGL context object.
+ Module["ctx"] = GLctx = GL.currentContext?.GLctx;
+ return !(contextHandle && !GLctx);
+ },
+ getContext: contextHandle => GL.contexts[contextHandle],
+ deleteContext: contextHandle => {
+ if (GL.currentContext === GL.contexts[contextHandle]) {
+ GL.currentContext = null;
+ }
+ if (typeof JSEvents == "object") {
+ // Release all JS event handlers on the DOM element that the GL context is
+ // associated with since the context is now deleted.
+ JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas);
+ }
+ // Make sure the canvas object no longer refers to the context object so
+ // there are no GC surprises.
+ if (GL.contexts[contextHandle]?.GLctx.canvas) {
+ GL.contexts[contextHandle].GLctx.canvas.GLctxObject = undefined;
+ }
+ GL.contexts[contextHandle] = null;
+ },
+ initExtensions: context => {
+ // If this function is called without a specific context object, init the
+ // extensions of the currently active context.
+ context ||= GL.currentContext;
+ if (context.initExtensionsDone) return;
+ context.initExtensionsDone = true;
+ var GLctx = context.GLctx;
+ // Detect the presence of a few extensions manually, since the GL interop
+ // layer itself will need to know if they exist.
+ // Extensions that are available in both WebGL 1 and WebGL 2
+ webgl_enable_WEBGL_multi_draw(GLctx);
+ webgl_enable_EXT_polygon_offset_clamp(GLctx);
+ webgl_enable_EXT_clip_control(GLctx);
+ webgl_enable_WEBGL_polygon_mode(GLctx);
+ // Extensions that are only available in WebGL 1 (the calls will be no-ops
+ // if called on a WebGL 2 context active)
+ webgl_enable_ANGLE_instanced_arrays(GLctx);
+ webgl_enable_OES_vertex_array_object(GLctx);
+ webgl_enable_WEBGL_draw_buffers(GLctx);
+ // Extensions that are available from WebGL >= 2 (no-op if called on a WebGL 1 context active)
+ webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(GLctx);
+ webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance(GLctx);
+ // On WebGL 2, EXT_disjoint_timer_query is replaced with an alternative
+ // that's based on core APIs, and exposes only the queryCounterEXT()
+ // entrypoint.
+ if (context.version >= 2) {
+ GLctx.disjointTimerQueryExt = GLctx.getExtension("EXT_disjoint_timer_query_webgl2");
+ }
+ // However, Firefox exposes the WebGL 1 version on WebGL 2 as well and
+ // thus we look for the WebGL 1 version again if the WebGL 2 version
+ // isn't present. https://bugzil.la/1328882
+ if (context.version < 2 || !GLctx.disjointTimerQueryExt) {
+ GLctx.disjointTimerQueryExt = GLctx.getExtension("EXT_disjoint_timer_query");
+ }
+ for (var ext of getEmscriptenSupportedExtensions(GLctx)) {
+ // WEBGL_lose_context, WEBGL_debug_renderer_info and WEBGL_debug_shaders
+ // are not enabled by default.
+ if (!ext.includes("lose_context") && !ext.includes("debug")) {
+ // Call .getExtension() to enable that extension permanently.
+ GLctx.getExtension(ext);
+ }
+ }
+ }
+};
+
+var webglPowerPreferences = [ "default", "low-power", "high-performance" ];
+
+/** @type {Object} */ var specialHTMLTargets = [ 0, globalThis.document ?? 0, globalThis.window ?? 0 ];
+
+var findEventTarget = target => {
+ // The sensible "default" target varies between events, but use window as the default
+ // since DOM events mostly can default to that. Specific callback registrations
+ // override their own defaults.
+ if (!target) return window;
+ if (typeof target == "number") target = specialHTMLTargets[target] || UTF8ToString(target);
+ if (target === "#window") return window; else if (target === "#document") return document; else if (target === "#screen") return screen; else if (target === "#canvas") return Module["canvas"]; else if (typeof target == "string") return globalThis.document?.getElementById(target);
+ return target;
+};
+
+var findCanvasEventTarget = target => {
+ if (typeof target == "number") target = UTF8ToString(target);
+ if (!target || target === "#canvas") {
+ if (typeof GL != "undefined" && GL.offscreenCanvases["canvas"]) return GL.offscreenCanvases["canvas"];
+ // TODO: Remove this line, target '#canvas' should refer only to Module['canvas'], not to GL.offscreenCanvases['canvas'] - but need stricter tests to be able to remove this line.
+ return Module["canvas"];
+ }
+ if (typeof GL != "undefined" && GL.offscreenCanvases[target]) return GL.offscreenCanvases[target];
+ return findEventTarget(target);
+};
+
+function _emscripten_webgl_do_create_context(target, attributes) {
+ target >>>= 0;
+ attributes >>>= 0;
+ var attr32 = ((attributes) >>> 2);
+ var powerPreference = HEAP32[attr32 + (8 >> 2) >>> 0];
+ var contextAttributes = {
+ "alpha": !!HEAP8[attributes + 0 >>> 0],
+ "depth": !!HEAP8[attributes + 1 >>> 0],
+ "stencil": !!HEAP8[attributes + 2 >>> 0],
+ "antialias": !!HEAP8[attributes + 3 >>> 0],
+ "premultipliedAlpha": !!HEAP8[attributes + 4 >>> 0],
+ "preserveDrawingBuffer": !!HEAP8[attributes + 5 >>> 0],
+ "powerPreference": webglPowerPreferences[powerPreference],
+ "failIfMajorPerformanceCaveat": !!HEAP8[attributes + 12 >>> 0],
+ // The following are not predefined WebGL context attributes in the WebGL specification, so the property names can be minified by Closure.
+ majorVersion: HEAP32[attr32 + (16 >> 2) >>> 0],
+ minorVersion: HEAP32[attr32 + (20 >> 2) >>> 0],
+ enableExtensionsByDefault: HEAP8[attributes + 24 >>> 0],
+ explicitSwapControl: HEAP8[attributes + 25 >>> 0],
+ proxyContextToMainThread: HEAP32[attr32 + (28 >> 2) >>> 0],
+ renderViaOffscreenBackBuffer: HEAP8[attributes + 32 >>> 0]
+ };
+ var canvas = findCanvasEventTarget(target);
+ if (!canvas) {
+ return 0;
+ }
+ if (contextAttributes.explicitSwapControl) {
+ return 0;
+ }
+ var contextHandle = GL.createContext(canvas, contextAttributes);
+ return contextHandle;
+}
+
+var _emscripten_webgl_create_context = _emscripten_webgl_do_create_context;
+
+function _emscripten_webgl_destroy_context(contextHandle) {
+ contextHandle >>>= 0;
+ if (GL.currentContext == contextHandle) GL.currentContext = 0;
+ GL.deleteContext(contextHandle);
+}
+
+function _emscripten_webgl_get_context_attributes(c, a) {
+ c >>>= 0;
+ a >>>= 0;
+ if (!a) return -5;
+ c = GL.contexts[c];
+ if (!c) return -3;
+ var t = c.GLctx?.getContextAttributes();
+ if (!t) return -3;
+ HEAP8[a >>> 0] = t.alpha;
+ HEAP8[(a) + (1) >>> 0] = t.depth;
+ HEAP8[(a) + (2) >>> 0] = t.stencil;
+ HEAP8[(a) + (3) >>> 0] = t.antialias;
+ HEAP8[(a) + (4) >>> 0] = t.premultipliedAlpha;
+ HEAP8[(a) + (5) >>> 0] = t.preserveDrawingBuffer;
+ var power = t["powerPreference"] && webglPowerPreferences.indexOf(t["powerPreference"]);
+ HEAP32[(((a) + (8)) >>> 2) >>> 0] = power;
+ HEAP8[(a) + (12) >>> 0] = t.failIfMajorPerformanceCaveat;
+ HEAP32[(((a) + (16)) >>> 2) >>> 0] = c.version;
+ HEAP32[(((a) + (20)) >>> 2) >>> 0] = 0;
+ HEAP8[(a) + (24) >>> 0] = c.attributes.enableExtensionsByDefault;
+ return 0;
+}
+
+function _emscripten_webgl_do_get_current_context() {
+ return GL.currentContext ? GL.currentContext.handle : 0;
+}
+
+var _emscripten_webgl_get_current_context = _emscripten_webgl_do_get_current_context;
+
+function _emscripten_webgl_make_context_current(contextHandle) {
+ contextHandle >>>= 0;
+ var success = GL.makeContextCurrent(contextHandle);
+ return success ? 0 : -5;
+}
+
+var stackAlloc = sz => __emscripten_stack_alloc(sz);
+
+var stringToUTF8OnStack = str => {
+ var size = lengthBytesUTF8(str) + 1;
+ var ret = stackAlloc(size);
+ stringToUTF8(str, ret, size);
+ return ret;
+};
+
+var writeI53ToI64 = (ptr, num) => {
+ HEAPU32[((ptr) >>> 2) >>> 0] = num;
+ var lower = HEAPU32[((ptr) >>> 2) >>> 0];
+ HEAPU32[(((ptr) + (4)) >>> 2) >>> 0] = (num - lower) / 4294967296;
+};
+
+var readI53FromI64 = ptr => HEAPU32[((ptr) >>> 2) >>> 0] + HEAP32[(((ptr) + (4)) >>> 2) >>> 0] * 4294967296;
+
+var WebGPU = {
+ Internals: {
+ jsObjects: [],
+ jsObjectInsert: (ptr, jsObject) => {
+ ptr >>>= 0;
+ WebGPU.Internals.jsObjects[ptr] = jsObject;
+ },
+ bufferOnUnmaps: [],
+ futures: [],
+ futureInsert: (futureId, promise) => {
+ WebGPU.Internals.futures[futureId] = new Promise(resolve => promise.finally(() => resolve(futureId)));
+ }
+ },
+ getJsObject: ptr => {
+ if (!ptr) return undefined;
+ ptr >>>= 0;
+ return WebGPU.Internals.jsObjects[ptr];
+ },
+ importJsAdapter: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateAdapter(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsBindGroup: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateBindGroup(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsBindGroupLayout: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateBindGroupLayout(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsBuffer: (buffer, parentPtr = 0) => {
+ // At the moment, we do not allow importing pending buffers.
+ assert(buffer.mapState === "unmapped");
+ var bufferPtr = _emwgpuImportBuffer(parentPtr);
+ WebGPU.Internals.jsObjectInsert(bufferPtr, buffer);
+ return bufferPtr;
+ },
+ importJsCommandBuffer: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateCommandBuffer(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsCommandEncoder: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateCommandEncoder(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsComputePassEncoder: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateComputePassEncoder(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsComputePipeline: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateComputePipeline(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsDevice: (device, parentPtr = 0) => {
+ var queuePtr = _emwgpuCreateQueue(parentPtr);
+ var devicePtr = _emwgpuCreateDevice(parentPtr, queuePtr);
+ WebGPU.Internals.jsObjectInsert(queuePtr, device.queue);
+ WebGPU.Internals.jsObjectInsert(devicePtr, device);
+ return devicePtr;
+ },
+ importJsExternalTexture: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateExternalTexture(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsPipelineLayout: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreatePipelineLayout(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsQuerySet: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateQuerySet(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsQueue: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateQueue(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsRenderBundle: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateRenderBundle(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsRenderBundleEncoder: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateRenderBundleEncoder(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsRenderPassEncoder: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateRenderPassEncoder(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsRenderPipeline: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateRenderPipeline(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsSampler: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateSampler(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsShaderModule: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateShaderModule(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsSurface: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateSurface(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsTexture: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateTexture(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ importJsTextureView: (obj, parentPtr = 0) => {
+ var ptr = _emwgpuCreateTextureView(parentPtr);
+ WebGPU.Internals.jsObjects[ptr] = obj;
+ return ptr;
+ },
+ errorCallback: (callback, type, message, userdata) => {
+ var sp = stackSave();
+ var messagePtr = stringToUTF8OnStack(message);
+ ((a1, a2, a3) => dynCall_viii(callback, a1, a2, a3))(type, messagePtr, userdata);
+ stackRestore(sp);
+ },
+ iterateExtensions: (root, handlers) => {
+ for (var ptr = HEAPU32[((root) >>> 2) >>> 0]; ptr; ptr = HEAPU32[((ptr) >>> 2) >>> 0]) {
+ var sType = HEAP32[(((ptr) + (4)) >>> 2) >>> 0];
+ // This will crash if there's no handler indicating either a bogus
+ // sType, or one we haven't implemented yet.
+ var handler = handlers[sType](ptr);
+ }
+ },
+ setStringView: (ptr, data, length) => {
+ HEAPU32[((ptr) >>> 2) >>> 0] = data;
+ HEAPU32[(((ptr) + (4)) >>> 2) >>> 0] = length;
+ },
+ makeStringFromStringView: stringViewPtr => {
+ var ptr = HEAPU32[((stringViewPtr) >>> 2) >>> 0];
+ var length = HEAPU32[(((stringViewPtr) + (4)) >>> 2) >>> 0];
+ // UTF8ToString stops at the first null terminator character in the
+ // string regardless of the length.
+ return UTF8ToString(ptr, length);
+ },
+ makeStringFromOptionalStringView: stringViewPtr => {
+ var ptr = HEAPU32[((stringViewPtr) >>> 2) >>> 0];
+ var length = HEAPU32[(((stringViewPtr) + (4)) >>> 2) >>> 0];
+ // If we don't have a valid string pointer, just return undefined when
+ // optional.
+ if (!ptr) {
+ if (length === 0) {
+ return "";
+ }
+ return undefined;
+ }
+ // UTF8ToString stops at the first null terminator character in the
+ // string regardless of the length.
+ return UTF8ToString(ptr, length);
+ },
+ makeColor: ptr => ({
+ "r": HEAPF64[((ptr) >>> 3) >>> 0],
+ "g": HEAPF64[(((ptr) + (8)) >>> 3) >>> 0],
+ "b": HEAPF64[(((ptr) + (16)) >>> 3) >>> 0],
+ "a": HEAPF64[(((ptr) + (24)) >>> 3) >>> 0]
+ }),
+ makeExtent3D: ptr => ({
+ "width": HEAPU32[((ptr) >>> 2) >>> 0],
+ "height": HEAPU32[(((ptr) + (4)) >>> 2) >>> 0],
+ "depthOrArrayLayers": HEAPU32[(((ptr) + (8)) >>> 2) >>> 0]
+ }),
+ makeOrigin3D: ptr => ({
+ "x": HEAPU32[((ptr) >>> 2) >>> 0],
+ "y": HEAPU32[(((ptr) + (4)) >>> 2) >>> 0],
+ "z": HEAPU32[(((ptr) + (8)) >>> 2) >>> 0]
+ }),
+ makeTexelCopyTextureInfo: ptr => ({
+ "texture": WebGPU.getJsObject(HEAPU32[((ptr) >>> 2) >>> 0]),
+ "mipLevel": HEAPU32[(((ptr) + (4)) >>> 2) >>> 0],
+ "origin": WebGPU.makeOrigin3D(ptr + 8),
+ "aspect": WebGPU.TextureAspect[HEAP32[(((ptr) + (20)) >>> 2) >>> 0]]
+ }),
+ makeTexelCopyBufferLayout: ptr => {
+ var bytesPerRow = HEAPU32[(((ptr) + (8)) >>> 2) >>> 0];
+ var rowsPerImage = HEAPU32[(((ptr) + (12)) >>> 2) >>> 0];
+ return {
+ "offset": readI53FromI64(ptr),
+ "bytesPerRow": bytesPerRow === 4294967295 ? undefined : bytesPerRow,
+ "rowsPerImage": rowsPerImage === 4294967295 ? undefined : rowsPerImage
+ };
+ },
+ makeTexelCopyBufferInfo: ptr => {
+ var layoutPtr = ptr + 0;
+ var bufferCopyView = WebGPU.makeTexelCopyBufferLayout(layoutPtr);
+ bufferCopyView["buffer"] = WebGPU.getJsObject(HEAPU32[(((ptr) + (16)) >>> 2) >>> 0]);
+ return bufferCopyView;
+ },
+ makePassTimestampWrites: ptr => {
+ if (ptr === 0) return undefined;
+ return {
+ "querySet": WebGPU.getJsObject(HEAPU32[(((ptr) + (4)) >>> 2) >>> 0]),
+ "beginningOfPassWriteIndex": HEAPU32[(((ptr) + (8)) >>> 2) >>> 0],
+ "endOfPassWriteIndex": HEAPU32[(((ptr) + (12)) >>> 2) >>> 0]
+ };
+ },
+ makePipelineConstants: (constantCount, constantsPtr) => {
+ if (!constantCount) return;
+ var constants = {};
+ for (var i = 0; i < constantCount; ++i) {
+ var entryPtr = constantsPtr + 24 * i;
+ var key = WebGPU.makeStringFromStringView(entryPtr + 4);
+ constants[key] = HEAPF64[(((entryPtr) + (16)) >>> 3) >>> 0];
+ }
+ return constants;
+ },
+ makePipelineLayout: layoutPtr => {
+ if (!layoutPtr) return "auto";
+ return WebGPU.getJsObject(layoutPtr);
+ },
+ makeComputeState: ptr => {
+ if (!ptr) return undefined;
+ var desc = {
+ "module": WebGPU.getJsObject(HEAPU32[(((ptr) + (4)) >>> 2) >>> 0]),
+ "constants": WebGPU.makePipelineConstants(HEAPU32[(((ptr) + (16)) >>> 2) >>> 0], HEAPU32[(((ptr) + (20)) >>> 2) >>> 0]),
+ "entryPoint": WebGPU.makeStringFromOptionalStringView(ptr + 8)
+ };
+ return desc;
+ },
+ makeComputePipelineDesc: descriptor => {
+ var desc = {
+ "label": WebGPU.makeStringFromOptionalStringView(descriptor + 4),
+ "layout": WebGPU.makePipelineLayout(HEAPU32[(((descriptor) + (12)) >>> 2) >>> 0]),
+ "compute": WebGPU.makeComputeState(descriptor + 16)
+ };
+ return desc;
+ },
+ makeRenderPipelineDesc: descriptor => {
+ function makePrimitiveState(psPtr) {
+ if (!psPtr) return undefined;
+ return {
+ "topology": WebGPU.PrimitiveTopology[HEAP32[(((psPtr) + (4)) >>> 2) >>> 0]],
+ "stripIndexFormat": WebGPU.IndexFormat[HEAP32[(((psPtr) + (8)) >>> 2) >>> 0]],
+ "frontFace": WebGPU.FrontFace[HEAP32[(((psPtr) + (12)) >>> 2) >>> 0]],
+ "cullMode": WebGPU.CullMode[HEAP32[(((psPtr) + (16)) >>> 2) >>> 0]],
+ "unclippedDepth": !!(HEAPU32[(((psPtr) + (20)) >>> 2) >>> 0])
+ };
+ }
+ function makeBlendComponent(bdPtr) {
+ if (!bdPtr) return undefined;
+ return {
+ "operation": WebGPU.BlendOperation[HEAP32[((bdPtr) >>> 2) >>> 0]],
+ "srcFactor": WebGPU.BlendFactor[HEAP32[(((bdPtr) + (4)) >>> 2) >>> 0]],
+ "dstFactor": WebGPU.BlendFactor[HEAP32[(((bdPtr) + (8)) >>> 2) >>> 0]]
+ };
+ }
+ function makeBlendState(bsPtr) {
+ if (!bsPtr) return undefined;
+ return {
+ "alpha": makeBlendComponent(bsPtr + 12),
+ "color": makeBlendComponent(bsPtr + 0)
+ };
+ }
+ function makeColorState(csPtr) {
+ var format = WebGPU.TextureFormat[HEAP32[(((csPtr) + (4)) >>> 2) >>> 0]];
+ return format ? {
+ "format": format,
+ "blend": makeBlendState(HEAPU32[(((csPtr) + (8)) >>> 2) >>> 0]),
+ "writeMask": HEAPU32[(((csPtr) + (16)) >>> 2) >>> 0]
+ } : undefined;
+ }
+ function makeColorStates(count, csArrayPtr) {
+ var states = [];
+ for (var i = 0; i < count; ++i) {
+ states.push(makeColorState(csArrayPtr + 24 * i));
+ }
+ return states;
+ }
+ function makeStencilStateFace(ssfPtr) {
+ return {
+ "compare": WebGPU.CompareFunction[HEAP32[((ssfPtr) >>> 2) >>> 0]],
+ "failOp": WebGPU.StencilOperation[HEAP32[(((ssfPtr) + (4)) >>> 2) >>> 0]],
+ "depthFailOp": WebGPU.StencilOperation[HEAP32[(((ssfPtr) + (8)) >>> 2) >>> 0]],
+ "passOp": WebGPU.StencilOperation[HEAP32[(((ssfPtr) + (12)) >>> 2) >>> 0]]
+ };
+ }
+ function makeDepthStencilState(dssPtr) {
+ if (!dssPtr) return undefined;
+ return {
+ "format": WebGPU.TextureFormat[HEAP32[(((dssPtr) + (4)) >>> 2) >>> 0]],
+ "depthWriteEnabled": !!(HEAPU32[(((dssPtr) + (8)) >>> 2) >>> 0]),
+ "depthCompare": WebGPU.CompareFunction[HEAP32[(((dssPtr) + (12)) >>> 2) >>> 0]],
+ "stencilFront": makeStencilStateFace(dssPtr + 16),
+ "stencilBack": makeStencilStateFace(dssPtr + 32),
+ "stencilReadMask": HEAPU32[(((dssPtr) + (48)) >>> 2) >>> 0],
+ "stencilWriteMask": HEAPU32[(((dssPtr) + (52)) >>> 2) >>> 0],
+ "depthBias": HEAP32[(((dssPtr) + (56)) >>> 2) >>> 0],
+ "depthBiasSlopeScale": HEAPF32[(((dssPtr) + (60)) >>> 2) >>> 0],
+ "depthBiasClamp": HEAPF32[(((dssPtr) + (64)) >>> 2) >>> 0]
+ };
+ }
+ function makeVertexAttribute(vaPtr) {
+ return {
+ "format": WebGPU.VertexFormat[HEAP32[(((vaPtr) + (4)) >>> 2) >>> 0]],
+ "offset": readI53FromI64((vaPtr) + (8)),
+ "shaderLocation": HEAPU32[(((vaPtr) + (16)) >>> 2) >>> 0]
+ };
+ }
+ function makeVertexAttributes(count, vaArrayPtr) {
+ var vas = [];
+ for (var i = 0; i < count; ++i) {
+ vas.push(makeVertexAttribute(vaArrayPtr + i * 24));
+ }
+ return vas;
+ }
+ function makeVertexBuffer(vbPtr) {
+ if (!vbPtr) return undefined;
+ var stepMode = WebGPU.VertexStepMode[HEAP32[(((vbPtr) + (4)) >>> 2) >>> 0]];
+ var attributeCount = HEAPU32[(((vbPtr) + (16)) >>> 2) >>> 0];
+ if (!stepMode && !attributeCount) {
+ return null;
+ }
+ return {
+ "arrayStride": readI53FromI64((vbPtr) + (8)),
+ "stepMode": stepMode,
+ "attributes": makeVertexAttributes(attributeCount, HEAPU32[(((vbPtr) + (20)) >>> 2) >>> 0])
+ };
+ }
+ function makeVertexBuffers(count, vbArrayPtr) {
+ if (!count) return undefined;
+ var vbs = [];
+ for (var i = 0; i < count; ++i) {
+ vbs.push(makeVertexBuffer(vbArrayPtr + i * 24));
+ }
+ return vbs;
+ }
+ function makeVertexState(viPtr) {
+ if (!viPtr) return undefined;
+ var desc = {
+ "module": WebGPU.getJsObject(HEAPU32[(((viPtr) + (4)) >>> 2) >>> 0]),
+ "constants": WebGPU.makePipelineConstants(HEAPU32[(((viPtr) + (16)) >>> 2) >>> 0], HEAPU32[(((viPtr) + (20)) >>> 2) >>> 0]),
+ "buffers": makeVertexBuffers(HEAPU32[(((viPtr) + (24)) >>> 2) >>> 0], HEAPU32[(((viPtr) + (28)) >>> 2) >>> 0]),
+ "entryPoint": WebGPU.makeStringFromOptionalStringView(viPtr + 8)
+ };
+ return desc;
+ }
+ function makeMultisampleState(msPtr) {
+ if (!msPtr) return undefined;
+ return {
+ "count": HEAPU32[(((msPtr) + (4)) >>> 2) >>> 0],
+ "mask": HEAPU32[(((msPtr) + (8)) >>> 2) >>> 0],
+ "alphaToCoverageEnabled": !!(HEAPU32[(((msPtr) + (12)) >>> 2) >>> 0])
+ };
+ }
+ function makeFragmentState(fsPtr) {
+ if (!fsPtr) return undefined;
+ var desc = {
+ "module": WebGPU.getJsObject(HEAPU32[(((fsPtr) + (4)) >>> 2) >>> 0]),
+ "constants": WebGPU.makePipelineConstants(HEAPU32[(((fsPtr) + (16)) >>> 2) >>> 0], HEAPU32[(((fsPtr) + (20)) >>> 2) >>> 0]),
+ "targets": makeColorStates(HEAPU32[(((fsPtr) + (24)) >>> 2) >>> 0], HEAPU32[(((fsPtr) + (28)) >>> 2) >>> 0]),
+ "entryPoint": WebGPU.makeStringFromOptionalStringView(fsPtr + 8)
+ };
+ return desc;
+ }
+ var desc = {
+ "label": WebGPU.makeStringFromOptionalStringView(descriptor + 4),
+ "layout": WebGPU.makePipelineLayout(HEAPU32[(((descriptor) + (12)) >>> 2) >>> 0]),
+ "vertex": makeVertexState(descriptor + 16),
+ "primitive": makePrimitiveState(descriptor + 48),
+ "depthStencil": makeDepthStencilState(HEAPU32[(((descriptor) + (72)) >>> 2) >>> 0]),
+ "multisample": makeMultisampleState(descriptor + 76),
+ "fragment": makeFragmentState(HEAPU32[(((descriptor) + (92)) >>> 2) >>> 0])
+ };
+ return desc;
+ },
+ fillLimitStruct: (limits, limitsOutPtr) => {
+ var nextInChainPtr = HEAPU32[((limitsOutPtr) >>> 2) >>> 0];
+ function setLimitValueU32(name, basePtr, limitOffset, fallbackValue = 0) {
+ var limitValue = limits[name] ?? fallbackValue;
+ HEAPU32[(((basePtr) + (limitOffset)) >>> 2) >>> 0] = limitValue;
+ }
+ function setLimitValueU64(name, basePtr, limitOffset, fallbackValue = 0) {
+ var limitValue = limits[name] ?? fallbackValue;
+ // Limits are integer-valued JS `Number`s, so they fit in 'i53'.
+ writeI53ToI64((basePtr) + (limitOffset), limitValue);
+ }
+ setLimitValueU32("maxTextureDimension1D", limitsOutPtr, 4);
+ setLimitValueU32("maxTextureDimension2D", limitsOutPtr, 8);
+ setLimitValueU32("maxTextureDimension3D", limitsOutPtr, 12);
+ setLimitValueU32("maxTextureArrayLayers", limitsOutPtr, 16);
+ setLimitValueU32("maxBindGroups", limitsOutPtr, 20);
+ setLimitValueU32("maxBindGroupsPlusVertexBuffers", limitsOutPtr, 24);
+ setLimitValueU32("maxBindingsPerBindGroup", limitsOutPtr, 28);
+ setLimitValueU32("maxDynamicUniformBuffersPerPipelineLayout", limitsOutPtr, 32);
+ setLimitValueU32("maxDynamicStorageBuffersPerPipelineLayout", limitsOutPtr, 36);
+ setLimitValueU32("maxSampledTexturesPerShaderStage", limitsOutPtr, 40);
+ setLimitValueU32("maxSamplersPerShaderStage", limitsOutPtr, 44);
+ setLimitValueU32("maxStorageBuffersPerShaderStage", limitsOutPtr, 48);
+ setLimitValueU32("maxStorageTexturesPerShaderStage", limitsOutPtr, 52);
+ setLimitValueU32("maxUniformBuffersPerShaderStage", limitsOutPtr, 56);
+ setLimitValueU32("minUniformBufferOffsetAlignment", limitsOutPtr, 80);
+ setLimitValueU32("minStorageBufferOffsetAlignment", limitsOutPtr, 84);
+ setLimitValueU64("maxUniformBufferBindingSize", limitsOutPtr, 64);
+ setLimitValueU64("maxStorageBufferBindingSize", limitsOutPtr, 72);
+ setLimitValueU32("maxVertexBuffers", limitsOutPtr, 88);
+ setLimitValueU64("maxBufferSize", limitsOutPtr, 96);
+ setLimitValueU32("maxVertexAttributes", limitsOutPtr, 104);
+ setLimitValueU32("maxVertexBufferArrayStride", limitsOutPtr, 108);
+ setLimitValueU32("maxInterStageShaderVariables", limitsOutPtr, 112);
+ setLimitValueU32("maxColorAttachments", limitsOutPtr, 116);
+ setLimitValueU32("maxColorAttachmentBytesPerSample", limitsOutPtr, 120);
+ setLimitValueU32("maxComputeWorkgroupStorageSize", limitsOutPtr, 124);
+ setLimitValueU32("maxComputeInvocationsPerWorkgroup", limitsOutPtr, 128);
+ setLimitValueU32("maxComputeWorkgroupSizeX", limitsOutPtr, 132);
+ setLimitValueU32("maxComputeWorkgroupSizeY", limitsOutPtr, 136);
+ setLimitValueU32("maxComputeWorkgroupSizeZ", limitsOutPtr, 140);
+ setLimitValueU32("maxComputeWorkgroupsPerDimension", limitsOutPtr, 144);
+ // Note this limit is new and won't be present in all browsers for a while. Fall back to 0.
+ setLimitValueU32("maxImmediateSize", limitsOutPtr, 148);
+ if (nextInChainPtr !== 0) {
+ var sType = HEAP32[(((nextInChainPtr) + (4)) >>> 2) >>> 0];
+ var compatibilityModeLimitsPtr = nextInChainPtr;
+ // Note these limits are new and won't be present in all browsers for a while. Fall back to exposing the PerShaderStage limit.
+ setLimitValueU32("maxStorageBuffersInVertexStage", compatibilityModeLimitsPtr, 8, limits.maxStorageBuffersPerShaderStage);
+ setLimitValueU32("maxStorageBuffersInFragmentStage", compatibilityModeLimitsPtr, 16, limits.maxStorageBuffersPerShaderStage);
+ setLimitValueU32("maxStorageTexturesInVertexStage", compatibilityModeLimitsPtr, 12, limits.maxStorageTexturesPerShaderStage);
+ setLimitValueU32("maxStorageTexturesInFragmentStage", compatibilityModeLimitsPtr, 20, limits.maxStorageTexturesPerShaderStage);
+ }
+ },
+ fillAdapterInfoStruct: (info, infoStruct) => {
+ // Populate subgroup limits.
+ HEAPU32[(((infoStruct) + (52)) >>> 2) >>> 0] = info.subgroupMinSize;
+ HEAPU32[(((infoStruct) + (56)) >>> 2) >>> 0] = info.subgroupMaxSize;
+ // Append all the strings together to condense into a single malloc.
+ var strs = info.vendor + info.architecture + info.device + info.description;
+ var strPtr = stringToNewUTF8(strs);
+ var vendorLen = lengthBytesUTF8(info.vendor);
+ WebGPU.setStringView(infoStruct + 4, strPtr, vendorLen);
+ strPtr += vendorLen;
+ var architectureLen = lengthBytesUTF8(info.architecture);
+ WebGPU.setStringView(infoStruct + 12, strPtr, architectureLen);
+ strPtr += architectureLen;
+ var deviceLen = lengthBytesUTF8(info.device);
+ WebGPU.setStringView(infoStruct + 20, strPtr, deviceLen);
+ strPtr += deviceLen;
+ var descriptionLen = lengthBytesUTF8(info.description);
+ WebGPU.setStringView(infoStruct + 28, strPtr, descriptionLen);
+ strPtr += descriptionLen;
+ HEAP32[(((infoStruct) + (36)) >>> 2) >>> 0] = 2;
+ var adapterType = info.isFallbackAdapter ? 3 : 4;
+ HEAP32[(((infoStruct) + (40)) >>> 2) >>> 0] = adapterType;
+ HEAPU32[(((infoStruct) + (44)) >>> 2) >>> 0] = 0;
+ HEAPU32[(((infoStruct) + (48)) >>> 2) >>> 0] = 0;
+ },
+ AddressMode: [ , "clamp-to-edge", "repeat", "mirror-repeat" ],
+ BlendFactor: [ , "zero", "one", "src", "one-minus-src", "src-alpha", "one-minus-src-alpha", "dst", "one-minus-dst", "dst-alpha", "one-minus-dst-alpha", "src-alpha-saturated", "constant", "one-minus-constant", "src1", "one-minus-src1", "src1-alpha", "one-minus-src1-alpha" ],
+ BlendOperation: [ , "add", "subtract", "reverse-subtract", "min", "max" ],
+ BufferBindingType: [ , , "uniform", "storage", "read-only-storage" ],
+ BufferMapState: [ , "unmapped", "pending", "mapped" ],
+ CompareFunction: [ , "never", "less", "equal", "less-equal", "greater", "not-equal", "greater-equal", "always" ],
+ CompilationInfoRequestStatus: [ , "success", "callback-cancelled" ],
+ ComponentSwizzle: [ , "0", "1", "r", "g", "b", "a" ],
+ CompositeAlphaMode: [ , "opaque", "premultiplied", "unpremultiplied", "inherit" ],
+ CullMode: [ , "none", "front", "back" ],
+ ErrorFilter: [ , "validation", "out-of-memory", "internal" ],
+ FeatureLevel: [ , "compatibility", "core" ],
+ FeatureName: {
+ 1: "core-features-and-limits",
+ 2: "depth-clip-control",
+ 3: "depth32float-stencil8",
+ 4: "texture-compression-bc",
+ 5: "texture-compression-bc-sliced-3d",
+ 6: "texture-compression-etc2",
+ 7: "texture-compression-astc",
+ 8: "texture-compression-astc-sliced-3d",
+ 9: "timestamp-query",
+ 10: "indirect-first-instance",
+ 11: "shader-f16",
+ 12: "rg11b10ufloat-renderable",
+ 13: "bgra8unorm-storage",
+ 14: "float32-filterable",
+ 15: "float32-blendable",
+ 16: "clip-distances",
+ 17: "dual-source-blending",
+ 18: "subgroups",
+ 19: "texture-formats-tier1",
+ 20: "texture-formats-tier2",
+ 21: "primitive-index",
+ 22: "texture-component-swizzle",
+ 327692: "chromium-experimental-unorm16-texture-formats",
+ 327729: "chromium-experimental-multi-draw-indirect"
+ },
+ FilterMode: [ , "nearest", "linear" ],
+ FrontFace: [ , "ccw", "cw" ],
+ IndexFormat: [ , "uint16", "uint32" ],
+ InstanceFeatureName: [ , "timed-wait-any", "shader-source-spirv", "multiple-devices-per-adapter" ],
+ LoadOp: [ , "load", "clear" ],
+ MipmapFilterMode: [ , "nearest", "linear" ],
+ OptionalBool: [ "false", "true" ],
+ PowerPreference: [ , "low-power", "high-performance" ],
+ PredefinedColorSpace: [ , "srgb", "display-p3" ],
+ PrimitiveTopology: [ , "point-list", "line-list", "line-strip", "triangle-list", "triangle-strip" ],
+ QueryType: [ , "occlusion", "timestamp" ],
+ SamplerBindingType: [ , , "filtering", "non-filtering", "comparison" ],
+ Status: [ , "success", "error" ],
+ StencilOperation: [ , "keep", "zero", "replace", "invert", "increment-clamp", "decrement-clamp", "increment-wrap", "decrement-wrap" ],
+ StorageTextureAccess: [ , , "write-only", "read-only", "read-write" ],
+ StoreOp: [ , "store", "discard" ],
+ SurfaceGetCurrentTextureStatus: [ , "success-optimal", "success-suboptimal", "timeout", "outdated", "lost", "error" ],
+ TextureAspect: [ , "all", "stencil-only", "depth-only" ],
+ TextureDimension: [ , "1d", "2d", "3d" ],
+ TextureFormat: [ , "r8unorm", "r8snorm", "r8uint", "r8sint", "r16unorm", "r16snorm", "r16uint", "r16sint", "r16float", "rg8unorm", "rg8snorm", "rg8uint", "rg8sint", "r32float", "r32uint", "r32sint", "rg16unorm", "rg16snorm", "rg16uint", "rg16sint", "rg16float", "rgba8unorm", "rgba8unorm-srgb", "rgba8snorm", "rgba8uint", "rgba8sint", "bgra8unorm", "bgra8unorm-srgb", "rgb10a2uint", "rgb10a2unorm", "rg11b10ufloat", "rgb9e5ufloat", "rg32float", "rg32uint", "rg32sint", "rgba16unorm", "rgba16snorm", "rgba16uint", "rgba16sint", "rgba16float", "rgba32float", "rgba32uint", "rgba32sint", "stencil8", "depth16unorm", "depth24plus", "depth24plus-stencil8", "depth32float", "depth32float-stencil8", "bc1-rgba-unorm", "bc1-rgba-unorm-srgb", "bc2-rgba-unorm", "bc2-rgba-unorm-srgb", "bc3-rgba-unorm", "bc3-rgba-unorm-srgb", "bc4-r-unorm", "bc4-r-snorm", "bc5-rg-unorm", "bc5-rg-snorm", "bc6h-rgb-ufloat", "bc6h-rgb-float", "bc7-rgba-unorm", "bc7-rgba-unorm-srgb", "etc2-rgb8unorm", "etc2-rgb8unorm-srgb", "etc2-rgb8a1unorm", "etc2-rgb8a1unorm-srgb", "etc2-rgba8unorm", "etc2-rgba8unorm-srgb", "eac-r11unorm", "eac-r11snorm", "eac-rg11unorm", "eac-rg11snorm", "astc-4x4-unorm", "astc-4x4-unorm-srgb", "astc-5x4-unorm", "astc-5x4-unorm-srgb", "astc-5x5-unorm", "astc-5x5-unorm-srgb", "astc-6x5-unorm", "astc-6x5-unorm-srgb", "astc-6x6-unorm", "astc-6x6-unorm-srgb", "astc-8x5-unorm", "astc-8x5-unorm-srgb", "astc-8x6-unorm", "astc-8x6-unorm-srgb", "astc-8x8-unorm", "astc-8x8-unorm-srgb", "astc-10x5-unorm", "astc-10x5-unorm-srgb", "astc-10x6-unorm", "astc-10x6-unorm-srgb", "astc-10x8-unorm", "astc-10x8-unorm-srgb", "astc-10x10-unorm", "astc-10x10-unorm-srgb", "astc-12x10-unorm", "astc-12x10-unorm-srgb", "astc-12x12-unorm", "astc-12x12-unorm-srgb" ],
+ TextureSampleType: [ , , "float", "unfilterable-float", "depth", "sint", "uint" ],
+ TextureViewDimension: [ , "1d", "2d", "2d-array", "cube", "cube-array", "3d" ],
+ ToneMappingMode: [ , "standard", "extended" ],
+ VertexFormat: [ , "uint8", "uint8x2", "uint8x4", "sint8", "sint8x2", "sint8x4", "unorm8", "unorm8x2", "unorm8x4", "snorm8", "snorm8x2", "snorm8x4", "uint16", "uint16x2", "uint16x4", "sint16", "sint16x2", "sint16x4", "unorm16", "unorm16x2", "unorm16x4", "snorm16", "snorm16x2", "snorm16x4", "float16", "float16x2", "float16x4", "float32", "float32x2", "float32x3", "float32x4", "uint32", "uint32x2", "uint32x3", "uint32x4", "sint32", "sint32x2", "sint32x3", "sint32x4", "unorm10-10-10-2", "unorm8x4-bgra" ],
+ VertexStepMode: [ , "vertex", "instance" ],
+ WGSLLanguageFeatureName: [ , "readonly_and_readwrite_storage_textures", "packed_4x8_integer_dot_product", "unrestricted_pointer_parameters", "pointer_composite_access", "uniform_buffer_standard_layout", "subgroup_id", "texture_and_sampler_let", "subgroup_uniformity", "texture_formats_tier1" ]
+};
+
+function _emscripten_webgpu_get_device() {
+ if (WebGPU.preinitializedDeviceId === undefined) {
+ WebGPU.preinitializedDeviceId = WebGPU.importJsDevice(Module["preinitializedWebGPUDevice"]);
+ // Some users depend on this keeping the device alive, so we add an
+ // additional reference when we first initialize it.
+ _wgpuDeviceAddRef(WebGPU.preinitializedDeviceId);
+ }
+ _wgpuDeviceAddRef(WebGPU.preinitializedDeviceId);
+ return WebGPU.preinitializedDeviceId;
+}
+
+function _emwgpuBufferDestroy(bufferPtr) {
+ bufferPtr >>>= 0;
+ var buffer = WebGPU.getJsObject(bufferPtr);
+ var onUnmap = WebGPU.Internals.bufferOnUnmaps[bufferPtr];
+ if (onUnmap) {
+ for (var i = 0; i < onUnmap.length; ++i) {
+ onUnmap[i]();
+ }
+ delete WebGPU.Internals.bufferOnUnmaps[bufferPtr];
+ }
+ buffer.destroy();
+}
+
+function _emwgpuBufferGetMappedRange(bufferPtr, offset, size) {
+ bufferPtr >>>= 0;
+ offset >>>= 0;
+ size >>>= 0;
+ var buffer = WebGPU.getJsObject(bufferPtr);
+ if (size == 4294967295) size = undefined;
+ var mapped;
+ try {
+ mapped = buffer.getMappedRange(offset, size);
+ } catch (ex) {
+ return 0;
+ }
+ var data = _memalign(16, mapped.byteLength);
+ HEAPU8.fill(0, data, mapped.byteLength);
+ WebGPU.Internals.bufferOnUnmaps[bufferPtr].push(() => {
+ new Uint8Array(mapped).set(HEAPU8.subarray(data >>> 0, data + mapped.byteLength >>> 0));
+ _free(data);
+ });
+ return data;
+}
+
+function _emwgpuBufferUnmap(bufferPtr) {
+ bufferPtr >>>= 0;
+ var buffer = WebGPU.getJsObject(bufferPtr);
+ var onUnmap = WebGPU.Internals.bufferOnUnmaps[bufferPtr];
+ if (!onUnmap) {
+ // Already unmapped
+ return;
+ }
+ for (var i = 0; i < onUnmap.length; ++i) {
+ onUnmap[i]();
+ }
+ delete WebGPU.Internals.bufferOnUnmaps[bufferPtr];
+ buffer.unmap();
+}
+
+function _emwgpuBufferWriteMappedRange(bufferPtr, offset, data, size) {
+ bufferPtr >>>= 0;
+ offset >>>= 0;
+ data >>>= 0;
+ size >>>= 0;
+ var buffer = WebGPU.getJsObject(bufferPtr);
+ var mapped;
+ try {
+ mapped = buffer.getMappedRange(offset, size);
+ } catch (ex) {
+ return 2;
+ }
+ new Uint8Array(mapped).set(HEAPU8.subarray(data >>> 0, data + size >>> 0));
+ return 1;
+}
+
+function _emwgpuDelete(ptr) {
+ ptr >>>= 0;
+ delete WebGPU.Internals.jsObjects[ptr];
+}
+
+function _emwgpuDeviceCreateBuffer(devicePtr, descriptor, bufferPtr) {
+ devicePtr >>>= 0;
+ descriptor >>>= 0;
+ bufferPtr >>>= 0;
+ var mappedAtCreation = !!(HEAPU32[(((descriptor) + (32)) >>> 2) >>> 0]);
+ var desc = {
+ "label": WebGPU.makeStringFromOptionalStringView(descriptor + 4),
+ "usage": HEAPU32[(((descriptor) + (16)) >>> 2) >>> 0],
+ "size": readI53FromI64((descriptor) + (24)),
+ "mappedAtCreation": mappedAtCreation
+ };
+ var device = WebGPU.getJsObject(devicePtr);
+ var buffer;
+ try {
+ buffer = device.createBuffer(desc);
+ } catch (ex) {
+ // The only exception should be RangeError if mapping at creation ran out of memory.
+ return false;
+ }
+ WebGPU.Internals.jsObjectInsert(bufferPtr, buffer);
+ if (mappedAtCreation) {
+ WebGPU.Internals.bufferOnUnmaps[bufferPtr] = [];
+ }
+ return true;
+}
+
+var _emwgpuDeviceCreateComputePipelineAsync = function(devicePtr, futureId_low, futureId_high, descriptor, pipelinePtr) {
+ devicePtr >>>= 0;
+ var futureId = convertI32PairToI53Checked(futureId_low, futureId_high);
+ descriptor >>>= 0;
+ pipelinePtr >>>= 0;
+ var desc = WebGPU.makeComputePipelineDesc(descriptor);
+ var device = WebGPU.getJsObject(devicePtr);
+ // createComputePipelineAsync
+ WebGPU.Internals.futureInsert(futureId, device.createComputePipelineAsync(desc).then(pipeline => {
+ // createComputePipelineAsync fulfilled
+ callUserCallback(() => {
+ WebGPU.Internals.jsObjectInsert(pipelinePtr, pipeline);
+ _emwgpuOnCreateComputePipelineCompleted(futureId, 1, pipelinePtr, 0);
+ });
+ }, pipelineError => {
+ // createComputePipelineAsync rejected
+ callUserCallback(() => {
+ var sp = stackSave();
+ var messagePtr = stringToUTF8OnStack(pipelineError.message);
+ var status = pipelineError.reason === "validation" ? 3 : pipelineError.reason === "internal" ? 4 : 0;
+ _emwgpuOnCreateComputePipelineCompleted(futureId, status, pipelinePtr, messagePtr);
+ stackRestore(sp);
+ });
+ }));
+};
+
+function _emwgpuDeviceCreateShaderModule(devicePtr, descriptor, shaderModulePtr) {
+ devicePtr >>>= 0;
+ descriptor >>>= 0;
+ shaderModulePtr >>>= 0;
+ var nextInChainPtr = HEAPU32[((descriptor) >>> 2) >>> 0];
+ var sType = HEAP32[(((nextInChainPtr) + (4)) >>> 2) >>> 0];
+ var desc = {
+ "label": WebGPU.makeStringFromOptionalStringView(descriptor + 4),
+ "code": ""
+ };
+ switch (sType) {
+ case 2:
+ {
+ desc["code"] = WebGPU.makeStringFromStringView(nextInChainPtr + 8);
+ break;
+ }
+ }
+ var device = WebGPU.getJsObject(devicePtr);
+ WebGPU.Internals.jsObjectInsert(shaderModulePtr, device.createShaderModule(desc));
+}
+
+var _emwgpuDeviceDestroy = devicePtr => {
+ const device = WebGPU.getJsObject(devicePtr);
+ // Remove the onuncapturederror handler which holds a pointer to the WGPUDevice.
+ device.onuncapturederror = null;
+ device.destroy();
+};
+
+var _emwgpuQueueOnSubmittedWorkDone = function(queuePtr, futureId_low, futureId_high) {
+ queuePtr >>>= 0;
+ var futureId = convertI32PairToI53Checked(futureId_low, futureId_high);
+ var queue = WebGPU.getJsObject(queuePtr);
+ // onSubmittedWorkDone
+ WebGPU.Internals.futureInsert(futureId, queue.onSubmittedWorkDone().then(() => {
+ // onSubmittedWorkDone fulfilled (assumed not to reject)
+ callUserCallback(() => {
+ _emwgpuOnWorkDoneCompleted(futureId, 1);
+ });
+ }));
+};
+
+var _emwgpuWaitAny = function(futurePtr, futureCount, timeoutMSPtr) {
+ futurePtr >>>= 0;
+ futureCount >>>= 0;
+ timeoutMSPtr >>>= 0;
+ return Asyncify.handleAsync(async () => {
+ var promises = [];
+ if (timeoutMSPtr) {
+ var timeoutMS = HEAP32[((timeoutMSPtr) >>> 2) >>> 0];
+ promises.length = futureCount + 1;
+ promises[futureCount] = new Promise(resolve => setTimeout(resolve, timeoutMS, 0));
+ } else {
+ promises.length = futureCount;
+ }
+ for (var i = 0; i < futureCount; ++i) {
+ // If any FutureID is not tracked, it means it must be done.
+ var futureId = readI53FromI64((futurePtr + i * 8));
+ if (!(futureId in WebGPU.Internals.futures)) {
+ return futureId;
+ }
+ promises[i] = WebGPU.Internals.futures[futureId];
+ }
+ const firstResolvedFuture = await Promise.race(promises);
+ delete WebGPU.Internals.futures[firstResolvedFuture];
+ return firstResolvedFuture;
+ });
+};
+
+_emwgpuWaitAny.isAsync = true;
+
+var ENV = {};
+
+var getExecutableName = () => thisProgram || "./this.program";
+
+var getEnvStrings = () => {
+ if (!getEnvStrings.strings) {
+ // Default values.
+ // Browser language detection #8751
+ var lang = (globalThis.navigator?.language ?? "C").replace("-", "_") + ".UTF-8";
+ var env = {
+ "USER": "web_user",
+ "LOGNAME": "web_user",
+ "PATH": "/",
+ "PWD": "/",
+ "HOME": "/home/web_user",
+ "LANG": lang,
+ "_": getExecutableName()
+ };
+ // Apply the user-provided values, if any.
+ for (var x in ENV) {
+ // x is a key in ENV; if ENV[x] is undefined, that means it was
+ // explicitly set to be so. We allow user code to do that to
+ // force variables with default values to remain unset.
+ if (ENV[x] === undefined) delete env[x]; else env[x] = ENV[x];
+ }
+ var strings = [];
+ for (var x in env) {
+ strings.push(`${x}=${env[x]}`);
+ }
+ getEnvStrings.strings = strings;
+ }
+ return getEnvStrings.strings;
+};
+
+function _environ_get(__environ, environ_buf) {
+ __environ >>>= 0;
+ environ_buf >>>= 0;
+ var bufSize = 0;
+ var envp = 0;
+ for (var string of getEnvStrings()) {
+ var ptr = environ_buf + bufSize;
+ HEAPU32[(((__environ) + (envp)) >>> 2) >>> 0] = ptr;
+ bufSize += stringToUTF8(string, ptr, Infinity) + 1;
+ envp += 4;
+ }
+ return 0;
+}
+
+function _environ_sizes_get(penviron_count, penviron_buf_size) {
+ penviron_count >>>= 0;
+ penviron_buf_size >>>= 0;
+ var strings = getEnvStrings();
+ HEAPU32[((penviron_count) >>> 2) >>> 0] = strings.length;
+ var bufSize = 0;
+ for (var string of strings) {
+ bufSize += lengthBytesUTF8(string) + 1;
+ }
+ HEAPU32[((penviron_buf_size) >>> 2) >>> 0] = bufSize;
+ return 0;
+}
+
+function _fd_close(fd) {
+ try {
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ FS.close(stream);
+ return 0;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return e.errno;
+ }
+}
+
+/** @param {number=} offset */ var doReadv = (stream, iov, iovcnt, offset) => {
+ var ret = 0;
+ for (var i = 0; i < iovcnt; i++) {
+ var ptr = HEAPU32[((iov) >>> 2) >>> 0];
+ var len = HEAPU32[(((iov) + (4)) >>> 2) >>> 0];
+ iov += 8;
+ var curr = FS.read(stream, HEAP8, ptr, len, offset);
+ if (curr < 0) return -1;
+ ret += curr;
+ if (curr < len) break;
+ // nothing more to read
+ if (typeof offset != "undefined") {
+ offset += curr;
+ }
+ }
+ return ret;
+};
+
+function _fd_pread(fd, iov, iovcnt, offset_low, offset_high, pnum) {
+ iov >>>= 0;
+ iovcnt >>>= 0;
+ var offset = convertI32PairToI53Checked(offset_low, offset_high);
+ pnum >>>= 0;
+ try {
+ if (isNaN(offset)) return 61;
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ var num = doReadv(stream, iov, iovcnt, offset);
+ HEAPU32[((pnum) >>> 2) >>> 0] = num;
+ return 0;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return e.errno;
+ }
+}
+
+function _fd_read(fd, iov, iovcnt, pnum) {
+ iov >>>= 0;
+ iovcnt >>>= 0;
+ pnum >>>= 0;
+ try {
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ var num = doReadv(stream, iov, iovcnt);
+ HEAPU32[((pnum) >>> 2) >>> 0] = num;
+ return 0;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return e.errno;
+ }
+}
+
+function _fd_seek(fd, offset_low, offset_high, whence, newOffset) {
+ var offset = convertI32PairToI53Checked(offset_low, offset_high);
+ newOffset >>>= 0;
+ try {
+ if (isNaN(offset)) return 61;
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ FS.llseek(stream, offset, whence);
+ (tempI64 = [ stream.position >>> 0, (tempDouble = stream.position, (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0) ],
+ HEAP32[((newOffset) >>> 2) >>> 0] = tempI64[0], HEAP32[(((newOffset) + (4)) >>> 2) >>> 0] = tempI64[1]);
+ if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null;
+ // reset readdir state
+ return 0;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return e.errno;
+ }
+}
+
+/** @param {number=} offset */ var doWritev = (stream, iov, iovcnt, offset) => {
+ var ret = 0;
+ for (var i = 0; i < iovcnt; i++) {
+ var ptr = HEAPU32[((iov) >>> 2) >>> 0];
+ var len = HEAPU32[(((iov) + (4)) >>> 2) >>> 0];
+ iov += 8;
+ var curr = FS.write(stream, HEAP8, ptr, len, offset);
+ if (curr < 0) return -1;
+ ret += curr;
+ if (curr < len) {
+ // No more space to write.
+ break;
+ }
+ if (typeof offset != "undefined") {
+ offset += curr;
+ }
+ }
+ return ret;
+};
+
+function _fd_write(fd, iov, iovcnt, pnum) {
+ iov >>>= 0;
+ iovcnt >>>= 0;
+ pnum >>>= 0;
+ try {
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ var num = doWritev(stream, iov, iovcnt);
+ HEAPU32[((pnum) >>> 2) >>> 0] = num;
+ return 0;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return e.errno;
+ }
+}
+
+var _emscripten_glActiveTexture = x0 => GLctx.activeTexture(x0);
+
+var _glActiveTexture = _emscripten_glActiveTexture;
+
+var _emscripten_glAttachShader = (program, shader) => {
+ GLctx.attachShader(GL.programs[program], GL.shaders[shader]);
+};
+
+var _glAttachShader = _emscripten_glAttachShader;
+
+function _emscripten_glBindAttribLocation(program, index, name) {
+ name >>>= 0;
+ GLctx.bindAttribLocation(GL.programs[program], index, UTF8ToString(name));
+}
+
+var _glBindAttribLocation = _emscripten_glBindAttribLocation;
+
+var _emscripten_glBindBuffer = (target, buffer) => {
+ // Calling glBindBuffer with an unknown buffer will implicitly create a
+ // new one. Here we bypass `GL.counter` and directly using the ID passed
+ // in.
+ if (buffer && !GL.buffers[buffer]) {
+ var b = GLctx.createBuffer();
+ b.name = buffer;
+ GL.buffers[buffer] = b;
+ }
+ if (target == 34962) {
+ GLctx.currentArrayBufferBinding = buffer;
+ } else if (target == 34963) {
+ GLctx.currentElementArrayBufferBinding = buffer;
+ }
+ if (target == 35051) {
+ // In WebGL 2 glReadPixels entry point, we need to use a different WebGL 2
+ // API function call when a buffer is bound to
+ // GL_PIXEL_PACK_BUFFER_BINDING point, so must keep track whether that
+ // binding point is non-null to know what is the proper API function to
+ // call.
+ GLctx.currentPixelPackBufferBinding = buffer;
+ } else if (target == 35052) {
+ // In WebGL 2 gl(Compressed)Tex(Sub)Image[23]D entry points, we need to
+ // use a different WebGL 2 API function call when a buffer is bound to
+ // GL_PIXEL_UNPACK_BUFFER_BINDING point, so must keep track whether that
+ // binding point is non-null to know what is the proper API function to
+ // call.
+ GLctx.currentPixelUnpackBufferBinding = buffer;
+ }
+ GLctx.bindBuffer(target, GL.buffers[buffer]);
+};
+
+var _glBindBuffer = _emscripten_glBindBuffer;
+
+var _emscripten_glBindFramebuffer = (target, framebuffer) => {
+ GLctx.bindFramebuffer(target, GL.framebuffers[framebuffer]);
+};
+
+var _glBindFramebuffer = _emscripten_glBindFramebuffer;
+
+var _emscripten_glBindTexture = (target, texture) => {
+ GLctx.bindTexture(target, GL.textures[texture]);
+};
+
+var _glBindTexture = _emscripten_glBindTexture;
+
+function _emscripten_glBufferData(target, size, data, usage) {
+ size >>>= 0;
+ data >>>= 0;
+ // N.b. here first form specifies a heap subarray, second form an integer
+ // size, so the ?: code here is polymorphic. It is advised to avoid
+ // randomly mixing both uses in calling code, to avoid any potential JS
+ // engine JIT issues.
+ GLctx.bufferData(target, data ? HEAPU8.subarray(data >>> 0, data + size >>> 0) : size, usage);
+}
+
+var _glBufferData = _emscripten_glBufferData;
+
+var convertI32PairToI53 = (lo, hi) => (lo >>> 0) + hi * 4294967296;
+
+function _emscripten_glClientWaitSync(sync, flags, timeout_low, timeout_high) {
+ sync >>>= 0;
+ // WebGL2 vs GLES3 differences: in GLES3, the timeout parameter is a uint64, where 0xFFFFFFFFFFFFFFFFULL means GL_TIMEOUT_IGNORED.
+ // In JS, there's no 64-bit value types, so instead timeout is taken to be signed, and GL_TIMEOUT_IGNORED is given value -1.
+ // Inherently the value accepted in the timeout is lossy, and can't take in arbitrary u64 bit pattern (but most likely doesn't matter)
+ // See https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.15
+ var timeout = convertI32PairToI53(timeout_low, timeout_high);
+ return GLctx.clientWaitSync(GL.syncs[sync], flags, timeout);
+}
+
+var _glClientWaitSync = _emscripten_glClientWaitSync;
+
+var _emscripten_glCompileShader = shader => {
+ GLctx.compileShader(GL.shaders[shader]);
+};
+
+var _glCompileShader = _emscripten_glCompileShader;
+
+var _emscripten_glCreateProgram = () => {
+ var id = GL.getNewId(GL.programs);
+ var program = GLctx.createProgram();
+ // Store additional information needed for each shader program:
+ program.name = id;
+ // Lazy cache results of
+ // glGetProgramiv(GL_ACTIVE_UNIFORM_MAX_LENGTH/GL_ACTIVE_ATTRIBUTE_MAX_LENGTH/GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH)
+ program.maxUniformLength = program.maxAttributeLength = program.maxUniformBlockNameLength = 0;
+ program.uniformIdCounter = 1;
+ GL.programs[id] = program;
+ return id;
+};
+
+var _glCreateProgram = _emscripten_glCreateProgram;
+
+var _emscripten_glCreateShader = shaderType => {
+ var id = GL.getNewId(GL.shaders);
+ GL.shaders[id] = GLctx.createShader(shaderType);
+ return id;
+};
+
+var _glCreateShader = _emscripten_glCreateShader;
+
+function _emscripten_glDeleteFramebuffers(n, framebuffers) {
+ framebuffers >>>= 0;
+ for (var i = 0; i < n; ++i) {
+ var id = HEAP32[(((framebuffers) + (i * 4)) >>> 2) >>> 0];
+ var framebuffer = GL.framebuffers[id];
+ if (!framebuffer) continue;
+ // GL spec: "glDeleteFramebuffers silently ignores 0s and names that do not correspond to existing framebuffer objects".
+ GLctx.deleteFramebuffer(framebuffer);
+ framebuffer.name = 0;
+ GL.framebuffers[id] = null;
+ }
+}
+
+var _glDeleteFramebuffers = _emscripten_glDeleteFramebuffers;
+
+var _emscripten_glDeleteProgram = id => {
+ if (!id) return;
+ var program = GL.programs[id];
+ if (!program) {
+ // glDeleteProgram actually signals an error when deleting a nonexisting
+ // object, unlike some other GL delete functions.
+ GL.recordError(1281);
+ return;
+ }
+ GLctx.deleteProgram(program);
+ program.name = 0;
+ GL.programs[id] = null;
+};
+
+var _glDeleteProgram = _emscripten_glDeleteProgram;
+
+var _emscripten_glDeleteShader = id => {
+ if (!id) return;
+ var shader = GL.shaders[id];
+ if (!shader) {
+ // glDeleteShader actually signals an error when deleting a nonexisting
+ // object, unlike some other GL delete functions.
+ GL.recordError(1281);
+ return;
+ }
+ GLctx.deleteShader(shader);
+ GL.shaders[id] = null;
+};
+
+var _glDeleteShader = _emscripten_glDeleteShader;
+
+function _emscripten_glDeleteSync(id) {
+ id >>>= 0;
+ if (!id) return;
+ var sync = GL.syncs[id];
+ if (!sync) {
+ // glDeleteSync signals an error when deleting a nonexisting object, unlike some other GL delete functions.
+ GL.recordError(1281);
+ return;
+ }
+ GLctx.deleteSync(sync);
+ sync.name = 0;
+ GL.syncs[id] = null;
+}
+
+var _glDeleteSync = _emscripten_glDeleteSync;
+
+function _emscripten_glDeleteTextures(n, textures) {
+ textures >>>= 0;
+ for (var i = 0; i < n; i++) {
+ var id = HEAP32[(((textures) + (i * 4)) >>> 2) >>> 0];
+ var texture = GL.textures[id];
+ // GL spec: "glDeleteTextures silently ignores 0s and names that do not
+ // correspond to existing textures".
+ if (!texture) continue;
+ GLctx.deleteTexture(texture);
+ texture.name = 0;
+ GL.textures[id] = null;
+ }
+}
+
+var _glDeleteTextures = _emscripten_glDeleteTextures;
+
+var _emscripten_glDetachShader = (program, shader) => {
+ GLctx.detachShader(GL.programs[program], GL.shaders[shader]);
+};
+
+var _glDetachShader = _emscripten_glDetachShader;
+
+var _emscripten_glDisableVertexAttribArray = index => {
+ var cb = GL.currentContext.clientBuffers[index];
+ cb.enabled = false;
+ GLctx.disableVertexAttribArray(index);
+};
+
+var _glDisableVertexAttribArray = _emscripten_glDisableVertexAttribArray;
+
+var _emscripten_glDrawArrays = (mode, first, count) => {
+ // bind any client-side buffers
+ GL.preDrawHandleClientVertexAttribBindings(first + count);
+ GLctx.drawArrays(mode, first, count);
+ GL.postDrawHandleClientVertexAttribBindings();
+};
+
+var _glDrawArrays = _emscripten_glDrawArrays;
+
+var _emscripten_glEnableVertexAttribArray = index => {
+ var cb = GL.currentContext.clientBuffers[index];
+ cb.enabled = true;
+ GLctx.enableVertexAttribArray(index);
+};
+
+var _glEnableVertexAttribArray = _emscripten_glEnableVertexAttribArray;
+
+function _emscripten_glFenceSync(condition, flags) {
+ var sync = GLctx.fenceSync(condition, flags);
+ if (sync) {
+ var id = GL.getNewId(GL.syncs);
+ sync.name = id;
+ GL.syncs[id] = sync;
+ return id;
+ }
+ return 0;
+}
+
+var _glFenceSync = _emscripten_glFenceSync;
+
+var _emscripten_glFinish = () => GLctx.finish();
+
+var _glFinish = _emscripten_glFinish;
+
+var _emscripten_glFramebufferTexture2D = (target, attachment, textarget, texture, level) => {
+ GLctx.framebufferTexture2D(target, attachment, textarget, GL.textures[texture], level);
+};
+
+var _glFramebufferTexture2D = _emscripten_glFramebufferTexture2D;
+
+function _emscripten_glGenBuffers(n, buffers) {
+ buffers >>>= 0;
+ GL.genObject(n, buffers, "createBuffer", GL.buffers);
+}
+
+var _glGenBuffers = _emscripten_glGenBuffers;
+
+function _emscripten_glGenFramebuffers(n, ids) {
+ ids >>>= 0;
+ GL.genObject(n, ids, "createFramebuffer", GL.framebuffers);
+}
+
+var _glGenFramebuffers = _emscripten_glGenFramebuffers;
+
+function _emscripten_glGenTextures(n, textures) {
+ textures >>>= 0;
+ GL.genObject(n, textures, "createTexture", GL.textures);
+}
+
+var _glGenTextures = _emscripten_glGenTextures;
+
+var _emscripten_glGetError = () => {
+ var error = GLctx.getError() || GL.lastError;
+ GL.lastError = 0;
+ return error;
+};
+
+var _glGetError = _emscripten_glGetError;
+
+var webglGetExtensions = () => {
+ var exts = getEmscriptenSupportedExtensions(GLctx);
+ exts = exts.concat(exts.map(e => "GL_" + e));
+ return exts;
+};
+
+var emscriptenWebGLGet = (name_, p, type) => {
+ // Guard against user passing a null pointer.
+ // Note that GLES2 spec does not say anything about how passing a null
+ // pointer should be treated. Testing on desktop core GL 3, the application
+ // crashes on glGetIntegerv to a null pointer, but better to report an error
+ // instead of doing anything random.
+ if (!p) {
+ GL.recordError(1281);
+ return;
+ }
+ var ret = undefined;
+ switch (name_) {
+ // Handle a few trivial GLES values
+ case 36346:
+ // GL_SHADER_COMPILER
+ ret = 1;
+ break;
+
+ case 36344:
+ // GL_SHADER_BINARY_FORMATS
+ if (type != 0 && type != 1) {
+ GL.recordError(1280);
+ }
+ // Do not write anything to the out pointer, since no binary formats are
+ // supported.
+ return;
+
+ case 34814:
+ // GL_NUM_PROGRAM_BINARY_FORMATS
+ case 36345:
+ // GL_NUM_SHADER_BINARY_FORMATS
+ ret = 0;
+ break;
+
+ case 34466:
+ // GL_NUM_COMPRESSED_TEXTURE_FORMATS
+ // WebGL doesn't have GL_NUM_COMPRESSED_TEXTURE_FORMATS (it's obsolete
+ // since GL_COMPRESSED_TEXTURE_FORMATS returns a JS array that can be
+ // queried for length), so implement it ourselves to allow C++ GLES2
+ // code to get the length.
+ var formats = GLctx.getParameter(34467);
+ ret = formats ? formats.length : 0;
+ break;
+
+ case 33309:
+ // GL_NUM_EXTENSIONS
+ if (GL.currentContext.version < 2) {
+ // Calling GLES3/WebGL2 function with a GLES2/WebGL1 context
+ GL.recordError(1282);
+ return;
+ }
+ ret = webglGetExtensions().length;
+ break;
+
+ case 33307:
+ // GL_MAJOR_VERSION
+ case 33308:
+ // GL_MINOR_VERSION
+ if (GL.currentContext.version < 2) {
+ GL.recordError(1280);
+ // GL_INVALID_ENUM
+ return;
+ }
+ ret = name_ == 33307 ? 3 : 0;
+ // return version 3.0
+ break;
+ }
+ if (ret === undefined) {
+ var result = GLctx.getParameter(name_);
+ switch (typeof result) {
+ case "number":
+ ret = result;
+ break;
+
+ case "boolean":
+ ret = result ? 1 : 0;
+ break;
+
+ case "string":
+ GL.recordError(1280);
+ // GL_INVALID_ENUM
+ return;
+
+ case "object":
+ if (result === null) {
+ // null is a valid result for some (e.g., which buffer is bound -
+ // perhaps nothing is bound), but otherwise can mean an invalid
+ // name_, which we need to report as an error
+ switch (name_) {
+ case 34964:
+ // ARRAY_BUFFER_BINDING
+ case 35725:
+ // CURRENT_PROGRAM
+ case 34965:
+ // ELEMENT_ARRAY_BUFFER_BINDING
+ case 36006:
+ // FRAMEBUFFER_BINDING or DRAW_FRAMEBUFFER_BINDING
+ case 36007:
+ // RENDERBUFFER_BINDING
+ case 32873:
+ // TEXTURE_BINDING_2D
+ case 34229:
+ // WebGL 2 GL_VERTEX_ARRAY_BINDING, or WebGL 1 extension OES_vertex_array_object GL_VERTEX_ARRAY_BINDING_OES
+ case 36662:
+ // COPY_READ_BUFFER_BINDING or COPY_READ_BUFFER
+ case 36663:
+ // COPY_WRITE_BUFFER_BINDING or COPY_WRITE_BUFFER
+ case 35053:
+ // PIXEL_PACK_BUFFER_BINDING
+ case 35055:
+ // PIXEL_UNPACK_BUFFER_BINDING
+ case 36010:
+ // READ_FRAMEBUFFER_BINDING
+ case 35097:
+ // SAMPLER_BINDING
+ case 35869:
+ // TEXTURE_BINDING_2D_ARRAY
+ case 32874:
+ // TEXTURE_BINDING_3D
+ case 36389:
+ // TRANSFORM_FEEDBACK_BINDING
+ case 35983:
+ // TRANSFORM_FEEDBACK_BUFFER_BINDING
+ case 35368:
+ // UNIFORM_BUFFER_BINDING
+ case 34068:
+ {
+ // TEXTURE_BINDING_CUBE_MAP
+ ret = 0;
+ break;
+ }
+
+ default:
+ {
+ GL.recordError(1280);
+ // GL_INVALID_ENUM
+ return;
+ }
+ }
+ } else if (result instanceof Float32Array || result instanceof Uint32Array || result instanceof Int32Array || result instanceof Array) {
+ for (var i = 0; i < result.length; ++i) {
+ switch (type) {
+ case 0:
+ HEAP32[(((p) + (i * 4)) >>> 2) >>> 0] = result[i];
+ break;
+
+ case 2:
+ HEAPF32[(((p) + (i * 4)) >>> 2) >>> 0] = result[i];
+ break;
+
+ case 4:
+ HEAP8[(p) + (i) >>> 0] = result[i] ? 1 : 0;
+ break;
+ }
+ }
+ return;
+ } else {
+ try {
+ ret = result.name | 0;
+ } catch (e) {
+ GL.recordError(1280);
+ // GL_INVALID_ENUM
+ err(`GL_INVALID_ENUM in glGet${type}v: Unknown object returned from WebGL getParameter(${name_})! (error: ${e})`);
+ return;
+ }
+ }
+ break;
+
+ default:
+ GL.recordError(1280);
+ // GL_INVALID_ENUM
+ err(`GL_INVALID_ENUM in glGet${type}v: Native code calling glGet${type}v(${name_}) and it returns ${result} of type ${typeof (result)}!`);
+ return;
+ }
+ }
+ switch (type) {
+ case 1:
+ writeI53ToI64(p, ret);
+ break;
+
+ case 0:
+ HEAP32[((p) >>> 2) >>> 0] = ret;
+ break;
+
+ case 2:
+ HEAPF32[((p) >>> 2) >>> 0] = ret;
+ break;
+
+ case 4:
+ HEAP8[p >>> 0] = ret ? 1 : 0;
+ break;
+ }
+};
+
+function _emscripten_glGetIntegerv(name_, p) {
+ p >>>= 0;
+ return emscriptenWebGLGet(name_, p, 0);
+}
+
+var _glGetIntegerv = _emscripten_glGetIntegerv;
+
+function _emscripten_glGetString(name_) {
+ var ret = GL.stringCache[name_];
+ if (!ret) {
+ switch (name_) {
+ case 7939:
+ ret = stringToNewUTF8(webglGetExtensions().join(" "));
+ break;
+
+ case 7936:
+ case 7937:
+ case 37445:
+ case 37446:
+ var s = GLctx.getParameter(name_);
+ if (!s) {
+ GL.recordError(1280);
+ }
+ ret = s ? stringToNewUTF8(s) : 0;
+ break;
+
+ case 7938:
+ var webGLVersion = GLctx.getParameter(7938);
+ // return GLES version string corresponding to the version of the WebGL context
+ var glVersion = `OpenGL ES 2.0 (${webGLVersion})`;
+ if (GL.currentContext.version >= 2) glVersion = `OpenGL ES 3.0 (${webGLVersion})`;
+ ret = stringToNewUTF8(glVersion);
+ break;
+
+ case 35724:
+ var glslVersion = GLctx.getParameter(35724);
+ // extract the version number 'N.M' from the string 'WebGL GLSL ES N.M ...'
+ var ver_re = /^WebGL GLSL ES ([0-9]\.[0-9][0-9]?)(?:$| .*)/;
+ var ver_num = glslVersion.match(ver_re);
+ if (ver_num !== null) {
+ if (ver_num[1].length == 3) ver_num[1] = ver_num[1] + "0";
+ // ensure minor version has 2 digits
+ glslVersion = `OpenGL ES GLSL ES ${ver_num[1]} (${glslVersion})`;
+ }
+ ret = stringToNewUTF8(glslVersion);
+ break;
+
+ default:
+ GL.recordError(1280);
+ }
+ GL.stringCache[name_] = ret;
+ }
+ return ret;
+}
+
+var _glGetString = _emscripten_glGetString;
+
+/** @suppress {checkTypes} */ var jstoi_q = str => parseInt(str);
+
+/** @noinline */ var webglGetLeftBracePos = name => name.slice(-1) == "]" && name.lastIndexOf("[");
+
+var webglPrepareUniformLocationsBeforeFirstUse = program => {
+ var uniformLocsById = program.uniformLocsById, // Maps GLuint -> WebGLUniformLocation
+ uniformSizeAndIdsByName = program.uniformSizeAndIdsByName, // Maps name -> [uniform array length, GLuint]
+ i, j;
+ // On the first time invocation of glGetUniformLocation on this shader program:
+ // initialize cache data structures and discover which uniforms are arrays.
+ if (!uniformLocsById) {
+ // maps GLint integer locations to WebGLUniformLocations
+ program.uniformLocsById = uniformLocsById = {};
+ // maps integer locations back to uniform name strings, so that we can lazily fetch uniform array locations
+ program.uniformArrayNamesById = {};
+ var numActiveUniforms = GLctx.getProgramParameter(program, 35718);
+ for (i = 0; i < numActiveUniforms; ++i) {
+ var u = GLctx.getActiveUniform(program, i);
+ var nm = u.name;
+ var sz = u.size;
+ var lb = webglGetLeftBracePos(nm);
+ var arrayName = lb > 0 ? nm.slice(0, lb) : nm;
+ // Assign a new location.
+ var id = program.uniformIdCounter;
+ program.uniformIdCounter += sz;
+ // Eagerly get the location of the uniformArray[0] base element.
+ // The remaining indices >0 will be left for lazy evaluation to
+ // improve performance. Those may never be needed to fetch, if the
+ // application fills arrays always in full starting from the first
+ // element of the array.
+ uniformSizeAndIdsByName[arrayName] = [ sz, id ];
+ // Store placeholder integers in place that highlight that these
+ // >0 index locations are array indices pending population.
+ for (j = 0; j < sz; ++j) {
+ uniformLocsById[id] = j;
+ program.uniformArrayNamesById[id++] = arrayName;
+ }
+ }
+ }
+};
+
+function _emscripten_glGetUniformLocation(program, name) {
+ name >>>= 0;
+ name = UTF8ToString(name);
+ if (program = GL.programs[program]) {
+ webglPrepareUniformLocationsBeforeFirstUse(program);
+ var uniformLocsById = program.uniformLocsById;
+ // Maps GLuint -> WebGLUniformLocation
+ var arrayIndex = 0;
+ var uniformBaseName = name;
+ // Invariant: when populating integer IDs for uniform locations, we must
+ // maintain the precondition that arrays reside in contiguous addresses,
+ // i.e. for a 'vec4 colors[10];', colors[4] must be at location
+ // colors[0]+4. However, user might call glGetUniformLocation(program,
+ // "colors") for an array, so we cannot discover based on the user input
+ // arguments whether the uniform we are dealing with is an array. The only
+ // way to discover which uniforms are arrays is to enumerate over all the
+ // active uniforms in the program.
+ var leftBrace = webglGetLeftBracePos(name);
+ // If user passed an array accessor "[index]", parse the array index off the accessor.
+ if (leftBrace > 0) {
+ arrayIndex = jstoi_q(name.slice(leftBrace + 1)) >>> 0;
+ // "index]", coerce parseInt(']') with >>>0 to treat "foo[]" as "foo[0]" and foo[-1] as unsigned out-of-bounds.
+ uniformBaseName = name.slice(0, leftBrace);
+ }
+ // Have we cached the location of this uniform before?
+ // A pair [array length, GLint of the uniform location]
+ var sizeAndId = program.uniformSizeAndIdsByName[uniformBaseName];
+ // If a uniform with this name exists, and if its index is within the
+ // array limits (if it's even an array), query the WebGLlocation, or
+ // return an existing cached location.
+ if (sizeAndId && arrayIndex < sizeAndId[0]) {
+ arrayIndex += sizeAndId[1];
+ // Add the base location of the uniform to the array index offset.
+ if ((uniformLocsById[arrayIndex] = uniformLocsById[arrayIndex] || GLctx.getUniformLocation(program, name))) {
+ return arrayIndex;
+ }
+ }
+ } else {
+ // N.b. we are currently unable to distinguish between GL program IDs that
+ // never existed vs GL program IDs that have been deleted, so report
+ // GL_INVALID_VALUE in both cases.
+ GL.recordError(1281);
+ }
+ return -1;
+}
+
+var _glGetUniformLocation = _emscripten_glGetUniformLocation;
+
+var _emscripten_glLinkProgram = program => {
+ program = GL.programs[program];
+ GLctx.linkProgram(program);
+ // Invalidate earlier computed uniform->ID mappings, those have now become stale
+ program.uniformLocsById = 0;
+ // Mark as null-like so that glGetUniformLocation() knows to populate this again.
+ program.uniformSizeAndIdsByName = {};
+};
+
+var _glLinkProgram = _emscripten_glLinkProgram;
+
+var _emscripten_glPixelStorei = (pname, param) => {
+ if (pname == 3317) {
+ GL.unpackAlignment = param;
+ } else if (pname == 3314) {
+ GL.unpackRowLength = param;
+ }
+ GLctx.pixelStorei(pname, param);
+};
+
+var _glPixelStorei = _emscripten_glPixelStorei;
+
+var computeUnpackAlignedImageSize = (width, height, sizePerPixel) => {
+ function roundedToNextMultipleOf(x, y) {
+ return (x + y - 1) & -y;
+ }
+ var plainRowSize = (GL.unpackRowLength || width) * sizePerPixel;
+ var alignedRowSize = roundedToNextMultipleOf(plainRowSize, GL.unpackAlignment);
+ return height * alignedRowSize;
+};
+
+var colorChannelsInGlTextureFormat = format => {
+ // Micro-optimizations for size: map format to size by subtracting smallest
+ // enum value (0x1902) from all values first. Also omit the most common
+ // size value (1) from the list, which is assumed by formats not on the
+ // list.
+ var colorChannels = {
+ // 0x1902 /* GL_DEPTH_COMPONENT */ - 0x1902: 1,
+ // 0x1906 /* GL_ALPHA */ - 0x1902: 1,
+ 5: 3,
+ 6: 4,
+ // 0x1909 /* GL_LUMINANCE */ - 0x1902: 1,
+ 8: 2,
+ 29502: 3,
+ 29504: 4,
+ // 0x1903 /* GL_RED */ - 0x1902: 1,
+ 26917: 2,
+ 26918: 2,
+ // 0x8D94 /* GL_RED_INTEGER */ - 0x1902: 1,
+ 29846: 3,
+ 29847: 4
+ };
+ return colorChannels[format - 6402] || 1;
+};
+
+var heapObjectForWebGLType = type => {
+ // Micro-optimization for size: Subtract lowest GL enum number (0x1400/* GL_BYTE */) from type to compare
+ // smaller values for the heap, for shorter generated code size.
+ // Also the type HEAPU16 is not tested for explicitly, but any unrecognized type will return out HEAPU16.
+ // (since most types are HEAPU16)
+ type -= 5120;
+ if (type == 0) return HEAP8;
+ if (type == 1) return HEAPU8;
+ if (type == 2) return HEAP16;
+ if (type == 4) return HEAP32;
+ if (type == 6) return HEAPF32;
+ if (type == 5 || type == 28922 || type == 28520 || type == 30779 || type == 30782) return HEAPU32;
+ return HEAPU16;
+};
+
+var toTypedArrayIndex = (pointer, heap) => pointer >>> (31 - Math.clz32(heap.BYTES_PER_ELEMENT));
+
+var emscriptenWebGLGetTexPixelData = (type, format, width, height, pixels, internalFormat) => {
+ var heap = heapObjectForWebGLType(type);
+ var sizePerPixel = colorChannelsInGlTextureFormat(format) * heap.BYTES_PER_ELEMENT;
+ var bytes = computeUnpackAlignedImageSize(width, height, sizePerPixel);
+ return heap.subarray(toTypedArrayIndex(pixels, heap) >>> 0, toTypedArrayIndex(pixels + bytes, heap) >>> 0);
+};
+
+function _emscripten_glReadPixels(x, y, width, height, format, type, pixels) {
+ pixels >>>= 0;
+ if (GL.currentContext.version >= 2) {
+ if (GLctx.currentPixelPackBufferBinding) {
+ GLctx.readPixels(x, y, width, height, format, type, pixels);
+ return;
+ }
+ }
+ var pixelData = emscriptenWebGLGetTexPixelData(type, format, width, height, pixels, format);
+ if (!pixelData) {
+ GL.recordError(1280);
+ return;
+ }
+ GLctx.readPixels(x, y, width, height, format, type, pixelData);
+}
+
+var _glReadPixels = _emscripten_glReadPixels;
+
+function _emscripten_glShaderSource(shader, count, string, length) {
+ string >>>= 0;
+ length >>>= 0;
+ var source = GL.getSource(shader, count, string, length);
+ GLctx.shaderSource(GL.shaders[shader], source);
+}
+
+var _glShaderSource = _emscripten_glShaderSource;
+
+function _emscripten_glTexImage2D(target, level, internalFormat, width, height, border, format, type, pixels) {
+ pixels >>>= 0;
+ if (GL.currentContext.version >= 2) {
+ if (GLctx.currentPixelUnpackBufferBinding) {
+ GLctx.texImage2D(target, level, internalFormat, width, height, border, format, type, pixels);
+ return;
+ }
+ }
+ var pixelData = pixels ? emscriptenWebGLGetTexPixelData(type, format, width, height, pixels, internalFormat) : null;
+ GLctx.texImage2D(target, level, internalFormat, width, height, border, format, type, pixelData);
+}
+
+var _glTexImage2D = _emscripten_glTexImage2D;
+
+var _emscripten_glTexParameteri = (x0, x1, x2) => GLctx.texParameteri(x0, x1, x2);
+
+var _glTexParameteri = _emscripten_glTexParameteri;
+
+var _emscripten_glTexStorage2D = (x0, x1, x2, x3, x4) => GLctx.texStorage2D(x0, x1, x2, x3, x4);
+
+var _glTexStorage2D = _emscripten_glTexStorage2D;
+
+var webglGetUniformLocation = location => {
+ var p = GLctx.currentProgram;
+ if (p) {
+ var webglLoc = p.uniformLocsById[location];
+ // p.uniformLocsById[location] stores either an integer, or a
+ // WebGLUniformLocation.
+ // If an integer, we have not yet bound the location, so do it now. The
+ // integer value specifies the array index we should bind to.
+ if (typeof webglLoc == "number") {
+ p.uniformLocsById[location] = webglLoc = GLctx.getUniformLocation(p, p.uniformArrayNamesById[location] + (webglLoc > 0 ? `[${webglLoc}]` : ""));
+ }
+ // Else an already cached WebGLUniformLocation, return it.
+ return webglLoc;
+ } else {
+ GL.recordError(1282);
+ }
+};
+
+var _emscripten_glUniform1i = (location, v0) => {
+ GLctx.uniform1i(webglGetUniformLocation(location), v0);
+};
+
+var _glUniform1i = _emscripten_glUniform1i;
+
+var _emscripten_glUseProgram = program => {
+ program = GL.programs[program];
+ GLctx.useProgram(program);
+ // Record the currently active program so that we can access the uniform
+ // mapping table of that program.
+ GLctx.currentProgram = program;
+};
+
+var _glUseProgram = _emscripten_glUseProgram;
+
+function _emscripten_glVertexAttribPointer(index, size, type, normalized, stride, ptr) {
+ ptr >>>= 0;
+ var cb = GL.currentContext.clientBuffers[index];
+ if (!GLctx.currentArrayBufferBinding) {
+ cb.size = size;
+ cb.type = type;
+ cb.normalized = normalized;
+ cb.stride = stride;
+ cb.ptr = ptr;
+ cb.clientside = true;
+ cb.vertexAttribPointerAdaptor = function(index, size, type, normalized, stride, ptr) {
+ this.vertexAttribPointer(index, size, type, normalized, stride, ptr);
+ };
+ return;
+ }
+ cb.clientside = false;
+ GLctx.vertexAttribPointer(index, size, type, !!normalized, stride, ptr);
+}
+
+var _glVertexAttribPointer = _emscripten_glVertexAttribPointer;
+
+var _emscripten_glViewport = (x0, x1, x2, x3) => GLctx.viewport(x0, x1, x2, x3);
+
+var _glViewport = _emscripten_glViewport;
+
+function _random_get(buffer, size) {
+ buffer >>>= 0;
+ size >>>= 0;
+ try {
+ randomFill(HEAPU8.subarray(buffer >>> 0, buffer + size >>> 0));
+ return 0;
+ } catch (e) {
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
+ return e.errno;
+ }
+}
+
+var _wgpuBufferGetSize = function(bufferPtr) {
+ bufferPtr >>>= 0;
+ var ret = (() => {
+ var buffer = WebGPU.getJsObject(bufferPtr);
+ // 64-bit
+ return buffer.size;
+ })();
+ return (setTempRet0((tempDouble = ret, (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0)),
+ ret >>> 0);
+};
+
+var _wgpuBufferGetUsage = function(bufferPtr) {
+ bufferPtr >>>= 0;
+ var ret = (() => {
+ var buffer = WebGPU.getJsObject(bufferPtr);
+ return buffer.usage;
+ })();
+ return (setTempRet0((tempDouble = ret, (+(Math.abs(tempDouble))) >= 1 ? (tempDouble > 0 ? (+(Math.floor((tempDouble) / 4294967296))) >>> 0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble))) >>> 0)) / 4294967296))))) >>> 0) : 0)),
+ ret >>> 0);
+};
+
+function _wgpuCommandEncoderBeginComputePass(encoderPtr, descriptor) {
+ encoderPtr >>>= 0;
+ descriptor >>>= 0;
+ var desc;
+ if (descriptor) {
+ desc = {
+ "label": WebGPU.makeStringFromOptionalStringView(descriptor + 4),
+ "timestampWrites": WebGPU.makePassTimestampWrites(HEAPU32[(((descriptor) + (12)) >>> 2) >>> 0])
+ };
+ }
+ var commandEncoder = WebGPU.getJsObject(encoderPtr);
+ var ptr = _emwgpuCreateComputePassEncoder(0);
+ WebGPU.Internals.jsObjectInsert(ptr, commandEncoder.beginComputePass(desc));
+ return ptr;
+}
+
+function _wgpuCommandEncoderCopyBufferToBuffer(encoderPtr, srcPtr, srcOffset_low, srcOffset_high, dstPtr, dstOffset_low, dstOffset_high, size_low, size_high) {
+ encoderPtr >>>= 0;
+ srcPtr >>>= 0;
+ var srcOffset = convertI32PairToI53Checked(srcOffset_low, srcOffset_high);
+ dstPtr >>>= 0;
+ var dstOffset = convertI32PairToI53Checked(dstOffset_low, dstOffset_high);
+ var size = convertI32PairToI53Checked(size_low, size_high);
+ var commandEncoder = WebGPU.getJsObject(encoderPtr);
+ var src = WebGPU.getJsObject(srcPtr);
+ var dst = WebGPU.getJsObject(dstPtr);
+ commandEncoder.copyBufferToBuffer(src, srcOffset, dst, dstOffset, size);
+}
+
+function _wgpuCommandEncoderCopyTextureToBuffer(encoderPtr, srcPtr, dstPtr, copySizePtr) {
+ encoderPtr >>>= 0;
+ srcPtr >>>= 0;
+ dstPtr >>>= 0;
+ copySizePtr >>>= 0;
+ var commandEncoder = WebGPU.getJsObject(encoderPtr);
+ var copySize = WebGPU.makeExtent3D(copySizePtr);
+ commandEncoder.copyTextureToBuffer(WebGPU.makeTexelCopyTextureInfo(srcPtr), WebGPU.makeTexelCopyBufferInfo(dstPtr), copySize);
+}
+
+function _wgpuCommandEncoderCopyTextureToTexture(encoderPtr, srcPtr, dstPtr, copySizePtr) {
+ encoderPtr >>>= 0;
+ srcPtr >>>= 0;
+ dstPtr >>>= 0;
+ copySizePtr >>>= 0;
+ var commandEncoder = WebGPU.getJsObject(encoderPtr);
+ var copySize = WebGPU.makeExtent3D(copySizePtr);
+ commandEncoder.copyTextureToTexture(WebGPU.makeTexelCopyTextureInfo(srcPtr), WebGPU.makeTexelCopyTextureInfo(dstPtr), copySize);
+}
+
+function _wgpuCommandEncoderFinish(encoderPtr, descriptor) {
+ encoderPtr >>>= 0;
+ descriptor >>>= 0;
+ // TODO: Use the descriptor.
+ var commandEncoder = WebGPU.getJsObject(encoderPtr);
+ var ptr = _emwgpuCreateCommandBuffer(0);
+ WebGPU.Internals.jsObjectInsert(ptr, commandEncoder.finish());
+ return ptr;
+}
+
+function _wgpuCommandEncoderResolveQuerySet(encoderPtr, querySetPtr, firstQuery, queryCount, destinationPtr, destinationOffset_low, destinationOffset_high) {
+ encoderPtr >>>= 0;
+ querySetPtr >>>= 0;
+ destinationPtr >>>= 0;
+ var destinationOffset = convertI32PairToI53Checked(destinationOffset_low, destinationOffset_high);
+ var commandEncoder = WebGPU.getJsObject(encoderPtr);
+ var querySet = WebGPU.getJsObject(querySetPtr);
+ var destination = WebGPU.getJsObject(destinationPtr);
+ commandEncoder.resolveQuerySet(querySet, firstQuery, queryCount, destination, destinationOffset);
+}
+
+function _wgpuComputePassEncoderDispatchWorkgroups(passPtr, x, y, z) {
+ passPtr >>>= 0;
+ var pass = WebGPU.getJsObject(passPtr);
+ pass.dispatchWorkgroups(x, y, z);
+}
+
+function _wgpuComputePassEncoderEnd(passPtr) {
+ passPtr >>>= 0;
+ var pass = WebGPU.getJsObject(passPtr);
+ pass.end();
+}
+
+function _wgpuComputePassEncoderSetBindGroup(passPtr, groupIndex, groupPtr, dynamicOffsetCount, dynamicOffsetsPtr) {
+ passPtr >>>= 0;
+ groupPtr >>>= 0;
+ dynamicOffsetCount >>>= 0;
+ dynamicOffsetsPtr >>>= 0;
+ var pass = WebGPU.getJsObject(passPtr);
+ var group = WebGPU.getJsObject(groupPtr);
+ if (dynamicOffsetCount == 0) {
+ pass.setBindGroup(groupIndex, group);
+ } else {
+ pass.setBindGroup(groupIndex, group, HEAPU32, ((dynamicOffsetsPtr) >>> 2), dynamicOffsetCount);
+ }
+}
+
+function _wgpuComputePassEncoderSetPipeline(passPtr, pipelinePtr) {
+ passPtr >>>= 0;
+ pipelinePtr >>>= 0;
+ var pass = WebGPU.getJsObject(passPtr);
+ var pipeline = WebGPU.getJsObject(pipelinePtr);
+ pass.setPipeline(pipeline);
+}
+
+var _wgpuDeviceCreateBindGroup = function(devicePtr, descriptor) {
+ devicePtr >>>= 0;
+ descriptor >>>= 0;
+ function makeEntry(entryPtr) {
+ var bufferPtr = HEAPU32[(((entryPtr) + (8)) >>> 2) >>> 0];
+ var samplerPtr = HEAPU32[(((entryPtr) + (32)) >>> 2) >>> 0];
+ var textureViewPtr = HEAPU32[(((entryPtr) + (36)) >>> 2) >>> 0];
+ var externalTexturePtr = 0;
+ WebGPU.iterateExtensions(entryPtr, {
+ 14: ptr => {
+ externalTexturePtr = HEAPU32[(((ptr) + (8)) >>> 2) >>> 0];
+ }
+ });
+ var resource;
+ if (bufferPtr) {
+ // Note the sentinel UINT64_MAX will be read as -1.
+ var size = readI53FromI64((entryPtr) + (24));
+ if (size == -1) size = undefined;
+ resource = {
+ "buffer": WebGPU.getJsObject(bufferPtr),
+ "offset": readI53FromI64((entryPtr) + (16)),
+ "size": size
+ };
+ } else {
+ resource = WebGPU.getJsObject(samplerPtr || textureViewPtr || externalTexturePtr);
+ }
+ return {
+ "binding": HEAPU32[(((entryPtr) + (4)) >>> 2) >>> 0],
+ "resource": resource
+ };
+ }
+ function makeEntries(count, entriesPtrs) {
+ var entries = [];
+ for (var i = 0; i < count; ++i) {
+ entries.push(makeEntry(entriesPtrs + 40 * i));
+ }
+ return entries;
+ }
+ var desc = {
+ "label": WebGPU.makeStringFromOptionalStringView(descriptor + 4),
+ "layout": WebGPU.getJsObject(HEAPU32[(((descriptor) + (12)) >>> 2) >>> 0]),
+ "entries": makeEntries(HEAPU32[(((descriptor) + (16)) >>> 2) >>> 0], HEAPU32[(((descriptor) + (20)) >>> 2) >>> 0])
+ };
+ var device = WebGPU.getJsObject(devicePtr);
+ var ptr = _emwgpuCreateBindGroup(0);
+ WebGPU.Internals.jsObjectInsert(ptr, device.createBindGroup(desc));
+ return ptr;
+};
+
+function _wgpuDeviceCreateBindGroupLayout(devicePtr, descriptor) {
+ devicePtr >>>= 0;
+ descriptor >>>= 0;
+ function makeBufferEntry(substructPtr) {
+ var typeInt = HEAPU32[(((substructPtr) + (4)) >>> 2) >>> 0];
+ if (!typeInt) return undefined;
+ return {
+ "type": WebGPU.BufferBindingType[typeInt],
+ "hasDynamicOffset": !!(HEAPU32[(((substructPtr) + (8)) >>> 2) >>> 0]),
+ "minBindingSize": readI53FromI64((substructPtr) + (16))
+ };
+ }
+ function makeSamplerEntry(substructPtr) {
+ var typeInt = HEAPU32[(((substructPtr) + (4)) >>> 2) >>> 0];
+ if (!typeInt) return undefined;
+ return {
+ "type": WebGPU.SamplerBindingType[typeInt]
+ };
+ }
+ function makeTextureEntry(substructPtr) {
+ var sampleTypeInt = HEAPU32[(((substructPtr) + (4)) >>> 2) >>> 0];
+ if (!sampleTypeInt) return undefined;
+ return {
+ "sampleType": WebGPU.TextureSampleType[sampleTypeInt],
+ "viewDimension": WebGPU.TextureViewDimension[HEAP32[(((substructPtr) + (8)) >>> 2) >>> 0]],
+ "multisampled": !!(HEAPU32[(((substructPtr) + (12)) >>> 2) >>> 0])
+ };
+ }
+ function makeStorageTextureEntry(substructPtr) {
+ var accessInt = HEAPU32[(((substructPtr) + (4)) >>> 2) >>> 0];
+ if (!accessInt) return undefined;
+ return {
+ "access": WebGPU.StorageTextureAccess[accessInt],
+ "format": WebGPU.TextureFormat[HEAP32[(((substructPtr) + (8)) >>> 2) >>> 0]],
+ "viewDimension": WebGPU.TextureViewDimension[HEAP32[(((substructPtr) + (12)) >>> 2) >>> 0]]
+ };
+ }
+ function makeEntry(entryPtr) {
+ var entry = {
+ "binding": HEAPU32[(((entryPtr) + (4)) >>> 2) >>> 0],
+ "visibility": HEAPU32[(((entryPtr) + (8)) >>> 2) >>> 0],
+ "buffer": makeBufferEntry(entryPtr + 24),
+ "sampler": makeSamplerEntry(entryPtr + 48),
+ "texture": makeTextureEntry(entryPtr + 56),
+ "storageTexture": makeStorageTextureEntry(entryPtr + 72)
+ };
+ WebGPU.iterateExtensions(entryPtr, {
+ 13: ptr => {
+ entry["externalTexture"] = {};
+ }
+ });
+ return entry;
+ }
+ function makeEntries(count, entriesPtrs) {
+ var entries = [];
+ for (var i = 0; i < count; ++i) {
+ entries.push(makeEntry(entriesPtrs + 88 * i));
+ }
+ return entries;
+ }
+ var desc = {
+ "label": WebGPU.makeStringFromOptionalStringView(descriptor + 4),
+ "entries": makeEntries(HEAPU32[(((descriptor) + (12)) >>> 2) >>> 0], HEAPU32[(((descriptor) + (16)) >>> 2) >>> 0])
+ };
+ var device = WebGPU.getJsObject(devicePtr);
+ var ptr = _emwgpuCreateBindGroupLayout(0);
+ WebGPU.Internals.jsObjectInsert(ptr, device.createBindGroupLayout(desc));
+ return ptr;
+}
+
+function _wgpuDeviceCreateCommandEncoder(devicePtr, descriptor) {
+ devicePtr >>>= 0;
+ descriptor >>>= 0;
+ var desc;
+ if (descriptor) {
+ desc = {
+ "label": WebGPU.makeStringFromOptionalStringView(descriptor + 4)
+ };
+ }
+ var device = WebGPU.getJsObject(devicePtr);
+ var ptr = _emwgpuCreateCommandEncoder(0);
+ WebGPU.Internals.jsObjectInsert(ptr, device.createCommandEncoder(desc));
+ return ptr;
+}
+
+function _wgpuDeviceCreateComputePipeline(devicePtr, descriptor) {
+ devicePtr >>>= 0;
+ descriptor >>>= 0;
+ var desc = WebGPU.makeComputePipelineDesc(descriptor);
+ var device = WebGPU.getJsObject(devicePtr);
+ var ptr = _emwgpuCreateComputePipeline(0);
+ WebGPU.Internals.jsObjectInsert(ptr, device.createComputePipeline(desc));
+ return ptr;
+}
+
+function _wgpuDeviceCreatePipelineLayout(devicePtr, descriptor) {
+ devicePtr >>>= 0;
+ descriptor >>>= 0;
+ var bglCount = HEAPU32[(((descriptor) + (12)) >>> 2) >>> 0];
+ var bglPtr = HEAPU32[(((descriptor) + (16)) >>> 2) >>> 0];
+ var bgls = [];
+ for (var i = 0; i < bglCount; ++i) {
+ bgls.push(WebGPU.getJsObject(HEAPU32[(((bglPtr) + (4 * i)) >>> 2) >>> 0]));
+ }
+ var desc = {
+ "label": WebGPU.makeStringFromOptionalStringView(descriptor + 4),
+ "bindGroupLayouts": bgls
+ };
+ var device = WebGPU.getJsObject(devicePtr);
+ var ptr = _emwgpuCreatePipelineLayout(0);
+ WebGPU.Internals.jsObjectInsert(ptr, device.createPipelineLayout(desc));
+ return ptr;
+}
+
+function _wgpuDeviceCreateQuerySet(devicePtr, descriptor) {
+ devicePtr >>>= 0;
+ descriptor >>>= 0;
+ var desc = {
+ "type": WebGPU.QueryType[HEAP32[(((descriptor) + (12)) >>> 2) >>> 0]],
+ "count": HEAPU32[(((descriptor) + (16)) >>> 2) >>> 0]
+ };
+ var device = WebGPU.getJsObject(devicePtr);
+ var ptr = _emwgpuCreateQuerySet(0);
+ WebGPU.Internals.jsObjectInsert(ptr, device.createQuerySet(desc));
+ return ptr;
+}
+
+function _wgpuDeviceCreateTexture(devicePtr, descriptor) {
+ devicePtr >>>= 0;
+ descriptor >>>= 0;
+ var nextInChainPtr = HEAPU32[((descriptor) >>> 2) >>> 0];
+ var textureBindingViewDimension;
+ if (nextInChainPtr !== 0) {
+ var sType = HEAP32[(((nextInChainPtr) + (4)) >>> 2) >>> 0];
+ var textureBindingViewDimensionDescriptor = nextInChainPtr;
+ textureBindingViewDimension = WebGPU.TextureViewDimension[HEAP32[(((textureBindingViewDimensionDescriptor) + (8)) >>> 2) >>> 0]];
+ }
+ var desc = {
+ "label": WebGPU.makeStringFromOptionalStringView(descriptor + 4),
+ "size": WebGPU.makeExtent3D(descriptor + 28),
+ "mipLevelCount": HEAPU32[(((descriptor) + (44)) >>> 2) >>> 0],
+ "sampleCount": HEAPU32[(((descriptor) + (48)) >>> 2) >>> 0],
+ "dimension": WebGPU.TextureDimension[HEAP32[(((descriptor) + (24)) >>> 2) >>> 0]],
+ "format": WebGPU.TextureFormat[HEAP32[(((descriptor) + (40)) >>> 2) >>> 0]],
+ "usage": HEAPU32[(((descriptor) + (16)) >>> 2) >>> 0],
+ "textureBindingViewDimension": textureBindingViewDimension
+ };
+ var viewFormatCount = HEAPU32[(((descriptor) + (52)) >>> 2) >>> 0];
+ if (viewFormatCount) {
+ var viewFormatsPtr = HEAPU32[(((descriptor) + (56)) >>> 2) >>> 0];
+ // viewFormatsPtr pointer to an array of TextureFormat which is an enum of size uint32_t
+ desc["viewFormats"] = Array.from(HEAP32.subarray((((viewFormatsPtr) >>> 2)) >>> 0, ((viewFormatsPtr + viewFormatCount * 4) >>> 2) >>> 0), format => WebGPU.TextureFormat[format]);
+ }
+ var device = WebGPU.getJsObject(devicePtr);
+ var ptr = _emwgpuCreateTexture(0);
+ WebGPU.Internals.jsObjectInsert(ptr, device.createTexture(desc));
+ return ptr;
+}
+
+function _wgpuDeviceGetAdapterInfo(devicePtr, adapterInfo) {
+ devicePtr >>>= 0;
+ adapterInfo >>>= 0;
+ var device = WebGPU.getJsObject(devicePtr);
+ WebGPU.fillAdapterInfoStruct(device.adapterInfo, adapterInfo);
+ return 1;
+}
+
+function _wgpuDeviceGetLimits(devicePtr, limitsOutPtr) {
+ devicePtr >>>= 0;
+ limitsOutPtr >>>= 0;
+ var device = WebGPU.getJsObject(devicePtr);
+ WebGPU.fillLimitStruct(device.limits, limitsOutPtr);
+ return 1;
+}
+
+function _wgpuDeviceHasFeature(devicePtr, featureEnumValue) {
+ devicePtr >>>= 0;
+ var device = WebGPU.getJsObject(devicePtr);
+ return device.features.has(WebGPU.FeatureName[featureEnumValue]);
+}
+
+var _wgpuQueueSubmit = function(queuePtr, commandCount, commands) {
+ queuePtr >>>= 0;
+ commandCount >>>= 0;
+ commands >>>= 0;
+ var queue = WebGPU.getJsObject(queuePtr);
+ var cmds = Array.from(HEAP32.subarray((((commands) >>> 2)) >>> 0, ((commands + commandCount * 4) >>> 2) >>> 0), id => WebGPU.getJsObject(id));
+ queue.submit(cmds);
+};
+
+function _wgpuQueueWriteBuffer(queuePtr, bufferPtr, bufferOffset_low, bufferOffset_high, data, size) {
+ queuePtr >>>= 0;
+ bufferPtr >>>= 0;
+ var bufferOffset = convertI32PairToI53Checked(bufferOffset_low, bufferOffset_high);
+ data >>>= 0;
+ size >>>= 0;
+ var queue = WebGPU.getJsObject(queuePtr);
+ var buffer = WebGPU.getJsObject(bufferPtr);
+ // There is a size limitation for ArrayBufferView. Work around by passing in a subarray
+ // instead of the whole heap. crbug.com/1201109
+ var subarray = HEAPU8.subarray(data >>> 0, data + size >>> 0);
+ queue.writeBuffer(buffer, bufferOffset, subarray, 0, size);
+}
+
+function _wgpuQueueWriteTexture(queuePtr, destinationPtr, data, dataSize, dataLayoutPtr, writeSizePtr) {
+ queuePtr >>>= 0;
+ destinationPtr >>>= 0;
+ data >>>= 0;
+ dataSize >>>= 0;
+ dataLayoutPtr >>>= 0;
+ writeSizePtr >>>= 0;
+ var queue = WebGPU.getJsObject(queuePtr);
+ var destination = WebGPU.makeTexelCopyTextureInfo(destinationPtr);
+ var dataLayout = WebGPU.makeTexelCopyBufferLayout(dataLayoutPtr);
+ var writeSize = WebGPU.makeExtent3D(writeSizePtr);
+ // This subarray isn't strictly necessary, but helps work around an issue
+ // where Chromium makes a copy of the entire heap. crbug.com/1134457
+ var subarray = HEAPU8.subarray(data >>> 0, data + dataSize >>> 0);
+ queue.writeTexture(destination, subarray, dataLayout, writeSize);
+}
+
+function _wgpuTextureCreateView(texturePtr, descriptor) {
+ texturePtr >>>= 0;
+ descriptor >>>= 0;
+ var desc;
+ if (descriptor) {
+ var swizzle;
+ var nextInChainPtr = HEAPU32[((descriptor) >>> 2) >>> 0];
+ if (nextInChainPtr !== 0) {
+ var sType = HEAP32[(((nextInChainPtr) + (4)) >>> 2) >>> 0];
+ var swizzleDescriptor = nextInChainPtr;
+ var swizzlePtr = swizzleDescriptor + 8;
+ var r = WebGPU.ComponentSwizzle[HEAP32[((swizzlePtr) >>> 2) >>> 0]] || "r";
+ var g = WebGPU.ComponentSwizzle[HEAP32[(((swizzlePtr) + (4)) >>> 2) >>> 0]] || "g";
+ var b = WebGPU.ComponentSwizzle[HEAP32[(((swizzlePtr) + (8)) >>> 2) >>> 0]] || "b";
+ var a = WebGPU.ComponentSwizzle[HEAP32[(((swizzlePtr) + (12)) >>> 2) >>> 0]] || "a";
+ swizzle = `${r}${g}${b}${a}`;
+ }
+ var mipLevelCount = HEAPU32[(((descriptor) + (24)) >>> 2) >>> 0];
+ var arrayLayerCount = HEAPU32[(((descriptor) + (32)) >>> 2) >>> 0];
+ desc = {
+ "label": WebGPU.makeStringFromOptionalStringView(descriptor + 4),
+ "format": WebGPU.TextureFormat[HEAP32[(((descriptor) + (12)) >>> 2) >>> 0]],
+ "dimension": WebGPU.TextureViewDimension[HEAP32[(((descriptor) + (16)) >>> 2) >>> 0]],
+ "baseMipLevel": HEAPU32[(((descriptor) + (20)) >>> 2) >>> 0],
+ "mipLevelCount": mipLevelCount === 4294967295 ? undefined : mipLevelCount,
+ "baseArrayLayer": HEAPU32[(((descriptor) + (28)) >>> 2) >>> 0],
+ "arrayLayerCount": arrayLayerCount === 4294967295 ? undefined : arrayLayerCount,
+ "aspect": WebGPU.TextureAspect[HEAP32[(((descriptor) + (36)) >>> 2) >>> 0]],
+ "usage": HEAPU32[(((descriptor) + (40)) >>> 2) >>> 0],
+ "swizzle": swizzle
+ };
+ }
+ var texture = WebGPU.getJsObject(texturePtr);
+ var ptr = _emwgpuCreateTextureView(0);
+ WebGPU.Internals.jsObjectInsert(ptr, texture.createView(desc));
+ return ptr;
+}
+
+function _wgpuTextureDestroy(texturePtr) {
+ texturePtr >>>= 0;
+ WebGPU.getJsObject(texturePtr).destroy();
+}
+
+function _wgpuTextureGetDepthOrArrayLayers(texturePtr) {
+ texturePtr >>>= 0;
+ var texture = WebGPU.getJsObject(texturePtr);
+ return texture.depthOrArrayLayers;
+}
+
+function _wgpuTextureGetFormat(texturePtr) {
+ texturePtr >>>= 0;
+ var texture = WebGPU.getJsObject(texturePtr);
+ // Should return the enum integer instead of string.
+ return WebGPU.TextureFormat.indexOf(texture.format);
+}
+
+function _wgpuTextureGetHeight(texturePtr) {
+ texturePtr >>>= 0;
+ var texture = WebGPU.getJsObject(texturePtr);
+ return texture.height;
+}
+
+function _wgpuTextureGetWidth(texturePtr) {
+ texturePtr >>>= 0;
+ var texture = WebGPU.getJsObject(texturePtr);
+ return texture.width;
+}
+
+var getCFunc = ident => {
+ var func = Module["_" + ident];
+ // closure exported function
+ return func;
+};
+
+var writeArrayToMemory = (array, buffer) => {
+ HEAP8.set(array, buffer >>> 0);
+};
+
+/**
+ * @param {string|null=} returnType
+ * @param {Array=} argTypes
+ * @param {Array=} args
+ * @param {Object=} opts
+ */ var ccall = (ident, returnType, argTypes, args, opts) => {
+ // For fast lookup of conversion functions
+ var toC = {
+ "string": str => {
+ var ret = 0;
+ if (str !== null && str !== undefined && str !== 0) {
+ // null string
+ ret = stringToUTF8OnStack(str);
+ }
+ return ret;
+ },
+ "array": arr => {
+ var ret = stackAlloc(arr.length);
+ writeArrayToMemory(arr, ret);
+ return ret;
+ }
+ };
+ function convertReturnValue(ret) {
+ if (returnType === "string") {
+ return UTF8ToString(ret);
+ }
+ if (returnType === "pointer") return ret >>> 0;
+ if (returnType === "boolean") return Boolean(ret);
+ return ret;
+ }
+ var func = getCFunc(ident);
+ var cArgs = [];
+ var stack = 0;
+ if (args) {
+ for (var i = 0; i < args.length; i++) {
+ var converter = toC[argTypes[i]];
+ if (converter) {
+ if (stack === 0) stack = stackSave();
+ cArgs[i] = converter(args[i]);
+ } else {
+ cArgs[i] = args[i];
+ }
+ }
+ }
+ // Data for a previous async operation that was in flight before us.
+ var previousAsync = Asyncify.currData;
+ var ret = func(...cArgs);
+ function onDone(ret) {
+ runtimeKeepalivePop();
+ if (stack !== 0) stackRestore(stack);
+ return convertReturnValue(ret);
+ }
+ var asyncMode = opts?.async;
+ // Keep the runtime alive through all calls. Note that this call might not be
+ // async, but for simplicity we push and pop in all calls.
+ runtimeKeepalivePush();
+ if (Asyncify.currData != previousAsync) {
+ // This is a new async operation. The wasm is paused and has unwound its stack.
+ // We need to return a Promise that resolves the return value
+ // once the stack is rewound and execution finishes.
+ return Asyncify.whenDone().then(onDone);
+ }
+ ret = onDone(ret);
+ // If this is an async ccall, ensure we return a promise
+ if (asyncMode) return Promise.resolve(ret);
+ return ret;
+};
+
+var FS_createPath = (...args) => FS.createPath(...args);
+
+var FS_unlink = (...args) => FS.unlink(...args);
+
+var FS_createLazyFile = (...args) => FS.createLazyFile(...args);
+
+var FS_createDevice = (...args) => FS.createDevice(...args);
+
+FS.createPreloadedFile = FS_createPreloadedFile;
+
+FS.preloadFile = FS_preloadFile;
+
+FS.staticInit();
+
+// Signal GL rendering layer that processing of a new frame is about to
+// start. This helps it optimize VBO double-buffering and reduce GPU stalls.
+registerPreMainLoop(() => GL.newRenderingFrameStarted());
+
+// End JS library code
+// include: postlibrary.js
+// This file is included after the automatically-generated JS library code
+// but before the wasm module is created.
+{
+ // Begin ATMODULES hooks
+ if (Module["preloadPlugins"]) preloadPlugins = Module["preloadPlugins"];
+ if (Module["noExitRuntime"]) noExitRuntime = Module["noExitRuntime"];
+ if (Module["print"]) out = Module["print"];
+ if (Module["printErr"]) err = Module["printErr"];
+ if (Module["wasmBinary"]) wasmBinary = Module["wasmBinary"];
+ // End ATMODULES hooks
+ if (Module["arguments"]) arguments_ = Module["arguments"];
+ if (Module["thisProgram"]) thisProgram = Module["thisProgram"];
+ if (Module["preInit"]) {
+ if (typeof Module["preInit"] == "function") Module["preInit"] = [ Module["preInit"] ];
+ while (Module["preInit"].length > 0) {
+ Module["preInit"].shift()();
+ }
+ }
+}
+
+// Begin runtime exports
+Module["addRunDependency"] = addRunDependency;
+
+Module["removeRunDependency"] = removeRunDependency;
+
+Module["ccall"] = ccall;
+
+Module["stringToNewUTF8"] = stringToNewUTF8;
+
+Module["FS_preloadFile"] = FS_preloadFile;
+
+Module["FS_unlink"] = FS_unlink;
+
+Module["FS_createPath"] = FS_createPath;
+
+Module["FS_createDevice"] = FS_createDevice;
+
+Module["FS_createDataFile"] = FS_createDataFile;
+
+Module["FS_createLazyFile"] = FS_createLazyFile;
+
+// End runtime exports
+// Begin JS library exports
+// End JS library exports
+// end include: postlibrary.js
+var ASM_CONSTS = {
+ 2019768: () => !!Module["preinitializedWebGPUDevice"],
+ 2019819: () => {
+ const retVal = Module.LLM_CANCEL_FLAG;
+ Module.LLM_CANCEL_FLAG = undefined;
+ return retVal || 0;
+ },
+ 2019918: $0 => {
+ const device = WebGPU.getJsObject($0);
+ return device.features.has("subgroups");
+ },
+ 2020002: () => !!Module["preinitializedWebGPUDevice"],
+ 2020053: () => {
+ specialHTMLTargets["#canvas"] = Module.canvas;
+ }
+};
+
+function __asyncjs__InvokeReadDataFn(fn, offset, size, mode) {
+ return Asyncify.handleAsync(async () => await Emval.toValue(fn)(offset, size, mode));
+}
+
+function JsProgressListener(text, done) {
+ Module._userProgressListener(UTF8ToString(text), done);
+}
+
+function DefaultErrorReporter(message) {
+ throw new Error(UTF8ToString(message));
+}
+
+function ThrowError(val_handle) {
+ const error = Emval.toValue(val_handle);
+ throw error;
+}
+
+function JsOnEmptyPacketListener(output_stream_name, timestamp) {
+ Module._wrapEmptyPacketListenerOutput(output_stream_name, timestamp);
+}
+
+function JsOnVectorFinishedListener(output_stream_name, timestamp) {
+ Module._wrapSimpleListenerOutput(output_stream_name, undefined, true, timestamp);
+}
+
+function JsOnSimpleListenerBool(output_stream_name, out_data, timestamp) {
+ Module._wrapSimpleListenerOutput(output_stream_name, out_data, timestamp);
+}
+
+function JsOnVectorListenerBool(output_stream_name, out_data, timestamp) {
+ Module._wrapSimpleListenerOutput(output_stream_name, out_data, false, timestamp);
+}
+
+function JsOnSimpleListenerInt(output_stream_name, out_data, timestamp) {
+ Module._wrapSimpleListenerOutput(output_stream_name, out_data, timestamp);
+}
+
+function JsOnVectorListenerInt(output_stream_name, out_data, timestamp) {
+ Module._wrapSimpleListenerOutput(output_stream_name, out_data, false, timestamp);
+}
+
+function JsOnSimpleListenerUint(output_stream_name, out_data, timestamp) {
+ Module._wrapSimpleListenerOutput(output_stream_name, out_data, timestamp);
+}
+
+function JsOnVectorListenerUint(output_stream_name, out_data, timestamp) {
+ Module._wrapSimpleListenerOutput(output_stream_name, out_data, false, timestamp);
+}
+
+function JsOnSimpleListenerDouble(output_stream_name, out_data, timestamp) {
+ Module._wrapSimpleListenerOutput(output_stream_name, out_data, timestamp);
+}
+
+function JsOnVectorListenerDouble(output_stream_name, out_data, timestamp) {
+ Module._wrapSimpleListenerOutput(output_stream_name, out_data, false, timestamp);
+}
+
+function JsOnSimpleListenerFloat(output_stream_name, out_data, timestamp) {
+ Module._wrapSimpleListenerOutput(output_stream_name, out_data, timestamp);
+}
+
+function JsOnVectorListenerFloat(output_stream_name, out_data, timestamp) {
+ Module._wrapSimpleListenerOutput(output_stream_name, out_data, false, timestamp);
+}
+
+function JsOnSimpleListenerString(output_stream_name, out_data, timestamp) {
+ Module._wrapSimpleListenerOutput(output_stream_name, UTF8ToString(out_data), timestamp);
+}
+
+function JsOnVectorListenerString(output_stream_name, out_data, timestamp) {
+ Module._wrapSimpleListenerOutput(output_stream_name, UTF8ToString(out_data), false, timestamp);
+}
+
+function JsOnVectorListenerProto(output_stream_name, proto_ptr, proto_size, make_deep_copy, timestamp) {
+ const newProtoArray = make_deep_copy ? Module.HEAPU8.slice(proto_ptr, proto_ptr + proto_size) : new Uint8Array(Module.HEAPU8.buffer, proto_ptr, proto_size);
+ Module._wrapSimpleListenerOutput(output_stream_name, newProtoArray, false, timestamp);
+}
+
+function JsWrapSimpleListeners() {
+ if (!Module._wrapSimpleListenerOutput) {
+ Module._wrapSimpleListenerOutput = (outputStreamName, ...args) => {
+ if (Module.simpleListeners) {
+ const streamName = UTF8ToString(outputStreamName);
+ if (Module.simpleListeners[streamName]) {
+ Module.simpleListeners[streamName](...args);
+ }
+ }
+ };
+ }
+ if (!Module._wrapEmptyPacketListenerOutput) {
+ Module._wrapEmptyPacketListenerOutput = (outputStreamName, timestamp) => {
+ if (Module.emptyPacketListeners) {
+ const streamName = UTF8ToString(outputStreamName);
+ if (Module.emptyPacketListeners[streamName]) {
+ Module.emptyPacketListeners[streamName](timestamp);
+ }
+ }
+ };
+ }
+}
+
+function JsOnSimpleListenerBinaryArray(output_stream_name, binary_ptr, binary_size, make_deep_copy, timestamp) {
+ const newProtoArray = make_deep_copy ? Module.HEAPU8.slice(binary_ptr, binary_ptr + binary_size) : new Uint8Array(Module.HEAPU8.buffer, binary_ptr, binary_size);
+ Module._wrapSimpleListenerOutput(output_stream_name, newProtoArray, timestamp);
+}
+
+function __asyncjs__CallReadDataFn(fn, offset, size, mode) {
+ return Asyncify.handleAsync(async () => await Emval.toValue(fn)(offset, size, mode));
+}
+
+function __asyncjs__mediapipe_map_buffer_jspi(buffer_handle, data) {
+ return Asyncify.handleAsync(async () => {
+ const buffer = WebGPU.getJsObject(buffer_handle);
+ if ("mapSync" in buffer) {
+ buffer.mapSync(GPUMapMode.READ);
+ } else {
+ await buffer.mapAsync(GPUMapMode.READ);
+ }
+ const mapped = buffer.getMappedRange();
+ HEAPU8.set(new Uint8Array(mapped), data >>> 0);
+ buffer.unmap();
+ });
+}
+
+function JsGetDeviceMinSubgroupSize(deviceId) {
+ const device = WebGPU.getJsObject(deviceId);
+ return device.adapterInfo.subgroupMinSize || device.limits.minSubgroupSize;
+}
+
+function JsGetDeviceMaxSubgroupSize(deviceId) {
+ const device = WebGPU.getJsObject(deviceId);
+ return device.adapterInfo.subgroupMaxSize || device.limits.maxSubgroupSize;
+}
+
+function __asyncjs__ReadBufferDataJs(buffer_handle, data_ptr) {
+ return Asyncify.handleAsync(async () => {
+ const gpuReadBuffer = WebGPU.getJsObject(buffer_handle);
+ await gpuReadBuffer.mapAsync(GPUMapMode.READ);
+ const arrayBuffer = gpuReadBuffer.getMappedRange();
+ const u8view = new Uint8Array(arrayBuffer);
+ HEAPU8.set(u8view, data_ptr >>> 0 >>> 0);
+ gpuReadBuffer.unmap();
+ });
+}
+
+function GetAdapterArchitecture() {
+ const device = Module["preinitializedWebGPUDevice"];
+ const architecture = device.adapterInfo ? device.adapterInfo.architecture : "Unknown";
+ return stringToNewUTF8(architecture);
+}
+
+function GetAdapterDescription() {
+ const device = Module["preinitializedWebGPUDevice"];
+ const description = device.adapterInfo ? device.adapterInfo.description : "Unknown";
+ return stringToNewUTF8(description);
+}
+
+function GetAdapterDeviceName() {
+ const device = Module["preinitializedWebGPUDevice"];
+ const deviceName = device.adapterInfo ? device.adapterInfo.device : "Unknown";
+ return stringToNewUTF8(deviceName);
+}
+
+function GetAdapterVendor() {
+ const device = Module["preinitializedWebGPUDevice"];
+ const vendor = device.adapterInfo ? device.adapterInfo.vendor : "Unknown";
+ return stringToNewUTF8(vendor);
+}
+
+function hardware_concurrency() {
+ var concurrency = 1;
+ try {
+ concurrency = self.navigator.hardwareConcurrency;
+ } catch (e) {}
+ return concurrency;
+}
+
+function JsWrapErrorListener(code, message) {
+ if (Module.errorListener) {
+ const stringMessage = UTF8ToString(message);
+ Module.errorListener(code, stringMessage);
+ }
+}
+
+function UseBottomLeftGpuOrigin() {
+ return (Module && Module.gpuOriginForWebTexturesIsBottomLeft);
+}
+
+function custom_emscripten_dbgn(str, len) {
+ if (typeof (dbg) !== "undefined") {
+ dbg(UTF8ToString(str, len));
+ } else {
+ if (typeof (custom_dbg) === "undefined") {
+ function custom_dbg(text) {
+ console.warn.apply(console, arguments);
+ }
+ }
+ custom_dbg(UTF8ToString(str, len));
+ }
+}
+
+// Imports from the Wasm binary.
+var _free, _CreateLlmInferenceEngineConverted, _DeleteLlmInferenceEngine, _MakeSessionForPredict, _AddTextQueryChunk, _AddImageQueryChunk, _AddAudioQueryChunk, _malloc, _PredictSession, _FreeSession, _GetSizeInTokens, _wgpuDeviceAddRef, _registerModelResourcesGraphService, _bindTextureToStream, _addBoundTextureToStream, _addDoubleToInputStream, _addFloatToInputStream, _addBoolToInputStream, _addIntToInputStream, _addUintToInputStream, _addStringToInputStream, _addRawDataSpanToInputStream, _allocateBoolVector, _allocateFloatVector, _allocateDoubleVector, _allocateIntVector, _allocateUintVector, _allocateStringVector, _addBoolVectorEntry, _addFloatVectorEntry, _addDoubleVectorEntry, _addIntVectorEntry, _addUintVectorEntry, _addStringVectorEntry, _addBoolVectorToInputStream, _addFloatVectorToInputStream, _addDoubleVectorToInputStream, _addIntVectorToInputStream, _addUintVectorToInputStream, _addStringVectorToInputStream, _addFlatHashMapToInputStream, _addProtoToInputStream, _addEmptyPacketToInputStream, _addBoolToInputSidePacket, _addDoubleToInputSidePacket, _addFloatToInputSidePacket, _addIntToInputSidePacket, _addUintToInputSidePacket, _addStringToInputSidePacket, _addRawDataSpanToInputSidePacket, _addProtoToInputSidePacket, _addBoolVectorToInputSidePacket, _addDoubleVectorToInputSidePacket, _addFloatVectorToInputSidePacket, _addIntVectorToInputSidePacket, _addUintVectorToInputSidePacket, _addStringVectorToInputSidePacket, _attachBoolListener, _attachBoolVectorListener, _attachDoubleListener, _attachDoubleVectorListener, _attachFloatListener, _attachFloatVectorListener, _attachIntListener, _attachIntVectorListener, _attachUintListener, _attachUintVectorListener, _attachStringListener, _attachStringVectorListener, _attachProtoListener, _attachProtoVectorListener, _getGraphConfig, ___getTypeName, _emwgpuCreateBindGroup, _emwgpuCreateBindGroupLayout, _emwgpuCreateCommandBuffer, _emwgpuCreateCommandEncoder, _emwgpuCreateComputePassEncoder, _emwgpuCreateComputePipeline, _emwgpuCreateExternalTexture, _emwgpuCreatePipelineLayout, _emwgpuCreateQuerySet, _emwgpuCreateRenderBundle, _emwgpuCreateRenderBundleEncoder, _emwgpuCreateRenderPassEncoder, _emwgpuCreateRenderPipeline, _emwgpuCreateSampler, _emwgpuCreateSurface, _emwgpuCreateTexture, _emwgpuCreateTextureView, _emwgpuCreateAdapter, _emwgpuImportBuffer, _emwgpuCreateDevice, _emwgpuCreateQueue, _emwgpuCreateShaderModule, _emwgpuOnCreateComputePipelineCompleted, _emwgpuOnWorkDoneCompleted, _clearSubgraphs, _pushBinarySubgraph, _pushTextSubgraph, _changeBinaryGraph, _changeTextGraph, _processGl, _process, _bindTextureToCanvas, _requestShaderRefreshOnGraphChange, _waitUntilIdle, _closeGraph, _setAutoRenderToScreen, _emscripten_builtin_memalign, _memalign, __emscripten_tempret_set, __emscripten_stack_restore, __emscripten_stack_alloc, _emscripten_stack_get_current, dynCall_vii, dynCall_viiiiiii, dynCall_viiiiii, dynCall_v, dynCall_ii, dynCall_vi, dynCall_iiiii, dynCall_iii, dynCall_viii, dynCall_i, dynCall_ji, dynCall_iiii, dynCall_viiii, dynCall_viiiii, dynCall_jii, dynCall_iiiijij, dynCall_ff, dynCall_did, dynCall_iiiiiii, dynCall_iiiiii, dynCall_iiiiiiiiiii, dynCall_iiiiiiiiiiii, dynCall_viji, dynCall_vijiii, dynCall_iiiiiiiii, dynCall_viiiiiiii, dynCall_iiiif, dynCall_viiiiiiiiiiiiiii, dynCall_viff, dynCall_viiffii, dynCall_viiffi, dynCall_viiiiiiiiii, dynCall_fi, dynCall_viiffff, dynCall_viiiiij, dynCall_vij, dynCall_viiiiiffii, dynCall_vif, dynCall_ddd, dynCall_dddd, dynCall_idd, dynCall_di, dynCall_jiiiijiiiii, dynCall_viiij, dynCall_viid, dynCall_vidd, dynCall_vifd, dynCall_viiiiiiiiiii, dynCall_iiif, dynCall_jiii, dynCall_viijj, dynCall_iiiiiiii, dynCall_iiiiiiiiii, dynCall_iij, dynCall_iiiijj, dynCall_viiijjj, dynCall_fff, dynCall_viifii, dynCall_fii, dynCall_jjj, dynCall_fiii, dynCall_viiiiiiiii, dynCall_viiiffii, dynCall_iiiiiffi, dynCall_viiiiiff, dynCall_viiiiiiiiiiiii, dynCall_viiiiiiiiiiii, dynCall_viiiiiiiiiiiiiiiii, dynCall_iifff, dynCall_iiff, dynCall_iiifiii, dynCall_iiffi, dynCall_iiffii, dynCall_viiiiiiiiiiiiii, dynCall_iif, dynCall_viijii, dynCall_iiiji, dynCall_viiif, dynCall_viiifiii, dynCall_fiif, dynCall_iiiifi, dynCall_iiiifiii, dynCall_iiifi, dynCall_viiiif, dynCall_viiiifii, dynCall_dii, dynCall_vifi, dynCall_vidi, dynCall_viiiji, dynCall_viiji, dynCall_vijjj, dynCall_vj, dynCall_viij, dynCall_jiji, dynCall_iidiiii, dynCall_iiiiij, dynCall_iiiiid, dynCall_iiiiijj, dynCall_iiiiiijj, _asyncify_start_unwind, _asyncify_stop_unwind, _asyncify_start_rewind, _asyncify_stop_rewind, memory, _kVersionStampBuildChangelistStr, _kVersionStampCitcSnapshotStr, _kVersionStampCitcWorkspaceIdStr, _kVersionStampSourceUriStr, _kVersionStampBuildClientStr, _kVersionStampBuildClientMintStatusStr, _kVersionStampBuildCompilerStr, _kVersionStampBuildDateTimePstStr, _kVersionStampBuildDepotPathStr, _kVersionStampBuildIdStr, _kVersionStampBuildInfoStr, _kVersionStampBuildLabelStr, _kVersionStampBuildTargetStr, _kVersionStampBuildTimestampStr, _kVersionStampBuildToolStr, _kVersionStampG3BuildTargetStr, _kVersionStampVerifiableStr, _kVersionStampBuildFdoTypeStr, _kVersionStampBuildBaselineChangelistStr, _kVersionStampBuildLtoTypeStr, _kVersionStampBuildPropellerTypeStr, _kVersionStampBuildPghoTypeStr, _kVersionStampBuildUsernameStr, _kVersionStampBuildHostnameStr, _kVersionStampBuildDirectoryStr, _kVersionStampBuildChangelistInt, _kVersionStampCitcSnapshotInt, _kVersionStampBuildClientMintStatusInt, _kVersionStampBuildTimestampInt, _kVersionStampVerifiableInt, _kVersionStampBuildCoverageEnabledInt, _kVersionStampBuildBaselineChangelistInt, _kVersionStampPrecookedTimestampStr, _kVersionStampPrecookedClientInfoStr, __indirect_function_table, wasmMemory;
+
+function assignWasmExports(wasmExports) {
+ _free = Module["_free"] = wasmExports["ad"];
+ _CreateLlmInferenceEngineConverted = Module["_CreateLlmInferenceEngineConverted"] = wasmExports["bd"];
+ _DeleteLlmInferenceEngine = Module["_DeleteLlmInferenceEngine"] = wasmExports["cd"];
+ _MakeSessionForPredict = Module["_MakeSessionForPredict"] = wasmExports["dd"];
+ _AddTextQueryChunk = Module["_AddTextQueryChunk"] = wasmExports["ed"];
+ _AddImageQueryChunk = Module["_AddImageQueryChunk"] = wasmExports["fd"];
+ _AddAudioQueryChunk = Module["_AddAudioQueryChunk"] = wasmExports["gd"];
+ _malloc = Module["_malloc"] = wasmExports["hd"];
+ _PredictSession = Module["_PredictSession"] = wasmExports["id"];
+ _FreeSession = Module["_FreeSession"] = wasmExports["jd"];
+ _GetSizeInTokens = Module["_GetSizeInTokens"] = wasmExports["kd"];
+ _wgpuDeviceAddRef = wasmExports["ld"];
+ _registerModelResourcesGraphService = Module["_registerModelResourcesGraphService"] = wasmExports["md"];
+ _bindTextureToStream = Module["_bindTextureToStream"] = wasmExports["nd"];
+ _addBoundTextureToStream = Module["_addBoundTextureToStream"] = wasmExports["od"];
+ _addDoubleToInputStream = Module["_addDoubleToInputStream"] = wasmExports["pd"];
+ _addFloatToInputStream = Module["_addFloatToInputStream"] = wasmExports["qd"];
+ _addBoolToInputStream = Module["_addBoolToInputStream"] = wasmExports["rd"];
+ _addIntToInputStream = Module["_addIntToInputStream"] = wasmExports["sd"];
+ _addUintToInputStream = Module["_addUintToInputStream"] = wasmExports["td"];
+ _addStringToInputStream = Module["_addStringToInputStream"] = wasmExports["ud"];
+ _addRawDataSpanToInputStream = Module["_addRawDataSpanToInputStream"] = wasmExports["vd"];
+ _allocateBoolVector = Module["_allocateBoolVector"] = wasmExports["wd"];
+ _allocateFloatVector = Module["_allocateFloatVector"] = wasmExports["xd"];
+ _allocateDoubleVector = Module["_allocateDoubleVector"] = wasmExports["yd"];
+ _allocateIntVector = Module["_allocateIntVector"] = wasmExports["zd"];
+ _allocateUintVector = Module["_allocateUintVector"] = wasmExports["Ad"];
+ _allocateStringVector = Module["_allocateStringVector"] = wasmExports["Bd"];
+ _addBoolVectorEntry = Module["_addBoolVectorEntry"] = wasmExports["Cd"];
+ _addFloatVectorEntry = Module["_addFloatVectorEntry"] = wasmExports["Dd"];
+ _addDoubleVectorEntry = Module["_addDoubleVectorEntry"] = wasmExports["Ed"];
+ _addIntVectorEntry = Module["_addIntVectorEntry"] = wasmExports["Fd"];
+ _addUintVectorEntry = Module["_addUintVectorEntry"] = wasmExports["Gd"];
+ _addStringVectorEntry = Module["_addStringVectorEntry"] = wasmExports["Hd"];
+ _addBoolVectorToInputStream = Module["_addBoolVectorToInputStream"] = wasmExports["Id"];
+ _addFloatVectorToInputStream = Module["_addFloatVectorToInputStream"] = wasmExports["Jd"];
+ _addDoubleVectorToInputStream = Module["_addDoubleVectorToInputStream"] = wasmExports["Kd"];
+ _addIntVectorToInputStream = Module["_addIntVectorToInputStream"] = wasmExports["Ld"];
+ _addUintVectorToInputStream = Module["_addUintVectorToInputStream"] = wasmExports["Md"];
+ _addStringVectorToInputStream = Module["_addStringVectorToInputStream"] = wasmExports["Nd"];
+ _addFlatHashMapToInputStream = Module["_addFlatHashMapToInputStream"] = wasmExports["Od"];
+ _addProtoToInputStream = Module["_addProtoToInputStream"] = wasmExports["Pd"];
+ _addEmptyPacketToInputStream = Module["_addEmptyPacketToInputStream"] = wasmExports["Qd"];
+ _addBoolToInputSidePacket = Module["_addBoolToInputSidePacket"] = wasmExports["Rd"];
+ _addDoubleToInputSidePacket = Module["_addDoubleToInputSidePacket"] = wasmExports["Sd"];
+ _addFloatToInputSidePacket = Module["_addFloatToInputSidePacket"] = wasmExports["Td"];
+ _addIntToInputSidePacket = Module["_addIntToInputSidePacket"] = wasmExports["Ud"];
+ _addUintToInputSidePacket = Module["_addUintToInputSidePacket"] = wasmExports["Vd"];
+ _addStringToInputSidePacket = Module["_addStringToInputSidePacket"] = wasmExports["Wd"];
+ _addRawDataSpanToInputSidePacket = Module["_addRawDataSpanToInputSidePacket"] = wasmExports["Xd"];
+ _addProtoToInputSidePacket = Module["_addProtoToInputSidePacket"] = wasmExports["Yd"];
+ _addBoolVectorToInputSidePacket = Module["_addBoolVectorToInputSidePacket"] = wasmExports["Zd"];
+ _addDoubleVectorToInputSidePacket = Module["_addDoubleVectorToInputSidePacket"] = wasmExports["_d"];
+ _addFloatVectorToInputSidePacket = Module["_addFloatVectorToInputSidePacket"] = wasmExports["$d"];
+ _addIntVectorToInputSidePacket = Module["_addIntVectorToInputSidePacket"] = wasmExports["ae"];
+ _addUintVectorToInputSidePacket = Module["_addUintVectorToInputSidePacket"] = wasmExports["be"];
+ _addStringVectorToInputSidePacket = Module["_addStringVectorToInputSidePacket"] = wasmExports["ce"];
+ _attachBoolListener = Module["_attachBoolListener"] = wasmExports["de"];
+ _attachBoolVectorListener = Module["_attachBoolVectorListener"] = wasmExports["ee"];
+ _attachDoubleListener = Module["_attachDoubleListener"] = wasmExports["fe"];
+ _attachDoubleVectorListener = Module["_attachDoubleVectorListener"] = wasmExports["ge"];
+ _attachFloatListener = Module["_attachFloatListener"] = wasmExports["he"];
+ _attachFloatVectorListener = Module["_attachFloatVectorListener"] = wasmExports["ie"];
+ _attachIntListener = Module["_attachIntListener"] = wasmExports["je"];
+ _attachIntVectorListener = Module["_attachIntVectorListener"] = wasmExports["ke"];
+ _attachUintListener = Module["_attachUintListener"] = wasmExports["le"];
+ _attachUintVectorListener = Module["_attachUintVectorListener"] = wasmExports["me"];
+ _attachStringListener = Module["_attachStringListener"] = wasmExports["ne"];
+ _attachStringVectorListener = Module["_attachStringVectorListener"] = wasmExports["oe"];
+ _attachProtoListener = Module["_attachProtoListener"] = wasmExports["pe"];
+ _attachProtoVectorListener = Module["_attachProtoVectorListener"] = wasmExports["qe"];
+ _getGraphConfig = Module["_getGraphConfig"] = wasmExports["re"];
+ ___getTypeName = wasmExports["se"];
+ _emwgpuCreateBindGroup = wasmExports["te"];
+ _emwgpuCreateBindGroupLayout = wasmExports["ue"];
+ _emwgpuCreateCommandBuffer = wasmExports["ve"];
+ _emwgpuCreateCommandEncoder = wasmExports["we"];
+ _emwgpuCreateComputePassEncoder = wasmExports["xe"];
+ _emwgpuCreateComputePipeline = wasmExports["ye"];
+ _emwgpuCreateExternalTexture = wasmExports["ze"];
+ _emwgpuCreatePipelineLayout = wasmExports["Ae"];
+ _emwgpuCreateQuerySet = wasmExports["Be"];
+ _emwgpuCreateRenderBundle = wasmExports["Ce"];
+ _emwgpuCreateRenderBundleEncoder = wasmExports["De"];
+ _emwgpuCreateRenderPassEncoder = wasmExports["Ee"];
+ _emwgpuCreateRenderPipeline = wasmExports["Fe"];
+ _emwgpuCreateSampler = wasmExports["Ge"];
+ _emwgpuCreateSurface = wasmExports["He"];
+ _emwgpuCreateTexture = wasmExports["Ie"];
+ _emwgpuCreateTextureView = wasmExports["Je"];
+ _emwgpuCreateAdapter = wasmExports["Ke"];
+ _emwgpuImportBuffer = wasmExports["Le"];
+ _emwgpuCreateDevice = wasmExports["Me"];
+ _emwgpuCreateQueue = wasmExports["Ne"];
+ _emwgpuCreateShaderModule = wasmExports["Oe"];
+ _emwgpuOnCreateComputePipelineCompleted = wasmExports["Pe"];
+ _emwgpuOnWorkDoneCompleted = wasmExports["Qe"];
+ _clearSubgraphs = Module["_clearSubgraphs"] = wasmExports["Re"];
+ _pushBinarySubgraph = Module["_pushBinarySubgraph"] = wasmExports["Se"];
+ _pushTextSubgraph = Module["_pushTextSubgraph"] = wasmExports["Te"];
+ _changeBinaryGraph = Module["_changeBinaryGraph"] = wasmExports["Ue"];
+ _changeTextGraph = Module["_changeTextGraph"] = wasmExports["Ve"];
+ _processGl = Module["_processGl"] = wasmExports["We"];
+ _process = Module["_process"] = wasmExports["Xe"];
+ _bindTextureToCanvas = Module["_bindTextureToCanvas"] = wasmExports["Ye"];
+ _requestShaderRefreshOnGraphChange = Module["_requestShaderRefreshOnGraphChange"] = wasmExports["Ze"];
+ _waitUntilIdle = Module["_waitUntilIdle"] = wasmExports["_e"];
+ _closeGraph = Module["_closeGraph"] = wasmExports["$e"];
+ _setAutoRenderToScreen = Module["_setAutoRenderToScreen"] = wasmExports["af"];
+ _emscripten_builtin_memalign = wasmExports["bf"];
+ _memalign = wasmExports["cf"];
+ __emscripten_tempret_set = wasmExports["df"];
+ __emscripten_stack_restore = wasmExports["ef"];
+ __emscripten_stack_alloc = wasmExports["ff"];
+ _emscripten_stack_get_current = wasmExports["gf"];
+ dynCall_vii = dynCalls["vii"] = wasmExports["hf"];
+ dynCall_viiiiiii = dynCalls["viiiiiii"] = wasmExports["jf"];
+ dynCall_viiiiii = dynCalls["viiiiii"] = wasmExports["kf"];
+ dynCall_v = dynCalls["v"] = wasmExports["lf"];
+ dynCall_ii = dynCalls["ii"] = wasmExports["mf"];
+ dynCall_vi = dynCalls["vi"] = wasmExports["nf"];
+ dynCall_iiiii = dynCalls["iiiii"] = wasmExports["of"];
+ dynCall_iii = dynCalls["iii"] = wasmExports["pf"];
+ dynCall_viii = dynCalls["viii"] = wasmExports["qf"];
+ dynCall_i = dynCalls["i"] = wasmExports["rf"];
+ dynCall_ji = dynCalls["ji"] = wasmExports["sf"];
+ dynCall_iiii = dynCalls["iiii"] = wasmExports["tf"];
+ dynCall_viiii = dynCalls["viiii"] = wasmExports["uf"];
+ dynCall_viiiii = dynCalls["viiiii"] = wasmExports["vf"];
+ dynCall_jii = dynCalls["jii"] = wasmExports["wf"];
+ dynCall_iiiijij = dynCalls["iiiijij"] = wasmExports["xf"];
+ dynCall_ff = dynCalls["ff"] = wasmExports["yf"];
+ dynCall_did = dynCalls["did"] = wasmExports["zf"];
+ dynCall_iiiiiii = dynCalls["iiiiiii"] = wasmExports["Af"];
+ dynCall_iiiiii = dynCalls["iiiiii"] = wasmExports["Bf"];
+ dynCall_iiiiiiiiiii = dynCalls["iiiiiiiiiii"] = wasmExports["Cf"];
+ dynCall_iiiiiiiiiiii = dynCalls["iiiiiiiiiiii"] = wasmExports["Df"];
+ dynCall_viji = dynCalls["viji"] = wasmExports["Ef"];
+ dynCall_vijiii = dynCalls["vijiii"] = wasmExports["Ff"];
+ dynCall_iiiiiiiii = dynCalls["iiiiiiiii"] = wasmExports["Gf"];
+ dynCall_viiiiiiii = dynCalls["viiiiiiii"] = wasmExports["Hf"];
+ dynCall_iiiif = dynCalls["iiiif"] = wasmExports["If"];
+ dynCall_viiiiiiiiiiiiiii = dynCalls["viiiiiiiiiiiiiii"] = wasmExports["Jf"];
+ dynCall_viff = dynCalls["viff"] = wasmExports["Kf"];
+ dynCall_viiffii = dynCalls["viiffii"] = wasmExports["Lf"];
+ dynCall_viiffi = dynCalls["viiffi"] = wasmExports["Mf"];
+ dynCall_viiiiiiiiii = dynCalls["viiiiiiiiii"] = wasmExports["Nf"];
+ dynCall_fi = dynCalls["fi"] = wasmExports["Of"];
+ dynCall_viiffff = dynCalls["viiffff"] = wasmExports["Pf"];
+ dynCall_viiiiij = dynCalls["viiiiij"] = wasmExports["Qf"];
+ dynCall_vij = dynCalls["vij"] = wasmExports["Rf"];
+ dynCall_viiiiiffii = dynCalls["viiiiiffii"] = wasmExports["Sf"];
+ dynCall_vif = dynCalls["vif"] = wasmExports["Tf"];
+ dynCall_ddd = dynCalls["ddd"] = wasmExports["Uf"];
+ dynCall_dddd = dynCalls["dddd"] = wasmExports["Vf"];
+ dynCall_idd = dynCalls["idd"] = wasmExports["Wf"];
+ dynCall_di = dynCalls["di"] = wasmExports["Xf"];
+ dynCall_jiiiijiiiii = dynCalls["jiiiijiiiii"] = wasmExports["Yf"];
+ dynCall_viiij = dynCalls["viiij"] = wasmExports["Zf"];
+ dynCall_viid = dynCalls["viid"] = wasmExports["_f"];
+ dynCall_vidd = dynCalls["vidd"] = wasmExports["$f"];
+ dynCall_vifd = dynCalls["vifd"] = wasmExports["ag"];
+ dynCall_viiiiiiiiiii = dynCalls["viiiiiiiiiii"] = wasmExports["bg"];
+ dynCall_iiif = dynCalls["iiif"] = wasmExports["cg"];
+ dynCall_jiii = dynCalls["jiii"] = wasmExports["dg"];
+ dynCall_viijj = dynCalls["viijj"] = wasmExports["eg"];
+ dynCall_iiiiiiii = dynCalls["iiiiiiii"] = wasmExports["fg"];
+ dynCall_iiiiiiiiii = dynCalls["iiiiiiiiii"] = wasmExports["gg"];
+ dynCall_iij = dynCalls["iij"] = wasmExports["hg"];
+ dynCall_iiiijj = dynCalls["iiiijj"] = wasmExports["ig"];
+ dynCall_viiijjj = dynCalls["viiijjj"] = wasmExports["jg"];
+ dynCall_fff = dynCalls["fff"] = wasmExports["kg"];
+ dynCall_viifii = dynCalls["viifii"] = wasmExports["lg"];
+ dynCall_fii = dynCalls["fii"] = wasmExports["mg"];
+ dynCall_jjj = dynCalls["jjj"] = wasmExports["ng"];
+ dynCall_fiii = dynCalls["fiii"] = wasmExports["og"];
+ dynCall_viiiiiiiii = dynCalls["viiiiiiiii"] = wasmExports["pg"];
+ dynCall_viiiffii = dynCalls["viiiffii"] = wasmExports["qg"];
+ dynCall_iiiiiffi = dynCalls["iiiiiffi"] = wasmExports["rg"];
+ dynCall_viiiiiff = dynCalls["viiiiiff"] = wasmExports["sg"];
+ dynCall_viiiiiiiiiiiii = dynCalls["viiiiiiiiiiiii"] = wasmExports["tg"];
+ dynCall_viiiiiiiiiiii = dynCalls["viiiiiiiiiiii"] = wasmExports["ug"];
+ dynCall_viiiiiiiiiiiiiiiii = dynCalls["viiiiiiiiiiiiiiiii"] = wasmExports["vg"];
+ dynCall_iifff = dynCalls["iifff"] = wasmExports["wg"];
+ dynCall_iiff = dynCalls["iiff"] = wasmExports["xg"];
+ dynCall_iiifiii = dynCalls["iiifiii"] = wasmExports["yg"];
+ dynCall_iiffi = dynCalls["iiffi"] = wasmExports["zg"];
+ dynCall_iiffii = dynCalls["iiffii"] = wasmExports["Ag"];
+ dynCall_viiiiiiiiiiiiii = dynCalls["viiiiiiiiiiiiii"] = wasmExports["Bg"];
+ dynCall_iif = dynCalls["iif"] = wasmExports["Cg"];
+ dynCall_viijii = dynCalls["viijii"] = wasmExports["Dg"];
+ dynCall_iiiji = dynCalls["iiiji"] = wasmExports["Eg"];
+ dynCall_viiif = dynCalls["viiif"] = wasmExports["Fg"];
+ dynCall_viiifiii = dynCalls["viiifiii"] = wasmExports["Gg"];
+ dynCall_fiif = dynCalls["fiif"] = wasmExports["Hg"];
+ dynCall_iiiifi = dynCalls["iiiifi"] = wasmExports["Ig"];
+ dynCall_iiiifiii = dynCalls["iiiifiii"] = wasmExports["Jg"];
+ dynCall_iiifi = dynCalls["iiifi"] = wasmExports["Kg"];
+ dynCall_viiiif = dynCalls["viiiif"] = wasmExports["Lg"];
+ dynCall_viiiifii = dynCalls["viiiifii"] = wasmExports["Mg"];
+ dynCall_dii = dynCalls["dii"] = wasmExports["Ng"];
+ dynCall_vifi = dynCalls["vifi"] = wasmExports["Og"];
+ dynCall_vidi = dynCalls["vidi"] = wasmExports["Pg"];
+ dynCall_viiiji = dynCalls["viiiji"] = wasmExports["Qg"];
+ dynCall_viiji = dynCalls["viiji"] = wasmExports["Rg"];
+ dynCall_vijjj = dynCalls["vijjj"] = wasmExports["Sg"];
+ dynCall_vj = dynCalls["vj"] = wasmExports["Tg"];
+ dynCall_viij = dynCalls["viij"] = wasmExports["Ug"];
+ dynCall_jiji = dynCalls["jiji"] = wasmExports["Vg"];
+ dynCall_iidiiii = dynCalls["iidiiii"] = wasmExports["Wg"];
+ dynCall_iiiiij = dynCalls["iiiiij"] = wasmExports["Xg"];
+ dynCall_iiiiid = dynCalls["iiiiid"] = wasmExports["Yg"];
+ dynCall_iiiiijj = dynCalls["iiiiijj"] = wasmExports["Zg"];
+ dynCall_iiiiiijj = dynCalls["iiiiiijj"] = wasmExports["_g"];
+ _asyncify_start_unwind = wasmExports["$g"];
+ _asyncify_stop_unwind = wasmExports["ah"];
+ _asyncify_start_rewind = wasmExports["bh"];
+ _asyncify_stop_rewind = wasmExports["ch"];
+ memory = wasmMemory = wasmExports["sc"];
+ _kVersionStampBuildChangelistStr = Module["_kVersionStampBuildChangelistStr"] = (wasmExports["uc"].value) >>> 0;
+ _kVersionStampCitcSnapshotStr = Module["_kVersionStampCitcSnapshotStr"] = (wasmExports["vc"].value) >>> 0;
+ _kVersionStampCitcWorkspaceIdStr = Module["_kVersionStampCitcWorkspaceIdStr"] = (wasmExports["wc"].value) >>> 0;
+ _kVersionStampSourceUriStr = Module["_kVersionStampSourceUriStr"] = (wasmExports["xc"].value) >>> 0;
+ _kVersionStampBuildClientStr = Module["_kVersionStampBuildClientStr"] = (wasmExports["yc"].value) >>> 0;
+ _kVersionStampBuildClientMintStatusStr = Module["_kVersionStampBuildClientMintStatusStr"] = (wasmExports["zc"].value) >>> 0;
+ _kVersionStampBuildCompilerStr = Module["_kVersionStampBuildCompilerStr"] = (wasmExports["Ac"].value) >>> 0;
+ _kVersionStampBuildDateTimePstStr = Module["_kVersionStampBuildDateTimePstStr"] = (wasmExports["Bc"].value) >>> 0;
+ _kVersionStampBuildDepotPathStr = Module["_kVersionStampBuildDepotPathStr"] = (wasmExports["Cc"].value) >>> 0;
+ _kVersionStampBuildIdStr = Module["_kVersionStampBuildIdStr"] = (wasmExports["Dc"].value) >>> 0;
+ _kVersionStampBuildInfoStr = Module["_kVersionStampBuildInfoStr"] = (wasmExports["Ec"].value) >>> 0;
+ _kVersionStampBuildLabelStr = Module["_kVersionStampBuildLabelStr"] = (wasmExports["Fc"].value) >>> 0;
+ _kVersionStampBuildTargetStr = Module["_kVersionStampBuildTargetStr"] = (wasmExports["Gc"].value) >>> 0;
+ _kVersionStampBuildTimestampStr = Module["_kVersionStampBuildTimestampStr"] = (wasmExports["Hc"].value) >>> 0;
+ _kVersionStampBuildToolStr = Module["_kVersionStampBuildToolStr"] = (wasmExports["Ic"].value) >>> 0;
+ _kVersionStampG3BuildTargetStr = Module["_kVersionStampG3BuildTargetStr"] = (wasmExports["Jc"].value) >>> 0;
+ _kVersionStampVerifiableStr = Module["_kVersionStampVerifiableStr"] = (wasmExports["Kc"].value) >>> 0;
+ _kVersionStampBuildFdoTypeStr = Module["_kVersionStampBuildFdoTypeStr"] = (wasmExports["Lc"].value) >>> 0;
+ _kVersionStampBuildBaselineChangelistStr = Module["_kVersionStampBuildBaselineChangelistStr"] = (wasmExports["Mc"].value) >>> 0;
+ _kVersionStampBuildLtoTypeStr = Module["_kVersionStampBuildLtoTypeStr"] = (wasmExports["Nc"].value) >>> 0;
+ _kVersionStampBuildPropellerTypeStr = Module["_kVersionStampBuildPropellerTypeStr"] = (wasmExports["Oc"].value) >>> 0;
+ _kVersionStampBuildPghoTypeStr = Module["_kVersionStampBuildPghoTypeStr"] = (wasmExports["Pc"].value) >>> 0;
+ _kVersionStampBuildUsernameStr = Module["_kVersionStampBuildUsernameStr"] = (wasmExports["Qc"].value) >>> 0;
+ _kVersionStampBuildHostnameStr = Module["_kVersionStampBuildHostnameStr"] = (wasmExports["Rc"].value) >>> 0;
+ _kVersionStampBuildDirectoryStr = Module["_kVersionStampBuildDirectoryStr"] = (wasmExports["Sc"].value) >>> 0;
+ _kVersionStampBuildChangelistInt = Module["_kVersionStampBuildChangelistInt"] = (wasmExports["Tc"].value) >>> 0;
+ _kVersionStampCitcSnapshotInt = Module["_kVersionStampCitcSnapshotInt"] = (wasmExports["Uc"].value) >>> 0;
+ _kVersionStampBuildClientMintStatusInt = Module["_kVersionStampBuildClientMintStatusInt"] = (wasmExports["Vc"].value) >>> 0;
+ _kVersionStampBuildTimestampInt = Module["_kVersionStampBuildTimestampInt"] = (wasmExports["Wc"].value) >>> 0;
+ _kVersionStampVerifiableInt = Module["_kVersionStampVerifiableInt"] = (wasmExports["Xc"].value) >>> 0;
+ _kVersionStampBuildCoverageEnabledInt = Module["_kVersionStampBuildCoverageEnabledInt"] = (wasmExports["Yc"].value) >>> 0;
+ _kVersionStampBuildBaselineChangelistInt = Module["_kVersionStampBuildBaselineChangelistInt"] = (wasmExports["Zc"].value) >>> 0;
+ _kVersionStampPrecookedTimestampStr = Module["_kVersionStampPrecookedTimestampStr"] = (wasmExports["_c"].value) >>> 0;
+ _kVersionStampPrecookedClientInfoStr = Module["_kVersionStampPrecookedClientInfoStr"] = (wasmExports["$c"].value) >>> 0;
+ __indirect_function_table = wasmExports["__indirect_function_table"];
+}
+
+var wasmImports = {
+ /** @export */ qc: DefaultErrorReporter,
+ /** @export */ pc: GetAdapterArchitecture,
+ /** @export */ oc: GetAdapterDescription,
+ /** @export */ nc: GetAdapterDeviceName,
+ /** @export */ mc: GetAdapterVendor,
+ /** @export */ kc: JsGetDeviceMaxSubgroupSize,
+ /** @export */ jc: JsGetDeviceMinSubgroupSize,
+ /** @export */ ic: JsOnEmptyPacketListener,
+ /** @export */ ma: JsOnSimpleListenerBinaryArray,
+ /** @export */ hc: JsOnSimpleListenerBool,
+ /** @export */ gc: JsOnSimpleListenerDouble,
+ /** @export */ fc: JsOnSimpleListenerFloat,
+ /** @export */ ec: JsOnSimpleListenerInt,
+ /** @export */ dc: JsOnSimpleListenerString,
+ /** @export */ cc: JsOnSimpleListenerUint,
+ /** @export */ p: JsOnVectorFinishedListener,
+ /** @export */ bc: JsOnVectorListenerBool,
+ /** @export */ ac: JsOnVectorListenerDouble,
+ /** @export */ $b: JsOnVectorListenerFloat,
+ /** @export */ _b: JsOnVectorListenerInt,
+ /** @export */ Zb: JsOnVectorListenerProto,
+ /** @export */ Yb: JsOnVectorListenerString,
+ /** @export */ Xb: JsOnVectorListenerUint,
+ /** @export */ la: JsProgressListener,
+ /** @export */ K: JsWrapErrorListener,
+ /** @export */ g: JsWrapSimpleListeners,
+ /** @export */ Wb: ThrowError,
+ /** @export */ ka: UseBottomLeftGpuOrigin,
+ /** @export */ Vb: __Unwind_RaiseException,
+ /** @export */ rc: __asyncjs__CallReadDataFn,
+ /** @export */ lc: __asyncjs__InvokeReadDataFn,
+ /** @export */ J: __asyncjs__ReadBufferDataJs,
+ /** @export */ Ea: __asyncjs__mediapipe_map_buffer_jspi,
+ /** @export */ Ub: ___syscall_dup,
+ /** @export */ Tb: ___syscall_faccessat,
+ /** @export */ ja: ___syscall_fcntl64,
+ /** @export */ Sb: ___syscall_fstat64,
+ /** @export */ Va: ___syscall_ftruncate64,
+ /** @export */ Rb: ___syscall_getcwd,
+ /** @export */ Qb: ___syscall_getdents64,
+ /** @export */ Pb: ___syscall_ioctl,
+ /** @export */ Ob: ___syscall_lstat64,
+ /** @export */ Nb: ___syscall_mkdirat,
+ /** @export */ Mb: ___syscall_newfstatat,
+ /** @export */ ia: ___syscall_openat,
+ /** @export */ Lb: ___syscall_stat64,
+ /** @export */ Gb: __abort_js,
+ /** @export */ Ra: __embind_register_bigint,
+ /** @export */ Fb: __embind_register_bool,
+ /** @export */ Eb: __embind_register_emval,
+ /** @export */ ga: __embind_register_float,
+ /** @export */ x: __embind_register_function,
+ /** @export */ n: __embind_register_integer,
+ /** @export */ e: __embind_register_memory_view,
+ /** @export */ Db: __embind_register_std_string,
+ /** @export */ I: __embind_register_std_wstring,
+ /** @export */ Cb: __embind_register_void,
+ /** @export */ fa: __emval_create_invoker,
+ /** @export */ l: __emval_decref,
+ /** @export */ o: __emval_incref,
+ /** @export */ ea: __emval_invoke,
+ /** @export */ da: __emval_run_destructors,
+ /** @export */ Qa: __gmtime_js,
+ /** @export */ Pa: __localtime_js,
+ /** @export */ Oa: __mktime_js,
+ /** @export */ Na: __mmap_js,
+ /** @export */ Ma: __munmap_js,
+ /** @export */ Bb: __tzset_js,
+ /** @export */ Ua: _clock_time_get,
+ /** @export */ Ab: custom_emscripten_dbgn,
+ /** @export */ s: _emscripten_asm_const_int,
+ /** @export */ H: _emscripten_errn,
+ /** @export */ zb: _emscripten_get_heap_max,
+ /** @export */ d: _emscripten_get_now,
+ /** @export */ ca: _emscripten_has_asyncify,
+ /** @export */ yb: _emscripten_outn,
+ /** @export */ xb: _emscripten_pc_get_function,
+ /** @export */ wb: _emscripten_resize_heap,
+ /** @export */ ba: _emscripten_stack_snapshot,
+ /** @export */ vb: _emscripten_stack_unwind_buffer,
+ /** @export */ ub: _emscripten_webgl_create_context,
+ /** @export */ tb: _emscripten_webgl_destroy_context,
+ /** @export */ sb: _emscripten_webgl_get_context_attributes,
+ /** @export */ r: _emscripten_webgl_get_current_context,
+ /** @export */ rb: _emscripten_webgl_make_context_current,
+ /** @export */ aa: _emscripten_webgpu_get_device,
+ /** @export */ qb: _emwgpuBufferDestroy,
+ /** @export */ pb: _emwgpuBufferGetMappedRange,
+ /** @export */ ob: _emwgpuBufferUnmap,
+ /** @export */ nb: _emwgpuBufferWriteMappedRange,
+ /** @export */ f: _emwgpuDelete,
+ /** @export */ mb: _emwgpuDeviceCreateBuffer,
+ /** @export */ La: _emwgpuDeviceCreateComputePipelineAsync,
+ /** @export */ lb: _emwgpuDeviceCreateShaderModule,
+ /** @export */ kb: _emwgpuDeviceDestroy,
+ /** @export */ Ka: _emwgpuQueueOnSubmittedWorkDone,
+ /** @export */ jb: _emwgpuWaitAny,
+ /** @export */ Kb: _environ_get,
+ /** @export */ Jb: _environ_sizes_get,
+ /** @export */ ib: _exit,
+ /** @export */ z: _fd_close,
+ /** @export */ Ta: _fd_pread,
+ /** @export */ ha: _fd_read,
+ /** @export */ Sa: _fd_seek,
+ /** @export */ y: _fd_write,
+ /** @export */ G: _glActiveTexture,
+ /** @export */ $: _glAttachShader,
+ /** @export */ hb: _glBindAttribLocation,
+ /** @export */ m: _glBindBuffer,
+ /** @export */ w: _glBindFramebuffer,
+ /** @export */ k: _glBindTexture,
+ /** @export */ F: _glBufferData,
+ /** @export */ q: _glClientWaitSync,
+ /** @export */ gb: _glCompileShader,
+ /** @export */ fb: _glCreateProgram,
+ /** @export */ eb: _glCreateShader,
+ /** @export */ _: _glDeleteFramebuffers,
+ /** @export */ db: _glDeleteProgram,
+ /** @export */ Z: _glDeleteShader,
+ /** @export */ v: _glDeleteSync,
+ /** @export */ Y: _glDeleteTextures,
+ /** @export */ X: _glDetachShader,
+ /** @export */ W: _glDisableVertexAttribArray,
+ /** @export */ cb: _glDrawArrays,
+ /** @export */ V: _glEnableVertexAttribArray,
+ /** @export */ U: _glFenceSync,
+ /** @export */ u: _glFinish,
+ /** @export */ E: _glFramebufferTexture2D,
+ /** @export */ T: _glGenBuffers,
+ /** @export */ bb: _glGenFramebuffers,
+ /** @export */ D: _glGenTextures,
+ /** @export */ t: _glGetError,
+ /** @export */ S: _glGetIntegerv,
+ /** @export */ C: _glGetString,
+ /** @export */ ab: _glGetUniformLocation,
+ /** @export */ $a: _glLinkProgram,
+ /** @export */ B: _glPixelStorei,
+ /** @export */ R: _glReadPixels,
+ /** @export */ _a: _glShaderSource,
+ /** @export */ Za: _glTexImage2D,
+ /** @export */ j: _glTexParameteri,
+ /** @export */ Q: _glTexStorage2D,
+ /** @export */ Ya: _glUniform1i,
+ /** @export */ Xa: _glUseProgram,
+ /** @export */ P: _glVertexAttribPointer,
+ /** @export */ Wa: _glViewport,
+ /** @export */ A: hardware_concurrency,
+ /** @export */ Ib: _proc_exit,
+ /** @export */ Hb: _random_get,
+ /** @export */ Ja: _wgpuBufferGetSize,
+ /** @export */ Ia: _wgpuBufferGetUsage,
+ /** @export */ i: _wgpuCommandEncoderBeginComputePass,
+ /** @export */ Ha: _wgpuCommandEncoderCopyBufferToBuffer,
+ /** @export */ O: _wgpuCommandEncoderCopyTextureToBuffer,
+ /** @export */ Da: _wgpuCommandEncoderCopyTextureToTexture,
+ /** @export */ c: _wgpuCommandEncoderFinish,
+ /** @export */ Ga: _wgpuCommandEncoderResolveQuerySet,
+ /** @export */ N: _wgpuComputePassEncoderDispatchWorkgroups,
+ /** @export */ h: _wgpuComputePassEncoderEnd,
+ /** @export */ Ca: _wgpuComputePassEncoderSetBindGroup,
+ /** @export */ M: _wgpuComputePassEncoderSetPipeline,
+ /** @export */ Ba: _wgpuDeviceCreateBindGroup,
+ /** @export */ Aa: _wgpuDeviceCreateBindGroupLayout,
+ /** @export */ b: _wgpuDeviceCreateCommandEncoder,
+ /** @export */ za: _wgpuDeviceCreateComputePipeline,
+ /** @export */ ya: _wgpuDeviceCreatePipelineLayout,
+ /** @export */ xa: _wgpuDeviceCreateQuerySet,
+ /** @export */ wa: _wgpuDeviceCreateTexture,
+ /** @export */ L: _wgpuDeviceGetAdapterInfo,
+ /** @export */ va: _wgpuDeviceGetLimits,
+ /** @export */ ua: _wgpuDeviceHasFeature,
+ /** @export */ a: _wgpuQueueSubmit,
+ /** @export */ Fa: _wgpuQueueWriteBuffer,
+ /** @export */ ta: _wgpuQueueWriteTexture,
+ /** @export */ sa: _wgpuTextureCreateView,
+ /** @export */ ra: _wgpuTextureDestroy,
+ /** @export */ qa: _wgpuTextureGetDepthOrArrayLayers,
+ /** @export */ pa: _wgpuTextureGetFormat,
+ /** @export */ oa: _wgpuTextureGetHeight,
+ /** @export */ na: _wgpuTextureGetWidth
+};
+
+// Argument name here must shadow the `wasmExports` global so
+// that it is recognised by metadce and minify-import-export-names
+// passes.
+function applySignatureConversions(wasmExports) {
+ // First, make a copy of the incoming exports object
+ wasmExports = Object.assign({}, wasmExports);
+ var makeWrapper_pp = f => a0 => f(a0) >>> 0;
+ var makeWrapper_ppp = f => (a0, a1) => f(a0, a1) >>> 0;
+ var makeWrapper_p = f => () => f() >>> 0;
+ wasmExports["hd"] = makeWrapper_pp(wasmExports["hd"]);
+ wasmExports["se"] = makeWrapper_pp(wasmExports["se"]);
+ wasmExports["bf"] = makeWrapper_ppp(wasmExports["bf"]);
+ wasmExports["cf"] = makeWrapper_ppp(wasmExports["cf"]);
+ wasmExports["ff"] = makeWrapper_pp(wasmExports["ff"]);
+ wasmExports["gf"] = makeWrapper_p(wasmExports["gf"]);
+ return wasmExports;
+}
+
+// include: postamble.js
+// === Auto-generated postamble setup entry stuff ===
+function run() {
+ if (runDependencies > 0) {
+ dependenciesFulfilled = run;
+ return;
+ }
+ preRun();
+ // a preRun added a dependency, run will be called later
+ if (runDependencies > 0) {
+ dependenciesFulfilled = run;
+ return;
+ }
+ function doRun() {
+ // run may have just been called through dependencies being fulfilled just in this very frame,
+ // or while the async setStatus time below was happening
+ Module["calledRun"] = true;
+ if (ABORT) return;
+ initRuntime();
+ readyPromiseResolve?.(Module);
+ Module["onRuntimeInitialized"]?.();
+ postRun();
+ }
+ if (Module["setStatus"]) {
+ Module["setStatus"]("Running...");
+ setTimeout(() => {
+ setTimeout(() => Module["setStatus"](""), 1);
+ doRun();
+ }, 1);
+ } else {
+ doRun();
+ }
+}
+
+var wasmExports;
+
+// In modularize mode the generated code is within a factory function so we
+// can use await here (since it's not top-level-await).
+wasmExports = await (createWasm());
+
+run();
+
+// end include: postamble.js
+// include: postamble_modularize.js
+// In MODULARIZE mode we wrap the generated code in a factory function
+// and return either the Module itself, or a promise of the module.
+// We assign to the `moduleRtn` global here and configure closure to see
+// this as an extern so it won't get minified.
+if (runtimeInitialized) {
+ moduleRtn = Module;
+} else {
+ // Set up the promise that indicates the Module is initialized
+ moduleRtn = new Promise((resolve, reject) => {
+ readyPromiseResolve = resolve;
+ readyPromiseReject = reject;
+ });
+}
+
+
+ return moduleRtn;
+}
+
+// Export using a UMD style export, or ES6 exports if selected
+export default ModuleFactory;
+
diff --git a/public/mediapipe/wasm/genai_wasm_module_internal.wasm b/public/mediapipe/wasm/genai_wasm_module_internal.wasm
new file mode 100644
index 0000000..a16e3a7
Binary files /dev/null and b/public/mediapipe/wasm/genai_wasm_module_internal.wasm differ
diff --git a/public/prompts/system_compact.md b/public/prompts/system_compact.md
new file mode 100644
index 0000000..8c6a5da
--- /dev/null
+++ b/public/prompts/system_compact.md
@@ -0,0 +1,102 @@
+You are K.G.Studio Music Assistant Agent.
+
+You are a skilled AI music assistant focused on composition, harmony, arrangement, MIDI editing, and music production.
+
+Your job:
+- Understand the user request
+- Read existing music if needed
+- Edit music step-by-step using tools
+- Make musically coherent decisions
+- Return a short summary after finishing
+
+====
+
+TOOLS
+
+## read_music
+Reads existing music in ABC notation.
+
+## remove_notes
+Removes notes from a beat range.
+
+## add_notes
+Adds notes to the current region.
+
+Pitch format:
+- Scientific notation
+- Examples: C4, F#3, Bb2
+
+Important:
+- `start` is ALWAYS the absolute beat position in the project timeline.
+
+====
+
+TOOL RULES
+
+- Use tools step-by-step.
+- Check tool results before continuing.
+- Do not assume success.
+- If information is missing, ask the user.
+- Use `read_music` before editing when musical context is needed.
+- Do not ask the user to manually provide existing music before using `read_music`.
+
+====
+
+EDITING RULES
+
+When adding notes:
+- Explicitly include ALL notes.
+- Never omit repeated notes with "..." or summaries.
+- Chords = multiple notes sharing the same `start`.
+- Melodies = sequential `start` values.
+
+Before adding notes:
+- Remove conflicting notes if necessary.
+- Avoid stacking unintended duplicate notes.
+
+Music quality guidelines:
+- Stay in key unless stylistically appropriate.
+- Use reasonable instrument ranges.
+- Respect the time signature grid.
+- Keep harmony and rhythm musically coherent.
+- Prefer smooth melodic and harmonic movement.
+
+====
+
+DRUM NOTE MAP
+
+Common drum pitches:
+- C2 = Kick
+- D2 = Snare
+- F#2 = Closed Hi-Hat
+- Bb2 = Open Hi-Hat
+- Db3 = Crash
+- Eb3 = Ride
+
+====
+
+CAPABILITIES
+
+You can:
+- Analyze existing music
+- Continue musical ideas
+- Create melodies, chords, basslines, and drums
+- Adapt to musical style and genre
+- Make arrangement decisions using music theory knowledge
+
+Project information such as BPM, key, time signature, track instrument, and region boundaries will be provided dynamically.
+
+Focus mainly on the current region.
+
+====
+
+WORKFLOW
+
+1. Understand the task
+2. Read music if needed
+3. Plan musical changes
+4. Edit step-by-step with tools
+5. Verify results
+6. Return a concise summary
+
+Do not endlessly continue conversations after finishing the task.
\ No newline at end of file
diff --git a/src/App.test.tsx b/src/App.test.tsx
index 4bd3d52..d25e1ec 100644
--- a/src/App.test.tsx
+++ b/src/App.test.tsx
@@ -2,6 +2,8 @@ import { act, render, screen } from '@testing-library/react';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
let mockState = { isPreparingPlayback: false };
+let mockActiveLoadCount = 0;
+let loadingListener: ((evt: { type: 'start' | 'end'; instrument: string }) => void) | null = null;
vi.mock('./stores/projectStore', () => ({
useProjectStore: (selector?: (state: typeof mockState) => unknown) => (
@@ -21,12 +23,21 @@ vi.mock('./components/ChatBox', () => ({ default: () => null }));
vi.mock('./components/KGOnePanel', () => ({ default: () => null }));
vi.mock('./components/EventListPanel', () => ({ default: () => null }));
vi.mock('./components/settings', () => ({ SettingsPanel: () => null }));
+vi.mock('./util/dialogUtil', () => ({
+ showAlert: vi.fn().mockResolvedValue(undefined),
+}));
vi.mock('./core/audio-interface/KGToneBuffersPool', () => ({
KGToneBuffersPool: {
instance: () => ({
- getActiveLoadCount: () => 0,
- addLoadingListener: () => undefined,
- removeLoadingListener: () => undefined,
+ getActiveLoadCount: () => mockActiveLoadCount,
+ addLoadingListener: (listener: (evt: { type: 'start' | 'end'; instrument: string }) => void) => {
+ loadingListener = listener;
+ },
+ removeLoadingListener: (listener: (evt: { type: 'start' | 'end'; instrument: string }) => void) => {
+ if (loadingListener === listener) {
+ loadingListener = null;
+ }
+ },
}),
},
}));
@@ -47,12 +58,14 @@ vi.mock('./core/KGCore', () => ({
},
}));
-import { PlaybackPreparationOverlayContainer } from './App';
+import { GlobalLoadingOverlayContainer, PlaybackPreparationOverlayContainer } from './App';
describe('PlaybackPreparationOverlayContainer', () => {
beforeEach(() => {
vi.useFakeTimers();
mockState = { isPreparingPlayback: false };
+ mockActiveLoadCount = 0;
+ loadingListener = null;
});
afterEach(() => {
@@ -112,3 +125,29 @@ describe('PlaybackPreparationOverlayContainer', () => {
expect(screen.queryByText('Preparing playback...')).not.toBeInTheDocument();
});
});
+
+describe('GlobalLoadingOverlayContainer', () => {
+ beforeEach(() => {
+ vi.useFakeTimers();
+ mockActiveLoadCount = 0;
+ loadingListener = null;
+ });
+
+ afterEach(() => {
+ vi.useRealTimers();
+ });
+
+ it('syncs to the pool active count instead of relying on incremental listener math', () => {
+ mockActiveLoadCount = 2;
+ render();
+
+ expect(screen.getByText('Loading ... (2)')).toBeInTheDocument();
+
+ mockActiveLoadCount = 0;
+ act(() => {
+ loadingListener?.({ type: 'end', instrument: 'woodblock' });
+ });
+
+ expect(screen.queryByText(/Loading \.\.\./)).not.toBeInTheDocument();
+ });
+});
diff --git a/src/App.tsx b/src/App.tsx
index c31919b..a4e4c9e 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -195,19 +195,20 @@ function App() {
export default App;
// Local component to subscribe to pool events and manage a counter
-const GlobalLoadingOverlayContainer: React.FC = () => {
+export const GlobalLoadingOverlayContainer: React.FC = () => {
const [loadingCount, setLoadingCount] = useState(() => KGToneBuffersPool.instance().getActiveLoadCount());
const [overdue, setOverdue] = useState(false);
const timeoutRef = useRef(null);
useEffectReact(() => {
const pool = KGToneBuffersPool.instance();
- const listener = (evt: { type: 'start' | 'end'; instrument: string }) => {
- setLoadingCount(prev => {
- if (evt.type === 'start') return prev + 1;
- return Math.max(0, prev - 1);
- });
+ const syncLoadingCount = () => {
+ setLoadingCount(pool.getActiveLoadCount());
};
+ const listener = (_evt: { type: 'start' | 'end'; instrument: string }) => {
+ syncLoadingCount();
+ };
+ syncLoadingCount();
pool.addLoadingListener(listener);
return () => {
pool.removeLoadingListener(listener);
@@ -219,8 +220,11 @@ const GlobalLoadingOverlayContainer: React.FC = () => {
// When loading starts, start a 30s timer if not already overdue/timed
if (loadingCount > 0 && !overdue && timeoutRef.current === null) {
timeoutRef.current = window.setTimeout(async () => {
- // Only trigger if still loading
- if (loadingCount > 0) {
+ const activeLoadCount = KGToneBuffersPool.instance().getActiveLoadCount();
+ setLoadingCount(activeLoadCount);
+
+ // Only trigger if still loading according to the source of truth
+ if (activeLoadCount > 0) {
setOverdue(true);
await showAlert(
'Loading resources is taking longer than expected and may have partially failed. If you notice any playback issues, please refresh the page to retry downloading the audio files.'
diff --git a/src/agent/core/AgentCore.ts b/src/agent/core/AgentCore.ts
index c943c3d..3dd9b7a 100644
--- a/src/agent/core/AgentCore.ts
+++ b/src/agent/core/AgentCore.ts
@@ -1,4 +1,4 @@
-import { LLMProvider } from '../llm/LLMProvider';
+import type { LLMProvider } from '../llm/LLMProvider';
import { AgentState } from './AgentState';
import { SystemPrompts } from './SystemPrompts';
import { AVAILABLE_TOOLS } from '../tools';
@@ -92,7 +92,9 @@ export class AgentCore {
// Add user message to state
this.currentUserMessageId = this.agentState.addMessage('user', userInput);
- const systemPrompt = await SystemPrompts.getSystemPromptWithContext();
+ const systemPrompt = await SystemPrompts.getSystemPromptWithContext(
+ this.llmProvider.getPreferredSystemPromptPath?.(),
+ );
const tools = this.getToolDefinitions();
try {
@@ -108,6 +110,7 @@ export class AgentCore {
let assistantTextContent = '';
const accumulatedToolCalls: ToolCall[] = [];
let finishReason = 'stop';
+ let performanceInfo: StreamChunk['performanceInfo'];
for await (const chunk of this.llmProvider.generateStream(conversationHistory, systemPrompt, tools)) {
if (chunk.type === 'text') {
@@ -118,6 +121,7 @@ export class AgentCore {
accumulatedToolCalls.push(chunk.toolCall);
} else if (chunk.type === 'done') {
finishReason = chunk.finishReason ?? 'stop';
+ performanceInfo = chunk.performanceInfo;
}
}
@@ -161,10 +165,9 @@ export class AgentCore {
// LLM finished with text response (stop reason)
this.agentState.updateMessage(this.currentAssistantMessageId, assistantTextContent);
continueLoop = false;
+ yield { type: 'done', content: '', finishReason, performanceInfo };
}
}
-
- yield { type: 'done', content: '', finishReason: 'stop' };
} finally {
this.currentUserMessageId = null;
this.currentAssistantMessageId = null;
diff --git a/src/agent/core/SystemPrompts.ts b/src/agent/core/SystemPrompts.ts
index 1f20d2d..ad292da 100644
--- a/src/agent/core/SystemPrompts.ts
+++ b/src/agent/core/SystemPrompts.ts
@@ -22,25 +22,26 @@ interface SystemPromptContext {
* System prompts for the AI agent with dynamic context loading
*/
export class SystemPrompts {
- private static cachedTemplate: string | null = null;
+ private static cachedTemplates: Map = new Map();
private static readonly FALLBACK_PROMPT = `You are K.G.Studio Musician Assistant Agent, a highly skilled music musician with extensive knowledge in music theory, composition, and production.`;
/**
* Load the system prompt template from the public folder
*/
- private static async loadTemplate(): Promise {
- if (this.cachedTemplate) {
- return this.cachedTemplate;
+ private static async loadTemplate(templatePath: string = 'prompts/system.md'): Promise {
+ if (this.cachedTemplates.has(templatePath)) {
+ return this.cachedTemplates.get(templatePath)!;
}
try {
- const response = await fetch(`${import.meta.env.BASE_URL}prompts/system.md`);
+ const response = await fetch(`${import.meta.env.BASE_URL}${templatePath}`);
if (!response.ok) {
throw new Error(`Failed to load system prompt: ${response.status}`);
}
- this.cachedTemplate = await response.text();
- return this.cachedTemplate;
+ const template = await response.text();
+ this.cachedTemplates.set(templatePath, template);
+ return template;
} catch (error) {
console.error('Failed to load system prompt template:', error);
return this.FALLBACK_PROMPT;
@@ -231,9 +232,9 @@ export class SystemPrompts {
/**
* Get the system prompt with current context applied (backward compatible)
*/
- static async getSystemPromptWithContext(): Promise {
+ static async getSystemPromptWithContext(templatePath?: string): Promise {
try {
- const template = await this.loadTemplate();
+ const template = await this.loadTemplate(templatePath);
let promptWithContext = await this.getPromptWithContext(template);
// Append custom instructions from config if provided
@@ -261,6 +262,6 @@ export class SystemPrompts {
* Clear the cached template (useful for development/testing)
*/
static clearCache(): void {
- this.cachedTemplate = null;
+ this.cachedTemplates.clear();
}
-}
\ No newline at end of file
+}
diff --git a/src/agent/llm/LLMProvider.ts b/src/agent/llm/LLMProvider.ts
index ad896e8..7a8db11 100644
--- a/src/agent/llm/LLMProvider.ts
+++ b/src/agent/llm/LLMProvider.ts
@@ -3,16 +3,24 @@ import type { StreamChunk } from './StreamingTypes';
import type { Message, ToolCall } from '../core/AgentState';
import type { OpenAIToolDefinition } from '../tools/BaseTool';
+export interface LLMProvider {
+ getPreferredSystemPromptPath?(): string | undefined;
+ generateStream(
+ messages: Message[],
+ systemPrompt?: string,
+ tools?: OpenAIToolDefinition[],
+ ): AsyncIterableIterator;
+}
+
/**
- * LLM provider using the OpenAI SDK.
- * Works with any OpenAI-compatible API (OpenAI, OpenRouter, Ollama, vLLM, etc.)
+ * OpenAI-compatible provider implementation.
+ * Works with OpenAI and OpenAI-compatible APIs (OpenRouter, Ollama, vLLM, etc.)
*/
-export class LLMProvider {
+export class OpenAICompatibleLLMProvider implements LLMProvider {
private client: OpenAI;
private model: string;
constructor(apiKey: string, model: string, baseURL?: string) {
- // The OpenAI SDK appends /chat/completions itself, so strip it if the user included it
const normalizedBaseURL = baseURL?.replace(/\/chat\/completions\/?$/, '') || undefined;
this.client = new OpenAI({
@@ -23,12 +31,9 @@ export class LLMProvider {
this.model = model;
}
- /**
- * Convert internal Message[] to OpenAI ChatCompletionMessageParam[]
- */
private convertMessages(
messages: Message[],
- systemPrompt?: string
+ systemPrompt?: string,
): OpenAI.ChatCompletionMessageParam[] {
const result: OpenAI.ChatCompletionMessageParam[] = [];
@@ -64,10 +69,6 @@ export class LLMProvider {
return result;
}
- /**
- * Generate a streaming response from the LLM.
- * Yields StreamChunks for text content and tool calls.
- */
async *generateStream(
messages: Message[],
systemPrompt?: string,
@@ -87,8 +88,6 @@ export class LLMProvider {
}
const stream = this.client.chat.completions.stream(requestParams);
-
- // Accumulate tool calls across chunks (they arrive incrementally)
const toolCallAccumulator = new Map();
for await (const chunk of stream) {
@@ -97,23 +96,18 @@ export class LLMProvider {
if (!choice) continue;
const delta = choice.delta;
-
- // Yield text content
if (delta.content) {
yield { type: 'text', content: delta.content };
}
- // Accumulate tool calls from deltas
if (delta.tool_calls) {
for (const tc of delta.tool_calls) {
const existing = toolCallAccumulator.get(tc.index);
if (existing) {
- // Append to existing tool call
if (tc.function?.arguments) {
existing.arguments += tc.function.arguments;
}
} else {
- // New tool call
toolCallAccumulator.set(tc.index, {
id: tc.id ?? '',
name: tc.function?.name ?? '',
@@ -124,11 +118,9 @@ export class LLMProvider {
}
}
- // After stream ends, get the final completion for finish_reason
const finalCompletion = await stream.finalChatCompletion();
const finishReason = finalCompletion.choices[0]?.finish_reason ?? 'stop';
- // Emit accumulated tool calls
if (toolCallAccumulator.size > 0) {
for (const [, tc] of toolCallAccumulator) {
const toolCall: ToolCall = {
@@ -140,7 +132,6 @@ export class LLMProvider {
}
}
- // Signal completion
yield { type: 'done', content: '', finishReason };
}
}
diff --git a/src/agent/llm/LocalBrowserLLMProvider.test.ts b/src/agent/llm/LocalBrowserLLMProvider.test.ts
new file mode 100644
index 0000000..1284c9d
--- /dev/null
+++ b/src/agent/llm/LocalBrowserLLMProvider.test.ts
@@ -0,0 +1,106 @@
+import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
+
+const {
+ configGetMock,
+ ensureRuntimeSupportedMock,
+ notifyLoadProgressMock,
+ notifyLoadStartMock,
+ notifyCacheReadyMock,
+ notifyLoadErrorMock,
+ loadModelReaderWithCacheMock,
+} = vi.hoisted(() => ({
+ configGetMock: vi.fn(),
+ ensureRuntimeSupportedMock: vi.fn(async () => undefined),
+ notifyLoadProgressMock: vi.fn(),
+ notifyLoadStartMock: vi.fn(),
+ notifyCacheReadyMock: vi.fn(),
+ notifyLoadErrorMock: vi.fn(),
+ loadModelReaderWithCacheMock: vi.fn(),
+}));
+
+vi.mock('../../core/config/ConfigManager', () => ({
+ ConfigManager: {
+ instance: () => ({
+ get: configGetMock,
+ }),
+ },
+}));
+
+vi.mock('../../util/localLLMModelManager', () => ({
+ LocalLLMModelManager: {
+ ensureRuntimeSupported: ensureRuntimeSupportedMock,
+ notifyLoadProgress: notifyLoadProgressMock,
+ notifyLoadStart: notifyLoadStartMock,
+ notifyCacheReady: notifyCacheReadyMock,
+ notifyLoadError: notifyLoadErrorMock,
+ },
+}));
+
+vi.mock('../../util/localLLMModelCache', () => ({
+ LocalLLMModelCache: {
+ loadModelReaderWithCache: loadModelReaderWithCacheMock,
+ },
+}));
+
+import { LocalBrowserLLMProvider } from './LocalBrowserLLMProvider';
+
+describe('LocalBrowserLLMProvider', () => {
+ afterEach(() => {
+ vi.restoreAllMocks();
+ });
+
+ beforeEach(() => {
+ configGetMock.mockReset();
+ ensureRuntimeSupportedMock.mockClear();
+ notifyLoadProgressMock.mockClear();
+ notifyLoadStartMock.mockClear();
+ notifyCacheReadyMock.mockClear();
+ notifyLoadErrorMock.mockClear();
+ loadModelReaderWithCacheMock.mockReset();
+ });
+
+ async function runProviderAndCaptureOptions(configValue: unknown): Promise> {
+ const createFromOptionsMock = vi.fn(async (_fileset: unknown, options: Record) => ({
+ generateResponse: (_prompt: string, callback: (partial: string, done: boolean) => void) => {
+ callback('hello', true);
+ },
+ sizeInTokens: (text: string) => text.length,
+ }));
+
+ configGetMock.mockReturnValue(configValue);
+ loadModelReaderWithCacheMock.mockResolvedValue({
+ reader: new Uint8Array([1, 2, 3]),
+ totalBytes: 3,
+ fromCache: true,
+ cacheWritePromise: null,
+ });
+
+ vi.spyOn(LocalBrowserLLMProvider.prototype as never, 'getMediaPipeModule' as never).mockResolvedValue({
+ FilesetResolver: {
+ forGenAiTasks: vi.fn(async () => ({})),
+ },
+ LlmInference: {
+ createFromOptions: createFromOptionsMock,
+ },
+ });
+
+ const provider = new LocalBrowserLLMProvider();
+ const chunks: unknown[] = [];
+ for await (const chunk of provider.generateStream([])) {
+ chunks.push(chunk);
+ }
+
+ expect(chunks.length).toBeGreaterThan(0);
+ return createFromOptionsMock.mock.calls[0][1] as Record;
+ }
+
+ it('uses the configured maxTokens value', async () => {
+ const options = await runProviderAndCaptureOptions(65536);
+ expect(options.maxTokens).toBe(65536);
+ });
+
+ it('falls back to 32768 when config is invalid', async () => {
+ const options = await runProviderAndCaptureOptions(99999);
+ expect(options.maxTokens).toBe(32768);
+ });
+});
diff --git a/src/agent/llm/LocalBrowserLLMProvider.ts b/src/agent/llm/LocalBrowserLLMProvider.ts
new file mode 100644
index 0000000..57970f8
--- /dev/null
+++ b/src/agent/llm/LocalBrowserLLMProvider.ts
@@ -0,0 +1,325 @@
+import type { StreamChunk } from './StreamingTypes';
+import type { Message, ToolCall } from '../core/AgentState';
+import type { OpenAIToolDefinition } from '../tools/BaseTool';
+import { LocalLLMModelManager } from '../../util/localLLMModelManager';
+import {
+ formatToolCall,
+ formatToolDeclaration,
+ formatToolResponse,
+ parseToolCalls,
+ stripToolProtocol,
+} from './gemmaToolProtocol';
+import {
+ LOCAL_LLM_DEFAULT_CONTEXT_LENGTH,
+ LOCAL_LLM_MODEL_FILENAME,
+ LOCAL_LLM_MODEL_URL,
+ normalizeLocalLLMContextLength,
+} from '../../util/localLLMConfig';
+import { LocalLLMModelCache } from '../../util/localLLMModelCache';
+import type { LLMProvider } from './LLMProvider';
+import { ConfigManager } from '../../core/config/ConfigManager';
+
+type MediaPipeGenAI = {
+ FilesetResolver: {
+ forGenAiTasks(basePath: string): Promise;
+ };
+ LlmInference: {
+ createFromOptions(fileset: unknown, options: Record): Promise;
+ };
+};
+
+type GemmaInference = {
+ generateResponse(
+ prompt: string,
+ callback: (partial: string, done: boolean) => void,
+ ): Promise | void;
+ sizeInTokens(text: string): number;
+ close?: () => void;
+};
+
+interface PromptTemplatePart {
+ pre: string;
+ post: string;
+}
+
+const PROMPT_TEMPLATE: Record<'user' | 'model' | 'system', PromptTemplatePart> = {
+ user: { pre: '<|turn>user\n', post: '\n' },
+ model: { pre: '<|turn>model\n', post: '\n' },
+ system: { pre: '<|turn>system\n', post: '\n' },
+};
+
+async function importMediaPipe(): Promise {
+ const bundleUrl = new URL(`${import.meta.env.BASE_URL}mediapipe/genai_bundle.mjs`, window.location.origin).href;
+ return import(/* @vite-ignore */ bundleUrl) as Promise;
+}
+
+export class LocalBrowserLLMProvider implements LLMProvider {
+ private inference: GemmaInference | null = null;
+
+ getPreferredSystemPromptPath(): string | undefined {
+ return 'prompts/system_compact.md';
+ }
+
+ private async ensureInference(): Promise {
+ await LocalLLMModelManager.ensureRuntimeSupported();
+ if (this.inference) {
+ return this.inference;
+ }
+
+ const maxTokens = this.getConfiguredContextLength();
+ console.log(`[localLLM] Initializing with max context length: ${maxTokens} tokens`);
+
+ const [{ FilesetResolver, LlmInference }, modelLoad] = await Promise.all([
+ this.getMediaPipeModule(),
+ LocalLLMModelCache.loadModelReaderWithCache(
+ LOCAL_LLM_MODEL_URL,
+ LOCAL_LLM_MODEL_FILENAME,
+ progress => {
+ LocalLLMModelManager.notifyLoadProgress(progress.receivedBytes, progress.totalBytes, progress.fromCache);
+ },
+ ),
+ ]);
+
+ LocalLLMModelManager.notifyLoadStart(modelLoad.fromCache);
+ console.log('[localLLM] Model stream prepared for MediaPipe.', {
+ filename: LOCAL_LLM_MODEL_FILENAME,
+ totalBytes: modelLoad.totalBytes,
+ fromCache: modelLoad.fromCache,
+ });
+
+ const fileset = await FilesetResolver.forGenAiTasks(`${import.meta.env.BASE_URL}mediapipe/wasm`);
+ console.log('[localLLM] MediaPipe fileset resolved. Creating inference engine...');
+ try {
+ this.inference = await LlmInference.createFromOptions(fileset, {
+ baseOptions: {
+ modelAssetBuffer: modelLoad.reader,
+ },
+ numResponses: 1,
+ maxTokens,
+ topK: 64,
+ temperature: 1.0,
+ });
+ console.log('[localLLM] MediaPipe inference engine created successfully.');
+ if (modelLoad.cacheWritePromise) {
+ void modelLoad.cacheWritePromise.then(() => {
+ LocalLLMModelManager.notifyCacheReady();
+ }).catch(error => {
+ console.error('[localLLM] Background cache write failed after inference creation.', error);
+ LocalLLMModelManager.notifyLoadError(error);
+ });
+ } else {
+ LocalLLMModelManager.notifyCacheReady();
+ }
+ return this.inference;
+ } catch (error) {
+ LocalLLMModelManager.notifyLoadError(error);
+ throw error;
+ }
+ }
+
+ private async getMediaPipeModule(): Promise {
+ return importMediaPipe();
+ }
+
+ private getConfiguredContextLength(): number {
+ try {
+ const configManager = ConfigManager.instance();
+ return normalizeLocalLLMContextLength(
+ configManager.get('general.local_browser.context_length'),
+ );
+ } catch {
+ return LOCAL_LLM_DEFAULT_CONTEXT_LENGTH;
+ }
+ }
+
+ private applyTemplate(message: { role: 'user' | 'model'; text: string }): string {
+ const template = PROMPT_TEMPLATE[message.role];
+ return `${template.pre}${message.text}${template.post}`;
+ }
+
+ private renderPrompt(
+ messages: Message[],
+ systemPrompt: string | undefined,
+ tools: OpenAIToolDefinition[] | undefined,
+ ): string {
+ const thinkPrefix = '<|think|>';
+ const toolDeclarations = (tools ?? []).map(formatToolDeclaration).join('');
+ const systemContent = `${thinkPrefix}${systemPrompt ?? ''}${toolDeclarations}`;
+ const systemSection = systemContent
+ ? `${PROMPT_TEMPLATE.system.pre}${systemContent}${PROMPT_TEMPLATE.system.post}`
+ : '';
+
+ const conversationParts: string[] = [];
+
+ for (let i = 0; i < messages.length; i += 1) {
+ const message = messages[i];
+ if (message.role === 'user') {
+ conversationParts.push(this.applyTemplate({ role: 'user', text: message.content ?? '' }));
+ continue;
+ }
+
+ if (message.role === 'assistant') {
+ let modelText = message.content ?? '';
+ if (message.tool_calls?.length) {
+ for (const toolCall of message.tool_calls) {
+ modelText += formatToolCall(toolCall.function.name, toolCall.function.arguments);
+ }
+
+ let scanIndex = i + 1;
+ while (scanIndex < messages.length && messages[scanIndex].role === 'tool') {
+ const toolMessage = messages[scanIndex];
+ const matchedCall = message.tool_calls.find(call => call.id === toolMessage.tool_call_id);
+ if (matchedCall) {
+ let parsedResult: unknown = toolMessage.content ?? '';
+ try {
+ parsedResult = JSON.parse(toolMessage.content ?? '{}');
+ } catch {
+ parsedResult = toolMessage.content ?? '';
+ }
+ modelText += formatToolResponse(matchedCall.function.name, parsedResult);
+ }
+ scanIndex += 1;
+ }
+ }
+
+ conversationParts.push(this.applyTemplate({ role: 'model', text: modelText }));
+ }
+ }
+
+ return `${systemSection}${conversationParts.join('')}${PROMPT_TEMPLATE.model.pre}`;
+ }
+
+ async *generateStream(
+ messages: Message[],
+ systemPrompt?: string,
+ tools?: OpenAIToolDefinition[],
+ ): AsyncIterableIterator {
+ const inference = await this.ensureInference();
+ const prompt = this.renderPrompt(messages, systemPrompt, tools);
+ console.log('------------ LOCAL RAW PROMPT ------------');
+ console.log(prompt);
+ console.log('------------------------------------------');
+
+ const start = performance.now();
+ let firstTokenTime: number | null = null;
+ let rawResponse = '';
+ let streamedVisibleText = '';
+ const pendingTextDeltas: string[] = [];
+ let generationError: unknown = null;
+ let generationDone = false;
+ let notifyWaiting: (() => void) | null = null;
+
+ const wake = () => {
+ if (notifyWaiting) {
+ const resolve = notifyWaiting;
+ notifyWaiting = null;
+ resolve();
+ }
+ };
+
+ const generationPromise = new Promise((resolve, reject) => {
+ try {
+ const result = inference.generateResponse(prompt, (partial, done) => {
+ if (firstTokenTime === null) {
+ firstTokenTime = performance.now();
+ }
+ rawResponse += partial;
+
+ const visibleText = stripToolProtocol(rawResponse);
+ if (visibleText.startsWith(streamedVisibleText)) {
+ const delta = visibleText.slice(streamedVisibleText.length);
+ if (delta) {
+ streamedVisibleText = visibleText;
+ pendingTextDeltas.push(delta);
+ wake();
+ }
+ } else if (visibleText && visibleText !== streamedVisibleText) {
+ const delta = visibleText.slice(streamedVisibleText.length) || visibleText;
+ streamedVisibleText = visibleText;
+ pendingTextDeltas.push(delta);
+ wake();
+ }
+
+ if (done) {
+ generationDone = true;
+ wake();
+ setTimeout(resolve, 0);
+ }
+ });
+
+ Promise.resolve(result).catch(error => {
+ generationError = error;
+ generationDone = true;
+ wake();
+ reject(error);
+ });
+ } catch (error) {
+ generationError = error;
+ generationDone = true;
+ wake();
+ reject(error);
+ }
+ });
+
+ while (!generationDone || pendingTextDeltas.length > 0) {
+ while (pendingTextDeltas.length > 0) {
+ const delta = pendingTextDeltas.shift();
+ if (delta) {
+ yield { type: 'text', content: delta };
+ }
+ }
+
+ if (generationDone) {
+ break;
+ }
+
+ await new Promise(resolve => {
+ notifyWaiting = resolve;
+ });
+ }
+
+ await generationPromise;
+ if (generationError) {
+ throw generationError;
+ }
+
+ console.log('------------ LOCAL RAW RESPONSE ------------');
+ console.log(rawResponse);
+ console.log('--------------------------------------------');
+
+ const toolCalls = parseToolCalls(rawResponse);
+ const finishReason = toolCalls.length > 0 ? 'tool_calls' : 'stop';
+
+ const promptTokenCount = inference.sizeInTokens(prompt);
+ const generatedTokenCount = inference.sizeInTokens(rawResponse);
+ const totalEnd = performance.now();
+ const prefillMs = firstTokenTime !== null ? firstTokenTime - start : 0;
+ const decodeMs = Math.max(0, totalEnd - start - prefillMs);
+ const prefillTps = prefillMs > 0 ? promptTokenCount / (prefillMs / 1000) : 0;
+ const generationTps = decodeMs > 0 ? generatedTokenCount / (decodeMs / 1000) : 0;
+ console.log(`[localLLM] prefill t/s: ${prefillTps.toFixed(1)}`);
+ console.log(`[localLLM] generation t/s: ${generationTps.toFixed(1)}`);
+
+ for (const parsed of toolCalls) {
+ const toolCall: ToolCall = {
+ id: `gemma_tool_${Date.now()}_${Math.random().toString(36).slice(2)}`,
+ type: 'function',
+ function: {
+ name: parsed.name,
+ arguments: JSON.stringify(parsed.args),
+ },
+ };
+ yield { type: 'tool_call', content: '', toolCall };
+ }
+
+ yield {
+ type: 'done',
+ content: '',
+ finishReason,
+ performanceInfo: {
+ prefillTps,
+ generationTps,
+ },
+ };
+ }
+}
diff --git a/src/agent/llm/StreamingTypes.ts b/src/agent/llm/StreamingTypes.ts
index 738ca01..4600a5f 100644
--- a/src/agent/llm/StreamingTypes.ts
+++ b/src/agent/llm/StreamingTypes.ts
@@ -4,10 +4,16 @@
import type { ToolCall } from '../core/AgentState';
+export interface PerformanceInfo {
+ prefillTps?: number;
+ generationTps?: number;
+}
+
export interface StreamChunk {
type: 'text' | 'tool_call' | 'tool_result' | 'done';
content: string;
toolCall?: ToolCall;
toolResult?: { name: string; success: boolean; result: string };
- finishReason?: string; // 'stop' | 'tool_calls' — present on 'done' chunks
+ performanceInfo?: PerformanceInfo;
+ finishReason?: string;
}
diff --git a/src/agent/llm/gemmaToolProtocol.streaming.test.ts b/src/agent/llm/gemmaToolProtocol.streaming.test.ts
new file mode 100644
index 0000000..04a388e
--- /dev/null
+++ b/src/agent/llm/gemmaToolProtocol.streaming.test.ts
@@ -0,0 +1,20 @@
+import { describe, expect, it } from 'vitest';
+import { stripToolProtocol } from './gemmaToolProtocol';
+
+describe('stripToolProtocol streaming safety', () => {
+ it('hides incomplete thought blocks entirely until they are closed', () => {
+ const partial = `<|channel>thought
+I have successfully read the music.
+I will summarize this for the user.`;
+
+ expect(stripToolProtocol(partial)).toBe('');
+ });
+
+ it('reveals visible answer cleanly after a thought block closes', () => {
+ const completed = `<|channel>thought
+Internal reasoning here.
+Here is the sheet music I read.`;
+
+ expect(stripToolProtocol(completed)).toBe('Here is the sheet music I read.');
+ });
+});
diff --git a/src/agent/llm/gemmaToolProtocol.test.ts b/src/agent/llm/gemmaToolProtocol.test.ts
new file mode 100644
index 0000000..1e64207
--- /dev/null
+++ b/src/agent/llm/gemmaToolProtocol.test.ts
@@ -0,0 +1,25 @@
+import { describe, expect, it } from 'vitest';
+import { parseToolCalls } from './gemmaToolProtocol';
+
+describe('parseToolCalls', () => {
+ it('parses nested object arguments emitted by Gemma tool calling', () => {
+ const text = '<|tool_call>call:add_notes{notes:[{pitch:<|"|>C4<|"|>,meta:{velocity:90,length:1.5}}],replaceExisting:false}';
+
+ const parsed = parseToolCalls(text);
+
+ expect(parsed).toHaveLength(1);
+ expect(parsed[0].name).toBe('add_notes');
+ expect(parsed[0].args).toEqual({
+ notes: [
+ {
+ pitch: 'C4',
+ meta: {
+ velocity: 90,
+ length: 1.5,
+ },
+ },
+ ],
+ replaceExisting: false,
+ });
+ });
+});
diff --git a/src/agent/llm/gemmaToolProtocol.ts b/src/agent/llm/gemmaToolProtocol.ts
new file mode 100644
index 0000000..2079755
--- /dev/null
+++ b/src/agent/llm/gemmaToolProtocol.ts
@@ -0,0 +1,154 @@
+import type { OpenAIToolDefinition } from '../tools/BaseTool';
+
+function gemmaValue(value: unknown): string {
+ if (typeof value === 'string') return `<|"|>${value}<|"|>`;
+ if (Array.isArray(value)) return `[${value.map(gemmaValue).join(',')}]`;
+ if (typeof value === 'object' && value !== null) {
+ return `{${Object.entries(value as Record).map(([key, nested]) => `${key}:${gemmaValue(nested)}`).join(',')}}`;
+ }
+ return String(value);
+}
+
+export function formatToolDeclaration(tool: OpenAIToolDefinition): string {
+ const body = {
+ description: tool.function.description,
+ parameters: tool.function.parameters,
+ };
+ return `<|tool>declaration:${tool.function.name}${gemmaValue(body)}`;
+}
+
+export function formatToolCall(name: string, args: string): string {
+ const parsed = JSON.parse(args) as Record;
+ return `<|tool_call>call:${name}${gemmaValue(parsed)}`;
+}
+
+export function formatToolResponse(name: string, result: unknown): string {
+ return `<|tool_response>response:${name}${gemmaValue(result)}`;
+}
+
+function parseGemmaValue(str: string, pos: number): { value: unknown; next: number } {
+ while (pos < str.length && str[pos] === ' ') pos += 1;
+
+ const stringDelimiter = '<|"|>';
+ if (str.startsWith(stringDelimiter, pos)) {
+ const start = pos + stringDelimiter.length;
+ const end = str.indexOf(stringDelimiter, start);
+ if (end === -1) {
+ return { value: '', next: str.length };
+ }
+ return { value: str.slice(start, end), next: end + stringDelimiter.length };
+ }
+
+ if (str[pos] === '{') {
+ const result: Record = {};
+ pos += 1;
+ while (pos < str.length && str[pos] !== '}') {
+ while (pos < str.length && (str[pos] === ',' || str[pos] === ' ')) pos += 1;
+ if (str[pos] === '}') break;
+ const colonIndex = str.indexOf(':', pos);
+ if (colonIndex === -1) break;
+ const key = str.slice(pos, colonIndex).trim();
+ pos = colonIndex + 1;
+ const nested = parseGemmaValue(str, pos);
+ result[key] = nested.value;
+ pos = nested.next;
+ }
+ return { value: result, next: pos + 1 };
+ }
+
+ if (str[pos] === '[') {
+ const result: unknown[] = [];
+ pos += 1;
+ while (pos < str.length && str[pos] !== ']') {
+ while (pos < str.length && (str[pos] === ',' || str[pos] === ' ')) pos += 1;
+ if (str[pos] === ']') break;
+ const nested = parseGemmaValue(str, pos);
+ result.push(nested.value);
+ pos = nested.next;
+ }
+ return { value: result, next: pos + 1 };
+ }
+
+ let end = pos;
+ while (end < str.length && str[end] !== ',' && str[end] !== '}' && str[end] !== ']') end += 1;
+ const raw = str.slice(pos, end).trim();
+ if (raw === 'true') return { value: true, next: end };
+ if (raw === 'false') return { value: false, next: end };
+ if (raw !== '' && !Number.isNaN(Number(raw))) return { value: Number(raw), next: end };
+ return { value: raw, next: end };
+}
+
+function parseArgs(argsStr: string): Record {
+ const parsed = parseGemmaValue(`{${argsStr}}`, 0).value;
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
+ return {};
+ }
+ return parsed as Record;
+}
+
+export interface ParsedGemmaToolCall {
+ name: string;
+ args: Record;
+ fullMatch: string;
+ index: number;
+ endIndex: number;
+}
+
+export function parseToolCalls(text: string): ParsedGemmaToolCall[] {
+ const prefix = '<|tool_call>call:';
+ const suffix = '';
+ const stringDelimiter = '<|"|>';
+ const calls: ParsedGemmaToolCall[] = [];
+ let searchFrom = 0;
+
+ while (true) {
+ const prefixIndex = text.indexOf(prefix, searchFrom);
+ if (prefixIndex === -1) break;
+
+ const braceStart = text.indexOf('{', prefixIndex + prefix.length);
+ if (braceStart === -1) break;
+ const name = text.slice(prefixIndex + prefix.length, braceStart).trim();
+
+ let depth = 1;
+ let index = braceStart + 1;
+ while (index < text.length && depth > 0) {
+ if (text.startsWith(stringDelimiter, index)) {
+ const stringEnd = text.indexOf(stringDelimiter, index + stringDelimiter.length);
+ index = stringEnd === -1 ? text.length : stringEnd + stringDelimiter.length;
+ continue;
+ }
+ if (text[index] === '{') depth += 1;
+ else if (text[index] === '}') depth -= 1;
+ index += 1;
+ }
+ const braceEnd = index;
+ const suffixIndex = text.indexOf(suffix, braceEnd);
+ if (suffixIndex === -1) break;
+
+ const argsStr = text.slice(braceStart + 1, braceEnd - 1);
+ const endIndex = suffixIndex + suffix.length;
+ calls.push({
+ name,
+ args: parseArgs(argsStr),
+ fullMatch: text.slice(prefixIndex, endIndex),
+ index: prefixIndex,
+ endIndex,
+ });
+ searchFrom = endIndex;
+ }
+
+ return calls;
+}
+
+export function stripToolProtocol(text: string): string {
+ let result = text.replace(
+ /<\|tool_call>call:(\w+)\{[\s\S]*?\}<\|tool_response>[\s\S]*?/g,
+ '[Tool call completed]',
+ );
+ result = result.replace(/<\|channel>thought[\s\S]*?/g, '');
+ result = result.replace(/<\|channel>thought[\s\S]*/g, '');
+ result = result.replace(/<\|tool_call>[\s\S]*/g, '');
+ result = result.replace(/<\|tool_response>[\s\S]*/g, '');
+ result = result.replace(/<\|"\|>/g, '');
+ return result.trimStart();
+}
diff --git a/src/components/ChatBox.css b/src/components/ChatBox.css
index 4f61eec..f71ee3a 100644
--- a/src/components/ChatBox.css
+++ b/src/components/ChatBox.css
@@ -85,6 +85,77 @@
overflow-y: auto;
}
+.chatbox-local-runtime-section {
+ padding: 10px 14px 0 14px;
+}
+
+.chatbox-local-runtime-card {
+ background-color: #252525;
+ border: 1px solid #3a3a3a;
+ border-radius: 6px;
+ margin-bottom: 12px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+}
+
+.chatbox-local-mode-title {
+ color: #e0e0e0;
+ font-size: 12px;
+ font-weight: 600;
+ margin: 0;
+}
+
+.chatbox-local-runtime-help,
+.chatbox-local-runtime-warning,
+.chatbox-local-runtime-error {
+ font-size: 11px;
+ line-height: 1.45;
+ margin: 0;
+}
+
+.chatbox-local-runtime-help {
+ color: #999;
+}
+
+.chatbox-local-runtime-warning {
+ color: #d0a56b;
+}
+
+.chatbox-local-runtime-error {
+ color: #d45a5a;
+ margin-bottom: 0;
+}
+
+.chatbox-progress-block {
+ display: flex;
+ flex-direction: column;
+ gap: 6px;
+}
+
+.chatbox-progress-track {
+ width: 100%;
+ height: 8px;
+ background-color: #1d1d1d;
+ border: 1px solid #3a3a3a;
+ border-radius: 999px;
+ overflow: hidden;
+}
+
+.chatbox-progress-fill {
+ height: 100%;
+ background: linear-gradient(90deg, #5a9fd4 0%, #7cc2f1 100%);
+ transition: width 0.15s linear;
+}
+
+.chatbox-gen-hint {
+ color: #888;
+ font-size: 10px;
+ text-align: center;
+ margin-top: -4px;
+}
+
/* Chat Messages */
.chatbox-messages {
flex: 1;
@@ -207,6 +278,16 @@
color: #ccc;
}
+.message-content .katex-display {
+ margin: 8px 0;
+ overflow-x: auto;
+ overflow-y: hidden;
+}
+
+.message-content .katex {
+ max-width: 100%;
+}
+
.message-content table {
border-collapse: collapse;
width: 100%;
@@ -226,6 +307,12 @@
font-weight: bold;
}
+.message-performance-info {
+ margin-top: 8px;
+ font-size: 10px;
+ color: #909090;
+}
+
/* Abort link styling */
.abort-link {
background: none !important;
@@ -310,4 +397,4 @@
100% {
background-position: -200% 0%;
}
-}
\ No newline at end of file
+}
diff --git a/src/components/ChatBox.tsx b/src/components/ChatBox.tsx
index c2736b4..7a3732b 100644
--- a/src/components/ChatBox.tsx
+++ b/src/components/ChatBox.tsx
@@ -3,7 +3,8 @@ import './ChatBox.css';
import { FaPlus, FaBan, FaDownload } from 'react-icons/fa';
import { UserMessage, AssistantMessage } from './chat';
import { AgentCore } from '../agent/core/AgentCore';
-import { LLMProvider } from '../agent/llm/LLMProvider';
+import { OpenAICompatibleLLMProvider, type LLMProvider } from '../agent/llm/LLMProvider';
+import { LocalBrowserLLMProvider } from '../agent/llm/LocalBrowserLLMProvider';
import { ConfigManager } from '../core/config/ConfigManager';
import { useProjectStore } from '../stores/projectStore';
import { SystemPrompts } from '../agent/core/SystemPrompts';
@@ -13,6 +14,8 @@ import { useStreamProcessor } from '../hooks/useStreamProcessor';
import { createMessage, addWelcomeMessage } from '../utils/chatMessageUtils';
import { formatLocalDateTime } from '../util/timeUtil';
import { downloadBlob, buildTimestampSuffix } from '../util/miscUtil';
+import { LocalLLMModelManager, type LocalLLMModelState } from '../util/localLLMModelManager';
+import { LOCAL_LLM_DISPLAY_NAME, LOCAL_LLM_PROVIDER_KEY } from '../util/localLLMConfig';
import KGDropdown from './common/KGDropdown';
import type { ChatMessage } from '../types/projectTypes';
@@ -32,6 +35,8 @@ const createLLMProviderFromConfig = (): LLMProvider => {
let baseURL: string | undefined;
switch (providerType) {
+ case LOCAL_LLM_PROVIDER_KEY:
+ return new LocalBrowserLLMProvider();
case 'openai':
apiKey = configManager.get('general.openai.api_key') as string;
model = configManager.get('general.openai.model') as string;
@@ -50,7 +55,7 @@ const createLLMProviderFromConfig = (): LLMProvider => {
break;
}
- return new LLMProvider(apiKey, model, baseURL);
+ return new OpenAICompatibleLLMProvider(apiKey, model, baseURL);
};
interface ChatBoxProps {
@@ -64,6 +69,8 @@ const ChatBox: React.FC = ({ isVisible }) => {
const [messages, setMessages] = useState([]);
const [isProcessing, setIsProcessing] = useState(false);
const [lastUserMessage, setLastUserMessage] = useState('');
+ const [localModelState, setLocalModelState] = useState(LocalLLMModelManager.getState());
+ const [activeProvider, setActiveProvider] = useState('openai');
// Track if this is the first message (for system prompt logging)
const [isFirstMessage, setIsFirstMessage] = useState(true);
@@ -180,9 +187,11 @@ const ChatBox: React.FC = ({ isVisible }) => {
}
const applyProviderFromConfig = () => {
+ const providerType = (configManager.get('general.llm_provider') as string) || 'openai';
const provider = createLLMProviderFromConfig();
const agentCore = AgentCore.instance();
agentCore.setLLMProvider(provider);
+ setActiveProvider(providerType);
console.log('LLM provider configured');
};
@@ -191,6 +200,7 @@ const ChatBox: React.FC = ({ isVisible }) => {
const unsubscribe = configManager.addChangeListener((changedKeys) => {
if (
changedKeys.includes('general.llm_provider') ||
+ changedKeys.includes('general.local_browser.context_length') ||
changedKeys.some(k => k.startsWith('general.openai.')) ||
changedKeys.some(k => k.startsWith('general.openai_compatible.'))
) {
@@ -204,6 +214,7 @@ const ChatBox: React.FC = ({ isVisible }) => {
registerClearChatUICallback(clearChatUI);
const maybeUnsubscribePromise = initializeProvider();
+ const unsubscribeLocalModel = LocalLLMModelManager.subscribe(setLocalModelState);
(async () => {
if (hasShownWelcomeOnceInRuntime) return;
@@ -216,6 +227,7 @@ const ChatBox: React.FC = ({ isVisible }) => {
})();
return () => {
+ unsubscribeLocalModel();
Promise.resolve(maybeUnsubscribePromise).then((cleanup) => {
if (typeof cleanup === 'function') cleanup();
}).catch(() => {});
@@ -266,7 +278,10 @@ const ChatBox: React.FC = ({ isVisible }) => {
// Log system prompt only for first message
if (isFirstMessage) {
try {
- const systemPrompt = await SystemPrompts.getSystemPromptWithContext();
+ const provider = AgentCore.instance().getLLMProvider();
+ const systemPrompt = await SystemPrompts.getSystemPromptWithContext(
+ provider?.getPreferredSystemPromptPath?.(),
+ );
console.log('------------ SYSTEM ------------');
console.log(systemPrompt);
console.log('--------------------------------');
@@ -372,6 +387,45 @@ const ChatBox: React.FC = ({ isVisible }) => {
+ The local language model has not been downloaded yet. It will be downloaded automatically the next time you send a chat request with this provider.
+
- Base URL of a running K.G.One server. Used for full-song generation, clip generation, and stem separation.
+ Base URL of a running K.G.One Music Studio server. Used for full-song generation, clip generation, and stem separation.
@@ -600,4 +720,4 @@ const GeneralSettings: React.FC = () => {
);
};
-export default GeneralSettings;
\ No newline at end of file
+export default GeneralSettings;
diff --git a/src/components/track/RegionItem.tsx b/src/components/track/RegionItem.tsx
index 9f92bd5..ed5a17a 100644
--- a/src/components/track/RegionItem.tsx
+++ b/src/components/track/RegionItem.tsx
@@ -45,6 +45,7 @@ interface RegionItemProps {
audioBuffer?: AudioBuffer;
previewWaveformPeaks?: AudioRecordingPeak[];
isPreview?: boolean;
+ isAudioRegion?: boolean;
}
const RegionItem: React.FC = ({
@@ -71,6 +72,7 @@ const RegionItem: React.FC = ({
audioBuffer,
previewWaveformPeaks,
isPreview = false,
+ isAudioRegion = false,
}) => {
// Get selection state and time signature from store
const { selectedRegionIds, timeSignature, bpm } = useProjectStore();
@@ -652,7 +654,7 @@ const RegionItem: React.FC = ({
return (