Compare commits

...

66 Commits

Author SHA1 Message Date
Alex Lam S.L
bca83cb9df v3.14.3 2021-11-02 05:03:46 +08:00
Alex Lam S.L
a841d45bc3 fix corner case in awaits (#5160)
fixes #5159
2021-10-31 23:46:55 +08:00
Alex Lam S.L
eb93d92357 fix corner case in awaits (#5158)
fixes #5157
2021-10-29 23:33:10 +08:00
Alex Lam S.L
a0250ec923 fix corner case in dead_code (#5154)
fixes #5153
2021-10-25 06:18:16 +08:00
Alex Lam S.L
25801627be parse let as symbol names correctly (#5151)
fixes #5149
2021-10-21 02:14:29 +08:00
Alex Lam S.L
32ae994f88 fix issues in tests flagged by LGTM (#5150) 2021-10-21 02:07:23 +08:00
Alex Lam S.L
03aec89f60 fix corner cases in strings & templates (#5147)
fixes #5145
2021-10-16 18:02:23 +08:00
Alex Lam S.L
faf0190546 document ECMAScript quirks (#5148)
- exclude Node.js v0.8 from CI as npm registry no longer works

closes #5146
2021-10-16 13:28:13 +08:00
Alex Lam S.L
c8b0f685ee fix corner case in merge_vars (#5143)
fixes #5142
2021-10-05 00:42:46 +08:00
Alex Lam S.L
87b99162fb fix corner case in inline (#5141)
fixes #5140
2021-10-02 06:54:42 +08:00
Alex Lam S.L
940887f20f fix corner case in evaluate (#5139)
fixes #5138
2021-10-01 02:52:21 +08:00
Alex Lam S.L
0b2573c3fa fix corner case in templates (#5137)
fixes #5136
2021-09-30 21:43:34 +08:00
Alex Lam S.L
157521066f avoid potential RegExp denial-of-service (#5135)
closes #5133
closes #5134
2021-09-30 01:49:46 +08:00
Alex Lam S.L
f766babf5e enhance templates (#5131)
closes #5125
2021-09-23 18:26:26 +08:00
Alex Lam S.L
436a29367c enhance dead_code (#5130) 2021-09-22 03:11:45 +08:00
Alex Lam S.L
55418fd460 fix corner case in rests (#5129)
fixes #5128
2021-09-20 05:02:35 +08:00
Alex Lam S.L
85786889bd v3.14.2 2021-09-07 21:52:59 +08:00
Alex Lam S.L
4b88dfb8d9 tweak test & warnings (#5123)
closes #5116
closes #5117
closes #5122
2021-09-07 01:33:23 +08:00
Alex Lam S.L
c3aef23614 fix corner case in reduce_vars (#5121)
fixes #5120
2021-08-25 10:39:35 +08:00
Alex Lam S.L
db94d21980 fix corner case in side_effects (#5118) 2021-08-23 08:51:59 +08:00
Alex Lam S.L
9634a9d1fd fix corner cases in optional_chains (#5110) 2021-08-20 10:10:10 +08:00
Alex Lam S.L
befb99bd71 fix corner case in inline (#5115)
fixes #5114
2021-08-18 15:57:08 +08:00
Alex Lam S.L
02eb8baa1c fix corner case in collapse_vars (#5113)
fixes #5112
2021-08-18 10:54:24 +08:00
Alex Lam S.L
c09f63aefb fix corner case in rests (#5109)
fixes #5108
2021-08-09 08:59:33 +08:00
Alex Lam S.L
fdcc6d3a9c fix corner case in dead_code (#5107)
fixes #5106
2021-08-06 08:35:11 +08:00
Alex Lam S.L
4fe2cac35e enhance inline (#5105) 2021-07-27 21:47:01 +08:00
Alex Lam S.L
e219a9a78a v3.14.1 2021-07-27 16:53:57 +08:00
Alex Lam S.L
c80eabd61e fix ie8 option alias (#5103)
fixes #5102
2021-07-26 16:45:43 +08:00
Alex Lam S.L
9b82f9be91 fix corner case in unused (#5101)
fixes #5100
2021-07-26 16:44:34 +08:00
Alex Lam S.L
657d525c80 fix corner case in reduce_vars (#5099)
fixes #5098
2021-07-24 07:10:14 +08:00
Alex Lam S.L
6a3fe9d1df fix corner cases in reduce_vars (#5097)
fixes #5096
2021-07-23 17:17:20 +08:00
Alex Lam S.L
ec7fadcb5b v3.14.0 2021-07-22 21:13:43 +08:00
Alex Lam S.L
65adeba55d extend keep_quoted_props over numeric keys (#5094)
fixes #5093
2021-07-22 06:12:57 +08:00
Alex Lam S.L
7fac839c62 fix corner case in merge_vars (#5092)
fixes #5091
2021-07-21 02:47:53 +08:00
Alex Lam S.L
8926a2f327 fix corner case in unused (#5090)
fixes #5089
2021-07-21 01:10:58 +08:00
Alex Lam S.L
85968dee54 fix corner case in inline (#5088)
fixes #5087
2021-07-19 22:35:45 +08:00
Alex Lam S.L
a7e7865e6b fix corner case in unused (#5086)
fixes #5085
2021-07-18 19:38:09 +08:00
Alex Lam S.L
ef5f7fc25e workaround various IE quirks (#5084)
fixes #5081
2021-07-17 20:20:56 +08:00
Alex Lam S.L
902997b73d fix corner case in inline (#5083)
fixes #5082
2021-07-16 22:13:33 +08:00
Alex Lam S.L
f18804fa06 fix corner case in unused (#5080)
fixes #5079
2021-07-14 23:02:45 +08:00
Alex Lam S.L
8e2dff632e suppress false positives in ufuzz (#5078) 2021-07-13 04:10:59 +08:00
Alex Lam S.L
92c3fddd7a fix corner case in unused & yields (#5077)
fixes #5076
2021-07-12 23:16:12 +08:00
Alex Lam S.L
0d350b78bf fix corner cases in unused (#5075)
fixes #5074
2021-07-12 07:43:13 +08:00
Alex Lam S.L
1ad830facb fix corner cases in unused (#5073)
fixes #5071
2021-07-11 14:52:38 +08:00
Alex Lam S.L
64ebf6efe9 fix corner case in awaits & side_effects (#5072)
fixes #5070
2021-07-11 13:43:08 +08:00
Alex Lam S.L
08391b8e1c fix corner case in hoist_props (#5069) 2021-07-11 10:59:57 +08:00
Alex Lam S.L
d147d5d7f0 fix corner case in inline (#5068)
fixes #5067
2021-07-11 04:11:10 +08:00
Alex Lam S.L
aae1fcd12d fix corner case in unused (#5066)
fixes #5065
2021-07-11 00:43:01 +08:00
Alex Lam S.L
f67dd31cbb enhance unused (#5064) 2021-07-10 19:58:57 +08:00
Alex Lam S.L
450aabaaa0 fix corner cases in rests & unused (#5063) 2021-07-10 00:28:23 +08:00
Alex Lam S.L
ea7829daf5 fix corner case in reduce_vars (#5062)
fixes #5061
2021-07-08 16:31:04 +08:00
Alex Lam S.L
6577d641ac enhance evaluate & reduce_vars (#5060) 2021-07-08 00:29:23 +08:00
Alex Lam S.L
2340feff87 support destructured shorthand for default parameters (#5059)
closes #4990
2021-07-07 22:45:24 +08:00
Alex Lam S.L
0c48b84540 fix corner cases in inline & unused (#5058)
fixes #5057
2021-07-07 10:29:16 +08:00
Alex Lam S.L
1fefe3f1d1 fix corner case in reduce_vars (#5056)
fixes #5055
2021-07-07 02:23:09 +08:00
Alex Lam S.L
0668fad5e9 fix corner case with class (#5054)
fixes #5053
2021-07-06 16:04:11 +08:00
Alex Lam S.L
d0e3f6955d enhance functions (#5052) 2021-07-06 02:43:09 +08:00
Alex Lam S.L
6961c57d1e fix corner case in reduce_vars (#5051)
fixes #5050
2021-07-05 11:57:58 +08:00
Alex Lam S.L
f5dbb672b9 fix corner case in reduce_funcs (#5049)
fixes #5048
2021-07-04 15:09:05 +08:00
Alex Lam S.L
f4ae267920 fix corner case in reduce_vars (#5047)
fixes #5046
2021-07-04 13:45:09 +08:00
Alex Lam S.L
972b9f0bef enhance functions & reduce_vars (#5045) 2021-07-04 06:19:08 +08:00
Alex Lam S.L
668f96623c tweak beautify output (#5044) 2021-07-03 23:10:39 +08:00
Alex Lam S.L
1b745494ce enhance booleans (#5043) 2021-07-01 03:05:52 +08:00
Alex Lam S.L
611abff49f fix corner case in booleans (#5042)
fixes #5041
2021-07-01 00:52:54 +08:00
Alex Lam S.L
4ba8b66c5a fix corner case in ie8 (#5040)
fixes #5039
2021-06-30 02:14:07 +08:00
Alex Lam S.L
798121c9f3 enhance reduce_vars (#5038) 2021-06-29 03:51:44 +08:00
69 changed files with 4604 additions and 1148 deletions

View File

@@ -10,7 +10,7 @@ jobs:
matrix:
options:
- '-mb braces'
- '--ie8 -c'
- '--ie -c'
- '-mc'
- '-p acorn --toplevel -mco spidermonkey'
- '--toplevel -mc passes=3,pure_getters,unsafe'

View File

@@ -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', 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:

View File

@@ -111,8 +111,8 @@ a double dash to prevent input files being used as option arguments:
-d, --define <expr>[=value] Global definitions.
-e, --enclose [arg[:value]] Embed everything in a big function, with configurable
argument(s) & value(s).
--ie8 Support non-standard Internet Explorer 8.
Equivalent to setting `ie8: true` in `minify()`
--ie Support non-standard Internet Explorer.
Equivalent to setting `ie: true` in `minify()`
for `compress`, `mangle` and `output` options.
By default UglifyJS will not try to be IE-proof.
--keep-fnames Do not mangle/drop function names. Useful for
@@ -502,7 +502,7 @@ if (result.error) throw result.error;
- `compress` (default: `{}`) — pass `false` to skip compressing entirely.
Pass an object to specify custom [compress options](#compress-options).
- `ie8` (default: `false`) — set to `true` to support IE8.
- `ie` (default: `false`) — enable workarounds for Internet Explorer bugs.
- `keep_fnames` (default: `false`) — pass `true` to prevent discarding or mangling
of function names. Useful for code relying on `Function.prototype.name`.
@@ -566,7 +566,6 @@ if (result.error) throw result.error;
},
nameCache: null, // or specify a name cache object
toplevel: false,
ie8: false,
warnings: false,
}
```
@@ -795,9 +794,8 @@ to be `false` and all symbol names will be omitted.
variables (`"vars"`) in the top level scope (`false` by default, `true` to drop
both unreferenced functions and variables)
- `typeofs` (default: `true`) — Transforms `typeof foo == "undefined"` into
`foo === void 0`. Note: recommend to set this value to `false` for IE10 and
earlier versions due to known issues.
- `typeofs` (default: `true`) — compress `typeof` expressions, e.g.
`typeof foo == "undefined" → void 0 === foo`
- `unsafe` (default: `false`) — apply "unsafe" transformations (discussion below)
@@ -1201,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
({

View File

@@ -101,7 +101,7 @@ function process_option(name, no_value) {
" --config-file <file> Read minify() options from JSON file.",
" -d, --define <expr>[=value] Global definitions.",
" -e, --enclose [arg[,...][:value[,...]]] Embed everything in a big function, with configurable argument(s) & value(s).",
" --ie8 Support non-standard Internet Explorer 8.",
" --ie Support non-standard Internet Explorer.",
" --keep-fnames Do not mangle/drop function names. Useful for code relying on Function.prototype.name.",
" --name-cache <file> File to hold mangled name mappings.",
" --rename Force symbol expansion.",
@@ -110,6 +110,7 @@ function process_option(name, no_value) {
" --source-map [options] Enable source map/specify source map options.",
" --timings Display operations run time on STDERR.",
" --toplevel Compress and/or mangle variables in toplevel scope.",
" --v8 Support non-standard Chrome & Node.js.",
" --validate Perform validation during AST manipulations.",
" --verbose Print diagnostic messages.",
" --warn Print warning messages.",
@@ -145,9 +146,11 @@ function process_option(name, no_value) {
options[name] = read_value();
break;
case "annotations":
case "ie":
case "ie8":
case "timings":
case "toplevel":
case "v8":
case "validate":
case "webkit":
options[name] = true;

View File

@@ -1289,13 +1289,14 @@ function must_be_expressions(node, prop, allow_spread, allow_hole) {
});
}
var AST_Call = DEFNODE("Call", "args expression optional pure", {
var AST_Call = DEFNODE("Call", "args expression optional pure terminal", {
$documentation: "A function call expression",
$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,23 +1340,23 @@ 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",
},
getProperty: function() {
get_property: function() {
var p = this.property;
if (p instanceof AST_Constant) {
return p.value;
}
if (p instanceof AST_UnaryPrefix
&& p.operator == "void"
&& p.expression instanceof AST_Constant) {
return;
}
if (p instanceof AST_Constant) return p.value;
if (p instanceof AST_UnaryPrefix && p.operator == "void" && p.expression instanceof AST_Constant) return;
return p;
},
_validate: function() {
@@ -1759,11 +1761,11 @@ var AST_SymbolLambda = DEFNODE("SymbolLambda", null, {
var AST_SymbolDefClass = DEFNODE("SymbolDefClass", null, {
$documentation: "Symbol defining a class",
}, AST_SymbolLet);
}, AST_SymbolConst);
var AST_SymbolClass = DEFNODE("SymbolClass", null, {
$documentation: "Symbol naming a class expression",
}, AST_SymbolLet);
}, AST_SymbolConst);
var AST_SymbolCatch = DEFNODE("SymbolCatch", null, {
$documentation: "Symbol naming the exception in catch",

File diff suppressed because it is too large Load Diff

View File

@@ -76,6 +76,7 @@ function minify(files, options) {
annotations: undefined,
compress: {},
enclose: false,
ie: false,
ie8: false,
keep_fnames: false,
mangle: {},
@@ -96,7 +97,8 @@ function minify(files, options) {
var timings = options.timings && { start: Date.now() };
if (options.rename === undefined) options.rename = options.compress && options.mangle;
if (options.annotations !== undefined) set_shorthand("annotations", options, [ "compress", "output" ]);
if (options.ie8) set_shorthand("ie8", options, [ "compress", "mangle", "output" ]);
if (options.ie8) options.ie = options.ie || options.ie8;
if (options.ie) set_shorthand("ie", options, [ "compress", "mangle", "output" ]);
if (options.keep_fnames) set_shorthand("keep_fnames", options, [ "compress", "mangle" ]);
if (options.toplevel) set_shorthand("toplevel", options, [ "compress", "mangle" ]);
if (options.v8) set_shorthand("v8", options, [ "mangle", "output" ]);
@@ -106,7 +108,7 @@ function minify(files, options) {
options.mangle = defaults(options.mangle, {
cache: options.nameCache && (options.nameCache.vars || {}),
eval: false,
ie8: false,
ie: false,
keep_fnames: false,
properties: false,
reserved: [],

View File

@@ -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) {

View File

@@ -56,7 +56,7 @@ function OutputStream(options) {
braces : false,
comments : false,
galio : false,
ie8 : false,
ie : false,
indent_level : 4,
indent_start : 0,
inline_script : true,
@@ -193,7 +193,7 @@ function OutputStream(options) {
case "\t": return "\\t";
case "\b": return "\\b";
case "\f": return "\\f";
case "\x0B": return options.ie8 ? "\\x0B" : "\\v";
case "\x0B": return options.ie ? "\\x0B" : "\\v";
case "\u2028": return "\\u2028";
case "\u2029": return "\\u2029";
case "\ufeff": return "\\ufeff";
@@ -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) {
@@ -980,7 +974,6 @@ function OutputStream(options) {
DEFPRINT(AST_Do, function(output) {
var self = this;
output.print("do");
output.space();
make_block(self.body, output);
output.space();
output.print("while");
@@ -997,7 +990,6 @@ function OutputStream(options) {
output.with_parens(function() {
self.condition.print(output);
});
output.space();
force_statement(self.body, output);
});
DEFPRINT(AST_For, function(output) {
@@ -1027,7 +1019,6 @@ function OutputStream(options) {
self.step.print(output);
}
});
output.space();
force_statement(self.body, output);
});
function print_for_enum(prefix, infix) {
@@ -1042,7 +1033,6 @@ function OutputStream(options) {
output.space();
self.object.print(output);
});
output.space();
force_statement(self.body, output);
};
}
@@ -1056,7 +1046,6 @@ function OutputStream(options) {
output.with_parens(function() {
self.expression.print(output);
});
output.space();
force_statement(self.body, output);
});
DEFPRINT(AST_ExportDeclaration, function(output) {
@@ -1295,7 +1284,7 @@ function OutputStream(options) {
function make_then(self, output) {
var b = self.body;
if (output.option("braces") && !(b instanceof AST_Const || b instanceof AST_Let)
|| output.option("ie8") && b instanceof AST_Do)
|| output.option("ie") && b instanceof AST_Do)
return make_block(b, output);
// The squeezer replaces "block"-s that contain only a single
// statement with the statement itself; technically, the AST
@@ -1325,16 +1314,16 @@ function OutputStream(options) {
output.with_parens(function() {
self.condition.print(output);
});
output.space();
if (self.alternative) {
make_then(self, output);
output.space();
output.print("else");
output.space();
if (self.alternative instanceof AST_If)
if (self.alternative instanceof AST_If) {
output.space();
self.alternative.print(output);
else
} else {
force_statement(self.alternative, output);
}
} else {
force_statement(self.body, output);
}
@@ -1520,7 +1509,7 @@ function OutputStream(options) {
var expr = self.expression;
expr.print(output);
var prop = self.property;
if (output.option("ie8") && RESERVED_WORDS[prop]) {
if (output.option("ie") && RESERVED_WORDS[prop]) {
output.print(self.optional ? "?.[" : "[");
output.add_mapping(self.end);
output.print_string(prop);
@@ -1634,7 +1623,19 @@ function OutputStream(options) {
var self = this;
var key = print_property_key(self, output);
var value = self.value;
if (key && value instanceof AST_SymbolDeclaration && key == get_symbol_name(value)) return;
if (key) {
if (value instanceof AST_DefaultValue) {
if (value.name instanceof AST_Symbol && key == get_symbol_name(value.name)) {
output.space();
output.print("=");
output.space();
value.value.print(output);
return;
}
} else if (value instanceof AST_Symbol) {
if (key == get_symbol_name(value)) return;
}
}
output.colon();
value.print(output);
});
@@ -1683,28 +1684,21 @@ function OutputStream(options) {
function print_property_key(self, output) {
var key = self.key;
if (key instanceof AST_Node) {
output.with_square(function() {
key.print(output);
});
} else if (output.option("quote_keys")) {
output.print_string(key);
if (key instanceof AST_Node) return output.with_square(function() {
key.print(output);
});
var quote = self.start && self.start.quote;
if (output.option("quote_keys") || quote && output.option("keep_quoted_props")) {
output.print_string(key, quote);
} else if ("" + +key == key && key >= 0) {
output.print(make_num(key));
} else if (self.private) {
output.print_name(key);
} else if (RESERVED_WORDS[key] ? !output.option("ie") : is_identifier_string(key)) {
output.print_name(key);
return key;
} else {
var quote = self.start && self.start.quote;
if (self.private) {
output.print_name(key);
} else if (RESERVED_WORDS[key] ? !output.option("ie8") : is_identifier_string(key)) {
if (quote && output.option("keep_quoted_props")) {
output.print_string(key, quote);
} else {
output.print_name(key);
return key;
}
} else {
output.print_string(key, quote);
}
output.print_string(key, quote);
}
}
DEFPRINT(AST_ObjectKeyVal, function(output) {
@@ -1836,6 +1830,7 @@ function OutputStream(options) {
} else if (stat instanceof AST_EmptyStatement) {
output.force_semicolon();
} else {
output.space();
stat.print(output);
}
}
@@ -1884,6 +1879,7 @@ function OutputStream(options) {
}
function make_block(stmt, output) {
output.space();
if (stmt instanceof AST_EmptyStatement) {
print_braced_empty(stmt, output);
} else if (stmt instanceof AST_BlockStatement) {

View File

@@ -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))
@@ -1535,12 +1543,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 +1569,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 +1729,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 +1832,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 +2144,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 +2241,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 +2252,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 +2319,7 @@ function parse($TEXT, options) {
}
}
return expr;
};
}
function maybe_unary(no_in) {
var start = S.token;

View File

@@ -118,7 +118,7 @@ function is_lhs(node, parent) {
AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
options = defaults(options, {
cache: null,
ie8: false,
ie: false,
});
// pass 1: setup scope chaining and handle definitions
@@ -211,7 +211,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
entangle(defun, scope);
} else if (node instanceof AST_SymbolLambda) {
var def = defun.def_function(node, node.name == "arguments" ? undefined : defun);
if (options.ie8) def.defun = defun.parent_scope.resolve();
if (options.ie) def.defun = defun.parent_scope.resolve();
} else if (node instanceof AST_SymbolLet) {
var def = scope.def_variable(node);
if (exported) def.exported = true;
@@ -351,7 +351,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
self.walk(tw);
// pass 3: fix up any scoping issue with IE8
if (options.ie8) self.walk(new TreeWalker(function(node) {
if (options.ie) self.walk(new TreeWalker(function(node) {
if (node instanceof AST_SymbolCatch) {
var scope = node.thedef.defun;
if (scope.name instanceof AST_SymbolLambda && scope.name.name == node.name) {
@@ -572,7 +572,7 @@ AST_Symbol.DEFMETHOD("definition", function() {
function _default_mangler_options(options) {
options = defaults(options, {
eval : false,
ie8 : false,
ie : false,
keep_fnames : false,
reserved : [],
toplevel : false,

View File

@@ -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;
});

View File

@@ -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.10",
"version": "3.14.3",
"engines": {
"node": ">=0.8.0"
},

View File

@@ -556,6 +556,75 @@ reduce_iife_3: {
node_version: ">=4"
}
reduce_lambda_1: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var f = () => {
console.log(a, b);
};
var a = "foo", b = 42;
f();
b = "bar";
f();
}
expect: {
var f = () => {
console.log("foo", b);
};
var b = 42;
f();
b = "bar";
f();
}
expect_stdout: [
"foo 42",
"foo bar",
]
node_version: ">=4"
}
reduce_lambda_2: {
options = {
evaluate: true,
passes: 2,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
(function(f, a, b) {
f = () => {
console.log(a, b);
};
a = "foo", b = 42;
f();
b = "bar";
f();
})();
}
expect: {
(function(f, a, b) {
f = () => {
console.log("foo", b);
};
b = 42;
f();
b = "bar";
f();
})();
}
expect_stdout: [
"foo 42",
"foo bar",
]
node_version: ">=4"
}
single_use_recursive: {
options = {
reduce_vars: true,

View File

@@ -227,7 +227,7 @@ inline_await_1_trim: {
console.log("PASS");
}
expect: {
void 0;
0;
console.log("PASS");
}
expect_stdout: "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"
@@ -2023,3 +2023,192 @@ issue_5034: {
expect_stdout: "PASS"
node_version: ">=8"
}
issue_5070: {
options = {
awaits: true,
side_effects: true,
}
input: {
(async function() {
try {
for await (var a of console.log("PASS"));
} catch (e) {}
})();
}
expect: {
(async function() {
try {
for await (var a of console.log("PASS"));
} catch (e) {}
})();
}
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"
}

View File

@@ -406,6 +406,27 @@ conditional_chain: {
expect_stdout: "PASS"
}
negated_if: {
options = {
booleans: true,
conditionals: true,
side_effects: true,
}
input: {
console.log(function(a) {
if (!a)
return a ? "FAIL" : "PASS";
}(!console));
}
expect: {
console.log(function(a) {
if (!a)
return "PASS";
}(!console));
}
expect_stdout: "PASS"
}
issue_3465_1: {
options = {
booleans: true,
@@ -634,3 +655,45 @@ issue_5028_3: {
}
expect_stdout: "-1"
}
issue_5041_1: {
options = {
booleans: true,
conditionals: true,
}
input: {
var a = 42;
if (a)
if ([ a = null ])
if (a)
console.log("FAIL");
else
console.log("PASS");
}
expect: {
var a = 42;
a && [ a = null ] && (a ? console.log("FAIL") : console.log("PASS"));
}
expect_stdout: "PASS"
}
issue_5041_2: {
options = {
booleans: true,
conditionals: true,
}
input: {
var a;
if (!a)
if (a = 42)
if (a)
console.log("PASS");
else
console.log("FAIL");
}
expect: {
var a;
a || (a = 42) && (a ? console.log("PASS") : console.log("FAIL"));
}
expect_stdout: "PASS"
}

View File

@@ -1157,7 +1157,7 @@ issue_4705: {
issue_4720: {
options = {
ie8: true,
ie: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -1629,7 +1629,7 @@ issue_4951_2: {
issue_4962_1: {
options = {
ie8: true,
ie: true,
inline: true,
reduce_vars: true,
unused: true,
@@ -1656,7 +1656,7 @@ issue_4962_1: {
issue_4962_2: {
options = {
ie8: true,
ie: true,
inline: true,
reduce_vars: true,
unused: true,
@@ -1875,3 +1875,225 @@ issue_5015_3: {
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5053_1: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
}
input: {
"use strict";
try {
console.log(new class A {
constructor() {
A = 42;
}
}());
} catch (e) {
console.log("PASS");
}
}
expect: {
"use strict";
try {
console.log(new class A {
constructor() {
A = 42;
}
}());
} catch (e) {
console.log("PASS");
}
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5053_2: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
}
input: {
"use strict";
try {
console.log(new class A {
f() {
A = 42;
}
}().f());
} catch (e) {
console.log("PASS");
}
}
expect: {
"use strict";
try {
console.log(new class A {
f() {
A = 42;
}
}().f());
} catch (e) {
console.log("PASS");
}
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5053_3: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
}
input: {
try {
console.log(new class A {
p = A = 42;
}().p);
} catch (e) {
console.log("PASS");
}
}
expect: {
try {
console.log(new class A {
p = A = 42;
}().p);
} catch (e) {
console.log("PASS");
}
}
expect_stdout: "PASS"
node_version: ">=12"
}
issue_5053_4: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
"use strict";
class A {
constructor() {
A = 42;
}
}
try {
console.log(new A());
} catch (e) {
console.log("PASS");
}
}
expect: {
"use strict";
class A {
constructor() {
A = 42;
}
}
try {
console.log(new A());
} catch (e) {
console.log("PASS");
}
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5082_1: {
options = {
inline: true,
reduce_vars: true,
unused: true,
}
input: {
(function() {
class A {
p = console.log("PASS");
q() {}
}
class B {
static P = new A();
}
})();
}
expect: {
(function() {
class A {
p = console.log("PASS");
q() {}
}
new A();
})();
}
expect_stdout: "PASS"
node_version: ">=12"
}
issue_5082_2: {
options = {
inline: true,
passes: 2,
reduce_vars: true,
unused: true,
}
input: {
(function() {
class A {
p = console.log("PASS");
q() {}
}
class B {
static P = new A();
}
})();
}
expect: {
void new class {
p = console.log("PASS");
q() {}
}();
}
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"
}

View File

@@ -6008,7 +6008,7 @@ issue_3215_1: {
options = {
collapse_vars: true,
evaluate: true,
ie8: false,
ie: false,
inline: true,
passes: 2,
side_effects: true,
@@ -6030,7 +6030,7 @@ issue_3215_2: {
options = {
collapse_vars: true,
evaluate: true,
ie8: true,
ie: true,
inline: true,
passes: 2,
side_effects: true,
@@ -6055,7 +6055,7 @@ issue_3215_3: {
options = {
collapse_vars: true,
evaluate: true,
ie8: false,
ie: false,
inline: true,
passes: 2,
side_effects: true,
@@ -6078,7 +6078,7 @@ issue_3215_4: {
options = {
collapse_vars: true,
evaluate: true,
ie8: true,
ie: true,
inline: true,
passes: 2,
side_effects: true,
@@ -9412,3 +9412,73 @@ 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"
}

View File

@@ -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"
}

View File

@@ -486,7 +486,7 @@ do_continue: {
catch_ie8_1: {
options = {
ie8: true,
ie: true,
unused: true,
}
input: {
@@ -506,7 +506,7 @@ catch_ie8_1: {
catch_ie8_2: {
options = {
dead_code: true,
ie8: true,
ie: true,
passes: 2,
toplevel: true,
unused: true,
@@ -727,7 +727,7 @@ issue_4193: {
issue_4195: {
mangle = {
ie8: true,
ie: true,
}
input: {
console.log(function f(a) {
@@ -1131,7 +1131,7 @@ issue_4225: {
issue_4229: {
options = {
ie8: true,
ie: true,
side_effects: true,
}
input: {
@@ -1151,7 +1151,7 @@ issue_4229: {
issue_4231: {
options = {
ie8: true,
ie: true,
side_effects: true,
}
input: {

View File

@@ -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"
}

View File

@@ -70,7 +70,7 @@ object_shorthand_assign: {
({ a = "PASS" } = 42);
console.log(a);
}
expect_exact: '({a:a="PASS"}=42);console.log(a);'
expect_exact: '({a="PASS"}=42);console.log(a);'
expect_stdout: "PASS"
node_version: ">=6"
}
@@ -80,7 +80,7 @@ object_shorthand_declaration: {
var { a = "PASS" } = 42;
console.log(a);
}
expect_exact: 'var{a:a="PASS"}=42;console.log(a);'
expect_exact: 'var{a="PASS"}=42;console.log(a);'
expect_stdout: "PASS"
node_version: ">=6"
}
@@ -91,7 +91,7 @@ object_shorthand_function: {
console.log(a);
})(42);
}
expect_exact: '(function({a:a="PASS"}){console.log(a)})(42);'
expect_exact: '(function({a="PASS"}){console.log(a)})(42);'
expect_stdout: "PASS"
node_version: ">=6"
}
@@ -149,7 +149,7 @@ process_boolean_returns: {
}
expect: {
console.log(function(a = console.log("FAIL 1")) {
return a() ? "PASS" : "FAIL 2";
return 42 ? "PASS" : "FAIL 2";
}(function() {
return 1;
}));
@@ -245,21 +245,64 @@ maintain_if: {
node_version: ">=6"
}
reduce_value: {
reduce_funarg: {
options = {
evaluate: true,
keep_fargs: false,
reduce_vars: true,
unused: true,
}
input: {
console.log(function(a = "PASS") {
return a;
}());
console.log(...function(a = "foo", b = "bar", c = "baz") {
return [ a, b, c ];
}(void 0, null));
}
expect: {
console.log("PASS");
console.log(...function() {
return [ "foo", null, "baz" ];
}());
}
expect_stdout: "PASS"
expect_stdout: "foo null baz"
node_version: ">=6"
}
reduce_array: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
unused: true,
}
input: {
var [ a = "foo", b = "bar", c = "baz" ] = [ void 0, null ];
console.log(a, b, c);
}
expect: {
var [ c = "baz" ] = [];
console.log("foo", null, c);
}
expect_stdout: "foo null baz"
node_version: ">=6"
}
reduce_object: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
unused: true,
}
input: {
var { a = "foo", b = "bar", c = "baz" } = { a: void 0, b: null };
console.log(a, b, c);
}
expect: {
var { c = "baz" } = {};
console.log("foo", null, c);
}
expect_stdout: "foo null baz"
node_version: ">=6"
}
@@ -525,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,
@@ -676,7 +733,7 @@ unused_value_var_2: {
console.log(a);
}
expect: {
var [ a ] = [ "PASS" ];
var a = [ "PASS" ][0];
console.log(a);
}
expect_stdout: "PASS"
@@ -1257,7 +1314,7 @@ issue_4468: {
expect: {
(function() {
var {
[console.log("PASS")]: b = 0,
[console.log("PASS")]: b,
} = 0;
})();
}
@@ -1416,6 +1473,7 @@ issue_4502_1: {
expect: {
(function() {
var a = "PASS";
void 0,
console.log(a),
a++,
void 0;
@@ -1439,6 +1497,7 @@ issue_4502_2: {
expect: {
(function() {
var a = "PASS";
void 0,
console.log(a),
a++,
void 0;
@@ -1664,7 +1723,7 @@ issue_4588_2_evaluate: {
issue_4817: {
options = {
ie8: true,
ie: true,
inline: true,
unused: true,
}
@@ -1698,7 +1757,7 @@ issue_4854: {
}());
}
expect: {
console.log(void ([] = "foo"));
console.log(void 0);
}
expect_stdout: "undefined"
node_version: ">=6"
@@ -1754,3 +1813,128 @@ issue_4994: {
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5057_1: {
options = {
collapse_vars: true,
inline: true,
sequences: true,
unused: true,
}
input: {
var a = 42;
(function() {
var b = function(c = (console.log("foo"), b = a)) {
a && console.log("bar");
}();
})();
}
expect: {
var a = 42;
console.log("foo"),
void (a && console.log("bar"));
}
expect_stdout: [
"foo",
"bar",
]
node_version: ">=6"
}
issue_5057_2: {
options = {
inline: true,
unused: true,
}
input: {
(function f(a) {
(function(b = console.log("FAIL")) {})(a);
})(42);
console.log(typeof b);
}
expect: {
(function(a) {
[ b = console.log("FAIL") ] = [ a ],
void 0;
var b;
})(42);
console.log(typeof b);
}
expect_stdout: "undefined"
node_version: ">=6"
}
issue_5057_3: {
options = {
inline: true,
unused: true,
}
input: {
(function(a) {
(function f(b) {
(function(a = console.log("FAIL 1")) {})(b);
console.log(a);
})("FAIL 2");
})("PASS");
}
expect: {
(function(a) {
(function(b) {
(function(a = console.log("FAIL 1")) {})(b);
console.log(a);
})("FAIL 2");
})("PASS");
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5065: {
options = {
pure_getters: "strict",
toplevel: true,
unused: true,
}
input: {
var [ a = console.log("PASS") ] = [ (A = 42).p ];
}
expect: {
var [ a = console.log("PASS") ] = [ (A = 42).p ];
}
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"
}

View File

@@ -1105,7 +1105,7 @@ drop_unused_1: {
try {
throw 42;
} catch (a) {
var [ a ] = [];
var a = [][0];
}
}
}
@@ -1138,6 +1138,175 @@ drop_unused_2: {
node_version: ">=6"
}
drop_hole: {
options = {
unused: true,
}
input: {
var [ a ] = [ , ];
console.log(a);
}
expect: {
var a = [][0];
console.log(a);
}
expect_stdout: "undefined"
node_version: ">=6"
}
keep_key_1: {
options = {
evaluate: true,
side_effects: true,
unused: true,
}
input: {
({} = {
[(console.log("PASS"), 42)]: null,
});
}
expect: {
({} = {
[(console.log("PASS"), 42)]: 0,
});
}
expect_stdout: "PASS"
node_version: ">=6"
}
keep_key_2: {
options = {
evaluate: true,
toplevel: true,
unused: true,
}
input: {
var { 42: a } = { [(console.log("PASS"), 42)](){} };
}
expect: {
var {} = { [(console.log("PASS"), 42)]: 0 };
}
expect_stdout: "PASS"
node_version: ">=6"
}
keep_key_2_pure_getters: {
options = {
evaluate: true,
pure_getters: "strict",
toplevel: true,
unused: true,
}
input: {
var { 42: a } = { [(console.log("PASS"), 42)](){} };
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=6"
}
keep_reference: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = [ {}, 42 ];
var [ b, c ] = a;
console.log(a[0] === b ? "PASS" : "FAIL");
}
expect: {
var a = [ {}, 42 ];
var [ b ] = a;
console.log(a[0] === b ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
node_version: ">=6"
}
maintain_position_assign: {
options = {
unused: true,
}
input: {
console.log(([ , ] = [ , "PASS" ])[1]);
}
expect: {
console.log([ , "PASS" ][1]);
}
expect_stdout: "PASS"
node_version: ">=6"
}
maintain_position_var: {
options = {
toplevel: true,
unused: true,
}
input: {
A = "FAIL";
var [ a, b ] = [ A ];
console.log(b || "PASS");
}
expect: {
A = "FAIL";
var [ , b ] = [ A ];
console.log(b || "PASS");
}
expect_stdout: "PASS"
node_version: ">=6"
}
side_effects_array: {
options = {
unused: true,
}
input: {
try {
var [ a ] = 42;
} catch (e) {
console.log("PASS");
}
}
expect: {
try {
var [ a ] = 42;
} catch (e) {
console.log("PASS");
}
}
expect_stdout: "PASS"
node_version: ">=6"
}
side_effects_object: {
options = {
toplevel: true,
unused: true,
}
input: {
var a = null, b = console, { c } = 42;
try {
c[a = "PASS"];
} catch (e) {
console.log(a);
}
}
expect: {
var a = null, c = (console, 42["c"]);
try {
c[a = "PASS"];
} catch (e) {
console.log(a);
}
}
expect_stdout: "PASS"
node_version: ">=6"
}
join_vars: {
options = {
conditionals: true,
@@ -1860,7 +2029,7 @@ issue_4321: {
issue_4323: {
options = {
ie8: true,
ie: true,
inline: true,
merge_vars: true,
reduce_vars: true,
@@ -1958,7 +2127,7 @@ issue_4372_2: {
}
expect: {
var a;
[ a ] = [ "PASS", "FAIL" ];
[ a ] = a = [ "PASS", "FAIL" ];
console.log(a);
}
expect_stdout: "PASS"
@@ -2647,3 +2816,412 @@ issue_5017: {
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5071_1: {
options = {
unused: true,
}
input: {
var a;
console.log(([ , a ] = [ "PA", , ]).join("SS"));
}
expect: {
var a;
console.log(([ , a ] = [ "PA", , ]).join("SS"));
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5071_2: {
options = {
pure_getters: "strict",
unused: true,
}
input: {
var a;
([ a ] = []).p = console.log("PASS");
}
expect: {
var a;
([ a ] = []).p = console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5074_getter: {
options = {
evaluate: true,
side_effects: true,
unused: true,
}
input: {
({} = { get [(console.log("PASS"), 42)]() {} });
}
expect: {
({} = { [(console.log("PASS"), 42)]: 0 });
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5074_getter_pure_getters: {
options = {
evaluate: true,
pure_getters: "strict",
side_effects: true,
unused: true,
}
input: {
({} = { get [(console.log("PASS"), 42)]() {} });
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5074_setter: {
options = {
evaluate: true,
side_effects: true,
unused: true,
}
input: {
({} = { set [(console.log("PASS"), 42)](v) {} });
}
expect: {
({} = { [(console.log("PASS"), 42)]: 0 });
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5074_setter_pure_getters: {
options = {
evaluate: true,
pure_getters: "strict",
side_effects: true,
unused: true,
}
input: {
({} = { set [(console.log("PASS"), 42)](v) {} });
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5074_method: {
options = {
evaluate: true,
side_effects: true,
unused: true,
}
input: {
({} = { [(console.log("PASS"), 42)]() {} });
}
expect: {
({} = { [(console.log("PASS"), 42)]: 0 });
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5074_method_pure_getters: {
options = {
evaluate: true,
pure_getters: "strict",
side_effects: true,
unused: true,
}
input: {
({} = { [(console.log("PASS"), 42)]() {} });
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5085_1: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
unused: true,
}
input: {
var a = "PASS";
var [ b ] = [ 42, a ], c = b ? 0 : a = "FAIL";
console.log(a);
}
expect: {
var a = "PASS";
var b = [ 42 ][0];
b;
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5085_2: {
options = {
evaluate: true,
reduce_vars: true,
side_effects: true,
unsafe: true,
unused: true,
}
input: {
var a = "PASS";
(function(b) {
[ b ] = [ 42, a ];
var c = b ? 0 : a = "FAIL";
})();
console.log(a);
}
expect: {
var a = "PASS";
(function(b) {
b = [ 42 ][0];
})();
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5087_1: {
options = {
collapse_vars: true,
inline: true,
properties: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
var a = "PASS";
(function() {
(function() {
(function([ b ]) {
b && console.log(b);
})([ a ]);
})();
})();
}
expect: {
var a = "PASS";
(function() {
var b;
(b = a) && console.log(b);
})();
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5087_2: {
options = {
collapse_vars: true,
inline: true,
passes: 2,
properties: true,
reduce_vars: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
var a = "PASS";
(function() {
(function() {
(function([ b ]) {
b && console.log(b);
})([ a ]);
})();
})();
}
expect: {
var a = "PASS";
a && console.log(a);
}
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"
}

View File

@@ -795,9 +795,9 @@ issue_1656: {
beautify: true,
}
input: {
for(var a=0;;);
for (var a=0;;);
}
expect_exact: "for (;;) ;"
expect_exact: "for (;;);"
}
issue_1709: {
@@ -1110,7 +1110,7 @@ issue_1838: {
}
expect_exact: [
"function f() {",
" for (a; c; ) ;",
" for (a; c; );",
"}",
]
}
@@ -1557,9 +1557,9 @@ issue_2665: {
}
expect: {
var a = 1;
!function g() {
(function g() {
a-- && g();
}();
})();
console.log(a);
}
expect_stdout: "-1"
@@ -2345,7 +2345,7 @@ function_argument_reference: {
function_parameter_ie8: {
options = {
ie8: true,
ie: true,
reduce_vars: true,
unused: true,
}
@@ -3081,7 +3081,8 @@ issue_4235: {
}
expect: {
void function() {
var f = console.log(f);
var f;
console.log(f);
}();
}
expect_stdout: "undefined"
@@ -3229,7 +3230,7 @@ issue_4558_1: {
issue_4558_2: {
options = {
evaluate: true,
ie8: true,
ie: true,
reduce_vars: true,
unused: true,
}
@@ -3378,7 +3379,7 @@ issue_4834: {
}
expect: {
try {
void b.p;
b.p;
} catch (e) {
console.log("PASS");
}
@@ -3468,3 +3469,26 @@ issue_4912_3: {
}
expect_stdout: "PASS"
}
issue_5079: {
options = {
collapse_vars: true,
pure_getters: "strict",
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a;
do {
(a = 123456).p = a;
a.q = null;
} while (console.log("PASS"));
}
expect: {
do {
0, 0, null;
} while (console.log("PASS"));
}
expect_stdout: "PASS"
}

View File

@@ -684,26 +684,47 @@ prototype_function: {
side_effects: true,
}
input: {
var a = ({valueOf: 0}) < 1;
var b = ({toString: 0}) < 1;
var c = ({valueOf: 0}) + "";
var d = ({toString: 0}) + "";
var e = (({valueOf: 0}) + "")[2];
var f = (({toString: 0}) + "")[2];
var g = ({valueOf: 0}).valueOf();
var h = ({toString: 0}).toString();
function v() {
return this.valueOf === v ? "PASS" : "FAIL";
}
console.log(({ valueOf: v }) < 1);
console.log(({ valueOf: v }) + "");
console.log((( {valueOf: v }) + "")[2]);
console.log(({ valueOf: v }).valueOf());
function t() {
return this.toString === t ? "PASS" : "FAIL";
}
console.log(({ toString: t }) < 1);
console.log(({ toString: t }) + "");
console.log((( {toString: t }) + "")[2]);
console.log(({ toString: t }).toString());
}
expect: {
var a = ({valueOf: 0}) < 1;
var b = ({toString: 0}) < 1;
var c = ({valueOf: 0}) + "";
var d = ({toString: 0}) + "";
var e = (({valueOf: 0}) + "")[2];
var f = (({toString: 0}) + "")[2];
var g = 0();
var h = 0();
function v() {
return this.valueOf === v ? "PASS" : "FAIL";
}
console.log(({ valueOf: v }) < 1);
console.log(({ valueOf: v }) + "");
console.log((( {valueOf: v }) + "")[2]);
console.log(({ valueOf: v }).valueOf());
function t() {
return this.toString === t ? "PASS" : "FAIL";
}
console.log(({ toString: t }) < 1);
console.log(({ toString: t }) + "");
console.log((( {toString: t }) + "")[2]);
console.log(({ toString: t }).toString());
}
expect_stdout: true
expect_stdout: [
"false",
"PASS",
"S",
"PASS",
"false",
"PASS",
"S",
"PASS",
]
}
call_args: {

View File

@@ -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"

View File

@@ -249,7 +249,7 @@ hoist_exports_2: {
}
}
expect: {
let e, { foo: a } = 42;
let e, a = 42["foo"];
function f(t, { [e]: o }) {
t(o, f);
}

View File

@@ -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"
@@ -2123,7 +2123,7 @@ issue_3016_2: {
issue_3016_2_ie8: {
options = {
dead_code: true,
ie8: true,
ie: true,
inline: true,
toplevel: true,
}
@@ -2188,7 +2188,7 @@ issue_3016_3: {
issue_3016_3_ie8: {
options = {
dead_code: true,
ie8: true,
ie: true,
inline: true,
toplevel: true,
}
@@ -2826,6 +2826,36 @@ functions_use_strict: {
expect_stdout: "a true 42 function function function"
}
functions_cross_scope_reference: {
options = {
functions: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
log = function(fn) {
console.log(typeof fn());
};
var a = function() {};
function f() {
return a;
}
while (log(f));
}
expect: {
log = function(fn) {
console.log(typeof fn());
};
function a() {}
function f() {
return a;
}
while (log(f));
}
expect_stdout: "function"
}
functions_inner_var: {
options = {
functions: true,
@@ -2905,6 +2935,7 @@ issue_2437: {
issue_2485_1: {
options = {
functions: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
unused: true,
@@ -2955,6 +2986,7 @@ issue_2485_2: {
options = {
functions: true,
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
unused: true,
@@ -6283,3 +6315,343 @@ issue_5036: {
}
expect_stdout: "PASS"
}
issue_5046: {
options = {
conditionals: true,
evaluate: true,
keep_fnames: true,
passes: 2,
reduce_vars: true,
side_effects: true,
toplevel: true,
}
input: {
var a = 0;
if (a)
0();
else
(function f() {
f;
return a = "PASS";
})();
console.log(a);
}
expect: {
var a = 0;
(a ? 0 : function f() {
return a = "PASS";
})();
console.log(a);
}
expect_stdout: "PASS"
}
issue_5061_1: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
}
input: {
var f, a = 1;
(f = function() {
console.log(a ? "foo" : "bar");
})();
f(a = 0);
}
expect: {
var f, a = 1;
(f = function() {
console.log(a ? "foo" : "bar");
})();
f(a = 0);
}
expect_stdout: [
"foo",
"bar",
]
}
issue_5061_2: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var f, a = 1;
(f = function() {
console.log(a ? "foo" : "bar");
})();
f(a = 0);
}
expect: {
var f, a = 1;
(f = function() {
console.log(a ? "foo" : "bar");
})();
f(a = 0);
}
expect_stdout: [
"foo",
"bar",
]
}
issue_5067: {
options = {
inline: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var f = function() {
f();
};
}
expect: {}
}
issue_5096_1: {
options = {
evaluate: true,
passes: 2,
reduce_vars: true,
side_effects: true,
toplevel: true,
}
input: {
var a, b = "FAIL", c = 1;
do {
a && a();
a = function() {
b = "PASS";
};
} while (c--);
console.log(b);
}
expect: {
var a, b = "FAIL", c = 1;
do {
a && a();
a = function() {
b = "PASS";
};
} while (c--);
console.log(b);
}
expect_stdout: "PASS"
}
issue_5096_2: {
options = {
passes: 2,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var a, b = "FAIL", c = 1;
do {
a && a();
a = function() {
b = "PASS";
};
} while (c--);
console.log(b);
}
expect: {
var a, b = "FAIL", c = 1;
do {
a && a();
a = function() {
b = "PASS";
};
} while (c--);
console.log(b);
}
expect_stdout: "PASS"
}
issue_5096_3: {
options = {
evaluate: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
}
input: {
var b = "FAIL", c = 1;
do {
a && a();
var a = function() {
b = "PASS";
};
} while (c--);
console.log(b);
}
expect: {
var b = "FAIL", c = 1;
do {
a && a();
var a = function() {
b = "PASS";
};
} while (c--);
console.log(b);
}
expect_stdout: "PASS"
}
issue_5096_4: {
options = {
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var b = "FAIL", c = 1;
do {
a && a();
var a = function() {
b = "PASS";
};
} while (c--);
console.log(b);
}
expect: {
var b = "FAIL", c = 1;
do {
a && a();
var a = function() {
b = "PASS";
};
} while (c--);
console.log(b);
}
expect_stdout: "PASS"
}
issue_5098: {
options = {
reduce_vars: true,
unused: true,
}
input: {
(function(o) {
function f() {
f = console.log;
if (o.p++)
throw "FAIL";
f("PASS");
}
return f;
})({ p: 0 })();
}
expect: {
(function(o) {
function f() {
f = console.log;
if (o.p++)
throw "FAIL";
f("PASS");
}
return f;
})({ p: 0 })();
}
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"
}

View File

@@ -777,6 +777,32 @@ issue_3046: {
}
issue_3071_1: {
options = {
evaluate: true,
hoist_props: true,
inline: true,
join_vars: true,
passes: 3,
reduce_vars: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
(function() {
var obj = {};
obj.one = 1;
obj.two = 2;
console.log(obj.one, obj.two);
})();
}
expect: {
console.log(1, 2);
}
expect_stdout: "1 2"
}
issue_3071_1_toplevel: {
options = {
evaluate: true,
hoist_props: true,
@@ -1094,3 +1120,24 @@ object_super: {
expect_stdout: "PASS"
node_version: ">=4"
}
issue_4985: {
options = {
hoist_props: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a = { p: 42 };
console.log(function() {
a;
}());
}
expect: {
var a_p = 42;
console.log(function() {
({});
}());
}
expect_stdout: "undefined"
}

View File

@@ -152,7 +152,8 @@ issue_4487: {
}
expect: {
function a() {
var f = console.log(typeof f);
var f;
console.log(typeof f);
}
a();
}
@@ -322,9 +323,7 @@ issue_4893_1: {
expect: {
try{
(function f() {
var b;
b = null;
b.p += 42;
null.p += 42;
f;
})();
} catch (e) {

File diff suppressed because it is too large Load Diff

View File

@@ -24,7 +24,7 @@ typeof_eq_undefined: {
typeof_eq_undefined_ie8: {
options = {
comparisons: true,
ie8: true,
ie: true,
typeofs: true,
}
input: {

View File

@@ -1,9 +1,9 @@
screw_ie8: {
options = {
ie8: false,
ie: false,
}
mangle = {
ie8: false,
ie: false,
}
input: {
try { throw "foo"; } catch (x) { console.log(x); }
@@ -16,10 +16,10 @@ screw_ie8: {
support_ie8: {
options = {
ie8: true,
ie: true,
}
mangle = {
ie8: true,
ie: true,
}
input: {
try { throw "foo"; } catch (x) { console.log(x); }

View File

@@ -1,10 +1,10 @@
mangle_catch: {
options = {
ie8: false,
ie: false,
toplevel: false,
}
mangle = {
ie8: false,
ie: false,
toplevel: false,
}
input: {
@@ -22,11 +22,11 @@ mangle_catch: {
mangle_catch_ie8: {
options = {
ie8: true,
ie: true,
toplevel: false,
}
mangle = {
ie8: true,
ie: true,
toplevel: false,
}
input: {
@@ -44,11 +44,11 @@ mangle_catch_ie8: {
mangle_catch_var: {
options = {
ie8: false,
ie: false,
toplevel: false,
}
mangle = {
ie8: false,
ie: false,
toplevel: false,
}
input: {
@@ -66,11 +66,11 @@ mangle_catch_var: {
mangle_catch_var_ie8: {
options = {
ie8: true,
ie: true,
toplevel: false,
}
mangle = {
ie8: true,
ie: true,
toplevel: false,
}
input: {
@@ -88,11 +88,11 @@ mangle_catch_var_ie8: {
mangle_catch_toplevel: {
options = {
ie8: false,
ie: false,
toplevel: true,
}
mangle = {
ie8: false,
ie: false,
toplevel: true,
}
input: {
@@ -110,11 +110,11 @@ mangle_catch_toplevel: {
mangle_catch_ie8_toplevel: {
options = {
ie8: true,
ie: true,
toplevel: true,
}
mangle = {
ie8: true,
ie: true,
toplevel: true,
}
input: {
@@ -132,11 +132,11 @@ mangle_catch_ie8_toplevel: {
mangle_catch_var_toplevel: {
options = {
ie8: false,
ie: false,
toplevel: true,
}
mangle = {
ie8: false,
ie: false,
toplevel: true,
}
input: {
@@ -154,11 +154,11 @@ mangle_catch_var_toplevel: {
mangle_catch_var_ie8_toplevel: {
options = {
ie8: true,
ie: true,
toplevel: true,
}
mangle = {
ie8: true,
ie: true,
toplevel: true,
}
input: {
@@ -176,11 +176,11 @@ mangle_catch_var_ie8_toplevel: {
mangle_catch_redef_1: {
options = {
ie8: false,
ie: false,
toplevel: false,
}
mangle = {
ie8: false,
ie: false,
toplevel: false,
}
input: {
@@ -198,11 +198,11 @@ mangle_catch_redef_1: {
mangle_catch_redef_1_ie8: {
options = {
ie8: true,
ie: true,
toplevel: false,
}
mangle = {
ie8: true,
ie: true,
toplevel: false,
}
input: {
@@ -220,11 +220,11 @@ mangle_catch_redef_1_ie8: {
mangle_catch_redef_1_toplevel: {
options = {
ie8: false,
ie: false,
toplevel: true,
}
mangle = {
ie8: false,
ie: false,
toplevel: true,
}
input: {
@@ -242,11 +242,11 @@ mangle_catch_redef_1_toplevel: {
mangle_catch_redef_1_ie8_toplevel: {
options = {
ie8: true,
ie: true,
toplevel: true,
}
mangle = {
ie8: true,
ie: true,
toplevel: true,
}
input: {
@@ -264,11 +264,11 @@ mangle_catch_redef_1_ie8_toplevel: {
mangle_catch_redef_2: {
options = {
ie8: false,
ie: false,
toplevel: false,
}
mangle = {
ie8: false,
ie: false,
toplevel: false,
}
input: {
@@ -285,11 +285,11 @@ mangle_catch_redef_2: {
mangle_catch_redef_2_ie8: {
options = {
ie8: true,
ie: true,
toplevel: false,
}
mangle = {
ie8: true,
ie: true,
toplevel: false,
}
input: {
@@ -306,11 +306,11 @@ mangle_catch_redef_2_ie8: {
mangle_catch_redef_2_toplevel: {
options = {
ie8: false,
ie: false,
toplevel: true,
}
mangle = {
ie8: false,
ie: false,
toplevel: true,
}
input: {
@@ -327,11 +327,11 @@ mangle_catch_redef_2_toplevel: {
mangle_catch_redef_2_ie8_toplevel: {
options = {
ie8: true,
ie: true,
toplevel: true,
}
mangle = {
ie8: true,
ie: true,
toplevel: true,
}
input: {
@@ -348,7 +348,7 @@ mangle_catch_redef_2_ie8_toplevel: {
mangle_catch_redef_3: {
mangle = {
ie8: false,
ie: false,
toplevel: false,
}
input: {
@@ -371,7 +371,7 @@ mangle_catch_redef_3: {
mangle_catch_redef_3_toplevel: {
mangle = {
ie8: false,
ie: false,
toplevel: true,
}
input: {
@@ -394,7 +394,7 @@ mangle_catch_redef_3_toplevel: {
mangle_catch_redef_3_ie8: {
mangle = {
ie8: true,
ie: true,
toplevel: false,
}
input: {
@@ -417,7 +417,7 @@ mangle_catch_redef_3_ie8: {
mangle_catch_redef_3_ie8_toplevel: {
mangle = {
ie8: true,
ie: true,
toplevel: true,
}
input: {

View File

@@ -1,6 +1,6 @@
function_iife_catch: {
mangle = {
ie8: false,
ie: false,
}
input: {
function f(n) {
@@ -21,7 +21,7 @@ function_iife_catch: {
function_iife_catch_ie8: {
mangle = {
ie8: true,
ie: true,
}
input: {
function f(n) {
@@ -42,7 +42,7 @@ function_iife_catch_ie8: {
function_catch_catch: {
mangle = {
ie8: false,
ie: false,
}
input: {
var o = 0;
@@ -70,7 +70,7 @@ function_catch_catch: {
function_catch_catch_ie8: {
mangle = {
ie8: true,
ie: true,
}
input: {
var o = 0;

View File

@@ -951,7 +951,7 @@ function_name_mangle_ie8: {
unused: true,
}
mangle = {
ie8: true,
ie: true,
toplevel: true,
}
input: {

View File

@@ -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: {

View File

@@ -494,6 +494,41 @@ reduce_vars_3: {
node_version: ">=4"
}
reduce_lambda: {
options = {
evaluate: true,
functions: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
"use strict";
let f = function() {
console.log(a, b);
};
let a = "foo", b = 42;
f();
b = "bar";
f();
}
expect: {
"use strict";
function f() {
console.log("foo", b);
}
let b = 42;
f();
b = "bar";
f();
}
expect_stdout: [
"foo 42",
"foo bar",
]
node_version: ">=4"
}
hoist_props: {
options = {
hoist_props: true,
@@ -1129,7 +1164,7 @@ issue_4225: {
issue_4229: {
options = {
ie8: true,
ie: true,
side_effects: true,
}
input: {
@@ -1160,7 +1195,7 @@ issue_4229: {
issue_4231: {
options = {
ie8: true,
ie: true,
side_effects: true,
}
input: {
@@ -1529,7 +1564,7 @@ issue_4438: {
issue_4531_1: {
mangle = {
ie8: true,
ie: true,
toplevel: true,
}
input: {
@@ -1555,11 +1590,11 @@ issue_4531_1: {
issue_4531_2: {
options = {
evaluate: true,
ie8: true,
ie: true,
toplevel: true,
}
mangle = {
ie8: true,
ie: true,
toplevel: true,
}
input: {

View File

@@ -193,9 +193,9 @@ evaluate: {
} while (false);
}
expect: {
for(;;)
for (;;)
a();
for(;;)
for (;;)
c();
d();
}
@@ -265,7 +265,7 @@ issue_1532_2: {
issue_186: {
beautify = {
beautify: false,
ie8: false,
ie: false,
}
input: {
var x = 3;
@@ -284,7 +284,7 @@ issue_186: {
issue_186_ie8: {
beautify = {
beautify: false,
ie8: true,
ie: true,
}
input: {
var x = 3;
@@ -303,7 +303,7 @@ issue_186_ie8: {
issue_186_beautify: {
beautify = {
beautify: true,
ie8: false,
ie: false,
}
input: {
var x = 3;
@@ -330,7 +330,7 @@ issue_186_beautify: {
issue_186_beautify_ie8: {
beautify = {
beautify: true,
ie8: true,
ie: true,
}
input: {
var x = 3;
@@ -360,7 +360,7 @@ issue_186_braces: {
beautify = {
beautify: false,
braces: true,
ie8: false,
ie: false,
}
input: {
var x = 3;
@@ -380,7 +380,7 @@ issue_186_braces_ie8: {
beautify = {
beautify: false,
braces: true,
ie8: true,
ie: true,
}
input: {
var x = 3;
@@ -400,7 +400,7 @@ issue_186_beautify_braces: {
beautify = {
beautify: true,
braces: true,
ie8: false,
ie: false,
}
input: {
var x = 3;
@@ -432,7 +432,7 @@ issue_186_beautify_braces_ie8: {
beautify = {
beautify: true,
braces: true,
ie8: true,
ie: true,
}
input: {
var x = 3;

View File

@@ -359,7 +359,7 @@ issue_4107: {
issue_4109: {
options = {
ie8: true,
ie: true,
merge_vars: true,
toplevel: true,
}
@@ -2735,8 +2735,7 @@ issue_4135: {
0;
a++;
if (!a)
c = (a++, c = 0, void (c && c.p));
var c;
var c = void a++;
console.log(a, -1, c);
}
expect_stdout: "1 -1 undefined"

View File

@@ -265,7 +265,7 @@ de_morgan_2e: {
issue_4679: {
options = {
comparisons: true,
ie8: true,
ie: true,
}
input: {
var a;

View File

@@ -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,
@@ -256,7 +369,7 @@ issue_4906: {
issue_4928: {
options = {
ie8: true,
ie: true,
toplevel: true,
unused: true,
}
@@ -305,3 +418,51 @@ issue_4947_2: {
expect_stdout: "PASS"
node_version: ">=14"
}
issue_5039: {
options = {
ie: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var a = a?.[function f() {
f;
a;
}];
console.log("PASS");
}
expect: {
(function f() {});
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=14"
}
issue_5091: {
options = {
merge_vars: true,
}
input: {
function f(a) {
var b = a.p;
var c;
b?.[c = "FAIL 2"];
return b || c;
}
console.log(f("FAIL 1") || "PASS");
}
expect: {
function f(b) {
var b = b.p;
var c;
b?.[c = "FAIL 2"];
return b || c;
}
console.log(f("FAIL 1") || "PASS");
}
expect_stdout: "PASS"
node_version: ">=14"
}

View File

@@ -17,7 +17,7 @@ dot_properties: {
properties: true,
}
beautify = {
ie8: true,
ie: true,
}
input: {
a["foo"] = "bar";
@@ -43,7 +43,7 @@ dot_properties_es5: {
properties: true,
}
beautify = {
ie8: false,
ie: false,
}
input: {
a["foo"] = "bar";
@@ -1463,3 +1463,50 @@ issue_4888: {
}
expect_stdout: "object"
}
issue_5093: {
beautify = {
keep_quoted_props: true,
}
input: {
console.log({
a: true,
'42': "PASS",
"null": [],
}[6 * 7]);
}
expect_exact: 'console.log({a:true,"42":"PASS","null":[]}[6*7]);'
expect_stdout: "PASS"
}
issue_5093_quote_keys: {
beautify = {
keep_quoted_props: true,
quote_keys: true,
}
input: {
console.log({
a: true,
'42': "PASS",
"null": [],
}[6 * 7]);
}
expect_exact: 'console.log({"a":true,"42":"PASS","null":[]}[6*7]);'
expect_stdout: "PASS"
}
issue_5093_quote_style: {
beautify = {
keep_quoted_props: true,
quote_style: 3,
}
input: {
console.log({
a: true,
'42': "PASS",
"null": [],
}[6 * 7]);
}
expect_exact: 'console.log({a:true,\'42\':"PASS","null":[]}[6*7]);'
expect_stdout: "PASS"
}

View File

@@ -1320,6 +1320,7 @@ issue_2878: {
issue_3427: {
options = {
assignments: true,
evaluate: true,
inline: true,
pure_getters: "strict",

View File

@@ -1292,6 +1292,7 @@ toplevel_on_loops_3: {
loops: true,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
@@ -3092,7 +3093,7 @@ accessor_1: {
a = 2;
return a;
},
b: 1
b: 1,
}.b, a);
}
expect: {
@@ -3102,7 +3103,7 @@ accessor_1: {
a = 2;
return a;
},
b: 1
b: 1,
}.b, a);
}
expect_stdout: "1 1"
@@ -3122,7 +3123,7 @@ accessor_2: {
var B = {
get c() {
console.log(A);
}
},
};
B.c;
}
@@ -3130,7 +3131,7 @@ accessor_2: {
({
get c() {
console.log(1);
}
},
}).c;
}
expect_stdout: "1"
@@ -3176,7 +3177,7 @@ obj_var_1: {
var obj = {
bar: function() {
return C + C;
}
},
};
console.log(obj.bar());
}
@@ -3184,7 +3185,7 @@ obj_var_1: {
console.log({
bar: function() {
return 2;
}
},
}.bar());
}
expect_stdout: "2"
@@ -3208,7 +3209,7 @@ obj_var_2: {
var obj = {
bar: function() {
return C + C;
}
},
};
console.log(obj.bar());
}
@@ -4422,6 +4423,7 @@ perf_2: {
perf_3: {
options = {
passes: 2,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
@@ -4430,10 +4432,10 @@ perf_3: {
input: {
var foo = function(x, y, z) {
return x < y ? x * y + z : x * z - y;
}
};
var indirect_foo = function(x, y, z) {
return foo(x, y, z);
}
};
var sum = 0;
for (var i = 0; i < 100; ++i)
sum += indirect_foo(i, i + 1, 3 * i);
@@ -4462,10 +4464,10 @@ perf_4: {
input: {
var foo = function(x, y, z) {
return x < y ? x * y + z : x * z - y;
}
};
var indirect_foo = function(x, y, z) {
return foo(x, y, z);
}
};
var sum = 0;
for (var i = 0; i < 100; ++i)
sum += indirect_foo(i, i + 1, 3 * i);
@@ -4474,10 +4476,10 @@ perf_4: {
expect: {
var foo = function(x, y, z) {
return x < y ? x * y + z : x * z - y;
}
};
var indirect_foo = function(x, y, z) {
return foo(x, y, z);
}
};
var sum = 0;
for (var i = 0; i < 100; ++i)
sum += indirect_foo(i, i + 1, 3 * i);
@@ -4566,9 +4568,9 @@ perf_7: {
var indirect_foo = function(x, y, z) {
var foo = function(x, y, z) {
return x < y ? x * y + z : x * z - y;
}
};
return foo(x, y, z);
}
};
var sum = 0;
for (var i = 0; i < 100; ++i)
sum += indirect_foo(i, i + 1, 3 * i);
@@ -4598,9 +4600,9 @@ perf_8: {
var indirect_foo = function(x, y, z) {
var foo = function(x, y, z) {
return x < y ? x * y + z : x * z - y;
}
};
return foo(x, y, z);
}
};
var sum = 0;
for (var i = 0; i < 100; ++i)
sum += indirect_foo(i, i + 1, 3 * i);
@@ -4611,7 +4613,7 @@ perf_8: {
return function(x, y, z) {
return x < y ? x * y + z : x * z - y;
}(x, y, z);
}
};
var sum = 0;
for (var i = 0; i < 100; ++i)
sum += indirect_foo(i, i + 1, 3 * i);
@@ -7676,3 +7678,97 @@ issue_4949: {
}
expect_stdout: "0 1"
}
issue_5048: {
options = {
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
console.log(function() {
var a = function() {
return a + 42;
};
}());
}
expect: {
console.log(function() {}());
}
expect_stdout: "undefined"
}
issue_5050: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
}
input: {
function f() {
console.log(a);
}
this;
var a = 1;
f(console.log(2), f(), a = 3);
}
expect: {
function f() {
console.log(a);
}
this;
var a = 1;
f(console.log(2), f(), a = 3);
}
expect_stdout: [
"2",
"1",
"3",
]
}
issue_5055_1: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a = "PASS";
function f() {
console.log(a || "FAIL");
}
f(0 && (a = 0)(f(this)));
}
expect: {
var a = "PASS";
function f() {
console.log(a || "FAIL");
}
f(0);
}
expect_stdout: "PASS"
}
issue_5055_2: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = "PASS";
function f() {
console.log(a || "FAIL");
}
f(0 && (a = 0)(f(this)));
}
expect: {
var a = "PASS";
function f() {
console.log(a || "FAIL");
}
f(0 && (a = 0)(f()));
}
expect_stdout: "PASS"
}

View File

@@ -1,11 +1,11 @@
mangle_catch: {
rename = true
options = {
ie8: false,
ie: false,
toplevel: false,
}
mangle = {
ie8: false,
ie: false,
toplevel: false,
}
input: {
@@ -24,11 +24,11 @@ mangle_catch: {
mangle_catch_ie8: {
rename = true
options = {
ie8: true,
ie: true,
toplevel: false,
}
mangle = {
ie8: true,
ie: true,
toplevel: false,
}
input: {
@@ -47,11 +47,11 @@ mangle_catch_ie8: {
mangle_catch_var: {
rename = true
options = {
ie8: false,
ie: false,
toplevel: false,
}
mangle = {
ie8: false,
ie: false,
toplevel: false,
}
input: {
@@ -70,11 +70,11 @@ mangle_catch_var: {
mangle_catch_var_ie8: {
rename = true
options = {
ie8: true,
ie: true,
toplevel: false,
}
mangle = {
ie8: true,
ie: true,
toplevel: false,
}
input: {
@@ -93,11 +93,11 @@ mangle_catch_var_ie8: {
mangle_catch_toplevel: {
rename = true
options = {
ie8: false,
ie: false,
toplevel: true,
}
mangle = {
ie8: false,
ie: false,
toplevel: true,
}
input: {
@@ -116,11 +116,11 @@ mangle_catch_toplevel: {
mangle_catch_ie8_toplevel: {
rename = true
options = {
ie8: true,
ie: true,
toplevel: true,
}
mangle = {
ie8: true,
ie: true,
toplevel: true,
}
input: {
@@ -139,11 +139,11 @@ mangle_catch_ie8_toplevel: {
mangle_catch_var_toplevel: {
rename = true
options = {
ie8: false,
ie: false,
toplevel: true,
}
mangle = {
ie8: false,
ie: false,
toplevel: true,
}
input: {
@@ -162,11 +162,11 @@ mangle_catch_var_toplevel: {
mangle_catch_var_ie8_toplevel: {
rename = true
options = {
ie8: true,
ie: true,
toplevel: true,
}
mangle = {
ie8: true,
ie: true,
toplevel: true,
}
input: {
@@ -185,11 +185,11 @@ mangle_catch_var_ie8_toplevel: {
mangle_catch_redef_1: {
rename = true
options = {
ie8: false,
ie: false,
toplevel: false,
}
mangle = {
ie8: false,
ie: false,
toplevel: false,
}
input: {
@@ -208,11 +208,11 @@ mangle_catch_redef_1: {
mangle_catch_redef_1_ie8: {
rename = true
options = {
ie8: true,
ie: true,
toplevel: false,
}
mangle = {
ie8: true,
ie: true,
toplevel: false,
}
input: {
@@ -231,11 +231,11 @@ mangle_catch_redef_1_ie8: {
mangle_catch_redef_1_toplevel: {
rename = true
options = {
ie8: false,
ie: false,
toplevel: true,
}
mangle = {
ie8: false,
ie: false,
toplevel: true,
}
input: {
@@ -254,11 +254,11 @@ mangle_catch_redef_1_toplevel: {
mangle_catch_redef_1_ie8_toplevel: {
rename = true
options = {
ie8: true,
ie: true,
toplevel: true,
}
mangle = {
ie8: true,
ie: true,
toplevel: true,
}
input: {
@@ -277,11 +277,11 @@ mangle_catch_redef_1_ie8_toplevel: {
mangle_catch_redef_2: {
rename = true
options = {
ie8: false,
ie: false,
toplevel: false,
}
mangle = {
ie8: false,
ie: false,
toplevel: false,
}
input: {
@@ -299,11 +299,11 @@ mangle_catch_redef_2: {
mangle_catch_redef_2_ie8: {
rename = true
options = {
ie8: true,
ie: true,
toplevel: false,
}
mangle = {
ie8: true,
ie: true,
toplevel: false,
}
input: {
@@ -321,11 +321,11 @@ mangle_catch_redef_2_ie8: {
mangle_catch_redef_2_toplevel: {
rename = true
options = {
ie8: false,
ie: false,
toplevel: true,
}
mangle = {
ie8: false,
ie: false,
toplevel: true,
}
input: {
@@ -343,11 +343,11 @@ mangle_catch_redef_2_toplevel: {
mangle_catch_redef_2_ie8_toplevel: {
rename = true
options = {
ie8: true,
ie: true,
toplevel: true,
}
mangle = {
ie8: true,
ie: true,
toplevel: true,
}
input: {
@@ -365,7 +365,7 @@ mangle_catch_redef_2_ie8_toplevel: {
issue_2120_1: {
rename = true
mangle = {
ie8: false,
ie: false,
}
input: {
"aaaaaaaa";
@@ -401,7 +401,7 @@ issue_2120_1: {
issue_2120_2: {
rename = true
mangle = {
ie8: true,
ie: true,
}
input: {
"aaaaaaaa";
@@ -436,7 +436,7 @@ issue_2120_2: {
function_iife_catch: {
rename = true
mangle = {
ie8: false,
ie: false,
}
input: {
function f(n) {
@@ -458,7 +458,7 @@ function_iife_catch: {
function_iife_catch_ie8: {
rename = true
mangle = {
ie8: true,
ie: true,
}
input: {
function f(n) {
@@ -480,7 +480,7 @@ function_iife_catch_ie8: {
function_catch_catch: {
rename = true
mangle = {
ie8: false,
ie: false,
}
input: {
var o = 0;
@@ -509,7 +509,7 @@ function_catch_catch: {
function_catch_catch_ie8: {
rename = true
mangle = {
ie8: true,
ie: true,
}
input: {
var o = 0;
@@ -538,12 +538,12 @@ function_catch_catch_ie8: {
function_do_catch_ie8: {
rename = true
options = {
ie8: true,
ie: true,
side_effects: true,
unused: true,
}
mangle = {
ie8: true,
ie: true,
toplevel: true,
}
input: {
@@ -615,7 +615,7 @@ function_do_catch_ie8: {
issue_3480: {
rename = true,
mangle = {
ie8: false,
ie: false,
toplevel: false,
}
input: {
@@ -647,7 +647,7 @@ issue_3480: {
issue_3480_ie8: {
rename = true,
mangle = {
ie8: true,
ie: true,
toplevel: false,
}
input: {
@@ -679,7 +679,7 @@ issue_3480_ie8: {
issue_3480_toplevel: {
rename = true,
mangle = {
ie8: false,
ie: false,
toplevel: true,
}
input: {
@@ -711,7 +711,7 @@ issue_3480_toplevel: {
issue_3480_ie8_toplevel: {
rename = true,
mangle = {
ie8: true,
ie: true,
toplevel: true,
}
input: {

View File

@@ -244,7 +244,7 @@ retain_destructured_array: {
console.log.apply(console, b);
}
expect: {
var [ , ...b ] = [ "FAIL", "PASS", 42 ];
var [ ...b ] = [ "PASS", 42 ];
console.log.apply(console, b);
}
expect_stdout: "PASS 42"
@@ -284,7 +284,7 @@ retain_destructured_object_2: {
console.log(k, b[k]);
}
expect: {
var { foo: [], ...b } = { foo: [ "FAIL" ], bar: "PASS", baz: 42 };
var { foo: {}, ...b } = { foo: 0, bar: "PASS", baz: 42 };
for (var k in b)
console.log(k, b[k]);
}
@@ -407,6 +407,24 @@ drop_unused_call_args_2: {
node_version: ">=6"
}
maintain_position: {
options = {
unused: true,
}
input: {
A = "FAIL";
var [ , ...a ] = [ A, "PASS" ];
console.log(a[0]);
}
expect: {
A = "FAIL";
var [ , ...a ] = [ A, "PASS" ];
console.log(a[0]);
}
expect_stdout: "PASS"
node_version: ">=6"
}
merge_funarg: {
options = {
merge_vars: true,
@@ -491,7 +509,7 @@ drop_rest_array: {
rests: true,
}
input: {
var [ ...[ a ]] = [ "PASS" ];
var [ ...[ a ] ] = [ "PASS" ];
console.log(a);
}
expect: {
@@ -542,6 +560,100 @@ drop_rest_lambda: {
node_version: ">=6"
}
keep_rest_array: {
options = {
rests: true,
}
input: {
var [ ...[ ...a ] ] = "PASS";
console.log(a.join(""));
}
expect: {
var [ ...a ] = "PASS";
console.log(a.join(""));
}
expect_stdout: "PASS"
node_version: ">=6"
}
keep_rest_arrow: {
options = {
arrows: true,
keep_fargs: false,
reduce_vars: true,
rests: true,
}
input: {
console.log(((...[ ...a ]) => a.join(""))("PASS"));
}
expect: {
console.log(((...a) => a.join(""))("PASS"));
}
expect_stdout: "PASS"
node_version: ">=6"
}
keep_rest_lambda_1: {
options = {
keep_fargs: false,
reduce_vars: true,
rests: true,
toplevel: true,
}
input: {
function f(...[ ...a ]) {
return a.join("");
}
console.log(f("PASS"), f([ 42 ]));
}
expect: {
function f(...a) {
return a.join("");
}
console.log(f("PASS"), f([ 42 ]));
}
expect_stdout: "PASS 42"
node_version: ">=6"
}
keep_rest_lambda_2: {
options = {
unused: true,
}
input: {
function f(...[ ...a ]) {
return a.join("");
}
console.log(f("PASS"), f([ 42 ]));
}
expect: {
function f(...[ ...a ]) {
return a.join("");
}
console.log(f("PASS"), f([ 42 ]));
}
expect_stdout: "PASS 42"
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,
@@ -647,6 +759,78 @@ issue_4544_2: {
node_version: ">=6"
}
issue_4560_1: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a = 0;
(function(...{
[a++]: {},
}) {})(2);
console.log(a);
}
expect: {
var a = 0;
(function(...{
[a++]: {},
}) {})(2);
console.log(a);
}
expect_stdout: "1"
node_version: ">=6"
}
issue_4560_2: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = 0;
(function(...{
[a++]: {},
}) {})(2);
console.log(a);
}
expect: {
var a = 0;
(function(...{
[a++]: {},
}) {})(2);
console.log(a);
}
expect_stdout: "1"
node_version: ">=6"
}
issue_4560_3: {
options = {
collapse_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a = 0, b;
[ ...{
[a++]: b,
} ] = [ "PASS" ];
console.log(b);
}
expect: {
var a = 0, b;
[ ...{
[a++]: b,
} ] = [ "PASS" ];
console.log(b);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_4562: {
options = {
evaluate: true,
@@ -667,7 +851,7 @@ issue_4562: {
issue_4575: {
options = {
collapse_vars: true,
ie8: true,
ie: true,
reduce_vars: true,
rests: true,
unused: true,
@@ -777,10 +961,193 @@ issue_4666: {
expect: {
var a = 0, b = 0;
var o = (c => +a + c)([ b ]);
for(var k in o)
for (var k in o)
b++;
console.log(1, b);
}
expect_stdout: "1 2"
node_version: ">=6"
}
issue_5089_1: {
options = {
unused: true,
}
input: {
var {
p: [] = 42,
...o
} = {
p: [],
};
console.log(o.p);
}
expect: {
var {
p: {},
...o
} = {
p: 0,
};
console.log(o.p);
}
expect_stdout: "undefined"
node_version: ">=8"
}
issue_5089_2: {
options = {
pure_getters: "strict",
unused: true,
}
input: {
var {
p: {} = null,
...o
} = {
p: {},
};
console.log(o.p);
}
expect: {
var {
p: {},
...o
} = {
p: 0,
};
console.log(o.p);
}
expect_stdout: "undefined"
node_version: ">=8"
}
issue_5100_1: {
options = {
passes: 2,
pure_getters: "strict",
side_effects: true,
unused: true,
}
input: {
var a;
[ {
p: {},
...a
} ] = [ {
p: {
q: a,
} = 42,
r: "PASS",
} ];
console.log(a.r);
}
expect: {
var a;
[ {
p: {},
...a
} ] = [ {
p: [ a = 42["q"] ],
r: "PASS",
} ];
console.log(a.r);
}
expect_stdout: "PASS"
node_version: ">=8"
}
issue_5100_2: {
options = {
passes: 2,
pure_getters: "strict",
side_effects: true,
unused: true,
}
input: {
var a;
[ {
p: {},
...a
} ] = [ {
p: (console.log("PASS"), {
q: a,
} = 42),
} ];
}
expect: {
var a;
[ {
p: {},
...a
} ] = [ {
p: [ console.log("PASS"), a = 42["q"] ],
} ];
}
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"
}

View File

@@ -945,78 +945,6 @@ issue_4556: {
node_version: ">=6"
}
issue_4560_1: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a = 0;
(function(...{
[a++]: {},
}) {})(2);
console.log(a);
}
expect: {
var a = 0;
(function(...{
[a++]: {},
}) {})(2);
console.log(a);
}
expect_stdout: "1"
node_version: ">=6"
}
issue_4560_2: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = 0;
(function(...{
[a++]: {},
}) {})(2);
console.log(a);
}
expect: {
var a = 0;
(function(...{
[a++]: {},
}) {})(2);
console.log(a);
}
expect_stdout: "1"
node_version: ">=6"
}
issue_4560_3: {
options = {
collapse_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a = 0, b;
[ ...{
[a++]: b,
} ] = [ "PASS" ];
console.log(b);
}
expect: {
var a = 0, b;
[ ...{
[a++]: b,
} ] = [ "PASS" ];
console.log(b);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_4614: {
options = {
pure_getters: "strict",

View File

@@ -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,212 @@ 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"
}

View File

@@ -95,7 +95,7 @@ while_if_break: {
}
}
expect: {
for(; a && (b && c && d, !e););
for (; a && (b && c && d, !e););
}
}

View File

@@ -61,7 +61,7 @@ lambda_name_mangle: {
lambda_name_mangle_ie8: {
mangle = {
ie8: true,
ie: true,
toplevel: true,
}
input: {
@@ -95,7 +95,7 @@ function_name_mangle_ie8: {
unused: true,
}
mangle = {
ie8: true,
ie: true,
toplevel: true,
}
input: {

View File

@@ -1246,3 +1246,32 @@ issue_5034: {
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5076: {
options = {
evaluate: true,
hoist_vars: true,
passes: 2,
pure_getters: "strict",
side_effects: true,
toplevel: true,
unused: true,
yields: true,
}
input: {
var a;
console.log("PASS");
var b = function*({
p: {},
}) {}({
p: { a } = 42,
});
}
expect: {
var a;
console.log("PASS");
a = 42["a"];
}
expect_stdout: "PASS"
node_version: ">=6"
}

View File

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

View File

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

View File

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

View File

@@ -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,

View File

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

View File

@@ -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';

View File

@@ -1,21 +0,0 @@
var assert = require("assert");
var UglifyJS = require("../..");
describe("ie8", function() {
it("Should be able to minify() with undefined as catch parameter in a try...catch statement", function() {
assert.strictEqual(
UglifyJS.minify([
"function a(b){",
" try {",
" throw 'Stuff';",
" } catch (undefined) {",
" console.log('caught: ' + undefined);",
" }",
" console.log('undefined is ' + undefined);",
" return b === undefined;",
"};",
].join("\n")).code,
'function a(o){try{throw"Stuff"}catch(o){console.log("caught: "+o)}return console.log("undefined is "+void 0),void 0===o}'
);
});
});

View File

@@ -1,5 +1,5 @@
var assert = require("assert");
var UglifyJS = require("../..");
var UglifyJS = require("../node");
describe("let", function() {
this.timeout(30000);
@@ -41,7 +41,7 @@ describe("let", function() {
}
var result = UglifyJS.minify(s, {
compress: false,
ie8: true,
ie: true,
mangle: {
properties: true,
}
@@ -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);
});
});
});

View File

@@ -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)";

View File

@@ -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;

View File

@@ -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() {

View File

@@ -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";

View File

@@ -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`" ],

View File

@@ -22,7 +22,7 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
reduce_options = reduce_options || {};
var print_options = {};
[
"ie8",
"ie",
"v8",
"webkit",
].forEach(function(name) {
@@ -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))) {
@@ -726,7 +726,7 @@ function to_statement_init(node) {
return node instanceof U.AST_Const || node instanceof U.AST_Let ? new U.AST_BlockStatement({
body: [ node ],
start: {},
}) : to_statement(node);;
}) : to_statement(node);
}
function wrap_with_console_log(node) {

View File

@@ -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, ",");
@@ -278,11 +278,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) {

View File

@@ -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) {
@@ -2256,7 +2258,7 @@ function sort_globals(code) {
return (typeof global[n] == "function") - (typeof global[m] == "function")
|| (m < n ? -1 : m > n ? 1 : 0);
};
} + "(this));" + code);
} + "(this));\n" + code);
if (!Array.isArray(globals)) {
errorln();
errorln();
@@ -2294,6 +2296,20 @@ function fuzzy_match(original, uglified) {
}
}
function patch_proto() {
[ Array, Boolean, Error, Function, Number, Object, RegExp, String ].forEach(function(type) {
[ "toString", "valueOf" ].forEach(function(prop) {
type.prototype[prop] = function(fn) {
return function() {
try {
return fn.apply(this, arguments);
} catch (e) {}
};
}(type.prototype[prop]);
});
});
}
function is_error_timeout(ex) {
return /timed out/.test(ex.message);
}
@@ -2336,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;
@@ -2500,8 +2516,8 @@ for (var round = 1; round <= num_iterations; round++) {
if (!ok && errored && uglify_result.name == "ReferenceError" && original_result.name == "ReferenceError") ok = true;
// ignore difference due to implicit strict-mode in `class`
if (!ok && /\bclass\b/.test(original_code)) {
var original_strict = run_code('"use strict";' + original_code, toplevel);
var uglify_strict = run_code('"use strict";' + uglify_code, toplevel);
var original_strict = run_code('"use strict";\n' + original_code, toplevel);
var uglify_strict = run_code('"use strict";\n' + uglify_code, toplevel);
if (typeof original_strict != "string") {
ok = typeof uglify_strict != "string";
} else {
@@ -2512,6 +2528,12 @@ for (var round = 1; round <= num_iterations; round++) {
if (!ok && errored && /\bimport\b/.test(original_code)) {
if (is_error_redeclaration(uglify_result) && is_error_redeclaration(original_result)) ok = true;
}
// ignore difference due to `__proto__` assignment
if (!ok && /\b__proto__\b/.test(original_code)) {
var original_proto = run_code("(" + patch_proto + ")();\n" + original_code, toplevel);
var uglify_proto = run_code("(" + patch_proto + ")();\n" + uglify_code, toplevel);
ok = sandbox.same_stdout(original_proto, uglify_proto);
}
// ignore difference in error message caused by `in`
if (!ok && errored && is_error_in(uglify_result) && is_error_in(original_result)) ok = true;
// ignore difference in error message caused by spread syntax

View File

@@ -16,7 +16,7 @@
},
{},
{
"ie8": true,
"ie": true,
"toplevel": true
},
{