summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormattkae <mattkae@protonmail.com>2023-07-31 07:31:52 -0400
committermattkae <mattkae@protonmail.com>2023-07-31 07:31:52 -0400
commitb6a666e96ffd04bd6d52be8fd9899faf27b751db (patch)
treeddc56ec77d0fa6a35a581ea49bcd1b4c3cac3756
parentffa1ada2b7f65e0b3afe561b3291219394df21f3 (diff)
Some initial shader loading work
-rw-r--r--themes/dist/output.js1071
-rwxr-xr-xthemes/dist/output.wasmbin147254 -> 147365 bytes
-rw-r--r--themes/src/Renderer2d.cpp10
-rw-r--r--themes/src/Renderer2d.h5
-rw-r--r--themes/src/_shaders/renderer2d.frag (renamed from themes/src/shaders/renderer2d.frag)0
-rw-r--r--themes/src/_shaders/renderer2d.vert (renamed from themes/src/shaders/renderer2d.vert)0
-rw-r--r--themes/src/_shaders/renderer3d.frag (renamed from themes/src/shaders/renderer3d.frag)0
-rw-r--r--themes/src/_shaders/renderer3d.vert (renamed from themes/src/shaders/renderer3d.vert)0
-rw-r--r--themes/src/_shaders/sun.vert0
-rw-r--r--themes/src/main.cpp5
-rw-r--r--themes/src/shaders/renderer2d_frag.h4
-rw-r--r--themes/src/shaders/renderer2d_vert.h4
-rw-r--r--themes/src/shaders/renderer3d_frag.h11
-rw-r--r--themes/src/shaders/renderer3d_vert.h19
-rw-r--r--themes/src/shaders/sun_vert.h4
-rw-r--r--themes/src/summer/SummerTheme.cpp3
-rw-r--r--themes/src/summer/SummerTheme.h2
-rw-r--r--themes/src/tools/shader.js30
-rw-r--r--themes/tools/bundle_shaders.py4
19 files changed, 652 insertions, 520 deletions
diff --git a/themes/dist/output.js b/themes/dist/output.js
index e814b4e..75522f9 100644
--- a/themes/dist/output.js
+++ b/themes/dist/output.js
@@ -61,24 +61,17 @@ var read_,
readBinary,
setWindowTitle;
-// Normally we don't log exceptions but instead let them bubble out the top
-// level where the embedding environment (e.g. the browser) can handle
-// them.
-// However under v8 and node we sometimes exit the process direcly in which case
-// its up to use us to log the exception before exiting.
-// If we fix https://github.com/emscripten-core/emscripten/issues/15080
-// this may no longer be needed under node.
-function logExceptionOnExit(e) {
- if (e instanceof ExitStatus) return;
- let toLog = e;
- if (e && typeof e == 'object' && e.stack) {
- toLog = [e, e.stack];
- }
- err('exiting due to exception: ' + toLog);
-}
-
if (ENVIRONMENT_IS_NODE) {
if (typeof process == 'undefined' || !process.release || process.release.name !== 'node') throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)');
+
+ var nodeVersion = process.versions.node;
+ var numericVersion = nodeVersion.split('.').slice(0, 3);
+ numericVersion = (numericVersion[0] * 10000) + (numericVersion[1] * 100) + (numericVersion[2].split('-')[0] * 1);
+ var minVersion = 101900;
+ if (numericVersion < 101900) {
+ throw new Error('This emscripten-generated code requires node v10.19.19.0 (detected v' + nodeVersion + ')');
+ }
+
// `require()` is no-op in an ESM module, use `createRequire()` to construct
// the require()` function. This is only necessary for multi-environment
// builds, `-sENVIRONMENT=node` emits a static import declaration instead.
@@ -111,29 +104,29 @@ readBinary = (filename) => {
return ret;
};
-readAsync = (filename, onload, onerror) => {
+readAsync = (filename, onload, onerror, binary = true) => {
// See the comment in the `read_` function.
filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename);
- fs.readFile(filename, function(err, data) {
+ fs.readFile(filename, binary ? undefined : 'utf8', (err, data) => {
if (err) onerror(err);
- else onload(data.buffer);
+ else onload(binary ? data.buffer : data);
});
};
// end include: node_shell_read.js
- if (process['argv'].length > 1) {
- thisProgram = process['argv'][1].replace(/\\/g, '/');
+ if (!Module['thisProgram'] && process.argv.length > 1) {
+ thisProgram = process.argv[1].replace(/\\/g, '/');
}
- arguments_ = process['argv'].slice(2);
+ arguments_ = process.argv.slice(2);
if (typeof module != 'undefined') {
module['exports'] = Module;
}
- process['on']('uncaughtException', function(ex) {
+ process.on('uncaughtException', (ex) => {
// suppress ExitStatus exceptions from showing an error
- if (!(ex instanceof ExitStatus)) {
+ if (ex !== 'unwind' && !(ex instanceof ExitStatus) && !(ex.context instanceof ExitStatus)) {
throw ex;
}
});
@@ -143,21 +136,17 @@ readAsync = (filename, onload, onerror) => {
// not be needed with node v15 and about because it is now the default
// behaviour:
// See https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode
- var nodeMajor = process.version.match(/^v(\d+)\./)[1];
+ var nodeMajor = process.versions.node.split(".")[0];
if (nodeMajor < 15) {
- process['on']('unhandledRejection', function(reason) { throw reason; });
+ process.on('unhandledRejection', (reason) => { throw reason; });
}
quit_ = (status, toThrow) => {
- if (keepRuntimeAlive()) {
- process['exitCode'] = status;
- throw toThrow;
- }
- logExceptionOnExit(toThrow);
- process['exit'](status);
+ process.exitCode = status;
+ throw toThrow;
};
- Module['inspect'] = function () { return '[Emscripten Module object]'; };
+ Module['inspect'] = () => '[Emscripten Module object]';
} else
if (ENVIRONMENT_IS_SHELL) {
@@ -165,12 +154,12 @@ if (ENVIRONMENT_IS_SHELL) {
if ((typeof process == 'object' && typeof require === 'function') || typeof window == 'object' || typeof importScripts == 'function') throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)');
if (typeof read != 'undefined') {
- read_ = function shell_read(f) {
+ read_ = (f) => {
return read(f);
};
}
- readBinary = function readBinary(f) {
+ readBinary = (f) => {
let data;
if (typeof readbuffer == 'function') {
return new Uint8Array(readbuffer(f));
@@ -180,7 +169,7 @@ if (ENVIRONMENT_IS_SHELL) {
return data;
};
- readAsync = function readAsync(f, onload, onerror) {
+ readAsync = (f, onload, onerror) => {
setTimeout(() => onload(readBinary(f)), 0);
};
@@ -196,8 +185,26 @@ if (ENVIRONMENT_IS_SHELL) {
if (typeof quit == 'function') {
quit_ = (status, toThrow) => {
- logExceptionOnExit(toThrow);
- quit(status);
+ // Unlike node which has process.exitCode, d8 has no such mechanism. So we
+ // have no way to set the exit code and then let the program exit with
+ // that code when it naturally stops running (say, when all setTimeouts
+ // have completed). For that reason, we must call `quit` - the only way to
+ // set the exit code - but quit also halts immediately. To increase
+ // consistency with node (and the web) we schedule the actual quit call
+ // using a setTimeout to give the current stack and any exception handlers
+ // a chance to run. This enables features such as addOnPostRun (which
+ // expected to be able to run code after main returns).
+ setTimeout(() => {
+ if (!(toThrow instanceof ExitStatus)) {
+ let toLog = toThrow;
+ if (toThrow && typeof toThrow == 'object' && toThrow.stack) {
+ toLog = [toThrow, toThrow.stack];
+ }
+ err(`exiting due to exception: ${toLog}`);
+ }
+ quit(status);
+ });
+ throw toThrow;
};
}
@@ -279,7 +286,7 @@ read_ = (url) => {
}
var out = Module['print'] || console.log.bind(console);
-var err = Module['printErr'] || console.warn.bind(console);
+var err = Module['printErr'] || console.error.bind(console);
// Merge back in the overrides
Object.assign(Module, moduleOverrides);
@@ -369,195 +376,6 @@ function assert(condition, text) {
// We used to include malloc/free by default in the past. Show a helpful error in
// builds with assertions.
-// include: runtime_strings.js
-// runtime_strings.js: String related runtime functions that are part of both
-// MINIMAL_RUNTIME and regular runtime.
-
-var UTF8Decoder = typeof TextDecoder != 'undefined' ? new TextDecoder('utf8') : undefined;
-
-/**
- * Given a pointer 'idx' to a null-terminated UTF8-encoded string in the given
- * array that contains uint8 values, returns a copy of that string as a
- * Javascript String object.
- * heapOrArray is either a regular array, or a JavaScript typed array view.
- * @param {number} idx
- * @param {number=} maxBytesToRead
- * @return {string}
- */
-function UTF8ArrayToString(heapOrArray, idx, maxBytesToRead) {
- var endIdx = idx + maxBytesToRead;
- var endPtr = idx;
- // TextDecoder needs to know the byte length in advance, it doesn't stop on
- // null terminator by itself. Also, use the length info to avoid running tiny
- // strings through TextDecoder, since .subarray() allocates garbage.
- // (As a tiny code save trick, compare endPtr against endIdx using a negation,
- // so that undefined means Infinity)
- while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr;
-
- if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) {
- return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr));
- }
- var str = '';
- // If building with TextDecoder, we have already computed the string length
- // above, so test loop end condition against that
- while (idx < endPtr) {
- // For UTF8 byte structure, see:
- // http://en.wikipedia.org/wiki/UTF-8#Description
- // https://www.ietf.org/rfc/rfc2279.txt
- // https://tools.ietf.org/html/rfc3629
- var u0 = heapOrArray[idx++];
- if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; }
- var u1 = heapOrArray[idx++] & 63;
- if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; }
- var u2 = heapOrArray[idx++] & 63;
- if ((u0 & 0xF0) == 0xE0) {
- u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
- } else {
- if ((u0 & 0xF8) != 0xF0) warnOnce('Invalid UTF-8 leading byte ' + ptrToString(u0) + ' encountered when deserializing a UTF-8 string in wasm memory to a JS string!');
- u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63);
- }
-
- if (u0 < 0x10000) {
- str += String.fromCharCode(u0);
- } else {
- var ch = u0 - 0x10000;
- str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF));
- }
- }
- return str;
-}
-
-/**
- * Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the
- * emscripten HEAP, returns a copy of that string as a Javascript String object.
- *
- * @param {number} ptr
- * @param {number=} maxBytesToRead - An optional length that specifies the
- * maximum number of bytes to read. You can omit this parameter to scan the
- * string until the first \0 byte. If maxBytesToRead is passed, and the string
- * at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the
- * string will cut short at that byte index (i.e. maxBytesToRead will not
- * produce a string of exact length [ptr, ptr+maxBytesToRead[) N.B. mixing
- * frequent uses of UTF8ToString() with and without maxBytesToRead may throw
- * JS JIT optimizations off, so it is worth to consider consistently using one
- * @return {string}
- */
-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.
- *
- * @param {string} str - The Javascript string to copy.
- * @param {ArrayBufferView|Array<number>} heap - The array to copy to. Each
- * index in this array is assumed
- * to be one 8-byte element.
- * @param {number} outIdx - The starting offset in the array to begin the copying.
- * @param {number} 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.
- * @return {number} The number of bytes written, EXCLUDING the null terminator.
- */
-function stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) {
- // Parameter maxBytesToWrite is not optional. Negative values, 0, null,
- // undefined and false each don't write out any bytes.
- if (!(maxBytesToWrite > 0))
- return 0;
-
- var startIdx = outIdx;
- var endIdx = outIdx + maxBytesToWrite - 1; // -1 for string null terminator.
- for (var i = 0; i < str.length; ++i) {
- // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code
- // unit, not a Unicode code point of the character! So decode
- // UTF16->UTF32->UTF8.
- // See http://unicode.org/faq/utf_bom.html#utf16-3
- // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description
- // and https://www.ietf.org/rfc/rfc2279.txt
- // and https://tools.ietf.org/html/rfc3629
- var u = str.charCodeAt(i); // possibly a lead surrogate
- if (u >= 0xD800 && u <= 0xDFFF) {
- var u1 = str.charCodeAt(++i);
- u = 0x10000 + ((u & 0x3FF) << 10) | (u1 & 0x3FF);
- }
- if (u <= 0x7F) {
- if (outIdx >= endIdx) break;
- heap[outIdx++] = u;
- } else if (u <= 0x7FF) {
- if (outIdx + 1 >= endIdx) break;
- heap[outIdx++] = 0xC0 | (u >> 6);
- heap[outIdx++] = 0x80 | (u & 63);
- } else if (u <= 0xFFFF) {
- if (outIdx + 2 >= endIdx) break;
- heap[outIdx++] = 0xE0 | (u >> 12);
- heap[outIdx++] = 0x80 | ((u >> 6) & 63);
- heap[outIdx++] = 0x80 | (u & 63);
- } else {
- if (outIdx + 3 >= endIdx) break;
- if (u > 0x10FFFF) warnOnce('Invalid Unicode code point ' + ptrToString(u) + ' encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF).');
- heap[outIdx++] = 0xF0 | (u >> 18);
- heap[outIdx++] = 0x80 | ((u >> 12) & 63);
- heap[outIdx++] = 0x80 | ((u >> 6) & 63);
- heap[outIdx++] = 0x80 | (u & 63);
- }
- }
- // Null-terminate the pointer to the buffer.
- heap[outIdx] = 0;
- return outIdx - startIdx;
-}
-
-/**
- * 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.
- *
- * @return {number} The number of bytes written, EXCLUDING the null terminator.
- */
-function stringToUTF8(str, outPtr, maxBytesToWrite) {
- assert(typeof maxBytesToWrite == 'number', 'stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!');
- return stringToUTF8Array(str, HEAPU8,outPtr, maxBytesToWrite);
-}
-
-/**
- * Returns the number of bytes the given Javascript string takes if encoded as a
- * UTF8 byte array, EXCLUDING the null terminator byte.
- *
- * @param {string} str - JavaScript string to operator on
- * @return {number} Length, in bytes, of the UTF8 encoded string.
- */
-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 c = str.charCodeAt(i); // possibly a lead surrogate
- if (c <= 0x7F) {
- len++;
- } else if (c <= 0x7FF) {
- len += 2;
- } else if (c >= 0xD800 && c <= 0xDFFF) {
- len += 4; ++i;
- } else {
- len += 3;
- }
- }
- return len;
-}
-
-// end include: runtime_strings.js
// Memory management
var HEAP,
@@ -612,18 +430,18 @@ function writeStackCookie() {
var max = _emscripten_stack_get_end();
assert((max & 3) == 0);
// If the stack ends at address zero we write our cookies 4 bytes into the
- // stack. This prevents interference with the (separate) address-zero check
- // below.
+ // stack. This prevents interference with SAFE_HEAP and ASAN which also
+ // monitor writes to address zero.
if (max == 0) {
max += 4;
}
// The stack grow downwards towards _emscripten_stack_get_end.
// We write cookies to the final two words in the stack and detect if they are
// ever overwritten.
- HEAPU32[((max)>>2)] = 0x2135467;
+ HEAPU32[((max)>>2)] = 0x02135467;
HEAPU32[(((max)+(4))>>2)] = 0x89BACDFE;
// Also test the global address 0 for integrity.
- HEAPU32[0] = 0x63736d65; /* 'emsc' */
+ HEAPU32[((0)>>2)] = 1668509029;
}
function checkStackCookie() {
@@ -635,11 +453,11 @@ function checkStackCookie() {
}
var cookie1 = HEAPU32[((max)>>2)];
var cookie2 = HEAPU32[(((max)+(4))>>2)];
- if (cookie1 != 0x2135467 || cookie2 != 0x89BACDFE) {
- abort('Stack overflow! Stack cookie has been overwritten at ' + ptrToString(max) + ', expected hex dwords 0x89BACDFE and 0x2135467, but received ' + ptrToString(cookie2) + ' ' + ptrToString(cookie1));
+ if (cookie1 != 0x02135467 || cookie2 != 0x89BACDFE) {
+ abort(`Stack overflow! Stack cookie has been overwritten at ${ptrToString(max)}, expected hex dwords 0x89BACDFE and 0x2135467, but received ${ptrToString(cookie2)} ${ptrToString(cookie1)}`);
}
// Also test the global address 0 for integrity.
- if (HEAPU32[0] !== 0x63736d65 /* 'emsc' */) {
+ if (HEAPU32[((0)>>2)] != 0x63736d65 /* 'emsc' */) {
abort('Runtime error: The application has corrupted its heap memory area (address zero)!');
}
}
@@ -663,8 +481,10 @@ var __ATPOSTRUN__ = []; // functions called after the main() is called
var runtimeInitialized = false;
+var runtimeKeepaliveCounter = 0;
+
function keepRuntimeAlive() {
- return noExitRuntime;
+ return noExitRuntime || runtimeKeepaliveCounter > 0;
}
function preRun() {
@@ -772,7 +592,7 @@ function addRunDependency(id) {
runDependencyTracking[id] = 1;
if (runDependencyWatcher === null && typeof setInterval != 'undefined') {
// Check for missing dependencies every few seconds
- runDependencyWatcher = setInterval(function() {
+ runDependencyWatcher = setInterval(() => {
if (ABORT) {
clearInterval(runDependencyWatcher);
runDependencyWatcher = null;
@@ -873,7 +693,6 @@ var FS = {
mkdev: function() { FS.error() },
registerDevice: function() { FS.error() },
analyzePath: function() { FS.error() },
- loadFilesFromDB: function() { FS.error() },
ErrnoError: function ErrnoError() { FS.error() },
};
@@ -912,6 +731,8 @@ function createExportWrapper(name, fixedasm) {
};
}
+// include: runtime_exceptions.js
+// end include: runtime_exceptions.js
var wasmBinaryFile;
wasmBinaryFile = 'output.wasm';
if (!isDataURI(wasmBinaryFile)) {
@@ -933,37 +754,88 @@ function getBinary(file) {
}
}
-function getBinaryPromise() {
- // If we don't have the binary yet, try to to load it asynchronously.
+function getBinaryPromise(binaryFile) {
+ // If we don't have the binary yet, try to load it asynchronously.
// Fetch has some additional restrictions over XHR, like it can't be used on a file:// url.
// See https://github.com/github/fetch/pull/92#issuecomment-140665932
// Cordova or Electron apps are typically loaded from a file:// url.
// So use fetch if it is available and the url is not a file, otherwise fall back to XHR.
if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) {
if (typeof fetch == 'function'
- && !isFileURI(wasmBinaryFile)
+ && !isFileURI(binaryFile)
) {
- return fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function(response) {
+ return fetch(binaryFile, { credentials: 'same-origin' }).then((response) => {
if (!response['ok']) {
- throw "failed to load wasm binary file at '" + wasmBinaryFile + "'";
+ throw "failed to load wasm binary file at '" + binaryFile + "'";
}
return response['arrayBuffer']();
- }).catch(function () {
- return getBinary(wasmBinaryFile);
- });
+ }).catch(() => getBinary(binaryFile));
}
else {
if (readAsync) {
// fetch is not available or url is file => try XHR (readAsync uses XHR internally)
- return new Promise(function(resolve, reject) {
- readAsync(wasmBinaryFile, function(response) { resolve(new Uint8Array(/** @type{!ArrayBuffer} */(response))) }, reject)
+ return new Promise((resolve, reject) => {
+ readAsync(binaryFile, (response) => resolve(new Uint8Array(/** @type{!ArrayBuffer} */(response))), reject)
});
}
}
}
// Otherwise, getBinary should be able to get it synchronously
- return Promise.resolve().then(function() { return getBinary(wasmBinaryFile); });
+ return Promise.resolve().then(() => getBinary(binaryFile));
+}
+
+function instantiateArrayBuffer(binaryFile, imports, receiver) {
+ return getBinaryPromise(binaryFile).then((binary) => {
+ return WebAssembly.instantiate(binary, imports);
+ }).then((instance) => {
+ return instance;
+ }).then(receiver, (reason) => {
+ err('failed to asynchronously prepare wasm: ' + reason);
+
+ // Warn on some common problems.
+ if (isFileURI(wasmBinaryFile)) {
+ err('warning: Loading from a file URI (' + wasmBinaryFile + ') is not supported in most browsers. See https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-does-my-program-stall-in-downloading-or-preparing');
+ }
+ abort(reason);
+ });
+}
+
+function instantiateAsync(binary, binaryFile, imports, callback) {
+ if (!binary &&
+ typeof WebAssembly.instantiateStreaming == 'function' &&
+ !isDataURI(binaryFile) &&
+ // Don't use streaming for file:// delivered objects in a webview, fetch them synchronously.
+ !isFileURI(binaryFile) &&
+ // Avoid instantiateStreaming() on Node.js environment for now, as while
+ // Node.js v18.1.0 implements it, it does not have a full fetch()
+ // implementation yet.
+ //
+ // Reference:
+ // https://github.com/emscripten-core/emscripten/pull/16917
+ !ENVIRONMENT_IS_NODE &&
+ typeof fetch == 'function') {
+ return fetch(binaryFile, { credentials: 'same-origin' }).then((response) => {
+ // Suppress closure warning here since the upstream definition for
+ // instantiateStreaming only allows Promise<Repsponse> rather than
+ // an actual Response.
+ // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure is fixed.
+ /** @suppress {checkTypes} */
+ var result = WebAssembly.instantiateStreaming(response, imports);
+
+ return result.then(
+ callback,
+ function(reason) {
+ // We expect the most common failure cause to be a bad MIME type for the binary,
+ // in which case falling back to ArrayBuffer instantiation should work.
+ err('wasm streaming compile failed: ' + reason);
+ err('falling back to ArrayBuffer instantiation');
+ return instantiateArrayBuffer(binaryFile, imports, callback);
+ });
+ });
+ } else {
+ return instantiateArrayBuffer(binaryFile, imports, callback);
+ }
}
// Create the wasm instance.
@@ -997,7 +869,7 @@ function createWasm() {
addOnInit(Module['asm']['__wasm_call_ctors']);
removeRunDependency('wasm-instantiate');
-
+ return exports;
}
// wait for the pthread pool (if any)
addRunDependency('wasm-instantiate');
@@ -1013,78 +885,27 @@ function createWasm() {
assert(Module === trueModule, 'the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?');
trueModule = null;
// 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.
+ // When the regression is fixed, can restore the above PTHREADS-enabled path.
receiveInstance(result['instance']);
}
- function instantiateArrayBuffer(receiver) {
- return getBinaryPromise().then(function(binary) {
- return WebAssembly.instantiate(binary, info);
- }).then(function (instance) {
- return instance;
- }).then(receiver, function(reason) {
- err('failed to asynchronously prepare wasm: ' + reason);
-
- // Warn on some common problems.
- if (isFileURI(wasmBinaryFile)) {
- err('warning: Loading from a file URI (' + wasmBinaryFile + ') is not supported in most browsers. See https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-does-my-program-stall-in-downloading-or-preparing');
- }
- abort(reason);
- });
- }
-
- function instantiateAsync() {
- if (!wasmBinary &&
- typeof WebAssembly.instantiateStreaming == 'function' &&
- !isDataURI(wasmBinaryFile) &&
- // Don't use streaming for file:// delivered objects in a webview, fetch them synchronously.
- !isFileURI(wasmBinaryFile) &&
- // Avoid instantiateStreaming() on Node.js environment for now, as while
- // Node.js v18.1.0 implements it, it does not have a full fetch()
- // implementation yet.
- //
- // Reference:
- // https://github.com/emscripten-core/emscripten/pull/16917
- !ENVIRONMENT_IS_NODE &&
- typeof fetch == 'function') {
- return fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function(response) {
- // Suppress closure warning here since the upstream definition for
- // instantiateStreaming only allows Promise<Repsponse> rather than
- // an actual Response.
- // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure is fixed.
- /** @suppress {checkTypes} */
- var result = WebAssembly.instantiateStreaming(response, info);
-
- return result.then(
- receiveInstantiationResult,
- 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(receiveInstantiationResult);
- });
- });
- } else {
- return instantiateArrayBuffer(receiveInstantiationResult);
- }
- }
-
// User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback
- // to manually instantiate the Wasm module themselves. This allows pages to run the instantiation parallel
- // to any other async startup actions they are performing.
- // Also pthreads and wasm workers initialize the wasm instance through this path.
+ // to manually instantiate the Wasm module themselves. This allows pages to
+ // run the instantiation parallel to any other async startup actions they are
+ // performing.
+ // Also pthreads and wasm workers initialize the wasm instance through this
+ // path.
if (Module['instantiateWasm']) {
+
try {
- var exports = Module['instantiateWasm'](info, receiveInstance);
- return exports;
+ return Module['instantiateWasm'](info, receiveInstance);
} catch(e) {
err('Module.instantiateWasm callback failed with error: ' + e);
return false;
}
}
- instantiateAsync();
+ instantiateAsync(wasmBinary, wasmBinaryFile, info, receiveInstantiationResult);
return {}; // no exports yet; we'll fill them in later
}
@@ -1161,7 +982,7 @@ function missingLibrarySymbol(sym) {
}
});
}
- // Any symbol that is not included from the JS libary is also (by definttion)
+ // Any symbol that is not included from the JS libary is also (by definition)
// not exported on the Module object.
unexportedRuntimeSymbol(sym);
}
@@ -1181,6 +1002,13 @@ function unexportedRuntimeSymbol(sym) {
}
}
+// Used by XXXXX_DEBUG settings to output debug messages.
+function dbg(text) {
+ // TODO(sbc): Make this configurable somehow. Its not always convenient for
+ // logging to show up as warnings.
+ console.warn.apply(console, arguments);
+}
+
// end include: runtime_debug.js
// === Body ===
@@ -1190,7 +1018,7 @@ function unexportedRuntimeSymbol(sym) {
/** @constructor */
function ExitStatus(status) {
this.name = 'ExitStatus';
- this.message = 'Program terminated with exit(' + status + ')';
+ this.message = `Program terminated with exit(${status})`;
this.status = status;
}
@@ -1207,20 +1035,19 @@ function unexportedRuntimeSymbol(sym) {
* @param {string} type
*/
function getValue(ptr, type = 'i8') {
- if (type.endsWith('*')) type = '*';
- switch (type) {
- case 'i1': return HEAP8[((ptr)>>0)];
- case 'i8': return HEAP8[((ptr)>>0)];
- case 'i16': return HEAP16[((ptr)>>1)];
- case 'i32': return HEAP32[((ptr)>>2)];
- case 'i64': return HEAP32[((ptr)>>2)];
- case 'float': return HEAPF32[((ptr)>>2)];
- case 'double': return HEAPF64[((ptr)>>3)];
- case '*': return HEAPU32[((ptr)>>2)];
- default: abort('invalid type for getValue: ' + type);
- }
- return null;
+ if (type.endsWith('*')) type = '*';
+ switch (type) {
+ case 'i1': return HEAP8[((ptr)>>0)];
+ case 'i8': return HEAP8[((ptr)>>0)];
+ case 'i16': return HEAP16[((ptr)>>1)];
+ case 'i32': return HEAP32[((ptr)>>2)];
+ case 'i64': abort('to do getValue(i64) use WASM_BIGINT');
+ case 'float': return HEAPF32[((ptr)>>2)];
+ case 'double': return HEAPF64[((ptr)>>3)];
+ case '*': return HEAPU32[((ptr)>>2)];
+ default: abort(`invalid type for getValue: ${type}`);
}
+ }
function ptrToString(ptr) {
assert(typeof ptr === 'number');
@@ -1234,19 +1061,19 @@ function unexportedRuntimeSymbol(sym) {
* @param {string} type
*/
function setValue(ptr, value, type = 'i8') {
- if (type.endsWith('*')) type = '*';
- switch (type) {
- case 'i1': HEAP8[((ptr)>>0)] = value; break;
- case 'i8': HEAP8[((ptr)>>0)] = value; break;
- case 'i16': HEAP16[((ptr)>>1)] = value; break;
- case 'i32': HEAP32[((ptr)>>2)] = value; break;
- case 'i64': (tempI64 = [value>>>0,(tempDouble=value,(+(Math.abs(tempDouble))) >= 1.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;
- case '*': HEAPU32[((ptr)>>2)] = value; break;
- default: abort('invalid type for setValue: ' + type);
- }
+ if (type.endsWith('*')) type = '*';
+ switch (type) {
+ case 'i1': HEAP8[((ptr)>>0)] = value; break;
+ case 'i8': HEAP8[((ptr)>>0)] = value; break;
+ case 'i16': HEAP16[((ptr)>>1)] = value; break;
+ case 'i32': HEAP32[((ptr)>>2)] = value; break;
+ case 'i64': abort('to do setValue(i64) use WASM_BIGINT');
+ case 'float': HEAPF32[((ptr)>>2)] = value; break;
+ case 'double': HEAPF64[((ptr)>>3)] = value; break;
+ case '*': HEAPU32[((ptr)>>2)] = value; break;
+ default: abort(`invalid type for setValue: ${type}`);
}
+ }
function warnOnce(text) {
if (!warnOnce.shown) warnOnce.shown = {};
@@ -1258,30 +1085,30 @@ function unexportedRuntimeSymbol(sym) {
}
function __emscripten_fetch_free(id) {
- var xhr = Fetch.xhrs[id];
- if (xhr) {
- delete Fetch.xhrs[id];
- // check if fetch is still in progress and should be aborted
- if (xhr.readyState > 0 && xhr.readyState < 4) {
- xhr.abort();
- }
+ if (Fetch.xhrs.has(id)) {
+ var xhr = Fetch.xhrs.get(id);
+ Fetch.xhrs.free(id);
+ // check if fetch is still in progress and should be aborted
+ if (xhr.readyState > 0 && xhr.readyState < 4) {
+ xhr.abort();
}
+ }
}
function readI53FromI64(ptr) {
return HEAPU32[ptr>>2] + HEAP32[ptr+4>>2] * 4294967296;
}
- function __isLeapYear(year) {
+ function isLeapYear(year) {
return year%4 === 0 && (year%100 !== 0 || year%400 === 0);
}
- var __MONTH_DAYS_LEAP_CUMULATIVE = [0,31,60,91,121,152,182,213,244,274,305,335];
+ var MONTH_DAYS_LEAP_CUMULATIVE = [0,31,60,91,121,152,182,213,244,274,305,335];
- var __MONTH_DAYS_REGULAR_CUMULATIVE = [0,31,59,90,120,151,181,212,243,273,304,334];
- function __yday_from_date(date) {
- var isLeapYear = __isLeapYear(date.getFullYear());
- var monthDaysCumulative = (isLeapYear ? __MONTH_DAYS_LEAP_CUMULATIVE : __MONTH_DAYS_REGULAR_CUMULATIVE);
+ var MONTH_DAYS_REGULAR_CUMULATIVE = [0,31,59,90,120,151,181,212,243,273,304,334];
+ function ydayFromDate(date) {
+ var leap = isLeapYear(date.getFullYear());
+ var monthDaysCumulative = (leap ? MONTH_DAYS_LEAP_CUMULATIVE : MONTH_DAYS_REGULAR_CUMULATIVE);
var yday = monthDaysCumulative[date.getMonth()] + date.getDate() - 1; // -1 since it's days since Jan 1
return yday;
@@ -1296,7 +1123,7 @@ function unexportedRuntimeSymbol(sym) {
HEAP32[(((tmPtr)+(20))>>2)] = date.getFullYear()-1900;
HEAP32[(((tmPtr)+(24))>>2)] = date.getDay();
- var yday = __yday_from_date(date)|0;
+ var yday = ydayFromDate(date)|0;
HEAP32[(((tmPtr)+(28))>>2)] = yday;
HEAP32[(((tmPtr)+(36))>>2)] = -(date.getTimezoneOffset() * 60);
@@ -1308,10 +1135,83 @@ function unexportedRuntimeSymbol(sym) {
HEAP32[(((tmPtr)+(32))>>2)] = dst;
}
- function allocateUTF8(str) {
+ 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 c = str.charCodeAt(i); // possibly a lead surrogate
+ if (c <= 0x7F) {
+ len++;
+ } else if (c <= 0x7FF) {
+ len += 2;
+ } else if (c >= 0xD800 && c <= 0xDFFF) {
+ len += 4; ++i;
+ } else {
+ len += 3;
+ }
+ }
+ return len;
+ }
+
+ function stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) {
+ assert(typeof str === 'string');
+ // Parameter maxBytesToWrite is not optional. Negative values, 0, null,
+ // undefined and false each don't write out any bytes.
+ if (!(maxBytesToWrite > 0))
+ return 0;
+
+ var startIdx = outIdx;
+ var endIdx = outIdx + maxBytesToWrite - 1; // -1 for string null terminator.
+ for (var i = 0; i < str.length; ++i) {
+ // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code
+ // unit, not a Unicode code point of the character! So decode
+ // UTF16->UTF32->UTF8.
+ // See http://unicode.org/faq/utf_bom.html#utf16-3
+ // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description
+ // and https://www.ietf.org/rfc/rfc2279.txt
+ // and https://tools.ietf.org/html/rfc3629
+ var u = str.charCodeAt(i); // possibly a lead surrogate
+ if (u >= 0xD800 && u <= 0xDFFF) {
+ var u1 = str.charCodeAt(++i);
+ u = 0x10000 + ((u & 0x3FF) << 10) | (u1 & 0x3FF);
+ }
+ if (u <= 0x7F) {
+ if (outIdx >= endIdx) break;
+ heap[outIdx++] = u;
+ } else if (u <= 0x7FF) {
+ if (outIdx + 1 >= endIdx) break;
+ heap[outIdx++] = 0xC0 | (u >> 6);
+ heap[outIdx++] = 0x80 | (u & 63);
+ } else if (u <= 0xFFFF) {
+ if (outIdx + 2 >= endIdx) break;
+ heap[outIdx++] = 0xE0 | (u >> 12);
+ heap[outIdx++] = 0x80 | ((u >> 6) & 63);
+ heap[outIdx++] = 0x80 | (u & 63);
+ } else {
+ if (outIdx + 3 >= endIdx) break;
+ if (u > 0x10FFFF) warnOnce('Invalid Unicode code point ' + ptrToString(u) + ' encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF).');
+ heap[outIdx++] = 0xF0 | (u >> 18);
+ heap[outIdx++] = 0x80 | ((u >> 12) & 63);
+ heap[outIdx++] = 0x80 | ((u >> 6) & 63);
+ heap[outIdx++] = 0x80 | (u & 63);
+ }
+ }
+ // Null-terminate the pointer to the buffer.
+ heap[outIdx] = 0;
+ return outIdx - startIdx;
+ }
+ function stringToUTF8(str, outPtr, maxBytesToWrite) {
+ assert(typeof maxBytesToWrite == 'number', 'stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!');
+ return stringToUTF8Array(str, HEAPU8,outPtr, maxBytesToWrite);
+ }
+
+ function stringToNewUTF8(str) {
var size = lengthBytesUTF8(str) + 1;
var ret = _malloc(size);
- if (ret) stringToUTF8Array(str, HEAP8, ret, size);
+ if (ret) stringToUTF8(str, ret, size);
return ret;
}
function __tzset_js(timezone, daylight, tzname) {
@@ -1342,8 +1242,8 @@ function unexportedRuntimeSymbol(sym) {
};
var winterName = extractZone(winter);
var summerName = extractZone(summer);
- var winterNamePtr = allocateUTF8(winterName);
- var summerNamePtr = allocateUTF8(summerName);
+ var winterNamePtr = stringToNewUTF8(winterName);
+ var summerNamePtr = stringToNewUTF8(summerName);
if (summerOffset < winterOffset) {
// Northern hemisphere
HEAPU32[((tzname)>>2)] = winterNamePtr;
@@ -1433,6 +1333,11 @@ function unexportedRuntimeSymbol(sym) {
h.target.removeEventListener(h.eventTypeString, h.eventListenerFunc, h.useCapture);
JSEvents.eventHandlers.splice(i, 1);
},registerOrRemoveHandler:function(eventHandler) {
+ if (!eventHandler.target) {
+ err('registerOrRemoveHandler: the target element for event handler registration does not exist, when processing the following event handler registration:');
+ console.dir(eventHandler);
+ return -4;
+ }
var jsEventHandler = function jsEventHandler(event) {
// Increment nesting count for the event handler.
++JSEvents.inEventHandler;
@@ -1460,6 +1365,7 @@ function unexportedRuntimeSymbol(sym) {
}
}
}
+ return 0;
},getNodeNameForTarget:function(target) {
if (!target) return '';
if (target == window) return '#window';
@@ -1473,6 +1379,80 @@ function unexportedRuntimeSymbol(sym) {
;
}};
+ var UTF8Decoder = typeof TextDecoder != 'undefined' ? new TextDecoder('utf8') : undefined;
+
+ /**
+ * Given a pointer 'idx' to a null-terminated UTF8-encoded string in the given
+ * array that contains uint8 values, returns a copy of that string as a
+ * Javascript String object.
+ * heapOrArray is either a regular array, or a JavaScript typed array view.
+ * @param {number} idx
+ * @param {number=} maxBytesToRead
+ * @return {string}
+ */
+ function UTF8ArrayToString(heapOrArray, idx, maxBytesToRead) {
+ var endIdx = idx + maxBytesToRead;
+ var endPtr = idx;
+ // TextDecoder needs to know the byte length in advance, it doesn't stop on
+ // null terminator by itself. Also, use the length info to avoid running tiny
+ // strings through TextDecoder, since .subarray() allocates garbage.
+ // (As a tiny code save trick, compare endPtr against endIdx using a negation,
+ // so that undefined means Infinity)
+ while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr;
+
+ if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) {
+ return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr));
+ }
+ var str = '';
+ // If building with TextDecoder, we have already computed the string length
+ // above, so test loop end condition against that
+ while (idx < endPtr) {
+ // For UTF8 byte structure, see:
+ // http://en.wikipedia.org/wiki/UTF-8#Description
+ // https://www.ietf.org/rfc/rfc2279.txt
+ // https://tools.ietf.org/html/rfc3629
+ var u0 = heapOrArray[idx++];
+ if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; }
+ var u1 = heapOrArray[idx++] & 63;
+ if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; }
+ var u2 = heapOrArray[idx++] & 63;
+ if ((u0 & 0xF0) == 0xE0) {
+ u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
+ } else {
+ if ((u0 & 0xF8) != 0xF0) warnOnce('Invalid UTF-8 leading byte ' + ptrToString(u0) + ' encountered when deserializing a UTF-8 string in wasm memory to a JS string!');
+ u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63);
+ }
+
+ if (u0 < 0x10000) {
+ str += String.fromCharCode(u0);
+ } else {
+ var ch = u0 - 0x10000;
+ str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF));
+ }
+ }
+ return str;
+ }
+
+
+ /**
+ * Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the
+ * emscripten HEAP, returns a copy of that string as a Javascript String object.
+ *
+ * @param {number} ptr
+ * @param {number=} maxBytesToRead - An optional length that specifies the
+ * maximum number of bytes to read. You can omit this parameter to scan the
+ * string until the first 0 byte. If maxBytesToRead is passed, and the string
+ * at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the
+ * string will cut short at that byte index (i.e. maxBytesToRead will not
+ * produce a string of exact length [ptr, ptr+maxBytesToRead[) N.B. mixing
+ * frequent uses of UTF8ToString() with and without maxBytesToRead may throw
+ * JS JIT optimizations off, so it is worth to consider consistently using one
+ * @return {string}
+ */
+ function UTF8ToString(ptr, maxBytesToRead) {
+ assert(typeof ptr == 'number');
+ return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : '';
+ }
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).
@@ -1540,13 +1520,14 @@ function unexportedRuntimeSymbol(sym) {
function emscripten_realloc_buffer(size) {
var b = wasmMemory.buffer;
+ var pages = (size - b.byteLength + 65535) >>> 16;
try {
// round size grow request up to wasm page size (fixed 64KB per spec)
- wasmMemory.grow((size - b.byteLength + 65535) >>> 16); // .grow() takes a delta compared to the previous size
+ wasmMemory.grow(pages); // .grow() takes a delta compared to the previous size
updateMemoryViews();
return 1 /*success*/;
} catch(e) {
- err('emscripten_realloc_buffer: Attempted to grow heap from ' + b.byteLength + ' bytes to ' + size + ' bytes, but got error: ' + e);
+ err(`emscripten_realloc_buffer: Attempted to grow heap from ${b.byteLength} bytes to ${size} bytes, but got error: ${e}`);
}
// implicit 0 return to save code size (caller will cast "undefined" into 0
// anyhow)
@@ -1579,11 +1560,11 @@ function unexportedRuntimeSymbol(sym) {
// (the wasm binary specifies it, so if we tried, we'd fail anyhow).
var maxHeapSize = getHeapMax();
if (requestedSize > maxHeapSize) {
- err('Cannot enlarge memory, asked to go up to ' + requestedSize + ' bytes, but the limit is ' + maxHeapSize + ' bytes!');
+ err(`Cannot enlarge memory, asked to go up to ${requestedSize} bytes, but the limit is ${maxHeapSize} bytes!`);
return false;
}
- let alignUp = (x, multiple) => x + (multiple - x % multiple) % multiple;
+ var alignUp = (x, multiple) => x + (multiple - x % multiple) % multiple;
// Loop through potential heap size increases. If we attempt a too eager
// reservation that fails, cut down on the attempted size and reserve a
@@ -1601,7 +1582,7 @@ function unexportedRuntimeSymbol(sym) {
return true;
}
}
- err('Failed to grow the heap from ' + oldSize + ' bytes to ' + newSize + ' bytes, not enough memory!');
+ err(`Failed to grow the heap from ${oldSize} bytes to ${newSize} bytes, not enough memory!`);
return false;
}
@@ -1646,6 +1627,7 @@ function unexportedRuntimeSymbol(sym) {
}
+
function registerMouseEventCallback(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) {
if (!JSEvents.mouseEvent) JSEvents.mouseEvent = _malloc( 72 );
target = findEventTarget(target);
@@ -1665,15 +1647,15 @@ function unexportedRuntimeSymbol(sym) {
handlerFunc: mouseEventHandlerFunc,
useCapture: useCapture
};
- JSEvents.registerOrRemoveHandler(eventHandler);
+ return JSEvents.registerOrRemoveHandler(eventHandler);
}
function _emscripten_set_click_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
- registerMouseEventCallback(target, userData, useCapture, callbackfunc, 4, "click", targetThread);
- return 0;
+ return registerMouseEventCallback(target, userData, useCapture, callbackfunc, 4, "click", targetThread);
}
+
function registerUiEventCallback(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) {
if (!JSEvents.uiEvent) JSEvents.uiEvent = _malloc( 36 );
@@ -1712,17 +1694,40 @@ function unexportedRuntimeSymbol(sym) {
handlerFunc: uiEventHandlerFunc,
useCapture: useCapture
};
- JSEvents.registerOrRemoveHandler(eventHandler);
+ return 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;
+ return registerUiEventCallback(target, userData, useCapture, callbackfunc, 10, "resize", targetThread);
}
- var Fetch = {xhrs:{},setu64:function(addr, val) {
- HEAPU32[addr >> 2] = val;
- HEAPU32[addr + 4 >> 2] = (val / 4294967296)|0;
- },openDatabase:function(dbname, dbversion, onsuccess, onerror) {
+
+
+ /** @constructor */
+ function HandleAllocator() {
+ // Reserve slot 0 so that 0 is always an invalid handle
+ this.allocated = [undefined];
+ this.freelist = [];
+ this.get = function(id) {
+ assert(this.allocated[id] !== undefined, `invalid handle: ${id}`);
+ return this.allocated[id];
+ };
+ this.has = function(id) {
+ return this.allocated[id] !== undefined;
+ };
+ this.allocate = function(handle) {
+ var id = this.freelist.pop() || this.allocated.length;
+ this.allocated[id] = handle;
+ return id;
+ };
+ this.free = function(id) {
+ assert(this.allocated[id] !== undefined);
+ // Set the slot to `undefined` rather than using `delete` here since
+ // apparently arrays with holes in them can be less efficient.
+ this.allocated[id] = undefined;
+ this.freelist.push(id);
+ };
+ }
+ var Fetch = {openDatabase:function(dbname, dbversion, onsuccess, onerror) {
try {
var openRequest = indexedDB.open(dbname, dbversion);
} catch (e) { return onerror(e); }
@@ -1736,7 +1741,8 @@ function unexportedRuntimeSymbol(sym) {
};
openRequest.onsuccess = (event) => onsuccess(event.target.result);
openRequest.onerror = (error) => onerror(error);
- },staticInit:function() {
+ },init:function() {
+ Fetch.xhrs = new HandleAllocator();
var onsuccess = (db) => {
Fetch.dbInstance = db;
removeRunDependency('library_fetch_init');
@@ -1752,7 +1758,7 @@ function unexportedRuntimeSymbol(sym) {
}};
function fetchXHR(fetch, onsuccess, onerror, onprogress, onreadystatechange) {
- var url = HEAPU32[fetch + 8 >> 2];
+ var url = HEAPU32[(((fetch)+(8))>>2)];
if (!url) {
onerror(fetch, 0, 'no url specified!');
return;
@@ -1760,33 +1766,26 @@ function unexportedRuntimeSymbol(sym) {
var url_ = UTF8ToString(url);
var fetch_attr = fetch + 112;
- var requestMethod = UTF8ToString(fetch_attr);
+ var requestMethod = UTF8ToString(fetch_attr + 0);
if (!requestMethod) requestMethod = 'GET';
- var userData = HEAPU32[fetch + 4 >> 2];
- var fetchAttributes = HEAPU32[fetch_attr + 52 >> 2];
- var timeoutMsecs = HEAPU32[fetch_attr + 56 >> 2];
- var withCredentials = !!HEAPU32[fetch_attr + 60 >> 2];
- var destinationPath = HEAPU32[fetch_attr + 64 >> 2];
- var userName = HEAPU32[fetch_attr + 68 >> 2];
- var password = HEAPU32[fetch_attr + 72 >> 2];
- var requestHeaders = HEAPU32[fetch_attr + 76 >> 2];
- var overriddenMimeType = HEAPU32[fetch_attr + 80 >> 2];
- var dataPtr = HEAPU32[fetch_attr + 84 >> 2];
- var dataLength = HEAPU32[fetch_attr + 88 >> 2];
-
+ var timeoutMsecs = HEAPU32[(((fetch_attr)+(56))>>2)];
+ var userName = HEAPU32[(((fetch_attr)+(68))>>2)];
+ var password = HEAPU32[(((fetch_attr)+(72))>>2)];
+ var requestHeaders = HEAPU32[(((fetch_attr)+(76))>>2)];
+ var overriddenMimeType = HEAPU32[(((fetch_attr)+(80))>>2)];
+ var dataPtr = HEAPU32[(((fetch_attr)+(84))>>2)];
+ var dataLength = HEAPU32[(((fetch_attr)+(88))>>2)];
+
+ var fetchAttributes = HEAPU32[(((fetch_attr)+(52))>>2)];
var fetchAttrLoadToMemory = !!(fetchAttributes & 1);
var fetchAttrStreamData = !!(fetchAttributes & 2);
- var fetchAttrPersistFile = !!(fetchAttributes & 4);
- var fetchAttrAppend = !!(fetchAttributes & 8);
- var fetchAttrReplace = !!(fetchAttributes & 16);
var fetchAttrSynchronous = !!(fetchAttributes & 64);
- var fetchAttrWaitable = !!(fetchAttributes & 128);
var userNameStr = userName ? UTF8ToString(userName) : undefined;
var passwordStr = password ? UTF8ToString(password) : undefined;
var xhr = new XMLHttpRequest();
- xhr.withCredentials = withCredentials;
+ xhr.withCredentials = !!HEAPU8[(((fetch_attr)+(60))>>0)];;
xhr.open(requestMethod, url_, !fetchAttrSynchronous, userNameStr, passwordStr);
if (!fetchAttrSynchronous) xhr.timeout = timeoutMsecs; // XHR timeout field is only accessible in async XHRs, and must be set after .open() but before .send().
xhr.url_ = url_; // Save the url for debugging purposes (and for comparing to the responseURL that server side advertised)
@@ -1799,9 +1798,9 @@ function unexportedRuntimeSymbol(sym) {
}
if (requestHeaders) {
for (;;) {
- var key = HEAPU32[requestHeaders >> 2];
+ var key = HEAPU32[((requestHeaders)>>2)];
if (!key) break;
- var value = HEAPU32[requestHeaders + 4 >> 2];
+ var value = HEAPU32[(((requestHeaders)+(4))>>2)];
if (!value) break;
requestHeaders += 8;
var keyStr = UTF8ToString(key);
@@ -1809,8 +1808,9 @@ function unexportedRuntimeSymbol(sym) {
xhr.setRequestHeader(keyStr, valueStr);
}
}
- var id = HEAPU32[fetch + 0 >> 2];
- Fetch.xhrs[id] = xhr;
+
+ var id = Fetch.xhrs.allocate(xhr);
+ HEAPU32[((fetch)>>2)] = id;
var data = (dataPtr && dataLength) ? HEAPU8.slice(dataPtr, dataPtr + dataLength) : null;
// TODO: Support specifying custom headers to the request.
@@ -1831,14 +1831,14 @@ function unexportedRuntimeSymbol(sym) {
HEAPU8.set(new Uint8Array(/** @type{Array<number>} */(xhr.response)), ptr);
}
HEAPU32[fetch + 12 >> 2] = ptr;
- Fetch.setu64(fetch + 16, ptrLen);
- Fetch.setu64(fetch + 24, 0);
+ writeI53ToI64(fetch + 16, ptrLen);
+ writeI53ToI64(fetch + 24, 0);
var len = xhr.response ? xhr.response.byteLength : 0;
if (len) {
// If the final XHR.onload handler receives the bytedata to compute total length, report that,
// otherwise don't write anything out here, which will retain the latest byte size reported in
// the most recent XHR.onprogress handler.
- Fetch.setu64(fetch + 32, len);
+ writeI53ToI64(fetch + 32, len);
}
HEAPU16[fetch + 40 >> 1] = xhr.readyState;
HEAPU16[fetch + 42 >> 1] = xhr.status;
@@ -1847,7 +1847,7 @@ function unexportedRuntimeSymbol(sym) {
xhr.onload = (e) => {
// check if xhr was aborted by user and don't try to call back
- if (!(id in Fetch.xhrs)) {
+ if (!Fetch.xhrs.has(id)) {
return;
}
saveResponseAndStatus();
@@ -1859,7 +1859,7 @@ function unexportedRuntimeSymbol(sym) {
};
xhr.onerror = (e) => {
// check if xhr was aborted by user and don't try to call back
- if (!(id in Fetch.xhrs)) {
+ if (!Fetch.xhrs.has(id)) {
return;
}
saveResponseAndStatus();
@@ -1867,14 +1867,14 @@ function unexportedRuntimeSymbol(sym) {
};
xhr.ontimeout = (e) => {
// check if xhr was aborted by user and don't try to call back
- if (!(id in Fetch.xhrs)) {
+ if (!Fetch.xhrs.has(id)) {
return;
}
if (onerror) onerror(fetch, xhr, e);
};
xhr.onprogress = (e) => {
// check if xhr was aborted by user and don't try to call back
- if (!(id in Fetch.xhrs)) {
+ if (!Fetch.xhrs.has(id)) {
return;
}
var ptrLen = (fetchAttrLoadToMemory && fetchAttrStreamData && xhr.response) ? xhr.response.byteLength : 0;
@@ -1886,9 +1886,9 @@ function unexportedRuntimeSymbol(sym) {
HEAPU8.set(new Uint8Array(/** @type{Array<number>} */(xhr.response)), ptr);
}
HEAPU32[fetch + 12 >> 2] = ptr;
- Fetch.setu64(fetch + 16, ptrLen);
- Fetch.setu64(fetch + 24, e.loaded - ptrLen);
- Fetch.setu64(fetch + 32, e.total);
+ writeI53ToI64(fetch + 16, ptrLen);
+ writeI53ToI64(fetch + 24, e.loaded - ptrLen);
+ writeI53ToI64(fetch + 32, e.total);
HEAPU16[fetch + 40 >> 1] = xhr.readyState;
// If loading files from a source that does not give HTTP status code, assume success if we get data bytes
if (xhr.readyState >= 3 && xhr.status === 0 && e.loaded > 0) xhr.status = 200;
@@ -1901,7 +1901,7 @@ function unexportedRuntimeSymbol(sym) {
};
xhr.onreadystatechange = (e) => {
// check if xhr was aborted by user and don't try to call back
- if (!(id in Fetch.xhrs)) {
+ if (!Fetch.xhrs.has(id)) {
return;
}
@@ -1930,11 +1930,56 @@ function unexportedRuntimeSymbol(sym) {
checkStackCookie();
if (e instanceof WebAssembly.RuntimeError) {
if (_emscripten_stack_get_current() <= 0) {
- err('Stack overflow detected. You can try increasing -sSTACK_SIZE (currently set to ' + 65536 + ')');
+ err('Stack overflow detected. You can try increasing -sSTACK_SIZE (currently set to 65536)');
}
}
quit_(1, e);
}
+
+
+ var SYSCALLS = {varargs:undefined,get:function() {
+ assert(SYSCALLS.varargs != undefined);
+ SYSCALLS.varargs += 4;
+ var ret = HEAP32[(((SYSCALLS.varargs)-(4))>>2)];
+ return ret;
+ },getStr:function(ptr) {
+ var ret = UTF8ToString(ptr);
+ return ret;
+ }};
+ function _proc_exit(code) {
+ EXITSTATUS = code;
+ if (!keepRuntimeAlive()) {
+ if (Module['onExit']) Module['onExit'](code);
+ ABORT = true;
+ }
+ quit_(code, new ExitStatus(code));
+ }
+ /** @suppress {duplicate } */
+ /** @param {boolean|number=} implicit */
+ function exitJS(status, implicit) {
+ EXITSTATUS = status;
+
+ checkUnflushedContent();
+
+ // if exit() was called explicitly, warn the user if the runtime isn't actually being shut down
+ if (keepRuntimeAlive() && !implicit) {
+ var msg = `program exited (with status: ${status}), but keepRuntimeAlive() is set (counter=${runtimeKeepaliveCounter}) due to an async operation, so halting execution but not exiting the runtime or preventing further async execution (you can use emscripten_force_exit, if you want to force a true shutdown)`;
+ err(msg);
+ }
+
+ _proc_exit(status);
+ }
+ var _exit = exitJS;
+
+ function maybeExit() {
+ if (!keepRuntimeAlive()) {
+ try {
+ _exit(EXITSTATUS);
+ } catch (e) {
+ handleException(e);
+ }
+ }
+ }
function callUserCallback(func) {
if (ABORT) {
err('user callback triggered after runtime exited or application aborted. Ignoring.');
@@ -1942,11 +1987,24 @@ function unexportedRuntimeSymbol(sym) {
}
try {
func();
+ maybeExit();
} catch (e) {
handleException(e);
}
}
+
+ function readI53FromU64(ptr) {
+ return HEAPU32[ptr>>2] + HEAPU32[ptr+4>>2] * 4294967296;
+ }
+ function writeI53ToI64(ptr, num) {
+ HEAPU32[ptr>>2] = num;
+ HEAPU32[ptr+4>>2] = (num - HEAPU32[ptr>>2])/4294967296;
+ var deserialized = (num >= 0) ? readI53FromU64(ptr) : readI53FromI64(ptr);
+ if (deserialized != num) warnOnce('writeI53ToI64() out of range: serialized JS Number ' + num + ' to Wasm heap as bytes lo=' + ptrToString(HEAPU32[ptr>>2]) + ', hi=' + ptrToString(HEAPU32[ptr+4>>2]) + ', which deserializes back to ' + deserialized + ' instead!');
+ }
+
+
function fetchCacheData(/** @type {IDBDatabase} */ db, fetch, data, onsuccess, onerror) {
if (!db) {
onerror(fetch, 0, 'IndexedDB not available!');
@@ -2006,9 +2064,9 @@ function unexportedRuntimeSymbol(sym) {
var ptr = _malloc(len);
HEAPU8.set(new Uint8Array(value), ptr);
HEAPU32[fetch + 12 >> 2] = ptr;
- Fetch.setu64(fetch + 16, len);
- Fetch.setu64(fetch + 24, 0);
- Fetch.setu64(fetch + 32, len);
+ writeI53ToI64(fetch + 16, len);
+ writeI53ToI64(fetch + 24, 0);
+ writeI53ToI64(fetch + 32, len);
HEAPU16[fetch + 40 >> 1] = 4; // Mimic XHR readyState 4 === 'DONE: The operation is complete'
HEAPU16[fetch + 42 >> 1] = 200; // Mimic XHR HTTP status code 200 "OK"
stringToUTF8("OK", fetch + 44, 64);
@@ -2050,9 +2108,9 @@ function unexportedRuntimeSymbol(sym) {
request.onsuccess = (event) => {
var value = event.target.result;
HEAPU32[fetch + 12 >> 2] = 0;
- Fetch.setu64(fetch + 16, 0);
- Fetch.setu64(fetch + 24, 0);
- Fetch.setu64(fetch + 32, 0);
+ writeI53ToI64(fetch + 16, 0);
+ writeI53ToI64(fetch + 24, 0);
+ writeI53ToI64(fetch + 32, 0);
HEAPU16[fetch + 40 >> 1] = 4; // Mimic XHR readyState 4 === 'DONE: The operation is complete'
HEAPU16[fetch + 42 >> 1] = 200; // Mimic XHR HTTP status code 200 "OK"
stringToUTF8("OK", fetch + 44, 64);
@@ -2069,24 +2127,18 @@ function unexportedRuntimeSymbol(sym) {
}
}
+
function _emscripten_start_fetch(fetch, successcb, errorcb, progresscb, readystatechangecb) {
// Avoid shutting down the runtime since we want to wait for the async
// response.
var fetch_attr = fetch + 112;
- var requestMethod = UTF8ToString(fetch_attr);
var onsuccess = HEAPU32[fetch_attr + 36 >> 2];
var onerror = HEAPU32[fetch_attr + 40 >> 2];
var onprogress = HEAPU32[fetch_attr + 44 >> 2];
var onreadystatechange = HEAPU32[fetch_attr + 48 >> 2];
var fetchAttributes = HEAPU32[fetch_attr + 52 >> 2];
- var fetchAttrLoadToMemory = !!(fetchAttributes & 1);
- var fetchAttrStreamData = !!(fetchAttributes & 2);
- var fetchAttrPersistFile = !!(fetchAttributes & 4);
- var fetchAttrNoDownload = !!(fetchAttributes & 32);
- var fetchAttrAppend = !!(fetchAttributes & 8);
- var fetchAttrReplace = !!(fetchAttributes & 16);
var fetchAttrSynchronous = !!(fetchAttributes & 64);
function doCallback(f) {
@@ -2153,10 +2205,15 @@ function unexportedRuntimeSymbol(sym) {
fetchXHR(fetch, cacheResultAndReportSuccess, reportError, reportProgress, reportReadyStateChange);
};
+ var requestMethod = UTF8ToString(fetch_attr + 0);
+ var fetchAttrReplace = !!(fetchAttributes & 16);
+ var fetchAttrPersistFile = !!(fetchAttributes & 4);
+ var fetchAttrNoDownload = !!(fetchAttributes & 32);
if (requestMethod === 'EM_IDB_STORE') {
// TODO(?): Here we perform a clone of the data, because storing shared typed arrays to IndexedDB does not seem to be allowed.
- var ptr = HEAPU32[fetch_attr + 84 >> 2];
- fetchCacheData(Fetch.dbInstance, fetch, HEAPU8.slice(ptr, ptr + HEAPU32[fetch_attr + 88 >> 2]), reportSuccess, reportError);
+ var ptr = HEAPU32[(((fetch_attr)+(84))>>2)];
+ var size = HEAPU32[(((fetch_attr)+(88))>>2)];
+ fetchCacheData(Fetch.dbInstance, fetch, HEAPU8.slice(ptr, ptr + size), reportSuccess, reportError);
} else if (requestMethod === 'EM_IDB_DELETE') {
fetchDeleteCachedData(Fetch.dbInstance, fetch, reportSuccess, reportError);
} else if (!fetchAttrReplace) {
@@ -2169,7 +2226,7 @@ function unexportedRuntimeSymbol(sym) {
return fetch;
}
- function __webgl_enable_ANGLE_instanced_arrays(ctx) {
+ 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) {
@@ -2180,7 +2237,7 @@ function unexportedRuntimeSymbol(sym) {
}
}
- function __webgl_enable_OES_vertex_array_object(ctx) {
+ 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) {
@@ -2192,7 +2249,7 @@ function unexportedRuntimeSymbol(sym) {
}
}
- function __webgl_enable_WEBGL_draw_buffers(ctx) {
+ 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) {
@@ -2201,21 +2258,22 @@ function unexportedRuntimeSymbol(sym) {
}
}
- function __webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(ctx) {
+ 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) {
+ 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) {
+ 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:[],shaders:[],vaos:[],contexts:[],offscreenCanvases:{},queries:[],samplers:[],transformFeedbacks:[],syncs:[],byteSizeByTypeRoot:5120,byteSizeByType:[1,1,2,2,4,4,4,2,3,4,8],stringCache:{},stringiCache:{},unpackAlignment:4,recordError:function recordError(errorCode) {
if (!GL.lastError) {
GL.lastError = errorCode;
@@ -2435,12 +2493,12 @@ function unexportedRuntimeSymbol(sym) {
// 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);
+ 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);
+ webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(GLctx);
+ webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance(GLctx);
// On WebGL 2, EXT_disjoint_timer_query is replaced with an alternative
// that's based on core APIs, and exposes only the queryCounterEXT()
@@ -2457,7 +2515,7 @@ function unexportedRuntimeSymbol(sym) {
GLctx.disjointTimerQueryExt = GLctx.getExtension("EXT_disjoint_timer_query");
}
- __webgl_enable_WEBGL_multi_draw(GLctx);
+ webgl_enable_WEBGL_multi_draw(GLctx);
// .getSupportedExtensions() can return null if context is lost, so coerce to empty array.
var exts = GLctx.getSupportedExtensions() || [];
@@ -2471,9 +2529,11 @@ function unexportedRuntimeSymbol(sym) {
}};
- var __emscripten_webgl_power_preferences = ['default', 'low-power', 'high-performance'];
+ var emscripten_webgl_power_preferences = ['default', 'low-power', 'high-performance'];
+
+ /** @suppress {duplicate } */
function _emscripten_webgl_do_create_context(target, attributes) {
assert(attributes);
var a = attributes >> 2;
@@ -2485,7 +2545,7 @@ function unexportedRuntimeSymbol(sym) {
'antialias': !!HEAP32[a + (12>>2)],
'premultipliedAlpha': !!HEAP32[a + (16>>2)],
'preserveDrawingBuffer': !!HEAP32[a + (20>>2)],
- 'powerPreference': __emscripten_webgl_power_preferences[powerPreference],
+ 'powerPreference': emscripten_webgl_power_preferences[powerPreference],
'failIfMajorPerformanceCaveat': !!HEAP32[a + (28>>2)],
// The following are not predefined WebGL context attributes in the WebGL specification, so the property names can be minified by Closure.
majorVersion: HEAP32[a + (32>>2)],
@@ -2532,15 +2592,6 @@ function unexportedRuntimeSymbol(sym) {
return success ? 0 : -5;
}
- var SYSCALLS = {varargs:undefined,get:function() {
- assert(SYSCALLS.varargs != undefined);
- SYSCALLS.varargs += 4;
- var ret = HEAP32[(((SYSCALLS.varargs)-(4))>>2)];
- return ret;
- },getStr:function(ptr) {
- var ret = UTF8ToString(ptr);
- return ret;
- }};
function _fd_close(fd) {
abort('fd_close called without SYSCALLS_REQUIRE_FILESYSTEM');
}
@@ -2559,6 +2610,7 @@ function unexportedRuntimeSymbol(sym) {
}
var printCharBuffers = [null,[],[]];
+
function printChar(stream, curr) {
var buffer = printCharBuffers[stream];
assert(buffer);
@@ -2622,12 +2674,12 @@ function unexportedRuntimeSymbol(sym) {
}
function _glBindVertexArray(vao) {
- GLctx['bindVertexArray'](GL.vaos[vao]);
+ GLctx.bindVertexArray(GL.vaos[vao]);
var ibo = GLctx.getParameter(0x8895 /*ELEMENT_ARRAY_BUFFER_BINDING*/);
GLctx.currentElementArrayBufferBinding = ibo ? (ibo.name | 0) : 0;
}
- function _glBlendFunc(x0, x1) { GLctx['blendFunc'](x0, x1) }
+ function _glBlendFunc(x0, x1) { GLctx.blendFunc(x0, x1) }
function _glBufferData(target, size, data, usage) {
@@ -2655,11 +2707,11 @@ function unexportedRuntimeSymbol(sym) {
GLctx.bufferSubData(target, offset, HEAPU8.subarray(data, data+size));
}
- function _glClear(x0) { GLctx['clear'](x0) }
+ function _glClear(x0) { GLctx.clear(x0) }
- function _glClearColor(x0, x1, x2, x3) { GLctx['clearColor'](x0, x1, x2, x3) }
+ function _glClearColor(x0, x1, x2, x3) { GLctx.clearColor(x0, x1, x2, x3) }
- function _glClearDepth(x0) { GLctx['clearDepth'](x0) }
+ function _glClearDepth(x0) { GLctx.clearDepth(x0) }
function _glCompileShader(shader) {
GLctx.compileShader(GL.shaders[shader]);
@@ -2730,12 +2782,12 @@ function unexportedRuntimeSymbol(sym) {
function _glDeleteVertexArrays(n, vaos) {
for (var i = 0; i < n; i++) {
var id = HEAP32[(((vaos)+(i*4))>>2)];
- GLctx['deleteVertexArray'](GL.vaos[id]);
+ GLctx.deleteVertexArray(GL.vaos[id]);
GL.vaos[id] = null;
}
}
- function _glDepthFunc(x0) { GLctx['depthFunc'](x0) }
+ function _glDepthFunc(x0) { GLctx.depthFunc(x0) }
function _glDepthMask(flag) {
GLctx.depthMask(!!flag);
@@ -2775,7 +2827,7 @@ function unexportedRuntimeSymbol(sym) {
}
}
- function _glEnable(x0) { GLctx['enable'](x0) }
+ function _glEnable(x0) { GLctx.enable(x0) }
function _glEnableVertexAttribArray(index) {
var cb = GL.currentContext.clientBuffers[index];
@@ -2809,6 +2861,7 @@ function unexportedRuntimeSymbol(sym) {
);
}
+
function _glGetAttribLocation(program, name) {
return GLctx.getAttribLocation(GL.programs[program], UTF8ToString(name));
}
@@ -2865,6 +2918,7 @@ function unexportedRuntimeSymbol(sym) {
}
}
+
function _glGetShaderInfoLog(shader, maxLength, length, infoLog) {
var log = GLctx.getShaderInfoLog(GL.shaders[shader]);
if (log === null) log = '(unknown error)';
@@ -2950,6 +3004,7 @@ function unexportedRuntimeSymbol(sym) {
}
+
function _glGetUniformLocation(program, name) {
name = UTF8ToString(name);
@@ -3077,7 +3132,7 @@ function unexportedRuntimeSymbol(sym) {
}
function _glVertexAttribDivisor(index, divisor) {
- GLctx['vertexAttribDivisor'](index, divisor);
+ GLctx.vertexAttribDivisor(index, divisor);
}
function _glVertexAttribPointer(index, size, type, normalized, stride, ptr) {
@@ -3098,31 +3153,8 @@ function unexportedRuntimeSymbol(sym) {
GLctx.vertexAttribPointer(index, size, type, !!normalized, stride, ptr);
}
-
- function _proc_exit(code) {
- EXITSTATUS = code;
- if (!keepRuntimeAlive()) {
- if (Module['onExit']) Module['onExit'](code);
- ABORT = true;
- }
- quit_(code, new ExitStatus(code));
- }
- /** @param {boolean|number=} implicit */
- function exitJS(status, implicit) {
- EXITSTATUS = status;
-
- checkUnflushedContent();
-
- // if exit() was called explicitly, warn the user if the runtime isn't actually being shut down
- if (keepRuntimeAlive() && !implicit) {
- var msg = 'program exited (with status: ' + status + '), but EXIT_RUNTIME is not set, so halting execution but not exiting the runtime or preventing further async execution (build with EXIT_RUNTIME=1, if you want a true shutdown)';
- err(msg);
- }
-
- _proc_exit(status);
- }
-Fetch.staticInit();;
+Fetch.init();;
var GLctx;;
var miniTempWebGLFloatBuffersStorage = new Float32Array(288);
for (/**@suppress{duplicate}*/var i = 0; i < 288; ++i) {
@@ -3243,7 +3275,8 @@ var dynCall_jiji = Module["dynCall_jiji"] = createExportWrapper("dynCall_jiji");
var missingLibrarySymbols = [
'zeroMemory',
- 'stringToNewUTF8',
+ 'arraySum',
+ 'addDays',
'setErrNo',
'inetPton4',
'inetNtop4',
@@ -3252,8 +3285,11 @@ var missingLibrarySymbols = [
'readSockaddr',
'writeSockaddr',
'getHostByName',
- 'getRandomDevice',
+ 'initRandomFill',
+ 'randomFill',
'traverseStack',
+ 'getCallstack',
+ 'emscriptenLog',
'convertPCtoSourceLocation',
'readEmAsmArgs',
'jstoi_s',
@@ -3265,24 +3301,20 @@ var missingLibrarySymbols = [
'dynCall',
'runtimeKeepalivePush',
'runtimeKeepalivePop',
- 'maybeExit',
'safeSetTimeout',
'asmjsMangle',
'asyncLoad',
'alignMemory',
'mmapAlloc',
- 'handleAllocator',
'getNativeTypeSize',
'STACK_SIZE',
'STACK_ALIGN',
'POINTER_SIZE',
'ASSERTIONS',
- 'writeI53ToI64',
'writeI53ToI64Clamped',
'writeI53ToI64Signaling',
'writeI53ToU64Clamped',
'writeI53ToU64Signaling',
- 'readI53FromU64',
'convertI32PairToI53',
'convertU32PairToI53',
'getCFunc',
@@ -3312,12 +3344,8 @@ var missingLibrarySymbols = [
'UTF32ToString',
'stringToUTF32',
'lengthBytesUTF32',
- 'allocateUTF8OnStack',
- 'writeStringToMemory',
+ 'stringToUTF8OnStack',
'writeArrayToMemory',
- 'writeAsciiToMemory',
- 'getSocketFromFD',
- 'getSocketAddress',
'registerKeyEventCallback',
'registerWheelEventCallback',
'registerFocusEventCallback',
@@ -3359,46 +3387,53 @@ var missingLibrarySymbols = [
'stackTrace',
'getEnvStrings',
'checkWasiClock',
+ 'wasiRightsToMuslOFlags',
+ 'wasiOFlagsToMuslOFlags',
'createDyncallWrapper',
'setImmediateWrapped',
'clearImmediateWrapped',
'polyfillSetImmediate',
- 'newNativePromise',
'getPromise',
+ 'makePromise',
+ 'idsToPromises',
+ 'makePromiseCallback',
'ExceptionInfo',
- 'exception_addRef',
- 'exception_decRef',
'setMainLoop',
+ 'getSocketFromFD',
+ 'getSocketAddress',
+ 'FS_createPreloadedFile',
+ 'FS_modeStringToFlags',
+ 'FS_getMode',
'_setNetworkCallback',
'heapObjectForWebGLType',
'heapAccessShiftForWebGLHeap',
'emscriptenWebGLGet',
'computeUnpackAlignedImageSize',
+ 'colorChannelsInGlTextureFormat',
'emscriptenWebGLGetTexPixelData',
'emscriptenWebGLGetUniform',
'emscriptenWebGLGetVertexAttrib',
+ '__glGetActiveAttribOrUniform',
'emscriptenWebGLGetBufferBinding',
'emscriptenWebGLValidateMapBufferTarget',
'writeGLArray',
+ 'registerWebGlEventCallback',
+ 'runAndAbortIfError',
'SDL_unicode',
'SDL_ttfContext',
'SDL_audio',
'GLFW_Window',
- 'runAndAbortIfError',
'emscriptenWebGLGetIndexed',
'ALLOC_NORMAL',
'ALLOC_STACK',
'allocate',
+ 'writeStringToMemory',
+ 'writeAsciiToMemory',
];
missingLibrarySymbols.forEach(missingLibrarySymbol)
var unexportedSymbols = [
'run',
- 'UTF8ArrayToString',
- 'UTF8ToString',
- 'stringToUTF8Array',
- 'stringToUTF8',
- 'lengthBytesUTF8',
'addOnPreRun',
'addOnInit',
'addOnPreMain',
@@ -3409,7 +3444,6 @@ var unexportedSymbols = [
'FS_createFolder',
'FS_createPath',
'FS_createDataFile',
- 'FS_createPreloadedFile',
'FS_createLazyFile',
'FS_createLink',
'FS_createDevice',
@@ -3432,6 +3466,12 @@ var unexportedSymbols = [
'getHeapMax',
'emscripten_realloc_buffer',
'ENV',
+ 'MONTH_DAYS_REGULAR',
+ 'MONTH_DAYS_LEAP',
+ 'MONTH_DAYS_REGULAR_CUMULATIVE',
+ 'MONTH_DAYS_LEAP_CUMULATIVE',
+ 'isLeapYear',
+ 'ydayFromDate',
'ERRNO_CODES',
'ERRNO_MESSAGES',
'DNS',
@@ -3444,7 +3484,11 @@ var unexportedSymbols = [
'jstoi_q',
'handleException',
'callUserCallback',
+ 'maybeExit',
+ 'HandleAllocator',
+ 'writeI53ToI64',
'readI53FromI64',
+ 'readI53FromU64',
'convertI32PairToI53Checked',
'freeTableIndexes',
'functionsInTableMap',
@@ -3452,9 +3496,14 @@ var unexportedSymbols = [
'getValue',
'PATH',
'PATH_FS',
+ 'UTF8Decoder',
+ 'UTF8ArrayToString',
+ 'UTF8ToString',
+ 'stringToUTF8Array',
+ 'stringToUTF8',
+ 'lengthBytesUTF8',
'UTF16Decoder',
- 'allocateUTF8',
- 'SYSCALLS',
+ 'stringToNewUTF8',
'JSEvents',
'specialHTMLTargets',
'maybeCStringToJsString',
@@ -3475,6 +3524,8 @@ var unexportedSymbols = [
'exceptionCaught',
'Browser',
'wget',
+ 'SYSCALLS',
+ 'preloadPlugins',
'FS',
'MEMFS',
'TTY',
@@ -3482,18 +3533,29 @@ var unexportedSymbols = [
'SOCKFS',
'tempFixedLengthArray',
'miniTempWebGLFloatBuffers',
+ 'miniTempWebGLIntBuffers',
+ 'webgl_enable_ANGLE_instanced_arrays',
+ 'webgl_enable_OES_vertex_array_object',
+ 'webgl_enable_WEBGL_draw_buffers',
+ 'webgl_enable_WEBGL_multi_draw',
'GL',
+ '__glGenObject',
'webglGetUniformLocation',
'webglPrepareUniformLocationsBeforeFirstUse',
'webglGetLeftBracePos',
+ 'emscripten_webgl_power_preferences',
'AL',
- 'SDL',
- 'SDL_gfx',
'GLUT',
'EGL',
- 'GLFW',
'GLEW',
'IDBStore',
+ 'SDL',
+ 'SDL_gfx',
+ 'GLFW',
+ 'webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance',
+ 'webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance',
+ 'allocateUTF8',
+ 'allocateUTF8OnStack',
'Fetch',
'fetchDeleteCachedData',
'fetchLoadCachedData',
@@ -3525,8 +3587,6 @@ function callMain() {
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
exitJS(ret, /* implicit = */ true);
return ret;
@@ -3545,7 +3605,6 @@ function stackCheckInit() {
writeStackCookie();
}
-/** @type {function(Array=)} */
function run() {
if (runDependencies > 0) {
diff --git a/themes/dist/output.wasm b/themes/dist/output.wasm
index 1b24bbd..b6d9fdc 100755
--- a/themes/dist/output.wasm
+++ b/themes/dist/output.wasm
Binary files differ
diff --git a/themes/src/Renderer2d.cpp b/themes/src/Renderer2d.cpp
index c303e83..06f0838 100644
--- a/themes/src/Renderer2d.cpp
+++ b/themes/src/Renderer2d.cpp
@@ -6,7 +6,7 @@
// Note: In the 'transform' attribute, the transform.x is the scale,
// transform.y is the rotation, and transform.zw is the translation.
-const char* Vertex2DShader =
+const char* DEFAULT_VERTEX_SHADER =
"attribute vec2 position; \n"
"attribute vec4 color; \n"
"attribute mat4 vMatrix; \n"
@@ -19,16 +19,18 @@ const char* Vertex2DShader =
" VertexColor = color; \n"
"}";
-const char* renderer2dFragmentShader =
+const char* DEFAULT_FRAGMENT_SHADER =
"varying lowp vec4 VertexColor; \n"
"void main() { \n"
" gl_FragColor = VertexColor; \n"
"}";
-void Renderer2d::load(WebglContext* inContext) {
+void Renderer2d::load(WebglContext* inContext, const char* inVertexShader, const char* inFragmentShader) {
+ auto vertexShader = inVertexShader ? inVertexShader : DEFAULT_VERTEX_SHADER;
+ auto fragmentShader = inFragmentShader ? inFragmentShader : DEFAULT_FRAGMENT_SHADER;
context = inContext;
printf("Compiling Renderer2d shader...\n");
- shader = loadShader(Vertex2DShader, renderer2dFragmentShader);
+ shader = loadShader(vertexShader, fragmentShader);
useShader(shader);
attributes.position = getShaderAttribute(shader, "position");
diff --git a/themes/src/Renderer2d.h b/themes/src/Renderer2d.h
index 909f088..8a96503 100644
--- a/themes/src/Renderer2d.h
+++ b/themes/src/Renderer2d.h
@@ -7,6 +7,7 @@
struct WebglContext;
+/// Responsible for rendering Mesh2Ds
struct Renderer2d {
WebglContext* context = NULL;
Mat4x4 projection;
@@ -24,7 +25,9 @@ struct Renderer2d {
i32 model;
} uniforms;
- void load(WebglContext* context);
+ /// Load with the provided context and shader programs. If the shaders are NULL, the default
+ /// shader is used
+ void load(WebglContext* context, const char* vertexShader = NULL, const char* fragmentShader = NULL);
void render();
void unload();
};
diff --git a/themes/src/shaders/renderer2d.frag b/themes/src/_shaders/renderer2d.frag
index e69de29..e69de29 100644
--- a/themes/src/shaders/renderer2d.frag
+++ b/themes/src/_shaders/renderer2d.frag
diff --git a/themes/src/shaders/renderer2d.vert b/themes/src/_shaders/renderer2d.vert
index e69de29..e69de29 100644
--- a/themes/src/shaders/renderer2d.vert
+++ b/themes/src/_shaders/renderer2d.vert
diff --git a/themes/src/shaders/renderer3d.frag b/themes/src/_shaders/renderer3d.frag
index 2f50347..2f50347 100644
--- a/themes/src/shaders/renderer3d.frag
+++ b/themes/src/_shaders/renderer3d.frag
diff --git a/themes/src/shaders/renderer3d.vert b/themes/src/_shaders/renderer3d.vert
index 026285f..026285f 100644
--- a/themes/src/shaders/renderer3d.vert
+++ b/themes/src/_shaders/renderer3d.vert
diff --git a/themes/src/_shaders/sun.vert b/themes/src/_shaders/sun.vert
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/themes/src/_shaders/sun.vert
diff --git a/themes/src/main.cpp b/themes/src/main.cpp
index 4e1a646..297a498 100644
--- a/themes/src/main.cpp
+++ b/themes/src/main.cpp
@@ -74,8 +74,7 @@ void load(Theme theme) {
break;
}
case Theme::Summer:
- renderer2d.load(&context);
- summerTheme.load(&renderer2d);
+ summerTheme.load(&renderer2d, &context);
break;
default:
break;
@@ -177,4 +176,4 @@ EM_BOOL selectSummer(int eventType, const EmscriptenMouseEvent* mouseEvent, void
printf("Summer theme selected\n");
load(Theme::Summer);
return true;
-} \ No newline at end of file
+}
diff --git a/themes/src/shaders/renderer2d_frag.h b/themes/src/shaders/renderer2d_frag.h
new file mode 100644
index 0000000..6f5e472
--- /dev/null
+++ b/themes/src/shaders/renderer2d_frag.h
@@ -0,0 +1,4 @@
+#ifndef SHADER_RENDERER2D_FRAG
+#define SHADER_RENDERER2D_FRAG
+const char* shader_renderer2d_frag = " \n";
+#endif
diff --git a/themes/src/shaders/renderer2d_vert.h b/themes/src/shaders/renderer2d_vert.h
new file mode 100644
index 0000000..b32cf9f
--- /dev/null
+++ b/themes/src/shaders/renderer2d_vert.h
@@ -0,0 +1,4 @@
+#ifndef SHADER_RENDERER2D_VERT
+#define SHADER_RENDERER2D_VERT
+const char* shader_renderer2d_vert = " \n";
+#endif
diff --git a/themes/src/shaders/renderer3d_frag.h b/themes/src/shaders/renderer3d_frag.h
new file mode 100644
index 0000000..6b3a936
--- /dev/null
+++ b/themes/src/shaders/renderer3d_frag.h
@@ -0,0 +1,11 @@
+#ifndef SHADER_RENDERER3D_FRAG
+#define SHADER_RENDERER3D_FRAG
+const char* shader_renderer3d_frag = "varying lowp vec4 VertexColor; \n"
+"varying lowp vec4 VertexNormal; \n"
+" \n"
+"void main() { \n"
+" const lowp vec3 lightDirection = vec3(0.0, 1.0, 0.0); \n"
+" gl_FragColor = vec4(VertexColor.xyz * dot(VertexNormal.xyz, lightDirection), 1); \n"
+"} \n"
+" \n";
+#endif
diff --git a/themes/src/shaders/renderer3d_vert.h b/themes/src/shaders/renderer3d_vert.h
new file mode 100644
index 0000000..20e69f9
--- /dev/null
+++ b/themes/src/shaders/renderer3d_vert.h
@@ -0,0 +1,19 @@
+#ifndef SHADER_RENDERER3D_VERT
+#define SHADER_RENDERER3D_VERT
+const char* shader_renderer3d_vert = "attribute vec4 position; \n"
+"attribute vec4 color; \n"
+"attribute vec4 normal; \n"
+"uniform mat4 projection; \n"
+"uniform mat4 view; \n"
+"uniform mat4 model; \n"
+"varying lowp vec4 VertexColor; \n"
+"varying lowp vec4 VertexNormal; \n"
+" \n"
+"void main() { \n"
+" vec4 fragmentPosition = projection * view * model * position; \n"
+" gl_Position = fragmentPosition; \n"
+" VertexColor = color; \n"
+" VertexNormal = normal; \n"
+"} \n"
+" \n";
+#endif
diff --git a/themes/src/shaders/sun_vert.h b/themes/src/shaders/sun_vert.h
new file mode 100644
index 0000000..2f9bf69
--- /dev/null
+++ b/themes/src/shaders/sun_vert.h
@@ -0,0 +1,4 @@
+#ifndef SHADER_SUN_VERT
+#define SHADER_SUN_VERT
+const char* shader_sun_vert = " \n";
+#endif
diff --git a/themes/src/summer/SummerTheme.cpp b/themes/src/summer/SummerTheme.cpp
index 406cd22..81cc43b 100644
--- a/themes/src/summer/SummerTheme.cpp
+++ b/themes/src/summer/SummerTheme.cpp
@@ -4,7 +4,8 @@
#include "../mathlib.h"
#include <vector>
-void SummerTheme::load(Renderer2d* renderer) {
+void SummerTheme::load(Renderer2d* renderer, WebglContext* context) {
+ renderer->load(context);
renderer->clearColor = Vector4(0, 181, 286, 255.f).toNormalizedColor();
sun.sectors = 180;
sun.radius = renderer->context->width / 4.f;
diff --git a/themes/src/summer/SummerTheme.h b/themes/src/summer/SummerTheme.h
index 4a9f76b..dad4ac9 100644
--- a/themes/src/summer/SummerTheme.h
+++ b/themes/src/summer/SummerTheme.h
@@ -16,7 +16,7 @@ struct Sun {
struct SummerTheme {
Sun sun;
- void load(Renderer2d* renderer);
+ void load(Renderer2d*, WebglContext*);
void update(f32 dtSeconds);
void render(Renderer2d* renderer);
void unload();
diff --git a/themes/src/tools/shader.js b/themes/src/tools/shader.js
new file mode 100644
index 0000000..27c8682
--- /dev/null
+++ b/themes/src/tools/shader.js
@@ -0,0 +1,30 @@
+/*
+ Responsible for generating .h files from GLSL files.
+ */
+
+
+const path = require('path');
+const fs = require('fs');
+const directory = path.join(__dirname, "..", "_shaders");
+const out_directory = path.join(__dirname, "..", "shaders");
+
+const files = fs.readdirSync(directory);
+files.forEach(file => {
+ const filePath = path.join(directory, file);
+ const text = String(fs.readFileSync(filePath));
+ const splitText = text.split('\n');
+ const splitName = file.split('.');
+ const def = `SHADER_${splitName.join('_').toUpperCase()}`;
+ let result = `#ifndef ${def} \n`;
+ result += `#define ${def} \n`;
+ result += `const char* ${def.toLowerCase()} = `
+ splitText.forEach((line, index) => {
+ result += "\"" + line + " \\n\"";
+ if (index == splitText.length - 1)
+ result += ";\n";
+ else
+ result += "\n";
+ });
+ result += '#endif\n';
+ fs.writeFileSync(path.join(out_directory, splitName.join('_') + '.h'), result);
+});
diff --git a/themes/tools/bundle_shaders.py b/themes/tools/bundle_shaders.py
deleted file mode 100644
index 19cf5db..0000000
--- a/themes/tools/bundle_shaders.py
+++ /dev/null
@@ -1,4 +0,0 @@
-
-# Renderer 2D
-with open('../Renderer2d_Vertex.glsl') as vs:
- \ No newline at end of file