diff --git a/ChangeLog.md b/ChangeLog.md index 4189cc53f7510..11fb822277f88 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -30,6 +30,9 @@ See docs/process.md for more on how version tagging works. - If exceptions are disabled, using `new` together with `std::nothrow` no longer aborts if the allocation fails. Instead `nullptr` is returned now. This does not change the behavior of regular usage of `new`. +- Default `MIN_CHROME_VERSION` was increased from 75 to 85 and default + `MIN_FIREFOX_VERSION` was increased from 68 to 79 to allow Emscripten + to use some ES2021 features for smaller JavaScript code size. (#20549) 3.1.47 - 10/09/23 ----------------- diff --git a/src/settings.js b/src/settings.js index 4109dcfbd80c6..5764f26d97f8c 100644 --- a/src/settings.js +++ b/src/settings.js @@ -1768,10 +1768,10 @@ var AUTO_NATIVE_LIBRARIES = true; // versions >= MIN_FIREFOX_VERSION // are desired to work. Pass -sMIN_FIREFOX_VERSION=majorVersion to drop support // for Firefox versions older than < majorVersion. -// Firefox ESR 68 was released on July 9, 2019. +// Firefox 79 was released on 2020-07-28. // MAX_INT (0x7FFFFFFF, or -1) specifies that target is not supported. // [link] -var MIN_FIREFOX_VERSION = 68; +var MIN_FIREFOX_VERSION = 79; // Specifies the oldest version of desktop Safari to target. Version is encoded // in MMmmVV, e.g. 70101 denotes Safari 7.1.1. @@ -1810,10 +1810,10 @@ var MIN_EDGE_VERSION = 0x7FFFFFFF; // Specifies the oldest version of Chrome. E.g. pass -sMIN_CHROME_VERSION=58 to // drop support for Chrome 57 and older. -// Chrome 75.0.3770 was released on 2019-06-04 +// Chrome 85 was released on 2020-08-25. // MAX_INT (0x7FFFFFFF, or -1) specifies that target is not supported. // [link] -var MIN_CHROME_VERSION = 75; +var MIN_CHROME_VERSION = 85; // Specifies minimum node version to target for the generated code. This is // distinct from the minimum version required run the emscripten compiler. diff --git a/test/test_core.py b/test/test_core.py index 885419f07d783..178946806b010 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -9907,13 +9907,9 @@ def test_main_reads_args(self): @requires_node def test_promise(self): # This test depends on Promise.any, which in turn requires a modern target. Check that it - # fails to even build without bumping the min versions: - err = self.expect_fail([EMCC, test_file('core/test_promise.c')]) + # fails to even build on old targets. + err = self.expect_fail([EMCC, test_file('core/test_promise.c'), '-sMIN_CHROME_VERSION=75']) self.assertContained('error: emscripten_promise_any used, but Promise.any is not supported by the current runtime configuration', err) - self.set_setting('MIN_NODE_VERSION', '150000') - self.set_setting('MIN_SAFARI_VERSION', '150000') - self.set_setting('MIN_FIREFOX_VERSION', '79') - self.set_setting('MIN_CHROME_VERSION', '85') self.do_core_test('test_promise.c') @with_asyncify_and_jspi diff --git a/test/test_other.py b/test/test_other.py index 5d39d6e79ff36..0080ab9ed0497 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -12967,6 +12967,8 @@ def test_es5_transpile(self, args): # - arrow funcs # - for..of # - object.assign + # - nullish coalescing & chaining + # - logical assignment create_file('es6_library.js', '''\ addToLibrary({ foo: function(arg="hello") { @@ -12974,7 +12976,7 @@ def test_es5_transpile(self, args): let obj = Object.assign({}, {prop:1}); err('prop: ' + obj.prop); - // arror funcs + const + // arrow funcs + const const bar = () => 2; err('bar: ' + bar()); @@ -12991,6 +12993,22 @@ def test_es5_transpile(self, args): }; global['foo'] = obj3; err('value2: ' + obj3.myMethod()); + + // Nullish coalescing + var definitely = global['maybe'] ?? {}; + + // Optional chaining + global['maybe'] + ?.subObj + ?.[key] + ?.func + ?.(); + + // Logical assignment + var obj4 = null; + obj4 ??= 0; + obj4 ||= 1; + obj4 &&= 2; } }); ''') @@ -13005,6 +13023,11 @@ def check_for_es6(filename, expect): self.assertContained(['() => 2', '()=>2'], js) self.assertContained('const ', js) self.assertContained('let ', js) + self.assertContained('?.[', js) + self.assertContained('?.(', js) + self.assertContained('??=', js) + self.assertContained('||=', js) + self.assertContained('&&=', js) else: self.verify_es5(filename) self.assertNotContained('foo(arg=', js) @@ -13012,6 +13035,10 @@ def check_for_es6(filename, expect): self.assertNotContained('()=>2', js) self.assertNotContained('const ', js) self.assertNotContained('let ', js) + self.assertNotContained('??', js) + self.assertNotContained('?.', js) + self.assertNotContained('||=', js) + self.assertNotContained('&&=', js) # Check that under normal circumstances none of these features get # removed / transpiled. diff --git a/tools/acorn-optimizer.js b/tools/acorn-optimizer.js index 8260ec601112b..2d97919f7959c 100755 --- a/tools/acorn-optimizer.js +++ b/tools/acorn-optimizer.js @@ -1044,7 +1044,7 @@ function applyDCEGraphRemovals(ast) { // Need a parser to pass to acorn.Node constructor. // Create it once and reuse it. -const stubParser = new acorn.Parser({ecmaVersion: 2020}); +const stubParser = new acorn.Parser({ecmaVersion: 2021}); function createNode(props) { const node = new acorn.Node(stubParser); @@ -2008,7 +2008,7 @@ let ast; try { ast = acorn.parse(input, { // Keep in sync with --language_in that we pass to closure in building.py - ecmaVersion: 2020, + ecmaVersion: 2021, preserveParens: closureFriendly, onComment: closureFriendly ? sourceComments : undefined, sourceType: exportES6 ? 'module' : 'script', diff --git a/tools/building.py b/tools/building.py index 7f063bffb07c1..c24f1c41c6fdf 100644 --- a/tools/building.py +++ b/tools/building.py @@ -567,7 +567,7 @@ def closure_compiler(filename, advanced=True, extra_closure_args=None): args = ['--compilation_level', 'ADVANCED_OPTIMIZATIONS' if advanced else 'SIMPLE_OPTIMIZATIONS'] # Keep in sync with ecmaVersion in tools/acorn-optimizer.js - args += ['--language_in', 'ECMASCRIPT_2020'] + args += ['--language_in', 'ECMASCRIPT_2021'] # Tell closure not to do any transpiling or inject any polyfills. # At some point we may want to look into using this as way to convert to ES5 but # babel is perhaps a better tool for that. diff --git a/tools/unsafe_optimizations.js b/tools/unsafe_optimizations.js index 41641f93499d3..45e8d01c3545b 100644 --- a/tools/unsafe_optimizations.js +++ b/tools/unsafe_optimizations.js @@ -223,7 +223,7 @@ function optPassMergeVarInitializationAssignments(ast) { } function runOnJsText(js, pretty = false) { - const ast = acorn.parse(js, {ecmaVersion: 2020}); + const ast = acorn.parse(js, {ecmaVersion: 2021}); optPassSimplifyModuleInitialization(ast); optPassRemoveRedundantOperatorNews(ast);