Skip to content

Commit

Permalink
Copy the asm object if we modify it in ASSERTIONS mode. That makes it…
Browse files Browse the repository at this point in the history
… work if it is the ES6 exports object of a wasm module, which is read-only. Fixes #8678
  • Loading branch information
kripken committed Jul 9, 2019
1 parent 11b0ae2 commit 95fc14d
Showing 1 changed file with 13 additions and 6 deletions.
19 changes: 13 additions & 6 deletions emscripten.py
Original file line number Diff line number Diff line change
Expand Up @@ -1684,6 +1684,15 @@ def create_the_global(metadata):
assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');'''

# We want to modify `asm` in some cases, for assertion purposes, however in ES6 environments that
# may be illegal as the wasm exports are an ES6 export object, which is read-only. To work around
# that, we simply make a copy of `asm` - the overhead doesn't matter in an assertions build.
COPY_ASM = '''
var originalAsm = asm;
Module['asm'] = asm = {};
for (var x in originalAsm) asm[x] = originalAsm[x];
'''


def create_receiving(function_table_data, function_tables_defs, exported_implemented_functions, initializers):
receiving = ''
Expand All @@ -1695,6 +1704,8 @@ def create_receiving(function_table_data, function_tables_defs, exported_impleme
# some support code
receiving_functions = [f for f in exported_implemented_functions if f not in ('_memcpy', '_memset', '_emscripten_replace_memory', '__start_module')]

receiving = COPY_ASM

wrappers = []
for name in receiving_functions:
wrappers.append('''\
Expand All @@ -1703,15 +1714,10 @@ def create_receiving(function_table_data, function_tables_defs, exported_impleme
return real_%(name)s.apply(null, arguments);
};
''' % {'name': name, 'runtime_assertions': runtime_assertions})
receiving = '\n'.join(wrappers)
receiving = COPY_ASM + '\n'.join(wrappers)

shared.Settings.MODULE_EXPORTS = module_exports = exported_implemented_functions + function_tables(function_table_data)

# Currently USE PTHREADS + EXPORT ES6 doesn't work with the previously generated assertions.
# ES6 modules disallow re-assigning read-only properties.
if shared.Settings.USE_PTHREADS and shared.Settings.EXPORT_ES6 and shared.Settings.ASSERTIONS and receiving:
receiving = "assert(!ENVIRONMENT_IS_PTHREAD, 'Error: USE_PTHREADS and EXPORT_ES6 requires ASSERTIONS=0');\n" + receiving

if not shared.Settings.SWAPPABLE_ASM_MODULE:
if shared.Settings.DECLARE_ASM_MODULE_EXPORTS:
imported_exports = [s for s in module_exports if s not in initializers]
Expand Down Expand Up @@ -2462,6 +2468,7 @@ def create_receiving_wasm(exports):
runtime_assertions = RUNTIME_ASSERTIONS
# assert on the runtime being in a valid state when calling into compiled code. The only exceptions are
# some support code
receiving.append(COPY_ASM)
for e in exports:
receiving.append('''\
var real_%(mangled)s = asm["%(e)s"];
Expand Down

0 comments on commit 95fc14d

Please sign in to comment.