Skip to content

Commit eac8e0b

Browse files
authored
Minify JS in wasm mode too (#4999)
* minify the JS in wasm mode when possible. even if the compiled code is in a side wasm file, in small projects the JS can be of significant size
1 parent ebf0980 commit eac8e0b

File tree

3 files changed

+44
-11
lines changed

3 files changed

+44
-11
lines changed

emcc.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1273,7 +1273,6 @@ def check(input_file):
12731273
shared.Settings.ASMJS_CODE_FILE = os.path.basename(asm_target)
12741274

12751275
shared.Settings.ASM_JS = 2 # when targeting wasm, we use a wasm Memory, but that is not compatible with asm.js opts
1276-
debug_level = max(1, debug_level) # keep whitespace readable, for asm.js parser simplicity
12771276
shared.Settings.GLOBAL_BASE = 1024 # leave some room for mapping global vars
12781277
assert not shared.Settings.SPLIT_MEMORY, 'WebAssembly does not support split memory'
12791278
assert not shared.Settings.USE_PTHREADS, 'WebAssembly does not support pthreads'
@@ -2195,6 +2194,21 @@ def do_minify(): # minifies the code. this is also when we do certain optimizati
21952194
os.unlink(js_target) # we don't need the js, it can just confuse
21962195
os.unlink(asm_target) # we don't need the asm.js, it can just confuse
21972196
sys.exit(0) # and we are done.
2197+
if opt_level >= 2:
2198+
# minify the JS
2199+
do_minify() # calculate how to minify
2200+
if JSOptimizer.cleanup_shell or JSOptimizer.minify_whitespace or use_closure_compiler:
2201+
misc_temp_files.note(final)
2202+
shutil.move(js_target, final)
2203+
if DEBUG: save_intermediate('preclean', 'js')
2204+
if use_closure_compiler:
2205+
logging.debug('running closure on shell code')
2206+
final = shared.Building.closure_compiler(final, pretty=not JSOptimizer.minify_whitespace)
2207+
else:
2208+
assert JSOptimizer.cleanup_shell
2209+
logging.debug('running cleanup on shell code')
2210+
final = shared.Building.js_optimizer_no_asmjs(final, ['noPrintMetadata', 'JSDCE', 'last'] + (['minifyWhitespace'] if JSOptimizer.minify_whitespace else []))
2211+
shutil.move(final, js_target)
21982212

21992213
# If we were asked to also generate HTML, do that
22002214
if final_suffix == 'html':

tests/test_other.py

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7394,24 +7394,32 @@ def test_binaryen_ctors(self):
73947394
seen = run_js('b.out.js', engine=SPIDERMONKEY_ENGINE)
73957395
assert correct == seen, correct + '\n vs \n' + seen
73967396

7397-
def test_binaryen_debuginfo(self):
7398-
with clean_write_access_to_canonical_temp_dir():
7397+
# test debug info and debuggability of JS output
7398+
def test_binaryen_debug(self):
73997399
if os.environ.get('EMCC_DEBUG'): return self.skip('cannot run in debug mode')
74007400
try:
74017401
os.environ['EMCC_DEBUG'] = '1'
7402-
for args, expect_dash_g, expect_emit_text in [
7403-
(['-O0'], False, False),
7404-
(['-O0', '-g1'], False, False),
7405-
(['-O0', '-g2'], True, False), # in -g2+, we emit -g to asm2wasm so function names are saved
7406-
(['-O0', '-g'], True, True),
7407-
(['-O0', '--profiling-funcs'], True, False),
7408-
(['-O1'], False, False),
7402+
for args, expect_dash_g, expect_emit_text, expect_clean_js, expect_whitespace_js, expect_closured in [
7403+
(['-O0'], False, False, False, True, False),
7404+
(['-O0', '-g1'], False, False, False, True, False),
7405+
(['-O0', '-g2'], True, False, False, True, False), # in -g2+, we emit -g to asm2wasm so function names are saved
7406+
(['-O0', '-g'], True, True, False, True, False),
7407+
(['-O0', '--profiling-funcs'], True, False, False, True, False),
7408+
(['-O1'], False, False, False, True, False),
7409+
(['-O2'], False, False, True, False, False),
7410+
(['-O2', '-g1'], False, False, True, True, False),
7411+
(['-O2', '-g'], True, True, False, True, False),
7412+
(['-O2', '--closure', '1'], False, False, True, False, True),
7413+
(['-O2', '--closure', '1', '-g1'], False, False, True, True, True),
7414+
(['-O2', '--js-opts', '1'], False, False, True, False, False),
74097415
]:
74107416
print args, expect_dash_g, expect_emit_text
74117417
try_delete('a.out.wast')
74127418
cmd = [PYTHON, EMCC, path_from_root('tests', 'hello_world.cpp'), '-s', 'WASM=1'] + args
74137419
print ' '.join(cmd)
7414-
output, err = Popen(cmd, stdout=PIPE, stderr=PIPE).communicate()
7420+
proc = Popen(cmd, stdout=PIPE, stderr=PIPE)
7421+
output, err = proc.communicate()
7422+
assert proc.returncode == 0
74157423
asm2wasm_line = filter(lambda x: 'asm2wasm' in x, err.split('\n'))[0]
74167424
asm2wasm_line = asm2wasm_line.strip() + ' ' # ensure it ends with a space, for simpler searches below
74177425
print '|' + asm2wasm_line + '|'
@@ -7421,6 +7429,10 @@ def test_binaryen_debuginfo(self):
74217429
text = open('a.out.wast').read()
74227430
assert ';;' in text, 'must see debug info comment'
74237431
assert 'hello_world.cpp:6' in text, 'must be file:line info'
7432+
js = open('a.out.js').read()
7433+
assert expect_clean_js == ('// ' not in js), 'cleaned-up js must not have comments'
7434+
assert expect_whitespace_js == ('{\n ' in js), 'whitespace-minified js must not have excess spacing'
7435+
assert expect_closured == ('var a;' in js), 'closured js must have tiny variable names'
74247436
finally:
74257437
del os.environ['EMCC_DEBUG']
74267438

tools/shared.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2018,6 +2018,13 @@ def js_optimizer(filename, passes, debug=False, extra_info=None, output_filename
20182018
ret = output_filename
20192019
return ret
20202020

2021+
# run JS optimizer on some JS, ignoring asm.js contents if any - just run on it all
2022+
@staticmethod
2023+
def js_optimizer_no_asmjs(filename, passes):
2024+
next = filename + '.jso.js'
2025+
subprocess.check_call(NODE_JS + [js_optimizer.JS_OPTIMIZER, filename] + passes, stdout=open(next, 'w'))
2026+
return next
2027+
20212028
@staticmethod
20222029
def eval_ctors(js_file, mem_init_file):
20232030
subprocess.check_call([PYTHON, path_from_root('tools', 'ctor_evaller.py'), js_file, mem_init_file, str(Settings.TOTAL_MEMORY), str(Settings.TOTAL_STACK), str(Settings.GLOBAL_BASE)])

0 commit comments

Comments
 (0)