Compare commits

...

50 Commits

Author SHA1 Message Date
Alex Lam S.L
860aa9531b v3.14.4 2021-12-01 02:34:20 +08:00
Alex Lam S.L
2547542873 workaround sporadic slowdown in GitHub Actions (#5201) 2021-11-28 08:45:29 +08:00
Alex Lam S.L
3f8f0e246e fix corner case in collapse_vars (#5200)
fixes #5199
2021-11-28 01:43:43 +08:00
Alex Lam S.L
12227ebbb0 workaround toString() quirks on global context (#5198)
closes #5197
2021-11-27 23:17:51 +08:00
Alex Lam S.L
1b4bd7082b fix corner case in hoist_vars (#5196)
fixes #5195
2021-11-25 04:49:38 +08:00
Alex Lam S.L
0b6c185818 enhance merge_vars (#5194)
closes #5182
2021-11-24 19:08:40 +08:00
Alex Lam S.L
bfd0ac7f4b fix corner case in ie (#5193)
fixes #5192
2021-11-24 17:29:26 +08:00
Alex Lam S.L
1a8f2ecc65 enhance collapse_vars (#5186)
closes #5182
2021-11-24 17:28:36 +08:00
Alex Lam S.L
dc9e1ff0b1 fix corner case in unused (#5190)
fixes #5189
2021-11-23 20:10:05 +08:00
Alex Lam S.L
ea10498902 fix corner case in hoist_vars (#5188)
fixes #5187
2021-11-23 18:00:47 +08:00
Alex Lam S.L
69636dad69 improve sandbox async detection (#5185)
closes #5184
2021-11-23 02:29:54 +08:00
Alex Lam S.L
3ee1b0d00d enhance hoist_props & reduce_vars (#5183)
closes #5182
2021-11-23 00:31:10 +08:00
Alex Lam S.L
1e3ca4c6f7 enhance side_effects & unused (#5181) 2021-11-22 11:14:28 +08:00
Alex Lam S.L
839f4361f4 minor clean-up (#5180) 2021-11-19 16:34:11 +08:00
Alex Lam S.L
ae5c3ee8a1 fix corner cases in properties (#5178)
fixes #5177
2021-11-17 04:21:44 +08:00
Alex Lam S.L
77f7ae5ba2 fix corner case in join_vars (#5176)
fixes #5175
2021-11-15 21:35:54 +08:00
Alex Lam S.L
2d0f8bcff5 fix corner case in inline (#5174)
fixes #5173
2021-11-15 07:14:08 +08:00
Alex Lam S.L
f97e107c09 enhance reduce_vars (#5171) 2021-11-13 22:18:56 +08:00
Alex Lam S.L
e9932e1314 fix corner case in collapse_vars (#5169)
fixes #5168
2021-11-13 22:18:18 +08:00
Alex Lam S.L
eaa84d32df include Node.js v16 in CI tests (#5170)
- fix compatibility issues on v0.10 & v0.12
2021-11-13 18:34:18 +08:00
Alex Lam S.L
6e4aa0326f enhance reduce_vars (#5164)
- fix corner case in `join_vars`
2021-11-04 18:36:39 +08:00
Alex Lam S.L
f9a4b36dd1 fix corner cases in reduce_vars & rests (#5166)
fixes #5165
2021-11-03 21:29:01 +08:00
Alex Lam S.L
3acb5a329e enhance join_vars (#5162) 2021-11-02 11:33:24 +08:00
Alex Lam S.L
6d94242318 enhance reduce_vars (#5163) 2021-11-02 11:32:26 +08:00
Alex Lam S.L
bca83cb9df v3.14.3 2021-11-02 05:03:46 +08:00
Alex Lam S.L
a841d45bc3 fix corner case in awaits (#5160)
fixes #5159
2021-10-31 23:46:55 +08:00
Alex Lam S.L
eb93d92357 fix corner case in awaits (#5158)
fixes #5157
2021-10-29 23:33:10 +08:00
Alex Lam S.L
a0250ec923 fix corner case in dead_code (#5154)
fixes #5153
2021-10-25 06:18:16 +08:00
Alex Lam S.L
25801627be parse let as symbol names correctly (#5151)
fixes #5149
2021-10-21 02:14:29 +08:00
Alex Lam S.L
32ae994f88 fix issues in tests flagged by LGTM (#5150) 2021-10-21 02:07:23 +08:00
Alex Lam S.L
03aec89f60 fix corner cases in strings & templates (#5147)
fixes #5145
2021-10-16 18:02:23 +08:00
Alex Lam S.L
faf0190546 document ECMAScript quirks (#5148)
- exclude Node.js v0.8 from CI as npm registry no longer works

closes #5146
2021-10-16 13:28:13 +08:00
Alex Lam S.L
c8b0f685ee fix corner case in merge_vars (#5143)
fixes #5142
2021-10-05 00:42:46 +08:00
Alex Lam S.L
87b99162fb fix corner case in inline (#5141)
fixes #5140
2021-10-02 06:54:42 +08:00
Alex Lam S.L
940887f20f fix corner case in evaluate (#5139)
fixes #5138
2021-10-01 02:52:21 +08:00
Alex Lam S.L
0b2573c3fa fix corner case in templates (#5137)
fixes #5136
2021-09-30 21:43:34 +08:00
Alex Lam S.L
157521066f avoid potential RegExp denial-of-service (#5135)
closes #5133
closes #5134
2021-09-30 01:49:46 +08:00
Alex Lam S.L
f766babf5e enhance templates (#5131)
closes #5125
2021-09-23 18:26:26 +08:00
Alex Lam S.L
436a29367c enhance dead_code (#5130) 2021-09-22 03:11:45 +08:00
Alex Lam S.L
55418fd460 fix corner case in rests (#5129)
fixes #5128
2021-09-20 05:02:35 +08:00
Alex Lam S.L
85786889bd v3.14.2 2021-09-07 21:52:59 +08:00
Alex Lam S.L
4b88dfb8d9 tweak test & warnings (#5123)
closes #5116
closes #5117
closes #5122
2021-09-07 01:33:23 +08:00
Alex Lam S.L
c3aef23614 fix corner case in reduce_vars (#5121)
fixes #5120
2021-08-25 10:39:35 +08:00
Alex Lam S.L
db94d21980 fix corner case in side_effects (#5118) 2021-08-23 08:51:59 +08:00
Alex Lam S.L
9634a9d1fd fix corner cases in optional_chains (#5110) 2021-08-20 10:10:10 +08:00
Alex Lam S.L
befb99bd71 fix corner case in inline (#5115)
fixes #5114
2021-08-18 15:57:08 +08:00
Alex Lam S.L
02eb8baa1c fix corner case in collapse_vars (#5113)
fixes #5112
2021-08-18 10:54:24 +08:00
Alex Lam S.L
c09f63aefb fix corner case in rests (#5109)
fixes #5108
2021-08-09 08:59:33 +08:00
Alex Lam S.L
fdcc6d3a9c fix corner case in dead_code (#5107)
fixes #5106
2021-08-06 08:35:11 +08:00
Alex Lam S.L
4fe2cac35e enhance inline (#5105) 2021-07-27 21:47:01 +08:00
50 changed files with 2879 additions and 484 deletions

View File

@@ -7,14 +7,9 @@ jobs:
test: test:
strategy: strategy:
matrix: matrix:
node: [ '0.8', '0.10', '0.12', '4', '6', '8', '10', '12', '14', latest ] node: [ '0.10', '0.12', '4', '6', '8', '10', '12', '14', '16', latest ]
os: [ ubuntu-latest, windows-latest ] os: [ ubuntu-latest, windows-latest ]
script: [ compress, mocha, release/benchmark, release/jetstream ] script: [ compress, mocha, release/benchmark, release/jetstream ]
exclude:
- node: '0.8'
script: release/benchmark
- node: '0.8'
script: release/jetstream
name: ${{ matrix.node }} ${{ matrix.os }} ${{ matrix.script }} name: ${{ matrix.node }} ${{ matrix.os }} ${{ matrix.script }}
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
env: env:

View File

@@ -1199,6 +1199,17 @@ To allow for better optimizations, the compiler makes various assumptions:
- Object properties can be added, removed and modified (not prevented with - Object properties can be added, removed and modified (not prevented with
`Object.defineProperty()`, `Object.defineProperties()`, `Object.freeze()`, `Object.defineProperty()`, `Object.defineProperties()`, `Object.freeze()`,
`Object.preventExtensions()` or `Object.seal()`). `Object.preventExtensions()` or `Object.seal()`).
- If array destructuring is present, index-like properties in `Array.prototype`
have not been overridden:
```javascript
Object.prototype[0] = 42;
var [ a ] = [];
var { 0: b } = {};
// 42 undefined
console.log([][0], a);
// 42 42
console.log({}[0], b);
```
- Earlier versions of JavaScript will throw `SyntaxError` with the following: - Earlier versions of JavaScript will throw `SyntaxError` with the following:
```javascript ```javascript
({ ({

View File

@@ -1289,13 +1289,14 @@ function must_be_expressions(node, prop, allow_spread, allow_hole) {
}); });
} }
var AST_Call = DEFNODE("Call", "args expression optional pure", { var AST_Call = DEFNODE("Call", "args expression optional pure terminal", {
$documentation: "A function call expression", $documentation: "A function call expression",
$propdoc: { $propdoc: {
args: "[AST_Node*] array of arguments", args: "[AST_Node*] array of arguments",
expression: "[AST_Node] expression to invoke as function", expression: "[AST_Node] expression to invoke as function",
optional: "[boolean] whether the expression is optional chaining", optional: "[boolean] whether the expression is optional chaining",
pure: "[string/S] marker for side-effect-free call expression", pure: "[string/S] marker for side-effect-free call expression",
terminal: "[boolean] whether the chain has ended",
}, },
walk: function(visitor) { walk: function(visitor) {
var node = this; var node = this;
@@ -1316,6 +1317,7 @@ var AST_New = DEFNODE("New", null, {
$documentation: "An object instantiation. Derives from a function call since it has exactly the same properties", $documentation: "An object instantiation. Derives from a function call since it has exactly the same properties",
_validate: function() { _validate: function() {
if (this.optional) throw new Error("optional must be false"); if (this.optional) throw new Error("optional must be false");
if (this.terminal) throw new Error("terminal must be false");
}, },
}, AST_Call); }, AST_Call);
@@ -1338,12 +1340,18 @@ var AST_Sequence = DEFNODE("Sequence", "expressions", {
}, },
}); });
var AST_PropAccess = DEFNODE("PropAccess", "expression optional property", { function root_expr(prop) {
while (prop instanceof AST_PropAccess) prop = prop.expression;
return prop;
}
var AST_PropAccess = DEFNODE("PropAccess", "expression optional property terminal", {
$documentation: "Base class for property access expressions, i.e. `a.foo` or `a[\"foo\"]`", $documentation: "Base class for property access expressions, i.e. `a.foo` or `a[\"foo\"]`",
$propdoc: { $propdoc: {
expression: "[AST_Node] the “container” expression", expression: "[AST_Node] the “container” expression",
optional: "[boolean] whether the expression is optional chaining", optional: "[boolean] whether the expression is optional chaining",
property: "[AST_Node|string] the property to access. For AST_Dot this is always a plain string, while for AST_Sub it's an arbitrary AST_Node", property: "[AST_Node|string] the property to access. For AST_Dot this is always a plain string, while for AST_Sub it's an arbitrary AST_Node",
terminal: "[boolean] whether the chain has ended",
}, },
get_property: function() { get_property: function() {
var p = this.property; var p = this.property;
@@ -1991,7 +1999,7 @@ TreeWalker.prototype = {
}, },
find_parent: function(type) { find_parent: function(type) {
var stack = this.stack; var stack = this.stack;
for (var i = stack.length; --i >= 0;) { for (var i = stack.length - 1; --i >= 0;) {
var x = stack[i]; var x = stack[i];
if (x instanceof type) return x; if (x instanceof type) return x;
} }

File diff suppressed because it is too large Load Diff

View File

@@ -556,7 +556,9 @@
return node; return node;
}, },
ChainExpression: function(M) { ChainExpression: function(M) {
return from_moz(M.expression); var node = from_moz(M.expression);
node.terminal = true;
return node;
}, },
}; };
@@ -868,7 +870,7 @@
def_to_moz(AST_PropAccess, function To_Moz_MemberExpression(M) { def_to_moz(AST_PropAccess, function To_Moz_MemberExpression(M) {
var computed = M instanceof AST_Sub; var computed = M instanceof AST_Sub;
return { var expr = {
type: "MemberExpression", type: "MemberExpression",
object: to_moz(M.expression), object: to_moz(M.expression),
computed: computed, computed: computed,
@@ -878,6 +880,10 @@
name: M.property, name: M.property,
}, },
}; };
return M.terminal ? {
type: "ChainExpression",
expression: expr,
} : expr;
}); });
def_to_moz(AST_Unary, function To_Moz_Unary(M) { def_to_moz(AST_Unary, function To_Moz_Unary(M) {

View File

@@ -790,35 +790,26 @@ function OutputStream(options) {
if (p instanceof AST_Unary) return true; if (p instanceof AST_Unary) return true;
}); });
function lhs_has_optional(node, output) { function need_chain_parens(node, parent) {
var p = output.parent(); if (!node.terminal) return false;
if (p instanceof AST_PropAccess && p.expression === node && is_lhs(p, output.parent(1))) { if (!(parent instanceof AST_Call || parent instanceof AST_PropAccess)) return false;
// ++(foo?.bar).baz return parent.expression === node;
// (foo?.()).bar = baz
do {
if (node.optional) return true;
node = node.expression;
} while (node.TYPE == "Call" || node instanceof AST_PropAccess);
}
} }
PARENS(AST_PropAccess, function(output) { PARENS(AST_PropAccess, function(output) {
var node = this; var node = this;
var p = output.parent(); var p = output.parent();
if (p instanceof AST_New) { // i.e. new (foo().bar)
if (p.expression !== node) return false; //
// i.e. new (foo().bar) // if there's one call into this subtree, then we need
// // parens around it too, otherwise the call will be
// if there's one call into this subtree, then we need // interpreted as passing the arguments to the upper New
// parens around it too, otherwise the call will be // expression.
// interpreted as passing the arguments to the upper New if (p instanceof AST_New && p.expression === node && root_expr(node).TYPE == "Call") return true;
// expression. // (foo?.bar)()
do { // (foo?.bar).baz
node = node.expression; // new (foo?.bar)()
} while (node instanceof AST_PropAccess); return need_chain_parens(node, p);
return node.TYPE == "Call";
}
return lhs_has_optional(node, output);
}); });
PARENS(AST_Call, function(output) { PARENS(AST_Call, function(output) {
@@ -833,7 +824,10 @@ function OutputStream(options) {
var g = output.parent(1); var g = output.parent(1);
if (g instanceof AST_Assign && g.left === p) return true; if (g instanceof AST_Assign && g.left === p) return true;
} }
return lhs_has_optional(node, output); // (foo?.())()
// (foo?.()).bar
// new (foo?.())()
return need_chain_parens(node, p);
}); });
PARENS(AST_New, function(output) { PARENS(AST_New, function(output) {
@@ -1158,8 +1152,9 @@ function OutputStream(options) {
}); });
} }
function print_arrow(self, output) { function print_arrow(self, output) {
if (self.argnames.length == 1 && self.argnames[0] instanceof AST_SymbolFunarg && !self.rest) { var argname = self.argnames.length == 1 && !self.rest && self.argnames[0];
self.argnames[0].print(output); if (argname instanceof AST_SymbolFunarg && argname.name != "yield") {
argname.print(output);
} else { } else {
print_funargs(self, output); print_funargs(self, output);
} }

View File

@@ -44,10 +44,10 @@
"use strict"; "use strict";
var KEYWORDS = "break case catch class const continue debugger default delete do else extends finally for function if in instanceof let new return switch throw try typeof var void while with"; var KEYWORDS = "break case catch class const continue debugger default delete do else extends finally for function if in instanceof new return switch throw try typeof var void while with";
var KEYWORDS_ATOM = "false null true"; var KEYWORDS_ATOM = "false null true";
var RESERVED_WORDS = [ var RESERVED_WORDS = [
"abstract async await boolean byte char double enum export final float goto implements import int interface long native package private protected public short static super synchronized this throws transient volatile yield", "abstract async await boolean byte char double enum export final float goto implements import int interface let long native package private protected public short static super synchronized this throws transient volatile yield",
KEYWORDS_ATOM, KEYWORDS_ATOM,
KEYWORDS, KEYWORDS,
].join(" "); ].join(" ");
@@ -242,10 +242,10 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
read_template : with_eof_error("Unterminated template literal", function(strings) { read_template : with_eof_error("Unterminated template literal", function(strings) {
var s = ""; var s = "";
for (;;) { for (;;) {
var ch = next(true, true); var ch = read();
switch (ch) { switch (ch) {
case "\\": case "\\":
ch += next(true, true); ch += read();
break; break;
case "`": case "`":
strings.push(s); strings.push(s);
@@ -260,6 +260,11 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
} }
s += ch; s += ch;
} }
function read() {
var ch = next(true, true);
return ch == "\r" ? "\n" : ch;
}
}), }),
}; };
var prev_was_dot = false; var prev_was_dot = false;
@@ -862,6 +867,15 @@ function parse($TEXT, options) {
next(); next();
return import_(); return import_();
} }
break;
case "let":
if (is_vardefs()) {
next();
var node = let_();
semicolon();
return node;
}
break;
case "yield": case "yield":
if (S.in_generator) return simple_statement(); if (S.in_generator) return simple_statement();
break; break;
@@ -947,12 +961,6 @@ function parse($TEXT, options) {
next(); next();
return if_(); return if_();
case "let":
next();
var node = let_();
semicolon();
return node;
case "return": case "return":
if (S.in_function == 0 && !options.bare_returns) if (S.in_function == 0 && !options.bare_returns)
croak("'return' outside of function"); croak("'return' outside of function");
@@ -1192,7 +1200,7 @@ function parse($TEXT, options) {
if (await || !is("punc", ";")) { if (await || !is("punc", ";")) {
init = is("keyword", "const") init = is("keyword", "const")
? (next(), const_(true)) ? (next(), const_(true))
: is("keyword", "let") : is("name", "let") && is_vardefs()
? (next(), let_(true)) ? (next(), let_(true))
: is("keyword", "var") : is("keyword", "var")
? (next(), var_(true)) ? (next(), var_(true))
@@ -1308,6 +1316,11 @@ function parse($TEXT, options) {
} }
if (node instanceof AST_SymbolFunarg) return node; if (node instanceof AST_SymbolFunarg) return node;
if (node instanceof AST_SymbolRef) return new AST_SymbolFunarg(node); if (node instanceof AST_SymbolRef) return new AST_SymbolFunarg(node);
if (node instanceof AST_Yield) return new AST_SymbolFunarg({
start: node.start,
name: "yield",
end: node.end,
});
token_error(node.start, "Invalid arrow parameter"); token_error(node.start, "Invalid arrow parameter");
} }
@@ -1535,12 +1548,18 @@ function parse($TEXT, options) {
} }
var export_decl = embed_tokens(function() { var export_decl = embed_tokens(function() {
if (is("name", "async")) { if (is("name")) switch (S.token.value) {
case "async":
next(); next();
expect_token("keyword", "function"); expect_token("keyword", "function");
if (!is("operator", "*")) return function_(AST_AsyncDefun); if (!is("operator", "*")) return function_(AST_AsyncDefun);
next(); next();
return function_(AST_AsyncGeneratorDefun); return function_(AST_AsyncGeneratorDefun);
case "let":
next();
var node = let_();
semicolon();
return node;
} else if (is("keyword")) switch (S.token.value) { } else if (is("keyword")) switch (S.token.value) {
case "class": case "class":
next(); next();
@@ -1555,11 +1574,6 @@ function parse($TEXT, options) {
if (!is("operator", "*")) return function_(AST_Defun); if (!is("operator", "*")) return function_(AST_Defun);
next(); next();
return function_(AST_GeneratorDefun); return function_(AST_GeneratorDefun);
case "let":
next();
var node = let_();
semicolon();
return node;
case "var": case "var":
next(); next();
var node = var_(); var node = var_();
@@ -1720,6 +1734,11 @@ function parse($TEXT, options) {
return a; return a;
} }
function is_vardefs() {
var token = peek();
return is_token(token, "name") || is_token(token, "punc", "[") || is_token(token, "punc", "{");
}
var const_ = function(no_in) { var const_ = function(no_in) {
return new AST_Const({ return new AST_Const({
start : prev(), start : prev(),
@@ -1818,10 +1837,7 @@ function parse($TEXT, options) {
if (is("punc")) { if (is("punc")) {
switch (start.value) { switch (start.value) {
case "`": case "`":
var tmpl = template(null); return subscripts(template(null), allow_calls);
tmpl.start = start;
tmpl.end = prev();
return subscripts(tmpl, allow_calls);
case "(": case "(":
next(); next();
if (is("punc", ")")) { if (is("punc", ")")) {
@@ -2133,7 +2149,7 @@ function parse($TEXT, options) {
} }
function strict_verify_symbol(sym) { function strict_verify_symbol(sym) {
if (sym.name == "arguments" || sym.name == "eval") if (sym.name == "arguments" || sym.name == "eval" || sym.name == "let")
token_error(sym.start, "Unexpected " + sym.name + " in strict mode"); token_error(sym.start, "Unexpected " + sym.name + " in strict mode");
} }
@@ -2230,6 +2246,7 @@ function parse($TEXT, options) {
} }
function template(tag) { function template(tag) {
var start = tag ? tag.start : S.token;
var read = S.input.context().read_template; var read = S.input.context().read_template;
var strings = []; var strings = [];
var expressions = []; var expressions = [];
@@ -2240,58 +2257,60 @@ function parse($TEXT, options) {
} }
next(); next();
return new AST_Template({ return new AST_Template({
start: start,
expressions: expressions, expressions: expressions,
strings: strings, strings: strings,
tag: tag, tag: tag,
end: prev(),
}); });
} }
var subscripts = function(expr, allow_calls, optional) { function subscripts(expr, allow_calls) {
var start = expr.start; var start = expr.start;
if (is("punc", "[")) { var optional = null;
next(); while (true) {
var prop = expression(); if (is("operator", "?") && is_token(peek(), "punc", ".")) {
expect("]"); next();
return subscripts(new AST_Sub({ next();
start: start, optional = expr;
optional: optional, }
expression: expr, if (is("punc", "[")) {
property: prop, next();
end: prev(), var prop = expression();
}), allow_calls); expect("]");
} expr = new AST_Sub({
if (allow_calls && is("punc", "(")) { start: start,
next(); optional: optional === expr,
var call = new AST_Call({ expression: expr,
start: start, property: prop,
optional: optional, end: prev(),
expression: expr, });
args: expr_list(")", !options.strict), } else if (allow_calls && is("punc", "(")) {
end: prev(), next();
}); expr = new AST_Call({
return subscripts(call, true); start: start,
} optional: optional === expr,
if (optional || is("punc", ".")) { expression: expr,
if (!optional) next(); args: expr_list(")", !options.strict),
return subscripts(new AST_Dot({ end: prev(),
start: start, });
optional: optional, } else if (optional === expr || is("punc", ".")) {
expression: expr, if (optional !== expr) next();
property: as_name(), expr = new AST_Dot({
end: prev(), start: start,
}), allow_calls); optional: optional === expr,
} expression: expr,
if (is("punc", "`")) { property: as_name(),
var tmpl = template(expr); end: prev(),
tmpl.start = expr.start; });
tmpl.end = prev(); } else if (is("punc", "`")) {
return subscripts(tmpl, allow_calls); if (optional) croak("Invalid template on optional chain");
} expr = template(expr);
if (is("operator", "?") && is_token(peek(), "punc", ".")) { } else {
next(); break;
next(); }
return subscripts(expr, allow_calls, true);
} }
if (optional) expr.terminal = true;
if (expr instanceof AST_Call && !expr.pure) { if (expr instanceof AST_Call && !expr.pure) {
var start = expr.start; var start = expr.start;
var comments = start.comments_before; var comments = start.comments_before;
@@ -2305,7 +2324,7 @@ function parse($TEXT, options) {
} }
} }
return expr; return expr;
}; }
function maybe_unary(no_in) { function maybe_unary(no_in) {
var start = S.token; var start = S.token;

View File

@@ -143,7 +143,7 @@ function push_uniq(array, el) {
} }
function string_template(text, props) { function string_template(text, props) {
return text.replace(/\{([^}]+)\}/g, function(str, p) { return text.replace(/\{([^{}]+)\}/g, function(str, p) {
var value = props[p]; var value = props[p];
return value instanceof AST_Node ? value.print_to_string() : value; return value instanceof AST_Node ? value.print_to_string() : value;
}); });

View File

@@ -3,7 +3,7 @@
"description": "JavaScript parser, mangler/compressor and beautifier toolkit", "description": "JavaScript parser, mangler/compressor and beautifier toolkit",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)", "author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"version": "3.14.1", "version": "3.14.4",
"engines": { "engines": {
"node": ">=0.8.0" "node": ">=0.8.0"
}, },

View File

@@ -550,6 +550,24 @@ logical_side_effects: {
node_version: ">=15" node_version: ">=15"
} }
evaluate_lazy_assignment: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = 42;
console.log(a &&= "PASS");
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=15"
}
issue_4815_1: { issue_4815_1: {
options = { options = {
evaluate: true, evaluate: true,

View File

@@ -227,7 +227,7 @@ inline_await_1_trim: {
console.log("PASS"); console.log("PASS");
} }
expect: { expect: {
void 0; 0;
console.log("PASS"); console.log("PASS");
} }
expect_stdout: "PASS" expect_stdout: "PASS"
@@ -453,7 +453,7 @@ object_function: {
}).f(); }).f();
} }
expect: { expect: {
(async function() { (async () => {
console.log("PASS"); console.log("PASS");
})(); })();
} }
@@ -571,7 +571,7 @@ drop_async_1: {
} }
expect: { expect: {
console.log(function(a) { console.log(function(a) {
void (a *= 7); a *= 7;
return a; return a;
}(6)); }(6));
} }
@@ -1774,7 +1774,7 @@ issue_5001: {
} }
expect: { expect: {
var a = 0; var a = 0;
void a++; a++;
console.log(a ? "PASS" : "FAIL"); console.log(a ? "PASS" : "FAIL");
} }
expect_stdout: "PASS" expect_stdout: "PASS"
@@ -2046,3 +2046,195 @@ issue_5070: {
expect_stdout: "PASS" expect_stdout: "PASS"
node_version: ">=10" node_version: ">=10"
} }
issue_5157_async_function: {
options = {
awaits: true,
side_effects: true,
}
input: {
async function f() {
throw "FAIL";
}
(async function() {
try {
return await f();
} catch (e) {
return "PASS";
}
})().then(console.log);
}
expect: {
async function f() {
throw "FAIL";
}
(async function() {
try {
return await f();
} catch (e) {
return "PASS";
}
})().then(console.log);
}
expect_stdout: "PASS"
node_version: ">=8"
}
issue_5157_async_iife: {
options = {
awaits: true,
side_effects: true,
}
input: {
(async function() {
try {
return await async function() {
throw "FAIL";
}();
} catch (e) {
return "PASS";
}
})().then(console.log);
}
expect: {
(async function() {
try {
return await async function() {
throw "FAIL";
}();
} catch (e) {
return "PASS";
}
})().then(console.log);
}
expect_stdout: "PASS"
node_version: ">=8"
}
issue_5157_promise: {
options = {
awaits: true,
side_effects: true,
}
input: {
var p = new Promise(function(resolve, reject) {
reject("FAIL");
});
(async function() {
try {
return await p;
} catch (e) {
return "PASS";
}
})().then(console.log);
}
expect: {
var p = new Promise(function(resolve, reject) {
reject("FAIL");
});
(async function() {
try {
return await p;
} catch (e) {
return "PASS";
}
})().then(console.log);
}
expect_stdout: "PASS"
node_version: ">=8"
}
issue_5159_1: {
options = {
awaits: true,
side_effects: true,
}
input: {
(async function() {
try {
throw "foo";
} catch (e) {
return await "bar";
} finally {
console.log("baz");
}
})().catch(console.log).then(console.log);
console.log("moo");
}
expect: {
(async function() {
try {
throw "foo";
} catch (e) {
return await "bar";
} finally {
console.log("baz");
}
})().catch(console.log).then(console.log);
console.log("moo");
}
expect_stdout: [
"moo",
"baz",
"bar",
]
node_version: ">=8"
}
issue_5159_2: {
options = {
awaits: true,
side_effects: true,
}
input: {
(async function() {
try {
throw "foo";
} catch (e) {
return await "bar";
}
})().catch(console.log).then(console.log);
console.log("baz");
}
expect: {
(async function() {
try {
throw "foo";
} catch (e) {
return "bar";
}
})().catch(console.log).then(console.log);
console.log("baz");
}
expect_stdout: [
"baz",
"bar",
]
node_version: ">=8"
}
issue_5177: {
options = {
properties: true,
}
input: {
(async function() {
return {
p(await) {},
}.p;
})().then(function(a) {
console.log(typeof a);
});
}
expect: {
(async function() {
return {
p(await) {},
}.p;
})().then(function(a) {
console.log(typeof a);
});
}
expect_stdout: "function"
node_version: ">=8"
}

View File

@@ -2066,3 +2066,34 @@ issue_5082_2: {
expect_stdout: "PASS" expect_stdout: "PASS"
node_version: ">=12" node_version: ">=12"
} }
issue_5142: {
options = {
evaluate: true,
merge_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a = 0, b;
if (++a)
new class {
p = b = null;
constructor(c) {
console.log(c ? "FAIL" : "PASS");
}
}(b, a);
}
expect: {
var a = 0, b;
if (++a)
new class {
p = b = null;
constructor(c) {
console.log(c ? "FAIL" : "PASS");
}
}(b, 1);
}
expect_stdout: "PASS"
node_version: ">=12"
}

View File

@@ -9253,13 +9253,13 @@ issue_4920_2: {
console.log(b); console.log(b);
} }
expect: { expect: {
var o = { var o;
var a = "PASS", b;
({
get PASS() { get PASS() {
a = "FAIL"; a = "FAIL";
}, },
}; })[b = a];
var a = "PASS", b;
o[b = a];
console.log(b); console.log(b);
} }
expect_stdout: "PASS" expect_stdout: "PASS"
@@ -9283,16 +9283,47 @@ issue_4920_3: {
} }
expect: { expect: {
var log = console.log; var log = console.log;
var o = { var o;
var a = "PASS", b;
({
get PASS() { get PASS() {
a = "FAIL"; a = "FAIL";
}, },
})[b = a];
log(b);
}
expect_stdout: "PASS"
}
issue_4920_4: {
options = {
collapse_vars: true,
toplevel: true,
}
input: {
var log = console.log;
var o = {
get [(a = "FAIL 1", "PASS")]() {
a = "FAIL 2";
},
};
var a = "PASS", b;
o[b = a];
log(b);
}
expect: {
var log = console.log;
var o = {
get [(a = "FAIL 1", "PASS")]() {
a = "FAIL 2";
},
}; };
var a = "PASS", b; var a = "PASS", b;
o[b = a]; o[b = a];
log(b); log(b);
} }
expect_stdout: "PASS" expect_stdout: "PASS"
node_version: ">=4"
} }
issue_4935: { issue_4935: {
@@ -9412,3 +9443,126 @@ issue_4977_2: {
} }
expect_stdout: "PASS PASS" expect_stdout: "PASS PASS"
} }
issue_5112_1: {
options = {
collapse_vars: true,
}
input: {
console.log(function(a) {
try {
try {
if (console + (a = "PASS", ""))
return "FAIL 1";
a.p;
} catch (e) {}
} finally {
return a;
}
}("FAIL 2"));
}
expect: {
console.log(function(a) {
try {
try {
if (console + (a = "PASS", ""))
return "FAIL 1";
a.p;
} catch (e) {}
} finally {
return a;
}
}("FAIL 2"));
}
expect_stdout: "PASS"
}
issue_5112_2: {
options = {
collapse_vars: true,
}
input: {
console.log(function(a) {
try {
return function() {
try {
if (console + (a = "PASS", ""))
return "FAIL 1";
a.p;
} catch (e) {}
}();
} finally {
return a;
}
}("FAIL 2"));
}
expect: {
console.log(function(a) {
try {
return function() {
try {
if (console + (a = "PASS", ""))
return "FAIL 1";
a.p;
} catch (e) {}
}();
} finally {
return a;
}
}("FAIL 2"));
}
expect_stdout: "PASS"
}
issue_5182: {
options = {
arrows: true,
collapse_vars: true,
evaluate: true,
hoist_props: true,
inline: true,
merge_vars: true,
passes: 4,
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var con = console;
global.log = con.log;
var jump = function(x) {
console.log("JUMP:", x * 10);
return x + x;
};
var jump2 = jump;
var run = function(x) {
console.log("RUN:", x * -10);
return x * x;
};
var run2 = run;
var bar = (x, y) => {
console.log("BAR:", x + y);
return x - y;
};
var bar2 = bar;
var obj = {
foo: bar2,
go: run2,
not_used: jump2,
};
console.log(obj.foo(1, 2), global.log("PASS"));
}
expect: {
var con = console;
global.log = con.log,
console.log((console.log("BAR:", 3), -1), global.log("PASS"));
}
expect_stdout: [
"BAR: 3",
"PASS",
"-1 undefined",
]
node_version: ">=4"
}

View File

@@ -289,3 +289,18 @@ issue_3689: {
} }
expect_stdout: "00" expect_stdout: "00"
} }
issue_5145: {
options = {
strings: true,
}
input: {
var a = [];
console.log("" + a + ((a[0] = 4) + "2"));
}
expect: {
var a = [];
console.log("" + a + (a[0] = 4) + "2");
}
expect_stdout: "42"
}

View File

@@ -1633,3 +1633,39 @@ issue_5030: {
expect_stdout: "PASS" expect_stdout: "PASS"
node_version: ">=0.12" node_version: ">=0.12"
} }
issue_5106_1: {
options = {
dead_code: true,
}
input: {
console.log(typeof function(a) {
return a = arguments;
}("FAIL")[0]);
}
expect: {
console.log(typeof function(a) {
return a = arguments;
}("FAIL")[0]);
}
expect_stdout: "object"
}
issue_5106_2: {
options = {
dead_code: true,
}
input: {
"use strict";
console.log(function(a) {
return a = arguments;
}("PASS")[0]);
}
expect: {
"use strict";
console.log(function(a) {
return arguments;
}("PASS")[0]);
}
expect_stdout: "PASS"
}

View File

@@ -568,6 +568,20 @@ retain_empty_iife: {
node_version: ">=6" node_version: ">=6"
} }
drop_new_function: {
options = {
side_effects: true,
}
input: {
new function(a = console.log("PASS")) {}();
}
expect: {
void console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=6"
}
retain_fargs: { retain_fargs: {
options = { options = {
unused: true, unused: true,
@@ -1890,3 +1904,56 @@ issue_5065: {
expect_stdout: "PASS" expect_stdout: "PASS"
node_version: ">=6" node_version: ">=6"
} }
issue_5138_1: {
options = {
evaluate: true,
}
input: {
console.log(function(a, b = a = "FAIL") {
return a;
}() && "PASS");
}
expect: {
console.log(function(a, b = a = "FAIL") {
return a;
}() && "PASS");
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5138_2: {
options = {
evaluate: true,
}
input: {
console.log(function(a, b = a = "FAIL 1") {
return a;
}(null, "FAIL 2") || "PASS");
}
expect: {
console.log((null, "PASS"));
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5192: {
options = {
dead_code: true,
ie: true,
}
input: {
(function a(a, [] = a = "PASS") {
console.log(a);
})("FAIL");
}
expect: {
(function a(a, [] = a = "PASS") {
console.log(a);
})("FAIL");
}
expect_stdout: "PASS"
node_version: ">=6"
}

View File

@@ -1581,6 +1581,75 @@ hoist_vars: {
node_version: ">=6" node_version: ">=6"
} }
singleton_1: {
options = {
pure_getters: true,
side_effects: true,
unused: true,
}
input: {
var [ a ] = "P", b, o = {};
[ { 1: o.p } ] = [ "FAIL" ];
({ foo: [ o.q ] } = { foo: "S" });
[ b = "S" ] = [];
console.log(a + o.p + o.q + b);
}
expect: {
var b, a = "P"[0], o = {};
o.p = [ "FAIL"["1"] ][0];
o.q = { foo: "S"[0] }["foo"];
[ b = "S" ] = [];
console.log(a + o.p + o.q + b);
}
expect_stdout: "PASS"
node_version: ">=6"
}
singleton_2: {
options = {
evaluate: true,
passes: 2,
pure_getters: true,
side_effects: true,
unsafe: true,
unused: true,
}
input: {
var [ a ] = "P", b, o = {};
[ { 1: o.p } ] = [ "FAIL" ];
({ foo: [ o.q ] } = { foo: "S" });
[ b = "S" ] = [];
console.log(a + o.p + o.q + b);
}
expect: {
var b, a = "P", o = {};
o.p = "A";
o.q = "S";
[ b = "S" ] = [];
console.log(a + o.p + o.q + b);
}
expect_stdout: "PASS"
node_version: ">=6"
}
singleton_side_effects: {
options = {
side_effects: true,
unused: true,
}
input: {
[ 42[console.log("foo")] ] = [ console.log("bar") ];
}
expect: {
[ 42[console.log("foo")] ] = [ console.log("bar") ];
}
expect_stdout: [
"bar",
"foo",
]
node_version: ">=6"
}
issue_4280: { issue_4280: {
options = { options = {
evaluate: true, evaluate: true,
@@ -2127,7 +2196,7 @@ issue_4372_2: {
} }
expect: { expect: {
var a; var a;
[ a ] = [ "PASS", "FAIL" ]; [ a ] = a = [ "PASS", "FAIL" ];
console.log(a); console.log(a);
} }
expect_stdout: "PASS" expect_stdout: "PASS"
@@ -3057,3 +3126,243 @@ issue_5087_2: {
expect_stdout: "PASS" expect_stdout: "PASS"
node_version: ">=6" node_version: ">=6"
} }
issue_5114_1: {
options = {
inline: true,
unused: true,
}
input: {
var a = "PASS";
(function({}, a) {})(42);
console.log(a);
}
expect: {
var a = "PASS";
[ {} ] = [ 42 ],
void 0;
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5114_2: {
options = {
inline: true,
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
var a = "PASS";
(function f([], a) {
f.length;
})([]);
console.log(a);
}
expect: {
var a = "PASS";
0;
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5114_3: {
options = {
inline: true,
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
var a = "PASS";
(function f(a, {}) {
f.length;
})(null, 42);
console.log(a);
}
expect: {
var a = "PASS";
0;
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5153_array_assign: {
options = {
dead_code: true,
}
input: {
var a = function*() {
yield b;
}(), b;
[ b ] = b = a;
console.log(a === b ? "PASS" : "FAIL");
}
expect: {
var a = function*() {
yield b;
}(), b;
[ b ] = b = a;
console.log(a === b ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5153_array_var: {
options = {
dead_code: true,
}
input: {
var a = function*() {
yield b;
}(), [ b ] = b = a;
console.log(a === b ? "PASS" : "FAIL");
}
expect: {
var a = function*() {
yield b;
}(), [ b ] = b = a;
console.log(a === b ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5153_object_assign: {
options = {
dead_code: true,
}
input: {
var a = {
get p() {
return b;
},
}, b;
({
p: b
} = b = a);
console.log(a === b ? "PASS" : "FAIL");
}
expect: {
var a = {
get p() {
return b;
},
}, b;
({
p: b
} = b = a);
console.log(a === b ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5153_object_var: {
options = {
dead_code: true,
}
input: {
var a = {
get p() {
return b;
},
}, {
p: b
} = b = a;
console.log(a === b ? "PASS" : "FAIL");
}
expect: {
var a = {
get p() {
return b;
},
}, {
p: b
} = b = a;
console.log(a === b ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5168: {
options = {
collapse_vars: true,
}
input: {
(function a({
[console.log(typeof function() {
++a;
return a;
}())]: b,
}) {
var a;
})({});
}
expect: {
(function a({
[console.log(typeof function() {
++a;
return a;
}())]: b,
}) {
var a;
})({});
}
expect_stdout: "function"
node_version: ">=6"
}
issue_5189_1: {
options = {
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var a = 42;
[ a.p ] = a = "PASS";
console.log(a);
}
expect: {
var a;
[ a.p ] = a = "PASS";
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5189_2: {
options = {
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var a = 42;
({ p: a.q } = a = "PASS");
console.log(a);
}
expect: {
var a;
({ p: a.q } = a = "PASS");
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=6"
}

View File

@@ -1557,9 +1557,9 @@ issue_2665: {
} }
expect: { expect: {
var a = 1; var a = 1;
!function g() { (function g() {
a-- && g(); a-- && g();
}(); })();
console.log(a); console.log(a);
} }
expect_stdout: "-1" expect_stdout: "-1"
@@ -2916,7 +2916,7 @@ issue_4133: {
console.log(a); console.log(a);
} }
expect: { expect: {
var b = 1; var a = 1;
console.log(0); console.log(0);
} }
expect_stdout: "0" expect_stdout: "0"
@@ -3062,7 +3062,7 @@ issue_4184: {
expect_stdout: "42" expect_stdout: "42"
} }
issue_4235: { issue_4235_1: {
options = { options = {
inline: true, inline: true,
reduce_vars: true, reduce_vars: true,
@@ -3081,13 +3081,37 @@ issue_4235: {
} }
expect: { expect: {
void function() { void function() {
var f; var f = console.log(f);
console.log(f);
}(); }();
} }
expect_stdout: "undefined" expect_stdout: "undefined"
} }
issue_4235_2: {
options = {
inline: true,
passes: 2,
reduce_vars: true,
side_effects: true,
unused: true,
varify: true,
}
input: {
(function() {
{
const f = 0;
}
(function f() {
var f = console.log(f);
})();
})();
}
expect: {
console.log(void 0);
}
expect_stdout: "undefined"
}
issue_4404: { issue_4404: {
options = { options = {
pure_getters: "strict", pure_getters: "strict",
@@ -3379,7 +3403,7 @@ issue_4834: {
} }
expect: { expect: {
try { try {
void b.p; b.p;
} catch (e) { } catch (e) {
console.log("PASS"); console.log("PASS");
} }

View File

@@ -99,8 +99,8 @@ issue_4664: {
expect: { expect: {
(function f() { (function f() {
new function(a) { new function(a) {
console.log(typeof f, 1073741824, typeof this); console.log(typeof f, a, typeof this);
}(A = 0); }((A = 0, 2 ** 30));
})(); })();
} }
expect_stdout: "function 1073741824 object" expect_stdout: "function 1073741824 object"

View File

@@ -1171,11 +1171,11 @@ issue_2620_4: {
} }
expect: { expect: {
var c = "FAIL"; var c = "FAIL";
!function() { (function() {
switch (NaN) { switch (NaN) {
case void (c = "PASS"): case void (c = "PASS"):
} }
}(); })();
console.log(c); console.log(c);
} }
expect_stdout: "PASS" expect_stdout: "PASS"
@@ -4857,8 +4857,9 @@ issue_4155: {
} }
expect: { expect: {
(function() { (function() {
void console.log(b); var a;
var b = function() {}; void console.log(a);
function b() {}
b && console.log(typeof b); b && console.log(typeof b);
})(); })();
} }
@@ -6565,3 +6566,139 @@ issue_5098: {
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
shorter_without_void: {
options = {
inline: true,
passes: 2,
reduce_vars: true,
side_effects: true,
toplevel: true,
}
input: {
var a;
function f(b) {
a = b;
}
f("foo");
console.log(a) || f("bar");
console.log(a, f("baz"));
console.log(a);
}
expect: {
var a;
function f(b) {
a = b;
}
a = "foo";
console.log(a) || (a = "bar");
console.log(a, f("baz"));
console.log(a);
}
expect_stdout: [
"foo",
"bar undefined",
"baz",
]
}
issue_5120: {
options = {
functions: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = function f() {
function g() {
f || g();
}
g();
return f.valueOf();
};
console.log(a() === a ? "PASS" : "FAIL");
}
expect: {
function a() {
(function g() {
a || g();
})();
return a.valueOf();
}
console.log(a() === a ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
}
issue_5140: {
options = {
collapse_vars: true,
inline: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
A = 42;
function f(b) {
return b >> 0;
}
var a = f(42 in []);
console.log(f(A));
}
expect: {
function f(b) {
return b >> 0;
}
A = 42;
console.log(A >> 0);
}
expect_stdout: "42"
}
issue_5173_1: {
options = {
conditionals: true,
inline: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
}
input: {
function f(a, b) {
console.log(b);
}
f([ A = 42, [] + "" || (A = f) ]);
}
expect: {
function f(a, b) {
console.log(b);
}
f([ A = 42, [] + "" || (A = f) ]);
}
expect_stdout: "undefined"
}
issue_5173_2: {
options = {
conditionals: true,
inline: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function f(a, b) {
console.log(b);
}
f([ A = 42, [] + "" || (A = f) ]);
}
expect: {
function f(a, b) {
console.log(b);
}
f(A = [] + "" ? 42 : f);
}
expect_stdout: "undefined"
}

View File

@@ -217,7 +217,8 @@ name_collision_1: {
var obj_foo = 1; var obj_foo = 1;
var obj_bar = 2; var obj_bar = 2;
function f() { function f() {
var obj_foo$0 = 3, var obj,
obj_foo$0 = 3,
obj_bar = 4, obj_bar = 4,
obj_b_r = 5, obj_b_r = 5,
obj_b_r$0 = 6, obj_b_r$0 = 6,
@@ -249,7 +250,8 @@ name_collision_2: {
console.log(o.p === o.p, o["+"](4), o["-"](5), o__$0, o__$1); console.log(o.p === o.p, o["+"](4), o["-"](5), o__$0, o__$1);
} }
expect: { expect: {
var o_p = 1, var o,
o_p = 1,
o__ = function(x) { o__ = function(x) {
return x; return x;
}, },
@@ -283,7 +285,8 @@ name_collision_3: {
console.log(o.p === o.p, o["+"](4), o["-"](5)); console.log(o.p === o.p, o["+"](4), o["-"](5));
} }
expect: { expect: {
var o_p = 1, var o,
o_p = 1,
o__ = function(x) { o__ = function(x) {
return x; return x;
}, },
@@ -315,7 +318,7 @@ name_collision_4: {
} }
expect: { expect: {
console.log(function() { console.log(function() {
var o_p$0 = 0, o_q = "PASS"; var o, o_p$0 = 0, o_q = "PASS";
return function(o_p) { return function(o_p) {
if (!o_p$0) return o_p; if (!o_p$0) return o_p;
}(o_q); }(o_q);
@@ -768,7 +771,7 @@ issue_3046: {
expect: { expect: {
console.log(function(a) { console.log(function(a) {
do { do {
var b_c = a++; var b, b_c = a++;
} while (b_c && a); } while (b_c && a);
return a; return a;
}(0)); }(0));
@@ -931,7 +934,7 @@ issue_3411: {
expect: { expect: {
var c = 1; var c = 1;
!function f() { !function f() {
var o_p = --c && f(); var o, o_p = --c && f();
+{} || console.log("PASS"); +{} || console.log("PASS");
}(); }();
} }
@@ -1042,9 +1045,7 @@ issue_3945_1: {
expect: { expect: {
function f() { function f() {
o.p; o.p;
var o = { var o, o_q = 0;
q: 0,
};
} }
} }
} }
@@ -1063,9 +1064,7 @@ issue_3945_2: {
} }
expect: { expect: {
console.log(typeof o); console.log(typeof o);
var o = { var o, o_p = 0;
p: 0,
};
} }
expect_stdout: "undefined" expect_stdout: "undefined"
} }
@@ -1134,10 +1133,46 @@ issue_4985: {
}()); }());
} }
expect: { expect: {
var a_p = 42; var a, a_p = 42;
console.log(function() { console.log(function() {
({}); ({});
}()); }());
} }
expect_stdout: "undefined" expect_stdout: "undefined"
} }
issue_5182: {
options = {
hoist_props: true,
merge_vars: true,
passes: 2,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var o = console;
log = o.log;
o = {
p: function(a) {
console.log(a ? "PASS" : "FAIL");
return a;
},
};
log(o.p(42));
}
expect: {
var o_p = console;
log = o_p.log;
o_p = function(a) {
console.log(a ? "PASS" : "FAIL");
return a;
};
log(o_p(42));
}
expect_stdout: [
"PASS",
"42",
]
}

View File

@@ -135,7 +135,7 @@ issue_2295: {
} }
} }
issue_4487: { issue_4487_1: {
options = { options = {
functions: true, functions: true,
hoist_vars: true, hoist_vars: true,
@@ -150,16 +150,64 @@ issue_4487: {
}; };
var b = a(); var b = a();
} }
expect: {
var a = function f() {
var f = console.log(typeof f);
};
a();
}
expect_stdout: "undefined"
}
issue_4487_2: {
options = {
functions: true,
hoist_vars: true,
keep_fnames: true,
passes: 2,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = function f() {
var f = console.log(typeof f);
};
var b = a();
}
expect: { expect: {
function a() { function a() {
var f; var f = console.log(typeof f);
console.log(typeof f);
} }
a(); a();
} }
expect_stdout: "undefined" expect_stdout: "undefined"
} }
issue_4487_3: {
options = {
functions: true,
hoist_vars: true,
keep_fnames: true,
passes: 3,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = function f() {
var f = console.log(typeof f);
};
var b = a();
}
expect: {
(function a() {
console.log(typeof void 0);
})();
}
expect_stdout: "undefined"
}
issue_4489: { issue_4489: {
options = { options = {
collapse_vars: true, collapse_vars: true,
@@ -251,18 +299,18 @@ issue_4839: {
unused: true, unused: true,
} }
input: { input: {
var o = function(a, b) { var log = console.log, o = function(a, b) {
return b && b; return b && b;
}("foo"); }("foo");
for (var k in o) for (var k in o)
throw "FAIL"; throw "FAIL";
console.log("PASS"); log("PASS");
} }
expect: { expect: {
var k, o = void 0; var k, log = console.log;
for (k in o) for (k in void 0)
throw "FAIL"; throw "FAIL";
console.log("PASS"); log("PASS");
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
@@ -288,8 +336,7 @@ issue_4859: {
} }
expect: { expect: {
(function f(a) { (function f(a) {
var d = 1 / 0, d = Infinity; console.log(Infinity);
console.log(d);
return f; return f;
})(); })();
} }
@@ -395,3 +442,61 @@ issue_4898: {
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
issue_5187: {
options = {
hoist_props: true,
hoist_vars: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
function f() {
var a = 42;
do {
var b = { 0: a++ };
} while (console.log(b[b ^= 0]));
}
f();
}
expect: {
(function() {
var b, a = 42;
do {
b = { 0: a++ };
} while (console.log(b[b ^= 0]));
})();
}
expect_stdout: "42"
}
issue_5195: {
options = {
hoist_props: true,
hoist_vars: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
function f() {
var a;
do {
var b = { p: a };
} while (console.log(b += ""));
}
f();
}
expect: {
(function() {
var a, b;
do {
b = { p: a };
} while (console.log(b += ""));
})();
}
expect_stdout: "[object Object]"
}

View File

@@ -489,6 +489,116 @@ join_object_assignments_regex: {
expect_stdout: "1" expect_stdout: "1"
} }
chained_assignments: {
options = {
join_vars: true,
}
input: {
var a, b = a = {};
b.p = "PASS";
console.log(a.p);
}
expect: {
var a, b = a = {
p: "PASS",
};
console.log(a.p);
}
expect_stdout: "PASS"
}
folded_assignments_1: {
options = {
evaluate: true,
join_vars: true,
}
input: {
var a = {};
a[a.PASS = 42] = "PASS";
console.log(a[42], a.PASS);
}
expect: {
var a = {
PASS: 42,
42: "PASS",
};
console.log(a[42], a.PASS);
}
expect_stdout: "PASS 42"
}
folded_assignments_2: {
options = {
evaluate: true,
join_vars: true,
}
input: {
"use strict";
var a = {};
a[42] = "FAIL";
a[a.PASS = 42] = "PASS";
console.log(a[42], a.PASS);
}
expect: {
"use strict";
var a = {
42: "FAIL",
PASS: 42,
};
a[42] = "PASS";
console.log(a[42], a.PASS);
}
expect_stdout: "PASS 42"
}
inlined_assignments: {
options = {
join_vars: true,
unused: true,
}
input: {
var a;
(a = {}).p = "PASS";
console.log(a.p);
}
expect: {
var a = {
p: "PASS",
};
console.log(a.p);
}
expect_stdout: "PASS"
}
typescript_enum: {
rename = true
options = {
assignments: true,
collapse_vars: true,
evaluate: true,
hoist_props: true,
inline: true,
join_vars: true,
passes: 4,
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var Enum;
(function (Enum) {
Enum[Enum.PASS = 42] = "PASS";
})(Enum || (Enum = {}));
console.log(Enum[42], Enum.PASS);
}
expect: {
console.log("PASS", 42);
}
expect_stdout: "PASS 42"
}
issue_2816: { issue_2816: {
options = { options = {
join_vars: true, join_vars: true,
@@ -1183,3 +1293,26 @@ assign_sequence_var: {
"1 2 3", "1 2 3",
] ]
} }
issue_5175: {
options = {
join_vars: true,
}
input: {
function log(f) {
console.log(f(), A.p);
}
log(function() {
return (A = {}).p = "PASS";
});
}
expect: {
function log(f) {
console.log(f(), A.p);
}
log(function() {
return (A = {}).p = "PASS";
});
}
expect_stdout: "PASS PASS"
}

View File

@@ -83,8 +83,9 @@ labels_5: {
conditionals: true, conditionals: true,
dead_code: true, dead_code: true,
if_return: true, if_return: true,
unused: true,
} }
// should keep the break-s in the following // should keep `break`s below
input: { input: {
while (foo) { while (foo) {
if (bar) break; if (bar) break;
@@ -100,8 +101,8 @@ labels_5: {
if (bar) break; if (bar) break;
console.log("foo"); console.log("foo");
} }
out: while (foo) { while (foo) {
if (bar) break out; if (bar) break;
console.log("foo"); console.log("foo");
} }
} }
@@ -189,23 +190,22 @@ labels_10: {
conditionals: true, conditionals: true,
dead_code: true, dead_code: true,
if_return: true, if_return: true,
unused: true,
} }
input: { input: {
out: while (foo) { out: while (42) {
x(); console.log("PASS");
y();
break out; break out;
z(); console.log("FAIL");
k();
} }
}; };
expect: { expect: {
out: while (foo) { while (42) {
x(); console.log("PASS");
y(); break;
break out;
} }
} }
expect_stdout: "PASS"
} }
issue_4466_1: { issue_4466_1: {

View File

@@ -476,9 +476,9 @@ issue_4112: {
try { try {
throw 42; throw 42;
} catch (e) { } catch (e) {
var a = e; var o = e;
for (e in a); for (e in o);
a = function() {}; function a() {}
console.log(typeof a); console.log(typeof a);
return a; return a;
} }
@@ -3377,3 +3377,60 @@ issue_4956_2: {
} }
expect_stdout: "42" expect_stdout: "42"
} }
issue_5182: {
options = {
arrows: true,
collapse_vars: true,
evaluate: true,
hoist_props: true,
inline: true,
merge_vars: true,
passes: 4,
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
try {
var con = console;
} catch (x) {}
global.log = con.log;
var jump = function(x) {
console.log("JUMP:", x * 10);
return x + x;
};
var jump2 = jump;
var run = function(x) {
console.log("RUN:", x * -10);
return x * x;
};
var run2 = run;
var bar = (x, y) => {
console.log("BAR:", x + y);
return x - y;
};
var bar2 = bar;
var obj = {
foo: bar2,
go: run2,
not_used: jump2,
};
console.log(obj.foo(1, 2), global.log("PASS"));
}
expect: {
try {
var con = console;
} catch (x) {}
global.log = con.log,
console.log((console.log("BAR:", 3), -1), global.log("PASS"));
}
expect_stdout: [
"BAR: 3",
"PASS",
"-1 undefined",
]
node_version: ">=4"
}

View File

@@ -58,7 +58,7 @@ assign_parentheses_dot: {
input: { input: {
(console?.log).name.p = console.log("PASS"); (console?.log).name.p = console.log("PASS");
} }
expect_exact: '(console?.log.name).p=console.log("PASS");' expect_exact: '(console?.log).name.p=console.log("PASS");'
expect_stdout: "PASS" expect_stdout: "PASS"
node_version: ">=14" node_version: ">=14"
} }
@@ -72,6 +72,26 @@ assign_no_parentheses: {
node_version: ">=14" node_version: ">=14"
} }
call_parentheses: {
input: {
(function(o) {
console.log(o.f("FAIL"), (o.f)("FAIL"), (0, o.f)(42));
console.log(o?.f("FAIL"), (o?.f)("FAIL"), (0, o?.f)(42));
})({
a: "PASS",
f(b) {
return this.a || b;
},
});
}
expect_exact: '(function(o){console.log(o.f("FAIL"),o.f("FAIL"),(0,o.f)(42));console.log(o?.f("FAIL"),(o?.f)("FAIL"),(0,o?.f)(42))})({a:"PASS",f(b){return this.a||b}});'
expect_stdout: [
"PASS PASS 42",
"PASS PASS 42",
]
node_version: ">=14"
}
unary_parentheses: { unary_parentheses: {
input: { input: {
var o = { p: 41 }; var o = { p: 41 };
@@ -237,6 +257,99 @@ trim_2: {
node_version: ">=14" node_version: ">=14"
} }
trim_dot_call_1: {
options = {
evaluate: true,
optional_chains: true,
}
input: {
console.log(null?.f());
}
expect: {
console.log(void 0);
}
expect_stdout: "undefined"
node_version: ">=14"
}
trim_dot_call_2: {
options = {
evaluate: true,
optional_chains: true,
unsafe: true,
}
input: {
try {
(null?.p)();
} catch (e) {
console.log("PASS");
}
}
expect: {
try {
(void 0)();
} catch (e) {
console.log("PASS");
}
}
expect_stdout: "PASS"
node_version: ">=14"
}
trim_dot_call_3: {
options = {
evaluate: true,
optional_chains: true,
unsafe: true,
}
input: {
try {
({ p: null })?.p();
} catch (e) {
console.log("PASS");
}
}
expect: {
try {
null();
} catch (e) {
console.log("PASS");
}
}
expect_stdout: "PASS"
node_version: ">=14"
}
trim_dot_sub: {
options = {
evaluate: true,
optional_chains: true,
}
input: {
console.log(null?.p[42]);
}
expect: {
console.log(void 0);
}
expect_stdout: "undefined"
node_version: ">=14"
}
trim_sub_call_call: {
options = {
evaluate: true,
optional_chains: true,
}
input: {
console.log(null?.[42]()());
}
expect: {
console.log(void 0);
}
expect_stdout: "undefined"
node_version: ">=14"
}
issue_4906: { issue_4906: {
options = { options = {
toplevel: true, toplevel: true,

View File

@@ -1510,3 +1510,71 @@ issue_5093_quote_style: {
expect_exact: 'console.log({a:true,\'42\':"PASS","null":[]}[6*7]);' expect_exact: 'console.log({a:true,\'42\':"PASS","null":[]}[6*7]);'
expect_stdout: "PASS" expect_stdout: "PASS"
} }
object_methods: {
options = {
properties: true,
}
input: {
({
p() {
console.log("FAIL 1");
},
*q() {
console.log("FAIL 2");
},
async r() {
console.log("FAIL 3");
},
async *s() {
console.log("PASS");
},
}).s().next();
}
expect: {
[
() => {
console.log("FAIL 1");
},
function*() {
console.log("FAIL 2");
},
async () => {
console.log("FAIL 3");
},
async function*() {
console.log("PASS");
},
][3]().next();
}
expect_stdout: "PASS"
node_version: ">=10"
}
issue_5177: {
options = {
properties: true,
}
input: {
var a = "FAIL";
var o = { a: "PASS" };
o.p = {
q() {
return this.a;
},
}.q;
console.log(o.p());
}
expect: {
var a = "FAIL";
var o = { a: "PASS" };
o.p = {
q() {
return this.a;
},
}.q;
console.log(o.p());
}
expect_stdout: "PASS"
node_version: ">=4"
}

View File

@@ -1640,6 +1640,26 @@ nested_property_assignments_3: {
expect_stdout: "PASS" expect_stdout: "PASS"
} }
nested_property_assignments_4: {
options = {
pure_getters: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var n, o = { p: { q: { r: "PASS" } } };
(n = o.p).r = n.q.r;
console.log(o.p.r);
}
expect: {
var n, o = { p: { q: { r: "PASS" } } };
(n = o.p).r = n.q.r;
console.log(o.p.r);
}
expect_stdout: "PASS"
}
issue_4939: { issue_4939: {
options = { options = {
pure_getters: "strict", pure_getters: "strict",

View File

@@ -7320,6 +7320,64 @@ local_assignment_loop: {
expect_stdout: "PASS" expect_stdout: "PASS"
} }
local_assignment_modified: {
options = {
evaluate: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
}
input: {
var a;
(a = a || {}).p = 42;
console.log(a.p);
}
expect: {
var a;
(a = {}).p = 42;
console.log(a.p);
}
expect_stdout: "42"
}
local_declaration: {
options = {
evaluate: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
}
input: {
var a;
a || console.log(a = "PASS");
}
expect: {
var a;
console.log("PASS");
}
expect_stdout: "PASS"
}
local_definition_modified: {
options = {
evaluate: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
}
input: {
var a = a || {};
a.p = 42;
console.log(a.p);
}
expect: {
var a = {};
a.p = 42;
console.log(a.p);
}
expect_stdout: "42"
}
issue_3957_1: { issue_3957_1: {
options = { options = {
evaluate: true, evaluate: true,
@@ -7435,6 +7493,7 @@ issue_4030: {
collapse_vars: true, collapse_vars: true,
evaluate: true, evaluate: true,
reduce_vars: true, reduce_vars: true,
side_effects: true,
toplevel: true, toplevel: true,
unused: true, unused: true,
} }

View File

@@ -636,6 +636,24 @@ keep_rest_lambda_2: {
node_version: ">=6" node_version: ">=6"
} }
drop_new_function: {
options = {
side_effects: true,
}
input: {
new function(...{
[console.log("PASS")]: a,
}) {}();
}
expect: {
void ([ ... {
[console.log("PASS")]: [].e,
}] = []);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_4525_1: { issue_4525_1: {
options = { options = {
arguments: true, arguments: true,
@@ -1026,13 +1044,13 @@ issue_5100_1: {
} }
expect: { expect: {
var a; var a;
[ { ({
p: {}, p: {},
...a ...a
} ] = [ { } = [ {
p: [ a = 42["q"] ], p: [ a = 42["q"] ],
r: "PASS", r: "PASS",
} ]; } ][0]);
console.log(a.r); console.log(a.r);
} }
expect_stdout: "PASS" expect_stdout: "PASS"
@@ -1059,13 +1077,131 @@ issue_5100_2: {
} }
expect: { expect: {
var a; var a;
[ { ({
p: {}, p: {},
...a ...a
} ] = [ { } = [ {
p: [ console.log("PASS"), a = 42["q"] ], p: [ console.log("PASS"), a = 42["q"] ],
} ]; } ][0]);
} }
expect_stdout: "PASS" expect_stdout: "PASS"
node_version: ">=10" node_version: ">=10"
} }
issue_5108: {
options = {
evaluate: true,
reduce_vars: true,
rests: true,
unsafe: true,
unused: true,
}
input: {
console.log(function([ ...[ a ] ]) {
return a;
}([ "PASS", "FAIL" ]));
}
expect: {
console.log(function([]) {
return "PASS";
}([ "PASS", "FAIL" ]));
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5128_1: {
options = {
inline: true,
}
input: {
console.log(function() {
return function f(...[ a ]) {
return a;
}("PASS");
}());
}
expect: {
console.log(function f(...[ a ]) {
return a;
}("PASS"));
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5128_2: {
options = {
inline: true,
keep_fnames: true,
unused: true,
}
input: {
console.log(function() {
return function f(...[ a ]) {
return a;
}("PASS");
}());
}
expect: {
console.log(function f(...[ a ]) {
return a;
}("PASS"));
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5165_1: {
options = {
conditionals: true,
dead_code: true,
evaluate: true,
reduce_vars: true,
rests: true,
side_effects: true,
switches: true,
unsafe: true,
}
input: {
console.log(function([ ...a ]) {
switch (a) {
case a:
return "PASS";
}
}([]));
}
expect: {
console.log(function([ ...a ]) {
return "PASS";
}([]));
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5165_2: {
options = {
conditionals: true,
dead_code: true,
evaluate: true,
reduce_vars: true,
rests: true,
side_effects: true,
switches: true,
unsafe: true,
}
input: {
console.log(function(...a) {
switch (a) {
case a:
return "PASS";
}
}());
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=6"
}

View File

@@ -201,3 +201,20 @@ issue_4811_2: {
expect_stdout: "PASS [object global] true" expect_stdout: "PASS [object global] true"
node_version: ">=8" node_version: ">=8"
} }
issue_5197: {
rename = true
input: {
function f(async) {
async(")=>{}");
}
console.log("" + this.__proto__);
}
expect: {
function f(a) {
a(")=>{}");
}
console.log("" + this.__proto__);
}
expect_stdout: "[object global]"
}

View File

@@ -131,6 +131,105 @@ malformed_escape: {
node_version: ">=4" node_version: ">=4"
} }
booleans: {
options = {
booleans: true,
evaluate: true,
templates: true,
}
input: {
var a;
console.log(`$${a}${a}` ? "PASS" : "FAIL");
}
expect: {
var a;
console.log("$" + a + a ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
node_version: ">=4"
}
escape_placeholder_1: {
options = {
templates: true,
}
input: {
console.log(`\${\n`);
}
expect: {
console.log(`\${
`);
}
expect_stdout: [
"${",
"",
]
node_version: ">=4"
}
escape_placeholder_2: {
options = {
evaluate: true,
templates: true,
}
input: {
console.log(`\n${"${"}\n`);
}
expect: {
console.log(`
\${
`);
}
expect_stdout: [
"",
"${",
"",
]
node_version: ">=4"
}
escape_placeholder_3: {
options = {
evaluate: true,
templates: true,
}
input: {
console.log(`\n$${"{"}\n`);
}
expect: {
console.log(`
\${
`);
}
expect_stdout: [
"",
"${",
"",
]
node_version: ">=4"
}
escape_placeholder_4: {
options = {
evaluate: true,
templates: true,
}
input: {
console.log(`\n${"$"}${"{"}\n`);
}
expect: {
console.log(`
\${
`);
}
expect_stdout: [
"",
"${",
"",
]
node_version: ">=4"
}
evaluate: { evaluate: {
options = { options = {
evaluate: true, evaluate: true,
@@ -174,7 +273,7 @@ partial_evaluate: {
console.log(`${6 * 7} foo ${console ? `PA` + "SS" : `FA` + `IL`}`); console.log(`${6 * 7} foo ${console ? `PA` + "SS" : `FA` + `IL`}`);
} }
expect: { expect: {
console.log(`42 foo ${console ? "PASS" : "FAIL"}`); console.log("42 foo " + (console ? "PASS" : "FAIL"));
} }
expect_stdout: "42 foo PASS" expect_stdout: "42 foo PASS"
node_version: ">=4" node_version: ">=4"
@@ -204,7 +303,7 @@ malformed_evaluate_2: {
console.log(`\u0${0}b${5}`); console.log(`\u0${0}b${5}`);
} }
expect: { expect: {
console.log(`\u0${0}b5`); console.log(`\u00b` + 5);
} }
expect_stdout: true expect_stdout: true
node_version: ">=4" node_version: ">=4"
@@ -357,13 +456,14 @@ issue_4604: {
issue_4606: { issue_4606: {
options = { options = {
evaluate: true, evaluate: true,
strings: true,
templates: true, templates: true,
} }
input: { input: {
console.log(`${typeof A} ${"\r"} ${"\\"} ${"`"}`); console.log(`${typeof A} ${"\r"} ${"\\"} ${"`"}`);
} }
expect: { expect: {
console.log(`${typeof A} \r \\ \``); console.log(typeof A + " \r \\ `");
} }
expect_stdout: "undefined \r \\ `" expect_stdout: "undefined \r \\ `"
node_version: ">=4" node_version: ">=4"
@@ -434,3 +534,238 @@ issue_4931: {
] ]
node_version: ">=4" node_version: ">=4"
} }
issue_5125_1: {
options = {
evaluate: true,
strings: true,
templates: true,
}
input: {
console.log(`PASS ${typeof A}`);
}
expect: {
console.log("PASS " + typeof A);
}
expect_stdout: "PASS undefined"
node_version: ">=4"
}
issue_5125_2: {
options = {
evaluate: true,
strings: true,
templates: true,
}
input: {
console.log(`PASS
${typeof A}`);
}
expect: {
console.log(`PASS
` + typeof A);
}
expect_stdout: [
"PASS",
"undefined",
]
node_version: ">=4"
}
issue_5125_3: {
options = {
evaluate: true,
strings: true,
templates: true,
}
input: {
console.log(`PASS\n${typeof A}`);
}
expect: {
console.log(`PASS
` + typeof A);
}
expect_stdout: [
"PASS",
"undefined",
]
node_version: ">=4"
}
issue_5125_4: {
options = {
evaluate: true,
strings: true,
templates: true,
}
input: {
console.log(`PASS
${typeof A}`);
}
expect: {
console.log(`PASS
` + typeof A);
}
expect_stdout: [
"PASS",
"",
"undefined",
]
node_version: ">=4"
}
issue_5125_5: {
options = {
evaluate: true,
strings: true,
templates: true,
}
input: {
console.log(`PASS\n\n${typeof A}`);
}
expect: {
console.log(`PASS
` + typeof A);
}
expect_stdout: [
"PASS",
"",
"undefined",
]
node_version: ">=4"
}
issue_5125_6: {
options = {
evaluate: true,
strings: true,
templates: true,
}
input: {
console.log(`${typeof A} ${typeof B} PASS`);
}
expect: {
console.log(typeof A + ` ${typeof B} PASS`);
}
expect_stdout: "undefined undefined PASS"
node_version: ">=4"
}
issue_5125_7: {
options = {
evaluate: true,
strings: true,
templates: true,
}
input: {
console.log(`${typeof A} ${typeof B} ${typeof C} PASS`);
}
expect: {
console.log(typeof A + ` ${typeof B} ${typeof C} PASS`);
}
expect_stdout: "undefined undefined undefined PASS"
node_version: ">=4"
}
issue_5125_8: {
options = {
evaluate: true,
strings: true,
templates: true,
}
input: {
console.log(`${typeof A}${typeof B}${typeof C} PASS`);
}
expect: {
console.log(typeof A + typeof B + typeof C + " PASS");
}
expect_stdout: "undefinedundefinedundefined PASS"
node_version: ">=4"
}
issue_5136: {
options = {
templates: true,
}
input: {
console.log(`${A = []}${A[0] = 42}`);
}
expect: {
console.log(`` + (A = []) + (A[0] = 42));
}
expect_stdout: "42"
node_version: ">=4"
}
issue_5145_1: {
options = {
strings: true,
templates: true,
}
input: {
var a = [];
console.log(`${a}${a[0] = 42}
`);
}
expect: {
var a = [];
console.log(`${a}${a[0] = 42}
`);
}
expect_stdout: [
"42",
"",
]
node_version: ">=4"
}
issue_5145_2: {
options = {
strings: true,
templates: true,
}
input: {
var a = [];
console.log(`${a}${a}${a[0] = 42}
`);
}
expect: {
var a = [];
console.log("" + a + a + (a[0] = 42) + `
`);
}
expect_stdout: [
"42",
"",
]
node_version: ">=4"
}
issue_5199: {
options = {
collapse_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = function() {
console.log(typeof b);
}``;
{
const b = a;
}
}
expect: {
var a = function() {
console.log(typeof b);
}``;
{
const b = a;
}
}
expect_stdout: "undefined"
node_version: ">=4"
}

View File

@@ -111,7 +111,7 @@ hoist_props_const: {
} }
} }
expect: { expect: {
var o_p = "PASS"; var o = 0, o_p = "PASS";
console.log(o_p); console.log(o_p);
} }
expect_stdout: "PASS" expect_stdout: "PASS"
@@ -136,7 +136,7 @@ hoist_props_let: {
} }
expect: { expect: {
"use strict"; "use strict";
var o_p = "PASS"; var o, o_p = "PASS";
console.log(o_p); console.log(o_p);
} }
expect_stdout: "PASS" expect_stdout: "PASS"

View File

@@ -96,7 +96,7 @@ pause_resume: {
node_version: ">=4" node_version: ">=4"
} }
arrow_yield: { arrow_yield_1: {
input: { input: {
yield = "PASS"; yield = "PASS";
console.log(function*() { console.log(function*() {
@@ -108,6 +108,18 @@ arrow_yield: {
node_version: ">=4" node_version: ">=4"
} }
arrow_yield_2: {
input: {
console.log(typeof function *() {
// Syntax error on Node.js v6+
return (yield) => {};
}().next().value);
}
expect_exact: "console.log(typeof function*(){return(yield)=>{}}().next().value);"
expect_stdout: "function"
node_version: "4"
}
for_of: { for_of: {
input: { input: {
function* f() { function* f() {
@@ -1275,3 +1287,25 @@ issue_5076: {
expect_stdout: "PASS" expect_stdout: "PASS"
node_version: ">=6" node_version: ">=6"
} }
issue_5177: {
options = {
properties: true,
}
input: {
console.log(typeof function*() {
return {
p(yield) {},
}.p;
}().next().value);
}
expect: {
console.log(typeof function*() {
return {
p(yield) {},
}.p;
}().next().value);
}
expect_stdout: "function"
node_version: ">=4"
}

View File

@@ -0,0 +1 @@
console?.log``;

View File

@@ -1,7 +1,5 @@
// (beautified) // (beautified)
console.log(function() { console.log(1 + .1 + .1);
return 1 + .1 + .1;
}());
// output: 1.2000000000000002 // output: 1.2000000000000002
// //
// minify: 1.2 // minify: 1.2

View File

@@ -68,6 +68,8 @@ if (typeof phantom == "undefined") {
(function install() { (function install() {
npm([ npm([
"install", "install",
"graceful-fs@4.2.6",
"is-my-json-valid@2.20.5",
"phantomjs-prebuilt@2.1.14", "phantomjs-prebuilt@2.1.14",
"--no-audit", "--no-audit",
"--no-optional", "--no-optional",

View File

@@ -721,6 +721,20 @@ describe("bin/uglifyjs", function() {
done(); done();
}); });
}); });
it("Should throw syntax error (console?.log``)", function(done) {
var command = uglifyjscmd + " test/input/invalid/optional-template.js";
exec(command, function(err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
"Parse error at test/input/invalid/optional-template.js:1,12",
"console?.log``;",
" ^",
"ERROR: Invalid template on optional chain",
].join("\n"));
done();
});
});
it("Should handle literal string as source map input", function(done) { it("Should handle literal string as source map input", function(done) {
var command = [ var command = [
uglifyjscmd, uglifyjscmd,

View File

@@ -191,7 +191,7 @@ describe("comments", function() {
}); });
it("Should correctly preserve new lines around comments", function() { it("Should correctly preserve new lines around comments", function() {
var tests = [ [
[ [
"// foo", "// foo",
"// bar", "// bar",

View File

@@ -1,7 +1,6 @@
var assert = require("assert"); var assert = require("assert");
var exec = require("child_process").exec; var exec = require("child_process").exec;
var path = require("path"); var path = require("path");
var readFileSync = require("fs").readFileSync;
describe("bin/uglifyjs with input file globs", function() { describe("bin/uglifyjs with input file globs", function() {
var uglifyjscmd = '"' + process.argv[0] + '" bin/uglifyjs'; var uglifyjscmd = '"' + process.argv[0] + '" bin/uglifyjs';

View File

@@ -1,5 +1,5 @@
var assert = require("assert"); var assert = require("assert");
var UglifyJS = require("../.."); var UglifyJS = require("../node");
describe("let", function() { describe("let", function() {
this.timeout(30000); this.timeout(30000);
@@ -54,4 +54,43 @@ describe("let", function() {
assert.notStrictEqual(result.indexOf('v["' + name + '"]'), -1); assert.notStrictEqual(result.indexOf('v["' + name + '"]'), -1);
}); });
}); });
it("Should parse `let` as name correctly", function() {
[
"for(var let;let;let)let;",
"function let(let){let}",
].forEach(function(code) {
var ast = UglifyJS.parse(code);
assert.strictEqual(ast.print_to_string(), code);
assert.throws(function() {
UglifyJS.parse('"use strict";' + code);
}, function(e) {
return e instanceof UglifyJS.JS_Parse_Error && e.message == "Unexpected let in strict mode";
}, code);
});
});
it("Should throw on ambiguous use of `let`", function() {
[
"export let",
[
"let",
"console.log(42)",
].join("\n"),
[
"let",
"[ console.log(42) ]",
].join("\n"),
[
"let",
"{",
" console.log(42)",
"}",
].join("\n"),
].forEach(function(code) {
assert.throws(function() {
UglifyJS.parse(code);
}, function(e) {
return e instanceof UglifyJS.JS_Parse_Error;
}, code);
});
});
}); });

View File

@@ -25,7 +25,7 @@ describe("minify", function() {
if (result.error) throw result.error; if (result.error) throw result.error;
assert.strictEqual(result.code, "print(42);"); assert.strictEqual(result.code, "print(42);");
assert.strictEqual(JSON.stringify(options), value); assert.strictEqual(JSON.stringify(options), value);
}) });
it("Should skip inherited keys from `files`", function() { it("Should skip inherited keys from `files`", function() {
var files = Object.create({ skip: this }); var files = Object.create({ skip: this });
files[0] = "alert(1 + 1)"; files[0] = "alert(1 + 1)";

View File

@@ -1,5 +1,4 @@
var assert = require("assert"); var assert = require("assert");
var exec = require("child_process").exec;
var fs = require("fs"); var fs = require("fs");
var reduce_test = require("../reduce"); var reduce_test = require("../reduce");
var semver = require("semver"); var semver = require("semver");
@@ -282,35 +281,40 @@ describe("test/reduce.js", function() {
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
assert.deepEqual(result.warnings, []); assert.deepEqual(result.warnings, []);
assert.strictEqual(result.code.replace(/function \(/g, "function("), (semver.satisfies(process.version, "<=0.10") ? [ if (semver.satisfies(process.version, "<=0.10")) {
"// Can't reproduce test failure", assert.strictEqual(result.code, [
"// minify options: {", "// Can't reproduce test failure",
'// "compress": false,', "// minify options: {",
'// "mangle": false,', '// "compress": false,',
'// "output": {', '// "mangle": false,',
'// "beautify": true', '// "output": {',
"// }", '// "beautify": true',
"// }", "// }",
] : [ "// }",
[ ].join("\n"));
"try{", } else {
"null[function(){}]", var message = result.code.split(/\n/, 3)[1].slice("// output: ".length);
"}catch(e){", assert.strictEqual(result.code, [
"console.log(e)", [
"}", "try{",
].join(""), "null[function(){}]",
"// output: TypeError: Cannot read property 'function(){}' of null", "}catch(e){",
"// ", "console.log(e)",
"// minify: TypeError: Cannot read property 'function() {}' of null", "}",
"// ", ].join(""),
"// options: {", "// output: " + message,
'// "compress": false,', "// ",
'// "mangle": false,', "// minify: " + message.replace("(){}", "() {}"),
'// "output": {', "// ",
'// "beautify": true', "// options: {",
"// }", '// "compress": false,',
"// }", '// "mangle": false,',
]).join("\n")); '// "output": {',
'// "beautify": true',
"// }",
"// }",
].join("\n"));
}
}); });
it("Should maintain block-scope for const/let", function() { it("Should maintain block-scope for const/let", function() {
if (semver.satisfies(process.version, "<4")) return; if (semver.satisfies(process.version, "<4")) return;

View File

@@ -362,7 +362,7 @@ describe("sourcemaps", function() {
it("Should not modify input source map", function() { it("Should not modify input source map", function() {
var orig = get_map(); var orig = get_map();
var original = JSON.stringify(orig); var original = JSON.stringify(orig);
var map = prepare_map(orig); prepare_map(orig);
assert.strictEqual(JSON.stringify(orig), original); assert.strictEqual(JSON.stringify(orig), original);
}); });
it("Should copy over original sourcesContent", function() { it("Should copy over original sourcesContent", function() {

View File

@@ -4,34 +4,27 @@ var UglifyJS = require("../..");
describe("spidermonkey export/import sanity test", function() { describe("spidermonkey export/import sanity test", function() {
it("Should produce a functional build when using --self with spidermonkey", function(done) { it("Should produce a functional build when using --self with spidermonkey", function(done) {
this.timeout(60000); this.timeout(120000);
var uglifyjs = '"' + process.argv[0] + '" bin/uglifyjs'; var uglifyjs = '"' + process.argv[0] + '" bin/uglifyjs';
var command = uglifyjs + " --self -cm --wrap SpiderUglify -o spidermonkey | " + var command = [
uglifyjs + " -p spidermonkey -cm"; uglifyjs + " --self -cm --wrap SpiderUglify -o spidermonkey",
uglifyjs + " -p spidermonkey -cm",
exec(command, { ].join(" | ");
maxBuffer: 1048576 exec(command, { maxBuffer: 1048576 }, function(err, stdout) {
}, function(err, stdout) {
if (err) throw err; if (err) throw err;
eval(stdout); eval(stdout);
assert.strictEqual(typeof SpiderUglify, "object"); assert.strictEqual(typeof SpiderUglify, "object");
var result = SpiderUglify.minify("foo([true,,2+3]);"); var result = SpiderUglify.minify("foo([true,,2+3]);");
assert.strictEqual(result.error, undefined); assert.strictEqual(result.error, undefined);
assert.strictEqual(result.code, "foo([!0,,5]);"); assert.strictEqual(result.code, "foo([!0,,5]);");
done(); done();
}); });
}); });
it("Should not add unnecessary escape slashes to regexps", function() { it("Should not add unnecessary escape slashes to RegExp", function() {
var input = "/[\\\\/]/;"; var input = "/[\\\\/]/;";
var ast = UglifyJS.parse(input).to_mozilla_ast(); var ast = UglifyJS.parse(input).to_mozilla_ast();
assert.equal( assert.strictEqual(UglifyJS.AST_Node.from_mozilla_ast(ast).print_to_string(), input);
UglifyJS.AST_Node.from_mozilla_ast(ast).print_to_string(),
input
);
}); });
it("Should judge between directives and strings correctly on import", function() { it("Should judge between directives and strings correctly on import", function() {

View File

@@ -12,7 +12,7 @@ describe("String literals", function() {
'"\u2029"', '"\u2029"',
].forEach(function(input) { ].forEach(function(input) {
assert.throws(function() { assert.throws(function() {
var ast = UglifyJS.parse(input); UglifyJS.parse(input);
}, function(e) { }, function(e) {
return e instanceof UglifyJS.JS_Parse_Error return e instanceof UglifyJS.JS_Parse_Error
&& e.message === "Unterminated string constant"; && e.message === "Unterminated string constant";
@@ -44,7 +44,7 @@ describe("String literals", function() {
'"use strict";\n"\\011"', '"use strict";\n"\\011"',
].forEach(function(input) { ].forEach(function(input) {
assert.throws(function() { assert.throws(function() {
var output = UglifyJS.parse(input); UglifyJS.parse(input);
}, function(e) { }, function(e) {
return e instanceof UglifyJS.JS_Parse_Error return e instanceof UglifyJS.JS_Parse_Error
&& e.message === "Legacy octal escape sequences are not allowed in strict mode"; && e.message === "Legacy octal escape sequences are not allowed in strict mode";

View File

@@ -34,20 +34,20 @@ describe("Template literals", function() {
[ [
// native line breaks // native line breaks
[ "`foo\nbar`", "`foo\nbar`" ], [ "`foo\nbar`", "`foo\nbar`" ],
[ "`foo\rbar`", "`foo\rbar`" ], [ "`foo\rbar`", "`foo\nbar`" ],
[ "`foo\r\nbar`", "`foo\nbar`" ], [ "`foo\r\nbar`", "`foo\nbar`" ],
[ "`foo\r\n\rbar`", "`foo\n\rbar`" ], [ "`foo\r\n\rbar`", "`foo\n\nbar`" ],
// escaped line breaks // escaped line breaks
[ "`foo\\nbar`", "`foo\\nbar`" ], [ "`foo\\nbar`", "`foo\\nbar`" ],
[ "`foo\\rbar`", "`foo\\rbar`" ], [ "`foo\\rbar`", "`foo\\rbar`" ],
[ "`foo\r\\nbar`", "`foo\r\\nbar`" ], [ "`foo\r\\nbar`", "`foo\n\\nbar`" ],
[ "`foo\\r\nbar`", "`foo\\r\nbar`" ], [ "`foo\\r\nbar`", "`foo\\r\nbar`" ],
[ "`foo\\r\\nbar`", "`foo\\r\\nbar`" ], [ "`foo\\r\\nbar`", "`foo\\r\\nbar`" ],
// continuation // continuation
[ "`foo\\\nbar`", "`foo\\\nbar`" ], [ "`foo\\\nbar`", "`foo\\\nbar`" ],
[ "`foo\\\rbar`", "`foo\\\rbar`" ], [ "`foo\\\rbar`", "`foo\\\nbar`" ],
[ "`foo\\\r\nbar`", "`foo\\\nbar`" ], [ "`foo\\\r\nbar`", "`foo\\\nbar`" ],
[ "`foo\\\r\n\rbar`", "`foo\\\n\rbar`" ], [ "`foo\\\r\n\rbar`", "`foo\\\n\nbar`" ],
[ "`foo\\\\nbar`", "`foo\\\\nbar`" ], [ "`foo\\\\nbar`", "`foo\\\\nbar`" ],
[ "`foo\\\\rbar`", "`foo\\\\rbar`" ], [ "`foo\\\\rbar`", "`foo\\\\rbar`" ],
[ "`foo\\\\r\nbar`", "`foo\\\\r\nbar`" ], [ "`foo\\\\r\nbar`", "`foo\\\\r\nbar`" ],

View File

@@ -215,9 +215,9 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
// hoist and return expressions from the IIFE function expression // hoist and return expressions from the IIFE function expression
var seq = []; var seq = [];
node.expression.body.forEach(function(node) { node.expression.body.forEach(function(node) {
var expr = expr instanceof U.AST_Exit ? node.value : node.body; var expr = node instanceof U.AST_Exit ? node.value : node.body;
if (expr instanceof U.AST_Node && !U.is_statement(expr) && can_hoist(expr)) { if (expr instanceof U.AST_Node && !U.is_statement(expr) && can_hoist(expr)) {
// collect expressions from each statements' body // collect expressions from each statement's body
seq.push(expr); seq.push(expr);
} }
}); });
@@ -395,7 +395,7 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
var expr = [ var expr = [
node.expression, // switch expression node.expression, // switch expression
node.body[0] && node.body[0].expression, // first case expression or undefined node.body[0] && node.body[0].expression, // first case expression or undefined
node.body[0] && node.body[0], // first case body or undefined node.body[0], // first case body or undefined
][ (node.start._permute * steps | 0) % 4 ]; ][ (node.start._permute * steps | 0) % 4 ];
node.start._permute += step; node.start._permute += step;
if (expr && (!(expr instanceof U.AST_Statement) || !has_loopcontrol(expr, node, parent))) { if (expr && (!(expr instanceof U.AST_Statement) || !has_loopcontrol(expr, node, parent))) {

View File

@@ -28,7 +28,7 @@ exports.run_code = semver.satisfies(process.version, "0.8") ? function(code, top
if ([ if ([
/\basync[ \t]*\([\s\S]*?\)[ \t]*=>/, /\basync[ \t]*\([\s\S]*?\)[ \t]*=>/,
/\b(async[ \t]+function|Promise|setImmediate|setInterval|setTimeout)\b/, /\b(async[ \t]+function|Promise|setImmediate|setInterval|setTimeout)\b/,
/\basync([ \t]+|[ \t]*#|[ \t]*\*[ \t]*)[^\s()[\]{},.&|!~=*%/+-]+(\s*\(|[ \t]*=>)/, /\basync([ \t]+|[ \t]*#|[ \t]*\*[ \t]*)[^\s()[\]{}#:;,.&|!~=*%/+-]+(\s*\(|[ \t]*=>)/,
].some(function(pattern) { ].some(function(pattern) {
return pattern.test(code); return pattern.test(code);
})) { })) {
@@ -51,13 +51,13 @@ exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expec
}; };
exports.patch_module_statements = function(code) { exports.patch_module_statements = function(code) {
var count = 0, imports = []; var count = 0, imports = [];
code = code.replace(/\bexport(?:\s*\{[^}]*}\s*?(?:$|\n|;)|\s+default\b(?:\s*(\(|\{|class\s*\{|class\s+(?=extends\b)|(?:async\s+)?function\s*(?:\*\s*)?\())?|\b)/g, function(match, header) { code = code.replace(/\bexport(?:\s*\{[^{}]*}\s*?(?:$|\n|;)|\s+default\b(?:\s*(\(|\{|class\s*\{|class\s+(?=extends\b)|(?:async\s+)?function\s*(?:\*\s*)?\())?|\b)/g, function(match, header) {
if (!header) return ""; if (!header) return "";
if (header.length == 1) return "0, " + header; if (header.length == 1) return "0, " + header;
return header.slice(0, -1) + " _" + ++count + header.slice(-1); return header.slice(0, -1) + " _" + ++count + header.slice(-1);
}).replace(/\bimport\.meta\b/g, function() { }).replace(/\bimport\.meta\b/g, function() {
return '({ url: "https://example.com/path/index.html" })'; return '({ url: "https://example.com/path/index.html" })';
}).replace(/\bimport\b(?:\s*([^('"]+)\bfrom\b)?\s*(['"]).*?\2(?:$|\n|;)/g, function(match, symbols) { }).replace(/\bimport\b(?:\s*([^\s('"][^('"]*)\bfrom\b)?\s*(['"]).*?\2(?:$|\n|;)/g, function(match, symbols) {
if (symbols) { if (symbols) {
if (!/^[{*]/.test(symbols)) symbols = "default:" + symbols; if (!/^[{*]/.test(symbols)) symbols = "default:" + symbols;
symbols = symbols.replace(/[{}]/g, "").trim().replace(/\s*,\s*/g, ","); symbols = symbols.replace(/[{}]/g, "").trim().replace(/\s*,\s*/g, ",");
@@ -202,13 +202,11 @@ function setup(global, builtins, setup_log, setup_tty) {
}); });
Object.defineProperties(global, props); Object.defineProperties(global, props);
// for Node.js v8+ // for Node.js v8+
if (global.toString !== Object.prototype.toString) { global.__proto__ = Object.defineProperty(Object.create(global.__proto__), "toString", {
global.__proto__ = Object.defineProperty(Object.create(global.__proto__), "toString", { value: function() {
value: function() { return "[object global]";
return "[object global]"; },
}, });
});
}
function self() { function self() {
return this; return this;
@@ -278,11 +276,11 @@ function run_code_exec(code, toplevel, timeout) {
timeout: timeout || 5000, timeout: timeout || 5000,
}); });
if (result.status === 0) return result.stdout; if (result.status === 0) return result.stdout;
var msg = ("" + result.stderr).replace(/\r\n/g, "\n");
if (result.error && result.error.code == "ETIMEDOUT" || /FATAL ERROR:/.test(msg)) { if (result.error && result.error.code == "ETIMEDOUT" || /FATAL ERROR:/.test(msg)) {
return new Error("Script execution timed out."); return new Error("Script execution timed out.");
} }
if (result.error) return result.error; if (result.error) return result.error;
var msg = result.stderr.replace(/\r\n/g, "\n");
var end = msg.indexOf("\n\n-----===== UNCAUGHT EXCEPTION =====-----\n\n"); var end = msg.indexOf("\n\n-----===== UNCAUGHT EXCEPTION =====-----\n\n");
var details; var details;
if (end >= 0) { if (end >= 0) {

View File

@@ -334,6 +334,7 @@ var VAR_NAMES = [
"arguments", "arguments",
"async", "async",
"await", "await",
"let",
"yield", "yield",
]; ];
var INITIAL_NAMES_LEN = VAR_NAMES.length; var INITIAL_NAMES_LEN = VAR_NAMES.length;
@@ -352,7 +353,7 @@ var TYPEOF_OUTCOMES = [
]; ];
var avoid_vars = []; var avoid_vars = [];
var block_vars = []; var block_vars = [ "let" ];
var lambda_vars = []; var lambda_vars = [];
var unique_vars = []; var unique_vars = [];
var classes = []; var classes = [];
@@ -399,7 +400,7 @@ function mayDefer(code) {
function createTopLevelCode() { function createTopLevelCode() {
VAR_NAMES.length = INITIAL_NAMES_LEN; // prune any previous names still in the list VAR_NAMES.length = INITIAL_NAMES_LEN; // prune any previous names still in the list
block_vars.length = 0; block_vars.length = 1;
lambda_vars.length = 0; lambda_vars.length = 0;
unique_vars.length = 0; unique_vars.length = 0;
classes.length = 0; classes.length = 0;
@@ -2027,6 +2028,7 @@ function removeAvoidVar(name) {
function isBannedKeyword(name) { function isBannedKeyword(name) {
switch (name) { switch (name) {
case "arguments": case "arguments":
case "let":
return in_class; return in_class;
case "await": case "await":
return async !== false; return async !== false;
@@ -2078,8 +2080,8 @@ if (require.main !== module) {
return; return;
} }
function run_code(code, toplevel) { function run_code(code, toplevel, timeout) {
return sandbox.run_code(sandbox.patch_module_statements(code), toplevel); return sandbox.run_code(sandbox.patch_module_statements(code), toplevel, timeout);
} }
function writeln(stream, msg) { function writeln(stream, msg) {
@@ -2350,7 +2352,7 @@ function patch_try_catch(orig, toplevel) {
tries: [], tries: [],
} ]; } ];
var tail_throw = '\nif (typeof UFUZZ_ERROR == "object") throw UFUZZ_ERROR;\n'; var tail_throw = '\nif (typeof UFUZZ_ERROR == "object") throw UFUZZ_ERROR;\n';
var re = /(?:(?:^|[\s{}):;])try|}\s*catch\s*\(([^)[{]+)\)|}\s*finally)\s*(?={)/g; var re = /(?:(?:^|[\s{}):;])try|}\s*catch\s*\(([^()[{]+)\)|}\s*finally)\s*(?={)/g;
while (stack.length) { while (stack.length) {
var code = stack[0].code; var code = stack[0].code;
var offset = stack[0].offset; var offset = stack[0].offset;