Skip to content

Commit

Permalink
Set INCOMING_MODULE_JS_API to empty in STRICT mode (emscripten-core#1…
Browse files Browse the repository at this point in the history
…6372)

In strict mode, make this list empty default which saves on code size
and complexity.  In this mode one needs to opt into any incoming module
symbols you want to use.
  • Loading branch information
sbc100 authored Aug 25, 2023
1 parent 7b3d638 commit e69b6cf
Show file tree
Hide file tree
Showing 9 changed files with 32 additions and 28 deletions.
6 changes: 6 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ See docs/process.md for more on how version tagging works.
- The `--minify=0` commnad line flag will now preserve comments as well as
whitespace. This means the resulting output can then be run though closure
compiler or some other tool that gives comments semantic meaning. (#20121)
- `-sSTRICT` now implies `-sINCOMING_MODULE_API=[]` which is generally good
for code size. If you `-sSTRICT` you now need to be explicit about the
incoming module APIs you are supplying. Users who supply symbols on the
incoming module but forget to include them in `-sINCOMING_MODULE_API`
will see an error in debug builds so this change will not generate any
silent failures.

3.1.45 - 08/23/23
-----------------
Expand Down
14 changes: 10 additions & 4 deletions emcc.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
STATICLIB_ENDINGS = ['.a']
ASSEMBLY_ENDINGS = ['.s']
HEADER_ENDINGS = ['.h', '.hxx', '.hpp', '.hh', '.H', '.HXX', '.HPP', '.HH']
DEFAULT_SHELL_HTML = utils.path_from_root('src/shell.html')

# Supported LLD flags which we will pass through to the linker.
SUPPORTED_LINKER_FLAGS = (
Expand Down Expand Up @@ -268,7 +269,7 @@ def __init__(self):
self.embed_files = []
self.exclude_files = []
self.ignore_dynamic_linking = False
self.shell_path = utils.path_from_root('src/shell.html')
self.shell_path = DEFAULT_SHELL_HTML
self.source_map_base = ''
self.embind_emit_tsd = ''
self.emrun = False
Expand Down Expand Up @@ -2041,6 +2042,11 @@ def phase_linker_setup(options, state, newargs):
default_setting('AUTO_ARCHIVE_INDEXES', 0)
default_setting('IGNORE_MISSING_MAIN', 0)
default_setting('ALLOW_UNIMPLEMENTED_SYSCALLS', 0)
if options.oformat == OFormat.HTML and options.shell_path == DEFAULT_SHELL_HTML:
# Out default shell.html file has minimal set of INCOMING_MODULE_JS_API elements that it expects
default_setting('INCOMING_MODULE_JS_API', 'canvas,monitorRunDependencies,onAbort,onExit,print,setStatus'.split(','))
else:
default_setting('INCOMING_MODULE_JS_API', [])

if 'GLOBAL_BASE' not in user_settings and not settings.SHRINK_LEVEL and not settings.OPT_LEVEL:
# When optimizing for size it helps to put static data first before
Expand Down Expand Up @@ -2602,7 +2608,7 @@ def check_memory_setting(setting):

if settings.MINIMAL_RUNTIME:
# Minimal runtime uses a different default shell file
if options.shell_path == utils.path_from_root('src/shell.html'):
if options.shell_path == DEFAULT_SHELL_HTML:
options.shell_path = utils.path_from_root('src/shell_minimal_runtime.html')

if settings.ASSERTIONS:
Expand All @@ -2614,7 +2620,7 @@ def check_memory_setting(setting):

if settings.MODULARIZE and not (settings.EXPORT_ES6 and not settings.SINGLE_FILE) and \
settings.EXPORT_NAME == 'Module' and options.oformat == OFormat.HTML and \
(options.shell_path == utils.path_from_root('src/shell.html') or options.shell_path == utils.path_from_root('src/shell_minimal.html')):
(options.shell_path == DEFAULT_SHELL_HTML or options.shell_path == utils.path_from_root('src/shell_minimal.html')):
exit_with_error(f'Due to collision in variable name "Module", the shell file "{options.shell_path}" is not compatible with build options "-sMODULARIZE -sEXPORT_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)')

# TODO(sbc): Remove WASM2JS here once the size regression it would introduce has been fixed.
Expand Down Expand Up @@ -4154,7 +4160,7 @@ def generate_html(target, options, js_target, target_basename,

if settings.EXPORT_NAME != 'Module' and \
not settings.MINIMAL_RUNTIME and \
options.shell_path == utils.path_from_root('src/shell.html'):
options.shell_path == DEFAULT_SHELL_HTML:
# the minimal runtime shell HTML is designed to support changing the export
# name, but the normal one does not support that currently
exit_with_error('Customizing EXPORT_NAME requires that the HTML be customized to use that name (see https://github.com/emscripten-core/emscripten/issues/10086)')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -755,7 +755,7 @@ For example, to set an environment variable ``MY_FILE_ROOT`` to be

.. code:: javascript
Module.preRun.push(function() {ENV.MY_FILE_ROOT = "/usr/lib/test"})
Module.preRun = () => {ENV.MY_FILE_ROOT = "/usr/lib/test"};
Note that Emscripten will set default values for some environment variables
(e.g. LANG) after you have configured ``ENV``, if you have not set your own
Expand All @@ -764,7 +764,7 @@ their value to `undefined`. For example:

.. code:: javascript
Module.preRun.push(function() {ENV.LANG = undefined})
Module.preRun = () => {ENV.LANG = undefined};
.. _interacting-with-code-binding-cpp:

Expand Down
1 change: 1 addition & 0 deletions src/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -1116,6 +1116,7 @@ var LINKABLE = false;
// * DEFAULT_TO_CXX is disabled.
// * USE_GLFW is set to 0 rather than 2 by default.
// * ALLOW_UNIMPLEMENTED_SYSCALLS is disabled.
// * INCOMING_MODULE_JS_API is set to empty by default.
// [compile+link]
var STRICT = false;

Expand Down
2 changes: 0 additions & 2 deletions src/shell.html
Original file line number Diff line number Diff line change
Expand Up @@ -1222,8 +1222,6 @@
var spinnerElement = document.getElementById('spinner');

var Module = {
preRun: [],
postRun: [],
print: (function() {
var element = document.getElementById('output');
if (element) element.value = ''; // clear browser cache
Expand Down
2 changes: 0 additions & 2 deletions src/shell_minimal.html
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,6 @@
var spinnerElement = document.getElementById('spinner');

var Module = {
preRun: [],
postRun: [],
print: (function() {
var element = document.getElementById('output');
if (element) element.value = ''; // clear browser cache
Expand Down
7 changes: 2 additions & 5 deletions test/browser/cwrap_early.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

Module['preRun'].push(function() {
Module['preRun'] = () => {
console.log('preRun');
// it is ok to call cwrap before the runtime is loaded. we don't need the code
// and everything to be ready, since cwrap just prepares to call code, it
Expand All @@ -15,6 +14,4 @@ Module['preRun'].push(function() {
xhr.send();
setTimeout(function() { window.close() }, 1000);
};
});


};
13 changes: 6 additions & 7 deletions test/test_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -2241,9 +2241,9 @@ def test_sdl_gfx_primitives(self):

def test_sdl_canvas_palette_2(self):
create_file('pre.js', '''
Module['preRun'].push(function() {
Module['preRun'] = () => {
SDL.defaults.copyOnLock = false;
});
};
''')

create_file('args-r.js', '''
Expand Down Expand Up @@ -2525,11 +2525,11 @@ def test_runtime_misuse(self, mode):
create_file('post.js', post_prep + post_test + post_hook)
self.btest(filename, expected='600', args=['--post-js', 'post.js', '-sEXIT_RUNTIME'] + extra_args + mode, reporting=Reporting.NONE)
print('sync startup, call too late')
create_file('post.js', post_prep + 'Module.postRun.push(function() { ' + post_test + ' });' + post_hook)
create_file('post.js', post_prep + 'Module.postRun = () => { ' + post_test + ' };' + post_hook)
self.btest(filename, expected=str(second_code), args=['--post-js', 'post.js', '-sEXIT_RUNTIME'] + extra_args + mode, reporting=Reporting.NONE)

print('sync, runtime still alive, so all good')
create_file('post.js', post_prep + 'expected_ok = true; Module.postRun.push(function() { ' + post_test + ' });' + post_hook)
create_file('post.js', post_prep + 'expected_ok = true; Module.postRun = () => { ' + post_test + ' };' + post_hook)
self.btest(filename, expected='606', args=['--post-js', 'post.js'] + extra_args + mode, reporting=Reporting.NONE)

def test_cwrap_early(self):
Expand Down Expand Up @@ -2644,11 +2644,10 @@ def test_glew(self):

def test_doublestart_bug(self):
create_file('pre.js', r'''
if (!Module['preRun']) Module['preRun'] = [];
Module["preRun"].push(function () {
Module["preRun"] = () => {
addRunDependency('test_run_dependency');
removeRunDependency('test_run_dependency');
});
};
''')

self.btest('doublestart.c', args=['--pre-js', 'pre.js'], expected='1')
Expand Down
11 changes: 5 additions & 6 deletions test/test_other.py
Original file line number Diff line number Diff line change
Expand Up @@ -4030,17 +4030,16 @@ def test_doublestart_bug(self):
''')

create_file('pre.js', r'''
if (!Module['preRun']) Module['preRun'] = [];
Module["preRun"].push(function () {
addRunDependency('test_run_dependency');
removeRunDependency('test_run_dependency');
});
Module["preRun"] = () => {
addRunDependency('test_run_dependency');
removeRunDependency('test_run_dependency');
};
''')

self.run_process([EMCC, 'code.c', '--pre-js', 'pre.js'])
output = self.run_js('a.out.js')

assert output.count('This should only appear once.') == 1, output
self.assertEqual(output.count('This should only appear once.'), 1)

def test_module_print(self):
create_file('code.c', r'''
Expand Down

0 comments on commit e69b6cf

Please sign in to comment.