diff --git a/src/api/Diablo.jscc b/src/api/Diablo.jscc index b2e8077..e494cd2 100644 --- a/src/api/Diablo.jscc +++ b/src/api/Diablo.jscc @@ -5,6 +5,11 @@ var Diablo = (function() { function(Diablo) { Diablo = Diablo || {}; +// Copyright 2010 The Emscripten Authors. All rights reserved. +// Emscripten is available under two separate licenses, the MIT license and the +// University of Illinois/NCSA Open Source License. Both these licenses can be +// found in the LICENSE file. + // The Module object: Our interface to the outside world. We import // and export values on it. There are various ways Module can be used: // 1. Not defined. We create it here @@ -45,25 +50,35 @@ Module['quit'] = function(status, toThrow) { Module['preRun'] = []; Module['postRun'] = []; -// The environment setup code below is customized to use Module. -// *** Environment setup code *** +// Determine the runtime environment we are in. You can customize this by +// setting the ENVIRONMENT setting at compile time (see settings.js). var ENVIRONMENT_IS_WEB = false; var ENVIRONMENT_IS_WORKER = false; var ENVIRONMENT_IS_NODE = false; +var ENVIRONMENT_HAS_NODE = false; var ENVIRONMENT_IS_SHELL = false; ENVIRONMENT_IS_WEB = typeof window === 'object'; ENVIRONMENT_IS_WORKER = typeof importScripts === 'function'; -ENVIRONMENT_IS_NODE = typeof process === 'object' && typeof require === 'function' && !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_WORKER; +// A web environment like Electron.js can have Node enabled, so we must +// distinguish between Node-enabled environments and Node environments per se. +// This will allow the former to do things like mount NODEFS. +// Extended check using process.versions fixes issue #8816. +// (Also makes redundant the original check that 'require' is a function.) +ENVIRONMENT_HAS_NODE = typeof process === 'object' && typeof process.versions === 'object' && typeof process.versions.node === 'string'; +ENVIRONMENT_IS_NODE = ENVIRONMENT_HAS_NODE && !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_WORKER; ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER; + // Three configurations we can be running in: // 1) We could be the application main() thread running in the main JS UI thread. (ENVIRONMENT_IS_WORKER == false and ENVIRONMENT_IS_PTHREAD == false) // 2) We could be the application main() thread proxied to worker. (with Emscripten -s PROXY_TO_WORKER=1) (ENVIRONMENT_IS_WORKER == true, ENVIRONMENT_IS_PTHREAD == false) // 3) We could be an application pthread running in a worker. (ENVIRONMENT_IS_WORKER == true and ENVIRONMENT_IS_PTHREAD == true) + + // `/` should be present at the end if `scriptDirectory` is not empty var scriptDirectory = ''; function locateFile(path) { @@ -74,6 +89,12 @@ function locateFile(path) { } } +// Hooks that are implemented differently in different runtime environments. +var read_, + readAsync, + readBinary, + setWindowTitle; + if (ENVIRONMENT_IS_NODE) { scriptDirectory = __dirname + '/'; @@ -82,7 +103,7 @@ if (ENVIRONMENT_IS_NODE) { var nodeFS; var nodePath; - Module['read'] = function shell_read(filename, binary) { + read_ = function shell_read(filename, binary) { var ret; if (!nodeFS) nodeFS = require('fs'); if (!nodePath) nodePath = require('path'); @@ -91,8 +112,8 @@ if (ENVIRONMENT_IS_NODE) { return binary ? ret : ret.toString(); }; - Module['readBinary'] = function readBinary(filename) { - var ret = Module['read'](filename, true); + readBinary = function readBinary(filename) { + var ret = read_(filename, true); if (!ret.buffer) { ret = new Uint8Array(ret); } @@ -116,9 +137,7 @@ if (ENVIRONMENT_IS_NODE) { }); // Currently node will swallow unhandled rejections, but this behavior is // deprecated, and in the future it will exit with error status. - process['on']('unhandledRejection', function(reason, p) { - process['exit'](1); - }); + process['on']('unhandledRejection', abort); Module['quit'] = function(status) { process['exit'](status); @@ -130,12 +149,12 @@ if (ENVIRONMENT_IS_SHELL) { if (typeof read != 'undefined') { - Module['read'] = function shell_read(f) { + read_ = function shell_read(f) { return read(f); }; } - Module['readBinary'] = function readBinary(f) { + readBinary = function readBinary(f) { var data; if (typeof readbuffer === 'function') { return new Uint8Array(readbuffer(f)); @@ -158,12 +177,10 @@ if (ENVIRONMENT_IS_SHELL) { } } else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { - if (ENVIRONMENT_IS_WEB) { - if (document.currentScript) { - scriptDirectory = document.currentScript.src; - } - } else { // worker + if (ENVIRONMENT_IS_WORKER) { // Check worker, not web, since window could be polyfilled scriptDirectory = self.location.href; + } else if (document.currentScript) { // web + scriptDirectory = document.currentScript.src; } // When MODULARIZE (and not _INSTANCE), this JS may be executed later, after document.currentScript // is gone, so we saved it, and we use it here instead of any other info. @@ -172,14 +189,16 @@ if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { } // blob urls look like blob:http://site.com/etc/etc and we cannot infer anything from them. // otherwise, slice off the final part of the url to find the script directory. + // if scriptDirectory does not contain a slash, lastIndexOf will return -1, + // and scriptDirectory will correctly be replaced with an empty string. if (scriptDirectory.indexOf('blob:') !== 0) { - scriptDirectory = scriptDirectory.split('/').slice(0, -1).join('/') + '/'; + scriptDirectory = scriptDirectory.substr(0, scriptDirectory.lastIndexOf('/')+1); } else { scriptDirectory = ''; } - Module['read'] = function shell_read(url) { + read_ = function shell_read(url) { var xhr = new XMLHttpRequest(); xhr.open('GET', url, false); xhr.send(null); @@ -187,7 +206,7 @@ if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { }; if (ENVIRONMENT_IS_WORKER) { - Module['readBinary'] = function readBinary(url) { + readBinary = function readBinary(url) { var xhr = new XMLHttpRequest(); xhr.open('GET', url, false); xhr.responseType = 'arraybuffer'; @@ -196,7 +215,7 @@ if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { }; } - Module['readAsync'] = function readAsync(url, onload, onerror) { + readAsync = function readAsync(url, onload, onerror) { var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.responseType = 'arraybuffer'; @@ -211,7 +230,7 @@ if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { xhr.send(null); }; - Module['setWindowTitle'] = function(title) { document.title = title }; + setWindowTitle = function(title) { document.title = title }; } else { } @@ -225,8 +244,6 @@ if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { var out = Module['print'] || (typeof console !== 'undefined' ? console.log.bind(console) : (typeof print !== 'undefined' ? print : null)); var err = Module['printErr'] || (typeof printErr !== 'undefined' ? printErr : ((typeof console !== 'undefined' && console.warn.bind(console)) || out)); -// *** Environment setup code *** - // Merge back in the overrides for (key in moduleOverrides) { if (moduleOverrides.hasOwnProperty(key)) { @@ -237,37 +254,35 @@ for (key in moduleOverrides) { // reclaim data used e.g. in memoryInitializerRequest, which is a large typed array. moduleOverrides = undefined; +// perform assertions in shell.js after we set up out() and err(), as otherwise if an assertion fails it cannot print the message +// TODO remove when SDL2 is fixed; also add the above assertion + + + +// Copyright 2017 The Emscripten Authors. All rights reserved. +// Emscripten is available under two separate licenses, the MIT license and the +// University of Illinois/NCSA Open Source License. Both these licenses can be +// found in the LICENSE file. // {{PREAMBLE_ADDITIONS}} var STACK_ALIGN = 16; -function staticAlloc(size) { - var ret = STATICTOP; - STATICTOP = (STATICTOP + size + 15) & -16; - return ret; -} - function dynamicAlloc(size) { var ret = HEAP32[DYNAMICTOP_PTR>>2]; var end = (ret + size + 15) & -16; - HEAP32[DYNAMICTOP_PTR>>2] = end; - if (end >= TOTAL_MEMORY) { - var success = enlargeMemory(); - if (!success) { - HEAP32[DYNAMICTOP_PTR>>2] = ret; - return 0; - } + if (end > _emscripten_get_heap_size()) { + abort(); } + HEAP32[DYNAMICTOP_PTR>>2] = end; return ret; } function alignMemory(size, factor) { if (!factor) factor = STACK_ALIGN; // stack alignment (16-byte) by default - var ret = size = Math.ceil(size / factor) * factor; - return ret; + return Math.ceil(size / factor) * factor; } function getNativeTypeSize(type) { @@ -283,7 +298,7 @@ function getNativeTypeSize(type) { return 4; // A pointer } else if (type[0] === 'i') { var bits = parseInt(type.substr(1)); - assert(bits % 8 === 0); + assert(bits % 8 === 0, 'getNativeTypeSize invalid bits ' + bits + ', type ' + type); return bits / 8; } else { return 0; @@ -314,8 +329,112 @@ var asm2wasmImports = { // special asm2wasm imports var jsCallStartIndex = 1; var functionPointers = new Array(0); -// 'sig' parameter is only used on LLVM wasm backend +// Wraps a JS function as a wasm function with a given signature. +// In the future, we may get a WebAssembly.Function constructor. Until then, +// we create a wasm module that takes the JS function as an import with a given +// signature, and re-exports that as a wasm function. +function convertJsFunctionToWasm(func, sig) { + + // The module is static, with the exception of the type section, which is + // generated based on the signature passed in. + var typeSection = [ + 0x01, // id: section, + 0x00, // length: 0 (placeholder) + 0x01, // count: 1 + 0x60, // form: func + ]; + var sigRet = sig.slice(0, 1); + var sigParam = sig.slice(1); + var typeCodes = { + 'i': 0x7f, // i32 + 'j': 0x7e, // i64 + 'f': 0x7d, // f32 + 'd': 0x7c, // f64 + }; + + // Parameters, length + signatures + typeSection.push(sigParam.length); + for (var i = 0; i < sigParam.length; ++i) { + typeSection.push(typeCodes[sigParam[i]]); + } + + // Return values, length + signatures + // With no multi-return in MVP, either 0 (void) or 1 (anything else) + if (sigRet == 'v') { + typeSection.push(0x00); + } else { + typeSection = typeSection.concat([0x01, typeCodes[sigRet]]); + } + + // Write the overall length of the type section back into the section header + // (excepting the 2 bytes for the section id and length) + typeSection[1] = typeSection.length - 2; + + // Rest of the module is static + var bytes = new Uint8Array([ + 0x00, 0x61, 0x73, 0x6d, // magic ("\0asm") + 0x01, 0x00, 0x00, 0x00, // version: 1 + ].concat(typeSection, [ + 0x02, 0x07, // import section + // (import "e" "f" (func 0 (type 0))) + 0x01, 0x01, 0x65, 0x01, 0x66, 0x00, 0x00, + 0x07, 0x05, // export section + // (export "f" (func 0 (type 0))) + 0x01, 0x01, 0x66, 0x00, 0x00, + ])); + + // We can compile this wasm module synchronously because it is very small. + // This accepts an import (at "e.f"), that it reroutes to an export (at "f") + var module = new WebAssembly.Module(bytes); + var instance = new WebAssembly.Instance(module, { + e: { + f: func + } + }); + var wrappedFunc = instance.exports.f; + return wrappedFunc; +} + +// Add a wasm function to the table. +function addFunctionWasm(func, sig) { + var table = wasmTable; + var ret = table.length; + + // Grow the table + try { + table.grow(1); + } catch (err) { + if (!err instanceof RangeError) { + throw err; + } + throw 'Unable to grow wasm table. Use a higher value for RESERVED_FUNCTION_POINTERS or set ALLOW_TABLE_GROWTH.'; + } + + // Insert new element + try { + // Attempting to call this with JS function will cause of table.set() to fail + table.set(ret, func); + } catch (err) { + if (!err instanceof TypeError) { + throw err; + } + assert(typeof sig !== 'undefined', 'Missing signature argument to addFunction'); + var wrapped = convertJsFunctionToWasm(func, sig); + table.set(ret, wrapped); + } + + return ret; +} + +function removeFunctionWasm(index) { + // TODO(sbc): Look into implementing this to allow re-using of table slots +} + +// 'sig' parameter is required for the llvm backend but only when func is not +// already a WebAssembly function. function addFunction(func, sig) { + + var base = 0; for (var i = base; i < base + 0; i++) { if (!functionPointers[i]) { @@ -324,9 +443,11 @@ function addFunction(func, sig) { } } throw 'Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.'; + } function removeFunction(index) { + functionPointers[index-jsCallStartIndex] = null; } @@ -372,13 +493,18 @@ function dynCall(sig, ptr, args) { } } +var tempRet0 = 0; + +var setTempRet0 = function(value) { + tempRet0 = value; +}; + +var getTempRet0 = function() { + return tempRet0; +}; var Runtime = { - // FIXME backwards compatibility layer for ports. Support some Runtime.* - // for now, fix it there, then remove it from here. That way we - // can minimize any period of breakage. - dynCall: dynCall, // for SDL2 port }; // The address globals begin at. Very low in memory, for code size and optimization opportunities. @@ -388,6 +514,8 @@ var Runtime = { var GLOBAL_BASE = 1024; + + // === Preamble library stuff === // Documentation for the public APIs defined in this file must be updated in: @@ -400,11 +528,70 @@ var GLOBAL_BASE = 1024; +if (typeof WebAssembly !== 'object') { + err('no native wasm support detected'); +} + + +// In MINIMAL_RUNTIME, setValue() and getValue() are only available when building with safe heap enabled, for heap safety checking. +// In traditional runtime, setValue() and getValue() are always available (although their use is highly discouraged due to perf penalties) + +/** @type {function(number, number, string, boolean=)} */ +function setValue(ptr, value, type, noSafe) { + type = type || 'i8'; + if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit + 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.0 ? (tempDouble > 0.0 ? ((Math_min((+(Math_floor((tempDouble)/4294967296.0))), 4294967295.0))|0)>>>0 : (~~((+(Math_ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>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; + default: abort('invalid type for setValue: ' + type); + } +} + +/** @type {function(number, string, boolean=)} */ +function getValue(ptr, type, noSafe) { + type = type || 'i8'; + if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit + 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)]; + default: abort('invalid type for getValue: ' + type); + } + return null; +} + + + + + +// Wasm globals + +var wasmMemory; + +// Potentially used for direct table calls. +var wasmTable; + + //======================================== // Runtime essentials //======================================== -var ABORT = 0; // whether we are quitting the application. no code should run after this. set in exit() and abort() +// whether we are quitting the application. no code should run after this. +// set in exit() and abort() +var ABORT = false; + +// set by exit() and abort(). Passed to 'onExit' handler. +// NOTE: This is also used as the process return code code in shell environments +// but only when noExitRuntime is false. var EXITSTATUS = 0; /** @type {function(*, string=)} */ @@ -414,8 +601,6 @@ function assert(condition, text) { } } -var globalScope = this; - // Returns the C function with a specified identifier (for C++, you need to do manual name mangling) function getCFunc(ident) { var func = Module['_' + ident]; // closure exported function @@ -423,44 +608,29 @@ function getCFunc(ident) { return func; } -var JSfuncs = { - // Helpers for cwrap -- it can't refer to Runtime directly because it might - // be renamed by closure, instead it calls JSfuncs['stackSave'].body to find - // out what the minified function name is. - 'stackSave': function() { - stackSave() - }, - 'stackRestore': function() { - stackRestore() - }, - // type conversion from js to c - 'arrayToC' : function(arr) { - var ret = stackAlloc(arr.length); - writeArrayToMemory(arr, ret); - return ret; - }, - 'stringToC' : function(str) { - var ret = 0; - if (str !== null && str !== undefined && str !== 0) { // null string - // at most 4 bytes per UTF-8 code point, +1 for the trailing '\0' - var len = (str.length << 2) + 1; - ret = stackAlloc(len); - stringToUTF8(str, ret, len); - } - return ret; - } -}; - -// For fast lookup of conversion functions -var toC = { - 'string': JSfuncs['stringToC'], 'array': JSfuncs['arrayToC'] -}; - - // C calling interface. function ccall(ident, returnType, argTypes, args, opts) { + // For fast lookup of conversion functions + var toC = { + 'string': function(str) { + var ret = 0; + if (str !== null && str !== undefined && str !== 0) { // null string + // at most 4 bytes per UTF-8 code point, +1 for the trailing '\0' + var len = (str.length << 2) + 1; + ret = stackAlloc(len); + stringToUTF8(str, ret, len); + } + return ret; + }, + 'array': function(arr) { + var ret = stackAlloc(arr.length); + writeArrayToMemory(arr, ret); + return ret; + } + }; + function convertReturnValue(ret) { - if (returnType === 'string') return Pointer_stringify(ret); + if (returnType === 'string') return UTF8ToString(ret); if (returnType === 'boolean') return Boolean(ret); return ret; } @@ -499,44 +669,10 @@ function cwrap(ident, returnType, argTypes, opts) { } } -/** @type {function(number, number, string, boolean=)} */ -function setValue(ptr, value, type, noSafe) { - type = type || 'i8'; - if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit - 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.0 ? (tempDouble > 0.0 ? ((Math_min((+(Math_floor((tempDouble)/4294967296.0))), 4294967295.0))|0)>>>0 : (~~((+(Math_ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>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; - default: abort('invalid type for setValue: ' + type); - } -} - -/** @type {function(number, string, boolean=)} */ -function getValue(ptr, type, noSafe) { - type = type || 'i8'; - if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit - 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)]; - default: abort('invalid type for getValue: ' + type); - } - return null; -} - var ALLOC_NORMAL = 0; // Tries to use _malloc() var ALLOC_STACK = 1; // Lives for the duration of the current function call -var ALLOC_STATIC = 2; // Cannot be freed -var ALLOC_DYNAMIC = 3; // Cannot be freed except through sbrk -var ALLOC_NONE = 4; // Do not allocate +var ALLOC_DYNAMIC = 2; // Cannot be freed except through sbrk +var ALLOC_NONE = 3; // Do not allocate // allocate(): This is for internal use. You can use it yourself as well, but the interface // is a little tricky (see docs right below). The reason is that it is optimized @@ -568,7 +704,9 @@ function allocate(slab, types, allocator, ptr) { if (allocator == ALLOC_NONE) { ret = ptr; } else { - ret = [typeof _malloc === 'function' ? _malloc : staticAlloc, stackAlloc, staticAlloc, dynamicAlloc][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length)); + ret = [_malloc, + stackAlloc, + dynamicAlloc][allocator](Math.max(size, singleType ? 1 : types.length)); } if (zeroinit) { @@ -622,41 +760,16 @@ function allocate(slab, types, allocator, ptr) { // Allocate memory during any stage of startup - static memory early on, dynamic memory later, malloc when ready function getMemory(size) { - if (!staticSealed) return staticAlloc(size); if (!runtimeInitialized) return dynamicAlloc(size); return _malloc(size); } + + + /** @type {function(number, number=)} */ function Pointer_stringify(ptr, length) { - if (length === 0 || !ptr) return ''; - // Find the length, and check for UTF while doing so - var hasUtf = 0; - var t; - var i = 0; - while (1) { - t = HEAPU8[(((ptr)+(i))>>0)]; - hasUtf |= t; - if (t == 0 && !length) break; - i++; - if (length && i == length) break; - } - if (!length) length = i; - - var ret = ''; - - if (hasUtf < 128) { - var MAX_CHUNK = 1024; // split up into chunks, because .apply on a huge string can overflow the stack - var curr; - while (length > 0) { - curr = String.fromCharCode.apply(String, HEAPU8.subarray(ptr, ptr + Math.min(length, MAX_CHUNK))); - ret = ret ? ret + curr : curr; - ptr += MAX_CHUNK; - length -= MAX_CHUNK; - } - return ret; - } - return UTF8ToString(ptr); + abort("this function has been removed - you should use UTF8ToString(ptr, maxBytesToRead) instead!"); } // Given a pointer 'ptr' to a null-terminated ASCII-encoded string in the emscripten HEAP, returns @@ -665,7 +778,7 @@ function Pointer_stringify(ptr, length) { function AsciiToString(ptr) { var str = ''; while (1) { - var ch = HEAP8[((ptr++)>>0)]; + var ch = HEAPU8[((ptr++)>>0)]; if (!ch) return str; str += String.fromCharCode(ch); } @@ -678,46 +791,46 @@ function stringToAscii(str, outPtr) { return writeAsciiToMemory(str, outPtr, false); } + // Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the given array that contains uint8 values, returns // a copy of that string as a Javascript String object. var UTF8Decoder = typeof TextDecoder !== 'undefined' ? new TextDecoder('utf8') : undefined; -function UTF8ArrayToString(u8Array, idx) { + +/** + * @param {number} idx + * @param {number=} maxBytesToRead + * @return {string} + */ +function UTF8ArrayToString(u8Array, idx, maxBytesToRead) { + var endIdx = idx + maxBytesToRead; var endPtr = idx; // TextDecoder needs to know the byte length in advance, it doesn't stop on null terminator by itself. // Also, use the length info to avoid running tiny strings through TextDecoder, since .subarray() allocates garbage. - while (u8Array[endPtr]) ++endPtr; + // (As a tiny code save trick, compare endPtr against endIdx using a negation, so that undefined means Infinity) + while (u8Array[endPtr] && !(endPtr >= endIdx)) ++endPtr; if (endPtr - idx > 16 && u8Array.subarray && UTF8Decoder) { return UTF8Decoder.decode(u8Array.subarray(idx, endPtr)); } else { - var u0, u1, u2, u3, u4, u5; - var str = ''; - while (1) { - // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description and https://www.ietf.org/rfc/rfc2279.txt and https://tools.ietf.org/html/rfc3629 - u0 = u8Array[idx++]; - if (!u0) return str; + // If building with TextDecoder, we have already computed the string length above, so test loop end condition against that + while (idx < endPtr) { + // For UTF8 byte structure, see: + // http://en.wikipedia.org/wiki/UTF-8#Description + // https://www.ietf.org/rfc/rfc2279.txt + // https://tools.ietf.org/html/rfc3629 + var u0 = u8Array[idx++]; if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; } - u1 = u8Array[idx++] & 63; + var u1 = u8Array[idx++] & 63; if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; } - u2 = u8Array[idx++] & 63; + var u2 = u8Array[idx++] & 63; if ((u0 & 0xF0) == 0xE0) { u0 = ((u0 & 15) << 12) | (u1 << 6) | u2; } else { - u3 = u8Array[idx++] & 63; - if ((u0 & 0xF8) == 0xF0) { - u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | u3; - } else { - u4 = u8Array[idx++] & 63; - if ((u0 & 0xFC) == 0xF8) { - u0 = ((u0 & 3) << 24) | (u1 << 18) | (u2 << 12) | (u3 << 6) | u4; - } else { - u5 = u8Array[idx++] & 63; - u0 = ((u0 & 1) << 30) | (u1 << 24) | (u2 << 18) | (u3 << 12) | (u4 << 6) | u5; - } - } + u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (u8Array[idx++] & 63); } + if (u0 < 0x10000) { str += String.fromCharCode(u0); } else { @@ -726,13 +839,26 @@ function UTF8ArrayToString(u8Array, idx) { } } } + return str; } -// Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the emscripten HEAP, returns -// a copy of that string as a Javascript String object. - -function UTF8ToString(ptr) { - return UTF8ArrayToString(HEAPU8,ptr); +// Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the emscripten HEAP, returns a +// copy of that string as a Javascript String object. +// maxBytesToRead: an optional length that specifies the maximum number of bytes to read. You can omit +// this parameter to scan the string until the first \0 byte. If maxBytesToRead is +// passed, and the string at [ptr, ptr+maxBytesToReadr[ contains a null byte in the +// middle, then the string will cut short at that byte index (i.e. maxBytesToRead will +// not produce a string of exact length [ptr, ptr+maxBytesToRead[) +// N.B. mixing frequent uses of UTF8ToString() with and without maxBytesToRead may +// throw JS JIT optimizations off, so it is worth to consider consistently using one +// style or the other. +/** + * @param {number} ptr + * @param {number=} maxBytesToRead + * @return {string} + */ +function UTF8ToString(ptr, maxBytesToRead) { + return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : ''; } // Copies the given Javascript String object 'str' to the given byte array at address 'outIdx', @@ -775,27 +901,12 @@ function stringToUTF8Array(str, outU8Array, outIdx, maxBytesToWrite) { outU8Array[outIdx++] = 0xE0 | (u >> 12); outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63); outU8Array[outIdx++] = 0x80 | (u & 63); - } else if (u <= 0x1FFFFF) { + } else { if (outIdx + 3 >= endIdx) break; outU8Array[outIdx++] = 0xF0 | (u >> 18); outU8Array[outIdx++] = 0x80 | ((u >> 12) & 63); outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63); outU8Array[outIdx++] = 0x80 | (u & 63); - } else if (u <= 0x3FFFFFF) { - if (outIdx + 4 >= endIdx) break; - outU8Array[outIdx++] = 0xF8 | (u >> 24); - outU8Array[outIdx++] = 0x80 | ((u >> 18) & 63); - outU8Array[outIdx++] = 0x80 | ((u >> 12) & 63); - outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63); - outU8Array[outIdx++] = 0x80 | (u & 63); - } else { - if (outIdx + 5 >= endIdx) break; - outU8Array[outIdx++] = 0xFC | (u >> 30); - outU8Array[outIdx++] = 0x80 | ((u >> 24) & 63); - outU8Array[outIdx++] = 0x80 | ((u >> 18) & 63); - outU8Array[outIdx++] = 0x80 | ((u >> 12) & 63); - outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63); - outU8Array[outIdx++] = 0x80 | (u & 63); } } // Null-terminate the pointer to the buffer. @@ -813,7 +924,6 @@ function stringToUTF8(str, outPtr, maxBytesToWrite) { } // Returns the number of bytes the given Javascript string takes if encoded as a UTF8 byte array, EXCLUDING the null terminator byte. - function lengthBytesUTF8(str) { var len = 0; for (var i = 0; i < str.length; ++i) { @@ -821,23 +931,15 @@ function lengthBytesUTF8(str) { // See http://unicode.org/faq/utf_bom.html#utf16-3 var u = str.charCodeAt(i); // possibly a lead surrogate if (u >= 0xD800 && u <= 0xDFFF) u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF); - if (u <= 0x7F) { - ++len; - } else if (u <= 0x7FF) { - len += 2; - } else if (u <= 0xFFFF) { - len += 3; - } else if (u <= 0x1FFFFF) { - len += 4; - } else if (u <= 0x3FFFFFF) { - len += 5; - } else { - len += 6; - } + if (u <= 0x7F) ++len; + else if (u <= 0x7FF) len += 2; + else if (u <= 0xFFFF) len += 3; + else len += 4; } return len; } + // Given a pointer 'ptr' to a null-terminated UTF16LE-encoded string in the emscripten HEAP, returns // a copy of that string as a Javascript String object. @@ -991,6 +1093,42 @@ function allocateUTF8OnStack(str) { return ret; } +// Deprecated: This function should not be called because it is unsafe and does not provide +// a maximum length limit of how many bytes it is allowed to write. Prefer calling the +// function stringToUTF8Array() instead, which takes in a maximum length that can be used +// to be secure from out of bounds writes. +/** @deprecated */ +function writeStringToMemory(string, buffer, dontAddNull) { + warnOnce('writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!'); + + var /** @type {number} */ lastChar, /** @type {number} */ end; + if (dontAddNull) { + // stringToUTF8Array always appends null. If we don't want to do that, remember the + // character that existed at the location where the null will be placed, and restore + // that after the write (below). + end = buffer + lengthBytesUTF8(string); + lastChar = HEAP8[end]; + } + stringToUTF8(string, buffer, Infinity); + if (dontAddNull) HEAP8[end] = lastChar; // Restore the value under the null character. +} + +function writeArrayToMemory(array, buffer) { + HEAP8.set(array, buffer); +} + +function writeAsciiToMemory(str, buffer, dontAddNull) { + for (var i = 0; i < str.length; ++i) { + HEAP8[((buffer++)>>0)]=str.charCodeAt(i); + } + // Null-terminate the pointer to the HEAP. + if (!dontAddNull) HEAP8[((buffer)>>0)]=0; +} + + + + + function demangle(func) { return func; } @@ -1001,7 +1139,7 @@ function demangleAll(text) { return text.replace(regex, function(x) { var y = demangle(x); - return x === y ? x : (x + ' [' + y + ']'); + return x === y ? x : (y + ' [' + x + ']'); }); } @@ -1028,12 +1166,13 @@ function stackTrace() { return demangleAll(js); } + + // Memory management var PAGE_SIZE = 16384; var WASM_PAGE_SIZE = 65536; var ASMJS_PAGE_SIZE = 16777216; -var MIN_TOTAL_MEMORY = 16777216; function alignUp(x, multiple) { if (x % multiple > 0) { @@ -1062,10 +1201,6 @@ var HEAP, /** @type {Float64Array} */ HEAPF64; -function updateGlobalBuffer(buf) { - Module['buffer'] = buffer = buf; -} - function updateGlobalBufferViews() { Module['HEAP8'] = HEAP8 = new Int8Array(buffer); Module['HEAP16'] = HEAP16 = new Int16Array(buffer); @@ -1077,116 +1212,53 @@ function updateGlobalBufferViews() { Module['HEAPF64'] = HEAPF64 = new Float64Array(buffer); } -var STATIC_BASE, STATICTOP, staticSealed; // static area -var STACK_BASE, STACKTOP, STACK_MAX; // stack area -var DYNAMIC_BASE, DYNAMICTOP_PTR; // dynamic area handled by sbrk - STATIC_BASE = STATICTOP = STACK_BASE = STACKTOP = STACK_MAX = DYNAMIC_BASE = DYNAMICTOP_PTR = 0; - staticSealed = false; +var STATIC_BASE = 1024, + STACK_BASE = 1875744, + STACKTOP = STACK_BASE, + STACK_MAX = 7118624, + DYNAMIC_BASE = 7118624, + DYNAMICTOP_PTR = 1875712; -function abortOnCannotGrowMemory() { - abort('Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value ' + TOTAL_MEMORY + ', (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 '); -} +var TOTAL_STACK = 5242880; -if (!Module['reallocBuffer']) Module['reallocBuffer'] = function(size) { - var ret; - try { - if (ArrayBuffer.transfer) { - ret = ArrayBuffer.transfer(buffer, size); - } else { - var oldHEAP8 = HEAP8; - ret = new ArrayBuffer(size); - var temp = new Int8Array(ret); - temp.set(oldHEAP8); - } - } catch(e) { - return false; - } - var success = _emscripten_replace_memory(ret); - if (!success) return false; - return ret; -}; - -function enlargeMemory() { - // TOTAL_MEMORY is the current size of the actual array, and DYNAMICTOP is the new top. - - - var PAGE_MULTIPLE = Module["usingWasm"] ? WASM_PAGE_SIZE : ASMJS_PAGE_SIZE; // In wasm, heap size must be a multiple of 64KB. In asm.js, they need to be multiples of 16MB. - var LIMIT = 2147483648 - PAGE_MULTIPLE; // We can do one page short of 2GB as theoretical maximum. - - if (HEAP32[DYNAMICTOP_PTR>>2] > LIMIT) { - return false; - } - - var OLD_TOTAL_MEMORY = TOTAL_MEMORY; - TOTAL_MEMORY = Math.max(TOTAL_MEMORY, MIN_TOTAL_MEMORY); // So the loop below will not be infinite, and minimum asm.js memory size is 16MB. - - while (TOTAL_MEMORY < HEAP32[DYNAMICTOP_PTR>>2]) { // Keep incrementing the heap size as long as it's less than what is requested. - if (TOTAL_MEMORY <= 536870912) { - TOTAL_MEMORY = alignUp(2 * TOTAL_MEMORY, PAGE_MULTIPLE); // Simple heuristic: double until 1GB... - } else { - // ..., but after that, add smaller increments towards 2GB, which we cannot reach - TOTAL_MEMORY = Math.min(alignUp((3 * TOTAL_MEMORY + 2147483648) / 4, PAGE_MULTIPLE), LIMIT); - } - } - - - var replacement = Module['reallocBuffer'](TOTAL_MEMORY); - if (!replacement || replacement.byteLength != TOTAL_MEMORY) { - // restore the state to before this call, we failed - TOTAL_MEMORY = OLD_TOTAL_MEMORY; - return false; - } - - // everything worked - - updateGlobalBuffer(replacement); - updateGlobalBufferViews(); - - - - return true; -} - -var byteLength; -try { - byteLength = Function.prototype.call.bind(Object.getOwnPropertyDescriptor(ArrayBuffer.prototype, 'byteLength').get); - byteLength(new ArrayBuffer(4)); // can fail on older ie -} catch(e) { // can fail on older node/v8 - byteLength = function(buffer) { return buffer.byteLength; }; -} - -var TOTAL_STACK = Module['TOTAL_STACK'] || 5242880; -var TOTAL_MEMORY = Module['TOTAL_MEMORY'] || 134217728; -if (TOTAL_MEMORY < TOTAL_STACK) err('TOTAL_MEMORY should be larger than TOTAL_STACK, was ' + TOTAL_MEMORY + '! (TOTAL_STACK=' + TOTAL_STACK + ')'); +var INITIAL_TOTAL_MEMORY = Module['TOTAL_MEMORY'] || 134217728; +if (INITIAL_TOTAL_MEMORY < TOTAL_STACK) err('TOTAL_MEMORY should be larger than TOTAL_STACK, was ' + INITIAL_TOTAL_MEMORY + '! (TOTAL_STACK=' + TOTAL_STACK + ')'); // Initialize the runtime's memory -// Use a provided buffer, if there is one, or else allocate a new one -if (Module['buffer']) { - buffer = Module['buffer']; -} else { - // Use a WebAssembly memory where available - if (typeof WebAssembly === 'object' && typeof WebAssembly.Memory === 'function') { - Module['wasmMemory'] = new WebAssembly.Memory({ 'initial': TOTAL_MEMORY / WASM_PAGE_SIZE }); - buffer = Module['wasmMemory'].buffer; - } else - { - buffer = new ArrayBuffer(TOTAL_MEMORY); + + + + if (Module['wasmMemory']) { + wasmMemory = Module['wasmMemory']; + } else { + wasmMemory = new WebAssembly.Memory({ + 'initial': INITIAL_TOTAL_MEMORY / WASM_PAGE_SIZE + }); } - Module['buffer'] = buffer; + + +if (wasmMemory) { + buffer = wasmMemory.buffer; } + +// If the user provides an incorrect length, just use that length instead rather than providing the user to +// specifically provide the memory length with Module['TOTAL_MEMORY']. +INITIAL_TOTAL_MEMORY = buffer.byteLength; updateGlobalBufferViews(); +HEAP32[DYNAMICTOP_PTR>>2] = DYNAMIC_BASE; + + + + -function getTotalMemory() { - return TOTAL_MEMORY; -} // Endianness check (note: assumes compiler arch was little-endian) @@ -1231,18 +1303,18 @@ function preRun() { callRuntimeCallbacks(__ATPRERUN__); } -function ensureInitRuntime() { - if (runtimeInitialized) return; +function initRuntime() { runtimeInitialized = true; + callRuntimeCallbacks(__ATINIT__); } function preMain() { + callRuntimeCallbacks(__ATMAIN__); } function exitRuntime() { - callRuntimeCallbacks(__ATEXIT__); runtimeExited = true; } @@ -1270,45 +1342,12 @@ function addOnPreMain(cb) { } function addOnExit(cb) { - __ATEXIT__.unshift(cb); } function addOnPostRun(cb) { __ATPOSTRUN__.unshift(cb); } -// Deprecated: This function should not be called because it is unsafe and does not provide -// a maximum length limit of how many bytes it is allowed to write. Prefer calling the -// function stringToUTF8Array() instead, which takes in a maximum length that can be used -// to be secure from out of bounds writes. -/** @deprecated */ -function writeStringToMemory(string, buffer, dontAddNull) { - warnOnce('writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!'); - - var /** @type {number} */ lastChar, /** @type {number} */ end; - if (dontAddNull) { - // stringToUTF8Array always appends null. If we don't want to do that, remember the - // character that existed at the location where the null will be placed, and restore - // that after the write (below). - end = buffer + lengthBytesUTF8(string); - lastChar = HEAP8[end]; - } - stringToUTF8(string, buffer, Infinity); - if (dontAddNull) HEAP8[end] = lastChar; // Restore the value under the null character. -} - -function writeArrayToMemory(array, buffer) { - HEAP8.set(array, buffer); -} - -function writeAsciiToMemory(str, buffer, dontAddNull) { - for (var i = 0; i < str.length; ++i) { - HEAP8[((buffer++)>>0)]=str.charCodeAt(i); - } - // Null-terminate the pointer to the HEAP. - if (!dontAddNull) HEAP8[((buffer)>>0)]=0; -} - function unSign(value, bits, ignore) { if (value >= 0) { return value; @@ -1331,6 +1370,7 @@ function reSign(value, bits, ignore) { } + var Math_abs = Math.abs; var Math_cos = Math.cos; var Math_sin = Math.sin; @@ -1353,10 +1393,12 @@ var Math_max = Math.max; var Math_clz32 = Math.clz32; var Math_trunc = Math.trunc; + + // A counter of dependencies for calling run(). If we need to // do asynchronous work before running, increment this and // decrement it. Incrementing must happen in a place like -// PRE_RUN_ADDITIONS (used by emcc to add file preloading). +// Module.preRun (used by emcc to add file preloading). // Note that you can add dependencies in preRun, even though // it happens right before run - run will be postponed until // the dependencies are met. @@ -1397,7 +1439,6 @@ Module["preloadedImages"] = {}; // maps url to image data Module["preloadedAudios"] = {}; // maps url to audio data - var memoryInitializer = null; @@ -1405,6 +1446,11 @@ var memoryInitializer = null; +// Copyright 2017 The Emscripten Authors. All rights reserved. +// Emscripten is available under two separate licenses, the MIT license and the +// University of Illinois/NCSA Open Source License. Both these licenses can be +// found in the LICENSE file. + // Prefix of data URIs emitted by SINGLE_FILE and related options. var dataURIPrefix = 'data:application/octet-stream;base64,'; @@ -1418,270 +1464,156 @@ function isDataURI(filename) { -function integrateWasmJS() { - // wasm.js has several methods for creating the compiled code module here: - // * 'native-wasm' : use native WebAssembly support in the browser - // * 'interpret-s-expr': load s-expression code from a .wast and interpret - // * 'interpret-binary': load binary wasm and interpret - // * 'interpret-asm2wasm': load asm.js code, translate to wasm, and interpret - // * 'asmjs': no wasm, just load the asm.js code and use that (good for testing) - // The method is set at compile time (BINARYEN_METHOD) - // The method can be a comma-separated list, in which case, we will try the - // options one by one. Some of them can fail gracefully, and then we can try - // the next. +var wasmBinaryFile = 'Diablo.wasm'; +if (!isDataURI(wasmBinaryFile)) { + wasmBinaryFile = locateFile(wasmBinaryFile); +} - // inputs - - var method = 'native-wasm'; - - var wasmTextFile = 'Diablo.wast'; - var wasmBinaryFile = 'Diablo.wasm'; - var asmjsCodeFile = 'Diablo.temp.asm.js'; - - if (!isDataURI(wasmTextFile)) { - wasmTextFile = locateFile(wasmTextFile); +function getBinary() { + try { + if (Module['wasmBinary']) { + return new Uint8Array(Module['wasmBinary']); + } + if (readBinary) { + return readBinary(wasmBinaryFile); + } else { + throw "both async and sync fetching of the wasm failed"; + } } - if (!isDataURI(wasmBinaryFile)) { - wasmBinaryFile = locateFile(wasmBinaryFile); + catch (err) { + abort(err); } - if (!isDataURI(asmjsCodeFile)) { - asmjsCodeFile = locateFile(asmjsCodeFile); +} + +function getBinaryPromise() { + // if we don't have the binary yet, and have the Fetch api, use that + // in some environments, like Electron's render process, Fetch api may be present, but have a different context than expected, let's only use it on the Web + if (!Module['wasmBinary'] && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) && typeof fetch === 'function') { + return fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function(response) { + if (!response['ok']) { + throw "failed to load wasm binary file at '" + wasmBinaryFile + "'"; + } + return response['arrayBuffer'](); + }).catch(function () { + return getBinary(); + }); } + // Otherwise, getBinary should be able to get it synchronously + return new Promise(function(resolve, reject) { + resolve(getBinary()); + }); +} - // utilities - var wasmPageSize = 64*1024; +// Create the wasm instance. +// Receives the wasm imports, returns the exports. +function createWasm(env) { + + // prepare imports var info = { - 'global': null, - 'env': null, - 'asm2wasm': asm2wasmImports, - 'parent': Module // Module inside wasm-js.cpp refers to wasm-js.cpp; this allows access to the outside program. + 'env': env + , + 'global': { + 'NaN': NaN, + 'Infinity': Infinity + }, + 'global.Math': Math, + 'asm2wasm': asm2wasmImports }; - - var exports = null; + // Load the wasm module and create an instance of using native support in the JS engine. + // handle a generated wasm instance, receiving its exports and + // performing other necessary setup + function receiveInstance(instance, module) { + var exports = instance.exports; + Module['asm'] = exports; + removeRunDependency('wasm-instantiate'); + } + addRunDependency('wasm-instantiate'); - function mergeMemory(newBuffer) { - // The wasm instance creates its memory. But static init code might have written to - // buffer already, including the mem init file, and we must copy it over in a proper merge. - // TODO: avoid this copy, by avoiding such static init writes - // TODO: in shorter term, just copy up to the last static init write - var oldBuffer = Module['buffer']; - if (newBuffer.byteLength < oldBuffer.byteLength) { - err('the new buffer in mergeMemory is smaller than the previous one. in native wasm, we should grow memory here'); - } - var oldView = new Int8Array(oldBuffer); - var newView = new Int8Array(newBuffer); - - - newView.set(oldView); - updateGlobalBuffer(newBuffer); - updateGlobalBufferViews(); + function receiveInstantiatedSource(output) { + // 'output' is a WebAssemblyInstantiatedSource object which has both the module and instance. + // receiveInstance() will swap in the exports (to Module.asm) so they can be called + // TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193, the above line no longer optimizes out down to the following line. + // When the regression is fixed, can restore the above USE_PTHREADS-enabled path. + receiveInstance(output['instance']); } - function fixImports(imports) { - return imports; - } - function getBinary() { - try { - if (Module['wasmBinary']) { - return new Uint8Array(Module['wasmBinary']); - } - if (Module['readBinary']) { - return Module['readBinary'](wasmBinaryFile); - } else { - throw "both async and sync fetching of the wasm failed"; - } - } - catch (err) { - abort(err); - } - } - - function getBinaryPromise() { - // if we don't have the binary yet, and have the Fetch api, use that - // in some environments, like Electron's render process, Fetch api may be present, but have a different context than expected, let's only use it on the Web - if (!Module['wasmBinary'] && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) && typeof fetch === 'function') { - return fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function(response) { - if (!response['ok']) { - throw "failed to load wasm binary file at '" + wasmBinaryFile + "'"; - } - return response['arrayBuffer'](); - }).catch(function () { - return getBinary(); - }); - } - // Otherwise, getBinary should be able to get it synchronously - return new Promise(function(resolve, reject) { - resolve(getBinary()); + function instantiateArrayBuffer(receiver) { + return getBinaryPromise().then(function(binary) { + return WebAssembly.instantiate(binary, info); + }).then(receiver, function(reason) { + err('failed to asynchronously prepare wasm: ' + reason); + abort(reason); }); } - // do-method functions - - - function doNativeWasm(global, env, providedBuffer) { - if (typeof WebAssembly !== 'object') { - err('no native wasm support detected'); - return false; - } - // prepare memory import - if (!(Module['wasmMemory'] instanceof WebAssembly.Memory)) { - err('no native wasm Memory in use'); - return false; - } - env['memory'] = Module['wasmMemory']; - // Load the wasm module and create an instance of using native support in the JS engine. - info['global'] = { - 'NaN': NaN, - 'Infinity': Infinity - }; - info['global.Math'] = Math; - info['env'] = env; - // handle a generated wasm instance, receiving its exports and - // performing other necessary setup - function receiveInstance(instance, module) { - exports = instance.exports; - if (exports.memory) mergeMemory(exports.memory); - Module['asm'] = exports; - Module["usingWasm"] = true; - removeRunDependency('wasm-instantiate'); - } - addRunDependency('wasm-instantiate'); - - // User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback - // to manually instantiate the Wasm module themselves. This allows pages to run the instantiation parallel - // to any other async startup actions they are performing. - if (Module['instantiateWasm']) { - try { - return Module['instantiateWasm'](info, receiveInstance); - } catch(e) { - err('Module.instantiateWasm callback failed with error: ' + e); - return false; - } - } - - function receiveInstantiatedSource(output) { - // 'output' is a WebAssemblyInstantiatedSource object which has both the module and instance. - // receiveInstance() will swap in the exports (to Module.asm) so they can be called - receiveInstance(output['instance'], output['module']); - } - function instantiateArrayBuffer(receiver) { - getBinaryPromise().then(function(binary) { - return WebAssembly.instantiate(binary, info); - }).then(receiver).catch(function(reason) { - err('failed to asynchronously prepare wasm: ' + reason); - abort(reason); - }); - } - // Prefer streaming instantiation if available. + // Prefer streaming instantiation if available. + function instantiateAsync() { if (!Module['wasmBinary'] && typeof WebAssembly.instantiateStreaming === 'function' && !isDataURI(wasmBinaryFile) && typeof fetch === 'function') { - WebAssembly.instantiateStreaming(fetch(wasmBinaryFile, { credentials: 'same-origin' }), info) - .then(receiveInstantiatedSource) - .catch(function(reason) { - // We expect the most common failure cause to be a bad MIME type for the binary, - // in which case falling back to ArrayBuffer instantiation should work. - err('wasm streaming compile failed: ' + reason); - err('falling back to ArrayBuffer instantiation'); - instantiateArrayBuffer(receiveInstantiatedSource); - }); + fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function (response) { + return WebAssembly.instantiateStreaming(response, info) + .then(receiveInstantiatedSource, function(reason) { + // We expect the most common failure cause to be a bad MIME type for the binary, + // in which case falling back to ArrayBuffer instantiation should work. + err('wasm streaming compile failed: ' + reason); + err('falling back to ArrayBuffer instantiation'); + instantiateArrayBuffer(receiveInstantiatedSource); + }); + }); } else { - instantiateArrayBuffer(receiveInstantiatedSource); + return instantiateArrayBuffer(receiveInstantiatedSource); + } + } + // User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback + // to manually instantiate the Wasm module themselves. This allows pages to run the instantiation parallel + // to any other async startup actions they are performing. + if (Module['instantiateWasm']) { + try { + var exports = Module['instantiateWasm'](info, receiveInstance); + return exports; + } catch(e) { + err('Module.instantiateWasm callback failed with error: ' + e); + return false; } - return {}; // no exports yet; we'll fill them in later } - - // We may have a preloaded value in Module.asm, save it - Module['asmPreload'] = Module['asm']; - - // Memory growth integration code - - var asmjsReallocBuffer = Module['reallocBuffer']; - - var wasmReallocBuffer = function(size) { - var PAGE_MULTIPLE = Module["usingWasm"] ? WASM_PAGE_SIZE : ASMJS_PAGE_SIZE; // In wasm, heap size must be a multiple of 64KB. In asm.js, they need to be multiples of 16MB. - size = alignUp(size, PAGE_MULTIPLE); // round up to wasm page size - var old = Module['buffer']; - var oldSize = old.byteLength; - if (Module["usingWasm"]) { - // native wasm support - try { - var result = Module['wasmMemory'].grow((size - oldSize) / wasmPageSize); // .grow() takes a delta compared to the previous size - if (result !== (-1 | 0)) { - // success in native wasm memory growth, get the buffer from the memory - return Module['buffer'] = Module['wasmMemory'].buffer; - } else { - return null; - } - } catch(e) { - return null; - } - } - }; - - Module['reallocBuffer'] = function(size) { - if (finalMethod === 'asmjs') { - return asmjsReallocBuffer(size); - } else { - return wasmReallocBuffer(size); - } - }; - - // we may try more than one; this is the final one, that worked and we are using - var finalMethod = ''; - - // Provide an "asm.js function" for the application, called to "link" the asm.js module. We instantiate - // the wasm module at that time, and it receives imports and provides exports and so forth, the app - // doesn't need to care that it is wasm or olyfilled wasm or asm.js. - - Module['asm'] = function(global, env, providedBuffer) { - env = fixImports(env); - - // import table - if (!env['table']) { - var TABLE_SIZE = Module['wasmTableSize']; - if (TABLE_SIZE === undefined) TABLE_SIZE = 1024; // works in binaryen interpreter at least - var MAX_TABLE_SIZE = Module['wasmMaxTableSize']; - if (typeof WebAssembly === 'object' && typeof WebAssembly.Table === 'function') { - if (MAX_TABLE_SIZE !== undefined) { - env['table'] = new WebAssembly.Table({ 'initial': TABLE_SIZE, 'maximum': MAX_TABLE_SIZE, 'element': 'anyfunc' }); - } else { - env['table'] = new WebAssembly.Table({ 'initial': TABLE_SIZE, element: 'anyfunc' }); - } - } else { - env['table'] = new Array(TABLE_SIZE); // works in binaryen interpreter at least - } - Module['wasmTable'] = env['table']; - } - - if (!env['memoryBase']) { - env['memoryBase'] = Module['STATIC_BASE']; // tell the memory segments where to place themselves - } - if (!env['tableBase']) { - env['tableBase'] = 0; // table starts at 0 by default, in dynamic linking this will change - } - - // try the methods. each should return the exports if it succeeded - - var exports; - exports = doNativeWasm(global, env, providedBuffer); - - assert(exports, 'no binaryen method succeeded.'); - - - return exports; - }; - - var methodHandler = Module['asm']; // note our method handler, as we may modify Module['asm'] later + instantiateAsync(); + return {}; // no exports yet; we'll fill them in later } -integrateWasmJS(); +// Provide an "asm.js function" for the application, called to "link" the asm.js module. We instantiate +// the wasm module at that time, and it receives imports and provides exports and so forth, the app +// doesn't need to care that it is wasm or asm.js. + +Module['asm'] = function(global, env, providedBuffer) { + // memory was already allocated (so js could use the buffer) + env['memory'] = wasmMemory + ; + // import table + env['table'] = wasmTable = new WebAssembly.Table({ + 'initial': 1116, + 'maximum': 1116, + 'element': 'anyfunc' + }); + // With the wasm backend __memory_base and __table_base and only needed for + // relocatable output. + env['__memory_base'] = 1024; // tell the memory segments where to place themselves + // table starts at 0 by default (even in dynamic linking, for the main module) + env['__table_base'] = 0; + + var exports = createWasm(env); + return exports; +}; + +// Globals used by JS i64 conversions +var tempDouble; +var tempI64; // === Body === @@ -1707,6 +1639,7 @@ function _api_play_sound(id,volume,pan,loop){ self.DApi.play_sound(id, volume, p function _api_set_cursor(x,y){ self.DApi.set_cursor(x, y); } function _api_set_volume(id,volume){ self.DApi.set_volume(id, volume); } function _api_stop_sound(id){ self.DApi.stop_sound(id); } +function _api_use_websocket(use){ self.DApi.use_websocket(use); } function _api_websocket_closed(){ return self.DApi.websocket_closed(); } function _api_websocket_send(ptr,size){ self.DApi.websocket_send(HEAPU8.subarray(ptr, ptr + size)); } function _exit_error(err){ var end = HEAPU8.indexOf( 0, err ); var text = String.fromCharCode.apply(null, HEAPU8.subarray( err, end )); self.DApi.exit_error( text ); } @@ -1720,10 +1653,8 @@ function _trace_push(ptr){ var end = HEAPU8.indexOf(0, ptr); var text = String.f -STATIC_BASE = GLOBAL_BASE; - -STATICTOP = STATIC_BASE + 1866608; -/* global initializers */ __ATINIT__.push({ func: function() { __GLOBAL__sub_I_msgcmd_cpp() } }, { func: function() { __GLOBAL__sub_I_snet_cpp() } }); +// STATICTOP = STATIC_BASE + 1874720; +/* global initializers */ __ATINIT__.push({ func: function() { globalCtors() } }); @@ -1731,50 +1662,33 @@ STATICTOP = STATIC_BASE + 1866608; -var STATIC_BUMP = 1866608; -Module["STATIC_BASE"] = STATIC_BASE; -Module["STATIC_BUMP"] = STATIC_BUMP; /* no memory initializer */ -var tempDoublePtr = STATICTOP; STATICTOP += 16; +var tempDoublePtr = 1875728 function copyTempFloat(ptr) { // functions, because inlining this code increases code size too much - HEAP8[tempDoublePtr] = HEAP8[ptr]; - HEAP8[tempDoublePtr+1] = HEAP8[ptr+1]; - HEAP8[tempDoublePtr+2] = HEAP8[ptr+2]; - HEAP8[tempDoublePtr+3] = HEAP8[ptr+3]; - } function copyTempDouble(ptr) { - HEAP8[tempDoublePtr] = HEAP8[ptr]; - HEAP8[tempDoublePtr+1] = HEAP8[ptr+1]; - HEAP8[tempDoublePtr+2] = HEAP8[ptr+2]; - HEAP8[tempDoublePtr+3] = HEAP8[ptr+3]; - HEAP8[tempDoublePtr+4] = HEAP8[ptr+4]; - HEAP8[tempDoublePtr+5] = HEAP8[ptr+5]; - HEAP8[tempDoublePtr+6] = HEAP8[ptr+6]; - HEAP8[tempDoublePtr+7] = HEAP8[ptr+7]; - } // {{PRE_LIBRARY}} function ___assert_fail(condition, filename, line, func) { - abort('Assertion failed: ' + Pointer_stringify(condition) + ', at: ' + [filename ? Pointer_stringify(filename) : 'unknown filename', line, func ? Pointer_stringify(func) : 'unknown function']); + abort('Assertion failed: ' + UTF8ToString(condition) + ', at: ' + [filename ? UTF8ToString(filename) : 'unknown filename', line, func ? UTF8ToString(func) : 'unknown function']); } function ___cxa_allocate_exception(size) { @@ -1782,79 +1696,127 @@ function copyTempDouble(ptr) { } - function __ZSt18uncaught_exceptionv() { // std::uncaught_exception() - return !!__ZSt18uncaught_exceptionv.uncaught_exception; + var ___exception_infos={}; + + var ___exception_caught= []; + + function ___exception_addRef(ptr) { + if (!ptr) return; + var info = ___exception_infos[ptr]; + info.refcount++; } - var EXCEPTIONS={last:0,caught:[],infos:{},deAdjust:function (adjusted) { - if (!adjusted || EXCEPTIONS.infos[adjusted]) return adjusted; - for (var key in EXCEPTIONS.infos) { - var ptr = +key; // the iteration key is a string, and if we throw this, it must be an integer as that is what we look for - var info = EXCEPTIONS.infos[ptr]; - if (info.adjusted === adjusted) { + function ___exception_deAdjust(adjusted) { + if (!adjusted || ___exception_infos[adjusted]) return adjusted; + for (var key in ___exception_infos) { + var ptr = +key; // the iteration key is a string, and if we throw this, it must be an integer as that is what we look for + var adj = ___exception_infos[ptr].adjusted; + var len = adj.length; + for (var i = 0; i < len; i++) { + if (adj[i] === adjusted) { return ptr; } } - return adjusted; - },addRef:function (ptr) { - if (!ptr) return; - var info = EXCEPTIONS.infos[ptr]; - info.refcount++; - },decRef:function (ptr) { - if (!ptr) return; - var info = EXCEPTIONS.infos[ptr]; - assert(info.refcount > 0); - info.refcount--; - // A rethrown exception can reach refcount 0; it must not be discarded - // Its next handler will clear the rethrown flag and addRef it, prior to - // final decRef and destruction here - if (info.refcount === 0 && !info.rethrown) { - if (info.destructor) { - Module['dynCall_vi'](info.destructor, ptr); - } - delete EXCEPTIONS.infos[ptr]; - ___cxa_free_exception(ptr); - } - },clearRef:function (ptr) { - if (!ptr) return; - var info = EXCEPTIONS.infos[ptr]; - info.refcount = 0; - }};function ___cxa_begin_catch(ptr) { - var info = EXCEPTIONS.infos[ptr]; + } + return adjusted; + }function ___cxa_begin_catch(ptr) { + var info = ___exception_infos[ptr]; if (info && !info.caught) { info.caught = true; - __ZSt18uncaught_exceptionv.uncaught_exception--; + __ZSt18uncaught_exceptionv.uncaught_exceptions--; } if (info) info.rethrown = false; - EXCEPTIONS.caught.push(ptr); - EXCEPTIONS.addRef(EXCEPTIONS.deAdjust(ptr)); + ___exception_caught.push(ptr); + ___exception_addRef(___exception_deAdjust(ptr)); return ptr; } + var ___exception_last=0; + + function ___cxa_free_exception(ptr) { try { return _free(ptr); - } catch(e) { // XXX FIXME + } catch(e) { } - }function ___cxa_end_catch() { + }function ___exception_decRef(ptr) { + if (!ptr) return; + var info = ___exception_infos[ptr]; + info.refcount--; + // A rethrown exception can reach refcount 0; it must not be discarded + // Its next handler will clear the rethrown flag and addRef it, prior to + // final decRef and destruction here + if (info.refcount === 0 && !info.rethrown) { + if (info.destructor) { + Module['dynCall_vi'](info.destructor, ptr); + } + delete ___exception_infos[ptr]; + ___cxa_free_exception(ptr); + } + } + + function ___cxa_end_catch() { // Clear state flag. - Module['setThrew'](0); + _setThrew(0); // Call destructor if one is registered then clear it. - var ptr = EXCEPTIONS.caught.pop(); + var ptr = ___exception_caught.pop(); if (ptr) { - EXCEPTIONS.decRef(EXCEPTIONS.deAdjust(ptr)); - EXCEPTIONS.last = 0; // XXX in decRef? + ___exception_decRef(___exception_deAdjust(ptr)); + ___exception_last = 0; // XXX in decRef? } } - function ___cxa_find_matching_catch_2() { - return ___cxa_find_matching_catch.apply(null, arguments); + + + function ___resumeException(ptr) { + if (!___exception_last) { ___exception_last = ptr; } + throw ptr; + }function ___cxa_find_matching_catch() { + var thrown = ___exception_last; + if (!thrown) { + // just pass through the null ptr + return ((setTempRet0(0),0)|0); + } + var info = ___exception_infos[thrown]; + var throwntype = info.type; + if (!throwntype) { + // just pass through the thrown ptr + return ((setTempRet0(0),thrown)|0); + } + var typeArray = Array.prototype.slice.call(arguments); + + var pointer = ___cxa_is_pointer_type(throwntype); + // can_catch receives a **, add indirection + var buffer = 1875696; + HEAP32[((buffer)>>2)]=thrown; + thrown = buffer; + // The different catch blocks are denoted by different types. + // Due to inheritance, those types may not precisely match the + // type of the thrown object. Find one which matches, and + // return the type of the catch block which should be called. + for (var i = 0; i < typeArray.length; i++) { + if (typeArray[i] && ___cxa_can_catch(typeArray[i], throwntype, thrown)) { + thrown = HEAP32[((thrown)>>2)]; // undo indirection + info.adjusted.push(thrown); + return ((setTempRet0(typeArray[i]),thrown)|0); } + } + // Shouldn't happen unless we have bogus data in typeArray + // or encounter a type for which emscripten doesn't have suitable + // typeinfo defined. Best-efforts match just in case. + thrown = HEAP32[((thrown)>>2)]; // undo indirection + return ((setTempRet0(throwntype),thrown)|0); + } + Module["___cxa_find_matching_catch"] = ___cxa_find_matching_catch;function ___cxa_find_matching_catch_2(a0,a1 + /*``*/) { + return ___cxa_find_matching_catch(a0,a1); + } - function ___cxa_find_matching_catch_3() { - return ___cxa_find_matching_catch.apply(null, arguments); - } + function ___cxa_find_matching_catch_3(a0,a1,a2 + /*``*/) { + return ___cxa_find_matching_catch(a0,a1,a2); + } function ___cxa_get_exception_ptr(ptr) { @@ -1867,65 +1829,29 @@ function copyTempDouble(ptr) { throw 'Pure virtual function called!'; } - - - function ___resumeException(ptr) { - if (!EXCEPTIONS.last) { EXCEPTIONS.last = ptr; } - throw ptr; - }function ___cxa_find_matching_catch() { - var thrown = EXCEPTIONS.last; - if (!thrown) { - // just pass through the null ptr - return ((setTempRet0(0),0)|0); - } - var info = EXCEPTIONS.infos[thrown]; - var throwntype = info.type; - if (!throwntype) { - // just pass through the thrown ptr - return ((setTempRet0(0),thrown)|0); - } - var typeArray = Array.prototype.slice.call(arguments); - - var pointer = Module['___cxa_is_pointer_type'](throwntype); - // can_catch receives a **, add indirection - if (!___cxa_find_matching_catch.buffer) ___cxa_find_matching_catch.buffer = _malloc(4); - HEAP32[((___cxa_find_matching_catch.buffer)>>2)]=thrown; - thrown = ___cxa_find_matching_catch.buffer; - // The different catch blocks are denoted by different types. - // Due to inheritance, those types may not precisely match the - // type of the thrown object. Find one which matches, and - // return the type of the catch block which should be called. - for (var i = 0; i < typeArray.length; i++) { - if (typeArray[i] && Module['___cxa_can_catch'](typeArray[i], throwntype, thrown)) { - thrown = HEAP32[((thrown)>>2)]; // undo indirection - info.adjusted = thrown; - return ((setTempRet0(typeArray[i]),thrown)|0); - } - } - // Shouldn't happen unless we have bogus data in typeArray - // or encounter a type for which emscripten doesn't have suitable - // typeinfo defined. Best-efforts match just in case. - thrown = HEAP32[((thrown)>>2)]; // undo indirection - return ((setTempRet0(throwntype),thrown)|0); - }function ___cxa_throw(ptr, type, destructor) { - EXCEPTIONS.infos[ptr] = { + function ___cxa_throw(ptr, type, destructor) { + ___exception_infos[ptr] = { ptr: ptr, - adjusted: ptr, + adjusted: [ptr], type: type, destructor: destructor, refcount: 0, caught: false, rethrown: false }; - EXCEPTIONS.last = ptr; + ___exception_last = ptr; if (!("uncaught_exception" in __ZSt18uncaught_exceptionv)) { - __ZSt18uncaught_exceptionv.uncaught_exception = 1; + __ZSt18uncaught_exceptionv.uncaught_exceptions = 1; } else { - __ZSt18uncaught_exceptionv.uncaught_exception++; + __ZSt18uncaught_exceptionv.uncaught_exceptions++; } throw ptr; } + function ___cxa_uncaught_exceptions() { + return __ZSt18uncaught_exceptionv.uncaught_exceptions; + } + function ___gxx_personality_v0() { } @@ -1933,29 +1859,96 @@ function copyTempDouble(ptr) { - var SYSCALLS={varargs:0,get:function (varargs) { + + var PATH={splitPath:function (filename) { + var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; + return splitPathRe.exec(filename).slice(1); + },normalizeArray:function (parts, allowAboveRoot) { + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = parts.length - 1; i >= 0; i--) { + var last = parts[i]; + if (last === '.') { + parts.splice(i, 1); + } else if (last === '..') { + parts.splice(i, 1); + up++; + } else if (up) { + parts.splice(i, 1); + up--; + } + } + // if the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up; up--) { + parts.unshift('..'); + } + } + return parts; + },normalize:function (path) { + var isAbsolute = path.charAt(0) === '/', + trailingSlash = path.substr(-1) === '/'; + // Normalize the path + path = PATH.normalizeArray(path.split('/').filter(function(p) { + return !!p; + }), !isAbsolute).join('/'); + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + return (isAbsolute ? '/' : '') + path; + },dirname:function (path) { + var result = PATH.splitPath(path), + root = result[0], + dir = result[1]; + if (!root && !dir) { + // No dirname whatsoever + return '.'; + } + if (dir) { + // It has a dirname, strip trailing slash + dir = dir.substr(0, dir.length - 1); + } + return root + dir; + },basename:function (path) { + // EMSCRIPTEN return '/'' for '/', not an empty string + if (path === '/') return '/'; + var lastSlash = path.lastIndexOf('/'); + if (lastSlash === -1) return path; + return path.substr(lastSlash+1); + },extname:function (path) { + return PATH.splitPath(path)[3]; + },join:function () { + var paths = Array.prototype.slice.call(arguments, 0); + return PATH.normalize(paths.join('/')); + },join2:function (l, r) { + return PATH.normalize(l + '/' + r); + }};var SYSCALLS={buffers:[null,[],[]],printChar:function (stream, curr) { + var buffer = SYSCALLS.buffers[stream]; + if (curr === 0 || curr === 10) { + (stream === 1 ? out : err)(UTF8ArrayToString(buffer, 0)); + buffer.length = 0; + } else { + buffer.push(curr); + } + },varargs:0,get:function (varargs) { SYSCALLS.varargs += 4; var ret = HEAP32[(((SYSCALLS.varargs)-(4))>>2)]; return ret; },getStr:function () { - var ret = Pointer_stringify(SYSCALLS.get()); + var ret = UTF8ToString(SYSCALLS.get()); return ret; },get64:function () { var low = SYSCALLS.get(), high = SYSCALLS.get(); - if (low >= 0) assert(high === 0); - else assert(high === -1); return low; },getZero:function () { - assert(SYSCALLS.get() === 0); + SYSCALLS.get(); }};function ___syscall140(which, varargs) {SYSCALLS.varargs = varargs; try { // llseek var stream = SYSCALLS.getStreamFromFD(), offset_high = SYSCALLS.get(), offset_low = SYSCALLS.get(), result = SYSCALLS.get(), whence = SYSCALLS.get(); - // NOTE: offset_high is unused - Emscripten's off_t is 32-bit - var offset = offset_low; - FS.llseek(stream, offset, whence); - HEAP32[((result)>>2)]=stream.position; - if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null; // reset readdir state return 0; } catch (e) { if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e); @@ -1968,35 +1961,20 @@ function copyTempDouble(ptr) { // flush anything remaining in the buffers during shutdown var fflush = Module["_fflush"]; if (fflush) fflush(0); - var printChar = ___syscall146.printChar; - if (!printChar) return; - var buffers = ___syscall146.buffers; - if (buffers[1].length) printChar(1, 10); - if (buffers[2].length) printChar(2, 10); + var buffers = SYSCALLS.buffers; + if (buffers[1].length) SYSCALLS.printChar(1, 10); + if (buffers[2].length) SYSCALLS.printChar(2, 10); }function ___syscall146(which, varargs) {SYSCALLS.varargs = varargs; try { // writev - // hack to support printf in NO_FILESYSTEM + // hack to support printf in SYSCALLS_REQUIRE_FILESYSTEM=0 var stream = SYSCALLS.get(), iov = SYSCALLS.get(), iovcnt = SYSCALLS.get(); var ret = 0; - if (!___syscall146.buffers) { - ___syscall146.buffers = [null, [], []]; // 1 => stdout, 2 => stderr - ___syscall146.printChar = function(stream, curr) { - var buffer = ___syscall146.buffers[stream]; - assert(buffer); - if (curr === 0 || curr === 10) { - (stream === 1 ? out : err)(UTF8ArrayToString(buffer, 0)); - buffer.length = 0; - } else { - buffer.push(curr); - } - }; - } for (var i = 0; i < iovcnt; i++) { var ptr = HEAP32[(((iov)+(i*8))>>2)]; var len = HEAP32[(((iov)+(i*8 + 4))>>2)]; for (var j = 0; j < len; j++) { - ___syscall146.printChar(stream, HEAPU8[ptr+j]); + SYSCALLS.printChar(stream, HEAPU8[ptr+j]); } ret += len; } @@ -2021,7 +1999,6 @@ function copyTempDouble(ptr) { try { // close var stream = SYSCALLS.getStreamFromFD(); - FS.close(stream); return 0; } catch (e) { if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e); @@ -2037,21 +2014,18 @@ function copyTempDouble(ptr) { var _emscripten_asm_const_int=true; - - function __exit(status) { + function _emscripten_get_heap_size() { + return HEAP8.length; + } + + function _exit(status) { // void _exit(int status); // http://pubs.opengroup.org/onlinepubs/000095399/functions/exit.html exit(status); - }function _exit(status) { - __exit(status); } - var _llvm_ceil_f32=Math_ceil; - - var _llvm_ctlz_i32=true; - function _llvm_eh_typeid_for(type) { return type; } @@ -2063,51 +2037,85 @@ function copyTempDouble(ptr) { function _emscripten_memcpy_big(dest, src, num) { HEAPU8.set(HEAPU8.subarray(src, src+num), dest); - return dest; - } - + } + - - var PTHREAD_SPECIFIC={};function _pthread_getspecific(key) { - return PTHREAD_SPECIFIC[key] || 0; - } - - - var PTHREAD_SPECIFIC_NEXT_KEY=1; - - var ERRNO_CODES={EPERM:1,ENOENT:2,ESRCH:3,EINTR:4,EIO:5,ENXIO:6,E2BIG:7,ENOEXEC:8,EBADF:9,ECHILD:10,EAGAIN:11,EWOULDBLOCK:11,ENOMEM:12,EACCES:13,EFAULT:14,ENOTBLK:15,EBUSY:16,EEXIST:17,EXDEV:18,ENODEV:19,ENOTDIR:20,EISDIR:21,EINVAL:22,ENFILE:23,EMFILE:24,ENOTTY:25,ETXTBSY:26,EFBIG:27,ENOSPC:28,ESPIPE:29,EROFS:30,EMLINK:31,EPIPE:32,EDOM:33,ERANGE:34,ENOMSG:42,EIDRM:43,ECHRNG:44,EL2NSYNC:45,EL3HLT:46,EL3RST:47,ELNRNG:48,EUNATCH:49,ENOCSI:50,EL2HLT:51,EDEADLK:35,ENOLCK:37,EBADE:52,EBADR:53,EXFULL:54,ENOANO:55,EBADRQC:56,EBADSLT:57,EDEADLOCK:35,EBFONT:59,ENOSTR:60,ENODATA:61,ETIME:62,ENOSR:63,ENONET:64,ENOPKG:65,EREMOTE:66,ENOLINK:67,EADV:68,ESRMNT:69,ECOMM:70,EPROTO:71,EMULTIHOP:72,EDOTDOT:73,EBADMSG:74,ENOTUNIQ:76,EBADFD:77,EREMCHG:78,ELIBACC:79,ELIBBAD:80,ELIBSCN:81,ELIBMAX:82,ELIBEXEC:83,ENOSYS:38,ENOTEMPTY:39,ENAMETOOLONG:36,ELOOP:40,EOPNOTSUPP:95,EPFNOSUPPORT:96,ECONNRESET:104,ENOBUFS:105,EAFNOSUPPORT:97,EPROTOTYPE:91,ENOTSOCK:88,ENOPROTOOPT:92,ESHUTDOWN:108,ECONNREFUSED:111,EADDRINUSE:98,ECONNABORTED:103,ENETUNREACH:101,ENETDOWN:100,ETIMEDOUT:110,EHOSTDOWN:112,EHOSTUNREACH:113,EINPROGRESS:115,EALREADY:114,EDESTADDRREQ:89,EMSGSIZE:90,EPROTONOSUPPORT:93,ESOCKTNOSUPPORT:94,EADDRNOTAVAIL:99,ENETRESET:102,EISCONN:106,ENOTCONN:107,ETOOMANYREFS:109,EUSERS:87,EDQUOT:122,ESTALE:116,ENOTSUP:95,ENOMEDIUM:123,EILSEQ:84,EOVERFLOW:75,ECANCELED:125,ENOTRECOVERABLE:131,EOWNERDEAD:130,ESTRPIPE:86};function _pthread_key_create(key, destructor) { - if (key == 0) { - return ERRNO_CODES.EINVAL; - } - HEAP32[((key)>>2)]=PTHREAD_SPECIFIC_NEXT_KEY; - // values start at 0 - PTHREAD_SPECIFIC[PTHREAD_SPECIFIC_NEXT_KEY] = 0; - PTHREAD_SPECIFIC_NEXT_KEY++; - return 0; - } - - function _pthread_once(ptr, func) { - if (!_pthread_once.seen) _pthread_once.seen = {}; - if (ptr in _pthread_once.seen) return; - Module['dynCall_v'](func); - _pthread_once.seen[ptr] = 1; - } - - function _pthread_setspecific(key, value) { - if (!(key in PTHREAD_SPECIFIC)) { - return ERRNO_CODES.EINVAL; - } - PTHREAD_SPECIFIC[key] = value; - return 0; - } + function ___setErrNo(value) { if (Module['___errno_location']) HEAP32[((Module['___errno_location']())>>2)]=value; return value; + } + + + function abortOnCannotGrowMemory(requestedSize) { + abort('OOM'); + } + + function emscripten_realloc_buffer(size) { + var PAGE_MULTIPLE = 65536; + size = alignUp(size, PAGE_MULTIPLE); // round up to wasm page size + var oldSize = buffer.byteLength; + // native wasm support + // note that this is *not* threadsafe. multiple threads can call .grow(), and each + // presents a delta, so in theory we may over-allocate here (e.g. if two threads + // ask to grow from 256MB to 512MB, we get 2 requests to add +256MB, and may end + // up growing to 768MB (even though we may have been able to make do with 512MB). + // TODO: consider decreasing the step sizes in emscripten_resize_heap + try { + var result = wasmMemory.grow((size - oldSize) / 65536); // .grow() takes a delta compared to the previous size + if (result !== (-1 | 0)) { + // success in native wasm memory growth, get the buffer from the memory + buffer = wasmMemory.buffer; + return true; + } else { + return false; + } + } catch(e) { + return false; + } + }function _emscripten_resize_heap(requestedSize) { + var oldSize = _emscripten_get_heap_size(); + // With pthreads, races can happen (another thread might increase the size in between), so return a failure, and let the caller retry. + + + var PAGE_MULTIPLE = 65536; + var LIMIT = 2147483648 - PAGE_MULTIPLE; // We can do one page short of 2GB as theoretical maximum. + + if (requestedSize > LIMIT) { + return false; + } + + var MIN_TOTAL_MEMORY = 16777216; + var newSize = Math.max(oldSize, MIN_TOTAL_MEMORY); // So the loop below will not be infinite, and minimum asm.js memory size is 16MB. + + // TODO: see realloc_buffer - for PTHREADS we may want to decrease these jumps + while (newSize < requestedSize) { // Keep incrementing the heap size as long as it's less than what is requested. + if (newSize <= 536870912) { + newSize = alignUp(2 * newSize, PAGE_MULTIPLE); // Simple heuristic: double until 1GB... + } else { + // ..., but after that, add smaller increments towards 2GB, which we cannot reach + newSize = Math.min(alignUp((3 * newSize + 2147483648) / 4, PAGE_MULTIPLE), LIMIT); + } + + } + + + + + if (!emscripten_realloc_buffer(newSize)) { + return false; + } + + updateGlobalBufferViews(); + + + + return true; } function _time(ptr) { @@ -2117,20 +2125,13 @@ function copyTempDouble(ptr) { } return ret; } -DYNAMICTOP_PTR = staticAlloc(4); - -STACK_BASE = STACKTOP = alignMemory(STATICTOP); - -STACK_MAX = STACK_BASE + TOTAL_STACK; - -DYNAMIC_BASE = alignMemory(STACK_MAX); - -HEAP32[DYNAMICTOP_PTR>>2] = DYNAMIC_BASE; - -staticSealed = true; // seal the static portion of memory - var ASSERTIONS = false; +// Copyright 2017 The Emscripten Authors. All rights reserved. +// Emscripten is available under two separate licenses, the MIT license and the +// University of Illinois/NCSA Open Source License. Both these licenses can be +// found in the LICENSE file. + /** @type {function(string, boolean=, number=)} */ function intArrayFromString(stringy, dontAddNull, length) { var len = length > 0 ? length : lengthBytesUTF8(stringy)+1; @@ -2156,303 +2157,582 @@ function intArrayToString(array) { } +// ASM_LIBRARY EXTERN PRIMITIVES: Int8Array,Int32Array -Module['wasmTableSize'] = 1114; - -Module['wasmMaxTableSize'] = 1114; function invoke_i(index) { var sp = stackSave(); try { - return Module["dynCall_i"](index); + return dynCall_i(index); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_ii(index,a1) { var sp = stackSave(); try { - return Module["dynCall_ii"](index,a1); + return dynCall_ii(index,a1); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_iii(index,a1,a2) { var sp = stackSave(); try { - return Module["dynCall_iii"](index,a1,a2); + return dynCall_iii(index,a1,a2); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_iiii(index,a1,a2,a3) { var sp = stackSave(); try { - return Module["dynCall_iiii"](index,a1,a2,a3); + return dynCall_iiii(index,a1,a2,a3); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_iiiii(index,a1,a2,a3,a4) { var sp = stackSave(); try { - return Module["dynCall_iiiii"](index,a1,a2,a3,a4); + return dynCall_iiiii(index,a1,a2,a3,a4); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_iiiiii(index,a1,a2,a3,a4,a5) { var sp = stackSave(); try { - return Module["dynCall_iiiiii"](index,a1,a2,a3,a4,a5); + return dynCall_iiiiii(index,a1,a2,a3,a4,a5); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_ji(index,a1) { var sp = stackSave(); try { - return Module["dynCall_ji"](index,a1); + return dynCall_ji(index,a1); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_v(index) { var sp = stackSave(); try { - Module["dynCall_v"](index); + dynCall_v(index); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_vi(index,a1) { var sp = stackSave(); try { - Module["dynCall_vi"](index,a1); + dynCall_vi(index,a1); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_vii(index,a1,a2) { var sp = stackSave(); try { - Module["dynCall_vii"](index,a1,a2); + dynCall_vii(index,a1,a2); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_viii(index,a1,a2,a3) { var sp = stackSave(); try { - Module["dynCall_viii"](index,a1,a2,a3); + dynCall_viii(index,a1,a2,a3); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_viiii(index,a1,a2,a3,a4) { var sp = stackSave(); try { - Module["dynCall_viiii"](index,a1,a2,a3,a4); + dynCall_viiii(index,a1,a2,a3,a4); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_viiiii(index,a1,a2,a3,a4,a5) { var sp = stackSave(); try { - Module["dynCall_viiiii"](index,a1,a2,a3,a4,a5); + dynCall_viiiii(index,a1,a2,a3,a4,a5); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); - } -} - -function invoke_viiiiii(index,a1,a2,a3,a4,a5,a6) { - var sp = stackSave(); - try { - Module["dynCall_viiiiii"](index,a1,a2,a3,a4,a5,a6); - } catch(e) { - stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7) { var sp = stackSave(); try { - Module["dynCall_viiiiiii"](index,a1,a2,a3,a4,a5,a6,a7); + dynCall_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); - } -} - -function invoke_viiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9) { - var sp = stackSave(); - try { - Module["dynCall_viiiiiiiii"](index,a1,a2,a3,a4,a5,a6,a7,a8,a9); - } catch(e) { - stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); - } -} - -function invoke_viiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) { - var sp = stackSave(); - try { - Module["dynCall_viiiiiiiiii"](index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10); - } catch(e) { - stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_viij(index,a1,a2,a3,a4) { var sp = stackSave(); try { - Module["dynCall_viij"](index,a1,a2,a3,a4); + dynCall_viij(index,a1,a2,a3,a4); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_viji(index,a1,a2,a3,a4) { var sp = stackSave(); try { - Module["dynCall_viji"](index,a1,a2,a3,a4); + dynCall_viji(index,a1,a2,a3,a4); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } -Module.asmGlobalArg = {}; +var asmGlobalArg = {}; -Module.asmLibraryArg = { "abort": abort, "assert": assert, "enlargeMemory": enlargeMemory, "getTotalMemory": getTotalMemory, "abortOnCannotGrowMemory": abortOnCannotGrowMemory, "invoke_i": invoke_i, "invoke_ii": invoke_ii, "invoke_iii": invoke_iii, "invoke_iiii": invoke_iiii, "invoke_iiiii": invoke_iiiii, "invoke_iiiiii": invoke_iiiiii, "invoke_ji": invoke_ji, "invoke_v": invoke_v, "invoke_vi": invoke_vi, "invoke_vii": invoke_vii, "invoke_viii": invoke_viii, "invoke_viiii": invoke_viiii, "invoke_viiiii": invoke_viiiii, "invoke_viiiiii": invoke_viiiiii, "invoke_viiiiiii": invoke_viiiiiii, "invoke_viiiiiiiii": invoke_viiiiiiiii, "invoke_viiiiiiiiii": invoke_viiiiiiiiii, "invoke_viij": invoke_viij, "invoke_viji": invoke_viji, "__ZSt18uncaught_exceptionv": __ZSt18uncaught_exceptionv, "___assert_fail": ___assert_fail, "___cxa_allocate_exception": ___cxa_allocate_exception, "___cxa_begin_catch": ___cxa_begin_catch, "___cxa_end_catch": ___cxa_end_catch, "___cxa_find_matching_catch": ___cxa_find_matching_catch, "___cxa_find_matching_catch_2": ___cxa_find_matching_catch_2, "___cxa_find_matching_catch_3": ___cxa_find_matching_catch_3, "___cxa_free_exception": ___cxa_free_exception, "___cxa_get_exception_ptr": ___cxa_get_exception_ptr, "___cxa_pure_virtual": ___cxa_pure_virtual, "___cxa_throw": ___cxa_throw, "___gxx_personality_v0": ___gxx_personality_v0, "___lock": ___lock, "___resumeException": ___resumeException, "___setErrNo": ___setErrNo, "___syscall140": ___syscall140, "___syscall146": ___syscall146, "___syscall54": ___syscall54, "___syscall6": ___syscall6, "___unlock": ___unlock, "__api_close_keyboard": __api_close_keyboard, "__api_open_keyboard": __api_open_keyboard, "__exit": __exit, "_abort": _abort, "_api_create_sound": _api_create_sound, "_api_create_sound_float": _api_create_sound_float, "_api_delete_sound": _api_delete_sound, "_api_draw_begin": _api_draw_begin, "_api_draw_belt": _api_draw_belt, "_api_draw_blit": _api_draw_blit, "_api_draw_clip_text": _api_draw_clip_text, "_api_draw_end": _api_draw_end, "_api_draw_text": _api_draw_text, "_api_duplicate_sound": _api_duplicate_sound, "_api_exit_game": _api_exit_game, "_api_play_sound": _api_play_sound, "_api_set_cursor": _api_set_cursor, "_api_set_volume": _api_set_volume, "_api_stop_sound": _api_stop_sound, "_api_websocket_closed": _api_websocket_closed, "_api_websocket_send": _api_websocket_send, "_emscripten_asm_const_ii": _emscripten_asm_const_ii, "_emscripten_memcpy_big": _emscripten_memcpy_big, "_exit": _exit, "_exit_error": _exit_error, "_get_file_contents": _get_file_contents, "_get_file_size": _get_file_size, "_llvm_ceil_f32": _llvm_ceil_f32, "_llvm_eh_typeid_for": _llvm_eh_typeid_for, "_llvm_trap": _llvm_trap, "_pthread_getspecific": _pthread_getspecific, "_pthread_key_create": _pthread_key_create, "_pthread_once": _pthread_once, "_pthread_setspecific": _pthread_setspecific, "_put_file_contents": _put_file_contents, "_remove_file": _remove_file, "_show_alert": _show_alert, "_time": _time, "_trace_pop": _trace_pop, "_trace_push": _trace_push, "flush_NO_FILESYSTEM": flush_NO_FILESYSTEM, "DYNAMICTOP_PTR": DYNAMICTOP_PTR, "tempDoublePtr": tempDoublePtr, "ABORT": ABORT, "STACKTOP": STACKTOP, "STACK_MAX": STACK_MAX }; +var asmLibraryArg = { + "abort": abort, + "setTempRet0": setTempRet0, + "getTempRet0": getTempRet0, + "invoke_i": invoke_i, + "invoke_ii": invoke_ii, + "invoke_iii": invoke_iii, + "invoke_iiii": invoke_iiii, + "invoke_iiiii": invoke_iiiii, + "invoke_iiiiii": invoke_iiiiii, + "invoke_ji": invoke_ji, + "invoke_v": invoke_v, + "invoke_vi": invoke_vi, + "invoke_vii": invoke_vii, + "invoke_viii": invoke_viii, + "invoke_viiii": invoke_viiii, + "invoke_viiiii": invoke_viiiii, + "invoke_viiiiiii": invoke_viiiiiii, + "invoke_viij": invoke_viij, + "invoke_viji": invoke_viji, + "___assert_fail": ___assert_fail, + "___cxa_allocate_exception": ___cxa_allocate_exception, + "___cxa_begin_catch": ___cxa_begin_catch, + "___cxa_end_catch": ___cxa_end_catch, + "___cxa_find_matching_catch": ___cxa_find_matching_catch, + "___cxa_find_matching_catch_2": ___cxa_find_matching_catch_2, + "___cxa_find_matching_catch_3": ___cxa_find_matching_catch_3, + "___cxa_free_exception": ___cxa_free_exception, + "___cxa_get_exception_ptr": ___cxa_get_exception_ptr, + "___cxa_pure_virtual": ___cxa_pure_virtual, + "___cxa_throw": ___cxa_throw, + "___cxa_uncaught_exceptions": ___cxa_uncaught_exceptions, + "___exception_addRef": ___exception_addRef, + "___exception_deAdjust": ___exception_deAdjust, + "___exception_decRef": ___exception_decRef, + "___gxx_personality_v0": ___gxx_personality_v0, + "___lock": ___lock, + "___resumeException": ___resumeException, + "___setErrNo": ___setErrNo, + "___syscall140": ___syscall140, + "___syscall146": ___syscall146, + "___syscall54": ___syscall54, + "___syscall6": ___syscall6, + "___unlock": ___unlock, + "__api_close_keyboard": __api_close_keyboard, + "__api_open_keyboard": __api_open_keyboard, + "_abort": _abort, + "_api_create_sound": _api_create_sound, + "_api_create_sound_float": _api_create_sound_float, + "_api_delete_sound": _api_delete_sound, + "_api_draw_begin": _api_draw_begin, + "_api_draw_belt": _api_draw_belt, + "_api_draw_blit": _api_draw_blit, + "_api_draw_clip_text": _api_draw_clip_text, + "_api_draw_end": _api_draw_end, + "_api_draw_text": _api_draw_text, + "_api_duplicate_sound": _api_duplicate_sound, + "_api_exit_game": _api_exit_game, + "_api_play_sound": _api_play_sound, + "_api_set_cursor": _api_set_cursor, + "_api_set_volume": _api_set_volume, + "_api_stop_sound": _api_stop_sound, + "_api_use_websocket": _api_use_websocket, + "_api_websocket_closed": _api_websocket_closed, + "_api_websocket_send": _api_websocket_send, + "_emscripten_asm_const_ii": _emscripten_asm_const_ii, + "_emscripten_get_heap_size": _emscripten_get_heap_size, + "_emscripten_memcpy_big": _emscripten_memcpy_big, + "_emscripten_resize_heap": _emscripten_resize_heap, + "_exit": _exit, + "_exit_error": _exit_error, + "_get_file_contents": _get_file_contents, + "_get_file_size": _get_file_size, + "_llvm_eh_typeid_for": _llvm_eh_typeid_for, + "_llvm_trap": _llvm_trap, + "_put_file_contents": _put_file_contents, + "_remove_file": _remove_file, + "_show_alert": _show_alert, + "_time": _time, + "_trace_pop": _trace_pop, + "_trace_push": _trace_push, + "abortOnCannotGrowMemory": abortOnCannotGrowMemory, + "emscripten_realloc_buffer": emscripten_realloc_buffer, + "flush_NO_FILESYSTEM": flush_NO_FILESYSTEM, + "tempDoublePtr": tempDoublePtr, + "DYNAMICTOP_PTR": DYNAMICTOP_PTR +}; // EMSCRIPTEN_START_ASM var asm =Module["asm"]// EMSCRIPTEN_END_ASM -(Module.asmGlobalArg, Module.asmLibraryArg, buffer); +(asmGlobalArg, asmLibraryArg, buffer); Module["asm"] = asm; -var _DApi_AllocPacket = Module["_DApi_AllocPacket"] = function() { return Module["asm"]["_DApi_AllocPacket"].apply(null, arguments) }; -var _DApi_Char = Module["_DApi_Char"] = function() { return Module["asm"]["_DApi_Char"].apply(null, arguments) }; -var _DApi_Init = Module["_DApi_Init"] = function() { return Module["asm"]["_DApi_Init"].apply(null, arguments) }; -var _DApi_Key = Module["_DApi_Key"] = function() { return Module["asm"]["_DApi_Key"].apply(null, arguments) }; -var _DApi_Mouse = Module["_DApi_Mouse"] = function() { return Module["asm"]["_DApi_Mouse"].apply(null, arguments) }; -var _DApi_Render = Module["_DApi_Render"] = function() { return Module["asm"]["_DApi_Render"].apply(null, arguments) }; -var _DApi_SyncText = Module["_DApi_SyncText"] = function() { return Module["asm"]["_DApi_SyncText"].apply(null, arguments) }; -var _DApi_SyncTextPtr = Module["_DApi_SyncTextPtr"] = function() { return Module["asm"]["_DApi_SyncTextPtr"].apply(null, arguments) }; -var _SNet_InitWebsocket = Module["_SNet_InitWebsocket"] = function() { return Module["asm"]["_SNet_InitWebsocket"].apply(null, arguments) }; -var __GLOBAL__sub_I_msgcmd_cpp = Module["__GLOBAL__sub_I_msgcmd_cpp"] = function() { return Module["asm"]["__GLOBAL__sub_I_msgcmd_cpp"].apply(null, arguments) }; -var __GLOBAL__sub_I_snet_cpp = Module["__GLOBAL__sub_I_snet_cpp"] = function() { return Module["asm"]["__GLOBAL__sub_I_snet_cpp"].apply(null, arguments) }; -var ___cxa_can_catch = Module["___cxa_can_catch"] = function() { return Module["asm"]["___cxa_can_catch"].apply(null, arguments) }; -var ___cxa_is_pointer_type = Module["___cxa_is_pointer_type"] = function() { return Module["asm"]["___cxa_is_pointer_type"].apply(null, arguments) }; -var ___em_js___api_close_keyboard = Module["___em_js___api_close_keyboard"] = function() { return Module["asm"]["___em_js___api_close_keyboard"].apply(null, arguments) }; -var ___em_js___api_open_keyboard = Module["___em_js___api_open_keyboard"] = function() { return Module["asm"]["___em_js___api_open_keyboard"].apply(null, arguments) }; -var ___em_js__api_create_sound = Module["___em_js__api_create_sound"] = function() { return Module["asm"]["___em_js__api_create_sound"].apply(null, arguments) }; -var ___em_js__api_create_sound_float = Module["___em_js__api_create_sound_float"] = function() { return Module["asm"]["___em_js__api_create_sound_float"].apply(null, arguments) }; -var ___em_js__api_delete_sound = Module["___em_js__api_delete_sound"] = function() { return Module["asm"]["___em_js__api_delete_sound"].apply(null, arguments) }; -var ___em_js__api_draw_begin = Module["___em_js__api_draw_begin"] = function() { return Module["asm"]["___em_js__api_draw_begin"].apply(null, arguments) }; -var ___em_js__api_draw_belt = Module["___em_js__api_draw_belt"] = function() { return Module["asm"]["___em_js__api_draw_belt"].apply(null, arguments) }; -var ___em_js__api_draw_blit = Module["___em_js__api_draw_blit"] = function() { return Module["asm"]["___em_js__api_draw_blit"].apply(null, arguments) }; -var ___em_js__api_draw_clip_text = Module["___em_js__api_draw_clip_text"] = function() { return Module["asm"]["___em_js__api_draw_clip_text"].apply(null, arguments) }; -var ___em_js__api_draw_end = Module["___em_js__api_draw_end"] = function() { return Module["asm"]["___em_js__api_draw_end"].apply(null, arguments) }; -var ___em_js__api_draw_text = Module["___em_js__api_draw_text"] = function() { return Module["asm"]["___em_js__api_draw_text"].apply(null, arguments) }; -var ___em_js__api_duplicate_sound = Module["___em_js__api_duplicate_sound"] = function() { return Module["asm"]["___em_js__api_duplicate_sound"].apply(null, arguments) }; -var ___em_js__api_exit_game = Module["___em_js__api_exit_game"] = function() { return Module["asm"]["___em_js__api_exit_game"].apply(null, arguments) }; -var ___em_js__api_play_sound = Module["___em_js__api_play_sound"] = function() { return Module["asm"]["___em_js__api_play_sound"].apply(null, arguments) }; -var ___em_js__api_set_cursor = Module["___em_js__api_set_cursor"] = function() { return Module["asm"]["___em_js__api_set_cursor"].apply(null, arguments) }; -var ___em_js__api_set_volume = Module["___em_js__api_set_volume"] = function() { return Module["asm"]["___em_js__api_set_volume"].apply(null, arguments) }; -var ___em_js__api_stop_sound = Module["___em_js__api_stop_sound"] = function() { return Module["asm"]["___em_js__api_stop_sound"].apply(null, arguments) }; -var ___em_js__api_websocket_closed = Module["___em_js__api_websocket_closed"] = function() { return Module["asm"]["___em_js__api_websocket_closed"].apply(null, arguments) }; -var ___em_js__api_websocket_send = Module["___em_js__api_websocket_send"] = function() { return Module["asm"]["___em_js__api_websocket_send"].apply(null, arguments) }; -var ___em_js__exit_error = Module["___em_js__exit_error"] = function() { return Module["asm"]["___em_js__exit_error"].apply(null, arguments) }; -var ___em_js__get_file_contents = Module["___em_js__get_file_contents"] = function() { return Module["asm"]["___em_js__get_file_contents"].apply(null, arguments) }; -var ___em_js__get_file_size = Module["___em_js__get_file_size"] = function() { return Module["asm"]["___em_js__get_file_size"].apply(null, arguments) }; -var ___em_js__put_file_contents = Module["___em_js__put_file_contents"] = function() { return Module["asm"]["___em_js__put_file_contents"].apply(null, arguments) }; -var ___em_js__remove_file = Module["___em_js__remove_file"] = function() { return Module["asm"]["___em_js__remove_file"].apply(null, arguments) }; -var ___em_js__show_alert = Module["___em_js__show_alert"] = function() { return Module["asm"]["___em_js__show_alert"].apply(null, arguments) }; -var ___em_js__trace_pop = Module["___em_js__trace_pop"] = function() { return Module["asm"]["___em_js__trace_pop"].apply(null, arguments) }; -var ___em_js__trace_push = Module["___em_js__trace_push"] = function() { return Module["asm"]["___em_js__trace_push"].apply(null, arguments) }; -var _emscripten_replace_memory = Module["_emscripten_replace_memory"] = function() { return Module["asm"]["_emscripten_replace_memory"].apply(null, arguments) }; -var _free = Module["_free"] = function() { return Module["asm"]["_free"].apply(null, arguments) }; -var _llvm_bswap_i32 = Module["_llvm_bswap_i32"] = function() { return Module["asm"]["_llvm_bswap_i32"].apply(null, arguments) }; -var _malloc = Module["_malloc"] = function() { return Module["asm"]["_malloc"].apply(null, arguments) }; -var _memcpy = Module["_memcpy"] = function() { return Module["asm"]["_memcpy"].apply(null, arguments) }; -var _memmove = Module["_memmove"] = function() { return Module["asm"]["_memmove"].apply(null, arguments) }; -var _memset = Module["_memset"] = function() { return Module["asm"]["_memset"].apply(null, arguments) }; -var _sbrk = Module["_sbrk"] = function() { return Module["asm"]["_sbrk"].apply(null, arguments) }; -var establishStackSpace = Module["establishStackSpace"] = function() { return Module["asm"]["establishStackSpace"].apply(null, arguments) }; -var getTempRet0 = Module["getTempRet0"] = function() { return Module["asm"]["getTempRet0"].apply(null, arguments) }; -var runPostSets = Module["runPostSets"] = function() { return Module["asm"]["runPostSets"].apply(null, arguments) }; -var setTempRet0 = Module["setTempRet0"] = function() { return Module["asm"]["setTempRet0"].apply(null, arguments) }; -var setThrew = Module["setThrew"] = function() { return Module["asm"]["setThrew"].apply(null, arguments) }; -var stackAlloc = Module["stackAlloc"] = function() { return Module["asm"]["stackAlloc"].apply(null, arguments) }; -var stackRestore = Module["stackRestore"] = function() { return Module["asm"]["stackRestore"].apply(null, arguments) }; -var stackSave = Module["stackSave"] = function() { return Module["asm"]["stackSave"].apply(null, arguments) }; -var dynCall_i = Module["dynCall_i"] = function() { return Module["asm"]["dynCall_i"].apply(null, arguments) }; -var dynCall_ii = Module["dynCall_ii"] = function() { return Module["asm"]["dynCall_ii"].apply(null, arguments) }; -var dynCall_iii = Module["dynCall_iii"] = function() { return Module["asm"]["dynCall_iii"].apply(null, arguments) }; -var dynCall_iiii = Module["dynCall_iiii"] = function() { return Module["asm"]["dynCall_iiii"].apply(null, arguments) }; -var dynCall_iiiii = Module["dynCall_iiiii"] = function() { return Module["asm"]["dynCall_iiiii"].apply(null, arguments) }; -var dynCall_iiiiii = Module["dynCall_iiiiii"] = function() { return Module["asm"]["dynCall_iiiiii"].apply(null, arguments) }; -var dynCall_ji = Module["dynCall_ji"] = function() { return Module["asm"]["dynCall_ji"].apply(null, arguments) }; -var dynCall_v = Module["dynCall_v"] = function() { return Module["asm"]["dynCall_v"].apply(null, arguments) }; -var dynCall_vi = Module["dynCall_vi"] = function() { return Module["asm"]["dynCall_vi"].apply(null, arguments) }; -var dynCall_vii = Module["dynCall_vii"] = function() { return Module["asm"]["dynCall_vii"].apply(null, arguments) }; -var dynCall_viii = Module["dynCall_viii"] = function() { return Module["asm"]["dynCall_viii"].apply(null, arguments) }; -var dynCall_viiii = Module["dynCall_viiii"] = function() { return Module["asm"]["dynCall_viiii"].apply(null, arguments) }; -var dynCall_viiiii = Module["dynCall_viiiii"] = function() { return Module["asm"]["dynCall_viiiii"].apply(null, arguments) }; -var dynCall_viiiiii = Module["dynCall_viiiiii"] = function() { return Module["asm"]["dynCall_viiiiii"].apply(null, arguments) }; -var dynCall_viiiiiii = Module["dynCall_viiiiiii"] = function() { return Module["asm"]["dynCall_viiiiiii"].apply(null, arguments) }; -var dynCall_viiiiiiiii = Module["dynCall_viiiiiiiii"] = function() { return Module["asm"]["dynCall_viiiiiiiii"].apply(null, arguments) }; -var dynCall_viiiiiiiiii = Module["dynCall_viiiiiiiiii"] = function() { return Module["asm"]["dynCall_viiiiiiiiii"].apply(null, arguments) }; -var dynCall_viij = Module["dynCall_viij"] = function() { return Module["asm"]["dynCall_viij"].apply(null, arguments) }; -var dynCall_viji = Module["dynCall_viji"] = function() { return Module["asm"]["dynCall_viji"].apply(null, arguments) }; +var _DApi_AllocPacket = Module["_DApi_AllocPacket"] = function() { + return Module["asm"]["_DApi_AllocPacket"].apply(null, arguments) +}; + +var _DApi_Char = Module["_DApi_Char"] = function() { + return Module["asm"]["_DApi_Char"].apply(null, arguments) +}; + +var _DApi_Init = Module["_DApi_Init"] = function() { + return Module["asm"]["_DApi_Init"].apply(null, arguments) +}; + +var _DApi_Key = Module["_DApi_Key"] = function() { + return Module["asm"]["_DApi_Key"].apply(null, arguments) +}; + +var _DApi_Mouse = Module["_DApi_Mouse"] = function() { + return Module["asm"]["_DApi_Mouse"].apply(null, arguments) +}; + +var _DApi_Render = Module["_DApi_Render"] = function() { + return Module["asm"]["_DApi_Render"].apply(null, arguments) +}; + +var _DApi_SyncText = Module["_DApi_SyncText"] = function() { + return Module["asm"]["_DApi_SyncText"].apply(null, arguments) +}; + +var _DApi_SyncTextPtr = Module["_DApi_SyncTextPtr"] = function() { + return Module["asm"]["_DApi_SyncTextPtr"].apply(null, arguments) +}; + +var _SNet_InitWebsocket = Module["_SNet_InitWebsocket"] = function() { + return Module["asm"]["_SNet_InitWebsocket"].apply(null, arguments) +}; + +var _SNet_WebsocketStatus = Module["_SNet_WebsocketStatus"] = function() { + return Module["asm"]["_SNet_WebsocketStatus"].apply(null, arguments) +}; + +var __ZSt18uncaught_exceptionv = Module["__ZSt18uncaught_exceptionv"] = function() { + return Module["asm"]["__ZSt18uncaught_exceptionv"].apply(null, arguments) +}; + +var ___cxa_can_catch = Module["___cxa_can_catch"] = function() { + return Module["asm"]["___cxa_can_catch"].apply(null, arguments) +}; + +var ___cxa_is_pointer_type = Module["___cxa_is_pointer_type"] = function() { + return Module["asm"]["___cxa_is_pointer_type"].apply(null, arguments) +}; + +var ___em_js___api_close_keyboard = Module["___em_js___api_close_keyboard"] = function() { + return Module["asm"]["___em_js___api_close_keyboard"].apply(null, arguments) +}; + +var ___em_js___api_open_keyboard = Module["___em_js___api_open_keyboard"] = function() { + return Module["asm"]["___em_js___api_open_keyboard"].apply(null, arguments) +}; + +var ___em_js__api_create_sound = Module["___em_js__api_create_sound"] = function() { + return Module["asm"]["___em_js__api_create_sound"].apply(null, arguments) +}; + +var ___em_js__api_create_sound_float = Module["___em_js__api_create_sound_float"] = function() { + return Module["asm"]["___em_js__api_create_sound_float"].apply(null, arguments) +}; + +var ___em_js__api_delete_sound = Module["___em_js__api_delete_sound"] = function() { + return Module["asm"]["___em_js__api_delete_sound"].apply(null, arguments) +}; + +var ___em_js__api_draw_begin = Module["___em_js__api_draw_begin"] = function() { + return Module["asm"]["___em_js__api_draw_begin"].apply(null, arguments) +}; + +var ___em_js__api_draw_belt = Module["___em_js__api_draw_belt"] = function() { + return Module["asm"]["___em_js__api_draw_belt"].apply(null, arguments) +}; + +var ___em_js__api_draw_blit = Module["___em_js__api_draw_blit"] = function() { + return Module["asm"]["___em_js__api_draw_blit"].apply(null, arguments) +}; + +var ___em_js__api_draw_clip_text = Module["___em_js__api_draw_clip_text"] = function() { + return Module["asm"]["___em_js__api_draw_clip_text"].apply(null, arguments) +}; + +var ___em_js__api_draw_end = Module["___em_js__api_draw_end"] = function() { + return Module["asm"]["___em_js__api_draw_end"].apply(null, arguments) +}; + +var ___em_js__api_draw_text = Module["___em_js__api_draw_text"] = function() { + return Module["asm"]["___em_js__api_draw_text"].apply(null, arguments) +}; + +var ___em_js__api_duplicate_sound = Module["___em_js__api_duplicate_sound"] = function() { + return Module["asm"]["___em_js__api_duplicate_sound"].apply(null, arguments) +}; + +var ___em_js__api_exit_game = Module["___em_js__api_exit_game"] = function() { + return Module["asm"]["___em_js__api_exit_game"].apply(null, arguments) +}; + +var ___em_js__api_play_sound = Module["___em_js__api_play_sound"] = function() { + return Module["asm"]["___em_js__api_play_sound"].apply(null, arguments) +}; + +var ___em_js__api_set_cursor = Module["___em_js__api_set_cursor"] = function() { + return Module["asm"]["___em_js__api_set_cursor"].apply(null, arguments) +}; + +var ___em_js__api_set_volume = Module["___em_js__api_set_volume"] = function() { + return Module["asm"]["___em_js__api_set_volume"].apply(null, arguments) +}; + +var ___em_js__api_stop_sound = Module["___em_js__api_stop_sound"] = function() { + return Module["asm"]["___em_js__api_stop_sound"].apply(null, arguments) +}; + +var ___em_js__api_use_websocket = Module["___em_js__api_use_websocket"] = function() { + return Module["asm"]["___em_js__api_use_websocket"].apply(null, arguments) +}; + +var ___em_js__api_websocket_closed = Module["___em_js__api_websocket_closed"] = function() { + return Module["asm"]["___em_js__api_websocket_closed"].apply(null, arguments) +}; + +var ___em_js__api_websocket_send = Module["___em_js__api_websocket_send"] = function() { + return Module["asm"]["___em_js__api_websocket_send"].apply(null, arguments) +}; + +var ___em_js__exit_error = Module["___em_js__exit_error"] = function() { + return Module["asm"]["___em_js__exit_error"].apply(null, arguments) +}; + +var ___em_js__get_file_contents = Module["___em_js__get_file_contents"] = function() { + return Module["asm"]["___em_js__get_file_contents"].apply(null, arguments) +}; + +var ___em_js__get_file_size = Module["___em_js__get_file_size"] = function() { + return Module["asm"]["___em_js__get_file_size"].apply(null, arguments) +}; + +var ___em_js__put_file_contents = Module["___em_js__put_file_contents"] = function() { + return Module["asm"]["___em_js__put_file_contents"].apply(null, arguments) +}; + +var ___em_js__remove_file = Module["___em_js__remove_file"] = function() { + return Module["asm"]["___em_js__remove_file"].apply(null, arguments) +}; + +var ___em_js__show_alert = Module["___em_js__show_alert"] = function() { + return Module["asm"]["___em_js__show_alert"].apply(null, arguments) +}; + +var ___em_js__trace_pop = Module["___em_js__trace_pop"] = function() { + return Module["asm"]["___em_js__trace_pop"].apply(null, arguments) +}; + +var ___em_js__trace_push = Module["___em_js__trace_push"] = function() { + return Module["asm"]["___em_js__trace_push"].apply(null, arguments) +}; + +var _emscripten_replace_memory = Module["_emscripten_replace_memory"] = function() { + return Module["asm"]["_emscripten_replace_memory"].apply(null, arguments) +}; + +var _free = Module["_free"] = function() { + return Module["asm"]["_free"].apply(null, arguments) +}; + +var _llvm_bswap_i32 = Module["_llvm_bswap_i32"] = function() { + return Module["asm"]["_llvm_bswap_i32"].apply(null, arguments) +}; + +var _malloc = Module["_malloc"] = function() { + return Module["asm"]["_malloc"].apply(null, arguments) +}; + +var _memcpy = Module["_memcpy"] = function() { + return Module["asm"]["_memcpy"].apply(null, arguments) +}; + +var _memmove = Module["_memmove"] = function() { + return Module["asm"]["_memmove"].apply(null, arguments) +}; + +var _memset = Module["_memset"] = function() { + return Module["asm"]["_memset"].apply(null, arguments) +}; + +var _sbrk = Module["_sbrk"] = function() { + return Module["asm"]["_sbrk"].apply(null, arguments) +}; + +var _setThrew = Module["_setThrew"] = function() { + return Module["asm"]["_setThrew"].apply(null, arguments) +}; + +var establishStackSpace = Module["establishStackSpace"] = function() { + return Module["asm"]["establishStackSpace"].apply(null, arguments) +}; + +var globalCtors = Module["globalCtors"] = function() { + return Module["asm"]["globalCtors"].apply(null, arguments) +}; + +var stackAlloc = Module["stackAlloc"] = function() { + return Module["asm"]["stackAlloc"].apply(null, arguments) +}; + +var stackRestore = Module["stackRestore"] = function() { + return Module["asm"]["stackRestore"].apply(null, arguments) +}; + +var stackSave = Module["stackSave"] = function() { + return Module["asm"]["stackSave"].apply(null, arguments) +}; + +var dynCall_i = Module["dynCall_i"] = function() { + return Module["asm"]["dynCall_i"].apply(null, arguments) +}; + +var dynCall_ii = Module["dynCall_ii"] = function() { + return Module["asm"]["dynCall_ii"].apply(null, arguments) +}; + +var dynCall_iidiiii = Module["dynCall_iidiiii"] = function() { + return Module["asm"]["dynCall_iidiiii"].apply(null, arguments) +}; + +var dynCall_iii = Module["dynCall_iii"] = function() { + return Module["asm"]["dynCall_iii"].apply(null, arguments) +}; + +var dynCall_iiii = Module["dynCall_iiii"] = function() { + return Module["asm"]["dynCall_iiii"].apply(null, arguments) +}; + +var dynCall_iiiii = Module["dynCall_iiiii"] = function() { + return Module["asm"]["dynCall_iiiii"].apply(null, arguments) +}; + +var dynCall_iiiiii = Module["dynCall_iiiiii"] = function() { + return Module["asm"]["dynCall_iiiiii"].apply(null, arguments) +}; + +var dynCall_ji = Module["dynCall_ji"] = function() { + return Module["asm"]["dynCall_ji"].apply(null, arguments) +}; + +var dynCall_jiji = Module["dynCall_jiji"] = function() { + return Module["asm"]["dynCall_jiji"].apply(null, arguments) +}; + +var dynCall_v = Module["dynCall_v"] = function() { + return Module["asm"]["dynCall_v"].apply(null, arguments) +}; + +var dynCall_vi = Module["dynCall_vi"] = function() { + return Module["asm"]["dynCall_vi"].apply(null, arguments) +}; + +var dynCall_vii = Module["dynCall_vii"] = function() { + return Module["asm"]["dynCall_vii"].apply(null, arguments) +}; + +var dynCall_viii = Module["dynCall_viii"] = function() { + return Module["asm"]["dynCall_viii"].apply(null, arguments) +}; + +var dynCall_viiii = Module["dynCall_viiii"] = function() { + return Module["asm"]["dynCall_viiii"].apply(null, arguments) +}; + +var dynCall_viiiii = Module["dynCall_viiiii"] = function() { + return Module["asm"]["dynCall_viiiii"].apply(null, arguments) +}; + +var dynCall_viiiiii = Module["dynCall_viiiiii"] = function() { + return Module["asm"]["dynCall_viiiiii"].apply(null, arguments) +}; + +var dynCall_viiiiiii = Module["dynCall_viiiiiii"] = function() { + return Module["asm"]["dynCall_viiiiiii"].apply(null, arguments) +}; + +var dynCall_viiiiiiiii = Module["dynCall_viiiiiiiii"] = function() { + return Module["asm"]["dynCall_viiiiiiiii"].apply(null, arguments) +}; + +var dynCall_viiiiiiiiii = Module["dynCall_viiiiiiiiii"] = function() { + return Module["asm"]["dynCall_viiiiiiiiii"].apply(null, arguments) +}; + +var dynCall_viij = Module["dynCall_viij"] = function() { + return Module["asm"]["dynCall_viij"].apply(null, arguments) +}; + +var dynCall_viji = Module["dynCall_viji"] = function() { + return Module["asm"]["dynCall_viji"].apply(null, arguments) +}; ; @@ -2567,18 +2847,17 @@ function ExitStatus(status) { this.name = "ExitStatus"; this.message = "Program terminated with exit(" + status + ")"; this.status = status; -}; +} ExitStatus.prototype = new Error(); ExitStatus.prototype.constructor = ExitStatus; -var initialStackTop; var calledMain = false; dependenciesFulfilled = function runCaller() { // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false) if (!Module['calledRun']) run(); if (!Module['calledRun']) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled -} +}; @@ -2604,7 +2883,7 @@ function run(args) { if (ABORT) return; - ensureInitRuntime(); + initRuntime(); preMain(); @@ -2644,7 +2923,6 @@ function exit(status, implicit) { ABORT = true; EXITSTATUS = status; - STACKTOP = initialStackTop; exitRuntime(); @@ -2661,13 +2939,9 @@ function abort(what) { Module['onAbort'](what); } - if (what !== undefined) { - out(what); - err(what); - what = JSON.stringify(what) - } else { - what = ''; - } + what += ''; + out(what); + err(what); ABORT = true; EXITSTATUS = 1; @@ -2676,8 +2950,6 @@ function abort(what) { } Module['abort'] = abort; -// {{PRE_RUN_ADDITIONS}} - if (Module['preInit']) { if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']]; while (Module['preInit'].length > 0) { @@ -2686,12 +2958,10 @@ if (Module['preInit']) { } -Module["noExitRuntime"] = true; + Module["noExitRuntime"] = true; run(); -// {{POST_RUN_ADDITIONS}} - @@ -2712,14 +2982,14 @@ Module['ready'] = new Promise(function (resolve, reject) { - return Diablo; + return Diablo } ); })(); if (typeof exports === 'object' && typeof module === 'object') - module.exports = Diablo; - else if (typeof define === 'function' && define['amd']) - define([], function() { return Diablo; }); - else if (typeof exports === 'object') - exports["Diablo"] = Diablo; - \ No newline at end of file + module.exports = Diablo; + else if (typeof define === 'function' && define['amd']) + define([], function() { return Diablo; }); + else if (typeof exports === 'object') + exports["Diablo"] = Diablo; + \ No newline at end of file diff --git a/src/api/Diablo.wasm b/src/api/Diablo.wasm index 7070a88..9111f11 100644 Binary files a/src/api/Diablo.wasm and b/src/api/Diablo.wasm differ diff --git a/src/api/DiabloSpawn.jscc b/src/api/DiabloSpawn.jscc index 38f5fb6..8e6445f 100644 --- a/src/api/DiabloSpawn.jscc +++ b/src/api/DiabloSpawn.jscc @@ -5,6 +5,11 @@ var DiabloSpawn = (function() { function(DiabloSpawn) { DiabloSpawn = DiabloSpawn || {}; +// Copyright 2010 The Emscripten Authors. All rights reserved. +// Emscripten is available under two separate licenses, the MIT license and the +// University of Illinois/NCSA Open Source License. Both these licenses can be +// found in the LICENSE file. + // The Module object: Our interface to the outside world. We import // and export values on it. There are various ways Module can be used: // 1. Not defined. We create it here @@ -45,25 +50,35 @@ Module['quit'] = function(status, toThrow) { Module['preRun'] = []; Module['postRun'] = []; -// The environment setup code below is customized to use Module. -// *** Environment setup code *** +// Determine the runtime environment we are in. You can customize this by +// setting the ENVIRONMENT setting at compile time (see settings.js). var ENVIRONMENT_IS_WEB = false; var ENVIRONMENT_IS_WORKER = false; var ENVIRONMENT_IS_NODE = false; +var ENVIRONMENT_HAS_NODE = false; var ENVIRONMENT_IS_SHELL = false; ENVIRONMENT_IS_WEB = typeof window === 'object'; ENVIRONMENT_IS_WORKER = typeof importScripts === 'function'; -ENVIRONMENT_IS_NODE = typeof process === 'object' && typeof require === 'function' && !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_WORKER; +// A web environment like Electron.js can have Node enabled, so we must +// distinguish between Node-enabled environments and Node environments per se. +// This will allow the former to do things like mount NODEFS. +// Extended check using process.versions fixes issue #8816. +// (Also makes redundant the original check that 'require' is a function.) +ENVIRONMENT_HAS_NODE = typeof process === 'object' && typeof process.versions === 'object' && typeof process.versions.node === 'string'; +ENVIRONMENT_IS_NODE = ENVIRONMENT_HAS_NODE && !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_WORKER; ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER; + // Three configurations we can be running in: // 1) We could be the application main() thread running in the main JS UI thread. (ENVIRONMENT_IS_WORKER == false and ENVIRONMENT_IS_PTHREAD == false) // 2) We could be the application main() thread proxied to worker. (with Emscripten -s PROXY_TO_WORKER=1) (ENVIRONMENT_IS_WORKER == true, ENVIRONMENT_IS_PTHREAD == false) // 3) We could be an application pthread running in a worker. (ENVIRONMENT_IS_WORKER == true and ENVIRONMENT_IS_PTHREAD == true) + + // `/` should be present at the end if `scriptDirectory` is not empty var scriptDirectory = ''; function locateFile(path) { @@ -74,6 +89,12 @@ function locateFile(path) { } } +// Hooks that are implemented differently in different runtime environments. +var read_, + readAsync, + readBinary, + setWindowTitle; + if (ENVIRONMENT_IS_NODE) { scriptDirectory = __dirname + '/'; @@ -82,7 +103,7 @@ if (ENVIRONMENT_IS_NODE) { var nodeFS; var nodePath; - Module['read'] = function shell_read(filename, binary) { + read_ = function shell_read(filename, binary) { var ret; if (!nodeFS) nodeFS = require('fs'); if (!nodePath) nodePath = require('path'); @@ -91,8 +112,8 @@ if (ENVIRONMENT_IS_NODE) { return binary ? ret : ret.toString(); }; - Module['readBinary'] = function readBinary(filename) { - var ret = Module['read'](filename, true); + readBinary = function readBinary(filename) { + var ret = read_(filename, true); if (!ret.buffer) { ret = new Uint8Array(ret); } @@ -116,9 +137,7 @@ if (ENVIRONMENT_IS_NODE) { }); // Currently node will swallow unhandled rejections, but this behavior is // deprecated, and in the future it will exit with error status. - process['on']('unhandledRejection', function(reason, p) { - process['exit'](1); - }); + process['on']('unhandledRejection', abort); Module['quit'] = function(status) { process['exit'](status); @@ -130,12 +149,12 @@ if (ENVIRONMENT_IS_SHELL) { if (typeof read != 'undefined') { - Module['read'] = function shell_read(f) { + read_ = function shell_read(f) { return read(f); }; } - Module['readBinary'] = function readBinary(f) { + readBinary = function readBinary(f) { var data; if (typeof readbuffer === 'function') { return new Uint8Array(readbuffer(f)); @@ -158,12 +177,10 @@ if (ENVIRONMENT_IS_SHELL) { } } else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { - if (ENVIRONMENT_IS_WEB) { - if (document.currentScript) { - scriptDirectory = document.currentScript.src; - } - } else { // worker + if (ENVIRONMENT_IS_WORKER) { // Check worker, not web, since window could be polyfilled scriptDirectory = self.location.href; + } else if (document.currentScript) { // web + scriptDirectory = document.currentScript.src; } // When MODULARIZE (and not _INSTANCE), this JS may be executed later, after document.currentScript // is gone, so we saved it, and we use it here instead of any other info. @@ -172,14 +189,16 @@ if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { } // blob urls look like blob:http://site.com/etc/etc and we cannot infer anything from them. // otherwise, slice off the final part of the url to find the script directory. + // if scriptDirectory does not contain a slash, lastIndexOf will return -1, + // and scriptDirectory will correctly be replaced with an empty string. if (scriptDirectory.indexOf('blob:') !== 0) { - scriptDirectory = scriptDirectory.split('/').slice(0, -1).join('/') + '/'; + scriptDirectory = scriptDirectory.substr(0, scriptDirectory.lastIndexOf('/')+1); } else { scriptDirectory = ''; } - Module['read'] = function shell_read(url) { + read_ = function shell_read(url) { var xhr = new XMLHttpRequest(); xhr.open('GET', url, false); xhr.send(null); @@ -187,7 +206,7 @@ if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { }; if (ENVIRONMENT_IS_WORKER) { - Module['readBinary'] = function readBinary(url) { + readBinary = function readBinary(url) { var xhr = new XMLHttpRequest(); xhr.open('GET', url, false); xhr.responseType = 'arraybuffer'; @@ -196,7 +215,7 @@ if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { }; } - Module['readAsync'] = function readAsync(url, onload, onerror) { + readAsync = function readAsync(url, onload, onerror) { var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.responseType = 'arraybuffer'; @@ -211,7 +230,7 @@ if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { xhr.send(null); }; - Module['setWindowTitle'] = function(title) { document.title = title }; + setWindowTitle = function(title) { document.title = title }; } else { } @@ -225,8 +244,6 @@ if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { var out = Module['print'] || (typeof console !== 'undefined' ? console.log.bind(console) : (typeof print !== 'undefined' ? print : null)); var err = Module['printErr'] || (typeof printErr !== 'undefined' ? printErr : ((typeof console !== 'undefined' && console.warn.bind(console)) || out)); -// *** Environment setup code *** - // Merge back in the overrides for (key in moduleOverrides) { if (moduleOverrides.hasOwnProperty(key)) { @@ -237,37 +254,35 @@ for (key in moduleOverrides) { // reclaim data used e.g. in memoryInitializerRequest, which is a large typed array. moduleOverrides = undefined; +// perform assertions in shell.js after we set up out() and err(), as otherwise if an assertion fails it cannot print the message +// TODO remove when SDL2 is fixed; also add the above assertion + + + +// Copyright 2017 The Emscripten Authors. All rights reserved. +// Emscripten is available under two separate licenses, the MIT license and the +// University of Illinois/NCSA Open Source License. Both these licenses can be +// found in the LICENSE file. // {{PREAMBLE_ADDITIONS}} var STACK_ALIGN = 16; -function staticAlloc(size) { - var ret = STATICTOP; - STATICTOP = (STATICTOP + size + 15) & -16; - return ret; -} - function dynamicAlloc(size) { var ret = HEAP32[DYNAMICTOP_PTR>>2]; var end = (ret + size + 15) & -16; - HEAP32[DYNAMICTOP_PTR>>2] = end; - if (end >= TOTAL_MEMORY) { - var success = enlargeMemory(); - if (!success) { - HEAP32[DYNAMICTOP_PTR>>2] = ret; - return 0; - } + if (end > _emscripten_get_heap_size()) { + abort(); } + HEAP32[DYNAMICTOP_PTR>>2] = end; return ret; } function alignMemory(size, factor) { if (!factor) factor = STACK_ALIGN; // stack alignment (16-byte) by default - var ret = size = Math.ceil(size / factor) * factor; - return ret; + return Math.ceil(size / factor) * factor; } function getNativeTypeSize(type) { @@ -283,7 +298,7 @@ function getNativeTypeSize(type) { return 4; // A pointer } else if (type[0] === 'i') { var bits = parseInt(type.substr(1)); - assert(bits % 8 === 0); + assert(bits % 8 === 0, 'getNativeTypeSize invalid bits ' + bits + ', type ' + type); return bits / 8; } else { return 0; @@ -314,8 +329,112 @@ var asm2wasmImports = { // special asm2wasm imports var jsCallStartIndex = 1; var functionPointers = new Array(0); -// 'sig' parameter is only used on LLVM wasm backend +// Wraps a JS function as a wasm function with a given signature. +// In the future, we may get a WebAssembly.Function constructor. Until then, +// we create a wasm module that takes the JS function as an import with a given +// signature, and re-exports that as a wasm function. +function convertJsFunctionToWasm(func, sig) { + + // The module is static, with the exception of the type section, which is + // generated based on the signature passed in. + var typeSection = [ + 0x01, // id: section, + 0x00, // length: 0 (placeholder) + 0x01, // count: 1 + 0x60, // form: func + ]; + var sigRet = sig.slice(0, 1); + var sigParam = sig.slice(1); + var typeCodes = { + 'i': 0x7f, // i32 + 'j': 0x7e, // i64 + 'f': 0x7d, // f32 + 'd': 0x7c, // f64 + }; + + // Parameters, length + signatures + typeSection.push(sigParam.length); + for (var i = 0; i < sigParam.length; ++i) { + typeSection.push(typeCodes[sigParam[i]]); + } + + // Return values, length + signatures + // With no multi-return in MVP, either 0 (void) or 1 (anything else) + if (sigRet == 'v') { + typeSection.push(0x00); + } else { + typeSection = typeSection.concat([0x01, typeCodes[sigRet]]); + } + + // Write the overall length of the type section back into the section header + // (excepting the 2 bytes for the section id and length) + typeSection[1] = typeSection.length - 2; + + // Rest of the module is static + var bytes = new Uint8Array([ + 0x00, 0x61, 0x73, 0x6d, // magic ("\0asm") + 0x01, 0x00, 0x00, 0x00, // version: 1 + ].concat(typeSection, [ + 0x02, 0x07, // import section + // (import "e" "f" (func 0 (type 0))) + 0x01, 0x01, 0x65, 0x01, 0x66, 0x00, 0x00, + 0x07, 0x05, // export section + // (export "f" (func 0 (type 0))) + 0x01, 0x01, 0x66, 0x00, 0x00, + ])); + + // We can compile this wasm module synchronously because it is very small. + // This accepts an import (at "e.f"), that it reroutes to an export (at "f") + var module = new WebAssembly.Module(bytes); + var instance = new WebAssembly.Instance(module, { + e: { + f: func + } + }); + var wrappedFunc = instance.exports.f; + return wrappedFunc; +} + +// Add a wasm function to the table. +function addFunctionWasm(func, sig) { + var table = wasmTable; + var ret = table.length; + + // Grow the table + try { + table.grow(1); + } catch (err) { + if (!err instanceof RangeError) { + throw err; + } + throw 'Unable to grow wasm table. Use a higher value for RESERVED_FUNCTION_POINTERS or set ALLOW_TABLE_GROWTH.'; + } + + // Insert new element + try { + // Attempting to call this with JS function will cause of table.set() to fail + table.set(ret, func); + } catch (err) { + if (!err instanceof TypeError) { + throw err; + } + assert(typeof sig !== 'undefined', 'Missing signature argument to addFunction'); + var wrapped = convertJsFunctionToWasm(func, sig); + table.set(ret, wrapped); + } + + return ret; +} + +function removeFunctionWasm(index) { + // TODO(sbc): Look into implementing this to allow re-using of table slots +} + +// 'sig' parameter is required for the llvm backend but only when func is not +// already a WebAssembly function. function addFunction(func, sig) { + + var base = 0; for (var i = base; i < base + 0; i++) { if (!functionPointers[i]) { @@ -324,9 +443,11 @@ function addFunction(func, sig) { } } throw 'Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.'; + } function removeFunction(index) { + functionPointers[index-jsCallStartIndex] = null; } @@ -372,13 +493,18 @@ function dynCall(sig, ptr, args) { } } +var tempRet0 = 0; + +var setTempRet0 = function(value) { + tempRet0 = value; +}; + +var getTempRet0 = function() { + return tempRet0; +}; var Runtime = { - // FIXME backwards compatibility layer for ports. Support some Runtime.* - // for now, fix it there, then remove it from here. That way we - // can minimize any period of breakage. - dynCall: dynCall, // for SDL2 port }; // The address globals begin at. Very low in memory, for code size and optimization opportunities. @@ -388,6 +514,8 @@ var Runtime = { var GLOBAL_BASE = 1024; + + // === Preamble library stuff === // Documentation for the public APIs defined in this file must be updated in: @@ -400,11 +528,70 @@ var GLOBAL_BASE = 1024; +if (typeof WebAssembly !== 'object') { + err('no native wasm support detected'); +} + + +// In MINIMAL_RUNTIME, setValue() and getValue() are only available when building with safe heap enabled, for heap safety checking. +// In traditional runtime, setValue() and getValue() are always available (although their use is highly discouraged due to perf penalties) + +/** @type {function(number, number, string, boolean=)} */ +function setValue(ptr, value, type, noSafe) { + type = type || 'i8'; + if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit + 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.0 ? (tempDouble > 0.0 ? ((Math_min((+(Math_floor((tempDouble)/4294967296.0))), 4294967295.0))|0)>>>0 : (~~((+(Math_ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>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; + default: abort('invalid type for setValue: ' + type); + } +} + +/** @type {function(number, string, boolean=)} */ +function getValue(ptr, type, noSafe) { + type = type || 'i8'; + if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit + 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)]; + default: abort('invalid type for getValue: ' + type); + } + return null; +} + + + + + +// Wasm globals + +var wasmMemory; + +// Potentially used for direct table calls. +var wasmTable; + + //======================================== // Runtime essentials //======================================== -var ABORT = 0; // whether we are quitting the application. no code should run after this. set in exit() and abort() +// whether we are quitting the application. no code should run after this. +// set in exit() and abort() +var ABORT = false; + +// set by exit() and abort(). Passed to 'onExit' handler. +// NOTE: This is also used as the process return code code in shell environments +// but only when noExitRuntime is false. var EXITSTATUS = 0; /** @type {function(*, string=)} */ @@ -414,8 +601,6 @@ function assert(condition, text) { } } -var globalScope = this; - // Returns the C function with a specified identifier (for C++, you need to do manual name mangling) function getCFunc(ident) { var func = Module['_' + ident]; // closure exported function @@ -423,44 +608,29 @@ function getCFunc(ident) { return func; } -var JSfuncs = { - // Helpers for cwrap -- it can't refer to Runtime directly because it might - // be renamed by closure, instead it calls JSfuncs['stackSave'].body to find - // out what the minified function name is. - 'stackSave': function() { - stackSave() - }, - 'stackRestore': function() { - stackRestore() - }, - // type conversion from js to c - 'arrayToC' : function(arr) { - var ret = stackAlloc(arr.length); - writeArrayToMemory(arr, ret); - return ret; - }, - 'stringToC' : function(str) { - var ret = 0; - if (str !== null && str !== undefined && str !== 0) { // null string - // at most 4 bytes per UTF-8 code point, +1 for the trailing '\0' - var len = (str.length << 2) + 1; - ret = stackAlloc(len); - stringToUTF8(str, ret, len); - } - return ret; - } -}; - -// For fast lookup of conversion functions -var toC = { - 'string': JSfuncs['stringToC'], 'array': JSfuncs['arrayToC'] -}; - - // C calling interface. function ccall(ident, returnType, argTypes, args, opts) { + // For fast lookup of conversion functions + var toC = { + 'string': function(str) { + var ret = 0; + if (str !== null && str !== undefined && str !== 0) { // null string + // at most 4 bytes per UTF-8 code point, +1 for the trailing '\0' + var len = (str.length << 2) + 1; + ret = stackAlloc(len); + stringToUTF8(str, ret, len); + } + return ret; + }, + 'array': function(arr) { + var ret = stackAlloc(arr.length); + writeArrayToMemory(arr, ret); + return ret; + } + }; + function convertReturnValue(ret) { - if (returnType === 'string') return Pointer_stringify(ret); + if (returnType === 'string') return UTF8ToString(ret); if (returnType === 'boolean') return Boolean(ret); return ret; } @@ -499,44 +669,10 @@ function cwrap(ident, returnType, argTypes, opts) { } } -/** @type {function(number, number, string, boolean=)} */ -function setValue(ptr, value, type, noSafe) { - type = type || 'i8'; - if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit - 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.0 ? (tempDouble > 0.0 ? ((Math_min((+(Math_floor((tempDouble)/4294967296.0))), 4294967295.0))|0)>>>0 : (~~((+(Math_ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>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; - default: abort('invalid type for setValue: ' + type); - } -} - -/** @type {function(number, string, boolean=)} */ -function getValue(ptr, type, noSafe) { - type = type || 'i8'; - if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit - 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)]; - default: abort('invalid type for getValue: ' + type); - } - return null; -} - var ALLOC_NORMAL = 0; // Tries to use _malloc() var ALLOC_STACK = 1; // Lives for the duration of the current function call -var ALLOC_STATIC = 2; // Cannot be freed -var ALLOC_DYNAMIC = 3; // Cannot be freed except through sbrk -var ALLOC_NONE = 4; // Do not allocate +var ALLOC_DYNAMIC = 2; // Cannot be freed except through sbrk +var ALLOC_NONE = 3; // Do not allocate // allocate(): This is for internal use. You can use it yourself as well, but the interface // is a little tricky (see docs right below). The reason is that it is optimized @@ -568,7 +704,9 @@ function allocate(slab, types, allocator, ptr) { if (allocator == ALLOC_NONE) { ret = ptr; } else { - ret = [typeof _malloc === 'function' ? _malloc : staticAlloc, stackAlloc, staticAlloc, dynamicAlloc][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length)); + ret = [_malloc, + stackAlloc, + dynamicAlloc][allocator](Math.max(size, singleType ? 1 : types.length)); } if (zeroinit) { @@ -622,41 +760,16 @@ function allocate(slab, types, allocator, ptr) { // Allocate memory during any stage of startup - static memory early on, dynamic memory later, malloc when ready function getMemory(size) { - if (!staticSealed) return staticAlloc(size); if (!runtimeInitialized) return dynamicAlloc(size); return _malloc(size); } + + + /** @type {function(number, number=)} */ function Pointer_stringify(ptr, length) { - if (length === 0 || !ptr) return ''; - // Find the length, and check for UTF while doing so - var hasUtf = 0; - var t; - var i = 0; - while (1) { - t = HEAPU8[(((ptr)+(i))>>0)]; - hasUtf |= t; - if (t == 0 && !length) break; - i++; - if (length && i == length) break; - } - if (!length) length = i; - - var ret = ''; - - if (hasUtf < 128) { - var MAX_CHUNK = 1024; // split up into chunks, because .apply on a huge string can overflow the stack - var curr; - while (length > 0) { - curr = String.fromCharCode.apply(String, HEAPU8.subarray(ptr, ptr + Math.min(length, MAX_CHUNK))); - ret = ret ? ret + curr : curr; - ptr += MAX_CHUNK; - length -= MAX_CHUNK; - } - return ret; - } - return UTF8ToString(ptr); + abort("this function has been removed - you should use UTF8ToString(ptr, maxBytesToRead) instead!"); } // Given a pointer 'ptr' to a null-terminated ASCII-encoded string in the emscripten HEAP, returns @@ -665,7 +778,7 @@ function Pointer_stringify(ptr, length) { function AsciiToString(ptr) { var str = ''; while (1) { - var ch = HEAP8[((ptr++)>>0)]; + var ch = HEAPU8[((ptr++)>>0)]; if (!ch) return str; str += String.fromCharCode(ch); } @@ -678,46 +791,46 @@ function stringToAscii(str, outPtr) { return writeAsciiToMemory(str, outPtr, false); } + // Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the given array that contains uint8 values, returns // a copy of that string as a Javascript String object. var UTF8Decoder = typeof TextDecoder !== 'undefined' ? new TextDecoder('utf8') : undefined; -function UTF8ArrayToString(u8Array, idx) { + +/** + * @param {number} idx + * @param {number=} maxBytesToRead + * @return {string} + */ +function UTF8ArrayToString(u8Array, idx, maxBytesToRead) { + var endIdx = idx + maxBytesToRead; var endPtr = idx; // TextDecoder needs to know the byte length in advance, it doesn't stop on null terminator by itself. // Also, use the length info to avoid running tiny strings through TextDecoder, since .subarray() allocates garbage. - while (u8Array[endPtr]) ++endPtr; + // (As a tiny code save trick, compare endPtr against endIdx using a negation, so that undefined means Infinity) + while (u8Array[endPtr] && !(endPtr >= endIdx)) ++endPtr; if (endPtr - idx > 16 && u8Array.subarray && UTF8Decoder) { return UTF8Decoder.decode(u8Array.subarray(idx, endPtr)); } else { - var u0, u1, u2, u3, u4, u5; - var str = ''; - while (1) { - // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description and https://www.ietf.org/rfc/rfc2279.txt and https://tools.ietf.org/html/rfc3629 - u0 = u8Array[idx++]; - if (!u0) return str; + // If building with TextDecoder, we have already computed the string length above, so test loop end condition against that + while (idx < endPtr) { + // For UTF8 byte structure, see: + // http://en.wikipedia.org/wiki/UTF-8#Description + // https://www.ietf.org/rfc/rfc2279.txt + // https://tools.ietf.org/html/rfc3629 + var u0 = u8Array[idx++]; if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; } - u1 = u8Array[idx++] & 63; + var u1 = u8Array[idx++] & 63; if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; } - u2 = u8Array[idx++] & 63; + var u2 = u8Array[idx++] & 63; if ((u0 & 0xF0) == 0xE0) { u0 = ((u0 & 15) << 12) | (u1 << 6) | u2; } else { - u3 = u8Array[idx++] & 63; - if ((u0 & 0xF8) == 0xF0) { - u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | u3; - } else { - u4 = u8Array[idx++] & 63; - if ((u0 & 0xFC) == 0xF8) { - u0 = ((u0 & 3) << 24) | (u1 << 18) | (u2 << 12) | (u3 << 6) | u4; - } else { - u5 = u8Array[idx++] & 63; - u0 = ((u0 & 1) << 30) | (u1 << 24) | (u2 << 18) | (u3 << 12) | (u4 << 6) | u5; - } - } + u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (u8Array[idx++] & 63); } + if (u0 < 0x10000) { str += String.fromCharCode(u0); } else { @@ -726,13 +839,26 @@ function UTF8ArrayToString(u8Array, idx) { } } } + return str; } -// Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the emscripten HEAP, returns -// a copy of that string as a Javascript String object. - -function UTF8ToString(ptr) { - return UTF8ArrayToString(HEAPU8,ptr); +// Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the emscripten HEAP, returns a +// copy of that string as a Javascript String object. +// maxBytesToRead: an optional length that specifies the maximum number of bytes to read. You can omit +// this parameter to scan the string until the first \0 byte. If maxBytesToRead is +// passed, and the string at [ptr, ptr+maxBytesToReadr[ contains a null byte in the +// middle, then the string will cut short at that byte index (i.e. maxBytesToRead will +// not produce a string of exact length [ptr, ptr+maxBytesToRead[) +// N.B. mixing frequent uses of UTF8ToString() with and without maxBytesToRead may +// throw JS JIT optimizations off, so it is worth to consider consistently using one +// style or the other. +/** + * @param {number} ptr + * @param {number=} maxBytesToRead + * @return {string} + */ +function UTF8ToString(ptr, maxBytesToRead) { + return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : ''; } // Copies the given Javascript String object 'str' to the given byte array at address 'outIdx', @@ -775,27 +901,12 @@ function stringToUTF8Array(str, outU8Array, outIdx, maxBytesToWrite) { outU8Array[outIdx++] = 0xE0 | (u >> 12); outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63); outU8Array[outIdx++] = 0x80 | (u & 63); - } else if (u <= 0x1FFFFF) { + } else { if (outIdx + 3 >= endIdx) break; outU8Array[outIdx++] = 0xF0 | (u >> 18); outU8Array[outIdx++] = 0x80 | ((u >> 12) & 63); outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63); outU8Array[outIdx++] = 0x80 | (u & 63); - } else if (u <= 0x3FFFFFF) { - if (outIdx + 4 >= endIdx) break; - outU8Array[outIdx++] = 0xF8 | (u >> 24); - outU8Array[outIdx++] = 0x80 | ((u >> 18) & 63); - outU8Array[outIdx++] = 0x80 | ((u >> 12) & 63); - outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63); - outU8Array[outIdx++] = 0x80 | (u & 63); - } else { - if (outIdx + 5 >= endIdx) break; - outU8Array[outIdx++] = 0xFC | (u >> 30); - outU8Array[outIdx++] = 0x80 | ((u >> 24) & 63); - outU8Array[outIdx++] = 0x80 | ((u >> 18) & 63); - outU8Array[outIdx++] = 0x80 | ((u >> 12) & 63); - outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63); - outU8Array[outIdx++] = 0x80 | (u & 63); } } // Null-terminate the pointer to the buffer. @@ -813,7 +924,6 @@ function stringToUTF8(str, outPtr, maxBytesToWrite) { } // Returns the number of bytes the given Javascript string takes if encoded as a UTF8 byte array, EXCLUDING the null terminator byte. - function lengthBytesUTF8(str) { var len = 0; for (var i = 0; i < str.length; ++i) { @@ -821,23 +931,15 @@ function lengthBytesUTF8(str) { // See http://unicode.org/faq/utf_bom.html#utf16-3 var u = str.charCodeAt(i); // possibly a lead surrogate if (u >= 0xD800 && u <= 0xDFFF) u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF); - if (u <= 0x7F) { - ++len; - } else if (u <= 0x7FF) { - len += 2; - } else if (u <= 0xFFFF) { - len += 3; - } else if (u <= 0x1FFFFF) { - len += 4; - } else if (u <= 0x3FFFFFF) { - len += 5; - } else { - len += 6; - } + if (u <= 0x7F) ++len; + else if (u <= 0x7FF) len += 2; + else if (u <= 0xFFFF) len += 3; + else len += 4; } return len; } + // Given a pointer 'ptr' to a null-terminated UTF16LE-encoded string in the emscripten HEAP, returns // a copy of that string as a Javascript String object. @@ -991,6 +1093,42 @@ function allocateUTF8OnStack(str) { return ret; } +// Deprecated: This function should not be called because it is unsafe and does not provide +// a maximum length limit of how many bytes it is allowed to write. Prefer calling the +// function stringToUTF8Array() instead, which takes in a maximum length that can be used +// to be secure from out of bounds writes. +/** @deprecated */ +function writeStringToMemory(string, buffer, dontAddNull) { + warnOnce('writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!'); + + var /** @type {number} */ lastChar, /** @type {number} */ end; + if (dontAddNull) { + // stringToUTF8Array always appends null. If we don't want to do that, remember the + // character that existed at the location where the null will be placed, and restore + // that after the write (below). + end = buffer + lengthBytesUTF8(string); + lastChar = HEAP8[end]; + } + stringToUTF8(string, buffer, Infinity); + if (dontAddNull) HEAP8[end] = lastChar; // Restore the value under the null character. +} + +function writeArrayToMemory(array, buffer) { + HEAP8.set(array, buffer); +} + +function writeAsciiToMemory(str, buffer, dontAddNull) { + for (var i = 0; i < str.length; ++i) { + HEAP8[((buffer++)>>0)]=str.charCodeAt(i); + } + // Null-terminate the pointer to the HEAP. + if (!dontAddNull) HEAP8[((buffer)>>0)]=0; +} + + + + + function demangle(func) { return func; } @@ -1001,7 +1139,7 @@ function demangleAll(text) { return text.replace(regex, function(x) { var y = demangle(x); - return x === y ? x : (x + ' [' + y + ']'); + return x === y ? x : (y + ' [' + x + ']'); }); } @@ -1028,12 +1166,13 @@ function stackTrace() { return demangleAll(js); } + + // Memory management var PAGE_SIZE = 16384; var WASM_PAGE_SIZE = 65536; var ASMJS_PAGE_SIZE = 16777216; -var MIN_TOTAL_MEMORY = 16777216; function alignUp(x, multiple) { if (x % multiple > 0) { @@ -1062,10 +1201,6 @@ var HEAP, /** @type {Float64Array} */ HEAPF64; -function updateGlobalBuffer(buf) { - Module['buffer'] = buffer = buf; -} - function updateGlobalBufferViews() { Module['HEAP8'] = HEAP8 = new Int8Array(buffer); Module['HEAP16'] = HEAP16 = new Int16Array(buffer); @@ -1077,116 +1212,53 @@ function updateGlobalBufferViews() { Module['HEAPF64'] = HEAPF64 = new Float64Array(buffer); } -var STATIC_BASE, STATICTOP, staticSealed; // static area -var STACK_BASE, STACKTOP, STACK_MAX; // stack area -var DYNAMIC_BASE, DYNAMICTOP_PTR; // dynamic area handled by sbrk - STATIC_BASE = STATICTOP = STACK_BASE = STACKTOP = STACK_MAX = DYNAMIC_BASE = DYNAMICTOP_PTR = 0; - staticSealed = false; +var STATIC_BASE = 1024, + STACK_BASE = 1850928, + STACKTOP = STACK_BASE, + STACK_MAX = 7093808, + DYNAMIC_BASE = 7093808, + DYNAMICTOP_PTR = 1850896; -function abortOnCannotGrowMemory() { - abort('Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value ' + TOTAL_MEMORY + ', (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 '); -} +var TOTAL_STACK = 5242880; -if (!Module['reallocBuffer']) Module['reallocBuffer'] = function(size) { - var ret; - try { - if (ArrayBuffer.transfer) { - ret = ArrayBuffer.transfer(buffer, size); - } else { - var oldHEAP8 = HEAP8; - ret = new ArrayBuffer(size); - var temp = new Int8Array(ret); - temp.set(oldHEAP8); - } - } catch(e) { - return false; - } - var success = _emscripten_replace_memory(ret); - if (!success) return false; - return ret; -}; - -function enlargeMemory() { - // TOTAL_MEMORY is the current size of the actual array, and DYNAMICTOP is the new top. - - - var PAGE_MULTIPLE = Module["usingWasm"] ? WASM_PAGE_SIZE : ASMJS_PAGE_SIZE; // In wasm, heap size must be a multiple of 64KB. In asm.js, they need to be multiples of 16MB. - var LIMIT = 2147483648 - PAGE_MULTIPLE; // We can do one page short of 2GB as theoretical maximum. - - if (HEAP32[DYNAMICTOP_PTR>>2] > LIMIT) { - return false; - } - - var OLD_TOTAL_MEMORY = TOTAL_MEMORY; - TOTAL_MEMORY = Math.max(TOTAL_MEMORY, MIN_TOTAL_MEMORY); // So the loop below will not be infinite, and minimum asm.js memory size is 16MB. - - while (TOTAL_MEMORY < HEAP32[DYNAMICTOP_PTR>>2]) { // Keep incrementing the heap size as long as it's less than what is requested. - if (TOTAL_MEMORY <= 536870912) { - TOTAL_MEMORY = alignUp(2 * TOTAL_MEMORY, PAGE_MULTIPLE); // Simple heuristic: double until 1GB... - } else { - // ..., but after that, add smaller increments towards 2GB, which we cannot reach - TOTAL_MEMORY = Math.min(alignUp((3 * TOTAL_MEMORY + 2147483648) / 4, PAGE_MULTIPLE), LIMIT); - } - } - - - var replacement = Module['reallocBuffer'](TOTAL_MEMORY); - if (!replacement || replacement.byteLength != TOTAL_MEMORY) { - // restore the state to before this call, we failed - TOTAL_MEMORY = OLD_TOTAL_MEMORY; - return false; - } - - // everything worked - - updateGlobalBuffer(replacement); - updateGlobalBufferViews(); - - - - return true; -} - -var byteLength; -try { - byteLength = Function.prototype.call.bind(Object.getOwnPropertyDescriptor(ArrayBuffer.prototype, 'byteLength').get); - byteLength(new ArrayBuffer(4)); // can fail on older ie -} catch(e) { // can fail on older node/v8 - byteLength = function(buffer) { return buffer.byteLength; }; -} - -var TOTAL_STACK = Module['TOTAL_STACK'] || 5242880; -var TOTAL_MEMORY = Module['TOTAL_MEMORY'] || 134217728; -if (TOTAL_MEMORY < TOTAL_STACK) err('TOTAL_MEMORY should be larger than TOTAL_STACK, was ' + TOTAL_MEMORY + '! (TOTAL_STACK=' + TOTAL_STACK + ')'); +var INITIAL_TOTAL_MEMORY = Module['TOTAL_MEMORY'] || 134217728; +if (INITIAL_TOTAL_MEMORY < TOTAL_STACK) err('TOTAL_MEMORY should be larger than TOTAL_STACK, was ' + INITIAL_TOTAL_MEMORY + '! (TOTAL_STACK=' + TOTAL_STACK + ')'); // Initialize the runtime's memory -// Use a provided buffer, if there is one, or else allocate a new one -if (Module['buffer']) { - buffer = Module['buffer']; -} else { - // Use a WebAssembly memory where available - if (typeof WebAssembly === 'object' && typeof WebAssembly.Memory === 'function') { - Module['wasmMemory'] = new WebAssembly.Memory({ 'initial': TOTAL_MEMORY / WASM_PAGE_SIZE }); - buffer = Module['wasmMemory'].buffer; - } else - { - buffer = new ArrayBuffer(TOTAL_MEMORY); + + + + if (Module['wasmMemory']) { + wasmMemory = Module['wasmMemory']; + } else { + wasmMemory = new WebAssembly.Memory({ + 'initial': INITIAL_TOTAL_MEMORY / WASM_PAGE_SIZE + }); } - Module['buffer'] = buffer; + + +if (wasmMemory) { + buffer = wasmMemory.buffer; } + +// If the user provides an incorrect length, just use that length instead rather than providing the user to +// specifically provide the memory length with Module['TOTAL_MEMORY']. +INITIAL_TOTAL_MEMORY = buffer.byteLength; updateGlobalBufferViews(); +HEAP32[DYNAMICTOP_PTR>>2] = DYNAMIC_BASE; + + + + -function getTotalMemory() { - return TOTAL_MEMORY; -} // Endianness check (note: assumes compiler arch was little-endian) @@ -1231,18 +1303,18 @@ function preRun() { callRuntimeCallbacks(__ATPRERUN__); } -function ensureInitRuntime() { - if (runtimeInitialized) return; +function initRuntime() { runtimeInitialized = true; + callRuntimeCallbacks(__ATINIT__); } function preMain() { + callRuntimeCallbacks(__ATMAIN__); } function exitRuntime() { - callRuntimeCallbacks(__ATEXIT__); runtimeExited = true; } @@ -1270,45 +1342,12 @@ function addOnPreMain(cb) { } function addOnExit(cb) { - __ATEXIT__.unshift(cb); } function addOnPostRun(cb) { __ATPOSTRUN__.unshift(cb); } -// Deprecated: This function should not be called because it is unsafe and does not provide -// a maximum length limit of how many bytes it is allowed to write. Prefer calling the -// function stringToUTF8Array() instead, which takes in a maximum length that can be used -// to be secure from out of bounds writes. -/** @deprecated */ -function writeStringToMemory(string, buffer, dontAddNull) { - warnOnce('writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!'); - - var /** @type {number} */ lastChar, /** @type {number} */ end; - if (dontAddNull) { - // stringToUTF8Array always appends null. If we don't want to do that, remember the - // character that existed at the location where the null will be placed, and restore - // that after the write (below). - end = buffer + lengthBytesUTF8(string); - lastChar = HEAP8[end]; - } - stringToUTF8(string, buffer, Infinity); - if (dontAddNull) HEAP8[end] = lastChar; // Restore the value under the null character. -} - -function writeArrayToMemory(array, buffer) { - HEAP8.set(array, buffer); -} - -function writeAsciiToMemory(str, buffer, dontAddNull) { - for (var i = 0; i < str.length; ++i) { - HEAP8[((buffer++)>>0)]=str.charCodeAt(i); - } - // Null-terminate the pointer to the HEAP. - if (!dontAddNull) HEAP8[((buffer)>>0)]=0; -} - function unSign(value, bits, ignore) { if (value >= 0) { return value; @@ -1331,6 +1370,7 @@ function reSign(value, bits, ignore) { } + var Math_abs = Math.abs; var Math_cos = Math.cos; var Math_sin = Math.sin; @@ -1353,10 +1393,12 @@ var Math_max = Math.max; var Math_clz32 = Math.clz32; var Math_trunc = Math.trunc; + + // A counter of dependencies for calling run(). If we need to // do asynchronous work before running, increment this and // decrement it. Incrementing must happen in a place like -// PRE_RUN_ADDITIONS (used by emcc to add file preloading). +// Module.preRun (used by emcc to add file preloading). // Note that you can add dependencies in preRun, even though // it happens right before run - run will be postponed until // the dependencies are met. @@ -1397,7 +1439,6 @@ Module["preloadedImages"] = {}; // maps url to image data Module["preloadedAudios"] = {}; // maps url to audio data - var memoryInitializer = null; @@ -1405,6 +1446,11 @@ var memoryInitializer = null; +// Copyright 2017 The Emscripten Authors. All rights reserved. +// Emscripten is available under two separate licenses, the MIT license and the +// University of Illinois/NCSA Open Source License. Both these licenses can be +// found in the LICENSE file. + // Prefix of data URIs emitted by SINGLE_FILE and related options. var dataURIPrefix = 'data:application/octet-stream;base64,'; @@ -1418,270 +1464,156 @@ function isDataURI(filename) { -function integrateWasmJS() { - // wasm.js has several methods for creating the compiled code module here: - // * 'native-wasm' : use native WebAssembly support in the browser - // * 'interpret-s-expr': load s-expression code from a .wast and interpret - // * 'interpret-binary': load binary wasm and interpret - // * 'interpret-asm2wasm': load asm.js code, translate to wasm, and interpret - // * 'asmjs': no wasm, just load the asm.js code and use that (good for testing) - // The method is set at compile time (BINARYEN_METHOD) - // The method can be a comma-separated list, in which case, we will try the - // options one by one. Some of them can fail gracefully, and then we can try - // the next. +var wasmBinaryFile = 'DiabloSpawn.wasm'; +if (!isDataURI(wasmBinaryFile)) { + wasmBinaryFile = locateFile(wasmBinaryFile); +} - // inputs - - var method = 'native-wasm'; - - var wasmTextFile = 'DiabloSpawn.wast'; - var wasmBinaryFile = 'DiabloSpawn.wasm'; - var asmjsCodeFile = 'DiabloSpawn.temp.asm.js'; - - if (!isDataURI(wasmTextFile)) { - wasmTextFile = locateFile(wasmTextFile); +function getBinary() { + try { + if (Module['wasmBinary']) { + return new Uint8Array(Module['wasmBinary']); + } + if (readBinary) { + return readBinary(wasmBinaryFile); + } else { + throw "both async and sync fetching of the wasm failed"; + } } - if (!isDataURI(wasmBinaryFile)) { - wasmBinaryFile = locateFile(wasmBinaryFile); + catch (err) { + abort(err); } - if (!isDataURI(asmjsCodeFile)) { - asmjsCodeFile = locateFile(asmjsCodeFile); +} + +function getBinaryPromise() { + // if we don't have the binary yet, and have the Fetch api, use that + // in some environments, like Electron's render process, Fetch api may be present, but have a different context than expected, let's only use it on the Web + if (!Module['wasmBinary'] && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) && typeof fetch === 'function') { + return fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function(response) { + if (!response['ok']) { + throw "failed to load wasm binary file at '" + wasmBinaryFile + "'"; + } + return response['arrayBuffer'](); + }).catch(function () { + return getBinary(); + }); } + // Otherwise, getBinary should be able to get it synchronously + return new Promise(function(resolve, reject) { + resolve(getBinary()); + }); +} - // utilities - var wasmPageSize = 64*1024; +// Create the wasm instance. +// Receives the wasm imports, returns the exports. +function createWasm(env) { + + // prepare imports var info = { - 'global': null, - 'env': null, - 'asm2wasm': asm2wasmImports, - 'parent': Module // Module inside wasm-js.cpp refers to wasm-js.cpp; this allows access to the outside program. + 'env': env + , + 'global': { + 'NaN': NaN, + 'Infinity': Infinity + }, + 'global.Math': Math, + 'asm2wasm': asm2wasmImports }; - - var exports = null; + // Load the wasm module and create an instance of using native support in the JS engine. + // handle a generated wasm instance, receiving its exports and + // performing other necessary setup + function receiveInstance(instance, module) { + var exports = instance.exports; + Module['asm'] = exports; + removeRunDependency('wasm-instantiate'); + } + addRunDependency('wasm-instantiate'); - function mergeMemory(newBuffer) { - // The wasm instance creates its memory. But static init code might have written to - // buffer already, including the mem init file, and we must copy it over in a proper merge. - // TODO: avoid this copy, by avoiding such static init writes - // TODO: in shorter term, just copy up to the last static init write - var oldBuffer = Module['buffer']; - if (newBuffer.byteLength < oldBuffer.byteLength) { - err('the new buffer in mergeMemory is smaller than the previous one. in native wasm, we should grow memory here'); - } - var oldView = new Int8Array(oldBuffer); - var newView = new Int8Array(newBuffer); - - - newView.set(oldView); - updateGlobalBuffer(newBuffer); - updateGlobalBufferViews(); + function receiveInstantiatedSource(output) { + // 'output' is a WebAssemblyInstantiatedSource object which has both the module and instance. + // receiveInstance() will swap in the exports (to Module.asm) so they can be called + // TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193, the above line no longer optimizes out down to the following line. + // When the regression is fixed, can restore the above USE_PTHREADS-enabled path. + receiveInstance(output['instance']); } - function fixImports(imports) { - return imports; - } - function getBinary() { - try { - if (Module['wasmBinary']) { - return new Uint8Array(Module['wasmBinary']); - } - if (Module['readBinary']) { - return Module['readBinary'](wasmBinaryFile); - } else { - throw "both async and sync fetching of the wasm failed"; - } - } - catch (err) { - abort(err); - } - } - - function getBinaryPromise() { - // if we don't have the binary yet, and have the Fetch api, use that - // in some environments, like Electron's render process, Fetch api may be present, but have a different context than expected, let's only use it on the Web - if (!Module['wasmBinary'] && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) && typeof fetch === 'function') { - return fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function(response) { - if (!response['ok']) { - throw "failed to load wasm binary file at '" + wasmBinaryFile + "'"; - } - return response['arrayBuffer'](); - }).catch(function () { - return getBinary(); - }); - } - // Otherwise, getBinary should be able to get it synchronously - return new Promise(function(resolve, reject) { - resolve(getBinary()); + function instantiateArrayBuffer(receiver) { + return getBinaryPromise().then(function(binary) { + return WebAssembly.instantiate(binary, info); + }).then(receiver, function(reason) { + err('failed to asynchronously prepare wasm: ' + reason); + abort(reason); }); } - // do-method functions - - - function doNativeWasm(global, env, providedBuffer) { - if (typeof WebAssembly !== 'object') { - err('no native wasm support detected'); - return false; - } - // prepare memory import - if (!(Module['wasmMemory'] instanceof WebAssembly.Memory)) { - err('no native wasm Memory in use'); - return false; - } - env['memory'] = Module['wasmMemory']; - // Load the wasm module and create an instance of using native support in the JS engine. - info['global'] = { - 'NaN': NaN, - 'Infinity': Infinity - }; - info['global.Math'] = Math; - info['env'] = env; - // handle a generated wasm instance, receiving its exports and - // performing other necessary setup - function receiveInstance(instance, module) { - exports = instance.exports; - if (exports.memory) mergeMemory(exports.memory); - Module['asm'] = exports; - Module["usingWasm"] = true; - removeRunDependency('wasm-instantiate'); - } - addRunDependency('wasm-instantiate'); - - // User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback - // to manually instantiate the Wasm module themselves. This allows pages to run the instantiation parallel - // to any other async startup actions they are performing. - if (Module['instantiateWasm']) { - try { - return Module['instantiateWasm'](info, receiveInstance); - } catch(e) { - err('Module.instantiateWasm callback failed with error: ' + e); - return false; - } - } - - function receiveInstantiatedSource(output) { - // 'output' is a WebAssemblyInstantiatedSource object which has both the module and instance. - // receiveInstance() will swap in the exports (to Module.asm) so they can be called - receiveInstance(output['instance'], output['module']); - } - function instantiateArrayBuffer(receiver) { - getBinaryPromise().then(function(binary) { - return WebAssembly.instantiate(binary, info); - }).then(receiver).catch(function(reason) { - err('failed to asynchronously prepare wasm: ' + reason); - abort(reason); - }); - } - // Prefer streaming instantiation if available. + // Prefer streaming instantiation if available. + function instantiateAsync() { if (!Module['wasmBinary'] && typeof WebAssembly.instantiateStreaming === 'function' && !isDataURI(wasmBinaryFile) && typeof fetch === 'function') { - WebAssembly.instantiateStreaming(fetch(wasmBinaryFile, { credentials: 'same-origin' }), info) - .then(receiveInstantiatedSource) - .catch(function(reason) { - // We expect the most common failure cause to be a bad MIME type for the binary, - // in which case falling back to ArrayBuffer instantiation should work. - err('wasm streaming compile failed: ' + reason); - err('falling back to ArrayBuffer instantiation'); - instantiateArrayBuffer(receiveInstantiatedSource); - }); + fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function (response) { + return WebAssembly.instantiateStreaming(response, info) + .then(receiveInstantiatedSource, function(reason) { + // We expect the most common failure cause to be a bad MIME type for the binary, + // in which case falling back to ArrayBuffer instantiation should work. + err('wasm streaming compile failed: ' + reason); + err('falling back to ArrayBuffer instantiation'); + instantiateArrayBuffer(receiveInstantiatedSource); + }); + }); } else { - instantiateArrayBuffer(receiveInstantiatedSource); + return instantiateArrayBuffer(receiveInstantiatedSource); + } + } + // User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback + // to manually instantiate the Wasm module themselves. This allows pages to run the instantiation parallel + // to any other async startup actions they are performing. + if (Module['instantiateWasm']) { + try { + var exports = Module['instantiateWasm'](info, receiveInstance); + return exports; + } catch(e) { + err('Module.instantiateWasm callback failed with error: ' + e); + return false; } - return {}; // no exports yet; we'll fill them in later } - - // We may have a preloaded value in Module.asm, save it - Module['asmPreload'] = Module['asm']; - - // Memory growth integration code - - var asmjsReallocBuffer = Module['reallocBuffer']; - - var wasmReallocBuffer = function(size) { - var PAGE_MULTIPLE = Module["usingWasm"] ? WASM_PAGE_SIZE : ASMJS_PAGE_SIZE; // In wasm, heap size must be a multiple of 64KB. In asm.js, they need to be multiples of 16MB. - size = alignUp(size, PAGE_MULTIPLE); // round up to wasm page size - var old = Module['buffer']; - var oldSize = old.byteLength; - if (Module["usingWasm"]) { - // native wasm support - try { - var result = Module['wasmMemory'].grow((size - oldSize) / wasmPageSize); // .grow() takes a delta compared to the previous size - if (result !== (-1 | 0)) { - // success in native wasm memory growth, get the buffer from the memory - return Module['buffer'] = Module['wasmMemory'].buffer; - } else { - return null; - } - } catch(e) { - return null; - } - } - }; - - Module['reallocBuffer'] = function(size) { - if (finalMethod === 'asmjs') { - return asmjsReallocBuffer(size); - } else { - return wasmReallocBuffer(size); - } - }; - - // we may try more than one; this is the final one, that worked and we are using - var finalMethod = ''; - - // Provide an "asm.js function" for the application, called to "link" the asm.js module. We instantiate - // the wasm module at that time, and it receives imports and provides exports and so forth, the app - // doesn't need to care that it is wasm or olyfilled wasm or asm.js. - - Module['asm'] = function(global, env, providedBuffer) { - env = fixImports(env); - - // import table - if (!env['table']) { - var TABLE_SIZE = Module['wasmTableSize']; - if (TABLE_SIZE === undefined) TABLE_SIZE = 1024; // works in binaryen interpreter at least - var MAX_TABLE_SIZE = Module['wasmMaxTableSize']; - if (typeof WebAssembly === 'object' && typeof WebAssembly.Table === 'function') { - if (MAX_TABLE_SIZE !== undefined) { - env['table'] = new WebAssembly.Table({ 'initial': TABLE_SIZE, 'maximum': MAX_TABLE_SIZE, 'element': 'anyfunc' }); - } else { - env['table'] = new WebAssembly.Table({ 'initial': TABLE_SIZE, element: 'anyfunc' }); - } - } else { - env['table'] = new Array(TABLE_SIZE); // works in binaryen interpreter at least - } - Module['wasmTable'] = env['table']; - } - - if (!env['memoryBase']) { - env['memoryBase'] = Module['STATIC_BASE']; // tell the memory segments where to place themselves - } - if (!env['tableBase']) { - env['tableBase'] = 0; // table starts at 0 by default, in dynamic linking this will change - } - - // try the methods. each should return the exports if it succeeded - - var exports; - exports = doNativeWasm(global, env, providedBuffer); - - assert(exports, 'no binaryen method succeeded.'); - - - return exports; - }; - - var methodHandler = Module['asm']; // note our method handler, as we may modify Module['asm'] later + instantiateAsync(); + return {}; // no exports yet; we'll fill them in later } -integrateWasmJS(); +// Provide an "asm.js function" for the application, called to "link" the asm.js module. We instantiate +// the wasm module at that time, and it receives imports and provides exports and so forth, the app +// doesn't need to care that it is wasm or asm.js. + +Module['asm'] = function(global, env, providedBuffer) { + // memory was already allocated (so js could use the buffer) + env['memory'] = wasmMemory + ; + // import table + env['table'] = wasmTable = new WebAssembly.Table({ + 'initial': 1116, + 'maximum': 1116, + 'element': 'anyfunc' + }); + // With the wasm backend __memory_base and __table_base and only needed for + // relocatable output. + env['__memory_base'] = 1024; // tell the memory segments where to place themselves + // table starts at 0 by default (even in dynamic linking, for the main module) + env['__table_base'] = 0; + + var exports = createWasm(env); + return exports; +}; + +// Globals used by JS i64 conversions +var tempDouble; +var tempI64; // === Body === @@ -1707,6 +1639,7 @@ function _api_play_sound(id,volume,pan,loop){ self.DApi.play_sound(id, volume, p function _api_set_cursor(x,y){ self.DApi.set_cursor(x, y); } function _api_set_volume(id,volume){ self.DApi.set_volume(id, volume); } function _api_stop_sound(id){ self.DApi.stop_sound(id); } +function _api_use_websocket(use){ self.DApi.use_websocket(use); } function _api_websocket_closed(){ return self.DApi.websocket_closed(); } function _api_websocket_send(ptr,size){ self.DApi.websocket_send(HEAPU8.subarray(ptr, ptr + size)); } function _exit_error(err){ var end = HEAPU8.indexOf( 0, err ); var text = String.fromCharCode.apply(null, HEAPU8.subarray( err, end )); self.DApi.exit_error( text ); } @@ -1720,10 +1653,8 @@ function _trace_push(ptr){ var end = HEAPU8.indexOf(0, ptr); var text = String.f -STATIC_BASE = GLOBAL_BASE; - -STATICTOP = STATIC_BASE + 1841808; -/* global initializers */ __ATINIT__.push({ func: function() { __GLOBAL__sub_I_msgcmd_cpp() } }, { func: function() { __GLOBAL__sub_I_snet_cpp() } }); +// STATICTOP = STATIC_BASE + 1849904; +/* global initializers */ __ATINIT__.push({ func: function() { globalCtors() } }); @@ -1731,50 +1662,33 @@ STATICTOP = STATIC_BASE + 1841808; -var STATIC_BUMP = 1841808; -Module["STATIC_BASE"] = STATIC_BASE; -Module["STATIC_BUMP"] = STATIC_BUMP; /* no memory initializer */ -var tempDoublePtr = STATICTOP; STATICTOP += 16; +var tempDoublePtr = 1850912 function copyTempFloat(ptr) { // functions, because inlining this code increases code size too much - HEAP8[tempDoublePtr] = HEAP8[ptr]; - HEAP8[tempDoublePtr+1] = HEAP8[ptr+1]; - HEAP8[tempDoublePtr+2] = HEAP8[ptr+2]; - HEAP8[tempDoublePtr+3] = HEAP8[ptr+3]; - } function copyTempDouble(ptr) { - HEAP8[tempDoublePtr] = HEAP8[ptr]; - HEAP8[tempDoublePtr+1] = HEAP8[ptr+1]; - HEAP8[tempDoublePtr+2] = HEAP8[ptr+2]; - HEAP8[tempDoublePtr+3] = HEAP8[ptr+3]; - HEAP8[tempDoublePtr+4] = HEAP8[ptr+4]; - HEAP8[tempDoublePtr+5] = HEAP8[ptr+5]; - HEAP8[tempDoublePtr+6] = HEAP8[ptr+6]; - HEAP8[tempDoublePtr+7] = HEAP8[ptr+7]; - } // {{PRE_LIBRARY}} function ___assert_fail(condition, filename, line, func) { - abort('Assertion failed: ' + Pointer_stringify(condition) + ', at: ' + [filename ? Pointer_stringify(filename) : 'unknown filename', line, func ? Pointer_stringify(func) : 'unknown function']); + abort('Assertion failed: ' + UTF8ToString(condition) + ', at: ' + [filename ? UTF8ToString(filename) : 'unknown filename', line, func ? UTF8ToString(func) : 'unknown function']); } function ___cxa_allocate_exception(size) { @@ -1782,79 +1696,127 @@ function copyTempDouble(ptr) { } - function __ZSt18uncaught_exceptionv() { // std::uncaught_exception() - return !!__ZSt18uncaught_exceptionv.uncaught_exception; + var ___exception_infos={}; + + var ___exception_caught= []; + + function ___exception_addRef(ptr) { + if (!ptr) return; + var info = ___exception_infos[ptr]; + info.refcount++; } - var EXCEPTIONS={last:0,caught:[],infos:{},deAdjust:function (adjusted) { - if (!adjusted || EXCEPTIONS.infos[adjusted]) return adjusted; - for (var key in EXCEPTIONS.infos) { - var ptr = +key; // the iteration key is a string, and if we throw this, it must be an integer as that is what we look for - var info = EXCEPTIONS.infos[ptr]; - if (info.adjusted === adjusted) { + function ___exception_deAdjust(adjusted) { + if (!adjusted || ___exception_infos[adjusted]) return adjusted; + for (var key in ___exception_infos) { + var ptr = +key; // the iteration key is a string, and if we throw this, it must be an integer as that is what we look for + var adj = ___exception_infos[ptr].adjusted; + var len = adj.length; + for (var i = 0; i < len; i++) { + if (adj[i] === adjusted) { return ptr; } } - return adjusted; - },addRef:function (ptr) { - if (!ptr) return; - var info = EXCEPTIONS.infos[ptr]; - info.refcount++; - },decRef:function (ptr) { - if (!ptr) return; - var info = EXCEPTIONS.infos[ptr]; - assert(info.refcount > 0); - info.refcount--; - // A rethrown exception can reach refcount 0; it must not be discarded - // Its next handler will clear the rethrown flag and addRef it, prior to - // final decRef and destruction here - if (info.refcount === 0 && !info.rethrown) { - if (info.destructor) { - Module['dynCall_vi'](info.destructor, ptr); - } - delete EXCEPTIONS.infos[ptr]; - ___cxa_free_exception(ptr); - } - },clearRef:function (ptr) { - if (!ptr) return; - var info = EXCEPTIONS.infos[ptr]; - info.refcount = 0; - }};function ___cxa_begin_catch(ptr) { - var info = EXCEPTIONS.infos[ptr]; + } + return adjusted; + }function ___cxa_begin_catch(ptr) { + var info = ___exception_infos[ptr]; if (info && !info.caught) { info.caught = true; - __ZSt18uncaught_exceptionv.uncaught_exception--; + __ZSt18uncaught_exceptionv.uncaught_exceptions--; } if (info) info.rethrown = false; - EXCEPTIONS.caught.push(ptr); - EXCEPTIONS.addRef(EXCEPTIONS.deAdjust(ptr)); + ___exception_caught.push(ptr); + ___exception_addRef(___exception_deAdjust(ptr)); return ptr; } + var ___exception_last=0; + + function ___cxa_free_exception(ptr) { try { return _free(ptr); - } catch(e) { // XXX FIXME + } catch(e) { } - }function ___cxa_end_catch() { + }function ___exception_decRef(ptr) { + if (!ptr) return; + var info = ___exception_infos[ptr]; + info.refcount--; + // A rethrown exception can reach refcount 0; it must not be discarded + // Its next handler will clear the rethrown flag and addRef it, prior to + // final decRef and destruction here + if (info.refcount === 0 && !info.rethrown) { + if (info.destructor) { + Module['dynCall_vi'](info.destructor, ptr); + } + delete ___exception_infos[ptr]; + ___cxa_free_exception(ptr); + } + } + + function ___cxa_end_catch() { // Clear state flag. - Module['setThrew'](0); + _setThrew(0); // Call destructor if one is registered then clear it. - var ptr = EXCEPTIONS.caught.pop(); + var ptr = ___exception_caught.pop(); if (ptr) { - EXCEPTIONS.decRef(EXCEPTIONS.deAdjust(ptr)); - EXCEPTIONS.last = 0; // XXX in decRef? + ___exception_decRef(___exception_deAdjust(ptr)); + ___exception_last = 0; // XXX in decRef? } } - function ___cxa_find_matching_catch_2() { - return ___cxa_find_matching_catch.apply(null, arguments); + + + function ___resumeException(ptr) { + if (!___exception_last) { ___exception_last = ptr; } + throw ptr; + }function ___cxa_find_matching_catch() { + var thrown = ___exception_last; + if (!thrown) { + // just pass through the null ptr + return ((setTempRet0(0),0)|0); + } + var info = ___exception_infos[thrown]; + var throwntype = info.type; + if (!throwntype) { + // just pass through the thrown ptr + return ((setTempRet0(0),thrown)|0); + } + var typeArray = Array.prototype.slice.call(arguments); + + var pointer = ___cxa_is_pointer_type(throwntype); + // can_catch receives a **, add indirection + var buffer = 1850880; + HEAP32[((buffer)>>2)]=thrown; + thrown = buffer; + // The different catch blocks are denoted by different types. + // Due to inheritance, those types may not precisely match the + // type of the thrown object. Find one which matches, and + // return the type of the catch block which should be called. + for (var i = 0; i < typeArray.length; i++) { + if (typeArray[i] && ___cxa_can_catch(typeArray[i], throwntype, thrown)) { + thrown = HEAP32[((thrown)>>2)]; // undo indirection + info.adjusted.push(thrown); + return ((setTempRet0(typeArray[i]),thrown)|0); } + } + // Shouldn't happen unless we have bogus data in typeArray + // or encounter a type for which emscripten doesn't have suitable + // typeinfo defined. Best-efforts match just in case. + thrown = HEAP32[((thrown)>>2)]; // undo indirection + return ((setTempRet0(throwntype),thrown)|0); + } + Module["___cxa_find_matching_catch"] = ___cxa_find_matching_catch;function ___cxa_find_matching_catch_2(a0,a1 + /*``*/) { + return ___cxa_find_matching_catch(a0,a1); + } - function ___cxa_find_matching_catch_3() { - return ___cxa_find_matching_catch.apply(null, arguments); - } + function ___cxa_find_matching_catch_3(a0,a1,a2 + /*``*/) { + return ___cxa_find_matching_catch(a0,a1,a2); + } function ___cxa_get_exception_ptr(ptr) { @@ -1867,65 +1829,29 @@ function copyTempDouble(ptr) { throw 'Pure virtual function called!'; } - - - function ___resumeException(ptr) { - if (!EXCEPTIONS.last) { EXCEPTIONS.last = ptr; } - throw ptr; - }function ___cxa_find_matching_catch() { - var thrown = EXCEPTIONS.last; - if (!thrown) { - // just pass through the null ptr - return ((setTempRet0(0),0)|0); - } - var info = EXCEPTIONS.infos[thrown]; - var throwntype = info.type; - if (!throwntype) { - // just pass through the thrown ptr - return ((setTempRet0(0),thrown)|0); - } - var typeArray = Array.prototype.slice.call(arguments); - - var pointer = Module['___cxa_is_pointer_type'](throwntype); - // can_catch receives a **, add indirection - if (!___cxa_find_matching_catch.buffer) ___cxa_find_matching_catch.buffer = _malloc(4); - HEAP32[((___cxa_find_matching_catch.buffer)>>2)]=thrown; - thrown = ___cxa_find_matching_catch.buffer; - // The different catch blocks are denoted by different types. - // Due to inheritance, those types may not precisely match the - // type of the thrown object. Find one which matches, and - // return the type of the catch block which should be called. - for (var i = 0; i < typeArray.length; i++) { - if (typeArray[i] && Module['___cxa_can_catch'](typeArray[i], throwntype, thrown)) { - thrown = HEAP32[((thrown)>>2)]; // undo indirection - info.adjusted = thrown; - return ((setTempRet0(typeArray[i]),thrown)|0); - } - } - // Shouldn't happen unless we have bogus data in typeArray - // or encounter a type for which emscripten doesn't have suitable - // typeinfo defined. Best-efforts match just in case. - thrown = HEAP32[((thrown)>>2)]; // undo indirection - return ((setTempRet0(throwntype),thrown)|0); - }function ___cxa_throw(ptr, type, destructor) { - EXCEPTIONS.infos[ptr] = { + function ___cxa_throw(ptr, type, destructor) { + ___exception_infos[ptr] = { ptr: ptr, - adjusted: ptr, + adjusted: [ptr], type: type, destructor: destructor, refcount: 0, caught: false, rethrown: false }; - EXCEPTIONS.last = ptr; + ___exception_last = ptr; if (!("uncaught_exception" in __ZSt18uncaught_exceptionv)) { - __ZSt18uncaught_exceptionv.uncaught_exception = 1; + __ZSt18uncaught_exceptionv.uncaught_exceptions = 1; } else { - __ZSt18uncaught_exceptionv.uncaught_exception++; + __ZSt18uncaught_exceptionv.uncaught_exceptions++; } throw ptr; } + function ___cxa_uncaught_exceptions() { + return __ZSt18uncaught_exceptionv.uncaught_exceptions; + } + function ___gxx_personality_v0() { } @@ -1933,29 +1859,96 @@ function copyTempDouble(ptr) { - var SYSCALLS={varargs:0,get:function (varargs) { + + var PATH={splitPath:function (filename) { + var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; + return splitPathRe.exec(filename).slice(1); + },normalizeArray:function (parts, allowAboveRoot) { + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = parts.length - 1; i >= 0; i--) { + var last = parts[i]; + if (last === '.') { + parts.splice(i, 1); + } else if (last === '..') { + parts.splice(i, 1); + up++; + } else if (up) { + parts.splice(i, 1); + up--; + } + } + // if the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up; up--) { + parts.unshift('..'); + } + } + return parts; + },normalize:function (path) { + var isAbsolute = path.charAt(0) === '/', + trailingSlash = path.substr(-1) === '/'; + // Normalize the path + path = PATH.normalizeArray(path.split('/').filter(function(p) { + return !!p; + }), !isAbsolute).join('/'); + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + return (isAbsolute ? '/' : '') + path; + },dirname:function (path) { + var result = PATH.splitPath(path), + root = result[0], + dir = result[1]; + if (!root && !dir) { + // No dirname whatsoever + return '.'; + } + if (dir) { + // It has a dirname, strip trailing slash + dir = dir.substr(0, dir.length - 1); + } + return root + dir; + },basename:function (path) { + // EMSCRIPTEN return '/'' for '/', not an empty string + if (path === '/') return '/'; + var lastSlash = path.lastIndexOf('/'); + if (lastSlash === -1) return path; + return path.substr(lastSlash+1); + },extname:function (path) { + return PATH.splitPath(path)[3]; + },join:function () { + var paths = Array.prototype.slice.call(arguments, 0); + return PATH.normalize(paths.join('/')); + },join2:function (l, r) { + return PATH.normalize(l + '/' + r); + }};var SYSCALLS={buffers:[null,[],[]],printChar:function (stream, curr) { + var buffer = SYSCALLS.buffers[stream]; + if (curr === 0 || curr === 10) { + (stream === 1 ? out : err)(UTF8ArrayToString(buffer, 0)); + buffer.length = 0; + } else { + buffer.push(curr); + } + },varargs:0,get:function (varargs) { SYSCALLS.varargs += 4; var ret = HEAP32[(((SYSCALLS.varargs)-(4))>>2)]; return ret; },getStr:function () { - var ret = Pointer_stringify(SYSCALLS.get()); + var ret = UTF8ToString(SYSCALLS.get()); return ret; },get64:function () { var low = SYSCALLS.get(), high = SYSCALLS.get(); - if (low >= 0) assert(high === 0); - else assert(high === -1); return low; },getZero:function () { - assert(SYSCALLS.get() === 0); + SYSCALLS.get(); }};function ___syscall140(which, varargs) {SYSCALLS.varargs = varargs; try { // llseek var stream = SYSCALLS.getStreamFromFD(), offset_high = SYSCALLS.get(), offset_low = SYSCALLS.get(), result = SYSCALLS.get(), whence = SYSCALLS.get(); - // NOTE: offset_high is unused - Emscripten's off_t is 32-bit - var offset = offset_low; - FS.llseek(stream, offset, whence); - HEAP32[((result)>>2)]=stream.position; - if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null; // reset readdir state return 0; } catch (e) { if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e); @@ -1968,35 +1961,20 @@ function copyTempDouble(ptr) { // flush anything remaining in the buffers during shutdown var fflush = Module["_fflush"]; if (fflush) fflush(0); - var printChar = ___syscall146.printChar; - if (!printChar) return; - var buffers = ___syscall146.buffers; - if (buffers[1].length) printChar(1, 10); - if (buffers[2].length) printChar(2, 10); + var buffers = SYSCALLS.buffers; + if (buffers[1].length) SYSCALLS.printChar(1, 10); + if (buffers[2].length) SYSCALLS.printChar(2, 10); }function ___syscall146(which, varargs) {SYSCALLS.varargs = varargs; try { // writev - // hack to support printf in NO_FILESYSTEM + // hack to support printf in SYSCALLS_REQUIRE_FILESYSTEM=0 var stream = SYSCALLS.get(), iov = SYSCALLS.get(), iovcnt = SYSCALLS.get(); var ret = 0; - if (!___syscall146.buffers) { - ___syscall146.buffers = [null, [], []]; // 1 => stdout, 2 => stderr - ___syscall146.printChar = function(stream, curr) { - var buffer = ___syscall146.buffers[stream]; - assert(buffer); - if (curr === 0 || curr === 10) { - (stream === 1 ? out : err)(UTF8ArrayToString(buffer, 0)); - buffer.length = 0; - } else { - buffer.push(curr); - } - }; - } for (var i = 0; i < iovcnt; i++) { var ptr = HEAP32[(((iov)+(i*8))>>2)]; var len = HEAP32[(((iov)+(i*8 + 4))>>2)]; for (var j = 0; j < len; j++) { - ___syscall146.printChar(stream, HEAPU8[ptr+j]); + SYSCALLS.printChar(stream, HEAPU8[ptr+j]); } ret += len; } @@ -2021,7 +1999,6 @@ function copyTempDouble(ptr) { try { // close var stream = SYSCALLS.getStreamFromFD(); - FS.close(stream); return 0; } catch (e) { if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e); @@ -2037,21 +2014,18 @@ function copyTempDouble(ptr) { var _emscripten_asm_const_int=true; - - function __exit(status) { + function _emscripten_get_heap_size() { + return HEAP8.length; + } + + function _exit(status) { // void _exit(int status); // http://pubs.opengroup.org/onlinepubs/000095399/functions/exit.html exit(status); - }function _exit(status) { - __exit(status); } - var _llvm_ceil_f32=Math_ceil; - - var _llvm_ctlz_i32=true; - function _llvm_eh_typeid_for(type) { return type; } @@ -2063,51 +2037,85 @@ function copyTempDouble(ptr) { function _emscripten_memcpy_big(dest, src, num) { HEAPU8.set(HEAPU8.subarray(src, src+num), dest); - return dest; - } - + } + - - var PTHREAD_SPECIFIC={};function _pthread_getspecific(key) { - return PTHREAD_SPECIFIC[key] || 0; - } - - - var PTHREAD_SPECIFIC_NEXT_KEY=1; - - var ERRNO_CODES={EPERM:1,ENOENT:2,ESRCH:3,EINTR:4,EIO:5,ENXIO:6,E2BIG:7,ENOEXEC:8,EBADF:9,ECHILD:10,EAGAIN:11,EWOULDBLOCK:11,ENOMEM:12,EACCES:13,EFAULT:14,ENOTBLK:15,EBUSY:16,EEXIST:17,EXDEV:18,ENODEV:19,ENOTDIR:20,EISDIR:21,EINVAL:22,ENFILE:23,EMFILE:24,ENOTTY:25,ETXTBSY:26,EFBIG:27,ENOSPC:28,ESPIPE:29,EROFS:30,EMLINK:31,EPIPE:32,EDOM:33,ERANGE:34,ENOMSG:42,EIDRM:43,ECHRNG:44,EL2NSYNC:45,EL3HLT:46,EL3RST:47,ELNRNG:48,EUNATCH:49,ENOCSI:50,EL2HLT:51,EDEADLK:35,ENOLCK:37,EBADE:52,EBADR:53,EXFULL:54,ENOANO:55,EBADRQC:56,EBADSLT:57,EDEADLOCK:35,EBFONT:59,ENOSTR:60,ENODATA:61,ETIME:62,ENOSR:63,ENONET:64,ENOPKG:65,EREMOTE:66,ENOLINK:67,EADV:68,ESRMNT:69,ECOMM:70,EPROTO:71,EMULTIHOP:72,EDOTDOT:73,EBADMSG:74,ENOTUNIQ:76,EBADFD:77,EREMCHG:78,ELIBACC:79,ELIBBAD:80,ELIBSCN:81,ELIBMAX:82,ELIBEXEC:83,ENOSYS:38,ENOTEMPTY:39,ENAMETOOLONG:36,ELOOP:40,EOPNOTSUPP:95,EPFNOSUPPORT:96,ECONNRESET:104,ENOBUFS:105,EAFNOSUPPORT:97,EPROTOTYPE:91,ENOTSOCK:88,ENOPROTOOPT:92,ESHUTDOWN:108,ECONNREFUSED:111,EADDRINUSE:98,ECONNABORTED:103,ENETUNREACH:101,ENETDOWN:100,ETIMEDOUT:110,EHOSTDOWN:112,EHOSTUNREACH:113,EINPROGRESS:115,EALREADY:114,EDESTADDRREQ:89,EMSGSIZE:90,EPROTONOSUPPORT:93,ESOCKTNOSUPPORT:94,EADDRNOTAVAIL:99,ENETRESET:102,EISCONN:106,ENOTCONN:107,ETOOMANYREFS:109,EUSERS:87,EDQUOT:122,ESTALE:116,ENOTSUP:95,ENOMEDIUM:123,EILSEQ:84,EOVERFLOW:75,ECANCELED:125,ENOTRECOVERABLE:131,EOWNERDEAD:130,ESTRPIPE:86};function _pthread_key_create(key, destructor) { - if (key == 0) { - return ERRNO_CODES.EINVAL; - } - HEAP32[((key)>>2)]=PTHREAD_SPECIFIC_NEXT_KEY; - // values start at 0 - PTHREAD_SPECIFIC[PTHREAD_SPECIFIC_NEXT_KEY] = 0; - PTHREAD_SPECIFIC_NEXT_KEY++; - return 0; - } - - function _pthread_once(ptr, func) { - if (!_pthread_once.seen) _pthread_once.seen = {}; - if (ptr in _pthread_once.seen) return; - Module['dynCall_v'](func); - _pthread_once.seen[ptr] = 1; - } - - function _pthread_setspecific(key, value) { - if (!(key in PTHREAD_SPECIFIC)) { - return ERRNO_CODES.EINVAL; - } - PTHREAD_SPECIFIC[key] = value; - return 0; - } + function ___setErrNo(value) { if (Module['___errno_location']) HEAP32[((Module['___errno_location']())>>2)]=value; return value; + } + + + function abortOnCannotGrowMemory(requestedSize) { + abort('OOM'); + } + + function emscripten_realloc_buffer(size) { + var PAGE_MULTIPLE = 65536; + size = alignUp(size, PAGE_MULTIPLE); // round up to wasm page size + var oldSize = buffer.byteLength; + // native wasm support + // note that this is *not* threadsafe. multiple threads can call .grow(), and each + // presents a delta, so in theory we may over-allocate here (e.g. if two threads + // ask to grow from 256MB to 512MB, we get 2 requests to add +256MB, and may end + // up growing to 768MB (even though we may have been able to make do with 512MB). + // TODO: consider decreasing the step sizes in emscripten_resize_heap + try { + var result = wasmMemory.grow((size - oldSize) / 65536); // .grow() takes a delta compared to the previous size + if (result !== (-1 | 0)) { + // success in native wasm memory growth, get the buffer from the memory + buffer = wasmMemory.buffer; + return true; + } else { + return false; + } + } catch(e) { + return false; + } + }function _emscripten_resize_heap(requestedSize) { + var oldSize = _emscripten_get_heap_size(); + // With pthreads, races can happen (another thread might increase the size in between), so return a failure, and let the caller retry. + + + var PAGE_MULTIPLE = 65536; + var LIMIT = 2147483648 - PAGE_MULTIPLE; // We can do one page short of 2GB as theoretical maximum. + + if (requestedSize > LIMIT) { + return false; + } + + var MIN_TOTAL_MEMORY = 16777216; + var newSize = Math.max(oldSize, MIN_TOTAL_MEMORY); // So the loop below will not be infinite, and minimum asm.js memory size is 16MB. + + // TODO: see realloc_buffer - for PTHREADS we may want to decrease these jumps + while (newSize < requestedSize) { // Keep incrementing the heap size as long as it's less than what is requested. + if (newSize <= 536870912) { + newSize = alignUp(2 * newSize, PAGE_MULTIPLE); // Simple heuristic: double until 1GB... + } else { + // ..., but after that, add smaller increments towards 2GB, which we cannot reach + newSize = Math.min(alignUp((3 * newSize + 2147483648) / 4, PAGE_MULTIPLE), LIMIT); + } + + } + + + + + if (!emscripten_realloc_buffer(newSize)) { + return false; + } + + updateGlobalBufferViews(); + + + + return true; } function _time(ptr) { @@ -2117,20 +2125,13 @@ function copyTempDouble(ptr) { } return ret; } -DYNAMICTOP_PTR = staticAlloc(4); - -STACK_BASE = STACKTOP = alignMemory(STATICTOP); - -STACK_MAX = STACK_BASE + TOTAL_STACK; - -DYNAMIC_BASE = alignMemory(STACK_MAX); - -HEAP32[DYNAMICTOP_PTR>>2] = DYNAMIC_BASE; - -staticSealed = true; // seal the static portion of memory - var ASSERTIONS = false; +// Copyright 2017 The Emscripten Authors. All rights reserved. +// Emscripten is available under two separate licenses, the MIT license and the +// University of Illinois/NCSA Open Source License. Both these licenses can be +// found in the LICENSE file. + /** @type {function(string, boolean=, number=)} */ function intArrayFromString(stringy, dontAddNull, length) { var len = length > 0 ? length : lengthBytesUTF8(stringy)+1; @@ -2156,303 +2157,582 @@ function intArrayToString(array) { } +// ASM_LIBRARY EXTERN PRIMITIVES: Int8Array,Int32Array -Module['wasmTableSize'] = 1114; - -Module['wasmMaxTableSize'] = 1114; function invoke_i(index) { var sp = stackSave(); try { - return Module["dynCall_i"](index); + return dynCall_i(index); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_ii(index,a1) { var sp = stackSave(); try { - return Module["dynCall_ii"](index,a1); + return dynCall_ii(index,a1); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_iii(index,a1,a2) { var sp = stackSave(); try { - return Module["dynCall_iii"](index,a1,a2); + return dynCall_iii(index,a1,a2); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_iiii(index,a1,a2,a3) { var sp = stackSave(); try { - return Module["dynCall_iiii"](index,a1,a2,a3); + return dynCall_iiii(index,a1,a2,a3); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_iiiii(index,a1,a2,a3,a4) { var sp = stackSave(); try { - return Module["dynCall_iiiii"](index,a1,a2,a3,a4); + return dynCall_iiiii(index,a1,a2,a3,a4); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_iiiiii(index,a1,a2,a3,a4,a5) { var sp = stackSave(); try { - return Module["dynCall_iiiiii"](index,a1,a2,a3,a4,a5); + return dynCall_iiiiii(index,a1,a2,a3,a4,a5); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_ji(index,a1) { var sp = stackSave(); try { - return Module["dynCall_ji"](index,a1); + return dynCall_ji(index,a1); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_v(index) { var sp = stackSave(); try { - Module["dynCall_v"](index); + dynCall_v(index); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_vi(index,a1) { var sp = stackSave(); try { - Module["dynCall_vi"](index,a1); + dynCall_vi(index,a1); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_vii(index,a1,a2) { var sp = stackSave(); try { - Module["dynCall_vii"](index,a1,a2); + dynCall_vii(index,a1,a2); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_viii(index,a1,a2,a3) { var sp = stackSave(); try { - Module["dynCall_viii"](index,a1,a2,a3); + dynCall_viii(index,a1,a2,a3); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_viiii(index,a1,a2,a3,a4) { var sp = stackSave(); try { - Module["dynCall_viiii"](index,a1,a2,a3,a4); + dynCall_viiii(index,a1,a2,a3,a4); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_viiiii(index,a1,a2,a3,a4,a5) { var sp = stackSave(); try { - Module["dynCall_viiiii"](index,a1,a2,a3,a4,a5); + dynCall_viiiii(index,a1,a2,a3,a4,a5); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); - } -} - -function invoke_viiiiii(index,a1,a2,a3,a4,a5,a6) { - var sp = stackSave(); - try { - Module["dynCall_viiiiii"](index,a1,a2,a3,a4,a5,a6); - } catch(e) { - stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7) { var sp = stackSave(); try { - Module["dynCall_viiiiiii"](index,a1,a2,a3,a4,a5,a6,a7); + dynCall_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); - } -} - -function invoke_viiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9) { - var sp = stackSave(); - try { - Module["dynCall_viiiiiiiii"](index,a1,a2,a3,a4,a5,a6,a7,a8,a9); - } catch(e) { - stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); - } -} - -function invoke_viiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) { - var sp = stackSave(); - try { - Module["dynCall_viiiiiiiiii"](index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10); - } catch(e) { - stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_viij(index,a1,a2,a3,a4) { var sp = stackSave(); try { - Module["dynCall_viij"](index,a1,a2,a3,a4); + dynCall_viij(index,a1,a2,a3,a4); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } function invoke_viji(index,a1,a2,a3,a4) { var sp = stackSave(); try { - Module["dynCall_viji"](index,a1,a2,a3,a4); + dynCall_viji(index,a1,a2,a3,a4); } catch(e) { stackRestore(sp); - if (typeof e !== 'number' && e !== 'longjmp') throw e; - Module["setThrew"](1, 0); + if (e !== e+0 && e !== 'longjmp') throw e; + _setThrew(1, 0); } } -Module.asmGlobalArg = {}; +var asmGlobalArg = {}; -Module.asmLibraryArg = { "abort": abort, "assert": assert, "enlargeMemory": enlargeMemory, "getTotalMemory": getTotalMemory, "abortOnCannotGrowMemory": abortOnCannotGrowMemory, "invoke_i": invoke_i, "invoke_ii": invoke_ii, "invoke_iii": invoke_iii, "invoke_iiii": invoke_iiii, "invoke_iiiii": invoke_iiiii, "invoke_iiiiii": invoke_iiiiii, "invoke_ji": invoke_ji, "invoke_v": invoke_v, "invoke_vi": invoke_vi, "invoke_vii": invoke_vii, "invoke_viii": invoke_viii, "invoke_viiii": invoke_viiii, "invoke_viiiii": invoke_viiiii, "invoke_viiiiii": invoke_viiiiii, "invoke_viiiiiii": invoke_viiiiiii, "invoke_viiiiiiiii": invoke_viiiiiiiii, "invoke_viiiiiiiiii": invoke_viiiiiiiiii, "invoke_viij": invoke_viij, "invoke_viji": invoke_viji, "__ZSt18uncaught_exceptionv": __ZSt18uncaught_exceptionv, "___assert_fail": ___assert_fail, "___cxa_allocate_exception": ___cxa_allocate_exception, "___cxa_begin_catch": ___cxa_begin_catch, "___cxa_end_catch": ___cxa_end_catch, "___cxa_find_matching_catch": ___cxa_find_matching_catch, "___cxa_find_matching_catch_2": ___cxa_find_matching_catch_2, "___cxa_find_matching_catch_3": ___cxa_find_matching_catch_3, "___cxa_free_exception": ___cxa_free_exception, "___cxa_get_exception_ptr": ___cxa_get_exception_ptr, "___cxa_pure_virtual": ___cxa_pure_virtual, "___cxa_throw": ___cxa_throw, "___gxx_personality_v0": ___gxx_personality_v0, "___lock": ___lock, "___resumeException": ___resumeException, "___setErrNo": ___setErrNo, "___syscall140": ___syscall140, "___syscall146": ___syscall146, "___syscall54": ___syscall54, "___syscall6": ___syscall6, "___unlock": ___unlock, "__api_close_keyboard": __api_close_keyboard, "__api_open_keyboard": __api_open_keyboard, "__exit": __exit, "_abort": _abort, "_api_create_sound": _api_create_sound, "_api_create_sound_float": _api_create_sound_float, "_api_delete_sound": _api_delete_sound, "_api_draw_begin": _api_draw_begin, "_api_draw_belt": _api_draw_belt, "_api_draw_blit": _api_draw_blit, "_api_draw_clip_text": _api_draw_clip_text, "_api_draw_end": _api_draw_end, "_api_draw_text": _api_draw_text, "_api_duplicate_sound": _api_duplicate_sound, "_api_exit_game": _api_exit_game, "_api_play_sound": _api_play_sound, "_api_set_cursor": _api_set_cursor, "_api_set_volume": _api_set_volume, "_api_stop_sound": _api_stop_sound, "_api_websocket_closed": _api_websocket_closed, "_api_websocket_send": _api_websocket_send, "_emscripten_asm_const_ii": _emscripten_asm_const_ii, "_emscripten_memcpy_big": _emscripten_memcpy_big, "_exit": _exit, "_exit_error": _exit_error, "_get_file_contents": _get_file_contents, "_get_file_size": _get_file_size, "_llvm_ceil_f32": _llvm_ceil_f32, "_llvm_eh_typeid_for": _llvm_eh_typeid_for, "_llvm_trap": _llvm_trap, "_pthread_getspecific": _pthread_getspecific, "_pthread_key_create": _pthread_key_create, "_pthread_once": _pthread_once, "_pthread_setspecific": _pthread_setspecific, "_put_file_contents": _put_file_contents, "_remove_file": _remove_file, "_show_alert": _show_alert, "_time": _time, "_trace_pop": _trace_pop, "_trace_push": _trace_push, "flush_NO_FILESYSTEM": flush_NO_FILESYSTEM, "DYNAMICTOP_PTR": DYNAMICTOP_PTR, "tempDoublePtr": tempDoublePtr, "ABORT": ABORT, "STACKTOP": STACKTOP, "STACK_MAX": STACK_MAX }; +var asmLibraryArg = { + "abort": abort, + "setTempRet0": setTempRet0, + "getTempRet0": getTempRet0, + "invoke_i": invoke_i, + "invoke_ii": invoke_ii, + "invoke_iii": invoke_iii, + "invoke_iiii": invoke_iiii, + "invoke_iiiii": invoke_iiiii, + "invoke_iiiiii": invoke_iiiiii, + "invoke_ji": invoke_ji, + "invoke_v": invoke_v, + "invoke_vi": invoke_vi, + "invoke_vii": invoke_vii, + "invoke_viii": invoke_viii, + "invoke_viiii": invoke_viiii, + "invoke_viiiii": invoke_viiiii, + "invoke_viiiiiii": invoke_viiiiiii, + "invoke_viij": invoke_viij, + "invoke_viji": invoke_viji, + "___assert_fail": ___assert_fail, + "___cxa_allocate_exception": ___cxa_allocate_exception, + "___cxa_begin_catch": ___cxa_begin_catch, + "___cxa_end_catch": ___cxa_end_catch, + "___cxa_find_matching_catch": ___cxa_find_matching_catch, + "___cxa_find_matching_catch_2": ___cxa_find_matching_catch_2, + "___cxa_find_matching_catch_3": ___cxa_find_matching_catch_3, + "___cxa_free_exception": ___cxa_free_exception, + "___cxa_get_exception_ptr": ___cxa_get_exception_ptr, + "___cxa_pure_virtual": ___cxa_pure_virtual, + "___cxa_throw": ___cxa_throw, + "___cxa_uncaught_exceptions": ___cxa_uncaught_exceptions, + "___exception_addRef": ___exception_addRef, + "___exception_deAdjust": ___exception_deAdjust, + "___exception_decRef": ___exception_decRef, + "___gxx_personality_v0": ___gxx_personality_v0, + "___lock": ___lock, + "___resumeException": ___resumeException, + "___setErrNo": ___setErrNo, + "___syscall140": ___syscall140, + "___syscall146": ___syscall146, + "___syscall54": ___syscall54, + "___syscall6": ___syscall6, + "___unlock": ___unlock, + "__api_close_keyboard": __api_close_keyboard, + "__api_open_keyboard": __api_open_keyboard, + "_abort": _abort, + "_api_create_sound": _api_create_sound, + "_api_create_sound_float": _api_create_sound_float, + "_api_delete_sound": _api_delete_sound, + "_api_draw_begin": _api_draw_begin, + "_api_draw_belt": _api_draw_belt, + "_api_draw_blit": _api_draw_blit, + "_api_draw_clip_text": _api_draw_clip_text, + "_api_draw_end": _api_draw_end, + "_api_draw_text": _api_draw_text, + "_api_duplicate_sound": _api_duplicate_sound, + "_api_exit_game": _api_exit_game, + "_api_play_sound": _api_play_sound, + "_api_set_cursor": _api_set_cursor, + "_api_set_volume": _api_set_volume, + "_api_stop_sound": _api_stop_sound, + "_api_use_websocket": _api_use_websocket, + "_api_websocket_closed": _api_websocket_closed, + "_api_websocket_send": _api_websocket_send, + "_emscripten_asm_const_ii": _emscripten_asm_const_ii, + "_emscripten_get_heap_size": _emscripten_get_heap_size, + "_emscripten_memcpy_big": _emscripten_memcpy_big, + "_emscripten_resize_heap": _emscripten_resize_heap, + "_exit": _exit, + "_exit_error": _exit_error, + "_get_file_contents": _get_file_contents, + "_get_file_size": _get_file_size, + "_llvm_eh_typeid_for": _llvm_eh_typeid_for, + "_llvm_trap": _llvm_trap, + "_put_file_contents": _put_file_contents, + "_remove_file": _remove_file, + "_show_alert": _show_alert, + "_time": _time, + "_trace_pop": _trace_pop, + "_trace_push": _trace_push, + "abortOnCannotGrowMemory": abortOnCannotGrowMemory, + "emscripten_realloc_buffer": emscripten_realloc_buffer, + "flush_NO_FILESYSTEM": flush_NO_FILESYSTEM, + "tempDoublePtr": tempDoublePtr, + "DYNAMICTOP_PTR": DYNAMICTOP_PTR +}; // EMSCRIPTEN_START_ASM var asm =Module["asm"]// EMSCRIPTEN_END_ASM -(Module.asmGlobalArg, Module.asmLibraryArg, buffer); +(asmGlobalArg, asmLibraryArg, buffer); Module["asm"] = asm; -var _DApi_AllocPacket = Module["_DApi_AllocPacket"] = function() { return Module["asm"]["_DApi_AllocPacket"].apply(null, arguments) }; -var _DApi_Char = Module["_DApi_Char"] = function() { return Module["asm"]["_DApi_Char"].apply(null, arguments) }; -var _DApi_Init = Module["_DApi_Init"] = function() { return Module["asm"]["_DApi_Init"].apply(null, arguments) }; -var _DApi_Key = Module["_DApi_Key"] = function() { return Module["asm"]["_DApi_Key"].apply(null, arguments) }; -var _DApi_Mouse = Module["_DApi_Mouse"] = function() { return Module["asm"]["_DApi_Mouse"].apply(null, arguments) }; -var _DApi_Render = Module["_DApi_Render"] = function() { return Module["asm"]["_DApi_Render"].apply(null, arguments) }; -var _DApi_SyncText = Module["_DApi_SyncText"] = function() { return Module["asm"]["_DApi_SyncText"].apply(null, arguments) }; -var _DApi_SyncTextPtr = Module["_DApi_SyncTextPtr"] = function() { return Module["asm"]["_DApi_SyncTextPtr"].apply(null, arguments) }; -var _SNet_InitWebsocket = Module["_SNet_InitWebsocket"] = function() { return Module["asm"]["_SNet_InitWebsocket"].apply(null, arguments) }; -var __GLOBAL__sub_I_msgcmd_cpp = Module["__GLOBAL__sub_I_msgcmd_cpp"] = function() { return Module["asm"]["__GLOBAL__sub_I_msgcmd_cpp"].apply(null, arguments) }; -var __GLOBAL__sub_I_snet_cpp = Module["__GLOBAL__sub_I_snet_cpp"] = function() { return Module["asm"]["__GLOBAL__sub_I_snet_cpp"].apply(null, arguments) }; -var ___cxa_can_catch = Module["___cxa_can_catch"] = function() { return Module["asm"]["___cxa_can_catch"].apply(null, arguments) }; -var ___cxa_is_pointer_type = Module["___cxa_is_pointer_type"] = function() { return Module["asm"]["___cxa_is_pointer_type"].apply(null, arguments) }; -var ___em_js___api_close_keyboard = Module["___em_js___api_close_keyboard"] = function() { return Module["asm"]["___em_js___api_close_keyboard"].apply(null, arguments) }; -var ___em_js___api_open_keyboard = Module["___em_js___api_open_keyboard"] = function() { return Module["asm"]["___em_js___api_open_keyboard"].apply(null, arguments) }; -var ___em_js__api_create_sound = Module["___em_js__api_create_sound"] = function() { return Module["asm"]["___em_js__api_create_sound"].apply(null, arguments) }; -var ___em_js__api_create_sound_float = Module["___em_js__api_create_sound_float"] = function() { return Module["asm"]["___em_js__api_create_sound_float"].apply(null, arguments) }; -var ___em_js__api_delete_sound = Module["___em_js__api_delete_sound"] = function() { return Module["asm"]["___em_js__api_delete_sound"].apply(null, arguments) }; -var ___em_js__api_draw_begin = Module["___em_js__api_draw_begin"] = function() { return Module["asm"]["___em_js__api_draw_begin"].apply(null, arguments) }; -var ___em_js__api_draw_belt = Module["___em_js__api_draw_belt"] = function() { return Module["asm"]["___em_js__api_draw_belt"].apply(null, arguments) }; -var ___em_js__api_draw_blit = Module["___em_js__api_draw_blit"] = function() { return Module["asm"]["___em_js__api_draw_blit"].apply(null, arguments) }; -var ___em_js__api_draw_clip_text = Module["___em_js__api_draw_clip_text"] = function() { return Module["asm"]["___em_js__api_draw_clip_text"].apply(null, arguments) }; -var ___em_js__api_draw_end = Module["___em_js__api_draw_end"] = function() { return Module["asm"]["___em_js__api_draw_end"].apply(null, arguments) }; -var ___em_js__api_draw_text = Module["___em_js__api_draw_text"] = function() { return Module["asm"]["___em_js__api_draw_text"].apply(null, arguments) }; -var ___em_js__api_duplicate_sound = Module["___em_js__api_duplicate_sound"] = function() { return Module["asm"]["___em_js__api_duplicate_sound"].apply(null, arguments) }; -var ___em_js__api_exit_game = Module["___em_js__api_exit_game"] = function() { return Module["asm"]["___em_js__api_exit_game"].apply(null, arguments) }; -var ___em_js__api_play_sound = Module["___em_js__api_play_sound"] = function() { return Module["asm"]["___em_js__api_play_sound"].apply(null, arguments) }; -var ___em_js__api_set_cursor = Module["___em_js__api_set_cursor"] = function() { return Module["asm"]["___em_js__api_set_cursor"].apply(null, arguments) }; -var ___em_js__api_set_volume = Module["___em_js__api_set_volume"] = function() { return Module["asm"]["___em_js__api_set_volume"].apply(null, arguments) }; -var ___em_js__api_stop_sound = Module["___em_js__api_stop_sound"] = function() { return Module["asm"]["___em_js__api_stop_sound"].apply(null, arguments) }; -var ___em_js__api_websocket_closed = Module["___em_js__api_websocket_closed"] = function() { return Module["asm"]["___em_js__api_websocket_closed"].apply(null, arguments) }; -var ___em_js__api_websocket_send = Module["___em_js__api_websocket_send"] = function() { return Module["asm"]["___em_js__api_websocket_send"].apply(null, arguments) }; -var ___em_js__exit_error = Module["___em_js__exit_error"] = function() { return Module["asm"]["___em_js__exit_error"].apply(null, arguments) }; -var ___em_js__get_file_contents = Module["___em_js__get_file_contents"] = function() { return Module["asm"]["___em_js__get_file_contents"].apply(null, arguments) }; -var ___em_js__get_file_size = Module["___em_js__get_file_size"] = function() { return Module["asm"]["___em_js__get_file_size"].apply(null, arguments) }; -var ___em_js__put_file_contents = Module["___em_js__put_file_contents"] = function() { return Module["asm"]["___em_js__put_file_contents"].apply(null, arguments) }; -var ___em_js__remove_file = Module["___em_js__remove_file"] = function() { return Module["asm"]["___em_js__remove_file"].apply(null, arguments) }; -var ___em_js__show_alert = Module["___em_js__show_alert"] = function() { return Module["asm"]["___em_js__show_alert"].apply(null, arguments) }; -var ___em_js__trace_pop = Module["___em_js__trace_pop"] = function() { return Module["asm"]["___em_js__trace_pop"].apply(null, arguments) }; -var ___em_js__trace_push = Module["___em_js__trace_push"] = function() { return Module["asm"]["___em_js__trace_push"].apply(null, arguments) }; -var _emscripten_replace_memory = Module["_emscripten_replace_memory"] = function() { return Module["asm"]["_emscripten_replace_memory"].apply(null, arguments) }; -var _free = Module["_free"] = function() { return Module["asm"]["_free"].apply(null, arguments) }; -var _llvm_bswap_i32 = Module["_llvm_bswap_i32"] = function() { return Module["asm"]["_llvm_bswap_i32"].apply(null, arguments) }; -var _malloc = Module["_malloc"] = function() { return Module["asm"]["_malloc"].apply(null, arguments) }; -var _memcpy = Module["_memcpy"] = function() { return Module["asm"]["_memcpy"].apply(null, arguments) }; -var _memmove = Module["_memmove"] = function() { return Module["asm"]["_memmove"].apply(null, arguments) }; -var _memset = Module["_memset"] = function() { return Module["asm"]["_memset"].apply(null, arguments) }; -var _sbrk = Module["_sbrk"] = function() { return Module["asm"]["_sbrk"].apply(null, arguments) }; -var establishStackSpace = Module["establishStackSpace"] = function() { return Module["asm"]["establishStackSpace"].apply(null, arguments) }; -var getTempRet0 = Module["getTempRet0"] = function() { return Module["asm"]["getTempRet0"].apply(null, arguments) }; -var runPostSets = Module["runPostSets"] = function() { return Module["asm"]["runPostSets"].apply(null, arguments) }; -var setTempRet0 = Module["setTempRet0"] = function() { return Module["asm"]["setTempRet0"].apply(null, arguments) }; -var setThrew = Module["setThrew"] = function() { return Module["asm"]["setThrew"].apply(null, arguments) }; -var stackAlloc = Module["stackAlloc"] = function() { return Module["asm"]["stackAlloc"].apply(null, arguments) }; -var stackRestore = Module["stackRestore"] = function() { return Module["asm"]["stackRestore"].apply(null, arguments) }; -var stackSave = Module["stackSave"] = function() { return Module["asm"]["stackSave"].apply(null, arguments) }; -var dynCall_i = Module["dynCall_i"] = function() { return Module["asm"]["dynCall_i"].apply(null, arguments) }; -var dynCall_ii = Module["dynCall_ii"] = function() { return Module["asm"]["dynCall_ii"].apply(null, arguments) }; -var dynCall_iii = Module["dynCall_iii"] = function() { return Module["asm"]["dynCall_iii"].apply(null, arguments) }; -var dynCall_iiii = Module["dynCall_iiii"] = function() { return Module["asm"]["dynCall_iiii"].apply(null, arguments) }; -var dynCall_iiiii = Module["dynCall_iiiii"] = function() { return Module["asm"]["dynCall_iiiii"].apply(null, arguments) }; -var dynCall_iiiiii = Module["dynCall_iiiiii"] = function() { return Module["asm"]["dynCall_iiiiii"].apply(null, arguments) }; -var dynCall_ji = Module["dynCall_ji"] = function() { return Module["asm"]["dynCall_ji"].apply(null, arguments) }; -var dynCall_v = Module["dynCall_v"] = function() { return Module["asm"]["dynCall_v"].apply(null, arguments) }; -var dynCall_vi = Module["dynCall_vi"] = function() { return Module["asm"]["dynCall_vi"].apply(null, arguments) }; -var dynCall_vii = Module["dynCall_vii"] = function() { return Module["asm"]["dynCall_vii"].apply(null, arguments) }; -var dynCall_viii = Module["dynCall_viii"] = function() { return Module["asm"]["dynCall_viii"].apply(null, arguments) }; -var dynCall_viiii = Module["dynCall_viiii"] = function() { return Module["asm"]["dynCall_viiii"].apply(null, arguments) }; -var dynCall_viiiii = Module["dynCall_viiiii"] = function() { return Module["asm"]["dynCall_viiiii"].apply(null, arguments) }; -var dynCall_viiiiii = Module["dynCall_viiiiii"] = function() { return Module["asm"]["dynCall_viiiiii"].apply(null, arguments) }; -var dynCall_viiiiiii = Module["dynCall_viiiiiii"] = function() { return Module["asm"]["dynCall_viiiiiii"].apply(null, arguments) }; -var dynCall_viiiiiiiii = Module["dynCall_viiiiiiiii"] = function() { return Module["asm"]["dynCall_viiiiiiiii"].apply(null, arguments) }; -var dynCall_viiiiiiiiii = Module["dynCall_viiiiiiiiii"] = function() { return Module["asm"]["dynCall_viiiiiiiiii"].apply(null, arguments) }; -var dynCall_viij = Module["dynCall_viij"] = function() { return Module["asm"]["dynCall_viij"].apply(null, arguments) }; -var dynCall_viji = Module["dynCall_viji"] = function() { return Module["asm"]["dynCall_viji"].apply(null, arguments) }; +var _DApi_AllocPacket = Module["_DApi_AllocPacket"] = function() { + return Module["asm"]["_DApi_AllocPacket"].apply(null, arguments) +}; + +var _DApi_Char = Module["_DApi_Char"] = function() { + return Module["asm"]["_DApi_Char"].apply(null, arguments) +}; + +var _DApi_Init = Module["_DApi_Init"] = function() { + return Module["asm"]["_DApi_Init"].apply(null, arguments) +}; + +var _DApi_Key = Module["_DApi_Key"] = function() { + return Module["asm"]["_DApi_Key"].apply(null, arguments) +}; + +var _DApi_Mouse = Module["_DApi_Mouse"] = function() { + return Module["asm"]["_DApi_Mouse"].apply(null, arguments) +}; + +var _DApi_Render = Module["_DApi_Render"] = function() { + return Module["asm"]["_DApi_Render"].apply(null, arguments) +}; + +var _DApi_SyncText = Module["_DApi_SyncText"] = function() { + return Module["asm"]["_DApi_SyncText"].apply(null, arguments) +}; + +var _DApi_SyncTextPtr = Module["_DApi_SyncTextPtr"] = function() { + return Module["asm"]["_DApi_SyncTextPtr"].apply(null, arguments) +}; + +var _SNet_InitWebsocket = Module["_SNet_InitWebsocket"] = function() { + return Module["asm"]["_SNet_InitWebsocket"].apply(null, arguments) +}; + +var _SNet_WebsocketStatus = Module["_SNet_WebsocketStatus"] = function() { + return Module["asm"]["_SNet_WebsocketStatus"].apply(null, arguments) +}; + +var __ZSt18uncaught_exceptionv = Module["__ZSt18uncaught_exceptionv"] = function() { + return Module["asm"]["__ZSt18uncaught_exceptionv"].apply(null, arguments) +}; + +var ___cxa_can_catch = Module["___cxa_can_catch"] = function() { + return Module["asm"]["___cxa_can_catch"].apply(null, arguments) +}; + +var ___cxa_is_pointer_type = Module["___cxa_is_pointer_type"] = function() { + return Module["asm"]["___cxa_is_pointer_type"].apply(null, arguments) +}; + +var ___em_js___api_close_keyboard = Module["___em_js___api_close_keyboard"] = function() { + return Module["asm"]["___em_js___api_close_keyboard"].apply(null, arguments) +}; + +var ___em_js___api_open_keyboard = Module["___em_js___api_open_keyboard"] = function() { + return Module["asm"]["___em_js___api_open_keyboard"].apply(null, arguments) +}; + +var ___em_js__api_create_sound = Module["___em_js__api_create_sound"] = function() { + return Module["asm"]["___em_js__api_create_sound"].apply(null, arguments) +}; + +var ___em_js__api_create_sound_float = Module["___em_js__api_create_sound_float"] = function() { + return Module["asm"]["___em_js__api_create_sound_float"].apply(null, arguments) +}; + +var ___em_js__api_delete_sound = Module["___em_js__api_delete_sound"] = function() { + return Module["asm"]["___em_js__api_delete_sound"].apply(null, arguments) +}; + +var ___em_js__api_draw_begin = Module["___em_js__api_draw_begin"] = function() { + return Module["asm"]["___em_js__api_draw_begin"].apply(null, arguments) +}; + +var ___em_js__api_draw_belt = Module["___em_js__api_draw_belt"] = function() { + return Module["asm"]["___em_js__api_draw_belt"].apply(null, arguments) +}; + +var ___em_js__api_draw_blit = Module["___em_js__api_draw_blit"] = function() { + return Module["asm"]["___em_js__api_draw_blit"].apply(null, arguments) +}; + +var ___em_js__api_draw_clip_text = Module["___em_js__api_draw_clip_text"] = function() { + return Module["asm"]["___em_js__api_draw_clip_text"].apply(null, arguments) +}; + +var ___em_js__api_draw_end = Module["___em_js__api_draw_end"] = function() { + return Module["asm"]["___em_js__api_draw_end"].apply(null, arguments) +}; + +var ___em_js__api_draw_text = Module["___em_js__api_draw_text"] = function() { + return Module["asm"]["___em_js__api_draw_text"].apply(null, arguments) +}; + +var ___em_js__api_duplicate_sound = Module["___em_js__api_duplicate_sound"] = function() { + return Module["asm"]["___em_js__api_duplicate_sound"].apply(null, arguments) +}; + +var ___em_js__api_exit_game = Module["___em_js__api_exit_game"] = function() { + return Module["asm"]["___em_js__api_exit_game"].apply(null, arguments) +}; + +var ___em_js__api_play_sound = Module["___em_js__api_play_sound"] = function() { + return Module["asm"]["___em_js__api_play_sound"].apply(null, arguments) +}; + +var ___em_js__api_set_cursor = Module["___em_js__api_set_cursor"] = function() { + return Module["asm"]["___em_js__api_set_cursor"].apply(null, arguments) +}; + +var ___em_js__api_set_volume = Module["___em_js__api_set_volume"] = function() { + return Module["asm"]["___em_js__api_set_volume"].apply(null, arguments) +}; + +var ___em_js__api_stop_sound = Module["___em_js__api_stop_sound"] = function() { + return Module["asm"]["___em_js__api_stop_sound"].apply(null, arguments) +}; + +var ___em_js__api_use_websocket = Module["___em_js__api_use_websocket"] = function() { + return Module["asm"]["___em_js__api_use_websocket"].apply(null, arguments) +}; + +var ___em_js__api_websocket_closed = Module["___em_js__api_websocket_closed"] = function() { + return Module["asm"]["___em_js__api_websocket_closed"].apply(null, arguments) +}; + +var ___em_js__api_websocket_send = Module["___em_js__api_websocket_send"] = function() { + return Module["asm"]["___em_js__api_websocket_send"].apply(null, arguments) +}; + +var ___em_js__exit_error = Module["___em_js__exit_error"] = function() { + return Module["asm"]["___em_js__exit_error"].apply(null, arguments) +}; + +var ___em_js__get_file_contents = Module["___em_js__get_file_contents"] = function() { + return Module["asm"]["___em_js__get_file_contents"].apply(null, arguments) +}; + +var ___em_js__get_file_size = Module["___em_js__get_file_size"] = function() { + return Module["asm"]["___em_js__get_file_size"].apply(null, arguments) +}; + +var ___em_js__put_file_contents = Module["___em_js__put_file_contents"] = function() { + return Module["asm"]["___em_js__put_file_contents"].apply(null, arguments) +}; + +var ___em_js__remove_file = Module["___em_js__remove_file"] = function() { + return Module["asm"]["___em_js__remove_file"].apply(null, arguments) +}; + +var ___em_js__show_alert = Module["___em_js__show_alert"] = function() { + return Module["asm"]["___em_js__show_alert"].apply(null, arguments) +}; + +var ___em_js__trace_pop = Module["___em_js__trace_pop"] = function() { + return Module["asm"]["___em_js__trace_pop"].apply(null, arguments) +}; + +var ___em_js__trace_push = Module["___em_js__trace_push"] = function() { + return Module["asm"]["___em_js__trace_push"].apply(null, arguments) +}; + +var _emscripten_replace_memory = Module["_emscripten_replace_memory"] = function() { + return Module["asm"]["_emscripten_replace_memory"].apply(null, arguments) +}; + +var _free = Module["_free"] = function() { + return Module["asm"]["_free"].apply(null, arguments) +}; + +var _llvm_bswap_i32 = Module["_llvm_bswap_i32"] = function() { + return Module["asm"]["_llvm_bswap_i32"].apply(null, arguments) +}; + +var _malloc = Module["_malloc"] = function() { + return Module["asm"]["_malloc"].apply(null, arguments) +}; + +var _memcpy = Module["_memcpy"] = function() { + return Module["asm"]["_memcpy"].apply(null, arguments) +}; + +var _memmove = Module["_memmove"] = function() { + return Module["asm"]["_memmove"].apply(null, arguments) +}; + +var _memset = Module["_memset"] = function() { + return Module["asm"]["_memset"].apply(null, arguments) +}; + +var _sbrk = Module["_sbrk"] = function() { + return Module["asm"]["_sbrk"].apply(null, arguments) +}; + +var _setThrew = Module["_setThrew"] = function() { + return Module["asm"]["_setThrew"].apply(null, arguments) +}; + +var establishStackSpace = Module["establishStackSpace"] = function() { + return Module["asm"]["establishStackSpace"].apply(null, arguments) +}; + +var globalCtors = Module["globalCtors"] = function() { + return Module["asm"]["globalCtors"].apply(null, arguments) +}; + +var stackAlloc = Module["stackAlloc"] = function() { + return Module["asm"]["stackAlloc"].apply(null, arguments) +}; + +var stackRestore = Module["stackRestore"] = function() { + return Module["asm"]["stackRestore"].apply(null, arguments) +}; + +var stackSave = Module["stackSave"] = function() { + return Module["asm"]["stackSave"].apply(null, arguments) +}; + +var dynCall_i = Module["dynCall_i"] = function() { + return Module["asm"]["dynCall_i"].apply(null, arguments) +}; + +var dynCall_ii = Module["dynCall_ii"] = function() { + return Module["asm"]["dynCall_ii"].apply(null, arguments) +}; + +var dynCall_iidiiii = Module["dynCall_iidiiii"] = function() { + return Module["asm"]["dynCall_iidiiii"].apply(null, arguments) +}; + +var dynCall_iii = Module["dynCall_iii"] = function() { + return Module["asm"]["dynCall_iii"].apply(null, arguments) +}; + +var dynCall_iiii = Module["dynCall_iiii"] = function() { + return Module["asm"]["dynCall_iiii"].apply(null, arguments) +}; + +var dynCall_iiiii = Module["dynCall_iiiii"] = function() { + return Module["asm"]["dynCall_iiiii"].apply(null, arguments) +}; + +var dynCall_iiiiii = Module["dynCall_iiiiii"] = function() { + return Module["asm"]["dynCall_iiiiii"].apply(null, arguments) +}; + +var dynCall_ji = Module["dynCall_ji"] = function() { + return Module["asm"]["dynCall_ji"].apply(null, arguments) +}; + +var dynCall_jiji = Module["dynCall_jiji"] = function() { + return Module["asm"]["dynCall_jiji"].apply(null, arguments) +}; + +var dynCall_v = Module["dynCall_v"] = function() { + return Module["asm"]["dynCall_v"].apply(null, arguments) +}; + +var dynCall_vi = Module["dynCall_vi"] = function() { + return Module["asm"]["dynCall_vi"].apply(null, arguments) +}; + +var dynCall_vii = Module["dynCall_vii"] = function() { + return Module["asm"]["dynCall_vii"].apply(null, arguments) +}; + +var dynCall_viii = Module["dynCall_viii"] = function() { + return Module["asm"]["dynCall_viii"].apply(null, arguments) +}; + +var dynCall_viiii = Module["dynCall_viiii"] = function() { + return Module["asm"]["dynCall_viiii"].apply(null, arguments) +}; + +var dynCall_viiiii = Module["dynCall_viiiii"] = function() { + return Module["asm"]["dynCall_viiiii"].apply(null, arguments) +}; + +var dynCall_viiiiii = Module["dynCall_viiiiii"] = function() { + return Module["asm"]["dynCall_viiiiii"].apply(null, arguments) +}; + +var dynCall_viiiiiii = Module["dynCall_viiiiiii"] = function() { + return Module["asm"]["dynCall_viiiiiii"].apply(null, arguments) +}; + +var dynCall_viiiiiiiii = Module["dynCall_viiiiiiiii"] = function() { + return Module["asm"]["dynCall_viiiiiiiii"].apply(null, arguments) +}; + +var dynCall_viiiiiiiiii = Module["dynCall_viiiiiiiiii"] = function() { + return Module["asm"]["dynCall_viiiiiiiiii"].apply(null, arguments) +}; + +var dynCall_viij = Module["dynCall_viij"] = function() { + return Module["asm"]["dynCall_viij"].apply(null, arguments) +}; + +var dynCall_viji = Module["dynCall_viji"] = function() { + return Module["asm"]["dynCall_viji"].apply(null, arguments) +}; ; @@ -2567,18 +2847,17 @@ function ExitStatus(status) { this.name = "ExitStatus"; this.message = "Program terminated with exit(" + status + ")"; this.status = status; -}; +} ExitStatus.prototype = new Error(); ExitStatus.prototype.constructor = ExitStatus; -var initialStackTop; var calledMain = false; dependenciesFulfilled = function runCaller() { // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false) if (!Module['calledRun']) run(); if (!Module['calledRun']) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled -} +}; @@ -2604,7 +2883,7 @@ function run(args) { if (ABORT) return; - ensureInitRuntime(); + initRuntime(); preMain(); @@ -2644,7 +2923,6 @@ function exit(status, implicit) { ABORT = true; EXITSTATUS = status; - STACKTOP = initialStackTop; exitRuntime(); @@ -2661,13 +2939,9 @@ function abort(what) { Module['onAbort'](what); } - if (what !== undefined) { - out(what); - err(what); - what = JSON.stringify(what) - } else { - what = ''; - } + what += ''; + out(what); + err(what); ABORT = true; EXITSTATUS = 1; @@ -2676,8 +2950,6 @@ function abort(what) { } Module['abort'] = abort; -// {{PRE_RUN_ADDITIONS}} - if (Module['preInit']) { if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']]; while (Module['preInit'].length > 0) { @@ -2686,12 +2958,10 @@ if (Module['preInit']) { } -Module["noExitRuntime"] = true; + Module["noExitRuntime"] = true; run(); -// {{POST_RUN_ADDITIONS}} - @@ -2712,14 +2982,14 @@ Module['ready'] = new Promise(function (resolve, reject) { - return DiabloSpawn; + return DiabloSpawn } ); })(); if (typeof exports === 'object' && typeof module === 'object') - module.exports = DiabloSpawn; - else if (typeof define === 'function' && define['amd']) - define([], function() { return DiabloSpawn; }); - else if (typeof exports === 'object') - exports["DiabloSpawn"] = DiabloSpawn; - \ No newline at end of file + module.exports = DiabloSpawn; + else if (typeof define === 'function' && define['amd']) + define([], function() { return DiabloSpawn; }); + else if (typeof exports === 'object') + exports["DiabloSpawn"] = DiabloSpawn; + \ No newline at end of file diff --git a/src/api/DiabloSpawn.wasm b/src/api/DiabloSpawn.wasm index 15125f8..18a091b 100644 Binary files a/src/api/DiabloSpawn.wasm and b/src/api/DiabloSpawn.wasm differ diff --git a/src/api/game.worker.js b/src/api/game.worker.js index 9b842a8..6dac0ea 100644 --- a/src/api/game.worker.js +++ b/src/api/game.worker.js @@ -4,6 +4,8 @@ import SpawnBinary from './DiabloSpawn.wasm'; import SpawnModule from './DiabloSpawn.jscc'; import axios from 'axios'; +import websocket_open from './websocket'; + const DiabloSize = 1466809; const SpawnSize = 1337416; @@ -16,6 +18,7 @@ let files = null; let renderBatch = null; let drawBelt = null; let is_spawn = false; +let websocket = null; const ChunkSize = 1 << 20; class RemoteFile { @@ -116,8 +119,35 @@ const DApi = { worker.postMessage({action: "keyboard", rect: null}); }, + use_websocket(flag) { + if (flag) { + if (!websocket || websocket.readyState !== 1) { + const sock = websocket = websocket_open('ws://diablo.rivsoft.net/', data => { + if (websocket === sock) { + try_api(() => { + const ptr = wasm._DApi_AllocPacket(data.byteLength); + wasm.HEAPU8.set(new Uint8Array(data), ptr); + }); + } + }, code => { + if (typeof code !== "number") { + worker.postMessage({action: "error", error: code.toString(), stack: code.stack}); + code = 3; + } + call_api("SNet_WebsocketStatus", code); + }); + } else { + call_api("SNet_WebsocketStatus", 0); + } + } else { + if (websocket) { + websocket.close(); + } + websocket = null; + } + }, websocket_closed() { - return false; + return websocket ? websocket.readyState !== 1 : false; }, }; @@ -234,7 +264,9 @@ let maxSoundId = 0, maxBatchId = 0; let packetBatch = null; DApi.websocket_send = function(data) { - if (packetBatch) { + if (websocket) { + websocket.send(data); + } else if (packetBatch) { packetBatch.push(data.slice().buffer); } else { worker.postMessage({action: "packet", buffer: data}); @@ -249,9 +281,6 @@ function try_api(func) { try { func(); } catch (e) { - if (typeof e === "string") { - worker.postMessage({action: ""}) - } worker.postMessage({action: "error", error: e.toString(), stack: e.stack}); } } diff --git a/src/api/packet.js b/src/api/packet.js new file mode 100644 index 0000000..7b1214f --- /dev/null +++ b/src/api/packet.js @@ -0,0 +1,260 @@ +export class buffer_reader { + constructor(buffer) { + this.buffer = (buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer)); + this.pos = 0; + } + done() { + return this.pos === this.buffer.byteLength; + } + read8() { + if (this.pos >= this.buffer.byteLength) { + throw Error('packet too small'); + } + return this.buffer[this.pos++]; + } + read16() { + const {pos, buffer} = this; + if (pos + 2 > buffer.byteLength) { + throw Error('packet too small'); + } + const result = buffer[pos] | (buffer[pos + 1] << 8); + this.pos += 2; + return result; + } + read32() { + const {pos, buffer} = this; + if (pos + 4 > buffer.byteLength) { + throw Error('packet too small'); + } + const result = buffer[pos] | (buffer[pos + 1] << 8) | (buffer[pos + 2] << 16) | (buffer[pos + 3] << 24); + this.pos += 4; + return result; + } + read_str() { + const length = this.read8(); + const {pos, buffer} = this; + if (pos + length > buffer.byteLength) { + throw Error('packet too small'); + } + const result = String.fromCharCode(...buffer.subarray(pos, pos + length)); + this.pos += length; + return result; + } + rest() { + const size = this.read32(); + const result = this.buffer.subarray(this.pos, this.pos + size); + this.pos += size; + return result; + } +} +export class buffer_writer { + constructor(length) { + this.buffer = new Uint8Array(length); + this.pos = 0; + } + get result() { + return this.buffer.buffer; + } + write8(value) { + this.buffer[this.pos++] = value; + return this; + } + write16(value) { + const {pos, buffer} = this; + buffer[pos] = value; + buffer[pos + 1] = value >> 8; + this.pos += 2; + return this; + } + write32(value) { + const {pos, buffer} = this; + buffer[pos] = value; + buffer[pos + 1] = value >> 8; + buffer[pos + 2] = value >> 16; + buffer[pos + 3] = value >> 24; + this.pos += 4; + return this; + } + write_str(value) { + const length = value.length; + this.write8(length); + const {pos, buffer} = this; + for (let i = 0; i < length; ++i) { + buffer[pos + i] = value.charCodeAt(i); + } + this.pos += length; + return this; + } + rest(value) { + this.write32(value.byteLength); + this.buffer.set(value, this.pos); + this.pos += value.byteLength; + return this; + } +} + +export const RejectionReason = { + JOIN_SUCCESS: 0x00, + JOIN_ALREADY_IN_GAME: 0x01, + JOIN_GAME_NOT_FOUND: 0x02, + JOIN_INCORRECT_PASSWORD: 0x03, + JOIN_VERSION_MISMATCH: 0x04, + JOIN_GAME_FULL: 0x05, + CREATE_GAME_EXISTS: 0x06, +}; + +export function read_packet(reader, types) { + const code = reader.read8(); + const cls = Object.values(types).find(cls => cls.code === code); + if (!cls) { + throw Error('invalid packet code'); + } + return {type: cls, packet: cls.read(reader)}; +} +export function packet_size(type, packet) { + return (typeof type.size === "function" ? type.size(packet) : type.size) + 1; +} +export function write_packet(type, packet) { + const size = packet_size(type, packet); + return type.write(new buffer_writer(size).write8(type.code), packet).result; +} + +export function make_batch(types) { + return { + code: 0x00, + read: reader => { + const count = reader.read16(); + const packets = []; + for (let i = 0; i < count; ++i) { + packets.push(read_packet(reader, types())); + } + return packets; + }, + size: packets => packets.reduce((sum, {type, packet}) => sum + packet_size(type, packet), 2), + write: (writer, packets) => { + writer.write16(packets.length); + for (let {type, packet} of packets) { + type.write(writer.write8(type.code), packet); + } + return writer; + }, + }; +} + +export const server_packet = { + info: { + code: 0x32, + read: reader => ({version: reader.read32()}), + size: 4, + write: (writer, {version}) => writer.write32(version), + }, + game_list: { + code: 0x21, + read: reader => { + const count = reader.read16(); + const games = []; + for (let i = 0; i < count; ++i) { + games.push({type: reader.read32(), name: reader.read_str()}); + } + return {games}; + }, + size: ({games}) => games.reduce((sum, {name}) => sum + 5 + name.length, 2), + write: (writer, {games}) => { + writer.write16(games.length); + for (let {type, name} of games) { + writer.write32(type); + writer.write_str(name); + } + return writer; + }, + }, + join_accept: { + code: 0x12, + read: reader => ({cookie: reader.read32(), index: reader.read8(), seed: reader.read32(), difficulty: reader.read32()}), + size: 13, + write: (writer, {cookie, index, seed, difficulty}) => writer.write32(cookie).write8(index).write32(seed).write32(difficulty), + }, + join_reject: { + code: 0x15, + read: reader => ({cookie: reader.read32(), reason: reader.read8()}), + size: 5, + write: (writer, {cookie, reason}) => writer.write32(cookie).write8(reason), + }, + connect: { + code: 0x13, + read: reader => ({id: reader.read8()}), + size: 1, + write: (writer, {id}) => writer.write8(id), + }, + disconnect: { + code: 0x14, + read: reader => ({id: reader.read8(), reason: reader.read32()}), + size: 5, + write: (writer, {id, reason}) => writer.write8(id).write32(reason), + }, + message: { + code: 0x01, + read: reader => ({id: reader.read8(), payload: reader.rest()}), + size: ({payload}) => 5 + payload.byteLength, + write: (writer, {id, payload}) => writer.write8(id).rest(payload), + }, + turn: { + code: 0x02, + read: reader => ({id: reader.read8(), turn: reader.read32()}), + size: 5, + write: (writer, {id, turn}) => writer.write8(id).write32(turn), + }, + batch: make_batch(() => server_packet), +}; + +export const client_packet = { + info: { + code: 0x31, + read: reader => ({version: reader.read32()}), + size: 4, + write: (writer, {version}) => writer.write32(version), + }, + game_list: { + code: 0x21, + read: () => ({}), + size: 0, + write: writer => writer, + }, + create_game: { + code: 0x22, + read: reader => ({cookie: reader.read32(), name: reader.read_str(), password: reader.read_str(), difficulty: reader.read32()}), + size: ({name, password}) => 10 + name.length + password.length, + write: (writer, {cookie, name, password, difficulty}) => writer.write32(cookie).write_str(name).write_str(password).write32(difficulty), + }, + join_game: { + code: 0x23, + read: reader => ({cookie: reader.read32(), name: reader.read_str(), password: reader.read_str()}), + size: ({name, password}) => 6 + name.length + password.length, + write: (writer, {cookie, name, password}) => writer.write32(cookie).write_str(name).write_str(password), + }, + leave_game: { + code: 0x24, + read: () => ({}), + size: 0, + write: writer => writer, + }, + drop_player: { + code: 0x03, + read: reader => ({id: reader.read8(), reason: reader.read32()}), + size: 5, + write: (writer, {id, reason}) => writer.write8(id).write32(reason), + }, + message: { + code: 0x01, + read: reader => ({id: reader.read8(), payload: reader.rest()}), + size: ({payload}) => 5 + payload.byteLength, + write: (writer, {id, payload}) => writer.write8(id).rest(payload), + }, + turn: { + code: 0x02, + read: reader => ({turn: reader.read32()}), + size: 4, + write: (writer, {turn}) => writer.write32(turn), + }, + batch: make_batch(() => server_packet), +}; diff --git a/src/api/webrtc.js b/src/api/webrtc.js index 383ab3f..36b5270 100644 --- a/src/api/webrtc.js +++ b/src/api/webrtc.js @@ -1,210 +1,5 @@ import Peer from 'peerjs'; - -class buffer_reader { - constructor(buffer) { - this.buffer = (buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer)); - this.pos = 0; - } - done() { - return this.pos === this.buffer.byteLength; - } - read8() { - if (this.pos >= this.buffer.byteLength) { - throw Error('packet too small'); - } - return this.buffer[this.pos++]; - } - read16() { - const {pos, buffer} = this; - if (pos + 2 > buffer.byteLength) { - throw Error('packet too small'); - } - const result = buffer[pos] | (buffer[pos + 1] << 8); - this.pos += 2; - return result; - } - read32() { - const {pos, buffer} = this; - if (pos + 4 > buffer.byteLength) { - throw Error('packet too small'); - } - const result = buffer[pos] | (buffer[pos + 1] << 8) | (buffer[pos + 2] << 16) | (buffer[pos + 3] << 24); - this.pos += 4; - return result; - } - read_str() { - const length = this.read8(); - const {pos, buffer} = this; - if (pos + length > buffer.byteLength) { - throw Error('packet too small'); - } - const result = String.fromCharCode(...buffer.subarray(pos, pos + length)); - this.pos += length; - return result; - } - rest() { - const result = this.buffer.subarray(this.pos); - this.pos = this.buffer.length; - return result; - } -} -class buffer_writer { - constructor(length) { - this.buffer = new Uint8Array(length); - this.pos = 0; - } - get result() { - return this.buffer.buffer; - } - write8(value) { - this.buffer[this.pos++] = value; - return this; - } - write16(value) { - const {pos, buffer} = this; - buffer[pos] = value; - buffer[pos + 1] = value >> 8; - this.pos += 2; - return this; - } - write32(value) { - const {pos, buffer} = this; - buffer[pos] = value; - buffer[pos + 1] = value >> 8; - buffer[pos + 2] = value >> 16; - buffer[pos + 3] = value >> 24; - this.pos += 4; - return this; - } - write_str(value) { - const length = value.length; - this.write8(length); - const {pos, buffer} = this; - for (let i = 0; i < length; ++i) { - buffer[pos + i] = value.charCodeAt(i); - } - this.pos += length; - return this; - } - rest(value) { - this.buffer.set(value, this.pos); - return this; - } -} - -const RejectionReason = { - JOIN_SUCCESS: 0x00, - JOIN_ALREADY_IN_GAME: 0x01, - JOIN_GAME_NOT_FOUND: 0x02, - JOIN_INCORRECT_PASSWORD: 0x03, - JOIN_VERSION_MISMATCH: 0x04, - JOIN_GAME_FULL: 0x05, - CREATE_GAME_EXISTS: 0x06, -}; - -const server_packet = { - info: { - code: 0x32, - read: reader => ({version: reader.read32()}), - write: ({version}) => new buffer_writer(5).write8(server_packet.info.code).write32(version).result, - }, - game_list: { - code: 0x21, - read: reader => { - const count = reader.read8(); - const games = []; - for (let i = 0; i < count; ++i) { - games.push({type: reader.read32(), name: reader.read_str()}); - } - return {games}; - }, - write: ({games}) => { - const writer = new buffer_writer(games.reduce((sum, {name}) => sum + 5 + name.length, 2)); - writer.write8(server_packet.game_list.code); - writer.write8(games.length); - for (let {code, name} of games) { - writer.write32(code); - writer.write_str(name); - } - return writer.result; - }, - }, - join_accept: { - code: 0x12, - read: reader => ({cookie: reader.read32(), index: reader.read8(), seed: reader.read32(), difficulty: reader.read32()}), - write: ({cookie, index, seed, difficulty}) => new buffer_writer(14).write8(server_packet.join_accept.code).write32(cookie).write8(index).write32(seed).write32(difficulty).result, - }, - join_reject: { - code: 0x15, - read: reader => ({cookie: reader.read32(), reason: reader.read8()}), - write: ({cookie, reason}) => new buffer_writer(6).write8(server_packet.join_reject.code).write32(cookie).write8(reason).result, - }, - connect: { - code: 0x13, - read: reader => ({id: reader.read8()}), - write: ({id}) => new buffer_writer(2).write8(server_packet.connect.code).write8(id).result, - }, - disconnect: { - code: 0x14, - read: reader => ({id: reader.read8(), reason: reader.read32()}), - write: ({id, reason}) => new buffer_writer(6).write8(server_packet.disconnect.code).write8(id).write32(reason).result, - }, - message: { - code: 0x01, - read: reader => ({id: reader.read8(), payload: reader.rest()}), - write: ({id, payload}) => new buffer_writer(2 + payload.byteLength).write8(server_packet.message.code).write8(id).rest(payload).result, - }, - turn: { - code: 0x02, - read: reader => ({id: reader.read8(), turn: reader.read32()}), - write: ({id, turn}) => new buffer_writer(6).write8(server_packet.turn.code).write8(id).write32(turn).result, - }, -}; - -const client_packet = { - info: { - code: 0x31, - read: reader => ({version: reader.read32()}), - write: ({version}) => new buffer_writer(5).write8(client_packet.info.code).write32(version).result, - }, - game_list: { - code: 0x21, - read: () => ({}), - write: () => new buffer_writer(1).write8(client_packet.game_list.code).result, - }, - create_game: { - code: 0x22, - read: reader => ({cookie: reader.read32(), name: reader.read_str(), password: reader.read_str(), difficulty: reader.read32()}), - write: ({cookie, name, password, difficulty}) => new buffer_writer(11 + name.length + password.length) - .write8(client_packet.create_game.code).write32(cookie).write_str(name).write_str(password).write32(difficulty).result, - }, - join_game: { - code: 0x23, - read: reader => ({cookie: reader.read32(), name: reader.read_str(), password: reader.read_str()}), - write: ({cookie, name, password}) => new buffer_writer(7 + name.length + password.length) - .write8(client_packet.join_game.code).write32(cookie).write_str(name).write_str(password).result, - }, - leave_game: { - code: 0x24, - read: () => ({}), - write: () => new buffer_writer(1).write8(client_packet.leave_game.code).result, - }, - drop_player: { - code: 0x03, - read: reader => ({id: reader.read8(), reason: reader.read32()}), - write: ({id, reason}) => new buffer_writer(6).write8(client_packet.drop_player.code).write8(id).write32(reason).result, - }, - message: { - code: 0x01, - read: reader => ({id: reader.read8(), payload: reader.rest()}), - write: ({id, payload}) => new buffer_writer(2 + payload.byteLength).write8(client_packet.message.code).write8(id).rest(payload).result, - }, - turn: { - code: 0x02, - read: reader => ({turn: reader.read32()}), - write: ({turn}) => new buffer_writer(5).write8(client_packet.turn.code).write32(turn).result, - }, -}; +import { buffer_reader, read_packet, write_packet, client_packet, server_packet, RejectionReason } from './packet'; /*function log_packet(data, type) { const reader = new buffer_reader(data); @@ -262,15 +57,12 @@ class webrtc_server { const peer = {conn}; conn.on('data', packet => { const reader = new buffer_reader(packet); - const code = reader.read8(); - let pkt; - switch (code) { + const {type, packet: pkt} = read_packet(reader, client_packet); + switch (type.code) { case client_packet.info.code: - pkt = client_packet.info.read(reader); peer.version = pkt.version; break; case client_packet.join_game.code: - pkt = client_packet.join_game.read(reader); if (peer.version !== this.version) { conn.send(server_packet.join_reject.write({cookie: pkt.cookie, reason: RejectionReason.JOIN_VERSION_MISMATCH})); } else if (pkt.name !== this.name) { @@ -294,7 +86,7 @@ class webrtc_server { break; default: if (peer.id != null) { - this.handle(peer.id, code, reader); + this.handle(peer.id, type.code, pkt); } else { return; } @@ -343,23 +135,18 @@ class webrtc_server { } } - handle(id, code, reader) { - let pkt; + handle(id, code, pkt) { switch (code) { case client_packet.leave_game.code: - pkt = client_packet.leave_game.read(reader); this.drop(id, 3); break; case client_packet.drop_player.code: - pkt = client_packet.drop_player.read(reader); this.drop(pkt.id, pkt.reason); break; case client_packet.message.code: - pkt = client_packet.message.read(reader); this.send(pkt.id === 0xFF ? ~(1 << id) : (1 << pkt.id), server_packet.message.write({id, payload: pkt.payload})); break; case client_packet.turn.code: - pkt = client_packet.turn.read(reader); this.send(~(1 << id), server_packet.turn.write({id, turn: pkt.turn})); break; default: @@ -411,18 +198,15 @@ class webrtc_client { this.conn.on('data', data => { unreg(); const reader = new buffer_reader(data); - const code = reader.read8(); - let pkt; - switch (code) { + const {type, packet: pkt} = read_packet(reader, server_packet); + switch (type.code) { case server_packet.join_accept.code: - pkt = server_packet.join_accept.read(reader); this.myplr = pkt.index; break; case server_packet.join_reject.code: onClose(); break; case server_packet.disconnect.code: - pkt = server_packet.disconnect.read(reader); if (pkt.id === 'myplr') { onClose(); } @@ -460,15 +244,12 @@ export default function webrtc_open(onMessage) { send: function(packet) { //log_packet(packet, client_packet); const reader = new buffer_reader(packet); - const code = reader.read8(); - let pkt; - switch (code) { + const {type, packet: pkt} = read_packet(reader, client_packet); + switch (type.code) { case client_packet.info.code: - pkt = client_packet.info.read(reader); version = pkt.version; break; case client_packet.create_game.code: - pkt = client_packet.create_game.read(reader); if (server || client) { onMessage(server_packet.join_reject.write({cookie: pkt.cookie, reason: RejectionReason.JOIN_ALREADY_IN_GAME})); } else { @@ -476,7 +257,6 @@ export default function webrtc_open(onMessage) { } break; case client_packet.join_game.code: - pkt = client_packet.join_game.read(reader); if (server || client) { onMessage(server_packet.join_reject.write({cookie: pkt.cookie, reason: RejectionReason.JOIN_ALREADY_IN_GAME})); } else { @@ -485,18 +265,18 @@ export default function webrtc_open(onMessage) { break; default: if (server) { - server.handle(0, code, reader); - if (code === client_packet.leave_game.code) { + server.handle(0, type.code, pkt); + if (type.code === client_packet.leave_game.code) { server = null; } } else if (client) { client.send(packet); - if (code === client_packet.leave_game.code) { + if (type.code === client_packet.leave_game.code) { client = null; } return; - } else if (code !== client_packet.leave_game.code) { - throw Error(`invalid packet ${code}`); + } else if (type.code !== client_packet.leave_game.code) { + throw Error(`invalid packet ${type.code}`); } } if (!reader.done()) { diff --git a/src/api/websocket.js b/src/api/websocket.js index 596d26b..8e8898f 100644 --- a/src/api/websocket.js +++ b/src/api/websocket.js @@ -1,4 +1,4 @@ -export default async function websocket_open(url, handler) { +async function do_websocket_open(url, handler) { const socket = new WebSocket(url); socket.binaryType = "arraybuffer"; let versionCbk = null; @@ -9,7 +9,7 @@ export default async function websocket_open(url, handler) { handler(data); }); await new Promise((resolve, reject) => { - const onError = err => reject(err); + const onError = err => reject(1); socket.addEventListener("error", onError); socket.addEventListener("open", () => { socket.removeEventListener("error", onError); @@ -19,7 +19,7 @@ export default async function websocket_open(url, handler) { await new Promise((resolve, reject) => { const to = setTimeout(() => { versionCbk = null; - reject(Error("connection timed out")); + reject(1); }, 5000); versionCbk = data => { clearTimeout(to); @@ -30,7 +30,7 @@ export default async function websocket_open(url, handler) { if (version === 1) { resolve(); } else { - reject("server version mismatch"); + reject(2); } } }; @@ -46,3 +46,40 @@ export default async function websocket_open(url, handler) { socket.send(clientInfo); return socket; } + +export default function websocket_open(url, handler, finisher) { + let ws = null, pending = []; + const proxy = { + get readyState() { + return ws ? ws.readyState : 0; + }, + send(msg) { + if (ws) { + ws.send(msg); + } else { + pending.push(msg.slice()); + } + }, + close() { + if (ws) { + ws.close(); + } else { + pending = null; + } + }, + }; + do_websocket_open(url, handler).then(sock => { + ws = sock; + if (pending) { + for (let msg of pending) { + ws.send(msg); + } + } else { + ws.close(); + } + finisher(0); + }, err => { + finisher(err); + }); + return proxy; +}