From e811c04eebb8240c77f243e9617f8a6e9a19701e Mon Sep 17 00:00:00 2001 From: kura Date: Fri, 13 Dec 2024 15:20:28 +0800 Subject: [PATCH] init --- convex_hull.c | 42 + convex_hull.js | 2614 +++++++++++++++++++++++++++++++++++++++++ convex_hull.wasm | Bin 0 -> 29860 bytes convex_hull.worker.js | 196 +++ readme.md | 1 + test.html | 54 + 生成 | 3 + 7 files changed, 2910 insertions(+) create mode 100644 convex_hull.c create mode 100644 convex_hull.js create mode 100755 convex_hull.wasm create mode 100644 convex_hull.worker.js create mode 100644 readme.md create mode 100644 test.html create mode 100644 生成 diff --git a/convex_hull.c b/convex_hull.c new file mode 100644 index 0000000..1253ae3 --- /dev/null +++ b/convex_hull.c @@ -0,0 +1,42 @@ +#include + +// 定义一个点结构体 +typedef struct { + int x, y; +} Point; + +// 计算两点的极角 +int orientation(Point p, Point q, Point r) { + int val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y); + if (val == 0) return 0; // 共线 + return (val > 0) ? 1 : 2; // 顺时针或逆时针 +} + +// 对点的极角排序 +int compare(const void *vp1, const void *vp2) { + Point *p1 = (Point *)vp1; + Point *p2 = (Point *)vp2; + return (p1->y < p2->y) || (p1->y == p2->y && p1->x < p2->x); +} + +// 凸包主函数 +void convexHull(Point points[], int n, Point result[], int *result_size) { + // 如果点数小于 3,无法构成凸包 + if (n < 3) { + *result_size = 0; + return; + } + + // 按 y 坐标排序,如果 y 坐标相同则按 x 坐标排序 + qsort(points, n, sizeof(Point), compare); + + // 构建凸包 + int m = 0; // 凸包的点数 + for (int i = 0; i < n; i++) { + while (m >= 2 && orientation(result[m-2], result[m-1], points[i]) != 2) + m--; + result[m++] = points[i]; + } + + *result_size = m; +} \ No newline at end of file diff --git a/convex_hull.js b/convex_hull.js new file mode 100644 index 0000000..117d28b --- /dev/null +++ b/convex_hull.js @@ -0,0 +1,2614 @@ +// include: shell.js +// The Module object: Our interface to the outside world. We import +// and export values on it. There are various ways Module can be used: +// 1. Not defined. We create it here +// 2. A function parameter, function(Module) { ..generated code.. } +// 3. pre-run appended it, var Module = {}; ..generated code.. +// 4. External script tag defines var Module. +// We need to check if Module already exists (e.g. case 3 above). +// Substitution will be replaced with actual code on later stage of the build, +// this way Closure Compiler will not mangle it (e.g. case 4. above). +// Note that if you want to run closure, and also to use Module +// after the generated code, you will need to define var Module = {}; +// before the code. Then that object will be used in the code, and you +// can continue to use Module afterwards as well. +var Module = typeof Module != 'undefined' ? Module : {}; + +// --pre-jses are emitted after the Module integration code, so that they can +// refer to Module (if they choose; they can also define Module) + + +// Sometimes an existing Module object exists with properties +// meant to overwrite the default module functionality. Here +// we collect those properties and reapply _after_ we configure +// the current environment's defaults to avoid having to be so +// defensive during initialization. +var moduleOverrides = Object.assign({}, Module); + +var arguments_ = []; +var thisProgram = './this.program'; +var quit_ = (status, toThrow) => { + throw toThrow; +}; + +// Determine the runtime environment we are in. You can customize this by +// setting the ENVIRONMENT setting at compile time (see settings.js). + +// Attempt to auto-detect the environment +var ENVIRONMENT_IS_WEB = typeof window == 'object'; +var ENVIRONMENT_IS_WORKER = typeof importScripts == 'function'; +// N.b. Electron.js environment is simultaneously a NODE-environment, but +// also a web environment. +var ENVIRONMENT_IS_NODE = typeof process == 'object' && typeof process.versions == 'object' && typeof process.versions.node == 'string'; +var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER; + +if (Module['ENVIRONMENT']) { + throw new Error('Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -sENVIRONMENT=web or -sENVIRONMENT=node)'); +} + +// Three configurations we can be running in: +// 1) We could be the application main() thread running in the main JS UI thread. (ENVIRONMENT_IS_WORKER == false and ENVIRONMENT_IS_PTHREAD == false) +// 2) We could be the application main() thread proxied to worker. (with Emscripten -sPROXY_TO_WORKER) (ENVIRONMENT_IS_WORKER == true, ENVIRONMENT_IS_PTHREAD == false) +// 3) We could be an application pthread running in a worker. (ENVIRONMENT_IS_WORKER == true and ENVIRONMENT_IS_PTHREAD == true) + +// ENVIRONMENT_IS_PTHREAD=true will have been preset in worker.js. Make it false in the main runtime thread. +var ENVIRONMENT_IS_PTHREAD = Module['ENVIRONMENT_IS_PTHREAD'] || false; + +// In MODULARIZE mode _scriptDir needs to be captured already at the very top of the page immediately when the page is parsed, so it is generated there +// before the page load. In non-MODULARIZE modes generate it here. +var _scriptDir = (typeof document != 'undefined' && document.currentScript) ? document.currentScript.src : undefined; + +if (ENVIRONMENT_IS_WORKER) { + _scriptDir = self.location.href; +} +else if (ENVIRONMENT_IS_NODE) { + _scriptDir = __filename; +} + +// `/` should be present at the end if `scriptDirectory` is not empty +var scriptDirectory = ''; +function locateFile(path) { + if (Module['locateFile']) { + return Module['locateFile'](path, scriptDirectory); + } + return scriptDirectory + path; +} + +// Hooks that are implemented differently in different runtime environments. +var read_, + readAsync, + readBinary; + +if (ENVIRONMENT_IS_NODE) { + if (typeof process == 'undefined' || !process.release || process.release.name !== 'node') throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)'); + + var nodeVersion = process.versions.node; + var numericVersion = nodeVersion.split('.').slice(0, 3); + numericVersion = (numericVersion[0] * 10000) + (numericVersion[1] * 100) + (numericVersion[2].split('-')[0] * 1); + var minVersion = 160000; + if (numericVersion < 160000) { + throw new Error('This emscripten-generated code requires node v16.0.0 (detected v' + nodeVersion + ')'); + } + + // `require()` is no-op in an ESM module, use `createRequire()` to construct + // the require()` function. This is only necessary for multi-environment + // builds, `-sENVIRONMENT=node` emits a static import declaration instead. + // TODO: Swap all `require()`'s with `import()`'s? + // These modules will usually be used on Node.js. Load them eagerly to avoid + // the complexity of lazy-loading. + var fs = require('fs'); + var nodePath = require('path'); + + if (ENVIRONMENT_IS_WORKER) { + scriptDirectory = nodePath.dirname(scriptDirectory) + '/'; + } else { + scriptDirectory = __dirname + '/'; + } + +// include: node_shell_read.js +read_ = (filename, binary) => { + // We need to re-wrap `file://` strings to URLs. Normalizing isn't + // necessary in that case, the path should already be absolute. + filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename); + return fs.readFileSync(filename, binary ? undefined : 'utf8'); +}; + +readBinary = (filename) => { + var ret = read_(filename, true); + if (!ret.buffer) { + ret = new Uint8Array(ret); + } + assert(ret.buffer); + return ret; +}; + +readAsync = (filename, onload, onerror, binary = true) => { + // See the comment in the `read_` function. + filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename); + fs.readFile(filename, binary ? undefined : 'utf8', (err, data) => { + if (err) onerror(err); + else onload(binary ? data.buffer : data); + }); +}; +// end include: node_shell_read.js + if (!Module['thisProgram'] && process.argv.length > 1) { + thisProgram = process.argv[1].replace(/\\/g, '/'); + } + + arguments_ = process.argv.slice(2); + + if (typeof module != 'undefined') { + module['exports'] = Module; + } + + process.on('uncaughtException', (ex) => { + // suppress ExitStatus exceptions from showing an error + if (ex !== 'unwind' && !(ex instanceof ExitStatus) && !(ex.context instanceof ExitStatus)) { + throw ex; + } + }); + + quit_ = (status, toThrow) => { + process.exitCode = status; + throw toThrow; + }; + + global.Worker = require('worker_threads').Worker; + +} else +if (ENVIRONMENT_IS_SHELL) { + + if ((typeof process == 'object' && typeof require === 'function') || typeof window == 'object' || typeof importScripts == 'function') throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)'); + + if (typeof read != 'undefined') { + read_ = read; + } + + readBinary = (f) => { + if (typeof readbuffer == 'function') { + return new Uint8Array(readbuffer(f)); + } + let data = read(f, 'binary'); + assert(typeof data == 'object'); + return data; + }; + + readAsync = (f, onload, onerror) => { + setTimeout(() => onload(readBinary(f))); + }; + + if (typeof clearTimeout == 'undefined') { + globalThis.clearTimeout = (id) => {}; + } + + if (typeof setTimeout == 'undefined') { + // spidermonkey lacks setTimeout but we use it above in readAsync. + globalThis.setTimeout = (f) => (typeof f == 'function') ? f() : abort(); + } + + if (typeof scriptArgs != 'undefined') { + arguments_ = scriptArgs; + } else if (typeof arguments != 'undefined') { + arguments_ = arguments; + } + + if (typeof quit == 'function') { + quit_ = (status, toThrow) => { + // Unlike node which has process.exitCode, d8 has no such mechanism. So we + // have no way to set the exit code and then let the program exit with + // that code when it naturally stops running (say, when all setTimeouts + // have completed). For that reason, we must call `quit` - the only way to + // set the exit code - but quit also halts immediately. To increase + // consistency with node (and the web) we schedule the actual quit call + // using a setTimeout to give the current stack and any exception handlers + // a chance to run. This enables features such as addOnPostRun (which + // expected to be able to run code after main returns). + setTimeout(() => { + if (!(toThrow instanceof ExitStatus)) { + let toLog = toThrow; + if (toThrow && typeof toThrow == 'object' && toThrow.stack) { + toLog = [toThrow, toThrow.stack]; + } + err(`exiting due to exception: ${toLog}`); + } + quit(status); + }); + throw toThrow; + }; + } + + if (typeof print != 'undefined') { + // Prefer to use print/printErr where they exist, as they usually work better. + if (typeof console == 'undefined') console = /** @type{!Console} */({}); + console.log = /** @type{!function(this:Console, ...*): undefined} */ (print); + console.warn = console.error = /** @type{!function(this:Console, ...*): undefined} */ (typeof printErr != 'undefined' ? printErr : print); + } + +} else + +// Note that this includes Node.js workers when relevant (pthreads is enabled). +// Node.js workers are detected as a combination of ENVIRONMENT_IS_WORKER and +// ENVIRONMENT_IS_NODE. +if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { + if (ENVIRONMENT_IS_WORKER) { // Check worker, not web, since window could be polyfilled + scriptDirectory = self.location.href; + } else if (typeof document != 'undefined' && document.currentScript) { // web + scriptDirectory = document.currentScript.src; + } + // blob urls look like blob:http://site.com/etc/etc and we cannot infer anything from them. + // otherwise, slice off the final part of the url to find the script directory. + // if scriptDirectory does not contain a slash, lastIndexOf will return -1, + // and scriptDirectory will correctly be replaced with an empty string. + // If scriptDirectory contains a query (starting with ?) or a fragment (starting with #), + // they are removed because they could contain a slash. + if (scriptDirectory.startsWith('blob:')) { + scriptDirectory = ''; + } else { + scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, '').lastIndexOf('/')+1); + } + + if (!(typeof window == 'object' || typeof importScripts == 'function')) throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)'); + + // Differentiate the Web Worker from the Node Worker case, as reading must + // be done differently. + if (!ENVIRONMENT_IS_NODE) + { +// include: web_or_worker_shell_read.js +read_ = (url) => { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + xhr.send(null); + return xhr.responseText; + } + + if (ENVIRONMENT_IS_WORKER) { + readBinary = (url) => { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + xhr.responseType = 'arraybuffer'; + xhr.send(null); + return new Uint8Array(/** @type{!ArrayBuffer} */(xhr.response)); + }; + } + + readAsync = (url, onload, onerror) => { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, true); + xhr.responseType = 'arraybuffer'; + xhr.onload = () => { + if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0 + onload(xhr.response); + return; + } + onerror(); + }; + xhr.onerror = onerror; + xhr.send(null); + } + +// end include: web_or_worker_shell_read.js + } +} else +{ + throw new Error('environment detection error'); +} + +if (ENVIRONMENT_IS_NODE) { + // Polyfill the performance object, which emscripten pthreads support + // depends on for good timing. + if (typeof performance == 'undefined') { + global.performance = require('perf_hooks').performance; + } +} + +// Set up the out() and err() hooks, which are how we can print to stdout or +// stderr, respectively. +// Normally just binding console.log/console.error here works fine, but +// under node (with workers) we see missing/out-of-order messages so route +// directly to stdout and stderr. +// See https://github.com/emscripten-core/emscripten/issues/14804 +var defaultPrint = console.log.bind(console); +var defaultPrintErr = console.error.bind(console); +if (ENVIRONMENT_IS_NODE) { + defaultPrint = (...args) => fs.writeSync(1, args.join(' ') + '\n'); + defaultPrintErr = (...args) => fs.writeSync(2, args.join(' ') + '\n'); +} +var out = Module['print'] || defaultPrint; +var err = Module['printErr'] || defaultPrintErr; + +// Merge back in the overrides +Object.assign(Module, moduleOverrides); +// Free the object hierarchy contained in the overrides, this lets the GC +// reclaim data used. +moduleOverrides = null; +checkIncomingModuleAPI(); + +// Emit code to handle expected values on the Module object. This applies Module.x +// to the proper local x. This has two benefits: first, we only emit it if it is +// expected to arrive, and second, by using a local everywhere else that can be +// minified. + +if (Module['arguments']) arguments_ = Module['arguments'];legacyModuleProp('arguments', 'arguments_'); + +if (Module['thisProgram']) thisProgram = Module['thisProgram'];legacyModuleProp('thisProgram', 'thisProgram'); + +if (Module['quit']) quit_ = Module['quit'];legacyModuleProp('quit', 'quit_'); + +// perform assertions in shell.js after we set up out() and err(), as otherwise if an assertion fails it cannot print the message +// Assertions on removed incoming Module JS APIs. +assert(typeof Module['memoryInitializerPrefixURL'] == 'undefined', 'Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead'); +assert(typeof Module['pthreadMainPrefixURL'] == 'undefined', 'Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead'); +assert(typeof Module['cdInitializerPrefixURL'] == 'undefined', 'Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead'); +assert(typeof Module['filePackagePrefixURL'] == 'undefined', 'Module.filePackagePrefixURL option was removed, use Module.locateFile instead'); +assert(typeof Module['read'] == 'undefined', 'Module.read option was removed (modify read_ in JS)'); +assert(typeof Module['readAsync'] == 'undefined', 'Module.readAsync option was removed (modify readAsync in JS)'); +assert(typeof Module['readBinary'] == 'undefined', 'Module.readBinary option was removed (modify readBinary in JS)'); +assert(typeof Module['setWindowTitle'] == 'undefined', 'Module.setWindowTitle option was removed (modify emscripten_set_window_title in JS)'); +assert(typeof Module['TOTAL_MEMORY'] == 'undefined', 'Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY'); +legacyModuleProp('asm', 'wasmExports'); +legacyModuleProp('read', 'read_'); +legacyModuleProp('readAsync', 'readAsync'); +legacyModuleProp('readBinary', 'readBinary'); +legacyModuleProp('setWindowTitle', 'setWindowTitle'); +var IDBFS = 'IDBFS is no longer included by default; build with -lidbfs.js'; +var PROXYFS = 'PROXYFS is no longer included by default; build with -lproxyfs.js'; +var WORKERFS = 'WORKERFS is no longer included by default; build with -lworkerfs.js'; +var FETCHFS = 'FETCHFS is no longer included by default; build with -lfetchfs.js'; +var ICASEFS = 'ICASEFS is no longer included by default; build with -licasefs.js'; +var JSFILEFS = 'JSFILEFS is no longer included by default; build with -ljsfilefs.js'; +var OPFS = 'OPFS is no longer included by default; build with -lopfs.js'; + +var NODEFS = 'NODEFS is no longer included by default; build with -lnodefs.js'; + +assert( + ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER || ENVIRONMENT_IS_NODE, 'Pthreads do not work in this environment yet (need Web Workers, or an alternative to them)'); + +assert(!ENVIRONMENT_IS_SHELL, 'shell environment detected but not enabled at build time. Add `shell` to `-sENVIRONMENT` to enable.'); + +// end include: shell.js + +// include: preamble.js +// === Preamble library stuff === + +// Documentation for the public APIs defined in this file must be updated in: +// site/source/docs/api_reference/preamble.js.rst +// A prebuilt local version of the documentation is available at: +// site/build/text/docs/api_reference/preamble.js.txt +// You can also build docs locally as HTML or other formats in site/ +// An online HTML version (which may be of a different version of Emscripten) +// is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html + +var wasmBinary; +if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];legacyModuleProp('wasmBinary', 'wasmBinary'); + +if (typeof WebAssembly != 'object') { + err('no native wasm support detected'); +} + +// Wasm globals + +var wasmMemory; + +// For sending to workers. +var wasmModule; + +//======================================== +// Runtime essentials +//======================================== + +// whether we are quitting the application. no code should run after this. +// set in exit() and abort() +var ABORT = false; + +// set by exit() and abort(). Passed to 'onExit' handler. +// NOTE: This is also used as the process return code code in shell environments +// but only when noExitRuntime is false. +var EXITSTATUS; + +// In STRICT mode, we only define assert() when ASSERTIONS is set. i.e. we +// don't define it at all in release modes. This matches the behaviour of +// MINIMAL_RUNTIME. +// TODO(sbc): Make this the default even without STRICT enabled. +/** @type {function(*, string=)} */ +function assert(condition, text) { + if (!condition) { + abort('Assertion failed' + (text ? ': ' + text : '')); + } +} + +// We used to include malloc/free by default in the past. Show a helpful error in +// builds with assertions. + +// Memory management + +var HEAP, +/** @type {!Int8Array} */ + HEAP8, +/** @type {!Uint8Array} */ + HEAPU8, +/** @type {!Int16Array} */ + HEAP16, +/** @type {!Uint16Array} */ + HEAPU16, +/** @type {!Int32Array} */ + HEAP32, +/** @type {!Uint32Array} */ + HEAPU32, +/** @type {!Float32Array} */ + HEAPF32, +/** @type {!Float64Array} */ + HEAPF64; + +// include: runtime_shared.js +function updateMemoryViews() { + var b = wasmMemory.buffer; + Module['HEAP8'] = HEAP8 = new Int8Array(b); + Module['HEAP16'] = HEAP16 = new Int16Array(b); + Module['HEAPU8'] = HEAPU8 = new Uint8Array(b); + Module['HEAPU16'] = HEAPU16 = new Uint16Array(b); + Module['HEAP32'] = HEAP32 = new Int32Array(b); + Module['HEAPU32'] = HEAPU32 = new Uint32Array(b); + Module['HEAPF32'] = HEAPF32 = new Float32Array(b); + Module['HEAPF64'] = HEAPF64 = new Float64Array(b); +} +// end include: runtime_shared.js +assert(!Module['STACK_SIZE'], 'STACK_SIZE can no longer be set at runtime. Use -sSTACK_SIZE at link time') + +assert(typeof Int32Array != 'undefined' && typeof Float64Array !== 'undefined' && Int32Array.prototype.subarray != undefined && Int32Array.prototype.set != undefined, + 'JS engine does not provide full typed array support'); + +// In non-standalone/normal mode, we create the memory here. +// include: runtime_init_memory.js +// Create the wasm memory. (Note: this only applies if IMPORTED_MEMORY is defined) + +var INITIAL_MEMORY = Module['INITIAL_MEMORY'] || 16777216;legacyModuleProp('INITIAL_MEMORY', 'INITIAL_MEMORY'); + +assert(INITIAL_MEMORY >= 65536, 'INITIAL_MEMORY should be larger than STACK_SIZE, was ' + INITIAL_MEMORY + '! (STACK_SIZE=' + 65536 + ')'); + +// check for full engine support (use string 'subarray' to avoid closure compiler confusion) + +if (ENVIRONMENT_IS_PTHREAD) { + wasmMemory = Module['wasmMemory']; +} else { + + if (Module['wasmMemory']) { + wasmMemory = Module['wasmMemory']; + } else + { + wasmMemory = new WebAssembly.Memory({ + 'initial': INITIAL_MEMORY / 65536, + 'maximum': INITIAL_MEMORY / 65536, + 'shared': true, + }); + if (!(wasmMemory.buffer instanceof SharedArrayBuffer)) { + err('requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag'); + if (ENVIRONMENT_IS_NODE) { + err('(on node you may need: --experimental-wasm-threads --experimental-wasm-bulk-memory and/or recent version)'); + } + throw Error('bad memory'); + } + } + +} + +updateMemoryViews(); + +// If the user provides an incorrect length, just use that length instead rather than providing the user to +// specifically provide the memory length with Module['INITIAL_MEMORY']. +INITIAL_MEMORY = wasmMemory.buffer.byteLength; +assert(INITIAL_MEMORY % 65536 === 0); +// end include: runtime_init_memory.js + +// include: runtime_stack_check.js +// Initializes the stack cookie. Called at the startup of main and at the startup of each thread in pthreads mode. +function writeStackCookie() { + var max = _emscripten_stack_get_end(); + assert((max & 3) == 0); + // If the stack ends at address zero we write our cookies 4 bytes into the + // stack. This prevents interference with SAFE_HEAP and ASAN which also + // monitor writes to address zero. + if (max == 0) { + max += 4; + } + // The stack grow downwards towards _emscripten_stack_get_end. + // We write cookies to the final two words in the stack and detect if they are + // ever overwritten. + HEAPU32[((max)>>2)] = 0x02135467; + HEAPU32[(((max)+(4))>>2)] = 0x89BACDFE; + // Also test the global address 0 for integrity. + HEAPU32[((0)>>2)] = 1668509029; +} + +function checkStackCookie() { + if (ABORT) return; + var max = _emscripten_stack_get_end(); + // See writeStackCookie(). + if (max == 0) { + max += 4; + } + var cookie1 = HEAPU32[((max)>>2)]; + var cookie2 = HEAPU32[(((max)+(4))>>2)]; + if (cookie1 != 0x02135467 || cookie2 != 0x89BACDFE) { + abort(`Stack overflow! Stack cookie has been overwritten at ${ptrToString(max)}, expected hex dwords 0x89BACDFE and 0x2135467, but received ${ptrToString(cookie2)} ${ptrToString(cookie1)}`); + } + // Also test the global address 0 for integrity. + if (HEAPU32[((0)>>2)] != 0x63736d65 /* 'emsc' */) { + abort('Runtime error: The application has corrupted its heap memory area (address zero)!'); + } +} +// end include: runtime_stack_check.js +// include: runtime_assertions.js +// Endianness check +(function() { + var h16 = new Int16Array(1); + var h8 = new Int8Array(h16.buffer); + h16[0] = 0x6373; + if (h8[0] !== 0x73 || h8[1] !== 0x63) throw 'Runtime error: expected the system to be little-endian! (Run with -sSUPPORT_BIG_ENDIAN to bypass)'; +})(); + +// end include: runtime_assertions.js +var __ATPRERUN__ = []; // functions called before the runtime is initialized +var __ATINIT__ = []; // functions called during startup +var __ATEXIT__ = []; // functions called during shutdown +var __ATPOSTRUN__ = []; // functions called after the main() is called + +var runtimeInitialized = false; + +function preRun() { + assert(!ENVIRONMENT_IS_PTHREAD); // PThreads reuse the runtime from the main thread. + if (Module['preRun']) { + if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']]; + while (Module['preRun'].length) { + addOnPreRun(Module['preRun'].shift()); + } + } + callRuntimeCallbacks(__ATPRERUN__); +} + +function initRuntime() { + assert(!runtimeInitialized); + runtimeInitialized = true; + + if (ENVIRONMENT_IS_PTHREAD) return; + + checkStackCookie(); + + + callRuntimeCallbacks(__ATINIT__); +} + +function postRun() { + checkStackCookie(); + if (ENVIRONMENT_IS_PTHREAD) return; // PThreads reuse the runtime from the main thread. + + if (Module['postRun']) { + if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']]; + while (Module['postRun'].length) { + addOnPostRun(Module['postRun'].shift()); + } + } + + callRuntimeCallbacks(__ATPOSTRUN__); +} + +function addOnPreRun(cb) { + __ATPRERUN__.unshift(cb); +} + +function addOnInit(cb) { + __ATINIT__.unshift(cb); +} + +function addOnExit(cb) { +} + +function addOnPostRun(cb) { + __ATPOSTRUN__.unshift(cb); +} + +// include: runtime_math.js +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/fround + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32 + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc + +assert(Math.imul, 'This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill'); +assert(Math.fround, 'This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill'); +assert(Math.clz32, 'This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill'); +assert(Math.trunc, 'This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill'); +// end include: runtime_math.js +// A counter of dependencies for calling run(). If we need to +// do asynchronous work before running, increment this and +// decrement it. Incrementing must happen in a place like +// Module.preRun (used by emcc to add file preloading). +// Note that you can add dependencies in preRun, even though +// it happens right before run - run will be postponed until +// the dependencies are met. +var runDependencies = 0; +var runDependencyWatcher = null; +var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled +var runDependencyTracking = {}; + +function getUniqueRunDependency(id) { + var orig = id; + while (1) { + if (!runDependencyTracking[id]) return id; + id = orig + Math.random(); + } +} + +function addRunDependency(id) { + runDependencies++; + + Module['monitorRunDependencies']?.(runDependencies); + + if (id) { + assert(!runDependencyTracking[id]); + runDependencyTracking[id] = 1; + if (runDependencyWatcher === null && typeof setInterval != 'undefined') { + // Check for missing dependencies every few seconds + runDependencyWatcher = setInterval(() => { + if (ABORT) { + clearInterval(runDependencyWatcher); + runDependencyWatcher = null; + return; + } + var shown = false; + for (var dep in runDependencyTracking) { + if (!shown) { + shown = true; + err('still waiting on run dependencies:'); + } + err(`dependency: ${dep}`); + } + if (shown) { + err('(end of list)'); + } + }, 10000); + } + } else { + err('warning: run dependency added without ID'); + } +} + +function removeRunDependency(id) { + runDependencies--; + + Module['monitorRunDependencies']?.(runDependencies); + + if (id) { + assert(runDependencyTracking[id]); + delete runDependencyTracking[id]; + } else { + err('warning: run dependency removed without ID'); + } + if (runDependencies == 0) { + if (runDependencyWatcher !== null) { + clearInterval(runDependencyWatcher); + runDependencyWatcher = null; + } + if (dependenciesFulfilled) { + var callback = dependenciesFulfilled; + dependenciesFulfilled = null; + callback(); // can add another dependenciesFulfilled + } + } +} + +/** @param {string|number=} what */ +function abort(what) { + Module['onAbort']?.(what); + + what = 'Aborted(' + what + ')'; + // TODO(sbc): Should we remove printing and leave it up to whoever + // catches the exception? + err(what); + + ABORT = true; + EXITSTATUS = 1; + + // Use a wasm runtime error, because a JS error might be seen as a foreign + // exception, which means we'd run destructors on it. We need the error to + // simply make the program stop. + // FIXME This approach does not work in Wasm EH because it currently does not assume + // all RuntimeErrors are from traps; it decides whether a RuntimeError is from + // a trap or not based on a hidden field within the object. So at the moment + // we don't have a way of throwing a wasm trap from JS. TODO Make a JS API that + // allows this in the wasm spec. + + // Suppress closure compiler warning here. Closure compiler's builtin extern + // definition for WebAssembly.RuntimeError claims it takes no arguments even + // though it can. + // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure gets fixed. + /** @suppress {checkTypes} */ + var e = new WebAssembly.RuntimeError(what); + + // Throw the error whether or not MODULARIZE is set because abort is used + // in code paths apart from instantiation where an exception is expected + // to be thrown when abort is called. + throw e; +} + +// include: memoryprofiler.js +// end include: memoryprofiler.js +// show errors on likely calls to FS when it was not included +var FS = { + error() { + abort('Filesystem support (FS) was not included. The problem is that you are using files from JS, but files were not used from C/C++, so filesystem support was not auto-included. You can force-include filesystem support with -sFORCE_FILESYSTEM'); + }, + init() { FS.error() }, + createDataFile() { FS.error() }, + createPreloadedFile() { FS.error() }, + createLazyFile() { FS.error() }, + open() { FS.error() }, + mkdev() { FS.error() }, + registerDevice() { FS.error() }, + analyzePath() { FS.error() }, + + ErrnoError() { FS.error() }, +}; +Module['FS_createDataFile'] = FS.createDataFile; +Module['FS_createPreloadedFile'] = FS.createPreloadedFile; + +// include: URIUtils.js +// Prefix of data URIs emitted by SINGLE_FILE and related options. +var dataURIPrefix = 'data:application/octet-stream;base64,'; + +/** + * Indicates whether filename is a base64 data URI. + * @noinline + */ +var isDataURI = (filename) => filename.startsWith(dataURIPrefix); + +/** + * Indicates whether filename is delivered via file protocol (as opposed to http/https) + * @noinline + */ +var isFileURI = (filename) => filename.startsWith('file://'); +// end include: URIUtils.js +function createExportWrapper(name) { + return (...args) => { + assert(runtimeInitialized, `native function \`${name}\` called before runtime initialization`); + var f = wasmExports[name]; + assert(f, `exported native function \`${name}\` not found`); + return f(...args); + }; +} + +// include: runtime_exceptions.js +// end include: runtime_exceptions.js +var wasmBinaryFile; + wasmBinaryFile = 'convex_hull.wasm'; + if (!isDataURI(wasmBinaryFile)) { + wasmBinaryFile = locateFile(wasmBinaryFile); + } + +function getBinarySync(file) { + if (file == wasmBinaryFile && wasmBinary) { + return new Uint8Array(wasmBinary); + } + if (readBinary) { + return readBinary(file); + } + throw 'both async and sync fetching of the wasm failed'; +} + +function getBinaryPromise(binaryFile) { + // If we don't have the binary yet, try to load it asynchronously. + // Fetch has some additional restrictions over XHR, like it can't be used on a file:// url. + // See https://github.com/github/fetch/pull/92#issuecomment-140665932 + // Cordova or Electron apps are typically loaded from a file:// url. + // So use fetch if it is available and the url is not a file, otherwise fall back to XHR. + if (!wasmBinary + && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) { + if (typeof fetch == 'function' + && !isFileURI(binaryFile) + ) { + return fetch(binaryFile, { credentials: 'same-origin' }).then((response) => { + if (!response['ok']) { + throw `failed to load wasm binary file at '${binaryFile}'`; + } + return response['arrayBuffer'](); + }).catch(() => getBinarySync(binaryFile)); + } + else if (readAsync) { + // fetch is not available or url is file => try XHR (readAsync uses XHR internally) + return new Promise((resolve, reject) => { + readAsync(binaryFile, (response) => resolve(new Uint8Array(/** @type{!ArrayBuffer} */(response))), reject) + }); + } + } + + // Otherwise, getBinarySync should be able to get it synchronously + return Promise.resolve().then(() => getBinarySync(binaryFile)); +} + +function instantiateArrayBuffer(binaryFile, imports, receiver) { + return getBinaryPromise(binaryFile).then((binary) => { + return WebAssembly.instantiate(binary, imports); + }).then(receiver, (reason) => { + err(`failed to asynchronously prepare wasm: ${reason}`); + + // Warn on some common problems. + if (isFileURI(wasmBinaryFile)) { + err(`warning: Loading from a file URI (${wasmBinaryFile}) is not supported in most browsers. See https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-does-my-program-stall-in-downloading-or-preparing`); + } + abort(reason); + }); +} + +function instantiateAsync(binary, binaryFile, imports, callback) { + if (!binary && + typeof WebAssembly.instantiateStreaming == 'function' && + !isDataURI(binaryFile) && + // Don't use streaming for file:// delivered objects in a webview, fetch them synchronously. + !isFileURI(binaryFile) && + // Avoid instantiateStreaming() on Node.js environment for now, as while + // Node.js v18.1.0 implements it, it does not have a full fetch() + // implementation yet. + // + // Reference: + // https://github.com/emscripten-core/emscripten/pull/16917 + !ENVIRONMENT_IS_NODE && + typeof fetch == 'function') { + return fetch(binaryFile, { credentials: 'same-origin' }).then((response) => { + // Suppress closure warning here since the upstream definition for + // instantiateStreaming only allows Promise rather than + // an actual Response. + // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure is fixed. + /** @suppress {checkTypes} */ + var result = WebAssembly.instantiateStreaming(response, imports); + + return result.then( + callback, + function(reason) { + // We expect the most common failure cause to be a bad MIME type for the binary, + // in which case falling back to ArrayBuffer instantiation should work. + err(`wasm streaming compile failed: ${reason}`); + err('falling back to ArrayBuffer instantiation'); + return instantiateArrayBuffer(binaryFile, imports, callback); + }); + }); + } + return instantiateArrayBuffer(binaryFile, imports, callback); +} + +// Create the wasm instance. +// Receives the wasm imports, returns the exports. +function createWasm() { + // prepare imports + var info = { + 'env': wasmImports, + 'wasi_snapshot_preview1': wasmImports, + }; + // Load the wasm module and create an instance of using native support in the JS engine. + // handle a generated wasm instance, receiving its exports and + // performing other necessary setup + /** @param {WebAssembly.Module=} module*/ + function receiveInstance(instance, module) { + wasmExports = instance.exports; + + + + registerTLSInit(wasmExports['_emscripten_tls_init']); + + wasmTable = wasmExports['__indirect_function_table']; + + assert(wasmTable, 'table not found in wasm exports'); + + addOnInit(wasmExports['__wasm_call_ctors']); + + // We now have the Wasm module loaded up, keep a reference to the compiled module so we can post it to the workers. + wasmModule = module; + removeRunDependency('wasm-instantiate'); + return wasmExports; + } + // wait for the pthread pool (if any) + addRunDependency('wasm-instantiate'); + + // Prefer streaming instantiation if available. + // Async compilation can be confusing when an error on the page overwrites Module + // (for example, if the order of elements is wrong, and the one defining Module is + // later), so we save Module and check it later. + var trueModule = Module; + function receiveInstantiationResult(result) { + // 'result' is a ResultObject object which has both the module and instance. + // receiveInstance() will swap in the exports (to Module.asm) so they can be called + assert(Module === trueModule, 'the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?'); + trueModule = null; + receiveInstance(result['instance'], result['module']); + } + + // User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback + // to manually instantiate the Wasm module themselves. This allows pages to + // run the instantiation parallel to any other async startup actions they are + // performing. + // Also pthreads and wasm workers initialize the wasm instance through this + // path. + if (Module['instantiateWasm']) { + + try { + return Module['instantiateWasm'](info, receiveInstance); + } catch(e) { + err(`Module.instantiateWasm callback failed with error: ${e}`); + return false; + } + } + + instantiateAsync(wasmBinary, wasmBinaryFile, info, receiveInstantiationResult); + return {}; // no exports yet; we'll fill them in later +} + +// Globals used by JS i64 conversions (see makeSetValue) +var tempDouble; +var tempI64; + +// include: runtime_debug.js +function legacyModuleProp(prop, newName, incoming=true) { + if (!Object.getOwnPropertyDescriptor(Module, prop)) { + Object.defineProperty(Module, prop, { + configurable: true, + get() { + let extra = incoming ? ' (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)' : ''; + abort(`\`Module.${prop}\` has been replaced by \`${newName}\`` + extra); + + } + }); + } +} + +function ignoredModuleProp(prop) { + if (Object.getOwnPropertyDescriptor(Module, prop)) { + abort(`\`Module.${prop}\` was supplied but \`${prop}\` not included in INCOMING_MODULE_JS_API`); + } +} + +// forcing the filesystem exports a few things by default +function isExportedByForceFilesystem(name) { + return name === 'FS_createPath' || + name === 'FS_createDataFile' || + name === 'FS_createPreloadedFile' || + name === 'FS_unlink' || + name === 'addRunDependency' || + // The old FS has some functionality that WasmFS lacks. + name === 'FS_createLazyFile' || + name === 'FS_createDevice' || + name === 'removeRunDependency'; +} + +function missingGlobal(sym, msg) { + if (typeof globalThis !== 'undefined') { + Object.defineProperty(globalThis, sym, { + configurable: true, + get() { + warnOnce(`\`${sym}\` is not longer defined by emscripten. ${msg}`); + return undefined; + } + }); + } +} + +missingGlobal('buffer', 'Please use HEAP8.buffer or wasmMemory.buffer'); +missingGlobal('asm', 'Please use wasmExports instead'); + +function missingLibrarySymbol(sym) { + if (typeof globalThis !== 'undefined' && !Object.getOwnPropertyDescriptor(globalThis, sym)) { + Object.defineProperty(globalThis, sym, { + configurable: true, + get() { + // Can't `abort()` here because it would break code that does runtime + // checks. e.g. `if (typeof SDL === 'undefined')`. + var msg = `\`${sym}\` is a library symbol and not included by default; add it to your library.js __deps or to DEFAULT_LIBRARY_FUNCS_TO_INCLUDE on the command line`; + // DEFAULT_LIBRARY_FUNCS_TO_INCLUDE requires the name as it appears in + // library.js, which means $name for a JS name with no prefix, or name + // for a JS name like _name. + var librarySymbol = sym; + if (!librarySymbol.startsWith('_')) { + librarySymbol = '$' + sym; + } + msg += ` (e.g. -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE='${librarySymbol}')`; + if (isExportedByForceFilesystem(sym)) { + msg += '. Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you'; + } + warnOnce(msg); + return undefined; + } + }); + } + // Any symbol that is not included from the JS library is also (by definition) + // not exported on the Module object. + unexportedRuntimeSymbol(sym); +} + +function unexportedRuntimeSymbol(sym) { + if (!Object.getOwnPropertyDescriptor(Module, sym)) { + Object.defineProperty(Module, sym, { + configurable: true, + get() { + var msg = `'${sym}' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the Emscripten FAQ)`; + if (isExportedByForceFilesystem(sym)) { + msg += '. Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you'; + } + abort(msg); + } + }); + } +} + +// Used by XXXXX_DEBUG settings to output debug messages. +function dbg(...args) { + // Avoid using the console for debugging in multi-threaded node applications + // See https://github.com/emscripten-core/emscripten/issues/14804 + if (ENVIRONMENT_IS_NODE) { + fs.writeSync(2, args.join(' ') + '\n'); + } else + // TODO(sbc): Make this configurable somehow. Its not always convenient for + // logging to show up as warnings. + console.warn(...args); +} +// end include: runtime_debug.js +// === Body === +// end include: preamble.js + + + /** @constructor */ + function ExitStatus(status) { + this.name = 'ExitStatus'; + this.message = `Program terminated with exit(${status})`; + this.status = status; + } + + + + var terminateWorker = (worker) => { + worker.terminate(); + // terminate() can be asynchronous, so in theory the worker can continue + // to run for some amount of time after termination. However from our POV + // the worker now dead and we don't want to hear from it again, so we stub + // out its message handler here. This avoids having to check in each of + // the onmessage handlers if the message was coming from valid worker. + worker.onmessage = (e) => { + var cmd = e['data']['cmd']; + err(`received "${cmd}" command from terminated worker: ${worker.workerID}`); + }; + }; + + var killThread = (pthread_ptr) => { + assert(!ENVIRONMENT_IS_PTHREAD, 'Internal Error! killThread() can only ever be called from main application thread!'); + assert(pthread_ptr, 'Internal Error! Null pthread_ptr in killThread!'); + var worker = PThread.pthreads[pthread_ptr]; + delete PThread.pthreads[pthread_ptr]; + terminateWorker(worker); + __emscripten_thread_free_data(pthread_ptr); + // The worker was completely nuked (not just the pthread execution it was hosting), so remove it from running workers + // but don't put it back to the pool. + PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(worker), 1); // Not a running Worker anymore. + worker.pthread_ptr = 0; + }; + + var cancelThread = (pthread_ptr) => { + assert(!ENVIRONMENT_IS_PTHREAD, 'Internal Error! cancelThread() can only ever be called from main application thread!'); + assert(pthread_ptr, 'Internal Error! Null pthread_ptr in cancelThread!'); + var worker = PThread.pthreads[pthread_ptr]; + worker.postMessage({ 'cmd': 'cancel' }); + }; + + var cleanupThread = (pthread_ptr) => { + assert(!ENVIRONMENT_IS_PTHREAD, 'Internal Error! cleanupThread() can only ever be called from main application thread!'); + assert(pthread_ptr, 'Internal Error! Null pthread_ptr in cleanupThread!'); + var worker = PThread.pthreads[pthread_ptr]; + assert(worker); + PThread.returnWorkerToPool(worker); + }; + + var zeroMemory = (address, size) => { + HEAPU8.fill(0, address, address + size); + return address; + }; + + var spawnThread = (threadParams) => { + assert(!ENVIRONMENT_IS_PTHREAD, 'Internal Error! spawnThread() can only ever be called from main application thread!'); + assert(threadParams.pthread_ptr, 'Internal error, no pthread ptr!'); + + var worker = PThread.getNewWorker(); + if (!worker) { + // No available workers in the PThread pool. + return 6; + } + assert(!worker.pthread_ptr, 'Internal error!'); + + PThread.runningWorkers.push(worker); + + // Add to pthreads map + PThread.pthreads[threadParams.pthread_ptr] = worker; + + worker.pthread_ptr = threadParams.pthread_ptr; + var msg = { + 'cmd': 'run', + 'start_routine': threadParams.startRoutine, + 'arg': threadParams.arg, + 'pthread_ptr': threadParams.pthread_ptr, + }; + if (ENVIRONMENT_IS_NODE) { + // Mark worker as weakly referenced once we start executing a pthread, + // so that its existence does not prevent Node.js from exiting. This + // has no effect if the worker is already weakly referenced (e.g. if + // this worker was previously idle/unused). + worker.unref(); + } + // Ask the worker to start executing its pthread entry point function. + worker.postMessage(msg, threadParams.transferList); + return 0; + }; + + + + var runtimeKeepaliveCounter = 0; + var keepRuntimeAlive = () => noExitRuntime || runtimeKeepaliveCounter > 0; + + + var withStackSave = (f) => { + var stack = stackSave(); + var ret = f(); + stackRestore(stack); + return ret; + }; + + + var convertI32PairToI53Checked = (lo, hi) => { + assert(lo == (lo >>> 0) || lo == (lo|0)); // lo should either be a i32 or a u32 + assert(hi === (hi|0)); // hi should be a i32 + return ((hi + 0x200000) >>> 0 < 0x400001 - !!lo) ? (lo >>> 0) + hi * 4294967296 : NaN; + }; + + /** @type{function(number, (number|boolean), ...number)} */ + var proxyToMainThread = (funcIndex, emAsmAddr, sync, ...callArgs) => { + // EM_ASM proxying is done by passing a pointer to the address of the EM_ASM + // content as `emAsmAddr`. JS library proxying is done by passing an index + // into `proxiedJSCallArgs` as `funcIndex`. If `emAsmAddr` is non-zero then + // `funcIndex` will be ignored. + // Additional arguments are passed after the first three are the actual + // function arguments. + // The serialization buffer contains the number of call params, and then + // all the args here. + // We also pass 'sync' to C separately, since C needs to look at it. + // Allocate a buffer, which will be copied by the C code. + return withStackSave(() => { + // First passed parameter specifies the number of arguments to the function. + // When BigInt support is enabled, we must handle types in a more complex + // way, detecting at runtime if a value is a BigInt or not (as we have no + // type info here). To do that, add a "prefix" before each value that + // indicates if it is a BigInt, which effectively doubles the number of + // values we serialize for proxying. TODO: pack this? + var serializedNumCallArgs = callArgs.length ; + var args = stackAlloc(serializedNumCallArgs * 8); + var b = ((args)>>3); + for (var i = 0; i < callArgs.length; i++) { + var arg = callArgs[i]; + HEAPF64[b + i] = arg; + } + return __emscripten_run_on_main_thread_js(funcIndex, emAsmAddr, serializedNumCallArgs, args, sync); + }); + }; + + function _proc_exit(code) { + if (ENVIRONMENT_IS_PTHREAD) + return proxyToMainThread(0, 0, 1, code); + + EXITSTATUS = code; + if (!keepRuntimeAlive()) { + PThread.terminateAllThreads(); + Module['onExit']?.(code); + ABORT = true; + } + quit_(code, new ExitStatus(code)); + + } + + + /** @suppress {duplicate } */ + /** @param {boolean|number=} implicit */ + var exitJS = (status, implicit) => { + EXITSTATUS = status; + + checkUnflushedContent(); + + if (ENVIRONMENT_IS_PTHREAD) { + // implicit exit can never happen on a pthread + assert(!implicit); + // When running in a pthread we propagate the exit back to the main thread + // where it can decide if the whole process should be shut down or not. + // The pthread may have decided not to exit its own runtime, for example + // because it runs a main loop, but that doesn't affect the main thread. + exitOnMainThread(status); + throw 'unwind'; + } + + // if exit() was called explicitly, warn the user if the runtime isn't actually being shut down + if (keepRuntimeAlive() && !implicit) { + var msg = `program exited (with status: ${status}), but keepRuntimeAlive() is set (counter=${runtimeKeepaliveCounter}) due to an async operation, so halting execution but not exiting the runtime or preventing further async execution (you can use emscripten_force_exit, if you want to force a true shutdown)`; + err(msg); + } + + _proc_exit(status); + }; + var _exit = exitJS; + + var ptrToString = (ptr) => { + assert(typeof ptr === 'number'); + // With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned. + ptr >>>= 0; + return '0x' + ptr.toString(16).padStart(8, '0'); + }; + + var handleException = (e) => { + // Certain exception types we do not treat as errors since they are used for + // internal control flow. + // 1. ExitStatus, which is thrown by exit() + // 2. "unwind", which is thrown by emscripten_unwind_to_js_event_loop() and others + // that wish to return to JS event loop. + if (e instanceof ExitStatus || e == 'unwind') { + return EXITSTATUS; + } + checkStackCookie(); + if (e instanceof WebAssembly.RuntimeError) { + if (_emscripten_stack_get_current() <= 0) { + err('Stack overflow detected. You can try increasing -sSTACK_SIZE (currently set to 65536)'); + } + } + quit_(1, e); + }; + + var PThread = { + unusedWorkers:[], + runningWorkers:[], + tlsInitFunctions:[], + pthreads:{ + }, + nextWorkerID:1, + debugInit() { + function pthreadLogPrefix() { + var t = 0; + if (runtimeInitialized && typeof _pthread_self != 'undefined' + ) { + t = _pthread_self(); + } + return 'w:' + (Module['workerID'] || 0) + ',t:' + ptrToString(t) + ': '; + } + + // Prefix all err()/dbg() messages with the calling thread ID. + var origDbg = dbg; + dbg = (...args) => origDbg(pthreadLogPrefix() + args.join(' ')); + }, + init() { + PThread.debugInit(); + if (ENVIRONMENT_IS_PTHREAD + ) { + PThread.initWorker(); + } else { + PThread.initMainThread(); + } + }, + initMainThread() { + // MINIMAL_RUNTIME takes care of calling loadWasmModuleToAllWorkers + // in postamble_minimal.js + addOnPreRun(() => { + addRunDependency('loading-workers') + PThread.loadWasmModuleToAllWorkers(() => removeRunDependency('loading-workers')); + }); + }, + initWorker() { + // worker.js is not compiled together with us, and must access certain + // things. + PThread['receiveObjectTransfer'] = PThread.receiveObjectTransfer; + PThread['threadInitTLS'] = PThread.threadInitTLS; + PThread['setExitStatus'] = PThread.setExitStatus; + + // The default behaviour for pthreads is always to exit once they return + // from their entry point (or call pthread_exit). If we set noExitRuntime + // to true here on pthreads they would never complete and attempt to + // pthread_join to them would block forever. + // pthreads can still choose to set `noExitRuntime` explicitly, or + // call emscripten_unwind_to_js_event_loop to extend their lifetime beyond + // their main function. See comment in src/worker.js for more. + noExitRuntime = false; + }, + setExitStatus:(status) => EXITSTATUS = status, + terminateAllThreads__deps:["$terminateWorker"], + terminateAllThreads:() => { + assert(!ENVIRONMENT_IS_PTHREAD, 'Internal Error! terminateAllThreads() can only ever be called from main application thread!'); + // Attempt to kill all workers. Sadly (at least on the web) there is no + // way to terminate a worker synchronously, or to be notified when a + // worker in actually terminated. This means there is some risk that + // pthreads will continue to be executing after `worker.terminate` has + // returned. For this reason, we don't call `returnWorkerToPool` here or + // free the underlying pthread data structures. + for (var worker of PThread.runningWorkers) { + terminateWorker(worker); + } + for (var worker of PThread.unusedWorkers) { + terminateWorker(worker); + } + PThread.unusedWorkers = []; + PThread.runningWorkers = []; + PThread.pthreads = []; + }, + returnWorkerToPool:(worker) => { + // We don't want to run main thread queued calls here, since we are doing + // some operations that leave the worker queue in an invalid state until + // we are completely done (it would be bad if free() ends up calling a + // queued pthread_create which looks at the global data structures we are + // modifying). To achieve that, defer the free() til the very end, when + // we are all done. + var pthread_ptr = worker.pthread_ptr; + delete PThread.pthreads[pthread_ptr]; + // Note: worker is intentionally not terminated so the pool can + // dynamically grow. + PThread.unusedWorkers.push(worker); + PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(worker), 1); + // Not a running Worker anymore + // Detach the worker from the pthread object, and return it to the + // worker pool as an unused worker. + worker.pthread_ptr = 0; + + // Finally, free the underlying (and now-unused) pthread structure in + // linear memory. + __emscripten_thread_free_data(pthread_ptr); + }, + receiveObjectTransfer(data) { + }, + threadInitTLS() { + // Call thread init functions (these are the _emscripten_tls_init for each + // module loaded. + PThread.tlsInitFunctions.forEach((f) => f()); + }, + loadWasmModuleToWorker:(worker) => new Promise((onFinishedLoading) => { + worker.onmessage = (e) => { + var d = e['data']; + var cmd = d['cmd']; + + // If this message is intended to a recipient that is not the main + // thread, forward it to the target thread. + if (d['targetThread'] && d['targetThread'] != _pthread_self()) { + var targetWorker = PThread.pthreads[d['targetThread']]; + if (targetWorker) { + targetWorker.postMessage(d, d['transferList']); + } else { + err(`Internal error! Worker sent a message "${cmd}" to target pthread ${d['targetThread']}, but that thread no longer exists!`); + } + return; + } + + if (cmd === 'checkMailbox') { + checkMailbox(); + } else if (cmd === 'spawnThread') { + spawnThread(d); + } else if (cmd === 'cleanupThread') { + cleanupThread(d['thread']); + } else if (cmd === 'killThread') { + killThread(d['thread']); + } else if (cmd === 'cancelThread') { + cancelThread(d['thread']); + } else if (cmd === 'loaded') { + worker.loaded = true; + onFinishedLoading(worker); + } else if (cmd === 'alert') { + alert(`Thread ${d['threadId']}: ${d['text']}`); + } else if (d.target === 'setimmediate') { + // Worker wants to postMessage() to itself to implement setImmediate() + // emulation. + worker.postMessage(d); + } else if (cmd === 'callHandler') { + Module[d['handler']](...d['args']); + } else if (cmd) { + // The received message looks like something that should be handled by this message + // handler, (since there is a e.data.cmd field present), but is not one of the + // recognized commands: + err(`worker sent an unknown command ${cmd}`); + } + }; + + worker.onerror = (e) => { + var message = 'worker sent an error!'; + if (worker.pthread_ptr) { + message = `Pthread ${ptrToString(worker.pthread_ptr)} sent an error!`; + } + err(`${message} ${e.filename}:${e.lineno}: ${e.message}`); + throw e; + }; + + if (ENVIRONMENT_IS_NODE) { + worker.on('message', (data) => worker.onmessage({ data: data })); + worker.on('error', (e) => worker.onerror(e)); + } + + assert(wasmMemory instanceof WebAssembly.Memory, 'WebAssembly memory should have been loaded by now!'); + assert(wasmModule instanceof WebAssembly.Module, 'WebAssembly Module should have been loaded by now!'); + + // When running on a pthread, none of the incoming parameters on the module + // object are present. Proxy known handlers back to the main thread if specified. + var handlers = []; + var knownHandlers = [ + 'onExit', + 'onAbort', + 'print', + 'printErr', + ]; + for (var handler of knownHandlers) { + if (Module.hasOwnProperty(handler)) { + handlers.push(handler); + } + } + + worker.workerID = PThread.nextWorkerID++; + + // Ask the new worker to load up the Emscripten-compiled page. This is a heavy operation. + worker.postMessage({ + 'cmd': 'load', + 'handlers': handlers, + // If the application main .js file was loaded from a Blob, then it is not possible + // to access the URL of the current script that could be passed to a Web Worker so that + // it could load up the same file. In that case, developer must either deliver the Blob + // object in Module['mainScriptUrlOrBlob'], or a URL to it, so that pthread Workers can + // independently load up the same main application file. + 'urlOrBlob': Module['mainScriptUrlOrBlob'] + || _scriptDir + , + 'wasmMemory': wasmMemory, + 'wasmModule': wasmModule, + 'workerID': worker.workerID, + }); + }), + loadWasmModuleToAllWorkers(onMaybeReady) { + onMaybeReady(); + }, + allocateUnusedWorker() { + var worker; + // Allow HTML module to configure the location where the 'worker.js' file will be loaded from, + // via Module.locateFile() function. If not specified, then the default URL 'worker.js' relative + // to the main html file is loaded. + var pthreadMainJs = locateFile('convex_hull.worker.js'); + worker = new Worker(pthreadMainJs); + PThread.unusedWorkers.push(worker); + }, + getNewWorker() { + if (PThread.unusedWorkers.length == 0) { + // PTHREAD_POOL_SIZE_STRICT should show a warning and, if set to level `2`, return from the function. + // However, if we're in Node.js, then we can create new workers on the fly and PTHREAD_POOL_SIZE_STRICT + // should be ignored altogether. + if (!ENVIRONMENT_IS_NODE) { + err('Tried to spawn a new thread, but the thread pool is exhausted.\n' + + 'This might result in a deadlock unless some threads eventually exit or the code explicitly breaks out to the event loop.\n' + + 'If you want to increase the pool size, use setting `-sPTHREAD_POOL_SIZE=...`.' + + '\nIf you want to throw an explicit error instead of the risk of deadlocking in those cases, use setting `-sPTHREAD_POOL_SIZE_STRICT=2`.' + ); + } + PThread.allocateUnusedWorker(); + PThread.loadWasmModuleToWorker(PThread.unusedWorkers[0]); + } + return PThread.unusedWorkers.pop(); + }, + }; + Module['PThread'] = PThread; + + var callRuntimeCallbacks = (callbacks) => { + while (callbacks.length > 0) { + // Pass the module as the first argument. + callbacks.shift()(Module); + } + }; + + + var establishStackSpace = () => { + var pthread_ptr = _pthread_self(); + var stackHigh = HEAPU32[(((pthread_ptr)+(52))>>2)]; + var stackSize = HEAPU32[(((pthread_ptr)+(56))>>2)]; + var stackLow = stackHigh - stackSize; + assert(stackHigh != 0); + assert(stackLow != 0); + assert(stackHigh > stackLow, 'stackHigh must be higher then stackLow'); + // Set stack limits used by `emscripten/stack.h` function. These limits are + // cached in wasm-side globals to make checks as fast as possible. + _emscripten_stack_set_limits(stackHigh, stackLow); + + // Call inside wasm module to set up the stack frame for this pthread in wasm module scope + stackRestore(stackHigh); + + // Write the stack cookie last, after we have set up the proper bounds and + // current position of the stack. + writeStackCookie(); + }; + Module['establishStackSpace'] = establishStackSpace; + + + + + + function exitOnMainThread(returnCode) { + if (ENVIRONMENT_IS_PTHREAD) + return proxyToMainThread(1, 0, 0, returnCode); + + _exit(returnCode); + + } + + + + /** + * @param {number} ptr + * @param {string} type + */ + function getValue(ptr, type = 'i8') { + if (type.endsWith('*')) type = '*'; + switch (type) { + case 'i1': return HEAP8[ptr]; + case 'i8': return HEAP8[ptr]; + case 'i16': return HEAP16[((ptr)>>1)]; + case 'i32': return HEAP32[((ptr)>>2)]; + case 'i64': abort('to do getValue(i64) use WASM_BIGINT'); + case 'float': return HEAPF32[((ptr)>>2)]; + case 'double': return HEAPF64[((ptr)>>3)]; + case '*': return HEAPU32[((ptr)>>2)]; + default: abort(`invalid type for getValue: ${type}`); + } + } + Module['getValue'] = getValue; + + + + + var wasmTableMirror = []; + + var wasmTable; + var getWasmTableEntry = (funcPtr) => { + var func = wasmTableMirror[funcPtr]; + if (!func) { + if (funcPtr >= wasmTableMirror.length) wasmTableMirror.length = funcPtr + 1; + wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr); + } + assert(wasmTable.get(funcPtr) == func, 'JavaScript-side Wasm function table mirror is out of date!'); + return func; + }; + var invokeEntryPoint = (ptr, arg) => { + + // pthread entry points are always of signature 'void *ThreadMain(void *arg)' + // Native codebases sometimes spawn threads with other thread entry point + // signatures, such as void ThreadMain(void *arg), void *ThreadMain(), or + // void ThreadMain(). That is not acceptable per C/C++ specification, but + // x86 compiler ABI extensions enable that to work. If you find the + // following line to crash, either change the signature to "proper" void + // *ThreadMain(void *arg) form, or try linking with the Emscripten linker + // flag -sEMULATE_FUNCTION_POINTER_CASTS to add in emulation for this x86 + // ABI extension. + var result = getWasmTableEntry(ptr)(arg); + checkStackCookie(); + function finish(result) { + if (keepRuntimeAlive()) { + PThread.setExitStatus(result); + } else { + __emscripten_thread_exit(result); + } + } + finish(result); + }; + Module['invokeEntryPoint'] = invokeEntryPoint; + + var noExitRuntime = Module['noExitRuntime'] || true; + + + var registerTLSInit = (tlsInitFunc) => PThread.tlsInitFunctions.push(tlsInitFunc); + + + /** + * @param {number} ptr + * @param {number} value + * @param {string} type + */ + function setValue(ptr, value, type = 'i8') { + if (type.endsWith('*')) type = '*'; + switch (type) { + case 'i1': HEAP8[ptr] = value; break; + case 'i8': HEAP8[ptr] = value; break; + case 'i16': HEAP16[((ptr)>>1)] = value; break; + case 'i32': HEAP32[((ptr)>>2)] = value; break; + case 'i64': abort('to do setValue(i64) use WASM_BIGINT'); + case 'float': HEAPF32[((ptr)>>2)] = value; break; + case 'double': HEAPF64[((ptr)>>3)] = value; break; + case '*': HEAPU32[((ptr)>>2)] = value; break; + default: abort(`invalid type for setValue: ${type}`); + } + } + Module['setValue'] = setValue; + + var warnOnce = (text) => { + warnOnce.shown ||= {}; + if (!warnOnce.shown[text]) { + warnOnce.shown[text] = 1; + if (ENVIRONMENT_IS_NODE) text = 'warning: ' + text; + err(text); + } + }; + + var UTF8Decoder = typeof TextDecoder != 'undefined' ? new TextDecoder('utf8') : undefined; + + /** + * Given a pointer 'idx' to a null-terminated UTF8-encoded string in the given + * array that contains uint8 values, returns a copy of that string as a + * Javascript String object. + * heapOrArray is either a regular array, or a JavaScript typed array view. + * @param {number} idx + * @param {number=} maxBytesToRead + * @return {string} + */ + var UTF8ArrayToString = (heapOrArray, idx, maxBytesToRead) => { + var endIdx = idx + maxBytesToRead; + var endPtr = idx; + // TextDecoder needs to know the byte length in advance, it doesn't stop on + // null terminator by itself. Also, use the length info to avoid running tiny + // strings through TextDecoder, since .subarray() allocates garbage. + // (As a tiny code save trick, compare endPtr against endIdx using a negation, + // so that undefined means Infinity) + while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr; + + if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) { + return UTF8Decoder.decode(heapOrArray.buffer instanceof SharedArrayBuffer ? heapOrArray.slice(idx, endPtr) : heapOrArray.subarray(idx, endPtr)); + } + var str = ''; + // If building with TextDecoder, we have already computed the string length + // above, so test loop end condition against that + while (idx < endPtr) { + // For UTF8 byte structure, see: + // http://en.wikipedia.org/wiki/UTF-8#Description + // https://www.ietf.org/rfc/rfc2279.txt + // https://tools.ietf.org/html/rfc3629 + var u0 = heapOrArray[idx++]; + if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; } + var u1 = heapOrArray[idx++] & 63; + if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; } + var u2 = heapOrArray[idx++] & 63; + if ((u0 & 0xF0) == 0xE0) { + u0 = ((u0 & 15) << 12) | (u1 << 6) | u2; + } else { + if ((u0 & 0xF8) != 0xF0) warnOnce('Invalid UTF-8 leading byte ' + ptrToString(u0) + ' encountered when deserializing a UTF-8 string in wasm memory to a JS string!'); + u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63); + } + + if (u0 < 0x10000) { + str += String.fromCharCode(u0); + } else { + var ch = u0 - 0x10000; + str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); + } + } + return str; + }; + + /** + * Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the + * emscripten HEAP, returns a copy of that string as a Javascript String object. + * + * @param {number} ptr + * @param {number=} maxBytesToRead - An optional length that specifies the + * maximum number of bytes to read. You can omit this parameter to scan the + * string until the first 0 byte. If maxBytesToRead is passed, and the string + * at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the + * string will cut short at that byte index (i.e. maxBytesToRead will not + * produce a string of exact length [ptr, ptr+maxBytesToRead[) N.B. mixing + * frequent uses of UTF8ToString() with and without maxBytesToRead may throw + * JS JIT optimizations off, so it is worth to consider consistently using one + * @return {string} + */ + var UTF8ToString = (ptr, maxBytesToRead) => { + assert(typeof ptr == 'number', `UTF8ToString expects a number (got ${typeof ptr})`); + return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : ''; + }; + var ___assert_fail = (condition, filename, line, func) => { + abort(`Assertion failed: ${UTF8ToString(condition)}, at: ` + [filename ? UTF8ToString(filename) : 'unknown filename', line, func ? UTF8ToString(func) : 'unknown function']); + }; + + var ___emscripten_init_main_thread_js = (tb) => { + // Pass the thread address to the native code where they stored in wasm + // globals which act as a form of TLS. Global constructors trying + // to access this value will read the wrong value, but that is UB anyway. + __emscripten_thread_init( + tb, + /*is_main=*/!ENVIRONMENT_IS_WORKER, + /*is_runtime=*/1, + /*can_block=*/!ENVIRONMENT_IS_WEB, + /*default_stacksize=*/65536, + /*start_profiling=*/false, + ); + PThread.threadInitTLS(); + }; + + var ___emscripten_thread_cleanup = (thread) => { + // Called when a thread needs to be cleaned up so it can be reused. + // A thread is considered reusable when it either returns from its + // entry point, calls pthread_exit, or acts upon a cancellation. + // Detached threads are responsible for calling this themselves, + // otherwise pthread_join is responsible for calling this. + if (!ENVIRONMENT_IS_PTHREAD) cleanupThread(thread); + else postMessage({ 'cmd': 'cleanupThread', 'thread': thread }); + }; + + var nowIsMonotonic = 1; + var __emscripten_get_now_is_monotonic = () => nowIsMonotonic; + + + + + + var maybeExit = () => { + if (!keepRuntimeAlive()) { + try { + if (ENVIRONMENT_IS_PTHREAD) __emscripten_thread_exit(EXITSTATUS); + else + _exit(EXITSTATUS); + } catch (e) { + handleException(e); + } + } + }; + var callUserCallback = (func) => { + if (ABORT) { + err('user callback triggered after runtime exited or application aborted. Ignoring.'); + return; + } + try { + func(); + maybeExit(); + } catch (e) { + handleException(e); + } + }; + + + + var __emscripten_thread_mailbox_await = (pthread_ptr) => { + if (typeof Atomics.waitAsync === 'function') { + // Wait on the pthread's initial self-pointer field because it is easy and + // safe to access from sending threads that need to notify the waiting + // thread. + // TODO: How to make this work with wasm64? + var wait = Atomics.waitAsync(HEAP32, ((pthread_ptr)>>2), pthread_ptr); + assert(wait.async); + wait.value.then(checkMailbox); + var waitingAsync = pthread_ptr + 128; + Atomics.store(HEAP32, ((waitingAsync)>>2), 1); + } + // If `Atomics.waitAsync` is not implemented, then we will always fall back + // to postMessage and there is no need to do anything here. + }; + Module['__emscripten_thread_mailbox_await'] = __emscripten_thread_mailbox_await; + + var checkMailbox = () => { + // Only check the mailbox if we have a live pthread runtime. We implement + // pthread_self to return 0 if there is no live runtime. + var pthread_ptr = _pthread_self(); + if (pthread_ptr) { + // If we are using Atomics.waitAsync as our notification mechanism, wait + // for a notification before processing the mailbox to avoid missing any + // work that could otherwise arrive after we've finished processing the + // mailbox and before we're ready for the next notification. + __emscripten_thread_mailbox_await(pthread_ptr); + callUserCallback(__emscripten_check_mailbox); + } + }; + Module['checkMailbox'] = checkMailbox; + + var __emscripten_notify_mailbox_postmessage = (targetThreadId, currThreadId, mainThreadId) => { + if (targetThreadId == currThreadId) { + setTimeout(checkMailbox); + } else if (ENVIRONMENT_IS_PTHREAD) { + postMessage({'targetThread' : targetThreadId, 'cmd' : 'checkMailbox'}); + } else { + var worker = PThread.pthreads[targetThreadId]; + if (!worker) { + err(`Cannot send message to thread with ID ${targetThreadId}, unknown thread ID!`); + return; + } + worker.postMessage({'cmd' : 'checkMailbox'}); + } + }; + + + var proxiedJSCallArgs = []; + + var __emscripten_receive_on_main_thread_js = (funcIndex, emAsmAddr, callingThread, numCallArgs, args) => { + // Sometimes we need to backproxy events to the calling thread (e.g. + // HTML5 DOM events handlers such as + // emscripten_set_mousemove_callback()), so keep track in a globally + // accessible variable about the thread that initiated the proxying. + proxiedJSCallArgs.length = numCallArgs; + var b = ((args)>>3); + for (var i = 0; i < numCallArgs; i++) { + proxiedJSCallArgs[i] = HEAPF64[b + i]; + } + // Proxied JS library funcs use funcIndex and EM_ASM functions use emAsmAddr + assert(!emAsmAddr); + var func = proxiedFunctionTable[funcIndex]; + assert(!(funcIndex && emAsmAddr)); + assert(func.length == numCallArgs, 'Call args mismatch in _emscripten_receive_on_main_thread_js'); + PThread.currentProxiedOperationCallerThread = callingThread; + var rtn = func(...proxiedJSCallArgs); + PThread.currentProxiedOperationCallerThread = 0; + // Proxied functions can return any type except bigint. All other types + // cooerce to f64/double (the return type of this function in C) but not + // bigint. + assert(typeof rtn != "bigint"); + return rtn; + }; + + + var __emscripten_thread_set_strongref = (thread) => { + // Called when a thread needs to be strongly referenced. + // Currently only used for: + // - keeping the "main" thread alive in PROXY_TO_PTHREAD mode; + // - crashed threads that needs to propagate the uncaught exception + // back to the main thread. + if (ENVIRONMENT_IS_NODE) { + PThread.pthreads[thread].ref(); + } + }; + + + var _emscripten_check_blocking_allowed = () => { + if (ENVIRONMENT_IS_NODE) return; + + if (ENVIRONMENT_IS_WORKER) return; // Blocking in a worker/pthread is fine. + + warnOnce('Blocking on the main thread is very dangerous, see https://emscripten.org/docs/porting/pthreads.html#blocking-on-the-main-browser-thread'); + + }; + + var _emscripten_date_now = () => Date.now(); + + var runtimeKeepalivePush = () => { + runtimeKeepaliveCounter += 1; + }; + var _emscripten_exit_with_live_runtime = () => { + runtimeKeepalivePush(); + throw 'unwind'; + }; + + var _emscripten_get_now; + // Pthreads need their clocks synchronized to the execution of the main + // thread, so, when using them, make sure to adjust all timings to the + // respective time origins. + _emscripten_get_now = () => performance.timeOrigin + performance.now(); + ; + + var getHeapMax = () => + HEAPU8.length; + + var abortOnCannotGrowMemory = (requestedSize) => { + abort(`Cannot enlarge memory arrays to size ${requestedSize} bytes (OOM). Either (1) compile with -sINITIAL_MEMORY=X with X higher than the current value ${HEAP8.length}, (2) compile with -sALLOW_MEMORY_GROWTH which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with -sABORTING_MALLOC=0`); + }; + var _emscripten_resize_heap = (requestedSize) => { + var oldSize = HEAPU8.length; + // With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned. + requestedSize >>>= 0; + abortOnCannotGrowMemory(requestedSize); + }; + + + var printCharBuffers = [null,[],[]]; + + var printChar = (stream, curr) => { + var buffer = printCharBuffers[stream]; + assert(buffer); + if (curr === 0 || curr === 10) { + (stream === 1 ? out : err)(UTF8ArrayToString(buffer, 0)); + buffer.length = 0; + } else { + buffer.push(curr); + } + }; + + var flush_NO_FILESYSTEM = () => { + // flush anything remaining in the buffers during shutdown + _fflush(0); + if (printCharBuffers[1].length) printChar(1, 10); + if (printCharBuffers[2].length) printChar(2, 10); + }; + + + var SYSCALLS = { + varargs:undefined, + get() { + assert(SYSCALLS.varargs != undefined); + // the `+` prepended here is necessary to convince the JSCompiler that varargs is indeed a number. + var ret = HEAP32[((+SYSCALLS.varargs)>>2)]; + SYSCALLS.varargs += 4; + return ret; + }, + getp() { return SYSCALLS.get() }, + getStr(ptr) { + var ret = UTF8ToString(ptr); + return ret; + }, + }; + + + function _fd_write(fd, iov, iovcnt, pnum) { + if (ENVIRONMENT_IS_PTHREAD) + return proxyToMainThread(2, 0, 1, fd, iov, iovcnt, pnum); + + // hack to support printf in SYSCALLS_REQUIRE_FILESYSTEM=0 + var num = 0; + for (var i = 0; i < iovcnt; i++) { + var ptr = HEAPU32[((iov)>>2)]; + var len = HEAPU32[(((iov)+(4))>>2)]; + iov += 8; + for (var j = 0; j < len; j++) { + printChar(fd, HEAPU8[ptr+j]); + } + num += len; + } + HEAPU32[((pnum)>>2)] = num; + return 0; + + } + + + var getCFunc = (ident) => { + var func = Module['_' + ident]; // closure exported function + assert(func, 'Cannot call unknown function ' + ident + ', make sure it is exported'); + return func; + }; + + var writeArrayToMemory = (array, buffer) => { + assert(array.length >= 0, 'writeArrayToMemory array must have a length (should be an array or typed array)') + HEAP8.set(array, buffer); + }; + + var lengthBytesUTF8 = (str) => { + var len = 0; + for (var i = 0; i < str.length; ++i) { + // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code + // unit, not a Unicode code point of the character! So decode + // UTF16->UTF32->UTF8. + // See http://unicode.org/faq/utf_bom.html#utf16-3 + var c = str.charCodeAt(i); // possibly a lead surrogate + if (c <= 0x7F) { + len++; + } else if (c <= 0x7FF) { + len += 2; + } else if (c >= 0xD800 && c <= 0xDFFF) { + len += 4; ++i; + } else { + len += 3; + } + } + return len; + }; + + var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => { + assert(typeof str === 'string', `stringToUTF8Array expects a string (got ${typeof str})`); + // Parameter maxBytesToWrite is not optional. Negative values, 0, null, + // undefined and false each don't write out any bytes. + if (!(maxBytesToWrite > 0)) + return 0; + + var startIdx = outIdx; + var endIdx = outIdx + maxBytesToWrite - 1; // -1 for string null terminator. + for (var i = 0; i < str.length; ++i) { + // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code + // unit, not a Unicode code point of the character! So decode + // UTF16->UTF32->UTF8. + // See http://unicode.org/faq/utf_bom.html#utf16-3 + // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description + // and https://www.ietf.org/rfc/rfc2279.txt + // and https://tools.ietf.org/html/rfc3629 + var u = str.charCodeAt(i); // possibly a lead surrogate + if (u >= 0xD800 && u <= 0xDFFF) { + var u1 = str.charCodeAt(++i); + u = 0x10000 + ((u & 0x3FF) << 10) | (u1 & 0x3FF); + } + if (u <= 0x7F) { + if (outIdx >= endIdx) break; + heap[outIdx++] = u; + } else if (u <= 0x7FF) { + if (outIdx + 1 >= endIdx) break; + heap[outIdx++] = 0xC0 | (u >> 6); + heap[outIdx++] = 0x80 | (u & 63); + } else if (u <= 0xFFFF) { + if (outIdx + 2 >= endIdx) break; + heap[outIdx++] = 0xE0 | (u >> 12); + heap[outIdx++] = 0x80 | ((u >> 6) & 63); + heap[outIdx++] = 0x80 | (u & 63); + } else { + if (outIdx + 3 >= endIdx) break; + if (u > 0x10FFFF) warnOnce('Invalid Unicode code point ' + ptrToString(u) + ' encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF).'); + heap[outIdx++] = 0xF0 | (u >> 18); + heap[outIdx++] = 0x80 | ((u >> 12) & 63); + heap[outIdx++] = 0x80 | ((u >> 6) & 63); + heap[outIdx++] = 0x80 | (u & 63); + } + } + // Null-terminate the pointer to the buffer. + heap[outIdx] = 0; + return outIdx - startIdx; + }; + var stringToUTF8 = (str, outPtr, maxBytesToWrite) => { + assert(typeof maxBytesToWrite == 'number', 'stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!'); + return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite); + }; + var stringToUTF8OnStack = (str) => { + var size = lengthBytesUTF8(str) + 1; + var ret = stackAlloc(size); + stringToUTF8(str, ret, size); + return ret; + }; + + + + + + /** + * @param {string|null=} returnType + * @param {Array=} argTypes + * @param {Arguments|Array=} args + * @param {Object=} opts + */ + var ccall = (ident, returnType, argTypes, args, opts) => { + // For fast lookup of conversion functions + var toC = { + 'string': (str) => { + var ret = 0; + if (str !== null && str !== undefined && str !== 0) { // null string + // at most 4 bytes per UTF-8 code point, +1 for the trailing '\0' + ret = stringToUTF8OnStack(str); + } + return ret; + }, + 'array': (arr) => { + var ret = stackAlloc(arr.length); + writeArrayToMemory(arr, ret); + return ret; + } + }; + + function convertReturnValue(ret) { + if (returnType === 'string') { + + return UTF8ToString(ret); + } + if (returnType === 'boolean') return Boolean(ret); + return ret; + } + + var func = getCFunc(ident); + var cArgs = []; + var stack = 0; + assert(returnType !== 'array', 'Return type should not be "array".'); + if (args) { + for (var i = 0; i < args.length; i++) { + var converter = toC[argTypes[i]]; + if (converter) { + if (stack === 0) stack = stackSave(); + cArgs[i] = converter(args[i]); + } else { + cArgs[i] = args[i]; + } + } + } + var ret = func(...cArgs); + function onDone(ret) { + if (stack !== 0) stackRestore(stack); + return convertReturnValue(ret); + } + + ret = onDone(ret); + return ret; + }; + + + + /** + * @param {string=} returnType + * @param {Array=} argTypes + * @param {Object=} opts + */ + var cwrap = (ident, returnType, argTypes, opts) => { + return (...args) => ccall(ident, returnType, argTypes, args, opts); + }; + + +PThread.init();; + +// proxiedFunctionTable specifies the list of functions that can be called +// either synchronously or asynchronously from other threads in postMessage()d +// or internally queued events. This way a pthread in a Worker can synchronously +// access e.g. the DOM on the main thread. +var proxiedFunctionTable = [ + _proc_exit, + exitOnMainThread, + _fd_write +]; + +function checkIncomingModuleAPI() { + ignoredModuleProp('fetchSettings'); +} +var wasmImports = { + /** @export */ + __assert_fail: ___assert_fail, + /** @export */ + __emscripten_init_main_thread_js: ___emscripten_init_main_thread_js, + /** @export */ + __emscripten_thread_cleanup: ___emscripten_thread_cleanup, + /** @export */ + _emscripten_get_now_is_monotonic: __emscripten_get_now_is_monotonic, + /** @export */ + _emscripten_notify_mailbox_postmessage: __emscripten_notify_mailbox_postmessage, + /** @export */ + _emscripten_receive_on_main_thread_js: __emscripten_receive_on_main_thread_js, + /** @export */ + _emscripten_thread_mailbox_await: __emscripten_thread_mailbox_await, + /** @export */ + _emscripten_thread_set_strongref: __emscripten_thread_set_strongref, + /** @export */ + emscripten_check_blocking_allowed: _emscripten_check_blocking_allowed, + /** @export */ + emscripten_date_now: _emscripten_date_now, + /** @export */ + emscripten_exit_with_live_runtime: _emscripten_exit_with_live_runtime, + /** @export */ + emscripten_get_now: _emscripten_get_now, + /** @export */ + emscripten_resize_heap: _emscripten_resize_heap, + /** @export */ + exit: _exit, + /** @export */ + fd_write: _fd_write, + /** @export */ + memory: wasmMemory +}; +var wasmExports = createWasm(); +var ___wasm_call_ctors = createExportWrapper('__wasm_call_ctors'); +var _convexHull = Module['_convexHull'] = createExportWrapper('convexHull'); +var __emscripten_tls_init = Module['__emscripten_tls_init'] = createExportWrapper('_emscripten_tls_init'); +var _pthread_self = Module['_pthread_self'] = () => (_pthread_self = Module['_pthread_self'] = wasmExports['pthread_self'])(); +var __emscripten_thread_init = Module['__emscripten_thread_init'] = createExportWrapper('_emscripten_thread_init'); +var __emscripten_thread_crashed = Module['__emscripten_thread_crashed'] = createExportWrapper('_emscripten_thread_crashed'); +var _fflush = createExportWrapper('fflush'); +var _emscripten_main_runtime_thread_id = createExportWrapper('emscripten_main_runtime_thread_id'); +var _emscripten_main_thread_process_queued_calls = createExportWrapper('emscripten_main_thread_process_queued_calls'); +var __emscripten_run_on_main_thread_js = createExportWrapper('_emscripten_run_on_main_thread_js'); +var __emscripten_thread_free_data = createExportWrapper('_emscripten_thread_free_data'); +var __emscripten_thread_exit = Module['__emscripten_thread_exit'] = createExportWrapper('_emscripten_thread_exit'); +var __emscripten_check_mailbox = createExportWrapper('_emscripten_check_mailbox'); +var _malloc = Module['_malloc'] = createExportWrapper('malloc'); +var _free = Module['_free'] = createExportWrapper('free'); +var _emscripten_stack_get_base = () => (_emscripten_stack_get_base = wasmExports['emscripten_stack_get_base'])(); +var _emscripten_stack_get_end = () => (_emscripten_stack_get_end = wasmExports['emscripten_stack_get_end'])(); +var _emscripten_stack_init = () => (_emscripten_stack_init = wasmExports['emscripten_stack_init'])(); +var _emscripten_stack_set_limits = (a0, a1) => (_emscripten_stack_set_limits = wasmExports['emscripten_stack_set_limits'])(a0, a1); +var _emscripten_stack_get_free = () => (_emscripten_stack_get_free = wasmExports['emscripten_stack_get_free'])(); +var stackSave = createExportWrapper('stackSave'); +var stackRestore = createExportWrapper('stackRestore'); +var stackAlloc = createExportWrapper('stackAlloc'); +var _emscripten_stack_get_current = () => (_emscripten_stack_get_current = wasmExports['emscripten_stack_get_current'])(); +var dynCall_jiji = Module['dynCall_jiji'] = createExportWrapper('dynCall_jiji'); + + +// include: postamble.js +// === Auto-generated postamble setup entry stuff === + +Module['wasmMemory'] = wasmMemory; +Module['keepRuntimeAlive'] = keepRuntimeAlive; +Module['ccall'] = ccall; +Module['cwrap'] = cwrap; +Module['ExitStatus'] = ExitStatus; +var missingLibrarySymbols = [ + 'writeI53ToI64', + 'writeI53ToI64Clamped', + 'writeI53ToI64Signaling', + 'writeI53ToU64Clamped', + 'writeI53ToU64Signaling', + 'readI53FromI64', + 'readI53FromU64', + 'convertI32PairToI53', + 'convertU32PairToI53', + 'growMemory', + 'isLeapYear', + 'ydayFromDate', + 'arraySum', + 'addDays', + 'inetPton4', + 'inetNtop4', + 'inetPton6', + 'inetNtop6', + 'readSockaddr', + 'writeSockaddr', + 'initRandomFill', + 'randomFill', + 'getCallstack', + 'emscriptenLog', + 'convertPCtoSourceLocation', + 'readEmAsmArgs', + 'jstoi_q', + 'getExecutableName', + 'listenOnce', + 'autoResumeAudioContext', + 'dynCallLegacy', + 'getDynCaller', + 'dynCall', + 'runtimeKeepalivePop', + 'asmjsMangle', + 'asyncLoad', + 'alignMemory', + 'mmapAlloc', + 'HandleAllocator', + 'getNativeTypeSize', + 'STACK_SIZE', + 'STACK_ALIGN', + 'POINTER_SIZE', + 'ASSERTIONS', + 'uleb128Encode', + 'sigToWasmTypes', + 'generateFuncType', + 'convertJsFunctionToWasm', + 'getEmptyTableSlot', + 'updateTableMap', + 'getFunctionAddress', + 'addFunction', + 'removeFunction', + 'reallyNegative', + 'unSign', + 'strLen', + 'reSign', + 'formatString', + 'intArrayFromString', + 'intArrayToString', + 'AsciiToString', + 'stringToAscii', + 'UTF16ToString', + 'stringToUTF16', + 'lengthBytesUTF16', + 'UTF32ToString', + 'stringToUTF32', + 'lengthBytesUTF32', + 'stringToNewUTF8', + 'registerKeyEventCallback', + 'maybeCStringToJsString', + 'findEventTarget', + 'getBoundingClientRect', + 'fillMouseEventData', + 'registerMouseEventCallback', + 'registerWheelEventCallback', + 'registerUiEventCallback', + 'registerFocusEventCallback', + 'fillDeviceOrientationEventData', + 'registerDeviceOrientationEventCallback', + 'fillDeviceMotionEventData', + 'registerDeviceMotionEventCallback', + 'screenOrientation', + 'fillOrientationChangeEventData', + 'registerOrientationChangeEventCallback', + 'fillFullscreenChangeEventData', + 'registerFullscreenChangeEventCallback', + 'JSEvents_requestFullscreen', + 'JSEvents_resizeCanvasForFullscreen', + 'registerRestoreOldStyle', + 'hideEverythingExceptGivenElement', + 'restoreHiddenElements', + 'setLetterbox', + 'softFullscreenResizeWebGLRenderTarget', + 'doRequestFullscreen', + 'fillPointerlockChangeEventData', + 'registerPointerlockChangeEventCallback', + 'registerPointerlockErrorEventCallback', + 'requestPointerLock', + 'fillVisibilityChangeEventData', + 'registerVisibilityChangeEventCallback', + 'registerTouchEventCallback', + 'fillGamepadEventData', + 'registerGamepadEventCallback', + 'registerBeforeUnloadEventCallback', + 'fillBatteryEventData', + 'battery', + 'registerBatteryEventCallback', + 'setCanvasElementSizeCallingThread', + 'setCanvasElementSizeMainThread', + 'setCanvasElementSize', + 'getCanvasSizeCallingThread', + 'getCanvasSizeMainThread', + 'getCanvasElementSize', + 'jsStackTrace', + 'stackTrace', + 'getEnvStrings', + 'checkWasiClock', + 'wasiRightsToMuslOFlags', + 'wasiOFlagsToMuslOFlags', + 'createDyncallWrapper', + 'safeSetTimeout', + 'setImmediateWrapped', + 'clearImmediateWrapped', + 'polyfillSetImmediate', + 'getPromise', + 'makePromise', + 'idsToPromises', + 'makePromiseCallback', + 'ExceptionInfo', + 'findMatchingCatch', + 'Browser_asyncPrepareDataCounter', + 'setMainLoop', + 'getSocketFromFD', + 'getSocketAddress', + 'FS_createPreloadedFile', + 'FS_modeStringToFlags', + 'FS_getMode', + 'FS_stdin_getChar', + 'FS_createDataFile', + 'FS_unlink', + 'FS_mkdirTree', + '_setNetworkCallback', + 'heapObjectForWebGLType', + 'toTypedArrayIndex', + 'webgl_enable_ANGLE_instanced_arrays', + 'webgl_enable_OES_vertex_array_object', + 'webgl_enable_WEBGL_draw_buffers', + 'webgl_enable_WEBGL_multi_draw', + 'emscriptenWebGLGet', + 'computeUnpackAlignedImageSize', + 'colorChannelsInGlTextureFormat', + 'emscriptenWebGLGetTexPixelData', + 'emscriptenWebGLGetUniform', + 'webglGetUniformLocation', + 'webglPrepareUniformLocationsBeforeFirstUse', + 'webglGetLeftBracePos', + 'emscriptenWebGLGetVertexAttrib', + '__glGetActiveAttribOrUniform', + 'writeGLArray', + 'emscripten_webgl_destroy_context_before_on_calling_thread', + 'registerWebGlEventCallback', + 'runAndAbortIfError', + 'ALLOC_NORMAL', + 'ALLOC_STACK', + 'allocate', + 'writeStringToMemory', + 'writeAsciiToMemory', + 'setErrNo', + 'demangle', +]; +missingLibrarySymbols.forEach(missingLibrarySymbol) + +var unexportedSymbols = [ + 'run', + 'addOnPreRun', + 'addOnInit', + 'addOnPreMain', + 'addOnExit', + 'addOnPostRun', + 'addRunDependency', + 'removeRunDependency', + 'FS_createFolder', + 'FS_createPath', + 'FS_createLazyFile', + 'FS_createLink', + 'FS_createDevice', + 'FS_readFile', + 'out', + 'err', + 'callMain', + 'abort', + 'wasmExports', + 'stackAlloc', + 'stackSave', + 'stackRestore', + 'getTempRet0', + 'setTempRet0', + 'writeStackCookie', + 'checkStackCookie', + 'convertI32PairToI53Checked', + 'ptrToString', + 'zeroMemory', + 'exitJS', + 'getHeapMax', + 'abortOnCannotGrowMemory', + 'ENV', + 'MONTH_DAYS_REGULAR', + 'MONTH_DAYS_LEAP', + 'MONTH_DAYS_REGULAR_CUMULATIVE', + 'MONTH_DAYS_LEAP_CUMULATIVE', + 'ERRNO_CODES', + 'ERRNO_MESSAGES', + 'DNS', + 'Protocols', + 'Sockets', + 'timers', + 'warnOnce', + 'UNWIND_CACHE', + 'readEmAsmArgsArray', + 'jstoi_s', + 'handleException', + 'runtimeKeepalivePush', + 'callUserCallback', + 'maybeExit', + 'wasmTable', + 'noExitRuntime', + 'getCFunc', + 'freeTableIndexes', + 'functionsInTableMap', + 'setValue', + 'getValue', + 'PATH', + 'PATH_FS', + 'UTF8Decoder', + 'UTF8ArrayToString', + 'UTF8ToString', + 'stringToUTF8Array', + 'stringToUTF8', + 'lengthBytesUTF8', + 'UTF16Decoder', + 'stringToUTF8OnStack', + 'writeArrayToMemory', + 'JSEvents', + 'specialHTMLTargets', + 'findCanvasEventTarget', + 'currentFullscreenStrategy', + 'restoreOldWindowedStyle', + 'flush_NO_FILESYSTEM', + 'promiseMap', + 'uncaughtExceptionCount', + 'exceptionLast', + 'exceptionCaught', + 'Browser', + 'getPreloadedImageData__data', + 'wget', + 'SYSCALLS', + 'preloadPlugins', + 'FS_stdin_getChar_buffer', + 'FS', + 'MEMFS', + 'TTY', + 'PIPEFS', + 'SOCKFS', + 'tempFixedLengthArray', + 'miniTempWebGLFloatBuffers', + 'miniTempWebGLIntBuffers', + 'GL', + 'AL', + 'GLUT', + 'EGL', + 'GLEW', + 'IDBStore', + 'SDL', + 'SDL_gfx', + 'allocateUTF8', + 'allocateUTF8OnStack', + 'PThread', + 'terminateWorker', + 'killThread', + 'cleanupThread', + 'registerTLSInit', + 'cancelThread', + 'spawnThread', + 'exitOnMainThread', + 'proxyToMainThread', + 'proxiedJSCallArgs', + 'invokeEntryPoint', + 'checkMailbox', +]; +unexportedSymbols.forEach(unexportedRuntimeSymbol); + + + +var calledRun; + +dependenciesFulfilled = function runCaller() { + // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false) + if (!calledRun) run(); + if (!calledRun) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled +}; + +function stackCheckInit() { + // This is normally called automatically during __wasm_call_ctors but need to + // get these values before even running any of the ctors so we call it redundantly + // here. + // See $establishStackSpace for the equivalent code that runs on a thread + assert(!ENVIRONMENT_IS_PTHREAD); + _emscripten_stack_init(); + // TODO(sbc): Move writeStackCookie to native to to avoid this. + writeStackCookie(); +} + +function run() { + + if (runDependencies > 0) { + return; + } + + if (!ENVIRONMENT_IS_PTHREAD) + stackCheckInit(); + + if (ENVIRONMENT_IS_PTHREAD) { + initRuntime(); + startWorker(Module); + return; + } + + preRun(); + + // a preRun added a dependency, run will be called later + if (runDependencies > 0) { + return; + } + + function doRun() { + // run may have just been called through dependencies being fulfilled just in this very frame, + // or while the async setStatus time below was happening + if (calledRun) return; + calledRun = true; + Module['calledRun'] = true; + + if (ABORT) return; + + initRuntime(); + + if (Module['onRuntimeInitialized']) Module['onRuntimeInitialized'](); + + assert(!Module['_main'], 'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]'); + + postRun(); + } + + if (Module['setStatus']) { + Module['setStatus']('Running...'); + setTimeout(function() { + setTimeout(function() { + Module['setStatus'](''); + }, 1); + doRun(); + }, 1); + } else + { + doRun(); + } + checkStackCookie(); +} + +function checkUnflushedContent() { + // Compiler settings do not allow exiting the runtime, so flushing + // the streams is not possible. but in ASSERTIONS mode we check + // if there was something to flush, and if so tell the user they + // should request that the runtime be exitable. + // Normally we would not even include flush() at all, but in ASSERTIONS + // builds we do so just for this check, and here we see if there is any + // content to flush, that is, we check if there would have been + // something a non-ASSERTIONS build would have not seen. + // How we flush the streams depends on whether we are in SYSCALLS_REQUIRE_FILESYSTEM=0 + // mode (which has its own special function for this; otherwise, all + // the code is inside libc) + var oldOut = out; + var oldErr = err; + var has = false; + out = err = (x) => { + has = true; + } + try { // it doesn't matter if it fails + flush_NO_FILESYSTEM(); + } catch(e) {} + out = oldOut; + err = oldErr; + if (has) { + warnOnce('stdio streams had content in them that was not flushed. you should set EXIT_RUNTIME to 1 (see the Emscripten FAQ), or make sure to emit a newline when you printf etc.'); + warnOnce('(this may also be due to not including full filesystem support - try building with -sFORCE_FILESYSTEM)'); + } +} + +if (Module['preInit']) { + if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']]; + while (Module['preInit'].length > 0) { + Module['preInit'].pop()(); + } +} + +run(); + +// end include: postamble.js + diff --git a/convex_hull.wasm b/convex_hull.wasm new file mode 100755 index 0000000000000000000000000000000000000000..2e48fdb68cd61634ab6767da3f62114483f59816 GIT binary patch literal 29860 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

DWEnjK26O!d! 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 literal 0 HcmV?d00001 diff --git a/convex_hull.worker.js b/convex_hull.worker.js new file mode 100644 index 0000000..b14c0fa --- /dev/null +++ b/convex_hull.worker.js @@ -0,0 +1,196 @@ +/** + * @license + * Copyright 2015 The Emscripten Authors + * SPDX-License-Identifier: MIT + */ + +// Pthread Web Worker startup routine: +// This is the entry point file that is loaded first by each Web Worker +// that executes pthreads on the Emscripten application. + +'use strict'; + +var Module = {}; + +// Node.js support +var ENVIRONMENT_IS_NODE = typeof process == 'object' && typeof process.versions == 'object' && typeof process.versions.node == 'string'; +if (ENVIRONMENT_IS_NODE) { + // Create as web-worker-like an environment as we can. + + // See the parallel code in shell.js, but here we don't need the condition on + // multi-environment builds, as we do not have the need to interact with the + // modularization logic as shell.js must (see link.py:node_es6_imports and + // how that is used in link.py). + + var nodeWorkerThreads = require('worker_threads'); + + var parentPort = nodeWorkerThreads.parentPort; + + parentPort.on('message', (data) => onmessage({ data: data })); + + var fs = require('fs'); + var vm = require('vm'); + + Object.assign(global, { + self: global, + require, + Module, + location: { + // __filename is undefined in ES6 modules, and import.meta.url only in ES6 + // modules. + href: __filename + }, + Worker: nodeWorkerThreads.Worker, + importScripts: (f) => vm.runInThisContext(fs.readFileSync(f, 'utf8'), {filename: f}), + postMessage: (msg) => parentPort.postMessage(msg), + performance: global.performance || { now: Date.now }, + }); +} + +// Thread-local guard variable for one-time init of the JS state +var initializedJS = false; + +function assert(condition, text) { + if (!condition) abort('Assertion failed: ' + text); +} + +function threadPrintErr(...args) { + var text = args.join(' '); + // See https://github.com/emscripten-core/emscripten/issues/14804 + if (ENVIRONMENT_IS_NODE) { + fs.writeSync(2, text + '\n'); + return; + } + console.error(text); +} +function threadAlert(...args) { + var text = args.join(' '); + postMessage({cmd: 'alert', text, threadId: Module['_pthread_self']()}); +} +// We don't need out() for now, but may need to add it if we want to use it +// here. Or, if this code all moves into the main JS, that problem will go +// away. (For now, adding it here increases code size for no benefit.) +var out = () => { throw 'out() is not defined in worker.js.'; } +var err = threadPrintErr; +self.alert = threadAlert; +var dbg = threadPrintErr; + +Module['instantiateWasm'] = (info, receiveInstance) => { + // Instantiate from the module posted from the main thread. + // We can just use sync instantiation in the worker. + var module = Module['wasmModule']; + // We don't need the module anymore; new threads will be spawned from the main thread. + Module['wasmModule'] = null; + var instance = new WebAssembly.Instance(module, info); + // TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193, + // the above line no longer optimizes out down to the following line. + // When the regression is fixed, we can remove this if/else. + return receiveInstance(instance); +} + +// Turn unhandled rejected promises into errors so that the main thread will be +// notified about them. +self.onunhandledrejection = (e) => { + throw e.reason || e; +}; + +function handleMessage(e) { + try { + if (e.data.cmd === 'load') { // Preload command that is called once per worker to parse and load the Emscripten code. + + // Until we initialize the runtime, queue up any further incoming messages. + let messageQueue = []; + self.onmessage = (e) => messageQueue.push(e); + + // And add a callback for when the runtime is initialized. + self.startWorker = (instance) => { + // Notify the main thread that this thread has loaded. + postMessage({ 'cmd': 'loaded' }); + // Process any messages that were queued before the thread was ready. + for (let msg of messageQueue) { + handleMessage(msg); + } + // Restore the real message handler. + self.onmessage = handleMessage; + }; + + // Module and memory were sent from main thread + Module['wasmModule'] = e.data.wasmModule; + + // Use `const` here to ensure that the variable is scoped only to + // that iteration, allowing safe reference from a closure. + for (const handler of e.data.handlers) { + Module[handler] = (...args) => { + postMessage({ cmd: 'callHandler', handler, args: args }); + } + } + + Module['wasmMemory'] = e.data.wasmMemory; + + Module['buffer'] = Module['wasmMemory'].buffer; + + Module['workerID'] = e.data.workerID; + + Module['ENVIRONMENT_IS_PTHREAD'] = true; + + if (typeof e.data.urlOrBlob == 'string') { + importScripts(e.data.urlOrBlob); + } else { + var objectUrl = URL.createObjectURL(e.data.urlOrBlob); + importScripts(objectUrl); + URL.revokeObjectURL(objectUrl); + } + } else if (e.data.cmd === 'run') { + // Pass the thread address to wasm to store it for fast access. + Module['__emscripten_thread_init'](e.data.pthread_ptr, /*is_main=*/0, /*is_runtime=*/0, /*can_block=*/1); + + // Await mailbox notifications with `Atomics.waitAsync` so we can start + // using the fast `Atomics.notify` notification path. + Module['__emscripten_thread_mailbox_await'](e.data.pthread_ptr); + + assert(e.data.pthread_ptr); + // Also call inside JS module to set up the stack frame for this pthread in JS module scope + Module['establishStackSpace'](); + Module['PThread'].receiveObjectTransfer(e.data); + Module['PThread'].threadInitTLS(); + + if (!initializedJS) { + initializedJS = true; + } + + try { + Module['invokeEntryPoint'](e.data.start_routine, e.data.arg); + } catch(ex) { + if (ex != 'unwind') { + // The pthread "crashed". Do not call `_emscripten_thread_exit` (which + // would make this thread joinable). Instead, re-throw the exception + // and let the top level handler propagate it back to the main thread. + throw ex; + } + } + } else if (e.data.cmd === 'cancel') { // Main thread is asking for a pthread_cancel() on this thread. + if (Module['_pthread_self']()) { + Module['__emscripten_thread_exit'](-1); + } + } else if (e.data.target === 'setimmediate') { + // no-op + } else if (e.data.cmd === 'checkMailbox') { + if (initializedJS) { + Module['checkMailbox'](); + } + } else if (e.data.cmd) { + // The received message looks like something that should be handled by this message + // handler, (since there is a e.data.cmd field present), but is not one of the + // recognized commands: + err(`worker.js received unknown command ${e.data.cmd}`); + err(e.data); + } + } catch(ex) { + err(`worker.js onmessage() captured an uncaught exception: ${ex}`); + if (ex?.stack) err(ex.stack); + Module['__emscripten_thread_crashed']?.(); + throw ex; + } +}; + +self.onmessage = handleMessage; diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..72a15a7 --- /dev/null +++ b/readme.md @@ -0,0 +1 @@ +凸包算法的wasm实现 \ No newline at end of file diff --git a/test.html b/test.html new file mode 100644 index 0000000..eb0f2b4 --- /dev/null +++ b/test.html @@ -0,0 +1,54 @@ + + \ No newline at end of file diff --git a/生成 b/生成 new file mode 100644 index 0000000..2f23279 --- /dev/null +++ b/生成 @@ -0,0 +1,3 @@ +docker run --rm -v $(pwd):/src emscripten/emsdk emcc convex_hull.c -o convex_hull.js -s IMPORTED_MEMORY=1 -s INITIAL_MEMORY=104857600 -s EXPORTED_FUNCTIONS="['_convexHull','_malloc','_free','setValue','getValue']" -s EXTRA_EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]' + +docker run --rm -v $(pwd):/src emscripten/emsdk emcc convex_hull.c -o convex_hull.js -s USE_PTHREADS=1 -s IMPORTED_MEMORY=1 -s EXPORTED_FUNCTIONS="['_convexHull','_malloc','_free','setValue','getValue']" -s EXTRA_EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]' \ No newline at end of file