diff --git a/emcc.py b/emcc.py index 49a0a288135e1..777fa36385a27 100755 --- a/emcc.py +++ b/emcc.py @@ -2604,24 +2604,43 @@ def modularize(): final = final + '.modular.js' f = open(final, 'w') - # Included code may refer to Module (e.g. from file packager), so alias it - f.write('''var %(EXPORT_NAME)s = function(%(EXPORT_NAME)s) { + src = ''' +function(%(EXPORT_NAME)s) { %(EXPORT_NAME)s = %(EXPORT_NAME)s || {}; %(src)s return %(EXPORT_NAME)s; -}; -// When MODULARIZE, this JS may be executed later, after document.currentScript -// is gone, so we save it. -%(EXPORT_NAME)s = %(EXPORT_NAME)s.bind({ - _scriptDir: typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined -})%(instantiate)s; +} ''' % { 'EXPORT_NAME': shared.Settings.EXPORT_NAME, - 'src': src, - 'instantiate': '()' if shared.Settings.MODULARIZE_INSTANCE else '' - }) + 'src': src + } + + if not shared.Settings.MODULARIZE_INSTANCE: + # When MODULARIZE this JS may be executed later, + # after document.currentScript is gone, so we save it. + # (when MODULARIZE_INSTANCE, an instance is created + # immediately anyhow, like in non-modularize mode) + src = ''' +var %(EXPORT_NAME)s = (function() { + var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; + return (%(src)s); +})(); +''' % { + 'EXPORT_NAME': shared.Settings.EXPORT_NAME, + 'src': src + } + else: + # Create the MODULARIZE_INSTANCE instance + src = ''' +var %(EXPORT_NAME)s = (%(src)s)(); +''' % { + 'EXPORT_NAME': shared.Settings.EXPORT_NAME, + 'src': src + } + + f.write(src) # Export using a UMD style export, or ES6 exports if selected if shared.Settings.EXPORT_ES6: diff --git a/src/closure-externs.js b/src/closure-externs.js index 24721dcb9575b..dcc8aede9232f 100644 --- a/src/closure-externs.js +++ b/src/closure-externs.js @@ -1073,6 +1073,10 @@ var wakaUnknownAfter; * @suppress {undefinedVars} */ var wakaUnknownBefore; +/** + * @suppress {undefinedVars} + */ +var _scriptDir; /** * @suppress {duplicate} */ diff --git a/src/shell.js b/src/shell.js index adcb3c7aad6b0..019f94bbf2742 100644 --- a/src/shell.js +++ b/src/shell.js @@ -237,11 +237,13 @@ if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { scriptDirectory = self.location.href; } #if MODULARIZE - // When MODULARIZE, this JS may be executed later, after document.currentScript +#if MODULARIZE_INSTANCE == 0 + // When MODULARIZE (and not _INSTANCE), this JS may be executed later, after document.currentScript // is gone, so we saved it, and we use it here instead of any other info. - if (this['_scriptDir']) { - scriptDirectory = this['_scriptDir']; + if (_scriptDir) { + scriptDirectory = _scriptDir; } +#endif #endif // blob urls look like blob:http://site.com/etc/etc and we cannot infer anything from them. // otherwise, slice off the final part of the url to find the script directory. diff --git a/tests/test_browser.py b/tests/test_browser.py index b0c619333c4ef..f39903dc9a368 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -3950,46 +3950,53 @@ def test_browser_run_from_different_directory(self): src = open('test.html').read() # Make sure JS is loaded from subdirectory open('test-subdir.html', 'w').write(src.replace('test.js', 'subdir/test.js')) - self.run_browser('test-subdir.html', None, '/report_result?0') # Similar to `test_browser_run_from_different_directory`, but asynchronous because of `-s MODULARIZE=1` def test_browser_run_from_different_directory_async(self): src = open(path_from_root('tests', 'browser_test_hello_world.c')).read() open('test.c', 'w').write(self.with_report_result(src)) - # compile the code with the modularize feature and the preload-file option enabled - Popen([PYTHON, EMCC, 'test.c', '-o', 'test.js', '-s', 'MODULARIZE=1', '-O3']).communicate() - if not os.path.exists('subdir'): - os.mkdir('subdir') - shutil.move('test.js', os.path.join('subdir', 'test.js')) - shutil.move('test.wasm', os.path.join('subdir', 'test.wasm')) - # Make sure JS is loaded from subdirectory - open('test-subdir.html', 'w').write(''' - - - ''') - - self.run_browser('test-subdir.html', None, '/report_result?0') + for args, creations in [ + (['-s', 'MODULARIZE=1'], [ + 'Module();', # documented way for using modularize + 'new Module();' # not documented as working, but we support it + ]), + (['-s', 'MODULARIZE_INSTANCE=1'], ['']) # instance: no need to create anything + ]: + print(args) + # compile the code with the modularize feature and the preload-file option enabled + Popen([PYTHON, EMCC, 'test.c', '-o', 'test.js', '-O3'] + args).communicate() + if not os.path.exists('subdir'): + os.mkdir('subdir') + shutil.move('test.js', os.path.join('subdir', 'test.js')) + shutil.move('test.wasm', os.path.join('subdir', 'test.wasm')) + for creation in creations: + print(creation) + # Make sure JS is loaded from subdirectory + open('test-subdir.html', 'w').write(''' + + + ''' % creation) + self.run_browser('test-subdir.html', None, '/report_result?0') # Similar to `test_browser_run_from_different_directory`, but # also also we eval the initial code, so currentScript is not present. That prevents us # from finding the file in a subdir, but here we at least check we do not regress compared to the # normal case of finding in the current dir. - # In addition, check for new Module(), which overrides the bind() and replaces the object - # which saved the _scriptDir. Again, we can't get the script dir that way, but at least we - # should not regress compared to the normal case. def test_browser_modularize_no_current_script(self): src = open(path_from_root('tests', 'browser_test_hello_world.c')).read() open('test.c', 'w').write(self.with_report_result(src)) - # compile the code with the modularize feature and the preload-file option enabled - Popen([PYTHON, EMCC, 'test.c', '-o', 'test.js', '-s', 'MODULARIZE=1']).communicate() - for creation in ( - 'Module();', - 'new Module();' - ): - print(creation) + # test both modularize (and creating an instance) and modularize-instance + # (which creates by itself) + for args, creation in [ + (['-s', 'MODULARIZE=1'], 'Module();'), + (['-s', 'MODULARIZE_INSTANCE=1'], '') + ]: + print(args, creation) + # compile the code with the modularize feature and the preload-file option enabled + Popen([PYTHON, EMCC, 'test.c', '-o', 'test.js'] + args).communicate() open('test.html', 'w').write('''