diff --git a/package-lock.json b/package-lock.json
index 98df7737ba..34260fd333 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -23,6 +23,7 @@
"file-saver": "^2.0.5",
"follow-redirects": "1.15.2",
"fs-extra": "11.1.1",
+ "node-forge": "1.3.1",
"octokit": "3.1.1",
"octokit-plugin-create-pull-request": "5.1.1",
"react": "^18.2.0",
@@ -32914,8 +32915,8 @@
},
"node_modules/node-forge": {
"version": "1.3.1",
- "dev": true,
- "license": "(BSD-3-Clause OR GPL-2.0)",
+ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
+ "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
"engines": {
"node": ">= 6.13.0"
}
diff --git a/package.json b/package.json
index 2420479f77..5a91afa438 100644
--- a/package.json
+++ b/package.json
@@ -61,6 +61,7 @@
"file-saver": "^2.0.5",
"follow-redirects": "1.15.2",
"fs-extra": "11.1.1",
+ "node-forge": "1.3.1",
"octokit": "3.1.1",
"octokit-plugin-create-pull-request": "5.1.1",
"react": "^18.2.0",
diff --git a/packages/php-wasm/compile/build.js b/packages/php-wasm/compile/build.js
index badafc90e4..8c778bbaa4 100644
--- a/packages/php-wasm/compile/build.js
+++ b/packages/php-wasm/compile/build.js
@@ -115,6 +115,7 @@ const platformDefaults = {
PHP_VERSION: '8.0.24',
WITH_LIBZIP: 'yes',
WITH_SQLITE: 'yes',
+ WITH_WS_NETWORKING_PROXY: 'yes',
},
['web-light']: {},
['web-kitchen-sink']: {
diff --git a/packages/php-wasm/compile/php/Dockerfile b/packages/php-wasm/compile/php/Dockerfile
index dcb2344506..98b7d57c1c 100644
--- a/packages/php-wasm/compile/php/Dockerfile
+++ b/packages/php-wasm/compile/php/Dockerfile
@@ -432,7 +432,17 @@ RUN echo -n ' -s ASYNCIFY=1 -s ASYNCIFY_IGNORE_INDIRECT=1 ' >> /root/.emcc-php-w
"dynCall_viiiii",\
"dynCall_viiiiiii",\
"dynCall_viiiiiiii",'; \
- export ASYNCIFY_ONLY=$'"__fwritex",\
+ export ASYNCIFY_ONLY=$'"zend_generator_iterator_move_forward",\
+"zend_fe_fetch_object_helper_SPEC",\
+"ZEND_FE_FETCH_R_SPEC_VAR_HANDLER",\
+"rc_dtor_func",\
+"zend_generator_resume",\
+"zend_call_method_if_exists",\
+"zend_generator_iterator_rewind",\
+"php_userstreamop_read",\
+"zend_fe_reset_iterator",\
+"ZEND_FE_RESET_R_SPEC_VAR_HANDLER",\
+"__fwritex",\
"read",\
"zif_sleep",\
"zif_stream_get_contents",\
@@ -532,6 +542,9 @@ RUN echo -n ' -s ASYNCIFY=1 -s ASYNCIFY_IGNORE_INDIRECT=1 ' >> /root/.emcc-php-w
"_php_stream_open_wrapper_ex",\
"_php_stream_read",\
"_php_stream_set_option",\
+"_php_stream_mmap_range",\
+"_php_stream_copy_to_stream_ex",\
+"zif_stream_copy_to_stream",\
"_php_stream_write",\
"_php_stream_xport_create",\
"do_cli",\
@@ -783,6 +796,7 @@ RUN set -euxo pipefail; \
"_wasm_set_phpini_path", \n\
"_wasm_set_phpini_entries", \n\
"_wasm_add_SERVER_entry", \n\
+"_wasm_add_ENV_entry", \n\
"_wasm_read", \n\
"_wasm_sapi_handle_request", \n\
"_wasm_set_content_length", \n\
@@ -797,11 +811,11 @@ RUN set -euxo pipefail; \
"_wasm_set_request_port", \n\
"_wasm_set_request_uri", \n\
"_wasm_set_skip_shebang" '"$(cat /root/.EXPORTED_FUNCTIONS)"']'; \
- export OPTIMIZATION_FLAGS="-O3"; \
+ export OPTIMIZATION_FLAGS="-O0 "; \
if [ "${WITH_SOURCEMAPS}" = "yes" ]; then \
export OPTIMIZATION_FLAGS="-O0"; \
fi; \
- emcc $OPTIMIZATION_FLAGS \
+ emcc $OPTIMIZATION_FLAGS -g2 \
--js-library /root/phpwasm-emscripten-library.js \
-I . \
-I ext \
diff --git a/packages/php-wasm/compile/php/php_wasm.c b/packages/php-wasm/compile/php/php_wasm.c
index ecd52d92e9..25ea7ecc15 100644
--- a/packages/php-wasm/compile/php/php_wasm.c
+++ b/packages/php-wasm/compile/php/php_wasm.c
@@ -131,7 +131,11 @@ EMSCRIPTEN_KEEPALIVE FILE *wasm_popen(const char *cmd, const char *mode)
NULL,
0,
descv,
- 3
+ 3,
+ "",
+ 0,
+ 0,
+ 0
);
// }}}
@@ -555,6 +559,7 @@ typedef struct
*php_code;
struct wasm_array_entry *server_array_entries;
+ struct wasm_array_entry *env_array_entries;
int content_length,
request_port,
@@ -588,6 +593,21 @@ void wasm_init_server_context();
static char *int_to_string(int i);
static int EMSCRIPTEN_KEEPALIVE run_php(char *code);
+static char *wasm_sapi_getenv(const char *name, size_t name_len)
+{
+ wasm_array_entry_t *current_entry = wasm_server_context->env_array_entries;
+ while (current_entry != NULL)
+ {
+ if (strncmp(current_entry->key, name, name_len) == 0)
+ {
+ return current_entry->value;
+ }
+ current_entry = current_entry->next;
+ }
+ return NULL;
+}
+
+
SAPI_API sapi_module_struct php_wasm_sapi_module = {
"wasm", /* name */
"PHP WASM SAPI", /* pretty name */
@@ -601,7 +621,7 @@ SAPI_API sapi_module_struct php_wasm_sapi_module = {
wasm_sapi_ub_write, /* unbuffered write */
wasm_sapi_flush, /* flush */
NULL, /* get uid */
- NULL, /* getenv */
+ wasm_sapi_getenv, /* getenv */
php_error, /* error handler */
@@ -661,6 +681,7 @@ void wasm_init_server_context()
wasm_server_context->execution_mode = MODE_EXECUTE_SCRIPT;
wasm_server_context->skip_shebang = 0;
wasm_server_context->server_array_entries = NULL;
+ wasm_server_context->env_array_entries = NULL;
}
void wasm_destroy_server_context()
@@ -712,6 +733,17 @@ void wasm_destroy_server_context()
free(current_entry);
current_entry = next_entry;
}
+
+ // Free wasm_server_context->env_array_entries
+ wasm_array_entry_t *current_env_entry = wasm_server_context->env_array_entries;
+ while (current_env_entry != NULL)
+ {
+ wasm_array_entry_t *next_entry = current_env_entry->next;
+ free(current_env_entry->key);
+ free(current_env_entry->value);
+ free(current_env_entry);
+ current_env_entry = next_entry;
+ }
}
/**
@@ -740,6 +772,23 @@ void wasm_add_SERVER_entry(char *key, char *value)
}
}
+/**
+ * Function: wasm_add_ENV_entry
+ * ----------------------------
+ * Exposes a new entry to the getenv() function.
+ *
+ * key: the key of the entry
+ * value: the value of the entry
+ */
+void wasm_add_ENV_entry(char *key, char *value)
+{
+ wasm_array_entry_t *entry = (wasm_array_entry_t *)malloc(sizeof(wasm_array_entry_t));
+ entry->key = strdup(key);
+ entry->value = strdup(value);
+ entry->next = wasm_server_context->env_array_entries;
+ wasm_server_context->env_array_entries = entry;
+}
+
/**
* Function: wasm_set_query_string
* ----------------------------
diff --git a/packages/php-wasm/compile/php/phpwasm-emscripten-library.js b/packages/php-wasm/compile/php/phpwasm-emscripten-library.js
index 1985201dd9..572ddde086 100644
--- a/packages/php-wasm/compile/php/phpwasm-emscripten-library.js
+++ b/packages/php-wasm/compile/php/phpwasm-emscripten-library.js
@@ -19,43 +19,43 @@ const LibraryExample = {
PHPWASM.EventEmitter = ENVIRONMENT_IS_NODE
? require('events').EventEmitter
: class EventEmitter {
- constructor() {
- this.listeners = {};
- }
- emit(eventName, data) {
- if (this.listeners[eventName]) {
- this.listeners[eventName].forEach(
- (callback) => {
- callback(data);
- }
- );
- }
+ constructor() {
+ this.listeners = {};
+ }
+ emit(eventName, data) {
+ if (this.listeners[eventName]) {
+ this.listeners[eventName].forEach(
+ (callback) => {
+ callback(data);
+ }
+ );
}
- once(eventName, callback) {
- const self = this;
- function removedCallback() {
- callback(...arguments);
- self.removeListener(eventName, removedCallback);
- }
- this.on(eventName, removedCallback);
+ }
+ once(eventName, callback) {
+ const self = this;
+ function removedCallback() {
+ callback(...arguments);
+ self.removeListener(eventName, removedCallback);
}
- removeAllListeners(eventName) {
- if (eventName) {
- delete this.listeners[eventName];
- } else {
- this.listeners = {};
- }
+ this.on(eventName, removedCallback);
+ }
+ removeAllListeners(eventName) {
+ if (eventName) {
+ delete this.listeners[eventName];
+ } else {
+ this.listeners = {};
}
- removeListener(eventName, callback) {
- if (this.listeners[eventName]) {
- const idx =
- this.listeners[eventName].indexOf(callback);
- if (idx !== -1) {
- this.listeners[eventName].splice(idx, 1);
- }
+ }
+ removeListener(eventName, callback) {
+ if (this.listeners[eventName]) {
+ const idx =
+ this.listeners[eventName].indexOf(callback);
+ if (idx !== -1) {
+ this.listeners[eventName].splice(idx, 1);
}
}
- };
+ }
+ };
PHPWASM.child_proc_by_fd = {};
PHPWASM.child_proc_by_pid = {};
PHPWASM.input_devices = {};
@@ -180,11 +180,11 @@ const LibraryExample = {
};
return [promise, cancel];
},
- noop: function () {},
+ noop: function () { },
- spawnProcess: function (command, args) {
+ spawnProcess: function (command, args, options) {
if (Module['spawnProcess']) {
- const spawnedPromise = Module['spawnProcess'](command, args);
+ const spawnedPromise = Module['spawnProcess'](command, args, options);
return Promise.resolve(spawnedPromise).then(function (spawned) {
if (!spawned || !spawned.on) {
throw new Error(
@@ -197,6 +197,7 @@ const LibraryExample = {
if (ENVIRONMENT_IS_NODE) {
return require('child_process').spawn(command, args, {
+ ...options,
shell: true,
stdio: ['pipe', 'pipe', 'pipe'],
timeout: 100,
@@ -204,8 +205,8 @@ const LibraryExample = {
}
const e = new Error(
'popen(), proc_open() etc. are unsupported in the browser. Call php.setSpawnHandler() ' +
- 'and provide a callback to handle spawning processes, or disable a popen(), proc_open() ' +
- 'and similar functions via php.ini.'
+ 'and provide a callback to handle spawning processes, or disable a popen(), proc_open() ' +
+ 'and similar functions via php.ini.'
);
e.code = 'SPAWN_UNSUPPORTED';
throw e;
@@ -255,7 +256,7 @@ const LibraryExample = {
const device = FS.createDevice(
'/dev',
filename,
- function () {},
+ function () { },
function (byte) {
try {
dataBuffer.push(byte);
@@ -300,7 +301,11 @@ const LibraryExample = {
argsPtr,
argsLength,
descriptorsPtr,
- descriptorsLength
+ descriptorsLength,
+ cwdPtr,
+ cwdLength,
+ envPtr,
+ envLength
) {
if (!command) {
return 1;
@@ -319,6 +324,24 @@ const LibraryExample = {
}
}
+ const cwdstr = cwdPtr ? UTF8ToString(cwdPtr) : null;
+ let envObject = null;
+
+ if (envLength) {
+ envObject = {};
+ for (var i = 0; i < envLength; i++) {
+ const envPointer = envPtr + i * 4;
+ const envEntry = UTF8ToString(HEAPU32[envPointer >> 2]);
+ const splitAt = envEntry.indexOf('=');
+ if (splitAt === -1) {
+ continue;
+ }
+ const key = envEntry.substring(0, splitAt);
+ const value = envEntry.substring(splitAt + 1);
+ envObject[key] = value;
+ }
+ }
+
var std = {};
// Extracts an array of available descriptors that should be dispatched to streams.
// On the C side, the descriptors are expressed as `**int` so we must go read
@@ -335,7 +358,14 @@ const LibraryExample = {
return Asyncify.handleSleep(async (wakeUp) => {
let cp;
try {
- cp = PHPWASM.spawnProcess(cmdstr, argsArray);
+ const options = {};
+ if (cwdstr !== null) {
+ options.cwd = cwdstr;
+ }
+ if (envObject !== null) {
+ options.env = envObject;
+ }
+ cp = PHPWASM.spawnProcess(cmdstr, argsArray, options);
if (cp instanceof Promise) {
cp = await cp;
}
@@ -396,6 +426,9 @@ const LibraryExample = {
);
stdoutAt += data.length;
});
+ cp.stdout.on('end', function (data) {
+ FS.close(stdoutStream);
+ });
}
// Pass data from child process's stderr to PHP's end of the stdout pipe.
@@ -415,6 +448,9 @@ const LibraryExample = {
);
stderrAt += data.length;
});
+ cp.stderr.on('end', function (data) {
+ FS.close(stdoutStream);
+ });
}
/**
@@ -493,16 +529,19 @@ const LibraryExample = {
});
},
- js_process_status: function (pid) {
+ js_process_status: function (pid, exitCodePtr) {
if (!PHPWASM.child_proc_by_pid[pid]) {
return -1;
}
if (PHPWASM.child_proc_by_pid[pid].exited) {
+ HEAPU32[exitCodePtr >> 2] =
+ PHPWASM.child_proc_by_pid[pid].exitCode;
return 1;
}
return 0;
},
+
js_waitpid: function (pid, exitCodePtr) {
if (!PHPWASM.child_proc_by_pid[pid]) {
return -1;
@@ -510,9 +549,9 @@ const LibraryExample = {
return Asyncify.handleSleep((wakeUp) => {
const poll = function () {
if (PHPWASM.child_proc_by_pid[pid]?.exited) {
- HEAPU8[exitCodePtr] =
+ HEAPU32[exitCodePtr >> 2] =
PHPWASM.child_proc_by_pid[pid].exitCode;
- wakeUp(0);
+ wakeUp(pid);
} else {
setTimeout(poll, 50);
}
@@ -722,74 +761,91 @@ const LibraryExample = {
* @see https://github.com/emscripten-core/emscripten/issues/13214
*/
js_fd_read: function (fd, iov, iovcnt, pnum) {
- var returnCode;
- var stream;
- try {
- stream = SYSCALLS.getStreamFromFD(fd);
- var num = doReadv(stream, iov, iovcnt);
- HEAPU32[pnum >> 2] = num;
- returnCode = 0;
- } catch (e) {
- if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
- returnCode = e.errno;
+ // Only run the read operation on a regular call,
+ // never when rewinding the stack.
+ if (Asyncify.state === Asyncify.State.Normal) {
+ var returnCode;
+ var stream;
+ let num = 0;
+ try {
+ stream = SYSCALLS.getStreamFromFD(fd);
+ const num = doReadv(stream, iov, iovcnt);
+ HEAPU32[pnum >> 2] = num;
+ return 0;
+ } catch (e) {
+ // Rethrow any unexpected non-filesystem errors.
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) {
+ throw e;
+ }
+ // Only return synchronously if this isn't an asynchronous pipe.
+ // Error code 6 indicates EWOULDBLOCK – this is our signal to wait.
+ // We also need to distinguish between a process pipe and a file pipe, otherwise
+ // reading from an empty file would block until the timeout.
+ if (e.errno !== 6 || !(stream?.fd in PHPWASM.child_proc_by_fd)) {
+ // On failure, yield 0 bytes read to indicate EOF.
+ HEAPU32[pnum >> 2] = 0;
+ return returnCode
+ }
+ }
}
- // If it's a blocking process pipe, wait for it to become readable.
- // We need to distinguish between a process pipe and a file pipe, otherwise
- // reading from an empty file would block until the timeout.
- if (
- returnCode === 6 /*EWOULDBLOCK*/ &&
- stream?.fd in PHPWASM.child_proc_by_fd
- ) {
- // You might wonder why we duplicate the code here instead of always using
- // Asyncify.handleSleep(). The reason is performance. Most of the time,
- // the read operation will work synchronously and won't require yielding
- // back to JS. In these cases we don't want to pay the Asyncify overhead,
- // save the stack, yield back to JS, restore the stack etc.
- return Asyncify.handleSleep(function (wakeUp) {
- var retries = 0;
- var interval = 50;
- var timeout = 5000;
- // We poll for data and give up after a timeout.
- // We can't simply rely on PHP timeout here because we don't want
- // to, say, block the entire PHPUnit test suite without any visible
- // feedback.
- var maxRetries = timeout / interval;
- function poll() {
- var returnCode;
- var stream;
- try {
- stream = SYSCALLS.getStreamFromFD(fd);
- var num = doReadv(stream, iov, iovcnt);
- HEAPU32[pnum >> 2] = num;
- returnCode = 0;
- } catch (e) {
- if (
- typeof FS == 'undefined' ||
- !(e.name === 'ErrnoError')
- ) {
- console.error(e);
- throw e;
- }
- returnCode = e.errno;
- }
-
+ // At this point we know we have to poll.
+ // You might wonder why we duplicate the code here instead of always using
+ // Asyncify.handleSleep(). The reason is performance. Most of the time,
+ // the read operation will work synchronously and won't require yielding
+ // back to JS. In these cases we don't want to pay the Asyncify overhead,
+ // save the stack, yield back to JS, restore the stack etc.
+ return Asyncify.handleSleep(function (wakeUp) {
+ var retries = 0;
+ var interval = 50;
+ var timeout = 5000;
+ // We poll for data and give up after a timeout.
+ // We can't simply rely on PHP timeout here because we don't want
+ // to, say, block the entire PHPUnit test suite without any visible
+ // feedback.
+ var maxRetries = timeout / interval;
+ function poll() {
+ var returnCode;
+ var stream;
+ let num;
+ try {
+ stream = SYSCALLS.getStreamFromFD(fd);
+ num = doReadv(stream, iov, iovcnt);
+ returnCode = 0;
+ } catch (e) {
if (
- returnCode !== 6 ||
- ++retries > maxRetries ||
- !(fd in PHPWASM.child_proc_by_fd) ||
- PHPWASM.child_proc_by_fd[fd]?.exited ||
- FS.isClosed(stream)
+ typeof FS == 'undefined' ||
+ !(e.name === 'ErrnoError')
) {
- wakeUp(returnCode);
- } else {
- setTimeout(poll, interval);
+ console.error(e);
+ throw e;
}
+ returnCode = e.errno;
}
- poll();
- });
- }
- return returnCode;
+
+ const success = returnCode === 0;
+ const failure = (
+ ++retries > maxRetries ||
+ !(fd in PHPWASM.child_proc_by_fd) ||
+ PHPWASM.child_proc_by_fd[fd]?.exited ||
+ FS.isClosed(stream)
+ );
+
+ if (success) {
+ HEAPU32[pnum >> 2] = num;
+ wakeUp(0);
+ } else if (failure) {
+ // On failure, yield 0 bytes read to indicate EOF.
+ HEAPU32[pnum >> 2] = 0;
+ // If the failure is due to a timeout, return 0 to indicate that we
+ // reached EOF. Otherwise, propagate the error code.
+ wakeUp(returnCode === 6 ? 0 : returnCode);
+ } else {
+ setTimeout(poll, interval);
+ }
+ }
+ poll();
+ });
},
/**
diff --git a/packages/php-wasm/compile/php/proc_open7.4.c b/packages/php-wasm/compile/php/proc_open7.4.c
index 3d9a515c9c..a1edb470ac 100644
--- a/packages/php-wasm/compile/php/proc_open7.4.c
+++ b/packages/php-wasm/compile/php/proc_open7.4.c
@@ -263,11 +263,13 @@ PHP_FUNCTION(proc_get_status)
add_assoc_long(return_value, "pid", (zend_long) proc->child);
errno = 0;
- int proc_status = js_process_status(proc->child);
+ int proc_status = js_process_status(proc->child, &exitcode);
if (proc_status == 1) {
running = 0;
+ stopped = 1;
} else if (proc_status == 0) {
running = 1;
+ stopped = 0;
} else if (proc_status == -1) {
php_error_docref(NULL, E_WARNING, "Failed to get process status");
}
@@ -391,7 +393,9 @@ PHP_FUNCTION(proc_open)
command = pestrdup(Z_STRVAL_P(command_zv), is_persistent);
}
+ int num_env = 0;
if (environment) {
+ num_env = zend_hash_num_elements(Z_ARRVAL_P(environment));
env = _php_array_to_envp(environment, is_persistent);
}
@@ -603,7 +607,11 @@ PHP_FUNCTION(proc_open)
argv,
num_argv,
descv,
- num_descv
+ num_descv,
+ cwd,
+ cwd_len,
+ env.envarray,
+ num_env
);
// }}}
diff --git a/packages/php-wasm/compile/php/proc_open7.4.h b/packages/php-wasm/compile/php/proc_open7.4.h
index e9e5908713..b1bfd1e7dc 100644
--- a/packages/php-wasm/compile/php/proc_open7.4.h
+++ b/packages/php-wasm/compile/php/proc_open7.4.h
@@ -37,9 +37,9 @@ struct php_process_handle {
php_process_env_t env;
};
-extern int js_waitpid(int pid, int *status);
-extern int js_process_status(int pid);
-extern int js_open_process(const char *command, char **args, int args_length, int **descv, int descv_length);
+extern int js_waitpid(int pid, int *exitcode);
+extern int js_process_status(int pid, int *exitcode);
+extern int js_open_process(const char *command, char **args, int args_length, int **descv, int descv_length, char *cwd, int cwd_length, char **env, int env_length);
extern char *js_create_input_device(int procopen_call_nb);
static int procopen_call_id = 0;
diff --git a/packages/php-wasm/node/bin/rebuild-while-asyncify-functions-missing.mjs b/packages/php-wasm/node/bin/rebuild-while-asyncify-functions-missing.mjs
index 6b38092ecc..6153c3516b 100644
--- a/packages/php-wasm/node/bin/rebuild-while-asyncify-functions-missing.mjs
+++ b/packages/php-wasm/node/bin/rebuild-while-asyncify-functions-missing.mjs
@@ -50,7 +50,8 @@ function getHash() {
return createHash('sha1')
.update(
fs.readFileSync(
- new URL('../../compile/Dockerfile', import.meta.url).pathname
+ new URL('../../compile/php/Dockerfile', import.meta.url)
+ .pathname
)
)
.digest('hex');
diff --git a/packages/php-wasm/node/public/8_2_10/php_8_2.wasm b/packages/php-wasm/node/public/8_2_10/php_8_2.wasm
index f9b95ab1c6..aa4985fd16 100755
Binary files a/packages/php-wasm/node/public/8_2_10/php_8_2.wasm and b/packages/php-wasm/node/public/8_2_10/php_8_2.wasm differ
diff --git a/packages/php-wasm/node/public/php_8_0.js b/packages/php-wasm/node/public/php_8_0.js
index 5c1927b393..56b72b585a 100644
--- a/packages/php-wasm/node/public/php_8_0.js
+++ b/packages/php-wasm/node/public/php_8_0.js
@@ -3123,6 +3123,7 @@ var SOCKFS = {
addr = null;
port = null;
}
+ console.log({ws})
if (ws) {
if (ws._socket) {
addr = ws._socket.remoteAddress;
diff --git a/packages/php-wasm/node/public/php_8_2.js b/packages/php-wasm/node/public/php_8_2.js
index c69f17e07b..206b95957e 100644
--- a/packages/php-wasm/node/public/php_8_2.js
+++ b/packages/php-wasm/node/public/php_8_2.js
@@ -1,6 +1,6 @@
const dependencyFilename = __dirname + '/8_2_10/php_8_2.wasm';
export { dependencyFilename };
-export const dependenciesTotalSize = 11250609;
+export const dependenciesTotalSize = 13217903;
export function init(RuntimeName, PHPLoader) {
/**
* Overrides Emscripten's default ExitStatus object which gets
@@ -38,133 +38,244 @@ export function init(RuntimeName, PHPLoader) {
}
// The rest of the code comes from the built php.js file and esm-suffix.js
-var Module = typeof PHPLoader != "undefined" ? PHPLoader : {};
-
+// include: shell.js
+// 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 PHPLoader != 'undefined' ? PHPLoader : {};
+
+// --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 = Object.assign({}, Module);
var arguments_ = [];
-
-var thisProgram = "./this.program";
-
+var thisProgram = './this.program';
var quit_ = (status, toThrow) => {
- throw toThrow;
+ throw toThrow;
};
-var ENVIRONMENT_IS_WEB=RuntimeName==="WEB";
+// 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=RuntimeName==="WEB";
var ENVIRONMENT_IS_WORKER=RuntimeName==="WORKER";
-
var ENVIRONMENT_IS_NODE=RuntimeName==="NODE";
+var ENVIRONMENT_IS_SHELL=RuntimeName==="SHELL";
-var scriptDirectory = "";
-
+// `/` 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;
+ if (Module['locateFile']) {
+ return Module['locateFile'](path, scriptDirectory);
+ }
+ return scriptDirectory + path;
}
-var read_, readAsync, readBinary;
+// Hooks that are implemented differently in different runtime environments.
+var read_,
+ readAsync,
+ readBinary,
+ setWindowTitle;
if (ENVIRONMENT_IS_NODE) {
- var fs = require("fs");
- var nodePath = require("path");
- if (ENVIRONMENT_IS_WORKER) {
- scriptDirectory = nodePath.dirname(scriptDirectory) + "/";
- } else {
- scriptDirectory = __dirname + "/";
- }
- read_ = (filename, binary) => {
+
+ // `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.
+ // TODO: Swap all `require()`'s with `import()`'s?
+ // These modules will usually be used on Node.js. Load them eagerly to avoid
+ // the complexity of lazy-loading.
+ var fs = require('fs');
+ var nodePath = require('path');
+
+ if (ENVIRONMENT_IS_WORKER) {
+ scriptDirectory = nodePath.dirname(scriptDirectory) + '/';
+ } else {
+ scriptDirectory = __dirname + '/';
+ }
+
+// include: node_shell_read.js
+read_ = (filename, binary) => {
+ // We need to re-wrap `file://` strings to URLs. Normalizing isn't
+ // necessary in that case, the path should already be absolute.
filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename);
- return fs.readFileSync(filename, binary ? undefined : "utf8");
- };
- readBinary = filename => {
+ return fs.readFileSync(filename, binary ? undefined : 'utf8');
+};
+
+readBinary = (filename) => {
var ret = read_(filename, true);
if (!ret.buffer) {
- ret = new Uint8Array(ret);
+ ret = new Uint8Array(ret);
}
return ret;
- };
- readAsync = (filename, onload, onerror, binary = true) => {
+};
+
+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, binary ? undefined : "utf8", ((err, data) => {
- if (err) onerror(err); else onload(binary ? data.buffer : data);
- }));
- };
- if (!Module["thisProgram"] && process.argv.length > 1) {
- thisProgram = process.argv[1].replace(/\\/g, "/");
- }
- arguments_ = process.argv.slice(2);
- if (typeof module != "undefined") {
- module["exports"] = Module;
- }
- quit_ = (status, toThrow) => {
- process.exitCode = status;
- throw toThrow;
- };
- Module["inspect"] = () => "[Emscripten Module object]";
-} else {}
+ fs.readFile(filename, binary ? undefined : 'utf8', (err, data) => {
+ if (err) onerror(err);
+ else onload(binary ? data.buffer : data);
+ });
+};
+// end include: node_shell_read.js
+ if (!Module['thisProgram'] && process.argv.length > 1) {
+ thisProgram = process.argv[1].replace(/\\/g, '/');
+ }
-var out = Module["print"] || console.log.bind(console);
+ arguments_ = process.argv.slice(2);
-var err = Module["printErr"] || console.error.bind(console);
+ if (typeof module != 'undefined') {
+ module['exports'] = Module;
+ }
-Object.assign(Module, moduleOverrides);
+ quit_ = (status, toThrow) => {
+ process.exitCode = status;
+ throw toThrow;
+ };
+ Module['inspect'] = () => '[Emscripten Module object]';
+
+} else
+
+// 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.
+{
+}
+
+var out = Module['print'] || console.log.bind(console);
+var err = Module['printErr'] || console.error.bind(console);
+
+// Merge back in the overrides
+Object.assign(Module, moduleOverrides);
+// 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;
-if (Module["arguments"]) arguments_ = Module["arguments"];
+// 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["thisProgram"]) thisProgram = Module["thisProgram"];
+if (Module['arguments']) arguments_ = Module['arguments'];
-if (Module["quit"]) quit_ = Module["quit"];
+if (Module['thisProgram']) thisProgram = Module['thisProgram'];
-var wasmBinary;
+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
-if (Module["wasmBinary"]) wasmBinary = Module["wasmBinary"];
+// end include: shell.js
+// include: preamble.js
+// === Preamble library stuff ===
-var noExitRuntime = Module["noExitRuntime"] || false;
+// 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
-if (typeof WebAssembly != "object") {
- abort("no native wasm support detected");
+var wasmBinary;
+if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
+var noExitRuntime = Module['noExitRuntime'] || false;
+
+if (typeof WebAssembly != 'object') {
+ abort('no native wasm support detected');
}
+// 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(text);
- }
-}
-
-var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64;
+ if (!condition) {
+ // This build was created without ASSERTIONS defined. `assert()` should not
+ // ever be called in this configuration but in case there are callers in
+ // the wild leave this simple abort() implemenation here for now.
+ abort(text);
+ }
+}
+
+// Memory management
+
+var HEAP,
+/** @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 updateMemoryViews() {
- var b = wasmMemory.buffer;
- Module["HEAP8"] = HEAP8 = new Int8Array(b);
- Module["HEAP16"] = HEAP16 = new Int16Array(b);
- Module["HEAP32"] = HEAP32 = new Int32Array(b);
- Module["HEAPU8"] = HEAPU8 = new Uint8Array(b);
- Module["HEAPU16"] = HEAPU16 = new Uint16Array(b);
- Module["HEAPU32"] = HEAPU32 = new Uint32Array(b);
- Module["HEAPF32"] = HEAPF32 = new Float32Array(b);
- Module["HEAPF64"] = HEAPF64 = new Float64Array(b);
-}
-
+ var b = wasmMemory.buffer;
+ Module['HEAP8'] = HEAP8 = new Int8Array(b);
+ Module['HEAP16'] = HEAP16 = new Int16Array(b);
+ Module['HEAP32'] = HEAP32 = new Int32Array(b);
+ Module['HEAPU8'] = HEAPU8 = new Uint8Array(b);
+ Module['HEAPU16'] = HEAPU16 = new Uint16Array(b);
+ Module['HEAPU32'] = HEAPU32 = new Uint32Array(b);
+ Module['HEAPF32'] = HEAPF32 = new Float32Array(b);
+ Module['HEAPF64'] = HEAPF64 = new Float64Array(b);
+}
+
+// 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;
-
-var __ATPRERUN__ = [];
-
-var __ATINIT__ = [];
-
-var __ATEXIT__ = [];
-
-var __ATPOSTRUN__ = [];
+// 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 __ATEXIT__ = []; // functions called during shutdown
+var __ATPOSTRUN__ = []; // functions called after the main() is called
var runtimeInitialized = false;
@@ -173,7362 +284,9119 @@ var runtimeExited = false;
var runtimeKeepaliveCounter = 0;
function keepRuntimeAlive() {
- return noExitRuntime || runtimeKeepaliveCounter > 0;
+ return noExitRuntime || runtimeKeepaliveCounter > 0;
}
function preRun() {
- if (Module["preRun"]) {
- if (typeof Module["preRun"] == "function") Module["preRun"] = [ Module["preRun"] ];
- while (Module["preRun"].length) {
- addOnPreRun(Module["preRun"].shift());
+ if (Module['preRun']) {
+ if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']];
+ while (Module['preRun'].length) {
+ addOnPreRun(Module['preRun'].shift());
+ }
}
- }
- callRuntimeCallbacks(__ATPRERUN__);
+ callRuntimeCallbacks(__ATPRERUN__);
}
function initRuntime() {
- runtimeInitialized = true;
- if (!Module["noFSInit"] && !FS.init.initialized) FS.init();
- FS.ignorePermissions = false;
- TTY.init();
- SOCKFS.root = FS.mount(SOCKFS, {}, null);
- PIPEFS.root = FS.mount(PIPEFS, {}, null);
- callRuntimeCallbacks(__ATINIT__);
+ runtimeInitialized = true;
+
+
+if (!Module["noFSInit"] && !FS.init.initialized)
+ FS.init();
+FS.ignorePermissions = false;
+
+TTY.init();
+SOCKFS.root = FS.mount(SOCKFS, {}, null);
+PIPEFS.root = FS.mount(PIPEFS, {}, null);
+ callRuntimeCallbacks(__ATINIT__);
}
function exitRuntime() {
- ___funcs_on_exit();
- callRuntimeCallbacks(__ATEXIT__);
- FS.quit();
- TTY.shutdown();
- runtimeExited = true;
+ ___funcs_on_exit(); // Native atexit() functions
+ callRuntimeCallbacks(__ATEXIT__);
+ FS.quit();
+TTY.shutdown();
+ runtimeExited = true;
}
function postRun() {
- if (Module["postRun"]) {
- if (typeof Module["postRun"] == "function") Module["postRun"] = [ Module["postRun"] ];
- while (Module["postRun"].length) {
- addOnPostRun(Module["postRun"].shift());
+
+ if (Module['postRun']) {
+ if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']];
+ while (Module['postRun'].length) {
+ addOnPostRun(Module['postRun'].shift());
+ }
}
- }
- callRuntimeCallbacks(__ATPOSTRUN__);
+
+ callRuntimeCallbacks(__ATPOSTRUN__);
}
function addOnPreRun(cb) {
- __ATPRERUN__.unshift(cb);
+ __ATPRERUN__.unshift(cb);
}
function addOnInit(cb) {
- __ATINIT__.unshift(cb);
+ __ATINIT__.unshift(cb);
+}
+
+function addOnExit(cb) {
+ __ATEXIT__.unshift(cb);
}
function addOnPostRun(cb) {
- __ATPOSTRUN__.unshift(cb);
+ __ATPOSTRUN__.unshift(cb);
}
-var runDependencies = 0;
+// include: runtime_math.js
+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul
-var runDependencyWatcher = null;
+// 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
-var dependenciesFulfilled = null;
+// 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;
+ return id;
}
function addRunDependency(id) {
- runDependencies++;
- if (Module["monitorRunDependencies"]) {
- Module["monitorRunDependencies"](runDependencies);
- }
+ 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();
- }
- }
+ 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
+ }
+ }
}
+/** @param {string|number=} what */
function abort(what) {
- if (Module["onAbort"]) {
- Module["onAbort"](what);
- }
- what = "Aborted(" + what + ")";
- err(what);
- ABORT = true;
- EXITSTATUS = 1;
- what += ". Build with -sASSERTIONS for more info.";
- var e = new WebAssembly.RuntimeError(what);
- throw e;
+ if (Module['onAbort']) {
+ Module['onAbort'](what);
+ }
+
+ what = 'Aborted(' + what + ')';
+ // TODO(sbc): Should we remove printing and leave it up to whoever
+ // catches the exception?
+ err(what);
+
+ ABORT = true;
+ EXITSTATUS = 1;
+
+ what += '. Build with -sASSERTIONS 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.
+ // FIXME This approach does not work in Wasm EH because it currently does not assume
+ // all RuntimeErrors are from traps; it decides whether a RuntimeError is from
+ // a trap or not based on a hidden field within the object. So at the moment
+ // we don't have a way of throwing a wasm trap from JS. TODO Make a JS API that
+ // allows this in the wasm spec.
+
+ // Suppress closure compiler warning here. Closure compiler's builtin extern
+ // defintion for WebAssembly.RuntimeError claims it takes no arguments even
+ // though it can.
+ // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure gets fixed.
+ /** @suppress {checkTypes} */
+ 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;
}
-var dataURIPrefix = "data:application/octet-stream;base64,";
+// include: memoryprofiler.js
+// end include: memoryprofiler.js
+// include: URIUtils.js
+// 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 filename.startsWith(dataURIPrefix);
+ // Prefix of data URIs emitted by SINGLE_FILE and related options.
+ return filename.startsWith(dataURIPrefix);
}
+// Indicates whether filename is delivered via file protocol (as opposed to http/https)
function isFileURI(filename) {
- return filename.startsWith("file://");
+ return filename.startsWith('file://');
}
-
+// end include: URIUtils.js
+// include: runtime_exceptions.js
+// end include: runtime_exceptions.js
var wasmBinaryFile;
-
-wasmBinaryFile = dependencyFilename;
-
-if (!isDataURI(wasmBinaryFile)) {
- wasmBinaryFile = locateFile(wasmBinaryFile);
-}
+ wasmBinaryFile = dependencyFilename;
+ if (!isDataURI(wasmBinaryFile)) {
+ wasmBinaryFile = locateFile(wasmBinaryFile);
+ }
function getBinarySync(file) {
- if (file == wasmBinaryFile && wasmBinary) {
- return new Uint8Array(wasmBinary);
- }
- if (readBinary) {
- return readBinary(file);
- }
- throw "both async and sync fetching of the wasm failed";
+ if (file == wasmBinaryFile && wasmBinary) {
+ return new Uint8Array(wasmBinary);
+ }
+ if (readBinary) {
+ return readBinary(file);
+ }
+ throw "both async and sync fetching of the wasm failed";
}
function getBinaryPromise(binaryFile) {
- if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) {
- if (typeof fetch == "function") {
- return fetch(binaryFile, {
- credentials: "same-origin"
- }).then((response => {
- if (!response["ok"]) {
- throw "failed to load wasm binary file at '" + 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'
+ ) {
+ return fetch(binaryFile, { credentials: 'same-origin' }).then((response) => {
+ if (!response['ok']) {
+ throw "failed to load wasm binary file at '" + binaryFile + "'";
+ }
+ return response['arrayBuffer']();
+ }).catch(() => getBinarySync(binaryFile));
}
- return response["arrayBuffer"]();
- })).catch((() => getBinarySync(binaryFile)));
}
- }
- return Promise.resolve().then((() => getBinarySync(binaryFile)));
+
+ // Otherwise, getBinarySync should be able to get it synchronously
+ return Promise.resolve().then(() => getBinarySync(binaryFile));
}
function instantiateArrayBuffer(binaryFile, imports, receiver) {
- return getBinaryPromise(binaryFile).then((binary => WebAssembly.instantiate(binary, imports))).then((instance => instance)).then(receiver, (reason => {
- err("failed to asynchronously prepare wasm: " + reason);
- abort(reason);
- }));
+ return getBinaryPromise(binaryFile).then((binary) => {
+ return WebAssembly.instantiate(binary, imports);
+ }).then((instance) => {
+ return instance;
+ }).then(receiver, (reason) => {
+ err('failed to asynchronously prepare wasm: ' + reason);
+
+ abort(reason);
+ });
}
function instantiateAsync(binary, binaryFile, imports, callback) {
- if (!binary && typeof WebAssembly.instantiateStreaming == "function" && !isDataURI(binaryFile) && !ENVIRONMENT_IS_NODE && typeof fetch == "function") {
- return fetch(binaryFile, {
- credentials: "same-origin"
- }).then((response => {
- var result = WebAssembly.instantiateStreaming(response, imports);
- return result.then(callback, (function(reason) {
- err("wasm streaming compile failed: " + reason);
- err("falling back to ArrayBuffer instantiation");
- return instantiateArrayBuffer(binaryFile, imports, callback);
- }));
- }));
- }
- return instantiateArrayBuffer(binaryFile, imports, callback);
+ if (!binary &&
+ typeof WebAssembly.instantiateStreaming == 'function' &&
+ !isDataURI(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 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);
+ });
+ });
+ }
+ return instantiateArrayBuffer(binaryFile, imports, callback);
}
+// Create the wasm instance.
+// Receives the wasm imports, returns the exports.
function createWasm() {
- var info = {
- "a": wasmImports
- };
- function receiveInstance(instance, module) {
- var exports = instance.exports;
- exports = Asyncify.instrumentWasmExports(exports);
- Module["asm"] = exports;
- wasmMemory = Module["asm"]["db"];
- updateMemoryViews();
- wasmTable = Module["asm"]["hb"];
- addOnInit(Module["asm"]["eb"]);
- removeRunDependency("wasm-instantiate");
- return exports;
- }
- addRunDependency("wasm-instantiate");
- function receiveInstantiationResult(result) {
- receiveInstance(result["instance"]);
- }
- if (Module["instantiateWasm"]) {
- try {
- return Module["instantiateWasm"](info, receiveInstance);
- } catch (e) {
- err("Module.instantiateWasm callback failed with error: " + e);
- return false;
- }
- }
- instantiateAsync(wasmBinary, wasmBinaryFile, info, receiveInstantiationResult);
- return {};
-}
-
-var tempDouble;
-
-var tempI64;
-
-function ExitStatus(status) {
- this.name = "ExitStatus";
- this.message = `Program terminated with exit(${status})`;
- this.status = status;
-}
+ // prepare imports
+ var info = {
+ 'env': wasmImports,
+ 'wasi_snapshot_preview1': wasmImports,
+ };
+ // 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;
-var callRuntimeCallbacks = callbacks => {
- while (callbacks.length > 0) {
- callbacks.shift()(Module);
- }
-};
+ exports = Asyncify.instrumentWasmExports(exports);
-var UTF8Decoder = typeof TextDecoder != "undefined" ? new TextDecoder("utf8") : undefined;
-
-var UTF8ArrayToString = (heapOrArray, idx, maxBytesToRead) => {
- var endIdx = idx + maxBytesToRead;
- var endPtr = idx;
- while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr;
- if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) {
- return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr));
- }
- var str = "";
- while (idx < endPtr) {
- var u0 = heapOrArray[idx++];
- if (!(u0 & 128)) {
- str += String.fromCharCode(u0);
- continue;
- }
- var u1 = heapOrArray[idx++] & 63;
- if ((u0 & 224) == 192) {
- str += String.fromCharCode((u0 & 31) << 6 | u1);
- continue;
- }
- var u2 = heapOrArray[idx++] & 63;
- if ((u0 & 240) == 224) {
- u0 = (u0 & 15) << 12 | u1 << 6 | u2;
- } else {
- u0 = (u0 & 7) << 18 | u1 << 12 | u2 << 6 | heapOrArray[idx++] & 63;
- }
- if (u0 < 65536) {
- str += String.fromCharCode(u0);
- } else {
- var ch = u0 - 65536;
- str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023);
- }
- }
- return str;
-};
+ Module['asm'] = exports;
-var UTF8ToString = (ptr, maxBytesToRead) => ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : "";
+ wasmMemory = Module['asm']['memory'];
+ updateMemoryViews();
-Module["UTF8ToString"] = UTF8ToString;
+ wasmTable = Module['asm']['__indirect_function_table'];
-var ___assert_fail = (condition, filename, line, func) => {
- abort(`Assertion failed: ${UTF8ToString(condition)}, at: ` + [ filename ? UTF8ToString(filename) : "unknown filename", line, func ? UTF8ToString(func) : "unknown function" ]);
-};
+ addOnInit(Module['asm']['__wasm_call_ctors']);
-var ___call_sighandler = (fp, sig) => (a1 => dynCall_vi.apply(null, [ fp, a1 ]))(sig);
-
-var PATH = {
- isAbs: path => path.charAt(0) === "/",
- splitPath: filename => {
- var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
- return splitPathRe.exec(filename).slice(1);
- },
- normalizeArray: (parts, allowAboveRoot) => {
- 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--;
- }
+ removeRunDependency('wasm-instantiate');
+ return exports;
}
- if (allowAboveRoot) {
- for (;up; up--) {
- parts.unshift("..");
- }
+ // wait for the pthread pool (if any)
+ addRunDependency('wasm-instantiate');
+
+ // Prefer streaming instantiation if available.
+ function receiveInstantiationResult(result) {
+ // 'result' is a ResultObject 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 PTHREADS-enabled path.
+ receiveInstance(result['instance']);
}
- return parts;
- },
- normalize: path => {
- var isAbsolute = PATH.isAbs(path), trailingSlash = path.substr(-1) === "/";
- path = PATH.normalizeArray(path.split("/").filter((p => !!p)), !isAbsolute).join("/");
- if (!path && !isAbsolute) {
- path = ".";
- }
- if (path && trailingSlash) {
- path += "/";
- }
- return (isAbsolute ? "/" : "") + path;
- },
- dirname: path => {
- var result = PATH.splitPath(path), root = result[0], dir = result[1];
- if (!root && !dir) {
- return ".";
- }
- if (dir) {
- dir = dir.substr(0, dir.length - 1);
- }
- return root + dir;
- },
- basename: path => {
- if (path === "/") return "/";
- path = PATH.normalize(path);
- path = path.replace(/\/$/, "");
- var lastSlash = path.lastIndexOf("/");
- if (lastSlash === -1) return path;
- return path.substr(lastSlash + 1);
- },
- join: function() {
- var paths = Array.prototype.slice.call(arguments);
- return PATH.normalize(paths.join("/"));
- },
- join2: (l, r) => PATH.normalize(l + "/" + r)
-};
-var initRandomFill = () => {
- if (typeof crypto == "object" && typeof crypto["getRandomValues"] == "function") {
- return view => crypto.getRandomValues(view);
- } else if (ENVIRONMENT_IS_NODE) {
- try {
- var crypto_module = require("crypto");
- var randomFillSync = crypto_module["randomFillSync"];
- if (randomFillSync) {
- return view => crypto_module["randomFillSync"](view);
- }
- var randomBytes = crypto_module["randomBytes"];
- return view => (view.set(randomBytes(view.byteLength)), view);
- } catch (e) {}
- }
- abort("initRandomDevice");
-};
+ // 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.
+ if (Module['instantiateWasm']) {
-var randomFill = view => (randomFill = initRandomFill())(view);
-
-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();
- if (typeof path != "string") {
- throw new TypeError("Arguments to path.resolve must be strings");
- } else if (!path) {
- return "";
- }
- resolvedPath = path + "/" + resolvedPath;
- resolvedAbsolute = PATH.isAbs(path);
- }
- resolvedPath = PATH.normalizeArray(resolvedPath.split("/").filter((p => !!p)), !resolvedAbsolute).join("/");
- return (resolvedAbsolute ? "/" : "") + resolvedPath || ".";
- },
- relative: (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("..");
+ try {
+ return Module['instantiateWasm'](info, receiveInstance);
+ } catch(e) {
+ err('Module.instantiateWasm callback failed with error: ' + e);
+ return false;
+ }
}
- outputParts = outputParts.concat(toParts.slice(samePartsLength));
- return outputParts.join("/");
- }
-};
-var FS_stdin_getChar_buffer = [];
-
-var lengthBytesUTF8 = str => {
- var len = 0;
- for (var i = 0; i < str.length; ++i) {
- var c = str.charCodeAt(i);
- if (c <= 127) {
- len++;
- } else if (c <= 2047) {
- len += 2;
- } else if (c >= 55296 && c <= 57343) {
- len += 4;
- ++i;
- } else {
- len += 3;
- }
- }
- return len;
-};
+ instantiateAsync(wasmBinary, wasmBinaryFile, info, receiveInstantiationResult);
+ return {}; // no exports yet; we'll fill them in later
+}
-Module["lengthBytesUTF8"] = lengthBytesUTF8;
-
-var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
- if (!(maxBytesToWrite > 0)) return 0;
- var startIdx = outIdx;
- var endIdx = outIdx + maxBytesToWrite - 1;
- for (var i = 0; i < str.length; ++i) {
- var u = str.charCodeAt(i);
- if (u >= 55296 && u <= 57343) {
- var u1 = str.charCodeAt(++i);
- u = 65536 + ((u & 1023) << 10) | u1 & 1023;
- }
- if (u <= 127) {
- if (outIdx >= endIdx) break;
- heap[outIdx++] = u;
- } else if (u <= 2047) {
- if (outIdx + 1 >= endIdx) break;
- heap[outIdx++] = 192 | u >> 6;
- heap[outIdx++] = 128 | u & 63;
- } else if (u <= 65535) {
- if (outIdx + 2 >= endIdx) break;
- heap[outIdx++] = 224 | u >> 12;
- heap[outIdx++] = 128 | u >> 6 & 63;
- heap[outIdx++] = 128 | u & 63;
- } else {
- if (outIdx + 3 >= endIdx) break;
- heap[outIdx++] = 240 | u >> 18;
- heap[outIdx++] = 128 | u >> 12 & 63;
- heap[outIdx++] = 128 | u >> 6 & 63;
- heap[outIdx++] = 128 | u & 63;
- }
- }
- heap[outIdx] = 0;
- return outIdx - startIdx;
-};
+// Globals used by JS i64 conversions (see makeSetValue)
+var tempDouble;
+var tempI64;
-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;
-}
+// include: runtime_debug.js
+// end include: runtime_debug.js
+// === Body ===
-var FS_stdin_getChar = () => {
- if (!FS_stdin_getChar_buffer.length) {
- var result = null;
- if (ENVIRONMENT_IS_NODE) {
- var BUFSIZE = 256;
- var buf = Buffer.alloc(BUFSIZE);
- var bytesRead = 0;
- var fd = process.stdin.fd;
- try {
- bytesRead = fs.readSync(fd, buf, 0, BUFSIZE, -1);
- } catch (e) {
- if (e.toString().includes("EOF")) bytesRead = 0; else throw e;
- }
- if (bytesRead > 0) {
- result = buf.slice(0, bytesRead).toString("utf-8");
- } else {
- result = null;
- }
- } else if (typeof window != "undefined" && typeof window.prompt == "function") {
- result = window.prompt("Input: ");
- if (result !== null) {
- result += "\n";
- }
- } else if (typeof readline == "function") {
- result = readline();
- if (result !== null) {
- result += "\n";
- }
- }
- if (!result) {
- return null;
- }
- FS_stdin_getChar_buffer = intArrayFromString(result, true);
- }
- return FS_stdin_getChar_buffer.shift();
-};
+// end include: preamble.js
-var TTY = {
- ttys: [],
- init: function() {},
- shutdown: function() {},
- 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) {
- stream.tty.ops.fsync(stream.tty);
- },
- fsync: function(stream) {
- stream.tty.ops.fsync(stream.tty);
- },
- read: function(stream, buffer, offset, length, pos) {
- 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);
+ /** @constructor */
+ function ExitStatus(status) {
+ this.name = 'ExitStatus';
+ this.message = `Program terminated with exit(${status})`;
+ this.status = status;
}
- if (result === undefined && bytesRead === 0) {
- throw new FS.ErrnoError(6);
+
+ var callRuntimeCallbacks = (callbacks) => {
+ while (callbacks.length > 0) {
+ // Pass the module as the first argument.
+ callbacks.shift()(Module);
+ }
+ };
+
+
+ /**
+ * @param {number} ptr
+ * @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': 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}`);
}
- 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]);
+ }
+
+
+ /**
+ * @param {number} ptr
+ * @param {number} value
+ * @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': 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}`);
}
- } catch (e) {
- throw new FS.ErrnoError(29);
- }
- if (length) {
- stream.node.timestamp = Date.now();
- }
- return i;
}
- },
- default_tty_ops: {
- get_char: function(tty) {
- return FS_stdin_getChar();
- },
- 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);
- }
- },
- fsync: function(tty) {
- if (tty.output && tty.output.length > 0) {
- out(UTF8ArrayToString(tty.output, 0));
- tty.output = [];
- }
- },
- ioctl_tcgets: function(tty) {
- return {
- c_iflag: 25856,
- c_oflag: 5,
- c_cflag: 191,
- c_lflag: 35387,
- c_cc: [ 3, 28, 127, 21, 4, 0, 1, 0, 17, 19, 26, 0, 18, 15, 23, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- };
+
+ 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}
+ */
+ var 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 {
+ 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}
+ */
+ var UTF8ToString = (ptr, maxBytesToRead) => {
+ return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : '';
+ };
+ Module['UTF8ToString'] = UTF8ToString;
+ var ___assert_fail = (condition, filename, line, func) => {
+ abort(`Assertion failed: ${UTF8ToString(condition)}, at: ` + [filename ? UTF8ToString(filename) : 'unknown filename', line, func ? UTF8ToString(func) : 'unknown function']);
+ };
+
+ var ___call_sighandler = (fp, sig) => ((a1) => dynCall_vi.apply(null, [fp, a1]))(sig);
+
+ var PATH = {
+ isAbs:(path) => path.charAt(0) === '/',
+ splitPath:(filename) => {
+ var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
+ return splitPathRe.exec(filename).slice(1);
+ },
+ normalizeArray:(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:(path) => {
+ var isAbsolute = PATH.isAbs(path),
+ trailingSlash = path.substr(-1) === '/';
+ // Normalize the path
+ path = PATH.normalizeArray(path.split('/').filter((p) => !!p), !isAbsolute).join('/');
+ if (!path && !isAbsolute) {
+ path = '.';
+ }
+ if (path && trailingSlash) {
+ path += '/';
+ }
+ return (isAbsolute ? '/' : '') + path;
+ },
+ dirname:(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:(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);
+ },
+ join:function() {
+ var paths = Array.prototype.slice.call(arguments);
+ return PATH.normalize(paths.join('/'));
+ },
+ join2:(l, r) => {
+ return PATH.normalize(l + '/' + r);
+ },
+ };
+
+ var initRandomFill = () => {
+ if (typeof crypto == 'object' && typeof crypto['getRandomValues'] == 'function') {
+ // for modern web browsers
+ return (view) => crypto.getRandomValues(view);
+ } else
+ if (ENVIRONMENT_IS_NODE) {
+ // for nodejs with or without crypto support included
+ try {
+ var crypto_module = require('crypto');
+ var randomFillSync = crypto_module['randomFillSync'];
+ if (randomFillSync) {
+ // nodejs with LTS crypto support
+ return (view) => crypto_module['randomFillSync'](view);
+ }
+ // very old nodejs with the original crypto API
+ var randomBytes = crypto_module['randomBytes'];
+ return (view) => (
+ view.set(randomBytes(view.byteLength)),
+ // Return the original view to match modern native implementations.
+ view
+ );
+ } catch (e) {
+ // nodejs doesn't have crypto support
+ }
+ }
+ // we couldn't find a proper implementation, as Math.random() is not suitable for /dev/random, see emscripten-core/emscripten/pull/7096
+ abort("initRandomDevice");
+ };
+ var randomFill = (view) => {
+ // Lazily init on the first invocation.
+ return (randomFill = initRandomFill())(view);
+ };
+
+
+
+ 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.isAbs(path);
+ }
+ // 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((p) => !!p), !resolvedAbsolute).join('/');
+ return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
+ },
+ relative:(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 FS_stdin_getChar_buffer = [];
+
+ var 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;
+ };
+ Module['lengthBytesUTF8'] = lengthBytesUTF8;
+
+ var 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;
+ 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;
+ };
+ /** @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;
+ }
+ var FS_stdin_getChar = () => {
+ if (!FS_stdin_getChar_buffer.length) {
+ var result = null;
+ if (ENVIRONMENT_IS_NODE) {
+ // we will read data by chunks of BUFSIZE
+ var BUFSIZE = 256;
+ var buf = Buffer.alloc(BUFSIZE);
+ var bytesRead = 0;
+
+ // For some reason we must suppress a closure warning here, even though
+ // fd definitely exists on process.stdin, and is even the proper way to
+ // get the fd of stdin,
+ // https://github.com/nodejs/help/issues/2136#issuecomment-523649904
+ // This started to happen after moving this logic out of library_tty.js,
+ // so it is related to the surrounding code in some unclear manner.
+ /** @suppress {missingProperties} */
+ var fd = process.stdin.fd;
+
+ try {
+ bytesRead = fs.readSync(fd, buf, 0, BUFSIZE, -1);
+ } catch(e) {
+ // Cross-platform differences: on Windows, reading EOF throws an exception, but on other OSes,
+ // reading EOF returns 0. Uniformize behavior by treating the EOF exception to return 0.
+ if (e.toString().includes('EOF')) bytesRead = 0;
+ else throw e;
+ }
+
+ if (bytesRead > 0) {
+ result = buf.slice(0, bytesRead).toString('utf-8');
+ } else {
+ result = null;
+ }
+ } else
+ 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;
+ }
+ FS_stdin_getChar_buffer = intArrayFromString(result, true);
+ }
+ return FS_stdin_getChar_buffer.shift();
+ };
+ 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.fsync(stream.tty);
+ },
+ fsync:function(stream) {
+ stream.tty.ops.fsync(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;
+ },
},
- ioctl_tcsets: function(tty, optional_actions, data) {
- return 0;
+ default_tty_ops:{
+ get_char:function(tty) {
+ return FS_stdin_getChar();
+ },
+ 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.
+ }
+ },
+ fsync:function(tty) {
+ if (tty.output && tty.output.length > 0) {
+ out(UTF8ArrayToString(tty.output, 0));
+ tty.output = [];
+ }
+ },
+ ioctl_tcgets:function(tty) {
+ // typical setting
+ return {
+ c_iflag: 25856,
+ c_oflag: 5,
+ c_cflag: 191,
+ c_lflag: 35387,
+ c_cc: [
+ 0x03, 0x1c, 0x7f, 0x15, 0x04, 0x00, 0x01, 0x00, 0x11, 0x13, 0x1a, 0x00,
+ 0x12, 0x0f, 0x17, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ ]
+ };
+ },
+ ioctl_tcsets:function(tty, optional_actions, data) {
+ // currently just ignore
+ return 0;
+ },
+ ioctl_tiocgwinsz:function(tty) {
+ return [24, 80];
+ },
},
- ioctl_tiocgwinsz: function(tty) {
- return [ 24, 80 ];
- }
- },
- 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);
- }
+ 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);
+ }
+ },
+ fsync:function(tty) {
+ if (tty.output && tty.output.length > 0) {
+ err(UTF8ArrayToString(tty.output, 0));
+ tty.output = [];
+ }
+ },
},
- fsync: function(tty) {
- if (tty.output && tty.output.length > 0) {
- err(UTF8ArrayToString(tty.output, 0));
- tty.output = [];
- }
- }
- }
-};
-
-var zeroMemory = (address, size) => {
- HEAPU8.fill(0, address, address + size);
- return address;
-};
-
-var alignMemory = (size, alignment) => Math.ceil(size / alignment) * alignment;
-
-var mmapAlloc = size => {
- size = alignMemory(size, 65536);
- var ptr = _emscripten_builtin_memalign(65536, size);
- if (!ptr) return 0;
- return zeroMemory(ptr, size);
-};
-
-var MEMFS = {
- ops_table: null,
- mount(mount) {
- return MEMFS.createNode(null, "/", 16384 | 511, 0);
- },
- createNode(parent, name, mode, dev) {
- if (FS.isBlkdev(mode) || FS.isFIFO(mode)) {
- 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;
- 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();
- if (parent) {
- parent.contents[name] = node;
- parent.timestamp = node.timestamp;
- }
- return node;
- },
- getFileDataAsTypedArray(node) {
- if (!node.contents) return new Uint8Array(0);
- if (node.contents.subarray) return node.contents.subarray(0, node.usedBytes);
- return new Uint8Array(node.contents);
- },
- expandFileStorage(node, newCapacity) {
- var prevCapacity = node.contents ? node.contents.length : 0;
- if (prevCapacity >= newCapacity) return;
- var CAPACITY_DOUBLING_MAX = 1024 * 1024;
- newCapacity = Math.max(newCapacity, prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2 : 1.125) >>> 0);
- if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256);
- var oldContents = node.contents;
- node.contents = new Uint8Array(newCapacity);
- if (node.usedBytes > 0) node.contents.set(oldContents.subarray(0, node.usedBytes), 0);
- },
- resizeFileStorage(node, newSize) {
- if (node.usedBytes == newSize) return;
- if (newSize == 0) {
- node.contents = null;
- node.usedBytes = 0;
- } else {
- var oldContents = node.contents;
- node.contents = new Uint8Array(newSize);
- if (oldContents) {
- node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes)));
- }
- node.usedBytes = newSize;
- }
- },
- node_ops: {
+ };
+
+
+ var zeroMemory = (address, size) => {
+ HEAPU8.fill(0, address, address + size);
+ return address;
+ };
+
+ var alignMemory = (size, alignment) => {
+ return Math.ceil(size / alignment) * alignment;
+ };
+ var mmapAlloc = (size) => {
+ size = alignMemory(size, 65536);
+ var ptr = _emscripten_builtin_memalign(65536, size);
+ if (!ptr) return 0;
+ return zeroMemory(ptr, size);
+ };
+ var MEMFS = {
+ ops_table:null,
+ mount(mount) {
+ return MEMFS.createNode(null, '/', 16384 | 511 /* 0777 */, 0);
+ },
+ createNode(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(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(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(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(node) {
- var attr = {};
- 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);
- attr.blksize = 4096;
- attr.blocks = Math.ceil(attr.size / attr.blksize);
- return attr;
- },
+ 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(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);
- }
- },
+ 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(parent, name) {
- throw FS.genericErrors[44];
- },
+ throw FS.genericErrors[44];
+ },
mknod(parent, name, mode, dev) {
- return MEMFS.createNode(parent, name, mode, dev);
- },
+ return MEMFS.createNode(parent, name, mode, dev);
+ },
rename(old_node, new_dir, new_name) {
- 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);
- }
- }
- }
- 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;
- },
+ // 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(parent, name) {
- delete parent.contents[name];
- parent.timestamp = Date.now();
- },
+ delete parent.contents[name];
+ parent.timestamp = Date.now();
+ },
rmdir(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();
- },
+ 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(node) {
- var entries = [ ".", ".." ];
- for (var key in node.contents) {
- if (!node.contents.hasOwnProperty(key)) {
- continue;
- }
- entries.push(key);
- }
- return entries;
- },
+ var entries = ['.', '..'];
+ for (var key in node.contents) {
+ if (!node.contents.hasOwnProperty(key)) {
+ continue;
+ }
+ entries.push(key);
+ }
+ return entries;
+ },
symlink(parent, newname, oldpath) {
- var node = MEMFS.createNode(parent, newname, 511 | 40960, 0);
- node.link = oldpath;
- return node;
- },
+ var node = MEMFS.createNode(parent, newname, 511 /* 0777 */ | 40960, 0);
+ node.link = oldpath;
+ return node;
+ },
readlink(node) {
- if (!FS.isLink(node.mode)) {
- throw new FS.ErrnoError(28);
- }
- return node.link;
- }
- },
- stream_ops: {
- read(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) {
- buffer.set(contents.subarray(position, position + size), offset);
- } else {
- for (var i = 0; i < size; i++) buffer[offset + i] = contents[position + i];
- }
- return size;
+ if (!FS.isLink(node.mode)) {
+ throw new FS.ErrnoError(28);
+ }
+ return node.link;
+ },
},
+ stream_ops:{
+ read(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(stream, buffer, offset, length, position, canOwn) {
- if (buffer.buffer === HEAP8.buffer) {
- canOwn = false;
- }
- if (!length) return 0;
- var node = stream.node;
- node.timestamp = Date.now();
- if (buffer.subarray && (!node.contents || node.contents.subarray)) {
- if (canOwn) {
- node.contents = buffer.subarray(offset, offset + length);
- node.usedBytes = length;
- return length;
- } else if (node.usedBytes === 0 && position === 0) {
- node.contents = buffer.slice(offset, offset + length);
- node.usedBytes = length;
- return length;
- } else if (position + length <= node.usedBytes) {
- node.contents.set(buffer.subarray(offset, offset + length), position);
- return length;
- }
- }
- MEMFS.expandFileStorage(node, position + length);
- if (node.contents.subarray && buffer.subarray) {
- node.contents.set(buffer.subarray(offset, offset + length), position);
- } else {
- for (var i = 0; i < length; i++) {
- node.contents[position + i] = buffer[offset + i];
- }
- }
- node.usedBytes = Math.max(node.usedBytes, position + length);
- return length;
- },
+ // If the buffer is located in main memory (HEAP), and if
+ // memory can grow, we can't hold on to references of the
+ // memory buffer, as they may get invalidated. That means we
+ // need to do copy its contents.
+ if (buffer.buffer === HEAP8.buffer) {
+ canOwn = false;
+ }
+
+ 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(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;
- },
+ 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(stream, offset, length) {
- MEMFS.expandFileStorage(stream.node, offset + length);
- stream.node.usedBytes = Math.max(stream.node.usedBytes, offset + length);
- },
+ MEMFS.expandFileStorage(stream.node, offset + length);
+ stream.node.usedBytes = Math.max(stream.node.usedBytes, offset + length);
+ },
mmap(stream, length, position, prot, flags) {
- if (!FS.isFile(stream.node.mode)) {
- throw new FS.ErrnoError(43);
- }
- var ptr;
- var allocated;
- var contents = stream.node.contents;
- if (!(flags & 2) && contents.buffer === HEAP8.buffer) {
- allocated = false;
- ptr = contents.byteOffset;
- } else {
- 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
- };
- },
+ 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 === HEAP8.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, allocated };
+ },
msync(stream, buffer, offset, length, mmapFlags) {
- MEMFS.stream_ops.write(stream, buffer, 0, length, offset, false);
- return 0;
- }
- }
-};
-
-var asyncLoad = (url, onload, onerror, noRunDep) => {
- var dep = !noRunDep ? getUniqueRunDependency(`al ${url}`) : "";
- readAsync(url, (arrayBuffer => {
- assert(arrayBuffer, `Loading data file "${url}" failed (no arrayBuffer).`);
- onload(new Uint8Array(arrayBuffer));
- if (dep) removeRunDependency(dep);
- }), (event => {
- if (onerror) {
- onerror();
- } else {
- throw `Loading data file "${url}" failed.`;
- }
- }));
- if (dep) addRunDependency(dep);
-};
-
-var preloadPlugins = Module["preloadPlugins"] || [];
-
-function FS_handledByPreloadPlugin(byteArray, fullname, finish, onerror) {
- if (typeof Browser != "undefined") Browser.init();
- var handled = false;
- preloadPlugins.forEach((function(plugin) {
- if (handled) return;
- if (plugin["canHandle"](fullname)) {
- plugin["handle"](byteArray, fullname, finish, onerror);
- handled = true;
- }
- }));
- return handled;
-}
-
-function FS_createPreloadedFile(parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) {
- var fullname = name ? PATH_FS.resolve(PATH.join2(parent, name)) : parent;
- var dep = getUniqueRunDependency(`cp ${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);
- }
- if (FS_handledByPreloadPlugin(byteArray, fullname, finish, (() => {
- if (onerror) onerror();
- removeRunDependency(dep);
- }))) {
- return;
- }
- finish(byteArray);
- }
- addRunDependency(dep);
- if (typeof url == "string") {
- asyncLoad(url, (byteArray => processData(byteArray)), onerror);
- } else {
- processData(url);
- }
-}
-
-function FS_modeStringToFlags(str) {
- var flagModes = {
- "r": 0,
- "r+": 2,
- "w": 512 | 64 | 1,
- "w+": 512 | 64 | 2,
- "a": 1024 | 64 | 1,
- "a+": 1024 | 64 | 2
- };
- var flags = flagModes[str];
- if (typeof flags == "undefined") {
- throw new Error(`Unknown file open mode: ${str}`);
- }
- return flags;
-}
-
-function FS_getMode(canRead, canWrite) {
- var mode = 0;
- if (canRead) mode |= 292 | 73;
- if (canWrite) mode |= 146;
- return mode;
-}
-
-var ERRNO_CODES = {};
-
-var NODEFS = {
- isWindows: false,
- staticInit: () => {
- NODEFS.isWindows = !!process.platform.match(/^win/);
- var flags = process.binding("constants");
- if (flags["fs"]) {
- flags = flags["fs"];
- }
- NODEFS.flagsForNodeMap = {
- 1024: flags["O_APPEND"],
- 64: flags["O_CREAT"],
- 128: flags["O_EXCL"],
- 256: flags["O_NOCTTY"],
- 0: flags["O_RDONLY"],
- 2: flags["O_RDWR"],
- 4096: flags["O_SYNC"],
- 512: flags["O_TRUNC"],
- 1: flags["O_WRONLY"],
- 131072: flags["O_NOFOLLOW"]
- };
- },
- convertNodeCode: e => {
- var code = e.code;
- return ERRNO_CODES[code];
- },
- mount: mount => NODEFS.createNode(null, "/", NODEFS.getMode(mount.opts.root), 0),
- createNode: (parent, name, mode, dev) => {
- if (!FS.isDir(mode) && !FS.isFile(mode) && !FS.isLink(mode)) {
- throw new FS.ErrnoError(28);
- }
- var node = FS.createNode(parent, name, mode);
- node.node_ops = NODEFS.node_ops;
- node.stream_ops = NODEFS.stream_ops;
- return node;
- },
- getMode: path => {
- var stat;
- try {
- stat = fs.lstatSync(path);
- if (NODEFS.isWindows) {
- stat.mode = stat.mode | (stat.mode & 292) >> 2;
- }
- } catch (e) {
- if (!e.code) throw e;
- throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
- }
- return stat.mode;
- },
- realPath: node => {
- var parts = [];
- while (node.parent !== node) {
- parts.push(node.name);
- node = node.parent;
- }
- parts.push(node.mount.opts.root);
- parts.reverse();
- return PATH.join.apply(null, parts);
- },
- flagsForNode: flags => {
- flags &= ~2097152;
- flags &= ~2048;
- flags &= ~32768;
- flags &= ~524288;
- flags &= ~65536;
- var newFlags = 0;
- for (var k in NODEFS.flagsForNodeMap) {
- if (flags & k) {
- newFlags |= NODEFS.flagsForNodeMap[k];
- flags ^= k;
- }
- }
- if (flags) {
- throw new FS.ErrnoError(28);
- }
- return newFlags;
- },
- node_ops: {
- getattr: node => {
- var path = NODEFS.realPath(node);
- var stat;
- try {
- stat = fs.lstatSync(path);
- } catch (e) {
- if (!e.code) throw e;
- throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
- }
- if (NODEFS.isWindows && !stat.blksize) {
- stat.blksize = 4096;
- }
- if (NODEFS.isWindows && !stat.blocks) {
- stat.blocks = (stat.size + stat.blksize - 1) / stat.blksize | 0;
- }
- return {
- dev: stat.dev,
- ino: stat.ino,
- mode: stat.mode,
- nlink: stat.nlink,
- uid: stat.uid,
- gid: stat.gid,
- rdev: stat.rdev,
- size: stat.size,
- atime: stat.atime,
- mtime: stat.mtime,
- ctime: stat.ctime,
- blksize: stat.blksize,
- blocks: stat.blocks
- };
+ MEMFS.stream_ops.write(stream, buffer, 0, length, offset, false);
+ // should we check if bytesWritten and length are the same?
+ return 0;
+ },
},
- setattr: (node, attr) => {
- var path = NODEFS.realPath(node);
- try {
- if (attr.mode !== undefined) {
- fs.chmodSync(path, attr.mode);
- node.mode = attr.mode;
+ };
+
+ /** @param {boolean=} noRunDep */
+ var asyncLoad = (url, onload, onerror, noRunDep) => {
+ var dep = !noRunDep ? getUniqueRunDependency(`al ${url}`) : '';
+ readAsync(url, (arrayBuffer) => {
+ assert(arrayBuffer, `Loading data file "${url}" failed (no arrayBuffer).`);
+ onload(new Uint8Array(arrayBuffer));
+ if (dep) removeRunDependency(dep);
+ }, (event) => {
+ if (onerror) {
+ onerror();
+ } else {
+ throw `Loading data file "${url}" failed.`;
+ }
+ });
+ if (dep) addRunDependency(dep);
+ };
+
+
+ var preloadPlugins = Module['preloadPlugins'] || [];
+ function FS_handledByPreloadPlugin(byteArray, fullname, finish, onerror) {
+ // Ensure plugins are ready.
+ if (typeof Browser != 'undefined') Browser.init();
+
+ var handled = false;
+ preloadPlugins.forEach(function(plugin) {
+ if (handled) return;
+ if (plugin['canHandle'](fullname)) {
+ plugin['handle'](byteArray, fullname, finish, onerror);
+ handled = true;
+ }
+ });
+ return handled;
}
- if (attr.timestamp !== undefined) {
- var date = new Date(attr.timestamp);
- fs.utimesSync(path, date, date);
+ function FS_createPreloadedFile(parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) {
+ // 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);
+ }
+ if (FS_handledByPreloadPlugin(byteArray, fullname, finish, () => {
+ if (onerror) onerror();
+ removeRunDependency(dep);
+ })) {
+ return;
+ }
+ finish(byteArray);
+ }
+ addRunDependency(dep);
+ if (typeof url == 'string') {
+ asyncLoad(url, (byteArray) => processData(byteArray), onerror);
+ } else {
+ processData(url);
+ }
}
- if (attr.size !== undefined) {
- fs.truncateSync(path, attr.size);
+
+ function FS_modeStringToFlags(str) {
+ var flagModes = {
+ 'r': 0,
+ 'r+': 2,
+ 'w': 512 | 64 | 1,
+ 'w+': 512 | 64 | 2,
+ 'a': 1024 | 64 | 1,
+ 'a+': 1024 | 64 | 2,
+ };
+ var flags = flagModes[str];
+ if (typeof flags == 'undefined') {
+ throw new Error(`Unknown file open mode: ${str}`);
+ }
+ return flags;
}
- } catch (e) {
- if (!e.code) throw e;
- throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
- }
- },
- lookup: (parent, name) => {
- var path = PATH.join2(NODEFS.realPath(parent), name);
- var mode = NODEFS.getMode(path);
- return NODEFS.createNode(parent, name, mode);
- },
- mknod: (parent, name, mode, dev) => {
- var node = NODEFS.createNode(parent, name, mode, dev);
- var path = NODEFS.realPath(node);
- try {
- if (FS.isDir(node.mode)) {
- fs.mkdirSync(path, node.mode);
- } else {
- fs.writeFileSync(path, "", {
- mode: node.mode
- });
+
+ function FS_getMode(canRead, canWrite) {
+ var mode = 0;
+ if (canRead) mode |= 292 | 73;
+ if (canWrite) mode |= 146;
+ return mode;
}
- } catch (e) {
- if (!e.code) throw e;
- throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
- }
- return node;
+
+
+
+
+
+
+ var ERRNO_CODES = {
+ };
+
+ var NODEFS = {
+ isWindows:false,
+ staticInit:() => {
+ NODEFS.isWindows = !!process.platform.match(/^win/);
+ var flags = process.binding("constants");
+ // Node.js 4 compatibility: it has no namespaces for constants
+ if (flags["fs"]) {
+ flags = flags["fs"];
+ }
+ NODEFS.flagsForNodeMap = {
+ "1024": flags["O_APPEND"],
+ "64": flags["O_CREAT"],
+ "128": flags["O_EXCL"],
+ "256": flags["O_NOCTTY"],
+ "0": flags["O_RDONLY"],
+ "2": flags["O_RDWR"],
+ "4096": flags["O_SYNC"],
+ "512": flags["O_TRUNC"],
+ "1": flags["O_WRONLY"],
+ "131072": flags["O_NOFOLLOW"],
+ };
+ },
+ convertNodeCode:(e) => {
+ var code = e.code;
+ return ERRNO_CODES[code];
+ },
+ mount:(mount) => {
+ return NODEFS.createNode(null, '/', NODEFS.getMode(mount.opts.root), 0);
+ },
+ createNode:(parent, name, mode, dev) => {
+ if (!FS.isDir(mode) && !FS.isFile(mode) && !FS.isLink(mode)) {
+ throw new FS.ErrnoError(28);
+ }
+ var node = FS.createNode(parent, name, mode);
+ node.node_ops = NODEFS.node_ops;
+ node.stream_ops = NODEFS.stream_ops;
+ return node;
+ },
+ getMode:(path) => {
+ var stat;
+ try {
+ stat = fs.lstatSync(path);
+ if (NODEFS.isWindows) {
+ // Node.js on Windows never represents permission bit 'x', so
+ // propagate read bits to execute bits
+ stat.mode = stat.mode | ((stat.mode & 292) >> 2);
+ }
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
+ }
+ return stat.mode;
+ },
+ realPath:(node) => {
+ var parts = [];
+ while (node.parent !== node) {
+ parts.push(node.name);
+ node = node.parent;
+ }
+ parts.push(node.mount.opts.root);
+ parts.reverse();
+ return PATH.join.apply(null, parts);
+ },
+ flagsForNode:(flags) => {
+ flags &= ~2097152; // Ignore this flag from musl, otherwise node.js fails to open the file.
+ flags &= ~2048; // Ignore this flag from musl, otherwise node.js fails to open the file.
+ flags &= ~32768; // Ignore this flag from musl, otherwise node.js fails to open the file.
+ flags &= ~524288; // Some applications may pass it; it makes no sense for a single process.
+ flags &= ~65536; // Node.js doesn't need this passed in, it errors.
+ var newFlags = 0;
+ for (var k in NODEFS.flagsForNodeMap) {
+ if (flags & k) {
+ newFlags |= NODEFS.flagsForNodeMap[k];
+ flags ^= k;
+ }
+ }
+ if (flags) {
+ throw new FS.ErrnoError(28);
+ }
+ return newFlags;
+ },
+ node_ops:{
+ getattr:(node) => {
+ var path = NODEFS.realPath(node);
+ var stat;
+ try {
+ stat = fs.lstatSync(path);
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
+ }
+ // node.js v0.10.20 doesn't report blksize and blocks on Windows. Fake them with default blksize of 4096.
+ // See http://support.microsoft.com/kb/140365
+ if (NODEFS.isWindows && !stat.blksize) {
+ stat.blksize = 4096;
+ }
+ if (NODEFS.isWindows && !stat.blocks) {
+ stat.blocks = (stat.size+stat.blksize-1)/stat.blksize|0;
+ }
+ return {
+ dev: stat.dev,
+ ino: stat.ino,
+ mode: stat.mode,
+ nlink: stat.nlink,
+ uid: stat.uid,
+ gid: stat.gid,
+ rdev: stat.rdev,
+ size: stat.size,
+ atime: stat.atime,
+ mtime: stat.mtime,
+ ctime: stat.ctime,
+ blksize: stat.blksize,
+ blocks: stat.blocks
+ };
+ },
+ setattr:(node, attr) => {
+ var path = NODEFS.realPath(node);
+ try {
+ if (attr.mode !== undefined) {
+ fs.chmodSync(path, attr.mode);
+ // update the common node structure mode as well
+ node.mode = attr.mode;
+ }
+ if (attr.timestamp !== undefined) {
+ var date = new Date(attr.timestamp);
+ fs.utimesSync(path, date, date);
+ }
+ if (attr.size !== undefined) {
+ fs.truncateSync(path, attr.size);
+ }
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
+ }
+ },
+ lookup:(parent, name) => {
+ var path = PATH.join2(NODEFS.realPath(parent), name);
+ var mode = NODEFS.getMode(path);
+ return NODEFS.createNode(parent, name, mode);
+ },
+ mknod:(parent, name, mode, dev) => {
+ var node = NODEFS.createNode(parent, name, mode, dev);
+ // create the backing node for this in the fs root as well
+ var path = NODEFS.realPath(node);
+ try {
+ if (FS.isDir(node.mode)) {
+ fs.mkdirSync(path, node.mode);
+ } else {
+ fs.writeFileSync(path, '', { mode: node.mode });
+ }
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
+ }
+ return node;
+ },
+ rename:(oldNode, newDir, newName) => {
+ var oldPath = NODEFS.realPath(oldNode);
+ var newPath = PATH.join2(NODEFS.realPath(newDir), newName);
+ try {
+ fs.renameSync(oldPath, newPath);
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
+ }
+ oldNode.name = newName;
+ },
+ unlink:(parent, name) => {
+ var path = PATH.join2(NODEFS.realPath(parent), name);
+ try {
+ fs.unlinkSync(path);
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
+ }
+ },
+ rmdir:(parent, name) => {
+ var path = PATH.join2(NODEFS.realPath(parent), name);
+ try {
+ fs.rmdirSync(path);
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
+ }
+ },
+ readdir:(node) => {
+ var path = NODEFS.realPath(node);
+ try {
+ return fs.readdirSync(path);
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
+ }
+ },
+ symlink:(parent, newName, oldPath) => {
+ var newPath = PATH.join2(NODEFS.realPath(parent), newName);
+ try {
+ fs.symlinkSync(oldPath, newPath);
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
+ }
+ },
+ readlink:(node) => {
+ var path = NODEFS.realPath(node);
+ try {
+ path = fs.readlinkSync(path);
+ path = nodePath.relative(nodePath.resolve(node.mount.opts.root), path);
+ return path;
+ } catch (e) {
+ if (!e.code) throw e;
+ // node under windows can return code 'UNKNOWN' here:
+ // https://github.com/emscripten-core/emscripten/issues/15468
+ if (e.code === 'UNKNOWN') throw new FS.ErrnoError(28);
+ throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
+ }
+ },
},
- rename: (oldNode, newDir, newName) => {
- var oldPath = NODEFS.realPath(oldNode);
- var newPath = PATH.join2(NODEFS.realPath(newDir), newName);
- try {
- fs.renameSync(oldPath, newPath);
- } catch (e) {
- if (!e.code) throw e;
- throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
- }
- oldNode.name = newName;
+ stream_ops:{
+ open:(stream) => {
+ var path = NODEFS.realPath(stream.node);
+ try {
+ if (FS.isFile(stream.node.mode)) {
+ stream.nfd = fs.openSync(path, NODEFS.flagsForNode(stream.flags));
+ }
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
+ }
+ },
+ close:(stream) => {
+ try {
+ if (FS.isFile(stream.node.mode) && stream.nfd) {
+ fs.closeSync(stream.nfd);
+ }
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
+ }
+ },
+ read:(stream, buffer, offset, length, position) => {
+ // Node.js < 6 compatibility: node errors on 0 length reads
+ if (length === 0) return 0;
+ try {
+ return fs.readSync(stream.nfd, Buffer.from(buffer.buffer), offset, length, position);
+ } catch (e) {
+ throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
+ }
+ },
+ write:(stream, buffer, offset, length, position) => {
+ try {
+ return fs.writeSync(stream.nfd, Buffer.from(buffer.buffer), offset, length, position);
+ } catch (e) {
+ throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
+ }
+ },
+ llseek:(stream, offset, whence) => {
+ var position = offset;
+ if (whence === 1) {
+ position += stream.position;
+ } else if (whence === 2) {
+ if (FS.isFile(stream.node.mode)) {
+ try {
+ var stat = fs.fstatSync(stream.nfd);
+ position += stat.size;
+ } catch (e) {
+ throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
+ }
+ }
+ }
+
+ if (position < 0) {
+ throw new FS.ErrnoError(28);
+ }
+
+ return position;
+ },
+ mmap:(stream, length, position, prot, flags) => {
+ if (!FS.isFile(stream.node.mode)) {
+ throw new FS.ErrnoError(43);
+ }
+
+ var ptr = mmapAlloc(length);
+
+ NODEFS.stream_ops.read(stream, HEAP8, ptr, length, position);
+ return { ptr, allocated: true };
+ },
+ msync:(stream, buffer, offset, length, mmapFlags) => {
+ NODEFS.stream_ops.write(stream, buffer, 0, length, offset, false);
+ // should we check if bytesWritten and length are the same?
+ return 0;
+ },
},
- unlink: (parent, name) => {
- var path = PATH.join2(NODEFS.realPath(parent), name);
- try {
- fs.unlinkSync(path);
- } catch (e) {
- if (!e.code) throw e;
- throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
- }
+ };
+ var FS = {
+ root:null,
+ mounts:[],
+ devices:{
},
- rmdir: (parent, name) => {
- var path = PATH.join2(NODEFS.realPath(parent), name);
- try {
- fs.rmdirSync(path);
- } catch (e) {
- if (!e.code) throw e;
- throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
- }
+ streams:[],
+ nextInode:1,
+ nameTable:null,
+ currentPath:"/",
+ initialized:false,
+ ignorePermissions:true,
+ ErrnoError:null,
+ genericErrors:{
},
- readdir: node => {
- var path = NODEFS.realPath(node);
- try {
- return fs.readdirSync(path);
- } catch (e) {
- if (!e.code) throw e;
- throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
- }
+ filesystems:null,
+ syncFSRequests:0,
+ lookupPath:(path, opts = {}) => {
+ path = PATH_FS.resolve(path);
+
+ if (!path) return { path: '', node: null };
+
+ var defaults = {
+ follow_mount: true,
+ recurse_count: 0
+ };
+ opts = Object.assign(defaults, opts)
+
+ if (opts.recurse_count > 8) { // max recursive lookup of 8
+ throw new FS.ErrnoError(32);
+ }
+
+ // split the absolute path
+ var parts = path.split('/').filter((p) => !!p);
+
+ // 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 + 1 });
+ 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:(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:(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:(node) => {
+ var hash = FS.hashName(node.parent.id, node.name);
+ node.name_next = FS.nameTable[hash];
+ FS.nameTable[hash] = node;
+ },
+ hashRemoveNode:(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:(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:(parent, name, mode, rdev) => {
+ var node = new FS.FSNode(parent, name, mode, rdev);
+
+ FS.hashAddNode(node);
+
+ return node;
+ },
+ destroyNode:(node) => {
+ FS.hashRemoveNode(node);
+ },
+ isRoot:(node) => {
+ return node === node.parent;
+ },
+ isMountpoint:(node) => {
+ return !!node.mounted;
+ },
+ isFile:(mode) => {
+ return (mode & 61440) === 32768;
+ },
+ isDir:(mode) => {
+ return (mode & 61440) === 16384;
+ },
+ isLink:(mode) => {
+ return (mode & 61440) === 40960;
+ },
+ isChrdev:(mode) => {
+ return (mode & 61440) === 8192;
+ },
+ isBlkdev:(mode) => {
+ return (mode & 61440) === 24576;
+ },
+ isFIFO:(mode) => {
+ return (mode & 61440) === 4096;
+ },
+ isSocket:(mode) => {
+ return (mode & 49152) === 49152;
+ },
+ flagsToPermissionString:(flag) => {
+ var perms = ['r', 'w', 'rw'][flag & 3];
+ if ((flag & 512)) {
+ perms += 'w';
+ }
+ return perms;
+ },
+ nodePermissions:(node, perms) => {
+ if (FS.ignorePermissions) {
+ return 0;
+ }
+ // return 0 if any user, group or owner bits are set.
+ if (perms.includes('r') && !(node.mode & 292)) {
+ return 2;
+ } else if (perms.includes('w') && !(node.mode & 146)) {
+ return 2;
+ } else if (perms.includes('x') && !(node.mode & 73)) {
+ return 2;
+ }
+ return 0;
+ },
+ mayLookup:(dir) => {
+ var errCode = FS.nodePermissions(dir, 'x');
+ if (errCode) return errCode;
+ if (!dir.node_ops.lookup) return 2;
+ return 0;
+ },
+ mayCreate:(dir, name) => {
+ try {
+ var node = FS.lookupNode(dir, name);
+ return 20;
+ } catch (e) {
+ }
+ return FS.nodePermissions(dir, 'wx');
+ },
+ mayDelete:(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:(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:() => {
+ for (var fd = 0; fd <= FS.MAX_OPEN_FDS; fd++) {
+ if (!FS.streams[fd]) {
+ return fd;
+ }
+ }
+ throw new FS.ErrnoError(33);
+ },
+ getStreamChecked:(fd) => {
+ var stream = FS.getStream(fd);
+ if (!stream) {
+ throw new FS.ErrnoError(8);
+ }
+ return stream;
+ },
+ getStream:(fd) => FS.streams[fd],
+ createStream:(stream, fd = -1) => {
+ if (!FS.FSStream) {
+ FS.FSStream = /** @constructor */ function() {
+ this.shared = { };
+ };
+ FS.FSStream.prototype = {};
+ Object.defineProperties(FS.FSStream.prototype, {
+ object: {
+ /** @this {FS.FSStream} */
+ get() { return this.node; },
+ /** @this {FS.FSStream} */
+ set(val) { this.node = val; }
+ },
+ isRead: {
+ /** @this {FS.FSStream} */
+ get() { return (this.flags & 2097155) !== 1; }
+ },
+ isWrite: {
+ /** @this {FS.FSStream} */
+ get() { return (this.flags & 2097155) !== 0; }
+ },
+ isAppend: {
+ /** @this {FS.FSStream} */
+ get() { return (this.flags & 1024); }
+ },
+ flags: {
+ /** @this {FS.FSStream} */
+ get() { return this.shared.flags; },
+ /** @this {FS.FSStream} */
+ set(val) { this.shared.flags = val; },
+ },
+ position : {
+ /** @this {FS.FSStream} */
+ get() { return this.shared.position; },
+ /** @this {FS.FSStream} */
+ set(val) { this.shared.position = val; },
+ },
+ });
+ }
+ // clone it, so we can return an instance of FSStream
+ stream = Object.assign(new FS.FSStream(), stream);
+ if (fd == -1) {
+ fd = FS.nextfd();
+ }
+ stream.fd = fd;
+ FS.streams[fd] = stream;
+ return stream;
+ },
+ closeStream:(fd) => {
+ FS.streams[fd] = null;
+ },
+ chrdev_stream_ops:{
+ open:(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:() => {
+ throw new FS.ErrnoError(70);
+ },
},
- symlink: (parent, newName, oldPath) => {
- var newPath = PATH.join2(NODEFS.realPath(parent), newName);
- try {
- fs.symlinkSync(oldPath, newPath);
- } catch (e) {
- if (!e.code) throw e;
- throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
- }
+ major:(dev) => ((dev) >> 8),
+ minor:(dev) => ((dev) & 0xff),
+ makedev:(ma, mi) => ((ma) << 8 | (mi)),
+ registerDevice:(dev, ops) => {
+ FS.devices[dev] = { stream_ops: ops };
+ },
+ getDevice:(dev) => FS.devices[dev],
+ getMounts:(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:(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((mount) => {
+ if (!mount.type.syncfs) {
+ return done(null);
+ }
+ mount.type.syncfs(mount, populate, done);
+ });
+ },
+ mount:(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,
+ opts,
+ 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:(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((hash) => {
+ var current = FS.nameTable[hash];
+
+ while (current) {
+ var next = current.name_next;
+
+ if (mounts.includes(current.mount)) {
+ 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:(parent, name) => {
+ return parent.node_ops.lookup(parent, name);
+ },
+ mknod:(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:(path, mode) => {
+ mode = mode !== undefined ? mode : 438 /* 0666 */;
+ mode &= 4095;
+ mode |= 32768;
+ return FS.mknod(path, mode, 0);
+ },
+ mkdir:(path, mode) => {
+ mode = mode !== undefined ? mode : 511 /* 0777 */;
+ mode &= 511 | 512;
+ mode |= 16384;
+ return FS.mknod(path, mode, 0);
+ },
+ mkdirTree:(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:(path, mode, dev) => {
+ if (typeof dev == 'undefined') {
+ dev = mode;
+ mode = 438 /* 0666 */;
+ }
+ mode |= 8192;
+ return FS.mknod(path, mode, dev);
+ },
+ symlink:(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:(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);
+ }
+ }
+ // 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);
+ }
+ },
+ rmdir:(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);
+ }
+ parent.node_ops.rmdir(parent, name);
+ FS.destroyNode(node);
+ },
+ readdir:(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:(path) => {
+ var lookup = FS.lookupPath(path, { parent: true });
+ var parent = lookup.node;
+ if (!parent) {
+ throw new FS.ErrnoError(44);
+ }
+ 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);
+ }
+ parent.node_ops.unlink(parent, name);
+ FS.destroyNode(node);
+ },
+ readlink:(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:(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:(path) => {
+ return FS.stat(path, true);
+ },
+ chmod:(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:(path, mode) => {
+ FS.chmod(path, mode, true);
+ },
+ fchmod:(fd, mode) => {
+ var stream = FS.getStreamChecked(fd);
+ FS.chmod(stream.node, mode);
+ },
+ chown:(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:(path, uid, gid) => {
+ FS.chown(path, uid, gid, true);
+ },
+ fchown:(fd, uid, gid) => {
+ var stream = FS.getStreamChecked(fd);
+ FS.chown(stream.node, uid, gid);
+ },
+ truncate:(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:(fd, len) => {
+ var stream = FS.getStreamChecked(fd);
+ if ((stream.flags & 2097155) === 0) {
+ throw new FS.ErrnoError(28);
+ }
+ FS.truncate(stream.node, len);
+ },
+ utime:(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:(path, flags, mode) => {
+ 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) && !created) {
+ 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,
+ path: FS.getPath(node), // we want the absolute path to the node
+ flags,
+ seekable: true,
+ position: 0,
+ stream_ops: node.stream_ops,
+ // used by the file family libc calls (fopen, fwrite, ferror, etc.)
+ ungotten: [],
+ error: false
+ });
+ // 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;
+ }
+ }
+ return stream;
+ },
+ close:(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:(stream) => {
+ return stream.fd === null;
+ },
+ llseek:(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:(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:(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;
+ return bytesWritten;
+ },
+ allocate:(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:(stream, 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, length, position, prot, flags);
+ },
+ msync:(stream, buffer, offset, length, mmapFlags) => {
+ if (!stream.stream_ops.msync) {
+ return 0;
+ }
+ return stream.stream_ops.msync(stream, buffer, offset, length, mmapFlags);
+ },
+ munmap:(stream) => 0,
+ ioctl:(stream, cmd, arg) => {
+ if (!stream.stream_ops.ioctl) {
+ throw new FS.ErrnoError(59);
+ }
+ return stream.stream_ops.ioctl(stream, cmd, arg);
+ },
+ readFile:(path, 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:(path, data, 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:() => FS.currentPath,
+ chdir:(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:() => {
+ FS.mkdir('/tmp');
+ FS.mkdir('/home');
+ FS.mkdir('/home/web_user');
+ },
+ createDefaultDevices:() => {
+ // create /dev
+ FS.mkdir('/dev');
+ // setup /dev/null
+ FS.registerDevice(FS.makedev(1, 3), {
+ read: () => 0,
+ write: (stream, buffer, offset, length, pos) => 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
+ // use a buffer to avoid overhead of individual crypto calls per byte
+ var randomBuffer = new Uint8Array(1024), randomLeft = 0;
+ var randomByte = () => {
+ if (randomLeft === 0) {
+ randomLeft = randomFill(randomBuffer).byteLength;
+ }
+ return randomBuffer[--randomLeft];
+ };
+ FS.createDevice('/dev', 'random', randomByte);
+ FS.createDevice('/dev', 'urandom', randomByte);
+ // 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:() => {
+ // 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: () => {
+ var node = FS.createNode(proc_self, 'fd', 16384 | 511 /* 0777 */, 73);
+ node.node_ops = {
+ lookup: (parent, name) => {
+ var fd = +name;
+ var stream = FS.getStreamChecked(fd);
+ var ret = {
+ parent: null,
+ mount: { mountpoint: 'fake' },
+ node_ops: { readlink: () => stream.path },
+ };
+ ret.parent = ret; // make it look like a simple root node
+ return ret;
+ }
+ };
+ return node;
+ }
+ }, {}, '/proc/self/fd');
+ },
+ createStandardStreams:() => {
+ // 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:() => {
+ if (FS.ErrnoError) return;
+ FS.ErrnoError = /** @this{Object} */ function ErrnoError(errno, node) {
+ // We set the `name` property to be able to identify `FS.ErrnoError`
+ // - the `name` is a standard ECMA-262 property of error objects. Kind of good to have it anyway.
+ // - when using PROXYFS, an error can come from an underlying FS
+ // as different FS objects have their own FS.ErrnoError each,
+ // the test `err instanceof FS.ErrnoError` won't detect an error coming from another filesystem, causing bugs.
+ // we'll use the reliable test `err.name == "ErrnoError"` instead
+ this.name = 'ErrnoError';
+ 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((code) => {
+ FS.genericErrors[code] = new FS.ErrnoError(code);
+ FS.genericErrors[code].stack = '';
+ });
+ },
+ staticInit:() => {
+ FS.ensureErrnoError();
+
+ FS.nameTable = new Array(4096);
+
+ FS.mount(MEMFS, {}, '/');
+
+ FS.createDefaultDirectories();
+ FS.createDefaultDevices();
+ FS.createSpecialDirectories();
+
+ FS.filesystems = {
+ 'MEMFS': MEMFS,
+ 'NODEFS': NODEFS,
+ };
+ },
+ init:(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:() => {
+ FS.init.initialized = false;
+ // force-flush all streams, so we get musl std streams printed out
+ _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);
+ }
+ },
+ findObject:(path, dontResolveLastLink) => {
+ var ret = FS.analyzePath(path, dontResolveLastLink);
+ if (!ret.exists) {
+ return null;
+ }
+ return ret.object;
+ },
+ analyzePath:(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:(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:(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:(parent, name, data, canRead, canWrite, canOwn) => {
+ var path = name;
+ if (parent) {
+ parent = typeof parent == 'string' ? parent : FS.getPath(parent);
+ path = name ? PATH.join2(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:(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: (stream) => {
+ stream.seekable = false;
+ },
+ close: (stream) => {
+ // flush any pending line data
+ if (output && output.buffer && output.buffer.length) {
+ output(10);
+ }
+ },
+ read: (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: (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:(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:(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 = (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.
+ 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 || []));
+ }
+ return intArrayFromString(xhr.responseText || '', true);
+ };
+ var lazyArray = this;
+ lazyArray.setDataGetter((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((key) => {
+ var fn = node.stream_ops[key];
+ stream_ops[key] = function forceLoadLazyFile() {
+ FS.forceLoadFile(node);
+ return fn.apply(null, arguments);
+ };
+ });
+ function writeChunks(stream, buffer, offset, length, position) {
+ 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;
+ }
+ // use a custom read function
+ stream_ops.read = (stream, buffer, offset, length, position) => {
+ FS.forceLoadFile(node);
+ return writeChunks(stream, buffer, offset, length, position)
+ };
+ // use a custom mmap function
+ stream_ops.mmap = (stream, length, position, prot, flags) => {
+ FS.forceLoadFile(node);
+ var ptr = mmapAlloc(length);
+ if (!ptr) {
+ throw new FS.ErrnoError(48);
+ }
+ writeChunks(stream, HEAP8, ptr, length, position);
+ return { ptr, allocated: true };
+ };
+ node.stream_ops = stream_ops;
+ return node;
+ },
+ };
+ Module['FS'] = FS;
+
+ var SYSCALLS = {
+ DEFAULT_POLLMASK:5,
+ calculateAt:function(dirfd, path, allowEmpty) {
+ if (PATH.isAbs(path)) {
+ return path;
+ }
+ // relative path
+ var dir;
+ if (dirfd === -100) {
+ dir = FS.cwd();
+ } else {
+ var dirstream = SYSCALLS.getStreamFromFD(dirfd);
+ 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)] = stat.mode;
+ HEAPU32[(((buf)+(8))>>2)] = stat.nlink;
+ HEAP32[(((buf)+(12))>>2)] = stat.uid;
+ HEAP32[(((buf)+(16))>>2)] = stat.gid;
+ HEAP32[(((buf)+(20))>>2)] = stat.rdev;
+ (tempI64 = [stat.size>>>0,(tempDouble=stat.size,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(24))>>2)] = tempI64[0],HEAP32[(((buf)+(28))>>2)] = tempI64[1]);
+ HEAP32[(((buf)+(32))>>2)] = 4096;
+ HEAP32[(((buf)+(36))>>2)] = stat.blocks;
+ var atime = stat.atime.getTime();
+ var mtime = stat.mtime.getTime();
+ var ctime = stat.ctime.getTime();
+ (tempI64 = [Math.floor(atime / 1000)>>>0,(tempDouble=Math.floor(atime / 1000),(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(40))>>2)] = tempI64[0],HEAP32[(((buf)+(44))>>2)] = tempI64[1]);
+ HEAPU32[(((buf)+(48))>>2)] = (atime % 1000) * 1000;
+ (tempI64 = [Math.floor(mtime / 1000)>>>0,(tempDouble=Math.floor(mtime / 1000),(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(56))>>2)] = tempI64[0],HEAP32[(((buf)+(60))>>2)] = tempI64[1]);
+ HEAPU32[(((buf)+(64))>>2)] = (mtime % 1000) * 1000;
+ (tempI64 = [Math.floor(ctime / 1000)>>>0,(tempDouble=Math.floor(ctime / 1000),(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(72))>>2)] = tempI64[0],HEAP32[(((buf)+(76))>>2)] = tempI64[1]);
+ HEAPU32[(((buf)+(80))>>2)] = (ctime % 1000) * 1000;
+ (tempI64 = [stat.ino>>>0,(tempDouble=stat.ino,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(88))>>2)] = tempI64[0],HEAP32[(((buf)+(92))>>2)] = tempI64[1]);
+ return 0;
+ },
+ doMsync:function(addr, stream, len, flags, offset) {
+ if (!FS.isFile(stream.node.mode)) {
+ throw new FS.ErrnoError(43);
+ }
+ if (flags & 2) {
+ // MAP_PRIVATE calls need not to be synced back to underlying fs
+ return 0;
+ }
+ var buffer = HEAPU8.slice(addr, addr + len);
+ FS.msync(stream, buffer, offset, len, flags);
+ },
+ varargs:undefined,
+ get() {
+ SYSCALLS.varargs += 4;
+ var ret = HEAP32[(((SYSCALLS.varargs)-(4))>>2)];
+ return ret;
+ },
+ getStr(ptr) {
+ var ret = UTF8ToString(ptr);
+ return ret;
+ },
+ getStreamFromFD:function(fd) {
+ var stream = FS.getStreamChecked(fd);
+ return stream;
+ },
+ };
+ function ___syscall__newselect(nfds, readfds, writefds, exceptfds, timeout) {
+ try {
+
+ // readfds are supported,
+ // writefds checks socket open status
+ // exceptfds not supported
+ // timeout is always 0 - fully async
+
+ var total = 0;
+
+ var srcReadLow = (readfds ? HEAP32[((readfds)>>2)] : 0),
+ srcReadHigh = (readfds ? HEAP32[(((readfds)+(4))>>2)] : 0);
+ var srcWriteLow = (writefds ? HEAP32[((writefds)>>2)] : 0),
+ srcWriteHigh = (writefds ? HEAP32[(((writefds)+(4))>>2)] : 0);
+ var srcExceptLow = (exceptfds ? HEAP32[((exceptfds)>>2)] : 0),
+ srcExceptHigh = (exceptfds ? HEAP32[(((exceptfds)+(4))>>2)] : 0);
+
+ var dstReadLow = 0,
+ dstReadHigh = 0;
+ var dstWriteLow = 0,
+ dstWriteHigh = 0;
+ var dstExceptLow = 0,
+ dstExceptHigh = 0;
+
+ var allLow = (readfds ? HEAP32[((readfds)>>2)] : 0) |
+ (writefds ? HEAP32[((writefds)>>2)] : 0) |
+ (exceptfds ? HEAP32[((exceptfds)>>2)] : 0);
+ var allHigh = (readfds ? HEAP32[(((readfds)+(4))>>2)] : 0) |
+ (writefds ? HEAP32[(((writefds)+(4))>>2)] : 0) |
+ (exceptfds ? HEAP32[(((exceptfds)+(4))>>2)] : 0);
+
+ var check = function(fd, low, high, val) {
+ return (fd < 32 ? (low & val) : (high & val));
+ };
+
+ for (var fd = 0; fd < nfds; fd++) {
+ var mask = 1 << (fd % 32);
+ if (!(check(fd, allLow, allHigh, mask))) {
+ continue; // index isn't in the set
+ }
+
+ var stream = SYSCALLS.getStreamFromFD(fd);
+
+ var flags = SYSCALLS.DEFAULT_POLLMASK;
+
+ if (stream.stream_ops?.poll) {
+ var timeoutInMillis = -1;
+ if (timeout) {
+ var tv_sec = (readfds ? HEAP32[((timeout)>>2)] : 0),
+ tv_usec = (readfds ? HEAP32[(((timeout)+(8))>>2)] : 0);
+ timeoutInMillis = (tv_sec + tv_usec / 1000000) * 1000;
+ }
+ flags = stream.stream_ops.poll(stream, timeoutInMillis);
+ }
+
+ if ((flags & 1) && check(fd, srcReadLow, srcReadHigh, mask)) {
+ fd < 32 ? (dstReadLow = dstReadLow | mask) : (dstReadHigh = dstReadHigh | mask);
+ total++;
+ }
+ if ((flags & 4) && check(fd, srcWriteLow, srcWriteHigh, mask)) {
+ fd < 32 ? (dstWriteLow = dstWriteLow | mask) : (dstWriteHigh = dstWriteHigh | mask);
+ total++;
+ }
+ if ((flags & 2) && check(fd, srcExceptLow, srcExceptHigh, mask)) {
+ fd < 32 ? (dstExceptLow = dstExceptLow | mask) : (dstExceptHigh = dstExceptHigh | mask);
+ total++;
+ }
+ }
+
+ if (readfds) {
+ HEAP32[((readfds)>>2)] = dstReadLow;
+ HEAP32[(((readfds)+(4))>>2)] = dstReadHigh;
+ }
+ if (writefds) {
+ HEAP32[((writefds)>>2)] = dstWriteLow;
+ HEAP32[(((writefds)+(4))>>2)] = dstWriteHigh;
+ }
+ if (exceptfds) {
+ HEAP32[((exceptfds)>>2)] = dstExceptLow;
+ HEAP32[(((exceptfds)+(4))>>2)] = dstExceptHigh;
+ }
+
+ return total;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+ var SOCKFS = {
+ mount(mount) {
+ // If Module['websocket'] has already been defined (e.g. for configuring
+ // the subprotocol/url) use that, if not initialise it to a new object.
+ Module['websocket'] = (Module['websocket'] &&
+ ('object' === typeof Module['websocket'])) ? Module['websocket'] : {};
+
+ // Add the Event registration mechanism to the exported websocket configuration
+ // object so we can register network callbacks from native JavaScript too.
+ // For more documentation see system/include/emscripten/emscripten.h
+ Module['websocket']._callbacks = {};
+ Module['websocket']['on'] = /** @this{Object} */ function(event, callback) {
+ if ('function' === typeof callback) {
+ this._callbacks[event] = callback;
+ }
+ return this;
+ };
+
+ Module['websocket'].emit = /** @this{Object} */ function(event, param) {
+ if ('function' === typeof this._callbacks[event]) {
+ this._callbacks[event].call(this, param);
+ }
+ };
+
+ // If debug is enabled register simple default logging callbacks for each Event.
+
+ return FS.createNode(null, '/', 16384 | 511 /* 0777 */, 0);
+ },
+ createSocket(family, type, protocol) {
+ type &= ~526336; // Some applications may pass it; it makes no sense for a single process.
+ var streaming = type == 1;
+ if (streaming && protocol && protocol != 6) {
+ throw new FS.ErrnoError(66); // if SOCK_STREAM, must be tcp or 0.
+ }
+
+ // create our internal socket structure
+ var sock = {
+ family,
+ type,
+ protocol,
+ server: null,
+ error: null, // Used in getsockopt for SOL_SOCKET/SO_ERROR test
+ peers: {},
+ pending: [],
+ recv_queue: [],
+ sock_ops: SOCKFS.websocket_sock_ops
+ };
+
+ // create the filesystem node to store the socket structure
+ var name = SOCKFS.nextname();
+ var node = FS.createNode(SOCKFS.root, name, 49152, 0);
+ node.sock = sock;
+
+ // and the wrapping stream that enables library functions such
+ // as read and write to indirectly interact with the socket
+ var stream = FS.createStream({
+ path: name,
+ node,
+ flags: 2,
+ seekable: false,
+ stream_ops: SOCKFS.stream_ops
+ });
+
+ // map the new stream to the socket structure (sockets have a 1:1
+ // relationship with a stream)
+ sock.stream = stream;
+
+ return sock;
+ },
+ getSocket(fd) {
+ var stream = FS.getStream(fd);
+ if (!stream || !FS.isSocket(stream.node.mode)) {
+ return null;
+ }
+ return stream.node.sock;
+ },
+ stream_ops:{
+ poll(stream) {
+ var sock = stream.node.sock;
+ return sock.sock_ops.poll(sock);
+ },
+ ioctl(stream, request, varargs) {
+ var sock = stream.node.sock;
+ return sock.sock_ops.ioctl(sock, request, varargs);
+ },
+ read(stream, buffer, offset, length, position /* ignored */) {
+ var sock = stream.node.sock;
+ var msg = sock.sock_ops.recvmsg(sock, length);
+ if (!msg) {
+ // socket is closed
+ return 0;
+ }
+ buffer.set(msg.buffer, offset);
+ return msg.buffer.length;
+ },
+ write(stream, buffer, offset, length, position /* ignored */) {
+ var sock = stream.node.sock;
+ return sock.sock_ops.sendmsg(sock, buffer, offset, length);
+ },
+ close(stream) {
+ var sock = stream.node.sock;
+ sock.sock_ops.close(sock);
+ },
},
- readlink: node => {
- var path = NODEFS.realPath(node);
- try {
- path = fs.readlinkSync(path);
- path = nodePath.relative(nodePath.resolve(node.mount.opts.root), path);
- return path;
- } catch (e) {
- if (!e.code) throw e;
- if (e.code === "UNKNOWN") throw new FS.ErrnoError(28);
- throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
- }
- }
- },
- stream_ops: {
- open: stream => {
- var path = NODEFS.realPath(stream.node);
- try {
- if (FS.isFile(stream.node.mode)) {
- stream.nfd = fs.openSync(path, NODEFS.flagsForNode(stream.flags));
- }
- } catch (e) {
- if (!e.code) throw e;
- throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
- }
+ nextname() {
+ if (!SOCKFS.nextname.current) {
+ SOCKFS.nextname.current = 0;
+ }
+ return 'socket[' + (SOCKFS.nextname.current++) + ']';
+ },
+ websocket_sock_ops:{
+ createPeer(sock, addr, port) {
+ var ws;
+
+ if (typeof addr == 'object') {
+ ws = addr;
+ addr = null;
+ port = null;
+ }
+
+ if (ws) {
+ // for sockets that've already connected (e.g. we're the server)
+ // we can inspect the _socket property for the address
+ if (ws._socket) {
+ addr = ws._socket.remoteAddress;
+ port = ws._socket.remotePort;
+ }
+ // if we're just now initializing a connection to the remote,
+ // inspect the url property
+ else {
+ var result = /ws[s]?:\/\/([^:]+):(\d+)/.exec(ws.url);
+ if (!result) {
+ throw new Error('WebSocket URL must be in the format ws(s)://address:port');
+ }
+ addr = result[1];
+ port = parseInt(result[2], 10);
+ }
+ } else {
+ // create the actual websocket object and connect
+ try {
+ // runtimeConfig gets set to true if WebSocket runtime configuration is available.
+ var runtimeConfig = (Module['websocket'] && ('object' === typeof Module['websocket']));
+
+ // The default value is 'ws://' the replace is needed because the compiler replaces '//' comments with '#'
+ // comments without checking context, so we'd end up with ws:#, the replace swaps the '#' for '//' again.
+ var url = 'ws:#'.replace('#', '//');
+
+ if (runtimeConfig) {
+ if("function"===typeof Module["websocket"]["url"]) {
+url = Module["websocket"]["url"](...arguments);
+}else if ("string" === typeof Module["websocket"]["url"]) {
+ url = Module['websocket']['url']; // Fetch runtime WebSocket URL config.
+ }
+ }
+
+ if (url === 'ws://' || url === 'wss://') { // Is the supplied URL config just a prefix, if so complete it.
+ var parts = addr.split('/');
+ url = url + parts[0] + ":" + port + "/" + parts.slice(1).join('/');
+ }
+
+ // Make the WebSocket subprotocol (Sec-WebSocket-Protocol) default to binary if no configuration is set.
+ var subProtocols = 'binary'; // The default value is 'binary'
+
+ if (runtimeConfig) {
+ if ('string' === typeof Module['websocket']['subprotocol']) {
+ subProtocols = Module['websocket']['subprotocol']; // Fetch runtime WebSocket subprotocol config.
+ }
+ }
+
+ // The default WebSocket options
+ var opts = undefined;
+
+ if (subProtocols !== 'null') {
+ // The regex trims the string (removes spaces at the beginning and end, then splits the string by
+ // , into an Array. Whitespace removal is important for Websockify and ws.
+ subProtocols = subProtocols.replace(/^ +| +$/g,"").split(/ *, */);
+
+ opts = subProtocols;
+ }
+
+ // some webservers (azure) does not support subprotocol header
+ if (runtimeConfig && null === Module['websocket']['subprotocol']) {
+ subProtocols = 'null';
+ opts = undefined;
+ }
+
+ // If node we use the ws library.
+ var WebSocketConstructor;
+ if (ENVIRONMENT_IS_NODE) {
+ WebSocketConstructor = /** @type{(typeof WebSocket)} */(require('ws'));
+ } else
+ {
+ WebSocketConstructor = WebSocket;
+ }
+ if (Module['websocket']['decorator']) {WebSocketConstructor = Module['websocket']['decorator'](WebSocketConstructor);}ws = new WebSocketConstructor(url, opts);
+ ws.binaryType = 'arraybuffer';
+ } catch (e) {
+ throw new FS.ErrnoError(23);
+ }
+ }
+
+ var peer = {
+ addr,
+ port,
+ socket: ws,
+ dgram_send_queue: []
+ };
+
+ SOCKFS.websocket_sock_ops.addPeer(sock, peer);
+ SOCKFS.websocket_sock_ops.handlePeerEvents(sock, peer);
+
+ // if this is a bound dgram socket, send the port number first to allow
+ // us to override the ephemeral port reported to us by remotePort on the
+ // remote end.
+ if (sock.type === 2 && typeof sock.sport != 'undefined') {
+ peer.dgram_send_queue.push(new Uint8Array([
+ 255, 255, 255, 255,
+ 'p'.charCodeAt(0), 'o'.charCodeAt(0), 'r'.charCodeAt(0), 't'.charCodeAt(0),
+ ((sock.sport & 0xff00) >> 8) , (sock.sport & 0xff)
+ ]));
+ }
+
+ return peer;
+ },
+ getPeer(sock, addr, port) {
+ return sock.peers[addr + ':' + port];
+ },
+ addPeer(sock, peer) {
+ sock.peers[peer.addr + ':' + peer.port] = peer;
+ },
+ removePeer(sock, peer) {
+ delete sock.peers[peer.addr + ':' + peer.port];
+ },
+ handlePeerEvents(sock, peer) {
+ var first = true;
+
+ var handleOpen = function () {
+
+ Module['websocket'].emit('open', sock.stream.fd);
+
+ try {
+ var queued = peer.dgram_send_queue.shift();
+ while (queued) {
+ peer.socket.send(queued);
+ queued = peer.dgram_send_queue.shift();
+ }
+ } catch (e) {
+ // not much we can do here in the way of proper error handling as we've already
+ // lied and said this data was sent. shut it down.
+ peer.socket.close();
+ }
+ };
+
+ function handleMessage(data) {
+ if (typeof data == 'string') {
+ var encoder = new TextEncoder(); // should be utf-8
+ data = encoder.encode(data); // make a typed array from the string
+ } else {
+ assert(data.byteLength !== undefined); // must receive an ArrayBuffer
+ if (data.byteLength == 0) {
+ // An empty ArrayBuffer will emit a pseudo disconnect event
+ // as recv/recvmsg will return zero which indicates that a socket
+ // has performed a shutdown although the connection has not been disconnected yet.
+ return;
+ }
+ data = new Uint8Array(data); // make a typed array view on the array buffer
+ }
+
+ // if this is the port message, override the peer's port with it
+ var wasfirst = first;
+ first = false;
+ if (wasfirst &&
+ data.length === 10 &&
+ data[0] === 255 && data[1] === 255 && data[2] === 255 && data[3] === 255 &&
+ data[4] === 'p'.charCodeAt(0) && data[5] === 'o'.charCodeAt(0) && data[6] === 'r'.charCodeAt(0) && data[7] === 't'.charCodeAt(0)) {
+ // update the peer's port and it's key in the peer map
+ var newport = ((data[8] << 8) | data[9]);
+ SOCKFS.websocket_sock_ops.removePeer(sock, peer);
+ peer.port = newport;
+ SOCKFS.websocket_sock_ops.addPeer(sock, peer);
+ return;
+ }
+
+ sock.recv_queue.push({ addr: peer.addr, port: peer.port, data: data });
+ Module['websocket'].emit('message', sock.stream.fd);
+ };
+
+ if (ENVIRONMENT_IS_NODE) {
+ peer.socket.on('open', handleOpen);
+ peer.socket.on('message', function(data, isBinary) {
+ if (!isBinary) {
+ return;
+ }
+ handleMessage((new Uint8Array(data)).buffer); // copy from node Buffer -> ArrayBuffer
+ });
+ peer.socket.on('close', function() {
+ Module['websocket'].emit('close', sock.stream.fd);
+ });
+ peer.socket.on('error', function(error) {
+ // Although the ws library may pass errors that may be more descriptive than
+ // ECONNREFUSED they are not necessarily the expected error code e.g.
+ // ENOTFOUND on getaddrinfo seems to be node.js specific, so using ECONNREFUSED
+ // is still probably the most useful thing to do.
+ sock.error = 14; // Used in getsockopt for SOL_SOCKET/SO_ERROR test.
+ Module['websocket'].emit('error', [sock.stream.fd, sock.error, 'ECONNREFUSED: Connection refused']);
+ // don't throw
+ });
+ } else {
+ peer.socket.onopen = handleOpen;
+ peer.socket.onclose = function() {
+ Module['websocket'].emit('close', sock.stream.fd);
+ };
+ peer.socket.onmessage = function peer_socket_onmessage(event) {
+ handleMessage(event.data);
+ };
+ peer.socket.onerror = function(error) {
+ // The WebSocket spec only allows a 'simple event' to be thrown on error,
+ // so we only really know as much as ECONNREFUSED.
+ sock.error = 14; // Used in getsockopt for SOL_SOCKET/SO_ERROR test.
+ Module['websocket'].emit('error', [sock.stream.fd, sock.error, 'ECONNREFUSED: Connection refused']);
+ };
+ }
+ },
+ poll(sock) {
+ if (sock.type === 1 && sock.server) {
+ // listen sockets should only say they're available for reading
+ // if there are pending clients.
+ return sock.pending.length ? (64 | 1) : 0;
+ }
+
+ var mask = 0;
+ var dest = sock.type === 1 ? // we only care about the socket state for connection-based sockets
+ SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport) :
+ null;
+
+ if (sock.recv_queue.length ||
+ !dest || // connection-less sockets are always ready to read
+ (dest && dest.socket.readyState === dest.socket.CLOSING) ||
+ (dest && dest.socket.readyState === dest.socket.CLOSED)) { // let recv return 0 once closed
+ mask |= (64 | 1);
+ }
+
+ if (!dest || // connection-less sockets are always ready to write
+ (dest && dest.socket.readyState === dest.socket.OPEN)) {
+ mask |= 4;
+ }
+
+ if ((dest && dest.socket.readyState === dest.socket.CLOSING) ||
+ (dest && dest.socket.readyState === dest.socket.CLOSED)) {
+ mask |= 16;
+ }
+
+ return mask;
+ },
+ ioctl(sock, request, arg) {
+ switch (request) {
+ case 21531:
+ var bytes = 0;
+ if (sock.recv_queue.length) {
+ bytes = sock.recv_queue[0].data.length;
+ }
+ HEAP32[((arg)>>2)] = bytes;
+ return 0;
+ default:
+ return 28;
+ }
+ },
+ close(sock) {
+ // if we've spawned a listen server, close it
+ if (sock.server) {
+ try {
+ sock.server.close();
+ } catch (e) {
+ }
+ sock.server = null;
+ }
+ // close any peer connections
+ var peers = Object.keys(sock.peers);
+ for (var i = 0; i < peers.length; i++) {
+ var peer = sock.peers[peers[i]];
+ try {
+ peer.socket.close();
+ } catch (e) {
+ }
+ SOCKFS.websocket_sock_ops.removePeer(sock, peer);
+ }
+ return 0;
+ },
+ bind(sock, addr, port) {
+ if (typeof sock.saddr != 'undefined' || typeof sock.sport != 'undefined') {
+ throw new FS.ErrnoError(28); // already bound
+ }
+ sock.saddr = addr;
+ sock.sport = port;
+ // in order to emulate dgram sockets, we need to launch a listen server when
+ // binding on a connection-less socket
+ // note: this is only required on the server side
+ if (sock.type === 2) {
+ // close the existing server if it exists
+ if (sock.server) {
+ sock.server.close();
+ sock.server = null;
+ }
+ // swallow error operation not supported error that occurs when binding in the
+ // browser where this isn't supported
+ try {
+ sock.sock_ops.listen(sock, 0);
+ } catch (e) {
+ if (!(e.name === 'ErrnoError')) throw e;
+ if (e.errno !== 138) throw e;
+ }
+ }
+ },
+ connect(sock, addr, port) {
+ if (sock.server) {
+ throw new FS.ErrnoError(138);
+ }
+
+ // TODO autobind
+ // if (!sock.addr && sock.type == 2) {
+ // }
+
+ // early out if we're already connected / in the middle of connecting
+ if (typeof sock.daddr != 'undefined' && typeof sock.dport != 'undefined') {
+ var dest = SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport);
+ if (dest) {
+ if (dest.socket.readyState === dest.socket.CONNECTING) {
+ throw new FS.ErrnoError(7);
+ } else {
+ throw new FS.ErrnoError(30);
+ }
+ }
+ }
+
+ // add the socket to our peer list and set our
+ // destination address / port to match
+ var peer = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port);
+ sock.daddr = peer.addr;
+ sock.dport = peer.port;
+
+ // always "fail" in non-blocking mode
+ throw new FS.ErrnoError(26);
+ },
+ listen(sock, backlog) {
+ if (!ENVIRONMENT_IS_NODE) {
+ throw new FS.ErrnoError(138);
+ }
+ if (sock.server) {
+ throw new FS.ErrnoError(28); // already listening
+ }
+ var WebSocketServer = require('ws').Server;
+ var host = sock.saddr;
+ if (Module['websocket']['serverDecorator']) {WebSocketServer = Module['websocket']['serverDecorator'](WebSocketServer);}sock.server = new WebSocketServer({
+ host,
+ port: sock.sport
+ // TODO support backlog
+ });
+ Module['websocket'].emit('listen', sock.stream.fd); // Send Event with listen fd.
+
+ sock.server.on('connection', function(ws) {
+ if (sock.type === 1) {
+ var newsock = SOCKFS.createSocket(sock.family, sock.type, sock.protocol);
+
+ // create a peer on the new socket
+ var peer = SOCKFS.websocket_sock_ops.createPeer(newsock, ws);
+ newsock.daddr = peer.addr;
+ newsock.dport = peer.port;
+
+ // push to queue for accept to pick up
+ sock.pending.push(newsock);
+ Module['websocket'].emit('connection', newsock.stream.fd);
+ } else {
+ // create a peer on the listen socket so calling sendto
+ // with the listen socket and an address will resolve
+ // to the correct client
+ SOCKFS.websocket_sock_ops.createPeer(sock, ws);
+ Module['websocket'].emit('connection', sock.stream.fd);
+ }
+ });
+ sock.server.on('close', function() {
+ Module['websocket'].emit('close', sock.stream.fd);
+ sock.server = null;
+ });
+ sock.server.on('error', function(error) {
+ // Although the ws library may pass errors that may be more descriptive than
+ // ECONNREFUSED they are not necessarily the expected error code e.g.
+ // ENOTFOUND on getaddrinfo seems to be node.js specific, so using EHOSTUNREACH
+ // is still probably the most useful thing to do. This error shouldn't
+ // occur in a well written app as errors should get trapped in the compiled
+ // app's own getaddrinfo call.
+ sock.error = 23; // Used in getsockopt for SOL_SOCKET/SO_ERROR test.
+ Module['websocket'].emit('error', [sock.stream.fd, sock.error, 'EHOSTUNREACH: Host is unreachable']);
+ // don't throw
+ });
+ },
+ accept(listensock) {
+ if (!listensock.server || !listensock.pending.length) {
+ throw new FS.ErrnoError(28);
+ }
+ var newsock = listensock.pending.shift();
+ newsock.stream.flags = listensock.stream.flags;
+ return newsock;
+ },
+ getname(sock, peer) {
+ var addr, port;
+ if (peer) {
+ if (sock.daddr === undefined || sock.dport === undefined) {
+ throw new FS.ErrnoError(53);
+ }
+ addr = sock.daddr;
+ port = sock.dport;
+ } else {
+ // TODO saddr and sport will be set for bind()'d UDP sockets, but what
+ // should we be returning for TCP sockets that've been connect()'d?
+ addr = sock.saddr || 0;
+ port = sock.sport || 0;
+ }
+ return { addr, port };
+ },
+ sendmsg(sock, buffer, offset, length, addr, port) {
+ if (sock.type === 2) {
+ // connection-less sockets will honor the message address,
+ // and otherwise fall back to the bound destination address
+ if (addr === undefined || port === undefined) {
+ addr = sock.daddr;
+ port = sock.dport;
+ }
+ // if there was no address to fall back to, error out
+ if (addr === undefined || port === undefined) {
+ throw new FS.ErrnoError(17);
+ }
+ } else {
+ // connection-based sockets will only use the bound
+ addr = sock.daddr;
+ port = sock.dport;
+ }
+
+ // find the peer for the destination address
+ var dest = SOCKFS.websocket_sock_ops.getPeer(sock, addr, port);
+
+ // early out if not connected with a connection-based socket
+ if (sock.type === 1) {
+ if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) {
+ throw new FS.ErrnoError(53);
+ } else if (dest.socket.readyState === dest.socket.CONNECTING) {
+ throw new FS.ErrnoError(6);
+ }
+ }
+
+ // create a copy of the incoming data to send, as the WebSocket API
+ // doesn't work entirely with an ArrayBufferView, it'll just send
+ // the entire underlying buffer
+ if (ArrayBuffer.isView(buffer)) {
+ offset += buffer.byteOffset;
+ buffer = buffer.buffer;
+ }
+
+ var data;
+ data = buffer.slice(offset, offset + length);
+
+ // if we're emulating a connection-less dgram socket and don't have
+ // a cached connection, queue the buffer to send upon connect and
+ // lie, saying the data was sent now.
+ if (sock.type === 2) {
+ if (!dest || dest.socket.readyState !== dest.socket.OPEN) {
+ // if we're not connected, open a new connection
+ if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) {
+ dest = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port);
+ }
+ dest.dgram_send_queue.push(data);
+ return length;
+ }
+ }
+
+ try {
+ // send the actual data
+ dest.socket.send(data);
+ return length;
+ } catch (e) {
+ throw new FS.ErrnoError(28);
+ }
+ },
+ recvmsg(sock, length, flags) {
+ // http://pubs.opengroup.org/onlinepubs/7908799/xns/recvmsg.html
+ if (sock.type === 1 && sock.server) {
+ // tcp servers should not be recv()'ing on the listen socket
+ throw new FS.ErrnoError(53);
+ }
+
+ var queued = sock.recv_queue.shift();
+ if (!queued) {
+ if (sock.type === 1) {
+ var dest = SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport);
+
+ if (!dest) {
+ // if we have a destination address but are not connected, error out
+ throw new FS.ErrnoError(53);
+ }
+ if (dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) {
+ // return null if the socket has closed
+ return null;
+ }
+ // else, our socket is in a valid state but truly has nothing available
+ throw new FS.ErrnoError(6);
+ }
+ throw new FS.ErrnoError(6);
+ }
+
+ // queued.data will be an ArrayBuffer if it's unadulterated, but if it's
+ // requeued TCP data it'll be an ArrayBufferView
+ var queuedLength = queued.data.byteLength || queued.data.length;
+ var queuedOffset = queued.data.byteOffset || 0;
+ var queuedBuffer = queued.data.buffer || queued.data;
+ var bytesRead = Math.min(length, queuedLength);
+ var res = {
+ buffer: new Uint8Array(queuedBuffer, queuedOffset, bytesRead),
+ addr: queued.addr,
+ port: queued.port
+ };
+
+ // push back any unread data for TCP connections
+ if (flags&2) {bytesRead = 0;} if (sock.type === 1 && bytesRead < queuedLength) {
+ var bytesRemaining = queuedLength - bytesRead;
+ queued.data = new Uint8Array(queuedBuffer, queuedOffset + bytesRead, bytesRemaining);
+ sock.recv_queue.unshift(queued);
+ }
+
+ return res;
+ },
},
- close: stream => {
- try {
- if (FS.isFile(stream.node.mode) && stream.nfd) {
- fs.closeSync(stream.nfd);
+ };
+
+ function getSocketFromFD(fd) {
+ var socket = SOCKFS.getSocket(fd);
+ if (!socket) throw new FS.ErrnoError(8);
+ return socket;
}
- } catch (e) {
- if (!e.code) throw e;
- throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
- }
- },
- read: (stream, buffer, offset, length, position) => {
- if (length === 0) return 0;
- try {
- return fs.readSync(stream.nfd, Buffer.from(buffer.buffer), offset, length, position);
- } catch (e) {
- throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
- }
- },
- write: (stream, buffer, offset, length, position) => {
- try {
- return fs.writeSync(stream.nfd, Buffer.from(buffer.buffer), offset, length, position);
- } catch (e) {
- throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
- }
+
+ var setErrNo = (value) => {
+ HEAP32[((___errno_location())>>2)] = value;
+ return value;
+ };
+ var Sockets = {
+ BUFFER_SIZE:10240,
+ MAX_BUFFER_SIZE:10485760,
+ nextFd:1,
+ fds:{
},
- llseek: (stream, offset, whence) => {
- var position = offset;
- if (whence === 1) {
- position += stream.position;
- } else if (whence === 2) {
- if (FS.isFile(stream.node.mode)) {
- try {
- var stat = fs.fstatSync(stream.nfd);
- position += stat.size;
- } catch (e) {
- throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
- }
- }
- }
- if (position < 0) {
- throw new FS.ErrnoError(28);
- }
- return position;
+ nextport:1,
+ maxport:65535,
+ peer:null,
+ connections:{
},
- mmap: (stream, length, position, prot, flags) => {
- if (!FS.isFile(stream.node.mode)) {
- throw new FS.ErrnoError(43);
- }
- var ptr = mmapAlloc(length);
- NODEFS.stream_ops.read(stream, HEAP8, ptr, length, position);
- return {
- ptr: ptr,
- allocated: true
- };
+ portmap:{
},
- msync: (stream, buffer, offset, length, mmapFlags) => {
- NODEFS.stream_ops.write(stream, buffer, 0, length, offset, false);
- return 0;
- }
- }
-};
-
-var FS = {
- root: null,
- mounts: [],
- devices: {},
- streams: [],
- nextInode: 1,
- nameTable: null,
- currentPath: "/",
- initialized: false,
- ignorePermissions: true,
- ErrnoError: null,
- genericErrors: {},
- filesystems: null,
- syncFSRequests: 0,
- lookupPath: (path, opts = {}) => {
- path = PATH_FS.resolve(path);
- if (!path) return {
- path: "",
- node: null
- };
- var defaults = {
- follow_mount: true,
- recurse_count: 0
+ localAddr:4261412874,
+ addrPool:[33554442,50331658,67108874,83886090,100663306,117440522,134217738,150994954,167772170,184549386,201326602,218103818,234881034],
};
- opts = Object.assign(defaults, opts);
- if (opts.recurse_count > 8) {
- throw new FS.ErrnoError(32);
- }
- var parts = path.split("/").filter((p => !!p));
- 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) {
- break;
- }
- current = FS.lookupNode(current, parts[i]);
- current_path = PATH.join2(current_path, parts[i]);
- if (FS.isMountpoint(current)) {
- if (!islast || islast && opts.follow_mount) {
- current = current.mounted.root;
- }
- }
- 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 + 1
- });
- current = lookup.node;
- if (count++ > 40) {
- throw new FS.ErrnoError(32);
- }
- }
- }
- }
- return {
- path: current_path,
- node: current
- };
- },
- getPath: 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: (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: node => {
- var hash = FS.hashName(node.parent.id, node.name);
- node.name_next = FS.nameTable[hash];
- FS.nameTable[hash] = node;
- },
- hashRemoveNode: 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: (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;
- }
- }
- return FS.lookup(parent, name);
- },
- createNode: (parent, name, mode, rdev) => {
- var node = new FS.FSNode(parent, name, mode, rdev);
- FS.hashAddNode(node);
- return node;
- },
- destroyNode: node => {
- FS.hashRemoveNode(node);
- },
- isRoot: node => node === node.parent,
- isMountpoint: node => !!node.mounted,
- isFile: mode => (mode & 61440) === 32768,
- isDir: mode => (mode & 61440) === 16384,
- isLink: mode => (mode & 61440) === 40960,
- isChrdev: mode => (mode & 61440) === 8192,
- isBlkdev: mode => (mode & 61440) === 24576,
- isFIFO: mode => (mode & 61440) === 4096,
- isSocket: mode => (mode & 49152) === 49152,
- flagsToPermissionString: flag => {
- var perms = [ "r", "w", "rw" ][flag & 3];
- if (flag & 512) {
- perms += "w";
- }
- return perms;
- },
- nodePermissions: (node, perms) => {
- if (FS.ignorePermissions) {
- return 0;
- }
- if (perms.includes("r") && !(node.mode & 292)) {
- return 2;
- } else if (perms.includes("w") && !(node.mode & 146)) {
- return 2;
- } else if (perms.includes("x") && !(node.mode & 73)) {
- return 2;
- }
- return 0;
- },
- mayLookup: dir => {
- var errCode = FS.nodePermissions(dir, "x");
- if (errCode) return errCode;
- if (!dir.node_ops.lookup) return 2;
- return 0;
- },
- mayCreate: (dir, name) => {
- try {
- var node = FS.lookupNode(dir, name);
- return 20;
- } catch (e) {}
- return FS.nodePermissions(dir, "wx");
- },
- mayDelete: (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: (node, flags) => {
- if (!node) {
- return 44;
- }
- if (FS.isLink(node.mode)) {
- return 32;
- } else if (FS.isDir(node.mode)) {
- if (FS.flagsToPermissionString(flags) !== "r" || flags & 512) {
- return 31;
- }
- }
- return FS.nodePermissions(node, FS.flagsToPermissionString(flags));
- },
- MAX_OPEN_FDS: 4096,
- nextfd: () => {
- for (var fd = 0; fd <= FS.MAX_OPEN_FDS; fd++) {
- if (!FS.streams[fd]) {
- return fd;
- }
- }
- throw new FS.ErrnoError(33);
- },
- getStreamChecked: fd => {
- var stream = FS.getStream(fd);
- if (!stream) {
- throw new FS.ErrnoError(8);
- }
- return stream;
- },
- getStream: fd => FS.streams[fd],
- createStream: (stream, fd = -1) => {
- if (!FS.FSStream) {
- FS.FSStream = function() {
- this.shared = {};
- };
- FS.FSStream.prototype = {};
- Object.defineProperties(FS.FSStream.prototype, {
- object: {
- get() {
- return this.node;
- },
- set(val) {
- this.node = val;
- }
- },
- isRead: {
- get() {
- return (this.flags & 2097155) !== 1;
- }
- },
- isWrite: {
- get() {
- return (this.flags & 2097155) !== 0;
- }
- },
- isAppend: {
- get() {
- return this.flags & 1024;
- }
- },
- flags: {
- get() {
- return this.shared.flags;
- },
- set(val) {
- this.shared.flags = val;
- }
- },
- position: {
- get() {
- return this.shared.position;
- },
- set(val) {
- this.shared.position = val;
- }
- }
- });
- }
- stream = Object.assign(new FS.FSStream, stream);
- if (fd == -1) {
- fd = FS.nextfd();
- }
- stream.fd = fd;
- FS.streams[fd] = stream;
- return stream;
- },
- closeStream: fd => {
- FS.streams[fd] = null;
- },
- chrdev_stream_ops: {
- open: stream => {
- var device = FS.getDevice(stream.node.rdev);
- stream.stream_ops = device.stream_ops;
- if (stream.stream_ops.open) {
- stream.stream_ops.open(stream);
- }
- },
- llseek: () => {
- throw new FS.ErrnoError(70);
- }
- },
- major: dev => dev >> 8,
- minor: dev => dev & 255,
- makedev: (ma, mi) => ma << 8 | mi,
- registerDevice: (dev, ops) => {
- FS.devices[dev] = {
- stream_ops: ops
- };
- },
- getDevice: dev => FS.devices[dev],
- getMounts: 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: (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);
- }
- }
- mounts.forEach((mount => {
- if (!mount.type.syncfs) {
- return done(null);
- }
- mount.type.syncfs(mount, populate, done);
- }));
- },
- mount: (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;
- 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: []
- };
- var mountRoot = type.mount(mount);
- mountRoot.mount = mount;
- mount.root = mountRoot;
- if (root) {
- FS.root = mountRoot;
- } else if (node) {
- node.mounted = mount;
- if (node.mount) {
- node.mount.mounts.push(mount);
- }
- }
- return mountRoot;
- },
- unmount: mountpoint => {
- var lookup = FS.lookupPath(mountpoint, {
- follow_mount: false
- });
- if (!FS.isMountpoint(lookup.node)) {
- throw new FS.ErrnoError(28);
- }
- var node = lookup.node;
- var mount = node.mounted;
- var mounts = FS.getMounts(mount);
- Object.keys(FS.nameTable).forEach((hash => {
- var current = FS.nameTable[hash];
- while (current) {
- var next = current.name_next;
- if (mounts.includes(current.mount)) {
- FS.destroyNode(current);
- }
- current = next;
- }
- }));
- node.mounted = null;
- var idx = node.mount.mounts.indexOf(mount);
- node.mount.mounts.splice(idx, 1);
- },
- lookup: (parent, name) => parent.node_ops.lookup(parent, name),
- mknod: (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: (path, mode) => {
- mode = mode !== undefined ? mode : 438;
- mode &= 4095;
- mode |= 32768;
- return FS.mknod(path, mode, 0);
- },
- mkdir: (path, mode) => {
- mode = mode !== undefined ? mode : 511;
- mode &= 511 | 512;
- mode |= 16384;
- return FS.mknod(path, mode, 0);
- },
- mkdirTree: (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: (path, mode, dev) => {
- if (typeof dev == "undefined") {
- dev = mode;
- mode = 438;
- }
- mode |= 8192;
- return FS.mknod(path, mode, dev);
- },
- symlink: (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: (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);
- var lookup, old_dir, new_dir;
- 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);
- if (old_dir.mount !== new_dir.mount) {
- throw new FS.ErrnoError(75);
- }
- var old_node = FS.lookupNode(old_dir, old_name);
- var relative = PATH_FS.relative(old_path, new_dirname);
- if (relative.charAt(0) !== ".") {
- throw new FS.ErrnoError(28);
- }
- relative = PATH_FS.relative(new_path, old_dirname);
- if (relative.charAt(0) !== ".") {
- throw new FS.ErrnoError(55);
- }
- var new_node;
- try {
- new_node = FS.lookupNode(new_dir, new_name);
- } catch (e) {}
- if (old_node === new_node) {
- return;
- }
- var isdir = FS.isDir(old_node.mode);
- var errCode = FS.mayDelete(old_dir, old_name, isdir);
- if (errCode) {
- throw new FS.ErrnoError(errCode);
- }
- 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 (new_dir !== old_dir) {
- errCode = FS.nodePermissions(old_dir, "w");
- if (errCode) {
- throw new FS.ErrnoError(errCode);
- }
- }
- FS.hashRemoveNode(old_node);
- try {
- old_dir.node_ops.rename(old_node, new_dir, new_name);
- } catch (e) {
- throw e;
- } finally {
- FS.hashAddNode(old_node);
- }
- },
- rmdir: 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);
- }
- parent.node_ops.rmdir(parent, name);
- FS.destroyNode(node);
- },
- readdir: 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: path => {
- var lookup = FS.lookupPath(path, {
- parent: true
- });
- var parent = lookup.node;
- if (!parent) {
- throw new FS.ErrnoError(44);
- }
- var name = PATH.basename(path);
- var node = FS.lookupNode(parent, name);
- var errCode = FS.mayDelete(parent, name, false);
- if (errCode) {
- throw new FS.ErrnoError(errCode);
- }
- if (!parent.node_ops.unlink) {
- throw new FS.ErrnoError(63);
- }
- if (FS.isMountpoint(node)) {
- throw new FS.ErrnoError(10);
- }
- parent.node_ops.unlink(parent, name);
- FS.destroyNode(node);
- },
- readlink: 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: (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: path => FS.stat(path, true),
- chmod: (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: (path, mode) => {
- FS.chmod(path, mode, true);
- },
- fchmod: (fd, mode) => {
- var stream = FS.getStreamChecked(fd);
- FS.chmod(stream.node, mode);
- },
- chown: (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()
- });
- },
- lchown: (path, uid, gid) => {
- FS.chown(path, uid, gid, true);
- },
- fchown: (fd, uid, gid) => {
- var stream = FS.getStreamChecked(fd);
- FS.chown(stream.node, uid, gid);
- },
- truncate: (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: (fd, len) => {
- var stream = FS.getStreamChecked(fd);
- if ((stream.flags & 2097155) === 0) {
- throw new FS.ErrnoError(28);
- }
- FS.truncate(stream.node, len);
- },
- utime: (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: (path, flags, mode) => {
- if (path === "") {
- throw new FS.ErrnoError(44);
- }
- flags = typeof flags == "string" ? FS_modeStringToFlags(flags) : flags;
- mode = typeof mode == "undefined" ? 438 : 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) {}
- }
- var created = false;
- if (flags & 64) {
- if (node) {
- if (flags & 128) {
- throw new FS.ErrnoError(20);
- }
- } else {
- node = FS.mknod(path, mode, 0);
- created = true;
- }
- }
- if (!node) {
- throw new FS.ErrnoError(44);
- }
- if (FS.isChrdev(node.mode)) {
- flags &= ~512;
- }
- if (flags & 65536 && !FS.isDir(node.mode)) {
- throw new FS.ErrnoError(54);
- }
- if (!created) {
- var errCode = FS.mayOpen(node, flags);
- if (errCode) {
- throw new FS.ErrnoError(errCode);
- }
- }
- if (flags & 512 && !created) {
- FS.truncate(node, 0);
- }
- flags &= ~(128 | 512 | 131072);
- var stream = FS.createStream({
- node: node,
- path: FS.getPath(node),
- flags: flags,
- seekable: true,
- position: 0,
- stream_ops: node.stream_ops,
- ungotten: [],
- error: false
- });
- 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;
- }
- }
- return stream;
- },
- close: stream => {
- if (FS.isClosed(stream)) {
- throw new FS.ErrnoError(8);
- }
- if (stream.getdents) stream.getdents = null;
- try {
- if (stream.stream_ops.close) {
- stream.stream_ops.close(stream);
- }
- } catch (e) {
- throw e;
- } finally {
- FS.closeStream(stream.fd);
- }
- stream.fd = null;
- },
- isClosed: stream => stream.fd === null,
- llseek: (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: (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: (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) {
- 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;
- return bytesWritten;
- },
- allocate: (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: (stream, length, position, prot, flags) => {
- 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, length, position, prot, flags);
- },
- msync: (stream, buffer, offset, length, mmapFlags) => {
- if (!stream.stream_ops.msync) {
- return 0;
- }
- return stream.stream_ops.msync(stream, buffer, offset, length, mmapFlags);
- },
- munmap: stream => 0,
- ioctl: (stream, cmd, arg) => {
- if (!stream.stream_ops.ioctl) {
- throw new FS.ErrnoError(59);
- }
- return stream.stream_ops.ioctl(stream, cmd, arg);
- },
- readFile: (path, 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: (path, data, 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: () => FS.currentPath,
- chdir: 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: () => {
- FS.mkdir("/tmp");
- FS.mkdir("/home");
- FS.mkdir("/home/web_user");
- },
- createDefaultDevices: () => {
- FS.mkdir("/dev");
- FS.registerDevice(FS.makedev(1, 3), {
- read: () => 0,
- write: (stream, buffer, offset, length, pos) => length
- });
- FS.mkdev("/dev/null", FS.makedev(1, 3));
- 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));
- var randomBuffer = new Uint8Array(1024), randomLeft = 0;
- var randomByte = () => {
- if (randomLeft === 0) {
- randomLeft = randomFill(randomBuffer).byteLength;
- }
- return randomBuffer[--randomLeft];
- };
- FS.createDevice("/dev", "random", randomByte);
- FS.createDevice("/dev", "urandom", randomByte);
- FS.mkdir("/dev/shm");
- FS.mkdir("/dev/shm/tmp");
- },
- createSpecialDirectories: () => {
- FS.mkdir("/proc");
- var proc_self = FS.mkdir("/proc/self");
- FS.mkdir("/proc/self/fd");
- FS.mount({
- mount: () => {
- var node = FS.createNode(proc_self, "fd", 16384 | 511, 73);
- node.node_ops = {
- lookup: (parent, name) => {
- var fd = +name;
- var stream = FS.getStreamChecked(fd);
- var ret = {
- parent: null,
- mount: {
- mountpoint: "fake"
- },
- node_ops: {
- readlink: () => stream.path
- }
- };
- ret.parent = ret;
- return ret;
- }
+
+ var inetPton4 = (str) => {
+ var b = str.split('.');
+ for (var i = 0; i < 4; i++) {
+ var tmp = Number(b[i]);
+ if (isNaN(tmp)) return null;
+ b[i] = tmp;
+ }
+ return (b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24)) >>> 0;
};
- return node;
- }
- }, {}, "/proc/self/fd");
- },
- createStandardStreams: () => {
- 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");
- }
- var stdin = FS.open("/dev/stdin", 0);
- var stdout = FS.open("/dev/stdout", 1);
- var stderr = FS.open("/dev/stderr", 1);
- },
- ensureErrnoError: () => {
- if (FS.ErrnoError) return;
- FS.ErrnoError = function ErrnoError(errno, node) {
- this.name = "ErrnoError";
- this.node = node;
- this.setErrno = function(errno) {
- this.errno = errno;
- };
- this.setErrno(errno);
- this.message = "FS error";
- };
- FS.ErrnoError.prototype = new Error;
- FS.ErrnoError.prototype.constructor = FS.ErrnoError;
- [ 44 ].forEach((code => {
- FS.genericErrors[code] = new FS.ErrnoError(code);
- FS.genericErrors[code].stack = "";
- }));
- },
- staticInit: () => {
- FS.ensureErrnoError();
- FS.nameTable = new Array(4096);
- FS.mount(MEMFS, {}, "/");
- FS.createDefaultDirectories();
- FS.createDefaultDevices();
- FS.createSpecialDirectories();
- FS.filesystems = {
- "MEMFS": MEMFS,
- "NODEFS": NODEFS
- };
- },
- init: (input, output, error) => {
- FS.init.initialized = true;
- FS.ensureErrnoError();
- Module["stdin"] = input || Module["stdin"];
- Module["stdout"] = output || Module["stdout"];
- Module["stderr"] = error || Module["stderr"];
- FS.createStandardStreams();
- },
- quit: () => {
- FS.init.initialized = false;
- _fflush(0);
- for (var i = 0; i < FS.streams.length; i++) {
- var stream = FS.streams[i];
- if (!stream) {
- continue;
- }
- FS.close(stream);
- }
- },
- findObject: (path, dontResolveLastLink) => {
- var ret = FS.analyzePath(path, dontResolveLastLink);
- if (!ret.exists) {
- return null;
- }
- return ret.object;
- },
- analyzePath: (path, dontResolveLastLink) => {
- 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: (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) {}
- parent = current;
- }
- return current;
- },
- createFile: (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: (parent, name, data, canRead, canWrite, canOwn) => {
- var path = name;
- if (parent) {
- parent = typeof parent == "string" ? parent : FS.getPath(parent);
- path = name ? PATH.join2(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;
- }
- 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: (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);
- FS.registerDevice(dev, {
- open: stream => {
- stream.seekable = false;
- },
- close: stream => {
- if (output && output.buffer && output.buffer.length) {
- output(10);
- }
- },
- read: (stream, buffer, offset, length, pos) => {
- 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: (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: 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_) {
- try {
- 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: (parent, name, url, canRead, canWrite) => {
- function LazyUint8Array() {
- this.lengthKnown = false;
- this.chunks = [];
- }
- LazyUint8Array.prototype.get = 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() {
- 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;
- if (!hasByteServing) chunkSize = datalength;
- var doXHR = (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!");
- var xhr = new XMLHttpRequest;
- xhr.open("GET", url, false);
- if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to);
- 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(xhr.response || []);
- }
- return intArrayFromString(xhr.responseText || "", true);
- };
- var lazyArray = this;
- lazyArray.setDataGetter((chunkNum => {
- var start = chunkNum * chunkSize;
- var end = (chunkNum + 1) * chunkSize - 1;
- end = Math.min(end, datalength - 1);
- 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) {
- chunkSize = datalength = 1;
- 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: function() {
- if (!this.lengthKnown) {
- this.cacheLength();
+
+
+ /** @suppress {checkTypes} */
+ var jstoi_q = (str) => parseInt(str);
+ var inetPton6 = (str) => {
+ var words;
+ var w, offset, z, i;
+ /* http://home.deds.nl/~aeron/regex/ */
+ var valid6regx = /^((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\3)::|:\b|$))|(?!\2\3)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i
+ var parts = [];
+ if (!valid6regx.test(str)) {
+ return null;
}
- return this._length;
- }
- },
- chunkSize: {
- get: function() {
- if (!this.lengthKnown) {
- this.cacheLength();
+ if (str === "::") {
+ return [0, 0, 0, 0, 0, 0, 0, 0];
}
- 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);
- if (properties.contents) {
- node.contents = properties.contents;
- } else if (properties.url) {
- node.contents = null;
- node.url = properties.url;
- }
- Object.defineProperties(node, {
- usedBytes: {
- get: function() {
- return this.contents.length;
- }
- }
- });
- var stream_ops = {};
- var keys = Object.keys(node.stream_ops);
- keys.forEach((key => {
- var fn = node.stream_ops[key];
- stream_ops[key] = function forceLoadLazyFile() {
- FS.forceLoadFile(node);
- return fn.apply(null, arguments);
- };
- }));
- function writeChunks(stream, buffer, offset, length, position) {
- var contents = stream.node.contents;
- if (position >= contents.length) return 0;
- var size = Math.min(contents.length - position, length);
- if (contents.slice) {
- for (var i = 0; i < size; i++) {
- buffer[offset + i] = contents[position + i];
- }
- } else {
- for (var i = 0; i < size; i++) {
- buffer[offset + i] = contents.get(position + i);
- }
- }
- return size;
- }
- stream_ops.read = (stream, buffer, offset, length, position) => {
- FS.forceLoadFile(node);
- return writeChunks(stream, buffer, offset, length, position);
- };
- stream_ops.mmap = (stream, length, position, prot, flags) => {
- FS.forceLoadFile(node);
- var ptr = mmapAlloc(length);
- if (!ptr) {
- throw new FS.ErrnoError(48);
- }
- writeChunks(stream, HEAP8, ptr, length, position);
- return {
- ptr: ptr,
- allocated: true
- };
- };
- node.stream_ops = stream_ops;
- return node;
- }
-};
-
-Module["FS"] = FS;
-
-var SYSCALLS = {
- DEFAULT_POLLMASK: 5,
- calculateAt: function(dirfd, path, allowEmpty) {
- if (PATH.isAbs(path)) {
- return path;
- }
- var dir;
- if (dirfd === -100) {
- dir = FS.cwd();
- } else {
- var dirstream = SYSCALLS.getStreamFromFD(dirfd);
- 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))) {
- return -54;
- }
- throw e;
- }
- HEAP32[buf >> 2] = stat.dev;
- HEAP32[buf + 4 >> 2] = stat.mode;
- HEAPU32[buf + 8 >> 2] = stat.nlink;
- HEAP32[buf + 12 >> 2] = stat.uid;
- HEAP32[buf + 16 >> 2] = stat.gid;
- HEAP32[buf + 20 >> 2] = stat.rdev;
- tempI64 = [ stat.size >>> 0, (tempDouble = stat.size, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? +Math.floor(tempDouble / 4294967296) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ],
- HEAP32[buf + 24 >> 2] = tempI64[0], HEAP32[buf + 28 >> 2] = tempI64[1];
- HEAP32[buf + 32 >> 2] = 4096;
- HEAP32[buf + 36 >> 2] = stat.blocks;
- var atime = stat.atime.getTime();
- var mtime = stat.mtime.getTime();
- var ctime = stat.ctime.getTime();
- tempI64 = [ Math.floor(atime / 1e3) >>> 0, (tempDouble = Math.floor(atime / 1e3),
- +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? +Math.floor(tempDouble / 4294967296) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ],
- HEAP32[buf + 40 >> 2] = tempI64[0], HEAP32[buf + 44 >> 2] = tempI64[1];
- HEAPU32[buf + 48 >> 2] = atime % 1e3 * 1e3;
- tempI64 = [ Math.floor(mtime / 1e3) >>> 0, (tempDouble = Math.floor(mtime / 1e3),
- +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? +Math.floor(tempDouble / 4294967296) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ],
- HEAP32[buf + 56 >> 2] = tempI64[0], HEAP32[buf + 60 >> 2] = tempI64[1];
- HEAPU32[buf + 64 >> 2] = mtime % 1e3 * 1e3;
- tempI64 = [ Math.floor(ctime / 1e3) >>> 0, (tempDouble = Math.floor(ctime / 1e3),
- +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? +Math.floor(tempDouble / 4294967296) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ],
- HEAP32[buf + 72 >> 2] = tempI64[0], HEAP32[buf + 76 >> 2] = tempI64[1];
- HEAPU32[buf + 80 >> 2] = ctime % 1e3 * 1e3;
- tempI64 = [ stat.ino >>> 0, (tempDouble = stat.ino, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? +Math.floor(tempDouble / 4294967296) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ],
- HEAP32[buf + 88 >> 2] = tempI64[0], HEAP32[buf + 92 >> 2] = tempI64[1];
- return 0;
- },
- doMsync: function(addr, stream, len, flags, offset) {
- if (!FS.isFile(stream.node.mode)) {
- throw new FS.ErrnoError(43);
- }
- if (flags & 2) {
- return 0;
- }
- var buffer = HEAPU8.slice(addr, addr + len);
- FS.msync(stream, buffer, offset, len, flags);
- },
- varargs: undefined,
- get() {
- SYSCALLS.varargs += 4;
- var ret = HEAP32[SYSCALLS.varargs - 4 >> 2];
- return ret;
- },
- getStr(ptr) {
- var ret = UTF8ToString(ptr);
- return ret;
- },
- getStreamFromFD: function(fd) {
- var stream = FS.getStreamChecked(fd);
- return stream;
- }
-};
-
-function ___syscall__newselect(nfds, readfds, writefds, exceptfds, timeout) {
- try {
- var total = 0;
- var srcReadLow = readfds ? HEAP32[readfds >> 2] : 0, srcReadHigh = readfds ? HEAP32[readfds + 4 >> 2] : 0;
- var srcWriteLow = writefds ? HEAP32[writefds >> 2] : 0, srcWriteHigh = writefds ? HEAP32[writefds + 4 >> 2] : 0;
- var srcExceptLow = exceptfds ? HEAP32[exceptfds >> 2] : 0, srcExceptHigh = exceptfds ? HEAP32[exceptfds + 4 >> 2] : 0;
- var dstReadLow = 0, dstReadHigh = 0;
- var dstWriteLow = 0, dstWriteHigh = 0;
- var dstExceptLow = 0, dstExceptHigh = 0;
- var allLow = (readfds ? HEAP32[readfds >> 2] : 0) | (writefds ? HEAP32[writefds >> 2] : 0) | (exceptfds ? HEAP32[exceptfds >> 2] : 0);
- var allHigh = (readfds ? HEAP32[readfds + 4 >> 2] : 0) | (writefds ? HEAP32[writefds + 4 >> 2] : 0) | (exceptfds ? HEAP32[exceptfds + 4 >> 2] : 0);
- var check = function(fd, low, high, val) {
- return fd < 32 ? low & val : high & val;
- };
- for (var fd = 0; fd < nfds; fd++) {
- var mask = 1 << fd % 32;
- if (!check(fd, allLow, allHigh, mask)) {
- continue;
- }
- var stream = SYSCALLS.getStreamFromFD(fd);
- var flags = SYSCALLS.DEFAULT_POLLMASK;
- if (stream.stream_ops?.poll) {
- var timeoutInMillis = -1;
- if (timeout) {
- var tv_sec = readfds ? HEAP32[timeout >> 2] : 0, tv_usec = readfds ? HEAP32[timeout + 8 >> 2] : 0;
- timeoutInMillis = (tv_sec + tv_usec / 1e6) * 1e3;
- }
- flags = stream.stream_ops.poll(stream, timeoutInMillis);
- }
- if (flags & 1 && check(fd, srcReadLow, srcReadHigh, mask)) {
- fd < 32 ? dstReadLow = dstReadLow | mask : dstReadHigh = dstReadHigh | mask;
- total++;
- }
- if (flags & 4 && check(fd, srcWriteLow, srcWriteHigh, mask)) {
- fd < 32 ? dstWriteLow = dstWriteLow | mask : dstWriteHigh = dstWriteHigh | mask;
- total++;
- }
- if (flags & 2 && check(fd, srcExceptLow, srcExceptHigh, mask)) {
- fd < 32 ? dstExceptLow = dstExceptLow | mask : dstExceptHigh = dstExceptHigh | mask;
- total++;
- }
- }
- if (readfds) {
- HEAP32[readfds >> 2] = dstReadLow;
- HEAP32[readfds + 4 >> 2] = dstReadHigh;
- }
- if (writefds) {
- HEAP32[writefds >> 2] = dstWriteLow;
- HEAP32[writefds + 4 >> 2] = dstWriteHigh;
- }
- if (exceptfds) {
- HEAP32[exceptfds >> 2] = dstExceptLow;
- HEAP32[exceptfds + 4 >> 2] = dstExceptHigh;
- }
- return total;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-var SOCKFS = {
- mount(mount) {
- Module["websocket"] = Module["websocket"] && "object" === typeof Module["websocket"] ? Module["websocket"] : {};
- Module["websocket"]._callbacks = {};
- Module["websocket"]["on"] = function(event, callback) {
- if ("function" === typeof callback) {
- this._callbacks[event] = callback;
- }
- return this;
- };
- Module["websocket"].emit = function(event, param) {
- if ("function" === typeof this._callbacks[event]) {
- this._callbacks[event].call(this, param);
- }
- };
- return FS.createNode(null, "/", 16384 | 511, 0);
- },
- createSocket(family, type, protocol) {
- type &= ~526336;
- var streaming = type == 1;
- if (streaming && protocol && protocol != 6) {
- throw new FS.ErrnoError(66);
- }
- var sock = {
- family: family,
- type: type,
- protocol: protocol,
- server: null,
- error: null,
- peers: {},
- pending: [],
- recv_queue: [],
- sock_ops: SOCKFS.websocket_sock_ops
- };
- var name = SOCKFS.nextname();
- var node = FS.createNode(SOCKFS.root, name, 49152, 0);
- node.sock = sock;
- var stream = FS.createStream({
- path: name,
- node: node,
- flags: 2,
- seekable: false,
- stream_ops: SOCKFS.stream_ops
- });
- sock.stream = stream;
- return sock;
- },
- getSocket(fd) {
- var stream = FS.getStream(fd);
- if (!stream || !FS.isSocket(stream.node.mode)) {
- return null;
- }
- return stream.node.sock;
- },
- stream_ops: {
- poll(stream) {
- var sock = stream.node.sock;
- return sock.sock_ops.poll(sock);
- },
- ioctl(stream, request, varargs) {
- var sock = stream.node.sock;
- return sock.sock_ops.ioctl(sock, request, varargs);
- },
- read(stream, buffer, offset, length, position) {
- var sock = stream.node.sock;
- var msg = sock.sock_ops.recvmsg(sock, length);
- if (!msg) {
- return 0;
- }
- buffer.set(msg.buffer, offset);
- return msg.buffer.length;
- },
- write(stream, buffer, offset, length, position) {
- var sock = stream.node.sock;
- return sock.sock_ops.sendmsg(sock, buffer, offset, length);
- },
- close(stream) {
- var sock = stream.node.sock;
- sock.sock_ops.close(sock);
- }
- },
- nextname() {
- if (!SOCKFS.nextname.current) {
- SOCKFS.nextname.current = 0;
- }
- return "socket[" + SOCKFS.nextname.current++ + "]";
- },
- websocket_sock_ops: {
- createPeer(sock, addr, port) {
- var ws;
- if (typeof addr == "object") {
- ws = addr;
- addr = null;
- port = null;
- }
- if (ws) {
- if (ws._socket) {
- addr = ws._socket.remoteAddress;
- port = ws._socket.remotePort;
- } else {
- var result = /ws[s]?:\/\/([^:]+):(\d+)/.exec(ws.url);
- if (!result) {
- throw new Error("WebSocket URL must be in the format ws(s)://address:port");
- }
- addr = result[1];
- port = parseInt(result[2], 10);
- }
- } else {
- try {
- var runtimeConfig = Module["websocket"] && "object" === typeof Module["websocket"];
- var url = "ws:#".replace("#", "//");
- if (runtimeConfig) {
- if("function"===typeof Module["websocket"]["url"]) {
-url = Module["websocket"]["url"](...arguments);
-}else if ("string" === typeof Module["websocket"]["url"]) {
- url = Module["websocket"]["url"];
+ // Z placeholder to keep track of zeros when splitting the string on ":"
+ if (str.startsWith("::")) {
+ str = str.replace("::", "Z:"); // leading zeros case
+ } else {
+ str = str.replace("::", ":Z:");
}
- }
- if (url === "ws://" || url === "wss://") {
- var parts = addr.split("/");
- url = url + parts[0] + ":" + port + "/" + parts.slice(1).join("/");
- }
- var subProtocols = "binary";
- if (runtimeConfig) {
- if ("string" === typeof Module["websocket"]["subprotocol"]) {
- subProtocols = Module["websocket"]["subprotocol"];
+
+ if (str.indexOf(".") > 0) {
+ // parse IPv4 embedded stress
+ str = str.replace(new RegExp('[.]', 'g'), ":");
+ words = str.split(":");
+ words[words.length-4] = jstoi_q(words[words.length-4]) + jstoi_q(words[words.length-3])*256;
+ words[words.length-3] = jstoi_q(words[words.length-2]) + jstoi_q(words[words.length-1])*256;
+ words = words.slice(0, words.length-2);
+ } else {
+ words = str.split(":");
}
- }
- var opts = undefined;
- if (subProtocols !== "null") {
- subProtocols = subProtocols.replace(/^ +| +$/g, "").split(/ *, */);
- opts = subProtocols;
- }
- if (runtimeConfig && null === Module["websocket"]["subprotocol"]) {
- subProtocols = "null";
- opts = undefined;
- }
- var WebSocketConstructor;
- if (ENVIRONMENT_IS_NODE) {
- WebSocketConstructor = require("ws");
- } else {
- WebSocketConstructor = WebSocket;
- }
- if (Module['websocket']['decorator']) {WebSocketConstructor = Module['websocket']['decorator'](WebSocketConstructor);}ws = new WebSocketConstructor(url, opts);
- ws.binaryType = "arraybuffer";
- } catch (e) {
- throw new FS.ErrnoError(23);
- }
- }
- var peer = {
- addr: addr,
- port: port,
- socket: ws,
- dgram_send_queue: []
- };
- SOCKFS.websocket_sock_ops.addPeer(sock, peer);
- SOCKFS.websocket_sock_ops.handlePeerEvents(sock, peer);
- if (sock.type === 2 && typeof sock.sport != "undefined") {
- peer.dgram_send_queue.push(new Uint8Array([ 255, 255, 255, 255, "p".charCodeAt(0), "o".charCodeAt(0), "r".charCodeAt(0), "t".charCodeAt(0), (sock.sport & 65280) >> 8, sock.sport & 255 ]));
- }
- return peer;
- },
- getPeer(sock, addr, port) {
- return sock.peers[addr + ":" + port];
- },
- addPeer(sock, peer) {
- sock.peers[peer.addr + ":" + peer.port] = peer;
- },
- removePeer(sock, peer) {
- delete sock.peers[peer.addr + ":" + peer.port];
- },
- handlePeerEvents(sock, peer) {
- var first = true;
- var handleOpen = function() {
- Module["websocket"].emit("open", sock.stream.fd);
- try {
- var queued = peer.dgram_send_queue.shift();
- while (queued) {
- peer.socket.send(queued);
- queued = peer.dgram_send_queue.shift();
- }
- } catch (e) {
- peer.socket.close();
- }
- };
- function handleMessage(data) {
- if (typeof data == "string") {
- var encoder = new TextEncoder;
- data = encoder.encode(data);
- } else {
- assert(data.byteLength !== undefined);
- if (data.byteLength == 0) {
- return;
- }
- data = new Uint8Array(data);
- }
- var wasfirst = first;
- first = false;
- if (wasfirst && data.length === 10 && data[0] === 255 && data[1] === 255 && data[2] === 255 && data[3] === 255 && data[4] === "p".charCodeAt(0) && data[5] === "o".charCodeAt(0) && data[6] === "r".charCodeAt(0) && data[7] === "t".charCodeAt(0)) {
- var newport = data[8] << 8 | data[9];
- SOCKFS.websocket_sock_ops.removePeer(sock, peer);
- peer.port = newport;
- SOCKFS.websocket_sock_ops.addPeer(sock, peer);
- return;
- }
- sock.recv_queue.push({
- addr: peer.addr,
- port: peer.port,
- data: data
- });
- Module["websocket"].emit("message", sock.stream.fd);
- }
- if (ENVIRONMENT_IS_NODE) {
- peer.socket.on("open", handleOpen);
- peer.socket.on("message", (function(data, isBinary) {
- if (!isBinary) {
- return;
- }
- handleMessage(new Uint8Array(data).buffer);
- }));
- peer.socket.on("close", (function() {
- Module["websocket"].emit("close", sock.stream.fd);
- }));
- peer.socket.on("error", (function(error) {
- sock.error = 14;
- Module["websocket"].emit("error", [ sock.stream.fd, sock.error, "ECONNREFUSED: Connection refused" ]);
- }));
- } else {
- peer.socket.onopen = handleOpen;
- peer.socket.onclose = function() {
- Module["websocket"].emit("close", sock.stream.fd);
- };
- peer.socket.onmessage = function peer_socket_onmessage(event) {
- handleMessage(event.data);
+
+ offset = 0; z = 0;
+ for (w=0; w < words.length; w++) {
+ if (typeof words[w] == 'string') {
+ if (words[w] === 'Z') {
+ // compressed zeros - write appropriate number of zero words
+ for (z = 0; z < (8 - words.length+1); z++) {
+ parts[w+z] = 0;
+ }
+ offset = z-1;
+ } else {
+ // parse hex to field to 16-bit value and write it in network byte-order
+ parts[w+offset] = _htons(parseInt(words[w],16));
+ }
+ } else {
+ // parsed IPv4 words
+ parts[w+offset] = words[w];
+ }
+ }
+ return [
+ (parts[1] << 16) | parts[0],
+ (parts[3] << 16) | parts[2],
+ (parts[5] << 16) | parts[4],
+ (parts[7] << 16) | parts[6]
+ ];
};
- peer.socket.onerror = function(error) {
- sock.error = 14;
- Module["websocket"].emit("error", [ sock.stream.fd, sock.error, "ECONNREFUSED: Connection refused" ]);
+
+
+ /** @param {number=} addrlen */
+ var writeSockaddr = (sa, family, addr, port, addrlen) => {
+ switch (family) {
+ case 2:
+ addr = inetPton4(addr);
+ zeroMemory(sa, 16);
+ if (addrlen) {
+ HEAP32[((addrlen)>>2)] = 16;
+ }
+ HEAP16[((sa)>>1)] = family;
+ HEAP32[(((sa)+(4))>>2)] = addr;
+ HEAP16[(((sa)+(2))>>1)] = _htons(port);
+ break;
+ case 10:
+ addr = inetPton6(addr);
+ zeroMemory(sa, 28);
+ if (addrlen) {
+ HEAP32[((addrlen)>>2)] = 28;
+ }
+ HEAP32[((sa)>>2)] = family;
+ HEAP32[(((sa)+(8))>>2)] = addr[0];
+ HEAP32[(((sa)+(12))>>2)] = addr[1];
+ HEAP32[(((sa)+(16))>>2)] = addr[2];
+ HEAP32[(((sa)+(20))>>2)] = addr[3];
+ HEAP16[(((sa)+(2))>>1)] = _htons(port);
+ break;
+ default:
+ return 5;
+ }
+ return 0;
};
- }
- },
- poll(sock) {
- if (sock.type === 1 && sock.server) {
- return sock.pending.length ? 64 | 1 : 0;
- }
- var mask = 0;
- var dest = sock.type === 1 ? SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport) : null;
- if (sock.recv_queue.length || !dest || dest && dest.socket.readyState === dest.socket.CLOSING || dest && dest.socket.readyState === dest.socket.CLOSED) {
- mask |= 64 | 1;
- }
- if (!dest || dest && dest.socket.readyState === dest.socket.OPEN) {
- mask |= 4;
- }
- if (dest && dest.socket.readyState === dest.socket.CLOSING || dest && dest.socket.readyState === dest.socket.CLOSED) {
- mask |= 16;
- }
- return mask;
- },
- ioctl(sock, request, arg) {
- switch (request) {
- case 21531:
- var bytes = 0;
- if (sock.recv_queue.length) {
- bytes = sock.recv_queue[0].data.length;
- }
- HEAP32[arg >> 2] = bytes;
- return 0;
-
- default:
- return 28;
- }
+
+
+ var DNS = {
+ address_map:{
+ id:1,
+ addrs:{
},
- close(sock) {
- if (sock.server) {
- try {
- sock.server.close();
- } catch (e) {}
- sock.server = null;
- }
- var peers = Object.keys(sock.peers);
- for (var i = 0; i < peers.length; i++) {
- var peer = sock.peers[peers[i]];
- try {
- peer.socket.close();
- } catch (e) {}
- SOCKFS.websocket_sock_ops.removePeer(sock, peer);
- }
- return 0;
+ names:{
},
- bind(sock, addr, port) {
- if (typeof sock.saddr != "undefined" || typeof sock.sport != "undefined") {
- throw new FS.ErrnoError(28);
- }
- sock.saddr = addr;
- sock.sport = port;
- if (sock.type === 2) {
- if (sock.server) {
- sock.server.close();
- sock.server = null;
- }
- try {
- sock.sock_ops.listen(sock, 0);
- } catch (e) {
- if (!(e.name === "ErrnoError")) throw e;
- if (e.errno !== 138) throw e;
- }
- }
- },
- connect(sock, addr, port) {
- if (sock.server) {
- throw new FS.ErrnoError(138);
- }
- if (typeof sock.daddr != "undefined" && typeof sock.dport != "undefined") {
- var dest = SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport);
- if (dest) {
- if (dest.socket.readyState === dest.socket.CONNECTING) {
- throw new FS.ErrnoError(7);
- } else {
- throw new FS.ErrnoError(30);
- }
- }
- }
- var peer = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port);
- sock.daddr = peer.addr;
- sock.dport = peer.port;
- throw new FS.ErrnoError(26);
- },
- listen(sock, backlog) {
- if (!ENVIRONMENT_IS_NODE) {
- throw new FS.ErrnoError(138);
- }
- if (sock.server) {
- throw new FS.ErrnoError(28);
- }
- var WebSocketServer = require("ws").Server;
- var host = sock.saddr;
- if (Module['websocket']['serverDecorator']) {WebSocketServer = Module['websocket']['serverDecorator'](WebSocketServer);}sock.server = new WebSocketServer({
- host: host,
- port: sock.sport
- });
- Module["websocket"].emit("listen", sock.stream.fd);
- sock.server.on("connection", (function(ws) {
- if (sock.type === 1) {
- var newsock = SOCKFS.createSocket(sock.family, sock.type, sock.protocol);
- var peer = SOCKFS.websocket_sock_ops.createPeer(newsock, ws);
- newsock.daddr = peer.addr;
- newsock.dport = peer.port;
- sock.pending.push(newsock);
- Module["websocket"].emit("connection", newsock.stream.fd);
- } else {
- SOCKFS.websocket_sock_ops.createPeer(sock, ws);
- Module["websocket"].emit("connection", sock.stream.fd);
- }
- }));
- sock.server.on("close", (function() {
- Module["websocket"].emit("close", sock.stream.fd);
- sock.server = null;
- }));
- sock.server.on("error", (function(error) {
- sock.error = 23;
- Module["websocket"].emit("error", [ sock.stream.fd, sock.error, "EHOSTUNREACH: Host is unreachable" ]);
- }));
- },
- accept(listensock) {
- if (!listensock.server || !listensock.pending.length) {
- throw new FS.ErrnoError(28);
- }
- var newsock = listensock.pending.shift();
- newsock.stream.flags = listensock.stream.flags;
- return newsock;
},
- getname(sock, peer) {
- var addr, port;
- if (peer) {
- if (sock.daddr === undefined || sock.dport === undefined) {
- throw new FS.ErrnoError(53);
- }
- addr = sock.daddr;
- port = sock.dport;
- } else {
- addr = sock.saddr || 0;
- port = sock.sport || 0;
- }
- return {
- addr: addr,
- port: port
- };
- },
- sendmsg(sock, buffer, offset, length, addr, port) {
- if (sock.type === 2) {
- if (addr === undefined || port === undefined) {
- addr = sock.daddr;
- port = sock.dport;
- }
- if (addr === undefined || port === undefined) {
- throw new FS.ErrnoError(17);
- }
- } else {
- addr = sock.daddr;
- port = sock.dport;
- }
- var dest = SOCKFS.websocket_sock_ops.getPeer(sock, addr, port);
- if (sock.type === 1) {
- if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) {
- throw new FS.ErrnoError(53);
- } else if (dest.socket.readyState === dest.socket.CONNECTING) {
- throw new FS.ErrnoError(6);
- }
- }
- if (ArrayBuffer.isView(buffer)) {
- offset += buffer.byteOffset;
- buffer = buffer.buffer;
- }
- var data;
- data = buffer.slice(offset, offset + length);
- if (sock.type === 2) {
- if (!dest || dest.socket.readyState !== dest.socket.OPEN) {
- if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) {
- dest = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port);
- }
- dest.dgram_send_queue.push(data);
- return length;
- }
- }
- try {
- dest.socket.send(data);
- return length;
- } catch (e) {
- throw new FS.ErrnoError(28);
- }
- },
- recvmsg(sock, length, flags) {
- if (sock.type === 1 && sock.server) {
- throw new FS.ErrnoError(53);
- }
- var queued = sock.recv_queue.shift();
- if (!queued) {
- if (sock.type === 1) {
- var dest = SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport);
- if (!dest) {
- throw new FS.ErrnoError(53);
- }
- if (dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) {
- return null;
- }
- throw new FS.ErrnoError(6);
- }
- throw new FS.ErrnoError(6);
- }
- var queuedLength = queued.data.byteLength || queued.data.length;
- var queuedOffset = queued.data.byteOffset || 0;
- var queuedBuffer = queued.data.buffer || queued.data;
- var bytesRead = Math.min(length, queuedLength);
- var res = {
- buffer: new Uint8Array(queuedBuffer, queuedOffset, bytesRead),
- addr: queued.addr,
- port: queued.port
- };
- if (flags&2) {bytesRead = 0;} if (sock.type === 1 && bytesRead < queuedLength) {
- var bytesRemaining = queuedLength - bytesRead;
- queued.data = new Uint8Array(queuedBuffer, queuedOffset + bytesRead, bytesRemaining);
- sock.recv_queue.unshift(queued);
- }
- return res;
- }
- }
-};
-
-function getSocketFromFD(fd) {
- var socket = SOCKFS.getSocket(fd);
- if (!socket) throw new FS.ErrnoError(8);
- return socket;
-}
-
-var setErrNo = value => {
- HEAP32[___errno_location() >> 2] = value;
- return value;
-};
-
-var inetPton4 = str => {
- var b = str.split(".");
- for (var i = 0; i < 4; i++) {
- var tmp = Number(b[i]);
- if (isNaN(tmp)) return null;
- b[i] = tmp;
- }
- return (b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24) >>> 0;
-};
-
-var jstoi_q = str => parseInt(str);
-
-var inetPton6 = str => {
- var words;
- var w, offset, z;
- var valid6regx = /^((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\3)::|:\b|$))|(?!\2\3)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i;
- var parts = [];
- if (!valid6regx.test(str)) {
- return null;
- }
- if (str === "::") {
- return [ 0, 0, 0, 0, 0, 0, 0, 0 ];
- }
- if (str.startsWith("::")) {
- str = str.replace("::", "Z:");
- } else {
- str = str.replace("::", ":Z:");
- }
- if (str.indexOf(".") > 0) {
- str = str.replace(new RegExp("[.]", "g"), ":");
- words = str.split(":");
- words[words.length - 4] = jstoi_q(words[words.length - 4]) + jstoi_q(words[words.length - 3]) * 256;
- words[words.length - 3] = jstoi_q(words[words.length - 2]) + jstoi_q(words[words.length - 1]) * 256;
- words = words.slice(0, words.length - 2);
- } else {
- words = str.split(":");
- }
- offset = 0;
- z = 0;
- for (w = 0; w < words.length; w++) {
- if (typeof words[w] == "string") {
- if (words[w] === "Z") {
- for (z = 0; z < 8 - words.length + 1; z++) {
- parts[w + z] = 0;
- }
- offset = z - 1;
- } else {
- parts[w + offset] = _htons(parseInt(words[w], 16));
- }
- } else {
- parts[w + offset] = words[w];
- }
- }
- return [ parts[1] << 16 | parts[0], parts[3] << 16 | parts[2], parts[5] << 16 | parts[4], parts[7] << 16 | parts[6] ];
-};
-
-var writeSockaddr = (sa, family, addr, port, addrlen) => {
- switch (family) {
- case 2:
- addr = inetPton4(addr);
- zeroMemory(sa, 16);
- if (addrlen) {
- HEAP32[addrlen >> 2] = 16;
- }
- HEAP16[sa >> 1] = family;
- HEAP32[sa + 4 >> 2] = addr;
- HEAP16[sa + 2 >> 1] = _htons(port);
- break;
-
- case 10:
- addr = inetPton6(addr);
- zeroMemory(sa, 28);
- if (addrlen) {
- HEAP32[addrlen >> 2] = 28;
- }
- HEAP32[sa >> 2] = family;
- HEAP32[sa + 8 >> 2] = addr[0];
- HEAP32[sa + 12 >> 2] = addr[1];
- HEAP32[sa + 16 >> 2] = addr[2];
- HEAP32[sa + 20 >> 2] = addr[3];
- HEAP16[sa + 2 >> 1] = _htons(port);
- break;
-
- default:
- return 5;
- }
- return 0;
-};
-
-var DNS = {
- address_map: {
- id: 1,
- addrs: {},
- names: {}
- },
- lookup_name: name => {
- var res = inetPton4(name);
- if (res !== null) {
- return name;
- }
- res = inetPton6(name);
- if (res !== null) {
- return name;
- }
- var addr;
- if (DNS.address_map.addrs[name]) {
- addr = DNS.address_map.addrs[name];
- } else {
- var id = DNS.address_map.id++;
- assert(id < 65535, "exceeded max address mappings of 65535");
- addr = "172.29." + (id & 255) + "." + (id & 65280);
- DNS.address_map.names[addr] = name;
- DNS.address_map.addrs[name] = addr;
- }
- return addr;
- },
- lookup_addr: addr => {
- if (DNS.address_map.names[addr]) {
- return DNS.address_map.names[addr];
- }
- return null;
- }
-};
-
-function ___syscall_accept4(fd, addr, addrlen, flags, d1, d2) {
- try {
- var sock = getSocketFromFD(fd);
- var newsock = sock.sock_ops.accept(sock);
- if (addr) {
- var errno = writeSockaddr(addr, newsock.family, DNS.lookup_name(newsock.daddr), newsock.dport, addrlen);
- }
- return newsock.stream.fd;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-var inetNtop4 = addr => (addr & 255) + "." + (addr >> 8 & 255) + "." + (addr >> 16 & 255) + "." + (addr >> 24 & 255);
-
-var inetNtop6 = ints => {
- var str = "";
- var word = 0;
- var longest = 0;
- var lastzero = 0;
- var zstart = 0;
- var len = 0;
- var i = 0;
- var parts = [ ints[0] & 65535, ints[0] >> 16, ints[1] & 65535, ints[1] >> 16, ints[2] & 65535, ints[2] >> 16, ints[3] & 65535, ints[3] >> 16 ];
- var hasipv4 = true;
- var v4part = "";
- for (i = 0; i < 5; i++) {
- if (parts[i] !== 0) {
- hasipv4 = false;
- break;
- }
- }
- if (hasipv4) {
- v4part = inetNtop4(parts[6] | parts[7] << 16);
- if (parts[5] === -1) {
- str = "::ffff:";
- str += v4part;
- return str;
- }
- if (parts[5] === 0) {
- str = "::";
- if (v4part === "0.0.0.0") v4part = "";
- if (v4part === "0.0.0.1") v4part = "1";
- str += v4part;
- return str;
- }
- }
- for (word = 0; word < 8; word++) {
- if (parts[word] === 0) {
- if (word - lastzero > 1) {
- len = 0;
- }
- lastzero = word;
- len++;
- }
- if (len > longest) {
- longest = len;
- zstart = word - longest + 1;
- }
- }
- for (word = 0; word < 8; word++) {
- if (longest > 1) {
- if (parts[word] === 0 && word >= zstart && word < zstart + longest) {
- if (word === zstart) {
- str += ":";
- if (zstart === 0) str += ":";
- }
- continue;
- }
- }
- str += Number(_ntohs(parts[word] & 65535)).toString(16);
- str += word < 7 ? ":" : "";
- }
- return str;
-};
-
-var readSockaddr = (sa, salen) => {
- var family = HEAP16[sa >> 1];
- var port = _ntohs(HEAPU16[sa + 2 >> 1]);
- var addr;
- switch (family) {
- case 2:
- if (salen !== 16) {
- return {
- errno: 28
- };
- }
- addr = HEAP32[sa + 4 >> 2];
- addr = inetNtop4(addr);
- break;
-
- case 10:
- if (salen !== 28) {
- return {
- errno: 28
- };
- }
- addr = [ HEAP32[sa + 8 >> 2], HEAP32[sa + 12 >> 2], HEAP32[sa + 16 >> 2], HEAP32[sa + 20 >> 2] ];
- addr = inetNtop6(addr);
- break;
-
- default:
- return {
- errno: 5
- };
- }
- return {
- family: family,
- addr: addr,
- port: port
- };
-};
-
-function getSocketAddress(addrp, addrlen, allowNull) {
- if (allowNull && addrp === 0) return null;
- var info = readSockaddr(addrp, addrlen);
- if (info.errno) throw new FS.ErrnoError(info.errno);
- info.addr = DNS.lookup_addr(info.addr) || info.addr;
- return info;
-}
-
-function ___syscall_bind(fd, addr, addrlen, d1, d2, d3) {
- try {
- var sock = getSocketFromFD(fd);
- var info = getSocketAddress(addr, addrlen);
- sock.sock_ops.bind(sock, info.addr, info.port);
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_chdir(path) {
- try {
- path = SYSCALLS.getStr(path);
- FS.chdir(path);
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_chmod(path, mode) {
- try {
- path = SYSCALLS.getStr(path);
- FS.chmod(path, mode);
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_connect(fd, addr, addrlen, d1, d2, d3) {
- try {
- var sock = getSocketFromFD(fd);
- var info = getSocketAddress(addr, addrlen);
- sock.sock_ops.connect(sock, info.addr, info.port);
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_dup(fd) {
- try {
- var old = SYSCALLS.getStreamFromFD(fd);
- return FS.createStream(old).fd;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_dup3(fd, newfd, flags) {
- try {
- var old = SYSCALLS.getStreamFromFD(fd);
- if (old.fd === newfd) return -28;
- var existing = FS.getStream(newfd);
- if (existing) FS.close(existing);
- return FS.createStream(old, newfd).fd;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_faccessat(dirfd, path, amode, flags) {
- try {
- path = SYSCALLS.getStr(path);
- path = SYSCALLS.calculateAt(dirfd, path);
- if (amode & ~7) {
- return -28;
- }
- var lookup = FS.lookupPath(path, {
- follow: true
- });
- var 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 && FS.nodePermissions(node, perms)) {
- return -2;
- }
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function convertI32PairToI53Checked(lo, hi) {
- return hi + 2097152 >>> 0 < 4194305 - !!lo ? (lo >>> 0) + hi * 4294967296 : NaN;
-}
-
-function ___syscall_fallocate(fd, mode, offset_low, offset_high, len_low, len_high) {
- var offset = convertI32PairToI53Checked(offset_low, offset_high);
- var len = convertI32PairToI53Checked(len_low, len_high);
- try {
- if (isNaN(offset)) return 61;
- var stream = SYSCALLS.getStreamFromFD(fd);
- FS.allocate(stream, offset, len);
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_fchmod(fd, mode) {
- try {
- FS.fchmod(fd, mode);
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_fchown32(fd, owner, group) {
- try {
- FS.fchown(fd, owner, group);
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_fchownat(dirfd, path, owner, group, flags) {
- try {
- path = SYSCALLS.getStr(path);
- var nofollow = flags & 256;
- flags = flags & ~256;
- path = SYSCALLS.calculateAt(dirfd, path);
- (nofollow ? FS.lchown : FS.chown)(path, owner, group);
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_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.createStream(stream, arg);
- return newStream.fd;
- }
-
- case 1:
- case 2:
- return 0;
-
- case 3:
- return stream.flags;
-
- case 4:
- {
- var arg = SYSCALLS.get();
- stream.flags |= arg;
- return 0;
- }
-
- case 5:
- {
- var arg = SYSCALLS.get();
- var offset = 0;
- HEAP16[arg + offset >> 1] = 2;
- return 0;
- }
-
- case 6:
- case 7:
- return 0;
-
- case 16:
- case 8:
- return -28;
-
- case 9:
- setErrNo(28);
- return -1;
-
- default:
- {
- return -28;
- }
- }
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_fdatasync(fd) {
- try {
- var stream = SYSCALLS.getStreamFromFD(fd);
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_fstat64(fd, buf) {
- try {
- var stream = SYSCALLS.getStreamFromFD(fd);
- return SYSCALLS.doStat(FS.stat, stream.path, buf);
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_ftruncate64(fd, length_low, length_high) {
- var length = convertI32PairToI53Checked(length_low, length_high);
- try {
- if (isNaN(length)) return 61;
- FS.ftruncate(fd, length);
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-var stringToUTF8 = (str, outPtr, maxBytesToWrite) => stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
-
-Module["stringToUTF8"] = stringToUTF8;
-
-function ___syscall_getcwd(buf, size) {
- try {
- if (size === 0) return -28;
- var cwd = FS.cwd();
- var cwdLengthInBytes = lengthBytesUTF8(cwd) + 1;
- if (size < cwdLengthInBytes) return -68;
- stringToUTF8(cwd, buf, size);
- return cwdLengthInBytes;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_getdents64(fd, dirp, count) {
- try {
- var stream = SYSCALLS.getStreamFromFD(fd);
- if (!stream.getdents) {
- stream.getdents = FS.readdir(stream.path);
- }
- var struct_size = 280;
- var pos = 0;
- var off = FS.llseek(stream, 0, 1);
- var idx = Math.floor(off / struct_size);
- while (idx < stream.getdents.length && pos + struct_size <= count) {
- var id;
- var type;
- var name = stream.getdents[idx];
- if (name === ".") {
- id = stream.node.id;
- type = 4;
- } else if (name === "..") {
- var lookup = FS.lookupPath(stream.path, {
- parent: true
- });
- id = lookup.node.id;
- type = 4;
- } else {
- var child = FS.lookupNode(stream.node, name);
- id = child.id;
- type = FS.isChrdev(child.mode) ? 2 : FS.isDir(child.mode) ? 4 : FS.isLink(child.mode) ? 10 : 8;
- }
- tempI64 = [ id >>> 0, (tempDouble = id, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? +Math.floor(tempDouble / 4294967296) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ],
- HEAP32[dirp + pos >> 2] = tempI64[0], HEAP32[dirp + pos + 4 >> 2] = tempI64[1];
- tempI64 = [ (idx + 1) * struct_size >>> 0, (tempDouble = (idx + 1) * struct_size,
- +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? +Math.floor(tempDouble / 4294967296) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ],
- HEAP32[dirp + pos + 8 >> 2] = tempI64[0], HEAP32[dirp + pos + 12 >> 2] = tempI64[1];
- HEAP16[dirp + pos + 16 >> 1] = 280;
- HEAP8[dirp + pos + 18 >> 0] = type;
- stringToUTF8(name, dirp + pos + 19, 256);
- pos += struct_size;
- idx += 1;
- }
- FS.llseek(stream, idx * struct_size, 0);
- return pos;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_getpeername(fd, addr, addrlen, d1, d2, d3) {
- try {
- var sock = getSocketFromFD(fd);
- if (!sock.daddr) {
- return -53;
- }
- var errno = writeSockaddr(addr, sock.family, DNS.lookup_name(sock.daddr), sock.dport, addrlen);
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_getsockname(fd, addr, addrlen, d1, d2, d3) {
- try {
- var sock = getSocketFromFD(fd);
- var errno = writeSockaddr(addr, sock.family, DNS.lookup_name(sock.saddr || "0.0.0.0"), sock.sport, addrlen);
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_getsockopt(fd, level, optname, optval, optlen, d1) {
- try {
- var sock = getSocketFromFD(fd);
- if (level === 1) {
- if (optname === 4) {
- HEAP32[optval >> 2] = sock.error;
- HEAP32[optlen >> 2] = 4;
- sock.error = null;
- return 0;
- }
- }
- return -50;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_ioctl(fd, op, varargs) {
- SYSCALLS.varargs = varargs;
- try {
- var stream = SYSCALLS.getStreamFromFD(fd);
- switch (op) {
- case 21509:
- {
- if (!stream.tty) return -59;
- return 0;
- }
-
- case 21505:
- {
- if (!stream.tty) return -59;
- if (stream.tty.ops.ioctl_tcgets) {
- var termios = stream.tty.ops.ioctl_tcgets(stream);
- var argp = SYSCALLS.get();
- HEAP32[argp >> 2] = termios.c_iflag || 0;
- HEAP32[argp + 4 >> 2] = termios.c_oflag || 0;
- HEAP32[argp + 8 >> 2] = termios.c_cflag || 0;
- HEAP32[argp + 12 >> 2] = termios.c_lflag || 0;
- for (var i = 0; i < 32; i++) {
- HEAP8[argp + i + 17 >> 0] = termios.c_cc[i] || 0;
- }
- return 0;
- }
- return 0;
- }
-
- case 21510:
- case 21511:
- case 21512:
- {
- if (!stream.tty) return -59;
- return 0;
- }
-
- case 21506:
- case 21507:
- case 21508:
- {
- if (!stream.tty) return -59;
- if (stream.tty.ops.ioctl_tcsets) {
- var argp = SYSCALLS.get();
- var c_iflag = HEAP32[argp >> 2];
- var c_oflag = HEAP32[argp + 4 >> 2];
- var c_cflag = HEAP32[argp + 8 >> 2];
- var c_lflag = HEAP32[argp + 12 >> 2];
- var c_cc = [];
- for (var i = 0; i < 32; i++) {
- c_cc.push(HEAP8[argp + i + 17 >> 0]);
- }
- return stream.tty.ops.ioctl_tcsets(stream.tty, op, {
- c_iflag: c_iflag,
- c_oflag: c_oflag,
- c_cflag: c_cflag,
- c_lflag: c_lflag,
- c_cc: c_cc
- });
- }
- return 0;
- }
-
- 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;
- }
-
- case 21531:
- {
- var argp = SYSCALLS.get();
- return FS.ioctl(stream, op, argp);
- }
-
- case 21523:
- {
- if (!stream.tty) return -59;
- if (stream.tty.ops.ioctl_tiocgwinsz) {
- var winsize = stream.tty.ops.ioctl_tiocgwinsz(stream.tty);
- var argp = SYSCALLS.get();
- HEAP16[argp >> 1] = winsize[0];
- HEAP16[argp + 2 >> 1] = winsize[1];
- }
- return 0;
- }
-
- case 21524:
- {
- if (!stream.tty) return -59;
- return 0;
- }
-
- case 21515:
- {
- if (!stream.tty) return -59;
- return 0;
- }
-
- default:
- return -28;
- }
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_listen(fd, backlog) {
- try {
- var sock = getSocketFromFD(fd);
- sock.sock_ops.listen(sock, backlog);
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_lstat64(path, buf) {
- try {
- path = SYSCALLS.getStr(path);
- return SYSCALLS.doStat(FS.lstat, path, buf);
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_mkdirat(dirfd, path, mode) {
- try {
- path = SYSCALLS.getStr(path);
- path = SYSCALLS.calculateAt(dirfd, path);
- path = PATH.normalize(path);
- if (path[path.length - 1] === "/") path = path.substr(0, path.length - 1);
- FS.mkdir(path, mode, 0);
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_newfstatat(dirfd, path, buf, flags) {
- try {
- path = SYSCALLS.getStr(path);
- var nofollow = flags & 256;
- var allowEmpty = flags & 4096;
- flags = flags & ~6400;
- path = SYSCALLS.calculateAt(dirfd, path, allowEmpty);
- return SYSCALLS.doStat(nofollow ? FS.lstat : FS.stat, path, buf);
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_openat(dirfd, path, flags, varargs) {
- SYSCALLS.varargs = varargs;
- try {
- path = SYSCALLS.getStr(path);
- path = SYSCALLS.calculateAt(dirfd, path);
- var mode = varargs ? SYSCALLS.get() : 0;
- return FS.open(path, flags, mode).fd;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-var PIPEFS = {
- BUCKET_BUFFER_SIZE: 8192,
- mount(mount) {
- return FS.createNode(null, "/", 16384 | 511, 0);
- },
- createPipe() {
- var pipe = {
- buckets: [],
- refcnt: 2
- };
- pipe.buckets.push({
- buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),
- offset: 0,
- roffset: 0
- });
- var rName = PIPEFS.nextname();
- var wName = PIPEFS.nextname();
- var rNode = FS.createNode(PIPEFS.root, rName, 4096, 0);
- var wNode = FS.createNode(PIPEFS.root, wName, 4096, 0);
- rNode.pipe = pipe;
- wNode.pipe = pipe;
- var readableStream = FS.createStream({
- path: rName,
- node: rNode,
- flags: 0,
- seekable: false,
- stream_ops: PIPEFS.stream_ops
- });
- rNode.stream = readableStream;
- var writableStream = FS.createStream({
- path: wName,
- node: wNode,
- flags: 1,
- seekable: false,
- stream_ops: PIPEFS.stream_ops
- });
- wNode.stream = writableStream;
- return {
- readable_fd: readableStream.fd,
- writable_fd: writableStream.fd
+ lookup_name:(name) => {
+ // If the name is already a valid ipv4 / ipv6 address, don't generate a fake one.
+ var res = inetPton4(name);
+ if (res !== null) {
+ return name;
+ }
+ res = inetPton6(name);
+ if (res !== null) {
+ return name;
+ }
+
+ // See if this name is already mapped.
+ var addr;
+
+ if (DNS.address_map.addrs[name]) {
+ addr = DNS.address_map.addrs[name];
+ } else {
+ var id = DNS.address_map.id++;
+ assert(id < 65535, 'exceeded max address mappings of 65535');
+
+ addr = '172.29.' + (id & 0xff) + '.' + (id & 0xff00);
+
+ DNS.address_map.names[addr] = name;
+ DNS.address_map.addrs[name] = addr;
+ }
+
+ return addr;
+ },
+ lookup_addr:(addr) => {
+ if (DNS.address_map.names[addr]) {
+ return DNS.address_map.names[addr];
+ }
+
+ return null;
+ },
};
- },
- stream_ops: {
- poll(stream) {
- var pipe = stream.node.pipe;
- if ((stream.flags & 2097155) === 1) {
- return 256 | 4;
- }
- if (pipe.buckets.length > 0) {
- for (var i = 0; i < pipe.buckets.length; i++) {
- var bucket = pipe.buckets[i];
- if (bucket.offset - bucket.roffset > 0) {
- return 64 | 1;
- }
- }
- }
- return 0;
- },
- ioctl(stream, request, varargs) {
- return 28;
- },
- fsync(stream) {
- return 28;
- },
- read(stream, buffer, offset, length, position) {
- var pipe = stream.node.pipe;
- var currentLength = 0;
- for (var i = 0; i < pipe.buckets.length; i++) {
- var bucket = pipe.buckets[i];
- currentLength += bucket.offset - bucket.roffset;
- }
- assert(buffer instanceof ArrayBuffer || ArrayBuffer.isView(buffer));
- var data = buffer.subarray(offset, offset + length);
- if (length <= 0) {
- return 0;
- }
- if (currentLength == 0) {
- throw new FS.ErrnoError(6);
- }
- var toRead = Math.min(currentLength, length);
- var totalRead = toRead;
- var toRemove = 0;
- for (var i = 0; i < pipe.buckets.length; i++) {
- var currBucket = pipe.buckets[i];
- var bucketSize = currBucket.offset - currBucket.roffset;
- if (toRead <= bucketSize) {
- var tmpSlice = currBucket.buffer.subarray(currBucket.roffset, currBucket.offset);
- if (toRead < bucketSize) {
- tmpSlice = tmpSlice.subarray(0, toRead);
- currBucket.roffset += toRead;
- } else {
- toRemove++;
- }
- data.set(tmpSlice);
- break;
- } else {
- var tmpSlice = currBucket.buffer.subarray(currBucket.roffset, currBucket.offset);
- data.set(tmpSlice);
- data = data.subarray(tmpSlice.byteLength);
- toRead -= tmpSlice.byteLength;
- toRemove++;
- }
- }
- if (toRemove && toRemove == pipe.buckets.length) {
- toRemove--;
- pipe.buckets[toRemove].offset = 0;
- pipe.buckets[toRemove].roffset = 0;
- }
- pipe.buckets.splice(0, toRemove);
- return totalRead;
- },
- write(stream, buffer, offset, length, position) {
- var pipe = stream.node.pipe;
- assert(buffer instanceof ArrayBuffer || ArrayBuffer.isView(buffer));
- var data = buffer.subarray(offset, offset + length);
- var dataLen = data.byteLength;
- if (dataLen <= 0) {
- return 0;
- }
- var currBucket = null;
- if (pipe.buckets.length == 0) {
- currBucket = {
- buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),
- offset: 0,
- roffset: 0
- };
- pipe.buckets.push(currBucket);
- } else {
- currBucket = pipe.buckets[pipe.buckets.length - 1];
- }
- assert(currBucket.offset <= PIPEFS.BUCKET_BUFFER_SIZE);
- var freeBytesInCurrBuffer = PIPEFS.BUCKET_BUFFER_SIZE - currBucket.offset;
- if (freeBytesInCurrBuffer >= dataLen) {
- currBucket.buffer.set(data, currBucket.offset);
- currBucket.offset += dataLen;
- return dataLen;
- } else if (freeBytesInCurrBuffer > 0) {
- currBucket.buffer.set(data.subarray(0, freeBytesInCurrBuffer), currBucket.offset);
- currBucket.offset += freeBytesInCurrBuffer;
- data = data.subarray(freeBytesInCurrBuffer, data.byteLength);
- }
- var numBuckets = data.byteLength / PIPEFS.BUCKET_BUFFER_SIZE | 0;
- var remElements = data.byteLength % PIPEFS.BUCKET_BUFFER_SIZE;
- for (var i = 0; i < numBuckets; i++) {
- var newBucket = {
- buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),
- offset: PIPEFS.BUCKET_BUFFER_SIZE,
- roffset: 0
- };
- pipe.buckets.push(newBucket);
- newBucket.buffer.set(data.subarray(0, PIPEFS.BUCKET_BUFFER_SIZE));
- data = data.subarray(PIPEFS.BUCKET_BUFFER_SIZE, data.byteLength);
- }
- if (remElements > 0) {
- var newBucket = {
- buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),
- offset: data.byteLength,
- roffset: 0
- };
- pipe.buckets.push(newBucket);
- newBucket.buffer.set(data);
- }
- return dataLen;
- },
- close(stream) {
- var pipe = stream.node.pipe;
- pipe.refcnt--;
- if (pipe.refcnt === 0) {
- pipe.buckets = null;
- }
- }
- },
- nextname() {
- if (!PIPEFS.nextname.current) {
- PIPEFS.nextname.current = 0;
- }
- return "pipe[" + PIPEFS.nextname.current++ + "]";
- }
-};
-
-function ___syscall_pipe(fdPtr) {
- try {
- if (fdPtr == 0) {
- throw new FS.ErrnoError(21);
- }
- var res = PIPEFS.createPipe();
- HEAP32[fdPtr >> 2] = res.readable_fd;
- HEAP32[fdPtr + 4 >> 2] = res.writable_fd;
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_poll(fds, nfds, timeout) {
- try {
- var nonzero = 0;
- for (var i = 0; i < nfds; i++) {
- var pollfd = fds + 8 * i;
- var fd = HEAP32[pollfd >> 2];
- var events = HEAP16[pollfd + 4 >> 1];
- var mask = 32;
- var stream = FS.getStream(fd);
- if (stream) {
- mask = SYSCALLS.DEFAULT_POLLMASK;
- if (stream.stream_ops?.poll) {
- mask = stream.stream_ops.poll(stream, -1);
- }
- }
- mask &= events | 8 | 16;
- if (mask) nonzero++;
- HEAP16[pollfd + 6 >> 1] = mask;
- }
- return nonzero;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_readlinkat(dirfd, path, buf, bufsize) {
- try {
- path = SYSCALLS.getStr(path);
- path = SYSCALLS.calculateAt(dirfd, path);
- 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);
- HEAP8[buf + len] = endChar;
- return len;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_recvfrom(fd, buf, len, flags, addr, addrlen) {
- try {
- var sock = getSocketFromFD(fd);
- var msg = sock.sock_ops.recvmsg(sock, len, typeof flags !== "undefined" ? flags : 0);
- if (!msg) return 0;
- if (addr) {
- var errno = writeSockaddr(addr, sock.family, DNS.lookup_name(msg.addr), msg.port, addrlen);
- }
- HEAPU8.set(msg.buffer, buf);
- return msg.buffer.byteLength;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_renameat(olddirfd, oldpath, newdirfd, newpath) {
- try {
- oldpath = SYSCALLS.getStr(oldpath);
- newpath = SYSCALLS.getStr(newpath);
- oldpath = SYSCALLS.calculateAt(olddirfd, oldpath);
- newpath = SYSCALLS.calculateAt(newdirfd, newpath);
- FS.rename(oldpath, newpath);
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_rmdir(path) {
- try {
- path = SYSCALLS.getStr(path);
- FS.rmdir(path);
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_sendto(fd, message, length, flags, addr, addr_len) {
- try {
- var sock = getSocketFromFD(fd);
- var dest = getSocketAddress(addr, addr_len, true);
- if (!dest) {
- return FS.write(sock.stream, HEAP8, message, length);
- }
- return sock.sock_ops.sendmsg(sock, HEAP8, message, length, dest.addr, dest.port);
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_socket(domain, type, protocol) {
- try {
- var sock = SOCKFS.createSocket(domain, type, protocol);
- return sock.stream.fd;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_stat64(path, buf) {
- try {
- path = SYSCALLS.getStr(path);
- return SYSCALLS.doStat(FS.stat, path, buf);
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-
-function ___syscall_statfs64(path, size, buf) {
- try {
- path = SYSCALLS.getStr(path);
- HEAP32[buf + 4 >> 2] = 4096;
- HEAP32[buf + 40 >> 2] = 4096;
- HEAP32[buf + 8 >> 2] = 1e6;
- HEAP32[buf + 12 >> 2] = 5e5;
- HEAP32[buf + 16 >> 2] = 5e5;
- HEAP32[buf + 20 >> 2] = FS.nextInode;
- HEAP32[buf + 24 >> 2] = 1e6;
- HEAP32[buf + 28 >> 2] = 42;
- HEAP32[buf + 44 >> 2] = 2;
- HEAP32[buf + 36 >> 2] = 255;
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
+
+ function ___syscall_accept4(fd, addr, addrlen, flags, d1, d2) {
+ try {
+
+ var sock = getSocketFromFD(fd);
+ var newsock = sock.sock_ops.accept(sock);
+ if (addr) {
+ var errno = writeSockaddr(addr, newsock.family, DNS.lookup_name(newsock.daddr), newsock.dport, addrlen);
+ }
+ return newsock.stream.fd;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-function ___syscall_symlink(target, linkpath) {
- try {
- target = SYSCALLS.getStr(target);
- linkpath = SYSCALLS.getStr(linkpath);
- FS.symlink(target, linkpath);
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
+
+
+ var inetNtop4 = (addr) => {
+ return (addr & 0xff) + '.' + ((addr >> 8) & 0xff) + '.' + ((addr >> 16) & 0xff) + '.' + ((addr >> 24) & 0xff)
+ };
+
+
+ var inetNtop6 = (ints) => {
+ // ref: http://www.ietf.org/rfc/rfc2373.txt - section 2.5.4
+ // Format for IPv4 compatible and mapped 128-bit IPv6 Addresses
+ // 128-bits are split into eight 16-bit words
+ // stored in network byte order (big-endian)
+ // | 80 bits | 16 | 32 bits |
+ // +-----------------------------------------------------------------+
+ // | 10 bytes | 2 | 4 bytes |
+ // +--------------------------------------+--------------------------+
+ // + 5 words | 1 | 2 words |
+ // +--------------------------------------+--------------------------+
+ // |0000..............................0000|0000| IPv4 ADDRESS | (compatible)
+ // +--------------------------------------+----+---------------------+
+ // |0000..............................0000|FFFF| IPv4 ADDRESS | (mapped)
+ // +--------------------------------------+----+---------------------+
+ var str = "";
+ var word = 0;
+ var longest = 0;
+ var lastzero = 0;
+ var zstart = 0;
+ var len = 0;
+ var i = 0;
+ var parts = [
+ ints[0] & 0xffff,
+ (ints[0] >> 16),
+ ints[1] & 0xffff,
+ (ints[1] >> 16),
+ ints[2] & 0xffff,
+ (ints[2] >> 16),
+ ints[3] & 0xffff,
+ (ints[3] >> 16)
+ ];
+
+ // Handle IPv4-compatible, IPv4-mapped, loopback and any/unspecified addresses
+
+ var hasipv4 = true;
+ var v4part = "";
+ // check if the 10 high-order bytes are all zeros (first 5 words)
+ for (i = 0; i < 5; i++) {
+ if (parts[i] !== 0) { hasipv4 = false; break; }
+ }
+
+ if (hasipv4) {
+ // low-order 32-bits store an IPv4 address (bytes 13 to 16) (last 2 words)
+ v4part = inetNtop4(parts[6] | (parts[7] << 16));
+ // IPv4-mapped IPv6 address if 16-bit value (bytes 11 and 12) == 0xFFFF (6th word)
+ if (parts[5] === -1) {
+ str = "::ffff:";
+ str += v4part;
+ return str;
+ }
+ // IPv4-compatible IPv6 address if 16-bit value (bytes 11 and 12) == 0x0000 (6th word)
+ if (parts[5] === 0) {
+ str = "::";
+ //special case IPv6 addresses
+ if (v4part === "0.0.0.0") v4part = ""; // any/unspecified address
+ if (v4part === "0.0.0.1") v4part = "1";// loopback address
+ str += v4part;
+ return str;
+ }
+ }
+
+ // Handle all other IPv6 addresses
+
+ // first run to find the longest contiguous zero words
+ for (word = 0; word < 8; word++) {
+ if (parts[word] === 0) {
+ if (word - lastzero > 1) {
+ len = 0;
+ }
+ lastzero = word;
+ len++;
+ }
+ if (len > longest) {
+ longest = len;
+ zstart = word - longest + 1;
+ }
+ }
+
+ for (word = 0; word < 8; word++) {
+ if (longest > 1) {
+ // compress contiguous zeros - to produce "::"
+ if (parts[word] === 0 && word >= zstart && word < (zstart + longest) ) {
+ if (word === zstart) {
+ str += ":";
+ if (zstart === 0) str += ":"; //leading zeros case
+ }
+ continue;
+ }
+ }
+ // converts 16-bit words from big-endian to little-endian before converting to hex string
+ str += Number(_ntohs(parts[word] & 0xffff)).toString(16);
+ str += word < 7 ? ":" : "";
+ }
+ return str;
+ };
+
+ var readSockaddr = (sa, salen) => {
+ // family / port offsets are common to both sockaddr_in and sockaddr_in6
+ var family = HEAP16[((sa)>>1)];
+ var port = _ntohs(HEAPU16[(((sa)+(2))>>1)]);
+ var addr;
+
+ switch (family) {
+ case 2:
+ if (salen !== 16) {
+ return { errno: 28 };
+ }
+ addr = HEAP32[(((sa)+(4))>>2)];
+ addr = inetNtop4(addr);
+ break;
+ case 10:
+ if (salen !== 28) {
+ return { errno: 28 };
+ }
+ addr = [
+ HEAP32[(((sa)+(8))>>2)],
+ HEAP32[(((sa)+(12))>>2)],
+ HEAP32[(((sa)+(16))>>2)],
+ HEAP32[(((sa)+(20))>>2)]
+ ];
+ addr = inetNtop6(addr);
+ break;
+ default:
+ return { errno: 5 };
+ }
+
+ return { family: family, addr: addr, port: port };
+ };
+
+
+ /** @param {boolean=} allowNull */
+ function getSocketAddress(addrp, addrlen, allowNull) {
+ if (allowNull && addrp === 0) return null;
+ var info = readSockaddr(addrp, addrlen);
+ if (info.errno) throw new FS.ErrnoError(info.errno);
+ info.addr = DNS.lookup_addr(info.addr) || info.addr;
+ return info;
+ }
+
+ function ___syscall_bind(fd, addr, addrlen, d1, d2, d3) {
+ try {
+
+ var sock = getSocketFromFD(fd);
+ var info = getSocketAddress(addr, addrlen);
+ sock.sock_ops.bind(sock, info.addr, info.port);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-function ___syscall_unlinkat(dirfd, path, flags) {
- try {
- path = SYSCALLS.getStr(path);
- path = SYSCALLS.calculateAt(dirfd, path);
- if (flags === 0) {
- FS.unlink(path);
- } else if (flags === 512) {
- FS.rmdir(path);
- } else {
- abort("Invalid flags passed to unlinkat");
+ function ___syscall_chdir(path) {
+ try {
+
+ path = SYSCALLS.getStr(path);
+ FS.chdir(path);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
}
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
-function readI53FromI64(ptr) {
- return HEAPU32[ptr >> 2] + HEAP32[ptr + 4 >> 2] * 4294967296;
-}
+ function ___syscall_chmod(path, mode) {
+ try {
+
+ path = SYSCALLS.getStr(path);
+ FS.chmod(path, mode);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-function ___syscall_utimensat(dirfd, path, times, flags) {
- try {
- path = SYSCALLS.getStr(path);
- path = SYSCALLS.calculateAt(dirfd, path, true);
- if (!times) {
- var atime = Date.now();
- var mtime = atime;
- } else {
- var seconds = readI53FromI64(times);
- var nanoseconds = HEAP32[times + 8 >> 2];
- atime = seconds * 1e3 + nanoseconds / (1e3 * 1e3);
- times += 16;
- seconds = readI53FromI64(times);
- nanoseconds = HEAP32[times + 8 >> 2];
- mtime = seconds * 1e3 + nanoseconds / (1e3 * 1e3);
- }
- FS.utime(path, atime, mtime);
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
+
+
+ function ___syscall_connect(fd, addr, addrlen, d1, d2, d3) {
+ try {
+
+ var sock = getSocketFromFD(fd);
+ var info = getSocketAddress(addr, addrlen);
+ sock.sock_ops.connect(sock, info.addr, info.port);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-var nowIsMonotonic = true;
+ function ___syscall_dup(fd) {
+ try {
+
+ var old = SYSCALLS.getStreamFromFD(fd);
+ return FS.createStream(old).fd;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-var __emscripten_get_now_is_monotonic = () => nowIsMonotonic;
+ function ___syscall_dup3(fd, newfd, flags) {
+ try {
+
+ var old = SYSCALLS.getStreamFromFD(fd);
+ if (old.fd === newfd) return -28;
+ var existing = FS.getStream(newfd);
+ if (existing) FS.close(existing);
+ return FS.createStream(old, newfd).fd;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-var __emscripten_throw_longjmp = () => {
- throw Infinity;
-};
+ function ___syscall_faccessat(dirfd, path, amode, flags) {
+ try {
+
+ path = SYSCALLS.getStr(path);
+ path = SYSCALLS.calculateAt(dirfd, path);
+ if (amode & ~7) {
+ // need a valid mode
+ return -28;
+ }
+ var lookup = FS.lookupPath(path, { follow: true });
+ var 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;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-function __gmtime_js(time_low, time_high, tmPtr) {
- var time = convertI32PairToI53Checked(time_low, time_high);
- var date = new Date(time * 1e3);
- HEAP32[tmPtr >> 2] = date.getUTCSeconds();
- HEAP32[tmPtr + 4 >> 2] = date.getUTCMinutes();
- HEAP32[tmPtr + 8 >> 2] = date.getUTCHours();
- HEAP32[tmPtr + 12 >> 2] = date.getUTCDate();
- HEAP32[tmPtr + 16 >> 2] = date.getUTCMonth();
- HEAP32[tmPtr + 20 >> 2] = date.getUTCFullYear() - 1900;
- HEAP32[tmPtr + 24 >> 2] = date.getUTCDay();
- var start = Date.UTC(date.getUTCFullYear(), 0, 1, 0, 0, 0, 0);
- var yday = (date.getTime() - start) / (1e3 * 60 * 60 * 24) | 0;
- HEAP32[tmPtr + 28 >> 2] = yday;
-}
+
+ function convertI32PairToI53Checked(lo, hi) {
+ return ((hi + 0x200000) >>> 0 < 0x400001 - !!lo) ? (lo >>> 0) + hi * 4294967296 : NaN;
+ }
+ function ___syscall_fallocate(fd,mode,offset_low, offset_high,len_low, len_high) {
+ var offset = convertI32PairToI53Checked(offset_low, offset_high);;
+ var len = convertI32PairToI53Checked(len_low, len_high);;
+
+
+ try {
+
+ if (isNaN(offset)) return 61;
+ var stream = SYSCALLS.getStreamFromFD(fd)
+ FS.allocate(stream, offset, len);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ ;
+ }
-var isLeapYear = year => year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
+ function ___syscall_fchmod(fd, mode) {
+ try {
+
+ FS.fchmod(fd, mode);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-var MONTH_DAYS_LEAP_CUMULATIVE = [ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 ];
+ function ___syscall_fchown32(fd, owner, group) {
+ try {
+
+ FS.fchown(fd, owner, group);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-var MONTH_DAYS_REGULAR_CUMULATIVE = [ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 ];
+ function ___syscall_fchownat(dirfd, path, owner, group, flags) {
+ try {
+
+ path = SYSCALLS.getStr(path);
+ var nofollow = flags & 256;
+ flags = flags & (~256);
+ path = SYSCALLS.calculateAt(dirfd, path);
+ (nofollow ? FS.lchown : FS.chown)(path, owner, group);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-var 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;
- return yday;
-};
+
+ function ___syscall_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.createStream(stream, 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 5:
+ /* case 5: 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 6:
+ case 7:
+ /* case 6: Currently in musl F_SETLK64 has same value as F_SETLK, so omitted to avoid duplicate case blocks. If that changes, uncomment this */
+ /* case 7: 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 fcntl() returns that, and we set errno ourselves.
+ setErrNo(28);
+ return -1;
+ default: {
+ return -28;
+ }
+ }
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-function __localtime_js(time_low, time_high, tmPtr) {
- var time = convertI32PairToI53Checked(time_low, time_high);
- var date = new Date(time * 1e3);
- HEAP32[tmPtr >> 2] = date.getSeconds();
- HEAP32[tmPtr + 4 >> 2] = date.getMinutes();
- HEAP32[tmPtr + 8 >> 2] = date.getHours();
- HEAP32[tmPtr + 12 >> 2] = date.getDate();
- HEAP32[tmPtr + 16 >> 2] = date.getMonth();
- HEAP32[tmPtr + 20 >> 2] = date.getFullYear() - 1900;
- HEAP32[tmPtr + 24 >> 2] = date.getDay();
- var yday = ydayFromDate(date) | 0;
- HEAP32[tmPtr + 28 >> 2] = yday;
- HEAP32[tmPtr + 36 >> 2] = -(date.getTimezoneOffset() * 60);
- var start = new Date(date.getFullYear(), 0, 1);
- var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset();
- var winterOffset = start.getTimezoneOffset();
- var dst = (summerOffset != winterOffset && date.getTimezoneOffset() == Math.min(winterOffset, summerOffset)) | 0;
- HEAP32[tmPtr + 32 >> 2] = dst;
-}
+ function ___syscall_fdatasync(fd) {
+ try {
+
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ return 0; // we can't do anything synchronously; the in-memory FS is already synced to
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-var __mktime_js = function(tmPtr) {
- var ret = (() => {
- var date = new Date(HEAP32[tmPtr + 20 >> 2] + 1900, HEAP32[tmPtr + 16 >> 2], HEAP32[tmPtr + 12 >> 2], HEAP32[tmPtr + 8 >> 2], HEAP32[tmPtr + 4 >> 2], HEAP32[tmPtr >> 2], 0);
- var dst = HEAP32[tmPtr + 32 >> 2];
- var guessedOffset = date.getTimezoneOffset();
- var start = new Date(date.getFullYear(), 0, 1);
- var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset();
- var winterOffset = start.getTimezoneOffset();
- var dstOffset = Math.min(winterOffset, summerOffset);
- if (dst < 0) {
- HEAP32[tmPtr + 32 >> 2] = Number(summerOffset != winterOffset && dstOffset == guessedOffset);
- } else if (dst > 0 != (dstOffset == guessedOffset)) {
- var nonDstOffset = Math.max(winterOffset, summerOffset);
- var trueOffset = dst > 0 ? dstOffset : nonDstOffset;
- date.setTime(date.getTime() + (trueOffset - guessedOffset) * 6e4);
- }
- HEAP32[tmPtr + 24 >> 2] = date.getDay();
- var yday = ydayFromDate(date) | 0;
- HEAP32[tmPtr + 28 >> 2] = yday;
- HEAP32[tmPtr >> 2] = date.getSeconds();
- HEAP32[tmPtr + 4 >> 2] = date.getMinutes();
- HEAP32[tmPtr + 8 >> 2] = date.getHours();
- HEAP32[tmPtr + 12 >> 2] = date.getDate();
- HEAP32[tmPtr + 16 >> 2] = date.getMonth();
- HEAP32[tmPtr + 20 >> 2] = date.getYear();
- return date.getTime() / 1e3;
- })();
- return setTempRet0((tempDouble = ret, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? +Math.floor(tempDouble / 4294967296) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0)),
- ret >>> 0;
-};
+ function ___syscall_fstat64(fd, buf) {
+ try {
+
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ return SYSCALLS.doStat(FS.stat, stream.path, buf);
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-function __mmap_js(len, prot, flags, fd, offset_low, offset_high, allocated, addr) {
- var offset = convertI32PairToI53Checked(offset_low, offset_high);
- try {
- if (isNaN(offset)) return 61;
- var stream = SYSCALLS.getStreamFromFD(fd);
- var res = FS.mmap(stream, len, offset, prot, flags);
- var ptr = res.ptr;
- HEAP32[allocated >> 2] = res.allocated;
- HEAPU32[addr >> 2] = ptr;
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
+
+ function ___syscall_ftruncate64(fd,length_low, length_high) {
+ var length = convertI32PairToI53Checked(length_low, length_high);;
+
+
+ try {
+
+ if (isNaN(length)) return 61;
+ FS.ftruncate(fd, length);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ ;
+ }
-function __munmap_js(addr, len, prot, flags, fd, offset_low, offset_high) {
- var offset = convertI32PairToI53Checked(offset_low, offset_high);
- try {
- if (isNaN(offset)) return 61;
- var stream = SYSCALLS.getStreamFromFD(fd);
- if (prot & 2) {
- SYSCALLS.doMsync(addr, stream, len, flags, offset);
- }
- FS.munmap(stream);
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
-}
+
+ var stringToUTF8 = (str, outPtr, maxBytesToWrite) => {
+ return stringToUTF8Array(str, HEAPU8,outPtr, maxBytesToWrite);
+ };
+ Module['stringToUTF8'] = stringToUTF8;
+
+ function ___syscall_getcwd(buf, size) {
+ try {
+
+ if (size === 0) return -28;
+ var cwd = FS.cwd();
+ var cwdLengthInBytes = lengthBytesUTF8(cwd) + 1;
+ if (size < cwdLengthInBytes) return -68;
+ stringToUTF8(cwd, buf, size);
+ return cwdLengthInBytes;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-var timers = {};
+
+ function ___syscall_getdents64(fd, dirp, count) {
+ try {
+
+ var stream = SYSCALLS.getStreamFromFD(fd)
+ if (!stream.getdents) {
+ stream.getdents = FS.readdir(stream.path);
+ }
+
+ var struct_size = 280;
+ var pos = 0;
+ var off = FS.llseek(stream, 0, 1);
+
+ var idx = Math.floor(off / struct_size);
+
+ while (idx < stream.getdents.length && pos + struct_size <= count) {
+ var id;
+ var type;
+ var name = stream.getdents[idx];
+ if (name === '.') {
+ id = stream.node.id;
+ type = 4; // DT_DIR
+ }
+ else if (name === '..') {
+ var lookup = FS.lookupPath(stream.path, { parent: true });
+ id = lookup.node.id;
+ type = 4; // DT_DIR
+ }
+ else {
+ var child = FS.lookupNode(stream.node, name);
+ id = child.id;
+ type = FS.isChrdev(child.mode) ? 2 : // DT_CHR, character device.
+ FS.isDir(child.mode) ? 4 : // DT_DIR, directory.
+ FS.isLink(child.mode) ? 10 : // DT_LNK, symbolic link.
+ 8; // DT_REG, regular file.
+ }
+ (tempI64 = [id>>>0,(tempDouble=id,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[((dirp + pos)>>2)] = tempI64[0],HEAP32[(((dirp + pos)+(4))>>2)] = tempI64[1]);
+ (tempI64 = [(idx + 1) * struct_size>>>0,(tempDouble=(idx + 1) * struct_size,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((dirp + pos)+(8))>>2)] = tempI64[0],HEAP32[(((dirp + pos)+(12))>>2)] = tempI64[1]);
+ HEAP16[(((dirp + pos)+(16))>>1)] = 280;
+ HEAP8[(((dirp + pos)+(18))>>0)] = type;
+ stringToUTF8(name, dirp + pos + 19, 256);
+ pos += struct_size;
+ idx += 1;
+ }
+ FS.llseek(stream, idx * struct_size, 0);
+ return pos;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-var handleException = e => {
- if (e instanceof ExitStatus || e == "unwind") {
- return EXITSTATUS;
- }
- quit_(1, e);
-};
+
+
+
+ function ___syscall_getpeername(fd, addr, addrlen, d1, d2, d3) {
+ try {
+
+ var sock = getSocketFromFD(fd);
+ if (!sock.daddr) {
+ return -53; // The socket is not connected.
+ }
+ var errno = writeSockaddr(addr, sock.family, DNS.lookup_name(sock.daddr), sock.dport, addrlen);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-var _proc_exit = code => {
- EXITSTATUS = code;
- if (!keepRuntimeAlive()) {
- if (Module["onExit"]) Module["onExit"](code);
- ABORT = true;
- }
- quit_(code, new ExitStatus(code));
-};
+
+
+
+ function ___syscall_getsockname(fd, addr, addrlen, d1, d2, d3) {
+ try {
+
+ var sock = getSocketFromFD(fd);
+ // TODO: sock.saddr should never be undefined, see TODO in websocket_sock_ops.getname
+ var errno = writeSockaddr(addr, sock.family, DNS.lookup_name(sock.saddr || '0.0.0.0'), sock.sport, addrlen);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-var exitJS = (status, implicit) => {
- EXITSTATUS = status;
- if (!keepRuntimeAlive()) {
- exitRuntime();
- }
- _proc_exit(status);
-};
+
+ function ___syscall_getsockopt(fd, level, optname, optval, optlen, d1) {
+ try {
+
+ var sock = getSocketFromFD(fd);
+ // Minimal getsockopt aimed at resolving https://github.com/emscripten-core/emscripten/issues/2211
+ // so only supports SOL_SOCKET with SO_ERROR.
+ if (level === 1) {
+ if (optname === 4) {
+ HEAP32[((optval)>>2)] = sock.error;
+ HEAP32[((optlen)>>2)] = 4;
+ sock.error = null; // Clear the error (The SO_ERROR option obtains and then clears this field).
+ return 0;
+ }
+ }
+ return -50; // The option is unknown at the level indicated.
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-var _exit = exitJS;
+ function ___syscall_ioctl(fd, op, varargs) {
+ SYSCALLS.varargs = varargs;
+ try {
+
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ switch (op) {
+ case 21509: {
+ if (!stream.tty) return -59;
+ return 0;
+ }
+ case 21505: {
+ if (!stream.tty) return -59;
+ if (stream.tty.ops.ioctl_tcgets) {
+ var termios = stream.tty.ops.ioctl_tcgets(stream);
+ var argp = SYSCALLS.get();
+ HEAP32[((argp)>>2)] = termios.c_iflag || 0;
+ HEAP32[(((argp)+(4))>>2)] = termios.c_oflag || 0;
+ HEAP32[(((argp)+(8))>>2)] = termios.c_cflag || 0;
+ HEAP32[(((argp)+(12))>>2)] = termios.c_lflag || 0;
+ for (var i = 0; i < 32; i++) {
+ HEAP8[(((argp + i)+(17))>>0)] = termios.c_cc[i] || 0;
+ }
+ return 0;
+ }
+ return 0;
+ }
+ case 21510:
+ case 21511:
+ case 21512: {
+ if (!stream.tty) return -59;
+ return 0; // no-op, not actually adjusting terminal settings
+ }
+ case 21506:
+ case 21507:
+ case 21508: {
+ if (!stream.tty) return -59;
+ if (stream.tty.ops.ioctl_tcsets) {
+ var argp = SYSCALLS.get();
+ var c_iflag = HEAP32[((argp)>>2)];
+ var c_oflag = HEAP32[(((argp)+(4))>>2)];
+ var c_cflag = HEAP32[(((argp)+(8))>>2)];
+ var c_lflag = HEAP32[(((argp)+(12))>>2)];
+ var c_cc = []
+ for (var i = 0; i < 32; i++) {
+ c_cc.push(HEAP8[(((argp + i)+(17))>>0)]);
+ }
+ return stream.tty.ops.ioctl_tcsets(stream.tty, op, { c_iflag, c_oflag, c_cflag, c_lflag, c_cc });
+ }
+ 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;
+ if (stream.tty.ops.ioctl_tiocgwinsz) {
+ var winsize = stream.tty.ops.ioctl_tiocgwinsz(stream.tty);
+ var argp = SYSCALLS.get();
+ HEAP16[((argp)>>1)] = winsize[0];
+ HEAP16[(((argp)+(2))>>1)] = winsize[1];
+ }
+ 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;
+ }
+ case 21515: {
+ if (!stream.tty) return -59;
+ return 0;
+ }
+ default: return -28; // not supported
+ }
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-Module["_exit"] = _exit;
+
+ function ___syscall_listen(fd, backlog) {
+ try {
+
+ var sock = getSocketFromFD(fd);
+ sock.sock_ops.listen(sock, backlog);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-var maybeExit = () => {
- if (runtimeExited) {
- return;
- }
- if (!keepRuntimeAlive()) {
+ function ___syscall_lstat64(path, buf) {
try {
- _exit(EXITSTATUS);
- } catch (e) {
- handleException(e);
+
+ path = SYSCALLS.getStr(path);
+ return SYSCALLS.doStat(FS.lstat, path, buf);
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
}
- }
-};
-var callUserCallback = func => {
- if (runtimeExited || ABORT) {
- return;
- }
- try {
- func();
- maybeExit();
- } catch (e) {
- handleException(e);
- }
-};
+ function ___syscall_mkdirat(dirfd, path, mode) {
+ try {
+
+ path = SYSCALLS.getStr(path);
+ path = SYSCALLS.calculateAt(dirfd, path);
+ // 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;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-var _emscripten_get_now;
-
-_emscripten_get_now = () => performance.now();
-
-var __setitimer_js = (which, timeout_ms) => {
- if (timers[which]) {
- clearTimeout(timers[which].id);
- delete timers[which];
- }
- if (!timeout_ms) return 0;
- var id = setTimeout((() => {
- delete timers[which];
- callUserCallback((() => __emscripten_timeout(which, _emscripten_get_now())));
- }), timeout_ms);
- timers[which] = {
- id: id,
- timeout_ms: timeout_ms
- };
- return 0;
-};
+ function ___syscall_newfstatat(dirfd, path, buf, flags) {
+ try {
+
+ path = SYSCALLS.getStr(path);
+ var nofollow = flags & 256;
+ var allowEmpty = flags & 4096;
+ flags = flags & (~6400);
+ path = SYSCALLS.calculateAt(dirfd, path, allowEmpty);
+ return SYSCALLS.doStat(nofollow ? FS.lstat : FS.stat, path, buf);
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-var stringToNewUTF8 = str => {
- var size = lengthBytesUTF8(str) + 1;
- var ret = _malloc(size);
- if (ret) stringToUTF8(str, ret, size);
- return ret;
-};
+ function ___syscall_openat(dirfd, path, flags, varargs) {
+ SYSCALLS.varargs = varargs;
+ try {
+
+ path = SYSCALLS.getStr(path);
+ path = SYSCALLS.calculateAt(dirfd, path);
+ var mode = varargs ? SYSCALLS.get() : 0;
+ return FS.open(path, flags, mode).fd;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+ var PIPEFS = {
+ BUCKET_BUFFER_SIZE:8192,
+ mount(mount) {
+ // Do not pollute the real root directory or its child nodes with pipes
+ // Looks like it is OK to create another pseudo-root node not linked to the FS.root hierarchy this way
+ return FS.createNode(null, '/', 16384 | 511 /* 0777 */, 0);
+ },
+ createPipe() {
+ var pipe = {
+ buckets: [],
+ // refcnt 2 because pipe has a read end and a write end. We need to be
+ // able to read from the read end after write end is closed.
+ refcnt : 2,
+ };
+
+ pipe.buckets.push({
+ buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),
+ offset: 0,
+ roffset: 0
+ });
+
+ var rName = PIPEFS.nextname();
+ var wName = PIPEFS.nextname();
+ var rNode = FS.createNode(PIPEFS.root, rName, 4096, 0);
+ var wNode = FS.createNode(PIPEFS.root, wName, 4096, 0);
+
+ rNode.pipe = pipe;
+ wNode.pipe = pipe;
+
+ var readableStream = FS.createStream({
+ path: rName,
+ node: rNode,
+ flags: 0,
+ seekable: false,
+ stream_ops: PIPEFS.stream_ops
+ });
+ rNode.stream = readableStream;
+
+ var writableStream = FS.createStream({
+ path: wName,
+ node: wNode,
+ flags: 1,
+ seekable: false,
+ stream_ops: PIPEFS.stream_ops
+ });
+ wNode.stream = writableStream;
+
+ return {
+ readable_fd: readableStream.fd,
+ writable_fd: writableStream.fd
+ };
+ },
+ stream_ops:{
+ poll(stream) {
+ var pipe = stream.node.pipe;
+
+ if ((stream.flags & 2097155) === 1) {
+ return (256 | 4);
+ }
+ if (pipe.buckets.length > 0) {
+ for (var i = 0; i < pipe.buckets.length; i++) {
+ var bucket = pipe.buckets[i];
+ if (bucket.offset - bucket.roffset > 0) {
+ return (64 | 1);
+ }
+ }
+ }
+
+ return 0;
+ },
+ ioctl(stream, request, varargs) {
+ return 28;
+ },
+ fsync(stream) {
+ return 28;
+ },
+ read(stream, buffer, offset, length, position /* ignored */) {
+ var pipe = stream.node.pipe;
+ var currentLength = 0;
+
+ for (var i = 0; i < pipe.buckets.length; i++) {
+ var bucket = pipe.buckets[i];
+ currentLength += bucket.offset - bucket.roffset;
+ }
+
+ assert(buffer instanceof ArrayBuffer || ArrayBuffer.isView(buffer));
+ var data = buffer.subarray(offset, offset + length);
+
+ if (length <= 0) {
+ return 0;
+ }
+ if (currentLength == 0) {
+ // Behave as if the read end is always non-blocking
+ throw new FS.ErrnoError(6);
+ }
+ var toRead = Math.min(currentLength, length);
+
+ var totalRead = toRead;
+ var toRemove = 0;
+
+ for (var i = 0; i < pipe.buckets.length; i++) {
+ var currBucket = pipe.buckets[i];
+ var bucketSize = currBucket.offset - currBucket.roffset;
+
+ if (toRead <= bucketSize) {
+ var tmpSlice = currBucket.buffer.subarray(currBucket.roffset, currBucket.offset);
+ if (toRead < bucketSize) {
+ tmpSlice = tmpSlice.subarray(0, toRead);
+ currBucket.roffset += toRead;
+ } else {
+ toRemove++;
+ }
+ data.set(tmpSlice);
+ break;
+ } else {
+ var tmpSlice = currBucket.buffer.subarray(currBucket.roffset, currBucket.offset);
+ data.set(tmpSlice);
+ data = data.subarray(tmpSlice.byteLength);
+ toRead -= tmpSlice.byteLength;
+ toRemove++;
+ }
+ }
+
+ if (toRemove && toRemove == pipe.buckets.length) {
+ // Do not generate excessive garbage in use cases such as
+ // write several bytes, read everything, write several bytes, read everything...
+ toRemove--;
+ pipe.buckets[toRemove].offset = 0;
+ pipe.buckets[toRemove].roffset = 0;
+ }
+
+ pipe.buckets.splice(0, toRemove);
+
+ return totalRead;
+ },
+ write(stream, buffer, offset, length, position /* ignored */) {
+ var pipe = stream.node.pipe;
+
+ assert(buffer instanceof ArrayBuffer || ArrayBuffer.isView(buffer));
+ var data = buffer.subarray(offset, offset + length);
+
+ var dataLen = data.byteLength;
+ if (dataLen <= 0) {
+ return 0;
+ }
+
+ var currBucket = null;
+
+ if (pipe.buckets.length == 0) {
+ currBucket = {
+ buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),
+ offset: 0,
+ roffset: 0
+ };
+ pipe.buckets.push(currBucket);
+ } else {
+ currBucket = pipe.buckets[pipe.buckets.length - 1];
+ }
+
+ assert(currBucket.offset <= PIPEFS.BUCKET_BUFFER_SIZE);
+
+ var freeBytesInCurrBuffer = PIPEFS.BUCKET_BUFFER_SIZE - currBucket.offset;
+ if (freeBytesInCurrBuffer >= dataLen) {
+ currBucket.buffer.set(data, currBucket.offset);
+ currBucket.offset += dataLen;
+ return dataLen;
+ } else if (freeBytesInCurrBuffer > 0) {
+ currBucket.buffer.set(data.subarray(0, freeBytesInCurrBuffer), currBucket.offset);
+ currBucket.offset += freeBytesInCurrBuffer;
+ data = data.subarray(freeBytesInCurrBuffer, data.byteLength);
+ }
+
+ var numBuckets = (data.byteLength / PIPEFS.BUCKET_BUFFER_SIZE) | 0;
+ var remElements = data.byteLength % PIPEFS.BUCKET_BUFFER_SIZE;
+
+ for (var i = 0; i < numBuckets; i++) {
+ var newBucket = {
+ buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),
+ offset: PIPEFS.BUCKET_BUFFER_SIZE,
+ roffset: 0
+ };
+ pipe.buckets.push(newBucket);
+ newBucket.buffer.set(data.subarray(0, PIPEFS.BUCKET_BUFFER_SIZE));
+ data = data.subarray(PIPEFS.BUCKET_BUFFER_SIZE, data.byteLength);
+ }
+
+ if (remElements > 0) {
+ var newBucket = {
+ buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),
+ offset: data.byteLength,
+ roffset: 0
+ };
+ pipe.buckets.push(newBucket);
+ newBucket.buffer.set(data);
+ }
+
+ return dataLen;
+ },
+ close(stream) {
+ var pipe = stream.node.pipe;
+ pipe.refcnt--;
+ if (pipe.refcnt === 0) {
+ pipe.buckets = null;
+ }
+ },
+ },
+ nextname() {
+ if (!PIPEFS.nextname.current) {
+ PIPEFS.nextname.current = 0;
+ }
+ return 'pipe[' + (PIPEFS.nextname.current++) + ']';
+ },
+ };
+
+ function ___syscall_pipe(fdPtr) {
+ try {
+
+ if (fdPtr == 0) {
+ throw new FS.ErrnoError(21);
+ }
+
+ var res = PIPEFS.createPipe();
+
+ HEAP32[((fdPtr)>>2)] = res.readable_fd;
+ HEAP32[(((fdPtr)+(4))>>2)] = res.writable_fd;
+
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-var __tzset_js = (timezone, daylight, tzname) => {
- var currentYear = (new Date).getFullYear();
- var winter = new Date(currentYear, 0, 1);
- var summer = new Date(currentYear, 6, 1);
- var winterOffset = winter.getTimezoneOffset();
- var summerOffset = summer.getTimezoneOffset();
- var stdTimezoneOffset = Math.max(winterOffset, summerOffset);
- HEAPU32[timezone >> 2] = stdTimezoneOffset * 60;
- HEAP32[daylight >> 2] = Number(winterOffset != summerOffset);
- function extractZone(date) {
- var match = date.toTimeString().match(/\(([A-Za-z ]+)\)$/);
- return match ? match[1] : "GMT";
- }
- var winterName = extractZone(winter);
- var summerName = extractZone(summer);
- var winterNamePtr = stringToNewUTF8(winterName);
- var summerNamePtr = stringToNewUTF8(summerName);
- if (summerOffset < winterOffset) {
- HEAPU32[tzname >> 2] = winterNamePtr;
- HEAPU32[tzname + 4 >> 2] = summerNamePtr;
- } else {
- HEAPU32[tzname >> 2] = summerNamePtr;
- HEAPU32[tzname + 4 >> 2] = winterNamePtr;
- }
-};
+ function ___syscall_poll(fds, nfds, timeout) {
+ try {
+
+ var nonzero = 0;
+ for (var i = 0; i < nfds; i++) {
+ var pollfd = fds + 8 * i;
+ var fd = HEAP32[((pollfd)>>2)];
+ var events = HEAP16[(((pollfd)+(4))>>1)];
+ var mask = 32;
+ var stream = FS.getStream(fd);
+ if (stream) {
+ mask = SYSCALLS.DEFAULT_POLLMASK;
+ if (stream.stream_ops?.poll) {
+ mask = stream.stream_ops.poll(stream, -1);
+ }
+ }
+ mask &= events | 8 | 16;
+ if (mask) nonzero++;
+ HEAP16[(((pollfd)+(6))>>1)] = mask;
+ }
+ return nonzero;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-var _abort = () => {
- abort("");
-};
+
+
+ function ___syscall_readlinkat(dirfd, path, buf, bufsize) {
+ try {
+
+ path = SYSCALLS.getStr(path);
+ path = SYSCALLS.calculateAt(dirfd, path);
+ 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;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-function _emscripten_date_now() {
- return Date.now();
-}
+
+
+
+ function ___syscall_recvfrom(fd, buf, len, flags, addr, addrlen) {
+ try {
+
+ var sock = getSocketFromFD(fd);
+ var msg = sock.sock_ops.recvmsg(sock, len, typeof flags !== "undefined" ? flags : 0);
+ if (!msg) return 0; // socket is closed
+ if (addr) {
+ var errno = writeSockaddr(addr, sock.family, DNS.lookup_name(msg.addr), msg.port, addrlen);
+ }
+ HEAPU8.set(msg.buffer, buf);
+ return msg.buffer.byteLength;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-var getHeapMax = () => 2147483648;
+ function ___syscall_renameat(olddirfd, oldpath, newdirfd, newpath) {
+ try {
+
+ oldpath = SYSCALLS.getStr(oldpath);
+ newpath = SYSCALLS.getStr(newpath);
+ oldpath = SYSCALLS.calculateAt(olddirfd, oldpath);
+ newpath = SYSCALLS.calculateAt(newdirfd, newpath);
+ FS.rename(oldpath, newpath);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-var _emscripten_get_heap_max = () => getHeapMax();
+ function ___syscall_rmdir(path) {
+ try {
+
+ path = SYSCALLS.getStr(path);
+ FS.rmdir(path);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-var _emscripten_memcpy_big = (dest, src, num) => HEAPU8.copyWithin(dest, src, src + num);
+
+
+ function ___syscall_sendto(fd, message, length, flags, addr, addr_len) {
+ try {
+
+ var sock = getSocketFromFD(fd);
+ var dest = getSocketAddress(addr, addr_len, true);
+ if (!dest) {
+ // send, no address provided
+ return FS.write(sock.stream, HEAP8,message, length);
+ }
+ // sendto an address
+ return sock.sock_ops.sendmsg(sock, HEAP8,message, length, dest.addr, dest.port);
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-var growMemory = size => {
- var b = wasmMemory.buffer;
- var pages = size - b.byteLength + 65535 >>> 16;
- try {
- wasmMemory.grow(pages);
- updateMemoryViews();
- return 1;
- } catch (e) {}
-};
+
+ function ___syscall_socket(domain, type, protocol) {
+ try {
+
+ var sock = SOCKFS.createSocket(domain, type, protocol);
+ return sock.stream.fd;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-var _emscripten_resize_heap = requestedSize => {
- var oldSize = HEAPU8.length;
- requestedSize >>>= 0;
- var maxHeapSize = getHeapMax();
- if (requestedSize > maxHeapSize) {
- return false;
- }
- var alignUp = (x, multiple) => x + (multiple - x % multiple) % multiple;
- for (var cutDown = 1; cutDown <= 4; cutDown *= 2) {
- var overGrownHeapSize = oldSize * (1 + .2 / cutDown);
- overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296);
- var newSize = Math.min(maxHeapSize, alignUp(Math.max(requestedSize, overGrownHeapSize), 65536));
- var replacement = growMemory(newSize);
- if (replacement) {
- return true;
- }
- }
- return false;
-};
+ function ___syscall_stat64(path, buf) {
+ try {
+
+ path = SYSCALLS.getStr(path);
+ return SYSCALLS.doStat(FS.stat, path, buf);
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-var runtimeKeepalivePush = () => {
- runtimeKeepaliveCounter += 1;
-};
+ function ___syscall_statfs64(path, size, buf) {
+ try {
+
+ path = SYSCALLS.getStr(path);
+ // NOTE: None of the constants here are true. We're just returning safe and
+ // sane values.
+ HEAP32[(((buf)+(4))>>2)] = 4096;
+ HEAP32[(((buf)+(40))>>2)] = 4096;
+ HEAP32[(((buf)+(8))>>2)] = 1000000;
+ HEAP32[(((buf)+(12))>>2)] = 500000;
+ HEAP32[(((buf)+(16))>>2)] = 500000;
+ HEAP32[(((buf)+(20))>>2)] = FS.nextInode;
+ HEAP32[(((buf)+(24))>>2)] = 1000000;
+ HEAP32[(((buf)+(28))>>2)] = 42;
+ HEAP32[(((buf)+(44))>>2)] = 2; // ST_NOSUID
+ HEAP32[(((buf)+(36))>>2)] = 255;
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-var runtimeKeepalivePop = () => {
- runtimeKeepaliveCounter -= 1;
-};
+ function ___syscall_symlink(target, linkpath) {
+ try {
+
+ target = SYSCALLS.getStr(target);
+ linkpath = SYSCALLS.getStr(linkpath);
+ FS.symlink(target, linkpath);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-var safeSetTimeout = (func, timeout) => {
- runtimeKeepalivePush();
- return setTimeout((() => {
- runtimeKeepalivePop();
- callUserCallback(func);
- }), timeout);
-};
+ function ___syscall_unlinkat(dirfd, path, flags) {
+ try {
+
+ path = SYSCALLS.getStr(path);
+ path = SYSCALLS.calculateAt(dirfd, path);
+ if (flags === 0) {
+ FS.unlink(path);
+ } else if (flags === 512) {
+ FS.rmdir(path);
+ } else {
+ abort('Invalid flags passed to unlinkat');
+ }
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-var _emscripten_sleep = function(ms) {
- return Asyncify.handleSleep((wakeUp => safeSetTimeout(wakeUp, ms)));
-};
+ function readI53FromI64(ptr) {
+ return HEAPU32[ptr>>2] + HEAP32[ptr+4>>2] * 4294967296;
+ }
+
+ function ___syscall_utimensat(dirfd, path, times, flags) {
+ try {
+
+ path = SYSCALLS.getStr(path);
+ path = SYSCALLS.calculateAt(dirfd, path, true);
+ if (!times) {
+ var atime = Date.now();
+ var mtime = atime;
+ } else {
+ var seconds = readI53FromI64(times);
+ var nanoseconds = HEAP32[(((times)+(8))>>2)];
+ atime = (seconds*1000) + (nanoseconds/(1000*1000));
+ times += 16;
+ seconds = readI53FromI64(times);
+ nanoseconds = HEAP32[(((times)+(8))>>2)];
+ mtime = (seconds*1000) + (nanoseconds/(1000*1000));
+ }
+ FS.utime(path, atime, mtime);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
-Module["_emscripten_sleep"] = _emscripten_sleep;
+ var nowIsMonotonic = true;;
+ var __emscripten_get_now_is_monotonic = () => nowIsMonotonic;
-_emscripten_sleep.isAsync = true;
+ var __emscripten_throw_longjmp = () => {
+ throw Infinity;
+ };
-var ENV = PHPLoader.ENV || {};
+ function __gmtime_js(time_low, time_high,tmPtr) {
+ var time = convertI32PairToI53Checked(time_low, time_high);;
+
+
+ var date = new Date(time * 1000);
+ HEAP32[((tmPtr)>>2)] = date.getUTCSeconds();
+ HEAP32[(((tmPtr)+(4))>>2)] = date.getUTCMinutes();
+ HEAP32[(((tmPtr)+(8))>>2)] = date.getUTCHours();
+ HEAP32[(((tmPtr)+(12))>>2)] = date.getUTCDate();
+ HEAP32[(((tmPtr)+(16))>>2)] = date.getUTCMonth();
+ HEAP32[(((tmPtr)+(20))>>2)] = date.getUTCFullYear()-1900;
+ HEAP32[(((tmPtr)+(24))>>2)] = date.getUTCDay();
+ var start = Date.UTC(date.getUTCFullYear(), 0, 1, 0, 0, 0, 0);
+ var yday = ((date.getTime() - start) / (1000 * 60 * 60 * 24))|0;
+ HEAP32[(((tmPtr)+(28))>>2)] = yday;
+ ;
+ }
+
+ var 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_REGULAR_CUMULATIVE = [0,31,59,90,120,151,181,212,243,273,304,334];
+ var 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;
+ };
+
+ function __localtime_js(time_low, time_high,tmPtr) {
+ var time = convertI32PairToI53Checked(time_low, time_high);;
+
+
+ var date = new Date(time*1000);
+ HEAP32[((tmPtr)>>2)] = date.getSeconds();
+ HEAP32[(((tmPtr)+(4))>>2)] = date.getMinutes();
+ HEAP32[(((tmPtr)+(8))>>2)] = date.getHours();
+ HEAP32[(((tmPtr)+(12))>>2)] = date.getDate();
+ HEAP32[(((tmPtr)+(16))>>2)] = date.getMonth();
+ HEAP32[(((tmPtr)+(20))>>2)] = date.getFullYear()-1900;
+ HEAP32[(((tmPtr)+(24))>>2)] = date.getDay();
+
+ var yday = ydayFromDate(date)|0;
+ HEAP32[(((tmPtr)+(28))>>2)] = yday;
+ HEAP32[(((tmPtr)+(36))>>2)] = -(date.getTimezoneOffset() * 60);
+
+ // Attention: DST is in December in South, and some regions don't have DST at all.
+ var start = new Date(date.getFullYear(), 0, 1);
+ var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset();
+ var winterOffset = start.getTimezoneOffset();
+ var dst = (summerOffset != winterOffset && date.getTimezoneOffset() == Math.min(winterOffset, summerOffset))|0;
+ HEAP32[(((tmPtr)+(32))>>2)] = dst;
+ ;
+ }
+
+
+
+ var __mktime_js = function(tmPtr) {
+
+ var ret = (() => {
+ var date = new Date(HEAP32[(((tmPtr)+(20))>>2)] + 1900,
+ HEAP32[(((tmPtr)+(16))>>2)],
+ HEAP32[(((tmPtr)+(12))>>2)],
+ HEAP32[(((tmPtr)+(8))>>2)],
+ HEAP32[(((tmPtr)+(4))>>2)],
+ HEAP32[((tmPtr)>>2)],
+ 0);
+
+ // There's an ambiguous hour when the time goes back; the tm_isdst field is
+ // used to disambiguate it. Date() basically guesses, so we fix it up if it
+ // guessed wrong, or fill in tm_isdst with the guess if it's -1.
+ var dst = HEAP32[(((tmPtr)+(32))>>2)];
+ var guessedOffset = date.getTimezoneOffset();
+ var start = new Date(date.getFullYear(), 0, 1);
+ var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset();
+ var winterOffset = start.getTimezoneOffset();
+ var dstOffset = Math.min(winterOffset, summerOffset); // DST is in December in South
+ if (dst < 0) {
+ // Attention: some regions don't have DST at all.
+ HEAP32[(((tmPtr)+(32))>>2)] = Number(summerOffset != winterOffset && dstOffset == guessedOffset);
+ } else if ((dst > 0) != (dstOffset == guessedOffset)) {
+ var nonDstOffset = Math.max(winterOffset, summerOffset);
+ var trueOffset = dst > 0 ? dstOffset : nonDstOffset;
+ // Don't try setMinutes(date.getMinutes() + ...) -- it's messed up.
+ date.setTime(date.getTime() + (trueOffset - guessedOffset)*60000);
+ }
+
+ HEAP32[(((tmPtr)+(24))>>2)] = date.getDay();
+ var yday = ydayFromDate(date)|0;
+ HEAP32[(((tmPtr)+(28))>>2)] = yday;
+ // To match expected behavior, update fields from date
+ HEAP32[((tmPtr)>>2)] = date.getSeconds();
+ HEAP32[(((tmPtr)+(4))>>2)] = date.getMinutes();
+ HEAP32[(((tmPtr)+(8))>>2)] = date.getHours();
+ HEAP32[(((tmPtr)+(12))>>2)] = date.getDate();
+ HEAP32[(((tmPtr)+(16))>>2)] = date.getMonth();
+ HEAP32[(((tmPtr)+(20))>>2)] = date.getYear();
+
+ return date.getTime() / 1000;
+ })();
+ return (setTempRet0((tempDouble=ret,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)), ret>>>0);
+ };
-var getExecutableName = () => thisProgram || "./this.program";
+
+
+
+
+
+ function __mmap_js(len,prot,flags,fd,offset_low, offset_high,allocated,addr) {
+ var offset = convertI32PairToI53Checked(offset_low, offset_high);;
+
+
+ try {
+
+ if (isNaN(offset)) return 61;
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ var res = FS.mmap(stream, len, offset, prot, flags);
+ var ptr = res.ptr;
+ HEAP32[((allocated)>>2)] = res.allocated;
+ HEAPU32[((addr)>>2)] = ptr;
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ ;
+ }
-var getEnvStrings = () => {
- if (!getEnvStrings.strings) {
- 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()
- };
- for (var x in ENV) {
- if (ENV[x] === undefined) delete env[x]; else env[x] = ENV[x];
+
+
+
+ function __munmap_js(addr,len,prot,flags,fd,offset_low, offset_high) {
+ var offset = convertI32PairToI53Checked(offset_low, offset_high);;
+
+
+ try {
+
+ if (isNaN(offset)) return 61;
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ if (prot & 2) {
+ SYSCALLS.doMsync(addr, stream, len, flags, offset);
+ }
+ FS.munmap(stream);
+ // implicitly return 0
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
}
- var strings = [];
- for (var x in env) {
- strings.push(`${x}=${env[x]}`);
+ ;
}
- getEnvStrings.strings = strings;
- }
- return getEnvStrings.strings;
-};
-var stringToAscii = (str, buffer) => {
- for (var i = 0; i < str.length; ++i) {
- HEAP8[buffer++ >> 0] = str.charCodeAt(i);
- }
- HEAP8[buffer >> 0] = 0;
-};
+ var timers = {
+ };
+
+ var handleException = (e) => {
+ // Certain exception types we do not treat as errors since they are used for
+ // internal control flow.
+ // 1. ExitStatus, which is thrown by exit()
+ // 2. "unwind", which is thrown by emscripten_unwind_to_js_event_loop() and others
+ // that wish to return to JS event loop.
+ if (e instanceof ExitStatus || e == 'unwind') {
+ return EXITSTATUS;
+ }
+ quit_(1, e);
+ };
+
+
+ var _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 */
+ var exitJS = (status, implicit) => {
+ EXITSTATUS = status;
+
+ if (!keepRuntimeAlive()) {
+ exitRuntime();
+ }
+
+ _proc_exit(status);
+ };
+ var _exit = exitJS;
+ Module['_exit'] = _exit;
+
+ var maybeExit = () => {
+ if (runtimeExited) {
+ return;
+ }
+ if (!keepRuntimeAlive()) {
+ try {
+ _exit(EXITSTATUS);
+ } catch (e) {
+ handleException(e);
+ }
+ }
+ };
+ var callUserCallback = (func) => {
+ if (runtimeExited || ABORT) {
+ return;
+ }
+ try {
+ func();
+ maybeExit();
+ } catch (e) {
+ handleException(e);
+ }
+ };
+
+
+ var _emscripten_get_now;
+ // Modern environment where performance.now() is supported:
+ // N.B. a shorter form "_emscripten_get_now = performance.now;" is
+ // unfortunately not allowed even in current browsers (e.g. FF Nightly 75).
+ _emscripten_get_now = () => performance.now();
+ ;
+ var __setitimer_js = (which, timeout_ms) => {
+ // First, clear any existing timer.
+ if (timers[which]) {
+ clearTimeout(timers[which].id);
+ delete timers[which];
+ }
+
+ // A timeout of zero simply cancels the current timeout so we have nothing
+ // more to do.
+ if (!timeout_ms) return 0;
+
+ var id = setTimeout(() => {
+ delete timers[which];
+ callUserCallback(() => __emscripten_timeout(which, _emscripten_get_now()));
+ }, timeout_ms);
+ timers[which] = { id, timeout_ms };
+ return 0;
+ };
-var _environ_get = (__environ, environ_buf) => {
- var bufSize = 0;
- getEnvStrings().forEach((function(string, i) {
- var ptr = environ_buf + bufSize;
- HEAPU32[__environ + i * 4 >> 2] = ptr;
- stringToAscii(string, ptr);
- bufSize += string.length + 1;
- }));
- return 0;
-};
+
+
+ var stringToNewUTF8 = (str) => {
+ var size = lengthBytesUTF8(str) + 1;
+ var ret = _malloc(size);
+ if (ret) stringToUTF8(str, ret, size);
+ return ret;
+ };
+ var __tzset_js = (timezone, daylight, tzname) => {
+ // TODO: Use (malleable) environment variables instead of system settings.
+ var currentYear = new Date().getFullYear();
+ var winter = new Date(currentYear, 0, 1);
+ var summer = new Date(currentYear, 6, 1);
+ var winterOffset = winter.getTimezoneOffset();
+ var summerOffset = summer.getTimezoneOffset();
+
+ // Local standard timezone offset. Local standard time is not adjusted for daylight savings.
+ // This code uses the fact that getTimezoneOffset returns a greater value during Standard Time versus Daylight Saving Time (DST).
+ // Thus it determines the expected output during Standard Time, and it compares whether the output of the given date the same (Standard) or less (DST).
+ var stdTimezoneOffset = Math.max(winterOffset, summerOffset);
+
+ // timezone is specified as seconds west of UTC ("The external variable
+ // `timezone` shall be set to the difference, in seconds, between
+ // Coordinated Universal Time (UTC) and local standard time."), the same
+ // as returned by stdTimezoneOffset.
+ // See http://pubs.opengroup.org/onlinepubs/009695399/functions/tzset.html
+ HEAPU32[((timezone)>>2)] = stdTimezoneOffset * 60;
+
+ HEAP32[((daylight)>>2)] = Number(winterOffset != summerOffset);
+
+ function extractZone(date) {
+ var match = date.toTimeString().match(/\(([A-Za-z ]+)\)$/);
+ return match ? match[1] : "GMT";
+ };
+ var winterName = extractZone(winter);
+ var summerName = extractZone(summer);
+ var winterNamePtr = stringToNewUTF8(winterName);
+ var summerNamePtr = stringToNewUTF8(summerName);
+ if (summerOffset < winterOffset) {
+ // Northern hemisphere
+ HEAPU32[((tzname)>>2)] = winterNamePtr;
+ HEAPU32[(((tzname)+(4))>>2)] = summerNamePtr;
+ } else {
+ HEAPU32[((tzname)>>2)] = summerNamePtr;
+ HEAPU32[(((tzname)+(4))>>2)] = winterNamePtr;
+ }
+ };
-var _environ_sizes_get = (penviron_count, penviron_buf_size) => {
- var strings = getEnvStrings();
- HEAPU32[penviron_count >> 2] = strings.length;
- var bufSize = 0;
- strings.forEach((function(string) {
- bufSize += string.length + 1;
- }));
- HEAPU32[penviron_buf_size >> 2] = bufSize;
- return 0;
-};
+ var _abort = () => {
+ abort('');
+ };
-function _fd_close(fd) {
- try {
- var stream = SYSCALLS.getStreamFromFD(fd);
- FS.close(stream);
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return e.errno;
- }
-}
+ function _emscripten_date_now() {
+ return Date.now();
+ }
-function _fd_fdstat_get(fd, pbuf) {
- try {
- var rightsBase = 0;
- var rightsInheriting = 0;
- var flags = 0;
- {
- var stream = SYSCALLS.getStreamFromFD(fd);
- var type = stream.tty ? 2 : FS.isDir(stream.mode) ? 3 : FS.isLink(stream.mode) ? 7 : 4;
- }
- HEAP8[pbuf >> 0] = type;
- HEAP16[pbuf + 2 >> 1] = flags;
- tempI64 = [ rightsBase >>> 0, (tempDouble = rightsBase, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? +Math.floor(tempDouble / 4294967296) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ],
- HEAP32[pbuf + 8 >> 2] = tempI64[0], HEAP32[pbuf + 12 >> 2] = tempI64[1];
- tempI64 = [ rightsInheriting >>> 0, (tempDouble = rightsInheriting, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? +Math.floor(tempDouble / 4294967296) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ],
- HEAP32[pbuf + 16 >> 2] = tempI64[0], HEAP32[pbuf + 20 >> 2] = tempI64[1];
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return e.errno;
- }
-}
+ var getHeapMax = () =>
+ // Stay one Wasm page short of 4GB: while e.g. Chrome is able to allocate
+ // full 4GB Wasm memories, the size will wrap back to 0 bytes in Wasm side
+ // for any code that deals with heap sizes, which would require special
+ // casing all heap size related code to treat 0 specially.
+ 2147483648;
+ var _emscripten_get_heap_max = () => getHeapMax();
-var doReadv = (stream, iov, iovcnt, offset) => {
- var ret = 0;
- for (var i = 0; i < iovcnt; i++) {
- var ptr = HEAPU32[iov >> 2];
- var len = HEAPU32[iov + 4 >> 2];
- iov += 8;
- var curr = FS.read(stream, HEAP8, ptr, len, offset);
- if (curr < 0) return -1;
- ret += curr;
- if (curr < len) break;
- if (typeof offset !== "undefined") {
- offset += curr;
- }
- }
- return ret;
-};
-function _fd_read(fd, iov, iovcnt, pnum) {
- try {
- var stream = SYSCALLS.getStreamFromFD(fd);
- var num = doReadv(stream, iov, iovcnt);
- HEAPU32[pnum >> 2] = num;
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return e.errno;
- }
-}
+ var _emscripten_memcpy_big = (dest, src, num) => HEAPU8.copyWithin(dest, src, src + num);
-function _fd_seek(fd, offset_low, offset_high, whence, newOffset) {
- var offset = convertI32PairToI53Checked(offset_low, offset_high);
- try {
- if (isNaN(offset)) return 61;
- var stream = SYSCALLS.getStreamFromFD(fd);
- FS.llseek(stream, offset, whence);
- tempI64 = [ stream.position >>> 0, (tempDouble = stream.position, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? +Math.floor(tempDouble / 4294967296) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ],
- HEAP32[newOffset >> 2] = tempI64[0], HEAP32[newOffset + 4 >> 2] = tempI64[1];
- if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null;
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return e.errno;
- }
-}
+
+ var growMemory = (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(pages); // .grow() takes a delta compared to the previous size
+ updateMemoryViews();
+ return 1 /*success*/;
+ } catch(e) {
+ }
+ // implicit 0 return to save code size (caller will cast "undefined" into 0
+ // anyhow)
+ };
+ var _emscripten_resize_heap = (requestedSize) => {
+ var oldSize = HEAPU8.length;
+ // With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned.
+ requestedSize >>>= 0;
+ // With multithreaded builds, races can happen (another thread might increase the size
+ // in between), so return a failure, and let the caller retry.
+
+ // Memory resize rules:
+ // 1. Always increase heap size to at least the requested size, rounded up
+ // to next page multiple.
+ // 2a. If MEMORY_GROWTH_LINEAR_STEP == -1, excessively resize the heap
+ // geometrically: increase the heap size according to
+ // MEMORY_GROWTH_GEOMETRIC_STEP factor (default +20%), At most
+ // overreserve by MEMORY_GROWTH_GEOMETRIC_CAP bytes (default 96MB).
+ // 2b. If MEMORY_GROWTH_LINEAR_STEP != -1, excessively resize the heap
+ // linearly: increase the heap size by at least
+ // MEMORY_GROWTH_LINEAR_STEP bytes.
+ // 3. Max size for the heap is capped at 2048MB-WASM_PAGE_SIZE, or by
+ // MAXIMUM_MEMORY, or by ASAN limit, depending on which is smallest
+ // 4. If we were unable to allocate as much memory, it may be due to
+ // over-eager decision to excessively reserve due to (3) above.
+ // Hence if an allocation fails, cut down on the amount of excess
+ // growth, in an attempt to succeed to perform a smaller allocation.
+
+ // A limit is set for how much we can grow. We should not exceed that
+ // (the wasm binary specifies it, so if we tried, we'd fail anyhow).
+ var maxHeapSize = getHeapMax();
+ if (requestedSize > maxHeapSize) {
+ return false;
+ }
+
+ 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
+ // smaller bump instead. (max 3 times, chosen somewhat arbitrarily)
+ for (var cutDown = 1; cutDown <= 4; cutDown *= 2) {
+ var overGrownHeapSize = oldSize * (1 + 0.2 / cutDown); // ensure geometric growth
+ // but limit overreserving (default to capping at +96MB overgrowth at most)
+ overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296 );
+
+ var newSize = Math.min(maxHeapSize, alignUp(Math.max(requestedSize, overGrownHeapSize), 65536));
+
+ var replacement = growMemory(newSize);
+ if (replacement) {
+
+ return true;
+ }
+ }
+ return false;
+ };
-function _fd_sync(fd) {
- try {
- var stream = SYSCALLS.getStreamFromFD(fd);
- return Asyncify.handleSleep((function(wakeUp) {
- var mount = stream.node.mount;
- if (!mount.type.syncfs) {
- wakeUp(0);
- return;
- }
- mount.type.syncfs(mount, false, (function(err) {
- if (err) {
- wakeUp((function() {
- return 29;
- }));
- return;
- }
- wakeUp(0);
- }));
- }));
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return e.errno;
- }
-}
+
+ var runtimeKeepalivePush = () => {
+ runtimeKeepaliveCounter += 1;
+ };
+
+ var runtimeKeepalivePop = () => {
+ runtimeKeepaliveCounter -= 1;
+ };
+ /** @param {number=} timeout */
+ var safeSetTimeout = (func, timeout) => {
+ runtimeKeepalivePush();
+ return setTimeout(() => {
+ runtimeKeepalivePop();
+ callUserCallback(func);
+ }, timeout);
+ };
+ var _emscripten_sleep = function(ms) {
+ // emscripten_sleep() does not return a value, but we still need a |return|
+ // here for stack switching support (ASYNCIFY=2). In that mode this function
+ // returns a Promise instead of nothing, and that Promise is what tells the
+ // wasm VM to pause the stack.
+ return Asyncify.handleSleep((wakeUp) => safeSetTimeout(wakeUp, ms));
+ };
+ Module['_emscripten_sleep'] = _emscripten_sleep;
+ _emscripten_sleep.isAsync = true;
-var doWritev = (stream, iov, iovcnt, offset) => {
- var ret = 0;
- for (var i = 0; i < iovcnt; i++) {
- var ptr = HEAPU32[iov >> 2];
- var len = HEAPU32[iov + 4 >> 2];
- iov += 8;
- var curr = FS.write(stream, HEAP8, ptr, len, offset);
- if (curr < 0) return -1;
- ret += curr;
- if (typeof offset !== "undefined") {
- offset += curr;
- }
- }
- return ret;
-};
+ var ENV = PHPLoader.ENV || {
+ };
+
+ var getExecutableName = () => {
+ return thisProgram || './this.program';
+ };
+ var 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) {
+ // x is a key in ENV; if ENV[x] is undefined, that means it was
+ // explicitly set to be so. We allow user code to do that to
+ // force variables with default values to remain unset.
+ if (ENV[x] === undefined) delete env[x];
+ else env[x] = ENV[x];
+ }
+ var strings = [];
+ for (var x in env) {
+ strings.push(`${x}=${env[x]}`);
+ }
+ getEnvStrings.strings = strings;
+ }
+ return getEnvStrings.strings;
+ };
+
+ var stringToAscii = (str, buffer) => {
+ for (var i = 0; i < str.length; ++i) {
+ HEAP8[((buffer++)>>0)] = str.charCodeAt(i);
+ }
+ // Null-terminate the string
+ HEAP8[((buffer)>>0)] = 0;
+ };
+
+ var _environ_get = (__environ, environ_buf) => {
+ var bufSize = 0;
+ getEnvStrings().forEach(function(string, i) {
+ var ptr = environ_buf + bufSize;
+ HEAPU32[(((__environ)+(i*4))>>2)] = ptr;
+ stringToAscii(string, ptr);
+ bufSize += string.length + 1;
+ });
+ return 0;
+ };
-function _fd_write(fd, iov, iovcnt, pnum) {
- try {
- var stream = SYSCALLS.getStreamFromFD(fd);
- var num = doWritev(stream, iov, iovcnt);
- HEAPU32[pnum >> 2] = num;
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return e.errno;
- }
-}
+
+ var _environ_sizes_get = (penviron_count, penviron_buf_size) => {
+ var strings = getEnvStrings();
+ HEAPU32[((penviron_count)>>2)] = strings.length;
+ var bufSize = 0;
+ strings.forEach(function(string) {
+ bufSize += string.length + 1;
+ });
+ HEAPU32[((penviron_buf_size)>>2)] = bufSize;
+ return 0;
+ };
-var _getaddrinfo = (node, service, hint, out) => {
- var addr = 0;
- var port = 0;
- var flags = 0;
- var family = 0;
- var type = 0;
- var proto = 0;
- var ai;
- function allocaddrinfo(family, type, proto, canon, addr, port) {
- var sa, salen, ai;
- var errno;
- salen = family === 10 ? 28 : 16;
- addr = family === 10 ? inetNtop6(addr) : inetNtop4(addr);
- sa = _malloc(salen);
- errno = writeSockaddr(sa, family, addr, port);
- assert(!errno);
- ai = _malloc(32);
- HEAP32[ai + 4 >> 2] = family;
- HEAP32[ai + 8 >> 2] = type;
- HEAP32[ai + 12 >> 2] = proto;
- HEAPU32[ai + 24 >> 2] = canon;
- HEAPU32[ai + 20 >> 2] = sa;
- if (family === 10) {
- HEAP32[ai + 16 >> 2] = 28;
- } else {
- HEAP32[ai + 16 >> 2] = 16;
- }
- HEAP32[ai + 28 >> 2] = 0;
- return ai;
- }
- if (hint) {
- flags = HEAP32[hint >> 2];
- family = HEAP32[hint + 4 >> 2];
- type = HEAP32[hint + 8 >> 2];
- proto = HEAP32[hint + 12 >> 2];
- }
- if (type && !proto) {
- proto = type === 2 ? 17 : 6;
- }
- if (!type && proto) {
- type = proto === 17 ? 2 : 1;
- }
- if (proto === 0) {
- proto = 6;
- }
- if (type === 0) {
- type = 1;
- }
- if (!node && !service) {
- return -2;
- }
- if (flags & ~(1 | 2 | 4 | 1024 | 8 | 16 | 32)) {
- return -1;
- }
- if (hint !== 0 && HEAP32[hint >> 2] & 2 && !node) {
- return -1;
- }
- if (flags & 32) {
- return -2;
- }
- if (type !== 0 && type !== 1 && type !== 2) {
- return -7;
- }
- if (family !== 0 && family !== 2 && family !== 10) {
- return -6;
- }
- if (service) {
- service = UTF8ToString(service);
- port = parseInt(service, 10);
- if (isNaN(port)) {
- if (flags & 1024) {
- return -2;
- }
- return -8;
- }
- }
- if (!node) {
- if (family === 0) {
- family = 2;
- }
- if ((flags & 1) === 0) {
- if (family === 2) {
- addr = _htonl(2130706433);
- } else {
- addr = [ 0, 0, 0, 1 ];
- }
+
+ function _fd_close(fd) {
+ try {
+
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ FS.close(stream);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return e.errno;
}
- ai = allocaddrinfo(family, type, proto, null, addr, port);
- HEAPU32[out >> 2] = ai;
- return 0;
- }
- node = UTF8ToString(node);
- addr = inetPton4(node);
- if (addr !== null) {
- if (family === 0 || family === 2) {
- family = 2;
- } else if (family === 10 && flags & 8) {
- addr = [ 0, 0, _htonl(65535), addr ];
- family = 10;
- } else {
- return -2;
- }
- } else {
- addr = inetPton6(node);
- if (addr !== null) {
- if (family === 0 || family === 10) {
- family = 10;
- } else {
- return -2;
- }
}
- }
- if (addr != null) {
- ai = allocaddrinfo(family, type, proto, node, addr, port);
- HEAPU32[out >> 2] = ai;
- return 0;
- }
- if (flags & 4) {
- return -2;
- }
- node = DNS.lookup_name(node);
- addr = inetPton4(node);
- if (family === 0) {
- family = 2;
- } else if (family === 10) {
- addr = [ 0, 0, _htonl(65535), addr ];
- }
- ai = allocaddrinfo(family, type, proto, null, addr, port);
- HEAPU32[out >> 2] = ai;
- return 0;
-};
-
-function _getcontext() {
- err("missing function: getcontext");
- abort(-1);
-}
-function _getdtablesize() {
- err("missing function: getdtablesize");
- abort(-1);
-}
+ function _fd_fdstat_get(fd, pbuf) {
+ try {
+
+ var rightsBase = 0;
+ var rightsInheriting = 0;
+ var flags = 0;
+ {
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ // All character devices are terminals (other things a Linux system would
+ // assume is a character device, like the mouse, we have special APIs for).
+ var type = stream.tty ? 2 :
+ FS.isDir(stream.mode) ? 3 :
+ FS.isLink(stream.mode) ? 7 :
+ 4;
+ }
+ HEAP8[((pbuf)>>0)] = type;
+ HEAP16[(((pbuf)+(2))>>1)] = flags;
+ (tempI64 = [rightsBase>>>0,(tempDouble=rightsBase,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((pbuf)+(8))>>2)] = tempI64[0],HEAP32[(((pbuf)+(12))>>2)] = tempI64[1]);
+ (tempI64 = [rightsInheriting>>>0,(tempDouble=rightsInheriting,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((pbuf)+(16))>>2)] = tempI64[0],HEAP32[(((pbuf)+(20))>>2)] = tempI64[1]);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return e.errno;
+ }
+ }
+
+ /** @param {number=} offset */
+ var doReadv = (stream, iov, iovcnt, offset) => {
+ var ret = 0;
+ for (var i = 0; i < iovcnt; i++) {
+ var ptr = HEAPU32[((iov)>>2)];
+ var len = HEAPU32[(((iov)+(4))>>2)];
+ iov += 8;
+ var curr = FS.read(stream, HEAP8,ptr, len, offset);
+ if (curr < 0) return -1;
+ ret += curr;
+ if (curr < len) break; // nothing more to read
+ if (typeof offset !== 'undefined') {
+ offset += curr;
+ }
+ }
+ return ret;
+ };
+
+ function _fd_read(fd, iov, iovcnt, pnum) {
+ try {
+
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ var num = doReadv(stream, iov, iovcnt);
+ HEAPU32[((pnum)>>2)] = num;
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return e.errno;
+ }
+ }
-var getHostByName = name => {
- var ret = _malloc(20);
- var nameBuf = stringToNewUTF8(name);
- HEAPU32[ret >> 2] = nameBuf;
- var aliasesBuf = _malloc(4);
- HEAPU32[aliasesBuf >> 2] = 0;
- HEAPU32[ret + 4 >> 2] = aliasesBuf;
- var afinet = 2;
- HEAP32[ret + 8 >> 2] = afinet;
- HEAP32[ret + 12 >> 2] = 4;
- var addrListBuf = _malloc(12);
- HEAPU32[addrListBuf >> 2] = addrListBuf + 8;
- HEAPU32[addrListBuf + 4 >> 2] = 0;
- HEAP32[addrListBuf + 8 >> 2] = inetPton4(DNS.lookup_name(name));
- HEAPU32[ret + 16 >> 2] = addrListBuf;
- return ret;
-};
+
+ function _fd_seek(fd,offset_low, offset_high,whence,newOffset) {
+ var offset = convertI32PairToI53Checked(offset_low, offset_high);;
+
+
+ try {
+
+ if (isNaN(offset)) return 61;
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ FS.llseek(stream, offset, whence);
+ (tempI64 = [stream.position>>>0,(tempDouble=stream.position,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.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.name === 'ErrnoError')) throw e;
+ return e.errno;
+ }
+ ;
+ }
-var _gethostbyname = name => getHostByName(UTF8ToString(name));
+ function _fd_sync(fd) {
+ try {
+
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ return Asyncify.handleSleep(function(wakeUp) {
+ var mount = stream.node.mount;
+ if (!mount.type.syncfs) {
+ // We write directly to the file system, so there's nothing to do here.
+ wakeUp(0);
+ return;
+ }
+ mount.type.syncfs(mount, false, function(err) {
+ if (err) {
+ wakeUp(function() { return 29 });
+ return;
+ }
+ wakeUp(0);
+ });
+ });
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return e.errno;
+ }
+ }
+
+ /** @param {number=} offset */
+ var doWritev = (stream, iov, iovcnt, offset) => {
+ var ret = 0;
+ for (var i = 0; i < iovcnt; i++) {
+ var ptr = HEAPU32[((iov)>>2)];
+ var len = HEAPU32[(((iov)+(4))>>2)];
+ iov += 8;
+ var curr = FS.write(stream, HEAP8,ptr, len, offset);
+ if (curr < 0) return -1;
+ ret += curr;
+ if (typeof offset !== 'undefined') {
+ offset += curr;
+ }
+ }
+ return ret;
+ };
+
+ function _fd_write(fd, iov, iovcnt, pnum) {
+ try {
+
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ var num = doWritev(stream, iov, iovcnt);
+ HEAPU32[((pnum)>>2)] = num;
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return e.errno;
+ }
+ }
+
+
+
+
+
+
+
+
+
+
+ var _getaddrinfo = (node, service, hint, out) => {
+ // Note getaddrinfo currently only returns a single addrinfo with ai_next defaulting to NULL. When NULL
+ // hints are specified or ai_family set to AF_UNSPEC or ai_socktype or ai_protocol set to 0 then we
+ // really should provide a linked list of suitable addrinfo values.
+ var addrs = [];
+ var canon = null;
+ var addr = 0;
+ var port = 0;
+ var flags = 0;
+ var family = 0;
+ var type = 0;
+ var proto = 0;
+ var ai, last;
+
+ function allocaddrinfo(family, type, proto, canon, addr, port) {
+ var sa, salen, ai;
+ var errno;
+
+ salen = family === 10 ?
+ 28 :
+ 16;
+ addr = family === 10 ?
+ inetNtop6(addr) :
+ inetNtop4(addr);
+ sa = _malloc(salen);
+ errno = writeSockaddr(sa, family, addr, port);
+ assert(!errno);
+
+ ai = _malloc(32);
+ HEAP32[(((ai)+(4))>>2)] = family;
+ HEAP32[(((ai)+(8))>>2)] = type;
+ HEAP32[(((ai)+(12))>>2)] = proto;
+ HEAPU32[(((ai)+(24))>>2)] = canon;
+ HEAPU32[(((ai)+(20))>>2)] = sa;
+ if (family === 10) {
+ HEAP32[(((ai)+(16))>>2)] = 28;
+ } else {
+ HEAP32[(((ai)+(16))>>2)] = 16;
+ }
+ HEAP32[(((ai)+(28))>>2)] = 0;
+
+ return ai;
+ }
+
+ if (hint) {
+ flags = HEAP32[((hint)>>2)];
+ family = HEAP32[(((hint)+(4))>>2)];
+ type = HEAP32[(((hint)+(8))>>2)];
+ proto = HEAP32[(((hint)+(12))>>2)];
+ }
+ if (type && !proto) {
+ proto = type === 2 ? 17 : 6;
+ }
+ if (!type && proto) {
+ type = proto === 17 ? 2 : 1;
+ }
+
+ // If type or proto are set to zero in hints we should really be returning multiple addrinfo values, but for
+ // now default to a TCP STREAM socket so we can at least return a sensible addrinfo given NULL hints.
+ if (proto === 0) {
+ proto = 6;
+ }
+ if (type === 0) {
+ type = 1;
+ }
+
+ if (!node && !service) {
+ return -2;
+ }
+ if (flags & ~(1|2|4|
+ 1024|8|16|32)) {
+ return -1;
+ }
+ if (hint !== 0 && (HEAP32[((hint)>>2)] & 2) && !node) {
+ return -1;
+ }
+ if (flags & 32) {
+ // TODO
+ return -2;
+ }
+ if (type !== 0 && type !== 1 && type !== 2) {
+ return -7;
+ }
+ if (family !== 0 && family !== 2 && family !== 10) {
+ return -6;
+ }
+
+ if (service) {
+ service = UTF8ToString(service);
+ port = parseInt(service, 10);
+
+ if (isNaN(port)) {
+ if (flags & 1024) {
+ return -2;
+ }
+ // TODO support resolving well-known service names from:
+ // http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.txt
+ return -8;
+ }
+ }
+
+ if (!node) {
+ if (family === 0) {
+ family = 2;
+ }
+ if ((flags & 1) === 0) {
+ if (family === 2) {
+ addr = _htonl(2130706433);
+ } else {
+ addr = [0, 0, 0, 1];
+ }
+ }
+ ai = allocaddrinfo(family, type, proto, null, addr, port);
+ HEAPU32[((out)>>2)] = ai;
+ return 0;
+ }
+
+ //
+ // try as a numeric address
+ //
+ node = UTF8ToString(node);
+ addr = inetPton4(node);
+ if (addr !== null) {
+ // incoming node is a valid ipv4 address
+ if (family === 0 || family === 2) {
+ family = 2;
+ }
+ else if (family === 10 && (flags & 8)) {
+ addr = [0, 0, _htonl(0xffff), addr];
+ family = 10;
+ } else {
+ return -2;
+ }
+ } else {
+ addr = inetPton6(node);
+ if (addr !== null) {
+ // incoming node is a valid ipv6 address
+ if (family === 0 || family === 10) {
+ family = 10;
+ } else {
+ return -2;
+ }
+ }
+ }
+ if (addr != null) {
+ ai = allocaddrinfo(family, type, proto, node, addr, port);
+ HEAPU32[((out)>>2)] = ai;
+ return 0;
+ }
+ if (flags & 4) {
+ return -2;
+ }
+
+ //
+ // try as a hostname
+ //
+ // resolve the hostname to a temporary fake address
+ node = DNS.lookup_name(node);
+ addr = inetPton4(node);
+ if (family === 0) {
+ family = 2;
+ } else if (family === 10) {
+ addr = [0, 0, _htonl(0xffff), addr];
+ }
+ ai = allocaddrinfo(family, type, proto, null, addr, port);
+ HEAPU32[((out)>>2)] = ai;
+ return 0;
+ };
-var _gethostbyname_r = (name, ret, buf, buflen, out, err) => {
- var data = _gethostbyname(name);
- _memcpy(ret, data, 20);
- _free(data);
- HEAP32[err >> 2] = 0;
- HEAPU32[out >> 2] = ret;
- return 0;
-};
+ /** @type {function(...*):?} */
+ function _getcontext(
+ ) {
+ err('missing function: getcontext'); abort(-1);
+ }
+
+ /** @type {function(...*):?} */
+ function _getdtablesize(
+ ) {
+ err('missing function: getdtablesize'); abort(-1);
+ }
+
+
+
+
+ var getHostByName = (name) => {
+ // generate hostent
+ var ret = _malloc(20); // XXX possibly leaked, as are others here
+ var nameBuf = stringToNewUTF8(name);
+ HEAPU32[((ret)>>2)] = nameBuf;
+ var aliasesBuf = _malloc(4);
+ HEAPU32[((aliasesBuf)>>2)] = 0;
+ HEAPU32[(((ret)+(4))>>2)] = aliasesBuf;
+ var afinet = 2;
+ HEAP32[(((ret)+(8))>>2)] = afinet;
+ HEAP32[(((ret)+(12))>>2)] = 4;
+ var addrListBuf = _malloc(12);
+ HEAPU32[((addrListBuf)>>2)] = addrListBuf+8;
+ HEAPU32[(((addrListBuf)+(4))>>2)] = 0;
+ HEAP32[(((addrListBuf)+(8))>>2)] = inetPton4(DNS.lookup_name(name));
+ HEAPU32[(((ret)+(16))>>2)] = addrListBuf;
+ return ret;
+ };
+
+ var _gethostbyname = (name) => {
+ return getHostByName(UTF8ToString(name));
+ };
+
+
+ var _gethostbyname_r = (name, ret, buf, buflen, out, err) => {
+ var data = _gethostbyname(name);
+ _memcpy(ret, data, 20);
+ _free(data);
+ HEAP32[((err)>>2)] = 0;
+ HEAPU32[((out)>>2)] = ret;
+ return 0;
+ };
-var _getloadavg = (loadavg, nelem) => {
- var limit = Math.min(nelem, 3);
- var doubleSize = 8;
- for (var i = 0; i < limit; i++) {
- HEAPF64[loadavg + i * doubleSize >> 3] = .1;
- }
- return limit;
-};
+ var _getloadavg = (loadavg, nelem) => {
+ // int getloadavg(double loadavg[], int nelem);
+ // http://linux.die.net/man/3/getloadavg
+ var limit = Math.min(nelem, 3);
+ var doubleSize = 8;
+ for (var i = 0; i < limit; i++) {
+ HEAPF64[(((loadavg)+(i * doubleSize))>>3)] = 0.1;
+ }
+ return limit;
+ };
-var _getnameinfo = (sa, salen, node, nodelen, serv, servlen, flags) => {
- var info = readSockaddr(sa, salen);
- if (info.errno) {
- return -6;
- }
- var port = info.port;
- var addr = info.addr;
- var overflowed = false;
- if (node && nodelen) {
- var lookup;
- if (flags & 1 || !(lookup = DNS.lookup_addr(addr))) {
- if (flags & 8) {
- return -2;
- }
- } else {
- addr = lookup;
- }
- var numBytesWrittenExclNull = stringToUTF8(addr, node, nodelen);
- if (numBytesWrittenExclNull + 1 >= nodelen) {
- overflowed = true;
- }
- }
- if (serv && servlen) {
- port = "" + port;
- var numBytesWrittenExclNull = stringToUTF8(port, serv, servlen);
- if (numBytesWrittenExclNull + 1 >= servlen) {
- overflowed = true;
- }
- }
- if (overflowed) {
- return -12;
- }
- return 0;
-};
+
+
+
+ var _getnameinfo = (sa, salen, node, nodelen, serv, servlen, flags) => {
+ var info = readSockaddr(sa, salen);
+ if (info.errno) {
+ return -6;
+ }
+ var port = info.port;
+ var addr = info.addr;
+
+ var overflowed = false;
+
+ if (node && nodelen) {
+ var lookup;
+ if ((flags & 1) || !(lookup = DNS.lookup_addr(addr))) {
+ if (flags & 8) {
+ return -2;
+ }
+ } else {
+ addr = lookup;
+ }
+ var numBytesWrittenExclNull = stringToUTF8(addr, node, nodelen);
+
+ if (numBytesWrittenExclNull+1 >= nodelen) {
+ overflowed = true;
+ }
+ }
+
+ if (serv && servlen) {
+ port = '' + port;
+ var numBytesWrittenExclNull = stringToUTF8(port, serv, servlen);
+
+ if (numBytesWrittenExclNull+1 >= servlen) {
+ overflowed = true;
+ }
+ }
+
+ if (overflowed) {
+ // Note: even when we overflow, getnameinfo() is specced to write out the truncated results.
+ return -12;
+ }
+
+ return 0;
+ };
-var Protocols = {
- list: [],
- map: {}
-};
+ var Protocols = {
+ list:[],
+ map:{
+ },
+ };
+
+
+ var _setprotoent = (stayopen) => {
+ // void setprotoent(int stayopen);
+
+ // Allocate and populate a protoent structure given a name, protocol number and array of aliases
+ function allocprotoent(name, proto, aliases) {
+ // write name into buffer
+ var nameBuf = _malloc(name.length + 1);
+ stringToAscii(name, nameBuf);
+
+ // write aliases into buffer
+ var j = 0;
+ var length = aliases.length;
+ var aliasListBuf = _malloc((length + 1) * 4); // Use length + 1 so we have space for the terminating NULL ptr.
+
+ for (var i = 0; i < length; i++, j += 4) {
+ var alias = aliases[i];
+ var aliasBuf = _malloc(alias.length + 1);
+ stringToAscii(alias, aliasBuf);
+ HEAPU32[(((aliasListBuf)+(j))>>2)] = aliasBuf;
+ }
+ HEAPU32[(((aliasListBuf)+(j))>>2)] = 0; // Terminating NULL pointer.
+
+ // generate protoent
+ var pe = _malloc(12);
+ HEAPU32[((pe)>>2)] = nameBuf;
+ HEAPU32[(((pe)+(4))>>2)] = aliasListBuf;
+ HEAP32[(((pe)+(8))>>2)] = proto;
+ return pe;
+ };
+
+ // Populate the protocol 'database'. The entries are limited to tcp and udp, though it is fairly trivial
+ // to add extra entries from /etc/protocols if desired - though not sure if that'd actually be useful.
+ var list = Protocols.list;
+ var map = Protocols.map;
+ if (list.length === 0) {
+ var entry = allocprotoent('tcp', 6, ['TCP']);
+ list.push(entry);
+ map['tcp'] = map['6'] = entry;
+ entry = allocprotoent('udp', 17, ['UDP']);
+ list.push(entry);
+ map['udp'] = map['17'] = entry;
+ }
+
+ _setprotoent.index = 0;
+ };
+
+
+ var _getprotobyname = (name) => {
+ // struct protoent *getprotobyname(const char *);
+ name = UTF8ToString(name);
+ _setprotoent(true);
+ var result = Protocols.map[name];
+ return result;
+ };
-var _setprotoent = stayopen => {
- function allocprotoent(name, proto, aliases) {
- var nameBuf = _malloc(name.length + 1);
- stringToAscii(name, nameBuf);
- var j = 0;
- var length = aliases.length;
- var aliasListBuf = _malloc((length + 1) * 4);
- for (var i = 0; i < length; i++, j += 4) {
- var alias = aliases[i];
- var aliasBuf = _malloc(alias.length + 1);
- stringToAscii(alias, aliasBuf);
- HEAPU32[aliasListBuf + j >> 2] = aliasBuf;
- }
- HEAPU32[aliasListBuf + j >> 2] = 0;
- var pe = _malloc(12);
- HEAPU32[pe >> 2] = nameBuf;
- HEAPU32[pe + 4 >> 2] = aliasListBuf;
- HEAP32[pe + 8 >> 2] = proto;
- return pe;
- }
- var list = Protocols.list;
- var map = Protocols.map;
- if (list.length === 0) {
- var entry = allocprotoent("tcp", 6, [ "TCP" ]);
- list.push(entry);
- map["tcp"] = map["6"] = entry;
- entry = allocprotoent("udp", 17, [ "UDP" ]);
- list.push(entry);
- map["udp"] = map["17"] = entry;
- }
- _setprotoent.index = 0;
-};
+
+ var _getprotobynumber = (number) => {
+ // struct protoent *getprotobynumber(int proto);
+ _setprotoent(true);
+ var result = Protocols.map[number];
+ return result;
+ };
-var _getprotobyname = name => {
- name = UTF8ToString(name);
- _setprotoent(true);
- var result = Protocols.map[name];
- return result;
-};
+
+ /** @suppress {duplicate } */
+ var stringToUTF8OnStack = (str) => {
+ var size = lengthBytesUTF8(str) + 1;
+ var ret = stackAlloc(size);
+ stringToUTF8(str, ret, size);
+ return ret;
+ };
+ var allocateUTF8OnStack = stringToUTF8OnStack;
+
+ var PHPWASM = {
+ init:function () {
+ PHPWASM.EventEmitter = ENVIRONMENT_IS_NODE
+ ? require('events').EventEmitter
+ : class EventEmitter {
+ constructor() {
+ this.listeners = {};
+ }
+ emit(eventName, data) {
+ if (this.listeners[eventName]) {
+ this.listeners[eventName].forEach(
+ (callback) => {
+ callback(data);
+ }
+ );
+ }
+ }
+ once(eventName, callback) {
+ const self = this;
+ function removedCallback() {
+ callback(...arguments);
+ self.removeListener(eventName, removedCallback);
+ }
+ this.on(eventName, removedCallback);
+ }
+ removeAllListeners(eventName) {
+ if (eventName) {
+ delete this.listeners[eventName];
+ } else {
+ this.listeners = {};
+ }
+ }
+ removeListener(eventName, callback) {
+ if (this.listeners[eventName]) {
+ const idx =
+ this.listeners[eventName].indexOf(callback);
+ if (idx !== -1) {
+ this.listeners[eventName].splice(idx, 1);
+ }
+ }
+ }
+ };
+ PHPWASM.child_proc_by_fd = {};
+ PHPWASM.child_proc_by_pid = {};
+ PHPWASM.input_devices = {};
+ },
+ getAllWebSockets:function (sock) {
+ const webSockets = /* @__PURE__ */ new Set();
+ if (sock.server) {
+ sock.server.clients.forEach((ws) => {
+ webSockets.add(ws);
+ });
+ }
+ for (const peer of PHPWASM.getAllPeers(sock)) {
+ webSockets.add(peer.socket);
+ }
+ return Array.from(webSockets);
+ },
+ getAllPeers:function (sock) {
+ const peers = new Set();
+ if (sock.server) {
+ sock.pending
+ .filter((pending) => pending.peers)
+ .forEach((pending) => {
+ for (const peer of Object.values(pending.peers)) {
+ peers.add(peer);
+ }
+ });
+ }
+ if (sock.peers) {
+ for (const peer of Object.values(sock.peers)) {
+ peers.add(peer);
+ }
+ }
+ return Array.from(peers);
+ },
+ awaitData:function (ws) {
+ return PHPWASM.awaitEvent(ws, 'message');
+ },
+ awaitConnection:function (ws) {
+ if (ws.OPEN === ws.readyState) {
+ return [Promise.resolve(), PHPWASM.noop];
+ }
+ return PHPWASM.awaitEvent(ws, 'open');
+ },
+ awaitClose:function (ws) {
+ if ([ws.CLOSING, ws.CLOSED].includes(ws.readyState)) {
+ return [Promise.resolve(), PHPWASM.noop];
+ }
+ return PHPWASM.awaitEvent(ws, 'close');
+ },
+ awaitError:function (ws) {
+ if ([ws.CLOSING, ws.CLOSED].includes(ws.readyState)) {
+ return [Promise.resolve(), PHPWASM.noop];
+ }
+ return PHPWASM.awaitEvent(ws, 'error');
+ },
+ awaitEvent:function (ws, event) {
+ let resolve;
+ const listener = () => {
+ resolve();
+ };
+ const promise = new Promise(function (_resolve) {
+ resolve = _resolve;
+ ws.once(event, listener);
+ });
+ const cancel = () => {
+ ws.removeListener(event, listener);
+ // Rejecting the promises bubbles up and kills the entire
+ // node process. Let's resolve them on the next tick instead
+ // to give the caller some space to unbind any handlers.
+ setTimeout(resolve);
+ };
+ return [promise, cancel];
+ },
+ noop:function () {},
+ spawnProcess:function (command, args, options) {
+ if (Module['spawnProcess']) {
+ const spawnedPromise = Module['spawnProcess'](command, args, options);
+ return Promise.resolve(spawnedPromise).then(function (spawned) {
+ if (!spawned || !spawned.on) {
+ throw new Error(
+ 'spawnProcess() must return an EventEmitter but returned a different type.'
+ );
+ }
+ return spawned;
+ });
+ }
+
+ if (ENVIRONMENT_IS_NODE) {
+ return require('child_process').spawn(command, args, {
+ ...options,
+ shell: true,
+ stdio: ['pipe', 'pipe', 'pipe'],
+ timeout: 100,
+ });
+ }
+ const e = new Error(
+ 'popen(), proc_open() etc. are unsupported in the browser. Call php.setSpawnHandler() ' +
+ 'and provide a callback to handle spawning processes, or disable a popen(), proc_open() ' +
+ 'and similar functions via php.ini.'
+ );
+ e.code = 'SPAWN_UNSUPPORTED';
+ throw e;
+ },
+ shutdownSocket:function (socketd, how) {
+ // This implementation only supports websockets at the moment
+ const sock = getSocketFromFD(socketd);
+ const peer = Object.values(sock.peers)[0];
+
+ if (!peer) {
+ return -1;
+ }
+
+ try {
+ peer.socket.close();
+ SOCKFS.websocket_sock_ops.removePeer(sock, peer);
+ return 0;
+ } catch (e) {
+ console.log('Socket shutdown error', e);
+ return -1;
+ }
+ },
+ };
+ function _js_create_input_device(deviceId) {
+ let dataBuffer = [];
+ let dataCallback;
+ const filename = 'proc_id_' + deviceId;
+ const device = FS.createDevice(
+ '/dev',
+ filename,
+ function () {},
+ function (byte) {
+ try {
+ dataBuffer.push(byte);
+ if (dataCallback) {
+ dataCallback(new Uint8Array(dataBuffer));
+ dataBuffer = [];
+ }
+ } catch (e) {
+ console.error(e);
+ throw e;
+ }
+ }
+ );
+
+ const devicePath = '/dev/' + filename;
+ PHPWASM.input_devices[deviceId] = {
+ devicePath: devicePath,
+ onData: function (cb) {
+ dataCallback = cb;
+ dataBuffer.forEach(function (data) {
+ cb(data);
+ });
+ dataBuffer.length = 0;
+ },
+ };
+ return allocateUTF8OnStack(devicePath);
+ }
+
+ function _js_fd_read(fd, iov, iovcnt, pnum) {
+ var returnCode;
+ var stream;
+ try {
+ stream = SYSCALLS.getStreamFromFD(fd);
+ var num = doReadv(stream, iov, iovcnt);
+ HEAPU32[pnum >> 2] = num;
+ returnCode = 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ returnCode = e.errno;
+ }
+
+ // If it's a blocking process pipe, wait for it to become readable.
+ // We need to distinguish between a process pipe and a file pipe, otherwise
+ // reading from an empty file would block until the timeout.
+ if (
+ returnCode === 6 /*EWOULDBLOCK*/ &&
+ stream?.fd in PHPWASM.child_proc_by_fd
+ ) {
+ // You might wonder why we duplicate the code here instead of always using
+ // Asyncify.handleSleep(). The reason is performance. Most of the time,
+ // the read operation will work synchronously and won't require yielding
+ // back to JS. In these cases we don't want to pay the Asyncify overhead,
+ // save the stack, yield back to JS, restore the stack etc.
+ return Asyncify.handleSleep(function (wakeUp) {
+ var retries = 0;
+ var interval = 50;
+ var timeout = 5000;
+ // We poll for data and give up after a timeout.
+ // We can't simply rely on PHP timeout here because we don't want
+ // to, say, block the entire PHPUnit test suite without any visible
+ // feedback.
+ var maxRetries = timeout / interval;
+ function poll() {
+ var returnCode;
+ var stream;
+ try {
+ stream = SYSCALLS.getStreamFromFD(fd);
+ var num = doReadv(stream, iov, iovcnt);
+ HEAPU32[pnum >> 2] = num;
+ returnCode = 0;
+ } catch (e) {
+ if (
+ typeof FS == 'undefined' ||
+ !(e.name === 'ErrnoError')
+ ) {
+ console.error(e);
+ throw e;
+ }
+ returnCode = e.errno;
+ }
+
+ if (
+ returnCode !== 6 ||
+ ++retries > maxRetries ||
+ !(fd in PHPWASM.child_proc_by_fd) ||
+ PHPWASM.child_proc_by_fd[fd]?.exited ||
+ FS.isClosed(stream)
+ ) {
+ wakeUp(returnCode);
+ } else {
+ setTimeout(poll, interval);
+ }
+ }
+ poll();
+ });
+ }
+ return returnCode;
+ }
+
+
+ function _js_module_onMessage(data, bufPtr) {
+ if (typeof Asyncify === 'undefined') {
+ return;
+ }
+
+ if (Module['onMessage']) {
+ const dataStr = UTF8ToString(data);
+
+ return Asyncify.handleSleep((wakeUp) => {
+ Module['onMessage'](dataStr)
+ .then((response) => {
+ const responseBytes =
+ typeof response === 'string'
+ ? new TextEncoder().encode(response)
+ : response;
+
+ // Copy the response bytes to heap
+ const responseSize = responseBytes.byteLength;
+ const responsePtr = _malloc(responseSize + 1);
+ HEAPU8.set(responseBytes, responsePtr);
+ HEAPU8[responsePtr + responseSize] = 0;
+ HEAPU8[bufPtr] = responsePtr;
+ HEAPU8[bufPtr + 1] = responsePtr >> 8;
+ HEAPU8[bufPtr + 2] = responsePtr >> 16;
+ HEAPU8[bufPtr + 3] = responsePtr >> 24;
+
+ wakeUp(responseSize);
+ })
+ .catch((e) => {
+ // Log the error and return NULL. Message passing
+ // separates JS context from the PHP context so we
+ // don't let PHP crash here.
+ console.error(e);
+ wakeUp(0);
+ });
+ });
+ }
+ }
+
+
+ function _js_open_process(
+ command,
+ argsPtr,
+ argsLength,
+ descriptorsPtr,
+ descriptorsLength,
+ cwdPtr,
+ cwdLength,
+ envPtr,
+ envLength
+ ) {
+ if (!command) {
+ return 1;
+ }
+
+ const cmdstr = UTF8ToString(command);
+ if (!cmdstr.length) {
+ return 0;
+ }
+
+ let argsArray = [];
+ if (argsLength) {
+ for (var i = 0; i < argsLength; i++) {
+ const charPointer = argsPtr + i * 4;
+ argsArray.push(UTF8ToString(HEAPU32[charPointer >> 2]));
+ }
+ }
+
+ const cwdstr = cwdPtr ? UTF8ToString(cwdPtr) : null;
+ let envObject = null;
+
+ if (envLength) {
+ envObject = {};
+ for (var i = 0; i < envLength; i++) {
+ const envPointer = envPtr + i * 4;
+ const envEntry = UTF8ToString(HEAPU32[envPointer >> 2]);
+ const splitAt = envEntry.indexOf('=');
+ if (splitAt === -1) {
+ continue;
+ }
+ const key = envEntry.substring(0, splitAt);
+ const value = envEntry.substring(splitAt + 1);
+ envObject[key] = value;
+ }
+ }
+
+ var std = {};
+ // Extracts an array of available descriptors that should be dispatched to streams.
+ // On the C side, the descriptors are expressed as `**int` so we must go read
+ // each of the `descriptorsLength` `*int` pointers and convert the associated data into
+ // a JavaScript object { descriptor : { child : fd, parent : fd } }.
+ for (var i = 0; i < descriptorsLength; i++) {
+ const descriptorPtr = HEAPU32[(descriptorsPtr + i * 4) >> 2];
+ std[HEAPU32[descriptorPtr >> 2]] = {
+ child: HEAPU32[(descriptorPtr + 4) >> 2],
+ parent: HEAPU32[(descriptorPtr + 8) >> 2],
+ };
+ }
+
+ return Asyncify.handleSleep(async (wakeUp) => {
+ let cp;
+ try {
+ const options = {};
+ if (cwdstr !== null) {
+ options.cwd = cwdstr;
+ }
+ if (envObject !== null) {
+ options.env = envObject;
+ }
+ cp = PHPWASM.spawnProcess(cmdstr, argsArray, options);
+ if (cp instanceof Promise) {
+ cp = await cp;
+ }
+ } catch (e) {
+ if (e.code === 'SPAWN_UNSUPPORTED') {
+ wakeUp(1);
+ return;
+ }
+ console.error(e);
+ wakeUp(1);
+ throw e;
+ }
+
+ const ProcInfo = {
+ pid: cp.pid,
+ exited: false,
+ stdinFd: std[0]?.child,
+ stdinIsDevice: std[0]?.child in PHPWASM.input_devices,
+ stdoutChildFd: std[1]?.child,
+ stdoutParentFd: std[1]?.parent,
+ stderrChildFd: std[2]?.child,
+ stderrParentFd: std[2]?.parent,
+ stdout: new PHPWASM.EventEmitter(),
+ stderr: new PHPWASM.EventEmitter(),
+ };
+ if (ProcInfo.stdoutChildFd)
+ PHPWASM.child_proc_by_fd[ProcInfo.stdoutChildFd] = ProcInfo;
+ if (ProcInfo.stderrChildFd)
+ PHPWASM.child_proc_by_fd[ProcInfo.stderrChildFd] = ProcInfo;
+ if (ProcInfo.stdoutParentFd)
+ PHPWASM.child_proc_by_fd[ProcInfo.stdoutParentFd] = ProcInfo;
+ if (ProcInfo.stderrParentFd)
+ PHPWASM.child_proc_by_fd[ProcInfo.stderrParentFd] = ProcInfo;
+ PHPWASM.child_proc_by_pid[ProcInfo.pid] = ProcInfo;
+
+ cp.on('exit', function (code) {
+ ProcInfo.exitCode = code;
+ ProcInfo.exited = true;
+ // Emit events for the wasm_poll_socket function.
+ ProcInfo.stdout.emit('data');
+ ProcInfo.stderr.emit('data');
+ });
+
+ // Pass data from child process's stdout to PHP's end of the stdout pipe.
+ if (ProcInfo.stdoutChildFd) {
+ const stdoutStream = SYSCALLS.getStreamFromFD(
+ ProcInfo.stdoutChildFd
+ );
+ let stdoutAt = 0;
+ cp.stdout.on('data', function (data) {
+ ProcInfo.stdout.emit('data', data);
+ stdoutStream.stream_ops.write(
+ stdoutStream,
+ data,
+ 0,
+ data.length,
+ stdoutAt
+ );
+ stdoutAt += data.length;
+ });
+ }
+
+ // Pass data from child process's stderr to PHP's end of the stdout pipe.
+ if (ProcInfo.stderrChildFd) {
+ const stderrStream = SYSCALLS.getStreamFromFD(
+ ProcInfo.stderrChildFd
+ );
+ let stderrAt = 0;
+ cp.stderr.on('data', function (data) {
+ ProcInfo.stderr.emit('data', data);
+ stderrStream.stream_ops.write(
+ stderrStream,
+ data,
+ 0,
+ data.length,
+ stderrAt
+ );
+ stderrAt += data.length;
+ });
+ }
+
+ /**
+ * Wait until the child process has been spawned.
+ * Unfortunately there is no Node.js API to check whether
+ * the process has already been spawned. We can only listen
+ * to the 'spawn' event and if it has already been spawned,
+ * listen to the 'exit' event.
+ */
+ try {
+ await new Promise((resolve, reject) => {
+ cp.on('spawn', resolve);
+ cp.on('error', reject);
+ });
+ } catch (e) {
+ console.error(e);
+ wakeUp(1);
+ return;
+ }
+
+ // Now we want to pass data from the STDIN source supplied by PHP
+ // to the child process.
+
+ // PHP will write STDIN data to a device.
+ if (ProcInfo.stdinIsDevice) {
+ // We use Emscripten devices as pipes. This is a bit of a hack
+ // but it works as we get a callback when the device is written to.
+ // Let's listen to anything it outputs and pass it to the child process.
+ PHPWASM.input_devices[ProcInfo.stdinFd].onData(function (data) {
+ if (!data) return;
+ const dataStr = new TextDecoder('utf-8').decode(data);
+ cp.stdin.write(dataStr);
+ });
+ wakeUp(ProcInfo.pid);
+ return;
+ }
+
+ if (ProcInfo.stdinFd) {
+ // PHP will write STDIN data to a file descriptor.
+ const stdinStream = SYSCALLS.getStreamFromFD(ProcInfo.stdinFd);
+ if (stdinStream.node) {
+ // Pipe the entire stdinStream to cp.stdin
+ const CHUNK_SIZE = 1024;
+ const buffer = new Uint8Array(CHUNK_SIZE);
+ let offset = 0;
+
+ while (true) {
+ const bytesRead = stdinStream.stream_ops.read(
+ stdinStream,
+ buffer,
+ 0,
+ CHUNK_SIZE,
+ offset
+ );
+ if (bytesRead === null || bytesRead === 0) {
+ break;
+ }
+ try {
+ cp.stdin.write(buffer.subarray(0, bytesRead));
+ } catch (e) {
+ console.error(e);
+ return 1;
+ }
+ if (bytesRead < CHUNK_SIZE) {
+ break;
+ }
+ offset += bytesRead;
+ }
+
+ wakeUp(ProcInfo.pid);
+ return;
+ }
+ }
+
+ wakeUp(ProcInfo.pid);
+ });
+ }
+
+
+ function _js_popen_to_file(command, mode, exitCodePtr) {
+ // Parse args
+ if (!command) return 1; // shell is available
+
+ const cmdstr = UTF8ToString(command);
+ if (!cmdstr.length) return 0; // this is what glibc seems to do (shell works test?)
+
+ const modestr = UTF8ToString(mode);
+ if (!modestr.length) return 0; // this is what glibc seems to do (shell works test?)
+ if (modestr === 'w') {
+ console.error('popen($cmd, "w") is not implemented yet');
+ }
+
+ return Asyncify.handleSleep(async (wakeUp) => {
+ let cp;
+ try {
+ cp = PHPWASM.spawnProcess(cmdstr, []);
+ if (cp instanceof Promise) {
+ cp = await cp;
+ }
+ } catch (e) {
+ console.error(e);
+ if (e.code === 'SPAWN_UNSUPPORTED') {
+ return 1;
+ }
+ throw e;
+ }
+
+ const outByteArrays = [];
+ cp.stdout.on('data', function (data) {
+ outByteArrays.push(data);
+ });
+
+ const outputPath = '/tmp/popen_output';
+ cp.on('exit', function (exitCode) {
+ // Concat outByteArrays, an array of UInt8Arrays
+ // into a single Uint8Array.
+ const outBytes = new Uint8Array(
+ outByteArrays.reduce((acc, curr) => acc + curr.length, 0)
+ );
+ let offset = 0;
+ for (const byteArray of outByteArrays) {
+ outBytes.set(byteArray, offset);
+ offset += byteArray.length;
+ }
+
+ FS.writeFile(outputPath, outBytes);
+
+ HEAPU8[exitCodePtr] = exitCode;
+ wakeUp(allocateUTF8OnStack(outputPath)); // 2 is SIGINT
+ });
+ });
+ }
+
+ function _js_process_status(pid) {
+ if (!PHPWASM.child_proc_by_pid[pid]) {
+ return -1;
+ }
+ if (PHPWASM.child_proc_by_pid[pid].exited) {
+ return 1;
+ }
+ return 0;
+ }
+
+ function _js_waitpid(pid, exitCodePtr) {
+ if (!PHPWASM.child_proc_by_pid[pid]) {
+ return -1;
+ }
+ return Asyncify.handleSleep((wakeUp) => {
+ const poll = function () {
+ if (PHPWASM.child_proc_by_pid[pid]?.exited) {
+ HEAPU8[exitCodePtr] =
+ PHPWASM.child_proc_by_pid[pid].exitCode;
+ wakeUp(0);
+ } else {
+ setTimeout(poll, 50);
+ }
+ };
+ poll();
+ });
+ }
+
+ /** @type {function(...*):?} */
+ function _makecontext(
+ ) {
+ err('missing function: makecontext'); abort(-1);
+ }
+
+
+
+ var arraySum = (array, index) => {
+ var sum = 0;
+ for (var i = 0; i <= index; sum += array[i++]) {
+ // no-op
+ }
+ return sum;
+ };
+
+
+ var MONTH_DAYS_LEAP = [31,29,31,30,31,30,31,31,30,31,30,31];
+
+ var MONTH_DAYS_REGULAR = [31,28,31,30,31,30,31,31,30,31,30,31];
+ var addDays = (date, days) => {
+ var newDate = new Date(date.getTime());
+ while (days > 0) {
+ var leap = isLeapYear(newDate.getFullYear());
+ var currentMonth = newDate.getMonth();
+ var daysInCurrentMonth = (leap ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR)[currentMonth];
+
+ if (days > daysInCurrentMonth-newDate.getDate()) {
+ // we spill over to next month
+ days -= (daysInCurrentMonth-newDate.getDate()+1);
+ newDate.setDate(1);
+ if (currentMonth < 11) {
+ newDate.setMonth(currentMonth+1)
+ } else {
+ newDate.setMonth(0);
+ newDate.setFullYear(newDate.getFullYear()+1);
+ }
+ } else {
+ // we stay in current month
+ newDate.setDate(newDate.getDate()+days);
+ return newDate;
+ }
+ }
+
+ return newDate;
+ };
+
+
+
+
+ var writeArrayToMemory = (array, buffer) => {
+ HEAP8.set(array, buffer);
+ };
+
+ var _strftime = (s, maxsize, format, tm) => {
+ // size_t strftime(char *restrict s, size_t maxsize, const char *restrict format, const struct tm *restrict timeptr);
+ // http://pubs.opengroup.org/onlinepubs/009695399/functions/strftime.html
+
+ var tm_zone = HEAP32[(((tm)+(40))>>2)];
+
+ var date = {
+ tm_sec: HEAP32[((tm)>>2)],
+ tm_min: HEAP32[(((tm)+(4))>>2)],
+ tm_hour: HEAP32[(((tm)+(8))>>2)],
+ tm_mday: HEAP32[(((tm)+(12))>>2)],
+ tm_mon: HEAP32[(((tm)+(16))>>2)],
+ tm_year: HEAP32[(((tm)+(20))>>2)],
+ tm_wday: HEAP32[(((tm)+(24))>>2)],
+ tm_yday: HEAP32[(((tm)+(28))>>2)],
+ tm_isdst: HEAP32[(((tm)+(32))>>2)],
+ tm_gmtoff: HEAP32[(((tm)+(36))>>2)],
+ tm_zone: tm_zone ? UTF8ToString(tm_zone) : ''
+ };
+
+ var pattern = UTF8ToString(format);
+
+ // expand format
+ var EXPANSION_RULES_1 = {
+ '%c': '%a %b %d %H:%M:%S %Y', // Replaced by the locale's appropriate date and time representation - e.g., Mon Aug 3 14:02:01 2013
+ '%D': '%m/%d/%y', // Equivalent to %m / %d / %y
+ '%F': '%Y-%m-%d', // Equivalent to %Y - %m - %d
+ '%h': '%b', // Equivalent to %b
+ '%r': '%I:%M:%S %p', // Replaced by the time in a.m. and p.m. notation
+ '%R': '%H:%M', // Replaced by the time in 24-hour notation
+ '%T': '%H:%M:%S', // Replaced by the time
+ '%x': '%m/%d/%y', // Replaced by the locale's appropriate date representation
+ '%X': '%H:%M:%S', // Replaced by the locale's appropriate time representation
+ // Modified Conversion Specifiers
+ '%Ec': '%c', // Replaced by the locale's alternative appropriate date and time representation.
+ '%EC': '%C', // Replaced by the name of the base year (period) in the locale's alternative representation.
+ '%Ex': '%m/%d/%y', // Replaced by the locale's alternative date representation.
+ '%EX': '%H:%M:%S', // Replaced by the locale's alternative time representation.
+ '%Ey': '%y', // Replaced by the offset from %EC (year only) in the locale's alternative representation.
+ '%EY': '%Y', // Replaced by the full alternative year representation.
+ '%Od': '%d', // Replaced by the day of the month, using the locale's alternative numeric symbols, filled as needed with leading zeros if there is any alternative symbol for zero; otherwise, with leading characters.
+ '%Oe': '%e', // Replaced by the day of the month, using the locale's alternative numeric symbols, filled as needed with leading characters.
+ '%OH': '%H', // Replaced by the hour (24-hour clock) using the locale's alternative numeric symbols.
+ '%OI': '%I', // Replaced by the hour (12-hour clock) using the locale's alternative numeric symbols.
+ '%Om': '%m', // Replaced by the month using the locale's alternative numeric symbols.
+ '%OM': '%M', // Replaced by the minutes using the locale's alternative numeric symbols.
+ '%OS': '%S', // Replaced by the seconds using the locale's alternative numeric symbols.
+ '%Ou': '%u', // Replaced by the weekday as a number in the locale's alternative representation (Monday=1).
+ '%OU': '%U', // Replaced by the week number of the year (Sunday as the first day of the week, rules corresponding to %U ) using the locale's alternative numeric symbols.
+ '%OV': '%V', // Replaced by the week number of the year (Monday as the first day of the week, rules corresponding to %V ) using the locale's alternative numeric symbols.
+ '%Ow': '%w', // Replaced by the number of the weekday (Sunday=0) using the locale's alternative numeric symbols.
+ '%OW': '%W', // Replaced by the week number of the year (Monday as the first day of the week) using the locale's alternative numeric symbols.
+ '%Oy': '%y', // Replaced by the year (offset from %C ) using the locale's alternative numeric symbols.
+ };
+ for (var rule in EXPANSION_RULES_1) {
+ pattern = pattern.replace(new RegExp(rule, 'g'), EXPANSION_RULES_1[rule]);
+ }
+
+ var WEEKDAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
+ var MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
+
+ function leadingSomething(value, digits, character) {
+ var str = typeof value == 'number' ? value.toString() : (value || '');
+ while (str.length < digits) {
+ str = character[0]+str;
+ }
+ return str;
+ }
+
+ function leadingNulls(value, digits) {
+ return leadingSomething(value, digits, '0');
+ }
+
+ function compareByDay(date1, date2) {
+ function sgn(value) {
+ return value < 0 ? -1 : (value > 0 ? 1 : 0);
+ }
+
+ var compare;
+ if ((compare = sgn(date1.getFullYear()-date2.getFullYear())) === 0) {
+ if ((compare = sgn(date1.getMonth()-date2.getMonth())) === 0) {
+ compare = sgn(date1.getDate()-date2.getDate());
+ }
+ }
+ return compare;
+ }
+
+ function getFirstWeekStartDate(janFourth) {
+ switch (janFourth.getDay()) {
+ case 0: // Sunday
+ return new Date(janFourth.getFullYear()-1, 11, 29);
+ case 1: // Monday
+ return janFourth;
+ case 2: // Tuesday
+ return new Date(janFourth.getFullYear(), 0, 3);
+ case 3: // Wednesday
+ return new Date(janFourth.getFullYear(), 0, 2);
+ case 4: // Thursday
+ return new Date(janFourth.getFullYear(), 0, 1);
+ case 5: // Friday
+ return new Date(janFourth.getFullYear()-1, 11, 31);
+ case 6: // Saturday
+ return new Date(janFourth.getFullYear()-1, 11, 30);
+ }
+ }
+
+ function getWeekBasedYear(date) {
+ var thisDate = addDays(new Date(date.tm_year+1900, 0, 1), date.tm_yday);
+
+ var janFourthThisYear = new Date(thisDate.getFullYear(), 0, 4);
+ var janFourthNextYear = new Date(thisDate.getFullYear()+1, 0, 4);
+
+ var firstWeekStartThisYear = getFirstWeekStartDate(janFourthThisYear);
+ var firstWeekStartNextYear = getFirstWeekStartDate(janFourthNextYear);
+
+ if (compareByDay(firstWeekStartThisYear, thisDate) <= 0) {
+ // this date is after the start of the first week of this year
+ if (compareByDay(firstWeekStartNextYear, thisDate) <= 0) {
+ return thisDate.getFullYear()+1;
+ }
+ return thisDate.getFullYear();
+ }
+ return thisDate.getFullYear()-1;
+ }
+
+ var EXPANSION_RULES_2 = {
+ '%a': (date) => WEEKDAYS[date.tm_wday].substring(0,3) ,
+ '%A': (date) => WEEKDAYS[date.tm_wday],
+ '%b': (date) => MONTHS[date.tm_mon].substring(0,3),
+ '%B': (date) => MONTHS[date.tm_mon],
+ '%C': (date) => {
+ var year = date.tm_year+1900;
+ return leadingNulls((year/100)|0,2);
+ },
+ '%d': (date) => leadingNulls(date.tm_mday, 2),
+ '%e': (date) => leadingSomething(date.tm_mday, 2, ' '),
+ '%g': (date) => {
+ // %g, %G, and %V give values according to the ISO 8601:2000 standard week-based year.
+ // In this system, weeks begin on a Monday and week 1 of the year is the week that includes
+ // January 4th, which is also the week that includes the first Thursday of the year, and
+ // is also the first week that contains at least four days in the year.
+ // If the first Monday of January is the 2nd, 3rd, or 4th, the preceding days are part of
+ // the last week of the preceding year; thus, for Saturday 2nd January 1999,
+ // %G is replaced by 1998 and %V is replaced by 53. If December 29th, 30th,
+ // or 31st is a Monday, it and any following days are part of week 1 of the following year.
+ // Thus, for Tuesday 30th December 1997, %G is replaced by 1998 and %V is replaced by 01.
+
+ return getWeekBasedYear(date).toString().substring(2);
+ },
+ '%G': (date) => getWeekBasedYear(date),
+ '%H': (date) => leadingNulls(date.tm_hour, 2),
+ '%I': (date) => {
+ var twelveHour = date.tm_hour;
+ if (twelveHour == 0) twelveHour = 12;
+ else if (twelveHour > 12) twelveHour -= 12;
+ return leadingNulls(twelveHour, 2);
+ },
+ '%j': (date) => {
+ // Day of the year (001-366)
+ return leadingNulls(date.tm_mday + arraySum(isLeapYear(date.tm_year+1900) ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR, date.tm_mon-1), 3);
+ },
+ '%m': (date) => leadingNulls(date.tm_mon+1, 2),
+ '%M': (date) => leadingNulls(date.tm_min, 2),
+ '%n': () => '\n',
+ '%p': (date) => {
+ if (date.tm_hour >= 0 && date.tm_hour < 12) {
+ return 'AM';
+ }
+ return 'PM';
+ },
+ '%S': (date) => leadingNulls(date.tm_sec, 2),
+ '%t': () => '\t',
+ '%u': (date) => date.tm_wday || 7,
+ '%U': (date) => {
+ var days = date.tm_yday + 7 - date.tm_wday;
+ return leadingNulls(Math.floor(days / 7), 2);
+ },
+ '%V': (date) => {
+ // Replaced by the week number of the year (Monday as the first day of the week)
+ // as a decimal number [01,53]. If the week containing 1 January has four
+ // or more days in the new year, then it is considered week 1.
+ // Otherwise, it is the last week of the previous year, and the next week is week 1.
+ // Both January 4th and the first Thursday of January are always in week 1. [ tm_year, tm_wday, tm_yday]
+ var val = Math.floor((date.tm_yday + 7 - (date.tm_wday + 6) % 7 ) / 7);
+ // If 1 Jan is just 1-3 days past Monday, the previous week
+ // is also in this year.
+ if ((date.tm_wday + 371 - date.tm_yday - 2) % 7 <= 2) {
+ val++;
+ }
+ if (!val) {
+ val = 52;
+ // If 31 December of prev year a Thursday, or Friday of a
+ // leap year, then the prev year has 53 weeks.
+ var dec31 = (date.tm_wday + 7 - date.tm_yday - 1) % 7;
+ if (dec31 == 4 || (dec31 == 5 && isLeapYear(date.tm_year%400-1))) {
+ val++;
+ }
+ } else if (val == 53) {
+ // If 1 January is not a Thursday, and not a Wednesday of a
+ // leap year, then this year has only 52 weeks.
+ var jan1 = (date.tm_wday + 371 - date.tm_yday) % 7;
+ if (jan1 != 4 && (jan1 != 3 || !isLeapYear(date.tm_year)))
+ val = 1;
+ }
+ return leadingNulls(val, 2);
+ },
+ '%w': (date) => date.tm_wday,
+ '%W': (date) => {
+ var days = date.tm_yday + 7 - ((date.tm_wday + 6) % 7);
+ return leadingNulls(Math.floor(days / 7), 2);
+ },
+ '%y': (date) => {
+ // Replaced by the last two digits of the year as a decimal number [00,99]. [ tm_year]
+ return (date.tm_year+1900).toString().substring(2);
+ },
+ // Replaced by the year as a decimal number (for example, 1997). [ tm_year]
+ '%Y': (date) => date.tm_year+1900,
+ '%z': (date) => {
+ // Replaced by the offset from UTC in the ISO 8601:2000 standard format ( +hhmm or -hhmm ).
+ // For example, "-0430" means 4 hours 30 minutes behind UTC (west of Greenwich).
+ var off = date.tm_gmtoff;
+ var ahead = off >= 0;
+ off = Math.abs(off) / 60;
+ // convert from minutes into hhmm format (which means 60 minutes = 100 units)
+ off = (off / 60)*100 + (off % 60);
+ return (ahead ? '+' : '-') + String("0000" + off).slice(-4);
+ },
+ '%Z': (date) => date.tm_zone,
+ '%%': () => '%'
+ };
+
+ // Replace %% with a pair of NULLs (which cannot occur in a C string), then
+ // re-inject them after processing.
+ pattern = pattern.replace(/%%/g, '\0\0')
+ for (var rule in EXPANSION_RULES_2) {
+ if (pattern.includes(rule)) {
+ pattern = pattern.replace(new RegExp(rule, 'g'), EXPANSION_RULES_2[rule](date));
+ }
+ }
+ pattern = pattern.replace(/\0\0/g, '%')
+
+ var bytes = intArrayFromString(pattern, false);
+ if (bytes.length > maxsize) {
+ return 0;
+ }
+
+ writeArrayToMemory(bytes, s);
+ return bytes.length-1;
+ };
-var _getprotobynumber = number => {
- _setprotoent(true);
- var result = Protocols.map[number];
- return result;
-};
+
+
+
+
+
+
+
+ var _strptime = (buf, format, tm) => {
+ // char *strptime(const char *restrict buf, const char *restrict format, struct tm *restrict tm);
+ // http://pubs.opengroup.org/onlinepubs/009695399/functions/strptime.html
+ var pattern = UTF8ToString(format);
+
+ // escape special characters
+ // TODO: not sure we really need to escape all of these in JS regexps
+ var SPECIAL_CHARS = '\\!@#$^&*()+=-[]/{}|:<>?,.';
+ for (var i=0, ii=SPECIAL_CHARS.length; i=0; i=pattern.indexOf('%')) {
+ capture.push(pattern[i+1]);
+ pattern = pattern.replace(new RegExp('\\%'+pattern[i+1], 'g'), '');
+ }
+
+ var matches = new RegExp('^'+pattern, "i").exec(UTF8ToString(buf))
+ // out(UTF8ToString(buf)+ ' is matched by '+((new RegExp('^'+pattern)).source)+' into: '+JSON.stringify(matches));
+
+ function initDate() {
+ function fixup(value, min, max) {
+ return (typeof value != 'number' || isNaN(value)) ? min : (value>=min ? (value<=max ? value: max): min);
+ };
+ return {
+ year: fixup(HEAP32[(((tm)+(20))>>2)] + 1900 , 1970, 9999),
+ month: fixup(HEAP32[(((tm)+(16))>>2)], 0, 11),
+ day: fixup(HEAP32[(((tm)+(12))>>2)], 1, 31),
+ hour: fixup(HEAP32[(((tm)+(8))>>2)], 0, 23),
+ min: fixup(HEAP32[(((tm)+(4))>>2)], 0, 59),
+ sec: fixup(HEAP32[((tm)>>2)], 0, 59)
+ };
+ };
+
+ if (matches) {
+ var date = initDate();
+ var value;
+
+ var getMatch = (symbol) => {
+ var pos = capture.indexOf(symbol);
+ // check if symbol appears in regexp
+ if (pos >= 0) {
+ // return matched value or null (falsy!) for non-matches
+ return matches[pos+1];
+ }
+ return;
+ };
+
+ // seconds
+ if ((value=getMatch('S'))) {
+ date.sec = jstoi_q(value);
+ }
+
+ // minutes
+ if ((value=getMatch('M'))) {
+ date.min = jstoi_q(value);
+ }
+
+ // hours
+ if ((value=getMatch('H'))) {
+ // 24h clock
+ date.hour = jstoi_q(value);
+ } else if ((value = getMatch('I'))) {
+ // AM/PM clock
+ var hour = jstoi_q(value);
+ if ((value=getMatch('p'))) {
+ hour += value.toUpperCase()[0] === 'P' ? 12 : 0;
+ }
+ date.hour = hour;
+ }
+
+ // year
+ if ((value=getMatch('Y'))) {
+ // parse from four-digit year
+ date.year = jstoi_q(value);
+ } else if ((value=getMatch('y'))) {
+ // parse from two-digit year...
+ var year = jstoi_q(value);
+ if ((value=getMatch('C'))) {
+ // ...and century
+ year += jstoi_q(value)*100;
+ } else {
+ // ...and rule-of-thumb
+ year += year<69 ? 2000 : 1900;
+ }
+ date.year = year;
+ }
+
+ // month
+ if ((value=getMatch('m'))) {
+ // parse from month number
+ date.month = jstoi_q(value)-1;
+ } else if ((value=getMatch('b'))) {
+ // parse from month name
+ date.month = MONTH_NUMBERS[value.substring(0,3).toUpperCase()] || 0;
+ // TODO: derive month from day in year+year, week number+day of week+year
+ }
+
+ // day
+ if ((value=getMatch('d'))) {
+ // get day of month directly
+ date.day = jstoi_q(value);
+ } else if ((value=getMatch('j'))) {
+ // get day of month from day of year ...
+ var day = jstoi_q(value);
+ var leapYear = isLeapYear(date.year);
+ for (var month=0; month<12; ++month) {
+ var daysUntilMonth = arraySum(leapYear ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR, month-1);
+ if (day<=daysUntilMonth+(leapYear ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR)[month]) {
+ date.day = day-daysUntilMonth;
+ }
+ }
+ } else if ((value=getMatch('a'))) {
+ // get day of month from weekday ...
+ var weekDay = value.substring(0,3).toUpperCase();
+ if ((value=getMatch('U'))) {
+ // ... and week number (Sunday being first day of week)
+ // Week number of the year (Sunday as the first day of the week) as a decimal number [00,53].
+ // All days in a new year preceding the first Sunday are considered to be in week 0.
+ var weekDayNumber = DAY_NUMBERS_SUN_FIRST[weekDay];
+ var weekNumber = jstoi_q(value);
+
+ // January 1st
+ var janFirst = new Date(date.year, 0, 1);
+ var endDate;
+ if (janFirst.getDay() === 0) {
+ // Jan 1st is a Sunday, and, hence in the 1st CW
+ endDate = addDays(janFirst, weekDayNumber+7*(weekNumber-1));
+ } else {
+ // Jan 1st is not a Sunday, and, hence still in the 0th CW
+ endDate = addDays(janFirst, 7-janFirst.getDay()+weekDayNumber+7*(weekNumber-1));
+ }
+ date.day = endDate.getDate();
+ date.month = endDate.getMonth();
+ } else if ((value=getMatch('W'))) {
+ // ... and week number (Monday being first day of week)
+ // Week number of the year (Monday as the first day of the week) as a decimal number [00,53].
+ // All days in a new year preceding the first Monday are considered to be in week 0.
+ var weekDayNumber = DAY_NUMBERS_MON_FIRST[weekDay];
+ var weekNumber = jstoi_q(value);
+
+ // January 1st
+ var janFirst = new Date(date.year, 0, 1);
+ var endDate;
+ if (janFirst.getDay()===1) {
+ // Jan 1st is a Monday, and, hence in the 1st CW
+ endDate = addDays(janFirst, weekDayNumber+7*(weekNumber-1));
+ } else {
+ // Jan 1st is not a Monday, and, hence still in the 0th CW
+ endDate = addDays(janFirst, 7-janFirst.getDay()+1+weekDayNumber+7*(weekNumber-1));
+ }
+
+ date.day = endDate.getDate();
+ date.month = endDate.getMonth();
+ }
+ }
+
+ /*
+ tm_sec int seconds after the minute 0-61*
+ tm_min int minutes after the hour 0-59
+ tm_hour int hours since midnight 0-23
+ tm_mday int day of the month 1-31
+ tm_mon int months since January 0-11
+ tm_year int years since 1900
+ tm_wday int days since Sunday 0-6
+ tm_yday int days since January 1 0-365
+ tm_isdst int Daylight Saving Time flag
+ */
+
+ var fullDate = new Date(date.year, date.month, date.day, date.hour, date.min, date.sec, 0);
+ HEAP32[((tm)>>2)] = fullDate.getSeconds();
+ HEAP32[(((tm)+(4))>>2)] = fullDate.getMinutes();
+ HEAP32[(((tm)+(8))>>2)] = fullDate.getHours();
+ HEAP32[(((tm)+(12))>>2)] = fullDate.getDate();
+ HEAP32[(((tm)+(16))>>2)] = fullDate.getMonth();
+ HEAP32[(((tm)+(20))>>2)] = fullDate.getFullYear()-1900;
+ HEAP32[(((tm)+(24))>>2)] = fullDate.getDay();
+ HEAP32[(((tm)+(28))>>2)] = arraySum(isLeapYear(fullDate.getFullYear()) ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR, fullDate.getMonth()-1)+fullDate.getDate()-1;
+ HEAP32[(((tm)+(32))>>2)] = 0;
+
+ // we need to convert the matched sequence into an integer array to take care of UTF-8 characters > 0x7F
+ // TODO: not sure that intArrayFromString handles all unicode characters correctly
+ return buf+intArrayFromString(matches[0]).length-1;
+ }
+
+ return 0;
+ };
-var stringToUTF8OnStack = str => {
- var size = lengthBytesUTF8(str) + 1;
- var ret = stackAlloc(size);
- stringToUTF8(str, ret, size);
- return ret;
-};
+ /** @type {function(...*):?} */
+ function _swapcontext(
+ ) {
+ err('missing function: swapcontext'); abort(-1);
+ }
+
+ function _wasm_close(socketd) {
+ return PHPWASM.shutdownSocket(socketd, 2);
+ }
+
+ function _wasm_poll_socket(socketd, events, timeout) {
+ if (typeof Asyncify === 'undefined') {
+ return 0;
+ }
+
+ const POLLIN = 0x0001; /* There is data to read */
+ const POLLPRI = 0x0002; /* There is urgent data to read */
+ const POLLOUT = 0x0004; /* Writing now will not block */
+ const POLLERR = 0x0008; /* Error condition */
+ const POLLHUP = 0x0010; /* Hung up */
+ const POLLNVAL = 0x0020; /* Invalid request: fd not open */
+
+ return Asyncify.handleSleep((wakeUp) => {
+ const polls = [];
+ if (socketd in PHPWASM.child_proc_by_fd) {
+ // This is a child process-related socket.
+ const procInfo = PHPWASM.child_proc_by_fd[socketd];
+ if (procInfo.exited) {
+ wakeUp(0);
+ return;
+ }
+ polls.push(PHPWASM.awaitEvent(procInfo.stdout, 'data'));
+ } else {
+ // This is, most likely, a websocket. Let's make sure.
+ const sock = getSocketFromFD(socketd);
+ if (!sock) {
+ wakeUp(0);
+ return;
+ }
+ const lookingFor = new Set();
+
+ if (events & POLLIN || events & POLLPRI) {
+ if (sock.server) {
+ for (const client of sock.pending) {
+ if ((client.recv_queue || []).length > 0) {
+ wakeUp(1);
+ return;
+ }
+ }
+ } else if ((sock.recv_queue || []).length > 0) {
+ wakeUp(1);
+ return;
+ }
+ }
+
+ const webSockets = PHPWASM.getAllWebSockets(sock);
+ if (!webSockets.length) {
+ wakeUp(0);
+ return;
+ }
+ for (const ws of webSockets) {
+ if (events & POLLIN || events & POLLPRI) {
+ polls.push(PHPWASM.awaitData(ws));
+ lookingFor.add('POLLIN');
+ }
+ if (events & POLLOUT) {
+ polls.push(PHPWASM.awaitConnection(ws));
+ lookingFor.add('POLLOUT');
+ }
+ if (events & POLLHUP) {
+ polls.push(PHPWASM.awaitClose(ws));
+ lookingFor.add('POLLHUP');
+ }
+ if (events & POLLERR || events & POLLNVAL) {
+ polls.push(PHPWASM.awaitError(ws));
+ lookingFor.add('POLLERR');
+ }
+ }
+ }
+ if (polls.length === 0) {
+ console.warn(
+ 'Unsupported poll event ' +
+ events +
+ ', defaulting to setTimeout().'
+ );
+ setTimeout(function () {
+ wakeUp(0);
+ }, timeout);
+ return;
+ }
+
+ const promises = polls.map(([promise]) => promise);
+ const clearPolling = () => polls.forEach(([, clear]) => clear());
+ let awaken = false;
+ let timeoutId;
+ Promise.race(promises).then(function (results) {
+ if (!awaken) {
+ awaken = true;
+ wakeUp(1);
+ if (timeoutId) {
+ clearTimeout(timeoutId);
+ }
+ clearPolling();
+ }
+ });
+
+ if (timeout !== -1) {
+ timeoutId = setTimeout(function () {
+ if (!awaken) {
+ awaken = true;
+ wakeUp(0);
+ clearPolling();
+ }
+ }, timeout);
+ }
+ });
+ }
+
+ function _wasm_setsockopt(
+ socketd,
+ level,
+ optionName,
+ optionValuePtr,
+ optionLen
+ ) {
+ const optionValue = HEAPU8[optionValuePtr];
+ const SOL_SOCKET = 1;
+ const SO_KEEPALIVE = 9;
+ const IPPROTO_TCP = 6;
+ const TCP_NODELAY = 1;
+ const isSupported =
+ (level === SOL_SOCKET && optionName === SO_KEEPALIVE) ||
+ (level === IPPROTO_TCP && optionName === TCP_NODELAY);
+ if (!isSupported) {
+ console.warn(
+ `Unsupported socket option: ${level}, ${optionName}, ${optionValue}`
+ );
+ return -1;
+ }
+ const ws = PHPWASM.getAllWebSockets(socketd)[0];
+ if (!ws) {
+ return -1;
+ }
+ ws.setSocketOpt(level, optionName, optionValuePtr);
+ return 0;
+ }
+
+ function _wasm_shutdown(socketd, how) {
+ return PHPWASM.shutdownSocket(socketd, how);
+ }
+
+ var wasmTableMirror = [];
+ var getWasmTableEntry = (funcPtr) => {
+ var func = wasmTableMirror[funcPtr];
+ if (!func) {
+ if (funcPtr >= wasmTableMirror.length) wasmTableMirror.length = funcPtr + 1;
+ wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr);
+ }
+ return func;
+ };
-var allocateUTF8OnStack = stringToUTF8OnStack;
-var PHPWASM = {
- init: function() {
- PHPWASM.EventEmitter = ENVIRONMENT_IS_NODE ? require("events").EventEmitter : class EventEmitter {
- constructor() {
- this.listeners = {};
- }
- emit(eventName, data) {
- if (this.listeners[eventName]) {
- this.listeners[eventName].forEach((callback => {
- callback(data);
- }));
- }
- }
- once(eventName, callback) {
- const self = this;
- function removedCallback() {
- callback(...arguments);
- self.removeListener(eventName, removedCallback);
- }
- this.on(eventName, removedCallback);
- }
- removeAllListeners(eventName) {
- if (eventName) {
- delete this.listeners[eventName];
- } else {
- this.listeners = {};
- }
- }
- removeListener(eventName, callback) {
- if (this.listeners[eventName]) {
- const idx = this.listeners[eventName].indexOf(callback);
- if (idx !== -1) {
- this.listeners[eventName].splice(idx, 1);
- }
+ function runAndAbortIfError(func) {
+ try {
+ return func();
+ } catch (e) {
+ abort(e);
+ }
}
- }
- };
- PHPWASM.child_proc_by_fd = {};
- PHPWASM.child_proc_by_pid = {};
- PHPWASM.input_devices = {};
- },
- getAllWebSockets: function(sock) {
- const webSockets = new Set;
- if (sock.server) {
- sock.server.clients.forEach((ws => {
- webSockets.add(ws);
- }));
- }
- for (const peer of PHPWASM.getAllPeers(sock)) {
- webSockets.add(peer.socket);
- }
- return Array.from(webSockets);
- },
- getAllPeers: function(sock) {
- const peers = new Set;
- if (sock.server) {
- sock.pending.filter((pending => pending.peers)).forEach((pending => {
- for (const peer of Object.values(pending.peers)) {
- peers.add(peer);
+
+
+ function sigToWasmTypes(sig) {
+ var typeNames = {
+ 'i': 'i32',
+ 'j': 'i64',
+ 'f': 'f32',
+ 'd': 'f64',
+ 'p': 'i32',
+ };
+ 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 type;
}
- }));
- }
- if (sock.peers) {
- for (const peer of Object.values(sock.peers)) {
- peers.add(peer);
- }
- }
- return Array.from(peers);
- },
- awaitData: function(ws) {
- return PHPWASM.awaitEvent(ws, "message");
- },
- awaitConnection: function(ws) {
- if (ws.OPEN === ws.readyState) {
- return [ Promise.resolve(), PHPWASM.noop ];
- }
- return PHPWASM.awaitEvent(ws, "open");
- },
- awaitClose: function(ws) {
- if ([ ws.CLOSING, ws.CLOSED ].includes(ws.readyState)) {
- return [ Promise.resolve(), PHPWASM.noop ];
- }
- return PHPWASM.awaitEvent(ws, "close");
- },
- awaitError: function(ws) {
- if ([ ws.CLOSING, ws.CLOSED ].includes(ws.readyState)) {
- return [ Promise.resolve(), PHPWASM.noop ];
- }
- return PHPWASM.awaitEvent(ws, "error");
- },
- awaitEvent: function(ws, event) {
- let resolve;
- const listener = () => {
- resolve();
- };
- const promise = new Promise((function(_resolve) {
- resolve = _resolve;
- ws.once(event, listener);
- }));
- const cancel = () => {
- ws.removeListener(event, listener);
- setTimeout(resolve);
+
+
+
+
+
+
+ var Asyncify = {
+ instrumentWasmImports:function(imports) {
+ var importPatterns = [/^_dlopen_js$/,/^invoke_i$/,/^invoke_ii$/,/^invoke_iii$/,/^invoke_iiii$/,/^invoke_iiiii$/,/^invoke_iiiiii$/,/^invoke_iiiiiii$/,/^invoke_iiiiiiii$/,/^invoke_iiiiiiiiii$/,/^invoke_v$/,/^invoke_vi$/,/^invoke_vii$/,/^invoke_viidii$/,/^invoke_viii$/,/^invoke_viiii$/,/^invoke_viiiii$/,/^invoke_viiiiii$/,/^invoke_viiiiiii$/,/^invoke_viiiiiiiii$/,/^js_open_process$/,/^js_popen_to_file$/,/^js_fd_read$/,/^js_module_onMessage$/,/^js_waitpid$/,/^wasm_poll_socket$/,/^wasm_shutdown$/,/^fd_sync$/,/^__wasi_fd_sync$/,/^__asyncjs__.*$/,/^emscripten_promise_await$/,/^emscripten_idb_load$/,/^emscripten_idb_store$/,/^emscripten_idb_delete$/,/^emscripten_idb_exists$/,/^emscripten_idb_load_blob$/,/^emscripten_idb_store_blob$/,/^emscripten_sleep$/,/^emscripten_wget_data$/,/^emscripten_scan_registers$/,/^emscripten_lazy_load_code$/,/^_load_secondary_module$/,/^emscripten_fiber_swap$/,/^SDL_Delay$/];
+
+ for (var x in imports) {
+ (function(x) {
+ var original = imports[x];
+ var sig = original.sig;
+ if (typeof original == 'function') {
+ var isAsyncifyImport = original.isAsync ||
+ importPatterns.some(pattern => !!x.match(pattern));
+ }
+ })(x);
+ }
+ },
+ instrumentWasmExports:function(exports) {
+ var ret = {};
+ for (var x in exports) {
+ (function(x) {
+ var original = exports[x];
+ if (typeof original == 'function') {
+ ret[x] = function() {
+ Asyncify.exportCallStack.push(x);
+ try {
+ return original.apply(null, arguments);
+ } finally {
+ if (!ABORT) {
+ var y = Asyncify.exportCallStack.pop();
+ assert(y === x);
+ Asyncify.maybeStopUnwind();
+ }
+ }
+ };
+ } else {
+ ret[x] = original;
+ }
+ })(x);
+ }
+ return ret;
+ },
+ State:{
+ Normal:0,
+ Unwinding:1,
+ Rewinding:2,
+ Disabled:3,
+ },
+ state:0,
+ StackSize:4096,
+ currData:null,
+ handleSleepReturnValue:0,
+ exportCallStack:[],
+ callStackNameToId:{
+ },
+ callStackIdToName:{
+ },
+ callStackId:0,
+ asyncPromiseHandlers:null,
+ sleepCallbacks:[],
+ getCallStackId:function(funcName) {
+ var id = Asyncify.callStackNameToId[funcName];
+ if (id === undefined) {
+ id = Asyncify.callStackId++;
+ Asyncify.callStackNameToId[funcName] = id;
+ Asyncify.callStackIdToName[id] = funcName;
+ }
+ return id;
+ },
+ maybeStopUnwind:function() {
+ if (Asyncify.currData &&
+ Asyncify.state === Asyncify.State.Unwinding &&
+ Asyncify.exportCallStack.length === 0) {
+ // We just finished unwinding.
+ // Be sure to set the state before calling any other functions to avoid
+ // possible infinite recursion here (For example in debug pthread builds
+ // the dbg() function itself can call back into WebAssembly to get the
+ // current pthread_self() pointer).
+ Asyncify.state = Asyncify.State.Normal;
+ runtimeKeepalivePush();
+ // Keep the runtime alive so that a re-wind can be done later.
+ runAndAbortIfError(_asyncify_stop_unwind);
+ if (typeof Fibers != 'undefined') {
+ Fibers.trampoline();
+ }
+ }
+ },
+ whenDone:function() {
+ return new Promise((resolve, reject) => {
+ Asyncify.asyncPromiseHandlers = { resolve, reject };
+ });
+ },
+ allocateData:function() {
+ // An asyncify data structure has three fields:
+ // 0 current stack pos
+ // 4 max stack pos
+ // 8 id of function at bottom of the call stack (callStackIdToName[id] == name of js function)
+ //
+ // The Asyncify ABI only interprets the first two fields, the rest is for the runtime.
+ // We also embed a stack in the same memory region here, right next to the structure.
+ // This struct is also defined as asyncify_data_t in emscripten/fiber.h
+ var ptr = _malloc(12 + Asyncify.StackSize);
+ Asyncify.setDataHeader(ptr, ptr + 12, Asyncify.StackSize);
+ Asyncify.setDataRewindFunc(ptr);
+ return ptr;
+ },
+ setDataHeader:function(ptr, stack, stackSize) {
+ HEAP32[((ptr)>>2)] = stack;
+ HEAP32[(((ptr)+(4))>>2)] = stack + stackSize;
+ },
+ setDataRewindFunc:function(ptr) {
+ var bottomOfCallStack = Asyncify.exportCallStack[0];
+ var rewindId = Asyncify.getCallStackId(bottomOfCallStack);
+ HEAP32[(((ptr)+(8))>>2)] = rewindId;
+ },
+ getDataRewindFunc:function(ptr) {
+ var id = HEAP32[(((ptr)+(8))>>2)];
+ var name = Asyncify.callStackIdToName[id];
+ var func = Module['asm'][name];
+ return func;
+ },
+ doRewind:function(ptr) {
+ var start = Asyncify.getDataRewindFunc(ptr);
+ // Once we have rewound and the stack we no longer need to artificially
+ // keep the runtime alive.
+ runtimeKeepalivePop();
+ return start();
+ },
+ handleSleep:function(startAsync) {
+ if (ABORT) return;
+ if (Asyncify.state === Asyncify.State.Normal) {
+ // Prepare to sleep. Call startAsync, and see what happens:
+ // if the code decided to call our callback synchronously,
+ // then no async operation was in fact begun, and we don't
+ // need to do anything.
+ var reachedCallback = false;
+ var reachedAfterCallback = false;
+ startAsync((handleSleepReturnValue = 0) => {
+ if (ABORT) return;
+ Asyncify.handleSleepReturnValue = handleSleepReturnValue;
+ reachedCallback = true;
+ if (!reachedAfterCallback) {
+ // We are happening synchronously, so no need for async.
+ return;
+ }
+ Asyncify.state = Asyncify.State.Rewinding;
+ runAndAbortIfError(() => _asyncify_start_rewind(Asyncify.currData));
+ if (typeof Browser != 'undefined' && Browser.mainLoop.func) {
+ Browser.mainLoop.resume();
+ }
+ var asyncWasmReturnValue, isError = false;
+ try {
+ asyncWasmReturnValue = Asyncify.doRewind(Asyncify.currData);
+ } catch (err) {
+ asyncWasmReturnValue = err;
+ isError = true;
+ }
+ // Track whether the return value was handled by any promise handlers.
+ var handled = false;
+ if (!Asyncify.currData) {
+ // All asynchronous execution has finished.
+ // `asyncWasmReturnValue` now contains the final
+ // return value of the exported async WASM function.
+ //
+ // Note: `asyncWasmReturnValue` is distinct from
+ // `Asyncify.handleSleepReturnValue`.
+ // `Asyncify.handleSleepReturnValue` contains the return
+ // value of the last C function to have executed
+ // `Asyncify.handleSleep()`, where as `asyncWasmReturnValue`
+ // contains the return value of the exported WASM function
+ // that may have called C functions that
+ // call `Asyncify.handleSleep()`.
+ var asyncPromiseHandlers = Asyncify.asyncPromiseHandlers;
+ if (asyncPromiseHandlers) {
+ Asyncify.asyncPromiseHandlers = null;
+ (isError ? asyncPromiseHandlers.reject : asyncPromiseHandlers.resolve)(asyncWasmReturnValue);
+ handled = true;
+ }
+ }
+ if (isError && !handled) {
+ // If there was an error and it was not handled by now, we have no choice but to
+ // rethrow that error into the global scope where it can be caught only by
+ // `onerror` or `onunhandledpromiserejection`.
+ throw asyncWasmReturnValue;
+ }
+ });
+ reachedAfterCallback = true;
+ if (!reachedCallback) {
+ // A true async operation was begun; start a sleep.
+ Asyncify.state = Asyncify.State.Unwinding;
+ // TODO: reuse, don't alloc/free every sleep
+ Asyncify.currData = Asyncify.allocateData();
+ if (typeof Browser != 'undefined' && Browser.mainLoop.func) {
+ Browser.mainLoop.pause();
+ }
+ runAndAbortIfError(() => _asyncify_start_unwind(Asyncify.currData));
+ }
+ } else if (Asyncify.state === Asyncify.State.Rewinding) {
+ // Stop a resume.
+ Asyncify.state = Asyncify.State.Normal;
+ runAndAbortIfError(_asyncify_stop_rewind);
+ _free(Asyncify.currData);
+ Asyncify.currData = null;
+ // Call all sleep callbacks now that the sleep-resume is all done.
+ Asyncify.sleepCallbacks.forEach((func) => callUserCallback(func));
+ } else {
+ abort(`invalid state: ${Asyncify.state}`);
+ }
+ return Asyncify.handleSleepReturnValue;
+ },
+ handleAsync:function(startAsync) {
+ return Asyncify.handleSleep((wakeUp) => {
+ // TODO: add error handling as a second param when handleSleep implements it.
+ startAsync().then(wakeUp);
+ });
+ },
};
- return [ promise, cancel ];
- },
- noop: function() {},
- spawnProcess: function(command, args) {
- if (Module["spawnProcess"]) {
- const spawnedPromise = Module["spawnProcess"](command, args);
- return Promise.resolve(spawnedPromise).then((function(spawned) {
- if (!spawned || !spawned.on) {
- throw new Error("spawnProcess() must return an EventEmitter but returned a different type.");
- }
- return spawned;
- }));
- }
- if (ENVIRONMENT_IS_NODE) {
- return require("child_process").spawn(command, args, {
- shell: true,
- stdio: [ "pipe", "pipe", "pipe" ],
- timeout: 100
- });
- }
- const e = new Error("popen(), proc_open() etc. are unsupported in the browser. Call php.setSpawnHandler() " + "and provide a callback to handle spawning processes, or disable a popen(), proc_open() " + "and similar functions via php.ini.");
- e.code = "SPAWN_UNSUPPORTED";
- throw e;
- },
- shutdownSocket: function(socketd, how) {
- const sock = getSocketFromFD(socketd);
- const peer = Object.values(sock.peers)[0];
- if (!peer) {
- return -1;
- }
- try {
- peer.socket.close();
- SOCKFS.websocket_sock_ops.removePeer(sock, peer);
- return 0;
- } catch (e) {
- console.log("Socket shutdown error", e);
- return -1;
- }
- }
-};
-
-function _js_create_input_device(deviceId) {
- let dataBuffer = [];
- let dataCallback;
- const filename = "proc_id_" + deviceId;
- const device = FS.createDevice("/dev", filename, (function() {}), (function(byte) {
- try {
- dataBuffer.push(byte);
- if (dataCallback) {
- dataCallback(new Uint8Array(dataBuffer));
- dataBuffer = [];
- }
- } catch (e) {
- console.error(e);
- throw e;
- }
- }));
- const devicePath = "/dev/" + filename;
- PHPWASM.input_devices[deviceId] = {
- devicePath: devicePath,
- onData: function(cb) {
- dataCallback = cb;
- dataBuffer.forEach((function(data) {
- cb(data);
- }));
- dataBuffer.length = 0;
- }
- };
- return allocateUTF8OnStack(devicePath);
-}
-function _js_fd_read(fd, iov, iovcnt, pnum) {
- var returnCode;
- var stream;
- try {
- stream = SYSCALLS.getStreamFromFD(fd);
- var num = doReadv(stream, iov, iovcnt);
- HEAPU32[pnum >> 2] = num;
- returnCode = 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- returnCode = e.errno;
- }
- if (returnCode === 6 && stream?.fd in PHPWASM.child_proc_by_fd) {
- return Asyncify.handleSleep((function(wakeUp) {
- var retries = 0;
- var interval = 50;
- var timeout = 5e3;
- var maxRetries = timeout / interval;
- function poll() {
- var returnCode;
- var stream;
- try {
- stream = SYSCALLS.getStreamFromFD(fd);
- var num = doReadv(stream, iov, iovcnt);
- HEAPU32[pnum >> 2] = num;
- returnCode = 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) {
- console.error(e);
- throw e;
- }
- returnCode = e.errno;
- }
- if (returnCode !== 6 || ++retries > maxRetries || !(fd in PHPWASM.child_proc_by_fd) || PHPWASM.child_proc_by_fd[fd]?.exited || FS.isClosed(stream)) {
- wakeUp(returnCode);
- } else {
- setTimeout(poll, interval);
+ function getCFunc(ident) {
+ var func = Module['_' + ident]; // closure exported function
+ return func;
}
- }
- poll();
- }));
- }
- return returnCode;
-}
+
+
+
+
+
+
+ /**
+ * @param {string|null=} returnType
+ * @param {Array=} argTypes
+ * @param {Arguments|Array=} args
+ * @param {Object=} opts
+ */
+ var ccall = function(ident, returnType, argTypes, args, opts) {
+ // For fast lookup of conversion functions
+ var toC = {
+ 'string': (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'
+ ret = stringToUTF8OnStack(str);
+ }
+ return ret;
+ },
+ 'array': (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];
+ }
+ }
+ }
+ // Data for a previous async operation that was in flight before us.
+ var previousAsync = Asyncify.currData;
+ var ret = func.apply(null, cArgs);
+ function onDone(ret) {
+ runtimeKeepalivePop();
+ if (stack !== 0) stackRestore(stack);
+ return convertReturnValue(ret);
+ }
+ var asyncMode = opts && opts.async;
+
+ // Keep the runtime alive through all calls. Note that this call might not be
+ // async, but for simplicity we push and pop in all calls.
+ runtimeKeepalivePush();
+ if (Asyncify.currData != previousAsync) {
+ // This is a new async operation. The wasm is paused and has unwound its stack.
+ // We need to return a Promise that resolves the return value
+ // once the stack is rewound and execution finishes.
+ return Asyncify.whenDone().then(onDone);
+ }
+
+ ret = onDone(ret);
+ // If this is an async ccall, ensure we return a promise
+ if (asyncMode) return Promise.resolve(ret);
+ return ret;
+ };
-function _js_module_onMessage(data, bufPtr) {
- if (typeof Asyncify === "undefined") {
- return;
- }
- if (Module["onMessage"]) {
- const dataStr = UTF8ToString(data);
- return Asyncify.handleSleep((wakeUp => {
- Module["onMessage"](dataStr).then((response => {
- const responseBytes = typeof response === "string" ? (new TextEncoder).encode(response) : response;
- const responseSize = responseBytes.byteLength;
- const responsePtr = _malloc(responseSize + 1);
- HEAPU8.set(responseBytes, responsePtr);
- HEAPU8[responsePtr + responseSize] = 0;
- HEAPU8[bufPtr] = responsePtr;
- HEAPU8[bufPtr + 1] = responsePtr >> 8;
- HEAPU8[bufPtr + 2] = responsePtr >> 16;
- HEAPU8[bufPtr + 3] = responsePtr >> 24;
- wakeUp(responseSize);
- })).catch((e => {
- console.error(e);
- wakeUp(0);
- }));
- }));
- }
-}
-function _js_open_process(command, argsPtr, argsLength, descriptorsPtr, descriptorsLength) {
- if (!command) {
- return 1;
- }
- const cmdstr = UTF8ToString(command);
- if (!cmdstr.length) {
- return 0;
- }
- let argsArray = [];
- if (argsLength) {
- for (var i = 0; i < argsLength; i++) {
- const charPointer = argsPtr + i * 4;
- argsArray.push(UTF8ToString(HEAPU32[charPointer >> 2]));
- }
- }
- var std = {};
- for (var i = 0; i < descriptorsLength; i++) {
- const descriptorPtr = HEAPU32[descriptorsPtr + i * 4 >> 2];
- std[HEAPU32[descriptorPtr >> 2]] = {
- child: HEAPU32[descriptorPtr + 4 >> 2],
- parent: HEAPU32[descriptorPtr + 8 >> 2]
- };
- }
- return Asyncify.handleSleep((async wakeUp => {
- let cp;
- try {
- cp = PHPWASM.spawnProcess(cmdstr, argsArray);
- if (cp instanceof Promise) {
- cp = await cp;
- }
- } catch (e) {
- if (e.code === "SPAWN_UNSUPPORTED") {
- wakeUp(1);
- return;
- }
- console.error(e);
- wakeUp(1);
- throw e;
- }
- const ProcInfo = {
- pid: cp.pid,
- exited: false,
- stdinFd: std[0]?.child,
- stdinIsDevice: std[0]?.child in PHPWASM.input_devices,
- stdoutChildFd: std[1]?.child,
- stdoutParentFd: std[1]?.parent,
- stderrChildFd: std[2]?.child,
- stderrParentFd: std[2]?.parent,
- stdout: new PHPWASM.EventEmitter,
- stderr: new PHPWASM.EventEmitter
+ 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;
};
- if (ProcInfo.stdoutChildFd) PHPWASM.child_proc_by_fd[ProcInfo.stdoutChildFd] = ProcInfo;
- if (ProcInfo.stderrChildFd) PHPWASM.child_proc_by_fd[ProcInfo.stderrChildFd] = ProcInfo;
- if (ProcInfo.stdoutParentFd) PHPWASM.child_proc_by_fd[ProcInfo.stdoutParentFd] = ProcInfo;
- if (ProcInfo.stderrParentFd) PHPWASM.child_proc_by_fd[ProcInfo.stderrParentFd] = ProcInfo;
- PHPWASM.child_proc_by_pid[ProcInfo.pid] = ProcInfo;
- cp.on("exit", (function(code) {
- ProcInfo.exitCode = code;
- ProcInfo.exited = true;
- ProcInfo.stdout.emit("data");
- ProcInfo.stderr.emit("data");
- }));
- if (ProcInfo.stdoutChildFd) {
- const stdoutStream = SYSCALLS.getStreamFromFD(ProcInfo.stdoutChildFd);
- let stdoutAt = 0;
- cp.stdout.on("data", (function(data) {
- ProcInfo.stdout.emit("data", data);
- stdoutStream.stream_ops.write(stdoutStream, data, 0, data.length, stdoutAt);
- stdoutAt += data.length;
- }));
- }
- if (ProcInfo.stderrChildFd) {
- const stderrStream = SYSCALLS.getStreamFromFD(ProcInfo.stderrChildFd);
- let stderrAt = 0;
- cp.stderr.on("data", (function(data) {
- ProcInfo.stderr.emit("data", data);
- stderrStream.stream_ops.write(stderrStream, data, 0, data.length, stderrAt);
- stderrAt += data.length;
- }));
- }
- try {
- await new Promise(((resolve, reject) => {
- cp.on("spawn", resolve);
- cp.on("error", reject);
- }));
- } catch (e) {
- console.error(e);
- wakeUp(1);
- return;
- }
- if (ProcInfo.stdinIsDevice) {
- PHPWASM.input_devices[ProcInfo.stdinFd].onData((function(data) {
- if (!data) return;
- const dataStr = new TextDecoder("utf-8").decode(data);
- cp.stdin.write(dataStr);
- }));
- wakeUp(ProcInfo.pid);
- return;
- }
- if (ProcInfo.stdinFd) {
- const stdinStream = SYSCALLS.getStreamFromFD(ProcInfo.stdinFd);
- if (stdinStream.node) {
- const CHUNK_SIZE = 1024;
- const buffer = new Uint8Array(CHUNK_SIZE);
- let offset = 0;
- while (true) {
- const bytesRead = stdinStream.stream_ops.read(stdinStream, buffer, 0, CHUNK_SIZE, offset);
- if (bytesRead === null || bytesRead === 0) {
- break;
- }
- try {
- cp.stdin.write(buffer.subarray(0, bytesRead));
- } catch (e) {
- console.error(e);
- return 1;
- }
- if (bytesRead < CHUNK_SIZE) {
- break;
- }
- offset += bytesRead;
+ 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);
}
- wakeUp(ProcInfo.pid);
- return;
}
- }
- wakeUp(ProcInfo.pid);
- }));
-}
+ });
+ FS.FSNode = FSNode;
+ FS.createPreloadedFile = FS_createPreloadedFile;
+ FS.staticInit();Module["FS_createPath"] = FS.createPath;Module["FS_createDataFile"] = FS.createDataFile;Module["FS_createPreloadedFile"] = FS.createPreloadedFile;Module["FS_unlink"] = FS.unlink;Module["FS_createLazyFile"] = FS.createLazyFile;Module["FS_createDevice"] = FS.createDevice;;
+if (ENVIRONMENT_IS_NODE) { NODEFS.staticInit(); };
+ERRNO_CODES = {
+ 'EPERM': 63,
+ 'ENOENT': 44,
+ 'ESRCH': 71,
+ 'EINTR': 27,
+ 'EIO': 29,
+ 'ENXIO': 60,
+ 'E2BIG': 1,
+ 'ENOEXEC': 45,
+ 'EBADF': 8,
+ 'ECHILD': 12,
+ 'EAGAIN': 6,
+ 'EWOULDBLOCK': 6,
+ 'ENOMEM': 48,
+ 'EACCES': 2,
+ 'EFAULT': 21,
+ 'ENOTBLK': 105,
+ 'EBUSY': 10,
+ 'EEXIST': 20,
+ 'EXDEV': 75,
+ 'ENODEV': 43,
+ 'ENOTDIR': 54,
+ 'EISDIR': 31,
+ 'EINVAL': 28,
+ 'ENFILE': 41,
+ 'EMFILE': 33,
+ 'ENOTTY': 59,
+ 'ETXTBSY': 74,
+ 'EFBIG': 22,
+ 'ENOSPC': 51,
+ 'ESPIPE': 70,
+ 'EROFS': 69,
+ 'EMLINK': 34,
+ 'EPIPE': 64,
+ 'EDOM': 18,
+ 'ERANGE': 68,
+ 'ENOMSG': 49,
+ 'EIDRM': 24,
+ 'ECHRNG': 106,
+ 'EL2NSYNC': 156,
+ 'EL3HLT': 107,
+ 'EL3RST': 108,
+ 'ELNRNG': 109,
+ 'EUNATCH': 110,
+ 'ENOCSI': 111,
+ 'EL2HLT': 112,
+ 'EDEADLK': 16,
+ 'ENOLCK': 46,
+ 'EBADE': 113,
+ 'EBADR': 114,
+ 'EXFULL': 115,
+ 'ENOANO': 104,
+ 'EBADRQC': 103,
+ 'EBADSLT': 102,
+ 'EDEADLOCK': 16,
+ 'EBFONT': 101,
+ 'ENOSTR': 100,
+ 'ENODATA': 116,
+ 'ETIME': 117,
+ 'ENOSR': 118,
+ 'ENONET': 119,
+ 'ENOPKG': 120,
+ 'EREMOTE': 121,
+ 'ENOLINK': 47,
+ 'EADV': 122,
+ 'ESRMNT': 123,
+ 'ECOMM': 124,
+ 'EPROTO': 65,
+ 'EMULTIHOP': 36,
+ 'EDOTDOT': 125,
+ 'EBADMSG': 9,
+ 'ENOTUNIQ': 126,
+ 'EBADFD': 127,
+ 'EREMCHG': 128,
+ 'ELIBACC': 129,
+ 'ELIBBAD': 130,
+ 'ELIBSCN': 131,
+ 'ELIBMAX': 132,
+ 'ELIBEXEC': 133,
+ 'ENOSYS': 52,
+ 'ENOTEMPTY': 55,
+ 'ENAMETOOLONG': 37,
+ 'ELOOP': 32,
+ 'EOPNOTSUPP': 138,
+ 'EPFNOSUPPORT': 139,
+ 'ECONNRESET': 15,
+ 'ENOBUFS': 42,
+ 'EAFNOSUPPORT': 5,
+ 'EPROTOTYPE': 67,
+ 'ENOTSOCK': 57,
+ 'ENOPROTOOPT': 50,
+ 'ESHUTDOWN': 140,
+ 'ECONNREFUSED': 14,
+ 'EADDRINUSE': 3,
+ 'ECONNABORTED': 13,
+ 'ENETUNREACH': 40,
+ 'ENETDOWN': 38,
+ 'ETIMEDOUT': 73,
+ 'EHOSTDOWN': 142,
+ 'EHOSTUNREACH': 23,
+ 'EINPROGRESS': 26,
+ 'EALREADY': 7,
+ 'EDESTADDRREQ': 17,
+ 'EMSGSIZE': 35,
+ 'EPROTONOSUPPORT': 66,
+ 'ESOCKTNOSUPPORT': 137,
+ 'EADDRNOTAVAIL': 4,
+ 'ENETRESET': 39,
+ 'EISCONN': 30,
+ 'ENOTCONN': 53,
+ 'ETOOMANYREFS': 141,
+ 'EUSERS': 136,
+ 'EDQUOT': 19,
+ 'ESTALE': 72,
+ 'ENOTSUP': 138,
+ 'ENOMEDIUM': 148,
+ 'EILSEQ': 25,
+ 'EOVERFLOW': 61,
+ 'ECANCELED': 11,
+ 'ENOTRECOVERABLE': 56,
+ 'EOWNERDEAD': 62,
+ 'ESTRPIPE': 135,
+ };;
+PHPWASM.init();;
+var wasmImports = {
+ __assert_fail: ___assert_fail,
+ __call_sighandler: ___call_sighandler,
+ __syscall__newselect: ___syscall__newselect,
+ __syscall_accept4: ___syscall_accept4,
+ __syscall_bind: ___syscall_bind,
+ __syscall_chdir: ___syscall_chdir,
+ __syscall_chmod: ___syscall_chmod,
+ __syscall_connect: ___syscall_connect,
+ __syscall_dup: ___syscall_dup,
+ __syscall_dup3: ___syscall_dup3,
+ __syscall_faccessat: ___syscall_faccessat,
+ __syscall_fallocate: ___syscall_fallocate,
+ __syscall_fchmod: ___syscall_fchmod,
+ __syscall_fchown32: ___syscall_fchown32,
+ __syscall_fchownat: ___syscall_fchownat,
+ __syscall_fcntl64: ___syscall_fcntl64,
+ __syscall_fdatasync: ___syscall_fdatasync,
+ __syscall_fstat64: ___syscall_fstat64,
+ __syscall_ftruncate64: ___syscall_ftruncate64,
+ __syscall_getcwd: ___syscall_getcwd,
+ __syscall_getdents64: ___syscall_getdents64,
+ __syscall_getpeername: ___syscall_getpeername,
+ __syscall_getsockname: ___syscall_getsockname,
+ __syscall_getsockopt: ___syscall_getsockopt,
+ __syscall_ioctl: ___syscall_ioctl,
+ __syscall_listen: ___syscall_listen,
+ __syscall_lstat64: ___syscall_lstat64,
+ __syscall_mkdirat: ___syscall_mkdirat,
+ __syscall_newfstatat: ___syscall_newfstatat,
+ __syscall_openat: ___syscall_openat,
+ __syscall_pipe: ___syscall_pipe,
+ __syscall_poll: ___syscall_poll,
+ __syscall_readlinkat: ___syscall_readlinkat,
+ __syscall_recvfrom: ___syscall_recvfrom,
+ __syscall_renameat: ___syscall_renameat,
+ __syscall_rmdir: ___syscall_rmdir,
+ __syscall_sendto: ___syscall_sendto,
+ __syscall_socket: ___syscall_socket,
+ __syscall_stat64: ___syscall_stat64,
+ __syscall_statfs64: ___syscall_statfs64,
+ __syscall_symlink: ___syscall_symlink,
+ __syscall_unlinkat: ___syscall_unlinkat,
+ __syscall_utimensat: ___syscall_utimensat,
+ _emscripten_get_now_is_monotonic: __emscripten_get_now_is_monotonic,
+ _emscripten_throw_longjmp: __emscripten_throw_longjmp,
+ _gmtime_js: __gmtime_js,
+ _localtime_js: __localtime_js,
+ _mktime_js: __mktime_js,
+ _mmap_js: __mmap_js,
+ _munmap_js: __munmap_js,
+ _setitimer_js: __setitimer_js,
+ _tzset_js: __tzset_js,
+ abort: _abort,
+ emscripten_date_now: _emscripten_date_now,
+ emscripten_get_heap_max: _emscripten_get_heap_max,
+ emscripten_get_now: _emscripten_get_now,
+ emscripten_memcpy_big: _emscripten_memcpy_big,
+ emscripten_resize_heap: _emscripten_resize_heap,
+ emscripten_sleep: _emscripten_sleep,
+ environ_get: _environ_get,
+ environ_sizes_get: _environ_sizes_get,
+ exit: _exit,
+ fd_close: _fd_close,
+ fd_fdstat_get: _fd_fdstat_get,
+ fd_read: _fd_read,
+ fd_seek: _fd_seek,
+ fd_sync: _fd_sync,
+ fd_write: _fd_write,
+ getaddrinfo: _getaddrinfo,
+ getcontext: _getcontext,
+ getdtablesize: _getdtablesize,
+ gethostbyname_r: _gethostbyname_r,
+ getloadavg: _getloadavg,
+ getnameinfo: _getnameinfo,
+ getprotobyname: _getprotobyname,
+ getprotobynumber: _getprotobynumber,
+ invoke_i: invoke_i,
+ invoke_ii: invoke_ii,
+ invoke_iii: invoke_iii,
+ invoke_iiii: invoke_iiii,
+ invoke_iiiii: invoke_iiiii,
+ invoke_iiiiii: invoke_iiiiii,
+ invoke_iiiiiii: invoke_iiiiiii,
+ invoke_iiiiiiii: invoke_iiiiiiii,
+ invoke_iiiiiiiiii: invoke_iiiiiiiiii,
+ invoke_v: invoke_v,
+ invoke_vi: invoke_vi,
+ invoke_vii: invoke_vii,
+ invoke_viidii: invoke_viidii,
+ invoke_viii: invoke_viii,
+ invoke_viiii: invoke_viiii,
+ invoke_viiiii: invoke_viiiii,
+ invoke_viiiiii: invoke_viiiiii,
+ invoke_viiiiiii: invoke_viiiiiii,
+ invoke_viiiiiiiii: invoke_viiiiiiiii,
+ js_create_input_device: _js_create_input_device,
+ js_fd_read: _js_fd_read,
+ js_module_onMessage: _js_module_onMessage,
+ js_open_process: _js_open_process,
+ js_popen_to_file: _js_popen_to_file,
+ js_process_status: _js_process_status,
+ js_waitpid: _js_waitpid,
+ makecontext: _makecontext,
+ proc_exit: _proc_exit,
+ strftime: _strftime,
+ strptime: _strptime,
+ swapcontext: _swapcontext,
+ wasm_close: _wasm_close,
+ wasm_poll_socket: _wasm_poll_socket,
+ wasm_setsockopt: _wasm_setsockopt,
+ wasm_shutdown: _wasm_shutdown
+};
+var asm = createWasm();
+/** @type {function(...*):?} */
+var ___wasm_call_ctors = function() {
+ return (___wasm_call_ctors = Module['asm']['__wasm_call_ctors']).apply(null, arguments);
+};
-function _js_popen_to_file(command, mode, exitCodePtr) {
- if (!command) return 1;
- const cmdstr = UTF8ToString(command);
- if (!cmdstr.length) return 0;
- const modestr = UTF8ToString(mode);
- if (!modestr.length) return 0;
- if (modestr === "w") {
- console.error('popen($cmd, "w") is not implemented yet');
- }
- return Asyncify.handleSleep((async wakeUp => {
- let cp;
- try {
- cp = PHPWASM.spawnProcess(cmdstr, []);
- if (cp instanceof Promise) {
- cp = await cp;
- }
- } catch (e) {
- console.error(e);
- if (e.code === "SPAWN_UNSUPPORTED") {
- return 1;
- }
- throw e;
- }
- const outByteArrays = [];
- cp.stdout.on("data", (function(data) {
- outByteArrays.push(data);
- }));
- const outputPath = "/tmp/popen_output";
- cp.on("exit", (function(exitCode) {
- const outBytes = new Uint8Array(outByteArrays.reduce(((acc, curr) => acc + curr.length), 0));
- let offset = 0;
- for (const byteArray of outByteArrays) {
- outBytes.set(byteArray, offset);
- offset += byteArray.length;
- }
- FS.writeFile(outputPath, outBytes);
- HEAPU8[exitCodePtr] = exitCode;
- wakeUp(allocateUTF8OnStack(outputPath));
- }));
- }));
-}
+/** @type {function(...*):?} */
+var _free = function() {
+ return (_free = Module['asm']['free']).apply(null, arguments);
+};
-function _js_process_status(pid) {
- if (!PHPWASM.child_proc_by_pid[pid]) {
- return -1;
- }
- if (PHPWASM.child_proc_by_pid[pid].exited) {
- return 1;
- }
- return 0;
-}
+/** @type {function(...*):?} */
+var _memcpy = function() {
+ return (_memcpy = Module['asm']['memcpy']).apply(null, arguments);
+};
-function _js_waitpid(pid, exitCodePtr) {
- if (!PHPWASM.child_proc_by_pid[pid]) {
- return -1;
- }
- return Asyncify.handleSleep((wakeUp => {
- const poll = function() {
- if (PHPWASM.child_proc_by_pid[pid]?.exited) {
- HEAPU8[exitCodePtr] = PHPWASM.child_proc_by_pid[pid].exitCode;
- wakeUp(0);
- } else {
- setTimeout(poll, 50);
- }
- };
- poll();
- }));
-}
+/** @type {function(...*):?} */
+var _malloc = function() {
+ return (_malloc = Module['asm']['malloc']).apply(null, arguments);
+};
-function _makecontext() {
- err("missing function: makecontext");
- abort(-1);
-}
+/** @type {function(...*):?} */
+var setTempRet0 = function() {
+ return (setTempRet0 = Module['asm']['setTempRet0']).apply(null, arguments);
+};
-var arraySum = (array, index) => {
- var sum = 0;
- for (var i = 0; i <= index; sum += array[i++]) {}
- return sum;
+/** @type {function(...*):?} */
+var ___errno_location = function() {
+ return (___errno_location = Module['asm']['__errno_location']).apply(null, arguments);
};
-var MONTH_DAYS_LEAP = [ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];
-
-var MONTH_DAYS_REGULAR = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];
-
-var addDays = (date, days) => {
- var newDate = new Date(date.getTime());
- while (days > 0) {
- var leap = isLeapYear(newDate.getFullYear());
- var currentMonth = newDate.getMonth();
- var daysInCurrentMonth = (leap ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR)[currentMonth];
- if (days > daysInCurrentMonth - newDate.getDate()) {
- days -= daysInCurrentMonth - newDate.getDate() + 1;
- newDate.setDate(1);
- if (currentMonth < 11) {
- newDate.setMonth(currentMonth + 1);
- } else {
- newDate.setMonth(0);
- newDate.setFullYear(newDate.getFullYear() + 1);
- }
- } else {
- newDate.setDate(newDate.getDate() + days);
- return newDate;
- }
- }
- return newDate;
+/** @type {function(...*):?} */
+var _wasm_popen = Module['_wasm_popen'] = function() {
+ return (_wasm_popen = Module['_wasm_popen'] = Module['asm']['wasm_popen']).apply(null, arguments);
};
-var writeArrayToMemory = (array, buffer) => {
- HEAP8.set(array, buffer);
+/** @type {function(...*):?} */
+var _wasm_php_exec = Module['_wasm_php_exec'] = function() {
+ return (_wasm_php_exec = Module['_wasm_php_exec'] = Module['asm']['wasm_php_exec']).apply(null, arguments);
};
-var _strftime = (s, maxsize, format, tm) => {
- var tm_zone = HEAP32[tm + 40 >> 2];
- var date = {
- tm_sec: HEAP32[tm >> 2],
- tm_min: HEAP32[tm + 4 >> 2],
- tm_hour: HEAP32[tm + 8 >> 2],
- tm_mday: HEAP32[tm + 12 >> 2],
- tm_mon: HEAP32[tm + 16 >> 2],
- tm_year: HEAP32[tm + 20 >> 2],
- tm_wday: HEAP32[tm + 24 >> 2],
- tm_yday: HEAP32[tm + 28 >> 2],
- tm_isdst: HEAP32[tm + 32 >> 2],
- tm_gmtoff: HEAP32[tm + 36 >> 2],
- tm_zone: tm_zone ? UTF8ToString(tm_zone) : ""
- };
- var pattern = UTF8ToString(format);
- var EXPANSION_RULES_1 = {
- "%c": "%a %b %d %H:%M:%S %Y",
- "%D": "%m/%d/%y",
- "%F": "%Y-%m-%d",
- "%h": "%b",
- "%r": "%I:%M:%S %p",
- "%R": "%H:%M",
- "%T": "%H:%M:%S",
- "%x": "%m/%d/%y",
- "%X": "%H:%M:%S",
- "%Ec": "%c",
- "%EC": "%C",
- "%Ex": "%m/%d/%y",
- "%EX": "%H:%M:%S",
- "%Ey": "%y",
- "%EY": "%Y",
- "%Od": "%d",
- "%Oe": "%e",
- "%OH": "%H",
- "%OI": "%I",
- "%Om": "%m",
- "%OM": "%M",
- "%OS": "%S",
- "%Ou": "%u",
- "%OU": "%U",
- "%OV": "%V",
- "%Ow": "%w",
- "%OW": "%W",
- "%Oy": "%y"
- };
- for (var rule in EXPANSION_RULES_1) {
- pattern = pattern.replace(new RegExp(rule, "g"), EXPANSION_RULES_1[rule]);
- }
- var WEEKDAYS = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ];
- var MONTHS = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ];
- function leadingSomething(value, digits, character) {
- var str = typeof value == "number" ? value.toString() : value || "";
- while (str.length < digits) {
- str = character[0] + str;
- }
- return str;
- }
- function leadingNulls(value, digits) {
- return leadingSomething(value, digits, "0");
- }
- function compareByDay(date1, date2) {
- function sgn(value) {
- return value < 0 ? -1 : value > 0 ? 1 : 0;
- }
- var compare;
- if ((compare = sgn(date1.getFullYear() - date2.getFullYear())) === 0) {
- if ((compare = sgn(date1.getMonth() - date2.getMonth())) === 0) {
- compare = sgn(date1.getDate() - date2.getDate());
- }
- }
- return compare;
- }
- function getFirstWeekStartDate(janFourth) {
- switch (janFourth.getDay()) {
- case 0:
- return new Date(janFourth.getFullYear() - 1, 11, 29);
-
- case 1:
- return janFourth;
-
- case 2:
- return new Date(janFourth.getFullYear(), 0, 3);
-
- case 3:
- return new Date(janFourth.getFullYear(), 0, 2);
-
- case 4:
- return new Date(janFourth.getFullYear(), 0, 1);
-
- case 5:
- return new Date(janFourth.getFullYear() - 1, 11, 31);
-
- case 6:
- return new Date(janFourth.getFullYear() - 1, 11, 30);
- }
- }
- function getWeekBasedYear(date) {
- var thisDate = addDays(new Date(date.tm_year + 1900, 0, 1), date.tm_yday);
- var janFourthThisYear = new Date(thisDate.getFullYear(), 0, 4);
- var janFourthNextYear = new Date(thisDate.getFullYear() + 1, 0, 4);
- var firstWeekStartThisYear = getFirstWeekStartDate(janFourthThisYear);
- var firstWeekStartNextYear = getFirstWeekStartDate(janFourthNextYear);
- if (compareByDay(firstWeekStartThisYear, thisDate) <= 0) {
- if (compareByDay(firstWeekStartNextYear, thisDate) <= 0) {
- return thisDate.getFullYear() + 1;
- }
- return thisDate.getFullYear();
- }
- return thisDate.getFullYear() - 1;
- }
- var EXPANSION_RULES_2 = {
- "%a": date => WEEKDAYS[date.tm_wday].substring(0, 3),
- "%A": date => WEEKDAYS[date.tm_wday],
- "%b": date => MONTHS[date.tm_mon].substring(0, 3),
- "%B": date => MONTHS[date.tm_mon],
- "%C": date => {
- var year = date.tm_year + 1900;
- return leadingNulls(year / 100 | 0, 2);
- },
- "%d": date => leadingNulls(date.tm_mday, 2),
- "%e": date => leadingSomething(date.tm_mday, 2, " "),
- "%g": date => getWeekBasedYear(date).toString().substring(2),
- "%G": date => getWeekBasedYear(date),
- "%H": date => leadingNulls(date.tm_hour, 2),
- "%I": date => {
- var twelveHour = date.tm_hour;
- if (twelveHour == 0) twelveHour = 12; else if (twelveHour > 12) twelveHour -= 12;
- return leadingNulls(twelveHour, 2);
- },
- "%j": date => leadingNulls(date.tm_mday + arraySum(isLeapYear(date.tm_year + 1900) ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR, date.tm_mon - 1), 3),
- "%m": date => leadingNulls(date.tm_mon + 1, 2),
- "%M": date => leadingNulls(date.tm_min, 2),
- "%n": () => "\n",
- "%p": date => {
- if (date.tm_hour >= 0 && date.tm_hour < 12) {
- return "AM";
- }
- return "PM";
- },
- "%S": date => leadingNulls(date.tm_sec, 2),
- "%t": () => "\t",
- "%u": date => date.tm_wday || 7,
- "%U": date => {
- var days = date.tm_yday + 7 - date.tm_wday;
- return leadingNulls(Math.floor(days / 7), 2);
- },
- "%V": date => {
- var val = Math.floor((date.tm_yday + 7 - (date.tm_wday + 6) % 7) / 7);
- if ((date.tm_wday + 371 - date.tm_yday - 2) % 7 <= 2) {
- val++;
- }
- if (!val) {
- val = 52;
- var dec31 = (date.tm_wday + 7 - date.tm_yday - 1) % 7;
- if (dec31 == 4 || dec31 == 5 && isLeapYear(date.tm_year % 400 - 1)) {
- val++;
- }
- } else if (val == 53) {
- var jan1 = (date.tm_wday + 371 - date.tm_yday) % 7;
- if (jan1 != 4 && (jan1 != 3 || !isLeapYear(date.tm_year))) val = 1;
- }
- return leadingNulls(val, 2);
- },
- "%w": date => date.tm_wday,
- "%W": date => {
- var days = date.tm_yday + 7 - (date.tm_wday + 6) % 7;
- return leadingNulls(Math.floor(days / 7), 2);
- },
- "%y": date => (date.tm_year + 1900).toString().substring(2),
- "%Y": date => date.tm_year + 1900,
- "%z": date => {
- var off = date.tm_gmtoff;
- var ahead = off >= 0;
- off = Math.abs(off) / 60;
- off = off / 60 * 100 + off % 60;
- return (ahead ? "+" : "-") + String("0000" + off).slice(-4);
- },
- "%Z": date => date.tm_zone,
- "%%": () => "%"
- };
- pattern = pattern.replace(/%%/g, "\0\0");
- for (var rule in EXPANSION_RULES_2) {
- if (pattern.includes(rule)) {
- pattern = pattern.replace(new RegExp(rule, "g"), EXPANSION_RULES_2[rule](date));
- }
- }
- pattern = pattern.replace(/\0\0/g, "%");
- var bytes = intArrayFromString(pattern, false);
- if (bytes.length > maxsize) {
- return 0;
- }
- writeArrayToMemory(bytes, s);
- return bytes.length - 1;
+/** @type {function(...*):?} */
+var _php_pollfd_for = Module['_php_pollfd_for'] = function() {
+ return (_php_pollfd_for = Module['_php_pollfd_for'] = Module['asm']['php_pollfd_for']).apply(null, arguments);
};
-var _strptime = (buf, format, tm) => {
- var pattern = UTF8ToString(format);
- var SPECIAL_CHARS = "\\!@#$^&*()+=-[]/{}|:<>?,.";
- for (var i = 0, ii = SPECIAL_CHARS.length; i < ii; ++i) {
- pattern = pattern.replace(new RegExp("\\" + SPECIAL_CHARS[i], "g"), "\\" + SPECIAL_CHARS[i]);
- }
- var EQUIVALENT_MATCHERS = {
- "%A": "%a",
- "%B": "%b",
- "%c": "%a %b %d %H:%M:%S %Y",
- "%D": "%m\\/%d\\/%y",
- "%e": "%d",
- "%F": "%Y-%m-%d",
- "%h": "%b",
- "%R": "%H\\:%M",
- "%r": "%I\\:%M\\:%S\\s%p",
- "%T": "%H\\:%M\\:%S",
- "%x": "%m\\/%d\\/(?:%y|%Y)",
- "%X": "%H\\:%M\\:%S"
- };
- for (var matcher in EQUIVALENT_MATCHERS) {
- pattern = pattern.replace(matcher, EQUIVALENT_MATCHERS[matcher]);
- }
- var DATE_PATTERNS = {
- "%a": "(?:Sun(?:day)?)|(?:Mon(?:day)?)|(?:Tue(?:sday)?)|(?:Wed(?:nesday)?)|(?:Thu(?:rsday)?)|(?:Fri(?:day)?)|(?:Sat(?:urday)?)",
- "%b": "(?:Jan(?:uary)?)|(?:Feb(?:ruary)?)|(?:Mar(?:ch)?)|(?:Apr(?:il)?)|May|(?:Jun(?:e)?)|(?:Jul(?:y)?)|(?:Aug(?:ust)?)|(?:Sep(?:tember)?)|(?:Oct(?:ober)?)|(?:Nov(?:ember)?)|(?:Dec(?:ember)?)",
- "%C": "\\d\\d",
- "%d": "0[1-9]|[1-9](?!\\d)|1\\d|2\\d|30|31",
- "%H": "\\d(?!\\d)|[0,1]\\d|20|21|22|23",
- "%I": "\\d(?!\\d)|0\\d|10|11|12",
- "%j": "00[1-9]|0?[1-9](?!\\d)|0?[1-9]\\d(?!\\d)|[1,2]\\d\\d|3[0-6]\\d",
- "%m": "0[1-9]|[1-9](?!\\d)|10|11|12",
- "%M": "0\\d|\\d(?!\\d)|[1-5]\\d",
- "%n": "\\s",
- "%p": "AM|am|PM|pm|A\\.M\\.|a\\.m\\.|P\\.M\\.|p\\.m\\.",
- "%S": "0\\d|\\d(?!\\d)|[1-5]\\d|60",
- "%U": "0\\d|\\d(?!\\d)|[1-4]\\d|50|51|52|53",
- "%W": "0\\d|\\d(?!\\d)|[1-4]\\d|50|51|52|53",
- "%w": "[0-6]",
- "%y": "\\d\\d",
- "%Y": "\\d\\d\\d\\d",
- "%%": "%",
- "%t": "\\s"
- };
- var MONTH_NUMBERS = {
- JAN: 0,
- FEB: 1,
- MAR: 2,
- APR: 3,
- MAY: 4,
- JUN: 5,
- JUL: 6,
- AUG: 7,
- SEP: 8,
- OCT: 9,
- NOV: 10,
- DEC: 11
- };
- var DAY_NUMBERS_SUN_FIRST = {
- SUN: 0,
- MON: 1,
- TUE: 2,
- WED: 3,
- THU: 4,
- FRI: 5,
- SAT: 6
- };
- var DAY_NUMBERS_MON_FIRST = {
- MON: 0,
- TUE: 1,
- WED: 2,
- THU: 3,
- FRI: 4,
- SAT: 5,
- SUN: 6
- };
- for (var datePattern in DATE_PATTERNS) {
- pattern = pattern.replace(datePattern, "(" + datePattern + DATE_PATTERNS[datePattern] + ")");
- }
- var capture = [];
- for (var i = pattern.indexOf("%"); i >= 0; i = pattern.indexOf("%")) {
- capture.push(pattern[i + 1]);
- pattern = pattern.replace(new RegExp("\\%" + pattern[i + 1], "g"), "");
- }
- var matches = new RegExp("^" + pattern, "i").exec(UTF8ToString(buf));
- function initDate() {
- function fixup(value, min, max) {
- return typeof value != "number" || isNaN(value) ? min : value >= min ? value <= max ? value : max : min;
- }
- return {
- year: fixup(HEAP32[tm + 20 >> 2] + 1900, 1970, 9999),
- month: fixup(HEAP32[tm + 16 >> 2], 0, 11),
- day: fixup(HEAP32[tm + 12 >> 2], 1, 31),
- hour: fixup(HEAP32[tm + 8 >> 2], 0, 23),
- min: fixup(HEAP32[tm + 4 >> 2], 0, 59),
- sec: fixup(HEAP32[tm >> 2], 0, 59)
- };
- }
- if (matches) {
- var date = initDate();
- var value;
- var getMatch = symbol => {
- var pos = capture.indexOf(symbol);
- if (pos >= 0) {
- return matches[pos + 1];
- }
- return;
- };
- if (value = getMatch("S")) {
- date.sec = jstoi_q(value);
- }
- if (value = getMatch("M")) {
- date.min = jstoi_q(value);
- }
- if (value = getMatch("H")) {
- date.hour = jstoi_q(value);
- } else if (value = getMatch("I")) {
- var hour = jstoi_q(value);
- if (value = getMatch("p")) {
- hour += value.toUpperCase()[0] === "P" ? 12 : 0;
- }
- date.hour = hour;
- }
- if (value = getMatch("Y")) {
- date.year = jstoi_q(value);
- } else if (value = getMatch("y")) {
- var year = jstoi_q(value);
- if (value = getMatch("C")) {
- year += jstoi_q(value) * 100;
- } else {
- year += year < 69 ? 2e3 : 1900;
- }
- date.year = year;
- }
- if (value = getMatch("m")) {
- date.month = jstoi_q(value) - 1;
- } else if (value = getMatch("b")) {
- date.month = MONTH_NUMBERS[value.substring(0, 3).toUpperCase()] || 0;
- }
- if (value = getMatch("d")) {
- date.day = jstoi_q(value);
- } else if (value = getMatch("j")) {
- var day = jstoi_q(value);
- var leapYear = isLeapYear(date.year);
- for (var month = 0; month < 12; ++month) {
- var daysUntilMonth = arraySum(leapYear ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR, month - 1);
- if (day <= daysUntilMonth + (leapYear ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR)[month]) {
- date.day = day - daysUntilMonth;
- }
- }
- } else if (value = getMatch("a")) {
- var weekDay = value.substring(0, 3).toUpperCase();
- if (value = getMatch("U")) {
- var weekDayNumber = DAY_NUMBERS_SUN_FIRST[weekDay];
- var weekNumber = jstoi_q(value);
- var janFirst = new Date(date.year, 0, 1);
- var endDate;
- if (janFirst.getDay() === 0) {
- endDate = addDays(janFirst, weekDayNumber + 7 * (weekNumber - 1));
- } else {
- endDate = addDays(janFirst, 7 - janFirst.getDay() + weekDayNumber + 7 * (weekNumber - 1));
- }
- date.day = endDate.getDate();
- date.month = endDate.getMonth();
- } else if (value = getMatch("W")) {
- var weekDayNumber = DAY_NUMBERS_MON_FIRST[weekDay];
- var weekNumber = jstoi_q(value);
- var janFirst = new Date(date.year, 0, 1);
- var endDate;
- if (janFirst.getDay() === 1) {
- endDate = addDays(janFirst, weekDayNumber + 7 * (weekNumber - 1));
- } else {
- endDate = addDays(janFirst, 7 - janFirst.getDay() + 1 + weekDayNumber + 7 * (weekNumber - 1));
- }
- date.day = endDate.getDate();
- date.month = endDate.getMonth();
- }
- }
- var fullDate = new Date(date.year, date.month, date.day, date.hour, date.min, date.sec, 0);
- HEAP32[tm >> 2] = fullDate.getSeconds();
- HEAP32[tm + 4 >> 2] = fullDate.getMinutes();
- HEAP32[tm + 8 >> 2] = fullDate.getHours();
- HEAP32[tm + 12 >> 2] = fullDate.getDate();
- HEAP32[tm + 16 >> 2] = fullDate.getMonth();
- HEAP32[tm + 20 >> 2] = fullDate.getFullYear() - 1900;
- HEAP32[tm + 24 >> 2] = fullDate.getDay();
- HEAP32[tm + 28 >> 2] = arraySum(isLeapYear(fullDate.getFullYear()) ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR, fullDate.getMonth() - 1) + fullDate.getDate() - 1;
- HEAP32[tm + 32 >> 2] = 0;
- return buf + intArrayFromString(matches[0]).length - 1;
- }
- return 0;
+/** @type {function(...*):?} */
+var _htons = function() {
+ return (_htons = Module['asm']['htons']).apply(null, arguments);
};
-function _swapcontext() {
- err("missing function: swapcontext");
- abort(-1);
-}
+/** @type {function(...*):?} */
+var _ntohs = function() {
+ return (_ntohs = Module['asm']['ntohs']).apply(null, arguments);
+};
-function _wasm_close(socketd) {
- return PHPWASM.shutdownSocket(socketd, 2);
-}
+/** @type {function(...*):?} */
+var _htonl = function() {
+ return (_htonl = Module['asm']['htonl']).apply(null, arguments);
+};
-function _wasm_poll_socket(socketd, events, timeout) {
- if (typeof Asyncify === "undefined") {
- return 0;
- }
- const POLLIN = 1;
- const POLLPRI = 2;
- const POLLOUT = 4;
- const POLLERR = 8;
- const POLLHUP = 16;
- const POLLNVAL = 32;
- return Asyncify.handleSleep((wakeUp => {
- const polls = [];
- if (socketd in PHPWASM.child_proc_by_fd) {
- const procInfo = PHPWASM.child_proc_by_fd[socketd];
- if (procInfo.exited) {
- wakeUp(0);
- return;
- }
- polls.push(PHPWASM.awaitEvent(procInfo.stdout, "data"));
- } else {
- const sock = getSocketFromFD(socketd);
- if (!sock) {
- wakeUp(0);
- return;
- }
- const lookingFor = new Set;
- if (events & POLLIN || events & POLLPRI) {
- if (sock.server) {
- for (const client of sock.pending) {
- if ((client.recv_queue || []).length > 0) {
- wakeUp(1);
- return;
- }
- }
- } else if ((sock.recv_queue || []).length > 0) {
- wakeUp(1);
- return;
- }
- }
- const webSockets = PHPWASM.getAllWebSockets(sock);
- if (!webSockets.length) {
- wakeUp(0);
- return;
- }
- for (const ws of webSockets) {
- if (events & POLLIN || events & POLLPRI) {
- polls.push(PHPWASM.awaitData(ws));
- lookingFor.add("POLLIN");
- }
- if (events & POLLOUT) {
- polls.push(PHPWASM.awaitConnection(ws));
- lookingFor.add("POLLOUT");
- }
- if (events & POLLHUP) {
- polls.push(PHPWASM.awaitClose(ws));
- lookingFor.add("POLLHUP");
- }
- if (events & POLLERR || events & POLLNVAL) {
- polls.push(PHPWASM.awaitError(ws));
- lookingFor.add("POLLERR");
- }
- }
- }
- if (polls.length === 0) {
- console.warn("Unsupported poll event " + events + ", defaulting to setTimeout().");
- setTimeout((function() {
- wakeUp(0);
- }), timeout);
- return;
- }
- const promises = polls.map((([promise]) => promise));
- const clearPolling = () => polls.forEach((([, clear]) => clear()));
- let awaken = false;
- let timeoutId;
- Promise.race(promises).then((function(results) {
- if (!awaken) {
- awaken = true;
- wakeUp(1);
- if (timeoutId) {
- clearTimeout(timeoutId);
- }
- clearPolling();
- }
- }));
- if (timeout !== -1) {
- timeoutId = setTimeout((function() {
- if (!awaken) {
- awaken = true;
- wakeUp(0);
- clearPolling();
- }
- }), timeout);
- }
- }));
-}
+/** @type {function(...*):?} */
+var _wasm_sleep = Module['_wasm_sleep'] = function() {
+ return (_wasm_sleep = Module['_wasm_sleep'] = Module['asm']['wasm_sleep']).apply(null, arguments);
+};
-function _wasm_setsockopt(socketd, level, optionName, optionValuePtr, optionLen) {
- const optionValue = HEAPU8[optionValuePtr];
- const SOL_SOCKET = 1;
- const SO_KEEPALIVE = 9;
- const IPPROTO_TCP = 6;
- const TCP_NODELAY = 1;
- const isSupported = level === SOL_SOCKET && optionName === SO_KEEPALIVE || level === IPPROTO_TCP && optionName === TCP_NODELAY;
- if (!isSupported) {
- console.warn(`Unsupported socket option: ${level}, ${optionName}, ${optionValue}`);
- return -1;
- }
- const ws = PHPWASM.getAllWebSockets(socketd)[0];
- if (!ws) {
- return -1;
- }
- ws.setSocketOpt(level, optionName, optionValuePtr);
- return 0;
-}
+/** @type {function(...*):?} */
+var _fflush = Module['_fflush'] = function() {
+ return (_fflush = Module['_fflush'] = Module['asm']['fflush']).apply(null, arguments);
+};
-function _wasm_shutdown(socketd, how) {
- return PHPWASM.shutdownSocket(socketd, how);
-}
+/** @type {function(...*):?} */
+var _wasm_read = Module['_wasm_read'] = function() {
+ return (_wasm_read = Module['_wasm_read'] = Module['asm']['wasm_read']).apply(null, arguments);
+};
-function runAndAbortIfError(func) {
- try {
- return func();
- } catch (e) {
- abort(e);
- }
-}
+/** @type {function(...*):?} */
+var _wasm_select = Module['_wasm_select'] = function() {
+ return (_wasm_select = Module['_wasm_select'] = Module['asm']['wasm_select']).apply(null, arguments);
+};
-var Asyncify = {
- instrumentWasmImports: function(imports) {
- var importPatterns = [ /^_dlopen_js$/, /^invoke_i$/, /^invoke_ii$/, /^invoke_iii$/, /^invoke_iiii$/, /^invoke_iiiii$/, /^invoke_iiiiii$/, /^invoke_iiiiiii$/, /^invoke_iiiiiiii$/, /^invoke_iiiiiiiiii$/, /^invoke_v$/, /^invoke_vi$/, /^invoke_vii$/, /^invoke_viidii$/, /^invoke_viii$/, /^invoke_viiii$/, /^invoke_viiiii$/, /^invoke_viiiiii$/, /^invoke_viiiiiii$/, /^invoke_viiiiiiiii$/, /^js_open_process$/, /^js_popen_to_file$/, /^js_fd_read$/, /^js_module_onMessage$/, /^js_waitpid$/, /^wasm_poll_socket$/, /^wasm_shutdown$/, /^fd_sync$/, /^__wasi_fd_sync$/, /^__asyncjs__.*$/, /^emscripten_promise_await$/, /^emscripten_idb_load$/, /^emscripten_idb_store$/, /^emscripten_idb_delete$/, /^emscripten_idb_exists$/, /^emscripten_idb_load_blob$/, /^emscripten_idb_store_blob$/, /^emscripten_sleep$/, /^emscripten_wget_data$/, /^emscripten_scan_registers$/, /^emscripten_lazy_load_code$/, /^_load_secondary_module$/, /^emscripten_fiber_swap$/, /^SDL_Delay$/ ];
- for (var x in imports) {
- (function(x) {
- var original = imports[x];
- var sig = original.sig;
- if (typeof original == "function") {
- var isAsyncifyImport = original.isAsync || importPatterns.some((pattern => !!x.match(pattern)));
- }
- })(x);
- }
- },
- instrumentWasmExports: function(exports) {
- var ret = {};
- for (var x in exports) {
- (function(x) {
- var original = exports[x];
- if (typeof original == "function") {
- ret[x] = function() {
- Asyncify.exportCallStack.push(x);
- try {
- return original.apply(null, arguments);
- } finally {
- if (!ABORT) {
- var y = Asyncify.exportCallStack.pop();
- assert(y === x);
- Asyncify.maybeStopUnwind();
- }
- }
- };
- } else {
- ret[x] = original;
- }
- })(x);
- }
- return ret;
- },
- State: {
- Normal: 0,
- Unwinding: 1,
- Rewinding: 2,
- Disabled: 3
- },
- state: 0,
- StackSize: 4096,
- currData: null,
- handleSleepReturnValue: 0,
- exportCallStack: [],
- callStackNameToId: {},
- callStackIdToName: {},
- callStackId: 0,
- asyncPromiseHandlers: null,
- sleepCallbacks: [],
- getCallStackId: function(funcName) {
- var id = Asyncify.callStackNameToId[funcName];
- if (id === undefined) {
- id = Asyncify.callStackId++;
- Asyncify.callStackNameToId[funcName] = id;
- Asyncify.callStackIdToName[id] = funcName;
- }
- return id;
- },
- maybeStopUnwind: function() {
- if (Asyncify.currData && Asyncify.state === Asyncify.State.Unwinding && Asyncify.exportCallStack.length === 0) {
- Asyncify.state = Asyncify.State.Normal;
- runtimeKeepalivePush();
- runAndAbortIfError(_asyncify_stop_unwind);
- if (typeof Fibers != "undefined") {
- Fibers.trampoline();
- }
- }
- },
- whenDone: function() {
- return new Promise(((resolve, reject) => {
- Asyncify.asyncPromiseHandlers = {
- resolve: resolve,
- reject: reject
- };
- }));
- },
- allocateData: function() {
- var ptr = _malloc(12 + Asyncify.StackSize);
- Asyncify.setDataHeader(ptr, ptr + 12, Asyncify.StackSize);
- Asyncify.setDataRewindFunc(ptr);
- return ptr;
- },
- setDataHeader: function(ptr, stack, stackSize) {
- HEAP32[ptr >> 2] = stack;
- HEAP32[ptr + 4 >> 2] = stack + stackSize;
- },
- setDataRewindFunc: function(ptr) {
- var bottomOfCallStack = Asyncify.exportCallStack[0];
- var rewindId = Asyncify.getCallStackId(bottomOfCallStack);
- HEAP32[ptr + 8 >> 2] = rewindId;
- },
- getDataRewindFunc: function(ptr) {
- var id = HEAP32[ptr + 8 >> 2];
- var name = Asyncify.callStackIdToName[id];
- var func = Module["asm"][name];
- return func;
- },
- doRewind: function(ptr) {
- var start = Asyncify.getDataRewindFunc(ptr);
- runtimeKeepalivePop();
- return start();
- },
- handleSleep: function(startAsync) {
- if (ABORT) return;
- if (Asyncify.state === Asyncify.State.Normal) {
- var reachedCallback = false;
- var reachedAfterCallback = false;
- startAsync(((handleSleepReturnValue = 0) => {
- if (ABORT) return;
- Asyncify.handleSleepReturnValue = handleSleepReturnValue;
- reachedCallback = true;
- if (!reachedAfterCallback) {
- return;
- }
- Asyncify.state = Asyncify.State.Rewinding;
- runAndAbortIfError((() => _asyncify_start_rewind(Asyncify.currData)));
- if (typeof Browser != "undefined" && Browser.mainLoop.func) {
- Browser.mainLoop.resume();
- }
- var asyncWasmReturnValue, isError = false;
- try {
- asyncWasmReturnValue = Asyncify.doRewind(Asyncify.currData);
- } catch (err) {
- asyncWasmReturnValue = err;
- isError = true;
- }
- var handled = false;
- if (!Asyncify.currData) {
- var asyncPromiseHandlers = Asyncify.asyncPromiseHandlers;
- if (asyncPromiseHandlers) {
- Asyncify.asyncPromiseHandlers = null;
- (isError ? asyncPromiseHandlers.reject : asyncPromiseHandlers.resolve)(asyncWasmReturnValue);
- handled = true;
- }
- }
- if (isError && !handled) {
- throw asyncWasmReturnValue;
- }
- }));
- reachedAfterCallback = true;
- if (!reachedCallback) {
- Asyncify.state = Asyncify.State.Unwinding;
- Asyncify.currData = Asyncify.allocateData();
- if (typeof Browser != "undefined" && Browser.mainLoop.func) {
- Browser.mainLoop.pause();
- }
- runAndAbortIfError((() => _asyncify_start_unwind(Asyncify.currData)));
- }
- } else if (Asyncify.state === Asyncify.State.Rewinding) {
- Asyncify.state = Asyncify.State.Normal;
- runAndAbortIfError(_asyncify_stop_rewind);
- _free(Asyncify.currData);
- Asyncify.currData = null;
- Asyncify.sleepCallbacks.forEach((func => callUserCallback(func)));
- } else {
- abort(`invalid state: ${Asyncify.state}`);
- }
- return Asyncify.handleSleepReturnValue;
- },
- handleAsync: function(startAsync) {
- return Asyncify.handleSleep((wakeUp => {
- startAsync().then(wakeUp);
- }));
- }
+/** @type {function(...*):?} */
+var _wasm_add_cli_arg = Module['_wasm_add_cli_arg'] = function() {
+ return (_wasm_add_cli_arg = Module['_wasm_add_cli_arg'] = Module['asm']['wasm_add_cli_arg']).apply(null, arguments);
};
-function getCFunc(ident) {
- var func = Module["_" + ident];
- return func;
-}
+/** @type {function(...*):?} */
+var _run_cli = Module['_run_cli'] = function() {
+ return (_run_cli = Module['_run_cli'] = Module['asm']['run_cli']).apply(null, arguments);
+};
-var ccall = function(ident, returnType, argTypes, args, opts) {
- var toC = {
- "string": str => {
- var ret = 0;
- if (str !== null && str !== undefined && str !== 0) {
- ret = stringToUTF8OnStack(str);
- }
- return ret;
- },
- "array": 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 previousAsync = Asyncify.currData;
- var ret = func.apply(null, cArgs);
- function onDone(ret) {
- runtimeKeepalivePop();
- if (stack !== 0) stackRestore(stack);
- return convertReturnValue(ret);
- }
- var asyncMode = opts && opts.async;
- runtimeKeepalivePush();
- if (Asyncify.currData != previousAsync) {
- return Asyncify.whenDone().then(onDone);
- }
- ret = onDone(ret);
- if (asyncMode) return Promise.resolve(ret);
- return ret;
+/** @type {function(...*):?} */
+var _wasm_set_sapi_name = Module['_wasm_set_sapi_name'] = function() {
+ return (_wasm_set_sapi_name = Module['_wasm_set_sapi_name'] = Module['asm']['wasm_set_sapi_name']).apply(null, arguments);
};
-var FSNode = function(parent, name, mode, rdev) {
- if (!parent) {
- parent = this;
- }
- 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;
+/** @type {function(...*):?} */
+var _wasm_set_phpini_path = Module['_wasm_set_phpini_path'] = function() {
+ return (_wasm_set_phpini_path = Module['_wasm_set_phpini_path'] = Module['asm']['wasm_set_phpini_path']).apply(null, arguments);
};
-var readMode = 292 | 73;
+/** @type {function(...*):?} */
+var _wasm_set_phpini_entries = Module['_wasm_set_phpini_entries'] = function() {
+ return (_wasm_set_phpini_entries = Module['_wasm_set_phpini_entries'] = Module['asm']['wasm_set_phpini_entries']).apply(null, arguments);
+};
-var writeMode = 146;
+/** @type {function(...*):?} */
+var _wasm_add_SERVER_entry = Module['_wasm_add_SERVER_entry'] = function() {
+ return (_wasm_add_SERVER_entry = Module['_wasm_add_SERVER_entry'] = Module['asm']['wasm_add_SERVER_entry']).apply(null, arguments);
+};
-Object.defineProperties(FSNode.prototype, {
- read: {
- get: function() {
- return (this.mode & readMode) === readMode;
- },
- set: function(val) {
- val ? this.mode |= readMode : this.mode &= ~readMode;
- }
- },
- write: {
- get: function() {
- return (this.mode & writeMode) === writeMode;
- },
- set: function(val) {
- val ? this.mode |= writeMode : this.mode &= ~writeMode;
- }
- },
- isFolder: {
- get: function() {
- return FS.isDir(this.mode);
- }
- },
- isDevice: {
- get: function() {
- return FS.isChrdev(this.mode);
- }
- }
-});
+/** @type {function(...*):?} */
+var _wasm_add_ENV_entry = Module['_wasm_add_ENV_entry'] = function() {
+ return (_wasm_add_ENV_entry = Module['_wasm_add_ENV_entry'] = Module['asm']['wasm_add_ENV_entry']).apply(null, arguments);
+};
-FS.FSNode = FSNode;
+/** @type {function(...*):?} */
+var _wasm_set_query_string = Module['_wasm_set_query_string'] = function() {
+ return (_wasm_set_query_string = Module['_wasm_set_query_string'] = Module['asm']['wasm_set_query_string']).apply(null, arguments);
+};
-FS.createPreloadedFile = FS_createPreloadedFile;
+/** @type {function(...*):?} */
+var _wasm_set_path_translated = Module['_wasm_set_path_translated'] = function() {
+ return (_wasm_set_path_translated = Module['_wasm_set_path_translated'] = Module['asm']['wasm_set_path_translated']).apply(null, arguments);
+};
-FS.staticInit();
+/** @type {function(...*):?} */
+var _wasm_set_skip_shebang = Module['_wasm_set_skip_shebang'] = function() {
+ return (_wasm_set_skip_shebang = Module['_wasm_set_skip_shebang'] = Module['asm']['wasm_set_skip_shebang']).apply(null, arguments);
+};
-Module["FS_createPath"] = FS.createPath;
+/** @type {function(...*):?} */
+var _wasm_set_request_uri = Module['_wasm_set_request_uri'] = function() {
+ return (_wasm_set_request_uri = Module['_wasm_set_request_uri'] = Module['asm']['wasm_set_request_uri']).apply(null, arguments);
+};
-Module["FS_createDataFile"] = FS.createDataFile;
+/** @type {function(...*):?} */
+var _wasm_set_request_method = Module['_wasm_set_request_method'] = function() {
+ return (_wasm_set_request_method = Module['_wasm_set_request_method'] = Module['asm']['wasm_set_request_method']).apply(null, arguments);
+};
-Module["FS_createPreloadedFile"] = FS.createPreloadedFile;
+/** @type {function(...*):?} */
+var _wasm_set_request_host = Module['_wasm_set_request_host'] = function() {
+ return (_wasm_set_request_host = Module['_wasm_set_request_host'] = Module['asm']['wasm_set_request_host']).apply(null, arguments);
+};
-Module["FS_unlink"] = FS.unlink;
+/** @type {function(...*):?} */
+var _wasm_set_content_type = Module['_wasm_set_content_type'] = function() {
+ return (_wasm_set_content_type = Module['_wasm_set_content_type'] = Module['asm']['wasm_set_content_type']).apply(null, arguments);
+};
-Module["FS_createLazyFile"] = FS.createLazyFile;
+/** @type {function(...*):?} */
+var _wasm_set_request_body = Module['_wasm_set_request_body'] = function() {
+ return (_wasm_set_request_body = Module['_wasm_set_request_body'] = Module['asm']['wasm_set_request_body']).apply(null, arguments);
+};
-Module["FS_createDevice"] = FS.createDevice;
+/** @type {function(...*):?} */
+var _wasm_set_content_length = Module['_wasm_set_content_length'] = function() {
+ return (_wasm_set_content_length = Module['_wasm_set_content_length'] = Module['asm']['wasm_set_content_length']).apply(null, arguments);
+};
-if (ENVIRONMENT_IS_NODE) {
- NODEFS.staticInit();
-}
+/** @type {function(...*):?} */
+var _wasm_set_cookies = Module['_wasm_set_cookies'] = function() {
+ return (_wasm_set_cookies = Module['_wasm_set_cookies'] = Module['asm']['wasm_set_cookies']).apply(null, arguments);
+};
-ERRNO_CODES = {
- "EPERM": 63,
- "ENOENT": 44,
- "ESRCH": 71,
- "EINTR": 27,
- "EIO": 29,
- "ENXIO": 60,
- "E2BIG": 1,
- "ENOEXEC": 45,
- "EBADF": 8,
- "ECHILD": 12,
- "EAGAIN": 6,
- "EWOULDBLOCK": 6,
- "ENOMEM": 48,
- "EACCES": 2,
- "EFAULT": 21,
- "ENOTBLK": 105,
- "EBUSY": 10,
- "EEXIST": 20,
- "EXDEV": 75,
- "ENODEV": 43,
- "ENOTDIR": 54,
- "EISDIR": 31,
- "EINVAL": 28,
- "ENFILE": 41,
- "EMFILE": 33,
- "ENOTTY": 59,
- "ETXTBSY": 74,
- "EFBIG": 22,
- "ENOSPC": 51,
- "ESPIPE": 70,
- "EROFS": 69,
- "EMLINK": 34,
- "EPIPE": 64,
- "EDOM": 18,
- "ERANGE": 68,
- "ENOMSG": 49,
- "EIDRM": 24,
- "ECHRNG": 106,
- "EL2NSYNC": 156,
- "EL3HLT": 107,
- "EL3RST": 108,
- "ELNRNG": 109,
- "EUNATCH": 110,
- "ENOCSI": 111,
- "EL2HLT": 112,
- "EDEADLK": 16,
- "ENOLCK": 46,
- "EBADE": 113,
- "EBADR": 114,
- "EXFULL": 115,
- "ENOANO": 104,
- "EBADRQC": 103,
- "EBADSLT": 102,
- "EDEADLOCK": 16,
- "EBFONT": 101,
- "ENOSTR": 100,
- "ENODATA": 116,
- "ETIME": 117,
- "ENOSR": 118,
- "ENONET": 119,
- "ENOPKG": 120,
- "EREMOTE": 121,
- "ENOLINK": 47,
- "EADV": 122,
- "ESRMNT": 123,
- "ECOMM": 124,
- "EPROTO": 65,
- "EMULTIHOP": 36,
- "EDOTDOT": 125,
- "EBADMSG": 9,
- "ENOTUNIQ": 126,
- "EBADFD": 127,
- "EREMCHG": 128,
- "ELIBACC": 129,
- "ELIBBAD": 130,
- "ELIBSCN": 131,
- "ELIBMAX": 132,
- "ELIBEXEC": 133,
- "ENOSYS": 52,
- "ENOTEMPTY": 55,
- "ENAMETOOLONG": 37,
- "ELOOP": 32,
- "EOPNOTSUPP": 138,
- "EPFNOSUPPORT": 139,
- "ECONNRESET": 15,
- "ENOBUFS": 42,
- "EAFNOSUPPORT": 5,
- "EPROTOTYPE": 67,
- "ENOTSOCK": 57,
- "ENOPROTOOPT": 50,
- "ESHUTDOWN": 140,
- "ECONNREFUSED": 14,
- "EADDRINUSE": 3,
- "ECONNABORTED": 13,
- "ENETUNREACH": 40,
- "ENETDOWN": 38,
- "ETIMEDOUT": 73,
- "EHOSTDOWN": 142,
- "EHOSTUNREACH": 23,
- "EINPROGRESS": 26,
- "EALREADY": 7,
- "EDESTADDRREQ": 17,
- "EMSGSIZE": 35,
- "EPROTONOSUPPORT": 66,
- "ESOCKTNOSUPPORT": 137,
- "EADDRNOTAVAIL": 4,
- "ENETRESET": 39,
- "EISCONN": 30,
- "ENOTCONN": 53,
- "ETOOMANYREFS": 141,
- "EUSERS": 136,
- "EDQUOT": 19,
- "ESTALE": 72,
- "ENOTSUP": 138,
- "ENOMEDIUM": 148,
- "EILSEQ": 25,
- "EOVERFLOW": 61,
- "ECANCELED": 11,
- "ENOTRECOVERABLE": 56,
- "EOWNERDEAD": 62,
- "ESTRPIPE": 135
+/** @type {function(...*):?} */
+var _wasm_set_php_code = Module['_wasm_set_php_code'] = function() {
+ return (_wasm_set_php_code = Module['_wasm_set_php_code'] = Module['asm']['wasm_set_php_code']).apply(null, arguments);
};
-PHPWASM.init();
+/** @type {function(...*):?} */
+var _wasm_set_request_port = Module['_wasm_set_request_port'] = function() {
+ return (_wasm_set_request_port = Module['_wasm_set_request_port'] = Module['asm']['wasm_set_request_port']).apply(null, arguments);
+};
-var wasmImports = {
- m: ___assert_fail,
- cb: ___call_sighandler,
- bb: ___syscall__newselect,
- ab: ___syscall_accept4,
- $a: ___syscall_bind,
- _a: ___syscall_chdir,
- S: ___syscall_chmod,
- Za: ___syscall_connect,
- Ya: ___syscall_dup,
- Xa: ___syscall_dup3,
- Wa: ___syscall_faccessat,
- ca: ___syscall_fallocate,
- Va: ___syscall_fchmod,
- Ua: ___syscall_fchown32,
- R: ___syscall_fchownat,
- o: ___syscall_fcntl64,
- Ta: ___syscall_fdatasync,
- Sa: ___syscall_fstat64,
- ba: ___syscall_ftruncate64,
- Ra: ___syscall_getcwd,
- Qa: ___syscall_getdents64,
- Pa: ___syscall_getpeername,
- Oa: ___syscall_getsockname,
- Na: ___syscall_getsockopt,
- Q: ___syscall_ioctl,
- Ma: ___syscall_listen,
- La: ___syscall_lstat64,
- Ka: ___syscall_mkdirat,
- Ja: ___syscall_newfstatat,
- y: ___syscall_openat,
- Ia: ___syscall_pipe,
- Ha: ___syscall_poll,
- Ga: ___syscall_readlinkat,
- Fa: ___syscall_recvfrom,
- Ea: ___syscall_renameat,
- P: ___syscall_rmdir,
- Da: ___syscall_sendto,
- O: ___syscall_socket,
- Ca: ___syscall_stat64,
- Ba: ___syscall_statfs64,
- Aa: ___syscall_symlink,
- E: ___syscall_unlinkat,
- za: ___syscall_utimensat,
- ua: __emscripten_get_now_is_monotonic,
- ta: __emscripten_throw_longjmp,
- $: __gmtime_js,
- _: __localtime_js,
- Z: __mktime_js,
- Y: __mmap_js,
- X: __munmap_js,
- L: __setitimer_js,
- sa: __tzset_js,
- f: _abort,
- C: _emscripten_date_now,
- ra: _emscripten_get_heap_max,
- v: _emscripten_get_now,
- qa: _emscripten_memcpy_big,
- pa: _emscripten_resize_heap,
- K: _emscripten_sleep,
- ya: _environ_get,
- xa: _environ_sizes_get,
- r: _exit,
- t: _fd_close,
- N: _fd_fdstat_get,
- M: _fd_read,
- aa: _fd_seek,
- wa: _fd_sync,
- D: _fd_write,
- oa: _getaddrinfo,
- na: _getcontext,
- ma: _getdtablesize,
- J: _gethostbyname_r,
- la: _getloadavg,
- x: _getnameinfo,
- ka: _getprotobyname,
- ja: _getprotobynumber,
- j: invoke_i,
- c: invoke_ii,
- b: invoke_iii,
- g: invoke_iiii,
- i: invoke_iiiii,
- q: invoke_iiiiii,
- s: invoke_iiiiiii,
- w: invoke_iiiiiiii,
- I: invoke_iiiiiiiiii,
- e: invoke_v,
- a: invoke_vi,
- d: invoke_vii,
- B: invoke_viidii,
- h: invoke_viii,
- l: invoke_viiii,
- n: invoke_viiiii,
- k: invoke_viiiiii,
- ia: invoke_viiiiiii,
- A: invoke_viiiiiiiii,
- H: _js_create_input_device,
- ha: _js_fd_read,
- ga: _js_module_onMessage,
- G: _js_open_process,
- fa: _js_popen_to_file,
- ea: _js_process_status,
- da: _js_waitpid,
- W: _makecontext,
- va: _proc_exit,
- F: _strftime,
- V: _strptime,
- U: _swapcontext,
- u: _wasm_close,
- z: _wasm_poll_socket,
- p: _wasm_setsockopt,
- T: _wasm_shutdown
+/** @type {function(...*):?} */
+var _wasm_sapi_handle_request = Module['_wasm_sapi_handle_request'] = function() {
+ return (_wasm_sapi_handle_request = Module['_wasm_sapi_handle_request'] = Module['asm']['wasm_sapi_handle_request']).apply(null, arguments);
};
-var asm = createWasm();
+/** @type {function(...*):?} */
+var _php_wasm_init = Module['_php_wasm_init'] = function() {
+ return (_php_wasm_init = Module['_php_wasm_init'] = Module['asm']['php_wasm_init']).apply(null, arguments);
+};
-var ___wasm_call_ctors = function() {
- return (___wasm_call_ctors = Module["asm"]["eb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var ___funcs_on_exit = function() {
+ return (___funcs_on_exit = Module['asm']['__funcs_on_exit']).apply(null, arguments);
};
-var _free = function() {
- return (_free = Module["asm"]["fb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var _emscripten_builtin_memalign = function() {
+ return (_emscripten_builtin_memalign = Module['asm']['emscripten_builtin_memalign']).apply(null, arguments);
};
-var _memcpy = function() {
- return (_memcpy = Module["asm"]["gb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var __emscripten_timeout = function() {
+ return (__emscripten_timeout = Module['asm']['_emscripten_timeout']).apply(null, arguments);
};
-var _malloc = function() {
- return (_malloc = Module["asm"]["ib"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var _setThrew = function() {
+ return (_setThrew = Module['asm']['setThrew']).apply(null, arguments);
};
-var setTempRet0 = function() {
- return (setTempRet0 = Module["asm"]["jb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var _emscripten_stack_set_limits = function() {
+ return (_emscripten_stack_set_limits = Module['asm']['emscripten_stack_set_limits']).apply(null, arguments);
};
-var ___errno_location = function() {
- return (___errno_location = Module["asm"]["kb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var _emscripten_stack_get_base = function() {
+ return (_emscripten_stack_get_base = Module['asm']['emscripten_stack_get_base']).apply(null, arguments);
};
-var _wasm_popen = Module["_wasm_popen"] = function() {
- return (_wasm_popen = Module["_wasm_popen"] = Module["asm"]["lb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var _emscripten_stack_get_end = function() {
+ return (_emscripten_stack_get_end = Module['asm']['emscripten_stack_get_end']).apply(null, arguments);
};
-var _wasm_php_exec = Module["_wasm_php_exec"] = function() {
- return (_wasm_php_exec = Module["_wasm_php_exec"] = Module["asm"]["mb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var stackSave = function() {
+ return (stackSave = Module['asm']['stackSave']).apply(null, arguments);
};
-var _php_pollfd_for = Module["_php_pollfd_for"] = function() {
- return (_php_pollfd_for = Module["_php_pollfd_for"] = Module["asm"]["nb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var stackRestore = function() {
+ return (stackRestore = Module['asm']['stackRestore']).apply(null, arguments);
};
-var _htons = function() {
- return (_htons = Module["asm"]["ob"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var stackAlloc = function() {
+ return (stackAlloc = Module['asm']['stackAlloc']).apply(null, arguments);
};
-var _ntohs = function() {
- return (_ntohs = Module["asm"]["pb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_iiii = Module['dynCall_iiii'] = function() {
+ return (dynCall_iiii = Module['dynCall_iiii'] = Module['asm']['dynCall_iiii']).apply(null, arguments);
};
-var _htonl = function() {
- return (_htonl = Module["asm"]["qb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_ii = Module['dynCall_ii'] = function() {
+ return (dynCall_ii = Module['dynCall_ii'] = Module['asm']['dynCall_ii']).apply(null, arguments);
};
-var _wasm_sleep = Module["_wasm_sleep"] = function() {
- return (_wasm_sleep = Module["_wasm_sleep"] = Module["asm"]["rb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_vi = Module['dynCall_vi'] = function() {
+ return (dynCall_vi = Module['dynCall_vi'] = Module['asm']['dynCall_vi']).apply(null, arguments);
};
-var _fflush = Module["_fflush"] = function() {
- return (_fflush = Module["_fflush"] = Module["asm"]["sb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_vii = Module['dynCall_vii'] = function() {
+ return (dynCall_vii = Module['dynCall_vii'] = Module['asm']['dynCall_vii']).apply(null, arguments);
};
-var _wasm_read = Module["_wasm_read"] = function() {
- return (_wasm_read = Module["_wasm_read"] = Module["asm"]["tb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_viiiii = Module['dynCall_viiiii'] = function() {
+ return (dynCall_viiiii = Module['dynCall_viiiii'] = Module['asm']['dynCall_viiiii']).apply(null, arguments);
};
-var _wasm_select = Module["_wasm_select"] = function() {
- return (_wasm_select = Module["_wasm_select"] = Module["asm"]["ub"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_iii = Module['dynCall_iii'] = function() {
+ return (dynCall_iii = Module['dynCall_iii'] = Module['asm']['dynCall_iii']).apply(null, arguments);
};
-var _wasm_add_cli_arg = Module["_wasm_add_cli_arg"] = function() {
- return (_wasm_add_cli_arg = Module["_wasm_add_cli_arg"] = Module["asm"]["vb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_iiiii = Module['dynCall_iiiii'] = function() {
+ return (dynCall_iiiii = Module['dynCall_iiiii'] = Module['asm']['dynCall_iiiii']).apply(null, arguments);
};
-var _run_cli = Module["_run_cli"] = function() {
- return (_run_cli = Module["_run_cli"] = Module["asm"]["wb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_iiiiii = Module['dynCall_iiiiii'] = function() {
+ return (dynCall_iiiiii = Module['dynCall_iiiiii'] = Module['asm']['dynCall_iiiiii']).apply(null, arguments);
};
-var _wasm_set_sapi_name = Module["_wasm_set_sapi_name"] = function() {
- return (_wasm_set_sapi_name = Module["_wasm_set_sapi_name"] = Module["asm"]["xb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_viii = Module['dynCall_viii'] = function() {
+ return (dynCall_viii = Module['dynCall_viii'] = Module['asm']['dynCall_viii']).apply(null, arguments);
};
-var _wasm_set_phpini_path = Module["_wasm_set_phpini_path"] = function() {
- return (_wasm_set_phpini_path = Module["_wasm_set_phpini_path"] = Module["asm"]["yb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_v = Module['dynCall_v'] = function() {
+ return (dynCall_v = Module['dynCall_v'] = Module['asm']['dynCall_v']).apply(null, arguments);
};
-var _wasm_set_phpini_entries = Module["_wasm_set_phpini_entries"] = function() {
- return (_wasm_set_phpini_entries = Module["_wasm_set_phpini_entries"] = Module["asm"]["zb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_i = Module['dynCall_i'] = function() {
+ return (dynCall_i = Module['dynCall_i'] = Module['asm']['dynCall_i']).apply(null, arguments);
};
-var _wasm_add_SERVER_entry = Module["_wasm_add_SERVER_entry"] = function() {
- return (_wasm_add_SERVER_entry = Module["_wasm_add_SERVER_entry"] = Module["asm"]["Ab"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_viiii = Module['dynCall_viiii'] = function() {
+ return (dynCall_viiii = Module['dynCall_viiii'] = Module['asm']['dynCall_viiii']).apply(null, arguments);
};
-var _wasm_set_query_string = Module["_wasm_set_query_string"] = function() {
- return (_wasm_set_query_string = Module["_wasm_set_query_string"] = Module["asm"]["Bb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_iiiiiii = Module['dynCall_iiiiiii'] = function() {
+ return (dynCall_iiiiiii = Module['dynCall_iiiiiii'] = Module['asm']['dynCall_iiiiiii']).apply(null, arguments);
};
-var _wasm_set_path_translated = Module["_wasm_set_path_translated"] = function() {
- return (_wasm_set_path_translated = Module["_wasm_set_path_translated"] = Module["asm"]["Cb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_vij = Module['dynCall_vij'] = function() {
+ return (dynCall_vij = Module['dynCall_vij'] = Module['asm']['dynCall_vij']).apply(null, arguments);
};
-var _wasm_set_skip_shebang = Module["_wasm_set_skip_shebang"] = function() {
- return (_wasm_set_skip_shebang = Module["_wasm_set_skip_shebang"] = Module["asm"]["Db"]).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);
};
-var _wasm_set_request_uri = Module["_wasm_set_request_uri"] = function() {
- return (_wasm_set_request_uri = Module["_wasm_set_request_uri"] = Module["asm"]["Eb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_viiiiiiii = Module['dynCall_viiiiiiii'] = function() {
+ return (dynCall_viiiiiiii = Module['dynCall_viiiiiiii'] = Module['asm']['dynCall_viiiiiiii']).apply(null, arguments);
};
-var _wasm_set_request_method = Module["_wasm_set_request_method"] = function() {
- return (_wasm_set_request_method = Module["_wasm_set_request_method"] = Module["asm"]["Fb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_viiiiiiiii = Module['dynCall_viiiiiiiii'] = function() {
+ return (dynCall_viiiiiiiii = Module['dynCall_viiiiiiiii'] = Module['asm']['dynCall_viiiiiiiii']).apply(null, arguments);
};
-var _wasm_set_request_host = Module["_wasm_set_request_host"] = function() {
- return (_wasm_set_request_host = Module["_wasm_set_request_host"] = Module["asm"]["Gb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_viiiiiii = Module['dynCall_viiiiiii'] = function() {
+ return (dynCall_viiiiiii = Module['dynCall_viiiiiii'] = Module['asm']['dynCall_viiiiiii']).apply(null, arguments);
};
-var _wasm_set_content_type = Module["_wasm_set_content_type"] = function() {
- return (_wasm_set_content_type = Module["_wasm_set_content_type"] = Module["asm"]["Hb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_viiiiii = Module['dynCall_viiiiii'] = function() {
+ return (dynCall_viiiiii = Module['dynCall_viiiiii'] = Module['asm']['dynCall_viiiiii']).apply(null, arguments);
};
-var _wasm_set_request_body = Module["_wasm_set_request_body"] = function() {
- return (_wasm_set_request_body = Module["_wasm_set_request_body"] = Module["asm"]["Ib"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_iiiiiiii = Module['dynCall_iiiiiiii'] = function() {
+ return (dynCall_iiiiiiii = Module['dynCall_iiiiiiii'] = Module['asm']['dynCall_iiiiiiii']).apply(null, arguments);
};
-var _wasm_set_content_length = Module["_wasm_set_content_length"] = function() {
- return (_wasm_set_content_length = Module["_wasm_set_content_length"] = Module["asm"]["Jb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_iiid = Module['dynCall_iiid'] = function() {
+ return (dynCall_iiid = Module['dynCall_iiid'] = Module['asm']['dynCall_iiid']).apply(null, arguments);
};
-var _wasm_set_cookies = Module["_wasm_set_cookies"] = function() {
- return (_wasm_set_cookies = Module["_wasm_set_cookies"] = Module["asm"]["Kb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_iiiiiiiii = Module['dynCall_iiiiiiiii'] = function() {
+ return (dynCall_iiiiiiiii = Module['dynCall_iiiiiiiii'] = Module['asm']['dynCall_iiiiiiiii']).apply(null, arguments);
};
-var _wasm_set_php_code = Module["_wasm_set_php_code"] = function() {
- return (_wasm_set_php_code = Module["_wasm_set_php_code"] = Module["asm"]["Lb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_iiiiiiiiii = Module['dynCall_iiiiiiiiii'] = function() {
+ return (dynCall_iiiiiiiiii = Module['dynCall_iiiiiiiiii'] = Module['asm']['dynCall_iiiiiiiiii']).apply(null, arguments);
};
-var _wasm_set_request_port = Module["_wasm_set_request_port"] = function() {
- return (_wasm_set_request_port = Module["_wasm_set_request_port"] = Module["asm"]["Mb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_iiiij = Module['dynCall_iiiij'] = function() {
+ return (dynCall_iiiij = Module['dynCall_iiiij'] = Module['asm']['dynCall_iiiij']).apply(null, arguments);
};
-var _wasm_sapi_handle_request = Module["_wasm_sapi_handle_request"] = function() {
- return (_wasm_sapi_handle_request = Module["_wasm_sapi_handle_request"] = Module["asm"]["Nb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_vijii = Module['dynCall_vijii'] = function() {
+ return (dynCall_vijii = Module['dynCall_vijii'] = Module['asm']['dynCall_vijii']).apply(null, arguments);
};
-var _php_wasm_init = Module["_php_wasm_init"] = function() {
- return (_php_wasm_init = Module["_php_wasm_init"] = Module["asm"]["Ob"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_iijj = Module['dynCall_iijj'] = function() {
+ return (dynCall_iijj = Module['dynCall_iijj'] = Module['asm']['dynCall_iijj']).apply(null, arguments);
};
-var ___funcs_on_exit = function() {
- return (___funcs_on_exit = Module["asm"]["Pb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_iij = Module['dynCall_iij'] = function() {
+ return (dynCall_iij = Module['dynCall_iij'] = Module['asm']['dynCall_iij']).apply(null, arguments);
};
-var _emscripten_builtin_memalign = function() {
- return (_emscripten_builtin_memalign = Module["asm"]["Qb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_iijii = Module['dynCall_iijii'] = function() {
+ return (dynCall_iijii = Module['dynCall_iijii'] = Module['asm']['dynCall_iijii']).apply(null, arguments);
};
-var __emscripten_timeout = function() {
- return (__emscripten_timeout = Module["asm"]["Rb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_iiji = Module['dynCall_iiji'] = function() {
+ return (dynCall_iiji = Module['dynCall_iiji'] = Module['asm']['dynCall_iiji']).apply(null, arguments);
};
-var _setThrew = function() {
- return (_setThrew = Module["asm"]["Sb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_iiiiiij = Module['dynCall_iiiiiij'] = function() {
+ return (dynCall_iiiiiij = Module['dynCall_iiiiiij'] = Module['asm']['dynCall_iiiiiij']).apply(null, arguments);
};
-var _emscripten_stack_set_limits = function() {
- return (_emscripten_stack_set_limits = Module["asm"]["emscripten_stack_set_limits"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_iiij = Module['dynCall_iiij'] = function() {
+ return (dynCall_iiij = Module['dynCall_iiij'] = Module['asm']['dynCall_iiij']).apply(null, arguments);
};
-var _emscripten_stack_get_base = function() {
- return (_emscripten_stack_get_base = Module["asm"]["emscripten_stack_get_base"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_dii = Module['dynCall_dii'] = function() {
+ return (dynCall_dii = Module['dynCall_dii'] = Module['asm']['dynCall_dii']).apply(null, arguments);
};
-var _emscripten_stack_get_end = function() {
- return (_emscripten_stack_get_end = Module["asm"]["emscripten_stack_get_end"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_jii = Module['dynCall_jii'] = function() {
+ return (dynCall_jii = Module['dynCall_jii'] = Module['asm']['dynCall_jii']).apply(null, arguments);
};
-var stackSave = function() {
- return (stackSave = Module["asm"]["Tb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_vid = Module['dynCall_vid'] = function() {
+ return (dynCall_vid = Module['dynCall_vid'] = Module['asm']['dynCall_vid']).apply(null, arguments);
};
-var stackRestore = function() {
- return (stackRestore = Module["asm"]["Ub"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_di = Module['dynCall_di'] = function() {
+ return (dynCall_di = Module['dynCall_di'] = Module['asm']['dynCall_di']).apply(null, arguments);
};
-var stackAlloc = function() {
- return (stackAlloc = Module["asm"]["Vb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_iiiiijii = Module['dynCall_iiiiijii'] = function() {
+ return (dynCall_iiiiijii = Module['dynCall_iiiiijii'] = Module['asm']['dynCall_iiiiijii']).apply(null, arguments);
};
-var dynCall_iiii = Module["dynCall_iiii"] = function() {
- return (dynCall_iiii = Module["dynCall_iiii"] = Module["asm"]["Wb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_j = Module['dynCall_j'] = function() {
+ return (dynCall_j = Module['dynCall_j'] = Module['asm']['dynCall_j']).apply(null, arguments);
};
-var dynCall_ii = Module["dynCall_ii"] = function() {
- return (dynCall_ii = Module["dynCall_ii"] = Module["asm"]["Xb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_jj = Module['dynCall_jj'] = function() {
+ return (dynCall_jj = Module['dynCall_jj'] = Module['asm']['dynCall_jj']).apply(null, arguments);
};
-var dynCall_vi = Module["dynCall_vi"] = function() {
- return (dynCall_vi = Module["dynCall_vi"] = Module["asm"]["Yb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_jiij = Module['dynCall_jiij'] = function() {
+ return (dynCall_jiij = Module['dynCall_jiij'] = Module['asm']['dynCall_jiij']).apply(null, arguments);
};
-var dynCall_vii = Module["dynCall_vii"] = function() {
- return (dynCall_vii = Module["dynCall_vii"] = Module["asm"]["Zb"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_iiiiji = Module['dynCall_iiiiji'] = function() {
+ return (dynCall_iiiiji = Module['dynCall_iiiiji'] = Module['asm']['dynCall_iiiiji']).apply(null, arguments);
};
-var dynCall_viiiii = Module["dynCall_viiiii"] = function() {
- return (dynCall_viiiii = Module["dynCall_viiiii"] = Module["asm"]["_b"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_iiiijii = Module['dynCall_iiiijii'] = function() {
+ return (dynCall_iiiijii = Module['dynCall_iiiijii'] = Module['asm']['dynCall_iiiijii']).apply(null, arguments);
};
-var dynCall_iii = Module["dynCall_iii"] = function() {
- return (dynCall_iii = Module["dynCall_iii"] = Module["asm"]["$b"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_ij = Module['dynCall_ij'] = function() {
+ return (dynCall_ij = Module['dynCall_ij'] = Module['asm']['dynCall_ij']).apply(null, arguments);
};
-var dynCall_iiiii = Module["dynCall_iiiii"] = function() {
- return (dynCall_iiiii = Module["dynCall_iiiii"] = Module["asm"]["ac"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_viiji = Module['dynCall_viiji'] = function() {
+ return (dynCall_viiji = Module['dynCall_viiji'] = Module['asm']['dynCall_viiji']).apply(null, arguments);
};
-var dynCall_iiiiii = Module["dynCall_iiiiii"] = function() {
- return (dynCall_iiiiii = Module["dynCall_iiiiii"] = Module["asm"]["bc"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_viijii = Module['dynCall_viijii'] = function() {
+ return (dynCall_viijii = Module['dynCall_viijii'] = Module['asm']['dynCall_viijii']).apply(null, arguments);
};
-var dynCall_viii = Module["dynCall_viii"] = function() {
- return (dynCall_viii = Module["dynCall_viii"] = Module["asm"]["cc"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_iiiiiiiiiii = Module['dynCall_iiiiiiiiiii'] = function() {
+ return (dynCall_iiiiiiiiiii = Module['dynCall_iiiiiiiiiii'] = Module['asm']['dynCall_iiiiiiiiiii']).apply(null, arguments);
};
-var dynCall_v = Module["dynCall_v"] = function() {
- return (dynCall_v = Module["dynCall_v"] = Module["asm"]["dc"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_iiiijji = Module['dynCall_iiiijji'] = function() {
+ return (dynCall_iiiijji = Module['dynCall_iiiijji'] = Module['asm']['dynCall_iiiijji']).apply(null, arguments);
};
-var dynCall_i = Module["dynCall_i"] = function() {
- return (dynCall_i = Module["dynCall_i"] = Module["asm"]["ec"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_dd = Module['dynCall_dd'] = function() {
+ return (dynCall_dd = Module['dynCall_dd'] = Module['asm']['dynCall_dd']).apply(null, arguments);
};
-var dynCall_viiii = Module["dynCall_viiii"] = function() {
- return (dynCall_viiii = Module["dynCall_viiii"] = Module["asm"]["fc"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_ddd = Module['dynCall_ddd'] = function() {
+ return (dynCall_ddd = Module['dynCall_ddd'] = Module['asm']['dynCall_ddd']).apply(null, arguments);
};
-var dynCall_iiiiiii = Module["dynCall_iiiiiii"] = function() {
- return (dynCall_iiiiiii = Module["dynCall_iiiiiii"] = Module["asm"]["gc"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_iiiiiiiiiiii = Module['dynCall_iiiiiiiiiiii'] = function() {
+ return (dynCall_iiiiiiiiiiii = Module['dynCall_iiiiiiiiiiii'] = Module['asm']['dynCall_iiiiiiiiiiii']).apply(null, arguments);
};
-var dynCall_viiiiiiiii = Module["dynCall_viiiiiiiii"] = function() {
- return (dynCall_viiiiiiiii = Module["dynCall_viiiiiiiii"] = Module["asm"]["hc"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_viidii = Module['dynCall_viidii'] = function() {
+ return (dynCall_viidii = Module['dynCall_viidii'] = Module['asm']['dynCall_viidii']).apply(null, arguments);
};
-var dynCall_viiiiiii = Module["dynCall_viiiiiii"] = function() {
- return (dynCall_viiiiiii = Module["dynCall_viiiiiii"] = Module["asm"]["ic"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_jiiji = Module['dynCall_jiiji'] = function() {
+ return (dynCall_jiiji = Module['dynCall_jiiji'] = Module['asm']['dynCall_jiiji']).apply(null, arguments);
};
-var dynCall_viiiiii = Module["dynCall_viiiiii"] = function() {
- return (dynCall_viiiiii = Module["dynCall_viiiiii"] = Module["asm"]["jc"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_jiiiji = Module['dynCall_jiiiji'] = function() {
+ return (dynCall_jiiiji = Module['dynCall_jiiiji'] = Module['asm']['dynCall_jiiiji']).apply(null, arguments);
};
-var dynCall_iiiiiiii = Module["dynCall_iiiiiiii"] = function() {
- return (dynCall_iiiiiiii = Module["dynCall_iiiiiiii"] = Module["asm"]["kc"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_iiiji = Module['dynCall_iiiji'] = function() {
+ return (dynCall_iiiji = Module['dynCall_iiiji'] = Module['asm']['dynCall_iiiji']).apply(null, arguments);
};
-var dynCall_iiiiiiiiii = Module["dynCall_iiiiiiiiii"] = function() {
- return (dynCall_iiiiiiiiii = Module["dynCall_iiiiiiiiii"] = Module["asm"]["lc"]).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);
};
-var dynCall_viidii = Module["dynCall_viidii"] = function() {
- return (dynCall_viidii = Module["dynCall_viidii"] = Module["asm"]["mc"]).apply(null, arguments);
+/** @type {function(...*):?} */
+var dynCall_iidiiii = Module['dynCall_iidiiii'] = function() {
+ return (dynCall_iidiiii = Module['dynCall_iidiiii'] = Module['asm']['dynCall_iidiiii']).apply(null, arguments);
};
+/** @type {function(...*):?} */
var _asyncify_start_unwind = function() {
- return (_asyncify_start_unwind = Module["asm"]["nc"]).apply(null, arguments);
+ return (_asyncify_start_unwind = Module['asm']['asyncify_start_unwind']).apply(null, arguments);
};
+/** @type {function(...*):?} */
var _asyncify_stop_unwind = function() {
- return (_asyncify_stop_unwind = Module["asm"]["oc"]).apply(null, arguments);
+ return (_asyncify_stop_unwind = Module['asm']['asyncify_stop_unwind']).apply(null, arguments);
};
+/** @type {function(...*):?} */
var _asyncify_start_rewind = function() {
- return (_asyncify_start_rewind = Module["asm"]["pc"]).apply(null, arguments);
+ return (_asyncify_start_rewind = Module['asm']['asyncify_start_rewind']).apply(null, arguments);
};
+/** @type {function(...*):?} */
var _asyncify_stop_rewind = function() {
- return (_asyncify_stop_rewind = Module["asm"]["qc"]).apply(null, arguments);
+ return (_asyncify_stop_rewind = Module['asm']['asyncify_stop_rewind']).apply(null, arguments);
};
-function invoke_iiiiiii(index, a1, a2, a3, a4, a5, a6) {
- var sp = stackSave();
- try {
- return dynCall_iiiiiii(index, a1, a2, a3, a4, a5, a6);
- } catch (e) {
- stackRestore(sp);
- if (e !== e + 0) throw e;
- _setThrew(1, 0);
- }
+
+function invoke_iiiiiii(index,a1,a2,a3,a4,a5,a6) {
+ var sp = stackSave();
+ try {
+ return dynCall_iiiiiii(index,a1,a2,a3,a4,a5,a6);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
}
-function invoke_vi(index, a1) {
- var sp = stackSave();
- try {
- dynCall_vi(index, a1);
- } catch (e) {
- stackRestore(sp);
- if (e !== e + 0) throw e;
- _setThrew(1, 0);
- }
+function invoke_vi(index,a1) {
+ var sp = stackSave();
+ try {
+ dynCall_vi(index,a1);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
}
-function invoke_iiii(index, a1, a2, a3) {
- var sp = stackSave();
- try {
- return dynCall_iiii(index, a1, a2, a3);
- } catch (e) {
- stackRestore(sp);
- if (e !== e + 0) throw e;
- _setThrew(1, 0);
- }
+function invoke_iiii(index,a1,a2,a3) {
+ var sp = stackSave();
+ try {
+ return dynCall_iiii(index,a1,a2,a3);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
}
-function invoke_iii(index, a1, a2) {
- var sp = stackSave();
- try {
- return dynCall_iii(index, a1, a2);
- } catch (e) {
- stackRestore(sp);
- if (e !== e + 0) throw e;
- _setThrew(1, 0);
- }
+function invoke_iii(index,a1,a2) {
+ var sp = stackSave();
+ try {
+ return dynCall_iii(index,a1,a2);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
}
-function invoke_vii(index, a1, a2) {
- var sp = stackSave();
- try {
- dynCall_vii(index, a1, a2);
- } catch (e) {
- stackRestore(sp);
- if (e !== e + 0) throw e;
- _setThrew(1, 0);
- }
+function invoke_vii(index,a1,a2) {
+ var sp = stackSave();
+ try {
+ dynCall_vii(index,a1,a2);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
}
-function invoke_ii(index, a1) {
- var sp = stackSave();
- try {
- return dynCall_ii(index, a1);
- } catch (e) {
- stackRestore(sp);
- if (e !== e + 0) throw e;
- _setThrew(1, 0);
- }
+function invoke_ii(index,a1) {
+ var sp = stackSave();
+ try {
+ return dynCall_ii(index,a1);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
}
-function invoke_viii(index, a1, a2, a3) {
- var sp = stackSave();
- try {
- dynCall_viii(index, a1, a2, a3);
- } catch (e) {
- stackRestore(sp);
- if (e !== e + 0) throw e;
- _setThrew(1, 0);
- }
+function invoke_viii(index,a1,a2,a3) {
+ var sp = stackSave();
+ try {
+ dynCall_viii(index,a1,a2,a3);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
}
function invoke_v(index) {
- var sp = stackSave();
- try {
- dynCall_v(index);
- } catch (e) {
- stackRestore(sp);
- if (e !== e + 0) throw e;
- _setThrew(1, 0);
- }
+ var sp = stackSave();
+ try {
+ dynCall_v(index);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
}
function invoke_i(index) {
- var sp = stackSave();
- try {
- return dynCall_i(index);
- } catch (e) {
- stackRestore(sp);
- if (e !== e + 0) throw e;
- _setThrew(1, 0);
- }
+ var sp = stackSave();
+ try {
+ return dynCall_i(index);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
}
-function invoke_viiii(index, a1, a2, a3, a4) {
- var sp = stackSave();
- try {
- dynCall_viiii(index, a1, a2, a3, a4);
- } catch (e) {
- stackRestore(sp);
- if (e !== e + 0) throw e;
- _setThrew(1, 0);
- }
+function invoke_viiii(index,a1,a2,a3,a4) {
+ var sp = stackSave();
+ try {
+ dynCall_viiii(index,a1,a2,a3,a4);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
}
-function invoke_viiiii(index, a1, a2, a3, a4, a5) {
- var sp = stackSave();
- try {
- dynCall_viiiii(index, a1, a2, a3, a4, a5);
- } catch (e) {
- stackRestore(sp);
- if (e !== e + 0) throw e;
- _setThrew(1, 0);
- }
+function invoke_viiiii(index,a1,a2,a3,a4,a5) {
+ var sp = stackSave();
+ try {
+ dynCall_viiiii(index,a1,a2,a3,a4,a5);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
}
-function invoke_iiiiii(index, a1, a2, a3, a4, a5) {
- var sp = stackSave();
- try {
- return dynCall_iiiiii(index, a1, a2, a3, a4, a5);
- } catch (e) {
- stackRestore(sp);
- if (e !== e + 0) throw e;
- _setThrew(1, 0);
- }
+function invoke_iiiiii(index,a1,a2,a3,a4,a5) {
+ var sp = stackSave();
+ try {
+ return dynCall_iiiiii(index,a1,a2,a3,a4,a5);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
}
-function invoke_iiiii(index, a1, a2, a3, a4) {
- var sp = stackSave();
- try {
- return dynCall_iiiii(index, a1, a2, a3, a4);
- } catch (e) {
- stackRestore(sp);
- if (e !== e + 0) throw e;
- _setThrew(1, 0);
- }
+function invoke_iiiii(index,a1,a2,a3,a4) {
+ var sp = stackSave();
+ try {
+ return dynCall_iiiii(index,a1,a2,a3,a4);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
}
-function invoke_iiiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9) {
- var sp = stackSave();
- try {
- return dynCall_iiiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9);
- } catch (e) {
- stackRestore(sp);
- if (e !== e + 0) throw e;
- _setThrew(1, 0);
- }
+function invoke_iiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9) {
+ var sp = stackSave();
+ try {
+ return dynCall_iiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
}
-function invoke_viiiiii(index, a1, a2, a3, a4, a5, a6) {
- var sp = stackSave();
- try {
- dynCall_viiiiii(index, a1, a2, a3, a4, a5, a6);
- } catch (e) {
- stackRestore(sp);
- if (e !== e + 0) throw e;
- _setThrew(1, 0);
- }
+function invoke_viiiiii(index,a1,a2,a3,a4,a5,a6) {
+ var sp = stackSave();
+ try {
+ dynCall_viiiiii(index,a1,a2,a3,a4,a5,a6);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
}
-function invoke_viidii(index, a1, a2, a3, a4, a5) {
- var sp = stackSave();
- try {
- dynCall_viidii(index, a1, a2, a3, a4, a5);
- } catch (e) {
- stackRestore(sp);
- if (e !== e + 0) throw e;
- _setThrew(1, 0);
- }
+function invoke_viidii(index,a1,a2,a3,a4,a5) {
+ var sp = stackSave();
+ try {
+ dynCall_viidii(index,a1,a2,a3,a4,a5);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
}
-function invoke_viiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9) {
- var sp = stackSave();
- try {
- dynCall_viiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9);
- } catch (e) {
- stackRestore(sp);
- if (e !== e + 0) throw e;
- _setThrew(1, 0);
- }
+function invoke_viiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9) {
+ var sp = stackSave();
+ try {
+ dynCall_viiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
}
-function invoke_iiiiiiii(index, a1, a2, a3, a4, a5, a6, a7) {
- var sp = stackSave();
- try {
- return dynCall_iiiiiiii(index, a1, a2, a3, a4, a5, a6, a7);
- } catch (e) {
- stackRestore(sp);
- if (e !== e + 0) throw e;
- _setThrew(1, 0);
- }
+function invoke_iiiiiiii(index,a1,a2,a3,a4,a5,a6,a7) {
+ var sp = stackSave();
+ try {
+ return dynCall_iiiiiiii(index,a1,a2,a3,a4,a5,a6,a7);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
}
-function invoke_viiiiiii(index, a1, a2, a3, a4, a5, a6, a7) {
- var sp = stackSave();
- try {
- dynCall_viiiiiii(index, a1, a2, a3, a4, a5, a6, a7);
- } catch (e) {
- stackRestore(sp);
- if (e !== e + 0) throw e;
- _setThrew(1, 0);
- }
+function invoke_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7) {
+ var sp = stackSave();
+ try {
+ dynCall_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
}
-Module["addRunDependency"] = addRunDependency;
-
-Module["removeRunDependency"] = removeRunDependency;
-
-Module["FS_createPath"] = FS.createPath;
-Module["FS_createDataFile"] = FS.createDataFile;
+// include: postamble.js
+// === Auto-generated postamble setup entry stuff ===
-Module["FS_createLazyFile"] = FS.createLazyFile;
+// include: base64Utils.js
+// Converts a string of base64 into a byte array.
+// Throws error on invalid input.
+function intArrayFromBase64(s) {
+ if (typeof ENVIRONMENT_IS_NODE != 'undefined' && ENVIRONMENT_IS_NODE) {
+ var buf = Buffer.from(s, 'base64');
+ return new Uint8Array(buf['buffer'], buf['byteOffset'], buf['byteLength']);
+ }
-Module["FS_createDevice"] = FS.createDevice;
+ try {
+ var decoded = atob(s);
+ var bytes = new Uint8Array(decoded.length);
+ for (var i = 0 ; i < decoded.length ; ++i) {
+ bytes[i] = decoded.charCodeAt(i);
+ }
+ return bytes;
+ } catch (_) {
+ throw new Error('Converting base64 string to bytes failed.');
+ }
+}
-Module["FS_unlink"] = FS.unlink;
+// If filename is a base64 data URI, parses and returns data (Buffer on node,
+// Uint8Array otherwise). If filename is not a base64 data URI, returns undefined.
+function tryParseAsDataURI(filename) {
+ if (!isDataURI(filename)) {
+ return;
+ }
-Module["ccall"] = ccall;
+ return intArrayFromBase64(filename.slice(dataURIPrefix.length));
+}
+// end include: base64Utils.js
+Module['addRunDependency'] = addRunDependency;
+Module['removeRunDependency'] = removeRunDependency;
+Module['FS_createPath'] = FS.createPath;
+Module['FS_createDataFile'] = FS.createDataFile;
+Module['FS_createLazyFile'] = FS.createLazyFile;
+Module['FS_createDevice'] = FS.createDevice;
+Module['FS_unlink'] = FS.unlink;
+Module['ccall'] = ccall;
+Module['FS_createPreloadedFile'] = FS.createPreloadedFile;
-Module["FS_createPreloadedFile"] = FS.createPreloadedFile;
var calledRun;
dependenciesFulfilled = function runCaller() {
- if (!calledRun) run();
- if (!calledRun) dependenciesFulfilled = 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 run() {
- if (runDependencies > 0) {
- return;
- }
- preRun();
- if (runDependencies > 0) {
- return;
- }
- function doRun() {
- if (calledRun) return;
- calledRun = true;
- Module["calledRun"] = true;
- if (ABORT) return;
- initRuntime();
- if (Module["onRuntimeInitialized"]) Module["onRuntimeInitialized"]();
- postRun();
- }
- if (Module["setStatus"]) {
- Module["setStatus"]("Running...");
- setTimeout((function() {
- setTimeout((function() {
- Module["setStatus"]("");
- }), 1);
- doRun();
- }), 1);
- } else {
- doRun();
- }
+
+ 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();
+
+ if (Module['onRuntimeInitialized']) Module['onRuntimeInitialized']();
+
+ postRun();
+ }
+
+ if (Module['setStatus']) {
+ Module['setStatus']('Running...');
+ setTimeout(function() {
+ setTimeout(function() {
+ Module['setStatus']('');
+ }, 1);
+ doRun();
+ }, 1);
+ } else
+ {
+ doRun();
+ }
}
-if (Module["preInit"]) {
- if (typeof Module["preInit"] == "function") Module["preInit"] = [ Module["preInit"] ];
- while (Module["preInit"].length > 0) {
- Module["preInit"].pop()();
- }
+if (Module['preInit']) {
+ if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']];
+ while (Module['preInit'].length > 0) {
+ Module['preInit'].pop()();
+ }
}
run();
+
+
+// end include: postamble.js
/**
* Emscripten resolves `localhost` to a random IP address. Let's
* make it always resolve to 127.0.0.1.
diff --git a/packages/php-wasm/node/src/test/php-asyncify.spec.ts b/packages/php-wasm/node/src/test/php-asyncify.spec.ts
index 363a1538cf..b926b6a396 100644
--- a/packages/php-wasm/node/src/test/php-asyncify.spec.ts
+++ b/packages/php-wasm/node/src/test/php-asyncify.spec.ts
@@ -28,7 +28,7 @@ const js = phpVars({
const phpVersions =
'PHP' in process.env ? [process.env['PHP']] : SupportedPHPVersions;
-describe.each(phpVersions)('PHP %s – asyncify', (phpVersion) => {
+describe.each(['8.2'])('PHP %s – asyncify', (phpVersion) => {
const topOfTheStack: Array = [
// http:// stream handler
`file_get_contents(${js['httpUrl']});`,
@@ -74,6 +74,13 @@ describe.each(phpVersions)('PHP %s – asyncify', (phpVersion) => {
));
});
+ describe('Generators', () => {
+ test('Simple iteration', () =>
+ assertNoCrash(
+ `function test() { yield ${networkCall} } foreach(test() as $val) { }`
+ ));
+ });
+
describe('Array functions', () => {
test('array_filter', () =>
assertNoCrash(`
diff --git a/packages/php-wasm/node/src/test/php.spec.ts b/packages/php-wasm/node/src/test/php.spec.ts
index 87a54eb03b..ff6916fe25 100644
--- a/packages/php-wasm/node/src/test/php.spec.ts
+++ b/packages/php-wasm/node/src/test/php.spec.ts
@@ -67,7 +67,7 @@ destructive results fifty years hence. He was, I believe, not in the
least an ill-natured man: very much the opposite, I should say; but he
would not suffer fools gladly.`;
-describe.each(SupportedPHPVersions)('PHP %s', (phpVersion) => {
+describe.each(['8.2'])('PHP %s', (phpVersion) => {
let php: NodePHP;
beforeEach(async () => {
php = await NodePHP.load(phpVersion as any, {
@@ -87,6 +87,37 @@ describe.each(SupportedPHPVersions)('PHP %s', (phpVersion) => {
}
});
+ describe('ENV variables', () => {
+ it('Supports setting per-request ENV variables', async () => {
+ const result = await php.run({
+ env: {
+ OPTIONS: 'WordPress',
+ },
+ code: ` {
+ await php.run({
+ env: {
+ OPTIONS: 'WordPress',
+ },
+ code: ` {
it('echo', async () => {
const result = await php.run({
@@ -274,6 +305,51 @@ describe.each(SupportedPHPVersions)('PHP %s', (phpVersion) => {
expect(result.text).toEqual('stdout: WordPress\nstderr: \n');
});
+ it('Passes the cwd and env arguments', async () => {
+ const handler = createSpawnHandler(
+ (command: string, processApi: any, options: any) => {
+ console.log({ command, options });
+ processApi.flushStdin();
+ processApi.stdout(options.cwd + '\n');
+ for (const key in options.env) {
+ processApi.stdout(key + '=' + options.env[key] + '\n');
+ }
+ processApi.exit(0);
+ }
+ );
+
+ php.setSpawnHandler(handler);
+
+ const result = await php.run({
+ code: ` "BAR", "BAZ" => "QUX")
+ );
+ fwrite($pipes[0], 'WordPress\n');
+
+ proc_close($res);
+
+ $stdout = file_get_contents("/tmp/process_out");
+ $stderr = file_get_contents("/tmp/process_err");
+
+ echo 'stdout: ' . $stdout . "";
+ echo 'stderr: ' . $stderr . PHP_EOL;
+ `,
+ });
+
+ expect(result.text).toEqual(
+ 'stdout: /wordpress\nFOO=BAR\nBAZ=QUX\nstderr: \n'
+ );
+ });
+
async function pygmalionToProcess(cmd = 'less') {
return await php.run({
code: ` {
expect(result.text).toEqual(pygmalion);
});
+
+ it('Pipe pygmalion from a file to STDOUT through "cat"', async () => {
+ const result = await pygmalionToProcess('cat');
+ expect(result.text).toEqual(pygmalion);
+ });
it('Pipe pygmalion from a file to STDOUT through "cat"', async () => {
const result = await pygmalionToProcess('cat');
expect(result.text).toEqual(pygmalion);
});
-
- // @TODO This test fails on some PHP versions for yet unknown reasons.
- // Interestingly, the "cat" test above succeeds.
- if (!['8.3', '8.2'].includes(phpVersion)) {
- it('Pipe pygmalion from a file to STDOUT through "less"', async () => {
- const result = await pygmalionToProcess('less');
- expect(result.text).toEqual(pygmalion);
- });
- }
it('Uses the specified spawn handler', async () => {
let spawnHandlerCalled = false;
diff --git a/packages/php-wasm/universal/src/lib/base-php.ts b/packages/php-wasm/universal/src/lib/base-php.ts
index c45b910800..e5b8b6223a 100644
--- a/packages/php-wasm/universal/src/lib/base-php.ts
+++ b/packages/php-wasm/universal/src/lib/base-php.ts
@@ -249,6 +249,11 @@ export abstract class BasePHP implements IsomorphicLocalPHP {
this.#initWebRuntime();
this.#webSapiInitialized = true;
}
+ if (request.scriptPath && !this.fileExists(request.scriptPath)) {
+ throw new Error(
+ `The script path "${request.scriptPath}" does not exist.`
+ );
+ }
this.#setScriptPath(request.scriptPath || '');
this.#setRelativeRequestUri(request.relativeUri || '');
this.#setRequestMethod(request.method || 'GET');
@@ -264,6 +269,12 @@ export abstract class BasePHP implements IsomorphicLocalPHP {
this.#setPHPCode(' ?>' + request.code);
}
this.#addServerGlobalEntriesInWasm();
+
+ const env = request.env || {};
+ for (const key in env) {
+ this.#setEnv(key, env[key]);
+ }
+
const response = await this.#handleRequest();
if (request.throwOnError && response.exitCode !== 0) {
const output = {
@@ -272,10 +283,12 @@ export abstract class BasePHP implements IsomorphicLocalPHP {
};
console.warn(`PHP.run() output was:`, output);
const error = new Error(
- `PHP.run() failed with exit code ${response.exitCode} and the following output`
+ `PHP.run() failed with exit code ${response.exitCode} and the following output: ` +
+ response.errors
);
// @ts-ignore
error.output = output;
+ console.error(error);
throw error;
}
return response;
@@ -534,6 +547,15 @@ export abstract class BasePHP implements IsomorphicLocalPHP {
}
}
+ #setEnv(name: string, value: string) {
+ this[__private__dont__use].ccall(
+ 'wasm_add_ENV_entry',
+ null,
+ [STRING, STRING],
+ [name, value]
+ );
+ }
+
defineConstant(key: string, value: string | boolean | number | null) {
let consts = {};
try {
@@ -577,6 +599,8 @@ export abstract class BasePHP implements IsomorphicLocalPHP {
// eslint-disable-next-line no-async-promise-executor
exitCode = await new Promise((resolve, reject) => {
errorListener = (e: ErrorEvent) => {
+ console.error(e);
+ console.error(e.error);
const rethrown = new Error('Rethrown');
rethrown.cause = e.error;
(rethrown as any).betterMessage = e.message;
@@ -622,6 +646,7 @@ export abstract class BasePHP implements IsomorphicLocalPHP {
) as string;
const rethrown = new Error(message);
rethrown.cause = err;
+ console.error(rethrown);
throw rethrown;
} finally {
this.#wasmErrorsTarget?.removeEventListener('error', errorListener);
@@ -794,7 +819,7 @@ export abstract class BasePHP implements IsomorphicLocalPHP {
// Copy the MEMFS directory structure from the old FS to the new one
if (this.requestHandler) {
const docroot = this.documentRoot;
- recreateMemFS(this[__private__dont__use].FS, oldFS, docroot);
+ copyFS(oldFS, this[__private__dont__use].FS, docroot);
}
}
@@ -830,14 +855,30 @@ export function normalizeHeaders(
type EmscriptenFS = any;
+export function syncFSTo(
+ source: BasePHP,
+ target: BasePHP,
+ path: string | null = null
+) {
+ copyFS(
+ source[__private__dont__use].FS,
+ target[__private__dont__use].FS,
+ path ?? source.documentRoot
+ );
+}
+
/**
* Copies the MEMFS directory structure from one FS in another FS.
* Non-MEMFS nodes are ignored.
*/
-function recreateMemFS(newFS: EmscriptenFS, oldFS: EmscriptenFS, path: string) {
+export function copyFS(
+ source: EmscriptenFS,
+ target: EmscriptenFS,
+ path: string
+) {
let oldNode;
try {
- oldNode = oldFS.lookupPath(path);
+ oldNode = source.lookupPath(path);
} catch (e) {
return;
}
@@ -850,23 +891,23 @@ function recreateMemFS(newFS: EmscriptenFS, oldFS: EmscriptenFS, path: string) {
// Let's be extra careful and only proceed if newFs doesn't
// already have a node at the given path.
try {
- newFS = newFS.lookupPath(path);
- return;
+ // target = target.lookupPath(path);
+ // return;
} catch (e) {
// There's no such node in the new FS. Good,
// we may proceed.
}
- if (!oldFS.isDir(oldNode.node.mode)) {
- newFS.writeFile(path, oldFS.readFile(path));
+ if (!source.isDir(oldNode.node.mode)) {
+ target.writeFile(path, source.readFile(path));
return;
}
- newFS.mkdirTree(path);
- const filenames = oldFS
+ target.mkdirTree(path);
+ const filenames = source
.readdir(path)
.filter((name: string) => name !== '.' && name !== '..');
for (const filename of filenames) {
- recreateMemFS(newFS, oldFS, joinPaths(path, filename));
+ copyFS(source, target, joinPaths(path, filename));
}
}
diff --git a/packages/php-wasm/universal/src/lib/index.ts b/packages/php-wasm/universal/src/lib/index.ts
index cc51f72e34..632ca3b8b2 100644
--- a/packages/php-wasm/universal/src/lib/index.ts
+++ b/packages/php-wasm/universal/src/lib/index.ts
@@ -39,7 +39,7 @@ export type {
SupportedPHPExtension,
SupportedPHPExtensionBundle,
} from './supported-php-extensions';
-export { BasePHP, __private__dont__use } from './base-php';
+export { BasePHP, syncFSTo, __private__dont__use } from './base-php';
export { loadPHPRuntime } from './load-php-runtime';
export type {
DataModule,
diff --git a/packages/php-wasm/universal/src/lib/load-php-runtime.ts b/packages/php-wasm/universal/src/lib/load-php-runtime.ts
index 4ba3e48193..8b411f88db 100644
--- a/packages/php-wasm/universal/src/lib/load-php-runtime.ts
+++ b/packages/php-wasm/universal/src/lib/load-php-runtime.ts
@@ -125,6 +125,7 @@ export async function loadPHPRuntime(
): Promise {
const [phpReady, resolvePHP, rejectPHP] = makePromise();
+ const ENV = {};
const PHPRuntime = phpLoaderModule.init(currentJsRuntime, {
onAbort(reason) {
rejectPHP(reason);
@@ -132,7 +133,7 @@ export async function loadPHPRuntime(
// let's just log it.
console.error(reason);
},
- ENV: {},
+ ENV: ENV,
// Emscripten sometimes prepends a '/' to the path, which
// breaks vite dev mode. An identity `locateFile` function
// fixes it.
diff --git a/packages/php-wasm/universal/src/lib/universal-php.ts b/packages/php-wasm/universal/src/lib/universal-php.ts
index f75d734f25..3cce22ddd7 100644
--- a/packages/php-wasm/universal/src/lib/universal-php.ts
+++ b/packages/php-wasm/universal/src/lib/universal-php.ts
@@ -524,6 +524,11 @@ export interface PHPRunOptions {
*/
body?: string | Uint8Array;
+ /**
+ * Environment variables to set for the PHP process.
+ */
+ env?: Record;
+
/**
* The code snippet to eval instead of a php file.
*/
diff --git a/packages/php-wasm/util/src/lib/create-spawn-handler.ts b/packages/php-wasm/util/src/lib/create-spawn-handler.ts
index 25974b234e..a42d9ab477 100644
--- a/packages/php-wasm/util/src/lib/create-spawn-handler.ts
+++ b/packages/php-wasm/util/src/lib/create-spawn-handler.ts
@@ -1,5 +1,12 @@
+import { splitShellCommand } from './split-shell-command';
+
type Listener = (...args: any[]) => any;
+export interface ProcessOptions {
+ cwd?: string;
+ env?: Record;
+}
+
/**
* Usage:
* ```ts
@@ -15,14 +22,33 @@ type Listener = (...args: any[]) => any;
* @returns
*/
export function createSpawnHandler(
- program: (command: string, processApi: ProcessApi) => void
+ program: (
+ command: string[],
+ processApi: ProcessApi,
+ options: ProcessOptions
+ ) => void | Promise
): any {
- return function (command: string) {
+ return function (
+ command: string | string[],
+ argsArray: string[] = [],
+ options: ProcessOptions = {}
+ ) {
+ console.log({ command, argsArray, options });
const childProcess = new ChildProcess();
const processApi = new ProcessApi(childProcess);
// Give PHP a chance to register listeners
setTimeout(async () => {
- await program(command, processApi);
+ let commandArray = [];
+ if (argsArray.length) {
+ commandArray = [command as string, ...argsArray];
+ } else if (typeof command === 'string') {
+ commandArray = splitShellCommand(command);
+ } else if (Array.isArray(command)) {
+ commandArray = command;
+ } else {
+ throw new Error('Invalid command ', command);
+ }
+ await program(commandArray, processApi, options);
childProcess.emit('spawn', true);
});
return childProcess;
@@ -67,15 +93,22 @@ export class ProcessApi extends EventEmitter {
}
this.childProcess.stdout.emit('data', data);
}
+ stdoutEnd() {
+ this.childProcess.stdout.emit('end', {});
+ }
stderr(data: string | ArrayBuffer) {
if (typeof data === 'string') {
data = new TextEncoder().encode(data);
}
this.childProcess.stderr.emit('data', data);
}
+ stderrEnd() {
+ this.childProcess.stderr.emit('end', {});
+ }
exit(code: number) {
if (!this.exited) {
this.exited = true;
+ console.log('Emit exit!');
this.childProcess.emit('exit', code);
}
}
diff --git a/packages/php-wasm/util/src/lib/index.ts b/packages/php-wasm/util/src/lib/index.ts
index c322dc7f63..41d08aaf46 100644
--- a/packages/php-wasm/util/src/lib/index.ts
+++ b/packages/php-wasm/util/src/lib/index.ts
@@ -5,5 +5,6 @@ export { dirname, joinPaths, basename, normalizePath } from './paths';
export { createSpawnHandler } from './create-spawn-handler';
export { randomString } from './random-string';
export { randomFilename } from './random-filename';
+export { splitShellCommand } from './split-shell-command';
export * from './php-vars';
diff --git a/packages/php-wasm/util/src/lib/split-shell-command.spec.ts b/packages/php-wasm/util/src/lib/split-shell-command.spec.ts
new file mode 100644
index 0000000000..2e5ab4910d
--- /dev/null
+++ b/packages/php-wasm/util/src/lib/split-shell-command.spec.ts
@@ -0,0 +1,27 @@
+import { splitShellCommand } from './split-shell-command';
+
+describe('splitShellCommand', () => {
+ it('Should split a shell command into an array', () => {
+ const command =
+ 'wp post create --post_title="Test post" --post_excerpt="Some content"';
+ const result = splitShellCommand(command);
+ expect(result).toEqual([
+ 'wp',
+ 'post',
+ 'create',
+ '--post_title=Test post',
+ '--post_excerpt=Some content',
+ ]);
+ });
+
+ it('Should treat multiple spaces as a single space', () => {
+ const command = 'ls --wordpress --playground --is-great';
+ const result = splitShellCommand(command);
+ expect(result).toEqual([
+ 'ls',
+ '--wordpress',
+ '--playground',
+ '--is-great',
+ ]);
+ });
+});
diff --git a/packages/php-wasm/util/src/lib/split-shell-command.ts b/packages/php-wasm/util/src/lib/split-shell-command.ts
new file mode 100644
index 0000000000..7ae131d72d
--- /dev/null
+++ b/packages/php-wasm/util/src/lib/split-shell-command.ts
@@ -0,0 +1,55 @@
+/**
+ * Naive shell command parser.
+ * Ensures that commands like `wp option set blogname "My blog name"` are split into
+ * `['wp', 'option', 'set', 'blogname', 'My blog name']` instead of
+ * `['wp', 'option', 'set', 'blogname', 'My', 'blog', 'name']`.
+ *
+ * @param command
+ * @returns
+ */
+export function splitShellCommand(command: string) {
+ const MODE_NORMAL = 0;
+ const MODE_IN_QUOTE = 1;
+
+ let mode = MODE_NORMAL;
+ let quote = '';
+
+ const parts: string[] = [];
+ let currentPart = '';
+ for (let i = 0; i < command.length; i++) {
+ const char = command[i];
+ if (char === '\\') {
+ // @TODO more reliable parsing, this is vary naive
+ if (command[i + 1] === '"' || command[i + 1] === "'") {
+ i++;
+ }
+ currentPart += command[i];
+ } else if (mode === MODE_NORMAL) {
+ if (char === '"' || char === "'") {
+ mode = MODE_IN_QUOTE;
+ quote = char;
+ } else if (char.match(/\s/)) {
+ parts.push(currentPart);
+ currentPart = '';
+ } else if (parts.length && !currentPart) {
+ // We just closed a quote to continue the same
+ // argument with different escaping style, e.g.:
+ // php -r 'require '\''vendor/autoload.php'\''
+ currentPart = parts.pop()! + char;
+ } else {
+ currentPart += char;
+ }
+ } else if (mode === MODE_IN_QUOTE) {
+ if (char === quote) {
+ mode = MODE_NORMAL;
+ quote = '';
+ } else {
+ currentPart += char;
+ }
+ }
+ }
+ if (currentPart) {
+ parts.push(currentPart);
+ }
+ return parts;
+}
diff --git a/packages/php-wasm/web/public/kitchen-sink/8_2_10/php_8_2.wasm b/packages/php-wasm/web/public/kitchen-sink/8_2_10/php_8_2.wasm
index 2b7262a26b..8a36d3e190 100755
Binary files a/packages/php-wasm/web/public/kitchen-sink/8_2_10/php_8_2.wasm and b/packages/php-wasm/web/public/kitchen-sink/8_2_10/php_8_2.wasm differ
diff --git a/packages/php-wasm/web/public/kitchen-sink/php_8_2.js b/packages/php-wasm/web/public/kitchen-sink/php_8_2.js
index e8eedf4e01..ea364f691e 100644
--- a/packages/php-wasm/web/public/kitchen-sink/php_8_2.js
+++ b/packages/php-wasm/web/public/kitchen-sink/php_8_2.js
@@ -1,6 +1,6 @@
import dependencyFilename from './8_2_10/php_8_2.wasm';
export { dependencyFilename };
-export const dependenciesTotalSize = 10101034;
+export const dependenciesTotalSize = 11982400;
export function init(RuntimeName, PHPLoader) {
/**
* Overrides Emscripten's default ExitStatus object which gets
@@ -38,9 +38,8810 @@ export function init(RuntimeName, PHPLoader) {
}
// The rest of the code comes from the built php.js file and esm-suffix.js
-var Module=typeof PHPLoader!="undefined"?PHPLoader:{};var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var ENVIRONMENT_IS_WEB=RuntimeName==="WEB";var ENVIRONMENT_IS_WORKER=RuntimeName==="WORKER";var ENVIRONMENT_IS_NODE=RuntimeName==="NODE";var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=(url,onload,onerror)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}setWindowTitle=title=>document.title=title}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.error.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime=Module["noExitRuntime"]||false;if(typeof WebAssembly!="object"){abort("no native wasm support detected")}var wasmMemory;var ABORT=false;var EXITSTATUS;function assert(condition,text){if(!condition){abort(text)}}var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);Module["HEAPF64"]=HEAPF64=new Float64Array(b)}var wasmTable;var __ATPRERUN__=[];var __ATINIT__=[];var __ATEXIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;var runtimeKeepaliveCounter=0;function keepRuntimeAlive(){return noExitRuntime||runtimeKeepaliveCounter>0}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;if(!Module["noFSInit"]&&!FS.init.initialized)FS.init();FS.ignorePermissions=false;TTY.init();SOCKFS.root=FS.mount(SOCKFS,{},null);PIPEFS.root=FS.mount(PIPEFS,{},null);callRuntimeCallbacks(__ATINIT__)}function exitRuntime(){___funcs_on_exit();callRuntimeCallbacks(__ATEXIT__);FS.quit();TTY.shutdown();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 addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;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()}}}function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what="Aborted("+what+")";err(what);ABORT=true;EXITSTATUS=1;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);throw e}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return filename.startsWith(dataURIPrefix)}var wasmBinaryFile;wasmBinaryFile=dependencyFilename;if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}function getBinaryPromise(binaryFile){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)){if(typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then((response=>{if(!response["ok"]){throw"failed to load wasm binary file at '"+binaryFile+"'"}return response["arrayBuffer"]()})).catch((()=>getBinarySync(binaryFile)))}}return Promise.resolve().then((()=>getBinarySync(binaryFile)))}function instantiateArrayBuffer(binaryFile,imports,receiver){return getBinaryPromise(binaryFile).then((binary=>WebAssembly.instantiate(binary,imports))).then((instance=>instance)).then(receiver,(reason=>{err("failed to asynchronously prepare wasm: "+reason);abort(reason)}))}function instantiateAsync(binary,binaryFile,imports,callback){if(!binary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(binaryFile)&&typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then((response=>{var result=WebAssembly.instantiateStreaming(response,imports);return result.then(callback,(function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(binaryFile,imports,callback)}))}))}return instantiateArrayBuffer(binaryFile,imports,callback)}function createWasm(){var info={"a":wasmImports};function receiveInstance(instance,module){var exports=instance.exports;exports=Asyncify.instrumentWasmExports(exports);Module["asm"]=exports;wasmMemory=Module["asm"]["ab"];updateMemoryViews();wasmTable=Module["asm"]["eb"];addOnInit(Module["asm"]["bb"]);removeRunDependency("wasm-instantiate");return exports}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){receiveInstance(result["instance"])}if(Module["instantiateWasm"]){try{return Module["instantiateWasm"](info,receiveInstance)}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync(wasmBinary,wasmBinaryFile,info,receiveInstantiationResult);return{}}var tempDouble;var tempI64;function ExitStatus(status){this.name="ExitStatus";this.message=`Program terminated with exit(${status})`;this.status=status}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var UTF8Decoder=typeof TextDecoder!="undefined"?new TextDecoder("utf8"):undefined;var UTF8ArrayToString=(heapOrArray,idx,maxBytesToRead)=>{var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};var UTF8ToString=(ptr,maxBytesToRead)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):"";Module["UTF8ToString"]=UTF8ToString;var ___assert_fail=(condition,filename,line,func)=>{abort(`Assertion failed: ${UTF8ToString(condition)}, at: `+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])};var ___call_sighandler=(fp,sig)=>(a1=>dynCall_vi.apply(null,[fp,a1]))(sig);var PATH={isAbs:path=>path.charAt(0)==="/",splitPath:filename=>{var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:(parts,allowAboveRoot)=>{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(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:path=>{var isAbsolute=PATH.isAbs(path),trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter((p=>!!p)),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:path=>{var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:path=>{if(path==="/")return"/";path=PATH.normalize(path);path=path.replace(/\/$/,"");var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},join:function(){var paths=Array.prototype.slice.call(arguments);return PATH.normalize(paths.join("/"))},join2:(l,r)=>PATH.normalize(l+"/"+r)};var initRandomFill=()=>{if(typeof crypto=="object"&&typeof crypto["getRandomValues"]=="function"){return view=>crypto.getRandomValues(view)}else abort("initRandomDevice")};var randomFill=view=>(randomFill=initRandomFill())(view);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();if(typeof path!="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=PATH.isAbs(path)}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter((p=>!!p)),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."},relative:(from,to)=>{from=PATH_FS.resolve(from).substr(1);to=PATH_FS.resolve(to).substr(1);function trim(arr){var start=0;for(;start=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{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};Module["lengthBytesUTF8"]=lengthBytesUTF8;var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx};function 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}var FS_stdin_getChar=()=>{if(!FS_stdin_getChar_buffer.length){var result=null;if(typeof window!="undefined"&&typeof window.prompt=="function"){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else if(typeof readline=="function"){result=readline();if(result!==null){result+="\n"}}if(!result){return null}FS_stdin_getChar_buffer=intArrayFromString(result,true)}return FS_stdin_getChar_buffer.shift()};var TTY={ttys:[],init:function(){},shutdown:function(){},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){stream.tty.ops.fsync(stream.tty)},fsync:function(stream){stream.tty.ops.fsync(stream.tty)},read:function(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.get_char){throw new FS.ErrnoError(60)}var bytesRead=0;for(var i=0;i0){out(UTF8ArrayToString(tty.output,0));tty.output=[]}},ioctl_tcgets:function(tty){return{c_iflag:25856,c_oflag:5,c_cflag:191,c_lflag:35387,c_cc:[3,28,127,21,4,0,1,0,17,19,26,0,18,15,23,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}},ioctl_tcsets:function(tty,optional_actions,data){return 0},ioctl_tiocgwinsz:function(tty){return[24,80]}},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)}},fsync:function(tty){if(tty.output&&tty.output.length>0){err(UTF8ArrayToString(tty.output,0));tty.output=[]}}}};var zeroMemory=(address,size)=>{HEAPU8.fill(0,address,address+size);return address};var alignMemory=(size,alignment)=>Math.ceil(size/alignment)*alignment;var mmapAlloc=size=>{size=alignMemory(size,65536);var ptr=_emscripten_builtin_memalign(65536,size);if(!ptr)return 0;return zeroMemory(ptr,size)};var MEMFS={ops_table:null,mount(mount){return MEMFS.createNode(null,"/",16384|511,0)},createNode(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){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;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();if(parent){parent.contents[name]=node;parent.timestamp=node.timestamp}return node},getFileDataAsTypedArray(node){if(!node.contents)return new Uint8Array(0);if(node.contents.subarray)return node.contents.subarray(0,node.usedBytes);return new Uint8Array(node.contents)},expandFileStorage(node,newCapacity){var prevCapacity=node.contents?node.contents.length:0;if(prevCapacity>=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity>>0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0)},resizeFileStorage(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0}else{var oldContents=node.contents;node.contents=new Uint8Array(newSize);if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize}},node_ops:{getattr(node){var attr={};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);attr.blksize=4096;attr.blocks=Math.ceil(attr.size/attr.blksize);return attr},setattr(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(parent,name){throw FS.genericErrors[44]},mknod(parent,name,mode,dev){return MEMFS.createNode(parent,name,mode,dev)},rename(old_node,new_dir,new_name){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)}}}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(parent,name){delete parent.contents[name];parent.timestamp=Date.now()},rmdir(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(node){var entries=[".",".."];for(var key in node.contents){if(!node.contents.hasOwnProperty(key)){continue}entries.push(key)}return entries},symlink(parent,newname,oldpath){var node=MEMFS.createNode(parent,newname,511|40960,0);node.link=oldpath;return node},readlink(node){if(!FS.isLink(node.mode)){throw new FS.ErrnoError(28)}return node.link}},stream_ops:{read(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){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i0||position+length{var dep=!noRunDep?getUniqueRunDependency(`al ${url}`):"";readAsync(url,(arrayBuffer=>{assert(arrayBuffer,`Loading data file "${url}" failed (no arrayBuffer).`);onload(new Uint8Array(arrayBuffer));if(dep)removeRunDependency(dep)}),(event=>{if(onerror){onerror()}else{throw`Loading data file "${url}" failed.`}}));if(dep)addRunDependency(dep)};var preloadPlugins=Module["preloadPlugins"]||[];function FS_handledByPreloadPlugin(byteArray,fullname,finish,onerror){if(typeof Browser!="undefined")Browser.init();var handled=false;preloadPlugins.forEach((function(plugin){if(handled)return;if(plugin["canHandle"](fullname)){plugin["handle"](byteArray,fullname,finish,onerror);handled=true}}));return handled}function FS_createPreloadedFile(parent,name,url,canRead,canWrite,onload,onerror,dontCreateFile,canOwn,preFinish){var fullname=name?PATH_FS.resolve(PATH.join2(parent,name)):parent;var dep=getUniqueRunDependency(`cp ${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)}if(FS_handledByPreloadPlugin(byteArray,fullname,finish,(()=>{if(onerror)onerror();removeRunDependency(dep)}))){return}finish(byteArray)}addRunDependency(dep);if(typeof url=="string"){asyncLoad(url,(byteArray=>processData(byteArray)),onerror)}else{processData(url)}}function FS_modeStringToFlags(str){var flagModes={"r":0,"r+":2,"w":512|64|1,"w+":512|64|2,"a":1024|64|1,"a+":1024|64|2};var flags=flagModes[str];if(typeof flags=="undefined"){throw new Error(`Unknown file open mode: ${str}`)}return flags}function FS_getMode(canRead,canWrite){var mode=0;if(canRead)mode|=292|73;if(canWrite)mode|=146;return mode}var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,ErrnoError:null,genericErrors:{},filesystems:null,syncFSRequests:0,lookupPath:(path,opts={})=>{path=PATH_FS.resolve(path);if(!path)return{path:"",node:null};var defaults={follow_mount:true,recurse_count:0};opts=Object.assign(defaults,opts);if(opts.recurse_count>8){throw new FS.ErrnoError(32)}var parts=path.split("/").filter((p=>!!p));var current=FS.root;var current_path="/";for(var i=0;i40){throw new FS.ErrnoError(32)}}}}return{path:current_path,node:current}},getPath: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:(parentid,name)=>{var hash=0;for(var i=0;i>>0)%FS.nameTable.length},hashAddNode:node=>{var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode: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:(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}}return FS.lookup(parent,name)},createNode:(parent,name,mode,rdev)=>{var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode:node=>{FS.hashRemoveNode(node)},isRoot:node=>node===node.parent,isMountpoint:node=>!!node.mounted,isFile:mode=>(mode&61440)===32768,isDir:mode=>(mode&61440)===16384,isLink:mode=>(mode&61440)===40960,isChrdev:mode=>(mode&61440)===8192,isBlkdev:mode=>(mode&61440)===24576,isFIFO:mode=>(mode&61440)===4096,isSocket:mode=>(mode&49152)===49152,flagsToPermissionString:flag=>{var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms},nodePermissions:(node,perms)=>{if(FS.ignorePermissions){return 0}if(perms.includes("r")&&!(node.mode&292)){return 2}else if(perms.includes("w")&&!(node.mode&146)){return 2}else if(perms.includes("x")&&!(node.mode&73)){return 2}return 0},mayLookup:dir=>{var errCode=FS.nodePermissions(dir,"x");if(errCode)return errCode;if(!dir.node_ops.lookup)return 2;return 0},mayCreate:(dir,name)=>{try{var node=FS.lookupNode(dir,name);return 20}catch(e){}return FS.nodePermissions(dir,"wx")},mayDelete:(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:(node,flags)=>{if(!node){return 44}if(FS.isLink(node.mode)){return 32}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!=="r"||flags&512){return 31}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))},MAX_OPEN_FDS:4096,nextfd:()=>{for(var fd=0;fd<=FS.MAX_OPEN_FDS;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(33)},getStreamChecked:fd=>{var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}return stream},getStream:fd=>FS.streams[fd],createStream:(stream,fd=-1)=>{if(!FS.FSStream){FS.FSStream=function(){this.shared={}};FS.FSStream.prototype={};Object.defineProperties(FS.FSStream.prototype,{object:{get(){return this.node},set(val){this.node=val}},isRead:{get(){return(this.flags&2097155)!==1}},isWrite:{get(){return(this.flags&2097155)!==0}},isAppend:{get(){return this.flags&1024}},flags:{get(){return this.shared.flags},set(val){this.shared.flags=val}},position:{get(){return this.shared.position},set(val){this.shared.position=val}}})}stream=Object.assign(new FS.FSStream,stream);if(fd==-1){fd=FS.nextfd()}stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream:fd=>{FS.streams[fd]=null},chrdev_stream_ops:{open:stream=>{var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;if(stream.stream_ops.open){stream.stream_ops.open(stream)}},llseek:()=>{throw new FS.ErrnoError(70)}},major:dev=>dev>>8,minor:dev=>dev&255,makedev:(ma,mi)=>ma<<8|mi,registerDevice:(dev,ops)=>{FS.devices[dev]={stream_ops:ops}},getDevice:dev=>FS.devices[dev],getMounts: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:(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)}}mounts.forEach((mount=>{if(!mount.type.syncfs){return done(null)}mount.type.syncfs(mount,populate,done)}))},mount:(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;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:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount:mountpoint=>{var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(28)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);Object.keys(FS.nameTable).forEach((hash=>{var current=FS.nameTable[hash];while(current){var next=current.name_next;if(mounts.includes(current.mount)){FS.destroyNode(current)}current=next}}));node.mounted=null;var idx=node.mount.mounts.indexOf(mount);node.mount.mounts.splice(idx,1)},lookup:(parent,name)=>parent.node_ops.lookup(parent,name),mknod:(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:(path,mode)=>{mode=mode!==undefined?mode:438;mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir:(path,mode)=>{mode=mode!==undefined?mode:511;mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree:(path,mode)=>{var dirs=path.split("/");var d="";for(var i=0;i{if(typeof dev=="undefined"){dev=mode;mode=438}mode|=8192;return FS.mknod(path,mode,dev)},symlink:(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:(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);var lookup,old_dir,new_dir;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);if(old_dir.mount!==new_dir.mount){throw new FS.ErrnoError(75)}var old_node=FS.lookupNode(old_dir,old_name);var relative=PATH_FS.relative(old_path,new_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(28)}relative=PATH_FS.relative(new_path,old_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(55)}var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(old_node===new_node){return}var isdir=FS.isDir(old_node.mode);var errCode=FS.mayDelete(old_dir,old_name,isdir);if(errCode){throw new FS.ErrnoError(errCode)}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(new_dir!==old_dir){errCode=FS.nodePermissions(old_dir,"w");if(errCode){throw new FS.ErrnoError(errCode)}}FS.hashRemoveNode(old_node);try{old_dir.node_ops.rename(old_node,new_dir,new_name)}catch(e){throw e}finally{FS.hashAddNode(old_node)}},rmdir: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)}parent.node_ops.rmdir(parent,name);FS.destroyNode(node)},readdir: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:path=>{var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,false);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.unlink){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.unlink(parent,name);FS.destroyNode(node)},readlink: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:(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:path=>FS.stat(path,true),chmod:(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:(path,mode)=>{FS.chmod(path,mode,true)},fchmod:(fd,mode)=>{var stream=FS.getStreamChecked(fd);FS.chmod(stream.node,mode)},chown:(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()})},lchown:(path,uid,gid)=>{FS.chown(path,uid,gid,true)},fchown:(fd,uid,gid)=>{var stream=FS.getStreamChecked(fd);FS.chown(stream.node,uid,gid)},truncate:(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:(fd,len)=>{var stream=FS.getStreamChecked(fd);if((stream.flags&2097155)===0){throw new FS.ErrnoError(28)}FS.truncate(stream.node,len)},utime:(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:(path,flags,mode)=>{if(path===""){throw new FS.ErrnoError(44)}flags=typeof flags=="string"?FS_modeStringToFlags(flags):flags;mode=typeof mode=="undefined"?438: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){}}var created=false;if(flags&64){if(node){if(flags&128){throw new FS.ErrnoError(20)}}else{node=FS.mknod(path,mode,0);created=true}}if(!node){throw new FS.ErrnoError(44)}if(FS.isChrdev(node.mode)){flags&=~512}if(flags&65536&&!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}if(!created){var errCode=FS.mayOpen(node,flags);if(errCode){throw new FS.ErrnoError(errCode)}}if(flags&512&&!created){FS.truncate(node,0)}flags&=~(128|512|131072);var stream=FS.createStream({node:node,path:FS.getPath(node),flags:flags,seekable:true,position:0,stream_ops:node.stream_ops,ungotten:[],error:false});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}}return stream},close:stream=>{if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(stream.getdents)stream.getdents=null;try{if(stream.stream_ops.close){stream.stream_ops.close(stream)}}catch(e){throw e}finally{FS.closeStream(stream.fd)}stream.fd=null},isClosed:stream=>stream.fd===null,llseek:(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:(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:(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){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;return bytesWritten},allocate:(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:(stream,length,position,prot,flags)=>{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,length,position,prot,flags)},msync:(stream,buffer,offset,length,mmapFlags)=>{if(!stream.stream_ops.msync){return 0}return stream.stream_ops.msync(stream,buffer,offset,length,mmapFlags)},munmap:stream=>0,ioctl:(stream,cmd,arg)=>{if(!stream.stream_ops.ioctl){throw new FS.ErrnoError(59)}return stream.stream_ops.ioctl(stream,cmd,arg)},readFile:(path,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:(path,data,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:()=>FS.currentPath,chdir: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:()=>{FS.mkdir("/tmp");FS.mkdir("/home");FS.mkdir("/home/web_user")},createDefaultDevices:()=>{FS.mkdir("/dev");FS.registerDevice(FS.makedev(1,3),{read:()=>0,write:(stream,buffer,offset,length,pos)=>length});FS.mkdev("/dev/null",FS.makedev(1,3));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));var randomBuffer=new Uint8Array(1024),randomLeft=0;var randomByte=()=>{if(randomLeft===0){randomLeft=randomFill(randomBuffer).byteLength}return randomBuffer[--randomLeft]};FS.createDevice("/dev","random",randomByte);FS.createDevice("/dev","urandom",randomByte);FS.mkdir("/dev/shm");FS.mkdir("/dev/shm/tmp")},createSpecialDirectories:()=>{FS.mkdir("/proc");var proc_self=FS.mkdir("/proc/self");FS.mkdir("/proc/self/fd");FS.mount({mount:()=>{var node=FS.createNode(proc_self,"fd",16384|511,73);node.node_ops={lookup:(parent,name)=>{var fd=+name;var stream=FS.getStreamChecked(fd);var ret={parent:null,mount:{mountpoint:"fake"},node_ops:{readlink:()=>stream.path}};ret.parent=ret;return ret}};return node}},{},"/proc/self/fd")},createStandardStreams:()=>{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")}var stdin=FS.open("/dev/stdin",0);var stdout=FS.open("/dev/stdout",1);var stderr=FS.open("/dev/stderr",1)},ensureErrnoError:()=>{if(FS.ErrnoError)return;FS.ErrnoError=function ErrnoError(errno,node){this.name="ErrnoError";this.node=node;this.setErrno=function(errno){this.errno=errno};this.setErrno(errno);this.message="FS error"};FS.ErrnoError.prototype=new Error;FS.ErrnoError.prototype.constructor=FS.ErrnoError;[44].forEach((code=>{FS.genericErrors[code]=new FS.ErrnoError(code);FS.genericErrors[code].stack=""}))},staticInit:()=>{FS.ensureErrnoError();FS.nameTable=new Array(4096);FS.mount(MEMFS,{},"/");FS.createDefaultDirectories();FS.createDefaultDevices();FS.createSpecialDirectories();FS.filesystems={"MEMFS":MEMFS}},init:(input,output,error)=>{FS.init.initialized=true;FS.ensureErrnoError();Module["stdin"]=input||Module["stdin"];Module["stdout"]=output||Module["stdout"];Module["stderr"]=error||Module["stderr"];FS.createStandardStreams()},quit:()=>{FS.init.initialized=false;_fflush(0);for(var i=0;i{var ret=FS.analyzePath(path,dontResolveLastLink);if(!ret.exists){return null}return ret.object},analyzePath:(path,dontResolveLastLink)=>{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:(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){}parent=current}return current},createFile:(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:(parent,name,data,canRead,canWrite,canOwn)=>{var path=name;if(parent){parent=typeof parent=="string"?parent:FS.getPath(parent);path=name?PATH.join2(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{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);FS.registerDevice(dev,{open:stream=>{stream.seekable=false},close:stream=>{if(output&&output.buffer&&output.buffer.length){output(10)}},read:(stream,buffer,offset,length,pos)=>{var bytesRead=0;for(var i=0;i{for(var i=0;i{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_){try{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:(parent,name,url,canRead,canWrite)=>{function LazyUint8Array(){this.lengthKnown=false;this.chunks=[]}LazyUint8Array.prototype.get=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(){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;if(!hasByteServing)chunkSize=datalength;var doXHR=(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!");var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range","bytes="+from+"-"+to);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(xhr.response||[])}return intArrayFromString(xhr.responseText||"",true)};var lazyArray=this;lazyArray.setDataGetter((chunkNum=>{var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);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){chunkSize=datalength=1;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:function(){if(!this.lengthKnown){this.cacheLength()}return this._length}},chunkSize:{get: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);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};var keys=Object.keys(node.stream_ops);keys.forEach((key=>{var fn=node.stream_ops[key];stream_ops[key]=function forceLoadLazyFile(){FS.forceLoadFile(node);return fn.apply(null,arguments)}}));function writeChunks(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);if(contents.slice){for(var i=0;i{FS.forceLoadFile(node);return writeChunks(stream,buffer,offset,length,position)};stream_ops.mmap=(stream,length,position,prot,flags)=>{FS.forceLoadFile(node);var ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}writeChunks(stream,HEAP8,ptr,length,position);return{ptr:ptr,allocated:true}};node.stream_ops=stream_ops;return node}};Module["FS"]=FS;var SYSCALLS={DEFAULT_POLLMASK:5,calculateAt:function(dirfd,path,allowEmpty){if(PATH.isAbs(path)){return path}var dir;if(dirfd===-100){dir=FS.cwd()}else{var dirstream=SYSCALLS.getStreamFromFD(dirfd);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))){return-54}throw e}HEAP32[buf>>2]=stat.dev;HEAP32[buf+4>>2]=stat.mode;HEAPU32[buf+8>>2]=stat.nlink;HEAP32[buf+12>>2]=stat.uid;HEAP32[buf+16>>2]=stat.gid;HEAP32[buf+20>>2]=stat.rdev;tempI64=[stat.size>>>0,(tempDouble=stat.size,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+24>>2]=tempI64[0],HEAP32[buf+28>>2]=tempI64[1];HEAP32[buf+32>>2]=4096;HEAP32[buf+36>>2]=stat.blocks;var atime=stat.atime.getTime();var mtime=stat.mtime.getTime();var ctime=stat.ctime.getTime();tempI64=[Math.floor(atime/1e3)>>>0,(tempDouble=Math.floor(atime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+40>>2]=tempI64[0],HEAP32[buf+44>>2]=tempI64[1];HEAPU32[buf+48>>2]=atime%1e3*1e3;tempI64=[Math.floor(mtime/1e3)>>>0,(tempDouble=Math.floor(mtime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+56>>2]=tempI64[0],HEAP32[buf+60>>2]=tempI64[1];HEAPU32[buf+64>>2]=mtime%1e3*1e3;tempI64=[Math.floor(ctime/1e3)>>>0,(tempDouble=Math.floor(ctime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+72>>2]=tempI64[0],HEAP32[buf+76>>2]=tempI64[1];HEAPU32[buf+80>>2]=ctime%1e3*1e3;tempI64=[stat.ino>>>0,(tempDouble=stat.ino,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+88>>2]=tempI64[0],HEAP32[buf+92>>2]=tempI64[1];return 0},doMsync:function(addr,stream,len,flags,offset){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}if(flags&2){return 0}var buffer=HEAPU8.slice(addr,addr+len);FS.msync(stream,buffer,offset,len,flags)},varargs:undefined,get(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr(ptr){var ret=UTF8ToString(ptr);return ret},getStreamFromFD:function(fd){var stream=FS.getStreamChecked(fd);return stream}};function ___syscall__newselect(nfds,readfds,writefds,exceptfds,timeout){try{var total=0;var srcReadLow=readfds?HEAP32[readfds>>2]:0,srcReadHigh=readfds?HEAP32[readfds+4>>2]:0;var srcWriteLow=writefds?HEAP32[writefds>>2]:0,srcWriteHigh=writefds?HEAP32[writefds+4>>2]:0;var srcExceptLow=exceptfds?HEAP32[exceptfds>>2]:0,srcExceptHigh=exceptfds?HEAP32[exceptfds+4>>2]:0;var dstReadLow=0,dstReadHigh=0;var dstWriteLow=0,dstWriteHigh=0;var dstExceptLow=0,dstExceptHigh=0;var allLow=(readfds?HEAP32[readfds>>2]:0)|(writefds?HEAP32[writefds>>2]:0)|(exceptfds?HEAP32[exceptfds>>2]:0);var allHigh=(readfds?HEAP32[readfds+4>>2]:0)|(writefds?HEAP32[writefds+4>>2]:0)|(exceptfds?HEAP32[exceptfds+4>>2]:0);var check=function(fd,low,high,val){return fd<32?low&val:high&val};for(var fd=0;fd>2]:0,tv_usec=readfds?HEAP32[timeout+8>>2]:0;timeoutInMillis=(tv_sec+tv_usec/1e6)*1e3}flags=stream.stream_ops.poll(stream,timeoutInMillis)}if(flags&1&&check(fd,srcReadLow,srcReadHigh,mask)){fd<32?dstReadLow=dstReadLow|mask:dstReadHigh=dstReadHigh|mask;total++}if(flags&4&&check(fd,srcWriteLow,srcWriteHigh,mask)){fd<32?dstWriteLow=dstWriteLow|mask:dstWriteHigh=dstWriteHigh|mask;total++}if(flags&2&&check(fd,srcExceptLow,srcExceptHigh,mask)){fd<32?dstExceptLow=dstExceptLow|mask:dstExceptHigh=dstExceptHigh|mask;total++}}if(readfds){HEAP32[readfds>>2]=dstReadLow;HEAP32[readfds+4>>2]=dstReadHigh}if(writefds){HEAP32[writefds>>2]=dstWriteLow;HEAP32[writefds+4>>2]=dstWriteHigh}if(exceptfds){HEAP32[exceptfds>>2]=dstExceptLow;HEAP32[exceptfds+4>>2]=dstExceptHigh}return total}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var SOCKFS={mount(mount){Module["websocket"]=Module["websocket"]&&"object"===typeof Module["websocket"]?Module["websocket"]:{};Module["websocket"]._callbacks={};Module["websocket"]["on"]=function(event,callback){if("function"===typeof callback){this._callbacks[event]=callback}return this};Module["websocket"].emit=function(event,param){if("function"===typeof this._callbacks[event]){this._callbacks[event].call(this,param)}};return FS.createNode(null,"/",16384|511,0)},createSocket(family,type,protocol){type&=~526336;var streaming=type==1;if(streaming&&protocol&&protocol!=6){throw new FS.ErrnoError(66)}var sock={family:family,type:type,protocol:protocol,server:null,error:null,peers:{},pending:[],recv_queue:[],sock_ops:SOCKFS.websocket_sock_ops};var name=SOCKFS.nextname();var node=FS.createNode(SOCKFS.root,name,49152,0);node.sock=sock;var stream=FS.createStream({path:name,node:node,flags:2,seekable:false,stream_ops:SOCKFS.stream_ops});sock.stream=stream;return sock},getSocket(fd){var stream=FS.getStream(fd);if(!stream||!FS.isSocket(stream.node.mode)){return null}return stream.node.sock},stream_ops:{poll(stream){var sock=stream.node.sock;return sock.sock_ops.poll(sock)},ioctl(stream,request,varargs){var sock=stream.node.sock;return sock.sock_ops.ioctl(sock,request,varargs)},read(stream,buffer,offset,length,position){var sock=stream.node.sock;var msg=sock.sock_ops.recvmsg(sock,length);if(!msg){return 0}buffer.set(msg.buffer,offset);return msg.buffer.length},write(stream,buffer,offset,length,position){var sock=stream.node.sock;return sock.sock_ops.sendmsg(sock,buffer,offset,length)},close(stream){var sock=stream.node.sock;sock.sock_ops.close(sock)}},nextname(){if(!SOCKFS.nextname.current){SOCKFS.nextname.current=0}return"socket["+SOCKFS.nextname.current+++"]"},websocket_sock_ops:{createPeer(sock,addr,port){var ws;if(typeof addr=="object"){ws=addr;addr=null;port=null}if(ws){if(ws._socket){addr=ws._socket.remoteAddress;port=ws._socket.remotePort}else{var result=/ws[s]?:\/\/([^:]+):(\d+)/.exec(ws.url);if(!result){throw new Error("WebSocket URL must be in the format ws(s)://address:port")}addr=result[1];port=parseInt(result[2],10)}}else{try{var runtimeConfig=Module["websocket"]&&"object"===typeof Module["websocket"];var url="ws:#".replace("#","//");if(runtimeConfig){if("function"===typeof Module["websocket"]["url"]) {
+// include: shell.js
+// 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 PHPLoader != 'undefined' ? PHPLoader : {};
+
+// --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 = Object.assign({}, Module);
+
+var arguments_ = [];
+var thisProgram = './this.program';
+var quit_ = (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=RuntimeName==="WEB";
+var ENVIRONMENT_IS_WORKER=RuntimeName==="WORKER";
+var ENVIRONMENT_IS_NODE=RuntimeName==="NODE";
+var ENVIRONMENT_IS_SHELL=RuntimeName==="SHELL";
+
+// `/` 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 contains a query (starting with ?) or a fragment (starting with #),
+ // they are removed because they could contain a slash.
+ if (scriptDirectory.indexOf('blob:') !== 0) {
+ scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, "").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_ = (url) => {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', url, false);
+ xhr.send(null);
+ return xhr.responseText;
+ }
+
+ if (ENVIRONMENT_IS_WORKER) {
+ readBinary = (url) => {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', url, false);
+ xhr.responseType = 'arraybuffer';
+ xhr.send(null);
+ return new Uint8Array(/** @type{!ArrayBuffer} */(xhr.response));
+ };
+ }
+
+ readAsync = (url, onload, onerror) => {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', url, true);
+ xhr.responseType = 'arraybuffer';
+ xhr.onload = () => {
+ if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // 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 = (title) => document.title = title;
+} else
+{
+}
+
+var out = Module['print'] || console.log.bind(console);
+var err = Module['printErr'] || console.error.bind(console);
+
+// Merge back in the overrides
+Object.assign(Module, moduleOverrides);
+// 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
+
+// end include: shell.js
+// include: preamble.js
+// === 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'] || false;
+
+if (typeof WebAssembly != 'object') {
+ abort('no native wasm support detected');
+}
+
+// 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) {
+ // This build was created without ASSERTIONS defined. `assert()` should not
+ // ever be called in this configuration but in case there are callers in
+ // the wild leave this simple abort() implemenation here for now.
+ abort(text);
+ }
+}
+
+// Memory management
+
+var HEAP,
+/** @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 updateMemoryViews() {
+ var b = wasmMemory.buffer;
+ Module['HEAP8'] = HEAP8 = new Int8Array(b);
+ Module['HEAP16'] = HEAP16 = new Int16Array(b);
+ Module['HEAP32'] = HEAP32 = new Int32Array(b);
+ Module['HEAPU8'] = HEAPU8 = new Uint8Array(b);
+ Module['HEAPU16'] = HEAPU16 = new Uint16Array(b);
+ Module['HEAPU32'] = HEAPU32 = new Uint32Array(b);
+ Module['HEAPF32'] = HEAPF32 = new Float32Array(b);
+ Module['HEAPF64'] = HEAPF64 = new Float64Array(b);
+}
+
+// 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 __ATEXIT__ = []; // functions called during shutdown
+var __ATPOSTRUN__ = []; // functions called after the main() is called
+
+var runtimeInitialized = false;
+
+var runtimeExited = false;
+
+var runtimeKeepaliveCounter = 0;
+
+function keepRuntimeAlive() {
+ return noExitRuntime || runtimeKeepaliveCounter > 0;
+}
+
+function preRun() {
+ if (Module['preRun']) {
+ if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']];
+ while (Module['preRun'].length) {
+ addOnPreRun(Module['preRun'].shift());
+ }
+ }
+ callRuntimeCallbacks(__ATPRERUN__);
+}
+
+function initRuntime() {
+ runtimeInitialized = true;
+
+
+if (!Module["noFSInit"] && !FS.init.initialized)
+ FS.init();
+FS.ignorePermissions = false;
+
+TTY.init();
+SOCKFS.root = FS.mount(SOCKFS, {}, null);
+PIPEFS.root = FS.mount(PIPEFS, {}, null);
+ callRuntimeCallbacks(__ATINIT__);
+}
+
+function exitRuntime() {
+ ___funcs_on_exit(); // Native atexit() functions
+ callRuntimeCallbacks(__ATEXIT__);
+ FS.quit();
+TTY.shutdown();
+ 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 addOnExit(cb) {
+ __ATEXIT__.unshift(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
+ }
+ }
+}
+
+/** @param {string|number=} what */
+function abort(what) {
+ if (Module['onAbort']) {
+ Module['onAbort'](what);
+ }
+
+ what = 'Aborted(' + what + ')';
+ // TODO(sbc): Should we remove printing and leave it up to whoever
+ // catches the exception?
+ err(what);
+
+ ABORT = true;
+ EXITSTATUS = 1;
+
+ what += '. Build with -sASSERTIONS 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.
+ // FIXME This approach does not work in Wasm EH because it currently does not assume
+ // all RuntimeErrors are from traps; it decides whether a RuntimeError is from
+ // a trap or not based on a hidden field within the object. So at the moment
+ // we don't have a way of throwing a wasm trap from JS. TODO Make a JS API that
+ // allows this in the wasm spec.
+
+ // Suppress closure compiler warning here. Closure compiler's builtin extern
+ // defintion for WebAssembly.RuntimeError claims it takes no arguments even
+ // though it can.
+ // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure gets fixed.
+ /** @suppress {checkTypes} */
+ 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;
+}
+
+// include: memoryprofiler.js
+// end include: memoryprofiler.js
+// include: URIUtils.js
+// 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) {
+ // Prefix of data URIs emitted by SINGLE_FILE and related options.
+ return filename.startsWith(dataURIPrefix);
+}
+
+// Indicates whether filename is delivered via file protocol (as opposed to http/https)
+function isFileURI(filename) {
+ return filename.startsWith('file://');
+}
+// end include: URIUtils.js
+// include: runtime_exceptions.js
+// end include: runtime_exceptions.js
+var wasmBinaryFile;
+ wasmBinaryFile = dependencyFilename;
+ if (!isDataURI(wasmBinaryFile)) {
+ wasmBinaryFile = locateFile(wasmBinaryFile);
+ }
+
+function getBinarySync(file) {
+ if (file == wasmBinaryFile && wasmBinary) {
+ return new Uint8Array(wasmBinary);
+ }
+ if (readBinary) {
+ return readBinary(file);
+ }
+ throw "both async and sync fetching of the wasm failed";
+}
+
+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'
+ ) {
+ return fetch(binaryFile, { credentials: 'same-origin' }).then((response) => {
+ if (!response['ok']) {
+ throw "failed to load wasm binary file at '" + binaryFile + "'";
+ }
+ return response['arrayBuffer']();
+ }).catch(() => getBinarySync(binaryFile));
+ }
+ }
+
+ // Otherwise, getBinarySync should be able to get it synchronously
+ return Promise.resolve().then(() => getBinarySync(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);
+
+ abort(reason);
+ });
+}
+
+function instantiateAsync(binary, binaryFile, imports, callback) {
+ if (!binary &&
+ typeof WebAssembly.instantiateStreaming == 'function' &&
+ !isDataURI(binaryFile) &&
+ typeof fetch == 'function') {
+ return fetch(binaryFile, { credentials: 'same-origin' }).then((response) => {
+ // Suppress closure warning here since the upstream definition for
+ // instantiateStreaming only allows Promise 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);
+ });
+ });
+ }
+ return instantiateArrayBuffer(binaryFile, imports, callback);
+}
+
+// Create the wasm instance.
+// Receives the wasm imports, returns the exports.
+function createWasm() {
+ // prepare imports
+ var info = {
+ 'env': wasmImports,
+ 'wasi_snapshot_preview1': wasmImports,
+ };
+ // 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;
+
+ exports = Asyncify.instrumentWasmExports(exports);
+
+ Module['asm'] = exports;
+
+ wasmMemory = Module['asm']['memory'];
+ updateMemoryViews();
+
+ wasmTable = Module['asm']['__indirect_function_table'];
+
+ addOnInit(Module['asm']['__wasm_call_ctors']);
+
+ removeRunDependency('wasm-instantiate');
+ return exports;
+ }
+ // wait for the pthread pool (if any)
+ addRunDependency('wasm-instantiate');
+
+ // Prefer streaming instantiation if available.
+ function receiveInstantiationResult(result) {
+ // 'result' is a ResultObject 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 PTHREADS-enabled path.
+ receiveInstance(result['instance']);
+ }
+
+ // 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.
+ if (Module['instantiateWasm']) {
+
+ try {
+ return Module['instantiateWasm'](info, receiveInstance);
+ } catch(e) {
+ err('Module.instantiateWasm callback failed with error: ' + e);
+ return false;
+ }
+ }
+
+ instantiateAsync(wasmBinary, wasmBinaryFile, info, receiveInstantiationResult);
+ return {}; // no exports yet; we'll fill them in later
+}
+
+// Globals used by JS i64 conversions (see makeSetValue)
+var tempDouble;
+var tempI64;
+
+// include: runtime_debug.js
+// end include: runtime_debug.js
+// === Body ===
+
+// end include: preamble.js
+
+ /** @constructor */
+ function ExitStatus(status) {
+ this.name = 'ExitStatus';
+ this.message = `Program terminated with exit(${status})`;
+ this.status = status;
+ }
+
+ var callRuntimeCallbacks = (callbacks) => {
+ while (callbacks.length > 0) {
+ // Pass the module as the first argument.
+ callbacks.shift()(Module);
+ }
+ };
+
+
+ /**
+ * @param {number} ptr
+ * @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': 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}`);
+ }
+ }
+
+
+ /**
+ * @param {number} ptr
+ * @param {number} value
+ * @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': 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}`);
+ }
+ }
+
+ 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}
+ */
+ var 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 {
+ 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}
+ */
+ var UTF8ToString = (ptr, maxBytesToRead) => {
+ return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : '';
+ };
+ Module['UTF8ToString'] = UTF8ToString;
+ var ___assert_fail = (condition, filename, line, func) => {
+ abort(`Assertion failed: ${UTF8ToString(condition)}, at: ` + [filename ? UTF8ToString(filename) : 'unknown filename', line, func ? UTF8ToString(func) : 'unknown function']);
+ };
+
+ var ___call_sighandler = (fp, sig) => ((a1) => dynCall_vi.apply(null, [fp, a1]))(sig);
+
+ var PATH = {
+ isAbs:(path) => path.charAt(0) === '/',
+ splitPath:(filename) => {
+ var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
+ return splitPathRe.exec(filename).slice(1);
+ },
+ normalizeArray:(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:(path) => {
+ var isAbsolute = PATH.isAbs(path),
+ trailingSlash = path.substr(-1) === '/';
+ // Normalize the path
+ path = PATH.normalizeArray(path.split('/').filter((p) => !!p), !isAbsolute).join('/');
+ if (!path && !isAbsolute) {
+ path = '.';
+ }
+ if (path && trailingSlash) {
+ path += '/';
+ }
+ return (isAbsolute ? '/' : '') + path;
+ },
+ dirname:(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:(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);
+ },
+ join:function() {
+ var paths = Array.prototype.slice.call(arguments);
+ return PATH.normalize(paths.join('/'));
+ },
+ join2:(l, r) => {
+ return PATH.normalize(l + '/' + r);
+ },
+ };
+
+ var initRandomFill = () => {
+ if (typeof crypto == 'object' && typeof crypto['getRandomValues'] == 'function') {
+ // for modern web browsers
+ return (view) => crypto.getRandomValues(view);
+ } else
+ // we couldn't find a proper implementation, as Math.random() is not suitable for /dev/random, see emscripten-core/emscripten/pull/7096
+ abort("initRandomDevice");
+ };
+ var randomFill = (view) => {
+ // Lazily init on the first invocation.
+ return (randomFill = initRandomFill())(view);
+ };
+
+
+
+ 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.isAbs(path);
+ }
+ // 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((p) => !!p), !resolvedAbsolute).join('/');
+ return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
+ },
+ relative:(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 FS_stdin_getChar_buffer = [];
+
+ var 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;
+ };
+ Module['lengthBytesUTF8'] = lengthBytesUTF8;
+
+ var 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;
+ 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;
+ };
+ /** @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;
+ }
+ var FS_stdin_getChar = () => {
+ if (!FS_stdin_getChar_buffer.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;
+ }
+ FS_stdin_getChar_buffer = intArrayFromString(result, true);
+ }
+ return FS_stdin_getChar_buffer.shift();
+ };
+ 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.fsync(stream.tty);
+ },
+ fsync:function(stream) {
+ stream.tty.ops.fsync(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) {
+ return FS_stdin_getChar();
+ },
+ 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.
+ }
+ },
+ fsync:function(tty) {
+ if (tty.output && tty.output.length > 0) {
+ out(UTF8ArrayToString(tty.output, 0));
+ tty.output = [];
+ }
+ },
+ ioctl_tcgets:function(tty) {
+ // typical setting
+ return {
+ c_iflag: 25856,
+ c_oflag: 5,
+ c_cflag: 191,
+ c_lflag: 35387,
+ c_cc: [
+ 0x03, 0x1c, 0x7f, 0x15, 0x04, 0x00, 0x01, 0x00, 0x11, 0x13, 0x1a, 0x00,
+ 0x12, 0x0f, 0x17, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ ]
+ };
+ },
+ ioctl_tcsets:function(tty, optional_actions, data) {
+ // currently just ignore
+ return 0;
+ },
+ ioctl_tiocgwinsz:function(tty) {
+ return [24, 80];
+ },
+ },
+ 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);
+ }
+ },
+ fsync:function(tty) {
+ if (tty.output && tty.output.length > 0) {
+ err(UTF8ArrayToString(tty.output, 0));
+ tty.output = [];
+ }
+ },
+ },
+ };
+
+
+ var zeroMemory = (address, size) => {
+ HEAPU8.fill(0, address, address + size);
+ return address;
+ };
+
+ var alignMemory = (size, alignment) => {
+ return Math.ceil(size / alignment) * alignment;
+ };
+ var mmapAlloc = (size) => {
+ size = alignMemory(size, 65536);
+ var ptr = _emscripten_builtin_memalign(65536, size);
+ if (!ptr) return 0;
+ return zeroMemory(ptr, size);
+ };
+ var MEMFS = {
+ ops_table:null,
+ mount(mount) {
+ return MEMFS.createNode(null, '/', 16384 | 511 /* 0777 */, 0);
+ },
+ createNode(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(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(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(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(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(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(parent, name) {
+ throw FS.genericErrors[44];
+ },
+ mknod(parent, name, mode, dev) {
+ return MEMFS.createNode(parent, name, mode, dev);
+ },
+ rename(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(parent, name) {
+ delete parent.contents[name];
+ parent.timestamp = Date.now();
+ },
+ rmdir(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(node) {
+ var entries = ['.', '..'];
+ for (var key in node.contents) {
+ if (!node.contents.hasOwnProperty(key)) {
+ continue;
+ }
+ entries.push(key);
+ }
+ return entries;
+ },
+ symlink(parent, newname, oldpath) {
+ var node = MEMFS.createNode(parent, newname, 511 /* 0777 */ | 40960, 0);
+ node.link = oldpath;
+ return node;
+ },
+ readlink(node) {
+ if (!FS.isLink(node.mode)) {
+ throw new FS.ErrnoError(28);
+ }
+ return node.link;
+ },
+ },
+ stream_ops:{
+ read(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(stream, buffer, offset, length, position, canOwn) {
+ // If the buffer is located in main memory (HEAP), and if
+ // memory can grow, we can't hold on to references of the
+ // memory buffer, as they may get invalidated. That means we
+ // need to do copy its contents.
+ if (buffer.buffer === HEAP8.buffer) {
+ canOwn = false;
+ }
+
+ 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(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(stream, offset, length) {
+ MEMFS.expandFileStorage(stream.node, offset + length);
+ stream.node.usedBytes = Math.max(stream.node.usedBytes, offset + length);
+ },
+ mmap(stream, length, position, prot, flags) {
+ 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 === HEAP8.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, allocated };
+ },
+ msync(stream, buffer, offset, length, mmapFlags) {
+ MEMFS.stream_ops.write(stream, buffer, 0, length, offset, false);
+ // should we check if bytesWritten and length are the same?
+ return 0;
+ },
+ },
+ };
+
+ /** @param {boolean=} noRunDep */
+ var asyncLoad = (url, onload, onerror, noRunDep) => {
+ var dep = !noRunDep ? getUniqueRunDependency(`al ${url}`) : '';
+ readAsync(url, (arrayBuffer) => {
+ assert(arrayBuffer, `Loading data file "${url}" failed (no arrayBuffer).`);
+ onload(new Uint8Array(arrayBuffer));
+ if (dep) removeRunDependency(dep);
+ }, (event) => {
+ if (onerror) {
+ onerror();
+ } else {
+ throw `Loading data file "${url}" failed.`;
+ }
+ });
+ if (dep) addRunDependency(dep);
+ };
+
+
+ var preloadPlugins = Module['preloadPlugins'] || [];
+ function FS_handledByPreloadPlugin(byteArray, fullname, finish, onerror) {
+ // Ensure plugins are ready.
+ if (typeof Browser != 'undefined') Browser.init();
+
+ var handled = false;
+ preloadPlugins.forEach(function(plugin) {
+ if (handled) return;
+ if (plugin['canHandle'](fullname)) {
+ plugin['handle'](byteArray, fullname, finish, onerror);
+ handled = true;
+ }
+ });
+ return handled;
+ }
+ function FS_createPreloadedFile(parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) {
+ // 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);
+ }
+ if (FS_handledByPreloadPlugin(byteArray, fullname, finish, () => {
+ if (onerror) onerror();
+ removeRunDependency(dep);
+ })) {
+ return;
+ }
+ finish(byteArray);
+ }
+ addRunDependency(dep);
+ if (typeof url == 'string') {
+ asyncLoad(url, (byteArray) => processData(byteArray), onerror);
+ } else {
+ processData(url);
+ }
+ }
+
+ function FS_modeStringToFlags(str) {
+ var flagModes = {
+ 'r': 0,
+ 'r+': 2,
+ 'w': 512 | 64 | 1,
+ 'w+': 512 | 64 | 2,
+ 'a': 1024 | 64 | 1,
+ 'a+': 1024 | 64 | 2,
+ };
+ var flags = flagModes[str];
+ if (typeof flags == 'undefined') {
+ throw new Error(`Unknown file open mode: ${str}`);
+ }
+ return flags;
+ }
+
+ function FS_getMode(canRead, canWrite) {
+ var mode = 0;
+ if (canRead) mode |= 292 | 73;
+ if (canWrite) mode |= 146;
+ return mode;
+ }
+
+
+
+ var FS = {
+ root:null,
+ mounts:[],
+ devices:{
+ },
+ streams:[],
+ nextInode:1,
+ nameTable:null,
+ currentPath:"/",
+ initialized:false,
+ ignorePermissions:true,
+ ErrnoError:null,
+ genericErrors:{
+ },
+ filesystems:null,
+ syncFSRequests:0,
+ lookupPath:(path, opts = {}) => {
+ path = PATH_FS.resolve(path);
+
+ if (!path) return { path: '', node: null };
+
+ var defaults = {
+ follow_mount: true,
+ recurse_count: 0
+ };
+ opts = Object.assign(defaults, opts)
+
+ if (opts.recurse_count > 8) { // max recursive lookup of 8
+ throw new FS.ErrnoError(32);
+ }
+
+ // split the absolute path
+ var parts = path.split('/').filter((p) => !!p);
+
+ // 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 + 1 });
+ 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:(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:(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:(node) => {
+ var hash = FS.hashName(node.parent.id, node.name);
+ node.name_next = FS.nameTable[hash];
+ FS.nameTable[hash] = node;
+ },
+ hashRemoveNode:(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:(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:(parent, name, mode, rdev) => {
+ var node = new FS.FSNode(parent, name, mode, rdev);
+
+ FS.hashAddNode(node);
+
+ return node;
+ },
+ destroyNode:(node) => {
+ FS.hashRemoveNode(node);
+ },
+ isRoot:(node) => {
+ return node === node.parent;
+ },
+ isMountpoint:(node) => {
+ return !!node.mounted;
+ },
+ isFile:(mode) => {
+ return (mode & 61440) === 32768;
+ },
+ isDir:(mode) => {
+ return (mode & 61440) === 16384;
+ },
+ isLink:(mode) => {
+ return (mode & 61440) === 40960;
+ },
+ isChrdev:(mode) => {
+ return (mode & 61440) === 8192;
+ },
+ isBlkdev:(mode) => {
+ return (mode & 61440) === 24576;
+ },
+ isFIFO:(mode) => {
+ return (mode & 61440) === 4096;
+ },
+ isSocket:(mode) => {
+ return (mode & 49152) === 49152;
+ },
+ flagsToPermissionString:(flag) => {
+ var perms = ['r', 'w', 'rw'][flag & 3];
+ if ((flag & 512)) {
+ perms += 'w';
+ }
+ return perms;
+ },
+ nodePermissions:(node, perms) => {
+ if (FS.ignorePermissions) {
+ return 0;
+ }
+ // return 0 if any user, group or owner bits are set.
+ if (perms.includes('r') && !(node.mode & 292)) {
+ return 2;
+ } else if (perms.includes('w') && !(node.mode & 146)) {
+ return 2;
+ } else if (perms.includes('x') && !(node.mode & 73)) {
+ return 2;
+ }
+ return 0;
+ },
+ mayLookup:(dir) => {
+ var errCode = FS.nodePermissions(dir, 'x');
+ if (errCode) return errCode;
+ if (!dir.node_ops.lookup) return 2;
+ return 0;
+ },
+ mayCreate:(dir, name) => {
+ try {
+ var node = FS.lookupNode(dir, name);
+ return 20;
+ } catch (e) {
+ }
+ return FS.nodePermissions(dir, 'wx');
+ },
+ mayDelete:(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:(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:() => {
+ for (var fd = 0; fd <= FS.MAX_OPEN_FDS; fd++) {
+ if (!FS.streams[fd]) {
+ return fd;
+ }
+ }
+ throw new FS.ErrnoError(33);
+ },
+ getStreamChecked:(fd) => {
+ var stream = FS.getStream(fd);
+ if (!stream) {
+ throw new FS.ErrnoError(8);
+ }
+ return stream;
+ },
+ getStream:(fd) => FS.streams[fd],
+ createStream:(stream, fd = -1) => {
+ if (!FS.FSStream) {
+ FS.FSStream = /** @constructor */ function() {
+ this.shared = { };
+ };
+ FS.FSStream.prototype = {};
+ Object.defineProperties(FS.FSStream.prototype, {
+ object: {
+ /** @this {FS.FSStream} */
+ get() { return this.node; },
+ /** @this {FS.FSStream} */
+ set(val) { this.node = val; }
+ },
+ isRead: {
+ /** @this {FS.FSStream} */
+ get() { return (this.flags & 2097155) !== 1; }
+ },
+ isWrite: {
+ /** @this {FS.FSStream} */
+ get() { return (this.flags & 2097155) !== 0; }
+ },
+ isAppend: {
+ /** @this {FS.FSStream} */
+ get() { return (this.flags & 1024); }
+ },
+ flags: {
+ /** @this {FS.FSStream} */
+ get() { return this.shared.flags; },
+ /** @this {FS.FSStream} */
+ set(val) { this.shared.flags = val; },
+ },
+ position : {
+ /** @this {FS.FSStream} */
+ get() { return this.shared.position; },
+ /** @this {FS.FSStream} */
+ set(val) { this.shared.position = val; },
+ },
+ });
+ }
+ // clone it, so we can return an instance of FSStream
+ stream = Object.assign(new FS.FSStream(), stream);
+ if (fd == -1) {
+ fd = FS.nextfd();
+ }
+ stream.fd = fd;
+ FS.streams[fd] = stream;
+ return stream;
+ },
+ closeStream:(fd) => {
+ FS.streams[fd] = null;
+ },
+ chrdev_stream_ops:{
+ open:(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:() => {
+ throw new FS.ErrnoError(70);
+ },
+ },
+ major:(dev) => ((dev) >> 8),
+ minor:(dev) => ((dev) & 0xff),
+ makedev:(ma, mi) => ((ma) << 8 | (mi)),
+ registerDevice:(dev, ops) => {
+ FS.devices[dev] = { stream_ops: ops };
+ },
+ getDevice:(dev) => FS.devices[dev],
+ getMounts:(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:(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((mount) => {
+ if (!mount.type.syncfs) {
+ return done(null);
+ }
+ mount.type.syncfs(mount, populate, done);
+ });
+ },
+ mount:(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,
+ opts,
+ 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:(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((hash) => {
+ var current = FS.nameTable[hash];
+
+ while (current) {
+ var next = current.name_next;
+
+ if (mounts.includes(current.mount)) {
+ 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:(parent, name) => {
+ return parent.node_ops.lookup(parent, name);
+ },
+ mknod:(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:(path, mode) => {
+ mode = mode !== undefined ? mode : 438 /* 0666 */;
+ mode &= 4095;
+ mode |= 32768;
+ return FS.mknod(path, mode, 0);
+ },
+ mkdir:(path, mode) => {
+ mode = mode !== undefined ? mode : 511 /* 0777 */;
+ mode &= 511 | 512;
+ mode |= 16384;
+ return FS.mknod(path, mode, 0);
+ },
+ mkdirTree:(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:(path, mode, dev) => {
+ if (typeof dev == 'undefined') {
+ dev = mode;
+ mode = 438 /* 0666 */;
+ }
+ mode |= 8192;
+ return FS.mknod(path, mode, dev);
+ },
+ symlink:(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:(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);
+ }
+ }
+ // 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);
+ }
+ },
+ rmdir:(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);
+ }
+ parent.node_ops.rmdir(parent, name);
+ FS.destroyNode(node);
+ },
+ readdir:(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:(path) => {
+ var lookup = FS.lookupPath(path, { parent: true });
+ var parent = lookup.node;
+ if (!parent) {
+ throw new FS.ErrnoError(44);
+ }
+ 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);
+ }
+ parent.node_ops.unlink(parent, name);
+ FS.destroyNode(node);
+ },
+ readlink:(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:(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:(path) => {
+ return FS.stat(path, true);
+ },
+ chmod:(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:(path, mode) => {
+ FS.chmod(path, mode, true);
+ },
+ fchmod:(fd, mode) => {
+ var stream = FS.getStreamChecked(fd);
+ FS.chmod(stream.node, mode);
+ },
+ chown:(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:(path, uid, gid) => {
+ FS.chown(path, uid, gid, true);
+ },
+ fchown:(fd, uid, gid) => {
+ var stream = FS.getStreamChecked(fd);
+ FS.chown(stream.node, uid, gid);
+ },
+ truncate:(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:(fd, len) => {
+ var stream = FS.getStreamChecked(fd);
+ if ((stream.flags & 2097155) === 0) {
+ throw new FS.ErrnoError(28);
+ }
+ FS.truncate(stream.node, len);
+ },
+ utime:(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:(path, flags, mode) => {
+ 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) && !created) {
+ 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,
+ path: FS.getPath(node), // we want the absolute path to the node
+ flags,
+ seekable: true,
+ position: 0,
+ stream_ops: node.stream_ops,
+ // used by the file family libc calls (fopen, fwrite, ferror, etc.)
+ ungotten: [],
+ error: false
+ });
+ // 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;
+ }
+ }
+ return stream;
+ },
+ close:(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:(stream) => {
+ return stream.fd === null;
+ },
+ llseek:(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:(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:(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;
+ return bytesWritten;
+ },
+ allocate:(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:(stream, 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, length, position, prot, flags);
+ },
+ msync:(stream, buffer, offset, length, mmapFlags) => {
+ if (!stream.stream_ops.msync) {
+ return 0;
+ }
+ return stream.stream_ops.msync(stream, buffer, offset, length, mmapFlags);
+ },
+ munmap:(stream) => 0,
+ ioctl:(stream, cmd, arg) => {
+ if (!stream.stream_ops.ioctl) {
+ throw new FS.ErrnoError(59);
+ }
+ return stream.stream_ops.ioctl(stream, cmd, arg);
+ },
+ readFile:(path, 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:(path, data, 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:() => FS.currentPath,
+ chdir:(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:() => {
+ FS.mkdir('/tmp');
+ FS.mkdir('/home');
+ FS.mkdir('/home/web_user');
+ },
+ createDefaultDevices:() => {
+ // create /dev
+ FS.mkdir('/dev');
+ // setup /dev/null
+ FS.registerDevice(FS.makedev(1, 3), {
+ read: () => 0,
+ write: (stream, buffer, offset, length, pos) => 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
+ // use a buffer to avoid overhead of individual crypto calls per byte
+ var randomBuffer = new Uint8Array(1024), randomLeft = 0;
+ var randomByte = () => {
+ if (randomLeft === 0) {
+ randomLeft = randomFill(randomBuffer).byteLength;
+ }
+ return randomBuffer[--randomLeft];
+ };
+ FS.createDevice('/dev', 'random', randomByte);
+ FS.createDevice('/dev', 'urandom', randomByte);
+ // 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:() => {
+ // 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: () => {
+ var node = FS.createNode(proc_self, 'fd', 16384 | 511 /* 0777 */, 73);
+ node.node_ops = {
+ lookup: (parent, name) => {
+ var fd = +name;
+ var stream = FS.getStreamChecked(fd);
+ var ret = {
+ parent: null,
+ mount: { mountpoint: 'fake' },
+ node_ops: { readlink: () => stream.path },
+ };
+ ret.parent = ret; // make it look like a simple root node
+ return ret;
+ }
+ };
+ return node;
+ }
+ }, {}, '/proc/self/fd');
+ },
+ createStandardStreams:() => {
+ // 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:() => {
+ if (FS.ErrnoError) return;
+ FS.ErrnoError = /** @this{Object} */ function ErrnoError(errno, node) {
+ // We set the `name` property to be able to identify `FS.ErrnoError`
+ // - the `name` is a standard ECMA-262 property of error objects. Kind of good to have it anyway.
+ // - when using PROXYFS, an error can come from an underlying FS
+ // as different FS objects have their own FS.ErrnoError each,
+ // the test `err instanceof FS.ErrnoError` won't detect an error coming from another filesystem, causing bugs.
+ // we'll use the reliable test `err.name == "ErrnoError"` instead
+ this.name = 'ErrnoError';
+ 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((code) => {
+ FS.genericErrors[code] = new FS.ErrnoError(code);
+ FS.genericErrors[code].stack = '';
+ });
+ },
+ staticInit:() => {
+ FS.ensureErrnoError();
+
+ FS.nameTable = new Array(4096);
+
+ FS.mount(MEMFS, {}, '/');
+
+ FS.createDefaultDirectories();
+ FS.createDefaultDevices();
+ FS.createSpecialDirectories();
+
+ FS.filesystems = {
+ 'MEMFS': MEMFS,
+ };
+ },
+ init:(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:() => {
+ FS.init.initialized = false;
+ // force-flush all streams, so we get musl std streams printed out
+ _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);
+ }
+ },
+ findObject:(path, dontResolveLastLink) => {
+ var ret = FS.analyzePath(path, dontResolveLastLink);
+ if (!ret.exists) {
+ return null;
+ }
+ return ret.object;
+ },
+ analyzePath:(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:(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:(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:(parent, name, data, canRead, canWrite, canOwn) => {
+ var path = name;
+ if (parent) {
+ parent = typeof parent == 'string' ? parent : FS.getPath(parent);
+ path = name ? PATH.join2(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:(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: (stream) => {
+ stream.seekable = false;
+ },
+ close: (stream) => {
+ // flush any pending line data
+ if (output && output.buffer && output.buffer.length) {
+ output(10);
+ }
+ },
+ read: (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: (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:(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:(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 = (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.
+ 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 || []));
+ }
+ return intArrayFromString(xhr.responseText || '', true);
+ };
+ var lazyArray = this;
+ lazyArray.setDataGetter((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((key) => {
+ var fn = node.stream_ops[key];
+ stream_ops[key] = function forceLoadLazyFile() {
+ FS.forceLoadFile(node);
+ return fn.apply(null, arguments);
+ };
+ });
+ function writeChunks(stream, buffer, offset, length, position) {
+ 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;
+ }
+ // use a custom read function
+ stream_ops.read = (stream, buffer, offset, length, position) => {
+ FS.forceLoadFile(node);
+ return writeChunks(stream, buffer, offset, length, position)
+ };
+ // use a custom mmap function
+ stream_ops.mmap = (stream, length, position, prot, flags) => {
+ FS.forceLoadFile(node);
+ var ptr = mmapAlloc(length);
+ if (!ptr) {
+ throw new FS.ErrnoError(48);
+ }
+ writeChunks(stream, HEAP8, ptr, length, position);
+ return { ptr, allocated: true };
+ };
+ node.stream_ops = stream_ops;
+ return node;
+ },
+ };
+ Module['FS'] = FS;
+
+ var SYSCALLS = {
+ DEFAULT_POLLMASK:5,
+ calculateAt:function(dirfd, path, allowEmpty) {
+ if (PATH.isAbs(path)) {
+ return path;
+ }
+ // relative path
+ var dir;
+ if (dirfd === -100) {
+ dir = FS.cwd();
+ } else {
+ var dirstream = SYSCALLS.getStreamFromFD(dirfd);
+ 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)] = stat.mode;
+ HEAPU32[(((buf)+(8))>>2)] = stat.nlink;
+ HEAP32[(((buf)+(12))>>2)] = stat.uid;
+ HEAP32[(((buf)+(16))>>2)] = stat.gid;
+ HEAP32[(((buf)+(20))>>2)] = stat.rdev;
+ (tempI64 = [stat.size>>>0,(tempDouble=stat.size,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(24))>>2)] = tempI64[0],HEAP32[(((buf)+(28))>>2)] = tempI64[1]);
+ HEAP32[(((buf)+(32))>>2)] = 4096;
+ HEAP32[(((buf)+(36))>>2)] = stat.blocks;
+ var atime = stat.atime.getTime();
+ var mtime = stat.mtime.getTime();
+ var ctime = stat.ctime.getTime();
+ (tempI64 = [Math.floor(atime / 1000)>>>0,(tempDouble=Math.floor(atime / 1000),(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(40))>>2)] = tempI64[0],HEAP32[(((buf)+(44))>>2)] = tempI64[1]);
+ HEAPU32[(((buf)+(48))>>2)] = (atime % 1000) * 1000;
+ (tempI64 = [Math.floor(mtime / 1000)>>>0,(tempDouble=Math.floor(mtime / 1000),(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(56))>>2)] = tempI64[0],HEAP32[(((buf)+(60))>>2)] = tempI64[1]);
+ HEAPU32[(((buf)+(64))>>2)] = (mtime % 1000) * 1000;
+ (tempI64 = [Math.floor(ctime / 1000)>>>0,(tempDouble=Math.floor(ctime / 1000),(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(72))>>2)] = tempI64[0],HEAP32[(((buf)+(76))>>2)] = tempI64[1]);
+ HEAPU32[(((buf)+(80))>>2)] = (ctime % 1000) * 1000;
+ (tempI64 = [stat.ino>>>0,(tempDouble=stat.ino,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(88))>>2)] = tempI64[0],HEAP32[(((buf)+(92))>>2)] = tempI64[1]);
+ return 0;
+ },
+ doMsync:function(addr, stream, len, flags, offset) {
+ if (!FS.isFile(stream.node.mode)) {
+ throw new FS.ErrnoError(43);
+ }
+ if (flags & 2) {
+ // MAP_PRIVATE calls need not to be synced back to underlying fs
+ return 0;
+ }
+ var buffer = HEAPU8.slice(addr, addr + len);
+ FS.msync(stream, buffer, offset, len, flags);
+ },
+ varargs:undefined,
+ get() {
+ SYSCALLS.varargs += 4;
+ var ret = HEAP32[(((SYSCALLS.varargs)-(4))>>2)];
+ return ret;
+ },
+ getStr(ptr) {
+ var ret = UTF8ToString(ptr);
+ return ret;
+ },
+ getStreamFromFD:function(fd) {
+ var stream = FS.getStreamChecked(fd);
+ return stream;
+ },
+ };
+ function ___syscall__newselect(nfds, readfds, writefds, exceptfds, timeout) {
+ try {
+
+ // readfds are supported,
+ // writefds checks socket open status
+ // exceptfds not supported
+ // timeout is always 0 - fully async
+
+ var total = 0;
+
+ var srcReadLow = (readfds ? HEAP32[((readfds)>>2)] : 0),
+ srcReadHigh = (readfds ? HEAP32[(((readfds)+(4))>>2)] : 0);
+ var srcWriteLow = (writefds ? HEAP32[((writefds)>>2)] : 0),
+ srcWriteHigh = (writefds ? HEAP32[(((writefds)+(4))>>2)] : 0);
+ var srcExceptLow = (exceptfds ? HEAP32[((exceptfds)>>2)] : 0),
+ srcExceptHigh = (exceptfds ? HEAP32[(((exceptfds)+(4))>>2)] : 0);
+
+ var dstReadLow = 0,
+ dstReadHigh = 0;
+ var dstWriteLow = 0,
+ dstWriteHigh = 0;
+ var dstExceptLow = 0,
+ dstExceptHigh = 0;
+
+ var allLow = (readfds ? HEAP32[((readfds)>>2)] : 0) |
+ (writefds ? HEAP32[((writefds)>>2)] : 0) |
+ (exceptfds ? HEAP32[((exceptfds)>>2)] : 0);
+ var allHigh = (readfds ? HEAP32[(((readfds)+(4))>>2)] : 0) |
+ (writefds ? HEAP32[(((writefds)+(4))>>2)] : 0) |
+ (exceptfds ? HEAP32[(((exceptfds)+(4))>>2)] : 0);
+
+ var check = function(fd, low, high, val) {
+ return (fd < 32 ? (low & val) : (high & val));
+ };
+
+ for (var fd = 0; fd < nfds; fd++) {
+ var mask = 1 << (fd % 32);
+ if (!(check(fd, allLow, allHigh, mask))) {
+ continue; // index isn't in the set
+ }
+
+ var stream = SYSCALLS.getStreamFromFD(fd);
+
+ var flags = SYSCALLS.DEFAULT_POLLMASK;
+
+ if (stream.stream_ops?.poll) {
+ var timeoutInMillis = -1;
+ if (timeout) {
+ var tv_sec = (readfds ? HEAP32[((timeout)>>2)] : 0),
+ tv_usec = (readfds ? HEAP32[(((timeout)+(8))>>2)] : 0);
+ timeoutInMillis = (tv_sec + tv_usec / 1000000) * 1000;
+ }
+ flags = stream.stream_ops.poll(stream, timeoutInMillis);
+ }
+
+ if ((flags & 1) && check(fd, srcReadLow, srcReadHigh, mask)) {
+ fd < 32 ? (dstReadLow = dstReadLow | mask) : (dstReadHigh = dstReadHigh | mask);
+ total++;
+ }
+ if ((flags & 4) && check(fd, srcWriteLow, srcWriteHigh, mask)) {
+ fd < 32 ? (dstWriteLow = dstWriteLow | mask) : (dstWriteHigh = dstWriteHigh | mask);
+ total++;
+ }
+ if ((flags & 2) && check(fd, srcExceptLow, srcExceptHigh, mask)) {
+ fd < 32 ? (dstExceptLow = dstExceptLow | mask) : (dstExceptHigh = dstExceptHigh | mask);
+ total++;
+ }
+ }
+
+ if (readfds) {
+ HEAP32[((readfds)>>2)] = dstReadLow;
+ HEAP32[(((readfds)+(4))>>2)] = dstReadHigh;
+ }
+ if (writefds) {
+ HEAP32[((writefds)>>2)] = dstWriteLow;
+ HEAP32[(((writefds)+(4))>>2)] = dstWriteHigh;
+ }
+ if (exceptfds) {
+ HEAP32[((exceptfds)>>2)] = dstExceptLow;
+ HEAP32[(((exceptfds)+(4))>>2)] = dstExceptHigh;
+ }
+
+ return total;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+ var SOCKFS = {
+ mount(mount) {
+ // If Module['websocket'] has already been defined (e.g. for configuring
+ // the subprotocol/url) use that, if not initialise it to a new object.
+ Module['websocket'] = (Module['websocket'] &&
+ ('object' === typeof Module['websocket'])) ? Module['websocket'] : {};
+
+ // Add the Event registration mechanism to the exported websocket configuration
+ // object so we can register network callbacks from native JavaScript too.
+ // For more documentation see system/include/emscripten/emscripten.h
+ Module['websocket']._callbacks = {};
+ Module['websocket']['on'] = /** @this{Object} */ function(event, callback) {
+ if ('function' === typeof callback) {
+ this._callbacks[event] = callback;
+ }
+ return this;
+ };
+
+ Module['websocket'].emit = /** @this{Object} */ function(event, param) {
+ if ('function' === typeof this._callbacks[event]) {
+ this._callbacks[event].call(this, param);
+ }
+ };
+
+ // If debug is enabled register simple default logging callbacks for each Event.
+
+ return FS.createNode(null, '/', 16384 | 511 /* 0777 */, 0);
+ },
+ createSocket(family, type, protocol) {
+ type &= ~526336; // Some applications may pass it; it makes no sense for a single process.
+ var streaming = type == 1;
+ if (streaming && protocol && protocol != 6) {
+ throw new FS.ErrnoError(66); // if SOCK_STREAM, must be tcp or 0.
+ }
+
+ // create our internal socket structure
+ var sock = {
+ family,
+ type,
+ protocol,
+ server: null,
+ error: null, // Used in getsockopt for SOL_SOCKET/SO_ERROR test
+ peers: {},
+ pending: [],
+ recv_queue: [],
+ sock_ops: SOCKFS.websocket_sock_ops
+ };
+
+ // create the filesystem node to store the socket structure
+ var name = SOCKFS.nextname();
+ var node = FS.createNode(SOCKFS.root, name, 49152, 0);
+ node.sock = sock;
+
+ // and the wrapping stream that enables library functions such
+ // as read and write to indirectly interact with the socket
+ var stream = FS.createStream({
+ path: name,
+ node,
+ flags: 2,
+ seekable: false,
+ stream_ops: SOCKFS.stream_ops
+ });
+
+ // map the new stream to the socket structure (sockets have a 1:1
+ // relationship with a stream)
+ sock.stream = stream;
+
+ return sock;
+ },
+ getSocket(fd) {
+ var stream = FS.getStream(fd);
+ if (!stream || !FS.isSocket(stream.node.mode)) {
+ return null;
+ }
+ return stream.node.sock;
+ },
+ stream_ops:{
+ poll(stream) {
+ var sock = stream.node.sock;
+ return sock.sock_ops.poll(sock);
+ },
+ ioctl(stream, request, varargs) {
+ var sock = stream.node.sock;
+ return sock.sock_ops.ioctl(sock, request, varargs);
+ },
+ read(stream, buffer, offset, length, position /* ignored */) {
+ var sock = stream.node.sock;
+ var msg = sock.sock_ops.recvmsg(sock, length);
+ if (!msg) {
+ // socket is closed
+ return 0;
+ }
+ buffer.set(msg.buffer, offset);
+ return msg.buffer.length;
+ },
+ write(stream, buffer, offset, length, position /* ignored */) {
+ var sock = stream.node.sock;
+ return sock.sock_ops.sendmsg(sock, buffer, offset, length);
+ },
+ close(stream) {
+ var sock = stream.node.sock;
+ sock.sock_ops.close(sock);
+ },
+ },
+ nextname() {
+ if (!SOCKFS.nextname.current) {
+ SOCKFS.nextname.current = 0;
+ }
+ return 'socket[' + (SOCKFS.nextname.current++) + ']';
+ },
+ websocket_sock_ops:{
+ createPeer(sock, addr, port) {
+ var ws;
+
+ if (typeof addr == 'object') {
+ ws = addr;
+ addr = null;
+ port = null;
+ }
+
+ if (ws) {
+ // for sockets that've already connected (e.g. we're the server)
+ // we can inspect the _socket property for the address
+ if (ws._socket) {
+ addr = ws._socket.remoteAddress;
+ port = ws._socket.remotePort;
+ }
+ // if we're just now initializing a connection to the remote,
+ // inspect the url property
+ else {
+ var result = /ws[s]?:\/\/([^:]+):(\d+)/.exec(ws.url);
+ if (!result) {
+ throw new Error('WebSocket URL must be in the format ws(s)://address:port');
+ }
+ addr = result[1];
+ port = parseInt(result[2], 10);
+ }
+ } else {
+ // create the actual websocket object and connect
+ try {
+ // runtimeConfig gets set to true if WebSocket runtime configuration is available.
+ var runtimeConfig = (Module['websocket'] && ('object' === typeof Module['websocket']));
+
+ // The default value is 'ws://' the replace is needed because the compiler replaces '//' comments with '#'
+ // comments without checking context, so we'd end up with ws:#, the replace swaps the '#' for '//' again.
+ var url = 'ws:#'.replace('#', '//');
+
+ if (runtimeConfig) {
+ if("function"===typeof Module["websocket"]["url"]) {
url = Module["websocket"]["url"](...arguments);
-}else if ("string" === typeof Module["websocket"]["url"]){url=Module["websocket"]["url"]}}if(url==="ws://"||url==="wss://"){var parts=addr.split("/");url=url+parts[0]+":"+port+"/"+parts.slice(1).join("/")}var subProtocols="binary";if(runtimeConfig){if("string"===typeof Module["websocket"]["subprotocol"]){subProtocols=Module["websocket"]["subprotocol"]}}var opts=undefined;if(subProtocols!=="null"){subProtocols=subProtocols.replace(/^ +| +$/g,"").split(/ *, */);opts=subProtocols}if(runtimeConfig&&null===Module["websocket"]["subprotocol"]){subProtocols="null";opts=undefined}var WebSocketConstructor;{WebSocketConstructor=WebSocket}if (Module['websocket']['decorator']) {WebSocketConstructor = Module['websocket']['decorator'](WebSocketConstructor);}ws = new WebSocketConstructor(url,opts);ws.binaryType="arraybuffer"}catch(e){throw new FS.ErrnoError(23)}}var peer={addr:addr,port:port,socket:ws,dgram_send_queue:[]};SOCKFS.websocket_sock_ops.addPeer(sock,peer);SOCKFS.websocket_sock_ops.handlePeerEvents(sock,peer);if(sock.type===2&&typeof sock.sport!="undefined"){peer.dgram_send_queue.push(new Uint8Array([255,255,255,255,"p".charCodeAt(0),"o".charCodeAt(0),"r".charCodeAt(0),"t".charCodeAt(0),(sock.sport&65280)>>8,sock.sport&255]))}return peer},getPeer(sock,addr,port){return sock.peers[addr+":"+port]},addPeer(sock,peer){sock.peers[peer.addr+":"+peer.port]=peer},removePeer(sock,peer){delete sock.peers[peer.addr+":"+peer.port]},handlePeerEvents(sock,peer){var first=true;var handleOpen=function(){Module["websocket"].emit("open",sock.stream.fd);try{var queued=peer.dgram_send_queue.shift();while(queued){peer.socket.send(queued);queued=peer.dgram_send_queue.shift()}}catch(e){peer.socket.close()}};function handleMessage(data){if(typeof data=="string"){var encoder=new TextEncoder;data=encoder.encode(data)}else{assert(data.byteLength!==undefined);if(data.byteLength==0){return}data=new Uint8Array(data)}var wasfirst=first;first=false;if(wasfirst&&data.length===10&&data[0]===255&&data[1]===255&&data[2]===255&&data[3]===255&&data[4]==="p".charCodeAt(0)&&data[5]==="o".charCodeAt(0)&&data[6]==="r".charCodeAt(0)&&data[7]==="t".charCodeAt(0)){var newport=data[8]<<8|data[9];SOCKFS.websocket_sock_ops.removePeer(sock,peer);peer.port=newport;SOCKFS.websocket_sock_ops.addPeer(sock,peer);return}sock.recv_queue.push({addr:peer.addr,port:peer.port,data:data});Module["websocket"].emit("message",sock.stream.fd)}if(ENVIRONMENT_IS_NODE){peer.socket.on("open",handleOpen);peer.socket.on("message",(function(data,isBinary){if(!isBinary){return}handleMessage(new Uint8Array(data).buffer)}));peer.socket.on("close",(function(){Module["websocket"].emit("close",sock.stream.fd)}));peer.socket.on("error",(function(error){sock.error=14;Module["websocket"].emit("error",[sock.stream.fd,sock.error,"ECONNREFUSED: Connection refused"])}))}else{peer.socket.onopen=handleOpen;peer.socket.onclose=function(){Module["websocket"].emit("close",sock.stream.fd)};peer.socket.onmessage=function peer_socket_onmessage(event){handleMessage(event.data)};peer.socket.onerror=function(error){sock.error=14;Module["websocket"].emit("error",[sock.stream.fd,sock.error,"ECONNREFUSED: Connection refused"])}}},poll(sock){if(sock.type===1&&sock.server){return sock.pending.length?64|1:0}var mask=0;var dest=sock.type===1?SOCKFS.websocket_sock_ops.getPeer(sock,sock.daddr,sock.dport):null;if(sock.recv_queue.length||!dest||dest&&dest.socket.readyState===dest.socket.CLOSING||dest&&dest.socket.readyState===dest.socket.CLOSED){mask|=64|1}if(!dest||dest&&dest.socket.readyState===dest.socket.OPEN){mask|=4}if(dest&&dest.socket.readyState===dest.socket.CLOSING||dest&&dest.socket.readyState===dest.socket.CLOSED){mask|=16}return mask},ioctl(sock,request,arg){switch(request){case 21531:var bytes=0;if(sock.recv_queue.length){bytes=sock.recv_queue[0].data.length}HEAP32[arg>>2]=bytes;return 0;default:return 28}},close(sock){if(sock.server){try{sock.server.close()}catch(e){}sock.server=null}var peers=Object.keys(sock.peers);for(var i=0;i{HEAP32[___errno_location()>>2]=value;return value};var inetPton4=str=>{var b=str.split(".");for(var i=0;i<4;i++){var tmp=Number(b[i]);if(isNaN(tmp))return null;b[i]=tmp}return(b[0]|b[1]<<8|b[2]<<16|b[3]<<24)>>>0};var jstoi_q=str=>parseInt(str);var inetPton6=str=>{var words;var w,offset,z;var valid6regx=/^((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\3)::|:\b|$))|(?!\2\3)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i;var parts=[];if(!valid6regx.test(str)){return null}if(str==="::"){return[0,0,0,0,0,0,0,0]}if(str.startsWith("::")){str=str.replace("::","Z:")}else{str=str.replace("::",":Z:")}if(str.indexOf(".")>0){str=str.replace(new RegExp("[.]","g"),":");words=str.split(":");words[words.length-4]=jstoi_q(words[words.length-4])+jstoi_q(words[words.length-3])*256;words[words.length-3]=jstoi_q(words[words.length-2])+jstoi_q(words[words.length-1])*256;words=words.slice(0,words.length-2)}else{words=str.split(":")}offset=0;z=0;for(w=0;w{switch(family){case 2:addr=inetPton4(addr);zeroMemory(sa,16);if(addrlen){HEAP32[addrlen>>2]=16}HEAP16[sa>>1]=family;HEAP32[sa+4>>2]=addr;HEAP16[sa+2>>1]=_htons(port);break;case 10:addr=inetPton6(addr);zeroMemory(sa,28);if(addrlen){HEAP32[addrlen>>2]=28}HEAP32[sa>>2]=family;HEAP32[sa+8>>2]=addr[0];HEAP32[sa+12>>2]=addr[1];HEAP32[sa+16>>2]=addr[2];HEAP32[sa+20>>2]=addr[3];HEAP16[sa+2>>1]=_htons(port);break;default:return 5}return 0};var DNS={address_map:{id:1,addrs:{},names:{}},lookup_name:name=>{var res=inetPton4(name);if(res!==null){return name}res=inetPton6(name);if(res!==null){return name}var addr;if(DNS.address_map.addrs[name]){addr=DNS.address_map.addrs[name]}else{var id=DNS.address_map.id++;assert(id<65535,"exceeded max address mappings of 65535");addr="172.29."+(id&255)+"."+(id&65280);DNS.address_map.names[addr]=name;DNS.address_map.addrs[name]=addr}return addr},lookup_addr:addr=>{if(DNS.address_map.names[addr]){return DNS.address_map.names[addr]}return null}};function ___syscall_accept4(fd,addr,addrlen,flags,d1,d2){try{var sock=getSocketFromFD(fd);var newsock=sock.sock_ops.accept(sock);if(addr){var errno=writeSockaddr(addr,newsock.family,DNS.lookup_name(newsock.daddr),newsock.dport,addrlen)}return newsock.stream.fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var inetNtop4=addr=>(addr&255)+"."+(addr>>8&255)+"."+(addr>>16&255)+"."+(addr>>24&255);var inetNtop6=ints=>{var str="";var word=0;var longest=0;var lastzero=0;var zstart=0;var len=0;var i=0;var parts=[ints[0]&65535,ints[0]>>16,ints[1]&65535,ints[1]>>16,ints[2]&65535,ints[2]>>16,ints[3]&65535,ints[3]>>16];var hasipv4=true;var v4part="";for(i=0;i<5;i++){if(parts[i]!==0){hasipv4=false;break}}if(hasipv4){v4part=inetNtop4(parts[6]|parts[7]<<16);if(parts[5]===-1){str="::ffff:";str+=v4part;return str}if(parts[5]===0){str="::";if(v4part==="0.0.0.0")v4part="";if(v4part==="0.0.0.1")v4part="1";str+=v4part;return str}}for(word=0;word<8;word++){if(parts[word]===0){if(word-lastzero>1){len=0}lastzero=word;len++}if(len>longest){longest=len;zstart=word-longest+1}}for(word=0;word<8;word++){if(longest>1){if(parts[word]===0&&word>=zstart&&word{var family=HEAP16[sa>>1];var port=_ntohs(HEAPU16[sa+2>>1]);var addr;switch(family){case 2:if(salen!==16){return{errno:28}}addr=HEAP32[sa+4>>2];addr=inetNtop4(addr);break;case 10:if(salen!==28){return{errno:28}}addr=[HEAP32[sa+8>>2],HEAP32[sa+12>>2],HEAP32[sa+16>>2],HEAP32[sa+20>>2]];addr=inetNtop6(addr);break;default:return{errno:5}}return{family:family,addr:addr,port:port}};function getSocketAddress(addrp,addrlen,allowNull){if(allowNull&&addrp===0)return null;var info=readSockaddr(addrp,addrlen);if(info.errno)throw new FS.ErrnoError(info.errno);info.addr=DNS.lookup_addr(info.addr)||info.addr;return info}function ___syscall_bind(fd,addr,addrlen,d1,d2,d3){try{var sock=getSocketFromFD(fd);var info=getSocketAddress(addr,addrlen);sock.sock_ops.bind(sock,info.addr,info.port);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_chdir(path){try{path=SYSCALLS.getStr(path);FS.chdir(path);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_chmod(path,mode){try{path=SYSCALLS.getStr(path);FS.chmod(path,mode);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_connect(fd,addr,addrlen,d1,d2,d3){try{var sock=getSocketFromFD(fd);var info=getSocketAddress(addr,addrlen);sock.sock_ops.connect(sock,info.addr,info.port);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_dup(fd){try{var old=SYSCALLS.getStreamFromFD(fd);return FS.createStream(old).fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_dup3(fd,newfd,flags){try{var old=SYSCALLS.getStreamFromFD(fd);if(old.fd===newfd)return-28;var existing=FS.getStream(newfd);if(existing)FS.close(existing);return FS.createStream(old,newfd).fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_faccessat(dirfd,path,amode,flags){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);if(amode&~7){return-28}var lookup=FS.lookupPath(path,{follow:true});var 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&&FS.nodePermissions(node,perms)){return-2}return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function convertI32PairToI53Checked(lo,hi){return hi+2097152>>>0<4194305-!!lo?(lo>>>0)+hi*4294967296:NaN}function ___syscall_fallocate(fd,mode,offset_low,offset_high,len_low,len_high){var offset=convertI32PairToI53Checked(offset_low,offset_high);var len=convertI32PairToI53Checked(len_low,len_high);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);FS.allocate(stream,offset,len);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fchmod(fd,mode){try{FS.fchmod(fd,mode);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fchown32(fd,owner,group){try{FS.fchown(fd,owner,group);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fchownat(dirfd,path,owner,group,flags){try{path=SYSCALLS.getStr(path);var nofollow=flags&256;flags=flags&~256;path=SYSCALLS.calculateAt(dirfd,path);(nofollow?FS.lchown:FS.chown)(path,owner,group);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_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.createStream(stream,arg);return newStream.fd}case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=SYSCALLS.get();stream.flags|=arg;return 0}case 5:{var arg=SYSCALLS.get();var offset=0;HEAP16[arg+offset>>1]=2;return 0}case 6:case 7:return 0;case 16:case 8:return-28;case 9:setErrNo(28);return-1;default:{return-28}}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fdatasync(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fstat64(fd,buf){try{var stream=SYSCALLS.getStreamFromFD(fd);return SYSCALLS.doStat(FS.stat,stream.path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_ftruncate64(fd,length_low,length_high){var length=convertI32PairToI53Checked(length_low,length_high);try{if(isNaN(length))return 61;FS.ftruncate(fd,length);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);Module["stringToUTF8"]=stringToUTF8;function ___syscall_getcwd(buf,size){try{if(size===0)return-28;var cwd=FS.cwd();var cwdLengthInBytes=lengthBytesUTF8(cwd)+1;if(size>>0,(tempDouble=id,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[dirp+pos>>2]=tempI64[0],HEAP32[dirp+pos+4>>2]=tempI64[1];tempI64=[(idx+1)*struct_size>>>0,(tempDouble=(idx+1)*struct_size,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[dirp+pos+8>>2]=tempI64[0],HEAP32[dirp+pos+12>>2]=tempI64[1];HEAP16[dirp+pos+16>>1]=280;HEAP8[dirp+pos+18>>0]=type;stringToUTF8(name,dirp+pos+19,256);pos+=struct_size;idx+=1}FS.llseek(stream,idx*struct_size,0);return pos}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_getpeername(fd,addr,addrlen,d1,d2,d3){try{var sock=getSocketFromFD(fd);if(!sock.daddr){return-53}var errno=writeSockaddr(addr,sock.family,DNS.lookup_name(sock.daddr),sock.dport,addrlen);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_getsockname(fd,addr,addrlen,d1,d2,d3){try{var sock=getSocketFromFD(fd);var errno=writeSockaddr(addr,sock.family,DNS.lookup_name(sock.saddr||"0.0.0.0"),sock.sport,addrlen);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_getsockopt(fd,level,optname,optval,optlen,d1){try{var sock=getSocketFromFD(fd);if(level===1){if(optname===4){HEAP32[optval>>2]=sock.error;HEAP32[optlen>>2]=4;sock.error=null;return 0}}return-50}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_ioctl(fd,op,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(op){case 21509:{if(!stream.tty)return-59;return 0}case 21505:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcgets){var termios=stream.tty.ops.ioctl_tcgets(stream);var argp=SYSCALLS.get();HEAP32[argp>>2]=termios.c_iflag||0;HEAP32[argp+4>>2]=termios.c_oflag||0;HEAP32[argp+8>>2]=termios.c_cflag||0;HEAP32[argp+12>>2]=termios.c_lflag||0;for(var i=0;i<32;i++){HEAP8[argp+i+17>>0]=termios.c_cc[i]||0}return 0}return 0}case 21510:case 21511:case 21512:{if(!stream.tty)return-59;return 0}case 21506:case 21507:case 21508:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcsets){var argp=SYSCALLS.get();var c_iflag=HEAP32[argp>>2];var c_oflag=HEAP32[argp+4>>2];var c_cflag=HEAP32[argp+8>>2];var c_lflag=HEAP32[argp+12>>2];var c_cc=[];for(var i=0;i<32;i++){c_cc.push(HEAP8[argp+i+17>>0])}return stream.tty.ops.ioctl_tcsets(stream.tty,op,{c_iflag:c_iflag,c_oflag:c_oflag,c_cflag:c_cflag,c_lflag:c_lflag,c_cc:c_cc})}return 0}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}case 21531:{var argp=SYSCALLS.get();return FS.ioctl(stream,op,argp)}case 21523:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tiocgwinsz){var winsize=stream.tty.ops.ioctl_tiocgwinsz(stream.tty);var argp=SYSCALLS.get();HEAP16[argp>>1]=winsize[0];HEAP16[argp+2>>1]=winsize[1]}return 0}case 21524:{if(!stream.tty)return-59;return 0}case 21515:{if(!stream.tty)return-59;return 0}default:return-28}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_listen(fd,backlog){try{var sock=getSocketFromFD(fd);sock.sock_ops.listen(sock,backlog);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_lstat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.lstat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_mkdirat(dirfd,path,mode){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);path=PATH.normalize(path);if(path[path.length-1]==="/")path=path.substr(0,path.length-1);FS.mkdir(path,mode,0);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_newfstatat(dirfd,path,buf,flags){try{path=SYSCALLS.getStr(path);var nofollow=flags&256;var allowEmpty=flags&4096;flags=flags&~6400;path=SYSCALLS.calculateAt(dirfd,path,allowEmpty);return SYSCALLS.doStat(nofollow?FS.lstat:FS.stat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_openat(dirfd,path,flags,varargs){SYSCALLS.varargs=varargs;try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);var mode=varargs?SYSCALLS.get():0;return FS.open(path,flags,mode).fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var PIPEFS={BUCKET_BUFFER_SIZE:8192,mount(mount){return FS.createNode(null,"/",16384|511,0)},createPipe(){var pipe={buckets:[],refcnt:2};pipe.buckets.push({buffer:new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),offset:0,roffset:0});var rName=PIPEFS.nextname();var wName=PIPEFS.nextname();var rNode=FS.createNode(PIPEFS.root,rName,4096,0);var wNode=FS.createNode(PIPEFS.root,wName,4096,0);rNode.pipe=pipe;wNode.pipe=pipe;var readableStream=FS.createStream({path:rName,node:rNode,flags:0,seekable:false,stream_ops:PIPEFS.stream_ops});rNode.stream=readableStream;var writableStream=FS.createStream({path:wName,node:wNode,flags:1,seekable:false,stream_ops:PIPEFS.stream_ops});wNode.stream=writableStream;return{readable_fd:readableStream.fd,writable_fd:writableStream.fd}},stream_ops:{poll(stream){var pipe=stream.node.pipe;if((stream.flags&2097155)===1){return 256|4}if(pipe.buckets.length>0){for(var i=0;i0){return 64|1}}}return 0},ioctl(stream,request,varargs){return 28},fsync(stream){return 28},read(stream,buffer,offset,length,position){var pipe=stream.node.pipe;var currentLength=0;for(var i=0;i=dataLen){currBucket.buffer.set(data,currBucket.offset);currBucket.offset+=dataLen;return dataLen}else if(freeBytesInCurrBuffer>0){currBucket.buffer.set(data.subarray(0,freeBytesInCurrBuffer),currBucket.offset);currBucket.offset+=freeBytesInCurrBuffer;data=data.subarray(freeBytesInCurrBuffer,data.byteLength)}var numBuckets=data.byteLength/PIPEFS.BUCKET_BUFFER_SIZE|0;var remElements=data.byteLength%PIPEFS.BUCKET_BUFFER_SIZE;for(var i=0;i0){var newBucket={buffer:new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),offset:data.byteLength,roffset:0};pipe.buckets.push(newBucket);newBucket.buffer.set(data)}return dataLen},close(stream){var pipe=stream.node.pipe;pipe.refcnt--;if(pipe.refcnt===0){pipe.buckets=null}}},nextname(){if(!PIPEFS.nextname.current){PIPEFS.nextname.current=0}return"pipe["+PIPEFS.nextname.current+++"]"}};function ___syscall_pipe(fdPtr){try{if(fdPtr==0){throw new FS.ErrnoError(21)}var res=PIPEFS.createPipe();HEAP32[fdPtr>>2]=res.readable_fd;HEAP32[fdPtr+4>>2]=res.writable_fd;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_poll(fds,nfds,timeout){try{var nonzero=0;for(var i=0;i>2];var events=HEAP16[pollfd+4>>1];var mask=32;var stream=FS.getStream(fd);if(stream){mask=SYSCALLS.DEFAULT_POLLMASK;if (stream.stream_ops?.poll){mask=stream.stream_ops.poll(stream,-1)}}mask&=events|8|16;if(mask)nonzero++;HEAP16[pollfd+6>>1]=mask}return nonzero}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_readlinkat(dirfd,path,buf,bufsize){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);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);HEAP8[buf+len]=endChar;return len}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_recvfrom(fd,buf,len,flags,addr,addrlen){try{var sock=getSocketFromFD(fd);var msg=sock.sock_ops.recvmsg(sock,len);if(!msg)return 0;if(addr){var errno=writeSockaddr(addr,sock.family,DNS.lookup_name(msg.addr),msg.port,addrlen)}HEAPU8.set(msg.buffer,buf);return msg.buffer.byteLength}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_renameat(olddirfd,oldpath,newdirfd,newpath){try{oldpath=SYSCALLS.getStr(oldpath);newpath=SYSCALLS.getStr(newpath);oldpath=SYSCALLS.calculateAt(olddirfd,oldpath);newpath=SYSCALLS.calculateAt(newdirfd,newpath);FS.rename(oldpath,newpath);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_rmdir(path){try{path=SYSCALLS.getStr(path);FS.rmdir(path);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_sendto(fd,message,length,flags,addr,addr_len){try{var sock=getSocketFromFD(fd);var dest=getSocketAddress(addr,addr_len,true);if(!dest){return FS.write(sock.stream,HEAP8,message,length)}return sock.sock_ops.sendmsg(sock,HEAP8,message,length,dest.addr,dest.port)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_socket(domain,type,protocol){try{var sock=SOCKFS.createSocket(domain,type,protocol);return sock.stream.fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_stat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.stat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_statfs64(path,size,buf){try{path=SYSCALLS.getStr(path);HEAP32[buf+4>>2]=4096;HEAP32[buf+40>>2]=4096;HEAP32[buf+8>>2]=1e6;HEAP32[buf+12>>2]=5e5;HEAP32[buf+16>>2]=5e5;HEAP32[buf+20>>2]=FS.nextInode;HEAP32[buf+24>>2]=1e6;HEAP32[buf+28>>2]=42;HEAP32[buf+44>>2]=2;HEAP32[buf+36>>2]=255;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_symlink(target,linkpath){try{target=SYSCALLS.getStr(target);linkpath=SYSCALLS.getStr(linkpath);FS.symlink(target,linkpath);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_unlinkat(dirfd,path,flags){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);if(flags===0){FS.unlink(path)}else if(flags===512){FS.rmdir(path)}else{abort("Invalid flags passed to unlinkat")}return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function readI53FromI64(ptr){return HEAPU32[ptr>>2]+HEAP32[ptr+4>>2]*4294967296}function ___syscall_utimensat(dirfd,path,times,flags){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path,true);if(!times){var atime=Date.now();var mtime=atime}else{var seconds=readI53FromI64(times);var nanoseconds=HEAP32[times+8>>2];atime=seconds*1e3+nanoseconds/(1e3*1e3);times+=16;seconds=readI53FromI64(times);nanoseconds=HEAP32[times+8>>2];mtime=seconds*1e3+nanoseconds/(1e3*1e3)}FS.utime(path,atime,mtime);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var nowIsMonotonic=true;var __emscripten_get_now_is_monotonic=()=>nowIsMonotonic;var __emscripten_throw_longjmp=()=>{throw Infinity};function __gmtime_js(time_low,time_high,tmPtr){var time=convertI32PairToI53Checked(time_low,time_high);var date=new Date(time*1e3);HEAP32[tmPtr>>2]=date.getUTCSeconds();HEAP32[tmPtr+4>>2]=date.getUTCMinutes();HEAP32[tmPtr+8>>2]=date.getUTCHours();HEAP32[tmPtr+12>>2]=date.getUTCDate();HEAP32[tmPtr+16>>2]=date.getUTCMonth();HEAP32[tmPtr+20>>2]=date.getUTCFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getUTCDay();var start=Date.UTC(date.getUTCFullYear(),0,1,0,0,0,0);var yday=(date.getTime()-start)/(1e3*60*60*24)|0;HEAP32[tmPtr+28>>2]=yday}var isLeapYear=year=>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_REGULAR_CUMULATIVE=[0,31,59,90,120,151,181,212,243,273,304,334];var 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;return yday};function __localtime_js(time_low,time_high,tmPtr){var time=convertI32PairToI53Checked(time_low,time_high);var date=new Date(time*1e3);HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();HEAP32[tmPtr+20>>2]=date.getFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getDay();var yday=ydayFromDate(date)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr+36>>2]=-(date.getTimezoneOffset()*60);var start=new Date(date.getFullYear(),0,1);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dst=(summerOffset!=winterOffset&&date.getTimezoneOffset()==Math.min(winterOffset,summerOffset))|0;HEAP32[tmPtr+32>>2]=dst}var __mktime_js=function(tmPtr){var ret=(()=>{var date=new Date(HEAP32[tmPtr+20>>2]+1900,HEAP32[tmPtr+16>>2],HEAP32[tmPtr+12>>2],HEAP32[tmPtr+8>>2],HEAP32[tmPtr+4>>2],HEAP32[tmPtr>>2],0);var dst=HEAP32[tmPtr+32>>2];var guessedOffset=date.getTimezoneOffset();var start=new Date(date.getFullYear(),0,1);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dstOffset=Math.min(winterOffset,summerOffset);if(dst<0){HEAP32[tmPtr+32>>2]=Number(summerOffset!=winterOffset&&dstOffset==guessedOffset)}else if(dst>0!=(dstOffset==guessedOffset)){var nonDstOffset=Math.max(winterOffset,summerOffset);var trueOffset=dst>0?dstOffset:nonDstOffset;date.setTime(date.getTime()+(trueOffset-guessedOffset)*6e4)}HEAP32[tmPtr+24>>2]=date.getDay();var yday=ydayFromDate(date)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();HEAP32[tmPtr+20>>2]=date.getYear();return date.getTime()/1e3})();return setTempRet0((tempDouble=ret,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)),ret>>>0};function __mmap_js(len,prot,flags,fd,offset_low,offset_high,allocated,addr){var offset=convertI32PairToI53Checked(offset_low,offset_high);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);var res=FS.mmap(stream,len,offset,prot,flags);var ptr=res.ptr;HEAP32[allocated>>2]=res.allocated;HEAPU32[addr>>2]=ptr;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function __munmap_js(addr,len,prot,flags,fd,offset_low,offset_high){var offset=convertI32PairToI53Checked(offset_low,offset_high);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);if(prot&2){SYSCALLS.doMsync(addr,stream,len,flags,offset)}FS.munmap(stream)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var timers={};var handleException=e=>{if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}quit_(1,e)};var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){if(Module["onExit"])Module["onExit"](code);ABORT=true}quit_(code,new ExitStatus(code))};var exitJS=(status,implicit)=>{EXITSTATUS=status;if(!keepRuntimeAlive()){exitRuntime()}_proc_exit(status)};var _exit=exitJS;Module["_exit"]=_exit;var maybeExit=()=>{if(runtimeExited){return}if(!keepRuntimeAlive()){try{_exit(EXITSTATUS)}catch(e){handleException(e)}}};var callUserCallback=func=>{if(runtimeExited||ABORT){return}try{func();maybeExit()}catch(e){handleException(e)}};var _emscripten_get_now;_emscripten_get_now=()=>performance.now();var __setitimer_js=(which,timeout_ms)=>{if(timers[which]){clearTimeout(timers[which].id);delete timers[which]}if(!timeout_ms)return 0;var id=setTimeout((()=>{delete timers[which];callUserCallback((()=>__emscripten_timeout(which,_emscripten_get_now())))}),timeout_ms);timers[which]={id:id,timeout_ms:timeout_ms};return 0};var stringToNewUTF8=str=>{var size=lengthBytesUTF8(str)+1;var ret=_malloc(size);if(ret)stringToUTF8(str,ret,size);return ret};var __tzset_js=(timezone,daylight,tzname)=>{var currentYear=(new Date).getFullYear();var winter=new Date(currentYear,0,1);var summer=new Date(currentYear,6,1);var winterOffset=winter.getTimezoneOffset();var summerOffset=summer.getTimezoneOffset();var stdTimezoneOffset=Math.max(winterOffset,summerOffset);HEAPU32[timezone>>2]=stdTimezoneOffset*60;HEAP32[daylight>>2]=Number(winterOffset!=summerOffset);function extractZone(date){var match=date.toTimeString().match(/\(([A-Za-z ]+)\)$/);return match?match[1]:"GMT"}var winterName=extractZone(winter);var summerName=extractZone(summer);var winterNamePtr=stringToNewUTF8(winterName);var summerNamePtr=stringToNewUTF8(summerName);if(summerOffset>2]=winterNamePtr;HEAPU32[tzname+4>>2]=summerNamePtr}else{HEAPU32[tzname>>2]=summerNamePtr;HEAPU32[tzname+4>>2]=winterNamePtr}};var _abort=()=>{abort("")};function _emscripten_date_now(){return Date.now()}var getHeapMax=()=>2147483648;var _emscripten_get_heap_max=()=>getHeapMax();var _emscripten_memcpy_big=(dest,src,num)=>HEAPU8.copyWithin(dest,src,src+num);var growMemory=size=>{var b=wasmMemory.buffer;var pages=size-b.byteLength+65535>>>16;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}var alignUp=(x,multiple)=>x+(multiple-x%multiple)%multiple;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false};var runtimeKeepalivePush=()=>{runtimeKeepaliveCounter+=1};var runtimeKeepalivePop=()=>{runtimeKeepaliveCounter-=1};var safeSetTimeout=(func,timeout)=>{runtimeKeepalivePush();return setTimeout((()=>{runtimeKeepalivePop();callUserCallback(func)}),timeout)};var _emscripten_sleep=function(ms){return Asyncify.handleSleep((wakeUp=>safeSetTimeout(wakeUp,ms)))};Module["_emscripten_sleep"]=_emscripten_sleep;_emscripten_sleep.isAsync=true;var ENV = PHPLoader.ENV || {};var getExecutableName=()=>thisProgram||"./this.program";var getEnvStrings=()=>{if(!getEnvStrings.strings){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()};for(var x in ENV){if(ENV[x]===undefined)delete env[x];else env[x]=ENV[x]}var strings=[];for(var x in env){strings.push(`${x}=${env[x]}`)}getEnvStrings.strings=strings}return getEnvStrings.strings};var stringToAscii=(str,buffer)=>{for(var i=0;i>0]=str.charCodeAt(i)}HEAP8[buffer>>0]=0};var _environ_get=(__environ,environ_buf)=>{var bufSize=0;getEnvStrings().forEach((function(string,i){var ptr=environ_buf+bufSize;HEAPU32[__environ+i*4>>2]=ptr;stringToAscii(string,ptr);bufSize+=string.length+1}));return 0};var _environ_sizes_get=(penviron_count,penviron_buf_size)=>{var strings=getEnvStrings();HEAPU32[penviron_count>>2]=strings.length;var bufSize=0;strings.forEach((function(string){bufSize+=string.length+1}));HEAPU32[penviron_buf_size>>2]=bufSize;return 0};function _fd_close(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);FS.close(stream);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_fdstat_get(fd,pbuf){try{var rightsBase=0;var rightsInheriting=0;var flags=0;{var stream=SYSCALLS.getStreamFromFD(fd);var type=stream.tty?2:FS.isDir(stream.mode)?3:FS.isLink(stream.mode)?7:4}HEAP8[pbuf>>0]=type;HEAP16[pbuf+2>>1]=flags;tempI64=[rightsBase>>>0,(tempDouble=rightsBase,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[pbuf+8>>2]=tempI64[0],HEAP32[pbuf+12>>2]=tempI64[1];tempI64=[rightsInheriting>>>0,(tempDouble=rightsInheriting,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[pbuf+16>>2]=tempI64[0],HEAP32[pbuf+20>>2]=tempI64[1];return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doReadv=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>2]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){var offset=convertI32PairToI53Checked(offset_low,offset_high);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);FS.llseek(stream,offset,whence);tempI64=[stream.position>>>0,(tempDouble=stream.position,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[newOffset>>2]=tempI64[0],HEAP32[newOffset+4>>2]=tempI64[1];if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_sync(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);return Asyncify.handleSleep((function(wakeUp){var mount=stream.node.mount;if(!mount.type.syncfs){wakeUp(0);return}mount.type.syncfs(mount,false,(function(err){if(err){wakeUp((function(){return 29}));return}wakeUp(0)}))}))}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doWritev=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(typeof offset!=="undefined"){offset+=curr}}return ret};function _fd_write(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStreamFromFD(fd);var num=doWritev(stream,iov,iovcnt);HEAPU32[pnum>>2]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var _getaddrinfo=(node,service,hint,out)=>{var addr=0;var port=0;var flags=0;var family=0;var type=0;var proto=0;var ai;function allocaddrinfo(family,type,proto,canon,addr,port){var sa,salen,ai;var errno;salen=family===10?28:16;addr=family===10?inetNtop6(addr):inetNtop4(addr);sa=_malloc(salen);errno=writeSockaddr(sa,family,addr,port);assert(!errno);ai=_malloc(32);HEAP32[ai+4>>2]=family;HEAP32[ai+8>>2]=type;HEAP32[ai+12>>2]=proto;HEAPU32[ai+24>>2]=canon;HEAPU32[ai+20>>2]=sa;if(family===10){HEAP32[ai+16>>2]=28}else{HEAP32[ai+16>>2]=16}HEAP32[ai+28>>2]=0;return ai}if(hint){flags=HEAP32[hint>>2];family=HEAP32[hint+4>>2];type=HEAP32[hint+8>>2];proto=HEAP32[hint+12>>2]}if(type&&!proto){proto=type===2?17:6}if(!type&&proto){type=proto===17?2:1}if(proto===0){proto=6}if(type===0){type=1}if(!node&&!service){return-2}if(flags&~(1|2|4|1024|8|16|32)){return-1}if(hint!==0&&HEAP32[hint>>2]&2&&!node){return-1}if(flags&32){return-2}if(type!==0&&type!==1&&type!==2){return-7}if(family!==0&&family!==2&&family!==10){return-6}if(service){service=UTF8ToString(service);port=parseInt(service,10);if(isNaN(port)){if(flags&1024){return-2}return-8}}if(!node){if(family===0){family=2}if((flags&1)===0){if(family===2){addr=_htonl(2130706433)}else{addr=[0,0,0,1]}}ai=allocaddrinfo(family,type,proto,null,addr,port);HEAPU32[out>>2]=ai;return 0}node=UTF8ToString(node);addr=inetPton4(node);if(addr!==null){if(family===0||family===2){family=2}else if(family===10&&flags&8){addr=[0,0,_htonl(65535),addr];family=10}else{return-2}}else{addr=inetPton6(node);if(addr!==null){if(family===0||family===10){family=10}else{return-2}}}if(addr!=null){ai=allocaddrinfo(family,type,proto,node,addr,port);HEAPU32[out>>2]=ai;return 0}if(flags&4){return-2}node=DNS.lookup_name(node);addr=inetPton4(node);if(family===0){family=2}else if(family===10){addr=[0,0,_htonl(65535),addr]}ai=allocaddrinfo(family,type,proto,null,addr,port);HEAPU32[out>>2]=ai;return 0};function _getcontext(){err("missing function: getcontext");abort(-1)}function _getdtablesize(){err("missing function: getdtablesize");abort(-1)}var getHostByName=name=>{var ret=_malloc(20);var nameBuf=stringToNewUTF8(name);HEAPU32[ret>>2]=nameBuf;var aliasesBuf=_malloc(4);HEAPU32[aliasesBuf>>2]=0;HEAPU32[ret+4>>2]=aliasesBuf;var afinet=2;HEAP32[ret+8>>2]=afinet;HEAP32[ret+12>>2]=4;var addrListBuf=_malloc(12);HEAPU32[addrListBuf>>2]=addrListBuf+8;HEAPU32[addrListBuf+4>>2]=0;HEAP32[addrListBuf+8>>2]=inetPton4(DNS.lookup_name(name));HEAPU32[ret+16>>2]=addrListBuf;return ret};var _gethostbyname=name=>getHostByName(UTF8ToString(name));var _gethostbyname_r=(name,ret,buf,buflen,out,err)=>{var data=_gethostbyname(name);_memcpy(ret,data,20);_free(data);HEAP32[err>>2]=0;HEAPU32[out>>2]=ret;return 0};var _getloadavg=(loadavg,nelem)=>{var limit=Math.min(nelem,3);var doubleSize=8;for(var i=0;i>3]=.1}return limit};var _getnameinfo=(sa,salen,node,nodelen,serv,servlen,flags)=>{var info=readSockaddr(sa,salen);if(info.errno){return-6}var port=info.port;var addr=info.addr;var overflowed=false;if(node&&nodelen){var lookup;if(flags&1||!(lookup=DNS.lookup_addr(addr))){if(flags&8){return-2}}else{addr=lookup}var numBytesWrittenExclNull=stringToUTF8(addr,node,nodelen);if(numBytesWrittenExclNull+1>=nodelen){overflowed=true}}if(serv&&servlen){port=""+port;var numBytesWrittenExclNull=stringToUTF8(port,serv,servlen);if(numBytesWrittenExclNull+1>=servlen){overflowed=true}}if(overflowed){return-12}return 0};var Protocols={list:[],map:{}};var _setprotoent=stayopen=>{function allocprotoent(name,proto,aliases){var nameBuf=_malloc(name.length+1);stringToAscii(name,nameBuf);var j=0;var length=aliases.length;var aliasListBuf=_malloc((length+1)*4);for(var i=0;i>2]=aliasBuf}HEAPU32[aliasListBuf+j>>2]=0;var pe=_malloc(12);HEAPU32[pe>>2]=nameBuf;HEAPU32[pe+4>>2]=aliasListBuf;HEAP32[pe+8>>2]=proto;return pe}var list=Protocols.list;var map=Protocols.map;if(list.length===0){var entry=allocprotoent("tcp",6,["TCP"]);list.push(entry);map["tcp"]=map["6"]=entry;entry=allocprotoent("udp",17,["UDP"]);list.push(entry);map["udp"]=map["17"]=entry}_setprotoent.index=0};var _getprotobyname=name=>{name=UTF8ToString(name);_setprotoent(true);var result=Protocols.map[name];return result};var _getprotobynumber=number=>{_setprotoent(true);var result=Protocols.map[number];return result};var stringToUTF8OnStack=str=>{var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8(str,ret,size);return ret};var allocateUTF8OnStack=stringToUTF8OnStack;var PHPWASM={init:function(){PHPWASM.EventEmitter=ENVIRONMENT_IS_NODE?require("events").EventEmitter:class EventEmitter{constructor(){this.listeners={}}emit(eventName,data){if(this.listeners[eventName]){this.listeners[eventName].forEach((callback=>{callback(data)}))}}once(eventName,callback){const self=this;function removedCallback(){callback(...arguments);self.removeListener(eventName,removedCallback)}this.on(eventName,removedCallback)}removeAllListeners(eventName){if(eventName){delete this.listeners[eventName]}else{this.listeners={}}}removeListener(eventName,callback){if(this.listeners[eventName]){const idx=this.listeners[eventName].indexOf(callback);if(idx!==-1){this.listeners[eventName].splice(idx,1)}}}};PHPWASM.child_proc_by_fd={};PHPWASM.child_proc_by_pid={};PHPWASM.input_devices={}},getAllWebSockets:function(sock){const webSockets=new Set;if(sock.server){sock.server.clients.forEach((ws=>{webSockets.add(ws)}))}for(const peer of PHPWASM.getAllPeers(sock)){webSockets.add(peer.socket)}return Array.from(webSockets)},getAllPeers:function(sock){const peers=new Set;if(sock.server){sock.pending.filter((pending=>pending.peers)).forEach((pending=>{for(const peer of Object.values(pending.peers)){peers.add(peer)}}))}if(sock.peers){for(const peer of Object.values(sock.peers)){peers.add(peer)}}return Array.from(peers)},awaitData:function(ws){return PHPWASM.awaitEvent(ws,"message")},awaitConnection:function(ws){if(ws.OPEN===ws.readyState){return[Promise.resolve(),PHPWASM.noop]}return PHPWASM.awaitEvent(ws,"open")},awaitClose:function(ws){if([ws.CLOSING,ws.CLOSED].includes(ws.readyState)){return[Promise.resolve(),PHPWASM.noop]}return PHPWASM.awaitEvent(ws,"close")},awaitError:function(ws){if([ws.CLOSING,ws.CLOSED].includes(ws.readyState)){return[Promise.resolve(),PHPWASM.noop]}return PHPWASM.awaitEvent(ws,"error")},awaitEvent:function(ws,event){let resolve;const listener=()=>{resolve()};const promise=new Promise((function(_resolve){resolve=_resolve;ws.once(event,listener)}));const cancel=()=>{ws.removeListener(event,listener);setTimeout(resolve)};return[promise,cancel]},noop:function(){},spawnProcess:function(command,args){if(Module["spawnProcess"]){const spawnedPromise=Module["spawnProcess"](command,args);return Promise.resolve(spawnedPromise).then((function(spawned){if(!spawned||!spawned.on){throw new Error("spawnProcess() must return an EventEmitter but returned a different type.")}return spawned}))}if(ENVIRONMENT_IS_NODE){return require("child_process").spawn(command,args,{shell:true,stdio:["pipe","pipe","pipe"],timeout:100})}const e=new Error("popen(), proc_open() etc. are unsupported in the browser. Call php.setSpawnHandler() "+"and provide a callback to handle spawning processes, or disable a popen(), proc_open() "+"and similar functions via php.ini.");e.code="SPAWN_UNSUPPORTED";throw e},shutdownSocket:function(socketd,how){const sock=getSocketFromFD(socketd);const peer=Object.values(sock.peers)[0];if(!peer){return-1}try{peer.socket.close();SOCKFS.websocket_sock_ops.removePeer(sock,peer);return 0}catch(e){console.log("Socket shutdown error",e);return-1}}};function _js_create_input_device(deviceId){let dataBuffer=[];let dataCallback;const filename="proc_id_"+deviceId;const device=FS.createDevice("/dev",filename,(function(){}),(function(byte){try{dataBuffer.push(byte);if(dataCallback){dataCallback(new Uint8Array(dataBuffer));dataBuffer=[]}}catch(e){console.error(e);throw e}}));const devicePath="/dev/"+filename;PHPWASM.input_devices[deviceId]={devicePath:devicePath,onData:function(cb){dataCallback=cb;dataBuffer.forEach((function(data){cb(data)}));dataBuffer.length=0}};return allocateUTF8OnStack(devicePath)}function _js_fd_read(fd,iov,iovcnt,pnum){var returnCode;var stream;try{stream=SYSCALLS.getStreamFromFD(fd);var num=doReadv(stream,iov,iovcnt);HEAPU32[pnum>>2]=num;returnCode=0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;returnCode=e.errno}if(returnCode===6&&stream?.fd in PHPWASM.child_proc_by_fd){return Asyncify.handleSleep((function(wakeUp){var retries=0;var interval=50;var timeout=5e3;var maxRetries=timeout/interval;function poll(){var returnCode;var stream;try{stream=SYSCALLS.getStreamFromFD(fd);var num=doReadv(stream,iov,iovcnt);HEAPU32[pnum>>2]=num;returnCode=0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError")){console.error(e);throw e}returnCode=e.errno}if(returnCode!==6||++retries>maxRetries||!(fd in PHPWASM.child_proc_by_fd)||PHPWASM.child_proc_by_fd[fd]?.exited||FS.isClosed(stream)){wakeUp(returnCode)}else{setTimeout(poll,interval)}}poll()}))}return returnCode}function _js_module_onMessage(data,bufPtr){if(typeof Asyncify==="undefined"){return}if(Module["onMessage"]){const dataStr=UTF8ToString(data);return Asyncify.handleSleep((wakeUp=>{Module["onMessage"](dataStr).then((response=>{const responseBytes=typeof response==="string"?(new TextEncoder).encode(response):response;const responseSize=responseBytes.byteLength;const responsePtr=_malloc(responseSize+1);HEAPU8.set(responseBytes,responsePtr);HEAPU8[responsePtr+responseSize]=0;HEAPU8[bufPtr]=responsePtr;HEAPU8[bufPtr+1]=responsePtr>>8;HEAPU8[bufPtr+2]=responsePtr>>16;HEAPU8[bufPtr+3]=responsePtr>>24;wakeUp(responseSize)})).catch((e=>{console.error(e);wakeUp(0)}))}))}}function _js_open_process(command,argsPtr,argsLength,descriptorsPtr,descriptorsLength){if(!command){return 1}const cmdstr=UTF8ToString(command);if(!cmdstr.length){return 0}let argsArray=[];if(argsLength){for(var i=0;i>2]))}}var std={};for(var i=0;i>2];std[HEAPU32[descriptorPtr>>2]]={child:HEAPU32[descriptorPtr+4>>2],parent:HEAPU32[descriptorPtr+8>>2]}}return Asyncify.handleSleep((async wakeUp=>{let cp;try{cp=PHPWASM.spawnProcess(cmdstr,argsArray);if(cp instanceof Promise){cp=await cp}}catch(e){if(e.code==="SPAWN_UNSUPPORTED"){wakeUp(1);return}console.error(e);wakeUp(1);throw e}const ProcInfo={pid:cp.pid,exited:false,stdinFd:std[0]?.child,stdinIsDevice:std[0]?.child in PHPWASM.input_devices,stdoutChildFd:std[1]?.child,stdoutParentFd:std[1]?.parent,stderrChildFd:std[2]?.child,stderrParentFd:std[2]?.parent,stdout:new PHPWASM.EventEmitter,stderr:new PHPWASM.EventEmitter};if(ProcInfo.stdoutChildFd)PHPWASM.child_proc_by_fd[ProcInfo.stdoutChildFd]=ProcInfo;if(ProcInfo.stderrChildFd)PHPWASM.child_proc_by_fd[ProcInfo.stderrChildFd]=ProcInfo;if(ProcInfo.stdoutParentFd)PHPWASM.child_proc_by_fd[ProcInfo.stdoutParentFd]=ProcInfo;if(ProcInfo.stderrParentFd)PHPWASM.child_proc_by_fd[ProcInfo.stderrParentFd]=ProcInfo;PHPWASM.child_proc_by_pid[ProcInfo.pid]=ProcInfo;cp.on("exit",(function(code){ProcInfo.exitCode=code;ProcInfo.exited=true;ProcInfo.stdout.emit("data");ProcInfo.stderr.emit("data")}));if(ProcInfo.stdoutChildFd){const stdoutStream=SYSCALLS.getStreamFromFD(ProcInfo.stdoutChildFd);let stdoutAt=0;cp.stdout.on("data",(function(data){ProcInfo.stdout.emit("data",data);stdoutStream.stream_ops.write(stdoutStream,data,0,data.length,stdoutAt);stdoutAt+=data.length}))}if(ProcInfo.stderrChildFd){const stderrStream=SYSCALLS.getStreamFromFD(ProcInfo.stderrChildFd);let stderrAt=0;cp.stderr.on("data",(function(data){ProcInfo.stderr.emit("data",data);stderrStream.stream_ops.write(stderrStream,data,0,data.length,stderrAt);stderrAt+=data.length}))}try{await new Promise(((resolve,reject)=>{cp.on("spawn",resolve);cp.on("error",reject)}))}catch(e){console.error(e);wakeUp(1);return}if(ProcInfo.stdinIsDevice){PHPWASM.input_devices[ProcInfo.stdinFd].onData((function(data){if(!data)return;const dataStr=new TextDecoder("utf-8").decode(data);cp.stdin.write(dataStr)}));wakeUp(ProcInfo.pid);return}if(ProcInfo.stdinFd){const stdinStream=SYSCALLS.getStreamFromFD(ProcInfo.stdinFd);if(stdinStream.node){const CHUNK_SIZE=1024;const buffer=new Uint8Array(CHUNK_SIZE);let offset=0;while(true){const bytesRead=stdinStream.stream_ops.read(stdinStream,buffer,0,CHUNK_SIZE,offset);if(bytesRead===null||bytesRead===0){break}try{cp.stdin.write(buffer.subarray(0,bytesRead))}catch(e){console.error(e);return 1}if(bytesRead{let cp;try{cp=PHPWASM.spawnProcess(cmdstr,[]);if(cp instanceof Promise){cp=await cp}}catch(e){console.error(e);if(e.code==="SPAWN_UNSUPPORTED"){return 1}throw e}const outByteArrays=[];cp.stdout.on("data",(function(data){outByteArrays.push(data)}));const outputPath="/tmp/popen_output";cp.on("exit",(function(exitCode){const outBytes=new Uint8Array(outByteArrays.reduce(((acc,curr)=>acc+curr.length),0));let offset=0;for(const byteArray of outByteArrays){outBytes.set(byteArray,offset);offset+=byteArray.length}FS.writeFile(outputPath,outBytes);HEAPU8[exitCodePtr]=exitCode;wakeUp(allocateUTF8OnStack(outputPath))}))}))}function _js_process_status(pid){if(!PHPWASM.child_proc_by_pid[pid]){return-1}if(PHPWASM.child_proc_by_pid[pid].exited){return 1}return 0}function _js_waitpid(pid,exitCodePtr){if(!PHPWASM.child_proc_by_pid[pid]){return-1}return Asyncify.handleSleep((wakeUp=>{const poll=function(){if(PHPWASM.child_proc_by_pid[pid]?.exited){HEAPU8[exitCodePtr]=PHPWASM.child_proc_by_pid[pid].exitCode;wakeUp(0)}else{setTimeout(poll,50)}};poll()}))}function _makecontext(){err("missing function: makecontext");abort(-1)}var arraySum=(array,index)=>{var sum=0;for(var i=0;i<=index;sum+=array[i++]){}return sum};var MONTH_DAYS_LEAP=[31,29,31,30,31,30,31,31,30,31,30,31];var MONTH_DAYS_REGULAR=[31,28,31,30,31,30,31,31,30,31,30,31];var addDays=(date,days)=>{var newDate=new Date(date.getTime());while(days>0){var leap=isLeapYear(newDate.getFullYear());var currentMonth=newDate.getMonth();var daysInCurrentMonth=(leap?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR)[currentMonth];if(days>daysInCurrentMonth-newDate.getDate()){days-=daysInCurrentMonth-newDate.getDate()+1;newDate.setDate(1);if(currentMonth<11){newDate.setMonth(currentMonth+1)}else{newDate.setMonth(0);newDate.setFullYear(newDate.getFullYear()+1)}}else{newDate.setDate(newDate.getDate()+days);return newDate}}return newDate};var writeArrayToMemory=(array,buffer)=>{HEAP8.set(array,buffer)};var _strftime=(s,maxsize,format,tm)=>{var tm_zone=HEAP32[tm+40>>2];var date={tm_sec:HEAP32[tm>>2],tm_min:HEAP32[tm+4>>2],tm_hour:HEAP32[tm+8>>2],tm_mday:HEAP32[tm+12>>2],tm_mon:HEAP32[tm+16>>2],tm_year:HEAP32[tm+20>>2],tm_wday:HEAP32[tm+24>>2],tm_yday:HEAP32[tm+28>>2],tm_isdst:HEAP32[tm+32>>2],tm_gmtoff:HEAP32[tm+36>>2],tm_zone:tm_zone?UTF8ToString(tm_zone):""};var pattern=UTF8ToString(format);var EXPANSION_RULES_1={"%c":"%a %b %d %H:%M:%S %Y","%D":"%m/%d/%y","%F":"%Y-%m-%d","%h":"%b","%r":"%I:%M:%S %p","%R":"%H:%M","%T":"%H:%M:%S","%x":"%m/%d/%y","%X":"%H:%M:%S","%Ec":"%c","%EC":"%C","%Ex":"%m/%d/%y","%EX":"%H:%M:%S","%Ey":"%y","%EY":"%Y","%Od":"%d","%Oe":"%e","%OH":"%H","%OI":"%I","%Om":"%m","%OM":"%M","%OS":"%S","%Ou":"%u","%OU":"%U","%OV":"%V","%Ow":"%w","%OW":"%W","%Oy":"%y"};for(var rule in EXPANSION_RULES_1){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_1[rule])}var WEEKDAYS=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];var MONTHS=["January","February","March","April","May","June","July","August","September","October","November","December"];function leadingSomething(value,digits,character){var str=typeof value=="number"?value.toString():value||"";while(str.length0?1:0}var compare;if((compare=sgn(date1.getFullYear()-date2.getFullYear()))===0){if((compare=sgn(date1.getMonth()-date2.getMonth()))===0){compare=sgn(date1.getDate()-date2.getDate())}}return compare}function getFirstWeekStartDate(janFourth){switch(janFourth.getDay()){case 0:return new Date(janFourth.getFullYear()-1,11,29);case 1:return janFourth;case 2:return new Date(janFourth.getFullYear(),0,3);case 3:return new Date(janFourth.getFullYear(),0,2);case 4:return new Date(janFourth.getFullYear(),0,1);case 5:return new Date(janFourth.getFullYear()-1,11,31);case 6:return new Date(janFourth.getFullYear()-1,11,30)}}function getWeekBasedYear(date){var thisDate=addDays(new Date(date.tm_year+1900,0,1),date.tm_yday);var janFourthThisYear=new Date(thisDate.getFullYear(),0,4);var janFourthNextYear=new Date(thisDate.getFullYear()+1,0,4);var firstWeekStartThisYear=getFirstWeekStartDate(janFourthThisYear);var firstWeekStartNextYear=getFirstWeekStartDate(janFourthNextYear);if(compareByDay(firstWeekStartThisYear,thisDate)<=0){if(compareByDay(firstWeekStartNextYear,thisDate)<=0){return thisDate.getFullYear()+1}return thisDate.getFullYear()}return thisDate.getFullYear()-1}var EXPANSION_RULES_2={"%a":date=>WEEKDAYS[date.tm_wday].substring(0,3),"%A":date=>WEEKDAYS[date.tm_wday],"%b":date=>MONTHS[date.tm_mon].substring(0,3),"%B":date=>MONTHS[date.tm_mon],"%C":date=>{var year=date.tm_year+1900;return leadingNulls(year/100|0,2)},"%d":date=>leadingNulls(date.tm_mday,2),"%e":date=>leadingSomething(date.tm_mday,2," "),"%g":date=>getWeekBasedYear(date).toString().substring(2),"%G":date=>getWeekBasedYear(date),"%H":date=>leadingNulls(date.tm_hour,2),"%I":date=>{var twelveHour=date.tm_hour;if(twelveHour==0)twelveHour=12;else if(twelveHour>12)twelveHour-=12;return leadingNulls(twelveHour,2)},"%j":date=>leadingNulls(date.tm_mday+arraySum(isLeapYear(date.tm_year+1900)?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR,date.tm_mon-1),3),"%m":date=>leadingNulls(date.tm_mon+1,2),"%M":date=>leadingNulls(date.tm_min,2),"%n":()=>"\n","%p":date=>{if(date.tm_hour>=0&&date.tm_hour<12){return"AM"}return"PM"},"%S":date=>leadingNulls(date.tm_sec,2),"%t":()=>"\t","%u":date=>date.tm_wday||7,"%U":date=>{var days=date.tm_yday+7-date.tm_wday;return leadingNulls(Math.floor(days/7),2)},"%V":date=>{var val=Math.floor((date.tm_yday+7-(date.tm_wday+6)%7)/7);if((date.tm_wday+371-date.tm_yday-2)%7<=2){val++}if(!val){val=52;var dec31=(date.tm_wday+7-date.tm_yday-1)%7;if(dec31==4||dec31==5&&isLeapYear(date.tm_year%400-1)){val++}}else if(val==53){var jan1=(date.tm_wday+371-date.tm_yday)%7;if(jan1!=4&&(jan1!=3||!isLeapYear(date.tm_year)))val=1}return leadingNulls(val,2)},"%w":date=>date.tm_wday,"%W":date=>{var days=date.tm_yday+7-(date.tm_wday+6)%7;return leadingNulls(Math.floor(days/7),2)},"%y":date=>(date.tm_year+1900).toString().substring(2),"%Y":date=>date.tm_year+1900,"%z":date=>{var off=date.tm_gmtoff;var ahead=off>=0;off=Math.abs(off)/60;off=off/60*100+off%60;return(ahead?"+":"-")+String("0000"+off).slice(-4)},"%Z":date=>date.tm_zone,"%%":()=>"%"};pattern=pattern.replace(/%%/g,"\0\0");for(var rule in EXPANSION_RULES_2){if(pattern.includes(rule)){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_2[rule](date))}}pattern=pattern.replace(/\0\0/g,"%");var bytes=intArrayFromString(pattern,false);if(bytes.length>maxsize){return 0}writeArrayToMemory(bytes,s);return bytes.length-1};var _strptime=(buf,format,tm)=>{var pattern=UTF8ToString(format);var SPECIAL_CHARS="\\!@#$^&*()+=-[]/{}|:<>?,.";for(var i=0,ii=SPECIAL_CHARS.length;i=0;i=pattern.indexOf("%")){capture.push(pattern[i+1]);pattern=pattern.replace(new RegExp("\\%"+pattern[i+1],"g"),"")}var matches=new RegExp("^"+pattern,"i").exec(UTF8ToString(buf));function initDate(){function fixup(value,min,max){return typeof value!="number"||isNaN(value)?min:value>=min?value<=max?value:max:min}return{year:fixup(HEAP32[tm+20>>2]+1900,1970,9999),month:fixup(HEAP32[tm+16>>2],0,11),day:fixup(HEAP32[tm+12>>2],1,31),hour:fixup(HEAP32[tm+8>>2],0,23),min:fixup(HEAP32[tm+4>>2],0,59),sec:fixup(HEAP32[tm>>2],0,59)}}if(matches){var date=initDate();var value;var getMatch=symbol=>{var pos=capture.indexOf(symbol);if(pos>=0){return matches[pos+1]}return};if(value=getMatch("S")){date.sec=jstoi_q(value)}if(value=getMatch("M")){date.min=jstoi_q(value)}if(value=getMatch("H")){date.hour=jstoi_q(value)}else if(value=getMatch("I")){var hour=jstoi_q(value);if(value=getMatch("p")){hour+=value.toUpperCase()[0]==="P"?12:0}date.hour=hour}if(value=getMatch("Y")){date.year=jstoi_q(value)}else if(value=getMatch("y")){var year=jstoi_q(value);if(value=getMatch("C")){year+=jstoi_q(value)*100}else{year+=year<69?2e3:1900}date.year=year}if(value=getMatch("m")){date.month=jstoi_q(value)-1}else if(value=getMatch("b")){date.month=MONTH_NUMBERS[value.substring(0,3).toUpperCase()]||0}if(value=getMatch("d")){date.day=jstoi_q(value)}else if(value=getMatch("j")){var day=jstoi_q(value);var leapYear=isLeapYear(date.year);for(var month=0;month<12;++month){var daysUntilMonth=arraySum(leapYear?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR,month-1);if(day<=daysUntilMonth+(leapYear?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR)[month]){date.day=day-daysUntilMonth}}}else if(value=getMatch("a")){var weekDay=value.substring(0,3).toUpperCase();if(value=getMatch("U")){var weekDayNumber=DAY_NUMBERS_SUN_FIRST[weekDay];var weekNumber=jstoi_q(value);var janFirst=new Date(date.year,0,1);var endDate;if(janFirst.getDay()===0){endDate=addDays(janFirst,weekDayNumber+7*(weekNumber-1))}else{endDate=addDays(janFirst,7-janFirst.getDay()+weekDayNumber+7*(weekNumber-1))}date.day=endDate.getDate();date.month=endDate.getMonth()}else if(value=getMatch("W")){var weekDayNumber=DAY_NUMBERS_MON_FIRST[weekDay];var weekNumber=jstoi_q(value);var janFirst=new Date(date.year,0,1);var endDate;if(janFirst.getDay()===1){endDate=addDays(janFirst,weekDayNumber+7*(weekNumber-1))}else{endDate=addDays(janFirst,7-janFirst.getDay()+1+weekDayNumber+7*(weekNumber-1))}date.day=endDate.getDate();date.month=endDate.getMonth()}}var fullDate=new Date(date.year,date.month,date.day,date.hour,date.min,date.sec,0);HEAP32[tm>>2]=fullDate.getSeconds();HEAP32[tm+4>>2]=fullDate.getMinutes();HEAP32[tm+8>>2]=fullDate.getHours();HEAP32[tm+12>>2]=fullDate.getDate();HEAP32[tm+16>>2]=fullDate.getMonth();HEAP32[tm+20>>2]=fullDate.getFullYear()-1900;HEAP32[tm+24>>2]=fullDate.getDay();HEAP32[tm+28>>2]=arraySum(isLeapYear(fullDate.getFullYear())?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR,fullDate.getMonth()-1)+fullDate.getDate()-1;HEAP32[tm+32>>2]=0;return buf+intArrayFromString(matches[0]).length-1}return 0};function _swapcontext(){err("missing function: swapcontext");abort(-1)}function _wasm_poll_socket(socketd,events,timeout){if(typeof Asyncify==="undefined"){return 0}const POLLIN=1;const POLLPRI=2;const POLLOUT=4;const POLLERR=8;const POLLHUP=16;const POLLNVAL=32;return Asyncify.handleSleep((wakeUp=>{const polls=[];if(socketd in PHPWASM.child_proc_by_fd){const procInfo=PHPWASM.child_proc_by_fd[socketd];if(procInfo.exited){wakeUp(0);return}polls.push(PHPWASM.awaitEvent(procInfo.stdout,"data"))}else{const sock=getSocketFromFD(socketd);if(!sock){wakeUp(0);return}const lookingFor=new Set;if(events&POLLIN||events&POLLPRI){if(sock.server){for(const client of sock.pending){if((client.recv_queue||[]).length>0){wakeUp(1);return}}}else if((sock.recv_queue||[]).length>0){wakeUp(1);return}}const webSockets=PHPWASM.getAllWebSockets(sock);if(!webSockets.length){wakeUp(0);return}for(const ws of webSockets){if(events&POLLIN||events&POLLPRI){polls.push(PHPWASM.awaitData(ws));lookingFor.add("POLLIN")}if(events&POLLOUT){polls.push(PHPWASM.awaitConnection(ws));lookingFor.add("POLLOUT")}if(events&POLLHUP){polls.push(PHPWASM.awaitClose(ws));lookingFor.add("POLLHUP")}if(events&POLLERR||events&POLLNVAL){polls.push(PHPWASM.awaitError(ws));lookingFor.add("POLLERR")}}}if(polls.length===0){console.warn("Unsupported poll event "+events+", defaulting to setTimeout().");setTimeout((function(){wakeUp(0)}),timeout);return}const promises=polls.map((([promise])=>promise));const clearPolling=()=>polls.forEach((([,clear])=>clear()));let awaken=false;let timeoutId;Promise.race(promises).then((function(results){if(!awaken){awaken=true;wakeUp(1);if(timeoutId){clearTimeout(timeoutId)}clearPolling()}}));if(timeout!==-1){timeoutId=setTimeout((function(){if(!awaken){awaken=true;wakeUp(0);clearPolling()}}),timeout)}}))}function _wasm_setsockopt(socketd,level,optionName,optionValuePtr,optionLen){const optionValue=HEAPU8[optionValuePtr];const SOL_SOCKET=1;const SO_KEEPALIVE=9;const IPPROTO_TCP=6;const TCP_NODELAY=1;const isSupported=level===SOL_SOCKET&&optionName===SO_KEEPALIVE||level===IPPROTO_TCP&&optionName===TCP_NODELAY;if(!isSupported){console.warn(`Unsupported socket option: ${level}, ${optionName}, ${optionValue}`);return-1}const ws=PHPWASM.getAllWebSockets(socketd)[0];if(!ws){return-1}ws.setSocketOpt(level,optionName,optionValuePtr);return 0}function runAndAbortIfError(func){try{return func()}catch(e){abort(e)}}var Asyncify={instrumentWasmImports:function(imports){var importPatterns=[/^_dlopen_js$/,/^invoke_i$/,/^invoke_ii$/,/^invoke_iii$/,/^invoke_iiii$/,/^invoke_iiiii$/,/^invoke_iiiiii$/,/^invoke_iiiiiii$/,/^invoke_iiiiiiii$/,/^invoke_iiiiiiiiii$/,/^invoke_v$/,/^invoke_vi$/,/^invoke_vii$/,/^invoke_viidii$/,/^invoke_viii$/,/^invoke_viiii$/,/^invoke_viiiii$/,/^invoke_viiiiii$/,/^invoke_viiiiiii$/,/^invoke_viiiiiiiii$/,/^js_open_process$/,/^js_popen_to_file$/,/^js_fd_read$/,/^js_module_onMessage$/,/^js_waitpid$/,/^wasm_poll_socket$/,/^wasm_shutdown$/,/^fd_sync$/,/^__wasi_fd_sync$/,/^__asyncjs__.*$/,/^emscripten_promise_await$/,/^emscripten_idb_load$/,/^emscripten_idb_store$/,/^emscripten_idb_delete$/,/^emscripten_idb_exists$/,/^emscripten_idb_load_blob$/,/^emscripten_idb_store_blob$/,/^emscripten_sleep$/,/^emscripten_wget_data$/,/^emscripten_scan_registers$/,/^emscripten_lazy_load_code$/,/^_load_secondary_module$/,/^emscripten_fiber_swap$/,/^SDL_Delay$/];for(var x in imports){(function(x){var original=imports[x];var sig=original.sig;if(typeof original=="function"){var isAsyncifyImport=original.isAsync||importPatterns.some((pattern=>!!x.match(pattern)))}})(x)}},instrumentWasmExports:function(exports){var ret={};for(var x in exports){(function(x){var original=exports[x];if(typeof original=="function"){ret[x]=function(){Asyncify.exportCallStack.push(x);try{return original.apply(null,arguments)}finally{if(!ABORT){var y=Asyncify.exportCallStack.pop();assert(y===x);Asyncify.maybeStopUnwind()}}}}else{ret[x]=original}})(x)}return ret},State:{Normal:0,Unwinding:1,Rewinding:2,Disabled:3},state:0,StackSize:4096,currData:null,handleSleepReturnValue:0,exportCallStack:[],callStackNameToId:{},callStackIdToName:{},callStackId:0,asyncPromiseHandlers:null,sleepCallbacks:[],getCallStackId:function(funcName){var id=Asyncify.callStackNameToId[funcName];if(id===undefined){id=Asyncify.callStackId++;Asyncify.callStackNameToId[funcName]=id;Asyncify.callStackIdToName[id]=funcName}return id},maybeStopUnwind:function(){if(Asyncify.currData&&Asyncify.state===Asyncify.State.Unwinding&&Asyncify.exportCallStack.length===0){Asyncify.state=Asyncify.State.Normal;runtimeKeepalivePush();runAndAbortIfError(_asyncify_stop_unwind);if(typeof Fibers!="undefined"){Fibers.trampoline()}}},whenDone:function(){return new Promise(((resolve,reject)=>{Asyncify.asyncPromiseHandlers={resolve:resolve,reject:reject}}))},allocateData:function(){var ptr=_malloc(12+Asyncify.StackSize);Asyncify.setDataHeader(ptr,ptr+12,Asyncify.StackSize);Asyncify.setDataRewindFunc(ptr);return ptr},setDataHeader:function(ptr,stack,stackSize){HEAP32[ptr>>2]=stack;HEAP32[ptr+4>>2]=stack+stackSize},setDataRewindFunc:function(ptr){var bottomOfCallStack=Asyncify.exportCallStack[0];var rewindId=Asyncify.getCallStackId(bottomOfCallStack);HEAP32[ptr+8>>2]=rewindId},getDataRewindFunc:function(ptr){var id=HEAP32[ptr+8>>2];var name=Asyncify.callStackIdToName[id];var func=Module["asm"][name];return func},doRewind:function(ptr){var start=Asyncify.getDataRewindFunc(ptr);runtimeKeepalivePop();return start()},handleSleep:function(startAsync){if(ABORT)return;if(Asyncify.state===Asyncify.State.Normal){var reachedCallback=false;var reachedAfterCallback=false;startAsync(((handleSleepReturnValue=0)=>{if(ABORT)return;Asyncify.handleSleepReturnValue=handleSleepReturnValue;reachedCallback=true;if(!reachedAfterCallback){return}Asyncify.state=Asyncify.State.Rewinding;runAndAbortIfError((()=>_asyncify_start_rewind(Asyncify.currData)));if(typeof Browser!="undefined"&&Browser.mainLoop.func){Browser.mainLoop.resume()}var asyncWasmReturnValue,isError=false;try{asyncWasmReturnValue=Asyncify.doRewind(Asyncify.currData)}catch(err){asyncWasmReturnValue=err;isError=true}var handled=false;if(!Asyncify.currData){var asyncPromiseHandlers=Asyncify.asyncPromiseHandlers;if(asyncPromiseHandlers){Asyncify.asyncPromiseHandlers=null;(isError?asyncPromiseHandlers.reject:asyncPromiseHandlers.resolve)(asyncWasmReturnValue);handled=true}}if(isError&&!handled){throw asyncWasmReturnValue}}));reachedAfterCallback=true;if(!reachedCallback){Asyncify.state=Asyncify.State.Unwinding;Asyncify.currData=Asyncify.allocateData();if(typeof Browser!="undefined"&&Browser.mainLoop.func){Browser.mainLoop.pause()}runAndAbortIfError((()=>_asyncify_start_unwind(Asyncify.currData)))}}else if(Asyncify.state===Asyncify.State.Rewinding){Asyncify.state=Asyncify.State.Normal;runAndAbortIfError(_asyncify_stop_rewind);_free(Asyncify.currData);Asyncify.currData=null;Asyncify.sleepCallbacks.forEach((func=>callUserCallback(func)))}else{abort(`invalid state: ${Asyncify.state}`)}return Asyncify.handleSleepReturnValue},handleAsync:function(startAsync){return Asyncify.handleSleep((wakeUp=>{startAsync().then(wakeUp)}))}};function getCFunc(ident){var func=Module["_"+ident];return func}var ccall=function(ident,returnType,argTypes,args,opts){var toC={"string":str=>{var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=stringToUTF8OnStack(str)}return ret},"array":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;i0){return}preRun();if(runDependencies>0){return}function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout((function(){setTimeout((function(){Module["setStatus"]("")}),1);doRun()}),1)}else{doRun()}}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}run();
+}else if ("string" === typeof Module["websocket"]["url"]) {
+ url = Module['websocket']['url']; // Fetch runtime WebSocket URL config.
+ }
+ }
+
+ if (url === 'ws://' || url === 'wss://') { // Is the supplied URL config just a prefix, if so complete it.
+ var parts = addr.split('/');
+ url = url + parts[0] + ":" + port + "/" + parts.slice(1).join('/');
+ }
+
+ // Make the WebSocket subprotocol (Sec-WebSocket-Protocol) default to binary if no configuration is set.
+ var subProtocols = 'binary'; // The default value is 'binary'
+
+ if (runtimeConfig) {
+ if ('string' === typeof Module['websocket']['subprotocol']) {
+ subProtocols = Module['websocket']['subprotocol']; // Fetch runtime WebSocket subprotocol config.
+ }
+ }
+
+ // The default WebSocket options
+ var opts = undefined;
+
+ if (subProtocols !== 'null') {
+ // The regex trims the string (removes spaces at the beginning and end, then splits the string by
+ // , into an Array. Whitespace removal is important for Websockify and ws.
+ subProtocols = subProtocols.replace(/^ +| +$/g,"").split(/ *, */);
+
+ opts = subProtocols;
+ }
+
+ // some webservers (azure) does not support subprotocol header
+ if (runtimeConfig && null === Module['websocket']['subprotocol']) {
+ subProtocols = 'null';
+ opts = undefined;
+ }
+
+ // If node we use the ws library.
+ var WebSocketConstructor;
+ {
+ WebSocketConstructor = WebSocket;
+ }
+ if (Module['websocket']['decorator']) {WebSocketConstructor = Module['websocket']['decorator'](WebSocketConstructor);}ws = new WebSocketConstructor(url, opts);
+ ws.binaryType = 'arraybuffer';
+ } catch (e) {
+ throw new FS.ErrnoError(23);
+ }
+ }
+
+ var peer = {
+ addr,
+ port,
+ socket: ws,
+ dgram_send_queue: []
+ };
+
+ SOCKFS.websocket_sock_ops.addPeer(sock, peer);
+ SOCKFS.websocket_sock_ops.handlePeerEvents(sock, peer);
+
+ // if this is a bound dgram socket, send the port number first to allow
+ // us to override the ephemeral port reported to us by remotePort on the
+ // remote end.
+ if (sock.type === 2 && typeof sock.sport != 'undefined') {
+ peer.dgram_send_queue.push(new Uint8Array([
+ 255, 255, 255, 255,
+ 'p'.charCodeAt(0), 'o'.charCodeAt(0), 'r'.charCodeAt(0), 't'.charCodeAt(0),
+ ((sock.sport & 0xff00) >> 8) , (sock.sport & 0xff)
+ ]));
+ }
+
+ return peer;
+ },
+ getPeer(sock, addr, port) {
+ return sock.peers[addr + ':' + port];
+ },
+ addPeer(sock, peer) {
+ sock.peers[peer.addr + ':' + peer.port] = peer;
+ },
+ removePeer(sock, peer) {
+ delete sock.peers[peer.addr + ':' + peer.port];
+ },
+ handlePeerEvents(sock, peer) {
+ var first = true;
+
+ var handleOpen = function () {
+
+ Module['websocket'].emit('open', sock.stream.fd);
+
+ try {
+ var queued = peer.dgram_send_queue.shift();
+ while (queued) {
+ peer.socket.send(queued);
+ queued = peer.dgram_send_queue.shift();
+ }
+ } catch (e) {
+ // not much we can do here in the way of proper error handling as we've already
+ // lied and said this data was sent. shut it down.
+ peer.socket.close();
+ }
+ };
+
+ function handleMessage(data) {
+ if (typeof data == 'string') {
+ var encoder = new TextEncoder(); // should be utf-8
+ data = encoder.encode(data); // make a typed array from the string
+ } else {
+ assert(data.byteLength !== undefined); // must receive an ArrayBuffer
+ if (data.byteLength == 0) {
+ // An empty ArrayBuffer will emit a pseudo disconnect event
+ // as recv/recvmsg will return zero which indicates that a socket
+ // has performed a shutdown although the connection has not been disconnected yet.
+ return;
+ }
+ data = new Uint8Array(data); // make a typed array view on the array buffer
+ }
+
+ // if this is the port message, override the peer's port with it
+ var wasfirst = first;
+ first = false;
+ if (wasfirst &&
+ data.length === 10 &&
+ data[0] === 255 && data[1] === 255 && data[2] === 255 && data[3] === 255 &&
+ data[4] === 'p'.charCodeAt(0) && data[5] === 'o'.charCodeAt(0) && data[6] === 'r'.charCodeAt(0) && data[7] === 't'.charCodeAt(0)) {
+ // update the peer's port and it's key in the peer map
+ var newport = ((data[8] << 8) | data[9]);
+ SOCKFS.websocket_sock_ops.removePeer(sock, peer);
+ peer.port = newport;
+ SOCKFS.websocket_sock_ops.addPeer(sock, peer);
+ return;
+ }
+
+ sock.recv_queue.push({ addr: peer.addr, port: peer.port, data: data });
+ Module['websocket'].emit('message', sock.stream.fd);
+ };
+
+ if (ENVIRONMENT_IS_NODE) {
+ peer.socket.on('open', handleOpen);
+ peer.socket.on('message', function(data, isBinary) {
+ if (!isBinary) {
+ return;
+ }
+ handleMessage((new Uint8Array(data)).buffer); // copy from node Buffer -> ArrayBuffer
+ });
+ peer.socket.on('close', function() {
+ Module['websocket'].emit('close', sock.stream.fd);
+ });
+ peer.socket.on('error', function(error) {
+ // Although the ws library may pass errors that may be more descriptive than
+ // ECONNREFUSED they are not necessarily the expected error code e.g.
+ // ENOTFOUND on getaddrinfo seems to be node.js specific, so using ECONNREFUSED
+ // is still probably the most useful thing to do.
+ sock.error = 14; // Used in getsockopt for SOL_SOCKET/SO_ERROR test.
+ Module['websocket'].emit('error', [sock.stream.fd, sock.error, 'ECONNREFUSED: Connection refused']);
+ // don't throw
+ });
+ } else {
+ peer.socket.onopen = handleOpen;
+ peer.socket.onclose = function() {
+ Module['websocket'].emit('close', sock.stream.fd);
+ };
+ peer.socket.onmessage = function peer_socket_onmessage(event) {
+ handleMessage(event.data);
+ };
+ peer.socket.onerror = function(error) {
+ // The WebSocket spec only allows a 'simple event' to be thrown on error,
+ // so we only really know as much as ECONNREFUSED.
+ sock.error = 14; // Used in getsockopt for SOL_SOCKET/SO_ERROR test.
+ Module['websocket'].emit('error', [sock.stream.fd, sock.error, 'ECONNREFUSED: Connection refused']);
+ };
+ }
+ },
+ poll(sock) {
+ if (sock.type === 1 && sock.server) {
+ // listen sockets should only say they're available for reading
+ // if there are pending clients.
+ return sock.pending.length ? (64 | 1) : 0;
+ }
+
+ var mask = 0;
+ var dest = sock.type === 1 ? // we only care about the socket state for connection-based sockets
+ SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport) :
+ null;
+
+ if (sock.recv_queue.length ||
+ !dest || // connection-less sockets are always ready to read
+ (dest && dest.socket.readyState === dest.socket.CLOSING) ||
+ (dest && dest.socket.readyState === dest.socket.CLOSED)) { // let recv return 0 once closed
+ mask |= (64 | 1);
+ }
+
+ if (!dest || // connection-less sockets are always ready to write
+ (dest && dest.socket.readyState === dest.socket.OPEN)) {
+ mask |= 4;
+ }
+
+ if ((dest && dest.socket.readyState === dest.socket.CLOSING) ||
+ (dest && dest.socket.readyState === dest.socket.CLOSED)) {
+ mask |= 16;
+ }
+
+ return mask;
+ },
+ ioctl(sock, request, arg) {
+ switch (request) {
+ case 21531:
+ var bytes = 0;
+ if (sock.recv_queue.length) {
+ bytes = sock.recv_queue[0].data.length;
+ }
+ HEAP32[((arg)>>2)] = bytes;
+ return 0;
+ default:
+ return 28;
+ }
+ },
+ close(sock) {
+ // if we've spawned a listen server, close it
+ if (sock.server) {
+ try {
+ sock.server.close();
+ } catch (e) {
+ }
+ sock.server = null;
+ }
+ // close any peer connections
+ var peers = Object.keys(sock.peers);
+ for (var i = 0; i < peers.length; i++) {
+ var peer = sock.peers[peers[i]];
+ try {
+ peer.socket.close();
+ } catch (e) {
+ }
+ SOCKFS.websocket_sock_ops.removePeer(sock, peer);
+ }
+ return 0;
+ },
+ bind(sock, addr, port) {
+ if (typeof sock.saddr != 'undefined' || typeof sock.sport != 'undefined') {
+ throw new FS.ErrnoError(28); // already bound
+ }
+ sock.saddr = addr;
+ sock.sport = port;
+ // in order to emulate dgram sockets, we need to launch a listen server when
+ // binding on a connection-less socket
+ // note: this is only required on the server side
+ if (sock.type === 2) {
+ // close the existing server if it exists
+ if (sock.server) {
+ sock.server.close();
+ sock.server = null;
+ }
+ // swallow error operation not supported error that occurs when binding in the
+ // browser where this isn't supported
+ try {
+ sock.sock_ops.listen(sock, 0);
+ } catch (e) {
+ if (!(e.name === 'ErrnoError')) throw e;
+ if (e.errno !== 138) throw e;
+ }
+ }
+ },
+ connect(sock, addr, port) {
+ if (sock.server) {
+ throw new FS.ErrnoError(138);
+ }
+
+ // TODO autobind
+ // if (!sock.addr && sock.type == 2) {
+ // }
+
+ // early out if we're already connected / in the middle of connecting
+ if (typeof sock.daddr != 'undefined' && typeof sock.dport != 'undefined') {
+ var dest = SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport);
+ if (dest) {
+ if (dest.socket.readyState === dest.socket.CONNECTING) {
+ throw new FS.ErrnoError(7);
+ } else {
+ throw new FS.ErrnoError(30);
+ }
+ }
+ }
+
+ // add the socket to our peer list and set our
+ // destination address / port to match
+ var peer = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port);
+ sock.daddr = peer.addr;
+ sock.dport = peer.port;
+
+ // always "fail" in non-blocking mode
+ throw new FS.ErrnoError(26);
+ },
+ listen(sock, backlog) {
+ if (!ENVIRONMENT_IS_NODE) {
+ throw new FS.ErrnoError(138);
+ }
+ },
+ accept(listensock) {
+ if (!listensock.server || !listensock.pending.length) {
+ throw new FS.ErrnoError(28);
+ }
+ var newsock = listensock.pending.shift();
+ newsock.stream.flags = listensock.stream.flags;
+ return newsock;
+ },
+ getname(sock, peer) {
+ var addr, port;
+ if (peer) {
+ if (sock.daddr === undefined || sock.dport === undefined) {
+ throw new FS.ErrnoError(53);
+ }
+ addr = sock.daddr;
+ port = sock.dport;
+ } else {
+ // TODO saddr and sport will be set for bind()'d UDP sockets, but what
+ // should we be returning for TCP sockets that've been connect()'d?
+ addr = sock.saddr || 0;
+ port = sock.sport || 0;
+ }
+ return { addr, port };
+ },
+ sendmsg(sock, buffer, offset, length, addr, port) {
+ if (sock.type === 2) {
+ // connection-less sockets will honor the message address,
+ // and otherwise fall back to the bound destination address
+ if (addr === undefined || port === undefined) {
+ addr = sock.daddr;
+ port = sock.dport;
+ }
+ // if there was no address to fall back to, error out
+ if (addr === undefined || port === undefined) {
+ throw new FS.ErrnoError(17);
+ }
+ } else {
+ // connection-based sockets will only use the bound
+ addr = sock.daddr;
+ port = sock.dport;
+ }
+
+ // find the peer for the destination address
+ var dest = SOCKFS.websocket_sock_ops.getPeer(sock, addr, port);
+
+ // early out if not connected with a connection-based socket
+ if (sock.type === 1) {
+ if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) {
+ throw new FS.ErrnoError(53);
+ } else if (dest.socket.readyState === dest.socket.CONNECTING) {
+ throw new FS.ErrnoError(6);
+ }
+ }
+
+ // create a copy of the incoming data to send, as the WebSocket API
+ // doesn't work entirely with an ArrayBufferView, it'll just send
+ // the entire underlying buffer
+ if (ArrayBuffer.isView(buffer)) {
+ offset += buffer.byteOffset;
+ buffer = buffer.buffer;
+ }
+
+ var data;
+ data = buffer.slice(offset, offset + length);
+
+ // if we're emulating a connection-less dgram socket and don't have
+ // a cached connection, queue the buffer to send upon connect and
+ // lie, saying the data was sent now.
+ if (sock.type === 2) {
+ if (!dest || dest.socket.readyState !== dest.socket.OPEN) {
+ // if we're not connected, open a new connection
+ if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) {
+ dest = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port);
+ }
+ dest.dgram_send_queue.push(data);
+ return length;
+ }
+ }
+
+ try {
+ // send the actual data
+ dest.socket.send(data);
+ return length;
+ } catch (e) {
+ throw new FS.ErrnoError(28);
+ }
+ },
+ recvmsg(sock, length, flags) {
+ // http://pubs.opengroup.org/onlinepubs/7908799/xns/recvmsg.html
+ if (sock.type === 1 && sock.server) {
+ // tcp servers should not be recv()'ing on the listen socket
+ throw new FS.ErrnoError(53);
+ }
+
+ var queued = sock.recv_queue.shift();
+ if (!queued) {
+ if (sock.type === 1) {
+ var dest = SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport);
+
+ if (!dest) {
+ // if we have a destination address but are not connected, error out
+ throw new FS.ErrnoError(53);
+ }
+ if (dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) {
+ // return null if the socket has closed
+ return null;
+ }
+ // else, our socket is in a valid state but truly has nothing available
+ throw new FS.ErrnoError(6);
+ }
+ throw new FS.ErrnoError(6);
+ }
+
+ // queued.data will be an ArrayBuffer if it's unadulterated, but if it's
+ // requeued TCP data it'll be an ArrayBufferView
+ var queuedLength = queued.data.byteLength || queued.data.length;
+ var queuedOffset = queued.data.byteOffset || 0;
+ var queuedBuffer = queued.data.buffer || queued.data;
+ var bytesRead = Math.min(length, queuedLength);
+ var res = {
+ buffer: new Uint8Array(queuedBuffer, queuedOffset, bytesRead),
+ addr: queued.addr,
+ port: queued.port
+ };
+
+ // push back any unread data for TCP connections
+ if (flags&2) {bytesRead = 0;} if (sock.type === 1 && bytesRead < queuedLength) {
+ var bytesRemaining = queuedLength - bytesRead;
+ queued.data = new Uint8Array(queuedBuffer, queuedOffset + bytesRead, bytesRemaining);
+ sock.recv_queue.unshift(queued);
+ }
+
+ return res;
+ },
+ },
+ };
+
+ function getSocketFromFD(fd) {
+ var socket = SOCKFS.getSocket(fd);
+ if (!socket) throw new FS.ErrnoError(8);
+ return socket;
+ }
+
+ var setErrNo = (value) => {
+ HEAP32[((___errno_location())>>2)] = value;
+ return value;
+ };
+ var Sockets = {
+ BUFFER_SIZE:10240,
+ MAX_BUFFER_SIZE:10485760,
+ nextFd:1,
+ fds:{
+ },
+ nextport:1,
+ maxport:65535,
+ peer:null,
+ connections:{
+ },
+ portmap:{
+ },
+ localAddr:4261412874,
+ addrPool:[33554442,50331658,67108874,83886090,100663306,117440522,134217738,150994954,167772170,184549386,201326602,218103818,234881034],
+ };
+
+ var inetPton4 = (str) => {
+ var b = str.split('.');
+ for (var i = 0; i < 4; i++) {
+ var tmp = Number(b[i]);
+ if (isNaN(tmp)) return null;
+ b[i] = tmp;
+ }
+ return (b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24)) >>> 0;
+ };
+
+
+ /** @suppress {checkTypes} */
+ var jstoi_q = (str) => parseInt(str);
+ var inetPton6 = (str) => {
+ var words;
+ var w, offset, z, i;
+ /* http://home.deds.nl/~aeron/regex/ */
+ var valid6regx = /^((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\3)::|:\b|$))|(?!\2\3)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i
+ var parts = [];
+ if (!valid6regx.test(str)) {
+ return null;
+ }
+ if (str === "::") {
+ return [0, 0, 0, 0, 0, 0, 0, 0];
+ }
+ // Z placeholder to keep track of zeros when splitting the string on ":"
+ if (str.startsWith("::")) {
+ str = str.replace("::", "Z:"); // leading zeros case
+ } else {
+ str = str.replace("::", ":Z:");
+ }
+
+ if (str.indexOf(".") > 0) {
+ // parse IPv4 embedded stress
+ str = str.replace(new RegExp('[.]', 'g'), ":");
+ words = str.split(":");
+ words[words.length-4] = jstoi_q(words[words.length-4]) + jstoi_q(words[words.length-3])*256;
+ words[words.length-3] = jstoi_q(words[words.length-2]) + jstoi_q(words[words.length-1])*256;
+ words = words.slice(0, words.length-2);
+ } else {
+ words = str.split(":");
+ }
+
+ offset = 0; z = 0;
+ for (w=0; w < words.length; w++) {
+ if (typeof words[w] == 'string') {
+ if (words[w] === 'Z') {
+ // compressed zeros - write appropriate number of zero words
+ for (z = 0; z < (8 - words.length+1); z++) {
+ parts[w+z] = 0;
+ }
+ offset = z-1;
+ } else {
+ // parse hex to field to 16-bit value and write it in network byte-order
+ parts[w+offset] = _htons(parseInt(words[w],16));
+ }
+ } else {
+ // parsed IPv4 words
+ parts[w+offset] = words[w];
+ }
+ }
+ return [
+ (parts[1] << 16) | parts[0],
+ (parts[3] << 16) | parts[2],
+ (parts[5] << 16) | parts[4],
+ (parts[7] << 16) | parts[6]
+ ];
+ };
+
+
+ /** @param {number=} addrlen */
+ var writeSockaddr = (sa, family, addr, port, addrlen) => {
+ switch (family) {
+ case 2:
+ addr = inetPton4(addr);
+ zeroMemory(sa, 16);
+ if (addrlen) {
+ HEAP32[((addrlen)>>2)] = 16;
+ }
+ HEAP16[((sa)>>1)] = family;
+ HEAP32[(((sa)+(4))>>2)] = addr;
+ HEAP16[(((sa)+(2))>>1)] = _htons(port);
+ break;
+ case 10:
+ addr = inetPton6(addr);
+ zeroMemory(sa, 28);
+ if (addrlen) {
+ HEAP32[((addrlen)>>2)] = 28;
+ }
+ HEAP32[((sa)>>2)] = family;
+ HEAP32[(((sa)+(8))>>2)] = addr[0];
+ HEAP32[(((sa)+(12))>>2)] = addr[1];
+ HEAP32[(((sa)+(16))>>2)] = addr[2];
+ HEAP32[(((sa)+(20))>>2)] = addr[3];
+ HEAP16[(((sa)+(2))>>1)] = _htons(port);
+ break;
+ default:
+ return 5;
+ }
+ return 0;
+ };
+
+
+ var DNS = {
+ address_map:{
+ id:1,
+ addrs:{
+ },
+ names:{
+ },
+ },
+ lookup_name:(name) => {
+ // If the name is already a valid ipv4 / ipv6 address, don't generate a fake one.
+ var res = inetPton4(name);
+ if (res !== null) {
+ return name;
+ }
+ res = inetPton6(name);
+ if (res !== null) {
+ return name;
+ }
+
+ // See if this name is already mapped.
+ var addr;
+
+ if (DNS.address_map.addrs[name]) {
+ addr = DNS.address_map.addrs[name];
+ } else {
+ var id = DNS.address_map.id++;
+ assert(id < 65535, 'exceeded max address mappings of 65535');
+
+ addr = '172.29.' + (id & 0xff) + '.' + (id & 0xff00);
+
+ DNS.address_map.names[addr] = name;
+ DNS.address_map.addrs[name] = addr;
+ }
+
+ return addr;
+ },
+ lookup_addr:(addr) => {
+ if (DNS.address_map.names[addr]) {
+ return DNS.address_map.names[addr];
+ }
+
+ return null;
+ },
+ };
+
+ function ___syscall_accept4(fd, addr, addrlen, flags, d1, d2) {
+ try {
+
+ var sock = getSocketFromFD(fd);
+ var newsock = sock.sock_ops.accept(sock);
+ if (addr) {
+ var errno = writeSockaddr(addr, newsock.family, DNS.lookup_name(newsock.daddr), newsock.dport, addrlen);
+ }
+ return newsock.stream.fd;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+
+
+ var inetNtop4 = (addr) => {
+ return (addr & 0xff) + '.' + ((addr >> 8) & 0xff) + '.' + ((addr >> 16) & 0xff) + '.' + ((addr >> 24) & 0xff)
+ };
+
+
+ var inetNtop6 = (ints) => {
+ // ref: http://www.ietf.org/rfc/rfc2373.txt - section 2.5.4
+ // Format for IPv4 compatible and mapped 128-bit IPv6 Addresses
+ // 128-bits are split into eight 16-bit words
+ // stored in network byte order (big-endian)
+ // | 80 bits | 16 | 32 bits |
+ // +-----------------------------------------------------------------+
+ // | 10 bytes | 2 | 4 bytes |
+ // +--------------------------------------+--------------------------+
+ // + 5 words | 1 | 2 words |
+ // +--------------------------------------+--------------------------+
+ // |0000..............................0000|0000| IPv4 ADDRESS | (compatible)
+ // +--------------------------------------+----+---------------------+
+ // |0000..............................0000|FFFF| IPv4 ADDRESS | (mapped)
+ // +--------------------------------------+----+---------------------+
+ var str = "";
+ var word = 0;
+ var longest = 0;
+ var lastzero = 0;
+ var zstart = 0;
+ var len = 0;
+ var i = 0;
+ var parts = [
+ ints[0] & 0xffff,
+ (ints[0] >> 16),
+ ints[1] & 0xffff,
+ (ints[1] >> 16),
+ ints[2] & 0xffff,
+ (ints[2] >> 16),
+ ints[3] & 0xffff,
+ (ints[3] >> 16)
+ ];
+
+ // Handle IPv4-compatible, IPv4-mapped, loopback and any/unspecified addresses
+
+ var hasipv4 = true;
+ var v4part = "";
+ // check if the 10 high-order bytes are all zeros (first 5 words)
+ for (i = 0; i < 5; i++) {
+ if (parts[i] !== 0) { hasipv4 = false; break; }
+ }
+
+ if (hasipv4) {
+ // low-order 32-bits store an IPv4 address (bytes 13 to 16) (last 2 words)
+ v4part = inetNtop4(parts[6] | (parts[7] << 16));
+ // IPv4-mapped IPv6 address if 16-bit value (bytes 11 and 12) == 0xFFFF (6th word)
+ if (parts[5] === -1) {
+ str = "::ffff:";
+ str += v4part;
+ return str;
+ }
+ // IPv4-compatible IPv6 address if 16-bit value (bytes 11 and 12) == 0x0000 (6th word)
+ if (parts[5] === 0) {
+ str = "::";
+ //special case IPv6 addresses
+ if (v4part === "0.0.0.0") v4part = ""; // any/unspecified address
+ if (v4part === "0.0.0.1") v4part = "1";// loopback address
+ str += v4part;
+ return str;
+ }
+ }
+
+ // Handle all other IPv6 addresses
+
+ // first run to find the longest contiguous zero words
+ for (word = 0; word < 8; word++) {
+ if (parts[word] === 0) {
+ if (word - lastzero > 1) {
+ len = 0;
+ }
+ lastzero = word;
+ len++;
+ }
+ if (len > longest) {
+ longest = len;
+ zstart = word - longest + 1;
+ }
+ }
+
+ for (word = 0; word < 8; word++) {
+ if (longest > 1) {
+ // compress contiguous zeros - to produce "::"
+ if (parts[word] === 0 && word >= zstart && word < (zstart + longest) ) {
+ if (word === zstart) {
+ str += ":";
+ if (zstart === 0) str += ":"; //leading zeros case
+ }
+ continue;
+ }
+ }
+ // converts 16-bit words from big-endian to little-endian before converting to hex string
+ str += Number(_ntohs(parts[word] & 0xffff)).toString(16);
+ str += word < 7 ? ":" : "";
+ }
+ return str;
+ };
+
+ var readSockaddr = (sa, salen) => {
+ // family / port offsets are common to both sockaddr_in and sockaddr_in6
+ var family = HEAP16[((sa)>>1)];
+ var port = _ntohs(HEAPU16[(((sa)+(2))>>1)]);
+ var addr;
+
+ switch (family) {
+ case 2:
+ if (salen !== 16) {
+ return { errno: 28 };
+ }
+ addr = HEAP32[(((sa)+(4))>>2)];
+ addr = inetNtop4(addr);
+ break;
+ case 10:
+ if (salen !== 28) {
+ return { errno: 28 };
+ }
+ addr = [
+ HEAP32[(((sa)+(8))>>2)],
+ HEAP32[(((sa)+(12))>>2)],
+ HEAP32[(((sa)+(16))>>2)],
+ HEAP32[(((sa)+(20))>>2)]
+ ];
+ addr = inetNtop6(addr);
+ break;
+ default:
+ return { errno: 5 };
+ }
+
+ return { family: family, addr: addr, port: port };
+ };
+
+
+ /** @param {boolean=} allowNull */
+ function getSocketAddress(addrp, addrlen, allowNull) {
+ if (allowNull && addrp === 0) return null;
+ var info = readSockaddr(addrp, addrlen);
+ if (info.errno) throw new FS.ErrnoError(info.errno);
+ info.addr = DNS.lookup_addr(info.addr) || info.addr;
+ return info;
+ }
+
+ function ___syscall_bind(fd, addr, addrlen, d1, d2, d3) {
+ try {
+
+ var sock = getSocketFromFD(fd);
+ var info = getSocketAddress(addr, addrlen);
+ sock.sock_ops.bind(sock, info.addr, info.port);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+ function ___syscall_chdir(path) {
+ try {
+
+ path = SYSCALLS.getStr(path);
+ FS.chdir(path);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+ function ___syscall_chmod(path, mode) {
+ try {
+
+ path = SYSCALLS.getStr(path);
+ FS.chmod(path, mode);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+
+
+ function ___syscall_connect(fd, addr, addrlen, d1, d2, d3) {
+ try {
+
+ var sock = getSocketFromFD(fd);
+ var info = getSocketAddress(addr, addrlen);
+ sock.sock_ops.connect(sock, info.addr, info.port);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+ function ___syscall_dup(fd) {
+ try {
+
+ var old = SYSCALLS.getStreamFromFD(fd);
+ return FS.createStream(old).fd;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+ function ___syscall_dup3(fd, newfd, flags) {
+ try {
+
+ var old = SYSCALLS.getStreamFromFD(fd);
+ if (old.fd === newfd) return -28;
+ var existing = FS.getStream(newfd);
+ if (existing) FS.close(existing);
+ return FS.createStream(old, newfd).fd;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+ function ___syscall_faccessat(dirfd, path, amode, flags) {
+ try {
+
+ path = SYSCALLS.getStr(path);
+ path = SYSCALLS.calculateAt(dirfd, path);
+ if (amode & ~7) {
+ // need a valid mode
+ return -28;
+ }
+ var lookup = FS.lookupPath(path, { follow: true });
+ var 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;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+
+ function convertI32PairToI53Checked(lo, hi) {
+ return ((hi + 0x200000) >>> 0 < 0x400001 - !!lo) ? (lo >>> 0) + hi * 4294967296 : NaN;
+ }
+ function ___syscall_fallocate(fd,mode,offset_low, offset_high,len_low, len_high) {
+ var offset = convertI32PairToI53Checked(offset_low, offset_high);;
+ var len = convertI32PairToI53Checked(len_low, len_high);;
+
+
+ try {
+
+ if (isNaN(offset)) return 61;
+ var stream = SYSCALLS.getStreamFromFD(fd)
+ FS.allocate(stream, offset, len);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ ;
+ }
+
+ function ___syscall_fchmod(fd, mode) {
+ try {
+
+ FS.fchmod(fd, mode);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+ function ___syscall_fchown32(fd, owner, group) {
+ try {
+
+ FS.fchown(fd, owner, group);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+ function ___syscall_fchownat(dirfd, path, owner, group, flags) {
+ try {
+
+ path = SYSCALLS.getStr(path);
+ var nofollow = flags & 256;
+ flags = flags & (~256);
+ path = SYSCALLS.calculateAt(dirfd, path);
+ (nofollow ? FS.lchown : FS.chown)(path, owner, group);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+
+ function ___syscall_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.createStream(stream, 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 5:
+ /* case 5: 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 6:
+ case 7:
+ /* case 6: Currently in musl F_SETLK64 has same value as F_SETLK, so omitted to avoid duplicate case blocks. If that changes, uncomment this */
+ /* case 7: 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 fcntl() returns that, and we set errno ourselves.
+ setErrNo(28);
+ return -1;
+ default: {
+ return -28;
+ }
+ }
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+ function ___syscall_fdatasync(fd) {
+ try {
+
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ return 0; // we can't do anything synchronously; the in-memory FS is already synced to
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+ function ___syscall_fstat64(fd, buf) {
+ try {
+
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ return SYSCALLS.doStat(FS.stat, stream.path, buf);
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+
+ function ___syscall_ftruncate64(fd,length_low, length_high) {
+ var length = convertI32PairToI53Checked(length_low, length_high);;
+
+
+ try {
+
+ if (isNaN(length)) return 61;
+ FS.ftruncate(fd, length);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ ;
+ }
+
+
+ var stringToUTF8 = (str, outPtr, maxBytesToWrite) => {
+ return stringToUTF8Array(str, HEAPU8,outPtr, maxBytesToWrite);
+ };
+ Module['stringToUTF8'] = stringToUTF8;
+
+ function ___syscall_getcwd(buf, size) {
+ try {
+
+ if (size === 0) return -28;
+ var cwd = FS.cwd();
+ var cwdLengthInBytes = lengthBytesUTF8(cwd) + 1;
+ if (size < cwdLengthInBytes) return -68;
+ stringToUTF8(cwd, buf, size);
+ return cwdLengthInBytes;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+
+ function ___syscall_getdents64(fd, dirp, count) {
+ try {
+
+ var stream = SYSCALLS.getStreamFromFD(fd)
+ if (!stream.getdents) {
+ stream.getdents = FS.readdir(stream.path);
+ }
+
+ var struct_size = 280;
+ var pos = 0;
+ var off = FS.llseek(stream, 0, 1);
+
+ var idx = Math.floor(off / struct_size);
+
+ while (idx < stream.getdents.length && pos + struct_size <= count) {
+ var id;
+ var type;
+ var name = stream.getdents[idx];
+ if (name === '.') {
+ id = stream.node.id;
+ type = 4; // DT_DIR
+ }
+ else if (name === '..') {
+ var lookup = FS.lookupPath(stream.path, { parent: true });
+ id = lookup.node.id;
+ type = 4; // DT_DIR
+ }
+ else {
+ var child = FS.lookupNode(stream.node, name);
+ id = child.id;
+ type = FS.isChrdev(child.mode) ? 2 : // DT_CHR, character device.
+ FS.isDir(child.mode) ? 4 : // DT_DIR, directory.
+ FS.isLink(child.mode) ? 10 : // DT_LNK, symbolic link.
+ 8; // DT_REG, regular file.
+ }
+ (tempI64 = [id>>>0,(tempDouble=id,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[((dirp + pos)>>2)] = tempI64[0],HEAP32[(((dirp + pos)+(4))>>2)] = tempI64[1]);
+ (tempI64 = [(idx + 1) * struct_size>>>0,(tempDouble=(idx + 1) * struct_size,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((dirp + pos)+(8))>>2)] = tempI64[0],HEAP32[(((dirp + pos)+(12))>>2)] = tempI64[1]);
+ HEAP16[(((dirp + pos)+(16))>>1)] = 280;
+ HEAP8[(((dirp + pos)+(18))>>0)] = type;
+ stringToUTF8(name, dirp + pos + 19, 256);
+ pos += struct_size;
+ idx += 1;
+ }
+ FS.llseek(stream, idx * struct_size, 0);
+ return pos;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+
+
+
+ function ___syscall_getpeername(fd, addr, addrlen, d1, d2, d3) {
+ try {
+
+ var sock = getSocketFromFD(fd);
+ if (!sock.daddr) {
+ return -53; // The socket is not connected.
+ }
+ var errno = writeSockaddr(addr, sock.family, DNS.lookup_name(sock.daddr), sock.dport, addrlen);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+
+
+
+ function ___syscall_getsockname(fd, addr, addrlen, d1, d2, d3) {
+ try {
+
+ var sock = getSocketFromFD(fd);
+ // TODO: sock.saddr should never be undefined, see TODO in websocket_sock_ops.getname
+ var errno = writeSockaddr(addr, sock.family, DNS.lookup_name(sock.saddr || '0.0.0.0'), sock.sport, addrlen);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+
+ function ___syscall_getsockopt(fd, level, optname, optval, optlen, d1) {
+ try {
+
+ var sock = getSocketFromFD(fd);
+ // Minimal getsockopt aimed at resolving https://github.com/emscripten-core/emscripten/issues/2211
+ // so only supports SOL_SOCKET with SO_ERROR.
+ if (level === 1) {
+ if (optname === 4) {
+ HEAP32[((optval)>>2)] = sock.error;
+ HEAP32[((optlen)>>2)] = 4;
+ sock.error = null; // Clear the error (The SO_ERROR option obtains and then clears this field).
+ return 0;
+ }
+ }
+ return -50; // The option is unknown at the level indicated.
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+ function ___syscall_ioctl(fd, op, varargs) {
+ SYSCALLS.varargs = varargs;
+ try {
+
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ switch (op) {
+ case 21509: {
+ if (!stream.tty) return -59;
+ return 0;
+ }
+ case 21505: {
+ if (!stream.tty) return -59;
+ if (stream.tty.ops.ioctl_tcgets) {
+ var termios = stream.tty.ops.ioctl_tcgets(stream);
+ var argp = SYSCALLS.get();
+ HEAP32[((argp)>>2)] = termios.c_iflag || 0;
+ HEAP32[(((argp)+(4))>>2)] = termios.c_oflag || 0;
+ HEAP32[(((argp)+(8))>>2)] = termios.c_cflag || 0;
+ HEAP32[(((argp)+(12))>>2)] = termios.c_lflag || 0;
+ for (var i = 0; i < 32; i++) {
+ HEAP8[(((argp + i)+(17))>>0)] = termios.c_cc[i] || 0;
+ }
+ return 0;
+ }
+ return 0;
+ }
+ case 21510:
+ case 21511:
+ case 21512: {
+ if (!stream.tty) return -59;
+ return 0; // no-op, not actually adjusting terminal settings
+ }
+ case 21506:
+ case 21507:
+ case 21508: {
+ if (!stream.tty) return -59;
+ if (stream.tty.ops.ioctl_tcsets) {
+ var argp = SYSCALLS.get();
+ var c_iflag = HEAP32[((argp)>>2)];
+ var c_oflag = HEAP32[(((argp)+(4))>>2)];
+ var c_cflag = HEAP32[(((argp)+(8))>>2)];
+ var c_lflag = HEAP32[(((argp)+(12))>>2)];
+ var c_cc = []
+ for (var i = 0; i < 32; i++) {
+ c_cc.push(HEAP8[(((argp + i)+(17))>>0)]);
+ }
+ return stream.tty.ops.ioctl_tcsets(stream.tty, op, { c_iflag, c_oflag, c_cflag, c_lflag, c_cc });
+ }
+ 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;
+ if (stream.tty.ops.ioctl_tiocgwinsz) {
+ var winsize = stream.tty.ops.ioctl_tiocgwinsz(stream.tty);
+ var argp = SYSCALLS.get();
+ HEAP16[((argp)>>1)] = winsize[0];
+ HEAP16[(((argp)+(2))>>1)] = winsize[1];
+ }
+ 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;
+ }
+ case 21515: {
+ if (!stream.tty) return -59;
+ return 0;
+ }
+ default: return -28; // not supported
+ }
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+
+ function ___syscall_listen(fd, backlog) {
+ try {
+
+ var sock = getSocketFromFD(fd);
+ sock.sock_ops.listen(sock, backlog);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+ function ___syscall_lstat64(path, buf) {
+ try {
+
+ path = SYSCALLS.getStr(path);
+ return SYSCALLS.doStat(FS.lstat, path, buf);
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+ function ___syscall_mkdirat(dirfd, path, mode) {
+ try {
+
+ path = SYSCALLS.getStr(path);
+ path = SYSCALLS.calculateAt(dirfd, path);
+ // 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;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+ function ___syscall_newfstatat(dirfd, path, buf, flags) {
+ try {
+
+ path = SYSCALLS.getStr(path);
+ var nofollow = flags & 256;
+ var allowEmpty = flags & 4096;
+ flags = flags & (~6400);
+ path = SYSCALLS.calculateAt(dirfd, path, allowEmpty);
+ return SYSCALLS.doStat(nofollow ? FS.lstat : FS.stat, path, buf);
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+ function ___syscall_openat(dirfd, path, flags, varargs) {
+ SYSCALLS.varargs = varargs;
+ try {
+
+ path = SYSCALLS.getStr(path);
+ path = SYSCALLS.calculateAt(dirfd, path);
+ var mode = varargs ? SYSCALLS.get() : 0;
+ return FS.open(path, flags, mode).fd;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+ var PIPEFS = {
+ BUCKET_BUFFER_SIZE:8192,
+ mount(mount) {
+ // Do not pollute the real root directory or its child nodes with pipes
+ // Looks like it is OK to create another pseudo-root node not linked to the FS.root hierarchy this way
+ return FS.createNode(null, '/', 16384 | 511 /* 0777 */, 0);
+ },
+ createPipe() {
+ var pipe = {
+ buckets: [],
+ // refcnt 2 because pipe has a read end and a write end. We need to be
+ // able to read from the read end after write end is closed.
+ refcnt : 2,
+ };
+
+ pipe.buckets.push({
+ buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),
+ offset: 0,
+ roffset: 0
+ });
+
+ var rName = PIPEFS.nextname();
+ var wName = PIPEFS.nextname();
+ var rNode = FS.createNode(PIPEFS.root, rName, 4096, 0);
+ var wNode = FS.createNode(PIPEFS.root, wName, 4096, 0);
+
+ rNode.pipe = pipe;
+ wNode.pipe = pipe;
+
+ var readableStream = FS.createStream({
+ path: rName,
+ node: rNode,
+ flags: 0,
+ seekable: false,
+ stream_ops: PIPEFS.stream_ops
+ });
+ rNode.stream = readableStream;
+
+ var writableStream = FS.createStream({
+ path: wName,
+ node: wNode,
+ flags: 1,
+ seekable: false,
+ stream_ops: PIPEFS.stream_ops
+ });
+ wNode.stream = writableStream;
+
+ return {
+ readable_fd: readableStream.fd,
+ writable_fd: writableStream.fd
+ };
+ },
+ stream_ops:{
+ poll(stream) {
+ var pipe = stream.node.pipe;
+
+ if ((stream.flags & 2097155) === 1) {
+ return (256 | 4);
+ }
+ if (pipe.buckets.length > 0) {
+ for (var i = 0; i < pipe.buckets.length; i++) {
+ var bucket = pipe.buckets[i];
+ if (bucket.offset - bucket.roffset > 0) {
+ return (64 | 1);
+ }
+ }
+ }
+
+ return 0;
+ },
+ ioctl(stream, request, varargs) {
+ return 28;
+ },
+ fsync(stream) {
+ return 28;
+ },
+ read(stream, buffer, offset, length, position /* ignored */) {
+ var pipe = stream.node.pipe;
+ var currentLength = 0;
+
+ for (var i = 0; i < pipe.buckets.length; i++) {
+ var bucket = pipe.buckets[i];
+ currentLength += bucket.offset - bucket.roffset;
+ }
+
+ assert(buffer instanceof ArrayBuffer || ArrayBuffer.isView(buffer));
+ var data = buffer.subarray(offset, offset + length);
+
+ if (length <= 0) {
+ return 0;
+ }
+ if (currentLength == 0) {
+ // Behave as if the read end is always non-blocking
+ throw new FS.ErrnoError(6);
+ }
+ var toRead = Math.min(currentLength, length);
+
+ var totalRead = toRead;
+ var toRemove = 0;
+
+ for (var i = 0; i < pipe.buckets.length; i++) {
+ var currBucket = pipe.buckets[i];
+ var bucketSize = currBucket.offset - currBucket.roffset;
+
+ if (toRead <= bucketSize) {
+ var tmpSlice = currBucket.buffer.subarray(currBucket.roffset, currBucket.offset);
+ if (toRead < bucketSize) {
+ tmpSlice = tmpSlice.subarray(0, toRead);
+ currBucket.roffset += toRead;
+ } else {
+ toRemove++;
+ }
+ data.set(tmpSlice);
+ break;
+ } else {
+ var tmpSlice = currBucket.buffer.subarray(currBucket.roffset, currBucket.offset);
+ data.set(tmpSlice);
+ data = data.subarray(tmpSlice.byteLength);
+ toRead -= tmpSlice.byteLength;
+ toRemove++;
+ }
+ }
+
+ if (toRemove && toRemove == pipe.buckets.length) {
+ // Do not generate excessive garbage in use cases such as
+ // write several bytes, read everything, write several bytes, read everything...
+ toRemove--;
+ pipe.buckets[toRemove].offset = 0;
+ pipe.buckets[toRemove].roffset = 0;
+ }
+
+ pipe.buckets.splice(0, toRemove);
+
+ return totalRead;
+ },
+ write(stream, buffer, offset, length, position /* ignored */) {
+ var pipe = stream.node.pipe;
+
+ assert(buffer instanceof ArrayBuffer || ArrayBuffer.isView(buffer));
+ var data = buffer.subarray(offset, offset + length);
+
+ var dataLen = data.byteLength;
+ if (dataLen <= 0) {
+ return 0;
+ }
+
+ var currBucket = null;
+
+ if (pipe.buckets.length == 0) {
+ currBucket = {
+ buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),
+ offset: 0,
+ roffset: 0
+ };
+ pipe.buckets.push(currBucket);
+ } else {
+ currBucket = pipe.buckets[pipe.buckets.length - 1];
+ }
+
+ assert(currBucket.offset <= PIPEFS.BUCKET_BUFFER_SIZE);
+
+ var freeBytesInCurrBuffer = PIPEFS.BUCKET_BUFFER_SIZE - currBucket.offset;
+ if (freeBytesInCurrBuffer >= dataLen) {
+ currBucket.buffer.set(data, currBucket.offset);
+ currBucket.offset += dataLen;
+ return dataLen;
+ } else if (freeBytesInCurrBuffer > 0) {
+ currBucket.buffer.set(data.subarray(0, freeBytesInCurrBuffer), currBucket.offset);
+ currBucket.offset += freeBytesInCurrBuffer;
+ data = data.subarray(freeBytesInCurrBuffer, data.byteLength);
+ }
+
+ var numBuckets = (data.byteLength / PIPEFS.BUCKET_BUFFER_SIZE) | 0;
+ var remElements = data.byteLength % PIPEFS.BUCKET_BUFFER_SIZE;
+
+ for (var i = 0; i < numBuckets; i++) {
+ var newBucket = {
+ buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),
+ offset: PIPEFS.BUCKET_BUFFER_SIZE,
+ roffset: 0
+ };
+ pipe.buckets.push(newBucket);
+ newBucket.buffer.set(data.subarray(0, PIPEFS.BUCKET_BUFFER_SIZE));
+ data = data.subarray(PIPEFS.BUCKET_BUFFER_SIZE, data.byteLength);
+ }
+
+ if (remElements > 0) {
+ var newBucket = {
+ buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),
+ offset: data.byteLength,
+ roffset: 0
+ };
+ pipe.buckets.push(newBucket);
+ newBucket.buffer.set(data);
+ }
+
+ return dataLen;
+ },
+ close(stream) {
+ var pipe = stream.node.pipe;
+ pipe.refcnt--;
+ if (pipe.refcnt === 0) {
+ pipe.buckets = null;
+ }
+ },
+ },
+ nextname() {
+ if (!PIPEFS.nextname.current) {
+ PIPEFS.nextname.current = 0;
+ }
+ return 'pipe[' + (PIPEFS.nextname.current++) + ']';
+ },
+ };
+
+ function ___syscall_pipe(fdPtr) {
+ try {
+
+ if (fdPtr == 0) {
+ throw new FS.ErrnoError(21);
+ }
+
+ var res = PIPEFS.createPipe();
+
+ HEAP32[((fdPtr)>>2)] = res.readable_fd;
+ HEAP32[(((fdPtr)+(4))>>2)] = res.writable_fd;
+
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+ function ___syscall_poll(fds, nfds, timeout) {
+ try {
+
+ var nonzero = 0;
+ for (var i = 0; i < nfds; i++) {
+ var pollfd = fds + 8 * i;
+ var fd = HEAP32[((pollfd)>>2)];
+ var events = HEAP16[(((pollfd)+(4))>>1)];
+ var mask = 32;
+ var stream = FS.getStream(fd);
+ if (stream) {
+ mask = SYSCALLS.DEFAULT_POLLMASK;
+ if (stream.stream_ops?.poll) {
+ mask = stream.stream_ops.poll(stream, -1);
+ }
+ }
+ mask &= events | 8 | 16;
+ if (mask) nonzero++;
+ HEAP16[(((pollfd)+(6))>>1)] = mask;
+ }
+ return nonzero;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+
+
+ function ___syscall_readlinkat(dirfd, path, buf, bufsize) {
+ try {
+
+ path = SYSCALLS.getStr(path);
+ path = SYSCALLS.calculateAt(dirfd, path);
+ 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;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+
+
+
+ function ___syscall_recvfrom(fd, buf, len, flags, addr, addrlen) {
+ try {
+
+ var sock = getSocketFromFD(fd);
+ var msg = sock.sock_ops.recvmsg(sock, len, typeof flags !== "undefined" ? flags : 0);
+ if (!msg) return 0; // socket is closed
+ if (addr) {
+ var errno = writeSockaddr(addr, sock.family, DNS.lookup_name(msg.addr), msg.port, addrlen);
+ }
+ HEAPU8.set(msg.buffer, buf);
+ return msg.buffer.byteLength;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+ function ___syscall_renameat(olddirfd, oldpath, newdirfd, newpath) {
+ try {
+
+ oldpath = SYSCALLS.getStr(oldpath);
+ newpath = SYSCALLS.getStr(newpath);
+ oldpath = SYSCALLS.calculateAt(olddirfd, oldpath);
+ newpath = SYSCALLS.calculateAt(newdirfd, newpath);
+ FS.rename(oldpath, newpath);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+ function ___syscall_rmdir(path) {
+ try {
+
+ path = SYSCALLS.getStr(path);
+ FS.rmdir(path);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+
+
+ function ___syscall_sendto(fd, message, length, flags, addr, addr_len) {
+ try {
+
+ var sock = getSocketFromFD(fd);
+ var dest = getSocketAddress(addr, addr_len, true);
+ if (!dest) {
+ // send, no address provided
+ return FS.write(sock.stream, HEAP8,message, length);
+ }
+ // sendto an address
+ return sock.sock_ops.sendmsg(sock, HEAP8,message, length, dest.addr, dest.port);
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+
+ function ___syscall_socket(domain, type, protocol) {
+ try {
+
+ var sock = SOCKFS.createSocket(domain, type, protocol);
+ return sock.stream.fd;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+ function ___syscall_stat64(path, buf) {
+ try {
+
+ path = SYSCALLS.getStr(path);
+ return SYSCALLS.doStat(FS.stat, path, buf);
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+ function ___syscall_statfs64(path, size, buf) {
+ try {
+
+ path = SYSCALLS.getStr(path);
+ // NOTE: None of the constants here are true. We're just returning safe and
+ // sane values.
+ HEAP32[(((buf)+(4))>>2)] = 4096;
+ HEAP32[(((buf)+(40))>>2)] = 4096;
+ HEAP32[(((buf)+(8))>>2)] = 1000000;
+ HEAP32[(((buf)+(12))>>2)] = 500000;
+ HEAP32[(((buf)+(16))>>2)] = 500000;
+ HEAP32[(((buf)+(20))>>2)] = FS.nextInode;
+ HEAP32[(((buf)+(24))>>2)] = 1000000;
+ HEAP32[(((buf)+(28))>>2)] = 42;
+ HEAP32[(((buf)+(44))>>2)] = 2; // ST_NOSUID
+ HEAP32[(((buf)+(36))>>2)] = 255;
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+ function ___syscall_symlink(target, linkpath) {
+ try {
+
+ target = SYSCALLS.getStr(target);
+ linkpath = SYSCALLS.getStr(linkpath);
+ FS.symlink(target, linkpath);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+ function ___syscall_unlinkat(dirfd, path, flags) {
+ try {
+
+ path = SYSCALLS.getStr(path);
+ path = SYSCALLS.calculateAt(dirfd, path);
+ if (flags === 0) {
+ FS.unlink(path);
+ } else if (flags === 512) {
+ FS.rmdir(path);
+ } else {
+ abort('Invalid flags passed to unlinkat');
+ }
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+ function readI53FromI64(ptr) {
+ return HEAPU32[ptr>>2] + HEAP32[ptr+4>>2] * 4294967296;
+ }
+
+ function ___syscall_utimensat(dirfd, path, times, flags) {
+ try {
+
+ path = SYSCALLS.getStr(path);
+ path = SYSCALLS.calculateAt(dirfd, path, true);
+ if (!times) {
+ var atime = Date.now();
+ var mtime = atime;
+ } else {
+ var seconds = readI53FromI64(times);
+ var nanoseconds = HEAP32[(((times)+(8))>>2)];
+ atime = (seconds*1000) + (nanoseconds/(1000*1000));
+ times += 16;
+ seconds = readI53FromI64(times);
+ nanoseconds = HEAP32[(((times)+(8))>>2)];
+ mtime = (seconds*1000) + (nanoseconds/(1000*1000));
+ }
+ FS.utime(path, atime, mtime);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ }
+
+ var nowIsMonotonic = true;;
+ var __emscripten_get_now_is_monotonic = () => nowIsMonotonic;
+
+ var __emscripten_throw_longjmp = () => {
+ throw Infinity;
+ };
+
+ function __gmtime_js(time_low, time_high,tmPtr) {
+ var time = convertI32PairToI53Checked(time_low, time_high);;
+
+
+ var date = new Date(time * 1000);
+ HEAP32[((tmPtr)>>2)] = date.getUTCSeconds();
+ HEAP32[(((tmPtr)+(4))>>2)] = date.getUTCMinutes();
+ HEAP32[(((tmPtr)+(8))>>2)] = date.getUTCHours();
+ HEAP32[(((tmPtr)+(12))>>2)] = date.getUTCDate();
+ HEAP32[(((tmPtr)+(16))>>2)] = date.getUTCMonth();
+ HEAP32[(((tmPtr)+(20))>>2)] = date.getUTCFullYear()-1900;
+ HEAP32[(((tmPtr)+(24))>>2)] = date.getUTCDay();
+ var start = Date.UTC(date.getUTCFullYear(), 0, 1, 0, 0, 0, 0);
+ var yday = ((date.getTime() - start) / (1000 * 60 * 60 * 24))|0;
+ HEAP32[(((tmPtr)+(28))>>2)] = yday;
+ ;
+ }
+
+ var 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_REGULAR_CUMULATIVE = [0,31,59,90,120,151,181,212,243,273,304,334];
+ var 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;
+ };
+
+ function __localtime_js(time_low, time_high,tmPtr) {
+ var time = convertI32PairToI53Checked(time_low, time_high);;
+
+
+ var date = new Date(time*1000);
+ HEAP32[((tmPtr)>>2)] = date.getSeconds();
+ HEAP32[(((tmPtr)+(4))>>2)] = date.getMinutes();
+ HEAP32[(((tmPtr)+(8))>>2)] = date.getHours();
+ HEAP32[(((tmPtr)+(12))>>2)] = date.getDate();
+ HEAP32[(((tmPtr)+(16))>>2)] = date.getMonth();
+ HEAP32[(((tmPtr)+(20))>>2)] = date.getFullYear()-1900;
+ HEAP32[(((tmPtr)+(24))>>2)] = date.getDay();
+
+ var yday = ydayFromDate(date)|0;
+ HEAP32[(((tmPtr)+(28))>>2)] = yday;
+ HEAP32[(((tmPtr)+(36))>>2)] = -(date.getTimezoneOffset() * 60);
+
+ // Attention: DST is in December in South, and some regions don't have DST at all.
+ var start = new Date(date.getFullYear(), 0, 1);
+ var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset();
+ var winterOffset = start.getTimezoneOffset();
+ var dst = (summerOffset != winterOffset && date.getTimezoneOffset() == Math.min(winterOffset, summerOffset))|0;
+ HEAP32[(((tmPtr)+(32))>>2)] = dst;
+ ;
+ }
+
+
+
+ var __mktime_js = function(tmPtr) {
+
+ var ret = (() => {
+ var date = new Date(HEAP32[(((tmPtr)+(20))>>2)] + 1900,
+ HEAP32[(((tmPtr)+(16))>>2)],
+ HEAP32[(((tmPtr)+(12))>>2)],
+ HEAP32[(((tmPtr)+(8))>>2)],
+ HEAP32[(((tmPtr)+(4))>>2)],
+ HEAP32[((tmPtr)>>2)],
+ 0);
+
+ // There's an ambiguous hour when the time goes back; the tm_isdst field is
+ // used to disambiguate it. Date() basically guesses, so we fix it up if it
+ // guessed wrong, or fill in tm_isdst with the guess if it's -1.
+ var dst = HEAP32[(((tmPtr)+(32))>>2)];
+ var guessedOffset = date.getTimezoneOffset();
+ var start = new Date(date.getFullYear(), 0, 1);
+ var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset();
+ var winterOffset = start.getTimezoneOffset();
+ var dstOffset = Math.min(winterOffset, summerOffset); // DST is in December in South
+ if (dst < 0) {
+ // Attention: some regions don't have DST at all.
+ HEAP32[(((tmPtr)+(32))>>2)] = Number(summerOffset != winterOffset && dstOffset == guessedOffset);
+ } else if ((dst > 0) != (dstOffset == guessedOffset)) {
+ var nonDstOffset = Math.max(winterOffset, summerOffset);
+ var trueOffset = dst > 0 ? dstOffset : nonDstOffset;
+ // Don't try setMinutes(date.getMinutes() + ...) -- it's messed up.
+ date.setTime(date.getTime() + (trueOffset - guessedOffset)*60000);
+ }
+
+ HEAP32[(((tmPtr)+(24))>>2)] = date.getDay();
+ var yday = ydayFromDate(date)|0;
+ HEAP32[(((tmPtr)+(28))>>2)] = yday;
+ // To match expected behavior, update fields from date
+ HEAP32[((tmPtr)>>2)] = date.getSeconds();
+ HEAP32[(((tmPtr)+(4))>>2)] = date.getMinutes();
+ HEAP32[(((tmPtr)+(8))>>2)] = date.getHours();
+ HEAP32[(((tmPtr)+(12))>>2)] = date.getDate();
+ HEAP32[(((tmPtr)+(16))>>2)] = date.getMonth();
+ HEAP32[(((tmPtr)+(20))>>2)] = date.getYear();
+
+ return date.getTime() / 1000;
+ })();
+ return (setTempRet0((tempDouble=ret,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)), ret>>>0);
+ };
+
+
+
+
+
+
+ function __mmap_js(len,prot,flags,fd,offset_low, offset_high,allocated,addr) {
+ var offset = convertI32PairToI53Checked(offset_low, offset_high);;
+
+
+ try {
+
+ if (isNaN(offset)) return 61;
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ var res = FS.mmap(stream, len, offset, prot, flags);
+ var ptr = res.ptr;
+ HEAP32[((allocated)>>2)] = res.allocated;
+ HEAPU32[((addr)>>2)] = ptr;
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ ;
+ }
+
+
+
+
+ function __munmap_js(addr,len,prot,flags,fd,offset_low, offset_high) {
+ var offset = convertI32PairToI53Checked(offset_low, offset_high);;
+
+
+ try {
+
+ if (isNaN(offset)) return 61;
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ if (prot & 2) {
+ SYSCALLS.doMsync(addr, stream, len, flags, offset);
+ }
+ FS.munmap(stream);
+ // implicitly return 0
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return -e.errno;
+ }
+ ;
+ }
+
+ var timers = {
+ };
+
+ var handleException = (e) => {
+ // Certain exception types we do not treat as errors since they are used for
+ // internal control flow.
+ // 1. ExitStatus, which is thrown by exit()
+ // 2. "unwind", which is thrown by emscripten_unwind_to_js_event_loop() and others
+ // that wish to return to JS event loop.
+ if (e instanceof ExitStatus || e == 'unwind') {
+ return EXITSTATUS;
+ }
+ quit_(1, e);
+ };
+
+
+ var _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 */
+ var exitJS = (status, implicit) => {
+ EXITSTATUS = status;
+
+ if (!keepRuntimeAlive()) {
+ exitRuntime();
+ }
+
+ _proc_exit(status);
+ };
+ var _exit = exitJS;
+ Module['_exit'] = _exit;
+
+ var maybeExit = () => {
+ if (runtimeExited) {
+ return;
+ }
+ if (!keepRuntimeAlive()) {
+ try {
+ _exit(EXITSTATUS);
+ } catch (e) {
+ handleException(e);
+ }
+ }
+ };
+ var callUserCallback = (func) => {
+ if (runtimeExited || ABORT) {
+ return;
+ }
+ try {
+ func();
+ maybeExit();
+ } catch (e) {
+ handleException(e);
+ }
+ };
+
+
+ var _emscripten_get_now;
+ // Modern environment where performance.now() is supported:
+ // N.B. a shorter form "_emscripten_get_now = performance.now;" is
+ // unfortunately not allowed even in current browsers (e.g. FF Nightly 75).
+ _emscripten_get_now = () => performance.now();
+ ;
+ var __setitimer_js = (which, timeout_ms) => {
+ // First, clear any existing timer.
+ if (timers[which]) {
+ clearTimeout(timers[which].id);
+ delete timers[which];
+ }
+
+ // A timeout of zero simply cancels the current timeout so we have nothing
+ // more to do.
+ if (!timeout_ms) return 0;
+
+ var id = setTimeout(() => {
+ delete timers[which];
+ callUserCallback(() => __emscripten_timeout(which, _emscripten_get_now()));
+ }, timeout_ms);
+ timers[which] = { id, timeout_ms };
+ return 0;
+ };
+
+
+
+ var stringToNewUTF8 = (str) => {
+ var size = lengthBytesUTF8(str) + 1;
+ var ret = _malloc(size);
+ if (ret) stringToUTF8(str, ret, size);
+ return ret;
+ };
+ var __tzset_js = (timezone, daylight, tzname) => {
+ // TODO: Use (malleable) environment variables instead of system settings.
+ var currentYear = new Date().getFullYear();
+ var winter = new Date(currentYear, 0, 1);
+ var summer = new Date(currentYear, 6, 1);
+ var winterOffset = winter.getTimezoneOffset();
+ var summerOffset = summer.getTimezoneOffset();
+
+ // Local standard timezone offset. Local standard time is not adjusted for daylight savings.
+ // This code uses the fact that getTimezoneOffset returns a greater value during Standard Time versus Daylight Saving Time (DST).
+ // Thus it determines the expected output during Standard Time, and it compares whether the output of the given date the same (Standard) or less (DST).
+ var stdTimezoneOffset = Math.max(winterOffset, summerOffset);
+
+ // timezone is specified as seconds west of UTC ("The external variable
+ // `timezone` shall be set to the difference, in seconds, between
+ // Coordinated Universal Time (UTC) and local standard time."), the same
+ // as returned by stdTimezoneOffset.
+ // See http://pubs.opengroup.org/onlinepubs/009695399/functions/tzset.html
+ HEAPU32[((timezone)>>2)] = stdTimezoneOffset * 60;
+
+ HEAP32[((daylight)>>2)] = Number(winterOffset != summerOffset);
+
+ function extractZone(date) {
+ var match = date.toTimeString().match(/\(([A-Za-z ]+)\)$/);
+ return match ? match[1] : "GMT";
+ };
+ var winterName = extractZone(winter);
+ var summerName = extractZone(summer);
+ var winterNamePtr = stringToNewUTF8(winterName);
+ var summerNamePtr = stringToNewUTF8(summerName);
+ if (summerOffset < winterOffset) {
+ // Northern hemisphere
+ HEAPU32[((tzname)>>2)] = winterNamePtr;
+ HEAPU32[(((tzname)+(4))>>2)] = summerNamePtr;
+ } else {
+ HEAPU32[((tzname)>>2)] = summerNamePtr;
+ HEAPU32[(((tzname)+(4))>>2)] = winterNamePtr;
+ }
+ };
+
+ var _abort = () => {
+ abort('');
+ };
+
+ function _emscripten_date_now() {
+ return Date.now();
+ }
+
+ var getHeapMax = () =>
+ // Stay one Wasm page short of 4GB: while e.g. Chrome is able to allocate
+ // full 4GB Wasm memories, the size will wrap back to 0 bytes in Wasm side
+ // for any code that deals with heap sizes, which would require special
+ // casing all heap size related code to treat 0 specially.
+ 2147483648;
+ var _emscripten_get_heap_max = () => getHeapMax();
+
+
+ var _emscripten_memcpy_big = (dest, src, num) => HEAPU8.copyWithin(dest, src, src + num);
+
+
+ var growMemory = (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(pages); // .grow() takes a delta compared to the previous size
+ updateMemoryViews();
+ return 1 /*success*/;
+ } catch(e) {
+ }
+ // implicit 0 return to save code size (caller will cast "undefined" into 0
+ // anyhow)
+ };
+ var _emscripten_resize_heap = (requestedSize) => {
+ var oldSize = HEAPU8.length;
+ // With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned.
+ requestedSize >>>= 0;
+ // With multithreaded builds, races can happen (another thread might increase the size
+ // in between), so return a failure, and let the caller retry.
+
+ // Memory resize rules:
+ // 1. Always increase heap size to at least the requested size, rounded up
+ // to next page multiple.
+ // 2a. If MEMORY_GROWTH_LINEAR_STEP == -1, excessively resize the heap
+ // geometrically: increase the heap size according to
+ // MEMORY_GROWTH_GEOMETRIC_STEP factor (default +20%), At most
+ // overreserve by MEMORY_GROWTH_GEOMETRIC_CAP bytes (default 96MB).
+ // 2b. If MEMORY_GROWTH_LINEAR_STEP != -1, excessively resize the heap
+ // linearly: increase the heap size by at least
+ // MEMORY_GROWTH_LINEAR_STEP bytes.
+ // 3. Max size for the heap is capped at 2048MB-WASM_PAGE_SIZE, or by
+ // MAXIMUM_MEMORY, or by ASAN limit, depending on which is smallest
+ // 4. If we were unable to allocate as much memory, it may be due to
+ // over-eager decision to excessively reserve due to (3) above.
+ // Hence if an allocation fails, cut down on the amount of excess
+ // growth, in an attempt to succeed to perform a smaller allocation.
+
+ // A limit is set for how much we can grow. We should not exceed that
+ // (the wasm binary specifies it, so if we tried, we'd fail anyhow).
+ var maxHeapSize = getHeapMax();
+ if (requestedSize > maxHeapSize) {
+ return false;
+ }
+
+ 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
+ // smaller bump instead. (max 3 times, chosen somewhat arbitrarily)
+ for (var cutDown = 1; cutDown <= 4; cutDown *= 2) {
+ var overGrownHeapSize = oldSize * (1 + 0.2 / cutDown); // ensure geometric growth
+ // but limit overreserving (default to capping at +96MB overgrowth at most)
+ overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296 );
+
+ var newSize = Math.min(maxHeapSize, alignUp(Math.max(requestedSize, overGrownHeapSize), 65536));
+
+ var replacement = growMemory(newSize);
+ if (replacement) {
+
+ return true;
+ }
+ }
+ return false;
+ };
+
+
+ var runtimeKeepalivePush = () => {
+ runtimeKeepaliveCounter += 1;
+ };
+
+ var runtimeKeepalivePop = () => {
+ runtimeKeepaliveCounter -= 1;
+ };
+ /** @param {number=} timeout */
+ var safeSetTimeout = (func, timeout) => {
+ runtimeKeepalivePush();
+ return setTimeout(() => {
+ runtimeKeepalivePop();
+ callUserCallback(func);
+ }, timeout);
+ };
+ var _emscripten_sleep = function(ms) {
+ // emscripten_sleep() does not return a value, but we still need a |return|
+ // here for stack switching support (ASYNCIFY=2). In that mode this function
+ // returns a Promise instead of nothing, and that Promise is what tells the
+ // wasm VM to pause the stack.
+ return Asyncify.handleSleep((wakeUp) => safeSetTimeout(wakeUp, ms));
+ };
+ Module['_emscripten_sleep'] = _emscripten_sleep;
+ _emscripten_sleep.isAsync = true;
+
+ var ENV = PHPLoader.ENV || {
+ };
+
+ var getExecutableName = () => {
+ return thisProgram || './this.program';
+ };
+ var 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) {
+ // x is a key in ENV; if ENV[x] is undefined, that means it was
+ // explicitly set to be so. We allow user code to do that to
+ // force variables with default values to remain unset.
+ if (ENV[x] === undefined) delete env[x];
+ else env[x] = ENV[x];
+ }
+ var strings = [];
+ for (var x in env) {
+ strings.push(`${x}=${env[x]}`);
+ }
+ getEnvStrings.strings = strings;
+ }
+ return getEnvStrings.strings;
+ };
+
+ var stringToAscii = (str, buffer) => {
+ for (var i = 0; i < str.length; ++i) {
+ HEAP8[((buffer++)>>0)] = str.charCodeAt(i);
+ }
+ // Null-terminate the string
+ HEAP8[((buffer)>>0)] = 0;
+ };
+
+ var _environ_get = (__environ, environ_buf) => {
+ var bufSize = 0;
+ getEnvStrings().forEach(function(string, i) {
+ var ptr = environ_buf + bufSize;
+ HEAPU32[(((__environ)+(i*4))>>2)] = ptr;
+ stringToAscii(string, ptr);
+ bufSize += string.length + 1;
+ });
+ return 0;
+ };
+
+
+ var _environ_sizes_get = (penviron_count, penviron_buf_size) => {
+ var strings = getEnvStrings();
+ HEAPU32[((penviron_count)>>2)] = strings.length;
+ var bufSize = 0;
+ strings.forEach(function(string) {
+ bufSize += string.length + 1;
+ });
+ HEAPU32[((penviron_buf_size)>>2)] = bufSize;
+ return 0;
+ };
+
+
+ function _fd_close(fd) {
+ try {
+
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ FS.close(stream);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return e.errno;
+ }
+ }
+
+ function _fd_fdstat_get(fd, pbuf) {
+ try {
+
+ var rightsBase = 0;
+ var rightsInheriting = 0;
+ var flags = 0;
+ {
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ // All character devices are terminals (other things a Linux system would
+ // assume is a character device, like the mouse, we have special APIs for).
+ var type = stream.tty ? 2 :
+ FS.isDir(stream.mode) ? 3 :
+ FS.isLink(stream.mode) ? 7 :
+ 4;
+ }
+ HEAP8[((pbuf)>>0)] = type;
+ HEAP16[(((pbuf)+(2))>>1)] = flags;
+ (tempI64 = [rightsBase>>>0,(tempDouble=rightsBase,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((pbuf)+(8))>>2)] = tempI64[0],HEAP32[(((pbuf)+(12))>>2)] = tempI64[1]);
+ (tempI64 = [rightsInheriting>>>0,(tempDouble=rightsInheriting,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((pbuf)+(16))>>2)] = tempI64[0],HEAP32[(((pbuf)+(20))>>2)] = tempI64[1]);
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return e.errno;
+ }
+ }
+
+ /** @param {number=} offset */
+ var doReadv = (stream, iov, iovcnt, offset) => {
+ var ret = 0;
+ for (var i = 0; i < iovcnt; i++) {
+ var ptr = HEAPU32[((iov)>>2)];
+ var len = HEAPU32[(((iov)+(4))>>2)];
+ iov += 8;
+ var curr = FS.read(stream, HEAP8,ptr, len, offset);
+ if (curr < 0) return -1;
+ ret += curr;
+ if (curr < len) break; // nothing more to read
+ if (typeof offset !== 'undefined') {
+ offset += curr;
+ }
+ }
+ return ret;
+ };
+
+ function _fd_read(fd, iov, iovcnt, pnum) {
+ try {
+
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ var num = doReadv(stream, iov, iovcnt);
+ HEAPU32[((pnum)>>2)] = num;
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return e.errno;
+ }
+ }
+
+
+ function _fd_seek(fd,offset_low, offset_high,whence,newOffset) {
+ var offset = convertI32PairToI53Checked(offset_low, offset_high);;
+
+
+ try {
+
+ if (isNaN(offset)) return 61;
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ FS.llseek(stream, offset, whence);
+ (tempI64 = [stream.position>>>0,(tempDouble=stream.position,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.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.name === 'ErrnoError')) throw e;
+ return e.errno;
+ }
+ ;
+ }
+
+ function _fd_sync(fd) {
+ try {
+
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ return Asyncify.handleSleep(function(wakeUp) {
+ var mount = stream.node.mount;
+ if (!mount.type.syncfs) {
+ // We write directly to the file system, so there's nothing to do here.
+ wakeUp(0);
+ return;
+ }
+ mount.type.syncfs(mount, false, function(err) {
+ if (err) {
+ wakeUp(function() { return 29 });
+ return;
+ }
+ wakeUp(0);
+ });
+ });
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return e.errno;
+ }
+ }
+
+ /** @param {number=} offset */
+ var doWritev = (stream, iov, iovcnt, offset) => {
+ var ret = 0;
+ for (var i = 0; i < iovcnt; i++) {
+ var ptr = HEAPU32[((iov)>>2)];
+ var len = HEAPU32[(((iov)+(4))>>2)];
+ iov += 8;
+ var curr = FS.write(stream, HEAP8,ptr, len, offset);
+ if (curr < 0) return -1;
+ ret += curr;
+ if (typeof offset !== 'undefined') {
+ offset += curr;
+ }
+ }
+ return ret;
+ };
+
+ function _fd_write(fd, iov, iovcnt, pnum) {
+ try {
+
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ var num = doWritev(stream, iov, iovcnt);
+ HEAPU32[((pnum)>>2)] = num;
+ return 0;
+ } catch (e) {
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
+ return e.errno;
+ }
+ }
+
+
+
+
+
+
+
+
+
+
+ var _getaddrinfo = (node, service, hint, out) => {
+ // Note getaddrinfo currently only returns a single addrinfo with ai_next defaulting to NULL. When NULL
+ // hints are specified or ai_family set to AF_UNSPEC or ai_socktype or ai_protocol set to 0 then we
+ // really should provide a linked list of suitable addrinfo values.
+ var addrs = [];
+ var canon = null;
+ var addr = 0;
+ var port = 0;
+ var flags = 0;
+ var family = 0;
+ var type = 0;
+ var proto = 0;
+ var ai, last;
+
+ function allocaddrinfo(family, type, proto, canon, addr, port) {
+ var sa, salen, ai;
+ var errno;
+
+ salen = family === 10 ?
+ 28 :
+ 16;
+ addr = family === 10 ?
+ inetNtop6(addr) :
+ inetNtop4(addr);
+ sa = _malloc(salen);
+ errno = writeSockaddr(sa, family, addr, port);
+ assert(!errno);
+
+ ai = _malloc(32);
+ HEAP32[(((ai)+(4))>>2)] = family;
+ HEAP32[(((ai)+(8))>>2)] = type;
+ HEAP32[(((ai)+(12))>>2)] = proto;
+ HEAPU32[(((ai)+(24))>>2)] = canon;
+ HEAPU32[(((ai)+(20))>>2)] = sa;
+ if (family === 10) {
+ HEAP32[(((ai)+(16))>>2)] = 28;
+ } else {
+ HEAP32[(((ai)+(16))>>2)] = 16;
+ }
+ HEAP32[(((ai)+(28))>>2)] = 0;
+
+ return ai;
+ }
+
+ if (hint) {
+ flags = HEAP32[((hint)>>2)];
+ family = HEAP32[(((hint)+(4))>>2)];
+ type = HEAP32[(((hint)+(8))>>2)];
+ proto = HEAP32[(((hint)+(12))>>2)];
+ }
+ if (type && !proto) {
+ proto = type === 2 ? 17 : 6;
+ }
+ if (!type && proto) {
+ type = proto === 17 ? 2 : 1;
+ }
+
+ // If type or proto are set to zero in hints we should really be returning multiple addrinfo values, but for
+ // now default to a TCP STREAM socket so we can at least return a sensible addrinfo given NULL hints.
+ if (proto === 0) {
+ proto = 6;
+ }
+ if (type === 0) {
+ type = 1;
+ }
+
+ if (!node && !service) {
+ return -2;
+ }
+ if (flags & ~(1|2|4|
+ 1024|8|16|32)) {
+ return -1;
+ }
+ if (hint !== 0 && (HEAP32[((hint)>>2)] & 2) && !node) {
+ return -1;
+ }
+ if (flags & 32) {
+ // TODO
+ return -2;
+ }
+ if (type !== 0 && type !== 1 && type !== 2) {
+ return -7;
+ }
+ if (family !== 0 && family !== 2 && family !== 10) {
+ return -6;
+ }
+
+ if (service) {
+ service = UTF8ToString(service);
+ port = parseInt(service, 10);
+
+ if (isNaN(port)) {
+ if (flags & 1024) {
+ return -2;
+ }
+ // TODO support resolving well-known service names from:
+ // http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.txt
+ return -8;
+ }
+ }
+
+ if (!node) {
+ if (family === 0) {
+ family = 2;
+ }
+ if ((flags & 1) === 0) {
+ if (family === 2) {
+ addr = _htonl(2130706433);
+ } else {
+ addr = [0, 0, 0, 1];
+ }
+ }
+ ai = allocaddrinfo(family, type, proto, null, addr, port);
+ HEAPU32[((out)>>2)] = ai;
+ return 0;
+ }
+
+ //
+ // try as a numeric address
+ //
+ node = UTF8ToString(node);
+ addr = inetPton4(node);
+ if (addr !== null) {
+ // incoming node is a valid ipv4 address
+ if (family === 0 || family === 2) {
+ family = 2;
+ }
+ else if (family === 10 && (flags & 8)) {
+ addr = [0, 0, _htonl(0xffff), addr];
+ family = 10;
+ } else {
+ return -2;
+ }
+ } else {
+ addr = inetPton6(node);
+ if (addr !== null) {
+ // incoming node is a valid ipv6 address
+ if (family === 0 || family === 10) {
+ family = 10;
+ } else {
+ return -2;
+ }
+ }
+ }
+ if (addr != null) {
+ ai = allocaddrinfo(family, type, proto, node, addr, port);
+ HEAPU32[((out)>>2)] = ai;
+ return 0;
+ }
+ if (flags & 4) {
+ return -2;
+ }
+
+ //
+ // try as a hostname
+ //
+ // resolve the hostname to a temporary fake address
+ node = DNS.lookup_name(node);
+ addr = inetPton4(node);
+ if (family === 0) {
+ family = 2;
+ } else if (family === 10) {
+ addr = [0, 0, _htonl(0xffff), addr];
+ }
+ ai = allocaddrinfo(family, type, proto, null, addr, port);
+ HEAPU32[((out)>>2)] = ai;
+ return 0;
+ };
+
+ /** @type {function(...*):?} */
+ function _getcontext(
+ ) {
+ err('missing function: getcontext'); abort(-1);
+ }
+
+ /** @type {function(...*):?} */
+ function _getdtablesize(
+ ) {
+ err('missing function: getdtablesize'); abort(-1);
+ }
+
+
+
+
+ var getHostByName = (name) => {
+ // generate hostent
+ var ret = _malloc(20); // XXX possibly leaked, as are others here
+ var nameBuf = stringToNewUTF8(name);
+ HEAPU32[((ret)>>2)] = nameBuf;
+ var aliasesBuf = _malloc(4);
+ HEAPU32[((aliasesBuf)>>2)] = 0;
+ HEAPU32[(((ret)+(4))>>2)] = aliasesBuf;
+ var afinet = 2;
+ HEAP32[(((ret)+(8))>>2)] = afinet;
+ HEAP32[(((ret)+(12))>>2)] = 4;
+ var addrListBuf = _malloc(12);
+ HEAPU32[((addrListBuf)>>2)] = addrListBuf+8;
+ HEAPU32[(((addrListBuf)+(4))>>2)] = 0;
+ HEAP32[(((addrListBuf)+(8))>>2)] = inetPton4(DNS.lookup_name(name));
+ HEAPU32[(((ret)+(16))>>2)] = addrListBuf;
+ return ret;
+ };
+
+ var _gethostbyname = (name) => {
+ return getHostByName(UTF8ToString(name));
+ };
+
+
+ var _gethostbyname_r = (name, ret, buf, buflen, out, err) => {
+ var data = _gethostbyname(name);
+ _memcpy(ret, data, 20);
+ _free(data);
+ HEAP32[((err)>>2)] = 0;
+ HEAPU32[((out)>>2)] = ret;
+ return 0;
+ };
+
+ var _getloadavg = (loadavg, nelem) => {
+ // int getloadavg(double loadavg[], int nelem);
+ // http://linux.die.net/man/3/getloadavg
+ var limit = Math.min(nelem, 3);
+ var doubleSize = 8;
+ for (var i = 0; i < limit; i++) {
+ HEAPF64[(((loadavg)+(i * doubleSize))>>3)] = 0.1;
+ }
+ return limit;
+ };
+
+
+
+
+ var _getnameinfo = (sa, salen, node, nodelen, serv, servlen, flags) => {
+ var info = readSockaddr(sa, salen);
+ if (info.errno) {
+ return -6;
+ }
+ var port = info.port;
+ var addr = info.addr;
+
+ var overflowed = false;
+
+ if (node && nodelen) {
+ var lookup;
+ if ((flags & 1) || !(lookup = DNS.lookup_addr(addr))) {
+ if (flags & 8) {
+ return -2;
+ }
+ } else {
+ addr = lookup;
+ }
+ var numBytesWrittenExclNull = stringToUTF8(addr, node, nodelen);
+
+ if (numBytesWrittenExclNull+1 >= nodelen) {
+ overflowed = true;
+ }
+ }
+
+ if (serv && servlen) {
+ port = '' + port;
+ var numBytesWrittenExclNull = stringToUTF8(port, serv, servlen);
+
+ if (numBytesWrittenExclNull+1 >= servlen) {
+ overflowed = true;
+ }
+ }
+
+ if (overflowed) {
+ // Note: even when we overflow, getnameinfo() is specced to write out the truncated results.
+ return -12;
+ }
+
+ return 0;
+ };
+
+ var Protocols = {
+ list:[],
+ map:{
+ },
+ };
+
+
+ var _setprotoent = (stayopen) => {
+ // void setprotoent(int stayopen);
+
+ // Allocate and populate a protoent structure given a name, protocol number and array of aliases
+ function allocprotoent(name, proto, aliases) {
+ // write name into buffer
+ var nameBuf = _malloc(name.length + 1);
+ stringToAscii(name, nameBuf);
+
+ // write aliases into buffer
+ var j = 0;
+ var length = aliases.length;
+ var aliasListBuf = _malloc((length + 1) * 4); // Use length + 1 so we have space for the terminating NULL ptr.
+
+ for (var i = 0; i < length; i++, j += 4) {
+ var alias = aliases[i];
+ var aliasBuf = _malloc(alias.length + 1);
+ stringToAscii(alias, aliasBuf);
+ HEAPU32[(((aliasListBuf)+(j))>>2)] = aliasBuf;
+ }
+ HEAPU32[(((aliasListBuf)+(j))>>2)] = 0; // Terminating NULL pointer.
+
+ // generate protoent
+ var pe = _malloc(12);
+ HEAPU32[((pe)>>2)] = nameBuf;
+ HEAPU32[(((pe)+(4))>>2)] = aliasListBuf;
+ HEAP32[(((pe)+(8))>>2)] = proto;
+ return pe;
+ };
+
+ // Populate the protocol 'database'. The entries are limited to tcp and udp, though it is fairly trivial
+ // to add extra entries from /etc/protocols if desired - though not sure if that'd actually be useful.
+ var list = Protocols.list;
+ var map = Protocols.map;
+ if (list.length === 0) {
+ var entry = allocprotoent('tcp', 6, ['TCP']);
+ list.push(entry);
+ map['tcp'] = map['6'] = entry;
+ entry = allocprotoent('udp', 17, ['UDP']);
+ list.push(entry);
+ map['udp'] = map['17'] = entry;
+ }
+
+ _setprotoent.index = 0;
+ };
+
+
+ var _getprotobyname = (name) => {
+ // struct protoent *getprotobyname(const char *);
+ name = UTF8ToString(name);
+ _setprotoent(true);
+ var result = Protocols.map[name];
+ return result;
+ };
+
+
+ var _getprotobynumber = (number) => {
+ // struct protoent *getprotobynumber(int proto);
+ _setprotoent(true);
+ var result = Protocols.map[number];
+ return result;
+ };
+
+
+ /** @suppress {duplicate } */
+ var stringToUTF8OnStack = (str) => {
+ var size = lengthBytesUTF8(str) + 1;
+ var ret = stackAlloc(size);
+ stringToUTF8(str, ret, size);
+ return ret;
+ };
+ var allocateUTF8OnStack = stringToUTF8OnStack;
+
+ var PHPWASM = {
+ init:function () {
+ PHPWASM.EventEmitter = ENVIRONMENT_IS_NODE
+ ? require('events').EventEmitter
+ : class EventEmitter {
+ constructor() {
+ this.listeners = {};
+ }
+ emit(eventName, data) {
+ if (this.listeners[eventName]) {
+ this.listeners[eventName].forEach(
+ (callback) => {
+ callback(data);
+ }
+ );
+ }
+ }
+ once(eventName, callback) {
+ const self = this;
+ function removedCallback() {
+ callback(...arguments);
+ self.removeListener(eventName, removedCallback);
+ }
+ this.on(eventName, removedCallback);
+ }
+ removeAllListeners(eventName) {
+ if (eventName) {
+ delete this.listeners[eventName];
+ } else {
+ this.listeners = {};
+ }
+ }
+ removeListener(eventName, callback) {
+ if (this.listeners[eventName]) {
+ const idx =
+ this.listeners[eventName].indexOf(callback);
+ if (idx !== -1) {
+ this.listeners[eventName].splice(idx, 1);
+ }
+ }
+ }
+ };
+ PHPWASM.child_proc_by_fd = {};
+ PHPWASM.child_proc_by_pid = {};
+ PHPWASM.input_devices = {};
+ },
+ getAllWebSockets:function (sock) {
+ const webSockets = /* @__PURE__ */ new Set();
+ if (sock.server) {
+ sock.server.clients.forEach((ws) => {
+ webSockets.add(ws);
+ });
+ }
+ for (const peer of PHPWASM.getAllPeers(sock)) {
+ webSockets.add(peer.socket);
+ }
+ return Array.from(webSockets);
+ },
+ getAllPeers:function (sock) {
+ const peers = new Set();
+ if (sock.server) {
+ sock.pending
+ .filter((pending) => pending.peers)
+ .forEach((pending) => {
+ for (const peer of Object.values(pending.peers)) {
+ peers.add(peer);
+ }
+ });
+ }
+ if (sock.peers) {
+ for (const peer of Object.values(sock.peers)) {
+ peers.add(peer);
+ }
+ }
+ return Array.from(peers);
+ },
+ awaitData:function (ws) {
+ return PHPWASM.awaitEvent(ws, 'message');
+ },
+ awaitConnection:function (ws) {
+ if (ws.OPEN === ws.readyState) {
+ return [Promise.resolve(), PHPWASM.noop];
+ }
+ return PHPWASM.awaitEvent(ws, 'open');
+ },
+ awaitClose:function (ws) {
+ if ([ws.CLOSING, ws.CLOSED].includes(ws.readyState)) {
+ return [Promise.resolve(), PHPWASM.noop];
+ }
+ return PHPWASM.awaitEvent(ws, 'close');
+ },
+ awaitError:function (ws) {
+ if ([ws.CLOSING, ws.CLOSED].includes(ws.readyState)) {
+ return [Promise.resolve(), PHPWASM.noop];
+ }
+ return PHPWASM.awaitEvent(ws, 'error');
+ },
+ awaitEvent:function (ws, event) {
+ let resolve;
+ const listener = () => {
+ resolve();
+ };
+ const promise = new Promise(function (_resolve) {
+ resolve = _resolve;
+ ws.once(event, listener);
+ });
+ const cancel = () => {
+ ws.removeListener(event, listener);
+ // Rejecting the promises bubbles up and kills the entire
+ // node process. Let's resolve them on the next tick instead
+ // to give the caller some space to unbind any handlers.
+ setTimeout(resolve);
+ };
+ return [promise, cancel];
+ },
+ noop:function () { },
+ spawnProcess:function (command, args, options) {
+ if (Module['spawnProcess']) {
+ const spawnedPromise = Module['spawnProcess'](command, args, options);
+ return Promise.resolve(spawnedPromise).then(function (spawned) {
+ if (!spawned || !spawned.on) {
+ throw new Error(
+ 'spawnProcess() must return an EventEmitter but returned a different type.'
+ );
+ }
+ return spawned;
+ });
+ }
+
+ if (ENVIRONMENT_IS_NODE) {
+ return require('child_process').spawn(command, args, {
+ ...options,
+ shell: true,
+ stdio: ['pipe', 'pipe', 'pipe'],
+ timeout: 100,
+ });
+ }
+ const e = new Error(
+ 'popen(), proc_open() etc. are unsupported in the browser. Call php.setSpawnHandler() ' +
+ 'and provide a callback to handle spawning processes, or disable a popen(), proc_open() ' +
+ 'and similar functions via php.ini.'
+ );
+ e.code = 'SPAWN_UNSUPPORTED';
+ throw e;
+ },
+ shutdownSocket:function (socketd, how) {
+ // This implementation only supports websockets at the moment
+ const sock = getSocketFromFD(socketd);
+ const peer = Object.values(sock.peers)[0];
+
+ if (!peer) {
+ return -1;
+ }
+
+ try {
+ peer.socket.close();
+ SOCKFS.websocket_sock_ops.removePeer(sock, peer);
+ return 0;
+ } catch (e) {
+ console.log('Socket shutdown error', e);
+ return -1;
+ }
+ },
+ };
+ function _js_create_input_device(deviceId) {
+ let dataBuffer = [];
+ let dataCallback;
+ const filename = 'proc_id_' + deviceId;
+ const device = FS.createDevice(
+ '/dev',
+ filename,
+ function () { },
+ function (byte) {
+ try {
+ dataBuffer.push(byte);
+ if (dataCallback) {
+ dataCallback(new Uint8Array(dataBuffer));
+ dataBuffer = [];
+ }
+ } catch (e) {
+ console.error(e);
+ throw e;
+ }
+ }
+ );
+
+ const devicePath = '/dev/' + filename;
+ PHPWASM.input_devices[deviceId] = {
+ devicePath: devicePath,
+ onData: function (cb) {
+ dataCallback = cb;
+ dataBuffer.forEach(function (data) {
+ cb(data);
+ });
+ dataBuffer.length = 0;
+ },
+ };
+ return allocateUTF8OnStack(devicePath);
+ }
+
+ function _js_fd_read(fd, iov, iovcnt, pnum) {
+ // Only run the read operation on a regular call,
+ // never when rewinding the stack.
+ if (Asyncify.state === Asyncify.State.Normal) {
+ var returnCode;
+ var stream;
+ let num = 0;
+ try {
+ stream = SYSCALLS.getStreamFromFD(fd);
+ const num = doReadv(stream, iov, iovcnt);
+ HEAPU32[pnum >> 2] = num;
+ return 0;
+ } catch (e) {
+ // Rethrow any unexpected non-filesystem errors.
+ if (typeof FS == "undefined" || !(e.name === "ErrnoError")) {
+ throw e;
+ }
+ // Only return synchronously if this isn't an asynchronous pipe.
+ // Error code 6 indicates EWOULDBLOCK – this is our signal to wait.
+ // We also need to distinguish between a process pipe and a file pipe, otherwise
+ // reading from an empty file would block until the timeout.
+ if (e.errno !== 6 || !(stream?.fd in PHPWASM.child_proc_by_fd)) {
+ // On failure, yield 0 bytes read to indicate EOF.
+ HEAPU32[pnum >> 2] = 0;
+ return returnCode
+ }
+ }
+ }
+
+ // At this point we know we have to poll.
+ // You might wonder why we duplicate the code here instead of always using
+ // Asyncify.handleSleep(). The reason is performance. Most of the time,
+ // the read operation will work synchronously and won't require yielding
+ // back to JS. In these cases we don't want to pay the Asyncify overhead,
+ // save the stack, yield back to JS, restore the stack etc.
+ return Asyncify.handleSleep(function (wakeUp) {
+ var retries = 0;
+ var interval = 50;
+ var timeout = 5000;
+ // We poll for data and give up after a timeout.
+ // We can't simply rely on PHP timeout here because we don't want
+ // to, say, block the entire PHPUnit test suite without any visible
+ // feedback.
+ var maxRetries = timeout / interval;
+ function poll() {
+ var returnCode;
+ var stream;
+ let num;
+ try {
+ stream = SYSCALLS.getStreamFromFD(fd);
+ num = doReadv(stream, iov, iovcnt);
+ returnCode = 0;
+ } catch (e) {
+ if (
+ typeof FS == 'undefined' ||
+ !(e.name === 'ErrnoError')
+ ) {
+ console.error(e);
+ throw e;
+ }
+ returnCode = e.errno;
+ }
+
+ const success = returnCode === 0;
+ const failure = (
+ ++retries > maxRetries ||
+ !(fd in PHPWASM.child_proc_by_fd) ||
+ PHPWASM.child_proc_by_fd[fd]?.exited ||
+ FS.isClosed(stream)
+ );
+
+ if (success) {
+ HEAPU32[pnum >> 2] = num;
+ wakeUp(0);
+ } else if (failure) {
+ // On failure, yield 0 bytes read to indicate EOF.
+ HEAPU32[pnum >> 2] = 0;
+ // If the failure is due to a timeout, return 0 to indicate that we
+ // reached EOF. Otherwise, propagate the error code.
+ wakeUp(returnCode === 6 ? 0 : returnCode);
+ } else {
+ setTimeout(poll, interval);
+ }
+ }
+ poll();
+ });
+ }
+
+
+ function _js_module_onMessage(data, bufPtr) {
+ if (typeof Asyncify === 'undefined') {
+ return;
+ }
+
+ if (Module['onMessage']) {
+ const dataStr = UTF8ToString(data);
+
+ return Asyncify.handleSleep((wakeUp) => {
+ Module['onMessage'](dataStr)
+ .then((response) => {
+ const responseBytes =
+ typeof response === 'string'
+ ? new TextEncoder().encode(response)
+ : response;
+
+ // Copy the response bytes to heap
+ const responseSize = responseBytes.byteLength;
+ const responsePtr = _malloc(responseSize + 1);
+ HEAPU8.set(responseBytes, responsePtr);
+ HEAPU8[responsePtr + responseSize] = 0;
+ HEAPU8[bufPtr] = responsePtr;
+ HEAPU8[bufPtr + 1] = responsePtr >> 8;
+ HEAPU8[bufPtr + 2] = responsePtr >> 16;
+ HEAPU8[bufPtr + 3] = responsePtr >> 24;
+
+ wakeUp(responseSize);
+ })
+ .catch((e) => {
+ // Log the error and return NULL. Message passing
+ // separates JS context from the PHP context so we
+ // don't let PHP crash here.
+ console.error(e);
+ wakeUp(0);
+ });
+ });
+ }
+ }
+
+
+ function _js_open_process(
+ command,
+ argsPtr,
+ argsLength,
+ descriptorsPtr,
+ descriptorsLength,
+ cwdPtr,
+ cwdLength,
+ envPtr,
+ envLength
+ ) {
+ if (!command) {
+ return 1;
+ }
+
+ const cmdstr = UTF8ToString(command);
+ if (!cmdstr.length) {
+ return 0;
+ }
+
+ let argsArray = [];
+ if (argsLength) {
+ for (var i = 0; i < argsLength; i++) {
+ const charPointer = argsPtr + i * 4;
+ argsArray.push(UTF8ToString(HEAPU32[charPointer >> 2]));
+ }
+ }
+
+ const cwdstr = cwdPtr ? UTF8ToString(cwdPtr) : null;
+ let envObject = null;
+
+ if (envLength) {
+ envObject = {};
+ for (var i = 0; i < envLength; i++) {
+ const envPointer = envPtr + i * 4;
+ const envEntry = UTF8ToString(HEAPU32[envPointer >> 2]);
+ const splitAt = envEntry.indexOf('=');
+ if (splitAt === -1) {
+ continue;
+ }
+ const key = envEntry.substring(0, splitAt);
+ const value = envEntry.substring(splitAt + 1);
+ envObject[key] = value;
+ }
+ }
+
+ var std = {};
+ // Extracts an array of available descriptors that should be dispatched to streams.
+ // On the C side, the descriptors are expressed as `**int` so we must go read
+ // each of the `descriptorsLength` `*int` pointers and convert the associated data into
+ // a JavaScript object { descriptor : { child : fd, parent : fd } }.
+ for (var i = 0; i < descriptorsLength; i++) {
+ const descriptorPtr = HEAPU32[(descriptorsPtr + i * 4) >> 2];
+ std[HEAPU32[descriptorPtr >> 2]] = {
+ child: HEAPU32[(descriptorPtr + 4) >> 2],
+ parent: HEAPU32[(descriptorPtr + 8) >> 2],
+ };
+ }
+
+ return Asyncify.handleSleep(async (wakeUp) => {
+ let cp;
+ try {
+ const options = {};
+ if (cwdstr !== null) {
+ options.cwd = cwdstr;
+ }
+ if (envObject !== null) {
+ options.env = envObject;
+ }
+ cp = PHPWASM.spawnProcess(cmdstr, argsArray, options);
+ if (cp instanceof Promise) {
+ cp = await cp;
+ }
+ } catch (e) {
+ if (e.code === 'SPAWN_UNSUPPORTED') {
+ wakeUp(1);
+ return;
+ }
+ console.error(e);
+ wakeUp(1);
+ throw e;
+ }
+
+ const ProcInfo = {
+ pid: cp.pid,
+ exited: false,
+ stdinFd: std[0]?.child,
+ stdinIsDevice: std[0]?.child in PHPWASM.input_devices,
+ stdoutChildFd: std[1]?.child,
+ stdoutParentFd: std[1]?.parent,
+ stderrChildFd: std[2]?.child,
+ stderrParentFd: std[2]?.parent,
+ stdout: new PHPWASM.EventEmitter(),
+ stderr: new PHPWASM.EventEmitter(),
+ };
+ if (ProcInfo.stdoutChildFd)
+ PHPWASM.child_proc_by_fd[ProcInfo.stdoutChildFd] = ProcInfo;
+ if (ProcInfo.stderrChildFd)
+ PHPWASM.child_proc_by_fd[ProcInfo.stderrChildFd] = ProcInfo;
+ if (ProcInfo.stdoutParentFd)
+ PHPWASM.child_proc_by_fd[ProcInfo.stdoutParentFd] = ProcInfo;
+ if (ProcInfo.stderrParentFd)
+ PHPWASM.child_proc_by_fd[ProcInfo.stderrParentFd] = ProcInfo;
+ PHPWASM.child_proc_by_pid[ProcInfo.pid] = ProcInfo;
+
+ cp.on('exit', function (code) {
+ ProcInfo.exitCode = code;
+ ProcInfo.exited = true;
+ // Emit events for the wasm_poll_socket function.
+ ProcInfo.stdout.emit('data');
+ ProcInfo.stderr.emit('data');
+ });
+
+ // Pass data from child process's stdout to PHP's end of the stdout pipe.
+ if (ProcInfo.stdoutChildFd) {
+ const stdoutStream = SYSCALLS.getStreamFromFD(
+ ProcInfo.stdoutChildFd
+ );
+ let stdoutAt = 0;
+ cp.stdout.on('data', function (data) {
+ ProcInfo.stdout.emit('data', data);
+ stdoutStream.stream_ops.write(
+ stdoutStream,
+ data,
+ 0,
+ data.length,
+ stdoutAt
+ );
+ stdoutAt += data.length;
+ });
+ cp.stdout.on('end', function (data) {
+ FS.close(stdoutStream);
+ });
+ }
+
+ // Pass data from child process's stderr to PHP's end of the stdout pipe.
+ if (ProcInfo.stderrChildFd) {
+ const stderrStream = SYSCALLS.getStreamFromFD(
+ ProcInfo.stderrChildFd
+ );
+ let stderrAt = 0;
+ cp.stderr.on('data', function (data) {
+ ProcInfo.stderr.emit('data', data);
+ stderrStream.stream_ops.write(
+ stderrStream,
+ data,
+ 0,
+ data.length,
+ stderrAt
+ );
+ stderrAt += data.length;
+ });
+ cp.stderr.on('end', function (data) {
+ FS.close(stdoutStream);
+ });
+ }
+
+ /**
+ * Wait until the child process has been spawned.
+ * Unfortunately there is no Node.js API to check whether
+ * the process has already been spawned. We can only listen
+ * to the 'spawn' event and if it has already been spawned,
+ * listen to the 'exit' event.
+ */
+ try {
+ await new Promise((resolve, reject) => {
+ cp.on('spawn', resolve);
+ cp.on('error', reject);
+ });
+ } catch (e) {
+ console.error(e);
+ wakeUp(1);
+ return;
+ }
+
+ // Now we want to pass data from the STDIN source supplied by PHP
+ // to the child process.
+
+ // PHP will write STDIN data to a device.
+ if (ProcInfo.stdinIsDevice) {
+ // We use Emscripten devices as pipes. This is a bit of a hack
+ // but it works as we get a callback when the device is written to.
+ // Let's listen to anything it outputs and pass it to the child process.
+ PHPWASM.input_devices[ProcInfo.stdinFd].onData(function (data) {
+ if (!data) return;
+ const dataStr = new TextDecoder('utf-8').decode(data);
+ cp.stdin.write(dataStr);
+ });
+ wakeUp(ProcInfo.pid);
+ return;
+ }
+
+ if (ProcInfo.stdinFd) {
+ // PHP will write STDIN data to a file descriptor.
+ const stdinStream = SYSCALLS.getStreamFromFD(ProcInfo.stdinFd);
+ if (stdinStream.node) {
+ // Pipe the entire stdinStream to cp.stdin
+ const CHUNK_SIZE = 1024;
+ const buffer = new Uint8Array(CHUNK_SIZE);
+ let offset = 0;
+
+ while (true) {
+ const bytesRead = stdinStream.stream_ops.read(
+ stdinStream,
+ buffer,
+ 0,
+ CHUNK_SIZE,
+ offset
+ );
+ if (bytesRead === null || bytesRead === 0) {
+ break;
+ }
+ try {
+ cp.stdin.write(buffer.subarray(0, bytesRead));
+ } catch (e) {
+ console.error(e);
+ return 1;
+ }
+ if (bytesRead < CHUNK_SIZE) {
+ break;
+ }
+ offset += bytesRead;
+ }
+
+ wakeUp(ProcInfo.pid);
+ return;
+ }
+ }
+
+ wakeUp(ProcInfo.pid);
+ });
+ }
+
+
+ function _js_popen_to_file(command, mode, exitCodePtr) {
+ // Parse args
+ if (!command) return 1; // shell is available
+
+ const cmdstr = UTF8ToString(command);
+ if (!cmdstr.length) return 0; // this is what glibc seems to do (shell works test?)
+
+ const modestr = UTF8ToString(mode);
+ if (!modestr.length) return 0; // this is what glibc seems to do (shell works test?)
+ if (modestr === 'w') {
+ console.error('popen($cmd, "w") is not implemented yet');
+ }
+
+ return Asyncify.handleSleep(async (wakeUp) => {
+ let cp;
+ try {
+ cp = PHPWASM.spawnProcess(cmdstr, []);
+ if (cp instanceof Promise) {
+ cp = await cp;
+ }
+ } catch (e) {
+ console.error(e);
+ if (e.code === 'SPAWN_UNSUPPORTED') {
+ return 1;
+ }
+ throw e;
+ }
+
+ const outByteArrays = [];
+ cp.stdout.on('data', function (data) {
+ outByteArrays.push(data);
+ });
+
+ const outputPath = '/tmp/popen_output';
+ cp.on('exit', function (exitCode) {
+ // Concat outByteArrays, an array of UInt8Arrays
+ // into a single Uint8Array.
+ const outBytes = new Uint8Array(
+ outByteArrays.reduce((acc, curr) => acc + curr.length, 0)
+ );
+ let offset = 0;
+ for (const byteArray of outByteArrays) {
+ outBytes.set(byteArray, offset);
+ offset += byteArray.length;
+ }
+
+ FS.writeFile(outputPath, outBytes);
+
+ HEAPU8[exitCodePtr] = exitCode;
+ wakeUp(allocateUTF8OnStack(outputPath)); // 2 is SIGINT
+ });
+ });
+ }
+
+ function _js_process_status(pid, exitCodePtr) {
+ if (!PHPWASM.child_proc_by_pid[pid]) {
+ return -1;
+ }
+ if (PHPWASM.child_proc_by_pid[pid].exited) {
+ HEAPU32[exitCodePtr >> 2] =
+ PHPWASM.child_proc_by_pid[pid].exitCode;
+ return 1;
+ }
+ return 0;
+ }
+
+ function _js_waitpid(pid, exitCodePtr) {
+ if (!PHPWASM.child_proc_by_pid[pid]) {
+ return -1;
+ }
+ return Asyncify.handleSleep((wakeUp) => {
+ const poll = function () {
+ if (PHPWASM.child_proc_by_pid[pid]?.exited) {
+ HEAPU32[exitCodePtr >> 2] =
+ PHPWASM.child_proc_by_pid[pid].exitCode;
+ wakeUp(pid);
+ } else {
+ setTimeout(poll, 50);
+ }
+ };
+ poll();
+ });
+ }
+
+ /** @type {function(...*):?} */
+ function _makecontext(
+ ) {
+ err('missing function: makecontext'); abort(-1);
+ }
+
+
+
+ var arraySum = (array, index) => {
+ var sum = 0;
+ for (var i = 0; i <= index; sum += array[i++]) {
+ // no-op
+ }
+ return sum;
+ };
+
+
+ var MONTH_DAYS_LEAP = [31,29,31,30,31,30,31,31,30,31,30,31];
+
+ var MONTH_DAYS_REGULAR = [31,28,31,30,31,30,31,31,30,31,30,31];
+ var addDays = (date, days) => {
+ var newDate = new Date(date.getTime());
+ while (days > 0) {
+ var leap = isLeapYear(newDate.getFullYear());
+ var currentMonth = newDate.getMonth();
+ var daysInCurrentMonth = (leap ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR)[currentMonth];
+
+ if (days > daysInCurrentMonth-newDate.getDate()) {
+ // we spill over to next month
+ days -= (daysInCurrentMonth-newDate.getDate()+1);
+ newDate.setDate(1);
+ if (currentMonth < 11) {
+ newDate.setMonth(currentMonth+1)
+ } else {
+ newDate.setMonth(0);
+ newDate.setFullYear(newDate.getFullYear()+1);
+ }
+ } else {
+ // we stay in current month
+ newDate.setDate(newDate.getDate()+days);
+ return newDate;
+ }
+ }
+
+ return newDate;
+ };
+
+
+
+
+ var writeArrayToMemory = (array, buffer) => {
+ HEAP8.set(array, buffer);
+ };
+
+ var _strftime = (s, maxsize, format, tm) => {
+ // size_t strftime(char *restrict s, size_t maxsize, const char *restrict format, const struct tm *restrict timeptr);
+ // http://pubs.opengroup.org/onlinepubs/009695399/functions/strftime.html
+
+ var tm_zone = HEAP32[(((tm)+(40))>>2)];
+
+ var date = {
+ tm_sec: HEAP32[((tm)>>2)],
+ tm_min: HEAP32[(((tm)+(4))>>2)],
+ tm_hour: HEAP32[(((tm)+(8))>>2)],
+ tm_mday: HEAP32[(((tm)+(12))>>2)],
+ tm_mon: HEAP32[(((tm)+(16))>>2)],
+ tm_year: HEAP32[(((tm)+(20))>>2)],
+ tm_wday: HEAP32[(((tm)+(24))>>2)],
+ tm_yday: HEAP32[(((tm)+(28))>>2)],
+ tm_isdst: HEAP32[(((tm)+(32))>>2)],
+ tm_gmtoff: HEAP32[(((tm)+(36))>>2)],
+ tm_zone: tm_zone ? UTF8ToString(tm_zone) : ''
+ };
+
+ var pattern = UTF8ToString(format);
+
+ // expand format
+ var EXPANSION_RULES_1 = {
+ '%c': '%a %b %d %H:%M:%S %Y', // Replaced by the locale's appropriate date and time representation - e.g., Mon Aug 3 14:02:01 2013
+ '%D': '%m/%d/%y', // Equivalent to %m / %d / %y
+ '%F': '%Y-%m-%d', // Equivalent to %Y - %m - %d
+ '%h': '%b', // Equivalent to %b
+ '%r': '%I:%M:%S %p', // Replaced by the time in a.m. and p.m. notation
+ '%R': '%H:%M', // Replaced by the time in 24-hour notation
+ '%T': '%H:%M:%S', // Replaced by the time
+ '%x': '%m/%d/%y', // Replaced by the locale's appropriate date representation
+ '%X': '%H:%M:%S', // Replaced by the locale's appropriate time representation
+ // Modified Conversion Specifiers
+ '%Ec': '%c', // Replaced by the locale's alternative appropriate date and time representation.
+ '%EC': '%C', // Replaced by the name of the base year (period) in the locale's alternative representation.
+ '%Ex': '%m/%d/%y', // Replaced by the locale's alternative date representation.
+ '%EX': '%H:%M:%S', // Replaced by the locale's alternative time representation.
+ '%Ey': '%y', // Replaced by the offset from %EC (year only) in the locale's alternative representation.
+ '%EY': '%Y', // Replaced by the full alternative year representation.
+ '%Od': '%d', // Replaced by the day of the month, using the locale's alternative numeric symbols, filled as needed with leading zeros if there is any alternative symbol for zero; otherwise, with leading characters.
+ '%Oe': '%e', // Replaced by the day of the month, using the locale's alternative numeric symbols, filled as needed with leading characters.
+ '%OH': '%H', // Replaced by the hour (24-hour clock) using the locale's alternative numeric symbols.
+ '%OI': '%I', // Replaced by the hour (12-hour clock) using the locale's alternative numeric symbols.
+ '%Om': '%m', // Replaced by the month using the locale's alternative numeric symbols.
+ '%OM': '%M', // Replaced by the minutes using the locale's alternative numeric symbols.
+ '%OS': '%S', // Replaced by the seconds using the locale's alternative numeric symbols.
+ '%Ou': '%u', // Replaced by the weekday as a number in the locale's alternative representation (Monday=1).
+ '%OU': '%U', // Replaced by the week number of the year (Sunday as the first day of the week, rules corresponding to %U ) using the locale's alternative numeric symbols.
+ '%OV': '%V', // Replaced by the week number of the year (Monday as the first day of the week, rules corresponding to %V ) using the locale's alternative numeric symbols.
+ '%Ow': '%w', // Replaced by the number of the weekday (Sunday=0) using the locale's alternative numeric symbols.
+ '%OW': '%W', // Replaced by the week number of the year (Monday as the first day of the week) using the locale's alternative numeric symbols.
+ '%Oy': '%y', // Replaced by the year (offset from %C ) using the locale's alternative numeric symbols.
+ };
+ for (var rule in EXPANSION_RULES_1) {
+ pattern = pattern.replace(new RegExp(rule, 'g'), EXPANSION_RULES_1[rule]);
+ }
+
+ var WEEKDAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
+ var MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
+
+ function leadingSomething(value, digits, character) {
+ var str = typeof value == 'number' ? value.toString() : (value || '');
+ while (str.length < digits) {
+ str = character[0]+str;
+ }
+ return str;
+ }
+
+ function leadingNulls(value, digits) {
+ return leadingSomething(value, digits, '0');
+ }
+
+ function compareByDay(date1, date2) {
+ function sgn(value) {
+ return value < 0 ? -1 : (value > 0 ? 1 : 0);
+ }
+
+ var compare;
+ if ((compare = sgn(date1.getFullYear()-date2.getFullYear())) === 0) {
+ if ((compare = sgn(date1.getMonth()-date2.getMonth())) === 0) {
+ compare = sgn(date1.getDate()-date2.getDate());
+ }
+ }
+ return compare;
+ }
+
+ function getFirstWeekStartDate(janFourth) {
+ switch (janFourth.getDay()) {
+ case 0: // Sunday
+ return new Date(janFourth.getFullYear()-1, 11, 29);
+ case 1: // Monday
+ return janFourth;
+ case 2: // Tuesday
+ return new Date(janFourth.getFullYear(), 0, 3);
+ case 3: // Wednesday
+ return new Date(janFourth.getFullYear(), 0, 2);
+ case 4: // Thursday
+ return new Date(janFourth.getFullYear(), 0, 1);
+ case 5: // Friday
+ return new Date(janFourth.getFullYear()-1, 11, 31);
+ case 6: // Saturday
+ return new Date(janFourth.getFullYear()-1, 11, 30);
+ }
+ }
+
+ function getWeekBasedYear(date) {
+ var thisDate = addDays(new Date(date.tm_year+1900, 0, 1), date.tm_yday);
+
+ var janFourthThisYear = new Date(thisDate.getFullYear(), 0, 4);
+ var janFourthNextYear = new Date(thisDate.getFullYear()+1, 0, 4);
+
+ var firstWeekStartThisYear = getFirstWeekStartDate(janFourthThisYear);
+ var firstWeekStartNextYear = getFirstWeekStartDate(janFourthNextYear);
+
+ if (compareByDay(firstWeekStartThisYear, thisDate) <= 0) {
+ // this date is after the start of the first week of this year
+ if (compareByDay(firstWeekStartNextYear, thisDate) <= 0) {
+ return thisDate.getFullYear()+1;
+ }
+ return thisDate.getFullYear();
+ }
+ return thisDate.getFullYear()-1;
+ }
+
+ var EXPANSION_RULES_2 = {
+ '%a': (date) => WEEKDAYS[date.tm_wday].substring(0,3) ,
+ '%A': (date) => WEEKDAYS[date.tm_wday],
+ '%b': (date) => MONTHS[date.tm_mon].substring(0,3),
+ '%B': (date) => MONTHS[date.tm_mon],
+ '%C': (date) => {
+ var year = date.tm_year+1900;
+ return leadingNulls((year/100)|0,2);
+ },
+ '%d': (date) => leadingNulls(date.tm_mday, 2),
+ '%e': (date) => leadingSomething(date.tm_mday, 2, ' '),
+ '%g': (date) => {
+ // %g, %G, and %V give values according to the ISO 8601:2000 standard week-based year.
+ // In this system, weeks begin on a Monday and week 1 of the year is the week that includes
+ // January 4th, which is also the week that includes the first Thursday of the year, and
+ // is also the first week that contains at least four days in the year.
+ // If the first Monday of January is the 2nd, 3rd, or 4th, the preceding days are part of
+ // the last week of the preceding year; thus, for Saturday 2nd January 1999,
+ // %G is replaced by 1998 and %V is replaced by 53. If December 29th, 30th,
+ // or 31st is a Monday, it and any following days are part of week 1 of the following year.
+ // Thus, for Tuesday 30th December 1997, %G is replaced by 1998 and %V is replaced by 01.
+
+ return getWeekBasedYear(date).toString().substring(2);
+ },
+ '%G': (date) => getWeekBasedYear(date),
+ '%H': (date) => leadingNulls(date.tm_hour, 2),
+ '%I': (date) => {
+ var twelveHour = date.tm_hour;
+ if (twelveHour == 0) twelveHour = 12;
+ else if (twelveHour > 12) twelveHour -= 12;
+ return leadingNulls(twelveHour, 2);
+ },
+ '%j': (date) => {
+ // Day of the year (001-366)
+ return leadingNulls(date.tm_mday + arraySum(isLeapYear(date.tm_year+1900) ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR, date.tm_mon-1), 3);
+ },
+ '%m': (date) => leadingNulls(date.tm_mon+1, 2),
+ '%M': (date) => leadingNulls(date.tm_min, 2),
+ '%n': () => '\n',
+ '%p': (date) => {
+ if (date.tm_hour >= 0 && date.tm_hour < 12) {
+ return 'AM';
+ }
+ return 'PM';
+ },
+ '%S': (date) => leadingNulls(date.tm_sec, 2),
+ '%t': () => '\t',
+ '%u': (date) => date.tm_wday || 7,
+ '%U': (date) => {
+ var days = date.tm_yday + 7 - date.tm_wday;
+ return leadingNulls(Math.floor(days / 7), 2);
+ },
+ '%V': (date) => {
+ // Replaced by the week number of the year (Monday as the first day of the week)
+ // as a decimal number [01,53]. If the week containing 1 January has four
+ // or more days in the new year, then it is considered week 1.
+ // Otherwise, it is the last week of the previous year, and the next week is week 1.
+ // Both January 4th and the first Thursday of January are always in week 1. [ tm_year, tm_wday, tm_yday]
+ var val = Math.floor((date.tm_yday + 7 - (date.tm_wday + 6) % 7 ) / 7);
+ // If 1 Jan is just 1-3 days past Monday, the previous week
+ // is also in this year.
+ if ((date.tm_wday + 371 - date.tm_yday - 2) % 7 <= 2) {
+ val++;
+ }
+ if (!val) {
+ val = 52;
+ // If 31 December of prev year a Thursday, or Friday of a
+ // leap year, then the prev year has 53 weeks.
+ var dec31 = (date.tm_wday + 7 - date.tm_yday - 1) % 7;
+ if (dec31 == 4 || (dec31 == 5 && isLeapYear(date.tm_year%400-1))) {
+ val++;
+ }
+ } else if (val == 53) {
+ // If 1 January is not a Thursday, and not a Wednesday of a
+ // leap year, then this year has only 52 weeks.
+ var jan1 = (date.tm_wday + 371 - date.tm_yday) % 7;
+ if (jan1 != 4 && (jan1 != 3 || !isLeapYear(date.tm_year)))
+ val = 1;
+ }
+ return leadingNulls(val, 2);
+ },
+ '%w': (date) => date.tm_wday,
+ '%W': (date) => {
+ var days = date.tm_yday + 7 - ((date.tm_wday + 6) % 7);
+ return leadingNulls(Math.floor(days / 7), 2);
+ },
+ '%y': (date) => {
+ // Replaced by the last two digits of the year as a decimal number [00,99]. [ tm_year]
+ return (date.tm_year+1900).toString().substring(2);
+ },
+ // Replaced by the year as a decimal number (for example, 1997). [ tm_year]
+ '%Y': (date) => date.tm_year+1900,
+ '%z': (date) => {
+ // Replaced by the offset from UTC in the ISO 8601:2000 standard format ( +hhmm or -hhmm ).
+ // For example, "-0430" means 4 hours 30 minutes behind UTC (west of Greenwich).
+ var off = date.tm_gmtoff;
+ var ahead = off >= 0;
+ off = Math.abs(off) / 60;
+ // convert from minutes into hhmm format (which means 60 minutes = 100 units)
+ off = (off / 60)*100 + (off % 60);
+ return (ahead ? '+' : '-') + String("0000" + off).slice(-4);
+ },
+ '%Z': (date) => date.tm_zone,
+ '%%': () => '%'
+ };
+
+ // Replace %% with a pair of NULLs (which cannot occur in a C string), then
+ // re-inject them after processing.
+ pattern = pattern.replace(/%%/g, '\0\0')
+ for (var rule in EXPANSION_RULES_2) {
+ if (pattern.includes(rule)) {
+ pattern = pattern.replace(new RegExp(rule, 'g'), EXPANSION_RULES_2[rule](date));
+ }
+ }
+ pattern = pattern.replace(/\0\0/g, '%')
+
+ var bytes = intArrayFromString(pattern, false);
+ if (bytes.length > maxsize) {
+ return 0;
+ }
+
+ writeArrayToMemory(bytes, s);
+ return bytes.length-1;
+ };
+
+
+
+
+
+
+
+
+ var _strptime = (buf, format, tm) => {
+ // char *strptime(const char *restrict buf, const char *restrict format, struct tm *restrict tm);
+ // http://pubs.opengroup.org/onlinepubs/009695399/functions/strptime.html
+ var pattern = UTF8ToString(format);
+
+ // escape special characters
+ // TODO: not sure we really need to escape all of these in JS regexps
+ var SPECIAL_CHARS = '\\!@#$^&*()+=-[]/{}|:<>?,.';
+ for (var i=0, ii=SPECIAL_CHARS.length; i=0; i=pattern.indexOf('%')) {
+ capture.push(pattern[i+1]);
+ pattern = pattern.replace(new RegExp('\\%'+pattern[i+1], 'g'), '');
+ }
+
+ var matches = new RegExp('^'+pattern, "i").exec(UTF8ToString(buf))
+ // out(UTF8ToString(buf)+ ' is matched by '+((new RegExp('^'+pattern)).source)+' into: '+JSON.stringify(matches));
+
+ function initDate() {
+ function fixup(value, min, max) {
+ return (typeof value != 'number' || isNaN(value)) ? min : (value>=min ? (value<=max ? value: max): min);
+ };
+ return {
+ year: fixup(HEAP32[(((tm)+(20))>>2)] + 1900 , 1970, 9999),
+ month: fixup(HEAP32[(((tm)+(16))>>2)], 0, 11),
+ day: fixup(HEAP32[(((tm)+(12))>>2)], 1, 31),
+ hour: fixup(HEAP32[(((tm)+(8))>>2)], 0, 23),
+ min: fixup(HEAP32[(((tm)+(4))>>2)], 0, 59),
+ sec: fixup(HEAP32[((tm)>>2)], 0, 59)
+ };
+ };
+
+ if (matches) {
+ var date = initDate();
+ var value;
+
+ var getMatch = (symbol) => {
+ var pos = capture.indexOf(symbol);
+ // check if symbol appears in regexp
+ if (pos >= 0) {
+ // return matched value or null (falsy!) for non-matches
+ return matches[pos+1];
+ }
+ return;
+ };
+
+ // seconds
+ if ((value=getMatch('S'))) {
+ date.sec = jstoi_q(value);
+ }
+
+ // minutes
+ if ((value=getMatch('M'))) {
+ date.min = jstoi_q(value);
+ }
+
+ // hours
+ if ((value=getMatch('H'))) {
+ // 24h clock
+ date.hour = jstoi_q(value);
+ } else if ((value = getMatch('I'))) {
+ // AM/PM clock
+ var hour = jstoi_q(value);
+ if ((value=getMatch('p'))) {
+ hour += value.toUpperCase()[0] === 'P' ? 12 : 0;
+ }
+ date.hour = hour;
+ }
+
+ // year
+ if ((value=getMatch('Y'))) {
+ // parse from four-digit year
+ date.year = jstoi_q(value);
+ } else if ((value=getMatch('y'))) {
+ // parse from two-digit year...
+ var year = jstoi_q(value);
+ if ((value=getMatch('C'))) {
+ // ...and century
+ year += jstoi_q(value)*100;
+ } else {
+ // ...and rule-of-thumb
+ year += year<69 ? 2000 : 1900;
+ }
+ date.year = year;
+ }
+
+ // month
+ if ((value=getMatch('m'))) {
+ // parse from month number
+ date.month = jstoi_q(value)-1;
+ } else if ((value=getMatch('b'))) {
+ // parse from month name
+ date.month = MONTH_NUMBERS[value.substring(0,3).toUpperCase()] || 0;
+ // TODO: derive month from day in year+year, week number+day of week+year
+ }
+
+ // day
+ if ((value=getMatch('d'))) {
+ // get day of month directly
+ date.day = jstoi_q(value);
+ } else if ((value=getMatch('j'))) {
+ // get day of month from day of year ...
+ var day = jstoi_q(value);
+ var leapYear = isLeapYear(date.year);
+ for (var month=0; month<12; ++month) {
+ var daysUntilMonth = arraySum(leapYear ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR, month-1);
+ if (day<=daysUntilMonth+(leapYear ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR)[month]) {
+ date.day = day-daysUntilMonth;
+ }
+ }
+ } else if ((value=getMatch('a'))) {
+ // get day of month from weekday ...
+ var weekDay = value.substring(0,3).toUpperCase();
+ if ((value=getMatch('U'))) {
+ // ... and week number (Sunday being first day of week)
+ // Week number of the year (Sunday as the first day of the week) as a decimal number [00,53].
+ // All days in a new year preceding the first Sunday are considered to be in week 0.
+ var weekDayNumber = DAY_NUMBERS_SUN_FIRST[weekDay];
+ var weekNumber = jstoi_q(value);
+
+ // January 1st
+ var janFirst = new Date(date.year, 0, 1);
+ var endDate;
+ if (janFirst.getDay() === 0) {
+ // Jan 1st is a Sunday, and, hence in the 1st CW
+ endDate = addDays(janFirst, weekDayNumber+7*(weekNumber-1));
+ } else {
+ // Jan 1st is not a Sunday, and, hence still in the 0th CW
+ endDate = addDays(janFirst, 7-janFirst.getDay()+weekDayNumber+7*(weekNumber-1));
+ }
+ date.day = endDate.getDate();
+ date.month = endDate.getMonth();
+ } else if ((value=getMatch('W'))) {
+ // ... and week number (Monday being first day of week)
+ // Week number of the year (Monday as the first day of the week) as a decimal number [00,53].
+ // All days in a new year preceding the first Monday are considered to be in week 0.
+ var weekDayNumber = DAY_NUMBERS_MON_FIRST[weekDay];
+ var weekNumber = jstoi_q(value);
+
+ // January 1st
+ var janFirst = new Date(date.year, 0, 1);
+ var endDate;
+ if (janFirst.getDay()===1) {
+ // Jan 1st is a Monday, and, hence in the 1st CW
+ endDate = addDays(janFirst, weekDayNumber+7*(weekNumber-1));
+ } else {
+ // Jan 1st is not a Monday, and, hence still in the 0th CW
+ endDate = addDays(janFirst, 7-janFirst.getDay()+1+weekDayNumber+7*(weekNumber-1));
+ }
+
+ date.day = endDate.getDate();
+ date.month = endDate.getMonth();
+ }
+ }
+
+ /*
+ tm_sec int seconds after the minute 0-61*
+ tm_min int minutes after the hour 0-59
+ tm_hour int hours since midnight 0-23
+ tm_mday int day of the month 1-31
+ tm_mon int months since January 0-11
+ tm_year int years since 1900
+ tm_wday int days since Sunday 0-6
+ tm_yday int days since January 1 0-365
+ tm_isdst int Daylight Saving Time flag
+ */
+
+ var fullDate = new Date(date.year, date.month, date.day, date.hour, date.min, date.sec, 0);
+ HEAP32[((tm)>>2)] = fullDate.getSeconds();
+ HEAP32[(((tm)+(4))>>2)] = fullDate.getMinutes();
+ HEAP32[(((tm)+(8))>>2)] = fullDate.getHours();
+ HEAP32[(((tm)+(12))>>2)] = fullDate.getDate();
+ HEAP32[(((tm)+(16))>>2)] = fullDate.getMonth();
+ HEAP32[(((tm)+(20))>>2)] = fullDate.getFullYear()-1900;
+ HEAP32[(((tm)+(24))>>2)] = fullDate.getDay();
+ HEAP32[(((tm)+(28))>>2)] = arraySum(isLeapYear(fullDate.getFullYear()) ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR, fullDate.getMonth()-1)+fullDate.getDate()-1;
+ HEAP32[(((tm)+(32))>>2)] = 0;
+
+ // we need to convert the matched sequence into an integer array to take care of UTF-8 characters > 0x7F
+ // TODO: not sure that intArrayFromString handles all unicode characters correctly
+ return buf+intArrayFromString(matches[0]).length-1;
+ }
+
+ return 0;
+ };
+
+ /** @type {function(...*):?} */
+ function _swapcontext(
+ ) {
+ err('missing function: swapcontext'); abort(-1);
+ }
+
+ function _wasm_poll_socket(socketd, events, timeout) {
+ if (typeof Asyncify === 'undefined') {
+ return 0;
+ }
+
+ const POLLIN = 0x0001; /* There is data to read */
+ const POLLPRI = 0x0002; /* There is urgent data to read */
+ const POLLOUT = 0x0004; /* Writing now will not block */
+ const POLLERR = 0x0008; /* Error condition */
+ const POLLHUP = 0x0010; /* Hung up */
+ const POLLNVAL = 0x0020; /* Invalid request: fd not open */
+
+ return Asyncify.handleSleep((wakeUp) => {
+ const polls = [];
+ if (socketd in PHPWASM.child_proc_by_fd) {
+ // This is a child process-related socket.
+ const procInfo = PHPWASM.child_proc_by_fd[socketd];
+ if (procInfo.exited) {
+ wakeUp(0);
+ return;
+ }
+ polls.push(PHPWASM.awaitEvent(procInfo.stdout, 'data'));
+ } else {
+ // This is, most likely, a websocket. Let's make sure.
+ const sock = getSocketFromFD(socketd);
+ if (!sock) {
+ wakeUp(0);
+ return;
+ }
+ const lookingFor = new Set();
+
+ if (events & POLLIN || events & POLLPRI) {
+ if (sock.server) {
+ for (const client of sock.pending) {
+ if ((client.recv_queue || []).length > 0) {
+ wakeUp(1);
+ return;
+ }
+ }
+ } else if ((sock.recv_queue || []).length > 0) {
+ wakeUp(1);
+ return;
+ }
+ }
+
+ const webSockets = PHPWASM.getAllWebSockets(sock);
+ if (!webSockets.length) {
+ wakeUp(0);
+ return;
+ }
+ for (const ws of webSockets) {
+ if (events & POLLIN || events & POLLPRI) {
+ polls.push(PHPWASM.awaitData(ws));
+ lookingFor.add('POLLIN');
+ }
+ if (events & POLLOUT) {
+ polls.push(PHPWASM.awaitConnection(ws));
+ lookingFor.add('POLLOUT');
+ }
+ if (events & POLLHUP) {
+ polls.push(PHPWASM.awaitClose(ws));
+ lookingFor.add('POLLHUP');
+ }
+ if (events & POLLERR || events & POLLNVAL) {
+ polls.push(PHPWASM.awaitError(ws));
+ lookingFor.add('POLLERR');
+ }
+ }
+ }
+ if (polls.length === 0) {
+ console.warn(
+ 'Unsupported poll event ' +
+ events +
+ ', defaulting to setTimeout().'
+ );
+ setTimeout(function () {
+ wakeUp(0);
+ }, timeout);
+ return;
+ }
+
+ const promises = polls.map(([promise]) => promise);
+ const clearPolling = () => polls.forEach(([, clear]) => clear());
+ let awaken = false;
+ let timeoutId;
+ Promise.race(promises).then(function (results) {
+ if (!awaken) {
+ awaken = true;
+ wakeUp(1);
+ if (timeoutId) {
+ clearTimeout(timeoutId);
+ }
+ clearPolling();
+ }
+ });
+
+ if (timeout !== -1) {
+ timeoutId = setTimeout(function () {
+ if (!awaken) {
+ awaken = true;
+ wakeUp(0);
+ clearPolling();
+ }
+ }, timeout);
+ }
+ });
+ }
+
+ function _wasm_setsockopt(
+ socketd,
+ level,
+ optionName,
+ optionValuePtr,
+ optionLen
+ ) {
+ const optionValue = HEAPU8[optionValuePtr];
+ const SOL_SOCKET = 1;
+ const SO_KEEPALIVE = 9;
+ const IPPROTO_TCP = 6;
+ const TCP_NODELAY = 1;
+ const isSupported =
+ (level === SOL_SOCKET && optionName === SO_KEEPALIVE) ||
+ (level === IPPROTO_TCP && optionName === TCP_NODELAY);
+ if (!isSupported) {
+ console.warn(
+ `Unsupported socket option: ${level}, ${optionName}, ${optionValue}`
+ );
+ return -1;
+ }
+ const ws = PHPWASM.getAllWebSockets(socketd)[0];
+ if (!ws) {
+ return -1;
+ }
+ ws.setSocketOpt(level, optionName, optionValuePtr);
+ return 0;
+ }
+
+ var wasmTableMirror = [];
+ var getWasmTableEntry = (funcPtr) => {
+ var func = wasmTableMirror[funcPtr];
+ if (!func) {
+ if (funcPtr >= wasmTableMirror.length) wasmTableMirror.length = funcPtr + 1;
+ wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr);
+ }
+ return func;
+ };
+
+
+ function runAndAbortIfError(func) {
+ try {
+ return func();
+ } catch (e) {
+ abort(e);
+ }
+ }
+
+
+ function sigToWasmTypes(sig) {
+ var typeNames = {
+ 'i': 'i32',
+ 'j': 'i64',
+ 'f': 'f32',
+ 'd': 'f64',
+ 'p': 'i32',
+ };
+ 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 type;
+ }
+
+
+
+
+
+
+ var Asyncify = {
+ instrumentWasmImports:function(imports) {
+ var importPatterns = [/^_dlopen_js$/,/^invoke_i$/,/^invoke_ii$/,/^invoke_iii$/,/^invoke_iiii$/,/^invoke_iiiii$/,/^invoke_iiiiii$/,/^invoke_iiiiiii$/,/^invoke_iiiiiiii$/,/^invoke_iiiiiiiiii$/,/^invoke_v$/,/^invoke_vi$/,/^invoke_vii$/,/^invoke_viidii$/,/^invoke_viii$/,/^invoke_viiii$/,/^invoke_viiiii$/,/^invoke_viiiiii$/,/^invoke_viiiiiii$/,/^invoke_viiiiiiiii$/,/^js_open_process$/,/^js_popen_to_file$/,/^js_fd_read$/,/^js_module_onMessage$/,/^js_waitpid$/,/^wasm_poll_socket$/,/^wasm_shutdown$/,/^fd_sync$/,/^__wasi_fd_sync$/,/^__asyncjs__.*$/,/^emscripten_promise_await$/,/^emscripten_idb_load$/,/^emscripten_idb_store$/,/^emscripten_idb_delete$/,/^emscripten_idb_exists$/,/^emscripten_idb_load_blob$/,/^emscripten_idb_store_blob$/,/^emscripten_sleep$/,/^emscripten_wget_data$/,/^emscripten_scan_registers$/,/^emscripten_lazy_load_code$/,/^_load_secondary_module$/,/^emscripten_fiber_swap$/,/^SDL_Delay$/];
+
+ for (var x in imports) {
+ (function(x) {
+ var original = imports[x];
+ var sig = original.sig;
+ if (typeof original == 'function') {
+ var isAsyncifyImport = original.isAsync ||
+ importPatterns.some(pattern => !!x.match(pattern));
+ }
+ })(x);
+ }
+ },
+ instrumentWasmExports:function(exports) {
+ var ret = {};
+ for (var x in exports) {
+ (function(x) {
+ var original = exports[x];
+ if (typeof original == 'function') {
+ ret[x] = function() {
+ Asyncify.exportCallStack.push(x);
+ try {
+ return original.apply(null, arguments);
+ } finally {
+ if (!ABORT) {
+ var y = Asyncify.exportCallStack.pop();
+ assert(y === x);
+ Asyncify.maybeStopUnwind();
+ }
+ }
+ };
+ } else {
+ ret[x] = original;
+ }
+ })(x);
+ }
+ return ret;
+ },
+ State:{
+ Normal:0,
+ Unwinding:1,
+ Rewinding:2,
+ Disabled:3,
+ },
+ state:0,
+ StackSize:4096,
+ currData:null,
+ handleSleepReturnValue:0,
+ exportCallStack:[],
+ callStackNameToId:{
+ },
+ callStackIdToName:{
+ },
+ callStackId:0,
+ asyncPromiseHandlers:null,
+ sleepCallbacks:[],
+ getCallStackId:function(funcName) {
+ var id = Asyncify.callStackNameToId[funcName];
+ if (id === undefined) {
+ id = Asyncify.callStackId++;
+ Asyncify.callStackNameToId[funcName] = id;
+ Asyncify.callStackIdToName[id] = funcName;
+ }
+ return id;
+ },
+ maybeStopUnwind:function() {
+ if (Asyncify.currData &&
+ Asyncify.state === Asyncify.State.Unwinding &&
+ Asyncify.exportCallStack.length === 0) {
+ // We just finished unwinding.
+ // Be sure to set the state before calling any other functions to avoid
+ // possible infinite recursion here (For example in debug pthread builds
+ // the dbg() function itself can call back into WebAssembly to get the
+ // current pthread_self() pointer).
+ Asyncify.state = Asyncify.State.Normal;
+ runtimeKeepalivePush();
+ // Keep the runtime alive so that a re-wind can be done later.
+ runAndAbortIfError(_asyncify_stop_unwind);
+ if (typeof Fibers != 'undefined') {
+ Fibers.trampoline();
+ }
+ }
+ },
+ whenDone:function() {
+ return new Promise((resolve, reject) => {
+ Asyncify.asyncPromiseHandlers = { resolve, reject };
+ });
+ },
+ allocateData:function() {
+ // An asyncify data structure has three fields:
+ // 0 current stack pos
+ // 4 max stack pos
+ // 8 id of function at bottom of the call stack (callStackIdToName[id] == name of js function)
+ //
+ // The Asyncify ABI only interprets the first two fields, the rest is for the runtime.
+ // We also embed a stack in the same memory region here, right next to the structure.
+ // This struct is also defined as asyncify_data_t in emscripten/fiber.h
+ var ptr = _malloc(12 + Asyncify.StackSize);
+ Asyncify.setDataHeader(ptr, ptr + 12, Asyncify.StackSize);
+ Asyncify.setDataRewindFunc(ptr);
+ return ptr;
+ },
+ setDataHeader:function(ptr, stack, stackSize) {
+ HEAP32[((ptr)>>2)] = stack;
+ HEAP32[(((ptr)+(4))>>2)] = stack + stackSize;
+ },
+ setDataRewindFunc:function(ptr) {
+ var bottomOfCallStack = Asyncify.exportCallStack[0];
+ var rewindId = Asyncify.getCallStackId(bottomOfCallStack);
+ HEAP32[(((ptr)+(8))>>2)] = rewindId;
+ },
+ getDataRewindFunc:function(ptr) {
+ var id = HEAP32[(((ptr)+(8))>>2)];
+ var name = Asyncify.callStackIdToName[id];
+ var func = Module['asm'][name];
+ return func;
+ },
+ doRewind:function(ptr) {
+ var start = Asyncify.getDataRewindFunc(ptr);
+ // Once we have rewound and the stack we no longer need to artificially
+ // keep the runtime alive.
+ runtimeKeepalivePop();
+ return start();
+ },
+ handleSleep:function(startAsync) {
+ if (ABORT) return;
+ if (Asyncify.state === Asyncify.State.Normal) {
+ // Prepare to sleep. Call startAsync, and see what happens:
+ // if the code decided to call our callback synchronously,
+ // then no async operation was in fact begun, and we don't
+ // need to do anything.
+ var reachedCallback = false;
+ var reachedAfterCallback = false;
+ startAsync((handleSleepReturnValue = 0) => {
+ if (ABORT) return;
+ Asyncify.handleSleepReturnValue = handleSleepReturnValue;
+ reachedCallback = true;
+ if (!reachedAfterCallback) {
+ // We are happening synchronously, so no need for async.
+ return;
+ }
+ Asyncify.state = Asyncify.State.Rewinding;
+ runAndAbortIfError(() => _asyncify_start_rewind(Asyncify.currData));
+ if (typeof Browser != 'undefined' && Browser.mainLoop.func) {
+ Browser.mainLoop.resume();
+ }
+ var asyncWasmReturnValue, isError = false;
+ try {
+ asyncWasmReturnValue = Asyncify.doRewind(Asyncify.currData);
+ } catch (err) {
+ asyncWasmReturnValue = err;
+ isError = true;
+ }
+ // Track whether the return value was handled by any promise handlers.
+ var handled = false;
+ if (!Asyncify.currData) {
+ // All asynchronous execution has finished.
+ // `asyncWasmReturnValue` now contains the final
+ // return value of the exported async WASM function.
+ //
+ // Note: `asyncWasmReturnValue` is distinct from
+ // `Asyncify.handleSleepReturnValue`.
+ // `Asyncify.handleSleepReturnValue` contains the return
+ // value of the last C function to have executed
+ // `Asyncify.handleSleep()`, where as `asyncWasmReturnValue`
+ // contains the return value of the exported WASM function
+ // that may have called C functions that
+ // call `Asyncify.handleSleep()`.
+ var asyncPromiseHandlers = Asyncify.asyncPromiseHandlers;
+ if (asyncPromiseHandlers) {
+ Asyncify.asyncPromiseHandlers = null;
+ (isError ? asyncPromiseHandlers.reject : asyncPromiseHandlers.resolve)(asyncWasmReturnValue);
+ handled = true;
+ }
+ }
+ if (isError && !handled) {
+ // If there was an error and it was not handled by now, we have no choice but to
+ // rethrow that error into the global scope where it can be caught only by
+ // `onerror` or `onunhandledpromiserejection`.
+ throw asyncWasmReturnValue;
+ }
+ });
+ reachedAfterCallback = true;
+ if (!reachedCallback) {
+ // A true async operation was begun; start a sleep.
+ Asyncify.state = Asyncify.State.Unwinding;
+ // TODO: reuse, don't alloc/free every sleep
+ Asyncify.currData = Asyncify.allocateData();
+ if (typeof Browser != 'undefined' && Browser.mainLoop.func) {
+ Browser.mainLoop.pause();
+ }
+ runAndAbortIfError(() => _asyncify_start_unwind(Asyncify.currData));
+ }
+ } else if (Asyncify.state === Asyncify.State.Rewinding) {
+ // Stop a resume.
+ Asyncify.state = Asyncify.State.Normal;
+ runAndAbortIfError(_asyncify_stop_rewind);
+ _free(Asyncify.currData);
+ Asyncify.currData = null;
+ // Call all sleep callbacks now that the sleep-resume is all done.
+ Asyncify.sleepCallbacks.forEach((func) => callUserCallback(func));
+ } else {
+ abort(`invalid state: ${Asyncify.state}`);
+ }
+ return Asyncify.handleSleepReturnValue;
+ },
+ handleAsync:function(startAsync) {
+ return Asyncify.handleSleep((wakeUp) => {
+ // TODO: add error handling as a second param when handleSleep implements it.
+ startAsync().then(wakeUp);
+ });
+ },
+ };
+
+ function getCFunc(ident) {
+ var func = Module['_' + ident]; // closure exported function
+ return func;
+ }
+
+
+
+
+
+
+ /**
+ * @param {string|null=} returnType
+ * @param {Array=} argTypes
+ * @param {Arguments|Array=} args
+ * @param {Object=} opts
+ */
+ var ccall = function(ident, returnType, argTypes, args, opts) {
+ // For fast lookup of conversion functions
+ var toC = {
+ 'string': (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'
+ ret = stringToUTF8OnStack(str);
+ }
+ return ret;
+ },
+ 'array': (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];
+ }
+ }
+ }
+ // Data for a previous async operation that was in flight before us.
+ var previousAsync = Asyncify.currData;
+ var ret = func.apply(null, cArgs);
+ function onDone(ret) {
+ runtimeKeepalivePop();
+ if (stack !== 0) stackRestore(stack);
+ return convertReturnValue(ret);
+ }
+ var asyncMode = opts && opts.async;
+
+ // Keep the runtime alive through all calls. Note that this call might not be
+ // async, but for simplicity we push and pop in all calls.
+ runtimeKeepalivePush();
+ if (Asyncify.currData != previousAsync) {
+ // This is a new async operation. The wasm is paused and has unwound its stack.
+ // We need to return a Promise that resolves the return value
+ // once the stack is rewound and execution finishes.
+ return Asyncify.whenDone().then(onDone);
+ }
+
+ ret = onDone(ret);
+ // If this is an async ccall, ensure we return a promise
+ if (asyncMode) return Promise.resolve(ret);
+ return ret;
+ };
+
+
+ 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.createPreloadedFile = FS_createPreloadedFile;
+ FS.staticInit();Module["FS_createPath"] = FS.createPath;Module["FS_createDataFile"] = FS.createDataFile;Module["FS_createPreloadedFile"] = FS.createPreloadedFile;Module["FS_unlink"] = FS.unlink;Module["FS_createLazyFile"] = FS.createLazyFile;Module["FS_createDevice"] = FS.createDevice;;
+PHPWASM.init();;
+var wasmImports = {
+ __assert_fail: ___assert_fail,
+ __call_sighandler: ___call_sighandler,
+ __syscall__newselect: ___syscall__newselect,
+ __syscall_accept4: ___syscall_accept4,
+ __syscall_bind: ___syscall_bind,
+ __syscall_chdir: ___syscall_chdir,
+ __syscall_chmod: ___syscall_chmod,
+ __syscall_connect: ___syscall_connect,
+ __syscall_dup: ___syscall_dup,
+ __syscall_dup3: ___syscall_dup3,
+ __syscall_faccessat: ___syscall_faccessat,
+ __syscall_fallocate: ___syscall_fallocate,
+ __syscall_fchmod: ___syscall_fchmod,
+ __syscall_fchown32: ___syscall_fchown32,
+ __syscall_fchownat: ___syscall_fchownat,
+ __syscall_fcntl64: ___syscall_fcntl64,
+ __syscall_fdatasync: ___syscall_fdatasync,
+ __syscall_fstat64: ___syscall_fstat64,
+ __syscall_ftruncate64: ___syscall_ftruncate64,
+ __syscall_getcwd: ___syscall_getcwd,
+ __syscall_getdents64: ___syscall_getdents64,
+ __syscall_getpeername: ___syscall_getpeername,
+ __syscall_getsockname: ___syscall_getsockname,
+ __syscall_getsockopt: ___syscall_getsockopt,
+ __syscall_ioctl: ___syscall_ioctl,
+ __syscall_listen: ___syscall_listen,
+ __syscall_lstat64: ___syscall_lstat64,
+ __syscall_mkdirat: ___syscall_mkdirat,
+ __syscall_newfstatat: ___syscall_newfstatat,
+ __syscall_openat: ___syscall_openat,
+ __syscall_pipe: ___syscall_pipe,
+ __syscall_poll: ___syscall_poll,
+ __syscall_readlinkat: ___syscall_readlinkat,
+ __syscall_recvfrom: ___syscall_recvfrom,
+ __syscall_renameat: ___syscall_renameat,
+ __syscall_rmdir: ___syscall_rmdir,
+ __syscall_sendto: ___syscall_sendto,
+ __syscall_socket: ___syscall_socket,
+ __syscall_stat64: ___syscall_stat64,
+ __syscall_statfs64: ___syscall_statfs64,
+ __syscall_symlink: ___syscall_symlink,
+ __syscall_unlinkat: ___syscall_unlinkat,
+ __syscall_utimensat: ___syscall_utimensat,
+ _emscripten_get_now_is_monotonic: __emscripten_get_now_is_monotonic,
+ _emscripten_throw_longjmp: __emscripten_throw_longjmp,
+ _gmtime_js: __gmtime_js,
+ _localtime_js: __localtime_js,
+ _mktime_js: __mktime_js,
+ _mmap_js: __mmap_js,
+ _munmap_js: __munmap_js,
+ _setitimer_js: __setitimer_js,
+ _tzset_js: __tzset_js,
+ abort: _abort,
+ emscripten_date_now: _emscripten_date_now,
+ emscripten_get_heap_max: _emscripten_get_heap_max,
+ emscripten_get_now: _emscripten_get_now,
+ emscripten_memcpy_big: _emscripten_memcpy_big,
+ emscripten_resize_heap: _emscripten_resize_heap,
+ emscripten_sleep: _emscripten_sleep,
+ environ_get: _environ_get,
+ environ_sizes_get: _environ_sizes_get,
+ exit: _exit,
+ fd_close: _fd_close,
+ fd_fdstat_get: _fd_fdstat_get,
+ fd_read: _fd_read,
+ fd_seek: _fd_seek,
+ fd_sync: _fd_sync,
+ fd_write: _fd_write,
+ getaddrinfo: _getaddrinfo,
+ getcontext: _getcontext,
+ getdtablesize: _getdtablesize,
+ gethostbyname_r: _gethostbyname_r,
+ getloadavg: _getloadavg,
+ getnameinfo: _getnameinfo,
+ getprotobyname: _getprotobyname,
+ getprotobynumber: _getprotobynumber,
+ invoke_i: invoke_i,
+ invoke_ii: invoke_ii,
+ invoke_iii: invoke_iii,
+ invoke_iiii: invoke_iiii,
+ invoke_iiiii: invoke_iiiii,
+ invoke_iiiiii: invoke_iiiiii,
+ invoke_iiiiiii: invoke_iiiiiii,
+ invoke_iiiiiiii: invoke_iiiiiiii,
+ invoke_iiiiiiiiii: invoke_iiiiiiiiii,
+ invoke_v: invoke_v,
+ invoke_vi: invoke_vi,
+ invoke_vii: invoke_vii,
+ invoke_viidii: invoke_viidii,
+ invoke_viii: invoke_viii,
+ invoke_viiii: invoke_viiii,
+ invoke_viiiii: invoke_viiiii,
+ invoke_viiiiii: invoke_viiiiii,
+ invoke_viiiiiiiii: invoke_viiiiiiiii,
+ js_create_input_device: _js_create_input_device,
+ js_fd_read: _js_fd_read,
+ js_module_onMessage: _js_module_onMessage,
+ js_open_process: _js_open_process,
+ js_popen_to_file: _js_popen_to_file,
+ js_process_status: _js_process_status,
+ js_waitpid: _js_waitpid,
+ makecontext: _makecontext,
+ proc_exit: _proc_exit,
+ strftime: _strftime,
+ strptime: _strptime,
+ swapcontext: _swapcontext,
+ wasm_poll_socket: _wasm_poll_socket,
+ wasm_setsockopt: _wasm_setsockopt
+};
+var asm = createWasm();
+/** @type {function(...*):?} */
+var ___wasm_call_ctors = function() {
+ return (___wasm_call_ctors = Module['asm']['__wasm_call_ctors']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _free = function() {
+ return (_free = Module['asm']['free']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _memcpy = function() {
+ return (_memcpy = Module['asm']['memcpy']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _malloc = function() {
+ return (_malloc = Module['asm']['malloc']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var setTempRet0 = function() {
+ return (setTempRet0 = Module['asm']['setTempRet0']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var ___errno_location = function() {
+ return (___errno_location = Module['asm']['__errno_location']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _wasm_popen = Module['_wasm_popen'] = function() {
+ return (_wasm_popen = Module['_wasm_popen'] = Module['asm']['wasm_popen']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _wasm_php_exec = Module['_wasm_php_exec'] = function() {
+ return (_wasm_php_exec = Module['_wasm_php_exec'] = Module['asm']['wasm_php_exec']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _php_pollfd_for = Module['_php_pollfd_for'] = function() {
+ return (_php_pollfd_for = Module['_php_pollfd_for'] = Module['asm']['php_pollfd_for']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _htons = function() {
+ return (_htons = Module['asm']['htons']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _ntohs = function() {
+ return (_ntohs = Module['asm']['ntohs']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _htonl = function() {
+ return (_htonl = Module['asm']['htonl']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _wasm_sleep = Module['_wasm_sleep'] = function() {
+ return (_wasm_sleep = Module['_wasm_sleep'] = Module['asm']['wasm_sleep']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _fflush = Module['_fflush'] = function() {
+ return (_fflush = Module['_fflush'] = Module['asm']['fflush']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _wasm_read = Module['_wasm_read'] = function() {
+ return (_wasm_read = Module['_wasm_read'] = Module['asm']['wasm_read']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _wasm_set_sapi_name = Module['_wasm_set_sapi_name'] = function() {
+ return (_wasm_set_sapi_name = Module['_wasm_set_sapi_name'] = Module['asm']['wasm_set_sapi_name']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _wasm_set_phpini_path = Module['_wasm_set_phpini_path'] = function() {
+ return (_wasm_set_phpini_path = Module['_wasm_set_phpini_path'] = Module['asm']['wasm_set_phpini_path']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _wasm_set_phpini_entries = Module['_wasm_set_phpini_entries'] = function() {
+ return (_wasm_set_phpini_entries = Module['_wasm_set_phpini_entries'] = Module['asm']['wasm_set_phpini_entries']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _wasm_add_SERVER_entry = Module['_wasm_add_SERVER_entry'] = function() {
+ return (_wasm_add_SERVER_entry = Module['_wasm_add_SERVER_entry'] = Module['asm']['wasm_add_SERVER_entry']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _wasm_add_ENV_entry = Module['_wasm_add_ENV_entry'] = function() {
+ return (_wasm_add_ENV_entry = Module['_wasm_add_ENV_entry'] = Module['asm']['wasm_add_ENV_entry']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _wasm_set_query_string = Module['_wasm_set_query_string'] = function() {
+ return (_wasm_set_query_string = Module['_wasm_set_query_string'] = Module['asm']['wasm_set_query_string']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _wasm_set_path_translated = Module['_wasm_set_path_translated'] = function() {
+ return (_wasm_set_path_translated = Module['_wasm_set_path_translated'] = Module['asm']['wasm_set_path_translated']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _wasm_set_skip_shebang = Module['_wasm_set_skip_shebang'] = function() {
+ return (_wasm_set_skip_shebang = Module['_wasm_set_skip_shebang'] = Module['asm']['wasm_set_skip_shebang']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _wasm_set_request_uri = Module['_wasm_set_request_uri'] = function() {
+ return (_wasm_set_request_uri = Module['_wasm_set_request_uri'] = Module['asm']['wasm_set_request_uri']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _wasm_set_request_method = Module['_wasm_set_request_method'] = function() {
+ return (_wasm_set_request_method = Module['_wasm_set_request_method'] = Module['asm']['wasm_set_request_method']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _wasm_set_request_host = Module['_wasm_set_request_host'] = function() {
+ return (_wasm_set_request_host = Module['_wasm_set_request_host'] = Module['asm']['wasm_set_request_host']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _wasm_set_content_type = Module['_wasm_set_content_type'] = function() {
+ return (_wasm_set_content_type = Module['_wasm_set_content_type'] = Module['asm']['wasm_set_content_type']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _wasm_set_request_body = Module['_wasm_set_request_body'] = function() {
+ return (_wasm_set_request_body = Module['_wasm_set_request_body'] = Module['asm']['wasm_set_request_body']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _wasm_set_content_length = Module['_wasm_set_content_length'] = function() {
+ return (_wasm_set_content_length = Module['_wasm_set_content_length'] = Module['asm']['wasm_set_content_length']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _wasm_set_cookies = Module['_wasm_set_cookies'] = function() {
+ return (_wasm_set_cookies = Module['_wasm_set_cookies'] = Module['asm']['wasm_set_cookies']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _wasm_set_php_code = Module['_wasm_set_php_code'] = function() {
+ return (_wasm_set_php_code = Module['_wasm_set_php_code'] = Module['asm']['wasm_set_php_code']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _wasm_set_request_port = Module['_wasm_set_request_port'] = function() {
+ return (_wasm_set_request_port = Module['_wasm_set_request_port'] = Module['asm']['wasm_set_request_port']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _wasm_sapi_handle_request = Module['_wasm_sapi_handle_request'] = function() {
+ return (_wasm_sapi_handle_request = Module['_wasm_sapi_handle_request'] = Module['asm']['wasm_sapi_handle_request']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _php_wasm_init = Module['_php_wasm_init'] = function() {
+ return (_php_wasm_init = Module['_php_wasm_init'] = Module['asm']['php_wasm_init']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var ___funcs_on_exit = function() {
+ return (___funcs_on_exit = Module['asm']['__funcs_on_exit']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _emscripten_builtin_memalign = function() {
+ return (_emscripten_builtin_memalign = Module['asm']['emscripten_builtin_memalign']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var __emscripten_timeout = function() {
+ return (__emscripten_timeout = Module['asm']['_emscripten_timeout']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _setThrew = function() {
+ return (_setThrew = Module['asm']['setThrew']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _emscripten_stack_set_limits = function() {
+ return (_emscripten_stack_set_limits = Module['asm']['emscripten_stack_set_limits']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _emscripten_stack_get_base = function() {
+ return (_emscripten_stack_get_base = Module['asm']['emscripten_stack_get_base']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _emscripten_stack_get_end = function() {
+ return (_emscripten_stack_get_end = Module['asm']['emscripten_stack_get_end']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var stackSave = function() {
+ return (stackSave = Module['asm']['stackSave']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var stackRestore = function() {
+ return (stackRestore = Module['asm']['stackRestore']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var stackAlloc = function() {
+ return (stackAlloc = Module['asm']['stackAlloc']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_iiii = Module['dynCall_iiii'] = function() {
+ return (dynCall_iiii = Module['dynCall_iiii'] = Module['asm']['dynCall_iiii']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_ii = Module['dynCall_ii'] = function() {
+ return (dynCall_ii = Module['dynCall_ii'] = Module['asm']['dynCall_ii']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_vi = Module['dynCall_vi'] = function() {
+ return (dynCall_vi = Module['dynCall_vi'] = Module['asm']['dynCall_vi']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_viiiii = Module['dynCall_viiiii'] = function() {
+ return (dynCall_viiiii = Module['dynCall_viiiii'] = Module['asm']['dynCall_viiiii']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_iii = Module['dynCall_iii'] = function() {
+ return (dynCall_iii = Module['dynCall_iii'] = Module['asm']['dynCall_iii']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_iiiii = Module['dynCall_iiiii'] = function() {
+ return (dynCall_iiiii = Module['dynCall_iiiii'] = Module['asm']['dynCall_iiiii']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_iiiiii = Module['dynCall_iiiiii'] = function() {
+ return (dynCall_iiiiii = Module['dynCall_iiiiii'] = Module['asm']['dynCall_iiiiii']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_vii = Module['dynCall_vii'] = function() {
+ return (dynCall_vii = Module['dynCall_vii'] = Module['asm']['dynCall_vii']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_viii = Module['dynCall_viii'] = function() {
+ return (dynCall_viii = Module['dynCall_viii'] = Module['asm']['dynCall_viii']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_v = Module['dynCall_v'] = function() {
+ return (dynCall_v = Module['dynCall_v'] = Module['asm']['dynCall_v']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_i = Module['dynCall_i'] = function() {
+ return (dynCall_i = Module['dynCall_i'] = Module['asm']['dynCall_i']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_viiii = Module['dynCall_viiii'] = function() {
+ return (dynCall_viiii = Module['dynCall_viiii'] = Module['asm']['dynCall_viiii']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_iiiiiii = Module['dynCall_iiiiiii'] = function() {
+ return (dynCall_iiiiiii = Module['dynCall_iiiiiii'] = Module['asm']['dynCall_iiiiiii']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_vij = Module['dynCall_vij'] = function() {
+ return (dynCall_vij = Module['dynCall_vij'] = Module['asm']['dynCall_vij']).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_viiiiiiii = Module['dynCall_viiiiiiii'] = function() {
+ return (dynCall_viiiiiiii = Module['dynCall_viiiiiiii'] = Module['asm']['dynCall_viiiiiiii']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_viiiiiiiii = Module['dynCall_viiiiiiiii'] = function() {
+ return (dynCall_viiiiiiiii = Module['dynCall_viiiiiiiii'] = Module['asm']['dynCall_viiiiiiiii']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_viiiiiii = Module['dynCall_viiiiiii'] = function() {
+ return (dynCall_viiiiiii = Module['dynCall_viiiiiii'] = Module['asm']['dynCall_viiiiiii']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_viiiiii = Module['dynCall_viiiiii'] = function() {
+ return (dynCall_viiiiii = Module['dynCall_viiiiii'] = Module['asm']['dynCall_viiiiii']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_iiiiiiii = Module['dynCall_iiiiiiii'] = function() {
+ return (dynCall_iiiiiiii = Module['dynCall_iiiiiiii'] = Module['asm']['dynCall_iiiiiiii']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_iiid = Module['dynCall_iiid'] = function() {
+ return (dynCall_iiid = Module['dynCall_iiid'] = Module['asm']['dynCall_iiid']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_iiiiiiiii = Module['dynCall_iiiiiiiii'] = function() {
+ return (dynCall_iiiiiiiii = Module['dynCall_iiiiiiiii'] = Module['asm']['dynCall_iiiiiiiii']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_iiiiiiiiii = Module['dynCall_iiiiiiiiii'] = function() {
+ return (dynCall_iiiiiiiiii = Module['dynCall_iiiiiiiiii'] = Module['asm']['dynCall_iiiiiiiiii']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_iiiij = Module['dynCall_iiiij'] = function() {
+ return (dynCall_iiiij = Module['dynCall_iiiij'] = Module['asm']['dynCall_iiiij']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_vijii = Module['dynCall_vijii'] = function() {
+ return (dynCall_vijii = Module['dynCall_vijii'] = Module['asm']['dynCall_vijii']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_iijj = Module['dynCall_iijj'] = function() {
+ return (dynCall_iijj = Module['dynCall_iijj'] = Module['asm']['dynCall_iijj']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_iij = Module['dynCall_iij'] = function() {
+ return (dynCall_iij = Module['dynCall_iij'] = Module['asm']['dynCall_iij']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_iijii = Module['dynCall_iijii'] = function() {
+ return (dynCall_iijii = Module['dynCall_iijii'] = Module['asm']['dynCall_iijii']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_iiji = Module['dynCall_iiji'] = function() {
+ return (dynCall_iiji = Module['dynCall_iiji'] = Module['asm']['dynCall_iiji']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_iiiiiij = Module['dynCall_iiiiiij'] = function() {
+ return (dynCall_iiiiiij = Module['dynCall_iiiiiij'] = Module['asm']['dynCall_iiiiiij']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_iiij = Module['dynCall_iiij'] = function() {
+ return (dynCall_iiij = Module['dynCall_iiij'] = Module['asm']['dynCall_iiij']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_dii = Module['dynCall_dii'] = function() {
+ return (dynCall_dii = Module['dynCall_dii'] = Module['asm']['dynCall_dii']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_jii = Module['dynCall_jii'] = function() {
+ return (dynCall_jii = Module['dynCall_jii'] = Module['asm']['dynCall_jii']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_vid = Module['dynCall_vid'] = function() {
+ return (dynCall_vid = Module['dynCall_vid'] = Module['asm']['dynCall_vid']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_di = Module['dynCall_di'] = function() {
+ return (dynCall_di = Module['dynCall_di'] = Module['asm']['dynCall_di']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_iiiiijii = Module['dynCall_iiiiijii'] = function() {
+ return (dynCall_iiiiijii = Module['dynCall_iiiiijii'] = Module['asm']['dynCall_iiiiijii']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_j = Module['dynCall_j'] = function() {
+ return (dynCall_j = Module['dynCall_j'] = Module['asm']['dynCall_j']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_jj = Module['dynCall_jj'] = function() {
+ return (dynCall_jj = Module['dynCall_jj'] = Module['asm']['dynCall_jj']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_jiij = Module['dynCall_jiij'] = function() {
+ return (dynCall_jiij = Module['dynCall_jiij'] = Module['asm']['dynCall_jiij']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_iiiiji = Module['dynCall_iiiiji'] = function() {
+ return (dynCall_iiiiji = Module['dynCall_iiiiji'] = Module['asm']['dynCall_iiiiji']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_iiiijii = Module['dynCall_iiiijii'] = function() {
+ return (dynCall_iiiijii = Module['dynCall_iiiijii'] = Module['asm']['dynCall_iiiijii']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_ij = Module['dynCall_ij'] = function() {
+ return (dynCall_ij = Module['dynCall_ij'] = Module['asm']['dynCall_ij']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_viiji = Module['dynCall_viiji'] = function() {
+ return (dynCall_viiji = Module['dynCall_viiji'] = Module['asm']['dynCall_viiji']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_viijii = Module['dynCall_viijii'] = function() {
+ return (dynCall_viijii = Module['dynCall_viijii'] = Module['asm']['dynCall_viijii']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_iiiiiiiiiii = Module['dynCall_iiiiiiiiiii'] = function() {
+ return (dynCall_iiiiiiiiiii = Module['dynCall_iiiiiiiiiii'] = Module['asm']['dynCall_iiiiiiiiiii']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_iiiijji = Module['dynCall_iiiijji'] = function() {
+ return (dynCall_iiiijji = Module['dynCall_iiiijji'] = Module['asm']['dynCall_iiiijji']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_dd = Module['dynCall_dd'] = function() {
+ return (dynCall_dd = Module['dynCall_dd'] = Module['asm']['dynCall_dd']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_ddd = Module['dynCall_ddd'] = function() {
+ return (dynCall_ddd = Module['dynCall_ddd'] = Module['asm']['dynCall_ddd']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_viidii = Module['dynCall_viidii'] = function() {
+ return (dynCall_viidii = Module['dynCall_viidii'] = Module['asm']['dynCall_viidii']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_jiiji = Module['dynCall_jiiji'] = function() {
+ return (dynCall_jiiji = Module['dynCall_jiiji'] = Module['asm']['dynCall_jiiji']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_jiiiji = Module['dynCall_jiiiji'] = function() {
+ return (dynCall_jiiiji = Module['dynCall_jiiiji'] = Module['asm']['dynCall_jiiiji']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_iiiji = Module['dynCall_iiiji'] = function() {
+ return (dynCall_iiiji = Module['dynCall_iiiji'] = Module['asm']['dynCall_iiiji']).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_iidiiii = Module['dynCall_iidiiii'] = function() {
+ return (dynCall_iidiiii = Module['dynCall_iidiiii'] = Module['asm']['dynCall_iidiiii']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _asyncify_start_unwind = function() {
+ return (_asyncify_start_unwind = Module['asm']['asyncify_start_unwind']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _asyncify_stop_unwind = function() {
+ return (_asyncify_stop_unwind = Module['asm']['asyncify_stop_unwind']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _asyncify_start_rewind = function() {
+ return (_asyncify_start_rewind = Module['asm']['asyncify_start_rewind']).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _asyncify_stop_rewind = function() {
+ return (_asyncify_stop_rewind = Module['asm']['asyncify_stop_rewind']).apply(null, arguments);
+};
+
+
+function invoke_iiiiiii(index,a1,a2,a3,a4,a5,a6) {
+ var sp = stackSave();
+ try {
+ return dynCall_iiiiiii(index,a1,a2,a3,a4,a5,a6);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
+}
+
+function invoke_vi(index,a1) {
+ var sp = stackSave();
+ try {
+ dynCall_vi(index,a1);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
+}
+
+function invoke_iiii(index,a1,a2,a3) {
+ var sp = stackSave();
+ try {
+ return dynCall_iiii(index,a1,a2,a3);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
+}
+
+function invoke_iii(index,a1,a2) {
+ var sp = stackSave();
+ try {
+ return dynCall_iii(index,a1,a2);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
+}
+
+function invoke_vii(index,a1,a2) {
+ var sp = stackSave();
+ try {
+ dynCall_vii(index,a1,a2);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
+}
+
+function invoke_ii(index,a1) {
+ var sp = stackSave();
+ try {
+ return dynCall_ii(index,a1);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
+}
+
+function invoke_viii(index,a1,a2,a3) {
+ var sp = stackSave();
+ try {
+ dynCall_viii(index,a1,a2,a3);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
+}
+
+function invoke_v(index) {
+ var sp = stackSave();
+ try {
+ dynCall_v(index);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
+}
+
+function invoke_i(index) {
+ var sp = stackSave();
+ try {
+ return dynCall_i(index);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
+}
+
+function invoke_viiii(index,a1,a2,a3,a4) {
+ var sp = stackSave();
+ try {
+ dynCall_viiii(index,a1,a2,a3,a4);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
+}
+
+function invoke_viiiii(index,a1,a2,a3,a4,a5) {
+ var sp = stackSave();
+ try {
+ dynCall_viiiii(index,a1,a2,a3,a4,a5);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
+}
+
+function invoke_iiiiii(index,a1,a2,a3,a4,a5) {
+ var sp = stackSave();
+ try {
+ return dynCall_iiiiii(index,a1,a2,a3,a4,a5);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
+}
+
+function invoke_iiiii(index,a1,a2,a3,a4) {
+ var sp = stackSave();
+ try {
+ return dynCall_iiiii(index,a1,a2,a3,a4);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
+}
+
+function invoke_iiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9) {
+ var sp = stackSave();
+ try {
+ return dynCall_iiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
+}
+
+function invoke_viiiiii(index,a1,a2,a3,a4,a5,a6) {
+ var sp = stackSave();
+ try {
+ dynCall_viiiiii(index,a1,a2,a3,a4,a5,a6);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
+}
+
+function invoke_viidii(index,a1,a2,a3,a4,a5) {
+ var sp = stackSave();
+ try {
+ dynCall_viidii(index,a1,a2,a3,a4,a5);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
+}
+
+function invoke_viiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9) {
+ var sp = stackSave();
+ try {
+ dynCall_viiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
+}
+
+function invoke_iiiiiiii(index,a1,a2,a3,a4,a5,a6,a7) {
+ var sp = stackSave();
+ try {
+ return dynCall_iiiiiiii(index,a1,a2,a3,a4,a5,a6,a7);
+ } catch(e) {
+ stackRestore(sp);
+ if (e !== e+0) throw e;
+ _setThrew(1, 0);
+ }
+}
+
+
+// include: postamble.js
+// === Auto-generated postamble setup entry stuff ===
+
+// include: base64Utils.js
+// Converts a string of base64 into a byte array.
+// Throws error on invalid input.
+function intArrayFromBase64(s) {
+
+ try {
+ var decoded = atob(s);
+ var bytes = new Uint8Array(decoded.length);
+ for (var i = 0 ; i < decoded.length ; ++i) {
+ bytes[i] = decoded.charCodeAt(i);
+ }
+ return bytes;
+ } catch (_) {
+ throw new Error('Converting base64 string to bytes failed.');
+ }
+}
+
+// If filename is a base64 data URI, parses and returns data (Buffer on node,
+// Uint8Array otherwise). If filename is not a base64 data URI, returns undefined.
+function tryParseAsDataURI(filename) {
+ if (!isDataURI(filename)) {
+ return;
+ }
+
+ return intArrayFromBase64(filename.slice(dataURIPrefix.length));
+}
+// end include: base64Utils.js
+Module['addRunDependency'] = addRunDependency;
+Module['removeRunDependency'] = removeRunDependency;
+Module['FS_createPath'] = FS.createPath;
+Module['FS_createDataFile'] = FS.createDataFile;
+Module['FS_createLazyFile'] = FS.createLazyFile;
+Module['FS_createDevice'] = FS.createDevice;
+Module['FS_unlink'] = FS.unlink;
+Module['ccall'] = ccall;
+Module['FS_createPreloadedFile'] = FS.createPreloadedFile;
+
+
+var calledRun;
+
+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 run() {
+
+ 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();
+
+ if (Module['onRuntimeInitialized']) Module['onRuntimeInitialized']();
+
+ postRun();
+ }
+
+ if (Module['setStatus']) {
+ Module['setStatus']('Running...');
+ setTimeout(function() {
+ setTimeout(function() {
+ Module['setStatus']('');
+ }, 1);
+ doRun();
+ }, 1);
+ } else
+ {
+ doRun();
+ }
+}
+
+if (Module['preInit']) {
+ if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']];
+ while (Module['preInit'].length > 0) {
+ Module['preInit'].pop()();
+ }
+}
+
+run();
+
+
+// end include: postamble.js
/**
* Emscripten resolves `localhost` to a random IP address. Let's
* make it always resolve to 127.0.0.1.
diff --git a/packages/php-wasm/web/src/lib/api.ts b/packages/php-wasm/web/src/lib/api.ts
index 7875db0ec5..3840e23343 100644
--- a/packages/php-wasm/web/src/lib/api.ts
+++ b/packages/php-wasm/web/src/lib/api.ts
@@ -82,17 +82,47 @@ export function exposeAPI(
let setReady: any;
let setFailed: any;
const ready = new Promise((resolve, reject) => {
- setReady = resolve;
+ setReady = (arg) => {
+ console.log('About to call resolve()!');
+ resolve(arg);
+ };
setFailed = reject;
+ }).then(() => {
+ console.log('ready.then()!');
});
const methods = proxyClone(apiMethods);
const exposedApi = new Proxy(methods, {
get: (target, prop) => {
if (prop === 'isConnected') {
- return () => connected;
+ console.log('exposedApi.isConnected() requested');
+ return async () => {
+ console.log('exposedApi.isConnected() called');
+ /*
+ * If exposeAPI() is called after this function,
+ * the isConnected() call will hang forever. Let's
+ * retry it a few times.
+ */
+ for (let i = 0; i < 10; i++) {
+ try {
+ await runWithTimeout(connected, 200);
+ break;
+ } catch (e) {
+ // Timeout exceeded, try again
+ }
+ }
+ return connected.then(() => {
+ console.log('exposedApi.isConnected().then()');
+ });
+ };
} else if (prop === 'isReady') {
- return () => ready;
+ console.log('exposedApi.isReady requested');
+ return () => {
+ console.log('exposedApi.isReady called');
+ return ready.then(() => {
+ console.log('exposedApi.isReady().then()');
+ });
+ };
} else if (prop in target) {
return target[prop];
}
diff --git a/packages/php-wasm/web/src/lib/index.ts b/packages/php-wasm/web/src/lib/index.ts
index 780062297a..32ee347c83 100644
--- a/packages/php-wasm/web/src/lib/index.ts
+++ b/packages/php-wasm/web/src/lib/index.ts
@@ -2,7 +2,7 @@ export * from './api';
export type { WithAPIState as WithIsReady } from './api';
export type { PHPWebLoaderOptions } from './web-php';
-export { WebPHP } from './web-php';
+export { WebPHP, CAPem } from './web-php';
export { WebPHPEndpoint } from './web-php-endpoint';
export { getPHPLoaderModule } from './get-php-loader-module';
export { registerServiceWorker } from './register-service-worker';
diff --git a/packages/php-wasm/web/src/lib/web-php.ts b/packages/php-wasm/web/src/lib/web-php.ts
index 27b976a236..2ab0d495c3 100644
--- a/packages/php-wasm/web/src/lib/web-php.ts
+++ b/packages/php-wasm/web/src/lib/web-php.ts
@@ -8,6 +8,8 @@ import {
} from '@php-wasm/universal';
import { EmscriptenDownloadMonitor } from '@php-wasm/progress';
import { getPHPLoaderModule } from './get-php-loader-module';
+import * as forge from 'node-forge';
+import { Certificate } from 'crypto';
export interface PHPWebLoaderOptions {
emscriptenOptions?: EmscriptenOptions;
@@ -28,6 +30,7 @@ const fakeWebsocket = () => {
decorator: (WebSocketConstructor: any) => {
return class FakeWebsocketConstructor extends WebSocketConstructor {
constructor() {
+ console.log('Called constructor()!');
try {
super();
} catch (e) {
@@ -36,6 +39,7 @@ const fakeWebsocket = () => {
}
send() {
+ console.log('Called send()!');
return null;
}
};
@@ -44,6 +48,560 @@ const fakeWebsocket = () => {
};
};
+async function generateKeys() {
+ const keyPair = await crypto.subtle.generateKey(
+ {
+ name: 'ECDH',
+ namedCurve: 'P-256',
+ },
+ true,
+ ['deriveKey']
+ );
+ return keyPair;
+}
+
+function createCertificate({ commonName }) {
+ // create certificate
+ var pki = forge.pki;
+ var keys = pki.rsa.generateKeyPair(2048);
+ var cert = pki.createCertificate();
+ cert.publicKey = keys.publicKey;
+ // alternatively set public key from a csr
+ //cert.publicKey = csr.publicKey;
+ // NOTE: serialNumber is the hex encoded value of an ASN.1 INTEGER.
+ // Conforming CAs should ensure serialNumber is:
+ // - no more than 20 octets
+ // - non-negative (prefix a '00' if your value starts with a '1' bit)
+ cert.serialNumber = '01';
+ cert.validity.notBefore = new Date();
+ cert.validity.notAfter = new Date();
+ cert.validity.notAfter.setFullYear(
+ cert.validity.notBefore.getFullYear() + 1
+ );
+ var attrs = [
+ {
+ name: 'commonName',
+ value: commonName,
+ },
+ {
+ name: 'countryName',
+ value: 'US',
+ },
+ {
+ shortName: 'ST',
+ value: 'Virginia',
+ },
+ {
+ name: 'localityName',
+ value: 'Blacksburg',
+ },
+ {
+ name: 'organizationName',
+ value: 'Test',
+ },
+ {
+ shortName: 'OU',
+ value: 'Test',
+ },
+ ];
+ cert.setSubject(attrs);
+ // alternatively set subject from a csr
+ //cert.setSubject(csr.subject.attributes);
+ cert.setIssuer(attrs);
+ cert.setExtensions([
+ {
+ name: 'basicConstraints',
+ cA: true,
+ },
+ {
+ name: 'keyUsage',
+ keyCertSign: true,
+ digitalSignature: true,
+ nonRepudiation: true,
+ keyEncipherment: true,
+ dataEncipherment: true,
+ },
+ {
+ name: 'extKeyUsage',
+ serverAuth: true,
+ clientAuth: true,
+ codeSigning: true,
+ emailProtection: true,
+ timeStamping: true,
+ },
+ {
+ name: 'nsCertType',
+ client: true,
+ server: true,
+ email: true,
+ objsign: true,
+ sslCA: true,
+ emailCA: true,
+ objCA: true,
+ },
+ {
+ name: 'subjectAltName',
+ altNames: [
+ {
+ type: 6, // URI
+ value: '*.org',
+ },
+ {
+ type: 7, // IP
+ ip: '127.0.0.1',
+ },
+ ],
+ },
+ {
+ name: 'subjectKeyIdentifier',
+ },
+ ]);
+ // FIXME: add subjectKeyIdentifier extension
+ // FIXME: add authorityKeyIdentifier extension
+ cert.publicKey = keys.publicKey;
+
+ // self-sign certificate
+ cert.sign(keys.privateKey);
+
+ // console.log('certificate created for \"' + forge.pki.certificateToPem(cert) + '\": \n' + forge.pki.privateKeyToPem(keys.privateKey));
+ return { certificate: cert, privateKey: keys.privateKey };
+}
+
+// Introduce artificial delay to test the race
+// condition when initializing the Playground client.
+// for (let i = 0; i < 2; i++) {
+// createCertificate();
+// }
+
+// @TODO: Create these certificates in FetchWebsocketConstructor based on the requested host
+const { certificate, privateKey } = createCertificate({
+ commonName: 'downloads.wordpress.org', //wsUrl.searchParams.get('host') || ''
+});
+const CAPair = { certificate, privateKey };
+// const CAPair = createCertificate({
+// commonName: ''
+// });
+export const CAPem = forge.pki.certificateToPem(CAPair.certificate);
+/**
+ * Websocket that buffers the received bytes and translates them into
+ * a fetch() call.
+ */
+const fetchingWebsocket = (phpModuleArgs: EmscriptenOptions = {}) => {
+ return {
+ websocket: {
+ ...(phpModuleArgs['websocket'] || {}),
+ url: (_: any, host: string, port: string) => {
+ const query = new URLSearchParams({
+ host,
+ port,
+ }).toString();
+ return `ws://playground.internal/?${query}`;
+ },
+ subprotocol: 'binary',
+ decorator: () => {
+ return class FetchWebsocketConstructor {
+ CONNECTING = 0;
+ OPEN = 1;
+ CLOSING = 2;
+ CLOSED = 3;
+ readyState = this.CONNECTING;
+ binaryType = 'blob';
+ bufferedAmount = 0;
+ extensions = '';
+ protocol = 'ws';
+ host = '';
+ port = 0;
+ listeners = new Map();
+ sslServer: any;
+ isPlaintext: boolean | null = null;
+
+ constructor(public url: string, public options: string[]) {
+ const wsUrl = new URL(url);
+ this.host = wsUrl.searchParams.get('host')!;
+ this.port = parseInt(
+ wsUrl.searchParams.get('port')!,
+ 10
+ );
+
+ const ws = this;
+ try {
+ this.sslServer = forge.tls.createConnection({
+ server: true,
+ caStore: forge.pki.createCaStore([
+ CAPair.certificate,
+ ]),
+ sessionCache: {},
+ // supported cipher suites in order of preference
+ cipherSuites: [
+ forge.tls.CipherSuites
+ .TLS_RSA_WITH_AES_128_CBC_SHA,
+ forge.tls.CipherSuites
+ .TLS_RSA_WITH_AES_256_CBC_SHA,
+ ],
+ // require a client-side certificate if you want
+ verifyClient: false,
+ verify: function (
+ connection,
+ verified,
+ depth,
+ certs
+ ) {
+ console.log('Verify ');
+ if (depth === 0) {
+ var cn =
+ certs[0].subject.getField(
+ 'CN'
+ ).value;
+ if (cn !== 'the-client') {
+ verified = {
+ alert: forge.tls.Alert
+ .Description
+ .bad_certificate,
+ message:
+ 'Certificate common name does not match expected client.',
+ };
+ }
+ }
+ return verified;
+ },
+ connected: function (connection) {
+ console.log(
+ 'Sending an encrypted message back to the client!'
+ );
+ // send message to client
+
+ console.log({ connection });
+
+ // connection.prepare(forge.util.encodeUtf8(
+ // `HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 12\r\n\r\nHello World!`
+ // ));
+
+ /* NOTE: experimental, start heartbeat retransmission timer
+ myHeartbeatTimer = setInterval(function() {
+ connection.prepareHeartbeatRequest(forge.util.createBuffer('1234'));
+ }, 5*60*1000);*/
+ },
+ getCertificate: function (connection, hint) {
+ console.log('====> getCertificate');
+ // return certificate;
+ // This should return Pem, I think
+ return forge.pki.certificateToPem(
+ certificate
+ );
+ },
+ getPrivateKey: function (connection, cert) {
+ console.log('====> getPrivateKey');
+ // return privateKey;
+ // This should return Pem, I think
+ return forge.pki.privateKeyToPem(
+ privateKey
+ );
+ },
+ tlsDataReady: function (connection) {
+ console.log('TLS data ready to be sent');
+ console.log({ connection });
+ const byteString =
+ connection.tlsData.getBytes();
+ const byteArray = new Uint8Array(
+ byteString.length
+ );
+ for (
+ let i = 0;
+ i < byteString.length;
+ i++
+ ) {
+ byteArray[i] = byteString.charCodeAt(i);
+ }
+ // TLS data (encrypted) is ready to be sent to the client
+ ws.emit('message', { data: byteArray });
+ // if you were communicating with the client above you'd do:
+ // client.process(connection.tlsData.getBytes());
+ },
+ dataReady: function (connection) {
+ // clear data from the client is ready
+ const receivedData = forge.util.decodeUtf8(
+ connection.data.getBytes()
+ );
+ if (receivedData === '') {
+ return;
+ }
+ console.log(
+ 'Clear data received: ' + receivedData
+ );
+
+ // @TODO: stream data from multiple dataReady calls in case the
+ // client, say, uploads a large file
+ setTimeout(() => {
+ httpRequestToFetch(
+ ws.host,
+ ws.port,
+ receivedData,
+ (data) =>
+ connection.prepare(
+ uint8ArrayToBinaryString(
+ new Uint8Array(data)
+ )
+ ),
+ () => connection.close()
+ );
+ });
+ console.log({ connection });
+
+ // close connection
+ // connection.close();
+ },
+ /* NOTE: experimental
+ heartbeatReceived: function(connection, payload) {
+ // restart retransmission timer, look at payload
+ clearInterval(myHeartbeatTimer);
+ myHeartbeatTimer = setInterval(function() {
+ connection.prepareHeartbeatRequest(forge.util.createBuffer('1234'));
+ }, 5*60*1000);
+ payload.getBytes();
+ },*/
+ closed: function (connection) {
+ console.log('disconnected');
+ },
+ error: function (connection, error) {
+ console.log(connection);
+ console.log('uh oh', error);
+ },
+ });
+ } catch (e) {
+ console.error(e);
+ }
+ setTimeout(() => {
+ this.readyState = this.OPEN;
+ this.emit('open');
+ });
+ }
+
+ on(eventName: string, callback: (e: any) => void) {
+ this.addEventListener(eventName, callback);
+ }
+
+ once(eventName: string, callback: (e: any) => void) {
+ const wrapper = (e: any) => {
+ callback(e);
+ this.removeEventListener(eventName, wrapper);
+ };
+ this.addEventListener(eventName, wrapper);
+ }
+
+ addEventListener(
+ eventName: string,
+ callback: (e: any) => void
+ ) {
+ // console.log("Adding listener for ", eventName, " event");
+ if (!this.listeners.has(eventName)) {
+ this.listeners.set(eventName, new Set());
+ }
+ this.listeners.get(eventName).add(callback);
+ }
+
+ removeListener(
+ eventName: string,
+ callback: (e: any) => void
+ ) {
+ this.removeEventListener(eventName, callback);
+ }
+
+ removeEventListener(
+ eventName: string,
+ callback: (e: any) => void
+ ) {
+ const listeners = this.listeners.get(eventName);
+ if (listeners) {
+ listeners.delete(callback);
+ }
+ }
+
+ emit(eventName: string, data: any = {}) {
+ // console.log("dispatching ", eventName, " event");
+ if (eventName === 'message') {
+ this.onmessage(data);
+ } else if (eventName === 'close') {
+ this.onclose(data);
+ } else if (eventName === 'error') {
+ this.onerror(data);
+ } else if (eventName === 'open') {
+ this.onopen(data);
+ }
+ const listeners = this.listeners.get(eventName);
+ if (listeners) {
+ for (const listener of listeners) {
+ listener(eventName, data);
+ }
+ }
+ }
+
+ onclose(data: any) {}
+ onerror(data: any) {}
+ onmessage(data: any) {}
+ onopen(data: any) {}
+
+ send(data: ArrayBuffer) {
+ console.log('Send called with ', data);
+ try {
+ if (this.isPlaintext === null) {
+ // If it's a HTTP request, we can just fetch it
+ // @TODO: This is very naive. Let's find a more robust way of detecting if
+ // it's a HTTP request
+ const string = new TextDecoder().decode(data);
+ const firstLine = string.split('\n')[0];
+ const [, , version] = firstLine.split(' ');
+ this.isPlaintext = version?.startsWith('HTTP');
+ }
+ if (this.isPlaintext) {
+ this.close();
+ // httpRequestToFetch(
+ // this.host,
+ // this.port,
+ // new TextDecoder().decode(data),
+ // (data) => this.emit('message', { data }),
+ // () => this.close()
+ // );
+ // console.log('fetch() sent');
+ return;
+ } else {
+ // If it's a HTTPS request, we'll pretend to be the server
+ // and negotiate a secure connection
+ console.log(new TextDecoder().decode(data));
+ this.sslServer.process(
+ uint8ArrayToBinaryString(
+ new Uint8Array(data)
+ )
+ );
+ }
+ return null;
+ } catch (e) {
+ console.log('Failed to fetch');
+ console.error(e);
+ }
+ }
+
+ close() {
+ console.log('Called close()!');
+ this.readyState = this.CLOSING;
+ this.emit('close');
+ this.readyState = this.CLOSED;
+ }
+ };
+ },
+ },
+ };
+};
+
+function httpRequestToFetch(
+ host: string,
+ port: number,
+ httpRequest: string,
+ onData: (data: ArrayBuffer) => void,
+ onDone: () => void
+) {
+ const firstLine = httpRequest.split('\n')[0];
+ const [method, path] = firstLine.split(' ');
+
+ const headers = new Headers();
+ for (const line of httpRequest.split('\r\n').slice(1)) {
+ if (line === '') {
+ break;
+ }
+ const [name, value] = line.split(': ');
+ console.log({ name, value });
+ headers.set(name, value);
+ }
+ // This is a naive implementation that doesn't handle
+ // PHP writing arbitrary Host headers to IP addresses,
+ // but it's the best we can do in the browser.
+ const protocol = port === 443 ? 'https' : 'http';
+ // @TODO: Decide which host to use. The header is less reliable,
+ // but in some cases it's more useful. E.g. the Host header
+ // may be `localhost` when `host` is 127.0.0.1, and, to
+ // run the fetch() request, we need to use the former since
+ // the latter may not respond to requests. Similarly,
+ // PHP may run requests to arbitrary IP addresses with
+ // the Host header set to a domain name, and we need to
+ // pass a valid domain to fetch().
+ const hostname = headers.get('Host')
+ ? headers.get('Host')
+ : [80, 443].includes(port)
+ ? host
+ : `${host}:${port}`;
+ const url = new URL(path, protocol + '://' + hostname).toString();
+ console.log({ httpRequest, method, url });
+
+ return fetch(url, {
+ method,
+ headers,
+ })
+ .then((response) => {
+ console.log('====> Got fetch() response!', response);
+ const reader = response.body?.getReader();
+ if (reader) {
+ const responseHeader = new TextEncoder().encode(
+ `HTTP/1.1 ${response.status} ${response.statusText}\r\n${[
+ ...response.headers,
+ ]
+ .map(([name, value]) => `${name}: ${value}`)
+ .join('\r\n')}\r\n\r\n`
+ );
+
+ // @TODO: calling onData() and waiting for more reader chunks
+ // passes the control back to PHP.wasm and never yields
+ // the control back to JavaScript. It's likely a polling
+ // issue, or perhaps something specific to a Symfony HTTP
+ // client. Either way, PHP blocks the thread and the
+ // read().then() callback is never called.
+ // We should find a way to yield the control back to
+ // JavaScript after each onData() call.
+ //
+ // One clue is PHP runs out of memory when onData() blocks
+ // the event loop. Then it fails with a regular PHP fatal error
+ // message. Perhaps there's an infinite loop somewhere that
+ // fails to correctly poll and increases the memory usage indefinitely.
+ const buffer = [responseHeader.buffer];
+ const read = () => {
+ console.log('Attempt to read the response stream');
+ reader
+ .read()
+ .then(({ done, value }) => {
+ // console.log("got some data", value);
+ if (done) {
+ // @TODO let's stream the chunks as they
+ // arrive without buffering them
+ for (const chunk of buffer) {
+ onData(chunk);
+ }
+ onDone();
+ return;
+ }
+ buffer.push(value.buffer);
+ read();
+ })
+ .catch((e) => {
+ console.error(e);
+ });
+ };
+ read();
+ }
+ })
+ .catch((e) => {
+ console.log('Could not fetch ', url);
+ console.error(e);
+ throw e;
+ });
+}
+
+function uint8ArrayToBinaryString(bytes: Uint8Array) {
+ const binary = [];
+ const len = bytes.byteLength;
+ for (let i = 0; i < len; i++) {
+ binary.push(String.fromCharCode(bytes[i]));
+ }
+ return binary.join('');
+}
+
export class WebPHP extends BasePHP {
/**
* Creates a new PHP instance.
@@ -81,7 +639,7 @@ export class WebPHP extends BasePHP {
});
return await loadPHPRuntime(phpLoaderModule, {
...(options.emscriptenOptions || {}),
- ...fakeWebsocket(),
+ ...fetchingWebsocket(),
});
}
}
diff --git a/packages/playground/blueprints/src/lib/steps/wp-cli.spec.ts b/packages/playground/blueprints/src/lib/steps/wp-cli.spec.ts
index 6e2e439cd1..a05e994431 100644
--- a/packages/playground/blueprints/src/lib/steps/wp-cli.spec.ts
+++ b/packages/playground/blueprints/src/lib/steps/wp-cli.spec.ts
@@ -1,5 +1,5 @@
import { NodePHP } from '@php-wasm/node';
-import { splitShellCommand, wpCLI } from './wp-cli';
+import { wpCLI } from './wp-cli';
import { readFileSync } from 'fs';
import { join } from 'path';
import { unzip } from './unzip';
@@ -32,29 +32,3 @@ describe('Blueprint step wpCLI', () => {
expect(result.text).toMatch(/Success: Created post/);
});
});
-
-describe('splitShellCommand', () => {
- it('Should split a shell command into an array', () => {
- const command =
- 'wp post create --post_title="Test post" --post_excerpt="Some content"';
- const result = splitShellCommand(command);
- expect(result).toEqual([
- 'wp',
- 'post',
- 'create',
- '--post_title=Test post',
- '--post_excerpt=Some content',
- ]);
- });
-
- it('Should treat multiple spaces as a single space', () => {
- const command = 'ls --wordpress --playground --is-great';
- const result = splitShellCommand(command);
- expect(result).toEqual([
- 'ls',
- '--wordpress',
- '--playground',
- '--is-great',
- ]);
- });
-});
diff --git a/packages/playground/blueprints/src/lib/steps/wp-cli.ts b/packages/playground/blueprints/src/lib/steps/wp-cli.ts
index f56e3ffac8..7d95238339 100644
--- a/packages/playground/blueprints/src/lib/steps/wp-cli.ts
+++ b/packages/playground/blueprints/src/lib/steps/wp-cli.ts
@@ -1,6 +1,6 @@
import { PHPResponse } from '@php-wasm/universal';
import { StepHandler } from '.';
-import { phpVar } from '@php-wasm/util';
+import { phpVar, splitShellCommand } from '@php-wasm/util';
/**
* @inheritDoc wpCLI
@@ -86,53 +86,3 @@ export const wpCLI: StepHandler> = async (
return result;
};
-
-/**
- * Naive shell command parser.
- * Ensures that commands like `wp option set blogname "My blog name"` are split into
- * `['wp', 'option', 'set', 'blogname', 'My blog name']` instead of
- * `['wp', 'option', 'set', 'blogname', 'My', 'blog', 'name']`.
- *
- * @param command
- * @returns
- */
-export function splitShellCommand(command: string) {
- const MODE_NORMAL = 0;
- const MODE_IN_QUOTE = 1;
-
- let mode = MODE_NORMAL;
- let quote = '';
-
- const parts: string[] = [];
- let currentPart = '';
- for (let i = 0; i < command.length; i++) {
- const char = command[i];
- if (mode === MODE_NORMAL) {
- if (char === '"' || char === "'") {
- mode = MODE_IN_QUOTE;
- quote = char;
- } else if (char.match(/\s/)) {
- if (currentPart) {
- parts.push(currentPart);
- }
- currentPart = '';
- } else {
- currentPart += char;
- }
- } else if (mode === MODE_IN_QUOTE) {
- if (char === '\\') {
- i++;
- currentPart += command[i];
- } else if (char === quote) {
- mode = MODE_NORMAL;
- quote = '';
- } else {
- currentPart += char;
- }
- }
- }
- if (currentPart) {
- parts.push(currentPart);
- }
- return parts;
-}
diff --git a/packages/playground/client/src/index.ts b/packages/playground/client/src/index.ts
index deb097b8e3..9e2892dbf8 100644
--- a/packages/playground/client/src/index.ts
+++ b/packages/playground/client/src/index.ts
@@ -83,6 +83,7 @@ export async function startPlaygroundWeb({
progress: progressTracker.stage(0.5),
onStepCompleted: onBlueprintStepCompleted,
});
+ console.log('calling doStartPlaygroundWeb');
const playground = await doStartPlaygroundWeb(
iframe,
setQueryParams(remoteUrl, {
@@ -94,7 +95,9 @@ export async function startPlaygroundWeb({
}),
progressTracker
);
+ console.log('after doStartPlaygroundWeb');
await runBlueprintSteps(compiled, playground);
+ console.log('after runBlueprintSteps');
progressTracker.finish();
return playground;
@@ -143,12 +146,20 @@ async function doStartPlaygroundWeb(
const playground = consumeAPI(
iframe.contentWindow!
) as PlaygroundClient;
+ console.log('[CLIENT] playground.isConnected()::before');
await playground.isConnected();
+ console.log('[CLIENT] playground.isConnected()::after');
progressTracker.pipe(playground);
const downloadPHPandWP = progressTracker.stage();
- await playground.onDownloadProgress(downloadPHPandWP.loadingListener);
+ console.log('[CLIENT] playground.onDownloadProgress()::before');
+ playground.onDownloadProgress(downloadPHPandWP.loadingListener);
+ console.log('[CLIENT] playground.onDownloadProgress()::after');
+ console.log('[CLIENT] playground.isReady()::before');
await playground.isReady();
+ console.log('[CLIENT] playground.isReady()::after');
downloadPHPandWP.finish();
+ console.log('[CLIENT] after downloadPHPandWP');
+
return playground;
}
diff --git a/packages/playground/remote/src/lib/boot-playground-remote.ts b/packages/playground/remote/src/lib/boot-playground-remote.ts
index 4b1e558d27..49addd0301 100644
--- a/packages/playground/remote/src/lib/boot-playground-remote.ts
+++ b/packages/playground/remote/src/lib/boot-playground-remote.ts
@@ -216,19 +216,31 @@ export async function bootPlaygroundRemote() {
const [setAPIReady, setAPIError, playground] = exposeAPI(webApi, workerApi);
try {
+ console.log('[REMOTE] workerApi.isReady()::before');
await workerApi.isReady();
+ console.log('[REMOTE] workerApi.isReady()::after');
await registerServiceWorker(
workerApi,
await workerApi.scope,
serviceWorkerUrl + ''
);
+ console.log('[REMOTE] registerServiceWorker()::after');
setupPostMessageRelay(wpFrame, getOrigin(await playground.absoluteUrl));
if (withNetworking) {
+ console.log(
+ '[REMOTE] registsetupFetchNetworkTransporterServiceWorker()::before'
+ );
await setupFetchNetworkTransport(workerApi);
+ console.log(
+ '[REMOTE] registsetupFetchNetworkTransporterServiceWorker()::after'
+ );
}
+ console.log('[REMOTE] setAPIReady()::before');
setAPIReady();
+ console.log('[REMOTE] setAPIReady()::after');
} catch (e) {
+ console.error(e);
setAPIError(e as Error);
throw e;
}
diff --git a/packages/playground/remote/src/lib/opfs/bind-opfs.ts b/packages/playground/remote/src/lib/opfs/bind-opfs.ts
index b1c72014b9..a6b4d1b390 100644
--- a/packages/playground/remote/src/lib/opfs/bind-opfs.ts
+++ b/packages/playground/remote/src/lib/opfs/bind-opfs.ts
@@ -13,7 +13,7 @@ import { __private__dont__use } from '@php-wasm/universal';
import { Semaphore, joinPaths } from '@php-wasm/util';
import type { WebPHP } from '@php-wasm/web';
import { EmscriptenFS } from './types';
-import { journalFSEventsToOpfs } from './journal-memfs-to-opfs';
+import { journalFSEventsToOpfs } from './journal-fs-to-opfs';
let unbindOpfs: (() => void) | undefined;
export type SyncProgress = {
diff --git a/packages/playground/remote/src/lib/opfs/journal-memfs-to-opfs.ts b/packages/playground/remote/src/lib/opfs/journal-fs-to-opfs.ts
similarity index 98%
rename from packages/playground/remote/src/lib/opfs/journal-memfs-to-opfs.ts
rename to packages/playground/remote/src/lib/opfs/journal-fs-to-opfs.ts
index a3aaee344c..5d32933dd2 100644
--- a/packages/playground/remote/src/lib/opfs/journal-memfs-to-opfs.ts
+++ b/packages/playground/remote/src/lib/opfs/journal-fs-to-opfs.ts
@@ -10,7 +10,6 @@
/* eslint-disable prefer-rest-params */
import type { WebPHP } from '@php-wasm/web';
-import type { EmscriptenFS } from './types';
import { FilesystemOperation, journalFSEvents } from '@php-wasm/fs-journal';
import { __private__dont__use } from '@php-wasm/universal';
import { copyMemfsToOpfs, overwriteOpfsFile } from './bind-opfs';
@@ -48,7 +47,6 @@ export function journalFSEventsToOpfs(
type JournalEntry = FilesystemOperation;
class OpfsRewriter {
- private FS: EmscriptenFS;
private memfsRoot: string;
constructor(
diff --git a/packages/playground/remote/src/lib/opfs/journal-fs-to-php.ts b/packages/playground/remote/src/lib/opfs/journal-fs-to-php.ts
new file mode 100644
index 0000000000..4176129ce4
--- /dev/null
+++ b/packages/playground/remote/src/lib/opfs/journal-fs-to-php.ts
@@ -0,0 +1,97 @@
+/**
+ * Synchronize MEMFS changes from a PHP instance into another PHP instance.
+ */
+
+/* eslint-disable prefer-rest-params */
+import type { WebPHP } from '@php-wasm/web';
+import { FilesystemOperation, journalFSEvents } from '@php-wasm/fs-journal';
+import { basename, normalizePath } from '@php-wasm/util';
+
+export function journalFSEventsToPhp(
+ sourcePhp: WebPHP,
+ targetPhp: WebPHP,
+ root: string
+) {
+ root = normalizePath(root);
+
+ const journal: FilesystemOperation[] = [];
+ const unbindJournal = journalFSEvents(sourcePhp, root, (entry) => {
+ if (
+ // entry.path.endsWith('/.ht.sqlite') ||
+ entry.path.endsWith('/.ht.sqlite-journal')
+ ) {
+ return;
+ }
+ journal.push(entry);
+ });
+ const rewriter = new MemfsRewriter(sourcePhp, targetPhp, root);
+
+ async function flushJournal() {
+ // @TODO This is way too slow in practice, we need to batch the
+ // changes into groups of parallelizable operations.
+ while (journal.length) {
+ rewriter.processEntry(journal.shift()!);
+ }
+ }
+ sourcePhp.addEventListener('request.end', flushJournal);
+ return function () {
+ unbindJournal();
+ sourcePhp.removeEventListener('request.end', flushJournal);
+ };
+}
+
+type JournalEntry = FilesystemOperation;
+
+class MemfsRewriter {
+ constructor(
+ private sourcePhp: WebPHP,
+ private targetPhp: WebPHP,
+ private root: string
+ ) {}
+
+ public processEntry(entry: JournalEntry) {
+ if (!entry.path.startsWith(this.root) || entry.path === this.root) {
+ return;
+ }
+ const name = basename(entry.path);
+ if (!name) {
+ return;
+ }
+
+ try {
+ if (entry.operation === 'DELETE') {
+ try {
+ if (this.targetPhp.isDir(entry.path)) {
+ this.targetPhp.rmdir(entry.path);
+ } else {
+ this.targetPhp.unlink(entry.path);
+ }
+ } catch (e) {
+ // If the directory already doesn't exist, it's fine
+ }
+ } else if (entry.operation === 'CREATE') {
+ if (entry.nodeType === 'directory') {
+ this.targetPhp.mkdir(entry.path);
+ } else {
+ this.targetPhp.writeFile(entry.path, '');
+ }
+ } else if (entry.operation === 'WRITE') {
+ this.targetPhp.writeFile(
+ entry.path,
+ this.sourcePhp.readFileAsBuffer(entry.path)
+ );
+ } else if (
+ entry.operation === 'RENAME' &&
+ entry.toPath.startsWith(this.root)
+ ) {
+ this.targetPhp.mv(entry.path, entry.toPath);
+ }
+ } catch (e) {
+ // Useful for debugging – the original error gets lost in the
+ // Comlink proxy.
+ console.log({ entry, name });
+ console.error(e);
+ throw e;
+ }
+ }
+}
diff --git a/packages/playground/remote/src/lib/setup-fetch-network-transport.ts b/packages/playground/remote/src/lib/setup-fetch-network-transport.ts
index be6128fb46..04a76d4ad3 100644
--- a/packages/playground/remote/src/lib/setup-fetch-network-transport.ts
+++ b/packages/playground/remote/src/lib/setup-fetch-network-transport.ts
@@ -58,6 +58,7 @@ export async function setupFetchNetworkTransport(playground: UniversalPHP) {
export async function handleRequest(data: RequestData, fetchFn = fetch) {
const hostname = new URL(data.url).hostname;
+ console.log(data.url, { hostname, data });
const fetchUrl = ['w.org', 's.w.org'].includes(hostname)
? `/plugin-proxy.php?url=${encodeURIComponent(data.url)}`
: data.url;
diff --git a/packages/playground/remote/src/lib/worker-thread.ts b/packages/playground/remote/src/lib/worker-thread.ts
index 8c3cd76c73..5610444da2 100644
--- a/packages/playground/remote/src/lib/worker-thread.ts
+++ b/packages/playground/remote/src/lib/worker-thread.ts
@@ -1,4 +1,4 @@
-import { WebPHP, WebPHPEndpoint, exposeAPI } from '@php-wasm/web';
+import { CAPem, WebPHP, WebPHPEndpoint, exposeAPI } from '@php-wasm/web';
import { EmscriptenDownloadMonitor } from '@php-wasm/progress';
import { setURLScope } from '@php-wasm/scopes';
import { DOCROOT, wordPressSiteUrl } from './config';
@@ -9,13 +9,15 @@ import {
SupportedWordPressVersionsList,
} from '@wp-playground/wordpress';
import {
+ PHPResponse,
SupportedPHPExtension,
SupportedPHPVersion,
SupportedPHPVersionsList,
rotatePHPRuntime,
+ syncFSTo,
writeFiles,
} from '@php-wasm/universal';
-import { createSpawnHandler } from '@php-wasm/util';
+import { createSpawnHandler, phpVar } from '@php-wasm/util';
import {
FilesystemOperation,
journalFSEvents,
@@ -39,6 +41,7 @@ import transportDummy from './playground-mu-plugin/playground-includes/wp_http_d
/** @ts-ignore */
import playgroundMuPlugin from './playground-mu-plugin/0-playground.php?raw';
import { joinPaths, randomString } from '@php-wasm/util';
+import { journalFSEventsToPhp } from './opfs/journal-fs-to-php';
// post message to parent
self.postMessage('worker-script-started');
@@ -238,6 +241,9 @@ try {
if (startupOptions.sapiName) {
await php.setSapiName(startupOptions.sapiName);
}
+ php.setPhpIniEntry('allow_url_fopen', 'On');
+ php.setPhpIniEntry('openssl.cafile', '/tmp/ca-bundle.crt');
+ php.writeFile('/tmp/ca-bundle.crt', CAPem);
const docroot = php.documentRoot;
// If WordPress isn't already installed, download and extract it from
@@ -293,12 +299,57 @@ try {
siteUrl: scopedSiteUrl,
});
+ php.writeFile(
+ joinPaths(docroot, 'spawn.php'),
+ `";
+ echo "Spawning /wordpress/child.php\n";
+ $handle = proc_open('php /wordpress/child.php', [
+ 0 => ['pipe', 'r'],
+ 1 => ['pipe', 'w'],
+ 2 => ['pipe', 'w'],
+ ], $pipes);
+
+ echo "stdout: " . stream_get_contents($pipes[1]) . "\n";
+ echo "stderr: " . stream_get_contents($pipes[2]) . "\n";
+ echo "Finished\n";
+ echo "Contents of the created file: " . file_get_contents("/wordpress/new.txt") . "\n";
+ `
+ );
+
+ php.writeFile(
+ joinPaths(docroot, 'child.php'),
+ `";
+ echo "Spawned, running";
+ error_log("Here's a message logged to stderr! " . rand());
+ file_put_contents("/wordpress/new.txt", "Hello, world!" . rand() . "\n");
+ `
+ );
+
+ // PHP Subprocess to handle proc_open("php");
+ // @TODO: Use this also for HTTP Requests
+ let childPHP: WebPHP | undefined = undefined;
+
// Spawning new processes on the web is not supported,
// let's always fail.
php.setSpawnHandler(
- createSpawnHandler(function (command, processApi) {
+ createSpawnHandler(async function (
+ [command, ...args],
+ processApi,
+ options
+ ) {
+ if (command === 'exec') {
+ command = args[0];
+ args = args.slice(1);
+ }
+
// Mock programs required by wp-cli:
- if (command.startsWith('/usr/bin/env stty size ')) {
+ if (
+ command === '/usr/bin/env' &&
+ args[0] === 'stty' &&
+ args[1] === 'size'
+ ) {
// These numbers are hardcoded because this
// spawnHandler is transmitted as a string to
// the PHP backend and has no access to local
@@ -307,19 +358,163 @@ try {
// @TODO: Do not hardcode this
processApi.stdout(`18 140`);
processApi.exit(0);
- } else if (command.startsWith('less')) {
+ return;
+ } else if (command === 'less') {
processApi.on('stdin', (data: Uint8Array) => {
processApi.stdout(data);
});
processApi.flushStdin();
processApi.exit(0);
+ return;
+ } else if (command === 'fetch') {
+ console.log('=========== FETCH ==========');
+ // Ignore STDIN
+ processApi.on('stdin', (data: Uint8Array) => {
+ console.log({ data });
+ });
+ processApi.flushStdin();
+ fetch(args[0]).then(async (res) => {
+ const reader = res.body?.getReader();
+ console.log('Got a reader');
+ if (!reader) {
+ console.log('EXIT 1');
+ processApi.exit(1);
+ return;
+ }
+ while (true) {
+ const { done, value } = await reader.read();
+ // console.log({value, done})
+ if (done) {
+ console.log('STD OUT end');
+ processApi.exit(0);
+ break;
+ }
+ processApi.stdout(value);
+ }
+ });
+ return;
+ } else if (command === 'php') {
+ if (!childPHP) {
+ childPHP = new WebPHP(await recreateRuntime(), {
+ documentRoot: DOCROOT,
+ absoluteUrl: scopedSiteUrl,
+ });
+ //
+ childPHP.setSapiName('cli');
+ } else {
+ try {
+ // Remove the document root to ensure that the
+ // child PHP instance is in a clean state.
+ // The journal seems to stay around longer than
+ // expected and this `rmdir` removes the `/wordpress`
+ // directory in the parent process.
+ // @TODO: Fix this
+ // childPHP.rmdir(childPHP.documentRoot);
+ } catch (e) {
+ // Ignore errors
+ }
+ }
+ let unbind = () => {};
+ let result: PHPResponse | undefined = undefined;
+ try {
+ syncFSTo(php, childPHP);
+ // @TODO: Either make sure syncFs goes through the entire
+ // directory tree each time, or kill the childPHP
+ // instance after each command. Otherwise, the
+ // childPHP instance won't be able to find the files
+ // created by the parent PHP instance.
+ syncFSTo(php, childPHP, '/tmp');
+ unbind = journalFSEventsToPhp(
+ childPHP,
+ php,
+ // @TODO: Sync both directories and any other
+ // relevant paths. OR, don't run
+ // blueprints outside of docroot :-)
+ childPHP.documentRoot // options.cwd ||
+ );
+ // @TODO: Run the actual PHP CLI SAPI instead of
+ // interpreting the arguments here.
+ if (args.includes('-r')) {
+ const script =
+ `WordPress Playground demos
Playground.
+ -
+ Blueprints PHP library
+
-
WP-CLI
diff --git a/packages/playground/website/demos/php-blueprints.html b/packages/playground/website/demos/php-blueprints.html
new file mode 100644
index 0000000000..f2c5b46e1b
--- /dev/null
+++ b/packages/playground/website/demos/php-blueprints.html
@@ -0,0 +1,30 @@
+
+
+ Blueprints PHP library
+
+
+
+
+
+ Blueprints PHP library
+
+ Uses the
+ PHP implementation of Blueprints
+ to set up a WordPress site. Open the devtools for full output.
+
+
+
+
+ Partial output:
+
+
+
diff --git a/packages/playground/website/demos/php-blueprints.ts b/packages/playground/website/demos/php-blueprints.ts
new file mode 100644
index 0000000000..abd5e2cf01
--- /dev/null
+++ b/packages/playground/website/demos/php-blueprints.ts
@@ -0,0 +1,227 @@
+import { startPlaygroundWeb } from '@wp-playground/client';
+import { getRemoteUrl } from '../src/lib/config';
+import { joinPaths } from '@php-wasm/util';
+export {};
+
+const iframe = document.querySelector('iframe')!;
+console.log('calling startPlaygroundWeb');
+const playground = await startPlaygroundWeb({
+ iframe,
+ remoteUrl: getRemoteUrl().toString(),
+ blueprint: {
+ preferredVersions: {
+ wp: 'latest',
+ // Required for the PHP library to run:
+ php: '8.2',
+ },
+ features: {
+ networking: true,
+ },
+ // landingPage: '/wp-content/index.php',
+ landingPage: '/',
+ // Required for the PHP library to run:
+ phpExtensionBundles: ['kitchen-sink'],
+ },
+});
+
+console.log('fetching the blueprints');
+const response = await fetch('./blueprints.phar');
+const phar = new Uint8Array(await response.arrayBuffer());
+await playground.writeFile(
+ joinPaths(await playground.documentRoot, 'blueprints.phar'),
+ phar
+);
+const outputDiv = document.getElementById('output')!;
+
+console.log('Running the PHP code');
+// For now, let's try to get a remote network call to work
+// const result = await playground.run({
+// code: ` [
+// 'method' => 'GET',
+// 'header' => 'Content-type: text/plain',
+// 'content' => 'Some body :)',
+// ],
+// ];
+// // $context = stream_context_create($opts);
+// // echo file_get_contents("https://localhost:5400/website-server/", false, $context);
+
+// // fopen, write some headers
+// // $fp = fsockopen("ssl://localhost:5400/website-server/", 443, $errno, $errstr, 30);
+// // fwrite($fp, "GET / HTTP/1.1\\r\\nHost: localhost:5400\\r\\nContent-type: text/plain\\r\\nConnection: close\\r\\n\\r\\nSome body :)");
+// // Get the response
+// // while (!feof($fp)) {
+// // echo fgets($fp, 128);
+// // }
+// // fclose($fp);
+// `,
+// throwOnError: true,
+// });
+// console.log(result.text);
+// throw new Error('Done!');
+
+try {
+ // Clean the WordPress directory so the Blueprints library
+ // may use it to extract WordPress.
+ // await playground.mv('/wordpress/blueprints.phar', '/tmp/blueprints.phar');
+ // await playground.rmdir('/wordpress');
+ // await playground.mkdir('/wordpress');
+ // await playground.mv('/tmp/blueprints.phar', '/wordpress/blueprints.phar');
+
+ // For now this only runs with ?php=8.2&php-extension-bundle=kitchen-sink
+ // ?php=8.2&php-extension-bundle=kitchen-sink
+ // const result = await playground.run({
+ // code:` $value) {
+ // update_option($name, $value);
+ // }
+ // echo "Done :)";
+ // '
+ // ],
+ // [
+ // 0 => ['pipe', 'r'],
+ // 1 => ['pipe', 'w'],
+ // 2 => ['pipe', 'w'],
+ // ],
+ // $pipes,
+ // "/wordpress",
+ // [
+ // "DOCROOT" => "/wordpress",
+ // "OPTIONS" => '{"blogname":"My Playground Blog"}',
+ // ]
+ // );
+ // if (is_resource($fp)) {
+ // echo stream_get_contents($pipes[1]);
+ // fclose($pipes[1]);
+ // fclose($pipes[2]);
+ // var_dump("Calling proc_close!");
+ // $exit_code = proc_close($fp);
+ // var_dump("Finished proc_close!");
+ // var_dump($exit_code);
+ // }
+ // `,
+ // env: {
+ // DOCROOT: '/wordpress',
+ // OPTIONS: JSON.stringify({
+ // 'blogname': 'My Playground Blog',
+ // }),
+ // },
+ // throwOnError: true,
+ // });
+ // console.log({ result });
+
+ const wpCliRequest = fetch(
+ 'https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar'
+ );
+ const wpCliResponse = await wpCliRequest;
+ const wpCli = await wpCliResponse.arrayBuffer();
+ await playground.writeFile('/wordpress/wp-cli.phar', new Uint8Array(wpCli));
+
+ const result = await playground.run({
+ code: ` "check-requirements": false,
+ * Then requiring it breaks http and https requests:
+ *
+ * > echo file_get_contents('http://localhost:5400/website-server/');
+ * > Warning: PHP Request Startup: Failed to open stream: Operation timed out in php-wasm run script on line 13
+ *
+ * The check is therefore disabled for now.
+ */
+ require '/wordpress/blueprints.phar';
+
+ $blueprint = BlueprintBuilder::create()
+ // This isn't a WordPress zip file since wordpress.org
+ // doesn't expose the right CORS headers. It is a HTTPS-hosted
+ // zip file nonetheless, and we can use it for testing.
+ // Uncomment this as needed
+ // ->setWordPressVersion( 'https://downloads.wordpress.org/plugin/hello-dolly.1.7.3.zip' )
+
+ // And, by default, let's use a real WordPress zip file – even if it's
+ // downloaded via http, not https.
+ // ->withWordPressVersion( 'http://localhost:5400/website-server/demos/wordpress.zip' )
+ ->withFile( 'wordpress.txt', (new UrlResource())->setUrl('https://downloads.wordpress.org/plugin/hello-dolly.zip') )
+ ->withSiteOptions( [
+ 'blogname' => 'My Playground Blog',
+ ] )
+ ->withWpConfigConstants( [
+ 'WP_DEBUG' => true,
+ 'WP_DEBUG_LOG' => true,
+ 'WP_DEBUG_DISPLAY' => true,
+ 'WP_CACHE' => true,
+ ] )
+ ->withPlugins( [
+ 'https://downloads.wordpress.org/plugin/hello-dolly.zip',
+ // When the regular UrlDataSource is used, the second
+ // downloaded zip file always errors with:
+ // > Failed to open stream: Operation timed out
+ 'https://downloads.wordpress.org/plugin/classic-editor.zip',
+ 'https://downloads.wordpress.org/plugin/gutenberg.17.7.0.zip',
+ ] )
+ ->withTheme( 'https://downloads.wordpress.org/theme/pendant.zip' )
+ ->withContent( 'https://raw.githubusercontent.com/WordPress/theme-test-data/master/themeunittestdata.wordpress.xml' )
+ // ->withSiteUrl( 'http://localhost:8081' )
+ ->andRunSQL( <<<'SQL'
+ CREATE TABLE tmp_table ( id INT );
+ INSERT INTO tmp_table VALUES (1);
+ INSERT INTO tmp_table VALUES (2);
+ SQL
+ )
+ ->withFile( 'wordpress.txt', 'Data' )
+ ->toBlueprint()
+ ;
+
+ echo "BEFORE\\n\\n";
+ $results = run_blueprint( $blueprint, '/wordpress' );
+ echo "\\n\\nAFTER\\n\\n";
+ print_r(glob('/wordpress/*'));
+ print_r(glob('/wordpress/wp-content/plugins/*'));
+ // `,
+ throwOnError: true,
+ });
+
+ outputDiv.textContent = result.text;
+ console.log(result.text);
+} catch (e) {
+ console.error(e);
+ outputDiv.textContent = e + '';
+ throw e;
+}
+
+console.log(await playground.listFiles('/wordpress/wp-content/plugins'));
diff --git a/packages/playground/website/demos/wordpress.zip b/packages/playground/website/demos/wordpress.zip
new file mode 100644
index 0000000000..54825cf516
Binary files /dev/null and b/packages/playground/website/demos/wordpress.zip differ
diff --git a/packages/playground/website/tsconfig.app.json b/packages/playground/website/tsconfig.app.json
index 9b9b776920..2edc05ecaf 100644
--- a/packages/playground/website/tsconfig.app.json
+++ b/packages/playground/website/tsconfig.app.json
@@ -29,6 +29,7 @@
"demos/peer.ts",
"demos/terminal.ts",
"demos/terminal-component.tsx",
+ "demos/php-blueprints.ts",
"./cypress.config.ts"
]
}
diff --git a/packages/playground/wordpress/src/wordpress/wp-beta.zip b/packages/playground/wordpress/src/wordpress/wp-beta.zip
index 4ff9905ad9..fde8f41376 100644
Binary files a/packages/playground/wordpress/src/wordpress/wp-beta.zip and b/packages/playground/wordpress/src/wordpress/wp-beta.zip differ