document various ECMAScript bugs (#4857)
authorAlex Lam S.L <alexlamsl@gmail.com>
Wed, 21 Apr 2021 00:33:54 +0000 (01:33 +0100)
committerGitHub <noreply@github.com>
Wed, 21 Apr 2021 00:33:54 +0000 (08:33 +0800)
README.md
test/compress/classes.js
test/compress/loops.js
test/ufuzz/index.js

index 914eb56..7f7abae 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1309,3 +1309,21 @@ To allow for better optimizations, the compiler makes various assumptions:
   // Actual:   { '42': undefined }
   ```
   UglifyJS may modify the input which in turn may suppress those errors.
+- Later versions of JavaScript will throw `SyntaxError` with the following:
+  ```javascript
+  var await;
+  async function f() {
+      class A {
+          static p = await;
+      }
+  }
+  // SyntaxError: Unexpected reserved word
+  ```
+  UglifyJS may modify the input which in turn may suppress those errors.
+- Later versions of JavaScript will throw `SyntaxError` with the following:
+  ```javascript
+  var async;
+  for (async of []);
+  // SyntaxError: The left-hand side of a for-of loop may not be 'async'.
+  ```
+  UglifyJS may modify the input which in turn may suppress those errors.
index badcb2e..ca9ddfd 100644 (file)
@@ -777,7 +777,7 @@ unused_await: {
         })();
     }
     expect_stdout: true
-    node_version: ">=12"
+    node_version: ">=12 <16"
 }
 
 computed_key_side_effects: {
index 5a66e02..4ba0d07 100644 (file)
@@ -829,6 +829,18 @@ empty_for_in_prop_init: {
 }
 
 for_of: {
+    input: {
+        var a = [ "PASS", 42 ];
+        a.p = "FAIL";
+        for (a of (null, a))
+            console.log(a);
+    }
+    expect_exact: 'var a=["PASS",42];a.p="FAIL";for(a of(null,a))console.log(a);'
+    expect_stdout: true
+    node_version: ">=0.12"
+}
+
+for_async_of: {
     input: {
         var async = [ "PASS", 42 ];
         async.p = "FAIL";
@@ -837,7 +849,7 @@ for_of: {
     }
     expect_exact: 'var async=["PASS",42];async.p="FAIL";for(async of(null,async))console.log(async);'
     expect_stdout: true
-    node_version: ">=0.12"
+    node_version: ">=0.12 <16"
 }
 
 issue_3631_1: {
index 5c6c262..5a791f1 100644 (file)
@@ -982,8 +982,17 @@ function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn
         var label = createLabel(canBreak, canContinue);
         canBreak = label.break || enableLoopControl(canBreak, CAN_BREAK);
         canContinue = label.continue || enableLoopControl(canContinue, CAN_CONTINUE);
-        var key = rng(10) ? "key" + loop : getVarName(NO_CONST);
         var of = SUPPORT.for_of && rng(20) == 0;
+        var key;
+        if (rng(10)) {
+            key = "key" + loop;
+        } else if (bug_for_of_async && of) {
+            addAvoidVar("async");
+            key = getVarName(NO_CONST);
+            removeAvoidVar("async");
+        } else {
+            key = getVarName(NO_CONST);
+        }
         var init = "";
         if (!/^key/.test(key)) {
             if (!(of && bug_for_of_var) && rng(10) == 0) init = "var ";
@@ -1789,7 +1798,9 @@ function createClassLiteral(recurmax, stmtDepth, canThrow, name) {
             if (rng(5)) {
                 async = false;
                 generator = false;
+                if (bug_async_class_await && fixed) addAvoidVar("await");
                 s += " = " + createExpression(recurmax, NO_COMMA, stmtDepth, fixed ? canThrow : CANNOT_THROW);
+                if (bug_async_class_await && fixed) removeAvoidVar("await");
                 generator = save_generator;
                 async = save_async;
             }
@@ -2383,6 +2394,8 @@ if (SUPPORT.arrow && SUPPORT.async && SUPPORT.rest && typeof sandbox.run_code("a
         return ex.name == "SyntaxError" && ex.message == "Rest parameter must be last formal parameter";
     };
 }
+var bug_async_class_await = SUPPORT.async && SUPPORT.class_field && typeof sandbox.run_code("var await; async function f() { class A { static p = await; } }") != "string";
+var bug_for_of_async = SUPPORT.for_await_of && typeof sandbox.run_code("var async; for (async of []);") != "string";
 var bug_for_of_var = SUPPORT.for_of && SUPPORT.let && typeof sandbox.run_code("try {} catch (e) { for (var e of []); }") != "string";
 if (SUPPORT.destructuring && typeof sandbox.run_code("console.log([ 1 ], {} = 2);") != "string") {
     beautify_options.output.v8 = true;