Compare commits
50 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c8d10b7cde | ||
|
|
7caab39e26 | ||
|
|
eff45eac0e | ||
|
|
1e787c556b | ||
|
|
df47632ecc | ||
|
|
eb08fed120 | ||
|
|
8b0c836515 | ||
|
|
5d4e6e3bdc | ||
|
|
d2a45ba441 | ||
|
|
de376c3d33 | ||
|
|
4a19575e74 | ||
|
|
e0695ef549 | ||
|
|
d6152e6a76 | ||
|
|
d930c705f6 | ||
|
|
254937754c | ||
|
|
ae4dbcb5b9 | ||
|
|
e13615549e | ||
|
|
a7698f8845 | ||
|
|
bbed9b13b1 | ||
|
|
2cff7c94e8 | ||
|
|
7576048118 | ||
|
|
3c1898fd65 | ||
|
|
e04429350f | ||
|
|
60f3b55156 | ||
|
|
689f8f504d | ||
|
|
ae51f76ba7 | ||
|
|
7eef86ed05 | ||
|
|
b1cfa71131 | ||
|
|
7b8570f16c | ||
|
|
bb225367cb | ||
|
|
bbca9de9cd | ||
|
|
ee9ceb79ca | ||
|
|
ac1f7d689b | ||
|
|
19d232badb | ||
|
|
d464be3f3f | ||
|
|
3094eaaa89 | ||
|
|
ce3c35fa8b | ||
|
|
5d9224deb8 | ||
|
|
45b6d23d36 | ||
|
|
f0de9a8b5d | ||
|
|
203f4b7ad9 | ||
|
|
4114431eec | ||
|
|
fb03561799 | ||
|
|
6ab26eef6c | ||
|
|
53b57ee57e | ||
|
|
16411dcb87 | ||
|
|
8bbfaacdae | ||
|
|
df980db4a8 | ||
|
|
8e4a19ffec | ||
|
|
d833e66d23 |
2
.github/workflows/ufuzz.yml
vendored
2
.github/workflows/ufuzz.yml
vendored
@@ -2,7 +2,7 @@ name: Fuzzing
|
||||
on:
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: '*/5 * * * *'
|
||||
- cron: '*/15 * * * *'
|
||||
env:
|
||||
BASE_URL: https://api.github.com/repos/${{ github.repository }}
|
||||
CAUSE: ${{ github.event_name }}
|
||||
|
||||
27
README.md
27
README.md
@@ -1327,3 +1327,30 @@ To allow for better optimizations, the compiler makes various assumptions:
|
||||
// SyntaxError: The left-hand side of a for-of loop may not be 'async'.
|
||||
```
|
||||
UglifyJS may modify the input which in turn may suppress those errors.
|
||||
- Later versions of Chrome and Node.js will give incorrect results with the
|
||||
following:
|
||||
```javascript
|
||||
console.log({
|
||||
...console,
|
||||
get 42() {
|
||||
return "FAIL";
|
||||
},
|
||||
[42]: "PASS",
|
||||
}[42]);
|
||||
// Expected: "PASS"
|
||||
// Actual: "FAIL"
|
||||
```
|
||||
UglifyJS may modify the input which in turn may suppress those errors.
|
||||
- Earlier versions of JavaScript will throw `TypeError` with the following:
|
||||
```javascript
|
||||
(function() {
|
||||
{
|
||||
const a = "foo";
|
||||
}
|
||||
{
|
||||
const a = "bar";
|
||||
}
|
||||
})();
|
||||
// TypeError: const 'a' has already been declared
|
||||
```
|
||||
UglifyJS may modify the input which in turn may suppress those errors.
|
||||
|
||||
24
lib/ast.js
24
lib/ast.js
@@ -261,9 +261,9 @@ var AST_BlockScope = DEFNODE("BlockScope", "enclosed functions make_def parent_s
|
||||
$documentation: "Base class for all statements introducing a lexical scope",
|
||||
$propdoc: {
|
||||
enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes",
|
||||
functions: "[Object/S] like `variables`, but only lists function declarations",
|
||||
functions: "[Dictionary/S] like `variables`, but only lists function declarations",
|
||||
parent_scope: "[AST_Scope?/S] link to the parent scope",
|
||||
variables: "[Object/S] a map of name ---> SymbolDef for all variables/functions defined in this scope",
|
||||
variables: "[Dictionary/S] a map of name ---> SymbolDef for all variables/functions defined in this scope",
|
||||
},
|
||||
clone: function(deep) {
|
||||
var node = this._clone(deep);
|
||||
@@ -506,7 +506,7 @@ var AST_Scope = DEFNODE("Scope", "uses_eval uses_with", {
|
||||
var AST_Toplevel = DEFNODE("Toplevel", "globals", {
|
||||
$documentation: "The toplevel scope",
|
||||
$propdoc: {
|
||||
globals: "[Object/S] a map of name ---> SymbolDef for all undeclared names",
|
||||
globals: "[Dictionary/S] a map of name ---> SymbolDef for all undeclared names",
|
||||
},
|
||||
wrap: function(name) {
|
||||
var body = this.body;
|
||||
@@ -1293,11 +1293,13 @@ function must_be_expressions(node, prop, allow_spread, allow_hole) {
|
||||
});
|
||||
}
|
||||
|
||||
var AST_Call = DEFNODE("Call", "expression args pure", {
|
||||
var AST_Call = DEFNODE("Call", "args expression optional pure", {
|
||||
$documentation: "A function call expression",
|
||||
$propdoc: {
|
||||
args: "[AST_Node*] array of arguments",
|
||||
expression: "[AST_Node] expression to invoke as function",
|
||||
args: "[AST_Node*] array of arguments"
|
||||
optional: "[boolean] whether the expression is optional chaining",
|
||||
pure: "[string/S] marker for side-effect-free call expression",
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
@@ -1315,7 +1317,10 @@ var AST_Call = DEFNODE("Call", "expression args pure", {
|
||||
});
|
||||
|
||||
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() {
|
||||
if (this.optional) throw new Error("optional must be false");
|
||||
},
|
||||
}, AST_Call);
|
||||
|
||||
var AST_Sequence = DEFNODE("Sequence", "expressions", {
|
||||
@@ -1337,11 +1342,12 @@ var AST_Sequence = DEFNODE("Sequence", "expressions", {
|
||||
},
|
||||
});
|
||||
|
||||
var AST_PropAccess = DEFNODE("PropAccess", "expression property", {
|
||||
var AST_PropAccess = DEFNODE("PropAccess", "expression optional property", {
|
||||
$documentation: "Base class for property access expressions, i.e. `a.foo` or `a[\"foo\"]`",
|
||||
$propdoc: {
|
||||
expression: "[AST_Node] the “container” expression",
|
||||
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"
|
||||
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",
|
||||
},
|
||||
getProperty: function() {
|
||||
var p = this.property;
|
||||
@@ -1686,7 +1692,7 @@ var AST_ObjectMethod = DEFNODE("ObjectMethod", null, {
|
||||
_validate: function() {
|
||||
if (!(this.value instanceof AST_LambdaExpression)) throw new Error("value must be AST_LambdaExpression");
|
||||
if (is_arrow(this.value)) throw new Error("value cannot be AST_Arrow or AST_AsyncArrow");
|
||||
if (this.value.name != null) throw new Error("name of class method's lambda must be null");
|
||||
if (this.value.name != null) throw new Error("name of object method's lambda must be null");
|
||||
},
|
||||
}, AST_ObjectKeyVal);
|
||||
|
||||
|
||||
602
lib/compress.js
602
lib/compress.js
File diff suppressed because it is too large
Load Diff
@@ -274,6 +274,7 @@
|
||||
return new (M.computed ? AST_Sub : AST_Dot)({
|
||||
start: my_start_token(M),
|
||||
end: my_end_token(M),
|
||||
optional: M.optional,
|
||||
expression: from_moz(M.object),
|
||||
property: M.computed ? from_moz(M.property) : M.property.name,
|
||||
});
|
||||
@@ -554,6 +555,9 @@
|
||||
node.end.parens.push(my_end_token(M));
|
||||
return node;
|
||||
},
|
||||
ChainExpression: function(M) {
|
||||
return from_moz(M.expression);
|
||||
},
|
||||
};
|
||||
|
||||
MOZ_TO_ME.UpdateExpression =
|
||||
@@ -593,7 +597,7 @@
|
||||
map("AssignmentPattern", AST_DefaultValue, "left>name, right>value");
|
||||
map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative");
|
||||
map("NewExpression", AST_New, "callee>expression, arguments@args, pure=pure");
|
||||
map("CallExpression", AST_Call, "callee>expression, arguments@args, pure=pure");
|
||||
map("CallExpression", AST_Call, "callee>expression, arguments@args, optional=optional, pure=pure");
|
||||
map("SequenceExpression", AST_Sequence, "expressions@expressions");
|
||||
map("SpreadElement", AST_Spread, "argument>expression");
|
||||
map("ObjectExpression", AST_Object, "properties@properties");
|
||||
@@ -868,6 +872,7 @@
|
||||
type: "MemberExpression",
|
||||
object: to_moz(M.expression),
|
||||
computed: computed,
|
||||
optional: M.optional,
|
||||
property: computed ? to_moz(M.property) : {
|
||||
type: "Identifier",
|
||||
name: M.property,
|
||||
|
||||
@@ -709,6 +709,8 @@ function OutputStream(options) {
|
||||
// (x++)[y]
|
||||
// (typeof x).y
|
||||
if (p instanceof AST_PropAccess) return p.expression === this;
|
||||
// (~x)`foo`
|
||||
if (p instanceof AST_Template) return p.tag === this;
|
||||
}
|
||||
PARENS(AST_Await, needs_parens_unary);
|
||||
PARENS(AST_Unary, needs_parens_unary);
|
||||
@@ -782,14 +784,29 @@ function OutputStream(options) {
|
||||
if (p instanceof AST_Class) return true;
|
||||
// (foo && bar)["prop"], (foo && bar).prop
|
||||
if (p instanceof AST_PropAccess) return p.expression === this;
|
||||
// (foo && bar)``
|
||||
if (p instanceof AST_Template) return p.tag === this;
|
||||
// typeof (foo && bar)
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
PARENS(AST_PropAccess, function(output) {
|
||||
var node = this;
|
||||
var p = output.parent();
|
||||
if (p instanceof AST_New && p.expression === node) {
|
||||
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
|
||||
@@ -801,20 +818,22 @@ function OutputStream(options) {
|
||||
} while (node instanceof AST_PropAccess);
|
||||
return node.TYPE == "Call";
|
||||
}
|
||||
return lhs_has_optional(node, output);
|
||||
});
|
||||
|
||||
PARENS(AST_Call, function(output) {
|
||||
var node = this;
|
||||
var p = output.parent();
|
||||
if (p instanceof AST_New) return p.expression === this;
|
||||
if (p instanceof AST_New) return p.expression === node;
|
||||
// https://bugs.webkit.org/show_bug.cgi?id=123506
|
||||
if (output.option("webkit")) {
|
||||
if (output.option("webkit")
|
||||
&& node.expression instanceof AST_Function
|
||||
&& p instanceof AST_PropAccess
|
||||
&& p.expression === node) {
|
||||
var g = output.parent(1);
|
||||
return this.expression instanceof AST_Function
|
||||
&& p instanceof AST_PropAccess
|
||||
&& p.expression === this
|
||||
&& g instanceof AST_Assign
|
||||
&& g.left === p;
|
||||
if (g instanceof AST_Assign && g.left === p) return true;
|
||||
}
|
||||
return lhs_has_optional(node, output);
|
||||
});
|
||||
|
||||
PARENS(AST_New, function(output) {
|
||||
@@ -1473,6 +1492,7 @@ function OutputStream(options) {
|
||||
var self = this;
|
||||
print_annotation(self, output);
|
||||
self.expression.print(output);
|
||||
if (self.optional) output.print("?.");
|
||||
print_call_args(self, output);
|
||||
});
|
||||
DEFPRINT(AST_New, function(output) {
|
||||
@@ -1501,22 +1521,23 @@ function OutputStream(options) {
|
||||
expr.print(output);
|
||||
var prop = self.property;
|
||||
if (output.option("ie8") && RESERVED_WORDS[prop]) {
|
||||
output.print("[");
|
||||
output.print(self.optional ? "?.[" : "[");
|
||||
output.add_mapping(self.end);
|
||||
output.print_string(prop);
|
||||
output.print("]");
|
||||
} else {
|
||||
if (expr instanceof AST_Number && !/[ex.)]/i.test(output.last())) output.print(".");
|
||||
output.print(".");
|
||||
output.print(self.optional ? "?." : ".");
|
||||
// the name after dot would be mapped about here.
|
||||
output.add_mapping(self.end);
|
||||
output.print_name(prop);
|
||||
}
|
||||
});
|
||||
DEFPRINT(AST_Sub, function(output) {
|
||||
this.expression.print(output);
|
||||
output.print("[");
|
||||
this.property.print(output);
|
||||
var self = this;
|
||||
self.expression.print(output);
|
||||
output.print(self.optional ? "?.[" : "[");
|
||||
self.property.print(output);
|
||||
output.print("]");
|
||||
});
|
||||
DEFPRINT(AST_Spread, function(output) {
|
||||
@@ -1914,7 +1935,11 @@ function OutputStream(options) {
|
||||
output.add_mapping(this.start);
|
||||
});
|
||||
|
||||
DEFMAP([ AST_DestructuredKeyVal, AST_ObjectProperty ], function(output) {
|
||||
DEFMAP([
|
||||
AST_ClassProperty,
|
||||
AST_DestructuredKeyVal,
|
||||
AST_ObjectProperty,
|
||||
], function(output) {
|
||||
if (typeof this.key == "string") output.add_mapping(this.start, this.key);
|
||||
});
|
||||
})();
|
||||
|
||||
54
lib/parse.js
54
lib/parse.js
@@ -124,7 +124,7 @@ var PUNC_AFTER_EXPRESSION = PUNC_SEPARATORS + PUNC_CLOSERS;
|
||||
var PUNC_BEFORE_EXPRESSION = PUNC_OPENERS + PUNC_SEPARATORS;
|
||||
var PUNC_CHARS = PUNC_BEFORE_EXPRESSION + "`" + PUNC_CLOSERS;
|
||||
var WHITESPACE_CHARS = NEWLINE_CHARS + " \u00a0\t\f\u000b\u200b\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\uFEFF";
|
||||
var NON_IDENTIFIER_CHARS = makePredicate(characters("./'\"" + OPERATOR_CHARS + PUNC_CHARS + WHITESPACE_CHARS));
|
||||
var NON_IDENTIFIER_CHARS = makePredicate(characters("./'\"#" + OPERATOR_CHARS + PUNC_CHARS + WHITESPACE_CHARS));
|
||||
|
||||
NEWLINE_CHARS = makePredicate(characters(NEWLINE_CHARS));
|
||||
OPERATOR_CHARS = makePredicate(characters(OPERATOR_CHARS));
|
||||
@@ -468,7 +468,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
});
|
||||
|
||||
function read_name() {
|
||||
var backslash = false, name = "", ch, escaped = false, hex;
|
||||
var backslash = false, ch, escaped = false, name = peek() == "#" ? next() : "";
|
||||
while (ch = peek()) {
|
||||
if (!backslash) {
|
||||
if (ch == "\\") escaped = backslash = true, next();
|
||||
@@ -483,7 +483,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
}
|
||||
}
|
||||
if (KEYWORDS[name] && escaped) {
|
||||
hex = name.charCodeAt(0).toString(16).toUpperCase();
|
||||
var hex = name.charCodeAt(0).toString(16).toUpperCase();
|
||||
name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1);
|
||||
}
|
||||
return name;
|
||||
@@ -618,7 +618,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
if (PUNC_CHARS[ch]) return token("punc", next());
|
||||
if (looking_at("=>")) return token("punc", next() + next());
|
||||
if (OPERATOR_CHARS[ch]) return read_operator();
|
||||
if (code == 92 || !NON_IDENTIFIER_CHARS[ch]) return read_word();
|
||||
if (code == 35 || code == 92 || !NON_IDENTIFIER_CHARS[ch]) return read_word();
|
||||
break;
|
||||
}
|
||||
parse_error("Unexpected character '" + ch + "'");
|
||||
@@ -2245,44 +2245,52 @@ function parse($TEXT, options) {
|
||||
});
|
||||
}
|
||||
|
||||
var subscripts = function(expr, allow_calls) {
|
||||
var subscripts = function(expr, allow_calls, optional) {
|
||||
var start = expr.start;
|
||||
if (is("punc", ".")) {
|
||||
next();
|
||||
return subscripts(new AST_Dot({
|
||||
start : start,
|
||||
expression : expr,
|
||||
property : as_name(),
|
||||
end : prev()
|
||||
}), allow_calls);
|
||||
}
|
||||
if (is("punc", "[")) {
|
||||
next();
|
||||
var prop = expression();
|
||||
expect("]");
|
||||
return subscripts(new AST_Sub({
|
||||
start : start,
|
||||
expression : expr,
|
||||
property : prop,
|
||||
end : prev()
|
||||
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,
|
||||
expression : expr,
|
||||
args : expr_list(")", !options.strict),
|
||||
end : prev()
|
||||
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);
|
||||
}
|
||||
if (expr instanceof AST_Call && !expr.pure) {
|
||||
var start = expr.start;
|
||||
var comments = start.comments_before;
|
||||
@@ -2405,7 +2413,7 @@ function parse($TEXT, options) {
|
||||
};
|
||||
|
||||
function is_assignable(expr) {
|
||||
return expr instanceof AST_PropAccess || expr instanceof AST_SymbolRef;
|
||||
return expr instanceof AST_PropAccess && !expr.optional || expr instanceof AST_SymbolRef;
|
||||
}
|
||||
|
||||
function to_destructured(node) {
|
||||
|
||||
27
lib/scope.js
27
lib/scope.js
@@ -80,15 +80,16 @@ SymbolDef.prototype = {
|
||||
}
|
||||
},
|
||||
redefined: function() {
|
||||
var scope = this.defun;
|
||||
var self = this;
|
||||
var scope = self.defun;
|
||||
if (!scope) return;
|
||||
var name = this.name;
|
||||
var name = self.name;
|
||||
var def = scope.variables.get(name)
|
||||
|| scope instanceof AST_Toplevel && scope.globals.get(name)
|
||||
|| this.orig[0] instanceof AST_SymbolConst && find_if(function(def) {
|
||||
|| self.orig[0] instanceof AST_SymbolConst && find_if(function(def) {
|
||||
return def.name == name;
|
||||
}, scope.enclosed);
|
||||
if (def && def !== this) return def.redefined() || def;
|
||||
if (def && def !== self) return def.redefined() || def;
|
||||
},
|
||||
unmangleable: function(options) {
|
||||
return this.global && !options.toplevel
|
||||
@@ -396,13 +397,14 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
||||
} else {
|
||||
new_def = scope.def_variable(node);
|
||||
}
|
||||
if (new_def.undeclared) self.variables.set(name, new_def);
|
||||
if (name == "arguments" && is_arguments(old_def) && node instanceof AST_SymbolLambda) return true;
|
||||
old_def.defun = new_def.scope;
|
||||
old_def.forEach(function(node) {
|
||||
node.redef = old_def;
|
||||
node.thedef = new_def;
|
||||
node.reference(options);
|
||||
});
|
||||
if (new_def.undeclared) self.variables.set(name, new_def);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
@@ -800,6 +802,7 @@ var base54 = (function() {
|
||||
var leading = init("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_");
|
||||
var chars, frequency;
|
||||
function reset() {
|
||||
chars = null;
|
||||
frequency = Object.create(freq);
|
||||
}
|
||||
base54.consider = function(str, delta) {
|
||||
@@ -811,19 +814,15 @@ var base54 = (function() {
|
||||
return frequency[b] - frequency[a];
|
||||
}
|
||||
base54.sort = function() {
|
||||
chars = leading.sort(compare).concat(digits.sort(compare));
|
||||
chars = leading.sort(compare).concat(digits).sort(compare);
|
||||
};
|
||||
base54.reset = reset;
|
||||
reset();
|
||||
function base54(num) {
|
||||
var ret = "", base = 54;
|
||||
num++;
|
||||
do {
|
||||
num--;
|
||||
ret += chars[num % base];
|
||||
num = Math.floor(num / base);
|
||||
base = 64;
|
||||
} while (num > 0);
|
||||
var ret = leading[num % 54];
|
||||
for (num = Math.floor(num / 54); --num >= 0; num >>= 6) {
|
||||
ret += chars[num & 0x3F];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return base54;
|
||||
|
||||
@@ -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.13.5",
|
||||
"version": "3.13.8",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
|
||||
@@ -701,3 +701,48 @@ issue_4876: {
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=15"
|
||||
}
|
||||
|
||||
issue_4924_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a, b;
|
||||
console.log("PASS");
|
||||
a = function() {};
|
||||
b = function() {}(b ||= a);
|
||||
}
|
||||
expect: {
|
||||
var b;
|
||||
console.log("PASS");
|
||||
b = void (b ||= function() {});
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=15"
|
||||
}
|
||||
|
||||
issue_4924_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
dead_code: true,
|
||||
passes: 2,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a, b;
|
||||
console.log("PASS");
|
||||
a = function() {};
|
||||
b = function() {}(b ||= a);
|
||||
}
|
||||
expect: {
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=15"
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ fields: {
|
||||
console.log(k, o[k]);
|
||||
console.log(o.q);
|
||||
}
|
||||
expect_exact: 'var o=new class A{"#p";static #p="PASS";async;get q(){return A.#p}[6*7]=console?"foo":"bar"};for(var k in o)console.log(k,o[k]);console.log(o.q);'
|
||||
expect_exact: 'var o=new class A{"#p";static#p="PASS";async;get q(){return A.#p}[6*7]=console?"foo":"bar"};for(var k in o)console.log(k,o[k]);console.log(o.q);'
|
||||
expect_stdout: [
|
||||
"42 foo",
|
||||
"#p undefined",
|
||||
@@ -136,7 +136,7 @@ private_methods: {
|
||||
}
|
||||
}().q.then(console.log);
|
||||
}
|
||||
expect_exact: "(new class A{static*#f(){yield 3*A.#p}async #g(){for(var a of A.#f())return a*await 2}static get #p(){return 7}get q(){return this.#g()}}).q.then(console.log);"
|
||||
expect_exact: "(new class A{static*#f(){yield 3*A.#p}async#g(){for(var a of A.#f())return a*await 2}static get#p(){return 7}get q(){return this.#g()}}).q.then(console.log);"
|
||||
expect_stdout: "42"
|
||||
node_version: ">=14.6"
|
||||
}
|
||||
@@ -1563,3 +1563,83 @@ drop_unused_self_reference: {
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
issue_4951_1: {
|
||||
input: {
|
||||
class A {
|
||||
static#p = console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect_exact: 'class A{static#p=console.log("PASS")}'
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=12"
|
||||
}
|
||||
|
||||
issue_4951_2: {
|
||||
input: {
|
||||
new class {
|
||||
constructor() {
|
||||
this.#f().then(console.log);
|
||||
}
|
||||
async#f() {
|
||||
return await "PASS";
|
||||
}
|
||||
}();
|
||||
}
|
||||
expect_exact: 'new class{constructor(){this.#f().then(console.log)}async#f(){return await"PASS"}};'
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=14.6"
|
||||
}
|
||||
|
||||
issue_4962_1: {
|
||||
options = {
|
||||
ie8: true,
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
function f() {
|
||||
while (console.log(typeof g));
|
||||
}
|
||||
class A {
|
||||
static p = f();
|
||||
}
|
||||
})(function g() {});
|
||||
}
|
||||
expect: {
|
||||
(function g() {}),
|
||||
void function() {
|
||||
while (console.log(typeof g));
|
||||
}();
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
node_version: ">=12"
|
||||
}
|
||||
|
||||
issue_4962_2: {
|
||||
options = {
|
||||
ie8: true,
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function f() {}(function g() {
|
||||
function h() {
|
||||
f;
|
||||
}
|
||||
class A {
|
||||
static p = h();
|
||||
}
|
||||
}, typeof g));
|
||||
}
|
||||
expect: {
|
||||
console.log(function f() {}(function g() {
|
||||
f;
|
||||
}));
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
node_version: ">=12"
|
||||
}
|
||||
|
||||
@@ -4724,7 +4724,7 @@ cascade_statement: {
|
||||
}
|
||||
function f3(a, b) {
|
||||
for (; a < b; a++)
|
||||
if ((c = a) && b)
|
||||
if (c = a, a && b)
|
||||
var c = c = b(a);
|
||||
}
|
||||
}
|
||||
@@ -8560,7 +8560,7 @@ issue_4047_1: {
|
||||
expect: {
|
||||
var b = 1;
|
||||
var a;
|
||||
console.log((a = --b + ((a = 0) !== typeof A), +void ((a >>= 0) && console.log("PASS"))));
|
||||
console.log((a = --b + (0 !== typeof A), +void ((a >>= 0) && console.log("PASS"))));
|
||||
}
|
||||
expect_stdout: [
|
||||
"PASS",
|
||||
@@ -9057,3 +9057,225 @@ issue_4874: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4891: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0, b;
|
||||
a++;
|
||||
console.log(b = a, b);
|
||||
b--;
|
||||
a.a += 0;
|
||||
console.log(b);
|
||||
}
|
||||
expect: {
|
||||
var a = 0, b;
|
||||
a++;
|
||||
console.log(a, b = a);
|
||||
b--;
|
||||
a.a += 0;
|
||||
console.log(b);
|
||||
}
|
||||
expect_stdout: [
|
||||
"1 1",
|
||||
"0",
|
||||
]
|
||||
}
|
||||
|
||||
issue_4895: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a, b;
|
||||
(function f() {
|
||||
a = 42;
|
||||
})();
|
||||
console.log((b = a) || b, b += 0);
|
||||
}
|
||||
expect: {
|
||||
var a, b;
|
||||
(function f() {
|
||||
a = 42;
|
||||
})();
|
||||
console.log((b = a) || b, b += 0);
|
||||
}
|
||||
expect_stdout: "42 42"
|
||||
}
|
||||
|
||||
issue_4908: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
join_vars: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0;
|
||||
var b;
|
||||
console || a++;
|
||||
var c = d = a, d = [ c && c, d += 42 ];
|
||||
console.log(d[1]);
|
||||
}
|
||||
expect: {
|
||||
var a = 0, b;
|
||||
console || a++;
|
||||
var c = a, d = [ (d = a) && d, d += 42 ];
|
||||
console.log(d[1]);
|
||||
}
|
||||
expect_stdout: "42"
|
||||
}
|
||||
|
||||
issue_4910: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = "foo", b;
|
||||
var c = b = a;
|
||||
1 && c[a = "bar"];
|
||||
console.log(a, b);
|
||||
}
|
||||
expect: {
|
||||
var a = "foo", b;
|
||||
var c = b = a;
|
||||
1 && b[a = "bar"];
|
||||
console.log(a, b);
|
||||
}
|
||||
expect_stdout: "bar foo"
|
||||
}
|
||||
|
||||
issue_4914: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
pure_getters: "strict",
|
||||
}
|
||||
input: {
|
||||
console.log(typeof function f() {
|
||||
f.__proto__ = 42;
|
||||
return f.__proto__;
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(typeof function f() {
|
||||
f.__proto__ = 42;
|
||||
return f.__proto__;
|
||||
}());
|
||||
}
|
||||
expect_stdout: "function"
|
||||
}
|
||||
|
||||
issue_4918: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
var a = "FAIL";
|
||||
({
|
||||
get 42() {
|
||||
console.log(a);
|
||||
}
|
||||
}[a = "PASS", 42] += "PASS");
|
||||
}
|
||||
expect: {
|
||||
var a = "FAIL";
|
||||
({
|
||||
get 42() {
|
||||
console.log(a);
|
||||
}
|
||||
}[a = "PASS", 42] += "PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4920: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = "PASS", b;
|
||||
({
|
||||
get PASS() {
|
||||
a = "FAIL";
|
||||
},
|
||||
})[b = a];
|
||||
console.log(b);
|
||||
}
|
||||
expect: {
|
||||
var a = "PASS", b;
|
||||
({
|
||||
get PASS() {
|
||||
a = "FAIL";
|
||||
},
|
||||
})[b = a];
|
||||
console.log(b);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4935: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = 1;
|
||||
var b;
|
||||
var c = b = a;
|
||||
console || c(a++);
|
||||
--b;
|
||||
console.log(a, b);
|
||||
}
|
||||
expect: {
|
||||
var a = 1;
|
||||
var b;
|
||||
var c = b = a;
|
||||
console || a(a++);
|
||||
--b;
|
||||
console.log(a, b);
|
||||
}
|
||||
expect_stdout: "1 0"
|
||||
}
|
||||
|
||||
inline_throw: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
inline: true,
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
try {
|
||||
(function() {
|
||||
return function(a) {
|
||||
return function(b) {
|
||||
throw b;
|
||||
}(a);
|
||||
};
|
||||
})()("PASS");
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
(function(a) {
|
||||
return function() {
|
||||
throw a;
|
||||
}();
|
||||
})("PASS");
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -1535,3 +1535,160 @@ issue_4848: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4954_1: {
|
||||
rename = true
|
||||
input: {
|
||||
"use strict";
|
||||
(function() {
|
||||
{
|
||||
const a = "foo";
|
||||
console.log(a);
|
||||
}
|
||||
{
|
||||
const a = "bar";
|
||||
console.log(a);
|
||||
}
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
(function() {
|
||||
{
|
||||
const a = "foo";
|
||||
console.log(a);
|
||||
}
|
||||
{
|
||||
const b = "bar";
|
||||
console.log(b);
|
||||
}
|
||||
})();
|
||||
}
|
||||
expect_stdout: [
|
||||
"foo",
|
||||
"bar",
|
||||
]
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
issue_4954_2: {
|
||||
mangle = {}
|
||||
input: {
|
||||
"use strict";
|
||||
const a = null;
|
||||
(function(b) {
|
||||
for (const a in null);
|
||||
for (const a in b)
|
||||
console.log("PASS");
|
||||
})([ null ]);
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
const a = null;
|
||||
(function(o) {
|
||||
for (const n in null);
|
||||
for (const n in o)
|
||||
console.log("PASS");
|
||||
})([ null ]);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
issue_4960: {
|
||||
mangle = {}
|
||||
input: {
|
||||
"use strict";
|
||||
var a;
|
||||
(function() {
|
||||
{
|
||||
const a = console.log("PASS");
|
||||
}
|
||||
try {} catch (e) {
|
||||
const a = console.log("FAIL");
|
||||
}
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
var a;
|
||||
(function() {
|
||||
{
|
||||
const o = console.log("PASS");
|
||||
}
|
||||
try {} catch (o) {
|
||||
const c = console.log("FAIL");
|
||||
}
|
||||
})();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
issue_4965_1: {
|
||||
mangle = {}
|
||||
input: {
|
||||
"use strict";
|
||||
try {
|
||||
c;
|
||||
} catch (a) {
|
||||
{
|
||||
const a = 1;
|
||||
}
|
||||
{
|
||||
const a = console.log(typeof c);
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
try {
|
||||
c;
|
||||
} catch (t) {
|
||||
{
|
||||
const c = 1;
|
||||
}
|
||||
{
|
||||
const t = console.log(typeof c);
|
||||
}
|
||||
}
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
issue_4965_2: {
|
||||
mangle = {}
|
||||
input: {
|
||||
"use strict";
|
||||
try {
|
||||
throw 1;
|
||||
} catch (e) {
|
||||
try {
|
||||
{
|
||||
const e = 2;
|
||||
}
|
||||
} finally {
|
||||
const e = 3;
|
||||
console.log(typeof t);
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
try {
|
||||
throw 1;
|
||||
} catch (o) {
|
||||
try {
|
||||
{
|
||||
const t = 2;
|
||||
}
|
||||
} finally {
|
||||
const o = 3;
|
||||
console.log(typeof t);
|
||||
}
|
||||
}
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
@@ -1703,3 +1703,29 @@ issue_4854: {
|
||||
expect_stdout: "undefined"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_4916: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
var log = console.log;
|
||||
(function(b = "foo") {
|
||||
b.value = "FAIL";
|
||||
b;
|
||||
log(b.value);
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
var log = console.log;
|
||||
(function(b = "foo") {
|
||||
b.value = "FAIL";
|
||||
b;
|
||||
log(b.value);
|
||||
})();
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
@@ -2382,7 +2382,7 @@ issue_3664: {
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
var b = (b && console.log("FAIL"), 0, 0);
|
||||
var a, b = (a = (a = [ b && console.log("FAIL") ]).p = 0, 0);
|
||||
return "PASS";
|
||||
}());
|
||||
}
|
||||
@@ -3080,11 +3080,9 @@ issue_4235: {
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
f = console.log(f),
|
||||
void 0;
|
||||
var f;
|
||||
})();
|
||||
void function() {
|
||||
var f = console.log(f);
|
||||
}();
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
@@ -3388,3 +3386,85 @@ issue_4834: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4912_1: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = A = function() {};
|
||||
A;
|
||||
a.prototype = {
|
||||
f: function() {
|
||||
console.log("PASS");
|
||||
},
|
||||
};
|
||||
new A().f();
|
||||
}
|
||||
expect: {
|
||||
var a = A = function() {};
|
||||
A;
|
||||
a.prototype = {
|
||||
f: function() {
|
||||
console.log("PASS");
|
||||
},
|
||||
};
|
||||
new A().f();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4912_2: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var g, f = function() {};
|
||||
f.p = {};
|
||||
(g = f.p.q = function() {}).r = "PASS";
|
||||
return f;
|
||||
}().p.q.r);
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
var g, f = function() {};
|
||||
f.p = {};
|
||||
(f.p.q = function() {}).r = "PASS";
|
||||
return f;
|
||||
}().p.q.r);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4912_3: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(f, g) {
|
||||
f = function() {};
|
||||
f.p = {};
|
||||
g = f.p.q = function() {};
|
||||
g.r = "PASS";
|
||||
return f;
|
||||
}().p.q.r);
|
||||
}
|
||||
expect: {
|
||||
console.log(function(f, g) {
|
||||
f = function() {};
|
||||
f.p = {};
|
||||
g = f.p.q = function() {};
|
||||
g.r = "PASS";
|
||||
return f;
|
||||
}().p.q.r);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -3181,3 +3181,23 @@ issue_4552: {
|
||||
}
|
||||
expect_stdout: "NaN"
|
||||
}
|
||||
|
||||
issue_4886: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log("length" in {
|
||||
__proto__: function() {},
|
||||
length: void 0,
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
console.log("length" in {
|
||||
__proto__: function() {},
|
||||
length: void 0,
|
||||
});
|
||||
}
|
||||
expect_stdout: "true"
|
||||
}
|
||||
|
||||
@@ -6013,7 +6013,7 @@ issue_4823: {
|
||||
console.log(typeof function() {
|
||||
{
|
||||
function f() {}
|
||||
arguments = f();
|
||||
f();
|
||||
var arguments = function() {};
|
||||
}
|
||||
return f && arguments;
|
||||
@@ -6040,3 +6040,171 @@ drop_unused_self_reference: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
reduce_cross_reference_1: {
|
||||
options = {
|
||||
passes: 3,
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function(a, b) {
|
||||
a = b = function() {};
|
||||
a.p = a;
|
||||
b = a = function() {};
|
||||
b.q = b;
|
||||
})();
|
||||
}
|
||||
expect: {}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
reduce_cross_reference_1_toplevel: {
|
||||
options = {
|
||||
passes: 2,
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = b = function() {};
|
||||
a.p = a;
|
||||
var b = a = function() {};
|
||||
b.q = b;
|
||||
}
|
||||
expect: {}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
reduce_cross_reference_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
passes: 3,
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function(a, b) {
|
||||
a = b = function() {};
|
||||
b.p = a;
|
||||
b = a = function() {};
|
||||
a.q = b;
|
||||
})();
|
||||
}
|
||||
expect: {}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
reduce_cross_reference_2_toplevel: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
passes: 2,
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = b = function() {};
|
||||
b.p = a;
|
||||
var b = a = function() {};
|
||||
a.q = b;
|
||||
}
|
||||
expect: {}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
reduce_cross_reference_3: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
passes: 3,
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function(a, b) {
|
||||
a = b = function() {};
|
||||
a.p = b;
|
||||
b = a = function() {};
|
||||
b.q = a;
|
||||
})();
|
||||
}
|
||||
expect: {}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
reduce_cross_reference_3_toplevel: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
passes: 2,
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = b = function() {};
|
||||
a.p = b;
|
||||
var b = a = function() {};
|
||||
b.q = a;
|
||||
}
|
||||
expect: {}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
reduce_cross_reference_4: {
|
||||
options = {
|
||||
passes: 3,
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function(a, b) {
|
||||
a = b = function() {};
|
||||
b.p = b;
|
||||
b = a = function() {};
|
||||
a.q = a;
|
||||
})();
|
||||
}
|
||||
expect: {}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
reduce_cross_reference_4_toplevel: {
|
||||
options = {
|
||||
passes: 2,
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = b = function() {};
|
||||
b.p = b;
|
||||
var b = a = function() {};
|
||||
a.q = a;
|
||||
}
|
||||
expect: {}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
@@ -294,3 +294,105 @@ issue_4859: {
|
||||
}
|
||||
expect_stdout: "Infinity"
|
||||
}
|
||||
|
||||
issue_4893_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
hoist_vars: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
function g() {}
|
||||
var a = null;
|
||||
var b = null;
|
||||
var c = null;
|
||||
b.p += a = 42;
|
||||
f;
|
||||
}
|
||||
try {
|
||||
f();
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
try{
|
||||
(function f() {
|
||||
var b;
|
||||
b = null;
|
||||
b.p += 42;
|
||||
f;
|
||||
})();
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4893_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
hoist_vars: true,
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
function g() {}
|
||||
var a = null;
|
||||
var b = null;
|
||||
var c = null;
|
||||
b.p += a = 42;
|
||||
f;
|
||||
}
|
||||
try {
|
||||
f();
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
try{
|
||||
(function() {
|
||||
var b;
|
||||
b = null;
|
||||
b.p += 42;
|
||||
})();
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4898: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
hoist_vars: true,
|
||||
loops: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
do {
|
||||
var b = [ console.log("PASS") ];
|
||||
var c = b;
|
||||
} while (c.p = 0);
|
||||
}
|
||||
expect: {
|
||||
var b;
|
||||
b = [ console.log("PASS") ];
|
||||
b.p = 0;
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -2653,7 +2653,9 @@ issue_4019: {
|
||||
try {
|
||||
console.log("FAIL");
|
||||
} catch (o) {}
|
||||
}, o = (console.log(o.length), ++o);
|
||||
};
|
||||
console.log(o.length),
|
||||
++o;
|
||||
}
|
||||
expect_stdout: "0"
|
||||
}
|
||||
@@ -2945,3 +2947,73 @@ issue_4729: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4928_1: {
|
||||
options = {
|
||||
ie8: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = function f() {
|
||||
f(a);
|
||||
};
|
||||
console.log(typeof f);
|
||||
}
|
||||
expect: {
|
||||
var a = function f() {
|
||||
f(a);
|
||||
};
|
||||
console.log(typeof f);
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
issue_4928_2: {
|
||||
options = {
|
||||
ie8: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
switch (42) {
|
||||
case console:
|
||||
var a = function f() {
|
||||
f(a);
|
||||
};
|
||||
case 42:
|
||||
var a = console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
switch (42) {
|
||||
case console:
|
||||
var a = function f() {
|
||||
f(a);
|
||||
};
|
||||
case 42:
|
||||
a = console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4958: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function arguments(a) {
|
||||
a = 21;
|
||||
return arguments[0] + 21;
|
||||
}("FAIL"));
|
||||
}
|
||||
expect: {
|
||||
console.log(function arguments(a) {
|
||||
a = 21;
|
||||
return arguments[0] + 21;
|
||||
}("FAIL"));
|
||||
}
|
||||
expect_stdout: "42"
|
||||
}
|
||||
|
||||
@@ -1024,7 +1024,7 @@ issue_3856: {
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
issue_3916: {
|
||||
issue_3916_1: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
}
|
||||
@@ -1044,8 +1044,8 @@ issue_3916: {
|
||||
var o = {
|
||||
p: "PASS",
|
||||
__proto__: 42,
|
||||
q: "FAIL",
|
||||
};
|
||||
o.q = "FAIL";
|
||||
o.__proto__ = {
|
||||
p: "FAIL",
|
||||
q: "PASS",
|
||||
@@ -1056,6 +1056,62 @@ issue_3916: {
|
||||
expect_stdout: "object PASS true PASS"
|
||||
}
|
||||
|
||||
issue_3916_2: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
var log = console.log, o = {};
|
||||
o.p = "FAIL 1";
|
||||
o.__proto__ = {
|
||||
get p() {
|
||||
return "FAIL 2";
|
||||
},
|
||||
set p(u) {
|
||||
log("FAIL 3");
|
||||
},
|
||||
set q(v) {
|
||||
log("PASS 1");
|
||||
},
|
||||
get q() {
|
||||
return "PASS 3";
|
||||
},
|
||||
};
|
||||
o.p = "PASS 2";
|
||||
o.q = "FAIL 4";
|
||||
log(o.p);
|
||||
log(o.q);
|
||||
}
|
||||
expect: {
|
||||
var log = console.log, o = {
|
||||
p: "FAIL 1",
|
||||
__proto__: {
|
||||
get p() {
|
||||
return "FAIL 2";
|
||||
},
|
||||
set p(u) {
|
||||
log("FAIL 3");
|
||||
},
|
||||
set q(v) {
|
||||
log("PASS 1");
|
||||
},
|
||||
get q() {
|
||||
return "PASS 3";
|
||||
},
|
||||
},
|
||||
};
|
||||
o.p = "PASS 2";
|
||||
o.q = "FAIL 4";
|
||||
log(o.p);
|
||||
log(o.q);
|
||||
}
|
||||
expect_stdout: [
|
||||
"PASS 1",
|
||||
"PASS 2",
|
||||
"PASS 3",
|
||||
]
|
||||
}
|
||||
|
||||
assign_var: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
|
||||
@@ -3301,3 +3301,80 @@ issue_4761: {
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
issue_4956_1: {
|
||||
options = {
|
||||
merge_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a, b;
|
||||
function f(c) {
|
||||
switch (c) {
|
||||
case 0:
|
||||
a = { p: 42 };
|
||||
|
||||
case 1:
|
||||
b = a.p;
|
||||
console.log(b);
|
||||
}
|
||||
}
|
||||
f(0);
|
||||
f(1);
|
||||
}
|
||||
expect: {
|
||||
var a, b;
|
||||
function f(c) {
|
||||
switch (c) {
|
||||
case 0:
|
||||
a = { p: 42 };
|
||||
|
||||
case 1:
|
||||
b = a.p;
|
||||
console.log(b);
|
||||
}
|
||||
}
|
||||
f(0);
|
||||
f(1);
|
||||
}
|
||||
expect_stdout: [
|
||||
"42",
|
||||
"42",
|
||||
]
|
||||
}
|
||||
|
||||
issue_4956_2: {
|
||||
options = {
|
||||
merge_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a, b;
|
||||
function f(c) {
|
||||
if (0 == c) {
|
||||
console;
|
||||
a = { p: 42 };
|
||||
}
|
||||
b = a.p;
|
||||
if (1 == c)
|
||||
console.log(b);
|
||||
}
|
||||
f(0);
|
||||
f(1);
|
||||
}
|
||||
expect: {
|
||||
var a, b;
|
||||
function f(c) {
|
||||
if (0 == c) {
|
||||
console;
|
||||
a = { p: 42 };
|
||||
}
|
||||
b = a.p;
|
||||
if (1 == c)
|
||||
console.log(b);
|
||||
}
|
||||
f(0);
|
||||
f(1);
|
||||
}
|
||||
expect_stdout: "42"
|
||||
}
|
||||
|
||||
307
test/compress/optional-chains.js
Normal file
307
test/compress/optional-chains.js
Normal file
@@ -0,0 +1,307 @@
|
||||
call: {
|
||||
input: {
|
||||
console.log?.(undefined?.(console.log("FAIL")));
|
||||
}
|
||||
expect_exact: 'console.log?.((void 0)?.(console.log("FAIL")));'
|
||||
expect_stdout: "undefined"
|
||||
node_version: ">=14"
|
||||
}
|
||||
|
||||
dot: {
|
||||
input: {
|
||||
console?.log((void 0)?.p);
|
||||
}
|
||||
expect_exact: "console?.log((void 0)?.p);"
|
||||
expect_stdout: "undefined"
|
||||
node_version: ">=14"
|
||||
}
|
||||
|
||||
dot_in: {
|
||||
input: {
|
||||
var o = { in: 42 };
|
||||
console.log(o.in, o?.in);
|
||||
}
|
||||
expect_exact: "var o={in:42};console.log(o.in,o?.in);"
|
||||
expect_stdout: "42 42"
|
||||
node_version: ">=14"
|
||||
}
|
||||
|
||||
sub: {
|
||||
input: {
|
||||
console?.["log"](null?.[console.log("FAIL")]);
|
||||
}
|
||||
expect_exact: 'console?.["log"](null?.[console.log("FAIL")]);'
|
||||
expect_stdout: "undefined"
|
||||
node_version: ">=14"
|
||||
}
|
||||
|
||||
ternary_decimal: {
|
||||
input: {
|
||||
null ? .42 : console.log("PASS");
|
||||
}
|
||||
expect_exact: 'null?.42:console.log("PASS");'
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
assign_parentheses_call: {
|
||||
input: {
|
||||
var o = {};
|
||||
((() => o)?.()).p = "PASS";
|
||||
console.log(o.p);
|
||||
}
|
||||
expect_exact: 'var o={};((()=>o)?.()).p="PASS";console.log(o.p);'
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=14"
|
||||
}
|
||||
|
||||
assign_parentheses_dot: {
|
||||
input: {
|
||||
(console?.log).name.p = console.log("PASS");
|
||||
}
|
||||
expect_exact: '(console?.log.name).p=console.log("PASS");'
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=14"
|
||||
}
|
||||
|
||||
assign_no_parentheses: {
|
||||
input: {
|
||||
console[console.log?.("PASS")] = 42;
|
||||
}
|
||||
expect_exact: 'console[console.log?.("PASS")]=42;'
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=14"
|
||||
}
|
||||
|
||||
unary_parentheses: {
|
||||
input: {
|
||||
var o = { p: 41 };
|
||||
(function() {
|
||||
return o;
|
||||
}?.()).p++;
|
||||
console.log(o.p);
|
||||
}
|
||||
expect_exact: "var o={p:41};(function(){return o}?.()).p++;console.log(o.p);"
|
||||
expect_stdout: "42"
|
||||
node_version: ">=14"
|
||||
}
|
||||
|
||||
collapse_vars_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
A = 42;
|
||||
a?.[42];
|
||||
console.log(typeof A);
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
A = 42;
|
||||
a?.[42];
|
||||
console.log(typeof A);
|
||||
}
|
||||
expect_stdout: "number"
|
||||
node_version: ">=14"
|
||||
}
|
||||
|
||||
collapse_vars_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
A = 42;
|
||||
a?.(42);
|
||||
console.log(typeof A);
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
A = 42;
|
||||
a?.(42);
|
||||
console.log(typeof A);
|
||||
}
|
||||
expect_stdout: "number"
|
||||
node_version: ">=14"
|
||||
}
|
||||
|
||||
properties: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
console.log(a?.["FAIL"]);
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
console.log(a?.FAIL);
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
node_version: ">=14"
|
||||
}
|
||||
|
||||
reduce_vars_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = 1;
|
||||
null?.[a = 0];
|
||||
console.log(a ? "PASS" : "FAIL");
|
||||
}
|
||||
expect: {
|
||||
var a = 1;
|
||||
null?.[a = 0];
|
||||
console.log(a ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=14"
|
||||
}
|
||||
|
||||
reduce_vars_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = 1;
|
||||
null?.(a = 0);
|
||||
console.log(a ? "PASS" : "FAIL");
|
||||
}
|
||||
expect: {
|
||||
var a = 1;
|
||||
null?.(a = 0);
|
||||
console.log(a ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=14"
|
||||
}
|
||||
|
||||
side_effects: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
a?.[a = "FAIL"];
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
a?.[a = "FAIL"];
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
node_version: ">=14"
|
||||
}
|
||||
|
||||
trim_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
optional_chains: true,
|
||||
reduce_vars: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
(function(a, b) {
|
||||
console?.log?.(a?.p, b?.[console.log("FAIL")]);
|
||||
})?.({ p: "PASS" });
|
||||
}
|
||||
expect: {
|
||||
(function(a, b) {
|
||||
console?.log?.(a.p, void 0);
|
||||
})({ p: "PASS" });
|
||||
}
|
||||
expect_stdout: "PASS undefined"
|
||||
node_version: ">=14"
|
||||
}
|
||||
|
||||
trim_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
optional_chains: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
(void console.log("PASS"))?.[console.log("FAIL")];
|
||||
}
|
||||
expect: {
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=14"
|
||||
}
|
||||
|
||||
issue_4906: {
|
||||
options = {
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
do {
|
||||
var a = a?.[42];
|
||||
} while (console.log("PASS"));
|
||||
}
|
||||
expect: {
|
||||
do {} while (console.log("PASS"));
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=14"
|
||||
}
|
||||
|
||||
issue_4928: {
|
||||
options = {
|
||||
ie8: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = a?.[function f() {
|
||||
f(a);
|
||||
}];
|
||||
console.log(typeof f);
|
||||
}
|
||||
expect: {
|
||||
var a = a?.[function f() {
|
||||
f(a);
|
||||
}];
|
||||
console.log(typeof f);
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
node_version: ">=14"
|
||||
}
|
||||
|
||||
issue_4947_1: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
console.log(console.foo ? 42..p : console.bar?.p);
|
||||
}
|
||||
expect: {
|
||||
console.log(console.foo ? 42..p : console.bar?.p);
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
node_version: ">=14"
|
||||
}
|
||||
|
||||
issue_4947_2: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
var log = console.log, fail;
|
||||
log("PASS") ? log(42) : fail?.(42);
|
||||
}
|
||||
expect: {
|
||||
var log = console.log, fail;
|
||||
log("PASS") ? log(42) : fail?.(42);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=14"
|
||||
}
|
||||
@@ -1446,3 +1446,20 @@ issue_4831_2: {
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
issue_4888: {
|
||||
options = {
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
console.log(typeof {
|
||||
__proto__: 42,
|
||||
}.__proto__);
|
||||
}
|
||||
expect: {
|
||||
console.log(typeof {
|
||||
__proto__: 42,
|
||||
}.__proto__);
|
||||
}
|
||||
expect_stdout: "object"
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ conditional: {
|
||||
relational: {
|
||||
options = {
|
||||
pure_funcs: [ "foo" ],
|
||||
side_effects :true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
foo() in new foo();
|
||||
@@ -158,7 +158,7 @@ relational: {
|
||||
arithmetic: {
|
||||
options = {
|
||||
pure_funcs: [ "foo" ],
|
||||
side_effects :true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
foo() + foo();
|
||||
@@ -183,7 +183,7 @@ arithmetic: {
|
||||
boolean_and: {
|
||||
options = {
|
||||
pure_funcs: [ "foo" ],
|
||||
side_effects :true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
foo() && foo();
|
||||
@@ -208,7 +208,7 @@ boolean_and: {
|
||||
boolean_or: {
|
||||
options = {
|
||||
pure_funcs: [ "foo" ],
|
||||
side_effects :true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
foo() || foo();
|
||||
@@ -233,7 +233,7 @@ boolean_or: {
|
||||
assign: {
|
||||
options = {
|
||||
pure_funcs: [ "foo" ],
|
||||
side_effects :true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
@@ -256,7 +256,7 @@ assign: {
|
||||
unary: {
|
||||
options = {
|
||||
pure_funcs: [ "foo" ],
|
||||
side_effects :true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
typeof foo();
|
||||
|
||||
@@ -1638,3 +1638,29 @@ nested_property_assignments_3: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4939: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
({
|
||||
__proto__: {
|
||||
get p() {
|
||||
console.log("PASS");
|
||||
},
|
||||
},
|
||||
}).p;
|
||||
}
|
||||
expect: {
|
||||
({
|
||||
__proto__: {
|
||||
get p() {
|
||||
console.log("PASS");
|
||||
},
|
||||
},
|
||||
}).p;
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -7631,3 +7631,114 @@ issue_4568: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4937: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
while (console.log("PASS"));
|
||||
}
|
||||
do {
|
||||
function g() {
|
||||
f();
|
||||
}
|
||||
} while (!g);
|
||||
f();
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
while (console.log("PASS"));
|
||||
}
|
||||
do {
|
||||
function g() {
|
||||
f();
|
||||
}
|
||||
} while (!g);
|
||||
f();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4943_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a, b = 1;
|
||||
(function f() {
|
||||
a = "foo";
|
||||
b-- && f();
|
||||
console.log(a);
|
||||
a = "bar";
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
var a, b = 1;
|
||||
(function f() {
|
||||
a = "foo";
|
||||
b-- && f();
|
||||
console.log(a);
|
||||
a = "bar";
|
||||
})();
|
||||
}
|
||||
expect_stdout: [
|
||||
"foo",
|
||||
"bar",
|
||||
]
|
||||
}
|
||||
|
||||
issue_4943_2: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a, b = 1;
|
||||
(function f() {
|
||||
a = "foo";
|
||||
b-- && f();
|
||||
console.log(a);
|
||||
a = "bar";
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
var a, b = 1;
|
||||
(function f() {
|
||||
a = "foo";
|
||||
b-- && f();
|
||||
console.log(a);
|
||||
a = "bar";
|
||||
})();
|
||||
}
|
||||
expect_stdout: [
|
||||
"foo",
|
||||
"bar",
|
||||
]
|
||||
}
|
||||
|
||||
issue_4949: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function f(a) {
|
||||
a = 0;
|
||||
console.log(a++, arguments[0]);
|
||||
})(0);
|
||||
}
|
||||
expect: {
|
||||
(function(a) {
|
||||
a = 0;
|
||||
console.log(a++, arguments[0]);
|
||||
})(0);
|
||||
}
|
||||
expect_stdout: "0 1"
|
||||
}
|
||||
|
||||
@@ -1068,3 +1068,91 @@ issue_4849: {
|
||||
expect_stdout: "object"
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
issue_4882_1: {
|
||||
options = {
|
||||
objects: true,
|
||||
spreads: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
p: "PASS",
|
||||
... {
|
||||
__proto__: {
|
||||
p: "FAIL 1",
|
||||
q: "FAIL 2",
|
||||
},
|
||||
},
|
||||
};
|
||||
console.log(o.p);
|
||||
console.log(o.q);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
p: "PASS",
|
||||
};
|
||||
console.log(o.p);
|
||||
console.log(o.q);
|
||||
}
|
||||
expect_stdout: [
|
||||
"PASS",
|
||||
"undefined",
|
||||
]
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
issue_4882_2: {
|
||||
options = {
|
||||
objects: true,
|
||||
spreads: true,
|
||||
}
|
||||
input: {
|
||||
console.log(null == Object.getPrototypeOf({
|
||||
... {
|
||||
__proto__: (console.log(42), null),
|
||||
},
|
||||
}) ? "FAIL" : "PASS");
|
||||
}
|
||||
expect: {
|
||||
console.log(null == Object.getPrototypeOf({
|
||||
... {
|
||||
__proto__: (console.log(42), null),
|
||||
},
|
||||
}) ? "FAIL" : "PASS");
|
||||
}
|
||||
expect_stdout: [
|
||||
"42",
|
||||
"PASS",
|
||||
]
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
issue_4882_3: {
|
||||
options = {
|
||||
objects: true,
|
||||
spreads: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
__proto__: { p: 42 },
|
||||
... {
|
||||
set __proto__(v) {},
|
||||
},
|
||||
};
|
||||
console.log(o.__proto__ === Object.getPrototypeOf(o) ? "FAIL" : "PASS");
|
||||
console.log(o.p);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
__proto__: { p: 42 },
|
||||
["__proto__"]: void 0,
|
||||
};
|
||||
console.log(o.__proto__ === Object.getPrototypeOf(o) ? "FAIL" : "PASS");
|
||||
console.log(o.p);
|
||||
}
|
||||
expect_stdout: [
|
||||
"PASS",
|
||||
"42",
|
||||
]
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
@@ -62,6 +62,23 @@ tag_parentheses_arrow: {
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
tag_parentheses_binary: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var f = function() {
|
||||
console.log("PASS");
|
||||
} || console
|
||||
f``;
|
||||
}
|
||||
expect_exact: '(function(){console.log("PASS")}||console)``;'
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
tag_parentheses_new: {
|
||||
input: {
|
||||
(new function() {
|
||||
@@ -87,6 +104,21 @@ tag_parentheses_sequence: {
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
tag_parentheses_unary: {
|
||||
input: {
|
||||
var a;
|
||||
try {
|
||||
(~a)``;
|
||||
(a++)``;
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect_exact: 'var a;try{(~a)``;(a++)``}catch(e){console.log("PASS")}'
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
malformed_escape: {
|
||||
input: {
|
||||
(function(s) {
|
||||
@@ -283,6 +315,21 @@ unsafe_side_effects: {
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
pure_funcs: {
|
||||
options = {
|
||||
pure_funcs: "Math.random",
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
Math.random`${console.log("PASS")}`;
|
||||
}
|
||||
expect: {
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
issue_4604: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
@@ -343,7 +390,7 @@ issue_4676: {
|
||||
reduce_vars: true,
|
||||
templates: true,
|
||||
toplevel: true,
|
||||
unsafe:true,
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -366,3 +413,24 @@ issue_4676: {
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
issue_4931: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
templates: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(String.raw`${typeof A} ${"\r"}`);
|
||||
console.log(String.raw`${"\\"} ${"`"}`);
|
||||
}
|
||||
expect: {
|
||||
console.log(String.raw`${typeof A} ${"\r"}`);
|
||||
console.log("\\ `");
|
||||
}
|
||||
expect_stdout: [
|
||||
"undefined \r",
|
||||
"\\ `",
|
||||
]
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
@@ -523,3 +523,93 @@ default_init: {
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
issue_4933_1: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
varify: true,
|
||||
}
|
||||
input: {
|
||||
console.log(f());
|
||||
function f() {
|
||||
var a;
|
||||
for (console in a = [ f ]) {
|
||||
const b = a;
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
console.log(function f() {
|
||||
var a;
|
||||
for (console in a = [ f ]) {
|
||||
const b = a;
|
||||
}
|
||||
}());
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
issue_4933_2: {
|
||||
options = {
|
||||
passes: 2,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
varify: true,
|
||||
}
|
||||
input: {
|
||||
console.log(f());
|
||||
function f() {
|
||||
var a;
|
||||
for (console in a = [ f ]) {
|
||||
const b = a;
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
console.log(function f() {
|
||||
for (console in [ f ]);
|
||||
}());
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
issue_4954: {
|
||||
options = {
|
||||
functions: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
varify: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
(function() {
|
||||
{
|
||||
let a = console;
|
||||
console.log(typeof a);
|
||||
}
|
||||
{
|
||||
let a = function() {};
|
||||
a && console.log(typeof a);
|
||||
}
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
(function() {
|
||||
var a = console;
|
||||
console.log(typeof a);
|
||||
{
|
||||
let a = function() {};
|
||||
a && console.log(typeof a);
|
||||
}
|
||||
})();
|
||||
}
|
||||
expect_stdout: [
|
||||
"object",
|
||||
"function",
|
||||
]
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
++null
|
||||
console.log(4 || (null = 4));
|
||||
|
||||
1
test/input/invalid/assign_5.js
Normal file
1
test/input/invalid/assign_5.js
Normal file
@@ -0,0 +1 @@
|
||||
console.log(5 || ([]?.length ^= 5));
|
||||
@@ -427,16 +427,30 @@ describe("bin/uglifyjs", function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (++null)", function(done) {
|
||||
it("Should throw syntax error (null = 4)", function(done) {
|
||||
var command = uglifyjscmd + " test/input/invalid/assign_4.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/assign_4.js:1,0",
|
||||
"++null",
|
||||
"^",
|
||||
"ERROR: Invalid use of ++ operator",
|
||||
"Parse error at test/input/invalid/assign_4.js:1,23",
|
||||
"console.log(4 || (null = 4));",
|
||||
" ^",
|
||||
"ERROR: Invalid assignment",
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error ([]?.length ^= 5)", function(done) {
|
||||
var command = uglifyjscmd + " test/input/invalid/assign_5.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/assign_5.js:1,29",
|
||||
"console.log(5 || ([]?.length ^= 5));",
|
||||
" ^",
|
||||
"ERROR: Invalid assignment",
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
|
||||
@@ -7,11 +7,11 @@ describe("let", function() {
|
||||
// Produce a lot of variables in a function and run it through mangle.
|
||||
var s = '"dddddeeeeelllllooooottttt"; function foo() {';
|
||||
for (var i = 0; i < 18000; i++) {
|
||||
s += "var v" + i + "=0;";
|
||||
s += "var v" + i + "=[];";
|
||||
}
|
||||
s += '}';
|
||||
var result = UglifyJS.minify(s, {
|
||||
compress: false
|
||||
compress: false,
|
||||
}).code;
|
||||
|
||||
// Verify that select keywords and reserved keywords not produced
|
||||
|
||||
@@ -101,6 +101,19 @@ describe("sourcemaps", function() {
|
||||
var map = JSON.parse(result.map);
|
||||
assert.deepEqual(map.names, []);
|
||||
});
|
||||
it("Should mark class properties", function() {
|
||||
var result = UglifyJS.minify([
|
||||
"class A {",
|
||||
" static P = 42",
|
||||
" set #q(v) {}",
|
||||
"}",
|
||||
].join("\n"), {
|
||||
sourceMap: true,
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, "class A{static P=42;set#q(s){}}");
|
||||
assert.strictEqual(result.map, '{"version":3,"sources":["0"],"names":["A","P","#q","v"],"mappings":"MAAMA,EACFC,SAAW,GACXC,MAAOC"}');
|
||||
});
|
||||
it("Should mark array/object literals", function() {
|
||||
var result = UglifyJS.minify([
|
||||
"var obj = {};",
|
||||
|
||||
@@ -46,7 +46,7 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
||||
if (verbose) {
|
||||
log("// Node.js " + process.version + " on " + os.platform() + " " + os.arch());
|
||||
}
|
||||
if (differs.error && [ "DefaultsError", "SyntaxError" ].indexOf(differs.error.name) < 0) {
|
||||
if (differs && differs.error && [ "DefaultsError", "SyntaxError" ].indexOf(differs.error.name) < 0) {
|
||||
test_for_diff = test_minify;
|
||||
differs = test_for_diff(testcase, minify_options, result_cache, max_timeout);
|
||||
}
|
||||
@@ -132,6 +132,8 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
||||
return;
|
||||
}
|
||||
if (parent instanceof U.AST_VarDef && parent.name === node) return;
|
||||
// preserve class methods
|
||||
if (parent instanceof U.AST_ClassMethod && parent.value === node) return;
|
||||
// preserve exports
|
||||
if (parent instanceof U.AST_ExportDeclaration) return;
|
||||
if (parent instanceof U.AST_ExportDefault) return;
|
||||
@@ -147,6 +149,9 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
||||
if (parent instanceof U.AST_For && parent.init === node && node instanceof U.AST_Definitions) return node;
|
||||
// preserve for (xxx in/of ...)
|
||||
if (parent instanceof U.AST_ForEnumeration && parent.init === node) return node;
|
||||
// preserve super(...)
|
||||
if (node.TYPE == "Call" && node.expression instanceof U.AST_Super) return;
|
||||
if (node instanceof U.AST_Super && parent.TYPE == "Call" && parent.expression === node) return node;
|
||||
|
||||
// node specific permutations with no parent logic
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ minify_in_situ() {
|
||||
do
|
||||
echo "$i"
|
||||
CODE=`cat "$i"`
|
||||
node_modules/.bin/esbuild --loader=ts --target=es2019 > "$i" <<EOF
|
||||
node_modules/.bin/esbuild --loader=ts --target=esnext > "$i" <<EOF
|
||||
$CODE
|
||||
EOF
|
||||
ARGS="$ARGS $i"
|
||||
|
||||
@@ -11,7 +11,7 @@ minify_in_situ() {
|
||||
do
|
||||
echo "$i"
|
||||
CODE=`cat "$i"`
|
||||
node_modules/.bin/esbuild --loader=ts --target=es2019 > "$i" <<EOF
|
||||
node_modules/.bin/esbuild --loader=ts --target=esnext > "$i" <<EOF
|
||||
$CODE
|
||||
EOF
|
||||
ARGS="$ARGS $i"
|
||||
|
||||
@@ -27,8 +27,8 @@ exports.run_code = semver.satisfies(process.version, "0.8") ? function(code, top
|
||||
} : semver.satisfies(process.version, "<0.12") ? run_code_vm : function(code, toplevel, timeout) {
|
||||
if ([
|
||||
/\basync[ \t]*\([\s\S]*?\)[ \t]*=>/,
|
||||
/\b(async[ \t]+function|setImmediate|setInterval|setTimeout)\b/,
|
||||
/\basync([ \t]+|[ \t]*\*[ \t]*)[^\s()[\]{},.&|!~=*%/+-]+(\s*\(|[ \t]*=>)/,
|
||||
/\b(async[ \t]+function|Promise|setImmediate|setInterval|setTimeout)\b/,
|
||||
/\basync([ \t]+|[ \t]*#|[ \t]*\*[ \t]*)[^\s()[\]{},.&|!~=*%/+-]+(\s*\(|[ \t]*=>)/,
|
||||
].some(function(pattern) {
|
||||
return pattern.test(code);
|
||||
})) {
|
||||
|
||||
@@ -152,6 +152,7 @@ var SUPPORT = function(matrix) {
|
||||
logical_assignment: "[].p ??= 0;",
|
||||
new_target: "function f() { new.target; }",
|
||||
nullish: "0 ?? 0",
|
||||
optional_chaining: "0?.p",
|
||||
rest: "var [...a] = [];",
|
||||
rest_object: "var {...a} = {};",
|
||||
spread: "[...[]];",
|
||||
@@ -355,6 +356,7 @@ var block_vars = [];
|
||||
var lambda_vars = [];
|
||||
var unique_vars = [];
|
||||
var classes = [];
|
||||
var allow_this = true;
|
||||
var async = false;
|
||||
var has_await = false;
|
||||
var export_default = false;
|
||||
@@ -401,6 +403,7 @@ function createTopLevelCode() {
|
||||
lambda_vars.length = 0;
|
||||
unique_vars.length = 0;
|
||||
classes.length = 0;
|
||||
allow_this = true;
|
||||
async = false;
|
||||
has_await = false;
|
||||
export_default = false;
|
||||
@@ -1188,7 +1191,7 @@ function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn
|
||||
|
||||
function createSwitchParts(recurmax, n, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) {
|
||||
var hadDefault = false;
|
||||
var s = [""];
|
||||
var s = [ "" ];
|
||||
canBreak = enableLoopControl(canBreak, CAN_BREAK);
|
||||
while (n-- > 0) {
|
||||
//hadDefault = n > 0; // disables weird `default` clause positioning (use when handling destabilizes)
|
||||
@@ -1487,12 +1490,16 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
|
||||
return createValue() + " in " + createObjectLiteral(recurmax, stmtDepth, canThrow);
|
||||
case p++:
|
||||
var name = getVarName();
|
||||
var s = name + "[" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "]";
|
||||
return canThrow && rng(20) == 0 ? s : name + " && " + s;
|
||||
var prop = "[" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "]";
|
||||
if (SUPPORT.optional_chaining && rng(50) == 0) return name + "?." + prop;
|
||||
if (canThrow && rng(20) == 0) return name + prop;
|
||||
return name + " && " + name + prop;
|
||||
case p++:
|
||||
var name = getVarName();
|
||||
var s = name + "." + getDotKey();
|
||||
return canThrow && rng(20) == 0 ? s : name + " && " + s;
|
||||
var prop = getDotKey();
|
||||
if (SUPPORT.optional_chaining && rng(50) == 0) return name + "?." + prop;
|
||||
if (canThrow && rng(20) == 0) return name + "." + prop;
|
||||
return name + " && " + name + "." + prop;
|
||||
case p++:
|
||||
case p++:
|
||||
var name = getVarName();
|
||||
@@ -1534,7 +1541,16 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
|
||||
name = rng(3) == 0 ? getVarName() : "f" + rng(funcs + 2);
|
||||
} while (name in called && !called[name]);
|
||||
called[name] = true;
|
||||
return mayDefer("typeof " + name + ' == "function" && --_calls_ >= 0 && ' + name + createArgs(recurmax, stmtDepth, canThrow));
|
||||
var args = createArgs(recurmax, stmtDepth, canThrow);
|
||||
var call = "typeof " + name + ' == "function" && --_calls_ >= 0 && ' + name + args;
|
||||
if (canThrow) {
|
||||
if (SUPPORT.optional_chaining && args[0] != "`" && rng(50) == 0) {
|
||||
call = "--_calls_ >= 0 && " + name + "?." + args;
|
||||
} else if (rng(20) == 0) {
|
||||
call = "--_calls_ >= 0 && " + name + args;
|
||||
}
|
||||
}
|
||||
return mayDefer(call);
|
||||
}
|
||||
_createExpression.N = p;
|
||||
return _createExpression(recurmax, noComma, stmtDepth, canThrow);
|
||||
@@ -1619,6 +1635,10 @@ var KEYS = [
|
||||
"1.5",
|
||||
"3",
|
||||
].concat(SAFE_KEYS);
|
||||
SAFE_KEYS = SAFE_KEYS.concat(SAFE_KEYS);
|
||||
SAFE_KEYS = SAFE_KEYS.concat(SAFE_KEYS);
|
||||
SAFE_KEYS = SAFE_KEYS.concat(SAFE_KEYS);
|
||||
SAFE_KEYS.push("__proto__");
|
||||
|
||||
function getDotKey(assign) {
|
||||
var key;
|
||||
@@ -1713,6 +1733,8 @@ function createObjectFunction(recurmax, stmtDepth, canThrow, internal, isClazz)
|
||||
fn = function(defns) {
|
||||
if (generator) name = "*" + name;
|
||||
if (async) name = "async "+ name;
|
||||
var save_allow = allow_this;
|
||||
if (internal == "super") allow_this = false;
|
||||
s = [
|
||||
name + "(" + createParams(save_async, save_generator, NO_DUPLICATE) + "){",
|
||||
strictMode(),
|
||||
@@ -1720,6 +1742,7 @@ function createObjectFunction(recurmax, stmtDepth, canThrow, internal, isClazz)
|
||||
];
|
||||
s.push(_createStatements(2, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CANNOT_RETURN, stmtDepth));
|
||||
if (internal == "super") s.push("super" + createArgs(recurmax, stmtDepth, canThrow, NO_TEMPLATE) + ";");
|
||||
allow_this = save_allow;
|
||||
if (/^(constructor|super)$/.test(internal) || rng(10) == 0) for (var i = rng(4); --i >= 0;) {
|
||||
s.push(rng(2) ? createSuperAssignment(recurmax, stmtDepth, canThrow) : createThisAssignment(recurmax, stmtDepth, canThrow));
|
||||
}
|
||||
@@ -1736,8 +1759,9 @@ function createObjectFunction(recurmax, stmtDepth, canThrow, internal, isClazz)
|
||||
|
||||
function createObjectLiteral(recurmax, stmtDepth, canThrow) {
|
||||
recurmax--;
|
||||
var obj = ["({"];
|
||||
var obj = [ "({" ];
|
||||
var offset = SUPPORT.spread_object ? 0 : SUPPORT.computed_key ? 2 : 4;
|
||||
var has_proto = false;
|
||||
for (var i = rng(6); --i >= 0;) switch (offset + rng(50 - offset)) {
|
||||
case 0:
|
||||
obj.push("..." + getVarName() + ",");
|
||||
@@ -1753,7 +1777,12 @@ function createObjectLiteral(recurmax, stmtDepth, canThrow) {
|
||||
obj.push(createObjectFunction(recurmax, stmtDepth, canThrow) + ",");
|
||||
break;
|
||||
default:
|
||||
obj.push(createObjectKey(recurmax, stmtDepth, canThrow) + ": " + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ",");
|
||||
if (has_proto || rng(200)) {
|
||||
obj.push(createObjectKey(recurmax, stmtDepth, canThrow) + ": " + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ",");
|
||||
} else {
|
||||
obj.push("__proto__: " + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + " || {},");
|
||||
has_proto = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
obj.push("})");
|
||||
@@ -1950,7 +1979,7 @@ function createValue() {
|
||||
var v;
|
||||
do {
|
||||
v = VALUES[rng(VALUES.length)];
|
||||
} while (v == "new.target" && rng(200));
|
||||
} while (v == "new.target" && rng(200) || !allow_this && v == "this");
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -2274,7 +2303,7 @@ function is_error_in(ex) {
|
||||
}
|
||||
|
||||
function is_error_spread(ex) {
|
||||
return ex.name == "TypeError" && /Found non-callable @@iterator| is not iterable| is not a function/.test(ex.message);
|
||||
return ex.name == "TypeError" && /Found non-callable @@iterator| is not iterable| not a function/.test(ex.message);
|
||||
}
|
||||
|
||||
function is_error_recursion(ex) {
|
||||
|
||||
Reference in New Issue
Block a user