New Upstream Release - uglify-js
Ready changes
Summary
Merged new upstream version: 3.17.4 (was: 3.17.3).
Resulting package
Built on 2022-11-23T04:24 (took 9m43s)
The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:
apt install -t fresh-releases libjs-uglify-jsapt install -t fresh-releases node-uglify-jsapt install -t fresh-releases uglifyjs
Lintian Result
Diff
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..6edcf864
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+*.js text eol=lf
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 00000000..f6dd9e08
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,51 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+<!-- Note: sub-optimal but correct code is not a bug -->
+
+**Uglify version (`uglifyjs -V`)**
+
+**JavaScript input**
+
+<!--
+A complete parsable JS program exhibiting the issue with UglifyJS alone
+- without third party tools or libraries.
+
+Ideally the input should be as small as possible, but may be large if isolating
+the problem proves to be difficult. The most important thing is that the
+standalone program reliably exhibits the bug when minified. Provide a link to a
+gist if necessary.
+
+Solely providing minified output without the original uglify JS input is not
+useful in determining the cause of the problem. Issues without a reproducible
+test case will be closed.
+-->
+
+**The `uglifyjs` CLI command executed or `minify()` options used.**
+
+<!--
+Command-line or API call to UglifyJS without third party tools or libraries.
+
+For users using bundlers or transpilers, you may be able to gather the required
+information through setting the `UGLIFY_BUG_REPORT` environment variable:
+
+ export UGLIFY_BUG_REPORT=1 (bash)
+ set UGLIFY_BUG_REPORT=1 (Command Prompt)
+ $Env:UGLIFY_BUG_REPORT=1 (PowerShell)
+
+before running your usual build process. The resulting "minified" output should
+contain the necessary details for this report.
+-->
+
+**JavaScript output or error produced.**
+
+<!--
+Only minified code that produces different output (or error) from the original
+upon execution would be considered a bug.
+-->
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 00000000..957e3cc6
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,58 @@
+name: Build testing
+on:
+ pull_request:
+ push:
+ branches: [ master ]
+jobs:
+ ufuzz:
+ strategy:
+ fail-fast: false
+ matrix:
+ options:
+ - '-mb braces'
+ - '--ie -c'
+ - '-mc'
+ - '-p acorn --toplevel -mco spidermonkey'
+ - '--toplevel -mc passes=3,pure_getters,unsafe'
+ script:
+ - acorn.sh
+ - bootstrap.sh
+ - buble.sh
+ - butternut.sh
+ - mathjs.sh
+ - rollup-es.sh
+ - rollup-ts.sh
+ - sucrase.sh
+ - web-tooling-benchmark.sh
+ include:
+ - node: '14'
+ script: acorn.sh
+ - node: '14'
+ script: bootstrap.sh
+ - node: '14'
+ script: buble.sh
+ - node: '14'
+ script: butternut.sh
+ - node: '14'
+ script: mathjs.sh
+ - node: '8'
+ script: rollup-es.sh
+ - node: '14'
+ script: rollup-ts.sh
+ - node: '14'
+ script: sucrase.sh
+ - node: '14'
+ script: web-tooling-benchmark.sh
+ name: ${{ matrix.script }} ${{ matrix.options }}
+ runs-on: ubuntu-latest
+ env:
+ NODE: ${{ matrix.node }}
+ OPTIONS: ${{ matrix.options }}
+ SCRIPT: ${{ matrix.script }}
+ steps:
+ - uses: actions/checkout@v3
+ - name: Perform uglify, build & test
+ shell: bash
+ run: |
+ . ./test/release/install.sh
+ ./test/release/$SCRIPT $OPTIONS
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 00000000..53c44d3f
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,29 @@
+name: CI
+on:
+ pull_request:
+ push:
+ branches: [ master ]
+jobs:
+ test:
+ strategy:
+ matrix:
+ node: [ '0.10', '0.12', '4', '6', '8', '10', '12', '14', '16', latest ]
+ os: [ ubuntu-latest, windows-latest ]
+ script: [ compress, mocha, release/benchmark, release/jetstream ]
+ name: ${{ matrix.node }} ${{ matrix.os }} ${{ matrix.script }}
+ runs-on: ${{ matrix.os }}
+ env:
+ NODE: ${{ matrix.node }}
+ TYPE: ${{ matrix.script }}
+ UGLIFY_GITHUB_LAG: 10000
+ steps:
+ - uses: actions/checkout@v3
+ - uses: actions/cache@v3
+ with:
+ path: tmp
+ key: tmp ${{ matrix.script }}
+ - name: Perform tests
+ shell: bash
+ run: |
+ . ./test/release/install.sh
+ node test/$TYPE
diff --git a/.github/workflows/ufuzz.yml b/.github/workflows/ufuzz.yml
new file mode 100644
index 00000000..43b6ed55
--- /dev/null
+++ b/.github/workflows/ufuzz.yml
@@ -0,0 +1,44 @@
+name: Fuzzing
+on:
+ pull_request:
+ schedule:
+ - cron: '*/15 * * * *'
+ workflow_dispatch:
+ workflow_run:
+ branches: [ master ]
+ types: [ completed ]
+ workflows: [ 'Build testing', CI ]
+env:
+ BASE_URL: https://api.github.com/repos/${{ github.repository }}
+ TOKEN: ${{ github.token }}
+jobs:
+ ufuzz:
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - node: '16'
+ os: macos-latest
+ - node: '12'
+ os: ubuntu-latest
+ - node: '8'
+ os: ubuntu-latest
+ - node: '12'
+ os: windows-latest
+ - node: '8'
+ os: windows-latest
+ name: ${{ matrix.node }} ${{ matrix.os }}
+ runs-on: ${{ matrix.os }}
+ env:
+ NODE: ${{ matrix.node }}
+ steps:
+ - uses: actions/checkout@v3
+ - name: Perform fuzzing
+ shell: bash
+ run: |
+ . ./test/release/install.sh
+ if [[ $GITHUB_EVENT_NAME == "pull_request" ]]; then
+ node test/ufuzz/job 5000
+ else
+ node test/ufuzz/job $BASE_URL $TOKEN $GITHUB_RUN_NUMBER
+ fi
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..6000c6c3
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+/node_modules/
+/npm-debug.log
+tmp/
diff --git a/debian/changelog b/debian/changelog
index dc4c109d..7956eb1e 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+uglify-js (3.17.4-1) UNRELEASED; urgency=low
+
+ * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk> Wed, 23 Nov 2022 04:17:32 -0000
+
uglify-js (3.17.3-2) unstable; urgency=medium
[ Debian Janitor ]
diff --git a/lib/compress.js b/lib/compress.js
index 29543727..cde397cf 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -501,6 +501,23 @@ Compressor.prototype.compress = function(node) {
if (parent instanceof AST_VarDef) return parent.value === node;
}
+ function make_ref(ref, fixed) {
+ var node = make_node(AST_SymbolRef, ref);
+ node.fixed = fixed || make_node(AST_Undefined, ref);
+ return node;
+ }
+
+ function replace_ref(resolve, fixed) {
+ return function(node) {
+ var ref = resolve(node);
+ var node = make_ref(ref, fixed);
+ var def = ref.definition();
+ def.references.push(node);
+ def.replaced++;
+ return node;
+ };
+ }
+
var RE_POSITIVE_INTEGER = /^(0|[1-9][0-9]*)$/;
(function(def) {
def(AST_Node, noop);
@@ -705,22 +722,6 @@ Compressor.prototype.compress = function(node) {
});
}
- function make_ref(ref, fixed) {
- var node = make_node(AST_SymbolRef, ref);
- node.fixed = fixed || make_node(AST_Undefined, ref);
- return node;
- }
-
- function replace_ref(ref, fixed) {
- return function() {
- var node = make_ref(ref, fixed);
- var def = ref.definition();
- def.references.push(node);
- def.replaced++;
- return node;
- };
- }
-
function ref_once(compressor, def) {
return compressor.option("unused")
&& !def.scope.pinned()
@@ -1021,7 +1022,9 @@ Compressor.prototype.compress = function(node) {
};
left.fixed.assigns = !fixed || !fixed.assigns ? [ ld.orig[0] ] : fixed.assigns.slice();
left.fixed.assigns.push(node);
- left.fixed.to_binary = replace_ref(left, fixed);
+ left.fixed.to_binary = replace_ref(function(node) {
+ return node.left;
+ }, fixed);
} else {
left.walk(tw);
ld.fixed = false;
@@ -1529,7 +1532,9 @@ Compressor.prototype.compress = function(node) {
});
};
exp.fixed.assigns = fixed && fixed.assigns;
- exp.fixed.to_prefix = replace_ref(exp, d.fixed);
+ exp.fixed.to_prefix = replace_ref(function(node) {
+ return node.expression;
+ }, d.fixed);
}
} else {
exp.walk(tw);
@@ -2156,7 +2161,7 @@ Compressor.prototype.compress = function(node) {
abort = true;
folded = make_node(AST_Binary, candidate, {
operator: compound,
- left: lhs.fixed && lhs.definition().fixed ? lhs.fixed.to_binary() : lhs,
+ left: lhs.fixed && lhs.definition().fixed ? lhs.fixed.to_binary(candidate) : lhs,
right: rvalue,
});
}
@@ -2220,7 +2225,7 @@ Compressor.prototype.compress = function(node) {
}
if (candidate instanceof AST_UnaryPostfix) return make_node(AST_UnaryPrefix, candidate, {
operator: candidate.operator,
- expression: lhs.fixed && lhs.definition().fixed ? lhs.fixed.to_prefix() : lhs,
+ expression: lhs.fixed && lhs.definition().fixed ? lhs.fixed.to_prefix(candidate) : lhs,
});
if (candidate instanceof AST_UnaryPrefix) {
clear_write_only(candidate);
@@ -3536,7 +3541,7 @@ Compressor.prototype.compress = function(node) {
var declare_only, jump, merge_jump;
var in_iife = in_lambda && parent && parent.TYPE == "Call" && parent.expression === self;
var chain_if_returns = in_lambda && compressor.option("conditionals") && compressor.option("sequences");
- var drop_return_void = !(in_try && in_try.bfinally && in_async_generator(in_lambda));
+ var drop_return_void = !(in_try && in_try.bfinally && in_async_generator(scope));
var multiple_if_returns = has_multiple_if_returns(statements);
for (var i = statements.length; --i >= 0;) {
var stat = statements[i];
@@ -6662,15 +6667,15 @@ Compressor.prototype.compress = function(node) {
do {
var head = first.shift();
if (tail.index > head.index) continue;
- var id = head.definition.id;
- if (!(id in prev)) continue;
- var head_refs = references[id];
+ var prev_def = head.definition;
+ if (!(prev_def.id in prev)) continue;
+ var head_refs = references[prev_def.id];
if (!head_refs) continue;
if (head_refs.start.block !== tail_refs.start.block
|| !mergeable(head_refs, tail_refs)
|| (head_refs.start.loop || !same_scope(def)) && !mergeable(tail_refs, head_refs)
- || compressor.option("webkit") && is_funarg(def) !== is_funarg(head.definition)
- || head.definition.const_redefs
+ || compressor.option("webkit") && is_funarg(def) !== is_funarg(prev_def)
+ || prev_def.const_redefs
|| !all(head_refs.scopes, function(scope) {
return scope.find_variable(def.name) === def;
})) {
@@ -6682,12 +6687,14 @@ Compressor.prototype.compress = function(node) {
sym.name = def.name;
if (sym instanceof AST_SymbolRef) {
def.references.push(sym);
+ prev_def.replaced++;
} else {
def.orig.push(sym);
+ prev_def.eliminated++;
}
});
- if (!head.definition.fixed) def.fixed = false;
- merged[id] = def;
+ if (!prev_def.fixed) def.fixed = false;
+ merged[prev_def.id] = def;
changed = true;
break;
} while (first.length);
@@ -7263,6 +7270,7 @@ Compressor.prototype.compress = function(node) {
return in_list ? List.skip : make_node(AST_EmptyStatement, node);
}
}
+ descend_scope();
if (node instanceof AST_LambdaExpression && node.name && drop_fn_name(node.name.definition())) {
node.name = null;
}
@@ -7357,6 +7365,7 @@ Compressor.prototype.compress = function(node) {
}
fns_with_marked_args.push(node);
}
+ return node;
}
if (node instanceof AST_Catch && node.argname instanceof AST_Destructured) {
node.argname.transform(trimmer);
@@ -8823,7 +8832,8 @@ Compressor.prototype.compress = function(node) {
var negated = node.clone();
negated.operator = op == "&&" ? "||" : "&&";
negated.left = left.negate(compressor, first_in_statement);
- if (negated.operator == negated.right.operator) swap_chain(negated);
+ var negated_rhs = negated.right.tail_node();
+ if (negated_rhs instanceof AST_Binary && negated.operator == negated_rhs.operator) swap_chain(negated);
var best = first_in_statement ? best_of_statement : best_of_expression;
return op == "&&" ? best(node, negated) : best(negated, node);
}
@@ -11607,7 +11617,14 @@ Compressor.prototype.compress = function(node) {
}
function swap_chain(self, compressor) {
- var rhs = self.right;
+ var rhs = self.right.tail_node();
+ if (rhs !== self.right) {
+ var exprs = self.right.expressions.slice(0, -1);
+ exprs.push(rhs.left);
+ rhs = rhs.clone();
+ rhs.left = make_sequence(self.right, exprs);
+ self.right = rhs;
+ }
self.left = make_node(AST_Binary, self, {
operator: self.operator,
left: self.left,
@@ -11799,15 +11816,16 @@ Compressor.prototype.compress = function(node) {
left: self.left.right,
right: self.right,
});
- var after = before.optimize(compressor);
+ var after = before.transform(compressor);
if (before !== after) {
self.left = self.left.left;
self.right = after;
}
}
// x && (y && z) ---> x && y && z
- // x || (y || z) ---> x || y || z
- if (self.right instanceof AST_Binary && self.operator == self.right.operator) swap_chain(self, compressor);
+ // w || (x, y || z) ---> w || (x, y) || z
+ var rhs = self.right.tail_node();
+ if (rhs instanceof AST_Binary && self.operator == rhs.operator) swap_chain(self, compressor);
}
if (compressor.option("strings") && self.operator == "+") {
// "foo" + 42 + "" ---> "foo" + 42
@@ -11833,12 +11851,13 @@ Compressor.prototype.compress = function(node) {
return self.optimize(compressor);
}
// "x" + (y + "z") ---> "x" + y + "z"
- // x + ("y" + z) ---> x + "y" + z
- if (self.right instanceof AST_Binary
- && self.operator == self.right.operator
- && (self.left.is_string(compressor) && self.right.is_string(compressor)
- || self.right.left.is_string(compressor)
- && (self.left.is_constant() || !self.right.right.has_side_effects(compressor)))) {
+ // w + (x, "y" + z) ---> w + (x, "y") + z
+ var rhs = self.right.tail_node();
+ if (rhs instanceof AST_Binary
+ && self.operator == rhs.operator
+ && (self.left.is_string(compressor) && rhs.is_string(compressor)
+ || rhs.left.is_string(compressor)
+ && (self.left.is_constant() || !rhs.right.has_side_effects(compressor)))) {
swap_chain(self, compressor);
}
}
@@ -12766,34 +12785,19 @@ Compressor.prototype.compress = function(node) {
}
if (compressor.option("assignments")) {
if (self.operator == "=" && self.left instanceof AST_SymbolRef && self.right instanceof AST_Binary) {
- var ref;
// x = expr1 OP expr2
- if ((ref = self.right.left) instanceof AST_SymbolRef
- && ref.name == self.left.name
+ if (self.right.left instanceof AST_SymbolRef
+ && self.right.left.name == self.left.name
&& ASSIGN_OPS[self.right.operator]) {
// x = x - 2 ---> x -= 2
- if (self.left.fixed) self.left.fixed.to_binary = function() {
- return ref;
- };
- return make_node(AST_Assign, self, {
- operator: self.right.operator + "=",
- left: self.left,
- right: self.right.right,
- });
+ return make_compound(self.right.right);
}
- if ((ref = self.right.right) instanceof AST_SymbolRef
- && ref.name == self.left.name
+ if (self.right.right instanceof AST_SymbolRef
+ && self.right.right.name == self.left.name
&& ASSIGN_OPS_COMMUTATIVE[self.right.operator]
&& !self.right.left.has_side_effects(compressor)) {
// x = 2 & x ---> x &= 2
- if (self.left.fixed) self.left.fixed.to_binary = function() {
- return ref;
- };
- return make_node(AST_Assign, self, {
- operator: self.right.operator + "=",
- left: self.left,
- right: self.right.left,
- });
+ return make_compound(self.right.left);
}
}
if ((self.operator == "-=" || self.operator == "+="
@@ -12856,6 +12860,18 @@ Compressor.prototype.compress = function(node) {
return find_try(compressor, level, node, scope, may_throw, sync);
}
+ function make_compound(rhs) {
+ var fixed = self.left.fixed;
+ if (fixed) fixed.to_binary = replace_ref(function(node) {
+ return node.left;
+ }, fixed);
+ return make_node(AST_Assign, self, {
+ operator: self.right.operator + "=",
+ left: self.left,
+ right: rhs,
+ });
+ }
+
function strip_assignment(def) {
if (def) def.fixed = false;
return (self.operator != "=" ? make_node(AST_Binary, self, {
@@ -13101,7 +13117,7 @@ Compressor.prototype.compress = function(node) {
operator: "||",
left: booleanize(condition),
right: alternative,
- });
+ }).optimize(compressor);
}
if (is_false(consequent)) {
// c ? false : true ---> !c
@@ -13111,20 +13127,20 @@ Compressor.prototype.compress = function(node) {
operator: "&&",
left: booleanize(condition.negate(compressor)),
right: alternative,
- });
+ }).optimize(compressor);
}
// c ? x : true ---> !c || x
if (is_true(alternative)) return make_node(AST_Binary, self, {
operator: "||",
left: booleanize(condition.negate(compressor)),
right: consequent,
- });
+ }).optimize(compressor);
// c ? x : false ---> !!c && x
if (is_false(alternative)) return make_node(AST_Binary, self, {
operator: "&&",
left: booleanize(condition),
right: consequent,
- });
+ }).optimize(compressor);
if (compressor.option("typeofs")) mark_locally_defined(condition, consequent, alternative);
return self;
diff --git a/package.json b/package.json
index dcaa7df5..5776de16 100644
--- a/package.json
+++ b/package.json
@@ -3,7 +3,7 @@
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause",
- "version": "3.17.3",
+ "version": "3.17.4",
"engines": {
"node": ">=0.8.0"
},
diff --git a/test/compress/concat-strings.js b/test/compress/concat-strings.js
index d2790d08..ac252b06 100644
--- a/test/compress/concat-strings.js
+++ b/test/compress/concat-strings.js
@@ -273,6 +273,23 @@ concat_9: {
expect_stdout: true
}
+concat_sequence: {
+ options = {
+ collapse_vars: true,
+ strings: true,
+ toplevel: true,
+ unused: true,
+ }
+ input: {
+ var a;
+ console.log(12 + (a = null, "34" + a));
+ }
+ expect: {
+ console.log(12 + "34" + null);
+ }
+ expect_stdout: "1234null"
+}
+
issue_3689: {
options = {
strings: true,
diff --git a/test/compress/conditionals.js b/test/compress/conditionals.js
index f42cce97..66de5c7d 100644
--- a/test/compress/conditionals.js
+++ b/test/compress/conditionals.js
@@ -3051,3 +3051,20 @@ issue_5694: {
}
expect_stdout: "NaN"
}
+
+issue_5712: {
+ options = {
+ booleans: true,
+ conditionals: true,
+ evaluate: true,
+ }
+ input: {
+ var a = 0;
+ a || (++a).toString() && a && console.log("PASS");
+ }
+ expect: {
+ var a = 0;
+ a || (++a).toString() && a && console.log("PASS");
+ }
+ expect_stdout: "PASS"
+}
diff --git a/test/compress/merge_vars.js b/test/compress/merge_vars.js
index 7082491e..e7b1be3a 100644
--- a/test/compress/merge_vars.js
+++ b/test/compress/merge_vars.js
@@ -3845,3 +3845,47 @@ issue_5471_2: {
}
expect_stdout: "PASS"
}
+
+issue_5714: {
+ options = {
+ inline: true,
+ join_vars: true,
+ loops: true,
+ merge_vars: true,
+ unused: true,
+ }
+ input: {
+ "use strict";
+ console.log(function() {
+ var i = 1;
+ while (i--) {
+ var a = function f(b) {
+ console.log(b);
+ var c = function(d) {
+ console.log(typeof d);
+ }(console);
+ }();
+ var e = 42;
+ }
+ return e;
+ }());
+ }
+ expect: {
+ "use strict";
+ console.log(function() {
+ for (var i = 1; i--;) {
+ var b = void 0;
+ console.log(b);
+ b = console,
+ console.log(typeof b);
+ var e = 42;
+ }
+ return e;
+ }());
+ }
+ expect_stdout: [
+ "undefined",
+ "object",
+ "42",
+ ]
+}
diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js
index 885887ed..93eccafe 100644
--- a/test/compress/reduce_vars.js
+++ b/test/compress/reduce_vars.js
@@ -7927,3 +7927,138 @@ issue_5623: {
}
expect_stdout: "1"
}
+
+issue_5716_1: {
+ options = {
+ collapse_vars: true,
+ inline: true,
+ merge_vars: true,
+ reduce_vars: true,
+ toplevel: true,
+ unused: true,
+ }
+ input: {
+ var a;
+ function f() {
+ var b = [ c, c ], c = function() {
+ return b++ + (a = b);
+ }();
+ }
+ f();
+ console.log(a);
+ }
+ expect: {
+ c = [ c, c ],
+ void (c = ++c);
+ var c;
+ console.log(c);
+ }
+ expect_stdout: "NaN"
+}
+
+issue_5716_2: {
+ options = {
+ collapse_vars: true,
+ inline: true,
+ merge_vars: true,
+ reduce_vars: true,
+ toplevel: true,
+ unused: true,
+ }
+ input: {
+ var a;
+ function f() {
+ var b = [ c, c ], c = function() {
+ return (b += 4) + (a = b += 2);
+ }();
+ }
+ f();
+ console.log(a);
+ }
+ expect: {
+ void (c = c = (c = [ c, c ]) + 4 + 2);
+ var c;
+ console.log(c);
+ }
+ expect_stdout: ",42"
+}
+
+issue_5716_3: {
+ options = {
+ assignments: true,
+ collapse_vars: true,
+ inline: true,
+ merge_vars: true,
+ reduce_vars: true,
+ toplevel: true,
+ unused: true,
+ }
+ input: {
+ var a;
+ function f() {
+ var b = [ c, c ], c = function() {
+ return (b = b + 4) + (a = b += 2);
+ }();
+ }
+ f();
+ console.log(a);
+ }
+ expect: {
+ void (c = c = (c = [ c, c ]) + 4 + 2);
+ var c;
+ console.log(c);
+ }
+ expect_stdout: ",42"
+}
+
+issue_5716_4: {
+ options = {
+ assignments: true,
+ collapse_vars: true,
+ inline: true,
+ merge_vars: true,
+ reduce_vars: true,
+ toplevel: true,
+ unused: true,
+ }
+ input: {
+ var a;
+ function f() {
+ var b = [ c, c ], c = function() {
+ return (b = true | b) + (a = b *= 42);
+ }();
+ }
+ f();
+ console.log(a);
+ }
+ expect: {
+ void (c = c = ((c = [ c, c ]) | true) * 42);
+ var c;
+ console.log(c);
+ }
+ expect_stdout: "42"
+}
+
+issue_5716_5: {
+ options = {
+ assignments: true,
+ reduce_vars: true,
+ }
+ input: {
+ console.log(function() {
+ return 0 || (a = 42 | a);
+ var a = function() {
+ return a;
+ };
+ }());
+ }
+ expect: {
+ console.log(function() {
+ return 0 || (a |= 42);
+ var a = function() {
+ return a;
+ };
+ }());
+ }
+ expect_stdout: "42"
+}
diff --git a/test/compress/rests.js b/test/compress/rests.js
index b18ab0b4..4d020d23 100644
--- a/test/compress/rests.js
+++ b/test/compress/rests.js
@@ -1624,3 +1624,21 @@ issue_5552_4: {
expect_stdout: "PASS"
node_version: ">=6"
}
+
+issue_5705: {
+ options = {
+ reduce_vars: true,
+ rests: true,
+ unused: true,
+ }
+ input: {
+ (function(...a) {
+ var b = { ...a };
+ })(console.log("PASS"));
+ }
+ expect: {
+ (function() {})(console.log("PASS"));
+ }
+ expect_stdout: "PASS"
+ node_version: ">=8.3.0"
+}
diff --git a/test/compress/transform.js b/test/compress/transform.js
index a06d08a9..e3621eb2 100644
--- a/test/compress/transform.js
+++ b/test/compress/transform.js
@@ -127,7 +127,7 @@ if_return: {
if (w) {
if (y) return;
} else if (z) return;
- return x != y && (x && w(), y && z()), !0;
+ return x != y && (x && w(), y) && z(), !0;
}
}
}
diff --git a/test/compress/yields.js b/test/compress/yields.js
index 8478d541..835eff1c 100644
--- a/test/compress/yields.js
+++ b/test/compress/yields.js
@@ -2018,3 +2018,61 @@ issue_5684: {
expect_stdout: "PASS"
node_version: ">=10"
}
+
+issue_5707: {
+ options = {
+ hoist_props: true,
+ reduce_vars: true,
+ side_effects: true,
+ toplevel: true,
+ unused: true,
+ yields: true,
+ }
+ input: {
+ var a, b;
+ function* f(c = (b = 42, console.log("PASS"))) {}
+ b = f();
+ }
+ expect: {
+ console.log("PASS");
+ }
+ expect_stdout: "PASS"
+ node_version: ">=6"
+}
+
+issue_5710: {
+ options = {
+ conditionals: true,
+ if_return: true,
+ }
+ input: {
+ (async function*() {
+ try {
+ switch (42) {
+ case 42:
+ {
+ if (console.log("PASS"))
+ return;
+ return null;
+ }
+ break;
+ }
+ } finally {}
+ })().next();
+ }
+ expect: {
+ (async function*() {
+ try {
+ switch (42) {
+ case 42:
+ if (console.log("PASS"))
+ return;
+ return null;
+ break;
+ }
+ } finally {}
+ })().next();
+ }
+ expect_stdout: "PASS"
+ node_version: ">=10"
+}