diff --git a/packages/php-wasm/compile/Dockerfile b/packages/php-wasm/compile/Dockerfile index 3b346285f9..1961bd42b5 100644 --- a/packages/php-wasm/compile/Dockerfile +++ b/packages/php-wasm/compile/Dockerfile @@ -3,7 +3,7 @@ # emscripten/emsdk:3.1.24 supports amd64 only. FROM ubuntu:lunar as emscripten -SHELL ["/bin/bash", "-c"] +SHELL ["/bin/bash", "-l", "-c"] ENV PKG_CONFIG_PATH /root/lib/lib/pkgconfig ENV TIMER "(which pv > /dev/null && pv --name '${@}' || cat)" @@ -37,9 +37,18 @@ RUN set -euxo pipefail;\ # Docker image, but there is no arm64 image available which makes # the build take forever on Apple Silicon. RUN ln -s /usr/bin/python3 /usr/bin/python -RUN git clone https://github.com/emscripten-core/emsdk.git && \ - ./emsdk/emsdk install latest && \ - /root/emsdk/emsdk activate latest +RUN git clone https://github.com/emscripten-core/emsdk.git + +RUN curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash +RUN echo 'source /root/.nvm/nvm.sh' >> /root/.bashrc +RUN . /root/.nvm/nvm.sh && nvm install 20 + +RUN /root/emsdk/emsdk install latest +RUN /root/emsdk/emsdk list +RUN /root/emsdk/emsdk activate latest + +RUN . /root/.nvm/nvm.sh && echo 'NODE_JS = "'$(which node)'"' >> /root/emsdk/.emscripten + RUN mkdir -p /root/lib/lib /root/lib/include /root/lib/share /root/lib/bin @@ -120,8 +129,8 @@ RUN cd libzip/build && \ -DZLIB_LIBRARY=/root/lib/lib/libz.a \ -DZLIB_INCLUDE_DIR=/root/lib/include \ .. -RUN cd libzip/build && source /root/emsdk/emsdk_env.sh && EMCC_SKIP="-lz" EMCC_FLAGS=" -sSIDE_MODULE " emmake make -RUN cd libzip/build && source /root/emsdk/emsdk_env.sh && EMCC_SKIP="-lz" EMCC_FLAGS=" -sSIDE_MODULE " emmake make install +RUN cd libzip/build && source /root/emsdk/emsdk_env.sh && EMCC_SKIP="-lz" EMCC_FLAGS=" -sSIDE_MODULE -sUSE_PTHREADS=1 " emmake make +RUN cd libzip/build && source /root/emsdk/emsdk_env.sh && EMCC_SKIP="-lz" EMCC_FLAGS=" -sSIDE_MODULE -sUSE_PTHREADS=1 " emmake make install # Compile ncurses FROM emscripten AS emscripten-ncurses @@ -180,7 +189,7 @@ RUN wget https://www.thrysoee.dk/editline/libedit-20221030-3.1.tar.gz && \ # Musl is ISO 10646 compliant but doesn't define __STDC_ISO_10646__, so # let's define it manually. Learn more at: # http://lists.busybox.net/pipermail/buildroot/2016-January/149100.html - EMCC_SKIP="-lc -lncurses " EMCC_FLAGS=" -sSIDE_MODULE -D__STDC_ISO_10646__=201103L " \ + EMCC_SKIP="-lc -lncurses " EMCC_FLAGS=" -sSIDE_MODULE -sUSE_PTHREADS=1 -D__STDC_ISO_10646__=201103L " \ emmake make && \ emmake make install @@ -193,8 +202,8 @@ RUN source /root/emsdk/emsdk_env.sh && \ --depth 1 && \ cd libxml2 && \ ./autogen.sh && \ - emconfigure ./configure --with-http=no --with-ftp=no --with-python=no --with-threads=no --enable-shared=no --prefix=/root/lib/ &&\ - EMCC_FLAGS=" -sSIDE_MODULE " emmake make && \ + emconfigure ./configure --with-http=no --with-ftp=no --with-python=no --with-threads=yes --enable-shared=no --prefix=/root/lib/ &&\ + EMCC_FLAGS=" -sSIDE_MODULE -sUSE_PTHREADS=1 " emmake make && \ emmake make install # Compile Bison 2.7 (for PHP <=7.3) @@ -222,7 +231,7 @@ RUN set -euxo pipefail &&\ --build i386-pc-linux-gnu \ --target wasm32-unknown-emscripten \ --prefix=/root/lib/ && \ - EMCC_SKIP="-lc" EMCC_FLAGS=" -sSIDE_MODULE " emmake make && \ + EMCC_SKIP="-lc" EMCC_FLAGS=" -sSIDE_MODULE -sUSE_PTHREADS=1 " emmake make && \ emmake make install # Compile OpenSSL @@ -237,12 +246,12 @@ RUN set -euxo pipefail && \ wget https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz && \ tar xf openssl-$OPENSSL_VERSION.tar.gz && \ cd openssl-$OPENSSL_VERSION && \ - emconfigure ./Configure dist -DHAVE_FORK=0 -DOPENSSL_NO_AFALGENG=1 no-threads --prefix=/root/lib && \ + emconfigure ./Configure dist -DHAVE_FORK=0 -DOPENSSL_NO_AFALGENG=1 --prefix=/root/lib && \ sed -i 's|^CROSS_COMPILE.*$|CROSS_COMPILE=|g' Makefile && \ - EMCC_FLAGS=" -sSIDE_MODULE " EMCC_SKIP="-lz" emmake make -j 12 build_generated libssl.a libcrypto.a; \ + EMCC_FLAGS=" -sSIDE_MODULE -sUSE_PTHREADS=1 " EMCC_SKIP="-lz" emmake make -j 12 build_generated libssl.a libcrypto.a; \ cp -RL include/openssl /root/lib/include && \ cp libcrypto.a libssl.a /root/lib/lib && \ - EMCC_FLAGS=" -sSIDE_MODULE " EMCC_SKIP="-lz" emmake make install; + EMCC_FLAGS=" -sSIDE_MODULE -sUSE_PTHREADS=1 " EMCC_SKIP="-lz" emmake make install; # Compile libpng FROM emscripten AS emscripten-libpng @@ -259,7 +268,7 @@ RUN source /root/emsdk/emsdk_env.sh && \ --build i386-pc-linux-gnu \ --target wasm32-unknown-emscripten \ --prefix=/root/lib/ -RUN source /root/emsdk/emsdk_env.sh && EMCC_SKIP="-lc -lz" EMCC_FLAGS="-sSIDE_MODULE" emmake make +RUN source /root/emsdk/emsdk_env.sh && EMCC_SKIP="-lc -lz" EMCC_FLAGS="-sSIDE_MODULE -sUSE_PTHREADS=1" emmake make RUN source /root/emsdk/emsdk_env.sh && emmake make install # Clone PHP @@ -330,15 +339,16 @@ RUN if [ "$WITH_LIBZIP" = "yes" ]; then \ echo -n ' --with-zlib --with-zlib-dir=/root/lib --with-zip' >> /root/.php-configure-flags; \ echo -n ' -I /root/zlib -I /root/libzip' >> /root/.emcc-php-wasm-flags; \ echo -n ' /root/lib/lib/libzip.a /root/lib/lib/libz.a' >> /root/.emcc-php-wasm-sources; \ - fi && \ - /root/replace.sh 's/pharcmd=pharcmd/pharcmd=/g' /root/php-src/configure && \ - /root/replace.sh 's/pharcmd_install=install-pharcmd/pharcmd_install=/g' /root/php-src/configure; \ + fi; \ fi; +RUN /root/replace.sh 's/pharcmd=pharcmd/pharcmd=/g' /root/php-src/configure +RUN /root/replace.sh 's/pharcmd_install=install-pharcmd/pharcmd_install=/g' /root/php-src/configure; + # Add ncurses if needed and libedit if needed COPY --from=emscripten-libedit /root/lib /root/lib-libedit COPY --from=emscripten-ncurses /root/lib /root/lib-ncurses -RUN if [ "$WITH_CLI_SAPI" = "yes" ]; \ +RUN if [ "$WITH_CLI_SAPI" = "disabled" ]; \ then \ /root/copy-lib.sh lib-ncurses && \ /root/copy-lib.sh lib-libedit && \ @@ -463,6 +473,10 @@ RUN source /root/emsdk/emsdk_env.sh && \ # --enable-json for PHP < 8.0: --enable-json \ --enable-embed=static \ + --enable-zts \ + --enable-maintainer-zts \ + --enable-pthreads \ + --enable-pcntl \ --with-layout=GNU \ --disable-cgi \ --disable-all \ @@ -485,7 +499,8 @@ RUN source /root/emsdk/emsdk_env.sh && \ # Silence the errors "munmap() failed: [28] Invalid argument" # @TODO: Identify the root cause behind these errors and fix them properly -RUN echo '#define ZEND_MM_ERROR 0' >> /root/php-src/main/php_config.h; +RUN echo '#define ZEND_MM_ERROR 1' >> /root/php-src/main/php_config.h; +RUN echo '#define ZEND_DEBUG 1' >> /root/php-src/main/php_config.h; # With HAVE_UNISTD_H=1 PHP complains about the missing getdtablesize() function RUN /root/replace.sh 's/define HAVE_UNISTD_H 1/define HAVE_UNISTD_H 0/g' /root/php-src/main/php_config.h @@ -511,7 +526,7 @@ RUN echo 'extern int wasm_close(int fd);' >> /root/php-src/main/php_config.h; RUN source /root/emsdk/emsdk_env.sh && \ # We're compiling PHP as emscripten's side module... - EMCC_FLAGS=" -sSIDE_MODULE -Dsetsockopt=wasm_setsockopt -Dpopen=wasm_popen -Dpclose=wasm_pclose " \ + EMCC_FLAGS=" -sSIDE_MODULE -sUSE_PTHREADS=1 -Dsetsockopt=wasm_setsockopt -Dpopen=wasm_popen -Dpclose=wasm_pclose " \ # ...which means we must skip all the libraries - they will be provided in the final linking step. EMCC_SKIP="-lz -ledit -ldl -lncurses -lzip -lpng16 -lssl -lcrypto -lxml2 -lc -lm -lsqlite3 /root/lib/lib/libxml2.a /root/lib/lib/libsqlite3.so /root/lib/lib/libsqlite3.a /root/lib/lib/libpng16.so" \ emmake make -j8 @@ -910,6 +925,7 @@ RUN mkdir /root/output COPY ./build-assets/phpwasm-emscripten-library.js /root/phpwasm-emscripten-library.js RUN source /root/emsdk/emsdk_env.sh && \ export EXPORTED_FUNCTIONS=$'["_php_wasm_init", \n\ +"_run_php", \n\ "_phpwasm_destroy_uploaded_files_hash", \n\ "_phpwasm_init_uploaded_files_hash", \n\ "_phpwasm_register_uploaded_file", \n\ @@ -930,8 +946,9 @@ RUN source /root/emsdk/emsdk_env.sh && \ "_wasm_set_request_port", \n\ "_wasm_set_request_uri", \n\ "_wasm_set_skip_shebang" '"$(cat /root/.EXPORTED_FUNCTIONS)"']'; \ - emcc -O3 \ + emcc -O0 -g2 \ --js-library /root/phpwasm-emscripten-library.js \ + -pthread \ -I . \ -I ext \ -I ext/json \ @@ -946,7 +963,8 @@ RUN source /root/emsdk/emsdk_env.sh && \ -s EXTRA_EXPORTED_RUNTIME_METHODS='["ccall", "UTF8ToString", "lengthBytesUTF8", "FS", "PROXYFS"]' \ -s INITIAL_MEMORY=1024MB \ -s ALLOW_MEMORY_GROWTH=1 \ - -s ASSERTIONS=0 \ + -s USE_PTHREADS=1 \ + -s ASSERTIONS=3 \ -s ERROR_ON_UNDEFINED_SYMBOLS=0 \ -s NODEJS_CATCH_EXIT=0 \ -s INVOKE_RUN=0 \ @@ -1038,13 +1056,13 @@ RUN \ # Turn the php.js file into an ES module # Manually turn the output into a esm module instead of relying on -s MODULARIZE=1. # which pollutes the global namespace and does not play well with import() mechanics. - echo "export const dependenciesTotalSize = $FILE_SIZE; " >> /root/output/php-module.js && \ + echo "const dependenciesTotalSize = $FILE_SIZE; " >> /root/output/php-module.js && \ if [ "$EMSCRIPTEN_ENVIRONMENT" = "node" ]; then \ - echo "const dependencyFilename = __dirname + '/$WASM_FILENAME'; " >> /root/output/php-module.js; \ + echo "const dependencyFilename = './$WASM_FILENAME'; " >> /root/output/php-module.js; \ else \ echo "import dependencyFilename from './$WASM_FILENAME'; " >> /root/output/php-module.js; \ fi; \ - echo " export { dependencyFilename }; export function init(RuntimeName, PHPLoader) {" >> /root/output/php-module.js && \ + echo " module.exports = function init(RuntimeName, PHPLoader) {" >> /root/output/php-module.js && \ cat /root/output/php.js >> /root/output/php-module.js && \ cat /root/append-before-return.js >> /root/output/php-module.js && \ echo " return PHPLoader; }" >> /root/output/php-module.js && \ diff --git a/packages/php-wasm/compile/build-assets/append-before-return.js b/packages/php-wasm/compile/build-assets/append-before-return.js index a16f715183..37758f6bcd 100644 --- a/packages/php-wasm/compile/build-assets/append-before-return.js +++ b/packages/php-wasm/compile/build-assets/append-before-return.js @@ -10,12 +10,3 @@ DNS.address_map.addrs.localhost = '127.0.0.1'; * so that it can be inspected later. */ PHPLoader.debug = 'debug' in PHPLoader ? PHPLoader.debug : true; -if (PHPLoader.debug) { - const originalHandleSleep = Asyncify.handleSleep; - Asyncify.handleSleep = function (startAsync) { - if (!ABORT) { - Module["lastAsyncifyStackSource"] = new Error(); - } - return originalHandleSleep(startAsync); - } -} diff --git a/packages/php-wasm/compile/build-assets/php_wasm.c b/packages/php-wasm/compile/build-assets/php_wasm.c index cf7d291444..c546d87431 100644 --- a/packages/php-wasm/compile/build-assets/php_wasm.c +++ b/packages/php-wasm/compile/build-assets/php_wasm.c @@ -174,22 +174,6 @@ static const zend_function_entry additional_functions[] = { }; #endif -#if !defined(TSRMLS_DC) -#define TSRMLS_DC -#endif -#if !defined(TSRMLS_D) -#define TSRMLS_D -#endif -#if !defined(TSRMLS_CC) -#define TSRMLS_CC -#endif -#if !defined(TSRMLS_C) -#define TSRMLS_C -#endif -#if !defined(TSRMLS_FETCH) -#define TSRMLS_FETCH() -#endif - // Lowest precedence ini rules. May be overwritten by a /usr/local/etc/php.ini file: const char WASM_HARDCODED_INI[] = "error_reporting = E_ALL\n" @@ -197,16 +181,6 @@ const char WASM_HARDCODED_INI[] = "html_errors = 1\n" "display_startup_errors = On\n" "log_errors = 1\n" - "always_populate_raw_post_data = -1\n" - "upload_max_filesize = 2000M\n" - "post_max_size = 2000M\n" - "disable_functions = proc_open,popen,curl_exec,curl_multi_exec\n" - "allow_url_fopen = Off\n" - "allow_url_include = Off\n" - "session.save_path = /home/web_user\n" - "implicit_flush = 1\n" - "output_buffering = 0\n" - "max_execution_time = 0\n" "max_input_time = -1\n\0" ; @@ -254,31 +228,53 @@ static wasm_server_context_t *wasm_server_context; int wasm_sapi_module_startup(sapi_module_struct *sapi_module); int wasm_sapi_shutdown_wrapper(sapi_module_struct *sapi_globals); void wasm_sapi_module_shutdown(); -static int wasm_sapi_deactivate(TSRMLS_D); +static int wasm_sapi_deactivate(); #if PHP_MAJOR_VERSION == 5 -static int wasm_sapi_ub_write(const char *str, uint str_length TSRMLS_DC); +static int wasm_sapi_ub_write(const char *str, uint str_length); static int wasm_sapi_read_post_body(char *buffer, uint count_bytes); #else -static size_t wasm_sapi_ub_write(const char *str, size_t str_length TSRMLS_DC); +static size_t wasm_sapi_ub_write(const char *str, size_t str_length); static size_t wasm_sapi_read_post_body(char *buffer, size_t count_bytes); #endif #if PHP_MAJOR_VERSION >= 8 -static void wasm_sapi_log_message(const char *message TSRMLS_DC, int syslog_type_int); +static void wasm_sapi_log_message(const char *message, int syslog_type_int); #else #if (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION >= 1) -static void wasm_sapi_log_message(char *message TSRMLS_DC, int syslog_type_int); +static void wasm_sapi_log_message(char *message, int syslog_type_int); #else -static void wasm_sapi_log_message(char *message TSRMLS_DC); +static void wasm_sapi_log_message(char *message); #endif #endif static void wasm_sapi_flush(void *server_context); -static int wasm_sapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC); -static void wasm_sapi_send_header(sapi_header_struct *sapi_header, void *server_context TSRMLS_DC); -static char *wasm_sapi_read_cookies(TSRMLS_D); -static void wasm_sapi_register_server_variables(zval *track_vars_array TSRMLS_DC); +static int wasm_sapi_send_headers(sapi_headers_struct *sapi_headers); +static void wasm_sapi_send_header(sapi_header_struct *sapi_header, void *server_context); +static char *wasm_sapi_read_cookies(); +static void wasm_sapi_register_server_variables(zval *track_vars_array); void wasm_init_server_context(); static char *int_to_string(int i); -static int EMSCRIPTEN_KEEPALIVE run_php(char *code); +int run_php(char *code) +{ + int retVal = 255; // Unknown error. + + zend_try + { + retVal = zend_eval_string(code, NULL, "php-wasm run script"); + + if (EG(exception)) + { + zend_exception_error(EG(exception), E_ERROR); + retVal = 2; + } + } + zend_catch + { + retVal = 1; // Code died. + } + + zend_end_try(); + + return retVal; +} SAPI_API sapi_module_struct php_wasm_sapi_module = { "wasm", /* name */ @@ -636,7 +632,7 @@ int stderr_replacement; * Called by PHP to retrieve the cookies associated with the currently * processed request. */ -static char *wasm_sapi_read_cookies(TSRMLS_D) +static char *wasm_sapi_read_cookies() { return wasm_server_context->cookies; } @@ -792,46 +788,46 @@ int wasm_sapi_module_startup(sapi_module_struct *sapi_module) { * * track_vars_array: the array where the $_SERVER keys and values are stored. */ -static void wasm_sapi_register_server_variables(zval *track_vars_array TSRMLS_DC) +static void wasm_sapi_register_server_variables(zval *track_vars_array) { - php_import_environment_variables(track_vars_array TSRMLS_CC); + php_import_environment_variables(track_vars_array); char *value; /* PHP_SELF and REQUEST_URI */ value = SG(request_info).request_uri; if (value != NULL) { - php_register_variable("SCRIPT_NAME", value, track_vars_array TSRMLS_CC); - php_register_variable("SCRIPT_FILENAME", value, track_vars_array TSRMLS_CC); - php_register_variable("PHP_SELF", value, track_vars_array TSRMLS_CC); - php_register_variable("REQUEST_URI", value, track_vars_array TSRMLS_CC); + php_register_variable("SCRIPT_NAME", value, track_vars_array); + php_register_variable("SCRIPT_FILENAME", value, track_vars_array); + php_register_variable("PHP_SELF", value, track_vars_array); + php_register_variable("REQUEST_URI", value, track_vars_array); } /* argv */ value = SG(request_info).query_string; if (value != NULL) - php_register_variable("argv", value, track_vars_array TSRMLS_CC); + php_register_variable("argv", value, track_vars_array); /* SERVER_SOFTWARE */ - php_register_variable("SERVER_SOFTWARE", "PHP.wasm", track_vars_array TSRMLS_CC); + php_register_variable("SERVER_SOFTWARE", "PHP.wasm", track_vars_array); /* SERVER_PROTOCOL */ if(SG(request_info).proto_num != -1) { char *port_str = int_to_string(wasm_server_context->request_port); - php_register_variable("SERVER_PORT", port_str, track_vars_array TSRMLS_CC); + php_register_variable("SERVER_PORT", port_str, track_vars_array); free(port_str); } /* SERVER_NAME */ value = wasm_server_context->request_host; if (value != NULL) { - php_register_variable("SERVER_NAME", value, track_vars_array TSRMLS_CC); - php_register_variable("HTTP_HOST", value, track_vars_array TSRMLS_CC); + php_register_variable("SERVER_NAME", value, track_vars_array); + php_register_variable("HTTP_HOST", value, track_vars_array); } /* REQUEST_METHOD */ value = (char*)SG(request_info).request_method; if (value != NULL) { - php_register_variable("REQUEST_METHOD", value, track_vars_array TSRMLS_CC); + php_register_variable("REQUEST_METHOD", value, track_vars_array); if (!strcmp(value, "HEAD")) { SG(request_info).headers_only = 1; } else { @@ -842,12 +838,12 @@ static void wasm_sapi_register_server_variables(zval *track_vars_array TSRMLS_DC /* QUERY_STRING */ value = SG(request_info).query_string; if (value != NULL) - php_register_variable("QUERY_STRING", value, track_vars_array TSRMLS_CC); + php_register_variable("QUERY_STRING", value, track_vars_array); // Register entries from wasm_server_context->server_array_entries linked list wasm_array_entry_t *entry = wasm_server_context->server_array_entries; while (entry != NULL) { - php_register_variable(entry->key, entry->value, track_vars_array TSRMLS_CC); + php_register_variable(entry->key, entry->value, track_vars_array); entry = entry->next; } } @@ -861,6 +857,13 @@ static void wasm_sapi_register_server_variables(zval *track_vars_array TSRMLS_DC */ int wasm_sapi_request_init() { + // Minimize the surface area of the code that can be called + if (php_request_startup()==FAILURE) { + wasm_sapi_module_shutdown(); + return FAILURE; + } + return SUCCESS; + putenv("USE_ZEND_ALLOC=0"); // Write to files instead of stdout and stderr because Emscripten truncates null @@ -890,7 +893,7 @@ int wasm_sapi_request_init() SG(request_info).proto_num = 1000; // For HTTP 1.0 SG(sapi_headers).http_response_code = 200; - if (php_request_startup(TSRMLS_C)==FAILURE) { + if (php_request_startup()==FAILURE) { wasm_sapi_module_shutdown(); return FAILURE; } @@ -903,7 +906,7 @@ int wasm_sapi_request_init() } #endif - php_register_variable("PHP_SELF", "-", NULL TSRMLS_CC); + php_register_variable("PHP_SELF", "-", NULL); // Set $_FILES in case any were passed via the wasm_server_context->uploaded_files // linked list @@ -975,7 +978,6 @@ int wasm_sapi_request_init() * required to run the PHP code. */ void wasm_sapi_request_shutdown() { - TSRMLS_FETCH(); if(SG(rfc1867_uploaded_files) != NULL) { phpwasm_destroy_uploaded_files_hash(); } @@ -1006,13 +1008,13 @@ void wasm_sapi_request_shutdown() { */ int EMSCRIPTEN_KEEPALIVE wasm_sapi_handle_request() { int result; + if (wasm_sapi_request_init() == FAILURE) { result = -1; goto wasm_request_done; } - TSRMLS_FETCH(); if (wasm_server_context->execution_mode == MODE_EXECUTE_SCRIPT) { zend_file_handle file_handle; @@ -1037,7 +1039,7 @@ int EMSCRIPTEN_KEEPALIVE wasm_sapi_handle_request() { // https://github.com/php/php-src/commit/c5f1b384b591009310370f0b06b10868d2d62741 // https://www.mail-archive.com/internals@lists.php.net/msg43642.html // http://git.php.net/?p=php-src.git;a=commit;h=896dad4c794f7826812bcfdbaaa9f0b3518d9385 - if (php_fopen_primary_script(&file_handle TSRMLS_CC) == FAILURE) { + if (php_fopen_primary_script(&file_handle) == FAILURE) { zend_try { if (errno == EACCES) { SG(sapi_headers).http_response_code = 403; @@ -1051,7 +1053,7 @@ int EMSCRIPTEN_KEEPALIVE wasm_sapi_handle_request() { goto wasm_request_done; } - result = php_execute_script(&file_handle TSRMLS_CC); + result = php_execute_script(&file_handle); } else { @@ -1063,7 +1065,7 @@ int EMSCRIPTEN_KEEPALIVE wasm_sapi_handle_request() { } void wasm_sapi_module_shutdown() { - php_module_shutdown(TSRMLS_C); + php_module_shutdown(); sapi_shutdown(); #ifdef ZTS tsrm_shutdown(); @@ -1082,12 +1084,11 @@ void wasm_sapi_module_shutdown() { */ int wasm_sapi_shutdown_wrapper(sapi_module_struct *sapi_globals) { - TSRMLS_FETCH(); wasm_sapi_module_shutdown(); return SUCCESS; } -static int wasm_sapi_deactivate(TSRMLS_D) +static int wasm_sapi_deactivate() { fflush(stdout); return SUCCESS; @@ -1118,9 +1119,9 @@ static inline size_t wasm_sapi_single_write(const char *str, uint str_length) * str_length: the length of the string. */ #if PHP_MAJOR_VERSION == 5 -static int wasm_sapi_ub_write(const char *str, uint str_length TSRMLS_DC) +static int wasm_sapi_ub_write(const char *str, uint str_length) #else -static size_t wasm_sapi_ub_write(const char *str, size_t str_length TSRMLS_DC) +static size_t wasm_sapi_ub_write(const char *str, size_t str_length) #endif { const char *ptr = str; @@ -1144,7 +1145,7 @@ static void wasm_sapi_flush(void *server_context) if (fflush(stdout)==EOF) { php_handle_aborted_connection(); } - sapi_send_headers(TSRMLS_C); + sapi_send_headers(); } static int _fwrite(FILE *file, char *str) @@ -1169,7 +1170,7 @@ FILE *headers_file; * * Called by PHP in the request shutdown handler. */ -static int wasm_sapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) +static int wasm_sapi_send_headers(sapi_headers_struct *sapi_headers) { headers_file = fopen("/tmp/headers.json", "w"); if (headers_file == NULL) @@ -1183,15 +1184,15 @@ static int wasm_sapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) free(response_code); _fwrite(headers_file, ", \"headers\": ["); - zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t) sapi_module.send_header, SG(server_context) TSRMLS_CC); + zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t) sapi_module.send_header, SG(server_context)); if(SG(sapi_headers).send_default_content_type) { sapi_header_struct default_header; - sapi_get_default_content_type_header(&default_header TSRMLS_CC); - sapi_module.send_header(&default_header, SG(server_context) TSRMLS_CC); + sapi_get_default_content_type_header(&default_header); + sapi_module.send_header(&default_header, SG(server_context)); sapi_free_header(&default_header); } - sapi_module.send_header(NULL, SG(server_context) TSRMLS_CC); + sapi_module.send_header(NULL, SG(server_context)); _fwrite(headers_file, "]}"); fclose(headers_file); @@ -1205,7 +1206,7 @@ static int wasm_sapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) * ---------------------------- * Appends a single header line to the headers JSON file. */ -static void wasm_sapi_send_header(sapi_header_struct *sapi_header, void *server_context TSRMLS_DC) { +static void wasm_sapi_send_header(sapi_header_struct *sapi_header, void *server_context) { if (sapi_header == NULL) { fseek(headers_file, ftell(headers_file) - 2, SEEK_SET); @@ -1225,12 +1226,12 @@ static void wasm_sapi_send_header(sapi_header_struct *sapi_header, void *server_ #if PHP_MAJOR_VERSION >= 8 -static void wasm_sapi_log_message(const char *message TSRMLS_DC, int syslog_type_int) +static void wasm_sapi_log_message(const char *message, int syslog_type_int) #else #if (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION >= 1) -static void wasm_sapi_log_message(char *message TSRMLS_DC, int syslog_type_int) +static void wasm_sapi_log_message(char *message, int syslog_type_int) #else -static void wasm_sapi_log_message(char *message TSRMLS_DC) +static void wasm_sapi_log_message(char *message) #endif #endif { @@ -1245,15 +1246,12 @@ static void wasm_sapi_log_message(char *message TSRMLS_DC) * other function. */ int php_wasm_init() { +#ifdef ZTS + php_tsrm_startup(); +#endif wasm_server_context = malloc(sizeof(wasm_server_context_t)); wasm_init_server_context(); -#ifdef ZTS - void ***tsrm_ls = NULL; - tsrm_startup(1, 1, 0, NULL); - tsrm_ls = ts_resource(0); - *ptsrm_ls = tsrm_ls; -#endif sapi_startup(&php_wasm_sapi_module); if(phpini_path_override != NULL) { free(php_wasm_sapi_module.php_ini_path_override); @@ -1291,30 +1289,6 @@ int php_wasm_init() { * * returns: The exit code. 0 means success, 1 means the code died, 2 means an error. */ -static int EMSCRIPTEN_KEEPALIVE run_php(char *code) -{ - int retVal = 255; // Unknown error. - - zend_try - { - retVal = zend_eval_string(code, NULL, "php-wasm run script"); - - if (EG(exception)) - { - zend_exception_error(EG(exception), E_ERROR); - retVal = 2; - } - } - zend_catch - { - retVal = 1; // Code died. - } - - zend_end_try(); - - return retVal; -} - #ifdef WITH_VRZNO #include "../php-src/ext/vrzno/php_vrzno.h" diff --git a/packages/php-wasm/compile/build.js b/packages/php-wasm/compile/build.js index b449980969..cccbdad620 100644 --- a/packages/php-wasm/compile/build.js +++ b/packages/php-wasm/compile/build.js @@ -94,19 +94,19 @@ const args = argParser.argv; const platformDefaults = { all: { PHP_VERSION: '8.0.24', - WITH_LIBZIP: 'yes', - WITH_SQLITE: 'yes', + WITH_LIBZIP: 'no', + WITH_SQLITE: 'no', }, web: {}, node: { - WITH_LIBXML: 'yes', - WITH_LIBPNG: 'yes', - WITH_MBSTRING: 'yes', - WITH_CLI_SAPI: 'yes', - WITH_OPENSSL: 'yes', - WITH_NODEFS: 'yes', - WITH_MYSQL: 'yes', - WITH_WS_NETWORKING_PROXY: 'yes', + WITH_LIBXML: 'no', + WITH_LIBPNG: 'no', + WITH_MBSTRING: 'no', + WITH_CLI_SAPI: 'no', + WITH_OPENSSL: 'no', + WITH_NODEFS: 'no', + WITH_MYSQL: 'no', + WITH_WS_NETWORKING_PROXY: 'no', }, }; const platform = args.PLATFORM === 'node' ? 'node' : 'web'; diff --git a/packages/php-wasm/node/public/php.worker.js b/packages/php-wasm/node/public/php.worker.js new file mode 100755 index 0000000000..f34d510d3f --- /dev/null +++ b/packages/php-wasm/node/public/php.worker.js @@ -0,0 +1,200 @@ +/** + * @license + * Copyright 2015 The Emscripten Authors + * SPDX-License-Identifier: MIT + */ + +// Pthread Web Worker startup routine: +// This is the entry point file that is loaded first by each Web Worker +// that executes pthreads on the Emscripten application. + +'use strict'; + +var Module = {}; + +// Node.js support +var ENVIRONMENT_IS_NODE = typeof process == 'object' && typeof process.versions == 'object' && typeof process.versions.node == 'string'; +if (ENVIRONMENT_IS_NODE) { + // Create as web-worker-like an environment as we can. + + var nodeWorkerThreads = require('worker_threads'); + + var parentPort = nodeWorkerThreads.parentPort; + + parentPort.on('message', (data) => onmessage({ data: data })); + + var fs = require('fs'); + + Object.assign(global, { + self: global, + require: require, + Module: Module, + location: { + href: __filename + }, + Worker: nodeWorkerThreads.Worker, + importScripts: function(f) { + (0, eval)(fs.readFileSync(f, 'utf8') + '//# sourceURL=' + f); + }, + postMessage: function(msg) { + parentPort.postMessage(msg); + }, + performance: global.performance || { + now: function() { + return Date.now(); + } + }, + }); +} + +// Thread-local guard variable for one-time init of the JS state +var initializedJS = false; + +function assert(condition, text) { + if (!condition) abort('Assertion failed: ' + text); +} + +function threadPrintErr() { + var text = Array.prototype.slice.call(arguments).join(' '); + // See https://github.com/emscripten-core/emscripten/issues/14804 + if (ENVIRONMENT_IS_NODE) { + fs.writeSync(2, text + '\n'); + return; + } + console.error(text); +} +function threadAlert() { + var text = Array.prototype.slice.call(arguments).join(' '); + postMessage({cmd: 'alert', text: text, threadId: Module['_pthread_self']()}); +} +// We don't need out() for now, but may need to add it if we want to use it +// here. Or, if this code all moves into the main JS, that problem will go +// away. (For now, adding it here increases code size for no benefit.) +var out = () => { throw 'out() is not defined in worker.js.'; } +var err = threadPrintErr; +self.alert = threadAlert; + +Module['instantiateWasm'] = (info, receiveInstance) => { + // Instantiate from the module posted from the main thread. + // We can just use sync instantiation in the worker. + var module = Module['wasmModule']; + // We don't need the module anymore; new threads will be spawned from the main thread. + Module['wasmModule'] = null; + var instance = new WebAssembly.Instance(module, info); + // 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, we can remove this if/else. + return receiveInstance(instance); +} + +// Turn unhandled rejected promises into errors so that the main thread will be +// notified about them. +self.onunhandledrejection = (e) => { + throw e.reason ?? e; +}; + +function handleMessage(e) { + try { + if (e.data.cmd === 'load') { // Preload command that is called once per worker to parse and load the Emscripten code. + + // Until we initialize the runtime, queue up any further incoming messages. + let messageQueue = []; + self.onmessage = (e) => messageQueue.push(e); + + // And add a callback for when the runtime is initialized. + self.startWorker = (instance) => { + // Notify the main thread that this thread has loaded. + postMessage({ 'cmd': 'loaded' }); + // Process any messages that were queued before the thread was ready. + for (let msg of messageQueue) { + handleMessage(msg); + } + // Restore the real message handler. + self.onmessage = handleMessage; + }; + + // Module and memory were sent from main thread + Module['wasmModule'] = e.data.wasmModule; + + // Use `const` here to ensure that the variable is scoped only to + // that iteration, allowing safe reference from a closure. + for (const handler of e.data.handlers) { + Module[handler] = function() { + postMessage({ cmd: 'callHandler', handler, args: [...arguments] }); + } + } + + Module['wasmMemory'] = e.data.wasmMemory; + + Module['buffer'] = Module['wasmMemory'].buffer; + + Module['workerID'] = e.data.workerID; + + Module['ENVIRONMENT_IS_PTHREAD'] = true; + + if (typeof e.data.urlOrBlob == 'string') { + importScripts(e.data.urlOrBlob); + } else { + var objectUrl = URL.createObjectURL(e.data.urlOrBlob); + importScripts(objectUrl); + URL.revokeObjectURL(objectUrl); + } + } else if (e.data.cmd === 'run') { + // Pass the thread address to wasm to store it for fast access. + Module['__emscripten_thread_init'](e.data.pthread_ptr, /*isMainBrowserThread=*/0, /*isMainRuntimeThread=*/0, /*canBlock=*/1); + + // Await mailbox notifications with `Atomics.waitAsync` so we can start + // using the fast `Atomics.notify` notification path. + Module['__emscripten_thread_mailbox_await'](e.data.pthread_ptr); + + assert(e.data.pthread_ptr); + // Also call inside JS module to set up the stack frame for this pthread in JS module scope + Module['establishStackSpace'](); + Module['PThread'].receiveObjectTransfer(e.data); + Module['PThread'].threadInitTLS(); + + if (!initializedJS) { + initializedJS = true; + } + + try { + Module['invokeEntryPoint'](e.data.start_routine, e.data.arg); + } catch(ex) { + if (ex != 'unwind') { + // The pthread "crashed". Do not call `_emscripten_thread_exit` (which + // would make this thread joinable). Instead, re-throw the exception + // and let the top level handler propagate it back to the main thread. + throw ex; + } + err('Pthread 0x' + Module['_pthread_self']().toString(16) + ' completed its main entry point with an `unwind`, keeping the worker alive for asynchronous operation.'); + } + } else if (e.data.cmd === 'cancel') { // Main thread is asking for a pthread_cancel() on this thread. + if (Module['_pthread_self']()) { + Module['__emscripten_thread_exit'](-1); + } + } else if (e.data.target === 'setimmediate') { + // no-op + } else if (e.data.cmd === 'checkMailbox') { + if (initializedJS) { + Module['checkMailbox'](); + } + } else if (e.data.cmd) { + // The received message looks like something that should be handled by this message + // handler, (since there is a e.data.cmd field present), but is not one of the + // recognized commands: + err('worker.js received unknown command ' + e.data.cmd); + err(e.data); + } + } catch(ex) { + err('worker.js onmessage() captured an uncaught exception: ' + ex); + if (ex && ex.stack) err(ex.stack); + if (Module['__emscripten_thread_crashed']) { + Module['__emscripten_thread_crashed'](); + } + throw ex; + } +}; + +self.onmessage = handleMessage; + + diff --git a/packages/php-wasm/node/public/php_7_4.js b/packages/php-wasm/node/public/php_7_4.js index e6c7e8b796..54f77a879d 100644 --- a/packages/php-wasm/node/public/php_7_4.js +++ b/packages/php-wasm/node/public/php_7_4.js @@ -1,6 +1,66 @@ -export const dependenciesTotalSize = 11015874; -const dependencyFilename = __dirname + '/php_7_4.wasm'; - export { dependencyFilename }; export function init(RuntimeName, PHPLoader) { +const dependenciesTotalSize = 4784045; +const dependencyFilename = './php_7_4.wasm'; + module.exports = function init(RuntimeName, PHPLoader) { + ExitStatus = class PHPExitStatus extends Error { + constructor(status) { + super(status); + this.name = "ExitStatus"; + this.message = "Program terminated with exit(" + status + ")"; + this.status = status; + } + } + +// Support for growable heap + pthreads, where the buffer may change, so JS views +// must be updated. +function GROWABLE_HEAP_I8() { + if (wasmMemory.buffer != HEAP8.buffer) { + updateMemoryViews(); + } + return HEAP8; +} +function GROWABLE_HEAP_U8() { + if (wasmMemory.buffer != HEAP8.buffer) { + updateMemoryViews(); + } + return HEAPU8; +} +function GROWABLE_HEAP_I16() { + if (wasmMemory.buffer != HEAP8.buffer) { + updateMemoryViews(); + } + return HEAP16; +} +function GROWABLE_HEAP_U16() { + if (wasmMemory.buffer != HEAP8.buffer) { + updateMemoryViews(); + } + return HEAPU16; +} +function GROWABLE_HEAP_I32() { + if (wasmMemory.buffer != HEAP8.buffer) { + updateMemoryViews(); + } + return HEAP32; +} +function GROWABLE_HEAP_U32() { + if (wasmMemory.buffer != HEAP8.buffer) { + updateMemoryViews(); + } + return HEAPU32; +} +function GROWABLE_HEAP_F32() { + if (wasmMemory.buffer != HEAP8.buffer) { + updateMemoryViews(); + } + return HEAPF32; +} +function GROWABLE_HEAP_F64() { + if (wasmMemory.buffer != HEAP8.buffer) { + updateMemoryViews(); + } + return HEAPF64; +} + var Module = typeof PHPLoader != "undefined" ? PHPLoader : {}; var moduleOverrides = Object.assign({}, Module); @@ -15,10 +75,26 @@ var quit_ = (status, toThrow) => { var ENVIRONMENT_IS_WEB=RuntimeName==="WEB"; -var ENVIRONMENT_IS_WORKER=RuntimeName==="WORKER"; +var ENVIRONMENT_IS_WORKER = typeof importScripts == "function"; var ENVIRONMENT_IS_NODE=RuntimeName==="NODE"; +var ENVIRONMENT_IS_SHELL=RuntimeName==="SHELL"; + +if (Module["ENVIRONMENT"]) { + throw new Error("Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -sENVIRONMENT=web or -sENVIRONMENT=node)"); +} + +var ENVIRONMENT_IS_PTHREAD = Module["ENVIRONMENT_IS_PTHREAD"] || false; + +var _scriptDir = typeof document != "undefined" && document.currentScript ? document.currentScript.src : undefined; + +if (ENVIRONMENT_IS_WORKER) { + _scriptDir = self.location.href; +} else if (ENVIRONMENT_IS_NODE) { + _scriptDir = __filename; +} + var scriptDirectory = ""; function locateFile(path) { @@ -28,31 +104,26 @@ function locateFile(path) { return scriptDirectory + path; } -var read_, readAsync, readBinary; - -function logExceptionOnExit(e) { - if (e instanceof ExitStatus) return; - let toLog = e; - err("exiting due to exception: " + toLog); -} +var read_, readAsync, readBinary, setWindowTitle; if (ENVIRONMENT_IS_NODE) { + if (typeof process == "undefined" || !process.release || process.release.name !== "node") throw new Error("not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)"); + var nodeVersion = process.versions.node; + var numericVersion = nodeVersion.split(".").slice(0, 3); + numericVersion = numericVersion[0] * 1e4 + numericVersion[1] * 100 + numericVersion[2] * 1; + var minVersion = 101900; + if (numericVersion < 101900) { + throw new Error("This emscripten-generated code requires node v10.19.19.0 (detected v" + nodeVersion + ")"); + } + var fs = require("fs"); + var nodePath = require("path"); if (ENVIRONMENT_IS_WORKER) { - scriptDirectory = require("path").dirname(scriptDirectory) + "/"; + scriptDirectory = nodePath.dirname(scriptDirectory) + "/"; } else { scriptDirectory = __dirname + "/"; } - var fs; - var nodePath; - var requireNodeFS = () => { - if (!nodePath) { - fs = require("fs"); - nodePath = require("path"); - } - }; read_ = (filename, binary) => { - requireNodeFS(); - filename = nodePath["normalize"](filename); + filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename); return fs.readFileSync(filename, binary ? undefined : "utf8"); }; readBinary = filename => { @@ -60,71 +131,238 @@ if (ENVIRONMENT_IS_NODE) { if (!ret.buffer) { ret = new Uint8Array(ret); } + assert(ret.buffer); return ret; }; readAsync = (filename, onload, onerror) => { - requireNodeFS(); - filename = nodePath["normalize"](filename); + filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename); fs.readFile(filename, function(err, data) { if (err) onerror(err); else onload(data.buffer); }); }; - if (process["argv"].length > 1) { - thisProgram = process["argv"][1].replace(/\\/g, "/"); + if (process.argv.length > 1) { + thisProgram = process.argv[1].replace(/\\/g, "/"); } - arguments_ = process["argv"].slice(2); + arguments_ = process.argv.slice(2); if (typeof module != "undefined") { module["exports"] = Module; } - process["on"]("unhandledRejection", function(reason) { - throw reason; - }); + var nodeMajor = process.versions.node.split(".")[0]; + if (nodeMajor < 15) { + process.on("unhandledRejection", function(reason) { + throw reason; + }); + } quit_ = (status, toThrow) => { - if (keepRuntimeAlive()) { - process["exitCode"] = status; - throw toThrow; - } - logExceptionOnExit(toThrow); - process["exit"](status); + process.exitCode = status; + throw toThrow; }; Module["inspect"] = function() { return "[Emscripten Module object]"; }; -} else {} + let nodeWorkerThreads; + try { + nodeWorkerThreads = require("worker_threads"); + } catch (e) { + console.error('The "worker_threads" module is not supported in this node.js build - perhaps a newer version is needed?'); + throw e; + } + global.Worker = nodeWorkerThreads.Worker; +} else if (ENVIRONMENT_IS_SHELL) { + if (typeof process == "object" && typeof require === "function" || typeof window == "object" || typeof importScripts == "function") throw new Error("not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)"); + if (typeof read != "undefined") { + read_ = function shell_read(f) { + return read(f); + }; + } + readBinary = function readBinary(f) { + let data; + if (typeof readbuffer == "function") { + return new Uint8Array(readbuffer(f)); + } + data = read(f, "binary"); + assert(typeof data == "object"); + return data; + }; + readAsync = function readAsync(f, onload, onerror) { + setTimeout(() => onload(readBinary(f)), 0); + }; + if (typeof clearTimeout == "undefined") { + globalThis.clearTimeout = id => {}; + } + if (typeof scriptArgs != "undefined") { + arguments_ = scriptArgs; + } else if (typeof arguments != "undefined") { + arguments_ = arguments; + } + if (typeof quit == "function") { + quit_ = (status, toThrow) => { + setTimeout(() => { + if (!(toThrow instanceof ExitStatus)) { + let toLog = toThrow; + if (toThrow && typeof toThrow == "object" && toThrow.stack) { + toLog = [ toThrow, toThrow.stack ]; + } + err("exiting due to exception: " + toLog); + } + quit(status); + }); + throw toThrow; + }; + } + if (typeof print != "undefined") { + if (typeof console == "undefined") console = {}; + console.log = print; + console.warn = console.error = typeof printErr != "undefined" ? printErr : print; + } +} else 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 = ""; + } + if (!(typeof window == "object" || typeof importScripts == "function")) throw new Error("not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)"); + if (!ENVIRONMENT_IS_NODE) { + 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 { + throw new Error("environment detection error"); +} + +if (ENVIRONMENT_IS_NODE) { + if (typeof performance == "undefined") { + global.performance = require("perf_hooks").performance; + } +} + +var defaultPrint = console.log.bind(console); + +var defaultPrintErr = console.warn.bind(console); + +if (ENVIRONMENT_IS_NODE) { + defaultPrint = str => fs.writeSync(1, str + "\n"); + defaultPrintErr = str => fs.writeSync(2, str + "\n"); +} -var out = Module["print"] || console.log.bind(console); +var out = Module["print"] || defaultPrint; -var err = Module["printErr"] || console.warn.bind(console); +var err = Module["printErr"] || defaultPrintErr; Object.assign(Module, moduleOverrides); moduleOverrides = null; +checkIncomingModuleAPI(); + if (Module["arguments"]) arguments_ = Module["arguments"]; +legacyModuleProp("arguments", "arguments_"); + if (Module["thisProgram"]) thisProgram = Module["thisProgram"]; +legacyModuleProp("thisProgram", "thisProgram"); + if (Module["quit"]) quit_ = Module["quit"]; +legacyModuleProp("quit", "quit_"); + +assert(typeof Module["memoryInitializerPrefixURL"] == "undefined", "Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead"); + +assert(typeof Module["pthreadMainPrefixURL"] == "undefined", "Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead"); + +assert(typeof Module["cdInitializerPrefixURL"] == "undefined", "Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead"); + +assert(typeof Module["filePackagePrefixURL"] == "undefined", "Module.filePackagePrefixURL option was removed, use Module.locateFile instead"); + +assert(typeof Module["read"] == "undefined", "Module.read option was removed (modify read_ in JS)"); + +assert(typeof Module["readAsync"] == "undefined", "Module.readAsync option was removed (modify readAsync in JS)"); + +assert(typeof Module["readBinary"] == "undefined", "Module.readBinary option was removed (modify readBinary in JS)"); + +assert(typeof Module["setWindowTitle"] == "undefined", "Module.setWindowTitle option was removed (modify setWindowTitle in JS)"); + +assert(typeof Module["TOTAL_MEMORY"] == "undefined", "Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY"); + +legacyModuleProp("read", "read_"); + +legacyModuleProp("readAsync", "readAsync"); + +legacyModuleProp("readBinary", "readBinary"); + +legacyModuleProp("setWindowTitle", "setWindowTitle"); + +var IDBFS = "IDBFS is no longer included by default; build with -lidbfs.js"; + +var PROXYFS = "PROXYFS is no longer included by default; build with -lproxyfs.js"; + +var WORKERFS = "WORKERFS is no longer included by default; build with -lworkerfs.js"; + +assert(ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER || ENVIRONMENT_IS_NODE, "Pthreads do not work in this environment yet (need Web Workers, or an alternative to them)"); + +assert(!ENVIRONMENT_IS_WEB, "web environment detected but not enabled at build time. Add 'web' to `-sENVIRONMENT` to enable."); + +assert(!ENVIRONMENT_IS_SHELL, "shell environment detected but not enabled at build time. Add 'shell' to `-sENVIRONMENT` to enable."); + var wasmBinary; if (Module["wasmBinary"]) wasmBinary = Module["wasmBinary"]; +legacyModuleProp("wasmBinary", "wasmBinary"); + var noExitRuntime = Module["noExitRuntime"] || false; +legacyModuleProp("noExitRuntime", "noExitRuntime"); + if (typeof WebAssembly != "object") { abort("no native wasm support detected"); } var wasmMemory; +var wasmModule; + var ABORT = false; var EXITSTATUS; function assert(condition, text) { if (!condition) { - abort(text); + abort("Assertion failed" + (text ? ": " + text : "")); } } @@ -135,7 +373,7 @@ function UTF8ArrayToString(heapOrArray, 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)); + return UTF8Decoder.decode(heapOrArray.buffer instanceof SharedArrayBuffer ? heapOrArray.slice(idx, endPtr) : heapOrArray.subarray(idx, endPtr)); } var str = ""; while (idx < endPtr) { @@ -153,6 +391,7 @@ function UTF8ArrayToString(heapOrArray, idx, maxBytesToRead) { if ((u0 & 240) == 224) { u0 = (u0 & 15) << 12 | u1 << 6 | u2; } else { + if ((u0 & 248) != 240) warnOnce("Invalid UTF-8 leading byte " + ptrToString(u0) + " encountered when deserializing a UTF-8 string in wasm memory to a JS string!"); u0 = (u0 & 7) << 18 | u1 << 12 | u2 << 6 | heapOrArray[idx++] & 63; } if (u0 < 65536) { @@ -166,7 +405,8 @@ function UTF8ArrayToString(heapOrArray, idx, maxBytesToRead) { } function UTF8ToString(ptr, maxBytesToRead) { - return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : ""; + assert(typeof ptr == "number"); + return ptr ? UTF8ArrayToString(GROWABLE_HEAP_U8(), ptr, maxBytesToRead) : ""; } function stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) { @@ -193,6 +433,7 @@ function stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) { heap[outIdx++] = 128 | u & 63; } else { if (outIdx + 3 >= endIdx) break; + if (u > 1114111) warnOnce("Invalid Unicode code point " + ptrToString(u) + " encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF)."); heap[outIdx++] = 240 | u >> 18; heap[outIdx++] = 128 | u >> 12 & 63; heap[outIdx++] = 128 | u >> 6 & 63; @@ -204,7 +445,8 @@ function stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) { } function stringToUTF8(str, outPtr, maxBytesToWrite) { - return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite); + assert(typeof maxBytesToWrite == "number", "stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!"); + return stringToUTF8Array(str, GROWABLE_HEAP_U8(), outPtr, maxBytesToWrite); } function lengthBytesUTF8(str) { @@ -225,24 +467,93 @@ function lengthBytesUTF8(str) { return len; } -var buffer, HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64; +var HEAP, HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64; -function updateGlobalBufferAndViews(buf) { - buffer = buf; - Module["HEAP8"] = HEAP8 = new Int8Array(buf); - Module["HEAP16"] = HEAP16 = new Int16Array(buf); - Module["HEAP32"] = HEAP32 = new Int32Array(buf); - Module["HEAPU8"] = HEAPU8 = new Uint8Array(buf); - Module["HEAPU16"] = HEAPU16 = new Uint16Array(buf); - Module["HEAPU32"] = HEAPU32 = new Uint32Array(buf); - Module["HEAPF32"] = HEAPF32 = new Float32Array(buf); - Module["HEAPF64"] = HEAPF64 = new Float64Array(buf); +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); } +assert(!Module["STACK_SIZE"], "STACK_SIZE can no longer be set at runtime. Use -sSTACK_SIZE at link time"); + +assert(typeof Int32Array != "undefined" && typeof Float64Array !== "undefined" && Int32Array.prototype.subarray != undefined && Int32Array.prototype.set != undefined, "JS engine does not provide full typed array support"); + var INITIAL_MEMORY = Module["INITIAL_MEMORY"] || 1073741824; +legacyModuleProp("INITIAL_MEMORY", "INITIAL_MEMORY"); + +assert(INITIAL_MEMORY >= 65536, "INITIAL_MEMORY should be larger than STACK_SIZE, was " + INITIAL_MEMORY + "! (STACK_SIZE=" + 65536 + ")"); + +if (ENVIRONMENT_IS_PTHREAD) { + wasmMemory = Module["wasmMemory"]; +} else { + if (Module["wasmMemory"]) { + wasmMemory = Module["wasmMemory"]; + } else { + wasmMemory = new WebAssembly.Memory({ + "initial": INITIAL_MEMORY / 65536, + "maximum": 2147483648 / 65536, + "shared": true + }); + if (!(wasmMemory.buffer instanceof SharedArrayBuffer)) { + err("requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag"); + if (ENVIRONMENT_IS_NODE) { + err("(on node you may need: --experimental-wasm-threads --experimental-wasm-bulk-memory and/or recent version)"); + } + throw Error("bad memory"); + } + } +} + +updateMemoryViews(); + +INITIAL_MEMORY = wasmMemory.buffer.byteLength; + +assert(INITIAL_MEMORY % 65536 === 0); + var wasmTable; +function writeStackCookie() { + var max = _emscripten_stack_get_end(); + assert((max & 3) == 0); + if (max == 0) { + max += 4; + } + GROWABLE_HEAP_U32()[max >> 2] = 34821223; + GROWABLE_HEAP_U32()[max + 4 >> 2] = 2310721022; + GROWABLE_HEAP_U32()[0] = 1668509029; +} + +function checkStackCookie() { + if (ABORT) return; + var max = _emscripten_stack_get_end(); + if (max == 0) { + max += 4; + } + var cookie1 = GROWABLE_HEAP_U32()[max >> 2]; + var cookie2 = GROWABLE_HEAP_U32()[max + 4 >> 2]; + if (cookie1 != 34821223 || cookie2 != 2310721022) { + abort("Stack overflow! Stack cookie has been overwritten at " + ptrToString(max) + ", expected hex dwords 0x89BACDFE and 0x2135467, but received " + ptrToString(cookie2) + " " + ptrToString(cookie1)); + } + if (GROWABLE_HEAP_U32()[0] !== 1668509029) { + abort("Runtime error: The application has corrupted its heap memory area (address zero)!"); + } +} + +(function() { + var h16 = new Int16Array(1); + var h8 = new Int8Array(h16.buffer); + h16[0] = 25459; + if (h8[0] !== 115 || h8[1] !== 99) throw "Runtime error: expected the system to be little-endian! (Run with -sSUPPORT_BIG_ENDIAN to bypass)"; +})(); + var __ATPRERUN__ = []; var __ATINIT__ = []; @@ -262,6 +573,7 @@ function keepRuntimeAlive() { } function preRun() { + assert(!ENVIRONMENT_IS_PTHREAD); if (Module["preRun"]) { if (typeof Module["preRun"] == "function") Module["preRun"] = [ Module["preRun"] ]; while (Module["preRun"].length) { @@ -272,7 +584,11 @@ function preRun() { } function initRuntime() { + assert(!runtimeInitialized); runtimeInitialized = true; + if (ENVIRONMENT_IS_PTHREAD) return; + checkStackCookie(); + ___set_stack_limits(_emscripten_stack_get_base(), _emscripten_stack_get_end()); if (!Module["noFSInit"] && !FS.init.initialized) FS.init(); FS.ignorePermissions = false; TTY.init(); @@ -282,14 +598,21 @@ function initRuntime() { } function exitRuntime() { + assert(!runtimeExited); + checkStackCookie(); + console.trace(); + if (ENVIRONMENT_IS_PTHREAD) return; ___funcs_on_exit(); callRuntimeCallbacks(__ATEXIT__); FS.quit(); TTY.shutdown(); + PThread.terminateAllThreads(); runtimeExited = true; } function postRun() { + checkStackCookie(); + if (ENVIRONMENT_IS_PTHREAD) return; if (Module["postRun"]) { if (typeof Module["postRun"] == "function") Module["postRun"] = [ Module["postRun"] ]; while (Module["postRun"].length) { @@ -307,18 +630,36 @@ function addOnInit(cb) { __ATINIT__.unshift(cb); } +function addOnExit(cb) { + __ATEXIT__.unshift(cb); +} + function addOnPostRun(cb) { __ATPOSTRUN__.unshift(cb); } +assert(Math.imul, "This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill"); + +assert(Math.fround, "This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill"); + +assert(Math.clz32, "This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill"); + +assert(Math.trunc, "This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill"); + var runDependencies = 0; var runDependencyWatcher = null; var dependenciesFulfilled = null; +var runDependencyTracking = {}; + function getUniqueRunDependency(id) { - return id; + var orig = id; + while (1) { + if (!runDependencyTracking[id]) return id; + id = orig + Math.random(); + } } function addRunDependency(id) { @@ -326,6 +667,32 @@ function addRunDependency(id) { if (Module["monitorRunDependencies"]) { Module["monitorRunDependencies"](runDependencies); } + if (id) { + assert(!runDependencyTracking[id]); + runDependencyTracking[id] = 1; + if (runDependencyWatcher === null && typeof setInterval != "undefined") { + runDependencyWatcher = setInterval(function() { + if (ABORT) { + clearInterval(runDependencyWatcher); + runDependencyWatcher = null; + return; + } + var shown = false; + for (var dep in runDependencyTracking) { + if (!shown) { + shown = true; + err("still waiting on run dependencies:"); + } + err("dependency: " + dep); + } + if (shown) { + err("(end of list)"); + } + }, 1e4); + } + } else { + err("warning: run dependency added without ID"); + } } function removeRunDependency(id) { @@ -333,6 +700,12 @@ function removeRunDependency(id) { if (Module["monitorRunDependencies"]) { Module["monitorRunDependencies"](runDependencies); } + if (id) { + assert(runDependencyTracking[id]); + delete runDependencyTracking[id]; + } else { + err("warning: run dependency removed without ID"); + } if (runDependencies == 0) { if (runDependencyWatcher !== null) { clearInterval(runDependencyWatcher); @@ -347,16 +720,13 @@ function removeRunDependency(id) { } function abort(what) { - { - if (Module["onAbort"]) { - Module["onAbort"](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; } @@ -367,6 +737,26 @@ function isDataURI(filename) { return filename.startsWith(dataURIPrefix); } +function isFileURI(filename) { + return filename.startsWith("file://"); +} + +function createExportWrapper(name, fixedasm) { + return function() { + var displayName = name; + var asm = fixedasm; + if (!fixedasm) { + asm = Module["asm"]; + } + assert(runtimeInitialized, "native function `" + displayName + "` called before runtime initialization"); + assert(!runtimeExited, "native function `" + displayName + "` called after runtime exit (use NO_EXIT_RUNTIME to keep it alive after main() exits)"); + if (!asm[name]) { + assert(asm[name], "exported native function `" + displayName + "` not found"); + } + return asm[name].apply(null, arguments); + }; +} + var wasmBinaryFile; wasmBinaryFile = dependencyFilename; @@ -389,81 +779,89 @@ function getBinary(file) { } } -function getBinaryPromise() { +function getBinaryPromise(binaryFile) { if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) { if (typeof fetch == "function") { - return fetch(wasmBinaryFile, { + return fetch(binaryFile, { credentials: "same-origin" }).then(function(response) { if (!response["ok"]) { - throw "failed to load wasm binary file at '" + wasmBinaryFile + "'"; + throw "failed to load wasm binary file at '" + binaryFile + "'"; } return response["arrayBuffer"](); }).catch(function() { - return getBinary(wasmBinaryFile); + return getBinary(binaryFile); }); } } return Promise.resolve().then(function() { - return getBinary(wasmBinaryFile); + return getBinary(binaryFile); + }); +} + +function instantiateArrayBuffer(binaryFile, imports, receiver) { + return getBinaryPromise(binaryFile).then(function(binary) { + return WebAssembly.instantiate(binary, imports); + }).then(function(instance) { + return instance; + }).then(receiver, function(reason) { + err("failed to asynchronously prepare wasm: " + reason); + if (isFileURI(wasmBinaryFile)) { + err("warning: Loading from a file URI (" + wasmBinaryFile + ") is not supported in most browsers. See https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-does-my-program-stall-in-downloading-or-preparing"); + } + abort(reason); }); } +function instantiateAsync(binary, binaryFile, imports, callback) { + if (!binary && typeof WebAssembly.instantiateStreaming == "function" && !isDataURI(binaryFile) && !ENVIRONMENT_IS_NODE && typeof fetch == "function") { + return fetch(binaryFile, { + credentials: "same-origin" + }).then(function(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); + }); + }); + } else { + return instantiateArrayBuffer(binaryFile, imports, callback); + } +} + function createWasm() { var info = { - "a": asmLibraryArg + "env": wasmImports, + "wasi_snapshot_preview1": wasmImports }; function receiveInstance(instance, module) { var exports = instance.exports; - exports = Asyncify.instrumentWasmExports(exports); Module["asm"] = exports; - wasmMemory = Module["asm"]["Wa"]; - updateGlobalBufferAndViews(wasmMemory.buffer); - wasmTable = Module["asm"]["gb"]; - addOnInit(Module["asm"]["Xa"]); - removeRunDependency("wasm-instantiate"); + registerTLSInit(Module["asm"]["_emscripten_tls_init"]); + wasmTable = Module["asm"]["__indirect_function_table"]; + assert(wasmTable, "table not found in wasm exports"); + addOnInit(Module["asm"]["__wasm_call_ctors"]); + wasmModule = module; + PThread.loadWasmModuleToAllWorkers(() => removeRunDependency("wasm-instantiate")); + return exports; } addRunDependency("wasm-instantiate"); + var trueModule = Module; function receiveInstantiationResult(result) { - receiveInstance(result["instance"]); - } - function instantiateArrayBuffer(receiver) { - return getBinaryPromise().then(function(binary) { - return WebAssembly.instantiate(binary, info); - }).then(function(instance) { - return instance; - }).then(receiver, function(reason) { - err("failed to asynchronously prepare wasm: " + reason); - abort(reason); - }); - } - function instantiateAsync() { - if (!wasmBinary && typeof WebAssembly.instantiateStreaming == "function" && !isDataURI(wasmBinaryFile) && !ENVIRONMENT_IS_NODE && typeof fetch == "function") { - return fetch(wasmBinaryFile, { - credentials: "same-origin" - }).then(function(response) { - var result = WebAssembly.instantiateStreaming(response, info); - return result.then(receiveInstantiationResult, function(reason) { - err("wasm streaming compile failed: " + reason); - err("falling back to ArrayBuffer instantiation"); - return instantiateArrayBuffer(receiveInstantiationResult); - }); - }); - } else { - return instantiateArrayBuffer(receiveInstantiationResult); - } + assert(Module === trueModule, "the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?"); + trueModule = null; + receiveInstance(result["instance"], result["module"]); } if (Module["instantiateWasm"]) { try { - var exports = Module["instantiateWasm"](info, receiveInstance); - exports = Asyncify.instrumentWasmExports(exports); - return exports; + return Module["instantiateWasm"](info, receiveInstance); } catch (e) { err("Module.instantiateWasm callback failed with error: " + e); return false; } } - instantiateAsync(); + instantiateAsync(wasmBinary, wasmBinaryFile, info, receiveInstantiationResult); return {}; } @@ -471,37 +869,153 @@ var tempDouble; var tempI64; +function legacyModuleProp(prop, newName) { + if (!Object.getOwnPropertyDescriptor(Module, prop)) { + Object.defineProperty(Module, prop, { + configurable: true, + get: function() { + abort("Module." + prop + " has been replaced with plain " + newName + " (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)"); + } + }); + } +} + +function ignoredModuleProp(prop) { + if (Object.getOwnPropertyDescriptor(Module, prop)) { + abort("`Module." + prop + "` was supplied but `" + prop + "` not included in INCOMING_MODULE_JS_API"); + } +} + +function isExportedByForceFilesystem(name) { + return name === "FS_createPath" || name === "FS_createDataFile" || name === "FS_createPreloadedFile" || name === "FS_unlink" || name === "addRunDependency" || name === "FS_createLazyFile" || name === "FS_createDevice" || name === "removeRunDependency"; +} + +function missingGlobal(sym, msg) { + if (typeof globalThis !== "undefined") { + Object.defineProperty(globalThis, sym, { + configurable: true, + get: function() { + warnOnce("`" + sym + "` is not longer defined by emscripten. " + msg); + return undefined; + } + }); + } +} + +missingGlobal("buffer", "Please use HEAP8.buffer or wasmMemory.buffer"); + +function missingLibrarySymbol(sym) { + if (typeof globalThis !== "undefined" && !Object.getOwnPropertyDescriptor(globalThis, sym)) { + Object.defineProperty(globalThis, sym, { + configurable: true, + get: function() { + var msg = "`" + sym + "` is a library symbol and not included by default; add it to your library.js __deps or to DEFAULT_LIBRARY_FUNCS_TO_INCLUDE on the command line"; + var librarySymbol = sym; + if (!librarySymbol.startsWith("_")) { + librarySymbol = "$" + sym; + } + msg += " (e.g. -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE=" + librarySymbol + ")"; + if (isExportedByForceFilesystem(sym)) { + msg += ". Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you"; + } + warnOnce(msg); + return undefined; + } + }); + } + unexportedRuntimeSymbol(sym); +} + +function unexportedRuntimeSymbol(sym) { + if (!Object.getOwnPropertyDescriptor(Module, sym)) { + Object.defineProperty(Module, sym, { + configurable: true, + get: function() { + var msg = "'" + sym + "' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)"; + if (isExportedByForceFilesystem(sym)) { + msg += ". Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you"; + } + abort(msg); + } + }); + } +} + +function dbg(text) { + if (ENVIRONMENT_IS_NODE) { + fs.writeSync(2, text + "\n"); + } else console.error(text); +} + function ExitStatus(status) { this.name = "ExitStatus"; this.message = "Program terminated with exit(" + status + ")"; this.status = status; } -function callRuntimeCallbacks(callbacks) { - while (callbacks.length > 0) { - callbacks.shift()(Module); - } +function terminateWorker(worker) { + worker.terminate(); + worker.onmessage = e => { + var cmd = e["data"]["cmd"]; + err('received "' + cmd + '" command from terminated worker: ' + worker.workerID); + }; } -function handleException(e) { - if (e instanceof ExitStatus || e == "unwind") { - return EXITSTATUS; - } - quit_(1, e); +function killThread(pthread_ptr) { + assert(!ENVIRONMENT_IS_PTHREAD, "Internal Error! killThread() can only ever be called from main application thread!"); + assert(pthread_ptr, "Internal Error! Null pthread_ptr in killThread!"); + var worker = PThread.pthreads[pthread_ptr]; + delete PThread.pthreads[pthread_ptr]; + terminateWorker(worker); + __emscripten_thread_free_data(pthread_ptr); + PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(worker), 1); + worker.pthread_ptr = 0; } -function writeArrayToMemory(array, buffer) { - HEAP8.set(array, buffer); +function cancelThread(pthread_ptr) { + assert(!ENVIRONMENT_IS_PTHREAD, "Internal Error! cancelThread() can only ever be called from main application thread!"); + assert(pthread_ptr, "Internal Error! Null pthread_ptr in cancelThread!"); + var worker = PThread.pthreads[pthread_ptr]; + worker.postMessage({ + "cmd": "cancel" + }); } -function ___assert_fail(condition, filename, line, func) { - abort("Assertion failed: " + UTF8ToString(condition) + ", at: " + [ filename ? UTF8ToString(filename) : "unknown filename", line, func ? UTF8ToString(func) : "unknown function" ]); +function cleanupThread(pthread_ptr) { + assert(!ENVIRONMENT_IS_PTHREAD, "Internal Error! cleanupThread() can only ever be called from main application thread!"); + assert(pthread_ptr, "Internal Error! Null pthread_ptr in cleanupThread!"); + var worker = PThread.pthreads[pthread_ptr]; + assert(worker); + PThread.returnWorkerToPool(worker); } -function ___call_sighandler(fp, sig) { - (function(a1) { - dynCall_vi.apply(null, [ fp, a1 ]); - })(sig); +function zeroMemory(address, size) { + GROWABLE_HEAP_U8().fill(0, address, address + size); + return address; +} + +function spawnThread(threadParams) { + assert(!ENVIRONMENT_IS_PTHREAD, "Internal Error! spawnThread() can only ever be called from main application thread!"); + assert(threadParams.pthread_ptr, "Internal error, no pthread ptr!"); + var worker = PThread.getNewWorker(); + if (!worker) { + return 6; + } + assert(!worker.pthread_ptr, "Internal error!"); + PThread.runningWorkers.push(worker); + PThread.pthreads[threadParams.pthread_ptr] = worker; + worker.pthread_ptr = threadParams.pthread_ptr; + var msg = { + "cmd": "run", + "start_routine": threadParams.startRoutine, + "arg": threadParams.arg, + "pthread_ptr": threadParams.pthread_ptr + }; + if (ENVIRONMENT_IS_NODE) { + worker.ref(); + } + worker.postMessage(msg, threadParams.transferList); + return 0; } var PATH = { @@ -582,7 +1096,7 @@ function getRandomDevice() { return () => crypto_module["randomBytes"](1)[0]; } catch (e) {} } - return () => abort("randomDevice"); + return () => abort("no cryptographic support found for randomDevice. consider polyfilling it if you want to use something insecure like Math.random(), e.g. put this in a --pre-js: var crypto = { getRandomValues: function(array) { for (var i = 0; i < array.length; i++) array[i] = (Math.random()*256)|0 } };"); } var PATH_FS = { @@ -780,12 +1294,8 @@ var TTY = { } }; -function zeroMemory(address, size) { - HEAPU8.fill(0, address, address + size); - return address; -} - function alignMemory(size, alignment) { + assert(alignment, "alignment argument is required"); return Math.ceil(size / alignment) * alignment; } @@ -1008,6 +1518,7 @@ var MEMFS = { var contents = stream.node.contents; if (position >= stream.node.usedBytes) return 0; var size = Math.min(stream.node.usedBytes - position, length); + assert(size >= 0); if (size > 8 && contents.subarray) { buffer.set(contents.subarray(position, position + size), offset); } else { @@ -1016,7 +1527,8 @@ var MEMFS = { return size; }, write: function(stream, buffer, offset, length, position, canOwn) { - if (buffer.buffer === HEAP8.buffer) { + assert(!(buffer instanceof ArrayBuffer)); + if (buffer.buffer === GROWABLE_HEAP_I8().buffer) { canOwn = false; } if (!length) return 0; @@ -1024,6 +1536,7 @@ var MEMFS = { node.timestamp = Date.now(); if (buffer.subarray && (!node.contents || node.contents.subarray)) { if (canOwn) { + assert(position === 0, "canOwn must imply no weird position inside the file"); node.contents = buffer.subarray(offset, offset + length); node.usedBytes = length; return length; @@ -1072,7 +1585,7 @@ var MEMFS = { var ptr; var allocated; var contents = stream.node.contents; - if (!(flags & 2) && contents.buffer === buffer) { + if (!(flags & 2) && contents.buffer === GROWABLE_HEAP_I8().buffer) { allocated = false; ptr = contents.byteOffset; } else { @@ -1088,7 +1601,7 @@ var MEMFS = { if (!ptr) { throw new FS.ErrnoError(48); } - HEAP8.set(contents, ptr); + GROWABLE_HEAP_I8().set(contents, ptr); } return { ptr: ptr, @@ -1124,7 +1637,7 @@ var NODEFS = { isWindows: false, staticInit: () => { NODEFS.isWindows = !!process.platform.match(/^win/); - var flags = process["binding"]("constants"); + var flags = process.binding("constants"); if (flags["fs"]) { flags = flags["fs"]; } @@ -1140,12 +1653,15 @@ var NODEFS = { 1: flags["O_WRONLY"], 131072: flags["O_NOFOLLOW"] }; + assert(NODEFS.flagsForNodeMap["0"] === 0); }, convertNodeCode: e => { var code = e.code; + assert(code in ERRNO_CODES, "unexpected node error code: " + code + " (" + e + ")"); return ERRNO_CODES[code]; }, mount: mount => { + assert(ENVIRONMENT_IS_NODE); return NODEFS.createNode(null, "/", NODEFS.getMode(mount.opts.root), 0); }, createNode: (parent, name, mode, dev) => { @@ -1392,7 +1908,7 @@ var NODEFS = { throw new FS.ErrnoError(43); } var ptr = mmapAlloc(length); - NODEFS.stream_ops.read(stream, HEAP8, ptr, length, position); + NODEFS.stream_ops.read(stream, GROWABLE_HEAP_I8(), ptr, length, position); return { ptr: ptr, allocated: true @@ -1405,6 +1921,141 @@ var NODEFS = { } }; +var ERRNO_MESSAGES = { + 0: "Success", + 1: "Arg list too long", + 2: "Permission denied", + 3: "Address already in use", + 4: "Address not available", + 5: "Address family not supported by protocol family", + 6: "No more processes", + 7: "Socket already connected", + 8: "Bad file number", + 9: "Trying to read unreadable message", + 10: "Mount device busy", + 11: "Operation canceled", + 12: "No children", + 13: "Connection aborted", + 14: "Connection refused", + 15: "Connection reset by peer", + 16: "File locking deadlock error", + 17: "Destination address required", + 18: "Math arg out of domain of func", + 19: "Quota exceeded", + 20: "File exists", + 21: "Bad address", + 22: "File too large", + 23: "Host is unreachable", + 24: "Identifier removed", + 25: "Illegal byte sequence", + 26: "Connection already in progress", + 27: "Interrupted system call", + 28: "Invalid argument", + 29: "I/O error", + 30: "Socket is already connected", + 31: "Is a directory", + 32: "Too many symbolic links", + 33: "Too many open files", + 34: "Too many links", + 35: "Message too long", + 36: "Multihop attempted", + 37: "File or path name too long", + 38: "Network interface is not configured", + 39: "Connection reset by network", + 40: "Network is unreachable", + 41: "Too many open files in system", + 42: "No buffer space available", + 43: "No such device", + 44: "No such file or directory", + 45: "Exec format error", + 46: "No record locks available", + 47: "The link has been severed", + 48: "Not enough core", + 49: "No message of desired type", + 50: "Protocol not available", + 51: "No space left on device", + 52: "Function not implemented", + 53: "Socket is not connected", + 54: "Not a directory", + 55: "Directory not empty", + 56: "State not recoverable", + 57: "Socket operation on non-socket", + 59: "Not a typewriter", + 60: "No such device or address", + 61: "Value too large for defined data type", + 62: "Previous owner died", + 63: "Not super-user", + 64: "Broken pipe", + 65: "Protocol error", + 66: "Unknown protocol", + 67: "Protocol wrong type for socket", + 68: "Math result not representable", + 69: "Read only file system", + 70: "Illegal seek", + 71: "No such process", + 72: "Stale file handle", + 73: "Connection timed out", + 74: "Text file busy", + 75: "Cross-device link", + 100: "Device not a stream", + 101: "Bad font file fmt", + 102: "Invalid slot", + 103: "Invalid request code", + 104: "No anode", + 105: "Block device required", + 106: "Channel number out of range", + 107: "Level 3 halted", + 108: "Level 3 reset", + 109: "Link number out of range", + 110: "Protocol driver not attached", + 111: "No CSI structure available", + 112: "Level 2 halted", + 113: "Invalid exchange", + 114: "Invalid request descriptor", + 115: "Exchange full", + 116: "No data (for no delay io)", + 117: "Timer expired", + 118: "Out of streams resources", + 119: "Machine is not on the network", + 120: "Package not installed", + 121: "The object is remote", + 122: "Advertise error", + 123: "Srmount error", + 124: "Communication error on send", + 125: "Cross mount point (not really error)", + 126: "Given log. name not unique", + 127: "f.d. invalid for this operation", + 128: "Remote address changed", + 129: "Can access a needed shared lib", + 130: "Accessing a corrupted shared lib", + 131: ".lib section in a.out corrupted", + 132: "Attempting to link in too many libs", + 133: "Attempting to exec a shared library", + 135: "Streams pipe error", + 136: "Too many users", + 137: "Socket type not supported", + 138: "Not supported", + 139: "Protocol family not supported", + 140: "Can't send after socket shutdown", + 141: "Too many references", + 142: "Host is down", + 148: "No medium (in tape drive)", + 156: "Level 2 not synchronized" +}; + +function demangle(func) { + warnOnce("warning: build with -sDEMANGLE_SUPPORT to link in libcxxabi demangling"); + return func; +} + +function demangleAll(text) { + var regex = /\b_Z[\w\d_]+/g; + return text.replace(regex, function(x) { + var y = demangle(x); + return x === y ? x : y + " [" + x + "]"; + }); +} + var FS = { root: null, mounts: [], @@ -1420,7 +2071,7 @@ var FS = { filesystems: null, syncFSRequests: 0, lookupPath: (path, opts = {}) => { - path = PATH_FS.resolve(FS.cwd(), path); + path = PATH_FS.resolve(path); if (!path) return { path: "", node: null @@ -1433,7 +2084,7 @@ var FS = { if (opts.recurse_count > 8) { throw new FS.ErrnoError(32); } - var parts = PATH.normalizeArray(path.split("/").filter(p => !!p), false); + var parts = path.split("/").filter(p => !!p); var current = FS.root; var current_path = "/"; for (var i = 0; i < parts.length; i++) { @@ -1522,6 +2173,7 @@ var FS = { return FS.lookup(parent, name); }, createNode: (parent, name, mode, rdev) => { + assert(typeof parent == "object"); var node = new FS.FSNode(parent, name, mode, rdev); FS.hashAddNode(node); return node; @@ -1752,6 +2404,7 @@ var FS = { var mounts = FS.getMounts(FS.root.mount); var completed = 0; function doCallback(errCode) { + assert(FS.syncFSRequests > 0); FS.syncFSRequests--; return callback(errCode); } @@ -1775,6 +2428,9 @@ var FS = { }); }, mount: (type, opts, mountpoint) => { + if (typeof type == "string") { + throw type; + } var root = mountpoint === "/"; var pseudo = !mountpoint; var node; @@ -1834,6 +2490,7 @@ var FS = { }); node.mounted = null; var idx = node.mount.mounts.indexOf(mount); + assert(idx !== -1); node.mount.mounts.splice(idx, 1); }, lookup: (parent, name) => { @@ -2486,16 +3143,33 @@ var FS = { var stdin = FS.open("/dev/stdin", 0); var stdout = FS.open("/dev/stdout", 1); var stderr = FS.open("/dev/stderr", 1); + assert(stdin.fd === 0, "invalid handle for stdin (" + stdin.fd + ")"); + assert(stdout.fd === 1, "invalid handle for stdout (" + stdout.fd + ")"); + assert(stderr.fd === 2, "invalid handle for stderr (" + stderr.fd + ")"); }, ensureErrnoError: () => { if (FS.ErrnoError) return; FS.ErrnoError = function ErrnoError(errno, node) { + this.name = "ErrnoError"; this.node = node; this.setErrno = function(errno) { this.errno = errno; + for (var key in ERRNO_CODES) { + if (ERRNO_CODES[key] === errno) { + this.code = key; + break; + } + } }; this.setErrno(errno); - this.message = "FS error"; + this.message = ERRNO_MESSAGES[errno]; + if (this.stack) { + Object.defineProperty(this, "stack", { + value: new Error().stack, + writable: true + }); + this.stack = demangleAll(this.stack); + } }; FS.ErrnoError.prototype = new Error(); FS.ErrnoError.prototype.constructor = FS.ErrnoError; @@ -2517,6 +3191,7 @@ var FS = { }; }, init: (input, output, error) => { + assert(!FS.init.initialized, "FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)"); FS.init.initialized = true; FS.ensureErrnoError(); Module["stdin"] = input || Module["stdin"]; @@ -2817,6 +3492,7 @@ var FS = { var contents = stream.node.contents; if (position >= contents.length) return 0; var size = Math.min(contents.length - position, length); + assert(size >= 0); if (contents.slice) { for (var i = 0; i < size; i++) { buffer[offset + i] = contents[position + i]; @@ -2838,7 +3514,7 @@ var FS = { if (!ptr) { throw new FS.ErrnoError(48); } - writeChunks(stream, HEAP8, ptr, length, position); + writeChunks(stream, GROWABLE_HEAP_I8(), ptr, length, position); return { ptr: ptr, allocated: true @@ -2882,9 +3558,7 @@ var FS = { }, DB_VERSION: 20, DB_STORE_NAME: "FILE_DATA", - saveFilesToDB: (paths, onload, onerror) => { - onload = onload || (() => {}); - onerror = onerror || (() => {}); + saveFilesToDB: (paths, onload = (() => {}), onerror = (() => {})) => { var indexedDB = FS.indexedDB(); try { var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION); @@ -2919,9 +3593,7 @@ var FS = { }; openRequest.onerror = onerror; }, - loadFilesFromDB: (paths, onload, onerror) => { - onload = onload || (() => {}); - onerror = onerror || (() => {}); + loadFilesFromDB: (paths, onload = (() => {}), onerror = (() => {})) => { var indexedDB = FS.indexedDB(); try { var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION); @@ -2960,6 +3632,24 @@ var FS = { transaction.onerror = onerror; }; openRequest.onerror = onerror; + }, + absolutePath: () => { + abort("FS.absolutePath has been removed; use PATH_FS.resolve instead"); + }, + createFolder: () => { + abort("FS.createFolder has been removed; use FS.mkdir instead"); + }, + createLink: () => { + abort("FS.createLink has been removed; use FS.symlink instead"); + }, + joinPath: () => { + abort("FS.joinPath has been removed; use PATH.join instead"); + }, + mmapAlloc: () => { + abort("FS.mmapAlloc has been replaced by the top level function mmapAlloc"); + }, + standardizePath: () => { + abort("FS.standardizePath has been removed; use PATH.normalize instead"); } }; @@ -2993,31 +3683,34 @@ var SYSCALLS = { } throw e; } - HEAP32[buf >> 2] = stat.dev; - HEAP32[buf + 8 >> 2] = stat.ino; - HEAP32[buf + 12 >> 2] = stat.mode; - HEAPU32[buf + 16 >> 2] = stat.nlink; - HEAP32[buf + 20 >> 2] = stat.uid; - HEAP32[buf + 24 >> 2] = stat.gid; - HEAP32[buf + 28 >> 2] = stat.rdev; + GROWABLE_HEAP_I32()[buf >> 2] = stat.dev; + GROWABLE_HEAP_I32()[buf + 8 >> 2] = stat.ino; + GROWABLE_HEAP_I32()[buf + 12 >> 2] = stat.mode; + GROWABLE_HEAP_U32()[buf + 16 >> 2] = stat.nlink; + GROWABLE_HEAP_I32()[buf + 20 >> 2] = stat.uid; + GROWABLE_HEAP_I32()[buf + 24 >> 2] = stat.gid; + GROWABLE_HEAP_I32()[buf + 28 >> 2] = stat.rdev; tempI64 = [ stat.size >>> 0, (tempDouble = stat.size, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], - HEAP32[buf + 40 >> 2] = tempI64[0], HEAP32[buf + 44 >> 2] = tempI64[1]; - HEAP32[buf + 48 >> 2] = 4096; - HEAP32[buf + 52 >> 2] = stat.blocks; - tempI64 = [ Math.floor(stat.atime.getTime() / 1e3) >>> 0, (tempDouble = Math.floor(stat.atime.getTime() / 1e3), + GROWABLE_HEAP_I32()[buf + 40 >> 2] = tempI64[0], GROWABLE_HEAP_I32()[buf + 44 >> 2] = tempI64[1]; + GROWABLE_HEAP_I32()[buf + 48 >> 2] = 4096; + GROWABLE_HEAP_I32()[buf + 52 >> 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.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 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] = 0; - tempI64 = [ Math.floor(stat.mtime.getTime() / 1e3) >>> 0, (tempDouble = Math.floor(stat.mtime.getTime() / 1e3), + GROWABLE_HEAP_I32()[buf + 56 >> 2] = tempI64[0], GROWABLE_HEAP_I32()[buf + 60 >> 2] = tempI64[1]; + GROWABLE_HEAP_U32()[buf + 64 >> 2] = atime % 1e3 * 1e3; + tempI64 = [ Math.floor(mtime / 1e3) >>> 0, (tempDouble = Math.floor(mtime / 1e3), +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 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] = 0; - tempI64 = [ Math.floor(stat.ctime.getTime() / 1e3) >>> 0, (tempDouble = Math.floor(stat.ctime.getTime() / 1e3), + GROWABLE_HEAP_I32()[buf + 72 >> 2] = tempI64[0], GROWABLE_HEAP_I32()[buf + 76 >> 2] = tempI64[1]; + GROWABLE_HEAP_U32()[buf + 80 >> 2] = mtime % 1e3 * 1e3; + tempI64 = [ Math.floor(ctime / 1e3) >>> 0, (tempDouble = Math.floor(ctime / 1e3), +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], - HEAP32[buf + 88 >> 2] = tempI64[0], HEAP32[buf + 92 >> 2] = tempI64[1]; - HEAPU32[buf + 96 >> 2] = 0; + GROWABLE_HEAP_I32()[buf + 88 >> 2] = tempI64[0], GROWABLE_HEAP_I32()[buf + 92 >> 2] = tempI64[1]; + GROWABLE_HEAP_U32()[buf + 96 >> 2] = ctime % 1e3 * 1e3; tempI64 = [ stat.ino >>> 0, (tempDouble = stat.ino, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], - HEAP32[buf + 104 >> 2] = tempI64[0], HEAP32[buf + 108 >> 2] = tempI64[1]; + GROWABLE_HEAP_I32()[buf + 104 >> 2] = tempI64[0], GROWABLE_HEAP_I32()[buf + 108 >> 2] = tempI64[1]; return 0; }, doMsync: function(addr, stream, len, flags, offset) { @@ -3027,13 +3720,14 @@ var SYSCALLS = { if (flags & 2) { return 0; } - var buffer = HEAPU8.slice(addr, addr + len); + var buffer = GROWABLE_HEAP_U8().slice(addr, addr + len); FS.msync(stream, buffer, offset, len, flags); }, varargs: undefined, get: function() { + assert(SYSCALLS.varargs != undefined); SYSCALLS.varargs += 4; - var ret = HEAP32[SYSCALLS.varargs - 4 >> 2]; + var ret = GROWABLE_HEAP_I32()[SYSCALLS.varargs - 4 >> 2]; return ret; }, getStr: function(ptr) { @@ -3047,17 +3741,394 @@ var SYSCALLS = { } }; -function ___syscall__newselect(nfds, readfds, writefds, exceptfds, timeout) { - try { +function _proc_exit(code) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(1, 1, code); + EXITSTATUS = code; + if (!keepRuntimeAlive()) { + PThread.terminateAllThreads(); + if (Module["onExit"]) Module["onExit"](code); + ABORT = true; + } + quit_(code, new ExitStatus(code)); +} + +function exitJS(status, implicit) { + EXITSTATUS = status; + if (ENVIRONMENT_IS_PTHREAD) { + assert(!implicit); + exitOnMainThread(status); + throw "unwind"; + } + if (!keepRuntimeAlive()) { + exitRuntime(); + } + if (keepRuntimeAlive() && !implicit) { + var msg = "program exited (with status: " + status + "), but keepRuntimeAlive() is set (counter=" + runtimeKeepaliveCounter + ") due to an async operation, so halting execution but not exiting the runtime or preventing further async execution (you can use emscripten_force_exit, if you want to force a true shutdown)"; + err(msg); + } + _proc_exit(status); +} + +var _exit = exitJS; + +function ptrToString(ptr) { + assert(typeof ptr === "number"); + return "0x" + ptr.toString(16).padStart(8, "0"); +} + +function handleException(e) { + if (e instanceof ExitStatus || e == "unwind") { + return EXITSTATUS; + } + checkStackCookie(); + if (e instanceof WebAssembly.RuntimeError) { + if (_emscripten_stack_get_current() <= 0) { + err("Stack overflow detected. You can try increasing -sSTACK_SIZE (currently set to " + 65536 + ")"); + } + } + quit_(1, e); +} + +var PThread = { + unusedWorkers: [], + runningWorkers: [], + tlsInitFunctions: [], + pthreads: {}, + nextWorkerID: 1, + debugInit: function() { + function pthreadLogPrefix() { + var t = 0; + if (runtimeInitialized && typeof _pthread_self != "undefined" && !runtimeExited) { + t = _pthread_self(); + } + return "w:" + (Module["workerID"] || 0) + ",t:" + ptrToString(t) + ": "; + } + var origDbg = dbg; + dbg = message => origDbg(pthreadLogPrefix() + message); + }, + init: function() { + PThread.debugInit(); + if (ENVIRONMENT_IS_PTHREAD) { + PThread.initWorker(); + } else { + PThread.initMainThread(); + } + }, + initMainThread: function() {}, + initWorker: function() { + noExitRuntime = false; + }, + setExitStatus: function(status) { + EXITSTATUS = status; + }, + terminateAllThreads__deps: [ "$terminateWorker" ], + terminateAllThreads: function() { + assert(!ENVIRONMENT_IS_PTHREAD, "Internal Error! terminateAllThreads() can only ever be called from main application thread!"); + for (var worker of PThread.runningWorkers) { + terminateWorker(worker); + } + for (var worker of PThread.unusedWorkers) { + terminateWorker(worker); + } + PThread.unusedWorkers = []; + PThread.runningWorkers = []; + PThread.pthreads = []; + }, + returnWorkerToPool: function(worker) { + var pthread_ptr = worker.pthread_ptr; + delete PThread.pthreads[pthread_ptr]; + PThread.unusedWorkers.push(worker); + PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(worker), 1); + worker.pthread_ptr = 0; + if (ENVIRONMENT_IS_NODE) { + worker.unref(); + } + __emscripten_thread_free_data(pthread_ptr); + }, + receiveObjectTransfer: function(data) {}, + threadInitTLS: function() { + PThread.tlsInitFunctions.forEach(f => f()); + }, + loadWasmModuleToWorker: worker => new Promise(onFinishedLoading => { + worker.onmessage = e => { + var d = e["data"]; + var cmd = d["cmd"]; + if (worker.pthread_ptr) PThread.currentProxiedOperationCallerThread = worker.pthread_ptr; + if (d["targetThread"] && d["targetThread"] != _pthread_self()) { + var targetWorker = PThread.pthreads[d.targetThread]; + if (targetWorker) { + targetWorker.postMessage(d, d["transferList"]); + } else { + err('Internal error! Worker sent a message "' + cmd + '" to target pthread ' + d["targetThread"] + ", but that thread no longer exists!"); + } + PThread.currentProxiedOperationCallerThread = undefined; + return; + } + if (cmd === "checkMailbox") { + checkMailbox(); + } else if (cmd === "spawnThread") { + spawnThread(d); + } else if (cmd === "cleanupThread") { + cleanupThread(d["thread"]); + } else if (cmd === "killThread") { + killThread(d["thread"]); + } else if (cmd === "cancelThread") { + cancelThread(d["thread"]); + } else if (cmd === "loaded") { + worker.loaded = true; + if (ENVIRONMENT_IS_NODE && !worker.pthread_ptr) { + worker.unref(); + } + onFinishedLoading(worker); + } else if (cmd === "print") { + out("Thread " + d["threadId"] + ": " + d["text"]); + } else if (cmd === "printErr") { + err("Thread " + d["threadId"] + ": " + d["text"]); + } else if (cmd === "alert") { + alert("Thread " + d["threadId"] + ": " + d["text"]); + } else if (d.target === "setimmediate") { + worker.postMessage(d); + } else if (cmd === "callHandler") { + Module[d["handler"]](...d["args"]); + } else if (cmd) { + err("worker sent an unknown command " + cmd); + } + PThread.currentProxiedOperationCallerThread = undefined; + }; + worker.onerror = e => { + var message = "worker sent an error!"; + if (worker.pthread_ptr) { + message = "Pthread " + ptrToString(worker.pthread_ptr) + " sent an error!"; + } + err(message + " " + e.filename + ":" + e.lineno + ": " + e.message); + throw e; + }; + if (ENVIRONMENT_IS_NODE) { + worker.on("message", function(data) { + worker.onmessage({ + data: data + }); + }); + worker.on("error", function(e) { + worker.onerror(e); + }); + worker.on("detachedExit", function() {}); + } + assert(wasmMemory instanceof WebAssembly.Memory, "WebAssembly memory should have been loaded by now!"); + assert(wasmModule instanceof WebAssembly.Module, "WebAssembly Module should have been loaded by now!"); + var handlers = []; + var knownHandlers = [ "onExit", "onAbort", "print", "printErr" ]; + for (var handler of knownHandlers) { + if (Module.hasOwnProperty(handler)) { + handlers.push(handler); + } + } + worker.workerID = PThread.nextWorkerID++; + worker.postMessage({ + "cmd": "load", + "handlers": handlers, + "urlOrBlob": Module["mainScriptUrlOrBlob"] || _scriptDir, + "wasmMemory": wasmMemory, + "wasmModule": wasmModule, + "workerID": worker.workerID + }); + }), + loadWasmModuleToAllWorkers: function(onMaybeReady) { + onMaybeReady(); + }, + allocateUnusedWorker: function() { + var worker; + var pthreadMainJs = locateFile("php.worker.js"); + worker = new Worker(pthreadMainJs); + PThread.unusedWorkers.push(worker); + }, + getNewWorker: function() { + if (PThread.unusedWorkers.length == 0) { + if (!ENVIRONMENT_IS_NODE) { + err("Tried to spawn a new thread, but the thread pool is exhausted.\n" + "This might result in a deadlock unless some threads eventually exit or the code explicitly breaks out to the event loop.\n" + "If you want to increase the pool size, use setting `-sPTHREAD_POOL_SIZE=...`." + "\nIf you want to throw an explicit error instead of the risk of deadlocking in those cases, use setting `-sPTHREAD_POOL_SIZE_STRICT=2`."); + } + PThread.allocateUnusedWorker(); + PThread.loadWasmModuleToWorker(PThread.unusedWorkers[0]); + } + return PThread.unusedWorkers.pop(); + } +}; + +Module["PThread"] = PThread; + +function callRuntimeCallbacks(callbacks) { + while (callbacks.length > 0) { + callbacks.shift()(Module); + } +} + +function establishStackSpace() { + var pthread_ptr = _pthread_self(); + var stackTop = GROWABLE_HEAP_I32()[pthread_ptr + 52 >> 2]; + var stackSize = GROWABLE_HEAP_I32()[pthread_ptr + 56 >> 2]; + var stackMax = stackTop - stackSize; + assert(stackTop != 0); + assert(stackMax != 0); + assert(stackTop > stackMax, "stackTop must be higher then stackMax"); + _emscripten_stack_set_limits(stackTop, stackMax); + ___set_stack_limits(stackTop, stackMax); + stackRestore(stackTop); + writeStackCookie(); +} + +Module["establishStackSpace"] = establishStackSpace; + +function exitOnMainThread(returnCode) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(2, 0, returnCode); + _exit(returnCode); +} + +function getValue(ptr, type = "i8") { + if (type.endsWith("*")) type = "*"; + switch (type) { + case "i1": + return GROWABLE_HEAP_I8()[ptr >> 0]; + + case "i8": + return GROWABLE_HEAP_I8()[ptr >> 0]; + + case "i16": + return GROWABLE_HEAP_I16()[ptr >> 1]; + + case "i32": + return GROWABLE_HEAP_I32()[ptr >> 2]; + + case "i64": + return GROWABLE_HEAP_I32()[ptr >> 2]; + + case "float": + return GROWABLE_HEAP_F32()[ptr >> 2]; + + case "double": + return GROWABLE_HEAP_F64()[ptr >> 3]; + + case "*": + return GROWABLE_HEAP_U32()[ptr >> 2]; + + default: + abort("invalid type for getValue: " + type); + } +} + +function invokeEntryPoint(ptr, arg) { + runtimeKeepaliveCounter = 0; + var result = (a1 => dynCall_ii.apply(null, [ ptr, a1 ]))(arg); + checkStackCookie(); + if (keepRuntimeAlive()) { + PThread.setExitStatus(result); + } else { + __emscripten_thread_exit(result); + } +} + +Module["invokeEntryPoint"] = invokeEntryPoint; + +function registerTLSInit(tlsInitFunc) { + PThread.tlsInitFunctions.push(tlsInitFunc); +} + +function setValue(ptr, value, type = "i8") { + if (type.endsWith("*")) type = "*"; + switch (type) { + case "i1": + GROWABLE_HEAP_I8()[ptr >> 0] = value; + break; + + case "i8": + GROWABLE_HEAP_I8()[ptr >> 0] = value; + break; + + case "i16": + GROWABLE_HEAP_I16()[ptr >> 1] = value; + break; + + case "i32": + GROWABLE_HEAP_I32()[ptr >> 2] = value; + break; + + case "i64": + tempI64 = [ value >>> 0, (tempDouble = value, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], + GROWABLE_HEAP_I32()[ptr >> 2] = tempI64[0], GROWABLE_HEAP_I32()[ptr + 4 >> 2] = tempI64[1]; + break; + + case "float": + GROWABLE_HEAP_F32()[ptr >> 2] = value; + break; + + case "double": + GROWABLE_HEAP_F64()[ptr >> 3] = value; + break; + + case "*": + GROWABLE_HEAP_U32()[ptr >> 2] = value; + break; + + default: + abort("invalid type for setValue: " + type); + } +} + +function warnOnce(text) { + if (!warnOnce.shown) warnOnce.shown = {}; + if (!warnOnce.shown[text]) { + warnOnce.shown[text] = 1; + if (ENVIRONMENT_IS_NODE) text = "warning: " + text; + err(text); + } +} + +function ___assert_fail(condition, filename, line, func) { + abort("Assertion failed: " + UTF8ToString(condition) + ", at: " + [ filename ? UTF8ToString(filename) : "unknown filename", line, func ? UTF8ToString(func) : "unknown function" ]); +} + +function ___call_sighandler(fp, sig) { + (a1 => dynCall_vi.apply(null, [ fp, a1 ]))(sig); +} + +var dlopenMissingError = "To use dlopen, you need enable dynamic linking, see https://github.com/emscripten-core/emscripten/wiki/Linking"; + +function ___dlsym(handle, symbol) { + abort(dlopenMissingError); +} + +function ___emscripten_init_main_thread_js(tb) { + __emscripten_thread_init(tb, !ENVIRONMENT_IS_WORKER, 1, !ENVIRONMENT_IS_WEB); + PThread.threadInitTLS(); +} + +function ___emscripten_thread_cleanup(thread) { + if (!ENVIRONMENT_IS_PTHREAD) cleanupThread(thread); else postMessage({ + "cmd": "cleanupThread", + "thread": thread + }); +} + +function ___handle_stack_overflow(requested) { + requested = requested >>> 0; + var base = _emscripten_stack_get_base(); + var end = _emscripten_stack_get_end(); + abort("stack overflow (Attempt to set SP to " + ptrToString(requested) + ", with stack limits [" + ptrToString(end) + " - " + ptrToString(base) + "]). If you require more stack space build with -sSTACK_SIZE="); +} + +function ___syscall__newselect(nfds, readfds, writefds, exceptfds, timeout) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(3, 1, nfds, readfds, writefds, exceptfds, timeout); + try { + assert(nfds <= 64, "nfds must be less than or equal to 64"); + assert(!exceptfds, "exceptfds not supported"); 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 srcReadLow = readfds ? GROWABLE_HEAP_I32()[readfds >> 2] : 0, srcReadHigh = readfds ? GROWABLE_HEAP_I32()[readfds + 4 >> 2] : 0; + var srcWriteLow = writefds ? GROWABLE_HEAP_I32()[writefds >> 2] : 0, srcWriteHigh = writefds ? GROWABLE_HEAP_I32()[writefds + 4 >> 2] : 0; + var srcExceptLow = exceptfds ? GROWABLE_HEAP_I32()[exceptfds >> 2] : 0, srcExceptHigh = exceptfds ? GROWABLE_HEAP_I32()[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 allLow = (readfds ? GROWABLE_HEAP_I32()[readfds >> 2] : 0) | (writefds ? GROWABLE_HEAP_I32()[writefds >> 2] : 0) | (exceptfds ? GROWABLE_HEAP_I32()[exceptfds >> 2] : 0); + var allHigh = (readfds ? GROWABLE_HEAP_I32()[readfds + 4 >> 2] : 0) | (writefds ? GROWABLE_HEAP_I32()[writefds + 4 >> 2] : 0) | (exceptfds ? GROWABLE_HEAP_I32()[exceptfds + 4 >> 2] : 0); var check = function(fd, low, high, val) { return fd < 32 ? low & val : high & val; }; @@ -3085,20 +4156,20 @@ function ___syscall__newselect(nfds, readfds, writefds, exceptfds, timeout) { } } if (readfds) { - HEAP32[readfds >> 2] = dstReadLow; - HEAP32[readfds + 4 >> 2] = dstReadHigh; + GROWABLE_HEAP_I32()[readfds >> 2] = dstReadLow; + GROWABLE_HEAP_I32()[readfds + 4 >> 2] = dstReadHigh; } if (writefds) { - HEAP32[writefds >> 2] = dstWriteLow; - HEAP32[writefds + 4 >> 2] = dstWriteHigh; + GROWABLE_HEAP_I32()[writefds >> 2] = dstWriteLow; + GROWABLE_HEAP_I32()[writefds + 4 >> 2] = dstWriteHigh; } if (exceptfds) { - HEAP32[exceptfds >> 2] = dstExceptLow; - HEAP32[exceptfds + 4 >> 2] = dstExceptHigh; + GROWABLE_HEAP_I32()[exceptfds >> 2] = dstExceptLow; + GROWABLE_HEAP_I32()[exceptfds + 4 >> 2] = dstExceptHigh; } return total; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } @@ -3368,7 +4439,7 @@ url = Module["websocket"]["url"](...arguments); if (sock.recv_queue.length) { bytes = sock.recv_queue[0].data.length; } - HEAP32[arg >> 2] = bytes; + GROWABLE_HEAP_I32()[arg >> 2] = bytes; return 0; default: @@ -3406,7 +4477,7 @@ url = Module["websocket"]["url"](...arguments); try { sock.sock_ops.listen(sock, 0); } catch (e) { - if (!(e instanceof FS.ErrnoError)) throw e; + if (!(e.name === "ErrnoError")) throw e; if (e.errno !== 138) throw e; } } @@ -3439,7 +4510,7 @@ url = Module["websocket"]["url"](...arguments); } var WebSocketServer = require("ws").Server; var host = sock.saddr; - if (Module['websocket']['serverDecorator']) {WebSocketServer = Module['websocket']['serverDecorator'](WebSocketServer);}sock.server = new WebSocketServer({ + sock.server = new WebSocketServer({ host: host, port: sock.sport }); @@ -3517,7 +4588,11 @@ url = Module["websocket"]["url"](...arguments); buffer = buffer.buffer; } var data; - data = buffer.slice(offset, offset + length); + if (buffer instanceof SharedArrayBuffer) { + data = new Uint8Array(new Uint8Array(buffer.slice(offset, offset + length))).buffer; + } else { + 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) { @@ -3534,7 +4609,7 @@ url = Module["websocket"]["url"](...arguments); throw new FS.ErrnoError(28); } }, - recvmsg: function(sock, length, flags) { + recvmsg: function(sock, length) { if (sock.type === 1 && sock.server) { throw new FS.ErrnoError(53); } @@ -3561,7 +4636,7 @@ url = Module["websocket"]["url"](...arguments); addr: queued.addr, port: queued.port }; - if (flags&2) {bytesRead = 0;} if (sock.type === 1 && bytesRead < queuedLength) { + if (sock.type === 1 && bytesRead < queuedLength) { var bytesRemaining = queuedLength - bytesRead; queued.data = new Uint8Array(queuedBuffer, queuedOffset + bytesRead, bytesRemaining); sock.recv_queue.unshift(queued); @@ -3578,10 +4653,24 @@ function getSocketFromFD(fd) { } function setErrNo(value) { - HEAP32[___errno_location() >> 2] = value; + GROWABLE_HEAP_I32()[___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 ] +}; + function inetPton4(str) { var b = str.split("."); for (var i = 0; i < 4; i++) { @@ -3598,7 +4687,7 @@ function jstoi_q(str) { function inetPton6(str) { var words; - var w, offset, z; + var w, offset, z, i; 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)) { @@ -3646,25 +4735,25 @@ function writeSockaddr(sa, family, addr, port, addrlen) { addr = inetPton4(addr); zeroMemory(sa, 16); if (addrlen) { - HEAP32[addrlen >> 2] = 16; + GROWABLE_HEAP_I32()[addrlen >> 2] = 16; } - HEAP16[sa >> 1] = family; - HEAP32[sa + 4 >> 2] = addr; - HEAP16[sa + 2 >> 1] = _htons(port); + GROWABLE_HEAP_I16()[sa >> 1] = family; + GROWABLE_HEAP_I32()[sa + 4 >> 2] = addr; + GROWABLE_HEAP_I16()[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); + GROWABLE_HEAP_I32()[addrlen >> 2] = 28; + } + GROWABLE_HEAP_I32()[sa >> 2] = family; + GROWABLE_HEAP_I32()[sa + 8 >> 2] = addr[0]; + GROWABLE_HEAP_I32()[sa + 12 >> 2] = addr[1]; + GROWABLE_HEAP_I32()[sa + 16 >> 2] = addr[2]; + GROWABLE_HEAP_I32()[sa + 20 >> 2] = addr[3]; + GROWABLE_HEAP_I16()[sa + 2 >> 1] = _htons(port); break; default: @@ -3709,15 +4798,17 @@ var DNS = { }; function ___syscall_accept4(fd, addr, addrlen, flags) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(4, 1, fd, addr, addrlen, flags); 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); + assert(!errno); } return newsock.stream.fd; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } @@ -3788,8 +4879,8 @@ function inetNtop6(ints) { } function readSockaddr(sa, salen) { - var family = HEAP16[sa >> 1]; - var port = _ntohs(HEAPU16[sa + 2 >> 1]); + var family = GROWABLE_HEAP_I16()[sa >> 1]; + var port = _ntohs(GROWABLE_HEAP_U16()[sa + 2 >> 1]); var addr; switch (family) { case 2: @@ -3798,7 +4889,7 @@ function readSockaddr(sa, salen) { errno: 28 }; } - addr = HEAP32[sa + 4 >> 2]; + addr = GROWABLE_HEAP_I32()[sa + 4 >> 2]; addr = inetNtop4(addr); break; @@ -3808,7 +4899,7 @@ function readSockaddr(sa, salen) { errno: 28 }; } - addr = [ HEAP32[sa + 8 >> 2], HEAP32[sa + 12 >> 2], HEAP32[sa + 16 >> 2], HEAP32[sa + 20 >> 2] ]; + addr = [ GROWABLE_HEAP_I32()[sa + 8 >> 2], GROWABLE_HEAP_I32()[sa + 12 >> 2], GROWABLE_HEAP_I32()[sa + 16 >> 2], GROWABLE_HEAP_I32()[sa + 20 >> 2] ]; addr = inetNtop6(addr); break; @@ -3833,77 +4924,86 @@ function getSocketAddress(addrp, addrlen, allowNull) { } function ___syscall_bind(fd, addr, addrlen) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(5, 1, fd, addr, addrlen); 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 instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_chdir(path) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(6, 1, path); try { path = SYSCALLS.getStr(path); FS.chdir(path); return 0; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_chmod(path, mode) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(7, 1, path, mode); try { path = SYSCALLS.getStr(path); FS.chmod(path, mode); return 0; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_connect(fd, addr, addrlen) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(8, 1, fd, addr, addrlen); 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 instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_dup(fd) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(9, 1, fd); try { var old = SYSCALLS.getStreamFromFD(fd); return FS.createStream(old, 0).fd; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_dup3(fd, suggestFD, flags) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(10, 1, fd, suggestFD, flags); try { var old = SYSCALLS.getStreamFromFD(fd); + assert(!flags); if (old.fd === suggestFD) return -28; var suggest = FS.getStream(suggestFD); if (suggest) FS.close(suggest); return FS.createStream(old, suggestFD, suggestFD + 1).fd; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_faccessat(dirfd, path, amode, flags) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(11, 1, dirfd, path, amode, flags); try { path = SYSCALLS.getStr(path); + assert(flags === 0); path = SYSCALLS.calculateAt(dirfd, path); if (amode & ~7) { return -28; @@ -3924,65 +5024,29 @@ function ___syscall_faccessat(dirfd, path, amode, flags) { } return 0; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.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) { - try { - var offset = convertI32PairToI53Checked(offset_low, offset_high); - if (isNaN(offset)) return -61; - var len = convertI32PairToI53Checked(len_low, len_high); - if (isNaN(len)) return -61; - var stream = SYSCALLS.getStreamFromFD(fd); - FS.allocate(stream, offset, len); - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.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 instanceof FS.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 instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_fchownat(dirfd, path, owner, group, flags) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(12, 1, dirfd, path, owner, group, flags); try { path = SYSCALLS.getStr(path); var nofollow = flags & 256; flags = flags & ~256; + assert(flags === 0); path = SYSCALLS.calculateAt(dirfd, path); (nofollow ? FS.lchown : FS.chown)(path, owner, group); return 0; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_fcntl64(fd, cmd, varargs) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(13, 1, fd, cmd, varargs); SYSCALLS.varargs = varargs; try { var stream = SYSCALLS.getStreamFromFD(fd); @@ -4016,7 +5080,7 @@ function ___syscall_fcntl64(fd, cmd, varargs) { { var arg = SYSCALLS.get(); var offset = 0; - HEAP16[arg + offset >> 1] = 2; + GROWABLE_HEAP_I16()[arg + offset >> 1] = 2; return 0; } @@ -4038,44 +5102,43 @@ function ___syscall_fcntl64(fd, cmd, varargs) { } } } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.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 instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_fstat64(fd, buf) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(14, 1, fd, buf); try { var stream = SYSCALLS.getStreamFromFD(fd); return SYSCALLS.doStat(FS.stat, stream.path, buf); } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } +function convertI32PairToI53Checked(lo, hi) { + assert(lo == lo >>> 0 || lo == (lo | 0)); + assert(hi === (hi | 0)); + return hi + 2097152 >>> 0 < 4194305 - !!lo ? (lo >>> 0) + hi * 4294967296 : NaN; +} + function ___syscall_ftruncate64(fd, length_low, length_high) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(15, 1, fd, length_low, length_high); try { var length = convertI32PairToI53Checked(length_low, length_high); if (isNaN(length)) return -61; FS.ftruncate(fd, length); return 0; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_getcwd(buf, size) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(16, 1, buf, size); try { if (size === 0) return -28; var cwd = FS.cwd(); @@ -4084,12 +5147,13 @@ function ___syscall_getcwd(buf, size) { stringToUTF8(cwd, buf, size); return cwdLengthInBytes; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_getdents64(fd, dirp, count) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(17, 1, fd, dirp, count); try { var stream = SYSCALLS.getStreamFromFD(fd); if (!stream.getdents) { @@ -4117,13 +5181,14 @@ function ___syscall_getdents64(fd, dirp, count) { id = child.id; type = FS.isChrdev(child.mode) ? 2 : FS.isDir(child.mode) ? 4 : FS.isLink(child.mode) ? 10 : 8; } + assert(id); tempI64 = [ id >>> 0, (tempDouble = id, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], - HEAP32[dirp + pos >> 2] = tempI64[0], HEAP32[dirp + pos + 4 >> 2] = tempI64[1]; + GROWABLE_HEAP_I32()[dirp + pos >> 2] = tempI64[0], GROWABLE_HEAP_I32()[dirp + pos + 4 >> 2] = tempI64[1]; tempI64 = [ (idx + 1) * struct_size >>> 0, (tempDouble = (idx + 1) * struct_size, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 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; + GROWABLE_HEAP_I32()[dirp + pos + 8 >> 2] = tempI64[0], GROWABLE_HEAP_I32()[dirp + pos + 12 >> 2] = tempI64[1]; + GROWABLE_HEAP_I16()[dirp + pos + 16 >> 1] = 280; + GROWABLE_HEAP_I8()[dirp + pos + 18 >> 0] = type; stringToUTF8(name, dirp + pos + 19, 256); pos += struct_size; idx += 1; @@ -4131,56 +5196,62 @@ function ___syscall_getdents64(fd, dirp, count) { FS.llseek(stream, idx * struct_size, 0); return pos; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_getpeername(fd, addr, addrlen) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(18, 1, fd, addr, addrlen); try { var sock = getSocketFromFD(fd); if (!sock.daddr) { return -53; } var errno = writeSockaddr(addr, sock.family, DNS.lookup_name(sock.daddr), sock.dport, addrlen); + assert(!errno); return 0; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_getsockname(fd, addr, addrlen) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(19, 1, fd, addr, addrlen); try { err("__syscall_getsockname " + fd); var sock = getSocketFromFD(fd); var errno = writeSockaddr(addr, sock.family, DNS.lookup_name(sock.saddr || "0.0.0.0"), sock.sport, addrlen); + assert(!errno); return 0; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_getsockopt(fd, level, optname, optval, optlen) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(20, 1, fd, level, optname, optval, optlen); try { var sock = getSocketFromFD(fd); if (level === 1) { if (optname === 4) { - HEAP32[optval >> 2] = sock.error; - HEAP32[optlen >> 2] = 4; + GROWABLE_HEAP_I32()[optval >> 2] = sock.error; + GROWABLE_HEAP_I32()[optlen >> 2] = 4; sock.error = null; return 0; } } return -50; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_ioctl(fd, op, varargs) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(21, 1, fd, op, varargs); SYSCALLS.varargs = varargs; try { var stream = SYSCALLS.getStreamFromFD(fd); @@ -4207,7 +5278,7 @@ function ___syscall_ioctl(fd, op, varargs) { { if (!stream.tty) return -59; var argp = SYSCALLS.get(); - HEAP32[argp >> 2] = 0; + GROWABLE_HEAP_I32()[argp >> 2] = 0; return 0; } @@ -4239,33 +5310,36 @@ function ___syscall_ioctl(fd, op, varargs) { return -28; } } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_listen(fd, backlog) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(22, 1, fd, backlog); try { var sock = getSocketFromFD(fd); sock.sock_ops.listen(sock, backlog); return 0; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_lstat64(path, buf) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(23, 1, path, buf); try { path = SYSCALLS.getStr(path); return SYSCALLS.doStat(FS.lstat, path, buf); } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_mkdirat(dirfd, path, mode) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(24, 1, dirfd, path, mode); try { path = SYSCALLS.getStr(path); path = SYSCALLS.calculateAt(dirfd, path); @@ -4274,26 +5348,29 @@ function ___syscall_mkdirat(dirfd, path, mode) { FS.mkdir(path, mode, 0); return 0; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_newfstatat(dirfd, path, buf, flags) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(25, 1, dirfd, path, buf, flags); try { path = SYSCALLS.getStr(path); var nofollow = flags & 256; var allowEmpty = flags & 4096; - flags = flags & ~4352; + flags = flags & ~6400; + assert(!flags, "unknown flags in __syscall_newfstatat: " + flags); path = SYSCALLS.calculateAt(dirfd, path, allowEmpty); return SYSCALLS.doStat(nofollow ? FS.lstat : FS.stat, path, buf); } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_openat(dirfd, path, flags, varargs) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(26, 1, dirfd, path, flags, varargs); SYSCALLS.varargs = varargs; try { path = SYSCALLS.getStr(path); @@ -4301,7 +5378,7 @@ function ___syscall_openat(dirfd, path, flags, varargs) { var mode = varargs ? SYSCALLS.get() : 0; return FS.open(path, flags, mode).fd; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } @@ -4377,7 +5454,7 @@ var PIPEFS = { var bucket = pipe.buckets[i]; currentLength += bucket.offset - bucket.roffset; } - assert(buffer instanceof ArrayBuffer || ArrayBuffer.isView(buffer)); + assert(buffer instanceof ArrayBuffer || buffer instanceof SharedArrayBuffer || ArrayBuffer.isView(buffer)); var data = buffer.subarray(offset, offset + length); if (length <= 0) { return 0; @@ -4419,7 +5496,7 @@ var PIPEFS = { }, write: function(stream, buffer, offset, length, position) { var pipe = stream.node.pipe; - assert(buffer instanceof ArrayBuffer || ArrayBuffer.isView(buffer)); + assert(buffer instanceof ArrayBuffer || buffer instanceof SharedArrayBuffer || ArrayBuffer.isView(buffer)); var data = buffer.subarray(offset, offset + length); var dataLen = data.byteLength; if (dataLen <= 0) { @@ -4487,27 +5564,29 @@ var PIPEFS = { }; function ___syscall_pipe(fdPtr) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(27, 1, 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; + GROWABLE_HEAP_I32()[fdPtr >> 2] = res.readable_fd; + GROWABLE_HEAP_I32()[fdPtr + 4 >> 2] = res.writable_fd; return 0; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_poll(fds, nfds, timeout) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(28, 1, 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 fd = GROWABLE_HEAP_I32()[pollfd >> 2]; + var events = GROWABLE_HEAP_I16()[pollfd + 4 >> 1]; var mask = 32; var stream = FS.getStream(fd); if (stream) { @@ -4518,49 +5597,53 @@ function ___syscall_poll(fds, nfds, timeout) { } mask &= events | 8 | 16; if (mask) nonzero++; - HEAP16[pollfd + 6 >> 1] = mask; + GROWABLE_HEAP_I16()[pollfd + 6 >> 1] = mask; } return nonzero; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_readlinkat(dirfd, path, buf, bufsize) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(29, 1, 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]; + var endChar = GROWABLE_HEAP_I8()[buf + len]; stringToUTF8(ret, buf, bufsize + 1); - HEAP8[buf + len] = endChar; + GROWABLE_HEAP_I8()[buf + len] = endChar; return len; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_recvfrom(fd, buf, len, flags, addr, addrlen) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(30, 1, fd, buf, len, flags, addr, addrlen); try { var sock = getSocketFromFD(fd); - var msg = sock.sock_ops.recvmsg(sock, len, typeof flags !== "undefined" ? flags : 0); + 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); + assert(!errno); } - HEAPU8.set(msg.buffer, buf); + GROWABLE_HEAP_U8().set(msg.buffer, buf); return msg.buffer.byteLength; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_renameat(olddirfd, oldpath, newdirfd, newpath) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(31, 1, olddirfd, oldpath, newdirfd, newpath); try { oldpath = SYSCALLS.getStr(oldpath); newpath = SYSCALLS.getStr(newpath); @@ -4569,89 +5652,98 @@ function ___syscall_renameat(olddirfd, oldpath, newdirfd, newpath) { FS.rename(oldpath, newpath); return 0; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_rmdir(path) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(32, 1, path); try { path = SYSCALLS.getStr(path); FS.rmdir(path); return 0; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_sendto(fd, message, length, flags, addr, addr_len) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(33, 1, 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 FS.write(sock.stream, GROWABLE_HEAP_I8(), message, length); } - return sock.sock_ops.sendmsg(sock, HEAP8, message, length, dest.addr, dest.port); + return sock.sock_ops.sendmsg(sock, GROWABLE_HEAP_I8(), message, length, dest.addr, dest.port); } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_socket(domain, type, protocol) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(34, 1, domain, type, protocol); try { var sock = SOCKFS.createSocket(domain, type, protocol); + assert(sock.stream.fd < 64); return sock.stream.fd; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_stat64(path, buf) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(35, 1, path, buf); try { path = SYSCALLS.getStr(path); return SYSCALLS.doStat(FS.stat, path, buf); } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_statfs64(path, size, buf) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(36, 1, 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; + assert(size === 64); + GROWABLE_HEAP_I32()[buf + 4 >> 2] = 4096; + GROWABLE_HEAP_I32()[buf + 40 >> 2] = 4096; + GROWABLE_HEAP_I32()[buf + 8 >> 2] = 1e6; + GROWABLE_HEAP_I32()[buf + 12 >> 2] = 5e5; + GROWABLE_HEAP_I32()[buf + 16 >> 2] = 5e5; + GROWABLE_HEAP_I32()[buf + 20 >> 2] = FS.nextInode; + GROWABLE_HEAP_I32()[buf + 24 >> 2] = 1e6; + GROWABLE_HEAP_I32()[buf + 28 >> 2] = 42; + GROWABLE_HEAP_I32()[buf + 44 >> 2] = 2; + GROWABLE_HEAP_I32()[buf + 36 >> 2] = 255; return 0; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_symlink(target, linkpath) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(37, 1, target, linkpath); try { target = SYSCALLS.getStr(target); linkpath = SYSCALLS.getStr(linkpath); FS.symlink(target, linkpath); return 0; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function ___syscall_unlinkat(dirfd, path, flags) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(38, 1, dirfd, path, flags); try { path = SYSCALLS.getStr(path); path = SYSCALLS.calculateAt(dirfd, path); @@ -4664,55 +5756,118 @@ function ___syscall_unlinkat(dirfd, path, flags) { } return 0; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw 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; + return GROWABLE_HEAP_U32()[ptr >> 2] + GROWABLE_HEAP_I32()[ptr + 4 >> 2] * 4294967296; } function ___syscall_utimensat(dirfd, path, times, flags) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(39, 1, dirfd, path, times, flags); try { path = SYSCALLS.getStr(path); + assert(flags === 0); 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]; + var nanoseconds = GROWABLE_HEAP_I32()[times + 8 >> 2]; atime = seconds * 1e3 + nanoseconds / (1e3 * 1e3); times += 16; seconds = readI53FromI64(times); - nanoseconds = HEAP32[times + 8 >> 2]; + nanoseconds = GROWABLE_HEAP_I32()[times + 8 >> 2]; mtime = seconds * 1e3 + nanoseconds / (1e3 * 1e3); } FS.utime(path, atime, mtime); return 0; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } -function __dlinit(main_dso_handle) {} +var nowIsMonotonic = true; -var dlopenMissingError = "To use dlopen, you need enable dynamic linking, see https://github.com/emscripten-core/emscripten/wiki/Linking"; +function __emscripten_get_now_is_monotonic() { + return nowIsMonotonic; +} -function __dlopen_js(filename, flag) { - abort(dlopenMissingError); +function maybeExit() { + if (runtimeExited) { + return; + } + if (!keepRuntimeAlive()) { + try { + if (ENVIRONMENT_IS_PTHREAD) __emscripten_thread_exit(EXITSTATUS); else _exit(EXITSTATUS); + } catch (e) { + handleException(e); + } + } } -function __dlsym_js(handle, symbol) { - abort(dlopenMissingError); +function callUserCallback(func) { + if (runtimeExited || ABORT) { + err("user callback triggered after runtime exited or application aborted. Ignoring."); + return; + } + try { + func(); + maybeExit(); + } catch (e) { + handleException(e); + } } -var nowIsMonotonic = true; +function __emscripten_thread_mailbox_await(pthread_ptr) { + if (typeof Atomics.waitAsync === "function") { + var wait = Atomics.waitAsync(GROWABLE_HEAP_I32(), pthread_ptr >> 2, pthread_ptr); + assert(wait.async); + wait.value.then(checkMailbox); + var waitingAsync = pthread_ptr + 128; + Atomics.store(GROWABLE_HEAP_I32(), waitingAsync >> 2, 1); + } +} -function __emscripten_get_now_is_monotonic() { - return nowIsMonotonic; +Module["__emscripten_thread_mailbox_await"] = __emscripten_thread_mailbox_await; + +function checkMailbox() { + var pthread_ptr = _pthread_self(); + if (pthread_ptr) { + __emscripten_thread_mailbox_await(pthread_ptr); + callUserCallback(() => __emscripten_check_mailbox()); + } +} + +Module["checkMailbox"] = checkMailbox; + +function __emscripten_notify_mailbox_postmessage(targetThreadId, currThreadId, mainThreadId) { + if (targetThreadId == currThreadId) { + setTimeout(() => checkMailbox()); + } else if (ENVIRONMENT_IS_PTHREAD) { + postMessage({ + "targetThread": targetThreadId, + "cmd": "checkMailbox" + }); + } else { + var worker = PThread.pthreads[targetThreadId]; + if (!worker) { + err("Cannot send message to thread with ID " + targetThreadId + ", unknown thread ID!"); + return; + } + worker.postMessage({ + "cmd": "checkMailbox" + }); + } +} + +function __emscripten_set_offscreencanvas_size(target, width, height) { + err("emscripten_set_offscreencanvas_size: Build with -sOFFSCREENCANVAS_SUPPORT=1 to enable transferring canvases to pthreads."); + return -1; } function __emscripten_throw_longjmp() { @@ -4721,78 +5876,96 @@ function __emscripten_throw_longjmp() { function __gmtime_js(time, tmPtr) { var date = new Date(readI53FromI64(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(); + GROWABLE_HEAP_I32()[tmPtr >> 2] = date.getUTCSeconds(); + GROWABLE_HEAP_I32()[tmPtr + 4 >> 2] = date.getUTCMinutes(); + GROWABLE_HEAP_I32()[tmPtr + 8 >> 2] = date.getUTCHours(); + GROWABLE_HEAP_I32()[tmPtr + 12 >> 2] = date.getUTCDate(); + GROWABLE_HEAP_I32()[tmPtr + 16 >> 2] = date.getUTCMonth(); + GROWABLE_HEAP_I32()[tmPtr + 20 >> 2] = date.getUTCFullYear() - 1900; + GROWABLE_HEAP_I32()[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; + GROWABLE_HEAP_I32()[tmPtr + 28 >> 2] = yday; +} + +function __isLeapYear(year) { + return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0); +} + +var __MONTH_DAYS_LEAP_CUMULATIVE = [ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 ]; + +var __MONTH_DAYS_REGULAR_CUMULATIVE = [ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 ]; + +function __yday_from_date(date) { + var isLeapYear = __isLeapYear(date.getFullYear()); + var monthDaysCumulative = isLeapYear ? __MONTH_DAYS_LEAP_CUMULATIVE : __MONTH_DAYS_REGULAR_CUMULATIVE; + var yday = monthDaysCumulative[date.getMonth()] + date.getDate() - 1; + return yday; } function __localtime_js(time, tmPtr) { var date = new Date(readI53FromI64(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(); + GROWABLE_HEAP_I32()[tmPtr >> 2] = date.getSeconds(); + GROWABLE_HEAP_I32()[tmPtr + 4 >> 2] = date.getMinutes(); + GROWABLE_HEAP_I32()[tmPtr + 8 >> 2] = date.getHours(); + GROWABLE_HEAP_I32()[tmPtr + 12 >> 2] = date.getDate(); + GROWABLE_HEAP_I32()[tmPtr + 16 >> 2] = date.getMonth(); + GROWABLE_HEAP_I32()[tmPtr + 20 >> 2] = date.getFullYear() - 1900; + GROWABLE_HEAP_I32()[tmPtr + 24 >> 2] = date.getDay(); + var yday = __yday_from_date(date) | 0; + GROWABLE_HEAP_I32()[tmPtr + 28 >> 2] = yday; + GROWABLE_HEAP_I32()[tmPtr + 36 >> 2] = -(date.getTimezoneOffset() * 60); var start = new Date(date.getFullYear(), 0, 1); - var yday = (date.getTime() - start.getTime()) / (1e3 * 60 * 60 * 24) | 0; - HEAP32[tmPtr + 28 >> 2] = yday; - HEAP32[tmPtr + 36 >> 2] = -(date.getTimezoneOffset() * 60); 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; + GROWABLE_HEAP_I32()[tmPtr + 32 >> 2] = dst; } function __mktime_js(tmPtr) { - 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 date = new Date(GROWABLE_HEAP_I32()[tmPtr + 20 >> 2] + 1900, GROWABLE_HEAP_I32()[tmPtr + 16 >> 2], GROWABLE_HEAP_I32()[tmPtr + 12 >> 2], GROWABLE_HEAP_I32()[tmPtr + 8 >> 2], GROWABLE_HEAP_I32()[tmPtr + 4 >> 2], GROWABLE_HEAP_I32()[tmPtr >> 2], 0); + var dst = GROWABLE_HEAP_I32()[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); + GROWABLE_HEAP_I32()[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 = (date.getTime() - start.getTime()) / (1e3 * 60 * 60 * 24) | 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(); + GROWABLE_HEAP_I32()[tmPtr + 24 >> 2] = date.getDay(); + var yday = __yday_from_date(date) | 0; + GROWABLE_HEAP_I32()[tmPtr + 28 >> 2] = yday; + GROWABLE_HEAP_I32()[tmPtr >> 2] = date.getSeconds(); + GROWABLE_HEAP_I32()[tmPtr + 4 >> 2] = date.getMinutes(); + GROWABLE_HEAP_I32()[tmPtr + 8 >> 2] = date.getHours(); + GROWABLE_HEAP_I32()[tmPtr + 12 >> 2] = date.getDate(); + GROWABLE_HEAP_I32()[tmPtr + 16 >> 2] = date.getMonth(); + GROWABLE_HEAP_I32()[tmPtr + 20 >> 2] = date.getYear(); return date.getTime() / 1e3 | 0; } -function __mmap_js(len, prot, flags, fd, off, allocated) { +function __mmap_js(len, prot, flags, fd, off, allocated, addr) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(40, 1, len, prot, flags, fd, off, allocated, addr); try { var stream = SYSCALLS.getStreamFromFD(fd); var res = FS.mmap(stream, len, off, prot, flags); var ptr = res.ptr; - HEAP32[allocated >> 2] = res.allocated; - return ptr; + GROWABLE_HEAP_I32()[allocated >> 2] = res.allocated; + GROWABLE_HEAP_U32()[addr >> 2] = ptr; + return 0; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } function __munmap_js(addr, len, prot, flags, fd, offset) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(41, 1, addr, len, prot, flags, fd, offset); try { var stream = SYSCALLS.getStreamFromFD(fd); if (prot & 2) { @@ -4800,27 +5973,57 @@ function __munmap_js(addr, len, prot, flags, fd, offset) { } FS.munmap(stream); } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return -e.errno; } } +var timers = {}; + +var _emscripten_get_now; + +if (ENVIRONMENT_IS_NODE) { + _emscripten_get_now = () => { + var t = process.hrtime(); + return t[0] * 1e3 + t[1] / 1e6; + }; +} else _emscripten_get_now = () => performance.timeOrigin + performance.now(); + +function __setitimer_js(which, timeout_ms) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(42, 1, which, timeout_ms); + if (timers[which]) { + clearTimeout(timers[which].id); + delete timers[which]; + } + if (!timeout_ms) return 0; + var id = setTimeout(() => { + assert(which in timers); + delete timers[which]; + callUserCallback(() => __emscripten_timeout(which, _emscripten_get_now())); + }, timeout_ms); + timers[which] = { + id: id, + timeout_ms: timeout_ms + }; + return 0; +} + function allocateUTF8(str) { var size = lengthBytesUTF8(str) + 1; var ret = _malloc(size); - if (ret) stringToUTF8Array(str, HEAP8, ret, size); + if (ret) stringToUTF8Array(str, GROWABLE_HEAP_I8(), ret, size); return ret; } -function _tzset_impl(timezone, daylight, tzname) { +function __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); - HEAP32[timezone >> 2] = stdTimezoneOffset * 60; - HEAP32[daylight >> 2] = Number(winterOffset != summerOffset); + GROWABLE_HEAP_U32()[timezone >> 2] = stdTimezoneOffset * 60; + GROWABLE_HEAP_I32()[daylight >> 2] = Number(winterOffset != summerOffset); function extractZone(date) { var match = date.toTimeString().match(/\(([A-Za-z ]+)\)$/); return match ? match[1] : "GMT"; @@ -4830,28 +6033,40 @@ function _tzset_impl(timezone, daylight, tzname) { var winterNamePtr = allocateUTF8(winterName); var summerNamePtr = allocateUTF8(summerName); if (summerOffset < winterOffset) { - HEAPU32[tzname >> 2] = winterNamePtr; - HEAPU32[tzname + 4 >> 2] = summerNamePtr; + GROWABLE_HEAP_U32()[tzname >> 2] = winterNamePtr; + GROWABLE_HEAP_U32()[tzname + 4 >> 2] = summerNamePtr; } else { - HEAPU32[tzname >> 2] = summerNamePtr; - HEAPU32[tzname + 4 >> 2] = winterNamePtr; + GROWABLE_HEAP_U32()[tzname >> 2] = summerNamePtr; + GROWABLE_HEAP_U32()[tzname + 4 >> 2] = winterNamePtr; } } -function __tzset_js(timezone, daylight, tzname) { - if (__tzset_js.called) return; - __tzset_js.called = true; - _tzset_impl(timezone, daylight, tzname); +function _abort() { + abort("native code called abort()"); } -function _abort() { - abort(""); +function _dlopen(handle) { + abort(dlopenMissingError); +} + +function _emscripten_console_error(str) { + assert(typeof str == "number"); + console.error(UTF8ToString(str)); } function _emscripten_date_now() { return Date.now(); } +function runtimeKeepalivePush() { + runtimeKeepaliveCounter += 1; +} + +function _emscripten_exit_with_live_runtime() { + runtimeKeepalivePush(); + throw "unwind"; +} + function getHeapMax() { return 2147483648; } @@ -4860,32 +6075,74 @@ function _emscripten_get_heap_max() { return getHeapMax(); } -var _emscripten_get_now; - -if (ENVIRONMENT_IS_NODE) { - _emscripten_get_now = () => { - var t = process["hrtime"](); - return t[0] * 1e3 + t[1] / 1e6; - }; -} else _emscripten_get_now = () => performance.now(); - function _emscripten_memcpy_big(dest, src, num) { - HEAPU8.copyWithin(dest, src, src + num); + GROWABLE_HEAP_U8().copyWithin(dest, src, src + num); +} + +function _emscripten_num_logical_cores() { + if (ENVIRONMENT_IS_NODE) return require("os").cpus().length; + return navigator["hardwareConcurrency"]; +} + +function withStackSave(f) { + var stack = stackSave(); + var ret = f(); + stackRestore(stack); + return ret; +} + +function _emscripten_proxy_to_main_thread_js(index, sync) { + var numCallArgs = arguments.length - 2; + var outerArgs = arguments; + var maxArgs = 19; + if (numCallArgs > maxArgs) { + throw "emscripten_proxy_to_main_thread_js: Too many arguments " + numCallArgs + " to proxied function idx=" + index + ", maximum supported is " + maxArgs; + } + return withStackSave(() => { + var serializedNumCallArgs = numCallArgs; + var args = stackAlloc(serializedNumCallArgs * 8); + var b = args >> 3; + for (var i = 0; i < numCallArgs; i++) { + var arg = outerArgs[2 + i]; + GROWABLE_HEAP_F64()[b + i] = arg; + } + return __emscripten_run_in_main_runtime_thread_js(index, serializedNumCallArgs, args, sync); + }); +} + +var _emscripten_receive_on_main_thread_js_callArgs = []; + +function _emscripten_receive_on_main_thread_js(index, numCallArgs, args) { + _emscripten_receive_on_main_thread_js_callArgs.length = numCallArgs; + var b = args >> 3; + for (var i = 0; i < numCallArgs; i++) { + _emscripten_receive_on_main_thread_js_callArgs[i] = GROWABLE_HEAP_F64()[b + i]; + } + var func = proxiedFunctionTable[index]; + assert(func.length == numCallArgs, "Call args mismatch in emscripten_receive_on_main_thread_js"); + return func.apply(null, _emscripten_receive_on_main_thread_js_callArgs); } function emscripten_realloc_buffer(size) { + var b = wasmMemory.buffer; try { - wasmMemory.grow(size - buffer.byteLength + 65535 >>> 16); - updateGlobalBufferAndViews(wasmMemory.buffer); + wasmMemory.grow(size - b.byteLength + 65535 >>> 16); + updateMemoryViews(); return 1; - } catch (e) {} + } catch (e) { + err("emscripten_realloc_buffer: Attempted to grow heap from " + b.byteLength + " bytes to " + size + " bytes, but got error: " + e); + } } function _emscripten_resize_heap(requestedSize) { - var oldSize = HEAPU8.length; + var oldSize = GROWABLE_HEAP_U8().length; requestedSize = requestedSize >>> 0; + if (requestedSize <= oldSize) { + return false; + } var maxHeapSize = getHeapMax(); if (requestedSize > maxHeapSize) { + err("Cannot enlarge memory, asked to go up to " + requestedSize + " bytes, but the limit is " + maxHeapSize + " bytes!"); return false; } let alignUp = (x, multiple) => x + (multiple - x % multiple) % multiple; @@ -4898,70 +6155,10 @@ function _emscripten_resize_heap(requestedSize) { return true; } } + err("Failed to grow the heap from " + oldSize + " bytes to " + newSize + " bytes, not enough memory!"); return false; } -function _proc_exit(code) { - EXITSTATUS = code; - if (!keepRuntimeAlive()) { - if (Module["onExit"]) Module["onExit"](code); - ABORT = true; - } - quit_(code, new ExitStatus(code)); -} - -function exitJS(status, implicit) { - EXITSTATUS = status; - if (!keepRuntimeAlive()) { - exitRuntime(); - } - _proc_exit(status); -} - -var _exit = exitJS; - -function maybeExit() { - if (!keepRuntimeAlive()) { - try { - _exit(EXITSTATUS); - } catch (e) { - handleException(e); - } - } -} - -function callUserCallback(func) { - if (runtimeExited || ABORT) { - return; - } - try { - func(); - maybeExit(); - } catch (e) { - handleException(e); - } -} - -function runtimeKeepalivePush() { - runtimeKeepaliveCounter += 1; -} - -function runtimeKeepalivePop() { - runtimeKeepaliveCounter -= 1; -} - -function safeSetTimeout(func, timeout) { - runtimeKeepalivePush(); - return setTimeout(function() { - runtimeKeepalivePop(); - callUserCallback(func); - }, timeout); -} - -function _emscripten_sleep(ms) { - return Asyncify.handleSleep(wakeUp => safeSetTimeout(wakeUp, ms)); -} - var ENV = PHPLoader.ENV || {}; function getExecutableName() { @@ -4994,16 +6191,18 @@ function getEnvStrings() { function writeAsciiToMemory(str, buffer, dontAddNull) { for (var i = 0; i < str.length; ++i) { - HEAP8[buffer++ >> 0] = str.charCodeAt(i); + assert(str.charCodeAt(i) === (str.charCodeAt(i) & 255)); + GROWABLE_HEAP_I8()[buffer++ >> 0] = str.charCodeAt(i); } - if (!dontAddNull) HEAP8[buffer >> 0] = 0; + if (!dontAddNull) GROWABLE_HEAP_I8()[buffer >> 0] = 0; } function _environ_get(__environ, environ_buf) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(43, 1, __environ, environ_buf); var bufSize = 0; getEnvStrings().forEach(function(string, i) { var ptr = environ_buf + bufSize; - HEAPU32[__environ + i * 4 >> 2] = ptr; + GROWABLE_HEAP_U32()[__environ + i * 4 >> 2] = ptr; writeAsciiToMemory(string, ptr); bufSize += string.length + 1; }); @@ -5011,35 +6210,38 @@ function _environ_get(__environ, environ_buf) { } function _environ_sizes_get(penviron_count, penviron_buf_size) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(44, 1, penviron_count, penviron_buf_size); var strings = getEnvStrings(); - HEAPU32[penviron_count >> 2] = strings.length; + GROWABLE_HEAP_U32()[penviron_count >> 2] = strings.length; var bufSize = 0; strings.forEach(function(string) { bufSize += string.length + 1; }); - HEAPU32[penviron_buf_size >> 2] = bufSize; + GROWABLE_HEAP_U32()[penviron_buf_size >> 2] = bufSize; return 0; } function _fd_close(fd) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(45, 1, fd); try { var stream = SYSCALLS.getStreamFromFD(fd); FS.close(stream); return 0; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return e.errno; } } function _fd_fdstat_get(fd, pbuf) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(46, 1, fd, pbuf); try { 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; + GROWABLE_HEAP_I8()[pbuf >> 0] = type; return 0; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return e.errno; } } @@ -5047,41 +6249,46 @@ function _fd_fdstat_get(fd, pbuf) { function 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]; + var ptr = GROWABLE_HEAP_U32()[iov >> 2]; + var len = GROWABLE_HEAP_U32()[iov + 4 >> 2]; iov += 8; - var curr = FS.read(stream, HEAP8, ptr, len, offset); + var curr = FS.read(stream, GROWABLE_HEAP_I8(), 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) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(47, 1, fd, iov, iovcnt, pnum); try { var stream = SYSCALLS.getStreamFromFD(fd); var num = doReadv(stream, iov, iovcnt); - HEAPU32[pnum >> 2] = num; + GROWABLE_HEAP_U32()[pnum >> 2] = num; return 0; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return e.errno; } } function _fd_seek(fd, offset_low, offset_high, whence, newOffset) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(48, 1, fd, offset_low, offset_high, whence, newOffset); try { var offset = convertI32PairToI53Checked(offset_low, offset_high); 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.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], - HEAP32[newOffset >> 2] = tempI64[0], HEAP32[newOffset + 4 >> 2] = tempI64[1]; + GROWABLE_HEAP_I32()[newOffset >> 2] = tempI64[0], GROWABLE_HEAP_I32()[newOffset + 4 >> 2] = tempI64[1]; if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null; return 0; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return e.errno; } } @@ -5089,36 +6296,43 @@ function _fd_seek(fd, offset_low, offset_high, whence, newOffset) { function 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]; + var ptr = GROWABLE_HEAP_U32()[iov >> 2]; + var len = GROWABLE_HEAP_U32()[iov + 4 >> 2]; iov += 8; - var curr = FS.write(stream, HEAP8, ptr, len, offset); + var curr = FS.write(stream, GROWABLE_HEAP_I8(), 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) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(49, 1, fd, iov, iovcnt, pnum); try { var stream = SYSCALLS.getStreamFromFD(fd); var num = doWritev(stream, iov, iovcnt); - HEAPU32[pnum >> 2] = num; + GROWABLE_HEAP_U32()[pnum >> 2] = num; return 0; } catch (e) { - if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e; + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return e.errno; } } function _getaddrinfo(node, service, hint, out) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(50, 1, node, service, hint, out); + 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; + var ai, last; function allocaddrinfo(family, type, proto, canon, addr, port) { var sa, salen, ai; var errno; @@ -5128,24 +6342,24 @@ function _getaddrinfo(node, service, hint, out) { 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; - HEAP32[ai + 24 >> 2] = canon; - HEAPU32[ai + 20 >> 2] = sa; + GROWABLE_HEAP_I32()[ai + 4 >> 2] = family; + GROWABLE_HEAP_I32()[ai + 8 >> 2] = type; + GROWABLE_HEAP_I32()[ai + 12 >> 2] = proto; + GROWABLE_HEAP_I32()[ai + 24 >> 2] = canon; + GROWABLE_HEAP_U32()[ai + 20 >> 2] = sa; if (family === 10) { - HEAP32[ai + 16 >> 2] = 28; + GROWABLE_HEAP_I32()[ai + 16 >> 2] = 28; } else { - HEAP32[ai + 16 >> 2] = 16; + GROWABLE_HEAP_I32()[ai + 16 >> 2] = 16; } - HEAP32[ai + 28 >> 2] = 0; + GROWABLE_HEAP_I32()[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]; + flags = GROWABLE_HEAP_I32()[hint >> 2]; + family = GROWABLE_HEAP_I32()[hint + 4 >> 2]; + type = GROWABLE_HEAP_I32()[hint + 8 >> 2]; + proto = GROWABLE_HEAP_I32()[hint + 12 >> 2]; } if (type && !proto) { proto = type === 2 ? 17 : 6; @@ -5165,7 +6379,7 @@ function _getaddrinfo(node, service, hint, out) { if (flags & ~(1 | 2 | 4 | 1024 | 8 | 16 | 32)) { return -1; } - if (hint !== 0 && HEAP32[hint >> 2] & 2 && !node) { + if (hint !== 0 && GROWABLE_HEAP_I32()[hint >> 2] & 2 && !node) { return -1; } if (flags & 32) { @@ -5199,7 +6413,7 @@ function _getaddrinfo(node, service, hint, out) { } } ai = allocaddrinfo(family, type, proto, null, addr, port); - HEAPU32[out >> 2] = ai; + GROWABLE_HEAP_U32()[out >> 2] = ai; return 0; } node = UTF8ToString(node); @@ -5225,7 +6439,7 @@ function _getaddrinfo(node, service, hint, out) { } if (addr != null) { ai = allocaddrinfo(family, type, proto, node, addr, port); - HEAPU32[out >> 2] = ai; + GROWABLE_HEAP_U32()[out >> 2] = ai; return 0; } if (flags & 4) { @@ -5239,7 +6453,7 @@ function _getaddrinfo(node, service, hint, out) { addr = [ 0, 0, _htonl(65535), addr ]; } ai = allocaddrinfo(family, type, proto, null, addr, port); - HEAPU32[out >> 2] = ai; + GROWABLE_HEAP_U32()[out >> 2] = ai; return 0; } @@ -5247,27 +6461,28 @@ function getHostByName(name) { var ret = _malloc(20); var nameBuf = _malloc(name.length + 1); stringToUTF8(name, nameBuf, name.length + 1); - HEAPU32[ret >> 2] = nameBuf; + GROWABLE_HEAP_U32()[ret >> 2] = nameBuf; var aliasesBuf = _malloc(4); - HEAPU32[aliasesBuf >> 2] = 0; - HEAPU32[ret + 4 >> 2] = aliasesBuf; + GROWABLE_HEAP_U32()[aliasesBuf >> 2] = 0; + GROWABLE_HEAP_U32()[ret + 4 >> 2] = aliasesBuf; var afinet = 2; - HEAP32[ret + 8 >> 2] = afinet; - HEAP32[ret + 12 >> 2] = 4; + GROWABLE_HEAP_I32()[ret + 8 >> 2] = afinet; + GROWABLE_HEAP_I32()[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; + GROWABLE_HEAP_U32()[addrListBuf >> 2] = addrListBuf + 8; + GROWABLE_HEAP_U32()[addrListBuf + 4 >> 2] = 0; + GROWABLE_HEAP_I32()[addrListBuf + 8 >> 2] = inetPton4(DNS.lookup_name(name)); + GROWABLE_HEAP_U32()[ret + 16 >> 2] = addrListBuf; return ret; } function _gethostbyaddr(addr, addrlen, type) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(51, 1, addr, addrlen, type); if (type !== 2) { setErrNo(5); return null; } - addr = HEAP32[addr >> 2]; + addr = GROWABLE_HEAP_I32()[addr >> 2]; var host = inetNtop4(addr); var lookup = DNS.lookup_addr(host); if (lookup) { @@ -5277,15 +6492,17 @@ function _gethostbyaddr(addr, addrlen, type) { } function _gethostbyname(name) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(53, 1, name); return getHostByName(UTF8ToString(name)); } function _gethostbyname_r(name, ret, buf, buflen, out, err) { + if (ENVIRONMENT_IS_PTHREAD) return _emscripten_proxy_to_main_thread_js(52, 1, name, ret, buf, buflen, out, err); var data = _gethostbyname(name); _memcpy(ret, data, 20); _free(data); - HEAP32[err >> 2] = 0; - HEAPU32[out >> 2] = ret; + GROWABLE_HEAP_I32()[err >> 2] = 0; + GROWABLE_HEAP_U32()[out >> 2] = ret; return 0; } @@ -5293,7 +6510,7 @@ function _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; + GROWABLE_HEAP_F64()[loadavg + i * doubleSize >> 3] = .1; } return limit; } @@ -5333,61 +6550,10 @@ function _getnameinfo(sa, salen, node, nodelen, serv, servlen, flags) { return 0; } -var Protocols = { - list: [], - map: {} -}; - -function _setprotoent(stayopen) { - function allocprotoent(name, proto, aliases) { - var nameBuf = _malloc(name.length + 1); - writeAsciiToMemory(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); - writeAsciiToMemory(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; -} - -function _getprotobyname(name) { - name = UTF8ToString(name); - _setprotoent(true); - var result = Protocols.map[name]; - return result; -} - -function _getprotobynumber(number) { - _setprotoent(true); - var result = Protocols.map[number]; - return result; -} - function allocateUTF8OnStack(str) { var size = lengthBytesUTF8(str) + 1; var ret = stackAlloc(size); - stringToUTF8Array(str, HEAP8, ret, size); + stringToUTF8Array(str, GROWABLE_HEAP_I8(), ret, size); return ret; } @@ -5482,7 +6648,7 @@ function _js_popen_to_file(command, mode, exitCodePtr) { if (!modestr.length) return 0; if (Module["popen_to_file"]) { const {path: path, exitCode: exitCode} = Module["popen_to_file"](cmdstr, modestr); - HEAPU8[exitCodePtr] = exitCode; + GROWABLE_HEAP_U8()[exitCodePtr] = exitCode; return allocateUTF8OnStack(path); } if (ENVIRONMENT_IS_NODE) { @@ -5496,7 +6662,7 @@ function _js_popen_to_file(command, mode, exitCodePtr) { shell: true, stdio: [ "inherit", "pipe", "inherit" ] }); - HEAPU8[exitCodePtr] = ret.status; + GROWABLE_HEAP_U8()[exitCodePtr] = ret.status; require("fs").writeFileSync(pipeFilePath, ret.stdout, { encoding: "utf8", flag: "w+" @@ -5514,10 +6680,6 @@ function _js_popen_to_file(command, mode, exitCodePtr) { return _W_EXITCODE(0, 2); } -function __isLeapYear(year) { - return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0); -} - function __arraySum(array, index) { var sum = 0; for (var i = 0; i <= index; sum += array[i++]) {} @@ -5551,19 +6713,24 @@ function __addDays(date, days) { return newDate; } +function writeArrayToMemory(array, buffer) { + assert(array.length >= 0, "writeArrayToMemory array must have a length (should be an array or typed array)"); + GROWABLE_HEAP_I8().set(array, buffer); +} + function _strftime(s, maxsize, format, tm) { - var tm_zone = HEAP32[tm + 40 >> 2]; + var tm_zone = GROWABLE_HEAP_I32()[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_sec: GROWABLE_HEAP_I32()[tm >> 2], + tm_min: GROWABLE_HEAP_I32()[tm + 4 >> 2], + tm_hour: GROWABLE_HEAP_I32()[tm + 8 >> 2], + tm_mday: GROWABLE_HEAP_I32()[tm + 12 >> 2], + tm_mon: GROWABLE_HEAP_I32()[tm + 16 >> 2], + tm_year: GROWABLE_HEAP_I32()[tm + 20 >> 2], + tm_wday: GROWABLE_HEAP_I32()[tm + 24 >> 2], + tm_yday: GROWABLE_HEAP_I32()[tm + 28 >> 2], + tm_isdst: GROWABLE_HEAP_I32()[tm + 32 >> 2], + tm_gmtoff: GROWABLE_HEAP_I32()[tm + 36 >> 2], tm_zone: tm_zone ? UTF8ToString(tm_zone) : "" }; var pattern = UTF8ToString(format); @@ -5879,12 +7046,12 @@ function _strptime(buf, format, tm) { 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) + year: fixup(GROWABLE_HEAP_I32()[tm + 20 >> 2] + 1900, 1970, 9999), + month: fixup(GROWABLE_HEAP_I32()[tm + 16 >> 2], 0, 11), + day: fixup(GROWABLE_HEAP_I32()[tm + 12 >> 2], 1, 31), + hour: fixup(GROWABLE_HEAP_I32()[tm + 8 >> 2], 0, 23), + min: fixup(GROWABLE_HEAP_I32()[tm + 4 >> 2], 0, 59), + sec: fixup(GROWABLE_HEAP_I32()[tm >> 2], 0, 59) }; } if (matches) { @@ -5968,24 +7135,20 @@ function _strptime(buf, format, tm) { } } 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; + GROWABLE_HEAP_I32()[tm >> 2] = fullDate.getSeconds(); + GROWABLE_HEAP_I32()[tm + 4 >> 2] = fullDate.getMinutes(); + GROWABLE_HEAP_I32()[tm + 8 >> 2] = fullDate.getHours(); + GROWABLE_HEAP_I32()[tm + 12 >> 2] = fullDate.getDate(); + GROWABLE_HEAP_I32()[tm + 16 >> 2] = fullDate.getMonth(); + GROWABLE_HEAP_I32()[tm + 20 >> 2] = fullDate.getFullYear() - 1900; + GROWABLE_HEAP_I32()[tm + 24 >> 2] = fullDate.getDay(); + GROWABLE_HEAP_I32()[tm + 28 >> 2] = __arraySum(__isLeapYear(fullDate.getFullYear()) ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR, fullDate.getMonth() - 1) + fullDate.getDate() - 1; + GROWABLE_HEAP_I32()[tm + 32 >> 2] = 0; return buf + intArrayFromString(matches[0]).length - 1; } return 0; } -function _wasm_close(socketd) { - return PHPWASM.shutdownSocket(socketd, 2); -} - function _wasm_poll_socket(socketd, events, timeout) { if (typeof Asyncify === "undefined") { return 0; @@ -6069,7 +7232,7 @@ function _wasm_poll_socket(socketd, events, timeout) { } function _wasm_setsockopt(socketd, level, optionName, optionValuePtr, optionLen) { - const optionValue = HEAPU8[optionValuePtr]; + const optionValue = GROWABLE_HEAP_U8()[optionValuePtr]; const SOL_SOCKET = 1; const SO_KEEPALIVE = 9; const IPPROTO_TCP = 6; @@ -6087,191 +7250,21 @@ function _wasm_setsockopt(socketd, level, optionName, optionValuePtr, optionLen) return 0; } -function _wasm_shutdown(socketd, how) { - return PHPWASM.shutdownSocket(socketd, how); -} +var wasmTableMirror = []; -function runAndAbortIfError(func) { - try { - return func(); - } catch (e) { - abort(e); - } -} - -var Asyncify = { - 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; - }, - instrumentWasmImports: function(imports) { - var ASYNCIFY_IMPORTS = [ "env._dlopen_js", "env.invoke_i", "env.invoke_ii", "env.invoke_iii", "env.invoke_iiii", "env.invoke_iiiii", "env.invoke_iiiiii", "env.invoke_iiiiiii", "env.invoke_iiiiiiii", "env.invoke_iiiiiiiiii", "env.invoke_v", "env.invoke_vi", "env.invoke_vii", "env.invoke_viidii", "env.invoke_viii", "env.invoke_viiii", "env.invoke_viiiii", "env.invoke_viiiiii", "env.invoke_viiiiiii", "env.invoke_viiiiiiiii", "env.wasm_poll_socket", "env.wasm_shutdown", "env.emscripten_sleep", "env.emscripten_wget", "env.emscripten_wget_data", "env.emscripten_idb_load", "env.emscripten_idb_store", "env.emscripten_idb_delete", "env.emscripten_idb_exists", "env.emscripten_idb_load_blob", "env.emscripten_idb_store_blob", "env.SDL_Delay", "env.emscripten_scan_registers", "env.emscripten_lazy_load_code", "env.emscripten_fiber_swap", "wasi_snapshot_preview1.fd_sync", "env.__wasi_fd_sync", "env._emval_await", "env._dlopen_js", "env.__asyncjs__*" ].map(x => x.split(".")[1]); - for (var x in imports) { - (function(x) { - var original = imports[x]; - var sig = original.sig; - if (typeof original == "function") { - var isAsyncifyImport = ASYNCIFY_IMPORTS.indexOf(x) >= 0 || x.startsWith("__asyncjs__"); - } - })(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; - }, - 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 => { - if (ABORT) return; - Asyncify.handleSleepReturnValue = handleSleepReturnValue || 0; - 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 getWasmTableEntry(funcPtr) { + var func = wasmTableMirror[funcPtr]; + if (!func) { + if (funcPtr >= wasmTableMirror.length) wasmTableMirror.length = funcPtr + 1; + wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr); } -}; + assert(wasmTable.get(funcPtr) == func, "JavaScript-side Wasm function table mirror is out of date!"); + return func; +} function getCFunc(ident) { var func = Module["_" + ident]; + assert(func, "Cannot call unknown function " + ident + ", make sure it is exported"); return func; } @@ -6302,6 +7295,7 @@ function ccall(ident, returnType, argTypes, args, opts) { var func = getCFunc(ident); var cArgs = []; var stack = 0; + assert(returnType !== "array", 'Return type should not be "array".'); if (args) { for (var i = 0; i < args.length; i++) { var converter = toC[argTypes[i]]; @@ -6313,23 +7307,17 @@ function ccall(ident, returnType, argTypes, args, opts) { } } } - var previousAsync = Asyncify.currData; var ret = func.apply(null, cArgs); function onDone(ret) { - runtimeKeepalivePop(); if (stack !== 0) stackRestore(stack); return convertReturnValue(ret); } - runtimeKeepalivePush(); - var asyncMode = opts && opts.async; - if (Asyncify.currData != previousAsync) { - return Asyncify.whenDone().then(onDone); - } ret = onDone(ret); - if (asyncMode) return Promise.resolve(ret); return ret; } +PThread.init(); + var FSNode = function(parent, name, mode, rdev) { if (!parent) { parent = this; @@ -6395,7 +7383,6 @@ Module["FS_createLazyFile"] = FS.createLazyFile; Module["FS_createDevice"] = FS.createDevice; if (ENVIRONMENT_IS_NODE) { - requireNodeFS(); NODEFS.staticInit(); } @@ -6523,368 +7510,346 @@ ERRNO_CODES = { "ESTRPIPE": 135 }; -var asmLibraryArg = { - "j": ___assert_fail, - "Va": ___call_sighandler, - "Ua": ___syscall__newselect, - "Ta": ___syscall_accept4, - "Sa": ___syscall_bind, - "Ra": ___syscall_chdir, - "P": ___syscall_chmod, - "Qa": ___syscall_connect, - "Pa": ___syscall_dup, - "Oa": ___syscall_dup3, - "Na": ___syscall_faccessat, - "U": ___syscall_fallocate, - "Ma": ___syscall_fchmod, - "La": ___syscall_fchown32, - "O": ___syscall_fchownat, - "o": ___syscall_fcntl64, - "Ka": ___syscall_fdatasync, - "Ja": ___syscall_fstat64, - "T": ___syscall_ftruncate64, - "Ia": ___syscall_getcwd, - "Ha": ___syscall_getdents64, - "Ga": ___syscall_getpeername, - "Fa": ___syscall_getsockname, - "Ea": ___syscall_getsockopt, - "N": ___syscall_ioctl, - "Da": ___syscall_listen, - "Ca": ___syscall_lstat64, - "Ba": ___syscall_mkdirat, - "Aa": ___syscall_newfstatat, - "w": ___syscall_openat, - "za": ___syscall_pipe, - "ya": ___syscall_poll, - "xa": ___syscall_readlinkat, - "wa": ___syscall_recvfrom, - "va": ___syscall_renameat, - "M": ___syscall_rmdir, - "ua": ___syscall_sendto, - "L": ___syscall_socket, - "ta": ___syscall_stat64, - "sa": ___syscall_statfs64, - "ra": ___syscall_symlink, - "D": ___syscall_unlinkat, - "qa": ___syscall_utimensat, - "ma": __dlinit, - "la": __dlopen_js, - "ka": __dlsym_js, - "ja": __emscripten_get_now_is_monotonic, - "ia": __emscripten_throw_longjmp, - "ha": __gmtime_js, - "ga": __localtime_js, - "fa": __mktime_js, - "ea": __mmap_js, - "da": __munmap_js, - "ca": __tzset_js, - "m": _abort, - "B": _emscripten_date_now, - "ba": _emscripten_get_heap_max, - "A": _emscripten_get_now, - "aa": _emscripten_memcpy_big, - "$": _emscripten_resize_heap, - "_": _emscripten_sleep, - "pa": _environ_get, - "oa": _environ_sizes_get, - "p": _exit, - "r": _fd_close, - "K": _fd_fdstat_get, - "J": _fd_read, - "S": _fd_seek, - "C": _fd_write, - "Z": _getaddrinfo, - "I": _gethostbyaddr, - "H": _gethostbyname_r, - "Y": _getloadavg, - "G": _getnameinfo, - "X": _getprotobyname, - "W": _getprotobynumber, - "h": invoke_i, - "d": invoke_ii, - "b": invoke_iii, - "f": invoke_iiii, - "g": invoke_iiiii, - "u": invoke_iiiiii, - "t": invoke_iiiiiii, - "v": invoke_iiiiiiii, - "F": invoke_iiiiiiiiii, - "e": invoke_v, - "a": invoke_vi, - "c": invoke_vii, - "z": invoke_viidii, - "l": invoke_viii, - "k": invoke_viiii, - "n": invoke_viiiii, - "i": invoke_viiiiii, - "y": invoke_viiiiiiiii, - "V": _js_popen_to_file, - "na": _proc_exit, - "E": _strftime, - "R": _strptime, - "s": _wasm_close, - "x": _wasm_poll_socket, - "q": _wasm_setsockopt, - "Q": _wasm_shutdown +var proxiedFunctionTable = [ null, _proc_exit, exitOnMainThread, ___syscall__newselect, ___syscall_accept4, ___syscall_bind, ___syscall_chdir, ___syscall_chmod, ___syscall_connect, ___syscall_dup, ___syscall_dup3, ___syscall_faccessat, ___syscall_fchownat, ___syscall_fcntl64, ___syscall_fstat64, ___syscall_ftruncate64, ___syscall_getcwd, ___syscall_getdents64, ___syscall_getpeername, ___syscall_getsockname, ___syscall_getsockopt, ___syscall_ioctl, ___syscall_listen, ___syscall_lstat64, ___syscall_mkdirat, ___syscall_newfstatat, ___syscall_openat, ___syscall_pipe, ___syscall_poll, ___syscall_readlinkat, ___syscall_recvfrom, ___syscall_renameat, ___syscall_rmdir, ___syscall_sendto, ___syscall_socket, ___syscall_stat64, ___syscall_statfs64, ___syscall_symlink, ___syscall_unlinkat, ___syscall_utimensat, __mmap_js, __munmap_js, __setitimer_js, _environ_get, _environ_sizes_get, _fd_close, _fd_fdstat_get, _fd_read, _fd_seek, _fd_write, _getaddrinfo, _gethostbyaddr, _gethostbyname_r, _gethostbyname ]; + +var decodeBase64 = typeof atob == "function" ? atob : function(input) { + var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + var output = ""; + var chr1, chr2, chr3; + var enc1, enc2, enc3, enc4; + var i = 0; + input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); + do { + enc1 = keyStr.indexOf(input.charAt(i++)); + enc2 = keyStr.indexOf(input.charAt(i++)); + enc3 = keyStr.indexOf(input.charAt(i++)); + enc4 = keyStr.indexOf(input.charAt(i++)); + chr1 = enc1 << 2 | enc2 >> 4; + chr2 = (enc2 & 15) << 4 | enc3 >> 2; + chr3 = (enc3 & 3) << 6 | enc4; + output = output + String.fromCharCode(chr1); + if (enc3 !== 64) { + output = output + String.fromCharCode(chr2); + } + if (enc4 !== 64) { + output = output + String.fromCharCode(chr3); + } + } while (i < input.length); + return output; }; -var asm = createWasm(); +function intArrayFromBase64(s) { + if (typeof ENVIRONMENT_IS_NODE == "boolean" && ENVIRONMENT_IS_NODE) { + var buf = Buffer.from(s, "base64"); + return new Uint8Array(buf["buffer"], buf["byteOffset"], buf["byteLength"]); + } + try { + var decoded = decodeBase64(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."); + } +} -var ___wasm_call_ctors = Module["___wasm_call_ctors"] = function() { - return (___wasm_call_ctors = Module["___wasm_call_ctors"] = Module["asm"]["Xa"]).apply(null, arguments); +function tryParseAsDataURI(filename) { + if (!isDataURI(filename)) { + return; + } + return intArrayFromBase64(filename.slice(dataURIPrefix.length)); +} + +function checkIncomingModuleAPI() { + ignoredModuleProp("fetchSettings"); +} + +var wasmImports = { + "__assert_fail": ___assert_fail, + "__call_sighandler": ___call_sighandler, + "__dlsym": ___dlsym, + "__emscripten_init_main_thread_js": ___emscripten_init_main_thread_js, + "__emscripten_thread_cleanup": ___emscripten_thread_cleanup, + "__handle_stack_overflow": ___handle_stack_overflow, + "__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_fchownat": ___syscall_fchownat, + "__syscall_fcntl64": ___syscall_fcntl64, + "__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_notify_mailbox_postmessage": __emscripten_notify_mailbox_postmessage, + "_emscripten_set_offscreencanvas_size": __emscripten_set_offscreencanvas_size, + "_emscripten_thread_mailbox_await": __emscripten_thread_mailbox_await, + "_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, + "dlopen": _dlopen, + "emscripten_console_error": _emscripten_console_error, + "emscripten_date_now": _emscripten_date_now, + "emscripten_exit_with_live_runtime": _emscripten_exit_with_live_runtime, + "emscripten_get_heap_max": _emscripten_get_heap_max, + "emscripten_get_now": _emscripten_get_now, + "emscripten_memcpy_big": _emscripten_memcpy_big, + "emscripten_num_logical_cores": _emscripten_num_logical_cores, + "emscripten_receive_on_main_thread_js": _emscripten_receive_on_main_thread_js, + "emscripten_resize_heap": _emscripten_resize_heap, + "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_write": _fd_write, + "getaddrinfo": _getaddrinfo, + "gethostbyaddr": _gethostbyaddr, + "gethostbyname_r": _gethostbyname_r, + "getloadavg": _getloadavg, + "getnameinfo": _getnameinfo, + "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_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, + "js_popen_to_file": _js_popen_to_file, + "memory": wasmMemory, + "proc_exit": _proc_exit, + "strftime": _strftime, + "strptime": _strptime, + "wasm_poll_socket": _wasm_poll_socket, + "wasm_setsockopt": _wasm_setsockopt }; -var _wasm_popen = Module["_wasm_popen"] = function() { - return (_wasm_popen = Module["_wasm_popen"] = Module["asm"]["Ya"]).apply(null, arguments); -}; +var asm = createWasm(); -var ___errno_location = Module["___errno_location"] = function() { - return (___errno_location = Module["___errno_location"] = Module["asm"]["Za"]).apply(null, arguments); -}; +var ___wasm_call_ctors = createExportWrapper("__wasm_call_ctors"); -var _wasm_pclose = Module["_wasm_pclose"] = function() { - return (_wasm_pclose = Module["_wasm_pclose"] = Module["asm"]["_a"]).apply(null, arguments); -}; +var _wasm_popen = Module["_wasm_popen"] = createExportWrapper("wasm_popen"); -var _php_pollfd_for = Module["_php_pollfd_for"] = function() { - return (_php_pollfd_for = Module["_php_pollfd_for"] = Module["asm"]["$a"]).apply(null, arguments); -}; +var ___errno_location = createExportWrapper("__errno_location"); -var _wasm_select = Module["_wasm_select"] = function() { - return (_wasm_select = Module["_wasm_select"] = Module["asm"]["ab"]).apply(null, arguments); -}; +var _wasm_pclose = Module["_wasm_pclose"] = createExportWrapper("wasm_pclose"); -var _wasm_add_cli_arg = Module["_wasm_add_cli_arg"] = function() { - return (_wasm_add_cli_arg = Module["_wasm_add_cli_arg"] = Module["asm"]["bb"]).apply(null, arguments); -}; +var _php_pollfd_for = Module["_php_pollfd_for"] = createExportWrapper("php_pollfd_for"); -var _malloc = Module["_malloc"] = function() { - return (_malloc = Module["_malloc"] = Module["asm"]["cb"]).apply(null, arguments); -}; +var _run_php = Module["_run_php"] = createExportWrapper("run_php"); -var _run_cli = Module["_run_cli"] = function() { - return (_run_cli = Module["_run_cli"] = Module["asm"]["db"]).apply(null, arguments); -}; +var _malloc = createExportWrapper("malloc"); -var _memcpy = Module["_memcpy"] = function() { - return (_memcpy = Module["_memcpy"] = Module["asm"]["eb"]).apply(null, arguments); -}; +var _free = createExportWrapper("free"); -var _free = Module["_free"] = function() { - return (_free = Module["_free"] = Module["asm"]["fb"]).apply(null, arguments); +var _pthread_self = Module["_pthread_self"] = function() { + return (_pthread_self = Module["_pthread_self"] = Module["asm"]["pthread_self"]).apply(null, arguments); }; -var _fflush = Module["_fflush"] = function() { - return (_fflush = Module["_fflush"] = Module["asm"]["hb"]).apply(null, arguments); -}; +var _saveSetjmp = createExportWrapper("saveSetjmp"); -var _htons = Module["_htons"] = function() { - return (_htons = Module["_htons"] = Module["asm"]["ib"]).apply(null, arguments); -}; +var _fflush = Module["_fflush"] = createExportWrapper("fflush"); -var _ntohs = Module["_ntohs"] = function() { - return (_ntohs = Module["_ntohs"] = Module["asm"]["jb"]).apply(null, arguments); -}; +var _htons = createExportWrapper("htons"); -var _htonl = Module["_htonl"] = function() { - return (_htonl = Module["_htonl"] = Module["asm"]["kb"]).apply(null, arguments); -}; +var _ntohs = createExportWrapper("ntohs"); -var _wasm_set_phpini_path = Module["_wasm_set_phpini_path"] = function() { - return (_wasm_set_phpini_path = Module["_wasm_set_phpini_path"] = Module["asm"]["lb"]).apply(null, arguments); -}; +var _htonl = createExportWrapper("htonl"); -var _wasm_set_phpini_entries = Module["_wasm_set_phpini_entries"] = function() { - return (_wasm_set_phpini_entries = Module["_wasm_set_phpini_entries"] = Module["asm"]["mb"]).apply(null, arguments); -}; +var _wasm_set_phpini_path = Module["_wasm_set_phpini_path"] = createExportWrapper("wasm_set_phpini_path"); -var _wasm_add_SERVER_entry = Module["_wasm_add_SERVER_entry"] = function() { - return (_wasm_add_SERVER_entry = Module["_wasm_add_SERVER_entry"] = Module["asm"]["nb"]).apply(null, arguments); -}; +var _wasm_set_phpini_entries = Module["_wasm_set_phpini_entries"] = createExportWrapper("wasm_set_phpini_entries"); -var _wasm_add_uploaded_file = Module["_wasm_add_uploaded_file"] = function() { - return (_wasm_add_uploaded_file = Module["_wasm_add_uploaded_file"] = Module["asm"]["ob"]).apply(null, arguments); -}; +var _wasm_add_SERVER_entry = Module["_wasm_add_SERVER_entry"] = createExportWrapper("wasm_add_SERVER_entry"); -var _wasm_set_query_string = Module["_wasm_set_query_string"] = function() { - return (_wasm_set_query_string = Module["_wasm_set_query_string"] = Module["asm"]["pb"]).apply(null, arguments); -}; +var _wasm_add_uploaded_file = Module["_wasm_add_uploaded_file"] = createExportWrapper("wasm_add_uploaded_file"); -var _wasm_set_path_translated = Module["_wasm_set_path_translated"] = function() { - return (_wasm_set_path_translated = Module["_wasm_set_path_translated"] = Module["asm"]["qb"]).apply(null, arguments); -}; +var _wasm_set_query_string = Module["_wasm_set_query_string"] = createExportWrapper("wasm_set_query_string"); -var _wasm_set_skip_shebang = Module["_wasm_set_skip_shebang"] = function() { - return (_wasm_set_skip_shebang = Module["_wasm_set_skip_shebang"] = Module["asm"]["rb"]).apply(null, arguments); -}; +var _wasm_set_path_translated = Module["_wasm_set_path_translated"] = createExportWrapper("wasm_set_path_translated"); -var _wasm_set_request_uri = Module["_wasm_set_request_uri"] = function() { - return (_wasm_set_request_uri = Module["_wasm_set_request_uri"] = Module["asm"]["sb"]).apply(null, arguments); -}; +var _wasm_set_skip_shebang = Module["_wasm_set_skip_shebang"] = createExportWrapper("wasm_set_skip_shebang"); -var _wasm_set_request_method = Module["_wasm_set_request_method"] = function() { - return (_wasm_set_request_method = Module["_wasm_set_request_method"] = Module["asm"]["tb"]).apply(null, arguments); -}; +var _wasm_set_request_uri = Module["_wasm_set_request_uri"] = createExportWrapper("wasm_set_request_uri"); -var _wasm_set_request_host = Module["_wasm_set_request_host"] = function() { - return (_wasm_set_request_host = Module["_wasm_set_request_host"] = Module["asm"]["ub"]).apply(null, arguments); -}; +var _wasm_set_request_method = Module["_wasm_set_request_method"] = createExportWrapper("wasm_set_request_method"); -var _wasm_set_content_type = Module["_wasm_set_content_type"] = function() { - return (_wasm_set_content_type = Module["_wasm_set_content_type"] = Module["asm"]["vb"]).apply(null, arguments); -}; +var _wasm_set_request_host = Module["_wasm_set_request_host"] = createExportWrapper("wasm_set_request_host"); -var _wasm_set_request_body = Module["_wasm_set_request_body"] = function() { - return (_wasm_set_request_body = Module["_wasm_set_request_body"] = Module["asm"]["wb"]).apply(null, arguments); -}; +var _wasm_set_content_type = Module["_wasm_set_content_type"] = createExportWrapper("wasm_set_content_type"); -var _wasm_set_content_length = Module["_wasm_set_content_length"] = function() { - return (_wasm_set_content_length = Module["_wasm_set_content_length"] = Module["asm"]["xb"]).apply(null, arguments); -}; +var _wasm_set_request_body = Module["_wasm_set_request_body"] = createExportWrapper("wasm_set_request_body"); -var _wasm_set_cookies = Module["_wasm_set_cookies"] = function() { - return (_wasm_set_cookies = Module["_wasm_set_cookies"] = Module["asm"]["yb"]).apply(null, arguments); -}; +var _wasm_set_content_length = Module["_wasm_set_content_length"] = createExportWrapper("wasm_set_content_length"); -var _wasm_set_php_code = Module["_wasm_set_php_code"] = function() { - return (_wasm_set_php_code = Module["_wasm_set_php_code"] = Module["asm"]["zb"]).apply(null, arguments); -}; +var _wasm_set_cookies = Module["_wasm_set_cookies"] = createExportWrapper("wasm_set_cookies"); -var _wasm_set_request_port = Module["_wasm_set_request_port"] = function() { - return (_wasm_set_request_port = Module["_wasm_set_request_port"] = Module["asm"]["Ab"]).apply(null, arguments); -}; +var _wasm_set_php_code = Module["_wasm_set_php_code"] = createExportWrapper("wasm_set_php_code"); -var _phpwasm_init_uploaded_files_hash = Module["_phpwasm_init_uploaded_files_hash"] = function() { - return (_phpwasm_init_uploaded_files_hash = Module["_phpwasm_init_uploaded_files_hash"] = Module["asm"]["Bb"]).apply(null, arguments); -}; +var _wasm_set_request_port = Module["_wasm_set_request_port"] = createExportWrapper("wasm_set_request_port"); -var _phpwasm_register_uploaded_file = Module["_phpwasm_register_uploaded_file"] = function() { - return (_phpwasm_register_uploaded_file = Module["_phpwasm_register_uploaded_file"] = Module["asm"]["Cb"]).apply(null, arguments); -}; +var _phpwasm_init_uploaded_files_hash = Module["_phpwasm_init_uploaded_files_hash"] = createExportWrapper("phpwasm_init_uploaded_files_hash"); -var _phpwasm_destroy_uploaded_files_hash = Module["_phpwasm_destroy_uploaded_files_hash"] = function() { - return (_phpwasm_destroy_uploaded_files_hash = Module["_phpwasm_destroy_uploaded_files_hash"] = Module["asm"]["Db"]).apply(null, arguments); -}; +var _phpwasm_register_uploaded_file = Module["_phpwasm_register_uploaded_file"] = createExportWrapper("phpwasm_register_uploaded_file"); -var _wasm_sapi_handle_request = Module["_wasm_sapi_handle_request"] = function() { - return (_wasm_sapi_handle_request = Module["_wasm_sapi_handle_request"] = Module["asm"]["Eb"]).apply(null, arguments); -}; +var _phpwasm_destroy_uploaded_files_hash = Module["_phpwasm_destroy_uploaded_files_hash"] = createExportWrapper("phpwasm_destroy_uploaded_files_hash"); -var _php_wasm_init = Module["_php_wasm_init"] = function() { - return (_php_wasm_init = Module["_php_wasm_init"] = Module["asm"]["Fb"]).apply(null, arguments); -}; +var _wasm_sapi_handle_request = Module["_wasm_sapi_handle_request"] = createExportWrapper("wasm_sapi_handle_request"); -var ___funcs_on_exit = Module["___funcs_on_exit"] = function() { - return (___funcs_on_exit = Module["___funcs_on_exit"] = Module["asm"]["Gb"]).apply(null, arguments); -}; +var _php_wasm_init = Module["_php_wasm_init"] = createExportWrapper("php_wasm_init"); -var _emscripten_builtin_memalign = Module["_emscripten_builtin_memalign"] = function() { - return (_emscripten_builtin_memalign = Module["_emscripten_builtin_memalign"] = Module["asm"]["Hb"]).apply(null, arguments); -}; +var __emscripten_tls_init = Module["__emscripten_tls_init"] = createExportWrapper("_emscripten_tls_init"); -var _setThrew = Module["_setThrew"] = function() { - return (_setThrew = Module["_setThrew"] = Module["asm"]["Ib"]).apply(null, arguments); -}; +var _emscripten_builtin_memalign = createExportWrapper("emscripten_builtin_memalign"); -var stackSave = Module["stackSave"] = function() { - return (stackSave = Module["stackSave"] = Module["asm"]["Jb"]).apply(null, arguments); -}; +var ___funcs_on_exit = createExportWrapper("__funcs_on_exit"); -var stackRestore = Module["stackRestore"] = function() { - return (stackRestore = Module["stackRestore"] = Module["asm"]["Kb"]).apply(null, arguments); -}; +var _memcpy = createExportWrapper("memcpy"); -var stackAlloc = Module["stackAlloc"] = function() { - return (stackAlloc = Module["stackAlloc"] = Module["asm"]["Lb"]).apply(null, arguments); -}; +var ___dl_seterr = createExportWrapper("__dl_seterr"); -var dynCall_vi = Module["dynCall_vi"] = function() { - return (dynCall_vi = Module["dynCall_vi"] = Module["asm"]["Mb"]).apply(null, arguments); -}; +var __emscripten_thread_init = Module["__emscripten_thread_init"] = createExportWrapper("_emscripten_thread_init"); -var dynCall_iiii = Module["dynCall_iiii"] = function() { - return (dynCall_iiii = Module["dynCall_iiii"] = Module["asm"]["Nb"]).apply(null, arguments); -}; +var __emscripten_thread_crashed = Module["__emscripten_thread_crashed"] = createExportWrapper("_emscripten_thread_crashed"); -var dynCall_ii = Module["dynCall_ii"] = function() { - return (dynCall_ii = Module["dynCall_ii"] = Module["asm"]["Ob"]).apply(null, arguments); -}; +var _emscripten_main_thread_process_queued_calls = createExportWrapper("emscripten_main_thread_process_queued_calls"); -var dynCall_iiiiii = Module["dynCall_iiiiii"] = function() { - return (dynCall_iiiiii = Module["dynCall_iiiiii"] = Module["asm"]["Pb"]).apply(null, arguments); -}; +var _emscripten_main_runtime_thread_id = createExportWrapper("emscripten_main_runtime_thread_id"); -var dynCall_iiiii = Module["dynCall_iiiii"] = function() { - return (dynCall_iiiii = Module["dynCall_iiiii"] = Module["asm"]["Qb"]).apply(null, arguments); -}; +var __emscripten_run_in_main_runtime_thread_js = createExportWrapper("_emscripten_run_in_main_runtime_thread_js"); -var dynCall_viii = Module["dynCall_viii"] = function() { - return (dynCall_viii = Module["dynCall_viii"] = Module["asm"]["Rb"]).apply(null, arguments); -}; +var _emscripten_dispatch_to_thread_ = createExportWrapper("emscripten_dispatch_to_thread_"); -var dynCall_vii = Module["dynCall_vii"] = function() { - return (dynCall_vii = Module["dynCall_vii"] = Module["asm"]["Sb"]).apply(null, arguments); +var _emscripten_stack_get_base = function() { + return (_emscripten_stack_get_base = Module["asm"]["emscripten_stack_get_base"]).apply(null, arguments); }; -var dynCall_iii = Module["dynCall_iii"] = function() { - return (dynCall_iii = Module["dynCall_iii"] = Module["asm"]["Tb"]).apply(null, arguments); +var _emscripten_stack_get_end = function() { + return (_emscripten_stack_get_end = Module["asm"]["emscripten_stack_get_end"]).apply(null, arguments); }; -var dynCall_viiiii = Module["dynCall_viiiii"] = function() { - return (dynCall_viiiii = Module["dynCall_viiiii"] = Module["asm"]["Ub"]).apply(null, arguments); -}; +var __emscripten_thread_free_data = createExportWrapper("_emscripten_thread_free_data"); -var dynCall_iiiiiii = Module["dynCall_iiiiiii"] = function() { - return (dynCall_iiiiiii = Module["dynCall_iiiiiii"] = Module["asm"]["Vb"]).apply(null, arguments); -}; +var __emscripten_thread_exit = Module["__emscripten_thread_exit"] = createExportWrapper("_emscripten_thread_exit"); -var dynCall_i = Module["dynCall_i"] = function() { - return (dynCall_i = Module["dynCall_i"] = Module["asm"]["Wb"]).apply(null, arguments); -}; +var __emscripten_timeout = createExportWrapper("_emscripten_timeout"); -var dynCall_v = Module["dynCall_v"] = function() { - return (dynCall_v = Module["dynCall_v"] = Module["asm"]["Xb"]).apply(null, arguments); -}; +var __emscripten_check_mailbox = Module["__emscripten_check_mailbox"] = createExportWrapper("_emscripten_check_mailbox"); -var dynCall_viiii = Module["dynCall_viiii"] = function() { - return (dynCall_viiii = Module["dynCall_viiii"] = Module["asm"]["Yb"]).apply(null, arguments); -}; +var _setThrew = createExportWrapper("setThrew"); -var dynCall_iiiiiiiiii = Module["dynCall_iiiiiiiiii"] = function() { - return (dynCall_iiiiiiiiii = Module["dynCall_iiiiiiiiii"] = Module["asm"]["Zb"]).apply(null, arguments); +var _emscripten_stack_init = function() { + return (_emscripten_stack_init = Module["asm"]["emscripten_stack_init"]).apply(null, arguments); }; -var dynCall_viiiiiiiii = Module["dynCall_viiiiiiiii"] = function() { - return (dynCall_viiiiiiiii = Module["dynCall_viiiiiiiii"] = Module["asm"]["_b"]).apply(null, arguments); +var _emscripten_stack_set_limits = function() { + return (_emscripten_stack_set_limits = Module["asm"]["emscripten_stack_set_limits"]).apply(null, arguments); }; -var dynCall_viiiiii = Module["dynCall_viiiiii"] = function() { - return (dynCall_viiiiii = Module["dynCall_viiiiii"] = Module["asm"]["$b"]).apply(null, arguments); +var _emscripten_stack_get_free = function() { + return (_emscripten_stack_get_free = Module["asm"]["emscripten_stack_get_free"]).apply(null, arguments); }; -var dynCall_iiiiiiii = Module["dynCall_iiiiiiii"] = function() { - return (dynCall_iiiiiiii = Module["dynCall_iiiiiiii"] = Module["asm"]["ac"]).apply(null, arguments); -}; +var stackSave = createExportWrapper("stackSave"); -var dynCall_viidii = Module["dynCall_viidii"] = function() { - return (dynCall_viidii = Module["dynCall_viidii"] = Module["asm"]["bc"]).apply(null, arguments); -}; +var stackRestore = createExportWrapper("stackRestore"); -var _asyncify_start_unwind = Module["_asyncify_start_unwind"] = function() { - return (_asyncify_start_unwind = Module["_asyncify_start_unwind"] = Module["asm"]["cc"]).apply(null, arguments); -}; +var stackAlloc = createExportWrapper("stackAlloc"); -var _asyncify_stop_unwind = Module["_asyncify_stop_unwind"] = function() { - return (_asyncify_stop_unwind = Module["_asyncify_stop_unwind"] = Module["asm"]["dc"]).apply(null, arguments); +var _emscripten_stack_get_current = function() { + return (_emscripten_stack_get_current = Module["asm"]["emscripten_stack_get_current"]).apply(null, arguments); }; -var _asyncify_start_rewind = Module["_asyncify_start_rewind"] = function() { - return (_asyncify_start_rewind = Module["_asyncify_start_rewind"] = Module["asm"]["ec"]).apply(null, arguments); -}; +var ___set_stack_limits = Module["___set_stack_limits"] = createExportWrapper("__set_stack_limits"); -var _asyncify_stop_rewind = Module["_asyncify_stop_rewind"] = function() { - return (_asyncify_stop_rewind = Module["_asyncify_stop_rewind"] = Module["asm"]["fc"]).apply(null, arguments); -}; +var dynCall_vi = Module["dynCall_vi"] = createExportWrapper("dynCall_vi"); + +var dynCall_viii = Module["dynCall_viii"] = createExportWrapper("dynCall_viii"); + +var dynCall_ii = Module["dynCall_ii"] = createExportWrapper("dynCall_ii"); + +var dynCall_iiii = Module["dynCall_iiii"] = createExportWrapper("dynCall_iiii"); + +var dynCall_iii = Module["dynCall_iii"] = createExportWrapper("dynCall_iii"); + +var dynCall_viiii = Module["dynCall_viiii"] = createExportWrapper("dynCall_viiii"); + +var dynCall_viiiii = Module["dynCall_viiiii"] = createExportWrapper("dynCall_viiiii"); + +var dynCall_iiiii = Module["dynCall_iiiii"] = createExportWrapper("dynCall_iiiii"); + +var dynCall_iiiiiii = Module["dynCall_iiiiiii"] = createExportWrapper("dynCall_iiiiiii"); + +var dynCall_iiiiii = Module["dynCall_iiiiii"] = createExportWrapper("dynCall_iiiiii"); + +var dynCall_i = Module["dynCall_i"] = createExportWrapper("dynCall_i"); + +var dynCall_vii = Module["dynCall_vii"] = createExportWrapper("dynCall_vii"); + +var dynCall_v = Module["dynCall_v"] = createExportWrapper("dynCall_v"); + +var dynCall_iiiiiiiiiiii = Module["dynCall_iiiiiiiiiiii"] = createExportWrapper("dynCall_iiiiiiiiiiii"); + +var dynCall_iiiiiiiiii = Module["dynCall_iiiiiiiiii"] = createExportWrapper("dynCall_iiiiiiiiii"); + +var dynCall_viiiiiiii = Module["dynCall_viiiiiiii"] = createExportWrapper("dynCall_viiiiiiii"); + +var dynCall_iiiiiiiiiiiiiii = Module["dynCall_iiiiiiiiiiiiiii"] = createExportWrapper("dynCall_iiiiiiiiiiiiiii"); + +var dynCall_viiiiii = Module["dynCall_viiiiii"] = createExportWrapper("dynCall_viiiiii"); + +var dynCall_viidii = Module["dynCall_viidii"] = createExportWrapper("dynCall_viidii"); + +var dynCall_jiji = Module["dynCall_jiji"] = createExportWrapper("dynCall_jiji"); + +var dynCall_iidiiii = Module["dynCall_iidiiii"] = createExportWrapper("dynCall_iidiiii"); function invoke_iiiiiii(index, a1, a2, a3, a4, a5, a6) { var sp = stackSave(); @@ -6897,10 +7862,10 @@ function invoke_iiiiiii(index, a1, a2, a3, a4, a5, a6) { } } -function invoke_vi(index, a1) { +function invoke_viiii(index, a1, a2, a3, a4) { var sp = stackSave(); try { - dynCall_vi(index, a1); + dynCall_viiii(index, a1, a2, a3, a4); } catch (e) { stackRestore(sp); if (e !== e + 0) throw e; @@ -6908,10 +7873,10 @@ function invoke_vi(index, a1) { } } -function invoke_iii(index, a1, a2) { +function invoke_viiiii(index, a1, a2, a3, a4, a5) { var sp = stackSave(); try { - return dynCall_iii(index, a1, a2); + dynCall_viiiii(index, a1, a2, a3, a4, a5); } catch (e) { stackRestore(sp); if (e !== e + 0) throw e; @@ -6930,10 +7895,10 @@ function invoke_vii(index, a1, a2) { } } -function invoke_i(index) { +function invoke_vi(index, a1) { var sp = stackSave(); try { - return dynCall_i(index); + dynCall_vi(index, a1); } catch (e) { stackRestore(sp); if (e !== e + 0) throw e; @@ -6952,32 +7917,10 @@ function invoke_viii(index, a1, a2, a3) { } } -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_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_viiii(index, a1, a2, a3, a4) { +function invoke_i(index) { var sp = stackSave(); try { - dynCall_viiii(index, a1, a2, a3, a4); + return dynCall_i(index); } catch (e) { stackRestore(sp); if (e !== e + 0) throw e; @@ -6985,10 +7928,10 @@ function invoke_viiii(index, a1, a2, a3, a4) { } } -function invoke_iiiii(index, a1, a2, a3, a4) { +function invoke_v(index) { var sp = stackSave(); try { - return dynCall_iiiii(index, a1, a2, a3, a4); + dynCall_v(index); } catch (e) { stackRestore(sp); if (e !== e + 0) throw e; @@ -6996,10 +7939,10 @@ function invoke_iiiii(index, a1, a2, a3, a4) { } } -function invoke_iiii(index, a1, a2, a3) { +function invoke_ii(index, a1) { var sp = stackSave(); try { - return dynCall_iiii(index, a1, a2, a3); + return dynCall_ii(index, a1); } catch (e) { stackRestore(sp); if (e !== e + 0) throw e; @@ -7007,10 +7950,10 @@ function invoke_iiii(index, a1, a2, a3) { } } -function invoke_viiiiii(index, a1, a2, a3, a4, a5, a6) { +function invoke_iiiiii(index, a1, a2, a3, a4, a5) { var sp = stackSave(); try { - dynCall_viiiiii(index, a1, a2, a3, a4, a5, a6); + return dynCall_iiiiii(index, a1, a2, a3, a4, a5); } catch (e) { stackRestore(sp); if (e !== e + 0) throw e; @@ -7018,10 +7961,10 @@ function invoke_viiiiii(index, a1, a2, a3, a4, a5, a6) { } } -function invoke_viiiii(index, a1, a2, a3, a4, a5) { +function invoke_iii(index, a1, a2) { var sp = stackSave(); try { - dynCall_viiiii(index, a1, a2, a3, a4, a5); + return dynCall_iii(index, a1, a2); } catch (e) { stackRestore(sp); if (e !== e + 0) throw e; @@ -7029,10 +7972,10 @@ function invoke_viiiii(index, a1, a2, a3, a4, a5) { } } -function invoke_viidii(index, a1, a2, a3, a4, a5) { +function invoke_iiii(index, a1, a2, a3) { var sp = stackSave(); try { - dynCall_viidii(index, a1, a2, a3, a4, a5); + return dynCall_iiii(index, a1, a2, a3); } catch (e) { stackRestore(sp); if (e !== e + 0) throw e; @@ -7051,10 +7994,10 @@ function invoke_iiiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9) { } } -function invoke_iiiiii(index, a1, a2, a3, a4, a5) { +function invoke_iiiii(index, a1, a2, a3, a4) { var sp = stackSave(); try { - return dynCall_iiiiii(index, a1, a2, a3, a4, a5); + return dynCall_iiiii(index, a1, a2, a3, a4); } catch (e) { stackRestore(sp); if (e !== e + 0) throw e; @@ -7062,10 +8005,10 @@ function invoke_iiiiii(index, a1, a2, a3, a4, a5) { } } -function invoke_viiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9) { +function invoke_viiiiii(index, a1, a2, a3, a4, a5, a6) { var sp = stackSave(); try { - dynCall_viiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9); + dynCall_viiiiii(index, a1, a2, a3, a4, a5, a6); } catch (e) { stackRestore(sp); if (e !== e + 0) throw e; @@ -7073,10 +8016,10 @@ function invoke_viiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9) { } } -function invoke_iiiiiiii(index, a1, a2, a3, a4, a5, a6, a7) { +function invoke_viidii(index, a1, a2, a3, a4, a5) { var sp = stackSave(); try { - return dynCall_iiiiiiii(index, a1, a2, a3, a4, a5, a6, a7); + dynCall_viidii(index, a1, a2, a3, a4, a5); } catch (e) { stackRestore(sp); if (e !== e + 0) throw e; @@ -7104,10 +8047,24 @@ Module["FS_createDevice"] = FS.createDevice; Module["FS_unlink"] = FS.unlink; +Module["keepRuntimeAlive"] = keepRuntimeAlive; + +Module["wasmMemory"] = wasmMemory; + Module["ccall"] = ccall; +Module["ExitStatus"] = ExitStatus; + Module["FS"] = FS; +var missingLibrarySymbols = [ "stringToNewUTF8", "traverseStack", "convertPCtoSourceLocation", "readEmAsmArgs", "jstoi_s", "listenOnce", "autoResumeAudioContext", "dynCallLegacy", "getDynCaller", "dynCall", "runtimeKeepalivePop", "safeSetTimeout", "asmjsMangle", "HandleAllocator", "getNativeTypeSize", "STACK_SIZE", "STACK_ALIGN", "POINTER_SIZE", "ASSERTIONS", "writeI53ToI64", "writeI53ToI64Clamped", "writeI53ToI64Signaling", "writeI53ToU64Clamped", "writeI53ToU64Signaling", "readI53FromU64", "convertI32PairToI53", "convertU32PairToI53", "cwrap", "uleb128Encode", "sigToWasmTypes", "generateFuncType", "convertJsFunctionToWasm", "getEmptyTableSlot", "updateTableMap", "getFunctionAddress", "addFunction", "removeFunction", "reallyNegative", "unSign", "strLen", "reSign", "formatString", "intArrayToString", "AsciiToString", "stringToAscii", "UTF16ToString", "stringToUTF16", "lengthBytesUTF16", "UTF32ToString", "stringToUTF32", "lengthBytesUTF32", "writeStringToMemory", "registerKeyEventCallback", "maybeCStringToJsString", "findEventTarget", "findCanvasEventTarget", "getBoundingClientRect", "fillMouseEventData", "registerMouseEventCallback", "registerWheelEventCallback", "registerUiEventCallback", "registerFocusEventCallback", "fillDeviceOrientationEventData", "registerDeviceOrientationEventCallback", "fillDeviceMotionEventData", "registerDeviceMotionEventCallback", "screenOrientation", "fillOrientationChangeEventData", "registerOrientationChangeEventCallback", "fillFullscreenChangeEventData", "registerFullscreenChangeEventCallback", "JSEvents_requestFullscreen", "JSEvents_resizeCanvasForFullscreen", "registerRestoreOldStyle", "hideEverythingExceptGivenElement", "restoreHiddenElements", "setLetterbox", "softFullscreenResizeWebGLRenderTarget", "doRequestFullscreen", "fillPointerlockChangeEventData", "registerPointerlockChangeEventCallback", "registerPointerlockErrorEventCallback", "requestPointerLock", "fillVisibilityChangeEventData", "registerVisibilityChangeEventCallback", "registerTouchEventCallback", "fillGamepadEventData", "registerGamepadEventCallback", "registerBeforeUnloadEventCallback", "fillBatteryEventData", "battery", "registerBatteryEventCallback", "setCanvasElementSize", "getCanvasElementSize", "jsStackTrace", "stackTrace", "checkWasiClock", "createDyncallWrapper", "setImmediateWrapped", "clearImmediateWrapped", "polyfillSetImmediate", "getPromise", "makePromise", "makePromiseCallback", "ExceptionInfo", "exception_addRef", "exception_decRef", "setMainLoop", "_setNetworkCallback", "heapObjectForWebGLType", "heapAccessShiftForWebGLHeap", "emscriptenWebGLGet", "computeUnpackAlignedImageSize", "emscriptenWebGLGetTexPixelData", "emscriptenWebGLGetUniform", "webglGetUniformLocation", "webglPrepareUniformLocationsBeforeFirstUse", "webglGetLeftBracePos", "emscriptenWebGLGetVertexAttrib", "writeGLArray", "SDL_unicode", "SDL_ttfContext", "SDL_audio", "GLFW_Window", "runAndAbortIfError", "ALLOC_NORMAL", "ALLOC_STACK", "allocate" ]; + +missingLibrarySymbols.forEach(missingLibrarySymbol); + +var unexportedSymbols = [ "run", "UTF8ArrayToString", "stringToUTF8Array", "stringToUTF8", "addOnPreRun", "addOnInit", "addOnPreMain", "addOnExit", "addOnPostRun", "FS_createFolder", "FS_createLink", "out", "err", "callMain", "abort", "stackAlloc", "stackSave", "stackRestore", "getTempRet0", "setTempRet0", "GROWABLE_HEAP_I8", "GROWABLE_HEAP_U8", "GROWABLE_HEAP_I16", "GROWABLE_HEAP_U16", "GROWABLE_HEAP_I32", "GROWABLE_HEAP_U32", "GROWABLE_HEAP_F32", "GROWABLE_HEAP_F64", "writeStackCookie", "checkStackCookie", "ptrToString", "zeroMemory", "exitJS", "getHeapMax", "emscripten_realloc_buffer", "ENV", "ERRNO_CODES", "ERRNO_MESSAGES", "setErrNo", "inetPton4", "inetNtop4", "inetPton6", "inetNtop6", "readSockaddr", "writeSockaddr", "DNS", "getHostByName", "Protocols", "Sockets", "getRandomDevice", "timers", "warnOnce", "UNWIND_CACHE", "readEmAsmArgsArray", "jstoi_q", "getExecutableName", "handleException", "runtimeKeepalivePush", "callUserCallback", "maybeExit", "asyncLoad", "alignMemory", "mmapAlloc", "readI53FromI64", "convertI32PairToI53Checked", "getCFunc", "freeTableIndexes", "functionsInTableMap", "setValue", "getValue", "PATH", "PATH_FS", "intArrayFromString", "UTF16Decoder", "allocateUTF8", "allocateUTF8OnStack", "writeArrayToMemory", "writeAsciiToMemory", "SYSCALLS", "getSocketFromFD", "getSocketAddress", "JSEvents", "specialHTMLTargets", "currentFullscreenStrategy", "restoreOldWindowedStyle", "demangle", "demangleAll", "getEnvStrings", "doReadv", "doWritev", "dlopenMissingError", "promiseMap", "uncaughtExceptionCount", "exceptionLast", "exceptionCaught", "Browser", "wget", "MEMFS", "TTY", "PIPEFS", "SOCKFS", "tempFixedLengthArray", "miniTempWebGLFloatBuffers", "GL", "AL", "SDL", "SDL_gfx", "GLUT", "EGL", "GLFW", "GLEW", "IDBStore", "PThread", "terminateWorker", "killThread", "cleanupThread", "registerTLSInit", "cancelThread", "spawnThread", "exitOnMainThread", "invokeEntryPoint", "checkMailbox", "PHPWASM", "NODEFS" ]; + +unexportedSymbols.forEach(unexportedRuntimeSymbol); + var calledRun; dependenciesFulfilled = function runCaller() { @@ -7115,11 +8072,22 @@ dependenciesFulfilled = function runCaller() { if (!calledRun) dependenciesFulfilled = runCaller; }; -function run(args) { - args = args || arguments_; +function stackCheckInit() { + assert(!ENVIRONMENT_IS_PTHREAD); + _emscripten_stack_init(); + writeStackCookie(); +} + +function run() { if (runDependencies > 0) { return; } + if (!ENVIRONMENT_IS_PTHREAD) stackCheckInit(); + if (ENVIRONMENT_IS_PTHREAD) { + initRuntime(); + startWorker(Module); + return; + } preRun(); if (runDependencies > 0) { return; @@ -7131,6 +8099,7 @@ function run(args) { if (ABORT) return; initRuntime(); if (Module["onRuntimeInitialized"]) Module["onRuntimeInitialized"](); + assert(!Module["_main"], 'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]'); postRun(); } if (Module["setStatus"]) { @@ -7144,6 +8113,7 @@ function run(args) { } else { doRun(); } + checkStackCookie(); } if (Module["preInit"]) { @@ -7166,13 +8136,4 @@ DNS.address_map.addrs.localhost = '127.0.0.1'; * so that it can be inspected later. */ PHPLoader.debug = 'debug' in PHPLoader ? PHPLoader.debug : true; -if (PHPLoader.debug) { - const originalHandleSleep = Asyncify.handleSleep; - Asyncify.handleSleep = function (startAsync) { - if (!ABORT) { - Module["lastAsyncifyStackSource"] = new Error(); - } - return originalHandleSleep(startAsync); - } -} return PHPLoader; } diff --git a/packages/php-wasm/node/public/php_7_4.wasm b/packages/php-wasm/node/public/php_7_4.wasm index af592714e4..47f1f17d24 100644 Binary files a/packages/php-wasm/node/public/php_7_4.wasm and b/packages/php-wasm/node/public/php_7_4.wasm differ diff --git a/packages/php-wasm/node/src/test/php.spec.ts b/packages/php-wasm/node/src/test/php.spec.ts index 9f53153ba2..ace554de4c 100644 --- a/packages/php-wasm/node/src/test/php.spec.ts +++ b/packages/php-wasm/node/src/test/php.spec.ts @@ -5,12 +5,24 @@ import { existsSync, rmSync, readFileSync } from 'fs'; const testDirPath = '/__test987654321'; const testFilePath = '/__test987654321.txt'; -describe.each(SupportedPHPVersions)('PHP %s', (phpVersion) => { +describe.each(['7.4'])('PHP %s', (phpVersion) => { let php: NodePHP; beforeEach(async () => { - php = await NodePHP.load(phpVersion); + // php = await NodePHP.load(phpVersion); }); + it.only('test', async () => { + const php = await NodePHP.load('7.4'); + expect(php).toBeDefined(); + await php.setPhpIniEntry('disable_functions', ''); + const out = await php.run({ + code: ` { // Unit tests for the filesystem methods of the // PHP runtime. diff --git a/packages/php-wasm/node/test.js b/packages/php-wasm/node/test.js new file mode 100644 index 0000000000..9d8103d71a --- /dev/null +++ b/packages/php-wasm/node/test.js @@ -0,0 +1,46 @@ +const load = require('./public/php_7_4.js') +const php = load( + 'NODE', + { + onAbort(reason) { + console.error('WASM aborted: '); + console.error(reason); + }, + ENV: { + // USE_ZEND_ALLOC: '0', + }, + noInitialRun: true, + print: (str) => console.log(str), + printErr: (str) => console.log(str), + async onRuntimeInitialized() { + php._php_wasm_init(); + php.FS.writeFile('/script.php', ` + `); + // php._wasm_set_path_translated(`/script.php`); + php._wasm_set_php_code(` +