Compare commits

..

57 Commits

Author SHA1 Message Date
Alex Lam S.L
e3c565b46f v3.5.1 2019-03-21 13:54:14 +08:00
Alex Lam S.L
54b0b49b68 enhance inline (#3352) 2019-03-21 02:58:33 +08:00
Alex Lam S.L
65648d84a5 enhance collapse_vars (#3351) 2019-03-20 23:31:21 +08:00
Alex Lam S.L
fd788590f6 v3.5.0 2019-03-20 18:43:54 +08:00
Alex Lam S.L
143f9054da fix corner case in sequences (#3350) 2019-03-20 14:54:26 +08:00
Alex Lam S.L
f2286c33f1 enhance unsafe for Array (#3349) 2019-03-20 06:37:51 +08:00
Alex Lam S.L
b9615f7a62 improve compress performance (#3348)
fixes #3174
2019-03-20 02:53:04 +08:00
Alex Lam S.L
c520e99eda enhance comparisons (#3347) 2019-03-19 01:34:25 +08:00
Alex Lam S.L
615ae37ca3 introduce assignments (#3345) 2019-03-18 21:28:41 +08:00
Alex Lam S.L
7aa7f21872 fix corner case in evaluate (#3344) 2019-03-18 21:24:42 +08:00
Alex Lam S.L
4430a436eb fix corner case in inline (#3343) 2019-03-17 05:31:40 +08:00
Alex Lam S.L
9707ccdc9f v3.4.10 2019-03-16 00:16:21 +08:00
Alex Lam S.L
cb8f3a2a31 add Node.js 10 to CI tests (#3342) 2019-03-15 16:45:12 +08:00
Alex Lam S.L
8b3259e0c2 fix corner case in reduce_vars (#3341) 2019-03-15 16:06:47 +08:00
Alex Lam S.L
b66f47b8dd update dependencies
- acorn@6.1.1
- commander@2.19.0
- semver@5.6.0
2019-03-15 14:49:48 +08:00
Alex Lam S.L
8d2e6f333e fix function inlining after reduce_vars (#3340)
fixes #3297
2019-03-15 05:45:46 +08:00
Alex Lam S.L
b3ef5e514d enhance evaluate (#3339)
fixes #3299
2019-03-15 02:48:23 +08:00
Alex Lam S.L
627f5fb41e fix corner case with nameCache (#3338)
fixes #3301
2019-03-15 01:15:50 +08:00
Alex Lam S.L
d90777b724 parse mangle.properties.regex in --config-file properly (#3337)
fixes #3315
2019-03-15 00:20:20 +08:00
Alex Lam S.L
e49297e5eb improve usability of pure_funcs (#3336)
fixes #3325
2019-03-14 21:36:45 +08:00
Alex Lam S.L
ebd82b3fb6 fix corner case in collapse_vars (#3334)
fixes #3274
2019-03-14 16:05:56 +08:00
Alex Lam S.L
d074aa6e27 fix corner case in collapse_vars (#3333)
fixes #3247
fixes #3305
fixes #3314
fixes #3327
2019-03-13 23:48:52 +08:00
Alex Lam S.L
b052f62710 fix corner case in reduce_vars (#3332)
fixes #3267
2019-03-13 21:56:38 +08:00
Alex Lam S.L
d4ac84b255 fix corner case in arguments & reduce_vars (#3331)
fixes #3282
2019-03-13 08:46:03 +08:00
Alex Lam S.L
e250396d7e fix corner case in arguments (#3330)
Track modifications to `arguments[i]` under Strict Mode.

fixes #3273
2019-03-13 06:59:53 +08:00
Seul-gi Choi(Chase)
c6fa39b482 Update README.md (#3311)
fix anchor for mangle-options
2019-03-13 05:31:04 +08:00
silverwind
9aae4f2424 make tests compatible with Node.js 12 (#3304)
In Node.js 12, the formatting of console arguments will change slightly.
Previously, a string other than the first argument was formatted using
single quotes if the first argument was non-string. Now, quotes are
never added regardless of position of a string argument.

To make test compatible in all Node.js versions, I work around by
ensuring the first argument to console.log is a string which prevents
the quotes from being added on older versions of Node.js.

Ref: https://github.com/nodejs/node/pull/23162
2019-03-13 04:55:04 +08:00
Alex Lam S.L
008c236137 fix corner case in conditionals (#3329)
fixes #3245
fixes #3257
fixes #3260
fixes #3269
fixes #3271
fixes #3278
fixes #3309
fixes #3319
fixes #3321
2019-03-13 04:28:21 +08:00
Ed S
b1c0664066 Fix typo in warning (#3324)
protoype -> prototype
2019-03-13 02:15:54 +08:00
Alex Lam S.L
ea999b0e92 v3.4.9 2018-08-31 04:28:21 +00:00
Alex Lam S.L
ce7e220de4 fix corner case in conditionals (#3244) 2018-08-30 15:59:05 +08:00
Alex Lam S.L
2bdaca10ae enhance conditionals (#3243) 2018-08-30 01:06:34 +08:00
Alex Lam S.L
aa0029204e fix corner case in reduce_vars (#3241)
fixes #3240
2018-08-29 22:14:25 +08:00
Alex Lam S.L
f352bcec3a fix corner case in collapse_vars (#3239)
fixes #3238
2018-08-29 11:34:34 +08:00
Alex Lam S.L
08514030f4 v3.4.8 2018-08-23 15:27:34 +08:00
Alex Lam S.L
694ca5d045 fix corner case in unused (#3234)
fixes #3233
2018-08-23 06:03:39 +08:00
Alex Lam S.L
57fb58b263 enhance if_return (#3232) 2018-08-21 18:34:16 +08:00
alexlamsl
18c1c9b38a update dependencies
- commander@2.17.1
2018-08-14 17:06:09 +08:00
Alex Lam S.L
5c1ae3662d v3.4.7 2018-08-09 14:47:24 +00:00
Alex Lam S.L
cfebeb2f63 fix corner case in mangle workaround for Safari (#3230)
fixes #3227
2018-08-09 17:34:28 +08:00
Alex Lam S.L
fc78423f1d clean up webkit quirks (#3229) 2018-08-08 16:15:45 +08:00
Alex Lam S.L
2a5277b391 v3.4.6 2018-07-27 11:35:26 +00:00
Alex Lam S.L
d47547dc71 fix corner case in join_vars (#3224) 2018-07-27 19:34:44 +08:00
Alex Lam S.L
304db15a20 fix corner case in ie8 & rename (#3223) 2018-07-26 16:35:43 +08:00
Alex Lam S.L
7cf72b8d66 fix corner case in global_defs (#3218)
fixes #3217
2018-07-19 18:14:36 +08:00
Alex Lam S.L
cea685f8d9 fix corner case in ie8 (#3216)
fixes #3215
2018-07-19 14:45:36 +08:00
Alex Lam S.L
8d4b5344f4 v3.4.5 2018-07-16 18:43:30 +00:00
alexlamsl
34a0ab6f2c improve fuzzing on Travis CI 2018-07-13 02:05:52 +08:00
Alex Lam S.L
bcebacbb9e fix corner cases in preserve_line (#3212) 2018-07-13 01:51:10 +08:00
Alex Lam S.L
018a5a750a v3.4.4 2018-07-09 01:09:56 +00:00
alexlamsl
b468103f26 use nvs for CI testing 2018-07-05 18:49:29 +08:00
Alex Lam S.L
66c126ffde fix corner case in ie8 (#3207)
fixes #3206
2018-07-03 16:44:23 +08:00
Alex Lam S.L
fdee083465 v3.4.3 2018-07-02 06:03:18 +00:00
alexlamsl
5ffc17d4aa fix corner case in unused 2018-07-01 14:34:42 +08:00
alexlamsl
6aa750010f update dependencies
- acorn@5.7.1
- commander@2.16.0
2018-07-01 01:49:43 +08:00
Alex Lam S.L
76df77c08c implement directives (#3203)
fixes #3166
2018-06-28 18:16:49 +08:00
Alex Lam S.L
957d5537a8 improve unsafe comparisons (#3200) 2018-06-28 03:46:19 +08:00
94 changed files with 5838 additions and 2274 deletions

View File

@@ -1,14 +1,35 @@
language: node_js addons:
node_js: apt:
- "0.10" sources:
- "0.12" - ubuntu-toolchain-r-test
- "4" packages:
- "6" - libstdc++-4.9-dev
- "8" cache:
env: directories: tmp
- UGLIFYJS_TEST_ALL=1 language: generic
matrix: matrix:
fast_finish: true fast_finish: true
sudo: false sudo: false
cache: env:
directories: tmp global:
- UGLIFYJS_TEST_ALL=1
matrix:
- NODEJS_VER=node/0.10
- NODEJS_VER=node/0.12
- NODEJS_VER=node/4
- NODEJS_VER=node/6
- NODEJS_VER=node/8
- NODEJS_VER=node/10
- NODEJS_VER=node/latest
before_install:
- git clone --branch v1.4.2 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
- . ~/.nvs/nvs.sh
- nvs --version
install:
- nvs add $NODEJS_VER
- nvs use $NODEJS_VER
- node --version
- npm --version --no-update-notifier
- npm install --no-optional --no-save --no-update-notifier
script:
- npm test --no-update-notifier

View File

@@ -605,6 +605,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `arguments` (default: `true`) -- replace `arguments[index]` with function - `arguments` (default: `true`) -- replace `arguments[index]` with function
parameter name whenever possible. parameter name whenever possible.
- `assignments` (default: `true`) -- apply optimizations to assignment expressions.
- `booleans` (default: `true`) -- various optimizations for boolean context, - `booleans` (default: `true`) -- various optimizations for boolean context,
for example `!!a ? b : c → a ? b : c` for example `!!a ? b : c → a ? b : c`
@@ -620,6 +622,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `dead_code` (default: `true`) -- remove unreachable code - `dead_code` (default: `true`) -- remove unreachable code
- `directives` (default: `true`) -- remove redundant or non-standard directives
- `drop_console` (default: `false`) -- Pass `true` to discard calls to - `drop_console` (default: `false`) -- Pass `true` to discard calls to
`console.*` functions. If you wish to drop a specific function call `console.*` functions. If you wish to drop a specific function call
such as `console.info` and/or retain side effects from function arguments such as `console.info` and/or retain side effects from function arguments
@@ -662,7 +666,7 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `keep_fnames` (default: `false`) -- Pass `true` to prevent the - `keep_fnames` (default: `false`) -- Pass `true` to prevent the
compressor from discarding function names. Useful for code relying on compressor from discarding function names. Useful for code relying on
`Function.prototype.name`. See also: the `keep_fnames` [mangle option](#mangle). `Function.prototype.name`. See also: the `keep_fnames` [mangle option](#mangle-options).
- `keep_infinity` (default: `false`) -- Pass `true` to prevent `Infinity` from - `keep_infinity` (default: `false`) -- Pass `true` to prevent `Infinity` from
being compressed into `1/0`, which may cause performance issues on Chrome. being compressed into `1/0`, which may cause performance issues on Chrome.
@@ -855,8 +859,8 @@ can pass additional arguments that control the code output:
adjust for this text. Can be used to insert a comment containing adjust for this text. Can be used to insert a comment containing
licensing information, for example. licensing information, for example.
- `preserve_line` (default `false`) -- pass `true` to preserve lines, but it - `preserve_line` (default `false`) -- pass `true` to retain line numbering on
only works if `beautify` is set to `false`. a best effort basis.
- `quote_keys` (default `false`) -- pass `true` to quote all keys in literal - `quote_keys` (default `false`) -- pass `true` to quote all keys in literal
objects objects

View File

@@ -1,20 +1,26 @@
environment: environment:
UGLIFYJS_TEST_ALL: 1
matrix: matrix:
- nodejs_version: "0.10" - NODEJS_VER: node/0.10
- nodejs_version: "0.12" - NODEJS_VER: node/0.12
- nodejs_version: "4" - NODEJS_VER: node/4
- nodejs_version: "6" - NODEJS_VER: node/6
- nodejs_version: "8" - NODEJS_VER: node/8
- NODEJS_VER: node/10
- NODEJS_VER: node/latest
install: install:
- ps: Install-Product node $env:nodejs_version - git clone --branch v1.4.2 --depth 1 https://github.com/jasongin/nvs.git %LOCALAPPDATA%\nvs
- set UGLIFYJS_TEST_ALL=1 - set PATH=%LOCALAPPDATA%\nvs;%PATH%
- npm install - nvs --version
- nvs add %NODEJS_VER%
- nvs use %NODEJS_VER%
- node --version
- npm --version --no-update-notifier
- npm install --no-optional --no-save --no-update-notifier
build: off build: off
cache: cache:
- tmp - tmp
matrix: matrix:
fast_finish: true fast_finish: true
test_script: test_script:
- node --version - npm test --no-update-notifier
- npm --version
- npm test

View File

@@ -56,6 +56,11 @@ program.option("--wrap <name>", "Embed everything as a function with “exports
program.arguments("[files...]").parseArgv(process.argv); program.arguments("[files...]").parseArgv(process.argv);
if (program.configFile) { if (program.configFile) {
options = JSON.parse(read_file(program.configFile)); options = JSON.parse(read_file(program.configFile));
if (options.mangle && options.mangle.properties && options.mangle.properties.regex) {
options.mangle.properties.regex = UglifyJS.parse(options.mangle.properties.regex, {
expression: true
}).getValue();
}
} }
if (!program.output && program.sourceMap && program.sourceMap.url != "inline") { if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
fatal("ERROR: cannot write source map to STDOUT"); fatal("ERROR: cannot write source map to STDOUT");
@@ -100,7 +105,7 @@ if (program.mangleProps) {
if (typeof program.mangleProps != "object") program.mangleProps = {}; if (typeof program.mangleProps != "object") program.mangleProps = {};
if (!Array.isArray(program.mangleProps.reserved)) program.mangleProps.reserved = []; if (!Array.isArray(program.mangleProps.reserved)) program.mangleProps.reserved = [];
require("../tools/domprops").forEach(function(name) { require("../tools/domprops").forEach(function(name) {
UglifyJS._push_uniq(program.mangleProps.reserved, name); UglifyJS.push_uniq(program.mangleProps.reserved, name);
}); });
} }
if (typeof options.mangle != "object") options.mangle = {}; if (typeof options.mangle != "object") options.mangle = {};
@@ -337,17 +342,9 @@ function parse_js(flag) {
return function(value, options) { return function(value, options) {
options = options || {}; options = options || {};
try { try {
UglifyJS.minify(value, { UglifyJS.parse(value, {
parse: { expression: true
expression: true }).walk(new UglifyJS.TreeWalker(function(node) {
},
compress: false,
mangle: false,
output: {
ast: true,
code: false
}
}).ast.walk(new UglifyJS.TreeWalker(function(node) {
if (node instanceof UglifyJS.AST_Assign) { if (node instanceof UglifyJS.AST_Assign) {
var name = node.left.print_to_string(); var name = node.left.print_to_string();
var value = node.right; var value = node.right;

View File

@@ -118,10 +118,8 @@ var AST_Node = DEFNODE("Node", "start end", {
} }
}, null); }, null);
AST_Node.warn_function = null;
AST_Node.warn = function(txt, props) { AST_Node.warn = function(txt, props) {
if (AST_Node.warn_function) if (AST_Node.warn_function) AST_Node.warn_function(string_template(txt, props));
AST_Node.warn_function(string_template(txt, props));
}; };
/* -----[ statements ]----- */ /* -----[ statements ]----- */
@@ -207,8 +205,7 @@ var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {
var label = node.label; var label = node.label;
var def = this.label; var def = this.label;
node.walk(new TreeWalker(function(node) { node.walk(new TreeWalker(function(node) {
if (node instanceof AST_LoopControl if (node instanceof AST_LoopControl && node.label && node.label.thedef === def) {
&& node.label && node.label.thedef === def) {
node.label.thedef = label; node.label.thedef = label;
label.references.push(node); label.references.push(node);
} }
@@ -328,7 +325,7 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
var body = this.body; var body = this.body;
var wrapped_tl = "(function(exports){'$ORIG';})(typeof " + name + "=='undefined'?(" + name + "={}):" + name + ");"; var wrapped_tl = "(function(exports){'$ORIG';})(typeof " + name + "=='undefined'?(" + name + "={}):" + name + ");";
wrapped_tl = parse(wrapped_tl); wrapped_tl = parse(wrapped_tl);
wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node) { wrapped_tl = wrapped_tl.transform(new TreeTransformer(function(node) {
if (node instanceof AST_Directive && node.value == "$ORIG") { if (node instanceof AST_Directive && node.value == "$ORIG") {
return MAP.splice(body); return MAP.splice(body);
} }

File diff suppressed because it is too large Load Diff

View File

@@ -198,16 +198,24 @@ function OutputStream(options) {
/* -----[ beautification/minification ]----- */ /* -----[ beautification/minification ]----- */
var has_parens = false; var has_parens = false;
var line_end = 0;
var line_fixed = true;
var might_need_space = false; var might_need_space = false;
var might_need_semicolon = false; var might_need_semicolon = false;
var might_add_newline = 0;
var need_newline_indented = false; var need_newline_indented = false;
var need_space = false; var need_space = false;
var newline_insert = -1; var newline_insert = -1;
var last = ""; var last = "";
var mapping_token, mapping_name, mappings = options.source_map && []; var mapping_token, mapping_name, mappings = options.source_map && [];
var do_add_mapping = mappings ? function() { var adjust_mappings = mappings ? function(line, col) {
mappings.forEach(function(mapping) {
mapping.line += line;
mapping.col += col;
});
} : noop;
var flush_mappings = mappings ? function() {
mappings.forEach(function(mapping) { mappings.forEach(function(mapping) {
try { try {
options.source_map.add( options.source_map.add(
@@ -230,31 +238,30 @@ function OutputStream(options) {
mappings = []; mappings = [];
} : noop; } : noop;
var ensure_line_len = options.max_line_len ? function() { function insert_newlines(count) {
if (current_col > options.max_line_len) { var index = OUTPUT.lastIndexOf("\n");
if (might_add_newline) { if (line_end < index) line_end = index;
var left = OUTPUT.slice(0, might_add_newline); var left = OUTPUT.slice(0, line_end);
var right = OUTPUT.slice(might_add_newline); var right = OUTPUT.slice(line_end);
if (mappings) { adjust_mappings(count, right.length - current_col);
var delta = right.length - current_col; current_line += count;
mappings.forEach(function(mapping) { current_pos += count;
mapping.line++; current_col = right.length;
mapping.col += delta; OUTPUT = left;
}); while (count--) OUTPUT += "\n";
} OUTPUT += right;
OUTPUT = left + "\n" + right; }
current_line++;
current_pos++; var fix_line = options.max_line_len ? function() {
current_col = right.length; if (line_fixed) {
}
if (current_col > options.max_line_len) { if (current_col > options.max_line_len) {
AST_Node.warn("Output exceeds {max_line_len} characters", options); AST_Node.warn("Output exceeds {max_line_len} characters", options);
} }
return;
} }
if (might_add_newline) { if (current_col > options.max_line_len) insert_newlines(1);
might_add_newline = 0; line_fixed = true;
do_add_mapping(); flush_mappings();
}
} : noop; } : noop;
var requireSemicolonChars = makePredicate("( [ + * / - , ."); var requireSemicolonChars = makePredicate("( [ + * / - , .");
@@ -286,7 +293,7 @@ function OutputStream(options) {
current_col++; current_col++;
current_pos++; current_pos++;
} else { } else {
ensure_line_len(); fix_line();
OUTPUT += "\n"; OUTPUT += "\n";
current_pos++; current_pos++;
current_line++; current_line++;
@@ -304,18 +311,6 @@ function OutputStream(options) {
} }
} }
if (!options.beautify && options.preserve_line && stack[stack.length - 1]) {
var target_line = stack[stack.length - 1].start.line;
while (current_line < target_line) {
ensure_line_len();
OUTPUT += "\n";
current_pos++;
current_line++;
current_col = 0;
might_need_space = false;
}
}
if (might_need_space) { if (might_need_space) {
if ((is_identifier_char(prev) if ((is_identifier_char(prev)
&& (is_identifier_char(ch) || ch == "\\")) && (is_identifier_char(ch) || ch == "\\"))
@@ -337,7 +332,7 @@ function OutputStream(options) {
col: current_col col: current_col
}); });
mapping_token = false; mapping_token = false;
if (!might_add_newline) do_add_mapping(); if (line_fixed) flush_mappings();
} }
OUTPUT += str; OUTPUT += str;
@@ -347,7 +342,7 @@ function OutputStream(options) {
current_line += n; current_line += n;
current_col += a[0].length; current_col += a[0].length;
if (n > 0) { if (n > 0) {
ensure_line_len(); fix_line();
current_col = a[n].length; current_col = a[n].length;
} }
last = str; last = str;
@@ -374,9 +369,10 @@ function OutputStream(options) {
return ret; return ret;
} : function(col, cont) { return cont() }; } : function(col, cont) { return cont() };
var may_add_newline = options.max_line_len ? function() { var may_add_newline = options.max_line_len || options.preserve_line ? function() {
ensure_line_len(); fix_line();
might_add_newline = OUTPUT.length; line_end = OUTPUT.length;
line_fixed = false;
} : noop; } : noop;
var newline = options.beautify ? function() { var newline = options.beautify ? function() {
@@ -455,9 +451,7 @@ function OutputStream(options) {
} : noop; } : noop;
function get() { function get() {
if (might_add_newline) { if (!line_fixed) fix_line();
ensure_line_len();
}
return OUTPUT; return OUTPUT;
} }
@@ -622,7 +616,14 @@ function OutputStream(options) {
col : function() { return current_col }, col : function() { return current_col },
pos : function() { return current_pos }, pos : function() { return current_pos },
push_node : function(node) { stack.push(node) }, push_node : function(node) { stack.push(node) },
pop_node : function() { return stack.pop() }, pop_node : options.preserve_line ? function() {
var node = stack.pop();
if (node.start && node.start.line > current_line) {
insert_newlines(node.start.line - current_line);
}
} : function() {
stack.pop();
},
parent : function(n) { parent : function(n) {
return stack[stack.length - 2 - (n || 0)]; return stack[stack.length - 2 - (n || 0)];
} }
@@ -693,23 +694,15 @@ function OutputStream(options) {
// a function expression needs parens around it when it's provably // a function expression needs parens around it when it's provably
// the first token to appear in a statement. // the first token to appear in a statement.
PARENS(AST_Function, function(output) { PARENS(AST_Function, function(output) {
if (!output.has_parens() && first_in_statement(output)) { if (!output.has_parens() && first_in_statement(output)) return true;
return true;
}
if (output.option('webkit')) { if (output.option('webkit')) {
var p = output.parent(); var p = output.parent();
if (p instanceof AST_PropAccess && p.expression === this) { if (p instanceof AST_PropAccess && p.expression === this) return true;
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; if (p instanceof AST_Call && p.expression === this) return true;
} }
return false;
}); });
// same goes for an object literal, because otherwise it would be // same goes for an object literal, because otherwise it would be
@@ -783,17 +776,17 @@ function OutputStream(options) {
}); });
PARENS(AST_Call, function(output) { PARENS(AST_Call, function(output) {
var p = output.parent(), p1; var p = output.parent();
if (p instanceof AST_New && p.expression === this) if (p instanceof AST_New && p.expression === this) return true;
return true;
// workaround for Safari bug.
// https://bugs.webkit.org/show_bug.cgi?id=123506 // https://bugs.webkit.org/show_bug.cgi?id=123506
return this.expression instanceof AST_Function if (output.option('webkit')) {
&& p instanceof AST_PropAccess var g = output.parent(1);
&& p.expression === this return this.expression instanceof AST_Function
&& (p1 = output.parent(1)) instanceof AST_Assign && p instanceof AST_PropAccess
&& p1.left === p; && p.expression === this
&& g instanceof AST_Assign
&& g.left === p;
}
}); });
PARENS(AST_New, function(output) { PARENS(AST_New, function(output) {
@@ -1160,7 +1153,7 @@ function OutputStream(options) {
def.print(output); def.print(output);
}); });
var p = output.parent(); var p = output.parent();
if (p.init !== self || !(p instanceof AST_For || p instanceof AST_ForIn)) output.semicolon(); if (p && p.init !== self || !(p instanceof AST_For || p instanceof AST_ForIn)) output.semicolon();
}); });
function parenthesize_for_noin(node, output, noin) { function parenthesize_for_noin(node, output, noin) {

View File

@@ -758,17 +758,21 @@ function parse($TEXT, options) {
croak(msg, token.line, token.col); croak(msg, token.line, token.col);
} }
function token_to_string(type, value) {
return type + (value === undefined ? "" : " «" + value + "»");
}
function unexpected(token) { function unexpected(token) {
if (token == null) if (token == null)
token = S.token; token = S.token;
token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")"); token_error(token, "Unexpected token: " + token_to_string(token.type, token.value));
} }
function expect_token(type, val) { function expect_token(type, val) {
if (is(type, val)) { if (is(type, val)) {
return next(); return next();
} }
token_error(S.token, "Unexpected token " + S.token.type + " «" + S.token.value + "»" + ", expected " + type + " «" + val + "»"); token_error(S.token, "Unexpected token: " + token_to_string(S.token.type, S.token.value) + ", expected: " + token_to_string(type, val));
} }
function expect(punc) { function expect(punc) {
@@ -788,7 +792,7 @@ function parse($TEXT, options) {
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()) expect_token("punc", ";");
} }
function parenthesised() { function parenthesised() {
@@ -1069,7 +1073,7 @@ function parse($TEXT, options) {
var in_statement = ctor === AST_Defun; var in_statement = ctor === AST_Defun;
var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null; var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null;
if (in_statement && !name) if (in_statement && !name)
unexpected(); expect_token("name");
if (name && ctor !== AST_Accessor && !(name instanceof AST_SymbolDeclaration)) if (name && ctor !== AST_Accessor && !(name instanceof AST_SymbolDeclaration))
unexpected(prev()); unexpected(prev());
expect("("); expect("(");
@@ -1119,7 +1123,7 @@ function parse($TEXT, options) {
expect("{"); expect("{");
var a = []; var a = [];
while (!is("punc", "}")) { while (!is("punc", "}")) {
if (is("eof")) unexpected(); if (is("eof")) expect_token("punc", "}");
a.push(statement(strict_defun)); a.push(statement(strict_defun));
} }
next(); next();
@@ -1130,7 +1134,7 @@ function parse($TEXT, options) {
expect("{"); expect("{");
var a = [], cur = null, branch = null, tmp; var a = [], cur = null, branch = null, tmp;
while (!is("punc", "}")) { while (!is("punc", "}")) {
if (is("eof")) unexpected(); if (is("eof")) expect_token("punc", "}");
if (is("keyword", "case")) { if (is("keyword", "case")) {
if (branch) branch.end = prev(); if (branch) branch.end = prev();
cur = []; cur = [];
@@ -1141,8 +1145,7 @@ function parse($TEXT, options) {
}); });
a.push(branch); a.push(branch);
expect(":"); expect(":");
} } else if (is("keyword", "default")) {
else if (is("keyword", "default")) {
if (branch) branch.end = prev(); if (branch) branch.end = prev();
cur = []; cur = [];
branch = new AST_Default({ branch = new AST_Default({
@@ -1150,8 +1153,7 @@ function parse($TEXT, options) {
body : cur body : cur
}); });
a.push(branch); a.push(branch);
} } else {
else {
if (!cur) unexpected(); if (!cur) unexpected();
cur.push(statement()); cur.push(statement());
} }
@@ -1420,10 +1422,10 @@ function parse($TEXT, options) {
} }
function as_name() { function as_name() {
var tmp = S.token; if (!is("name")) expect_token("name");
if (tmp.type != "name") unexpected(); var name = S.token.value;
next(); next();
return tmp.value; return name;
} }
function _make_symbol(type) { function _make_symbol(type) {
@@ -1625,6 +1627,7 @@ function parse($TEXT, options) {
} }
if (options.expression) { if (options.expression) {
handle_regexp();
return expression(true); return expression(true);
} }

View File

@@ -53,25 +53,30 @@ function find_builtins(reserved) {
"-Infinity", "-Infinity",
"undefined", "undefined",
].forEach(add); ].forEach(add);
[ Object, Array, Function, Number, [
String, Boolean, Error, Math, Array,
Date, RegExp Boolean,
Date,
Error,
Function,
Math,
Number,
Object,
RegExp,
String,
].forEach(function(ctor) { ].forEach(function(ctor) {
Object.getOwnPropertyNames(ctor).map(add); Object.getOwnPropertyNames(ctor).map(add);
if (ctor.prototype) { if (ctor.prototype) {
Object.getOwnPropertyNames(ctor.prototype).map(add); Object.getOwnPropertyNames(ctor.prototype).map(add);
} }
}); });
function add(name) { function add(name) {
push_uniq(reserved, name); push_uniq(reserved, name);
} }
} }
function reserve_quoted_keys(ast, reserved) { function reserve_quoted_keys(ast, reserved) {
function add(name) {
push_uniq(reserved, name);
}
ast.walk(new TreeWalker(function(node) { ast.walk(new TreeWalker(function(node) {
if (node instanceof AST_ObjectKeyVal && node.quote) { if (node instanceof AST_ObjectKeyVal && node.quote) {
add(node.key); add(node.key);
@@ -79,6 +84,10 @@ function reserve_quoted_keys(ast, reserved) {
addStrings(node.property, add); addStrings(node.property, add);
} }
})); }));
function add(name) {
push_uniq(reserved, name);
}
} }
function addStrings(node, add) { function addStrings(node, add) {
@@ -127,10 +136,8 @@ function mangle_properties(ast, options) {
// note debug may be enabled as an empty string, which is falsey. Also treat passing 'true' // note debug may be enabled as an empty string, which is falsey. Also treat passing 'true'
// the same as passing an empty string. // the same as passing an empty string.
var debug = options.debug !== false; var debug = options.debug !== false;
var debug_name_suffix; var debug_suffix;
if (debug) { if (debug) debug_suffix = options.debug === true ? "" : options.debug;
debug_name_suffix = (options.debug === true ? "" : options.debug);
}
var names_to_mangle = []; var names_to_mangle = [];
var unmangleable = []; var unmangleable = [];
@@ -139,18 +146,14 @@ function mangle_properties(ast, options) {
ast.walk(new TreeWalker(function(node) { ast.walk(new TreeWalker(function(node) {
if (node instanceof AST_ObjectKeyVal) { if (node instanceof AST_ObjectKeyVal) {
add(node.key); add(node.key);
} } else if (node instanceof AST_ObjectProperty) {
else if (node instanceof AST_ObjectProperty) {
// setter or getter, since KeyVal is handled above // setter or getter, since KeyVal is handled above
add(node.key.name); add(node.key.name);
} } else if (node instanceof AST_Dot) {
else if (node instanceof AST_Dot) {
add(node.property); add(node.property);
} } else if (node instanceof AST_Sub) {
else if (node instanceof AST_Sub) {
addStrings(node.property, add); addStrings(node.property, add);
} } else if (node instanceof AST_Call
else if (node instanceof AST_Call
&& node.expression.print_to_string() == "Object.defineProperty") { && node.expression.print_to_string() == "Object.defineProperty") {
addStrings(node.args[1], add); addStrings(node.args[1], add);
} }
@@ -160,18 +163,14 @@ function mangle_properties(ast, options) {
return ast.transform(new TreeTransformer(function(node) { return ast.transform(new TreeTransformer(function(node) {
if (node instanceof AST_ObjectKeyVal) { if (node instanceof AST_ObjectKeyVal) {
node.key = mangle(node.key); node.key = mangle(node.key);
} } else if (node instanceof AST_ObjectProperty) {
else if (node instanceof AST_ObjectProperty) {
// setter or getter // setter or getter
node.key.name = mangle(node.key.name); node.key.name = mangle(node.key.name);
} } else if (node instanceof AST_Dot) {
else if (node instanceof AST_Dot) {
node.property = mangle(node.property); node.property = mangle(node.property);
} } else if (!options.keep_quoted && node instanceof AST_Sub) {
else if (!options.keep_quoted && node instanceof AST_Sub) {
node.property = mangleStrings(node.property); node.property = mangleStrings(node.property);
} } else if (node instanceof AST_Call
else if (node instanceof AST_Call
&& node.expression.print_to_string() == "Object.defineProperty") { && node.expression.print_to_string() == "Object.defineProperty") {
node.args[1] = mangleStrings(node.args[1]); node.args[1] = mangleStrings(node.args[1]);
} }
@@ -182,9 +181,7 @@ function mangle_properties(ast, options) {
function can_mangle(name) { function can_mangle(name) {
if (unmangleable.indexOf(name) >= 0) return false; if (unmangleable.indexOf(name) >= 0) return false;
if (reserved.indexOf(name) >= 0) return false; if (reserved.indexOf(name) >= 0) return false;
if (options.only_cache) { if (options.only_cache) return cache.has(name);
return cache.has(name);
}
if (/^-?[0-9]+(\.[0-9]+)?(e[+-][0-9]+)?$/.test(name)) return false; if (/^-?[0-9]+(\.[0-9]+)?(e[+-][0-9]+)?$/.test(name)) return false;
return true; return true;
} }
@@ -192,42 +189,29 @@ function mangle_properties(ast, options) {
function should_mangle(name) { function should_mangle(name) {
if (regex && !regex.test(name)) return false; if (regex && !regex.test(name)) return false;
if (reserved.indexOf(name) >= 0) return false; if (reserved.indexOf(name) >= 0) return false;
return cache.has(name) return cache.has(name) || names_to_mangle.indexOf(name) >= 0;
|| names_to_mangle.indexOf(name) >= 0;
} }
function add(name) { function add(name) {
if (can_mangle(name)) if (can_mangle(name)) push_uniq(names_to_mangle, name);
push_uniq(names_to_mangle, name); if (!should_mangle(name)) push_uniq(unmangleable, name);
if (!should_mangle(name)) {
push_uniq(unmangleable, name);
}
} }
function mangle(name) { function mangle(name) {
if (!should_mangle(name)) { if (!should_mangle(name)) {
return name; return name;
} }
var mangled = cache.get(name); var mangled = cache.get(name);
if (!mangled) { if (!mangled) {
if (debug) { if (debug) {
// debug mode: use a prefix and suffix to preserve readability, e.g. o.foo -> o._$foo$NNN_. // debug mode: use a prefix and suffix to preserve readability, e.g. o.foo -> o._$foo$NNN_.
var debug_mangled = "_$" + name + "$" + debug_name_suffix + "_"; var debug_mangled = "_$" + name + "$" + debug_suffix + "_";
if (can_mangle(debug_mangled)) mangled = debug_mangled;
if (can_mangle(debug_mangled)) {
mangled = debug_mangled;
}
} }
// either debug mode is off, or it is on and we could not use the mangled name // either debug mode is off, or it is on and we could not use the mangled name
if (!mangled) { if (!mangled) do {
do { mangled = base54(++cname);
mangled = base54(++cname); } while (!can_mangle(mangled));
} while (!can_mangle(mangled));
}
cache.set(name, mangled); cache.set(name, mangled);
} }
return mangled; return mangled;
@@ -238,11 +222,9 @@ function mangle_properties(ast, options) {
if (node instanceof AST_Sequence) { if (node instanceof AST_Sequence) {
var last = node.expressions.length - 1; var last = node.expressions.length - 1;
node.expressions[last] = mangleStrings(node.expressions[last]); node.expressions[last] = mangleStrings(node.expressions[last]);
} } else if (node instanceof AST_String) {
else if (node instanceof AST_String) {
node.value = mangle(node.value); node.value = mangle(node.value);
} } else if (node instanceof AST_Conditional) {
else if (node instanceof AST_Conditional) {
node.consequent = mangleStrings(node.consequent); node.consequent = mangleStrings(node.consequent);
node.alternative = mangleStrings(node.alternative); node.alternative = mangleStrings(node.alternative);
} }

View File

@@ -118,11 +118,10 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
descend(); descend();
scope = save_scope; scope = save_scope;
defun = save_defun; defun = save_defun;
return true; // don't descend again in TreeWalker return true;
} }
if (node instanceof AST_With) { if (node instanceof AST_With) {
for (var s = scope; s; s = s.parent_scope) for (var s = scope; s; s = s.parent_scope) s.uses_with = true;
s.uses_with = true;
return; return;
} }
if (node instanceof AST_Symbol) { if (node instanceof AST_Symbol) {
@@ -132,18 +131,14 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
node.thedef = node; node.thedef = node;
node.references = []; node.references = [];
} }
if (node instanceof AST_SymbolDefun || options.ie8 && node instanceof AST_SymbolLambda) { if (node instanceof AST_SymbolDefun) {
// Careful here, the scope where this should be defined is // This should be defined in the parent scope, as we encounter the
// the parent scope. The reason is that we enter a new // AST_Defun node before getting to its AST_Symbol.
// scope when we encounter the AST_Defun node (which is (node.scope = defun.parent_scope.resolve()).def_function(node, defun);
// instanceof AST_Scope) but we get to the symbol a bit } else if (node instanceof AST_SymbolLambda) {
// later. var def = defun.def_function(node, node.name == "arguments" ? undefined : defun);
(node.scope = defun.parent_scope).def_function(node, defun); if (options.ie8) def.defun = defun.parent_scope.resolve();
} } else if (node instanceof AST_SymbolVar) {
else if (node instanceof AST_SymbolLambda) {
defun.def_function(node, node.name == "arguments" ? undefined : defun);
}
else if (node instanceof AST_SymbolVar) {
defun.def_variable(node, node.TYPE == "SymbolVar" ? null : undefined); defun.def_variable(node, node.TYPE == "SymbolVar" ? null : undefined);
if (defun !== scope) { if (defun !== scope) {
node.mark_enclosed(options); node.mark_enclosed(options);
@@ -153,8 +148,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
} }
node.reference(options); node.reference(options);
} }
} } else if (node instanceof AST_SymbolCatch) {
else if (node instanceof AST_SymbolCatch) {
scope.def_variable(node).defun = defun; scope.def_variable(node).defun = defun;
} }
}); });
@@ -162,9 +156,9 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
// pass 2: find back references and eval // pass 2: find back references and eval
self.globals = new Dictionary(); self.globals = new Dictionary();
var tw = new TreeWalker(function(node, descend) { var tw = new TreeWalker(function(node) {
if (node instanceof AST_LoopControl && node.label) { if (node instanceof AST_LoopControl) {
node.label.thedef.references.push(node); if (node.label) node.label.thedef.references.push(node);
return true; return true;
} }
if (node instanceof AST_SymbolRef) { if (node instanceof AST_SymbolRef) {
@@ -185,35 +179,43 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
return true; return true;
} }
// ensure mangling works if catch reuses a scope variable // ensure mangling works if catch reuses a scope variable
var def; if (node instanceof AST_SymbolCatch) {
if (node instanceof AST_SymbolCatch && (def = node.definition().redefined())) { var def = node.definition().redefined();
var s = node.scope; if (def) for (var s = node.scope; s; s = s.parent_scope) {
while (s) {
push_uniq(s.enclosed, def); push_uniq(s.enclosed, def);
if (s === def.scope) break; if (s === def.scope) break;
s = s.parent_scope;
} }
return true;
} }
}); });
self.walk(tw); self.walk(tw);
// pass 3: fix up any scoping issue with IE8 // pass 3: fix up any scoping issue with IE8
if (options.ie8) { if (options.ie8) self.walk(new TreeWalker(function(node) {
self.walk(new TreeWalker(function(node, descend) { if (node instanceof AST_SymbolCatch) {
if (node instanceof AST_SymbolCatch) { redefine(node, node.thedef.defun);
var name = node.name; return true;
var refs = node.thedef.references; }
var scope = node.thedef.defun; if (node instanceof AST_SymbolLambda) {
var def = scope.find_variable(name) || self.globals.get(name) || scope.def_variable(node); var def = node.thedef;
refs.forEach(function(ref) { if (def.orig.length == 1) {
ref.thedef = def; redefine(node, node.scope.parent_scope);
ref.reference(options); node.thedef.init = def.init;
});
node.thedef = def;
node.reference(options);
return true;
} }
})); return true;
}
}));
function redefine(node, scope) {
var name = node.name;
var refs = node.thedef.references;
var def = scope.find_variable(name) || self.globals.get(name) || scope.def_variable(node);
refs.forEach(function(ref) {
ref.thedef = def;
ref.reference(options);
});
node.thedef = def;
node.reference(options);
} }
}); });
@@ -252,8 +254,7 @@ AST_Lambda.DEFMETHOD("init_scope_vars", function() {
AST_Symbol.DEFMETHOD("mark_enclosed", function(options) { AST_Symbol.DEFMETHOD("mark_enclosed", function(options) {
var def = this.definition(); var def = this.definition();
var s = this.scope; for (var s = this.scope; s; s = s.parent_scope) {
while (s) {
push_uniq(s.enclosed, def); push_uniq(s.enclosed, def);
if (options.keep_fnames) { if (options.keep_fnames) {
s.functions.each(function(d) { s.functions.each(function(d) {
@@ -261,7 +262,6 @@ AST_Symbol.DEFMETHOD("mark_enclosed", function(options) {
}); });
} }
if (s === def.scope) break; if (s === def.scope) break;
s = s.parent_scope;
} }
}); });
@@ -298,13 +298,23 @@ AST_Scope.DEFMETHOD("def_variable", function(symbol, init) {
return symbol.thedef = def; return symbol.thedef = def;
}); });
AST_Lambda.DEFMETHOD("resolve", return_this);
AST_Scope.DEFMETHOD("resolve", function() {
return this.parent_scope;
});
AST_Toplevel.DEFMETHOD("resolve", return_this);
function names_in_use(scope, options) { function names_in_use(scope, options) {
var names = scope.names_in_use; var names = scope.names_in_use;
if (!names) { if (!names) {
scope.names_in_use = names = Object.create(scope.mangled_names || null); scope.names_in_use = names = Object.create(scope.mangled_names || null);
scope.cname_holes = []; scope.cname_holes = [];
var cache = options.cache && options.cache.props;
scope.enclosed.forEach(function(def) { scope.enclosed.forEach(function(def) {
if (def.unmangleable(options)) names[def.name] = true; if (def.unmangleable(options)) names[def.name] = true;
if (def.global && cache && cache.has(def.name)) {
names[cache.get(def.name)] = true;
}
}); });
} }
return names; return names;
@@ -314,14 +324,6 @@ function next_mangled_name(scope, options, def) {
var in_use = names_in_use(scope, options); var in_use = names_in_use(scope, options);
var holes = scope.cname_holes; var holes = scope.cname_holes;
var names = Object.create(null); var names = Object.create(null);
// #179, #326
// in Safari strict mode, something like (function x(x){...}) is a syntax error;
// a function expression's argument cannot shadow the function expression's name
if (scope instanceof AST_Function && scope.name && def.orig[0] instanceof AST_SymbolFunarg) {
var tricky_def = scope.name.definition();
// the function's mangled_name is null when keep_fnames is true
names[tricky_def.mangled_name || tricky_def.name] = true;
}
var scopes = [ scope ]; var scopes = [ scope ];
def.references.forEach(function(sym) { def.references.forEach(function(sym) {
var scope = sym.scope; var scope = sym.scope;
@@ -410,7 +412,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
var save_nesting = lname; var save_nesting = lname;
descend(); descend();
lname = save_nesting; lname = save_nesting;
return true; // don't descend again in TreeWalker return true;
} }
if (node instanceof AST_Scope) { if (node instanceof AST_Scope) {
descend(); descend();
@@ -422,7 +424,9 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
} }
if (node instanceof AST_Label) { if (node instanceof AST_Label) {
var name; var name;
do name = base54(++lname); while (!is_identifier(name)); do {
name = base54(++lname);
} while (!is_identifier(name));
node.mangled_name = name; node.mangled_name = name;
return true; return true;
} }

View File

@@ -162,8 +162,7 @@ var MAP = (function() {
})(); })();
function push_uniq(array, el) { function push_uniq(array, el) {
if (array.indexOf(el) < 0) if (array.indexOf(el) < 0) return array.push(el);
array.push(el);
} }
function string_template(text, props) { function string_template(text, props) {
@@ -173,9 +172,8 @@ function string_template(text, props) {
} }
function remove(array, el) { function remove(array, el) {
for (var i = array.length; --i >= 0;) { var index = array.indexOf(el);
if (array[i] === el) array.splice(i, 1); if (index >= 0) array.splice(index, 1);
}
} }
function makePredicate(words) { function makePredicate(words) {

View File

@@ -3,7 +3,7 @@
"description": "JavaScript parser, mangler/compressor and beautifier toolkit", "description": "JavaScript parser, mangler/compressor and beautifier toolkit",
"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.4.2", "version": "3.5.1",
"engines": { "engines": {
"node": ">=0.8.0" "node": ">=0.8.0"
}, },
@@ -23,12 +23,12 @@
"LICENSE" "LICENSE"
], ],
"dependencies": { "dependencies": {
"commander": "~2.15.0", "commander": "~2.19.0",
"source-map": "~0.6.1" "source-map": "~0.6.1"
}, },
"devDependencies": { "devDependencies": {
"acorn": "~5.5.3", "acorn": "~6.1.1",
"semver": "~5.5.0" "semver": "~5.6.0"
}, },
"scripts": { "scripts": {
"test": "node test/run-tests.js" "test": "node test/run-tests.js"

View File

@@ -237,3 +237,342 @@ duplicate_argname: {
} }
expect_stdout: "bar 42 foo 42 bar" expect_stdout: "bar 42 foo 42 bar"
} }
issue_3273: {
options = {
arguments: true,
}
input: {
function f(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect: {
function f(a) {
console.log(a, a);
a++;
console.log(a, a);
}
f(0);
}
expect_stdout: [
"0 0",
"1 1",
]
}
issue_3273_reduce_vars: {
options = {
arguments: true,
reduce_vars: true,
}
input: {
function f(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect: {
function f(a) {
console.log(a, a);
a++;
console.log(a, a);
}
f(0);
}
expect_stdout: [
"0 0",
"1 1",
]
}
issue_3273_local_strict: {
options = {
arguments: true,
}
input: {
function f(a) {
"use strict";
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect: {
function f(a) {
"use strict";
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect_stdout: [
"0 0",
"1 0",
]
}
issue_3273_local_strict_reduce_vars: {
options = {
arguments: true,
reduce_vars: true,
}
input: {
function f(a) {
"use strict";
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect: {
function f(a) {
"use strict";
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect_stdout: [
"0 0",
"1 0",
]
}
issue_3273_global_strict: {
options = {
arguments: true,
}
input: {
"use strict";
function f(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect: {
"use strict";
function f(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect_stdout: [
"0 0",
"1 0",
]
}
issue_3273_global_strict_reduce_vars: {
options = {
arguments: true,
reduce_vars: true,
}
input: {
"use strict";
function f(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect: {
"use strict";
function f(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect_stdout: [
"0 0",
"1 0",
]
}
issue_3282_1: {
options = {
arguments: true,
reduce_funcs: true,
reduce_vars: true,
keep_fargs: false,
unused: true,
}
input: {
(function(t) {
return function() {
t();
};
})(function() {
'use strict';
function e() {
return arguments[0];
}
e();
e();
})();
}
expect: {
(function() {
return function() {
(function() {
"use strict";
function e() {
return arguments[0];
}
e();
e();
})();
};
})()();
}
expect_stdout: true
}
issue_3282_1_passes: {
options = {
arguments: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
keep_fargs: false,
unused: true,
}
input: {
(function(t) {
return function() {
t();
};
})(function() {
'use strict';
function e() {
return arguments[0];
}
e();
e();
})();
}
expect: {
(function() {
return function() {
(function() {
"use strict";
function e(argument_0) {
return argument_0;
}
e();
e();
})();
};
})()();
}
expect_stdout: true
}
issue_3282_2: {
options = {
arguments: true,
reduce_vars: true,
keep_fargs: false,
unused: true,
}
input: {
(function(f) {
f();
})(function() {
return (function(t) {
return function() {
t();
};
})(function() {
'use strict';
function e() {
return arguments[0];
}
e();
e();
})();
});
}
expect: {
(function() {
(function() {
return function(t) {
return function() {
t();
};
}(function() {
"use strict";
function e() {
return arguments[0];
}
e();
e();
})();
})();
})();
}
expect_stdout: true
}
issue_3282_2_passes: {
options = {
arguments: true,
passes: 2,
reduce_vars: true,
keep_fargs: false,
unused: true,
}
input: {
(function(f) {
f();
})(function() {
return (function(t) {
return function() {
t();
};
})(function() {
'use strict';
function e() {
return arguments[0];
}
e();
e();
})();
});
}
expect: {
(function() {
(function() {
return function(t) {
return function() {
t();
};
}(function() {
"use strict";
function e(argument_0) {
return argument_0;
}
e();
e();
})();
})();
})();
}
expect_stdout: true
}

View File

@@ -15,9 +15,9 @@ holes_and_undefined: {
constant_join: { constant_join: {
options = { options = {
unsafe : true, evaluate: true,
evaluate : true unsafe: true,
}; }
input: { input: {
var a = [ "foo", "bar", "baz" ].join(""); var a = [ "foo", "bar", "baz" ].join("");
var a1 = [ "foo", "bar", "baz" ].join(); var a1 = [ "foo", "bar", "baz" ].join();
@@ -64,9 +64,9 @@ constant_join: {
constant_join_2: { constant_join_2: {
options = { options = {
unsafe : true, evaluate: true,
evaluate : true unsafe: true,
}; }
input: { input: {
var a = [ "foo", "bar", boo(), "baz", "x", "y" ].join(""); var a = [ "foo", "bar", boo(), "baz", "x", "y" ].join("");
var b = [ "foo", "bar", boo(), "baz", "x", "y" ].join("-"); var b = [ "foo", "bar", boo(), "baz", "x", "y" ].join("-");
@@ -93,9 +93,9 @@ constant_join_2: {
constant_join_3: { constant_join_3: {
options = { options = {
unsafe: true,
evaluate: true, evaluate: true,
}; unsafe: true,
}
input: { input: {
var a = [ null ].join(); var a = [ null ].join();
var b = [ , ].join(); var b = [ , ].join();
@@ -133,7 +133,7 @@ for_loop: {
reduce_vars: true, reduce_vars: true,
unsafe: true, unsafe: true,
unused: true, unused: true,
}; }
input: { input: {
function f0() { function f0() {
var a = [1, 2, 3]; var a = [1, 2, 3];
@@ -239,3 +239,113 @@ index_length: {
} }
expect_stdout: "1 2" expect_stdout: "1 2"
} }
constructor_bad: {
options = {
unsafe: true
}
input: {
try {
Array(NaN);
console.log("FAIL1");
} catch (ex) {
try {
new Array(NaN);
console.log("FAIL2");
} catch (ex) {
console.log("PASS");
}
}
try {
Array(3.14);
console.log("FAIL1");
} catch (ex) {
try {
new Array(3.14);
console.log("FAIL2");
} catch (ex) {
console.log("PASS");
}
}
}
expect: {
try {
Array(NaN);
console.log("FAIL1");
} catch (ex) {
try {
Array(NaN);
console.log("FAIL2");
} catch (ex) {
console.log("PASS");
}
}
try {
Array(3.14);
console.log("FAIL1");
} catch (ex) {
try {
Array(3.14);
console.log("FAIL2");
} catch (ex) {
console.log("PASS");
}
}
}
expect_stdout: [
"PASS",
"PASS",
]
expect_warnings: [
"WARN: Invalid array length: 3.14 [test/compress/arrays.js:13,12]",
"WARN: Invalid array length: 3.14 [test/compress/arrays.js:17,16]",
]
}
constructor_good: {
options = {
unsafe: true
}
input: {
console.log(Array());
console.log(Array(0));
console.log(Array(1));
console.log(Array(6));
console.log(Array(7));
console.log(Array(1, 2));
console.log(Array(false));
console.log(Array("foo"));
console.log(Array(Array));
console.log(new Array());
console.log(new Array(0));
console.log(new Array(1));
console.log(new Array(6));
console.log(new Array(7));
console.log(new Array(1, 2));
console.log(new Array(false));
console.log(new Array("foo"));
console.log(new Array(Array));
}
expect: {
console.log([]);
console.log([]);
console.log([,]);
console.log([,,,,,,]);
console.log(Array(7));
console.log([ 1, 2 ]);
console.log([ false ]);
console.log([ "foo" ]);
console.log(Array(Array));
console.log([]);
console.log([]);
console.log([,]);
console.log([,,,,,,]);
console.log(Array(7));
console.log([ 1, 2 ]);
console.log([ false ]);
console.log([ "foo" ]);
console.log(Array(Array));
}
expect_stdout: true
expect_warnings: []
}

View File

@@ -1,24 +1,25 @@
asm_mixed: { asm_mixed: {
options = { options = {
sequences : true, assignments: true,
properties : true, booleans: true,
dead_code : true, comparisons: true,
drop_debugger : true, conditionals: true,
conditionals : true, dead_code: true,
comparisons : true, drop_debugger: true,
evaluate : true, evaluate: true,
booleans : true, hoist_funs: true,
loops : true, hoist_vars: true,
unused : true, if_return: true,
hoist_funs : true, join_vars: true,
keep_fargs : true, keep_fargs: true,
keep_fnames : false, keep_fnames: false,
hoist_vars : true, loops: true,
if_return : true, negate_iife: true,
join_vars : true, properties: true,
side_effects : true, sequences: true,
negate_iife : true side_effects: true,
}; unused: true,
}
input: { input: {
// adapted from http://asmjs.org/spec/latest/ // adapted from http://asmjs.org/spec/latest/
function asm_GeometricMean(stdlib, foreign, buffer) { function asm_GeometricMean(stdlib, foreign, buffer) {

View File

@@ -1,5 +1,6 @@
op_equals_left_local_var: { op_equals_left_local_var: {
options = { options = {
assignments: true,
evaluate: true, evaluate: true,
} }
input: { input: {
@@ -60,6 +61,7 @@ op_equals_left_local_var: {
op_equals_right_local_var: { op_equals_right_local_var: {
options = { options = {
assignments: true,
evaluate: true, evaluate: true,
} }
input: { input: {
@@ -123,6 +125,7 @@ op_equals_right_local_var: {
} }
op_equals_left_global_var: { op_equals_left_global_var: {
options = { options = {
assignments: true,
evaluate: true, evaluate: true,
} }
input: { input: {
@@ -179,6 +182,7 @@ op_equals_left_global_var: {
op_equals_right_global_var: { op_equals_right_global_var: {
options = { options = {
assignments: true,
evaluate: true, evaluate: true,
} }
input: { input: {
@@ -236,3 +240,52 @@ op_equals_right_global_var: {
x = g() & x; x = g() & x;
} }
} }
increment_decrement_1: {
options = {
assignments: true,
reduce_vars: true,
}
input: {
console.log(function(a) {
a += 1;
a -= 1;
return a;
}(42));
}
expect: {
console.log(function(a){
++a;
--a;
return a;
}(42));
}
expect_stdout: "42"
}
increment_decrement_2: {
options = {
assignments: true,
passes: 2,
reduce_vars: true,
}
input: {
console.log(function(a) {
a = a + 1;
a = a - 1;
a += 1;
a -= 1;
return a;
}(42));
}
expect: {
console.log(function(a){
++a;
--a;
++a;
--a;
return a;
}(42));
}
expect_stdout: "42"
}

File diff suppressed because it is too large Load Diff

View File

@@ -295,3 +295,53 @@ issue_2857_6: {
} }
expect_stdout: "true" expect_stdout: "true"
} }
is_boolean_unsafe: {
options = {
comparisons: true,
unsafe: true,
}
input: {
console.log(/foo/.test("bar") === [].isPrototypeOf({}));
}
expect: {
console.log(/foo/.test("bar") == [].isPrototypeOf({}));
}
expect_stdout: "true"
}
is_number_unsafe: {
options = {
comparisons: true,
unsafe: true,
}
input: {
console.log(Math.acos(42) !== "foo".charCodeAt(4));
}
expect: {
console.log(Math.acos(42) != "foo".charCodeAt(4));
}
expect_stdout: "true"
}
is_boolean_var: {
options = {
comparisons: true,
reduce_vars: true,
}
input: {
console.log(function(a, b) {
for (var i = 0, c = !b; i < a.length; i++)
if (!a[i] === c)
return i;
}([ false, true ], 42));
}
expect: {
console.log(function(a, b) {
for (var i = 0, c = !b; i < a.length; i++)
if (!a[i] == c)
return i;
}([ false, true ], 42));
}
expect_stdout: "1"
}

View File

@@ -1,7 +1,7 @@
concat_1: { concat_1: {
options = { options = {
evaluate: true evaluate: true,
}; }
input: { input: {
var a = "foo" + "bar" + x() + "moo" + "foo" + y() + "x" + "y" + "z" + q(); var a = "foo" + "bar" + x() + "moo" + "foo" + y() + "x" + "y" + "z" + q();
var b = "foo" + 1 + x() + 2 + "boo"; var b = "foo" + 1 + x() + 2 + "boo";
@@ -26,7 +26,7 @@ concat_1: {
} }
concat_2: { concat_2: {
options = {}; options = {}
input: { input: {
console.log( console.log(
1 + (2 + 3), 1 + (2 + 3),
@@ -55,7 +55,7 @@ concat_2: {
} }
concat_3: { concat_3: {
options = {}; options = {}
input: { input: {
console.log( console.log(
1 + 2 + (3 + 4 + 5), 1 + 2 + (3 + 4 + 5),
@@ -84,7 +84,7 @@ concat_3: {
} }
concat_4: { concat_4: {
options = {}; options = {}
input: { input: {
console.log( console.log(
1 + "2" + (3 + 4 + 5), 1 + "2" + (3 + 4 + 5),
@@ -113,7 +113,7 @@ concat_4: {
} }
concat_5: { concat_5: {
options = {}; options = {}
input: { input: {
console.log( console.log(
"1" + 2 + (3 + 4 + 5), "1" + 2 + (3 + 4 + 5),
@@ -142,7 +142,7 @@ concat_5: {
} }
concat_6: { concat_6: {
options = {}; options = {}
input: { input: {
console.log( console.log(
"1" + "2" + (3 + 4 + 5), "1" + "2" + (3 + 4 + 5),

View File

@@ -1,7 +1,7 @@
ifs_1: { ifs_1: {
options = { options = {
conditionals: true conditionals: true,
}; }
input: { input: {
if (foo) bar(); if (foo) bar();
if (!foo); else bar(); if (!foo); else bar();
@@ -18,8 +18,8 @@ ifs_1: {
ifs_2: { ifs_2: {
options = { options = {
conditionals: true conditionals: true,
}; }
input: { input: {
if (foo) { if (foo) {
x(); x();
@@ -47,12 +47,12 @@ ifs_2: {
ifs_3_should_warn: { ifs_3_should_warn: {
options = { options = {
conditionals : true, booleans: true,
dead_code : true, conditionals: true,
evaluate : true, dead_code: true,
booleans : true, evaluate: true,
side_effects : true, side_effects: true,
}; }
input: { input: {
var x, y; var x, y;
if (x && !(x + "1") && y) { // 1 if (x && !(x + "1") && y) { // 1
@@ -78,8 +78,8 @@ ifs_3_should_warn: {
ifs_4: { ifs_4: {
options = { options = {
conditionals: true conditionals: true,
}; }
input: { input: {
if (foo && bar) { if (foo && bar) {
x(foo)[10].bar.baz = something(); x(foo)[10].bar.baz = something();
@@ -95,10 +95,10 @@ ifs_4: {
ifs_5: { ifs_5: {
options = { options = {
if_return: true,
conditionals: true,
comparisons: true, comparisons: true,
}; conditionals: true,
if_return: true,
}
input: { input: {
function f() { function f() {
if (foo) return; if (foo) return;
@@ -132,9 +132,9 @@ ifs_5: {
ifs_6: { ifs_6: {
options = { options = {
comparisons: true,
conditionals: true, conditionals: true,
comparisons: true }
};
input: { input: {
var x, y; var x, y;
if (!foo && !bar && !baz && !boo) { if (!foo && !bar && !baz && !boo) {
@@ -163,8 +163,8 @@ ifs_6: {
cond_1: { cond_1: {
options = { options = {
conditionals: true conditionals: true,
}; }
input: { input: {
function foo(do_something, some_condition) { function foo(do_something, some_condition) {
if (some_condition) { if (some_condition) {
@@ -189,8 +189,8 @@ cond_1: {
cond_2: { cond_2: {
options = { options = {
conditionals: true conditionals: true,
}; }
input: { input: {
function foo(x, FooBar, some_condition) { function foo(x, FooBar, some_condition) {
if (some_condition) { if (some_condition) {
@@ -209,8 +209,8 @@ cond_2: {
cond_3: { cond_3: {
options = { options = {
conditionals: true conditionals: true,
}; }
input: { input: {
var FooBar; var FooBar;
if (some_condition()) { if (some_condition()) {
@@ -227,8 +227,8 @@ cond_3: {
cond_4: { cond_4: {
options = { options = {
conditionals: true conditionals: true,
}; }
input: { input: {
var do_something; var do_something;
if (some_condition()) { if (some_condition()) {
@@ -251,8 +251,8 @@ cond_4: {
cond_5: { cond_5: {
options = { options = {
conditionals: true conditionals: true,
}; }
input: { input: {
if (some_condition()) { if (some_condition()) {
if (some_other_condition()) { if (some_other_condition()) {
@@ -279,9 +279,9 @@ cond_5: {
cond_7: { cond_7: {
options = { options = {
conditionals: true, conditionals: true,
evaluate : true, evaluate: true,
side_effects: true, side_effects: true,
}; }
input: { input: {
var x, y, z, a, b; var x, y, z, a, b;
// compress these // compress these
@@ -342,8 +342,8 @@ cond_7: {
cond_7_1: { cond_7_1: {
options = { options = {
conditionals: true, conditionals: true,
evaluate : true evaluate: true,
}; }
input: { input: {
var x; var x;
// access to global should be assumed to have side effects // access to global should be assumed to have side effects
@@ -361,10 +361,10 @@ cond_7_1: {
cond_8: { cond_8: {
options = { options = {
booleans: false,
conditionals: true, conditionals: true,
evaluate : true, evaluate: true,
booleans : false }
};
input: { input: {
var a; var a;
// compress these // compress these
@@ -445,10 +445,10 @@ cond_8: {
cond_8b: { cond_8b: {
options = { options = {
booleans: true,
conditionals: true, conditionals: true,
evaluate : true, evaluate: true,
booleans : true }
};
input: { input: {
var a; var a;
// compress these // compress these
@@ -528,10 +528,10 @@ cond_8b: {
cond_8c: { cond_8c: {
options = { options = {
booleans: false,
conditionals: true, conditionals: true,
evaluate : false, evaluate: false,
booleans : false }
};
input: { input: {
var a; var a;
// compress these // compress these
@@ -647,9 +647,21 @@ cond_9: {
ternary_boolean_consequent: { ternary_boolean_consequent: {
options = { options = {
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true, booleans: true,
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true, collapse_vars: true,
keep_fargs:true, if_return:true, join_vars:true, side_effects:true comparisons: true,
conditionals: true,
dead_code: true,
evaluate: true,
hoist_funs: true,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
properties: true,
sequences: true,
side_effects: true,
unused: true,
} }
input: { input: {
function f1() { return a == b ? true : x; } function f1() { return a == b ? true : x; }
@@ -675,9 +687,21 @@ ternary_boolean_consequent: {
ternary_boolean_alternative: { ternary_boolean_alternative: {
options = { options = {
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true, booleans: true,
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true, collapse_vars: true,
keep_fargs:true, if_return:true, join_vars:true, side_effects:true comparisons: true,
conditionals: true,
dead_code: true,
evaluate: true,
hoist_funs: true,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
properties: true,
sequences: true,
side_effects: true,
unused: true,
} }
input: { input: {
function f1() { return a == b ? x : true; } function f1() { return a == b ? x : true; }
@@ -778,11 +802,11 @@ trivial_boolean_ternary_expressions : {
issue_1154: { issue_1154: {
options = { options = {
booleans: true,
conditionals: true, conditionals: true,
evaluate : true, evaluate: true,
booleans : true,
side_effects: true, side_effects: true,
}; }
input: { input: {
function f1(x) { return x ? -1 : -1; } function f1(x) { return x ? -1 : -1; }
function f2(x) { return x ? +2 : +2; } function f2(x) { return x ? +2 : +2; }
@@ -818,7 +842,7 @@ issue_1154: {
no_evaluate: { no_evaluate: {
options = { options = {
conditionals: true, conditionals: true,
evaluate : false, evaluate: false,
side_effects: true, side_effects: true,
} }
input: { input: {
@@ -1268,3 +1292,127 @@ to_and_or: {
} }
expect_stdout: true expect_stdout: true
} }
cond_seq_assign_1: {
options = {
conditionals: true,
sequences: true,
}
input: {
function f(a) {
var t;
if (a) {
t = "foo";
t = "bar";
} else {
console.log(t);
t = 42;
}
console.log(t);
}
f(f);
f();
}
expect: {
function f(a) {
var t;
t = a ? (t = "foo", "bar") : (console.log(t), 42),
console.log(t);
}
f(f),
f();
}
expect_stdout: [
"bar",
"undefined",
"42",
]
}
cond_seq_assign_2: {
options = {
conditionals: true,
sequences: true,
}
input: {
function f(a) {
var t;
if (a) {
t = "foo";
a = "bar";
} else {
console.log(t);
t = 42;
}
console.log(t);
}
f(f);
f();
}
expect: {
function f(a) {
var t;
a ? (t = "foo", a = "bar") : (console.log(t), t = 42),
console.log(t);
}
f(f),
f();
}
expect_stdout: [
"foo",
"undefined",
"42",
]
}
cond_seq_assign_3: {
options = {
assignments: true,
conditionals: true,
}
input: {
var c = 0;
if (this)
c = 1 + c, c = c + 1;
else
c = 1 + c, c = c + 1;
console.log(c);
}
expect: {
var c = 0;
this, c = 1 + c, c += 1;
console.log(c);
}
expect_stdout: "2"
}
issue_3271: {
options = {
conditionals: true,
}
input: {
function f(a) {
var i = 0, b = [];
if (a) {
b[i++] = 4,
b[i++] = 1;
} else {
b[i++] = 3,
b[i++] = 2,
b[i++] = 1;
}
return b;
}
console.log(f(0).pop(), f(1).pop());
}
expect: {
function f(a) {
var i = 0, b = [];
a ? b[i++] = 4 : (b[i++] = 3, b[i++] = 2),
b[i++] = 1;
return b;
}
console.log(f(0).pop(), f(1).pop());
}
expect_stdout: "1 1"
}

View File

@@ -1,7 +1,7 @@
dead_code_1: { dead_code_1: {
options = { options = {
dead_code: true dead_code: true,
}; }
input: { input: {
function f() { function f() {
a(); a();
@@ -25,8 +25,8 @@ dead_code_1: {
dead_code_2_should_warn: { dead_code_2_should_warn: {
options = { options = {
dead_code: true dead_code: true,
}; }
input: { input: {
function f() { function f() {
g(); g();
@@ -64,13 +64,13 @@ dead_code_2_should_warn: {
dead_code_constant_boolean_should_warn_more: { dead_code_constant_boolean_should_warn_more: {
options = { options = {
dead_code : true, booleans: true,
loops : true, conditionals: true,
booleans : true, dead_code: true,
conditionals : true, evaluate: true,
evaluate : true, loops: true,
side_effects : true, side_effects: true,
}; }
input: { input: {
while (!((foo && bar) || (x + "0"))) { while (!((foo && bar) || (x + "0"))) {
console.log("unreachable"); console.log("unreachable");

View File

@@ -1,7 +1,7 @@
keep_debugger: { keep_debugger: {
options = { options = {
drop_debugger: false drop_debugger: false,
}; }
input: { input: {
debugger; debugger;
} }
@@ -12,8 +12,8 @@ keep_debugger: {
drop_debugger: { drop_debugger: {
options = { options = {
drop_debugger: true drop_debugger: true,
}; }
input: { input: {
debugger; debugger;
if (foo) debugger; if (foo) debugger;

View File

@@ -1,5 +1,5 @@
drop_console_1: { drop_console_1: {
options = {}; options = {}
input: { input: {
console.log('foo'); console.log('foo');
console.log.apply(console, arguments); console.log.apply(console, arguments);
@@ -11,7 +11,9 @@ drop_console_1: {
} }
drop_console_2: { drop_console_2: {
options = { drop_console: true }; options = {
drop_console: true,
}
input: { input: {
console.log('foo'); console.log('foo');
console.log.apply(console, arguments); console.log.apply(console, arguments);

View File

@@ -1,5 +1,8 @@
unused_funarg_1: { unused_funarg_1: {
options = { unused: true, keep_fargs: false }; options = {
keep_fargs: false,
unused: true,
}
input: { input: {
function f(a, b, c, d, e) { function f(a, b, c, d, e) {
return a + b; return a + b;
@@ -13,7 +16,10 @@ unused_funarg_1: {
} }
unused_funarg_2: { unused_funarg_2: {
options = { unused: true, keep_fargs: false }; options = {
keep_fargs: false,
unused: true,
}
input: { input: {
function f(a, b, c, d, e) { function f(a, b, c, d, e) {
return a + c; return a + c;
@@ -27,7 +33,9 @@ unused_funarg_2: {
} }
unused_nested_function: { unused_nested_function: {
options = { unused: true }; options = {
unused: true,
}
input: { input: {
function f(x, y) { function f(x, y) {
function g() { function g() {
@@ -44,7 +52,9 @@ unused_nested_function: {
} }
unused_circular_references_1: { unused_circular_references_1: {
options = { unused: true }; options = {
unused: true,
}
input: { input: {
function f(x, y) { function f(x, y) {
// circular reference // circular reference
@@ -65,7 +75,9 @@ unused_circular_references_1: {
} }
unused_circular_references_2: { unused_circular_references_2: {
options = { unused: true }; options = {
unused: true,
}
input: { input: {
function f(x, y) { function f(x, y) {
var foo = 1, bar = baz, baz = foo + bar, qwe = moo(); var foo = 1, bar = baz, baz = foo + bar, qwe = moo();
@@ -81,7 +93,9 @@ unused_circular_references_2: {
} }
unused_circular_references_3: { unused_circular_references_3: {
options = { unused: true }; options = {
unused: true,
}
input: { input: {
function f(x, y) { function f(x, y) {
var g = function() { return h() }; var g = function() { return h() };
@@ -97,7 +111,9 @@ unused_circular_references_3: {
} }
unused_keep_setter_arg: { unused_keep_setter_arg: {
options = { unused: true }; options = {
unused: true,
}
input: { input: {
var x = { var x = {
_foo: null, _foo: null,
@@ -121,7 +137,9 @@ unused_keep_setter_arg: {
} }
unused_var_in_catch: { unused_var_in_catch: {
options = { unused: true }; options = {
unused: true,
}
input: { input: {
function foo() { function foo() {
try { try {
@@ -141,7 +159,9 @@ unused_var_in_catch: {
} }
used_var_in_catch: { used_var_in_catch: {
options = { unused: true }; options = {
unused: true,
}
input: { input: {
function foo() { function foo() {
try { try {
@@ -165,7 +185,11 @@ used_var_in_catch: {
} }
keep_fnames: { keep_fnames: {
options = { unused: true, keep_fnames: true, unsafe: true }; options = {
keep_fnames: true,
unsafe: true,
unused: true,
}
input: { input: {
function foo() { function foo() {
return function bar(baz) {}; return function bar(baz) {};
@@ -367,7 +391,7 @@ drop_toplevel_vars_fargs: {
drop_toplevel_all: { drop_toplevel_all: {
options = { options = {
toplevel: true, toplevel: true,
unused: true unused: true,
} }
input: { input: {
var a, b = 1, c = g; var a, b = 1, c = g;
@@ -418,7 +442,11 @@ drop_toplevel_retain: {
drop_toplevel_retain_array: { drop_toplevel_retain_array: {
options = { options = {
top_retain: [ "f", "a", "o" ], top_retain: [
"f",
"a",
"o"
],
unused: true, unused: true,
} }
input: { input: {
@@ -476,8 +504,8 @@ drop_toplevel_retain_regex: {
drop_toplevel_all_retain: { drop_toplevel_all_retain: {
options = { options = {
toplevel: true,
top_retain: "f,a,o", top_retain: "f,a,o",
toplevel: true,
unused: true, unused: true,
} }
input: { input: {
@@ -506,8 +534,8 @@ drop_toplevel_all_retain: {
drop_toplevel_funcs_retain: { drop_toplevel_funcs_retain: {
options = { options = {
toplevel: "funcs",
top_retain: "f,a,o", top_retain: "f,a,o",
toplevel: "funcs",
unused: true, unused: true,
} }
input: { input: {
@@ -537,8 +565,8 @@ drop_toplevel_funcs_retain: {
drop_toplevel_vars_retain: { drop_toplevel_vars_retain: {
options = { options = {
toplevel: "vars",
top_retain: "f,a,o", top_retain: "f,a,o",
toplevel: "vars",
unused: true, unused: true,
} }
input: { input: {
@@ -1377,9 +1405,9 @@ issue_2516_1: {
issue_2516_2: { issue_2516_2: {
options = { options = {
collapse_vars: true, collapse_vars: true,
passes: 2,
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
passes: 2,
unused: true, unused: true,
} }
input: { input: {
@@ -1954,3 +1982,26 @@ issue_3192: {
"foo bar", "foo bar",
] ]
} }
issue_3233: {
options = {
pure_getters: "strict",
side_effects: true,
unused: true,
}
input: {
var a = function b() {
b.c = "PASS";
};
a();
console.log(a.c);
}
expect: {
var a = function b() {
b.c = "PASS";
};
a();
console.log(a.c);
}
expect_stdout: "PASS"
}

View File

@@ -186,7 +186,9 @@ unary_prefix: {
} }
negative_zero: { negative_zero: {
options = { evaluate: true } options = {
evaluate: true,
}
input: { input: {
console.log( console.log(
-"", -"",
@@ -207,7 +209,9 @@ negative_zero: {
} }
positive_zero: { positive_zero: {
options = { evaluate: true } options = {
evaluate: true,
}
input: { input: {
console.log( console.log(
+"", +"",
@@ -229,8 +233,8 @@ positive_zero: {
unsafe_constant: { unsafe_constant: {
options = { options = {
evaluate : true, evaluate: true,
unsafe : true unsafe: true,
} }
input: { input: {
console.log( console.log(
@@ -421,8 +425,8 @@ prop_function: {
unsafe_integer_key: { unsafe_integer_key: {
options = { options = {
evaluate : true, evaluate: true,
unsafe : true unsafe: true,
} }
input: { input: {
console.log( console.log(
@@ -449,8 +453,8 @@ unsafe_integer_key: {
unsafe_integer_key_complex: { unsafe_integer_key_complex: {
options = { options = {
evaluate : true, evaluate: true,
unsafe : true unsafe: true,
} }
input: { input: {
console.log( console.log(
@@ -477,8 +481,8 @@ unsafe_integer_key_complex: {
unsafe_float_key: { unsafe_float_key: {
options = { options = {
evaluate : true, evaluate: true,
unsafe : true unsafe: true,
} }
input: { input: {
console.log( console.log(
@@ -505,8 +509,8 @@ unsafe_float_key: {
unsafe_float_key_complex: { unsafe_float_key_complex: {
options = { options = {
evaluate : true, evaluate: true,
unsafe : true unsafe: true,
} }
input: { input: {
console.log( console.log(
@@ -533,8 +537,8 @@ unsafe_float_key_complex: {
unsafe_array: { unsafe_array: {
options = { options = {
evaluate : true, evaluate: true,
unsafe : true unsafe: true,
} }
input: { input: {
console.log( console.log(
@@ -569,8 +573,8 @@ unsafe_array: {
unsafe_string: { unsafe_string: {
options = { options = {
evaluate : true, evaluate: true,
unsafe : true unsafe: true,
} }
input: { input: {
console.log( console.log(
@@ -597,8 +601,8 @@ unsafe_string: {
unsafe_array_bad_index: { unsafe_array_bad_index: {
options = { options = {
evaluate : true, evaluate: true,
unsafe : true unsafe: true,
} }
input: { input: {
console.log( console.log(
@@ -619,8 +623,8 @@ unsafe_array_bad_index: {
unsafe_string_bad_index: { unsafe_string_bad_index: {
options = { options = {
evaluate : true, evaluate: true,
unsafe : true unsafe: true,
} }
input: { input: {
console.log( console.log(
@@ -754,8 +758,8 @@ in_boolean_context: {
unsafe_charAt: { unsafe_charAt: {
options = { options = {
evaluate : true, evaluate: true,
unsafe : true unsafe: true,
} }
input: { input: {
console.log( console.log(
@@ -782,8 +786,8 @@ unsafe_charAt: {
unsafe_charAt_bad_index: { unsafe_charAt_bad_index: {
options = { options = {
evaluate : true, evaluate: true,
unsafe : true unsafe: true,
} }
input: { input: {
console.log( console.log(
@@ -804,8 +808,8 @@ unsafe_charAt_bad_index: {
unsafe_charAt_noop: { unsafe_charAt_noop: {
options = { options = {
evaluate : true, evaluate: true,
unsafe : true unsafe: true,
} }
input: { input: {
console.log( console.log(
@@ -1195,7 +1199,7 @@ issue_2231_1: {
} }
expect_stdout: true expect_stdout: true
expect_warnings: [ expect_warnings: [
"WARN: Error evaluating Object.keys(void 0) [test/compress/evaluate.js:1191,20]", "WARN: Error evaluating Object.keys(void 0) [test/compress/evaluate.js:1,20]",
] ]
} }
@@ -1212,7 +1216,7 @@ issue_2231_2: {
} }
expect_stdout: true expect_stdout: true
expect_warnings: [ expect_warnings: [
"WARN: Error evaluating Object.getOwnPropertyNames(null) [test/compress/evaluate.js:1208,20]", "WARN: Error evaluating Object.getOwnPropertyNames(null) [test/compress/evaluate.js:1,20]",
] ]
} }
@@ -1241,12 +1245,12 @@ self_comparison_1: {
} }
input: { input: {
var o = { n: NaN }; var o = { n: NaN };
console.log(o.n == o.n, o.n === o.n, o.n != o.n, o.n !== o.n, typeof o.n); console.log(typeof o.n, o.n == o.n, o.n === o.n, o.n != o.n, o.n !== o.n);
} }
expect: { expect: {
console.log(false, false, true, true, "number"); console.log("number", false, false, true, true);
} }
expect_stdout: "false false true true 'number'" expect_stdout: "number false false true true"
} }
self_comparison_2: { self_comparison_2: {
@@ -1261,12 +1265,12 @@ self_comparison_2: {
} }
input: { input: {
var o = { n: NaN }; var o = { n: NaN };
console.log(o.n == o.n, o.n === o.n, o.n != o.n, o.n !== o.n, typeof o.n); console.log(typeof o.n, o.n == o.n, o.n === o.n, o.n != o.n, o.n !== o.n);
} }
expect: { expect: {
console.log(false, false, true, true, "number"); console.log("number", false, false, true, true);
} }
expect_stdout: "false false true true 'number'" expect_stdout: "number false false true true"
} }
issue_2535_1: { issue_2535_1: {
@@ -1350,14 +1354,14 @@ issue_2535_3: {
} }
expect_stdout: true expect_stdout: true
expect_warnings: [ expect_warnings: [
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1336,20]", "WARN: Dropping side-effect-free && [test/compress/evaluate.js:1,20]",
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1337,20]", "WARN: Dropping side-effect-free && [test/compress/evaluate.js:2,20]",
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1338,20]", "WARN: Dropping side-effect-free && [test/compress/evaluate.js:3,20]",
"WARN: Condition left of && always false [test/compress/evaluate.js:1338,20]", "WARN: Condition left of && always false [test/compress/evaluate.js:3,20]",
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1339,20]", "WARN: Dropping side-effect-free || [test/compress/evaluate.js:4,20]",
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1340,20]", "WARN: Dropping side-effect-free || [test/compress/evaluate.js:5,20]",
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1341,20]", "WARN: Dropping side-effect-free || [test/compress/evaluate.js:6,20]",
"WARN: Condition left of || always true [test/compress/evaluate.js:1341,20]", "WARN: Condition left of || always true [test/compress/evaluate.js:6,20]",
] ]
} }
@@ -1536,7 +1540,7 @@ issue_2926_2: {
expect_stdout: "function" expect_stdout: "function"
} }
issue_2968: { issue_2968_1: {
options = { options = {
collapse_vars: true, collapse_vars: true,
evaluate: true, evaluate: true,
@@ -1567,6 +1571,39 @@ issue_2968: {
expect_stdout: "PASS" expect_stdout: "PASS"
} }
issue_2968_2: {
options = {
assignments: true,
collapse_vars: true,
evaluate: true,
inline: true,
passes: 2,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
var c = "FAIL";
(function() {
(function(a, b) {
a <<= 0;
a && (a[(c = "PASS", 0 >>> (b += 1))] = 0);
})(42, -42);
})();
console.log(c);
}
expect: {
var c = "FAIL";
(function() {
a = 42,
((a <<= 0) && (a[(c = "PASS", 0)] = 0));
var a;
})();
console.log(c);
}
expect_stdout: "PASS"
}
truthy_conditionals: { truthy_conditionals: {
options = { options = {
conditionals: true, conditionals: true,
@@ -1606,3 +1643,47 @@ truthy_loops: {
} }
} }
} }
if_increment: {
options = {
evaluate: true,
reduce_vars: true,
unused: true,
}
input: {
console.log(function(a) {
if (console)
return ++a;
}(0));
}
expect: {
console.log(function(a) {
if (console)
return 1;
}());
}
expect_stdout: "1"
}
try_increment: {
options = {
evaluate: true,
reduce_vars: true,
unused: true,
}
input: {
console.log(function(a) {
try {
return ++a;
} catch (e) {}
}(0));
}
expect: {
console.log(function(a) {
try {
return 1;
} catch (e) {}
}());
}
expect_stdout: "1"
}

View File

@@ -9,20 +9,20 @@ non_ascii_function_identifier_name: {
iifes_returning_constants_keep_fargs_true: { iifes_returning_constants_keep_fargs_true: {
options = { options = {
keep_fargs : true, booleans: true,
side_effects : true, collapse_vars: true,
evaluate : true, comparisons: true,
unused : true, conditionals: true,
dead_code : true, dead_code: true,
conditionals : true, evaluate: true,
comparisons : true, if_return: true,
booleans : true, inline: true,
if_return : true, join_vars: true,
join_vars : true, keep_fargs: true,
reduce_funcs : true, reduce_funcs: true,
reduce_vars : true, reduce_vars: true,
collapse_vars : true, side_effects: true,
inline : true, unused: true,
} }
input: { input: {
(function(){ return -1.23; }()); (function(){ return -1.23; }());
@@ -46,20 +46,20 @@ iifes_returning_constants_keep_fargs_true: {
iifes_returning_constants_keep_fargs_false: { iifes_returning_constants_keep_fargs_false: {
options = { options = {
keep_fargs : false, booleans: true,
side_effects : true, collapse_vars: true,
evaluate : true, comparisons: true,
unused : true, conditionals: true,
dead_code : true, dead_code: true,
conditionals : true, evaluate: true,
comparisons : true, if_return: true,
booleans : true, inline: true,
if_return : true, join_vars: true,
join_vars : true, keep_fargs: false,
reduce_funcs : true, reduce_funcs: true,
reduce_vars : true, reduce_vars: true,
collapse_vars : true, side_effects: true,
inline : true, unused: true,
} }
input: { input: {
(function(){ return -1.23; }()); (function(){ return -1.23; }());
@@ -236,32 +236,6 @@ issue_203: {
expect_stdout: "42" 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: { issue_2084: {
options = { options = {
collapse_vars: true, collapse_vars: true,
@@ -384,6 +358,7 @@ inner_ref: {
issue_2107: { issue_2107: {
options = { options = {
assignments: true,
collapse_vars: true, collapse_vars: true,
inline: true, inline: true,
passes: 3, passes: 3,
@@ -413,6 +388,7 @@ issue_2107: {
issue_2114_1: { issue_2114_1: {
options = { options = {
assignments: true,
collapse_vars: true, collapse_vars: true,
if_return: true, if_return: true,
inline: true, inline: true,
@@ -445,6 +421,7 @@ issue_2114_1: {
issue_2114_2: { issue_2114_2: {
options = { options = {
assignments: true,
collapse_vars: true, collapse_vars: true,
if_return: true, if_return: true,
inline: true, inline: true,
@@ -1175,8 +1152,8 @@ issue_2620_3: {
issue_2620_4: { issue_2620_4: {
rename = true, rename = true,
options = { options = {
evaluate: true,
dead_code: true, dead_code: true,
evaluate: true,
inline: true, inline: true,
passes: 2, passes: 2,
reduce_vars: true, reduce_vars: true,
@@ -1249,6 +1226,7 @@ issue_2630_1: {
issue_2630_2: { issue_2630_2: {
options = { options = {
assignments: true,
collapse_vars: true, collapse_vars: true,
inline: true, inline: true,
passes: 2, passes: 2,
@@ -1346,6 +1324,7 @@ issue_2630_4: {
issue_2630_5: { issue_2630_5: {
options = { options = {
assignments: true,
collapse_vars: true, collapse_vars: true,
inline: true, inline: true,
reduce_vars: true, reduce_vars: true,
@@ -1424,6 +1403,8 @@ recursive_inline_2: {
issue_2657: { issue_2657: {
options = { options = {
inline: true, inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
sequences: true, sequences: true,
unused: true, unused: true,
@@ -2025,6 +2006,7 @@ deduplicate_parenthesis: {
drop_lone_use_strict: { drop_lone_use_strict: {
options = { options = {
directives: true,
side_effects: true, side_effects: true,
} }
input: { input: {
@@ -2052,6 +2034,27 @@ drop_lone_use_strict: {
} }
} }
issue_3166: {
options = {
directives: true,
}
input: {
"foo";
"use strict";
function f() {
"use strict";
"bar";
"use asm";
}
}
expect: {
"use strict";
function f() {
"use asm";
}
}
}
issue_3016_1: { issue_3016_1: {
options = { options = {
inline: true, inline: true,
@@ -2319,3 +2322,384 @@ issue_3125: {
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
issue_3274: {
options = {
collapse_vars: true,
inline: true,
join_vars: true,
loops: true,
reduce_vars: true,
unused: true,
}
input: {
(function() {
var g = function(a) {
var c = a.p, b = c;
return b != c;
};
while (g(1))
console.log("FAIL");
console.log("PASS");
})();
}
expect: {
(function() {
for (var c; void 0, (c = 1..p) != c;)
console.log("FAIL");
console.log("PASS");
})();
}
expect_stdout: "PASS"
}
issue_3297_1: {
options = {
collapse_vars: true,
inline: true,
reduce_vars: true,
unused: true,
}
mangle = {}
input: {
function function1() {
var r = {
function2: function2
};
function function2() {
alert(1234);
function function3() {
function2();
};
function3();
}
return r;
}
}
expect: {
function function1() {
return {
function2: function n() {
alert(1234);
function t() {
n();
}
t();
}
};
}
}
}
issue_3297_2: {
options = {
collapse_vars: true,
conditionals: true,
inline: true,
reduce_vars: true,
unused: true,
}
mangle = {}
input: {
function function1(session) {
var public = {
processBulk: processBulk
};
return public;
function processBulk(bulk) {
var subparam1 = session();
function processOne(param1) {
var param2 = {
subparam1: subparam1
};
doProcessOne({
param1: param1,
param2: param2,
}, function () {
processBulk(bulk);
});
};
if (bulk && bulk.length > 0)
processOne(bulk.shift());
}
function doProcessOne(config, callback) {
console.log(JSON.stringify(config));
callback();
}
}
function1(function session() {
return 42;
}).processBulk([1, 2, 3]);
}
expect: {
function function1(o) {
return {
processBulk: function t(u) {
var r = o();
function n(n) {
var o = {
subparam1: r
};
c({
param1: n,
param2: o
}, function() {
t(u);
});
}
u && u.length > 0 && n(u.shift());
}
};
function c(n, o) {
console.log(JSON.stringify(n));
o();
}
}
function1(function() {
return 42;
}).processBulk([ 1, 2, 3 ]);
}
expect_stdout: [
'{"param1":1,"param2":{"subparam1":42}}',
'{"param1":2,"param2":{"subparam1":42}}',
'{"param1":3,"param2":{"subparam1":42}}',
]
}
issue_3297_3: {
options = {
collapse_vars: true,
comparisons: true,
conditionals: true,
inline: true,
join_vars: true,
passes: 3,
reduce_funcs: true,
reduce_vars: true,
sequences: true,
side_effects: true,
unused: true,
}
mangle = {}
input: {
function function1(session) {
var public = {
processBulk: processBulk
};
return public;
function processBulk(bulk) {
var subparam1 = session();
function processOne(param1) {
var param2 = {
subparam1: subparam1
};
doProcessOne({
param1: param1,
param2: param2,
}, function () {
processBulk(bulk);
});
};
if (bulk && bulk.length > 0)
processOne(bulk.shift());
}
function doProcessOne(config, callback) {
console.log(JSON.stringify(config));
callback();
}
}
function1(function session() {
return 42;
}).processBulk([1, 2, 3]);
}
expect: {
function function1(u) {
return {
processBulk: function n(r) {
var o, t = u();
r && 0 < r.length && (o = {
param1: r.shift(),
param2: {
subparam1: t
}
},
console.log(JSON.stringify(o)),
n(r));
}
};
}
function1(function() {
return 42;
}).processBulk([ 1, 2, 3 ]);
}
expect_stdout: [
'{"param1":1,"param2":{"subparam1":42}}',
'{"param1":2,"param2":{"subparam1":42}}',
'{"param1":3,"param2":{"subparam1":42}}',
]
}
cross_references_1: {
options = {
inline: true,
reduce_vars: true,
unused: true,
}
input: {
var Math = {
square: function(n) {
return n * n;
}
};
console.log((function(factory) {
return factory();
})(function() {
return function(Math) {
return function(n) {
return Math.square(n);
};
}(Math);
})(3));
}
expect: {
var Math = {
square: function(n) {
return n * n;
}
};
console.log(function(Math) {
return function(n) {
return Math.square(n);
};
}(Math)(3));
}
expect_stdout: "9"
}
cross_references_2: {
options = {
collapse_vars: true,
evaluate: true,
hoist_props: true,
inline: true,
passes: 4,
pure_getters: true,
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var Math = {
square: function(n) {
return n * n;
}
};
console.log((function(factory) {
return factory();
})(function() {
return function(Math) {
return function(n) {
return Math.square(n);
};
}(Math);
})(3));
}
expect: {
console.log(9);
}
expect_stdout: "9"
}
cross_references_3: {
options = {
inline: true,
reduce_vars: true,
unused: true,
}
input: {
var Math = {
square: function(n) {
return n * n;
},
cube: function(n) {
return n * n * n;
}
};
console.log(function(factory) {
return factory();
}(function() {
return function(Math) {
return function(n) {
Math = {
square: function(x) {
return "(SQUARE" + x + ")";
},
cube: function(x) {
return "(CUBE" + x + ")";
}
};
return Math.square(n) + Math.cube(n);
};
}(Math);
})(2));
console.log(Math.square(3), Math.cube(3));
}
expect: {
var Math = {
square: function(n) {
return n * n;
},
cube: function(n) {
return n * n * n;
}
};
console.log(function(Math) {
return function(n) {
Math = {
square: function(x) {
return "(SQUARE" + x + ")";
},
cube: function(x) {
return "(CUBE" + x + ")";
}
};
return Math.square(n) + Math.cube(n);
};
}(Math)(2));
console.log(Math.square(3), Math.cube(3));
}
expect_stdout: [
"(SQUARE2)(CUBE2)",
"9 27",
]
}
loop_inline: {
options = {
inline: true,
reduce_vars: true,
unused: true,
}
input: {
console.log(function(o) {
function g(p) {
return o[p];
}
function h(q) {
while (g(q));
}
return h;
}([ 1, "foo", 0 ])(2));
}
expect: {
console.log(function(o) {
return function(q) {
while (p = q, o[p]);
var p;
};
}([ 1, "foo", 0 ])(2));
}
expect_stdout: "undefined"
}

View File

@@ -2,7 +2,7 @@ must_replace: {
options = { options = {
global_defs: { global_defs: {
D: "foo bar", D: "foo bar",
} },
} }
input: { input: {
console.log(D); console.log(D);
@@ -141,9 +141,8 @@ mixed: {
console.log(CONFIG); console.log(CONFIG);
} }
expect_warnings: [ expect_warnings: [
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:127,22]', "WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:4,22]",
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:128,22]', "WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:7,8]",
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:130,8]',
] ]
} }
@@ -197,3 +196,23 @@ issue_2167: {
doWork(); doWork();
} }
} }
issue_3217: {
options = {
collapse_vars: true,
global_defs: {
"@o": "{fn:function(){var a=42;console.log(a)}}",
},
inline: true,
properties: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
o.fn();
}
expect: {
console.log(42);
}
}

View File

@@ -1,8 +1,8 @@
issue_2377_1: { issue_2377_1: {
options = { options = {
evaluate: true, evaluate: true,
inline: true,
hoist_props: true, hoist_props: true,
inline: true,
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
toplevel: true, toplevel: true,
@@ -33,8 +33,8 @@ issue_2377_1: {
issue_2377_2: { issue_2377_2: {
options = { options = {
evaluate: true, evaluate: true,
inline: true,
hoist_props: true, hoist_props: true,
inline: true,
passes: 2, passes: 2,
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
@@ -64,8 +64,8 @@ issue_2377_2: {
issue_2377_3: { issue_2377_3: {
options = { options = {
evaluate: true, evaluate: true,
inline: true,
hoist_props: true, hoist_props: true,
inline: true,
passes: 4, passes: 4,
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
@@ -416,7 +416,10 @@ issue_2473_1: {
options = { options = {
hoist_props: false, hoist_props: false,
reduce_vars: true, reduce_vars: true,
top_retain: [ "x", "y" ], top_retain: [
"x",
"y"
],
toplevel: true, toplevel: true,
unused: true, unused: true,
} }
@@ -435,7 +438,10 @@ issue_2473_2: {
options = { options = {
hoist_props: true, hoist_props: true,
reduce_vars: true, reduce_vars: true,
top_retain: [ "x", "y" ], top_retain: [
"x",
"y"
],
toplevel: true, toplevel: true,
unused: true, unused: true,
} }
@@ -746,9 +752,9 @@ issue_3046: {
issue_3071_1: { issue_3071_1: {
options = { options = {
evaluate: true, evaluate: true,
hoist_props: true,
inline: true, inline: true,
join_vars: true, join_vars: true,
hoist_props: true,
passes: 3, passes: 3,
reduce_vars: true, reduce_vars: true,
sequences: true, sequences: true,
@@ -773,9 +779,9 @@ issue_3071_1: {
issue_3071_2: { issue_3071_2: {
options = { options = {
evaluate: true, evaluate: true,
hoist_props: true,
inline: true, inline: true,
join_vars: true, join_vars: true,
hoist_props: true,
passes: 3, passes: 3,
reduce_vars: true, reduce_vars: true,
sequences: true, sequences: true,
@@ -800,9 +806,9 @@ issue_3071_2: {
issue_3071_2_toplevel: { issue_3071_2_toplevel: {
options = { options = {
evaluate: true, evaluate: true,
hoist_props: true,
inline: true, inline: true,
join_vars: true, join_vars: true,
hoist_props: true,
passes: 3, passes: 3,
reduce_vars: true, reduce_vars: true,
sequences: true, sequences: true,

View File

@@ -187,9 +187,9 @@ dont_screw_try_catch_undefined: {
reduce_vars: { reduce_vars: {
options = { options = {
evaluate: true, evaluate: true,
ie8: true,
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
ie8: true,
unused: true, unused: true,
} }
mangle = { mangle = {
@@ -666,3 +666,198 @@ issue_3197_2_ie8: {
} }
expect_stdout: "true" expect_stdout: "true"
} }
issue_3206_1: {
options = {
evaluate: true,
ie8: false,
reduce_vars: true,
typeofs: true,
unused: true,
}
input: {
console.log(function() {
var foo = function bar() {};
var baz = function moo() {};
return "function" == typeof bar;
}());
}
expect: {
console.log(function() {
return "function" == typeof bar;
}());
}
expect_stdout: "false"
}
issue_3206_2: {
options = {
evaluate: true,
ie8: true,
reduce_vars: true,
typeofs: true,
unused: true,
}
input: {
console.log(function() {
var foo = function bar() {};
var baz = function moo() {};
return "function" == typeof bar;
}());
}
expect: {
console.log(function() {
(function bar() {});
return "function" == typeof bar;
}());
}
expect_stdout: "false"
}
issue_3215_1: {
mangle = {
ie8: false,
}
input: {
console.log(function foo() {
var bar = function bar(name) {
return "PASS";
};
try {
"moo";
} catch (e) {
bar = function bar(name) {
return "FAIL";
};
}
return bar;
}()());
}
expect: {
console.log(function n() {
var o = function n(o) {
return "PASS";
};
try {
"moo";
} catch (n) {
o = function n(o) {
return "FAIL";
};
}
return o;
}()());
}
expect_stdout: "PASS"
}
issue_3215_2: {
mangle = {
ie8: true,
}
input: {
console.log(function foo() {
var bar = function bar(name) {
return "PASS";
};
try {
"moo";
} catch (e) {
bar = function bar(name) {
return "FAIL";
};
}
return bar;
}()());
}
expect: {
console.log(function foo() {
var o = function o(n) {
return "PASS";
};
try {
"moo";
} catch (n) {
o = function o(n) {
return "FAIL";
};
}
return o;
}()());
}
expect_stdout: "PASS"
}
issue_3215_3: {
mangle = {
ie8: false,
}
input: {
console.log(function foo() {
var bar = function bar(name) {
return "FAIL";
};
try {
moo;
} catch (e) {
bar = function bar(name) {
return "PASS";
};
}
return bar;
}()());
}
expect: {
console.log(function n() {
var o = function n(o) {
return "FAIL";
};
try {
moo;
} catch (n) {
o = function n(o) {
return "PASS";
};
}
return o;
}()());
}
expect_stdout: "PASS"
}
issue_3215_4: {
mangle = {
ie8: true,
}
input: {
console.log(function foo() {
var bar = function bar(name) {
return "FAIL";
};
try {
moo;
} catch (e) {
bar = function bar(name) {
return "PASS";
};
}
return bar;
}()());
}
expect: {
console.log(function foo() {
var o = function o(n) {
return "FAIL";
};
try {
moo;
} catch (n) {
o = function o(n) {
return "PASS";
};
}
return o;
}()());
}
expect_stdout: "PASS"
}

View File

@@ -1,14 +1,14 @@
if_return_1: { if_return_1: {
options = { options = {
if_return : true, booleans: true,
sequences : true, comparisons: true,
conditionals : true, conditionals: true,
comparisons : true, dead_code: true,
evaluate : true, evaluate: true,
booleans : true, if_return: true,
unused : true, sequences: true,
side_effects : true, side_effects: true,
dead_code : true, unused: true,
} }
input: { input: {
function f(x) { function f(x) {
@@ -24,15 +24,15 @@ if_return_1: {
if_return_2: { if_return_2: {
options = { options = {
if_return : true, booleans: true,
sequences : true, comparisons: true,
conditionals : true, conditionals: true,
comparisons : true, dead_code: true,
evaluate : true, evaluate: true,
booleans : true, if_return: true,
unused : true, sequences: true,
side_effects : true, side_effects: true,
dead_code : true, unused: true,
} }
input: { input: {
function f(x, y) { function f(x, y) {
@@ -49,15 +49,15 @@ if_return_2: {
if_return_3: { if_return_3: {
options = { options = {
if_return : true, booleans: true,
sequences : true, comparisons: true,
conditionals : true, conditionals: true,
comparisons : true, dead_code: true,
evaluate : true, evaluate: true,
booleans : true, if_return: true,
unused : true, sequences: true,
side_effects : true, side_effects: true,
dead_code : true, unused: true,
} }
input: { input: {
function f(x) { function f(x) {
@@ -75,15 +75,15 @@ if_return_3: {
if_return_4: { if_return_4: {
options = { options = {
if_return : true, booleans: true,
sequences : true, comparisons: true,
conditionals : true, conditionals: true,
comparisons : true, dead_code: true,
evaluate : true, evaluate: true,
booleans : true, if_return: true,
unused : true, sequences: true,
side_effects : true, side_effects: true,
dead_code : true, unused: true,
} }
input: { input: {
function f(x, y) { function f(x, y) {
@@ -100,15 +100,15 @@ if_return_4: {
if_return_5: { if_return_5: {
options = { options = {
if_return : true, booleans: true,
sequences : true, comparisons: true,
conditionals : true, conditionals: true,
comparisons : true, dead_code: true,
evaluate : true, evaluate: true,
booleans : true, if_return: true,
unused : true, sequences: true,
side_effects : true, side_effects: true,
dead_code : true, unused: true,
} }
input: { input: {
function f() { function f() {
@@ -126,15 +126,15 @@ if_return_5: {
if_return_6: { if_return_6: {
options = { options = {
if_return : true, booleans: true,
sequences : true, comparisons: true,
conditionals : true, conditionals: true,
comparisons : true, dead_code: true,
evaluate : true, evaluate: true,
booleans : true, if_return: true,
unused : true, sequences: true,
side_effects : true, side_effects: true,
dead_code : true, unused: true,
} }
input: { input: {
function f(x) { function f(x) {
@@ -150,15 +150,15 @@ if_return_6: {
if_return_7: { if_return_7: {
options = { options = {
if_return : true, booleans: true,
sequences : true, comparisons: true,
conditionals : true, conditionals: true,
comparisons : true, dead_code: true,
evaluate : true, evaluate: true,
booleans : true, if_return: true,
unused : true, sequences: true,
side_effects : true, side_effects: true,
dead_code : true, unused: true,
} }
input: { input: {
function f(x) { function f(x) {
@@ -176,10 +176,10 @@ if_return_7: {
if_return_8: { if_return_8: {
options = { options = {
if_return: true, conditionals: true,
sequences: true, if_return: true,
conditionals: true, sequences: true,
side_effects : true, side_effects: true,
} }
input: { input: {
function f(e) { function f(e) {
@@ -220,15 +220,15 @@ if_return_8: {
issue_1089: { issue_1089: {
options = { options = {
if_return : true, booleans: true,
sequences : true, comparisons: true,
conditionals : true, conditionals: true,
comparisons : true, dead_code: true,
evaluate : true, evaluate: true,
booleans : true, if_return: true,
unused : true, sequences: true,
side_effects : true, side_effects: true,
dead_code : true, unused: true,
} }
input: { input: {
function x() { function x() {
@@ -251,9 +251,9 @@ issue_1089: {
issue_1437: { issue_1437: {
options = { options = {
if_return : true, conditionals: false,
sequences : true, if_return: true,
conditionals : false sequences: true,
} }
input: { input: {
function x() { function x() {
@@ -281,9 +281,9 @@ issue_1437: {
issue_1437_conditionals: { issue_1437_conditionals: {
options = { options = {
conditionals : true, conditionals: true,
if_return : true, if_return: true,
sequences : true sequences: true,
} }
input: { input: {
function x() { function x() {
@@ -396,3 +396,151 @@ if_if_return_return: {
} }
} }
} }
if_body_return_1: {
options = {
if_return: true,
}
input: {
var c = "PASS";
function f(a, b) {
if (a) {
if (b) throw new Error(c);
return 42;
}
return true;
}
console.log(f(0, 0));
console.log(f(0, 1));
console.log(f(1, 0));
try {
f(1, 1);
console.log("FAIL");
} catch (e) {
console.log(e.message);
}
}
expect: {
var c = "PASS";
function f(a, b) {
if (a) {
if (b) throw new Error(c);
return 42;
}
return true;
}
console.log(f(0, 0));
console.log(f(0, 1));
console.log(f(1, 0));
try {
f(1, 1);
console.log("FAIL");
} catch (e) {
console.log(e.message);
}
}
expect_stdout: [
"true",
"true",
"42",
"PASS",
]
}
if_body_return_2: {
options = {
if_return: true,
}
input: {
var c = "PASS";
function f(a, b) {
if (0 + a) {
if (b) throw new Error(c);
return 42;
}
return true;
}
console.log(f(0, 0));
console.log(f(0, 1));
console.log(f(1, 0));
try {
f(1, 1);
console.log("FAIL");
} catch (e) {
console.log(e.message);
}
}
expect: {
var c = "PASS";
function f(a, b) {
if (0 + a) {
if (b) throw new Error(c);
return 42;
}
return true;
}
console.log(f(0, 0));
console.log(f(0, 1));
console.log(f(1, 0));
try {
f(1, 1);
console.log("FAIL");
} catch (e) {
console.log(e.message);
}
}
expect_stdout: [
"true",
"true",
"42",
"PASS",
]
}
if_body_return_3: {
options = {
if_return: true,
}
input: {
var c = "PASS";
function f(a, b) {
if (1 == a) {
if (b) throw new Error(c);
return 42;
}
return true;
}
console.log(f(0, 0));
console.log(f(0, 1));
console.log(f(1, 0));
try {
f(1, 1);
console.log("FAIL");
} catch (e) {
console.log(e.message);
}
}
expect: {
var c = "PASS";
function f(a, b) {
if (1 != a) return true;
if (b) throw new Error(c);
return 42;
}
console.log(f(0, 0));
console.log(f(0, 1));
console.log(f(1, 0));
try {
f(1, 1);
console.log("FAIL");
} catch (e) {
console.log(e.message);
}
}
expect_stdout: [
"true",
"true",
"42",
"PASS",
]
}

View File

@@ -1,8 +1,17 @@
non_hoisted_function_after_return: { non_hoisted_function_after_return: {
options = { options = {
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true, booleans: true,
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true, comparisons: true,
if_return: true, join_vars: true, side_effects: true conditionals: true,
dead_code: true,
evaluate: true,
hoist_funs: false,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
side_effects: true,
unused: true,
} }
input: { input: {
function foo(x) { function foo(x) {
@@ -27,19 +36,30 @@ non_hoisted_function_after_return: {
} }
} }
expect_warnings: [ expect_warnings: [
'WARN: Dropping unreachable code [test/compress/issue-1034.js:11,16]', "WARN: Dropping unreachable code [test/compress/issue-1034.js:4,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:14,16]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:7,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:17,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:10,12]",
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:18,21]" "WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:11,21]"
] ]
} }
non_hoisted_function_after_return_2a: { non_hoisted_function_after_return_2a: {
options = { options = {
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true, booleans: true,
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true, collapse_vars: false,
if_return: true, join_vars: true, side_effects: true, comparisons: true,
collapse_vars: false, passes: 2, warnings: "verbose" conditionals: true,
dead_code: true,
evaluate: true,
hoist_funs: false,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
passes: 2,
side_effects: true,
unused: true,
warnings: "verbose",
} }
input: { input: {
function foo(x) { function foo(x) {
@@ -65,28 +85,37 @@ non_hoisted_function_after_return_2a: {
} }
} }
expect_warnings: [ expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:48,16]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:4,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:48,16]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:4,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:51,16]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:7,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:51,16]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:7,16]",
"WARN: Dropping unused variable a [test/compress/issue-1034.js:48,20]", "WARN: Dropping unused variable a [test/compress/issue-1034.js:4,20]",
"WARN: Dropping unused function nope [test/compress/issue-1034.js:55,21]", "WARN: Dropping unused function nope [test/compress/issue-1034.js:11,21]",
"WARN: pass 0: last_count: Infinity, count: 37", "WARN: pass 0: last_count: Infinity, count: 37",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:53,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:9,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:53,12]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:9,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:56,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:12,12]",
"WARN: Dropping unused variable b [test/compress/issue-1034.js:51,20]", "WARN: Dropping unused variable b [test/compress/issue-1034.js:7,20]",
"WARN: Dropping unused variable c [test/compress/issue-1034.js:53,16]", "WARN: Dropping unused variable c [test/compress/issue-1034.js:9,16]",
"WARN: pass 1: last_count: 37, count: 18", "WARN: pass 1: last_count: 37, count: 18",
] ]
} }
non_hoisted_function_after_return_2b: { non_hoisted_function_after_return_2b: {
options = { options = {
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true, booleans: true,
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true, collapse_vars: false,
if_return: true, join_vars: true, side_effects: true, comparisons: true,
collapse_vars: false conditionals: true,
dead_code: true,
evaluate: true,
hoist_funs: false,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
side_effects: true,
unused: true,
} }
input: { input: {
function foo(x) { function foo(x) {
@@ -110,20 +139,28 @@ non_hoisted_function_after_return_2b: {
} }
} }
expect_warnings: [ expect_warnings: [
// duplicate warnings no longer emitted "WARN: Dropping unreachable code [test/compress/issue-1034.js:6,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:97,16]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:6,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:97,16]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:8,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:99,12]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:8,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:99,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:12,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:103,12]",
] ]
} }
non_hoisted_function_after_return_strict: { non_hoisted_function_after_return_strict: {
options = { options = {
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true, booleans: true,
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true, comparisons: true,
if_return: true, join_vars: true, side_effects: true conditionals: true,
dead_code: true,
evaluate: true,
hoist_funs: false,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
side_effects: true,
unused: true,
} }
input: { input: {
"use strict"; "use strict";
@@ -153,19 +190,30 @@ non_hoisted_function_after_return_strict: {
} }
expect_stdout: "8 7" expect_stdout: "8 7"
expect_warnings: [ expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:133,16]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:5,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:136,16]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:8,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:139,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:11,12]",
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:140,21]", "WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:12,21]",
] ]
} }
non_hoisted_function_after_return_2a_strict: { non_hoisted_function_after_return_2a_strict: {
options = { options = {
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true, booleans: true,
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true, collapse_vars: false,
if_return: true, join_vars: true, side_effects: true, comparisons: true,
collapse_vars: false, passes: 2, warnings: "verbose" conditionals: true,
dead_code: true,
evaluate: true,
hoist_funs: false,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
passes: 2,
side_effects: true,
unused: true,
warnings: "verbose",
} }
input: { input: {
"use strict"; "use strict";
@@ -196,28 +244,37 @@ non_hoisted_function_after_return_2a_strict: {
} }
expect_stdout: "5 6" expect_stdout: "5 6"
expect_warnings: [ expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:175,16]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:5,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:175,16]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:5,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:178,16]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:8,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:178,16]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:8,16]",
"WARN: Dropping unused variable a [test/compress/issue-1034.js:175,20]", "WARN: Dropping unused variable a [test/compress/issue-1034.js:5,20]",
"WARN: Dropping unused function nope [test/compress/issue-1034.js:182,21]", "WARN: Dropping unused function nope [test/compress/issue-1034.js:12,21]",
"WARN: pass 0: last_count: Infinity, count: 48", "WARN: pass 0: last_count: Infinity, count: 48",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:180,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:10,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:180,12]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:10,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:183,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:13,12]",
"WARN: Dropping unused variable b [test/compress/issue-1034.js:178,20]", "WARN: Dropping unused variable b [test/compress/issue-1034.js:8,20]",
"WARN: Dropping unused variable c [test/compress/issue-1034.js:180,16]", "WARN: Dropping unused variable c [test/compress/issue-1034.js:10,16]",
"WARN: pass 1: last_count: 48, count: 29", "WARN: pass 1: last_count: 48, count: 29",
] ]
} }
non_hoisted_function_after_return_2b_strict: { non_hoisted_function_after_return_2b_strict: {
options = { options = {
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true, booleans: true,
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true, collapse_vars: false,
if_return: true, join_vars: true, side_effects: true, comparisons: true,
collapse_vars: false conditionals: true,
dead_code: true,
evaluate: true,
hoist_funs: false,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
side_effects: true,
unused: true,
} }
input: { input: {
"use strict"; "use strict";
@@ -246,11 +303,10 @@ non_hoisted_function_after_return_2b_strict: {
} }
expect_stdout: "5 6" expect_stdout: "5 6"
expect_warnings: [ expect_warnings: [
// duplicate warnings no longer emitted "WARN: Dropping unreachable code [test/compress/issue-1034.js:7,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:229,16]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:7,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:229,16]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:9,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:231,12]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:9,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:231,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:13,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:235,12]",
] ]
} }

View File

@@ -3,7 +3,7 @@ const_pragma: {
evaluate: true, evaluate: true,
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
}; }
input: { input: {
/** @const */ var goog = goog || {}; /** @const */ var goog = goog || {};
@@ -19,7 +19,7 @@ not_const: {
evaluate: true, evaluate: true,
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
}; }
input: { input: {
var goog = goog || {}; var goog = goog || {};

View File

@@ -1,6 +1,6 @@
with_in_global_scope: { with_in_global_scope: {
options = { options = {
unused: true unused: true,
} }
input: { input: {
var o = 42; var o = 42;
@@ -18,7 +18,7 @@ with_in_global_scope: {
} }
with_in_function_scope: { with_in_function_scope: {
options = { options = {
unused: true unused: true,
} }
input: { input: {
function foo() { function foo() {
@@ -40,7 +40,7 @@ with_in_function_scope: {
} }
compress_with_with_in_other_scope: { compress_with_with_in_other_scope: {
options = { options = {
unused: true unused: true,
} }
input: { input: {
function foo() { function foo() {
@@ -69,7 +69,7 @@ compress_with_with_in_other_scope: {
} }
with_using_existing_variable_outside_scope: { with_using_existing_variable_outside_scope: {
options = { options = {
unused: true unused: true,
} }
input: { input: {
function f() { function f() {
@@ -99,7 +99,7 @@ with_using_existing_variable_outside_scope: {
} }
check_drop_unused_in_peer_function: { check_drop_unused_in_peer_function: {
options = { options = {
unused: true unused: true,
} }
input: { input: {
function outer() { function outer() {
@@ -148,7 +148,7 @@ check_drop_unused_in_peer_function: {
Infinity_not_in_with_scope: { Infinity_not_in_with_scope: {
options = { options = {
unused: true unused: true,
} }
input: { input: {
var o = { Infinity: 'oInfinity' }; var o = { Infinity: 'oInfinity' };
@@ -164,7 +164,7 @@ Infinity_not_in_with_scope: {
Infinity_in_with_scope: { Infinity_in_with_scope: {
options = { options = {
unused: true unused: true,
} }
input: { input: {
var o = { Infinity: 'oInfinity' }; var o = { Infinity: 'oInfinity' };
@@ -180,19 +180,19 @@ Infinity_in_with_scope: {
assorted_Infinity_NaN_undefined_in_with_scope: { assorted_Infinity_NaN_undefined_in_with_scope: {
options = { options = {
unused: true, booleans: true,
evaluate: true, comparisons: true,
dead_code: true, conditionals: true,
conditionals: true, dead_code: true,
comparisons: true, evaluate: true,
booleans: true, hoist_funs: true,
hoist_funs: true, if_return: true,
keep_fargs: true, join_vars: true,
if_return: true, keep_fargs: true,
join_vars: true,
side_effects: true,
sequences: false,
keep_infinity: false, keep_infinity: false,
sequences: false,
side_effects: true,
unused: true,
} }
input: { input: {
var f = console.log; var f = console.log;
@@ -242,19 +242,19 @@ assorted_Infinity_NaN_undefined_in_with_scope: {
assorted_Infinity_NaN_undefined_in_with_scope_keep_infinity: { assorted_Infinity_NaN_undefined_in_with_scope_keep_infinity: {
options = { options = {
unused: true, booleans: true,
evaluate: true, comparisons: true,
dead_code: true, conditionals: true,
conditionals: true, dead_code: true,
comparisons: true, evaluate: true,
booleans: true, hoist_funs: true,
hoist_funs: true, if_return: true,
keep_fargs: true, join_vars: true,
if_return: true, keep_fargs: true,
join_vars: true,
side_effects: true,
sequences: false,
keep_infinity: true, keep_infinity: true,
sequences: false,
side_effects: true,
unused: true,
} }
input: { input: {
var f = console.log; var f = console.log;

View File

@@ -1,11 +1,15 @@
keep_name_of_getter: { keep_name_of_getter: {
options = { unused: true }; options = {
unused: true,
}
input: { a = { get foo () {} } } input: { a = { get foo () {} } }
expect: { a = { get foo () {} } } expect: { a = { get foo () {} } }
} }
keep_name_of_setter: { keep_name_of_setter: {
options = { unused: true }; options = {
unused: true,
}
input: { a = { set foo () {} } } input: { a = { set foo () {} } }
expect: { a = { set foo () {} } } expect: { a = { set foo () {} } }
} }

View File

@@ -1,7 +1,7 @@
mangle_keep_fnames_false: { mangle_keep_fnames_false: {
options = { options = {
keep_fnames : true, keep_fargs: true,
keep_fargs : true, keep_fnames: true,
} }
mangle = { mangle = {
keep_fnames : false, keep_fnames : false,
@@ -26,8 +26,8 @@ mangle_keep_fnames_false: {
mangle_keep_fnames_true: { mangle_keep_fnames_true: {
options = { options = {
keep_fnames : true, keep_fargs: true,
keep_fargs : true, keep_fnames: true,
} }
mangle = { mangle = {
keep_fnames : true, keep_fnames : true,

View File

@@ -1,14 +1,14 @@
pure_function_calls: { pure_function_calls: {
options = { options = {
evaluate : true, booleans: true,
conditionals : true, comparisons: true,
comparisons : true, conditionals: true,
side_effects : true, evaluate: true,
booleans : true, if_return: true,
unused : true, join_vars: true,
if_return : true, negate_iife: true,
join_vars : true, side_effects: true,
negate_iife : true, unused: true,
} }
input: { input: {
// pure top-level IIFE will be dropped // pure top-level IIFE will be dropped
@@ -48,28 +48,28 @@ pure_function_calls: {
a.b(), f.g(); a.b(), f.g();
} }
expect_warnings: [ expect_warnings: [
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:16,8]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:3,8]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:16,8]", "WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:3,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:29,37]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:16,37]",
"WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:29,16]", "WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:16,16]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:27,8]", "WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:14,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:37,8]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:24,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:38,31]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:25,31]",
] ]
} }
pure_function_calls_toplevel: { pure_function_calls_toplevel: {
options = { options = {
evaluate : true, booleans: true,
conditionals : true, comparisons: true,
comparisons : true, conditionals: true,
side_effects : true, evaluate: true,
booleans : true, if_return: true,
unused : true, join_vars: true,
if_return : true, negate_iife: true,
join_vars : true, side_effects: true,
negate_iife : true, toplevel: true,
toplevel : true, unused: true,
} }
input: { input: {
// pure top-level IIFE will be dropped // pure top-level IIFE will be dropped
@@ -110,17 +110,17 @@ pure_function_calls_toplevel: {
a.b(), f.g(); a.b(), f.g();
} }
expect_warnings: [ expect_warnings: [
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:77,8]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:3,8]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:77,8]", "WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:3,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:90,37]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:16,37]",
"WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:90,16]", "WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:16,16]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:88,8]", "WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:14,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:105,8]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:31,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:106,31]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:32,31]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:82,33]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:8,33]",
"WARN: Dropping unused variable iife1 [test/compress/issue-1261.js:82,12]", "WARN: Dropping unused variable iife1 [test/compress/issue-1261.js:8,12]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:98,45]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:24,45]",
"WARN: Dropping unused variable MyClass [test/compress/issue-1261.js:98,12]", "WARN: Dropping unused variable MyClass [test/compress/issue-1261.js:24,12]",
] ]
} }
@@ -155,29 +155,29 @@ should_warn: {
baz(); baz();
} }
expect_warnings: [ expect_warnings: [
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:135,61]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:1,61]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:135,23]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:1,23]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:135,23]", "WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:1,23]",
"WARN: Boolean || always true [test/compress/issue-1261.js:136,23]", "WARN: Boolean || always true [test/compress/issue-1261.js:2,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:136,23]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:2,23]",
"WARN: Condition always true [test/compress/issue-1261.js:136,23]", "WARN: Condition always true [test/compress/issue-1261.js:2,23]",
"WARN: Condition left of || always true [test/compress/issue-1261.js:137,8]", "WARN: Condition left of || always true [test/compress/issue-1261.js:3,8]",
"WARN: Condition always true [test/compress/issue-1261.js:137,8]", "WARN: Condition always true [test/compress/issue-1261.js:3,8]",
"WARN: Boolean && always false [test/compress/issue-1261.js:138,23]", "WARN: Boolean && always false [test/compress/issue-1261.js:4,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:138,23]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:4,23]",
"WARN: Condition always false [test/compress/issue-1261.js:138,23]", "WARN: Condition always false [test/compress/issue-1261.js:4,23]",
"WARN: Condition left of && always false [test/compress/issue-1261.js:139,8]", "WARN: Condition left of && always false [test/compress/issue-1261.js:5,8]",
"WARN: Condition always false [test/compress/issue-1261.js:139,8]", "WARN: Condition always false [test/compress/issue-1261.js:5,8]",
"WARN: + in boolean context always true [test/compress/issue-1261.js:140,23]", "WARN: + in boolean context always true [test/compress/issue-1261.js:6,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:140,23]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:6,23]",
"WARN: Condition always true [test/compress/issue-1261.js:140,23]", "WARN: Condition always true [test/compress/issue-1261.js:6,23]",
"WARN: + in boolean context always true [test/compress/issue-1261.js:141,8]", "WARN: + in boolean context always true [test/compress/issue-1261.js:7,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:141,31]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:7,31]",
"WARN: Condition always true [test/compress/issue-1261.js:141,8]", "WARN: Condition always true [test/compress/issue-1261.js:7,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:142,23]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:8,23]",
"WARN: Condition always true [test/compress/issue-1261.js:143,8]", "WARN: Condition always true [test/compress/issue-1261.js:9,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:143,24]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:9,24]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:144,31]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:10,31]",
"WARN: Condition always false [test/compress/issue-1261.js:144,8]", "WARN: Condition always false [test/compress/issue-1261.js:10,8]",
] ]
} }

View File

@@ -1,16 +1,16 @@
string_plus_optimization: { string_plus_optimization: {
options = { options = {
side_effects : true, booleans: true,
evaluate : true, comparisons: true,
conditionals : true, conditionals: true,
comparisons : true, dead_code: true,
dead_code : true, evaluate: true,
booleans : true, hoist_funs: true,
unused : true, if_return: true,
if_return : true, join_vars: true,
join_vars : true, side_effects: true,
hoist_funs : true, unused: true,
}; }
input: { input: {
function foo(anything) { function foo(anything) {
function throwing_function() { function throwing_function() {

View File

@@ -15,7 +15,7 @@
tranformation_sort_order_equal: { tranformation_sort_order_equal: {
options = { options = {
comparisons: true, comparisons: true,
}; }
input: { (a = parseInt('100')) == a } input: { (a = parseInt('100')) == a }
expect: { (a = parseInt('100')) == a } expect: { (a = parseInt('100')) == a }
@@ -24,7 +24,7 @@ tranformation_sort_order_equal: {
tranformation_sort_order_unequal: { tranformation_sort_order_unequal: {
options = { options = {
comparisons: true, comparisons: true,
}; }
input: { (a = parseInt('100')) != a } input: { (a = parseInt('100')) != a }
expect: { (a = parseInt('100')) != a } expect: { (a = parseInt('100')) != a }
@@ -33,7 +33,7 @@ tranformation_sort_order_unequal: {
tranformation_sort_order_lesser_or_equal: { tranformation_sort_order_lesser_or_equal: {
options = { options = {
comparisons: true, comparisons: true,
}; }
input: { (a = parseInt('100')) <= a } input: { (a = parseInt('100')) <= a }
expect: { (a = parseInt('100')) <= a } expect: { (a = parseInt('100')) <= a }
@@ -41,7 +41,7 @@ tranformation_sort_order_lesser_or_equal: {
tranformation_sort_order_greater_or_equal: { tranformation_sort_order_greater_or_equal: {
options = { options = {
comparisons: true, comparisons: true,
}; }
input: { (a = parseInt('100')) >= a } input: { (a = parseInt('100')) >= a }
expect: { (a = parseInt('100')) >= a } expect: { (a = parseInt('100')) >= a }

View File

@@ -1,6 +1,6 @@
level_zero: { level_zero: {
options = { options = {
keep_fnames: true keep_fnames: true,
} }
mangle = { mangle = {
keep_fnames: true keep_fnames: true
@@ -29,7 +29,7 @@ level_zero: {
level_one: { level_one: {
options = { options = {
keep_fnames: true keep_fnames: true,
} }
mangle = { mangle = {
keep_fnames: true keep_fnames: true
@@ -58,7 +58,7 @@ level_one: {
level_two: { level_two: {
options = { options = {
keep_fnames: true keep_fnames: true,
} }
mangle = { mangle = {
keep_fnames: true keep_fnames: true
@@ -97,7 +97,7 @@ level_two: {
level_three: { level_three: {
options = { options = {
keep_fnames: true keep_fnames: true,
} }
mangle = { mangle = {
keep_fnames: true keep_fnames: true

View File

@@ -22,17 +22,17 @@ else_with_empty_statement: {
conditional_false_stray_else_in_loop: { conditional_false_stray_else_in_loop: {
options = { options = {
evaluate : true, booleans: true,
comparisons : true, comparisons: true,
booleans : true, conditionals: false,
unused : true, dead_code: true,
loops : true, evaluate: true,
side_effects : true, hoist_vars: true,
dead_code : true, if_return: true,
hoist_vars : true, join_vars: true,
join_vars : true, loops: true,
if_return : true, side_effects: true,
conditionals : false, unused: true,
} }
input: { input: {
for (var i = 1; i <= 4; ++i) { for (var i = 1; i <= 4; ++i) {

View File

@@ -125,8 +125,8 @@ label_do: {
label_while: { label_while: {
options = { options = {
evaluate: true,
dead_code: true, dead_code: true,
evaluate: true,
loops: true, loops: true,
} }
input: { input: {

View File

@@ -1,6 +1,8 @@
do_not_update_lhs: { do_not_update_lhs: {
options = { options = {
global_defs: { DEBUG: 0 } global_defs: {
DEBUG: 0,
},
} }
input: { input: {
DEBUG++; DEBUG++;
@@ -16,7 +18,9 @@ do_not_update_lhs: {
do_update_rhs: { do_update_rhs: {
options = { options = {
global_defs: { DEBUG: 0 } global_defs: {
DEBUG: 0,
},
} }
input: { input: {
MY_DEBUG = DEBUG; MY_DEBUG = DEBUG;
@@ -35,7 +39,7 @@ mixed: {
DEBUG: 0, DEBUG: 0,
ENV: 1, ENV: 1,
FOO: 2, FOO: 2,
} },
} }
input: { input: {
var ENV = 3; var ENV = 3;
@@ -60,11 +64,11 @@ mixed: {
x = 0; x = 0;
} }
expect_warnings: [ expect_warnings: [
'WARN: global_defs ENV redefined [test/compress/issue-208.js:41,12]', "WARN: global_defs ENV redefined [test/compress/issue-208.js:1,12]",
'WARN: global_defs FOO redefined [test/compress/issue-208.js:42,12]', "WARN: global_defs FOO redefined [test/compress/issue-208.js:2,12]",
'WARN: global_defs FOO redefined [test/compress/issue-208.js:44,10]', "WARN: global_defs FOO redefined [test/compress/issue-208.js:4,10]",
'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:45,8]', "WARN: global_defs DEBUG redefined [test/compress/issue-208.js:5,8]",
'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:46,8]', "WARN: global_defs DEBUG redefined [test/compress/issue-208.js:6,8]",
'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:47,8]', "WARN: global_defs DEBUG redefined [test/compress/issue-208.js:7,8]",
] ]
} }

View File

@@ -1,5 +1,7 @@
return_with_no_value_in_if_body: { return_with_no_value_in_if_body: {
options = { conditionals: true }; options = {
conditionals: true,
}
input: { input: {
function foo(bar) { function foo(bar) {
if (bar) { if (bar) {

View File

@@ -1,5 +1,7 @@
issue_267: { issue_267: {
options = { comparisons: true }; options = {
comparisons: true,
}
input: { input: {
x = a % b / b * c * 2; x = a % b / b * c * 2;
x = a % b * 2 x = a % b * 2

View File

@@ -1,5 +1,7 @@
issue_269_1: { issue_269_1: {
options = {unsafe: true}; options = {
unsafe: true,
}
input: { input: {
f( f(
String(x), String(x),
@@ -20,7 +22,9 @@ issue_269_1: {
} }
issue_269_dangers: { issue_269_dangers: {
options = {unsafe: true}; options = {
unsafe: true,
}
input: { input: {
f( f(
String(x, x), String(x, x),
@@ -34,7 +38,9 @@ issue_269_dangers: {
} }
issue_269_in_scope: { issue_269_in_scope: {
options = {unsafe: true}; options = {
unsafe: true,
}
input: { input: {
var String, Number, Boolean; var String, Number, Boolean;
f( f(
@@ -50,7 +56,9 @@ issue_269_in_scope: {
} }
strings_concat: { strings_concat: {
options = {unsafe: true}; options = {
unsafe: true,
}
input: { input: {
f( f(
String(x + 'str'), String(x + 'str'),
@@ -67,9 +75,9 @@ strings_concat: {
regexp: { regexp: {
options = { options = {
evaluate: true, evaluate: true,
unsafe: true, unsafe: true,
} }
input: { input: {
RegExp("foo"); RegExp("foo");
RegExp("bar", "ig"); RegExp("bar", "ig");
@@ -85,6 +93,6 @@ regexp: {
RegExp("should", "fail"); RegExp("should", "fail");
} }
expect_warnings: [ expect_warnings: [
'WARN: Error converting RegExp("should","fail") [test/compress/issue-269.js:78,2]', 'WARN: Error converting RegExp("should","fail") [test/compress/issue-269.js:5,2]',
] ]
} }

View File

@@ -26,7 +26,7 @@ warn: {
}().length); }().length);
} }
expect_warnings: [ expect_warnings: [
"WARN: Function.protoype.caller not supported [test/compress/issue-2719.js:17,19]", "WARN: Function.prototype.caller not supported [test/compress/issue-2719.js:5,19]",
"WARN: Function.protoype.arguments not supported [test/compress/issue-2719.js:17,19]", "WARN: Function.prototype.arguments not supported [test/compress/issue-2719.js:5,19]",
] ]
} }

View File

@@ -186,7 +186,7 @@ negate_iife_5_off: {
inline: true, inline: true,
negate_iife: false, negate_iife: false,
sequences: true, sequences: true,
}; }
input: { input: {
if ((function(){ return t })()) { if ((function(){ return t })()) {
foo(true); foo(true);
@@ -245,7 +245,7 @@ negate_iife_issue_1073: {
reduce_vars: true, reduce_vars: true,
sequences: true, sequences: true,
unused: true, unused: true,
}; }
input: { input: {
new (function(a) { new (function(a) {
return function Foo() { return function Foo() {
@@ -273,7 +273,7 @@ issue_1288_side_effects: {
reduce_vars: true, reduce_vars: true,
side_effects: true, side_effects: true,
unused: true, unused: true,
}; }
input: { input: {
if (w) ; if (w) ;
else { else {

View File

@@ -1,5 +1,7 @@
issue_44_valid_ast_1: { issue_44_valid_ast_1: {
options = { unused: true }; options = {
unused: true,
}
input: { input: {
function a(b) { function a(b) {
for (var i = 0, e = b.qoo(); ; i++) {} for (var i = 0, e = b.qoo(); ; i++) {}
@@ -14,7 +16,9 @@ issue_44_valid_ast_1: {
} }
issue_44_valid_ast_2: { issue_44_valid_ast_2: {
options = { unused: true }; options = {
unused: true,
}
input: { input: {
function a(b) { function a(b) {
if (foo) for (var i = 0, e = b.qoo(); ; i++) {} if (foo) for (var i = 0, e = b.qoo(); ; i++) {}

View File

@@ -1,8 +1,8 @@
keep_continue: { keep_continue: {
options = { options = {
dead_code: true, dead_code: true,
evaluate: true evaluate: true,
}; }
input: { input: {
while (a) { while (a) {
if (b) { if (b) {

View File

@@ -1,5 +1,5 @@
NaN_and_Infinity_must_have_parens: { NaN_and_Infinity_must_have_parens: {
options = {}; options = {}
input: { input: {
Infinity.toString(); Infinity.toString();
NaN.toString(); NaN.toString();
@@ -11,7 +11,7 @@ NaN_and_Infinity_must_have_parens: {
} }
NaN_and_Infinity_should_not_be_replaced_when_they_are_redefined: { NaN_and_Infinity_should_not_be_replaced_when_they_are_redefined: {
options = {}; options = {}
input: { input: {
var Infinity, NaN; var Infinity, NaN;
Infinity.toString(); Infinity.toString();

View File

@@ -1,8 +1,8 @@
issue_611: { issue_611: {
options = { options = {
sequences: true, sequences: true,
side_effects: true side_effects: true,
}; }
input: { input: {
define(function() { define(function() {
function fn() {} function fn() {}

View File

@@ -1,9 +1,9 @@
wrongly_optimized: { wrongly_optimized: {
options = { options = {
conditionals: true,
booleans: true, booleans: true,
evaluate: true conditionals: true,
}; evaluate: true,
}
input: { input: {
function func() { function func() {
foo(); foo();

View File

@@ -28,12 +28,12 @@ cond_5: {
dead_code_const_annotation_regex: { dead_code_const_annotation_regex: {
options = { options = {
booleans : true, booleans: true,
conditionals : true, conditionals: true,
dead_code : true, dead_code: true,
evaluate : true, evaluate: true,
expression : true, expression: true,
loops : true, loops: true,
} }
input: { input: {
var unused; var unused;
@@ -82,8 +82,8 @@ drop_value: {
wrongly_optimized: { wrongly_optimized: {
options = { options = {
conditionals: true,
booleans: true, booleans: true,
conditionals: true,
evaluate: true, evaluate: true,
expression: true, expression: true,
} }
@@ -195,7 +195,7 @@ negate_iife_5_off: {
expression: true, expression: true,
negate_iife: false, negate_iife: false,
sequences: true, sequences: true,
}; }
input: { input: {
if ((function(){ return t })()) { if ((function(){ return t })()) {
foo(true); foo(true);
@@ -248,7 +248,9 @@ issue_1254_negate_iife_nested: {
conditional: { conditional: {
options = { options = {
expression: true, expression: true,
pure_funcs: [ "pure" ], pure_funcs: [
"pure"
],
side_effects: true, side_effects: true,
} }
input: { input: {

View File

@@ -1,7 +1,7 @@
negate_booleans_1: { negate_booleans_1: {
options = { options = {
comparisons: true comparisons: true,
}; }
input: { input: {
var a = !a || !b || !c || !d || !e || !f; var a = !a || !b || !c || !d || !e || !f;
} }
@@ -12,8 +12,8 @@ negate_booleans_1: {
negate_booleans_2: { negate_booleans_2: {
options = { options = {
comparisons: true comparisons: true,
}; }
input: { input: {
var match = !x && // should not touch this one var match = !x && // should not touch this one
(!z || c) && (!z || c) &&

View File

@@ -2,25 +2,25 @@ dont_mangle_arguments: {
mangle = { mangle = {
}; };
options = { options = {
sequences : true, booleans: true,
properties : true, comparisons: true,
dead_code : true, conditionals: true,
drop_debugger : true, dead_code: true,
conditionals : true, drop_debugger: true,
comparisons : true, evaluate: true,
evaluate : true, hoist_funs: true,
booleans : true, hoist_vars: true,
loops : true, if_return: true,
unused : true, join_vars: true,
hoist_funs : true, keep_fargs: true,
keep_fargs : true, keep_fnames: false,
keep_fnames : false, loops: true,
hoist_vars : true, negate_iife: false,
if_return : true, properties: true,
join_vars : true, sequences: true,
side_effects : true, side_effects: true,
negate_iife : false unused: true,
}; }
input: { input: {
(function(){ (function(){
var arguments = arguments, not_arguments = 9; var arguments = arguments, not_arguments = 9;

View File

@@ -1,8 +1,8 @@
keep_var_for_in: { keep_var_for_in: {
options = { options = {
hoist_vars: true, hoist_vars: true,
unused: true unused: true,
}; }
input: { input: {
(function(obj){ (function(obj){
var foo = 5; var foo = 5;

View File

@@ -72,7 +72,7 @@ this_binding_collapse_vars: {
this_binding_side_effects: { this_binding_side_effects: {
options = { options = {
side_effects : true side_effects: true,
} }
input: { input: {
(function(foo) { (function(foo) {

View File

@@ -1,9 +1,21 @@
eval_collapse_vars: { eval_collapse_vars: {
options = { options = {
collapse_vars:true, sequences:false, properties:true, dead_code:true, conditionals:true, booleans: true,
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true, collapse_vars: true,
keep_fargs:true, if_return:true, join_vars:true, side_effects:true comparisons: true,
}; conditionals: true,
dead_code: true,
evaluate: true,
hoist_funs: true,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
properties: true,
sequences: false,
side_effects: true,
unused: true,
}
input: { input: {
function f1() { function f1() {
var e = 7; var e = 7;
@@ -46,7 +58,10 @@ eval_collapse_vars: {
} }
eval_unused: { eval_unused: {
options = { unused: true, keep_fargs: false }; options = {
keep_fargs: false,
unused: true,
}
input: { input: {
function f1(a, eval, c, d, e) { function f1(a, eval, c, d, e) {
return a('c') + eval; return a('c') + eval;

View File

@@ -1,8 +1,19 @@
issue979_reported: { issue979_reported: {
options = { options = {
sequences:true, properties:true, dead_code:true, conditionals:true, booleans: true,
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true, comparisons: true,
keep_fargs:true, if_return:true, join_vars:true, side_effects:true conditionals: true,
dead_code: true,
evaluate: true,
hoist_funs: true,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
properties: true,
sequences: true,
side_effects: true,
unused: true,
} }
input: { input: {
function f1() { function f1() {
@@ -30,9 +41,20 @@ issue979_reported: {
issue979_test_negated_is_best: { issue979_test_negated_is_best: {
options = { options = {
sequences:true, properties:true, dead_code:true, conditionals:true, booleans: true,
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true, comparisons: true,
keep_fargs:true, if_return:true, join_vars:true, side_effects:true conditionals: true,
dead_code: true,
evaluate: true,
hoist_funs: true,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
properties: true,
sequences: true,
side_effects: true,
unused: true,
} }
input: { input: {
function f3() { function f3() {

View File

@@ -1,5 +1,9 @@
labels_1: { labels_1: {
options = { if_return: true, conditionals: true, dead_code: true }; options = {
conditionals: true,
dead_code: true,
if_return: true,
}
input: { input: {
out: { out: {
if (foo) break out; if (foo) break out;
@@ -13,7 +17,11 @@ labels_1: {
} }
labels_2: { labels_2: {
options = { if_return: true, conditionals: true, dead_code: true }; options = {
conditionals: true,
dead_code: true,
if_return: true,
}
input: { input: {
out: { out: {
if (foo) print("stuff"); if (foo) print("stuff");
@@ -30,7 +38,11 @@ labels_2: {
} }
labels_3: { labels_3: {
options = { if_return: true, conditionals: true, dead_code: true }; options = {
conditionals: true,
dead_code: true,
if_return: true,
}
input: { input: {
for (var i = 0; i < 5; ++i) { for (var i = 0; i < 5; ++i) {
if (i < 3) continue; if (i < 3) continue;
@@ -45,7 +57,11 @@ labels_3: {
} }
labels_4: { labels_4: {
options = { if_return: true, conditionals: true, dead_code: true }; options = {
conditionals: true,
dead_code: true,
if_return: true,
}
input: { input: {
out: for (var i = 0; i < 5; ++i) { out: for (var i = 0; i < 5; ++i) {
if (i < 3) continue out; if (i < 3) continue out;
@@ -60,7 +76,11 @@ labels_4: {
} }
labels_5: { labels_5: {
options = { if_return: true, conditionals: true, dead_code: true }; options = {
conditionals: true,
dead_code: true,
if_return: true,
}
// should keep the break-s in the following // should keep the break-s in the following
input: { input: {
while (foo) { while (foo) {
@@ -92,7 +112,11 @@ labels_6: {
} }
labels_7: { labels_7: {
options = { if_return: true, conditionals: true, dead_code: true }; options = {
conditionals: true,
dead_code: true,
if_return: true,
}
input: { input: {
while (foo) { while (foo) {
x(); x();
@@ -109,7 +133,11 @@ labels_7: {
} }
labels_8: { labels_8: {
options = { if_return: true, conditionals: true, dead_code: true }; options = {
conditionals: true,
dead_code: true,
if_return: true,
}
input: { input: {
while (foo) { while (foo) {
x(); x();
@@ -127,7 +155,11 @@ labels_8: {
} }
labels_9: { labels_9: {
options = { if_return: true, conditionals: true, dead_code: true }; options = {
conditionals: true,
dead_code: true,
if_return: true,
}
input: { input: {
out: while (foo) { out: while (foo) {
x(); x();
@@ -146,7 +178,11 @@ labels_9: {
} }
labels_10: { labels_10: {
options = { if_return: true, conditionals: true, dead_code: true }; options = {
conditionals: true,
dead_code: true,
if_return: true,
}
input: { input: {
out: while (foo) { out: while (foo) {
x(); x();

View File

@@ -1,5 +1,7 @@
while_becomes_for: { while_becomes_for: {
options = { loops: true }; options = {
loops: true,
}
input: { input: {
while (foo()) bar(); while (foo()) bar();
} }
@@ -9,7 +11,9 @@ while_becomes_for: {
} }
drop_if_break_1: { drop_if_break_1: {
options = { loops: true }; options = {
loops: true,
}
input: { input: {
for (;;) for (;;)
if (foo()) break; if (foo()) break;
@@ -20,7 +24,9 @@ drop_if_break_1: {
} }
drop_if_break_2: { drop_if_break_2: {
options = { loops: true }; options = {
loops: true,
}
input: { input: {
for (;bar();) for (;bar();)
if (foo()) break; if (foo()) break;
@@ -31,7 +37,9 @@ drop_if_break_2: {
} }
drop_if_break_3: { drop_if_break_3: {
options = { loops: true }; options = {
loops: true,
}
input: { input: {
for (;bar();) { for (;bar();) {
if (foo()) break; if (foo()) break;
@@ -48,7 +56,10 @@ drop_if_break_3: {
} }
drop_if_break_4: { drop_if_break_4: {
options = { loops: true, sequences: true }; options = {
loops: true,
sequences: true,
}
input: { input: {
for (;bar();) { for (;bar();) {
x(); x();
@@ -64,7 +75,9 @@ drop_if_break_4: {
} }
drop_if_else_break_1: { drop_if_else_break_1: {
options = { loops: true }; options = {
loops: true,
}
input: { input: {
for (;;) if (foo()) bar(); else break; for (;;) if (foo()) bar(); else break;
} }
@@ -74,7 +87,9 @@ drop_if_else_break_1: {
} }
drop_if_else_break_2: { drop_if_else_break_2: {
options = { loops: true }; options = {
loops: true,
}
input: { input: {
for (;bar();) { for (;bar();) {
if (foo()) baz(); if (foo()) baz();
@@ -87,7 +102,9 @@ drop_if_else_break_2: {
} }
drop_if_else_break_3: { drop_if_else_break_3: {
options = { loops: true }; options = {
loops: true,
}
input: { input: {
for (;bar();) { for (;bar();) {
if (foo()) baz(); if (foo()) baz();
@@ -106,7 +123,10 @@ drop_if_else_break_3: {
} }
drop_if_else_break_4: { drop_if_else_break_4: {
options = { loops: true, sequences: true }; options = {
loops: true,
sequences: true,
}
input: { input: {
for (;bar();) { for (;bar();) {
x(); x();
@@ -123,7 +143,9 @@ drop_if_else_break_4: {
} }
parse_do_while_with_semicolon: { parse_do_while_with_semicolon: {
options = { loops: false }; options = {
loops: false,
}
input: { input: {
do { do {
x(); x();
@@ -135,7 +157,9 @@ parse_do_while_with_semicolon: {
} }
parse_do_while_without_semicolon: { parse_do_while_without_semicolon: {
options = { loops: false }; options = {
loops: false,
}
input: { input: {
do { do {
x(); x();
@@ -153,7 +177,7 @@ evaluate: {
loops: true, loops: true,
passes: 2, passes: 2,
side_effects: true, side_effects: true,
}; }
input: { input: {
while (true) { while (true) {
a(); a();
@@ -457,7 +481,7 @@ init_side_effects: {
options = { options = {
loops: true, loops: true,
side_effects: true, side_effects: true,
}; }
input: { input: {
for (function() {}(), i = 0; i < 5; i++) console.log(i); for (function() {}(), i = 0; i < 5; i++) console.log(i);
for (function() {}(); i < 10; i++) console.log(i); for (function() {}(); i < 10; i++) console.log(i);

View File

@@ -1,7 +1,7 @@
negate_iife_1: { negate_iife_1: {
options = { options = {
negate_iife: true negate_iife: true,
}; }
input: { input: {
(function(){ stuff() })(); (function(){ stuff() })();
} }
@@ -13,7 +13,7 @@ negate_iife_1: {
negate_iife_1_off: { negate_iife_1_off: {
options = { options = {
negate_iife: false, negate_iife: false,
}; }
input: { input: {
(function(){ stuff() })(); (function(){ stuff() })();
} }
@@ -24,7 +24,7 @@ negate_iife_2: {
options = { options = {
inline: true, inline: true,
negate_iife: true, negate_iife: true,
}; }
input: { input: {
(function(){ return {} })().x = 10; (function(){ return {} })().x = 10;
} }
@@ -45,9 +45,9 @@ negate_iife_2_side_effects: {
negate_iife_3: { negate_iife_3: {
options = { options = {
conditionals: true,
negate_iife: true, negate_iife: true,
conditionals: true }
};
input: { input: {
(function(){ return t })() ? console.log(true) : console.log(false); (function(){ return t })() ? console.log(true) : console.log(false);
} }
@@ -88,9 +88,9 @@ negate_iife_3_side_effects: {
negate_iife_3_off: { negate_iife_3_off: {
options = { options = {
negate_iife: false,
conditionals: true, conditionals: true,
}; negate_iife: false,
}
input: { input: {
(function(){ return t })() ? console.log(true) : console.log(false); (function(){ return t })() ? console.log(true) : console.log(false);
} }
@@ -117,10 +117,10 @@ negate_iife_3_off_evaluate: {
negate_iife_4: { negate_iife_4: {
options = { options = {
negate_iife: true,
conditionals: true, conditionals: true,
sequences: true negate_iife: true,
}; sequences: true,
}
input: { input: {
(function(){ return t })() ? console.log(true) : console.log(false); (function(){ return t })() ? console.log(true) : console.log(false);
(function(){ (function(){
@@ -136,11 +136,11 @@ negate_iife_4: {
sequence_off: { sequence_off: {
options = { options = {
negate_iife: false,
conditionals: true, conditionals: true,
sequences: true, negate_iife: false,
passes: 2, passes: 2,
}; sequences: true,
}
input: { input: {
function f() { function f() {
(function(){ return t })() ? console.log(true) : console.log(false); (function(){ return t })() ? console.log(true) : console.log(false);
@@ -171,10 +171,10 @@ sequence_off: {
negate_iife_5: { negate_iife_5: {
options = { options = {
conditionals: true,
negate_iife: true, negate_iife: true,
sequences: true, sequences: true,
conditionals: true, }
};
input: { input: {
if ((function(){ return t })()) { if ((function(){ return t })()) {
foo(true); foo(true);
@@ -194,10 +194,10 @@ negate_iife_5: {
negate_iife_5_off: { negate_iife_5_off: {
options = { options = {
conditionals: true,
negate_iife: false, negate_iife: false,
sequences: true, sequences: true,
conditionals: true, }
};
input: { input: {
if ((function(){ return t })()) { if ((function(){ return t })()) {
foo(true); foo(true);
@@ -217,10 +217,10 @@ negate_iife_5_off: {
negate_iife_nested: { negate_iife_nested: {
options = { options = {
conditionals: true,
negate_iife: true, negate_iife: true,
sequences: true, sequences: true,
conditionals: true, }
};
input: { input: {
function Foo(f) { function Foo(f) {
this.f = f; this.f = f;
@@ -250,10 +250,10 @@ negate_iife_nested: {
negate_iife_nested_off: { negate_iife_nested_off: {
options = { options = {
conditionals: true,
negate_iife: false, negate_iife: false,
sequences: true, sequences: true,
conditionals: true, }
};
input: { input: {
function Foo(f) { function Foo(f) {
this.f = f; this.f = f;
@@ -283,10 +283,10 @@ negate_iife_nested_off: {
negate_iife_issue_1073: { negate_iife_issue_1073: {
options = { options = {
conditionals: true,
negate_iife: true, negate_iife: true,
sequences: true, sequences: true,
conditionals: true, }
};
input: { input: {
new (function(a) { new (function(a) {
return function Foo() { return function Foo() {
@@ -356,7 +356,7 @@ issue_1288: {
conditionals: true, conditionals: true,
negate_iife: true, negate_iife: true,
side_effects: false, side_effects: false,
}; }
input: { input: {
if (w) ; if (w) ;
else { else {

View File

@@ -36,7 +36,9 @@ new_statements_3: {
} }
new_with_rewritten_true_value: { new_with_rewritten_true_value: {
options = { booleans: true } options = {
booleans: true,
}
input: { input: {
new true; new true;
} }

View File

@@ -0,0 +1,181 @@
return_1: {
beautify = {
beautify: false,
preserve_line: true,
}
input: {
console.log(function f() {
return (
f.toString() != 42
);
}());
}
expect_exact: [
"console.log(function f(){",
"",
"return 42!=f.toString()}());",
]
expect_stdout: "true"
}
return_2: {
beautify = {
beautify: true,
preserve_line: true,
}
input: {
console.log(function f() {
return (
f.toString() != 42
);
}());
}
expect_exact: [
"console.log(function f() {",
"",
" return 42 != f.toString();",
"}());",
]
expect_stdout: "true"
}
return_3: {
options = {}
beautify = {
beautify: false,
preserve_line: true,
}
input: {
console.log(function f() {
return (
f.toString() != 42
);
}());
}
expect_exact: [
"console.log(function f(){",
"",
"return 42!=f.toString()}());",
]
expect_stdout: "true"
}
return_4: {
options = {}
beautify = {
beautify: true,
preserve_line: true,
}
input: {
console.log(function f() {
return (
f.toString() != 42
);
}());
}
expect_exact: [
"console.log(function f() {",
"",
" return 42 != f.toString();",
"}());",
]
expect_stdout: "true"
}
return_5: {
beautify = {
beautify: false,
preserve_line: true,
}
input: {
_is_selected = function(tags, slug) {
var ref;
return (ref = _.find(tags, {
slug: slug
})) != null ? ref.selected : void 0;
};
}
expect_exact: [
"_is_selected=function(tags,slug){",
"var ref",
"",
"",
";return null!=(ref=_.find(tags,{slug:slug}))?ref.selected:void 0};",
]
}
return_6: {
beautify = {
beautify: true,
preserve_line: true,
}
input: {
_is_selected = function(tags, slug) {
var ref;
return (ref = _.find(tags, {
slug: slug
})) != null ? ref.selected : void 0;
};
}
expect_exact: [
"_is_selected = function(tags, slug) {",
" var ref;",
"",
"",
" return null != (ref = _.find(tags, {",
" slug: slug",
" })) ? ref.selected : void 0;",
"};",
]
}
return_7: {
options = {}
mangle = {}
beautify = {
beautify: false,
preserve_line: true,
}
input: {
_is_selected = function(tags, slug) {
var ref;
return (ref = _.find(tags, {
slug: slug
})) != null ? ref.selected : void 0;
};
}
expect_exact: [
"_is_selected=function(e,l){",
"var n",
"",
"",
";return null!=(n=_.find(e,{slug:l}))?n.selected:void 0};",
]
}
return_8: {
options = {}
mangle = {}
beautify = {
beautify: true,
preserve_line: true,
}
input: {
_is_selected = function(tags, slug) {
var ref;
return (ref = _.find(tags, {
slug: slug
})) != null ? ref.selected : void 0;
};
}
expect_exact: [
"_is_selected = function(e, l) {",
" var n;",
"",
"",
" return null != (n = _.find(e, {",
" slug: l",
" })) ? n.selected : void 0;",
"};",
]
}

View File

@@ -1832,3 +1832,33 @@ issue_3188_3: {
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
join_expr: {
options = {
evaluate: true,
join_vars: true,
}
input: {
var c = "FAIL";
(function() {
var a = 0;
switch ((a = {}) && (a.b = 0)) {
case 0:
c = "PASS";
}
})();
console.log(c);
}
expect: {
var c = "FAIL";
(function() {
var a = 0;
switch (a = { b: 0 }, a.b) {
case 0:
c = "PASS";
}
})();
console.log(c);
}
expect_stdout: "PASS"
}

View File

@@ -642,3 +642,41 @@ issue_3065_4: {
})(); })();
} }
} }
issue_3325_1: {
options = {
pure_funcs: "cb",
side_effects: true,
}
input: {
function cb() {
console.log("PASS");
}
cb();
}
expect: {
function cb() {
console.log("PASS");
}
}
}
issue_3325_2: {
options = {
pure_funcs: "xxxcbxxx",
side_effects: true,
}
input: {
function cb() {
console.log("PASS");
}
cb();
}
expect: {
function cb() {
console.log("PASS");
}
cb();
}
expect_stdout: "PASS"
}

View File

@@ -187,10 +187,10 @@ issue_2110_1: {
options = { options = {
collapse_vars: true, collapse_vars: true,
pure_getters: "strict", pure_getters: "strict",
sequences: true,
side_effects: true,
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
sequences: true,
side_effects: true,
unused: true, unused: true,
} }
input: { input: {

View File

@@ -1,15 +1,15 @@
reduce_vars: { reduce_vars: {
options = { options = {
conditionals : true, conditionals: true,
evaluate : true, evaluate: true,
inline : true, global_defs: {
global_defs : { C: 0,
C : 0
}, },
reduce_funcs : true, inline: true,
reduce_vars : true, reduce_funcs: true,
toplevel : true, reduce_vars: true,
unused : true toplevel: true,
unused: true,
} }
input: { input: {
var A = 1; var A = 1;
@@ -63,11 +63,11 @@ reduce_vars: {
modified: { modified: {
options = { options = {
conditionals : true, conditionals: true,
evaluate : true, evaluate: true,
reduce_funcs : true, reduce_funcs: true,
reduce_vars : true, reduce_vars: true,
unused : true, unused: true,
} }
input: { input: {
function f0() { function f0() {
@@ -184,12 +184,12 @@ modified: {
unsafe_evaluate: { unsafe_evaluate: {
options = { options = {
evaluate : true, evaluate: true,
reduce_funcs : true, reduce_funcs: true,
reduce_vars : true, reduce_vars: true,
side_effects : true, side_effects: true,
unsafe : true, unsafe: true,
unused : true unused: true,
} }
input: { input: {
function f0(){ function f0(){
@@ -344,10 +344,10 @@ unsafe_evaluate_unknown: {
unsafe_evaluate_object_1: { unsafe_evaluate_object_1: {
options = { options = {
evaluate : true, evaluate: true,
reduce_funcs : true, reduce_funcs: true,
reduce_vars : true, reduce_vars: true,
unsafe : true unsafe: true,
} }
input: { input: {
function f0(){ function f0(){
@@ -463,10 +463,10 @@ unsafe_evaluate_object_3: {
unsafe_evaluate_array_1: { unsafe_evaluate_array_1: {
options = { options = {
evaluate : true, evaluate: true,
reduce_funcs : true, reduce_funcs: true,
reduce_vars : true, reduce_vars: true,
unsafe : true unsafe: true,
} }
input: { input: {
function f0(){ function f0(){
@@ -642,11 +642,11 @@ unsafe_evaluate_array_5: {
unsafe_evaluate_equality_1: { unsafe_evaluate_equality_1: {
options = { options = {
evaluate : true, evaluate: true,
reduce_funcs : true, reduce_funcs: true,
reduce_vars : true, reduce_vars: true,
unsafe : true, unsafe: true,
unused : true unused: true,
} }
input: { input: {
function f0() { function f0() {
@@ -674,12 +674,12 @@ unsafe_evaluate_equality_1: {
unsafe_evaluate_equality_2: { unsafe_evaluate_equality_2: {
options = { options = {
collapse_vars: true, collapse_vars: true,
evaluate : true, evaluate: true,
passes : 2, passes: 2,
reduce_funcs : true, reduce_funcs: true,
reduce_vars : true, reduce_vars: true,
unsafe : true, unsafe: true,
unused : true unused: true,
} }
input: { input: {
function f2() { function f2() {
@@ -1130,7 +1130,7 @@ toplevel_on: {
evaluate: true, evaluate: true,
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
toplevel:true, toplevel: true,
unused: true, unused: true,
} }
input: { input: {
@@ -1148,7 +1148,7 @@ toplevel_off: {
evaluate: true, evaluate: true,
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
toplevel:false, toplevel: false,
unused: true, unused: true,
} }
input: { input: {
@@ -1168,7 +1168,7 @@ toplevel_on_loops_1: {
loops: true, loops: true,
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
toplevel:true, toplevel: true,
unused: true, unused: true,
} }
input: { input: {
@@ -1196,7 +1196,7 @@ toplevel_off_loops_1: {
loops: true, loops: true,
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
toplevel:false, toplevel: false,
unused: true, unused: true,
} }
input: { input: {
@@ -1225,7 +1225,7 @@ toplevel_on_loops_2: {
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
side_effects: true, side_effects: true,
toplevel:true, toplevel: true,
unused: true, unused: true,
} }
input: { input: {
@@ -1251,7 +1251,7 @@ toplevel_off_loops_2: {
loops: true, loops: true,
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
toplevel:false, toplevel: false,
unused: true, unused: true,
} }
input: { input: {
@@ -1278,7 +1278,7 @@ toplevel_on_loops_3: {
loops: true, loops: true,
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
toplevel:true, toplevel: true,
unused: true, unused: true,
} }
input: { input: {
@@ -1296,7 +1296,7 @@ toplevel_off_loops_3: {
loops: true, loops: true,
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
toplevel:false, toplevel: false,
unused: true, unused: true,
} }
input: { input: {
@@ -1560,6 +1560,32 @@ func_modified: {
expect_stdout: "7" expect_stdout: "7"
} }
unused_modified: {
options = {
reduce_vars: true,
unused: true,
}
input: {
console.log(function() {
var b = 1, c = "FAIL";
if (0 || b--)
c = "PASS";
b = 1;
return c;
}());
}
expect: {
console.log(function() {
var b = 1, c = "FAIL";
if (0 || b--)
c = "PASS";
b = 1;
return c;
}());
}
expect_stdout: "PASS"
}
defun_label: { defun_label: {
options = { options = {
passes: 2, passes: 2,
@@ -1868,8 +1894,8 @@ issue_1670_1: {
options = { options = {
comparisons: true, comparisons: true,
conditionals: true, conditionals: true,
evaluate: true,
dead_code: true, dead_code: true,
evaluate: true,
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
side_effects: true, side_effects: true,
@@ -1901,8 +1927,8 @@ issue_1670_1: {
issue_1670_2: { issue_1670_2: {
options = { options = {
conditionals: true, conditionals: true,
evaluate: true,
dead_code: true, dead_code: true,
evaluate: true,
passes: 2, passes: 2,
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
@@ -1934,8 +1960,8 @@ issue_1670_3: {
options = { options = {
comparisons: true, comparisons: true,
conditionals: true, conditionals: true,
evaluate: true,
dead_code: true, dead_code: true,
evaluate: true,
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
side_effects: true, side_effects: true,
@@ -1967,8 +1993,8 @@ issue_1670_3: {
issue_1670_4: { issue_1670_4: {
options = { options = {
conditionals: true, conditionals: true,
evaluate: true,
dead_code: true, dead_code: true,
evaluate: true,
passes: 2, passes: 2,
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
@@ -2714,18 +2740,18 @@ issue_1814_2: {
!function() { !function() {
var b = a + 1; var b = a + 1;
!function(a) { !function(a) {
console.log(a++, b); console.log(b, a++);
}(0); }(0);
}(); }();
} }
expect: { expect: {
!function() { !function() {
!function(a) { !function(a) {
console.log(a++, "321"); console.log("321", a++);
}(0); }(0);
}(); }();
} }
expect_stdout: "0 '321'" expect_stdout: "321 0"
} }
try_abort: { try_abort: {
@@ -5205,11 +5231,11 @@ defun_catch_4: {
try { try {
throw 42; throw 42;
} catch (a) { } catch (a) {
function a() {}
console.log(a); console.log(a);
} }
} }
expect_stdout: true expect_stdout: "42"
node_version: "<=4"
} }
defun_catch_5: { defun_catch_5: {
@@ -5231,10 +5257,10 @@ defun_catch_5: {
throw 42; throw 42;
} catch (a) { } catch (a) {
console.log(a); console.log(a);
function a() {}
} }
} }
expect_stdout: true expect_stdout: "42"
node_version: "<=4"
} }
defun_catch_6: { defun_catch_6: {
@@ -5328,6 +5354,7 @@ issue_2774: {
issue_2799_1: { issue_2799_1: {
options = { options = {
passes: 2,
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
unused: true, unused: true,
@@ -6403,3 +6430,310 @@ issue_3140_5: {
} }
expect_stdout: "1" expect_stdout: "1"
} }
issue_3240_1: {
options = {
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
(function() {
f(1);
function f(a) {
console.log(a);
var g = function() {
f(a - 1);
};
if (a) g();
}
})();
}
expect: {
(function() {
(function f(a) {
console.log(a);
var g = function() {
f(a - 1);
};
if (a) g();
})(1);
})();
}
expect_stdout: [
"1",
"0",
]
}
issue_3240_2: {
options = {
passes: 2,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
(function() {
f(1);
function f(a) {
console.log(a);
var g = function() {
f(a - 1);
};
if (a) g();
}
})();
}
expect: {
(function() {
(function f(a) {
console.log(a);
if (a) (function() {
f(a - 1);
})();
})(1);
})();
}
expect_stdout: [
"1",
"0",
]
}
issue_3240_3: {
options = {
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
(function() {
f();
function f(b) {
if (!f.a) f.a = 0;
console.log(f.a.toString());
var g = function() {
(b ? function() {} : function() {
f.a++;
f(1);
})();
};
g();
}
})();
}
expect: {
(function() {
(function f(b) {
if (!f.a) f.a = 0;
console.log(f.a.toString());
var g = function() {
(b ? function() {} : function() {
f.a++;
f(1);
})();
};
g();
})();
})();
}
expect_stdout: [
"0",
"1",
]
}
issue_3240_4: {
options = {
passes: 2,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
(function() {
f();
function f(b) {
if (!f.a) f.a = 0;
console.log(f.a.toString());
var g = function() {
(b ? function() {} : function() {
f.a++;
f(1);
})();
};
g();
}
})();
}
expect: {
(function() {
(function f(b) {
if (!f.a) f.a = 0;
console.log(f.a.toString());
(function() {
(b ? function() {} : function() {
f.a++;
f(1);
})();
})();
})();
})();
}
expect_stdout: [
"0",
"1",
]
}
issues_3267_1: {
options = {
collapse_vars: true,
conditionals: true,
dead_code: true,
evaluate: true,
inline: true,
reduce_vars: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
(function(x) {
x();
})(function() {
(function(i) {
if (i)
return console.log("PASS");
throw "FAIL";
})(Object());
});
}
expect: {
!function(i) {
if (i)
return console.log("PASS");
throw "FAIL";
}(Object());
}
expect_stdout: "PASS"
}
issues_3267_2: {
options = {
collapse_vars: true,
conditionals: true,
dead_code: true,
evaluate: true,
inline: true,
keep_fargs: false,
passes: 2,
reduce_vars: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
(function(x) {
x();
})(function() {
(function(i) {
if (i)
return console.log("PASS");
throw "FAIL";
})(Object());
});
}
expect: {
!function() {
if (Object())
return console.log("PASS");
throw "FAIL";
}();
}
expect_stdout: "PASS"
}
issues_3267_3: {
options = {
collapse_vars: true,
conditionals: true,
dead_code: true,
evaluate: true,
inline: true,
keep_fargs: false,
passes: 2,
reduce_vars: true,
sequences: true,
side_effects: true,
unsafe: true,
unused: true,
}
input: {
(function(x) {
x();
})(function() {
(function(i) {
if (i)
return console.log("PASS");
throw "FAIL";
})(Object());
});
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
}
issue_3297: {
options = {
reduce_vars: true,
unused: true,
}
input: {
(function() {
function f() {
var a;
var b = function a() {
console.log(a === b) && f();
};
b();
}
f();
})();
}
expect: {
(function() {
(function f() {
var b = function a() {
console.log(a === b) && f();
};
b();
})();
})();
}
expect_stdout: "true"
}
drop_side_effect_free: {
options = {
collapse_vars: true,
evaluate: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
}
input: {
var a = 123;
"" + (a && (a.b = 0) || a);
console.log(a);
}
expect: {
var a = 123;
a.b = 0;
console.log(a);
}
expect_stdout: "123"
}

View File

@@ -534,3 +534,80 @@ function_catch_catch_ie8: {
"undefined", "undefined",
] ]
} }
function_do_catch_ie8: {
rename = true
options = {
ie8: true,
side_effects: true,
unused: true,
}
mangle = {
ie8: true,
toplevel: true,
}
input: {
var a = 1, b = 1, c = 0;
function d(e) {
var f, g, h, i;
do {
try {
try {
var j = function q(){}();
} catch (r) {
--a && w("ddddddddeeeeeeegggggggggiiiiilllllllnnnnntuuuuuuuuyyyyyyy");
var k, l, m, n, o;
--m;
--n;
--o;
}
try {
i[1];
} catch (s) {
var p;
switch (function t() {
c++;
}()) {
case j + --p:
}
}
} catch (u) {}
} while (--i);
b--;
}
d();
console.log(b, c);
}
expect: {
var t = 1, u = 1, y = 0;
function c(c) {
var d;
do {
try {
try {
var e = void 0;
} catch (i) {
--t && w("ddddddddeeeeeeegggggggggiiiiilllllllnnnnntuuuuuuuuyyyyyyy");
0;
0;
0;
}
try {
d[1];
} catch (l) {
var g;
switch(function x() {
y++;
}()) {
case e + --g:
}
}
} catch (n) {}
} while (--d);
u--;
}
c();
console.log(u, y);
}
expect_stdout: "0 1"
}

View File

@@ -1,24 +1,24 @@
return_undefined: { return_undefined: {
options = { options = {
sequences : false, booleans: true,
if_return : true, comparisons: true,
evaluate : true, conditionals: true,
dead_code : true, dead_code: true,
conditionals : true, drop_debugger: true,
comparisons : true, evaluate: true,
booleans : true, hoist_funs: true,
unused : true, hoist_vars: true,
side_effects : true, if_return: true,
properties : true, join_vars: true,
drop_debugger : true, keep_fargs: true,
loops : true, keep_fnames: false,
hoist_funs : true, loops: true,
keep_fargs : true, negate_iife: true,
keep_fnames : false, properties: true,
hoist_vars : true, sequences: false,
join_vars : true, side_effects: true,
negate_iife : true unused: true,
}; }
input: { input: {
function f0() { function f0() {
} }

View File

@@ -1,7 +1,7 @@
make_sequences_1: { make_sequences_1: {
options = { options = {
sequences: true sequences: true,
}; }
input: { input: {
foo(); foo();
bar(); bar();
@@ -14,8 +14,8 @@ make_sequences_1: {
make_sequences_2: { make_sequences_2: {
options = { options = {
sequences: true sequences: true,
}; }
input: { input: {
if (boo) { if (boo) {
foo(); foo();
@@ -35,8 +35,8 @@ make_sequences_2: {
make_sequences_3: { make_sequences_3: {
options = { options = {
sequences: true sequences: true,
}; }
input: { input: {
function f() { function f() {
foo(); foo();
@@ -61,8 +61,8 @@ make_sequences_3: {
make_sequences_4: { make_sequences_4: {
options = { options = {
sequences: true sequences: true,
}; }
input: { input: {
x = 5; x = 5;
if (y) z(); if (y) z();
@@ -90,7 +90,9 @@ make_sequences_4: {
} }
lift_sequences_1: { lift_sequences_1: {
options = { sequences: true }; options = {
sequences: true,
}
input: { input: {
var foo, x, y, bar; var foo, x, y, bar;
foo = !(x(), y(), bar()); foo = !(x(), y(), bar());
@@ -102,7 +104,10 @@ lift_sequences_1: {
} }
lift_sequences_2: { lift_sequences_2: {
options = { sequences: true, evaluate: true }; options = {
evaluate: true,
sequences: true,
}
input: { input: {
var foo = 1, bar; var foo = 1, bar;
foo.x = (foo = {}, 10); foo.x = (foo = {}, 10);
@@ -119,7 +124,10 @@ lift_sequences_2: {
} }
lift_sequences_3: { lift_sequences_3: {
options = { sequences: true, conditionals: true }; options = {
conditionals: true,
sequences: true,
}
input: { input: {
var x, foo, bar, baz; var x, foo, bar, baz;
x = (foo(), bar(), baz()) ? 10 : 20; x = (foo(), bar(), baz()) ? 10 : 20;
@@ -131,7 +139,9 @@ lift_sequences_3: {
} }
lift_sequences_4: { lift_sequences_4: {
options = { side_effects: true }; options = {
side_effects: true,
}
input: { input: {
var x, foo, bar, baz; var x, foo, bar, baz;
x = (foo, bar, baz); x = (foo, bar, baz);
@@ -160,7 +170,9 @@ lift_sequences_5: {
} }
for_sequences: { for_sequences: {
options = { sequences: true }; options = {
sequences: true,
}
input: { input: {
// 1 // 1
foo(); foo();
@@ -203,7 +215,7 @@ for_sequences: {
limit_1: { limit_1: {
options = { options = {
sequences: 3, sequences: 3,
}; }
input: { input: {
a; a;
b; b;
@@ -228,7 +240,7 @@ limit_1: {
limit_2: { limit_2: {
options = { options = {
sequences: 3, sequences: 3,
}; }
input: { input: {
a, b; a, b;
c, d; c, d;
@@ -246,9 +258,9 @@ limit_2: {
negate_iife_for: { negate_iife_for: {
options = { options = {
sequences: true,
negate_iife: true, negate_iife: true,
}; sequences: true,
}
input: { input: {
(function() {})(); (function() {})();
for (i = 0; i < 5; i++) console.log(i); for (i = 0; i < 5; i++) console.log(i);
@@ -265,7 +277,7 @@ negate_iife_for: {
iife: { iife: {
options = { options = {
sequences: true, sequences: true,
}; }
input: { input: {
x = 42; x = 42;
(function a() {})(); (function a() {})();
@@ -912,14 +924,14 @@ call: {
b.c = function() { b.c = function() {
console.log(this === b ? "bar" : "baz"); console.log(this === b ? "bar" : "baz");
}, },
a, b(), b(),
(a, b.c)(), (a, b.c)(),
a, function() { function() {
console.log(this === a); console.log(this === a);
}(), }(),
a, new b(), new b(),
a, new b.c(), new b.c(),
a, new function() { new function() {
console.log(this === a); console.log(this === a);
}(); }();
} }
@@ -932,3 +944,23 @@ call: {
"false", "false",
] ]
} }
missing_link: {
options = {
conditionals: true,
evaluate: true,
sequences: true,
}
input: {
var a = 100;
a;
a++ + (0 ? 2 : 1);
console.log(a);
}
expect: {
var a = 100;
a,
a++,
console.log(a);
}
}

View File

@@ -820,8 +820,8 @@ issue_1758: {
issue_2535: { issue_2535: {
options = { options = {
evaluate: true,
dead_code: true, dead_code: true,
evaluate: true,
switches: true, switches: true,
} }
input: { input: {

View File

@@ -2,7 +2,7 @@ typeof_evaluation: {
options = { options = {
evaluate: true, evaluate: true,
typeofs: true, typeofs: true,
}; }
input: { input: {
a = typeof 1; a = typeof 1;
b = typeof 'test'; b = typeof 'test';
@@ -27,11 +27,11 @@ typeof_evaluation: {
typeof_in_boolean_context: { typeof_in_boolean_context: {
options = { options = {
booleans : true, booleans: true,
evaluate : true, conditionals: true,
conditionals : true, evaluate: true,
side_effects : true, side_effects: true,
}; }
input: { input: {
function f1(x) { return typeof x ? "yes" : "no"; } function f1(x) { return typeof x ? "yes" : "no"; }
function f2() { return typeof g()? "Yes" : "No"; } function f2() { return typeof g()? "Yes" : "No"; }

View File

@@ -1,5 +1,5 @@
unicode_parse_variables: { unicode_parse_variables: {
options = {}; options = {}
input: { input: {
var a = {}; var a = {};
a.你好 = 456; a.你好 = 456;

109
test/compress/webkit.js Normal file
View File

@@ -0,0 +1,109 @@
lambda_call_dot_assign: {
beautify = {
webkit: false,
}
input: {
console.log(function() {
return {};
}().a = 1);
}
expect_exact: "console.log(function(){return{}}().a=1);"
expect_stdout: "1"
}
lambda_call_dot_assign_webkit: {
beautify = {
webkit: true,
}
input: {
console.log(function() {
return {};
}().a = 1);
}
expect_exact: "console.log((function(){return{}}()).a=1);"
expect_stdout: "1"
}
lambda_dot_assign: {
beautify = {
webkit: false,
}
input: {
console.log(function() {
1 + 1;
}.a = 1);
}
expect_exact: "console.log(function(){1+1}.a=1);"
expect_stdout: "1"
}
lambda_dot_assign_webkit: {
beautify = {
webkit: true,
}
input: {
console.log(function() {
1 + 1;
}.a = 1);
}
expect_exact: "console.log((function(){1+1}).a=1);"
expect_stdout: "1"
}
lambda_name_mangle: {
mangle = {}
input: {
console.log(typeof function foo(bar) {});
}
expect_exact: "console.log(typeof function o(n){});"
expect_stdout: "function"
}
lambda_name_mangle_ie8: {
mangle = {
ie8: true,
toplevel: true,
}
input: {
console.log(typeof function foo(bar) {});
}
expect_exact: "console.log(typeof function n(o){});"
expect_stdout: "function"
}
function_name_mangle: {
options = {
keep_fnames: true,
reduce_vars: true,
unused: true,
}
mangle = {}
input: {
(function() {
function foo(bar) {}
console.log(typeof foo);
})();
}
expect_exact: "(function(){console.log(typeof function o(n){})})();"
expect_stdout: "function"
}
function_name_mangle_ie8: {
options = {
keep_fnames: true,
reduce_vars: true,
unused: true,
}
mangle = {
ie8: true,
toplevel: true,
}
input: {
(function() {
function foo(bar) {}
console.log(typeof foo);
})();
}
expect_exact: "(function(){console.log(typeof function n(o){})})();"
expect_stdout: "function"
}

View File

@@ -1,14 +1,16 @@
exports["Compressor"] = Compressor;
exports["JS_Parse_Error"] = JS_Parse_Error;
exports["OutputStream"] = OutputStream;
exports["SourceMap"] = SourceMap;
exports["TreeWalker"] = TreeWalker;
exports["base54"] = base54; exports["base54"] = base54;
exports["Compressor"] = Compressor;
exports["defaults"] = defaults; exports["defaults"] = defaults;
exports["is_identifier"] = is_identifier;
exports["JS_Parse_Error"] = JS_Parse_Error;
exports["mangle_properties"] = mangle_properties; exports["mangle_properties"] = mangle_properties;
exports["minify"] = minify; exports["minify"] = minify;
exports["OutputStream"] = OutputStream;
exports["parse"] = parse; exports["parse"] = parse;
exports["push_uniq"] = push_uniq;
exports["reserve_quoted_keys"] = reserve_quoted_keys; exports["reserve_quoted_keys"] = reserve_quoted_keys;
exports["SourceMap"] = SourceMap;
exports["string_template"] = string_template; exports["string_template"] = string_template;
exports["tokenizer"] = tokenizer; exports["tokenizer"] = tokenizer;
exports["is_identifier"] = is_identifier; exports["TreeTransformer"] = TreeTransformer;
exports["TreeWalker"] = TreeWalker;

View File

@@ -23,10 +23,9 @@ module.exports = function(url, callback) {
var options = parse(url); var options = parse(url);
options.rejectUnauthorized = false; options.rejectUnauthorized = false;
require(options.protocol.slice(0, -1)).get(options, function(res) { require(options.protocol.slice(0, -1)).get(options, function(res) {
if (res.statusCode !== 200) return callback(res); if (res.statusCode !== 200) return callback(res.statusCode);
res.pipe(fs.createWriteStream(local(url)).on("close", function() { res.pipe(fs.createWriteStream(local(url)));
callback(null, read(url)); callback(null, res);
}));
}); });
}).on("open", function() { }).on("open", function() {
callback(null, result); callback(null, result);

View File

@@ -0,0 +1,8 @@
{
"compress": false,
"mangle": {
"properties": {
"regex": "/^_/"
}
}
}

View File

@@ -0,0 +1,8 @@
function f() {
"aaaaaaaaaa";
var o = {
prop: 1,
_int: 2,
};
return o.prop + o._int;
}

View File

@@ -25,30 +25,35 @@ if (typeof phantom == "undefined") {
request.resume(); request.resume();
var url = site + request.url; var url = site + request.url;
fetch(url, function(err, res) { fetch(url, function(err, res) {
if (err) throw err; if (err) {
response.writeHead(200, { if (typeof err != "number") throw err;
"Content-Type": { response.writeHead(err);
css: "text/css", response.end();
js: "application/javascript",
png: "image/png"
}[url.slice(url.lastIndexOf(".") + 1)] || "text/html; charset=utf-8"
});
if (/\.js$/.test(url)) {
var stderr = "";
var uglifyjs = child_process.fork("bin/uglifyjs", args, {
silent: true
}).on("exit", function(code) {
console.log("uglifyjs", url.slice(site.length + 1), args.join(" "));
console.log(stderr);
if (code) throw new Error("uglifyjs failed with code " + code);
});
uglifyjs.stderr.on("data", function(data) {
stderr += data;
}).setEncoding("utf8");
uglifyjs.stdout.pipe(response);
res.pipe(uglifyjs.stdin);
} else { } else {
res.pipe(response); 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 uglifyjs = child_process.fork("bin/uglifyjs", args, {
silent: true
}).on("exit", function(code) {
console.log("uglifyjs", url.slice(site.length + 1), args.join(" "));
console.log(stderr);
if (code) throw new Error("uglifyjs failed with code " + code);
});
uglifyjs.stderr.on("data", function(data) {
stderr += data;
}).setEncoding("utf8");
uglifyjs.stdout.pipe(response);
res.pipe(uglifyjs.stdin);
} else {
res.pipe(response);
}
} }
}); });
}).listen(); }).listen();

View File

@@ -1,6 +1,7 @@
var assert = require("assert"); var assert = require("assert");
var exec = require("child_process").exec; var exec = require("child_process").exec;
var fs = require("fs"); var fs = require("fs");
var run_code = require("../sandbox").run_code;
function read(path) { function read(path) {
return fs.readFileSync(path, "utf8"); return fs.readFileSync(path, "utf8");
@@ -8,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(30000); this.timeout(30000);
var command = uglifyjscmd + ' --self -cm --wrap WrappedUglifyJS'; var command = uglifyjscmd + ' --self -cm --wrap WrappedUglifyJS';
exec(command, function(err, stdout) { exec(command, function(err, stdout) {
@@ -68,7 +69,7 @@ describe("bin/uglifyjs", function() {
done(); done();
}); });
}); });
it("should not append source map to output when not using --source-map url=inline", function(done) { it("Should not append source map to output when not using --source-map url=inline", function(done) {
var command = uglifyjscmd + ' test/input/issue-1323/sample.js'; var command = uglifyjscmd + ' test/input/issue-1323/sample.js';
exec(command, function(err, stdout) { exec(command, function(err, stdout) {
if (err) throw err; if (err) throw err;
@@ -76,7 +77,7 @@ describe("bin/uglifyjs", function() {
done(); done();
}); });
}); });
it("should not consider source map file content as source map file name (issue #2082)", function(done) { it("Should not consider source map file content as source map file name (issue #2082)", function(done) {
var command = [ var command = [
uglifyjscmd, uglifyjscmd,
"test/input/issue-2082/sample.js", "test/input/issue-2082/sample.js",
@@ -257,7 +258,7 @@ describe("bin/uglifyjs", function() {
assert.strictEqual(lines[0], "Parse error at test/input/invalid/simple.js:1,12"); assert.strictEqual(lines[0], "Parse error at test/input/invalid/simple.js:1,12");
assert.strictEqual(lines[1], "function f(a{}"); assert.strictEqual(lines[1], "function f(a{}");
assert.strictEqual(lines[2], " ^"); assert.strictEqual(lines[2], " ^");
assert.strictEqual(lines[3], "ERROR: Unexpected token punc «{», expected punc «,»"); assert.strictEqual(lines[3], "ERROR: Unexpected token: punc «{», expected: punc «,»");
done(); done();
}); });
}); });
@@ -281,7 +282,7 @@ describe("bin/uglifyjs", function() {
assert.strictEqual(lines[0], "Parse error at test/input/invalid/eof.js:2,0"); assert.strictEqual(lines[0], "Parse error at test/input/invalid/eof.js:2,0");
assert.strictEqual(lines[1], "foo, bar("); assert.strictEqual(lines[1], "foo, bar(");
assert.strictEqual(lines[2], " ^"); assert.strictEqual(lines[2], " ^");
assert.strictEqual(lines[3], "ERROR: Unexpected token: eof (undefined)"); assert.strictEqual(lines[3], "ERROR: Unexpected token: eof");
done(); done();
}); });
}); });
@@ -293,7 +294,7 @@ describe("bin/uglifyjs", function() {
assert.strictEqual(lines[0], "Parse error at test/input/invalid/loop-no-body.js:2,0"); assert.strictEqual(lines[0], "Parse error at test/input/invalid/loop-no-body.js:2,0");
assert.strictEqual(lines[1], "for (var i = 0; i < 1; i++) "); assert.strictEqual(lines[1], "for (var i = 0; i < 1; i++) ");
assert.strictEqual(lines[2], " ^"); assert.strictEqual(lines[2], " ^");
assert.strictEqual(lines[3], "ERROR: Unexpected token: eof (undefined)"); assert.strictEqual(lines[3], "ERROR: Unexpected token: eof");
done(); done();
}); });
}); });
@@ -362,7 +363,7 @@ describe("bin/uglifyjs", function() {
"Parse error at test/input/invalid/dot_1.js:1,2", "Parse error at test/input/invalid/dot_1.js:1,2",
"a.=", "a.=",
" ^", " ^",
"ERROR: Unexpected token: operator (=)" "ERROR: Unexpected token: operator «=», expected: name"
].join("\n")); ].join("\n"));
done(); done();
}); });
@@ -376,7 +377,7 @@ describe("bin/uglifyjs", function() {
"Parse error at test/input/invalid/dot_2.js:1,0", "Parse error at test/input/invalid/dot_2.js:1,0",
"%.a;", "%.a;",
"^", "^",
"ERROR: Unexpected token: operator (%)" "ERROR: Unexpected token: operator «%»"
].join("\n")); ].join("\n"));
done(); done();
}); });
@@ -390,7 +391,7 @@ describe("bin/uglifyjs", function() {
"Parse error at test/input/invalid/dot_3.js:1,2", "Parse error at test/input/invalid/dot_3.js:1,2",
"a./();", "a./();",
" ^", " ^",
"ERROR: Unexpected token: operator (/)" "ERROR: Unexpected token: operator «/», expected: name"
].join("\n")); ].join("\n"));
done(); done();
}); });
@@ -404,7 +405,7 @@ describe("bin/uglifyjs", function() {
"Parse error at test/input/invalid/object.js:1,13", "Parse error at test/input/invalid/object.js:1,13",
"console.log({%: 1});", "console.log({%: 1});",
" ^", " ^",
"ERROR: Unexpected token: operator (%)" "ERROR: Unexpected token: operator «%»"
].join("\n")); ].join("\n"));
done(); done();
}); });
@@ -502,7 +503,7 @@ describe("bin/uglifyjs", function() {
"Parse error at test/input/invalid/else.js:1,7", "Parse error at test/input/invalid/else.js:1,7",
"if (0) else 1;", "if (0) else 1;",
" ^", " ^",
"ERROR: Unexpected token: keyword (else)" "ERROR: Unexpected token: keyword «else»"
].join("\n")); ].join("\n"));
done(); done();
}); });
@@ -633,6 +634,14 @@ describe("bin/uglifyjs", function() {
done(); done();
}); });
}); });
it("Should work with mangle.properties.regex from --config-file", function(done) {
var command = uglifyjscmd + " test/input/issue-3315/input.js --config-file test/input/issue-3315/config.json";
exec(command, function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, 'function f(){"aaaaaaaaaa";var a={prop:1,a:2};return a.prop+a.a}\n');
done();
});
});
it("Should fail with --define a-b", function(done) { it("Should fail with --define a-b", function(done) {
var command = uglifyjscmd + " test/input/issue-505/input.js --define a-b"; var command = uglifyjscmd + " test/input/issue-505/input.js --define a-b";
exec(command, function(err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
@@ -651,7 +660,7 @@ describe("bin/uglifyjs", function() {
}); });
}); });
it("Should work with explicit --no-rename", function(done) { it("Should work with explicit --no-rename", function(done) {
var command = uglifyjscmd + " test/input/rename/input.js -mc --no-rename"; var command = uglifyjscmd + " test/input/rename/input.js -mc passes=2 --no-rename";
exec(command, function(err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "function f(n){return function(n){return n}(n)}\n"); assert.strictEqual(stdout, "function f(n){return function(n){return n}(n)}\n");
@@ -659,7 +668,7 @@ describe("bin/uglifyjs", function() {
}); });
}); });
it("Should work with implicit --rename", function(done) { it("Should work with implicit --rename", function(done) {
var command = uglifyjscmd + " test/input/rename/input.js -mc"; var command = uglifyjscmd + " test/input/rename/input.js -mc passes=2";
exec(command, function(err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "function f(n){return n}\n"); assert.strictEqual(stdout, "function f(n){return n}\n");
@@ -667,7 +676,7 @@ describe("bin/uglifyjs", function() {
}); });
}); });
it("Should work with implicit --no-rename", function(done) { it("Should work with implicit --no-rename", function(done) {
var command = uglifyjscmd + " test/input/rename/input.js -c"; var command = uglifyjscmd + " test/input/rename/input.js -c passes=2";
exec(command, function(err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "function f(x){return function(x){return x}(x)}\n"); assert.strictEqual(stdout, "function f(x){return function(x){return x}(x)}\n");
@@ -706,4 +715,32 @@ describe("bin/uglifyjs", function() {
done(); done();
}); });
}); });
it("Should compress swarm of unused variables with reasonable performance", function(done) {
var code = [
"console.log(function() {",
];
for (var i = 0; i < 10000; i++) {
code.push("var obj" + i + " = {p: " + i + "};");
}
code.push("var map = {");
for (var i = 0; i < 10000; i++) {
code.push("obj" + i + ": obj" + i + ",");
}
code = code.concat([
"};",
"return obj25.p + obj121.p + obj1024.p;",
"}());",
]).join("\n");
exec(uglifyjscmd + " -mc", function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, [
"console.log(function(){",
"var p={p:25},n={p:121},o={p:1024};",
"return p.p+n.p+o.p",
"}());\n",
].join(""));
assert.strictEqual(run_code(stdout), run_code(code));
done();
}).stdin.end(code);
});
}); });

View File

@@ -13,7 +13,7 @@ describe("comments", function() {
var fail = function(e) { var fail = function(e) {
return e instanceof UglifyJS.JS_Parse_Error return e instanceof UglifyJS.JS_Parse_Error
&& e.message === "Unexpected token: operator (>)" && e.message === "Unexpected token: operator «>»"
&& e.line === 2 && e.line === 2
&& e.col === 0; && e.col === 0;
} }
@@ -36,7 +36,7 @@ describe("comments", function() {
var fail = function(e) { var fail = function(e) {
return e instanceof UglifyJS.JS_Parse_Error return e instanceof UglifyJS.JS_Parse_Error
&& e.message === "Unexpected token: operator (>)" && e.message === "Unexpected token: operator «>»"
&& e.line === 5 && e.line === 5
&& e.col === 0; && e.col === 0;
} }

View File

@@ -2,14 +2,12 @@ var assert = require("assert");
var UglifyJS = require("../node"); var UglifyJS = require("../node");
describe("Directives", function() { describe("Directives", function() {
it ("Should allow tokenizer to store directives state", function() { it("Should allow tokenizer to store directives state", function() {
var tokenizer = UglifyJS.tokenizer("", "foo.js"); var tokenizer = UglifyJS.tokenizer("", "foo.js");
// Stack level 0 // Stack level 0
assert.strictEqual(tokenizer.has_directive("use strict"), false); assert.strictEqual(tokenizer.has_directive("use strict"), false);
assert.strictEqual(tokenizer.has_directive("use asm"), false); assert.strictEqual(tokenizer.has_directive("use asm"), false);
assert.strictEqual(tokenizer.has_directive("use thing"), false); assert.strictEqual(tokenizer.has_directive("use thing"), false);
// Stack level 2 // Stack level 2
tokenizer.push_directives_stack(); tokenizer.push_directives_stack();
tokenizer.push_directives_stack(); tokenizer.push_directives_stack();
@@ -17,7 +15,6 @@ describe("Directives", function() {
assert.strictEqual(tokenizer.has_directive("use strict"), true); assert.strictEqual(tokenizer.has_directive("use strict"), true);
assert.strictEqual(tokenizer.has_directive("use asm"), false); assert.strictEqual(tokenizer.has_directive("use asm"), false);
assert.strictEqual(tokenizer.has_directive("use thing"), false); assert.strictEqual(tokenizer.has_directive("use thing"), false);
// Stack level 3 // Stack level 3
tokenizer.push_directives_stack(); tokenizer.push_directives_stack();
tokenizer.add_directive("use strict"); tokenizer.add_directive("use strict");
@@ -25,13 +22,11 @@ describe("Directives", function() {
assert.strictEqual(tokenizer.has_directive("use strict"), true); assert.strictEqual(tokenizer.has_directive("use strict"), true);
assert.strictEqual(tokenizer.has_directive("use asm"), true); assert.strictEqual(tokenizer.has_directive("use asm"), true);
assert.strictEqual(tokenizer.has_directive("use thing"), false); assert.strictEqual(tokenizer.has_directive("use thing"), false);
// Stack level 2 // Stack level 2
tokenizer.pop_directives_stack(); tokenizer.pop_directives_stack();
assert.strictEqual(tokenizer.has_directive("use strict"), true); assert.strictEqual(tokenizer.has_directive("use strict"), true);
assert.strictEqual(tokenizer.has_directive("use asm"), false); assert.strictEqual(tokenizer.has_directive("use asm"), false);
assert.strictEqual(tokenizer.has_directive("use thing"), false); assert.strictEqual(tokenizer.has_directive("use thing"), false);
// Stack level 3 // Stack level 3
tokenizer.push_directives_stack(); tokenizer.push_directives_stack();
tokenizer.add_directive("use thing"); tokenizer.add_directive("use thing");
@@ -39,152 +34,138 @@ describe("Directives", function() {
assert.strictEqual(tokenizer.has_directive("use strict"), true); assert.strictEqual(tokenizer.has_directive("use strict"), true);
assert.strictEqual(tokenizer.has_directive("use asm"), false); // Directives are strict! assert.strictEqual(tokenizer.has_directive("use asm"), false); // Directives are strict!
assert.strictEqual(tokenizer.has_directive("use thing"), true); assert.strictEqual(tokenizer.has_directive("use thing"), true);
// Stack level 2 // Stack level 2
tokenizer.pop_directives_stack(); tokenizer.pop_directives_stack();
assert.strictEqual(tokenizer.has_directive("use strict"), true); assert.strictEqual(tokenizer.has_directive("use strict"), true);
assert.strictEqual(tokenizer.has_directive("use asm"), false); assert.strictEqual(tokenizer.has_directive("use asm"), false);
assert.strictEqual(tokenizer.has_directive("use thing"), false); assert.strictEqual(tokenizer.has_directive("use thing"), false);
// Stack level 1 // Stack level 1
tokenizer.pop_directives_stack(); tokenizer.pop_directives_stack();
assert.strictEqual(tokenizer.has_directive("use strict"), false); assert.strictEqual(tokenizer.has_directive("use strict"), false);
assert.strictEqual(tokenizer.has_directive("use asm"), false); assert.strictEqual(tokenizer.has_directive("use asm"), false);
assert.strictEqual(tokenizer.has_directive("use thing"), false); assert.strictEqual(tokenizer.has_directive("use thing"), false);
// Stack level 0 // Stack level 0
tokenizer.pop_directives_stack(); tokenizer.pop_directives_stack();
assert.strictEqual(tokenizer.has_directive("use strict"), false); assert.strictEqual(tokenizer.has_directive("use strict"), false);
assert.strictEqual(tokenizer.has_directive("use asm"), false); assert.strictEqual(tokenizer.has_directive("use asm"), false);
assert.strictEqual(tokenizer.has_directive("use thing"), false); assert.strictEqual(tokenizer.has_directive("use thing"), false);
}); });
it("Should know which strings are directive and which ones are not", function() { it("Should know which strings are directive and which ones are not", function() {
var test_directive = function(tokenizer, test) { [
test.directives.map(function(directive) { [
assert.strictEqual(tokenizer.has_directive(directive), true, directive + " in " + test.input); '"use strict"\n',
}); [ "use strict"],
test.non_directives.map(function(fake_directive) { [ "use asm"]
assert.strictEqual(tokenizer.has_directive(fake_directive), false, fake_directive + " in " + test.input); ],
}); [
} '"use\\\nstrict";',
[],
var tests = [ [ "use strict", "use\nstrict", "use \nstrict", "use asm" ]
{ ],
input: '"use strict"\n', [
directives: ["use strict"], '"use strict"\n"use asm"\n"use bar"\n',
non_directives: ["use asm"] [ "use strict", "use asm", "use bar" ],
}, [ "use foo", "use\\x20strict" ]
{ ],
input: '"use\\\nstrict";', [
directives: [], '"use \\\nstrict";"use strict";',
non_directives: ["use strict", "use\nstrict", "use \nstrict", "use asm"] [],
}, [ "use strict", "use\nstrict", "use \nstrict", "use asm" ]
{ ],
input: '"use strict"\n"use asm"\n"use bar"\n', [
directives: ["use strict", "use asm", "use bar"], '"\\76";',
non_directives: ["use foo", "use\\x20strict"] [],
}, [ ">", "\\76" ]
{ ],
input: '"use \\\nstrict";"use strict";', [
directives: [], // no ; or newline
non_directives: ["use strict", "use\nstrict", "use \nstrict", "use asm"] '"use strict"',
}, [],
{ [ "use strict", "use\nstrict", "use \nstrict", "use asm" ]
input: '"\\76";', ],
directives: [], [
non_directives: [">", "\\76"] ';"use strict"',
}, [],
{ [ "use strict", "use\nstrict", "use \nstrict", "use asm" ]
input: '"use strict"', // no ; or newline ],
directives: [],
non_directives: ["use strict", "use\nstrict", "use \nstrict", "use asm"]
},
{
input: ';"use strict"',
directives: [],
non_directives: ["use strict", "use\nstrict", "use \nstrict", "use asm"]
},
// Duplicate above code but put it in a function // Duplicate above code but put it in a function
{ [
input: 'function foo() {"use strict"\n', 'function foo() {"use strict"\n',
directives: ["use strict"], [ "use strict" ],
non_directives: ["use asm"] [ "use asm" ]
}, ],
{ [
input: 'function foo() {"use\\\nstrict";', 'function foo() {"use\\\nstrict";',
directives: [], [],
non_directives: ["use strict", "use\nstrict", "use \nstrict", "use asm"] [ "use strict", "use\nstrict", "use \nstrict", "use asm" ]
}, ],
{ [
input: 'function foo() {"use strict"\n"use asm"\n"use bar"\n', 'function foo() {"use strict"\n"use asm"\n"use bar"\n',
directives: ["use strict", "use asm", "use bar"], [ "use strict", "use asm", "use bar" ],
non_directives: ["use foo", "use\\x20strict"] [ "use foo", "use\\x20strict" ]
}, ],
{ [
input: 'function foo() {"use \\\nstrict";"use strict";', 'function foo() {"use \\\nstrict";"use strict";',
directives: [], [],
non_directives: ["use strict", "use\nstrict", "use \nstrict", "use asm"] [ "use strict", "use\nstrict", "use \nstrict", "use asm" ]
}, ],
{ [
input: 'var foo = function() {"\\76";', 'var foo = function() {"\\76";',
directives: [], [],
non_directives: [">", "\\76"] [ ">", "\\76" ]
}, ],
{ [
input: 'var foo = function() {"use strict"', // no ; or newline 'var foo = function() {"use strict"', // no ; or newline
directives: [], [],
non_directives: ["use strict", "use\nstrict", "use \nstrict", "use asm"] [ "use strict", "use\nstrict", "use \nstrict", "use asm" ]
}, ],
{ [
input: 'var foo = function() {;"use strict"', 'var foo = function() {;"use strict"',
directives: [], [],
non_directives: ["use strict", "use\nstrict", "use \nstrict", "use asm"] [ "use strict", "use\nstrict", "use \nstrict", "use asm" ]
}, ],
// Special cases // Special cases
{ [
input: '"1";"2";"3";"4";;"5"', '"1";"2";"3";"4";;"5"',
directives: ["1", "2", "3", "4"], [ "1", "2", "3", "4" ],
non_directives: ["5", "6", "use strict", "use asm"] [ "5", "6", "use strict", "use asm" ]
}, ],
{ [
input: 'if(1){"use strict";', 'if(1){"use strict";',
directives: [], [],
non_directives: ["use strict", "use\nstrict", "use \nstrict", "use asm"] [ "use strict", "use\nstrict", "use \nstrict", "use asm" ]
}, ],
{ [
input: '"use strict";try{"use asm";', '"use strict";try{"use asm";',
directives: ["use strict"], [ "use strict" ],
non_directives: ["use\nstrict", "use \nstrict", "use asm"] [ "use\nstrict", "use \nstrict", "use asm" ]
} ],
]; ].forEach(function(test) {
var tokenizer = UglifyJS.tokenizer(test[0] + "]", "foo.js");
for (var i = 0; i < tests.length; i++) { assert.throws(function() {
// Fail parser deliberately to get state at failure UglifyJS.parse(tokenizer);
var tokenizer = UglifyJS.tokenizer(tests[i].input + "]", "foo.js"); }, function(e) {
return e instanceof UglifyJS.JS_Parse_Error
try { && /^Unexpected token: punc «]»/.test(e.message)
var parser = UglifyJS.parse(tokenizer); }, test[0]);
throw new Error("Expected parser to fail"); test[1].forEach(function(directive) {
} catch (e) { assert.strictEqual(tokenizer.has_directive(directive), true, directive + " in " + test[0]);
assert.strictEqual(e instanceof UglifyJS.JS_Parse_Error, true); });
assert.strictEqual(e.message, "Unexpected token: punc (])"); test[2].forEach(function(fake_directive) {
} assert.strictEqual(tokenizer.has_directive(fake_directive), false, fake_directive + " in " + test[0]);
});
test_directive(tokenizer, tests[i]); });
}
}); });
it("Should test EXPECT_DIRECTIVE RegExp", function() { it("Should test EXPECT_DIRECTIVE RegExp", function() {
[ [
["", true], [ "", true ],
["'test';", true], [ "'test';", true ],
["'test';;", true], [ "'test';;", true ],
["'tests';\n", true], [ "'tests';\n", true ],
["'tests'", false], [ "'tests'", false ],
["'tests'; \n\t", true], [ "'tests'; \n\t", true ],
["'tests';\n\n", true], [ "'tests';\n\n", true ],
["\n\n\"use strict\";\n\n", true] [ "\n\n\"use strict\";\n\n", true ],
].forEach(function(test) { ].forEach(function(test) {
var out = UglifyJS.OutputStream(); var out = UglifyJS.OutputStream();
out.print(test[0]); out.print(test[0]);
@@ -192,19 +173,33 @@ describe("Directives", function() {
assert.strictEqual(out.get() === test[0] + ';""', test[1], test[0]); assert.strictEqual(out.get() === test[0] + ';""', test[1], test[0]);
}); });
}); });
it("Should only print 2 semicolons spread over 2 lines in beautify mode", function() { it("Should only print 2 semicolons spread over 2 lines in beautify mode", function() {
assert.strictEqual( var result = UglifyJS.minify([
UglifyJS.minify( '"use strict";',
'"use strict";\'use strict\';"use strict";"use strict";;\'use strict\';console.log(\'use strict\');', "'use strict';",
{output: {beautify: true, quote_style: 3}, compress: false} '"use strict";',
).code, '"use strict";;',
'"use strict";\n\n\'use strict\';\n\n"use strict";\n\n"use strict";\n\n;\'use strict\';\n\nconsole.log(\'use strict\');' "'use strict';",
); "console.log('use strict');"
].join(""), {
compress: false,
output: {
beautify: true,
quote_style: 3
}
});
if (result.error) throw result.error;
assert.strictEqual(result.code, [
'"use strict";',
"'use strict';",
'"use strict";',
'"use strict";',
";'use strict';",
"console.log('use strict');"
].join("\n\n"));
}); });
it("Should not add double semicolons in non-scoped block statements to avoid strings becoming directives", function() { it("Should not add double semicolons in non-scoped block statements to avoid strings becoming directives", function() {
var tests = [ [
[ [
'{"use\x20strict"}', '{"use\x20strict"}',
'{"use strict"}' '{"use strict"}'
@@ -221,26 +216,27 @@ describe("Directives", function() {
'if(1){"use\x20strict"} else {"use strict"}', 'if(1){"use\x20strict"} else {"use strict"}',
'if(1){"use strict"}else{"use strict"}' 'if(1){"use strict"}else{"use strict"}'
] ]
]; ].forEach(function(test) {
var result = UglifyJS.minify(test[0], {
for (var i = 0; i < tests.length; i++) { compress: false,
assert.strictEqual( mangle: false
UglifyJS.minify(tests[i][0], {compress: false, mangle: false}).code, });
tests[i][1], if (result.error) throw result.error;
tests[i][0] assert.strictEqual(result.code, test[1], test[0]);
); });
}
}); });
it("Should add double semicolon when relying on automatic semicolon insertion", function() { it("Should add double semicolon when relying on automatic semicolon insertion", function() {
var code = UglifyJS.minify('"use strict";"use\\x20strict";', var result = UglifyJS.minify('"use strict";"use\\x20strict";', {
{output: {semicolons: false}, compress: false} compress: false,
).code; output: {
assert.strictEqual(code, '"use strict";;"use strict"\n'); semicolons: false
}
});
if (result.error) throw result.error;
assert.strictEqual(result.code, '"use strict";;"use strict"\n');
}); });
it("Should check quote style of directives", function() { it("Should check quote style of directives", function() {
var tests = [ [
// 0. Prefer double quotes, unless string contains more double quotes than single quotes // 0. Prefer double quotes, unless string contains more double quotes than single quotes
[ [
'"testing something";', '"testing something";',
@@ -337,45 +333,53 @@ describe("Directives", function() {
3, 3,
"'\"use strict\"';", "'\"use strict\"';",
], ],
]; ].forEach(function(test) {
for (var i = 0; i < tests.length; i++) { var result = UglifyJS.minify(test[0], {
assert.strictEqual( compress: false,
UglifyJS.minify(tests[i][0], {output:{quote_style: tests[i][1]}, compress: false}).code, output: {
tests[i][2], quote_style: test[1]
tests[i][0] + " using mode " + tests[i][1] }
); });
} if (result.error) throw result.error;
assert.strictEqual(result.code, test[2], test[0] + " using mode " + test[1]);
});
}); });
it("Should be able to compress without side effects", function() { it("Should be able to compress without side effects", function() {
// NOTE: the "use asm" directive disables any optimisation after being defined [
var tests = [
[ [
'"use strict";"use strict";"use strict";"use foo";"use strict";;"use sloppy";doSomething("foo");', '"use strict";"use strict";"use strict";"use foo";"use strict";;"use sloppy";doSomething("foo");',
'"use strict";"use foo";doSomething("foo");', '"use strict";doSomething("foo");'
'function f(){ "use strict" }',
'function f(){ "use asm" }',
'function f(){ "use nondirective" }',
'function f(){ ;"use strict" }',
'function f(){ "use \n"; }',
], ],
[ [
// Nothing gets optimised in the compressor because "use asm" is the first statement // Nothing gets optimised in the compressor because "use asm" is the first statement
'"use asm";"use\\x20strict";1+1;', '"use asm";"use\\x20strict";1+1;',
'"use asm";;"use strict";1+1;', // Yet, the parser noticed that "use strict" wasn't a directive // Yet, the parser noticed that "use strict" wasn't a directive
'function f(){"use strict"}', '"use asm";;"use strict";1+1;',
'function f(){"use asm"}', ],
'function f(){"use nondirective"}', [
'function f(){}', 'function f(){ "use strict" }',
'function f(){}', 'function f(){}'
] ],
]; [
'function f(){ "use asm" }',
for (var i = 0; i < tests.length; i++) { 'function f(){"use asm"}'
assert.strictEqual( ],
UglifyJS.minify(tests[i][0]).code, [
tests[i][1], 'function f(){ "use nondirective" }',
tests[i][0] 'function f(){}'
); ],
} [
'function f(){ ;"use strict" }',
'function f(){}'
],
[
'function f(){ "use \\n"; }',
'function f(){}'
],
].forEach(function(test) {
var result = UglifyJS.minify(test[0]);
if (result.error) throw result.error;
assert.strictEqual(result.code, test[1], test[0]);
});
}); });
}); });

View File

@@ -69,7 +69,7 @@ describe("Getters and setters", function() {
var fail = function(data) { var fail = function(data) {
return function(e) { return function(e) {
return e instanceof UglifyJS.JS_Parse_Error return e instanceof UglifyJS.JS_Parse_Error
&& e.message === "Unexpected token: operator (" + data.operator + ")"; && e.message === "Unexpected token: operator «" + data.operator + "»";
}; };
}; };
var errorMessage = function(data) { var errorMessage = function(data) {

View File

@@ -35,7 +35,7 @@ describe("bin/uglifyjs with input file globs", function() {
done(); done();
}); });
}); });
it("should throw with non-matching glob string", function(done) { it("Should throw with non-matching glob string", function(done) {
var command = uglifyjscmd + ' "test/input/issue-1242/blah.*"'; var command = uglifyjscmd + ' "test/input/issue-1242/blah.*"';
exec(command, function(err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
@@ -53,7 +53,7 @@ describe("bin/uglifyjs with input file globs", function() {
done(); done();
}); });
}); });
it("should handle special characters in glob string", function(done) { it("Should handle special characters in glob string", function(done) {
var command = uglifyjscmd + ' "test/input/issue-1632/^{*}[???](*)+$.??" -cm'; var command = uglifyjscmd + ' "test/input/issue-1632/^{*}[???](*)+$.??" -cm';
exec(command, function(err, stdout) { exec(command, function(err, stdout) {
@@ -63,7 +63,7 @@ describe("bin/uglifyjs with input file globs", function() {
done(); done();
}); });
}); });
it("should handle array of glob strings - matching and otherwise", function(done) { it("Should handle array of glob strings - matching and otherwise", function(done) {
var dir = "test/input/issue-1242"; var dir = "test/input/issue-1242";
var command = uglifyjscmd + ' "' + [ var command = uglifyjscmd + ' "' + [
path.join(dir, "b*.es5"), path.join(dir, "b*.es5"),

View File

@@ -87,7 +87,7 @@ describe("minify", function() {
assert.strictEqual(run_code(compressed), run_code(original)); assert.strictEqual(run_code(compressed), run_code(original));
}); });
it("Should avoid mangled names in cache", function() { it("Should avoid cached names when mangling top-level variables", function() {
var cache = {}; var cache = {};
var original = ""; var original = "";
var compressed = ""; var compressed = "";
@@ -116,10 +116,34 @@ describe("minify", function() {
assert.strictEqual(run_code(compressed), run_code(original)); assert.strictEqual(run_code(compressed), run_code(original));
}); });
it("Should avoid cached names when mangling inner-scoped variables", function() {
var cache = {};
var original = "";
var compressed = "";
[
'var extend = function(a, b) { console.log("extend"); a(); b(); }; function A() { console.log("A"); };',
'var B = function(A) { function B() { console.log("B") }; extend(B, A); return B; }(A);',
].forEach(function(code) {
var result = UglifyJS.minify(code, {
compress: false,
nameCache: cache,
toplevel: true,
});
if (result.error) throw result.error;
original += code;
compressed += result.code;
});
assert.strictEqual(compressed, [
'var o=function(o,n){console.log("extend");o();n()};function n(){console.log("A")}',
'var e=function(n){function e(){console.log("B")}o(e,n);return e}(n);',
].join(""));
assert.strictEqual(run_code(compressed), run_code(original));
});
it("Should not parse invalid use of reserved words", function() { it("Should not parse invalid use of reserved words", function() {
assert.strictEqual(UglifyJS.minify("function enum(){}").error, undefined); assert.strictEqual(UglifyJS.minify("function enum(){}").error, undefined);
assert.strictEqual(UglifyJS.minify("function static(){}").error, undefined); assert.strictEqual(UglifyJS.minify("function static(){}").error, undefined);
assert.strictEqual(UglifyJS.minify("function this(){}").error.message, "Unexpected token: name (this)"); assert.strictEqual(UglifyJS.minify("function this(){}").error.message, "Unexpected token: name «this»");
}); });
describe("keep_quoted_props", function() { describe("keep_quoted_props", function() {
@@ -187,7 +211,7 @@ describe("minify", function() {
}); });
describe("#__PURE__", function() { describe("#__PURE__", function() {
it("should drop #__PURE__ hint after use", function() { it("Should drop #__PURE__ hint after use", function() {
var result = UglifyJS.minify('//@__PURE__ comment1 #__PURE__ comment2\n foo(), bar();', { var result = UglifyJS.minify('//@__PURE__ comment1 #__PURE__ comment2\n foo(), bar();', {
output: { output: {
comments: "all", comments: "all",
@@ -197,7 +221,7 @@ describe("minify", function() {
var code = result.code; var code = result.code;
assert.strictEqual(code, "// comment1 comment2\nbar();"); assert.strictEqual(code, "// comment1 comment2\nbar();");
}); });
it("should drop #__PURE__ hint if function is retained", function() { it("Should drop #__PURE__ hint if function is retained", function() {
var result = UglifyJS.minify("var a = /*#__PURE__*/(function(){ foo(); })();", { var result = UglifyJS.minify("var a = /*#__PURE__*/(function(){ foo(); })();", {
output: { output: {
comments: "all", comments: "all",
@@ -210,16 +234,16 @@ describe("minify", function() {
}); });
describe("JS_Parse_Error", function() { describe("JS_Parse_Error", function() {
it("should return syntax error", function() { it("Should return syntax error", function() {
var result = UglifyJS.minify("function f(a{}"); var result = UglifyJS.minify("function f(a{}");
var err = result.error; var err = result.error;
assert.ok(err instanceof Error); assert.ok(err instanceof Error);
assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: Unexpected token punc «{», expected punc «,»"); assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: Unexpected token: punc «{», expected: punc «,»");
assert.strictEqual(err.filename, "0"); assert.strictEqual(err.filename, "0");
assert.strictEqual(err.line, 1); assert.strictEqual(err.line, 1);
assert.strictEqual(err.col, 12); assert.strictEqual(err.col, 12);
}); });
it("should reject duplicated label name", function() { it("Should reject duplicated label name", function() {
var result = UglifyJS.minify("L:{L:{}}"); var result = UglifyJS.minify("L:{L:{}}");
var err = result.error; var err = result.error;
assert.ok(err instanceof Error); assert.ok(err instanceof Error);
@@ -231,7 +255,7 @@ describe("minify", function() {
}); });
describe("global_defs", function() { describe("global_defs", function() {
it("should throw for non-trivial expressions", function() { it("Should throw for non-trivial expressions", function() {
var result = UglifyJS.minify("alert(42);", { var result = UglifyJS.minify("alert(42);", {
compress: { compress: {
global_defs: { global_defs: {
@@ -241,9 +265,9 @@ describe("minify", function() {
}); });
var err = result.error; var err = result.error;
assert.ok(err instanceof Error); assert.ok(err instanceof Error);
assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: Unexpected token: keyword (debugger)"); assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: Unexpected token: keyword «debugger»");
}); });
it("should skip inherited properties", function() { it("Should skip inherited properties", function() {
var foo = Object.create({ skip: this }); var foo = Object.create({ skip: this });
foo.bar = 42; foo.bar = 42;
var result = UglifyJS.minify("alert(FOO);", { var result = UglifyJS.minify("alert(FOO);", {

View File

@@ -53,7 +53,6 @@ describe("sourcemaps", function() {
assert.strictEqual(map.version, 3); assert.strictEqual(map.version, 3);
assert.deepEqual(map.names, [ "x" ]); assert.deepEqual(map.names, [ "x" ]);
}); });
it("Should give correct names", function() { it("Should give correct names", function() {
var map = source_map([ var map = source_map([
"({", "({",
@@ -67,7 +66,6 @@ describe("sourcemaps", function() {
].join("\n")); ].join("\n"));
assert.deepEqual(map.names, [ "enabled", "x" ]); assert.deepEqual(map.names, [ "enabled", "x" ]);
}); });
it("Should mark array/object literals", function() { it("Should mark array/object literals", function() {
var result = UglifyJS.minify([ var result = UglifyJS.minify([
"var obj = {};", "var obj = {};",
@@ -80,7 +78,6 @@ describe("sourcemaps", function() {
assert.strictEqual(result.code, "({}).wat([]);"); assert.strictEqual(result.code, "({}).wat([]);");
assert.strictEqual(result.map, '{"version":3,"sources":["0"],"names":["wat"],"mappings":"CAAU,IACNA,IAAI"}'); assert.strictEqual(result.map, '{"version":3,"sources":["0"],"names":["wat"],"mappings":"CAAU,IACNA,IAAI"}');
}); });
it("Should give correct sourceRoot", function() { it("Should give correct sourceRoot", function() {
var code = "console.log(42);"; var code = "console.log(42);";
var result = UglifyJS.minify(code, { var result = UglifyJS.minify(code, {
@@ -212,6 +209,9 @@ describe("sourcemaps", function() {
}); });
it("Should work with max_line_len", function() { it("Should work with max_line_len", function() {
var result = UglifyJS.minify(read("./test/input/issue-505/input.js"), { var result = UglifyJS.minify(read("./test/input/issue-505/input.js"), {
compress: {
directives: false,
},
output: { output: {
max_line_len: 20 max_line_len: 20
}, },
@@ -261,7 +261,6 @@ describe("sourcemaps", function() {
var map = prepare_map(orig); var map = prepare_map(orig);
assert.equal(map.sourceContentFor("index.js"), orig.sourcesContent[0]); assert.equal(map.sourceContentFor("index.js"), orig.sourcesContent[0]);
}); });
it("Should copy sourcesContent if sources are relative", function() { it("Should copy sourcesContent if sources are relative", function() {
var relativeMap = get_map(); var relativeMap = get_map();
relativeMap.sources = ['./index.js']; relativeMap.sources = ['./index.js'];
@@ -270,7 +269,6 @@ describe("sourcemaps", function() {
assert.equal(map.sourcesContent.length, 1); assert.equal(map.sourcesContent.length, 1);
assert.equal(map.sourceContentFor("index.js"), relativeMap.sourcesContent[0]); assert.equal(map.sourceContentFor("index.js"), relativeMap.sourcesContent[0]);
}); });
it("Should not have invalid mappings from inputSourceMap", function() { it("Should not have invalid mappings from inputSourceMap", function() {
var map = prepare_map(get_map()); var map = prepare_map(get_map());
// The original source has only 2 lines, check that mappings don't have more lines // The original source has only 2 lines, check that mappings don't have more lines

View File

@@ -3,7 +3,7 @@ var exec = require("child_process").exec;
var UglifyJS = require("../.."); var UglifyJS = require("../..");
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(60000); this.timeout(60000);
var uglifyjs = '"' + process.argv[0] + '" bin/uglifyjs'; var uglifyjs = '"' + process.argv[0] + '" bin/uglifyjs';
@@ -23,7 +23,7 @@ describe("spidermonkey export/import sanity test", function() {
}); });
}); });
it("should not add unnecessary escape slashes to regexps", function() { it("Should not add unnecessary escape slashes to regexps", function() {
var input = "/[\\\\/]/;"; var input = "/[\\\\/]/;";
var ast = UglifyJS.parse(input).to_mozilla_ast(); var ast = UglifyJS.parse(input).to_mozilla_ast();
assert.equal( assert.equal(

View File

@@ -23,68 +23,200 @@ require("./mocha.js");
/* -----[ utils ]----- */ /* -----[ utils ]----- */
function tmpl() { function evaluate(code) {
return U.string_template.apply(this, arguments); if (code instanceof U.AST_Node) code = make_code(code, { beautify: true });
return new Function("return(" + code + ")")();
} }
function log() { function log() {
var txt = tmpl.apply(this, arguments); console.log("%s", tmpl.apply(null, arguments));
console.log("%s", txt);
} }
function log_directory(dir) { function make_code(ast, options) {
log("*** Entering [{dir}]", { dir: dir }); var stream = U.OutputStream(options);
ast.print(stream);
return stream.get();
} }
function log_start_file(file) { function parse_test(file) {
log("--- {file}", { file: file }); var script = fs.readFileSync(file, "utf8");
} // TODO try/catch can be removed after fixing https://github.com/mishoo/UglifyJS2/issues/348
try {
function log_test(name) { var ast = U.parse(script, {
log(" Running test [{name}]", { name: name }); filename: file
} });
} catch (e) {
function find_test_files(dir) { console.log("Caught error while parsing tests in " + file + "\n");
return fs.readdirSync(dir).filter(function(name) { console.log(e);
return /\.js$/i.test(name); throw e;
});
}
function test_directory(dir) {
return path.resolve(tests_dir, dir);
}
function as_toplevel(input, mangle_options) {
if (!(input instanceof U.AST_BlockStatement))
throw new Error("Unsupported input syntax");
for (var i = 0; i < input.body.length; i++) {
var stat = input.body[i];
if (stat instanceof U.AST_SimpleStatement && stat.body instanceof U.AST_String)
input.body[i] = new U.AST_Directive(stat.body);
else break;
} }
var toplevel = new U.AST_Toplevel(input); var tests = {};
toplevel.figure_out_scope(mangle_options); var tw = new U.TreeWalker(function(node, descend) {
return toplevel; if (node instanceof U.AST_LabeledStatement
&& tw.parent() instanceof U.AST_Toplevel) {
var name = node.label.name;
if (name in tests) {
throw new Error('Duplicated test name "' + name + '" in ' + file);
}
tests[name] = get_one_test(name, node.body);
return true;
}
if (!(node instanceof U.AST_Toplevel)) croak(node);
});
ast.walk(tw);
return tests;
function croak(node) {
throw new Error(tmpl("Can't understand test file {file} [{line},{col}]\n{code}", {
file: file,
line: node.start.line,
col: node.start.col,
code: make_code(node, { beautify: false })
}));
}
function read_string(stat) {
if (stat.TYPE == "SimpleStatement") {
var body = stat.body;
switch(body.TYPE) {
case "String":
return body.value;
case "Array":
return body.elements.map(function(element) {
if (element.TYPE !== "String")
throw new Error("Should be array of strings");
return element.value;
}).join("\n");
}
}
throw new Error("Should be string or array of strings");
}
function get_one_test(name, block) {
var test = { name: name, options: {} };
var tw = new U.TreeWalker(function(node, descend) {
if (node instanceof U.AST_Assign) {
if (!(node.left instanceof U.AST_SymbolRef)) {
croak(node);
}
var name = node.left.name;
test[name] = evaluate(node.right);
return true;
}
if (node instanceof U.AST_LabeledStatement) {
var label = node.label;
assert.ok([
"input",
"expect",
"expect_exact",
"expect_warnings",
"expect_stdout",
"node_version",
].indexOf(label.name) >= 0, tmpl("Unsupported label {name} [{line},{col}]", {
name: label.name,
line: label.start.line,
col: label.start.col
}));
var stat = node.body;
if (label.name == "expect_exact" || label.name == "node_version") {
test[label.name] = read_string(stat);
} else if (label.name == "expect_stdout") {
var body = stat.body;
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 {
test[label.name] = read_string(stat) + "\n";
}
} else {
test[label.name] = stat;
}
return true;
}
});
block.walk(tw);
return test;
}
}
// Try to reminify original input with standard options
// to see if it matches expect_stdout.
function reminify(orig_options, input_code, input_formatted, expect_stdout) {
for (var i = 0; i < minify_options.length; i++) {
var options = JSON.parse(minify_options[i]);
if (options.compress) [
"keep_fargs",
"keep_fnames",
].forEach(function(name) {
if (name in orig_options) {
options.compress[name] = orig_options[name];
}
});
var options_formatted = JSON.stringify(options, null, 4);
var result = U.minify(input_code, options);
if (result.error) {
log("!!! failed input reminify\n---INPUT---\n{input}\n---OPTIONS---\n{options}\n--ERROR---\n{error}\n\n", {
input: input_formatted,
options: options_formatted,
error: result.error,
});
return false;
} else {
var stdout = run_code(result.code);
if (typeof expect_stdout != "string" && typeof stdout != "string" && expect_stdout.name == stdout.name) {
stdout = expect_stdout;
}
if (!sandbox.same_stdout(expect_stdout, stdout)) {
log("!!! failed running reminified input\n---INPUT---\n{input}\n---OPTIONS---\n{options}\n---OUTPUT---\n{output}\n---EXPECTED {expected_type}---\n{expected}\n---ACTUAL {actual_type}---\n{actual}\n\n", {
input: input_formatted,
options: options_formatted,
output: result.code,
expected_type: typeof expect_stdout == "string" ? "STDOUT" : "ERROR",
expected: expect_stdout,
actual_type: typeof stdout == "string" ? "STDOUT" : "ERROR",
actual: stdout,
});
return false;
}
}
}
return true;
}
function run_code(code) {
var result = sandbox.run_code(code, true);
return typeof result == "string" ? result.replace(/\u001b\[\d+m/g, "") : result;
} }
function run_compress_tests() { function run_compress_tests() {
var dir = test_directory("compress"); var dir = path.resolve(tests_dir, "compress");
log_directory("compress"); fs.readdirSync(dir).filter(function(name) {
var files = find_test_files(dir); return /\.js$/i.test(name);
function test_file(file) { }).forEach(function(file) {
log_start_file(file); log("--- {file}", { file: file });
function test_case(test) { function test_case(test) {
log_test(test.name); log(" Running test [{name}]", { name: test.name });
var output_options = test.beautify || {}; var output_options = test.beautify || {};
var expect; var expect;
if (test.expect) { if (test.expect) {
expect = make_code(as_toplevel(test.expect, test.mangle), output_options); expect = make_code(to_toplevel(test.expect, test.mangle), output_options);
} else { } else {
expect = test.expect_exact; expect = test.expect_exact;
} }
var input = as_toplevel(test.input, test.mangle); var input = to_toplevel(test.input, test.mangle);
var input_code = make_code(input, output_options); var input_code = make_code(input);
var input_formatted = make_code(test.input, { var input_formatted = make_code(test.input, {
beautify: true, beautify: true,
quote_style: 3, quote_style: 3,
@@ -209,185 +341,27 @@ function run_compress_tests() {
failed_files[file] = 1; failed_files[file] = 1;
} }
} }
}
files.forEach(function(file) {
test_file(file);
}); });
} }
function parse_test(file) { function tmpl() {
var script = fs.readFileSync(file, "utf8"); return U.string_template.apply(null, arguments);
// TODO try/catch can be removed after fixing https://github.com/mishoo/UglifyJS2/issues/348
try {
var ast = U.parse(script, {
filename: file
});
} catch (e) {
console.log("Caught error while parsing tests in " + file + "\n");
console.log(e);
throw e;
}
var tests = {};
var tw = new U.TreeWalker(function(node, descend) {
if (node instanceof U.AST_LabeledStatement
&& tw.parent() instanceof U.AST_Toplevel) {
var name = node.label.name;
if (name in tests) {
throw new Error('Duplicated test name "' + name + '" in ' + file);
}
tests[name] = get_one_test(name, node.body);
return true;
}
if (!(node instanceof U.AST_Toplevel)) croak(node);
});
ast.walk(tw);
return tests;
function croak(node) {
throw new Error(tmpl("Can't understand test file {file} [{line},{col}]\n{code}", {
file: file,
line: node.start.line,
col: node.start.col,
code: make_code(node, { beautify: false })
}));
}
function read_string(stat) {
if (stat.TYPE == "SimpleStatement") {
var body = stat.body;
switch(body.TYPE) {
case "String":
return body.value;
case "Array":
return body.elements.map(function(element) {
if (element.TYPE !== "String")
throw new Error("Should be array of strings");
return element.value;
}).join("\n");
}
}
throw new Error("Should be string or array of strings");
}
function get_one_test(name, block) {
var test = { name: name, options: {} };
var tw = new U.TreeWalker(function(node, descend) {
if (node instanceof U.AST_Assign) {
if (!(node.left instanceof U.AST_SymbolRef)) {
croak(node);
}
var name = node.left.name;
test[name] = evaluate(node.right);
return true;
}
if (node instanceof U.AST_LabeledStatement) {
var label = node.label;
assert.ok(
[
"input",
"expect",
"expect_exact",
"expect_warnings",
"expect_stdout",
"node_version",
].indexOf(label.name) >= 0,
tmpl("Unsupported label {name} [{line},{col}]", {
name: label.name,
line: label.start.line,
col: label.start.col
})
);
var stat = node.body;
if (label.name == "expect_exact" || label.name == "node_version") {
test[label.name] = read_string(stat);
} else if (label.name == "expect_stdout") {
var body = stat.body;
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 {
test[label.name] = read_string(stat) + "\n";
}
} else {
test[label.name] = stat;
}
return true;
}
});
block.walk(tw);
return test;
};
} }
function make_code(ast, options) { function to_toplevel(input, mangle_options) {
var stream = U.OutputStream(options); if (!(input instanceof U.AST_BlockStatement)) throw new Error("Unsupported input syntax");
ast.print(stream); var directive = true;
return stream.get(); var offset = input.start.line;
} var tokens = [];
var toplevel = new U.AST_Toplevel(input.transform(new U.TreeTransformer(function(node) {
function evaluate(code) { if (U.push_uniq(tokens, node.start)) node.start.line -= offset;
if (code instanceof U.AST_Node) if (!directive || node === input) return;
code = make_code(code, { beautify: true }); if (node instanceof U.AST_SimpleStatement && node.body instanceof U.AST_String) {
return new Function("return(" + code + ")")(); return new U.AST_Directive(node.body);
}
function run_code(code) {
var result = sandbox.run_code(code, true);
return typeof result == "string" ? result.replace(/\u001b\[\d+m/g, "") : result;
}
// Try to reminify original input with standard options
// to see if it matches expect_stdout.
function reminify(orig_options, input_code, input_formatted, expect_stdout) {
for (var i = 0; i < minify_options.length; i++) {
var options = JSON.parse(minify_options[i]);
if (options.compress) [
"keep_fargs",
"keep_fnames",
].forEach(function(name) {
if (name in orig_options) {
options.compress[name] = orig_options[name];
}
});
var options_formatted = JSON.stringify(options, null, 4);
var result = U.minify(input_code, options);
if (result.error) {
log("!!! failed input reminify\n---INPUT---\n{input}\n---OPTIONS---\n{options}\n--ERROR---\n{error}\n\n", {
input: input_formatted,
options: options_formatted,
error: result.error,
});
return false;
} else { } else {
var stdout = run_code(result.code); directive = false;
if (typeof expect_stdout != "string" && typeof stdout != "string" && expect_stdout.name == stdout.name) {
stdout = expect_stdout;
}
if (!sandbox.same_stdout(expect_stdout, stdout)) {
log("!!! failed running reminified input\n---INPUT---\n{input}\n---OPTIONS---\n{options}\n---OUTPUT---\n{output}\n---EXPECTED {expected_type}---\n{expected}\n---ACTUAL {actual_type}---\n{actual}\n\n", {
input: input_formatted,
options: options_formatted,
output: result.code,
expected_type: typeof expect_stdout == "string" ? "STDOUT" : "ERROR",
expected: expect_stdout,
actual_type: typeof stdout == "string" ? "STDOUT" : "ERROR",
actual: stdout,
});
return false;
}
} }
} })));
return true; toplevel.figure_out_scope(mangle_options);
return toplevel;
} }

View File

@@ -1,21 +1,6 @@
var semver = require("semver"); var semver = require("semver");
var vm = require("vm"); var vm = require("vm");
function createContext() {
return vm.createContext(Object.defineProperty({}, "console", {
value: {
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 safe_log(arg, 3);
}));
}
}
}));
}
function safe_log(arg, level) { function safe_log(arg, level) {
if (arg) switch (typeof arg) { if (arg) switch (typeof arg) {
case "function": case "function":
@@ -25,21 +10,21 @@ function safe_log(arg, level) {
arg.constructor.toString(); arg.constructor.toString();
if (level--) for (var key in arg) { if (level--) for (var key in arg) {
var desc = Object.getOwnPropertyDescriptor(arg, key); var desc = Object.getOwnPropertyDescriptor(arg, key);
if (!desc || !desc.get) { if (!desc || !desc.get) arg[key] = safe_log(arg[key], level);
arg[key] = safe_log(arg[key], level);
}
} }
} }
return arg; return arg;
} }
function strip_func_ids(text) { function log(msg) {
return ("" + text).replace(/F[0-9]{6}N/g, "<F<>N>"); if (arguments.length == 1 && typeof msg == "string") return console.log("%s", msg);
return console.log.apply(console, [].map.call(arguments, function(arg) {
return safe_log(arg, 3);
}));
} }
var context; var func_toString = new vm.Script([
var FUNC_TOSTRING = [ "[ Array, Boolean, Error, Function, Number, Object, RegExp, String ].forEach(function(f) {",
"[ Array, Boolean, Error, Function, Number, Object, RegExp, String].forEach(function(f) {",
" f.toString = Function.prototype.toString;", " f.toString = Function.prototype.toString;",
"});", "});",
"Function.prototype.toString = function() {", "Function.prototype.toString = function() {",
@@ -59,7 +44,15 @@ var FUNC_TOSTRING = [
' return "function(){}";', ' return "function(){}";',
" };", " };",
"}();", "}();",
]).join("\n"); ]).join("\n"));
function createContext() {
var ctx = vm.createContext(Object.defineProperty({}, "console", { value: { log: log } }));
func_toString.runInContext(ctx);
return ctx;
}
var context;
exports.run_code = function(code, reuse) { exports.run_code = function(code, reuse) {
var stdout = ""; var stdout = "";
var original_write = process.stdout.write; var original_write = process.stdout.write;
@@ -69,7 +62,6 @@ exports.run_code = function(code, reuse) {
try { try {
if (!reuse || !context) context = createContext(); if (!reuse || !context) context = createContext();
vm.runInContext([ vm.runInContext([
FUNC_TOSTRING,
"!function() {", "!function() {",
code, code,
"}();", "}();",
@@ -79,13 +71,18 @@ exports.run_code = function(code, reuse) {
return ex; return ex;
} finally { } finally {
process.stdout.write = original_write; process.stdout.write = original_write;
if (!reuse || /prototype/.test(code)) { if (!reuse || code.indexOf(".prototype") >= 0) {
context = null; context = null;
} else for (var key in context) { } else for (var key in context) {
delete context[key]; delete context[key];
} }
} }
}; };
function strip_func_ids(text) {
return ("" + text).replace(/F[0-9]{6}N/g, "<F<>N>");
}
exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expected, actual) { exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expected, actual) {
if (typeof expected != typeof actual) return false; if (typeof expected != typeof actual) return false;
if (typeof expected != "string") { if (typeof expected != "string") {

View File

@@ -15,6 +15,7 @@ if (process.argv[2] == "run") {
var branch = process.argv[3] || "v" + require("../package.json").version; var branch = process.argv[3] || "v" + require("../package.json").version;
var repository = encodeURIComponent(process.argv[4] || "mishoo/UglifyJS2"); var repository = encodeURIComponent(process.argv[4] || "mishoo/UglifyJS2");
var concurrency = process.argv[5] || 1; var concurrency = process.argv[5] || 1;
var platform = process.argv[6] || "node/latest";
(function request() { (function request() {
setTimeout(request, (period + wait) / concurrency); setTimeout(request, (period + wait) / concurrency);
var options = url.parse("https://api.travis-ci.org/repo/" + repository + "/requests"); var options = url.parse("https://api.travis-ci.org/repo/" + repository + "/requests");
@@ -32,20 +33,18 @@ if (process.argv[2] == "run") {
res.on("data", console.log); res.on("data", console.log);
}).on("error", console.error).end(JSON.stringify({ }).on("error", console.error).end(JSON.stringify({
request: { request: {
message: "ufuzz testing (when idle)", message: "ufuzz testing",
branch: branch, branch: branch,
config: { config: {
merge_mode: "replace", cache: false,
language: "node_js", env: "NODEJS_VER=" + platform,
node_js: "9",
sudo: false,
script: "node test/travis-ufuzz run" script: "node test/travis-ufuzz run"
} }
} }
})); }));
})(); })();
} else { } else {
console.log("Usage: test/travis-ufuzz.js <token> [branch] [repository] [concurrency]"); console.log("Usage: test/travis-ufuzz.js <token> [branch] [repository] [concurrency] [platform]");
} }
function spawn(endTime) { function spawn(endTime) {

View File

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

View File

@@ -1,6 +1,6 @@
exports["Dictionary"] = Dictionary; exports["Dictionary"] = Dictionary;
exports["TreeWalker"] = TreeWalker;
exports["TreeTransformer"] = TreeTransformer;
exports["minify"] = minify; exports["minify"] = minify;
exports["parse"] = parse; exports["parse"] = parse;
exports["_push_uniq"] = push_uniq; exports["push_uniq"] = push_uniq;
exports["TreeTransformer"] = TreeTransformer;
exports["TreeWalker"] = TreeWalker;

View File

@@ -1,7 +1,6 @@
var fs = require("fs"); var fs = require("fs");
var UglifyJS = exports; exports.FILES = [
var FILES = UglifyJS.FILES = [
"../lib/utils.js", "../lib/utils.js",
"../lib/ast.js", "../lib/ast.js",
"../lib/parse.js", "../lib/parse.js",
@@ -19,15 +18,12 @@ var FILES = UglifyJS.FILES = [
}); });
new Function("MOZ_SourceMap", "exports", function() { new Function("MOZ_SourceMap", "exports", function() {
var code = FILES.map(function(file) { var code = exports.FILES.map(function(file) {
return fs.readFileSync(file, "utf8"); return fs.readFileSync(file, "utf8");
}); });
code.push("exports.describe_ast = " + describe_ast.toString()); code.push("exports.describe_ast = " + describe_ast.toString());
return code.join("\n\n"); return code.join("\n\n");
}())( }())(require("source-map"), exports);
require("source-map"),
UglifyJS
);
function describe_ast() { function describe_ast() {
var out = OutputStream({ beautify: true }); var out = OutputStream({ beautify: true });
@@ -65,11 +61,11 @@ function describe_ast() {
} }
function infer_options(options) { function infer_options(options) {
var result = UglifyJS.minify("", options); var result = exports.minify("", options);
return result.error && result.error.defs; return result.error && result.error.defs;
} }
UglifyJS.default_options = function() { exports.default_options = function() {
var defs = {}; var defs = {};
Object.keys(infer_options({ 0: 0 })).forEach(function(component) { Object.keys(infer_options({ 0: 0 })).forEach(function(component) {
var options = {}; var options = {};