Created
February 28, 2023 00:52
-
-
Save kripken/bb18ae751e80771c34f56d53b42929ae to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Module = typeof Module != "undefined" ? Module : {}; | |
(function() { | |
return this; | |
}())["Module"] = function() { | |
var moduleOverrides = Object.assign({}, Module); | |
var arguments_ = []; | |
var thisProgram = "./this.program"; | |
var quit_ = (status, toThrow) => { | |
throw toThrow; | |
}; | |
var ENVIRONMENT_IS_WEB = typeof window == "object"; | |
var ENVIRONMENT_IS_WORKER = typeof importScripts == "function"; | |
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)"); | |
} | |
var scriptDirectory = ""; | |
function locateFile(path) { | |
if (Module["locateFile"]) { | |
return Module["locateFile"](path, scriptDirectory); | |
} | |
return scriptDirectory + path; | |
} | |
var read_, readAsync, readBinary, setWindowTitle; | |
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] * 1e4 + numericVersion[1] * 100 + numericVersion[2] * 1; | |
var minVersion = 101900; | |
if (numericVersion < 101900) { | |
throw new Error("This emscripten-generated code requires node v10.19.19.0 (detected v" + nodeVersion + ")"); | |
} | |
var fs = require("fs"); | |
var nodePath = require("path"); | |
if (ENVIRONMENT_IS_WORKER) { | |
scriptDirectory = nodePath.dirname(scriptDirectory) + "/"; | |
} else { | |
scriptDirectory = __dirname + "/"; | |
} | |
read_ = (filename, binary) => { | |
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) => { | |
filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename); | |
fs.readFile(filename, function(err, data) { | |
if (err) onerror(err); else onload(data.buffer); | |
}); | |
}; | |
if (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", function(ex) { | |
if (ex !== "unwind" && !(ex instanceof ExitStatus) && !(ex.context instanceof ExitStatus)) { | |
throw ex; | |
} | |
}); | |
var nodeMajor = process.versions.node.split(".")[0]; | |
if (nodeMajor < 15) { | |
process.on("unhandledRejection", function(reason) { | |
throw reason; | |
}); | |
} | |
quit_ = (status, toThrow) => { | |
process.exitCode = status; | |
throw toThrow; | |
}; | |
Module["inspect"] = function() { | |
return "[Emscripten Module object]"; | |
}; | |
} 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_ = function shell_read(f) { | |
return read(f); | |
}; | |
} | |
readBinary = function readBinary(f) { | |
let data; | |
if (typeof readbuffer == "function") { | |
return new Uint8Array(readbuffer(f)); | |
} | |
data = read(f, "binary"); | |
assert(typeof data == "object"); | |
return data; | |
}; | |
readAsync = function readAsync(f, onload, onerror) { | |
setTimeout(() => onload(readBinary(f)), 0); | |
}; | |
if (typeof clearTimeout == "undefined") { | |
globalThis.clearTimeout = id => {}; | |
} | |
if (typeof scriptArgs != "undefined") { | |
arguments_ = scriptArgs; | |
} else if (typeof arguments != "undefined") { | |
arguments_ = arguments; | |
} | |
if (typeof quit == "function") { | |
quit_ = (status, toThrow) => { | |
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") { | |
if (typeof console == "undefined") console = {}; | |
console.log = print; | |
console.warn = console.error = typeof printErr != "undefined" ? printErr : print; | |
} | |
} else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { | |
if (ENVIRONMENT_IS_WORKER) { | |
scriptDirectory = self.location.href; | |
} else if (typeof document != "undefined" && document.currentScript) { | |
scriptDirectory = document.currentScript.src; | |
} | |
if (scriptDirectory.indexOf("blob:") !== 0) { | |
scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, "").lastIndexOf("/") + 1); | |
} else { | |
scriptDirectory = ""; | |
} | |
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?)"); | |
{ | |
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(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) { | |
onload(xhr.response); | |
return; | |
} | |
onerror(); | |
}; | |
xhr.onerror = onerror; | |
xhr.send(null); | |
}; | |
} | |
setWindowTitle = title => document.title = title; | |
} else { | |
throw new Error("environment detection error"); | |
} | |
var out = Module["print"] || console.log.bind(console); | |
var err = Module["printErr"] || console.warn.bind(console); | |
Object.assign(Module, moduleOverrides); | |
moduleOverrides = null; | |
checkIncomingModuleAPI(); | |
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_"); | |
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 setWindowTitle in JS)"); | |
assert(typeof Module["TOTAL_MEMORY"] == "undefined", "Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY"); | |
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 NODEFS = "NODEFS is no longer included by default; build with -lnodefs.js"; | |
assert(!ENVIRONMENT_IS_SHELL, "shell environment detected but not enabled at build time. Add 'shell' to `-sENVIRONMENT` to enable."); | |
var wasmBinary; | |
if (Module["wasmBinary"]) wasmBinary = Module["wasmBinary"]; | |
legacyModuleProp("wasmBinary", "wasmBinary"); | |
var noExitRuntime = Module["noExitRuntime"] || true; | |
legacyModuleProp("noExitRuntime", "noExitRuntime"); | |
if (typeof WebAssembly != "object") { | |
abort("no native wasm support detected"); | |
} | |
var wasmMemory; | |
var ABORT = false; | |
var EXITSTATUS; | |
function assert(condition, text) { | |
if (!condition) { | |
abort("Assertion failed" + (text ? ": " + text : "")); | |
} | |
} | |
var UTF8Decoder = typeof TextDecoder != "undefined" ? new TextDecoder("utf8") : undefined; | |
function UTF8ArrayToString(heapOrArray, idx, maxBytesToRead) { | |
var endIdx = idx + maxBytesToRead; | |
var endPtr = idx; | |
while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr; | |
if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) { | |
return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr)); | |
} | |
var str = ""; | |
while (idx < endPtr) { | |
var u0 = heapOrArray[idx++]; | |
if (!(u0 & 128)) { | |
str += String.fromCharCode(u0); | |
continue; | |
} | |
var u1 = heapOrArray[idx++] & 63; | |
if ((u0 & 224) == 192) { | |
str += String.fromCharCode((u0 & 31) << 6 | u1); | |
continue; | |
} | |
var u2 = heapOrArray[idx++] & 63; | |
if ((u0 & 240) == 224) { | |
u0 = (u0 & 15) << 12 | u1 << 6 | u2; | |
} else { | |
if ((u0 & 248) != 240) 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 < 65536) { | |
str += String.fromCharCode(u0); | |
} else { | |
var ch = u0 - 65536; | |
str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023); | |
} | |
} | |
return str; | |
} | |
function UTF8ToString(ptr, maxBytesToRead) { | |
assert(typeof ptr == "number"); | |
return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : ""; | |
} | |
function stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) { | |
if (!(maxBytesToWrite > 0)) return 0; | |
var startIdx = outIdx; | |
var endIdx = outIdx + maxBytesToWrite - 1; | |
for (var i = 0; i < str.length; ++i) { | |
var u = str.charCodeAt(i); | |
if (u >= 55296 && u <= 57343) { | |
var u1 = str.charCodeAt(++i); | |
u = 65536 + ((u & 1023) << 10) | u1 & 1023; | |
} | |
if (u <= 127) { | |
if (outIdx >= endIdx) break; | |
heap[outIdx++] = u; | |
} else if (u <= 2047) { | |
if (outIdx + 1 >= endIdx) break; | |
heap[outIdx++] = 192 | u >> 6; | |
heap[outIdx++] = 128 | u & 63; | |
} else if (u <= 65535) { | |
if (outIdx + 2 >= endIdx) break; | |
heap[outIdx++] = 224 | u >> 12; | |
heap[outIdx++] = 128 | u >> 6 & 63; | |
heap[outIdx++] = 128 | u & 63; | |
} else { | |
if (outIdx + 3 >= endIdx) break; | |
if (u > 1114111) 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++] = 240 | u >> 18; | |
heap[outIdx++] = 128 | u >> 12 & 63; | |
heap[outIdx++] = 128 | u >> 6 & 63; | |
heap[outIdx++] = 128 | u & 63; | |
} | |
} | |
heap[outIdx] = 0; | |
return outIdx - startIdx; | |
} | |
function 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); | |
} | |
function lengthBytesUTF8(str) { | |
var len = 0; | |
for (var i = 0; i < str.length; ++i) { | |
var c = str.charCodeAt(i); | |
if (c <= 127) { | |
len++; | |
} else if (c <= 2047) { | |
len += 2; | |
} else if (c >= 55296 && c <= 57343) { | |
len += 4; | |
++i; | |
} else { | |
len += 3; | |
} | |
} | |
return len; | |
} | |
var HEAP, HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64; | |
function updateMemoryViews() { | |
var b = wasmMemory.buffer; | |
Module["HEAP8"] = HEAP8 = new Int8Array(b); | |
Module["HEAP16"] = HEAP16 = new Int16Array(b); | |
Module["HEAP32"] = HEAP32 = new Int32Array(b); | |
Module["HEAPU8"] = HEAPU8 = new Uint8Array(b); | |
Module["HEAPU16"] = HEAPU16 = new Uint16Array(b); | |
Module["HEAPU32"] = HEAPU32 = new Uint32Array(b); | |
Module["HEAPF32"] = HEAPF32 = new Float32Array(b); | |
Module["HEAPF64"] = HEAPF64 = new Float64Array(b); | |
} | |
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"); | |
assert(!Module["wasmMemory"], "Use of `wasmMemory` detected. Use -sIMPORTED_MEMORY to define wasmMemory externally"); | |
assert(!Module["INITIAL_MEMORY"], "Detected runtime INITIAL_MEMORY setting. Use -sIMPORTED_MEMORY to define wasmMemory dynamically"); | |
var wasmTable; | |
function writeStackCookie() { | |
var max = _emscripten_stack_get_end(); | |
assert((max & 3) == 0); | |
if (max == 0) { | |
max += 4; | |
} | |
HEAPU32[max >> 2] = 34821223; | |
HEAPU32[max + 4 >> 2] = 2310721022; | |
HEAPU32[0] = 1668509029; | |
} | |
function checkStackCookie() { | |
if (ABORT) return; | |
var max = _emscripten_stack_get_end(); | |
if (max == 0) { | |
max += 4; | |
} | |
var cookie1 = HEAPU32[max >> 2]; | |
var cookie2 = HEAPU32[max + 4 >> 2]; | |
if (cookie1 != 34821223 || cookie2 != 2310721022) { | |
abort("Stack overflow! Stack cookie has been overwritten at " + ptrToString(max) + ", expected hex dwords 0x89BACDFE and 0x2135467, but received " + ptrToString(cookie2) + " " + ptrToString(cookie1)); | |
} | |
if (HEAPU32[0] !== 1668509029) { | |
abort("Runtime error: The application has corrupted its heap memory area (address zero)!"); | |
} | |
} | |
(function() { | |
var h16 = new Int16Array(1); | |
var h8 = new Int8Array(h16.buffer); | |
h16[0] = 25459; | |
if (h8[0] !== 115 || h8[1] !== 99) throw "Runtime error: expected the system to be little-endian! (Run with -sSUPPORT_BIG_ENDIAN to bypass)"; | |
})(); | |
var __ATPRERUN__ = []; | |
var __ATINIT__ = []; | |
var __ATEXIT__ = []; | |
var __ATPOSTRUN__ = []; | |
var runtimeInitialized = false; | |
var runtimeKeepaliveCounter = 0; | |
function keepRuntimeAlive() { | |
return noExitRuntime || runtimeKeepaliveCounter > 0; | |
} | |
function preRun() { | |
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; | |
checkStackCookie(); | |
callRuntimeCallbacks(__ATINIT__); | |
} | |
function postRun() { | |
checkStackCookie(); | |
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); | |
} | |
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"); | |
var runDependencies = 0; | |
var runDependencyWatcher = null; | |
var dependenciesFulfilled = null; | |
var runDependencyTracking = {}; | |
function getUniqueRunDependency(id) { | |
var orig = id; | |
while (1) { | |
if (!runDependencyTracking[id]) return id; | |
id = orig + Math.random(); | |
} | |
} | |
function addRunDependency(id) { | |
runDependencies++; | |
if (Module["monitorRunDependencies"]) { | |
Module["monitorRunDependencies"](runDependencies); | |
} | |
if (id) { | |
assert(!runDependencyTracking[id]); | |
runDependencyTracking[id] = 1; | |
if (runDependencyWatcher === null && typeof setInterval != "undefined") { | |
runDependencyWatcher = setInterval(function() { | |
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)"); | |
} | |
}, 1e4); | |
} | |
} else { | |
err("warning: run dependency added without ID"); | |
} | |
} | |
function removeRunDependency(id) { | |
runDependencies--; | |
if (Module["monitorRunDependencies"]) { | |
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(); | |
} | |
} | |
} | |
function abort(what) { | |
if (Module["onAbort"]) { | |
Module["onAbort"](what); | |
} | |
what = "Aborted(" + what + ")"; | |
err(what); | |
ABORT = true; | |
EXITSTATUS = 1; | |
var e = new WebAssembly.RuntimeError(what); | |
throw e; | |
} | |
var FS = { | |
error: function() { | |
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: function() { | |
FS.error(); | |
}, | |
createDataFile: function() { | |
FS.error(); | |
}, | |
createPreloadedFile: function() { | |
FS.error(); | |
}, | |
createLazyFile: function() { | |
FS.error(); | |
}, | |
open: function() { | |
FS.error(); | |
}, | |
mkdev: function() { | |
FS.error(); | |
}, | |
registerDevice: function() { | |
FS.error(); | |
}, | |
analyzePath: function() { | |
FS.error(); | |
}, | |
loadFilesFromDB: function() { | |
FS.error(); | |
}, | |
ErrnoError: function ErrnoError() { | |
FS.error(); | |
} | |
}; | |
Module["FS_createDataFile"] = FS.createDataFile; | |
Module["FS_createPreloadedFile"] = FS.createPreloadedFile; | |
var dataURIPrefix = "data:application/octet-stream;base64,"; | |
function isDataURI(filename) { | |
return filename.startsWith(dataURIPrefix); | |
} | |
function isFileURI(filename) { | |
return filename.startsWith("file://"); | |
} | |
function createExportWrapper(name, fixedasm) { | |
return function() { | |
var displayName = name; | |
var asm = fixedasm; | |
if (!fixedasm) { | |
asm = Module["asm"]; | |
} | |
assert(runtimeInitialized, "native function `" + displayName + "` called before runtime initialization"); | |
if (!asm[name]) { | |
assert(asm[name], "exported native function `" + displayName + "` not found"); | |
} | |
return asm[name].apply(null, arguments); | |
}; | |
} | |
var wasmBinaryFile; | |
wasmBinaryFile = "a.out.wasm"; | |
if (!isDataURI(wasmBinaryFile)) { | |
wasmBinaryFile = locateFile(wasmBinaryFile); | |
} | |
function getBinary(file) { | |
try { | |
if (file == wasmBinaryFile && wasmBinary) { | |
return new Uint8Array(wasmBinary); | |
} | |
if (readBinary) { | |
return readBinary(file); | |
} | |
throw "sync fetching of the wasm failed: you can preload it to Module['wasmBinary'] manually, or emcc.py will do that for you when generating HTML (but not JS)"; | |
} catch (err) { | |
abort(err); | |
} | |
} | |
function getBinaryPromise(binaryFile) { | |
if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) { | |
if (typeof fetch == "function" && !isFileURI(binaryFile)) { | |
return fetch(binaryFile, { | |
credentials: "same-origin" | |
}).then(function(response) { | |
if (!response["ok"]) { | |
throw "failed to load wasm binary file at '" + binaryFile + "'"; | |
} | |
return response["arrayBuffer"](); | |
}).catch(function() { | |
return getBinary(binaryFile); | |
}); | |
} else { | |
if (readAsync) { | |
return new Promise(function(resolve, reject) { | |
readAsync(binaryFile, function(response) { | |
resolve(new Uint8Array(response)); | |
}, reject); | |
}); | |
} | |
} | |
} | |
return Promise.resolve().then(function() { | |
return getBinary(binaryFile); | |
}); | |
} | |
function instantiateSync(file, info) { | |
var instance; | |
var module; | |
var binary; | |
try { | |
binary = getBinary(file); | |
module = new WebAssembly.Module(binary); | |
instance = new WebAssembly.Instance(module, info); | |
} catch (e) { | |
var str = e.toString(); | |
err("failed to compile wasm module: " + str); | |
if (str.includes("imported Memory") || str.includes("memory import")) { | |
err("Memory size incompatibility issues may be due to changing INITIAL_MEMORY at runtime to something too large. Use ALLOW_MEMORY_GROWTH to allow any size memory (and also make sure not to set INITIAL_MEMORY at runtime to something smaller than it was at compile time)."); | |
} | |
throw e; | |
} | |
return [ instance, module ]; | |
} | |
function createWasm() { | |
var info = { | |
"env": wasmImports, | |
"wasi_snapshot_preview1": wasmImports | |
}; | |
function receiveInstance(instance, module) { | |
var exports = instance.exports; | |
Module["asm"] = exports; | |
wasmMemory = Module["asm"]["memory"]; | |
assert(wasmMemory, "memory not found in wasm exports"); | |
updateMemoryViews(); | |
wasmTable = Module["asm"]["__indirect_function_table"]; | |
assert(wasmTable, "table not found in wasm exports"); | |
addOnInit(Module["asm"]["__wasm_call_ctors"]); | |
removeRunDependency("wasm-instantiate"); | |
return exports; | |
} | |
addRunDependency("wasm-instantiate"); | |
if (Module["instantiateWasm"]) { | |
try { | |
return Module["instantiateWasm"](info, receiveInstance); | |
} catch (e) { | |
err("Module.instantiateWasm callback failed with error: " + e); | |
return false; | |
} | |
} | |
var result = instantiateSync(wasmBinaryFile, info); | |
return receiveInstance(result[0]); | |
} | |
var tempDouble; | |
var tempI64; | |
function legacyModuleProp(prop, newName) { | |
if (!Object.getOwnPropertyDescriptor(Module, prop)) { | |
Object.defineProperty(Module, prop, { | |
configurable: true, | |
get: function() { | |
abort("Module." + prop + " has been replaced with plain " + newName + " (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)"); | |
} | |
}); | |
} | |
} | |
function ignoredModuleProp(prop) { | |
if (Object.getOwnPropertyDescriptor(Module, prop)) { | |
abort("`Module." + prop + "` was supplied but `" + prop + "` not included in INCOMING_MODULE_JS_API"); | |
} | |
} | |
function isExportedByForceFilesystem(name) { | |
return name === "FS_createPath" || name === "FS_createDataFile" || name === "FS_createPreloadedFile" || name === "FS_unlink" || name === "addRunDependency" || name === "FS_createLazyFile" || name === "FS_createDevice" || name === "removeRunDependency"; | |
} | |
function missingGlobal(sym, msg) { | |
if (typeof globalThis !== "undefined") { | |
Object.defineProperty(globalThis, sym, { | |
configurable: true, | |
get: function() { | |
warnOnce("`" + sym + "` is not longer defined by emscripten. " + msg); | |
return undefined; | |
} | |
}); | |
} | |
} | |
missingGlobal("buffer", "Please use HEAP8.buffer or wasmMemory.buffer"); | |
function missingLibrarySymbol(sym) { | |
if (typeof globalThis !== "undefined" && !Object.getOwnPropertyDescriptor(globalThis, sym)) { | |
Object.defineProperty(globalThis, sym, { | |
configurable: true, | |
get: function() { | |
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"; | |
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; | |
} | |
}); | |
} | |
unexportedRuntimeSymbol(sym); | |
} | |
function unexportedRuntimeSymbol(sym) { | |
if (!Object.getOwnPropertyDescriptor(Module, sym)) { | |
Object.defineProperty(Module, sym, { | |
configurable: true, | |
get: function() { | |
var msg = "'" + sym + "' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)"; | |
if (isExportedByForceFilesystem(sym)) { | |
msg += ". Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you"; | |
} | |
abort(msg); | |
} | |
}); | |
} | |
} | |
function dbg(text) { | |
console.error(text); | |
} | |
var compilerSettings = { | |
"ABORTING_MALLOC": true, | |
"ABORT_ON_WASM_EXCEPTIONS": false, | |
"AGGRESSIVE_VARIABLE_ELIMINATION": 0, | |
"ALIASING_FUNCTION_POINTERS": 0, | |
"ALLOW_BLOCKING_ON_MAIN_THREAD": true, | |
"ALLOW_MEMORY_GROWTH": false, | |
"ALLOW_TABLE_GROWTH": false, | |
"ALLOW_UNIMPLEMENTED_SYSCALLS": true, | |
"ASAN_SHADOW_SIZE": -1, | |
"ASM_JS": 1, | |
"ASSERTIONS": 1, | |
"ASYNCIFY": 0, | |
"ASYNCIFY_ADVISE": false, | |
"ASYNCIFY_DEBUG": 0, | |
"ASYNCIFY_IGNORE_INDIRECT": false, | |
"ASYNCIFY_LAZY_LOAD_CODE": false, | |
"ASYNCIFY_STACK_SIZE": 4096, | |
"AUDIO_WORKLET": 0, | |
"AUDIO_WORKLET_FILE": "", | |
"AUTODEBUG": false, | |
"AUTOLOAD_DYLIBS": true, | |
"AUTO_ARCHIVE_INDEXES": true, | |
"AUTO_JS_LIBRARIES": true, | |
"AUTO_NATIVE_LIBRARIES": true, | |
"BENCHMARK": false, | |
"BINARYEN": 1, | |
"BINARYEN_ASYNC_COMPILATION": 0, | |
"BINARYEN_EXTRA_PASSES": "", | |
"BINARYEN_IGNORE_IMPLICIT_TRAPS": false, | |
"BINARYEN_MEM_MAX": 2147483648, | |
"BINARYEN_METHOD": "native-wasm", | |
"BINARYEN_PASSES": "", | |
"BINARYEN_SCRIPTS": "", | |
"BINARYEN_TRAP_MODE": -1, | |
"BOOTSTRAPPING_STRUCT_INFO": false, | |
"BUILD_AS_SHARED_LIB": 0, | |
"BUILD_AS_WORKER": false, | |
"CAN_ADDRESS_2GB": false, | |
"CASE_INSENSITIVE_FS": false, | |
"CLOSURE_WARNINGS": "quiet", | |
"DEBUG_LEVEL": 0, | |
"DECLARE_ASM_MODULE_EXPORTS": true, | |
"DEFAULT_PTHREAD_STACK_SIZE": 0, | |
"DEFAULT_TO_CXX": true, | |
"DEMANGLE_SUPPORT": false, | |
"DETERMINISTIC": false, | |
"DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR": true, | |
"DISABLE_EXCEPTION_CATCHING": 1, | |
"DISABLE_EXCEPTION_THROWING": false, | |
"DOUBLE_MODE": 0, | |
"DYLINK_DEBUG": false, | |
"DYNAMIC_EXECUTION": 0, | |
"DYNCALLS": false, | |
"ELIMINATE_DUPLICATE_FUNCTIONS": 0, | |
"ELIMINATE_DUPLICATE_FUNCTIONS_DUMP_EQUIVALENT_FUNCTIONS": 0, | |
"ELIMINATE_DUPLICATE_FUNCTIONS_PASSES": 5, | |
"EMBIND": 1, | |
"EMBIND_STD_STRING_IS_UTF8": true, | |
"EMITTING_JS": 1, | |
"EMIT_EMSCRIPTEN_LICENSE": false, | |
"EMIT_EMSCRIPTEN_METADATA": 0, | |
"EMIT_NAME_SECTION": false, | |
"EMIT_PRODUCERS_SECTION": false, | |
"EMIT_SYMBOL_MAP": false, | |
"EMSCRIPTEN_TRACING": false, | |
"EMSCRIPTEN_VERSION": "3.1.33-git", | |
"EMULATE_FUNCTION_POINTER_CASTS": false, | |
"ENVIRONMENT": "web,webview,worker,node", | |
"ENVIRONMENT_MAY_BE_NODE": true, | |
"ENVIRONMENT_MAY_BE_SHELL": false, | |
"ENVIRONMENT_MAY_BE_WEB": true, | |
"ENVIRONMENT_MAY_BE_WEBVIEW": true, | |
"ENVIRONMENT_MAY_BE_WORKER": true, | |
"ERROR_ON_MISSING_LIBRARIES": 1, | |
"ERROR_ON_UNDEFINED_SYMBOLS": true, | |
"ERROR_ON_WASM_CHANGES_AFTER_LINK": false, | |
"EVAL_CTORS": 0, | |
"EXCEPTION_DEBUG": false, | |
"EXCEPTION_STACK_TRACES": false, | |
"EXIT_RUNTIME": false, | |
"EXPECT_MAIN": true, | |
"EXPORT_ALL": false, | |
"EXPORT_BINDINGS": 0, | |
"EXPORT_ES6": false, | |
"EXPORT_EXCEPTION_HANDLING_HELPERS": false, | |
"EXPORT_FUNCTION_TABLES": 0, | |
"EXPORT_KEEPALIVE": true, | |
"EXPORT_NAME": "Module", | |
"EXPORT_READY_PROMISE": true, | |
"FAST_UNROLLED_MEMCPY_AND_MEMSET": 0, | |
"FETCH": false, | |
"FETCH_DEBUG": false, | |
"FETCH_SUPPORT_INDEXEDDB": true, | |
"FETCH_WORKER_FILE": "", | |
"FILESYSTEM": true, | |
"FINALIZE_ASM_JS": 0, | |
"FORCE_ALIGNED_MEMORY": 0, | |
"FORCE_FILESYSTEM": false, | |
"FS_DEBUG": false, | |
"FULL_ES2": false, | |
"FULL_ES3": false, | |
"FUNCTION_POINTER_ALIGNMENT": 2, | |
"GENERATE_DWARF": false, | |
"GENERATE_SOURCE_MAP": false, | |
"GLOBAL_BASE": 1024, | |
"GL_ASSERTIONS": false, | |
"GL_DEBUG": false, | |
"GL_DISABLE_HALF_FLOAT_EXTENSION_IF_BROKEN": false, | |
"GL_EMULATE_GLES_VERSION_STRING_FORMAT": true, | |
"GL_EXPLICIT_UNIFORM_BINDING": false, | |
"GL_EXPLICIT_UNIFORM_LOCATION": false, | |
"GL_EXTENSIONS_IN_PREFIXED_FORMAT": true, | |
"GL_FFP_ONLY": false, | |
"GL_MAX_TEMP_BUFFER_SIZE": 2097152, | |
"GL_POOL_TEMP_BUFFERS": true, | |
"GL_PREINITIALIZED_CONTEXT": false, | |
"GL_SUPPORT_AUTOMATIC_ENABLE_EXTENSIONS": true, | |
"GL_SUPPORT_EXPLICIT_SWAP_CONTROL": false, | |
"GL_SUPPORT_SIMPLE_ENABLE_EXTENSIONS": true, | |
"GL_TESTING": false, | |
"GL_TRACK_ERRORS": true, | |
"GL_UNSAFE_OPTS": true, | |
"GL_WORKAROUND_SAFARI_GETCONTEXT_BUG": true, | |
"HAS_MAIN": false, | |
"HAVE_EM_ASM": true, | |
"HEADLESS": false, | |
"HEAP_BASE": 0, | |
"HTML5_SUPPORT_DEFERRING_USER_SENSITIVE_REQUESTS": true, | |
"IGNORE_CLOSURE_COMPILER_ERRORS": false, | |
"IGNORE_MISSING_MAIN": true, | |
"IMPORTED_MEMORY": false, | |
"INCLUDE_FULL_LIBRARY": false, | |
"INITIAL_MEMORY": 16777216, | |
"INITIAL_TABLE": -1, | |
"INLINING_LIMIT": false, | |
"INVOKE_RUN": true, | |
"IN_TEST_HARNESS": 1, | |
"JS_MATH": false, | |
"LEGACY_GL_EMULATION": false, | |
"LEGACY_RUNTIME": false, | |
"LEGACY_VM_SUPPORT": false, | |
"LEGALIZE_JS_FFI": true, | |
"LIBRARY_DEBUG": false, | |
"LINKABLE": false, | |
"LINK_AS_CXX": true, | |
"LLD_REPORT_UNDEFINED": 1, | |
"LOAD_SOURCE_MAP": false, | |
"LTO": 0, | |
"LZ4": false, | |
"MAIN_MODULE": 0, | |
"MAIN_READS_PARAMS": false, | |
"MALLOC": "dlmalloc", | |
"MAXIMUM_MEMORY": 2147483648, | |
"MAX_WEBGL_VERSION": 1, | |
"MAYBE_WASM2JS": false, | |
"MEMFS_APPEND_TO_TYPED_ARRAYS": 1, | |
"MEMORY64": 0, | |
"MEMORYPROFILER": false, | |
"MEMORY_GROWTH_GEOMETRIC_CAP": 100663296, | |
"MEMORY_GROWTH_GEOMETRIC_STEP": .2, | |
"MEMORY_GROWTH_LINEAR_STEP": -1, | |
"MEMORY_GROWTH_STEP": -1, | |
"MEM_INIT_IN_WASM": true, | |
"MEM_INIT_METHOD": 1, | |
"MINIFY_ASMJS_EXPORT_NAMES": true, | |
"MINIFY_HTML": true, | |
"MINIFY_WASM_IMPORTED_MODULES": false, | |
"MINIFY_WASM_IMPORTS_AND_EXPORTS": false, | |
"MINIMAL_RUNTIME": 0, | |
"MINIMAL_RUNTIME_STREAMING_WASM_COMPILATION": false, | |
"MINIMAL_RUNTIME_STREAMING_WASM_INSTANTIATION": false, | |
"MIN_CHROME_VERSION": 75, | |
"MIN_EDGE_VERSION": 2147483647, | |
"MIN_FIREFOX_VERSION": 65, | |
"MIN_IE_VERSION": 2147483647, | |
"MIN_NODE_VERSION": 101900, | |
"MIN_SAFARI_VERSION": 140100, | |
"MIN_WEBGL_VERSION": 1, | |
"MODULARIZE": false, | |
"NODEJS_CATCH_EXIT": true, | |
"NODEJS_CATCH_REJECTION": true, | |
"NODERAWFS": false, | |
"NODE_CODE_CACHING": false, | |
"OFFSCREENCANVASES_TO_PTHREAD": "#canvas", | |
"OFFSCREENCANVAS_SUPPORT": false, | |
"OFFSCREEN_FRAMEBUFFER": false, | |
"OFFSCREEN_FRAMEBUFFER_FORBID_VAO_PATH": false, | |
"OPENAL_DEBUG": false, | |
"OPT_LEVEL": 0, | |
"PGO": 0, | |
"POLYFILL": true, | |
"POLYFILL_OLD_MATH_FUNCTIONS": 0, | |
"PRECISE_F32": 0, | |
"PRECISE_I64_MATH": 1, | |
"PRINTF_LONG_DOUBLE": false, | |
"PROXY_POSIX_SOCKETS": false, | |
"PROXY_TO_PTHREAD": false, | |
"PROXY_TO_WORKER": false, | |
"PROXY_TO_WORKER_FILENAME": "", | |
"PTHREADS_DEBUG": false, | |
"PTHREADS_PROFILING": false, | |
"PTHREAD_POOL_DELAY_LOAD": false, | |
"PTHREAD_POOL_SIZE": 0, | |
"PTHREAD_POOL_SIZE_STRICT": 1, | |
"PTHREAD_WORKER_FILE": "", | |
"PURE_WASI": false, | |
"QUANTUM_SIZE": 4, | |
"RELOCATABLE": false, | |
"RESERVED_FUNCTION_POINTERS": false, | |
"RETAIN_COMPILER_SETTINGS": 1, | |
"REVERSE_DEPS": "auto", | |
"RUNNING_JS_OPTS": 0, | |
"RUNTIME_DEBUG": 0, | |
"RUNTIME_LOGGING": false, | |
"SAFE_HEAP": 0, | |
"SAFE_HEAP_LOG": false, | |
"SAFE_SPLIT_MEMORY": 0, | |
"SAFE_STACK": 0, | |
"SEPARATE_ASM": 0, | |
"SEPARATE_ASM_MODULE_NAME": "", | |
"SEPARATE_DWARF": false, | |
"SEPARATE_DWARF_URL": "", | |
"SHARED_MEMORY": false, | |
"SHELL_FILE": "", | |
"SHRINK_LEVEL": 0, | |
"SIDE_MODULE": 0, | |
"SIMPLIFY_IFS": 1, | |
"SINGLE_FILE": false, | |
"SKIP_STACK_IN_SMALL": 0, | |
"SMALL_XHR_CHUNKS": false, | |
"SOCKET_DEBUG": false, | |
"SOCKET_WEBRTC": false, | |
"SOURCE_MAP_BASE": "", | |
"SPLIT_MEMORY": 0, | |
"SPLIT_MODULE": false, | |
"STACK_FIRST": true, | |
"STACK_HIGH": 0, | |
"STACK_LOW": 0, | |
"STACK_OVERFLOW_CHECK": 1, | |
"STACK_SIZE": 2097152, | |
"STANDALONE_WASM": false, | |
"STB_IMAGE": false, | |
"STRICT": false, | |
"STRICT_JS": false, | |
"SUPPORTS_GLOBALTHIS": true, | |
"SUPPORT_BASE64_EMBEDDING": false, | |
"SUPPORT_BIG_ENDIAN": false, | |
"SUPPORT_ERRNO": true, | |
"SUPPORT_LONGJMP": "emscripten", | |
"SWAPPABLE_ASM_MODULE": 0, | |
"SYSCALLS_REQUIRE_FILESYSTEM": 0, | |
"SYSCALL_DEBUG": false, | |
"TARGET_BASENAME": "a.out", | |
"TARGET_JS_NAME": "a.out.js", | |
"TARGET_NOT_SUPPORTED": 2147483647, | |
"TEST_MEMORY_GROWTH_FAILS": false, | |
"TEXTDECODER": 1, | |
"TOTAL_MEMORY": 16777216, | |
"TOTAL_STACK": 2097152, | |
"TRACE_WEBGL_CALLS": false, | |
"TRANSPILE_TO_ES5": false, | |
"TRUSTED_TYPES": false, | |
"UBSAN_RUNTIME": 0, | |
"UNALIGNED_MEMORY": 0, | |
"USES_DYNAMIC_ALLOC": true, | |
"USE_ASAN": false, | |
"USE_BOOST_HEADERS": false, | |
"USE_BULLET": false, | |
"USE_BZIP2": false, | |
"USE_CLOSURE_COMPILER": false, | |
"USE_COCOS2D": 0, | |
"USE_ES6_IMPORT_META": true, | |
"USE_FREETYPE": false, | |
"USE_GIFLIB": false, | |
"USE_GLFW": 2, | |
"USE_HARFBUZZ": false, | |
"USE_ICU": false, | |
"USE_LIBJPEG": false, | |
"USE_LIBPNG": false, | |
"USE_LSAN": false, | |
"USE_MODPLUG": false, | |
"USE_MPG123": false, | |
"USE_OFFSET_CONVERTER": false, | |
"USE_OGG": false, | |
"USE_PTHREADS": false, | |
"USE_REGAL": false, | |
"USE_RTTI": true, | |
"USE_SDL": 0, | |
"USE_SDL_GFX": 0, | |
"USE_SDL_IMAGE": 1, | |
"USE_SDL_MIXER": 1, | |
"USE_SDL_NET": 1, | |
"USE_SDL_TTF": 1, | |
"USE_SQLITE3": false, | |
"USE_VORBIS": false, | |
"USE_WEBGL2": false, | |
"USE_WEBGPU": false, | |
"USE_ZLIB": false, | |
"VERBOSE": false, | |
"WARN_ON_UNDEFINED_SYMBOLS": true, | |
"WARN_UNALIGNED": 0, | |
"WASI_MODULE_NAME": "wasi_snapshot_preview1", | |
"WASM": 1, | |
"WASM2C": false, | |
"WASM2C_SANDBOXING": "full", | |
"WASM2JS": false, | |
"WASMFS": false, | |
"WASM_ASYNC_COMPILATION": 0, | |
"WASM_BACKEND": -1, | |
"WASM_BIGINT": false, | |
"WASM_BINARY_FILE": "a.out.wasm", | |
"WASM_EXCEPTIONS": false, | |
"WASM_MEM_MAX": 2147483648, | |
"WASM_OBJECT_FILES": 0, | |
"WASM_WORKERS": 0, | |
"WASM_WORKER_FILE": "", | |
"WEBAUDIO_DEBUG": 0, | |
"WEBGL2_BACKWARDS_COMPATIBILITY_EMULATION": false, | |
"WEBSOCKET_DEBUG": false, | |
"WEBSOCKET_SUBPROTOCOL": "binary", | |
"WEBSOCKET_URL": "ws:#", | |
"WORKAROUND_IOS_9_RIGHT_SHIFT_BUG": 0, | |
"WORKAROUND_OLD_WEBGL_UNIFORM_UPLOAD_IGNORED_OFFSET_BUG": 0, | |
"FOUR_GB": 4294967296, | |
"POINTER_SIZE": 4, | |
"STACK_ALIGN": 16, | |
"GL_POOL_TEMP_BUFFERS_SIZE": 288 | |
}; | |
function getCompilerSetting(name) { | |
if (!(name in compilerSettings)) return "invalid compiler setting: " + name; | |
return compilerSettings[name]; | |
} | |
var ASM_CONSTS = { | |
2142100: () => { | |
globalThis.oldheap = HEAPU8; | |
} | |
}; | |
function ExitStatus(status) { | |
this.name = "ExitStatus"; | |
this.message = "Program terminated with exit(" + status + ")"; | |
this.status = status; | |
} | |
function callRuntimeCallbacks(callbacks) { | |
while (callbacks.length > 0) { | |
callbacks.shift()(Module); | |
} | |
} | |
function getValue(ptr, type = "i8") { | |
if (type.endsWith("*")) type = "*"; | |
switch (type) { | |
case "i1": | |
return HEAP8[ptr >> 0]; | |
case "i8": | |
return HEAP8[ptr >> 0]; | |
case "i16": | |
return HEAP16[ptr >> 1]; | |
case "i32": | |
return HEAP32[ptr >> 2]; | |
case "i64": | |
return HEAP32[ptr >> 2]; | |
case "float": | |
return HEAPF32[ptr >> 2]; | |
case "double": | |
return HEAPF64[ptr >> 3]; | |
case "*": | |
return HEAPU32[ptr >> 2]; | |
default: | |
abort("invalid type for getValue: " + type); | |
} | |
} | |
function ptrToString(ptr) { | |
assert(typeof ptr === "number"); | |
return "0x" + ptr.toString(16).padStart(8, "0"); | |
} | |
function setValue(ptr, value, type = "i8") { | |
if (type.endsWith("*")) type = "*"; | |
switch (type) { | |
case "i1": | |
HEAP8[ptr >> 0] = value; | |
break; | |
case "i8": | |
HEAP8[ptr >> 0] = value; | |
break; | |
case "i16": | |
HEAP16[ptr >> 1] = value; | |
break; | |
case "i32": | |
HEAP32[ptr >> 2] = value; | |
break; | |
case "i64": | |
tempI64 = [ value >>> 0, (tempDouble = value, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], | |
HEAP32[ptr >> 2] = tempI64[0], HEAP32[ptr + 4 >> 2] = tempI64[1]; | |
break; | |
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); | |
} | |
} | |
function warnOnce(text) { | |
if (!warnOnce.shown) warnOnce.shown = {}; | |
if (!warnOnce.shown[text]) { | |
warnOnce.shown[text] = 1; | |
if (ENVIRONMENT_IS_NODE) text = "warning: " + text; | |
err(text); | |
} | |
} | |
function ___assert_fail(condition, filename, line, func) { | |
abort("Assertion failed: " + UTF8ToString(condition) + ", at: " + [ filename ? UTF8ToString(filename) : "unknown filename", line, func ? UTF8ToString(func) : "unknown function" ]); | |
} | |
function ExceptionInfo(excPtr) { | |
this.excPtr = excPtr; | |
this.ptr = excPtr - 24; | |
this.set_type = function(type) { | |
HEAPU32[this.ptr + 4 >> 2] = type; | |
}; | |
this.get_type = function() { | |
return HEAPU32[this.ptr + 4 >> 2]; | |
}; | |
this.set_destructor = function(destructor) { | |
HEAPU32[this.ptr + 8 >> 2] = destructor; | |
}; | |
this.get_destructor = function() { | |
return HEAPU32[this.ptr + 8 >> 2]; | |
}; | |
this.set_refcount = function(refcount) { | |
HEAP32[this.ptr >> 2] = refcount; | |
}; | |
this.set_caught = function(caught) { | |
caught = caught ? 1 : 0; | |
HEAP8[this.ptr + 12 >> 0] = caught; | |
}; | |
this.get_caught = function() { | |
return HEAP8[this.ptr + 12 >> 0] != 0; | |
}; | |
this.set_rethrown = function(rethrown) { | |
rethrown = rethrown ? 1 : 0; | |
HEAP8[this.ptr + 13 >> 0] = rethrown; | |
}; | |
this.get_rethrown = function() { | |
return HEAP8[this.ptr + 13 >> 0] != 0; | |
}; | |
this.init = function(type, destructor) { | |
this.set_adjusted_ptr(0); | |
this.set_type(type); | |
this.set_destructor(destructor); | |
this.set_refcount(0); | |
this.set_caught(false); | |
this.set_rethrown(false); | |
}; | |
this.add_ref = function() { | |
var value = HEAP32[this.ptr >> 2]; | |
HEAP32[this.ptr >> 2] = value + 1; | |
}; | |
this.release_ref = function() { | |
var prev = HEAP32[this.ptr >> 2]; | |
HEAP32[this.ptr >> 2] = prev - 1; | |
assert(prev > 0); | |
return prev === 1; | |
}; | |
this.set_adjusted_ptr = function(adjustedPtr) { | |
HEAPU32[this.ptr + 16 >> 2] = adjustedPtr; | |
}; | |
this.get_adjusted_ptr = function() { | |
return HEAPU32[this.ptr + 16 >> 2]; | |
}; | |
this.get_exception_ptr = function() { | |
var isPointer = ___cxa_is_pointer_type(this.get_type()); | |
if (isPointer) { | |
return HEAPU32[this.excPtr >> 2]; | |
} | |
var adjusted = this.get_adjusted_ptr(); | |
if (adjusted !== 0) return adjusted; | |
return this.excPtr; | |
}; | |
} | |
var exceptionLast = 0; | |
var uncaughtExceptionCount = 0; | |
function ___cxa_throw(ptr, type, destructor) { | |
var info = new ExceptionInfo(ptr); | |
info.init(type, destructor); | |
exceptionLast = ptr; | |
uncaughtExceptionCount++; | |
throw ptr + " - Exception catching is disabled, this exception cannot be caught. Compile with -sNO_DISABLE_EXCEPTION_CATCHING or -sEXCEPTION_CATCHING_ALLOWED=[..] to catch."; | |
} | |
var char_0 = 48; | |
var char_9 = 57; | |
function makeLegalFunctionName(name) { | |
if (undefined === name) { | |
return "_unknown"; | |
} | |
name = name.replace(/[^a-zA-Z0-9_]/g, "$"); | |
var f = name.charCodeAt(0); | |
if (f >= char_0 && f <= char_9) { | |
return "_" + name; | |
} | |
return name; | |
} | |
function createNamedFunction(name, body) { | |
name = makeLegalFunctionName(name); | |
return { | |
[name]: function() { | |
return body.apply(this, arguments); | |
} | |
}[name]; | |
} | |
var emval_handle_array = [ {}, { | |
value: undefined | |
}, { | |
value: null | |
}, { | |
value: true | |
}, { | |
value: false | |
} ]; | |
var emval_free_list = []; | |
function extendError(baseErrorType, errorName) { | |
var errorClass = createNamedFunction(errorName, function(message) { | |
this.name = errorName; | |
this.message = message; | |
var stack = new Error(message).stack; | |
if (stack !== undefined) { | |
this.stack = this.toString() + "\n" + stack.replace(/^Error(:[^\n]*)?\n/, ""); | |
} | |
}); | |
errorClass.prototype = Object.create(baseErrorType.prototype); | |
errorClass.prototype.constructor = errorClass; | |
errorClass.prototype.toString = function() { | |
if (this.message === undefined) { | |
return this.name; | |
} else { | |
return this.name + ": " + this.message; | |
} | |
}; | |
return errorClass; | |
} | |
var BindingError = undefined; | |
function throwBindingError(message) { | |
throw new BindingError(message); | |
} | |
function count_emval_handles() { | |
var count = 0; | |
for (var i = 5; i < emval_handle_array.length; ++i) { | |
if (emval_handle_array[i] !== undefined) { | |
++count; | |
} | |
} | |
return count; | |
} | |
function get_first_emval() { | |
for (var i = 5; i < emval_handle_array.length; ++i) { | |
if (emval_handle_array[i] !== undefined) { | |
return emval_handle_array[i]; | |
} | |
} | |
return null; | |
} | |
function init_emval() { | |
Module["count_emval_handles"] = count_emval_handles; | |
Module["get_first_emval"] = get_first_emval; | |
} | |
var Emval = { | |
toValue: handle => { | |
if (!handle) { | |
throwBindingError("Cannot use deleted val. handle = " + handle); | |
} | |
return emval_handle_array[handle].value; | |
}, | |
toHandle: value => { | |
switch (value) { | |
case undefined: | |
return 1; | |
case null: | |
return 2; | |
case true: | |
return 3; | |
case false: | |
return 4; | |
default: | |
{ | |
var handle = emval_free_list.length ? emval_free_list.pop() : emval_handle_array.length; | |
emval_handle_array[handle] = { | |
refcount: 1, | |
value: value | |
}; | |
return handle; | |
} | |
} | |
} | |
}; | |
var PureVirtualError = undefined; | |
function embind_init_charCodes() { | |
var codes = new Array(256); | |
for (var i = 0; i < 256; ++i) { | |
codes[i] = String.fromCharCode(i); | |
} | |
embind_charCodes = codes; | |
} | |
var embind_charCodes = undefined; | |
function readLatin1String(ptr) { | |
var ret = ""; | |
var c = ptr; | |
while (HEAPU8[c]) { | |
ret += embind_charCodes[HEAPU8[c++]]; | |
} | |
return ret; | |
} | |
function getInheritedInstanceCount() { | |
return Object.keys(registeredInstances).length; | |
} | |
function getLiveInheritedInstances() { | |
var rv = []; | |
for (var k in registeredInstances) { | |
if (registeredInstances.hasOwnProperty(k)) { | |
rv.push(registeredInstances[k]); | |
} | |
} | |
return rv; | |
} | |
var deletionQueue = []; | |
function flushPendingDeletes() { | |
while (deletionQueue.length) { | |
var obj = deletionQueue.pop(); | |
obj.$$.deleteScheduled = false; | |
obj["delete"](); | |
} | |
} | |
var delayFunction = undefined; | |
function setDelayFunction(fn) { | |
delayFunction = fn; | |
if (deletionQueue.length && delayFunction) { | |
delayFunction(flushPendingDeletes); | |
} | |
} | |
function init_embind() { | |
Module["getInheritedInstanceCount"] = getInheritedInstanceCount; | |
Module["getLiveInheritedInstances"] = getLiveInheritedInstances; | |
Module["flushPendingDeletes"] = flushPendingDeletes; | |
Module["setDelayFunction"] = setDelayFunction; | |
Module["ASSERTIONS"] = true; | |
Module["EMBIND_STD_STRING_IS_UTF8"] = true; | |
} | |
var registeredInstances = {}; | |
function getBasestPointer(class_, ptr) { | |
if (ptr === undefined) { | |
throwBindingError("ptr should not be undefined"); | |
} | |
while (class_.baseClass) { | |
ptr = class_.upcast(ptr); | |
class_ = class_.baseClass; | |
} | |
return ptr; | |
} | |
function registerInheritedInstance(class_, ptr, instance) { | |
ptr = getBasestPointer(class_, ptr); | |
if (registeredInstances.hasOwnProperty(ptr)) { | |
throwBindingError("Tried to register registered instance: " + ptr); | |
} else { | |
registeredInstances[ptr] = instance; | |
} | |
} | |
var registeredTypes = {}; | |
function getTypeName(type) { | |
var ptr = ___getTypeName(type); | |
var rv = readLatin1String(ptr); | |
_free(ptr); | |
return rv; | |
} | |
function requireRegisteredType(rawType, humanName) { | |
var impl = registeredTypes[rawType]; | |
if (undefined === impl) { | |
throwBindingError(humanName + " has unknown type " + getTypeName(rawType)); | |
} | |
return impl; | |
} | |
function unregisterInheritedInstance(class_, ptr) { | |
ptr = getBasestPointer(class_, ptr); | |
if (registeredInstances.hasOwnProperty(ptr)) { | |
delete registeredInstances[ptr]; | |
} else { | |
throwBindingError("Tried to unregister unregistered instance: " + ptr); | |
} | |
} | |
function detachFinalizer(handle) {} | |
var finalizationRegistry = false; | |
function runDestructor($$) { | |
if ($$.smartPtr) { | |
$$.smartPtrType.rawDestructor($$.smartPtr); | |
} else { | |
$$.ptrType.registeredClass.rawDestructor($$.ptr); | |
} | |
} | |
function releaseClassHandle($$) { | |
$$.count.value -= 1; | |
var toDelete = 0 === $$.count.value; | |
if (toDelete) { | |
runDestructor($$); | |
} | |
} | |
function downcastPointer(ptr, ptrClass, desiredClass) { | |
if (ptrClass === desiredClass) { | |
return ptr; | |
} | |
if (undefined === desiredClass.baseClass) { | |
return null; | |
} | |
var rv = downcastPointer(ptr, ptrClass, desiredClass.baseClass); | |
if (rv === null) { | |
return null; | |
} | |
return desiredClass.downcast(rv); | |
} | |
var registeredPointers = {}; | |
function getInheritedInstance(class_, ptr) { | |
ptr = getBasestPointer(class_, ptr); | |
return registeredInstances[ptr]; | |
} | |
var InternalError = undefined; | |
function throwInternalError(message) { | |
throw new InternalError(message); | |
} | |
function makeClassHandle(prototype, record) { | |
if (!record.ptrType || !record.ptr) { | |
throwInternalError("makeClassHandle requires ptr and ptrType"); | |
} | |
var hasSmartPtrType = !!record.smartPtrType; | |
var hasSmartPtr = !!record.smartPtr; | |
if (hasSmartPtrType !== hasSmartPtr) { | |
throwInternalError("Both smartPtrType and smartPtr must be specified"); | |
} | |
record.count = { | |
value: 1 | |
}; | |
return attachFinalizer(Object.create(prototype, { | |
$$: { | |
value: record | |
} | |
})); | |
} | |
function RegisteredPointer_fromWireType(ptr) { | |
var rawPointer = this.getPointee(ptr); | |
if (!rawPointer) { | |
this.destructor(ptr); | |
return null; | |
} | |
var registeredInstance = getInheritedInstance(this.registeredClass, rawPointer); | |
if (undefined !== registeredInstance) { | |
if (0 === registeredInstance.$$.count.value) { | |
registeredInstance.$$.ptr = rawPointer; | |
registeredInstance.$$.smartPtr = ptr; | |
return registeredInstance["clone"](); | |
} else { | |
var rv = registeredInstance["clone"](); | |
this.destructor(ptr); | |
return rv; | |
} | |
} | |
function makeDefaultHandle() { | |
if (this.isSmartPointer) { | |
return makeClassHandle(this.registeredClass.instancePrototype, { | |
ptrType: this.pointeeType, | |
ptr: rawPointer, | |
smartPtrType: this, | |
smartPtr: ptr | |
}); | |
} else { | |
return makeClassHandle(this.registeredClass.instancePrototype, { | |
ptrType: this, | |
ptr: ptr | |
}); | |
} | |
} | |
var actualType = this.registeredClass.getActualType(rawPointer); | |
var registeredPointerRecord = registeredPointers[actualType]; | |
if (!registeredPointerRecord) { | |
return makeDefaultHandle.call(this); | |
} | |
var toType; | |
if (this.isConst) { | |
toType = registeredPointerRecord.constPointerType; | |
} else { | |
toType = registeredPointerRecord.pointerType; | |
} | |
var dp = downcastPointer(rawPointer, this.registeredClass, toType.registeredClass); | |
if (dp === null) { | |
return makeDefaultHandle.call(this); | |
} | |
if (this.isSmartPointer) { | |
return makeClassHandle(toType.registeredClass.instancePrototype, { | |
ptrType: toType, | |
ptr: dp, | |
smartPtrType: this, | |
smartPtr: ptr | |
}); | |
} else { | |
return makeClassHandle(toType.registeredClass.instancePrototype, { | |
ptrType: toType, | |
ptr: dp | |
}); | |
} | |
} | |
function attachFinalizer(handle) { | |
if ("undefined" === typeof FinalizationRegistry) { | |
attachFinalizer = handle => handle; | |
return handle; | |
} | |
finalizationRegistry = new FinalizationRegistry(info => { | |
console.warn(info.leakWarning.stack.replace(/^Error: /, "")); | |
releaseClassHandle(info.$$); | |
}); | |
attachFinalizer = handle => { | |
var $$ = handle.$$; | |
var hasSmartPtr = !!$$.smartPtr; | |
if (hasSmartPtr) { | |
var info = { | |
$$: $$ | |
}; | |
var cls = $$.ptrType.registeredClass; | |
info.leakWarning = new Error("Embind found a leaked C++ instance " + cls.name + " <" + ptrToString($$.ptr) + ">.\n" + "We'll free it automatically in this case, but this functionality is not reliable across various environments.\n" + "Make sure to invoke .delete() manually once you're done with the instance instead.\n" + "Originally allocated"); | |
if ("captureStackTrace" in Error) { | |
Error.captureStackTrace(info.leakWarning, RegisteredPointer_fromWireType); | |
} | |
finalizationRegistry.register(handle, info, handle); | |
} | |
return handle; | |
}; | |
detachFinalizer = handle => finalizationRegistry.unregister(handle); | |
return attachFinalizer(handle); | |
} | |
function __embind_create_inheriting_constructor(constructorName, wrapperType, properties) { | |
constructorName = readLatin1String(constructorName); | |
wrapperType = requireRegisteredType(wrapperType, "wrapper"); | |
properties = Emval.toValue(properties); | |
var arraySlice = [].slice; | |
var registeredClass = wrapperType.registeredClass; | |
var wrapperPrototype = registeredClass.instancePrototype; | |
var baseClass = registeredClass.baseClass; | |
var baseClassPrototype = baseClass.instancePrototype; | |
var baseConstructor = registeredClass.baseClass.constructor; | |
var ctor = createNamedFunction(constructorName, function() { | |
registeredClass.baseClass.pureVirtualFunctions.forEach(function(name) { | |
if (this[name] === baseClassPrototype[name]) { | |
throw new PureVirtualError("Pure virtual function " + name + " must be implemented in JavaScript"); | |
} | |
}.bind(this)); | |
Object.defineProperty(this, "__parent", { | |
value: wrapperPrototype | |
}); | |
this["__construct"].apply(this, arraySlice.call(arguments)); | |
}); | |
wrapperPrototype["__construct"] = function __construct() { | |
if (this === wrapperPrototype) { | |
throwBindingError("Pass correct 'this' to __construct"); | |
} | |
var inner = baseConstructor["implement"].apply(undefined, [ this ].concat(arraySlice.call(arguments))); | |
detachFinalizer(inner); | |
var $$ = inner.$$; | |
inner["notifyOnDestruction"](); | |
$$.preservePointerOnDelete = true; | |
Object.defineProperties(this, { | |
$$: { | |
value: $$ | |
} | |
}); | |
attachFinalizer(this); | |
registerInheritedInstance(registeredClass, $$.ptr, this); | |
}; | |
wrapperPrototype["__destruct"] = function __destruct() { | |
if (this === wrapperPrototype) { | |
throwBindingError("Pass correct 'this' to __destruct"); | |
} | |
detachFinalizer(this); | |
unregisterInheritedInstance(registeredClass, this.$$.ptr); | |
}; | |
ctor.prototype = Object.create(wrapperPrototype); | |
for (var p in properties) { | |
ctor.prototype[p] = properties[p]; | |
} | |
return Emval.toHandle(ctor); | |
} | |
var tupleRegistrations = {}; | |
function runDestructors(destructors) { | |
while (destructors.length) { | |
var ptr = destructors.pop(); | |
var del = destructors.pop(); | |
del(ptr); | |
} | |
} | |
function simpleReadValueFromPointer(pointer) { | |
return this["fromWireType"](HEAP32[pointer >> 2]); | |
} | |
var awaitingDependencies = {}; | |
var typeDependencies = {}; | |
function whenDependentTypesAreResolved(myTypes, dependentTypes, getTypeConverters) { | |
myTypes.forEach(function(type) { | |
typeDependencies[type] = dependentTypes; | |
}); | |
function onComplete(typeConverters) { | |
var myTypeConverters = getTypeConverters(typeConverters); | |
if (myTypeConverters.length !== myTypes.length) { | |
throwInternalError("Mismatched type converter count"); | |
} | |
for (var i = 0; i < myTypes.length; ++i) { | |
registerType(myTypes[i], myTypeConverters[i]); | |
} | |
} | |
var typeConverters = new Array(dependentTypes.length); | |
var unregisteredTypes = []; | |
var registered = 0; | |
dependentTypes.forEach((dt, i) => { | |
if (registeredTypes.hasOwnProperty(dt)) { | |
typeConverters[i] = registeredTypes[dt]; | |
} else { | |
unregisteredTypes.push(dt); | |
if (!awaitingDependencies.hasOwnProperty(dt)) { | |
awaitingDependencies[dt] = []; | |
} | |
awaitingDependencies[dt].push(() => { | |
typeConverters[i] = registeredTypes[dt]; | |
++registered; | |
if (registered === unregisteredTypes.length) { | |
onComplete(typeConverters); | |
} | |
}); | |
} | |
}); | |
if (0 === unregisteredTypes.length) { | |
onComplete(typeConverters); | |
} | |
} | |
function __embind_finalize_value_array(rawTupleType) { | |
var reg = tupleRegistrations[rawTupleType]; | |
delete tupleRegistrations[rawTupleType]; | |
var elements = reg.elements; | |
var elementsLength = elements.length; | |
var elementTypes = elements.map(function(elt) { | |
return elt.getterReturnType; | |
}).concat(elements.map(function(elt) { | |
return elt.setterArgumentType; | |
})); | |
var rawConstructor = reg.rawConstructor; | |
var rawDestructor = reg.rawDestructor; | |
whenDependentTypesAreResolved([ rawTupleType ], elementTypes, function(elementTypes) { | |
elements.forEach((elt, i) => { | |
var getterReturnType = elementTypes[i]; | |
var getter = elt.getter; | |
var getterContext = elt.getterContext; | |
var setterArgumentType = elementTypes[i + elementsLength]; | |
var setter = elt.setter; | |
var setterContext = elt.setterContext; | |
elt.read = ptr => { | |
return getterReturnType["fromWireType"](getter(getterContext, ptr)); | |
}; | |
elt.write = (ptr, o) => { | |
var destructors = []; | |
setter(setterContext, ptr, setterArgumentType["toWireType"](destructors, o)); | |
runDestructors(destructors); | |
}; | |
}); | |
return [ { | |
name: reg.name, | |
"fromWireType": function(ptr) { | |
var rv = new Array(elementsLength); | |
for (var i = 0; i < elementsLength; ++i) { | |
rv[i] = elements[i].read(ptr); | |
} | |
rawDestructor(ptr); | |
return rv; | |
}, | |
"toWireType": function(destructors, o) { | |
if (elementsLength !== o.length) { | |
throw new TypeError("Incorrect number of tuple elements for " + reg.name + ": expected=" + elementsLength + ", actual=" + o.length); | |
} | |
var ptr = rawConstructor(); | |
for (var i = 0; i < elementsLength; ++i) { | |
elements[i].write(ptr, o[i]); | |
} | |
if (destructors !== null) { | |
destructors.push(rawDestructor, ptr); | |
} | |
return ptr; | |
}, | |
"argPackAdvance": 8, | |
"readValueFromPointer": simpleReadValueFromPointer, | |
destructorFunction: rawDestructor | |
} ]; | |
}); | |
} | |
var structRegistrations = {}; | |
function __embind_finalize_value_object(structType) { | |
var reg = structRegistrations[structType]; | |
delete structRegistrations[structType]; | |
var rawConstructor = reg.rawConstructor; | |
var rawDestructor = reg.rawDestructor; | |
var fieldRecords = reg.fields; | |
var fieldTypes = fieldRecords.map(field => field.getterReturnType).concat(fieldRecords.map(field => field.setterArgumentType)); | |
whenDependentTypesAreResolved([ structType ], fieldTypes, fieldTypes => { | |
var fields = {}; | |
fieldRecords.forEach((field, i) => { | |
var fieldName = field.fieldName; | |
var getterReturnType = fieldTypes[i]; | |
var getter = field.getter; | |
var getterContext = field.getterContext; | |
var setterArgumentType = fieldTypes[i + fieldRecords.length]; | |
var setter = field.setter; | |
var setterContext = field.setterContext; | |
fields[fieldName] = { | |
read: ptr => { | |
return getterReturnType["fromWireType"](getter(getterContext, ptr)); | |
}, | |
write: (ptr, o) => { | |
var destructors = []; | |
setter(setterContext, ptr, setterArgumentType["toWireType"](destructors, o)); | |
runDestructors(destructors); | |
} | |
}; | |
}); | |
return [ { | |
name: reg.name, | |
"fromWireType": function(ptr) { | |
var rv = {}; | |
for (var i in fields) { | |
rv[i] = fields[i].read(ptr); | |
} | |
rawDestructor(ptr); | |
return rv; | |
}, | |
"toWireType": function(destructors, o) { | |
for (var fieldName in fields) { | |
if (!(fieldName in o)) { | |
throw new TypeError('Missing field: "' + fieldName + '"'); | |
} | |
} | |
var ptr = rawConstructor(); | |
for (fieldName in fields) { | |
fields[fieldName].write(ptr, o[fieldName]); | |
} | |
if (destructors !== null) { | |
destructors.push(rawDestructor, ptr); | |
} | |
return ptr; | |
}, | |
"argPackAdvance": 8, | |
"readValueFromPointer": simpleReadValueFromPointer, | |
destructorFunction: rawDestructor | |
} ]; | |
}); | |
} | |
function __embind_register_bigint(primitiveType, name, size, minRange, maxRange) {} | |
function getShiftFromSize(size) { | |
switch (size) { | |
case 1: | |
return 0; | |
case 2: | |
return 1; | |
case 4: | |
return 2; | |
case 8: | |
return 3; | |
default: | |
throw new TypeError("Unknown type size: " + size); | |
} | |
} | |
function registerType(rawType, registeredInstance, options = {}) { | |
if (!("argPackAdvance" in registeredInstance)) { | |
throw new TypeError("registerType registeredInstance requires argPackAdvance"); | |
} | |
var name = registeredInstance.name; | |
if (!rawType) { | |
throwBindingError('type "' + name + '" must have a positive integer typeid pointer'); | |
} | |
if (registeredTypes.hasOwnProperty(rawType)) { | |
if (options.ignoreDuplicateRegistrations) { | |
return; | |
} else { | |
throwBindingError("Cannot register type '" + name + "' twice"); | |
} | |
} | |
registeredTypes[rawType] = registeredInstance; | |
delete typeDependencies[rawType]; | |
if (awaitingDependencies.hasOwnProperty(rawType)) { | |
var callbacks = awaitingDependencies[rawType]; | |
delete awaitingDependencies[rawType]; | |
callbacks.forEach(cb => cb()); | |
} | |
} | |
function __embind_register_bool(rawType, name, size, trueValue, falseValue) { | |
var shift = getShiftFromSize(size); | |
name = readLatin1String(name); | |
registerType(rawType, { | |
name: name, | |
"fromWireType": function(wt) { | |
return !!wt; | |
}, | |
"toWireType": function(destructors, o) { | |
return o ? trueValue : falseValue; | |
}, | |
"argPackAdvance": 8, | |
"readValueFromPointer": function(pointer) { | |
var heap; | |
if (size === 1) { | |
heap = HEAP8; | |
} else if (size === 2) { | |
heap = HEAP16; | |
} else if (size === 4) { | |
heap = HEAP32; | |
} else { | |
throw new TypeError("Unknown boolean type size: " + name); | |
} | |
return this["fromWireType"](heap[pointer >> shift]); | |
}, | |
destructorFunction: null | |
}); | |
} | |
function ClassHandle_isAliasOf(other) { | |
if (!(this instanceof ClassHandle)) { | |
return false; | |
} | |
if (!(other instanceof ClassHandle)) { | |
return false; | |
} | |
var leftClass = this.$$.ptrType.registeredClass; | |
var left = this.$$.ptr; | |
var rightClass = other.$$.ptrType.registeredClass; | |
var right = other.$$.ptr; | |
while (leftClass.baseClass) { | |
left = leftClass.upcast(left); | |
leftClass = leftClass.baseClass; | |
} | |
while (rightClass.baseClass) { | |
right = rightClass.upcast(right); | |
rightClass = rightClass.baseClass; | |
} | |
return leftClass === rightClass && left === right; | |
} | |
function shallowCopyInternalPointer(o) { | |
return { | |
count: o.count, | |
deleteScheduled: o.deleteScheduled, | |
preservePointerOnDelete: o.preservePointerOnDelete, | |
ptr: o.ptr, | |
ptrType: o.ptrType, | |
smartPtr: o.smartPtr, | |
smartPtrType: o.smartPtrType | |
}; | |
} | |
function throwInstanceAlreadyDeleted(obj) { | |
function getInstanceTypeName(handle) { | |
return handle.$$.ptrType.registeredClass.name; | |
} | |
throwBindingError(getInstanceTypeName(obj) + " instance already deleted"); | |
} | |
function ClassHandle_clone() { | |
if (!this.$$.ptr) { | |
throwInstanceAlreadyDeleted(this); | |
} | |
if (this.$$.preservePointerOnDelete) { | |
this.$$.count.value += 1; | |
return this; | |
} else { | |
var clone = attachFinalizer(Object.create(Object.getPrototypeOf(this), { | |
$$: { | |
value: shallowCopyInternalPointer(this.$$) | |
} | |
})); | |
clone.$$.count.value += 1; | |
clone.$$.deleteScheduled = false; | |
return clone; | |
} | |
} | |
function ClassHandle_delete() { | |
if (!this.$$.ptr) { | |
throwInstanceAlreadyDeleted(this); | |
} | |
if (this.$$.deleteScheduled && !this.$$.preservePointerOnDelete) { | |
throwBindingError("Object already scheduled for deletion"); | |
} | |
detachFinalizer(this); | |
releaseClassHandle(this.$$); | |
if (!this.$$.preservePointerOnDelete) { | |
this.$$.smartPtr = undefined; | |
this.$$.ptr = undefined; | |
} | |
} | |
function ClassHandle_isDeleted() { | |
return !this.$$.ptr; | |
} | |
function ClassHandle_deleteLater() { | |
if (!this.$$.ptr) { | |
throwInstanceAlreadyDeleted(this); | |
} | |
if (this.$$.deleteScheduled && !this.$$.preservePointerOnDelete) { | |
throwBindingError("Object already scheduled for deletion"); | |
} | |
deletionQueue.push(this); | |
if (deletionQueue.length === 1 && delayFunction) { | |
delayFunction(flushPendingDeletes); | |
} | |
this.$$.deleteScheduled = true; | |
return this; | |
} | |
function init_ClassHandle() { | |
ClassHandle.prototype["isAliasOf"] = ClassHandle_isAliasOf; | |
ClassHandle.prototype["clone"] = ClassHandle_clone; | |
ClassHandle.prototype["delete"] = ClassHandle_delete; | |
ClassHandle.prototype["isDeleted"] = ClassHandle_isDeleted; | |
ClassHandle.prototype["deleteLater"] = ClassHandle_deleteLater; | |
} | |
function ClassHandle() {} | |
function ensureOverloadTable(proto, methodName, humanName) { | |
if (undefined === proto[methodName].overloadTable) { | |
var prevFunc = proto[methodName]; | |
proto[methodName] = function() { | |
if (!proto[methodName].overloadTable.hasOwnProperty(arguments.length)) { | |
throwBindingError("Function '" + humanName + "' called with an invalid number of arguments (" + arguments.length + ") - expects one of (" + proto[methodName].overloadTable + ")!"); | |
} | |
return proto[methodName].overloadTable[arguments.length].apply(this, arguments); | |
}; | |
proto[methodName].overloadTable = []; | |
proto[methodName].overloadTable[prevFunc.argCount] = prevFunc; | |
} | |
} | |
function exposePublicSymbol(name, value, numArguments) { | |
if (Module.hasOwnProperty(name)) { | |
if (undefined === numArguments || undefined !== Module[name].overloadTable && undefined !== Module[name].overloadTable[numArguments]) { | |
throwBindingError("Cannot register public name '" + name + "' twice"); | |
} | |
ensureOverloadTable(Module, name, name); | |
if (Module.hasOwnProperty(numArguments)) { | |
throwBindingError("Cannot register multiple overloads of a function with the same number of arguments (" + numArguments + ")!"); | |
} | |
Module[name].overloadTable[numArguments] = value; | |
} else { | |
Module[name] = value; | |
if (undefined !== numArguments) { | |
Module[name].numArguments = numArguments; | |
} | |
} | |
} | |
function RegisteredClass(name, constructor, instancePrototype, rawDestructor, baseClass, getActualType, upcast, downcast) { | |
this.name = name; | |
this.constructor = constructor; | |
this.instancePrototype = instancePrototype; | |
this.rawDestructor = rawDestructor; | |
this.baseClass = baseClass; | |
this.getActualType = getActualType; | |
this.upcast = upcast; | |
this.downcast = downcast; | |
this.pureVirtualFunctions = []; | |
} | |
function upcastPointer(ptr, ptrClass, desiredClass) { | |
while (ptrClass !== desiredClass) { | |
if (!ptrClass.upcast) { | |
throwBindingError("Expected null or instance of " + desiredClass.name + ", got an instance of " + ptrClass.name); | |
} | |
ptr = ptrClass.upcast(ptr); | |
ptrClass = ptrClass.baseClass; | |
} | |
return ptr; | |
} | |
function constNoSmartPtrRawPointerToWireType(destructors, handle) { | |
if (handle === null) { | |
if (this.isReference) { | |
throwBindingError("null is not a valid " + this.name); | |
} | |
return 0; | |
} | |
if (!handle.$$) { | |
throwBindingError('Cannot pass "' + embindRepr(handle) + '" as a ' + this.name); | |
} | |
if (!handle.$$.ptr) { | |
throwBindingError("Cannot pass deleted object as a pointer of type " + this.name); | |
} | |
var handleClass = handle.$$.ptrType.registeredClass; | |
var ptr = upcastPointer(handle.$$.ptr, handleClass, this.registeredClass); | |
return ptr; | |
} | |
function genericPointerToWireType(destructors, handle) { | |
var ptr; | |
if (handle === null) { | |
if (this.isReference) { | |
throwBindingError("null is not a valid " + this.name); | |
} | |
if (this.isSmartPointer) { | |
ptr = this.rawConstructor(); | |
if (destructors !== null) { | |
destructors.push(this.rawDestructor, ptr); | |
} | |
return ptr; | |
} else { | |
return 0; | |
} | |
} | |
if (!handle.$$) { | |
throwBindingError('Cannot pass "' + embindRepr(handle) + '" as a ' + this.name); | |
} | |
if (!handle.$$.ptr) { | |
throwBindingError("Cannot pass deleted object as a pointer of type " + this.name); | |
} | |
if (!this.isConst && handle.$$.ptrType.isConst) { | |
throwBindingError("Cannot convert argument of type " + (handle.$$.smartPtrType ? handle.$$.smartPtrType.name : handle.$$.ptrType.name) + " to parameter type " + this.name); | |
} | |
var handleClass = handle.$$.ptrType.registeredClass; | |
ptr = upcastPointer(handle.$$.ptr, handleClass, this.registeredClass); | |
if (this.isSmartPointer) { | |
if (undefined === handle.$$.smartPtr) { | |
throwBindingError("Passing raw pointer to smart pointer is illegal"); | |
} | |
switch (this.sharingPolicy) { | |
case 0: | |
if (handle.$$.smartPtrType === this) { | |
ptr = handle.$$.smartPtr; | |
} else { | |
throwBindingError("Cannot convert argument of type " + (handle.$$.smartPtrType ? handle.$$.smartPtrType.name : handle.$$.ptrType.name) + " to parameter type " + this.name); | |
} | |
break; | |
case 1: | |
ptr = handle.$$.smartPtr; | |
break; | |
case 2: | |
if (handle.$$.smartPtrType === this) { | |
ptr = handle.$$.smartPtr; | |
} else { | |
var clonedHandle = handle["clone"](); | |
ptr = this.rawShare(ptr, Emval.toHandle(function() { | |
clonedHandle["delete"](); | |
})); | |
if (destructors !== null) { | |
destructors.push(this.rawDestructor, ptr); | |
} | |
} | |
break; | |
default: | |
throwBindingError("Unsupporting sharing policy"); | |
} | |
} | |
return ptr; | |
} | |
function nonConstNoSmartPtrRawPointerToWireType(destructors, handle) { | |
if (handle === null) { | |
if (this.isReference) { | |
throwBindingError("null is not a valid " + this.name); | |
} | |
return 0; | |
} | |
if (!handle.$$) { | |
throwBindingError('Cannot pass "' + embindRepr(handle) + '" as a ' + this.name); | |
} | |
if (!handle.$$.ptr) { | |
throwBindingError("Cannot pass deleted object as a pointer of type " + this.name); | |
} | |
if (handle.$$.ptrType.isConst) { | |
throwBindingError("Cannot convert argument of type " + handle.$$.ptrType.name + " to parameter type " + this.name); | |
} | |
var handleClass = handle.$$.ptrType.registeredClass; | |
var ptr = upcastPointer(handle.$$.ptr, handleClass, this.registeredClass); | |
return ptr; | |
} | |
function RegisteredPointer_getPointee(ptr) { | |
if (this.rawGetPointee) { | |
ptr = this.rawGetPointee(ptr); | |
} | |
return ptr; | |
} | |
function RegisteredPointer_destructor(ptr) { | |
if (this.rawDestructor) { | |
this.rawDestructor(ptr); | |
} | |
} | |
function RegisteredPointer_deleteObject(handle) { | |
if (handle !== null) { | |
handle["delete"](); | |
} | |
} | |
function init_RegisteredPointer() { | |
RegisteredPointer.prototype.getPointee = RegisteredPointer_getPointee; | |
RegisteredPointer.prototype.destructor = RegisteredPointer_destructor; | |
RegisteredPointer.prototype["argPackAdvance"] = 8; | |
RegisteredPointer.prototype["readValueFromPointer"] = simpleReadValueFromPointer; | |
RegisteredPointer.prototype["deleteObject"] = RegisteredPointer_deleteObject; | |
RegisteredPointer.prototype["fromWireType"] = RegisteredPointer_fromWireType; | |
} | |
function RegisteredPointer(name, registeredClass, isReference, isConst, isSmartPointer, pointeeType, sharingPolicy, rawGetPointee, rawConstructor, rawShare, rawDestructor) { | |
this.name = name; | |
this.registeredClass = registeredClass; | |
this.isReference = isReference; | |
this.isConst = isConst; | |
this.isSmartPointer = isSmartPointer; | |
this.pointeeType = pointeeType; | |
this.sharingPolicy = sharingPolicy; | |
this.rawGetPointee = rawGetPointee; | |
this.rawConstructor = rawConstructor; | |
this.rawShare = rawShare; | |
this.rawDestructor = rawDestructor; | |
if (!isSmartPointer && registeredClass.baseClass === undefined) { | |
if (isConst) { | |
this["toWireType"] = constNoSmartPtrRawPointerToWireType; | |
this.destructorFunction = null; | |
} else { | |
this["toWireType"] = nonConstNoSmartPtrRawPointerToWireType; | |
this.destructorFunction = null; | |
} | |
} else { | |
this["toWireType"] = genericPointerToWireType; | |
} | |
} | |
function replacePublicSymbol(name, value, numArguments) { | |
if (!Module.hasOwnProperty(name)) { | |
throwInternalError("Replacing nonexistant public symbol"); | |
} | |
if (undefined !== Module[name].overloadTable && undefined !== numArguments) { | |
Module[name].overloadTable[numArguments] = value; | |
} else { | |
Module[name] = value; | |
Module[name].argCount = numArguments; | |
} | |
} | |
function dynCallLegacy(sig, ptr, args) { | |
assert("dynCall_" + sig in Module, "bad function pointer type - dynCall function not found for sig '" + sig + "'"); | |
if (args && args.length) { | |
assert(args.length === sig.substring(1).replace(/j/g, "--").length); | |
} else { | |
assert(sig.length == 1); | |
} | |
var f = Module["dynCall_" + sig]; | |
return args && args.length ? f.apply(null, [ ptr ].concat(args)) : f.call(null, ptr); | |
} | |
var wasmTableMirror = []; | |
function 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; | |
} | |
function dynCall(sig, ptr, args) { | |
if (sig.includes("j")) { | |
return dynCallLegacy(sig, ptr, args); | |
} | |
assert(getWasmTableEntry(ptr), "missing table entry in dynCall: " + ptr); | |
var rtn = getWasmTableEntry(ptr).apply(null, args); | |
return rtn; | |
} | |
function getDynCaller(sig, ptr) { | |
assert(sig.includes("j") || sig.includes("p"), "getDynCaller should only be called with i64 sigs"); | |
var argCache = []; | |
return function() { | |
argCache.length = 0; | |
Object.assign(argCache, arguments); | |
return dynCall(sig, ptr, argCache); | |
}; | |
} | |
function embind__requireFunction(signature, rawFunction) { | |
signature = readLatin1String(signature); | |
function makeDynCaller() { | |
if (signature.includes("j")) { | |
return getDynCaller(signature, rawFunction); | |
} | |
return getWasmTableEntry(rawFunction); | |
} | |
var fp = makeDynCaller(); | |
if (typeof fp != "function") { | |
throwBindingError("unknown function pointer with signature " + signature + ": " + rawFunction); | |
} | |
return fp; | |
} | |
var UnboundTypeError = undefined; | |
function throwUnboundTypeError(message, types) { | |
var unboundTypes = []; | |
var seen = {}; | |
function visit(type) { | |
if (seen[type]) { | |
return; | |
} | |
if (registeredTypes[type]) { | |
return; | |
} | |
if (typeDependencies[type]) { | |
typeDependencies[type].forEach(visit); | |
return; | |
} | |
unboundTypes.push(type); | |
seen[type] = true; | |
} | |
types.forEach(visit); | |
throw new UnboundTypeError(message + ": " + unboundTypes.map(getTypeName).join([ ", " ])); | |
} | |
function __embind_register_class(rawType, rawPointerType, rawConstPointerType, baseClassRawType, getActualTypeSignature, getActualType, upcastSignature, upcast, downcastSignature, downcast, name, destructorSignature, rawDestructor) { | |
name = readLatin1String(name); | |
getActualType = embind__requireFunction(getActualTypeSignature, getActualType); | |
if (upcast) { | |
upcast = embind__requireFunction(upcastSignature, upcast); | |
} | |
if (downcast) { | |
downcast = embind__requireFunction(downcastSignature, downcast); | |
} | |
rawDestructor = embind__requireFunction(destructorSignature, rawDestructor); | |
var legalFunctionName = makeLegalFunctionName(name); | |
exposePublicSymbol(legalFunctionName, function() { | |
throwUnboundTypeError("Cannot construct " + name + " due to unbound types", [ baseClassRawType ]); | |
}); | |
whenDependentTypesAreResolved([ rawType, rawPointerType, rawConstPointerType ], baseClassRawType ? [ baseClassRawType ] : [], function(base) { | |
base = base[0]; | |
var baseClass; | |
var basePrototype; | |
if (baseClassRawType) { | |
baseClass = base.registeredClass; | |
basePrototype = baseClass.instancePrototype; | |
} else { | |
basePrototype = ClassHandle.prototype; | |
} | |
var constructor = createNamedFunction(legalFunctionName, function() { | |
if (Object.getPrototypeOf(this) !== instancePrototype) { | |
throw new BindingError("Use 'new' to construct " + name); | |
} | |
if (undefined === registeredClass.constructor_body) { | |
throw new BindingError(name + " has no accessible constructor"); | |
} | |
var body = registeredClass.constructor_body[arguments.length]; | |
if (undefined === body) { | |
throw new BindingError("Tried to invoke ctor of " + name + " with invalid number of parameters (" + arguments.length + ") - expected (" + Object.keys(registeredClass.constructor_body).toString() + ") parameters instead!"); | |
} | |
return body.apply(this, arguments); | |
}); | |
var instancePrototype = Object.create(basePrototype, { | |
constructor: { | |
value: constructor | |
} | |
}); | |
constructor.prototype = instancePrototype; | |
var registeredClass = new RegisteredClass(name, constructor, instancePrototype, rawDestructor, baseClass, getActualType, upcast, downcast); | |
var referenceConverter = new RegisteredPointer(name, registeredClass, true, false, false); | |
var pointerConverter = new RegisteredPointer(name + "*", registeredClass, false, false, false); | |
var constPointerConverter = new RegisteredPointer(name + " const*", registeredClass, false, true, false); | |
registeredPointers[rawType] = { | |
pointerType: pointerConverter, | |
constPointerType: constPointerConverter | |
}; | |
replacePublicSymbol(legalFunctionName, constructor); | |
return [ referenceConverter, pointerConverter, constPointerConverter ]; | |
}); | |
} | |
function new_(constructor, argumentList) { | |
if (!(constructor instanceof Function)) { | |
throw new TypeError("new_ called with constructor type " + typeof constructor + " which is not a function"); | |
} | |
if (constructor === Function) { | |
throw new Error("new_ cannot create a new Function with DYNAMIC_EXECUTION == 0."); | |
} | |
var dummy = createNamedFunction(constructor.name || "unknownFunctionName", function() {}); | |
dummy.prototype = constructor.prototype; | |
var obj = new dummy(); | |
var r = constructor.apply(obj, argumentList); | |
return r instanceof Object ? r : obj; | |
} | |
function craftInvokerFunction(humanName, argTypes, classType, cppInvokerFunc, cppTargetFunc) { | |
var argCount = argTypes.length; | |
if (argCount < 2) { | |
throwBindingError("argTypes array size mismatch! Must at least get return value and 'this' types!"); | |
} | |
var isClassMethodFunc = argTypes[1] !== null && classType !== null; | |
var needsDestructorStack = false; | |
for (var i = 1; i < argTypes.length; ++i) { | |
if (argTypes[i] !== null && argTypes[i].destructorFunction === undefined) { | |
needsDestructorStack = true; | |
break; | |
} | |
} | |
var returns = argTypes[0].name !== "void"; | |
var expectedArgCount = argCount - 2; | |
var argsWired = new Array(expectedArgCount); | |
var invokerFuncArgs = []; | |
var destructors = []; | |
return function() { | |
if (arguments.length !== expectedArgCount) { | |
throwBindingError("function " + humanName + " called with " + arguments.length + " arguments, expected " + expectedArgCount + " args!"); | |
} | |
destructors.length = 0; | |
var thisWired; | |
invokerFuncArgs.length = isClassMethodFunc ? 2 : 1; | |
invokerFuncArgs[0] = cppTargetFunc; | |
if (isClassMethodFunc) { | |
thisWired = argTypes[1]["toWireType"](destructors, this); | |
invokerFuncArgs[1] = thisWired; | |
} | |
for (var i = 0; i < expectedArgCount; ++i) { | |
argsWired[i] = argTypes[i + 2]["toWireType"](destructors, arguments[i]); | |
invokerFuncArgs.push(argsWired[i]); | |
} | |
var rv = cppInvokerFunc.apply(null, invokerFuncArgs); | |
function onDone(rv) { | |
if (needsDestructorStack) { | |
runDestructors(destructors); | |
} else { | |
for (var i = isClassMethodFunc ? 1 : 2; i < argTypes.length; i++) { | |
var param = i === 1 ? thisWired : argsWired[i - 2]; | |
if (argTypes[i].destructorFunction !== null) { | |
argTypes[i].destructorFunction(param); | |
} | |
} | |
} | |
if (returns) { | |
return argTypes[0]["fromWireType"](rv); | |
} | |
} | |
return onDone(rv); | |
}; | |
} | |
function heap32VectorToArray(count, firstElement) { | |
var array = []; | |
for (var i = 0; i < count; i++) { | |
array.push(HEAPU32[firstElement + i * 4 >> 2]); | |
} | |
return array; | |
} | |
function __embind_register_class_class_function(rawClassType, methodName, argCount, rawArgTypesAddr, invokerSignature, rawInvoker, fn) { | |
var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr); | |
methodName = readLatin1String(methodName); | |
rawInvoker = embind__requireFunction(invokerSignature, rawInvoker); | |
whenDependentTypesAreResolved([], [ rawClassType ], function(classType) { | |
classType = classType[0]; | |
var humanName = classType.name + "." + methodName; | |
function unboundTypesHandler() { | |
throwUnboundTypeError("Cannot call " + humanName + " due to unbound types", rawArgTypes); | |
} | |
if (methodName.startsWith("@@")) { | |
methodName = Symbol[methodName.substring(2)]; | |
} | |
var proto = classType.registeredClass.constructor; | |
if (undefined === proto[methodName]) { | |
unboundTypesHandler.argCount = argCount - 1; | |
proto[methodName] = unboundTypesHandler; | |
} else { | |
ensureOverloadTable(proto, methodName, humanName); | |
proto[methodName].overloadTable[argCount - 1] = unboundTypesHandler; | |
} | |
whenDependentTypesAreResolved([], rawArgTypes, function(argTypes) { | |
var invokerArgsArray = [ argTypes[0], null ].concat(argTypes.slice(1)); | |
var func = craftInvokerFunction(humanName, invokerArgsArray, null, rawInvoker, fn); | |
if (undefined === proto[methodName].overloadTable) { | |
func.argCount = argCount - 1; | |
proto[methodName] = func; | |
} else { | |
proto[methodName].overloadTable[argCount - 1] = func; | |
} | |
return []; | |
}); | |
return []; | |
}); | |
} | |
function validateThis(this_, classType, humanName) { | |
if (!(this_ instanceof Object)) { | |
throwBindingError(humanName + ' with invalid "this": ' + this_); | |
} | |
if (!(this_ instanceof classType.registeredClass.constructor)) { | |
throwBindingError(humanName + ' incompatible with "this" of type ' + this_.constructor.name); | |
} | |
if (!this_.$$.ptr) { | |
throwBindingError("cannot call emscripten binding method " + humanName + " on deleted object"); | |
} | |
return upcastPointer(this_.$$.ptr, this_.$$.ptrType.registeredClass, classType.registeredClass); | |
} | |
function __embind_register_class_class_property(rawClassType, fieldName, rawFieldType, rawFieldPtr, getterSignature, getter, setterSignature, setter) { | |
fieldName = readLatin1String(fieldName); | |
getter = embind__requireFunction(getterSignature, getter); | |
whenDependentTypesAreResolved([], [ rawClassType ], function(classType) { | |
classType = classType[0]; | |
var humanName = classType.name + "." + fieldName; | |
var desc = { | |
get: function() { | |
throwUnboundTypeError("Cannot access " + humanName + " due to unbound types", [ rawFieldType ]); | |
}, | |
enumerable: true, | |
configurable: true | |
}; | |
if (setter) { | |
desc.set = () => { | |
throwUnboundTypeError("Cannot access " + humanName + " due to unbound types", [ rawFieldType ]); | |
}; | |
} else { | |
desc.set = v => { | |
throwBindingError(humanName + " is a read-only property"); | |
}; | |
} | |
Object.defineProperty(classType.registeredClass.constructor, fieldName, desc); | |
whenDependentTypesAreResolved([], [ rawFieldType ], function(fieldType) { | |
fieldType = fieldType[0]; | |
var desc = { | |
get: function() { | |
return fieldType["fromWireType"](getter(rawFieldPtr)); | |
}, | |
enumerable: true | |
}; | |
if (setter) { | |
setter = embind__requireFunction(setterSignature, setter); | |
desc.set = v => { | |
var destructors = []; | |
setter(rawFieldPtr, fieldType["toWireType"](destructors, v)); | |
runDestructors(destructors); | |
}; | |
} | |
Object.defineProperty(classType.registeredClass.constructor, fieldName, desc); | |
return []; | |
}); | |
return []; | |
}); | |
} | |
function __embind_register_class_constructor(rawClassType, argCount, rawArgTypesAddr, invokerSignature, invoker, rawConstructor) { | |
assert(argCount > 0); | |
var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr); | |
invoker = embind__requireFunction(invokerSignature, invoker); | |
var args = [ rawConstructor ]; | |
var destructors = []; | |
whenDependentTypesAreResolved([], [ rawClassType ], function(classType) { | |
classType = classType[0]; | |
var humanName = "constructor " + classType.name; | |
if (undefined === classType.registeredClass.constructor_body) { | |
classType.registeredClass.constructor_body = []; | |
} | |
if (undefined !== classType.registeredClass.constructor_body[argCount - 1]) { | |
throw new BindingError("Cannot register multiple constructors with identical number of parameters (" + (argCount - 1) + ") for class '" + classType.name + "'! Overload resolution is currently only performed using the parameter count, not actual type info!"); | |
} | |
classType.registeredClass.constructor_body[argCount - 1] = () => { | |
throwUnboundTypeError("Cannot construct " + classType.name + " due to unbound types", rawArgTypes); | |
}; | |
whenDependentTypesAreResolved([], rawArgTypes, function(argTypes) { | |
argTypes.splice(1, 0, null); | |
classType.registeredClass.constructor_body[argCount - 1] = craftInvokerFunction(humanName, argTypes, null, invoker, rawConstructor); | |
return []; | |
}); | |
return []; | |
}); | |
} | |
function __embind_register_class_function(rawClassType, methodName, argCount, rawArgTypesAddr, invokerSignature, rawInvoker, context, isPureVirtual) { | |
var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr); | |
methodName = readLatin1String(methodName); | |
rawInvoker = embind__requireFunction(invokerSignature, rawInvoker); | |
whenDependentTypesAreResolved([], [ rawClassType ], function(classType) { | |
classType = classType[0]; | |
var humanName = classType.name + "." + methodName; | |
if (methodName.startsWith("@@")) { | |
methodName = Symbol[methodName.substring(2)]; | |
} | |
if (isPureVirtual) { | |
classType.registeredClass.pureVirtualFunctions.push(methodName); | |
} | |
function unboundTypesHandler() { | |
throwUnboundTypeError("Cannot call " + humanName + " due to unbound types", rawArgTypes); | |
} | |
var proto = classType.registeredClass.instancePrototype; | |
var method = proto[methodName]; | |
if (undefined === method || undefined === method.overloadTable && method.className !== classType.name && method.argCount === argCount - 2) { | |
unboundTypesHandler.argCount = argCount - 2; | |
unboundTypesHandler.className = classType.name; | |
proto[methodName] = unboundTypesHandler; | |
} else { | |
ensureOverloadTable(proto, methodName, humanName); | |
proto[methodName].overloadTable[argCount - 2] = unboundTypesHandler; | |
} | |
whenDependentTypesAreResolved([], rawArgTypes, function(argTypes) { | |
var memberFunction = craftInvokerFunction(humanName, argTypes, classType, rawInvoker, context); | |
if (undefined === proto[methodName].overloadTable) { | |
memberFunction.argCount = argCount - 2; | |
proto[methodName] = memberFunction; | |
} else { | |
proto[methodName].overloadTable[argCount - 2] = memberFunction; | |
} | |
return []; | |
}); | |
return []; | |
}); | |
} | |
function __embind_register_class_property(classType, fieldName, getterReturnType, getterSignature, getter, getterContext, setterArgumentType, setterSignature, setter, setterContext) { | |
fieldName = readLatin1String(fieldName); | |
getter = embind__requireFunction(getterSignature, getter); | |
whenDependentTypesAreResolved([], [ classType ], function(classType) { | |
classType = classType[0]; | |
var humanName = classType.name + "." + fieldName; | |
var desc = { | |
get: function() { | |
throwUnboundTypeError("Cannot access " + humanName + " due to unbound types", [ getterReturnType, setterArgumentType ]); | |
}, | |
enumerable: true, | |
configurable: true | |
}; | |
if (setter) { | |
desc.set = () => { | |
throwUnboundTypeError("Cannot access " + humanName + " due to unbound types", [ getterReturnType, setterArgumentType ]); | |
}; | |
} else { | |
desc.set = v => { | |
throwBindingError(humanName + " is a read-only property"); | |
}; | |
} | |
Object.defineProperty(classType.registeredClass.instancePrototype, fieldName, desc); | |
whenDependentTypesAreResolved([], setter ? [ getterReturnType, setterArgumentType ] : [ getterReturnType ], function(types) { | |
var getterReturnType = types[0]; | |
var desc = { | |
get: function() { | |
var ptr = validateThis(this, classType, humanName + " getter"); | |
return getterReturnType["fromWireType"](getter(getterContext, ptr)); | |
}, | |
enumerable: true | |
}; | |
if (setter) { | |
setter = embind__requireFunction(setterSignature, setter); | |
var setterArgumentType = types[1]; | |
desc.set = function(v) { | |
var ptr = validateThis(this, classType, humanName + " setter"); | |
var destructors = []; | |
setter(setterContext, ptr, setterArgumentType["toWireType"](destructors, v)); | |
runDestructors(destructors); | |
}; | |
} | |
Object.defineProperty(classType.registeredClass.instancePrototype, fieldName, desc); | |
return []; | |
}); | |
return []; | |
}); | |
} | |
function __embind_register_constant(name, type, value) { | |
name = readLatin1String(name); | |
whenDependentTypesAreResolved([], [ type ], function(type) { | |
type = type[0]; | |
Module[name] = type["fromWireType"](value); | |
return []; | |
}); | |
} | |
function __emval_decref(handle) { | |
if (handle > 4 && 0 === --emval_handle_array[handle].refcount) { | |
emval_handle_array[handle] = undefined; | |
emval_free_list.push(handle); | |
} | |
} | |
function __embind_register_emval(rawType, name) { | |
name = readLatin1String(name); | |
registerType(rawType, { | |
name: name, | |
"fromWireType": function(handle) { | |
var rv = Emval.toValue(handle); | |
__emval_decref(handle); | |
return rv; | |
}, | |
"toWireType": function(destructors, value) { | |
return Emval.toHandle(value); | |
}, | |
"argPackAdvance": 8, | |
"readValueFromPointer": simpleReadValueFromPointer, | |
destructorFunction: null | |
}); | |
} | |
function enumReadValueFromPointer(name, shift, signed) { | |
switch (shift) { | |
case 0: | |
return function(pointer) { | |
var heap = signed ? HEAP8 : HEAPU8; | |
return this["fromWireType"](heap[pointer]); | |
}; | |
case 1: | |
return function(pointer) { | |
var heap = signed ? HEAP16 : HEAPU16; | |
return this["fromWireType"](heap[pointer >> 1]); | |
}; | |
case 2: | |
return function(pointer) { | |
var heap = signed ? HEAP32 : HEAPU32; | |
return this["fromWireType"](heap[pointer >> 2]); | |
}; | |
default: | |
throw new TypeError("Unknown integer type: " + name); | |
} | |
} | |
function __embind_register_enum(rawType, name, size, isSigned) { | |
var shift = getShiftFromSize(size); | |
name = readLatin1String(name); | |
function ctor() {} | |
ctor.values = {}; | |
registerType(rawType, { | |
name: name, | |
constructor: ctor, | |
"fromWireType": function(c) { | |
return this.constructor.values[c]; | |
}, | |
"toWireType": function(destructors, c) { | |
return c.value; | |
}, | |
"argPackAdvance": 8, | |
"readValueFromPointer": enumReadValueFromPointer(name, shift, isSigned), | |
destructorFunction: null | |
}); | |
exposePublicSymbol(name, ctor); | |
} | |
function __embind_register_enum_value(rawEnumType, name, enumValue) { | |
var enumType = requireRegisteredType(rawEnumType, "enum"); | |
name = readLatin1String(name); | |
var Enum = enumType.constructor; | |
var Value = Object.create(enumType.constructor.prototype, { | |
value: { | |
value: enumValue | |
}, | |
constructor: { | |
value: createNamedFunction(enumType.name + "_" + name, function() {}) | |
} | |
}); | |
Enum.values[enumValue] = Value; | |
Enum[name] = Value; | |
} | |
function embindRepr(v) { | |
if (v === null) { | |
return "null"; | |
} | |
var t = typeof v; | |
if (t === "object" || t === "array" || t === "function") { | |
return v.toString(); | |
} else { | |
return "" + v; | |
} | |
} | |
function floatReadValueFromPointer(name, shift) { | |
switch (shift) { | |
case 2: | |
return function(pointer) { | |
return this["fromWireType"](HEAPF32[pointer >> 2]); | |
}; | |
case 3: | |
return function(pointer) { | |
return this["fromWireType"](HEAPF64[pointer >> 3]); | |
}; | |
default: | |
throw new TypeError("Unknown float type: " + name); | |
} | |
} | |
function __embind_register_float(rawType, name, size) { | |
var shift = getShiftFromSize(size); | |
name = readLatin1String(name); | |
registerType(rawType, { | |
name: name, | |
"fromWireType": function(value) { | |
return value; | |
}, | |
"toWireType": function(destructors, value) { | |
if (typeof value != "number" && typeof value != "boolean") { | |
throw new TypeError('Cannot convert "' + embindRepr(value) + '" to ' + this.name); | |
} | |
return value; | |
}, | |
"argPackAdvance": 8, | |
"readValueFromPointer": floatReadValueFromPointer(name, shift), | |
destructorFunction: null | |
}); | |
} | |
function __embind_register_function(name, argCount, rawArgTypesAddr, signature, rawInvoker, fn) { | |
var argTypes = heap32VectorToArray(argCount, rawArgTypesAddr); | |
name = readLatin1String(name); | |
rawInvoker = embind__requireFunction(signature, rawInvoker); | |
exposePublicSymbol(name, function() { | |
throwUnboundTypeError("Cannot call " + name + " due to unbound types", argTypes); | |
}, argCount - 1); | |
whenDependentTypesAreResolved([], argTypes, function(argTypes) { | |
var invokerArgsArray = [ argTypes[0], null ].concat(argTypes.slice(1)); | |
replacePublicSymbol(name, craftInvokerFunction(name, invokerArgsArray, null, rawInvoker, fn), argCount - 1); | |
return []; | |
}); | |
} | |
function integerReadValueFromPointer(name, shift, signed) { | |
switch (shift) { | |
case 0: | |
return signed ? function readS8FromPointer(pointer) { | |
return HEAP8[pointer]; | |
} : function readU8FromPointer(pointer) { | |
return HEAPU8[pointer]; | |
}; | |
case 1: | |
return signed ? function readS16FromPointer(pointer) { | |
return HEAP16[pointer >> 1]; | |
} : function readU16FromPointer(pointer) { | |
return HEAPU16[pointer >> 1]; | |
}; | |
case 2: | |
return signed ? function readS32FromPointer(pointer) { | |
return HEAP32[pointer >> 2]; | |
} : function readU32FromPointer(pointer) { | |
return HEAPU32[pointer >> 2]; | |
}; | |
default: | |
throw new TypeError("Unknown integer type: " + name); | |
} | |
} | |
function __embind_register_integer(primitiveType, name, size, minRange, maxRange) { | |
name = readLatin1String(name); | |
if (maxRange === -1) { | |
maxRange = 4294967295; | |
} | |
var shift = getShiftFromSize(size); | |
var fromWireType = value => value; | |
if (minRange === 0) { | |
var bitshift = 32 - 8 * size; | |
fromWireType = value => value << bitshift >>> bitshift; | |
} | |
var isUnsignedType = name.includes("unsigned"); | |
var checkAssertions = (value, toTypeName) => { | |
if (typeof value != "number" && typeof value != "boolean") { | |
throw new TypeError('Cannot convert "' + embindRepr(value) + '" to ' + toTypeName); | |
} | |
if (value < minRange || value > maxRange) { | |
throw new TypeError('Passing a number "' + embindRepr(value) + '" from JS side to C/C++ side to an argument of type "' + name + '", which is outside the valid range [' + minRange + ", " + maxRange + "]!"); | |
} | |
}; | |
var toWireType; | |
if (isUnsignedType) { | |
toWireType = function(destructors, value) { | |
checkAssertions(value, this.name); | |
return value >>> 0; | |
}; | |
} else { | |
toWireType = function(destructors, value) { | |
checkAssertions(value, this.name); | |
return value; | |
}; | |
} | |
registerType(primitiveType, { | |
name: name, | |
"fromWireType": fromWireType, | |
"toWireType": toWireType, | |
"argPackAdvance": 8, | |
"readValueFromPointer": integerReadValueFromPointer(name, shift, minRange !== 0), | |
destructorFunction: null | |
}); | |
} | |
function __embind_register_memory_view(rawType, dataTypeIndex, name) { | |
var typeMapping = [ Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array ]; | |
var TA = typeMapping[dataTypeIndex]; | |
function decodeMemoryView(handle) { | |
handle = handle >> 2; | |
var heap = HEAPU32; | |
var size = heap[handle]; | |
var data = heap[handle + 1]; | |
return new TA(heap.buffer, data, size); | |
} | |
name = readLatin1String(name); | |
registerType(rawType, { | |
name: name, | |
"fromWireType": decodeMemoryView, | |
"argPackAdvance": 8, | |
"readValueFromPointer": decodeMemoryView | |
}, { | |
ignoreDuplicateRegistrations: true | |
}); | |
} | |
function __embind_register_smart_ptr(rawType, rawPointeeType, name, sharingPolicy, getPointeeSignature, rawGetPointee, constructorSignature, rawConstructor, shareSignature, rawShare, destructorSignature, rawDestructor) { | |
name = readLatin1String(name); | |
rawGetPointee = embind__requireFunction(getPointeeSignature, rawGetPointee); | |
rawConstructor = embind__requireFunction(constructorSignature, rawConstructor); | |
rawShare = embind__requireFunction(shareSignature, rawShare); | |
rawDestructor = embind__requireFunction(destructorSignature, rawDestructor); | |
whenDependentTypesAreResolved([ rawType ], [ rawPointeeType ], function(pointeeType) { | |
pointeeType = pointeeType[0]; | |
var registeredPointer = new RegisteredPointer(name, pointeeType.registeredClass, false, false, true, pointeeType, sharingPolicy, rawGetPointee, rawConstructor, rawShare, rawDestructor); | |
return [ registeredPointer ]; | |
}); | |
} | |
function __embind_register_std_string(rawType, name) { | |
name = readLatin1String(name); | |
var stdStringIsUTF8 = name === "std::string"; | |
registerType(rawType, { | |
name: name, | |
"fromWireType": function(value) { | |
var length = HEAPU32[value >> 2]; | |
var payload = value + 4; | |
var str; | |
if (stdStringIsUTF8) { | |
var decodeStartPtr = payload; | |
for (var i = 0; i <= length; ++i) { | |
var currentBytePtr = payload + i; | |
if (i == length || HEAPU8[currentBytePtr] == 0) { | |
var maxRead = currentBytePtr - decodeStartPtr; | |
var stringSegment = UTF8ToString(decodeStartPtr, maxRead); | |
if (str === undefined) { | |
str = stringSegment; | |
} else { | |
str += String.fromCharCode(0); | |
str += stringSegment; | |
} | |
decodeStartPtr = currentBytePtr + 1; | |
} | |
} | |
} else { | |
var a = new Array(length); | |
for (var i = 0; i < length; ++i) { | |
a[i] = String.fromCharCode(HEAPU8[payload + i]); | |
} | |
str = a.join(""); | |
} | |
_free(value); | |
return str; | |
}, | |
"toWireType": function(destructors, value) { | |
if (value instanceof ArrayBuffer) { | |
value = new Uint8Array(value); | |
} | |
var length; | |
var valueIsOfTypeString = typeof value == "string"; | |
if (!(valueIsOfTypeString || value instanceof Uint8Array || value instanceof Uint8ClampedArray || value instanceof Int8Array)) { | |
throwBindingError("Cannot pass non-string to std::string"); | |
} | |
if (stdStringIsUTF8 && valueIsOfTypeString) { | |
length = lengthBytesUTF8(value); | |
} else { | |
length = value.length; | |
} | |
var base = _malloc(4 + length + 1); | |
var ptr = base + 4; | |
HEAPU32[base >> 2] = length; | |
if (stdStringIsUTF8 && valueIsOfTypeString) { | |
stringToUTF8(value, ptr, length + 1); | |
} else { | |
if (valueIsOfTypeString) { | |
for (var i = 0; i < length; ++i) { | |
var charCode = value.charCodeAt(i); | |
if (charCode > 255) { | |
_free(ptr); | |
throwBindingError("String has UTF-16 code units that do not fit in 8 bits"); | |
} | |
HEAPU8[ptr + i] = charCode; | |
} | |
} else { | |
for (var i = 0; i < length; ++i) { | |
HEAPU8[ptr + i] = value[i]; | |
} | |
} | |
} | |
if (destructors !== null) { | |
destructors.push(_free, base); | |
} | |
return base; | |
}, | |
"argPackAdvance": 8, | |
"readValueFromPointer": simpleReadValueFromPointer, | |
destructorFunction: function(ptr) { | |
_free(ptr); | |
} | |
}); | |
} | |
var UTF16Decoder = typeof TextDecoder != "undefined" ? new TextDecoder("utf-16le") : undefined; | |
function UTF16ToString(ptr, maxBytesToRead) { | |
assert(ptr % 2 == 0, "Pointer passed to UTF16ToString must be aligned to two bytes!"); | |
var endPtr = ptr; | |
var idx = endPtr >> 1; | |
var maxIdx = idx + maxBytesToRead / 2; | |
while (!(idx >= maxIdx) && HEAPU16[idx]) ++idx; | |
endPtr = idx << 1; | |
if (endPtr - ptr > 32 && UTF16Decoder) return UTF16Decoder.decode(HEAPU8.subarray(ptr, endPtr)); | |
var str = ""; | |
for (var i = 0; !(i >= maxBytesToRead / 2); ++i) { | |
var codeUnit = HEAP16[ptr + i * 2 >> 1]; | |
if (codeUnit == 0) break; | |
str += String.fromCharCode(codeUnit); | |
} | |
return str; | |
} | |
function stringToUTF16(str, outPtr, maxBytesToWrite) { | |
assert(outPtr % 2 == 0, "Pointer passed to stringToUTF16 must be aligned to two bytes!"); | |
assert(typeof maxBytesToWrite == "number", "stringToUTF16(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!"); | |
if (maxBytesToWrite === undefined) { | |
maxBytesToWrite = 2147483647; | |
} | |
if (maxBytesToWrite < 2) return 0; | |
maxBytesToWrite -= 2; | |
var startPtr = outPtr; | |
var numCharsToWrite = maxBytesToWrite < str.length * 2 ? maxBytesToWrite / 2 : str.length; | |
for (var i = 0; i < numCharsToWrite; ++i) { | |
var codeUnit = str.charCodeAt(i); | |
HEAP16[outPtr >> 1] = codeUnit; | |
outPtr += 2; | |
} | |
HEAP16[outPtr >> 1] = 0; | |
return outPtr - startPtr; | |
} | |
function lengthBytesUTF16(str) { | |
return str.length * 2; | |
} | |
function UTF32ToString(ptr, maxBytesToRead) { | |
assert(ptr % 4 == 0, "Pointer passed to UTF32ToString must be aligned to four bytes!"); | |
var i = 0; | |
var str = ""; | |
while (!(i >= maxBytesToRead / 4)) { | |
var utf32 = HEAP32[ptr + i * 4 >> 2]; | |
if (utf32 == 0) break; | |
++i; | |
if (utf32 >= 65536) { | |
var ch = utf32 - 65536; | |
str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023); | |
} else { | |
str += String.fromCharCode(utf32); | |
} | |
} | |
return str; | |
} | |
function stringToUTF32(str, outPtr, maxBytesToWrite) { | |
assert(outPtr % 4 == 0, "Pointer passed to stringToUTF32 must be aligned to four bytes!"); | |
assert(typeof maxBytesToWrite == "number", "stringToUTF32(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!"); | |
if (maxBytesToWrite === undefined) { | |
maxBytesToWrite = 2147483647; | |
} | |
if (maxBytesToWrite < 4) return 0; | |
var startPtr = outPtr; | |
var endPtr = startPtr + maxBytesToWrite - 4; | |
for (var i = 0; i < str.length; ++i) { | |
var codeUnit = str.charCodeAt(i); | |
if (codeUnit >= 55296 && codeUnit <= 57343) { | |
var trailSurrogate = str.charCodeAt(++i); | |
codeUnit = 65536 + ((codeUnit & 1023) << 10) | trailSurrogate & 1023; | |
} | |
HEAP32[outPtr >> 2] = codeUnit; | |
outPtr += 4; | |
if (outPtr + 4 > endPtr) break; | |
} | |
HEAP32[outPtr >> 2] = 0; | |
return outPtr - startPtr; | |
} | |
function lengthBytesUTF32(str) { | |
var len = 0; | |
for (var i = 0; i < str.length; ++i) { | |
var codeUnit = str.charCodeAt(i); | |
if (codeUnit >= 55296 && codeUnit <= 57343) ++i; | |
len += 4; | |
} | |
return len; | |
} | |
function __embind_register_std_wstring(rawType, charSize, name) { | |
name = readLatin1String(name); | |
var decodeString, encodeString, getHeap, lengthBytesUTF, shift; | |
if (charSize === 2) { | |
decodeString = UTF16ToString; | |
encodeString = stringToUTF16; | |
lengthBytesUTF = lengthBytesUTF16; | |
getHeap = () => HEAPU16; | |
shift = 1; | |
} else if (charSize === 4) { | |
decodeString = UTF32ToString; | |
encodeString = stringToUTF32; | |
lengthBytesUTF = lengthBytesUTF32; | |
getHeap = () => HEAPU32; | |
shift = 2; | |
} | |
registerType(rawType, { | |
name: name, | |
"fromWireType": function(value) { | |
var length = HEAPU32[value >> 2]; | |
var HEAP = getHeap(); | |
var str; | |
var decodeStartPtr = value + 4; | |
for (var i = 0; i <= length; ++i) { | |
var currentBytePtr = value + 4 + i * charSize; | |
if (i == length || HEAP[currentBytePtr >> shift] == 0) { | |
var maxReadBytes = currentBytePtr - decodeStartPtr; | |
var stringSegment = decodeString(decodeStartPtr, maxReadBytes); | |
if (str === undefined) { | |
str = stringSegment; | |
} else { | |
str += String.fromCharCode(0); | |
str += stringSegment; | |
} | |
decodeStartPtr = currentBytePtr + charSize; | |
} | |
} | |
_free(value); | |
return str; | |
}, | |
"toWireType": function(destructors, value) { | |
if (!(typeof value == "string")) { | |
throwBindingError("Cannot pass non-string to C++ string type " + name); | |
} | |
var length = lengthBytesUTF(value); | |
var ptr = _malloc(4 + length + charSize); | |
HEAPU32[ptr >> 2] = length >> shift; | |
encodeString(value, ptr + 4, length + charSize); | |
if (destructors !== null) { | |
destructors.push(_free, ptr); | |
} | |
return ptr; | |
}, | |
"argPackAdvance": 8, | |
"readValueFromPointer": simpleReadValueFromPointer, | |
destructorFunction: function(ptr) { | |
_free(ptr); | |
} | |
}); | |
} | |
function __embind_register_value_array(rawType, name, constructorSignature, rawConstructor, destructorSignature, rawDestructor) { | |
tupleRegistrations[rawType] = { | |
name: readLatin1String(name), | |
rawConstructor: embind__requireFunction(constructorSignature, rawConstructor), | |
rawDestructor: embind__requireFunction(destructorSignature, rawDestructor), | |
elements: [] | |
}; | |
} | |
function __embind_register_value_array_element(rawTupleType, getterReturnType, getterSignature, getter, getterContext, setterArgumentType, setterSignature, setter, setterContext) { | |
tupleRegistrations[rawTupleType].elements.push({ | |
getterReturnType: getterReturnType, | |
getter: embind__requireFunction(getterSignature, getter), | |
getterContext: getterContext, | |
setterArgumentType: setterArgumentType, | |
setter: embind__requireFunction(setterSignature, setter), | |
setterContext: setterContext | |
}); | |
} | |
function __embind_register_value_object(rawType, name, constructorSignature, rawConstructor, destructorSignature, rawDestructor) { | |
structRegistrations[rawType] = { | |
name: readLatin1String(name), | |
rawConstructor: embind__requireFunction(constructorSignature, rawConstructor), | |
rawDestructor: embind__requireFunction(destructorSignature, rawDestructor), | |
fields: [] | |
}; | |
} | |
function __embind_register_value_object_field(structType, fieldName, getterReturnType, getterSignature, getter, getterContext, setterArgumentType, setterSignature, setter, setterContext) { | |
structRegistrations[structType].fields.push({ | |
fieldName: readLatin1String(fieldName), | |
getterReturnType: getterReturnType, | |
getter: embind__requireFunction(getterSignature, getter), | |
getterContext: getterContext, | |
setterArgumentType: setterArgumentType, | |
setter: embind__requireFunction(setterSignature, setter), | |
setterContext: setterContext | |
}); | |
} | |
function __embind_register_void(rawType, name) { | |
name = readLatin1String(name); | |
registerType(rawType, { | |
isVoid: true, | |
name: name, | |
"argPackAdvance": 0, | |
"fromWireType": function() { | |
return undefined; | |
}, | |
"toWireType": function(destructors, o) { | |
return undefined; | |
} | |
}); | |
} | |
function __emval_as(handle, returnType, destructorsRef) { | |
handle = Emval.toValue(handle); | |
returnType = requireRegisteredType(returnType, "emval::as"); | |
var destructors = []; | |
var rd = Emval.toHandle(destructors); | |
HEAPU32[destructorsRef >> 2] = rd; | |
return returnType["toWireType"](destructors, handle); | |
} | |
function emval_lookupTypes(argCount, argTypes) { | |
var a = new Array(argCount); | |
for (var i = 0; i < argCount; ++i) { | |
a[i] = requireRegisteredType(HEAPU32[argTypes + i * 4 >> 2], "parameter " + i); | |
} | |
return a; | |
} | |
function __emval_call(handle, argCount, argTypes, argv) { | |
handle = Emval.toValue(handle); | |
var types = emval_lookupTypes(argCount, argTypes); | |
var args = new Array(argCount); | |
for (var i = 0; i < argCount; ++i) { | |
var type = types[i]; | |
args[i] = type["readValueFromPointer"](argv); | |
argv += type["argPackAdvance"]; | |
} | |
var rv = handle.apply(undefined, args); | |
return Emval.toHandle(rv); | |
} | |
function emval_allocateDestructors(destructorsRef) { | |
var destructors = []; | |
HEAPU32[destructorsRef >> 2] = Emval.toHandle(destructors); | |
return destructors; | |
} | |
var emval_symbols = {}; | |
function getStringOrSymbol(address) { | |
var symbol = emval_symbols[address]; | |
if (symbol === undefined) { | |
return readLatin1String(address); | |
} | |
return symbol; | |
} | |
var emval_methodCallers = []; | |
function __emval_call_method(caller, handle, methodName, destructorsRef, args) { | |
caller = emval_methodCallers[caller]; | |
handle = Emval.toValue(handle); | |
methodName = getStringOrSymbol(methodName); | |
return caller(handle, methodName, emval_allocateDestructors(destructorsRef), args); | |
} | |
function __emval_call_void_method(caller, handle, methodName, args) { | |
caller = emval_methodCallers[caller]; | |
handle = Emval.toValue(handle); | |
methodName = getStringOrSymbol(methodName); | |
caller(handle, methodName, null, args); | |
} | |
function __emval_equals(first, second) { | |
first = Emval.toValue(first); | |
second = Emval.toValue(second); | |
return first == second; | |
} | |
function emval_get_global() { | |
if (typeof globalThis == "object") { | |
return globalThis; | |
} | |
function testGlobal(obj) { | |
obj["$$$embind_global$$$"] = obj; | |
var success = typeof $$$embind_global$$$ == "object" && obj["$$$embind_global$$$"] == obj; | |
if (!success) { | |
delete obj["$$$embind_global$$$"]; | |
} | |
return success; | |
} | |
if (typeof $$$embind_global$$$ == "object") { | |
return $$$embind_global$$$; | |
} | |
if (typeof global == "object" && testGlobal(global)) { | |
$$$embind_global$$$ = global; | |
} else if (typeof self == "object" && testGlobal(self)) { | |
$$$embind_global$$$ = self; | |
} | |
if (typeof $$$embind_global$$$ == "object") { | |
return $$$embind_global$$$; | |
} | |
throw Error("unable to get global object."); | |
} | |
function __emval_get_global(name) { | |
if (name === 0) { | |
return Emval.toHandle(emval_get_global()); | |
} else { | |
name = getStringOrSymbol(name); | |
return Emval.toHandle(emval_get_global()[name]); | |
} | |
} | |
function emval_addMethodCaller(caller) { | |
var id = emval_methodCallers.length; | |
emval_methodCallers.push(caller); | |
return id; | |
} | |
var emval_registeredMethods = []; | |
function __emval_get_method_caller(argCount, argTypes) { | |
var types = emval_lookupTypes(argCount, argTypes); | |
var retType = types[0]; | |
var signatureName = retType.name + "_$" + types.slice(1).map(function(t) { | |
return t.name; | |
}).join("_") + "$"; | |
var returnId = emval_registeredMethods[signatureName]; | |
if (returnId !== undefined) { | |
return returnId; | |
} | |
var argN = new Array(argCount - 1); | |
var invokerFunction = (handle, name, destructors, args) => { | |
var offset = 0; | |
for (var i = 0; i < argCount - 1; ++i) { | |
argN[i] = types[i + 1]["readValueFromPointer"](args + offset); | |
offset += types[i + 1]["argPackAdvance"]; | |
} | |
var rv = handle[name].apply(handle, argN); | |
for (var i = 0; i < argCount - 1; ++i) { | |
if (types[i + 1].deleteObject) { | |
types[i + 1].deleteObject(argN[i]); | |
} | |
} | |
if (!retType.isVoid) { | |
return retType["toWireType"](destructors, rv); | |
} | |
}; | |
returnId = emval_addMethodCaller(invokerFunction); | |
emval_registeredMethods[signatureName] = returnId; | |
return returnId; | |
} | |
function __emval_get_module_property(name) { | |
name = getStringOrSymbol(name); | |
return Emval.toHandle(Module[name]); | |
} | |
function __emval_get_property(handle, key) { | |
handle = Emval.toValue(handle); | |
key = Emval.toValue(key); | |
return Emval.toHandle(handle[key]); | |
} | |
function __emval_incref(handle) { | |
if (handle > 4) { | |
emval_handle_array[handle].refcount += 1; | |
} | |
} | |
function craftEmvalAllocator(argCount) { | |
var argsList = new Array(argCount + 1); | |
return function(constructor, argTypes, args) { | |
argsList[0] = constructor; | |
for (var i = 0; i < argCount; ++i) { | |
var argType = requireRegisteredType(HEAPU32[argTypes + i * 4 >> 2], "parameter " + i); | |
argsList[i + 1] = argType["readValueFromPointer"](args); | |
args += argType["argPackAdvance"]; | |
} | |
var obj = new (constructor.bind.apply(constructor, argsList))(); | |
return Emval.toHandle(obj); | |
}; | |
} | |
var emval_newers = {}; | |
function __emval_new(handle, argCount, argTypes, args) { | |
handle = Emval.toValue(handle); | |
var newer = emval_newers[argCount]; | |
if (!newer) { | |
newer = craftEmvalAllocator(argCount); | |
emval_newers[argCount] = newer; | |
} | |
return newer(handle, argTypes, args); | |
} | |
function __emval_new_array() { | |
return Emval.toHandle([]); | |
} | |
function __emval_new_cstring(v) { | |
return Emval.toHandle(getStringOrSymbol(v)); | |
} | |
function __emval_new_object() { | |
return Emval.toHandle({}); | |
} | |
function __emval_register_symbol(address) { | |
emval_symbols[address] = readLatin1String(address); | |
} | |
function __emval_run_destructors(handle) { | |
var destructors = Emval.toValue(handle); | |
runDestructors(destructors); | |
__emval_decref(handle); | |
} | |
function __emval_set_property(handle, key, value) { | |
handle = Emval.toValue(handle); | |
key = Emval.toValue(key); | |
value = Emval.toValue(value); | |
handle[key] = value; | |
} | |
function __emval_strictly_equals(first, second) { | |
first = Emval.toValue(first); | |
second = Emval.toValue(second); | |
return first === second; | |
} | |
function __emval_take_value(type, arg) { | |
type = requireRegisteredType(type, "_emval_take_value"); | |
var v = type["readValueFromPointer"](arg); | |
return Emval.toHandle(v); | |
} | |
function __emval_typeof(handle) { | |
handle = Emval.toValue(handle); | |
return Emval.toHandle(typeof handle); | |
} | |
function _abort() { | |
abort("native code called abort()"); | |
} | |
var readEmAsmArgsArray = []; | |
function readEmAsmArgs(sigPtr, buf) { | |
assert(Array.isArray(readEmAsmArgsArray)); | |
assert(buf % 16 == 0); | |
readEmAsmArgsArray.length = 0; | |
var ch; | |
buf >>= 2; | |
while (ch = HEAPU8[sigPtr++]) { | |
var chr = String.fromCharCode(ch); | |
var validChars = [ "d", "f", "i" ]; | |
assert(validChars.includes(chr), "Invalid character " + ch + '("' + chr + '") in readEmAsmArgs! Use only [' + validChars + '], and do not specify "v" for void return argument.'); | |
buf += ch != 105 & buf; | |
readEmAsmArgsArray.push(ch == 105 ? HEAP32[buf] : HEAPF64[buf++ >> 1]); | |
++buf; | |
} | |
return readEmAsmArgsArray; | |
} | |
function runEmAsmFunction(code, sigPtr, argbuf) { | |
var args = readEmAsmArgs(sigPtr, argbuf); | |
if (!ASM_CONSTS.hasOwnProperty(code)) abort("No EM_ASM constant found at address " + code); | |
return ASM_CONSTS[code].apply(null, args); | |
} | |
function _emscripten_asm_const_int(code, sigPtr, argbuf) { | |
return runEmAsmFunction(code, sigPtr, argbuf); | |
} | |
function _emscripten_memcpy_big(dest, src, num) { | |
HEAPU8.copyWithin(dest, src, src + num); | |
} | |
function getHeapMax() { | |
return HEAPU8.length; | |
} | |
function 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"); | |
} | |
function _emscripten_resize_heap(requestedSize) { | |
var oldSize = HEAPU8.length; | |
requestedSize = requestedSize >>> 0; | |
abortOnCannotGrowMemory(requestedSize); | |
} | |
var SYSCALLS = { | |
varargs: undefined, | |
get: function() { | |
assert(SYSCALLS.varargs != undefined); | |
SYSCALLS.varargs += 4; | |
var ret = HEAP32[SYSCALLS.varargs - 4 >> 2]; | |
return ret; | |
}, | |
getStr: function(ptr) { | |
var ret = UTF8ToString(ptr); | |
return ret; | |
} | |
}; | |
function _fd_close(fd) { | |
abort("fd_close called without SYSCALLS_REQUIRE_FILESYSTEM"); | |
} | |
function convertI32PairToI53Checked(lo, hi) { | |
assert(lo == lo >>> 0 || lo == (lo | 0)); | |
assert(hi === (hi | 0)); | |
return hi + 2097152 >>> 0 < 4194305 - !!lo ? (lo >>> 0) + hi * 4294967296 : NaN; | |
} | |
function _fd_seek(fd, offset_low, offset_high, whence, newOffset) { | |
return 70; | |
} | |
var printCharBuffers = [ null, [], [] ]; | |
function 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); | |
} | |
} | |
function flush_NO_FILESYSTEM() { | |
_fflush(0); | |
if (printCharBuffers[1].length) printChar(1, 10); | |
if (printCharBuffers[2].length) printChar(2, 10); | |
} | |
function _fd_write(fd, iov, iovcnt, pnum) { | |
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; | |
} | |
BindingError = Module["BindingError"] = extendError(Error, "BindingError"); | |
init_emval(); | |
PureVirtualError = Module["PureVirtualError"] = extendError(Error, "PureVirtualError"); | |
embind_init_charCodes(); | |
init_embind(); | |
InternalError = Module["InternalError"] = extendError(Error, "InternalError"); | |
init_ClassHandle(); | |
init_RegisteredPointer(); | |
UnboundTypeError = Module["UnboundTypeError"] = extendError(Error, "UnboundTypeError"); | |
function checkIncomingModuleAPI() { | |
ignoredModuleProp("fetchSettings"); | |
} | |
var wasmImports = { | |
"__assert_fail": ___assert_fail, | |
"__cxa_throw": ___cxa_throw, | |
"_embind_create_inheriting_constructor": __embind_create_inheriting_constructor, | |
"_embind_finalize_value_array": __embind_finalize_value_array, | |
"_embind_finalize_value_object": __embind_finalize_value_object, | |
"_embind_register_bigint": __embind_register_bigint, | |
"_embind_register_bool": __embind_register_bool, | |
"_embind_register_class": __embind_register_class, | |
"_embind_register_class_class_function": __embind_register_class_class_function, | |
"_embind_register_class_class_property": __embind_register_class_class_property, | |
"_embind_register_class_constructor": __embind_register_class_constructor, | |
"_embind_register_class_function": __embind_register_class_function, | |
"_embind_register_class_property": __embind_register_class_property, | |
"_embind_register_constant": __embind_register_constant, | |
"_embind_register_emval": __embind_register_emval, | |
"_embind_register_enum": __embind_register_enum, | |
"_embind_register_enum_value": __embind_register_enum_value, | |
"_embind_register_float": __embind_register_float, | |
"_embind_register_function": __embind_register_function, | |
"_embind_register_integer": __embind_register_integer, | |
"_embind_register_memory_view": __embind_register_memory_view, | |
"_embind_register_smart_ptr": __embind_register_smart_ptr, | |
"_embind_register_std_string": __embind_register_std_string, | |
"_embind_register_std_wstring": __embind_register_std_wstring, | |
"_embind_register_value_array": __embind_register_value_array, | |
"_embind_register_value_array_element": __embind_register_value_array_element, | |
"_embind_register_value_object": __embind_register_value_object, | |
"_embind_register_value_object_field": __embind_register_value_object_field, | |
"_embind_register_void": __embind_register_void, | |
"_emval_as": __emval_as, | |
"_emval_call": __emval_call, | |
"_emval_call_method": __emval_call_method, | |
"_emval_call_void_method": __emval_call_void_method, | |
"_emval_decref": __emval_decref, | |
"_emval_equals": __emval_equals, | |
"_emval_get_global": __emval_get_global, | |
"_emval_get_method_caller": __emval_get_method_caller, | |
"_emval_get_module_property": __emval_get_module_property, | |
"_emval_get_property": __emval_get_property, | |
"_emval_incref": __emval_incref, | |
"_emval_new": __emval_new, | |
"_emval_new_array": __emval_new_array, | |
"_emval_new_cstring": __emval_new_cstring, | |
"_emval_new_object": __emval_new_object, | |
"_emval_register_symbol": __emval_register_symbol, | |
"_emval_run_destructors": __emval_run_destructors, | |
"_emval_set_property": __emval_set_property, | |
"_emval_strictly_equals": __emval_strictly_equals, | |
"_emval_take_value": __emval_take_value, | |
"_emval_typeof": __emval_typeof, | |
"abort": _abort, | |
"emscripten_asm_const_int": _emscripten_asm_const_int, | |
"emscripten_memcpy_big": _emscripten_memcpy_big, | |
"emscripten_resize_heap": _emscripten_resize_heap, | |
"fd_close": _fd_close, | |
"fd_seek": _fd_seek, | |
"fd_write": _fd_write | |
}; | |
var asm = createWasm(); | |
var ___wasm_call_ctors = createExportWrapper("__wasm_call_ctors", asm); | |
var _malloc = createExportWrapper("malloc", asm); | |
var ___getTypeName = Module["___getTypeName"] = createExportWrapper("__getTypeName", asm); | |
var __embind_initialize_bindings = Module["__embind_initialize_bindings"] = createExportWrapper("_embind_initialize_bindings", asm); | |
var ___errno_location = createExportWrapper("__errno_location", asm); | |
var _fflush = Module["_fflush"] = createExportWrapper("fflush", asm); | |
var _free = createExportWrapper("free", asm); | |
var _emscripten_stack_init = asm["emscripten_stack_init"]; | |
var _emscripten_stack_get_free = asm["emscripten_stack_get_free"]; | |
var _emscripten_stack_get_base = asm["emscripten_stack_get_base"]; | |
var _emscripten_stack_get_end = asm["emscripten_stack_get_end"]; | |
var stackSave = createExportWrapper("stackSave", asm); | |
var stackRestore = createExportWrapper("stackRestore", asm); | |
var stackAlloc = createExportWrapper("stackAlloc", asm); | |
var _emscripten_stack_get_current = asm["emscripten_stack_get_current"]; | |
var ___cxa_is_pointer_type = createExportWrapper("__cxa_is_pointer_type", asm); | |
var dynCall_jiji = Module["dynCall_jiji"] = createExportWrapper("dynCall_jiji", asm); | |
var missingLibrarySymbols = [ "zeroMemory", "stringToNewUTF8", "exitJS", "emscripten_realloc_buffer", "setErrNo", "inetPton4", "inetNtop4", "inetPton6", "inetNtop6", "readSockaddr", "writeSockaddr", "getHostByName", "getRandomDevice", "traverseStack", "convertPCtoSourceLocation", "runMainThreadEmAsm", "jstoi_q", "jstoi_s", "getExecutableName", "listenOnce", "autoResumeAudioContext", "handleException", "runtimeKeepalivePush", "runtimeKeepalivePop", "callUserCallback", "maybeExit", "safeSetTimeout", "asmjsMangle", "asyncLoad", "alignMemory", "mmapAlloc", "HandleAllocator", "getNativeTypeSize", "STACK_SIZE", "STACK_ALIGN", "POINTER_SIZE", "ASSERTIONS", "writeI53ToI64", "writeI53ToI64Clamped", "writeI53ToI64Signaling", "writeI53ToU64Clamped", "writeI53ToU64Signaling", "readI53FromI64", "readI53FromU64", "convertI32PairToI53", "convertU32PairToI53", "getCFunc", "ccall", "cwrap", "uleb128Encode", "sigToWasmTypes", "generateFuncType", "convertJsFunctionToWasm", "getEmptyTableSlot", "updateTableMap", "getFunctionAddress", "addFunction", "removeFunction", "reallyNegative", "unSign", "strLen", "reSign", "formatString", "intArrayFromString", "intArrayToString", "AsciiToString", "stringToAscii", "allocateUTF8", "allocateUTF8OnStack", "writeStringToMemory", "writeArrayToMemory", "writeAsciiToMemory", "getSocketFromFD", "getSocketAddress", "registerKeyEventCallback", "maybeCStringToJsString", "findEventTarget", "findCanvasEventTarget", "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", "setCanvasElementSize", "getCanvasElementSize", "demangle", "demangleAll", "jsStackTrace", "stackTrace", "getEnvStrings", "checkWasiClock", "createDyncallWrapper", "setImmediateWrapped", "clearImmediateWrapped", "polyfillSetImmediate", "getPromise", "makePromise", "makePromiseCallback", "exception_addRef", "exception_decRef", "setMainLoop", "_setNetworkCallback", "heapObjectForWebGLType", "heapAccessShiftForWebGLHeap", "emscriptenWebGLGet", "computeUnpackAlignedImageSize", "emscriptenWebGLGetTexPixelData", "emscriptenWebGLGetUniform", "webglGetUniformLocation", "webglPrepareUniformLocationsBeforeFirstUse", "webglGetLeftBracePos", "emscriptenWebGLGetVertexAttrib", "writeGLArray", "SDL_unicode", "SDL_ttfContext", "SDL_audio", "GLFW_Window", "runAndAbortIfError", "ALLOC_NORMAL", "ALLOC_STACK", "allocate" ]; | |
missingLibrarySymbols.forEach(missingLibrarySymbol); | |
var unexportedSymbols = [ "run", "UTF8ArrayToString", "UTF8ToString", "stringToUTF8Array", "stringToUTF8", "lengthBytesUTF8", "addOnPreRun", "addOnInit", "addOnPreMain", "addOnExit", "addOnPostRun", "addRunDependency", "removeRunDependency", "FS_createFolder", "FS_createPath", "FS_createDataFile", "FS_createPreloadedFile", "FS_createLazyFile", "FS_createLink", "FS_createDevice", "FS_unlink", "out", "err", "callMain", "abort", "keepRuntimeAlive", "wasmMemory", "stackAlloc", "stackSave", "stackRestore", "getTempRet0", "setTempRet0", "writeStackCookie", "checkStackCookie", "getCompilerSetting", "ptrToString", "getHeapMax", "abortOnCannotGrowMemory", "ENV", "ERRNO_CODES", "ERRNO_MESSAGES", "DNS", "Protocols", "Sockets", "timers", "warnOnce", "UNWIND_CACHE", "readEmAsmArgsArray", "readEmAsmArgs", "runEmAsmFunction", "dynCallLegacy", "getDynCaller", "dynCall", "convertI32PairToI53Checked", "freeTableIndexes", "functionsInTableMap", "setValue", "getValue", "PATH", "PATH_FS", "UTF16Decoder", "UTF16ToString", "stringToUTF16", "lengthBytesUTF16", "UTF32ToString", "stringToUTF32", "lengthBytesUTF32", "SYSCALLS", "JSEvents", "specialHTMLTargets", "currentFullscreenStrategy", "restoreOldWindowedStyle", "ExitStatus", "flush_NO_FILESYSTEM", "dlopenMissingError", "promiseMap", "uncaughtExceptionCount", "exceptionLast", "exceptionCaught", "ExceptionInfo", "Browser", "wget", "FS", "MEMFS", "TTY", "PIPEFS", "SOCKFS", "tempFixedLengthArray", "miniTempWebGLFloatBuffers", "GL", "AL", "SDL", "SDL_gfx", "GLUT", "EGL", "GLFW", "GLEW", "IDBStore", "InternalError", "BindingError", "UnboundTypeError", "PureVirtualError", "init_embind", "throwInternalError", "throwBindingError", "throwUnboundTypeError", "ensureOverloadTable", "exposePublicSymbol", "replacePublicSymbol", "extendError", "createNamedFunction", "embindRepr", "registeredInstances", "getBasestPointer", "registerInheritedInstance", "unregisterInheritedInstance", "getInheritedInstance", "getInheritedInstanceCount", "getLiveInheritedInstances", "registeredTypes", "awaitingDependencies", "typeDependencies", "registeredPointers", "registerType", "whenDependentTypesAreResolved", "embind_charCodes", "embind_init_charCodes", "readLatin1String", "getTypeName", "heap32VectorToArray", "requireRegisteredType", "getShiftFromSize", "integerReadValueFromPointer", "enumReadValueFromPointer", "floatReadValueFromPointer", "simpleReadValueFromPointer", "runDestructors", "new_", "craftInvokerFunction", "embind__requireFunction", "tupleRegistrations", "structRegistrations", "genericPointerToWireType", "constNoSmartPtrRawPointerToWireType", "nonConstNoSmartPtrRawPointerToWireType", "init_RegisteredPointer", "RegisteredPointer", "RegisteredPointer_getPointee", "RegisteredPointer_destructor", "RegisteredPointer_deleteObject", "RegisteredPointer_fromWireType", "runDestructor", "releaseClassHandle", "finalizationRegistry", "detachFinalizer_deps", "detachFinalizer", "attachFinalizer", "makeClassHandle", "init_ClassHandle", "ClassHandle", "ClassHandle_isAliasOf", "throwInstanceAlreadyDeleted", "ClassHandle_clone", "ClassHandle_delete", "deletionQueue", "ClassHandle_isDeleted", "ClassHandle_deleteLater", "flushPendingDeletes", "delayFunction", "setDelayFunction", "RegisteredClass", "shallowCopyInternalPointer", "downcastPointer", "upcastPointer", "validateThis", "char_0", "char_9", "makeLegalFunctionName", "emval_handle_array", "emval_free_list", "emval_symbols", "init_emval", "count_emval_handles", "get_first_emval", "getStringOrSymbol", "Emval", "emval_newers", "craftEmvalAllocator", "emval_get_global", "emval_lookupTypes", "emval_allocateDestructors", "emval_methodCallers", "emval_addMethodCaller", "emval_registeredMethods" ]; | |
unexportedSymbols.forEach(unexportedRuntimeSymbol); | |
var calledRun; | |
dependenciesFulfilled = function runCaller() { | |
if (!calledRun) run(); | |
if (!calledRun) dependenciesFulfilled = runCaller; | |
}; | |
function stackCheckInit() { | |
_emscripten_stack_init(); | |
writeStackCookie(); | |
} | |
function run() { | |
if (runDependencies > 0) { | |
return; | |
} | |
stackCheckInit(); | |
preRun(); | |
if (runDependencies > 0) { | |
return; | |
} | |
function doRun() { | |
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() { | |
var oldOut = out; | |
var oldErr = err; | |
var has = false; | |
out = err = x => { | |
has = true; | |
}; | |
try { | |
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 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(); | |
return Module; | |
}(); | |
var root = this; | |
var previousUnderscore = root._; | |
var breaker = {}; | |
var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; | |
var push = ArrayProto.push, slice = ArrayProto.slice, concat = ArrayProto.concat, unshift = ArrayProto.unshift, toString = ObjProto.toString, hasOwnProperty = ObjProto.hasOwnProperty; | |
var nativeForEach = ArrayProto.forEach, nativeMap = ArrayProto.map, nativeReduce = ArrayProto.reduce, nativeReduceRight = ArrayProto.reduceRight, nativeFilter = ArrayProto.filter, nativeEvery = ArrayProto.every, nativeSome = ArrayProto.some, nativeIndexOf = ArrayProto.indexOf, nativeLastIndexOf = ArrayProto.lastIndexOf, nativeIsArray = Array.isArray, nativeKeys = Object.keys, nativeBind = FuncProto.bind; | |
var _ = function(obj) { | |
if (obj instanceof _) return obj; | |
if (!(this instanceof _)) return new _(obj); | |
this._wrapped = obj; | |
}; | |
if (typeof exports !== "undefined") { | |
if (typeof module !== "undefined" && module.exports) { | |
exports = module.exports = _; | |
} | |
exports._ = _; | |
} else { | |
root["_"] = _; | |
} | |
_.VERSION = "1.4.2"; | |
var each = _.each = _.forEach = function(obj, iterator, context) { | |
if (obj == null) return; | |
if (nativeForEach && obj.forEach === nativeForEach) { | |
obj.forEach(iterator, context); | |
} else if (obj.length === +obj.length) { | |
for (var i = 0, l = obj.length; i < l; i++) { | |
if (iterator.call(context, obj[i], i, obj) === breaker) return; | |
} | |
} else { | |
for (var key in obj) { | |
if (_.has(obj, key)) { | |
if (iterator.call(context, obj[key], key, obj) === breaker) return; | |
} | |
} | |
} | |
}; | |
_.map = _.collect = function(obj, iterator, context) { | |
var results = []; | |
if (obj == null) return results; | |
if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); | |
each(obj, function(value, index, list) { | |
results[results.length] = iterator.call(context, value, index, list); | |
}); | |
return results; | |
}; | |
_.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { | |
var initial = arguments.length > 2; | |
if (obj == null) obj = []; | |
if (nativeReduce && obj.reduce === nativeReduce) { | |
if (context) iterator = _.bind(iterator, context); | |
return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator); | |
} | |
each(obj, function(value, index, list) { | |
if (!initial) { | |
memo = value; | |
initial = true; | |
} else { | |
memo = iterator.call(context, memo, value, index, list); | |
} | |
}); | |
if (!initial) throw new TypeError("Reduce of empty array with no initial value"); | |
return memo; | |
}; | |
_.reduceRight = _.foldr = function(obj, iterator, memo, context) { | |
var initial = arguments.length > 2; | |
if (obj == null) obj = []; | |
if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { | |
if (context) iterator = _.bind(iterator, context); | |
return arguments.length > 2 ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); | |
} | |
var length = obj.length; | |
if (length !== +length) { | |
var keys = _.keys(obj); | |
length = keys.length; | |
} | |
each(obj, function(value, index, list) { | |
index = keys ? keys[--length] : --length; | |
if (!initial) { | |
memo = obj[index]; | |
initial = true; | |
} else { | |
memo = iterator.call(context, memo, obj[index], index, list); | |
} | |
}); | |
if (!initial) throw new TypeError("Reduce of empty array with no initial value"); | |
return memo; | |
}; | |
_.find = _.detect = function(obj, iterator, context) { | |
var result; | |
any(obj, function(value, index, list) { | |
if (iterator.call(context, value, index, list)) { | |
result = value; | |
return true; | |
} | |
}); | |
return result; | |
}; | |
_.filter = _.select = function(obj, iterator, context) { | |
var results = []; | |
if (obj == null) return results; | |
if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context); | |
each(obj, function(value, index, list) { | |
if (iterator.call(context, value, index, list)) results[results.length] = value; | |
}); | |
return results; | |
}; | |
_.reject = function(obj, iterator, context) { | |
var results = []; | |
if (obj == null) return results; | |
each(obj, function(value, index, list) { | |
if (!iterator.call(context, value, index, list)) results[results.length] = value; | |
}); | |
return results; | |
}; | |
_.every = _.all = function(obj, iterator, context) { | |
iterator || (iterator = _.identity); | |
var result = true; | |
if (obj == null) return result; | |
if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context); | |
each(obj, function(value, index, list) { | |
if (!(result = result && iterator.call(context, value, index, list))) return breaker; | |
}); | |
return !!result; | |
}; | |
var any = _.some = _.any = function(obj, iterator, context) { | |
iterator || (iterator = _.identity); | |
var result = false; | |
if (obj == null) return result; | |
if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context); | |
each(obj, function(value, index, list) { | |
if (result || (result = iterator.call(context, value, index, list))) return breaker; | |
}); | |
return !!result; | |
}; | |
_.contains = _.include = function(obj, target) { | |
var found = false; | |
if (obj == null) return found; | |
if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; | |
found = any(obj, function(value) { | |
return value === target; | |
}); | |
return found; | |
}; | |
_.invoke = function(obj, method) { | |
var args = slice.call(arguments, 2); | |
return _.map(obj, function(value) { | |
return (_.isFunction(method) ? method : value[method]).apply(value, args); | |
}); | |
}; | |
_.pluck = function(obj, key) { | |
return _.map(obj, function(value) { | |
return value[key]; | |
}); | |
}; | |
_.where = function(obj, attrs) { | |
if (_.isEmpty(attrs)) return []; | |
return _.filter(obj, function(value) { | |
for (var key in attrs) { | |
if (attrs[key] !== value[key]) return false; | |
} | |
return true; | |
}); | |
}; | |
_.max = function(obj, iterator, context) { | |
if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { | |
return Math.max.apply(Math, obj); | |
} | |
if (!iterator && _.isEmpty(obj)) return -Infinity; | |
var result = { | |
computed: -Infinity | |
}; | |
each(obj, function(value, index, list) { | |
var computed = iterator ? iterator.call(context, value, index, list) : value; | |
computed >= result.computed && (result = { | |
value: value, | |
computed: computed | |
}); | |
}); | |
return result.value; | |
}; | |
_.min = function(obj, iterator, context) { | |
if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { | |
return Math.min.apply(Math, obj); | |
} | |
if (!iterator && _.isEmpty(obj)) return Infinity; | |
var result = { | |
computed: Infinity | |
}; | |
each(obj, function(value, index, list) { | |
var computed = iterator ? iterator.call(context, value, index, list) : value; | |
computed < result.computed && (result = { | |
value: value, | |
computed: computed | |
}); | |
}); | |
return result.value; | |
}; | |
_.shuffle = function(obj) { | |
var rand; | |
var index = 0; | |
var shuffled = []; | |
each(obj, function(value) { | |
rand = _.random(index++); | |
shuffled[index - 1] = shuffled[rand]; | |
shuffled[rand] = value; | |
}); | |
return shuffled; | |
}; | |
var lookupIterator = function(value) { | |
return _.isFunction(value) ? value : function(obj) { | |
return obj[value]; | |
}; | |
}; | |
_.sortBy = function(obj, value, context) { | |
var iterator = lookupIterator(value); | |
return _.pluck(_.map(obj, function(value, index, list) { | |
return { | |
value: value, | |
index: index, | |
criteria: iterator.call(context, value, index, list) | |
}; | |
}).sort(function(left, right) { | |
var a = left.criteria; | |
var b = right.criteria; | |
if (a !== b) { | |
if (a > b || a === void 0) return 1; | |
if (a < b || b === void 0) return -1; | |
} | |
return left.index < right.index ? -1 : 1; | |
}), "value"); | |
}; | |
var group = function(obj, value, context, behavior) { | |
var result = {}; | |
var iterator = lookupIterator(value); | |
each(obj, function(value, index) { | |
var key = iterator.call(context, value, index, obj); | |
behavior(result, key, value); | |
}); | |
return result; | |
}; | |
_.groupBy = function(obj, value, context) { | |
return group(obj, value, context, function(result, key, value) { | |
(_.has(result, key) ? result[key] : result[key] = []).push(value); | |
}); | |
}; | |
_.countBy = function(obj, value, context) { | |
return group(obj, value, context, function(result, key, value) { | |
if (!_.has(result, key)) result[key] = 0; | |
result[key]++; | |
}); | |
}; | |
_.sortedIndex = function(array, obj, iterator, context) { | |
iterator = iterator == null ? _.identity : lookupIterator(iterator); | |
var value = iterator.call(context, obj); | |
var low = 0, high = array.length; | |
while (low < high) { | |
var mid = low + high >>> 1; | |
iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid; | |
} | |
return low; | |
}; | |
_.toArray = function(obj) { | |
if (!obj) return []; | |
if (obj.length === +obj.length) return slice.call(obj); | |
return _.values(obj); | |
}; | |
_.size = function(obj) { | |
return obj.length === +obj.length ? obj.length : _.keys(obj).length; | |
}; | |
_.first = _.head = _.take = function(array, n, guard) { | |
return n != null && !guard ? slice.call(array, 0, n) : array[0]; | |
}; | |
_.initial = function(array, n, guard) { | |
return slice.call(array, 0, array.length - (n == null || guard ? 1 : n)); | |
}; | |
_.last = function(array, n, guard) { | |
if (n != null && !guard) { | |
return slice.call(array, Math.max(array.length - n, 0)); | |
} else { | |
return array[array.length - 1]; | |
} | |
}; | |
_.rest = _.tail = _.drop = function(array, n, guard) { | |
return slice.call(array, n == null || guard ? 1 : n); | |
}; | |
_.compact = function(array) { | |
return _.filter(array, function(value) { | |
return !!value; | |
}); | |
}; | |
var flatten = function(input, shallow, output) { | |
each(input, function(value) { | |
if (_.isArray(value)) { | |
shallow ? push.apply(output, value) : flatten(value, shallow, output); | |
} else { | |
output.push(value); | |
} | |
}); | |
return output; | |
}; | |
_.flatten = function(array, shallow) { | |
return flatten(array, shallow, []); | |
}; | |
_.without = function(array) { | |
return _.difference(array, slice.call(arguments, 1)); | |
}; | |
_.uniq = _.unique = function(array, isSorted, iterator, context) { | |
var initial = iterator ? _.map(array, iterator, context) : array; | |
var results = []; | |
var seen = []; | |
each(initial, function(value, index) { | |
if (isSorted ? !index || seen[seen.length - 1] !== value : !_.contains(seen, value)) { | |
seen.push(value); | |
results.push(array[index]); | |
} | |
}); | |
return results; | |
}; | |
_.union = function() { | |
return _.uniq(concat.apply(ArrayProto, arguments)); | |
}; | |
_.intersection = function(array) { | |
var rest = slice.call(arguments, 1); | |
return _.filter(_.uniq(array), function(item) { | |
return _.every(rest, function(other) { | |
return _.indexOf(other, item) >= 0; | |
}); | |
}); | |
}; | |
_.difference = function(array) { | |
var rest = concat.apply(ArrayProto, slice.call(arguments, 1)); | |
return _.filter(array, function(value) { | |
return !_.contains(rest, value); | |
}); | |
}; | |
_.zip = function() { | |
var args = slice.call(arguments); | |
var length = _.max(_.pluck(args, "length")); | |
var results = new Array(length); | |
for (var i = 0; i < length; i++) { | |
results[i] = _.pluck(args, "" + i); | |
} | |
return results; | |
}; | |
_.object = function(list, values) { | |
var result = {}; | |
for (var i = 0, l = list.length; i < l; i++) { | |
if (values) { | |
result[list[i]] = values[i]; | |
} else { | |
result[list[i][0]] = list[i][1]; | |
} | |
} | |
return result; | |
}; | |
_.indexOf = function(array, item, isSorted) { | |
if (array == null) return -1; | |
var i = 0, l = array.length; | |
if (isSorted) { | |
if (typeof isSorted == "number") { | |
i = isSorted < 0 ? Math.max(0, l + isSorted) : isSorted; | |
} else { | |
i = _.sortedIndex(array, item); | |
return array[i] === item ? i : -1; | |
} | |
} | |
if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted); | |
for (;i < l; i++) if (array[i] === item) return i; | |
return -1; | |
}; | |
_.lastIndexOf = function(array, item, from) { | |
if (array == null) return -1; | |
var hasIndex = from != null; | |
if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) { | |
return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item); | |
} | |
var i = hasIndex ? from : array.length; | |
while (i--) if (array[i] === item) return i; | |
return -1; | |
}; | |
_.range = function(start, stop, step) { | |
if (arguments.length <= 1) { | |
stop = start || 0; | |
start = 0; | |
} | |
step = arguments[2] || 1; | |
var len = Math.max(Math.ceil((stop - start) / step), 0); | |
var idx = 0; | |
var range = new Array(len); | |
while (idx < len) { | |
range[idx++] = start; | |
start += step; | |
} | |
return range; | |
}; | |
var ctor = function() {}; | |
_.bind = function bind(func, context) { | |
var bound, args; | |
if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); | |
if (!_.isFunction(func)) throw new TypeError(); | |
args = slice.call(arguments, 2); | |
return bound = function() { | |
if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); | |
ctor.prototype = func.prototype; | |
var self = new ctor(); | |
var result = func.apply(self, args.concat(slice.call(arguments))); | |
if (Object(result) === result) return result; | |
return self; | |
}; | |
}; | |
_.bindAll = function(obj) { | |
var funcs = slice.call(arguments, 1); | |
if (funcs.length == 0) funcs = _.functions(obj); | |
each(funcs, function(f) { | |
obj[f] = _.bind(obj[f], obj); | |
}); | |
return obj; | |
}; | |
_.memoize = function(func, hasher) { | |
var memo = {}; | |
hasher || (hasher = _.identity); | |
return function() { | |
var key = hasher.apply(this, arguments); | |
return _.has(memo, key) ? memo[key] : memo[key] = func.apply(this, arguments); | |
}; | |
}; | |
_.delay = function(func, wait) { | |
var args = slice.call(arguments, 2); | |
return setTimeout(function() { | |
return func.apply(null, args); | |
}, wait); | |
}; | |
_.defer = function(func) { | |
return _.delay.apply(_, [ func, 1 ].concat(slice.call(arguments, 1))); | |
}; | |
_.throttle = function(func, wait) { | |
var context, args, timeout, throttling, more, result; | |
var whenDone = _.debounce(function() { | |
more = throttling = false; | |
}, wait); | |
return function() { | |
context = this; | |
args = arguments; | |
var later = function() { | |
timeout = null; | |
if (more) { | |
result = func.apply(context, args); | |
} | |
whenDone(); | |
}; | |
if (!timeout) timeout = setTimeout(later, wait); | |
if (throttling) { | |
more = true; | |
} else { | |
throttling = true; | |
result = func.apply(context, args); | |
} | |
whenDone(); | |
return result; | |
}; | |
}; | |
_.debounce = function(func, wait, immediate) { | |
var timeout, result; | |
return function() { | |
var context = this, args = arguments; | |
var later = function() { | |
timeout = null; | |
if (!immediate) result = func.apply(context, args); | |
}; | |
var callNow = immediate && !timeout; | |
clearTimeout(timeout); | |
timeout = setTimeout(later, wait); | |
if (callNow) result = func.apply(context, args); | |
return result; | |
}; | |
}; | |
_.once = function(func) { | |
var ran = false, memo; | |
return function() { | |
if (ran) return memo; | |
ran = true; | |
memo = func.apply(this, arguments); | |
func = null; | |
return memo; | |
}; | |
}; | |
_.wrap = function(func, wrapper) { | |
return function() { | |
var args = [ func ]; | |
push.apply(args, arguments); | |
return wrapper.apply(this, args); | |
}; | |
}; | |
_.compose = function() { | |
var funcs = arguments; | |
return function() { | |
var args = arguments; | |
for (var i = funcs.length - 1; i >= 0; i--) { | |
args = [ funcs[i].apply(this, args) ]; | |
} | |
return args[0]; | |
}; | |
}; | |
_.after = function(times, func) { | |
if (times <= 0) return func(); | |
return function() { | |
if (--times < 1) { | |
return func.apply(this, arguments); | |
} | |
}; | |
}; | |
_.keys = nativeKeys || function(obj) { | |
if (obj !== Object(obj)) throw new TypeError("Invalid object"); | |
var keys = []; | |
for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key; | |
return keys; | |
}; | |
_.values = function(obj) { | |
var values = []; | |
for (var key in obj) if (_.has(obj, key)) values.push(obj[key]); | |
return values; | |
}; | |
_.pairs = function(obj) { | |
var pairs = []; | |
for (var key in obj) if (_.has(obj, key)) pairs.push([ key, obj[key] ]); | |
return pairs; | |
}; | |
_.invert = function(obj) { | |
var result = {}; | |
for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key; | |
return result; | |
}; | |
_.functions = _.methods = function(obj) { | |
var names = []; | |
for (var key in obj) { | |
if (_.isFunction(obj[key])) names.push(key); | |
} | |
return names.sort(); | |
}; | |
_.extend = function(obj) { | |
each(slice.call(arguments, 1), function(source) { | |
for (var prop in source) { | |
obj[prop] = source[prop]; | |
} | |
}); | |
return obj; | |
}; | |
_.pick = function(obj) { | |
var copy = {}; | |
var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); | |
each(keys, function(key) { | |
if (key in obj) copy[key] = obj[key]; | |
}); | |
return copy; | |
}; | |
_.omit = function(obj) { | |
var copy = {}; | |
var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); | |
for (var key in obj) { | |
if (!_.contains(keys, key)) copy[key] = obj[key]; | |
} | |
return copy; | |
}; | |
_.defaults = function(obj) { | |
each(slice.call(arguments, 1), function(source) { | |
for (var prop in source) { | |
if (obj[prop] == null) obj[prop] = source[prop]; | |
} | |
}); | |
return obj; | |
}; | |
_.clone = function(obj) { | |
if (!_.isObject(obj)) return obj; | |
return _.isArray(obj) ? obj.slice() : _.extend({}, obj); | |
}; | |
_.tap = function(obj, interceptor) { | |
interceptor(obj); | |
return obj; | |
}; | |
var eq = function(a, b, aStack, bStack) { | |
if (a === b) return a !== 0 || 1 / a == 1 / b; | |
if (a == null || b == null) return a === b; | |
if (a instanceof _) a = a._wrapped; | |
if (b instanceof _) b = b._wrapped; | |
var className = toString.call(a); | |
if (className != toString.call(b)) return false; | |
switch (className) { | |
case "[object String]": | |
return a == String(b); | |
case "[object Number]": | |
return a != +a ? b != +b : a == 0 ? 1 / a == 1 / b : a == +b; | |
case "[object Date]": | |
case "[object Boolean]": | |
return +a == +b; | |
case "[object RegExp]": | |
return a.source == b.source && a.global == b.global && a.multiline == b.multiline && a.ignoreCase == b.ignoreCase; | |
} | |
if (typeof a != "object" || typeof b != "object") return false; | |
var length = aStack.length; | |
while (length--) { | |
if (aStack[length] == a) return bStack[length] == b; | |
} | |
aStack.push(a); | |
bStack.push(b); | |
var size = 0, result = true; | |
if (className == "[object Array]") { | |
size = a.length; | |
result = size == b.length; | |
if (result) { | |
while (size--) { | |
if (!(result = eq(a[size], b[size], aStack, bStack))) break; | |
} | |
} | |
} else { | |
var aCtor = a.constructor, bCtor = b.constructor; | |
if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor && _.isFunction(bCtor) && bCtor instanceof bCtor)) { | |
return false; | |
} | |
for (var key in a) { | |
if (_.has(a, key)) { | |
size++; | |
if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break; | |
} | |
} | |
if (result) { | |
for (key in b) { | |
if (_.has(b, key) && !size--) break; | |
} | |
result = !size; | |
} | |
} | |
aStack.pop(); | |
bStack.pop(); | |
return result; | |
}; | |
_.isEqual = function(a, b) { | |
return eq(a, b, [], []); | |
}; | |
_.isEmpty = function(obj) { | |
if (obj == null) return true; | |
if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; | |
for (var key in obj) if (_.has(obj, key)) return false; | |
return true; | |
}; | |
_.isElement = function(obj) { | |
return !!(obj && obj.nodeType === 1); | |
}; | |
_.isArray = nativeIsArray || function(obj) { | |
return toString.call(obj) == "[object Array]"; | |
}; | |
_.isObject = function(obj) { | |
return obj === Object(obj); | |
}; | |
each([ "Arguments", "Function", "String", "Number", "Date", "RegExp" ], function(name) { | |
_["is" + name] = function(obj) { | |
return toString.call(obj) == "[object " + name + "]"; | |
}; | |
}); | |
if (!_.isArguments(arguments)) { | |
_.isArguments = function(obj) { | |
return !!(obj && _.has(obj, "callee")); | |
}; | |
} | |
if (typeof /./ !== "function") { | |
_.isFunction = function(obj) { | |
return typeof obj === "function"; | |
}; | |
} | |
_.isFinite = function(obj) { | |
return _.isNumber(obj) && isFinite(obj); | |
}; | |
_.isNaN = function(obj) { | |
return _.isNumber(obj) && obj != +obj; | |
}; | |
_.isBoolean = function(obj) { | |
return obj === true || obj === false || toString.call(obj) == "[object Boolean]"; | |
}; | |
_.isNull = function(obj) { | |
return obj === null; | |
}; | |
_.isUndefined = function(obj) { | |
return obj === void 0; | |
}; | |
_.has = function(obj, key) { | |
return hasOwnProperty.call(obj, key); | |
}; | |
_.noConflict = function() { | |
root._ = previousUnderscore; | |
return this; | |
}; | |
_.identity = function(value) { | |
return value; | |
}; | |
_.times = function(n, iterator, context) { | |
for (var i = 0; i < n; i++) iterator.call(context, i); | |
}; | |
_.random = function(min, max) { | |
if (max == null) { | |
max = min; | |
min = 0; | |
} | |
return min + (0 | Math.random() * (max - min + 1)); | |
}; | |
var entityMap = { | |
escape: { | |
"&": "&", | |
"<": "<", | |
">": ">", | |
'"': """, | |
"'": "'", | |
"/": "/" | |
} | |
}; | |
entityMap.unescape = _.invert(entityMap.escape); | |
var entityRegexes = { | |
escape: new RegExp("[" + _.keys(entityMap.escape).join("") + "]", "g"), | |
unescape: new RegExp("(" + _.keys(entityMap.unescape).join("|") + ")", "g") | |
}; | |
_.each([ "escape", "unescape" ], function(method) { | |
_[method] = function(string) { | |
if (string == null) return ""; | |
return ("" + string).replace(entityRegexes[method], function(match) { | |
return entityMap[method][match]; | |
}); | |
}; | |
}); | |
_.result = function(object, property) { | |
if (object == null) return null; | |
var value = object[property]; | |
return _.isFunction(value) ? value.call(object) : value; | |
}; | |
_.mixin = function(obj) { | |
each(_.functions(obj), function(name) { | |
var func = _[name] = obj[name]; | |
_.prototype[name] = function() { | |
var args = [ this._wrapped ]; | |
push.apply(args, arguments); | |
return result.call(this, func.apply(_, args)); | |
}; | |
}); | |
}; | |
var idCounter = 0; | |
_.uniqueId = function(prefix) { | |
var id = idCounter++; | |
return prefix ? prefix + id : id; | |
}; | |
_.templateSettings = { | |
evaluate: /<%([\s\S]+?)%>/g, | |
interpolate: /<%=([\s\S]+?)%>/g, | |
escape: /<%-([\s\S]+?)%>/g | |
}; | |
var noMatch = /(.)^/; | |
var escapes = { | |
"'": "'", | |
"\\": "\\", | |
"\r": "r", | |
"\n": "n", | |
"\t": "t", | |
"\u2028": "u2028", | |
"\u2029": "u2029" | |
}; | |
var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; | |
_.template = function(text, data, settings) { | |
settings = _.defaults({}, settings, _.templateSettings); | |
var matcher = new RegExp([ (settings.escape || noMatch).source, (settings.interpolate || noMatch).source, (settings.evaluate || noMatch).source ].join("|") + "|$", "g"); | |
var index = 0; | |
var source = "__p+='"; | |
text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { | |
source += text.slice(index, offset).replace(escaper, function(match) { | |
return "\\" + escapes[match]; | |
}); | |
source += escape ? "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'" : interpolate ? "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'" : evaluate ? "';\n" + evaluate + "\n__p+='" : ""; | |
index = offset + match.length; | |
}); | |
source += "';\n"; | |
if (!settings.variable) source = "with(obj||{}){\n" + source + "}\n"; | |
source = "var __t,__p='',__j=Array.prototype.join," + "print=function(){__p+=__j.call(arguments,'');};\n" + source + "return __p;\n"; | |
try { | |
var render = new Function(settings.variable || "obj", "_", source); | |
} catch (e) { | |
e.source = source; | |
throw e; | |
} | |
if (data) return render(data, _); | |
var template = function(data) { | |
return render.call(this, data, _); | |
}; | |
template.source = "function(" + (settings.variable || "obj") + "){\n" + source + "}"; | |
return template; | |
}; | |
_.chain = function(obj) { | |
return _(obj).chain(); | |
}; | |
var result = function(obj) { | |
return this._chain ? _(obj).chain() : obj; | |
}; | |
_.mixin(_); | |
each([ "pop", "push", "reverse", "shift", "sort", "splice", "unshift" ], function(name) { | |
var method = ArrayProto[name]; | |
_.prototype[name] = function() { | |
var obj = this._wrapped; | |
method.apply(obj, arguments); | |
if ((name == "shift" || name == "splice") && obj.length === 0) delete obj[0]; | |
return result.call(this, obj); | |
}; | |
}); | |
each([ "concat", "join", "slice" ], function(name) { | |
var method = ArrayProto[name]; | |
_.prototype[name] = function() { | |
return result.call(this, method.apply(this._wrapped, arguments)); | |
}; | |
}); | |
_.extend(_.prototype, { | |
chain: function() { | |
this._chain = true; | |
return this; | |
}, | |
value: function() { | |
return this._wrapped; | |
} | |
}); | |
function module(ignore, func) { | |
func({ | |
Emscripten: Module | |
}); | |
} | |
var superFixtures = []; | |
function registerSuperFixture(superFixture) { | |
superFixtures.push(superFixture); | |
} | |
var allTests = []; | |
function test(name, fn) { | |
if (arguments.length !== 2) { | |
throw new TypeError("test requires 2 arguments"); | |
} | |
if (undefined !== activeFixture && activeFixture.abstract) { | |
activeFixture.abstractTests.push({ | |
name: name, | |
body: fn | |
}); | |
} else { | |
var fixtureName = undefined !== activeFixture ? activeFixture.name + ": " : ""; | |
allTests.push({ | |
name: fixtureName + name, | |
body: fn, | |
fixture: activeFixture | |
}); | |
} | |
} | |
function runTest(test, continuation) { | |
try { | |
var afterTests = []; | |
for (var i = 0; i < superFixtures.length; ++i) { | |
var superFixture = superFixtures[i]; | |
var superScope = {}; | |
superFixture.beforeTest.call(superScope); | |
afterTests.push(superFixture.afterTest.bind(superScope)); | |
} | |
var testScope = test.fixture ? Object.create(test.fixture.scope) : {}; | |
var runSetUp = function(fixtureObject) { | |
if (undefined === fixtureObject) { | |
return; | |
} | |
runSetUp(fixtureObject.parent); | |
fixtureObject.setUp.call(testScope); | |
afterTests.push(fixtureObject.tearDown.bind(testScope)); | |
}; | |
runSetUp(test.fixture); | |
test.body.call(testScope); | |
while (afterTests.length) { | |
afterTests.pop()(); | |
} | |
return false; | |
} catch (e) { | |
console.error(e.stack); | |
console.error("error:", e); | |
return { | |
stack: e.stack, | |
e: e | |
}; | |
} | |
} | |
function run_all(reporter) { | |
for (var i = 0; i < allTests.length; ++i) { | |
var test = allTests[i]; | |
reporter({ | |
type: "test-start", | |
name: test.name | |
}); | |
var failed = runTest(test); | |
if (failed) { | |
reporter({ | |
type: "test-complete", | |
name: test.name, | |
verdict: "FAIL", | |
stack: failed.stack, | |
e: failed.e | |
}); | |
return false; | |
} else { | |
reporter({ | |
type: "test-complete", | |
name: test.name, | |
verdict: "PASS" | |
}); | |
} | |
} | |
reporter({ | |
type: "all-tests-complete" | |
}); | |
allTests = []; | |
return true; | |
} | |
var activeFixture; | |
function Fixture(parent, name, definition, abstract_) { | |
if (!(definition instanceof Function)) { | |
throw new TypeError("fixture's 2nd argument must be a function"); | |
} | |
this.name = name; | |
this.parent = parent; | |
this.abstract = abstract_; | |
if (this.abstract) { | |
this.abstractTests = []; | |
} | |
if (this.parent !== undefined) { | |
this.parent.addAbstractTests(this); | |
} | |
this.scope = this.parent === undefined ? {} : Object.create(this.parent.scope); | |
this.scope.setUp = function(setUp) { | |
this.setUp = setUp; | |
}.bind(this); | |
this.scope.tearDown = function(tearDown) { | |
this.tearDown = tearDown; | |
}.bind(this); | |
if (undefined !== activeFixture) { | |
throw new TypeError("Cannot define a fixture within another fixture"); | |
} | |
activeFixture = this; | |
try { | |
definition.call(this.scope); | |
} finally { | |
activeFixture = undefined; | |
} | |
} | |
Fixture.prototype.setUp = function defaultSetUp() {}; | |
Fixture.prototype.tearDown = function defaultTearDown() {}; | |
Fixture.prototype.addAbstractTests = function(concreteFixture) { | |
if (this.abstract) { | |
for (var i = 0; i < this.abstractTests.length; ++i) { | |
var test = this.abstractTests[i]; | |
allTests.push({ | |
name: concreteFixture.name + ": " + test.name, | |
body: test.body, | |
fixture: concreteFixture | |
}); | |
} | |
} | |
if (this.parent) { | |
this.parent.addAbstractTests(concreteFixture); | |
} | |
}; | |
Fixture.prototype.extend = function(fixtureName, definition) { | |
return new Fixture(this, fixtureName, definition, false); | |
}; | |
function fixture(fixtureName, definition) { | |
return new Fixture(undefined, fixtureName, definition, false); | |
} | |
fixture.abstract = function(fixtureName, definition) { | |
return new Fixture(undefined, fixtureName, definition, true); | |
}; | |
var AssertionError = Error; | |
function fail(exception, info) { | |
exception.info = info; | |
throw exception; | |
} | |
var formatTestValue = function(v) { | |
if (v === undefined) return "undefined"; | |
return v.toString(); | |
}; | |
var assert = {}; | |
assert.fail = function(info) { | |
info = info || "assert.fail()"; | |
fail(new AssertionError(info)); | |
}; | |
assert["true"] = function(value) { | |
if (!value) { | |
fail(new AssertionError("expected truthy, actual " + formatTestValue(value)), { | |
Value: value | |
}); | |
} | |
}; | |
assert["false"] = function(value) { | |
if (value) { | |
fail(new AssertionError("expected falsy, actual " + formatTestValue(value)), { | |
Value: value | |
}); | |
} | |
}; | |
assert.equal = function(expected, actual) { | |
if (expected !== actual) { | |
fail(new AssertionError("expected: " + formatTestValue(expected) + ", actual: " + formatTestValue(actual)), { | |
Expected: expected, | |
Actual: actual | |
}); | |
} | |
}; | |
assert.notEqual = function(expected, actual) { | |
if (expected === actual) { | |
fail(new AssertionError("actual was equal to: " + formatTestValue(expected))); | |
} | |
}; | |
assert.greater = function(lhs, rhs) { | |
if (lhs <= rhs) { | |
fail(new AssertionError(formatTestValue(lhs) + " not greater than " + formatTestValue(rhs))); | |
} | |
}; | |
assert.less = function(lhs, rhs) { | |
if (lhs >= rhs) { | |
fail(new AssertionError(formatTestValue(lhs) + " not less than " + formatTestValue(rhs))); | |
} | |
}; | |
assert.greaterOrEqual = function(lhs, rhs) { | |
if (lhs < rhs) { | |
fail(new AssertionError(formatTestValue(lhs) + " not greater than or equal to " + formatTestValue(rhs))); | |
} | |
}; | |
assert.lessOrEqual = function(lhs, rhs) { | |
if (lhs > rhs) { | |
fail(new AssertionError(formatTestValue(lhs) + " not less than or equal to " + formatTestValue(rhs))); | |
} | |
}; | |
assert.deepEqual = function(expected, actual) { | |
if (!_.isEqual(expected, actual)) { | |
fail(new AssertionError("expected: " + formatTestValue(expected) + ", actual: " + formatTestValue(actual)), { | |
Expected: expected, | |
Actual: actual | |
}); | |
} | |
}; | |
assert.notDeepEqual = function(expected, actual) { | |
if (_.isEqual(expected, actual)) { | |
fail(new AssertionError("expected: " + formatTestValue(expected) + " and actual: " + formatTestValue(actual) + " were equal")); | |
} | |
}; | |
assert.nearEqual = function(expected, actual, tolerance) { | |
if (tolerance === undefined) { | |
tolerance = 0; | |
} | |
if (expected instanceof Array && actual instanceof Array) { | |
assert.equal(expected.length, actual.length); | |
for (var i = 0; i < expected.length; ++i) { | |
assert.nearEqual(expected[i], actual[i], tolerance); | |
} | |
return; | |
} | |
if (Math.abs(expected - actual) > tolerance) { | |
fail(new AssertionError("expected: " + formatTestValue(expected) + ", actual: " + formatTestValue(actual) + ", tolerance: " + formatTestValue(tolerance) + ", diff: " + formatTestValue(actual - expected)), { | |
Expected: expected, | |
Actual: actual, | |
Tolerance: tolerance | |
}); | |
} | |
}; | |
assert.inString = function(expected, string) { | |
if (-1 === string.indexOf(expected)) { | |
fail(new AssertionError("expected: " + formatTestValue(expected) + " not in string: " + formatTestValue(string)), { | |
Expected: expected, | |
"String": string | |
}); | |
} | |
}; | |
assert.notInString = function(expected, string) { | |
if (-1 !== string.indexOf(expected)) { | |
fail(new AssertionError("unexpected: " + formatTestValue(expected) + " in string: " + formatTestValue(string)), { | |
Expected: expected, | |
"String": string | |
}); | |
} | |
}; | |
assert.matches = function(re, string) { | |
if (!re.test(string)) { | |
fail(new AssertionError("regexp " + re + " does not match: " + string)); | |
} | |
}; | |
assert.inArray = function(expected, array) { | |
var found = false; | |
_.each(array, function(element) { | |
if (_.isEqual(expected, element)) { | |
found = true; | |
} | |
}); | |
if (!found) { | |
fail(new AssertionError("expected: " + formatTestValue(expected) + " not found in array: " + formatTestValue(array)), { | |
Expected: expected, | |
"Array": array | |
}); | |
} | |
}; | |
assert.notInArray = function(expected, array) { | |
var found = false; | |
_.each(array, function(element) { | |
if (_.isEqual(expected, element)) { | |
found = true; | |
} | |
}); | |
if (found) { | |
fail(new AssertionError("unexpected: " + formatTestValue(expected) + " found in array: " + formatTestValue(array)), { | |
Expected: expected, | |
"Array": array | |
}); | |
} | |
}; | |
assert.hasKey = function(key, object) { | |
if (!(key in object)) { | |
fail(new AssertionError("Key " + formatTestValue(key) + " is not in object: " + formatTestValue(object))); | |
} | |
}; | |
assert.notHasKey = function(key, object) { | |
if (key in object) { | |
fail(new AssertionError("Unexpected key " + formatTestValue(key) + " is found in object: " + formatTestValue(object))); | |
} | |
}; | |
assert.throws = function(exception, fn) { | |
try { | |
fn(); | |
} catch (e) { | |
if (e instanceof exception) { | |
return e; | |
} | |
fail(new AssertionError('Expected to throw "' + exception.name + '", actually threw: ' + formatTestValue(e) + ": " + e.message), { | |
Expected: exception, | |
Actual: e | |
}); | |
} | |
throw new AssertionError("did not throw"); | |
}; | |
assert["instanceof"] = function(actual, type) { | |
if (!(actual instanceof type)) { | |
fail(new AssertionError(formatTestValue(actual) + " not instance of " + formatTestValue(type)), { | |
Type: type, | |
Actual: actual | |
}); | |
} | |
}; | |
assert.dom = { | |
present: function(domElement) { | |
if (!$(domElement).length) { | |
fail(new AssertionError(decipherDomElement(domElement) + " should be present")); | |
} | |
}, | |
notPresent: function(selector) { | |
assert.equal(0, $(selector).length); | |
}, | |
hasTag: function(tag, domElement) { | |
var elementTag = $(domElement)[0].tagName.toLowerCase(); | |
if (elementTag !== tag.toLowerCase()) { | |
fail(new AssertionError(decipherDomElement(domElement) + " expected to have tag name " + formatTestValue(tag) + ", was " + formatTestValue(elementTag) + " instead")); | |
} | |
}, | |
hasClass: function(className, domElement) { | |
if (!$(domElement).hasClass(className)) { | |
fail(new AssertionError(decipherDomElement(domElement) + " expected to have class " + formatTestValue(className) + ", has " + formatTestValue($(domElement).attr("class")) + " instead")); | |
} | |
}, | |
notHasClass: function(className, domElement) { | |
assert.dom.present(domElement); | |
if ($(domElement).hasClass(className)) { | |
fail(new AssertionError(decipherDomElement(domElement) + " expected NOT to have class " + formatTestValue(className))); | |
} | |
}, | |
hasAttribute: function(attributeName, selector) { | |
assert["true"]($(selector).is("[" + attributeName + "]")); | |
}, | |
notHasAttribute: function(attributeName, selector) { | |
assert.dom.present(selector); | |
assert["false"]($(selector).is("[" + attributeName + "]")); | |
}, | |
attr: function(value, attributeName, selector) { | |
assert.equal(value, $(selector).attr(attributeName)); | |
}, | |
attributeValues: function(values, selector) { | |
var $el = $(selector); | |
_(values).each(function(val, key) { | |
assert.equal(val, $el.attr(key)); | |
}); | |
}, | |
text: function(expected, selector) { | |
assert.equal(expected, $(selector).text()); | |
}, | |
value: function(expected, selector) { | |
assert.equal(expected, $(selector).val()); | |
}, | |
count: function(elementCount, selector) { | |
assert.equal(elementCount, $(selector).length); | |
}, | |
visible: function(domElement) { | |
if (!$(domElement).is(":visible")) { | |
fail(new AssertionError(decipherDomElement(domElement) + " expected to be visible")); | |
} | |
}, | |
notVisible: function(domElement) { | |
assert.dom.present(domElement); | |
if ($(domElement).is(":visible")) { | |
fail(new AssertionError(decipherDomElement(domElement) + " expected to be NOT visible")); | |
} | |
}, | |
disabled: function(domElement) { | |
if (!$(domElement).is(":disabled")) { | |
fail(new AssertionError(decipherDomElement(domElement) + " expected to be disabled")); | |
} | |
}, | |
enabled: function(domElement) { | |
if (!$(domElement).is(":enabled")) { | |
fail(new AssertionError(decipherDomElement(domElement) + " expected to be enabled")); | |
} | |
}, | |
focused: function(selector) { | |
var expected = $(selector)[0]; | |
var actual = document.activeElement; | |
if (expected !== actual) { | |
throw new AssertionError(actual.outerHTML + " has focus. expected: " + expected.outerHTML); | |
} | |
}, | |
notFocused: function(selector) { | |
var expected = $(selector)[0]; | |
var actual = document.activeElement; | |
if (expected === actual) { | |
throw new AssertionError(expected.outerHTML + " expected not to have focus."); | |
} | |
}, | |
html: function(expected, selector) { | |
assert.equal(expected, $(selector).html()); | |
}, | |
css: function(expected, propertyName, selector) { | |
assert.equal(expected, $(selector).css(propertyName)); | |
}, | |
empty: function(selectorOrJQueryObject) { | |
var el = selectorOrJQueryObject; | |
assert.dom.present(el); | |
if (!$(el).is(":empty")) { | |
fail(new AssertionError(decipherDomElement(el) + " expected to be empty")); | |
} | |
}, | |
notEmpty: function(selectorOrJQueryObject) { | |
var el = selectorOrJQueryObject; | |
assert.dom.present(el); | |
if ($(el).is(":empty")) { | |
fail(new AssertionError(decipherDomElement(el) + " expected NOT to be empty")); | |
} | |
} | |
}; | |
function decipherDomElement(selectorOrJQueryObject) { | |
if (typeof selectorOrJQueryObject === "string") { | |
return "Selector " + formatTestValue(selectorOrJQueryObject); | |
} else if (typeof selectorOrJQueryObject === "object") { | |
return "'" + selectorOrJQueryObject[0] + "'"; | |
} | |
} | |
(function() { | |
var g = "undefined" === typeof window ? global : window; | |
assert.equals = assert.equal; | |
assert.notEquals = assert.notEqual; | |
assert["null"] = assert.equal.bind(null, null); | |
assert.notNull = assert.notEqual.bind(null, null); | |
assert["undefined"] = assert.equal.bind(null, undefined); | |
assert.notUndefined = assert.notEqual.bind(null, undefined); | |
g.registerSuperFixture = registerSuperFixture; | |
g.test = test; | |
g.run_all = run_all; | |
g.fixture = fixture; | |
g.AssertionError = AssertionError; | |
g.assert = assert; | |
g.test = test; | |
g.TEST_MAX_OUTPUT_SIZE = 1024; | |
g.setTimeout = function(fn, time) { | |
if (time === 1 || time === 0) { | |
fn(); | |
return 0; | |
} | |
throw new AssertionError("Don't call setTimeout in tests. Use fakes."); | |
}; | |
g.setInterval = function() { | |
throw new AssertionError("Don't call setInterval in tests. Use fakes."); | |
}; | |
Math.random = function() { | |
throw new AssertionError("Don't call Math.random in tests. Use fakes."); | |
}; | |
g.requestAnimationFrame = function() { | |
throw new AssertionError("Don't call requestAnimationFrame in tests. Use fakes."); | |
}; | |
})(); | |
function run_all_tests() { | |
function report_to_stdout(msg) { | |
if (msg.type === "test-complete") console.log(msg.name + ": " + msg.verdict); | |
} | |
run_all(report_to_stdout); | |
} | |
var INVOKED_FROM_EMSCRIPTEN_TEST_RUNNER = 1; | |
module({ | |
Emscripten: "../../../../build/embind_test.js" | |
}, function(imports) { | |
var cm = imports.Emscripten; | |
var CheckForLeaks = fixture("check for leaks", function() { | |
this.setUp(function() { | |
cm.setDelayFunction(undefined); | |
if (typeof INVOKED_FROM_EMSCRIPTEN_TEST_RUNNER === "undefined") { | |
assert.equal(0, cm.count_emval_handles()); | |
} | |
}); | |
this.tearDown(function() { | |
cm.flushPendingDeletes(); | |
if (typeof INVOKED_FROM_EMSCRIPTEN_TEST_RUNNER === "undefined") { | |
assert.equal(0, cm.count_emval_handles()); | |
} | |
}); | |
}); | |
var BaseFixture = CheckForLeaks; | |
BaseFixture.extend("temp jig", function() { | |
test("temp test", function() {}); | |
}); | |
BaseFixture.extend("access to base class members", function() { | |
test("method name in derived class silently overrides inherited name", function() { | |
var derived = new cm.Derived(); | |
assert.equal("Derived", derived.getClassName()); | |
derived.delete(); | |
}); | |
test("can reference base method from derived class", function() { | |
var derived = new cm.Derived(); | |
assert.equal("Base", derived.getClassNameFromBase()); | |
derived.delete(); | |
}); | |
test("can reference base method from doubly derived class", function() { | |
var derivedTwice = new cm.DerivedTwice(); | |
assert.equal("Base", derivedTwice.getClassNameFromBase()); | |
derivedTwice.delete(); | |
}); | |
test("can reference base method through unbound classes", function() { | |
var derivedThrice = new cm.DerivedThrice(); | |
assert.equal("Base", derivedThrice.getClassNameFromBase()); | |
derivedThrice.delete(); | |
}); | |
test("property name in derived class hides identically named property in base class for set", function() { | |
var derived = new cm.Derived(); | |
derived.setMember(7); | |
derived.member = 17; | |
assert.equal(17, derived.getMember()); | |
derived.delete(); | |
}); | |
test("can reference base property from derived class for get", function() { | |
var derived = new cm.Derived(); | |
derived.setBaseMember(5); | |
assert.equal(5, derived.baseMember); | |
derived.delete(); | |
}); | |
test("can reference property of any base class for get when multiply derived", function() { | |
var derived = new cm.MultiplyDerived(); | |
derived.setBaseMember(11); | |
assert.equal(11, derived.baseMember); | |
derived.delete(); | |
}); | |
test("can reference base property from derived class for set", function() { | |
var derived = new cm.Derived(); | |
derived.baseMember = 32; | |
assert.equal(32, derived.getBaseMember()); | |
derived.delete(); | |
}); | |
test("can reference property of any base for set when multiply derived", function() { | |
var derived = new cm.MultiplyDerived(); | |
derived.setBaseMember(97); | |
derived.baseMember = 32; | |
assert.equal(32, derived.getBaseMember()); | |
derived.delete(); | |
}); | |
test("can reach around derived property to access base property with same name for get", function() { | |
var derived = new cm.Derived(); | |
derived.setMember(12); | |
derived.delete(); | |
}); | |
test("if deriving from second base adjusts pointer", function() { | |
var derived = new cm.HasTwoBases(); | |
assert.equal("Base2", derived.getField()); | |
derived.delete(); | |
}); | |
test("properties adjust pointer", function() { | |
var derived = new cm.HasTwoBases(); | |
derived.field = "Foo"; | |
assert.equal("Foo", derived.getField()); | |
assert.equal("Foo", derived.field); | |
derived.delete(); | |
}); | |
test("calling method on unrelated class throws error", function() { | |
var a = new cm.HasTwoBases(); | |
var e = assert.throws(cm.BindingError, function() { | |
cm.Derived.prototype.setMember.call(a, "foo"); | |
}); | |
assert.equal("Expected null or instance of Derived, got an instance of Base2", e.message); | |
a.delete(); | |
var b = new cm.Base1(); | |
var e = assert.throws(cm.BindingError, function() { | |
cm.Base2.prototype.getField.call(b); | |
}); | |
assert.equal("Expected null or instance of Base2, got an instance of Base1", e.message); | |
b.delete(); | |
}); | |
test("calling method with invalid this throws error", function() { | |
var e = assert.throws(cm.BindingError, function() { | |
cm.Derived.prototype.setMember.call(undefined, "foo"); | |
}); | |
assert.equal('Cannot pass "[object global]" as a Derived*', e.message); | |
var e = assert.throws(cm.BindingError, function() { | |
cm.Derived.prototype.setMember.call(true, "foo"); | |
}); | |
assert.equal('Cannot pass "true" as a Derived*', e.message); | |
var e = assert.throws(cm.BindingError, function() { | |
cm.Derived.prototype.setMember.call(null, "foo"); | |
}); | |
assert.equal('Cannot pass "[object global]" as a Derived*', e.message); | |
var e = assert.throws(cm.BindingError, function() { | |
cm.Derived.prototype.setMember.call(42, "foo"); | |
}); | |
assert.equal('Cannot pass "42" as a Derived*', e.message); | |
var e = assert.throws(cm.BindingError, function() { | |
cm.Derived.prototype.setMember.call("this", "foo"); | |
}); | |
assert.equal('Cannot pass "this" as a Derived*', e.message); | |
var e = assert.throws(cm.BindingError, function() { | |
cm.Derived.prototype.setMember.call({}, "foo"); | |
}); | |
assert.equal('Cannot pass "[object Object]" as a Derived*', e.message); | |
}); | |
test("setting and getting property on unrelated class throws error", function() { | |
var a = new cm.HasTwoBases(); | |
var e = assert.throws(cm.BindingError, function() { | |
Object.getOwnPropertyDescriptor(cm.HeldBySmartPtr.prototype, "i").set.call(a, 10); | |
}); | |
assert.equal('HeldBySmartPtr.i setter incompatible with "this" of type HasTwoBases', e.message); | |
var e = assert.throws(cm.BindingError, function() { | |
Object.getOwnPropertyDescriptor(cm.HeldBySmartPtr.prototype, "i").get.call(a); | |
}); | |
assert.equal('HeldBySmartPtr.i getter incompatible with "this" of type HasTwoBases', e.message); | |
a.delete(); | |
}); | |
}); | |
BaseFixture.extend("automatic upcasting of parameters passed to C++", function() { | |
test("raw pointer argument is upcast to parameter type", function() { | |
var derived = new cm.Derived(); | |
var name = cm.embind_test_get_class_name_via_base_ptr(derived); | |
assert.equal("Base", name); | |
derived.delete(); | |
}); | |
test("automatic raw pointer upcasting works with multiple inheritance", function() { | |
var derived = new cm.MultiplyDerived(); | |
var name = cm.embind_test_get_class_name_via_base_ptr(derived); | |
assert.equal("Base", name); | |
derived.delete(); | |
}); | |
test("automatic raw pointer upcasting does not change local pointer", function() { | |
var derived = new cm.MultiplyDerived(); | |
cm.embind_test_get_class_name_via_base_ptr(derived); | |
assert.equal("MultiplyDerived", derived.getClassName()); | |
derived.delete(); | |
}); | |
test("passing incompatible raw pointer to method throws exception", function() { | |
var base = new cm.Base(); | |
assert.throws(cm.BindingError, function() { | |
cm.embind_test_get_class_name_via_second_base_ptr(base); | |
}); | |
base.delete(); | |
}); | |
test("polymorphic raw pointer argument is upcast to parameter type", function() { | |
var derived = new cm.PolyDerived(); | |
var name = cm.embind_test_get_class_name_via_polymorphic_base_ptr(derived); | |
assert.equal("PolyBase", name); | |
derived.delete(); | |
}); | |
test("automatic polymorphic raw pointer upcasting works with multiple inheritance", function() { | |
var derived = new cm.PolyMultiplyDerived(); | |
var name = cm.embind_test_get_class_name_via_polymorphic_base_ptr(derived); | |
assert.equal("PolyBase", name); | |
derived.delete(); | |
}); | |
test("passing incompatible raw polymorphic pointer to method throws exception", function() { | |
var base = new cm.PolyBase(); | |
assert.throws(cm.BindingError, function() { | |
cm.embind_test_get_class_name_via_polymorphic_second_base_ptr(base); | |
}); | |
base.delete(); | |
}); | |
test("can pass smart pointer to raw pointer parameter", function() { | |
var smartBase = cm.embind_test_return_smart_base_ptr(); | |
assert.equal("Base", cm.embind_test_get_class_name_via_base_ptr(smartBase)); | |
smartBase.delete(); | |
}); | |
test("can pass and upcast smart pointer to raw pointer parameter", function() { | |
var smartDerived = cm.embind_test_return_smart_derived_ptr(); | |
assert.equal("Base", cm.embind_test_get_class_name_via_base_ptr(smartDerived)); | |
smartDerived.delete(); | |
}); | |
test("smart pointer argument is upcast to parameter type", function() { | |
var derived = cm.embind_test_return_smart_derived_ptr(); | |
assert.instanceof(derived, cm.Derived); | |
assert.instanceof(derived, cm.Base); | |
var name = cm.embind_test_get_class_name_via_smart_base_ptr(derived); | |
assert.equal("Base", name); | |
derived.delete(); | |
}); | |
test("return smart derived ptr as base", function() { | |
var derived = cm.embind_test_return_smart_derived_ptr_as_base(); | |
assert.equal("PolyDerived", cm.embind_test_get_virtual_class_name_via_smart_polymorphic_base_ptr(derived)); | |
assert.equal("PolyDerived", derived.getClassName()); | |
derived.delete(); | |
}); | |
test("return smart derived ptr as val", function() { | |
var derived = cm.embind_test_return_smart_derived_ptr_as_val(); | |
assert.equal("PolyDerived", cm.embind_test_get_virtual_class_name_via_smart_polymorphic_base_ptr(derived)); | |
derived.delete(); | |
}); | |
test("automatic smart pointer upcasting works with multiple inheritance", function() { | |
var derived = cm.embind_test_return_smart_multiply_derived_ptr(); | |
var name = cm.embind_test_get_class_name_via_smart_base_ptr(derived); | |
assert.equal("Base", name); | |
derived.delete(); | |
}); | |
test("automatically upcasted smart pointer parameter shares ownership with original argument", function() { | |
var derived = cm.embind_test_return_smart_multiply_derived_ptr(); | |
assert.equal(1, cm.MultiplyDerived.getInstanceCount()); | |
cm.embind_save_smart_base_pointer(derived); | |
assert.equal(1, cm.MultiplyDerived.getInstanceCount()); | |
derived.delete(); | |
assert.equal(1, cm.MultiplyDerived.getInstanceCount()); | |
cm.embind_save_smart_base_pointer(null); | |
assert.equal(0, cm.MultiplyDerived.getInstanceCount()); | |
}); | |
test("smart polymorphic pointer argument is upcast to parameter type", function() { | |
var derived = cm.embind_test_return_smart_polymorphic_derived_ptr(); | |
var name = cm.embind_test_get_class_name_via_smart_polymorphic_base_ptr(derived); | |
assert.equal("PolyBase", name); | |
derived.delete(); | |
}); | |
test("automatic smart polymorphic pointer upcasting works with multiple inheritance", function() { | |
var derived = cm.embind_test_return_smart_polymorphic_multiply_derived_ptr(); | |
var name = cm.embind_test_get_class_name_via_smart_polymorphic_base_ptr(derived); | |
assert.equal("PolyBase", name); | |
derived.delete(); | |
}); | |
}); | |
BaseFixture.extend("automatic downcasting of return values received from C++", function() { | |
test("non-polymorphic raw pointers are not downcast and do not break automatic casting mechanism", function() { | |
var base = cm.embind_test_return_raw_derived_ptr_as_base(); | |
assert.equal("Base", base.getClassName()); | |
assert.instanceof(base, cm.Base); | |
base.delete(); | |
}); | |
test("polymorphic raw pointer return value is downcast to allocated type (if that is bound)", function() { | |
var derived = cm.embind_test_return_raw_polymorphic_derived_ptr_as_base(); | |
assert.instanceof(derived, cm.PolyBase); | |
assert.instanceof(derived, cm.PolyDerived); | |
assert.equal("PolyDerived", derived.getClassName()); | |
var siblingDerived = cm.embind_test_return_raw_polymorphic_sibling_derived_ptr_as_base(); | |
assert.equal("PolySiblingDerived", siblingDerived.getClassName()); | |
siblingDerived.delete(); | |
derived.delete(); | |
}); | |
test("polymorphic raw pointer return value is downcast to the most derived bound type", function() { | |
var derivedThrice = cm.embind_test_return_raw_polymorphic_derived_four_times_not_bound_as_base(); | |
assert.equal("PolyBase", derivedThrice.getClassName()); | |
derivedThrice.delete(); | |
}); | |
test("polymorphic smart pointer return value is downcast to the most derived type which has an associated smart pointer", function() { | |
var derived = cm.embind_test_return_poly_derived_twice_without_smart_pointer_as_poly_base(); | |
assert.equal("PolyBase", derived.getClassName()); | |
derived.delete(); | |
}); | |
test("automatic downcasting works with multiple inheritance", function() { | |
var base = cm.embind_test_return_raw_polymorphic_multiply_derived_ptr_as_base(); | |
var secondBase = cm.embind_test_return_raw_polymorphic_multiply_derived_ptr_as_second_base(); | |
assert.equal("PolyMultiplyDerived", base.getClassName()); | |
secondBase.delete(); | |
base.delete(); | |
}); | |
test("non-polymorphic smart pointers do not break automatic casting mechanism", function() {}); | |
test("automatically downcasting a smart pointer does not change the underlying pointer", function() { | |
cm.PolyDerived.setPtrDerived(); | |
assert.equal("PolyBase", cm.PolyDerived.getPtrClassName()); | |
var derived = cm.PolyDerived.getPtr(); | |
assert.equal("PolyDerived", derived.getClassName()); | |
assert.equal("PolyBase", cm.PolyDerived.getPtrClassName()); | |
derived.delete(); | |
cm.PolyDerived.releasePtr(); | |
}); | |
test("polymorphic smart pointer return value is actual allocated type (when bound)", function() { | |
var derived = cm.embind_test_return_smart_polymorphic_derived_ptr_as_base(); | |
assert.equal("PolyDerived", derived.getClassName()); | |
var siblingDerived = cm.embind_test_return_smart_polymorphic_sibling_derived_ptr_as_base(); | |
assert.equal("PolySiblingDerived", siblingDerived.getClassName()); | |
siblingDerived.delete(); | |
derived.delete(); | |
}); | |
}); | |
BaseFixture.extend("string", function() { | |
var stdStringIsUTF8 = getCompilerSetting("EMBIND_STD_STRING_IS_UTF8") === true; | |
test("non-ascii strings", function() { | |
var expected = ""; | |
if (stdStringIsUTF8) { | |
expected = "aei"; | |
expected += "áéí"; | |
expected += "αει"; | |
expected += "ЖЛФ"; | |
expected += "從獅子"; | |
expected += "€"; | |
} else { | |
for (var i = 0; i < 128; ++i) { | |
expected += String.fromCharCode(128 + i); | |
} | |
} | |
assert.equal(expected, cm.get_non_ascii_string(stdStringIsUTF8)); | |
}); | |
if (!stdStringIsUTF8) { | |
test("passing non-8-bit strings from JS to std::string throws", function() { | |
assert.throws(cm.BindingError, function() { | |
cm.emval_test_take_and_return_std_string("ሴ"); | |
}); | |
}); | |
} | |
test("can't pass integers as strings", function() { | |
var e = assert.throws(cm.BindingError, function() { | |
cm.emval_test_take_and_return_std_string(10); | |
}); | |
}); | |
test("can pass Uint8Array to std::string", function() { | |
var e = cm.emval_test_take_and_return_std_string(new Uint8Array([ 65, 66, 67, 68 ])); | |
assert.equal("ABCD", e); | |
}); | |
test("can pass Uint8ClampedArray to std::string", function() { | |
var e = cm.emval_test_take_and_return_std_string(new Uint8ClampedArray([ 65, 66, 67, 68 ])); | |
assert.equal("ABCD", e); | |
}); | |
test("can pass Int8Array to std::string", function() { | |
var e = cm.emval_test_take_and_return_std_string(new Int8Array([ 65, 66, 67, 68 ])); | |
assert.equal("ABCD", e); | |
}); | |
test("can pass ArrayBuffer to std::string", function() { | |
var e = cm.emval_test_take_and_return_std_string(new Int8Array([ 65, 66, 67, 68 ]).buffer); | |
assert.equal("ABCD", e); | |
}); | |
test("can pass Uint8Array to std::basic_string<unsigned char>", function() { | |
var e = cm.emval_test_take_and_return_std_basic_string_unsigned_char(new Uint8Array([ 65, 66, 67, 68 ])); | |
assert.equal("ABCD", e); | |
}); | |
test("can pass long string to std::basic_string<unsigned char>", function() { | |
var s = "this string is long enough to exceed the short string optimization"; | |
var e = cm.emval_test_take_and_return_std_basic_string_unsigned_char(s); | |
assert.equal(s, e); | |
}); | |
test("can pass Uint8ClampedArray to std::basic_string<unsigned char>", function() { | |
var e = cm.emval_test_take_and_return_std_basic_string_unsigned_char(new Uint8ClampedArray([ 65, 66, 67, 68 ])); | |
assert.equal("ABCD", e); | |
}); | |
test("can pass Int8Array to std::basic_string<unsigned char>", function() { | |
var e = cm.emval_test_take_and_return_std_basic_string_unsigned_char(new Int8Array([ 65, 66, 67, 68 ])); | |
assert.equal("ABCD", e); | |
}); | |
test("can pass ArrayBuffer to std::basic_string<unsigned char>", function() { | |
var e = cm.emval_test_take_and_return_std_basic_string_unsigned_char(new Int8Array([ 65, 66, 67, 68 ]).buffer); | |
assert.equal("ABCD", e); | |
}); | |
test("can pass string to std::string", function() { | |
var string = stdStringIsUTF8 ? "aeiáéíαειЖЛФ從獅子€" : "ABCD"; | |
var e = cm.emval_test_take_and_return_std_string(string); | |
assert.equal(string, e); | |
}); | |
var utf16TestString = String.fromCharCode(10) + String.fromCharCode(1234) + String.fromCharCode(2345) + String.fromCharCode(65535); | |
var utf32TestString = String.fromCharCode(10) + String.fromCharCode(1234) + String.fromCharCode(2345) + String.fromCharCode(55357) + String.fromCharCode(56833) + String.fromCharCode(55357) + String.fromCharCode(56960); | |
test("non-ascii wstrings", function() { | |
assert.equal(utf16TestString, cm.get_non_ascii_wstring()); | |
}); | |
test("non-ascii u16strings", function() { | |
assert.equal(utf16TestString, cm.get_non_ascii_u16string()); | |
}); | |
test("non-ascii u32strings", function() { | |
assert.equal(utf32TestString, cm.get_non_ascii_u32string()); | |
}); | |
test("passing unicode (wide) string into C++", function() { | |
assert.equal(utf16TestString, cm.take_and_return_std_wstring(utf16TestString)); | |
}); | |
test("passing unicode (utf-16) string into C++", function() { | |
assert.equal(utf16TestString, cm.take_and_return_std_u16string(utf16TestString)); | |
}); | |
test("passing unicode (utf-32) string into C++", function() { | |
assert.equal(utf32TestString, cm.take_and_return_std_u32string(utf32TestString)); | |
}); | |
if (cm.isMemoryGrowthEnabled) { | |
test("can access a literal wstring after a memory growth", function() { | |
cm.force_memory_growth(); | |
assert.equal("get_literal_wstring", cm.get_literal_wstring()); | |
}); | |
test("can access a literal u16string after a memory growth", function() { | |
cm.force_memory_growth(); | |
assert.equal("get_literal_u16string", cm.get_literal_u16string()); | |
}); | |
test("can access a literal u32string after a memory growth", function() { | |
cm.force_memory_growth(); | |
assert.equal("get_literal_u32string", cm.get_literal_u32string()); | |
}); | |
} | |
}); | |
BaseFixture.extend("embind", function() { | |
test("value creation", function() { | |
assert.equal(15, cm.emval_test_new_integer()); | |
assert.equal("Hello everyone", cm.emval_test_new_string()); | |
assert.equal("Hello everyone", cm.emval_test_get_string_from_val({ | |
key: "Hello everyone" | |
})); | |
var object = cm.emval_test_new_object(); | |
assert.equal("bar", object.foo); | |
assert.equal(1, object.baz); | |
}); | |
test("pass const reference to primitive", function() { | |
assert.equal(3, cm.const_ref_adder(1, 2)); | |
}); | |
test("get instance pointer as value", function() { | |
var v = cm.emval_test_instance_pointer(); | |
assert.instanceof(v, cm.DummyForPointer); | |
}); | |
test("cast value to instance pointer using as<T*>", function() { | |
var v = cm.emval_test_instance_pointer(); | |
var p_value = cm.emval_test_value_from_instance_pointer(v); | |
assert.equal(42, p_value); | |
}); | |
test("passthrough", function() { | |
var a = { | |
foo: "bar" | |
}; | |
var b = cm.emval_test_passthrough(a); | |
a.bar = "baz"; | |
assert.equal("baz", b.bar); | |
assert.equal(0, cm.count_emval_handles()); | |
}); | |
test("void return converts to undefined", function() { | |
assert.equal(undefined, cm.emval_test_return_void()); | |
}); | |
test("booleans can be marshalled", function() { | |
assert.equal(false, cm.emval_test_not(true)); | |
assert.equal(true, cm.emval_test_not(false)); | |
}); | |
test("val.is_undefined() is functional", function() { | |
assert.equal(true, cm.emval_test_is_undefined(undefined)); | |
assert.equal(false, cm.emval_test_is_undefined(true)); | |
assert.equal(false, cm.emval_test_is_undefined(false)); | |
assert.equal(false, cm.emval_test_is_undefined(null)); | |
assert.equal(false, cm.emval_test_is_undefined({})); | |
}); | |
test("val.is_null() is functional", function() { | |
assert.equal(true, cm.emval_test_is_null(null)); | |
assert.equal(false, cm.emval_test_is_null(true)); | |
assert.equal(false, cm.emval_test_is_null(false)); | |
assert.equal(false, cm.emval_test_is_null(undefined)); | |
assert.equal(false, cm.emval_test_is_null({})); | |
}); | |
test("val.is_true() is functional", function() { | |
assert.equal(true, cm.emval_test_is_true(true)); | |
assert.equal(false, cm.emval_test_is_true(false)); | |
assert.equal(false, cm.emval_test_is_true(null)); | |
assert.equal(false, cm.emval_test_is_true(undefined)); | |
assert.equal(false, cm.emval_test_is_true({})); | |
}); | |
test("val.is_false() is functional", function() { | |
assert.equal(true, cm.emval_test_is_false(false)); | |
assert.equal(false, cm.emval_test_is_false(true)); | |
assert.equal(false, cm.emval_test_is_false(null)); | |
assert.equal(false, cm.emval_test_is_false(undefined)); | |
assert.equal(false, cm.emval_test_is_false({})); | |
}); | |
test("val.equals() is functional", function() { | |
var values = [ undefined, null, true, false, {} ]; | |
for (var i = 0; i < values.length; ++i) { | |
var first = values[i]; | |
for (var j = i; j < values.length; ++j) { | |
var second = values[j]; | |
assert.equal(first == second, cm.emval_test_equals(first, second)); | |
} | |
} | |
}); | |
test("val.strictlyEquals() is functional", function() { | |
var values = [ undefined, null, true, false, {} ]; | |
for (var i = 0; i < values.length; ++i) { | |
var first = values[i]; | |
for (var j = i; j < values.length; ++j) { | |
var second = values[j]; | |
assert.equal(first === second, cm.emval_test_strictly_equals(first, second)); | |
} | |
} | |
}); | |
test("can pass booleans as integers", function() { | |
assert.equal(1, cm.emval_test_as_unsigned(true)); | |
assert.equal(0, cm.emval_test_as_unsigned(false)); | |
}); | |
test("can pass booleans as floats", function() { | |
assert.equal(2, cm.const_ref_adder(true, true)); | |
}); | |
test("passing Symbol or BigInt as floats always throws", function() { | |
assert.throws(TypeError, function() { | |
cm.const_ref_adder(Symbol("0"), 1); | |
}); | |
assert.throws(TypeError, function() { | |
cm.const_ref_adder(0n, 1); | |
}); | |
}); | |
if (getCompilerSetting("ASSERTIONS")) { | |
test("can pass only number and boolean as floats with assertions", function() { | |
assert.throws(TypeError, function() { | |
cm.const_ref_adder(1, undefined); | |
}); | |
assert.throws(TypeError, function() { | |
cm.const_ref_adder(1, null); | |
}); | |
assert.throws(TypeError, function() { | |
cm.const_ref_adder(1, "2"); | |
}); | |
}); | |
} else { | |
test("can pass other types as floats without assertions", function() { | |
assert.equal(3, cm.const_ref_adder(1, "2")); | |
assert.equal(1, cm.const_ref_adder(1, null)); | |
assert.true(isNaN(cm.const_ref_adder(1, "cannot parse"))); | |
assert.true(isNaN(cm.const_ref_adder(1, undefined))); | |
}); | |
} | |
test("convert double to unsigned", function() { | |
var rv = cm.emval_test_as_unsigned(1.5); | |
assert.equal("number", typeof rv); | |
assert.equal(1, rv); | |
assert.equal(0, cm.count_emval_handles()); | |
}); | |
test("get length of array", function() { | |
assert.equal(10, cm.emval_test_get_length([ 0, 1, 2, 3, 4, 5, "a", "b", "c", "d" ])); | |
assert.equal(0, cm.count_emval_handles()); | |
}); | |
test("add a bunch of things", function() { | |
assert.equal(66, cm.emval_test_add(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)); | |
assert.equal(0, cm.count_emval_handles()); | |
}); | |
test("sum array", function() { | |
assert.equal(66, cm.emval_test_sum([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ])); | |
assert.equal(0, cm.count_emval_handles()); | |
}); | |
test("strings", function() { | |
assert.equal("foobar", "foo" + "bar"); | |
assert.equal("foobar", cm.emval_test_take_and_return_std_string("foobar")); | |
assert.equal("foobar", cm.emval_test_take_and_return_std_string_const_ref("foobar")); | |
}); | |
test("nuls pass through strings", function() { | |
assert.equal("foo\0bar", cm.emval_test_take_and_return_std_string("foo\0bar")); | |
}); | |
test("no memory leak when passing strings in by const reference", function() { | |
cm.emval_test_take_and_return_std_string_const_ref("foobar"); | |
}); | |
test("can get global", function() { | |
assert.equal(new Function("return this;")(), cm.embind_test_getglobal()); | |
}); | |
test("can create new object", function() { | |
assert.deepEqual({}, cm.embind_test_new_Object()); | |
}); | |
test("can invoke constructors with arguments", function() { | |
function constructor(i, s, argument) { | |
this.i = i; | |
this.s = s; | |
this.argument = argument; | |
} | |
constructor.prototype.method = function() { | |
return this.argument; | |
}; | |
var x = {}; | |
var instance = cm.embind_test_new_factory(constructor, x); | |
assert.equal(10, instance.i); | |
assert.equal("hello", instance.s); | |
assert.equal(x, instance.argument); | |
}); | |
test("can return module property objects", function() { | |
assert.equal(cm.HEAP8, cm.get_module_property("HEAP8")); | |
}); | |
test("can return big class instances", function() { | |
var c = cm.embind_test_return_big_class_instance(); | |
assert.equal(11, c.member); | |
c.delete(); | |
}); | |
test("can return small class instances", function() { | |
var c = cm.embind_test_return_small_class_instance(); | |
assert.equal(7, c.member); | |
c.delete(); | |
}); | |
test("can pass small class instances", function() { | |
var c = new cm.SmallClass(); | |
var m = cm.embind_test_accept_small_class_instance(c); | |
assert.equal(7, m); | |
c.delete(); | |
}); | |
test("can pass big class instances", function() { | |
var c = new cm.BigClass(); | |
var m = cm.embind_test_accept_big_class_instance(c); | |
assert.equal(11, m); | |
c.delete(); | |
}); | |
test("can pass unique_ptr", function() { | |
var p = cm.embind_test_return_unique_ptr(42); | |
var m = cm.embind_test_accept_unique_ptr(p); | |
assert.equal(42, m); | |
}); | |
test("can pass unique_ptr to constructor", function() { | |
var c = new cm.embind_test_construct_class_with_unique_ptr(42); | |
assert.equal(42, c.getValue()); | |
c.delete(); | |
}); | |
test("can get member classes then call its member functions", function() { | |
var p = new cm.ParentClass(); | |
var c = p.getBigClass(); | |
var m = c.getMember(); | |
assert.equal(11, m); | |
c.delete(); | |
p.delete(); | |
}); | |
test("C++ -> JS primitive type range checks", function() { | |
assert.equal("0", cm.char_to_string(0)); | |
assert.equal("0", cm.signed_char_to_string(0)); | |
assert.equal("0", cm.unsigned_char_to_string(0)); | |
assert.equal("0", cm.short_to_string(0)); | |
assert.equal("0", cm.unsigned_short_to_string(0)); | |
assert.equal("0", cm.int_to_string(0)); | |
assert.equal("0", cm.unsigned_int_to_string(0)); | |
assert.equal("0", cm.long_to_string(0)); | |
assert.equal("0", cm.unsigned_long_to_string(0)); | |
assert.equal("5", cm.char_to_string(5)); | |
assert.equal("5", cm.signed_char_to_string(5)); | |
assert.equal("5", cm.unsigned_char_to_string(5)); | |
assert.equal("5", cm.short_to_string(5)); | |
assert.equal("5", cm.unsigned_short_to_string(5)); | |
assert.equal("5", cm.int_to_string(5)); | |
assert.equal("5", cm.unsigned_int_to_string(5)); | |
assert.equal("5", cm.long_to_string(5)); | |
assert.equal("5", cm.unsigned_long_to_string(5)); | |
assert.equal("-5", cm.char_to_string(-5)); | |
assert.equal("-5", cm.signed_char_to_string(-5)); | |
assert.equal("-5", cm.short_to_string(-5)); | |
assert.equal("-5", cm.int_to_string(-5)); | |
assert.equal("-5", cm.long_to_string(-5)); | |
assert.equal("127", cm.char_to_string(127)); | |
assert.equal("127", cm.signed_char_to_string(127)); | |
assert.equal("255", cm.unsigned_char_to_string(255)); | |
assert.equal("32767", cm.short_to_string(32767)); | |
assert.equal("65535", cm.unsigned_short_to_string(65535)); | |
assert.equal("2147483647", cm.int_to_string(2147483647)); | |
assert.equal("4294967295", cm.unsigned_int_to_string(4294967295)); | |
assert.equal("2147483647", cm.long_to_string(2147483647)); | |
assert.equal("4294967295", cm.unsigned_long_to_string(4294967295)); | |
assert.equal("-128", cm.char_to_string(-128)); | |
assert.equal("-128", cm.signed_char_to_string(-128)); | |
assert.equal("-32768", cm.short_to_string(-32768)); | |
assert.equal("-2147483648", cm.int_to_string(-2147483648)); | |
assert.equal("-2147483648", cm.long_to_string(-2147483648)); | |
if (getCompilerSetting("ASSERTIONS")) { | |
assert.throws(TypeError, function() { | |
cm.char_to_string(-129); | |
}); | |
assert.throws(TypeError, function() { | |
cm.char_to_string(128); | |
}); | |
assert.throws(TypeError, function() { | |
cm.signed_char_to_string(-129); | |
}); | |
assert.throws(TypeError, function() { | |
cm.signed_char_to_string(128); | |
}); | |
assert.throws(TypeError, function() { | |
cm.unsigned_char_to_string(-1); | |
}); | |
assert.throws(TypeError, function() { | |
cm.unsigned_char_to_string(256); | |
}); | |
assert.throws(TypeError, function() { | |
cm.short_to_string(-32769); | |
}); | |
assert.throws(TypeError, function() { | |
cm.short_to_string(32768); | |
}); | |
assert.throws(TypeError, function() { | |
cm.unsigned_short_to_string(-1); | |
}); | |
assert.throws(TypeError, function() { | |
cm.unsigned_short_to_string(65536); | |
}); | |
assert.throws(TypeError, function() { | |
cm.int_to_string(-2147483649); | |
}); | |
assert.throws(TypeError, function() { | |
cm.int_to_string(2147483648); | |
}); | |
assert.throws(TypeError, function() { | |
cm.unsigned_int_to_string(-1); | |
}); | |
assert.throws(TypeError, function() { | |
cm.unsigned_int_to_string(4294967296); | |
}); | |
assert.throws(TypeError, function() { | |
cm.long_to_string(-2147483649); | |
}); | |
assert.throws(TypeError, function() { | |
cm.long_to_string(2147483648); | |
}); | |
assert.throws(TypeError, function() { | |
cm.unsigned_long_to_string(-1); | |
}); | |
assert.throws(TypeError, function() { | |
cm.unsigned_long_to_string(4294967296); | |
}); | |
} else { | |
assert.equal("-129", cm.char_to_string(-129)); | |
} | |
}); | |
test("unsigned values are correctly returned when stored in memory", function() { | |
cm.store_unsigned_char(255); | |
assert.equal(255, cm.load_unsigned_char()); | |
cm.store_unsigned_short(32768); | |
assert.equal(32768, cm.load_unsigned_short()); | |
cm.store_unsigned_int(2147483648); | |
assert.equal(2147483648, cm.load_unsigned_int()); | |
cm.store_unsigned_long(2147483648); | |
assert.equal(2147483648, cm.load_unsigned_long()); | |
}); | |
if (getCompilerSetting("ASSERTIONS")) { | |
test("throws type error when attempting to coerce null to int", function() { | |
var e = assert.throws(TypeError, function() { | |
cm.int_to_string(null); | |
}); | |
assert.equal('Cannot convert "null" to int', e.message); | |
}); | |
} else { | |
test("null is converted to 0 without assertions", function() { | |
assert.equal("0", cm.int_to_string(null)); | |
}); | |
} | |
test("access multiple class ctors", function() { | |
var a = new cm.MultipleCtors(10); | |
assert.equal(a.WhichCtorCalled(), 1); | |
var b = new cm.MultipleCtors(20, 20); | |
assert.equal(b.WhichCtorCalled(), 2); | |
var c = new cm.MultipleCtors(30, 30, 30); | |
assert.equal(c.WhichCtorCalled(), 3); | |
a.delete(); | |
b.delete(); | |
c.delete(); | |
}); | |
test("access multiple smart ptr ctors", function() { | |
var a = new cm.MultipleSmartCtors(10); | |
assert.equal(a.WhichCtorCalled(), 1); | |
var b = new cm.MultipleCtors(20, 20); | |
assert.equal(b.WhichCtorCalled(), 2); | |
a.delete(); | |
b.delete(); | |
}); | |
test("wrong number of constructor arguments throws", function() { | |
assert.throws(cm.BindingError, function() { | |
new cm.MultipleCtors(); | |
}); | |
assert.throws(cm.BindingError, function() { | |
new cm.MultipleCtors(1, 2, 3, 4); | |
}); | |
}); | |
test("overloading of free functions", function() { | |
var a = cm.overloaded_function(10); | |
assert.equal(a, 1); | |
var b = cm.overloaded_function(20, 20); | |
assert.equal(b, 2); | |
}); | |
test("wrong number of arguments to an overloaded free function", function() { | |
assert.throws(cm.BindingError, function() { | |
cm.overloaded_function(); | |
}); | |
assert.throws(cm.BindingError, function() { | |
cm.overloaded_function(30, 30, 30); | |
}); | |
}); | |
test("overloading of class member functions", function() { | |
var foo = new cm.MultipleOverloads(); | |
assert.equal(foo.Func(10), 1); | |
assert.equal(foo.WhichFuncCalled(), 1); | |
assert.equal(foo.Func(20, 20), 2); | |
assert.equal(foo.WhichFuncCalled(), 2); | |
foo.delete(); | |
}); | |
test("wrong number of arguments to an overloaded class member function", function() { | |
var foo = new cm.MultipleOverloads(); | |
assert.throws(cm.BindingError, function() { | |
foo.Func(); | |
}); | |
assert.throws(cm.BindingError, function() { | |
foo.Func(30, 30, 30); | |
}); | |
foo.delete(); | |
}); | |
test("wrong number of arguments to an overloaded class static function", function() { | |
assert.throws(cm.BindingError, function() { | |
cm.MultipleOverloads.StaticFunc(); | |
}); | |
assert.throws(cm.BindingError, function() { | |
cm.MultipleOverloads.StaticFunc(30, 30, 30); | |
}); | |
}); | |
test("overloading of derived class member functions", function() { | |
var foo = new cm.MultipleOverloadsDerived(); | |
assert.equal(foo.Func(10), 1); | |
assert.equal(foo.WhichFuncCalled(), 1); | |
assert.equal(foo.Func(20, 20), 2); | |
assert.equal(foo.WhichFuncCalled(), 2); | |
assert.equal(foo.Func(30, 30, 30), 3); | |
assert.equal(foo.WhichFuncCalled(), 3); | |
assert.equal(foo.Func(40, 40, 40, 40), 4); | |
assert.equal(foo.WhichFuncCalled(), 4); | |
foo.delete(); | |
}); | |
test("overloading of class static functions", function() { | |
assert.equal(cm.MultipleOverloads.StaticFunc(10), 1); | |
assert.equal(cm.MultipleOverloads.WhichStaticFuncCalled(), 1); | |
assert.equal(cm.MultipleOverloads.StaticFunc(20, 20), 2); | |
assert.equal(cm.MultipleOverloads.WhichStaticFuncCalled(), 2); | |
}); | |
test("overloading of derived class static functions", function() { | |
assert.equal(cm.MultipleOverloadsDerived.StaticFunc(30, 30, 30), 3); | |
assert.equal(cm.MultipleOverloads.WhichStaticFuncCalled(), 3); | |
assert.equal(cm.MultipleOverloadsDerived.StaticFunc(40, 40, 40, 40), 4); | |
assert.equal(cm.MultipleOverloads.WhichStaticFuncCalled(), 4); | |
}); | |
test("class member function named with a well-known symbol", function() { | |
var instance = new cm.SymbolNameClass(); | |
assert.equal("Iterator", instance[Symbol.iterator]()); | |
assert.equal("Species", cm.SymbolNameClass[Symbol.species]()); | |
}); | |
test("no undefined entry in overload table when depending on already bound types", function() { | |
var dummy_overloads = cm.MultipleOverloadsDependingOnDummy.prototype.dummy; | |
if (dummy_overloads.hasOwnProperty("overloadTable")) { | |
assert.false(dummy_overloads.overloadTable.hasOwnProperty("undefined")); | |
} | |
var dummy_static_overloads = cm.MultipleOverloadsDependingOnDummy.staticDummy; | |
if (dummy_static_overloads.hasOwnProperty("overloadTable")) { | |
assert.false(dummy_static_overloads.overloadTable.hasOwnProperty("undefined")); | |
} | |
var dependOnDummy = new cm.MultipleOverloadsDependingOnDummy(); | |
var dummy = dependOnDummy.dummy(); | |
dependOnDummy.dummy(dummy); | |
dummy.delete(); | |
dependOnDummy.delete(); | |
var dummy = cm.MultipleOverloadsDependingOnDummy.staticDummy(); | |
cm.MultipleOverloadsDependingOnDummy.staticDummy(dummy); | |
dummy.delete(); | |
}); | |
test("no undefined entry in overload table for free functions", function() { | |
var dummy_free_func = cm.getDummy; | |
console.log(dummy_free_func); | |
if (dummy_free_func.hasOwnProperty("overloadTable")) { | |
assert.false(dummy_free_func.overloadTable.hasOwnProperty("undefined")); | |
} | |
var dummy = cm.getDummy(); | |
cm.getDummy(dummy); | |
}); | |
}); | |
BaseFixture.extend("vector", function() { | |
test("std::vector returns as an native object", function() { | |
var vec = cm.emval_test_return_vector(); | |
assert.equal(3, vec.size()); | |
assert.equal(10, vec.get(0)); | |
assert.equal(20, vec.get(1)); | |
assert.equal(30, vec.get(2)); | |
vec.delete(); | |
}); | |
test("out of bounds std::vector access returns undefined", function() { | |
var vec = cm.emval_test_return_vector(); | |
assert.equal(undefined, vec.get(4)); | |
if (!getCompilerSetting("ASSERTIONS")) { | |
assert.equal(undefined, vec.get(-1)); | |
} | |
vec.delete(); | |
}); | |
if (getCompilerSetting("ASSERTIONS")) { | |
test("out of type range array index throws with assertions", function() { | |
var vec = cm.emval_test_return_vector(); | |
assert.throws(TypeError, function() { | |
vec.get(-1); | |
}); | |
vec.delete(); | |
}); | |
} | |
test("std::vector<std::shared_ptr<>> can be passed back", function() { | |
var vec = cm.emval_test_return_shared_ptr_vector(); | |
assert.equal(2, vec.size()); | |
var str0 = vec.get(0); | |
var str1 = vec.get(1); | |
assert.equal("string #1", str0.get()); | |
assert.equal("string #2", str1.get()); | |
str0.delete(); | |
str1.delete(); | |
vec.delete(); | |
}); | |
test("objects can be pushed back", function() { | |
var vectorHolder = new cm.VectorHolder(); | |
var vec = vectorHolder.get(); | |
assert.equal(2, vec.size()); | |
var str = new cm.StringHolder("abc"); | |
vec.push_back(str); | |
str.delete(); | |
assert.equal(3, vec.size()); | |
var str = vec.get(2); | |
assert.equal("abc", str.get()); | |
str.delete(); | |
vec.delete(); | |
vectorHolder.delete(); | |
}); | |
test("can get elements with array operator", function() { | |
var vec = cm.emval_test_return_vector(); | |
assert.equal(10, vec.get(0)); | |
vec.delete(); | |
}); | |
test("can set elements with array operator", function() { | |
var vec = cm.emval_test_return_vector(); | |
assert.equal(10, vec.get(0)); | |
vec.set(2, 60); | |
assert.equal(60, vec.get(2)); | |
vec.delete(); | |
}); | |
test("can set and get objects", function() { | |
var vec = cm.emval_test_return_shared_ptr_vector(); | |
var str = vec.get(0); | |
assert.equal("string #1", str.get()); | |
str.delete(); | |
vec.delete(); | |
}); | |
test("resize appends the given value", function() { | |
var vec = cm.emval_test_return_vector(); | |
vec.resize(5, 42); | |
assert.equal(5, vec.size()); | |
assert.equal(10, vec.get(0)); | |
assert.equal(20, vec.get(1)); | |
assert.equal(30, vec.get(2)); | |
assert.equal(42, vec.get(3)); | |
assert.equal(42, vec.get(4)); | |
vec.delete(); | |
}); | |
test("resize preserves content when shrinking", function() { | |
var vec = cm.emval_test_return_vector(); | |
vec.resize(2, 42); | |
assert.equal(2, vec.size()); | |
assert.equal(10, vec.get(0)); | |
assert.equal(20, vec.get(1)); | |
vec.delete(); | |
}); | |
}); | |
BaseFixture.extend("map", function() { | |
test("std::map returns as native object", function() { | |
var map = cm.embind_test_get_string_int_map(); | |
assert.equal(2, map.size()); | |
assert.equal(1, map.get("one")); | |
assert.equal(2, map.get("two")); | |
map.delete(); | |
}); | |
test("std::map can get keys", function() { | |
var map = cm.embind_test_get_string_int_map(); | |
var keys = map.keys(); | |
assert.equal(map.size(), keys.size()); | |
assert.equal("one", keys.get(0)); | |
assert.equal("two", keys.get(1)); | |
keys.delete(); | |
map.delete(); | |
}); | |
test("std::map can set keys and values", function() { | |
var map = cm.embind_test_get_string_int_map(); | |
assert.equal(2, map.size()); | |
map.set("three", 3); | |
assert.equal(3, map.size()); | |
assert.equal(3, map.get("three")); | |
map.set("three", 4); | |
assert.equal(3, map.size()); | |
assert.equal(4, map.get("three")); | |
map.delete(); | |
}); | |
}); | |
BaseFixture.extend("functors", function() { | |
test("can get and call function ptrs", function() { | |
var ptr = cm.emval_test_get_function_ptr(); | |
assert.equal("foobar", ptr.opcall("foobar")); | |
ptr.delete(); | |
}); | |
test("can pass functor to C++", function() { | |
var ptr = cm.emval_test_get_function_ptr(); | |
assert.equal("asdf", cm.emval_test_take_and_call_functor(ptr)); | |
ptr.delete(); | |
}); | |
test("can clone handles", function() { | |
var a = cm.emval_test_get_function_ptr(); | |
var b = a.clone(); | |
a.delete(); | |
assert.throws(cm.BindingError, function() { | |
a.delete(); | |
}); | |
b.delete(); | |
}); | |
}); | |
BaseFixture.extend("classes", function() { | |
test("class instance", function() { | |
var a = { | |
foo: "bar" | |
}; | |
assert.equal(0, cm.count_emval_handles()); | |
var c = new cm.ValHolder(a); | |
assert.equal(1, cm.count_emval_handles()); | |
assert.equal("bar", c.getVal().foo); | |
assert.equal(1, cm.count_emval_handles()); | |
c.setVal("1234"); | |
assert.equal("1234", c.getVal()); | |
c.delete(); | |
assert.equal(0, cm.count_emval_handles()); | |
}); | |
test("class properties can be methods", function() { | |
var a = {}; | |
var b = { | |
foo: "foo" | |
}; | |
var c = new cm.ValHolder(a); | |
assert.equal(a, c.val); | |
c.val = b; | |
assert.equal(b, c.val); | |
c.delete(); | |
}); | |
test("class properties can be std::function objects", function() { | |
var a = {}; | |
var b = { | |
foo: "foo" | |
}; | |
var c = new cm.ValHolder(a); | |
assert.equal(a, c.function_val); | |
c.function_val = b; | |
assert.equal(b, c.function_val); | |
c.delete(); | |
}); | |
test("class properties can be read-only std::function objects", function() { | |
var a = {}; | |
var h = new cm.ValHolder(a); | |
assert.equal(a, h.readonly_function_val); | |
var e = assert.throws(cm.BindingError, function() { | |
h.readonly_function_val = 10; | |
}); | |
assert.equal("ValHolder.readonly_function_val is a read-only property", e.message); | |
h.delete(); | |
}); | |
test("class properties can be function objects (functor)", function() { | |
var a = {}; | |
var b = { | |
foo: "foo" | |
}; | |
var c = new cm.ValHolder(a); | |
assert.equal(a, c.functor_val); | |
c.function_val = b; | |
assert.equal(b, c.functor_val); | |
c.delete(); | |
}); | |
test("class properties can be read-only function objects (functor)", function() { | |
var a = {}; | |
var h = new cm.ValHolder(a); | |
assert.equal(a, h.readonly_functor_val); | |
var e = assert.throws(cm.BindingError, function() { | |
h.readonly_functor_val = 10; | |
}); | |
assert.equal("ValHolder.readonly_functor_val is a read-only property", e.message); | |
h.delete(); | |
}); | |
test("class properties can be read-only", function() { | |
var a = {}; | |
var h = new cm.ValHolder(a); | |
assert.equal(a, h.val_readonly); | |
var e = assert.throws(cm.BindingError, function() { | |
h.val_readonly = 10; | |
}); | |
assert.equal("ValHolder.val_readonly is a read-only property", e.message); | |
h.delete(); | |
}); | |
test("read-only member field", function() { | |
var a = new cm.HasReadOnlyProperty(10); | |
assert.equal(10, a.i); | |
var e = assert.throws(cm.BindingError, function() { | |
a.i = 20; | |
}); | |
assert.equal("HasReadOnlyProperty.i is a read-only property", e.message); | |
a.delete(); | |
}); | |
test("class instance $$ property is non-enumerable", function() { | |
var c = new cm.ValHolder(undefined); | |
assert.deepEqual([], Object.keys(c)); | |
var d = c.clone(); | |
c.delete(); | |
assert.deepEqual([], Object.keys(d)); | |
d.delete(); | |
}); | |
test("class methods", function() { | |
assert.equal(10, cm.ValHolder.some_class_method(10)); | |
var b = cm.ValHolder.makeValHolder("foo"); | |
assert.equal("foo", b.getVal()); | |
b.delete(); | |
}); | |
test("function objects as class constructors", function() { | |
var a = new cm.ConstructFromStdFunction("foo", 10); | |
assert.equal("foo", a.getVal()); | |
assert.equal(10, a.getA()); | |
var b = new cm.ConstructFromFunctionObject("bar", 12); | |
assert.equal("bar", b.getVal()); | |
assert.equal(12, b.getA()); | |
a.delete(); | |
b.delete(); | |
}); | |
test("function objects as class methods", function() { | |
var b = cm.ValHolder.makeValHolder("foo"); | |
assert.equal("foo", b.getValFunction()); | |
b.setValFunction("bar"); | |
assert.equal("bar", b.getValFunctor()); | |
b.setValFunctor("baz"); | |
assert.equal("baz", b.getValFunction()); | |
b.delete(); | |
}); | |
test("can't call methods on deleted class instances", function() { | |
var c = new cm.ValHolder(undefined); | |
c.delete(); | |
assert.throws(cm.BindingError, function() { | |
c.getVal(); | |
}); | |
assert.throws(cm.BindingError, function() { | |
c.delete(); | |
}); | |
}); | |
test("calling constructor without new raises BindingError", function() { | |
var e = assert.throws(cm.BindingError, function() { | |
cm.ValHolder(undefined); | |
}); | |
assert.equal("Use 'new' to construct ValHolder", e.message); | |
}); | |
test("can return class instances by value", function() { | |
var c = cm.emval_test_return_ValHolder(); | |
assert.deepEqual({}, c.getVal()); | |
c.delete(); | |
}); | |
test("can pass class instances to functions by reference", function() { | |
var a = { | |
a: 1 | |
}; | |
var c = new cm.ValHolder(a); | |
cm.emval_test_set_ValHolder_to_empty_object(c); | |
assert.deepEqual({}, c.getVal()); | |
c.delete(); | |
}); | |
test("can pass smart pointer by reference", function() { | |
var base = cm.embind_test_return_smart_base_ptr(); | |
var name = cm.embind_test_get_class_name_via_reference_to_smart_base_ptr(base); | |
assert.equal("Base", name); | |
base.delete(); | |
}); | |
test("can pass smart pointer by value", function() { | |
var base = cm.embind_test_return_smart_base_ptr(); | |
var name = cm.embind_test_get_class_name_via_smart_base_ptr(base); | |
assert.equal("Base", name); | |
base.delete(); | |
}); | |
test("can modify smart pointers passed by reference", function() {}); | |
test("can not modify smart pointers passed by value", function() { | |
var base = cm.embind_test_return_smart_base_ptr(); | |
cm.embind_attempt_to_modify_smart_pointer_when_passed_by_value(base); | |
assert.equal("Base", base.getClassName()); | |
base.delete(); | |
}); | |
test("const return value", function() { | |
var c = new cm.ValHolder("foo"); | |
assert.equal("foo", c.getConstVal()); | |
c.delete(); | |
}); | |
test("return object by const ref", function() { | |
var c = new cm.ValHolder("foo"); | |
assert.equal("foo", c.getValConstRef()); | |
c.delete(); | |
}); | |
test("instanceof", function() { | |
var c = new cm.ValHolder("foo"); | |
assert.instanceof(c, cm.ValHolder); | |
c.delete(); | |
}); | |
test("can access struct fields", function() { | |
var c = new cm.CustomStruct(); | |
assert.equal(10, c.field); | |
assert.equal(10, c.getField()); | |
c.delete(); | |
}); | |
test("can set struct fields", function() { | |
var c = new cm.CustomStruct(); | |
c.field = 15; | |
assert.equal(15, c.field); | |
c.delete(); | |
}); | |
test("assignment returns value", function() { | |
var c = new cm.CustomStruct(); | |
assert.equal(15, c.field = 15); | |
c.delete(); | |
}); | |
if (getCompilerSetting("ASSERTIONS")) { | |
test("assigning string or object to integer raises TypeError with assertions", function() { | |
var c = new cm.CustomStruct(); | |
var e = assert.throws(TypeError, function() { | |
c.field = "hi"; | |
}); | |
assert.equal('Cannot convert "hi" to int', e.message); | |
var e = assert.throws(TypeError, function() { | |
c.field = { | |
foo: "bar" | |
}; | |
}); | |
assert.equal('Cannot convert "[object Object]" to int', e.message); | |
c.delete(); | |
}); | |
} else { | |
test("assigning string or object to integer is converted to 0", function() { | |
var c = new cm.CustomStruct(); | |
c.field = "hi"; | |
assert.equal(0, c.field); | |
c.field = { | |
foo: "bar" | |
}; | |
assert.equal(0, c.field); | |
c.delete(); | |
}); | |
} | |
test("can return tuples by value", function() { | |
var c = cm.emval_test_return_TupleVector(); | |
assert.deepEqual([ 1, 2, 3, 4 ], c); | |
}); | |
test("tuples can contain tuples", function() { | |
var c = cm.emval_test_return_TupleVectorTuple(); | |
assert.deepEqual([ [ 1, 2, 3, 4 ] ], c); | |
}); | |
test("can pass tuples by value", function() { | |
var c = cm.emval_test_take_and_return_TupleVector([ 4, 5, 6, 7 ]); | |
assert.deepEqual([ 4, 5, 6, 7 ], c); | |
}); | |
test("can return structs by value", function() { | |
var c = cm.emval_test_return_StructVector(); | |
assert.deepEqual({ | |
x: 1, | |
y: 2, | |
z: 3, | |
w: 4 | |
}, c); | |
}); | |
test("can pass structs by value", function() { | |
var c = cm.emval_test_take_and_return_StructVector({ | |
x: 4, | |
y: 5, | |
z: 6, | |
w: 7 | |
}); | |
assert.deepEqual({ | |
x: 4, | |
y: 5, | |
z: 6, | |
w: 7 | |
}, c); | |
}); | |
test("can pass and return tuples in structs", function() { | |
var d = cm.emval_test_take_and_return_TupleInStruct({ | |
field: [ 1, 2, 3, 4 ] | |
}); | |
assert.deepEqual({ | |
field: [ 1, 2, 3, 4 ] | |
}, d); | |
}); | |
test("can pass and return arrays in structs", function() { | |
var d = cm.emval_test_take_and_return_ArrayInStruct({ | |
field1: [ 1, 2 ], | |
field2: [ { | |
x: 1, | |
y: 2 | |
}, { | |
x: 3, | |
y: 4 | |
} ] | |
}); | |
assert.deepEqual({ | |
field1: [ 1, 2 ], | |
field2: [ { | |
x: 1, | |
y: 2 | |
}, { | |
x: 3, | |
y: 4 | |
} ] | |
}, d); | |
}); | |
test("can clone handles", function() { | |
var a = new cm.ValHolder({}); | |
assert.equal(1, cm.count_emval_handles()); | |
var b = a.clone(); | |
a.delete(); | |
assert.equal(1, cm.count_emval_handles()); | |
assert.throws(cm.BindingError, function() { | |
a.delete(); | |
}); | |
b.delete(); | |
assert.equal(0, cm.count_emval_handles()); | |
}); | |
test("A shared pointer set/get point to the same underlying pointer", function() { | |
var a = new cm.SharedPtrHolder(); | |
var b = a.get(); | |
a.set(b); | |
var c = a.get(); | |
assert.true(b.isAliasOf(c)); | |
b.delete(); | |
c.delete(); | |
a.delete(); | |
}); | |
test("can return shared ptrs from instance methods", function() { | |
var a = new cm.SharedPtrHolder(); | |
var b = a.get(); | |
assert.equal("a string", b.get()); | |
b.delete(); | |
a.delete(); | |
}); | |
test("smart ptrs clone correctly", function() { | |
assert.equal(0, cm.count_emval_handles()); | |
var a = cm.emval_test_return_shared_ptr(); | |
var b = a.clone(); | |
a.delete(); | |
assert.equal(1, cm.count_emval_handles()); | |
assert.throws(cm.BindingError, function() { | |
a.delete(); | |
}); | |
b.delete(); | |
assert.equal(0, cm.count_emval_handles()); | |
}); | |
test("can't clone if already deleted", function() { | |
var a = new cm.ValHolder({}); | |
a.delete(); | |
assert.throws(cm.BindingError, function() { | |
a.clone(); | |
}); | |
}); | |
test("virtual calls work correctly", function() { | |
var derived = cm.embind_test_return_raw_polymorphic_derived_ptr_as_base(); | |
assert.equal("PolyDerived", derived.virtualGetClassName()); | |
derived.delete(); | |
}); | |
test("virtual calls work correctly on smart ptrs", function() { | |
var derived = cm.embind_test_return_smart_polymorphic_derived_ptr_as_base(); | |
assert.equal("PolyDerived", derived.virtualGetClassName()); | |
derived.delete(); | |
}); | |
test("Empty smart ptr is null", function() { | |
var a = cm.emval_test_return_empty_shared_ptr(); | |
assert.equal(null, a); | |
}); | |
test("string cannot be given as smart pointer argument", function() { | |
assert.throws(cm.BindingError, function() { | |
cm.emval_test_is_shared_ptr_null("hello world"); | |
}); | |
}); | |
test("number cannot be given as smart pointer argument", function() { | |
assert.throws(cm.BindingError, function() { | |
cm.emval_test_is_shared_ptr_null(105); | |
}); | |
}); | |
test("raw pointer cannot be given as smart pointer argument", function() { | |
var p = new cm.ValHolder({}); | |
assert.throws(cm.BindingError, function() { | |
cm.emval_test_is_shared_ptr_null(p); | |
}); | |
p.delete(); | |
}); | |
test("null is passed as empty smart pointer", function() { | |
assert.true(cm.emval_test_is_shared_ptr_null(null)); | |
}); | |
test("Deleting already deleted smart ptrs fails", function() { | |
var a = cm.emval_test_return_shared_ptr(); | |
a.delete(); | |
assert.throws(cm.BindingError, function() { | |
a.delete(); | |
}); | |
}); | |
test("returned unique_ptr does not call destructor", function() { | |
var logged = ""; | |
var c = new cm.emval_test_return_unique_ptr_lifetime(function(s) { | |
logged += s; | |
}); | |
assert.equal("(constructor)", logged); | |
c.delete(); | |
}); | |
test("returned unique_ptr calls destructor on delete", function() { | |
var logged = ""; | |
var c = new cm.emval_test_return_unique_ptr_lifetime(function(s) { | |
logged += s; | |
}); | |
logged = ""; | |
c.delete(); | |
assert.equal("(destructor)", logged); | |
}); | |
test("StringHolder", function() { | |
var a = new cm.StringHolder("foobar"); | |
assert.equal("foobar", a.get()); | |
a.set("barfoo"); | |
assert.equal("barfoo", a.get()); | |
assert.equal("barfoo", a.get_const_ref()); | |
a.delete(); | |
}); | |
test("can call methods on unique ptr", function() { | |
var result = cm.emval_test_return_unique_ptr(); | |
result.setVal("1234"); | |
assert.equal("1234", result.getVal()); | |
result.delete(); | |
}); | |
test("can call methods on shared ptr", function() { | |
var result = cm.emval_test_return_shared_ptr(); | |
result.setVal("1234"); | |
assert.equal("1234", result.getVal()); | |
result.delete(); | |
}); | |
test("Non functors throw exception", function() { | |
var a = { | |
foo: "bar" | |
}; | |
var c = new cm.ValHolder(a); | |
assert.throws(TypeError, function() { | |
c(); | |
}); | |
c.delete(); | |
}); | |
test("non-member methods", function() { | |
var a = { | |
foo: "bar" | |
}; | |
var c = new cm.ValHolder(a); | |
c.setEmpty(); | |
assert.deepEqual({}, c.getValNonMember()); | |
c.delete(); | |
}); | |
test("instantiating class without constructor gives error", function() { | |
var e = assert.throws(cm.BindingError, function() { | |
cm.AbstractClass(); | |
}); | |
assert.equal("Use 'new' to construct AbstractClass", e.message); | |
var e = assert.throws(cm.BindingError, function() { | |
new cm.AbstractClass(); | |
}); | |
assert.equal("AbstractClass has no accessible constructor", e.message); | |
}); | |
test("can construct class with external constructor", function() { | |
var e = new cm.HasExternalConstructor("foo"); | |
assert.instanceof(e, cm.HasExternalConstructor); | |
assert.equal("foo", e.getString()); | |
e.delete(); | |
}); | |
}); | |
BaseFixture.extend("const", function() { | |
test("calling non-const method with const handle is error", function() { | |
var vh = cm.ValHolder.makeConst({}); | |
var e = assert.throws(cm.BindingError, function() { | |
vh.setVal({}); | |
}); | |
assert.equal("Cannot convert argument of type ValHolder const* to parameter type ValHolder*", e.message); | |
vh.delete(); | |
}); | |
test("passing const pointer to non-const pointer is error", function() { | |
var vh = new cm.ValHolder.makeConst({}); | |
var e = assert.throws(cm.BindingError, function() { | |
cm.ValHolder.set_via_raw_pointer(vh, {}); | |
}); | |
assert.equal("Cannot convert argument of type ValHolder const* to parameter type ValHolder*", e.message); | |
vh.delete(); | |
}); | |
}); | |
BaseFixture.extend("smart pointers", function() { | |
test("constructor can return smart pointer", function() { | |
var e = new cm.HeldBySmartPtr(10, "foo"); | |
assert.instanceof(e, cm.HeldBySmartPtr); | |
assert.equal(10, e.i); | |
assert.equal("foo", e.s); | |
var f = cm.takesHeldBySmartPtr(e); | |
f.delete(); | |
e.delete(); | |
}); | |
test("cannot pass incorrect smart pointer type", function() { | |
var e = cm.emval_test_return_shared_ptr(); | |
assert.throws(cm.BindingError, function() { | |
cm.takesHeldBySmartPtr(e); | |
}); | |
e.delete(); | |
}); | |
test("smart pointer object has no object keys", function() { | |
var e = new cm.HeldBySmartPtr(10, "foo"); | |
assert.deepEqual([], Object.keys(e)); | |
var f = e.clone(); | |
e.delete(); | |
assert.deepEqual([], Object.keys(f)); | |
f.delete(); | |
}); | |
test("smart pointer object has correct constructor name", function() { | |
var e = new cm.HeldBySmartPtr(10, "foo"); | |
assert.equal("HeldBySmartPtr", e.constructor.name); | |
e.delete(); | |
}); | |
test("constructor can return smart pointer", function() { | |
var e = new cm.HeldBySmartPtr(10, "foo"); | |
assert.instanceof(e, cm.HeldBySmartPtr); | |
assert.equal(10, e.i); | |
assert.equal("foo", e.s); | |
var f = cm.takesHeldBySmartPtr(e); | |
assert.instanceof(f, cm.HeldBySmartPtr); | |
f.delete(); | |
e.delete(); | |
}); | |
test("custom smart pointer", function() { | |
var e = new cm.HeldByCustomSmartPtr(20, "bar"); | |
assert.instanceof(e, cm.HeldByCustomSmartPtr); | |
assert.equal(20, e.i); | |
assert.equal("bar", e.s); | |
e.delete(); | |
}); | |
test("custom smart pointer passed through wiretype", function() { | |
var e = new cm.HeldByCustomSmartPtr(20, "bar"); | |
var f = cm.passThroughCustomSmartPtr(e); | |
e.delete(); | |
assert.instanceof(f, cm.HeldByCustomSmartPtr); | |
assert.equal(20, f.i); | |
assert.equal("bar", f.s); | |
f.delete(); | |
}); | |
test("cannot give null to by-value argument", function() { | |
var e = assert.throws(cm.BindingError, function() { | |
cm.takesHeldBySmartPtr(null); | |
}); | |
assert.equal("null is not a valid HeldBySmartPtr", e.message); | |
}); | |
test("raw pointer can take and give null", function() { | |
assert.equal(null, cm.passThroughRawPtr(null)); | |
}); | |
test("custom smart pointer can take and give null", function() { | |
assert.equal(null, cm.passThroughCustomSmartPtr(null)); | |
}); | |
test("cannot pass shared_ptr to CustomSmartPtr", function() { | |
var o = cm.HeldByCustomSmartPtr.createSharedPtr(10, "foo"); | |
var e = assert.throws(cm.BindingError, function() { | |
cm.passThroughCustomSmartPtr(o); | |
}); | |
assert.equal("Cannot convert argument of type shared_ptr<HeldByCustomSmartPtr> to parameter type CustomSmartPtr<HeldByCustomSmartPtr>", e.message); | |
o.delete(); | |
}); | |
test("custom smart pointers can be passed to shared_ptr parameter", function() { | |
var e = cm.HeldBySmartPtr.newCustomPtr(10, "abc"); | |
assert.equal(10, e.i); | |
assert.equal("abc", e.s); | |
cm.takesHeldBySmartPtrSharedPtr(e).delete(); | |
e.delete(); | |
}); | |
test("can call non-member functions as methods", function() { | |
var e = new cm.HeldBySmartPtr(20, "bar"); | |
var f = e.returnThis(); | |
e.delete(); | |
assert.equal(20, f.i); | |
assert.equal("bar", f.s); | |
f.delete(); | |
}); | |
}); | |
BaseFixture.extend("enumerations", function() { | |
test("can compare enumeration values", function() { | |
assert.equal(cm.Enum.ONE, cm.Enum.ONE); | |
assert.notEqual(cm.Enum.ONE, cm.Enum.TWO); | |
}); | |
if (typeof INVOKED_FROM_EMSCRIPTEN_TEST_RUNNER === "undefined") { | |
test("repr includes enum value", function() { | |
assert.equal("<#Enum_ONE {}>", IMVU.repr(cm.Enum.ONE)); | |
assert.equal("<#Enum_TWO {}>", IMVU.repr(cm.Enum.TWO)); | |
}); | |
} | |
test("instanceof", function() { | |
assert.instanceof(cm.Enum.ONE, cm.Enum); | |
}); | |
test("can pass and return enumeration values to functions", function() { | |
assert.equal(cm.Enum.TWO, cm.emval_test_take_and_return_Enum(cm.Enum.TWO)); | |
}); | |
}); | |
BaseFixture.extend("C++11 enum class", function() { | |
test("can compare enumeration values", function() { | |
assert.equal(cm.EnumClass.ONE, cm.EnumClass.ONE); | |
assert.notEqual(cm.EnumClass.ONE, cm.EnumClass.TWO); | |
}); | |
if (typeof INVOKED_FROM_EMSCRIPTEN_TEST_RUNNER === "undefined") { | |
test("repr includes enum value", function() { | |
assert.equal("<#EnumClass_ONE {}>", IMVU.repr(cm.EnumClass.ONE)); | |
assert.equal("<#EnumClass_TWO {}>", IMVU.repr(cm.EnumClass.TWO)); | |
}); | |
} | |
test("instanceof", function() { | |
assert.instanceof(cm.EnumClass.ONE, cm.EnumClass); | |
}); | |
test("can pass and return enumeration values to functions", function() { | |
assert.equal(cm.EnumClass.TWO, cm.emval_test_take_and_return_EnumClass(cm.EnumClass.TWO)); | |
}); | |
}); | |
BaseFixture.extend("emval call tests", function() { | |
test("can call functions from C++", function() { | |
var called = false; | |
cm.emval_test_call_function(function(i, f, tv, sv) { | |
called = true; | |
assert.equal(10, i); | |
assert.equal(1.5, f); | |
assert.deepEqual([ 1.25, 2.5, 3.75, 4 ], tv); | |
assert.deepEqual({ | |
x: 1.25, | |
y: 2.5, | |
z: 3.75, | |
w: 4 | |
}, sv); | |
}, 10, 1.5, [ 1.25, 2.5, 3.75, 4 ], { | |
x: 1.25, | |
y: 2.5, | |
z: 3.75, | |
w: 4 | |
}); | |
assert.true(called); | |
}); | |
}); | |
BaseFixture.extend("extending built-in classes", function() { | |
test("can access patched value on new instances", function() { | |
cm.ValHolder.prototype.patched = 10; | |
var c = new cm.ValHolder(undefined); | |
assert.equal(10, c.patched); | |
c.delete(); | |
cm.ValHolder.prototype.patched = undefined; | |
}); | |
test("can access patched value on returned instances", function() { | |
cm.ValHolder.prototype.patched = 10; | |
var c = cm.emval_test_return_ValHolder(); | |
assert.equal(10, c.patched); | |
c.delete(); | |
cm.ValHolder.prototype.patched = undefined; | |
}); | |
}); | |
BaseFixture.extend("raw pointers", function() { | |
test("can pass raw pointers into functions if explicitly allowed", function() { | |
var vh = new cm.ValHolder({}); | |
cm.ValHolder.set_via_raw_pointer(vh, 10); | |
assert.equal(10, cm.ValHolder.get_via_raw_pointer(vh)); | |
vh.delete(); | |
}); | |
test("can return raw pointers from functions if explicitly allowed", function() { | |
var p = cm.embind_test_return_raw_base_ptr(); | |
assert.equal("Base", p.getClassName()); | |
p.delete(); | |
}); | |
test("can pass multiple raw pointers to functions", function() { | |
var target = new cm.ValHolder(undefined); | |
var source = new cm.ValHolder("hi"); | |
cm.ValHolder.transfer_via_raw_pointer(target, source); | |
assert.equal("hi", target.getVal()); | |
target.delete(); | |
source.delete(); | |
}); | |
}); | |
BaseFixture.extend("implementing abstract methods with JS objects", function() { | |
test("can call abstract methods", function() { | |
var obj = cm.getAbstractClass(); | |
assert.equal("from concrete", obj.abstractMethod()); | |
obj.delete(); | |
}); | |
test("can implement abstract methods in JavaScript", function() { | |
var expected = "my JS string"; | |
function MyImplementation() { | |
this.rv = expected; | |
} | |
MyImplementation.prototype.abstractMethod = function() { | |
return this.rv; | |
}; | |
var impl = cm.AbstractClass.implement(new MyImplementation()); | |
assert.equal(expected, impl.abstractMethod()); | |
assert.equal(expected, cm.callAbstractMethod(impl)); | |
impl.delete(); | |
}); | |
test("can implement optional methods in JavaScript", function() { | |
var expected = "my JS string"; | |
function MyImplementation() { | |
this.rv = expected; | |
} | |
MyImplementation.prototype.optionalMethod = function() { | |
return this.rv; | |
}; | |
var impl = cm.AbstractClass.implement(new MyImplementation()); | |
assert.equal(expected, cm.callOptionalMethod(impl, expected)); | |
impl.delete(); | |
}); | |
test("if not implemented then optional method runs default", function() { | |
var impl = cm.AbstractClass.implement({}); | |
assert.equal("optionalfoo", impl.optionalMethod("foo")); | |
impl.delete(); | |
}); | |
test("returning null shared pointer from interfaces implemented in JS code does not leak", function() { | |
var impl = cm.AbstractClass.implement({ | |
returnsSharedPtr: function() { | |
return null; | |
} | |
}); | |
cm.callReturnsSharedPtrMethod(impl); | |
impl.delete(); | |
}); | |
test("returning a new shared pointer from interfaces implemented in JS code does not leak", function() { | |
var impl = cm.AbstractClass.implement({ | |
returnsSharedPtr: function() { | |
return cm.embind_test_return_smart_derived_ptr().deleteLater(); | |
} | |
}); | |
cm.callReturnsSharedPtrMethod(impl); | |
impl.delete(); | |
}); | |
test("void methods work", function() { | |
var saved = {}; | |
var impl = cm.AbstractClass.implement({ | |
differentArguments: function(i, d, f, q, s) { | |
saved.i = i; | |
saved.d = d; | |
saved.f = f; | |
saved.q = q; | |
saved.s = s; | |
} | |
}); | |
cm.callDifferentArguments(impl, 1, 2, 3, 4, "foo"); | |
assert.deepEqual(saved, { | |
i: 1, | |
d: 2, | |
f: 3, | |
q: 4, | |
s: "foo" | |
}); | |
impl.delete(); | |
}); | |
test("returning a cached new shared pointer from interfaces implemented in JS code does not leak", function() { | |
var derived = cm.embind_test_return_smart_derived_ptr(); | |
var impl = cm.AbstractClass.implement({ | |
returnsSharedPtr: function() { | |
return derived; | |
} | |
}); | |
cm.callReturnsSharedPtrMethod(impl); | |
impl.delete(); | |
derived.delete(); | |
}); | |
}); | |
BaseFixture.extend("constructor prototype class inheritance", function() { | |
var Empty = cm.AbstractClass.extend("Empty", { | |
abstractMethod: function() {} | |
}); | |
test("can extend, construct, and delete", function() { | |
var instance = new Empty(); | |
instance.delete(); | |
}); | |
test("properties set in constructor are externally visible", function() { | |
var HasProperty = cm.AbstractClass.extend("HasProperty", { | |
__construct: function(x) { | |
this.__parent.__construct.call(this); | |
this.property = x; | |
}, | |
abstractMethod: function() {} | |
}); | |
var instance = new HasProperty(10); | |
assert.equal(10, instance.property); | |
instance.delete(); | |
}); | |
test("pass derived object to c++", function() { | |
var Implementation = cm.AbstractClass.extend("Implementation", { | |
abstractMethod: function() { | |
return "abc"; | |
} | |
}); | |
var instance = new Implementation(); | |
var result = cm.callAbstractMethod(instance); | |
instance.delete(); | |
assert.equal("abc", result); | |
}); | |
test("properties set in constructor are visible in overridden methods", function() { | |
var HasProperty = cm.AbstractClass.extend("HasProperty", { | |
__construct: function(x) { | |
this.__parent.__construct.call(this); | |
this.x = x; | |
}, | |
abstractMethod: function() { | |
return this.x; | |
} | |
}); | |
var instance = new HasProperty("xyz"); | |
var result = cm.callAbstractMethod(instance); | |
instance.delete(); | |
assert.equal("xyz", result); | |
}); | |
test("interface methods are externally visible", function() { | |
var instance = new Empty(); | |
var result = instance.concreteMethod(); | |
instance.delete(); | |
assert.equal("concrete", result); | |
}); | |
test("optional methods are externally visible", function() { | |
var instance = new Empty(); | |
var result = instance.optionalMethod("_123"); | |
instance.delete(); | |
assert.equal("optional_123", result); | |
}); | |
test("optional methods: not defined", function() { | |
var instance = new Empty(); | |
var result = cm.callOptionalMethod(instance, "_123"); | |
instance.delete(); | |
assert.equal("optional_123", result); | |
}); | |
test("can call parent implementation from within derived implementation", function() { | |
var parent = cm.AbstractClass; | |
var ExtendsOptionalMethod = parent.extend("ExtendsOptionalMethod", { | |
abstractMethod: function() {}, | |
optionalMethod: function(s) { | |
return "optionaljs_" + parent.prototype.optionalMethod.call(this, s); | |
} | |
}); | |
var instance = new ExtendsOptionalMethod(); | |
var result = cm.callOptionalMethod(instance, "_123"); | |
instance.delete(); | |
assert.equal("optionaljs_optional_123", result); | |
}); | |
test("instanceof", function() { | |
var instance = new Empty(); | |
assert.instanceof(instance, Empty); | |
assert.instanceof(instance, cm.AbstractClass); | |
instance.delete(); | |
}); | |
test("returning null shared pointer from interfaces implemented in JS code does not leak", function() { | |
var C = cm.AbstractClass.extend("C", { | |
abstractMethod: function() {}, | |
returnsSharedPtr: function() { | |
return null; | |
} | |
}); | |
var impl = new C(); | |
cm.callReturnsSharedPtrMethod(impl); | |
impl.delete(); | |
}); | |
test("returning a new shared pointer from interfaces implemented in JS code does not leak", function() { | |
var C = cm.AbstractClass.extend("C", { | |
abstractMethod: function() {}, | |
returnsSharedPtr: function() { | |
return cm.embind_test_return_smart_derived_ptr().deleteLater(); | |
} | |
}); | |
var impl = new C(); | |
cm.callReturnsSharedPtrMethod(impl); | |
impl.delete(); | |
}); | |
test("void methods work", function() { | |
var saved = {}; | |
var C = cm.AbstractClass.extend("C", { | |
abstractMethod: function() {}, | |
differentArguments: function(i, d, f, q, s) { | |
saved.i = i; | |
saved.d = d; | |
saved.f = f; | |
saved.q = q; | |
saved.s = s; | |
} | |
}); | |
var impl = new C(); | |
cm.callDifferentArguments(impl, 1, 2, 3, 4, "foo"); | |
assert.deepEqual(saved, { | |
i: 1, | |
d: 2, | |
f: 3, | |
q: 4, | |
s: "foo" | |
}); | |
impl.delete(); | |
}); | |
test("returning a cached new shared pointer from interfaces implemented in JS code does not leak", function() { | |
var derived = cm.embind_test_return_smart_derived_ptr(); | |
var C = cm.AbstractClass.extend("C", { | |
abstractMethod: function() {}, | |
returnsSharedPtr: function() { | |
return derived; | |
} | |
}); | |
var impl = new C(); | |
cm.callReturnsSharedPtrMethod(impl); | |
impl.delete(); | |
derived.delete(); | |
}); | |
test("calling pure virtual function gives good error message", function() { | |
var C = cm.AbstractClass.extend("C", {}); | |
var error = assert.throws(cm.PureVirtualError, function() { | |
new C(); | |
}); | |
assert.equal("Pure virtual function abstractMethod must be implemented in JavaScript", error.message); | |
}); | |
test("can extend from C++ class with constructor arguments", function() { | |
var parent = cm.AbstractClassWithConstructor; | |
var C = parent.extend("C", { | |
__construct: function(x) { | |
this.__parent.__construct.call(this, x); | |
}, | |
abstractMethod: function() { | |
return this.concreteMethod(); | |
} | |
}); | |
var impl = new C("hi"); | |
var rv = cm.callAbstractMethod2(impl); | |
impl.delete(); | |
assert.equal("hi", rv); | |
}); | |
test("__destruct is called when object is destroyed", function() { | |
var parent = cm.HeldAbstractClass; | |
var calls = []; | |
var C = parent.extend("C", { | |
method: function() {}, | |
__destruct: function() { | |
calls.push("__destruct"); | |
this.__parent.__destruct.call(this); | |
} | |
}); | |
var impl = new C(); | |
var copy = impl.clone(); | |
impl.delete(); | |
assert.deepEqual([], calls); | |
copy.delete(); | |
assert.deepEqual([ "__destruct" ], calls); | |
}); | |
test("if JavaScript implementation of interface is returned, don't wrap in new handle", function() { | |
var parent = cm.HeldAbstractClass; | |
var C = parent.extend("C", { | |
method: function() {} | |
}); | |
var impl = new C(); | |
var rv = cm.passHeldAbstractClass(impl); | |
impl.delete(); | |
assert.equal(impl, rv); | |
rv.delete(); | |
}); | |
test("can instantiate two wrappers with constructors", function() { | |
var parent = cm.HeldAbstractClass; | |
var C = parent.extend("C", { | |
__construct: function() { | |
this.__parent.__construct.call(this); | |
}, | |
method: function() {} | |
}); | |
var a = new C(); | |
var b = new C(); | |
a.delete(); | |
b.delete(); | |
}); | |
test("incorrectly calling parent is an error", function() { | |
var parent = cm.HeldAbstractClass; | |
var C = parent.extend("C", { | |
__construct: function() { | |
this.__parent.__construct(); | |
}, | |
method: function() {} | |
}); | |
assert.throws(cm.BindingError, function() { | |
new C(); | |
}); | |
}); | |
test("deleteLater() works for JavaScript implementations", function() { | |
var parent = cm.HeldAbstractClass; | |
var C = parent.extend("C", { | |
method: function() {} | |
}); | |
var impl = new C(); | |
var rv = cm.passHeldAbstractClass(impl); | |
impl.deleteLater(); | |
rv.deleteLater(); | |
cm.flushPendingDeletes(); | |
}); | |
test("deleteLater() combined with delete() works for JavaScript implementations", function() { | |
var parent = cm.HeldAbstractClass; | |
var C = parent.extend("C", { | |
method: function() {} | |
}); | |
var impl = new C(); | |
var rv = cm.passHeldAbstractClass(impl); | |
impl.deleteLater(); | |
rv.delete(); | |
cm.flushPendingDeletes(); | |
}); | |
test("method arguments with pointer ownership semantics are cleaned up after call", function() { | |
var parent = cm.AbstractClass; | |
var C = parent.extend("C", { | |
abstractMethod: function() {} | |
}); | |
var impl = new C(); | |
cm.passShared(impl); | |
impl.delete(); | |
}); | |
test("method arguments with pointer ownership semantics can be cloned", function() { | |
var parent = cm.AbstractClass; | |
var owned; | |
var C = parent.extend("C", { | |
abstractMethod: function() {}, | |
passShared: function(p) { | |
owned = p.clone(); | |
} | |
}); | |
var impl = new C(); | |
cm.passShared(impl); | |
impl.delete(); | |
assert.equal("Derived", owned.getClassName()); | |
owned.delete(); | |
}); | |
test("emscripten::val method arguments don't leak", function() { | |
var parent = cm.AbstractClass; | |
var got; | |
var C = parent.extend("C", { | |
abstractMethod: function() {}, | |
passVal: function(g) { | |
got = g; | |
} | |
}); | |
var impl = new C(); | |
var v = {}; | |
cm.passVal(impl, v); | |
impl.delete(); | |
assert.equal(v, got); | |
}); | |
}); | |
BaseFixture.extend("registration order", function() { | |
test("registration of tuple elements out of order leaves them in order", function() { | |
var ot = cm.getOrderedTuple(); | |
assert.instanceof(ot[0], cm.FirstElement); | |
assert.instanceof(ot[1], cm.SecondElement); | |
ot[0].delete(); | |
ot[1].delete(); | |
}); | |
test("registration of struct elements out of order", function() { | |
var os = cm.getOrderedStruct(); | |
assert.instanceof(os.first, cm.FirstElement); | |
assert.instanceof(os.second, cm.SecondElement); | |
os.first.delete(); | |
os.second.delete(); | |
}); | |
}); | |
if (typeof INVOKED_FROM_EMSCRIPTEN_TEST_RUNNER === "undefined") { | |
BaseFixture.extend("unbound types", function() { | |
if (!cm.hasUnboundTypeNames) { | |
return; | |
} | |
function assertMessage(fn, message) { | |
var e = assert.throws(cm.UnboundTypeError, fn); | |
assert.equal(message, e.message); | |
} | |
test("calling function with unbound types produces error", function() { | |
assertMessage(function() { | |
cm.getUnboundClass(); | |
}, "Cannot call getUnboundClass due to unbound types: 12UnboundClass"); | |
}); | |
test("unbound base class produces error", function() { | |
assertMessage(function() { | |
cm.getHasUnboundBase(); | |
}, "Cannot call getHasUnboundBase due to unbound types: 12UnboundClass"); | |
}); | |
test("construct of class with unbound base", function() { | |
assertMessage(function() { | |
new cm.HasUnboundBase(); | |
}, "Cannot construct HasUnboundBase due to unbound types: 12UnboundClass"); | |
}); | |
test("unbound constructor argument", function() { | |
assertMessage(function() { | |
new cm.HasConstructorUsingUnboundArgument(1); | |
}, "Cannot construct HasConstructorUsingUnboundArgument due to unbound types: 12UnboundClass"); | |
}); | |
test("unbound constructor argument of class with unbound base", function() { | |
assertMessage(function() { | |
new cm.HasConstructorUsingUnboundArgumentAndUnboundBase(); | |
}, "Cannot construct HasConstructorUsingUnboundArgumentAndUnboundBase due to unbound types: 18SecondUnboundClass"); | |
}); | |
test("class function with unbound argument", function() { | |
var x = new cm.BoundClass(); | |
assertMessage(function() { | |
x.method(); | |
}, "Cannot call BoundClass.method due to unbound types: 12UnboundClass"); | |
x.delete(); | |
}); | |
test("class class function with unbound argument", function() { | |
assertMessage(function() { | |
cm.BoundClass.classfunction(); | |
}, "Cannot call BoundClass.classfunction due to unbound types: 12UnboundClass"); | |
}); | |
test("class property of unbound type", function() { | |
var x = new cm.BoundClass(); | |
var y; | |
assertMessage(function() { | |
y = x.property; | |
}, "Cannot access BoundClass.property due to unbound types: 12UnboundClass"); | |
assertMessage(function() { | |
x.property = 10; | |
}, "Cannot access BoundClass.property due to unbound types: 12UnboundClass"); | |
x.delete(); | |
}); | |
}); | |
} | |
BaseFixture.extend("noncopyable", function() { | |
test("can call method on noncopyable object", function() { | |
var x = new cm.Noncopyable(); | |
assert.equal("foo", x.method()); | |
x.delete(); | |
}); | |
}); | |
BaseFixture.extend("function names", function() { | |
assert.equal("ValHolder", cm.ValHolder.name); | |
if (!getCompilerSetting("DYNAMIC_EXECUTION")) { | |
assert.equal("", cm.ValHolder.prototype.setVal.name); | |
assert.equal("", cm.ValHolder.makeConst.name); | |
} else { | |
assert.equal("ValHolder$setVal", cm.ValHolder.prototype.setVal.name); | |
assert.equal("ValHolder$makeConst", cm.ValHolder.makeConst.name); | |
} | |
}); | |
BaseFixture.extend("constants", function() { | |
assert.equal(10, cm.INT_CONSTANT); | |
assert.equal(1, cm.STATIC_CONST_INTEGER_VALUE_1); | |
assert.equal(1e3, cm.STATIC_CONST_INTEGER_VALUE_1000); | |
assert.equal("some string", cm.STRING_CONSTANT); | |
assert.deepEqual([ 1, 2, 3, 4 ], cm.VALUE_ARRAY_CONSTANT); | |
assert.deepEqual({ | |
x: 1, | |
y: 2, | |
z: 3, | |
w: 4 | |
}, cm.VALUE_OBJECT_CONSTANT); | |
}); | |
BaseFixture.extend("object handle comparison", function() { | |
var e = new cm.ValHolder("foo"); | |
var f = new cm.ValHolder("foo"); | |
assert.false(e.isAliasOf(undefined)); | |
assert.false(e.isAliasOf(10)); | |
assert.true(e.isAliasOf(e)); | |
assert.false(e.isAliasOf(f)); | |
assert.false(f.isAliasOf(e)); | |
e.delete(); | |
f.delete(); | |
}); | |
BaseFixture.extend("derived-with-offset types compare with base", function() { | |
var e = new cm.DerivedWithOffset(); | |
var f = cm.return_Base_from_DerivedWithOffset(e); | |
assert.true(e.isAliasOf(f)); | |
assert.true(f.isAliasOf(e)); | |
e.delete(); | |
f.delete(); | |
}); | |
BaseFixture.extend("memory view", function() { | |
test("can pass memory view from C++ to JS", function() { | |
var views = []; | |
cm.callWithMemoryView(function(view) { | |
views.push(view); | |
}); | |
assert.equal(3, views.length); | |
assert.instanceof(views[0], Uint8Array); | |
assert.equal(8, views[0].length); | |
assert.deepEqual([ 0, 1, 2, 3, 4, 5, 6, 7 ], [].slice.call(new Uint8Array(views[0]))); | |
assert.instanceof(views[1], Float32Array); | |
assert.equal(4, views[1].length); | |
assert.deepEqual([ 1.5, 2.5, 3.5, 4.5 ], [].slice.call(views[1])); | |
assert.instanceof(views[2], Int16Array); | |
assert.equal(4, views[2].length); | |
assert.deepEqual([ 1e3, 100, 10, 1 ], [].slice.call(views[2])); | |
}); | |
}); | |
BaseFixture.extend("delete pool", function() { | |
test("can delete objects later", function() { | |
var v = new cm.ValHolder({}); | |
v.deleteLater(); | |
assert.deepEqual({}, v.getVal()); | |
cm.flushPendingDeletes(); | |
assert.throws(cm.BindingError, function() { | |
v.getVal(); | |
}); | |
}); | |
test("calling deleteLater twice is an error", function() { | |
var v = new cm.ValHolder({}); | |
v.deleteLater(); | |
assert.throws(cm.BindingError, function() { | |
v.deleteLater(); | |
}); | |
}); | |
test("can clone instances that have been scheduled for deletion", function() { | |
var v = new cm.ValHolder({}); | |
v.deleteLater(); | |
var v2 = v.clone(); | |
v2.delete(); | |
}); | |
test("deleteLater returns the object", function() { | |
var v = new cm.ValHolder({}).deleteLater(); | |
assert.deepEqual({}, v.getVal()); | |
}); | |
test("deleteLater throws if object is already deleted", function() { | |
var v = new cm.ValHolder({}); | |
v.delete(); | |
assert.throws(cm.BindingError, function() { | |
v.deleteLater(); | |
}); | |
}); | |
test("delete throws if object is already scheduled for deletion", function() { | |
var v = new cm.ValHolder({}); | |
v.deleteLater(); | |
assert.throws(cm.BindingError, function() { | |
v.delete(); | |
}); | |
}); | |
test("deleteLater invokes delay function", function() { | |
var runLater; | |
cm.setDelayFunction(function(fn) { | |
runLater = fn; | |
}); | |
var v = new cm.ValHolder({}); | |
assert.false(runLater); | |
v.deleteLater(); | |
assert.true(runLater); | |
assert.false(v.isDeleted()); | |
runLater(); | |
assert.true(v.isDeleted()); | |
}); | |
test("deleteLater twice invokes delay function once", function() { | |
var count = 0; | |
var runLater; | |
cm.setDelayFunction(function(fn) { | |
++count; | |
runLater = fn; | |
}); | |
new cm.ValHolder({}).deleteLater(); | |
new cm.ValHolder({}).deleteLater(); | |
assert.equal(1, count); | |
runLater(); | |
new cm.ValHolder({}).deleteLater(); | |
assert.equal(2, count); | |
}); | |
test("The delay function is immediately invoked if the deletion queue is not empty", function() { | |
new cm.ValHolder({}).deleteLater(); | |
var count = 0; | |
cm.setDelayFunction(function(fn) { | |
++count; | |
}); | |
assert.equal(1, count); | |
}); | |
}); | |
BaseFixture.extend("references", function() { | |
test("JS object handles can be passed through to C++ by reference", function() { | |
var sh = new cm.StringHolder("Hello world"); | |
assert.equal("Hello world", sh.get()); | |
cm.clear_StringHolder(sh); | |
assert.equal("", sh.get()); | |
sh.delete(); | |
}); | |
}); | |
BaseFixture.extend("val::as from pointer to value", function() { | |
test("calling as on pointer with value makes a copy", function() { | |
var sh1 = new cm.StringHolder("Hello world"); | |
var sh2 = cm.return_StringHolder_copy(sh1); | |
assert.equal("Hello world", sh1.get()); | |
assert.equal("Hello world", sh2.get()); | |
assert.false(sh1.isAliasOf(sh2)); | |
sh2.delete(); | |
sh1.delete(); | |
}); | |
test("calling function that returns a StringHolder", function() { | |
var sh1 = new cm.StringHolder("Hello world"); | |
var sh2 = cm.call_StringHolder_func(function() { | |
return sh1; | |
}); | |
assert.equal("Hello world", sh1.get()); | |
assert.equal("Hello world", sh2.get()); | |
assert.false(sh1.isAliasOf(sh2)); | |
sh2.delete(); | |
sh1.delete(); | |
}); | |
}); | |
BaseFixture.extend("mixin", function() { | |
test("can call mixin method", function() { | |
var a = new cm.DerivedWithMixin(); | |
assert.instanceof(a, cm.Base); | |
assert.equal(10, a.get10()); | |
a.delete(); | |
}); | |
}); | |
BaseFixture.extend("val::as", function() { | |
test("built-ins", function() { | |
assert.equal(true, cm.val_as_bool(true)); | |
assert.equal(false, cm.val_as_bool(false)); | |
assert.equal(127, cm.val_as_char(127)); | |
assert.equal(32767, cm.val_as_short(32767)); | |
assert.equal(65536, cm.val_as_int(65536)); | |
assert.equal(65536, cm.val_as_long(65536)); | |
assert.equal(10.5, cm.val_as_float(10.5)); | |
assert.equal(10.5, cm.val_as_double(10.5)); | |
assert.equal("foo", cm.val_as_string("foo")); | |
assert.equal("foo", cm.val_as_wstring("foo")); | |
var obj = {}; | |
assert.equal(obj, cm.val_as_val(obj)); | |
}); | |
test("value types", function() { | |
var tuple = [ 1, 2, 3, 4 ]; | |
assert.deepEqual(tuple, cm.val_as_value_array(tuple)); | |
var struct = { | |
x: 1, | |
y: 2, | |
z: 3, | |
w: 4 | |
}; | |
assert.deepEqual(struct, cm.val_as_value_object(struct)); | |
}); | |
test("enums", function() { | |
assert.equal(cm.Enum.ONE, cm.val_as_enum(cm.Enum.ONE)); | |
}); | |
}); | |
BaseFixture.extend("val::new_", function() { | |
test("variety of types", function() { | |
function factory() { | |
this.arguments = Array.prototype.slice.call(arguments, 0); | |
} | |
var instance = cm.construct_with_6_arguments(factory); | |
assert.deepEqual([ 6, -12.5, "a3", { | |
x: 1, | |
y: 2, | |
z: 3, | |
w: 4 | |
}, cm.EnumClass.TWO, [ -1, -2, -3, -4 ] ], instance.arguments); | |
}); | |
test("memory view", function() { | |
function factory(before, view, after) { | |
this.before = before; | |
this.view = view; | |
this.after = after; | |
} | |
var instance = cm.construct_with_memory_view(factory); | |
assert.equal("before", instance.before); | |
assert.equal(10, instance.view.byteLength); | |
assert.equal("after", instance.after); | |
}); | |
test("ints_and_float", function() { | |
function factory(a, b, c) { | |
this.a = a; | |
this.b = b; | |
this.c = c; | |
} | |
var instance = cm.construct_with_ints_and_float(factory); | |
assert.equal(65537, instance.a); | |
assert.equal(4, instance.b); | |
assert.equal(65538, instance.c); | |
}); | |
if (cm.isMemoryGrowthEnabled) { | |
test("before and after memory growth", function() { | |
var array = cm.construct_with_arguments_before_and_after_memory_growth(); | |
assert.equal(array[0].byteLength, 5); | |
assert.equal(array[0].byteLength, array[1].byteLength); | |
}); | |
} | |
}); | |
BaseFixture.extend("intrusive pointers", function() { | |
test("can pass intrusive pointers", function() { | |
var ic = new cm.IntrusiveClass(); | |
var d = cm.passThroughIntrusiveClass(ic); | |
assert.true(ic.isAliasOf(d)); | |
ic.delete(); | |
d.delete(); | |
}); | |
test("can hold intrusive pointers", function() { | |
var ic = new cm.IntrusiveClass(); | |
var holder = new cm.IntrusiveClassHolder(); | |
holder.set(ic); | |
ic.delete(); | |
var d = holder.get(); | |
d.delete(); | |
holder.delete(); | |
}); | |
test("can extend from intrusive pointer class and still preserve reference in JavaScript", function() { | |
var C = cm.IntrusiveClass.extend("C", {}); | |
var instance = new C(); | |
var holder = new cm.IntrusiveClassHolder(); | |
holder.set(instance); | |
instance.delete(); | |
var back = holder.get(); | |
assert.equal(back, instance); | |
holder.delete(); | |
back.delete(); | |
}); | |
}); | |
BaseFixture.extend("typeof", function() { | |
test("typeof", function() { | |
assert.equal("object", cm.getTypeOfVal(null)); | |
assert.equal("object", cm.getTypeOfVal({})); | |
assert.equal("function", cm.getTypeOfVal(function() {})); | |
assert.equal("number", cm.getTypeOfVal(1)); | |
assert.equal("string", cm.getTypeOfVal("hi")); | |
}); | |
}); | |
BaseFixture.extend("static member", function() { | |
test("static members", function() { | |
assert.equal(10, cm.HasStaticMember.c); | |
assert.equal(20, cm.HasStaticMember.v); | |
cm.HasStaticMember.v = 30; | |
assert.equal(30, cm.HasStaticMember.v); | |
}); | |
}); | |
}); | |
if (typeof run_all_tests !== "undefined") { | |
run_all_tests(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/test/embind/embind.test.js b/test/embind/embind.test.js | |
index e19a9dc4e..24cf6d520 100644 | |
--- a/test/embind/embind.test.js | |
+++ b/test/embind/embind.test.js | |
@@ -371,24 +371,21 @@ module({ | |
var siblingDerived = cm.embind_test_return_smart_polymorphic_sibling_derived_ptr_as_base(); | |
assert.equal("PolySiblingDerived", siblingDerived.getClassName()); | |
siblingDerived.delete(); | |
derived.delete(); | |
}); | |
}); | |
BaseFixture.extend("string", function() { | |
- // The test harness should set this value one way or the other. | |
- assert.true(cm['EMBIND_STD_STRING_IS_UTF8'] !== undefined); | |
- | |
- var stdStringIsUTF8 = (cm['EMBIND_STD_STRING_IS_UTF8'] === true); | |
+ var stdStringIsUTF8 = (getCompilerSetting('EMBIND_STD_STRING_IS_UTF8') === true); | |
test("non-ascii strings", function() { | |
var expected = ''; | |
if(stdStringIsUTF8) { | |
//ASCII | |
expected = 'aei'; | |
//Latin-1 Supplement | |
expected += '\u00E1\u00E9\u00ED'; | |
//Greek | |
@@ -638,24 +635,21 @@ module({ | |
test("can pass booleans as floats", function() { | |
assert.equal(2, cm.const_ref_adder(true, true)); | |
}); | |
test("passing Symbol or BigInt as floats always throws", function() { | |
assert.throws(TypeError, function() { cm.const_ref_adder(Symbol('0'), 1); }); | |
assert.throws(TypeError, function() { cm.const_ref_adder(0n, 1); }); | |
}); | |
- // The test harness should set this value one way or the other. | |
- assert.true(cm['ASSERTIONS'] !== undefined); | |
- | |
- if (cm['ASSERTIONS']) { | |
+ if (getCompilerSetting('ASSERTIONS')) { | |
test("can pass only number and boolean as floats with assertions", function() { | |
assert.throws(TypeError, function() { cm.const_ref_adder(1, undefined); }); | |
assert.throws(TypeError, function() { cm.const_ref_adder(1, null); }); | |
assert.throws(TypeError, function() { cm.const_ref_adder(1, '2'); }); | |
}); | |
} else { | |
test("can pass other types as floats without assertions", function() { | |
assert.equal(3, cm.const_ref_adder(1, '2')); | |
assert.equal(1, cm.const_ref_adder(1, null)); // null => 0 | |
assert.true(isNaN(cm.const_ref_adder(1, 'cannot parse'))); | |
@@ -823,21 +817,21 @@ module({ | |
assert.equal("4294967295", cm.unsigned_long_to_string(4294967295)); | |
// signed types should have their min negative values. | |
assert.equal("-128", cm.char_to_string(-128)); | |
assert.equal("-128", cm.signed_char_to_string(-128)); | |
assert.equal("-32768", cm.short_to_string(-32768)); | |
assert.equal("-2147483648", cm.int_to_string(-2147483648)); | |
assert.equal("-2147483648", cm.long_to_string(-2147483648)); | |
// passing out of range values should fail with assertions. | |
- if (cm['ASSERTIONS']) { | |
+ if (getCompilerSetting('ASSERTIONS')) { | |
assert.throws(TypeError, function() { cm.char_to_string(-129); }); | |
assert.throws(TypeError, function() { cm.char_to_string(128); }); | |
assert.throws(TypeError, function() { cm.signed_char_to_string(-129); }); | |
assert.throws(TypeError, function() { cm.signed_char_to_string(128); }); | |
assert.throws(TypeError, function() { cm.unsigned_char_to_string(-1); }); | |
assert.throws(TypeError, function() { cm.unsigned_char_to_string(256); }); | |
assert.throws(TypeError, function() { cm.short_to_string(-32769); }); | |
assert.throws(TypeError, function() { cm.short_to_string(32768); }); | |
assert.throws(TypeError, function() { cm.unsigned_short_to_string(-1); }); | |
assert.throws(TypeError, function() { cm.unsigned_short_to_string(65536); }); | |
@@ -862,21 +856,21 @@ module({ | |
cm.store_unsigned_short(32768); | |
assert.equal(32768, cm.load_unsigned_short()); | |
cm.store_unsigned_int(2147483648); | |
assert.equal(2147483648, cm.load_unsigned_int()); | |
cm.store_unsigned_long(2147483648); | |
assert.equal(2147483648, cm.load_unsigned_long()); | |
}); | |
- if (cm['ASSERTIONS']) { | |
+ if (getCompilerSetting('ASSERTIONS')) { | |
test("throws type error when attempting to coerce null to int", function() { | |
var e = assert.throws(TypeError, function() { | |
cm.int_to_string(null); | |
}); | |
assert.equal('Cannot convert "null" to int', e.message); | |
}); | |
} else { | |
test("null is converted to 0 without assertions", function() { | |
assert.equal('0', cm.int_to_string(null)); | |
}); | |
@@ -1043,27 +1037,27 @@ module({ | |
assert.equal(20, vec.get(1)); | |
assert.equal(30, vec.get(2)); | |
vec.delete(); | |
}); | |
test("out of bounds std::vector access returns undefined", function() { | |
var vec = cm.emval_test_return_vector(); | |
assert.equal(undefined, vec.get(4)); | |
// only test a negative index without assertions. | |
- if (!cm['ASSERTIONS']) { | |
+ if (!getCompilerSetting('ASSERTIONS')) { | |
assert.equal(undefined, vec.get(-1)); | |
} | |
vec.delete(); | |
}); | |
- if (cm['ASSERTIONS']) { | |
+ if (getCompilerSetting('ASSERTIONS')) { | |
test("out of type range array index throws with assertions", function() { | |
var vec = cm.emval_test_return_vector(); | |
assert.throws(TypeError, function() { vec.get(-1); }); | |
vec.delete(); | |
}); | |
} | |
test("std::vector<std::shared_ptr<>> can be passed back", function() { | |
@@ -1444,21 +1438,21 @@ module({ | |
assert.equal(15, c.field); | |
c.delete(); | |
}); | |
test("assignment returns value", function() { | |
var c = new cm.CustomStruct(); | |
assert.equal(15, c.field = 15); | |
c.delete(); | |
}); | |
- if (cm['ASSERTIONS']) { | |
+ if (getCompilerSetting('ASSERTIONS')) { | |
test("assigning string or object to integer raises TypeError with assertions", function() { | |
var c = new cm.CustomStruct(); | |
var e = assert.throws(TypeError, function() { | |
c.field = "hi"; | |
}); | |
assert.equal('Cannot convert "hi" to int', e.message); | |
var e = assert.throws(TypeError, function() { | |
c.field = {foo:'bar'}; | |
}); | |
@@ -2509,24 +2503,21 @@ module({ | |
test('can call method on noncopyable object', function() { | |
var x = new cm.Noncopyable; | |
assert.equal('foo', x.method()); | |
x.delete(); | |
}); | |
}); | |
BaseFixture.extend("function names", function() { | |
assert.equal('ValHolder', cm.ValHolder.name); | |
- // The test harness should set this value one way or the other. | |
- assert.true(cm['DYNAMIC_EXECUTION'] !== undefined); | |
- | |
- if (!cm['DYNAMIC_EXECUTION']) { | |
+ if (!getCompilerSetting('DYNAMIC_EXECUTION')) { | |
assert.equal('', cm.ValHolder.prototype.setVal.name); | |
assert.equal('', cm.ValHolder.makeConst.name); | |
} else { | |
assert.equal('ValHolder$setVal', cm.ValHolder.prototype.setVal.name); | |
assert.equal('ValHolder$makeConst', cm.ValHolder.makeConst.name); | |
} | |
}); | |
BaseFixture.extend("constants", function() { | |
assert.equal(10, cm.INT_CONSTANT); | |
diff --git a/test/test_other.py b/test/test_other.py | |
index 477fc5ca7..ad0a2d3f1 100644 | |
--- a/test/test_other.py | |
+++ b/test/test_other.py | |
@@ -2736,20 +2736,21 @@ int f() { | |
@with_env_modify({'EMCC_CLOSURE_ARGS': '--externs ' + shlex.quote(test_file('embind/underscore-externs.js'))}) | |
def test_embind(self, extra_args): | |
test_cases = [ | |
(['-lembind']), | |
# Ensure embind compiles under C++17 where "noexcept" became part of the function signature. | |
(['-lembind', '-std=c++17']), | |
(['-lembind', '-O1']), | |
(['-lembind', '-O2']), | |
(['-lembind', '-O2', '-sALLOW_MEMORY_GROWTH', test_file('embind/isMemoryGrowthEnabled=true.cpp')]), | |
] | |
+ extra_args = extra_args + ['-sRETAIN_COMPILER_SETTINGS'] | |
test_cases = [t + extra_args for t in test_cases] | |
# closure compiler doesn't work with DYNAMIC_EXECUTION=0 | |
test_cases.append((['-lembind', '-O2', '--closure=1'])) | |
for args in test_cases: | |
print(args) | |
self.clear() | |
testFiles = [ | |
test_file('embind/underscore-1.4.2.js'), | |
test_file('embind/imvu_test_adapter.js'), |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment