diff --git a/AUTHORS b/AUTHORS index 6d8817dbc71a7..b5d7c1238bf72 100644 --- a/AUTHORS +++ b/AUTHORS @@ -159,4 +159,5 @@ a license to everyone to use it as detailed in LICENSE.) * Gauthier Billot * Árpád Goretity * Nicholas Wilson +* Aaron Mandle diff --git a/emscripten-version.txt b/emscripten-version.txt index 5416318ab2a57..7ae54502c613c 100644 --- a/emscripten-version.txt +++ b/emscripten-version.txt @@ -1,2 +1,2 @@ -1.23.5 +1.24.0 diff --git a/site/source/docs/api_reference/module.rst b/site/source/docs/api_reference/module.rst index 1605474807ad6..29bffc0fac6dd 100644 --- a/site/source/docs/api_reference/module.rst +++ b/site/source/docs/api_reference/module.rst @@ -85,11 +85,14 @@ The following ``Module`` attributes affect code execution. This is the "prefix" URL for a preloaded data file that is hosted separately from its JavaScript and HTML files (it includes the full path up to, but not including, the data file). See :ref:`packaging-files-data-file-location` for more information. +.. js:attribute:: Module.locateFile + + If set, this method will be called when the runtime needs to load either a file generated by the file packager (this is a generalization of ``Module.filePackagePrefixURL``), or the ``.mem`` memory init file. In both cases the function receives the URL, and should return the actual URL. This lets you host file packages or the ``.mem`` file on a different location than the current directory (which is the default expectation), for example if you want to host them on a CDN. .. js:attribute:: Module.logReadFiles If set, :js:attr:`Module.printErr` will log when any file is read. - + Other methods ============= @@ -99,4 +102,4 @@ Other methods This method should be called to destroy C++ objects created in JavaScript using :ref:`WebIDL bindings `. If this method is not called, an object may be garbage collected, but its destructor will not be called. :param obj: The JavaScript-wrapped C++ object to be destroyed. - \ No newline at end of file + diff --git a/src/library.js b/src/library.js index e7e2e3e4a4d99..e3e2446d88881 100644 --- a/src/library.js +++ b/src/library.js @@ -5273,6 +5273,8 @@ LibraryManager.library = { // size_t strftime(char *restrict s, size_t maxsize, const char *restrict format, const struct tm *restrict timeptr); // http://pubs.opengroup.org/onlinepubs/009695399/functions/strftime.html + var tm_zone = {{{ makeGetValue('tm', C_STRUCTS.tm.tm_zone, 'i32') }}}; + var date = { tm_sec: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_sec, 'i32') }}}, tm_min: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_min, 'i32') }}}, @@ -5284,7 +5286,7 @@ LibraryManager.library = { tm_yday: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_yday, 'i32') }}}, tm_isdst: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_isdst, 'i32') }}}, tm_gmtoff: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_gmtoff, 'i32') }}}, - tm_zone: Pointer_stringify( {{{ makeGetValue('tm', C_STRUCTS.tm.tm_zone, 'i32') }}} ) + tm_zone: tm_zone ? Pointer_stringify(tm_zone) : '' }; var pattern = Pointer_stringify(format); diff --git a/src/library_idbfs.js b/src/library_idbfs.js index 0ce13db85025f..277cf68971287 100644 --- a/src/library_idbfs.js +++ b/src/library_idbfs.js @@ -157,6 +157,7 @@ mergeInto(LibraryManager.library, { return callback(new Error('node type not supported')); } + FS.chmod(path, entry.mode); FS.utime(path, entry.timestamp, entry.timestamp); } catch (e) { return callback(e); diff --git a/src/postamble.js b/src/postamble.js index 37aacf3bcf40b..f751bad6a06d5 100644 --- a/src/postamble.js +++ b/src/postamble.js @@ -2,7 +2,9 @@ // === Auto-generated postamble setup entry stuff === if (memoryInitializer) { - if (Module['memoryInitializerPrefixURL']) { + if (typeof Module['locateFile'] === 'function') { + memoryInitializer = Module['locateFile'](memoryInitializer); + } else if (Module['memoryInitializerPrefixURL']) { memoryInitializer = Module['memoryInitializerPrefixURL'] + memoryInitializer; } if (ENVIRONMENT_IS_NODE || ENVIRONMENT_IS_SHELL) { diff --git a/tests/core/test_posixtime.in b/tests/core/test_posixtime.c similarity index 100% rename from tests/core/test_posixtime.in rename to tests/core/test_posixtime.c diff --git a/tests/core/test_posixtime_no_monotonic.out b/tests/core/test_posixtime_no_monotonic.out new file mode 100644 index 0000000000000..52a47a143b79d --- /dev/null +++ b/tests/core/test_posixtime_no_monotonic.out @@ -0,0 +1,17 @@ +Tests for clockid_t=0 +----------------- +clock_getres resolution OK +clock_gettime OK +clock_settime failed with EPERM (OK) + +Tests for clockid_t=1 +----------------- +clock_getres failed +clock_gettime failed +clock_settime failed with EINVAL (OK) + +Tests for clockid_t=42 +----------------- +clock_gettime failed with EINVAL (OK) +clock_getres failed with EINVAL (OK) +clock_settime failed with EINVAL (OK) diff --git a/tests/runner.py b/tests/runner.py index ce7959367da59..b84a1ff796367 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -466,10 +466,13 @@ def do_run(self, src, expected_output, args=[], output_nicerizer=None, output_pr js_engines = filter(lambda engine: engine not in self.banned_js_engines, js_engines) if len(js_engines) == 0: return self.skip('No JS engine present to run this test with. Check %s and the paths therein.' % EM_CONFIG) for engine in js_engines: - #print engine js_output = self.run_generated_code(engine, filename + '.o.js', args, output_nicerizer=output_nicerizer, assert_returncode=assert_returncode) - self.assertContained(expected_output, js_output.replace('\r\n', '\n')) - self.assertNotContained('ERROR', js_output) + try: + self.assertContained(expected_output, js_output.replace('\r\n', '\n')) + self.assertNotContained('ERROR', js_output) + except Exception, e: + print '(test did not pass in JS engine: %s)' % engine + raise e #shutil.rmtree(dirname) # TODO: leave no trace in memory. But for now nice for debugging diff --git a/tests/sockets/p2p/broker/p2p-broker.js b/tests/sockets/p2p/broker/p2p-broker.js index 028eb25ba6c10..ec37db987a694 100644 --- a/tests/sockets/p2p/broker/p2p-broker.js +++ b/tests/sockets/p2p/broker/p2p-broker.js @@ -4,7 +4,7 @@ var https = require('https'); var SSL_KEY = 'ssl/ssl.key'; var SSL_CERT = 'ssl/ssl-unified.crt'; -var PORT = 8080; +var PORT = 8182; var sslSupported = false; if(fs.existsSync(SSL_KEY) && fs.existsSync(SSL_CERT) && fs.statSync(SSL_KEY).isFile() && fs.statSync(SSL_CERT).isFile()) { @@ -28,7 +28,7 @@ if(sslSupported) { console.info('ssl mode enabled'); } else { app = require('http').createServer(handler); - port = 8080; + port = 8182; console.info('ssl mode disabled'); } console.info('listening on port', port); diff --git a/tests/test_browser.py b/tests/test_browser.py index 26405336ada60..29953bfaadea6 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -1992,3 +1992,34 @@ def test_wget(self): with open(os.path.join(self.get_dir(), 'test.txt'), 'w') as f: f.write('emscripten') self.btest(path_from_root('tests', 'test_wget.c'), expected='1', args=['-s', 'ASYNCIFY=1']) + + def test_locate_file(self): + self.clear() + open('src.cpp', 'w').write(self.with_report_result(r''' + #include + #include + #include + int main() { + FILE *f = fopen("data.txt", "r"); + assert(f && "could not open file"); + char buf[100]; + int num = fread(buf, 1, 20, f); + assert(num == 20 && "could not read 20 bytes"); + buf[20] = 0; + fclose(f); + int result = !strcmp("load me right before", buf); + printf("|%s| : %d\n", buf, result); + REPORT_RESULT(); + return 0; + } + ''')) + open('data.txt', 'w').write('load me right before...') + open('pre.js', 'w').write('Module.locateFile = function(x) { return "sub/" + x };') + Popen([PYTHON, FILE_PACKAGER, 'test.data', '--preload', 'data.txt'], stdout=open('data.js', 'w')).communicate() + # put pre.js first, then the file packager data, so locateFile is there for the file loading code + Popen([PYTHON, EMCC, 'src.cpp', '-O2', '-g', '--pre-js', 'pre.js', '--pre-js', 'data.js', '-o', 'page.html']).communicate() + os.mkdir('sub') + shutil.move('page.html.mem', os.path.join('sub', 'page.html.mem')) + shutil.move('test.data', os.path.join('sub', 'test.data')) + self.run_browser('page.html', None, '/report_result?1') + diff --git a/tests/test_core.py b/tests/test_core.py index ad43c3e2f3b07..142811bacb915 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -4634,14 +4634,19 @@ def test_unistd_misc(self): def test_posixtime(self): test_path = path_from_root('tests', 'core', 'test_posixtime') - src, output = (test_path + s for s in ('.in', '.out')) - + src, output = (test_path + s for s in ('.c', '.out')) + self.banned_js_engines = [V8_ENGINE] # v8 lacks monotonic time self.do_run_from_file(src, output) + if V8_ENGINE in JS_ENGINES: + self.banned_js_engines = filter(lambda engine: engine != V8_ENGINE, JS_ENGINES) + self.do_run_from_file(src, test_path + '_no_monotonic.out') + else: + print '(no v8, skipping no-monotonic case)' + def test_uname(self): test_path = path_from_root('tests', 'core', 'test_uname') src, output = (test_path + s for s in ('.in', '.out')) - self.do_run_from_file(src, output) def test_env(self): diff --git a/tests/test_sockets.py b/tests/test_sockets.py index 7e248e22b2fc3..dad89a369c5b0 100644 --- a/tests/test_sockets.py +++ b/tests/test_sockets.py @@ -378,7 +378,7 @@ def test_webrtc(self): open(os.path.join(self.get_dir(), 'host_pre.js'), 'w').write(''' var Module = { webrtc: { - broker: 'http://localhost:8080', + broker: 'http://localhost:8182', session: undefined, onpeer: function(peer, route) { window.open('http://localhost:8888/peer.html?' + route); @@ -402,7 +402,7 @@ def test_webrtc(self): open(os.path.join(self.get_dir(), 'peer_pre.js'), 'w').write(''' var Module = { webrtc: { - broker: 'http://localhost:8080', + broker: 'http://localhost:8182', session: window.location.toString().split('?')[1], onpeer: function(peer, route) { peer.connect(Module['webrtc']['session']); diff --git a/tools/file_packager.py b/tools/file_packager.py index ae15b76c6578f..4e348b474086f 100644 --- a/tools/file_packager.py +++ b/tools/file_packager.py @@ -488,8 +488,12 @@ def was_seen(name): } var PACKAGE_NAME = '%s'; var REMOTE_PACKAGE_BASE = '%s'; - var REMOTE_PACKAGE_NAME = typeof Module['locateFilePackage'] === 'function' ? - Module['locateFilePackage'](REMOTE_PACKAGE_BASE) : + if (typeof Module['locateFilePackage'] === 'function' && !Module['locateFile']) { + Module['locateFile'] = Module['locateFilePackage']; + Module.printErr('warning: you defined Module.locateFilePackage, that has been renamed to Module.locateFile (using your locateFilePackage for now)'); + } + var REMOTE_PACKAGE_NAME = typeof Module['locateFile'] === 'function' ? + Module['locateFile'](REMOTE_PACKAGE_BASE) : ((Module['filePackagePrefixURL'] || '') + REMOTE_PACKAGE_BASE); var REMOTE_PACKAGE_SIZE = %d; var PACKAGE_UUID = '%s';