// This test often times out on debug simulators due to the extreme slowdown. if (getBuildConfiguration("debug") && isSimulator)
quit();
// All the glue code is wrapped in a function so it can be executed uncached and // cached or compiled separately. function runBox2d(cacheEntryOrModule) {
// The Module object: Our interface to the outside world. We import // and export values on it, and do the work to get that through // closure compiler if necessary. There are various ways Module can be used: // 1. Not defined. We create it here // 2. A function parameter, function(Module) { ..generated code.. } // 3. pre-run appended it, var Module = {}; ..generated code.. // 4. External script tag defines var Module. // We need to do an eval in order to handle the closure compiler // case, where this code here is minified but Module was defined // elsewhere (e.g. case 4 above). We also need to check if Module // already exists (e.g. case 3 above). // Note that if you want to run closure, and also to use Module // after the generated code, you will need to define var Module = {}; // before the code. Then that object will be used in the code, and you // can continue to use Module afterwards as well. var Module; if (!Module) Module = (typeof Module !== 'undefined' ? Module : null) || {};
// Sometimes an existing Module object exists with properties // meant to overwrite the default module functionality. Here // we collect those properties and reapply _after_ we configure // the current environment's defaults to avoid having to be so // defensive during initialization. var moduleOverrides = {}; for (var key in Module) { if (Module.hasOwnProperty(key)) {
moduleOverrides[key] = Module[key];
}
}
if (!Module['print']) Module['print'] = print; if (typeof printErr != 'undefined') Module['printErr'] = print;
// Merge back in the overrides for (var key in moduleOverrides) { if (moduleOverrides.hasOwnProperty(key)) {
Module[key] = moduleOverrides[key];
}
} // Free the object hierarchy contained in the overrides, this lets the GC // reclaim data used e.g. in memoryInitializerRequest, which is a large typed array.
moduleOverrides = undefined;
// {{PREAMBLE_ADDITIONS}}
// === Preamble library stuff ===
// Documentation for the public APIs defined in this file must be updated in: // site/source/docs/api_reference/preamble.js.rst // A prebuilt local version of the documentation is available at: // site/build/text/docs/api_reference/preamble.js.txt // You can also build docs locally as HTML or other formats in site/ // An online HTML version (which may be of a different version of Emscripten) // is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html
//======================================== // Runtime code shared with compiler //========================================
var Runtime = {
setTempRet0: function (value) {
tempRet0 = value;
},
getTempRet0: function () { return tempRet0;
},
stackSave: function () { return STACKTOP;
},
stackRestore: function (stackTop) {
STACKTOP = stackTop;
},
getNativeTypeSize: function (type) { switch (type) { case'i1': case'i8': return 1; case'i16': return 2; case'i32': return 4; case'i64': return 8; case'float': return 4; case'double': return 8; default: { if (type[type.length-1] === '*') { return Runtime.QUANTUM_SIZE; // A pointer
} elseif (type[0] === 'i') { var bits = parseInt(type.substr(1)); assert(bits % 8 === 0); return bits/8;
} else { return 0;
}
}
}
},
getNativeFieldSize: function (type) { return Math.max(Runtime.getNativeTypeSize(type), Runtime.QUANTUM_SIZE);
},
STACK_ALIGN: 16,
prepVararg: function (ptr, type) { if (type === 'double' || type === 'i64') { // move so the load is aligned if (ptr & 7) { assert((ptr & 7) === 4);
ptr += 4;
}
} else { assert((ptr & 3) === 0);
} return ptr;
},
getAlignSize: function (type, size, vararg) { // we align i64s and doubles on 64-bit boundaries, unlike x86 if (!vararg && (type == 'i64' || type == 'double')) return 8; if (!type) return Math.min(size, 8); // align structures internally to 64 bits return Math.min(size || (type ? Runtime.getNativeFieldSize(type) : 0), Runtime.QUANTUM_SIZE);
},
dynCall: function (sig, ptr, args) { if (args && args.length) { return Module['dynCall_' + sig].apply(null, [ptr].concat(args));
} else { return Module['dynCall_' + sig].call(null, ptr);
}
},
functionPointers: [],
addFunction: function (func) { for (var i = 0; i < Runtime.functionPointers.length; i++) { if (!Runtime.functionPointers[i]) {
Runtime.functionPointers[i] = func; return 2*(1 + i);
}
} throw'Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.';
},
removeFunction: function (index) {
Runtime.functionPointers[(index-2)/2] = null;
},
warnOnce: function (text) { if (!Runtime.warnOnce.shown) Runtime.warnOnce.shown = {}; if (!Runtime.warnOnce.shown[text]) {
Runtime.warnOnce.shown[text] = 1;
Module.printErr(text);
}
},
funcWrappers: {},
getFuncWrapper: function (func, sig) { assert(sig); if (!Runtime.funcWrappers[sig]) {
Runtime.funcWrappers[sig] = {};
} var sigCache = Runtime.funcWrappers[sig]; if (!sigCache[func]) { // optimize away arguments usage in common cases if (sig.length === 1) {
sigCache[func] = function dynCall_wrapper() { return Runtime.dynCall(sig, func);
};
} elseif (sig.length === 2) {
sigCache[func] = function dynCall_wrapper(arg) { return Runtime.dynCall(sig, func, [arg]);
};
} else { // general case
sigCache[func] = function dynCall_wrapper() { return Runtime.dynCall(sig, func, Array.prototype.slice.call(arguments));
};
}
} return sigCache[func];
},
getCompilerSetting: function (name) { throw'You must build with -s RETAIN_COMPILER_SETTINGS=1 for Runtime.getCompilerSetting or emscripten_get_compiler_setting to work';
},
stackAlloc: function (size) { var ret = STACKTOP;STACKTOP = (STACKTOP + size)|0;STACKTOP = (((STACKTOP)+15)&-16); return ret; },
staticAlloc: function (size) { var ret = STATICTOP;STATICTOP = (STATICTOP + size)|0;STATICTOP = (((STATICTOP)+15)&-16); return ret; },
dynamicAlloc: function (size) { var ret = HEAP32[DYNAMICTOP_PTR>>2];var end = (((ret + size + 15)|0) & -16);HEAP32[DYNAMICTOP_PTR>>2] = end;if (end >= TOTAL_MEMORY) {var success = enlargeMemory();if (!success) {HEAP32[DYNAMICTOP_PTR>>2] = ret;return 0;}}return ret;},
alignMemory: function (size,quantum) { var ret = size = Math.ceil((size)/(quantum ? quantum : 16))*(quantum ? quantum : 16); return ret; },
makeBigInt: function (low,high,unsigned) { var ret = (unsigned ? ((+((low>>>0)))+((+((high>>>0)))*4294967296.0)) : ((+((low>>>0)))+((+((high|0)))*4294967296.0))); return ret; },
GLOBAL_BASE: 1024,
QUANTUM_SIZE: 4,
__dummy__: 0
}
// 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 if (!func) { try { func = eval('_' + ident); } catch(e) {}
} assert(func, 'Cannot call unknown function ' + ident + ' (perhaps LLVM optimizations or closure removed it?)'); return func;
}
var cwrap, ccall;
(function(){ 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() {
Runtime.stackSave()
}, 'stackRestore': function() {
Runtime.stackRestore()
}, // type conversion from js to c 'arrayToC' : function(arr) { var ret = Runtime.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 = Runtime.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.
ccall = function ccallFunc(ident, returnType, argTypes, args, opts) { var func = getCFunc(ident); var cArgs = []; var stack = 0; if (args) { for (var i = 0; i < args.length; i++) { var converter = toC[argTypes[i]]; if (converter) { if (stack === 0) stack = Runtime.stackSave();
cArgs[i] = converter(args[i]);
} else {
cArgs[i] = args[i];
}
}
} var ret = func.apply(null, cArgs); if (returnType === 'string') ret = Pointer_stringify(ret); if (stack !== 0) { if (opts && opts.async) {
EmterpreterAsync.asyncFinalizers.push(function() {
Runtime.stackRestore(stack);
}); return;
}
Runtime.stackRestore(stack);
} return ret;
}
var sourceRegex = /^function\s*[a-zA-Z$_0-9]*\s*\(([^)]*)\)\s*{\s*([^*]*?)[\s;]*(?:return\s*(.*?)[;\s]*)?}$/; function parseJSFunc(jsfunc) { // Match the body and the return value of a javascript function source var parsed = jsfunc.toString().match(sourceRegex).slice(1); return {arguments : parsed[0], body : parsed[1], returnValue: parsed[2]}
}
// sources of useful functions. we create this lazily as it can trigger a source decompression on this entire file var JSsource = null; function ensureJSsource() { if (!JSsource) {
JSsource = {}; for (var fun in JSfuncs) { if (JSfuncs.hasOwnProperty(fun)) { // Elements of toCsource are arrays of three items: // the code, and the return value
JSsource[fun] = parseJSFunc(JSfuncs[fun]);
}
}
}
}
cwrap = function cwrap(ident, returnType, argTypes) {
argTypes = argTypes || []; var cfunc = getCFunc(ident); // When the function takes numbers and returns a number, we can just return // the original function var numericArgs = argTypes.every(function(type){ return type === 'number'}); var numericRet = (returnType !== 'string'); if ( numericRet && numericArgs) { return cfunc;
} // Creation of the arguments list (["$1","$2",...,"$nargs"]) var argNames = argTypes.map(function(x,i){return'$'+i}); var funcstr = "(function(" + argNames.join(',') + ") {"; var nargs = argTypes.length; if (!numericArgs) { // Generate the code needed to convert the arguments from javascript // values to pointers
ensureJSsource();
funcstr += 'var stack = ' + JSsource['stackSave'].body + ';'; for (var i = 0; i < nargs; i++) { var arg = argNames[i], type = argTypes[i]; if (type === 'number') continue; var convertCode = JSsource[type + 'ToC']; // [code, return]
funcstr += 'var ' + convertCode.arguments + ' = ' + arg + ';';
funcstr += convertCode.body + ';';
funcstr += arg + '=(' + convertCode.returnValue + ');';
}
}
// When the code is compressed, the name of cfunc is not literally 'cfunc' anymore var cfuncname = parseJSFunc(function(){return cfunc}).returnValue; // Call the function
funcstr += 'var ret = ' + cfuncname + '(' + argNames.join(',') + ');'; if (!numericRet) { // Return type can only by 'string' or 'number' // Convert the result to a string var strgfy = parseJSFunc(function(){return Pointer_stringify}).returnValue;
funcstr += 'ret = ' + strgfy + '(ret);';
} if (!numericArgs) { // If we had a stack, restore it
ensureJSsource();
funcstr += JSsource['stackRestore'].body.replace('()', '(stack)') + ';';
}
funcstr += 'return ret})'; return eval(funcstr);
};
})();
Module["ccall"] = ccall;
Module["cwrap"] = cwrap;
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);
}
}
Module["setValue"] = setValue;
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 setValue: ' + type);
} returnnull;
}
Module["getValue"] = getValue;
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
Module["ALLOC_NORMAL"] = ALLOC_NORMAL;
Module["ALLOC_STACK"] = ALLOC_STACK;
Module["ALLOC_STATIC"] = ALLOC_STATIC;
Module["ALLOC_DYNAMIC"] = ALLOC_DYNAMIC;
Module["ALLOC_NONE"] = ALLOC_NONE;
// 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 // for multiple syntaxes to save space in generated code. So you should // normally not use allocate(), and instead allocate memory using _malloc(), // initialize it with setValue(), and so forth. // @slab: An array of data, or a number. If a number, then the size of the block to allocate, // in *bytes* (note that this is sometimes confusing: the next parameter does not // affect this!) // @types: Either an array of types, one for each byte (or 0 if no type at that position), // or a single type which is used for the entire block. This only matters if there // is initial data - if @slab is a number, then this does not matter at all and is // ignored. // @allocator: How to allocate memory, see ALLOC_* function allocate(slab, types, allocator, ptr) { var zeroinit, size; if (typeof slab === 'number') {
zeroinit = true;
size = slab;
} else {
zeroinit = false;
size = slab.length;
}
var i = 0, type, typeSize, previousType; while (i < size) { var curr = slab[i];
if (typeof curr === 'function') {
curr = Runtime.getFunctionIndex(curr);
}
type = singleType || types[i]; if (type === 0) {
i++; continue;
}
if (type == 'i64') type = 'i32'; // special case: we have one i32 here, and one i32 later
setValue(ret+i, curr, type);
// no need to look up size unless type changes, so cache it if (previousType !== type) {
typeSize = Runtime.getNativeTypeSize(type);
previousType = type;
}
i += typeSize;
}
return ret;
}
Module["allocate"] = allocate;
// Allocate memory during any stage of startup - static memory early on, dynamic memory later, malloc when ready function getMemory(size) { if (!staticSealed) return Runtime.staticAlloc(size); if (!runtimeInitialized) return Runtime.dynamicAlloc(size); return _malloc(size);
}
Module["getMemory"] = getMemory;
function Pointer_stringify(ptr, /* optional */ length) { if (length === 0 || !ptr) return''; // TODO: use TextDecoder // 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 Module['UTF8ToString'](ptr);
}
Module["Pointer_stringify"] = Pointer_stringify;
// Given a pointer 'ptr' to a null-terminated ASCII-encoded string in the emscripten HEAP, returns // a copy of that string as a Javascript String object.
function AsciiToString(ptr) { var str = ''; while (1) { var ch = HEAP8[((ptr++)>>0)]; if (!ch) return str;
str += String.fromCharCode(ch);
}
}
Module["AsciiToString"] = AsciiToString;
// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', // null-terminated and encoded in ASCII form. The copy will require at most str.length+1 bytes of space in the HEAP.
// 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) { 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;
// 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);
}
Module["UTF8ToString"] = UTF8ToString;
// Copies the given Javascript String object 'str' to the given byte array at address 'outIdx', // encoded in UTF8 form and null-terminated. The copy will require at most str.length*4+1 bytes of space in the HEAP. // Use the function lengthBytesUTF8 to compute the exact number of bytes (excluding null terminator) that this function will write. // Parameters: // str: the Javascript string to copy. // outU8Array: the array to copy to. Each index in this array is assumed to be one 8-byte element. // outIdx: The starting offset in the array to begin the copying. // maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null // terminator, i.e. if maxBytesToWrite=1, only the null terminator will be written and nothing else. // maxBytesToWrite=0 does not write any bytes to the output, not even the null terminator. // Returns the number of bytes written, EXCLUDING the null terminator.
function stringToUTF8Array(str, outU8Array, outIdx, maxBytesToWrite) { if (!(maxBytesToWrite > 0)) // Parameter maxBytesToWrite is not optional. Negative values, 0, null, undefined and false each don't write out any bytes. return 0;
var startIdx = outIdx; var endIdx = outIdx + maxBytesToWrite - 1; // -1 for string null terminator. for (var i = 0; i < str.length; ++i) { // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! So decode UTF16->UTF32->UTF8. // See http://unicode.org/faq/utf_bom.html#utf16-3 // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description and https://www.ietf.org/rfc/rfc2279.txt and https://tools.ietf.org/html/rfc3629 var u = str.charCodeAt(i); // possibly a lead surrogate if (u >= 0xD800 && u <= 0xDFFF) u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF); if (u <= 0x7F) { if (outIdx >= endIdx) break;
outU8Array[outIdx++] = u;
} elseif (u <= 0x7FF) { if (outIdx + 1 >= endIdx) break;
outU8Array[outIdx++] = 0xC0 | (u >> 6);
outU8Array[outIdx++] = 0x80 | (u & 63);
} elseif (u <= 0xFFFF) { if (outIdx + 2 >= endIdx) break;
outU8Array[outIdx++] = 0xE0 | (u >> 12);
outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63);
outU8Array[outIdx++] = 0x80 | (u & 63);
} elseif (u <= 0x1FFFFF) { 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);
} elseif (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.
outU8Array[outIdx] = 0; return outIdx - startIdx;
}
Module["stringToUTF8Array"] = stringToUTF8Array;
// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', // null-terminated and encoded in UTF8 form. The copy will require at most str.length*4+1 bytes of space in the HEAP. // Use the function lengthBytesUTF8 to compute the exact number of bytes (excluding null terminator) that this function will write. // Returns the number of bytes written, EXCLUDING the null terminator.
// 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) { // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! So decode UTF16->UTF32->UTF8. // See http://unicode.org/faq/utf_bom.html#utf16-3 var 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;
} elseif (u <= 0x7FF) {
len += 2;
} elseif (u <= 0xFFFF) {
len += 3;
} elseif (u <= 0x1FFFFF) {
len += 4;
} elseif (u <= 0x3FFFFFF) {
len += 5;
} else {
len += 6;
}
} return len;
}
Module["lengthBytesUTF8"] = lengthBytesUTF8;
// 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.
var UTF16Decoder = typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-16le') : undefined; function UTF16ToString(ptr) { var endPtr = ptr; // 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. var idx = endPtr >> 1; while (HEAP16[idx]) ++idx;
endPtr = idx << 1;
if (endPtr - ptr > 32 && UTF16Decoder) { return UTF16Decoder.decode(HEAPU8.subarray(ptr, endPtr));
} else { var i = 0;
var str = ''; while (1) { var codeUnit = HEAP16[(((ptr)+(i*2))>>1)]; if (codeUnit == 0) return str;
++i; // fromCharCode constructs a character from a UTF-16 code unit, so we can pass the UTF16 string right through.
str += String.fromCharCode(codeUnit);
}
}
}
// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', // null-terminated and encoded in UTF16 form. The copy will require at most str.length*4+2 bytes of space in the HEAP. // Use the function lengthBytesUTF16() to compute the exact number of bytes (excluding null terminator) that this function will write. // Parameters: // str: the Javascript string to copy. // outPtr: Byte address in Emscripten HEAP where to write the string to. // maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null // terminator, i.e. if maxBytesToWrite=2, only the null terminator will be written and nothing else. // maxBytesToWrite<2 does not write any bytes to the output, not even the null terminator. // Returns the number of bytes written, EXCLUDING the null terminator.
function stringToUTF16(str, outPtr, maxBytesToWrite) { // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed. if (maxBytesToWrite === undefined) {
maxBytesToWrite = 0x7FFFFFFF;
} if (maxBytesToWrite < 2) return 0;
maxBytesToWrite -= 2; // Null terminator. var startPtr = outPtr; var numCharsToWrite = (maxBytesToWrite < str.length*2) ? (maxBytesToWrite / 2) : str.length; for (var i = 0; i < numCharsToWrite; ++i) { // charCodeAt returns a UTF-16 encoded code unit, so it can be directly written to the HEAP. var codeUnit = str.charCodeAt(i); // possibly a lead surrogate
HEAP16[((outPtr)>>1)]=codeUnit;
outPtr += 2;
} // Null-terminate the pointer to the HEAP.
HEAP16[((outPtr)>>1)]=0; return outPtr - startPtr;
}
// Returns the number of bytes the given Javascript string takes if encoded as a UTF16 byte array, EXCLUDING the null terminator byte.
function lengthBytesUTF16(str) { return str.length*2;
}
function UTF32ToString(ptr) { var i = 0;
var str = ''; while (1) { var utf32 = HEAP32[(((ptr)+(i*4))>>2)]; if (utf32 == 0) return str;
++i; // Gotcha: fromCharCode constructs a character from a UTF-16 encoded code (pair), not from a Unicode code point! So encode the code point to UTF-16 for constructing. // See http://unicode.org/faq/utf_bom.html#utf16-3 if (utf32 >= 0x10000) { var ch = utf32 - 0x10000;
str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF));
} else {
str += String.fromCharCode(utf32);
}
}
}
// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', // null-terminated and encoded in UTF32 form. The copy will require at most str.length*4+4 bytes of space in the HEAP. // Use the function lengthBytesUTF32() to compute the exact number of bytes (excluding null terminator) that this function will write. // Parameters: // str: the Javascript string to copy. // outPtr: Byte address in Emscripten HEAP where to write the string to. // maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null // terminator, i.e. if maxBytesToWrite=4, only the null terminator will be written and nothing else. // maxBytesToWrite<4 does not write any bytes to the output, not even the null terminator. // Returns the number of bytes written, EXCLUDING the null terminator.
function stringToUTF32(str, outPtr, maxBytesToWrite) { // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed. if (maxBytesToWrite === undefined) {
maxBytesToWrite = 0x7FFFFFFF;
} if (maxBytesToWrite < 4) return 0; var startPtr = outPtr; var endPtr = startPtr + maxBytesToWrite - 4; for (var i = 0; i < str.length; ++i) { // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap. // See http://unicode.org/faq/utf_bom.html#utf16-3 var codeUnit = str.charCodeAt(i); // possibly a lead surrogate if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) { var trailSurrogate = str.charCodeAt(++i);
codeUnit = 0x10000 + ((codeUnit & 0x3FF) << 10) | (trailSurrogate & 0x3FF);
}
HEAP32[((outPtr)>>2)]=codeUnit;
outPtr += 4; if (outPtr + 4 > endPtr) break;
} // Null-terminate the pointer to the HEAP.
HEAP32[((outPtr)>>2)]=0; return outPtr - startPtr;
}
// Returns the number of bytes the given Javascript string takes if encoded as a UTF16 byte array, EXCLUDING the null terminator byte.
function lengthBytesUTF32(str) { var len = 0; for (var i = 0; i < str.length; ++i) { // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap. // See http://unicode.org/faq/utf_bom.html#utf16-3 var codeUnit = str.charCodeAt(i); if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) ++i; // possibly a lead surrogate, so skip over the tail surrogate.
len += 4;
}
return len;
}
function demangle(func) { var __cxa_demangle_func = Module['___cxa_demangle'] || Module['__cxa_demangle']; if (__cxa_demangle_func) { try { var s =
func.substr(1); var len = lengthBytesUTF8(s)+1; var buf = _malloc(len);
stringToUTF8(s, buf, len); var status = _malloc(4); var ret = __cxa_demangle_func(buf, 0, 0, status); if (getValue(status, 'i32') === 0 && ret) { return Pointer_stringify(ret);
} // otherwise, libcxxabi failed
} catch(e) { // ignore problems here
} finally { if (buf) _free(buf); if (status) _free(status); if (ret) _free(ret);
} // failure when using libcxxabi, don't demangle return func;
}
Runtime.warnOnce('warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling'); return func;
}
function demangleAll(text) { var regex =
/__Z[\w\d_]+/g; return text.replace(regex, function(x) { var y = demangle(x); return x === y ? x : (x + ' [' + y + ']');
});
}
function jsStackTrace() { var err = new Error(); if (!err.stack) { // IE10+ special cases: It does have callstack info, but it is only populated if an Error object is thrown, // so try that as a special-case. try { thrownew Error(0);
} catch(e) {
err = e;
} if (!err.stack) { return'(no stack trace available)';
}
} return err.stack.toString();
}
function stackTrace() { var js = jsStackTrace(); if (Module['extraStackTrace']) js += '\n' + Module['extraStackTrace'](); return demangleAll(js);
}
Module["stackTrace"] = stackTrace;
// 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) {
x += multiple - (x % multiple);
} return x;
}
var HEAP; var buffer; var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64;
function updateGlobalBuffer(buf) {
Module['buffer'] = buffer = buf;
}
function updateGlobalBufferViews() {
Module['HEAP8'] = HEAP8 = new Int8Array(buffer);
Module['HEAP16'] = HEAP16 = new Int16Array(buffer);
Module['HEAP32'] = HEAP32 = new Int32Array(buffer);
Module['HEAPU8'] = HEAPU8 = new Uint8Array(buffer);
Module['HEAPU16'] = HEAPU16 = new Uint16Array(buffer);
Module['HEAPU32'] = HEAPU32 = new Uint32Array(buffer);
Module['HEAPF32'] = HEAPF32 = new Float32Array(buffer);
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
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 adjusts the size at runtime but prevents some optimizations, (3) set Module.TOTAL_MEMORY to a higher value before the program runs, or if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 ');
}
function enlargeMemory() {
abortOnCannotGrowMemory();
}
var TOTAL_STACK = Module['TOTAL_STACK'] || 5242880; var TOTAL_MEMORY = Module['TOTAL_MEMORY'] || 16777216; if (TOTAL_MEMORY < TOTAL_STACK) Module.printErr('TOTAL_MEMORY should be larger than TOTAL_STACK, was ' + 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, maximum: TOTAL_MEMORY / WASM_PAGE_SIZE });
buffer = Module['wasmMemory'].buffer;
} else
{
buffer = new ArrayBuffer(TOTAL_MEMORY);
}
}
updateGlobalBufferViews();
function getTotalMemory() { return TOTAL_MEMORY;
}
// Endianness check (note: assumes compiler arch was little-endian)
HEAP32[0] = 0x63736d65; /* 'emsc' */
HEAP16[1] = 0x6373; if (HEAPU8[2] !== 0x73 || HEAPU8[3] !== 0x63) throw'Runtime error: expected the system to be little-endian!';
function callRuntimeCallbacks(callbacks) { while(callbacks.length > 0) { var callback = callbacks.shift(); if (typeof callback == 'function') {
callback(); continue;
} var func = callback.func; if (typeof func === 'number') { if (callback.arg === undefined) {
Module['dynCall_v'](func);
} else {
Module['dynCall_vi'](func, callback.arg);
}
} else {
func(callback.arg === undefined ? null : callback.arg);
}
}
}
var __ATPRERUN__ = []; // functions called before the runtime is initialized var __ATINIT__ = []; // functions called during startup var __ATMAIN__ = []; // functions called when main() is to be run var __ATEXIT__ = []; // functions called during shutdown var __ATPOSTRUN__ = []; // functions called after the runtime has exited
var runtimeInitialized = false; var runtimeExited = false;
function preRun() { // compatibility - merge in anything from Module['preRun'] at this time if (Module['preRun']) { if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']]; while (Module['preRun'].length) {
addOnPreRun(Module['preRun'].shift());
}
}
callRuntimeCallbacks(__ATPRERUN__);
}
function ensureInitRuntime() { if (runtimeInitialized) return;
runtimeInitialized = true;
callRuntimeCallbacks(__ATINIT__);
}
function preMain() {
callRuntimeCallbacks(__ATMAIN__);
}
function exitRuntime() {
callRuntimeCallbacks(__ATEXIT__);
runtimeExited = true;
}
function postRun() { // compatibility - merge in anything from Module['postRun'] at this time if (Module['postRun']) { if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']]; while (Module['postRun'].length) {
addOnPostRun(Module['postRun'].shift());
}
}
callRuntimeCallbacks(__ATPOSTRUN__);
}
function addOnPreRun(cb) {
__ATPRERUN__.unshift(cb);
}
Module["addOnPreRun"] = addOnPreRun;
function addOnInit(cb) {
__ATINIT__.unshift(cb);
}
Module["addOnInit"] = addOnInit;
function addOnPreMain(cb) {
__ATMAIN__.unshift(cb);
}
Module["addOnPreMain"] = addOnPreMain;
function addOnExit(cb) {
__ATEXIT__.unshift(cb);
}
Module["addOnExit"] = addOnExit;
function addOnPostRun(cb) {
__ATPOSTRUN__.unshift(cb);
}
Module["addOnPostRun"] = addOnPostRun;
// Tools
function intArrayFromString(stringy, dontAddNull, length /* optional */) { var len = length > 0 ? length : lengthBytesUTF8(stringy)+1; var u8array = new Array(len); var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length); if (dontAddNull) u8array.length = numBytesWritten; return u8array;
}
Module["intArrayFromString"] = intArrayFromString;
function intArrayToString(array) { var ret = []; for (var i = 0; i < array.length; i++) { var chr = array[i]; if (chr > 0xFF) {
chr &= 0xFF;
}
ret.push(String.fromCharCode(chr));
} return ret.join('');
}
Module["intArrayToString"] = intArrayToString;
// 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. function writeStringToMemory(string, buffer, dontAddNull) {
Runtime.warnOnce('writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!');
var lastChar, 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.
}
Module["writeStringToMemory"] = writeStringToMemory;
function writeArrayToMemory(array, buffer) {
HEAP8.set(array, buffer);
}
Module["writeArrayToMemory"] = writeArrayToMemory;
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;
}
Module["writeAsciiToMemory"] = writeAsciiToMemory;
function unSign(value, bits, ignore) { if (value >= 0) { return value;
} return bits <= 32 ? 2*Math.abs(1 << (bits-1)) + value // Need some trickery, since if bits == 32, we are right at the limit of the bits JS uses in bitshifts
: Math.pow(2, bits) + value;
} function reSign(value, bits, ignore) { if (value <= 0) { return value;
} var half = bits <= 32 ? Math.abs(1 << (bits-1)) // abs is needed if bits == 32
: Math.pow(2, bits-1); if (value >= half && (bits <= 32 || value > half)) { // for huge values, we can hit the precision limit and always get true here. so don't do that // but, in general there is no perfect solution here. With 64-bit ints, we get rounding and errors // TODO: In i64 mode 1, resign the two parts separately and safely
value = -2*half + value; // Cannot bitshift half, as it may be at the limit of the bits JS uses in bitshifts
} return value;
}
// check for imul support, and also for correctness ( https://bugs.webkit.org/show_bug.cgi?id=126345 ) if (!Math['imul'] || Math['imul'](0xffffffff, 5) !== -5) Math['imul'] = function imul(a, b) { var ah = a >>> 16; var al = a & 0xffff; var bh = b >>> 16; var bl = b & 0xffff; return (al*bl + ((ah*bl + al*bh) << 16))|0;
};
Math.imul = Math['imul'];
if (!Math['fround']) { var froundBuffer = new Float32Array(1);
Math['fround'] = function(x) { froundBuffer[0] = x; return froundBuffer[0] };
}
Math.fround = Math['fround'];
if (!Math['clz32']) Math['clz32'] = function(x) {
x = x >>> 0; for (var i = 0; i < 32; i++) { if (x & (1 << (31 - i))) return i;
} return 32;
};
Math.clz32 = Math['clz32']
if (!Math['trunc']) Math['trunc'] = function(x) { return x < 0 ? Math.ceil(x) : Math.floor(x);
};
Math.trunc = Math['trunc'];
var Math_abs = Math.abs; var Math_cos = Math.cos; var Math_sin = Math.sin; var Math_tan = Math.tan; var Math_acos = Math.acos; var Math_asin = Math.asin; var Math_atan = Math.atan; var Math_atan2 = Math.atan2; var Math_exp = Math.exp; var Math_log = Math.log; var Math_sqrt = Math.sqrt; var Math_ceil = Math.ceil; var Math_floor = Math.floor; var Math_pow = Math.pow; var Math_imul = Math.imul; var Math_fround = Math.fround; var Math_round = Math.round; var Math_min = Math.min; 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). // Note that you can add dependencies in preRun, even though // it happens right before run - run will be postponed until // the dependencies are met. var runDependencies = 0; var runDependencyWatcher = null; var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled
function getUniqueRunDependency(id) { return id;
}
function addRunDependency(id) {
runDependencies++; if (Module['monitorRunDependencies']) {
Module['monitorRunDependencies'](runDependencies);
}
}
Module["addRunDependency"] = addRunDependency;
function removeRunDependency(id) {
runDependencies--; if (Module['monitorRunDependencies']) {
Module['monitorRunDependencies'](runDependencies);
} if (runDependencies == 0) { if (runDependencyWatcher !== null) {
clearInterval(runDependencyWatcher);
runDependencyWatcher = null;
} if (dependenciesFulfilled) { var callback = dependenciesFulfilled;
dependenciesFulfilled = null;
callback(); // can add another dependenciesFulfilled
}
}
}
Module["removeRunDependency"] = removeRunDependency;
Module["preloadedImages"] = {}; // maps url to image data
Module["preloadedAudios"] = {}; // maps url to audio data
var memoryInitializer = null;
function integrateWasmJS(Module) { // 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 can be set at compile time (BINARYEN_METHOD), or runtime by setting Module['wasmJSMethod']. // 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.
// inputs
var method = Module['wasmJSMethod'] || 'native-wasm';
Module['wasmJSMethod'] = method;
var wasmBinaryFile = Module['wasmBinaryFile'] || scriptdir + 'wasm_box2d.wasm';
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.
};
var exports = null;
function lookupImport(mod, base) { var lookup = info; if (mod.indexOf('.') < 0) {
lookup = (lookup || {})[mod];
} else { var parts = mod.split('.');
lookup = (lookup || {})[parts[0]];
lookup = (lookup || {})[parts[1]];
} if (base) {
lookup = (lookup || {})[base];
} if (lookup === undefined) {
abort('bad lookupImport to (' + mod + ').' + base);
} return lookup;
}
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) {
Module['printErr']('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);
// If we have a mem init file, do not trample it if (!memoryInitializer) {
oldView.set(newView.subarray(Module['STATIC_BASE'], Module['STATIC_BASE'] + Module['STATIC_BUMP']), Module['STATIC_BASE']);
}
function fixImports(imports) { if (!0) return imports; var ret = {}; for (var i in imports) { var fixed = i; if (fixed[0] == '_') fixed = fixed.substr(1);
ret[fixed] = imports[i];
} return ret;
}
// do-method functions
function doJustAsm(global, env, providedBuffer) { // if no Module.asm, or it's the method handler helper (see below), then apply // the asmjs if (typeof Module['asm'] !== 'function' || Module['asm'] === methodHandler) { if (!Module['asmPreload']) { // you can load the .asm.js file before this, to avoid this sync xhr and eval
eval(Module['read'](asmjsCodeFile)); // set Module.asm
} else {
Module['asm'] = Module['asmPreload'];
}
} if (typeof Module['asm'] !== 'function') {
Module['printErr']('asm evalling did not set the module properly'); returnfalse;
} return Module['asm'](global, env, providedBuffer);
}
function doNativeWasm(global, env, providedBuffer) { if (typeof WebAssembly !== 'object') {
Module['printErr']('no native wasm support detected'); returnfalse;
} // prepare memory import if (!(Module['wasmMemory'] instanceof WebAssembly.Memory)) {
Module['printErr']('no native wasm Memory in use'); returnfalse;
}
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'] = global.Math;
info['env'] = env; // handle a generated wasm instance, receiving its exports and // performing other necessary setup function receiveInstance(instance) {
exports = instance.exports; if (exports.memory) mergeMemory(exports.memory);
Module['asm'] = exports;
Module["usingWasm"] = true;
}
Module['printErr']('asynchronously preparing wasm');
addRunDependency('wasm-instantiate'); // we can't run yet
// receiveInstance() will swap in the exports (to Module.asm) so they can be called
receiveInstance(output.instance);
removeRunDependency('wasm-instantiate');
})
.catch(function(reason) {
Module['printErr']('failed to asynchronously prepare wasm:\n ' + reason);
}); 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
Module['reallocBuffer'] = 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"]) { 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 { returnnull;
}
} catch(e) { returnnull;
}
} else {
exports['__growWasmMemory']((size - oldSize) / wasmPageSize); // tiny wasm method that just does memory.grow // in interpreter, we replace Module.buffer if we allocate return Module['buffer'] !== old ? Module['buffer'] : null; // if it was reallocated, it changed
}
};
// 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.
// 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
}
var Browser={mainLoop:{scheduler:null,method:"",currentlyRunningMainloop:0,func:null,arg:0,timingMode:0,timingValue:0,currentFrameNumber:0,queue:[],pause:function() {
Browser.mainLoop.scheduler = null;
Browser.mainLoop.currentlyRunningMainloop++; // Incrementing this signals the previous main loop that it's now become old, and it must return.
},resume:function () {
Browser.mainLoop.currentlyRunningMainloop++; var timingMode = Browser.mainLoop.timingMode; var timingValue = Browser.mainLoop.timingValue; var func = Browser.mainLoop.func;
Browser.mainLoop.func = null;
_emscripten_set_main_loop(func, 0, false, Browser.mainLoop.arg, true/* do not set timing and call scheduler, we will do it on the next lines */);
_emscripten_set_main_loop_timing(timingMode, timingValue);
Browser.mainLoop.scheduler();
},updateStatus:function () { if (Module['setStatus']) { var message = Module['statusMessage'] || 'Please wait...'; var remaining = Browser.mainLoop.remainingBlockers; var expected = Browser.mainLoop.expectedBlockers; if (remaining) { if (remaining < expected) {
Module['setStatus'](message + ' (' + (expected - remaining) + '/' + expected + ')');
} else {
Module['setStatus'](message);
}
} else {
Module['setStatus']('');
}
}
},runIter:function (func) { if (ABORT) return; if (Module['preMainLoop']) { var preRet = Module['preMainLoop'](); if (preRet === false) { return; // |return false| skips a frame
}
} try {
func();
} catch (e) { if (e instanceof ExitStatus) { return;
} else { if (e && typeof e === 'object' && e.stack) Module.printErr('exception thrown: ' + [e, e.stack]); throw e;
}
} if (Module['postMainLoop']) Module['postMainLoop']();
}},isFullscreen:false,pointerLock:false,moduleContextCreatedCallbacks:[],workers:[],init:function () { if (!Module["preloadPlugins"]) Module["preloadPlugins"] = []; // needs to exist even in workers
if (Browser.initted) return;
Browser.initted = true;
try { new Blob();
Browser.hasBlobConstructor = true;
} catch(e) {
Browser.hasBlobConstructor = false;
console.log("warning: no blob constructor, cannot create blobs with mimetypes");
}
Browser.BlobBuilder = typeof MozBlobBuilder != "undefined" ? MozBlobBuilder : (typeof WebKitBlobBuilder != "undefined" ? WebKitBlobBuilder : (!Browser.hasBlobConstructor ? console.log("warning: no BlobBuilder") : null));
Browser.URLObject = typeof window != "undefined" ? (window.URL ? window.URL : window.webkitURL) : undefined; if (!Module.noImageDecoding && typeof Browser.URLObject === 'undefined') {
console.log("warning: Browser does not support creating object URLs. Built-in browser image decoding will not be available.");
Module.noImageDecoding = true;
}
// Support for plugins that can process preloaded files. You can add more of these to // your app by creating and appending to Module.preloadPlugins. // // Each plugin is asked if it can handle a file based on the file's name. If it can, // it is given the file's raw data. When it is done, it calls a callback with the file's // (possibly modified) data. For example, a plugin might decompress a file, or it // might create some side data structure for use later (like an Image element, etc.).
var imagePlugin = {};
imagePlugin['canHandle'] = function imagePlugin_canHandle(name) { return !Module.noImageDecoding && /\.(jpg|jpeg|png|bmp)$/i.test(name);
};
imagePlugin['handle'] = function imagePlugin_handle(byteArray, name, onload, onerror) { var b = null; if (Browser.hasBlobConstructor) { try {
b = new Blob([byteArray], { type: Browser.getMimetype(name) }); if (b.size !== byteArray.length) { // Safari bug #118630 // Safari's Blob can only take an ArrayBuffer
b = new Blob([(new Uint8Array(byteArray)).buffer], { type: Browser.getMimetype(name) });
}
} catch(e) {
Runtime.warnOnce('Blob constructor present but fails: ' + e + '; falling back to blob builder');
}
} if (!b) { var bb = new Browser.BlobBuilder();
bb.append((new Uint8Array(byteArray)).buffer); // we need to pass a buffer, and must copy the array to get the right data range
b = bb.getBlob();
} var url = Browser.URLObject.createObjectURL(b); var img = new Image();
img.onload = function img_onload() { assert(img.complete, 'Image ' + name + ' could not be decoded'); var canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height; var ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
Module["preloadedImages"][name] = canvas;
Browser.URLObject.revokeObjectURL(url); if (onload) onload(byteArray);
};
img.onerror = function img_onerror(event) {
console.log('Image ' + url + ' could not be decoded'); if (onerror) onerror();
};
img.src = url;
};
Module['preloadPlugins'].push(imagePlugin);
var audioPlugin = {};
audioPlugin['canHandle'] = function audioPlugin_canHandle(name) { return !Module.noAudioDecoding && name.substr(-4) in { '.ogg': 1, '.wav': 1, '.mp3': 1 };
};
audioPlugin['handle'] = function audioPlugin_handle(byteArray, name, onload, onerror) { var done = false; function finish(audio) { if (done) return;
done = true;
Module["preloadedAudios"][name] = audio; if (onload) onload(byteArray);
} function fail() { if (done) return;
done = true;
Module["preloadedAudios"][name] = new Audio(); // empty shim if (onerror) onerror();
} if (Browser.hasBlobConstructor) { try { var b = new Blob([byteArray], { type: Browser.getMimetype(name) });
} catch(e) { return fail();
} var url = Browser.URLObject.createObjectURL(b); // XXX we never revoke this! var audio = new Audio();
audio.addEventListener('canplaythrough', function() { finish(audio) }, false); // use addEventListener due to chromium bug 124926
audio.onerror = function audio_onerror(event) { if (done) return;
console.log('warning: browser could not fully decode audio ' + name + ', trying slower base64 approach'); function encode64(data) { var BASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; var PAD = '='; var ret = ''; var leftchar = 0; var leftbits = 0; for (var i = 0; i < data.length; i++) {
leftchar = (leftchar << 8) | data[i];
leftbits += 8; while (leftbits >= 6) { var curr = (leftchar >> (leftbits-6)) & 0x3f;
leftbits -= 6;
ret += BASE[curr];
}
} if (leftbits == 2) {
ret += BASE[(leftchar&3) << 4];
ret += PAD + PAD;
} elseif (leftbits == 4) {
ret += BASE[(leftchar&0xf) << 2];
ret += PAD;
} return ret;
}
audio.src = 'data:audio/x-' + name.substr(-3) + ';base64,' + encode64(byteArray);
finish(audio); // we don't wait for confirmation this worked - but it's worth trying
};
audio.src = url; // workaround for chrome bug 124926 - we do not always get oncanplaythrough or onerror
Browser.safeSetTimeout(function() {
finish(audio); // try to use it even though it is not necessarily ready to play
}, 10000);
} else { return fail();
}
};
Module['preloadPlugins'].push(audioPlugin);
// Canvas event setup
function pointerLockChange() {
Browser.pointerLock = document['pointerLockElement'] === Module['canvas'] ||
document['mozPointerLockElement'] === Module['canvas'] ||
document['webkitPointerLockElement'] === Module['canvas'] ||
document['msPointerLockElement'] === Module['canvas'];
} var canvas = Module['canvas']; if (canvas) { // forced aspect ratio can be enabled by defining 'forcedAspectRatio' on Module // Module['forcedAspectRatio'] = 4 / 3;
canvas.requestPointerLock = canvas['requestPointerLock'] ||
canvas['mozRequestPointerLock'] ||
canvas['webkitRequestPointerLock'] ||
canvas['msRequestPointerLock'] || function(){};
canvas.exitPointerLock = document['exitPointerLock'] ||
document['mozExitPointerLock'] ||
document['webkitExitPointerLock'] ||
document['msExitPointerLock'] || function(){}; // no-op if function does not exist
canvas.exitPointerLock = canvas.exitPointerLock.bind(document);
if (Module['elementPointerLock']) {
canvas.addEventListener("click", function(ev) { if (!Browser.pointerLock && Module['canvas'].requestPointerLock) {
Module['canvas'].requestPointerLock();
ev.preventDefault();
}
}, false);
}
}
},createContext:function (canvas, useWebGL, setInModule, webGLContextAttributes) { if (useWebGL && Module.ctx && canvas == Module.canvas) return Module.ctx; // no need to recreate GL context if it's already been created for this canvas.
var ctx; var contextHandle; if (useWebGL) { // For GLES2/desktop GL compatibility, adjust a few defaults to be different to WebGL defaults, so that they align better with the desktop defaults. var contextAttributes = {
antialias: false,
alpha: false
};
if (webGLContextAttributes) { for (var attribute in webGLContextAttributes) {
contextAttributes[attribute] = webGLContextAttributes[attribute];
}
}
if (setInModule) { if (!useWebGL) assert(typeof GLctx === 'undefined', 'cannot set in module if GLctx is used, but we are a non-GL context that would replace it');
var canvas = Module['canvas']; function fullscreenChange() {
Browser.isFullscreen = false; var canvasContainer = canvas.parentNode; if ((document['fullscreenElement'] || document['mozFullScreenElement'] ||
document['msFullscreenElement'] || document['webkitFullscreenElement'] ||
document['webkitCurrentFullScreenElement']) === canvasContainer) {
canvas.exitFullscreen = document['exitFullscreen'] ||
document['cancelFullScreen'] ||
document['mozCancelFullScreen'] ||
document['msExitFullscreen'] ||
document['webkitCancelFullScreen'] || function() {};
canvas.exitFullscreen = canvas.exitFullscreen.bind(document); if (Browser.lockPointer) canvas.requestPointerLock();
Browser.isFullscreen = true; if (Browser.resizeCanvas) Browser.setFullscreenCanvasSize();
} else {
// remove the full screen specific parent of the canvas again to restore the HTML structure from before going full screen
canvasContainer.parentNode.insertBefore(canvas, canvasContainer);
canvasContainer.parentNode.removeChild(canvasContainer);
if (Browser.resizeCanvas) Browser.setWindowedCanvasSize();
} if (Module['onFullScreen']) Module['onFullScreen'](Browser.isFullscreen); if (Module['onFullscreen']) Module['onFullscreen'](Browser.isFullscreen);
Browser.updateCanvasDimensions(canvas);
}
// create a new parent to ensure the canvas has no siblings. this allows browsers to optimize full screen performance when its parent is the full screen root var canvasContainer = document.createElement("div");
canvas.parentNode.insertBefore(canvasContainer, canvas);
canvasContainer.appendChild(canvas);
// use parent of canvas as full screen root to allow aspect ratio correction (Firefox stretches the root to screen size)
canvasContainer.requestFullscreen = canvasContainer['requestFullscreen'] ||
canvasContainer['mozRequestFullScreen'] ||
canvasContainer['msRequestFullscreen'] ||
(canvasContainer['webkitRequestFullscreen'] ? function() { canvasContainer['webkitRequestFullscreen'](Element['ALLOW_KEYBOARD_INPUT']) } : null) ||
(canvasContainer['webkitRequestFullScreen'] ? function() { canvasContainer['webkitRequestFullScreen'](Element['ALLOW_KEYBOARD_INPUT']) } : null);
if (vrDevice) {
canvasContainer.requestFullscreen({ vrDisplay: vrDevice });
} else {
canvasContainer.requestFullscreen();
}
},requestFullScreen:function (lockPointer, resizeCanvas, vrDevice) {
Module.printErr('Browser.requestFullScreen() is deprecated. Please call Browser.requestFullscreen instead.');
Browser.requestFullScreen = function(lockPointer, resizeCanvas, vrDevice) { return Browser.requestFullscreen(lockPointer, resizeCanvas, vrDevice);
} return Browser.requestFullscreen(lockPointer, resizeCanvas, vrDevice);
},nextRAF:0,fakeRequestAnimationFrame:function (func) { // try to keep 60fps between calls to here var now = Date.now(); if (Browser.nextRAF === 0) {
Browser.nextRAF = now + 1000/60;
} else { while (now + 2 >= Browser.nextRAF) { // fudge a little, to avoid timer jitter causing us to do lots of delay:0
Browser.nextRAF += 1000/60;
}
} var delay = Math.max(Browser.nextRAF - now, 0);
setTimeout(func, delay);
},requestAnimationFrame:function requestAnimationFrame(func) { if (typeof window === 'undefined') { // Provide fallback to setTimeout if window is undefined (e.g. in Node.js)
Browser.fakeRequestAnimationFrame(func);
} else { if (!window.requestAnimationFrame) {
window.requestAnimationFrame = window['requestAnimationFrame'] ||
window['mozRequestAnimationFrame'] ||
window['webkitRequestAnimationFrame'] ||
window['msRequestAnimationFrame'] ||
window['oRequestAnimationFrame'] ||
Browser.fakeRequestAnimationFrame;
}
window.requestAnimationFrame(func);
}
},safeCallback:function (func) { returnfunction() { if (!ABORT) return func.apply(null, arguments);
};
},allowAsyncCallbacks:true,queuedAsyncCallbacks:[],pauseAsyncCallbacks:function () {
Browser.allowAsyncCallbacks = false;
},resumeAsyncCallbacks:function () { // marks future callbacks as ok to execute, and synchronously runs any remaining ones right now
Browser.allowAsyncCallbacks = true; if (Browser.queuedAsyncCallbacks.length > 0) { var callbacks = Browser.queuedAsyncCallbacks;
Browser.queuedAsyncCallbacks = [];
callbacks.forEach(function(func) {
func();
});
}
},safeRequestAnimationFrame:function (func) { return Browser.requestAnimationFrame(function() { if (ABORT) return; if (Browser.allowAsyncCallbacks) {
func();
} else {
Browser.queuedAsyncCallbacks.push(func);
}
});
},safeSetTimeout:function (func, timeout) {
Module['noExitRuntime'] = true; return setTimeout(function() { if (ABORT) return; if (Browser.allowAsyncCallbacks) {
func();
} else {
Browser.queuedAsyncCallbacks.push(func);
}
}, timeout);
},safeSetInterval:function (func, timeout) {
Module['noExitRuntime'] = true; return setInterval(function() { if (ABORT) return; if (Browser.allowAsyncCallbacks) {
func();
} // drop it on the floor otherwise, next interval will kick in
}, timeout);
},getMimetype:function (name) { return { 'jpg': 'image/jpeg', 'jpeg': 'image/jpeg', 'png': 'image/png', 'bmp': 'image/bmp', 'ogg': 'audio/ogg', 'wav': 'audio/wav', 'mp3': 'audio/mpeg'
}[name.substr(name.lastIndexOf('.')+1)];
},getUserMedia:function (func) { if(!window.getUserMedia) {
window.getUserMedia = navigator['getUserMedia'] ||
navigator['mozGetUserMedia'];
}
window.getUserMedia(func);
},getMovementX:function (event) { return event['movementX'] ||
event['mozMovementX'] ||
event['webkitMovementX'] ||
0;
},getMovementY:function (event) { return event['movementY'] ||
event['mozMovementY'] ||
event['webkitMovementY'] ||
0;
},getMouseWheelDelta:function (event) { var delta = 0; switch (event.type) { case'DOMMouseScroll':
delta = event.detail; break; case'mousewheel':
delta = event.wheelDelta; break; case'wheel':
delta = event['deltaY']; break; default: throw'unrecognized mouse wheel event: ' + event.type;
} return delta;
},mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,touches:{},lastTouches:{},calculateMouseEvent:function (event) { // event should be mousemove, mousedown or mouseup if (Browser.pointerLock) { // When the pointer is locked, calculate the coordinates // based on the movement of the mouse. // Workaround for Firefox bug 764498 if (event.type != 'mousemove' &&
('mozMovementX' in event)) {
Browser.mouseMovementX = Browser.mouseMovementY = 0;
} else {
Browser.mouseMovementX = Browser.getMovementX(event);
Browser.mouseMovementY = Browser.getMovementY(event);
}
// check if SDL is available if (typeof SDL != "undefined") {
Browser.mouseX = SDL.mouseX + Browser.mouseMovementX;
Browser.mouseY = SDL.mouseY + Browser.mouseMovementY;
} else { // just add the mouse delta to the current absolut mouse position // FIXME: ideally this should be clamped against the canvas size and zero
Browser.mouseX += Browser.mouseMovementX;
Browser.mouseY += Browser.mouseMovementY;
}
} else { // Otherwise, calculate the movement based on the changes // in the coordinates. var rect = Module["canvas"].getBoundingClientRect(); var cw = Module["canvas"].width; var ch = Module["canvas"].height;
// Neither .scrollX or .pageXOffset are defined in a spec, but // we prefer .scrollX because it is currently in a spec draft. // (see: http://www.w3.org/TR/2013/WD-cssom-view-20131217/) var scrollX = ((typeof window.scrollX !== 'undefined') ? window.scrollX : window.pageXOffset); var scrollY = ((typeof window.scrollY !== 'undefined') ? window.scrollY : window.pageYOffset);
if (event.type === 'touchstart' || event.type === 'touchend' || event.type === 'touchmove') { var touch = event.touch; if (touch === undefined) { return; // the "touch" property is only defined in SDL
} var adjustedX = touch.pageX - (scrollX + rect.left); var adjustedY = touch.pageY - (scrollY + rect.top);
if (event.type === 'touchstart') {
Browser.lastTouches[touch.identifier] = coords;
Browser.touches[touch.identifier] = coords;
} elseif (event.type === 'touchend' || event.type === 'touchmove') { var last = Browser.touches[touch.identifier]; if (!last) last = coords;
Browser.lastTouches[touch.identifier] = last;
Browser.touches[touch.identifier] = coords;
} return;
}
var x = event.pageX - (scrollX + rect.left); var y = event.pageY - (scrollY + rect.top);
// the canvas might be CSS-scaled compared to its backbuffer; // SDL-using content will want mouse coordinates in terms // of backbuffer units.
x = x * (cw / rect.width);
y = y * (ch / rect.height);
Browser.mouseMovementX = x - Browser.mouseX;
Browser.mouseMovementY = y - Browser.mouseY;
Browser.mouseX = x;
Browser.mouseY = y;
}
},asyncLoad:function (url, onload, onerror, noRunDep) { var dep = !noRunDep ? getUniqueRunDependency('al ' + url) : '';
Module['readAsync'](url, function(arrayBuffer) { assert(arrayBuffer, 'Loading data file "' + url + '" failed (no arrayBuffer).');
onload(new Uint8Array(arrayBuffer)); if (dep) removeRunDependency(dep);
}, function(event) { if (onerror) {
onerror();
} else { throw'Loading data file "' + url + '" failed.';
}
}); if (dep) addRunDependency(dep);
},resizeListeners:[],updateResizeListeners:function () { var canvas = Module['canvas'];
Browser.resizeListeners.forEach(function(listener) {
listener(canvas.width, canvas.height);
});
},setCanvasSize:function (width, height, noUpdates) { var canvas = Module['canvas'];
Browser.updateCanvasDimensions(canvas, width, height); if (!noUpdates) Browser.updateResizeListeners();
},windowedWidth:0,windowedHeight:0,setFullscreenCanvasSize:function () { // check if SDL is available if (typeof SDL != "undefined") { var flags = HEAPU32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)];
flags = flags | 0x00800000; // set SDL_FULLSCREEN flag
HEAP32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]=flags
}
Browser.updateResizeListeners();
},setWindowedCanvasSize:function () { // check if SDL is available if (typeof SDL != "undefined") { var flags = HEAPU32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)];
flags = flags & ~0x00800000; // clear SDL_FULLSCREEN flag
HEAP32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]=flags
}
Browser.updateResizeListeners();
},updateCanvasDimensions:function (canvas, wNative, hNative) { if (wNative && hNative) {
canvas.widthNative = wNative;
canvas.heightNative = hNative;
} else {
wNative = canvas.widthNative;
hNative = canvas.heightNative;
} var w = wNative; var h = hNative; if (Module['forcedAspectRatio'] && Module['forcedAspectRatio'] > 0) { if (w/h < Module['forcedAspectRatio']) {
w = Math.round(h * Module['forcedAspectRatio']);
} else {
h = Math.round(w / Module['forcedAspectRatio']);
}
} if (((document['fullscreenElement'] || document['mozFullScreenElement'] ||
document['msFullscreenElement'] || document['webkitFullscreenElement'] ||
document['webkitCurrentFullScreenElement']) === canvas.parentNode) && (typeof screen != 'undefined')) { var factor = Math.min(screen.width / w, screen.height / h);
w = Math.round(w * factor);
h = Math.round(h * factor);
} if (Browser.resizeCanvas) { if (canvas.width != w) canvas.width = w; if (canvas.height != h) canvas.height = h; if (typeof canvas.style != 'undefined') {
canvas.style.removeProperty( "width");
canvas.style.removeProperty("height");
}
} else { if (canvas.width != wNative) canvas.width = wNative; if (canvas.height != hNative) canvas.height = hNative; if (typeof canvas.style != 'undefined') { if (w != wNative || h != hNative) {
canvas.style.setProperty( "width", w + "px", "important");
canvas.style.setProperty("height", h + "px", "important");
} else {
canvas.style.removeProperty( "width");
canvas.style.removeProperty("height");
}
}
}
},wgetRequests:{},nextWgetRequestHandle:0,getNextWgetRequestHandle:function () { var handle = Browser.nextWgetRequestHandle;
Browser.nextWgetRequestHandle++; return handle;
}};function _emscripten_set_main_loop_timing(mode, value) {
Browser.mainLoop.timingMode = mode;
Browser.mainLoop.timingValue = value;
if (!Browser.mainLoop.func) { return 1; // Return non-zero on failure, can't set timing mode when there is no main loop.
}
if (mode == 0 /*EM_TIMING_SETTIMEOUT*/) {
Browser.mainLoop.scheduler = function Browser_mainLoop_scheduler_setTimeout() { var timeUntilNextTick = Math.max(0, Browser.mainLoop.tickStartTime + value - _emscripten_get_now())|0;
setTimeout(Browser.mainLoop.runner, timeUntilNextTick); // doing this each time means that on exception, we stop
};
Browser.mainLoop.method = 'timeout';
} elseif (mode == 1 /*EM_TIMING_RAF*/) {
Browser.mainLoop.scheduler = function Browser_mainLoop_scheduler_rAF() {
Browser.requestAnimationFrame(Browser.mainLoop.runner);
};
Browser.mainLoop.method = 'rAF';
} elseif (mode == 2 /*EM_TIMING_SETIMMEDIATE*/) { if (!window['setImmediate']) { // Emulate setImmediate. (note: not a complete polyfill, we don't emulate clearImmediate() to keep code size to minimum, since not needed) var setImmediates = []; var emscriptenMainLoopMessageId = 'setimmediate'; function Browser_setImmediate_messageHandler(event) { if (event.source === window && event.data === emscriptenMainLoopMessageId) {
event.stopPropagation();
setImmediates.shift()();
}
}
window.addEventListener("message", Browser_setImmediate_messageHandler, true);
window['setImmediate'] = function Browser_emulated_setImmediate(func) {
setImmediates.push(func);
}
}
Browser.mainLoop.scheduler = function Browser_mainLoop_scheduler_setImmediate() {
window['setImmediate'](Browser.mainLoop.runner);
};
Browser.mainLoop.method = 'immediate';
} return 0;
}
assert(!Browser.mainLoop.func, 'emscripten_set_main_loop: there can only be one main loop function at once: call emscripten_cancel_main_loop to cancel the previous one before setting a new one with different parameters.');
var thisMainLoopId = Browser.mainLoop.currentlyRunningMainloop;
Browser.mainLoop.runner = function Browser_mainLoop_runner() { if (ABORT) return; if (Browser.mainLoop.queue.length > 0) { var start = Date.now(); var blocker = Browser.mainLoop.queue.shift();
blocker.func(blocker.arg); if (Browser.mainLoop.remainingBlockers) { var remaining = Browser.mainLoop.remainingBlockers; var next = remaining%1 == 0 ? remaining-1 : Math.floor(remaining); if (blocker.counted) {
Browser.mainLoop.remainingBlockers = next;
} else { // not counted, but move the progress along a tiny bit
next = next + 0.5; // do not steal all the next one's progress
Browser.mainLoop.remainingBlockers = (8*remaining + next)/9;
}
}
console.log('main loop blocker "' + blocker.name + '" took ' + (Date.now() - start) + ' ms'); //, left: ' + Browser.mainLoop.remainingBlockers);
Browser.mainLoop.updateStatus();
// catches pause/resume main loop from blocker execution if (thisMainLoopId < Browser.mainLoop.currentlyRunningMainloop) return;
setTimeout(Browser.mainLoop.runner, 0); return;
}
// catch pauses from non-main loop sources if (thisMainLoopId < Browser.mainLoop.currentlyRunningMainloop) return;
// Implement very basic swap interval control
Browser.mainLoop.currentFrameNumber = Browser.mainLoop.currentFrameNumber + 1 | 0; if (Browser.mainLoop.timingMode == 1/*EM_TIMING_RAF*/ && Browser.mainLoop.timingValue > 1 && Browser.mainLoop.currentFrameNumber % Browser.mainLoop.timingValue != 0) { // Not the scheduled time to render this frame - skip.
Browser.mainLoop.scheduler(); return;
} elseif (Browser.mainLoop.timingMode == 0/*EM_TIMING_SETTIMEOUT*/) {
Browser.mainLoop.tickStartTime = _emscripten_get_now();
}
// Signal GL rendering layer that processing of a new frame is about to start. This helps it optimize // VBO double-buffering and reduce GPU stalls.
if (Browser.mainLoop.method === 'timeout' && Module.ctx) {
Module.printErr('Looks like you are rendering without using requestAnimationFrame for the main loop. You should use 0 for the frame rate in emscripten_set_main_loop in order to use requestAnimationFrame, as that can greatly improve your frame rates!');
Browser.mainLoop.method = ''; // just warn once per call to set main loop
}
Browser.mainLoop.runIter(browserIterationFunc);
// catch pauses from the main loop itself if (thisMainLoopId < Browser.mainLoop.currentlyRunningMainloop) return;
// Queue new audio data. This is important to be right after the main loop invocation, so that we will immediately be able // to queue the newest produced audio samples. // TODO: Consider adding pre- and post- rAF callbacks so that GL.newRenderingFrameStarted() and SDL.audio.queueNewAudioData() // do not need to be hardcoded into this function, but can be more generic. if (typeof SDL === 'object' && SDL.audio && SDL.audio.queueNewAudioData) SDL.audio.queueNewAudioData();
Browser.mainLoop.scheduler();
}
if (!noSetTiming) { if (fps && fps > 0) _emscripten_set_main_loop_timing(0/*EM_TIMING_SETTIMEOUT*/, 1000.0 / fps); else _emscripten_set_main_loop_timing(1/*EM_TIMING_RAF*/, 1); // Do rAF by rendering each frame (no decimating)
Browser.mainLoop.scheduler();
}
if (simulateInfiniteLoop) { throw'SimulateInfiniteLoop';
}
}
function _pthread_cleanup_pop() { assert(_pthread_cleanup_push.level == __ATEXIT__.length, 'cannot pop if something else added meanwhile!');
__ATEXIT__.pop();
_pthread_cleanup_push.level = __ATEXIT__.length;
}
function _abort() {
Module['abort']();
}
function __ZSt18uncaught_exceptionv() { // std::uncaught_exception() return !!__ZSt18uncaught_exceptionv.uncaught_exception;
}
var EXCEPTIONS={last:0,caught:[],infos:{},deAdjust:function (adjusted) { if (!adjusted || EXCEPTIONS.infos[adjusted]) return adjusted; for (var ptr in EXCEPTIONS.infos) { var info = EXCEPTIONS.infos[ptr]; if (info.adjusted === 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]; if (info && !info.caught) {
info.caught = true;
__ZSt18uncaught_exceptionv.uncaught_exception--;
} if (info) info.rethrown = false;
EXCEPTIONS.caught.push(ptr);
EXCEPTIONS.addRef(EXCEPTIONS.deAdjust(ptr)); return ptr;
}
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 ___lock() {}
function ___unlock() {}
var SYSCALLS={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()); return ret;
},get64:function () { var low = SYSCALLS.get(), high = SYSCALLS.get(); if (low >= 0) assert(high === 0); elseassert(high === -1); return low;
},getZero:function () { assert(SYSCALLS.get() === 0);
}};function ___syscall6(which, varargs) {SYSCALLS.varargs = varargs; try { // close var stream = SYSCALLS.getStreamFromFD();
FS.close(stream); return 0;
} catch (e) { if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e); return -e.errno;
}
}
var PTHREAD_SPECIFIC={};function _pthread_getspecific(key) { return PTHREAD_SPECIFIC[key] || 0;
}
function ___setErrNo(value) { if (Module['___errno_location']) HEAP32[((Module['___errno_location']())>>2)]=value; return value;
}
Module["_sbrk"] = _sbrk;
function _clock() { if (_clock.start === undefined) _clock.start = Date.now(); return ((Date.now() - _clock.start) * (1000000 / 1000))|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 ___resumeException(ptr) { if (!EXCEPTIONS.last) { EXCEPTIONS.last = ptr; } throw ptr + " - Exception catching is disabled, this exception cannot be caught. Compile with -s DISABLE_EXCEPTION_CATCHING=0 or DISABLE_EXCEPTION_CATCHING=2 to catch.";
}function ___cxa_find_matching_catch() { var thrown = EXCEPTIONS.last; if (!thrown) { // just pass through the null ptr return ((Runtime.setTempRet0(0),0)|0);
} var info = EXCEPTIONS.infos[thrown]; var throwntype = info.type; if (!throwntype) { // just pass through the thrown ptr return ((Runtime.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 ((Runtime.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 ((Runtime.setTempRet0(throwntype),thrown)|0);
}function ___gxx_personality_v0() {
}
if (memoryInitializer) { if (typeof Module['locateFile'] === 'function') {
memoryInitializer = Module['locateFile'](memoryInitializer);
} elseif (Module['memoryInitializerPrefixURL']) {
memoryInitializer = Module['memoryInitializerPrefixURL'] + memoryInitializer;
} var data = Module['readBinary'](memoryInitializer);
HEAPU8.set(data, Runtime.GLOBAL_BASE);
}
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 preloadStartTime = null; 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
}
Module['callMain'] = Module.callMain = function callMain(args) {
args = args || [];
ensureInitRuntime();
var argc = args.length+1; function pad() { for (var i = 0; i < 4-1; i++) {
argv.push(0);
}
} var argv = [allocate(intArrayFromString(Module['thisProgram']), 'i8', ALLOC_NORMAL) ];
pad(); for (var i = 0; i < argc-1; i = i + 1) {
argv.push(allocate(intArrayFromString(args[i]), 'i8', ALLOC_NORMAL));
pad();
}
argv.push(0);
argv = allocate(argv, 'i32', ALLOC_NORMAL);
try {
var ret = Module['_main'](argc, argv, 0);
// if we're not running an evented main loop, it's time to exit
exit(ret, /* implicit = */ true);
} catch(e) { if (e instanceof ExitStatus) { // exit() throws this once it's done to make sure execution // has been stopped completely return;
} elseif (e == 'SimulateInfiniteLoop') { // running an evented main loop, don't immediately exit
Module['noExitRuntime'] = true; return;
} else { if (e && typeof e === 'object' && e.stack) Module.printErr('exception thrown: ' + [e, e.stack]); throw e;
}
} finally {
calledMain = true;
}
}
function run(args) {
args = args || Module['arguments'];
if (preloadStartTime === null) preloadStartTime = Date.now();
if (runDependencies > 0) { return;
}
preRun();
if (runDependencies > 0) return; // a preRun added a dependency, run will be called later if (Module['calledRun']) return; // run may have just been called through dependencies being fulfilled just in this very frame
function doRun() { if (Module['calledRun']) return; // run may have just been called while the async setStatus time below was happening
Module['calledRun'] = true;
if (ABORT) return;
ensureInitRuntime();
preMain();
if (Module['onRuntimeInitialized']) Module['onRuntimeInitialized']();
if (Module['_main'] && shouldRunNow) Module['callMain'](args);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.