diff --git a/emcc.py b/emcc.py index 4ba8a6b9c3583..6bf4d260f7985 100755 --- a/emcc.py +++ b/emcc.py @@ -1103,6 +1103,10 @@ def get_last_setting_change(setting): if 'WARN_ON_UNDEFINED_SYMBOLS=0' in settings_changes: shared.Settings.ERROR_ON_UNDEFINED_SYMBOLS = 0 + if shared.Settings.MINIMAL_RUNTIME or 'MINIMAL_RUNTIME=1' in settings_changes or 'MINIMAL_RUNTIME=2' in settings_changes: + # Remove the default exported functions 'malloc', 'free', etc. those should only be linked in if used + shared.Settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE = [] + # Set ASM_JS default here so that we can override it from the command line. shared.Settings.ASM_JS = 1 if options.opt_level > 0 else 2 @@ -1249,10 +1253,6 @@ def is_supported_link_flag(f): link_flags = [f for f in link_flags if is_supported_link_flag(f[1])] - if shared.Settings.MINIMAL_RUNTIME: - # Remove the default exported functions 'memcpy', 'memset', 'malloc', 'free', etc. - those should only be linked in if used - shared.Settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE = [] - if shared.Settings.STACK_OVERFLOW_CHECK: if shared.Settings.MINIMAL_RUNTIME: shared.Settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$abortStackOverflow'] diff --git a/src/Fetch.js b/src/Fetch.js index 1b9361d60284b..26184d0158852 100644 --- a/src/Fetch.js +++ b/src/Fetch.js @@ -325,7 +325,9 @@ function __emscripten_fetch_xhr(fetch, onsuccess, onerror, onprogress, onreadyst xhr.open(requestMethod, url_, !fetchAttrSynchronous, userNameStr, passwordStr); if (!fetchAttrSynchronous) xhr.timeout = timeoutMsecs; // XHR timeout field is only accessible in async XHRs, and must be set after .open() but before .send(). xhr.url_ = url_; // Save the url for debugging purposes (and for comparing to the responseURL that server side advertised) +#if ASSERTIONS assert(!fetchAttrStreamData, 'streaming uses moz-chunked-arraybuffer which is no longer supported; TODO: rewrite using fetch()'); +#endif xhr.responseType = 'arraybuffer'; if (overriddenMimeType) { diff --git a/src/deps_info.json b/src/deps_info.json index 8914d7a5dbd4f..7103bbe808c50 100644 --- a/src/deps_info.json +++ b/src/deps_info.json @@ -80,13 +80,13 @@ "sleep": ["usleep"], "recv": ["htons"], "send": ["htons"], - "ctime": ["_get_tzname", "_get_daylight", "_get_timezone"], - "ctime_r": ["_get_tzname", "_get_daylight", "_get_timezone"], - "localtime": ["_get_tzname", "_get_daylight", "_get_timezone"], - "localtime_r": ["_get_tzname", "_get_daylight", "_get_timezone"], - "mktime": ["_get_tzname", "_get_daylight", "_get_timezone"], - "timegm": ["_get_tzname", "_get_daylight", "_get_timezone"], - "tzset": ["_get_tzname", "_get_daylight", "_get_timezone"], + "ctime": ["_get_tzname", "_get_daylight", "_get_timezone", "malloc"], + "ctime_r": ["_get_tzname", "_get_daylight", "_get_timezone", "malloc"], + "localtime": ["_get_tzname", "_get_daylight", "_get_timezone", "malloc"], + "localtime_r": ["_get_tzname", "_get_daylight", "_get_timezone", "malloc"], + "mktime": ["_get_tzname", "_get_daylight", "_get_timezone", "malloc"], + "timegm": ["_get_tzname", "_get_daylight", "_get_timezone", "malloc"], + "tzset": ["_get_tzname", "_get_daylight", "_get_timezone", "malloc"], "emscripten_set_canvas_element_size_calling_thread": ["emscripten_async_queue_on_thread_"], "emscripten_webgl_destroy_context": ["emscripten_webgl_make_context_current", "emscripten_webgl_get_current_context"], "emscripten_webgl_create_context": ["malloc", "free"], diff --git a/src/library.js b/src/library.js index 005ce6f41cfb8..6aadf579f55a0 100644 --- a/src/library.js +++ b/src/library.js @@ -467,7 +467,7 @@ LibraryManager.library = { }, emscripten_get_heap_size: function() { - return HEAP8.length; + return HEAPU8.length; }, emscripten_get_sbrk_ptr__asm: true, @@ -703,7 +703,7 @@ LibraryManager.library = { _exit(-1234); }, -#if MINIMAL_RUNTIME +#if MINIMAL_RUNTIME && !EXIT_RUNTIME atexit: function(){}, __cxa_atexit: function(){}, __cxa_thread_atexit: function(){}, @@ -746,7 +746,7 @@ LibraryManager.library = { // to limitations in the system libraries (we can't easily add a global // ctor to create the environment without it always being linked in with // libc). - __buildEnvironment__deps: ['$ENV'], + __buildEnvironment__deps: ['$ENV', '_getExecutableName'], __buildEnvironment: function(environ) { // WARNING: Arbitrary limit! var MAX_ENV_VALUES = 64; @@ -765,7 +765,7 @@ LibraryManager.library = { ENV['HOME'] = '/home/web_user'; // Browser language detection #8751 ENV['LANG'] = ((typeof navigator === 'object' && navigator.languages && navigator.languages[0]) || 'C').replace('-', '_') + '.UTF-8'; - ENV['_'] = thisProgram; + ENV['_'] = __getExecutableName(); // Allocate memory. #if !MINIMAL_RUNTIME // TODO: environment support in MINIMAL_RUNTIME poolPtr = getMemory(TOTAL_ENV_SIZE); @@ -1844,12 +1844,12 @@ LibraryManager.library = { } }, - dladdr__deps: ['$stringToNewUTF8'], + dladdr__deps: ['$stringToNewUTF8', '_getExecutableName'], dladdr__proxy: 'sync', dladdr__sig: 'iii', dladdr: function(addr, info) { // report all function pointers as coming from this program itself XXX not really correct in any way - var fname = stringToNewUTF8(thisProgram || './this.program'); // XXX leak + var fname = stringToNewUTF8(__getExecutableName()); // XXX leak {{{ makeSetValue('info', 0, 'fname', 'i32') }}}; {{{ makeSetValue('info', Runtime.QUANTUM_SIZE, '0', 'i32') }}}; {{{ makeSetValue('info', Runtime.QUANTUM_SIZE*2, '0', 'i32') }}}; @@ -2068,6 +2068,9 @@ LibraryManager.library = { // Note: glibc has one fewer underscore for all of these. Also used in other related functions (timegm) tzset__proxy: 'sync', tzset__sig: 'v', +#if MINIMAL_RUNTIME + tzset__deps: ['$allocateUTF8'], +#endif tzset: function() { // TODO: Use (malleable) environment variables instead of system settings. if (_tzset.called) return; @@ -2091,8 +2094,8 @@ LibraryManager.library = { }; var winterName = extractZone(winter); var summerName = extractZone(summer); - var winterNamePtr = allocate(intArrayFromString(winterName), 'i8', ALLOC_NORMAL); - var summerNamePtr = allocate(intArrayFromString(summerName), 'i8', ALLOC_NORMAL); + var winterNamePtr = allocateUTF8(winterName); + var summerNamePtr = allocateUTF8(summerName); if (summer.getTimezoneOffset() < winter.getTimezoneOffset()) { // Northern hemisphere {{{ makeSetValue('__get_tzname()', '0', 'winterNamePtr', 'i32') }}}; @@ -2158,7 +2161,11 @@ LibraryManager.library = { // Note: this is not used in STANDALONE_WASM mode, because it is more // compact to do it in JS. - strftime__deps: ['_isLeapYear', '_arraySum', '_addDays', '_MONTH_DAYS_REGULAR', '_MONTH_DAYS_LEAP'], + strftime__deps: ['_isLeapYear', '_arraySum', '_addDays', '_MONTH_DAYS_REGULAR', '_MONTH_DAYS_LEAP' +#if MINIMAL_RUNTIME + , '$intArrayFromString', '$writeArrayToMemory' +#endif + ], strftime: function(s, maxsize, format, tm) { // size_t strftime(char *restrict s, size_t maxsize, const char *restrict format, const struct tm *restrict timeptr); // http://pubs.opengroup.org/onlinepubs/009695399/functions/strftime.html @@ -2481,7 +2488,11 @@ LibraryManager.library = { return _strftime(s, maxsize, format, tm); // no locale support yet }, - strptime__deps: ['_isLeapYear', '_arraySum', '_addDays', '_MONTH_DAYS_REGULAR', '_MONTH_DAYS_LEAP'], + strptime__deps: ['_isLeapYear', '_arraySum', '_addDays', '_MONTH_DAYS_REGULAR', '_MONTH_DAYS_LEAP' +#if MINIMAL_RUNTIME + , '$intArrayFromString' +#endif + ], strptime: function(buf, format, tm) { // char *strptime(const char *restrict buf, const char *restrict format, struct tm *restrict tm); // http://pubs.opengroup.org/onlinepubs/009695399/functions/strptime.html @@ -5149,6 +5160,19 @@ LibraryManager.library = { __handle_stack_overflow: function() { abort('stack overflow') }, + + _getExecutableName: function() { +#if MINIMAL_RUNTIME // MINIMAL_RUNTIME does not have a global runtime variable thisProgram +#if ENVIRONMENT_MAY_BE_NODE + if (ENVIRONMENT_IS_NODE && process['argv'].length > 1) { + return process['argv'][1].replace(/\\/g, '/'); + } +#endif + return "./this.program"; +#else + return thisProgram || './this.program'; +#endif + }, }; function autoAddDeps(object, name) { diff --git a/src/library_formatString.js b/src/library_formatString.js index bc6bb387a6640..5b685237229ec 100644 --- a/src/library_formatString.js +++ b/src/library_formatString.js @@ -10,7 +10,9 @@ mergeInto(LibraryManager.library, { // Returns the resulting string string as a character array. _formatString__deps: ['_reallyNegative'], _formatString: function(format, varargs) { +#if ASSERTIONS assert((varargs & 3) === 0); +#endif var textIndex = format; var argIndex = varargs; // This must be called before reading a double or i64 vararg. It will bump the pointer properly. @@ -19,11 +21,15 @@ mergeInto(LibraryManager.library, { if (type === 'double' || type === 'i64') { // move so the load is aligned if (ptr & 7) { +#if ASSERTIONS assert((ptr & 7) === 4); +#endif ptr += 4; } } else { +#if ASSERTIONS assert((ptr & 3) === 0); +#endif } return ptr; } @@ -40,7 +46,9 @@ mergeInto(LibraryManager.library, { {{{ makeGetValue('argIndex', 4, 'i32', undefined, undefined, true, 4) }}}]; argIndex += 8; } else { +#if ASSERTIONS assert((argIndex & 3) === 0); +#endif type = 'i32'; // varargs are always i32, i64, or double ret = {{{ makeGetValue('argIndex', 0, 'i32', undefined, undefined, true) }}}; argIndex += 4; @@ -418,7 +426,11 @@ mergeInto(LibraryManager.library, { }, // printf/puts implementations for when musl is not pulled in - very partial. useful for tests, and when bootstrapping structInfo - printf__deps: ['_formatString'], + printf__deps: ['_formatString' +#if MINIMAL_RUNTIME + , '$intArrayToString' +#endif + ], printf: function(format, varargs) { // int printf(const char *restrict format, ...); // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html diff --git a/src/library_html5.js b/src/library_html5.js index dfe96d7378c59..9f36984c3a11e 100644 --- a/src/library_html5.js +++ b/src/library_html5.js @@ -41,7 +41,7 @@ var LibraryJSEvents = { #endif }, -#if !MINIMAL_RUNTIME // In minimal runtime, there is no concept of the page running vs being closed, and hence __ATEXIT__ is not present +#if !MINIMAL_RUNTIME || EXIT_RUNTIME // In minimal runtime, there is no concept of the page running vs being closed, and hence __ATEXIT__ is not present registerRemoveEventListeners: function() { if (!JSEvents.removeEventListenersRegistered) { __ATEXIT__.push(JSEvents.removeAllEventListeners); @@ -175,7 +175,7 @@ var LibraryJSEvents = { }, #if USE_PTHREADS -#if MINIMAL_RUNTIME +#if MINIMAL_RUNTIME && !WASM_BACKEND queueEventHandlerOnThread_iiii__deps: ['$stackSave', '$stackAlloc', '$stackRestore'], #endif queueEventHandlerOnThread_iiii: function(targetThread, eventHandlerFunc, eventTypeId, eventData, userData) { @@ -2824,7 +2824,7 @@ var LibraryJSEvents = { }, emscripten_set_offscreencanvas_size_on_target_thread_js__deps: ['$stringToNewUTF8' -#if MINIMAL_RUNTIME +#if MINIMAL_RUNTIME && !WASM_BACKEND , '$stackSave', '$stackAlloc', '$stackRestore' #endif ], @@ -2887,7 +2887,7 @@ var LibraryJSEvents = { #endif _set_canvas_element_size__deps: ['emscripten_set_canvas_element_size' -#if MINIMAL_RUNTIME +#if MINIMAL_RUNTIME && !WASM_BACKEND , '$stackSave', '$stackAlloc', '$stackRestore' #endif ], @@ -2964,7 +2964,7 @@ var LibraryJSEvents = { // JavaScript-friendly API, returns pair [width, height] _get_canvas_element_size__deps: ['emscripten_get_canvas_element_size' -#if MINIMAL_RUNTIME +#if MINIMAL_RUNTIME && !WASM_BACKEND , '$stackSave', '$stackAlloc', '$stackRestore' #endif ], diff --git a/src/library_nodefs.js b/src/library_nodefs.js index 780c15ecf3053..415da896a49f1 100644 --- a/src/library_nodefs.js +++ b/src/library_nodefs.js @@ -34,11 +34,15 @@ mergeInto(LibraryManager.library, { }, convertNodeCode: function(e) { var code = e.code; +#if ASSERTIONS assert(code in ERRNO_CODES); +#endif return ERRNO_CODES[code]; }, mount: function (mount) { +#if ASSERTIONS assert(ENVIRONMENT_IS_NODE); +#endif return NODEFS.createNode(null, '/', NODEFS.getMode(mount.opts.root), 0); }, createNode: function (parent, name, mode, dev) { diff --git a/src/library_pthread_stub.js b/src/library_pthread_stub.js index 3d47b3c404d24..0a3749d0edcd4 100644 --- a/src/library_pthread_stub.js +++ b/src/library_pthread_stub.js @@ -163,23 +163,15 @@ var LibraryPThreadStub = { emscripten_main_browser_thread_id: function() { return _pthread_self(); }, // When pthreads is not enabled, we can't use the Atomics futex api to do proper sleeps, so simulate a busy spin wait loop instead. + usleep__deps: ['emscripten_get_now'], usleep: function(useconds) { // int usleep(useconds_t useconds); // http://pubs.opengroup.org/onlinepubs/000095399/functions/usleep.html // We're single-threaded, so use a busy loop. Super-ugly. - var msec = useconds / 1000; - if ((ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) && self['performance'] && self['performance']['now']) { - var start = self['performance']['now'](); - while (self['performance']['now']() - start < msec) { - // Do nothing. - } - } else { - var start = Date.now(); - while (Date.now() - start < msec) { - // Do nothing. - } + var start = _emscripten_get_now(); + while (_emscripten_get_now() - start < useconds / 1000) { + // Do nothing. } - return 0; }, nanosleep__deps: ['usleep', '__setErrNo'], diff --git a/src/library_stack_trace.js b/src/library_stack_trace.js index 8a05fe7d1c9d3..a7ac2850b70f6 100644 --- a/src/library_stack_trace.js +++ b/src/library_stack_trace.js @@ -1,7 +1,7 @@ var LibraryStackTrace = { $demangle__deps: [ -#if MINIMAL_RUNTIME +#if MINIMAL_RUNTIME && !WASM_BACKEND '$stackSave', '$stackAlloc', '$stackRestore' #if ASSERTIONS , '$warnOnce' diff --git a/src/library_strings.js b/src/library_strings.js index 6fa0580cf0c1d..277946107901c 100644 --- a/src/library_strings.js +++ b/src/library_strings.js @@ -1,6 +1,7 @@ #if MINIMAL_RUNTIME #include "runtime_strings_extra.js" +#include "arrayUtils.js" mergeInto(LibraryManager.library, { $AsciiToString: AsciiToString, @@ -15,7 +16,9 @@ mergeInto(LibraryManager.library, { $allocateUTF8OnStack: allocateUTF8OnStack, $writeStringToMemory: writeStringToMemory, $writeArrayToMemory: writeArrayToMemory, - $writeAsciiToMemory: writeAsciiToMemory + $writeAsciiToMemory: writeAsciiToMemory, + $intArrayFromString: intArrayFromString, + $intArrayToString: intArrayToString }); #endif diff --git a/src/library_syscall.js b/src/library_syscall.js index ba8442ae44dc0..e147e6e4f1847 100644 --- a/src/library_syscall.js +++ b/src/library_syscall.js @@ -739,6 +739,9 @@ var SyscallsLibrary = { __syscall121: function(which, varargs) { // setdomainname return -{{{ cDefine('EPERM') }}}; }, +#if MINIMAL_RUNTIME + __syscall122__deps: ['$writeAsciiToMemory'], +#endif __syscall122: function(which, varargs) { // uname var buf = SYSCALLS.get(); if (!buf) return -{{{ cDefine('EFAULT') }}} @@ -1357,17 +1360,16 @@ var SyscallsLibrary = { // This is the set of syscalls that use the FS etc. APIs. The rest is in // library_wasi.js. -#if SYSCALLS_REQUIRE_FILESYSTEM == 0 +#if SYSCALLS_REQUIRE_FILESYSTEM == 0 && (!MINIMAL_RUNTIME || EXIT_RUNTIME) $flush_NO_FILESYSTEM: function() { // flush anything remaining in the buffers during shutdown - var fflush = Module["_fflush"]; - if (fflush) fflush(0); + if (typeof _fflush !== 'undefined') _fflush(0); var buffers = SYSCALLS.buffers; if (buffers[1].length) SYSCALLS.printChar(1, {{{ charCode("\n") }}}); if (buffers[2].length) SYSCALLS.printChar(2, {{{ charCode("\n") }}}); }, fd_write__deps: ['$flush_NO_FILESYSTEM'], -#if EXIT_RUNTIME == 1 && !MINIMAL_RUNTIME // MINIMAL_RUNTIME does not have __ATEXIT__ (so it does not get flushed stdout at program exit - programs in MINIMAL_RUNTIME do not have a concept of exiting) +#if EXIT_RUNTIME == 1 fd_write__postset: '__ATEXIT__.push(flush_NO_FILESYSTEM);', #endif #endif diff --git a/src/library_wasi.js b/src/library_wasi.js index 70632d115e2fb..d62581292594e 100644 --- a/src/library_wasi.js +++ b/src/library_wasi.js @@ -11,7 +11,7 @@ var WasiLibrary = { return _exit(code); }, - emscripten_get_environ__deps: ['$ENV'], + emscripten_get_environ__deps: ['$ENV', '_getExecutableName'], emscripten_get_environ: function() { if (!_emscripten_get_environ.strings) { // Default values. @@ -23,7 +23,7 @@ var WasiLibrary = { 'HOME': '/home/web_user', // Browser language detection #8751 'LANG': ((typeof navigator === 'object' && navigator.languages && navigator.languages[0]) || 'C').replace('-', '_') + '.UTF-8', - '_': thisProgram + '_': __getExecutableName() }; // Apply the user-provided values, if any. for (var x in ENV) { @@ -50,7 +50,11 @@ var WasiLibrary = { return 0; }, - environ_get__deps: ['emscripten_get_environ'], + environ_get__deps: ['emscripten_get_environ' +#if MINIMAL_RUNTIME + , '$writeAsciiToMemory' +#endif + ], environ_get: function(__environ, environ_buf) { var strings = _emscripten_get_environ(); var bufSize = 0; diff --git a/src/modules.js b/src/modules.js index 964746c1e4a00..129ce4db4fc83 100644 --- a/src/modules.js +++ b/src/modules.js @@ -376,21 +376,11 @@ function exportRuntime() { 'getValue', 'allocate', 'getMemory', - 'AsciiToString', - 'stringToAscii', 'UTF8ArrayToString', 'UTF8ToString', 'stringToUTF8Array', 'stringToUTF8', 'lengthBytesUTF8', - 'UTF16ToString', - 'stringToUTF16', - 'lengthBytesUTF16', - 'UTF32ToString', - 'stringToUTF32', - 'lengthBytesUTF32', - 'allocateUTF8', - 'allocateUTF8OnStack', 'stackTrace', 'addOnPreRun', 'addOnInit', @@ -436,10 +426,24 @@ function exportRuntime() { ]; if (!MINIMAL_RUNTIME) { - runtimeElements.push('warnOnce'); - runtimeElements.push('stackSave'); - runtimeElements.push('stackRestore'); - runtimeElements.push('stackAlloc'); + // MINIMAL_RUNTIME has moved these functions to library_strings.js + runtimeElements = runtimeElements.concat([ + 'warnOnce', + 'stackSave', + 'stackRestore', + 'stackAlloc', + 'AsciiToString', + 'stringToAscii', + 'UTF16ToString', + 'stringToUTF16', + 'lengthBytesUTF16', + 'UTF32ToString', + 'stringToUTF32', + 'lengthBytesUTF32', + 'allocateUTF8', + 'allocateUTF8OnStack' + ]); + if (USE_PTHREADS) { runtimeElements.push('establishStackSpace'); } diff --git a/src/postamble_minimal.js b/src/postamble_minimal.js index c21811c3fa02e..c004eff1c6f41 100644 --- a/src/postamble_minimal.js +++ b/src/postamble_minimal.js @@ -14,6 +14,22 @@ function run() { var ret = _proxy_main(); #else var ret = _main(); + +#if EXIT_RUNTIME + callRuntimeCallbacks(__ATEXIT__); + {{{ getQuoted('ATEXITS') }}} +#endif + +#if IN_TEST_HARNESS + // fflush() filesystem stdio for test harness, since there are existing tests that depend on this behavior. + // For production use, instead print full lines to avoid this kind of lazy behavior. + if (typeof _fflush !== 'undefined') _fflush(); +#endif + +#if ASSERTIONS + runtimeExited = true; +#endif + #endif #if STACK_OVERFLOW_CHECK diff --git a/src/preamble_minimal.js b/src/preamble_minimal.js index 2420615b652fd..2b2f5b4ac53df 100644 --- a/src/preamble_minimal.js +++ b/src/preamble_minimal.js @@ -185,6 +185,31 @@ var wasmOffsetConverter; #include "wasm_offset_converter.js" #endif +#if EXIT_RUNTIME + +function callRuntimeCallbacks(callbacks) { + while(callbacks.length > 0) { + var callback = callbacks.shift(); + if (typeof callback == 'function') { + callback(); + continue; + } + var func = callback.func; + if (typeof func === 'number') { + if (callback.arg === undefined) { + dynCall_v(func); + } else { + dynCall_vi(func, callback.arg); + } + } else { + func(callback.arg === undefined ? null : callback.arg); + } + } +} + +var __ATEXIT__ = []; // functions called during shutdown +#endif + #if ASSERTIONS var runtimeInitialized = false; diff --git a/src/promise_polyfill.js b/src/promise_polyfill.js index 8ebc4114c30ef..e4e3483ca209b 100644 --- a/src/promise_polyfill.js +++ b/src/promise_polyfill.js @@ -23,6 +23,8 @@ // THE SOFTWARE. //============================================================================== +/** @suppress{duplicate} This is already defined in from Closure's built-in + externs.zip//es6.js, Closure should not yell when seeing this again. */ var Promise = (function() { function noop() {} diff --git a/tests/test_core.py b/tests/test_core.py index 2e8b667d449f2..25671ddce7c37 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -233,6 +233,21 @@ def decorated(self, *args, **kwargs): return decorator +def no_minimal_runtime(note): + assert not callable(note) + + def decorator(f): + assert callable(f) + + @wraps(f) + def decorated(self, *args, **kwargs): + if 'MINIMAL_RUNTIME=1' in self.emcc_args or self.get_setting('MINIMAL_RUNTIME'): + self.skipTest(note) + f(self, *args, **kwargs) + return decorated + return decorator + + class TestCoreBase(RunnerCore): def is_wasm2js(self): return self.is_wasm_backend() and not self.get_setting('WASM') @@ -1971,7 +1986,7 @@ def test_em_asm_arguments_side_effects(self): def test_em_js(self, args): if 'MAIN_MODULE' in args and self.get_setting('WASM') == 0: self.skipTest('main module support for non-wasm') - self.emcc_args += args + self.emcc_args += args + ['-s', 'EXPORTED_FUNCTIONS=["_main","_malloc"]'] self.do_run_in_out_file_test('tests', 'core', 'test_em_js') self.do_run_in_out_file_test('tests', 'core', 'test_em_js', force_c=True) @@ -5133,6 +5148,7 @@ def test_utime(self): src = open(path_from_root('tests', 'utime', 'test_utime.c')).read() self.do_run(src, 'success', force_c=True) + @no_minimal_runtime('MINIMAL_RUNTIME does not have getValue() and setValue() (TODO add it to a JS library function to get it in)') def test_utf(self): self.banned_js_engines = [SPIDERMONKEY_ENGINE] # only node handles utf well self.set_setting('EXPORTED_FUNCTIONS', ['_main', '_malloc']) @@ -5140,13 +5156,19 @@ def test_utf(self): self.do_run_in_out_file_test('tests', 'core', 'test_utf') def test_utf32(self): - self.set_setting('EXTRA_EXPORTED_RUNTIME_METHODS', ['UTF32ToString', 'stringToUTF32', 'lengthBytesUTF32']) + if self.get_setting('MINIMAL_RUNTIME'): + self.set_setting('DEFAULT_LIBRARY_FUNCS_TO_INCLUDE', ['$UTF32ToString', '$stringToUTF32', '$lengthBytesUTF32']) + else: + self.set_setting('EXTRA_EXPORTED_RUNTIME_METHODS', ['UTF32ToString', 'stringToUTF32', 'lengthBytesUTF32']) self.do_run(open(path_from_root('tests', 'utf32.cpp')).read(), 'OK.') self.do_run(open(path_from_root('tests', 'utf32.cpp')).read(), 'OK.', args=['-fshort-wchar']) def test_utf8(self): - self.set_setting('EXTRA_EXPORTED_RUNTIME_METHODS', - ['UTF8ToString', 'stringToUTF8', 'AsciiToString', 'stringToAscii']) + if self.get_setting('MINIMAL_RUNTIME'): + self.set_setting('DEFAULT_LIBRARY_FUNCS_TO_INCLUDE', ['$AsciiToString', '$stringToAscii', '$writeAsciiToMemory']) + else: + self.set_setting('EXTRA_EXPORTED_RUNTIME_METHODS', + ['UTF8ToString', 'stringToUTF8', 'AsciiToString', 'stringToAscii']) self.emcc_args += ['-std=c++11'] self.do_run(open(path_from_root('tests', 'utf8.cpp')).read(), 'OK.') @@ -6588,6 +6610,7 @@ def test_EXTRA_EXPORTED_RUNTIME_METHODS(self): self.do_run_in_out_file_test('tests', 'core', 'EXTRA_EXPORTED_RUNTIME_METHODS') @no_fastcomp('fails mysteriously on fastcomp (dynCall_viji is not defined); ignored, because fastcomp is deprecated') + @no_minimal_runtime('MINIMAL_RUNTIME does not blindly export all symbols to Module to save code size') def test_dyncall_specific(self): emcc_args = self.emcc_args[:] for which, exported_runtime_methods in [ diff --git a/tests/test_other.py b/tests/test_other.py index c75c4db0d4869..2a3cd2e76ed67 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -9624,11 +9624,11 @@ def test_minimal_runtime_code_size(self): ] else: test_cases = [ - (asmjs + opts, hello_world_sources, {'a.html': 1223, 'a.js': 289, 'a.asm.js': 113, 'a.mem': 6}), - (opts, hello_world_sources, {'a.html': 1205, 'a.js': 633, 'a.wasm': 86}), - (asmjs + opts, hello_webgl_sources, {'a.html': 1353, 'a.js': 4921, 'a.asm.js': 11129, 'a.mem': 321}), - (opts, hello_webgl_sources, {'a.html': 1335, 'a.js': 4874, 'a.wasm': 8932}), - (opts, hello_webgl2_sources, {'a.html': 1335, 'a.js': 5361, 'a.wasm': 8932}) # Compare how WebGL2 sizes stack up with WebGL 1 + (asmjs + opts, hello_world_sources, {'a.html': 1222, 'a.js': 289, 'a.asm.js': 113, 'a.mem': 6}), + (opts, hello_world_sources, {'a.html': 1204, 'a.js': 630, 'a.wasm': 86}), + (asmjs + opts, hello_webgl_sources, {'a.html': 1352, 'a.js': 4896, 'a.asm.js': 11129, 'a.mem': 321}), + (opts, hello_webgl_sources, {'a.html': 1334, 'a.js': 4850, 'a.wasm': 8932}), + (opts, hello_webgl2_sources, {'a.html': 1334, 'a.js': 5357, 'a.wasm': 8932}) # Compare how WebGL2 sizes stack up with WebGL 1 ] success = True diff --git a/tests/utf32.cpp b/tests/utf32.cpp index 64674bea03ef6..6acd298a1e529 100644 --- a/tests/utf32.cpp +++ b/tests/utf32.cpp @@ -22,9 +22,9 @@ int main() { utf32 *memory = new utf32[wstr.length()+1]; EM_ASM({ - var str = Module.UTF32ToString($0); + var str = UTF32ToString($0); out(str); - var numBytesWritten = Module.stringToUTF32(str, $1, $2); + var numBytesWritten = stringToUTF32(str, $1, $2); if (numBytesWritten != 23*4) throw 'stringToUTF32 wrote an invalid length ' + numBytesWritten; }, wstr.c_str(), memory, (wstr.length()+1)*sizeof(utf32)); @@ -37,9 +37,9 @@ int main() { } EM_ASM({ - var str = Module.UTF32ToString($0); + var str = UTF32ToString($0); out(str); - var numBytesWritten = Module.stringToUTF32(str, $1, $2); + var numBytesWritten = stringToUTF32(str, $1, $2); if (numBytesWritten != 5*4) throw 'stringToUTF32 wrote an invalid length ' + numBytesWritten; }, wstr.c_str(), memory, 6*sizeof(utf32)); assert(memory[5] == 0); @@ -49,9 +49,9 @@ int main() { utf16 *memory = new utf16[2*wstr.length()+1]; EM_ASM({ - var str = Module.UTF16ToString($0); + var str = UTF16ToString($0); out(str); - var numBytesWritten = Module.stringToUTF16(str, $1, $2); + var numBytesWritten = stringToUTF16(str, $1, $2); if (numBytesWritten != 25*2) throw 'stringToUTF16 wrote an invalid length ' + numBytesWritten; }, wstr.c_str(), memory, (2*wstr.length()+1)*sizeof(utf16)); @@ -64,9 +64,9 @@ int main() { } EM_ASM({ - var str = Module.UTF16ToString($0); + var str = UTF16ToString($0); out(str); - var numBytesWritten = Module.stringToUTF16(str, $1, $2); + var numBytesWritten = stringToUTF16(str, $1, $2); if (numBytesWritten != 5*2) throw 'stringToUTF16 wrote an invalid length ' + numBytesWritten; }, wstr.c_str(), memory, 6*sizeof(utf16)); assert(memory[5] == 0); diff --git a/tests/utf8.cpp b/tests/utf8.cpp index ea9335f48f369..fabb1412c6028 100644 --- a/tests/utf8.cpp +++ b/tests/utf8.cpp @@ -14,24 +14,24 @@ int main() { const char latin1String[] = "\x26\xA0\xF7"; EM_ASM({ - var str = Module.AsciiToString($0); + var str = AsciiToString($0); assert(str === "\\x26\\xA0\\xF7"); }, latin1String); const char asciiString[] = "Hello world!"; char asciiString2[128] = {}; EM_ASM({ - var str = Module.AsciiToString($0); + var str = AsciiToString($0); out(str); - Module.stringToAscii(str, $1); + stringToAscii(str, $1); }, asciiString, asciiString2); assert(!strcmp(asciiString, asciiString2)); char asciiString3[128] = {}; EM_ASM({ - var str = Module.UTF8ToString($0); + var str = UTF8ToString($0); out(str); - var numBytesWritten = Module.stringToUTF8(str, $1, $2); + var numBytesWritten = stringToUTF8(str, $1, $2); if (numBytesWritten != 12) throw 'stringToUTF8 wrote an invalid length ' + numBytesWritten; }, asciiString, asciiString3, 128); assert(!strcmp(asciiString, asciiString3)); @@ -39,9 +39,9 @@ int main() { const char utf8String[] = u8"Hyv\u00E4\u00E4 p\u00E4iv\u00E4\u00E4! T\u00F6\u00F6\u00F6\u00F6t! abc\u2603\u20AC\U0002007C123 --- abc\u2603\u20AC\U0002007C123."; // U+2603 is snowman, U+20AC is the Euro sign, U+2007C is a Chinese Han character that looks like three raindrops. char utf8String2[128] = {}; EM_ASM({ - var str = Module.UTF8ToString($0); + var str = UTF8ToString($0); out(str); - var numBytesWritten = Module.stringToUTF8(str, $1, $2); + var numBytesWritten = stringToUTF8(str, $1, $2); if (numBytesWritten != 69) throw 'stringToUTF8 wrote an invalid length ' + numBytesWritten; }, utf8String, utf8String2, 128); assert(strlen(utf8String) == strlen(utf8String2)); @@ -52,18 +52,18 @@ int main() { // Test that text gets properly cut off if output buffer is too small. EM_ASM({ - var str = Module.UTF8ToString($0); + var str = UTF8ToString($0); out(str); - var numBytesWritten = Module.stringToUTF8(str, $1, $2); + var numBytesWritten = stringToUTF8(str, $1, $2); if (numBytesWritten != 9) throw 'stringToUTF8 wrote an invalid length ' + numBytesWritten; }, utf8String, utf8String2, 10); assert(strlen(utf8String2) == 9); // Zero-length string. EM_ASM({ - var str = Module.UTF8ToString($0); + var str = UTF8ToString($0); out(str); - var numBytesWritten = Module.stringToUTF8(str, $1, $2); + var numBytesWritten = stringToUTF8(str, $1, $2); if (numBytesWritten != 0) throw 'stringToUTF8 wrote an invalid length ' + numBytesWritten; }, utf8String, utf8String2, 1); assert(utf8String2[0] == 0); @@ -71,9 +71,9 @@ int main() { // No bytes output. utf8String2[0] = 'X'; EM_ASM({ - var str = Module.UTF8ToString($0); + var str = UTF8ToString($0); out(str); - var numBytesWritten = Module.stringToUTF8(str, $1, $2); + var numBytesWritten = stringToUTF8(str, $1, $2); if (numBytesWritten != 0) throw 'stringToUTF8 wrote an invalid length ' + numBytesWritten; }, utf8String, utf8String2, 0); assert(utf8String2[0] == 'X');