forked from emscripten-core/emscripten
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjs_manipulation.py
141 lines (118 loc) · 4.69 KB
/
js_manipulation.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# Copyright 2020 The Emscripten Authors. All rights reserved.
# Emscripten is available under two separate licenses, the MIT license and the
# University of Illinois/NCSA Open Source License. Both these licenses can be
# found in the LICENSE file.
import re
from .settings import settings
from . import utils
emscripten_license = '''\
/**
* @license
* Copyright 2010 The Emscripten Authors
* SPDX-License-Identifier: MIT
*/
'''
# handle the above form, and also what closure can emit which is stuff like
# /*
#
# Copyright 2019 The Emscripten Authors
# SPDX-License-Identifier: MIT
#
# Copyright 2017 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*\*\/'
def add_files_pre_js(user_pre_js, files_pre_js):
# the normal thing is to just combine the pre-js content
if not settings.ASSERTIONS:
return files_pre_js + user_pre_js
# if a user pre-js tramples the file code's changes to Module.preRun
# that could be confusing. show a clear error at runtime if assertions are
# enabled
return files_pre_js + '''
// All the pre-js content up to here must remain later on, we need to run
// it.
if (Module['ENVIRONMENT_IS_PTHREAD']) Module['preRun'] = [];
var necessaryPreJSTasks = Module['preRun'].slice();
''' + user_pre_js + '''
if (!Module['preRun']) throw 'Module.preRun should exist because file support used it; did a pre-js delete it?';
necessaryPreJSTasks.forEach(function(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?';
});
'''
def handle_license(js_target):
# ensure we emit the license if and only if we need to, and exactly once
js = utils.read_file(js_target)
# first, remove the license as there may be more than once
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)
# Returns the given string with escapes added so that it can safely be placed inside a string in JS code.
def escape_for_js_string(s):
s = s.replace('\\', '/').replace("'", "\\'").replace('"', '\\"')
return s
def legalize_sig(sig):
# with BigInt support all sigs are legal since we can use i64s.
if settings.WASM_BIGINT:
return sig
legal = [sig[0]]
# a return of i64 is legalized into an i32 (and the high bits are
# accessible on the side through getTempRet0).
if legal[0] == 'j':
legal[0] = 'i'
# a parameter of i64 is legalized into i32, i32
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):
# with BigInt support all sigs are legal since we can use i64s.
if settings.WASM_BIGINT:
return True
return sig == legalize_sig(sig)
def isidentifier(name):
# https://stackoverflow.com/questions/43244604/check-that-a-string-is-a-valid-javascript-identifier-name-using-python-3
return name.replace('$', '_').isidentifier()
def make_dynCall(sig, args):
# wasm2c and asyncify are not yet compatible with direct wasm table calls
if settings.DYNCALLS or not is_legal_sig(sig):
args = ','.join(args)
if not settings.MAIN_MODULE and not settings.SIDE_MODULE:
# Optimize dynCall accesses in the case when not building with dynamic
# linking enabled.
return 'dynCall_%s(%s)' % (sig, args)
else:
return 'Module["dynCall_%s"](%s)' % (sig, args)
else:
return 'getWasmTableEntry(%s)(%s)' % (args[0], ','.join(args[1:]))
def make_invoke(sig):
legal_sig = legalize_sig(sig) # TODO: do this in extcall, jscall?
args = ['index'] + ['a' + str(i) for i in range(1, len(legal_sig))]
ret = 'return ' if sig[0] != 'v' else ''
# For function that needs to return a genuine i64 (i.e. if legal_sig[0] is 'j')
# we need to return an actual BigInt, even in the exceptional case because
# wasm won't implicitly convert undefined to 0 in this case.
exceptional_ret = '\n return BigInt(0);' if legal_sig[0] == 'j' else ''
body = '%s%s;' % (ret, make_dynCall(sig, args))
# C++ exceptions are numbers, and longjmp is a string 'longjmp'
if settings.SUPPORT_LONGJMP:
rethrow = "if (e !== e+0 && e !== 'longjmp') throw e;"
else:
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, rethrow, exceptional_ret)
return ret