├── .npmignore ├── .czrc ├── tsconfig.lint.json ├── artifacts ├── bergamot-translator-worker.wasm └── bergamot-translator-worker.js ├── .gitignore ├── release.sh ├── example ├── README.md └── src │ ├── index.html │ └── index.css ├── .cspell.json ├── scripts ├── clean.ts ├── build.ts ├── testSetup.ts └── setup.ts ├── src ├── bergamot-translator │ ├── README.md │ └── Dockerfile ├── index.ts ├── main.ts └── worker.ts ├── tsconfig.json ├── .releaserc.json ├── .github └── workflows │ └── browsermt.yml ├── LICENSE ├── esbuild-hook.js ├── README.md ├── .eslintrc.json └── package.json /.npmignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | node_modules/ 3 | .nyc_output/ 4 | coverage/ 5 | example/ 6 | -------------------------------------------------------------------------------- /.czrc: -------------------------------------------------------------------------------- 1 | { 2 | "path": "./node_modules/@ryansonshine/cz-conventional-changelog" 3 | } 4 | -------------------------------------------------------------------------------- /tsconfig.lint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": [] 4 | } 5 | -------------------------------------------------------------------------------- /artifacts/bergamot-translator-worker.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sign/browsermt/main/artifacts/bergamot-translator-worker.wasm -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | 3 | build/ 4 | node_modules/ 5 | .nyc_output/ 6 | coverage/ 7 | .DS_Store 8 | 9 | example/src/models/ 10 | example/src/firefox-translations-models/ -------------------------------------------------------------------------------- /release.sh: -------------------------------------------------------------------------------- 1 | npm ci 2 | 3 | # Dependencies audit 4 | npm audit 5 | 6 | # Build 7 | npm run build 8 | 9 | # Format check 10 | npm run format 11 | 12 | # Lint check 13 | npm run lint 14 | 15 | # Spell check 16 | npm run spell:check 17 | 18 | # Release 19 | npm run semantic-release 20 | 21 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # Example 2 | 3 | To get models for the example, run: 4 | 5 | ```bash 6 | git clone --depth 1 --branch main --single-branch https://github.com/mozilla/firefox-translations-models/ 7 | mkdir models 8 | cp -rf firefox-translations-models/registry.json models 9 | cp -rf firefox-translations-models/models/prod/* models 10 | cp -rf firefox-translations-models/models/dev/* models 11 | gunzip models/*/* 12 | ``` 13 | -------------------------------------------------------------------------------- /.cspell.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1", 3 | "language": "en", 4 | "words": [ 5 | "esbuild", 6 | "rmrf", 7 | "gjuchault", 8 | "socio", 9 | "octocat", 10 | "comlink", 11 | "browsermt", 12 | "gemm", 13 | "enru", 14 | "intgemm" 15 | ], 16 | "flagWords": [], 17 | "ignorePaths": [ 18 | "package.json", 19 | "package-lock.json", 20 | "tsconfig.json", 21 | "node_modules/**" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /scripts/clean.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs/promises"; 2 | import path from "path"; 3 | 4 | async function main() { 5 | await Promise.all([rmrf("build"), rmrf("coverage"), rmrf(".nyc_output")]); 6 | } 7 | 8 | async function rmrf(pathFromRoot: string): Promise { 9 | await fs.rm(path.join(__dirname, "../", pathFromRoot), { 10 | recursive: true, 11 | force: true, 12 | }); 13 | } 14 | 15 | if (require.main === module) { 16 | main(); 17 | } 18 | -------------------------------------------------------------------------------- /src/bergamot-translator/README.md: -------------------------------------------------------------------------------- 1 | # Bergamot Translator 2 | 3 | Bergamot is the tool we use for translating locally in the browser, even offline. 4 | 5 | In order to get the relevant wasm files, we must run: 6 | 7 | ``` 8 | docker build --platform linux/amd64 -t bergamot . 9 | ``` 10 | 11 | To run a server and make sure the build was successful, run: 12 | 13 | ``` 14 | docker run -it -p 80:80 bergamot 15 | ``` 16 | 17 | Then we copy the worker files to the `bergamot` directory. 18 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["./src/**/*.ts"], 3 | "exclude": ["./src/**/__tests__"], 4 | "compilerOptions": { 5 | "lib": ["es2020", "dom"], 6 | "module": "commonjs", 7 | "target": "es2020", 8 | 9 | "rootDir": "./", 10 | "outDir": "build", 11 | 12 | "strict": true, 13 | "sourceMap": true, 14 | "esModuleInterop": true, 15 | "skipLibCheck": true, 16 | "forceConsistentCasingInFileNames": true, 17 | "declaration": true, 18 | "resolveJsonModule": true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.releaserc.json: -------------------------------------------------------------------------------- 1 | { 2 | "branches": [ 3 | "+([0-9])?(.{+([0-9]),x}).x", 4 | "main", 5 | "master", 6 | "next", 7 | "next-major", 8 | { 9 | "name": "beta", 10 | "prerelease": true 11 | }, 12 | { 13 | "name": "alpha", 14 | "prerelease": true 15 | } 16 | ], 17 | "repositoryUrl": "https://github.com/sign/browsermt", 18 | "plugins": [ 19 | "@semantic-release/commit-analyzer", 20 | "@semantic-release/release-notes-generator", 21 | "@semantic-release/changelog", 22 | "@semantic-release/npm", 23 | "@semantic-release/github" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /scripts/build.ts: -------------------------------------------------------------------------------- 1 | import path from "path"; 2 | import { build as esbuild } from "esbuild"; 3 | 4 | const baseConfig = { 5 | platform: "node" as const, 6 | target: "esnext" as const, 7 | format: "cjs" as const, 8 | nodePaths: [path.join(__dirname, "../src")], 9 | sourcemap: true, 10 | external: [], 11 | }; 12 | 13 | async function main() { 14 | const entryPoints = [ 15 | path.join(__dirname, "../src/index.ts"), 16 | path.join(__dirname, "../src/main.ts"), 17 | path.join(__dirname, "../src/worker.ts"), 18 | ]; 19 | await esbuild({ 20 | ...baseConfig, 21 | outdir: path.join(__dirname, "../build/cjs"), 22 | entryPoints, 23 | }); 24 | 25 | await esbuild({ 26 | ...baseConfig, 27 | format: "esm", 28 | outdir: path.join(__dirname, "../build/esm"), 29 | entryPoints, 30 | }); 31 | 32 | await esbuild({ 33 | ...baseConfig, 34 | format: "esm", 35 | bundle: true, 36 | outdir: path.join(__dirname, "../build/bundled"), 37 | entryPoints, 38 | }); 39 | } 40 | 41 | if (require.main === module) { 42 | main(); 43 | } 44 | -------------------------------------------------------------------------------- /example/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Mozilla Translations 5 | 6 | 7 | 11 | 12 | 13 |
14 |
15 | 19 | 20 |
21 | 22 |
23 | 27 |
28 |
29 | 30 |
31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /.github/workflows/browsermt.yml: -------------------------------------------------------------------------------- 1 | name: browsermt 2 | 3 | on: 4 | push: 5 | branches: [master, main] 6 | 7 | env: 8 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 9 | 10 | jobs: 11 | browsermt: 12 | runs-on: ubuntu-latest 13 | 14 | concurrency: 15 | group: ${{ github.ref }} 16 | cancel-in-progress: true 17 | 18 | steps: 19 | - uses: actions/checkout@v3 20 | 21 | - uses: volta-cli/action@v1 22 | 23 | - run: npm ci 24 | 25 | - name: Dependencies audit 26 | run: npm audit 27 | 28 | - name: Build 29 | run: npm run build 30 | 31 | - name: Format check 32 | run: npm run format:check 33 | 34 | - name: Lint check 35 | run: npm run lint:check 36 | 37 | - name: Spell check 38 | run: npm run spell:check 39 | # - name: Test 40 | # run: npm run test 41 | # 42 | # - name: Setup test 43 | # run: npm run test:setup 44 | 45 | # - name: Release 46 | # env: 47 | # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 48 | # NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 49 | # run: npm run semantic-release 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 sign 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /esbuild-hook.js: -------------------------------------------------------------------------------- 1 | const Module = require("module"); 2 | const { transformSync } = require("esbuild"); 3 | const sourceMapSupport = require("source-map-support"); 4 | 5 | const cache = {}; 6 | 7 | function esbuildHook(code, filepath) { 8 | const result = transformSync(code, { 9 | target: "node16", 10 | sourcemap: "both", 11 | loader: "ts", 12 | format: "cjs", 13 | sourcefile: filepath, 14 | }); 15 | 16 | cache[filepath] = { 17 | url: filepath, 18 | code: result.code, 19 | map: result.map, 20 | }; 21 | 22 | return result.code; 23 | } 24 | 25 | sourceMapSupport.install({ 26 | environment: "node", 27 | retrieveFile(pathOrUrl) { 28 | const file = cache[pathOrUrl]; 29 | if (file) { 30 | return file.code; 31 | } else { 32 | return ""; 33 | } 34 | }, 35 | }); 36 | 37 | const defaultLoader = Module._extensions[".js"]; 38 | 39 | Module._extensions[".ts"] = function (mod, filename) { 40 | if (filename.includes("node_modules")) { 41 | return defaultLoader(mod, filename); 42 | } 43 | 44 | const defaultCompile = mod._compile; 45 | mod._compile = function (code) { 46 | mod._compile = defaultCompile; 47 | return mod._compile(esbuildHook(code, filename), filename); 48 | }; 49 | 50 | defaultLoader(mod, filename); 51 | }; 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `sign`/browsermt 2 | 3 | Based on https://github.com/gjuchault/typescript-library-starter 4 | 5 | This library is designed as a drop-in to run Bergamot models in the browser. 6 | 7 | ## Installation 8 | 9 | ``` 10 | npm install @sign-mt/browsermt 11 | ``` 12 | 13 | ## Usage 14 | 15 | ```ts 16 | import { createBergamotWorker } from "@sign-mt/browsermt"; 17 | // OR import {createBergamotWorker} from 'https://unpkg.com/@sign-mt/browsermt@0.0.2/build/bundled/index.js' 18 | 19 | const worker = createBergamotWorker( 20 | "/node_modules/@sign-mt/browsermt/build/esm/worker.js" 21 | ); 22 | // OR createBergamotWorker('https://unpkg.com/@sign-mt/browsermt@0.0.2/build/bundled/worker.js') 23 | 24 | // Copy these artifacts to your deployed folder 25 | await worker.importBergamotWorker( 26 | "browsermt/bergamot-translator-worker.js", 27 | "browsermt/bergamot-translator-worker.wasm" 28 | ); 29 | 30 | // Create object with URLs to the model files 31 | const modelRegistry = { 32 | enru: { 33 | model: { name: "/models/enru/model.enru.intgemm.alphas.bin" }, 34 | lex: { name: "/models/enru/lex.50.50.enru.s2t.bin" }, 35 | vocab: { name: "/models/enru/vocab.enru.spm" }, 36 | }, 37 | }; 38 | 39 | await worker.loadModel("en", "ru", modelRegistry); 40 | 41 | const translations = await worker.translate( 42 | "en", 43 | "ru", 44 | ["test sentence", "other sentence"], 45 | [{ isHtml: false }, { isHtml: false }] 46 | ); 47 | console.log(translations); 48 | ``` 49 | -------------------------------------------------------------------------------- /src/bergamot-translator/Dockerfile: -------------------------------------------------------------------------------- 1 | # Steps from https://github.com/browsermt/bergamot-translator 2 | # docker build --platform linux/amd64 -t bergamot . 3 | # docker run -it -p 80:80 bergamot 4 | # docker cp 4f0ed685abd1:/bergamot-translator/build-wasm/bergamot-translator-worker.wasm artifacts/bergamot-translator-worker.wasm 5 | # docker cp 4f0ed685abd1:/bergamot-translator/build-wasm/bergamot-translator-worker.js artifacts/bergamot-translator-worker.js 6 | 7 | # python required by emcmake 8 | FROM python:3.9.13 9 | 10 | RUN apt-get update 11 | RUN apt-get install -y git git-lfs cmake 12 | 13 | # WASM prerequisites 14 | RUN git clone https://github.com/emscripten-core/emsdk.git 15 | WORKDIR emsdk 16 | RUN ./emsdk install 3.1.8 17 | RUN ./emsdk activate 3.1.8 18 | # RUN /bin/bash -c "source ./emsdk_env.sh" 19 | 20 | # Compile 21 | WORKDIR / 22 | RUN git clone https://github.com/browsermt/bergamot-translator.git 23 | WORKDIR bergamot-translator 24 | RUN mkdir build-wasm 25 | 26 | 27 | WORKDIR build-wasm 28 | RUN /emsdk/upstream/emscripten/emcmake cmake -DCOMPILE_WASM=on -DWORMHOLE=off ../ 29 | RUN /emsdk/upstream/emscripten/emmake make -j2 30 | RUN bash ../wasm/patch-artifacts-import-gemm-module.sh 31 | 32 | # Test server 33 | WORKDIR /bergamot-translator/wasm/test_page 34 | RUN apt install nodejs npm -y 35 | RUN npm install 36 | RUN chmod +x start_server.sh 37 | # Get models 38 | RUN git clone --depth 1 --branch main --single-branch https://github.com/mozilla/firefox-translations-models/ 39 | RUN mkdir models 40 | RUN cp -rf firefox-translations-models/registry.json models 41 | RUN cp -rf firefox-translations-models/models/prod/* models 42 | RUN cp -rf firefox-translations-models/models/dev/* models 43 | RUN gunzip models/*/* 44 | 45 | ENTRYPOINT ["./start_server.sh", "../../build-wasm"] 46 | 47 | -------------------------------------------------------------------------------- /scripts/testSetup.ts: -------------------------------------------------------------------------------- 1 | import childProcess from "child_process"; 2 | import { promisify } from "util"; 3 | import { run } from "./setup"; 4 | 5 | const exec = promisify(childProcess.exec); 6 | 7 | async function main() { 8 | try { 9 | const { stdout: gitEmail } = await exec( 10 | `git config --global --get user.email` 11 | ); 12 | 13 | if (!gitEmail.trim().length) { 14 | await exec(`git config --global user.email actions@github.com`); 15 | await exec(`git config --global user.name GithubActions`); 16 | } 17 | } catch (err) { 18 | await exec(`git config --global user.email actions@github.com`); 19 | await exec(`git config --global user.name GithubActions`); 20 | } 21 | 22 | await run({ 23 | githubUserName: "ghUserName", 24 | packageName: "packageName", 25 | userMail: "ghUserName@mail.com", 26 | }); 27 | 28 | try { 29 | await test(); 30 | } catch (err) { 31 | throw err; 32 | } finally { 33 | await restore(); 34 | } 35 | } 36 | 37 | async function test() { 38 | await testNoGrep("gjuchault"); 39 | await testNoGrep("typescript-library-starter"); 40 | await testNoGrep("template"); 41 | } 42 | 43 | async function restore() { 44 | await exec(`git reset HEAD~ && git checkout . && git clean -df`); 45 | 46 | await exec( 47 | `git remote add origin git@github.com:gjuchault/typescript-library-starter.git` 48 | ); 49 | 50 | await exec(`npm install`); 51 | } 52 | 53 | async function testNoGrep(pattern: string) { 54 | try { 55 | await exec( 56 | `grep -r "${pattern}" --exclude-dir=node_modules --exclude-dir=.git --exclude=README.md .` 57 | ); 58 | } catch (err) { 59 | if ((err as unknown as Record).stderr === "") { 60 | return; 61 | } 62 | 63 | throw err; 64 | } 65 | } 66 | 67 | if (require.main === module) { 68 | main(); 69 | } 70 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "env": { 4 | "es2021": true, 5 | "node": true 6 | }, 7 | "parser": "@typescript-eslint/parser", 8 | "parserOptions": { 9 | "project": "./tsconfig.lint.json" 10 | }, 11 | "plugins": ["import", "@typescript-eslint"], 12 | "ignorePatterns": ["scripts/*", "esbuild-hook.js"], 13 | "extends": [ 14 | "eslint:recommended", 15 | "plugin:eslint-comments/recommended", 16 | "plugin:@typescript-eslint/eslint-recommended", 17 | "plugin:@typescript-eslint/recommended", 18 | "plugin:@typescript-eslint/recommended-requiring-type-checking", 19 | "plugin:@typescript-eslint/strict", 20 | "plugin:import/recommended", 21 | "plugin:import/typescript", 22 | "prettier" 23 | ], 24 | "settings": { 25 | "import/resolver": { 26 | "typescript": { 27 | "project": "tsconfig.json" 28 | } 29 | } 30 | }, 31 | "rules": { 32 | "import/order": [ 33 | "error", 34 | { 35 | "alphabetize": { 36 | "order": "asc", 37 | "caseInsensitive": true 38 | } 39 | } 40 | ], 41 | "import/no-extraneous-dependencies": "error", 42 | "import/no-mutable-exports": "error", 43 | "import/no-unused-modules": "error", 44 | "@typescript-eslint/no-non-null-assertion": "off", 45 | "@typescript-eslint/no-unsafe-return": "off", 46 | "@typescript-eslint/no-unsafe-call": "off", 47 | "@typescript-eslint/no-unsafe-member-access": "off", 48 | "@typescript-eslint/no-unsafe-assignment": "off", 49 | "@typescript-eslint/restrict-template-expressions": "off", 50 | "@typescript-eslint/no-unnecessary-condition": "off", 51 | "@typescript-eslint/no-unsafe-argument": "off", 52 | "@typescript-eslint/require-await": "off", 53 | "@typescript-eslint/no-explicit-any": "off", 54 | "@typescript-eslint/no-misused-new": "off", 55 | "@typescript-eslint/no-misused-promises": "off", 56 | "@typescript-eslint/ban-ts-comment": "off", 57 | "@typescript-eslint/no-var-requires": "off", 58 | "@typescript-eslint/no-unused-vars": "off", 59 | "no-var": "off" 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import * as comlink from "comlink"; 2 | 3 | interface ModelInfoPiece { 4 | estimatedCompressedSize: number; 5 | expectedSha256Hash: string; 6 | modelType: string; 7 | name: string; 8 | size: number; 9 | } 10 | 11 | interface ModelInfo { 12 | model: ModelInfoPiece; 13 | vocab?: ModelInfoPiece; 14 | srcvocab?: ModelInfoPiece; 15 | trgvocab?: ModelInfoPiece; 16 | lex: ModelInfoPiece; 17 | qualityModel: ModelInfoPiece; 18 | } 19 | 20 | export type ModelRegistry = Record; 21 | 22 | // Information corresponding to each file type 23 | type FileType = "model" | "lex" | "vocab" | "srcvocab" | "trgvocab" | "qualityModel"; 24 | 25 | export interface FileInfo { 26 | type: FileType; 27 | alignment: number; 28 | } 29 | 30 | export interface TranslationOptions { 31 | isHtml?: boolean; 32 | isQualityScores?: boolean; 33 | } 34 | 35 | export interface TranslationResponse { 36 | text: string; 37 | } 38 | 39 | interface WorkerInterface { 40 | importBergamotWorker: ( 41 | jsFilePath: string, 42 | wasmFilePath: string | Buffer 43 | ) => Promise; 44 | loadModel: ( 45 | from: string, 46 | to: string, 47 | modelRegistry: ModelRegistry 48 | ) => Promise; 49 | translate: ( 50 | from: string, 51 | to: string, 52 | sentences: string[], 53 | options: TranslationOptions[] 54 | ) => Promise; 55 | terminate: () => Promise; 56 | } 57 | 58 | export type ComlinkWorkerInterface = comlink.Remote; 59 | 60 | export function createBergamotWorker(path: string): ComlinkWorkerInterface { 61 | const workerClass = 62 | "Worker" in globalThis ? globalThis.Worker : require("web-worker"); 63 | const worker: Worker = new workerClass(path); 64 | const abortionError = new Promise((resolve, reject) => { 65 | worker.addEventListener("error", reject); 66 | worker.addEventListener("close", resolve); 67 | }); 68 | 69 | return new Proxy(comlink.wrap(worker), { 70 | get(target, prop, receiver) { 71 | if (prop === "terminate") { 72 | return () => { 73 | worker.terminate(); 74 | }; 75 | } 76 | const targetProp = Reflect.get(target, prop, receiver); 77 | if (typeof targetProp === "function") { 78 | return (...args: any[]) => { 79 | // If for any reason the worker terminates unexpectedly, reject the promise 80 | return Promise.race([targetProp(...args), abortionError]); 81 | }; 82 | } 83 | return targetProp; 84 | }, 85 | }); 86 | } 87 | -------------------------------------------------------------------------------- /example/src/index.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | html, 6 | body { 7 | height: 100%; 8 | margin: 0; 9 | font-size: 18px; 10 | font-family: Optima, Helvetica, Arial; 11 | } 12 | 13 | body { 14 | padding: 1rem; 15 | } 16 | 17 | .app { 18 | padding: 1rem; 19 | display: grid; 20 | grid: "from swap to" 1fr "status status status" auto / 1fr auto 1fr; 21 | grid-gap: 1rem; 22 | overflow: hidden; 23 | min-height: 400px; 24 | max-width: 1024px; 25 | margin: 1em auto; 26 | } 27 | 28 | @media screen and (max-width: 640px) { 29 | .app { 30 | grid: "from from" auto "status swap" auto "to to" auto / 1fr; 31 | } 32 | } 33 | 34 | .panel { 35 | display: grid; 36 | grid-template-rows: auto 1fr; 37 | grid-gap: 1rem; 38 | } 39 | 40 | label { 41 | padding: 0 0.5em; 42 | display: flex; 43 | align-items: center; 44 | } 45 | 46 | .lang-select { 47 | padding: 0.25rem 0.5rem; 48 | margin-left: 1rem; 49 | background: #f4f4f4; 50 | font-size: 0.9rem; 51 | border: 1px solid #ccc; 52 | border-radius: 0.25rem; 53 | cursor: pointer; 54 | } 55 | 56 | .panel--from { 57 | grid-area: from; 58 | } 59 | 60 | .panel--to { 61 | grid-area: to; 62 | } 63 | 64 | .swap { 65 | align-self: center; 66 | grid-area: swap; 67 | font-size: 1.1rem; 68 | } 69 | 70 | #status { 71 | grid-area: status; 72 | text-align: center; 73 | align-self: center; 74 | } 75 | 76 | textarea, 77 | .output-area { 78 | padding: 1rem; 79 | font-family: sans-serif; 80 | font-size: 1rem; 81 | resize: none; 82 | border-radius: 2px; 83 | border: 1px solid #ccc; 84 | } 85 | 86 | button { 87 | cursor: pointer; 88 | border: 1px solid #88c; 89 | border-radius: 4px; 90 | background: #eef; 91 | padding: 0; 92 | padding: 0.25rem 0.5rem; 93 | } 94 | button:hover { 95 | background: #cce; 96 | } 97 | 98 | #output { 99 | background-color: #f4f4f4; 100 | } 101 | 102 | .output-area [x-bergamot-word-score].bad { 103 | background-image: linear-gradient( 104 | 45deg, 105 | transparent 65%, 106 | red 80%, 107 | transparent 90% 108 | ), 109 | linear-gradient(135deg, transparent 5%, red 15%, transparent 25%), 110 | linear-gradient(135deg, transparent 45%, red 55%, transparent 65%), 111 | linear-gradient(45deg, transparent 25%, red 35%, transparent 50%); 112 | background-repeat: repeat-x; 113 | background-size: 8px 2px; 114 | background-position: 0 95%; 115 | } 116 | 117 | .output-area [x-bergamot-sentence-score].bad { 118 | background: rgba(255, 128, 128, 0.8); 119 | } 120 | 121 | .output-area [x-bergamot-sentence-index].highlight-sentence { 122 | background: rgba(255, 255, 128, 0.8); 123 | } 124 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@sign-mt/browsermt", 3 | "version": "0.2.3", 4 | "description": "browsermt inference code", 5 | "keywords": [ 6 | "browsermt", 7 | "bergamot" 8 | ], 9 | "homepage": "https://github.com/sign/browsermt", 10 | "bugs": "https://github.com/sign/browsermt/issues", 11 | "author": "sign.mt ltd", 12 | "repository": "sign/browsermt", 13 | "main": "./build/cjs/index.js", 14 | "module": "./build/esm/index.js", 15 | "types": "./build/src/index.d.ts", 16 | "engines": { 17 | "node": "^18.7.0 || >= 16", 18 | "npm": "^8.16.0 || >= 8" 19 | }, 20 | "volta": { 21 | "node": "18.7.0", 22 | "npm": "8.16.0" 23 | }, 24 | "publishConfig": { 25 | "access": "public" 26 | }, 27 | "scripts": { 28 | "setup": "node -r ./esbuild-hook ./scripts/setup", 29 | "build": "npm run clean && npm run type:dts && npm run build:main", 30 | "build:main": "node -r ./esbuild-hook ./scripts/build", 31 | "clean": "node -r ./esbuild-hook ./scripts/clean", 32 | "type:dts": "tsc --emitDeclarationOnly", 33 | "type:check": "tsc --noEmit", 34 | "format": "prettier \"src/**/*.ts\" --write", 35 | "format:check": "prettier \"src/**/*.ts\" --check", 36 | "lint": "eslint src --ext .ts --fix", 37 | "lint:check": "eslint src --ext .ts", 38 | "test": "vitest run", 39 | "test:watch": "vitest watch", 40 | "test:coverage": "vitest run --coverage", 41 | "test:setup": "node -r ./esbuild-hook ./scripts/testSetup", 42 | "spell:check": "cspell \"{README.md,CODE_OF_CONDUCT.md,CONTRIBUTING.md,.github/*.md,src/**/*.ts}\"", 43 | "cz": "cz", 44 | "semantic-release": "semantic-release" 45 | }, 46 | "devDependencies": { 47 | "@ryansonshine/commitizen": "^4.2.8", 48 | "@ryansonshine/cz-conventional-changelog": "^3.3.4", 49 | "@semantic-release/changelog": "^6.0.1", 50 | "@semantic-release/commit-analyzer": "^9.0.2", 51 | "@semantic-release/github": "^8.0.5", 52 | "@semantic-release/npm": "^9.0.1", 53 | "@semantic-release/release-notes-generator": "^10.0.3", 54 | "@types/node": "^18.6.5", 55 | "@types/prompts": "^2.0.14", 56 | "@typescript-eslint/eslint-plugin": "^5.33.0", 57 | "@typescript-eslint/parser": "^5.33.0", 58 | "c8": "^7.12.0", 59 | "cspell": "^6.6.0", 60 | "esbuild": "^0.14.54", 61 | "eslint": "^8.21.0", 62 | "eslint-config-prettier": "^8.5.0", 63 | "eslint-import-resolver-typescript": "^3.4.0", 64 | "eslint-plugin-eslint-comments": "^3.2.0", 65 | "eslint-plugin-import": "^2.26.0", 66 | "nyc": "^15.1.0", 67 | "prettier": "^2.7.1", 68 | "prompts": "^2.4.2", 69 | "semantic-release": "^19.0.3", 70 | "slugify": "^1.6.5", 71 | "source-map-support": "^0.5.21", 72 | "typescript": "^4.7.4", 73 | "vitest": "^0.21.1" 74 | }, 75 | "overrides": { 76 | "semver-regex": "3.1.4" 77 | }, 78 | "dependencies": { 79 | "browser-or-node": "^2.0.0", 80 | "comlink": "^4.3.1", 81 | "web-worker": "^1.2.0" 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /scripts/setup.ts: -------------------------------------------------------------------------------- 1 | import path from "path"; 2 | import slugify from "slugify"; 3 | import fs from "fs/promises"; 4 | import childProcess from "child_process"; 5 | import { promisify } from "util"; 6 | import prompts from "prompts"; 7 | 8 | const exec = promisify(childProcess.exec); 9 | 10 | const rootPath = path.join(__dirname, ".."); 11 | const releaseRcPath = path.join(rootPath, ".releaserc.json"); 12 | const cspellPath = path.join(rootPath, ".cspell.json"); 13 | const packageJsonPath = path.join(rootPath, "package.json"); 14 | const contributingPath = path.join(rootPath, "CONTRIBUTING.md"); 15 | const setupPath = __filename; 16 | const testSetupPath = path.join(rootPath, "scripts/testSetup.ts"); 17 | const workflowPath = path.join( 18 | rootPath, 19 | ".github/workflows/typescript-library-starter.yml" 20 | ); 21 | const issueConfigPath = path.join( 22 | rootPath, 23 | ".github/ISSUE_TEMPLATE/config.yml" 24 | ); 25 | const codeOfConductPath = path.join(rootPath, "CODE_OF_CONDUCT.md"); 26 | 27 | interface Input { 28 | packageName: string; 29 | githubUserName: string; 30 | userMail: string; 31 | } 32 | 33 | async function main() { 34 | const initialProjectName = path.basename(rootPath); 35 | 36 | const input: Input = await prompts([ 37 | { 38 | type: "text", 39 | name: "packageName", 40 | message: "What is your project name?", 41 | initial: initialProjectName, 42 | }, 43 | { 44 | type: "text", 45 | name: "githubUserName", 46 | message: "What is your github username (package.json)?", 47 | }, 48 | { 49 | type: "text", 50 | name: "userMail", 51 | message: "What is your mail (CODE_OF_CONDUCT.md)?", 52 | }, 53 | ]); 54 | 55 | // \u0015 may be inserted by clearing the pre-filled value by doing 56 | // cmd+backspace 57 | const packageName = input.packageName?.trim().replace("\u0015", ""); 58 | const githubUserName = input.githubUserName?.trim(); 59 | const userMail = input.userMail?.trim(); 60 | 61 | if (!packageName || !githubUserName) { 62 | console.log("User input missing. Exiting"); 63 | process.exit(1); 64 | } 65 | 66 | return run({ packageName, githubUserName, userMail }); 67 | } 68 | 69 | export async function run({ 70 | packageName, 71 | githubUserName, 72 | userMail, 73 | }: { 74 | packageName: string; 75 | githubUserName: string; 76 | userMail: string; 77 | }) { 78 | await applyPackageName({ packageName, githubUserName, userMail }); 79 | 80 | await cleanup({ packageName }); 81 | 82 | await commitAll("chore: typescript-library-startup"); 83 | 84 | await removeOrigin(); 85 | 86 | console.log("Ready to go 🚀"); 87 | } 88 | 89 | async function applyPackageName({ 90 | packageName, 91 | githubUserName, 92 | userMail, 93 | }: { 94 | packageName: string; 95 | githubUserName: string; 96 | userMail: string; 97 | }) { 98 | const packageSlug = slugify(packageName); 99 | 100 | await logAsyncTask( 101 | "Changing GitHub workflow file", 102 | replaceInFile( 103 | workflowPath, 104 | new Map([ 105 | [/Typescript Library Starter/, packageName], 106 | [/typescript-library-starter/, packageSlug], 107 | [/\s+- name: Setup test\s+run:[\w :]+/i, ""], 108 | ]) 109 | ) 110 | ); 111 | 112 | await logAsyncTask( 113 | "Changing GitHub Discussions file", 114 | replaceInFile( 115 | issueConfigPath, 116 | new Map([ 117 | [ 118 | "gjuchault/typescript-library-starter", 119 | `${githubUserName}/${packageName}`, 120 | ], 121 | ]) 122 | ) 123 | ); 124 | 125 | await logAsyncTask( 126 | "Changing CONTRIBUTING.md file", 127 | replaceInFile( 128 | contributingPath, 129 | new Map([ 130 | [ 131 | /gjuchault\/typescript-library-starter/g, 132 | `${githubUserName}/${packageName}`, 133 | ], 134 | ]) 135 | ) 136 | ); 137 | 138 | await logAsyncTask( 139 | "Renaming GitHub workflow file", 140 | fs.rename( 141 | workflowPath, 142 | path.join(rootPath, `.github/workflows/${packageName}.yml`) 143 | ) 144 | ); 145 | 146 | await logAsyncTask( 147 | "Editing .releaserc.json", 148 | replaceInFile( 149 | releaseRcPath, 150 | new Map([ 151 | [ 152 | "gjuchault/typescript-library-starter", 153 | `${githubUserName}/${packageName}`, 154 | ], 155 | ]) 156 | ) 157 | ); 158 | 159 | await logAsyncTask( 160 | "Editing CODE_OF_CONDUCT.md", 161 | replaceInFile( 162 | codeOfConductPath, 163 | new Map([["gabriel.juchault@gmail.com", userMail]]) 164 | ) 165 | ); 166 | 167 | await logAsyncTask( 168 | "Editing package.json", 169 | 170 | replaceInFile( 171 | packageJsonPath, 172 | new Map([ 173 | ["@gjuchault/typescript-library-starter", packageName], 174 | [/[^\n]+"description[^\n]+\n/, ""], 175 | [/[^\n]+"keywords[^\]]+\],\n/, ""], 176 | [/[^\n]+"homepage[^\n]+\n/, ""], 177 | [/[^\n]+"bugs[^\n]+\n/, ""], 178 | [/[^\n]+"author[^\n]+\n/, ""], 179 | [/[^\n]+"repository[^\n]+\n/, ""], 180 | [/[^\n]+"setup[^\n]+\n/, ""], 181 | ]) 182 | ) 183 | ); 184 | } 185 | 186 | async function cleanup({ packageName }: { packageName: string }) { 187 | await logAsyncTask( 188 | "Removing dependencies", 189 | exec("npm uninstall slugify prompts") 190 | ); 191 | 192 | await logAsyncTask( 193 | "Cleaning cspell", 194 | replaceInFile(cspellPath, new Map([["gjuchault", packageName]])) 195 | ); 196 | 197 | await logAsyncTask("Removing setup.ts script", fs.rm(setupPath)); 198 | await logAsyncTask("Removing testSetup.ts script", fs.rm(testSetupPath)); 199 | } 200 | 201 | async function replaceInFile( 202 | filePath: string, 203 | replacers: Map 204 | ) { 205 | const fileContent = await fs.readFile(filePath, "utf8"); 206 | 207 | let replacedContent = fileContent; 208 | for (const [searchFor, replaceBy] of replacers) { 209 | replacedContent = replacedContent.replace(searchFor, replaceBy); 210 | } 211 | 212 | await fs.writeFile(filePath, replacedContent); 213 | } 214 | 215 | async function commitAll(message: string) { 216 | await exec("git add ."); 217 | await logAsyncTask( 218 | `Committing changes: ${message}`, 219 | exec(`git commit -m "${message}"`) 220 | ); 221 | } 222 | 223 | async function removeOrigin() { 224 | const { stdout: origin } = await exec(`git remote get-url origin`); 225 | if (origin.includes("gjuchault/typescript-library-starter")) { 226 | await logAsyncTask(`Removing git origin`, exec(`git remote rm origin`)); 227 | } 228 | } 229 | 230 | async function logAsyncTask( 231 | message: string, 232 | promise: Promise 233 | ) { 234 | process.stdout.write(message); 235 | 236 | const output = await promise; 237 | 238 | console.log(" ✅"); 239 | 240 | return output; 241 | } 242 | 243 | if (require.main === module) { 244 | main(); 245 | } 246 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | // import * as Comlink from "https://unpkg.com/comlink/dist/esm/comlink.mjs"; 2 | 3 | import { createBergamotWorker, ModelRegistry } from "./index"; 4 | 5 | const statusEl: HTMLElement = document.querySelector("#status")!; 6 | const displayStatus = (status: string) => (statusEl.innerText = status); 7 | 8 | const langFromEl: HTMLSelectElement = document.querySelector("#lang-from")!; 9 | const langToEl: HTMLSelectElement = document.querySelector("#lang-to")!; 10 | 11 | const inputEl: HTMLInputElement = document.querySelector("#input")!; 12 | const outputEl: HTMLInputElement = document.querySelector("#output")!; 13 | const swapButtonEl: HTMLButtonElement = document.querySelector(".swap")!; 14 | 15 | function _prepareTranslateOptions(paragraphs: string[]) { 16 | // Each option object can be different for each entry. But to keep the test page simple, 17 | // we just keep all the options same (specifically avoiding parsing the input to determine 18 | // html/non-html text) 19 | return new Array(paragraphs.length).fill({ 20 | isQualityScores: true, 21 | isHtml: true, 22 | }); 23 | } 24 | 25 | function textToHTML(text: string): string { 26 | const div = document.createElement("div"); 27 | div.appendChild(document.createTextNode(text)); 28 | return div.innerHTML; 29 | } 30 | 31 | async function main() { 32 | const comlinkWorker = createBergamotWorker("../../build/bundled/worker.js"); 33 | 34 | await comlinkWorker.importBergamotWorker( 35 | "../../../artifacts/bergamot-translator-worker.js", 36 | "../../../artifacts/bergamot-translator-worker.wasm" 37 | ); 38 | 39 | const MODEL_REGISTRY = "../../example/src/models/registry.json"; 40 | const response = await fetch(MODEL_REGISTRY); 41 | const modelRegistry: ModelRegistry = await response.json(); 42 | // Model Registry only has names, not paths. So we need to add the path to each entry. 43 | for (const [name, model] of Object.entries(modelRegistry)) { 44 | for (const file of Object.values(model)) { 45 | file.name = `../../example/src/models/${name}/${file.name}`; 46 | } 47 | } 48 | 49 | // await comlinkWorker.loadModel("en", "bg", modelRegistry); 50 | // await comlinkWorker.translate( 51 | // "en", 52 | // "bg", 53 | // ["my test sentence"], 54 | // [ 55 | // { 56 | // isQualityScores: true, 57 | // isHtml: false, 58 | // }, 59 | // ] 60 | // ); 61 | 62 | const translateCall = async () => { 63 | const text = inputEl.value; 64 | if (!text.trim().length) return; 65 | 66 | const paragraphs = text.split(/\n+/).map(textToHTML); // escape HTML 67 | const translateOptions = _prepareTranslateOptions(paragraphs); 68 | const lngFrom = langFromEl.value; 69 | const lngTo = langToEl.value; 70 | 71 | const results: any[] = await comlinkWorker.translate( 72 | lngFrom, 73 | lngTo, 74 | paragraphs, 75 | translateOptions 76 | ); 77 | outputEl.innerHTML = ""; // Clear output of previous translation 78 | 79 | // Add each translation in its own div to have a known root in which the 80 | // sentence ids are unique. Used for highlighting sentences. 81 | for (const translatedHTML of results) { 82 | const translation = document.createElement("div"); 83 | translation.classList.add("translation"); 84 | translation.innerHTML = translatedHTML; 85 | addQualityClasses(translation); 86 | outputEl.appendChild(translation); 87 | } 88 | }; 89 | 90 | const addQualityClasses = (root: HTMLElement) => { 91 | // You can do this wit CSS variables, calc() and min/max, but JS is just easier 92 | 93 | root.querySelectorAll("[x-bergamot-sentence-score]").forEach((el) => { 94 | // The threshold is ln(0.5) (https://github.com/browsermt/bergamot-translator/pull/370#issuecomment-1058123399) 95 | const score = el.getAttribute("x-bergamot-sentence-score") ?? ""; 96 | el.classList.toggle("bad", parseFloat(score) < -0.6931); 97 | }); 98 | 99 | root.querySelectorAll("[x-bergamot-word-score]").forEach((el) => { 100 | // The threshold is ln(0.5) (https://github.com/browsermt/bergamot-translator/pull/370#issuecomment-1058123399) 101 | const score = el.getAttribute("x-bergamot-word-score") ?? ""; 102 | el.classList.toggle("bad", parseFloat(score) < -0.6931); 103 | }); 104 | 105 | // Add tooltips to each (sub)word with sentence and word score. 106 | root 107 | .querySelectorAll("[x-bergamot-sentence-score] > [x-bergamot-word-score]") 108 | .forEach((el) => { 109 | const parent = el.parentNode as HTMLElement; 110 | const sentenceScore = parseFloat( 111 | parent.getAttribute("x-bergamot-sentence-score") ?? "" 112 | ); 113 | const wordScore = parseFloat( 114 | el.getAttribute("x-bergamot-word-score") ?? "" 115 | ); 116 | el.setAttribute( 117 | "title", 118 | `Sentence: ${sentenceScore} Word: ${wordScore}` 119 | ); 120 | }); 121 | }; 122 | 123 | const loadModel = async () => { 124 | const lngFrom = langFromEl.value; 125 | const lngTo = langToEl.value; 126 | if (lngFrom !== lngTo) { 127 | displayStatus(`Installing model...`); 128 | console.log(`Loading model '${lngFrom}${lngTo}'`); 129 | displayStatus( 130 | await comlinkWorker.loadModel(lngFrom, lngTo, modelRegistry) 131 | ); 132 | await translateCall(); 133 | } else { 134 | outputEl.innerHTML = textToHTML(inputEl.value); 135 | } 136 | }; 137 | 138 | langFromEl.addEventListener("change", loadModel); 139 | langToEl.addEventListener("change", loadModel); 140 | 141 | swapButtonEl.addEventListener("click", async () => { 142 | [langFromEl.value, langToEl.value] = [langToEl.value, langFromEl.value]; 143 | inputEl.value = outputEl.innerText; 144 | await loadModel(); 145 | }); 146 | 147 | outputEl.addEventListener("mouseover", (e) => { 148 | const target = e.target as HTMLElement; 149 | const parent = target.parentNode as HTMLElement; 150 | const root = target.closest(".translation"); 151 | const sentence = parent.hasAttribute("x-bergamot-sentence-index") 152 | ? parent.getAttribute("x-bergamot-sentence-index") 153 | : null; 154 | document 155 | .querySelectorAll("#output font[x-bergamot-sentence-index]") 156 | .forEach((el) => { 157 | el.classList.toggle( 158 | "highlight-sentence", 159 | el.getAttribute("x-bergamot-sentence-index") === sentence && 160 | el.closest(".translation") === root 161 | ); 162 | }); 163 | }); 164 | 165 | async function init() { 166 | const langs: string[] = Array.from( 167 | new Set( 168 | Object.keys(modelRegistry).reduce((acc, key) => { 169 | const middle = Math.round(key.length / 2); 170 | // @ts-expect-error 171 | return acc.concat([ 172 | key.substring(0, middle), 173 | key.substring(middle, key.length), 174 | ]); 175 | }, []) 176 | ) 177 | ); 178 | const langNames = new Intl.DisplayNames(undefined, { type: "language" }); 179 | const langName = (lang: string) => langNames.of(lang) ?? lang; 180 | 181 | // Sort languages by display name 182 | langs.sort((a, b) => langName(a).localeCompare(langName(b))); 183 | 184 | // Populate the dropdowns 185 | langs.forEach((code) => { 186 | const name = langName(code); 187 | langFromEl.innerHTML += ``; 188 | langToEl.innerHTML += ``; 189 | }); 190 | 191 | langFromEl.value = "spoken"; 192 | langToEl.value = "signed"; 193 | // // try to guess input language from user agent 194 | // let myLang = "navigator" in globalThis ? navigator.language : ""; 195 | // if (myLang) { 196 | // myLang = myLang.split("-")[0]; 197 | // if (langs.includes(myLang)) { 198 | // console.log("guessing input language is", myLang); 199 | // langFromEl.value = myLang; 200 | // } 201 | // } 202 | // 203 | // // find first output lang that *isn't* input language 204 | // langToEl.value = langs.find((code) => code !== langFromEl.value)!; 205 | 206 | // load this model 207 | await loadModel(); 208 | } 209 | 210 | inputEl.addEventListener("keyup", translateCall); 211 | 212 | return init(); 213 | } 214 | 215 | main() 216 | .then(() => { 217 | console.log("ready"); 218 | }) 219 | .catch((err) => console.error(err)); 220 | -------------------------------------------------------------------------------- /src/worker.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import { IncomingMessage } from "http"; 4 | 5 | import { isNode } from "browser-or-node"; 6 | import * as comlink from "comlink"; 7 | import { FileInfo, ModelRegistry, TranslationOptions } from "./index"; 8 | 9 | comlink.expose({ importBergamotWorker, loadModel, translate }); 10 | 11 | const timing: Record = { workerStart: Date.now() }; 12 | 13 | const FILE_INFO: FileInfo[] = [ 14 | { type: "model", alignment: 256 }, 15 | { type: "lex", alignment: 64 }, 16 | { type: "vocab", alignment: 64 }, 17 | { type: "srcvocab", alignment: 64 }, 18 | { type: "trgvocab", alignment: 64 }, 19 | { type: "qualityModel", alignment: 64 }, 20 | ]; 21 | 22 | function log(...args: any[]) { 23 | console.debug(...args); 24 | } 25 | 26 | function logTime(timingKey: string, ...args: any[]) { 27 | const time = (Date.now() - timing[timingKey]) / 1000; 28 | log(...args, `${time} secs`); 29 | } 30 | 31 | interface TranslationServiceConfig { 32 | cacheSize: number; 33 | } 34 | 35 | interface TranslationService { 36 | new (config: TranslationServiceConfig): TranslationService; 37 | 38 | translateViaPivoting: ( 39 | translationModelSrcToPivot: any, 40 | translationModelPivotToTarget: any, 41 | vectorSourceText: any, 42 | vectorResponseOptions: any 43 | ) => any; 44 | 45 | translate: ( 46 | translationModel: any, 47 | vectorSourceText: any, 48 | vectorResponseOptions: any 49 | ) => ResponseVector; 50 | } 51 | 52 | let translationService: TranslationService; 53 | 54 | let runtimeInitializedPromiseResolve: CallableFunction; 55 | const runtimeInitializedPromise = new Promise( 56 | (resolve) => (runtimeInitializedPromiseResolve = resolve) 57 | ); 58 | 59 | // bergamot-translator-worker.js expects a "Module" object to be available 60 | let workerWasmFilePath: string; 61 | 62 | (globalThis as any).Module = { 63 | preRun: [ 64 | () => { 65 | logTime("workerStart", "Time until Module.preRun"); 66 | timing.moduleLoadStart = Date.now(); 67 | }, 68 | ], 69 | 70 | locateFile: () => { 71 | return workerWasmFilePath; 72 | }, 73 | 74 | onRuntimeInitialized: async () => { 75 | logTime( 76 | "moduleLoadStart", 77 | "Wasm Runtime initialized Successfully (preRun -> onRuntimeInitialized)" 78 | ); 79 | runtimeInitializedPromiseResolve(); 80 | }, 81 | } as any; 82 | 83 | async function importBergamotWorker( 84 | jsFilePath: string, 85 | wasmFilePath: string | Buffer 86 | ) { 87 | if (typeof wasmFilePath === "string") { 88 | workerWasmFilePath = wasmFilePath; 89 | } else { 90 | (globalThis as any).Module.wasmBinary = wasmFilePath; 91 | } 92 | 93 | if (isNode) { 94 | const fs = require("fs"); 95 | const code = fs.readFileSync(jsFilePath, "utf-8"); 96 | const vm = require("vm"); 97 | vm.runInThisContext(code); 98 | } else { 99 | importScripts(jsFilePath); 100 | } 101 | await runtimeInitializedPromise; 102 | } 103 | 104 | async function loadModel( 105 | from: string, 106 | to: string, 107 | modelRegistry: ModelRegistry 108 | ) { 109 | timing.loadModelStart = Date.now(); 110 | 111 | try { 112 | await constructTranslationService(); 113 | await constructTranslationModel(from, to, modelRegistry); 114 | logTime("loadModelStart", `Model '${from}-${to}' successfully constructed`); 115 | return "Model successfully loaded"; 116 | } catch (error: any) { 117 | console.error(error); 118 | log(`Model '${from}${to}' construction failed:`, error.message); 119 | return "Model loading failed"; 120 | } 121 | } 122 | 123 | function translate( 124 | from: string, 125 | to: string, 126 | sentences: string[], 127 | options: TranslationOptions[] 128 | ) { 129 | timing.translateStart = Date.now(); 130 | 131 | const wordCount = sentences.reduce( 132 | (acc, sentence) => acc + _wordsCount(sentence), 133 | 0 134 | ); 135 | let result; 136 | try { 137 | log(`Blocks to translate: ${sentences.length}`); 138 | result = _translate(from, to, sentences, options); 139 | const secs = (Date.now() - timing.translateStart) / 1000; 140 | log( 141 | `Speed: ${Math.round( 142 | wordCount / secs 143 | )} WPS (${wordCount} words in ${secs} secs)` 144 | ); 145 | } catch (error: any) { 146 | log(`Error:`, error.message); 147 | } 148 | return result; 149 | } 150 | 151 | // All variables specific to translation service 152 | 153 | // A map of language-pair to TranslationModel object 154 | const languagePairToTranslationModels = new Map(); 155 | 156 | const PIVOT_LANGUAGE = "en"; 157 | 158 | onmessage = async function (e) { 159 | const command = e.data[0]; 160 | log(`Message '${command}' received from main script`); 161 | if (command === "translate") { 162 | const from = e.data[1]; 163 | const to = e.data[2]; 164 | const input = e.data[3]; 165 | const translateOptions = e.data[4]; 166 | const result = translate(from, to, input, translateOptions); 167 | console.warn(result); 168 | log(`'${command}' command done, Posting message back to main script`); 169 | postMessage([`${command}_reply`, result]); 170 | } 171 | }; 172 | 173 | // Instantiates the Translation Service 174 | const constructTranslationService = async () => { 175 | if (!translationService) { 176 | const config: TranslationServiceConfig = { cacheSize: 20000 }; 177 | log(`Creating Translation Service with config`, config); 178 | translationService = new (globalThis as any).Module.BlockingService(config); 179 | log(`Translation Service created successfully`); 180 | } 181 | }; 182 | 183 | // Constructs translation model(s) for the source and target language pair (using 184 | // pivoting if required). 185 | const constructTranslationModel = async ( 186 | from: string, 187 | to: string, 188 | modelRegistry: ModelRegistry 189 | ) => { 190 | // Delete all previously constructed translation models and clear the map 191 | languagePairToTranslationModels.forEach((value, key) => { 192 | log(`Destructing model '${key}'`); 193 | value.delete(); 194 | }); 195 | languagePairToTranslationModels.clear(); 196 | 197 | if (_isPivotingRequired(from, to)) { 198 | // Pivoting requires 2 translation models 199 | const languagePairSrcToPivot = _getLanguagePair(from, PIVOT_LANGUAGE); 200 | const languagePairPivotToTarget = _getLanguagePair(PIVOT_LANGUAGE, to); 201 | await Promise.all([ 202 | _constructTranslationModelHelper(languagePairSrcToPivot, modelRegistry), 203 | _constructTranslationModelHelper( 204 | languagePairPivotToTarget, 205 | modelRegistry 206 | ), 207 | ]); 208 | } else { 209 | // Non-pivoting case requires only 1 translation model 210 | await _constructTranslationModelHelper( 211 | _getLanguagePair(from, to), 212 | modelRegistry 213 | ); 214 | } 215 | }; 216 | 217 | // Translates text from source language to target language (via pivoting if necessary). 218 | const _translate = ( 219 | from: string, 220 | to: string, 221 | input: string[], 222 | translateOptions: TranslationOptions[] 223 | ) => { 224 | let vectorResponseOptions, vectorSourceText, vectorResponse; 225 | try { 226 | // Prepare the arguments (vectorResponseOptions and vectorSourceText (vector)) of Translation API and call it. 227 | // Result is a vector where each of its item corresponds to one item of vectorSourceText in the same order. 228 | vectorResponseOptions = _prepareResponseOptions(translateOptions); 229 | vectorSourceText = _prepareSourceText(input); 230 | 231 | if (_isPivotingRequired(from, to)) { 232 | // Translate via pivoting 233 | const translationModelSrcToPivot = _getLoadedTranslationModel( 234 | from, 235 | PIVOT_LANGUAGE 236 | ); 237 | const translationModelPivotToTarget = _getLoadedTranslationModel( 238 | PIVOT_LANGUAGE, 239 | to 240 | ); 241 | vectorResponse = translationService.translateViaPivoting( 242 | translationModelSrcToPivot, 243 | translationModelPivotToTarget, 244 | vectorSourceText, 245 | vectorResponseOptions 246 | ); 247 | } else { 248 | // Translate without pivoting 249 | const translationModel = _getLoadedTranslationModel(from, to); 250 | vectorResponse = translationService.translate( 251 | translationModel, 252 | vectorSourceText, 253 | vectorResponseOptions 254 | ); 255 | } 256 | 257 | // Parse all relevant information from vectorResponse 258 | const listTranslatedText = _parseTranslatedText(vectorResponse); 259 | const listSourceText = _parseSourceText(vectorResponse); 260 | const listTranslatedTextSentences = 261 | _parseTranslatedTextSentences(vectorResponse); 262 | const listSourceTextSentences = _parseSourceTextSentences(vectorResponse); 263 | 264 | log(`Source text: ${listSourceText}`); 265 | log(`Translated text: ${listTranslatedText}`); 266 | log(`Translated sentences: ${JSON.stringify(listTranslatedTextSentences)}`); 267 | log(`Source sentences: ${JSON.stringify(listSourceTextSentences)}`); 268 | 269 | return listTranslatedText; 270 | } finally { 271 | // Necessary clean up 272 | if (vectorSourceText != null) vectorSourceText.delete(); 273 | if (vectorResponseOptions != null) vectorResponseOptions.delete(); 274 | if (vectorResponse != null) vectorResponse.delete(); 275 | } 276 | }; 277 | 278 | const _downloadAsArrayBufferNode = async ( 279 | url: string 280 | ): Promise => { 281 | const protocol = url.split("://")[0]; 282 | const https = require(protocol); 283 | return new Promise((resolve, reject) => { 284 | const req = https.get(url, (res: IncomingMessage) => { 285 | if (res.statusCode !== 200) { 286 | reject(new Error(`Status code ${res.statusCode}`)); 287 | return; 288 | } 289 | const chunks: Buffer[] = []; 290 | res.on("error", (error: Error) => { 291 | console.error("Error in fetching", error); 292 | reject(error); 293 | }); 294 | res.on("data", (chunk) => { 295 | if (res.statusCode !== 200) { 296 | reject("data: Status code is not 200"); 297 | } 298 | chunks.push(chunk); 299 | }); 300 | res.on("end", async () => { 301 | if (res.statusCode !== 200) { 302 | reject("end: Status code is not 200"); 303 | } 304 | const { Blob } = require("buffer"); 305 | const data = new Blob(chunks); 306 | try { 307 | const buffer = await data.arrayBuffer(); 308 | resolve(buffer); 309 | } catch (error) { 310 | reject(error); 311 | } 312 | }); 313 | }); 314 | 315 | req.on("error", function (e: any) { 316 | // For some reason, firebase storage returns ECONNRESET while returning the right data 317 | if (e.code !== "ECONNRESET") { 318 | reject(e); 319 | } 320 | }); 321 | req.on("timeout", function (e: any) { 322 | console.error(`timeout: problem with request: ${e.message}`); 323 | reject(e); 324 | }); 325 | req.on("uncaughtException", function (e: any) { 326 | console.error(`uncaughtException: problem with request: ${e.message}`); 327 | reject(e); 328 | }); 329 | }); 330 | }; 331 | 332 | // Downloads file from a url and returns the array buffer 333 | const _downloadAsArrayBuffer = async (url: string): Promise => { 334 | if (isNode) { 335 | return _downloadAsArrayBufferNode(url); 336 | } 337 | const response = await fetch(url); 338 | if (!response.ok) { 339 | throw Error( 340 | `Downloading ${url} failed: HTTP ${response.status} - ${response.statusText}` 341 | ); 342 | } 343 | return response.arrayBuffer(); 344 | }; 345 | 346 | // Constructs and initializes the AlignedMemory from the array buffer and alignment size 347 | const _prepareAlignedMemoryFromBuffer = async ( 348 | buffer: ArrayBuffer, 349 | alignmentSize: number 350 | ) => { 351 | const byteArray = new Int8Array(buffer); 352 | const alignedMemory = new (globalThis as any).Module.AlignedMemory( 353 | byteArray.byteLength, 354 | alignmentSize 355 | ); 356 | const alignedByteArrayView = alignedMemory.getByteArrayView(); 357 | alignedByteArrayView.set(byteArray); 358 | return alignedMemory; 359 | }; 360 | 361 | async function prepareAlignedMemory( 362 | file: FileInfo, 363 | languagePair: string, 364 | modelRegistry: ModelRegistry 365 | ) { 366 | const fileName = modelRegistry[languagePair][file.type]!.name; 367 | const buffer = await _downloadAsArrayBuffer(fileName); 368 | const alignedMemory = await _prepareAlignedMemoryFromBuffer( 369 | buffer, 370 | file.alignment 371 | ); 372 | log( 373 | `${ 374 | file.type 375 | } aligned memory prepared. Size: ${alignedMemory.size()} bytes, alignment: ${ 376 | file.alignment 377 | }` 378 | ); 379 | return alignedMemory; 380 | } 381 | 382 | const _constructTranslationModelHelper = async ( 383 | languagePair: string, 384 | modelRegistry: ModelRegistry 385 | ) => { 386 | log(`Constructing translation model ${languagePair}`); 387 | 388 | /*Set the Model Configuration as YAML formatted string. 389 | For available configuration options, please check: https://marian-nmt.github.io/docs/cmd/marian-decoder/ 390 | Vocab files are re-used in both translation directions. 391 | DO NOT CHANGE THE SPACES BETWEEN EACH ENTRY OF CONFIG 392 | */ 393 | // Constraints: 394 | // max-length-factor * max-length-break < mini-batch-words 395 | const modelConfig = `beam-size: 12 396 | normalize: 1.0 397 | word-penalty: 0 398 | max-length-break: 512 399 | mini-batch-words: 8192 400 | workspace: 512 401 | max-length-factor: 12 402 | skip-cost: false 403 | cpu-threads: 0 404 | quiet: true 405 | quiet-translation: true 406 | gemm-precision: int8shiftAlphaAll 407 | alignment: soft 408 | `; 409 | 410 | const alignedMemories = Object.fromEntries(await Promise.all( 411 | FILE_INFO.filter((file) => file.type in modelRegistry[languagePair]).map( 412 | async (file) => [file.type, await prepareAlignedMemory(file, languagePair, modelRegistry)] 413 | ) 414 | )); 415 | 416 | const alignedVocabMemoryList = new ( 417 | globalThis as any 418 | ).Module.AlignedMemoryList(); 419 | 420 | if (alignedMemories.vocab) { 421 | alignedVocabMemoryList.push_back(alignedMemories.vocab); 422 | } else { 423 | if (alignedMemories.srcvocab) { 424 | alignedVocabMemoryList.push_back(alignedMemories.srcvocab); 425 | } 426 | if (alignedMemories.trgvocab) { 427 | alignedVocabMemoryList.push_back(alignedMemories.trgvocab); 428 | } 429 | } 430 | let vocabMemSize = 0; 431 | for (let i = 0; i < alignedVocabMemoryList.size(); i++) { 432 | vocabMemSize += alignedVocabMemoryList.get(i).size(); 433 | } 434 | 435 | log(`Translation Model config: ${modelConfig}`); 436 | log( 437 | `Aligned memory sizes: Model:${alignedMemories.model.size()} Shortlist:${alignedMemories.lex.size()} Vocab:${vocabMemSize}` 438 | ); 439 | let translationModel; 440 | if (alignedMemories.qualityModel) { 441 | log(`QE:${alignedMemories[3].size()}`); 442 | } 443 | translationModel = new (globalThis as any).Module.TranslationModel( 444 | modelConfig, 445 | alignedMemories.model, 446 | alignedMemories.lex, 447 | alignedVocabMemoryList, 448 | alignedMemories.qualityModel || null, 449 | ); 450 | 451 | languagePairToTranslationModels.set(languagePair, translationModel); 452 | }; 453 | 454 | const _isPivotingRequired = (from: string, to: string) => { 455 | return false; 456 | // return from !== PIVOT_LANGUAGE && to !== PIVOT_LANGUAGE; 457 | }; 458 | 459 | const _getLanguagePair = (srcLang: string, tgtLang: string) => { 460 | return `${srcLang}${tgtLang}`; 461 | }; 462 | 463 | const _getLoadedTranslationModel = (srcLang: string, tgtLang: string) => { 464 | const languagePair = _getLanguagePair(srcLang, tgtLang); 465 | if (!languagePairToTranslationModels.has(languagePair)) { 466 | throw Error(`Translation model '${languagePair}' not loaded`); 467 | } 468 | return languagePairToTranslationModels.get(languagePair); 469 | }; 470 | 471 | const _parseTranslatedText = (vectorResponse: ResponseVector) => { 472 | const result = []; 473 | for (let i = 0; i < vectorResponse.size(); i++) { 474 | const response = vectorResponse.get(i); 475 | result.push(response.getTranslatedText()); 476 | } 477 | return result; 478 | }; 479 | 480 | const _parseTranslatedTextSentences = (vectorResponse: ResponseVector) => { 481 | const result = []; 482 | for (let i = 0; i < vectorResponse.size(); i++) { 483 | const response = vectorResponse.get(i); 484 | result.push(_getTranslatedSentences(response)); 485 | } 486 | return result; 487 | }; 488 | 489 | const _parseSourceText = (vectorResponse: ResponseVector) => { 490 | const result = []; 491 | for (let i = 0; i < vectorResponse.size(); i++) { 492 | const response = vectorResponse.get(i); 493 | result.push(response.getOriginalText()); 494 | } 495 | return result; 496 | }; 497 | 498 | const _parseSourceTextSentences = (vectorResponse: ResponseVector) => { 499 | const result = []; 500 | for (let i = 0; i < vectorResponse.size(); i++) { 501 | const response = vectorResponse.get(i); 502 | result.push(_getSourceSentences(response)); 503 | } 504 | return result; 505 | }; 506 | 507 | const _prepareResponseOptions = (translateOptions: TranslationOptions[]) => { 508 | const vectorResponseOptions = new ( 509 | globalThis as any 510 | ).Module.VectorResponseOptions(); 511 | translateOptions.forEach((translateOption) => { 512 | vectorResponseOptions.push_back({ 513 | qualityScores: translateOption.isQualityScores, 514 | alignment: true, 515 | html: translateOption.isHtml, 516 | }); 517 | }); 518 | if (vectorResponseOptions.size() == 0) { 519 | vectorResponseOptions.delete(); 520 | throw Error(`No Translation Options provided`); 521 | } 522 | return vectorResponseOptions; 523 | }; 524 | 525 | const _prepareSourceText = (input: string[]) => { 526 | const vectorSourceText = new (globalThis as any).Module.VectorString(); 527 | input.forEach((paragraph) => { 528 | // prevent empty paragraph - it breaks the translation 529 | if (paragraph.trim() === "") { 530 | return; 531 | } 532 | vectorSourceText.push_back(paragraph.trim()); 533 | }); 534 | if (vectorSourceText.size() == 0) { 535 | vectorSourceText.delete(); 536 | throw Error(`No text provided to translate`); 537 | } 538 | return vectorSourceText; 539 | }; 540 | 541 | interface Response { 542 | getTranslatedText(): string; 543 | 544 | getTranslatedSentence(index: number): { begin: number; end: number }; 545 | 546 | getSourceSentence(index: number): { begin: number; end: number }; 547 | 548 | size(): number; 549 | 550 | getOriginalText(): string; 551 | } 552 | 553 | interface ResponseVector { 554 | size(): number; 555 | 556 | get(index: number): Response; 557 | } 558 | 559 | const _getTranslatedSentences = (response: Response) => { 560 | const sentences = []; 561 | const text = response.getTranslatedText(); 562 | for ( 563 | let sentenceIndex = 0; 564 | sentenceIndex < response.size(); 565 | sentenceIndex++ 566 | ) { 567 | const utf8SentenceByteRange = response.getTranslatedSentence(sentenceIndex); 568 | sentences.push(_getSubString(text, utf8SentenceByteRange)); 569 | } 570 | return sentences; 571 | }; 572 | 573 | const _getSourceSentences = (response: Response) => { 574 | const sentences = []; 575 | const text = response.getOriginalText(); 576 | for ( 577 | let sentenceIndex = 0; 578 | sentenceIndex < response.size(); 579 | sentenceIndex++ 580 | ) { 581 | const utf8SentenceByteRange = response.getSourceSentence(sentenceIndex); 582 | sentences.push(_getSubString(text, utf8SentenceByteRange)); 583 | } 584 | return sentences; 585 | }; 586 | 587 | /* 588 | * Returns a substring of text (a string). The substring is represented by 589 | * byteRange (begin and end indices) within the utf-8 encoded version of the text. 590 | */ 591 | const _getSubString = ( 592 | text: string, 593 | utf8ByteRange: { begin: number; end: number } 594 | ) => { 595 | const encoder = new TextEncoder(); // string to utf-8 converter 596 | const decoder = new TextDecoder(); // utf-8 to string converter 597 | 598 | const textUtf8ByteView = encoder.encode(text); 599 | const substringUtf8ByteView = textUtf8ByteView.subarray( 600 | utf8ByteRange.begin, 601 | utf8ByteRange.end 602 | ); 603 | return decoder.decode(substringUtf8ByteView); 604 | }; 605 | 606 | function _wordsCount(sentence: string) { 607 | return sentence 608 | .trim() 609 | .split(" ") 610 | .filter((word) => word.trim() !== "").length; 611 | } 612 | -------------------------------------------------------------------------------- /artifacts/bergamot-translator-worker.js: -------------------------------------------------------------------------------- 1 | var BERGAMOT_VERSION_FULL = 'v0.4.5+7f79128'; 2 | null; 3 | 4 | var Module = typeof Module != 'undefined' ? Module : {}; 5 | 6 | var moduleOverrides = Object.assign({}, Module); 7 | 8 | var arguments_ = []; 9 | 10 | var thisProgram = './this.program'; 11 | 12 | var quit_ = (status, toThrow) => { 13 | throw toThrow; 14 | }; 15 | 16 | var ENVIRONMENT_IS_WEB = typeof window == 'object'; 17 | 18 | var ENVIRONMENT_IS_WORKER = typeof importScripts == 'function'; 19 | 20 | var ENVIRONMENT_IS_NODE = 21 | typeof process == 'object' && typeof process.versions == 'object' && typeof process.versions.node == 'string'; 22 | 23 | var scriptDirectory = ''; 24 | 25 | function locateFile(path) { 26 | if (Module['locateFile']) { 27 | return Module['locateFile'](path, scriptDirectory); 28 | } 29 | return scriptDirectory + path; 30 | } 31 | 32 | var read_, readAsync, readBinary, setWindowTitle; 33 | 34 | if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { 35 | if (ENVIRONMENT_IS_WORKER) { 36 | scriptDirectory = self.location.href; 37 | } else if (typeof document != 'undefined' && document.currentScript) { 38 | scriptDirectory = document.currentScript.src; 39 | } 40 | if (scriptDirectory.indexOf('blob:') !== 0) { 41 | scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, '').lastIndexOf('/') + 1); 42 | } else { 43 | scriptDirectory = ''; 44 | } 45 | { 46 | read_ = url => { 47 | var xhr = new XMLHttpRequest(); 48 | xhr.open('GET', url, false); 49 | xhr.send(null); 50 | return xhr.responseText; 51 | }; 52 | if (ENVIRONMENT_IS_WORKER) { 53 | readBinary = url => { 54 | var xhr = new XMLHttpRequest(); 55 | xhr.open('GET', url, false); 56 | xhr.responseType = 'arraybuffer'; 57 | xhr.send(null); 58 | return new Uint8Array(xhr.response); 59 | }; 60 | } 61 | readAsync = (url, onload, onerror) => { 62 | var xhr = new XMLHttpRequest(); 63 | xhr.open('GET', url, true); 64 | xhr.responseType = 'arraybuffer'; 65 | xhr.onload = () => { 66 | if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { 67 | onload(xhr.response); 68 | return; 69 | } 70 | onerror(); 71 | }; 72 | xhr.onerror = onerror; 73 | xhr.send(null); 74 | }; 75 | } 76 | setWindowTitle = title => (document.title = title); 77 | } else { 78 | } 79 | 80 | var out = Module['print'] || console.log.bind(console); 81 | 82 | var err = Module['printErr'] || console.warn.bind(console); 83 | 84 | Object.assign(Module, moduleOverrides); 85 | 86 | moduleOverrides = null; 87 | 88 | if (Module['arguments']) arguments_ = Module['arguments']; 89 | 90 | if (Module['thisProgram']) thisProgram = Module['thisProgram']; 91 | 92 | if (Module['quit']) quit_ = Module['quit']; 93 | 94 | var tempRet0 = 0; 95 | 96 | var setTempRet0 = value => { 97 | tempRet0 = value; 98 | }; 99 | 100 | var wasmBinary; 101 | 102 | if (Module['wasmBinary']) wasmBinary = Module['wasmBinary']; 103 | 104 | var noExitRuntime = Module['noExitRuntime'] || true; 105 | 106 | if (typeof WebAssembly != 'object') { 107 | abort('no native wasm support detected'); 108 | } 109 | 110 | var wasmMemory; 111 | 112 | var ABORT = false; 113 | 114 | var EXITSTATUS; 115 | 116 | function assert(condition, text) { 117 | if (!condition) { 118 | abort(text); 119 | } 120 | } 121 | 122 | var UTF8Decoder = typeof TextDecoder != 'undefined' ? new TextDecoder('utf8') : undefined; 123 | 124 | function UTF8ArrayToString(heapOrArray, idx, maxBytesToRead) { 125 | var endIdx = idx + maxBytesToRead; 126 | var endPtr = idx; 127 | while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr; 128 | if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) { 129 | return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr)); 130 | } else { 131 | var str = ''; 132 | while (idx < endPtr) { 133 | var u0 = heapOrArray[idx++]; 134 | if (!(u0 & 128)) { 135 | str += String.fromCharCode(u0); 136 | continue; 137 | } 138 | var u1 = heapOrArray[idx++] & 63; 139 | if ((u0 & 224) == 192) { 140 | str += String.fromCharCode(((u0 & 31) << 6) | u1); 141 | continue; 142 | } 143 | var u2 = heapOrArray[idx++] & 63; 144 | if ((u0 & 240) == 224) { 145 | u0 = ((u0 & 15) << 12) | (u1 << 6) | u2; 146 | } else { 147 | u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63); 148 | } 149 | if (u0 < 65536) { 150 | str += String.fromCharCode(u0); 151 | } else { 152 | var ch = u0 - 65536; 153 | str += String.fromCharCode(55296 | (ch >> 10), 56320 | (ch & 1023)); 154 | } 155 | } 156 | } 157 | return str; 158 | } 159 | 160 | function UTF8ToString(ptr, maxBytesToRead) { 161 | return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : ''; 162 | } 163 | 164 | function stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) { 165 | if (!(maxBytesToWrite > 0)) return 0; 166 | var startIdx = outIdx; 167 | var endIdx = outIdx + maxBytesToWrite - 1; 168 | for (var i = 0; i < str.length; ++i) { 169 | var u = str.charCodeAt(i); 170 | if (u >= 55296 && u <= 57343) { 171 | var u1 = str.charCodeAt(++i); 172 | u = (65536 + ((u & 1023) << 10)) | (u1 & 1023); 173 | } 174 | if (u <= 127) { 175 | if (outIdx >= endIdx) break; 176 | heap[outIdx++] = u; 177 | } else if (u <= 2047) { 178 | if (outIdx + 1 >= endIdx) break; 179 | heap[outIdx++] = 192 | (u >> 6); 180 | heap[outIdx++] = 128 | (u & 63); 181 | } else if (u <= 65535) { 182 | if (outIdx + 2 >= endIdx) break; 183 | heap[outIdx++] = 224 | (u >> 12); 184 | heap[outIdx++] = 128 | ((u >> 6) & 63); 185 | heap[outIdx++] = 128 | (u & 63); 186 | } else { 187 | if (outIdx + 3 >= endIdx) break; 188 | heap[outIdx++] = 240 | (u >> 18); 189 | heap[outIdx++] = 128 | ((u >> 12) & 63); 190 | heap[outIdx++] = 128 | ((u >> 6) & 63); 191 | heap[outIdx++] = 128 | (u & 63); 192 | } 193 | } 194 | heap[outIdx] = 0; 195 | return outIdx - startIdx; 196 | } 197 | 198 | function stringToUTF8(str, outPtr, maxBytesToWrite) { 199 | return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite); 200 | } 201 | 202 | function lengthBytesUTF8(str) { 203 | var len = 0; 204 | for (var i = 0; i < str.length; ++i) { 205 | var u = str.charCodeAt(i); 206 | if (u >= 55296 && u <= 57343) u = (65536 + ((u & 1023) << 10)) | (str.charCodeAt(++i) & 1023); 207 | if (u <= 127) ++len; 208 | else if (u <= 2047) len += 2; 209 | else if (u <= 65535) len += 3; 210 | else len += 4; 211 | } 212 | return len; 213 | } 214 | 215 | var UTF16Decoder = typeof TextDecoder != 'undefined' ? new TextDecoder('utf-16le') : undefined; 216 | 217 | function UTF16ToString(ptr, maxBytesToRead) { 218 | var endPtr = ptr; 219 | var idx = endPtr >> 1; 220 | var maxIdx = idx + maxBytesToRead / 2; 221 | while (!(idx >= maxIdx) && HEAPU16[idx]) ++idx; 222 | endPtr = idx << 1; 223 | if (endPtr - ptr > 32 && UTF16Decoder) { 224 | return UTF16Decoder.decode(HEAPU8.subarray(ptr, endPtr)); 225 | } else { 226 | var str = ''; 227 | for (var i = 0; !(i >= maxBytesToRead / 2); ++i) { 228 | var codeUnit = HEAP16[(ptr + i * 2) >> 1]; 229 | if (codeUnit == 0) break; 230 | str += String.fromCharCode(codeUnit); 231 | } 232 | return str; 233 | } 234 | } 235 | 236 | function stringToUTF16(str, outPtr, maxBytesToWrite) { 237 | if (maxBytesToWrite === undefined) { 238 | maxBytesToWrite = 2147483647; 239 | } 240 | if (maxBytesToWrite < 2) return 0; 241 | maxBytesToWrite -= 2; 242 | var startPtr = outPtr; 243 | var numCharsToWrite = maxBytesToWrite < str.length * 2 ? maxBytesToWrite / 2 : str.length; 244 | for (var i = 0; i < numCharsToWrite; ++i) { 245 | var codeUnit = str.charCodeAt(i); 246 | HEAP16[outPtr >> 1] = codeUnit; 247 | outPtr += 2; 248 | } 249 | HEAP16[outPtr >> 1] = 0; 250 | return outPtr - startPtr; 251 | } 252 | 253 | function lengthBytesUTF16(str) { 254 | return str.length * 2; 255 | } 256 | 257 | function UTF32ToString(ptr, maxBytesToRead) { 258 | var i = 0; 259 | var str = ''; 260 | while (!(i >= maxBytesToRead / 4)) { 261 | var utf32 = HEAP32[(ptr + i * 4) >> 2]; 262 | if (utf32 == 0) break; 263 | ++i; 264 | if (utf32 >= 65536) { 265 | var ch = utf32 - 65536; 266 | str += String.fromCharCode(55296 | (ch >> 10), 56320 | (ch & 1023)); 267 | } else { 268 | str += String.fromCharCode(utf32); 269 | } 270 | } 271 | return str; 272 | } 273 | 274 | function stringToUTF32(str, outPtr, maxBytesToWrite) { 275 | if (maxBytesToWrite === undefined) { 276 | maxBytesToWrite = 2147483647; 277 | } 278 | if (maxBytesToWrite < 4) return 0; 279 | var startPtr = outPtr; 280 | var endPtr = startPtr + maxBytesToWrite - 4; 281 | for (var i = 0; i < str.length; ++i) { 282 | var codeUnit = str.charCodeAt(i); 283 | if (codeUnit >= 55296 && codeUnit <= 57343) { 284 | var trailSurrogate = str.charCodeAt(++i); 285 | codeUnit = (65536 + ((codeUnit & 1023) << 10)) | (trailSurrogate & 1023); 286 | } 287 | HEAP32[outPtr >> 2] = codeUnit; 288 | outPtr += 4; 289 | if (outPtr + 4 > endPtr) break; 290 | } 291 | HEAP32[outPtr >> 2] = 0; 292 | return outPtr - startPtr; 293 | } 294 | 295 | function lengthBytesUTF32(str) { 296 | var len = 0; 297 | for (var i = 0; i < str.length; ++i) { 298 | var codeUnit = str.charCodeAt(i); 299 | if (codeUnit >= 55296 && codeUnit <= 57343) ++i; 300 | len += 4; 301 | } 302 | return len; 303 | } 304 | 305 | function allocateUTF8(str) { 306 | var size = lengthBytesUTF8(str) + 1; 307 | var ret = _malloc(size); 308 | if (ret) stringToUTF8Array(str, HEAP8, ret, size); 309 | return ret; 310 | } 311 | 312 | function writeArrayToMemory(array, buffer) { 313 | HEAP8.set(array, buffer); 314 | } 315 | 316 | function writeAsciiToMemory(str, buffer, dontAddNull) { 317 | for (var i = 0; i < str.length; ++i) { 318 | HEAP8[buffer++ >> 0] = str.charCodeAt(i); 319 | } 320 | if (!dontAddNull) HEAP8[buffer >> 0] = 0; 321 | } 322 | 323 | var buffer, HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64; 324 | 325 | function updateGlobalBufferAndViews(buf) { 326 | buffer = buf; 327 | Module['HEAP8'] = HEAP8 = new Int8Array(buf); 328 | Module['HEAP16'] = HEAP16 = new Int16Array(buf); 329 | Module['HEAP32'] = HEAP32 = new Int32Array(buf); 330 | Module['HEAPU8'] = HEAPU8 = new Uint8Array(buf); 331 | Module['HEAPU16'] = HEAPU16 = new Uint16Array(buf); 332 | Module['HEAPU32'] = HEAPU32 = new Uint32Array(buf); 333 | Module['HEAPF32'] = HEAPF32 = new Float32Array(buf); 334 | Module['HEAPF64'] = HEAPF64 = new Float64Array(buf); 335 | } 336 | 337 | var INITIAL_MEMORY = Module['INITIAL_MEMORY'] || 16777216; 338 | 339 | if (Module['wasmMemory']) { 340 | wasmMemory = Module['wasmMemory']; 341 | } else { 342 | wasmMemory = new WebAssembly.Memory({ 343 | initial: INITIAL_MEMORY / 65536, 344 | maximum: 2147483648 / 65536, 345 | }); 346 | } 347 | 348 | if (wasmMemory) { 349 | buffer = wasmMemory.buffer; 350 | } 351 | 352 | INITIAL_MEMORY = buffer.byteLength; 353 | 354 | updateGlobalBufferAndViews(buffer); 355 | 356 | var wasmTable; 357 | 358 | var __ATPRERUN__ = []; 359 | 360 | var __ATINIT__ = []; 361 | 362 | var __ATPOSTRUN__ = []; 363 | 364 | var runtimeInitialized = false; 365 | 366 | function keepRuntimeAlive() { 367 | return noExitRuntime; 368 | } 369 | 370 | function preRun() { 371 | if (Module['preRun']) { 372 | if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']]; 373 | while (Module['preRun'].length) { 374 | addOnPreRun(Module['preRun'].shift()); 375 | } 376 | } 377 | callRuntimeCallbacks(__ATPRERUN__); 378 | } 379 | 380 | function initRuntime() { 381 | runtimeInitialized = true; 382 | callRuntimeCallbacks(__ATINIT__); 383 | } 384 | 385 | function postRun() { 386 | if (Module['postRun']) { 387 | if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']]; 388 | while (Module['postRun'].length) { 389 | addOnPostRun(Module['postRun'].shift()); 390 | } 391 | } 392 | callRuntimeCallbacks(__ATPOSTRUN__); 393 | } 394 | 395 | function addOnPreRun(cb) { 396 | __ATPRERUN__.unshift(cb); 397 | } 398 | 399 | function addOnInit(cb) { 400 | __ATINIT__.unshift(cb); 401 | } 402 | 403 | function addOnPostRun(cb) { 404 | __ATPOSTRUN__.unshift(cb); 405 | } 406 | 407 | var runDependencies = 0; 408 | 409 | var runDependencyWatcher = null; 410 | 411 | var dependenciesFulfilled = null; 412 | 413 | function addRunDependency(id) { 414 | runDependencies++; 415 | if (Module['monitorRunDependencies']) { 416 | Module['monitorRunDependencies'](runDependencies); 417 | } 418 | } 419 | 420 | function removeRunDependency(id) { 421 | runDependencies--; 422 | if (Module['monitorRunDependencies']) { 423 | Module['monitorRunDependencies'](runDependencies); 424 | } 425 | if (runDependencies == 0) { 426 | if (runDependencyWatcher !== null) { 427 | clearInterval(runDependencyWatcher); 428 | runDependencyWatcher = null; 429 | } 430 | if (dependenciesFulfilled) { 431 | var callback = dependenciesFulfilled; 432 | dependenciesFulfilled = null; 433 | callback(); 434 | } 435 | } 436 | } 437 | 438 | Module['preloadedImages'] = {}; 439 | 440 | Module['preloadedAudios'] = {}; 441 | 442 | function abort(what) { 443 | { 444 | if (Module['onAbort']) { 445 | Module['onAbort'](what); 446 | } 447 | } 448 | what = 'Aborted(' + what + ')'; 449 | err(what); 450 | ABORT = true; 451 | EXITSTATUS = 1; 452 | what += '. Build with -s ASSERTIONS=1 for more info.'; 453 | var e = new WebAssembly.RuntimeError(what); 454 | throw e; 455 | } 456 | 457 | var dataURIPrefix = 'data:application/octet-stream;base64,'; 458 | 459 | function isDataURI(filename) { 460 | return filename.startsWith(dataURIPrefix); 461 | } 462 | 463 | var wasmBinaryFile; 464 | 465 | wasmBinaryFile = 'bergamot-translator-worker.wasm'; 466 | 467 | if (!isDataURI(wasmBinaryFile)) { 468 | wasmBinaryFile = locateFile(wasmBinaryFile); 469 | } 470 | 471 | function getBinary(file) { 472 | try { 473 | if (file == wasmBinaryFile && wasmBinary) { 474 | return new Uint8Array(wasmBinary); 475 | } 476 | if (readBinary) { 477 | return readBinary(file); 478 | } else { 479 | throw 'both async and sync fetching of the wasm failed'; 480 | } 481 | } catch (err) { 482 | abort(err); 483 | } 484 | } 485 | 486 | function getBinaryPromise() { 487 | if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) { 488 | if (typeof fetch == 'function') { 489 | return fetch(wasmBinaryFile, { 490 | credentials: 'same-origin', 491 | }) 492 | .then(function (response) { 493 | if (!response['ok']) { 494 | throw "failed to load wasm binary file at '" + wasmBinaryFile + "'"; 495 | } 496 | return response['arrayBuffer'](); 497 | }) 498 | .catch(function () { 499 | return getBinary(wasmBinaryFile); 500 | }); 501 | } 502 | } 503 | return Promise.resolve().then(function () { 504 | return getBinary(wasmBinaryFile); 505 | }); 506 | } 507 | 508 | function createWasm() { 509 | var info = { 510 | env: asmLibraryArg, 511 | wasm_gemm: createWasmGemm(), 512 | wasi_snapshot_preview1: asmLibraryArg, 513 | }; 514 | function receiveInstance(instance, module) { 515 | var exports = instance.exports; 516 | Module['asm'] = exports; 517 | wasmTable = Module['asm']['__indirect_function_table']; 518 | addOnInit(Module['asm']['__wasm_call_ctors']); 519 | exportAsmFunctions(exports); 520 | removeRunDependency('wasm-instantiate'); 521 | } 522 | addRunDependency('wasm-instantiate'); 523 | function receiveInstantiationResult(result) { 524 | receiveInstance(result['instance']); 525 | } 526 | function instantiateArrayBuffer(receiver) { 527 | return getBinaryPromise() 528 | .then(function (binary) { 529 | return WebAssembly.instantiate(binary, info); 530 | }) 531 | .then(function (instance) { 532 | return instance; 533 | }) 534 | .then(receiver, function (reason) { 535 | err('failed to asynchronously prepare wasm: ' + reason); 536 | abort(reason); 537 | }); 538 | } 539 | function instantiateAsync() { 540 | if ( 541 | !wasmBinary && 542 | typeof WebAssembly.instantiateStreaming == 'function' && 543 | !isDataURI(wasmBinaryFile) && 544 | typeof fetch == 'function' 545 | ) { 546 | return fetch(wasmBinaryFile, { 547 | credentials: 'same-origin', 548 | }).then(function (response) { 549 | var result = WebAssembly.instantiateStreaming(response, info); 550 | return result.then(receiveInstantiationResult, function (reason) { 551 | err('wasm streaming compile failed: ' + reason); 552 | err('falling back to ArrayBuffer instantiation'); 553 | return instantiateArrayBuffer(receiveInstantiationResult); 554 | }); 555 | }); 556 | } else { 557 | return instantiateArrayBuffer(receiveInstantiationResult); 558 | } 559 | } 560 | if (Module['instantiateWasm']) { 561 | try { 562 | var exports = Module['instantiateWasm'](info, receiveInstance); 563 | return exports; 564 | } catch (e) { 565 | err('Module.instantiateWasm callback failed with error: ' + e); 566 | return false; 567 | } 568 | } 569 | instantiateAsync(); 570 | return {}; 571 | } 572 | 573 | function callRuntimeCallbacks(callbacks) { 574 | while (callbacks.length > 0) { 575 | var callback = callbacks.shift(); 576 | if (typeof callback == 'function') { 577 | callback(Module); 578 | continue; 579 | } 580 | var func = callback.func; 581 | if (typeof func == 'number') { 582 | if (callback.arg === undefined) { 583 | getWasmTableEntry(func)(); 584 | } else { 585 | getWasmTableEntry(func)(callback.arg); 586 | } 587 | } else { 588 | func(callback.arg === undefined ? null : callback.arg); 589 | } 590 | } 591 | } 592 | 593 | function asmjsMangle(x) { 594 | var unmangledSymbols = ['stackAlloc', 'stackSave', 'stackRestore']; 595 | return x.indexOf('dynCall_') == 0 || unmangledSymbols.includes(x) ? x : '_' + x; 596 | } 597 | 598 | function exportAsmFunctions(asm) { 599 | var global_object = this; 600 | for (var __exportedFunc in asm) { 601 | var jsname = asmjsMangle(__exportedFunc); 602 | global_object[jsname] = Module[jsname] = asm[__exportedFunc]; 603 | } 604 | } 605 | 606 | var wasmTableMirror = []; 607 | 608 | function getWasmTableEntry(funcPtr) { 609 | var func = wasmTableMirror[funcPtr]; 610 | if (!func) { 611 | if (funcPtr >= wasmTableMirror.length) wasmTableMirror.length = funcPtr + 1; 612 | wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr); 613 | } 614 | return func; 615 | } 616 | 617 | function ___assert_fail(condition, filename, line, func) { 618 | abort( 619 | 'Assertion failed: ' + 620 | UTF8ToString(condition) + 621 | ', at: ' + 622 | [filename ? UTF8ToString(filename) : 'unknown filename', line, func ? UTF8ToString(func) : 'unknown function'] 623 | ); 624 | } 625 | 626 | function ___cxa_allocate_exception(size) { 627 | return _malloc(size + 16) + 16; 628 | } 629 | 630 | var exceptionCaught = []; 631 | 632 | var exceptionLast = 0; 633 | 634 | var uncaughtExceptionCount = 0; 635 | 636 | function ___cxa_rethrow() { 637 | var catchInfo = exceptionCaught.pop(); 638 | if (!catchInfo) { 639 | abort('no exception to throw'); 640 | } 641 | var info = catchInfo.get_exception_info(); 642 | var ptr = catchInfo.get_base_ptr(); 643 | if (!info.get_rethrown()) { 644 | exceptionCaught.push(catchInfo); 645 | info.set_rethrown(true); 646 | info.set_caught(false); 647 | uncaughtExceptionCount++; 648 | } else { 649 | catchInfo.free(); 650 | } 651 | exceptionLast = ptr; 652 | throw ptr; 653 | } 654 | 655 | function ExceptionInfo(excPtr) { 656 | this.excPtr = excPtr; 657 | this.ptr = excPtr - 16; 658 | this.set_type = function (type) { 659 | HEAP32[(this.ptr + 4) >> 2] = type; 660 | }; 661 | this.get_type = function () { 662 | return HEAP32[(this.ptr + 4) >> 2]; 663 | }; 664 | this.set_destructor = function (destructor) { 665 | HEAP32[(this.ptr + 8) >> 2] = destructor; 666 | }; 667 | this.get_destructor = function () { 668 | return HEAP32[(this.ptr + 8) >> 2]; 669 | }; 670 | this.set_refcount = function (refcount) { 671 | HEAP32[this.ptr >> 2] = refcount; 672 | }; 673 | this.set_caught = function (caught) { 674 | caught = caught ? 1 : 0; 675 | HEAP8[(this.ptr + 12) >> 0] = caught; 676 | }; 677 | this.get_caught = function () { 678 | return HEAP8[(this.ptr + 12) >> 0] != 0; 679 | }; 680 | this.set_rethrown = function (rethrown) { 681 | rethrown = rethrown ? 1 : 0; 682 | HEAP8[(this.ptr + 13) >> 0] = rethrown; 683 | }; 684 | this.get_rethrown = function () { 685 | return HEAP8[(this.ptr + 13) >> 0] != 0; 686 | }; 687 | this.init = function (type, destructor) { 688 | this.set_type(type); 689 | this.set_destructor(destructor); 690 | this.set_refcount(0); 691 | this.set_caught(false); 692 | this.set_rethrown(false); 693 | }; 694 | this.add_ref = function () { 695 | var value = HEAP32[this.ptr >> 2]; 696 | HEAP32[this.ptr >> 2] = value + 1; 697 | }; 698 | this.release_ref = function () { 699 | var prev = HEAP32[this.ptr >> 2]; 700 | HEAP32[this.ptr >> 2] = prev - 1; 701 | return prev === 1; 702 | }; 703 | } 704 | 705 | function ___cxa_throw(ptr, type, destructor) { 706 | var info = new ExceptionInfo(ptr); 707 | info.init(type, destructor); 708 | exceptionLast = ptr; 709 | uncaughtExceptionCount++; 710 | throw ptr; 711 | } 712 | 713 | var SYSCALLS = { 714 | buffers: [null, [], []], 715 | printChar: function (stream, curr) { 716 | var buffer = SYSCALLS.buffers[stream]; 717 | if (curr === 0 || curr === 10) { 718 | (stream === 1 ? out : err)(UTF8ArrayToString(buffer, 0)); 719 | buffer.length = 0; 720 | } else { 721 | buffer.push(curr); 722 | } 723 | }, 724 | varargs: undefined, 725 | get: function () { 726 | SYSCALLS.varargs += 4; 727 | var ret = HEAP32[(SYSCALLS.varargs - 4) >> 2]; 728 | return ret; 729 | }, 730 | getStr: function (ptr) { 731 | var ret = UTF8ToString(ptr); 732 | return ret; 733 | }, 734 | get64: function (low, high) { 735 | return low; 736 | }, 737 | }; 738 | 739 | function ___syscall_faccessat(dirfd, path, amode, flags) { 740 | path = SYSCALLS.getStr(path); 741 | path = SYSCALLS.calculateAt(dirfd, path); 742 | return SYSCALLS.doAccess(path, amode); 743 | } 744 | 745 | function ___syscall_fcntl64(fd, cmd, varargs) { 746 | SYSCALLS.varargs = varargs; 747 | return 0; 748 | } 749 | 750 | function ___syscall_fstat64(fd, buf) {} 751 | 752 | function ___syscall_getcwd(buf, size) {} 753 | 754 | function ___syscall_ioctl(fd, op, varargs) { 755 | SYSCALLS.varargs = varargs; 756 | return 0; 757 | } 758 | 759 | function ___syscall_lstat64(path, buf) {} 760 | 761 | function ___syscall_newfstatat(dirfd, path, buf, flags) {} 762 | 763 | function ___syscall_openat(dirfd, path, flags, varargs) { 764 | SYSCALLS.varargs = varargs; 765 | } 766 | 767 | function ___syscall_renameat(olddirfd, oldpath, newdirfd, newpath) {} 768 | 769 | function ___syscall_rmdir(path) {} 770 | 771 | function ___syscall_stat64(path, buf) {} 772 | 773 | function ___syscall_unlinkat(dirfd, path, flags) {} 774 | 775 | var structRegistrations = {}; 776 | 777 | function runDestructors(destructors) { 778 | while (destructors.length) { 779 | var ptr = destructors.pop(); 780 | var del = destructors.pop(); 781 | del(ptr); 782 | } 783 | } 784 | 785 | function simpleReadValueFromPointer(pointer) { 786 | return this['fromWireType'](HEAPU32[pointer >> 2]); 787 | } 788 | 789 | var awaitingDependencies = {}; 790 | 791 | var registeredTypes = {}; 792 | 793 | var typeDependencies = {}; 794 | 795 | var char_0 = 48; 796 | 797 | var char_9 = 57; 798 | 799 | function makeLegalFunctionName(name) { 800 | if (undefined === name) { 801 | return '_unknown'; 802 | } 803 | name = name.replace(/[^a-zA-Z0-9_]/g, '$'); 804 | var f = name.charCodeAt(0); 805 | if (f >= char_0 && f <= char_9) { 806 | return '_' + name; 807 | } 808 | return name; 809 | } 810 | 811 | function createNamedFunction(name, body) { 812 | name = makeLegalFunctionName(name); 813 | return function () { 814 | null; 815 | return body.apply(this, arguments); 816 | }; 817 | } 818 | 819 | function extendError(baseErrorType, errorName) { 820 | var errorClass = createNamedFunction(errorName, function (message) { 821 | this.name = errorName; 822 | this.message = message; 823 | var stack = new Error(message).stack; 824 | if (stack !== undefined) { 825 | this.stack = this.toString() + '\n' + stack.replace(/^Error(:[^\n]*)?\n/, ''); 826 | } 827 | }); 828 | errorClass.prototype = Object.create(baseErrorType.prototype); 829 | errorClass.prototype.constructor = errorClass; 830 | errorClass.prototype.toString = function () { 831 | if (this.message === undefined) { 832 | return this.name; 833 | } else { 834 | return this.name + ': ' + this.message; 835 | } 836 | }; 837 | return errorClass; 838 | } 839 | 840 | var InternalError = undefined; 841 | 842 | function throwInternalError(message) { 843 | throw new InternalError(message); 844 | } 845 | 846 | function whenDependentTypesAreResolved(myTypes, dependentTypes, getTypeConverters) { 847 | myTypes.forEach(function (type) { 848 | typeDependencies[type] = dependentTypes; 849 | }); 850 | function onComplete(typeConverters) { 851 | var myTypeConverters = getTypeConverters(typeConverters); 852 | if (myTypeConverters.length !== myTypes.length) { 853 | throwInternalError('Mismatched type converter count'); 854 | } 855 | for (var i = 0; i < myTypes.length; ++i) { 856 | registerType(myTypes[i], myTypeConverters[i]); 857 | } 858 | } 859 | var typeConverters = new Array(dependentTypes.length); 860 | var unregisteredTypes = []; 861 | var registered = 0; 862 | dependentTypes.forEach((dt, i) => { 863 | if (registeredTypes.hasOwnProperty(dt)) { 864 | typeConverters[i] = registeredTypes[dt]; 865 | } else { 866 | unregisteredTypes.push(dt); 867 | if (!awaitingDependencies.hasOwnProperty(dt)) { 868 | awaitingDependencies[dt] = []; 869 | } 870 | awaitingDependencies[dt].push(() => { 871 | typeConverters[i] = registeredTypes[dt]; 872 | ++registered; 873 | if (registered === unregisteredTypes.length) { 874 | onComplete(typeConverters); 875 | } 876 | }); 877 | } 878 | }); 879 | if (0 === unregisteredTypes.length) { 880 | onComplete(typeConverters); 881 | } 882 | } 883 | 884 | function __embind_finalize_value_object(structType) { 885 | var reg = structRegistrations[structType]; 886 | delete structRegistrations[structType]; 887 | var rawConstructor = reg.rawConstructor; 888 | var rawDestructor = reg.rawDestructor; 889 | var fieldRecords = reg.fields; 890 | var fieldTypes = fieldRecords 891 | .map(field => field.getterReturnType) 892 | .concat(fieldRecords.map(field => field.setterArgumentType)); 893 | whenDependentTypesAreResolved([structType], fieldTypes, fieldTypes => { 894 | var fields = {}; 895 | fieldRecords.forEach((field, i) => { 896 | var fieldName = field.fieldName; 897 | var getterReturnType = fieldTypes[i]; 898 | var getter = field.getter; 899 | var getterContext = field.getterContext; 900 | var setterArgumentType = fieldTypes[i + fieldRecords.length]; 901 | var setter = field.setter; 902 | var setterContext = field.setterContext; 903 | fields[fieldName] = { 904 | read: ptr => { 905 | return getterReturnType['fromWireType'](getter(getterContext, ptr)); 906 | }, 907 | write: (ptr, o) => { 908 | var destructors = []; 909 | setter(setterContext, ptr, setterArgumentType['toWireType'](destructors, o)); 910 | runDestructors(destructors); 911 | }, 912 | }; 913 | }); 914 | return [ 915 | { 916 | name: reg.name, 917 | fromWireType: function (ptr) { 918 | var rv = {}; 919 | for (var i in fields) { 920 | rv[i] = fields[i].read(ptr); 921 | } 922 | rawDestructor(ptr); 923 | return rv; 924 | }, 925 | toWireType: function (destructors, o) { 926 | for (var fieldName in fields) { 927 | if (!(fieldName in o)) { 928 | throw new TypeError('Missing field: "' + fieldName + '"'); 929 | } 930 | } 931 | var ptr = rawConstructor(); 932 | for (fieldName in fields) { 933 | fields[fieldName].write(ptr, o[fieldName]); 934 | } 935 | if (destructors !== null) { 936 | destructors.push(rawDestructor, ptr); 937 | } 938 | return ptr; 939 | }, 940 | argPackAdvance: 8, 941 | readValueFromPointer: simpleReadValueFromPointer, 942 | destructorFunction: rawDestructor, 943 | }, 944 | ]; 945 | }); 946 | } 947 | 948 | function __embind_register_bigint(primitiveType, name, size, minRange, maxRange) {} 949 | 950 | function getShiftFromSize(size) { 951 | switch (size) { 952 | case 1: 953 | return 0; 954 | 955 | case 2: 956 | return 1; 957 | 958 | case 4: 959 | return 2; 960 | 961 | case 8: 962 | return 3; 963 | 964 | default: 965 | throw new TypeError('Unknown type size: ' + size); 966 | } 967 | } 968 | 969 | function embind_init_charCodes() { 970 | var codes = new Array(256); 971 | for (var i = 0; i < 256; ++i) { 972 | codes[i] = String.fromCharCode(i); 973 | } 974 | embind_charCodes = codes; 975 | } 976 | 977 | var embind_charCodes = undefined; 978 | 979 | function readLatin1String(ptr) { 980 | var ret = ''; 981 | var c = ptr; 982 | while (HEAPU8[c]) { 983 | ret += embind_charCodes[HEAPU8[c++]]; 984 | } 985 | return ret; 986 | } 987 | 988 | var BindingError = undefined; 989 | 990 | function throwBindingError(message) { 991 | throw new BindingError(message); 992 | } 993 | 994 | function registerType(rawType, registeredInstance, options = {}) { 995 | if (!('argPackAdvance' in registeredInstance)) { 996 | throw new TypeError('registerType registeredInstance requires argPackAdvance'); 997 | } 998 | var name = registeredInstance.name; 999 | if (!rawType) { 1000 | throwBindingError('type "' + name + '" must have a positive integer typeid pointer'); 1001 | } 1002 | if (registeredTypes.hasOwnProperty(rawType)) { 1003 | if (options.ignoreDuplicateRegistrations) { 1004 | return; 1005 | } else { 1006 | throwBindingError("Cannot register type '" + name + "' twice"); 1007 | } 1008 | } 1009 | registeredTypes[rawType] = registeredInstance; 1010 | delete typeDependencies[rawType]; 1011 | if (awaitingDependencies.hasOwnProperty(rawType)) { 1012 | var callbacks = awaitingDependencies[rawType]; 1013 | delete awaitingDependencies[rawType]; 1014 | callbacks.forEach(cb => cb()); 1015 | } 1016 | } 1017 | 1018 | function __embind_register_bool(rawType, name, size, trueValue, falseValue) { 1019 | var shift = getShiftFromSize(size); 1020 | name = readLatin1String(name); 1021 | registerType(rawType, { 1022 | name: name, 1023 | fromWireType: function (wt) { 1024 | return !!wt; 1025 | }, 1026 | toWireType: function (destructors, o) { 1027 | return o ? trueValue : falseValue; 1028 | }, 1029 | argPackAdvance: 8, 1030 | readValueFromPointer: function (pointer) { 1031 | var heap; 1032 | if (size === 1) { 1033 | heap = HEAP8; 1034 | } else if (size === 2) { 1035 | heap = HEAP16; 1036 | } else if (size === 4) { 1037 | heap = HEAP32; 1038 | } else { 1039 | throw new TypeError('Unknown boolean type size: ' + name); 1040 | } 1041 | return this['fromWireType'](heap[pointer >> shift]); 1042 | }, 1043 | destructorFunction: null, 1044 | }); 1045 | } 1046 | 1047 | function ClassHandle_isAliasOf(other) { 1048 | if (!(this instanceof ClassHandle)) { 1049 | return false; 1050 | } 1051 | if (!(other instanceof ClassHandle)) { 1052 | return false; 1053 | } 1054 | var leftClass = this.$$.ptrType.registeredClass; 1055 | var left = this.$$.ptr; 1056 | var rightClass = other.$$.ptrType.registeredClass; 1057 | var right = other.$$.ptr; 1058 | while (leftClass.baseClass) { 1059 | left = leftClass.upcast(left); 1060 | leftClass = leftClass.baseClass; 1061 | } 1062 | while (rightClass.baseClass) { 1063 | right = rightClass.upcast(right); 1064 | rightClass = rightClass.baseClass; 1065 | } 1066 | return leftClass === rightClass && left === right; 1067 | } 1068 | 1069 | function shallowCopyInternalPointer(o) { 1070 | return { 1071 | count: o.count, 1072 | deleteScheduled: o.deleteScheduled, 1073 | preservePointerOnDelete: o.preservePointerOnDelete, 1074 | ptr: o.ptr, 1075 | ptrType: o.ptrType, 1076 | smartPtr: o.smartPtr, 1077 | smartPtrType: o.smartPtrType, 1078 | }; 1079 | } 1080 | 1081 | function throwInstanceAlreadyDeleted(obj) { 1082 | function getInstanceTypeName(handle) { 1083 | return handle.$$.ptrType.registeredClass.name; 1084 | } 1085 | throwBindingError(getInstanceTypeName(obj) + ' instance already deleted'); 1086 | } 1087 | 1088 | var finalizationRegistry = false; 1089 | 1090 | function detachFinalizer(handle) {} 1091 | 1092 | function runDestructor($$) { 1093 | if ($$.smartPtr) { 1094 | $$.smartPtrType.rawDestructor($$.smartPtr); 1095 | } else { 1096 | $$.ptrType.registeredClass.rawDestructor($$.ptr); 1097 | } 1098 | } 1099 | 1100 | function releaseClassHandle($$) { 1101 | $$.count.value -= 1; 1102 | var toDelete = 0 === $$.count.value; 1103 | if (toDelete) { 1104 | runDestructor($$); 1105 | } 1106 | } 1107 | 1108 | function downcastPointer(ptr, ptrClass, desiredClass) { 1109 | if (ptrClass === desiredClass) { 1110 | return ptr; 1111 | } 1112 | if (undefined === desiredClass.baseClass) { 1113 | return null; 1114 | } 1115 | var rv = downcastPointer(ptr, ptrClass, desiredClass.baseClass); 1116 | if (rv === null) { 1117 | return null; 1118 | } 1119 | return desiredClass.downcast(rv); 1120 | } 1121 | 1122 | var registeredPointers = {}; 1123 | 1124 | function getInheritedInstanceCount() { 1125 | return Object.keys(registeredInstances).length; 1126 | } 1127 | 1128 | function getLiveInheritedInstances() { 1129 | var rv = []; 1130 | for (var k in registeredInstances) { 1131 | if (registeredInstances.hasOwnProperty(k)) { 1132 | rv.push(registeredInstances[k]); 1133 | } 1134 | } 1135 | return rv; 1136 | } 1137 | 1138 | var deletionQueue = []; 1139 | 1140 | function flushPendingDeletes() { 1141 | while (deletionQueue.length) { 1142 | var obj = deletionQueue.pop(); 1143 | obj.$$.deleteScheduled = false; 1144 | obj['delete'](); 1145 | } 1146 | } 1147 | 1148 | var delayFunction = undefined; 1149 | 1150 | function setDelayFunction(fn) { 1151 | delayFunction = fn; 1152 | if (deletionQueue.length && delayFunction) { 1153 | delayFunction(flushPendingDeletes); 1154 | } 1155 | } 1156 | 1157 | function init_embind() { 1158 | Module['getInheritedInstanceCount'] = getInheritedInstanceCount; 1159 | Module['getLiveInheritedInstances'] = getLiveInheritedInstances; 1160 | Module['flushPendingDeletes'] = flushPendingDeletes; 1161 | Module['setDelayFunction'] = setDelayFunction; 1162 | } 1163 | 1164 | var registeredInstances = {}; 1165 | 1166 | function getBasestPointer(class_, ptr) { 1167 | if (ptr === undefined) { 1168 | throwBindingError('ptr should not be undefined'); 1169 | } 1170 | while (class_.baseClass) { 1171 | ptr = class_.upcast(ptr); 1172 | class_ = class_.baseClass; 1173 | } 1174 | return ptr; 1175 | } 1176 | 1177 | function getInheritedInstance(class_, ptr) { 1178 | ptr = getBasestPointer(class_, ptr); 1179 | return registeredInstances[ptr]; 1180 | } 1181 | 1182 | function makeClassHandle(prototype, record) { 1183 | if (!record.ptrType || !record.ptr) { 1184 | throwInternalError('makeClassHandle requires ptr and ptrType'); 1185 | } 1186 | var hasSmartPtrType = !!record.smartPtrType; 1187 | var hasSmartPtr = !!record.smartPtr; 1188 | if (hasSmartPtrType !== hasSmartPtr) { 1189 | throwInternalError('Both smartPtrType and smartPtr must be specified'); 1190 | } 1191 | record.count = { 1192 | value: 1, 1193 | }; 1194 | return attachFinalizer( 1195 | Object.create(prototype, { 1196 | $$: { 1197 | value: record, 1198 | }, 1199 | }) 1200 | ); 1201 | } 1202 | 1203 | function RegisteredPointer_fromWireType(ptr) { 1204 | var rawPointer = this.getPointee(ptr); 1205 | if (!rawPointer) { 1206 | this.destructor(ptr); 1207 | return null; 1208 | } 1209 | var registeredInstance = getInheritedInstance(this.registeredClass, rawPointer); 1210 | if (undefined !== registeredInstance) { 1211 | if (0 === registeredInstance.$$.count.value) { 1212 | registeredInstance.$$.ptr = rawPointer; 1213 | registeredInstance.$$.smartPtr = ptr; 1214 | return registeredInstance['clone'](); 1215 | } else { 1216 | var rv = registeredInstance['clone'](); 1217 | this.destructor(ptr); 1218 | return rv; 1219 | } 1220 | } 1221 | function makeDefaultHandle() { 1222 | if (this.isSmartPointer) { 1223 | return makeClassHandle(this.registeredClass.instancePrototype, { 1224 | ptrType: this.pointeeType, 1225 | ptr: rawPointer, 1226 | smartPtrType: this, 1227 | smartPtr: ptr, 1228 | }); 1229 | } else { 1230 | return makeClassHandle(this.registeredClass.instancePrototype, { 1231 | ptrType: this, 1232 | ptr: ptr, 1233 | }); 1234 | } 1235 | } 1236 | var actualType = this.registeredClass.getActualType(rawPointer); 1237 | var registeredPointerRecord = registeredPointers[actualType]; 1238 | if (!registeredPointerRecord) { 1239 | return makeDefaultHandle.call(this); 1240 | } 1241 | var toType; 1242 | if (this.isConst) { 1243 | toType = registeredPointerRecord.constPointerType; 1244 | } else { 1245 | toType = registeredPointerRecord.pointerType; 1246 | } 1247 | var dp = downcastPointer(rawPointer, this.registeredClass, toType.registeredClass); 1248 | if (dp === null) { 1249 | return makeDefaultHandle.call(this); 1250 | } 1251 | if (this.isSmartPointer) { 1252 | return makeClassHandle(toType.registeredClass.instancePrototype, { 1253 | ptrType: toType, 1254 | ptr: dp, 1255 | smartPtrType: this, 1256 | smartPtr: ptr, 1257 | }); 1258 | } else { 1259 | return makeClassHandle(toType.registeredClass.instancePrototype, { 1260 | ptrType: toType, 1261 | ptr: dp, 1262 | }); 1263 | } 1264 | } 1265 | 1266 | function attachFinalizer(handle) { 1267 | if ('undefined' === typeof FinalizationRegistry) { 1268 | attachFinalizer = handle => handle; 1269 | return handle; 1270 | } 1271 | finalizationRegistry = new FinalizationRegistry(info => { 1272 | releaseClassHandle(info.$$); 1273 | }); 1274 | attachFinalizer = handle => { 1275 | var $$ = handle.$$; 1276 | var hasSmartPtr = !!$$.smartPtr; 1277 | if (hasSmartPtr) { 1278 | var info = { 1279 | $$: $$, 1280 | }; 1281 | finalizationRegistry.register(handle, info, handle); 1282 | } 1283 | return handle; 1284 | }; 1285 | detachFinalizer = handle => finalizationRegistry.unregister(handle); 1286 | return attachFinalizer(handle); 1287 | } 1288 | 1289 | function ClassHandle_clone() { 1290 | if (!this.$$.ptr) { 1291 | throwInstanceAlreadyDeleted(this); 1292 | } 1293 | if (this.$$.preservePointerOnDelete) { 1294 | this.$$.count.value += 1; 1295 | return this; 1296 | } else { 1297 | var clone = attachFinalizer( 1298 | Object.create(Object.getPrototypeOf(this), { 1299 | $$: { 1300 | value: shallowCopyInternalPointer(this.$$), 1301 | }, 1302 | }) 1303 | ); 1304 | clone.$$.count.value += 1; 1305 | clone.$$.deleteScheduled = false; 1306 | return clone; 1307 | } 1308 | } 1309 | 1310 | function ClassHandle_delete() { 1311 | if (!this.$$.ptr) { 1312 | throwInstanceAlreadyDeleted(this); 1313 | } 1314 | if (this.$$.deleteScheduled && !this.$$.preservePointerOnDelete) { 1315 | throwBindingError('Object already scheduled for deletion'); 1316 | } 1317 | detachFinalizer(this); 1318 | releaseClassHandle(this.$$); 1319 | if (!this.$$.preservePointerOnDelete) { 1320 | this.$$.smartPtr = undefined; 1321 | this.$$.ptr = undefined; 1322 | } 1323 | } 1324 | 1325 | function ClassHandle_isDeleted() { 1326 | return !this.$$.ptr; 1327 | } 1328 | 1329 | function ClassHandle_deleteLater() { 1330 | if (!this.$$.ptr) { 1331 | throwInstanceAlreadyDeleted(this); 1332 | } 1333 | if (this.$$.deleteScheduled && !this.$$.preservePointerOnDelete) { 1334 | throwBindingError('Object already scheduled for deletion'); 1335 | } 1336 | deletionQueue.push(this); 1337 | if (deletionQueue.length === 1 && delayFunction) { 1338 | delayFunction(flushPendingDeletes); 1339 | } 1340 | this.$$.deleteScheduled = true; 1341 | return this; 1342 | } 1343 | 1344 | function init_ClassHandle() { 1345 | ClassHandle.prototype['isAliasOf'] = ClassHandle_isAliasOf; 1346 | ClassHandle.prototype['clone'] = ClassHandle_clone; 1347 | ClassHandle.prototype['delete'] = ClassHandle_delete; 1348 | ClassHandle.prototype['isDeleted'] = ClassHandle_isDeleted; 1349 | ClassHandle.prototype['deleteLater'] = ClassHandle_deleteLater; 1350 | } 1351 | 1352 | function ClassHandle() {} 1353 | 1354 | function ensureOverloadTable(proto, methodName, humanName) { 1355 | if (undefined === proto[methodName].overloadTable) { 1356 | var prevFunc = proto[methodName]; 1357 | proto[methodName] = function () { 1358 | if (!proto[methodName].overloadTable.hasOwnProperty(arguments.length)) { 1359 | throwBindingError( 1360 | "Function '" + 1361 | humanName + 1362 | "' called with an invalid number of arguments (" + 1363 | arguments.length + 1364 | ') - expects one of (' + 1365 | proto[methodName].overloadTable + 1366 | ')!' 1367 | ); 1368 | } 1369 | return proto[methodName].overloadTable[arguments.length].apply(this, arguments); 1370 | }; 1371 | proto[methodName].overloadTable = []; 1372 | proto[methodName].overloadTable[prevFunc.argCount] = prevFunc; 1373 | } 1374 | } 1375 | 1376 | function exposePublicSymbol(name, value, numArguments) { 1377 | if (Module.hasOwnProperty(name)) { 1378 | if ( 1379 | undefined === numArguments || 1380 | (undefined !== Module[name].overloadTable && undefined !== Module[name].overloadTable[numArguments]) 1381 | ) { 1382 | throwBindingError("Cannot register public name '" + name + "' twice"); 1383 | } 1384 | ensureOverloadTable(Module, name, name); 1385 | if (Module.hasOwnProperty(numArguments)) { 1386 | throwBindingError( 1387 | 'Cannot register multiple overloads of a function with the same number of arguments (' + numArguments + ')!' 1388 | ); 1389 | } 1390 | Module[name].overloadTable[numArguments] = value; 1391 | } else { 1392 | Module[name] = value; 1393 | if (undefined !== numArguments) { 1394 | Module[name].numArguments = numArguments; 1395 | } 1396 | } 1397 | } 1398 | 1399 | function RegisteredClass( 1400 | name, 1401 | constructor, 1402 | instancePrototype, 1403 | rawDestructor, 1404 | baseClass, 1405 | getActualType, 1406 | upcast, 1407 | downcast 1408 | ) { 1409 | this.name = name; 1410 | this.constructor = constructor; 1411 | this.instancePrototype = instancePrototype; 1412 | this.rawDestructor = rawDestructor; 1413 | this.baseClass = baseClass; 1414 | this.getActualType = getActualType; 1415 | this.upcast = upcast; 1416 | this.downcast = downcast; 1417 | this.pureVirtualFunctions = []; 1418 | } 1419 | 1420 | function upcastPointer(ptr, ptrClass, desiredClass) { 1421 | while (ptrClass !== desiredClass) { 1422 | if (!ptrClass.upcast) { 1423 | throwBindingError('Expected null or instance of ' + desiredClass.name + ', got an instance of ' + ptrClass.name); 1424 | } 1425 | ptr = ptrClass.upcast(ptr); 1426 | ptrClass = ptrClass.baseClass; 1427 | } 1428 | return ptr; 1429 | } 1430 | 1431 | function constNoSmartPtrRawPointerToWireType(destructors, handle) { 1432 | if (handle === null) { 1433 | if (this.isReference) { 1434 | throwBindingError('null is not a valid ' + this.name); 1435 | } 1436 | return 0; 1437 | } 1438 | if (!handle.$$) { 1439 | throwBindingError('Cannot pass "' + _embind_repr(handle) + '" as a ' + this.name); 1440 | } 1441 | if (!handle.$$.ptr) { 1442 | throwBindingError('Cannot pass deleted object as a pointer of type ' + this.name); 1443 | } 1444 | var handleClass = handle.$$.ptrType.registeredClass; 1445 | var ptr = upcastPointer(handle.$$.ptr, handleClass, this.registeredClass); 1446 | return ptr; 1447 | } 1448 | 1449 | function genericPointerToWireType(destructors, handle) { 1450 | var ptr; 1451 | if (handle === null) { 1452 | if (this.isReference) { 1453 | throwBindingError('null is not a valid ' + this.name); 1454 | } 1455 | if (this.isSmartPointer) { 1456 | ptr = this.rawConstructor(); 1457 | if (destructors !== null) { 1458 | destructors.push(this.rawDestructor, ptr); 1459 | } 1460 | return ptr; 1461 | } else { 1462 | return 0; 1463 | } 1464 | } 1465 | if (!handle.$$) { 1466 | throwBindingError('Cannot pass "' + _embind_repr(handle) + '" as a ' + this.name); 1467 | } 1468 | if (!handle.$$.ptr) { 1469 | throwBindingError('Cannot pass deleted object as a pointer of type ' + this.name); 1470 | } 1471 | if (!this.isConst && handle.$$.ptrType.isConst) { 1472 | throwBindingError( 1473 | 'Cannot convert argument of type ' + 1474 | (handle.$$.smartPtrType ? handle.$$.smartPtrType.name : handle.$$.ptrType.name) + 1475 | ' to parameter type ' + 1476 | this.name 1477 | ); 1478 | } 1479 | var handleClass = handle.$$.ptrType.registeredClass; 1480 | ptr = upcastPointer(handle.$$.ptr, handleClass, this.registeredClass); 1481 | if (this.isSmartPointer) { 1482 | if (undefined === handle.$$.smartPtr) { 1483 | throwBindingError('Passing raw pointer to smart pointer is illegal'); 1484 | } 1485 | switch (this.sharingPolicy) { 1486 | case 0: 1487 | if (handle.$$.smartPtrType === this) { 1488 | ptr = handle.$$.smartPtr; 1489 | } else { 1490 | throwBindingError( 1491 | 'Cannot convert argument of type ' + 1492 | (handle.$$.smartPtrType ? handle.$$.smartPtrType.name : handle.$$.ptrType.name) + 1493 | ' to parameter type ' + 1494 | this.name 1495 | ); 1496 | } 1497 | break; 1498 | 1499 | case 1: 1500 | ptr = handle.$$.smartPtr; 1501 | break; 1502 | 1503 | case 2: 1504 | if (handle.$$.smartPtrType === this) { 1505 | ptr = handle.$$.smartPtr; 1506 | } else { 1507 | var clonedHandle = handle['clone'](); 1508 | ptr = this.rawShare( 1509 | ptr, 1510 | Emval.toHandle(function () { 1511 | clonedHandle['delete'](); 1512 | }) 1513 | ); 1514 | if (destructors !== null) { 1515 | destructors.push(this.rawDestructor, ptr); 1516 | } 1517 | } 1518 | break; 1519 | 1520 | default: 1521 | throwBindingError('Unsupporting sharing policy'); 1522 | } 1523 | } 1524 | return ptr; 1525 | } 1526 | 1527 | function nonConstNoSmartPtrRawPointerToWireType(destructors, handle) { 1528 | if (handle === null) { 1529 | if (this.isReference) { 1530 | throwBindingError('null is not a valid ' + this.name); 1531 | } 1532 | return 0; 1533 | } 1534 | if (!handle.$$) { 1535 | throwBindingError('Cannot pass "' + _embind_repr(handle) + '" as a ' + this.name); 1536 | } 1537 | if (!handle.$$.ptr) { 1538 | throwBindingError('Cannot pass deleted object as a pointer of type ' + this.name); 1539 | } 1540 | if (handle.$$.ptrType.isConst) { 1541 | throwBindingError('Cannot convert argument of type ' + handle.$$.ptrType.name + ' to parameter type ' + this.name); 1542 | } 1543 | var handleClass = handle.$$.ptrType.registeredClass; 1544 | var ptr = upcastPointer(handle.$$.ptr, handleClass, this.registeredClass); 1545 | return ptr; 1546 | } 1547 | 1548 | function RegisteredPointer_getPointee(ptr) { 1549 | if (this.rawGetPointee) { 1550 | ptr = this.rawGetPointee(ptr); 1551 | } 1552 | return ptr; 1553 | } 1554 | 1555 | function RegisteredPointer_destructor(ptr) { 1556 | if (this.rawDestructor) { 1557 | this.rawDestructor(ptr); 1558 | } 1559 | } 1560 | 1561 | function RegisteredPointer_deleteObject(handle) { 1562 | if (handle !== null) { 1563 | handle['delete'](); 1564 | } 1565 | } 1566 | 1567 | function init_RegisteredPointer() { 1568 | RegisteredPointer.prototype.getPointee = RegisteredPointer_getPointee; 1569 | RegisteredPointer.prototype.destructor = RegisteredPointer_destructor; 1570 | RegisteredPointer.prototype['argPackAdvance'] = 8; 1571 | RegisteredPointer.prototype['readValueFromPointer'] = simpleReadValueFromPointer; 1572 | RegisteredPointer.prototype['deleteObject'] = RegisteredPointer_deleteObject; 1573 | RegisteredPointer.prototype['fromWireType'] = RegisteredPointer_fromWireType; 1574 | } 1575 | 1576 | function RegisteredPointer( 1577 | name, 1578 | registeredClass, 1579 | isReference, 1580 | isConst, 1581 | isSmartPointer, 1582 | pointeeType, 1583 | sharingPolicy, 1584 | rawGetPointee, 1585 | rawConstructor, 1586 | rawShare, 1587 | rawDestructor 1588 | ) { 1589 | this.name = name; 1590 | this.registeredClass = registeredClass; 1591 | this.isReference = isReference; 1592 | this.isConst = isConst; 1593 | this.isSmartPointer = isSmartPointer; 1594 | this.pointeeType = pointeeType; 1595 | this.sharingPolicy = sharingPolicy; 1596 | this.rawGetPointee = rawGetPointee; 1597 | this.rawConstructor = rawConstructor; 1598 | this.rawShare = rawShare; 1599 | this.rawDestructor = rawDestructor; 1600 | if (!isSmartPointer && registeredClass.baseClass === undefined) { 1601 | if (isConst) { 1602 | this['toWireType'] = constNoSmartPtrRawPointerToWireType; 1603 | this.destructorFunction = null; 1604 | } else { 1605 | this['toWireType'] = nonConstNoSmartPtrRawPointerToWireType; 1606 | this.destructorFunction = null; 1607 | } 1608 | } else { 1609 | this['toWireType'] = genericPointerToWireType; 1610 | } 1611 | } 1612 | 1613 | function replacePublicSymbol(name, value, numArguments) { 1614 | if (!Module.hasOwnProperty(name)) { 1615 | throwInternalError('Replacing nonexistant public symbol'); 1616 | } 1617 | if (undefined !== Module[name].overloadTable && undefined !== numArguments) { 1618 | Module[name].overloadTable[numArguments] = value; 1619 | } else { 1620 | Module[name] = value; 1621 | Module[name].argCount = numArguments; 1622 | } 1623 | } 1624 | 1625 | function dynCallLegacy(sig, ptr, args) { 1626 | var f = Module['dynCall_' + sig]; 1627 | return args && args.length ? f.apply(null, [ptr].concat(args)) : f.call(null, ptr); 1628 | } 1629 | 1630 | function dynCall(sig, ptr, args) { 1631 | if (sig.includes('j')) { 1632 | return dynCallLegacy(sig, ptr, args); 1633 | } 1634 | return getWasmTableEntry(ptr).apply(null, args); 1635 | } 1636 | 1637 | function getDynCaller(sig, ptr) { 1638 | var argCache = []; 1639 | return function () { 1640 | argCache.length = 0; 1641 | Object.assign(argCache, arguments); 1642 | return dynCall(sig, ptr, argCache); 1643 | }; 1644 | } 1645 | 1646 | function embind__requireFunction(signature, rawFunction) { 1647 | signature = readLatin1String(signature); 1648 | function makeDynCaller() { 1649 | if (signature.includes('j')) { 1650 | return getDynCaller(signature, rawFunction); 1651 | } 1652 | return getWasmTableEntry(rawFunction); 1653 | } 1654 | var fp = makeDynCaller(); 1655 | if (typeof fp != 'function') { 1656 | throwBindingError('unknown function pointer with signature ' + signature + ': ' + rawFunction); 1657 | } 1658 | return fp; 1659 | } 1660 | 1661 | var UnboundTypeError = undefined; 1662 | 1663 | function getTypeName(type) { 1664 | var ptr = ___getTypeName(type); 1665 | var rv = readLatin1String(ptr); 1666 | _free(ptr); 1667 | return rv; 1668 | } 1669 | 1670 | function throwUnboundTypeError(message, types) { 1671 | var unboundTypes = []; 1672 | var seen = {}; 1673 | function visit(type) { 1674 | if (seen[type]) { 1675 | return; 1676 | } 1677 | if (registeredTypes[type]) { 1678 | return; 1679 | } 1680 | if (typeDependencies[type]) { 1681 | typeDependencies[type].forEach(visit); 1682 | return; 1683 | } 1684 | unboundTypes.push(type); 1685 | seen[type] = true; 1686 | } 1687 | types.forEach(visit); 1688 | throw new UnboundTypeError(message + ': ' + unboundTypes.map(getTypeName).join([', '])); 1689 | } 1690 | 1691 | function __embind_register_class( 1692 | rawType, 1693 | rawPointerType, 1694 | rawConstPointerType, 1695 | baseClassRawType, 1696 | getActualTypeSignature, 1697 | getActualType, 1698 | upcastSignature, 1699 | upcast, 1700 | downcastSignature, 1701 | downcast, 1702 | name, 1703 | destructorSignature, 1704 | rawDestructor 1705 | ) { 1706 | name = readLatin1String(name); 1707 | getActualType = embind__requireFunction(getActualTypeSignature, getActualType); 1708 | if (upcast) { 1709 | upcast = embind__requireFunction(upcastSignature, upcast); 1710 | } 1711 | if (downcast) { 1712 | downcast = embind__requireFunction(downcastSignature, downcast); 1713 | } 1714 | rawDestructor = embind__requireFunction(destructorSignature, rawDestructor); 1715 | var legalFunctionName = makeLegalFunctionName(name); 1716 | exposePublicSymbol(legalFunctionName, function () { 1717 | throwUnboundTypeError('Cannot construct ' + name + ' due to unbound types', [baseClassRawType]); 1718 | }); 1719 | whenDependentTypesAreResolved( 1720 | [rawType, rawPointerType, rawConstPointerType], 1721 | baseClassRawType ? [baseClassRawType] : [], 1722 | function (base) { 1723 | base = base[0]; 1724 | var baseClass; 1725 | var basePrototype; 1726 | if (baseClassRawType) { 1727 | baseClass = base.registeredClass; 1728 | basePrototype = baseClass.instancePrototype; 1729 | } else { 1730 | basePrototype = ClassHandle.prototype; 1731 | } 1732 | var constructor = createNamedFunction(legalFunctionName, function () { 1733 | if (Object.getPrototypeOf(this) !== instancePrototype) { 1734 | throw new BindingError("Use 'new' to construct " + name); 1735 | } 1736 | if (undefined === registeredClass.constructor_body) { 1737 | throw new BindingError(name + ' has no accessible constructor'); 1738 | } 1739 | var body = registeredClass.constructor_body[arguments.length]; 1740 | if (undefined === body) { 1741 | throw new BindingError( 1742 | 'Tried to invoke ctor of ' + 1743 | name + 1744 | ' with invalid number of parameters (' + 1745 | arguments.length + 1746 | ') - expected (' + 1747 | Object.keys(registeredClass.constructor_body).toString() + 1748 | ') parameters instead!' 1749 | ); 1750 | } 1751 | return body.apply(this, arguments); 1752 | }); 1753 | var instancePrototype = Object.create(basePrototype, { 1754 | constructor: { 1755 | value: constructor, 1756 | }, 1757 | }); 1758 | constructor.prototype = instancePrototype; 1759 | var registeredClass = new RegisteredClass( 1760 | name, 1761 | constructor, 1762 | instancePrototype, 1763 | rawDestructor, 1764 | baseClass, 1765 | getActualType, 1766 | upcast, 1767 | downcast 1768 | ); 1769 | var referenceConverter = new RegisteredPointer(name, registeredClass, true, false, false); 1770 | var pointerConverter = new RegisteredPointer(name + '*', registeredClass, false, false, false); 1771 | var constPointerConverter = new RegisteredPointer(name + ' const*', registeredClass, false, true, false); 1772 | registeredPointers[rawType] = { 1773 | pointerType: pointerConverter, 1774 | constPointerType: constPointerConverter, 1775 | }; 1776 | replacePublicSymbol(legalFunctionName, constructor); 1777 | return [referenceConverter, pointerConverter, constPointerConverter]; 1778 | } 1779 | ); 1780 | } 1781 | 1782 | function heap32VectorToArray(count, firstElement) { 1783 | var array = []; 1784 | for (var i = 0; i < count; i++) { 1785 | array.push(HEAP32[(firstElement >> 2) + i]); 1786 | } 1787 | return array; 1788 | } 1789 | 1790 | function __embind_register_class_constructor( 1791 | rawClassType, 1792 | argCount, 1793 | rawArgTypesAddr, 1794 | invokerSignature, 1795 | invoker, 1796 | rawConstructor 1797 | ) { 1798 | assert(argCount > 0); 1799 | var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr); 1800 | invoker = embind__requireFunction(invokerSignature, invoker); 1801 | whenDependentTypesAreResolved([], [rawClassType], function (classType) { 1802 | classType = classType[0]; 1803 | var humanName = 'constructor ' + classType.name; 1804 | if (undefined === classType.registeredClass.constructor_body) { 1805 | classType.registeredClass.constructor_body = []; 1806 | } 1807 | if (undefined !== classType.registeredClass.constructor_body[argCount - 1]) { 1808 | throw new BindingError( 1809 | 'Cannot register multiple constructors with identical number of parameters (' + 1810 | (argCount - 1) + 1811 | ") for class '" + 1812 | classType.name + 1813 | "'! Overload resolution is currently only performed using the parameter count, not actual type info!" 1814 | ); 1815 | } 1816 | classType.registeredClass.constructor_body[argCount - 1] = () => { 1817 | throwUnboundTypeError('Cannot construct ' + classType.name + ' due to unbound types', rawArgTypes); 1818 | }; 1819 | whenDependentTypesAreResolved([], rawArgTypes, function (argTypes) { 1820 | argTypes.splice(1, 0, null); 1821 | classType.registeredClass.constructor_body[argCount - 1] = craftInvokerFunction( 1822 | humanName, 1823 | argTypes, 1824 | null, 1825 | invoker, 1826 | rawConstructor 1827 | ); 1828 | return []; 1829 | }); 1830 | return []; 1831 | }); 1832 | } 1833 | 1834 | function craftInvokerFunction(humanName, argTypes, classType, cppInvokerFunc, cppTargetFunc) { 1835 | var argCount = argTypes.length; 1836 | if (argCount < 2) { 1837 | throwBindingError("argTypes array size mismatch! Must at least get return value and 'this' types!"); 1838 | } 1839 | var isClassMethodFunc = argTypes[1] !== null && classType !== null; 1840 | var needsDestructorStack = false; 1841 | for (var i = 1; i < argTypes.length; ++i) { 1842 | if (argTypes[i] !== null && argTypes[i].destructorFunction === undefined) { 1843 | needsDestructorStack = true; 1844 | break; 1845 | } 1846 | } 1847 | var returns = argTypes[0].name !== 'void'; 1848 | var expectedArgCount = argCount - 2; 1849 | var argsWired = new Array(expectedArgCount); 1850 | var invokerFuncArgs = []; 1851 | var destructors = []; 1852 | return function () { 1853 | if (arguments.length !== expectedArgCount) { 1854 | throwBindingError( 1855 | 'function ' + 1856 | humanName + 1857 | ' called with ' + 1858 | arguments.length + 1859 | ' arguments, expected ' + 1860 | expectedArgCount + 1861 | ' args!' 1862 | ); 1863 | } 1864 | destructors.length = 0; 1865 | var thisWired; 1866 | invokerFuncArgs.length = isClassMethodFunc ? 2 : 1; 1867 | invokerFuncArgs[0] = cppTargetFunc; 1868 | if (isClassMethodFunc) { 1869 | thisWired = argTypes[1]['toWireType'](destructors, this); 1870 | invokerFuncArgs[1] = thisWired; 1871 | } 1872 | for (var i = 0; i < expectedArgCount; ++i) { 1873 | argsWired[i] = argTypes[i + 2]['toWireType'](destructors, arguments[i]); 1874 | invokerFuncArgs.push(argsWired[i]); 1875 | } 1876 | var rv = cppInvokerFunc.apply(null, invokerFuncArgs); 1877 | function onDone(rv) { 1878 | if (needsDestructorStack) { 1879 | runDestructors(destructors); 1880 | } else { 1881 | for (var i = isClassMethodFunc ? 1 : 2; i < argTypes.length; i++) { 1882 | var param = i === 1 ? thisWired : argsWired[i - 2]; 1883 | if (argTypes[i].destructorFunction !== null) { 1884 | argTypes[i].destructorFunction(param); 1885 | } 1886 | } 1887 | } 1888 | if (returns) { 1889 | return argTypes[0]['fromWireType'](rv); 1890 | } 1891 | } 1892 | return onDone(rv); 1893 | }; 1894 | } 1895 | 1896 | function __embind_register_class_function( 1897 | rawClassType, 1898 | methodName, 1899 | argCount, 1900 | rawArgTypesAddr, 1901 | invokerSignature, 1902 | rawInvoker, 1903 | context, 1904 | isPureVirtual 1905 | ) { 1906 | var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr); 1907 | methodName = readLatin1String(methodName); 1908 | rawInvoker = embind__requireFunction(invokerSignature, rawInvoker); 1909 | whenDependentTypesAreResolved([], [rawClassType], function (classType) { 1910 | classType = classType[0]; 1911 | var humanName = classType.name + '.' + methodName; 1912 | if (methodName.startsWith('@@')) { 1913 | methodName = Symbol[methodName.substring(2)]; 1914 | } 1915 | if (isPureVirtual) { 1916 | classType.registeredClass.pureVirtualFunctions.push(methodName); 1917 | } 1918 | function unboundTypesHandler() { 1919 | throwUnboundTypeError('Cannot call ' + humanName + ' due to unbound types', rawArgTypes); 1920 | } 1921 | var proto = classType.registeredClass.instancePrototype; 1922 | var method = proto[methodName]; 1923 | if ( 1924 | undefined === method || 1925 | (undefined === method.overloadTable && method.className !== classType.name && method.argCount === argCount - 2) 1926 | ) { 1927 | unboundTypesHandler.argCount = argCount - 2; 1928 | unboundTypesHandler.className = classType.name; 1929 | proto[methodName] = unboundTypesHandler; 1930 | } else { 1931 | ensureOverloadTable(proto, methodName, humanName); 1932 | proto[methodName].overloadTable[argCount - 2] = unboundTypesHandler; 1933 | } 1934 | whenDependentTypesAreResolved([], rawArgTypes, function (argTypes) { 1935 | var memberFunction = craftInvokerFunction(humanName, argTypes, classType, rawInvoker, context); 1936 | if (undefined === proto[methodName].overloadTable) { 1937 | memberFunction.argCount = argCount - 2; 1938 | proto[methodName] = memberFunction; 1939 | } else { 1940 | proto[methodName].overloadTable[argCount - 2] = memberFunction; 1941 | } 1942 | return []; 1943 | }); 1944 | return []; 1945 | }); 1946 | } 1947 | 1948 | var emval_free_list = []; 1949 | 1950 | var emval_handle_array = [ 1951 | {}, 1952 | { 1953 | value: undefined, 1954 | }, 1955 | { 1956 | value: null, 1957 | }, 1958 | { 1959 | value: true, 1960 | }, 1961 | { 1962 | value: false, 1963 | }, 1964 | ]; 1965 | 1966 | function __emval_decref(handle) { 1967 | if (handle > 4 && 0 === --emval_handle_array[handle].refcount) { 1968 | emval_handle_array[handle] = undefined; 1969 | emval_free_list.push(handle); 1970 | } 1971 | } 1972 | 1973 | function count_emval_handles() { 1974 | var count = 0; 1975 | for (var i = 5; i < emval_handle_array.length; ++i) { 1976 | if (emval_handle_array[i] !== undefined) { 1977 | ++count; 1978 | } 1979 | } 1980 | return count; 1981 | } 1982 | 1983 | function get_first_emval() { 1984 | for (var i = 5; i < emval_handle_array.length; ++i) { 1985 | if (emval_handle_array[i] !== undefined) { 1986 | return emval_handle_array[i]; 1987 | } 1988 | } 1989 | return null; 1990 | } 1991 | 1992 | function init_emval() { 1993 | Module['count_emval_handles'] = count_emval_handles; 1994 | Module['get_first_emval'] = get_first_emval; 1995 | } 1996 | 1997 | var Emval = { 1998 | toValue: handle => { 1999 | if (!handle) { 2000 | throwBindingError('Cannot use deleted val. handle = ' + handle); 2001 | } 2002 | return emval_handle_array[handle].value; 2003 | }, 2004 | toHandle: value => { 2005 | switch (value) { 2006 | case undefined: 2007 | return 1; 2008 | 2009 | case null: 2010 | return 2; 2011 | 2012 | case true: 2013 | return 3; 2014 | 2015 | case false: 2016 | return 4; 2017 | 2018 | default: { 2019 | var handle = emval_free_list.length ? emval_free_list.pop() : emval_handle_array.length; 2020 | emval_handle_array[handle] = { 2021 | refcount: 1, 2022 | value: value, 2023 | }; 2024 | return handle; 2025 | } 2026 | } 2027 | }, 2028 | }; 2029 | 2030 | function __embind_register_emval(rawType, name) { 2031 | name = readLatin1String(name); 2032 | registerType(rawType, { 2033 | name: name, 2034 | fromWireType: function (handle) { 2035 | var rv = Emval.toValue(handle); 2036 | __emval_decref(handle); 2037 | return rv; 2038 | }, 2039 | toWireType: function (destructors, value) { 2040 | return Emval.toHandle(value); 2041 | }, 2042 | argPackAdvance: 8, 2043 | readValueFromPointer: simpleReadValueFromPointer, 2044 | destructorFunction: null, 2045 | }); 2046 | } 2047 | 2048 | function _embind_repr(v) { 2049 | if (v === null) { 2050 | return 'null'; 2051 | } 2052 | var t = typeof v; 2053 | if (t === 'object' || t === 'array' || t === 'function') { 2054 | return v.toString(); 2055 | } else { 2056 | return '' + v; 2057 | } 2058 | } 2059 | 2060 | function floatReadValueFromPointer(name, shift) { 2061 | switch (shift) { 2062 | case 2: 2063 | return function (pointer) { 2064 | return this['fromWireType'](HEAPF32[pointer >> 2]); 2065 | }; 2066 | 2067 | case 3: 2068 | return function (pointer) { 2069 | return this['fromWireType'](HEAPF64[pointer >> 3]); 2070 | }; 2071 | 2072 | default: 2073 | throw new TypeError('Unknown float type: ' + name); 2074 | } 2075 | } 2076 | 2077 | function __embind_register_float(rawType, name, size) { 2078 | var shift = getShiftFromSize(size); 2079 | name = readLatin1String(name); 2080 | registerType(rawType, { 2081 | name: name, 2082 | fromWireType: function (value) { 2083 | return value; 2084 | }, 2085 | toWireType: function (destructors, value) { 2086 | return value; 2087 | }, 2088 | argPackAdvance: 8, 2089 | readValueFromPointer: floatReadValueFromPointer(name, shift), 2090 | destructorFunction: null, 2091 | }); 2092 | } 2093 | 2094 | function integerReadValueFromPointer(name, shift, signed) { 2095 | switch (shift) { 2096 | case 0: 2097 | return signed 2098 | ? function readS8FromPointer(pointer) { 2099 | return HEAP8[pointer]; 2100 | } 2101 | : function readU8FromPointer(pointer) { 2102 | return HEAPU8[pointer]; 2103 | }; 2104 | 2105 | case 1: 2106 | return signed 2107 | ? function readS16FromPointer(pointer) { 2108 | return HEAP16[pointer >> 1]; 2109 | } 2110 | : function readU16FromPointer(pointer) { 2111 | return HEAPU16[pointer >> 1]; 2112 | }; 2113 | 2114 | case 2: 2115 | return signed 2116 | ? function readS32FromPointer(pointer) { 2117 | return HEAP32[pointer >> 2]; 2118 | } 2119 | : function readU32FromPointer(pointer) { 2120 | return HEAPU32[pointer >> 2]; 2121 | }; 2122 | 2123 | default: 2124 | throw new TypeError('Unknown integer type: ' + name); 2125 | } 2126 | } 2127 | 2128 | function __embind_register_integer(primitiveType, name, size, minRange, maxRange) { 2129 | name = readLatin1String(name); 2130 | if (maxRange === -1) { 2131 | maxRange = 4294967295; 2132 | } 2133 | var shift = getShiftFromSize(size); 2134 | var fromWireType = value => value; 2135 | if (minRange === 0) { 2136 | var bitshift = 32 - 8 * size; 2137 | fromWireType = value => (value << bitshift) >>> bitshift; 2138 | } 2139 | var isUnsignedType = name.includes('unsigned'); 2140 | var checkAssertions = (value, toTypeName) => {}; 2141 | var toWireType; 2142 | if (isUnsignedType) { 2143 | toWireType = function (destructors, value) { 2144 | checkAssertions(value, this.name); 2145 | return value >>> 0; 2146 | }; 2147 | } else { 2148 | toWireType = function (destructors, value) { 2149 | checkAssertions(value, this.name); 2150 | return value; 2151 | }; 2152 | } 2153 | registerType(primitiveType, { 2154 | name: name, 2155 | fromWireType: fromWireType, 2156 | toWireType: toWireType, 2157 | argPackAdvance: 8, 2158 | readValueFromPointer: integerReadValueFromPointer(name, shift, minRange !== 0), 2159 | destructorFunction: null, 2160 | }); 2161 | } 2162 | 2163 | function __embind_register_memory_view(rawType, dataTypeIndex, name) { 2164 | var typeMapping = [ 2165 | Int8Array, 2166 | Uint8Array, 2167 | Int16Array, 2168 | Uint16Array, 2169 | Int32Array, 2170 | Uint32Array, 2171 | Float32Array, 2172 | Float64Array, 2173 | ]; 2174 | var TA = typeMapping[dataTypeIndex]; 2175 | function decodeMemoryView(handle) { 2176 | handle = handle >> 2; 2177 | var heap = HEAPU32; 2178 | var size = heap[handle]; 2179 | var data = heap[handle + 1]; 2180 | return new TA(buffer, data, size); 2181 | } 2182 | name = readLatin1String(name); 2183 | registerType( 2184 | rawType, 2185 | { 2186 | name: name, 2187 | fromWireType: decodeMemoryView, 2188 | argPackAdvance: 8, 2189 | readValueFromPointer: decodeMemoryView, 2190 | }, 2191 | { 2192 | ignoreDuplicateRegistrations: true, 2193 | } 2194 | ); 2195 | } 2196 | 2197 | function __embind_register_smart_ptr( 2198 | rawType, 2199 | rawPointeeType, 2200 | name, 2201 | sharingPolicy, 2202 | getPointeeSignature, 2203 | rawGetPointee, 2204 | constructorSignature, 2205 | rawConstructor, 2206 | shareSignature, 2207 | rawShare, 2208 | destructorSignature, 2209 | rawDestructor 2210 | ) { 2211 | name = readLatin1String(name); 2212 | rawGetPointee = embind__requireFunction(getPointeeSignature, rawGetPointee); 2213 | rawConstructor = embind__requireFunction(constructorSignature, rawConstructor); 2214 | rawShare = embind__requireFunction(shareSignature, rawShare); 2215 | rawDestructor = embind__requireFunction(destructorSignature, rawDestructor); 2216 | whenDependentTypesAreResolved([rawType], [rawPointeeType], function (pointeeType) { 2217 | pointeeType = pointeeType[0]; 2218 | var registeredPointer = new RegisteredPointer( 2219 | name, 2220 | pointeeType.registeredClass, 2221 | false, 2222 | false, 2223 | true, 2224 | pointeeType, 2225 | sharingPolicy, 2226 | rawGetPointee, 2227 | rawConstructor, 2228 | rawShare, 2229 | rawDestructor 2230 | ); 2231 | return [registeredPointer]; 2232 | }); 2233 | } 2234 | 2235 | function __embind_register_std_string(rawType, name) { 2236 | name = readLatin1String(name); 2237 | var stdStringIsUTF8 = name === 'std::string'; 2238 | registerType(rawType, { 2239 | name: name, 2240 | fromWireType: function (value) { 2241 | var length = HEAPU32[value >> 2]; 2242 | var str; 2243 | if (stdStringIsUTF8) { 2244 | var decodeStartPtr = value + 4; 2245 | for (var i = 0; i <= length; ++i) { 2246 | var currentBytePtr = value + 4 + i; 2247 | if (i == length || HEAPU8[currentBytePtr] == 0) { 2248 | var maxRead = currentBytePtr - decodeStartPtr; 2249 | var stringSegment = UTF8ToString(decodeStartPtr, maxRead); 2250 | if (str === undefined) { 2251 | str = stringSegment; 2252 | } else { 2253 | str += String.fromCharCode(0); 2254 | str += stringSegment; 2255 | } 2256 | decodeStartPtr = currentBytePtr + 1; 2257 | } 2258 | } 2259 | } else { 2260 | var a = new Array(length); 2261 | for (var i = 0; i < length; ++i) { 2262 | a[i] = String.fromCharCode(HEAPU8[value + 4 + i]); 2263 | } 2264 | str = a.join(''); 2265 | } 2266 | _free(value); 2267 | return str; 2268 | }, 2269 | toWireType: function (destructors, value) { 2270 | if (value instanceof ArrayBuffer) { 2271 | value = new Uint8Array(value); 2272 | } 2273 | var getLength; 2274 | var valueIsOfTypeString = typeof value == 'string'; 2275 | if ( 2276 | !( 2277 | valueIsOfTypeString || 2278 | value instanceof Uint8Array || 2279 | value instanceof Uint8ClampedArray || 2280 | value instanceof Int8Array 2281 | ) 2282 | ) { 2283 | throwBindingError('Cannot pass non-string to std::string'); 2284 | } 2285 | if (stdStringIsUTF8 && valueIsOfTypeString) { 2286 | getLength = () => lengthBytesUTF8(value); 2287 | } else { 2288 | getLength = () => value.length; 2289 | } 2290 | var length = getLength(); 2291 | var ptr = _malloc(4 + length + 1); 2292 | HEAPU32[ptr >> 2] = length; 2293 | if (stdStringIsUTF8 && valueIsOfTypeString) { 2294 | stringToUTF8(value, ptr + 4, length + 1); 2295 | } else { 2296 | if (valueIsOfTypeString) { 2297 | for (var i = 0; i < length; ++i) { 2298 | var charCode = value.charCodeAt(i); 2299 | if (charCode > 255) { 2300 | _free(ptr); 2301 | throwBindingError('String has UTF-16 code units that do not fit in 8 bits'); 2302 | } 2303 | HEAPU8[ptr + 4 + i] = charCode; 2304 | } 2305 | } else { 2306 | for (var i = 0; i < length; ++i) { 2307 | HEAPU8[ptr + 4 + i] = value[i]; 2308 | } 2309 | } 2310 | } 2311 | if (destructors !== null) { 2312 | destructors.push(_free, ptr); 2313 | } 2314 | return ptr; 2315 | }, 2316 | argPackAdvance: 8, 2317 | readValueFromPointer: simpleReadValueFromPointer, 2318 | destructorFunction: function (ptr) { 2319 | _free(ptr); 2320 | }, 2321 | }); 2322 | } 2323 | 2324 | function __embind_register_std_wstring(rawType, charSize, name) { 2325 | name = readLatin1String(name); 2326 | var decodeString, encodeString, getHeap, lengthBytesUTF, shift; 2327 | if (charSize === 2) { 2328 | decodeString = UTF16ToString; 2329 | encodeString = stringToUTF16; 2330 | lengthBytesUTF = lengthBytesUTF16; 2331 | getHeap = () => HEAPU16; 2332 | shift = 1; 2333 | } else if (charSize === 4) { 2334 | decodeString = UTF32ToString; 2335 | encodeString = stringToUTF32; 2336 | lengthBytesUTF = lengthBytesUTF32; 2337 | getHeap = () => HEAPU32; 2338 | shift = 2; 2339 | } 2340 | registerType(rawType, { 2341 | name: name, 2342 | fromWireType: function (value) { 2343 | var length = HEAPU32[value >> 2]; 2344 | var HEAP = getHeap(); 2345 | var str; 2346 | var decodeStartPtr = value + 4; 2347 | for (var i = 0; i <= length; ++i) { 2348 | var currentBytePtr = value + 4 + i * charSize; 2349 | if (i == length || HEAP[currentBytePtr >> shift] == 0) { 2350 | var maxReadBytes = currentBytePtr - decodeStartPtr; 2351 | var stringSegment = decodeString(decodeStartPtr, maxReadBytes); 2352 | if (str === undefined) { 2353 | str = stringSegment; 2354 | } else { 2355 | str += String.fromCharCode(0); 2356 | str += stringSegment; 2357 | } 2358 | decodeStartPtr = currentBytePtr + charSize; 2359 | } 2360 | } 2361 | _free(value); 2362 | return str; 2363 | }, 2364 | toWireType: function (destructors, value) { 2365 | if (!(typeof value == 'string')) { 2366 | throwBindingError('Cannot pass non-string to C++ string type ' + name); 2367 | } 2368 | var length = lengthBytesUTF(value); 2369 | var ptr = _malloc(4 + length + charSize); 2370 | HEAPU32[ptr >> 2] = length >> shift; 2371 | encodeString(value, ptr + 4, length + charSize); 2372 | if (destructors !== null) { 2373 | destructors.push(_free, ptr); 2374 | } 2375 | return ptr; 2376 | }, 2377 | argPackAdvance: 8, 2378 | readValueFromPointer: simpleReadValueFromPointer, 2379 | destructorFunction: function (ptr) { 2380 | _free(ptr); 2381 | }, 2382 | }); 2383 | } 2384 | 2385 | function __embind_register_value_object( 2386 | rawType, 2387 | name, 2388 | constructorSignature, 2389 | rawConstructor, 2390 | destructorSignature, 2391 | rawDestructor 2392 | ) { 2393 | structRegistrations[rawType] = { 2394 | name: readLatin1String(name), 2395 | rawConstructor: embind__requireFunction(constructorSignature, rawConstructor), 2396 | rawDestructor: embind__requireFunction(destructorSignature, rawDestructor), 2397 | fields: [], 2398 | }; 2399 | } 2400 | 2401 | function __embind_register_value_object_field( 2402 | structType, 2403 | fieldName, 2404 | getterReturnType, 2405 | getterSignature, 2406 | getter, 2407 | getterContext, 2408 | setterArgumentType, 2409 | setterSignature, 2410 | setter, 2411 | setterContext 2412 | ) { 2413 | structRegistrations[structType].fields.push({ 2414 | fieldName: readLatin1String(fieldName), 2415 | getterReturnType: getterReturnType, 2416 | getter: embind__requireFunction(getterSignature, getter), 2417 | getterContext: getterContext, 2418 | setterArgumentType: setterArgumentType, 2419 | setter: embind__requireFunction(setterSignature, setter), 2420 | setterContext: setterContext, 2421 | }); 2422 | } 2423 | 2424 | function __embind_register_void(rawType, name) { 2425 | name = readLatin1String(name); 2426 | registerType(rawType, { 2427 | isVoid: true, 2428 | name: name, 2429 | argPackAdvance: 0, 2430 | fromWireType: function () { 2431 | return undefined; 2432 | }, 2433 | toWireType: function (destructors, o) { 2434 | return undefined; 2435 | }, 2436 | }); 2437 | } 2438 | 2439 | function __emscripten_date_now() { 2440 | return Date.now(); 2441 | } 2442 | 2443 | var nowIsMonotonic = true; 2444 | 2445 | function __emscripten_get_now_is_monotonic() { 2446 | return nowIsMonotonic; 2447 | } 2448 | 2449 | function requireRegisteredType(rawType, humanName) { 2450 | var impl = registeredTypes[rawType]; 2451 | if (undefined === impl) { 2452 | throwBindingError(humanName + ' has unknown type ' + getTypeName(rawType)); 2453 | } 2454 | return impl; 2455 | } 2456 | 2457 | function __emval_lookupTypes(argCount, argTypes) { 2458 | var a = new Array(argCount); 2459 | for (var i = 0; i < argCount; ++i) { 2460 | a[i] = requireRegisteredType(HEAP32[(argTypes >> 2) + i], 'parameter ' + i); 2461 | } 2462 | return a; 2463 | } 2464 | 2465 | function __emval_call(handle, argCount, argTypes, argv) { 2466 | handle = Emval.toValue(handle); 2467 | var types = __emval_lookupTypes(argCount, argTypes); 2468 | var args = new Array(argCount); 2469 | for (var i = 0; i < argCount; ++i) { 2470 | var type = types[i]; 2471 | args[i] = type['readValueFromPointer'](argv); 2472 | argv += type['argPackAdvance']; 2473 | } 2474 | var rv = handle.apply(undefined, args); 2475 | return Emval.toHandle(rv); 2476 | } 2477 | 2478 | function __emval_incref(handle) { 2479 | if (handle > 4) { 2480 | emval_handle_array[handle].refcount += 1; 2481 | } 2482 | } 2483 | 2484 | function __emval_take_value(type, argv) { 2485 | type = requireRegisteredType(type, '_emval_take_value'); 2486 | var v = type['readValueFromPointer'](argv); 2487 | return Emval.toHandle(v); 2488 | } 2489 | 2490 | function __localtime_js(time, tmPtr) { 2491 | var date = new Date(HEAP32[time >> 2] * 1e3); 2492 | HEAP32[tmPtr >> 2] = date.getSeconds(); 2493 | HEAP32[(tmPtr + 4) >> 2] = date.getMinutes(); 2494 | HEAP32[(tmPtr + 8) >> 2] = date.getHours(); 2495 | HEAP32[(tmPtr + 12) >> 2] = date.getDate(); 2496 | HEAP32[(tmPtr + 16) >> 2] = date.getMonth(); 2497 | HEAP32[(tmPtr + 20) >> 2] = date.getFullYear() - 1900; 2498 | HEAP32[(tmPtr + 24) >> 2] = date.getDay(); 2499 | var start = new Date(date.getFullYear(), 0, 1); 2500 | var yday = ((date.getTime() - start.getTime()) / (1e3 * 60 * 60 * 24)) | 0; 2501 | HEAP32[(tmPtr + 28) >> 2] = yday; 2502 | HEAP32[(tmPtr + 36) >> 2] = -(date.getTimezoneOffset() * 60); 2503 | var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset(); 2504 | var winterOffset = start.getTimezoneOffset(); 2505 | var dst = (summerOffset != winterOffset && date.getTimezoneOffset() == Math.min(winterOffset, summerOffset)) | 0; 2506 | HEAP32[(tmPtr + 32) >> 2] = dst; 2507 | } 2508 | 2509 | function __mmap_js(addr, len, prot, flags, fd, off, allocated, builtin) { 2510 | return -52; 2511 | } 2512 | 2513 | function __munmap_js(addr, len, prot, flags, fd, offset) {} 2514 | 2515 | function _tzset_impl(timezone, daylight, tzname) { 2516 | var currentYear = new Date().getFullYear(); 2517 | var winter = new Date(currentYear, 0, 1); 2518 | var summer = new Date(currentYear, 6, 1); 2519 | var winterOffset = winter.getTimezoneOffset(); 2520 | var summerOffset = summer.getTimezoneOffset(); 2521 | var stdTimezoneOffset = Math.max(winterOffset, summerOffset); 2522 | HEAP32[timezone >> 2] = stdTimezoneOffset * 60; 2523 | HEAP32[daylight >> 2] = Number(winterOffset != summerOffset); 2524 | function extractZone(date) { 2525 | var match = date.toTimeString().match(/\(([A-Za-z ]+)\)$/); 2526 | return match ? match[1] : 'GMT'; 2527 | } 2528 | var winterName = extractZone(winter); 2529 | var summerName = extractZone(summer); 2530 | var winterNamePtr = allocateUTF8(winterName); 2531 | var summerNamePtr = allocateUTF8(summerName); 2532 | if (summerOffset < winterOffset) { 2533 | HEAP32[tzname >> 2] = winterNamePtr; 2534 | HEAP32[(tzname + 4) >> 2] = summerNamePtr; 2535 | } else { 2536 | HEAP32[tzname >> 2] = summerNamePtr; 2537 | HEAP32[(tzname + 4) >> 2] = winterNamePtr; 2538 | } 2539 | } 2540 | 2541 | function __tzset_js(timezone, daylight, tzname) { 2542 | if (__tzset_js.called) return; 2543 | __tzset_js.called = true; 2544 | _tzset_impl(timezone, daylight, tzname); 2545 | } 2546 | 2547 | function _abort() { 2548 | abort(''); 2549 | } 2550 | 2551 | function _emscripten_get_heap_max() { 2552 | return 2147483648; 2553 | } 2554 | 2555 | var _emscripten_get_now; 2556 | 2557 | _emscripten_get_now = () => performance.now(); 2558 | 2559 | function _emscripten_memcpy_big(dest, src, num) { 2560 | HEAPU8.copyWithin(dest, src, src + num); 2561 | } 2562 | 2563 | function emscripten_realloc_buffer(size) { 2564 | try { 2565 | wasmMemory.grow((size - buffer.byteLength + 65535) >>> 16); 2566 | updateGlobalBufferAndViews(wasmMemory.buffer); 2567 | return 1; 2568 | } catch (e) {} 2569 | } 2570 | 2571 | function _emscripten_resize_heap(requestedSize) { 2572 | var oldSize = HEAPU8.length; 2573 | requestedSize = requestedSize >>> 0; 2574 | var maxHeapSize = _emscripten_get_heap_max(); 2575 | if (requestedSize > maxHeapSize) { 2576 | return false; 2577 | } 2578 | let alignUp = (x, multiple) => x + ((multiple - (x % multiple)) % multiple); 2579 | for (var cutDown = 1; cutDown <= 4; cutDown *= 2) { 2580 | var overGrownHeapSize = oldSize * (1 + 0.2 / cutDown); 2581 | overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296); 2582 | var newSize = Math.min(maxHeapSize, alignUp(Math.max(requestedSize, overGrownHeapSize), 65536)); 2583 | var replacement = emscripten_realloc_buffer(newSize); 2584 | if (replacement) { 2585 | return true; 2586 | } 2587 | } 2588 | return false; 2589 | } 2590 | 2591 | var ENV = {}; 2592 | 2593 | function getExecutableName() { 2594 | return thisProgram || './this.program'; 2595 | } 2596 | 2597 | function getEnvStrings() { 2598 | if (!getEnvStrings.strings) { 2599 | var lang = 2600 | ((typeof navigator == 'object' && navigator.languages && navigator.languages[0]) || 'C').replace('-', '_') + 2601 | '.UTF-8'; 2602 | var env = { 2603 | USER: 'web_user', 2604 | LOGNAME: 'web_user', 2605 | PATH: '/', 2606 | PWD: '/', 2607 | HOME: '/home/web_user', 2608 | LANG: lang, 2609 | _: getExecutableName(), 2610 | }; 2611 | for (var x in ENV) { 2612 | if (ENV[x] === undefined) delete env[x]; 2613 | else env[x] = ENV[x]; 2614 | } 2615 | var strings = []; 2616 | for (var x in env) { 2617 | strings.push(x + '=' + env[x]); 2618 | } 2619 | getEnvStrings.strings = strings; 2620 | } 2621 | return getEnvStrings.strings; 2622 | } 2623 | 2624 | function _environ_get(__environ, environ_buf) { 2625 | var bufSize = 0; 2626 | getEnvStrings().forEach(function (string, i) { 2627 | var ptr = environ_buf + bufSize; 2628 | HEAP32[(__environ + i * 4) >> 2] = ptr; 2629 | writeAsciiToMemory(string, ptr); 2630 | bufSize += string.length + 1; 2631 | }); 2632 | return 0; 2633 | } 2634 | 2635 | function _environ_sizes_get(penviron_count, penviron_buf_size) { 2636 | var strings = getEnvStrings(); 2637 | HEAP32[penviron_count >> 2] = strings.length; 2638 | var bufSize = 0; 2639 | strings.forEach(function (string) { 2640 | bufSize += string.length + 1; 2641 | }); 2642 | HEAP32[penviron_buf_size >> 2] = bufSize; 2643 | return 0; 2644 | } 2645 | 2646 | function _exit(status) { 2647 | exit(status); 2648 | } 2649 | 2650 | function _fd_close(fd) { 2651 | return 0; 2652 | } 2653 | 2654 | function _fd_read(fd, iov, iovcnt, pnum) { 2655 | var stream = SYSCALLS.getStreamFromFD(fd); 2656 | var num = SYSCALLS.doReadv(stream, iov, iovcnt); 2657 | HEAP32[pnum >> 2] = num; 2658 | return 0; 2659 | } 2660 | 2661 | function _fd_seek(fd, offset_low, offset_high, whence, newOffset) {} 2662 | 2663 | function _fd_write(fd, iov, iovcnt, pnum) { 2664 | var num = 0; 2665 | for (var i = 0; i < iovcnt; i++) { 2666 | var ptr = HEAP32[iov >> 2]; 2667 | var len = HEAP32[(iov + 4) >> 2]; 2668 | iov += 8; 2669 | for (var j = 0; j < len; j++) { 2670 | SYSCALLS.printChar(fd, HEAPU8[ptr + j]); 2671 | } 2672 | num += len; 2673 | } 2674 | HEAP32[pnum >> 2] = num; 2675 | return 0; 2676 | } 2677 | 2678 | function getRandomDevice() { 2679 | if (typeof crypto == 'object' && typeof crypto['getRandomValues'] == 'function') { 2680 | var randomBuffer = new Uint8Array(1); 2681 | return function () { 2682 | crypto.getRandomValues(randomBuffer); 2683 | return randomBuffer[0]; 2684 | }; 2685 | } else 2686 | return function () { 2687 | abort('randomDevice'); 2688 | }; 2689 | } 2690 | 2691 | function _getentropy(buffer, size) { 2692 | if (!_getentropy.randomDevice) { 2693 | _getentropy.randomDevice = getRandomDevice(); 2694 | } 2695 | for (var i = 0; i < size; i++) { 2696 | HEAP8[(buffer + i) >> 0] = _getentropy.randomDevice(); 2697 | } 2698 | return 0; 2699 | } 2700 | 2701 | function _pclose() { 2702 | err('missing function: pclose'); 2703 | abort(-1); 2704 | } 2705 | 2706 | function _setTempRet0(val) { 2707 | setTempRet0(val); 2708 | } 2709 | 2710 | function __isLeapYear(year) { 2711 | return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0); 2712 | } 2713 | 2714 | function __arraySum(array, index) { 2715 | var sum = 0; 2716 | for (var i = 0; i <= index; sum += array[i++]) {} 2717 | return sum; 2718 | } 2719 | 2720 | var __MONTH_DAYS_LEAP = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; 2721 | 2722 | var __MONTH_DAYS_REGULAR = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; 2723 | 2724 | function __addDays(date, days) { 2725 | var newDate = new Date(date.getTime()); 2726 | while (days > 0) { 2727 | var leap = __isLeapYear(newDate.getFullYear()); 2728 | var currentMonth = newDate.getMonth(); 2729 | var daysInCurrentMonth = (leap ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR)[currentMonth]; 2730 | if (days > daysInCurrentMonth - newDate.getDate()) { 2731 | days -= daysInCurrentMonth - newDate.getDate() + 1; 2732 | newDate.setDate(1); 2733 | if (currentMonth < 11) { 2734 | newDate.setMonth(currentMonth + 1); 2735 | } else { 2736 | newDate.setMonth(0); 2737 | newDate.setFullYear(newDate.getFullYear() + 1); 2738 | } 2739 | } else { 2740 | newDate.setDate(newDate.getDate() + days); 2741 | return newDate; 2742 | } 2743 | } 2744 | return newDate; 2745 | } 2746 | 2747 | function _strftime(s, maxsize, format, tm) { 2748 | var tm_zone = HEAP32[(tm + 40) >> 2]; 2749 | var date = { 2750 | tm_sec: HEAP32[tm >> 2], 2751 | tm_min: HEAP32[(tm + 4) >> 2], 2752 | tm_hour: HEAP32[(tm + 8) >> 2], 2753 | tm_mday: HEAP32[(tm + 12) >> 2], 2754 | tm_mon: HEAP32[(tm + 16) >> 2], 2755 | tm_year: HEAP32[(tm + 20) >> 2], 2756 | tm_wday: HEAP32[(tm + 24) >> 2], 2757 | tm_yday: HEAP32[(tm + 28) >> 2], 2758 | tm_isdst: HEAP32[(tm + 32) >> 2], 2759 | tm_gmtoff: HEAP32[(tm + 36) >> 2], 2760 | tm_zone: tm_zone ? UTF8ToString(tm_zone) : '', 2761 | }; 2762 | var pattern = UTF8ToString(format); 2763 | var EXPANSION_RULES_1 = { 2764 | '%c': '%a %b %d %H:%M:%S %Y', 2765 | '%D': '%m/%d/%y', 2766 | '%F': '%Y-%m-%d', 2767 | '%h': '%b', 2768 | '%r': '%I:%M:%S %p', 2769 | '%R': '%H:%M', 2770 | '%T': '%H:%M:%S', 2771 | '%x': '%m/%d/%y', 2772 | '%X': '%H:%M:%S', 2773 | '%Ec': '%c', 2774 | '%EC': '%C', 2775 | '%Ex': '%m/%d/%y', 2776 | '%EX': '%H:%M:%S', 2777 | '%Ey': '%y', 2778 | '%EY': '%Y', 2779 | '%Od': '%d', 2780 | '%Oe': '%e', 2781 | '%OH': '%H', 2782 | '%OI': '%I', 2783 | '%Om': '%m', 2784 | '%OM': '%M', 2785 | '%OS': '%S', 2786 | '%Ou': '%u', 2787 | '%OU': '%U', 2788 | '%OV': '%V', 2789 | '%Ow': '%w', 2790 | '%OW': '%W', 2791 | '%Oy': '%y', 2792 | }; 2793 | for (var rule in EXPANSION_RULES_1) { 2794 | pattern = pattern.replace(new RegExp(rule, 'g'), EXPANSION_RULES_1[rule]); 2795 | } 2796 | var WEEKDAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; 2797 | var MONTHS = [ 2798 | 'January', 2799 | 'February', 2800 | 'March', 2801 | 'April', 2802 | 'May', 2803 | 'June', 2804 | 'July', 2805 | 'August', 2806 | 'September', 2807 | 'October', 2808 | 'November', 2809 | 'December', 2810 | ]; 2811 | function leadingSomething(value, digits, character) { 2812 | var str = typeof value == 'number' ? value.toString() : value || ''; 2813 | while (str.length < digits) { 2814 | str = character[0] + str; 2815 | } 2816 | return str; 2817 | } 2818 | function leadingNulls(value, digits) { 2819 | return leadingSomething(value, digits, '0'); 2820 | } 2821 | function compareByDay(date1, date2) { 2822 | function sgn(value) { 2823 | return value < 0 ? -1 : value > 0 ? 1 : 0; 2824 | } 2825 | var compare; 2826 | if ((compare = sgn(date1.getFullYear() - date2.getFullYear())) === 0) { 2827 | if ((compare = sgn(date1.getMonth() - date2.getMonth())) === 0) { 2828 | compare = sgn(date1.getDate() - date2.getDate()); 2829 | } 2830 | } 2831 | return compare; 2832 | } 2833 | function getFirstWeekStartDate(janFourth) { 2834 | switch (janFourth.getDay()) { 2835 | case 0: 2836 | return new Date(janFourth.getFullYear() - 1, 11, 29); 2837 | 2838 | case 1: 2839 | return janFourth; 2840 | 2841 | case 2: 2842 | return new Date(janFourth.getFullYear(), 0, 3); 2843 | 2844 | case 3: 2845 | return new Date(janFourth.getFullYear(), 0, 2); 2846 | 2847 | case 4: 2848 | return new Date(janFourth.getFullYear(), 0, 1); 2849 | 2850 | case 5: 2851 | return new Date(janFourth.getFullYear() - 1, 11, 31); 2852 | 2853 | case 6: 2854 | return new Date(janFourth.getFullYear() - 1, 11, 30); 2855 | } 2856 | } 2857 | function getWeekBasedYear(date) { 2858 | var thisDate = __addDays(new Date(date.tm_year + 1900, 0, 1), date.tm_yday); 2859 | var janFourthThisYear = new Date(thisDate.getFullYear(), 0, 4); 2860 | var janFourthNextYear = new Date(thisDate.getFullYear() + 1, 0, 4); 2861 | var firstWeekStartThisYear = getFirstWeekStartDate(janFourthThisYear); 2862 | var firstWeekStartNextYear = getFirstWeekStartDate(janFourthNextYear); 2863 | if (compareByDay(firstWeekStartThisYear, thisDate) <= 0) { 2864 | if (compareByDay(firstWeekStartNextYear, thisDate) <= 0) { 2865 | return thisDate.getFullYear() + 1; 2866 | } else { 2867 | return thisDate.getFullYear(); 2868 | } 2869 | } else { 2870 | return thisDate.getFullYear() - 1; 2871 | } 2872 | } 2873 | var EXPANSION_RULES_2 = { 2874 | '%a': function (date) { 2875 | return WEEKDAYS[date.tm_wday].substring(0, 3); 2876 | }, 2877 | '%A': function (date) { 2878 | return WEEKDAYS[date.tm_wday]; 2879 | }, 2880 | '%b': function (date) { 2881 | return MONTHS[date.tm_mon].substring(0, 3); 2882 | }, 2883 | '%B': function (date) { 2884 | return MONTHS[date.tm_mon]; 2885 | }, 2886 | '%C': function (date) { 2887 | var year = date.tm_year + 1900; 2888 | return leadingNulls((year / 100) | 0, 2); 2889 | }, 2890 | '%d': function (date) { 2891 | return leadingNulls(date.tm_mday, 2); 2892 | }, 2893 | '%e': function (date) { 2894 | return leadingSomething(date.tm_mday, 2, ' '); 2895 | }, 2896 | '%g': function (date) { 2897 | return getWeekBasedYear(date).toString().substring(2); 2898 | }, 2899 | '%G': function (date) { 2900 | return getWeekBasedYear(date); 2901 | }, 2902 | '%H': function (date) { 2903 | return leadingNulls(date.tm_hour, 2); 2904 | }, 2905 | '%I': function (date) { 2906 | var twelveHour = date.tm_hour; 2907 | if (twelveHour == 0) twelveHour = 12; 2908 | else if (twelveHour > 12) twelveHour -= 12; 2909 | return leadingNulls(twelveHour, 2); 2910 | }, 2911 | '%j': function (date) { 2912 | return leadingNulls( 2913 | date.tm_mday + 2914 | __arraySum(__isLeapYear(date.tm_year + 1900) ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR, date.tm_mon - 1), 2915 | 3 2916 | ); 2917 | }, 2918 | '%m': function (date) { 2919 | return leadingNulls(date.tm_mon + 1, 2); 2920 | }, 2921 | '%M': function (date) { 2922 | return leadingNulls(date.tm_min, 2); 2923 | }, 2924 | '%n': function () { 2925 | return '\n'; 2926 | }, 2927 | '%p': function (date) { 2928 | if (date.tm_hour >= 0 && date.tm_hour < 12) { 2929 | return 'AM'; 2930 | } else { 2931 | return 'PM'; 2932 | } 2933 | }, 2934 | '%S': function (date) { 2935 | return leadingNulls(date.tm_sec, 2); 2936 | }, 2937 | '%t': function () { 2938 | return '\t'; 2939 | }, 2940 | '%u': function (date) { 2941 | return date.tm_wday || 7; 2942 | }, 2943 | '%U': function (date) { 2944 | var days = date.tm_yday + 7 - date.tm_wday; 2945 | return leadingNulls(Math.floor(days / 7), 2); 2946 | }, 2947 | '%V': function (date) { 2948 | var val = Math.floor((date.tm_yday + 7 - ((date.tm_wday + 6) % 7)) / 7); 2949 | if ((date.tm_wday + 371 - date.tm_yday - 2) % 7 <= 2) { 2950 | val++; 2951 | } 2952 | if (!val) { 2953 | val = 52; 2954 | var dec31 = (date.tm_wday + 7 - date.tm_yday - 1) % 7; 2955 | if (dec31 == 4 || (dec31 == 5 && __isLeapYear((date.tm_year % 400) - 1))) { 2956 | val++; 2957 | } 2958 | } else if (val == 53) { 2959 | var jan1 = (date.tm_wday + 371 - date.tm_yday) % 7; 2960 | if (jan1 != 4 && (jan1 != 3 || !__isLeapYear(date.tm_year))) val = 1; 2961 | } 2962 | return leadingNulls(val, 2); 2963 | }, 2964 | '%w': function (date) { 2965 | return date.tm_wday; 2966 | }, 2967 | '%W': function (date) { 2968 | var days = date.tm_yday + 7 - ((date.tm_wday + 6) % 7); 2969 | return leadingNulls(Math.floor(days / 7), 2); 2970 | }, 2971 | '%y': function (date) { 2972 | return (date.tm_year + 1900).toString().substring(2); 2973 | }, 2974 | '%Y': function (date) { 2975 | return date.tm_year + 1900; 2976 | }, 2977 | '%z': function (date) { 2978 | var off = date.tm_gmtoff; 2979 | var ahead = off >= 0; 2980 | off = Math.abs(off) / 60; 2981 | off = (off / 60) * 100 + (off % 60); 2982 | return (ahead ? '+' : '-') + String('0000' + off).slice(-4); 2983 | }, 2984 | '%Z': function (date) { 2985 | return date.tm_zone; 2986 | }, 2987 | '%%': function () { 2988 | return '%'; 2989 | }, 2990 | }; 2991 | pattern = pattern.replace(/%%/g, '\0\0'); 2992 | for (var rule in EXPANSION_RULES_2) { 2993 | if (pattern.includes(rule)) { 2994 | pattern = pattern.replace(new RegExp(rule, 'g'), EXPANSION_RULES_2[rule](date)); 2995 | } 2996 | } 2997 | pattern = pattern.replace(/\0\0/g, '%'); 2998 | var bytes = intArrayFromString(pattern, false); 2999 | if (bytes.length > maxsize) { 3000 | return 0; 3001 | } 3002 | writeArrayToMemory(bytes, s); 3003 | return bytes.length - 1; 3004 | } 3005 | 3006 | function _strftime_l(s, maxsize, format, tm) { 3007 | return _strftime(s, maxsize, format, tm); 3008 | } 3009 | 3010 | InternalError = Module['InternalError'] = extendError(Error, 'InternalError'); 3011 | 3012 | embind_init_charCodes(); 3013 | 3014 | BindingError = Module['BindingError'] = extendError(Error, 'BindingError'); 3015 | 3016 | init_ClassHandle(); 3017 | 3018 | init_embind(); 3019 | 3020 | init_RegisteredPointer(); 3021 | 3022 | UnboundTypeError = Module['UnboundTypeError'] = extendError(Error, 'UnboundTypeError'); 3023 | 3024 | init_emval(); 3025 | 3026 | function intArrayFromString(stringy, dontAddNull, length) { 3027 | var len = length > 0 ? length : lengthBytesUTF8(stringy) + 1; 3028 | var u8array = new Array(len); 3029 | var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length); 3030 | if (dontAddNull) u8array.length = numBytesWritten; 3031 | return u8array; 3032 | } 3033 | 3034 | var asmLibraryArg = { 3035 | __assert_fail: ___assert_fail, 3036 | __cxa_allocate_exception: ___cxa_allocate_exception, 3037 | __cxa_rethrow: ___cxa_rethrow, 3038 | __cxa_throw: ___cxa_throw, 3039 | __syscall_faccessat: ___syscall_faccessat, 3040 | __syscall_fcntl64: ___syscall_fcntl64, 3041 | __syscall_fstat64: ___syscall_fstat64, 3042 | __syscall_getcwd: ___syscall_getcwd, 3043 | __syscall_ioctl: ___syscall_ioctl, 3044 | __syscall_lstat64: ___syscall_lstat64, 3045 | __syscall_newfstatat: ___syscall_newfstatat, 3046 | __syscall_openat: ___syscall_openat, 3047 | __syscall_renameat: ___syscall_renameat, 3048 | __syscall_rmdir: ___syscall_rmdir, 3049 | __syscall_stat64: ___syscall_stat64, 3050 | __syscall_unlinkat: ___syscall_unlinkat, 3051 | _embind_finalize_value_object: __embind_finalize_value_object, 3052 | _embind_register_bigint: __embind_register_bigint, 3053 | _embind_register_bool: __embind_register_bool, 3054 | _embind_register_class: __embind_register_class, 3055 | _embind_register_class_constructor: __embind_register_class_constructor, 3056 | _embind_register_class_function: __embind_register_class_function, 3057 | _embind_register_emval: __embind_register_emval, 3058 | _embind_register_float: __embind_register_float, 3059 | _embind_register_integer: __embind_register_integer, 3060 | _embind_register_memory_view: __embind_register_memory_view, 3061 | _embind_register_smart_ptr: __embind_register_smart_ptr, 3062 | _embind_register_std_string: __embind_register_std_string, 3063 | _embind_register_std_wstring: __embind_register_std_wstring, 3064 | _embind_register_value_object: __embind_register_value_object, 3065 | _embind_register_value_object_field: __embind_register_value_object_field, 3066 | _embind_register_void: __embind_register_void, 3067 | _emscripten_date_now: __emscripten_date_now, 3068 | _emscripten_get_now_is_monotonic: __emscripten_get_now_is_monotonic, 3069 | _emval_call: __emval_call, 3070 | _emval_decref: __emval_decref, 3071 | _emval_incref: __emval_incref, 3072 | _emval_take_value: __emval_take_value, 3073 | _localtime_js: __localtime_js, 3074 | _mmap_js: __mmap_js, 3075 | _munmap_js: __munmap_js, 3076 | _tzset_js: __tzset_js, 3077 | abort: _abort, 3078 | emscripten_get_heap_max: _emscripten_get_heap_max, 3079 | emscripten_get_now: _emscripten_get_now, 3080 | emscripten_memcpy_big: _emscripten_memcpy_big, 3081 | emscripten_resize_heap: _emscripten_resize_heap, 3082 | environ_get: _environ_get, 3083 | environ_sizes_get: _environ_sizes_get, 3084 | exit: _exit, 3085 | fd_close: _fd_close, 3086 | fd_read: _fd_read, 3087 | fd_seek: _fd_seek, 3088 | fd_write: _fd_write, 3089 | getentropy: _getentropy, 3090 | memory: wasmMemory, 3091 | pclose: _pclose, 3092 | setTempRet0: _setTempRet0, 3093 | strftime_l: _strftime_l, 3094 | }; 3095 | 3096 | var asm = createWasm(); 3097 | 3098 | var calledRun; 3099 | 3100 | function ExitStatus(status) { 3101 | this.name = 'ExitStatus'; 3102 | this.message = 'Program terminated with exit(' + status + ')'; 3103 | this.status = status; 3104 | } 3105 | 3106 | dependenciesFulfilled = function runCaller() { 3107 | if (!calledRun) run(); 3108 | if (!calledRun) dependenciesFulfilled = runCaller; 3109 | }; 3110 | 3111 | function run(args) { 3112 | args = args || arguments_; 3113 | if (runDependencies > 0) { 3114 | return; 3115 | } 3116 | preRun(); 3117 | if (runDependencies > 0) { 3118 | return; 3119 | } 3120 | function doRun() { 3121 | if (calledRun) return; 3122 | calledRun = true; 3123 | Module['calledRun'] = true; 3124 | if (ABORT) return; 3125 | initRuntime(); 3126 | if (Module['onRuntimeInitialized']) Module['onRuntimeInitialized'](); 3127 | postRun(); 3128 | } 3129 | if (Module['setStatus']) { 3130 | Module['setStatus']('Running...'); 3131 | setTimeout(function () { 3132 | setTimeout(function () { 3133 | Module['setStatus'](''); 3134 | }, 1); 3135 | doRun(); 3136 | }, 1); 3137 | } else { 3138 | doRun(); 3139 | } 3140 | } 3141 | 3142 | Module['run'] = run; 3143 | 3144 | function exit(status, implicit) { 3145 | EXITSTATUS = status; 3146 | procExit(status); 3147 | } 3148 | 3149 | function procExit(code) { 3150 | EXITSTATUS = code; 3151 | if (!keepRuntimeAlive()) { 3152 | if (Module['onExit']) Module['onExit'](code); 3153 | ABORT = true; 3154 | } 3155 | quit_(code, new ExitStatus(code)); 3156 | } 3157 | 3158 | if (Module['preInit']) { 3159 | if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']]; 3160 | while (Module['preInit'].length > 0) { 3161 | Module['preInit'].pop()(); 3162 | } 3163 | } 3164 | 3165 | run(); 3166 | 3167 | /* Use an optimized gemm implementation if available, otherwise use the fallback 3168 | * implementation. 3169 | */ 3170 | function createWasmGemm() { 3171 | // A map of expected gemm function to the corresponding fallback gemm function names. 3172 | const GEMM_TO_FALLBACK_FUNCTIONS_MAP = { 3173 | int8_prepare_a: 'int8PrepareAFallback', 3174 | int8_prepare_b: 'int8PrepareBFallback', 3175 | int8_prepare_b_from_transposed: 'int8PrepareBFromTransposedFallback', 3176 | int8_prepare_b_from_quantized_transposed: 'int8PrepareBFromQuantizedTransposedFallback', 3177 | int8_prepare_bias: 'int8PrepareBiasFallback', 3178 | int8_multiply_and_add_bias: 'int8MultiplyAndAddBiasFallback', 3179 | int8_select_columns_of_b: 'int8SelectColumnsOfBFallback', 3180 | }; 3181 | 3182 | // Name of the optimized gemm implementation. 3183 | const OPTIMIZED_GEMM = 'mozIntGemm'; 3184 | 3185 | const optimizedGemmModule = WebAssembly[OPTIMIZED_GEMM]; 3186 | if (!optimizedGemmModule) { 3187 | return fallbackGemm(GEMM_TO_FALLBACK_FUNCTIONS_MAP); 3188 | } 3189 | 3190 | const optimizedGemmModuleExports = new WebAssembly.Instance(optimizedGemmModule(), {'': {memory: wasmMemory}}) 3191 | .exports; 3192 | for (let key in GEMM_TO_FALLBACK_FUNCTIONS_MAP) { 3193 | if (!optimizedGemmModuleExports[key]) { 3194 | return fallbackGemm(GEMM_TO_FALLBACK_FUNCTIONS_MAP); 3195 | } 3196 | } 3197 | console.log(`Using optimized gemm (${OPTIMIZED_GEMM}) implementation`); 3198 | return optimizedGemmModuleExports; 3199 | } 3200 | 3201 | // Return the fallback gemm implementation. 3202 | function fallbackGemm(gemmToFallbackFunctionsMap) { 3203 | // The fallback gemm implementation 3204 | const FALLBACK_GEMM = 'asm'; 3205 | 3206 | let fallbackGemmModuleExports = {}; 3207 | for (let key in gemmToFallbackFunctionsMap) { 3208 | fallbackGemmModuleExports[key] = (...a) => Module[FALLBACK_GEMM][gemmToFallbackFunctionsMap[key]](...a); 3209 | } 3210 | console.log(`Using fallback gemm implementation`); 3211 | return fallbackGemmModuleExports; 3212 | } 3213 | --------------------------------------------------------------------------------