Compare commits
17 Commits
harmony-v3
...
harmony-v3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
888a321417 | ||
|
|
ee5c03f7f1 | ||
|
|
4377e932ca | ||
|
|
bac14ba881 | ||
|
|
ec095ed647 | ||
|
|
17e73121fa | ||
|
|
0cb75089f0 | ||
|
|
f71e8fd948 | ||
|
|
a1647ee0c5 | ||
|
|
c814060b4a | ||
|
|
3e62faa64f | ||
|
|
e9645e017f | ||
|
|
55b5f2a8aa | ||
|
|
303293e4aa | ||
|
|
23265ac253 | ||
|
|
0cc6dedccc | ||
|
|
ec63588496 |
23
README.md
23
README.md
@@ -569,6 +569,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
||||
comparison are switching. Compression only works if both `comparisons` and
|
||||
`unsafe_comps` are both set to true.
|
||||
|
||||
- `unsafe_Func` (default: false) -- compress and mangle `Function(args, code)`.
|
||||
|
||||
- `unsafe_math` (default: false) -- optimize numerical expressions like
|
||||
`2 * x * 3` into `6 * x`, which may give imprecise floating point results.
|
||||
|
||||
@@ -675,17 +677,22 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
||||
|
||||
## Mangle options
|
||||
|
||||
- `reserved` - pass an array of identifiers that should be excluded from mangling
|
||||
- `reserved` (default `[]`). Pass an array of identifiers that should be
|
||||
excluded from mangling. Example: `["foo", "bar"]`.
|
||||
|
||||
- `toplevel` — mangle names declared in the top level scope (disabled by
|
||||
default).
|
||||
- `toplevel` (default `false`). Pass `true` to mangle names declared in the
|
||||
top level scope.
|
||||
|
||||
- `eval` — mangle names visible in scopes where eval or with are used
|
||||
(disabled by default).
|
||||
- `keep_fnames` (default `false`). Pass `true` to not mangle function names.
|
||||
Useful for code relying on `Function.prototype.name`. See also: the `keep_fnames`
|
||||
[compress option](#compress-options).
|
||||
|
||||
- `keep_fnames` -- default `false`. Pass `true` to not mangle
|
||||
function names. Useful for code relying on `Function.prototype.name`.
|
||||
See also: the `keep_fnames` [compress option](#compress-options).
|
||||
- `eval` (default `false`). Pass `true` to mangle names visible in scopes
|
||||
where `eval` or `with` are used.
|
||||
|
||||
- `safari10` (default `false`). Pass `true` to work around the Safari 10 loop
|
||||
iterator [bug](https://bugs.webkit.org/show_bug.cgi?id=171041)
|
||||
"Cannot declare a let variable twice".
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
@@ -225,9 +225,10 @@ function run() {
|
||||
col = line.length;
|
||||
}
|
||||
if (line) {
|
||||
if (col > 40) {
|
||||
line = line.slice(col - 40);
|
||||
col = 40;
|
||||
var limit = 70;
|
||||
if (col > limit) {
|
||||
line = line.slice(col - limit);
|
||||
col = limit;
|
||||
}
|
||||
console.error(line.slice(0, 80));
|
||||
console.error(line.slice(0, col).replace(/\S/g, " ") + "^");
|
||||
|
||||
201
lib/compress.js
201
lib/compress.js
@@ -82,6 +82,7 @@ function Compressor(options, false_by_default) {
|
||||
toplevel : !!(options && options["top_retain"]),
|
||||
unsafe : false,
|
||||
unsafe_comps : false,
|
||||
unsafe_Func : false,
|
||||
unsafe_math : false,
|
||||
unsafe_proto : false,
|
||||
unsafe_regexp : false,
|
||||
@@ -251,7 +252,7 @@ merge(Compressor.prototype, {
|
||||
})
|
||||
});
|
||||
}
|
||||
if (node instanceof AST_Lambda && node !== self) {
|
||||
if (node instanceof AST_Class || node instanceof AST_Lambda && node !== self) {
|
||||
return node;
|
||||
}
|
||||
if (node instanceof AST_Block) {
|
||||
@@ -372,14 +373,16 @@ merge(Compressor.prototype, {
|
||||
// (function(a,b) {...})(c,d) => (function() {var a=c,b=d; ...})()
|
||||
// So existing transformation rules can work on them.
|
||||
node.argnames.forEach(function(arg, i) {
|
||||
var d = arg.definition();
|
||||
if (!node.uses_arguments && d.fixed === undefined) {
|
||||
d.fixed = function() {
|
||||
return iife.args[i] || make_node(AST_Undefined, iife);
|
||||
};
|
||||
mark(d, true);
|
||||
} else {
|
||||
d.fixed = false;
|
||||
if (arg.definition) {
|
||||
var d = arg.definition();
|
||||
if (!node.uses_arguments && d.fixed === undefined) {
|
||||
d.fixed = function() {
|
||||
return iife.args[i] || make_node(AST_Undefined, iife);
|
||||
};
|
||||
mark(d, true);
|
||||
} else {
|
||||
d.fixed = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -666,6 +669,7 @@ merge(Compressor.prototype, {
|
||||
function can_be_evicted_from_block(node) {
|
||||
return !(
|
||||
node instanceof AST_DefClass ||
|
||||
node instanceof AST_Defun ||
|
||||
node instanceof AST_Let ||
|
||||
node instanceof AST_Const
|
||||
);
|
||||
@@ -1714,6 +1718,63 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
throw def;
|
||||
});
|
||||
var object_fns = [
|
||||
'constructor',
|
||||
'toString',
|
||||
'valueOf',
|
||||
];
|
||||
var native_fns = {
|
||||
Array: makePredicate([
|
||||
'indexOf',
|
||||
'join',
|
||||
'lastIndexOf',
|
||||
'slice',
|
||||
].concat(object_fns)),
|
||||
Boolean: makePredicate(object_fns),
|
||||
Number: makePredicate([
|
||||
'toExponential',
|
||||
'toFixed',
|
||||
'toPrecision',
|
||||
].concat(object_fns)),
|
||||
RegExp: makePredicate([
|
||||
'test',
|
||||
].concat(object_fns)),
|
||||
String: makePredicate([
|
||||
'charAt',
|
||||
'charCodeAt',
|
||||
'concat',
|
||||
'indexOf',
|
||||
'italics',
|
||||
'lastIndexOf',
|
||||
'match',
|
||||
'replace',
|
||||
'search',
|
||||
'slice',
|
||||
'split',
|
||||
'substr',
|
||||
'substring',
|
||||
'trim',
|
||||
].concat(object_fns)),
|
||||
};
|
||||
def(AST_Call, function(compressor){
|
||||
var exp = this.expression;
|
||||
if (compressor.option("unsafe") && exp instanceof AST_PropAccess) {
|
||||
var key = exp.property;
|
||||
if (key instanceof AST_Node) {
|
||||
key = ev(key, compressor);
|
||||
}
|
||||
var val = ev(exp.expression, compressor);
|
||||
if ((val && native_fns[val.constructor.name] || return_false)(key)) {
|
||||
return val[key].apply(val, this.args.map(function(arg) {
|
||||
return ev(arg, compressor);
|
||||
}));
|
||||
}
|
||||
}
|
||||
throw def;
|
||||
});
|
||||
def(AST_New, function(compressor){
|
||||
throw def;
|
||||
});
|
||||
})(function(node, func){
|
||||
node.DEFMETHOD("_eval", func);
|
||||
});
|
||||
@@ -1995,7 +2056,8 @@ merge(Compressor.prototype, {
|
||||
self.body = tighten_body(self.body, compressor);
|
||||
switch (self.body.length) {
|
||||
case 1:
|
||||
if (can_be_evicted_from_block(self.body[0])) {
|
||||
if (!compressor.has_directive("use strict") && compressor.parent() instanceof AST_If
|
||||
|| can_be_evicted_from_block(self.body[0])) {
|
||||
return self.body[0];
|
||||
}
|
||||
break;
|
||||
@@ -3133,63 +3195,6 @@ merge(Compressor.prototype, {
|
||||
operator: "!"
|
||||
}).optimize(compressor);
|
||||
break;
|
||||
case "Function":
|
||||
// new Function() => function(){}
|
||||
if (self.args.length == 0) return make_node(AST_Function, self, {
|
||||
argnames: [],
|
||||
body: []
|
||||
});
|
||||
if (all(self.args, function(x){ return x instanceof AST_String })) {
|
||||
// quite a corner-case, but we can handle it:
|
||||
// https://github.com/mishoo/UglifyJS2/issues/203
|
||||
// if the code argument is a constant, then we can minify it.
|
||||
try {
|
||||
var code = "(function(" + self.args.slice(0, -1).map(function(arg){
|
||||
return arg.value;
|
||||
}).join(",") + "){" + self.args[self.args.length - 1].value + "})()";
|
||||
var ast = parse(code);
|
||||
var mangle = { ie8: compressor.option("ie8") };
|
||||
ast.figure_out_scope(mangle);
|
||||
var comp = new Compressor(compressor.options);
|
||||
ast = ast.transform(comp);
|
||||
ast.figure_out_scope(mangle);
|
||||
ast.mangle_names();
|
||||
var fun;
|
||||
try {
|
||||
ast.walk(new TreeWalker(function(node){
|
||||
if (node instanceof AST_Lambda) {
|
||||
fun = node;
|
||||
throw ast;
|
||||
}
|
||||
}));
|
||||
} catch(ex) {
|
||||
if (ex !== ast) throw ex;
|
||||
};
|
||||
if (!fun) return self;
|
||||
var args = fun.argnames.map(function(arg, i){
|
||||
return make_node(AST_String, self.args[i], {
|
||||
value: arg.print_to_string({ecma: compressor.option("ecma")})
|
||||
});
|
||||
});
|
||||
var code = OutputStream();
|
||||
AST_BlockStatement.prototype._codegen.call(fun, fun, code);
|
||||
code = code.toString().replace(/^\{|\}$/g, "");
|
||||
args.push(make_node(AST_String, self.args[self.args.length - 1], {
|
||||
value: code
|
||||
}));
|
||||
self.args = args;
|
||||
return self;
|
||||
} catch(ex) {
|
||||
if (ex instanceof JS_Parse_Error) {
|
||||
compressor.warn("Error parsing code passed to new Function [{file}:{line},{col}]", self.args[self.args.length - 1].start);
|
||||
compressor.warn(ex.toString());
|
||||
} else {
|
||||
console.log(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "Symbol":
|
||||
// Symbol's argument is only used for debugging.
|
||||
self.args = [];
|
||||
@@ -3276,6 +3281,63 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (compressor.option("unsafe_Func")
|
||||
&& exp instanceof AST_SymbolRef
|
||||
&& exp.undeclared()
|
||||
&& exp.name == "Function") {
|
||||
// new Function() => function(){}
|
||||
if (self.args.length == 0) return make_node(AST_Function, self, {
|
||||
argnames: [],
|
||||
body: []
|
||||
});
|
||||
if (all(self.args, function(x) {
|
||||
return x instanceof AST_String;
|
||||
})) {
|
||||
// quite a corner-case, but we can handle it:
|
||||
// https://github.com/mishoo/UglifyJS2/issues/203
|
||||
// if the code argument is a constant, then we can minify it.
|
||||
try {
|
||||
var code = "NaN(function(" + self.args.slice(0, -1).map(function(arg) {
|
||||
return arg.value;
|
||||
}).join(",") + "){" + self.args[self.args.length - 1].value + "})";
|
||||
var ast = parse(code);
|
||||
var mangle = { ie8: compressor.option("ie8") };
|
||||
ast.figure_out_scope(mangle);
|
||||
var comp = new Compressor(compressor.options);
|
||||
ast = ast.transform(comp);
|
||||
ast.figure_out_scope(mangle);
|
||||
ast.mangle_names();
|
||||
var fun;
|
||||
ast.walk(new TreeWalker(function(node) {
|
||||
if (fun) return true;
|
||||
if (node instanceof AST_Lambda) {
|
||||
fun = node;
|
||||
return true;
|
||||
}
|
||||
}));
|
||||
var args = fun.argnames.map(function(arg, i) {
|
||||
return make_node(AST_String, self.args[i], {
|
||||
value: arg.print_to_string()
|
||||
});
|
||||
});
|
||||
var code = OutputStream();
|
||||
AST_BlockStatement.prototype._codegen.call(fun, fun, code);
|
||||
code = code.toString().replace(/^\{|\}$/g, "");
|
||||
args.push(make_node(AST_String, self.args[self.args.length - 1], {
|
||||
value: code
|
||||
}));
|
||||
self.args = args;
|
||||
return self;
|
||||
} catch (ex) {
|
||||
if (ex instanceof JS_Parse_Error) {
|
||||
compressor.warn("Error parsing code passed to new Function [{file}:{line},{col}]", self.args[self.args.length - 1].start);
|
||||
compressor.warn(ex.toString());
|
||||
} else {
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (exp instanceof AST_Function && !self.expression.is_generator) {
|
||||
if (exp.body[0] instanceof AST_Return) {
|
||||
var value = exp.body[0].value;
|
||||
@@ -3307,6 +3369,11 @@ merge(Compressor.prototype, {
|
||||
&& is_iife_call(self)) {
|
||||
return self.negate(compressor, true);
|
||||
}
|
||||
var ev = self.evaluate(compressor);
|
||||
if (ev !== self) {
|
||||
ev = make_node_from_constant(ev, self).optimize(compressor);
|
||||
return best_of(compressor, ev, self);
|
||||
}
|
||||
return self;
|
||||
});
|
||||
|
||||
|
||||
@@ -1536,7 +1536,8 @@ function OutputStream(options) {
|
||||
DEFPRINT(AST_NewTarget, function(self, output) {
|
||||
output.print("new.target");
|
||||
});
|
||||
AST_ObjectProperty.DEFMETHOD("print_property_name", function(key, quote, output) {
|
||||
|
||||
function print_property_name(key, quote, output) {
|
||||
if (output.option("quote_keys")) {
|
||||
output.print_string(key + "");
|
||||
} else if ((typeof key == "number"
|
||||
@@ -1553,7 +1554,8 @@ function OutputStream(options) {
|
||||
} else {
|
||||
output.print_string(key, quote);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
DEFPRINT(AST_ObjectKeyVal, function(self, output){
|
||||
function get_name(self) {
|
||||
var def = self.definition();
|
||||
@@ -1566,7 +1568,7 @@ function OutputStream(options) {
|
||||
is_identifier_string(self.key) &&
|
||||
get_name(self.value) === self.key
|
||||
) {
|
||||
self.print_property_name(self.key, self.quote, output);
|
||||
print_property_name(self.key, self.quote, output);
|
||||
|
||||
} else if (allowShortHand &&
|
||||
self.value instanceof AST_DefaultAssign &&
|
||||
@@ -1574,12 +1576,12 @@ function OutputStream(options) {
|
||||
is_identifier_string(self.key) &&
|
||||
get_name(self.value.left) === self.key
|
||||
) {
|
||||
self.print_property_name(self.key, self.quote, output);
|
||||
print_property_name(self.key, self.quote, output);
|
||||
output.print("=");
|
||||
self.value.right.print(output);
|
||||
} else {
|
||||
if (!(self.key instanceof AST_Node)) {
|
||||
self.print_property_name(self.key, self.quote, output);
|
||||
print_property_name(self.key, self.quote, output);
|
||||
} else {
|
||||
output.with_square(function() {
|
||||
self.key.print(output);
|
||||
@@ -1589,15 +1591,18 @@ function OutputStream(options) {
|
||||
self.value.print(output);
|
||||
}
|
||||
});
|
||||
AST_ObjectProperty.DEFMETHOD("_print_getter_setter", function(type, self, output) {
|
||||
AST_ObjectProperty.DEFMETHOD("_print_getter_setter", function(type, output) {
|
||||
var self = this;
|
||||
if (self.static) {
|
||||
output.print("static");
|
||||
output.space();
|
||||
}
|
||||
output.print(type);
|
||||
output.space();
|
||||
if (type) {
|
||||
output.print(type);
|
||||
output.space();
|
||||
}
|
||||
if (self.key instanceof AST_SymbolMethod) {
|
||||
self.print_property_name(self.key.name, self.quote, output);
|
||||
print_property_name(self.key.name, self.quote, output);
|
||||
} else {
|
||||
output.with_square(function() {
|
||||
self.key.print(output);
|
||||
@@ -1606,27 +1611,13 @@ function OutputStream(options) {
|
||||
self.value._do_print(output, true);
|
||||
});
|
||||
DEFPRINT(AST_ObjectSetter, function(self, output){
|
||||
self._print_getter_setter("set", self, output);
|
||||
self._print_getter_setter("set", output);
|
||||
});
|
||||
DEFPRINT(AST_ObjectGetter, function(self, output){
|
||||
self._print_getter_setter("get", self, output);
|
||||
self._print_getter_setter("get", output);
|
||||
});
|
||||
DEFPRINT(AST_ConciseMethod, function(self, output){
|
||||
if (self.static) {
|
||||
output.print("static");
|
||||
output.space();
|
||||
}
|
||||
if (self.is_generator) {
|
||||
output.print("*");
|
||||
}
|
||||
if (self.key instanceof AST_SymbolMethod) {
|
||||
self.print_property_name(self.key.name, self.quote, output);
|
||||
} else {
|
||||
output.with_square(function() {
|
||||
self.key.print(output);
|
||||
});
|
||||
}
|
||||
self.value._do_print(output, true);
|
||||
self._print_getter_setter(self.is_generator && "*", output);
|
||||
});
|
||||
AST_Symbol.DEFMETHOD("_do_print", function(output){
|
||||
var def = this.definition();
|
||||
|
||||
@@ -51,7 +51,6 @@ function SymbolDef(scope, index, orig) {
|
||||
this.global = false;
|
||||
this.export = false;
|
||||
this.mangled_name = null;
|
||||
this.object_destructuring_arg = false;
|
||||
this.undeclared = false;
|
||||
this.index = index;
|
||||
this.id = SymbolDef.next_id++;
|
||||
@@ -65,7 +64,6 @@ SymbolDef.prototype = {
|
||||
|
||||
return (this.global && !options.toplevel)
|
||||
|| this.export
|
||||
|| this.object_destructuring_arg
|
||||
|| this.undeclared
|
||||
|| (!options.eval && (this.scope.uses_eval || this.scope.uses_with))
|
||||
|| (options.keep_fnames
|
||||
@@ -168,9 +166,6 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
if (node instanceof AST_Symbol) {
|
||||
node.scope = scope;
|
||||
}
|
||||
if (node instanceof AST_SymbolFunarg) {
|
||||
node.object_destructuring_arg = !!in_destructuring;
|
||||
}
|
||||
if (node instanceof AST_Label) {
|
||||
node.thedef = node;
|
||||
node.references = [];
|
||||
@@ -378,7 +373,6 @@ AST_Scope.DEFMETHOD("def_variable", function(symbol){
|
||||
if (!this.variables.has(symbol.name)) {
|
||||
def = new SymbolDef(this, this.variables.size(), symbol);
|
||||
this.variables.set(symbol.name, def);
|
||||
def.object_destructuring_arg = symbol.object_destructuring_arg;
|
||||
def.global = !this.parent_scope;
|
||||
} else {
|
||||
def = this.variables.get(symbol.name);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"homepage": "https://github.com/mishoo/UglifyJS2/tree/harmony",
|
||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||
"license": "BSD-2-Clause",
|
||||
"version": "3.0.13",
|
||||
"version": "3.0.15",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
|
||||
@@ -47,3 +47,142 @@ keep_some_blocks: {
|
||||
} else stuff();
|
||||
}
|
||||
}
|
||||
|
||||
issue_1664: {
|
||||
input: {
|
||||
var a = 1;
|
||||
function f() {
|
||||
if (undefined) a = 2;
|
||||
{
|
||||
function undefined() {}
|
||||
undefined();
|
||||
}
|
||||
}
|
||||
f();
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = 1;
|
||||
function f() {
|
||||
if (undefined) a = 2;
|
||||
{
|
||||
function undefined() {}
|
||||
undefined();
|
||||
}
|
||||
}
|
||||
f();
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_1672_for: {
|
||||
input: {
|
||||
switch (function() {
|
||||
return xxx;
|
||||
}) {
|
||||
case xxx:
|
||||
for (; console.log("FAIL");) {
|
||||
function xxx() {}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
switch (function() {
|
||||
return xxx;
|
||||
}) {
|
||||
case xxx:
|
||||
for (; console.log("FAIL");) {
|
||||
function xxx() {}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_1672_for_strict: {
|
||||
input: {
|
||||
"use strict";
|
||||
switch (function() {
|
||||
return xxx;
|
||||
}) {
|
||||
case xxx:
|
||||
for (; console.log("FAIL");) {
|
||||
function xxx() {}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
switch (function() {
|
||||
return xxx;
|
||||
}) {
|
||||
case xxx:
|
||||
for (; console.log("FAIL");) {
|
||||
function xxx() {}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_1672_if: {
|
||||
input: {
|
||||
switch (function() {
|
||||
return xxx;
|
||||
}) {
|
||||
case xxx:
|
||||
if (console.log("FAIL")) {
|
||||
function xxx() {}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
switch (function() {
|
||||
return xxx;
|
||||
}) {
|
||||
case xxx:
|
||||
if (console.log("FAIL")) function xxx() {}
|
||||
break;
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_1672_if_strict: {
|
||||
input: {
|
||||
"use strict";
|
||||
switch (function() {
|
||||
return xxx;
|
||||
}) {
|
||||
case xxx:
|
||||
if (console.log("FAIL")) {
|
||||
function xxx() {}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
switch (function() {
|
||||
return xxx;
|
||||
}) {
|
||||
case xxx:
|
||||
if (console.log("FAIL")) {
|
||||
function xxx() {}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
@@ -543,3 +543,55 @@ mangle_destructuring_decl_array: {
|
||||
expect_stdout: "8 7 6 undefined 2 [ 3 ]"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
anon_func_with_destructuring_args: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unused: true,
|
||||
toplevel: true,
|
||||
}
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
beautify = {
|
||||
ecma: 5,
|
||||
}
|
||||
input: {
|
||||
(function({foo = 1 + 0, bar = 2}, [car = 3, far = 4]) {
|
||||
console.log(foo, bar, car, far);
|
||||
})({bar: 5 - 0}, [, 6]);
|
||||
}
|
||||
expect: {
|
||||
(function({foo: o = 1, bar: n = 2}, [a = 3, b = 4]) {
|
||||
console.log(o, n, a, b);
|
||||
})({bar: 5}, [, 6]);
|
||||
}
|
||||
expect_stdout: "1 5 3 6"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
arrow_func_with_destructuring_args: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unused: true,
|
||||
toplevel: true,
|
||||
}
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
beautify = {
|
||||
ecma: 5,
|
||||
}
|
||||
input: {
|
||||
(({foo = 1 + 0, bar = 2}, [car = 3, far = 4]) => {
|
||||
console.log(foo, bar, car, far);
|
||||
})({bar: 5 - 0}, [, 6]);
|
||||
}
|
||||
expect: {
|
||||
(({foo: o = 1, bar: n = 2}, [a = 3, b = 4]) => {
|
||||
console.log(o, n, a, b);
|
||||
})({bar: 5}, [, 6]);
|
||||
}
|
||||
expect_stdout: "1 5 3 6"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
@@ -873,13 +873,15 @@ unsafe_charAt_noop: {
|
||||
input: {
|
||||
console.log(
|
||||
s.charAt(0),
|
||||
"string".charAt(x)
|
||||
"string".charAt(x),
|
||||
(typeof x).charAt()
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
console.log(
|
||||
s.charAt(0),
|
||||
"string".charAt(x)
|
||||
"string".charAt(x),
|
||||
(typeof x)[0]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1130,3 +1132,31 @@ issue_1964_2: {
|
||||
}
|
||||
expect_stdout: "b"
|
||||
}
|
||||
|
||||
array_slice_index: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log([1,2,3].slice(1)[1]);
|
||||
}
|
||||
expect: {
|
||||
console.log(3);
|
||||
}
|
||||
expect_stdout: "3"
|
||||
}
|
||||
|
||||
string_charCodeAt: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log("foo".charCodeAt("bar".length));
|
||||
}
|
||||
expect: {
|
||||
console.log(NaN);
|
||||
}
|
||||
expect_stdout: "NaN"
|
||||
}
|
||||
|
||||
@@ -245,3 +245,25 @@ hoist_funs_strict: {
|
||||
]
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
issue_203: {
|
||||
options = {
|
||||
keep_fargs: false,
|
||||
side_effects: true,
|
||||
unsafe_Func: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var m = {};
|
||||
var fn = Function("require", "module", "exports", "module.exports = 42;");
|
||||
fn(null, m, m.exports);
|
||||
console.log(m.exports);
|
||||
}
|
||||
expect: {
|
||||
var m = {};
|
||||
var fn = Function("a", "b", "b.exports=42");
|
||||
fn(null, m, m.exports);
|
||||
console.log(m.exports);
|
||||
}
|
||||
expect_stdout: "42"
|
||||
}
|
||||
|
||||
@@ -583,3 +583,39 @@ class_extends_regex: {
|
||||
}
|
||||
expect_exact: "function f(){class rx1 extends(/rx/){}}"
|
||||
}
|
||||
|
||||
issue_2028: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var a = {};
|
||||
(function(x) {
|
||||
x.X = function() {
|
||||
return X;
|
||||
};
|
||||
class X {
|
||||
static hello() {
|
||||
console.log("hello");
|
||||
}
|
||||
}
|
||||
}(a));
|
||||
a.X().hello();
|
||||
}
|
||||
expect: {
|
||||
var a = {};
|
||||
(function(x) {
|
||||
x.X = function() {
|
||||
return X;
|
||||
};
|
||||
class X {
|
||||
static hello() {
|
||||
console.log("hello");
|
||||
}
|
||||
}
|
||||
}(a));
|
||||
a.X().hello();
|
||||
}
|
||||
expect_stdout: "hello"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
|
||||
compress_new_function: {
|
||||
options = {
|
||||
unsafe: true
|
||||
unsafe: true,
|
||||
unsafe_Func: true,
|
||||
}
|
||||
input: {
|
||||
new Function("aa, bb", 'return aa;');
|
||||
@@ -14,6 +15,7 @@ compress_new_function: {
|
||||
compress_new_function_with_destruct: {
|
||||
options = {
|
||||
unsafe: true,
|
||||
unsafe_Func: true,
|
||||
ecma: 6
|
||||
}
|
||||
beautify = {
|
||||
@@ -26,9 +28,7 @@ compress_new_function_with_destruct: {
|
||||
}
|
||||
expect: {
|
||||
Function("a", "[b]", "return a");
|
||||
Function("a", "{bb}", "return a");
|
||||
Function("[[a]]", "[{bb}]", 'return a');
|
||||
Function("a", "{bb:b}", "return a");
|
||||
Function("[[a]]", "[{bb:b}]", 'return a');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -557,3 +557,20 @@ native_prototype: {
|
||||
"".indexOf.call(e, "bar");
|
||||
}
|
||||
}
|
||||
|
||||
issue_2040: {
|
||||
input: {
|
||||
var a = 1;
|
||||
var b = {
|
||||
get "a-b"() {
|
||||
return a;
|
||||
},
|
||||
set "a-b"(c) {
|
||||
a = c;
|
||||
}
|
||||
};
|
||||
console.log(b["a-b"], b["a-b"] = 2, b["a-b"]);
|
||||
}
|
||||
expect_exact: 'var a=1;var b={get"a-b"(){return a},set"a-b"(c){a=c}};console.log(b["a-b"],b["a-b"]=2,b["a-b"]);'
|
||||
expect_stdout: "1 2 2"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user