Skip to content

Commit 9429b48

Browse files
authored
Remove limits of ES6 features in standard library code (#20700)
When transpiling to ES5 use closure with `SIMPLE_OPTIMIZATIONS` rather then `WHITESPACE_ONLY`. This means that polyfills cant be included as needed and removes the limits on what ES6 features we can use. The downside of this is that is slows down builds for ES5 users but this seems like a reasonable tradeoff. Fixes: #11984
1 parent 5b6bf91 commit 9429b48

File tree

4 files changed

+28
-9
lines changed

4 files changed

+28
-9
lines changed

ChangeLog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ See docs/process.md for more on how version tagging works.
2727
`warning: treating 'c' input as 'c++' when in C++ mode`. This also means that
2828
the `DEFAULT_TO_CXX` setting now only applies when linking and not when
2929
compiling. (#20712)
30+
- JavaScript library code can now use the full range ES6 features and we rely
31+
on closure compiler to transpile for ES5 when targetting older browsers.
32+
For those that want to would rather perform transpilation seperately outside
33+
of emscripten you can use the `-sPOLYFILL=0` setting. (#20700)
3034

3135
3.1.49 - 11/14/23
3236
-----------------

emcc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2318,7 +2318,7 @@ def phase_linker_setup(options, state, newargs):
23182318

23192319
setup_environment_settings()
23202320

2321-
if options.use_closure_compiler != 0:
2321+
if options.use_closure_compiler != 0 and settings.POLYFILL:
23222322
# Emscripten requires certain ES6 constructs by default in library code
23232323
# - https://caniuse.com/let : EDGE:12 FF:44 CHROME:49 SAFARI:11
23242324
# - https://caniuse.com/const : EDGE:12 FF:36 CHROME:49 SAFARI:11

test/test_other.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12990,7 +12990,7 @@ def test_hello_function(self):
1299012990
})
1299112991
@crossplatform
1299212992
def test_es5_transpile(self, args):
12993-
self.emcc_args += args
12993+
self.emcc_args += ['-Wno-transpile'] + args
1299412994

1299512995
# Create a library file that uses the following ES6 features
1299612996
# - let/const
@@ -13006,6 +13006,11 @@ def test_es5_transpile(self, args):
1300613006
let obj = Object.assign({}, {prop:1});
1300713007
err('prop: ' + obj.prop);
1300813008

13009+
// for .. of
13010+
for (var elem of [42, 43]) {
13011+
err('array elem: ' + elem);
13012+
}
13013+
1300913014
// arrow funcs + const
1301013015
const bar = () => 2;
1301113016
err('bar: ' + bar());
@@ -13015,14 +13020,14 @@ def test_es5_transpile(self, args):
1301513020
var obj2 = {
1301613021
[key]: 42,
1301713022
};
13018-
err('value: ' + obj2[key]);
13023+
err('computed prop: ' + obj2[key]);
1301913024

1302013025
// Method syntax
1302113026
var obj3 = {
1302213027
myMethod() { return 43 },
1302313028
};
1302413029
global['foo'] = obj3;
13025-
err('value2: ' + obj3.myMethod());
13030+
err('myMethod: ' + obj3.myMethod());
1302613031

1302713032
// Nullish coalescing
1302813033
var definitely = global['maybe'] ?? {};
@@ -13042,6 +13047,15 @@ def test_es5_transpile(self, args):
1304213047
}
1304313048
});
1304413049
''')
13050+
expected = '''\
13051+
prop: 1
13052+
array elem: 42
13053+
array elem: 43
13054+
bar: 2
13055+
computed prop: 42
13056+
myMethod: 43
13057+
'''
13058+
1304513059
create_file('test.c', 'extern void foo(); int main() { foo(); }')
1304613060
self.emcc_args += ['--js-library', 'es6_library.js']
1304713061
self.uses_es6 = True
@@ -13073,26 +13087,26 @@ def check_for_es6(filename, expect):
1307313087
# Check that under normal circumstances none of these features get
1307413088
# removed / transpiled.
1307513089
print('base case')
13076-
self.do_runf('test.c', 'prop: 1\nbar: 2\n')
13090+
self.do_runf('test.c', expected)
1307713091
check_for_es6('test.js', True)
1307813092

1307913093
# If we select and older browser than closure will kick in by default
1308013094
# to transpile.
1308113095
print('with old browser')
1308213096
self.emcc_args.remove('-Werror')
1308313097
self.set_setting('MIN_CHROME_VERSION', '10')
13084-
self.do_runf('test.c', 'prop: 1\nbar: 2\n', output_basename='test_old')
13098+
self.do_runf('test.c', expected, output_basename='test_old')
1308513099
check_for_es6('test_old.js', False)
1308613100

1308713101
# If we add `--closure=0` that transpiler (closure) is not run at all
1308813102
print('with old browser + --closure=0')
13089-
self.do_runf('test.c', 'prop: 1\nbar: 2\n', emcc_args=['--closure=0'], output_basename='test_no_closure')
13103+
self.do_runf('test.c', expected, emcc_args=['--closure=0'], output_basename='test_no_closure')
1309013104
check_for_es6('test_no_closure.js', True)
1309113105

1309213106
# If we use `--closure=1` closure will run in full optimization mode
1309313107
# and also transpile to ES5
1309413108
print('with old browser + --closure=1')
13095-
self.do_runf('test.c', 'prop: 1\nbar: 2\n', emcc_args=['--closure=1'], output_basename='test_closure')
13109+
self.do_runf('test.c', expected, emcc_args=['--closure=1'], output_basename='test_closure')
1309613110
check_for_es6('test_closure.js', False)
1309713111

1309813112
def test_gmtime_noleak(self):

tools/building.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,8 @@ def closure_transpile(filename):
513513
user_args = []
514514
closure_cmd, env = get_closure_compiler_and_env(user_args)
515515
closure_cmd += ['--language_out', 'ES5']
516-
closure_cmd += ['--compilation_level', 'WHITESPACE_ONLY']
516+
closure_cmd += ['--compilation_level', 'SIMPLE_OPTIMIZATIONS']
517+
closure_cmd += ['--formatting', 'PRETTY_PRINT']
517518
return run_closure_cmd(closure_cmd, filename, env)
518519

519520

0 commit comments

Comments
 (0)