| |
| |
| |
| |
|
|
| import re |
|
|
| from . import shared, utils |
| from .settings import settings |
|
|
| emscripten_license = '''\ |
| /** |
| * @license |
| * Copyright 2010 The Emscripten Authors |
| * SPDX-License-Identifier: MIT |
| */ |
| ''' |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| emscripten_license_regex = r'\/\*\*?(\s*\*?\s*@license)?(\s*\*?\s*Copyright \d+ The Emscripten Authors\s*\*?\s*SPDX-License-Identifier: MIT)+\s*\*\/\s*' |
|
|
|
|
| def add_files_pre_js(pre_js_list, files_pre_js): |
| |
| filename = shared.get_temp_files().get('.js').name |
| utils.write_file(filename, files_pre_js) |
| pre_js_list.insert(0, filename) |
| if not settings.ASSERTIONS: |
| return |
|
|
| |
| |
| |
| pre = shared.get_temp_files().get('.js').name |
| post = shared.get_temp_files().get('.js').name |
| utils.write_file(pre, ''' |
| // All the pre-js content up to here must remain later on, we need to run |
| // it. |
| if ((typeof ENVIRONMENT_IS_WASM_WORKER != 'undefined' && ENVIRONMENT_IS_WASM_WORKER) || (typeof ENVIRONMENT_IS_PTHREAD != 'undefined' && ENVIRONMENT_IS_PTHREAD) || (typeof ENVIRONMENT_IS_AUDIO_WORKLET != 'undefined' && ENVIRONMENT_IS_AUDIO_WORKLET)) Module['preRun'] = []; |
| var necessaryPreJSTasks = Module['preRun'].slice(); |
| ''') |
| utils.write_file(post, ''' |
| if (!Module['preRun']) throw 'Module.preRun should exist because file support used it; did a pre-js delete it?'; |
| necessaryPreJSTasks.forEach((task) => { |
| if (Module['preRun'].indexOf(task) < 0) throw 'All preRun tasks that exist before user pre-js code should remain after; did you replace Module or modify Module.preRun?'; |
| }); |
| ''') |
|
|
| pre_js_list.insert(1, pre) |
| pre_js_list.append(post) |
|
|
|
|
| def handle_license(js_target): |
| |
| js = utils.read_file(js_target) |
| |
| processed_js = re.sub(emscripten_license_regex, '', js) |
| if settings.EMIT_EMSCRIPTEN_LICENSE: |
| processed_js = emscripten_license + processed_js |
| if processed_js != js: |
| utils.write_file(js_target, processed_js) |
|
|
|
|
| |
| def escape_for_js_string(s): |
| s = s.replace('\\', '/').replace("'", "\\'").replace('"', '\\"') |
| return s |
|
|
|
|
| def legalize_sig(sig): |
| |
| if settings.WASM_BIGINT: |
| return sig |
| legal = [sig[0]] |
| |
| |
| if legal[0] == 'j': |
| legal[0] = 'i' |
| |
| for s in sig[1:]: |
| if s != 'j': |
| legal.append(s) |
| else: |
| legal.append('i') |
| legal.append('i') |
| return ''.join(legal) |
|
|
|
|
| def is_legal_sig(sig): |
| |
| if settings.WASM_BIGINT: |
| return True |
| return sig == legalize_sig(sig) |
|
|
|
|
| def isidentifier(name): |
| |
| return name.replace('$', '_').isidentifier() |
|
|
|
|
| def make_dynCall(sig, args): |
| if settings.MEMORY64: |
| args = list(args) |
| args[0] = f'Number({args[0]})' |
| |
| |
| if settings.DYNCALLS or not is_legal_sig(sig): |
| args = ','.join(args) |
| if settings.MAIN_MODULE or settings.SIDE_MODULE: |
| |
| |
| |
| return "dynCalls['%s'](%s)" % (sig, args) |
| return 'dynCall_%s(%s)' % (sig, args) |
| else: |
| call_args = ",".join(args[1:]) |
| return f'getWasmTableEntry({args[0]})({call_args})' |
|
|
|
|
| def make_invoke(sig): |
| legal_sig = legalize_sig(sig) |
| args = ['index'] + ['a' + str(i) for i in range(1, len(legal_sig))] |
| ret = 'return ' if sig[0] != 'v' else '' |
| |
| |
| |
| exceptional_ret = '\n return 0n;' if legal_sig[0] == 'j' else '' |
| body = '%s%s;' % (ret, make_dynCall(sig, args)) |
| |
| maybe_rethrow = 'if (!(e instanceof EmscriptenEH)) throw e;' |
|
|
| ret = '''\ |
| function invoke_%s(%s) { |
| var sp = stackSave(); |
| try { |
| %s |
| } catch(e) { |
| stackRestore(sp); |
| %s |
| _setThrew(1, 0);%s |
| } |
| }''' % (sig, ','.join(args), body, maybe_rethrow, exceptional_ret) |
|
|
| return ret |
|
|
|
|
| def make_wasm64_wrapper(sig): |
| assert 'p' in sig.lower() |
| n_args = len(sig) - 1 |
| args = ['a%d' % i for i in range(n_args)] |
| args_converted = args.copy() |
| for i, arg_type in enumerate(sig[1:]): |
| if arg_type == 'p': |
| args_converted[i] = f'BigInt({args_converted[i]})' |
| elif arg_type == 'P': |
| args_converted[i] = f'BigInt({args_converted[i]} ? {args_converted[i]} : 0)' |
| else: |
| assert arg_type == '_' |
|
|
| args_in = ', '.join(args) |
| args_out = ', '.join(args_converted) |
| result = f'f({args_out})' |
| if sig[0] == 'p': |
| result = f'Number({result})' |
|
|
| |
| |
| |
| |
| return f' var makeWrapper_{sig} = (f) => ({args_in}) => {result};\n' |
|
|
|
|
| def make_unsign_pointer_wrapper(sig): |
| assert sig[0] == 'p' |
| n_args = len(sig) - 1 |
| args = ','.join('a%d' % i for i in range(n_args)) |
| return f' var makeWrapper_{sig} = (f) => ({args}) => f({args}) >>> 0;\n' |
|
|