diff --git a/ChangeLog.md b/ChangeLog.md index 2769497f80ea0..0014c1737589f 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -17,6 +17,9 @@ See docs/process.md for how version tagging works. Current Trunk ------------- +- Remove `MODULARIZE_INSTANCE` build option (#11037). This was a seldom used + option that was complicating the logic for `MODULARIZE`. Module instances can + be created by using `MODULARIZE` and calling the factory function explicitly. 1.39.14: 05/01/2020 ------------------- diff --git a/emcc.py b/emcc.py index ea88596e703af..b09d10aa860d5 100755 --- a/emcc.py +++ b/emcc.py @@ -1294,11 +1294,8 @@ def has_c_source(args): else: shared.Settings.EXPORTED_RUNTIME_METHODS += ['writeStackCookie', 'checkStackCookie', 'abortStackOverflow'] - if shared.Settings.MODULARIZE_INSTANCE: - shared.Settings.MODULARIZE = 1 - if shared.Settings.MODULARIZE: - assert not options.proxy_to_worker, '-s MODULARIZE=1 and -s MODULARIZE_INSTANCE=1 are not compatible with --proxy-to-worker (if you want to run in a worker with -s MODULARIZE=1, you likely want to do the worker side setup manually)' + assert not options.proxy_to_worker, '-s MODULARIZE=1 is not compatible with --proxy-to-worker (if you want to run in a worker with -s MODULARIZE=1, you likely want to do the worker side setup manually)' # MODULARIZE's .then() method uses onRuntimeInitialized currently, so make sure # it is expected to be used. shared.Settings.INCOMING_MODULE_JS_API += ['onRuntimeInitialized'] @@ -1702,7 +1699,7 @@ def include_and_export(name): if not shared.Settings.WASM and not shared.Settings.WASM_BACKEND: options.memory_init_file = True - if shared.Settings.MODULARIZE and not shared.Settings.MODULARIZE_INSTANCE and shared.Settings.EXPORT_NAME == 'Module' and final_suffix == '.html' and \ + if shared.Settings.MODULARIZE and shared.Settings.EXPORT_NAME == 'Module' and final_suffix == '.html' and \ (options.shell_path == shared.path_from_root('src', 'shell.html') or options.shell_path == shared.path_from_root('src', 'shell_minimal.html')): exit_with_error('Due to collision in variable name "Module", the shell file "' + options.shell_path + '" is not compatible with build options "-s MODULARIZE=1 -s EXPORT_NAME=Module". Either provide your own shell file, change the name of the export to something else to avoid the name collision. (see https://github.com/emscripten-core/emscripten/issues/7950 for details)') @@ -3407,47 +3404,32 @@ def modularize(): 'exports_object': exports_object } - if not shared.Settings.MODULARIZE_INSTANCE: - if shared.Settings.MINIMAL_RUNTIME and not shared.Settings.USE_PTHREADS: - # Single threaded MINIMAL_RUNTIME programs do not need access to - # document.currentScript, so a simple export declaration is enough. - src = 'var %s=%s' % (shared.Settings.EXPORT_NAME, src) + if shared.Settings.MINIMAL_RUNTIME and not shared.Settings.USE_PTHREADS: + # Single threaded MINIMAL_RUNTIME programs do not need access to + # document.currentScript, so a simple export declaration is enough. + src = 'var %s=%s' % (shared.Settings.EXPORT_NAME, src) + else: + script_url_node = "" + # When MODULARIZE this JS may be executed later, + # after document.currentScript is gone, so we save it. + # In EXPORT_ES6 + USE_PTHREADS the 'thread' is actually an ES6 module webworker running in strict mode, + # so doesn't have access to 'document'. In this case use 'import.meta' instead. + if shared.Settings.EXPORT_ES6 and shared.Settings.USE_ES6_IMPORT_META: + script_url = "import.meta.url" else: - script_url_node = "" - # 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) - # In EXPORT_ES6 + USE_PTHREADS the 'thread' is actually an ES6 module webworker running in strict mode, - # so doesn't have access to 'document'. In this case use 'import.meta' instead. - if shared.Settings.EXPORT_ES6 and shared.Settings.USE_ES6_IMPORT_META: - script_url = "import.meta.url" - else: - script_url = "typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined" - if shared.Settings.target_environment_may_be('node'): - script_url_node = "if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename;" - src = ''' + script_url = "typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined" + if shared.Settings.target_environment_may_be('node'): + script_url_node = "if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename;" + src = ''' var %(EXPORT_NAME)s = (function() { var _scriptDir = %(script_url)s; %(script_url_node)s return (%(src)s); })(); -''' % { - 'EXPORT_NAME': shared.Settings.EXPORT_NAME, - 'script_url': script_url, - 'script_url_node': script_url_node, - 'src': src - } - else: - # Create the MODULARIZE_INSTANCE instance - # Note that we notice the global Module object, just like in normal - # non-MODULARIZE mode (while MODULARIZE has the user create the instances, - # and the user can decide whether to use Module there or something - # else etc.). - src = ''' -var %(EXPORT_NAME)s = (%(src)s)(typeof %(EXPORT_NAME)s === 'object' ? %(EXPORT_NAME)s : {}); ''' % { 'EXPORT_NAME': shared.Settings.EXPORT_NAME, + 'script_url': script_url, + 'script_url_node': script_url_node, 'src': src } @@ -3487,7 +3469,7 @@ def module_export_name_substitution(): src = re.sub(r'{[\'"]?__EMSCRIPTEN_PRIVATE_MODULE_EXPORT_NAME_SUBSTITUTION__[\'"]?:1}', replacement, src) # For Node.js and other shell environments, create an unminified Module object so that # loading external .asm.js file that assigns to Module['asm'] works even when Closure is used. - if shared.Settings.MINIMAL_RUNTIME and not shared.Settings.MODULARIZE_INSTANCE and (shared.Settings.target_environment_may_be('node') or shared.Settings.target_environment_may_be('shell')): + if shared.Settings.MINIMAL_RUNTIME and (shared.Settings.target_environment_may_be('node') or shared.Settings.target_environment_may_be('shell')): src = 'if(typeof Module==="undefined"){var Module={};}' + src f.write(src) save_intermediate('module_export_name_substitution') diff --git a/src/postamble.js b/src/postamble.js index b515f043d1a7b..a0b998bc2b83e 100644 --- a/src/postamble.js +++ b/src/postamble.js @@ -122,7 +122,6 @@ if (memoryInitializer) { var calledRun; #if MODULARIZE -#if MODULARIZE_INSTANCE == 0 // Modularize mode returns a function, which can be called to // create instances. The instances provide a then() method, // must like a Promise, that receives a callback. The callback @@ -149,7 +148,6 @@ Module['then'] = function(func) { return Module; }; #endif -#endif /** * @constructor diff --git a/src/settings.js b/src/settings.js index 1c1d7b2694946..919520c661c99 100644 --- a/src/settings.js +++ b/src/settings.js @@ -1081,21 +1081,9 @@ var DETERMINISTIC = 0; // Note that in MODULARIZE mode we do *not* look at the global `Module` // object, so if you define things there they will be ignored. The reason // is that you will be constructing the instances manually, and can -// provide Module there, or something else, as you want. This differs -// in MODULARIZE_INSTANCE mode, where we *do* look at the global, since -// as in non-MODULARIZE mode there is just one global instance, and it -// is constructed by the setup code. +// provide Module there, or something else, as you want. var MODULARIZE = 0; -// Similar to MODULARIZE, but while that mode exports a function, with which you -// can create multiple instances, this option exports a singleton instance. In -// other words, it's the same as if you used MODULARIZE and did EXPORT_NAME = -// EXPORT_NAME() to create the instance manually. -// -// Note that the promise-like API MODULARIZE provides isn't available here -// (since you aren't creating the instance yourself). -var MODULARIZE_INSTANCE = 0; - // If we separate out asm.js with the --separate-asm option, // this is the name of the variable where the generated asm.js // Module is assigned to. This name can either be a property diff --git a/src/shell.js b/src/shell.js index cc5c51b115663..628f157509416 100644 --- a/src/shell.js +++ b/src/shell.js @@ -92,7 +92,7 @@ if (Module['ENVIRONMENT']) { #include "shell_pthreads.js" #endif -#if USE_PTHREADS && (!MODULARIZE || MODULARIZE_INSTANCE) +#if USE_PTHREADS && !MODULARIZE // In MODULARIZE mode _scriptDir needs to be captured already at the very top of the page immediately when the page is parsed, so it is generated there // before the page load. In non-MODULARIZE modes generate it here. #if EXPORT_ES6 @@ -276,8 +276,8 @@ if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { } else if (document.currentScript) { // web scriptDirectory = document.currentScript.src; } -#if MODULARIZE && MODULARIZE_INSTANCE == 0 - // When MODULARIZE (and not _INSTANCE), this JS may be executed later, after document.currentScript +#if MODULARIZE + // When MODULARIZE, 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 (_scriptDir) { scriptDirectory = _scriptDir; diff --git a/src/shell_minimal.js b/src/shell_minimal.js index b722e9bdd8f6e..d7a5c4da4c564 100644 --- a/src/shell_minimal.js +++ b/src/shell_minimal.js @@ -153,7 +153,7 @@ function ready() { #if USE_PTHREADS -#if !MODULARIZE || MODULARIZE_INSTANCE +#if !MODULARIZE // In MODULARIZE mode _scriptDir needs to be captured already at the very top of the page immediately when the page is parsed, so it is generated there // before the page load. In non-MODULARIZE modes generate it here. var _scriptDir = (typeof document !== 'undefined' && document.currentScript) ? document.currentScript.src : undefined; diff --git a/src/shell_minimal_runtime.html b/src/shell_minimal_runtime.html index 9c6f0c8e8a1d1..711102b5ecef9 100644 --- a/src/shell_minimal_runtime.html +++ b/src/shell_minimal_runtime.html @@ -2,7 +2,7 @@ - {{{ SCRIPT }}} - - diff --git a/tests/test_browser.py b/tests/test_browser.py index edb28f8231e76..e8563edfb9b92 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -3718,7 +3718,6 @@ def test(args): test([]) test(['-O3']) - test(['-s', 'MODULARIZE_INSTANCE=1']) test(['-s', 'MINIMAL_RUNTIME=1']) # Test that preallocating worker threads work. @@ -4620,7 +4619,6 @@ def run(emcc_args=[]): self.btest(path_from_root('tests', 'pthread', 'test_pthread_memory_growth_mainthread.c'), expected='1', args=['-s', 'USE_PTHREADS=1', '-s', 'PTHREAD_POOL_SIZE=2', '-s', 'ALLOW_MEMORY_GROWTH=1', '-s', 'INITIAL_MEMORY=32MB', '-s', 'MAXIMUM_MEMORY=256MB'] + emcc_args, also_asmjs=False) run() - run(['-s', 'MODULARIZE_INSTANCE=1']) run(['-s', 'PROXY_TO_PTHREAD=1']) # Tests memory growth in a pthread. @@ -4796,7 +4794,6 @@ def test_browser_run_from_different_directory_async(self): '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 @@ -4826,9 +4823,7 @@ def test_browser_modularize_no_current_script(self): # (which creates by itself) for path, args, creation in [ ([], ['-s', 'MODULARIZE=1'], 'Module();'), - ([], ['-s', 'MODULARIZE_INSTANCE=1'], ''), (['subdir'], ['-s', 'MODULARIZE=1'], 'Module();'), - (['subdir'], ['-s', 'MODULARIZE_INSTANCE=1'], ''), ]: print(path, args, creation) filesystem_path = os.path.join('.', *path) @@ -4850,9 +4845,6 @@ def test_browser_modularize_no_current_script(self): ''' % creation) self.run_browser('/'.join(path + ['test.html']), None, '/report_result?0') - def test_modularize_Module_input(self): - self.btest(path_from_root('tests', 'browser', 'modularize_Module_input.cpp'), '0', args=['--shell-file', path_from_root('tests', 'browser', 'modularize_Module_input.html'), '-s', 'MODULARIZE_INSTANCE=1']) - def test_emscripten_request_animation_frame(self): self.btest(path_from_root('tests', 'emscripten_request_animation_frame.c'), '0') @@ -4996,21 +4988,6 @@ def test_wasm2js_fallback(self): os.remove('test.wasm') # Also delete the Wasm file to test that it is not attempted to be loaded. self.run_browser('test.html', 'hello!', '/report_result?0') - # Test that basic thread creation works in combination with MODULARIZE_INSTANCE=1 and EXPORT_NAME=MyModule - @no_fastcomp('more work would be needed for this to work in deprecated fastcomp') - @requires_threads - def test_pthread_modularize_export_name(self): - create_test_file('shell.html', ''' - - {{{ SCRIPT }}} - - ''') - self.btest(path_from_root('tests', 'pthread', 'test_pthread_create.cpp'), - expected='0', - args=['-s', 'INITIAL_MEMORY=64MB', '-s', 'USE_PTHREADS=1', - '-s', 'PTHREAD_POOL_SIZE=8', '-s', 'MODULARIZE_INSTANCE=1', - '-s', 'EXPORT_NAME=MyModule', '--shell-file', 'shell.html']) - def test_system(self): self.btest(path_from_root('tests', 'system.c'), '0') diff --git a/tests/test_core.py b/tests/test_core.py index a32399f8cd478..58a868421397f 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -7568,26 +7568,20 @@ def get_wat_addr(call_index): def test_modularize_closure_pre(self): # test that the combination of modularize + closure + pre-js works. in that mode, # closure should not minify the Module object in a way that the pre-js cannot use it. - base_args = self.emcc_args + [ + self.emcc_args += [ '--pre-js', path_from_root('tests', 'core', 'modularize_closure_pre.js'), '--closure', '1', - '-g1' + '-g1', + '-s', + 'MODULARIZE=1', ] - for instance in (0, 1): - print("instance: %d" % instance) - if instance: - self.emcc_args = base_args + ['-s', 'MODULARIZE_INSTANCE=1'] - else: - self.emcc_args = base_args + ['-s', 'MODULARIZE=1'] - - def post(filename): - with open(filename, 'a') as f: - f.write('\n\n') - if not instance: - f.write('var TheModule = Module();\n') + def post(filename): + with open(filename, 'a') as f: + f.write('\n\n') + f.write('var TheModule = Module();\n') - self.do_run_in_out_file_test('tests', 'core', 'modularize_closure_pre', post_build=post) + self.do_run_in_out_file_test('tests', 'core', 'modularize_closure_pre', post_build=post) @no_emterpreter @no_wasm('wasmifying destroys debug info and stack tracability') diff --git a/tools/minimal_runtime_shell.py b/tools/minimal_runtime_shell.py index d8e13ac6e5f6d..4ae490602ae6f 100644 --- a/tools/minimal_runtime_shell.py +++ b/tools/minimal_runtime_shell.py @@ -16,8 +16,6 @@ def generate_minimal_runtime_load_statement(target_basename): then_statements = [] # Statements to appear inside a Promise .then() block after loading has finished modularize_imports = [] # Import parameters to call the main JS runtime function with - modularize_not_instance = shared.Settings.MODULARIZE and not shared.Settings.MODULARIZE_INSTANCE - # Depending on whether streaming Wasm compilation is enabled or not, the minimal sized code to download Wasm looks a bit different. # Expand {{{ DOWNLOAD_WASM }}} block from here (if we added #define support, this could be done in the template directly) if shared.Settings.MINIMAL_RUNTIME_STREAMING_WASM_COMPILATION: @@ -45,7 +43,7 @@ def generate_minimal_runtime_load_statement(target_basename): # Download separate memory initializer file .mem if shared.Settings.MEM_INIT_METHOD == 1 and not shared.Settings.MEM_INIT_IN_WASM: - if modularize_not_instance: + if shared.Settings.MODULARIZE: modularize_imports += ['mem: r[%d]' % len(files_to_load)] else: then_statements += ["Module.mem = r[%d];" % len(files_to_load)] @@ -57,26 +55,26 @@ def generate_minimal_runtime_load_statement(target_basename): # Download .wasm file if shared.Settings.WASM == 1 or not download_wasm: - if modularize_not_instance: + if shared.Settings.MODULARIZE: modularize_imports += ['wasm: r[%d]' % len(files_to_load)] else: then_statements += ["Module.wasm = r[%d];" % len(files_to_load)] if download_wasm: files_to_load += [download_wasm] - if modularize_not_instance and shared.Settings.USE_PTHREADS: + if shared.Settings.MODULARIZE and shared.Settings.USE_PTHREADS: modularize_imports += ["worker: '{{{ PTHREAD_WORKER_FILE }}}'"] # Download Wasm2JS code if target browser does not support WebAssembly if shared.Settings.WASM == 2: - if modularize_not_instance: + if shared.Settings.MODULARIZE: modularize_imports += ['wasm: supportsWasm ? r[%d] : 0' % len(files_to_load)] else: then_statements += ["if (supportsWasm) Module.wasm = r[%d];" % len(files_to_load)] files_to_load += ["supportsWasm ? %s : script('%s')" % (download_wasm, target_basename + '.wasm.js')] # Execute compiled output when building with MODULARIZE - if modularize_not_instance: + if shared.Settings.MODULARIZE: then_statements += ['''// Detour the JS code to a separate variable to avoid instantiating with 'r' array as "this" directly to avoid strict ECMAScript/Firefox GC problems that cause a leak, see https://bugzilla.mozilla.org/show_bug.cgi?id=1540101 var js = r[0];\n js({ %s });''' % ',\n '.join(modularize_imports)] @@ -96,7 +94,8 @@ def generate_minimal_runtime_load_statement(target_basename): var s = document.createElement('script'); s.src = url; s.onload = () => { -#if MODULARIZE && !MODULARIZE_INSTANCE && WASM == 2 +#if MODULARIZE +#if WASM == 2 // In MODULARIZEd WASM==2 builds, we use this same function to download // both .js and .asm.js that are structured with {{{ EXPORT_NAME }}} // at the top level, but also use this function to download the Wasm2JS @@ -110,13 +109,12 @@ def generate_minimal_runtime_load_statement(target_basename): ok(); } #else -#if MODULARIZE && !MODULARIZE_INSTANCE var c = {{{ EXPORT_NAME }}}; delete {{{ EXPORT_NAME }}}; ok(c); +#endif #else ok(); -#endif #endif }; document.body.appendChild(s); @@ -126,12 +124,12 @@ def generate_minimal_runtime_load_statement(target_basename): # Only one file to download - no need to use Promise.all() if len(files_to_load) == 1: - if modularize_not_instance: + if shared.Settings.MODULARIZE: return script_xhr + files_to_load[0] + ".then((js) => {\n js();\n});" else: return script_xhr + files_to_load[0] + ";" - if not modularize_not_instance: + if not shared.Settings.MODULARIZE: # If downloading multiple files like .wasm or .mem, those need to be loaded in # before we can add the main runtime script to the DOM, so convert the main .js # script load from direct script() load to a binary() load so we can still