Compare commits
50 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
860aa9531b | ||
|
|
2547542873 | ||
|
|
3f8f0e246e | ||
|
|
12227ebbb0 | ||
|
|
1b4bd7082b | ||
|
|
0b6c185818 | ||
|
|
bfd0ac7f4b | ||
|
|
1a8f2ecc65 | ||
|
|
dc9e1ff0b1 | ||
|
|
ea10498902 | ||
|
|
69636dad69 | ||
|
|
3ee1b0d00d | ||
|
|
1e3ca4c6f7 | ||
|
|
839f4361f4 | ||
|
|
ae5c3ee8a1 | ||
|
|
77f7ae5ba2 | ||
|
|
2d0f8bcff5 | ||
|
|
f97e107c09 | ||
|
|
e9932e1314 | ||
|
|
eaa84d32df | ||
|
|
6e4aa0326f | ||
|
|
f9a4b36dd1 | ||
|
|
3acb5a329e | ||
|
|
6d94242318 | ||
|
|
bca83cb9df | ||
|
|
a841d45bc3 | ||
|
|
eb93d92357 | ||
|
|
a0250ec923 | ||
|
|
25801627be | ||
|
|
32ae994f88 | ||
|
|
03aec89f60 | ||
|
|
faf0190546 | ||
|
|
c8b0f685ee | ||
|
|
87b99162fb | ||
|
|
940887f20f | ||
|
|
0b2573c3fa | ||
|
|
157521066f | ||
|
|
f766babf5e | ||
|
|
436a29367c | ||
|
|
55418fd460 | ||
|
|
85786889bd | ||
|
|
4b88dfb8d9 | ||
|
|
c3aef23614 | ||
|
|
db94d21980 | ||
|
|
9634a9d1fd | ||
|
|
befb99bd71 | ||
|
|
02eb8baa1c | ||
|
|
c09f63aefb | ||
|
|
fdcc6d3a9c | ||
|
|
4fe2cac35e |
7
.github/workflows/ci.yml
vendored
7
.github/workflows/ci.yml
vendored
@@ -7,14 +7,9 @@ jobs:
|
||||
test:
|
||||
strategy:
|
||||
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 ]
|
||||
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 }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
|
||||
11
README.md
11
README.md
@@ -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.defineProperty()`, `Object.defineProperties()`, `Object.freeze()`,
|
||||
`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:
|
||||
```javascript
|
||||
({
|
||||
|
||||
14
lib/ast.js
14
lib/ast.js
@@ -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",
|
||||
$propdoc: {
|
||||
args: "[AST_Node*] array of arguments",
|
||||
expression: "[AST_Node] expression to invoke as function",
|
||||
optional: "[boolean] whether the expression is optional chaining",
|
||||
pure: "[string/S] marker for side-effect-free call expression",
|
||||
terminal: "[boolean] whether the chain has ended",
|
||||
},
|
||||
walk: function(visitor) {
|
||||
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",
|
||||
_validate: function() {
|
||||
if (this.optional) throw new Error("optional must be false");
|
||||
if (this.terminal) throw new Error("terminal must be false");
|
||||
},
|
||||
}, 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\"]`",
|
||||
$propdoc: {
|
||||
expression: "[AST_Node] the “container” expression",
|
||||
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",
|
||||
terminal: "[boolean] whether the chain has ended",
|
||||
},
|
||||
get_property: function() {
|
||||
var p = this.property;
|
||||
@@ -1991,7 +1999,7 @@ TreeWalker.prototype = {
|
||||
},
|
||||
find_parent: function(type) {
|
||||
var stack = this.stack;
|
||||
for (var i = stack.length; --i >= 0;) {
|
||||
for (var i = stack.length - 1; --i >= 0;) {
|
||||
var x = stack[i];
|
||||
if (x instanceof type) return x;
|
||||
}
|
||||
|
||||
664
lib/compress.js
664
lib/compress.js
File diff suppressed because it is too large
Load Diff
@@ -556,7 +556,9 @@
|
||||
return node;
|
||||
},
|
||||
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) {
|
||||
var computed = M instanceof AST_Sub;
|
||||
return {
|
||||
var expr = {
|
||||
type: "MemberExpression",
|
||||
object: to_moz(M.expression),
|
||||
computed: computed,
|
||||
@@ -878,6 +880,10 @@
|
||||
name: M.property,
|
||||
},
|
||||
};
|
||||
return M.terminal ? {
|
||||
type: "ChainExpression",
|
||||
expression: expr,
|
||||
} : expr;
|
||||
});
|
||||
|
||||
def_to_moz(AST_Unary, function To_Moz_Unary(M) {
|
||||
|
||||
@@ -790,35 +790,26 @@ function OutputStream(options) {
|
||||
if (p instanceof AST_Unary) return true;
|
||||
});
|
||||
|
||||
function lhs_has_optional(node, output) {
|
||||
var p = output.parent();
|
||||
if (p instanceof AST_PropAccess && p.expression === node && is_lhs(p, output.parent(1))) {
|
||||
// ++(foo?.bar).baz
|
||||
// (foo?.()).bar = baz
|
||||
do {
|
||||
if (node.optional) return true;
|
||||
node = node.expression;
|
||||
} while (node.TYPE == "Call" || node instanceof AST_PropAccess);
|
||||
}
|
||||
function need_chain_parens(node, parent) {
|
||||
if (!node.terminal) return false;
|
||||
if (!(parent instanceof AST_Call || parent instanceof AST_PropAccess)) return false;
|
||||
return parent.expression === node;
|
||||
}
|
||||
|
||||
PARENS(AST_PropAccess, function(output) {
|
||||
var node = this;
|
||||
var p = output.parent();
|
||||
if (p instanceof AST_New) {
|
||||
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
|
||||
// interpreted as passing the arguments to the upper New
|
||||
// expression.
|
||||
do {
|
||||
node = node.expression;
|
||||
} while (node instanceof AST_PropAccess);
|
||||
return node.TYPE == "Call";
|
||||
}
|
||||
return lhs_has_optional(node, output);
|
||||
// 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
|
||||
// interpreted as passing the arguments to the upper New
|
||||
// expression.
|
||||
if (p instanceof AST_New && p.expression === node && root_expr(node).TYPE == "Call") return true;
|
||||
// (foo?.bar)()
|
||||
// (foo?.bar).baz
|
||||
// new (foo?.bar)()
|
||||
return need_chain_parens(node, p);
|
||||
});
|
||||
|
||||
PARENS(AST_Call, function(output) {
|
||||
@@ -833,7 +824,10 @@ function OutputStream(options) {
|
||||
var g = output.parent(1);
|
||||
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) {
|
||||
@@ -1158,8 +1152,9 @@ function OutputStream(options) {
|
||||
});
|
||||
}
|
||||
function print_arrow(self, output) {
|
||||
if (self.argnames.length == 1 && self.argnames[0] instanceof AST_SymbolFunarg && !self.rest) {
|
||||
self.argnames[0].print(output);
|
||||
var argname = self.argnames.length == 1 && !self.rest && self.argnames[0];
|
||||
if (argname instanceof AST_SymbolFunarg && argname.name != "yield") {
|
||||
argname.print(output);
|
||||
} else {
|
||||
print_funargs(self, output);
|
||||
}
|
||||
|
||||
153
lib/parse.js
153
lib/parse.js
@@ -44,10 +44,10 @@
|
||||
|
||||
"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 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,
|
||||
].join(" ");
|
||||
@@ -242,10 +242,10 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
read_template : with_eof_error("Unterminated template literal", function(strings) {
|
||||
var s = "";
|
||||
for (;;) {
|
||||
var ch = next(true, true);
|
||||
var ch = read();
|
||||
switch (ch) {
|
||||
case "\\":
|
||||
ch += next(true, true);
|
||||
ch += read();
|
||||
break;
|
||||
case "`":
|
||||
strings.push(s);
|
||||
@@ -260,6 +260,11 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
}
|
||||
s += ch;
|
||||
}
|
||||
|
||||
function read() {
|
||||
var ch = next(true, true);
|
||||
return ch == "\r" ? "\n" : ch;
|
||||
}
|
||||
}),
|
||||
};
|
||||
var prev_was_dot = false;
|
||||
@@ -862,6 +867,15 @@ function parse($TEXT, options) {
|
||||
next();
|
||||
return import_();
|
||||
}
|
||||
break;
|
||||
case "let":
|
||||
if (is_vardefs()) {
|
||||
next();
|
||||
var node = let_();
|
||||
semicolon();
|
||||
return node;
|
||||
}
|
||||
break;
|
||||
case "yield":
|
||||
if (S.in_generator) return simple_statement();
|
||||
break;
|
||||
@@ -947,12 +961,6 @@ function parse($TEXT, options) {
|
||||
next();
|
||||
return if_();
|
||||
|
||||
case "let":
|
||||
next();
|
||||
var node = let_();
|
||||
semicolon();
|
||||
return node;
|
||||
|
||||
case "return":
|
||||
if (S.in_function == 0 && !options.bare_returns)
|
||||
croak("'return' outside of function");
|
||||
@@ -1192,7 +1200,7 @@ function parse($TEXT, options) {
|
||||
if (await || !is("punc", ";")) {
|
||||
init = is("keyword", "const")
|
||||
? (next(), const_(true))
|
||||
: is("keyword", "let")
|
||||
: is("name", "let") && is_vardefs()
|
||||
? (next(), let_(true))
|
||||
: is("keyword", "var")
|
||||
? (next(), var_(true))
|
||||
@@ -1308,6 +1316,11 @@ function parse($TEXT, options) {
|
||||
}
|
||||
if (node instanceof AST_SymbolFunarg) return 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");
|
||||
}
|
||||
|
||||
@@ -1535,12 +1548,18 @@ function parse($TEXT, options) {
|
||||
}
|
||||
|
||||
var export_decl = embed_tokens(function() {
|
||||
if (is("name", "async")) {
|
||||
if (is("name")) switch (S.token.value) {
|
||||
case "async":
|
||||
next();
|
||||
expect_token("keyword", "function");
|
||||
if (!is("operator", "*")) return function_(AST_AsyncDefun);
|
||||
next();
|
||||
return function_(AST_AsyncGeneratorDefun);
|
||||
case "let":
|
||||
next();
|
||||
var node = let_();
|
||||
semicolon();
|
||||
return node;
|
||||
} else if (is("keyword")) switch (S.token.value) {
|
||||
case "class":
|
||||
next();
|
||||
@@ -1555,11 +1574,6 @@ function parse($TEXT, options) {
|
||||
if (!is("operator", "*")) return function_(AST_Defun);
|
||||
next();
|
||||
return function_(AST_GeneratorDefun);
|
||||
case "let":
|
||||
next();
|
||||
var node = let_();
|
||||
semicolon();
|
||||
return node;
|
||||
case "var":
|
||||
next();
|
||||
var node = var_();
|
||||
@@ -1720,6 +1734,11 @@ function parse($TEXT, options) {
|
||||
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) {
|
||||
return new AST_Const({
|
||||
start : prev(),
|
||||
@@ -1818,10 +1837,7 @@ function parse($TEXT, options) {
|
||||
if (is("punc")) {
|
||||
switch (start.value) {
|
||||
case "`":
|
||||
var tmpl = template(null);
|
||||
tmpl.start = start;
|
||||
tmpl.end = prev();
|
||||
return subscripts(tmpl, allow_calls);
|
||||
return subscripts(template(null), allow_calls);
|
||||
case "(":
|
||||
next();
|
||||
if (is("punc", ")")) {
|
||||
@@ -2133,7 +2149,7 @@ function parse($TEXT, options) {
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
@@ -2230,6 +2246,7 @@ function parse($TEXT, options) {
|
||||
}
|
||||
|
||||
function template(tag) {
|
||||
var start = tag ? tag.start : S.token;
|
||||
var read = S.input.context().read_template;
|
||||
var strings = [];
|
||||
var expressions = [];
|
||||
@@ -2240,58 +2257,60 @@ function parse($TEXT, options) {
|
||||
}
|
||||
next();
|
||||
return new AST_Template({
|
||||
start: start,
|
||||
expressions: expressions,
|
||||
strings: strings,
|
||||
tag: tag,
|
||||
end: prev(),
|
||||
});
|
||||
}
|
||||
|
||||
var subscripts = function(expr, allow_calls, optional) {
|
||||
function subscripts(expr, allow_calls) {
|
||||
var start = expr.start;
|
||||
if (is("punc", "[")) {
|
||||
next();
|
||||
var prop = expression();
|
||||
expect("]");
|
||||
return subscripts(new AST_Sub({
|
||||
start: start,
|
||||
optional: optional,
|
||||
expression: expr,
|
||||
property: prop,
|
||||
end: prev(),
|
||||
}), allow_calls);
|
||||
}
|
||||
if (allow_calls && is("punc", "(")) {
|
||||
next();
|
||||
var call = new AST_Call({
|
||||
start: start,
|
||||
optional: optional,
|
||||
expression: expr,
|
||||
args: expr_list(")", !options.strict),
|
||||
end: prev(),
|
||||
});
|
||||
return subscripts(call, true);
|
||||
}
|
||||
if (optional || is("punc", ".")) {
|
||||
if (!optional) next();
|
||||
return subscripts(new AST_Dot({
|
||||
start: start,
|
||||
optional: optional,
|
||||
expression: expr,
|
||||
property: as_name(),
|
||||
end: prev(),
|
||||
}), allow_calls);
|
||||
}
|
||||
if (is("punc", "`")) {
|
||||
var tmpl = template(expr);
|
||||
tmpl.start = expr.start;
|
||||
tmpl.end = prev();
|
||||
return subscripts(tmpl, allow_calls);
|
||||
}
|
||||
if (is("operator", "?") && is_token(peek(), "punc", ".")) {
|
||||
next();
|
||||
next();
|
||||
return subscripts(expr, allow_calls, true);
|
||||
var optional = null;
|
||||
while (true) {
|
||||
if (is("operator", "?") && is_token(peek(), "punc", ".")) {
|
||||
next();
|
||||
next();
|
||||
optional = expr;
|
||||
}
|
||||
if (is("punc", "[")) {
|
||||
next();
|
||||
var prop = expression();
|
||||
expect("]");
|
||||
expr = new AST_Sub({
|
||||
start: start,
|
||||
optional: optional === expr,
|
||||
expression: expr,
|
||||
property: prop,
|
||||
end: prev(),
|
||||
});
|
||||
} else if (allow_calls && is("punc", "(")) {
|
||||
next();
|
||||
expr = new AST_Call({
|
||||
start: start,
|
||||
optional: optional === expr,
|
||||
expression: expr,
|
||||
args: expr_list(")", !options.strict),
|
||||
end: prev(),
|
||||
});
|
||||
} else if (optional === expr || is("punc", ".")) {
|
||||
if (optional !== expr) next();
|
||||
expr = new AST_Dot({
|
||||
start: start,
|
||||
optional: optional === expr,
|
||||
expression: expr,
|
||||
property: as_name(),
|
||||
end: prev(),
|
||||
});
|
||||
} else if (is("punc", "`")) {
|
||||
if (optional) croak("Invalid template on optional chain");
|
||||
expr = template(expr);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (optional) expr.terminal = true;
|
||||
if (expr instanceof AST_Call && !expr.pure) {
|
||||
var start = expr.start;
|
||||
var comments = start.comments_before;
|
||||
@@ -2305,7 +2324,7 @@ function parse($TEXT, options) {
|
||||
}
|
||||
}
|
||||
return expr;
|
||||
};
|
||||
}
|
||||
|
||||
function maybe_unary(no_in) {
|
||||
var start = S.token;
|
||||
|
||||
@@ -143,7 +143,7 @@ function push_uniq(array, el) {
|
||||
}
|
||||
|
||||
function string_template(text, props) {
|
||||
return text.replace(/\{([^}]+)\}/g, function(str, p) {
|
||||
return text.replace(/\{([^{}]+)\}/g, function(str, p) {
|
||||
var value = props[p];
|
||||
return value instanceof AST_Node ? value.print_to_string() : value;
|
||||
});
|
||||
|
||||
@@ -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.14.1",
|
||||
"version": "3.14.4",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
|
||||
@@ -550,6 +550,24 @@ logical_side_effects: {
|
||||
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: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
|
||||
@@ -227,7 +227,7 @@ inline_await_1_trim: {
|
||||
console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
void 0;
|
||||
0;
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
@@ -453,7 +453,7 @@ object_function: {
|
||||
}).f();
|
||||
}
|
||||
expect: {
|
||||
(async function() {
|
||||
(async () => {
|
||||
console.log("PASS");
|
||||
})();
|
||||
}
|
||||
@@ -571,7 +571,7 @@ drop_async_1: {
|
||||
}
|
||||
expect: {
|
||||
console.log(function(a) {
|
||||
void (a *= 7);
|
||||
a *= 7;
|
||||
return a;
|
||||
}(6));
|
||||
}
|
||||
@@ -1774,7 +1774,7 @@ issue_5001: {
|
||||
}
|
||||
expect: {
|
||||
var a = 0;
|
||||
void a++;
|
||||
a++;
|
||||
console.log(a ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
@@ -2046,3 +2046,195 @@ issue_5070: {
|
||||
expect_stdout: "PASS"
|
||||
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"
|
||||
}
|
||||
|
||||
@@ -2066,3 +2066,34 @@ issue_5082_2: {
|
||||
expect_stdout: "PASS"
|
||||
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"
|
||||
}
|
||||
|
||||
@@ -9253,13 +9253,13 @@ issue_4920_2: {
|
||||
console.log(b);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
var o;
|
||||
var a = "PASS", b;
|
||||
({
|
||||
get PASS() {
|
||||
a = "FAIL";
|
||||
},
|
||||
};
|
||||
var a = "PASS", b;
|
||||
o[b = a];
|
||||
})[b = a];
|
||||
console.log(b);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
@@ -9283,16 +9283,47 @@ issue_4920_3: {
|
||||
}
|
||||
expect: {
|
||||
var log = console.log;
|
||||
var o = {
|
||||
var o;
|
||||
var a = "PASS", b;
|
||||
({
|
||||
get PASS() {
|
||||
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;
|
||||
o[b = a];
|
||||
log(b);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
issue_4935: {
|
||||
@@ -9412,3 +9443,126 @@ issue_4977_2: {
|
||||
}
|
||||
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"
|
||||
}
|
||||
|
||||
@@ -289,3 +289,18 @@ issue_3689: {
|
||||
}
|
||||
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"
|
||||
}
|
||||
|
||||
@@ -1633,3 +1633,39 @@ issue_5030: {
|
||||
expect_stdout: "PASS"
|
||||
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"
|
||||
}
|
||||
|
||||
@@ -568,6 +568,20 @@ retain_empty_iife: {
|
||||
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: {
|
||||
options = {
|
||||
unused: true,
|
||||
@@ -1890,3 +1904,56 @@ issue_5065: {
|
||||
expect_stdout: "PASS"
|
||||
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"
|
||||
}
|
||||
|
||||
@@ -1581,6 +1581,75 @@ hoist_vars: {
|
||||
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: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
@@ -2127,7 +2196,7 @@ issue_4372_2: {
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
[ a ] = [ "PASS", "FAIL" ];
|
||||
[ a ] = a = [ "PASS", "FAIL" ];
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
@@ -3057,3 +3126,243 @@ issue_5087_2: {
|
||||
expect_stdout: "PASS"
|
||||
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"
|
||||
}
|
||||
|
||||
@@ -1557,9 +1557,9 @@ issue_2665: {
|
||||
}
|
||||
expect: {
|
||||
var a = 1;
|
||||
!function g() {
|
||||
(function g() {
|
||||
a-- && g();
|
||||
}();
|
||||
})();
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "-1"
|
||||
@@ -2916,7 +2916,7 @@ issue_4133: {
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var b = 1;
|
||||
var a = 1;
|
||||
console.log(0);
|
||||
}
|
||||
expect_stdout: "0"
|
||||
@@ -3062,7 +3062,7 @@ issue_4184: {
|
||||
expect_stdout: "42"
|
||||
}
|
||||
|
||||
issue_4235: {
|
||||
issue_4235_1: {
|
||||
options = {
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
@@ -3081,13 +3081,37 @@ issue_4235: {
|
||||
}
|
||||
expect: {
|
||||
void function() {
|
||||
var f;
|
||||
console.log(f);
|
||||
var f = console.log(f);
|
||||
}();
|
||||
}
|
||||
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: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
@@ -3379,7 +3403,7 @@ issue_4834: {
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
void b.p;
|
||||
b.p;
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
|
||||
@@ -99,8 +99,8 @@ issue_4664: {
|
||||
expect: {
|
||||
(function f() {
|
||||
new function(a) {
|
||||
console.log(typeof f, 1073741824, typeof this);
|
||||
}(A = 0);
|
||||
console.log(typeof f, a, typeof this);
|
||||
}((A = 0, 2 ** 30));
|
||||
})();
|
||||
}
|
||||
expect_stdout: "function 1073741824 object"
|
||||
|
||||
@@ -1171,11 +1171,11 @@ issue_2620_4: {
|
||||
}
|
||||
expect: {
|
||||
var c = "FAIL";
|
||||
!function() {
|
||||
(function() {
|
||||
switch (NaN) {
|
||||
case void (c = "PASS"):
|
||||
}
|
||||
}();
|
||||
})();
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
@@ -4857,8 +4857,9 @@ issue_4155: {
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
void console.log(b);
|
||||
var b = function() {};
|
||||
var a;
|
||||
void console.log(a);
|
||||
function b() {}
|
||||
b && console.log(typeof b);
|
||||
})();
|
||||
}
|
||||
@@ -6565,3 +6566,139 @@ issue_5098: {
|
||||
}
|
||||
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"
|
||||
}
|
||||
|
||||
@@ -217,7 +217,8 @@ name_collision_1: {
|
||||
var obj_foo = 1;
|
||||
var obj_bar = 2;
|
||||
function f() {
|
||||
var obj_foo$0 = 3,
|
||||
var obj,
|
||||
obj_foo$0 = 3,
|
||||
obj_bar = 4,
|
||||
obj_b_r = 5,
|
||||
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);
|
||||
}
|
||||
expect: {
|
||||
var o_p = 1,
|
||||
var o,
|
||||
o_p = 1,
|
||||
o__ = function(x) {
|
||||
return x;
|
||||
},
|
||||
@@ -283,7 +285,8 @@ name_collision_3: {
|
||||
console.log(o.p === o.p, o["+"](4), o["-"](5));
|
||||
}
|
||||
expect: {
|
||||
var o_p = 1,
|
||||
var o,
|
||||
o_p = 1,
|
||||
o__ = function(x) {
|
||||
return x;
|
||||
},
|
||||
@@ -315,7 +318,7 @@ name_collision_4: {
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
var o_p$0 = 0, o_q = "PASS";
|
||||
var o, o_p$0 = 0, o_q = "PASS";
|
||||
return function(o_p) {
|
||||
if (!o_p$0) return o_p;
|
||||
}(o_q);
|
||||
@@ -768,7 +771,7 @@ issue_3046: {
|
||||
expect: {
|
||||
console.log(function(a) {
|
||||
do {
|
||||
var b_c = a++;
|
||||
var b, b_c = a++;
|
||||
} while (b_c && a);
|
||||
return a;
|
||||
}(0));
|
||||
@@ -931,7 +934,7 @@ issue_3411: {
|
||||
expect: {
|
||||
var c = 1;
|
||||
!function f() {
|
||||
var o_p = --c && f();
|
||||
var o, o_p = --c && f();
|
||||
+{} || console.log("PASS");
|
||||
}();
|
||||
}
|
||||
@@ -1042,9 +1045,7 @@ issue_3945_1: {
|
||||
expect: {
|
||||
function f() {
|
||||
o.p;
|
||||
var o = {
|
||||
q: 0,
|
||||
};
|
||||
var o, o_q = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1063,9 +1064,7 @@ issue_3945_2: {
|
||||
}
|
||||
expect: {
|
||||
console.log(typeof o);
|
||||
var o = {
|
||||
p: 0,
|
||||
};
|
||||
var o, o_p = 0;
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
@@ -1134,10 +1133,46 @@ issue_4985: {
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
var a_p = 42;
|
||||
var a, a_p = 42;
|
||||
console.log(function() {
|
||||
({});
|
||||
}());
|
||||
}
|
||||
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",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ issue_2295: {
|
||||
}
|
||||
}
|
||||
|
||||
issue_4487: {
|
||||
issue_4487_1: {
|
||||
options = {
|
||||
functions: true,
|
||||
hoist_vars: true,
|
||||
@@ -150,16 +150,64 @@ issue_4487: {
|
||||
};
|
||||
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: {
|
||||
function a() {
|
||||
var f;
|
||||
console.log(typeof f);
|
||||
var f = console.log(typeof f);
|
||||
}
|
||||
a();
|
||||
}
|
||||
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: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
@@ -251,18 +299,18 @@ issue_4839: {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var o = function(a, b) {
|
||||
var log = console.log, o = function(a, b) {
|
||||
return b && b;
|
||||
}("foo");
|
||||
for (var k in o)
|
||||
throw "FAIL";
|
||||
console.log("PASS");
|
||||
log("PASS");
|
||||
}
|
||||
expect: {
|
||||
var k, o = void 0;
|
||||
for (k in o)
|
||||
var k, log = console.log;
|
||||
for (k in void 0)
|
||||
throw "FAIL";
|
||||
console.log("PASS");
|
||||
log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
@@ -288,8 +336,7 @@ issue_4859: {
|
||||
}
|
||||
expect: {
|
||||
(function f(a) {
|
||||
var d = 1 / 0, d = Infinity;
|
||||
console.log(d);
|
||||
console.log(Infinity);
|
||||
return f;
|
||||
})();
|
||||
}
|
||||
@@ -395,3 +442,61 @@ issue_4898: {
|
||||
}
|
||||
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]"
|
||||
}
|
||||
|
||||
@@ -489,6 +489,116 @@ join_object_assignments_regex: {
|
||||
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: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
@@ -1183,3 +1293,26 @@ assign_sequence_var: {
|
||||
"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"
|
||||
}
|
||||
|
||||
@@ -83,8 +83,9 @@ labels_5: {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
if_return: true,
|
||||
unused: true,
|
||||
}
|
||||
// should keep the break-s in the following
|
||||
// should keep `break`s below
|
||||
input: {
|
||||
while (foo) {
|
||||
if (bar) break;
|
||||
@@ -100,8 +101,8 @@ labels_5: {
|
||||
if (bar) break;
|
||||
console.log("foo");
|
||||
}
|
||||
out: while (foo) {
|
||||
if (bar) break out;
|
||||
while (foo) {
|
||||
if (bar) break;
|
||||
console.log("foo");
|
||||
}
|
||||
}
|
||||
@@ -189,23 +190,22 @@ labels_10: {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
if_return: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
out: while (foo) {
|
||||
x();
|
||||
y();
|
||||
out: while (42) {
|
||||
console.log("PASS");
|
||||
break out;
|
||||
z();
|
||||
k();
|
||||
console.log("FAIL");
|
||||
}
|
||||
};
|
||||
expect: {
|
||||
out: while (foo) {
|
||||
x();
|
||||
y();
|
||||
break out;
|
||||
while (42) {
|
||||
console.log("PASS");
|
||||
break;
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4466_1: {
|
||||
|
||||
@@ -476,9 +476,9 @@ issue_4112: {
|
||||
try {
|
||||
throw 42;
|
||||
} catch (e) {
|
||||
var a = e;
|
||||
for (e in a);
|
||||
a = function() {};
|
||||
var o = e;
|
||||
for (e in o);
|
||||
function a() {}
|
||||
console.log(typeof a);
|
||||
return a;
|
||||
}
|
||||
@@ -3377,3 +3377,60 @@ issue_4956_2: {
|
||||
}
|
||||
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"
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ assign_parentheses_dot: {
|
||||
input: {
|
||||
(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"
|
||||
node_version: ">=14"
|
||||
}
|
||||
@@ -72,6 +72,26 @@ assign_no_parentheses: {
|
||||
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: {
|
||||
input: {
|
||||
var o = { p: 41 };
|
||||
@@ -237,6 +257,99 @@ trim_2: {
|
||||
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: {
|
||||
options = {
|
||||
toplevel: true,
|
||||
|
||||
@@ -1510,3 +1510,71 @@ issue_5093_quote_style: {
|
||||
expect_exact: 'console.log({a:true,\'42\':"PASS","null":[]}[6*7]);'
|
||||
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"
|
||||
}
|
||||
|
||||
@@ -1640,6 +1640,26 @@ nested_property_assignments_3: {
|
||||
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: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
|
||||
@@ -7320,6 +7320,64 @@ local_assignment_loop: {
|
||||
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: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
@@ -7435,6 +7493,7 @@ issue_4030: {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
|
||||
@@ -636,6 +636,24 @@ keep_rest_lambda_2: {
|
||||
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: {
|
||||
options = {
|
||||
arguments: true,
|
||||
@@ -1026,13 +1044,13 @@ issue_5100_1: {
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
[ {
|
||||
({
|
||||
p: {},
|
||||
...a
|
||||
} ] = [ {
|
||||
} = [ {
|
||||
p: [ a = 42["q"] ],
|
||||
r: "PASS",
|
||||
} ];
|
||||
} ][0]);
|
||||
console.log(a.r);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
@@ -1059,13 +1077,131 @@ issue_5100_2: {
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
[ {
|
||||
({
|
||||
p: {},
|
||||
...a
|
||||
} ] = [ {
|
||||
} = [ {
|
||||
p: [ console.log("PASS"), a = 42["q"] ],
|
||||
} ];
|
||||
} ][0]);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
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"
|
||||
}
|
||||
|
||||
@@ -201,3 +201,20 @@ issue_4811_2: {
|
||||
expect_stdout: "PASS [object global] true"
|
||||
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]"
|
||||
}
|
||||
|
||||
@@ -131,6 +131,105 @@ malformed_escape: {
|
||||
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: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
@@ -174,7 +273,7 @@ partial_evaluate: {
|
||||
console.log(`${6 * 7} foo ${console ? `PA` + "SS" : `FA` + `IL`}`);
|
||||
}
|
||||
expect: {
|
||||
console.log(`42 foo ${console ? "PASS" : "FAIL"}`);
|
||||
console.log("42 foo " + (console ? "PASS" : "FAIL"));
|
||||
}
|
||||
expect_stdout: "42 foo PASS"
|
||||
node_version: ">=4"
|
||||
@@ -204,7 +303,7 @@ malformed_evaluate_2: {
|
||||
console.log(`\u0${0}b${5}`);
|
||||
}
|
||||
expect: {
|
||||
console.log(`\u0${0}b5`);
|
||||
console.log(`\u00b` + 5);
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=4"
|
||||
@@ -357,13 +456,14 @@ issue_4604: {
|
||||
issue_4606: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
strings: true,
|
||||
templates: true,
|
||||
}
|
||||
input: {
|
||||
console.log(`${typeof A} ${"\r"} ${"\\"} ${"`"}`);
|
||||
}
|
||||
expect: {
|
||||
console.log(`${typeof A} \r \\ \``);
|
||||
console.log(typeof A + " \r \\ `");
|
||||
}
|
||||
expect_stdout: "undefined \r \\ `"
|
||||
node_version: ">=4"
|
||||
@@ -434,3 +534,238 @@ issue_4931: {
|
||||
]
|
||||
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"
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ hoist_props_const: {
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var o_p = "PASS";
|
||||
var o = 0, o_p = "PASS";
|
||||
console.log(o_p);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
@@ -136,7 +136,7 @@ hoist_props_let: {
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
var o_p = "PASS";
|
||||
var o, o_p = "PASS";
|
||||
console.log(o_p);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
|
||||
@@ -96,7 +96,7 @@ pause_resume: {
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
arrow_yield: {
|
||||
arrow_yield_1: {
|
||||
input: {
|
||||
yield = "PASS";
|
||||
console.log(function*() {
|
||||
@@ -108,6 +108,18 @@ arrow_yield: {
|
||||
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: {
|
||||
input: {
|
||||
function* f() {
|
||||
@@ -1275,3 +1287,25 @@ issue_5076: {
|
||||
expect_stdout: "PASS"
|
||||
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"
|
||||
}
|
||||
|
||||
1
test/input/invalid/optional-template.js
Normal file
1
test/input/invalid/optional-template.js
Normal file
@@ -0,0 +1 @@
|
||||
console?.log``;
|
||||
@@ -1,7 +1,5 @@
|
||||
// (beautified)
|
||||
console.log(function() {
|
||||
return 1 + .1 + .1;
|
||||
}());
|
||||
console.log(1 + .1 + .1);
|
||||
// output: 1.2000000000000002
|
||||
//
|
||||
// minify: 1.2
|
||||
|
||||
@@ -68,6 +68,8 @@ if (typeof phantom == "undefined") {
|
||||
(function install() {
|
||||
npm([
|
||||
"install",
|
||||
"graceful-fs@4.2.6",
|
||||
"is-my-json-valid@2.20.5",
|
||||
"phantomjs-prebuilt@2.1.14",
|
||||
"--no-audit",
|
||||
"--no-optional",
|
||||
|
||||
@@ -721,6 +721,20 @@ describe("bin/uglifyjs", function() {
|
||||
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) {
|
||||
var command = [
|
||||
uglifyjscmd,
|
||||
|
||||
@@ -191,7 +191,7 @@ describe("comments", function() {
|
||||
});
|
||||
|
||||
it("Should correctly preserve new lines around comments", function() {
|
||||
var tests = [
|
||||
[
|
||||
[
|
||||
"// foo",
|
||||
"// bar",
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
var assert = require("assert");
|
||||
var exec = require("child_process").exec;
|
||||
var path = require("path");
|
||||
var readFileSync = require("fs").readFileSync;
|
||||
|
||||
describe("bin/uglifyjs with input file globs", function() {
|
||||
var uglifyjscmd = '"' + process.argv[0] + '" bin/uglifyjs';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
var assert = require("assert");
|
||||
var UglifyJS = require("../..");
|
||||
var UglifyJS = require("../node");
|
||||
|
||||
describe("let", function() {
|
||||
this.timeout(30000);
|
||||
@@ -54,4 +54,43 @@ describe("let", function() {
|
||||
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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -25,7 +25,7 @@ describe("minify", function() {
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, "print(42);");
|
||||
assert.strictEqual(JSON.stringify(options), value);
|
||||
})
|
||||
});
|
||||
it("Should skip inherited keys from `files`", function() {
|
||||
var files = Object.create({ skip: this });
|
||||
files[0] = "alert(1 + 1)";
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
var assert = require("assert");
|
||||
var exec = require("child_process").exec;
|
||||
var fs = require("fs");
|
||||
var reduce_test = require("../reduce");
|
||||
var semver = require("semver");
|
||||
@@ -282,35 +281,40 @@ describe("test/reduce.js", function() {
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.deepEqual(result.warnings, []);
|
||||
assert.strictEqual(result.code.replace(/function \(/g, "function("), (semver.satisfies(process.version, "<=0.10") ? [
|
||||
"// Can't reproduce test failure",
|
||||
"// minify options: {",
|
||||
'// "compress": false,',
|
||||
'// "mangle": false,',
|
||||
'// "output": {',
|
||||
'// "beautify": true',
|
||||
"// }",
|
||||
"// }",
|
||||
] : [
|
||||
[
|
||||
"try{",
|
||||
"null[function(){}]",
|
||||
"}catch(e){",
|
||||
"console.log(e)",
|
||||
"}",
|
||||
].join(""),
|
||||
"// output: TypeError: Cannot read property 'function(){}' of null",
|
||||
"// ",
|
||||
"// minify: TypeError: Cannot read property 'function() {}' of null",
|
||||
"// ",
|
||||
"// options: {",
|
||||
'// "compress": false,',
|
||||
'// "mangle": false,',
|
||||
'// "output": {',
|
||||
'// "beautify": true',
|
||||
"// }",
|
||||
"// }",
|
||||
]).join("\n"));
|
||||
if (semver.satisfies(process.version, "<=0.10")) {
|
||||
assert.strictEqual(result.code, [
|
||||
"// Can't reproduce test failure",
|
||||
"// minify options: {",
|
||||
'// "compress": false,',
|
||||
'// "mangle": false,',
|
||||
'// "output": {',
|
||||
'// "beautify": true',
|
||||
"// }",
|
||||
"// }",
|
||||
].join("\n"));
|
||||
} else {
|
||||
var message = result.code.split(/\n/, 3)[1].slice("// output: ".length);
|
||||
assert.strictEqual(result.code, [
|
||||
[
|
||||
"try{",
|
||||
"null[function(){}]",
|
||||
"}catch(e){",
|
||||
"console.log(e)",
|
||||
"}",
|
||||
].join(""),
|
||||
"// output: " + message,
|
||||
"// ",
|
||||
"// minify: " + message.replace("(){}", "() {}"),
|
||||
"// ",
|
||||
"// options: {",
|
||||
'// "compress": false,',
|
||||
'// "mangle": false,',
|
||||
'// "output": {',
|
||||
'// "beautify": true',
|
||||
"// }",
|
||||
"// }",
|
||||
].join("\n"));
|
||||
}
|
||||
});
|
||||
it("Should maintain block-scope for const/let", function() {
|
||||
if (semver.satisfies(process.version, "<4")) return;
|
||||
|
||||
@@ -362,7 +362,7 @@ describe("sourcemaps", function() {
|
||||
it("Should not modify input source map", function() {
|
||||
var orig = get_map();
|
||||
var original = JSON.stringify(orig);
|
||||
var map = prepare_map(orig);
|
||||
prepare_map(orig);
|
||||
assert.strictEqual(JSON.stringify(orig), original);
|
||||
});
|
||||
it("Should copy over original sourcesContent", function() {
|
||||
|
||||
@@ -4,34 +4,27 @@ var UglifyJS = require("../..");
|
||||
|
||||
describe("spidermonkey export/import sanity test", function() {
|
||||
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 command = uglifyjs + " --self -cm --wrap SpiderUglify -o spidermonkey | " +
|
||||
uglifyjs + " -p spidermonkey -cm";
|
||||
|
||||
exec(command, {
|
||||
maxBuffer: 1048576
|
||||
}, function(err, stdout) {
|
||||
var command = [
|
||||
uglifyjs + " --self -cm --wrap SpiderUglify -o spidermonkey",
|
||||
uglifyjs + " -p spidermonkey -cm",
|
||||
].join(" | ");
|
||||
exec(command, { maxBuffer: 1048576 }, function(err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
eval(stdout);
|
||||
assert.strictEqual(typeof SpiderUglify, "object");
|
||||
var result = SpiderUglify.minify("foo([true,,2+3]);");
|
||||
assert.strictEqual(result.error, undefined);
|
||||
assert.strictEqual(result.code, "foo([!0,,5]);");
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("Should not add unnecessary escape slashes to regexps", function() {
|
||||
it("Should not add unnecessary escape slashes to RegExp", function() {
|
||||
var input = "/[\\\\/]/;";
|
||||
var ast = UglifyJS.parse(input).to_mozilla_ast();
|
||||
assert.equal(
|
||||
UglifyJS.AST_Node.from_mozilla_ast(ast).print_to_string(),
|
||||
input
|
||||
);
|
||||
assert.strictEqual(UglifyJS.AST_Node.from_mozilla_ast(ast).print_to_string(), input);
|
||||
});
|
||||
|
||||
it("Should judge between directives and strings correctly on import", function() {
|
||||
|
||||
@@ -12,7 +12,7 @@ describe("String literals", function() {
|
||||
'"\u2029"',
|
||||
].forEach(function(input) {
|
||||
assert.throws(function() {
|
||||
var ast = UglifyJS.parse(input);
|
||||
UglifyJS.parse(input);
|
||||
}, function(e) {
|
||||
return e instanceof UglifyJS.JS_Parse_Error
|
||||
&& e.message === "Unterminated string constant";
|
||||
@@ -44,7 +44,7 @@ describe("String literals", function() {
|
||||
'"use strict";\n"\\011"',
|
||||
].forEach(function(input) {
|
||||
assert.throws(function() {
|
||||
var output = UglifyJS.parse(input);
|
||||
UglifyJS.parse(input);
|
||||
}, function(e) {
|
||||
return e instanceof UglifyJS.JS_Parse_Error
|
||||
&& e.message === "Legacy octal escape sequences are not allowed in strict mode";
|
||||
|
||||
@@ -34,20 +34,20 @@ describe("Template literals", function() {
|
||||
[
|
||||
// native line breaks
|
||||
[ "`foo\nbar`", "`foo\nbar`" ],
|
||||
[ "`foo\rbar`", "`foo\rbar`" ],
|
||||
[ "`foo\rbar`", "`foo\nbar`" ],
|
||||
[ "`foo\r\nbar`", "`foo\nbar`" ],
|
||||
[ "`foo\r\n\rbar`", "`foo\n\rbar`" ],
|
||||
[ "`foo\r\n\rbar`", "`foo\n\nbar`" ],
|
||||
// escaped line breaks
|
||||
[ "`foo\\nbar`", "`foo\\nbar`" ],
|
||||
[ "`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`" ],
|
||||
// continuation
|
||||
[ "`foo\\\nbar`", "`foo\\\nbar`" ],
|
||||
[ "`foo\\\rbar`", "`foo\\\rbar`" ],
|
||||
[ "`foo\\\rbar`", "`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\\\\rbar`", "`foo\\\\rbar`" ],
|
||||
[ "`foo\\\\r\nbar`", "`foo\\\\r\nbar`" ],
|
||||
|
||||
@@ -215,9 +215,9 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
||||
// hoist and return expressions from the IIFE function expression
|
||||
var seq = [];
|
||||
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)) {
|
||||
// collect expressions from each statements' body
|
||||
// collect expressions from each statement's body
|
||||
seq.push(expr);
|
||||
}
|
||||
});
|
||||
@@ -395,7 +395,7 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
||||
var expr = [
|
||||
node.expression, // switch expression
|
||||
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 += step;
|
||||
if (expr && (!(expr instanceof U.AST_Statement) || !has_loopcontrol(expr, node, parent))) {
|
||||
|
||||
@@ -28,7 +28,7 @@ exports.run_code = semver.satisfies(process.version, "0.8") ? function(code, top
|
||||
if ([
|
||||
/\basync[ \t]*\([\s\S]*?\)[ \t]*=>/,
|
||||
/\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) {
|
||||
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) {
|
||||
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.length == 1) return "0, " + header;
|
||||
return header.slice(0, -1) + " _" + ++count + header.slice(-1);
|
||||
}).replace(/\bimport\.meta\b/g, function() {
|
||||
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 (!/^[{*]/.test(symbols)) symbols = "default:" + symbols;
|
||||
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);
|
||||
// for Node.js v8+
|
||||
if (global.toString !== Object.prototype.toString) {
|
||||
global.__proto__ = Object.defineProperty(Object.create(global.__proto__), "toString", {
|
||||
value: function() {
|
||||
return "[object global]";
|
||||
},
|
||||
});
|
||||
}
|
||||
global.__proto__ = Object.defineProperty(Object.create(global.__proto__), "toString", {
|
||||
value: function() {
|
||||
return "[object global]";
|
||||
},
|
||||
});
|
||||
|
||||
function self() {
|
||||
return this;
|
||||
@@ -278,11 +276,11 @@ function run_code_exec(code, toplevel, timeout) {
|
||||
timeout: timeout || 5000,
|
||||
});
|
||||
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)) {
|
||||
return new Error("Script execution timed out.");
|
||||
}
|
||||
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 details;
|
||||
if (end >= 0) {
|
||||
|
||||
@@ -334,6 +334,7 @@ var VAR_NAMES = [
|
||||
"arguments",
|
||||
"async",
|
||||
"await",
|
||||
"let",
|
||||
"yield",
|
||||
];
|
||||
var INITIAL_NAMES_LEN = VAR_NAMES.length;
|
||||
@@ -352,7 +353,7 @@ var TYPEOF_OUTCOMES = [
|
||||
];
|
||||
|
||||
var avoid_vars = [];
|
||||
var block_vars = [];
|
||||
var block_vars = [ "let" ];
|
||||
var lambda_vars = [];
|
||||
var unique_vars = [];
|
||||
var classes = [];
|
||||
@@ -399,7 +400,7 @@ function mayDefer(code) {
|
||||
|
||||
function createTopLevelCode() {
|
||||
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;
|
||||
unique_vars.length = 0;
|
||||
classes.length = 0;
|
||||
@@ -2027,6 +2028,7 @@ function removeAvoidVar(name) {
|
||||
function isBannedKeyword(name) {
|
||||
switch (name) {
|
||||
case "arguments":
|
||||
case "let":
|
||||
return in_class;
|
||||
case "await":
|
||||
return async !== false;
|
||||
@@ -2078,8 +2080,8 @@ if (require.main !== module) {
|
||||
return;
|
||||
}
|
||||
|
||||
function run_code(code, toplevel) {
|
||||
return sandbox.run_code(sandbox.patch_module_statements(code), toplevel);
|
||||
function run_code(code, toplevel, timeout) {
|
||||
return sandbox.run_code(sandbox.patch_module_statements(code), toplevel, timeout);
|
||||
}
|
||||
|
||||
function writeln(stream, msg) {
|
||||
@@ -2350,7 +2352,7 @@ function patch_try_catch(orig, toplevel) {
|
||||
tries: [],
|
||||
} ];
|
||||
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) {
|
||||
var code = stack[0].code;
|
||||
var offset = stack[0].offset;
|
||||
|
||||
Reference in New Issue
Block a user