Compare commits
56 Commits
harmony-v3
...
harmony-v3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
370f2cc906 | ||
|
|
78cf35f89c | ||
|
|
57dc4fb32f | ||
|
|
b85a358deb | ||
|
|
100e18305d | ||
|
|
43697958f3 | ||
|
|
3f961bbba0 | ||
|
|
7cc03d4d40 | ||
|
|
0a1e523cd5 | ||
|
|
c28056d7ed | ||
|
|
8af362ed57 | ||
|
|
4231f7323e | ||
|
|
68138f2281 | ||
|
|
da2de350c3 | ||
|
|
41beae4dd7 | ||
|
|
82db9188ac | ||
|
|
3dc9e140e4 | ||
|
|
fed0096556 | ||
|
|
2bdc8802dd | ||
|
|
5ef7cb372a | ||
|
|
4ad7b1dae4 | ||
|
|
9186859cb7 | ||
|
|
47c0713747 | ||
|
|
293c566d6c | ||
|
|
9c306406f1 | ||
|
|
9db0695b10 | ||
|
|
a7971f4e34 | ||
|
|
f2af093402 | ||
|
|
b9ad53d1ab | ||
|
|
b0eab71470 | ||
|
|
3493a182b2 | ||
|
|
27c5284d3d | ||
|
|
540220b91b | ||
|
|
82fefc5d29 | ||
|
|
753932b302 | ||
|
|
84634da4b5 | ||
|
|
1743621889 | ||
|
|
1edbd6556f | ||
|
|
f330ab743a | ||
|
|
888a321417 | ||
|
|
ee5c03f7f1 | ||
|
|
4377e932ca | ||
|
|
bac14ba881 | ||
|
|
ec095ed647 | ||
|
|
17e73121fa | ||
|
|
0cb75089f0 | ||
|
|
f71e8fd948 | ||
|
|
a1647ee0c5 | ||
|
|
c814060b4a | ||
|
|
3e62faa64f | ||
|
|
e9645e017f | ||
|
|
55b5f2a8aa | ||
|
|
303293e4aa | ||
|
|
23265ac253 | ||
|
|
0cc6dedccc | ||
|
|
ec63588496 |
@@ -4,8 +4,11 @@ node_js:
|
|||||||
- "0.12"
|
- "0.12"
|
||||||
- "4"
|
- "4"
|
||||||
- "6"
|
- "6"
|
||||||
|
- "8"
|
||||||
env:
|
env:
|
||||||
- UGLIFYJS_TEST_ALL=1
|
- UGLIFYJS_TEST_ALL=1
|
||||||
matrix:
|
matrix:
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
sudo: false
|
sudo: false
|
||||||
|
cache:
|
||||||
|
directories: tmp
|
||||||
|
|||||||
28
README.md
28
README.md
@@ -569,6 +569,9 @@ 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
|
comparison are switching. Compression only works if both `comparisons` and
|
||||||
`unsafe_comps` are both set to true.
|
`unsafe_comps` are both set to true.
|
||||||
|
|
||||||
|
- `unsafe_Func` (default: false) -- compress and mangle `Function(args, code)`
|
||||||
|
when both `args` and `code` are string literals.
|
||||||
|
|
||||||
- `unsafe_math` (default: false) -- optimize numerical expressions like
|
- `unsafe_math` (default: false) -- optimize numerical expressions like
|
||||||
`2 * x * 3` into `6 * x`, which may give imprecise floating point results.
|
`2 * x * 3` into `6 * x`, which may give imprecise floating point results.
|
||||||
|
|
||||||
@@ -610,6 +613,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
|||||||
|
|
||||||
- `if_return` -- optimizations for if/return and if/continue
|
- `if_return` -- optimizations for if/return and if/continue
|
||||||
|
|
||||||
|
- `inline` -- embed simple functions
|
||||||
|
|
||||||
- `join_vars` -- join consecutive `var` statements
|
- `join_vars` -- join consecutive `var` statements
|
||||||
|
|
||||||
- `cascade` -- small optimization for sequences, transform `x, x` into `x`
|
- `cascade` -- small optimization for sequences, transform `x, x` into `x`
|
||||||
@@ -675,17 +680,22 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
|||||||
|
|
||||||
## Mangle options
|
## 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
|
- `toplevel` (default `false`). Pass `true` to mangle names declared in the
|
||||||
default).
|
top level scope.
|
||||||
|
|
||||||
- `eval` — mangle names visible in scopes where eval or with are used
|
- `keep_fnames` (default `false`). Pass `true` to not mangle function names.
|
||||||
(disabled by default).
|
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
|
- `eval` (default `false`). Pass `true` to mangle names visible in scopes
|
||||||
function names. Useful for code relying on `Function.prototype.name`.
|
where `eval` or `with` are used.
|
||||||
See also: the `keep_fnames` [compress option](#compress-options).
|
|
||||||
|
- `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:
|
Examples:
|
||||||
|
|
||||||
@@ -760,7 +770,7 @@ can pass additional arguments that control the code output:
|
|||||||
- `quote_style` (default `0`) -- preferred quote style for strings (affects
|
- `quote_style` (default `0`) -- preferred quote style for strings (affects
|
||||||
quoted property names and directives as well):
|
quoted property names and directives as well):
|
||||||
- `0` -- prefers double quotes, switches to single quotes when there are
|
- `0` -- prefers double quotes, switches to single quotes when there are
|
||||||
more double quotes in the string itself.
|
more double quotes in the string itself. `0` is best for gzip size.
|
||||||
- `1` -- always use single quotes
|
- `1` -- always use single quotes
|
||||||
- `2` -- always use double quotes
|
- `2` -- always use double quotes
|
||||||
- `3` -- always use the original quotes
|
- `3` -- always use the original quotes
|
||||||
|
|||||||
66
bin/uglifyjs
66
bin/uglifyjs
@@ -30,14 +30,7 @@ else if (process.argv.indexOf("options") >= 0) program.helpInformation = functio
|
|||||||
var options = UglifyJS.default_options();
|
var options = UglifyJS.default_options();
|
||||||
for (var option in options) {
|
for (var option in options) {
|
||||||
text.push("--" + (option == "output" ? "beautify" : option == "sourceMap" ? "source-map" : option) + " options:");
|
text.push("--" + (option == "output" ? "beautify" : option == "sourceMap" ? "source-map" : option) + " options:");
|
||||||
var defs = options[option];
|
text.push(format_object(options[option]));
|
||||||
var padding = "";
|
|
||||||
Object.keys(defs).map(function(name) {
|
|
||||||
if (padding.length < name.length) padding = Array(name.length + 1).join(" ");
|
|
||||||
return [ name, JSON.stringify(defs[name]) ];
|
|
||||||
}).forEach(function(tokens) {
|
|
||||||
text.push(" " + tokens[0] + padding.slice(tokens[0].length - 2) + tokens[1]);
|
|
||||||
});
|
|
||||||
text.push("");
|
text.push("");
|
||||||
}
|
}
|
||||||
return text.join("\n");
|
return text.join("\n");
|
||||||
@@ -157,7 +150,7 @@ if (program.verbose) {
|
|||||||
}
|
}
|
||||||
if (program.self) {
|
if (program.self) {
|
||||||
if (program.args.length) {
|
if (program.args.length) {
|
||||||
console.error("WARN: Ignoring input files since --self was passed");
|
print_error("WARN: Ignoring input files since --self was passed");
|
||||||
}
|
}
|
||||||
if (!options.wrap) options.wrap = "UglifyJS";
|
if (!options.wrap) options.wrap = "UglifyJS";
|
||||||
simple_glob(UglifyJS.FILES).forEach(function(name) {
|
simple_glob(UglifyJS.FILES).forEach(function(name) {
|
||||||
@@ -187,7 +180,7 @@ function convert_ast(fn) {
|
|||||||
|
|
||||||
function run() {
|
function run() {
|
||||||
UglifyJS.AST_Node.warn_function = function(msg) {
|
UglifyJS.AST_Node.warn_function = function(msg) {
|
||||||
console.error("WARN:", msg);
|
print_error("WARN: " + msg);
|
||||||
};
|
};
|
||||||
if (program.timings) options.timings = true;
|
if (program.timings) options.timings = true;
|
||||||
try {
|
try {
|
||||||
@@ -216,7 +209,7 @@ function run() {
|
|||||||
if (result.error) {
|
if (result.error) {
|
||||||
var ex = result.error;
|
var ex = result.error;
|
||||||
if (ex.name == "SyntaxError") {
|
if (ex.name == "SyntaxError") {
|
||||||
console.error("Parse error at " + ex.filename + ":" + ex.line + "," + ex.col);
|
print_error("Parse error at " + ex.filename + ":" + ex.line + "," + ex.col);
|
||||||
var col = ex.col;
|
var col = ex.col;
|
||||||
var lines = files[ex.filename].split(/\r?\n/);
|
var lines = files[ex.filename].split(/\r?\n/);
|
||||||
var line = lines[ex.line - 1];
|
var line = lines[ex.line - 1];
|
||||||
@@ -225,21 +218,22 @@ function run() {
|
|||||||
col = line.length;
|
col = line.length;
|
||||||
}
|
}
|
||||||
if (line) {
|
if (line) {
|
||||||
if (col > 40) {
|
var limit = 70;
|
||||||
line = line.slice(col - 40);
|
if (col > limit) {
|
||||||
col = 40;
|
line = line.slice(col - limit);
|
||||||
|
col = limit;
|
||||||
}
|
}
|
||||||
console.error(line.slice(0, 80));
|
print_error(line.slice(0, 80));
|
||||||
console.error(line.slice(0, col).replace(/\S/g, " ") + "^");
|
print_error(line.slice(0, col).replace(/\S/g, " ") + "^");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ex.defs) {
|
if (ex.defs) {
|
||||||
console.error("Supported options:");
|
print_error("Supported options:");
|
||||||
console.error(ex.defs);
|
print_error(format_object(ex.defs));
|
||||||
}
|
}
|
||||||
fatal(ex);
|
fatal(ex);
|
||||||
} else if (program.output == "ast") {
|
} else if (program.output == "ast") {
|
||||||
console.log(JSON.stringify(result.ast, function(key, value) {
|
print(JSON.stringify(result.ast, function(key, value) {
|
||||||
if (skip_key(key)) return;
|
if (skip_key(key)) return;
|
||||||
if (value instanceof UglifyJS.AST_Token) return;
|
if (value instanceof UglifyJS.AST_Token) return;
|
||||||
if (value instanceof UglifyJS.Dictionary) return;
|
if (value instanceof UglifyJS.Dictionary) return;
|
||||||
@@ -255,7 +249,7 @@ function run() {
|
|||||||
return value;
|
return value;
|
||||||
}, 2));
|
}, 2));
|
||||||
} else if (program.output == "spidermonkey") {
|
} else if (program.output == "spidermonkey") {
|
||||||
console.log(JSON.stringify(UglifyJS.minify(result.code, {
|
print(JSON.stringify(UglifyJS.minify(result.code, {
|
||||||
compress: false,
|
compress: false,
|
||||||
mangle: false,
|
mangle: false,
|
||||||
output: {
|
output: {
|
||||||
@@ -269,7 +263,7 @@ function run() {
|
|||||||
fs.writeFileSync(program.output + ".map", result.map);
|
fs.writeFileSync(program.output + ".map", result.map);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log(result.code);
|
print(result.code);
|
||||||
}
|
}
|
||||||
if (program.nameCache) {
|
if (program.nameCache) {
|
||||||
fs.writeFileSync(program.nameCache, JSON.stringify(cache, function(key, value) {
|
fs.writeFileSync(program.nameCache, JSON.stringify(cache, function(key, value) {
|
||||||
@@ -277,13 +271,13 @@ function run() {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
if (result.timings) for (var phase in result.timings) {
|
if (result.timings) for (var phase in result.timings) {
|
||||||
console.error("- " + phase + ": " + result.timings[phase].toFixed(3) + "s");
|
print_error("- " + phase + ": " + result.timings[phase].toFixed(3) + "s");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function fatal(message) {
|
function fatal(message) {
|
||||||
if (message instanceof Error) message = message.stack.replace(/^\S*?Error:/, "ERROR:")
|
if (message instanceof Error) message = message.stack.replace(/^\S*?Error:/, "ERROR:")
|
||||||
console.error(message);
|
print_error(message);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,10 +371,10 @@ function parse_js(flag, constants) {
|
|||||||
function parse_source_map() {
|
function parse_source_map() {
|
||||||
var parse = parse_js("sourceMap", true);
|
var parse = parse_js("sourceMap", true);
|
||||||
return function(value, options) {
|
return function(value, options) {
|
||||||
var hasContent = options && options.sourceMap && "content" in options.sourceMap;
|
var hasContent = options && "content" in options;
|
||||||
var settings = parse(value, options);
|
var settings = parse(value, options);
|
||||||
if (!hasContent && settings.content && settings.content != "inline") {
|
if (!hasContent && settings.content && settings.content != "inline") {
|
||||||
console.error("INFO: Using input source map:", settings.content);
|
print_error("INFO: Using input source map: " + settings.content);
|
||||||
settings.content = read_file(settings.content, settings.content);
|
settings.content = read_file(settings.content, settings.content);
|
||||||
}
|
}
|
||||||
return settings;
|
return settings;
|
||||||
@@ -402,3 +396,25 @@ function to_cache(key) {
|
|||||||
function skip_key(key) {
|
function skip_key(key) {
|
||||||
return skip_keys.indexOf(key) >= 0;
|
return skip_keys.indexOf(key) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function format_object(obj) {
|
||||||
|
var lines = [];
|
||||||
|
var padding = "";
|
||||||
|
Object.keys(obj).map(function(name) {
|
||||||
|
if (padding.length < name.length) padding = Array(name.length + 1).join(" ");
|
||||||
|
return [ name, JSON.stringify(obj[name]) ];
|
||||||
|
}).forEach(function(tokens) {
|
||||||
|
lines.push(" " + tokens[0] + padding.slice(tokens[0].length - 2) + tokens[1]);
|
||||||
|
});
|
||||||
|
return lines.join("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
function print_error(msg) {
|
||||||
|
process.stderr.write(msg);
|
||||||
|
process.stderr.write("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
function print(txt) {
|
||||||
|
process.stdout.write(txt);
|
||||||
|
process.stdout.write("\n");
|
||||||
|
}
|
||||||
|
|||||||
26
lib/ast.js
26
lib/ast.js
@@ -355,13 +355,14 @@ var AST_Expansion = DEFNODE("Expansion", "expression", {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments is_generator", {
|
var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments is_generator async", {
|
||||||
$documentation: "Base class for functions",
|
$documentation: "Base class for functions",
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
is_generator: "[boolean] is generatorFn or not",
|
|
||||||
name: "[AST_SymbolDeclaration?] the name of this function",
|
name: "[AST_SymbolDeclaration?] the name of this function",
|
||||||
argnames: "[AST_SymbolFunarg|AST_Destructuring|AST_Expansion|AST_DefaultAssign*] array of function arguments, destructurings, or expanding arguments",
|
argnames: "[AST_SymbolFunarg|AST_Destructuring|AST_Expansion|AST_DefaultAssign*] array of function arguments, destructurings, or expanding arguments",
|
||||||
uses_arguments: "[boolean/S] tells whether this function accesses the arguments array"
|
uses_arguments: "[boolean/S] tells whether this function accesses the arguments array",
|
||||||
|
is_generator: "[boolean] is this a generator method",
|
||||||
|
async: "[boolean] is this method async",
|
||||||
},
|
},
|
||||||
args_as_names: function () {
|
args_as_names: function () {
|
||||||
var out = [];
|
var out = [];
|
||||||
@@ -893,11 +894,12 @@ var AST_ObjectGetter = DEFNODE("ObjectGetter", "quote static", {
|
|||||||
$documentation: "An object getter property",
|
$documentation: "An object getter property",
|
||||||
}, AST_ObjectProperty);
|
}, AST_ObjectProperty);
|
||||||
|
|
||||||
var AST_ConciseMethod = DEFNODE("ConciseMethod", "quote static is_generator", {
|
var AST_ConciseMethod = DEFNODE("ConciseMethod", "quote static is_generator async", {
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
quote: "[string|undefined] the original quote character, if any",
|
quote: "[string|undefined] the original quote character, if any",
|
||||||
static: "[boolean] whether this method is static (classes only)",
|
static: "[boolean] is this method static (classes only)",
|
||||||
is_generator: "[boolean] is generatorFn or not",
|
is_generator: "[boolean] is this a generator method",
|
||||||
|
async: "[boolean] is this method async",
|
||||||
},
|
},
|
||||||
$documentation: "An ES6 concise method inside an object or class"
|
$documentation: "An ES6 concise method inside an object or class"
|
||||||
}, AST_ObjectProperty);
|
}, AST_ObjectProperty);
|
||||||
@@ -1101,7 +1103,17 @@ var AST_True = DEFNODE("True", null, {
|
|||||||
value: true
|
value: true
|
||||||
}, AST_Boolean);
|
}, AST_Boolean);
|
||||||
|
|
||||||
/* -----[ Yield ]----- */
|
var AST_Await = DEFNODE("Await", "expression", {
|
||||||
|
$documentation: "An `await` statement",
|
||||||
|
$propdoc: {
|
||||||
|
expression: "[AST_Node] the mandatory expression being awaited",
|
||||||
|
},
|
||||||
|
_walk: function(visitor) {
|
||||||
|
return visitor._visit(this, function(){
|
||||||
|
this.expression._walk(visitor);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
var AST_Yield = DEFNODE("Yield", "expression is_star", {
|
var AST_Yield = DEFNODE("Yield", "expression is_star", {
|
||||||
$documentation: "A `yield` statement",
|
$documentation: "A `yield` statement",
|
||||||
|
|||||||
304
lib/compress.js
304
lib/compress.js
@@ -64,6 +64,7 @@ function Compressor(options, false_by_default) {
|
|||||||
hoist_vars : false,
|
hoist_vars : false,
|
||||||
ie8 : false,
|
ie8 : false,
|
||||||
if_return : !false_by_default,
|
if_return : !false_by_default,
|
||||||
|
inline : !false_by_default,
|
||||||
join_vars : !false_by_default,
|
join_vars : !false_by_default,
|
||||||
keep_fargs : true,
|
keep_fargs : true,
|
||||||
keep_fnames : false,
|
keep_fnames : false,
|
||||||
@@ -82,6 +83,7 @@ function Compressor(options, false_by_default) {
|
|||||||
toplevel : !!(options && options["top_retain"]),
|
toplevel : !!(options && options["top_retain"]),
|
||||||
unsafe : false,
|
unsafe : false,
|
||||||
unsafe_comps : false,
|
unsafe_comps : false,
|
||||||
|
unsafe_Func : false,
|
||||||
unsafe_math : false,
|
unsafe_math : false,
|
||||||
unsafe_proto : false,
|
unsafe_proto : false,
|
||||||
unsafe_regexp : false,
|
unsafe_regexp : false,
|
||||||
@@ -251,7 +253,7 @@ merge(Compressor.prototype, {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Lambda && node !== self) {
|
if (node instanceof AST_Class || node instanceof AST_Lambda && node !== self) {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Block) {
|
if (node instanceof AST_Block) {
|
||||||
@@ -362,7 +364,7 @@ merge(Compressor.prototype, {
|
|||||||
safe_ids = save_ids;
|
safe_ids = save_ids;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Function) {
|
if (node instanceof AST_Function || node instanceof AST_Arrow) {
|
||||||
push();
|
push();
|
||||||
var iife;
|
var iife;
|
||||||
if (!node.name
|
if (!node.name
|
||||||
@@ -372,6 +374,7 @@ merge(Compressor.prototype, {
|
|||||||
// (function(a,b) {...})(c,d) => (function() {var a=c,b=d; ...})()
|
// (function(a,b) {...})(c,d) => (function() {var a=c,b=d; ...})()
|
||||||
// So existing transformation rules can work on them.
|
// So existing transformation rules can work on them.
|
||||||
node.argnames.forEach(function(arg, i) {
|
node.argnames.forEach(function(arg, i) {
|
||||||
|
if (arg.definition) {
|
||||||
var d = arg.definition();
|
var d = arg.definition();
|
||||||
if (!node.uses_arguments && d.fixed === undefined) {
|
if (!node.uses_arguments && d.fixed === undefined) {
|
||||||
d.fixed = function() {
|
d.fixed = function() {
|
||||||
@@ -381,6 +384,7 @@ merge(Compressor.prototype, {
|
|||||||
} else {
|
} else {
|
||||||
d.fixed = false;
|
d.fixed = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
descend();
|
descend();
|
||||||
@@ -666,6 +670,7 @@ merge(Compressor.prototype, {
|
|||||||
function can_be_evicted_from_block(node) {
|
function can_be_evicted_from_block(node) {
|
||||||
return !(
|
return !(
|
||||||
node instanceof AST_DefClass ||
|
node instanceof AST_DefClass ||
|
||||||
|
node instanceof AST_Defun ||
|
||||||
node instanceof AST_Let ||
|
node instanceof AST_Let ||
|
||||||
node instanceof AST_Const
|
node instanceof AST_Const
|
||||||
);
|
);
|
||||||
@@ -746,6 +751,7 @@ merge(Compressor.prototype, {
|
|||||||
// Stop immediately if these node types are encountered
|
// Stop immediately if these node types are encountered
|
||||||
var parent = tt.parent();
|
var parent = tt.parent();
|
||||||
if (node instanceof AST_Assign && node.operator != "=" && lhs.equivalent_to(node.left)
|
if (node instanceof AST_Assign && node.operator != "=" && lhs.equivalent_to(node.left)
|
||||||
|
|| node instanceof AST_Await
|
||||||
|| node instanceof AST_Debugger
|
|| node instanceof AST_Debugger
|
||||||
|| node instanceof AST_Destructuring
|
|| node instanceof AST_Destructuring
|
||||||
|| node instanceof AST_IterationStatement && !(node instanceof AST_For)
|
|| node instanceof AST_IterationStatement && !(node instanceof AST_For)
|
||||||
@@ -1455,7 +1461,7 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
if (value && typeof value == "object") {
|
if (value && typeof value == "object") {
|
||||||
var props = [];
|
var props = [];
|
||||||
for (var key in value) {
|
for (var key in value) if (HOP(value, key)) {
|
||||||
props.push(make_node(AST_ObjectKeyVal, orig, {
|
props.push(make_node(AST_ObjectKeyVal, orig, {
|
||||||
key: key,
|
key: key,
|
||||||
value: to_node(value[key], orig)
|
value: to_node(value[key], orig)
|
||||||
@@ -1714,6 +1720,63 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
throw def;
|
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){
|
})(function(node, func){
|
||||||
node.DEFMETHOD("_eval", func);
|
node.DEFMETHOD("_eval", func);
|
||||||
});
|
});
|
||||||
@@ -1862,6 +1925,7 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
def(AST_Defun, return_true);
|
def(AST_Defun, return_true);
|
||||||
def(AST_Function, return_false);
|
def(AST_Function, return_false);
|
||||||
|
def(AST_Arrow, return_false);
|
||||||
def(AST_Class, return_false);
|
def(AST_Class, return_false);
|
||||||
def(AST_DefClass, return_true);
|
def(AST_DefClass, return_true);
|
||||||
def(AST_Binary, function(compressor){
|
def(AST_Binary, function(compressor){
|
||||||
@@ -1995,7 +2059,8 @@ merge(Compressor.prototype, {
|
|||||||
self.body = tighten_body(self.body, compressor);
|
self.body = tighten_body(self.body, compressor);
|
||||||
switch (self.body.length) {
|
switch (self.body.length) {
|
||||||
case 1:
|
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];
|
return self.body[0];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -2215,7 +2280,9 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Definitions && !(parent instanceof AST_ForIn && parent.init === node)) {
|
if (node instanceof AST_Definitions
|
||||||
|
&& !(parent instanceof AST_ForIn && parent.init === node)
|
||||||
|
&& (drop_vars || !(parent instanceof AST_Toplevel) && !(node instanceof AST_Var))) {
|
||||||
// place uninitialized names at the start
|
// place uninitialized names at the start
|
||||||
var body = [], head = [], tail = [];
|
var body = [], head = [], tail = [];
|
||||||
// for unused names whose initialization has
|
// for unused names whose initialization has
|
||||||
@@ -2546,6 +2613,8 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
def(AST_Accessor, return_null);
|
def(AST_Accessor, return_null);
|
||||||
def(AST_Function, return_null);
|
def(AST_Function, return_null);
|
||||||
|
def(AST_Arrow, return_null);
|
||||||
|
def(AST_ClassExpression, return_null);
|
||||||
def(AST_Binary, function(compressor, first_in_statement){
|
def(AST_Binary, function(compressor, first_in_statement){
|
||||||
var right = this.right.drop_side_effect_free(compressor);
|
var right = this.right.drop_side_effect_free(compressor);
|
||||||
if (!right) return this.left.drop_side_effect_free(compressor, first_in_statement);
|
if (!right) return this.left.drop_side_effect_free(compressor, first_in_statement);
|
||||||
@@ -3045,24 +3114,9 @@ merge(Compressor.prototype, {
|
|||||||
|
|
||||||
OPT(AST_Call, function(self, compressor){
|
OPT(AST_Call, function(self, compressor){
|
||||||
var exp = self.expression;
|
var exp = self.expression;
|
||||||
if (compressor.option("reduce_vars")
|
if (compressor.option("reduce_vars") && exp instanceof AST_SymbolRef) {
|
||||||
&& exp instanceof AST_SymbolRef) {
|
|
||||||
var def = exp.definition();
|
|
||||||
var fixed = exp.fixed_value();
|
var fixed = exp.fixed_value();
|
||||||
if (fixed instanceof AST_Defun) {
|
if (fixed instanceof AST_Function) exp = fixed;
|
||||||
def.fixed = fixed = make_node(AST_Function, fixed, fixed).clone(true);
|
|
||||||
}
|
|
||||||
if (fixed instanceof AST_Function) {
|
|
||||||
exp = fixed;
|
|
||||||
if (compressor.option("unused")
|
|
||||||
&& def.references.length == 1
|
|
||||||
&& !(def.scope.uses_arguments
|
|
||||||
&& def.orig[0] instanceof AST_SymbolFunarg)
|
|
||||||
&& !def.scope.uses_eval
|
|
||||||
&& compressor.find_parent(AST_Scope) === def.scope) {
|
|
||||||
self.expression = exp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (compressor.option("unused")
|
if (compressor.option("unused")
|
||||||
&& exp instanceof AST_Function
|
&& exp instanceof AST_Function
|
||||||
@@ -3133,63 +3187,6 @@ merge(Compressor.prototype, {
|
|||||||
operator: "!"
|
operator: "!"
|
||||||
}).optimize(compressor);
|
}).optimize(compressor);
|
||||||
break;
|
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":
|
case "Symbol":
|
||||||
// Symbol's argument is only used for debugging.
|
// Symbol's argument is only used for debugging.
|
||||||
self.args = [];
|
self.args = [];
|
||||||
@@ -3276,14 +3273,133 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (exp instanceof AST_Function && !self.expression.is_generator) {
|
if (compressor.option("unsafe_Func")
|
||||||
if (exp.body[0] instanceof AST_Return) {
|
&& exp instanceof AST_SymbolRef
|
||||||
var value = exp.body[0].value;
|
&& 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 && !self.expression.async) {
|
||||||
|
var stat = exp.body[0];
|
||||||
|
if (compressor.option("inline") && stat instanceof AST_Return) {
|
||||||
|
var value = stat && stat.value;
|
||||||
if (!value || value.is_constant_expression()) {
|
if (!value || value.is_constant_expression()) {
|
||||||
var args = self.args.concat(value || make_node(AST_Undefined, self));
|
var args = self.args.concat(value || make_node(AST_Undefined, self));
|
||||||
return make_sequence(self, args).transform(compressor);
|
return make_sequence(self, args).transform(compressor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (compressor.option("inline")
|
||||||
|
&& !exp.name
|
||||||
|
&& exp.body.length == 1
|
||||||
|
&& !exp.uses_arguments
|
||||||
|
&& !exp.uses_eval
|
||||||
|
&& !self.has_pure_annotation(compressor)) {
|
||||||
|
var value;
|
||||||
|
if (stat instanceof AST_Return) {
|
||||||
|
value = stat.value.clone(true);
|
||||||
|
} else if (stat instanceof AST_SimpleStatement) {
|
||||||
|
value = make_node(AST_UnaryPrefix, stat, {
|
||||||
|
operator: "void",
|
||||||
|
expression: stat.body.clone(true)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (value) {
|
||||||
|
var fn = exp.clone();
|
||||||
|
fn.argnames = [];
|
||||||
|
fn.body = [];
|
||||||
|
if (exp.argnames.length > 0) {
|
||||||
|
fn.body.push(make_node(AST_Var, self, {
|
||||||
|
definitions: exp.argnames.map(function(sym, i) {
|
||||||
|
return make_node(AST_VarDef, sym, {
|
||||||
|
name: sym,
|
||||||
|
value: self.args[i] || make_node(AST_Undefined, self)
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
if (self.args.length > exp.argnames.length) {
|
||||||
|
fn.body.push(make_node(AST_SimpleStatement, self, {
|
||||||
|
body: make_sequence(self, self.args.slice(exp.argnames.length))
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
fn.body.push(make_node(AST_Return, self, {
|
||||||
|
value: value
|
||||||
|
}));
|
||||||
|
var body = fn.transform(compressor).body;
|
||||||
|
if (body.length == 0) return make_node(AST_Undefined, self);
|
||||||
|
if (body.length == 1 && body[0] instanceof AST_Return) {
|
||||||
|
value = body[0].value;
|
||||||
|
if (!value) return make_node(AST_Undefined, self);
|
||||||
|
value.walk(new TreeWalker(function(node) {
|
||||||
|
if (value === self) return true;
|
||||||
|
if (node instanceof AST_SymbolRef && matches(node.scope.find_variable(node))
|
||||||
|
|| node instanceof AST_This && matches(node)) {
|
||||||
|
value = self;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function matches(ref) {
|
||||||
|
return ref && ref.scope.parent_scope === fn.parent_scope;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
if (value !== self) value = best_of(compressor, value, self);
|
||||||
|
} else {
|
||||||
|
value = self;
|
||||||
|
}
|
||||||
|
if (value !== self) return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (compressor.option("side_effects") && all(exp.body, is_empty)) {
|
if (compressor.option("side_effects") && all(exp.body, is_empty)) {
|
||||||
var args = self.args.concat(make_node(AST_Undefined, self));
|
var args = self.args.concat(make_node(AST_Undefined, self));
|
||||||
return make_sequence(self, args).transform(compressor);
|
return make_sequence(self, args).transform(compressor);
|
||||||
@@ -3307,6 +3423,11 @@ merge(Compressor.prototype, {
|
|||||||
&& is_iife_call(self)) {
|
&& is_iife_call(self)) {
|
||||||
return self.negate(compressor, true);
|
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;
|
return self;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -3381,6 +3502,7 @@ merge(Compressor.prototype, {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var parent = null, field;
|
var parent = null, field;
|
||||||
|
expressions[j] = cdr = cdr.clone();
|
||||||
while (true) {
|
while (true) {
|
||||||
if (cdr.equivalent_to(left)) {
|
if (cdr.equivalent_to(left)) {
|
||||||
var car = expressions[i];
|
var car = expressions[i];
|
||||||
@@ -3417,7 +3539,7 @@ merge(Compressor.prototype, {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
parent = cdr;
|
parent = cdr;
|
||||||
cdr = cdr[field];
|
cdr = cdr[field] = cdr[field].clone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end = i;
|
end = i;
|
||||||
@@ -3937,12 +4059,22 @@ merge(Compressor.prototype, {
|
|||||||
return make_node(AST_Infinity, self).optimize(compressor);
|
return make_node(AST_Infinity, self).optimize(compressor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (compressor.option("evaluate")
|
if (compressor.option("reduce_vars")
|
||||||
&& compressor.option("reduce_vars")
|
|
||||||
&& is_lhs(self, compressor.parent()) !== self) {
|
&& is_lhs(self, compressor.parent()) !== self) {
|
||||||
var d = self.definition();
|
var d = self.definition();
|
||||||
var fixed = self.fixed_value();
|
var fixed = self.fixed_value();
|
||||||
if (fixed) {
|
if (fixed instanceof AST_Defun) {
|
||||||
|
d.fixed = fixed = make_node(AST_Function, fixed, fixed).clone(true);
|
||||||
|
}
|
||||||
|
if (compressor.option("unused")
|
||||||
|
&& fixed instanceof AST_Function
|
||||||
|
&& d.references.length == 1
|
||||||
|
&& !(d.scope.uses_arguments && d.orig[0] instanceof AST_SymbolFunarg)
|
||||||
|
&& !d.scope.uses_eval
|
||||||
|
&& compressor.find_parent(AST_Scope) === fixed.parent_scope) {
|
||||||
|
return fixed;
|
||||||
|
}
|
||||||
|
if (compressor.option("evaluate") && fixed) {
|
||||||
if (d.should_replace === undefined) {
|
if (d.should_replace === undefined) {
|
||||||
var init = fixed.evaluate(compressor);
|
var init = fixed.evaluate(compressor);
|
||||||
if (init !== fixed && (compressor.option("unsafe_regexp") || !(init instanceof RegExp))) {
|
if (init !== fixed && (compressor.option("unsafe_regexp") || !(init instanceof RegExp))) {
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ function minify(files, options) {
|
|||||||
}
|
}
|
||||||
options.parse = options.parse || {};
|
options.parse = options.parse || {};
|
||||||
options.parse.toplevel = null;
|
options.parse.toplevel = null;
|
||||||
for (var name in files) {
|
for (var name in files) if (HOP(files, name)) {
|
||||||
options.parse.filename = name;
|
options.parse.filename = name;
|
||||||
options.parse.toplevel = parse(files[name], options.parse);
|
options.parse.toplevel = parse(files[name], options.parse);
|
||||||
if (options.sourceMap && options.sourceMap.content == "inline") {
|
if (options.sourceMap && options.sourceMap.content == "inline") {
|
||||||
@@ -136,7 +136,7 @@ function minify(files, options) {
|
|||||||
if (options.sourceMap.includeSources) {
|
if (options.sourceMap.includeSources) {
|
||||||
if (files instanceof AST_Toplevel) {
|
if (files instanceof AST_Toplevel) {
|
||||||
throw new Error("original source content unavailable");
|
throw new Error("original source content unavailable");
|
||||||
} else for (var name in files) {
|
} else for (var name in files) if (HOP(files, name)) {
|
||||||
options.output.source_map.get().setSourceContent(name, files[name]);
|
options.output.source_map.get().setSourceContent(name, files[name]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ function OutputStream(options) {
|
|||||||
shebang : true,
|
shebang : true,
|
||||||
shorthand : undefined,
|
shorthand : undefined,
|
||||||
source_map : null,
|
source_map : null,
|
||||||
|
webkit : false,
|
||||||
width : 80,
|
width : 80,
|
||||||
wrap_iife : false,
|
wrap_iife : false,
|
||||||
}, true);
|
}, true);
|
||||||
@@ -629,6 +630,13 @@ function OutputStream(options) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (output.option('webkit')) {
|
||||||
|
var p = output.parent();
|
||||||
|
if (p instanceof AST_PropAccess && p.expression === this) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (output.option('wrap_iife')) {
|
if (output.option('wrap_iife')) {
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
return p instanceof AST_Call && p.expression === this;
|
return p instanceof AST_Call && p.expression === this;
|
||||||
@@ -642,6 +650,10 @@ function OutputStream(options) {
|
|||||||
return p instanceof AST_PropAccess && p.expression === this;
|
return p instanceof AST_PropAccess && p.expression === this;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
PARENS(AST_ClassExpression, function(output){
|
||||||
|
return output.parent() instanceof AST_SimpleStatement;
|
||||||
|
});
|
||||||
|
|
||||||
// same goes for an object literal, because otherwise it would be
|
// same goes for an object literal, because otherwise it would be
|
||||||
// interpreted as a block of code.
|
// interpreted as a block of code.
|
||||||
PARENS(AST_Object, function(output){
|
PARENS(AST_Object, function(output){
|
||||||
@@ -805,17 +817,15 @@ function OutputStream(options) {
|
|||||||
|
|
||||||
DEFPRINT(AST_Destructuring, function (self, output) {
|
DEFPRINT(AST_Destructuring, function (self, output) {
|
||||||
output.print(self.is_array ? "[" : "{");
|
output.print(self.is_array ? "[" : "{");
|
||||||
var first = true;
|
|
||||||
var len = self.names.length;
|
var len = self.names.length;
|
||||||
self.names.forEach(function (name, i) {
|
self.names.forEach(function (name, i) {
|
||||||
if (first) first = false; else { output.comma(); output.space(); }
|
if (i > 0) output.comma();
|
||||||
name.print(output);
|
name.print(output);
|
||||||
// If the final element is a hole, we need to make sure it
|
// If the final element is a hole, we need to make sure it
|
||||||
// doesn't look like a trailing comma, by inserting an actual
|
// doesn't look like a trailing comma, by inserting an actual
|
||||||
// trailing comma.
|
// trailing comma.
|
||||||
if (i === len - 1 && name instanceof AST_Hole)
|
if (i == len - 1 && name instanceof AST_Hole) output.comma();
|
||||||
output.comma();
|
});
|
||||||
})
|
|
||||||
output.print(self.is_array ? "]" : "}");
|
output.print(self.is_array ? "]" : "}");
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -968,6 +978,10 @@ function OutputStream(options) {
|
|||||||
AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword){
|
AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword){
|
||||||
var self = this;
|
var self = this;
|
||||||
if (!nokeyword) {
|
if (!nokeyword) {
|
||||||
|
if (this.async) {
|
||||||
|
output.print("async");
|
||||||
|
output.space();
|
||||||
|
}
|
||||||
output.print("function");
|
output.print("function");
|
||||||
if (this.is_generator) {
|
if (this.is_generator) {
|
||||||
output.star();
|
output.star();
|
||||||
@@ -1073,6 +1087,22 @@ function OutputStream(options) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
DEFPRINT(AST_Await, function(self, output){
|
||||||
|
output.print("await");
|
||||||
|
output.space();
|
||||||
|
var e = self.expression;
|
||||||
|
var parens = !(
|
||||||
|
e instanceof AST_Call
|
||||||
|
|| e instanceof AST_SymbolRef
|
||||||
|
|| e instanceof AST_PropAccess
|
||||||
|
|| e instanceof AST_Unary
|
||||||
|
|| e instanceof AST_Constant
|
||||||
|
);
|
||||||
|
if (parens) output.print("(");
|
||||||
|
self.expression.print(output);
|
||||||
|
if (parens) output.print(")");
|
||||||
|
});
|
||||||
|
|
||||||
/* -----[ loop control ]----- */
|
/* -----[ loop control ]----- */
|
||||||
AST_LoopControl.DEFMETHOD("_do_print", function(output, kind){
|
AST_LoopControl.DEFMETHOD("_do_print", function(output, kind){
|
||||||
output.print(kind);
|
output.print(kind);
|
||||||
@@ -1536,7 +1566,8 @@ function OutputStream(options) {
|
|||||||
DEFPRINT(AST_NewTarget, function(self, output) {
|
DEFPRINT(AST_NewTarget, function(self, output) {
|
||||||
output.print("new.target");
|
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")) {
|
if (output.option("quote_keys")) {
|
||||||
output.print_string(key + "");
|
output.print_string(key + "");
|
||||||
} else if ((typeof key == "number"
|
} else if ((typeof key == "number"
|
||||||
@@ -1553,7 +1584,8 @@ function OutputStream(options) {
|
|||||||
} else {
|
} else {
|
||||||
output.print_string(key, quote);
|
output.print_string(key, quote);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
DEFPRINT(AST_ObjectKeyVal, function(self, output){
|
DEFPRINT(AST_ObjectKeyVal, function(self, output){
|
||||||
function get_name(self) {
|
function get_name(self) {
|
||||||
var def = self.definition();
|
var def = self.definition();
|
||||||
@@ -1566,7 +1598,7 @@ function OutputStream(options) {
|
|||||||
is_identifier_string(self.key) &&
|
is_identifier_string(self.key) &&
|
||||||
get_name(self.value) === 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 &&
|
} else if (allowShortHand &&
|
||||||
self.value instanceof AST_DefaultAssign &&
|
self.value instanceof AST_DefaultAssign &&
|
||||||
@@ -1574,12 +1606,14 @@ function OutputStream(options) {
|
|||||||
is_identifier_string(self.key) &&
|
is_identifier_string(self.key) &&
|
||||||
get_name(self.value.left) === 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.space();
|
||||||
output.print("=");
|
output.print("=");
|
||||||
|
output.space();
|
||||||
self.value.right.print(output);
|
self.value.right.print(output);
|
||||||
} else {
|
} else {
|
||||||
if (!(self.key instanceof AST_Node)) {
|
if (!(self.key instanceof AST_Node)) {
|
||||||
self.print_property_name(self.key, self.quote, output);
|
print_property_name(self.key, self.quote, output);
|
||||||
} else {
|
} else {
|
||||||
output.with_square(function() {
|
output.with_square(function() {
|
||||||
self.key.print(output);
|
self.key.print(output);
|
||||||
@@ -1589,15 +1623,18 @@ function OutputStream(options) {
|
|||||||
self.value.print(output);
|
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) {
|
if (self.static) {
|
||||||
output.print("static");
|
output.print("static");
|
||||||
output.space();
|
output.space();
|
||||||
}
|
}
|
||||||
|
if (type) {
|
||||||
output.print(type);
|
output.print(type);
|
||||||
output.space();
|
output.space();
|
||||||
|
}
|
||||||
if (self.key instanceof AST_SymbolMethod) {
|
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 {
|
} else {
|
||||||
output.with_square(function() {
|
output.with_square(function() {
|
||||||
self.key.print(output);
|
self.key.print(output);
|
||||||
@@ -1606,27 +1643,13 @@ function OutputStream(options) {
|
|||||||
self.value._do_print(output, true);
|
self.value._do_print(output, true);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_ObjectSetter, function(self, output){
|
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){
|
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){
|
DEFPRINT(AST_ConciseMethod, function(self, output){
|
||||||
if (self.static) {
|
self._print_getter_setter(self.is_generator && "*" || self.async && "async", output);
|
||||||
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);
|
|
||||||
});
|
});
|
||||||
AST_Symbol.DEFMETHOD("_do_print", function(output){
|
AST_Symbol.DEFMETHOD("_do_print", function(output){
|
||||||
var def = this.definition();
|
var def = this.definition();
|
||||||
|
|||||||
85
lib/parse.js
85
lib/parse.js
@@ -47,7 +47,7 @@
|
|||||||
var KEYWORDS = 'break case catch class const continue debugger default delete do else export extends finally for function if in instanceof new return switch throw try typeof var let void while with import';
|
var KEYWORDS = 'break case catch class const continue debugger default delete do else export extends finally for function if in instanceof new return switch throw try typeof var let void while with import';
|
||||||
var KEYWORDS_ATOM = 'false null true';
|
var KEYWORDS_ATOM = 'false null true';
|
||||||
var RESERVED_WORDS = 'enum implements interface package private protected public static super this ' + KEYWORDS_ATOM + " " + KEYWORDS;
|
var RESERVED_WORDS = 'enum implements interface package private protected public static super this ' + KEYWORDS_ATOM + " " + KEYWORDS;
|
||||||
var KEYWORDS_BEFORE_EXPRESSION = 'return new delete throw else case yield';
|
var KEYWORDS_BEFORE_EXPRESSION = 'return new delete throw else case yield await';
|
||||||
|
|
||||||
KEYWORDS = makePredicate(KEYWORDS);
|
KEYWORDS = makePredicate(KEYWORDS);
|
||||||
RESERVED_WORDS = makePredicate(RESERVED_WORDS);
|
RESERVED_WORDS = makePredicate(RESERVED_WORDS);
|
||||||
@@ -122,8 +122,6 @@ var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,;:"));
|
|||||||
|
|
||||||
var PUNC_CHARS = makePredicate(characters("[]{}(),;:"));
|
var PUNC_CHARS = makePredicate(characters("[]{}(),;:"));
|
||||||
|
|
||||||
var REGEXP_MODIFIERS = makePredicate(characters("gmsiy"));
|
|
||||||
|
|
||||||
/* -----[ Tokenizer ]----- */
|
/* -----[ Tokenizer ]----- */
|
||||||
|
|
||||||
// surrogate safe regexps adapted from https://github.com/mathiasbynens/unicode-8.0.0/tree/89b412d8a71ecca9ed593d9e9fa073ab64acfebe/Binary_Property
|
// surrogate safe regexps adapted from https://github.com/mathiasbynens/unicode-8.0.0/tree/89b412d8a71ecca9ed593d9e9fa073ab64acfebe/Binary_Property
|
||||||
@@ -850,9 +848,7 @@ var PRECEDENCE = (function(a, ret){
|
|||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
|
|
||||||
var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]);
|
var ATOMIC_START_TOKEN = makePredicate([ "atom", "num", "string", "regexp", "name" ]);
|
||||||
|
|
||||||
var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]);
|
|
||||||
|
|
||||||
/* -----[ Parser ]----- */
|
/* -----[ Parser ]----- */
|
||||||
|
|
||||||
@@ -877,6 +873,7 @@ function parse($TEXT, options) {
|
|||||||
prev : null,
|
prev : null,
|
||||||
peeked : null,
|
peeked : null,
|
||||||
in_function : 0,
|
in_function : 0,
|
||||||
|
in_async : -1,
|
||||||
in_generator : -1,
|
in_generator : -1,
|
||||||
in_directives : true,
|
in_directives : true,
|
||||||
in_loop : 0,
|
in_loop : 0,
|
||||||
@@ -947,6 +944,10 @@ function parse($TEXT, options) {
|
|||||||
return S.in_generator === S.in_function;
|
return S.in_generator === S.in_function;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function is_in_async() {
|
||||||
|
return S.in_async === S.in_function;
|
||||||
|
}
|
||||||
|
|
||||||
function semicolon(optional) {
|
function semicolon(optional) {
|
||||||
if (is("punc", ";")) next();
|
if (is("punc", ";")) next();
|
||||||
else if (!optional && !can_insert_semicolon()) unexpected();
|
else if (!optional && !can_insert_semicolon()) unexpected();
|
||||||
@@ -1003,6 +1004,11 @@ function parse($TEXT, options) {
|
|||||||
return simple_statement();
|
return simple_statement();
|
||||||
|
|
||||||
case "name":
|
case "name":
|
||||||
|
if (S.token.value == "async" && is_token(peek(), "keyword", "function")) {
|
||||||
|
next();
|
||||||
|
next();
|
||||||
|
return function_(AST_Defun, false, true);
|
||||||
|
}
|
||||||
return is_token(peek(), "punc", ":")
|
return is_token(peek(), "punc", ":")
|
||||||
? labeled_statement()
|
? labeled_statement()
|
||||||
: simple_statement();
|
: simple_statement();
|
||||||
@@ -1159,6 +1165,9 @@ function parse($TEXT, options) {
|
|||||||
// Ecma-262, 12.1.1 Static Semantics: Early Errors
|
// Ecma-262, 12.1.1 Static Semantics: Early Errors
|
||||||
token_error(S.prev, "Yield cannot be used as label inside generators");
|
token_error(S.prev, "Yield cannot be used as label inside generators");
|
||||||
}
|
}
|
||||||
|
if (label.name === "await" && is_in_async()) {
|
||||||
|
token_error(S.prev, "await cannot be used as label inside async function");
|
||||||
|
}
|
||||||
if (find_if(function(l){ return l.name == label.name }, S.labels)) {
|
if (find_if(function(l){ return l.name == label.name }, S.labels)) {
|
||||||
// ECMA-262, 12.12: An ECMAScript program is considered
|
// ECMA-262, 12.12: An ECMAScript program is considered
|
||||||
// syntactically incorrect if it contains a
|
// syntactically incorrect if it contains a
|
||||||
@@ -1289,7 +1298,8 @@ function parse($TEXT, options) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var function_ = function(ctor, is_generator_property) {
|
var function_ = function(ctor, is_generator_property, is_async) {
|
||||||
|
if (is_generator_property && is_async) croak("generators cannot be async");
|
||||||
var start = S.token
|
var start = S.token
|
||||||
|
|
||||||
var in_statement = ctor === AST_Defun;
|
var in_statement = ctor === AST_Defun;
|
||||||
@@ -1303,11 +1313,12 @@ function parse($TEXT, options) {
|
|||||||
unexpected();
|
unexpected();
|
||||||
|
|
||||||
var args = parameters();
|
var args = parameters();
|
||||||
var body = _function_body(true, is_generator || is_generator_property, name, args);
|
var body = _function_body(true, is_generator || is_generator_property, is_async, name, args);
|
||||||
return new ctor({
|
return new ctor({
|
||||||
start : args.start,
|
start : args.start,
|
||||||
end : body.end,
|
end : body.end,
|
||||||
is_generator: is_generator,
|
is_generator: is_generator,
|
||||||
|
async : is_async,
|
||||||
name : name,
|
name : name,
|
||||||
argnames: args,
|
argnames: args,
|
||||||
body : body
|
body : body
|
||||||
@@ -1628,13 +1639,16 @@ function parse($TEXT, options) {
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _function_body(block, generator, name, args) {
|
function _function_body(block, generator, is_async, name, args) {
|
||||||
var loop = S.in_loop;
|
var loop = S.in_loop;
|
||||||
var labels = S.labels;
|
var labels = S.labels;
|
||||||
var current_generator = S.in_generator;
|
var current_generator = S.in_generator;
|
||||||
|
var current_async = S.in_async;
|
||||||
++S.in_function;
|
++S.in_function;
|
||||||
if (generator)
|
if (generator)
|
||||||
S.in_generator = S.in_function;
|
S.in_generator = S.in_function;
|
||||||
|
if (is_async)
|
||||||
|
S.in_async = S.in_function;
|
||||||
if (block)
|
if (block)
|
||||||
S.in_directives = true;
|
S.in_directives = true;
|
||||||
S.in_loop = 0;
|
S.in_loop = 0;
|
||||||
@@ -1654,9 +1668,22 @@ function parse($TEXT, options) {
|
|||||||
S.in_loop = loop;
|
S.in_loop = loop;
|
||||||
S.labels = labels;
|
S.labels = labels;
|
||||||
S.in_generator = current_generator;
|
S.in_generator = current_generator;
|
||||||
|
S.in_async = current_async;
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _await_expression() {
|
||||||
|
// Previous token must be "await" and not be interpreted as an identifier
|
||||||
|
if (!is_in_async()) {
|
||||||
|
croak("Unexpected await expression outside async function",
|
||||||
|
S.prev.line, S.prev.col, S.prev.pos);
|
||||||
|
}
|
||||||
|
// the await expression is parsed as a unary expression in Babel
|
||||||
|
return new AST_Await({
|
||||||
|
expression : maybe_unary(true),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function _yield_expression() {
|
function _yield_expression() {
|
||||||
// Previous token must be keyword yield and not be interpret as an identifier
|
// Previous token must be keyword yield and not be interpret as an identifier
|
||||||
if (!is_in_generator()) {
|
if (!is_in_generator()) {
|
||||||
@@ -1665,7 +1692,6 @@ function parse($TEXT, options) {
|
|||||||
}
|
}
|
||||||
var star = false;
|
var star = false;
|
||||||
var has_expression = true;
|
var has_expression = true;
|
||||||
var tmp;
|
|
||||||
|
|
||||||
// Attempt to get expression or star (and then the mandatory expression)
|
// Attempt to get expression or star (and then the mandatory expression)
|
||||||
// behind yield on the same line.
|
// behind yield on the same line.
|
||||||
@@ -1872,7 +1898,6 @@ function parse($TEXT, options) {
|
|||||||
var tok = S.token, ret;
|
var tok = S.token, ret;
|
||||||
switch (tok.type) {
|
switch (tok.type) {
|
||||||
case "name":
|
case "name":
|
||||||
case "keyword":
|
|
||||||
ret = _make_symbol(AST_SymbolRef);
|
ret = _make_symbol(AST_SymbolRef);
|
||||||
break;
|
break;
|
||||||
case "num":
|
case "num":
|
||||||
@@ -1902,13 +1927,6 @@ function parse($TEXT, options) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "operator":
|
|
||||||
if (!is_identifier_string(tok.value)) {
|
|
||||||
croak("Invalid getter/setter name: " + tok.value,
|
|
||||||
tok.line, tok.col, tok.pos);
|
|
||||||
}
|
|
||||||
ret = _make_symbol(AST_SymbolRef);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
return ret;
|
return ret;
|
||||||
@@ -1998,6 +2016,14 @@ function parse($TEXT, options) {
|
|||||||
}
|
}
|
||||||
unexpected();
|
unexpected();
|
||||||
}
|
}
|
||||||
|
if (is("name", "async") && is_token(peek(), "keyword", "function")) {
|
||||||
|
next();
|
||||||
|
next();
|
||||||
|
var func = function_(AST_Function, false, true);
|
||||||
|
func.start = start;
|
||||||
|
func.end = prev();
|
||||||
|
return subscripts(func, allow_calls);
|
||||||
|
}
|
||||||
if (is("keyword", "function")) {
|
if (is("keyword", "function")) {
|
||||||
next();
|
next();
|
||||||
var func = function_(AST_Function);
|
var func = function_(AST_Function);
|
||||||
@@ -2015,7 +2041,7 @@ function parse($TEXT, options) {
|
|||||||
if (is("template_head")) {
|
if (is("template_head")) {
|
||||||
return subscripts(template_string(), allow_calls);
|
return subscripts(template_string(), allow_calls);
|
||||||
}
|
}
|
||||||
if (ATOMIC_START_TOKEN[S.token.type]) {
|
if (ATOMIC_START_TOKEN(S.token.type)) {
|
||||||
return subscripts(as_atom_node(), allow_calls);
|
return subscripts(as_atom_node(), allow_calls);
|
||||||
}
|
}
|
||||||
unexpected();
|
unexpected();
|
||||||
@@ -2079,8 +2105,8 @@ function parse($TEXT, options) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
var create_accessor = embed_tokens(function(is_generator) {
|
var create_accessor = embed_tokens(function(is_generator, is_async) {
|
||||||
return function_(AST_Accessor, is_generator);
|
return function_(AST_Accessor, is_generator, is_async);
|
||||||
});
|
});
|
||||||
|
|
||||||
var object_or_object_destructuring_ = embed_tokens(function() {
|
var object_or_object_destructuring_ = embed_tokens(function() {
|
||||||
@@ -2196,6 +2222,7 @@ function parse($TEXT, options) {
|
|||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
var is_async = false;
|
||||||
var is_static = false;
|
var is_static = false;
|
||||||
var is_generator = false;
|
var is_generator = false;
|
||||||
var property_token = start;
|
var property_token = start;
|
||||||
@@ -2204,6 +2231,11 @@ function parse($TEXT, options) {
|
|||||||
property_token = S.token;
|
property_token = S.token;
|
||||||
name = as_property_name();
|
name = as_property_name();
|
||||||
}
|
}
|
||||||
|
if (name === "async" && !is("punc", "(")) {
|
||||||
|
is_async = true;
|
||||||
|
property_token = S.token;
|
||||||
|
name = as_property_name();
|
||||||
|
}
|
||||||
if (name === null) {
|
if (name === null) {
|
||||||
is_generator = true;
|
is_generator = true;
|
||||||
property_token = S.token;
|
property_token = S.token;
|
||||||
@@ -2218,10 +2250,11 @@ function parse($TEXT, options) {
|
|||||||
start : start,
|
start : start,
|
||||||
static : is_static,
|
static : is_static,
|
||||||
is_generator: is_generator,
|
is_generator: is_generator,
|
||||||
|
async : is_async,
|
||||||
key : name,
|
key : name,
|
||||||
quote : name instanceof AST_SymbolMethod ?
|
quote : name instanceof AST_SymbolMethod ?
|
||||||
property_token.quote : undefined,
|
property_token.quote : undefined,
|
||||||
value : create_accessor(is_generator),
|
value : create_accessor(is_generator, is_async),
|
||||||
end : prev()
|
end : prev()
|
||||||
});
|
});
|
||||||
return node;
|
return node;
|
||||||
@@ -2586,6 +2619,14 @@ function parse($TEXT, options) {
|
|||||||
|
|
||||||
var maybe_unary = function(allow_calls) {
|
var maybe_unary = function(allow_calls) {
|
||||||
var start = S.token;
|
var start = S.token;
|
||||||
|
if (start.type == "name" && start.value == "await") {
|
||||||
|
if (is_in_async()) {
|
||||||
|
next();
|
||||||
|
return _await_expression();
|
||||||
|
} else if (S.input.has_directive("use strict")) {
|
||||||
|
token_error(S.token, "Unexpected await identifier inside strict mode")
|
||||||
|
}
|
||||||
|
}
|
||||||
if (is("operator") && UNARY_PREFIX(start.value)) {
|
if (is("operator") && UNARY_PREFIX(start.value)) {
|
||||||
next();
|
next();
|
||||||
handle_regexp();
|
handle_regexp();
|
||||||
|
|||||||
@@ -96,7 +96,8 @@ function mangle_properties(ast, options) {
|
|||||||
reserved: null,
|
reserved: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
var reserved = options.reserved || [];
|
var reserved = options.reserved;
|
||||||
|
if (!Array.isArray(reserved)) reserved = [];
|
||||||
if (!options.builtins) find_builtins(reserved);
|
if (!options.builtins) find_builtins(reserved);
|
||||||
|
|
||||||
var cache = options.cache;
|
var cache = options.cache;
|
||||||
|
|||||||
17
lib/scope.js
17
lib/scope.js
@@ -51,7 +51,6 @@ function SymbolDef(scope, index, orig) {
|
|||||||
this.global = false;
|
this.global = false;
|
||||||
this.export = false;
|
this.export = false;
|
||||||
this.mangled_name = null;
|
this.mangled_name = null;
|
||||||
this.object_destructuring_arg = false;
|
|
||||||
this.undeclared = false;
|
this.undeclared = false;
|
||||||
this.index = index;
|
this.index = index;
|
||||||
this.id = SymbolDef.next_id++;
|
this.id = SymbolDef.next_id++;
|
||||||
@@ -65,7 +64,6 @@ SymbolDef.prototype = {
|
|||||||
|
|
||||||
return (this.global && !options.toplevel)
|
return (this.global && !options.toplevel)
|
||||||
|| this.export
|
|| this.export
|
||||||
|| this.object_destructuring_arg
|
|
||||||
|| this.undeclared
|
|| this.undeclared
|
||||||
|| (!options.eval && (this.scope.uses_eval || this.scope.uses_with))
|
|| (!options.eval && (this.scope.uses_eval || this.scope.uses_with))
|
||||||
|| (options.keep_fnames
|
|| (options.keep_fnames
|
||||||
@@ -168,9 +166,6 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
|||||||
if (node instanceof AST_Symbol) {
|
if (node instanceof AST_Symbol) {
|
||||||
node.scope = scope;
|
node.scope = scope;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_SymbolFunarg) {
|
|
||||||
node.object_destructuring_arg = !!in_destructuring;
|
|
||||||
}
|
|
||||||
if (node instanceof AST_Label) {
|
if (node instanceof AST_Label) {
|
||||||
node.thedef = node;
|
node.thedef = node;
|
||||||
node.references = [];
|
node.references = [];
|
||||||
@@ -251,11 +246,10 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
var sym = node.scope.find_variable(name);
|
var sym = node.scope.find_variable(name);
|
||||||
if (node.scope instanceof AST_Lambda && name == "arguments") {
|
|
||||||
node.scope.uses_arguments = true;
|
|
||||||
}
|
|
||||||
if (!sym) {
|
if (!sym) {
|
||||||
sym = self.def_global(node);
|
sym = self.def_global(node);
|
||||||
|
} else if (sym.scope instanceof AST_Lambda && name == "arguments") {
|
||||||
|
sym.scope.uses_arguments = true;
|
||||||
}
|
}
|
||||||
node.thedef = sym;
|
node.thedef = sym;
|
||||||
node.reference(options);
|
node.reference(options);
|
||||||
@@ -378,7 +372,6 @@ AST_Scope.DEFMETHOD("def_variable", function(symbol){
|
|||||||
if (!this.variables.has(symbol.name)) {
|
if (!this.variables.has(symbol.name)) {
|
||||||
def = new SymbolDef(this, this.variables.size(), symbol);
|
def = new SymbolDef(this, this.variables.size(), symbol);
|
||||||
this.variables.set(symbol.name, def);
|
this.variables.set(symbol.name, def);
|
||||||
def.object_destructuring_arg = symbol.object_destructuring_arg;
|
|
||||||
def.global = !this.parent_scope;
|
def.global = !this.parent_scope;
|
||||||
} else {
|
} else {
|
||||||
def = this.variables.get(symbol.name);
|
def = this.variables.get(symbol.name);
|
||||||
@@ -456,7 +449,7 @@ AST_Symbol.DEFMETHOD("global", function(){
|
|||||||
});
|
});
|
||||||
|
|
||||||
AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
|
AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
|
||||||
return defaults(options, {
|
options = defaults(options, {
|
||||||
eval : false,
|
eval : false,
|
||||||
ie8 : false,
|
ie8 : false,
|
||||||
keep_classnames: false,
|
keep_classnames: false,
|
||||||
@@ -464,6 +457,8 @@ AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
|
|||||||
reserved : [],
|
reserved : [],
|
||||||
toplevel : false,
|
toplevel : false,
|
||||||
});
|
});
|
||||||
|
if (!Array.isArray(options.reserved)) options.reserved = [];
|
||||||
|
return options;
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
||||||
@@ -594,6 +589,8 @@ AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
|
|||||||
base54.consider("finally");
|
base54.consider("finally");
|
||||||
else if (node instanceof AST_Yield)
|
else if (node instanceof AST_Yield)
|
||||||
base54.consider("yield");
|
base54.consider("yield");
|
||||||
|
else if (node instanceof AST_Await)
|
||||||
|
base54.consider("await");
|
||||||
else if (node instanceof AST_Symbol && node.unmangleable(options))
|
else if (node instanceof AST_Symbol && node.unmangleable(options))
|
||||||
base54.consider(node.name);
|
base54.consider(node.name);
|
||||||
else if (node instanceof AST_Unary || node instanceof AST_Binary)
|
else if (node instanceof AST_Unary || node instanceof AST_Binary)
|
||||||
|
|||||||
@@ -199,6 +199,10 @@ TreeTransformer.prototype = new TreeWalker;
|
|||||||
if (self.expression) self.expression = self.expression.transform(tw);
|
if (self.expression) self.expression = self.expression.transform(tw);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_(AST_Await, function(self, tw){
|
||||||
|
self.expression = self.expression.transform(tw);
|
||||||
|
});
|
||||||
|
|
||||||
_(AST_Unary, function(self, tw){
|
_(AST_Unary, function(self, tw){
|
||||||
self.expression = self.expression.transform(tw);
|
self.expression = self.expression.transform(tw);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -43,13 +43,6 @@
|
|||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
function array_to_hash(a) {
|
|
||||||
var ret = Object.create(null);
|
|
||||||
for (var i = 0; i < a.length; ++i)
|
|
||||||
ret[a[i]] = true;
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
|
|
||||||
function slice(a, start) {
|
function slice(a, start) {
|
||||||
return Array.prototype.slice.call(a, start || 0);
|
return Array.prototype.slice.call(a, start || 0);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"homepage": "https://github.com/mishoo/UglifyJS2/tree/harmony",
|
"homepage": "https://github.com/mishoo/UglifyJS2/tree/harmony",
|
||||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"version": "3.0.13",
|
"version": "3.0.17",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var createHash = require("crypto").createHash;
|
var createHash = require("crypto").createHash;
|
||||||
|
var fetch = require("./fetch");
|
||||||
var fork = require("child_process").fork;
|
var fork = require("child_process").fork;
|
||||||
var args = process.argv.slice(2);
|
var args = process.argv.slice(2);
|
||||||
if (!args.length) {
|
if (!args.length) {
|
||||||
@@ -52,7 +53,8 @@ urls.forEach(function(url) {
|
|||||||
output: 0,
|
output: 0,
|
||||||
log: ""
|
log: ""
|
||||||
};
|
};
|
||||||
require(url.slice(0, url.indexOf(":"))).get(url, function(res) {
|
fetch(url, function(err, res) {
|
||||||
|
if (err) throw err;
|
||||||
var uglifyjs = fork("bin/uglifyjs", args, { silent: true });
|
var uglifyjs = fork("bin/uglifyjs", args, { silent: true });
|
||||||
res.on("data", function(data) {
|
res.on("data", function(data) {
|
||||||
results[url].input += data.length;
|
results[url].input += data.length;
|
||||||
|
|||||||
@@ -135,3 +135,70 @@ arrow_with_regexp: {
|
|||||||
num => /\d{11,14}/.test( num )
|
num => /\d{11,14}/.test( num )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
arrow_unused: {
|
||||||
|
options = {
|
||||||
|
toplevel: false,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
top => dog;
|
||||||
|
let fn = a => { console.log(a * a); };
|
||||||
|
let u = (x, y) => x - y + g;
|
||||||
|
(() => { console.log("0"); })();
|
||||||
|
!function(x) {
|
||||||
|
(() => { console.log("1"); })();
|
||||||
|
let unused = x => { console.log(x); };
|
||||||
|
let baz = e => e + e;
|
||||||
|
console.log(baz(x));
|
||||||
|
}(1);
|
||||||
|
fn(3);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
let fn = a => { console.log(a * a); };
|
||||||
|
let u = (x, y) => x - y + g;
|
||||||
|
(() => { console.log("0"); })();
|
||||||
|
!function(x) {
|
||||||
|
(() => { console.log("1"); })();
|
||||||
|
let baz = e => e + e;
|
||||||
|
console.log(baz(x));
|
||||||
|
}(1);
|
||||||
|
fn(3);
|
||||||
|
}
|
||||||
|
expect_stdout: [ "0", "1", "2", "9" ]
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
|
arrow_unused_toplevel: {
|
||||||
|
options = {
|
||||||
|
toplevel: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
top => dog;
|
||||||
|
let fn = a => { console.log(a * a); };
|
||||||
|
let u = (x, y) => x - y + g;
|
||||||
|
(() => { console.log("0"); })();
|
||||||
|
!function(x) {
|
||||||
|
(() => { console.log("1"); })();
|
||||||
|
let unused = x => { console.log(x); };
|
||||||
|
let baz = e => e + e;
|
||||||
|
console.log(baz(x));
|
||||||
|
}(1);
|
||||||
|
fn(3);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
let fn = a => { console.log(a * a); };
|
||||||
|
(() => { console.log("0"); })();
|
||||||
|
!function(x) {
|
||||||
|
(() => { console.log("1"); })();
|
||||||
|
let baz = e => e + e;
|
||||||
|
console.log(baz(x));
|
||||||
|
}(1);
|
||||||
|
fn(3);
|
||||||
|
}
|
||||||
|
expect_stdout: [ "0", "1", "2", "9" ]
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|||||||
200
test/compress/async.js
Normal file
200
test/compress/async.js
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
await_precedence: {
|
||||||
|
input: {
|
||||||
|
async function f1() { await x + y; }
|
||||||
|
async function f2() { await (x + y); }
|
||||||
|
}
|
||||||
|
expect_exact: "async function f1(){await x+y}async function f2(){await(x+y)}"
|
||||||
|
}
|
||||||
|
|
||||||
|
async_function_declaration: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
async function f0() {}
|
||||||
|
async function f1() { await x + y; }
|
||||||
|
async function f2() { await (x + y); }
|
||||||
|
async function f3() { await x + await y; }
|
||||||
|
async function f4() { await (x + await y); }
|
||||||
|
async function f5() { await x; await y; }
|
||||||
|
async function f6() { await x, await y; }
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
async function f0() {}
|
||||||
|
async function f1() { await x, y; }
|
||||||
|
async function f2() { await (x + y); }
|
||||||
|
async function f3() { await x, await y; }
|
||||||
|
async function f4() { await (x + await y); }
|
||||||
|
async function f5() { await x; await y; }
|
||||||
|
async function f6() { await x, await y; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async_function_expression: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var named = async function foo() {
|
||||||
|
await bar(1 + 0) + (2 + 0);
|
||||||
|
}
|
||||||
|
var anon = async function() {
|
||||||
|
await (1 + 0) + bar(2 + 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var named = async function() {
|
||||||
|
await bar(1);
|
||||||
|
};
|
||||||
|
var anon = async function() {
|
||||||
|
await 1, bar(2);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async_class: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
class Foo {
|
||||||
|
async m1() {
|
||||||
|
return await foo(1 + 2);
|
||||||
|
}
|
||||||
|
static async m2() {
|
||||||
|
return await foo(3 + 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
class Foo {
|
||||||
|
async m1() {
|
||||||
|
return await foo(3);
|
||||||
|
}
|
||||||
|
static async m2() {
|
||||||
|
return await foo(7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async_object_literal: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var obj = {
|
||||||
|
async a() {
|
||||||
|
await foo(1 + 0);
|
||||||
|
},
|
||||||
|
anon: async function(){
|
||||||
|
await foo(2 + 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var obj = {
|
||||||
|
async a() {
|
||||||
|
await foo(1);
|
||||||
|
},
|
||||||
|
anon: async function() {
|
||||||
|
await foo(2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async_export: {
|
||||||
|
input: {
|
||||||
|
export async function run() {};
|
||||||
|
export default async function def() {};
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
export async function run() {};
|
||||||
|
export default async function def() {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async_inline: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
negate_iife: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(async function(){ return await 3; })();
|
||||||
|
(async function(x){ await console.log(x); })(4);
|
||||||
|
|
||||||
|
function echo(x) { return x; }
|
||||||
|
echo( async function(){ return await 1; }() );
|
||||||
|
echo( async function(x){ await console.log(x); }(2) );
|
||||||
|
|
||||||
|
function top() { console.log("top"); }
|
||||||
|
top();
|
||||||
|
|
||||||
|
async function async_top() { console.log("async_top"); }
|
||||||
|
async_top();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!async function(){await 3}();
|
||||||
|
!async function(x){await console.log(4)}();
|
||||||
|
|
||||||
|
function echo(x){return x}
|
||||||
|
echo(async function(){return await 1}());
|
||||||
|
echo(async function(x){await console.log(2)}());
|
||||||
|
|
||||||
|
console.log("top");
|
||||||
|
|
||||||
|
!async function(){console.log("async_top")}();
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"4",
|
||||||
|
"2",
|
||||||
|
"top",
|
||||||
|
"async_top",
|
||||||
|
]
|
||||||
|
node_version: ">=8"
|
||||||
|
}
|
||||||
|
|
||||||
|
async_identifiers: {
|
||||||
|
input: {
|
||||||
|
let async = function(x){ console.log("async", x); };
|
||||||
|
let await = function(x){ console.log("await", x); };
|
||||||
|
async(1);
|
||||||
|
await(2);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
let async = function(x){ console.log("async", x); };
|
||||||
|
let await = function(x){ console.log("await", x); };
|
||||||
|
async(1);
|
||||||
|
await(2);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"async 1",
|
||||||
|
"await 2",
|
||||||
|
]
|
||||||
|
node_version: ">=8"
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: add test when supported by parser
|
||||||
|
async_arrow: {
|
||||||
|
input: {
|
||||||
|
let a1 = async x => await foo(x);
|
||||||
|
let a2 = async () => await bar();
|
||||||
|
let a3 = async (x) => await baz(x);
|
||||||
|
let a4 = async (x, y) => { await far(x, y); }
|
||||||
|
let a5 = async ({x = [1], y: z = 2}) => { await wow(x, y); }
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
@@ -47,3 +47,142 @@ keep_some_blocks: {
|
|||||||
} else stuff();
|
} 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"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1146,7 +1146,7 @@ collapse_vars_constants: {
|
|||||||
function f3(x) {
|
function f3(x) {
|
||||||
var b = x.prop;
|
var b = x.prop;
|
||||||
sideeffect1();
|
sideeffect1();
|
||||||
return b + -9;
|
return b + (function() { return -9; })();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -543,3 +543,99 @@ mangle_destructuring_decl_array: {
|
|||||||
expect_stdout: "8 7 6 undefined 2 [ 3 ]"
|
expect_stdout: "8 7 6 undefined 2 [ 3 ]"
|
||||||
node_version: ">=6"
|
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"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2044_ecma_5: {
|
||||||
|
beautify = {
|
||||||
|
beautify: false,
|
||||||
|
ecma: 5,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
({x : a = 1, y = 2 + b, z = 3 - c} = obj);
|
||||||
|
}
|
||||||
|
expect_exact: "({x:a=1,y:y=2+b,z:z=3-c}=obj);"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2044_ecma_6: {
|
||||||
|
beautify = {
|
||||||
|
beautify: false,
|
||||||
|
ecma: 6,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
({x : a = 1, y = 2 + b, z = 3 - c} = obj);
|
||||||
|
}
|
||||||
|
expect_exact: "({x:a=1,y=2+b,z=3-c}=obj);"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2044_ecma_5_beautify: {
|
||||||
|
beautify = {
|
||||||
|
beautify: true,
|
||||||
|
ecma: 5,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
({x : a = 1, y = 2 + b, z = 3 - c} = obj);
|
||||||
|
}
|
||||||
|
expect_exact: "({x: a = 1, y: y = 2 + b, z: z = 3 - c} = obj);"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2044_ecma_6_beautify: {
|
||||||
|
beautify = {
|
||||||
|
beautify: true,
|
||||||
|
ecma: 6,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
({x : a = 1, y = 2 + b, z = 3 - c} = obj);
|
||||||
|
}
|
||||||
|
expect_exact: "({x: a = 1, y = 2 + b, z = 3 - c} = obj);"
|
||||||
|
}
|
||||||
|
|||||||
@@ -863,12 +863,12 @@ issue_1583: {
|
|||||||
expect: {
|
expect: {
|
||||||
function m(t) {
|
function m(t) {
|
||||||
(function(e) {
|
(function(e) {
|
||||||
t = (function() {
|
t = e();
|
||||||
|
})(function() {
|
||||||
return (function(a) {
|
return (function(a) {
|
||||||
return a;
|
return a;
|
||||||
})(function(a) {});
|
})(function(a) {});
|
||||||
})();
|
});
|
||||||
})();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1280,3 +1280,17 @@ issue_1968: {
|
|||||||
expect_stdout: "5"
|
expect_stdout: "5"
|
||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2063: {
|
||||||
|
options = {
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
var a;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
var a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -738,6 +738,7 @@ unsafe_prototype_function: {
|
|||||||
call_args: {
|
call_args: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
@@ -758,6 +759,7 @@ call_args: {
|
|||||||
call_args_drop_param: {
|
call_args_drop_param: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
keep_fargs: false,
|
keep_fargs: false,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
@@ -873,13 +875,15 @@ unsafe_charAt_noop: {
|
|||||||
input: {
|
input: {
|
||||||
console.log(
|
console.log(
|
||||||
s.charAt(0),
|
s.charAt(0),
|
||||||
"string".charAt(x)
|
"string".charAt(x),
|
||||||
|
(typeof x).charAt()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(
|
console.log(
|
||||||
s.charAt(0),
|
s.charAt(0),
|
||||||
"string".charAt(x)
|
"string".charAt(x),
|
||||||
|
(typeof x)[0]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1130,3 +1134,31 @@ issue_1964_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "b"
|
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"
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ iifes_returning_constants_keep_fargs_true: {
|
|||||||
join_vars : true,
|
join_vars : true,
|
||||||
reduce_vars : true,
|
reduce_vars : true,
|
||||||
cascade : true,
|
cascade : true,
|
||||||
|
inline : true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
(function(){ return -1.23; }());
|
(function(){ return -1.23; }());
|
||||||
@@ -56,6 +57,7 @@ iifes_returning_constants_keep_fargs_false: {
|
|||||||
join_vars : true,
|
join_vars : true,
|
||||||
reduce_vars : true,
|
reduce_vars : true,
|
||||||
cascade : true,
|
cascade : true,
|
||||||
|
inline : true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
(function(){ return -1.23; }());
|
(function(){ return -1.23; }());
|
||||||
@@ -82,6 +84,7 @@ issue_485_crashing_1530: {
|
|||||||
conditionals: true,
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
(function(a) {
|
(function(a) {
|
||||||
@@ -154,6 +157,7 @@ function_returning_constant_literal: {
|
|||||||
evaluate: true,
|
evaluate: true,
|
||||||
cascade: true,
|
cascade: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
|
inline: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
function greeter() {
|
function greeter() {
|
||||||
@@ -245,3 +249,168 @@ hoist_funs_strict: {
|
|||||||
]
|
]
|
||||||
node_version: ">=4"
|
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"
|
||||||
|
}
|
||||||
|
|
||||||
|
no_webkit: {
|
||||||
|
beautify = {
|
||||||
|
webkit: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
1 + 1;
|
||||||
|
}.a = 1);
|
||||||
|
}
|
||||||
|
expect_exact: "console.log(function(){1+1}.a=1);"
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
webkit: {
|
||||||
|
beautify = {
|
||||||
|
webkit: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
1 + 1;
|
||||||
|
}.a = 1);
|
||||||
|
}
|
||||||
|
expect_exact: "console.log((function(){1+1}).a=1);"
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2084: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = 0;
|
||||||
|
!function() {
|
||||||
|
!function(c) {
|
||||||
|
c = 1 + c;
|
||||||
|
var c = 0;
|
||||||
|
function f14(a_1) {
|
||||||
|
if (c = 1 + c, 0 !== 23..toString())
|
||||||
|
c = 1 + c, a_1 && (a_1[0] = 0);
|
||||||
|
}
|
||||||
|
f14();
|
||||||
|
}(-1);
|
||||||
|
}();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = 0;
|
||||||
|
!function(c) {
|
||||||
|
c = 1 + c,
|
||||||
|
c = 1 + (c = 0),
|
||||||
|
0 !== 23..toString() && (c = 1 + c);
|
||||||
|
}(-1),
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2097: {
|
||||||
|
options = {
|
||||||
|
negate_iife: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (e) {
|
||||||
|
console.log(arguments[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f(1);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function() {
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (e) {
|
||||||
|
console.log(arguments[0]);
|
||||||
|
}
|
||||||
|
}(1);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2101: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
a = {};
|
||||||
|
console.log(function() {
|
||||||
|
return function() {
|
||||||
|
return this.a;
|
||||||
|
}();
|
||||||
|
}() === function() {
|
||||||
|
return a;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a = {};
|
||||||
|
console.log(function() {
|
||||||
|
return this.a;
|
||||||
|
}() === a);
|
||||||
|
}
|
||||||
|
expect_stdout: "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
inner_ref: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a) {
|
||||||
|
return function() {
|
||||||
|
return a;
|
||||||
|
}();
|
||||||
|
}(1), function(a) {
|
||||||
|
return function(a) {
|
||||||
|
return a;
|
||||||
|
}();
|
||||||
|
}(2));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a) {
|
||||||
|
return a;
|
||||||
|
}(1), function(a) {
|
||||||
|
return a;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "1 undefined"
|
||||||
|
}
|
||||||
|
|||||||
@@ -583,3 +583,84 @@ class_extends_regex: {
|
|||||||
}
|
}
|
||||||
expect_exact: "function f(){class rx1 extends(/rx/){}}"
|
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"
|
||||||
|
}
|
||||||
|
|
||||||
|
class_expression_statement: {
|
||||||
|
options = {
|
||||||
|
toplevel: false,
|
||||||
|
side_effects: false,
|
||||||
|
unused: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(class {});
|
||||||
|
(class NamedClassExpr {});
|
||||||
|
let expr = (class AnotherClassExpr {});
|
||||||
|
class C {}
|
||||||
|
}
|
||||||
|
expect_exact: "(class{});(class NamedClassExpr{});let expr=class AnotherClassExpr{};class C{}"
|
||||||
|
}
|
||||||
|
|
||||||
|
class_expression_statement_unused: {
|
||||||
|
options = {
|
||||||
|
toplevel: false,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(class {});
|
||||||
|
(class NamedClassExpr {});
|
||||||
|
let expr = (class AnotherClassExpr {});
|
||||||
|
class C {}
|
||||||
|
}
|
||||||
|
expect_exact: "let expr=class{};class C{}"
|
||||||
|
}
|
||||||
|
|
||||||
|
class_expression_statement_unused_toplevel: {
|
||||||
|
options = {
|
||||||
|
toplevel: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(class {});
|
||||||
|
(class NamedClassExpr {});
|
||||||
|
let expr = (class AnotherClassExpr {});
|
||||||
|
class C {}
|
||||||
|
}
|
||||||
|
expect_exact: ""
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
unary_prefix: {
|
unary_prefix: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
|
|
||||||
compress_new_function: {
|
compress_new_function: {
|
||||||
options = {
|
options = {
|
||||||
unsafe: true
|
unsafe: true,
|
||||||
|
unsafe_Func: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
new Function("aa, bb", 'return aa;');
|
new Function("aa, bb", 'return aa;');
|
||||||
@@ -14,6 +15,7 @@ compress_new_function: {
|
|||||||
compress_new_function_with_destruct: {
|
compress_new_function_with_destruct: {
|
||||||
options = {
|
options = {
|
||||||
unsafe: true,
|
unsafe: true,
|
||||||
|
unsafe_Func: true,
|
||||||
ecma: 6
|
ecma: 6
|
||||||
}
|
}
|
||||||
beautify = {
|
beautify = {
|
||||||
@@ -26,9 +28,7 @@ compress_new_function_with_destruct: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
Function("a", "[b]", "return a");
|
Function("a", "[b]", "return a");
|
||||||
Function("a", "{bb}", "return a");
|
Function("a", "{bb:b}", "return a");
|
||||||
Function("[[a]]", "[{bb}]", 'return a');
|
Function("[[a]]", "[{bb:b}]", 'return a');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
483
test/compress/issue-281.js
Normal file
483
test/compress/issue-281.js
Normal file
@@ -0,0 +1,483 @@
|
|||||||
|
collapse_vars_constants: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f1(x) {
|
||||||
|
var a = 4, b = x.prop, c = 5, d = sideeffect1(), e = sideeffect2();
|
||||||
|
return b + (function() { return d - a * e - c; })();
|
||||||
|
}
|
||||||
|
function f2(x) {
|
||||||
|
var a = 4, b = x.prop, c = 5, not_used = sideeffect1(), e = sideeffect2();
|
||||||
|
return b + (function() { return -a * e - c; })();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f1(x) {
|
||||||
|
var b = x.prop, d = sideeffect1(), e = sideeffect2();
|
||||||
|
return b + (d - 4 * e - 5);
|
||||||
|
}
|
||||||
|
function f2(x) {
|
||||||
|
var b = x.prop;
|
||||||
|
sideeffect1();
|
||||||
|
return b + (-4 * sideeffect2() - 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
modified: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
inline: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f5(b) {
|
||||||
|
var a = function() {
|
||||||
|
return b;
|
||||||
|
}();
|
||||||
|
return b++ + a;
|
||||||
|
}
|
||||||
|
console.log(f5(1));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f5(b) {
|
||||||
|
var a = b;
|
||||||
|
return b++ + a;
|
||||||
|
}
|
||||||
|
console.log(f5(1));
|
||||||
|
}
|
||||||
|
expect_stdout: "2"
|
||||||
|
}
|
||||||
|
|
||||||
|
ref_scope: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
inline: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
var a = 1, b = 2, c = 3;
|
||||||
|
var a = c++, b = b /= a;
|
||||||
|
return function() {
|
||||||
|
return a;
|
||||||
|
}() + b;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
var a = 1, b = 2, c = 3;
|
||||||
|
b = b /= a = c++;
|
||||||
|
return a + b;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
safe_undefined: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
|
inline: true,
|
||||||
|
unsafe: false,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
mangle = {}
|
||||||
|
input: {
|
||||||
|
var a, c;
|
||||||
|
console.log(function(undefined) {
|
||||||
|
return function() {
|
||||||
|
if (a)
|
||||||
|
return b;
|
||||||
|
if (c)
|
||||||
|
return d;
|
||||||
|
};
|
||||||
|
}(1)());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, c;
|
||||||
|
console.log(a ? b : c ? d : void 0);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
negate_iife_3: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
expression: true,
|
||||||
|
inline: true,
|
||||||
|
negate_iife: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(){ return t })() ? console.log(true) : console.log(false);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
t ? console.log(true) : console.log(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
negate_iife_3_off: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
expression: true,
|
||||||
|
inline: true,
|
||||||
|
negate_iife: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(){ return t })() ? console.log(true) : console.log(false);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
t ? console.log(true) : console.log(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
negate_iife_4: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
expression: true,
|
||||||
|
inline: true,
|
||||||
|
negate_iife: true,
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(){ return t })() ? console.log(true) : console.log(false);
|
||||||
|
(function(){
|
||||||
|
console.log("something");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
t ? console.log(true) : console.log(false), void console.log("something");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
negate_iife_5: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
expression: true,
|
||||||
|
inline: true,
|
||||||
|
negate_iife: true,
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
if ((function(){ return t })()) {
|
||||||
|
foo(true);
|
||||||
|
} else {
|
||||||
|
bar(false);
|
||||||
|
}
|
||||||
|
(function(){
|
||||||
|
console.log("something");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
t ? foo(true) : bar(false), void console.log("something");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
negate_iife_5_off: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
expression: true,
|
||||||
|
inline: true,
|
||||||
|
negate_iife: false,
|
||||||
|
sequences: true,
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
if ((function(){ return t })()) {
|
||||||
|
foo(true);
|
||||||
|
} else {
|
||||||
|
bar(false);
|
||||||
|
}
|
||||||
|
(function(){
|
||||||
|
console.log("something");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
t ? foo(true) : bar(false), void console.log("something");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1254_negate_iife_true: {
|
||||||
|
options = {
|
||||||
|
expression: true,
|
||||||
|
inline: true,
|
||||||
|
negate_iife: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
return function() {
|
||||||
|
console.log('test')
|
||||||
|
};
|
||||||
|
})()();
|
||||||
|
}
|
||||||
|
expect_exact: 'void console.log("test");'
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1254_negate_iife_nested: {
|
||||||
|
options = {
|
||||||
|
expression: true,
|
||||||
|
inline: true,
|
||||||
|
negate_iife: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
return function() {
|
||||||
|
console.log('test')
|
||||||
|
};
|
||||||
|
})()()()()();
|
||||||
|
}
|
||||||
|
expect_exact: '(void console.log("test"))()()();'
|
||||||
|
}
|
||||||
|
|
||||||
|
negate_iife_issue_1073: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
negate_iife: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
unused: true,
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
new (function(a) {
|
||||||
|
return function Foo() {
|
||||||
|
this.x = a;
|
||||||
|
console.log(this);
|
||||||
|
};
|
||||||
|
}(7))();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
new function() {
|
||||||
|
this.x = 7,
|
||||||
|
console.log(this);
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1288_side_effects: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
negate_iife: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
if (w) ;
|
||||||
|
else {
|
||||||
|
(function f() {})();
|
||||||
|
}
|
||||||
|
if (!x) {
|
||||||
|
(function() {
|
||||||
|
x = {};
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
if (y)
|
||||||
|
(function() {})();
|
||||||
|
else
|
||||||
|
(function(z) {
|
||||||
|
return z;
|
||||||
|
})(0);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
w;
|
||||||
|
x || (x = {});
|
||||||
|
y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner_var_for_in_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
var a = 1, b = 2;
|
||||||
|
for (b in (function() {
|
||||||
|
return x(a, b, c);
|
||||||
|
})()) {
|
||||||
|
var c = 3, d = 4;
|
||||||
|
x(a, b, c, d);
|
||||||
|
}
|
||||||
|
x(a, b, c, d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
var a = 1, b = 2;
|
||||||
|
for (b in x(1, b, c)) {
|
||||||
|
var c = 3, d = 4;
|
||||||
|
x(1, b, c, d);
|
||||||
|
}
|
||||||
|
x(1, b, c, d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1595_3: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function f(a) {
|
||||||
|
return g(a + 1);
|
||||||
|
})(2);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
g(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1758: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(c) {
|
||||||
|
var undefined = 42;
|
||||||
|
return function() {
|
||||||
|
c--;
|
||||||
|
c--, c.toString();
|
||||||
|
return;
|
||||||
|
}();
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(c) {
|
||||||
|
var undefined = 42;
|
||||||
|
return c--, c--, void c.toString();
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
wrap_iife: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
negate_iife: false,
|
||||||
|
}
|
||||||
|
beautify = {
|
||||||
|
wrap_iife: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
return function() {
|
||||||
|
console.log('test')
|
||||||
|
};
|
||||||
|
})()();
|
||||||
|
}
|
||||||
|
expect_exact: 'void console.log("test");'
|
||||||
|
}
|
||||||
|
|
||||||
|
wrap_iife_in_expression: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
negate_iife: false,
|
||||||
|
}
|
||||||
|
beautify = {
|
||||||
|
wrap_iife: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
foo = (function () {
|
||||||
|
return bar();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_exact: 'foo=bar();'
|
||||||
|
}
|
||||||
|
|
||||||
|
wrap_iife_in_return_call: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
negate_iife: false,
|
||||||
|
}
|
||||||
|
beautify = {
|
||||||
|
wrap_iife: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
return (function() {
|
||||||
|
console.log('test')
|
||||||
|
})();
|
||||||
|
})()();
|
||||||
|
}
|
||||||
|
expect_exact: '(void console.log("test"))();'
|
||||||
|
}
|
||||||
|
|
||||||
|
pure_annotation: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
/*@__PURE__*/(function() {
|
||||||
|
console.log("hello");
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_exact: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_fargs: {
|
||||||
|
options = {
|
||||||
|
cascade: true,
|
||||||
|
inline: true,
|
||||||
|
keep_fargs: false,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
!function(a_1) {
|
||||||
|
a++;
|
||||||
|
}(a++ + (a && a.var));
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1;
|
||||||
|
!function() {
|
||||||
|
a++;
|
||||||
|
}(++a && a.var);
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "3"
|
||||||
|
}
|
||||||
|
|
||||||
|
keep_fargs: {
|
||||||
|
options = {
|
||||||
|
cascade: true,
|
||||||
|
inline: true,
|
||||||
|
keep_fargs: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
!function(a_1) {
|
||||||
|
a++;
|
||||||
|
}(a++ + (a && a.var));
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1;
|
||||||
|
!function(a_1) {
|
||||||
|
a++;
|
||||||
|
}(++a && a.var);
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "3"
|
||||||
|
}
|
||||||
@@ -22,7 +22,8 @@ negate_iife_1_off: {
|
|||||||
|
|
||||||
negate_iife_2: {
|
negate_iife_2: {
|
||||||
options = {
|
options = {
|
||||||
negate_iife: true
|
inline: true,
|
||||||
|
negate_iife: true,
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
(function(){ return {} })().x = 10;
|
(function(){ return {} })().x = 10;
|
||||||
@@ -32,6 +33,7 @@ negate_iife_2: {
|
|||||||
|
|
||||||
negate_iife_2_side_effects: {
|
negate_iife_2_side_effects: {
|
||||||
options = {
|
options = {
|
||||||
|
inline: true,
|
||||||
negate_iife: true,
|
negate_iife: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
}
|
}
|
||||||
@@ -58,6 +60,7 @@ negate_iife_3_evaluate: {
|
|||||||
options = {
|
options = {
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
negate_iife: true,
|
negate_iife: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
@@ -100,6 +103,7 @@ negate_iife_3_off_evaluate: {
|
|||||||
options = {
|
options = {
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
negate_iife: false,
|
negate_iife: false,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
eval_let: {
|
eval_let_6: {
|
||||||
input: {
|
input: {
|
||||||
eval("let a;");
|
eval("let a;");
|
||||||
console.log();
|
console.log();
|
||||||
@@ -10,3 +10,29 @@ eval_let: {
|
|||||||
expect_stdout: ""
|
expect_stdout: ""
|
||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eval_let_4: {
|
||||||
|
input: {
|
||||||
|
eval("let a;");
|
||||||
|
console.log();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
eval("let a;");
|
||||||
|
console.log();
|
||||||
|
}
|
||||||
|
expect_stdout: SyntaxError("Block-scoped declarations (let, const, function, class) not yet supported outside strict mode")
|
||||||
|
node_version: "4"
|
||||||
|
}
|
||||||
|
|
||||||
|
eval_let_0: {
|
||||||
|
input: {
|
||||||
|
eval("let a;");
|
||||||
|
console.log();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
eval("let a;");
|
||||||
|
console.log();
|
||||||
|
}
|
||||||
|
expect_stdout: SyntaxError("Unexpected identifier")
|
||||||
|
node_version: "<=0.12"
|
||||||
|
}
|
||||||
|
|||||||
@@ -557,3 +557,105 @@ native_prototype: {
|
|||||||
"".indexOf.call(e, "bar");
|
"".indexOf.call(e, "bar");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
accessor_boolean: {
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
var b = {
|
||||||
|
get true() {
|
||||||
|
return a;
|
||||||
|
},
|
||||||
|
set false(c) {
|
||||||
|
a = c;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
console.log(b.true, b.false = 2, b.true);
|
||||||
|
}
|
||||||
|
expect_exact: 'var a=1;var b={get true(){return a},set false(c){a=c}};console.log(b.true,b.false=2,b.true);'
|
||||||
|
expect_stdout: "1 2 2"
|
||||||
|
}
|
||||||
|
|
||||||
|
accessor_get_set: {
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
var b = {
|
||||||
|
get set() {
|
||||||
|
return a;
|
||||||
|
},
|
||||||
|
set get(c) {
|
||||||
|
a = c;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
console.log(b.set, b.get = 2, b.set);
|
||||||
|
}
|
||||||
|
expect_exact: 'var a=1;var b={get set(){return a},set get(c){a=c}};console.log(b.set,b.get=2,b.set);'
|
||||||
|
expect_stdout: "1 2 2"
|
||||||
|
}
|
||||||
|
|
||||||
|
accessor_null_undefined: {
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
var b = {
|
||||||
|
get null() {
|
||||||
|
return a;
|
||||||
|
},
|
||||||
|
set undefined(c) {
|
||||||
|
a = c;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
console.log(b.null, b.undefined = 2, b.null);
|
||||||
|
}
|
||||||
|
expect_exact: 'var a=1;var b={get null(){return a},set undefined(c){a=c}};console.log(b.null,b.undefined=2,b.null);'
|
||||||
|
expect_stdout: "1 2 2"
|
||||||
|
}
|
||||||
|
|
||||||
|
accessor_number: {
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
var b = {
|
||||||
|
get 42() {
|
||||||
|
return a;
|
||||||
|
},
|
||||||
|
set 42(c) {
|
||||||
|
a = c;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
console.log(b[42], b[42] = 2, b[42]);
|
||||||
|
}
|
||||||
|
expect_exact: 'var a=1;var b={get 42(){return a},set 42(c){a=c}};console.log(b[42],b[42]=2,b[42]);'
|
||||||
|
expect_stdout: "1 2 2"
|
||||||
|
}
|
||||||
|
|
||||||
|
accessor_string: {
|
||||||
|
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"
|
||||||
|
}
|
||||||
|
|
||||||
|
accessor_this: {
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
var b = {
|
||||||
|
get this() {
|
||||||
|
return a;
|
||||||
|
},
|
||||||
|
set this(c) {
|
||||||
|
a = c;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
console.log(b.this, b.this = 2, b.this);
|
||||||
|
}
|
||||||
|
expect_exact: 'var a=1;var b={get this(){return a},set this(c){a=c}};console.log(b.this,b.this=2,b.this);'
|
||||||
|
expect_stdout: "1 2 2"
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ reduce_vars: {
|
|||||||
options = {
|
options = {
|
||||||
conditionals : true,
|
conditionals : true,
|
||||||
evaluate : true,
|
evaluate : true,
|
||||||
|
inline : true,
|
||||||
global_defs : {
|
global_defs : {
|
||||||
C : 0
|
C : 0
|
||||||
},
|
},
|
||||||
@@ -1032,6 +1033,7 @@ defun_inline_2: {
|
|||||||
defun_inline_3: {
|
defun_inline_3: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
passes: 2,
|
passes: 2,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -1054,6 +1056,7 @@ defun_inline_3: {
|
|||||||
|
|
||||||
defun_call: {
|
defun_call: {
|
||||||
options = {
|
options = {
|
||||||
|
inline: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
@@ -1080,6 +1083,7 @@ defun_call: {
|
|||||||
|
|
||||||
defun_redefine: {
|
defun_redefine: {
|
||||||
options = {
|
options = {
|
||||||
|
inline: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
@@ -1112,6 +1116,7 @@ defun_redefine: {
|
|||||||
|
|
||||||
func_inline: {
|
func_inline: {
|
||||||
options = {
|
options = {
|
||||||
|
inline: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
@@ -1138,6 +1143,7 @@ func_inline: {
|
|||||||
|
|
||||||
func_modified: {
|
func_modified: {
|
||||||
options = {
|
options = {
|
||||||
|
inline: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
@@ -1311,19 +1317,47 @@ iife_func_side_effects: {
|
|||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
|
function x() {
|
||||||
|
console.log("x");
|
||||||
|
}
|
||||||
|
function y() {
|
||||||
|
console.log("y");
|
||||||
|
}
|
||||||
|
function z() {
|
||||||
|
console.log("z");
|
||||||
|
}
|
||||||
(function(a, b, c) {
|
(function(a, b, c) {
|
||||||
return b();
|
function y() {
|
||||||
|
console.log("FAIL");
|
||||||
|
}
|
||||||
|
return y + b();
|
||||||
})(x(), function() {
|
})(x(), function() {
|
||||||
return y();
|
return y();
|
||||||
}, z());
|
}, z());
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
|
function x() {
|
||||||
|
console.log("x");
|
||||||
|
}
|
||||||
|
function y() {
|
||||||
|
console.log("y");
|
||||||
|
}
|
||||||
|
function z() {
|
||||||
|
console.log("z");
|
||||||
|
}
|
||||||
(function(a, b, c) {
|
(function(a, b, c) {
|
||||||
return function() {
|
return function() {
|
||||||
|
console.log("FAIL");
|
||||||
|
} + b();
|
||||||
|
})(x(), function() {
|
||||||
return y();
|
return y();
|
||||||
}();
|
}, z());
|
||||||
})(x(), 0, z());
|
|
||||||
}
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"x",
|
||||||
|
"z",
|
||||||
|
"y",
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_1595_1: {
|
issue_1595_1: {
|
||||||
@@ -1687,6 +1721,7 @@ redefine_arguments_1: {
|
|||||||
redefine_arguments_2: {
|
redefine_arguments_2: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
keep_fargs: false,
|
keep_fargs: false,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -1723,6 +1758,7 @@ redefine_arguments_2: {
|
|||||||
redefine_arguments_3: {
|
redefine_arguments_3: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
keep_fargs: false,
|
keep_fargs: false,
|
||||||
passes: 3,
|
passes: 3,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
@@ -1799,6 +1835,7 @@ redefine_farg_1: {
|
|||||||
redefine_farg_2: {
|
redefine_farg_2: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
keep_fargs: false,
|
keep_fargs: false,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -1835,6 +1872,7 @@ redefine_farg_2: {
|
|||||||
redefine_farg_3: {
|
redefine_farg_3: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
keep_fargs: false,
|
keep_fargs: false,
|
||||||
passes: 3,
|
passes: 3,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
@@ -2537,3 +2575,53 @@ accessor: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "1 1"
|
expect_stdout: "1 1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2090_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
var x = 1;
|
||||||
|
[].forEach(() => x = 2);
|
||||||
|
return x;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
var x = 1;
|
||||||
|
[].forEach(() => x = 2);
|
||||||
|
return x;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2090_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
var x = 1;
|
||||||
|
[].forEach(() => {
|
||||||
|
x = 2;
|
||||||
|
});
|
||||||
|
return x;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
var x = 1;
|
||||||
|
[].forEach(() => {
|
||||||
|
x = 2;
|
||||||
|
});
|
||||||
|
return x;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|||||||
14
test/compress/sandbox.js
Normal file
14
test/compress/sandbox.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
console_log: {
|
||||||
|
input: {
|
||||||
|
console.log("%% %s");
|
||||||
|
console.log("%% %s", "%s");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("%% %s");
|
||||||
|
console.log("%% %s", "%s");
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"%% %s",
|
||||||
|
"% %s",
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -734,3 +734,23 @@ reassign_const: {
|
|||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2062: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
cascade: true,
|
||||||
|
conditionals: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
if ([ a || a++ + a--, a++ + a--, a && a.var ]);
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1;
|
||||||
|
a || (a++, a--), a++, --a && a.var;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|||||||
31
test/fetch.js
Normal file
31
test/fetch.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
var fs = require("fs");
|
||||||
|
var path = require("path");
|
||||||
|
|
||||||
|
try {
|
||||||
|
fs.mkdirSync("./tmp");
|
||||||
|
} catch (e) {
|
||||||
|
if (e.code != "EEXIST") throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
function local(url) {
|
||||||
|
return path.join("./tmp", encodeURIComponent(url));
|
||||||
|
}
|
||||||
|
|
||||||
|
function read(url) {
|
||||||
|
return fs.createReadStream(local(url));
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = function(url, callback) {
|
||||||
|
var result = read(url);
|
||||||
|
result.on("error", function(e) {
|
||||||
|
if (e.code != "ENOENT") return callback(e);
|
||||||
|
require(url.slice(0, url.indexOf(":"))).get(url, function(res) {
|
||||||
|
if (res.statusCode !== 200) return callback(res);
|
||||||
|
res.pipe(fs.createWriteStream(local(url)).on("close", function() {
|
||||||
|
callback(null, read(url));
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}).on("open", function() {
|
||||||
|
callback(null, result);
|
||||||
|
});
|
||||||
|
};
|
||||||
1
test/input/issue-2082/sample.js
Normal file
1
test/input/issue-2082/sample.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
console.log(x);
|
||||||
1
test/input/issue-2082/sample.js.map
Normal file
1
test/input/issue-2082/sample.js.map
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"version": 3,"sources": ["index.js"],"mappings": ";"}
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var site = "http://browserbench.org/JetStream/";
|
var site = "http://browserbench.org/JetStream";
|
||||||
if (typeof phantom == "undefined") {
|
if (typeof phantom == "undefined") {
|
||||||
// workaround for tty output truncation upon process.exit()
|
// workaround for tty output truncation upon process.exit()
|
||||||
[process.stdout, process.stderr].forEach(function(stream){
|
[process.stdout, process.stderr].forEach(function(stream){
|
||||||
@@ -11,25 +11,38 @@ if (typeof phantom == "undefined") {
|
|||||||
stream._handle.setBlocking(true);
|
stream._handle.setBlocking(true);
|
||||||
});
|
});
|
||||||
var args = process.argv.slice(2);
|
var args = process.argv.slice(2);
|
||||||
|
var debug = args.indexOf("--debug");
|
||||||
|
if (debug >= 0) {
|
||||||
|
args.splice(debug, 1);
|
||||||
|
debug = true;
|
||||||
|
} else {
|
||||||
|
debug = false;
|
||||||
|
}
|
||||||
if (!args.length) {
|
if (!args.length) {
|
||||||
args.push("-mc");
|
args.push("-mcb", "beautify=false,webkit");
|
||||||
}
|
}
|
||||||
args.push("--timings");
|
args.push("--timings");
|
||||||
var child_process = require("child_process");
|
var child_process = require("child_process");
|
||||||
try {
|
var fetch = require("./fetch");
|
||||||
require("phantomjs-prebuilt");
|
|
||||||
} catch(e) {
|
|
||||||
child_process.execSync("npm install phantomjs-prebuilt@2.1.14");
|
|
||||||
}
|
|
||||||
var http = require("http");
|
var http = require("http");
|
||||||
var server = http.createServer(function(request, response) {
|
var server = http.createServer(function(request, response) {
|
||||||
request.resume();
|
request.resume();
|
||||||
var url = decodeURIComponent(request.url.slice(1));
|
var url = site + request.url;
|
||||||
|
fetch(url, function(err, res) {
|
||||||
|
if (err) throw err;
|
||||||
|
response.writeHead(200, {
|
||||||
|
"Content-Type": {
|
||||||
|
css: "text/css",
|
||||||
|
js: "application/javascript",
|
||||||
|
png: "image/png"
|
||||||
|
}[url.slice(url.lastIndexOf(".") + 1)] || "text/html; charset=utf-8"
|
||||||
|
});
|
||||||
|
if (/\.js$/.test(url)) {
|
||||||
var stderr = "";
|
var stderr = "";
|
||||||
var uglifyjs = child_process.fork("bin/uglifyjs", args, {
|
var uglifyjs = child_process.fork("bin/uglifyjs", args, {
|
||||||
silent: true
|
silent: true
|
||||||
}).on("exit", function(code) {
|
}).on("exit", function(code) {
|
||||||
console.log("uglifyjs", url.indexOf(site) == 0 ? url.slice(site.length) : url, args.join(" "));
|
console.log("uglifyjs", url.slice(site.length + 1), args.join(" "));
|
||||||
console.log(stderr);
|
console.log(stderr);
|
||||||
if (code) throw new Error("uglifyjs failed with code " + code);
|
if (code) throw new Error("uglifyjs failed with code " + code);
|
||||||
});
|
});
|
||||||
@@ -37,20 +50,31 @@ if (typeof phantom == "undefined") {
|
|||||||
stderr += data;
|
stderr += data;
|
||||||
}).setEncoding("utf8");
|
}).setEncoding("utf8");
|
||||||
uglifyjs.stdout.pipe(response);
|
uglifyjs.stdout.pipe(response);
|
||||||
http.get(url, function(res) {
|
|
||||||
res.pipe(uglifyjs.stdin);
|
res.pipe(uglifyjs.stdin);
|
||||||
|
} else {
|
||||||
|
res.pipe(response);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}).listen().on("listening", function() {
|
}).listen();
|
||||||
var phantomjs = require("phantomjs-prebuilt");
|
server.on("listening", function() {
|
||||||
var program = phantomjs.exec(process.argv[1], server.address().port);
|
var port = server.address().port;
|
||||||
|
if (debug) {
|
||||||
|
console.log("http://localhost:" + port + "/");
|
||||||
|
} else {
|
||||||
|
child_process.exec("npm install phantomjs-prebuilt@2.1.14 --no-save", function(error) {
|
||||||
|
if (error) throw error;
|
||||||
|
var program = require("phantomjs-prebuilt").exec(process.argv[1], port);
|
||||||
program.stdout.pipe(process.stdout);
|
program.stdout.pipe(process.stdout);
|
||||||
program.stderr.pipe(process.stderr);
|
program.stderr.pipe(process.stderr);
|
||||||
program.on("exit", function(code) {
|
program.on("exit", function(code) {
|
||||||
server.close();
|
server.close();
|
||||||
if (code) throw new Error("JetStream failed!");
|
if (code) throw new Error("JetStream failed!");
|
||||||
console.log("JetStream completed successfully.");
|
console.log("JetStream completed successfully.");
|
||||||
|
process.exit(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
server.timeout = 0;
|
server.timeout = 0;
|
||||||
} else {
|
} else {
|
||||||
var page = require("webpage").create();
|
var page = require("webpage").create();
|
||||||
@@ -63,10 +87,6 @@ if (typeof phantom == "undefined") {
|
|||||||
phantom.exit(1);
|
phantom.exit(1);
|
||||||
};
|
};
|
||||||
var url = "http://localhost:" + require("system").args[1] + "/";
|
var url = "http://localhost:" + require("system").args[1] + "/";
|
||||||
page.onResourceRequested = function(requestData, networkRequest) {
|
|
||||||
if (/\.js$/.test(requestData.url))
|
|
||||||
networkRequest.changeUrl(url + encodeURIComponent(requestData.url));
|
|
||||||
}
|
|
||||||
page.onConsoleMessage = function(msg) {
|
page.onConsoleMessage = function(msg) {
|
||||||
if (/Error:/i.test(msg)) {
|
if (/Error:/i.test(msg)) {
|
||||||
console.error(msg);
|
console.error(msg);
|
||||||
@@ -77,8 +97,8 @@ if (typeof phantom == "undefined") {
|
|||||||
phantom.exit();
|
phantom.exit();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
page.open(site, function(status) {
|
page.open(url, function(status) {
|
||||||
if (status != "success") phantomjs.exit(1);
|
if (status != "success") phantom.exit(1);
|
||||||
page.evaluate(function() {
|
page.evaluate(function() {
|
||||||
JetStream.switchToQuick();
|
JetStream.switchToQuick();
|
||||||
JetStream.start();
|
JetStream.start();
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ function read(path) {
|
|||||||
describe("bin/uglifyjs", function () {
|
describe("bin/uglifyjs", function () {
|
||||||
var uglifyjscmd = '"' + process.argv[0] + '" bin/uglifyjs';
|
var uglifyjscmd = '"' + process.argv[0] + '" bin/uglifyjs';
|
||||||
it("should produce a functional build when using --self", function (done) {
|
it("should produce a functional build when using --self", function (done) {
|
||||||
this.timeout(15000);
|
this.timeout(30000);
|
||||||
|
|
||||||
var command = uglifyjscmd + ' --self -cm --wrap WrappedUglifyJS';
|
var command = uglifyjscmd + ' --self -cm --wrap WrappedUglifyJS';
|
||||||
|
|
||||||
@@ -77,6 +77,23 @@ describe("bin/uglifyjs", function () {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it("should not consider source map file content as source map file name (issue #2082)", function (done) {
|
||||||
|
var command = [
|
||||||
|
uglifyjscmd,
|
||||||
|
"test/input/issue-2082/sample.js",
|
||||||
|
"--source-map", "content=test/input/issue-2082/sample.js.map",
|
||||||
|
"--source-map", "url=inline",
|
||||||
|
].join(" ");
|
||||||
|
|
||||||
|
exec(command, function (err, stdout, stderr) {
|
||||||
|
if (err) throw err;
|
||||||
|
|
||||||
|
var stderrLines = stderr.split('\n');
|
||||||
|
assert.strictEqual(stderrLines[0], 'INFO: Using input source map: test/input/issue-2082/sample.js.map');
|
||||||
|
assert.notStrictEqual(stderrLines[1], 'INFO: Using input source map: {"version": 3,"sources": ["index.js"],"mappings": ";"}');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
it("Should work with --keep-fnames (mangle only)", function (done) {
|
it("Should work with --keep-fnames (mangle only)", function (done) {
|
||||||
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m';
|
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m';
|
||||||
|
|
||||||
@@ -557,7 +574,27 @@ describe("bin/uglifyjs", function () {
|
|||||||
exec(command, function (err, stdout, stderr) {
|
exec(command, function (err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
assert.ok(/^Supported options:\n\{[^}]+}\nERROR: `ascii-only` is not a supported option/.test(stderr), stderr);
|
assert.ok(/^Supported options:\n[\s\S]*?\nERROR: `ascii-only` is not a supported option/.test(stderr), stderr);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it("Should work with --mangle reserved=[]", function (done) {
|
||||||
|
var command = uglifyjscmd + ' test/input/issue-505/input.js -m reserved=[callback]';
|
||||||
|
|
||||||
|
exec(command, function (err, stdout) {
|
||||||
|
if (err) throw err;
|
||||||
|
|
||||||
|
assert.strictEqual(stdout, 'function test(callback){"aaaaaaaaaaaaaaaa";callback(err,data);callback(err,data)}\n');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it("Should work with --mangle reserved=false", function (done) {
|
||||||
|
var command = uglifyjscmd + ' test/input/issue-505/input.js -m reserved=false';
|
||||||
|
|
||||||
|
exec(command, function (err, stdout) {
|
||||||
|
if (err) throw err;
|
||||||
|
|
||||||
|
assert.strictEqual(stdout, 'function test(a){"aaaaaaaaaaaaaaaa";a(err,data);a(err,data)}\n');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ describe("bin/uglifyjs with input file globs", function() {
|
|||||||
exec(command, function(err, stdout) {
|
exec(command, function(err, stdout) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
|
|
||||||
assert.strictEqual(stdout, 'var print=console.log.bind(console),a=function(n){return 3*n}(3),b=function(n){return n/2}(12);print("qux",a,b),function(n){print("Foo:",2*n)}(11);\n');
|
assert.strictEqual(stdout, 'var print=console.log.bind(console);print("qux",9,6),print("Foo:",2*11);\n');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,6 +13,13 @@ describe("minify", function() {
|
|||||||
assert.strictEqual(result.code, 'function foo(n){return n?3:7}');
|
assert.strictEqual(result.code, 'function foo(n){return n?3:7}');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Should skip inherited keys from `files`", function() {
|
||||||
|
var files = Object.create({ skip: this });
|
||||||
|
files[0] = "alert(1 + 1)";
|
||||||
|
var result = Uglify.minify(files);
|
||||||
|
assert.strictEqual(result.code, "alert(2);");
|
||||||
|
});
|
||||||
|
|
||||||
describe("keep_quoted_props", function() {
|
describe("keep_quoted_props", function() {
|
||||||
it("Should preserve quotes in object literals", function() {
|
it("Should preserve quotes in object literals", function() {
|
||||||
var js = 'var foo = {"x": 1, y: 2, \'z\': 3};';
|
var js = 'var foo = {"x": 1, y: 2, \'z\': 3};';
|
||||||
@@ -106,7 +113,7 @@ describe("minify", function() {
|
|||||||
content: "inline"
|
content: "inline"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
assert.strictEqual(result.code, "var bar=function(){function foo(bar){return bar}return foo}();");
|
assert.strictEqual(result.code, "var bar=function(){return function(bar){return bar}}();");
|
||||||
assert.strictEqual(warnings.length, 1);
|
assert.strictEqual(warnings.length, 1);
|
||||||
assert.strictEqual(warnings[0], "inline source map not found");
|
assert.strictEqual(warnings[0], "inline source map not found");
|
||||||
} finally {
|
} finally {
|
||||||
@@ -207,5 +214,17 @@ describe("minify", function() {
|
|||||||
assert.ok(err instanceof Error);
|
assert.ok(err instanceof Error);
|
||||||
assert.strictEqual(err.stack.split(/\n/)[0], "Error: Can't handle expression: debugger");
|
assert.strictEqual(err.stack.split(/\n/)[0], "Error: Can't handle expression: debugger");
|
||||||
});
|
});
|
||||||
|
it("should skip inherited properties", function() {
|
||||||
|
var foo = Object.create({ skip: this });
|
||||||
|
foo.bar = 42;
|
||||||
|
var result = Uglify.minify("alert(FOO);", {
|
||||||
|
compress: {
|
||||||
|
global_defs: {
|
||||||
|
FOO: foo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
assert.strictEqual(result.code, "alert({bar:42});");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
var assert = require("assert");
|
var assert = require("assert");
|
||||||
|
var semver = require("semver");
|
||||||
var spawn = require("child_process").spawn;
|
var spawn = require("child_process").spawn;
|
||||||
|
|
||||||
if (!process.env.UGLIFYJS_TEST_ALL) return;
|
if (!process.env.UGLIFYJS_TEST_ALL) return;
|
||||||
|
|
||||||
function run(command, args, done) {
|
function run(command, args, done) {
|
||||||
var id = setInterval(function() {
|
|
||||||
process.stdout.write("\0");
|
|
||||||
}, 5 * 60 * 1000);
|
|
||||||
spawn(command, args, {
|
spawn(command, args, {
|
||||||
stdio: "ignore"
|
stdio: [ "ignore", 1, 2 ]
|
||||||
}).on("exit", function(code) {
|
}).on("exit", function(code) {
|
||||||
clearInterval(id);
|
|
||||||
assert.strictEqual(code, 0);
|
assert.strictEqual(code, 0);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
describe("test/benchmark.js", function() {
|
describe("test/benchmark.js", function() {
|
||||||
this.timeout(5 * 60 * 1000);
|
this.timeout(10 * 60 * 1000);
|
||||||
[
|
[
|
||||||
"-b",
|
"-b",
|
||||||
"-b bracketize",
|
"-b bracketize",
|
||||||
@@ -36,11 +33,9 @@ describe("test/benchmark.js", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (semver.satisfies(process.version, "0.12")) return;
|
||||||
describe("test/jetstream.js", function() {
|
describe("test/jetstream.js", function() {
|
||||||
this.timeout(20 * 60 * 1000);
|
this.timeout(20 * 60 * 1000);
|
||||||
it("Should install phantomjs-prebuilt", function(done) {
|
|
||||||
run("npm", ["install", "phantomjs-prebuilt@2.1.14"], done);
|
|
||||||
});
|
|
||||||
[
|
[
|
||||||
"-mc",
|
"-mc",
|
||||||
"-mc keep_fargs=false,passes=3,pure_getters,unsafe,unsafe_comps,unsafe_math,unsafe_proto",
|
"-mc keep_fargs=false,passes=3,pure_getters,unsafe,unsafe_comps,unsafe_math,unsafe_proto",
|
||||||
@@ -48,6 +43,7 @@ describe("test/jetstream.js", function() {
|
|||||||
it("Should pass with options " + options, function(done) {
|
it("Should pass with options " + options, function(done) {
|
||||||
var args = options.split(/ /);
|
var args = options.split(/ /);
|
||||||
args.unshift("test/jetstream.js");
|
args.unshift("test/jetstream.js");
|
||||||
|
args.push("-b", "beautify=false,webkit");
|
||||||
run(process.argv[0], args, done);
|
run(process.argv[0], args, done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ var uglify = require("../node");
|
|||||||
|
|
||||||
describe("spidermonkey export/import sanity test", function() {
|
describe("spidermonkey export/import sanity test", function() {
|
||||||
it("should produce a functional build when using --self with spidermonkey", function(done) {
|
it("should produce a functional build when using --self with spidermonkey", function(done) {
|
||||||
this.timeout(30000);
|
this.timeout(60000);
|
||||||
|
|
||||||
var uglifyjs = '"' + process.argv[0] + '" bin/uglifyjs';
|
var uglifyjs = '"' + process.argv[0] + '" bin/uglifyjs';
|
||||||
var command = uglifyjs + " --self -cm --wrap SpiderUglify -o spidermonkey | " +
|
var command = uglifyjs + " --self -cm --wrap SpiderUglify -o spidermonkey | " +
|
||||||
|
|||||||
@@ -294,8 +294,22 @@ function parse_test(file) {
|
|||||||
if (label.name == "expect_exact" || label.name == "node_version") {
|
if (label.name == "expect_exact" || label.name == "node_version") {
|
||||||
test[label.name] = read_string(stat);
|
test[label.name] = read_string(stat);
|
||||||
} else if (label.name == "expect_stdout") {
|
} else if (label.name == "expect_stdout") {
|
||||||
if (stat.TYPE == "SimpleStatement" && stat.body instanceof U.AST_Boolean) {
|
var body = stat.body;
|
||||||
test[label.name] = stat.body.value;
|
if (body instanceof U.AST_Boolean) {
|
||||||
|
test[label.name] = body.value;
|
||||||
|
} else if (body instanceof U.AST_Call) {
|
||||||
|
var ctor = global[body.expression.name];
|
||||||
|
assert.ok(ctor === Error || ctor.prototype instanceof Error, tmpl("Unsupported expect_stdout format [{line},{col}]", {
|
||||||
|
line: label.start.line,
|
||||||
|
col: label.start.col
|
||||||
|
}));
|
||||||
|
test[label.name] = ctor.apply(null, body.args.map(function(node) {
|
||||||
|
assert.ok(node instanceof U.AST_Constant, tmpl("Unsupported expect_stdout format [{line},{col}]", {
|
||||||
|
line: label.start.line,
|
||||||
|
col: label.start.col
|
||||||
|
}));
|
||||||
|
return node.value;
|
||||||
|
}));
|
||||||
} else {
|
} else {
|
||||||
test[label.name] = read_string(stat) + "\n";
|
test[label.name] = read_string(stat) + "\n";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,23 +19,25 @@ function safe_log(arg, level) {
|
|||||||
|
|
||||||
var FUNC_TOSTRING = [
|
var FUNC_TOSTRING = [
|
||||||
"Function.prototype.toString = Function.prototype.valueOf = function() {",
|
"Function.prototype.toString = Function.prototype.valueOf = function() {",
|
||||||
" var id = 0;",
|
" var id = 100000;",
|
||||||
" return function() {",
|
" return function() {",
|
||||||
' if (this === Array) return "[Function: Array]";',
|
' if (this === Array) return "[Function: Array]";',
|
||||||
' if (this === Object) return "[Function: Object]";',
|
' if (this === Object) return "[Function: Object]";',
|
||||||
" var i = this.name;",
|
" var i = this.name;",
|
||||||
' if (typeof i != "number") {',
|
' if (typeof i != "number") {',
|
||||||
" i = ++id;",
|
" i = ++id;",
|
||||||
|
].concat(Object.getOwnPropertyDescriptor(Function.prototype, "name").configurable ? [
|
||||||
' Object.defineProperty(this, "name", {',
|
' Object.defineProperty(this, "name", {',
|
||||||
" get: function() {",
|
" get: function() {",
|
||||||
" return i;",
|
" return i;",
|
||||||
" }",
|
" }",
|
||||||
" });",
|
" });",
|
||||||
|
] : [], [
|
||||||
" }",
|
" }",
|
||||||
' return "[Function: " + i + "]";',
|
' return "[Function: " + i + "]";',
|
||||||
" }",
|
" }",
|
||||||
"}();",
|
"}();",
|
||||||
].join("\n");
|
]).join("\n");
|
||||||
exports.run_code = function(code) {
|
exports.run_code = function(code) {
|
||||||
var stdout = "";
|
var stdout = "";
|
||||||
var original_write = process.stdout.write;
|
var original_write = process.stdout.write;
|
||||||
@@ -50,7 +52,10 @@ exports.run_code = function(code) {
|
|||||||
"}();",
|
"}();",
|
||||||
].join("\n"), {
|
].join("\n"), {
|
||||||
console: {
|
console: {
|
||||||
log: function() {
|
log: function(msg) {
|
||||||
|
if (arguments.length == 1 && typeof msg == "string") {
|
||||||
|
return console.log("%s", msg);
|
||||||
|
}
|
||||||
return console.log.apply(console, [].map.call(arguments, function(arg) {
|
return console.log.apply(console, [].map.call(arguments, function(arg) {
|
||||||
return safe_log(arg, 3);
|
return safe_log(arg, 3);
|
||||||
}));
|
}));
|
||||||
|
|||||||
140
test/ufuzz.js
140
test/ufuzz.js
@@ -102,23 +102,23 @@ for (var i = 2; i < process.argv.length; ++i) {
|
|||||||
case '--help':
|
case '--help':
|
||||||
case '-h':
|
case '-h':
|
||||||
case '-?':
|
case '-?':
|
||||||
console.log('** UglifyJS fuzzer help **');
|
println('** UglifyJS fuzzer help **');
|
||||||
console.log('Valid options (optional):');
|
println('Valid options (optional):');
|
||||||
console.log('<number>: generate this many cases (if used must be first arg)');
|
println('<number>: generate this many cases (if used must be first arg)');
|
||||||
console.log('-v: print every generated test case');
|
println('-v: print every generated test case');
|
||||||
console.log('-V: print every 100th generated test case');
|
println('-V: print every 100th generated test case');
|
||||||
console.log('-t <int>: generate this many toplevels per run (more take longer)');
|
println('-t <int>: generate this many toplevels per run (more take longer)');
|
||||||
console.log('-r <int>: maximum recursion depth for generator (higher takes longer)');
|
println('-r <int>: maximum recursion depth for generator (higher takes longer)');
|
||||||
console.log('-s1 <statement name>: force the first level statement to be this one (see list below)');
|
println('-s1 <statement name>: force the first level statement to be this one (see list below)');
|
||||||
console.log('-s2 <statement name>: force the second level statement to be this one (see list below)');
|
println('-s2 <statement name>: force the second level statement to be this one (see list below)');
|
||||||
console.log('--no-catch-redef: do not redefine catch variables');
|
println('--no-catch-redef: do not redefine catch variables');
|
||||||
console.log('--no-directive: do not generate directives');
|
println('--no-directive: do not generate directives');
|
||||||
console.log('--use-strict: generate "use strict"');
|
println('--use-strict: generate "use strict"');
|
||||||
console.log('--stmt-depth-from-func: reset statement depth counter at each function, counts from global otherwise');
|
println('--stmt-depth-from-func: reset statement depth counter at each function, counts from global otherwise');
|
||||||
console.log('--only-stmt <statement names>: a comma delimited white list of statements that may be generated');
|
println('--only-stmt <statement names>: a comma delimited white list of statements that may be generated');
|
||||||
console.log('--without-stmt <statement names>: a comma delimited black list of statements never to generate');
|
println('--without-stmt <statement names>: a comma delimited black list of statements never to generate');
|
||||||
console.log('List of accepted statement names: ' + Object.keys(STMT_ARG_TO_ID));
|
println('List of accepted statement names: ' + Object.keys(STMT_ARG_TO_ID));
|
||||||
console.log('** UglifyJS fuzzer exiting **');
|
println('** UglifyJS fuzzer exiting **');
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
// first arg may be a number.
|
// first arg may be a number.
|
||||||
@@ -941,7 +941,17 @@ if (require.main !== module) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
function try_beautify(code, result) {
|
function println(msg) {
|
||||||
|
if (typeof msg != "undefined") process.stdout.write(msg);
|
||||||
|
process.stdout.write("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
function errorln(msg) {
|
||||||
|
if (typeof msg != "undefined") process.stderr.write(msg);
|
||||||
|
process.stderr.write("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
function try_beautify(code, result, printfn) {
|
||||||
var beautified = UglifyJS.minify(code, {
|
var beautified = UglifyJS.minify(code, {
|
||||||
compress: false,
|
compress: false,
|
||||||
mangle: false,
|
mangle: false,
|
||||||
@@ -951,15 +961,15 @@ function try_beautify(code, result) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (beautified.error) {
|
if (beautified.error) {
|
||||||
console.log("// !!! beautify failed !!!");
|
printfn("// !!! beautify failed !!!");
|
||||||
console.log(beautified.error.stack);
|
printfn(beautified.error.stack);
|
||||||
} else if (sandbox.same_stdout(sandbox.run_code(beautified.code), result)) {
|
} else if (sandbox.same_stdout(sandbox.run_code(beautified.code), result)) {
|
||||||
console.log("// (beautified)");
|
printfn("// (beautified)");
|
||||||
console.log(beautified.code);
|
printfn(beautified.code);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log("//");
|
printfn("//");
|
||||||
console.log(code);
|
printfn(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
var default_options = UglifyJS.default_options();
|
var default_options = UglifyJS.default_options();
|
||||||
@@ -977,8 +987,8 @@ function log_suspects(minify_options, component) {
|
|||||||
m[component] = o;
|
m[component] = o;
|
||||||
var result = UglifyJS.minify(original_code, m);
|
var result = UglifyJS.minify(original_code, m);
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
console.log("Error testing options." + component + "." + name);
|
errorln("Error testing options." + component + "." + name);
|
||||||
console.log(result.error);
|
errorln(result.error.stack);
|
||||||
} else {
|
} else {
|
||||||
var r = sandbox.run_code(result.code);
|
var r = sandbox.run_code(result.code);
|
||||||
return sandbox.same_stdout(original_result, r);
|
return sandbox.same_stdout(original_result, r);
|
||||||
@@ -986,49 +996,49 @@ function log_suspects(minify_options, component) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (suspects.length > 0) {
|
if (suspects.length > 0) {
|
||||||
console.log("Suspicious", component, "options:");
|
errorln("Suspicious " + component + " options:");
|
||||||
suspects.forEach(function(name) {
|
suspects.forEach(function(name) {
|
||||||
console.log(" " + name);
|
errorln(" " + name);
|
||||||
});
|
});
|
||||||
console.log();
|
errorln();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function log(options) {
|
function log(options) {
|
||||||
if (!ok) console.log('\n\n\n\n\n\n!!!!!!!!!!\n\n\n');
|
if (!ok) errorln('\n\n\n\n\n\n!!!!!!!!!!\n\n\n');
|
||||||
console.log("//=============================================================");
|
errorln("//=============================================================");
|
||||||
if (!ok) console.log("// !!!!!! Failed... round", round);
|
if (!ok) errorln("// !!!!!! Failed... round " + round);
|
||||||
console.log("// original code");
|
errorln("// original code");
|
||||||
try_beautify(original_code, original_result);
|
try_beautify(original_code, original_result, errorln);
|
||||||
console.log();
|
errorln();
|
||||||
console.log();
|
errorln();
|
||||||
console.log("//-------------------------------------------------------------");
|
errorln("//-------------------------------------------------------------");
|
||||||
if (typeof uglify_code == "string") {
|
if (typeof uglify_code == "string") {
|
||||||
console.log("// uglified code");
|
errorln("// uglified code");
|
||||||
try_beautify(uglify_code, uglify_result);
|
try_beautify(uglify_code, uglify_result, errorln);
|
||||||
console.log();
|
errorln();
|
||||||
console.log();
|
errorln();
|
||||||
console.log("original result:");
|
errorln("original result:");
|
||||||
console.log(original_result);
|
errorln(typeof original_result == "string" ? original_result : original_result.stack);
|
||||||
console.log("uglified result:");
|
errorln("uglified result:");
|
||||||
console.log(uglify_result);
|
errorln(typeof uglify_result == "string" ? uglify_result : uglify_result.stack);
|
||||||
} else {
|
} else {
|
||||||
console.log("// !!! uglify failed !!!");
|
errorln("// !!! uglify failed !!!");
|
||||||
console.log(uglify_code.stack);
|
errorln(uglify_code.stack);
|
||||||
if (typeof original_result != "string") {
|
if (typeof original_result != "string") {
|
||||||
console.log();
|
errorln();
|
||||||
console.log();
|
errorln();
|
||||||
console.log("original stacktrace:");
|
errorln("original stacktrace:");
|
||||||
console.log(original_result.stack);
|
errorln(original_result.stack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log("minify(options):");
|
errorln("minify(options):");
|
||||||
options = JSON.parse(options);
|
options = JSON.parse(options);
|
||||||
console.log(options);
|
errorln(JSON.stringify(options, null, 2));
|
||||||
console.log();
|
errorln();
|
||||||
if (!ok && typeof uglify_code == "string") {
|
if (!ok && typeof uglify_code == "string") {
|
||||||
Object.keys(default_options).forEach(log_suspects.bind(null, options));
|
Object.keys(default_options).forEach(log_suspects.bind(null, options));
|
||||||
console.log("!!!!!! Failed... round", round);
|
errorln("!!!!!! Failed... round " + round);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1058,19 +1068,19 @@ for (var round = 1; round <= num_iterations; round++) {
|
|||||||
}
|
}
|
||||||
if (verbose || (verbose_interval && !(round % INTERVAL_COUNT)) || !ok) log(options);
|
if (verbose || (verbose_interval && !(round % INTERVAL_COUNT)) || !ok) log(options);
|
||||||
else if (typeof original_result != "string") {
|
else if (typeof original_result != "string") {
|
||||||
console.log("//=============================================================");
|
println("//=============================================================");
|
||||||
console.log("// original code");
|
println("// original code");
|
||||||
try_beautify(original_code, original_result);
|
try_beautify(original_code, original_result, println);
|
||||||
console.log();
|
println();
|
||||||
console.log();
|
println();
|
||||||
console.log("original result:");
|
println("original result:");
|
||||||
console.log(original_result);
|
println(original_result.stack);
|
||||||
console.log();
|
println();
|
||||||
}
|
}
|
||||||
if (!ok && isFinite(num_iterations)) {
|
if (!ok && isFinite(num_iterations)) {
|
||||||
console.log();
|
println();
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
console.log();
|
println();
|
||||||
|
|||||||
Reference in New Issue
Block a user