// The Module object: Our interface to the outside world. We import // and export values on it. There are various ways Module can be used: // 1. Not defined. We create it here // 2. A function parameter, function(Module) { ..generated code.. } // 3. pre-run appended it, var Module = {}; ..generated code.. // 4. External script tag defines var Module. // We need to check if Module already exists (e.g. case 3 above). // Substitution will be replaced with actual code on later stage of the build, // this way Closure Compiler will not mangle it (e.g. case 4. above). // Note that if you want to run closure, and also to use Module // after the generated code, you will need to define var Module = {}; // before the code. Then that object will be used in the code, and you // can continue to use Module afterwards as well. var Module = typeof Module !== 'undefined' ? Module : {}; // --pre-jses are emitted after the Module integration code, so that they can // refer to Module (if they choose; they can also define Module) // Sometimes an existing Module object exists with properties // meant to overwrite the default module functionality. Here // we collect those properties and reapply _after_ we configure // the current environment's defaults to avoid having to be so // defensive during initialization. var moduleOverrides = {}; var key; for (key in Module) { if (Module.hasOwnProperty(key)) { moduleOverrides[key] = Module[key]; } } var arguments_ = []; var thisProgram = './this.program'; var quit_ = function(status, toThrow) { throw toThrow; }; // Determine the runtime environment we are in. You can customize this by // setting the ENVIRONMENT setting at compile time (see settings.js). var ENVIRONMENT_IS_WEB = true; var ENVIRONMENT_IS_WORKER = false; var ENVIRONMENT_IS_NODE = false; var ENVIRONMENT_IS_SHELL = false; // `/` should be present at the end if `scriptDirectory` is not empty var scriptDirectory = ''; function locateFile(path) { if (Module['locateFile']) { return Module['locateFile'](path, scriptDirectory); } return scriptDirectory + path; } // Hooks that are implemented differently in different runtime environments. var read_, readAsync, readBinary, setWindowTitle; // Note that this includes Node.js workers when relevant (pthreads is enabled). // Node.js workers are detected as a combination of ENVIRONMENT_IS_WORKER and // ENVIRONMENT_IS_NODE. if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { if (ENVIRONMENT_IS_WORKER) { // Check worker, not web, since window could be polyfilled scriptDirectory = self.location.href; } else if (typeof document !== 'undefined' && document.currentScript) { // web scriptDirectory = document.currentScript.src; } // blob urls look like blob:http://site.com/etc/etc and we cannot infer anything from them. // otherwise, slice off the final part of the url to find the script directory. // if scriptDirectory does not contain a slash, lastIndexOf will return -1, // and scriptDirectory will correctly be replaced with an empty string. if (scriptDirectory.indexOf('blob:') !== 0) { scriptDirectory = scriptDirectory.substr(0, scriptDirectory.lastIndexOf('/')+1); } else { scriptDirectory = ''; } // Differentiate the Web Worker from the Node Worker case, as reading must // be done differently. { // include: web_or_worker_shell_read.js read_ = function(url) { var xhr = new XMLHttpRequest(); xhr.open('GET', url, false); xhr.send(null); return xhr.responseText; }; if (ENVIRONMENT_IS_WORKER) { readBinary = function(url) { var xhr = new XMLHttpRequest(); xhr.open('GET', url, false); xhr.responseType = 'arraybuffer'; xhr.send(null); return new Uint8Array(/** @type{!ArrayBuffer} */(xhr.response)); }; } readAsync = function(url, onload, onerror) { var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.responseType = 'arraybuffer'; xhr.onload = function() { if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0 onload(xhr.response); return; } onerror(); }; xhr.onerror = onerror; xhr.send(null); }; // end include: web_or_worker_shell_read.js } setWindowTitle = function(title) { document.title = title }; } else { } // Set up the out() and err() hooks, which are how we can print to stdout or // stderr, respectively. var out = Module['print'] || console.log.bind(console); var err = Module['printErr'] || console.warn.bind(console); // Merge back in the overrides for (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 = null; // Emit code to handle expected values on the Module object. This applies Module.x // to the proper local x. This has two benefits: first, we only emit it if it is // expected to arrive, and second, by using a local everywhere else that can be // minified. if (Module['arguments']) arguments_ = Module['arguments']; if (Module['thisProgram']) thisProgram = Module['thisProgram']; if (Module['quit']) quit_ = Module['quit']; // perform assertions in shell.js after we set up out() and err(), as otherwise if an assertion fails it cannot print the message var STACK_ALIGN = 16; function alignMemory(size, factor) { if (!factor) factor = STACK_ALIGN; // stack alignment (16-byte) by default return Math.ceil(size / factor) * factor; } function getNativeTypeSize(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 4; // A pointer } else if (type[0] === 'i') { var bits = Number(type.substr(1)); assert(bits % 8 === 0, 'getNativeTypeSize invalid bits ' + bits + ', type ' + type); return bits / 8; } else { return 0; } } } } function warnOnce(text) { if (!warnOnce.shown) warnOnce.shown = {}; if (!warnOnce.shown[text]) { warnOnce.shown[text] = 1; err(text); } } // include: runtime_functions.js // Wraps a JS function as a wasm function with a given signature. function convertJsFunctionToWasm(func, sig) { // If the type reflection proposal is available, use the new // "WebAssembly.Function" constructor. // Otherwise, construct a minimal wasm module importing the JS function and // re-exporting it. if (typeof WebAssembly.Function === "function") { var typeNames = { 'i': 'i32', 'j': 'i64', 'f': 'f32', 'd': 'f64' }; var type = { parameters: [], results: sig[0] == 'v' ? [] : [typeNames[sig[0]]] }; for (var i = 1; i < sig.length; ++i) { type.parameters.push(typeNames[sig[i]]); } return new WebAssembly.Function(type, func); } // 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; } var freeTableIndexes = []; // Weak map of functions in the table to their indexes, created on first use. var functionsInTableMap; function getEmptyTableSlot() { // Reuse a free index if there is one, otherwise grow. if (freeTableIndexes.length) { return freeTableIndexes.pop(); } // Grow the table try { wasmTable.grow(1); } catch (err) { if (!(err instanceof RangeError)) { throw err; } throw 'Unable to grow wasm table. Set ALLOW_TABLE_GROWTH.'; } return wasmTable.length - 1; } // Add a wasm function to the table. function addFunctionWasm(func, sig) { // Check if the function is already in the table, to ensure each function // gets a unique index. First, create the map if this is the first use. if (!functionsInTableMap) { functionsInTableMap = new WeakMap(); for (var i = 0; i < wasmTable.length; i++) { var item = wasmTable.get(i); // Ignore null values. if (item) { functionsInTableMap.set(item, i); } } } if (functionsInTableMap.has(func)) { return functionsInTableMap.get(func); } // It's not in the table, add it now. var ret = getEmptyTableSlot(); // Set the new value. try { // Attempting to call this with JS function will cause of table.set() to fail wasmTable.set(ret, func); } catch (err) { if (!(err instanceof TypeError)) { throw err; } var wrapped = convertJsFunctionToWasm(func, sig); wasmTable.set(ret, wrapped); } functionsInTableMap.set(func, ret); return ret; } function removeFunction(index) { functionsInTableMap.delete(wasmTable.get(index)); freeTableIndexes.push(index); } // 'sig' parameter is required for the llvm backend but only when func is not // already a WebAssembly function. function addFunction(func, sig) { return addFunctionWasm(func, sig); } // end include: runtime_functions.js // include: runtime_debug.js // end include: runtime_debug.js function makeBigInt(low, high, unsigned) { return unsigned ? ((+((low>>>0)))+((+((high>>>0)))*4294967296.0)) : ((+((low>>>0)))+((+((high|0)))*4294967296.0)); } var tempRet0 = 0; var setTempRet0 = function(value) { tempRet0 = value; }; var getTempRet0 = function() { return tempRet0; }; // === Preamble library stuff === // Documentation for the public APIs defined in this file must be updated in: // site/source/docs/api_reference/preamble.js.rst // A prebuilt local version of the documentation is available at: // site/build/text/docs/api_reference/preamble.js.txt // You can also build docs locally as HTML or other formats in site/ // An online HTML version (which may be of a different version of Emscripten) // is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html var wasmBinary; if (Module['wasmBinary']) wasmBinary = Module['wasmBinary']; var noExitRuntime = Module['noExitRuntime'] || true; if (typeof WebAssembly !== 'object') { abort('no native wasm support detected'); } // include: runtime_safe_heap.js // 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) /** @param {number} ptr @param {number} value @param {string} type @param {number|boolean=} noSafe */ 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); } } /** @param {number} ptr @param {string} type @param {number|boolean=} noSafe */ 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; } // end include: runtime_safe_heap.js // Wasm globals var wasmMemory; //======================================== // Runtime essentials //======================================== // whether we are quitting the application. no code should run after this. // set in exit() and abort() var ABORT = false; // set by exit() and abort(). Passed to 'onExit' handler. // NOTE: This is also used as the process return code code in shell environments // but only when noExitRuntime is false. var EXITSTATUS; /** @type {function(*, string=)} */ function assert(condition, text) { if (!condition) { abort('Assertion failed: ' + text); } } // 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 assert(func, 'Cannot call unknown function ' + ident + ', make sure it is exported'); return func; } // C calling interface. /** @param {string|null=} returnType @param {Array=} argTypes @param {Arguments|Array=} args @param {Object=} opts */ 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 UTF8ToString(ret); if (returnType === 'boolean') return Boolean(ret); return ret; } 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 = stackSave(); cArgs[i] = converter(args[i]); } else { cArgs[i] = args[i]; } } } var ret = func.apply(null, cArgs); ret = convertReturnValue(ret); if (stack !== 0) stackRestore(stack); return ret; } /** @param {string=} returnType @param {Array=} argTypes @param {Object=} opts */ function cwrap(ident, returnType, argTypes, opts) { argTypes = argTypes || []; // 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 && !opts) { return getCFunc(ident); } return function() { return ccall(ident, returnType, argTypes, arguments, opts); } } var ALLOC_NORMAL = 0; // Tries to use _malloc() var ALLOC_STACK = 1; // Lives for the duration of the current function call // 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. // @allocator: How to allocate memory, see ALLOC_* /** @type {function((Uint8Array|Array), number)} */ function allocate(slab, allocator) { var ret; if (allocator == ALLOC_STACK) { ret = stackAlloc(slab.length); } else { ret = _malloc(slab.length); } if (slab.subarray || slab.slice) { HEAPU8.set(/** @type {!Uint8Array} */(slab), ret); } else { HEAPU8.set(new Uint8Array(slab), ret); } return ret; } // include: runtime_strings.js // runtime_strings.js: Strings related runtime functions that are part of both MINIMAL_RUNTIME and regular runtime. // 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; /** * @param {number} idx * @param {number=} maxBytesToRead * @return {string} */ function UTF8ArrayToString(heap, idx, maxBytesToRead) { var endIdx = idx + maxBytesToRead; var endPtr = idx; // TextDecoder needs to know the byte length in advance, it doesn't stop on null terminator by itself. // Also, use the length info to avoid running tiny strings through TextDecoder, since .subarray() allocates garbage. // (As a tiny code save trick, compare endPtr against endIdx using a negation, so that undefined means Infinity) while (heap[endPtr] && !(endPtr >= endIdx)) ++endPtr; if (endPtr - idx > 16 && heap.subarray && UTF8Decoder) { return UTF8Decoder.decode(heap.subarray(idx, endPtr)); } else { var str = ''; // If building with TextDecoder, we have already computed the string length above, so test loop end condition against that while (idx < endPtr) { // For UTF8 byte structure, see: // http://en.wikipedia.org/wiki/UTF-8#Description // https://www.ietf.org/rfc/rfc2279.txt // https://tools.ietf.org/html/rfc3629 var u0 = heap[idx++]; if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; } var u1 = heap[idx++] & 63; if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; } var u2 = heap[idx++] & 63; if ((u0 & 0xF0) == 0xE0) { u0 = ((u0 & 15) << 12) | (u1 << 6) | u2; } else { u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heap[idx++] & 63); } if (u0 < 0x10000) { str += String.fromCharCode(u0); } else { var ch = u0 - 0x10000; str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); } } } return str; } // Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the emscripten HEAP, returns a // copy of that string as a Javascript String object. // 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', // 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. // heap: 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, heap, 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) { var u1 = str.charCodeAt(++i); u = 0x10000 + ((u & 0x3FF) << 10) | (u1 & 0x3FF); } if (u <= 0x7F) { if (outIdx >= endIdx) break; heap[outIdx++] = u; } else if (u <= 0x7FF) { if (outIdx + 1 >= endIdx) break; heap[outIdx++] = 0xC0 | (u >> 6); heap[outIdx++] = 0x80 | (u & 63); } else if (u <= 0xFFFF) { if (outIdx + 2 >= endIdx) break; heap[outIdx++] = 0xE0 | (u >> 12); heap[outIdx++] = 0x80 | ((u >> 6) & 63); heap[outIdx++] = 0x80 | (u & 63); } else { if (outIdx + 3 >= endIdx) break; heap[outIdx++] = 0xF0 | (u >> 18); heap[outIdx++] = 0x80 | ((u >> 12) & 63); heap[outIdx++] = 0x80 | ((u >> 6) & 63); heap[outIdx++] = 0x80 | (u & 63); } } // Null-terminate the pointer to the buffer. heap[outIdx] = 0; return outIdx - startIdx; } // 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. function stringToUTF8(str, outPtr, maxBytesToWrite) { return stringToUTF8Array(str, HEAPU8,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) { // 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; else if (u <= 0x7FF) len += 2; else if (u <= 0xFFFF) len += 3; else len += 4; } return len; } // end include: runtime_strings.js // include: runtime_strings_extra.js // runtime_strings_extra.js: Strings related runtime functions that are available only in regular runtime. // 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 = HEAPU8[((ptr++)>>0)]; if (!ch) return str; str += String.fromCharCode(ch); } } // 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. function stringToAscii(str, outPtr) { return writeAsciiToMemory(str, outPtr, false); } // 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, maxBytesToRead) { 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; var maxIdx = idx + maxBytesToRead / 2; // If maxBytesToRead is not passed explicitly, it will be undefined, and this // will always evaluate to true. This saves on code size. while (!(idx >= maxIdx) && HEAPU16[idx]) ++idx; endPtr = idx << 1; if (endPtr - ptr > 32 && UTF16Decoder) { return UTF16Decoder.decode(HEAPU8.subarray(ptr, endPtr)); } else { var str = ''; // If maxBytesToRead is not passed explicitly, it will be undefined, and the for-loop's condition // will always evaluate to true. The loop is then terminated on the first null char. for (var i = 0; !(i >= maxBytesToRead / 2); ++i) { var codeUnit = HEAP16[(((ptr)+(i*2))>>1)]; if (codeUnit == 0) break; // fromCharCode constructs a character from a UTF-16 code unit, so we can pass the UTF16 string right through. str += String.fromCharCode(codeUnit); } return str; } } // 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, maxBytesToRead) { var i = 0; var str = ''; // If maxBytesToRead is not passed explicitly, it will be undefined, and this // will always evaluate to true. This saves on code size. while (!(i >= maxBytesToRead / 4)) { var utf32 = HEAP32[(((ptr)+(i*4))>>2)]; if (utf32 == 0) break; ++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); } } return str; } // 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; } // Allocate heap space for a JS string, and write it there. // It is the responsibility of the caller to free() that memory. function allocateUTF8(str) { var size = lengthBytesUTF8(str) + 1; var ret = _malloc(size); if (ret) stringToUTF8Array(str, HEAP8, ret, size); return ret; } // Allocate stack space for a JS string, and write it there. function allocateUTF8OnStack(str) { var size = lengthBytesUTF8(str) + 1; var ret = stackAlloc(size); stringToUTF8Array(str, HEAP8, ret, size); 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 @param {boolean=} dontAddNull */ 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); } /** @param {boolean=} dontAddNull */ 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; } // end include: runtime_strings_extra.js // Memory management function alignUp(x, multiple) { if (x % multiple > 0) { x += multiple - (x % multiple); } return x; } var HEAP, /** @type {ArrayBuffer} */ buffer, /** @type {Int8Array} */ HEAP8, /** @type {Uint8Array} */ HEAPU8, /** @type {Int16Array} */ HEAP16, /** @type {Uint16Array} */ HEAPU16, /** @type {Int32Array} */ HEAP32, /** @type {Uint32Array} */ HEAPU32, /** @type {Float32Array} */ HEAPF32, /** @type {Float64Array} */ HEAPF64; function updateGlobalBufferAndViews(buf) { buffer = buf; Module['HEAP8'] = HEAP8 = new Int8Array(buf); Module['HEAP16'] = HEAP16 = new Int16Array(buf); Module['HEAP32'] = HEAP32 = new Int32Array(buf); Module['HEAPU8'] = HEAPU8 = new Uint8Array(buf); Module['HEAPU16'] = HEAPU16 = new Uint16Array(buf); Module['HEAPU32'] = HEAPU32 = new Uint32Array(buf); Module['HEAPF32'] = HEAPF32 = new Float32Array(buf); Module['HEAPF64'] = HEAPF64 = new Float64Array(buf); } var TOTAL_STACK = 5242880; var INITIAL_MEMORY = Module['INITIAL_MEMORY'] || 1468006400; // include: runtime_init_table.js // In regular non-RELOCATABLE mode the table is exported // from the wasm module and this will be assigned once // the exports are available. var wasmTable; // end include: runtime_init_table.js // include: runtime_stack_check.js // end include: runtime_stack_check.js // include: runtime_assertions.js // end include: runtime_assertions.js 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 main() is called var runtimeInitialized = false; var runtimeExited = false; function preRun() { if (Module['preRun']) { if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']]; while (Module['preRun'].length) { addOnPreRun(Module['preRun'].shift()); } } callRuntimeCallbacks(__ATPRERUN__); } function initRuntime() { runtimeInitialized = true; if (!Module["noFSInit"] && !FS.init.initialized) FS.init(); TTY.init(); callRuntimeCallbacks(__ATINIT__); } function preMain() { FS.ignorePermissions = false; callRuntimeCallbacks(__ATMAIN__); } function exitRuntime() { runtimeExited = true; } function postRun() { if (Module['postRun']) { if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']]; while (Module['postRun'].length) { addOnPostRun(Module['postRun'].shift()); } } callRuntimeCallbacks(__ATPOSTRUN__); } function addOnPreRun(cb) { __ATPRERUN__.unshift(cb); } function addOnInit(cb) { __ATINIT__.unshift(cb); } function addOnPreMain(cb) { __ATMAIN__.unshift(cb); } function addOnExit(cb) { } function addOnPostRun(cb) { __ATPOSTRUN__.unshift(cb); } // include: runtime_math.js // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/fround // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc // end include: runtime_math.js // A counter of dependencies for calling run(). If we need to // do asynchronous work before running, increment this and // decrement it. Incrementing must happen in a place like // Module.preRun (used by emcc to add file preloading). // Note that you can add dependencies in preRun, even though // it happens right before run - run will be postponed until // the dependencies are met. var runDependencies = 0; var runDependencyWatcher = null; var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled function getUniqueRunDependency(id) { return id; } function addRunDependency(id) { runDependencies++; if (Module['monitorRunDependencies']) { Module['monitorRunDependencies'](runDependencies); } } 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["preloadedImages"] = {}; // maps url to image data Module["preloadedAudios"] = {}; // maps url to audio data /** @param {string|number=} what */ function abort(what) { if (Module['onAbort']) { Module['onAbort'](what); } what += ''; err(what); ABORT = true; EXITSTATUS = 1; what = 'abort(' + what + '). Build with -s ASSERTIONS=1 for more info.'; // Use a wasm runtime error, because a JS error might be seen as a foreign // exception, which means we'd run destructors on it. We need the error to // simply make the program stop. var e = new WebAssembly.RuntimeError(what); // Throw the error whether or not MODULARIZE is set because abort is used // in code paths apart from instantiation where an exception is expected // to be thrown when abort is called. throw e; } // {{MEM_INITIALIZER}} // include: memoryprofiler.js // end include: memoryprofiler.js // include: URIUtils.js function hasPrefix(str, prefix) { return String.prototype.startsWith ? str.startsWith(prefix) : str.indexOf(prefix) === 0; } // Prefix of data URIs emitted by SINGLE_FILE and related options. var dataURIPrefix = 'data:application/octet-stream;base64,'; // Indicates whether filename is a base64 data URI. function isDataURI(filename) { return hasPrefix(filename, dataURIPrefix); } var fileURIPrefix = "file://"; // Indicates whether filename is delivered via file protocol (as opposed to http/https) function isFileURI(filename) { return hasPrefix(filename, fileURIPrefix); } // end include: URIUtils.js var wasmBinaryFile = 'b3006.wasm'; if (!isDataURI(wasmBinaryFile)) { wasmBinaryFile = locateFile(wasmBinaryFile); } function getBinary(file) { try { if (file == wasmBinaryFile && wasmBinary) { return new Uint8Array(wasmBinary); } if (readBinary) { return readBinary(file); } 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, try to to load it asynchronously. // Fetch has some additional restrictions over XHR, like it can't be used on a file:// url. // See https://github.com/github/fetch/pull/92#issuecomment-140665932 // Cordova or Electron apps are typically loaded from a file:// url. // So use fetch if it is available and the url is not a file, otherwise fall back to XHR. if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) { if (typeof fetch === 'function' ) { 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(wasmBinaryFile); }); } } // Otherwise, getBinary should be able to get it synchronously return Promise.resolve().then(function() { return getBinary(wasmBinaryFile); }); } // Create the wasm instance. // Receives the wasm imports, returns the exports. function createWasm() { // prepare imports var info = { 'env': asmLibraryArg, 'wasi_snapshot_preview1': asmLibraryArg, }; // Load the wasm module and create an instance of using native support in the JS engine. // handle a generated wasm instance, receiving its exports and // performing other necessary setup /** @param {WebAssembly.Module=} module*/ function receiveInstance(instance, module) { var exports = instance.exports; Module['asm'] = exports; wasmMemory = Module['asm']['memory']; updateGlobalBufferAndViews(wasmMemory.buffer); wasmTable = Module['asm']['__indirect_function_table']; addOnInit(Module['asm']['__wasm_call_ctors']); removeRunDependency('wasm-instantiate'); } // we can't run yet (except in a pthread, where we have a custom sync instantiator) addRunDependency('wasm-instantiate'); 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 instantiateArrayBuffer(receiver) { return getBinaryPromise().then(function(binary) { var result = WebAssembly.instantiate(binary, info); return result; }).then(receiver, function(reason) { err('failed to asynchronously prepare wasm: ' + reason); abort(reason); }); } // Prefer streaming instantiation if available. function instantiateAsync() { if (!wasmBinary && typeof WebAssembly.instantiateStreaming === 'function' && !isDataURI(wasmBinaryFile) && typeof fetch === 'function') { return fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function (response) { var result = WebAssembly.instantiateStreaming(response, info); return result.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'); return instantiateArrayBuffer(receiveInstantiatedSource); }); }); } else { 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; } } instantiateAsync(); return {}; // no exports yet; we'll fill them in later } // Globals used by JS i64 conversions (see makeSetValue) var tempDouble; var tempI64; // === Body === var ASM_CONSTS = { 54696: function($0, $1, $2) {var w = $0; var h = $1; var pixels = $2; if (!Module['SDL2']) Module['SDL2'] = {}; var SDL2 = Module['SDL2']; if (SDL2.ctxCanvas !== Module['canvas']) { SDL2.ctx = Module['createContext'](Module['canvas'], false, true); SDL2.ctxCanvas = Module['canvas']; } if (SDL2.w !== w || SDL2.h !== h || SDL2.imageCtx !== SDL2.ctx) { SDL2.image = SDL2.ctx.createImageData(w, h); SDL2.w = w; SDL2.h = h; SDL2.imageCtx = SDL2.ctx; } var data = SDL2.image.data; var src = pixels >> 2; var dst = 0; var num; if (typeof CanvasPixelArray !== 'undefined' && data instanceof CanvasPixelArray) { num = data.length; while (dst < num) { var val = HEAP32[src]; data[dst ] = val & 0xff; data[dst+1] = (val >> 8) & 0xff; data[dst+2] = (val >> 16) & 0xff; data[dst+3] = 0xff; src++; dst += 4; } } else { if (SDL2.data32Data !== data) { SDL2.data32 = new Int32Array(data.buffer); SDL2.data8 = new Uint8Array(data.buffer); } var data32 = SDL2.data32; num = data32.length; data32.set(HEAP32.subarray(src, src + num)); var data8 = SDL2.data8; var i = 3; var j = i + 4*num; if (num % 8 == 0) { while (i < j) { data8[i] = 0xff; i = i + 4 | 0; data8[i] = 0xff; i = i + 4 | 0; data8[i] = 0xff; i = i + 4 | 0; data8[i] = 0xff; i = i + 4 | 0; data8[i] = 0xff; i = i + 4 | 0; data8[i] = 0xff; i = i + 4 | 0; data8[i] = 0xff; i = i + 4 | 0; data8[i] = 0xff; i = i + 4 | 0; } } else { while (i < j) { data8[i] = 0xff; i = i + 4 | 0; } } } SDL2.ctx.putImageData(SDL2.image, 0, 0); return 0;}, 56151: function($0) {if (Module['canvas']) { Module['canvas'].style['cursor'] = UTF8ToString($0); } return 0;}, 56244: function() {if (Module['canvas']) { Module['canvas'].style['cursor'] = 'none'; }}, 56313: function($0, $1, $2, $3, $4) {var w = $0; var h = $1; var hot_x = $2; var hot_y = $3; var pixels = $4; var canvas = document.createElement("canvas"); canvas.width = w; canvas.height = h; var ctx = canvas.getContext("2d"); var image = ctx.createImageData(w, h); var data = image.data; var src = pixels >> 2; var dst = 0; var num; if (typeof CanvasPixelArray !== 'undefined' && data instanceof CanvasPixelArray) { num = data.length; while (dst < num) { var val = HEAP32[src]; data[dst ] = val & 0xff; data[dst+1] = (val >> 8) & 0xff; data[dst+2] = (val >> 16) & 0xff; data[dst+3] = (val >> 24) & 0xff; src++; dst += 4; } } else { var data32 = new Int32Array(data.buffer); num = data32.length; data32.set(HEAP32.subarray(src, src + num)); } ctx.putImageData(image, 0, 0); var url = hot_x === 0 && hot_y === 0 ? "url(" + canvas.toDataURL() + "), auto" : "url(" + canvas.toDataURL() + ") " + hot_x + " " + hot_y + ", auto"; var urlBuf = _malloc(url.length + 1); stringToUTF8(url, urlBuf, url.length + 1); return urlBuf;}, 57302: function($0) {if (typeof setWindowTitle !== 'undefined') { setWindowTitle(UTF8ToString($0)); } return 0;}, 57397: function() {return window.innerWidth;}, 57427: function() {return window.innerHeight;}, 57458: function() {return screen.width;}, 57483: function() {return screen.height;}, 57509: function() {if (typeof(AudioContext) !== 'undefined') { return 1; } else if (typeof(webkitAudioContext) !== 'undefined') { return 1; } return 0;}, 57646: function() {if ((typeof(navigator.mediaDevices) !== 'undefined') && (typeof(navigator.mediaDevices.getUserMedia) !== 'undefined')) { return 1; } else if (typeof(navigator.webkitGetUserMedia) !== 'undefined') { return 1; } return 0;}, 57870: function($0) {var SDL2 = Module['SDL2']; if ($0) { if (SDL2.capture.silenceTimer !== undefined) { clearTimeout(SDL2.capture.silenceTimer); } if (SDL2.capture.stream !== undefined) { var tracks = SDL2.capture.stream.getAudioTracks(); for (var i = 0; i < tracks.length; i++) { SDL2.capture.stream.removeTrack(tracks[i]); } SDL2.capture.stream = undefined; } if (SDL2.capture.scriptProcessorNode !== undefined) { SDL2.capture.scriptProcessorNode.onaudioprocess = function(audioProcessingEvent) {}; SDL2.capture.scriptProcessorNode.disconnect(); SDL2.capture.scriptProcessorNode = undefined; } if (SDL2.capture.mediaStreamNode !== undefined) { SDL2.capture.mediaStreamNode.disconnect(); SDL2.capture.mediaStreamNode = undefined; } if (SDL2.capture.silenceBuffer !== undefined) { SDL2.capture.silenceBuffer = undefined } SDL2.capture = undefined; } else { if (SDL2.audio.scriptProcessorNode != undefined) { SDL2.audio.scriptProcessorNode.disconnect(); SDL2.audio.scriptProcessorNode = undefined; } SDL2.audio = undefined; } if ((SDL2.audioContext !== undefined) && (SDL2.audio === undefined) && (SDL2.capture === undefined)) { SDL2.audioContext.close(); SDL2.audioContext = undefined; }}, 59042: function($0) {if(typeof(Module['SDL2']) === 'undefined') { Module['SDL2'] = {}; } var SDL2 = Module['SDL2']; if (!$0) { SDL2.audio = {}; } else { SDL2.capture = {}; } if (!SDL2.audioContext) { if (typeof(AudioContext) !== 'undefined') { SDL2.audioContext = new AudioContext(); } else if (typeof(webkitAudioContext) !== 'undefined') { SDL2.audioContext = new webkitAudioContext(); } if (SDL2.audioContext) { autoResumeAudioContext(SDL2.audioContext); } } return SDL2.audioContext === undefined ? -1 : 0;}, 59535: function() {var SDL2 = Module['SDL2']; return SDL2.audioContext.sampleRate;}, 59603: function($0, $1, $2, $3) {var SDL2 = Module['SDL2']; var have_microphone = function(stream) { if (SDL2.capture.silenceTimer !== undefined) { clearTimeout(SDL2.capture.silenceTimer); SDL2.capture.silenceTimer = undefined; } SDL2.capture.mediaStreamNode = SDL2.audioContext.createMediaStreamSource(stream); SDL2.capture.scriptProcessorNode = SDL2.audioContext.createScriptProcessor($1, $0, 1); SDL2.capture.scriptProcessorNode.onaudioprocess = function(audioProcessingEvent) { if ((SDL2 === undefined) || (SDL2.capture === undefined)) { return; } audioProcessingEvent.outputBuffer.getChannelData(0).fill(0.0); SDL2.capture.currentCaptureBuffer = audioProcessingEvent.inputBuffer; dynCall('vi', $2, [$3]); }; SDL2.capture.mediaStreamNode.connect(SDL2.capture.scriptProcessorNode); SDL2.capture.scriptProcessorNode.connect(SDL2.audioContext.destination); SDL2.capture.stream = stream; }; var no_microphone = function(error) { }; SDL2.capture.silenceBuffer = SDL2.audioContext.createBuffer($0, $1, SDL2.audioContext.sampleRate); SDL2.capture.silenceBuffer.getChannelData(0).fill(0.0); var silence_callback = function() { SDL2.capture.currentCaptureBuffer = SDL2.capture.silenceBuffer; dynCall('vi', $2, [$3]); }; SDL2.capture.silenceTimer = setTimeout(silence_callback, ($1 / SDL2.audioContext.sampleRate) * 1000); if ((navigator.mediaDevices !== undefined) && (navigator.mediaDevices.getUserMedia !== undefined)) { navigator.mediaDevices.getUserMedia({ audio: true, video: false }).then(have_microphone).catch(no_microphone); } else if (navigator.webkitGetUserMedia !== undefined) { navigator.webkitGetUserMedia({ audio: true, video: false }, have_microphone, no_microphone); }}, 61255: function($0, $1, $2, $3) {var SDL2 = Module['SDL2']; SDL2.audio.scriptProcessorNode = SDL2.audioContext['createScriptProcessor']($1, 0, $0); SDL2.audio.scriptProcessorNode['onaudioprocess'] = function (e) { if ((SDL2 === undefined) || (SDL2.audio === undefined)) { return; } SDL2.audio.currentOutputBuffer = e['outputBuffer']; dynCall('vi', $2, [$3]); }; SDL2.audio.scriptProcessorNode['connect'](SDL2.audioContext['destination']);}, 61665: function($0, $1) {var SDL2 = Module['SDL2']; var numChannels = SDL2.audio.currentOutputBuffer['numberOfChannels']; for (var c = 0; c < numChannels; ++c) { var channelData = SDL2.audio.currentOutputBuffer['getChannelData'](c); if (channelData.length != $1) { throw 'Web Audio output buffer length mismatch! Destination size: ' + channelData.length + ' samples vs expected ' + $1 + ' samples!'; } for (var j = 0; j < $1; ++j) { channelData[j] = HEAPF32[$0 + ((j*numChannels + c) << 2) >> 2]; } }}, 62145: function($0, $1) {var SDL2 = Module['SDL2']; var numChannels = SDL2.capture.currentCaptureBuffer.numberOfChannels; for (var c = 0; c < numChannels; ++c) { var channelData = SDL2.capture.currentCaptureBuffer.getChannelData(c); if (channelData.length != $1) { throw 'Web Audio capture buffer length mismatch! Destination size: ' + channelData.length + ' samples vs expected ' + $1 + ' samples!'; } if (numChannels == 1) { for (var j = 0; j < $1; ++j) { setValue($0 + (j * 4), channelData[j], 'float'); } } else { for (var j = 0; j < $1; ++j) { setValue($0 + (((j * numChannels) + c) * 4), channelData[j], 'float'); } } }}, 62750: function() {FS.mkdir('/snd');} }; function ma(){ let d=S();if(d)d();d=S();function S(){ let w$=parseInt(document.getElementById("iwid").innerHTML,10); let h$=parseInt(document.getElementById("ihig").innerHTML,10); w$=Math.round(w$);h$=Math.round(h$);let canvas=document.getElementById("vcanvas"); let contx=canvas.getContext('webgl2',{alpha:true,stencil:false,depth:true,premultipliedAlpha:false,imageSmoothingEnabled:false,lowLatency:true,powerPreference:'high-performance',majorVersion:2}); const g=new GPU({canvas:canvas,webGl:contx}); let Rn=parseInt(document.getElementById("frate").innerHTML,10); let l=(w$*h$*4);let m=((l/65536)+1);m=Math.floor(m); let W=new WebAssembly.Memory({initial:m});let o=[w$,h$]; const v=document.getElementById("mv"); const t=g.createKernel(function(v){const P=v[this.thread.y][this.thread.x]; return[P[0],P[1],P[2]];}).setTactic("precision").setPipeline(true).setOutput(o); const r=g.createKernel(function(f){const p=f[this.thread.y][this.thread.x]; this.color(p[0],p[1],p[2]);}).setTactic("precision").setGraphical(true).setOutput(o); let $=new Uint8ClampedArray(W.buffer,0,l);$.set(t(v),0);r(t($)); $.set(t(v),0);r(t($));$.set(t(v),0);let T=false;let ms=1;let R=16;let f=(1000/Rn); function M(){if(T){return;}r(t($));$.set(t(v),0);let mq=((ms*f)/R);let k=Math.floor(mq); let y=((k*f)-(k*Rn));if(y>8){R=8;}ms=ms+1;setTimeout(function(){M();},R);}M(); document.getElementById("di").onclick=function(){T=true;t.destroy();r.destroy();g.destroy();S();};return()=>{T=true;};}} function listenOnce(object, event, func) { object.addEventListener(event, func, { 'once': true }); } function autoResumeAudioContext(ctx, elements) { if (!elements) { elements = [document, document.getElementById('canvas')]; } ['keydown', 'mousedown', 'touchstart'].forEach(function(event) { elements.forEach(function(element) { if (element) { listenOnce(element, event, function() { if (ctx.state === 'suspended') ctx.resume(); }); } }); }); } function callRuntimeCallbacks(callbacks) { while (callbacks.length > 0) { var callback = callbacks.shift(); if (typeof callback == 'function') { callback(Module); // Pass the module as the first argument. continue; } var func = callback.func; if (typeof func === 'number') { if (callback.arg === undefined) { wasmTable.get(func)(); } else { wasmTable.get(func)(callback.arg); } } else { func(callback.arg === undefined ? null : callback.arg); } } } function demangle(func) { return func; } function demangleAll(text) { var regex = /\b_Z[\w\d_]+/g; return text.replace(regex, function(x) { var y = demangle(x); return x === y ? x : (y + ' [' + x + ']'); }); } function dynCallLegacy(sig, ptr, args) { var f = Module["dynCall_" + sig]; return args && args.length ? f.apply(null, [ptr].concat(args)) : f.call(null, ptr); } function dynCall(sig, ptr, args) { // Without WASM_BIGINT support we cannot directly call function with i64 as // part of thier signature, so we rely the dynCall functions generated by // wasm-emscripten-finalize if (sig.indexOf('j') != -1) { return dynCallLegacy(sig, ptr, args); } return wasmTable.get(ptr).apply(null, args) } function jsStackTrace() { var error = new Error(); if (!error.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 { throw new Error(); } catch(e) { error = e; } if (!error.stack) { return '(no stack trace available)'; } } return error.stack.toString(); } var runtimeKeepaliveCounter=0; function keepRuntimeAlive() { return noExitRuntime || runtimeKeepaliveCounter > 0; } function stackTrace() { var js = jsStackTrace(); if (Module['extraStackTrace']) js += '\n' + Module['extraStackTrace'](); return demangleAll(js); } function setErrNo(value) { HEAP32[((___errno_location())>>2)] = value; return value; } 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 '/'; path = PATH.normalize(path); path = path.replace(/\/$/, ""); 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); }}; function getRandomDevice() { if (typeof crypto === 'object' && typeof crypto['getRandomValues'] === 'function') { // for modern web browsers var randomBuffer = new Uint8Array(1); return function() { crypto.getRandomValues(randomBuffer); return randomBuffer[0]; }; } else // we couldn't find a proper implementation, as Math.random() is not suitable for /dev/random, see emscripten-core/emscripten/pull/7096 return function() { abort("randomDevice"); }; } var PATH_FS={resolve:function() { var resolvedPath = '', resolvedAbsolute = false; for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { var path = (i >= 0) ? arguments[i] : FS.cwd(); // Skip empty and invalid entries if (typeof path !== 'string') { throw new TypeError('Arguments to path.resolve must be strings'); } else if (!path) { return ''; // an invalid portion invalidates the whole thing } resolvedPath = path + '/' + resolvedPath; resolvedAbsolute = path.charAt(0) === '/'; } // At this point the path should be resolved to a full absolute path, but // handle relative paths to be safe (might happen when process.cwd() fails) resolvedPath = PATH.normalizeArray(resolvedPath.split('/').filter(function(p) { return !!p; }), !resolvedAbsolute).join('/'); return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; },relative:function(from, to) { from = PATH_FS.resolve(from).substr(1); to = PATH_FS.resolve(to).substr(1); function trim(arr) { var start = 0; for (; start < arr.length; start++) { if (arr[start] !== '') break; } var end = arr.length - 1; for (; end >= 0; end--) { if (arr[end] !== '') break; } if (start > end) return []; return arr.slice(start, end - start + 1); } var fromParts = trim(from.split('/')); var toParts = trim(to.split('/')); var length = Math.min(fromParts.length, toParts.length); var samePartsLength = length; for (var i = 0; i < length; i++) { if (fromParts[i] !== toParts[i]) { samePartsLength = i; break; } } var outputParts = []; for (var i = samePartsLength; i < fromParts.length; i++) { outputParts.push('..'); } outputParts = outputParts.concat(toParts.slice(samePartsLength)); return outputParts.join('/'); }}; var TTY={ttys:[],init:function () { // https://github.com/emscripten-core/emscripten/pull/1555 // if (ENVIRONMENT_IS_NODE) { // // currently, FS.init does not distinguish if process.stdin is a file or TTY // // device, it always assumes it's a TTY device. because of this, we're forcing // // process.stdin to UTF8 encoding to at least make stdin reading compatible // // with text files until FS.init can be refactored. // process['stdin']['setEncoding']('utf8'); // } },shutdown:function() { // https://github.com/emscripten-core/emscripten/pull/1555 // if (ENVIRONMENT_IS_NODE) { // // inolen: any idea as to why node -e 'process.stdin.read()' wouldn't exit immediately (with process.stdin being a tty)? // // isaacs: because now it's reading from the stream, you've expressed interest in it, so that read() kicks off a _read() which creates a ReadReq operation // // inolen: I thought read() in that case was a synchronous operation that just grabbed some amount of buffered data if it exists? // // isaacs: it is. but it also triggers a _read() call, which calls readStart() on the handle // // isaacs: do process.stdin.pause() and i'd think it'd probably close the pending call // process['stdin']['pause'](); // } },register:function(dev, ops) { TTY.ttys[dev] = { input: [], output: [], ops: ops }; FS.registerDevice(dev, TTY.stream_ops); },stream_ops:{open:function(stream) { var tty = TTY.ttys[stream.node.rdev]; if (!tty) { throw new FS.ErrnoError(43); } stream.tty = tty; stream.seekable = false; },close:function(stream) { // flush any pending line data stream.tty.ops.flush(stream.tty); },flush:function(stream) { stream.tty.ops.flush(stream.tty); },read:function(stream, buffer, offset, length, pos /* ignored */) { if (!stream.tty || !stream.tty.ops.get_char) { throw new FS.ErrnoError(60); } var bytesRead = 0; for (var i = 0; i < length; i++) { var result; try { result = stream.tty.ops.get_char(stream.tty); } catch (e) { throw new FS.ErrnoError(29); } if (result === undefined && bytesRead === 0) { throw new FS.ErrnoError(6); } if (result === null || result === undefined) break; bytesRead++; buffer[offset+i] = result; } if (bytesRead) { stream.node.timestamp = Date.now(); } return bytesRead; },write:function(stream, buffer, offset, length, pos) { if (!stream.tty || !stream.tty.ops.put_char) { throw new FS.ErrnoError(60); } try { for (var i = 0; i < length; i++) { stream.tty.ops.put_char(stream.tty, buffer[offset+i]); } } catch (e) { throw new FS.ErrnoError(29); } if (length) { stream.node.timestamp = Date.now(); } return i; }},default_tty_ops:{get_char:function(tty) { if (!tty.input.length) { var result = null; if (typeof window != 'undefined' && typeof window.prompt == 'function') { // Browser. result = window.prompt('Input: '); // returns null on cancel if (result !== null) { result += '\n'; } } else if (typeof readline == 'function') { // Command line. result = readline(); if (result !== null) { result += '\n'; } } if (!result) { return null; } tty.input = intArrayFromString(result, true); } return tty.input.shift(); },put_char:function(tty, val) { if (val === null || val === 10) { out(UTF8ArrayToString(tty.output, 0)); tty.output = []; } else { if (val != 0) tty.output.push(val); // val == 0 would cut text output off in the middle. } },flush:function(tty) { if (tty.output && tty.output.length > 0) { out(UTF8ArrayToString(tty.output, 0)); tty.output = []; } }},default_tty1_ops:{put_char:function(tty, val) { if (val === null || val === 10) { err(UTF8ArrayToString(tty.output, 0)); tty.output = []; } else { if (val != 0) tty.output.push(val); } },flush:function(tty) { if (tty.output && tty.output.length > 0) { err(UTF8ArrayToString(tty.output, 0)); tty.output = []; } }}}; function mmapAlloc(size) { var alignedSize = alignMemory(size, 16384); var ptr = _malloc(alignedSize); while (size < alignedSize) HEAP8[ptr + size++] = 0; return ptr; } var MEMFS={ops_table:null,mount:function(mount) { return MEMFS.createNode(null, '/', 16384 | 511 /* 0777 */, 0); },createNode:function(parent, name, mode, dev) { if (FS.isBlkdev(mode) || FS.isFIFO(mode)) { // no supported throw new FS.ErrnoError(63); } if (!MEMFS.ops_table) { MEMFS.ops_table = { dir: { node: { getattr: MEMFS.node_ops.getattr, setattr: MEMFS.node_ops.setattr, lookup: MEMFS.node_ops.lookup, mknod: MEMFS.node_ops.mknod, rename: MEMFS.node_ops.rename, unlink: MEMFS.node_ops.unlink, rmdir: MEMFS.node_ops.rmdir, readdir: MEMFS.node_ops.readdir, symlink: MEMFS.node_ops.symlink }, stream: { llseek: MEMFS.stream_ops.llseek } }, file: { node: { getattr: MEMFS.node_ops.getattr, setattr: MEMFS.node_ops.setattr }, stream: { llseek: MEMFS.stream_ops.llseek, read: MEMFS.stream_ops.read, write: MEMFS.stream_ops.write, allocate: MEMFS.stream_ops.allocate, mmap: MEMFS.stream_ops.mmap, msync: MEMFS.stream_ops.msync } }, link: { node: { getattr: MEMFS.node_ops.getattr, setattr: MEMFS.node_ops.setattr, readlink: MEMFS.node_ops.readlink }, stream: {} }, chrdev: { node: { getattr: MEMFS.node_ops.getattr, setattr: MEMFS.node_ops.setattr }, stream: FS.chrdev_stream_ops } }; } var node = FS.createNode(parent, name, mode, dev); if (FS.isDir(node.mode)) { node.node_ops = MEMFS.ops_table.dir.node; node.stream_ops = MEMFS.ops_table.dir.stream; node.contents = {}; } else if (FS.isFile(node.mode)) { node.node_ops = MEMFS.ops_table.file.node; node.stream_ops = MEMFS.ops_table.file.stream; node.usedBytes = 0; // The actual number of bytes used in the typed array, as opposed to contents.length which gives the whole capacity. // When the byte data of the file is populated, this will point to either a typed array, or a normal JS array. Typed arrays are preferred // for performance, and used by default. However, typed arrays are not resizable like normal JS arrays are, so there is a small disk size // penalty involved for appending file writes that continuously grow a file similar to std::vector capacity vs used -scheme. node.contents = null; } else if (FS.isLink(node.mode)) { node.node_ops = MEMFS.ops_table.link.node; node.stream_ops = MEMFS.ops_table.link.stream; } else if (FS.isChrdev(node.mode)) { node.node_ops = MEMFS.ops_table.chrdev.node; node.stream_ops = MEMFS.ops_table.chrdev.stream; } node.timestamp = Date.now(); // add the new node to the parent if (parent) { parent.contents[name] = node; parent.timestamp = node.timestamp; } return node; },getFileDataAsTypedArray:function(node) { if (!node.contents) return new Uint8Array(0); if (node.contents.subarray) return node.contents.subarray(0, node.usedBytes); // Make sure to not return excess unused bytes. return new Uint8Array(node.contents); },expandFileStorage:function(node, newCapacity) { var prevCapacity = node.contents ? node.contents.length : 0; if (prevCapacity >= newCapacity) return; // No need to expand, the storage was already large enough. // Don't expand strictly to the given requested limit if it's only a very small increase, but instead geometrically grow capacity. // For small filesizes (<1MB), perform size*2 geometric increase, but for large sizes, do a much more conservative size*1.125 increase to // avoid overshooting the allocation cap by a very large margin. var CAPACITY_DOUBLING_MAX = 1024 * 1024; newCapacity = Math.max(newCapacity, (prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2.0 : 1.125)) >>> 0); if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256); // At minimum allocate 256b for each file when expanding. var oldContents = node.contents; node.contents = new Uint8Array(newCapacity); // Allocate new storage. if (node.usedBytes > 0) node.contents.set(oldContents.subarray(0, node.usedBytes), 0); // Copy old data over to the new storage. },resizeFileStorage:function(node, newSize) { if (node.usedBytes == newSize) return; if (newSize == 0) { node.contents = null; // Fully decommit when requesting a resize to zero. node.usedBytes = 0; } else { var oldContents = node.contents; node.contents = new Uint8Array(newSize); // Allocate new storage. if (oldContents) { node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes))); // Copy old data over to the new storage. } node.usedBytes = newSize; } },node_ops:{getattr:function(node) { var attr = {}; // device numbers reuse inode numbers. attr.dev = FS.isChrdev(node.mode) ? node.id : 1; attr.ino = node.id; attr.mode = node.mode; attr.nlink = 1; attr.uid = 0; attr.gid = 0; attr.rdev = node.rdev; if (FS.isDir(node.mode)) { attr.size = 4096; } else if (FS.isFile(node.mode)) { attr.size = node.usedBytes; } else if (FS.isLink(node.mode)) { attr.size = node.link.length; } else { attr.size = 0; } attr.atime = new Date(node.timestamp); attr.mtime = new Date(node.timestamp); attr.ctime = new Date(node.timestamp); // NOTE: In our implementation, st_blocks = Math.ceil(st_size/st_blksize), // but this is not required by the standard. attr.blksize = 4096; attr.blocks = Math.ceil(attr.size / attr.blksize); return attr; },setattr:function(node, attr) { if (attr.mode !== undefined) { node.mode = attr.mode; } if (attr.timestamp !== undefined) { node.timestamp = attr.timestamp; } if (attr.size !== undefined) { MEMFS.resizeFileStorage(node, attr.size); } },lookup:function(parent, name) { throw FS.genericErrors[44]; },mknod:function(parent, name, mode, dev) { return MEMFS.createNode(parent, name, mode, dev); },rename:function(old_node, new_dir, new_name) { // if we're overwriting a directory at new_name, make sure it's empty. if (FS.isDir(old_node.mode)) { var new_node; try { new_node = FS.lookupNode(new_dir, new_name); } catch (e) { } if (new_node) { for (var i in new_node.contents) { throw new FS.ErrnoError(55); } } } // do the internal rewiring delete old_node.parent.contents[old_node.name]; old_node.parent.timestamp = Date.now() old_node.name = new_name; new_dir.contents[new_name] = old_node; new_dir.timestamp = old_node.parent.timestamp; old_node.parent = new_dir; },unlink:function(parent, name) { delete parent.contents[name]; parent.timestamp = Date.now(); },rmdir:function(parent, name) { var node = FS.lookupNode(parent, name); for (var i in node.contents) { throw new FS.ErrnoError(55); } delete parent.contents[name]; parent.timestamp = Date.now(); },readdir:function(node) { var entries = ['.', '..']; for (var key in node.contents) { if (!node.contents.hasOwnProperty(key)) { continue; } entries.push(key); } return entries; },symlink:function(parent, newname, oldpath) { var node = MEMFS.createNode(parent, newname, 511 /* 0777 */ | 40960, 0); node.link = oldpath; return node; },readlink:function(node) { if (!FS.isLink(node.mode)) { throw new FS.ErrnoError(28); } return node.link; }},stream_ops:{read:function(stream, buffer, offset, length, position) { var contents = stream.node.contents; if (position >= stream.node.usedBytes) return 0; var size = Math.min(stream.node.usedBytes - position, length); if (size > 8 && contents.subarray) { // non-trivial, and typed array buffer.set(contents.subarray(position, position + size), offset); } else { for (var i = 0; i < size; i++) buffer[offset + i] = contents[position + i]; } return size; },write:function(stream, buffer, offset, length, position, canOwn) { if (!length) return 0; var node = stream.node; node.timestamp = Date.now(); if (buffer.subarray && (!node.contents || node.contents.subarray)) { // This write is from a typed array to a typed array? if (canOwn) { node.contents = buffer.subarray(offset, offset + length); node.usedBytes = length; return length; } else if (node.usedBytes === 0 && position === 0) { // If this is a simple first write to an empty file, do a fast set since we don't need to care about old data. node.contents = buffer.slice(offset, offset + length); node.usedBytes = length; return length; } else if (position + length <= node.usedBytes) { // Writing to an already allocated and used subrange of the file? node.contents.set(buffer.subarray(offset, offset + length), position); return length; } } // Appending to an existing file and we need to reallocate, or source data did not come as a typed array. MEMFS.expandFileStorage(node, position+length); if (node.contents.subarray && buffer.subarray) { // Use typed array write which is available. node.contents.set(buffer.subarray(offset, offset + length), position); } else { for (var i = 0; i < length; i++) { node.contents[position + i] = buffer[offset + i]; // Or fall back to manual write if not. } } node.usedBytes = Math.max(node.usedBytes, position + length); return length; },llseek:function(stream, offset, whence) { var position = offset; if (whence === 1) { position += stream.position; } else if (whence === 2) { if (FS.isFile(stream.node.mode)) { position += stream.node.usedBytes; } } if (position < 0) { throw new FS.ErrnoError(28); } return position; },allocate:function(stream, offset, length) { MEMFS.expandFileStorage(stream.node, offset + length); stream.node.usedBytes = Math.max(stream.node.usedBytes, offset + length); },mmap:function(stream, address, length, position, prot, flags) { if (address !== 0) { // We don't currently support location hints for the address of the mapping throw new FS.ErrnoError(28); } if (!FS.isFile(stream.node.mode)) { throw new FS.ErrnoError(43); } var ptr; var allocated; var contents = stream.node.contents; // Only make a new copy when MAP_PRIVATE is specified. if (!(flags & 2) && contents.buffer === buffer) { // We can't emulate MAP_SHARED when the file is not backed by the buffer // we're mapping to (e.g. the HEAP buffer). allocated = false; ptr = contents.byteOffset; } else { // Try to avoid unnecessary slices. if (position > 0 || position + length < contents.length) { if (contents.subarray) { contents = contents.subarray(position, position + length); } else { contents = Array.prototype.slice.call(contents, position, position + length); } } allocated = true; ptr = mmapAlloc(length); if (!ptr) { throw new FS.ErrnoError(48); } HEAP8.set(contents, ptr); } return { ptr: ptr, allocated: allocated }; },msync:function(stream, buffer, offset, length, mmapFlags) { if (!FS.isFile(stream.node.mode)) { throw new FS.ErrnoError(43); } if (mmapFlags & 2) { // MAP_PRIVATE calls need not to be synced back to underlying fs return 0; } var bytesWritten = MEMFS.stream_ops.write(stream, buffer, 0, length, offset, false); // should we check if bytesWritten and length are the same? return 0; }}}; var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,trackingDelegate:{},tracking:{openFlags:{READ:1,WRITE:2}},ErrnoError:null,genericErrors:{},filesystems:null,syncFSRequests:0,lookupPath:function(path, opts) { path = PATH_FS.resolve(FS.cwd(), path); opts = opts || {}; if (!path) return { path: '', node: null }; var defaults = { follow_mount: true, recurse_count: 0 }; for (var key in defaults) { if (opts[key] === undefined) { opts[key] = defaults[key]; } } if (opts.recurse_count > 8) { // max recursive lookup of 8 throw new FS.ErrnoError(32); } // split the path var parts = PATH.normalizeArray(path.split('/').filter(function(p) { return !!p; }), false); // start at the root var current = FS.root; var current_path = '/'; for (var i = 0; i < parts.length; i++) { var islast = (i === parts.length-1); if (islast && opts.parent) { // stop resolving break; } current = FS.lookupNode(current, parts[i]); current_path = PATH.join2(current_path, parts[i]); // jump to the mount's root node if this is a mountpoint if (FS.isMountpoint(current)) { if (!islast || (islast && opts.follow_mount)) { current = current.mounted.root; } } // by default, lookupPath will not follow a symlink if it is the final path component. // setting opts.follow = true will override this behavior. if (!islast || opts.follow) { var count = 0; while (FS.isLink(current.mode)) { var link = FS.readlink(current_path); current_path = PATH_FS.resolve(PATH.dirname(current_path), link); var lookup = FS.lookupPath(current_path, { recurse_count: opts.recurse_count }); current = lookup.node; if (count++ > 40) { // limit max consecutive symlinks to 40 (SYMLOOP_MAX). throw new FS.ErrnoError(32); } } } } return { path: current_path, node: current }; },getPath:function(node) { var path; while (true) { if (FS.isRoot(node)) { var mount = node.mount.mountpoint; if (!path) return mount; return mount[mount.length-1] !== '/' ? mount + '/' + path : mount + path; } path = path ? node.name + '/' + path : node.name; node = node.parent; } },hashName:function(parentid, name) { var hash = 0; for (var i = 0; i < name.length; i++) { hash = ((hash << 5) - hash + name.charCodeAt(i)) | 0; } return ((parentid + hash) >>> 0) % FS.nameTable.length; },hashAddNode:function(node) { var hash = FS.hashName(node.parent.id, node.name); node.name_next = FS.nameTable[hash]; FS.nameTable[hash] = node; },hashRemoveNode:function(node) { var hash = FS.hashName(node.parent.id, node.name); if (FS.nameTable[hash] === node) { FS.nameTable[hash] = node.name_next; } else { var current = FS.nameTable[hash]; while (current) { if (current.name_next === node) { current.name_next = node.name_next; break; } current = current.name_next; } } },lookupNode:function(parent, name) { var errCode = FS.mayLookup(parent); if (errCode) { throw new FS.ErrnoError(errCode, parent); } var hash = FS.hashName(parent.id, name); for (var node = FS.nameTable[hash]; node; node = node.name_next) { var nodeName = node.name; if (node.parent.id === parent.id && nodeName === name) { return node; } } // if we failed to find it in the cache, call into the VFS return FS.lookup(parent, name); },createNode:function(parent, name, mode, rdev) { var node = new FS.FSNode(parent, name, mode, rdev); FS.hashAddNode(node); return node; },destroyNode:function(node) { FS.hashRemoveNode(node); },isRoot:function(node) { return node === node.parent; },isMountpoint:function(node) { return !!node.mounted; },isFile:function(mode) { return (mode & 61440) === 32768; },isDir:function(mode) { return (mode & 61440) === 16384; },isLink:function(mode) { return (mode & 61440) === 40960; },isChrdev:function(mode) { return (mode & 61440) === 8192; },isBlkdev:function(mode) { return (mode & 61440) === 24576; },isFIFO:function(mode) { return (mode & 61440) === 4096; },isSocket:function(mode) { return (mode & 49152) === 49152; },flagModes:{"r":0,"r+":2,"w":577,"w+":578,"a":1089,"a+":1090},modeStringToFlags:function(str) { var flags = FS.flagModes[str]; if (typeof flags === 'undefined') { throw new Error('Unknown file open mode: ' + str); } return flags; },flagsToPermissionString:function(flag) { var perms = ['r', 'w', 'rw'][flag & 3]; if ((flag & 512)) { perms += 'w'; } return perms; },nodePermissions:function(node, perms) { if (FS.ignorePermissions) { return 0; } // return 0 if any user, group or owner bits are set. if (perms.indexOf('r') !== -1 && !(node.mode & 292)) { return 2; } else if (perms.indexOf('w') !== -1 && !(node.mode & 146)) { return 2; } else if (perms.indexOf('x') !== -1 && !(node.mode & 73)) { return 2; } return 0; },mayLookup:function(dir) { var errCode = FS.nodePermissions(dir, 'x'); if (errCode) return errCode; if (!dir.node_ops.lookup) return 2; return 0; },mayCreate:function(dir, name) { try { var node = FS.lookupNode(dir, name); return 20; } catch (e) { } return FS.nodePermissions(dir, 'wx'); },mayDelete:function(dir, name, isdir) { var node; try { node = FS.lookupNode(dir, name); } catch (e) { return e.errno; } var errCode = FS.nodePermissions(dir, 'wx'); if (errCode) { return errCode; } if (isdir) { if (!FS.isDir(node.mode)) { return 54; } if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) { return 10; } } else { if (FS.isDir(node.mode)) { return 31; } } return 0; },mayOpen:function(node, flags) { if (!node) { return 44; } if (FS.isLink(node.mode)) { return 32; } else if (FS.isDir(node.mode)) { if (FS.flagsToPermissionString(flags) !== 'r' || // opening for write (flags & 512)) { // TODO: check for O_SEARCH? (== search for dir only) return 31; } } return FS.nodePermissions(node, FS.flagsToPermissionString(flags)); },MAX_OPEN_FDS:4096,nextfd:function(fd_start, fd_end) { fd_start = fd_start || 0; fd_end = fd_end || FS.MAX_OPEN_FDS; for (var fd = fd_start; fd <= fd_end; fd++) { if (!FS.streams[fd]) { return fd; } } throw new FS.ErrnoError(33); },getStream:function(fd) { return FS.streams[fd]; },createStream:function(stream, fd_start, fd_end) { if (!FS.FSStream) { FS.FSStream = /** @constructor */ function(){}; FS.FSStream.prototype = { object: { get: function() { return this.node; }, set: function(val) { this.node = val; } }, isRead: { get: function() { return (this.flags & 2097155) !== 1; } }, isWrite: { get: function() { return (this.flags & 2097155) !== 0; } }, isAppend: { get: function() { return (this.flags & 1024); } } }; } // clone it, so we can return an instance of FSStream var newStream = new FS.FSStream(); for (var p in stream) { newStream[p] = stream[p]; } stream = newStream; var fd = FS.nextfd(fd_start, fd_end); stream.fd = fd; FS.streams[fd] = stream; return stream; },closeStream:function(fd) { FS.streams[fd] = null; },chrdev_stream_ops:{open:function(stream) { var device = FS.getDevice(stream.node.rdev); // override node's stream ops with the device's stream.stream_ops = device.stream_ops; // forward the open call if (stream.stream_ops.open) { stream.stream_ops.open(stream); } },llseek:function() { throw new FS.ErrnoError(70); }},major:function(dev) { return ((dev) >> 8); },minor:function(dev) { return ((dev) & 0xff); },makedev:function(ma, mi) { return ((ma) << 8 | (mi)); },registerDevice:function(dev, ops) { FS.devices[dev] = { stream_ops: ops }; },getDevice:function(dev) { return FS.devices[dev]; },getMounts:function(mount) { var mounts = []; var check = [mount]; while (check.length) { var m = check.pop(); mounts.push(m); check.push.apply(check, m.mounts); } return mounts; },syncfs:function(populate, callback) { if (typeof(populate) === 'function') { callback = populate; populate = false; } FS.syncFSRequests++; if (FS.syncFSRequests > 1) { err('warning: ' + FS.syncFSRequests + ' FS.syncfs operations in flight at once, probably just doing extra work'); } var mounts = FS.getMounts(FS.root.mount); var completed = 0; function doCallback(errCode) { FS.syncFSRequests--; return callback(errCode); } function done(errCode) { if (errCode) { if (!done.errored) { done.errored = true; return doCallback(errCode); } return; } if (++completed >= mounts.length) { doCallback(null); } }; // sync all mounts mounts.forEach(function (mount) { if (!mount.type.syncfs) { return done(null); } mount.type.syncfs(mount, populate, done); }); },mount:function(type, opts, mountpoint) { var root = mountpoint === '/'; var pseudo = !mountpoint; var node; if (root && FS.root) { throw new FS.ErrnoError(10); } else if (!root && !pseudo) { var lookup = FS.lookupPath(mountpoint, { follow_mount: false }); mountpoint = lookup.path; // use the absolute path node = lookup.node; if (FS.isMountpoint(node)) { throw new FS.ErrnoError(10); } if (!FS.isDir(node.mode)) { throw new FS.ErrnoError(54); } } var mount = { type: type, opts: opts, mountpoint: mountpoint, mounts: [] }; // create a root node for the fs var mountRoot = type.mount(mount); mountRoot.mount = mount; mount.root = mountRoot; if (root) { FS.root = mountRoot; } else if (node) { // set as a mountpoint node.mounted = mount; // add the new mount to the current mount's children if (node.mount) { node.mount.mounts.push(mount); } } return mountRoot; },unmount:function (mountpoint) { var lookup = FS.lookupPath(mountpoint, { follow_mount: false }); if (!FS.isMountpoint(lookup.node)) { throw new FS.ErrnoError(28); } // destroy the nodes for this mount, and all its child mounts var node = lookup.node; var mount = node.mounted; var mounts = FS.getMounts(mount); Object.keys(FS.nameTable).forEach(function (hash) { var current = FS.nameTable[hash]; while (current) { var next = current.name_next; if (mounts.indexOf(current.mount) !== -1) { FS.destroyNode(current); } current = next; } }); // no longer a mountpoint node.mounted = null; // remove this mount from the child mounts var idx = node.mount.mounts.indexOf(mount); node.mount.mounts.splice(idx, 1); },lookup:function(parent, name) { return parent.node_ops.lookup(parent, name); },mknod:function(path, mode, dev) { var lookup = FS.lookupPath(path, { parent: true }); var parent = lookup.node; var name = PATH.basename(path); if (!name || name === '.' || name === '..') { throw new FS.ErrnoError(28); } var errCode = FS.mayCreate(parent, name); if (errCode) { throw new FS.ErrnoError(errCode); } if (!parent.node_ops.mknod) { throw new FS.ErrnoError(63); } return parent.node_ops.mknod(parent, name, mode, dev); },create:function(path, mode) { mode = mode !== undefined ? mode : 438 /* 0666 */; mode &= 4095; mode |= 32768; return FS.mknod(path, mode, 0); },mkdir:function(path, mode) { mode = mode !== undefined ? mode : 511 /* 0777 */; mode &= 511 | 512; mode |= 16384; return FS.mknod(path, mode, 0); },mkdirTree:function(path, mode) { var dirs = path.split('/'); var d = ''; for (var i = 0; i < dirs.length; ++i) { if (!dirs[i]) continue; d += '/' + dirs[i]; try { FS.mkdir(d, mode); } catch(e) { if (e.errno != 20) throw e; } } },mkdev:function(path, mode, dev) { if (typeof(dev) === 'undefined') { dev = mode; mode = 438 /* 0666 */; } mode |= 8192; return FS.mknod(path, mode, dev); },symlink:function(oldpath, newpath) { if (!PATH_FS.resolve(oldpath)) { throw new FS.ErrnoError(44); } var lookup = FS.lookupPath(newpath, { parent: true }); var parent = lookup.node; if (!parent) { throw new FS.ErrnoError(44); } var newname = PATH.basename(newpath); var errCode = FS.mayCreate(parent, newname); if (errCode) { throw new FS.ErrnoError(errCode); } if (!parent.node_ops.symlink) { throw new FS.ErrnoError(63); } return parent.node_ops.symlink(parent, newname, oldpath); },rename:function(old_path, new_path) { var old_dirname = PATH.dirname(old_path); var new_dirname = PATH.dirname(new_path); var old_name = PATH.basename(old_path); var new_name = PATH.basename(new_path); // parents must exist var lookup, old_dir, new_dir; // let the errors from non existant directories percolate up lookup = FS.lookupPath(old_path, { parent: true }); old_dir = lookup.node; lookup = FS.lookupPath(new_path, { parent: true }); new_dir = lookup.node; if (!old_dir || !new_dir) throw new FS.ErrnoError(44); // need to be part of the same mount if (old_dir.mount !== new_dir.mount) { throw new FS.ErrnoError(75); } // source must exist var old_node = FS.lookupNode(old_dir, old_name); // old path should not be an ancestor of the new path var relative = PATH_FS.relative(old_path, new_dirname); if (relative.charAt(0) !== '.') { throw new FS.ErrnoError(28); } // new path should not be an ancestor of the old path relative = PATH_FS.relative(new_path, old_dirname); if (relative.charAt(0) !== '.') { throw new FS.ErrnoError(55); } // see if the new path already exists var new_node; try { new_node = FS.lookupNode(new_dir, new_name); } catch (e) { // not fatal } // early out if nothing needs to change if (old_node === new_node) { return; } // we'll need to delete the old entry var isdir = FS.isDir(old_node.mode); var errCode = FS.mayDelete(old_dir, old_name, isdir); if (errCode) { throw new FS.ErrnoError(errCode); } // need delete permissions if we'll be overwriting. // need create permissions if new doesn't already exist. errCode = new_node ? FS.mayDelete(new_dir, new_name, isdir) : FS.mayCreate(new_dir, new_name); if (errCode) { throw new FS.ErrnoError(errCode); } if (!old_dir.node_ops.rename) { throw new FS.ErrnoError(63); } if (FS.isMountpoint(old_node) || (new_node && FS.isMountpoint(new_node))) { throw new FS.ErrnoError(10); } // if we are going to change the parent, check write permissions if (new_dir !== old_dir) { errCode = FS.nodePermissions(old_dir, 'w'); if (errCode) { throw new FS.ErrnoError(errCode); } } try { if (FS.trackingDelegate['willMovePath']) { FS.trackingDelegate['willMovePath'](old_path, new_path); } } catch(e) { err("FS.trackingDelegate['willMovePath']('"+old_path+"', '"+new_path+"') threw an exception: " + e.message); } // remove the node from the lookup hash FS.hashRemoveNode(old_node); // do the underlying fs rename try { old_dir.node_ops.rename(old_node, new_dir, new_name); } catch (e) { throw e; } finally { // add the node back to the hash (in case node_ops.rename // changed its name) FS.hashAddNode(old_node); } try { if (FS.trackingDelegate['onMovePath']) FS.trackingDelegate['onMovePath'](old_path, new_path); } catch(e) { err("FS.trackingDelegate['onMovePath']('"+old_path+"', '"+new_path+"') threw an exception: " + e.message); } },rmdir:function(path) { var lookup = FS.lookupPath(path, { parent: true }); var parent = lookup.node; var name = PATH.basename(path); var node = FS.lookupNode(parent, name); var errCode = FS.mayDelete(parent, name, true); if (errCode) { throw new FS.ErrnoError(errCode); } if (!parent.node_ops.rmdir) { throw new FS.ErrnoError(63); } if (FS.isMountpoint(node)) { throw new FS.ErrnoError(10); } try { if (FS.trackingDelegate['willDeletePath']) { FS.trackingDelegate['willDeletePath'](path); } } catch(e) { err("FS.trackingDelegate['willDeletePath']('"+path+"') threw an exception: " + e.message); } parent.node_ops.rmdir(parent, name); FS.destroyNode(node); try { if (FS.trackingDelegate['onDeletePath']) FS.trackingDelegate['onDeletePath'](path); } catch(e) { err("FS.trackingDelegate['onDeletePath']('"+path+"') threw an exception: " + e.message); } },readdir:function(path) { var lookup = FS.lookupPath(path, { follow: true }); var node = lookup.node; if (!node.node_ops.readdir) { throw new FS.ErrnoError(54); } return node.node_ops.readdir(node); },unlink:function(path) { var lookup = FS.lookupPath(path, { parent: true }); var parent = lookup.node; var name = PATH.basename(path); var node = FS.lookupNode(parent, name); var errCode = FS.mayDelete(parent, name, false); if (errCode) { // According to POSIX, we should map EISDIR to EPERM, but // we instead do what Linux does (and we must, as we use // the musl linux libc). throw new FS.ErrnoError(errCode); } if (!parent.node_ops.unlink) { throw new FS.ErrnoError(63); } if (FS.isMountpoint(node)) { throw new FS.ErrnoError(10); } try { if (FS.trackingDelegate['willDeletePath']) { FS.trackingDelegate['willDeletePath'](path); } } catch(e) { err("FS.trackingDelegate['willDeletePath']('"+path+"') threw an exception: " + e.message); } parent.node_ops.unlink(parent, name); FS.destroyNode(node); try { if (FS.trackingDelegate['onDeletePath']) FS.trackingDelegate['onDeletePath'](path); } catch(e) { err("FS.trackingDelegate['onDeletePath']('"+path+"') threw an exception: " + e.message); } },readlink:function(path) { var lookup = FS.lookupPath(path); var link = lookup.node; if (!link) { throw new FS.ErrnoError(44); } if (!link.node_ops.readlink) { throw new FS.ErrnoError(28); } return PATH_FS.resolve(FS.getPath(link.parent), link.node_ops.readlink(link)); },stat:function(path, dontFollow) { var lookup = FS.lookupPath(path, { follow: !dontFollow }); var node = lookup.node; if (!node) { throw new FS.ErrnoError(44); } if (!node.node_ops.getattr) { throw new FS.ErrnoError(63); } return node.node_ops.getattr(node); },lstat:function(path) { return FS.stat(path, true); },chmod:function(path, mode, dontFollow) { var node; if (typeof path === 'string') { var lookup = FS.lookupPath(path, { follow: !dontFollow }); node = lookup.node; } else { node = path; } if (!node.node_ops.setattr) { throw new FS.ErrnoError(63); } node.node_ops.setattr(node, { mode: (mode & 4095) | (node.mode & ~4095), timestamp: Date.now() }); },lchmod:function(path, mode) { FS.chmod(path, mode, true); },fchmod:function(fd, mode) { var stream = FS.getStream(fd); if (!stream) { throw new FS.ErrnoError(8); } FS.chmod(stream.node, mode); },chown:function(path, uid, gid, dontFollow) { var node; if (typeof path === 'string') { var lookup = FS.lookupPath(path, { follow: !dontFollow }); node = lookup.node; } else { node = path; } if (!node.node_ops.setattr) { throw new FS.ErrnoError(63); } node.node_ops.setattr(node, { timestamp: Date.now() // we ignore the uid / gid for now }); },lchown:function(path, uid, gid) { FS.chown(path, uid, gid, true); },fchown:function(fd, uid, gid) { var stream = FS.getStream(fd); if (!stream) { throw new FS.ErrnoError(8); } FS.chown(stream.node, uid, gid); },truncate:function(path, len) { if (len < 0) { throw new FS.ErrnoError(28); } var node; if (typeof path === 'string') { var lookup = FS.lookupPath(path, { follow: true }); node = lookup.node; } else { node = path; } if (!node.node_ops.setattr) { throw new FS.ErrnoError(63); } if (FS.isDir(node.mode)) { throw new FS.ErrnoError(31); } if (!FS.isFile(node.mode)) { throw new FS.ErrnoError(28); } var errCode = FS.nodePermissions(node, 'w'); if (errCode) { throw new FS.ErrnoError(errCode); } node.node_ops.setattr(node, { size: len, timestamp: Date.now() }); },ftruncate:function(fd, len) { var stream = FS.getStream(fd); if (!stream) { throw new FS.ErrnoError(8); } if ((stream.flags & 2097155) === 0) { throw new FS.ErrnoError(28); } FS.truncate(stream.node, len); },utime:function(path, atime, mtime) { var lookup = FS.lookupPath(path, { follow: true }); var node = lookup.node; node.node_ops.setattr(node, { timestamp: Math.max(atime, mtime) }); },open:function(path, flags, mode, fd_start, fd_end) { if (path === "") { throw new FS.ErrnoError(44); } flags = typeof flags === 'string' ? FS.modeStringToFlags(flags) : flags; mode = typeof mode === 'undefined' ? 438 /* 0666 */ : mode; if ((flags & 64)) { mode = (mode & 4095) | 32768; } else { mode = 0; } var node; if (typeof path === 'object') { node = path; } else { path = PATH.normalize(path); try { var lookup = FS.lookupPath(path, { follow: !(flags & 131072) }); node = lookup.node; } catch (e) { // ignore } } // perhaps we need to create the node var created = false; if ((flags & 64)) { if (node) { // if O_CREAT and O_EXCL are set, error out if the node already exists if ((flags & 128)) { throw new FS.ErrnoError(20); } } else { // node doesn't exist, try to create it node = FS.mknod(path, mode, 0); created = true; } } if (!node) { throw new FS.ErrnoError(44); } // can't truncate a device if (FS.isChrdev(node.mode)) { flags &= ~512; } // if asked only for a directory, then this must be one if ((flags & 65536) && !FS.isDir(node.mode)) { throw new FS.ErrnoError(54); } // check permissions, if this is not a file we just created now (it is ok to // create and write to a file with read-only permissions; it is read-only // for later use) if (!created) { var errCode = FS.mayOpen(node, flags); if (errCode) { throw new FS.ErrnoError(errCode); } } // do truncation if necessary if ((flags & 512)) { FS.truncate(node, 0); } // we've already handled these, don't pass down to the underlying vfs flags &= ~(128 | 512 | 131072); // register the stream with the filesystem var stream = FS.createStream({ node: node, path: FS.getPath(node), // we want the absolute path to the node flags: flags, seekable: true, position: 0, stream_ops: node.stream_ops, // used by the file family libc calls (fopen, fwrite, ferror, etc.) ungotten: [], error: false }, fd_start, fd_end); // call the new stream's open function if (stream.stream_ops.open) { stream.stream_ops.open(stream); } if (Module['logReadFiles'] && !(flags & 1)) { if (!FS.readFiles) FS.readFiles = {}; if (!(path in FS.readFiles)) { FS.readFiles[path] = 1; err("FS.trackingDelegate error on read file: " + path); } } try { if (FS.trackingDelegate['onOpenFile']) { var trackingFlags = 0; if ((flags & 2097155) !== 1) { trackingFlags |= FS.tracking.openFlags.READ; } if ((flags & 2097155) !== 0) { trackingFlags |= FS.tracking.openFlags.WRITE; } FS.trackingDelegate['onOpenFile'](path, trackingFlags); } } catch(e) { err("FS.trackingDelegate['onOpenFile']('"+path+"', flags) threw an exception: " + e.message); } return stream; },close:function(stream) { if (FS.isClosed(stream)) { throw new FS.ErrnoError(8); } if (stream.getdents) stream.getdents = null; // free readdir state try { if (stream.stream_ops.close) { stream.stream_ops.close(stream); } } catch (e) { throw e; } finally { FS.closeStream(stream.fd); } stream.fd = null; },isClosed:function(stream) { return stream.fd === null; },llseek:function(stream, offset, whence) { if (FS.isClosed(stream)) { throw new FS.ErrnoError(8); } if (!stream.seekable || !stream.stream_ops.llseek) { throw new FS.ErrnoError(70); } if (whence != 0 && whence != 1 && whence != 2) { throw new FS.ErrnoError(28); } stream.position = stream.stream_ops.llseek(stream, offset, whence); stream.ungotten = []; return stream.position; },read:function(stream, buffer, offset, length, position) { if (length < 0 || position < 0) { throw new FS.ErrnoError(28); } if (FS.isClosed(stream)) { throw new FS.ErrnoError(8); } if ((stream.flags & 2097155) === 1) { throw new FS.ErrnoError(8); } if (FS.isDir(stream.node.mode)) { throw new FS.ErrnoError(31); } if (!stream.stream_ops.read) { throw new FS.ErrnoError(28); } var seeking = typeof position !== 'undefined'; if (!seeking) { position = stream.position; } else if (!stream.seekable) { throw new FS.ErrnoError(70); } var bytesRead = stream.stream_ops.read(stream, buffer, offset, length, position); if (!seeking) stream.position += bytesRead; return bytesRead; },write:function(stream, buffer, offset, length, position, canOwn) { if (length < 0 || position < 0) { throw new FS.ErrnoError(28); } if (FS.isClosed(stream)) { throw new FS.ErrnoError(8); } if ((stream.flags & 2097155) === 0) { throw new FS.ErrnoError(8); } if (FS.isDir(stream.node.mode)) { throw new FS.ErrnoError(31); } if (!stream.stream_ops.write) { throw new FS.ErrnoError(28); } if (stream.seekable && stream.flags & 1024) { // seek to the end before writing in append mode FS.llseek(stream, 0, 2); } var seeking = typeof position !== 'undefined'; if (!seeking) { position = stream.position; } else if (!stream.seekable) { throw new FS.ErrnoError(70); } var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn); if (!seeking) stream.position += bytesWritten; try { if (stream.path && FS.trackingDelegate['onWriteToFile']) FS.trackingDelegate['onWriteToFile'](stream.path); } catch(e) { err("FS.trackingDelegate['onWriteToFile']('"+stream.path+"') threw an exception: " + e.message); } return bytesWritten; },allocate:function(stream, offset, length) { if (FS.isClosed(stream)) { throw new FS.ErrnoError(8); } if (offset < 0 || length <= 0) { throw new FS.ErrnoError(28); } if ((stream.flags & 2097155) === 0) { throw new FS.ErrnoError(8); } if (!FS.isFile(stream.node.mode) && !FS.isDir(stream.node.mode)) { throw new FS.ErrnoError(43); } if (!stream.stream_ops.allocate) { throw new FS.ErrnoError(138); } stream.stream_ops.allocate(stream, offset, length); },mmap:function(stream, address, length, position, prot, flags) { // User requests writing to file (prot & PROT_WRITE != 0). // Checking if we have permissions to write to the file unless // MAP_PRIVATE flag is set. According to POSIX spec it is possible // to write to file opened in read-only mode with MAP_PRIVATE flag, // as all modifications will be visible only in the memory of // the current process. if ((prot & 2) !== 0 && (flags & 2) === 0 && (stream.flags & 2097155) !== 2) { throw new FS.ErrnoError(2); } if ((stream.flags & 2097155) === 1) { throw new FS.ErrnoError(2); } if (!stream.stream_ops.mmap) { throw new FS.ErrnoError(43); } return stream.stream_ops.mmap(stream, address, length, position, prot, flags); },msync:function(stream, buffer, offset, length, mmapFlags) { if (!stream || !stream.stream_ops.msync) { return 0; } return stream.stream_ops.msync(stream, buffer, offset, length, mmapFlags); },munmap:function(stream) { return 0; },ioctl:function(stream, cmd, arg) { if (!stream.stream_ops.ioctl) { throw new FS.ErrnoError(59); } return stream.stream_ops.ioctl(stream, cmd, arg); },readFile:function(path, opts) { opts = opts || {}; opts.flags = opts.flags || 0; opts.encoding = opts.encoding || 'binary'; if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') { throw new Error('Invalid encoding type "' + opts.encoding + '"'); } var ret; var stream = FS.open(path, opts.flags); var stat = FS.stat(path); var length = stat.size; var buf = new Uint8Array(length); FS.read(stream, buf, 0, length, 0); if (opts.encoding === 'utf8') { ret = UTF8ArrayToString(buf, 0); } else if (opts.encoding === 'binary') { ret = buf; } FS.close(stream); return ret; },writeFile:function(path, data, opts) { opts = opts || {}; opts.flags = opts.flags || 577; var stream = FS.open(path, opts.flags, opts.mode); if (typeof data === 'string') { var buf = new Uint8Array(lengthBytesUTF8(data)+1); var actualNumBytes = stringToUTF8Array(data, buf, 0, buf.length); FS.write(stream, buf, 0, actualNumBytes, undefined, opts.canOwn); } else if (ArrayBuffer.isView(data)) { FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn); } else { throw new Error('Unsupported data type'); } FS.close(stream); },cwd:function() { return FS.currentPath; },chdir:function(path) { var lookup = FS.lookupPath(path, { follow: true }); if (lookup.node === null) { throw new FS.ErrnoError(44); } if (!FS.isDir(lookup.node.mode)) { throw new FS.ErrnoError(54); } var errCode = FS.nodePermissions(lookup.node, 'x'); if (errCode) { throw new FS.ErrnoError(errCode); } FS.currentPath = lookup.path; },createDefaultDirectories:function() { FS.mkdir('/tmp'); FS.mkdir('/home'); FS.mkdir('/home/web_user'); },createDefaultDevices:function() { // create /dev FS.mkdir('/dev'); // setup /dev/null FS.registerDevice(FS.makedev(1, 3), { read: function() { return 0; }, write: function(stream, buffer, offset, length, pos) { return length; } }); FS.mkdev('/dev/null', FS.makedev(1, 3)); // setup /dev/tty and /dev/tty1 // stderr needs to print output using err() rather than out() // so we register a second tty just for it. TTY.register(FS.makedev(5, 0), TTY.default_tty_ops); TTY.register(FS.makedev(6, 0), TTY.default_tty1_ops); FS.mkdev('/dev/tty', FS.makedev(5, 0)); FS.mkdev('/dev/tty1', FS.makedev(6, 0)); // setup /dev/[u]random var random_device = getRandomDevice(); FS.createDevice('/dev', 'random', random_device); FS.createDevice('/dev', 'urandom', random_device); // we're not going to emulate the actual shm device, // just create the tmp dirs that reside in it commonly FS.mkdir('/dev/shm'); FS.mkdir('/dev/shm/tmp'); },createSpecialDirectories:function() { // create /proc/self/fd which allows /proc/self/fd/6 => readlink gives the // name of the stream for fd 6 (see test_unistd_ttyname) FS.mkdir('/proc'); var proc_self = FS.mkdir('/proc/self'); FS.mkdir('/proc/self/fd'); FS.mount({ mount: function() { var node = FS.createNode(proc_self, 'fd', 16384 | 511 /* 0777 */, 73); node.node_ops = { lookup: function(parent, name) { var fd = +name; var stream = FS.getStream(fd); if (!stream) throw new FS.ErrnoError(8); var ret = { parent: null, mount: { mountpoint: 'fake' }, node_ops: { readlink: function() { return stream.path } } }; ret.parent = ret; // make it look like a simple root node return ret; } }; return node; } }, {}, '/proc/self/fd'); },createStandardStreams:function() { // TODO deprecate the old functionality of a single // input / output callback and that utilizes FS.createDevice // and instead require a unique set of stream ops // by default, we symlink the standard streams to the // default tty devices. however, if the standard streams // have been overwritten we create a unique device for // them instead. if (Module['stdin']) { FS.createDevice('/dev', 'stdin', Module['stdin']); } else { FS.symlink('/dev/tty', '/dev/stdin'); } if (Module['stdout']) { FS.createDevice('/dev', 'stdout', null, Module['stdout']); } else { FS.symlink('/dev/tty', '/dev/stdout'); } if (Module['stderr']) { FS.createDevice('/dev', 'stderr', null, Module['stderr']); } else { FS.symlink('/dev/tty1', '/dev/stderr'); } // open default streams for the stdin, stdout and stderr devices var stdin = FS.open('/dev/stdin', 0); var stdout = FS.open('/dev/stdout', 1); var stderr = FS.open('/dev/stderr', 1); },ensureErrnoError:function() { if (FS.ErrnoError) return; FS.ErrnoError = /** @this{Object} */ function ErrnoError(errno, node) { this.node = node; this.setErrno = /** @this{Object} */ function(errno) { this.errno = errno; }; this.setErrno(errno); this.message = 'FS error'; }; FS.ErrnoError.prototype = new Error(); FS.ErrnoError.prototype.constructor = FS.ErrnoError; // Some errors may happen quite a bit, to avoid overhead we reuse them (and suffer a lack of stack info) [44].forEach(function(code) { FS.genericErrors[code] = new FS.ErrnoError(code); FS.genericErrors[code].stack = ''; }); },staticInit:function() { FS.ensureErrnoError(); FS.nameTable = new Array(4096); FS.mount(MEMFS, {}, '/'); FS.createDefaultDirectories(); FS.createDefaultDevices(); FS.createSpecialDirectories(); FS.filesystems = { 'MEMFS': MEMFS, }; },init:function(input, output, error) { FS.init.initialized = true; FS.ensureErrnoError(); // Allow Module.stdin etc. to provide defaults, if none explicitly passed to us here Module['stdin'] = input || Module['stdin']; Module['stdout'] = output || Module['stdout']; Module['stderr'] = error || Module['stderr']; FS.createStandardStreams(); },quit:function() { FS.init.initialized = false; // force-flush all streams, so we get musl std streams printed out var fflush = Module['_fflush']; if (fflush) fflush(0); // close all of our streams for (var i = 0; i < FS.streams.length; i++) { var stream = FS.streams[i]; if (!stream) { continue; } FS.close(stream); } },getMode:function(canRead, canWrite) { var mode = 0; if (canRead) mode |= 292 | 73; if (canWrite) mode |= 146; return mode; },findObject:function(path, dontResolveLastLink) { var ret = FS.analyzePath(path, dontResolveLastLink); if (ret.exists) { return ret.object; } else { return null; } },analyzePath:function(path, dontResolveLastLink) { // operate from within the context of the symlink's target try { var lookup = FS.lookupPath(path, { follow: !dontResolveLastLink }); path = lookup.path; } catch (e) { } var ret = { isRoot: false, exists: false, error: 0, name: null, path: null, object: null, parentExists: false, parentPath: null, parentObject: null }; try { var lookup = FS.lookupPath(path, { parent: true }); ret.parentExists = true; ret.parentPath = lookup.path; ret.parentObject = lookup.node; ret.name = PATH.basename(path); lookup = FS.lookupPath(path, { follow: !dontResolveLastLink }); ret.exists = true; ret.path = lookup.path; ret.object = lookup.node; ret.name = lookup.node.name; ret.isRoot = lookup.path === '/'; } catch (e) { ret.error = e.errno; }; return ret; },createPath:function(parent, path, canRead, canWrite) { parent = typeof parent === 'string' ? parent : FS.getPath(parent); var parts = path.split('/').reverse(); while (parts.length) { var part = parts.pop(); if (!part) continue; var current = PATH.join2(parent, part); try { FS.mkdir(current); } catch (e) { // ignore EEXIST } parent = current; } return current; },createFile:function(parent, name, properties, canRead, canWrite) { var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name); var mode = FS.getMode(canRead, canWrite); return FS.create(path, mode); },createDataFile:function(parent, name, data, canRead, canWrite, canOwn) { var path = name ? PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name) : parent; var mode = FS.getMode(canRead, canWrite); var node = FS.create(path, mode); if (data) { if (typeof data === 'string') { var arr = new Array(data.length); for (var i = 0, len = data.length; i < len; ++i) arr[i] = data.charCodeAt(i); data = arr; } // make sure we can write to the file FS.chmod(node, mode | 146); var stream = FS.open(node, 577); FS.write(stream, data, 0, data.length, 0, canOwn); FS.close(stream); FS.chmod(node, mode); } return node; },createDevice:function(parent, name, input, output) { var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name); var mode = FS.getMode(!!input, !!output); if (!FS.createDevice.major) FS.createDevice.major = 64; var dev = FS.makedev(FS.createDevice.major++, 0); // Create a fake device that a set of stream ops to emulate // the old behavior. FS.registerDevice(dev, { open: function(stream) { stream.seekable = false; }, close: function(stream) { // flush any pending line data if (output && output.buffer && output.buffer.length) { output(10); } }, read: function(stream, buffer, offset, length, pos /* ignored */) { var bytesRead = 0; for (var i = 0; i < length; i++) { var result; try { result = input(); } catch (e) { throw new FS.ErrnoError(29); } if (result === undefined && bytesRead === 0) { throw new FS.ErrnoError(6); } if (result === null || result === undefined) break; bytesRead++; buffer[offset+i] = result; } if (bytesRead) { stream.node.timestamp = Date.now(); } return bytesRead; }, write: function(stream, buffer, offset, length, pos) { for (var i = 0; i < length; i++) { try { output(buffer[offset+i]); } catch (e) { throw new FS.ErrnoError(29); } } if (length) { stream.node.timestamp = Date.now(); } return i; } }); return FS.mkdev(path, mode, dev); },forceLoadFile:function(obj) { if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true; if (typeof XMLHttpRequest !== 'undefined') { throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread."); } else if (read_) { // Command-line. try { // WARNING: Can't read binary files in V8's d8 or tracemonkey's js, as // read() will try to parse UTF8. obj.contents = intArrayFromString(read_(obj.url), true); obj.usedBytes = obj.contents.length; } catch (e) { throw new FS.ErrnoError(29); } } else { throw new Error('Cannot load without read() or XMLHttpRequest.'); } },createLazyFile:function(parent, name, url, canRead, canWrite) { // Lazy chunked Uint8Array (implements get and length from Uint8Array). Actual getting is abstracted away for eventual reuse. /** @constructor */ function LazyUint8Array() { this.lengthKnown = false; this.chunks = []; // Loaded chunks. Index is the chunk number } LazyUint8Array.prototype.get = /** @this{Object} */ function LazyUint8Array_get(idx) { if (idx > this.length-1 || idx < 0) { return undefined; } var chunkOffset = idx % this.chunkSize; var chunkNum = (idx / this.chunkSize)|0; return this.getter(chunkNum)[chunkOffset]; }; LazyUint8Array.prototype.setDataGetter = function LazyUint8Array_setDataGetter(getter) { this.getter = getter; }; LazyUint8Array.prototype.cacheLength = function LazyUint8Array_cacheLength() { // Find length var xhr = new XMLHttpRequest(); xhr.open('HEAD', url, false); xhr.send(null); if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); var datalength = Number(xhr.getResponseHeader("Content-length")); var header; var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes"; var usesGzip = (header = xhr.getResponseHeader("Content-Encoding")) && header === "gzip"; var chunkSize = 1024*1024; // Chunk size in bytes if (!hasByteServing) chunkSize = datalength; // Function to get a range from the remote URL. var doXHR = (function(from, to) { if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!"); if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!"); // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available. var xhr = new XMLHttpRequest(); xhr.open('GET', url, false); if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to); // Some hints to the browser that we want binary data. if (typeof Uint8Array != 'undefined') xhr.responseType = 'arraybuffer'; if (xhr.overrideMimeType) { xhr.overrideMimeType('text/plain; charset=x-user-defined'); } xhr.send(null); if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); if (xhr.response !== undefined) { return new Uint8Array(/** @type{Array} */(xhr.response || [])); } else { return intArrayFromString(xhr.responseText || '', true); } }); var lazyArray = this; lazyArray.setDataGetter(function(chunkNum) { var start = chunkNum * chunkSize; var end = (chunkNum+1) * chunkSize - 1; // including this byte end = Math.min(end, datalength-1); // if datalength-1 is selected, this is the last block if (typeof(lazyArray.chunks[chunkNum]) === "undefined") { lazyArray.chunks[chunkNum] = doXHR(start, end); } if (typeof(lazyArray.chunks[chunkNum]) === "undefined") throw new Error("doXHR failed!"); return lazyArray.chunks[chunkNum]; }); if (usesGzip || !datalength) { // if the server uses gzip or doesn't supply the length, we have to download the whole file to get the (uncompressed) length chunkSize = datalength = 1; // this will force getter(0)/doXHR do download the whole file datalength = this.getter(0).length; chunkSize = datalength; out("LazyFiles on gzip forces download of the whole file when length is accessed"); } this._length = datalength; this._chunkSize = chunkSize; this.lengthKnown = true; }; if (typeof XMLHttpRequest !== 'undefined') { if (!ENVIRONMENT_IS_WORKER) throw 'Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc'; var lazyArray = new LazyUint8Array(); Object.defineProperties(lazyArray, { length: { get: /** @this{Object} */ function() { if (!this.lengthKnown) { this.cacheLength(); } return this._length; } }, chunkSize: { get: /** @this{Object} */ function() { if (!this.lengthKnown) { this.cacheLength(); } return this._chunkSize; } } }); var properties = { isDevice: false, contents: lazyArray }; } else { var properties = { isDevice: false, url: url }; } var node = FS.createFile(parent, name, properties, canRead, canWrite); // This is a total hack, but I want to get this lazy file code out of the // core of MEMFS. If we want to keep this lazy file concept I feel it should // be its own thin LAZYFS proxying calls to MEMFS. if (properties.contents) { node.contents = properties.contents; } else if (properties.url) { node.contents = null; node.url = properties.url; } // Add a function that defers querying the file size until it is asked the first time. Object.defineProperties(node, { usedBytes: { get: /** @this {FSNode} */ function() { return this.contents.length; } } }); // override each stream op with one that tries to force load the lazy file first var stream_ops = {}; var keys = Object.keys(node.stream_ops); keys.forEach(function(key) { var fn = node.stream_ops[key]; stream_ops[key] = function forceLoadLazyFile() { FS.forceLoadFile(node); return fn.apply(null, arguments); }; }); // use a custom read function stream_ops.read = function stream_ops_read(stream, buffer, offset, length, position) { FS.forceLoadFile(node); var contents = stream.node.contents; if (position >= contents.length) return 0; var size = Math.min(contents.length - position, length); if (contents.slice) { // normal array for (var i = 0; i < size; i++) { buffer[offset + i] = contents[position + i]; } } else { for (var i = 0; i < size; i++) { // LazyUint8Array from sync binary XHR buffer[offset + i] = contents.get(position + i); } } return size; }; node.stream_ops = stream_ops; return node; },createPreloadedFile:function(parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) { Browser.init(); // XXX perhaps this method should move onto Browser? // TODO we should allow people to just pass in a complete filename instead // of parent and name being that we just join them anyways var fullname = name ? PATH_FS.resolve(PATH.join2(parent, name)) : parent; var dep = getUniqueRunDependency('cp ' + fullname); // might have several active requests for the same fullname function processData(byteArray) { function finish(byteArray) { if (preFinish) preFinish(); if (!dontCreateFile) { FS.createDataFile(parent, name, byteArray, canRead, canWrite, canOwn); } if (onload) onload(); removeRunDependency(dep); } var handled = false; Module['preloadPlugins'].forEach(function(plugin) { if (handled) return; if (plugin['canHandle'](fullname)) { plugin['handle'](byteArray, fullname, finish, function() { if (onerror) onerror(); removeRunDependency(dep); }); handled = true; } }); if (!handled) finish(byteArray); } addRunDependency(dep); if (typeof url == 'string') { Browser.asyncLoad(url, function(byteArray) { processData(byteArray); }, onerror); } else { processData(url); } },indexedDB:function() { return window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB; },DB_NAME:function() { return 'EM_FS_' + window.location.pathname; },DB_VERSION:20,DB_STORE_NAME:"FILE_DATA",saveFilesToDB:function(paths, onload, onerror) { onload = onload || function(){}; onerror = onerror || function(){}; var indexedDB = FS.indexedDB(); try { var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION); } catch (e) { return onerror(e); } openRequest.onupgradeneeded = function openRequest_onupgradeneeded() { out('creating db'); var db = openRequest.result; db.createObjectStore(FS.DB_STORE_NAME); }; openRequest.onsuccess = function openRequest_onsuccess() { var db = openRequest.result; var transaction = db.transaction([FS.DB_STORE_NAME], 'readwrite'); var files = transaction.objectStore(FS.DB_STORE_NAME); var ok = 0, fail = 0, total = paths.length; function finish() { if (fail == 0) onload(); else onerror(); } paths.forEach(function(path) { var putRequest = files.put(FS.analyzePath(path).object.contents, path); putRequest.onsuccess = function putRequest_onsuccess() { ok++; if (ok + fail == total) finish() }; putRequest.onerror = function putRequest_onerror() { fail++; if (ok + fail == total) finish() }; }); transaction.onerror = onerror; }; openRequest.onerror = onerror; },loadFilesFromDB:function(paths, onload, onerror) { onload = onload || function(){}; onerror = onerror || function(){}; var indexedDB = FS.indexedDB(); try { var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION); } catch (e) { return onerror(e); } openRequest.onupgradeneeded = onerror; // no database to load from openRequest.onsuccess = function openRequest_onsuccess() { var db = openRequest.result; try { var transaction = db.transaction([FS.DB_STORE_NAME], 'readonly'); } catch(e) { onerror(e); return; } var files = transaction.objectStore(FS.DB_STORE_NAME); var ok = 0, fail = 0, total = paths.length; function finish() { if (fail == 0) onload(); else onerror(); } paths.forEach(function(path) { var getRequest = files.get(path); getRequest.onsuccess = function getRequest_onsuccess() { if (FS.analyzePath(path).exists) { FS.unlink(path); } FS.createDataFile(PATH.dirname(path), PATH.basename(path), getRequest.result, true, true, true); ok++; if (ok + fail == total) finish(); }; getRequest.onerror = function getRequest_onerror() { fail++; if (ok + fail == total) finish() }; }); transaction.onerror = onerror; }; openRequest.onerror = onerror; }}; var SYSCALLS={mappings:{},DEFAULT_POLLMASK:5,umask:511,calculateAt:function(dirfd, path, allowEmpty) { if (path[0] === '/') { return path; } // relative path var dir; if (dirfd === -100) { dir = FS.cwd(); } else { var dirstream = FS.getStream(dirfd); if (!dirstream) throw new FS.ErrnoError(8); dir = dirstream.path; } if (path.length == 0) { if (!allowEmpty) { throw new FS.ErrnoError(44);; } return dir; } return PATH.join2(dir, path); },doStat:function(func, path, buf) { try { var stat = func(path); } catch (e) { if (e && e.node && PATH.normalize(path) !== PATH.normalize(FS.getPath(e.node))) { // an error occurred while trying to look up the path; we should just report ENOTDIR return -54; } throw e; } HEAP32[((buf)>>2)] = stat.dev; HEAP32[(((buf)+(4))>>2)] = 0; HEAP32[(((buf)+(8))>>2)] = stat.ino; HEAP32[(((buf)+(12))>>2)] = stat.mode; HEAP32[(((buf)+(16))>>2)] = stat.nlink; HEAP32[(((buf)+(20))>>2)] = stat.uid; HEAP32[(((buf)+(24))>>2)] = stat.gid; HEAP32[(((buf)+(28))>>2)] = stat.rdev; HEAP32[(((buf)+(32))>>2)] = 0; (tempI64 = [stat.size>>>0,(tempDouble=stat.size,(+(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[(((buf)+(40))>>2)] = tempI64[0],HEAP32[(((buf)+(44))>>2)] = tempI64[1]); HEAP32[(((buf)+(48))>>2)] = 4096; HEAP32[(((buf)+(52))>>2)] = stat.blocks; HEAP32[(((buf)+(56))>>2)] = (stat.atime.getTime() / 1000)|0; HEAP32[(((buf)+(60))>>2)] = 0; HEAP32[(((buf)+(64))>>2)] = (stat.mtime.getTime() / 1000)|0; HEAP32[(((buf)+(68))>>2)] = 0; HEAP32[(((buf)+(72))>>2)] = (stat.ctime.getTime() / 1000)|0; HEAP32[(((buf)+(76))>>2)] = 0; (tempI64 = [stat.ino>>>0,(tempDouble=stat.ino,(+(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[(((buf)+(80))>>2)] = tempI64[0],HEAP32[(((buf)+(84))>>2)] = tempI64[1]); return 0; },doMsync:function(addr, stream, len, flags, offset) { var buffer = HEAPU8.slice(addr, addr + len); FS.msync(stream, buffer, offset, len, flags); },doMkdir:function(path, mode) { // remove a trailing slash, if one - /a/b/ has basename of '', but // we want to create b in the context of this function path = PATH.normalize(path); if (path[path.length-1] === '/') path = path.substr(0, path.length-1); FS.mkdir(path, mode, 0); return 0; },doMknod:function(path, mode, dev) { // we don't want this in the JS API as it uses mknod to create all nodes. switch (mode & 61440) { case 32768: case 8192: case 24576: case 4096: case 49152: break; default: return -28; } FS.mknod(path, mode, dev); return 0; },doReadlink:function(path, buf, bufsize) { if (bufsize <= 0) return -28; var ret = FS.readlink(path); var len = Math.min(bufsize, lengthBytesUTF8(ret)); var endChar = HEAP8[buf+len]; stringToUTF8(ret, buf, bufsize+1); // readlink is one of the rare functions that write out a C string, but does never append a null to the output buffer(!) // stringToUTF8() always appends a null byte, so restore the character under the null byte after the write. HEAP8[buf+len] = endChar; return len; },doAccess:function(path, amode) { if (amode & ~7) { // need a valid mode return -28; } var node; var lookup = FS.lookupPath(path, { follow: true }); node = lookup.node; if (!node) { return -44; } var perms = ''; if (amode & 4) perms += 'r'; if (amode & 2) perms += 'w'; if (amode & 1) perms += 'x'; if (perms /* otherwise, they've just passed F_OK */ && FS.nodePermissions(node, perms)) { return -2; } return 0; },doDup:function(path, flags, suggestFD) { var suggest = FS.getStream(suggestFD); if (suggest) FS.close(suggest); return FS.open(path, flags, 0, suggestFD, suggestFD).fd; },doReadv:function(stream, iov, iovcnt, offset) { var ret = 0; for (var i = 0; i < iovcnt; i++) { var ptr = HEAP32[(((iov)+(i*8))>>2)]; var len = HEAP32[(((iov)+(i*8 + 4))>>2)]; var curr = FS.read(stream, HEAP8,ptr, len, offset); if (curr < 0) return -1; ret += curr; if (curr < len) break; // nothing more to read } return ret; },doWritev:function(stream, iov, iovcnt, offset) { var ret = 0; for (var i = 0; i < iovcnt; i++) { var ptr = HEAP32[(((iov)+(i*8))>>2)]; var len = HEAP32[(((iov)+(i*8 + 4))>>2)]; var curr = FS.write(stream, HEAP8,ptr, len, offset); if (curr < 0) return -1; ret += curr; } return ret; },varargs:undefined,get:function() { SYSCALLS.varargs += 4; var ret = HEAP32[(((SYSCALLS.varargs)-(4))>>2)]; return ret; },getStr:function(ptr) { var ret = UTF8ToString(ptr); return ret; },getStreamFromFD:function(fd) { var stream = FS.getStream(fd); if (!stream) throw new FS.ErrnoError(8); return stream; },get64:function(low, high) { return low; }}; function ___sys_fcntl64(fd, cmd, varargs) {SYSCALLS.varargs = varargs; try { var stream = SYSCALLS.getStreamFromFD(fd); switch (cmd) { case 0: { var arg = SYSCALLS.get(); if (arg < 0) { return -28; } var newStream; newStream = FS.open(stream.path, stream.flags, 0, arg); return newStream.fd; } case 1: case 2: return 0; // FD_CLOEXEC makes no sense for a single process. case 3: return stream.flags; case 4: { var arg = SYSCALLS.get(); stream.flags |= arg; return 0; } case 12: /* case 12: Currently in musl F_GETLK64 has same value as F_GETLK, so omitted to avoid duplicate case blocks. If that changes, uncomment this */ { var arg = SYSCALLS.get(); var offset = 0; // We're always unlocked. HEAP16[(((arg)+(offset))>>1)] = 2; return 0; } case 13: case 14: /* case 13: Currently in musl F_SETLK64 has same value as F_SETLK, so omitted to avoid duplicate case blocks. If that changes, uncomment this */ /* case 14: Currently in musl F_SETLKW64 has same value as F_SETLKW, so omitted to avoid duplicate case blocks. If that changes, uncomment this */ return 0; // Pretend that the locking is successful. case 16: case 8: return -28; // These are for sockets. We don't have them fully implemented yet. case 9: // musl trusts getown return values, due to a bug where they must be, as they overlap with errors. just return -1 here, so fnctl() returns that, and we set errno ourselves. setErrNo(28); return -1; default: { return -28; } } } catch (e) { if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e); return -e.errno; } } function ___sys_ioctl(fd, op, varargs) {SYSCALLS.varargs = varargs; try { var stream = SYSCALLS.getStreamFromFD(fd); switch (op) { case 21509: case 21505: { if (!stream.tty) return -59; return 0; } case 21510: case 21511: case 21512: case 21506: case 21507: case 21508: { if (!stream.tty) return -59; return 0; // no-op, not actually adjusting terminal settings } case 21519: { if (!stream.tty) return -59; var argp = SYSCALLS.get(); HEAP32[((argp)>>2)] = 0; return 0; } case 21520: { if (!stream.tty) return -59; return -28; // not supported } case 21531: { var argp = SYSCALLS.get(); return FS.ioctl(stream, op, argp); } case 21523: { // TODO: in theory we should write to the winsize struct that gets // passed in, but for now musl doesn't read anything on it if (!stream.tty) return -59; return 0; } case 21524: { // TODO: technically, this ioctl call should change the window size. // but, since emscripten doesn't have any concept of a terminal window // yet, we'll just silently throw it away as we do TIOCGWINSZ if (!stream.tty) return -59; return 0; } default: abort('bad ioctl syscall ' + op); } } catch (e) { if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e); return -e.errno; } } function ___sys_open(path, flags, varargs) {SYSCALLS.varargs = varargs; try { var pathname = SYSCALLS.getStr(path); var mode = varargs ? SYSCALLS.get() : 0; var stream = FS.open(pathname, flags, mode); return stream.fd; } catch (e) { if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e); return -e.errno; } } var _emscripten_get_now;_emscripten_get_now = function() { return performance.now(); } ; var _emscripten_get_now_is_monotonic=true;; function _clock_gettime(clk_id, tp) { // int clock_gettime(clockid_t clk_id, struct timespec *tp); var now; if (clk_id === 0) { now = Date.now(); } else if ((clk_id === 1 || clk_id === 4) && _emscripten_get_now_is_monotonic) { now = _emscripten_get_now(); } else { setErrNo(28); return -1; } HEAP32[((tp)>>2)] = (now/1000)|0; // seconds HEAP32[(((tp)+(4))>>2)] = ((now % 1000)*1000*1000)|0; // nanoseconds return 0; } function _dlclose(handle) { abort("To use dlopen, you need to use Emscripten's linking support, see https://github.com/emscripten-core/emscripten/wiki/Linking"); } 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 (!Browser.mainLoop.running) { Browser.mainLoop.running = true; } 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'; } else if (mode == 1 /*EM_TIMING_RAF*/) { Browser.mainLoop.scheduler = function Browser_mainLoop_scheduler_rAF() { Browser.requestAnimationFrame(Browser.mainLoop.runner); }; Browser.mainLoop.method = 'rAF'; } else if (mode == 2 /*EM_TIMING_SETIMMEDIATE*/) { if (typeof setImmediate === 'undefined') { // 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'; var Browser_setImmediate_messageHandler = function(event) { // When called in current thread or Worker, the main loop ID is structured slightly different to accommodate for --proxy-to-worker runtime listening to Worker events, // so check for both cases. if (event.data === emscriptenMainLoopMessageId || event.data.target === emscriptenMainLoopMessageId) { event.stopPropagation(); setImmediates.shift()(); } } addEventListener("message", Browser_setImmediate_messageHandler, true); setImmediate = /** @type{function(function(): ?, ...?): number} */(function Browser_emulated_setImmediate(func) { setImmediates.push(func); if (ENVIRONMENT_IS_WORKER) { if (Module['setImmediates'] === undefined) Module['setImmediates'] = []; Module['setImmediates'].push(func); postMessage({target: emscriptenMainLoopMessageId}); // In --proxy-to-worker, route the message via proxyClient.js } else postMessage(emscriptenMainLoopMessageId, "*"); // On the main thread, can just send the message to itself. }) } Browser.mainLoop.scheduler = function Browser_mainLoop_scheduler_setImmediate() { setImmediate(Browser.mainLoop.runner); }; Browser.mainLoop.method = 'immediate'; } return 0; } function runtimeKeepalivePush() { runtimeKeepaliveCounter += 1; } function _exit(status) { // void _exit(int status); // http://pubs.opengroup.org/onlinepubs/000095399/functions/exit.html exit(status); } function maybeExit() { if (!keepRuntimeAlive()) { try { _exit(EXITSTATUS); } catch (e) { if (e instanceof ExitStatus) { return; } throw e; } } } function setMainLoop(browserIterationFunc, fps, simulateInfiniteLoop, arg, noSetTiming) { 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.'); Browser.mainLoop.func = browserIterationFunc; Browser.mainLoop.arg = arg; var thisMainLoopId = Browser.mainLoop.currentlyRunningMainloop; function checkIsRunning() { if (thisMainLoopId < Browser.mainLoop.currentlyRunningMainloop) { maybeExit(); return false; } return true; } // We create the loop runner here but it is not actually running until // _emscripten_set_main_loop_timing is called (which might happen a // later time). This member signifies that the current runner has not // yet been started so that we can call runtimeKeepalivePush when it // gets it timing set for the first time. Browser.mainLoop.running = false; 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 (!checkIsRunning()) return; setTimeout(Browser.mainLoop.runner, 0); return; } // catch pauses from non-main loop sources if (!checkIsRunning()) 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; } else if (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. GL.newRenderingFrameStarted(); Browser.mainLoop.runIter(browserIterationFunc); // catch pauses from the main loop itself if (!checkIsRunning()) 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 'unwind'; } } function callUserCallback(func) { if (ABORT) { } try { func(); } catch (e) { if (e instanceof ExitStatus) { return; } else if (e !== 'unwind') { // And actual unexpected user-exectpion occured if (e && typeof e === 'object' && e.stack) err('exception thrown: ' + [e, e.stack]); throw e; } } } function runtimeKeepalivePop() { runtimeKeepaliveCounter -= 1; } var Browser={mainLoop:{running:false,scheduler:null,method:"",currentlyRunningMainloop:0,func:null,arg:0,timingMode:0,timingValue:0,currentFrameNumber:0,queue:[],pause:function() { Browser.mainLoop.scheduler = null; // Incrementing this signals the previous main loop that it's now become old, and it must return. Browser.mainLoop.currentlyRunningMainloop++; },resume:function() { Browser.mainLoop.currentlyRunningMainloop++; var timingMode = Browser.mainLoop.timingMode; var timingValue = Browser.mainLoop.timingValue; var func = Browser.mainLoop.func; Browser.mainLoop.func = null; // do not set timing and call scheduler, we will do it on the next lines setMainLoop(func, 0, false, Browser.mainLoop.arg, true); _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 } } callUserCallback(func); 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) { 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; } else if (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); document.addEventListener('pointerlockchange', pointerLockChange, false); document.addEventListener('mozpointerlockchange', pointerLockChange, false); document.addEventListener('webkitpointerlockchange', pointerLockChange, false); document.addEventListener('mspointerlockchange', pointerLockChange, false); 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: true, stencil: true, depth: true, lowLatency: true, majorVersion: (typeof WebGL2RenderingContext !== 'undefined') ? 2 : 1, }; if (webGLContextAttributes) { for (var attribute in webGLContextAttributes) { contextAttributes[attribute] = webGLContextAttributes[attribute]; } } // This check of existence of GL is here to satisfy Closure compiler, which yells if variable GL is referenced below but GL object is not // actually compiled in because application is not doing any GL operations. TODO: Ideally if GL is not being used, this function // Browser.createContext() should not even be emitted. if (typeof GL !== 'undefined') { contextHandle = GL.createContext(canvas, contextAttributes); if (contextHandle) { ctx = GL.getContext(contextHandle).GLctx; } } } else { ctx = canvas.getContext('2d'); } if (!ctx) return null; 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'); Module.ctx = ctx; if (useWebGL) GL.makeContextCurrent(contextHandle); Module.useWebGL = useWebGL; Browser.moduleContextCreatedCallbacks.forEach(function(callback) { callback() }); Browser.init(); } return ctx; },destroyContext:function(canvas, useWebGL, setInModule) {},fullscreenHandlersInstalled:false,lockPointer:undefined,resizeCanvas:undefined,requestFullscreen:function(lockPointer, resizeCanvas) { Browser.lockPointer = lockPointer; Browser.resizeCanvas = resizeCanvas; if (typeof Browser.lockPointer === 'undefined') Browser.lockPointer = true; if (typeof Browser.resizeCanvas === 'undefined') Browser.resizeCanvas = false; 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 = Browser.exitFullscreen; if (Browser.lockPointer) canvas.requestPointerLock(); Browser.isFullscreen = true; if (Browser.resizeCanvas) { Browser.setFullscreenCanvasSize(); } else { Browser.updateCanvasDimensions(canvas); } } 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(); } else { Browser.updateCanvasDimensions(canvas); } } if (Module['onFullScreen']) Module['onFullScreen'](Browser.isFullscreen); if (Module['onFullscreen']) Module['onFullscreen'](Browser.isFullscreen); } if (!Browser.fullscreenHandlersInstalled) { Browser.fullscreenHandlersInstalled = true; document.addEventListener('fullscreenchange', fullscreenChange, false); document.addEventListener('mozfullscreenchange', fullscreenChange, false); document.addEventListener('webkitfullscreenchange', fullscreenChange, false); document.addEventListener('MSFullscreenChange', fullscreenChange, false); } // 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); canvasContainer.requestFullscreen(); },exitFullscreen:function() { // This is workaround for chrome. Trying to exit from fullscreen // not in fullscreen state will cause "TypeError: Document not active" // in chrome. See https://github.com/emscripten-core/emscripten/pull/8236 if (!Browser.isFullscreen) { return false; } var CFS = document['exitFullscreen'] || document['cancelFullScreen'] || document['mozCancelFullScreen'] || document['msExitFullscreen'] || document['webkitCancelFullScreen'] || (function() {}); CFS.apply(document, []); return true; },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(func) { if (typeof requestAnimationFrame === 'function') { requestAnimationFrame(func); return; } var RAF = Browser.fakeRequestAnimationFrame; RAF(func); },safeRequestAnimationFrame:function(func) { return Browser.requestAnimationFrame(function() { callUserCallback(func); }); },safeSetTimeout:function(func, timeout) { return setTimeout(function() { callUserCallback(func); }, 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': // 3 lines make up a step delta = event.detail / 3; break; case 'mousewheel': // 120 units make up a step delta = event.wheelDelta / 120; break; case 'wheel': delta = event.deltaY switch (event.deltaMode) { case 0: // DOM_DELTA_PIXEL: 100 pixels make up a step delta /= 100; break; case 1: // DOM_DELTA_LINE: 3 lines make up a step delta /= 3; break; case 2: // DOM_DELTA_PAGE: A page makes up 80 steps delta *= 80; break; default: throw 'unrecognized mouse wheel delta mode: ' + event.deltaMode; } 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); adjustedX = adjustedX * (cw / rect.width); adjustedY = adjustedY * (ch / rect.height); var coords = { x: adjustedX, y: adjustedY }; if (event.type === 'touchstart') { Browser.lastTouches[touch.identifier] = coords; Browser.touches[touch.identifier] = coords; } else if (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) : ''; 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)>>2)]; flags = flags | 0x00800000; // set SDL_FULLSCREEN flag HEAP32[((SDL.screen)>>2)] = flags } Browser.updateCanvasDimensions(Module['canvas']); Browser.updateResizeListeners(); },setWindowedCanvasSize:function() { // check if SDL is available if (typeof SDL != "undefined") { var flags = HEAPU32[((SDL.screen)>>2)]; flags = flags & ~0x00800000; // clear SDL_FULLSCREEN flag HEAP32[((SDL.screen)>>2)] = flags } Browser.updateCanvasDimensions(Module['canvas']); 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; }}; var EGL={errorCode:12288,defaultDisplayInitialized:false,currentContext:0,currentReadSurface:0,currentDrawSurface:0,contextAttributes:{alpha:false,depth:false,stencil:false,antialias:false},stringCache:{},setErrorCode:function(code) { EGL.errorCode = code; },chooseConfig:function(display, attribList, config, config_size, numConfigs) { if (display != 62000 /* Magic ID for Emscripten 'default display' */) { EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */); return 0; } if (attribList) { // read attribList if it is non-null for (;;) { var param = HEAP32[((attribList)>>2)]; if (param == 0x3021 /*EGL_ALPHA_SIZE*/) { var alphaSize = HEAP32[(((attribList)+(4))>>2)]; EGL.contextAttributes.alpha = (alphaSize > 0); var requestedPriority = HEAP32[(((attribList)+(4))>>2)]; EGL.contextAttributes.lowLatency = (requestedPriority != 0x3103 /*EGL_CONTEXT_PRIORITY_LOW_IMG*/); } else if (param == 0x3025 /*EGL_DEPTH_SIZE*/) { var depthSize = HEAP32[(((attribList)+(4))>>2)]; EGL.contextAttributes.depth = (depthSize > 0); } else if (param == 0x3026 /*EGL_STENCIL_SIZE*/) { var stencilSize = HEAP32[(((attribList)+(4))>>2)]; EGL.contextAttributes.stencil = (stencilSize > 0); } else if (param == 0x3031 /*EGL_SAMPLES*/) { var samples = HEAP32[(((attribList)+(4))>>2)]; EGL.contextAttributes.antialias = (samples > 0); } else if (param == 0x3032 /*EGL_SAMPLE_BUFFERS*/) { var samples = HEAP32[(((attribList)+(4))>>2)]; EGL.contextAttributes.antialias = (samples == 1); } else if (param == 0x3100 /*EGL_CONTEXT_PRIORITY_LEVEL_IMG*/) { var requestedPriority = HEAP32[(((attribList)+(4))>>2)]; EGL.contextAttributes.lowLatency = (requestedPriority != 0x3103 /*EGL_CONTEXT_PRIORITY_LOW_IMG*/); } else if (param == 0x3038 /*EGL_NONE*/) { break; } attribList += 8; } } if ((!config || !config_size) && !numConfigs) { EGL.setErrorCode(0x300C /* EGL_BAD_PARAMETER */); return 0; } if (numConfigs) { HEAP32[((numConfigs)>>2)] = 1; // Total number of supported configs: 1. } if (config && config_size > 0) { HEAP32[((config)>>2)] = 62002; } EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); return 1; }}; function _eglBindAPI(api) { if (api == 0x30A0 /* EGL_OPENGL_ES_API */) { EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); return 1; } else { // if (api == 0x30A1 /* EGL_OPENVG_API */ || api == 0x30A2 /* EGL_OPENGL_API */) { EGL.setErrorCode(0x300C /* EGL_BAD_PARAMETER */); return 0; } } function _eglChooseConfig(display, attrib_list, configs, config_size, numConfigs) { return EGL.chooseConfig(display, attrib_list, configs, config_size, numConfigs); } function __webgl_enable_ANGLE_instanced_arrays(ctx) { // Extension available in WebGL 1 from Firefox 26 and Google Chrome 30 onwards. Core feature in WebGL 2. var ext = ctx.getExtension('ANGLE_instanced_arrays'); if (ext) { ctx['vertexAttribDivisor'] = function(index, divisor) { ext['vertexAttribDivisorANGLE'](index, divisor); }; ctx['drawArraysInstanced'] = function(mode, first, count, primcount) { ext['drawArraysInstancedANGLE'](mode, first, count, primcount); }; ctx['drawElementsInstanced'] = function(mode, count, type, indices, primcount) { ext['drawElementsInstancedANGLE'](mode, count, type, indices, primcount); }; return 1; } } function __webgl_enable_OES_vertex_array_object(ctx) { // Extension available in WebGL 1 from Firefox 25 and WebKit 536.28/desktop Safari 6.0.3 onwards. Core feature in WebGL 2. var ext = ctx.getExtension('OES_vertex_array_object'); if (ext) { ctx['createVertexArray'] = function() { return ext['createVertexArrayOES'](); }; ctx['deleteVertexArray'] = function(vao) { ext['deleteVertexArrayOES'](vao); }; ctx['bindVertexArray'] = function(vao) { ext['bindVertexArrayOES'](vao); }; ctx['isVertexArray'] = function(vao) { return ext['isVertexArrayOES'](vao); }; return 1; } } function __webgl_enable_WEBGL_draw_buffers(ctx) { // Extension available in WebGL 1 from Firefox 28 onwards. Core feature in WebGL 2. var ext = ctx.getExtension('WEBGL_draw_buffers'); if (ext) { ctx['drawBuffers'] = function(n, bufs) { ext['drawBuffersWEBGL'](n, bufs); }; return 1; } } function __webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(ctx) { // Closure is expected to be allowed to minify the '.dibvbi' property, so not accessing it quoted. return !!(ctx.dibvbi = ctx.getExtension('WEBGL_draw_instanced_base_vertex_base_instance')); } function __webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance(ctx) { // Closure is expected to be allowed to minify the '.mdibvbi' property, so not accessing it quoted. return !!(ctx.mdibvbi = ctx.getExtension('WEBGL_multi_draw_instanced_base_vertex_base_instance')); } function __webgl_enable_WEBGL_multi_draw(ctx) { // Closure is expected to be allowed to minify the '.multiDrawWebgl' property, so not accessing it quoted. return !!(ctx.multiDrawWebgl = ctx.getExtension('WEBGL_multi_draw')); } var GL={counter:1,buffers:[],mappedBuffers:{},programs:[],framebuffers:[],renderbuffers:[],textures:[],uniforms:[],shaders:[],vaos:[],contexts:[],offscreenCanvases:{},timerQueriesEXT:[],queries:[],samplers:[],transformFeedbacks:[],syncs:[],byteSizeByTypeRoot:5120,byteSizeByType:[1,1,2,2,4,4,4,2,3,4,8],programInfos:{},stringCache:{},stringiCache:{},unpackAlignment:4,recordError:function recordError(errorCode) { if (!GL.lastError) { GL.lastError = errorCode; } },getNewId:function(table) { var ret = GL.counter++; for (var i = table.length; i < ret; i++) { table[i] = null; } return ret; },MAX_TEMP_BUFFER_SIZE:2097152,numTempVertexBuffersPerSize:64,log2ceilLookup:function(i) { return 32 - Math.clz32(i === 0 ? 0 : i - 1); },generateTempBuffers:function(quads, context) { var largestIndex = GL.log2ceilLookup(GL.MAX_TEMP_BUFFER_SIZE); context.tempVertexBufferCounters1 = []; context.tempVertexBufferCounters2 = []; context.tempVertexBufferCounters1.length = context.tempVertexBufferCounters2.length = largestIndex+1; context.tempVertexBuffers1 = []; context.tempVertexBuffers2 = []; context.tempVertexBuffers1.length = context.tempVertexBuffers2.length = largestIndex+1; context.tempIndexBuffers = []; context.tempIndexBuffers.length = largestIndex+1; for (var i = 0; i <= largestIndex; ++i) { context.tempIndexBuffers[i] = null; // Created on-demand context.tempVertexBufferCounters1[i] = context.tempVertexBufferCounters2[i] = 0; var ringbufferLength = GL.numTempVertexBuffersPerSize; context.tempVertexBuffers1[i] = []; context.tempVertexBuffers2[i] = []; var ringbuffer1 = context.tempVertexBuffers1[i]; var ringbuffer2 = context.tempVertexBuffers2[i]; ringbuffer1.length = ringbuffer2.length = ringbufferLength; for (var j = 0; j < ringbufferLength; ++j) { ringbuffer1[j] = ringbuffer2[j] = null; // Created on-demand } } if (quads) { // GL_QUAD indexes can be precalculated context.tempQuadIndexBuffer = GLctx.createBuffer(); context.GLctx.bindBuffer(0x8893 /*GL_ELEMENT_ARRAY_BUFFER*/, context.tempQuadIndexBuffer); var numIndexes = GL.MAX_TEMP_BUFFER_SIZE >> 1; var quadIndexes = new Uint16Array(numIndexes); var i = 0, v = 0; while (1) { quadIndexes[i++] = v; if (i >= numIndexes) break; quadIndexes[i++] = v+1; if (i >= numIndexes) break; quadIndexes[i++] = v+2; if (i >= numIndexes) break; quadIndexes[i++] = v; if (i >= numIndexes) break; quadIndexes[i++] = v+2; if (i >= numIndexes) break; quadIndexes[i++] = v+3; if (i >= numIndexes) break; v += 4; } context.GLctx.bufferData(0x8893 /*GL_ELEMENT_ARRAY_BUFFER*/, quadIndexes, 0x88E4 /*GL_STATIC_DRAW*/); context.GLctx.bindBuffer(0x8893 /*GL_ELEMENT_ARRAY_BUFFER*/, null); } },getTempVertexBuffer:function getTempVertexBuffer(sizeBytes) { var idx = GL.log2ceilLookup(sizeBytes); var ringbuffer = GL.currentContext.tempVertexBuffers1[idx]; var nextFreeBufferIndex = GL.currentContext.tempVertexBufferCounters1[idx]; GL.currentContext.tempVertexBufferCounters1[idx] = (GL.currentContext.tempVertexBufferCounters1[idx]+1) & (GL.numTempVertexBuffersPerSize-1); var vbo = ringbuffer[nextFreeBufferIndex]; if (vbo) { return vbo; } var prevVBO = GLctx.getParameter(0x8894 /*GL_ARRAY_BUFFER_BINDING*/); ringbuffer[nextFreeBufferIndex] = GLctx.createBuffer(); GLctx.bindBuffer(0x8892 /*GL_ARRAY_BUFFER*/, ringbuffer[nextFreeBufferIndex]); GLctx.bufferData(0x8892 /*GL_ARRAY_BUFFER*/, 1 << idx, 0x88E8 /*GL_DYNAMIC_DRAW*/); GLctx.bindBuffer(0x8892 /*GL_ARRAY_BUFFER*/, prevVBO); return ringbuffer[nextFreeBufferIndex]; },getTempIndexBuffer:function getTempIndexBuffer(sizeBytes) { var idx = GL.log2ceilLookup(sizeBytes); var ibo = GL.currentContext.tempIndexBuffers[idx]; if (ibo) { return ibo; } var prevIBO = GLctx.getParameter(0x8895 /*ELEMENT_ARRAY_BUFFER_BINDING*/); GL.currentContext.tempIndexBuffers[idx] = GLctx.createBuffer(); GLctx.bindBuffer(0x8893 /*GL_ELEMENT_ARRAY_BUFFER*/, GL.currentContext.tempIndexBuffers[idx]); GLctx.bufferData(0x8893 /*GL_ELEMENT_ARRAY_BUFFER*/, 1 << idx, 0x88E8 /*GL_DYNAMIC_DRAW*/); GLctx.bindBuffer(0x8893 /*GL_ELEMENT_ARRAY_BUFFER*/, prevIBO); return GL.currentContext.tempIndexBuffers[idx]; },newRenderingFrameStarted:function newRenderingFrameStarted() { if (!GL.currentContext) { return; } var vb = GL.currentContext.tempVertexBuffers1; GL.currentContext.tempVertexBuffers1 = GL.currentContext.tempVertexBuffers2; GL.currentContext.tempVertexBuffers2 = vb; vb = GL.currentContext.tempVertexBufferCounters1; GL.currentContext.tempVertexBufferCounters1 = GL.currentContext.tempVertexBufferCounters2; GL.currentContext.tempVertexBufferCounters2 = vb; var largestIndex = GL.log2ceilLookup(GL.MAX_TEMP_BUFFER_SIZE); for (var i = 0; i <= largestIndex; ++i) { GL.currentContext.tempVertexBufferCounters1[i] = 0; } },getSource:function(shader, count, string, length) { var source = ''; for (var i = 0; i < count; ++i) { var len = length ? HEAP32[(((length)+(i*4))>>2)] : -1; source += UTF8ToString(HEAP32[(((string)+(i*4))>>2)], len < 0 ? undefined : len); } return source; },calcBufLength:function calcBufLength(size, type, stride, count) { if (stride > 0) { return count * stride; // XXXvlad this is not exactly correct I don't think } var typeSize = GL.byteSizeByType[type - GL.byteSizeByTypeRoot]; return size * typeSize * count; },usedTempBuffers:[],preDrawHandleClientVertexAttribBindings:function preDrawHandleClientVertexAttribBindings(count) { GL.resetBufferBinding = false; // TODO: initial pass to detect ranges we need to upload, might not need an upload per attrib for (var i = 0; i < GL.currentContext.maxVertexAttribs; ++i) { var cb = GL.currentContext.clientBuffers[i]; if (!cb.clientside || !cb.enabled) continue; GL.resetBufferBinding = true; var size = GL.calcBufLength(cb.size, cb.type, cb.stride, count); var buf = GL.getTempVertexBuffer(size); GLctx.bindBuffer(0x8892 /*GL_ARRAY_BUFFER*/, buf); GLctx.bufferSubData(0x8892 /*GL_ARRAY_BUFFER*/, 0, HEAPU8.subarray(cb.ptr, cb.ptr + size)); cb.vertexAttribPointerAdaptor.call(GLctx, i, cb.size, cb.type, cb.normalized, cb.stride, 0); } },postDrawHandleClientVertexAttribBindings:function postDrawHandleClientVertexAttribBindings() { if (GL.resetBufferBinding) { GLctx.bindBuffer(0x8892 /*GL_ARRAY_BUFFER*/, GL.buffers[GLctx.currentArrayBufferBinding]); } },createContext:function(canvas, webGLContextAttributes) { webGLContextAttributes['preserveDrawingBuffer'] = true; // BUG: Workaround Safari WebGL issue: After successfully acquiring WebGL context on a canvas, // calling .getContext() will always return that context independent of which 'webgl' or 'webgl2' // context version was passed. See https://bugs.webkit.org/show_bug.cgi?id=222758 and // https://github.com/emscripten-core/emscripten/issues/13295. // TODO: Once the bug is fixed and shipped in Safari, adjust the Safari version field in above check. if (!canvas.getContextSafariWebGL2Fixed) { canvas.getContextSafariWebGL2Fixed = canvas.getContext; canvas.getContext = function(ver, attrs) { var gl = canvas.getContextSafariWebGL2Fixed(ver, attrs); return ((ver == 'webgl') == (gl instanceof WebGLRenderingContext)) ? gl : null; } } var ctx = (webGLContextAttributes.majorVersion > 1) ? canvas.getContext("webgl2", webGLContextAttributes) : (canvas.getContext("webgl", webGLContextAttributes) // https://caniuse.com/#feat=webgl ); if (!ctx) return 0; var handle = GL.registerContext(ctx, webGLContextAttributes); return handle; },registerContext:function(ctx, webGLContextAttributes) { // without pthreads a context is just an integer ID var handle = GL.getNewId(GL.contexts); var context = { handle: handle, attributes: webGLContextAttributes, version: webGLContextAttributes.majorVersion, GLctx: ctx }; // Store the created context object so that we can access the context given a canvas without having to pass the parameters again. if (ctx.canvas) ctx.canvas.GLctxObject = context; GL.contexts[handle] = context; if (typeof webGLContextAttributes.enableExtensionsByDefault === 'undefined' || webGLContextAttributes.enableExtensionsByDefault) { GL.initExtensions(context); } context.maxVertexAttribs = context.GLctx.getParameter(0x8869 /*GL_MAX_VERTEX_ATTRIBS*/); context.clientBuffers = []; for (var i = 0; i < context.maxVertexAttribs; i++) { context.clientBuffers[i] = { enabled: false, clientside: false, size: 0, type: 0, normalized: 0, stride: 0, ptr: 0, vertexAttribPointerAdaptor: null }; } GL.generateTempBuffers(false, context); return handle; },makeContextCurrent:function(contextHandle) { GL.currentContext = GL.contexts[contextHandle]; // Active Emscripten GL layer context object. Module.ctx = GLctx = GL.currentContext && GL.currentContext.GLctx; // Active WebGL context object. return !(contextHandle && !GLctx); },getContext:function(contextHandle) { return GL.contexts[contextHandle]; },deleteContext:function(contextHandle) { if (GL.currentContext === GL.contexts[contextHandle]) GL.currentContext = null; if (typeof JSEvents === 'object') JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas); // Release all JS event handlers on the DOM element that the GL context is associated with since the context is now deleted. if (GL.contexts[contextHandle] && GL.contexts[contextHandle].GLctx.canvas) GL.contexts[contextHandle].GLctx.canvas.GLctxObject = undefined; // Make sure the canvas object no longer refers to the context object so there are no GC surprises. GL.contexts[contextHandle] = null; },initExtensions:function(context) { // If this function is called without a specific context object, init the extensions of the currently active context. if (!context) context = GL.currentContext; if (context.initExtensionsDone) return; context.initExtensionsDone = true; var GLctx = context.GLctx; // Detect the presence of a few extensions manually, this GL interop layer itself will need to know if they exist. // Extensions that are only available in WebGL 1 (the calls will be no-ops if called on a WebGL 2 context active) __webgl_enable_ANGLE_instanced_arrays(GLctx); __webgl_enable_OES_vertex_array_object(GLctx); __webgl_enable_WEBGL_draw_buffers(GLctx); // Extensions that are available from WebGL >= 2 (no-op if called on a WebGL 1 context active) __webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(GLctx); __webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance(GLctx); GLctx.disjointTimerQueryExt = GLctx.getExtension("EXT_disjoint_timer_query"); __webgl_enable_WEBGL_multi_draw(GLctx); // .getSupportedExtensions() can return null if context is lost, so coerce to empty array. var exts = GLctx.getSupportedExtensions() || []; exts.forEach(function(ext) { // WEBGL_lose_context, WEBGL_debug_renderer_info and WEBGL_debug_shaders are not enabled by default. if (ext.indexOf('lose_context') < 0 && ext.indexOf('debug') < 0) { // Call .getExtension() to enable that extension permanently. GLctx.getExtension(ext); } }); },populateUniformTable:function(program) { var p = GL.programs[program]; var ptable = GL.programInfos[program] = { uniforms: {}, maxUniformLength: 0, // This is eagerly computed below, since we already enumerate all uniforms anyway. maxAttributeLength: -1, // This is lazily computed and cached, computed when/if first asked, "-1" meaning not computed yet. maxUniformBlockNameLength: -1 // Lazily computed as well }; var utable = ptable.uniforms; // A program's uniform table maps the string name of an uniform to an integer location of that uniform. // The global GL.uniforms map maps integer locations to WebGLUniformLocations. var numUniforms = GLctx.getProgramParameter(p, 0x8B86/*GL_ACTIVE_UNIFORMS*/); for (var i = 0; i < numUniforms; ++i) { var u = GLctx.getActiveUniform(p, i); var name = u.name; ptable.maxUniformLength = Math.max(ptable.maxUniformLength, name.length+1); // If we are dealing with an array, e.g. vec4 foo[3], strip off the array index part to canonicalize that "foo", "foo[]", // and "foo[0]" will mean the same. Loop below will populate foo[1] and foo[2]. if (name.slice(-1) == ']') { name = name.slice(0, name.lastIndexOf('[')); } // Optimize memory usage slightly: If we have an array of uniforms, e.g. 'vec3 colors[3];', then // only store the string 'colors' in utable, and 'colors[0]', 'colors[1]' and 'colors[2]' will be parsed as 'colors'+i. // Note that for the GL.uniforms table, we still need to fetch the all WebGLUniformLocations for all the indices. var loc = GLctx.getUniformLocation(p, name); if (loc) { var id = GL.getNewId(GL.uniforms); utable[name] = [u.size, id]; GL.uniforms[id] = loc; for (var j = 1; j < u.size; ++j) { var n = name + '['+j+']'; loc = GLctx.getUniformLocation(p, n); id = GL.getNewId(GL.uniforms); GL.uniforms[id] = loc; } } } }}; function _eglCreateContext(display, config, hmm, contextAttribs) { if (display != 62000 /* Magic ID for Emscripten 'default display' */) { EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */); return 0; } // EGL 1.4 spec says default EGL_CONTEXT_CLIENT_VERSION is GLES1, but this is not supported by Emscripten. // So user must pass EGL_CONTEXT_CLIENT_VERSION == 2 to initialize EGL. var glesContextVersion = 1; for (;;) { var param = HEAP32[((contextAttribs)>>2)]; if (param == 0x3098 /*EGL_CONTEXT_CLIENT_VERSION*/) { glesContextVersion = HEAP32[(((contextAttribs)+(4))>>2)]; } else if (param == 0x3038 /*EGL_NONE*/) { break; } else { /* EGL1.4 specifies only EGL_CONTEXT_CLIENT_VERSION as supported attribute */ EGL.setErrorCode(0x3004 /*EGL_BAD_ATTRIBUTE*/); return 0; } contextAttribs += 8; } if (glesContextVersion < 2 || glesContextVersion > 3) { EGL.setErrorCode(0x3005 /* EGL_BAD_CONFIG */); return 0; /* EGL_NO_CONTEXT */ } EGL.contextAttributes.majorVersion = glesContextVersion - 1; // WebGL 1 is GLES 2, WebGL2 is GLES3 EGL.contextAttributes.minorVersion = 0; EGL.context = GL.createContext(Module['canvas'], EGL.contextAttributes); if (EGL.context != 0) { EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); // Run callbacks so that GL emulation works GL.makeContextCurrent(EGL.context); Module.useWebGL = true; Browser.moduleContextCreatedCallbacks.forEach(function(callback) { callback() }); // Note: This function only creates a context, but it shall not make it active. GL.makeContextCurrent(null); return 62004; // Magic ID for Emscripten EGLContext } else { EGL.setErrorCode(0x3009 /* EGL_BAD_MATCH */); // By the EGL 1.4 spec, an implementation that does not support GLES2 (WebGL in this case), this error code is set. return 0; /* EGL_NO_CONTEXT */ } } function _eglCreateWindowSurface(display, config, win, attrib_list) { if (display != 62000 /* Magic ID for Emscripten 'default display' */) { EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */); return 0; } if (config != 62002 /* Magic ID for the only EGLConfig supported by Emscripten */) { EGL.setErrorCode(0x3005 /* EGL_BAD_CONFIG */); return 0; } // TODO: Examine attrib_list! Parameters that can be present there are: // - EGL_RENDER_BUFFER (must be EGL_BACK_BUFFER) // - EGL_VG_COLORSPACE (can't be set) // - EGL_VG_ALPHA_FORMAT (can't be set) EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); return 62006; /* Magic ID for Emscripten 'default surface' */ } function _eglDestroyContext(display, context) { if (display != 62000 /* Magic ID for Emscripten 'default display' */) { EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */); return 0; } if (context != 62004 /* Magic ID for Emscripten EGLContext */) { EGL.setErrorCode(0x3006 /* EGL_BAD_CONTEXT */); return 0; } GL.deleteContext(EGL.context); EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); if (EGL.currentContext == context) { EGL.currentContext = 0; } return 1 /* EGL_TRUE */; } function _eglDestroySurface(display, surface) { if (display != 62000 /* Magic ID for Emscripten 'default display' */) { EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */); return 0; } if (surface != 62006 /* Magic ID for the only EGLSurface supported by Emscripten */) { EGL.setErrorCode(0x300D /* EGL_BAD_SURFACE */); return 1; } if (EGL.currentReadSurface == surface) { EGL.currentReadSurface = 0; } if (EGL.currentDrawSurface == surface) { EGL.currentDrawSurface = 0; } EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); return 1; /* Magic ID for Emscripten 'default surface' */ } function _eglGetConfigAttrib(display, config, attribute, value) { if (display != 62000 /* Magic ID for Emscripten 'default display' */) { EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */); return 0; } if (config != 62002 /* Magic ID for the only EGLConfig supported by Emscripten */) { EGL.setErrorCode(0x3005 /* EGL_BAD_CONFIG */); return 0; } if (!value) { EGL.setErrorCode(0x300C /* EGL_BAD_PARAMETER */); return 0; } EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); switch (attribute) { case 0x3020: // EGL_BUFFER_SIZE HEAP32[((value)>>2)] = EGL.contextAttributes.alpha ? 32 : 32; return 1; case 0x3021: // EGL_ALPHA_SIZE HEAP32[((value)>>2)] = EGL.contextAttributes.alpha ? 32 : 0; return 1; case 0x3022: // EGL_BLUE_SIZE HEAP32[((value)>>2)] = 32; return 1; case 0x3023: // EGL_GREEN_SIZE HEAP32[((value)>>2)] = 32; return 1; case 0x3024: // EGL_RED_SIZE HEAP32[((value)>>2)] = 32; return 1; case 0x3025: // EGL_DEPTH_SIZE HEAP32[((value)>>2)] = EGL.contextAttributes.depth ? 32 : 0; return 1; case 0x3026: // EGL_STENCIL_SIZE HEAP32[((value)>>2)] = EGL.contextAttributes.stencil ? 32 : 0; return 1; case 0x3027: // EGL_CONFIG_CAVEAT // We can return here one of EGL_NONE (0x3038), EGL_SLOW_CONFIG (0x3050) or EGL_NON_CONFORMANT_CONFIG (0x3051). HEAP32[((value)>>2)] = 0x3038; return 1; case 0x3028: // EGL_CONFIG_ID HEAP32[((value)>>2)] = 62002; return 1; case 0x3029: // EGL_LEVEL HEAP32[((value)>>2)] = 0; return 1; case 0x302A: // EGL_MAX_PBUFFER_HEIGHT HEAP32[((value)>>2)] = 4096; return 1; case 0x302B: // EGL_MAX_PBUFFER_PIXELS HEAP32[((value)>>2)] = 16777216; return 1; case 0x302C: // EGL_MAX_PBUFFER_WIDTH HEAP32[((value)>>2)] = 4096; return 1; case 0x302D: // EGL_NATIVE_RENDERABLE HEAP32[((value)>>2)] = 0; return 1; case 0x302E: // EGL_NATIVE_VISUAL_ID HEAP32[((value)>>2)] = 0; return 1; case 0x302F: // EGL_NATIVE_VISUAL_TYPE HEAP32[((value)>>2)] = 0x3038; return 1; case 0x3031: // EGL_SAMPLES HEAP32[((value)>>2)] = EGL.contextAttributes.antialias ? 4 : 0; return 1; case 0x3032: // EGL_SAMPLE_BUFFERS HEAP32[((value)>>2)] = EGL.contextAttributes.antialias ? 1 : 0; return 1; case 0x3033: // EGL_SURFACE_TYPE HEAP32[((value)>>2)] = 0x4; return 1; case 0x3034: // EGL_TRANSPARENT_TYPE // If this returns EGL_TRANSPARENT_RGB (0x3052), transparency is used through color-keying. No such thing applies to Emscripten canvas. HEAP32[((value)>>2)] = 0x3038; return 1; case 0x3035: // EGL_TRANSPARENT_BLUE_VALUE case 0x3036: // EGL_TRANSPARENT_GREEN_VALUE case 0x3037: // EGL_TRANSPARENT_RED_VALUE // "If EGL_TRANSPARENT_TYPE is EGL_NONE, then the values for EGL_TRANSPARENT_RED_VALUE, EGL_TRANSPARENT_GREEN_VALUE, and EGL_TRANSPARENT_BLUE_VALUE are undefined." HEAP32[((value)>>2)] = -1; return 1; case 0x3039: // EGL_BIND_TO_TEXTURE_RGB case 0x303A: // EGL_BIND_TO_TEXTURE_RGBA HEAP32[((value)>>2)] = 0; return 1; case 0x303B: // EGL_MIN_SWAP_INTERVAL HEAP32[((value)>>2)] = 0; return 1; case 0x303C: // EGL_MAX_SWAP_INTERVAL HEAP32[((value)>>2)] = 1; return 1; case 0x303D: // EGL_LUMINANCE_SIZE case 0x303E: // EGL_ALPHA_MASK_SIZE HEAP32[((value)>>2)] = 0; return 1; case 0x303F: // EGL_COLOR_BUFFER_TYPE // EGL has two types of buffers: EGL_RGB_BUFFER and EGL_LUMINANCE_BUFFER. HEAP32[((value)>>2)] = 0x308E; return 1; case 0x3040: // EGL_RENDERABLE_TYPE // A bit combination of EGL_OPENGL_ES_BIT,EGL_OPENVG_BIT,EGL_OPENGL_ES2_BIT and EGL_OPENGL_BIT. HEAP32[((value)>>2)] = 0x4; return 1; case 0x3042: // EGL_CONFORMANT // "EGL_CONFORMANT is a mask indicating if a client API context created with respect to the corresponding EGLConfig will pass the required conformance tests for that API." HEAP32[((value)>>2)] = 0; return 1; default: EGL.setErrorCode(0x3004 /* EGL_BAD_ATTRIBUTE */); return 0; } } function _eglGetDisplay(nativeDisplayType) { EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); // Note: As a 'conformant' implementation of EGL, we would prefer to init here only if the user // calls this function with EGL_DEFAULT_DISPLAY. Other display IDs would be preferred to be unsupported // and EGL_NO_DISPLAY returned. Uncomment the following code lines to do this. // Instead, an alternative route has been preferred, namely that the Emscripten EGL implementation // "emulates" X11, and eglGetDisplay is expected to accept/receive a pointer to an X11 Display object. // Therefore, be lax and allow anything to be passed in, and return the magic handle to our default EGLDisplay object. // if (nativeDisplayType == 0 /* EGL_DEFAULT_DISPLAY */) { return 62000; // Magic ID for Emscripten 'default display' // } // else // return 0; // EGL_NO_DISPLAY } function _eglGetError() { return EGL.errorCode; } function _eglInitialize(display, majorVersion, minorVersion) { if (display == 62000 /* Magic ID for Emscripten 'default display' */) { if (majorVersion) { HEAP32[((majorVersion)>>2)] = 1; // Advertise EGL Major version: '1' } if (minorVersion) { HEAP32[((minorVersion)>>2)] = 4; // Advertise EGL Minor version: '4' } EGL.defaultDisplayInitialized = true; EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); return 1; } else { EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */); return 0; } } function _eglMakeCurrent(display, draw, read, context) { if (display != 62000 /* Magic ID for Emscripten 'default display' */) { EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */); return 0 /* EGL_FALSE */; } //\todo An EGL_NOT_INITIALIZED error is generated if EGL is not initialized for dpy. if (context != 0 && context != 62004 /* Magic ID for Emscripten EGLContext */) { EGL.setErrorCode(0x3006 /* EGL_BAD_CONTEXT */); return 0; } if ((read != 0 && read != 62006) || (draw != 0 && draw != 62006 /* Magic ID for Emscripten 'default surface' */)) { EGL.setErrorCode(0x300D /* EGL_BAD_SURFACE */); return 0; } GL.makeContextCurrent(context ? EGL.context : null); EGL.currentContext = context; EGL.currentDrawSurface = draw; EGL.currentReadSurface = read; EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); return 1 /* EGL_TRUE */; } function _eglQueryString(display, name) { if (display != 62000 /* Magic ID for Emscripten 'default display' */) { EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */); return 0; } //\todo An EGL_NOT_INITIALIZED error is generated if EGL is not initialized for dpy. EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); if (EGL.stringCache[name]) return EGL.stringCache[name]; var ret; switch (name) { case 0x3053 /* EGL_VENDOR */: ret = allocateUTF8("Emscripten"); break; case 0x3054 /* EGL_VERSION */: ret = allocateUTF8("1.4 Emscripten EGL"); break; case 0x3055 /* EGL_EXTENSIONS */: ret = allocateUTF8(""); break; // Currently not supporting any EGL extensions. case 0x308D /* EGL_CLIENT_APIS */: ret = allocateUTF8("OpenGL_ES"); break; default: EGL.setErrorCode(0x300C /* EGL_BAD_PARAMETER */); return 0; } EGL.stringCache[name] = ret; return ret; } function _eglSwapBuffers() { if (!EGL.defaultDisplayInitialized) { EGL.setErrorCode(0x3001 /* EGL_NOT_INITIALIZED */); } else if (!Module.ctx) { EGL.setErrorCode(0x3002 /* EGL_BAD_ACCESS */); } else if (Module.ctx.isContextLost()) { EGL.setErrorCode(0x300E /* EGL_CONTEXT_LOST */); } else { // According to documentation this does an implicit flush. // Due to discussion at https://github.com/emscripten-core/emscripten/pull/1871 // the flush was removed since this _may_ result in slowing code down. //_glFlush(); EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); return 1 /* EGL_TRUE */; } return 0 /* EGL_FALSE */; } function _eglSwapInterval(display, interval) { if (display != 62000 /* Magic ID for Emscripten 'default display' */) { EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */); return 0; } if (interval == 0) _emscripten_set_main_loop_timing(0/*EM_TIMING_SETTIMEOUT*/, 0); else _emscripten_set_main_loop_timing(1/*EM_TIMING_RAF*/, interval); EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); return 1; } function _eglTerminate(display) { if (display != 62000 /* Magic ID for Emscripten 'default display' */) { EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */); return 0; } EGL.currentContext = 0; EGL.currentReadSurface = 0; EGL.currentDrawSurface = 0; EGL.defaultDisplayInitialized = false; EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); return 1; } function _eglWaitClient() { EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); return 1; } function _eglWaitGL( ) { return _eglWaitClient(); } function _eglWaitNative(nativeEngineId) { EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); return 1; } function _emscripten_asm_const_int(code, sigPtr, argbuf) { var args = readAsmConstArgs(sigPtr, argbuf); return ASM_CONSTS[code].apply(null, args); } var JSEvents={inEventHandler:0,removeAllEventListeners:function() { for (var i = JSEvents.eventHandlers.length-1; i >= 0; --i) { JSEvents._removeHandler(i); } JSEvents.eventHandlers = []; JSEvents.deferredCalls = []; },registerRemoveEventListeners:function() { if (!JSEvents.removeEventListenersRegistered) { __ATEXIT__.push(JSEvents.removeAllEventListeners); JSEvents.removeEventListenersRegistered = true; } },deferredCalls:[],deferCall:function(targetFunction, precedence, argsList) { function arraysHaveEqualContent(arrA, arrB) { if (arrA.length != arrB.length) return false; for (var i in arrA) { if (arrA[i] != arrB[i]) return false; } return true; } // Test if the given call was already queued, and if so, don't add it again. for (var i in JSEvents.deferredCalls) { var call = JSEvents.deferredCalls[i]; if (call.targetFunction == targetFunction && arraysHaveEqualContent(call.argsList, argsList)) { return; } } JSEvents.deferredCalls.push({ targetFunction: targetFunction, precedence: precedence, argsList: argsList }); JSEvents.deferredCalls.sort(function(x,y) { return x.precedence < y.precedence; }); },removeDeferredCalls:function(targetFunction) { for (var i = 0; i < JSEvents.deferredCalls.length; ++i) { if (JSEvents.deferredCalls[i].targetFunction == targetFunction) { JSEvents.deferredCalls.splice(i, 1); --i; } } },canPerformEventHandlerRequests:function() { return JSEvents.inEventHandler && JSEvents.currentEventHandler.allowsDeferredCalls; },runDeferredCalls:function() { if (!JSEvents.canPerformEventHandlerRequests()) { return; } for (var i = 0; i < JSEvents.deferredCalls.length; ++i) { var call = JSEvents.deferredCalls[i]; JSEvents.deferredCalls.splice(i, 1); --i; call.targetFunction.apply(null, call.argsList); } },eventHandlers:[],removeAllHandlersOnTarget:function(target, eventTypeString) { for (var i = 0; i < JSEvents.eventHandlers.length; ++i) { if (JSEvents.eventHandlers[i].target == target && (!eventTypeString || eventTypeString == JSEvents.eventHandlers[i].eventTypeString)) { JSEvents._removeHandler(i--); } } },_removeHandler:function(i) { var h = JSEvents.eventHandlers[i]; h.target.removeEventListener(h.eventTypeString, h.eventListenerFunc, h.useCapture); JSEvents.eventHandlers.splice(i, 1); },registerOrRemoveHandler:function(eventHandler) { var jsEventHandler = function jsEventHandler(event) { // Increment nesting count for the event handler. ++JSEvents.inEventHandler; JSEvents.currentEventHandler = eventHandler; // Process any old deferred calls the user has placed. JSEvents.runDeferredCalls(); // Process the actual event, calls back to user C code handler. eventHandler.handlerFunc(event); // Process any new deferred calls that were placed right now from this event handler. JSEvents.runDeferredCalls(); // Out of event handler - restore nesting count. --JSEvents.inEventHandler; }; if (eventHandler.callbackfunc) { eventHandler.eventListenerFunc = jsEventHandler; eventHandler.target.addEventListener(eventHandler.eventTypeString, jsEventHandler, eventHandler.useCapture); JSEvents.eventHandlers.push(eventHandler); JSEvents.registerRemoveEventListeners(); } else { for (var i = 0; i < JSEvents.eventHandlers.length; ++i) { if (JSEvents.eventHandlers[i].target == eventHandler.target && JSEvents.eventHandlers[i].eventTypeString == eventHandler.eventTypeString) { JSEvents._removeHandler(i--); } } } },getNodeNameForTarget:function(target) { if (!target) return ''; if (target == window) return '#window'; if (target == screen) return '#screen'; return (target && target.nodeName) ? target.nodeName : ''; },fullscreenEnabled:function() { return document.fullscreenEnabled // Safari 13.0.3 on macOS Catalina 10.15.1 still ships with prefixed webkitFullscreenEnabled. // TODO: If Safari at some point ships with unprefixed version, update the version check above. || document.webkitFullscreenEnabled ; }}; var currentFullscreenStrategy={}; function maybeCStringToJsString(cString) { // "cString > 2" checks if the input is a number, and isn't of the special // values we accept here, EMSCRIPTEN_EVENT_TARGET_* (which map to 0, 1, 2). // In other words, if cString > 2 then it's a pointer to a valid place in // memory, and points to a C string. return cString > 2 ? UTF8ToString(cString) : cString; } var specialHTMLTargets=[0, document, window]; function findEventTarget(target) { target = maybeCStringToJsString(target); var domElement = specialHTMLTargets[target] || document.querySelector(target); return domElement; } function findCanvasEventTarget(target) { return findEventTarget(target); } function _emscripten_get_canvas_element_size(target, width, height) { var canvas = findCanvasEventTarget(target); if (!canvas) return -4; HEAP32[((width)>>2)] = canvas.width; HEAP32[((height)>>2)] = canvas.height; } function getCanvasElementSize(target) { var stackTop = stackSave(); var w = stackAlloc(8); var h = w + 4; var targetInt = stackAlloc(target.id.length+1); stringToUTF8(target.id, targetInt, target.id.length+1); var ret = _emscripten_get_canvas_element_size(targetInt, w, h); var size = [HEAP32[((w)>>2)], HEAP32[((h)>>2)]]; stackRestore(stackTop); return size; } function _emscripten_set_canvas_element_size(target, width, height) { var canvas = findCanvasEventTarget(target); if (!canvas) return -4; canvas.width = width; canvas.height = height; return 0; } function setCanvasElementSize(target, width, height) { if (!target.controlTransferredOffscreen) { target.width = width; target.height = height; } else { // This function is being called from high-level JavaScript code instead of asm.js/Wasm, // and it needs to synchronously proxy over to another thread, so marshal the string onto the heap to do the call. var stackTop = stackSave(); var targetInt = stackAlloc(target.id.length+1); stringToUTF8(target.id, targetInt, target.id.length+1); _emscripten_set_canvas_element_size(targetInt, width, height); stackRestore(stackTop); } } function registerRestoreOldStyle(canvas) { var canvasSize = getCanvasElementSize(canvas); var oldWidth = canvasSize[0]; var oldHeight = canvasSize[1]; var oldCssWidth = canvas.style.width; var oldCssHeight = canvas.style.height; var oldBackgroundColor = canvas.style.backgroundColor; // Chrome reads color from here. var oldDocumentBackgroundColor = document.body.style.backgroundColor; // IE11 reads color from here. // Firefox always has black background color. var oldPaddingLeft = canvas.style.paddingLeft; // Chrome, FF, Safari var oldPaddingRight = canvas.style.paddingRight; var oldPaddingTop = canvas.style.paddingTop; var oldPaddingBottom = canvas.style.paddingBottom; var oldMarginLeft = canvas.style.marginLeft; // IE11 var oldMarginRight = canvas.style.marginRight; var oldMarginTop = canvas.style.marginTop; var oldMarginBottom = canvas.style.marginBottom; var oldDocumentBodyMargin = document.body.style.margin; var oldDocumentOverflow = document.documentElement.style.overflow; // Chrome, Firefox var oldDocumentScroll = document.body.scroll; // IE var oldImageRendering = canvas.style.imageRendering; function restoreOldStyle() { var fullscreenElement = document.fullscreenElement || document.webkitFullscreenElement || document.msFullscreenElement ; if (!fullscreenElement) { document.removeEventListener('fullscreenchange', restoreOldStyle); // Unprefixed Fullscreen API shipped in Chromium 71 (https://bugs.chromium.org/p/chromium/issues/detail?id=383813) // As of Safari 13.0.3 on macOS Catalina 10.15.1 still ships with prefixed webkitfullscreenchange. TODO: revisit this check once Safari ships unprefixed version. document.removeEventListener('webkitfullscreenchange', restoreOldStyle); setCanvasElementSize(canvas, oldWidth, oldHeight); canvas.style.width = oldCssWidth; canvas.style.height = oldCssHeight; canvas.style.backgroundColor = oldBackgroundColor; // Chrome // IE11 hack: assigning 'undefined' or an empty string to document.body.style.backgroundColor has no effect, so first assign back the default color // before setting the undefined value. Setting undefined value is also important, or otherwise we would later treat that as something that the user // had explicitly set so subsequent fullscreen transitions would not set background color properly. if (!oldDocumentBackgroundColor) document.body.style.backgroundColor = 'white'; document.body.style.backgroundColor = oldDocumentBackgroundColor; // IE11 canvas.style.paddingLeft = oldPaddingLeft; // Chrome, FF, Safari canvas.style.paddingRight = oldPaddingRight; canvas.style.paddingTop = oldPaddingTop; canvas.style.paddingBottom = oldPaddingBottom; canvas.style.marginLeft = oldMarginLeft; // IE11 canvas.style.marginRight = oldMarginRight; canvas.style.marginTop = oldMarginTop; canvas.style.marginBottom = oldMarginBottom; document.body.style.margin = oldDocumentBodyMargin; document.documentElement.style.overflow = oldDocumentOverflow; // Chrome, Firefox document.body.scroll = oldDocumentScroll; // IE canvas.style.imageRendering = oldImageRendering; if (canvas.GLctxObject) canvas.GLctxObject.GLctx.viewport(0, 0, oldWidth, oldHeight); if (currentFullscreenStrategy.canvasResizedCallback) { wasmTable.get(currentFullscreenStrategy.canvasResizedCallback)(37, 0, currentFullscreenStrategy.canvasResizedCallbackUserData); } } } document.addEventListener('fullscreenchange', restoreOldStyle); // Unprefixed Fullscreen API shipped in Chromium 71 (https://bugs.chromium.org/p/chromium/issues/detail?id=383813) // As of Safari 13.0.3 on macOS Catalina 10.15.1 still ships with prefixed webkitfullscreenchange. TODO: revisit this check once Safari ships unprefixed version. document.addEventListener('webkitfullscreenchange', restoreOldStyle); return restoreOldStyle; } function setLetterbox(element, topBottom, leftRight) { // Cannot use margin to specify letterboxes in FF or Chrome, since those ignore margins in fullscreen mode. element.style.paddingLeft = element.style.paddingRight = leftRight + 'px'; element.style.paddingTop = element.style.paddingBottom = topBottom + 'px'; } function getBoundingClientRect(e) { return specialHTMLTargets.indexOf(e) < 0 ? e.getBoundingClientRect() : {'left':0,'top':0}; } function _JSEvents_resizeCanvasForFullscreen(target, strategy) { var restoreOldStyle = registerRestoreOldStyle(target); var cssWidth = strategy.softFullscreen ? innerWidth : screen.width; var cssHeight = strategy.softFullscreen ? innerHeight : screen.height; var rect = getBoundingClientRect(target); var windowedCssWidth = rect.width; var windowedCssHeight = rect.height; var canvasSize = getCanvasElementSize(target); var windowedRttWidth = canvasSize[0]; var windowedRttHeight = canvasSize[1]; if (strategy.scaleMode == 3) { setLetterbox(target, (cssHeight - windowedCssHeight) / 2, (cssWidth - windowedCssWidth) / 2); cssWidth = windowedCssWidth; cssHeight = windowedCssHeight; } else if (strategy.scaleMode == 2) { if (cssWidth*windowedRttHeight < windowedRttWidth*cssHeight) { var desiredCssHeight = windowedRttHeight * cssWidth / windowedRttWidth; setLetterbox(target, (cssHeight - desiredCssHeight) / 2, 0); cssHeight = desiredCssHeight; } else { var desiredCssWidth = windowedRttWidth * cssHeight / windowedRttHeight; setLetterbox(target, 0, (cssWidth - desiredCssWidth) / 2); cssWidth = desiredCssWidth; } } // If we are adding padding, must choose a background color or otherwise Chrome will give the // padding a default white color. Do it only if user has not customized their own background color. if (!target.style.backgroundColor) target.style.backgroundColor = 'black'; // IE11 does the same, but requires the color to be set in the document body. if (!document.body.style.backgroundColor) document.body.style.backgroundColor = 'black'; // IE11 // Firefox always shows black letterboxes independent of style color. target.style.width = cssWidth + 'px'; target.style.height = cssHeight + 'px'; if (strategy.filteringMode == 1) { target.style.imageRendering = 'optimizeSpeed'; target.style.imageRendering = '-moz-crisp-edges'; target.style.imageRendering = '-o-crisp-edges'; target.style.imageRendering = '-webkit-optimize-contrast'; target.style.imageRendering = 'optimize-contrast'; target.style.imageRendering = 'crisp-edges'; target.style.imageRendering = 'pixelated'; } var dpiScale = (strategy.canvasResolutionScaleMode == 2) ? devicePixelRatio : 1; if (strategy.canvasResolutionScaleMode != 0) { var newWidth = (cssWidth * dpiScale)|0; var newHeight = (cssHeight * dpiScale)|0; setCanvasElementSize(target, newWidth, newHeight); if (target.GLctxObject) target.GLctxObject.GLctx.viewport(0, 0, newWidth, newHeight); } return restoreOldStyle; } function _JSEvents_requestFullscreen(target, strategy) { // EMSCRIPTEN_FULLSCREEN_SCALE_DEFAULT + EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_NONE is a mode where no extra logic is performed to the DOM elements. if (strategy.scaleMode != 0 || strategy.canvasResolutionScaleMode != 0) { _JSEvents_resizeCanvasForFullscreen(target, strategy); } if (target.requestFullscreen) { target.requestFullscreen(); } else if (target.webkitRequestFullscreen) { target.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT); } else { return JSEvents.fullscreenEnabled() ? -3 : -1; } currentFullscreenStrategy = strategy; if (strategy.canvasResizedCallback) { wasmTable.get(strategy.canvasResizedCallback)(37, 0, strategy.canvasResizedCallbackUserData); } return 0; } function _emscripten_exit_fullscreen() { if (!JSEvents.fullscreenEnabled()) return -1; // Make sure no queued up calls will fire after this. JSEvents.removeDeferredCalls(_JSEvents_requestFullscreen); var d = specialHTMLTargets[1]; if (d.exitFullscreen) { d.fullscreenElement && d.exitFullscreen(); } else if (d.webkitExitFullscreen) { d.webkitFullscreenElement && d.webkitExitFullscreen(); } else { return -1; } return 0; } function requestPointerLock(target) { if (target.requestPointerLock) { target.requestPointerLock(); } else if (target.msRequestPointerLock) { target.msRequestPointerLock(); } else { // document.body is known to accept pointer lock, so use that to differentiate if the user passed a bad element, // or if the whole browser just doesn't support the feature. if (document.body.requestPointerLock || document.body.msRequestPointerLock ) { return -3; } else { return -1; } } return 0; } function _emscripten_exit_pointerlock() { // Make sure no queued up calls will fire after this. JSEvents.removeDeferredCalls(requestPointerLock); if (document.exitPointerLock) { document.exitPointerLock(); } else if (document.msExitPointerLock) { document.msExitPointerLock(); } else { return -1; } return 0; } function _emscripten_get_device_pixel_ratio() { return devicePixelRatio; } function _emscripten_get_element_css_size(target, width, height) { target = findEventTarget(target); if (!target) return -4; var rect = getBoundingClientRect(target); HEAPF64[((width)>>3)] = rect.width; HEAPF64[((height)>>3)] = rect.height; return 0; } function fillGamepadEventData(eventStruct, e) { HEAPF64[((eventStruct)>>3)] = e.timestamp; for (var i = 0; i < e.axes.length; ++i) { HEAPF64[(((eventStruct+i*8)+(16))>>3)] = e.axes[i]; } for (var i = 0; i < e.buttons.length; ++i) { if (typeof(e.buttons[i]) === 'object') { HEAPF64[(((eventStruct+i*8)+(528))>>3)] = e.buttons[i].value; } else { HEAPF64[(((eventStruct+i*8)+(528))>>3)] = e.buttons[i]; } } for (var i = 0; i < e.buttons.length; ++i) { if (typeof(e.buttons[i]) === 'object') { HEAP32[(((eventStruct+i*4)+(1040))>>2)] = e.buttons[i].pressed; } else { // Assigning a boolean to HEAP32, that's ok, but Closure would like to warn about it: /** @suppress {checkTypes} */ HEAP32[(((eventStruct+i*4)+(1040))>>2)] = e.buttons[i] == 1; } } HEAP32[(((eventStruct)+(1296))>>2)] = e.connected; HEAP32[(((eventStruct)+(1300))>>2)] = e.index; HEAP32[(((eventStruct)+(8))>>2)] = e.axes.length; HEAP32[(((eventStruct)+(12))>>2)] = e.buttons.length; stringToUTF8(e.id, eventStruct + 1304, 64); stringToUTF8(e.mapping, eventStruct + 1368, 64); } function _emscripten_get_gamepad_status(index, gamepadState) { // INVALID_PARAM is returned on a Gamepad index that never was there. if (index < 0 || index >= JSEvents.lastGamepadState.length) return -5; // NO_DATA is returned on a Gamepad index that was removed. // For previously disconnected gamepads there should be an empty slot (null/undefined/false) at the index. // This is because gamepads must keep their original position in the array. // For example, removing the first of two gamepads produces [null/undefined/false, gamepad]. if (!JSEvents.lastGamepadState[index]) return -7; fillGamepadEventData(gamepadState, JSEvents.lastGamepadState[index]); return 0; } function _emscripten_get_num_gamepads() { // N.B. Do not call emscripten_get_num_gamepads() unless having first called emscripten_sample_gamepad_data(), and that has returned EMSCRIPTEN_RESULT_SUCCESS. // Otherwise the following line will throw an exception. return JSEvents.lastGamepadState.length; } function _emscripten_glActiveTexture(x0) { GLctx['activeTexture'](x0) } function _emscripten_glAttachShader(program, shader) { GLctx.attachShader(GL.programs[program], GL.shaders[shader]); } function _emscripten_glBeginQuery(target, id) { GLctx['beginQuery'](target, GL.queries[id]); } function _emscripten_glBeginQueryEXT(target, id) { GLctx.disjointTimerQueryExt['beginQueryEXT'](target, GL.timerQueriesEXT[id]); } function _emscripten_glBeginTransformFeedback(x0) { GLctx['beginTransformFeedback'](x0) } function _emscripten_glBindAttribLocation(program, index, name) { GLctx.bindAttribLocation(GL.programs[program], index, UTF8ToString(name)); } function _emscripten_glBindBuffer(target, buffer) { if (target == 0x8892 /*GL_ARRAY_BUFFER*/) { GLctx.currentArrayBufferBinding = buffer; } else if (target == 0x8893 /*GL_ELEMENT_ARRAY_BUFFER*/) { GLctx.currentElementArrayBufferBinding = buffer; } if (target == 0x88EB /*GL_PIXEL_PACK_BUFFER*/) { // In WebGL 2 glReadPixels entry point, we need to use a different WebGL 2 API function call when a buffer is bound to // GL_PIXEL_PACK_BUFFER_BINDING point, so must keep track whether that binding point is non-null to know what is // the proper API function to call. GLctx.currentPixelPackBufferBinding = buffer; } else if (target == 0x88EC /*GL_PIXEL_UNPACK_BUFFER*/) { // In WebGL 2 gl(Compressed)Tex(Sub)Image[23]D entry points, we need to // use a different WebGL 2 API function call when a buffer is bound to // GL_PIXEL_UNPACK_BUFFER_BINDING point, so must keep track whether that // binding point is non-null to know what is the proper API function to // call. GLctx.currentPixelUnpackBufferBinding = buffer; } GLctx.bindBuffer(target, GL.buffers[buffer]); } function _emscripten_glBindBufferBase(target, index, buffer) { GLctx['bindBufferBase'](target, index, GL.buffers[buffer]); } function _emscripten_glBindBufferRange(target, index, buffer, offset, ptrsize) { GLctx['bindBufferRange'](target, index, GL.buffers[buffer], offset, ptrsize); } function _emscripten_glBindFramebuffer(target, framebuffer) { GLctx.bindFramebuffer(target, GL.framebuffers[framebuffer]); } function _emscripten_glBindRenderbuffer(target, renderbuffer) { GLctx.bindRenderbuffer(target, GL.renderbuffers[renderbuffer]); } function _emscripten_glBindSampler(unit, sampler) { GLctx['bindSampler'](unit, GL.samplers[sampler]); } function _emscripten_glBindTexture(target, texture) { GLctx.bindTexture(target, GL.textures[texture]); } function _emscripten_glBindTransformFeedback(target, id) { GLctx['bindTransformFeedback'](target, GL.transformFeedbacks[id]); } function _emscripten_glBindVertexArray(vao) { GLctx['bindVertexArray'](GL.vaos[vao]); var ibo = GLctx.getParameter(0x8895 /*ELEMENT_ARRAY_BUFFER_BINDING*/); GLctx.currentElementArrayBufferBinding = ibo ? (ibo.name | 0) : 0; } function _emscripten_glBindVertexArrayOES(vao) { GLctx['bindVertexArray'](GL.vaos[vao]); var ibo = GLctx.getParameter(0x8895 /*ELEMENT_ARRAY_BUFFER_BINDING*/); GLctx.currentElementArrayBufferBinding = ibo ? (ibo.name | 0) : 0; } function _emscripten_glBlendColor(x0, x1, x2, x3) { GLctx['blendColor'](x0, x1, x2, x3) } function _emscripten_glBlendEquation(x0) { GLctx['blendEquation'](x0) } function _emscripten_glBlendEquationSeparate(x0, x1) { GLctx['blendEquationSeparate'](x0, x1) } function _emscripten_glBlendFunc(x0, x1) { GLctx['blendFunc'](x0, x1) } function _emscripten_glBlendFuncSeparate(x0, x1, x2, x3) { GLctx['blendFuncSeparate'](x0, x1, x2, x3) } function _emscripten_glBlitFramebuffer(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9) { GLctx['blitFramebuffer'](x0, x1, x2, x3, x4, x5, x6, x7, x8, x9) } function _emscripten_glBufferData(target, size, data, usage) { if (GL.currentContext.version >= 2) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. if (data) { GLctx.bufferData(target, HEAPU8, usage, data, size); } else { GLctx.bufferData(target, size, usage); } } else { // N.b. here first form specifies a heap subarray, second form an integer size, so the ?: code here is polymorphic. It is advised to avoid // randomly mixing both uses in calling code, to avoid any potential JS engine JIT issues. GLctx.bufferData(target, data ? HEAPU8.subarray(data, data+size) : size, usage); } } function _emscripten_glBufferSubData(target, offset, size, data) { if (GL.currentContext.version >= 2) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. GLctx.bufferSubData(target, offset, HEAPU8, data, size); return; } GLctx.bufferSubData(target, offset, HEAPU8.subarray(data, data+size)); } function _emscripten_glCheckFramebufferStatus(x0) { return GLctx['checkFramebufferStatus'](x0) } function _emscripten_glClear(x0) { GLctx['clear'](x0) } function _emscripten_glClearBufferfi(x0, x1, x2, x3) { GLctx['clearBufferfi'](x0, x1, x2, x3) } function _emscripten_glClearBufferfv(buffer, drawbuffer, value) { GLctx['clearBufferfv'](buffer, drawbuffer, HEAPF32, value>>2); } function _emscripten_glClearBufferiv(buffer, drawbuffer, value) { GLctx['clearBufferiv'](buffer, drawbuffer, HEAP32, value>>2); } function _emscripten_glClearBufferuiv(buffer, drawbuffer, value) { GLctx['clearBufferuiv'](buffer, drawbuffer, HEAPU32, value>>2); } function _emscripten_glClearColor(x0, x1, x2, x3) { GLctx['clearColor'](x0, x1, x2, x3) } function _emscripten_glClearDepthf(x0) { GLctx['clearDepth'](x0) } function _emscripten_glClearStencil(x0) { GLctx['clearStencil'](x0) } function convertI32PairToI53(lo, hi) { return (lo >>> 0) + hi * 4294967296; } function _emscripten_glClientWaitSync(sync, flags, timeoutLo, timeoutHi) { // WebGL2 vs GLES3 differences: in GLES3, the timeout parameter is a uint64, where 0xFFFFFFFFFFFFFFFFULL means GL_TIMEOUT_IGNORED. // In JS, there's no 64-bit value types, so instead timeout is taken to be signed, and GL_TIMEOUT_IGNORED is given value -1. // Inherently the value accepted in the timeout is lossy, and can't take in arbitrary u64 bit pattern (but most likely doesn't matter) // See https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.15 return GLctx.clientWaitSync(GL.syncs[sync], flags, convertI32PairToI53(timeoutLo, timeoutHi)); } function _emscripten_glColorMask(red, green, blue, alpha) { GLctx.colorMask(!!red, !!green, !!blue, !!alpha); } function _emscripten_glCompileShader(shader) { GLctx.compileShader(GL.shaders[shader]); } function _emscripten_glCompressedTexImage2D(target, level, internalFormat, width, height, border, imageSize, data) { if (GL.currentContext.version >= 2) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. if (GLctx.currentPixelUnpackBufferBinding) { GLctx['compressedTexImage2D'](target, level, internalFormat, width, height, border, imageSize, data); } else { GLctx['compressedTexImage2D'](target, level, internalFormat, width, height, border, HEAPU8, data, imageSize); } return; } GLctx['compressedTexImage2D'](target, level, internalFormat, width, height, border, data ? HEAPU8.subarray((data), (data+imageSize)) : null); } function _emscripten_glCompressedTexImage3D(target, level, internalFormat, width, height, depth, border, imageSize, data) { if (GLctx.currentPixelUnpackBufferBinding) { GLctx['compressedTexImage3D'](target, level, internalFormat, width, height, depth, border, imageSize, data); } else { GLctx['compressedTexImage3D'](target, level, internalFormat, width, height, depth, border, HEAPU8, data, imageSize); } } function _emscripten_glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data) { if (GL.currentContext.version >= 2) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. if (GLctx.currentPixelUnpackBufferBinding) { GLctx['compressedTexSubImage2D'](target, level, xoffset, yoffset, width, height, format, imageSize, data); } else { GLctx['compressedTexSubImage2D'](target, level, xoffset, yoffset, width, height, format, HEAPU8, data, imageSize); } return; } GLctx['compressedTexSubImage2D'](target, level, xoffset, yoffset, width, height, format, data ? HEAPU8.subarray((data), (data+imageSize)) : null); } function _emscripten_glCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data) { if (GLctx.currentPixelUnpackBufferBinding) { GLctx['compressedTexSubImage3D'](target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data); } else { GLctx['compressedTexSubImage3D'](target, level, xoffset, yoffset, zoffset, width, height, depth, format, HEAPU8, data, imageSize); } } function _emscripten_glCopyBufferSubData(x0, x1, x2, x3, x4) { GLctx['copyBufferSubData'](x0, x1, x2, x3, x4) } function _emscripten_glCopyTexImage2D(x0, x1, x2, x3, x4, x5, x6, x7) { GLctx['copyTexImage2D'](x0, x1, x2, x3, x4, x5, x6, x7) } function _emscripten_glCopyTexSubImage2D(x0, x1, x2, x3, x4, x5, x6, x7) { GLctx['copyTexSubImage2D'](x0, x1, x2, x3, x4, x5, x6, x7) } function _emscripten_glCopyTexSubImage3D(x0, x1, x2, x3, x4, x5, x6, x7, x8) { GLctx['copyTexSubImage3D'](x0, x1, x2, x3, x4, x5, x6, x7, x8) } function _emscripten_glCreateProgram() { var id = GL.getNewId(GL.programs); var program = GLctx.createProgram(); program.name = id; GL.programs[id] = program; return id; } function _emscripten_glCreateShader(shaderType) { var id = GL.getNewId(GL.shaders); GL.shaders[id] = GLctx.createShader(shaderType); return id; } function _emscripten_glCullFace(x0) { GLctx['cullFace'](x0) } function _emscripten_glDeleteBuffers(n, buffers) { for (var i = 0; i < n; i++) { var id = HEAP32[(((buffers)+(i*4))>>2)]; var buffer = GL.buffers[id]; // From spec: "glDeleteBuffers silently ignores 0's and names that do not // correspond to existing buffer objects." if (!buffer) continue; GLctx.deleteBuffer(buffer); buffer.name = 0; GL.buffers[id] = null; if (id == GLctx.currentArrayBufferBinding) GLctx.currentArrayBufferBinding = 0; if (id == GLctx.currentElementArrayBufferBinding) GLctx.currentElementArrayBufferBinding = 0; if (id == GLctx.currentPixelPackBufferBinding) GLctx.currentPixelPackBufferBinding = 0; if (id == GLctx.currentPixelUnpackBufferBinding) GLctx.currentPixelUnpackBufferBinding = 0; } } function _emscripten_glDeleteFramebuffers(n, framebuffers) { for (var i = 0; i < n; ++i) { var id = HEAP32[(((framebuffers)+(i*4))>>2)]; var framebuffer = GL.framebuffers[id]; if (!framebuffer) continue; // GL spec: "glDeleteFramebuffers silently ignores 0s and names that do not correspond to existing framebuffer objects". GLctx.deleteFramebuffer(framebuffer); framebuffer.name = 0; GL.framebuffers[id] = null; } } function _emscripten_glDeleteProgram(id) { if (!id) return; var program = GL.programs[id]; if (!program) { // glDeleteProgram actually signals an error when deleting a nonexisting object, unlike some other GL delete functions. GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } GLctx.deleteProgram(program); program.name = 0; GL.programs[id] = null; GL.programInfos[id] = null; } function _emscripten_glDeleteQueries(n, ids) { for (var i = 0; i < n; i++) { var id = HEAP32[(((ids)+(i*4))>>2)]; var query = GL.queries[id]; if (!query) continue; // GL spec: "unused names in ids are ignored, as is the name zero." GLctx['deleteQuery'](query); GL.queries[id] = null; } } function _emscripten_glDeleteQueriesEXT(n, ids) { for (var i = 0; i < n; i++) { var id = HEAP32[(((ids)+(i*4))>>2)]; var query = GL.timerQueriesEXT[id]; if (!query) continue; // GL spec: "unused names in ids are ignored, as is the name zero." GLctx.disjointTimerQueryExt['deleteQueryEXT'](query); GL.timerQueriesEXT[id] = null; } } function _emscripten_glDeleteRenderbuffers(n, renderbuffers) { for (var i = 0; i < n; i++) { var id = HEAP32[(((renderbuffers)+(i*4))>>2)]; var renderbuffer = GL.renderbuffers[id]; if (!renderbuffer) continue; // GL spec: "glDeleteRenderbuffers silently ignores 0s and names that do not correspond to existing renderbuffer objects". GLctx.deleteRenderbuffer(renderbuffer); renderbuffer.name = 0; GL.renderbuffers[id] = null; } } function _emscripten_glDeleteSamplers(n, samplers) { for (var i = 0; i < n; i++) { var id = HEAP32[(((samplers)+(i*4))>>2)]; var sampler = GL.samplers[id]; if (!sampler) continue; GLctx['deleteSampler'](sampler); sampler.name = 0; GL.samplers[id] = null; } } function _emscripten_glDeleteShader(id) { if (!id) return; var shader = GL.shaders[id]; if (!shader) { // glDeleteShader actually signals an error when deleting a nonexisting object, unlike some other GL delete functions. GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } GLctx.deleteShader(shader); GL.shaders[id] = null; } function _emscripten_glDeleteSync(id) { if (!id) return; var sync = GL.syncs[id]; if (!sync) { // glDeleteSync signals an error when deleting a nonexisting object, unlike some other GL delete functions. GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } GLctx.deleteSync(sync); sync.name = 0; GL.syncs[id] = null; } function _emscripten_glDeleteTextures(n, textures) { for (var i = 0; i < n; i++) { var id = HEAP32[(((textures)+(i*4))>>2)]; var texture = GL.textures[id]; if (!texture) continue; // GL spec: "glDeleteTextures silently ignores 0s and names that do not correspond to existing textures". GLctx.deleteTexture(texture); texture.name = 0; GL.textures[id] = null; } } function _emscripten_glDeleteTransformFeedbacks(n, ids) { for (var i = 0; i < n; i++) { var id = HEAP32[(((ids)+(i*4))>>2)]; var transformFeedback = GL.transformFeedbacks[id]; if (!transformFeedback) continue; // GL spec: "unused names in ids are ignored, as is the name zero." GLctx['deleteTransformFeedback'](transformFeedback); transformFeedback.name = 0; GL.transformFeedbacks[id] = null; } } function _emscripten_glDeleteVertexArrays(n, vaos) { for (var i = 0; i < n; i++) { var id = HEAP32[(((vaos)+(i*4))>>2)]; GLctx['deleteVertexArray'](GL.vaos[id]); GL.vaos[id] = null; } } function _emscripten_glDeleteVertexArraysOES(n, vaos) { for (var i = 0; i < n; i++) { var id = HEAP32[(((vaos)+(i*4))>>2)]; GLctx['deleteVertexArray'](GL.vaos[id]); GL.vaos[id] = null; } } function _emscripten_glDepthFunc(x0) { GLctx['depthFunc'](x0) } function _emscripten_glDepthMask(flag) { GLctx.depthMask(!!flag); } function _emscripten_glDepthRangef(x0, x1) { GLctx['depthRange'](x0, x1) } function _emscripten_glDetachShader(program, shader) { GLctx.detachShader(GL.programs[program], GL.shaders[shader]); } function _emscripten_glDisable(x0) { GLctx['disable'](x0) } function _emscripten_glDisableVertexAttribArray(index) { var cb = GL.currentContext.clientBuffers[index]; cb.enabled = false; GLctx.disableVertexAttribArray(index); } function _emscripten_glDrawArrays(mode, first, count) { // bind any client-side buffers GL.preDrawHandleClientVertexAttribBindings(first + count); GLctx.drawArrays(mode, first, count); GL.postDrawHandleClientVertexAttribBindings(); } function _emscripten_glDrawArraysInstanced(mode, first, count, primcount) { GLctx['drawArraysInstanced'](mode, first, count, primcount); } function _emscripten_glDrawArraysInstancedANGLE(mode, first, count, primcount) { GLctx['drawArraysInstanced'](mode, first, count, primcount); } function _emscripten_glDrawArraysInstancedARB(mode, first, count, primcount) { GLctx['drawArraysInstanced'](mode, first, count, primcount); } function _emscripten_glDrawArraysInstancedEXT(mode, first, count, primcount) { GLctx['drawArraysInstanced'](mode, first, count, primcount); } function _emscripten_glDrawArraysInstancedNV(mode, first, count, primcount) { GLctx['drawArraysInstanced'](mode, first, count, primcount); } var tempFixedLengthArray=[]; function _emscripten_glDrawBuffers(n, bufs) { var bufArray = tempFixedLengthArray[n]; for (var i = 0; i < n; i++) { bufArray[i] = HEAP32[(((bufs)+(i*4))>>2)]; } GLctx['drawBuffers'](bufArray); } function _emscripten_glDrawBuffersEXT(n, bufs) { var bufArray = tempFixedLengthArray[n]; for (var i = 0; i < n; i++) { bufArray[i] = HEAP32[(((bufs)+(i*4))>>2)]; } GLctx['drawBuffers'](bufArray); } function _emscripten_glDrawBuffersWEBGL(n, bufs) { var bufArray = tempFixedLengthArray[n]; for (var i = 0; i < n; i++) { bufArray[i] = HEAP32[(((bufs)+(i*4))>>2)]; } GLctx['drawBuffers'](bufArray); } function _emscripten_glDrawElements(mode, count, type, indices) { var buf; if (!GLctx.currentElementArrayBufferBinding) { var size = GL.calcBufLength(1, type, 0, count); buf = GL.getTempIndexBuffer(size); GLctx.bindBuffer(0x8893 /*GL_ELEMENT_ARRAY_BUFFER*/, buf); GLctx.bufferSubData(0x8893 /*GL_ELEMENT_ARRAY_BUFFER*/, 0, HEAPU8.subarray(indices, indices + size)); // the index is now 0 indices = 0; } // bind any client-side buffers GL.preDrawHandleClientVertexAttribBindings(count); GLctx.drawElements(mode, count, type, indices); GL.postDrawHandleClientVertexAttribBindings(count); if (!GLctx.currentElementArrayBufferBinding) { GLctx.bindBuffer(0x8893 /*GL_ELEMENT_ARRAY_BUFFER*/, null); } } function _emscripten_glDrawElementsInstanced(mode, count, type, indices, primcount) { GLctx['drawElementsInstanced'](mode, count, type, indices, primcount); } function _emscripten_glDrawElementsInstancedANGLE(mode, count, type, indices, primcount) { GLctx['drawElementsInstanced'](mode, count, type, indices, primcount); } function _emscripten_glDrawElementsInstancedARB(mode, count, type, indices, primcount) { GLctx['drawElementsInstanced'](mode, count, type, indices, primcount); } function _emscripten_glDrawElementsInstancedEXT(mode, count, type, indices, primcount) { GLctx['drawElementsInstanced'](mode, count, type, indices, primcount); } function _emscripten_glDrawElementsInstancedNV(mode, count, type, indices, primcount) { GLctx['drawElementsInstanced'](mode, count, type, indices, primcount); } function _glDrawElements(mode, count, type, indices) { var buf; if (!GLctx.currentElementArrayBufferBinding) { var size = GL.calcBufLength(1, type, 0, count); buf = GL.getTempIndexBuffer(size); GLctx.bindBuffer(0x8893 /*GL_ELEMENT_ARRAY_BUFFER*/, buf); GLctx.bufferSubData(0x8893 /*GL_ELEMENT_ARRAY_BUFFER*/, 0, HEAPU8.subarray(indices, indices + size)); // the index is now 0 indices = 0; } // bind any client-side buffers GL.preDrawHandleClientVertexAttribBindings(count); GLctx.drawElements(mode, count, type, indices); GL.postDrawHandleClientVertexAttribBindings(count); if (!GLctx.currentElementArrayBufferBinding) { GLctx.bindBuffer(0x8893 /*GL_ELEMENT_ARRAY_BUFFER*/, null); } } function _emscripten_glDrawRangeElements(mode, start, end, count, type, indices) { // TODO: This should be a trivial pass-though function registered at the bottom of this page as // glFuncs[6][1] += ' drawRangeElements'; // but due to https://bugzilla.mozilla.org/show_bug.cgi?id=1202427, // we work around by ignoring the range. _glDrawElements(mode, count, type, indices); } function _emscripten_glEnable(x0) { GLctx['enable'](x0) } function _emscripten_glEnableVertexAttribArray(index) { var cb = GL.currentContext.clientBuffers[index]; cb.enabled = true; GLctx.enableVertexAttribArray(index); } function _emscripten_glEndQuery(x0) { GLctx['endQuery'](x0) } function _emscripten_glEndQueryEXT(target) { GLctx.disjointTimerQueryExt['endQueryEXT'](target); } function _emscripten_glEndTransformFeedback() { GLctx['endTransformFeedback']() } function _emscripten_glFenceSync(condition, flags) { var sync = GLctx.fenceSync(condition, flags); if (sync) { var id = GL.getNewId(GL.syncs); sync.name = id; GL.syncs[id] = sync; return id; } else { return 0; // Failed to create a sync object } } function _emscripten_glFinish() { GLctx['finish']() } function _emscripten_glFlush() { GLctx['flush']() } function emscriptenWebGLGetBufferBinding(target) { switch (target) { case 0x8892 /*GL_ARRAY_BUFFER*/: target = 0x8894 /*GL_ARRAY_BUFFER_BINDING*/; break; case 0x8893 /*GL_ELEMENT_ARRAY_BUFFER*/: target = 0x8895 /*GL_ELEMENT_ARRAY_BUFFER_BINDING*/; break; case 0x88EB /*GL_PIXEL_PACK_BUFFER*/: target = 0x88ED /*GL_PIXEL_PACK_BUFFER_BINDING*/; break; case 0x88EC /*GL_PIXEL_UNPACK_BUFFER*/: target = 0x88EF /*GL_PIXEL_UNPACK_BUFFER_BINDING*/; break; case 0x8C8E /*GL_TRANSFORM_FEEDBACK_BUFFER*/: target = 0x8C8F /*GL_TRANSFORM_FEEDBACK_BUFFER_BINDING*/; break; case 0x8F36 /*GL_COPY_READ_BUFFER*/: target = 0x8F36 /*GL_COPY_READ_BUFFER_BINDING*/; break; case 0x8F37 /*GL_COPY_WRITE_BUFFER*/: target = 0x8F37 /*GL_COPY_WRITE_BUFFER_BINDING*/; break; case 0x8A11 /*GL_UNIFORM_BUFFER*/: target = 0x8A28 /*GL_UNIFORM_BUFFER_BINDING*/; break; // In default case, fall through and assume passed one of the _BINDING enums directly. } var buffer = GLctx.getParameter(target); if (buffer) return buffer.name|0; else return 0; } function emscriptenWebGLValidateMapBufferTarget(target) { switch (target) { case 0x8892: // GL_ARRAY_BUFFER case 0x8893: // GL_ELEMENT_ARRAY_BUFFER case 0x8F36: // GL_COPY_READ_BUFFER case 0x8F37: // GL_COPY_WRITE_BUFFER case 0x88EB: // GL_PIXEL_PACK_BUFFER case 0x88EC: // GL_PIXEL_UNPACK_BUFFER case 0x8C2A: // GL_TEXTURE_BUFFER case 0x8C8E: // GL_TRANSFORM_FEEDBACK_BUFFER case 0x8A11: // GL_UNIFORM_BUFFER return true; default: return false; } } function _emscripten_glFlushMappedBufferRange(target, offset, length) { if (!emscriptenWebGLValidateMapBufferTarget(target)) { GL.recordError(0x500/*GL_INVALID_ENUM*/); err('GL_INVALID_ENUM in glFlushMappedBufferRange'); return; } var mapping = GL.mappedBuffers[emscriptenWebGLGetBufferBinding(target)]; if (!mapping) { GL.recordError(0x502 /* GL_INVALID_OPERATION */); err('buffer was never mapped in glFlushMappedBufferRange'); return; } if (!(mapping.access & 0x10)) { GL.recordError(0x502 /* GL_INVALID_OPERATION */); err('buffer was not mapped with GL_MAP_FLUSH_EXPLICIT_BIT in glFlushMappedBufferRange'); return; } if (offset < 0 || length < 0 || offset + length > mapping.length) { GL.recordError(0x501 /* GL_INVALID_VALUE */); err('invalid range in glFlushMappedBufferRange'); return; } GLctx.bufferSubData( target, mapping.offset, HEAPU8.subarray(mapping.mem + offset, mapping.mem + offset + length)); } function _emscripten_glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer) { GLctx.framebufferRenderbuffer(target, attachment, renderbuffertarget, GL.renderbuffers[renderbuffer]); } function _emscripten_glFramebufferTexture2D(target, attachment, textarget, texture, level) { GLctx.framebufferTexture2D(target, attachment, textarget, GL.textures[texture], level); } function _emscripten_glFramebufferTextureLayer(target, attachment, texture, level, layer) { GLctx.framebufferTextureLayer(target, attachment, GL.textures[texture], level, layer); } function _emscripten_glFrontFace(x0) { GLctx['frontFace'](x0) } function __glGenObject(n, buffers, createFunction, objectTable ) { for (var i = 0; i < n; i++) { var buffer = GLctx[createFunction](); var id = buffer && GL.getNewId(objectTable); if (buffer) { buffer.name = id; objectTable[id] = buffer; } else { GL.recordError(0x502 /* GL_INVALID_OPERATION */); } HEAP32[(((buffers)+(i*4))>>2)] = id; } } function _emscripten_glGenBuffers(n, buffers) { __glGenObject(n, buffers, 'createBuffer', GL.buffers ); } function _emscripten_glGenFramebuffers(n, ids) { __glGenObject(n, ids, 'createFramebuffer', GL.framebuffers ); } function _emscripten_glGenQueries(n, ids) { __glGenObject(n, ids, 'createQuery', GL.queries ); } function _emscripten_glGenQueriesEXT(n, ids) { for (var i = 0; i < n; i++) { var query = GLctx.disjointTimerQueryExt['createQueryEXT'](); if (!query) { GL.recordError(0x502 /* GL_INVALID_OPERATION */); while (i < n) HEAP32[(((ids)+(i++*4))>>2)] = 0; return; } var id = GL.getNewId(GL.timerQueriesEXT); query.name = id; GL.timerQueriesEXT[id] = query; HEAP32[(((ids)+(i*4))>>2)] = id; } } function _emscripten_glGenRenderbuffers(n, renderbuffers) { __glGenObject(n, renderbuffers, 'createRenderbuffer', GL.renderbuffers ); } function _emscripten_glGenSamplers(n, samplers) { __glGenObject(n, samplers, 'createSampler', GL.samplers ); } function _emscripten_glGenTextures(n, textures) { __glGenObject(n, textures, 'createTexture', GL.textures ); } function _emscripten_glGenTransformFeedbacks(n, ids) { __glGenObject(n, ids, 'createTransformFeedback', GL.transformFeedbacks ); } function _emscripten_glGenVertexArrays(n, arrays) { __glGenObject(n, arrays, 'createVertexArray', GL.vaos ); } function _emscripten_glGenVertexArraysOES(n, arrays) { __glGenObject(n, arrays, 'createVertexArray', GL.vaos ); } function _emscripten_glGenerateMipmap(x0) { GLctx['generateMipmap'](x0) } function __glGetActiveAttribOrUniform(funcName, program, index, bufSize, length, size, type, name) { program = GL.programs[program]; var info = GLctx[funcName](program, index); if (info) { // If an error occurs, nothing will be written to length, size and type and name. var numBytesWrittenExclNull = name && stringToUTF8(info.name, name, bufSize); if (length) HEAP32[((length)>>2)] = numBytesWrittenExclNull; if (size) HEAP32[((size)>>2)] = info.size; if (type) HEAP32[((type)>>2)] = info.type; } } function _emscripten_glGetActiveAttrib(program, index, bufSize, length, size, type, name) { __glGetActiveAttribOrUniform('getActiveAttrib', program, index, bufSize, length, size, type, name); } function _emscripten_glGetActiveUniform(program, index, bufSize, length, size, type, name) { __glGetActiveAttribOrUniform('getActiveUniform', program, index, bufSize, length, size, type, name); } function _emscripten_glGetActiveUniformBlockName(program, uniformBlockIndex, bufSize, length, uniformBlockName) { program = GL.programs[program]; var result = GLctx['getActiveUniformBlockName'](program, uniformBlockIndex); if (!result) return; // If an error occurs, nothing will be written to uniformBlockName or length. if (uniformBlockName && bufSize > 0) { var numBytesWrittenExclNull = stringToUTF8(result, uniformBlockName, bufSize); if (length) HEAP32[((length)>>2)] = numBytesWrittenExclNull; } else { if (length) HEAP32[((length)>>2)] = 0; } } function _emscripten_glGetActiveUniformBlockiv(program, uniformBlockIndex, pname, params) { if (!params) { // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense // if params == null, issue a GL error to notify user about it. GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } program = GL.programs[program]; if (pname == 0x8A41 /* GL_UNIFORM_BLOCK_NAME_LENGTH */) { var name = GLctx['getActiveUniformBlockName'](program, uniformBlockIndex); HEAP32[((params)>>2)] = name.length+1; return; } var result = GLctx['getActiveUniformBlockParameter'](program, uniformBlockIndex, pname); if (result === null) return; // If an error occurs, nothing should be written to params. if (pname == 0x8A43 /*GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES*/) { for (var i = 0; i < result.length; i++) { HEAP32[(((params)+(i*4))>>2)] = result[i]; } } else { HEAP32[((params)>>2)] = result; } } function _emscripten_glGetActiveUniformsiv(program, uniformCount, uniformIndices, pname, params) { if (!params) { // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense // if params == null, issue a GL error to notify user about it. GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } if (uniformCount > 0 && uniformIndices == 0) { GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } program = GL.programs[program]; var ids = []; for (var i = 0; i < uniformCount; i++) { ids.push(HEAP32[(((uniformIndices)+(i*4))>>2)]); } var result = GLctx['getActiveUniforms'](program, ids, pname); if (!result) return; // GL spec: If an error is generated, nothing is written out to params. var len = result.length; for (var i = 0; i < len; i++) { HEAP32[(((params)+(i*4))>>2)] = result[i]; } } function _emscripten_glGetAttachedShaders(program, maxCount, count, shaders) { var result = GLctx.getAttachedShaders(GL.programs[program]); var len = result.length; if (len > maxCount) { len = maxCount; } HEAP32[((count)>>2)] = len; for (var i = 0; i < len; ++i) { var id = GL.shaders.indexOf(result[i]); HEAP32[(((shaders)+(i*4))>>2)] = id; } } function _emscripten_glGetAttribLocation(program, name) { return GLctx.getAttribLocation(GL.programs[program], UTF8ToString(name)); } function writeI53ToI64(ptr, num) { HEAPU32[ptr>>2] = num; HEAPU32[ptr+4>>2] = (num - HEAPU32[ptr>>2])/4294967296; } function emscriptenWebGLGet(name_, p, type) { // Guard against user passing a null pointer. // Note that GLES2 spec does not say anything about how passing a null pointer should be treated. // Testing on desktop core GL 3, the application crashes on glGetIntegerv to a null pointer, but // better to report an error instead of doing anything random. if (!p) { GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } var ret = undefined; switch (name_) { // Handle a few trivial GLES values case 0x8DFA: // GL_SHADER_COMPILER ret = 1; break; case 0x8DF8: // GL_SHADER_BINARY_FORMATS if (type != 0 && type != 1) { GL.recordError(0x500); // GL_INVALID_ENUM } return; // Do not write anything to the out pointer, since no binary formats are supported. case 0x87FE: // GL_NUM_PROGRAM_BINARY_FORMATS case 0x8DF9: // GL_NUM_SHADER_BINARY_FORMATS ret = 0; break; case 0x86A2: // GL_NUM_COMPRESSED_TEXTURE_FORMATS // WebGL doesn't have GL_NUM_COMPRESSED_TEXTURE_FORMATS (it's obsolete since GL_COMPRESSED_TEXTURE_FORMATS returns a JS array that can be queried for length), // so implement it ourselves to allow C++ GLES2 code get the length. var formats = GLctx.getParameter(0x86A3 /*GL_COMPRESSED_TEXTURE_FORMATS*/); ret = formats ? formats.length : 0; break; case 0x821D: // GL_NUM_EXTENSIONS if (GL.currentContext.version < 2) { GL.recordError(0x502 /* GL_INVALID_OPERATION */); // Calling GLES3/WebGL2 function with a GLES2/WebGL1 context return; } // .getSupportedExtensions() can return null if context is lost, so coerce to empty array. var exts = GLctx.getSupportedExtensions() || []; ret = 2 * exts.length; // each extension is duplicated, first in unprefixed WebGL form, and then a second time with "GL_" prefix. break; case 0x821B: // GL_MAJOR_VERSION case 0x821C: // GL_MINOR_VERSION if (GL.currentContext.version < 2) { GL.recordError(0x500); // GL_INVALID_ENUM return; } ret = name_ == 0x821B ? 3 : 0; // return version 3.0 break; } if (ret === undefined) { var result = GLctx.getParameter(name_); switch (typeof(result)) { case "number": ret = result; break; case "boolean": ret = result ? 1 : 0; break; case "string": GL.recordError(0x500); // GL_INVALID_ENUM return; case "object": if (result === null) { // null is a valid result for some (e.g., which buffer is bound - perhaps nothing is bound), but otherwise // can mean an invalid name_, which we need to report as an error switch (name_) { case 0x8894: // ARRAY_BUFFER_BINDING case 0x8B8D: // CURRENT_PROGRAM case 0x8895: // ELEMENT_ARRAY_BUFFER_BINDING case 0x8CA6: // FRAMEBUFFER_BINDING or DRAW_FRAMEBUFFER_BINDING case 0x8CA7: // RENDERBUFFER_BINDING case 0x8069: // TEXTURE_BINDING_2D case 0x85B5: // WebGL 2 GL_VERTEX_ARRAY_BINDING, or WebGL 1 extension OES_vertex_array_object GL_VERTEX_ARRAY_BINDING_OES case 0x8F36: // COPY_READ_BUFFER_BINDING or COPY_READ_BUFFER case 0x8F37: // COPY_WRITE_BUFFER_BINDING or COPY_WRITE_BUFFER case 0x88ED: // PIXEL_PACK_BUFFER_BINDING case 0x88EF: // PIXEL_UNPACK_BUFFER_BINDING case 0x8CAA: // READ_FRAMEBUFFER_BINDING case 0x8919: // SAMPLER_BINDING case 0x8C1D: // TEXTURE_BINDING_2D_ARRAY case 0x806A: // TEXTURE_BINDING_3D case 0x8E25: // TRANSFORM_FEEDBACK_BINDING case 0x8C8F: // TRANSFORM_FEEDBACK_BUFFER_BINDING case 0x8A28: // UNIFORM_BUFFER_BINDING case 0x8514: { // TEXTURE_BINDING_CUBE_MAP ret = 0; break; } default: { GL.recordError(0x500); // GL_INVALID_ENUM return; } } } else if (result instanceof Float32Array || result instanceof Uint32Array || result instanceof Int32Array || result instanceof Array) { for (var i = 0; i < result.length; ++i) { switch (type) { case 0: HEAP32[(((p)+(i*4))>>2)] = result[i]; break; case 2: HEAPF32[(((p)+(i*4))>>2)] = result[i]; break; case 4: HEAP8[(((p)+(i))>>0)] = result[i] ? 1 : 0; break; } } return; } else { try { ret = result.name | 0; } catch(e) { GL.recordError(0x500); // GL_INVALID_ENUM err('GL_INVALID_ENUM in glGet' + type + 'v: Unknown object returned from WebGL getParameter(' + name_ + ')! (error: ' + e + ')'); return; } } break; default: GL.recordError(0x500); // GL_INVALID_ENUM err('GL_INVALID_ENUM in glGet' + type + 'v: Native code calling glGet' + type + 'v(' + name_ + ') and it returns ' + result + ' of type ' + typeof(result) + '!'); return; } } switch (type) { case 1: writeI53ToI64(p, ret); break; case 0: HEAP32[((p)>>2)] = ret; break; case 2: HEAPF32[((p)>>2)] = ret; break; case 4: HEAP8[((p)>>0)] = ret ? 1 : 0; break; } } function _emscripten_glGetBooleanv(name_, p) { emscriptenWebGLGet(name_, p, 4); } function _emscripten_glGetBufferParameteri64v(target, value, data) { if (!data) { // GLES2 specification does not specify how to behave if data is a null pointer. Since calling this function does not make sense // if data == null, issue a GL error to notify user about it. GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } writeI53ToI64(data, GLctx.getBufferParameter(target, value)); } function _emscripten_glGetBufferParameteriv(target, value, data) { if (!data) { // GLES2 specification does not specify how to behave if data is a null pointer. Since calling this function does not make sense // if data == null, issue a GL error to notify user about it. GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } HEAP32[((data)>>2)] = GLctx.getBufferParameter(target, value); } function _emscripten_glGetBufferPointerv(target, pname, params) { if (pname == 0x88BD/*GL_BUFFER_MAP_POINTER*/) { var ptr = 0; var mappedBuffer = GL.mappedBuffers[emscriptenWebGLGetBufferBinding(target)]; if (mappedBuffer) { ptr = mappedBuffer.mem; } HEAP32[((params)>>2)] = ptr; } else { GL.recordError(0x500/*GL_INVALID_ENUM*/); err('GL_INVALID_ENUM in glGetBufferPointerv'); } } function _emscripten_glGetError() { var error = GLctx.getError() || GL.lastError; GL.lastError = 0/*GL_NO_ERROR*/; return error; } function _emscripten_glGetFloatv(name_, p) { emscriptenWebGLGet(name_, p, 2); } function _emscripten_glGetFragDataLocation(program, name) { return GLctx['getFragDataLocation'](GL.programs[program], UTF8ToString(name)); } function _emscripten_glGetFramebufferAttachmentParameteriv(target, attachment, pname, params) { var result = GLctx.getFramebufferAttachmentParameter(target, attachment, pname); if (result instanceof WebGLRenderbuffer || result instanceof WebGLTexture) { result = result.name | 0; } HEAP32[((params)>>2)] = result; } function emscriptenWebGLGetIndexed(target, index, data, type) { if (!data) { // GLES2 specification does not specify how to behave if data is a null pointer. Since calling this function does not make sense // if data == null, issue a GL error to notify user about it. GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } var result = GLctx['getIndexedParameter'](target, index); var ret; switch (typeof result) { case 'boolean': ret = result ? 1 : 0; break; case 'number': ret = result; break; case 'object': if (result === null) { switch (target) { case 0x8C8F: // TRANSFORM_FEEDBACK_BUFFER_BINDING case 0x8A28: // UNIFORM_BUFFER_BINDING ret = 0; break; default: { GL.recordError(0x500); // GL_INVALID_ENUM return; } } } else if (result instanceof WebGLBuffer) { ret = result.name | 0; } else { GL.recordError(0x500); // GL_INVALID_ENUM return; } break; default: GL.recordError(0x500); // GL_INVALID_ENUM return; } switch (type) { case 1: writeI53ToI64(data, ret); break; case 0: HEAP32[((data)>>2)] = ret; break; case 2: HEAPF32[((data)>>2)] = ret; break; case 4: HEAP8[((data)>>0)] = ret ? 1 : 0; break; default: throw 'internal emscriptenWebGLGetIndexed() error, bad type: ' + type; } } function _emscripten_glGetInteger64i_v(target, index, data) { emscriptenWebGLGetIndexed(target, index, data, 1); } function _emscripten_glGetInteger64v(name_, p) { emscriptenWebGLGet(name_, p, 1); } function _emscripten_glGetIntegeri_v(target, index, data) { emscriptenWebGLGetIndexed(target, index, data, 0); } function _emscripten_glGetIntegerv(name_, p) { emscriptenWebGLGet(name_, p, 0); } function _emscripten_glGetInternalformativ(target, internalformat, pname, bufSize, params) { if (bufSize < 0) { GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } if (!params) { // GLES3 specification does not specify how to behave if values is a null pointer. Since calling this function does not make sense // if values == null, issue a GL error to notify user about it. GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } var ret = GLctx['getInternalformatParameter'](target, internalformat, pname); if (ret === null) return; for (var i = 0; i < ret.length && i < bufSize; ++i) { HEAP32[(((params)+(i))>>2)] = ret[i]; } } function _emscripten_glGetProgramBinary(program, bufSize, length, binaryFormat, binary) { GL.recordError(0x502/*GL_INVALID_OPERATION*/); } function _emscripten_glGetProgramInfoLog(program, maxLength, length, infoLog) { var log = GLctx.getProgramInfoLog(GL.programs[program]); if (log === null) log = '(unknown error)'; var numBytesWrittenExclNull = (maxLength > 0 && infoLog) ? stringToUTF8(log, infoLog, maxLength) : 0; if (length) HEAP32[((length)>>2)] = numBytesWrittenExclNull; } function _emscripten_glGetProgramiv(program, pname, p) { if (!p) { // GLES2 specification does not specify how to behave if p is a null pointer. Since calling this function does not make sense // if p == null, issue a GL error to notify user about it. GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } if (program >= GL.counter) { GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } var ptable = GL.programInfos[program]; if (!ptable) { GL.recordError(0x502 /* GL_INVALID_OPERATION */); return; } if (pname == 0x8B84) { // GL_INFO_LOG_LENGTH var log = GLctx.getProgramInfoLog(GL.programs[program]); if (log === null) log = '(unknown error)'; HEAP32[((p)>>2)] = log.length + 1; } else if (pname == 0x8B87 /* GL_ACTIVE_UNIFORM_MAX_LENGTH */) { HEAP32[((p)>>2)] = ptable.maxUniformLength; } else if (pname == 0x8B8A /* GL_ACTIVE_ATTRIBUTE_MAX_LENGTH */) { if (ptable.maxAttributeLength == -1) { program = GL.programs[program]; var numAttribs = GLctx.getProgramParameter(program, 0x8B89/*GL_ACTIVE_ATTRIBUTES*/); ptable.maxAttributeLength = 0; // Spec says if there are no active attribs, 0 must be returned. for (var i = 0; i < numAttribs; ++i) { var activeAttrib = GLctx.getActiveAttrib(program, i); ptable.maxAttributeLength = Math.max(ptable.maxAttributeLength, activeAttrib.name.length+1); } } HEAP32[((p)>>2)] = ptable.maxAttributeLength; } else if (pname == 0x8A35 /* GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH */) { if (ptable.maxUniformBlockNameLength == -1) { program = GL.programs[program]; var numBlocks = GLctx.getProgramParameter(program, 0x8A36/*GL_ACTIVE_UNIFORM_BLOCKS*/); ptable.maxUniformBlockNameLength = 0; for (var i = 0; i < numBlocks; ++i) { var activeBlockName = GLctx.getActiveUniformBlockName(program, i); ptable.maxUniformBlockNameLength = Math.max(ptable.maxUniformBlockNameLength, activeBlockName.length+1); } } HEAP32[((p)>>2)] = ptable.maxUniformBlockNameLength; } else { HEAP32[((p)>>2)] = GLctx.getProgramParameter(GL.programs[program], pname); } } function _emscripten_glGetQueryObjecti64vEXT(id, pname, params) { if (!params) { // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense // if p == null, issue a GL error to notify user about it. GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } var query = GL.timerQueriesEXT[id]; var param = GLctx.disjointTimerQueryExt['getQueryObjectEXT'](query, pname); var ret; if (typeof param == 'boolean') { ret = param ? 1 : 0; } else { ret = param; } writeI53ToI64(params, ret); } function _emscripten_glGetQueryObjectivEXT(id, pname, params) { if (!params) { // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense // if p == null, issue a GL error to notify user about it. GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } var query = GL.timerQueriesEXT[id]; var param = GLctx.disjointTimerQueryExt['getQueryObjectEXT'](query, pname); var ret; if (typeof param == 'boolean') { ret = param ? 1 : 0; } else { ret = param; } HEAP32[((params)>>2)] = ret; } function _emscripten_glGetQueryObjectui64vEXT(id, pname, params) { if (!params) { // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense // if p == null, issue a GL error to notify user about it. GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } var query = GL.timerQueriesEXT[id]; var param = GLctx.disjointTimerQueryExt['getQueryObjectEXT'](query, pname); var ret; if (typeof param == 'boolean') { ret = param ? 1 : 0; } else { ret = param; } writeI53ToI64(params, ret); } function _emscripten_glGetQueryObjectuiv(id, pname, params) { if (!params) { // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense // if p == null, issue a GL error to notify user about it. GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } var query = GL.queries[id]; var param = GLctx['getQueryParameter'](query, pname); var ret; if (typeof param == 'boolean') { ret = param ? 1 : 0; } else { ret = param; } HEAP32[((params)>>2)] = ret; } function _emscripten_glGetQueryObjectuivEXT(id, pname, params) { if (!params) { // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense // if p == null, issue a GL error to notify user about it. GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } var query = GL.timerQueriesEXT[id]; var param = GLctx.disjointTimerQueryExt['getQueryObjectEXT'](query, pname); var ret; if (typeof param == 'boolean') { ret = param ? 1 : 0; } else { ret = param; } HEAP32[((params)>>2)] = ret; } function _emscripten_glGetQueryiv(target, pname, params) { if (!params) { // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense // if p == null, issue a GL error to notify user about it. GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } HEAP32[((params)>>2)] = GLctx['getQuery'](target, pname); } function _emscripten_glGetQueryivEXT(target, pname, params) { if (!params) { // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense // if p == null, issue a GL error to notify user about it. GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } HEAP32[((params)>>2)] = GLctx.disjointTimerQueryExt['getQueryEXT'](target, pname); } function _emscripten_glGetRenderbufferParameteriv(target, pname, params) { if (!params) { // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense // if params == null, issue a GL error to notify user about it. GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } HEAP32[((params)>>2)] = GLctx.getRenderbufferParameter(target, pname); } function _emscripten_glGetSamplerParameterfv(sampler, pname, params) { if (!params) { // GLES3 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense // if p == null, issue a GL error to notify user about it. GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } HEAPF32[((params)>>2)] = GLctx['getSamplerParameter'](GL.samplers[sampler], pname); } function _emscripten_glGetSamplerParameteriv(sampler, pname, params) { if (!params) { // GLES3 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense // if p == null, issue a GL error to notify user about it. GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } HEAP32[((params)>>2)] = GLctx['getSamplerParameter'](GL.samplers[sampler], pname); } function _emscripten_glGetShaderInfoLog(shader, maxLength, length, infoLog) { var log = GLctx.getShaderInfoLog(GL.shaders[shader]); if (log === null) log = '(unknown error)'; var numBytesWrittenExclNull = (maxLength > 0 && infoLog) ? stringToUTF8(log, infoLog, maxLength) : 0; if (length) HEAP32[((length)>>2)] = numBytesWrittenExclNull; } function _emscripten_glGetShaderPrecisionFormat(shaderType, precisionType, range, precision) { var result = GLctx.getShaderPrecisionFormat(shaderType, precisionType); HEAP32[((range)>>2)] = result.rangeMin; HEAP32[(((range)+(4))>>2)] = result.rangeMax; HEAP32[((precision)>>2)] = result.precision; } function _emscripten_glGetShaderSource(shader, bufSize, length, source) { var result = GLctx.getShaderSource(GL.shaders[shader]); if (!result) return; // If an error occurs, nothing will be written to length or source. var numBytesWrittenExclNull = (bufSize > 0 && source) ? stringToUTF8(result, source, bufSize) : 0; if (length) HEAP32[((length)>>2)] = numBytesWrittenExclNull; } function _emscripten_glGetShaderiv(shader, pname, p) { if (!p) { // GLES2 specification does not specify how to behave if p is a null pointer. Since calling this function does not make sense // if p == null, issue a GL error to notify user about it. GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } if (pname == 0x8B84) { // GL_INFO_LOG_LENGTH var log = GLctx.getShaderInfoLog(GL.shaders[shader]); if (log === null) log = '(unknown error)'; // The GLES2 specification says that if the shader has an empty info log, // a value of 0 is returned. Otherwise the log has a null char appended. // (An empty string is falsey, so we can just check that instead of // looking at log.length.) var logLength = log ? log.length + 1 : 0; HEAP32[((p)>>2)] = logLength; } else if (pname == 0x8B88) { // GL_SHADER_SOURCE_LENGTH var source = GLctx.getShaderSource(GL.shaders[shader]); // source may be a null, or the empty string, both of which are falsey // values that we report a 0 length for. var sourceLength = source ? source.length + 1 : 0; HEAP32[((p)>>2)] = sourceLength; } else { HEAP32[((p)>>2)] = GLctx.getShaderParameter(GL.shaders[shader], pname); } } function stringToNewUTF8(jsString) { var length = lengthBytesUTF8(jsString)+1; var cString = _malloc(length); stringToUTF8(jsString, cString, length); return cString; } function _emscripten_glGetString(name_) { if (GL.stringCache[name_]) return GL.stringCache[name_]; var ret; switch (name_) { case 0x1F03 /* GL_EXTENSIONS */: var exts = GLctx.getSupportedExtensions() || []; // .getSupportedExtensions() can return null if context is lost, so coerce to empty array. exts = exts.concat(exts.map(function(e) { return "GL_" + e; })); ret = stringToNewUTF8(exts.join(' ')); break; case 0x1F00 /* GL_VENDOR */: case 0x1F01 /* GL_RENDERER */: case 0x9245 /* UNMASKED_VENDOR_WEBGL */: case 0x9246 /* UNMASKED_RENDERER_WEBGL */: var s = GLctx.getParameter(name_); if (!s) { GL.recordError(0x500/*GL_INVALID_ENUM*/); } ret = stringToNewUTF8(s); break; case 0x1F02 /* GL_VERSION */: var glVersion = GLctx.getParameter(0x1F02 /*GL_VERSION*/); // return GLES version string corresponding to the version of the WebGL context if (GL.currentContext.version >= 2) glVersion = 'OpenGL ES 3.0 (' + glVersion + ')'; else { glVersion = 'OpenGL ES 2.0 (' + glVersion + ')'; } ret = stringToNewUTF8(glVersion); break; case 0x8B8C /* GL_SHADING_LANGUAGE_VERSION */: var glslVersion = GLctx.getParameter(0x8B8C /*GL_SHADING_LANGUAGE_VERSION*/); // extract the version number 'N.M' from the string 'WebGL GLSL ES N.M ...' var ver_re = /^WebGL GLSL ES ([0-9]\.[0-9][0-9]?)(?:$| .*)/; var ver_num = glslVersion.match(ver_re); if (ver_num !== null) { if (ver_num[1].length == 3) ver_num[1] = ver_num[1] + '0'; // ensure minor version has 2 digits glslVersion = 'OpenGL ES GLSL ES ' + ver_num[1] + ' (' + glslVersion + ')'; } ret = stringToNewUTF8(glslVersion); break; default: GL.recordError(0x500/*GL_INVALID_ENUM*/); return 0; } GL.stringCache[name_] = ret; return ret; } function _emscripten_glGetStringi(name, index) { if (GL.currentContext.version < 2) { GL.recordError(0x502 /* GL_INVALID_OPERATION */); // Calling GLES3/WebGL2 function with a GLES2/WebGL1 context return 0; } var stringiCache = GL.stringiCache[name]; if (stringiCache) { if (index < 0 || index >= stringiCache.length) { GL.recordError(0x501/*GL_INVALID_VALUE*/); return 0; } return stringiCache[index]; } switch (name) { case 0x1F03 /* GL_EXTENSIONS */: var exts = GLctx.getSupportedExtensions() || []; // .getSupportedExtensions() can return null if context is lost, so coerce to empty array. exts = exts.concat(exts.map(function(e) { return "GL_" + e; })); exts = exts.map(function(e) { return stringToNewUTF8(e); }); stringiCache = GL.stringiCache[name] = exts; if (index < 0 || index >= stringiCache.length) { GL.recordError(0x501/*GL_INVALID_VALUE*/); return 0; } return stringiCache[index]; default: GL.recordError(0x500/*GL_INVALID_ENUM*/); return 0; } } function _emscripten_glGetSynciv(sync, pname, bufSize, length, values) { if (bufSize < 0) { // GLES3 specification does not specify how to behave if bufSize < 0, however in the spec wording for glGetInternalformativ, it does say that GL_INVALID_VALUE should be raised, // so raise GL_INVALID_VALUE here as well. GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } if (!values) { // GLES3 specification does not specify how to behave if values is a null pointer. Since calling this function does not make sense // if values == null, issue a GL error to notify user about it. GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } var ret = GLctx.getSyncParameter(GL.syncs[sync], pname); if (ret !== null) { HEAP32[((values)>>2)] = ret; if (length) HEAP32[((length)>>2)] = 1; // Report a single value outputted. } } function _emscripten_glGetTexParameterfv(target, pname, params) { if (!params) { // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense // if p == null, issue a GL error to notify user about it. GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } HEAPF32[((params)>>2)] = GLctx.getTexParameter(target, pname); } function _emscripten_glGetTexParameteriv(target, pname, params) { if (!params) { // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense // if p == null, issue a GL error to notify user about it. GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } HEAP32[((params)>>2)] = GLctx.getTexParameter(target, pname); } function _emscripten_glGetTransformFeedbackVarying(program, index, bufSize, length, size, type, name) { program = GL.programs[program]; var info = GLctx['getTransformFeedbackVarying'](program, index); if (!info) return; // If an error occurred, the return parameters length, size, type and name will be unmodified. if (name && bufSize > 0) { var numBytesWrittenExclNull = stringToUTF8(info.name, name, bufSize); if (length) HEAP32[((length)>>2)] = numBytesWrittenExclNull; } else { if (length) HEAP32[((length)>>2)] = 0; } if (size) HEAP32[((size)>>2)] = info.size; if (type) HEAP32[((type)>>2)] = info.type; } function _emscripten_glGetUniformBlockIndex(program, uniformBlockName) { return GLctx['getUniformBlockIndex'](GL.programs[program], UTF8ToString(uniformBlockName)); } function _emscripten_glGetUniformIndices(program, uniformCount, uniformNames, uniformIndices) { if (!uniformIndices) { // GLES2 specification does not specify how to behave if uniformIndices is a null pointer. Since calling this function does not make sense // if uniformIndices == null, issue a GL error to notify user about it. GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } if (uniformCount > 0 && (uniformNames == 0 || uniformIndices == 0)) { GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } program = GL.programs[program]; var names = []; for (var i = 0; i < uniformCount; i++) names.push(UTF8ToString(HEAP32[(((uniformNames)+(i*4))>>2)])); var result = GLctx['getUniformIndices'](program, names); if (!result) return; // GL spec: If an error is generated, nothing is written out to uniformIndices. var len = result.length; for (var i = 0; i < len; i++) { HEAP32[(((uniformIndices)+(i*4))>>2)] = result[i]; } } /** @suppress {checkTypes} */ function jstoi_q(str) { return parseInt(str); } function _emscripten_glGetUniformLocation(program, name) { name = UTF8ToString(name); var arrayIndex = 0; // If user passed an array accessor "[index]", parse the array index off the accessor. if (name[name.length - 1] == ']') { var leftBrace = name.lastIndexOf('['); arrayIndex = name[leftBrace+1] != ']' ? jstoi_q(name.slice(leftBrace + 1)) : 0; // "index]", parseInt will ignore the ']' at the end; but treat "foo[]" as "foo[0]" name = name.slice(0, leftBrace); } var uniformInfo = GL.programInfos[program] && GL.programInfos[program].uniforms[name]; // returns pair [ dimension_of_uniform_array, uniform_location ] if (uniformInfo && arrayIndex >= 0 && arrayIndex < uniformInfo[0]) { // Check if user asked for an out-of-bounds element, i.e. for 'vec4 colors[3];' user could ask for 'colors[10]' which should return -1. return uniformInfo[1] + arrayIndex; } else { return -1; } } /** @suppress{checkTypes} */ function emscriptenWebGLGetUniform(program, location, params, type) { if (!params) { // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense // if params == null, issue a GL error to notify user about it. GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } var data = GLctx.getUniform(GL.programs[program], GL.uniforms[location]); if (typeof data == 'number' || typeof data == 'boolean') { switch (type) { case 0: HEAP32[((params)>>2)] = data; break; case 2: HEAPF32[((params)>>2)] = data; break; } } else { for (var i = 0; i < data.length; i++) { switch (type) { case 0: HEAP32[(((params)+(i*4))>>2)] = data[i]; break; case 2: HEAPF32[(((params)+(i*4))>>2)] = data[i]; break; } } } } function _emscripten_glGetUniformfv(program, location, params) { emscriptenWebGLGetUniform(program, location, params, 2); } function _emscripten_glGetUniformiv(program, location, params) { emscriptenWebGLGetUniform(program, location, params, 0); } function _emscripten_glGetUniformuiv(program, location, params) { emscriptenWebGLGetUniform(program, location, params, 0); } /** @suppress{checkTypes} */ function emscriptenWebGLGetVertexAttrib(index, pname, params, type) { if (!params) { // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense // if params == null, issue a GL error to notify user about it. GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } if (GL.currentContext.clientBuffers[index].enabled) { err("glGetVertexAttrib*v on client-side array: not supported, bad data returned"); } var data = GLctx.getVertexAttrib(index, pname); if (pname == 0x889F/*VERTEX_ATTRIB_ARRAY_BUFFER_BINDING*/) { HEAP32[((params)>>2)] = data && data["name"]; } else if (typeof data == 'number' || typeof data == 'boolean') { switch (type) { case 0: HEAP32[((params)>>2)] = data; break; case 2: HEAPF32[((params)>>2)] = data; break; case 5: HEAP32[((params)>>2)] = Math.fround(data); break; } } else { for (var i = 0; i < data.length; i++) { switch (type) { case 0: HEAP32[(((params)+(i*4))>>2)] = data[i]; break; case 2: HEAPF32[(((params)+(i*4))>>2)] = data[i]; break; case 5: HEAP32[(((params)+(i*4))>>2)] = Math.fround(data[i]); break; } } } } function _emscripten_glGetVertexAttribIiv(index, pname, params) { // N.B. This function may only be called if the vertex attribute was specified using the function glVertexAttribI4iv(), // otherwise the results are undefined. (GLES3 spec 6.1.12) emscriptenWebGLGetVertexAttrib(index, pname, params, 0); } function _emscripten_glGetVertexAttribIuiv(index, pname, params) { // N.B. This function may only be called if the vertex attribute was specified using the function glVertexAttribI4iv(), // otherwise the results are undefined. (GLES3 spec 6.1.12) emscriptenWebGLGetVertexAttrib(index, pname, params, 0); } function _emscripten_glGetVertexAttribPointerv(index, pname, pointer) { if (!pointer) { // GLES2 specification does not specify how to behave if pointer is a null pointer. Since calling this function does not make sense // if pointer == null, issue a GL error to notify user about it. GL.recordError(0x501 /* GL_INVALID_VALUE */); return; } if (GL.currentContext.clientBuffers[index].enabled) { err("glGetVertexAttribPointer on client-side array: not supported, bad data returned"); } HEAP32[((pointer)>>2)] = GLctx.getVertexAttribOffset(index, pname); } function _emscripten_glGetVertexAttribfv(index, pname, params) { // N.B. This function may only be called if the vertex attribute was specified using the function glVertexAttrib*f(), // otherwise the results are undefined. (GLES3 spec 6.1.12) emscriptenWebGLGetVertexAttrib(index, pname, params, 2); } function _emscripten_glGetVertexAttribiv(index, pname, params) { // N.B. This function may only be called if the vertex attribute was specified using the function glVertexAttrib*f(), // otherwise the results are undefined. (GLES3 spec 6.1.12) emscriptenWebGLGetVertexAttrib(index, pname, params, 5); } function _emscripten_glHint(x0, x1) { GLctx['hint'](x0, x1) } function _emscripten_glInvalidateFramebuffer(target, numAttachments, attachments) { var list = tempFixedLengthArray[numAttachments]; for (var i = 0; i < numAttachments; i++) { list[i] = HEAP32[(((attachments)+(i*4))>>2)]; } GLctx['invalidateFramebuffer'](target, list); } function _emscripten_glInvalidateSubFramebuffer(target, numAttachments, attachments, x, y, width, height) { var list = tempFixedLengthArray[numAttachments]; for (var i = 0; i < numAttachments; i++) { list[i] = HEAP32[(((attachments)+(i*4))>>2)]; } GLctx['invalidateSubFramebuffer'](target, list, x, y, width, height); } function _emscripten_glIsBuffer(buffer) { var b = GL.buffers[buffer]; if (!b) return 0; return GLctx.isBuffer(b); } function _emscripten_glIsEnabled(x0) { return GLctx['isEnabled'](x0) } function _emscripten_glIsFramebuffer(framebuffer) { var fb = GL.framebuffers[framebuffer]; if (!fb) return 0; return GLctx.isFramebuffer(fb); } function _emscripten_glIsProgram(program) { program = GL.programs[program]; if (!program) return 0; return GLctx.isProgram(program); } function _emscripten_glIsQuery(id) { var query = GL.queries[id]; if (!query) return 0; return GLctx['isQuery'](query); } function _emscripten_glIsQueryEXT(id) { var query = GL.timerQueriesEXT[id]; if (!query) return 0; return GLctx.disjointTimerQueryExt['isQueryEXT'](query); } function _emscripten_glIsRenderbuffer(renderbuffer) { var rb = GL.renderbuffers[renderbuffer]; if (!rb) return 0; return GLctx.isRenderbuffer(rb); } function _emscripten_glIsSampler(id) { var sampler = GL.samplers[id]; if (!sampler) return 0; return GLctx['isSampler'](sampler); } function _emscripten_glIsShader(shader) { var s = GL.shaders[shader]; if (!s) return 0; return GLctx.isShader(s); } function _emscripten_glIsSync(sync) { return GLctx.isSync(GL.syncs[sync]); } function _emscripten_glIsTexture(id) { var texture = GL.textures[id]; if (!texture) return 0; return GLctx.isTexture(texture); } function _emscripten_glIsTransformFeedback(id) { return GLctx['isTransformFeedback'](GL.transformFeedbacks[id]); } function _emscripten_glIsVertexArray(array) { var vao = GL.vaos[array]; if (!vao) return 0; return GLctx['isVertexArray'](vao); } function _emscripten_glIsVertexArrayOES(array) { var vao = GL.vaos[array]; if (!vao) return 0; return GLctx['isVertexArray'](vao); } function _emscripten_glLineWidth(x0) { GLctx['lineWidth'](x0) } function _emscripten_glLinkProgram(program) { GLctx.linkProgram(GL.programs[program]); GL.populateUniformTable(program); } function _emscripten_glMapBufferRange(target, offset, length, access) { if (access != 0x1A && access != 0xA) { err("glMapBufferRange is only supported when access is MAP_WRITE|INVALIDATE_BUFFER"); return 0; } if (!emscriptenWebGLValidateMapBufferTarget(target)) { GL.recordError(0x500/*GL_INVALID_ENUM*/); err('GL_INVALID_ENUM in glMapBufferRange'); return 0; } var mem = _malloc(length); if (!mem) return 0; GL.mappedBuffers[emscriptenWebGLGetBufferBinding(target)] = { offset: offset, length: length, mem: mem, access: access, }; return mem; } function _emscripten_glPauseTransformFeedback() { GLctx['pauseTransformFeedback']() } function _emscripten_glPixelStorei(pname, param) { if (pname == 0xCF5 /* GL_UNPACK_ALIGNMENT */) { GL.unpackAlignment = param; } GLctx.pixelStorei(pname, param); } function _emscripten_glPolygonOffset(x0, x1) { GLctx['polygonOffset'](x0, x1) } function _emscripten_glProgramBinary(program, binaryFormat, binary, length) { GL.recordError(0x500/*GL_INVALID_ENUM*/); } function _emscripten_glProgramParameteri(program, pname, value) { GL.recordError(0x500/*GL_INVALID_ENUM*/); } function _emscripten_glQueryCounterEXT(id, target) { GLctx.disjointTimerQueryExt['queryCounterEXT'](GL.timerQueriesEXT[id], target); } function _emscripten_glReadBuffer(x0) { GLctx['readBuffer'](x0) } function computeUnpackAlignedImageSize(width, height, sizePerPixel, alignment) { function roundedToNextMultipleOf(x, y) { return (x + y - 1) & -y; } var plainRowSize = width * sizePerPixel; var alignedRowSize = roundedToNextMultipleOf(plainRowSize, alignment); return height * alignedRowSize; } function __colorChannelsInGlTextureFormat(format) { // Micro-optimizations for size: map format to size by subtracting smallest enum value (0x1902) from all values first. // Also omit the most common size value (1) from the list, which is assumed by formats not on the list. var colorChannels = { // 0x1902 /* GL_DEPTH_COMPONENT */ - 0x1902: 1, // 0x1906 /* GL_ALPHA */ - 0x1902: 1, 5: 3, 6: 4, // 0x1909 /* GL_LUMINANCE */ - 0x1902: 1, 8: 2, 29502: 3, 29504: 4, // 0x1903 /* GL_RED */ - 0x1902: 1, 26917: 2, 26918: 2, // 0x8D94 /* GL_RED_INTEGER */ - 0x1902: 1, 29846: 3, 29847: 4 }; return colorChannels[format - 0x1902]||1; } function heapObjectForWebGLType(type) { // Micro-optimization for size: Subtract lowest GL enum number (0x1400/* GL_BYTE */) from type to compare // smaller values for the heap, for shorter generated code size. // Also the type HEAPU16 is not tested for explicitly, but any unrecognized type will return out HEAPU16. // (since most types are HEAPU16) type -= 0x1400; if (type == 0) return HEAP8; if (type == 1) return HEAPU8; if (type == 2) return HEAP16; if (type == 4) return HEAP32; if (type == 6) return HEAPF32; if (type == 5 || type == 28922 || type == 28520 || type == 30779 || type == 30782 ) return HEAPU32; return HEAPU16; } function heapAccessShiftForWebGLHeap(heap) { return 31 - Math.clz32(heap.BYTES_PER_ELEMENT); } function emscriptenWebGLGetTexPixelData(type, format, width, height, pixels, internalFormat) { var heap = heapObjectForWebGLType(type); var shift = heapAccessShiftForWebGLHeap(heap); var byteSize = 1<> shift, pixels + bytes >> shift); } function _emscripten_glReadPixels(x, y, width, height, format, type, pixels) { if (GL.currentContext.version >= 2) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. if (GLctx.currentPixelPackBufferBinding) { GLctx.readPixels(x, y, width, height, format, type, pixels); } else { var heap = heapObjectForWebGLType(type); GLctx.readPixels(x, y, width, height, format, type, heap, pixels >> heapAccessShiftForWebGLHeap(heap)); } return; } var pixelData = emscriptenWebGLGetTexPixelData(type, format, width, height, pixels, format); if (!pixelData) { GL.recordError(0x500/*GL_INVALID_ENUM*/); return; } GLctx.readPixels(x, y, width, height, format, type, pixelData); } function _emscripten_glReleaseShaderCompiler() { // NOP (as allowed by GLES 2.0 spec) } function _emscripten_glRenderbufferStorage(x0, x1, x2, x3) { GLctx['renderbufferStorage'](x0, x1, x2, x3) } function _emscripten_glRenderbufferStorageMultisample(x0, x1, x2, x3, x4) { GLctx['renderbufferStorageMultisample'](x0, x1, x2, x3, x4) } function _emscripten_glResumeTransformFeedback() { GLctx['resumeTransformFeedback']() } function _emscripten_glSampleCoverage(value, invert) { GLctx.sampleCoverage(value, !!invert); } function _emscripten_glSamplerParameterf(sampler, pname, param) { GLctx['samplerParameterf'](GL.samplers[sampler], pname, param); } function _emscripten_glSamplerParameterfv(sampler, pname, params) { var param = HEAPF32[((params)>>2)]; GLctx['samplerParameterf'](GL.samplers[sampler], pname, param); } function _emscripten_glSamplerParameteri(sampler, pname, param) { GLctx['samplerParameteri'](GL.samplers[sampler], pname, param); } function _emscripten_glSamplerParameteriv(sampler, pname, params) { var param = HEAP32[((params)>>2)]; GLctx['samplerParameteri'](GL.samplers[sampler], pname, param); } function _emscripten_glScissor(x0, x1, x2, x3) { GLctx['scissor'](x0, x1, x2, x3) } function _emscripten_glShaderBinary() { GL.recordError(0x500/*GL_INVALID_ENUM*/); } function _emscripten_glShaderSource(shader, count, string, length) { var source = GL.getSource(shader, count, string, length); GLctx.shaderSource(GL.shaders[shader], source); } function _emscripten_glStencilFunc(x0, x1, x2) { GLctx['stencilFunc'](x0, x1, x2) } function _emscripten_glStencilFuncSeparate(x0, x1, x2, x3) { GLctx['stencilFuncSeparate'](x0, x1, x2, x3) } function _emscripten_glStencilMask(x0) { GLctx['stencilMask'](x0) } function _emscripten_glStencilMaskSeparate(x0, x1) { GLctx['stencilMaskSeparate'](x0, x1) } function _emscripten_glStencilOp(x0, x1, x2) { GLctx['stencilOp'](x0, x1, x2) } function _emscripten_glStencilOpSeparate(x0, x1, x2, x3) { GLctx['stencilOpSeparate'](x0, x1, x2, x3) } function _emscripten_glTexImage2D(target, level, internalFormat, width, height, border, format, type, pixels) { if (GL.currentContext.version >= 2) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. if (GLctx.currentPixelUnpackBufferBinding) { GLctx.texImage2D(target, level, internalFormat, width, height, border, format, type, pixels); } else if (pixels) { var heap = heapObjectForWebGLType(type); GLctx.texImage2D(target, level, internalFormat, width, height, border, format, type, heap, pixels >> heapAccessShiftForWebGLHeap(heap)); } else { GLctx.texImage2D(target, level, internalFormat, width, height, border, format, type, null); } return; } GLctx.texImage2D(target, level, internalFormat, width, height, border, format, type, pixels ? emscriptenWebGLGetTexPixelData(type, format, width, height, pixels, internalFormat) : null); } function _emscripten_glTexImage3D(target, level, internalFormat, width, height, depth, border, format, type, pixels) { if (GLctx.currentPixelUnpackBufferBinding) { GLctx['texImage3D'](target, level, internalFormat, width, height, depth, border, format, type, pixels); } else if (pixels) { var heap = heapObjectForWebGLType(type); GLctx['texImage3D'](target, level, internalFormat, width, height, depth, border, format, type, heap, pixels >> heapAccessShiftForWebGLHeap(heap)); } else { GLctx['texImage3D'](target, level, internalFormat, width, height, depth, border, format, type, null); } } function _emscripten_glTexParameterf(x0, x1, x2) { GLctx['texParameterf'](x0, x1, x2) } function _emscripten_glTexParameterfv(target, pname, params) { var param = HEAPF32[((params)>>2)]; GLctx.texParameterf(target, pname, param); } function _emscripten_glTexParameteri(x0, x1, x2) { GLctx['texParameteri'](x0, x1, x2) } function _emscripten_glTexParameteriv(target, pname, params) { var param = HEAP32[((params)>>2)]; GLctx.texParameteri(target, pname, param); } function _emscripten_glTexStorage2D(x0, x1, x2, x3, x4) { GLctx['texStorage2D'](x0, x1, x2, x3, x4) } function _emscripten_glTexStorage3D(x0, x1, x2, x3, x4, x5) { GLctx['texStorage3D'](x0, x1, x2, x3, x4, x5) } function _emscripten_glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels) { if (GL.currentContext.version >= 2) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. if (GLctx.currentPixelUnpackBufferBinding) { GLctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); } else if (pixels) { var heap = heapObjectForWebGLType(type); GLctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, heap, pixels >> heapAccessShiftForWebGLHeap(heap)); } else { GLctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, null); } return; } var pixelData = null; if (pixels) pixelData = emscriptenWebGLGetTexPixelData(type, format, width, height, pixels, 0); GLctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixelData); } function _emscripten_glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels) { if (GLctx.currentPixelUnpackBufferBinding) { GLctx['texSubImage3D'](target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); } else if (pixels) { var heap = heapObjectForWebGLType(type); GLctx['texSubImage3D'](target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, heap, pixels >> heapAccessShiftForWebGLHeap(heap)); } else { GLctx['texSubImage3D'](target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, null); } } function _emscripten_glTransformFeedbackVaryings(program, count, varyings, bufferMode) { program = GL.programs[program]; var vars = []; for (var i = 0; i < count; i++) vars.push(UTF8ToString(HEAP32[(((varyings)+(i*4))>>2)])); GLctx['transformFeedbackVaryings'](program, vars, bufferMode); } function _emscripten_glUniform1f(location, v0) { GLctx.uniform1f(GL.uniforms[location], v0); } var miniTempWebGLFloatBuffers=[]; function _emscripten_glUniform1fv(location, count, value) { if (GL.currentContext.version >= 2) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. GLctx.uniform1fv(GL.uniforms[location], HEAPF32, value>>2, count); return; } if (count <= 288) { // avoid allocation when uploading few enough uniforms var view = miniTempWebGLFloatBuffers[count-1]; for (var i = 0; i < count; ++i) { view[i] = HEAPF32[(((value)+(4*i))>>2)]; } } else { var view = HEAPF32.subarray((value)>>2, (value+count*4)>>2); } GLctx.uniform1fv(GL.uniforms[location], view); } function _emscripten_glUniform1i(location, v0) { GLctx.uniform1i(GL.uniforms[location], v0); } var __miniTempWebGLIntBuffers=[]; function _emscripten_glUniform1iv(location, count, value) { if (GL.currentContext.version >= 2) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. GLctx.uniform1iv(GL.uniforms[location], HEAP32, value>>2, count); return; } if (count <= 288) { // avoid allocation when uploading few enough uniforms var view = __miniTempWebGLIntBuffers[count-1]; for (var i = 0; i < count; ++i) { view[i] = HEAP32[(((value)+(4*i))>>2)]; } } else { var view = HEAP32.subarray((value)>>2, (value+count*4)>>2); } GLctx.uniform1iv(GL.uniforms[location], view); } function _emscripten_glUniform1ui(location, v0) { GLctx.uniform1ui(GL.uniforms[location], v0); } function _emscripten_glUniform1uiv(location, count, value) { GLctx.uniform1uiv(GL.uniforms[location], HEAPU32, value>>2, count); } function _emscripten_glUniform2f(location, v0, v1) { GLctx.uniform2f(GL.uniforms[location], v0, v1); } function _emscripten_glUniform2fv(location, count, value) { if (GL.currentContext.version >= 2) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. GLctx.uniform2fv(GL.uniforms[location], HEAPF32, value>>2, count*2); return; } if (count <= 144) { // avoid allocation when uploading few enough uniforms var view = miniTempWebGLFloatBuffers[2*count-1]; for (var i = 0; i < 2*count; i += 2) { view[i] = HEAPF32[(((value)+(4*i))>>2)]; view[i+1] = HEAPF32[(((value)+(4*i+4))>>2)]; } } else { var view = HEAPF32.subarray((value)>>2, (value+count*8)>>2); } GLctx.uniform2fv(GL.uniforms[location], view); } function _emscripten_glUniform2i(location, v0, v1) { GLctx.uniform2i(GL.uniforms[location], v0, v1); } function _emscripten_glUniform2iv(location, count, value) { if (GL.currentContext.version >= 2) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. GLctx.uniform2iv(GL.uniforms[location], HEAP32, value>>2, count*2); return; } if (count <= 144) { // avoid allocation when uploading few enough uniforms var view = __miniTempWebGLIntBuffers[2*count-1]; for (var i = 0; i < 2*count; i += 2) { view[i] = HEAP32[(((value)+(4*i))>>2)]; view[i+1] = HEAP32[(((value)+(4*i+4))>>2)]; } } else { var view = HEAP32.subarray((value)>>2, (value+count*8)>>2); } GLctx.uniform2iv(GL.uniforms[location], view); } function _emscripten_glUniform2ui(location, v0, v1) { GLctx.uniform2ui(GL.uniforms[location], v0, v1); } function _emscripten_glUniform2uiv(location, count, value) { GLctx.uniform2uiv(GL.uniforms[location], HEAPU32, value>>2, count*2); } function _emscripten_glUniform3f(location, v0, v1, v2) { GLctx.uniform3f(GL.uniforms[location], v0, v1, v2); } function _emscripten_glUniform3fv(location, count, value) { if (GL.currentContext.version >= 2) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. GLctx.uniform3fv(GL.uniforms[location], HEAPF32, value>>2, count*3); return; } if (count <= 96) { // avoid allocation when uploading few enough uniforms var view = miniTempWebGLFloatBuffers[3*count-1]; for (var i = 0; i < 3*count; i += 3) { view[i] = HEAPF32[(((value)+(4*i))>>2)]; view[i+1] = HEAPF32[(((value)+(4*i+4))>>2)]; view[i+2] = HEAPF32[(((value)+(4*i+8))>>2)]; } } else { var view = HEAPF32.subarray((value)>>2, (value+count*12)>>2); } GLctx.uniform3fv(GL.uniforms[location], view); } function _emscripten_glUniform3i(location, v0, v1, v2) { GLctx.uniform3i(GL.uniforms[location], v0, v1, v2); } function _emscripten_glUniform3iv(location, count, value) { if (GL.currentContext.version >= 2) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. GLctx.uniform3iv(GL.uniforms[location], HEAP32, value>>2, count*3); return; } if (count <= 96) { // avoid allocation when uploading few enough uniforms var view = __miniTempWebGLIntBuffers[3*count-1]; for (var i = 0; i < 3*count; i += 3) { view[i] = HEAP32[(((value)+(4*i))>>2)]; view[i+1] = HEAP32[(((value)+(4*i+4))>>2)]; view[i+2] = HEAP32[(((value)+(4*i+8))>>2)]; } } else { var view = HEAP32.subarray((value)>>2, (value+count*12)>>2); } GLctx.uniform3iv(GL.uniforms[location], view); } function _emscripten_glUniform3ui(location, v0, v1, v2) { GLctx.uniform3ui(GL.uniforms[location], v0, v1, v2); } function _emscripten_glUniform3uiv(location, count, value) { GLctx.uniform3uiv(GL.uniforms[location], HEAPU32, value>>2, count*3); } function _emscripten_glUniform4f(location, v0, v1, v2, v3) { GLctx.uniform4f(GL.uniforms[location], v0, v1, v2, v3); } function _emscripten_glUniform4fv(location, count, value) { if (GL.currentContext.version >= 2) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. GLctx.uniform4fv(GL.uniforms[location], HEAPF32, value>>2, count*4); return; } if (count <= 72) { // avoid allocation when uploading few enough uniforms var view = miniTempWebGLFloatBuffers[4*count-1]; // hoist the heap out of the loop for size and for pthreads+growth. var heap = HEAPF32; value >>= 2; for (var i = 0; i < 4 * count; i += 4) { var dst = value + i; view[i] = heap[dst]; view[i + 1] = heap[dst + 1]; view[i + 2] = heap[dst + 2]; view[i + 3] = heap[dst + 3]; } } else { var view = HEAPF32.subarray((value)>>2, (value+count*16)>>2); } GLctx.uniform4fv(GL.uniforms[location], view); } function _emscripten_glUniform4i(location, v0, v1, v2, v3) { GLctx.uniform4i(GL.uniforms[location], v0, v1, v2, v3); } function _emscripten_glUniform4iv(location, count, value) { if (GL.currentContext.version >= 2) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. GLctx.uniform4iv(GL.uniforms[location], HEAP32, value>>2, count*4); return; } if (count <= 72) { // avoid allocation when uploading few enough uniforms var view = __miniTempWebGLIntBuffers[4*count-1]; for (var i = 0; i < 4*count; i += 4) { view[i] = HEAP32[(((value)+(4*i))>>2)]; view[i+1] = HEAP32[(((value)+(4*i+4))>>2)]; view[i+2] = HEAP32[(((value)+(4*i+8))>>2)]; view[i+3] = HEAP32[(((value)+(4*i+12))>>2)]; } } else { var view = HEAP32.subarray((value)>>2, (value+count*16)>>2); } GLctx.uniform4iv(GL.uniforms[location], view); } function _emscripten_glUniform4ui(location, v0, v1, v2, v3) { GLctx.uniform4ui(GL.uniforms[location], v0, v1, v2, v3); } function _emscripten_glUniform4uiv(location, count, value) { GLctx.uniform4uiv(GL.uniforms[location], HEAPU32, value>>2, count*4); } function _emscripten_glUniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding) { program = GL.programs[program]; GLctx['uniformBlockBinding'](program, uniformBlockIndex, uniformBlockBinding); } function _emscripten_glUniformMatrix2fv(location, count, transpose, value) { if (GL.currentContext.version >= 2) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. GLctx.uniformMatrix2fv(GL.uniforms[location], !!transpose, HEAPF32, value>>2, count*4); return; } if (count <= 72) { // avoid allocation when uploading few enough uniforms var view = miniTempWebGLFloatBuffers[4*count-1]; for (var i = 0; i < 4*count; i += 4) { view[i] = HEAPF32[(((value)+(4*i))>>2)]; view[i+1] = HEAPF32[(((value)+(4*i+4))>>2)]; view[i+2] = HEAPF32[(((value)+(4*i+8))>>2)]; view[i+3] = HEAPF32[(((value)+(4*i+12))>>2)]; } } else { var view = HEAPF32.subarray((value)>>2, (value+count*16)>>2); } GLctx.uniformMatrix2fv(GL.uniforms[location], !!transpose, view); } function _emscripten_glUniformMatrix2x3fv(location, count, transpose, value) { GLctx.uniformMatrix2x3fv(GL.uniforms[location], !!transpose, HEAPF32, value>>2, count*6); } function _emscripten_glUniformMatrix2x4fv(location, count, transpose, value) { GLctx.uniformMatrix2x4fv(GL.uniforms[location], !!transpose, HEAPF32, value>>2, count*8); } function _emscripten_glUniformMatrix3fv(location, count, transpose, value) { if (GL.currentContext.version >= 2) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. GLctx.uniformMatrix3fv(GL.uniforms[location], !!transpose, HEAPF32, value>>2, count*9); return; } if (count <= 32) { // avoid allocation when uploading few enough uniforms var view = miniTempWebGLFloatBuffers[9*count-1]; for (var i = 0; i < 9*count; i += 9) { view[i] = HEAPF32[(((value)+(4*i))>>2)]; view[i+1] = HEAPF32[(((value)+(4*i+4))>>2)]; view[i+2] = HEAPF32[(((value)+(4*i+8))>>2)]; view[i+3] = HEAPF32[(((value)+(4*i+12))>>2)]; view[i+4] = HEAPF32[(((value)+(4*i+16))>>2)]; view[i+5] = HEAPF32[(((value)+(4*i+20))>>2)]; view[i+6] = HEAPF32[(((value)+(4*i+24))>>2)]; view[i+7] = HEAPF32[(((value)+(4*i+28))>>2)]; view[i+8] = HEAPF32[(((value)+(4*i+32))>>2)]; } } else { var view = HEAPF32.subarray((value)>>2, (value+count*36)>>2); } GLctx.uniformMatrix3fv(GL.uniforms[location], !!transpose, view); } function _emscripten_glUniformMatrix3x2fv(location, count, transpose, value) { GLctx.uniformMatrix3x2fv(GL.uniforms[location], !!transpose, HEAPF32, value>>2, count*6); } function _emscripten_glUniformMatrix3x4fv(location, count, transpose, value) { GLctx.uniformMatrix3x4fv(GL.uniforms[location], !!transpose, HEAPF32, value>>2, count*12); } function _emscripten_glUniformMatrix4fv(location, count, transpose, value) { if (GL.currentContext.version >= 2) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. GLctx.uniformMatrix4fv(GL.uniforms[location], !!transpose, HEAPF32, value>>2, count*16); return; } if (count <= 18) { // avoid allocation when uploading few enough uniforms var view = miniTempWebGLFloatBuffers[16*count-1]; // hoist the heap out of the loop for size and for pthreads+growth. var heap = HEAPF32; value >>= 2; for (var i = 0; i < 16 * count; i += 16) { var dst = value + i; view[i] = heap[dst]; view[i + 1] = heap[dst + 1]; view[i + 2] = heap[dst + 2]; view[i + 3] = heap[dst + 3]; view[i + 4] = heap[dst + 4]; view[i + 5] = heap[dst + 5]; view[i + 6] = heap[dst + 6]; view[i + 7] = heap[dst + 7]; view[i + 8] = heap[dst + 8]; view[i + 9] = heap[dst + 9]; view[i + 10] = heap[dst + 10]; view[i + 11] = heap[dst + 11]; view[i + 12] = heap[dst + 12]; view[i + 13] = heap[dst + 13]; view[i + 14] = heap[dst + 14]; view[i + 15] = heap[dst + 15]; } } else { var view = HEAPF32.subarray((value)>>2, (value+count*64)>>2); } GLctx.uniformMatrix4fv(GL.uniforms[location], !!transpose, view); } function _emscripten_glUniformMatrix4x2fv(location, count, transpose, value) { GLctx.uniformMatrix4x2fv(GL.uniforms[location], !!transpose, HEAPF32, value>>2, count*8); } function _emscripten_glUniformMatrix4x3fv(location, count, transpose, value) { GLctx.uniformMatrix4x3fv(GL.uniforms[location], !!transpose, HEAPF32, value>>2, count*12); } function _emscripten_glUnmapBuffer(target) { if (!emscriptenWebGLValidateMapBufferTarget(target)) { GL.recordError(0x500/*GL_INVALID_ENUM*/); err('GL_INVALID_ENUM in glUnmapBuffer'); return 0; } var buffer = emscriptenWebGLGetBufferBinding(target); var mapping = GL.mappedBuffers[buffer]; if (!mapping) { GL.recordError(0x502 /* GL_INVALID_OPERATION */); err('buffer was never mapped in glUnmapBuffer'); return 0; } GL.mappedBuffers[buffer] = null; if (!(mapping.access & 0x10)) /* GL_MAP_FLUSH_EXPLICIT_BIT */ if (GL.currentContext.version >= 2) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. GLctx.bufferSubData(target, mapping.offset, HEAPU8, mapping.mem, mapping.length); } else { GLctx.bufferSubData(target, mapping.offset, HEAPU8.subarray(mapping.mem, mapping.mem+mapping.length)); } _free(mapping.mem); return 1; } function _emscripten_glUseProgram(program) { GLctx.useProgram(GL.programs[program]); } function _emscripten_glValidateProgram(program) { GLctx.validateProgram(GL.programs[program]); } function _emscripten_glVertexAttrib1f(x0, x1) { GLctx['vertexAttrib1f'](x0, x1) } function _emscripten_glVertexAttrib1fv(index, v) { GLctx.vertexAttrib1f(index, HEAPF32[v>>2]); } function _emscripten_glVertexAttrib2f(x0, x1, x2) { GLctx['vertexAttrib2f'](x0, x1, x2) } function _emscripten_glVertexAttrib2fv(index, v) { GLctx.vertexAttrib2f(index, HEAPF32[v>>2], HEAPF32[v+4>>2]); } function _emscripten_glVertexAttrib3f(x0, x1, x2, x3) { GLctx['vertexAttrib3f'](x0, x1, x2, x3) } function _emscripten_glVertexAttrib3fv(index, v) { GLctx.vertexAttrib3f(index, HEAPF32[v>>2], HEAPF32[v+4>>2], HEAPF32[v+8>>2]); } function _emscripten_glVertexAttrib4f(x0, x1, x2, x3, x4) { GLctx['vertexAttrib4f'](x0, x1, x2, x3, x4) } function _emscripten_glVertexAttrib4fv(index, v) { GLctx.vertexAttrib4f(index, HEAPF32[v>>2], HEAPF32[v+4>>2], HEAPF32[v+8>>2], HEAPF32[v+12>>2]); } function _emscripten_glVertexAttribDivisor(index, divisor) { GLctx['vertexAttribDivisor'](index, divisor); } function _emscripten_glVertexAttribDivisorANGLE(index, divisor) { GLctx['vertexAttribDivisor'](index, divisor); } function _emscripten_glVertexAttribDivisorARB(index, divisor) { GLctx['vertexAttribDivisor'](index, divisor); } function _emscripten_glVertexAttribDivisorEXT(index, divisor) { GLctx['vertexAttribDivisor'](index, divisor); } function _emscripten_glVertexAttribDivisorNV(index, divisor) { GLctx['vertexAttribDivisor'](index, divisor); } function _emscripten_glVertexAttribI4i(x0, x1, x2, x3, x4) { GLctx['vertexAttribI4i'](x0, x1, x2, x3, x4) } function _emscripten_glVertexAttribI4iv(index, v) { GLctx.vertexAttribI4i(index, HEAP32[v>>2], HEAP32[v+4>>2], HEAP32[v+8>>2], HEAP32[v+12>>2]); } function _emscripten_glVertexAttribI4ui(x0, x1, x2, x3, x4) { GLctx['vertexAttribI4ui'](x0, x1, x2, x3, x4) } function _emscripten_glVertexAttribI4uiv(index, v) { GLctx.vertexAttribI4ui(index, HEAPU32[v>>2], HEAPU32[v+4>>2], HEAPU32[v+8>>2], HEAPU32[v+12>>2]); } function _emscripten_glVertexAttribIPointer(index, size, type, stride, ptr) { var cb = GL.currentContext.clientBuffers[index]; if (!GLctx.currentArrayBufferBinding) { cb.size = size; cb.type = type; cb.normalized = false; cb.stride = stride; cb.ptr = ptr; cb.clientside = true; cb.vertexAttribPointerAdaptor = function(index, size, type, normalized, stride, ptr) { this.vertexAttribIPointer(index, size, type, stride, ptr); }; return; } cb.clientside = false; GLctx['vertexAttribIPointer'](index, size, type, stride, ptr); } function _emscripten_glVertexAttribPointer(index, size, type, normalized, stride, ptr) { var cb = GL.currentContext.clientBuffers[index]; if (!GLctx.currentArrayBufferBinding) { cb.size = size; cb.type = type; cb.normalized = normalized; cb.stride = stride; cb.ptr = ptr; cb.clientside = true; cb.vertexAttribPointerAdaptor = function(index, size, type, normalized, stride, ptr) { this.vertexAttribPointer(index, size, type, normalized, stride, ptr); }; return; } cb.clientside = false; GLctx.vertexAttribPointer(index, size, type, !!normalized, stride, ptr); } function _emscripten_glViewport(x0, x1, x2, x3) { GLctx['viewport'](x0, x1, x2, x3) } function _emscripten_glWaitSync(sync, flags, timeoutLo, timeoutHi) { // See WebGL2 vs GLES3 difference on GL_TIMEOUT_IGNORED above (https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.15) GLctx.waitSync(GL.syncs[sync], flags, convertI32PairToI53(timeoutLo, timeoutHi)); } function _emscripten_has_asyncify() { return 0; } function _emscripten_memcpy_big(dest, src, num) { HEAPU8.copyWithin(dest, src, src + num); } function doRequestFullscreen(target, strategy) { if (!JSEvents.fullscreenEnabled()) return -1; target = findEventTarget(target); if (!target) return -4; if (!target.requestFullscreen && !target.webkitRequestFullscreen ) { return -3; } var canPerformRequests = JSEvents.canPerformEventHandlerRequests(); // Queue this function call if we're not currently in an event handler and the user saw it appropriate to do so. if (!canPerformRequests) { if (strategy.deferUntilInEventHandler) { JSEvents.deferCall(_JSEvents_requestFullscreen, 1 /* priority over pointer lock */, [target, strategy]); return 1; } else { return -2; } } return _JSEvents_requestFullscreen(target, strategy); } function _emscripten_request_fullscreen_strategy(target, deferUntilInEventHandler, fullscreenStrategy) { var strategy = { scaleMode: HEAP32[((fullscreenStrategy)>>2)], canvasResolutionScaleMode: HEAP32[(((fullscreenStrategy)+(4))>>2)], filteringMode: HEAP32[(((fullscreenStrategy)+(8))>>2)], deferUntilInEventHandler: deferUntilInEventHandler, canvasResizedCallback: HEAP32[(((fullscreenStrategy)+(12))>>2)], canvasResizedCallbackUserData: HEAP32[(((fullscreenStrategy)+(16))>>2)] }; return doRequestFullscreen(target, strategy); } function _emscripten_request_pointerlock(target, deferUntilInEventHandler) { target = findEventTarget(target); if (!target) return -4; if (!target.requestPointerLock && !target.msRequestPointerLock ) { return -1; } var canPerformRequests = JSEvents.canPerformEventHandlerRequests(); // Queue this function call if we're not currently in an event handler and the user saw it appropriate to do so. if (!canPerformRequests) { if (deferUntilInEventHandler) { JSEvents.deferCall(requestPointerLock, 2 /* priority below fullscreen */, [target]); return 1; } else { return -2; } } return requestPointerLock(target); } function abortOnCannotGrowMemory(requestedSize) { abort('OOM'); } function _emscripten_resize_heap(requestedSize) { var oldSize = HEAPU8.length; requestedSize = requestedSize >>> 0; abortOnCannotGrowMemory(requestedSize); } function _emscripten_sample_gamepad_data() { return (JSEvents.lastGamepadState = (navigator.getGamepads ? navigator.getGamepads() : (navigator.webkitGetGamepads ? navigator.webkitGetGamepads() : null))) ? 0 : -1; } function registerBeforeUnloadEventCallback(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString) { var beforeUnloadEventHandlerFunc = function(ev) { var e = ev || event; // Note: This is always called on the main browser thread, since it needs synchronously return a value! var confirmationMessage = wasmTable.get(callbackfunc)(eventTypeId, 0, userData); if (confirmationMessage) { confirmationMessage = UTF8ToString(confirmationMessage); } if (confirmationMessage) { e.preventDefault(); e.returnValue = confirmationMessage; return confirmationMessage; } }; var eventHandler = { target: findEventTarget(target), eventTypeString: eventTypeString, callbackfunc: callbackfunc, handlerFunc: beforeUnloadEventHandlerFunc, useCapture: useCapture }; JSEvents.registerOrRemoveHandler(eventHandler); } function _emscripten_set_beforeunload_callback_on_thread(userData, callbackfunc, targetThread) { if (typeof onbeforeunload === 'undefined') return -1; // beforeunload callback can only be registered on the main browser thread, because the page will go away immediately after returning from the handler, // and there is no time to start proxying it anywhere. if (targetThread !== 1) return -5; registerBeforeUnloadEventCallback(2, userData, true, callbackfunc, 28, "beforeunload"); return 0; } function registerFocusEventCallback(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) { if (!JSEvents.focusEvent) JSEvents.focusEvent = _malloc( 256 ); var focusEventHandlerFunc = function(ev) { var e = ev || event; var nodeName = JSEvents.getNodeNameForTarget(e.target); var id = e.target.id ? e.target.id : ''; var focusEvent = JSEvents.focusEvent; stringToUTF8(nodeName, focusEvent + 0, 128); stringToUTF8(id, focusEvent + 128, 128); if (wasmTable.get(callbackfunc)(eventTypeId, focusEvent, userData)) e.preventDefault(); }; var eventHandler = { target: findEventTarget(target), eventTypeString: eventTypeString, callbackfunc: callbackfunc, handlerFunc: focusEventHandlerFunc, useCapture: useCapture }; JSEvents.registerOrRemoveHandler(eventHandler); } function _emscripten_set_blur_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) { registerFocusEventCallback(target, userData, useCapture, callbackfunc, 12, "blur", targetThread); return 0; } function _emscripten_set_element_css_size(target, width, height) { target = findEventTarget(target); if (!target) return -4; target.style.width = width + "px"; target.style.height = height + "px"; return 0; } function _emscripten_set_focus_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) { registerFocusEventCallback(target, userData, useCapture, callbackfunc, 13, "focus", targetThread); return 0; } function fillFullscreenChangeEventData(eventStruct) { var fullscreenElement = document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement; var isFullscreen = !!fullscreenElement; /** @suppress{checkTypes} */ HEAP32[((eventStruct)>>2)] = isFullscreen; HEAP32[(((eventStruct)+(4))>>2)] = JSEvents.fullscreenEnabled(); // If transitioning to fullscreen, report info about the element that is now fullscreen. // If transitioning to windowed mode, report info about the element that just was fullscreen. var reportedElement = isFullscreen ? fullscreenElement : JSEvents.previousFullscreenElement; var nodeName = JSEvents.getNodeNameForTarget(reportedElement); var id = (reportedElement && reportedElement.id) ? reportedElement.id : ''; stringToUTF8(nodeName, eventStruct + 8, 128); stringToUTF8(id, eventStruct + 136, 128); HEAP32[(((eventStruct)+(264))>>2)] = reportedElement ? reportedElement.clientWidth : 0; HEAP32[(((eventStruct)+(268))>>2)] = reportedElement ? reportedElement.clientHeight : 0; HEAP32[(((eventStruct)+(272))>>2)] = screen.width; HEAP32[(((eventStruct)+(276))>>2)] = screen.height; if (isFullscreen) { JSEvents.previousFullscreenElement = fullscreenElement; } } function registerFullscreenChangeEventCallback(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) { if (!JSEvents.fullscreenChangeEvent) JSEvents.fullscreenChangeEvent = _malloc( 280 ); var fullscreenChangeEventhandlerFunc = function(ev) { var e = ev || event; var fullscreenChangeEvent = JSEvents.fullscreenChangeEvent; fillFullscreenChangeEventData(fullscreenChangeEvent); if (wasmTable.get(callbackfunc)(eventTypeId, fullscreenChangeEvent, userData)) e.preventDefault(); }; var eventHandler = { target: target, eventTypeString: eventTypeString, callbackfunc: callbackfunc, handlerFunc: fullscreenChangeEventhandlerFunc, useCapture: useCapture }; JSEvents.registerOrRemoveHandler(eventHandler); } function _emscripten_set_fullscreenchange_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) { if (!JSEvents.fullscreenEnabled()) return -1; target = findEventTarget(target); if (!target) return -4; registerFullscreenChangeEventCallback(target, userData, useCapture, callbackfunc, 19, "fullscreenchange", targetThread); // Unprefixed Fullscreen API shipped in Chromium 71 (https://bugs.chromium.org/p/chromium/issues/detail?id=383813) // As of Safari 13.0.3 on macOS Catalina 10.15.1 still ships with prefixed webkitfullscreenchange. TODO: revisit this check once Safari ships unprefixed version. registerFullscreenChangeEventCallback(target, userData, useCapture, callbackfunc, 19, "webkitfullscreenchange", targetThread); return 0; } function registerGamepadEventCallback(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) { if (!JSEvents.gamepadEvent) JSEvents.gamepadEvent = _malloc( 1432 ); var gamepadEventHandlerFunc = function(ev) { var e = ev || event; var gamepadEvent = JSEvents.gamepadEvent; fillGamepadEventData(gamepadEvent, e["gamepad"]); if (wasmTable.get(callbackfunc)(eventTypeId, gamepadEvent, userData)) e.preventDefault(); }; var eventHandler = { target: findEventTarget(target), allowsDeferredCalls: true, eventTypeString: eventTypeString, callbackfunc: callbackfunc, handlerFunc: gamepadEventHandlerFunc, useCapture: useCapture }; JSEvents.registerOrRemoveHandler(eventHandler); } function _emscripten_set_gamepadconnected_callback_on_thread(userData, useCapture, callbackfunc, targetThread) { if (!navigator.getGamepads && !navigator.webkitGetGamepads) return -1; registerGamepadEventCallback(2, userData, useCapture, callbackfunc, 26, "gamepadconnected", targetThread); return 0; } function _emscripten_set_gamepaddisconnected_callback_on_thread(userData, useCapture, callbackfunc, targetThread) { if (!navigator.getGamepads && !navigator.webkitGetGamepads) return -1; registerGamepadEventCallback(2, userData, useCapture, callbackfunc, 27, "gamepaddisconnected", targetThread); return 0; } function registerKeyEventCallback(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) { if (!JSEvents.keyEvent) JSEvents.keyEvent = _malloc( 164 ); var keyEventHandlerFunc = function(e) { var keyEventData = JSEvents.keyEvent; var idx = keyEventData >> 2; HEAP32[idx + 0] = e.location; HEAP32[idx + 1] = e.ctrlKey; HEAP32[idx + 2] = e.shiftKey; HEAP32[idx + 3] = e.altKey; HEAP32[idx + 4] = e.metaKey; HEAP32[idx + 5] = e.repeat; HEAP32[idx + 6] = e.charCode; HEAP32[idx + 7] = e.keyCode; HEAP32[idx + 8] = e.which; stringToUTF8(e.key || '', keyEventData + 36, 32); stringToUTF8(e.code || '', keyEventData + 68, 32); stringToUTF8(e.char || '', keyEventData + 100, 32); stringToUTF8(e.locale || '', keyEventData + 132, 32); if (wasmTable.get(callbackfunc)(eventTypeId, keyEventData, userData)) e.preventDefault(); }; var eventHandler = { target: findEventTarget(target), allowsDeferredCalls: true, eventTypeString: eventTypeString, callbackfunc: callbackfunc, handlerFunc: keyEventHandlerFunc, useCapture: useCapture }; JSEvents.registerOrRemoveHandler(eventHandler); } function _emscripten_set_keydown_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) { registerKeyEventCallback(target, userData, useCapture, callbackfunc, 2, "keydown", targetThread); return 0; } function _emscripten_set_keypress_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) { registerKeyEventCallback(target, userData, useCapture, callbackfunc, 1, "keypress", targetThread); return 0; } function _emscripten_set_keyup_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) { registerKeyEventCallback(target, userData, useCapture, callbackfunc, 3, "keyup", targetThread); return 0; } function fillMouseEventData(eventStruct, e, target) { var idx = eventStruct >> 2; HEAP32[idx + 0] = e.screenX; HEAP32[idx + 1] = e.screenY; HEAP32[idx + 2] = e.clientX; HEAP32[idx + 3] = e.clientY; HEAP32[idx + 4] = e.ctrlKey; HEAP32[idx + 5] = e.shiftKey; HEAP32[idx + 6] = e.altKey; HEAP32[idx + 7] = e.metaKey; HEAP16[idx*2 + 16] = e.button; HEAP16[idx*2 + 17] = e.buttons; HEAP32[idx + 9] = e["movementX"] ; HEAP32[idx + 10] = e["movementY"] ; var rect = getBoundingClientRect(target); HEAP32[idx + 11] = e.clientX - rect.left; HEAP32[idx + 12] = e.clientY - rect.top; } function registerMouseEventCallback(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) { if (!JSEvents.mouseEvent) JSEvents.mouseEvent = _malloc( 64 ); target = findEventTarget(target); var mouseEventHandlerFunc = function(ev) { var e = ev || event; // TODO: Make this access thread safe, or this could update live while app is reading it. fillMouseEventData(JSEvents.mouseEvent, e, target); if (wasmTable.get(callbackfunc)(eventTypeId, JSEvents.mouseEvent, userData)) e.preventDefault(); }; var eventHandler = { target: target, allowsDeferredCalls: eventTypeString != 'mousemove' && eventTypeString != 'mouseenter' && eventTypeString != 'mouseleave', // Mouse move events do not allow fullscreen/pointer lock requests to be handled in them! eventTypeString: eventTypeString, callbackfunc: callbackfunc, handlerFunc: mouseEventHandlerFunc, useCapture: useCapture }; JSEvents.registerOrRemoveHandler(eventHandler); } function _emscripten_set_mousedown_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) { registerMouseEventCallback(target, userData, useCapture, callbackfunc, 5, "mousedown", targetThread); return 0; } function _emscripten_set_mouseenter_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) { registerMouseEventCallback(target, userData, useCapture, callbackfunc, 33, "mouseenter", targetThread); return 0; } function _emscripten_set_mouseleave_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) { registerMouseEventCallback(target, userData, useCapture, callbackfunc, 34, "mouseleave", targetThread); return 0; } function _emscripten_set_mousemove_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) { registerMouseEventCallback(target, userData, useCapture, callbackfunc, 8, "mousemove", targetThread); return 0; } function _emscripten_set_mouseup_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) { registerMouseEventCallback(target, userData, useCapture, callbackfunc, 6, "mouseup", targetThread); return 0; } function fillPointerlockChangeEventData(eventStruct) { var pointerLockElement = document.pointerLockElement || document.mozPointerLockElement || document.webkitPointerLockElement || document.msPointerLockElement; var isPointerlocked = !!pointerLockElement; /** @suppress {checkTypes} */ HEAP32[((eventStruct)>>2)] = isPointerlocked; var nodeName = JSEvents.getNodeNameForTarget(pointerLockElement); var id = (pointerLockElement && pointerLockElement.id) ? pointerLockElement.id : ''; stringToUTF8(nodeName, eventStruct + 4, 128); stringToUTF8(id, eventStruct + 132, 128); } function registerPointerlockChangeEventCallback(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) { if (!JSEvents.pointerlockChangeEvent) JSEvents.pointerlockChangeEvent = _malloc( 260 ); var pointerlockChangeEventHandlerFunc = function(ev) { var e = ev || event; var pointerlockChangeEvent = JSEvents.pointerlockChangeEvent; fillPointerlockChangeEventData(pointerlockChangeEvent); if (wasmTable.get(callbackfunc)(eventTypeId, pointerlockChangeEvent, userData)) e.preventDefault(); }; var eventHandler = { target: target, eventTypeString: eventTypeString, callbackfunc: callbackfunc, handlerFunc: pointerlockChangeEventHandlerFunc, useCapture: useCapture }; JSEvents.registerOrRemoveHandler(eventHandler); } /** @suppress {missingProperties} */ function _emscripten_set_pointerlockchange_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) { // TODO: Currently not supported in pthreads or in --proxy-to-worker mode. (In pthreads mode, document object is not defined) if (!document || !document.body || (!document.body.requestPointerLock && !document.body.mozRequestPointerLock && !document.body.webkitRequestPointerLock && !document.body.msRequestPointerLock)) { return -1; } target = findEventTarget(target); if (!target) return -4; registerPointerlockChangeEventCallback(target, userData, useCapture, callbackfunc, 20, "pointerlockchange", targetThread); registerPointerlockChangeEventCallback(target, userData, useCapture, callbackfunc, 20, "mozpointerlockchange", targetThread); registerPointerlockChangeEventCallback(target, userData, useCapture, callbackfunc, 20, "webkitpointerlockchange", targetThread); registerPointerlockChangeEventCallback(target, userData, useCapture, callbackfunc, 20, "mspointerlockchange", targetThread); return 0; } function registerUiEventCallback(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) { if (!JSEvents.uiEvent) JSEvents.uiEvent = _malloc( 36 ); target = findEventTarget(target); var uiEventHandlerFunc = function(ev) { var e = ev || event; if (e.target != target) { // Never take ui events such as scroll via a 'bubbled' route, but always from the direct element that // was targeted. Otherwise e.g. if app logs a message in response to a page scroll, the Emscripten log // message box could cause to scroll, generating a new (bubbled) scroll message, causing a new log print, // causing a new scroll, etc.. return; } var b = document.body; // Take document.body to a variable, Closure compiler does not outline access to it on its own. if (!b) { // During a page unload 'body' can be null, with "Cannot read property 'clientWidth' of null" being thrown return; } var uiEvent = JSEvents.uiEvent; HEAP32[((uiEvent)>>2)] = e.detail; HEAP32[(((uiEvent)+(4))>>2)] = b.clientWidth; HEAP32[(((uiEvent)+(8))>>2)] = b.clientHeight; HEAP32[(((uiEvent)+(12))>>2)] = innerWidth; HEAP32[(((uiEvent)+(16))>>2)] = innerHeight; HEAP32[(((uiEvent)+(20))>>2)] = outerWidth; HEAP32[(((uiEvent)+(24))>>2)] = outerHeight; HEAP32[(((uiEvent)+(28))>>2)] = pageXOffset; HEAP32[(((uiEvent)+(32))>>2)] = pageYOffset; if (wasmTable.get(callbackfunc)(eventTypeId, uiEvent, userData)) e.preventDefault(); }; var eventHandler = { target: target, eventTypeString: eventTypeString, callbackfunc: callbackfunc, handlerFunc: uiEventHandlerFunc, useCapture: useCapture }; JSEvents.registerOrRemoveHandler(eventHandler); } function _emscripten_set_resize_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) { registerUiEventCallback(target, userData, useCapture, callbackfunc, 10, "resize", targetThread); return 0; } function registerTouchEventCallback(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) { if (!JSEvents.touchEvent) JSEvents.touchEvent = _malloc( 1684 ); target = findEventTarget(target); var touchEventHandlerFunc = function(e) { var touches = {}; var et = e.touches; for (var i = 0; i < et.length; ++i) { var touch = et[i]; touches[touch.identifier] = touch; } et = e.changedTouches; for (var i = 0; i < et.length; ++i) { var touch = et[i]; touch.isChanged = 1; touches[touch.identifier] = touch; } et = e.targetTouches; for (var i = 0; i < et.length; ++i) { touches[et[i].identifier].onTarget = 1; } var touchEvent = JSEvents.touchEvent; var idx = touchEvent>>2; // Pre-shift the ptr to index to HEAP32 to save code size HEAP32[idx + 1] = e.ctrlKey; HEAP32[idx + 2] = e.shiftKey; HEAP32[idx + 3] = e.altKey; HEAP32[idx + 4] = e.metaKey; idx += 5; // Advance to the start of the touch array. var targetRect = getBoundingClientRect(target); var numTouches = 0; for (var i in touches) { var t = touches[i]; HEAP32[idx + 0] = t.identifier; HEAP32[idx + 1] = t.screenX; HEAP32[idx + 2] = t.screenY; HEAP32[idx + 3] = t.clientX; HEAP32[idx + 4] = t.clientY; HEAP32[idx + 5] = t.pageX; HEAP32[idx + 6] = t.pageY; HEAP32[idx + 7] = t.isChanged; HEAP32[idx + 8] = t.onTarget; HEAP32[idx + 9] = t.clientX - targetRect.left; HEAP32[idx + 10] = t.clientY - targetRect.top; idx += 13; if (++numTouches > 31) { break; } } HEAP32[((touchEvent)>>2)] = numTouches; if (wasmTable.get(callbackfunc)(eventTypeId, touchEvent, userData)) e.preventDefault(); }; var eventHandler = { target: target, allowsDeferredCalls: eventTypeString == 'touchstart' || eventTypeString == 'touchend', eventTypeString: eventTypeString, callbackfunc: callbackfunc, handlerFunc: touchEventHandlerFunc, useCapture: useCapture }; JSEvents.registerOrRemoveHandler(eventHandler); } function _emscripten_set_touchcancel_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) { registerTouchEventCallback(target, userData, useCapture, callbackfunc, 25, "touchcancel", targetThread); return 0; } function _emscripten_set_touchend_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) { registerTouchEventCallback(target, userData, useCapture, callbackfunc, 23, "touchend", targetThread); return 0; } function _emscripten_set_touchmove_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) { registerTouchEventCallback(target, userData, useCapture, callbackfunc, 24, "touchmove", targetThread); return 0; } function _emscripten_set_touchstart_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) { registerTouchEventCallback(target, userData, useCapture, callbackfunc, 22, "touchstart", targetThread); return 0; } function fillVisibilityChangeEventData(eventStruct) { var visibilityStates = [ "hidden", "visible", "prerender", "unloaded" ]; var visibilityState = visibilityStates.indexOf(document.visibilityState); // Assigning a boolean to HEAP32 with expected type coercion. /** @suppress {checkTypes} */ HEAP32[((eventStruct)>>2)] = document.hidden; HEAP32[(((eventStruct)+(4))>>2)] = visibilityState; } function registerVisibilityChangeEventCallback(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) { if (!JSEvents.visibilityChangeEvent) JSEvents.visibilityChangeEvent = _malloc( 8 ); var visibilityChangeEventHandlerFunc = function(ev) { var e = ev || event; var visibilityChangeEvent = JSEvents.visibilityChangeEvent; fillVisibilityChangeEventData(visibilityChangeEvent); if (wasmTable.get(callbackfunc)(eventTypeId, visibilityChangeEvent, userData)) e.preventDefault(); }; var eventHandler = { target: target, eventTypeString: eventTypeString, callbackfunc: callbackfunc, handlerFunc: visibilityChangeEventHandlerFunc, useCapture: useCapture }; JSEvents.registerOrRemoveHandler(eventHandler); } function _emscripten_set_visibilitychange_callback_on_thread(userData, useCapture, callbackfunc, targetThread) { registerVisibilityChangeEventCallback(specialHTMLTargets[1], userData, useCapture, callbackfunc, 21, "visibilitychange", targetThread); return 0; } function registerWheelEventCallback(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) { if (!JSEvents.wheelEvent) JSEvents.wheelEvent = _malloc( 96 ); // The DOM Level 3 events spec event 'wheel' var wheelHandlerFunc = function(ev) { var e = ev || event; var wheelEvent = JSEvents.wheelEvent; fillMouseEventData(wheelEvent, e, target); HEAPF64[(((wheelEvent)+(64))>>3)] = e["deltaX"]; HEAPF64[(((wheelEvent)+(72))>>3)] = e["deltaY"]; HEAPF64[(((wheelEvent)+(80))>>3)] = e["deltaZ"]; HEAP32[(((wheelEvent)+(88))>>2)] = e["deltaMode"]; if (wasmTable.get(callbackfunc)(eventTypeId, wheelEvent, userData)) e.preventDefault(); }; var eventHandler = { target: target, allowsDeferredCalls: true, eventTypeString: eventTypeString, callbackfunc: callbackfunc, handlerFunc: wheelHandlerFunc, useCapture: useCapture }; JSEvents.registerOrRemoveHandler(eventHandler); } function _emscripten_set_wheel_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) { target = findEventTarget(target); if (typeof target.onwheel !== 'undefined') { registerWheelEventCallback(target, userData, useCapture, callbackfunc, 9, "wheel", targetThread); return 0; } else { return -1; } } function _emscripten_sleep() { throw 'Please compile your program with async support in order to use asynchronous operations like emscripten_sleep'; } function _emscripten_thread_sleep(msecs) { var start = _emscripten_get_now(); while (_emscripten_get_now() - start < msecs) { // Do nothing. } } var ENV={}; function getExecutableName() { return thisProgram || './this.program'; } function getEnvStrings() { if (!getEnvStrings.strings) { // Default values. // Browser language detection #8751 var lang = ((typeof navigator === 'object' && navigator.languages && navigator.languages[0]) || 'C').replace('-', '_') + '.UTF-8'; var env = { 'USER': 'web_user', 'LOGNAME': 'web_user', 'PATH': '/', 'PWD': '/', 'HOME': '/home/web_user', 'LANG': lang, '_': getExecutableName() }; // Apply the user-provided values, if any. for (var x in ENV) { env[x] = ENV[x]; } var strings = []; for (var x in env) { strings.push(x + '=' + env[x]); } getEnvStrings.strings = strings; } return getEnvStrings.strings; } function _environ_get(__environ, environ_buf) {try { var bufSize = 0; getEnvStrings().forEach(function(string, i) { var ptr = environ_buf + bufSize; HEAP32[(((__environ)+(i * 4))>>2)] = ptr; writeAsciiToMemory(string, ptr); bufSize += string.length + 1; }); return 0; } catch (e) { if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e); return e.errno; } } function _environ_sizes_get(penviron_count, penviron_buf_size) {try { var strings = getEnvStrings(); HEAP32[((penviron_count)>>2)] = strings.length; var bufSize = 0; strings.forEach(function(string) { bufSize += string.length + 1; }); HEAP32[((penviron_buf_size)>>2)] = bufSize; return 0; } catch (e) { if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e); return e.errno; } } function _fd_close(fd) {try { var stream = SYSCALLS.getStreamFromFD(fd); FS.close(stream); return 0; } catch (e) { if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e); return e.errno; } } function _fd_read(fd, iov, iovcnt, pnum) {try { var stream = SYSCALLS.getStreamFromFD(fd); var num = SYSCALLS.doReadv(stream, iov, iovcnt); HEAP32[((pnum)>>2)] = num return 0; } catch (e) { if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e); return e.errno; } } function _fd_seek(fd, offset_low, offset_high, whence, newOffset) {try { var stream = SYSCALLS.getStreamFromFD(fd); var HIGH_OFFSET = 0x100000000; // 2^32 // use an unsigned operator on low and shift high by 32-bits var offset = offset_high * HIGH_OFFSET + (offset_low >>> 0); var DOUBLE_LIMIT = 0x20000000000000; // 2^53 // we also check for equality since DOUBLE_LIMIT + 1 == DOUBLE_LIMIT if (offset <= -DOUBLE_LIMIT || offset >= DOUBLE_LIMIT) { return -61; } FS.llseek(stream, offset, whence); (tempI64 = [stream.position>>>0,(tempDouble=stream.position,(+(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[((newOffset)>>2)] = tempI64[0],HEAP32[(((newOffset)+(4))>>2)] = tempI64[1]); 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); return e.errno; } } function _fd_write(fd, iov, iovcnt, pnum) {try { var stream = SYSCALLS.getStreamFromFD(fd); var num = SYSCALLS.doWritev(stream, iov, iovcnt); HEAP32[((pnum)>>2)] = num return 0; } catch (e) { if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e); return e.errno; } } function _gettimeofday(ptr) { var now = Date.now(); HEAP32[((ptr)>>2)] = (now/1000)|0; // seconds HEAP32[(((ptr)+(4))>>2)] = ((now % 1000)*1000)|0; // microseconds return 0; } function _setTempRet0($i) { setTempRet0(($i) | 0); } function _sigaction(signum, act, oldact) { //int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); return 0; } var __sigalrm_handler=0; function _signal(sig, func) { if (sig == 14) { __sigalrm_handler = func; } else { } return 0; } var readAsmConstArgsArray=[]; function readAsmConstArgs(sigPtr, buf) { readAsmConstArgsArray.length = 0; var ch; // Most arguments are i32s, so shift the buffer pointer so it is a plain // index into HEAP32. buf >>= 2; while (ch = HEAPU8[sigPtr++]) { // A double takes two 32-bit slots, and must also be aligned - the backend // will emit padding to avoid that. var double = ch < 105; if (double && (buf & 1)) buf++; readAsmConstArgsArray.push(double ? HEAPF64[buf++ >> 1] : HEAP32[buf]); ++buf; } return readAsmConstArgsArray; } var FSNode = /** @constructor */ function(parent, name, mode, rdev) { if (!parent) { parent = this; // root node sets parent to itself } this.parent = parent; this.mount = parent.mount; this.mounted = null; this.id = FS.nextInode++; this.name = name; this.mode = mode; this.node_ops = {}; this.stream_ops = {}; this.rdev = rdev; }; var readMode = 292/*292*/ | 73/*73*/; var writeMode = 146/*146*/; Object.defineProperties(FSNode.prototype, { read: { get: /** @this{FSNode} */function() { return (this.mode & readMode) === readMode; }, set: /** @this{FSNode} */function(val) { val ? this.mode |= readMode : this.mode &= ~readMode; } }, write: { get: /** @this{FSNode} */function() { return (this.mode & writeMode) === writeMode; }, set: /** @this{FSNode} */function(val) { val ? this.mode |= writeMode : this.mode &= ~writeMode; } }, isFolder: { get: /** @this{FSNode} */function() { return FS.isDir(this.mode); } }, isDevice: { get: /** @this{FSNode} */function() { return FS.isChrdev(this.mode); } } }); FS.FSNode = FSNode; FS.staticInit();Module["FS_createPath"] = FS.createPath;Module["FS_createDataFile"] = FS.createDataFile;Module["FS_createPreloadedFile"] = FS.createPreloadedFile;Module["FS_createLazyFile"] = FS.createLazyFile;Module["FS_createDevice"] = FS.createDevice;Module["FS_unlink"] = FS.unlink;; Module["requestFullscreen"] = function Module_requestFullscreen(lockPointer, resizeCanvas) { Browser.requestFullscreen(lockPointer, resizeCanvas) }; Module["requestAnimationFrame"] = function Module_requestAnimationFrame(func) { Browser.requestAnimationFrame(func) }; Module["setCanvasSize"] = function Module_setCanvasSize(width, height, noUpdates) { Browser.setCanvasSize(width, height, noUpdates) }; Module["pauseMainLoop"] = function Module_pauseMainLoop() { Browser.mainLoop.pause() }; Module["resumeMainLoop"] = function Module_resumeMainLoop() { Browser.mainLoop.resume() }; Module["getUserMedia"] = function Module_getUserMedia() { Browser.getUserMedia() } Module["createContext"] = function Module_createContext(canvas, useWebGL, setInModule, webGLContextAttributes) { return Browser.createContext(canvas, useWebGL, setInModule, webGLContextAttributes) }; var GLctx;; for (var i = 0; i < 32; ++i) tempFixedLengthArray.push(new Array(i));; var miniTempWebGLFloatBuffersStorage = new Float32Array(288); for (/**@suppress{duplicate}*/var i = 0; i < 288; ++i) { miniTempWebGLFloatBuffers[i] = miniTempWebGLFloatBuffersStorage.subarray(0, i+1); } ; var __miniTempWebGLIntBuffersStorage = new Int32Array(288); for (/**@suppress{duplicate}*/var i = 0; i < 288; ++i) { __miniTempWebGLIntBuffers[i] = __miniTempWebGLIntBuffersStorage.subarray(0, i+1); } ; var ASSERTIONS = false; /** @type {function(string, boolean=, number=)} */ function intArrayFromString(stringy, dontAddNull, length) { 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; } function intArrayToString(array) { var ret = []; for (var i = 0; i < array.length; i++) { var chr = array[i]; if (chr > 0xFF) { if (ASSERTIONS) { assert(false, 'Character code ' + chr + ' (' + String.fromCharCode(chr) + ') at offset ' + i + ' not in 0x00-0xFF.'); } chr &= 0xFF; } ret.push(String.fromCharCode(chr)); } return ret.join(''); } var asmLibraryArg = { "__sys_fcntl64": ___sys_fcntl64, "__sys_ioctl": ___sys_ioctl, "__sys_open": ___sys_open, "clock_gettime": _clock_gettime, "dlclose": _dlclose, "eglBindAPI": _eglBindAPI, "eglChooseConfig": _eglChooseConfig, "eglCreateContext": _eglCreateContext, "eglCreateWindowSurface": _eglCreateWindowSurface, "eglDestroyContext": _eglDestroyContext, "eglDestroySurface": _eglDestroySurface, "eglGetConfigAttrib": _eglGetConfigAttrib, "eglGetDisplay": _eglGetDisplay, "eglGetError": _eglGetError, "eglInitialize": _eglInitialize, "eglMakeCurrent": _eglMakeCurrent, "eglQueryString": _eglQueryString, "eglSwapBuffers": _eglSwapBuffers, "eglSwapInterval": _eglSwapInterval, "eglTerminate": _eglTerminate, "eglWaitGL": _eglWaitGL, "eglWaitNative": _eglWaitNative, "emscripten_asm_const_int": _emscripten_asm_const_int, "emscripten_exit_fullscreen": _emscripten_exit_fullscreen, "emscripten_exit_pointerlock": _emscripten_exit_pointerlock, "emscripten_get_device_pixel_ratio": _emscripten_get_device_pixel_ratio, "emscripten_get_element_css_size": _emscripten_get_element_css_size, "emscripten_get_gamepad_status": _emscripten_get_gamepad_status, "emscripten_get_num_gamepads": _emscripten_get_num_gamepads, "emscripten_glActiveTexture": _emscripten_glActiveTexture, "emscripten_glAttachShader": _emscripten_glAttachShader, "emscripten_glBeginQuery": _emscripten_glBeginQuery, "emscripten_glBeginQueryEXT": _emscripten_glBeginQueryEXT, "emscripten_glBeginTransformFeedback": _emscripten_glBeginTransformFeedback, "emscripten_glBindAttribLocation": _emscripten_glBindAttribLocation, "emscripten_glBindBuffer": _emscripten_glBindBuffer, "emscripten_glBindBufferBase": _emscripten_glBindBufferBase, "emscripten_glBindBufferRange": _emscripten_glBindBufferRange, "emscripten_glBindFramebuffer": _emscripten_glBindFramebuffer, "emscripten_glBindRenderbuffer": _emscripten_glBindRenderbuffer, "emscripten_glBindSampler": _emscripten_glBindSampler, "emscripten_glBindTexture": _emscripten_glBindTexture, "emscripten_glBindTransformFeedback": _emscripten_glBindTransformFeedback, "emscripten_glBindVertexArray": _emscripten_glBindVertexArray, "emscripten_glBindVertexArrayOES": _emscripten_glBindVertexArrayOES, "emscripten_glBlendColor": _emscripten_glBlendColor, "emscripten_glBlendEquation": _emscripten_glBlendEquation, "emscripten_glBlendEquationSeparate": _emscripten_glBlendEquationSeparate, "emscripten_glBlendFunc": _emscripten_glBlendFunc, "emscripten_glBlendFuncSeparate": _emscripten_glBlendFuncSeparate, "emscripten_glBlitFramebuffer": _emscripten_glBlitFramebuffer, "emscripten_glBufferData": _emscripten_glBufferData, "emscripten_glBufferSubData": _emscripten_glBufferSubData, "emscripten_glCheckFramebufferStatus": _emscripten_glCheckFramebufferStatus, "emscripten_glClear": _emscripten_glClear, "emscripten_glClearBufferfi": _emscripten_glClearBufferfi, "emscripten_glClearBufferfv": _emscripten_glClearBufferfv, "emscripten_glClearBufferiv": _emscripten_glClearBufferiv, "emscripten_glClearBufferuiv": _emscripten_glClearBufferuiv, "emscripten_glClearColor": _emscripten_glClearColor, "emscripten_glClearDepthf": _emscripten_glClearDepthf, "emscripten_glClearStencil": _emscripten_glClearStencil, "emscripten_glClientWaitSync": _emscripten_glClientWaitSync, "emscripten_glColorMask": _emscripten_glColorMask, "emscripten_glCompileShader": _emscripten_glCompileShader, "emscripten_glCompressedTexImage2D": _emscripten_glCompressedTexImage2D, "emscripten_glCompressedTexImage3D": _emscripten_glCompressedTexImage3D, "emscripten_glCompressedTexSubImage2D": _emscripten_glCompressedTexSubImage2D, "emscripten_glCompressedTexSubImage3D": _emscripten_glCompressedTexSubImage3D, "emscripten_glCopyBufferSubData": _emscripten_glCopyBufferSubData, "emscripten_glCopyTexImage2D": _emscripten_glCopyTexImage2D, "emscripten_glCopyTexSubImage2D": _emscripten_glCopyTexSubImage2D, "emscripten_glCopyTexSubImage3D": _emscripten_glCopyTexSubImage3D, "emscripten_glCreateProgram": _emscripten_glCreateProgram, "emscripten_glCreateShader": _emscripten_glCreateShader, "emscripten_glCullFace": _emscripten_glCullFace, "emscripten_glDeleteBuffers": _emscripten_glDeleteBuffers, "emscripten_glDeleteFramebuffers": _emscripten_glDeleteFramebuffers, "emscripten_glDeleteProgram": _emscripten_glDeleteProgram, "emscripten_glDeleteQueries": _emscripten_glDeleteQueries, "emscripten_glDeleteQueriesEXT": _emscripten_glDeleteQueriesEXT, "emscripten_glDeleteRenderbuffers": _emscripten_glDeleteRenderbuffers, "emscripten_glDeleteSamplers": _emscripten_glDeleteSamplers, "emscripten_glDeleteShader": _emscripten_glDeleteShader, "emscripten_glDeleteSync": _emscripten_glDeleteSync, "emscripten_glDeleteTextures": _emscripten_glDeleteTextures, "emscripten_glDeleteTransformFeedbacks": _emscripten_glDeleteTransformFeedbacks, "emscripten_glDeleteVertexArrays": _emscripten_glDeleteVertexArrays, "emscripten_glDeleteVertexArraysOES": _emscripten_glDeleteVertexArraysOES, "emscripten_glDepthFunc": _emscripten_glDepthFunc, "emscripten_glDepthMask": _emscripten_glDepthMask, "emscripten_glDepthRangef": _emscripten_glDepthRangef, "emscripten_glDetachShader": _emscripten_glDetachShader, "emscripten_glDisable": _emscripten_glDisable, "emscripten_glDisableVertexAttribArray": _emscripten_glDisableVertexAttribArray, "emscripten_glDrawArrays": _emscripten_glDrawArrays, "emscripten_glDrawArraysInstanced": _emscripten_glDrawArraysInstanced, "emscripten_glDrawArraysInstancedANGLE": _emscripten_glDrawArraysInstancedANGLE, "emscripten_glDrawArraysInstancedARB": _emscripten_glDrawArraysInstancedARB, "emscripten_glDrawArraysInstancedEXT": _emscripten_glDrawArraysInstancedEXT, "emscripten_glDrawArraysInstancedNV": _emscripten_glDrawArraysInstancedNV, "emscripten_glDrawBuffers": _emscripten_glDrawBuffers, "emscripten_glDrawBuffersEXT": _emscripten_glDrawBuffersEXT, "emscripten_glDrawBuffersWEBGL": _emscripten_glDrawBuffersWEBGL, "emscripten_glDrawElements": _emscripten_glDrawElements, "emscripten_glDrawElementsInstanced": _emscripten_glDrawElementsInstanced, "emscripten_glDrawElementsInstancedANGLE": _emscripten_glDrawElementsInstancedANGLE, "emscripten_glDrawElementsInstancedARB": _emscripten_glDrawElementsInstancedARB, "emscripten_glDrawElementsInstancedEXT": _emscripten_glDrawElementsInstancedEXT, "emscripten_glDrawElementsInstancedNV": _emscripten_glDrawElementsInstancedNV, "emscripten_glDrawRangeElements": _emscripten_glDrawRangeElements, "emscripten_glEnable": _emscripten_glEnable, "emscripten_glEnableVertexAttribArray": _emscripten_glEnableVertexAttribArray, "emscripten_glEndQuery": _emscripten_glEndQuery, "emscripten_glEndQueryEXT": _emscripten_glEndQueryEXT, "emscripten_glEndTransformFeedback": _emscripten_glEndTransformFeedback, "emscripten_glFenceSync": _emscripten_glFenceSync, "emscripten_glFinish": _emscripten_glFinish, "emscripten_glFlush": _emscripten_glFlush, "emscripten_glFlushMappedBufferRange": _emscripten_glFlushMappedBufferRange, "emscripten_glFramebufferRenderbuffer": _emscripten_glFramebufferRenderbuffer, "emscripten_glFramebufferTexture2D": _emscripten_glFramebufferTexture2D, "emscripten_glFramebufferTextureLayer": _emscripten_glFramebufferTextureLayer, "emscripten_glFrontFace": _emscripten_glFrontFace, "emscripten_glGenBuffers": _emscripten_glGenBuffers, "emscripten_glGenFramebuffers": _emscripten_glGenFramebuffers, "emscripten_glGenQueries": _emscripten_glGenQueries, "emscripten_glGenQueriesEXT": _emscripten_glGenQueriesEXT, "emscripten_glGenRenderbuffers": _emscripten_glGenRenderbuffers, "emscripten_glGenSamplers": _emscripten_glGenSamplers, "emscripten_glGenTextures": _emscripten_glGenTextures, "emscripten_glGenTransformFeedbacks": _emscripten_glGenTransformFeedbacks, "emscripten_glGenVertexArrays": _emscripten_glGenVertexArrays, "emscripten_glGenVertexArraysOES": _emscripten_glGenVertexArraysOES, "emscripten_glGenerateMipmap": _emscripten_glGenerateMipmap, "emscripten_glGetActiveAttrib": _emscripten_glGetActiveAttrib, "emscripten_glGetActiveUniform": _emscripten_glGetActiveUniform, "emscripten_glGetActiveUniformBlockName": _emscripten_glGetActiveUniformBlockName, "emscripten_glGetActiveUniformBlockiv": _emscripten_glGetActiveUniformBlockiv, "emscripten_glGetActiveUniformsiv": _emscripten_glGetActiveUniformsiv, "emscripten_glGetAttachedShaders": _emscripten_glGetAttachedShaders, "emscripten_glGetAttribLocation": _emscripten_glGetAttribLocation, "emscripten_glGetBooleanv": _emscripten_glGetBooleanv, "emscripten_glGetBufferParameteri64v": _emscripten_glGetBufferParameteri64v, "emscripten_glGetBufferParameteriv": _emscripten_glGetBufferParameteriv, "emscripten_glGetBufferPointerv": _emscripten_glGetBufferPointerv, "emscripten_glGetError": _emscripten_glGetError, "emscripten_glGetFloatv": _emscripten_glGetFloatv, "emscripten_glGetFragDataLocation": _emscripten_glGetFragDataLocation, "emscripten_glGetFramebufferAttachmentParameteriv": _emscripten_glGetFramebufferAttachmentParameteriv, "emscripten_glGetInteger64i_v": _emscripten_glGetInteger64i_v, "emscripten_glGetInteger64v": _emscripten_glGetInteger64v, "emscripten_glGetIntegeri_v": _emscripten_glGetIntegeri_v, "emscripten_glGetIntegerv": _emscripten_glGetIntegerv, "emscripten_glGetInternalformativ": _emscripten_glGetInternalformativ, "emscripten_glGetProgramBinary": _emscripten_glGetProgramBinary, "emscripten_glGetProgramInfoLog": _emscripten_glGetProgramInfoLog, "emscripten_glGetProgramiv": _emscripten_glGetProgramiv, "emscripten_glGetQueryObjecti64vEXT": _emscripten_glGetQueryObjecti64vEXT, "emscripten_glGetQueryObjectivEXT": _emscripten_glGetQueryObjectivEXT, "emscripten_glGetQueryObjectui64vEXT": _emscripten_glGetQueryObjectui64vEXT, "emscripten_glGetQueryObjectuiv": _emscripten_glGetQueryObjectuiv, "emscripten_glGetQueryObjectuivEXT": _emscripten_glGetQueryObjectuivEXT, "emscripten_glGetQueryiv": _emscripten_glGetQueryiv, "emscripten_glGetQueryivEXT": _emscripten_glGetQueryivEXT, "emscripten_glGetRenderbufferParameteriv": _emscripten_glGetRenderbufferParameteriv, "emscripten_glGetSamplerParameterfv": _emscripten_glGetSamplerParameterfv, "emscripten_glGetSamplerParameteriv": _emscripten_glGetSamplerParameteriv, "emscripten_glGetShaderInfoLog": _emscripten_glGetShaderInfoLog, "emscripten_glGetShaderPrecisionFormat": _emscripten_glGetShaderPrecisionFormat, "emscripten_glGetShaderSource": _emscripten_glGetShaderSource, "emscripten_glGetShaderiv": _emscripten_glGetShaderiv, "emscripten_glGetString": _emscripten_glGetString, "emscripten_glGetStringi": _emscripten_glGetStringi, "emscripten_glGetSynciv": _emscripten_glGetSynciv, "emscripten_glGetTexParameterfv": _emscripten_glGetTexParameterfv, "emscripten_glGetTexParameteriv": _emscripten_glGetTexParameteriv, "emscripten_glGetTransformFeedbackVarying": _emscripten_glGetTransformFeedbackVarying, "emscripten_glGetUniformBlockIndex": _emscripten_glGetUniformBlockIndex, "emscripten_glGetUniformIndices": _emscripten_glGetUniformIndices, "emscripten_glGetUniformLocation": _emscripten_glGetUniformLocation, "emscripten_glGetUniformfv": _emscripten_glGetUniformfv, "emscripten_glGetUniformiv": _emscripten_glGetUniformiv, "emscripten_glGetUniformuiv": _emscripten_glGetUniformuiv, "emscripten_glGetVertexAttribIiv": _emscripten_glGetVertexAttribIiv, "emscripten_glGetVertexAttribIuiv": _emscripten_glGetVertexAttribIuiv, "emscripten_glGetVertexAttribPointerv": _emscripten_glGetVertexAttribPointerv, "emscripten_glGetVertexAttribfv": _emscripten_glGetVertexAttribfv, "emscripten_glGetVertexAttribiv": _emscripten_glGetVertexAttribiv, "emscripten_glHint": _emscripten_glHint, "emscripten_glInvalidateFramebuffer": _emscripten_glInvalidateFramebuffer, "emscripten_glInvalidateSubFramebuffer": _emscripten_glInvalidateSubFramebuffer, "emscripten_glIsBuffer": _emscripten_glIsBuffer, "emscripten_glIsEnabled": _emscripten_glIsEnabled, "emscripten_glIsFramebuffer": _emscripten_glIsFramebuffer, "emscripten_glIsProgram": _emscripten_glIsProgram, "emscripten_glIsQuery": _emscripten_glIsQuery, "emscripten_glIsQueryEXT": _emscripten_glIsQueryEXT, "emscripten_glIsRenderbuffer": _emscripten_glIsRenderbuffer, "emscripten_glIsSampler": _emscripten_glIsSampler, "emscripten_glIsShader": _emscripten_glIsShader, "emscripten_glIsSync": _emscripten_glIsSync, "emscripten_glIsTexture": _emscripten_glIsTexture, "emscripten_glIsTransformFeedback": _emscripten_glIsTransformFeedback, "emscripten_glIsVertexArray": _emscripten_glIsVertexArray, "emscripten_glIsVertexArrayOES": _emscripten_glIsVertexArrayOES, "emscripten_glLineWidth": _emscripten_glLineWidth, "emscripten_glLinkProgram": _emscripten_glLinkProgram, "emscripten_glMapBufferRange": _emscripten_glMapBufferRange, "emscripten_glPauseTransformFeedback": _emscripten_glPauseTransformFeedback, "emscripten_glPixelStorei": _emscripten_glPixelStorei, "emscripten_glPolygonOffset": _emscripten_glPolygonOffset, "emscripten_glProgramBinary": _emscripten_glProgramBinary, "emscripten_glProgramParameteri": _emscripten_glProgramParameteri, "emscripten_glQueryCounterEXT": _emscripten_glQueryCounterEXT, "emscripten_glReadBuffer": _emscripten_glReadBuffer, "emscripten_glReadPixels": _emscripten_glReadPixels, "emscripten_glReleaseShaderCompiler": _emscripten_glReleaseShaderCompiler, "emscripten_glRenderbufferStorage": _emscripten_glRenderbufferStorage, "emscripten_glRenderbufferStorageMultisample": _emscripten_glRenderbufferStorageMultisample, "emscripten_glResumeTransformFeedback": _emscripten_glResumeTransformFeedback, "emscripten_glSampleCoverage": _emscripten_glSampleCoverage, "emscripten_glSamplerParameterf": _emscripten_glSamplerParameterf, "emscripten_glSamplerParameterfv": _emscripten_glSamplerParameterfv, "emscripten_glSamplerParameteri": _emscripten_glSamplerParameteri, "emscripten_glSamplerParameteriv": _emscripten_glSamplerParameteriv, "emscripten_glScissor": _emscripten_glScissor, "emscripten_glShaderBinary": _emscripten_glShaderBinary, "emscripten_glShaderSource": _emscripten_glShaderSource, "emscripten_glStencilFunc": _emscripten_glStencilFunc, "emscripten_glStencilFuncSeparate": _emscripten_glStencilFuncSeparate, "emscripten_glStencilMask": _emscripten_glStencilMask, "emscripten_glStencilMaskSeparate": _emscripten_glStencilMaskSeparate, "emscripten_glStencilOp": _emscripten_glStencilOp, "emscripten_glStencilOpSeparate": _emscripten_glStencilOpSeparate, "emscripten_glTexImage2D": _emscripten_glTexImage2D, "emscripten_glTexImage3D": _emscripten_glTexImage3D, "emscripten_glTexParameterf": _emscripten_glTexParameterf, "emscripten_glTexParameterfv": _emscripten_glTexParameterfv, "emscripten_glTexParameteri": _emscripten_glTexParameteri, "emscripten_glTexParameteriv": _emscripten_glTexParameteriv, "emscripten_glTexStorage2D": _emscripten_glTexStorage2D, "emscripten_glTexStorage3D": _emscripten_glTexStorage3D, "emscripten_glTexSubImage2D": _emscripten_glTexSubImage2D, "emscripten_glTexSubImage3D": _emscripten_glTexSubImage3D, "emscripten_glTransformFeedbackVaryings": _emscripten_glTransformFeedbackVaryings, "emscripten_glUniform1f": _emscripten_glUniform1f, "emscripten_glUniform1fv": _emscripten_glUniform1fv, "emscripten_glUniform1i": _emscripten_glUniform1i, "emscripten_glUniform1iv": _emscripten_glUniform1iv, "emscripten_glUniform1ui": _emscripten_glUniform1ui, "emscripten_glUniform1uiv": _emscripten_glUniform1uiv, "emscripten_glUniform2f": _emscripten_glUniform2f, "emscripten_glUniform2fv": _emscripten_glUniform2fv, "emscripten_glUniform2i": _emscripten_glUniform2i, "emscripten_glUniform2iv": _emscripten_glUniform2iv, "emscripten_glUniform2ui": _emscripten_glUniform2ui, "emscripten_glUniform2uiv": _emscripten_glUniform2uiv, "emscripten_glUniform3f": _emscripten_glUniform3f, "emscripten_glUniform3fv": _emscripten_glUniform3fv, "emscripten_glUniform3i": _emscripten_glUniform3i, "emscripten_glUniform3iv": _emscripten_glUniform3iv, "emscripten_glUniform3ui": _emscripten_glUniform3ui, "emscripten_glUniform3uiv": _emscripten_glUniform3uiv, "emscripten_glUniform4f": _emscripten_glUniform4f, "emscripten_glUniform4fv": _emscripten_glUniform4fv, "emscripten_glUniform4i": _emscripten_glUniform4i, "emscripten_glUniform4iv": _emscripten_glUniform4iv, "emscripten_glUniform4ui": _emscripten_glUniform4ui, "emscripten_glUniform4uiv": _emscripten_glUniform4uiv, "emscripten_glUniformBlockBinding": _emscripten_glUniformBlockBinding, "emscripten_glUniformMatrix2fv": _emscripten_glUniformMatrix2fv, "emscripten_glUniformMatrix2x3fv": _emscripten_glUniformMatrix2x3fv, "emscripten_glUniformMatrix2x4fv": _emscripten_glUniformMatrix2x4fv, "emscripten_glUniformMatrix3fv": _emscripten_glUniformMatrix3fv, "emscripten_glUniformMatrix3x2fv": _emscripten_glUniformMatrix3x2fv, "emscripten_glUniformMatrix3x4fv": _emscripten_glUniformMatrix3x4fv, "emscripten_glUniformMatrix4fv": _emscripten_glUniformMatrix4fv, "emscripten_glUniformMatrix4x2fv": _emscripten_glUniformMatrix4x2fv, "emscripten_glUniformMatrix4x3fv": _emscripten_glUniformMatrix4x3fv, "emscripten_glUnmapBuffer": _emscripten_glUnmapBuffer, "emscripten_glUseProgram": _emscripten_glUseProgram, "emscripten_glValidateProgram": _emscripten_glValidateProgram, "emscripten_glVertexAttrib1f": _emscripten_glVertexAttrib1f, "emscripten_glVertexAttrib1fv": _emscripten_glVertexAttrib1fv, "emscripten_glVertexAttrib2f": _emscripten_glVertexAttrib2f, "emscripten_glVertexAttrib2fv": _emscripten_glVertexAttrib2fv, "emscripten_glVertexAttrib3f": _emscripten_glVertexAttrib3f, "emscripten_glVertexAttrib3fv": _emscripten_glVertexAttrib3fv, "emscripten_glVertexAttrib4f": _emscripten_glVertexAttrib4f, "emscripten_glVertexAttrib4fv": _emscripten_glVertexAttrib4fv, "emscripten_glVertexAttribDivisor": _emscripten_glVertexAttribDivisor, "emscripten_glVertexAttribDivisorANGLE": _emscripten_glVertexAttribDivisorANGLE, "emscripten_glVertexAttribDivisorARB": _emscripten_glVertexAttribDivisorARB, "emscripten_glVertexAttribDivisorEXT": _emscripten_glVertexAttribDivisorEXT, "emscripten_glVertexAttribDivisorNV": _emscripten_glVertexAttribDivisorNV, "emscripten_glVertexAttribI4i": _emscripten_glVertexAttribI4i, "emscripten_glVertexAttribI4iv": _emscripten_glVertexAttribI4iv, "emscripten_glVertexAttribI4ui": _emscripten_glVertexAttribI4ui, "emscripten_glVertexAttribI4uiv": _emscripten_glVertexAttribI4uiv, "emscripten_glVertexAttribIPointer": _emscripten_glVertexAttribIPointer, "emscripten_glVertexAttribPointer": _emscripten_glVertexAttribPointer, "emscripten_glViewport": _emscripten_glViewport, "emscripten_glWaitSync": _emscripten_glWaitSync, "emscripten_has_asyncify": _emscripten_has_asyncify, "emscripten_memcpy_big": _emscripten_memcpy_big, "emscripten_request_fullscreen_strategy": _emscripten_request_fullscreen_strategy, "emscripten_request_pointerlock": _emscripten_request_pointerlock, "emscripten_resize_heap": _emscripten_resize_heap, "emscripten_sample_gamepad_data": _emscripten_sample_gamepad_data, "emscripten_set_beforeunload_callback_on_thread": _emscripten_set_beforeunload_callback_on_thread, "emscripten_set_blur_callback_on_thread": _emscripten_set_blur_callback_on_thread, "emscripten_set_canvas_element_size": _emscripten_set_canvas_element_size, "emscripten_set_element_css_size": _emscripten_set_element_css_size, "emscripten_set_focus_callback_on_thread": _emscripten_set_focus_callback_on_thread, "emscripten_set_fullscreenchange_callback_on_thread": _emscripten_set_fullscreenchange_callback_on_thread, "emscripten_set_gamepadconnected_callback_on_thread": _emscripten_set_gamepadconnected_callback_on_thread, "emscripten_set_gamepaddisconnected_callback_on_thread": _emscripten_set_gamepaddisconnected_callback_on_thread, "emscripten_set_keydown_callback_on_thread": _emscripten_set_keydown_callback_on_thread, "emscripten_set_keypress_callback_on_thread": _emscripten_set_keypress_callback_on_thread, "emscripten_set_keyup_callback_on_thread": _emscripten_set_keyup_callback_on_thread, "emscripten_set_mousedown_callback_on_thread": _emscripten_set_mousedown_callback_on_thread, "emscripten_set_mouseenter_callback_on_thread": _emscripten_set_mouseenter_callback_on_thread, "emscripten_set_mouseleave_callback_on_thread": _emscripten_set_mouseleave_callback_on_thread, "emscripten_set_mousemove_callback_on_thread": _emscripten_set_mousemove_callback_on_thread, "emscripten_set_mouseup_callback_on_thread": _emscripten_set_mouseup_callback_on_thread, "emscripten_set_pointerlockchange_callback_on_thread": _emscripten_set_pointerlockchange_callback_on_thread, "emscripten_set_resize_callback_on_thread": _emscripten_set_resize_callback_on_thread, "emscripten_set_touchcancel_callback_on_thread": _emscripten_set_touchcancel_callback_on_thread, "emscripten_set_touchend_callback_on_thread": _emscripten_set_touchend_callback_on_thread, "emscripten_set_touchmove_callback_on_thread": _emscripten_set_touchmove_callback_on_thread, "emscripten_set_touchstart_callback_on_thread": _emscripten_set_touchstart_callback_on_thread, "emscripten_set_visibilitychange_callback_on_thread": _emscripten_set_visibilitychange_callback_on_thread, "emscripten_set_wheel_callback_on_thread": _emscripten_set_wheel_callback_on_thread, "emscripten_sleep": _emscripten_sleep, "emscripten_thread_sleep": _emscripten_thread_sleep, "environ_get": _environ_get, "environ_sizes_get": _environ_sizes_get, "exit": _exit, "fd_close": _fd_close, "fd_read": _fd_read, "fd_seek": _fd_seek, "fd_write": _fd_write, "gettimeofday": _gettimeofday, "ma": ma, "setTempRet0": _setTempRet0, "sigaction": _sigaction, "signal": _signal }; var asm = createWasm(); /** @type {function(...*):?} */ var ___wasm_call_ctors = Module["___wasm_call_ctors"] = function() { return (___wasm_call_ctors = Module["___wasm_call_ctors"] = Module["asm"]["__wasm_call_ctors"]).apply(null, arguments); }; /** @type {function(...*):?} */ var _pl = Module["_pl"] = function() { return (_pl = Module["_pl"] = Module["asm"]["pl"]).apply(null, arguments); }; /** @type {function(...*):?} */ var _main = Module["_main"] = function() { return (_main = Module["_main"] = Module["asm"]["main"]).apply(null, arguments); }; /** @type {function(...*):?} */ var _free = Module["_free"] = function() { return (_free = Module["_free"] = Module["asm"]["free"]).apply(null, arguments); }; /** @type {function(...*):?} */ var _malloc = Module["_malloc"] = function() { return (_malloc = Module["_malloc"] = Module["asm"]["malloc"]).apply(null, arguments); }; /** @type {function(...*):?} */ var ___errno_location = Module["___errno_location"] = function() { return (___errno_location = Module["___errno_location"] = Module["asm"]["__errno_location"]).apply(null, arguments); }; /** @type {function(...*):?} */ var _memcpy = Module["_memcpy"] = function() { return (_memcpy = Module["_memcpy"] = Module["asm"]["memcpy"]).apply(null, arguments); }; /** @type {function(...*):?} */ var _memset = Module["_memset"] = function() { return (_memset = Module["_memset"] = Module["asm"]["memset"]).apply(null, arguments); }; /** @type {function(...*):?} */ var stackSave = Module["stackSave"] = function() { return (stackSave = Module["stackSave"] = Module["asm"]["stackSave"]).apply(null, arguments); }; /** @type {function(...*):?} */ var stackRestore = Module["stackRestore"] = function() { return (stackRestore = Module["stackRestore"] = Module["asm"]["stackRestore"]).apply(null, arguments); }; /** @type {function(...*):?} */ var stackAlloc = Module["stackAlloc"] = function() { return (stackAlloc = Module["stackAlloc"] = Module["asm"]["stackAlloc"]).apply(null, arguments); }; /** @type {function(...*):?} */ var dynCall_jiji = Module["dynCall_jiji"] = function() { return (dynCall_jiji = Module["dynCall_jiji"] = Module["asm"]["dynCall_jiji"]).apply(null, arguments); }; /** @type {function(...*):?} */ var dynCall_ji = Module["dynCall_ji"] = function() { return (dynCall_ji = Module["dynCall_ji"] = Module["asm"]["dynCall_ji"]).apply(null, arguments); }; /** @type {function(...*):?} */ var dynCall_iijjiiii = Module["dynCall_iijjiiii"] = function() { return (dynCall_iijjiiii = Module["dynCall_iijjiiii"] = Module["asm"]["dynCall_iijjiiii"]).apply(null, arguments); }; // === Auto-generated postamble setup entry stuff === Module["ccall"] = ccall; Module["addRunDependency"] = addRunDependency; Module["removeRunDependency"] = removeRunDependency; Module["FS_createPath"] = FS.createPath; Module["FS_createDataFile"] = FS.createDataFile; Module["FS_createPreloadedFile"] = FS.createPreloadedFile; Module["FS_createLazyFile"] = FS.createLazyFile; Module["FS_createDevice"] = FS.createDevice; Module["FS_unlink"] = FS.unlink; var calledRun; /** * @constructor * @this {ExitStatus} */ function ExitStatus(status) { this.name = "ExitStatus"; this.message = "Program terminated with exit(" + status + ")"; this.status = status; } 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 (!calledRun) run(); if (!calledRun) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled }; function callMain(args) { var entryFunction = Module['_main']; var argc = 0; var argv = 0; try { var ret = entryFunction(argc, argv); // In PROXY_TO_PTHREAD builds, we should never exit the runtime below, as // execution is asynchronously handed off to a pthread. // 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; } else if (e == 'unwind') { // running an evented main loop, don't immediately exit return; } else { var toLog = e; if (e && typeof e === 'object' && e.stack) { toLog = [e, e.stack]; } err('exception thrown: ' + toLog); quit_(1, e); } } finally { calledMain = true; } } /** @type {function(Array=)} */ function run(args) { args = args || arguments_; if (runDependencies > 0) { return; } preRun(); // a preRun added a dependency, run will be called later if (runDependencies > 0) { return; } function doRun() { // run may have just been called through dependencies being fulfilled just in this very frame, // or while the async setStatus time below was happening if (calledRun) return; calledRun = true; Module['calledRun'] = true; if (ABORT) return; initRuntime(); preMain(); if (Module['onRuntimeInitialized']) Module['onRuntimeInitialized'](); if (shouldRunNow) callMain(args); postRun(); } if (Module['setStatus']) { Module['setStatus']('Running...'); setTimeout(function() { setTimeout(function() { Module['setStatus'](''); }, 1); doRun(); }, 1); } else { doRun(); } } Module['run'] = run; /** @param {boolean|number=} implicit */ function exit(status, implicit) { EXITSTATUS = status; // if this is just main exit-ing implicitly, and the status is 0, then we // don't need to do anything here and can just leave. if the status is // non-zero, though, then we need to report it. // (we may have warned about this earlier, if a situation justifies doing so) if (implicit && keepRuntimeAlive() && status === 0) { return; } if (keepRuntimeAlive()) { } else { exitRuntime(); if (Module['onExit']) Module['onExit'](status); ABORT = true; } quit_(status, new ExitStatus(status)); } if (Module['preInit']) { if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']]; while (Module['preInit'].length > 0) { Module['preInit'].pop()(); } } // shouldRunNow refers to calling main(), not run(). var shouldRunNow = true; if (Module['noInitialRun']) shouldRunNow = false; run(); let fll=new BroadcastChannel('file'); fll.addEventListener('message',ea=> { let fill=new Uint8Array(ea.data.data); FS.writeFile('/snd/sample.wav',fill); Module.ccall("pl"); }); document.getElementById('btn3').addEventListener('click',function(){ window.open('https://test.1ink.us/libflac.js/'); }); /** * gpu.js * http://gpu.rocks/ * * GPU Accelerated JavaScript * * @version 2.11.3 * @date Wed Apr 14 2021 16:49:13 GMT-0400 (Eastern Daylight Time) * * @license MIT * The MIT License * * Copyright (c) 2021 gpu.js Team */(function(f){ if(typeof exports === "object" && typeof module !== "undefined"){module.exports = f();}else if(typeof define === "function" && define.amd){define([],f);}else{ var g; if(typeof window !== "undefined"){g = window;}else if(typeof global !== "undefined"){g = global;}else if(typeof self !== "undefined"){g = self;}else{g = this;} g.GPU = f(); } })(function(){ var define,module,exports; return (function(){ function r(e,n,t){ function o(i,f){ if(!n[i]){ if(!e[i]){ var c = "function" == typeof require && require; if(!f && c){ return c(i,!0); } if(u){ return u(i,!0); } var a = new Error("Cannot find module '" + i + "'"); throw a.code = "MODULE_NOT_FOUND", a; } var p = n[i] = {exports:{}}; e[i][0].call(p.exports,function(r){ var n = e[i][1][r]; return o(n || r); },p,p.exports,r,e,n,t); } return n[i].exports; } for(var u = "function" == typeof require && require,i = 0; i < t.length; i ++) o(t[i]); return o; } return r; })()({ 1:[function(require,module,exports){ (function(global,factory){ typeof exports === 'object' && typeof module !== 'undefined'?factory(exports):typeof define === 'function' && define.amd?define(['exports'],factory):(global = global || self, factory(global.acorn = {})); }(this,function(exports){ 'use strict'; var reservedWords = { 3:"abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile",5:"class enum extends super const export import",6:"enum",strict:"implements interface let package private protected public static yield",strictBind:"eval arguments" }; var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"; var keywords = { 5:ecma5AndLessKeywords,"5module":ecma5AndLessKeywords + " export import",6:ecma5AndLessKeywords + " const class extends export import super" }; var keywordRelationalOperator = /^in(stanceof)?$/; var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u08a0-\u08b4\u08b6-\u08bd\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fef\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7bf\ua7c2-\ua7c6\ua7f7-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab67\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc"; var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08d3-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1df9\u1dfb-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f"; var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); nonASCIIidentifierStartChars = nonASCIIidentifierChars = null; var astralIdentifierStartCodes = [0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,14,29,6,37,11,29,3,35,5,7,2,4,43,157,19,35,5,35,5,39,9,51,157,310,10,21,11,7,153,5,3,0,2,43,2,1,4,0,3,22,11,22,10,30,66,18,2,1,11,21,11,25,71,55,7,1,65,0,16,3,2,2,2,28,43,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,56,50,14,50,14,35,477,28,11,0,9,21,155,22,13,52,76,44,33,24,27,35,30,0,12,34,4,0,13,47,15,3,22,0,2,0,36,17,2,24,85,6,2,0,2,3,2,14,2,9,8,46,39,7,3,1,3,21,2,6,2,1,2,4,4,0,19,0,13,4,159,52,19,3,21,0,33,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,14,0,72,26,230,43,117,63,32,0,161,7,3,38,17,0,2,0,29,0,11,39,8,0,22,0,12,45,20,0,35,56,264,8,2,36,18,0,50,29,113,6,2,1,2,37,22,0,26,5,2,1,2,31,15,0,328,18,270,921,103,110,18,195,2749,1070,4050,582,8634,568,8,30,114,29,19,47,17,3,32,20,6,18,689,63,129,74,6,0,67,12,65,1,2,0,29,6135,9,754,9486,286,50,2,18,3,9,395,2309,106,6,12,4,8,8,9,5991,84,2,70,2,1,3,0,3,1,3,3,2,11,2,0,2,6,2,64,2,3,3,7,2,6,2,27,2,3,2,4,2,0,4,6,2,339,3,24,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,7,2357,44,11,6,17,0,370,43,1301,196,60,67,8,0,1205,3,2,26,2,1,2,0,3,0,2,9,2,3,2,0,2,0,7,0,5,0,2,0,2,0,2,2,2,1,2,0,3,0,2,0,2,0,2,0,2,0,2,1,2,0,3,3,2,6,2,3,2,3,2,0,2,9,2,16,6,2,2,4,2,16,4421,42710,42,4148,12,221,3,5761,15,7472,3104,541]; var astralIdentifierCodes = [509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,574,3,9,9,525,10,176,2,54,14,32,9,16,3,46,10,54,9,7,2,37,13,2,9,6,1,45,0,13,2,49,13,9,3,4,9,83,11,7,0,161,11,6,9,7,3,56,1,2,6,3,1,3,2,10,0,11,1,3,6,4,4,193,17,10,9,5,0,82,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,84,14,5,9,243,14,166,9,232,6,3,6,4,0,29,9,41,6,2,3,9,0,10,10,47,15,406,7,2,7,17,9,57,21,2,13,123,5,4,0,2,1,2,6,2,0,9,9,49,4,2,1,2,4,9,9,330,3,19306,9,135,4,60,6,26,9,1014,0,2,54,8,3,19723,1,5319,4,4,5,9,7,3,6,31,3,149,2,1418,49,513,54,5,49,9,0,15,0,23,4,2,14,1361,6,2,16,3,6,2,1,2,4,262,6,10,9,419,13,1495,6,110,6,6,9,792487,239]; function isInAstralSet(code,set){ var pos = 0x10000; for(var i = 0; i < set.length; i += 2){ pos += set[i]; if(pos > code){ return false; } pos += set[i + 1]; if(pos >= code){ return true; } } } function isIdentifierStart(code,astral){ if(code < 65){ return code === 36; } if(code < 91){ return true; } if(code < 97){ return code === 95; } if(code < 123){ return true; } if(code <= 0xffff){ return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)); } if(astral === false){ return false; } return isInAstralSet(code,astralIdentifierStartCodes); } function isIdentifierChar(code,astral){ if(code < 48){ return code === 36; } if(code < 58){ return true; } if(code < 65){ return false; } if(code < 91){ return true; } if(code < 97){ return code === 95; } if(code < 123){ return true; } if(code <= 0xffff){ return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)); } if(astral === false){ return false; } return isInAstralSet(code,astralIdentifierStartCodes) || isInAstralSet(code,astralIdentifierCodes); } var TokenType = function TokenType(label,conf){ if(conf === void 0){ conf = {}; } this.label = label; this.keyword = conf.keyword; this.beforeExpr = !!conf.beforeExpr; this.startsExpr = !!conf.startsExpr; this.isLoop = !!conf.isLoop; this.isAssign = !!conf.isAssign; this.prefix = !!conf.prefix; this.postfix = !!conf.postfix; this.binop = conf.binop || null; this.updateContext = null; }; function binop(name,prec){ return new TokenType(name,{beforeExpr:true,binop:prec}); } var beforeExpr = {beforeExpr:true},startsExpr = {startsExpr:true}; var keywords$1 = {}; function kw(name,options){ if(options === void 0){ options = {}; } options.keyword = name; return keywords$1[name] = new TokenType(name,options); } var types = { num:new TokenType("num",startsExpr),regexp:new TokenType("regexp",startsExpr),string:new TokenType("string",startsExpr),name:new TokenType("name",startsExpr),eof:new TokenType("eof"),bracketL:new TokenType("[",{beforeExpr:true,startsExpr:true}),bracketR:new TokenType("]"),braceL:new TokenType("{",{beforeExpr:true,startsExpr:true}),braceR:new TokenType("}"),parenL:new TokenType("(",{beforeExpr:true,startsExpr:true}),parenR:new TokenType(")"),comma:new TokenType(",",beforeExpr),semi:new TokenType(";",beforeExpr),colon:new TokenType(":",beforeExpr),dot:new TokenType("."),question:new TokenType("?",beforeExpr),arrow:new TokenType("=>",beforeExpr),template:new TokenType("template"),invalidTemplate:new TokenType("invalidTemplate"),ellipsis:new TokenType("...",beforeExpr),backQuote:new TokenType("`",startsExpr),dollarBraceL:new TokenType("${",{beforeExpr:true,startsExpr:true}),eq:new TokenType("=",{beforeExpr:true,isAssign:true}),assign:new TokenType("_=",{beforeExpr:true,isAssign:true}),incDec:new TokenType("++/--",{prefix:true,postfix:true,startsExpr:true}),prefix:new TokenType("!/~",{beforeExpr:true,prefix:true,startsExpr:true}),logicalOR:binop("||",1),logicalAND:binop("&&",2),bitwiseOR:binop("|",3),bitwiseXOR:binop("^",4),bitwiseAND:binop("&",5),equality:binop("==/!=/===/!==",6),relational:binop("/<=/>=",7),bitShift:binop("<>/>>>",8),plusMin:new TokenType("+/-",{beforeExpr:true,binop:9,prefix:true,startsExpr:true}),modulo:binop("%",10),star:binop("*",10),slash:binop("/",10),starstar:new TokenType("**",{beforeExpr:true}),_break:kw("break"),_case:kw("case",beforeExpr),_catch:kw("catch"),_continue:kw("continue"),_debugger:kw("debugger"),_default:kw("default",beforeExpr),_do:kw("do",{isLoop:true,beforeExpr:true}),_else:kw("else",beforeExpr),_finally:kw("finally"),_for:kw("for",{isLoop:true}),_function:kw("function",startsExpr),_if:kw("if"),_return:kw("return",beforeExpr),_switch:kw("switch"),_throw:kw("throw",beforeExpr),_try:kw("try"),_var:kw("var"),_const:kw("const"),_while:kw("while",{isLoop:true}),_with:kw("with"),_new:kw("new",{beforeExpr:true,startsExpr:true}),_this:kw("this",startsExpr),_super:kw("super",startsExpr),_class:kw("class",startsExpr),_extends:kw("extends",beforeExpr),_export:kw("export"),_import:kw("import",startsExpr),_null:kw("null",startsExpr),_true:kw("true",startsExpr),_false:kw("false",startsExpr),_in:kw("in",{beforeExpr:true,binop:7}),_instanceof:kw("instanceof",{beforeExpr:true,binop:7}),_typeof:kw("typeof",{beforeExpr:true,prefix:true,startsExpr:true}),_void:kw("void",{beforeExpr:true,prefix:true,startsExpr:true}),_delete:kw("delete",{beforeExpr:true,prefix:true,startsExpr:true}) }; var lineBreak = /\r\n?|\n|\u2028|\u2029/; var lineBreakG = new RegExp(lineBreak.source,"g"); function isNewLine(code,ecma2019String){ return code === 10 || code === 13 || (!ecma2019String && (code === 0x2028 || code === 0x2029)); } var nonASCIIwhitespace = /[\u1680\u2000-\u200a\u202f\u205f\u3000\ufeff]/; var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g; var ref = Object.prototype; var hasOwnProperty = ref.hasOwnProperty; var toString = ref.toString; function has(obj,propName){ return hasOwnProperty.call(obj,propName); } var isArray = Array.isArray || (function(obj){ return (toString.call(obj) === "[object Array]"); }); function wordsRegexp(words){ return new RegExp("^(?:" + words.replace(/ /g,"|") + ")$"); } var Position = function Position(line,col){ this.line = line; this.column = col; }; Position.prototype.offset = function offset(n){ return new Position(this.line,this.column + n); }; var SourceLocation = function SourceLocation(p,start,end){ this.start = start; this.end = end; if(p.sourceFile !== null){ this.source = p.sourceFile; } }; function getLineInfo(input,offset){ for(var line = 1,cur = 0; ;){ lineBreakG.lastIndex = cur; var match = lineBreakG.exec(input); if(match && match.index < offset){ ++ line; cur = match.index + match[0].length; }else{ return new Position(line,offset - cur); } } } var defaultOptions = { ecmaVersion:10,sourceType:"script",onInsertedSemicolon:null,onTrailingComma:null,allowReserved:null,allowReturnOutsideFunction:false,allowImportExportEverywhere:false,allowAwaitOutsideFunction:false,allowHashBang:false,locations:false,onToken:null,onComment:null,ranges:false,program:null,sourceFile:null,directSourceFile:null,preserveParens:false }; function getOptions(opts){ var options = {}; for(var opt in defaultOptions){ options[opt] = opts && has(opts,opt)?opts[opt]:defaultOptions[opt]; } if(options.ecmaVersion >= 2015){ options.ecmaVersion -= 2009; } if(options.allowReserved == null){ options.allowReserved = options.ecmaVersion < 5; } if(isArray(options.onToken)){ var tokens = options.onToken; options.onToken = function(token){ return tokens.push(token); }; } if(isArray(options.onComment)){ options.onComment = pushComment(options,options.onComment); } return options; } function pushComment(options,array){ return function(block,text,start,end,startLoc,endLoc){ var comment = { type:block?"Block":"Line",value:text,start:start,end:end }; if(options.locations){ comment.loc = new SourceLocation(this,startLoc,endLoc); } if(options.ranges){ comment.range = [start,end]; } array.push(comment); }; } var SCOPE_TOP = 1,SCOPE_FUNCTION = 2,SCOPE_VAR = SCOPE_TOP | SCOPE_FUNCTION,SCOPE_ASYNC = 4,SCOPE_GENERATOR = 8,SCOPE_ARROW = 16,SCOPE_SIMPLE_CATCH = 32,SCOPE_SUPER = 64,SCOPE_DIRECT_SUPER = 128; function functionFlags(async,generator){ return SCOPE_FUNCTION | (async?SCOPE_ASYNC:0) | (generator?SCOPE_GENERATOR:0); } var BIND_NONE = 0,BIND_VAR = 1,BIND_LEXICAL = 2,BIND_FUNCTION = 3,BIND_SIMPLE_CATCH = 4,BIND_OUTSIDE = 5; var Parser = function Parser(options,input,startPos){ this.options = options = getOptions(options); this.sourceFile = options.sourceFile; this.keywords = wordsRegexp(keywords[options.ecmaVersion >= 6?6:options.sourceType === "module"?"5module":5]); var reserved = ""; if(options.allowReserved !== true){ for(var v = options.ecmaVersion; ; v --){ if(reserved = reservedWords[v]){ break; } } if(options.sourceType === "module"){ reserved += " await"; } } this.reservedWords = wordsRegexp(reserved); var reservedStrict = (reserved?reserved + " ":"") + reservedWords.strict; this.reservedWordsStrict = wordsRegexp(reservedStrict); this.reservedWordsStrictBind = wordsRegexp(reservedStrict + " " + reservedWords.strictBind); this.input = String(input); this.containsEsc = false; if(startPos){ this.pos = startPos; this.lineStart = this.input.lastIndexOf("\n",startPos - 1) + 1; this.curLine = this.input.slice(0,this.lineStart).split(lineBreak).length; }else{ this.pos = this.lineStart = 0; this.curLine = 1; } this.type = types.eof; this.value = null; this.start = this.end = this.pos; this.startLoc = this.endLoc = this.curPosition(); this.lastTokEndLoc = this.lastTokStartLoc = null; this.lastTokStart = this.lastTokEnd = this.pos; this.context = this.initialContext(); this.exprAllowed = true; this.inModule = options.sourceType === "module"; this.strict = this.inModule || this.strictDirective(this.pos); this.potentialArrowAt = - 1; this.yieldPos = this.awaitPos = this.awaitIdentPos = 0; this.labels = []; this.undefinedExports = {}; if(this.pos === 0 && options.allowHashBang && this.input.slice(0,2) === "#!"){ this.skipLineComment(2); } this.scopeStack = []; this.enterScope(SCOPE_TOP); this.regexpState = null; }; var prototypeAccessors = {inFunction:{configurable:true},inGenerator:{configurable:true},inAsync:{configurable:true},allowSuper:{configurable:true},allowDirectSuper:{configurable:true},treatFunctionsAsVar:{configurable:true}}; Parser.prototype.parse = function parse(){ var node = this.options.program || this.startNode(); this.nextToken(); return this.parseTopLevel(node); }; prototypeAccessors.inFunction.get = function(){ return (this.currentVarScope().flags & SCOPE_FUNCTION) > 0; }; prototypeAccessors.inGenerator.get = function(){ return (this.currentVarScope().flags & SCOPE_GENERATOR) > 0; }; prototypeAccessors.inAsync.get = function(){ return (this.currentVarScope().flags & SCOPE_ASYNC) > 0; }; prototypeAccessors.allowSuper.get = function(){ return (this.currentThisScope().flags & SCOPE_SUPER) > 0; }; prototypeAccessors.allowDirectSuper.get = function(){ return (this.currentThisScope().flags & SCOPE_DIRECT_SUPER) > 0; }; prototypeAccessors.treatFunctionsAsVar.get = function(){ return this.treatFunctionsAsVarInScope(this.currentScope()); }; Parser.prototype.inNonArrowFunction = function inNonArrowFunction(){ return (this.currentThisScope().flags & SCOPE_FUNCTION) > 0; }; Parser.extend = function extend(){ var plugins = [],len = arguments.length; while(len --) plugins[len] = arguments[len]; var cls = this; for(var i = 0; i < plugins.length; i ++){ cls = plugins[i](cls); } return cls; }; Parser.parse = function parse(input,options){ return new this(options,input).parse(); }; Parser.parseExpressionAt = function parseExpressionAt(input,pos,options){ var parser = new this(options,input,pos); parser.nextToken(); return parser.parseExpression(); }; Parser.tokenizer = function tokenizer(input,options){ return new this(options,input); }; Object.defineProperties(Parser.prototype,prototypeAccessors); var pp = Parser.prototype; var literal = /^(?:'((?:\\.|[^'])*?)'|"((?:\\.|[^"])*?)")/; pp.strictDirective = function(start){ for(; ;){ skipWhiteSpace.lastIndex = start; start += skipWhiteSpace.exec(this.input)[0].length; var match = literal.exec(this.input.slice(start)); if(!match){ return false; } if((match[1] || match[2]) === "use strict"){ return true; } start += match[0].length; skipWhiteSpace.lastIndex = start; start += skipWhiteSpace.exec(this.input)[0].length; if(this.input[start] === ";"){ start ++; } } }; pp.eat = function(type){ if(this.type === type){ this.next(); return true; }else{ return false; } }; pp.isContextual = function(name){ return this.type === types.name && this.value === name && !this.containsEsc; }; pp.eatContextual = function(name){ if(!this.isContextual(name)){ return false; } this.next(); return true; }; pp.expectContextual = function(name){ if(!this.eatContextual(name)){ this.unexpected(); } }; pp.canInsertSemicolon = function(){ return this.type === types.eof || this.type === types.braceR || lineBreak.test(this.input.slice(this.lastTokEnd,this.start)); }; pp.insertSemicolon = function(){ if(this.canInsertSemicolon()){ if(this.options.onInsertedSemicolon){ this.options.onInsertedSemicolon(this.lastTokEnd,this.lastTokEndLoc); } return true; } }; pp.semicolon = function(){ if(!this.eat(types.semi) && !this.insertSemicolon()){ this.unexpected(); } }; pp.afterTrailingComma = function(tokType,notNext){ if(this.type === tokType){ if(this.options.onTrailingComma){ this.options.onTrailingComma(this.lastTokStart,this.lastTokStartLoc); } if(!notNext){ this.next(); } return true; } }; pp.expect = function(type){ this.eat(type) || this.unexpected(); }; pp.unexpected = function(pos){ this.raise(pos != null?pos:this.start,"Unexpected token"); }; function DestructuringErrors(){ this.shorthandAssign = this.trailingComma = this.parenthesizedAssign = this.parenthesizedBind = this.doubleProto = - 1; } pp.checkPatternErrors = function(refDestructuringErrors,isAssign){ if(!refDestructuringErrors){ return; } if(refDestructuringErrors.trailingComma > - 1){ this.raiseRecoverable(refDestructuringErrors.trailingComma,"Comma is not permitted after the rest element"); } var parens = isAssign?refDestructuringErrors.parenthesizedAssign:refDestructuringErrors.parenthesizedBind; if(parens > - 1){ this.raiseRecoverable(parens,"Parenthesized pattern"); } }; pp.checkExpressionErrors = function(refDestructuringErrors,andThrow){ if(!refDestructuringErrors){ return false; } var shorthandAssign = refDestructuringErrors.shorthandAssign; var doubleProto = refDestructuringErrors.doubleProto; if(!andThrow){ return shorthandAssign >= 0 || doubleProto >= 0; } if(shorthandAssign >= 0){ this.raise(shorthandAssign,"Shorthand property assignments are valid only in destructuring patterns"); } if(doubleProto >= 0){ this.raiseRecoverable(doubleProto,"Redefinition of __proto__ property"); } }; pp.checkYieldAwaitInDefaultParams = function(){ if(this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos)){ this.raise(this.yieldPos,"Yield expression cannot be a default value"); } if(this.awaitPos){ this.raise(this.awaitPos,"Await expression cannot be a default value"); } }; pp.isSimpleAssignTarget = function(expr){ if(expr.type === "ParenthesizedExpression"){ return this.isSimpleAssignTarget(expr.expression); } return expr.type === "Identifier" || expr.type === "MemberExpression"; }; var pp$1 = Parser.prototype; pp$1.parseTopLevel = function(node){ var exports = {}; if(!node.body){ node.body = []; } while(this.type !== types.eof){ var stmt = this.parseStatement(null,true,exports); node.body.push(stmt); } if(this.inModule){ for(var i = 0,list = Object.keys(this.undefinedExports); i < list.length; i += 1){ var name = list[i]; this.raiseRecoverable(this.undefinedExports[name].start,("Export '" + name + "' is not defined")); } } this.adaptDirectivePrologue(node.body); this.next(); node.sourceType = this.options.sourceType; return this.finishNode(node,"Program"); }; var loopLabel = {kind:"loop"},switchLabel = {kind:"switch"}; pp$1.isLet = function(context){ if(this.options.ecmaVersion < 6 || !this.isContextual("let")){ return false; } skipWhiteSpace.lastIndex = this.pos; var skip = skipWhiteSpace.exec(this.input); var next = this.pos + skip[0].length,nextCh = this.input.charCodeAt(next); if(nextCh === 91){ return true; } if(context){ return false; } if(nextCh === 123){ return true; } if(isIdentifierStart(nextCh,true)){ var pos = next + 1; while(isIdentifierChar(this.input.charCodeAt(pos),true)){ ++ pos; } var ident = this.input.slice(next,pos); if(!keywordRelationalOperator.test(ident)){ return true; } } return false; }; pp$1.isAsyncFunction = function(){ if(this.options.ecmaVersion < 8 || !this.isContextual("async")){ return false; } skipWhiteSpace.lastIndex = this.pos; var skip = skipWhiteSpace.exec(this.input); var next = this.pos + skip[0].length; return !lineBreak.test(this.input.slice(this.pos,next)) && this.input.slice(next,next + 8) === "function" && (next + 8 === this.input.length || !isIdentifierChar(this.input.charAt(next + 8))); }; pp$1.parseStatement = function(context,topLevel,exports){ var starttype = this.type,node = this.startNode(),kind; if(this.isLet(context)){ starttype = types._var; kind = "let"; } switch(starttype){ case types._break: case types._continue: return this.parseBreakContinueStatement(node,starttype.keyword); case types._debugger: return this.parseDebuggerStatement(node); case types._do: return this.parseDoStatement(node); case types._for: return this.parseForStatement(node); case types._function: if((context && (this.strict || context !== "if" && context !== "label")) && this.options.ecmaVersion >= 6){ this.unexpected(); } return this.parseFunctionStatement(node,false,!context); case types._class: if(context){ this.unexpected(); } return this.parseClass(node,true); case types._if: return this.parseIfStatement(node); case types._return: return this.parseReturnStatement(node); case types._switch: return this.parseSwitchStatement(node); case types._throw: return this.parseThrowStatement(node); case types._try: return this.parseTryStatement(node); case types._const: case types._var: kind = kind || this.value; if(context && kind !== "var"){ this.unexpected(); } return this.parseVarStatement(node,kind); case types._while: return this.parseWhileStatement(node); case types._with: return this.parseWithStatement(node); case types.braceL: return this.parseBlock(true,node); case types.semi: return this.parseEmptyStatement(node); case types._export: case types._import: if(this.options.ecmaVersion > 10 && starttype === types._import){ skipWhiteSpace.lastIndex = this.pos; var skip = skipWhiteSpace.exec(this.input); var next = this.pos + skip[0].length,nextCh = this.input.charCodeAt(next); if(nextCh === 40){ return this.parseExpressionStatement(node,this.parseExpression()); } } if(!this.options.allowImportExportEverywhere){ if(!topLevel){ this.raise(this.start,"'import' and 'export' may only appear at the top level"); } if(!this.inModule){ this.raise(this.start,"'import' and 'export' may appear only with 'sourceType: module'"); } } return starttype === types._import?this.parseImport(node):this.parseExport(node,exports); default: if(this.isAsyncFunction()){ if(context){ this.unexpected(); } this.next(); return this.parseFunctionStatement(node,true,!context); } var maybeName = this.value,expr = this.parseExpression(); if(starttype === types.name && expr.type === "Identifier" && this.eat(types.colon)){ return this.parseLabeledStatement(node,maybeName,expr,context); }else{ return this.parseExpressionStatement(node,expr); } } }; pp$1.parseBreakContinueStatement = function(node,keyword){ var isBreak = keyword === "break"; this.next(); if(this.eat(types.semi) || this.insertSemicolon()){ node.label = null; }else if(this.type !== types.name){ this.unexpected(); }else{ node.label = this.parseIdent(); this.semicolon(); } var i = 0; for(; i < this.labels.length; ++ i){ var lab = this.labels[i]; if(node.label == null || lab.name === node.label.name){ if(lab.kind != null && (isBreak || lab.kind === "loop")){ break; } if(node.label && isBreak){ break; } } } if(i === this.labels.length){ this.raise(node.start,"Unsyntactic " + keyword); } return this.finishNode(node,isBreak?"BreakStatement":"ContinueStatement"); }; pp$1.parseDebuggerStatement = function(node){ this.next(); this.semicolon(); return this.finishNode(node,"DebuggerStatement"); }; pp$1.parseDoStatement = function(node){ this.next(); this.labels.push(loopLabel); node.body = this.parseStatement("do"); this.labels.pop(); this.expect(types._while); node.test = this.parseParenExpression(); if(this.options.ecmaVersion >= 6){ this.eat(types.semi); }else{ this.semicolon(); } return this.finishNode(node,"DoWhileStatement"); }; pp$1.parseForStatement = function(node){ this.next(); var awaitAt = (this.options.ecmaVersion >= 9 && (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction)) && this.eatContextual("await"))?this.lastTokStart:- 1; this.labels.push(loopLabel); this.enterScope(0); this.expect(types.parenL); if(this.type === types.semi){ if(awaitAt > - 1){ this.unexpected(awaitAt); } return this.parseFor(node,null); } var isLet = this.isLet(); if(this.type === types._var || this.type === types._const || isLet){ var init$1 = this.startNode(),kind = isLet?"let":this.value; this.next(); this.parseVar(init$1,true,kind); this.finishNode(init$1,"VariableDeclaration"); if((this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init$1.declarations.length === 1){ if(this.options.ecmaVersion >= 9){ if(this.type === types._in){ if(awaitAt > - 1){ this.unexpected(awaitAt); } }else{ node.await = awaitAt > - 1; } } return this.parseForIn(node,init$1); } if(awaitAt > - 1){ this.unexpected(awaitAt); } return this.parseFor(node,init$1); } var refDestructuringErrors = new DestructuringErrors; var init = this.parseExpression(true,refDestructuringErrors); if(this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))){ if(this.options.ecmaVersion >= 9){ if(this.type === types._in){ if(awaitAt > - 1){ this.unexpected(awaitAt); } }else{ node.await = awaitAt > - 1; } } this.toAssignable(init,false,refDestructuringErrors); this.checkLVal(init); return this.parseForIn(node,init); }else{ this.checkExpressionErrors(refDestructuringErrors,true); } if(awaitAt > - 1){ this.unexpected(awaitAt); } return this.parseFor(node,init); }; pp$1.parseFunctionStatement = function(node,isAsync,declarationPosition){ this.next(); return this.parseFunction(node,FUNC_STATEMENT | (declarationPosition?0:FUNC_HANGING_STATEMENT),false,isAsync); }; pp$1.parseIfStatement = function(node){ this.next(); node.test = this.parseParenExpression(); node.consequent = this.parseStatement("if"); node.alternate = this.eat(types._else)?this.parseStatement("if"):null; return this.finishNode(node,"IfStatement"); }; pp$1.parseReturnStatement = function(node){ if(!this.inFunction && !this.options.allowReturnOutsideFunction){ this.raise(this.start,"'return' outside of function"); } this.next(); if(this.eat(types.semi) || this.insertSemicolon()){ node.argument = null; }else{ node.argument = this.parseExpression(); this.semicolon(); } return this.finishNode(node,"ReturnStatement"); }; pp$1.parseSwitchStatement = function(node){ this.next(); node.discriminant = this.parseParenExpression(); node.cases = []; this.expect(types.braceL); this.labels.push(switchLabel); this.enterScope(0); var cur; for(var sawDefault = false; this.type !== types.braceR;){ if(this.type === types._case || this.type === types._default){ var isCase = this.type === types._case; if(cur){ this.finishNode(cur,"SwitchCase"); } node.cases.push(cur = this.startNode()); cur.consequent = []; this.next(); if(isCase){ cur.test = this.parseExpression(); }else{ if(sawDefault){ this.raiseRecoverable(this.lastTokStart,"Multiple default clauses"); } sawDefault = true; cur.test = null; } this.expect(types.colon); }else{ if(!cur){ this.unexpected(); } cur.consequent.push(this.parseStatement(null)); } } this.exitScope(); if(cur){ this.finishNode(cur,"SwitchCase"); } this.next(); this.labels.pop(); return this.finishNode(node,"SwitchStatement"); }; pp$1.parseThrowStatement = function(node){ this.next(); if(lineBreak.test(this.input.slice(this.lastTokEnd,this.start))){ this.raise(this.lastTokEnd,"Illegal newline after throw"); } node.argument = this.parseExpression(); this.semicolon(); return this.finishNode(node,"ThrowStatement"); }; var empty = []; pp$1.parseTryStatement = function(node){ this.next(); node.block = this.parseBlock(); node.handler = null; if(this.type === types._catch){ var clause = this.startNode(); this.next(); if(this.eat(types.parenL)){ clause.param = this.parseBindingAtom(); var simple = clause.param.type === "Identifier"; this.enterScope(simple?SCOPE_SIMPLE_CATCH:0); this.checkLVal(clause.param,simple?BIND_SIMPLE_CATCH:BIND_LEXICAL); this.expect(types.parenR); }else{ if(this.options.ecmaVersion < 10){ this.unexpected(); } clause.param = null; this.enterScope(0); } clause.body = this.parseBlock(false); this.exitScope(); node.handler = this.finishNode(clause,"CatchClause"); } node.finalizer = this.eat(types._finally)?this.parseBlock():null; if(!node.handler && !node.finalizer){ this.raise(node.start,"Missing catch or finally clause"); } return this.finishNode(node,"TryStatement"); }; pp$1.parseVarStatement = function(node,kind){ this.next(); this.parseVar(node,false,kind); this.semicolon(); return this.finishNode(node,"VariableDeclaration"); }; pp$1.parseWhileStatement = function(node){ this.next(); node.test = this.parseParenExpression(); this.labels.push(loopLabel); node.body = this.parseStatement("while"); this.labels.pop(); return this.finishNode(node,"WhileStatement"); }; pp$1.parseWithStatement = function(node){ if(this.strict){ this.raise(this.start,"'with' in strict mode"); } this.next(); node.object = this.parseParenExpression(); node.body = this.parseStatement("with"); return this.finishNode(node,"WithStatement"); }; pp$1.parseEmptyStatement = function(node){ this.next(); return this.finishNode(node,"EmptyStatement"); }; pp$1.parseLabeledStatement = function(node,maybeName,expr,context){ for(var i$1 = 0,list = this.labels; i$1 < list.length; i$1 += 1){ var label = list[i$1]; if(label.name === maybeName){ this.raise(expr.start,"Label '" + maybeName + "' is already declared"); } } var kind = this.type.isLoop?"loop":this.type === types._switch?"switch":null; for(var i = this.labels.length - 1; i >= 0; i --){ var label$1 = this.labels[i]; if(label$1.statementStart === node.start){ label$1.statementStart = this.start; label$1.kind = kind; }else{ break; } } this.labels.push({name:maybeName,kind:kind,statementStart:this.start}); node.body = this.parseStatement(context?context.indexOf("label") === - 1?context + "label":context:"label"); this.labels.pop(); node.label = expr; return this.finishNode(node,"LabeledStatement"); }; pp$1.parseExpressionStatement = function(node,expr){ node.expression = expr; this.semicolon(); return this.finishNode(node,"ExpressionStatement"); }; pp$1.parseBlock = function(createNewLexicalScope,node){ if(createNewLexicalScope === void 0){ createNewLexicalScope = true; } if(node === void 0){ node = this.startNode(); } node.body = []; this.expect(types.braceL); if(createNewLexicalScope){ this.enterScope(0); } while(!this.eat(types.braceR)){ var stmt = this.parseStatement(null); node.body.push(stmt); } if(createNewLexicalScope){ this.exitScope(); } return this.finishNode(node,"BlockStatement"); }; pp$1.parseFor = function(node,init){ node.init = init; this.expect(types.semi); node.test = this.type === types.semi?null:this.parseExpression(); this.expect(types.semi); node.update = this.type === types.parenR?null:this.parseExpression(); this.expect(types.parenR); node.body = this.parseStatement("for"); this.exitScope(); this.labels.pop(); return this.finishNode(node,"ForStatement"); }; pp$1.parseForIn = function(node,init){ var isForIn = this.type === types._in; this.next(); if(init.type === "VariableDeclaration" && init.declarations[0].init != null && (!isForIn || this.options.ecmaVersion < 8 || this.strict || init.kind !== "var" || init.declarations[0].id.type !== "Identifier")){ this.raise(init.start,((isForIn?"for-in":"for-of") + " loop variable declaration may not have an initializer")); }else if(init.type === "AssignmentPattern"){ this.raise(init.start,"Invalid left-hand side in for-loop"); } node.left = init; node.right = isForIn?this.parseExpression():this.parseMaybeAssign(); this.expect(types.parenR); node.body = this.parseStatement("for"); this.exitScope(); this.labels.pop(); return this.finishNode(node,isForIn?"ForInStatement":"ForOfStatement"); }; pp$1.parseVar = function(node,isFor,kind){ node.declarations = []; node.kind = kind; for(; ;){ var decl = this.startNode(); this.parseVarId(decl,kind); if(this.eat(types.eq)){ decl.init = this.parseMaybeAssign(isFor); }else if(kind === "const" && !(this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of")))){ this.unexpected(); }else if(decl.id.type !== "Identifier" && !(isFor && (this.type === types._in || this.isContextual("of")))){ this.raise(this.lastTokEnd,"Complex binding patterns require an initialization value"); }else{ decl.init = null; } node.declarations.push(this.finishNode(decl,"VariableDeclarator")); if(!this.eat(types.comma)){ break; } } return node; }; pp$1.parseVarId = function(decl,kind){ decl.id = this.parseBindingAtom(); this.checkLVal(decl.id,kind === "var"?BIND_VAR:BIND_LEXICAL,false); }; var FUNC_STATEMENT = 1,FUNC_HANGING_STATEMENT = 2,FUNC_NULLABLE_ID = 4; pp$1.parseFunction = function(node,statement,allowExpressionBody,isAsync){ this.initFunction(node); if(this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync){ if(this.type === types.star && (statement & FUNC_HANGING_STATEMENT)){ this.unexpected(); } node.generator = this.eat(types.star); } if(this.options.ecmaVersion >= 8){ node.async = !!isAsync; } if(statement & FUNC_STATEMENT){ node.id = (statement & FUNC_NULLABLE_ID) && this.type !== types.name?null:this.parseIdent(); if(node.id && !(statement & FUNC_HANGING_STATEMENT)){ this.checkLVal(node.id,(this.strict || node.generator || node.async)?this.treatFunctionsAsVar?BIND_VAR:BIND_LEXICAL:BIND_FUNCTION); } } var oldYieldPos = this.yieldPos,oldAwaitPos = this.awaitPos,oldAwaitIdentPos = this.awaitIdentPos; this.yieldPos = 0; this.awaitPos = 0; this.awaitIdentPos = 0; this.enterScope(functionFlags(node.async,node.generator)); if(!(statement & FUNC_STATEMENT)){ node.id = this.type === types.name?this.parseIdent():null; } this.parseFunctionParams(node); this.parseFunctionBody(node,allowExpressionBody,false); this.yieldPos = oldYieldPos; this.awaitPos = oldAwaitPos; this.awaitIdentPos = oldAwaitIdentPos; return this.finishNode(node,(statement & FUNC_STATEMENT)?"FunctionDeclaration":"FunctionExpression"); }; pp$1.parseFunctionParams = function(node){ this.expect(types.parenL); node.params = this.parseBindingList(types.parenR,false,this.options.ecmaVersion >= 8); this.checkYieldAwaitInDefaultParams(); }; pp$1.parseClass = function(node,isStatement){ this.next(); var oldStrict = this.strict; this.strict = true; this.parseClassId(node,isStatement); this.parseClassSuper(node); var classBody = this.startNode(); var hadConstructor = false; classBody.body = []; this.expect(types.braceL); while(!this.eat(types.braceR)){ var element = this.parseClassElement(node.superClass !== null); if(element){ classBody.body.push(element); if(element.type === "MethodDefinition" && element.kind === "constructor"){ if(hadConstructor){ this.raise(element.start,"Duplicate constructor in the same class"); } hadConstructor = true; } } } node.body = this.finishNode(classBody,"ClassBody"); this.strict = oldStrict; return this.finishNode(node,isStatement?"ClassDeclaration":"ClassExpression"); }; pp$1.parseClassElement = function(constructorAllowsSuper){ var this$1 = this; if(this.eat(types.semi)){ return null; } var method = this.startNode(); var tryContextual = function(k,noLineBreak){ if(noLineBreak === void 0){ noLineBreak = false; } var start = this$1.start,startLoc = this$1.startLoc; if(!this$1.eatContextual(k)){ return false; } if(this$1.type !== types.parenL && (!noLineBreak || !this$1.canInsertSemicolon())){ return true; } if(method.key){ this$1.unexpected(); } method.computed = false; method.key = this$1.startNodeAt(start,startLoc); method.key.name = k; this$1.finishNode(method.key,"Identifier"); return false; }; method.kind = "method"; method.static = tryContextual("static"); var isGenerator = this.eat(types.star); var isAsync = false; if(!isGenerator){ if(this.options.ecmaVersion >= 8 && tryContextual("async",true)){ isAsync = true; isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star); }else if(tryContextual("get")){ method.kind = "get"; }else if(tryContextual("set")){ method.kind = "set"; } } if(!method.key){ this.parsePropertyName(method); } var key = method.key; var allowsDirectSuper = false; if(!method.computed && !method.static && (key.type === "Identifier" && key.name === "constructor" || key.type === "Literal" && key.value === "constructor")){ if(method.kind !== "method"){ this.raise(key.start,"Constructor can't have get/set modifier"); } if(isGenerator){ this.raise(key.start,"Constructor can't be a generator"); } if(isAsync){ this.raise(key.start,"Constructor can't be an async method"); } method.kind = "constructor"; allowsDirectSuper = constructorAllowsSuper; }else if(method.static && key.type === "Identifier" && key.name === "prototype"){ this.raise(key.start,"Classes may not have a static property named prototype"); } this.parseClassMethod(method,isGenerator,isAsync,allowsDirectSuper); if(method.kind === "get" && method.value.params.length !== 0){ this.raiseRecoverable(method.value.start,"getter should have no params"); } if(method.kind === "set" && method.value.params.length !== 1){ this.raiseRecoverable(method.value.start,"setter should have exactly one param"); } if(method.kind === "set" && method.value.params[0].type === "RestElement"){ this.raiseRecoverable(method.value.params[0].start,"Setter cannot use rest params"); } return method; }; pp$1.parseClassMethod = function(method,isGenerator,isAsync,allowsDirectSuper){ method.value = this.parseMethod(isGenerator,isAsync,allowsDirectSuper); return this.finishNode(method,"MethodDefinition"); }; pp$1.parseClassId = function(node,isStatement){ if(this.type === types.name){ node.id = this.parseIdent(); if(isStatement){ this.checkLVal(node.id,BIND_LEXICAL,false); } }else{ if(isStatement === true){ this.unexpected(); } node.id = null; } }; pp$1.parseClassSuper = function(node){ node.superClass = this.eat(types._extends)?this.parseExprSubscripts():null; }; pp$1.parseExport = function(node,exports){ this.next(); if(this.eat(types.star)){ this.expectContextual("from"); if(this.type !== types.string){ this.unexpected(); } node.source = this.parseExprAtom(); this.semicolon(); return this.finishNode(node,"ExportAllDeclaration"); } if(this.eat(types._default)){ this.checkExport(exports,"default",this.lastTokStart); var isAsync; if(this.type === types._function || (isAsync = this.isAsyncFunction())){ var fNode = this.startNode(); this.next(); if(isAsync){ this.next(); } node.declaration = this.parseFunction(fNode,FUNC_STATEMENT | FUNC_NULLABLE_ID,false,isAsync); }else if(this.type === types._class){ var cNode = this.startNode(); node.declaration = this.parseClass(cNode,"nullableID"); }else{ node.declaration = this.parseMaybeAssign(); this.semicolon(); } return this.finishNode(node,"ExportDefaultDeclaration"); } if(this.shouldParseExportStatement()){ node.declaration = this.parseStatement(null); if(node.declaration.type === "VariableDeclaration"){ this.checkVariableExport(exports,node.declaration.declarations); }else{ this.checkExport(exports,node.declaration.id.name,node.declaration.id.start); } node.specifiers = []; node.source = null; }else{ node.declaration = null; node.specifiers = this.parseExportSpecifiers(exports); if(this.eatContextual("from")){ if(this.type !== types.string){ this.unexpected(); } node.source = this.parseExprAtom(); }else{ for(var i = 0,list = node.specifiers; i < list.length; i += 1){ var spec = list[i]; this.checkUnreserved(spec.local); this.checkLocalExport(spec.local); } node.source = null; } this.semicolon(); } return this.finishNode(node,"ExportNamedDeclaration"); }; pp$1.checkExport = function(exports,name,pos){ if(!exports){ return; } if(has(exports,name)){ this.raiseRecoverable(pos,"Duplicate export '" + name + "'"); } exports[name] = true; }; pp$1.checkPatternExport = function(exports,pat){ var type = pat.type; if(type === "Identifier"){ this.checkExport(exports,pat.name,pat.start); }else if(type === "ObjectPattern"){ for(var i = 0,list = pat.properties; i < list.length; i += 1){ var prop = list[i]; this.checkPatternExport(exports,prop); } }else if(type === "ArrayPattern"){ for(var i$1 = 0,list$1 = pat.elements; i$1 < list$1.length; i$1 += 1){ var elt = list$1[i$1]; if(elt){ this.checkPatternExport(exports,elt); } } }else if(type === "Property"){ this.checkPatternExport(exports,pat.value); }else if(type === "AssignmentPattern"){ this.checkPatternExport(exports,pat.left); }else if(type === "RestElement"){ this.checkPatternExport(exports,pat.argument); }else if(type === "ParenthesizedExpression"){ this.checkPatternExport(exports,pat.expression); } }; pp$1.checkVariableExport = function(exports,decls){ if(!exports){ return; } for(var i = 0,list = decls; i < list.length; i += 1){ var decl = list[i]; this.checkPatternExport(exports,decl.id); } }; pp$1.shouldParseExportStatement = function(){ return this.type.keyword === "var" || this.type.keyword === "const" || this.type.keyword === "class" || this.type.keyword === "function" || this.isLet() || this.isAsyncFunction(); }; pp$1.parseExportSpecifiers = function(exports){ var nodes = [],first = true; this.expect(types.braceL); while(!this.eat(types.braceR)){ if(!first){ this.expect(types.comma); if(this.afterTrailingComma(types.braceR)){ break; } }else{ first = false; } var node = this.startNode(); node.local = this.parseIdent(true); node.exported = this.eatContextual("as")?this.parseIdent(true):node.local; this.checkExport(exports,node.exported.name,node.exported.start); nodes.push(this.finishNode(node,"ExportSpecifier")); } return nodes; }; pp$1.parseImport = function(node){ this.next(); if(this.type === types.string){ node.specifiers = empty; node.source = this.parseExprAtom(); }else{ node.specifiers = this.parseImportSpecifiers(); this.expectContextual("from"); node.source = this.type === types.string?this.parseExprAtom():this.unexpected(); } this.semicolon(); return this.finishNode(node,"ImportDeclaration"); }; pp$1.parseImportSpecifiers = function(){ var nodes = [],first = true; if(this.type === types.name){ var node = this.startNode(); node.local = this.parseIdent(); this.checkLVal(node.local,BIND_LEXICAL); nodes.push(this.finishNode(node,"ImportDefaultSpecifier")); if(!this.eat(types.comma)){ return nodes; } } if(this.type === types.star){ var node$1 = this.startNode(); this.next(); this.expectContextual("as"); node$1.local = this.parseIdent(); this.checkLVal(node$1.local,BIND_LEXICAL); nodes.push(this.finishNode(node$1,"ImportNamespaceSpecifier")); return nodes; } this.expect(types.braceL); while(!this.eat(types.braceR)){ if(!first){ this.expect(types.comma); if(this.afterTrailingComma(types.braceR)){ break; } }else{ first = false; } var node$2 = this.startNode(); node$2.imported = this.parseIdent(true); if(this.eatContextual("as")){ node$2.local = this.parseIdent(); }else{ this.checkUnreserved(node$2.imported); node$2.local = node$2.imported; } this.checkLVal(node$2.local,BIND_LEXICAL); nodes.push(this.finishNode(node$2,"ImportSpecifier")); } return nodes; }; pp$1.adaptDirectivePrologue = function(statements){ for(var i = 0; i < statements.length && this.isDirectiveCandidate(statements[i]); ++ i){ statements[i].directive = statements[i].expression.raw.slice(1,- 1); } }; pp$1.isDirectiveCandidate = function(statement){ return (statement.type === "ExpressionStatement" && statement.expression.type === "Literal" && typeof statement.expression.value === "string" && (this.input[statement.start] === "\"" || this.input[statement.start] === "'")); }; var pp$2 = Parser.prototype; pp$2.toAssignable = function(node,isBinding,refDestructuringErrors){ if(this.options.ecmaVersion >= 6 && node){ switch(node.type){ case "Identifier": if(this.inAsync && node.name === "await"){ this.raise(node.start,"Cannot use 'await' as identifier inside an async function"); } break; case "ObjectPattern": case "ArrayPattern": case "RestElement": break; case "ObjectExpression": node.type = "ObjectPattern"; if(refDestructuringErrors){ this.checkPatternErrors(refDestructuringErrors,true); } for(var i = 0,list = node.properties; i < list.length; i += 1){ var prop = list[i]; this.toAssignable(prop,isBinding); if(prop.type === "RestElement" && (prop.argument.type === "ArrayPattern" || prop.argument.type === "ObjectPattern")){ this.raise(prop.argument.start,"Unexpected token"); } } break; case "Property": if(node.kind !== "init"){ this.raise(node.key.start,"Object pattern can't contain getter or setter"); } this.toAssignable(node.value,isBinding); break; case "ArrayExpression": node.type = "ArrayPattern"; if(refDestructuringErrors){ this.checkPatternErrors(refDestructuringErrors,true); } this.toAssignableList(node.elements,isBinding); break; case "SpreadElement": node.type = "RestElement"; this.toAssignable(node.argument,isBinding); if(node.argument.type === "AssignmentPattern"){ this.raise(node.argument.start,"Rest elements cannot have a default value"); } break; case "AssignmentExpression": if(node.operator !== "="){ this.raise(node.left.end,"Only '=' operator can be used for specifying default value."); } node.type = "AssignmentPattern"; delete node.operator; this.toAssignable(node.left,isBinding); case "AssignmentPattern": break; case "ParenthesizedExpression": this.toAssignable(node.expression,isBinding,refDestructuringErrors); break; case "MemberExpression": if(!isBinding){ break; } default: this.raise(node.start,"Assigning to rvalue"); } }else if(refDestructuringErrors){ this.checkPatternErrors(refDestructuringErrors,true); } return node; }; pp$2.toAssignableList = function(exprList,isBinding){ var end = exprList.length; for(var i = 0; i < end; i ++){ var elt = exprList[i]; if(elt){ this.toAssignable(elt,isBinding); } } if(end){ var last = exprList[end - 1]; if(this.options.ecmaVersion === 6 && isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier"){ this.unexpected(last.argument.start); } } return exprList; }; pp$2.parseSpread = function(refDestructuringErrors){ var node = this.startNode(); this.next(); node.argument = this.parseMaybeAssign(false,refDestructuringErrors); return this.finishNode(node,"SpreadElement"); }; pp$2.parseRestBinding = function(){ var node = this.startNode(); this.next(); if(this.options.ecmaVersion === 6 && this.type !== types.name){ this.unexpected(); } node.argument = this.parseBindingAtom(); return this.finishNode(node,"RestElement"); }; pp$2.parseBindingAtom = function(){ if(this.options.ecmaVersion >= 6){ switch(this.type){ case types.bracketL: var node = this.startNode(); this.next(); node.elements = this.parseBindingList(types.bracketR,true,true); return this.finishNode(node,"ArrayPattern"); case types.braceL: return this.parseObj(true); } } return this.parseIdent(); }; pp$2.parseBindingList = function(close,allowEmpty,allowTrailingComma){ var elts = [],first = true; while(!this.eat(close)){ if(first){ first = false; }else{ this.expect(types.comma); } if(allowEmpty && this.type === types.comma){ elts.push(null); }else if(allowTrailingComma && this.afterTrailingComma(close)){ break; }else if(this.type === types.ellipsis){ var rest = this.parseRestBinding(); this.parseBindingListItem(rest); elts.push(rest); if(this.type === types.comma){ this.raise(this.start,"Comma is not permitted after the rest element"); } this.expect(close); break; }else{ var elem = this.parseMaybeDefault(this.start,this.startLoc); this.parseBindingListItem(elem); elts.push(elem); } } return elts; }; pp$2.parseBindingListItem = function(param){ return param; }; pp$2.parseMaybeDefault = function(startPos,startLoc,left){ left = left || this.parseBindingAtom(); if(this.options.ecmaVersion < 6 || !this.eat(types.eq)){ return left; } var node = this.startNodeAt(startPos,startLoc); node.left = left; node.right = this.parseMaybeAssign(); return this.finishNode(node,"AssignmentPattern"); }; pp$2.checkLVal = function(expr,bindingType,checkClashes){ if(bindingType === void 0){ bindingType = BIND_NONE; } switch(expr.type){ case "Identifier": if(bindingType === BIND_LEXICAL && expr.name === "let"){ this.raiseRecoverable(expr.start,"let is disallowed as a lexically bound name"); } if(this.strict && this.reservedWordsStrictBind.test(expr.name)){ this.raiseRecoverable(expr.start,(bindingType?"Binding ":"Assigning to ") + expr.name + " in strict mode"); } if(checkClashes){ if(has(checkClashes,expr.name)){ this.raiseRecoverable(expr.start,"Argument name clash"); } checkClashes[expr.name] = true; } if(bindingType !== BIND_NONE && bindingType !== BIND_OUTSIDE){ this.declareName(expr.name,bindingType,expr.start); } break; case "MemberExpression": if(bindingType){ this.raiseRecoverable(expr.start,"Binding member expression"); } break; case "ObjectPattern": for(var i = 0,list = expr.properties; i < list.length; i += 1){ var prop = list[i]; this.checkLVal(prop,bindingType,checkClashes); } break; case "Property": this.checkLVal(expr.value,bindingType,checkClashes); break; case "ArrayPattern": for(var i$1 = 0,list$1 = expr.elements; i$1 < list$1.length; i$1 += 1){ var elem = list$1[i$1]; if(elem){ this.checkLVal(elem,bindingType,checkClashes); } } break; case "AssignmentPattern": this.checkLVal(expr.left,bindingType,checkClashes); break; case "RestElement": this.checkLVal(expr.argument,bindingType,checkClashes); break; case "ParenthesizedExpression": this.checkLVal(expr.expression,bindingType,checkClashes); break; default: this.raise(expr.start,(bindingType?"Binding":"Assigning to") + " rvalue"); } }; var pp$3 = Parser.prototype; pp$3.checkPropClash = function(prop,propHash,refDestructuringErrors){ if(this.options.ecmaVersion >= 9 && prop.type === "SpreadElement"){ return; } if(this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand)){ return; } var key = prop.key; var name; switch(key.type){ case "Identifier": name = key.name; break; case "Literal": name = String(key.value); break; default: return; } var kind = prop.kind; if(this.options.ecmaVersion >= 6){ if(name === "__proto__" && kind === "init"){ if(propHash.proto){ if(refDestructuringErrors){ if(refDestructuringErrors.doubleProto < 0){ refDestructuringErrors.doubleProto = key.start; } }else{ this.raiseRecoverable(key.start,"Redefinition of __proto__ property"); } } propHash.proto = true; } return; } name = "$" + name; var other = propHash[name]; if(other){ var redefinition; if(kind === "init"){ redefinition = this.strict && other.init || other.get || other.set; }else{ redefinition = other.init || other[kind]; } if(redefinition){ this.raiseRecoverable(key.start,"Redefinition of property"); } }else{ other = propHash[name] = { init:false,get:false,set:false }; } other[kind] = true; }; pp$3.parseExpression = function(noIn,refDestructuringErrors){ var startPos = this.start,startLoc = this.startLoc; var expr = this.parseMaybeAssign(noIn,refDestructuringErrors); if(this.type === types.comma){ var node = this.startNodeAt(startPos,startLoc); node.expressions = [expr]; while(this.eat(types.comma)){ node.expressions.push(this.parseMaybeAssign(noIn,refDestructuringErrors)); } return this.finishNode(node,"SequenceExpression"); } return expr; }; pp$3.parseMaybeAssign = function(noIn,refDestructuringErrors,afterLeftParse){ if(this.isContextual("yield")){ if(this.inGenerator){ return this.parseYield(noIn); }else{ this.exprAllowed = false; } } var ownDestructuringErrors = false,oldParenAssign = - 1,oldTrailingComma = - 1; if(refDestructuringErrors){ oldParenAssign = refDestructuringErrors.parenthesizedAssign; oldTrailingComma = refDestructuringErrors.trailingComma; refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = - 1; }else{ refDestructuringErrors = new DestructuringErrors; ownDestructuringErrors = true; } var startPos = this.start,startLoc = this.startLoc; if(this.type === types.parenL || this.type === types.name){ this.potentialArrowAt = this.start; } var left = this.parseMaybeConditional(noIn,refDestructuringErrors); if(afterLeftParse){ left = afterLeftParse.call(this,left,startPos,startLoc); } if(this.type.isAssign){ var node = this.startNodeAt(startPos,startLoc); node.operator = this.value; node.left = this.type === types.eq?this.toAssignable(left,false,refDestructuringErrors):left; if(!ownDestructuringErrors){ refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = refDestructuringErrors.doubleProto = - 1; } if(refDestructuringErrors.shorthandAssign >= node.left.start){ refDestructuringErrors.shorthandAssign = - 1; } this.checkLVal(left); this.next(); node.right = this.parseMaybeAssign(noIn); return this.finishNode(node,"AssignmentExpression"); }else{ if(ownDestructuringErrors){ this.checkExpressionErrors(refDestructuringErrors,true); } } if(oldParenAssign > - 1){ refDestructuringErrors.parenthesizedAssign = oldParenAssign; } if(oldTrailingComma > - 1){ refDestructuringErrors.trailingComma = oldTrailingComma; } return left; }; pp$3.parseMaybeConditional = function(noIn,refDestructuringErrors){ var startPos = this.start,startLoc = this.startLoc; var expr = this.parseExprOps(noIn,refDestructuringErrors); if(this.checkExpressionErrors(refDestructuringErrors)){ return expr; } if(this.eat(types.question)){ var node = this.startNodeAt(startPos,startLoc); node.test = expr; node.consequent = this.parseMaybeAssign(); this.expect(types.colon); node.alternate = this.parseMaybeAssign(noIn); return this.finishNode(node,"ConditionalExpression"); } return expr; }; pp$3.parseExprOps = function(noIn,refDestructuringErrors){ var startPos = this.start,startLoc = this.startLoc; var expr = this.parseMaybeUnary(refDestructuringErrors,false); if(this.checkExpressionErrors(refDestructuringErrors)){ return expr; } return expr.start === startPos && expr.type === "ArrowFunctionExpression"?expr:this.parseExprOp(expr,startPos,startLoc,- 1,noIn); }; pp$3.parseExprOp = function(left,leftStartPos,leftStartLoc,minPrec,noIn){ var prec = this.type.binop; if(prec != null && (!noIn || this.type !== types._in)){ if(prec > minPrec){ var logical = this.type === types.logicalOR || this.type === types.logicalAND; var op = this.value; this.next(); var startPos = this.start,startLoc = this.startLoc; var right = this.parseExprOp(this.parseMaybeUnary(null,false),startPos,startLoc,prec,noIn); var node = this.buildBinary(leftStartPos,leftStartLoc,left,right,op,logical); return this.parseExprOp(node,leftStartPos,leftStartLoc,minPrec,noIn); } } return left; }; pp$3.buildBinary = function(startPos,startLoc,left,right,op,logical){ var node = this.startNodeAt(startPos,startLoc); node.left = left; node.operator = op; node.right = right; return this.finishNode(node,logical?"LogicalExpression":"BinaryExpression"); }; pp$3.parseMaybeUnary = function(refDestructuringErrors,sawUnary){ var startPos = this.start,startLoc = this.startLoc,expr; if(this.isContextual("await") && (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction))){ expr = this.parseAwait(); sawUnary = true; }else if(this.type.prefix){ var node = this.startNode(),update = this.type === types.incDec; node.operator = this.value; node.prefix = true; this.next(); node.argument = this.parseMaybeUnary(null,true); this.checkExpressionErrors(refDestructuringErrors,true); if(update){ this.checkLVal(node.argument); }else if(this.strict && node.operator === "delete" && node.argument.type === "Identifier"){ this.raiseRecoverable(node.start,"Deleting local variable in strict mode"); }else{ sawUnary = true; } expr = this.finishNode(node,update?"UpdateExpression":"UnaryExpression"); }else{ expr = this.parseExprSubscripts(refDestructuringErrors); if(this.checkExpressionErrors(refDestructuringErrors)){ return expr; } while(this.type.postfix && !this.canInsertSemicolon()){ var node$1 = this.startNodeAt(startPos,startLoc); node$1.operator = this.value; node$1.prefix = false; node$1.argument = expr; this.checkLVal(expr); this.next(); expr = this.finishNode(node$1,"UpdateExpression"); } } if(!sawUnary && this.eat(types.starstar)){ return this.buildBinary(startPos,startLoc,expr,this.parseMaybeUnary(null,false),"**",false); }else{ return expr; } }; pp$3.parseExprSubscripts = function(refDestructuringErrors){ var startPos = this.start,startLoc = this.startLoc; var expr = this.parseExprAtom(refDestructuringErrors); if(expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart,this.lastTokEnd) !== ")"){ return expr; } var result = this.parseSubscripts(expr,startPos,startLoc); if(refDestructuringErrors && result.type === "MemberExpression"){ if(refDestructuringErrors.parenthesizedAssign >= result.start){ refDestructuringErrors.parenthesizedAssign = - 1; } if(refDestructuringErrors.parenthesizedBind >= result.start){ refDestructuringErrors.parenthesizedBind = - 1; } } return result; }; pp$3.parseSubscripts = function(base,startPos,startLoc,noCalls){ var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" && this.lastTokEnd === base.end && !this.canInsertSemicolon() && this.input.slice(base.start,base.end) === "async"; while(true){ var element = this.parseSubscript(base,startPos,startLoc,noCalls,maybeAsyncArrow); if(element === base || element.type === "ArrowFunctionExpression"){ return element; } base = element; } }; pp$3.parseSubscript = function(base,startPos,startLoc,noCalls,maybeAsyncArrow){ var computed = this.eat(types.bracketL); if(computed || this.eat(types.dot)){ var node = this.startNodeAt(startPos,startLoc); node.object = base; node.property = computed?this.parseExpression():this.parseIdent(this.options.allowReserved !== "never"); node.computed = !!computed; if(computed){ this.expect(types.bracketR); } base = this.finishNode(node,"MemberExpression"); }else if(!noCalls && this.eat(types.parenL)){ var refDestructuringErrors = new DestructuringErrors,oldYieldPos = this.yieldPos,oldAwaitPos = this.awaitPos,oldAwaitIdentPos = this.awaitIdentPos; this.yieldPos = 0; this.awaitPos = 0; this.awaitIdentPos = 0; var exprList = this.parseExprList(types.parenR,this.options.ecmaVersion >= 8,false,refDestructuringErrors); if(maybeAsyncArrow && !this.canInsertSemicolon() && this.eat(types.arrow)){ this.checkPatternErrors(refDestructuringErrors,false); this.checkYieldAwaitInDefaultParams(); if(this.awaitIdentPos > 0){ this.raise(this.awaitIdentPos,"Cannot use 'await' as identifier inside an async function"); } this.yieldPos = oldYieldPos; this.awaitPos = oldAwaitPos; this.awaitIdentPos = oldAwaitIdentPos; return this.parseArrowExpression(this.startNodeAt(startPos,startLoc),exprList,true); } this.checkExpressionErrors(refDestructuringErrors,true); this.yieldPos = oldYieldPos || this.yieldPos; this.awaitPos = oldAwaitPos || this.awaitPos; this.awaitIdentPos = oldAwaitIdentPos || this.awaitIdentPos; var node$1 = this.startNodeAt(startPos,startLoc); node$1.callee = base; node$1.arguments = exprList; base = this.finishNode(node$1,"CallExpression"); }else if(this.type === types.backQuote){ var node$2 = this.startNodeAt(startPos,startLoc); node$2.tag = base; node$2.quasi = this.parseTemplate({isTagged:true}); base = this.finishNode(node$2,"TaggedTemplateExpression"); } return base; }; pp$3.parseExprAtom = function(refDestructuringErrors){ if(this.type === types.slash){ this.readRegexp(); } var node,canBeArrow = this.potentialArrowAt === this.start; switch(this.type){ case types._super: if(!this.allowSuper){ this.raise(this.start,"'super' keyword outside a method"); } node = this.startNode(); this.next(); if(this.type === types.parenL && !this.allowDirectSuper){ this.raise(node.start,"super() call outside constructor of a subclass"); } if(this.type !== types.dot && this.type !== types.bracketL && this.type !== types.parenL){ this.unexpected(); } return this.finishNode(node,"Super"); case types._this: node = this.startNode(); this.next(); return this.finishNode(node,"ThisExpression"); case types.name: var startPos = this.start,startLoc = this.startLoc,containsEsc = this.containsEsc; var id = this.parseIdent(false); if(this.options.ecmaVersion >= 8 && !containsEsc && id.name === "async" && !this.canInsertSemicolon() && this.eat(types._function)){ return this.parseFunction(this.startNodeAt(startPos,startLoc),0,false,true); } if(canBeArrow && !this.canInsertSemicolon()){ if(this.eat(types.arrow)){ return this.parseArrowExpression(this.startNodeAt(startPos,startLoc),[id],false); } if(this.options.ecmaVersion >= 8 && id.name === "async" && this.type === types.name && !containsEsc){ id = this.parseIdent(false); if(this.canInsertSemicolon() || !this.eat(types.arrow)){ this.unexpected(); } return this.parseArrowExpression(this.startNodeAt(startPos,startLoc),[id],true); } } return id; case types.regexp: var value = this.value; node = this.parseLiteral(value.value); node.regex = {pattern:value.pattern,flags:value.flags}; return node; case types.num: case types.string: return this.parseLiteral(this.value); case types._null: case types._true: case types._false: node = this.startNode(); node.value = this.type === types._null?null:this.type === types._true; node.raw = this.type.keyword; this.next(); return this.finishNode(node,"Literal"); case types.parenL: var start = this.start,expr = this.parseParenAndDistinguishExpression(canBeArrow); if(refDestructuringErrors){ if(refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr)){ refDestructuringErrors.parenthesizedAssign = start; } if(refDestructuringErrors.parenthesizedBind < 0){ refDestructuringErrors.parenthesizedBind = start; } } return expr; case types.bracketL: node = this.startNode(); this.next(); node.elements = this.parseExprList(types.bracketR,true,true,refDestructuringErrors); return this.finishNode(node,"ArrayExpression"); case types.braceL: return this.parseObj(false,refDestructuringErrors); case types._function: node = this.startNode(); this.next(); return this.parseFunction(node,0); case types._class: return this.parseClass(this.startNode(),false); case types._new: return this.parseNew(); case types.backQuote: return this.parseTemplate(); case types._import: if(this.options.ecmaVersion >= 11){ return this.parseExprImport(); }else{ return this.unexpected(); } default: this.unexpected(); } }; pp$3.parseExprImport = function(){ var node = this.startNode(); this.next(); switch(this.type){ case types.parenL: return this.parseDynamicImport(node); default: this.unexpected(); } }; pp$3.parseDynamicImport = function(node){ this.next(); node.source = this.parseMaybeAssign(); if(!this.eat(types.parenR)){ var errorPos = this.start; if(this.eat(types.comma) && this.eat(types.parenR)){ this.raiseRecoverable(errorPos,"Trailing comma is not allowed in import()"); }else{ this.unexpected(errorPos); } } return this.finishNode(node,"ImportExpression"); }; pp$3.parseLiteral = function(value){ var node = this.startNode(); node.value = value; node.raw = this.input.slice(this.start,this.end); if(node.raw.charCodeAt(node.raw.length - 1) === 110){ node.bigint = node.raw.slice(0,- 1); } this.next(); return this.finishNode(node,"Literal"); }; pp$3.parseParenExpression = function(){ this.expect(types.parenL); var val = this.parseExpression(); this.expect(types.parenR); return val; }; pp$3.parseParenAndDistinguishExpression = function(canBeArrow){ var startPos = this.start,startLoc = this.startLoc,val,allowTrailingComma = this.options.ecmaVersion >= 8; if(this.options.ecmaVersion >= 6){ this.next(); var innerStartPos = this.start,innerStartLoc = this.startLoc; var exprList = [],first = true,lastIsComma = false; var refDestructuringErrors = new DestructuringErrors,oldYieldPos = this.yieldPos,oldAwaitPos = this.awaitPos,spreadStart; this.yieldPos = 0; this.awaitPos = 0; while(this.type !== types.parenR){ first?first = false:this.expect(types.comma); if(allowTrailingComma && this.afterTrailingComma(types.parenR,true)){ lastIsComma = true; break; }else if(this.type === types.ellipsis){ spreadStart = this.start; exprList.push(this.parseParenItem(this.parseRestBinding())); if(this.type === types.comma){ this.raise(this.start,"Comma is not permitted after the rest element"); } break; }else{ exprList.push(this.parseMaybeAssign(false,refDestructuringErrors,this.parseParenItem)); } } var innerEndPos = this.start,innerEndLoc = this.startLoc; this.expect(types.parenR); if(canBeArrow && !this.canInsertSemicolon() && this.eat(types.arrow)){ this.checkPatternErrors(refDestructuringErrors,false); this.checkYieldAwaitInDefaultParams(); this.yieldPos = oldYieldPos; this.awaitPos = oldAwaitPos; return this.parseParenArrowList(startPos,startLoc,exprList); } if(!exprList.length || lastIsComma){ this.unexpected(this.lastTokStart); } if(spreadStart){ this.unexpected(spreadStart); } this.checkExpressionErrors(refDestructuringErrors,true); this.yieldPos = oldYieldPos || this.yieldPos; this.awaitPos = oldAwaitPos || this.awaitPos; if(exprList.length > 1){ val = this.startNodeAt(innerStartPos,innerStartLoc); val.expressions = exprList; this.finishNodeAt(val,"SequenceExpression",innerEndPos,innerEndLoc); }else{ val = exprList[0]; } }else{ val = this.parseParenExpression(); } if(this.options.preserveParens){ var par = this.startNodeAt(startPos,startLoc); par.expression = val; return this.finishNode(par,"ParenthesizedExpression"); }else{ return val; } }; pp$3.parseParenItem = function(item){ return item; }; pp$3.parseParenArrowList = function(startPos,startLoc,exprList){ return this.parseArrowExpression(this.startNodeAt(startPos,startLoc),exprList); }; var empty$1 = []; pp$3.parseNew = function(){ if(this.containsEsc){ this.raiseRecoverable(this.start,"Escape sequence in keyword new"); } var node = this.startNode(); var meta = this.parseIdent(true); if(this.options.ecmaVersion >= 6 && this.eat(types.dot)){ node.meta = meta; var containsEsc = this.containsEsc; node.property = this.parseIdent(true); if(node.property.name !== "target" || containsEsc){ this.raiseRecoverable(node.property.start,"The only valid meta property for new is new.target"); } if(!this.inNonArrowFunction()){ this.raiseRecoverable(node.start,"new.target can only be used in functions"); } return this.finishNode(node,"MetaProperty"); } var startPos = this.start,startLoc = this.startLoc,isImport = this.type === types._import; node.callee = this.parseSubscripts(this.parseExprAtom(),startPos,startLoc,true); if(isImport && node.callee.type === "ImportExpression"){ this.raise(startPos,"Cannot use new with import()"); } if(this.eat(types.parenL)){ node.arguments = this.parseExprList(types.parenR,this.options.ecmaVersion >= 8,false); }else{ node.arguments = empty$1; } return this.finishNode(node,"NewExpression"); }; pp$3.parseTemplateElement = function(ref){ var isTagged = ref.isTagged; var elem = this.startNode(); if(this.type === types.invalidTemplate){ if(!isTagged){ this.raiseRecoverable(this.start,"Bad escape sequence in untagged template literal"); } elem.value = { raw:this.value,cooked:null }; }else{ elem.value = { raw:this.input.slice(this.start,this.end).replace(/\r\n?/g,"\n"),cooked:this.value }; } this.next(); elem.tail = this.type === types.backQuote; return this.finishNode(elem,"TemplateElement"); }; pp$3.parseTemplate = function(ref){ if(ref === void 0){ ref = {}; } var isTagged = ref.isTagged; if(isTagged === void 0){ isTagged = false; } var node = this.startNode(); this.next(); node.expressions = []; var curElt = this.parseTemplateElement({isTagged:isTagged}); node.quasis = [curElt]; while(!curElt.tail){ if(this.type === types.eof){ this.raise(this.pos,"Unterminated template literal"); } this.expect(types.dollarBraceL); node.expressions.push(this.parseExpression()); this.expect(types.braceR); node.quasis.push(curElt = this.parseTemplateElement({isTagged:isTagged})); } this.next(); return this.finishNode(node,"TemplateLiteral"); }; pp$3.isAsyncProp = function(prop){ return !prop.computed && prop.key.type === "Identifier" && prop.key.name === "async" && (this.type === types.name || this.type === types.num || this.type === types.string || this.type === types.bracketL || this.type.keyword || (this.options.ecmaVersion >= 9 && this.type === types.star)) && !lineBreak.test(this.input.slice(this.lastTokEnd,this.start)); }; pp$3.parseObj = function(isPattern,refDestructuringErrors){ var node = this.startNode(),first = true,propHash = {}; node.properties = []; this.next(); while(!this.eat(types.braceR)){ if(!first){ this.expect(types.comma); if(this.options.ecmaVersion >= 5 && this.afterTrailingComma(types.braceR)){ break; } }else{ first = false; } var prop = this.parseProperty(isPattern,refDestructuringErrors); if(!isPattern){ this.checkPropClash(prop,propHash,refDestructuringErrors); } node.properties.push(prop); } return this.finishNode(node,isPattern?"ObjectPattern":"ObjectExpression"); }; pp$3.parseProperty = function(isPattern,refDestructuringErrors){ var prop = this.startNode(),isGenerator,isAsync,startPos,startLoc; if(this.options.ecmaVersion >= 9 && this.eat(types.ellipsis)){ if(isPattern){ prop.argument = this.parseIdent(false); if(this.type === types.comma){ this.raise(this.start,"Comma is not permitted after the rest element"); } return this.finishNode(prop,"RestElement"); } if(this.type === types.parenL && refDestructuringErrors){ if(refDestructuringErrors.parenthesizedAssign < 0){ refDestructuringErrors.parenthesizedAssign = this.start; } if(refDestructuringErrors.parenthesizedBind < 0){ refDestructuringErrors.parenthesizedBind = this.start; } } prop.argument = this.parseMaybeAssign(false,refDestructuringErrors); if(this.type === types.comma && refDestructuringErrors && refDestructuringErrors.trailingComma < 0){ refDestructuringErrors.trailingComma = this.start; } return this.finishNode(prop,"SpreadElement"); } if(this.options.ecmaVersion >= 6){ prop.method = false; prop.shorthand = false; if(isPattern || refDestructuringErrors){ startPos = this.start; startLoc = this.startLoc; } if(!isPattern){ isGenerator = this.eat(types.star); } } var containsEsc = this.containsEsc; this.parsePropertyName(prop); if(!isPattern && !containsEsc && this.options.ecmaVersion >= 8 && !isGenerator && this.isAsyncProp(prop)){ isAsync = true; isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star); this.parsePropertyName(prop,refDestructuringErrors); }else{ isAsync = false; } this.parsePropertyValue(prop,isPattern,isGenerator,isAsync,startPos,startLoc,refDestructuringErrors,containsEsc); return this.finishNode(prop,"Property"); }; pp$3.parsePropertyValue = function(prop,isPattern,isGenerator,isAsync,startPos,startLoc,refDestructuringErrors,containsEsc){ if((isGenerator || isAsync) && this.type === types.colon){ this.unexpected(); } if(this.eat(types.colon)){ prop.value = isPattern?this.parseMaybeDefault(this.start,this.startLoc):this.parseMaybeAssign(false,refDestructuringErrors); prop.kind = "init"; }else if(this.options.ecmaVersion >= 6 && this.type === types.parenL){ if(isPattern){ this.unexpected(); } prop.kind = "init"; prop.method = true; prop.value = this.parseMethod(isGenerator,isAsync); }else if(!isPattern && !containsEsc && this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && (prop.key.name === "get" || prop.key.name === "set") && (this.type !== types.comma && this.type !== types.braceR)){ if(isGenerator || isAsync){ this.unexpected(); } prop.kind = prop.key.name; this.parsePropertyName(prop); prop.value = this.parseMethod(false); var paramCount = prop.kind === "get"?0:1; if(prop.value.params.length !== paramCount){ var start = prop.value.start; if(prop.kind === "get"){ this.raiseRecoverable(start,"getter should have no params"); }else{ this.raiseRecoverable(start,"setter should have exactly one param"); } }else{ if(prop.kind === "set" && prop.value.params[0].type === "RestElement"){ this.raiseRecoverable(prop.value.params[0].start,"Setter cannot use rest params"); } } }else if(this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier"){ if(isGenerator || isAsync){ this.unexpected(); } this.checkUnreserved(prop.key); if(prop.key.name === "await" && !this.awaitIdentPos){ this.awaitIdentPos = startPos; } prop.kind = "init"; if(isPattern){ prop.value = this.parseMaybeDefault(startPos,startLoc,prop.key); }else if(this.type === types.eq && refDestructuringErrors){ if(refDestructuringErrors.shorthandAssign < 0){ refDestructuringErrors.shorthandAssign = this.start; } prop.value = this.parseMaybeDefault(startPos,startLoc,prop.key); }else{ prop.value = prop.key; } prop.shorthand = true; }else{ this.unexpected(); } }; pp$3.parsePropertyName = function(prop){ if(this.options.ecmaVersion >= 6){ if(this.eat(types.bracketL)){ prop.computed = true; prop.key = this.parseMaybeAssign(); this.expect(types.bracketR); return prop.key; }else{ prop.computed = false; } } return prop.key = this.type === types.num || this.type === types.string?this.parseExprAtom():this.parseIdent(this.options.allowReserved !== "never"); }; pp$3.initFunction = function(node){ node.id = null; if(this.options.ecmaVersion >= 6){ node.generator = node.expression = false; } if(this.options.ecmaVersion >= 8){ node.async = false; } }; pp$3.parseMethod = function(isGenerator,isAsync,allowDirectSuper){ var node = this.startNode(),oldYieldPos = this.yieldPos,oldAwaitPos = this.awaitPos,oldAwaitIdentPos = this.awaitIdentPos; this.initFunction(node); if(this.options.ecmaVersion >= 6){ node.generator = isGenerator; } if(this.options.ecmaVersion >= 8){ node.async = !!isAsync; } this.yieldPos = 0; this.awaitPos = 0; this.awaitIdentPos = 0; this.enterScope(functionFlags(isAsync,node.generator) | SCOPE_SUPER | (allowDirectSuper?SCOPE_DIRECT_SUPER:0)); this.expect(types.parenL); node.params = this.parseBindingList(types.parenR,false,this.options.ecmaVersion >= 8); this.checkYieldAwaitInDefaultParams(); this.parseFunctionBody(node,false,true); this.yieldPos = oldYieldPos; this.awaitPos = oldAwaitPos; this.awaitIdentPos = oldAwaitIdentPos; return this.finishNode(node,"FunctionExpression"); }; pp$3.parseArrowExpression = function(node,params,isAsync){ var oldYieldPos = this.yieldPos,oldAwaitPos = this.awaitPos,oldAwaitIdentPos = this.awaitIdentPos; this.enterScope(functionFlags(isAsync,false) | SCOPE_ARROW); this.initFunction(node); if(this.options.ecmaVersion >= 8){ node.async = !!isAsync; } this.yieldPos = 0; this.awaitPos = 0; this.awaitIdentPos = 0; node.params = this.toAssignableList(params,true); this.parseFunctionBody(node,true,false); this.yieldPos = oldYieldPos; this.awaitPos = oldAwaitPos; this.awaitIdentPos = oldAwaitIdentPos; return this.finishNode(node,"ArrowFunctionExpression"); }; pp$3.parseFunctionBody = function(node,isArrowFunction,isMethod){ var isExpression = isArrowFunction && this.type !== types.braceL; var oldStrict = this.strict,useStrict = false; if(isExpression){ node.body = this.parseMaybeAssign(); node.expression = true; this.checkParams(node,false); }else{ var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params); if(!oldStrict || nonSimple){ useStrict = this.strictDirective(this.end); if(useStrict && nonSimple){ this.raiseRecoverable(node.start,"Illegal 'use strict' directive in function with non-simple parameter list"); } } var oldLabels = this.labels; this.labels = []; if(useStrict){ this.strict = true; } this.checkParams(node,!oldStrict && !useStrict && !isArrowFunction && !isMethod && this.isSimpleParamList(node.params)); node.body = this.parseBlock(false); node.expression = false; this.adaptDirectivePrologue(node.body.body); this.labels = oldLabels; } this.exitScope(); if(this.strict && node.id){ this.checkLVal(node.id,BIND_OUTSIDE); } this.strict = oldStrict; }; pp$3.isSimpleParamList = function(params){ for(var i = 0,list = params; i < list.length; i += 1){ var param = list[i]; if(param.type !== "Identifier"){ return false; } } return true; }; pp$3.checkParams = function(node,allowDuplicates){ var nameHash = {}; for(var i = 0,list = node.params; i < list.length; i += 1){ var param = list[i]; this.checkLVal(param,BIND_VAR,allowDuplicates?null:nameHash); } }; pp$3.parseExprList = function(close,allowTrailingComma,allowEmpty,refDestructuringErrors){ var elts = [],first = true; while(!this.eat(close)){ if(!first){ this.expect(types.comma); if(allowTrailingComma && this.afterTrailingComma(close)){ break; } }else{ first = false; } var elt = (void 0); if(allowEmpty && this.type === types.comma){ elt = null; }else if(this.type === types.ellipsis){ elt = this.parseSpread(refDestructuringErrors); if(refDestructuringErrors && this.type === types.comma && refDestructuringErrors.trailingComma < 0){ refDestructuringErrors.trailingComma = this.start; } }else{ elt = this.parseMaybeAssign(false,refDestructuringErrors); } elts.push(elt); } return elts; }; pp$3.checkUnreserved = function(ref){ var start = ref.start; var end = ref.end; var name = ref.name; if(this.inGenerator && name === "yield"){ this.raiseRecoverable(start,"Cannot use 'yield' as identifier inside a generator"); } if(this.inAsync && name === "await"){ this.raiseRecoverable(start,"Cannot use 'await' as identifier inside an async function"); } if(this.keywords.test(name)){ this.raise(start,("Unexpected keyword '" + name + "'")); } if(this.options.ecmaVersion < 6 && this.input.slice(start,end).indexOf("\\") !== - 1){ return; } var re = this.strict?this.reservedWordsStrict:this.reservedWords; if(re.test(name)){ if(!this.inAsync && name === "await"){ this.raiseRecoverable(start,"Cannot use keyword 'await' outside an async function"); } this.raiseRecoverable(start,("The keyword '" + name + "' is reserved")); } }; pp$3.parseIdent = function(liberal,isBinding){ var node = this.startNode(); if(this.type === types.name){ node.name = this.value; }else if(this.type.keyword){ node.name = this.type.keyword; if((node.name === "class" || node.name === "function") && (this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46)){ this.context.pop(); } }else{ this.unexpected(); } this.next(!!liberal); this.finishNode(node,"Identifier"); if(!liberal){ this.checkUnreserved(node); if(node.name === "await" && !this.awaitIdentPos){ this.awaitIdentPos = node.start; } } return node; }; pp$3.parseYield = function(noIn){ if(!this.yieldPos){ this.yieldPos = this.start; } var node = this.startNode(); this.next(); if(this.type === types.semi || this.canInsertSemicolon() || (this.type !== types.star && !this.type.startsExpr)){ node.delegate = false; node.argument = null; }else{ node.delegate = this.eat(types.star); node.argument = this.parseMaybeAssign(noIn); } return this.finishNode(node,"YieldExpression"); }; pp$3.parseAwait = function(){ if(!this.awaitPos){ this.awaitPos = this.start; } var node = this.startNode(); this.next(); node.argument = this.parseMaybeUnary(null,false); return this.finishNode(node,"AwaitExpression"); }; var pp$4 = Parser.prototype; pp$4.raise = function(pos,message){ var loc = getLineInfo(this.input,pos); message += " (" + loc.line + ":" + loc.column + ")"; var err = new SyntaxError(message); err.pos = pos; err.loc = loc; err.raisedAt = this.pos; throw err; }; pp$4.raiseRecoverable = pp$4.raise; pp$4.curPosition = function(){ if(this.options.locations){ return new Position(this.curLine,this.pos - this.lineStart); } }; var pp$5 = Parser.prototype; var Scope = function Scope(flags){ this.flags = flags; this.var = []; this.lexical = []; this.functions = []; }; pp$5.enterScope = function(flags){ this.scopeStack.push(new Scope(flags)); }; pp$5.exitScope = function(){ this.scopeStack.pop(); }; pp$5.treatFunctionsAsVarInScope = function(scope){ return (scope.flags & SCOPE_FUNCTION) || !this.inModule && (scope.flags & SCOPE_TOP); }; pp$5.declareName = function(name,bindingType,pos){ var redeclared = false; if(bindingType === BIND_LEXICAL){ var scope = this.currentScope(); redeclared = scope.lexical.indexOf(name) > - 1 || scope.functions.indexOf(name) > - 1 || scope.var.indexOf(name) > - 1; scope.lexical.push(name); if(this.inModule && (scope.flags & SCOPE_TOP)){ delete this.undefinedExports[name]; } }else if(bindingType === BIND_SIMPLE_CATCH){ var scope$1 = this.currentScope(); scope$1.lexical.push(name); }else if(bindingType === BIND_FUNCTION){ var scope$2 = this.currentScope(); if(this.treatFunctionsAsVar){ redeclared = scope$2.lexical.indexOf(name) > - 1; }else{ redeclared = scope$2.lexical.indexOf(name) > - 1 || scope$2.var.indexOf(name) > - 1; } scope$2.functions.push(name); }else{ for(var i = this.scopeStack.length - 1; i >= 0; -- i){ var scope$3 = this.scopeStack[i]; if(scope$3.lexical.indexOf(name) > - 1 && !((scope$3.flags & SCOPE_SIMPLE_CATCH) && scope$3.lexical[0] === name) || !this.treatFunctionsAsVarInScope(scope$3) && scope$3.functions.indexOf(name) > - 1){ redeclared = true; break; } scope$3.var.push(name); if(this.inModule && (scope$3.flags & SCOPE_TOP)){ delete this.undefinedExports[name]; } if(scope$3.flags & SCOPE_VAR){ break; } } } if(redeclared){ this.raiseRecoverable(pos,("Identifier '" + name + "' has already been declared")); } }; pp$5.checkLocalExport = function(id){ if(this.scopeStack[0].lexical.indexOf(id.name) === - 1 && this.scopeStack[0].var.indexOf(id.name) === - 1){ this.undefinedExports[id.name] = id; } }; pp$5.currentScope = function(){ return this.scopeStack[this.scopeStack.length - 1]; }; pp$5.currentVarScope = function(){ for(var i = this.scopeStack.length - 1; ; i --){ var scope = this.scopeStack[i]; if(scope.flags & SCOPE_VAR){ return scope; } } }; pp$5.currentThisScope = function(){ for(var i = this.scopeStack.length - 1; ; i --){ var scope = this.scopeStack[i]; if(scope.flags & SCOPE_VAR && !(scope.flags & SCOPE_ARROW)){ return scope; } } }; var Node = function Node(parser,pos,loc){ this.type = ""; this.start = pos; this.end = 0; if(parser.options.locations){ this.loc = new SourceLocation(parser,loc); } if(parser.options.directSourceFile){ this.sourceFile = parser.options.directSourceFile; } if(parser.options.ranges){ this.range = [pos,0]; } }; var pp$6 = Parser.prototype; pp$6.startNode = function(){ return new Node(this,this.start,this.startLoc); }; pp$6.startNodeAt = function(pos,loc){ return new Node(this,pos,loc); }; function finishNodeAt(node,type,pos,loc){ node.type = type; node.end = pos; if(this.options.locations){ node.loc.end = loc; } if(this.options.ranges){ node.range[1] = pos; } return node; } pp$6.finishNode = function(node,type){ return finishNodeAt.call(this,node,type,this.lastTokEnd,this.lastTokEndLoc); }; pp$6.finishNodeAt = function(node,type,pos,loc){ return finishNodeAt.call(this,node,type,pos,loc); }; var TokContext = function TokContext(token,isExpr,preserveSpace,override,generator){ this.token = token; this.isExpr = !!isExpr; this.preserveSpace = !!preserveSpace; this.override = override; this.generator = !!generator; }; var types$1 = { b_stat:new TokContext("{",false),b_expr:new TokContext("{",true),b_tmpl:new TokContext("${",false),p_stat:new TokContext("(",false),p_expr:new TokContext("(",true),q_tmpl:new TokContext("`",true,true,function(p){ return p.tryReadTemplateToken(); }),f_stat:new TokContext("function",false),f_expr:new TokContext("function",true),f_expr_gen:new TokContext("function",true,false,null,true),f_gen:new TokContext("function",false,false,null,true) }; var pp$7 = Parser.prototype; pp$7.initialContext = function(){ return [types$1.b_stat]; }; pp$7.braceIsBlock = function(prevType){ var parent = this.curContext(); if(parent === types$1.f_expr || parent === types$1.f_stat){ return true; } if(prevType === types.colon && (parent === types$1.b_stat || parent === types$1.b_expr)){ return !parent.isExpr; } if(prevType === types._return || prevType === types.name && this.exprAllowed){ return lineBreak.test(this.input.slice(this.lastTokEnd,this.start)); } if(prevType === types._else || prevType === types.semi || prevType === types.eof || prevType === types.parenR || prevType === types.arrow){ return true; } if(prevType === types.braceL){ return parent === types$1.b_stat; } if(prevType === types._var || prevType === types._const || prevType === types.name){ return false; } return !this.exprAllowed; }; pp$7.inGeneratorContext = function(){ for(var i = this.context.length - 1; i >= 1; i --){ var context = this.context[i]; if(context.token === "function"){ return context.generator; } } return false; }; pp$7.updateContext = function(prevType){ var update,type = this.type; if(type.keyword && prevType === types.dot){ this.exprAllowed = false; }else if(update = type.updateContext){ update.call(this,prevType); }else{ this.exprAllowed = type.beforeExpr; } }; types.parenR.updateContext = types.braceR.updateContext = function(){ if(this.context.length === 1){ this.exprAllowed = true; return; } var out = this.context.pop(); if(out === types$1.b_stat && this.curContext().token === "function"){ out = this.context.pop(); } this.exprAllowed = !out.isExpr; }; types.braceL.updateContext = function(prevType){ this.context.push(this.braceIsBlock(prevType)?types$1.b_stat:types$1.b_expr); this.exprAllowed = true; }; types.dollarBraceL.updateContext = function(){ this.context.push(types$1.b_tmpl); this.exprAllowed = true; }; types.parenL.updateContext = function(prevType){ var statementParens = prevType === types._if || prevType === types._for || prevType === types._with || prevType === types._while; this.context.push(statementParens?types$1.p_stat:types$1.p_expr); this.exprAllowed = true; }; types.incDec.updateContext = function(){ }; types._function.updateContext = types._class.updateContext = function(prevType){ if(prevType.beforeExpr && prevType !== types.semi && prevType !== types._else && !(prevType === types._return && lineBreak.test(this.input.slice(this.lastTokEnd,this.start))) && !((prevType === types.colon || prevType === types.braceL) && this.curContext() === types$1.b_stat)){ this.context.push(types$1.f_expr); }else{ this.context.push(types$1.f_stat); } this.exprAllowed = false; }; types.backQuote.updateContext = function(){ if(this.curContext() === types$1.q_tmpl){ this.context.pop(); }else{ this.context.push(types$1.q_tmpl); } this.exprAllowed = false; }; types.star.updateContext = function(prevType){ if(prevType === types._function){ var index = this.context.length - 1; if(this.context[index] === types$1.f_expr){ this.context[index] = types$1.f_expr_gen; }else{ this.context[index] = types$1.f_gen; } } this.exprAllowed = true; }; types.name.updateContext = function(prevType){ var allowed = false; if(this.options.ecmaVersion >= 6 && prevType !== types.dot){ if(this.value === "of" && !this.exprAllowed || this.value === "yield" && this.inGeneratorContext()){ allowed = true; } } this.exprAllowed = allowed; }; var ecma9BinaryProperties = "ASCII ASCII_Hex_Digit AHex Alphabetic Alpha Any Assigned Bidi_Control Bidi_C Bidi_Mirrored Bidi_M Case_Ignorable CI Cased Changes_When_Casefolded CWCF Changes_When_Casemapped CWCM Changes_When_Lowercased CWL Changes_When_NFKC_Casefolded CWKCF Changes_When_Titlecased CWT Changes_When_Uppercased CWU Dash Default_Ignorable_Code_Point DI Deprecated Dep Diacritic Dia Emoji Emoji_Component Emoji_Modifier Emoji_Modifier_Base Emoji_Presentation Extender Ext Grapheme_Base Gr_Base Grapheme_Extend Gr_Ext Hex_Digit Hex IDS_Binary_Operator IDSB IDS_Trinary_Operator IDST ID_Continue IDC ID_Start IDS Ideographic Ideo Join_Control Join_C Logical_Order_Exception LOE Lowercase Lower Math Noncharacter_Code_Point NChar Pattern_Syntax Pat_Syn Pattern_White_Space Pat_WS Quotation_Mark QMark Radical Regional_Indicator RI Sentence_Terminal STerm Soft_Dotted SD Terminal_Punctuation Term Unified_Ideograph UIdeo Uppercase Upper Variation_Selector VS White_Space space XID_Continue XIDC XID_Start XIDS"; var ecma10BinaryProperties = ecma9BinaryProperties + " Extended_Pictographic"; var ecma11BinaryProperties = ecma10BinaryProperties; var unicodeBinaryProperties = { 9:ecma9BinaryProperties,10:ecma10BinaryProperties,11:ecma11BinaryProperties }; var unicodeGeneralCategoryValues = "Cased_Letter LC Close_Punctuation Pe Connector_Punctuation Pc Control Cc cntrl Currency_Symbol Sc Dash_Punctuation Pd Decimal_Number Nd digit Enclosing_Mark Me Final_Punctuation Pf Format Cf Initial_Punctuation Pi Letter L Letter_Number Nl Line_Separator Zl Lowercase_Letter Ll Mark M Combining_Mark Math_Symbol Sm Modifier_Letter Lm Modifier_Symbol Sk Nonspacing_Mark Mn Number N Open_Punctuation Ps Other C Other_Letter Lo Other_Number No Other_Punctuation Po Other_Symbol So Paragraph_Separator Zp Private_Use Co Punctuation P punct Separator Z Space_Separator Zs Spacing_Mark Mc Surrogate Cs Symbol S Titlecase_Letter Lt Unassigned Cn Uppercase_Letter Lu"; var ecma9ScriptValues = "Adlam Adlm Ahom Ahom Anatolian_Hieroglyphs Hluw Arabic Arab Armenian Armn Avestan Avst Balinese Bali Bamum Bamu Bassa_Vah Bass Batak Batk Bengali Beng Bhaiksuki Bhks Bopomofo Bopo Brahmi Brah Braille Brai Buginese Bugi Buhid Buhd Canadian_Aboriginal Cans Carian Cari Caucasian_Albanian Aghb Chakma Cakm Cham Cham Cherokee Cher Common Zyyy Coptic Copt Qaac Cuneiform Xsux Cypriot Cprt Cyrillic Cyrl Deseret Dsrt Devanagari Deva Duployan Dupl Egyptian_Hieroglyphs Egyp Elbasan Elba Ethiopic Ethi Georgian Geor Glagolitic Glag Gothic Goth Grantha Gran Greek Grek Gujarati Gujr Gurmukhi Guru Han Hani Hangul Hang Hanunoo Hano Hatran Hatr Hebrew Hebr Hiragana Hira Imperial_Aramaic Armi Inherited Zinh Qaai Inscriptional_Pahlavi Phli Inscriptional_Parthian Prti Javanese Java Kaithi Kthi Kannada Knda Katakana Kana Kayah_Li Kali Kharoshthi Khar Khmer Khmr Khojki Khoj Khudawadi Sind Lao Laoo Latin Latn Lepcha Lepc Limbu Limb Linear_A Lina Linear_B Linb Lisu Lisu Lycian Lyci Lydian Lydi Mahajani Mahj Malayalam Mlym Mandaic Mand Manichaean Mani Marchen Marc Masaram_Gondi Gonm Meetei_Mayek Mtei Mende_Kikakui Mend Meroitic_Cursive Merc Meroitic_Hieroglyphs Mero Miao Plrd Modi Modi Mongolian Mong Mro Mroo Multani Mult Myanmar Mymr Nabataean Nbat New_Tai_Lue Talu Newa Newa Nko Nkoo Nushu Nshu Ogham Ogam Ol_Chiki Olck Old_Hungarian Hung Old_Italic Ital Old_North_Arabian Narb Old_Permic Perm Old_Persian Xpeo Old_South_Arabian Sarb Old_Turkic Orkh Oriya Orya Osage Osge Osmanya Osma Pahawh_Hmong Hmng Palmyrene Palm Pau_Cin_Hau Pauc Phags_Pa Phag Phoenician Phnx Psalter_Pahlavi Phlp Rejang Rjng Runic Runr Samaritan Samr Saurashtra Saur Sharada Shrd Shavian Shaw Siddham Sidd SignWriting Sgnw Sinhala Sinh Sora_Sompeng Sora Soyombo Soyo Sundanese Sund Syloti_Nagri Sylo Syriac Syrc Tagalog Tglg Tagbanwa Tagb Tai_Le Tale Tai_Tham Lana Tai_Viet Tavt Takri Takr Tamil Taml Tangut Tang Telugu Telu Thaana Thaa Thai Thai Tibetan Tibt Tifinagh Tfng Tirhuta Tirh Ugaritic Ugar Vai Vaii Warang_Citi Wara Yi Yiii Zanabazar_Square Zanb"; var ecma10ScriptValues = ecma9ScriptValues + " Dogra Dogr Gunjala_Gondi Gong Hanifi_Rohingya Rohg Makasar Maka Medefaidrin Medf Old_Sogdian Sogo Sogdian Sogd"; var ecma11ScriptValues = ecma10ScriptValues + " Elymaic Elym Nandinagari Nand Nyiakeng_Puachue_Hmong Hmnp Wancho Wcho"; var unicodeScriptValues = { 9:ecma9ScriptValues,10:ecma10ScriptValues,11:ecma11ScriptValues }; var data = {}; function buildUnicodeData(ecmaVersion){ var d = data[ecmaVersion] = { binary:wordsRegexp(unicodeBinaryProperties[ecmaVersion] + " " + unicodeGeneralCategoryValues),nonBinary:{ General_Category:wordsRegexp(unicodeGeneralCategoryValues),Script:wordsRegexp(unicodeScriptValues[ecmaVersion]) } }; d.nonBinary.Script_Extensions = d.nonBinary.Script; d.nonBinary.gc = d.nonBinary.General_Category; d.nonBinary.sc = d.nonBinary.Script; d.nonBinary.scx = d.nonBinary.Script_Extensions; } buildUnicodeData(9); buildUnicodeData(10); buildUnicodeData(11); var pp$8 = Parser.prototype; var RegExpValidationState = function RegExpValidationState(parser){ this.parser = parser; this.validFlags = "gim" + (parser.options.ecmaVersion >= 6?"uy":"") + (parser.options.ecmaVersion >= 9?"s":""); this.unicodeProperties = data[parser.options.ecmaVersion >= 11?11:parser.options.ecmaVersion]; this.source = ""; this.flags = ""; this.start = 0; this.switchU = false; this.switchN = false; this.pos = 0; this.lastIntValue = 0; this.lastStringValue = ""; this.lastAssertionIsQuantifiable = false; this.numCapturingParens = 0; this.maxBackReference = 0; this.groupNames = []; this.backReferenceNames = []; }; RegExpValidationState.prototype.reset = function reset(start,pattern,flags){ var unicode = flags.indexOf("u") !== - 1; this.start = start | 0; this.source = pattern + ""; this.flags = flags; this.switchU = unicode && this.parser.options.ecmaVersion >= 6; this.switchN = unicode && this.parser.options.ecmaVersion >= 9; }; RegExpValidationState.prototype.raise = function raise(message){ this.parser.raiseRecoverable(this.start,("Invalid regular expression: /" + (this.source) + "/: " + message)); }; RegExpValidationState.prototype.at = function at(i){ var s = this.source; var l = s.length; if(i >= l){ return - 1; } var c = s.charCodeAt(i); if(!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l){ return c; } var next = s.charCodeAt(i + 1); return next >= 0xDC00 && next <= 0xDFFF?(c << 10) + next - 0x35FDC00:c; }; RegExpValidationState.prototype.nextIndex = function nextIndex(i){ var s = this.source; var l = s.length; if(i >= l){ return l; } var c = s.charCodeAt(i),next; if(!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l || (next = s.charCodeAt(i + 1)) < 0xDC00 || next > 0xDFFF){ return i + 1; } return i + 2; }; RegExpValidationState.prototype.current = function current(){ return this.at(this.pos); }; RegExpValidationState.prototype.lookahead = function lookahead(){ return this.at(this.nextIndex(this.pos)); }; RegExpValidationState.prototype.advance = function advance(){ this.pos = this.nextIndex(this.pos); }; RegExpValidationState.prototype.eat = function eat(ch){ if(this.current() === ch){ this.advance(); return true; } return false; }; function codePointToString(ch){ if(ch <= 0xFFFF){ return String.fromCharCode(ch); } ch -= 0x10000; return String.fromCharCode((ch >> 10) + 0xD800,(ch & 0x03FF) + 0xDC00); } pp$8.validateRegExpFlags = function(state){ var validFlags = state.validFlags; var flags = state.flags; for(var i = 0; i < flags.length; i ++){ var flag = flags.charAt(i); if(validFlags.indexOf(flag) === - 1){ this.raise(state.start,"Invalid regular expression flag"); } if(flags.indexOf(flag,i + 1) > - 1){ this.raise(state.start,"Duplicate regular expression flag"); } } }; pp$8.validateRegExpPattern = function(state){ this.regexp_pattern(state); if(!state.switchN && this.options.ecmaVersion >= 9 && state.groupNames.length > 0){ state.switchN = true; this.regexp_pattern(state); } }; pp$8.regexp_pattern = function(state){ state.pos = 0; state.lastIntValue = 0; state.lastStringValue = ""; state.lastAssertionIsQuantifiable = false; state.numCapturingParens = 0; state.maxBackReference = 0; state.groupNames.length = 0; state.backReferenceNames.length = 0; this.regexp_disjunction(state); if(state.pos !== state.source.length){ if(state.eat(0x29)){ state.raise("Unmatched ')'"); } if(state.eat(0x5D) || state.eat(0x7D)){ state.raise("Lone quantifier brackets"); } } if(state.maxBackReference > state.numCapturingParens){ state.raise("Invalid escape"); } for(var i = 0,list = state.backReferenceNames; i < list.length; i += 1){ var name = list[i]; if(state.groupNames.indexOf(name) === - 1){ state.raise("Invalid named capture referenced"); } } }; pp$8.regexp_disjunction = function(state){ this.regexp_alternative(state); while(state.eat(0x7C)){ this.regexp_alternative(state); } if(this.regexp_eatQuantifier(state,true)){ state.raise("Nothing to repeat"); } if(state.eat(0x7B)){ state.raise("Lone quantifier brackets"); } }; pp$8.regexp_alternative = function(state){ while(state.pos < state.source.length && this.regexp_eatTerm(state)){ } }; pp$8.regexp_eatTerm = function(state){ if(this.regexp_eatAssertion(state)){ if(state.lastAssertionIsQuantifiable && this.regexp_eatQuantifier(state)){ if(state.switchU){ state.raise("Invalid quantifier"); } } return true; } if(state.switchU?this.regexp_eatAtom(state):this.regexp_eatExtendedAtom(state)){ this.regexp_eatQuantifier(state); return true; } return false; }; pp$8.regexp_eatAssertion = function(state){ var start = state.pos; state.lastAssertionIsQuantifiable = false; if(state.eat(0x5E) || state.eat(0x24)){ return true; } if(state.eat(0x5C)){ if(state.eat(0x42) || state.eat(0x62)){ return true; } state.pos = start; } if(state.eat(0x28) && state.eat(0x3F)){ var lookbehind = false; if(this.options.ecmaVersion >= 9){ lookbehind = state.eat(0x3C); } if(state.eat(0x3D) || state.eat(0x21)){ this.regexp_disjunction(state); if(!state.eat(0x29)){ state.raise("Unterminated group"); } state.lastAssertionIsQuantifiable = !lookbehind; return true; } } state.pos = start; return false; }; pp$8.regexp_eatQuantifier = function(state,noError){ if(noError === void 0){ noError = false; } if(this.regexp_eatQuantifierPrefix(state,noError)){ state.eat(0x3F); return true; } return false; }; pp$8.regexp_eatQuantifierPrefix = function(state,noError){ return (state.eat(0x2A) || state.eat(0x2B) || state.eat(0x3F) || this.regexp_eatBracedQuantifier(state,noError)); }; pp$8.regexp_eatBracedQuantifier = function(state,noError){ var start = state.pos; if(state.eat(0x7B)){ var min = 0,max = - 1; if(this.regexp_eatDecimalDigits(state)){ min = state.lastIntValue; if(state.eat(0x2C) && this.regexp_eatDecimalDigits(state)){ max = state.lastIntValue; } if(state.eat(0x7D)){ if(max !== - 1 && max < min && !noError){ state.raise("numbers out of order in {} quantifier"); } return true; } } if(state.switchU && !noError){ state.raise("Incomplete quantifier"); } state.pos = start; } return false; }; pp$8.regexp_eatAtom = function(state){ return (this.regexp_eatPatternCharacters(state) || state.eat(0x2E) || this.regexp_eatReverseSolidusAtomEscape(state) || this.regexp_eatCharacterClass(state) || this.regexp_eatUncapturingGroup(state) || this.regexp_eatCapturingGroup(state)); }; pp$8.regexp_eatReverseSolidusAtomEscape = function(state){ var start = state.pos; if(state.eat(0x5C)){ if(this.regexp_eatAtomEscape(state)){ return true; } state.pos = start; } return false; }; pp$8.regexp_eatUncapturingGroup = function(state){ var start = state.pos; if(state.eat(0x28)){ if(state.eat(0x3F) && state.eat(0x3A)){ this.regexp_disjunction(state); if(state.eat(0x29)){ return true; } state.raise("Unterminated group"); } state.pos = start; } return false; }; pp$8.regexp_eatCapturingGroup = function(state){ if(state.eat(0x28)){ if(this.options.ecmaVersion >= 9){ this.regexp_groupSpecifier(state); }else if(state.current() === 0x3F){ state.raise("Invalid group"); } this.regexp_disjunction(state); if(state.eat(0x29)){ state.numCapturingParens += 1; return true; } state.raise("Unterminated group"); } return false; }; pp$8.regexp_eatExtendedAtom = function(state){ return (state.eat(0x2E) || this.regexp_eatReverseSolidusAtomEscape(state) || this.regexp_eatCharacterClass(state) || this.regexp_eatUncapturingGroup(state) || this.regexp_eatCapturingGroup(state) || this.regexp_eatInvalidBracedQuantifier(state) || this.regexp_eatExtendedPatternCharacter(state)); }; pp$8.regexp_eatInvalidBracedQuantifier = function(state){ if(this.regexp_eatBracedQuantifier(state,true)){ state.raise("Nothing to repeat"); } return false; }; pp$8.regexp_eatSyntaxCharacter = function(state){ var ch = state.current(); if(isSyntaxCharacter(ch)){ state.lastIntValue = ch; state.advance(); return true; } return false; }; function isSyntaxCharacter(ch){ return (ch === 0x24 || ch >= 0x28 && ch <= 0x2B || ch === 0x2E || ch === 0x3F || ch >= 0x5B && ch <= 0x5E || ch >= 0x7B && ch <= 0x7D); } pp$8.regexp_eatPatternCharacters = function(state){ var start = state.pos; var ch = 0; while((ch = state.current()) !== - 1 && !isSyntaxCharacter(ch)){ state.advance(); } return state.pos !== start; }; pp$8.regexp_eatExtendedPatternCharacter = function(state){ var ch = state.current(); if(ch !== - 1 && ch !== 0x24 && !(ch >= 0x28 && ch <= 0x2B) && ch !== 0x2E && ch !== 0x3F && ch !== 0x5B && ch !== 0x5E && ch !== 0x7C){ state.advance(); return true; } return false; }; pp$8.regexp_groupSpecifier = function(state){ if(state.eat(0x3F)){ if(this.regexp_eatGroupName(state)){ if(state.groupNames.indexOf(state.lastStringValue) !== - 1){ state.raise("Duplicate capture group name"); } state.groupNames.push(state.lastStringValue); return; } state.raise("Invalid group"); } }; pp$8.regexp_eatGroupName = function(state){ state.lastStringValue = ""; if(state.eat(0x3C)){ if(this.regexp_eatRegExpIdentifierName(state) && state.eat(0x3E)){ return true; } state.raise("Invalid capture group name"); } return false; }; pp$8.regexp_eatRegExpIdentifierName = function(state){ state.lastStringValue = ""; if(this.regexp_eatRegExpIdentifierStart(state)){ state.lastStringValue += codePointToString(state.lastIntValue); while(this.regexp_eatRegExpIdentifierPart(state)){ state.lastStringValue += codePointToString(state.lastIntValue); } return true; } return false; }; pp$8.regexp_eatRegExpIdentifierStart = function(state){ var start = state.pos; var ch = state.current(); state.advance(); if(ch === 0x5C && this.regexp_eatRegExpUnicodeEscapeSequence(state)){ ch = state.lastIntValue; } if(isRegExpIdentifierStart(ch)){ state.lastIntValue = ch; return true; } state.pos = start; return false; }; function isRegExpIdentifierStart(ch){ return isIdentifierStart(ch,true) || ch === 0x24 || ch === 0x5F; } pp$8.regexp_eatRegExpIdentifierPart = function(state){ var start = state.pos; var ch = state.current(); state.advance(); if(ch === 0x5C && this.regexp_eatRegExpUnicodeEscapeSequence(state)){ ch = state.lastIntValue; } if(isRegExpIdentifierPart(ch)){ state.lastIntValue = ch; return true; } state.pos = start; return false; }; function isRegExpIdentifierPart(ch){ return isIdentifierChar(ch,true) || ch === 0x24 || ch === 0x5F || ch === 0x200C || ch === 0x200D; } pp$8.regexp_eatAtomEscape = function(state){ if(this.regexp_eatBackReference(state) || this.regexp_eatCharacterClassEscape(state) || this.regexp_eatCharacterEscape(state) || (state.switchN && this.regexp_eatKGroupName(state))){ return true; } if(state.switchU){ if(state.current() === 0x63){ state.raise("Invalid unicode escape"); } state.raise("Invalid escape"); } return false; }; pp$8.regexp_eatBackReference = function(state){ var start = state.pos; if(this.regexp_eatDecimalEscape(state)){ var n = state.lastIntValue; if(state.switchU){ if(n > state.maxBackReference){ state.maxBackReference = n; } return true; } if(n <= state.numCapturingParens){ return true; } state.pos = start; } return false; }; pp$8.regexp_eatKGroupName = function(state){ if(state.eat(0x6B)){ if(this.regexp_eatGroupName(state)){ state.backReferenceNames.push(state.lastStringValue); return true; } state.raise("Invalid named reference"); } return false; }; pp$8.regexp_eatCharacterEscape = function(state){ return (this.regexp_eatControlEscape(state) || this.regexp_eatCControlLetter(state) || this.regexp_eatZero(state) || this.regexp_eatHexEscapeSequence(state) || this.regexp_eatRegExpUnicodeEscapeSequence(state) || (!state.switchU && this.regexp_eatLegacyOctalEscapeSequence(state)) || this.regexp_eatIdentityEscape(state)); }; pp$8.regexp_eatCControlLetter = function(state){ var start = state.pos; if(state.eat(0x63)){ if(this.regexp_eatControlLetter(state)){ return true; } state.pos = start; } return false; }; pp$8.regexp_eatZero = function(state){ if(state.current() === 0x30 && !isDecimalDigit(state.lookahead())){ state.lastIntValue = 0; state.advance(); return true; } return false; }; pp$8.regexp_eatControlEscape = function(state){ var ch = state.current(); if(ch === 0x74){ state.lastIntValue = 0x09; state.advance(); return true; } if(ch === 0x6E){ state.lastIntValue = 0x0A; state.advance(); return true; } if(ch === 0x76){ state.lastIntValue = 0x0B; state.advance(); return true; } if(ch === 0x66){ state.lastIntValue = 0x0C; state.advance(); return true; } if(ch === 0x72){ state.lastIntValue = 0x0D; state.advance(); return true; } return false; }; pp$8.regexp_eatControlLetter = function(state){ var ch = state.current(); if(isControlLetter(ch)){ state.lastIntValue = ch % 0x20; state.advance(); return true; } return false; }; function isControlLetter(ch){ return ((ch >= 0x41 && ch <= 0x5A) || (ch >= 0x61 && ch <= 0x7A)); } pp$8.regexp_eatRegExpUnicodeEscapeSequence = function(state){ var start = state.pos; if(state.eat(0x75)){ if(this.regexp_eatFixedHexDigits(state,4)){ var lead = state.lastIntValue; if(state.switchU && lead >= 0xD800 && lead <= 0xDBFF){ var leadSurrogateEnd = state.pos; if(state.eat(0x5C) && state.eat(0x75) && this.regexp_eatFixedHexDigits(state,4)){ var trail = state.lastIntValue; if(trail >= 0xDC00 && trail <= 0xDFFF){ state.lastIntValue = (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000; return true; } } state.pos = leadSurrogateEnd; state.lastIntValue = lead; } return true; } if(state.switchU && state.eat(0x7B) && this.regexp_eatHexDigits(state) && state.eat(0x7D) && isValidUnicode(state.lastIntValue)){ return true; } if(state.switchU){ state.raise("Invalid unicode escape"); } state.pos = start; } return false; }; function isValidUnicode(ch){ return ch >= 0 && ch <= 0x10FFFF; } pp$8.regexp_eatIdentityEscape = function(state){ if(state.switchU){ if(this.regexp_eatSyntaxCharacter(state)){ return true; } if(state.eat(0x2F)){ state.lastIntValue = 0x2F; return true; } return false; } var ch = state.current(); if(ch !== 0x63 && (!state.switchN || ch !== 0x6B)){ state.lastIntValue = ch; state.advance(); return true; } return false; }; pp$8.regexp_eatDecimalEscape = function(state){ state.lastIntValue = 0; var ch = state.current(); if(ch >= 0x31 && ch <= 0x39){ do{ state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30); state.advance(); }while((ch = state.current()) >= 0x30 && ch <= 0x39); return true; } return false; }; pp$8.regexp_eatCharacterClassEscape = function(state){ var ch = state.current(); if(isCharacterClassEscape(ch)){ state.lastIntValue = - 1; state.advance(); return true; } if(state.switchU && this.options.ecmaVersion >= 9 && (ch === 0x50 || ch === 0x70)){ state.lastIntValue = - 1; state.advance(); if(state.eat(0x7B) && this.regexp_eatUnicodePropertyValueExpression(state) && state.eat(0x7D)){ return true; } state.raise("Invalid property name"); } return false; }; function isCharacterClassEscape(ch){ return (ch === 0x64 || ch === 0x44 || ch === 0x73 || ch === 0x53 || ch === 0x77 || ch === 0x57); } pp$8.regexp_eatUnicodePropertyValueExpression = function(state){ var start = state.pos; if(this.regexp_eatUnicodePropertyName(state) && state.eat(0x3D)){ var name = state.lastStringValue; if(this.regexp_eatUnicodePropertyValue(state)){ var value = state.lastStringValue; this.regexp_validateUnicodePropertyNameAndValue(state,name,value); return true; } } state.pos = start; if(this.regexp_eatLoneUnicodePropertyNameOrValue(state)){ var nameOrValue = state.lastStringValue; this.regexp_validateUnicodePropertyNameOrValue(state,nameOrValue); return true; } return false; }; pp$8.regexp_validateUnicodePropertyNameAndValue = function(state,name,value){ if(!has(state.unicodeProperties.nonBinary,name)){ state.raise("Invalid property name"); } if(!state.unicodeProperties.nonBinary[name].test(value)){ state.raise("Invalid property value"); } }; pp$8.regexp_validateUnicodePropertyNameOrValue = function(state,nameOrValue){ if(!state.unicodeProperties.binary.test(nameOrValue)){ state.raise("Invalid property name"); } }; pp$8.regexp_eatUnicodePropertyName = function(state){ var ch = 0; state.lastStringValue = ""; while(isUnicodePropertyNameCharacter(ch = state.current())){ state.lastStringValue += codePointToString(ch); state.advance(); } return state.lastStringValue !== ""; }; function isUnicodePropertyNameCharacter(ch){ return isContro