import re
from .settings import settings
from . import utils, shared
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 not settings.MAIN_MODULE and not settings.SIDE_MODULE:
return 'dynCall_%s(%s)' % (sig, args)
else:
return 'Module["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))
if settings.EXCEPTION_STACK_TRACES:
maybe_rethrow = 'if (!(e instanceof EmscriptenEH)) throw e;'
else:
maybe_rethrow = 'if (e !== e+0) 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'