Compare commits

...

60 Commits

Author SHA1 Message Date
Alex Lam S.L
20f9a1d908 v3.9.2 2020-05-03 11:01:18 +08:00
Alex Lam S.L
dcb74f558e fix diagnostic text (#3838) 2020-05-01 18:55:06 +08:00
Alex Lam S.L
0794aaa2c2 fix corner case in inline (#3837)
fixes #3836
2020-05-01 17:20:23 +08:00
Alex Lam S.L
74801de315 fix corner cases in inline (#3834)
fixes #3833
fixes #3835
2020-05-01 09:06:40 +08:00
Alex Lam S.L
f80d5b8c9e enhance inline (#3832) 2020-05-01 04:33:46 +08:00
Alex Lam S.L
d900006973 fix corner case in dead_code (#3831)
fixes #3830
2020-04-30 21:52:57 +08:00
Alex Lam S.L
39f849590b update dependencies (#3828)
- actions/checkout@v2
2020-04-30 05:55:04 +08:00
Alex Lam S.L
818738beec fix corner case in ie8 (#3826)
fixes #3825
2020-04-27 16:51:21 +08:00
Alex Lam S.L
bc2a4a3bb8 fix corner case in ie8 (#3824)
fixes #3823
2020-04-27 06:44:53 +08:00
Alex Lam S.L
a4a8ccea8c fix corner case in inline (#3822)
fixes #3821
2020-04-27 03:31:19 +08:00
Alex Lam S.L
36dcfa3e82 improve suspicious option detection (#3820) 2020-04-27 00:59:26 +08:00
Alex Lam S.L
94f33570e3 fix corner case in --reduce-test (#3819) 2020-04-25 06:49:50 +08:00
Alex Lam S.L
44d6912a55 improve --reduce-test on Error.message (#3816)
closes #3815
2020-04-25 01:30:37 +08:00
Alex Lam S.L
3a4497a1c3 fix corner case in typeofs (#3818)
fixes #3817
2020-04-25 01:29:42 +08:00
Alex Lam S.L
3ee13cae02 improve compress (#3814)
- avoid identifier overflow through consecutive API calls
- simplify `reduce_vars`
- enhance `unsafe` `evaluate`
2020-04-24 06:50:53 +08:00
Alex Lam S.L
99cf3a38c5 improve unused efficiency (#3813) 2020-04-23 08:31:35 +08:00
Alex Lam S.L
3ae24329eb gate various label-related transformations (#3812) 2020-04-23 05:27:26 +08:00
Alex Lam S.L
01b13d797c enhance dead_code (#3811) 2020-04-22 18:22:45 +08:00
Alex Lam S.L
306e8e9873 adjust ufuzz schedule (#3810) 2020-04-22 16:03:15 +08:00
Alex Lam S.L
9577c8c1b7 fix corner case in conditionals (#3809)
fixes #3808
2020-04-22 06:30:08 +08:00
Alex Lam S.L
925a0ca1a0 adjust ufuzz schedule (#3807) 2020-04-22 02:58:02 +08:00
Alex Lam S.L
b694bfa351 speed up ufuzz on GitHub Actions (#3806) 2020-04-21 22:51:42 +08:00
Alex Lam S.L
a2fc32c64b enhance conditionals (#3805) 2020-04-20 09:42:13 +08:00
Alex Lam S.L
88504ab869 enhance join_vars (#3804) 2020-04-20 06:37:46 +08:00
Alex Lam S.L
e38754e802 fix corner case in functions & unused (#3803)
fixes #3802
2020-04-19 06:28:01 +08:00
Alex Lam S.L
eb6f32bfc3 enhance collapse_vars (#3801) 2020-04-19 05:04:21 +08:00
Alex Lam S.L
f110601fb4 enhance unused (#3800) 2020-04-19 00:10:24 +08:00
Alex Lam S.L
2a508c6e5f enhance collapse_vars (#3799) 2020-04-18 23:12:20 +08:00
Alex Lam S.L
fd6144d95b enhance conditionals (#3798) 2020-04-18 22:32:22 +08:00
Alex Lam S.L
60d4e7b09f enhance unused (#3794) 2020-04-18 18:52:44 +08:00
Alex Lam S.L
b38838c6bf fix corner case in join_vars (#3796)
fixes #3795
2020-04-18 18:08:05 +08:00
Alex Lam S.L
708973e51d report top-level default options (#3797) 2020-04-18 18:03:06 +08:00
Alex Lam S.L
dac9e69f9e enhance collapse_vars (#3793) 2020-04-18 10:06:20 +08:00
Alex Lam S.L
39aa33749b expand ufuzz patterns (#3792) 2020-04-18 07:12:13 +08:00
Alex Lam S.L
da68ec6e19 fix corner cases in join_vars (#3790)
fixes #3789
fixes #3791
2020-04-18 02:53:26 +08:00
Alex Lam S.L
15a3ebd467 fix corner cases in join_vars (#3787)
fixes #3786
fixes #3788
2020-04-17 21:19:18 +08:00
Alex Lam S.L
9110fac9a2 suppress mutation of input options (#3785) 2020-04-17 15:13:49 +08:00
Alex Lam S.L
83f42ede36 support optional output of names in source maps (#3784) 2020-04-17 07:20:48 +08:00
Alex Lam S.L
0ce71bbec0 enhance join_vars (#3783) 2020-04-17 05:31:33 +08:00
Alex Lam S.L
46d142cbf6 improve source-map generation (#3782)
- emit singleton segments to mark generated code from input
2020-04-16 23:30:25 +08:00
Alex Lam S.L
38c3bcf9a0 v3.9.1 2020-04-15 17:26:30 +08:00
Alex Lam S.L
6e9afdc94f prevent input source map mutation (#3781)
fixes #3780
2020-04-15 17:25:58 +08:00
Alex Lam S.L
c4d28e3b2a expand testing on Node.js versions (#3779) 2020-04-14 10:13:42 +08:00
Alex Lam S.L
77261e1ee0 v3.9.0 2020-04-13 13:45:02 +01:00
Alex Lam S.L
903a5df9a5 fix corner case in inline (#3778)
fixes #3777
2020-04-11 19:54:26 +08:00
Alex Lam S.L
c810ecd081 improve handling of eval (#3776)
closes #3768
2020-04-11 06:36:17 +08:00
Alex Lam S.L
dce9dfce0e fix corner case in reduce_vars (#3775)
fixes #3774
2020-04-11 02:19:38 +08:00
Alex Lam S.L
3d72663689 add tests for eval() (#3769)
closes #3768
2020-04-11 00:36:53 +08:00
Alex Lam S.L
a2b16e89a4 fix corner cases in inline (#3773)
fixes #3770
fixes #3771
fixes #3772
2020-04-11 00:34:45 +08:00
Alex Lam S.L
b35f4c5a83 enhance inline (#3767) 2020-04-10 10:48:24 +08:00
Alex Lam S.L
41eb4f1725 workaround intermittent nodejs.org corruptions (#3766) 2020-04-07 08:40:38 +08:00
Alex Lam S.L
94bc221669 fix export of PATH to Node.js (#3765) 2020-04-07 01:14:16 +08:00
Alex Lam S.L
822d298a55 fix Github Actions retry logic (#3763) 2020-04-06 22:16:48 +08:00
Alex Lam S.L
273c6020ba expand ufuzz patterns (#3761) 2020-04-05 22:12:46 +08:00
Alex Lam S.L
1b07f64057 enhance inline (#3760) 2020-04-05 10:42:23 +08:00
Alex Lam S.L
80d9c44b22 improve resilience against nodejs.org failures (#3759) 2020-04-03 02:49:38 +08:00
Alex Lam S.L
dc0cd088cf fix corner case in evaluate & unsafe_math (#3756)
fixes #3755
2020-03-30 19:13:14 +08:00
Alex Lam S.L
c69c026728 improve resilience against nodejs.org failures (#3758) 2020-03-30 10:20:13 +08:00
Alex Lam S.L
b5f4e1187f handle single-field segments (#3757) 2020-03-30 06:39:32 +08:00
Alex Lam S.L
827bcec186 handle source-map operations internally (#3754) 2020-03-28 22:18:56 +08:00
55 changed files with 4197 additions and 1184 deletions

View File

@@ -4,16 +4,19 @@ jobs:
test:
strategy:
matrix:
node: [ "0.10", "0.12", 4, 6, 8, 10, latest ]
node: [ "0.8", "0.10", "0.12", "4", "6", "8", "10", "12", latest ]
os: [ ubuntu-latest, windows-latest ]
script: [ compress, mocha, release/benchmark, release/jetstream ]
exclude:
- node: "0.8"
script: release/jetstream
name: ${{ matrix.node }} ${{ matrix.os }} ${{ matrix.script }}
runs-on: ${{ matrix.os }}
env:
NODE: ${{ matrix.node }}
TYPE: ${{ matrix.script }}
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2
- uses: actions/cache@v1
with:
path: tmp
@@ -21,11 +24,20 @@ jobs:
- name: Perform tests
shell: bash
run: |
git clone --branch v1.5.3 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
git clone --branch v1.5.4 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
while ! timeout 60 bash -c '. ~/.nvs/nvs.sh add $NODE && nvs use $NODE'; do
cd ~/.nvs
git clean -xdf
cd -
done
. ~/.nvs/nvs.sh --version
nvs add $NODE
nvs use $NODE
node --version
npm --version --no-update-notifier
npm install --no-audit --no-optional --no-save --no-update-notifier
npm config set audit false
npm config set optional false
npm config set save false
npm config set strict-ssl false
npm config set update-notifier false
npm --version
while !(npm install); do echo "'npm install' failed - retrying..."; done
node test/$TYPE

View File

@@ -1,7 +1,7 @@
name: Fuzzing
on:
schedule:
- cron: "*/15 * * * *"
- cron: "*/8 * * * *"
jobs:
ufuzz:
strategy:
@@ -11,15 +11,24 @@ jobs:
name: ${{ matrix.os }}
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2
- name: Perform fuzzing
shell: bash
run: |
git clone --branch v1.5.3 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
git clone --branch v1.5.4 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
while ! timeout 60 bash -c '. ~/.nvs/nvs.sh add 10 && nvs use 10'; do
cd ~/.nvs
git clean -xdf
cd -
done
. ~/.nvs/nvs.sh --version
nvs add 10
nvs use 10
node --version
npm --version --no-update-notifier
npm install --no-audit --no-optional --no-save --no-update-notifier
npm config set audit false
npm config set optional false
npm config set save false
npm config set strict-ssl false
npm config set update-notifier false
npm --version
while !(npm install); do echo "'npm install' failed - retrying..."; done
node test/ufuzz/job 3600000

View File

@@ -126,6 +126,7 @@ a double dash to prevent input files being used as option arguments:
`includeSources` Pass this flag if you want to include
the content of source files in the
source map as sourcesContent property.
`names` Include symbol names in the source map.
`root` Path to the original source to be included in
the source map.
`url` If specified, path to the source map to append in
@@ -159,6 +160,9 @@ Additional options:
- `--source-map "root='<URL>'"` to pass the URL where the original files can be found.
- `--source-map "names=false"` to omit symbol names if you want to reduce size
of the source map file.
- `--source-map "url='<URL>'"` to specify the URL where the source map can be found.
Otherwise UglifyJS assumes HTTP `X-SourceMap` is being used and will omit the
`//# sourceMappingURL=` directive.
@@ -593,6 +597,9 @@ var result = UglifyJS.minify({"compiled.js": "compiled code"}, {
If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.url`.
If you wish to reduce file size of the source map, set option `sourceMap.names`
to be `false` and all symbol names will be omitted.
## Parse options
- `bare_returns` (default `false`) -- support top level `return` statements

View File

@@ -23,12 +23,29 @@ program.parse = undefined;
if (process.argv.indexOf("ast") >= 0) program.helpInformation = UglifyJS.describe_ast;
else if (process.argv.indexOf("options") >= 0) program.helpInformation = function() {
var text = [];
var toplevels = [];
var padding = "";
var options = UglifyJS.default_options();
for (var option in options) {
text.push("--" + (option == "output" ? "beautify" : option == "sourceMap" ? "source-map" : option) + " options:");
text.push(format_object(options[option]));
text.push("");
for (var name in options) {
var option = options[name];
if (option && typeof option == "object") {
text.push("--" + ({
output: "beautify",
sourceMap: "source-map",
}[name] || name) + " options:");
text.push(format_object(option));
text.push("");
} else {
if (padding.length < name.length) padding = Array(name.length + 1).join(" ");
toplevels.push([ {
keep_fnames: "keep-fnames",
nameCache: "name-cache",
}[name] || name, option ]);
}
}
toplevels.forEach(function(tokens) {
text.push("--" + tokens[0] + padding.slice(tokens[0].length - 2) + tokens[1]);
});
return text.join("\n");
};
program.option("-p, --parse <options>", "Specify parser options.", parse_js());
@@ -220,7 +237,10 @@ function run() {
// load on demand - assumes dev tree checked out
var reduce_test = require("../test/reduce");
var testcase = files[0] || files[Object.keys(files)[0]];
var result = reduce_test(testcase, options, {verbose: true});
var result = reduce_test(testcase, options, {
log: print_error,
verbose: true,
});
}
else {
var result = UglifyJS.minify(files, options);
@@ -337,7 +357,7 @@ function simple_glob(glob) {
.replace(/\?/g, "[^/\\\\]") + "$";
var mod = process.platform === "win32" ? "i" : "";
var rx = new RegExp(pattern, mod);
var results = entries.filter(function(name) {
var results = entries.sort().filter(function(name) {
return rx.test(name);
}).map(function(name) {
return path.join(dir, name);

File diff suppressed because it is too large Load Diff

View File

@@ -129,6 +129,7 @@ function minify(files, options) {
content: null,
filename: null,
includeSources: false,
names: true,
root: null,
url: null,
}, true);
@@ -138,7 +139,7 @@ function minify(files, options) {
warnings.push(warning);
}, options.warnings == "verbose");
if (timings) timings.parse = Date.now();
var source_maps, toplevel;
var toplevel;
if (files instanceof AST_Toplevel) {
toplevel = files;
} else {
@@ -151,19 +152,17 @@ function minify(files, options) {
if (typeof source_map_content == "string" && source_map_content != "inline") {
source_map_content = parse_source_map(source_map_content);
}
source_maps = source_map_content && Object.create(null);
if (source_map_content) options.sourceMap.orig = Object.create(null);
for (var name in files) if (HOP(files, name)) {
options.parse.filename = name;
options.parse.toplevel = toplevel = parse(files[name], options.parse);
if (source_maps) {
if (source_map_content == "inline") {
var inlined_content = read_source_map(name, toplevel);
if (inlined_content) {
source_maps[name] = parse_source_map(inlined_content);
}
} else {
source_maps[name] = source_map_content;
if (source_map_content == "inline") {
var inlined_content = read_source_map(name, toplevel);
if (inlined_content) {
options.sourceMap.orig[name] = parse_source_map(inlined_content);
}
} else if (source_map_content) {
options.sourceMap.orig[name] = source_map_content;
}
}
}
@@ -202,19 +201,13 @@ function minify(files, options) {
}
if (!HOP(options.output, "code") || options.output.code) {
if (options.sourceMap) {
options.output.source_map = SourceMap({
file: options.sourceMap.filename,
orig: source_maps,
root: options.sourceMap.root
});
options.output.source_map = SourceMap(options.sourceMap);
if (options.sourceMap.includeSources) {
if (files instanceof AST_Toplevel) {
throw new Error("original source content unavailable");
} else for (var name in files) if (HOP(files, name)) {
options.output.source_map.get().setSourceContent(name, files[name]);
options.output.source_map.setSourceContent(name, files[name]);
}
} else {
options.output.source_map.get()._sourcesContents = null;
}
}
delete options.output.ast;

View File

@@ -1470,7 +1470,6 @@ function OutputStream(options) {
AST_Node,
// since the label symbol will mark it
AST_LabeledStatement,
AST_Toplevel,
], noop);
// XXX: I'm not exactly sure if we need it for all of these nodes,
@@ -1482,7 +1481,6 @@ function OutputStream(options) {
AST_Constant,
AST_Debugger,
AST_Definitions,
AST_Directive,
AST_Finally,
AST_Jump,
AST_Lambda,

View File

@@ -43,23 +43,21 @@
"use strict";
function SymbolDef(scope, orig, init) {
function SymbolDef(id, scope, orig, init) {
this.eliminated = 0;
this.global = false;
this.id = id;
this.init = init;
this.lambda = orig instanceof AST_SymbolLambda;
this.mangled_name = null;
this.name = orig.name;
this.orig = [ orig ];
this.init = init;
this.eliminated = 0;
this.scope = scope;
this.references = [];
this.replaced = 0;
this.global = false;
this.mangled_name = null;
this.scope = scope;
this.undeclared = false;
this.id = SymbolDef.next_id++;
this.lambda = orig instanceof AST_SymbolLambda;
}
SymbolDef.next_id = 1;
SymbolDef.prototype = {
unmangleable: function(options) {
return this.global && !options.toplevel
@@ -151,6 +149,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
scope.def_variable(node).defun = defun;
}
});
self.next_def_id = 0;
self.walk(tw);
// pass 2: find back references and eval
@@ -162,17 +161,22 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
}
if (node instanceof AST_SymbolRef) {
var name = node.name;
if (name == "eval" && tw.parent() instanceof AST_Call) {
for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) {
s.uses_eval = true;
}
}
var sym = node.scope.find_variable(name);
if (!sym) {
sym = self.def_global(node);
} else if (sym.scope instanceof AST_Lambda && name == "arguments") {
sym.scope.uses_arguments = true;
}
if (name == "eval") {
var parent = tw.parent();
if (parent.TYPE == "Call" && parent.expression === node) {
for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) {
s.uses_eval = true;
}
} else if (sym.undeclared) {
self.uses_eval = true;
}
}
node.thedef = sym;
node.reference(options);
return true;
@@ -235,12 +239,18 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
}
});
AST_Scope.DEFMETHOD("make_def", function(orig, init) {
var top = this;
while (top.parent_scope) top = top.parent_scope;
return new SymbolDef(++top.next_def_id, this, orig, init);
});
AST_Toplevel.DEFMETHOD("def_global", function(node) {
var globals = this.globals, name = node.name;
if (globals.has(name)) {
return globals.get(name);
} else {
var g = new SymbolDef(this, node);
var g = this.make_def(node);
g.undeclared = true;
g.global = true;
globals.set(name, g);
@@ -305,7 +315,7 @@ AST_Scope.DEFMETHOD("def_variable", function(symbol, init) {
def.orig.push(symbol);
if (def.init instanceof AST_Function) def.init = init;
} else {
def = new SymbolDef(this, symbol, init);
def = this.make_def(symbol, init);
this.variables.set(symbol.name, def);
def.global = !this.parent_scope;
}

View File

@@ -43,62 +43,149 @@
"use strict";
// a small wrapper around fitzgen's source-map library
function SourceMap(options) {
options = defaults(options, {
file: null,
root: null,
orig: null,
orig_line_diff: 0,
dest_line_diff: 0,
}, true);
var generator = new MOZ_SourceMap.SourceMapGenerator({
file: options.file,
sourceRoot: options.root
});
var maps = options.orig && Object.create(null);
if (maps) for (var source in options.orig) {
var map = new MOZ_SourceMap.SourceMapConsumer(options.orig[source]);
if (Array.isArray(options.orig[source].sources)) {
map._sources.toArray().forEach(function(source) {
var sourceContent = map.sourceContentFor(source, true);
if (sourceContent) generator.setSourceContent(source, sourceContent);
});
var vlq_char = characters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
var vlq_bits = vlq_char.reduce(function(map, ch, bits) {
map[ch] = bits;
return map;
}, Object.create(null));
function vlq_decode(indices, str) {
var value = 0;
var shift = 0;
for (var i = 0, j = 0; i < str.length; i++) {
var bits = vlq_bits[str[i]];
value += (bits & 31) << shift;
if (bits & 32) {
shift += 5;
} else {
indices[j++] += value & 1 ? 0x80000000 | -(value >> 1) : value >> 1;
value = shift = 0;
}
maps[source] = map;
}
return {
add: function(source, gen_line, gen_col, orig_line, orig_col, name) {
var map = maps && maps[source];
if (map) {
var info = map.originalPositionFor({
line: orig_line,
column: orig_col
return j;
}
function vlq_encode(num) {
var result = "";
num = Math.abs(num) << 1 | num >>> 31;
do {
var bits = num & 31;
if (num >>>= 5) bits |= 32;
result += vlq_char[bits];
} while (num);
return result;
}
function create_array_map() {
var map = Object.create(null);
var array = [];
array.index = function(name) {
if (!HOP(map, name)) {
map[name] = array.length;
array.push(name);
}
return map[name];
};
return array;
}
function SourceMap(options) {
var sources = create_array_map();
var sources_content = options.includeSources && Object.create(null);
var names = create_array_map();
var mappings = "";
if (options.orig) Object.keys(options.orig).forEach(function(name) {
var map = options.orig[name];
var indices = [ 0, 0, 1, 0, 0 ];
options.orig[name] = {
names: map.names,
mappings: map.mappings.split(/;/).map(function(line) {
indices[0] = 0;
return line.split(/,/).map(function(segment) {
return indices.slice(0, vlq_decode(indices, segment));
});
if (info.source === null) return;
source = info.source;
orig_line = info.line;
orig_col = info.column;
name = info.name || name;
}
generator.addMapping({
name: name,
source: source,
generated: {
line: gen_line + options.dest_line_diff,
column: gen_col
},
original: {
line: orig_line + options.orig_line_diff,
column: orig_col
}),
sources: map.sources,
};
if (!sources_content || !map.sourcesContent) return;
for (var i = 0; i < map.sources.length; i++) {
var content = map.sourcesContent[i];
if (content) sources_content[map.sources[i]] = content;
}
});
var prev_source;
var generated_line = 1;
var generated_column = 0;
var source_index = 0;
var original_line = 1;
var original_column = 0;
var name_index = 0;
return {
add: options.orig ? function(source, gen_line, gen_col, orig_line, orig_col, name) {
var map = options.orig[source];
if (map) {
var segments = map.mappings[orig_line - 1];
if (!segments) return;
var indices;
for (var i = 0; i < segments.length; i++) {
var col = segments[i][0];
if (orig_col >= col) indices = segments[i];
if (orig_col <= col) break;
}
});
},
get: function() {
return generator;
},
if (!indices || indices.length < 4) {
source = null;
} else {
source = map.sources[indices[1]];
orig_line = indices[2];
orig_col = indices[3];
if (indices.length > 4) name = map.names[indices[4]];
}
}
add(source, gen_line, gen_col, orig_line, orig_col, name);
} : add,
setSourceContent: sources_content ? function(source, content) {
sources_content[source] = content;
} : noop,
toString: function() {
return JSON.stringify(generator.toJSON());
return JSON.stringify({
version: 3,
file: options.filename || undefined,
sourceRoot: options.root || undefined,
sources: sources,
sourcesContent: sources_content ? sources.map(function(source) {
return sources_content[source] || null;
}) : undefined,
names: names,
mappings: mappings,
});
}
};
function add(source, gen_line, gen_col, orig_line, orig_col, name) {
if (prev_source == null && source == null) return;
prev_source = source;
if (generated_line < gen_line) {
generated_column = 0;
do {
mappings += ";";
} while (++generated_line < gen_line);
} else if (mappings) {
mappings += ",";
}
mappings += vlq_encode(gen_col - generated_column);
generated_column = gen_col;
if (source == null) return;
var src_idx = sources.index(source);
mappings += vlq_encode(src_idx - source_index);
source_index = src_idx;
mappings += vlq_encode(orig_line - original_line);
original_line = orig_line;
mappings += vlq_encode(orig_col - original_column);
original_column = orig_col;
if (options.names && name != null) {
var name_idx = names.index(name);
mappings += vlq_encode(name_idx - name_index);
name_index = name_idx;
}
}
}

View File

@@ -87,15 +87,13 @@ DefaultsError.prototype.name = "DefaultsError";
configure_error_stack(DefaultsError);
function defaults(args, defs, croak) {
if (args === true) args = {};
var ret = args || {};
if (croak) for (var i in ret) if (HOP(ret, i) && !HOP(defs, i)) {
throw new DefaultsError("`" + i + "` is not a supported option", defs);
if (croak) for (var i in args) {
if (HOP(args, i) && !HOP(defs, i)) throw new DefaultsError("`" + i + "` is not a supported option", defs);
}
for (var i in defs) if (HOP(defs, i)) {
ret[i] = (args && HOP(args, i)) ? args[i] : defs[i];
for (var i in args) {
if (HOP(args, i)) defs[i] = args[i];
}
return ret;
return defs;
}
function merge(obj, ext) {
@@ -217,6 +215,12 @@ Dictionary.prototype = {
return this;
},
has: function(key) { return ("$" + key) in this._values },
all: function(predicate) {
for (var i in this._values)
if (!predicate(this._values[i], i.substr(1)))
return false;
return true;
},
each: function(f) {
for (var i in this._values)
f(this._values[i], i.substr(1));

View File

@@ -3,7 +3,7 @@
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause",
"version": "3.8.1",
"version": "3.9.2",
"engines": {
"node": ">=0.8.0"
},
@@ -23,8 +23,7 @@
"LICENSE"
],
"dependencies": {
"commander": "~2.20.3",
"source-map": "~0.6.1"
"commander": "~2.20.3"
},
"devDependencies": {
"acorn": "~7.1.0",

View File

@@ -5,12 +5,11 @@
var createHash = require("crypto").createHash;
var fetch = require("./fetch");
var fork = require("child_process").fork;
var spawn = require("child_process").spawn;
var zlib = require("zlib");
var args = process.argv.slice(2);
if (!args.length) {
args.push("-mc");
}
args.unshift("bin/uglifyjs");
if (!args.length) args.push("-mc");
args.push("--timings");
var urls = [
"https://code.jquery.com/jquery-3.4.1.js",
@@ -70,18 +69,20 @@ urls.forEach(function(url) {
};
fetch(url, function(err, res) {
if (err) throw err;
var uglifyjs = fork("bin/uglifyjs", args, { silent: true });
var uglifyjs = spawn(process.argv[0], args, { silent: true });
res.on("data", function(data) {
results[url].input += data.length;
}).pipe(uglifyjs.stdin);
var sha1 = createHash("sha1");
uglifyjs.stdout.on("data", function(data) {
results[url].output += data.length;
}).pipe(zlib.createGzip({
level: zlib.Z_BEST_COMPRESSION
})).on("data", function(data) {
results[url].gzip += data.length;
}).pipe(createHash("sha1")).on("data", function(data) {
results[url].sha1 = data.toString("hex");
sha1.update(data);
}).on("end", function() {
results[url].sha1 = sha1.digest("hex");
done();
});
uglifyjs.stderr.setEncoding("utf8");

View File

@@ -91,8 +91,7 @@ asm_mixed: {
function no_asm_GeometricMean(stdlib, foreign, buffer) {
function logSum(start, end) {
start |= 0, end |= 0;
var sum = 0, p = 0, q = 0;
for (p = start << 3, q = end << 3; (0 | p) < (0 | q); p = p + 8 | 0) sum += +log(values[p >> 3]);
for (var sum = 0, p = 0, q = 0, p = start << 3, q = end << 3; (0 | p) < (0 | q); p = p + 8 | 0) sum += +log(values[p >> 3]);
return +sum;
}
function geometricMean(start, end) {

View File

@@ -803,8 +803,7 @@ collapse_vars_assignment: {
expect: {
function log(x) { return console.log(x), x; }
function f0(c) {
var a = 3 / c;
return a = a;
return 3 / c;
}
function f1(c) {
return 1 - 3 / c;
@@ -2012,6 +2011,7 @@ issue_1631_3: {
join_vars: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
function g() {
@@ -2031,8 +2031,8 @@ issue_1631_3: {
function f() {
return a = 2, 4;
}
var a = 0, b = 1, t = f();
return b = a + t;
var a = 0, t = f();
return a + t;
}
console.log(g());
}
@@ -2204,8 +2204,8 @@ var_defs: {
}
expect: {
var f1 = function(x, y) {
var r = x + y, a = r * r - r, b = 7;
console.log(a + b);
var r = x + y, z = r * r - r, b = 7;
console.log(z + b);
};
f1("1", 0);
}
@@ -2569,8 +2569,7 @@ chained_3: {
}
expect: {
console.log(function(a, b) {
var c = 1;
c = b;
var c = 1, c = b;
b++;
return c;
}(0, 2));
@@ -2665,8 +2664,8 @@ double_def_1: {
a();
}
expect: {
var a;
(a = (a = x) && y)();
var a = x;
(a = a && y)();
}
}
@@ -2699,8 +2698,8 @@ toplevel_single_reference: {
}
expect: {
for (var b in x) {
var a;
b(a = b);
var a = b;
b(b);
}
}
}
@@ -4243,8 +4242,7 @@ issue_2497: {
if (true)
for (var i = 0; i < 1; ++i)
for (var k = 0; k < 1; ++k) {
value = 1;
value = value ? value + 1 : 0;
value = (value = 1) ? value + 1 : 0;
}
else
for (i = 0; i < 1; ++i)
@@ -7806,3 +7804,153 @@ issue_3744: {
}
expect_stdout: "PASS"
}
assign_value_def: {
options = {
collapse_vars: true,
unused: true,
}
input: {
function f(a) {
while (1) {
var b = a[0], c = a[1];
d = b;
e = c;
if (c[0] - e[0] > c[1] - d[1]) break;
return "PASS";
}
var d, e;
return "FAIL";
}
console.log(f([
[ 1, 2 ],
[ 3, 4 ],
]));
}
expect: {
function f(a) {
while (1) {
var b = a[0], c = a[1];
if (c[0] - c[0] > c[1] - b[1]) break;
return "PASS";
}
return "FAIL";
}
console.log(f([
[ 1, 2 ],
[ 3, 4 ],
]));
}
expect_stdout: "PASS"
}
join_vars_value_def: {
options = {
collapse_vars: true,
join_vars: true,
unused: true,
}
input: {
function f(a) {
while (1) {
var b = a[0], c = a[1];
d = b;
e = c;
if (c[0] - e[0] > c[1] - d[1]) break;
return "PASS";
}
var d, e;
return "FAIL";
}
console.log(f([
[ 1, 2 ],
[ 3, 4 ],
]));
}
expect: {
function f(a) {
while (1) {
var b = a[0], c = a[1];
if (c[0] - c[0] > c[1] - b[1]) break;
return "PASS";
}
return "FAIL";
}
console.log(f([
[ 1, 2 ],
[ 3, 4 ],
]));
}
expect_stdout: "PASS"
}
var_value_def: {
options = {
collapse_vars: true,
unused: true,
}
input: {
function f(a) {
while (1) {
var b = a[0], c = a[1], d = b, e = c;
if (c[0] - e[0] > c[1] - d[1]) break;
return "PASS";
}
var d, e;
return "FAIL";
}
console.log(f([
[ 1, 2 ],
[ 3, 4 ],
]));
}
expect: {
function f(a) {
while (1) {
var b = a[0], c = a[1];
if (c[0] - c[0] > c[1] - b[1]) break;
return "PASS";
}
return "FAIL";
}
console.log(f([
[ 1, 2 ],
[ 3, 4 ],
]));
}
expect_stdout: "PASS"
}
mangleable_var: {
options = {
collapse_vars: true,
unused: true,
}
input: {
function f(a) {
var b = a(), c = a(), d = b;
return c.p(c, d);
}
console.log(f(function() {
return {
p: function() {
return "PASS"
},
};
}));
}
expect: {
function f(a) {
var b = a(), c = a();
return c.p(c, b);
}
console.log(f(function() {
return {
p: function() {
return "PASS";
}
};
}));
}
expect_stdout: "PASS"
}

View File

@@ -1384,7 +1384,7 @@ hoist_decl: {
}
expect: {
var a, b;
x() ? y() : z();
(x() ? y : z)();
}
}
@@ -1666,3 +1666,130 @@ issue_3668: {
}
expect_stdout: "undefined"
}
conditional_assignments_1: {
options = {
conditionals: true,
sequences: true,
}
input: {
function f(a, b, c, d) {
a = b;
if (c) a = d;
return a;
}
function g(a, b, c, d) {
a = b;
if (c); else a = d;
return a;
}
console.log(f(0, "FAIL", 1, "PASS"), g(0, "PASS", 1, "FAIL"));
}
expect: {
function f(a, b, c, d) {
return a = c ? d : b, a;
}
function g(a, b, c, d) {
return a = c ? b : d, a;
}
console.log(f(0, "FAIL", 1, "PASS"), g(0, "PASS", 1, "FAIL"));
}
expect_stdout: "PASS PASS"
}
conditional_assignments_2: {
options = {
conditionals: true,
sequences: true,
}
input: {
function f1(b, c, d) {
a = b;
if (c) a = d;
return a;
}
function f2(a, c, d) {
a = b;
if (c) a = d;
return a;
}
function f3(a, b, d) {
a = b;
if (c) a = d;
return a;
}
function f4(a, b, c) {
a = b;
if (c) a = d;
return a;
}
}
expect: {
function f1(b, c, d) {
return a = c ? d : b, a;
}
function f2(a, c, d) {
return a = b, c && (a = d), a;
}
function f3(a, b, d) {
return a = b, c && (a = d), a;
}
function f4(a, b, c) {
return a = b, c && (a = d), a;
}
}
}
conditional_assignments_3: {
options = {
conditionals: true,
sequences: true,
}
input: {
console.log(function(a, b) {
a = "PASS";
if (b) a = a;
return a;
}(0, 1));
}
expect: {
console.log(function(a, b) {
return a = "PASS", b && (a = a), a;
}(0, 1));
}
expect_stdout: "PASS"
}
issue_3808_1: {
options = {
conditionals: true,
side_effects: true,
}
input: {
var a;
a = "PASS", [] + "" && (a = "FAIL");
console.log(a);
}
expect: {
var a;
a = [] + "" ? "FAIL" : "PASS";
console.log(a);
}
expect_stdout: "PASS"
}
issue_3808_2: {
options = {
conditionals: true,
side_effects: true,
}
input: {
var a;
console.log((a = "PASS", [] + "" && (a = "FAIL")), a);
}
expect: {
var a;
console.log((a = "PASS", [] + "" && (a = "FAIL")), a);
}
expect_stdout: " PASS"
}

View File

@@ -97,6 +97,66 @@ dead_code_constant_boolean_should_warn_more: {
node_version: "<=4"
}
trim_try: {
options = {
dead_code: true,
}
input: {
try {
var a;
} catch (e) {
console.log("FAIL");
} finally {
console.log(a);
}
}
expect: {
var a;
console.log(a);
}
expect_stdout: "undefined"
}
trim_finally_1: {
options = {
dead_code: true,
}
input: {
try {
console.log("PASS");
} finally {
var a;
}
}
expect: {
console.log("PASS");
var a;
}
expect_stdout: "PASS"
}
trim_finally_2: {
options = {
dead_code: true,
}
input: {
try {
console.log("PASS");
} catch (e) {
} finally {
var a;
}
}
expect: {
try {
console.log("PASS");
var a;
} catch (e) {
}
}
expect_stdout: "PASS"
}
try_catch_finally: {
options = {
conditionals: true,
@@ -130,10 +190,7 @@ try_catch_finally: {
a = 3;
console.log("PASS");
}();
try {
console.log(a);
} finally {
}
console.log(a);
}
expect_stdout: [
"PASS",
@@ -892,3 +949,205 @@ issue_3578: {
}
expect_stdout: "PASS"
}
issue_3830_1: {
options = {
dead_code: true,
}
input: {
var o = {
set p(v) {
o = o.p = o = v;
}
};
o.p = "PASS";
console.log(o);
}
expect: {
var o = {
set p(v) {
o = o.p = o = v;
}
};
o.p = "PASS";
console.log(o);
}
expect_stdout: "PASS"
}
issue_3830_2: {
options = {
dead_code: true,
}
input: {
var a = "FAIL";
var o = {
set FAIL(v) {
a = o[a] = a = v;
}
};
o[a] = "PASS";
console.log(a);
}
expect: {
var a = "FAIL";
var o = {
set FAIL(v) {
a = o[a] = a = v;
}
};
o[a] = "PASS";
console.log(a);
}
expect_stdout: "PASS"
}
issue_3830_3: {
options = {
dead_code: true,
}
input: {
function f() {
return a;
}
var a = "FAIL";
var o = {
set FAIL(v) {
a = o[f()] = a = v;
}
};
o[f()] = "PASS";
console.log(a);
}
expect: {
function f() {
return a;
}
var a = "FAIL";
var o = {
set FAIL(v) {
a = o[f()] = a = v;
}
};
o[f()] = "PASS";
console.log(a);
}
expect_stdout: "PASS"
}
issue_3830_4: {
options = {
dead_code: true,
}
input: {
function f() {
return o;
}
var a = "FAIL";
var o = {
set FAIL(v) {
a = f()[a] = a = v;
}
};
f()[a] = "PASS";
console.log(a);
}
expect: {
function f() {
return o;
}
var a = "FAIL";
var o = {
set FAIL(v) {
a = f()[a] = a = v;
}
};
f()[a] = "PASS";
console.log(a);
}
expect_stdout: "PASS"
}
issue_3830_5: {
options = {
dead_code: true,
}
input: {
function f() {
return o;
}
function g() {
return a;
}
var a = "FAIL";
var o = {
set FAIL(v) {
a = f()[g()] = a = v;
}
};
f()[g()] = "PASS";
console.log(a);
}
expect: {
function f() {
return o;
}
function g() {
return a;
}
var a = "FAIL";
var o = {
set FAIL(v) {
a = f()[g()] = a = v;
}
};
f()[g()] = "PASS";
console.log(a);
}
expect_stdout: "PASS"
}
issue_3830_6: {
options = {
dead_code: true,
}
input: {
function f() {
return o;
}
function g() {
return a;
}
function h(v) {
a = f()[g()] = a = v;
}
var a = "FAIL";
var o = {
set FAIL(v) {
h(v);
}
};
o.FAIL = "PASS";
console.log(a);
}
expect: {
function f() {
return o;
}
function g() {
return a;
}
function h(v) {
a = f()[g()] = a = v;
}
var a = "FAIL";
var o = {
set FAIL(v) {
h(v);
}
};
o.FAIL = "PASS";
console.log(a);
}
expect_stdout: "PASS"
}

View File

@@ -46,7 +46,7 @@ simple_statement_is_not_a_directive: {
drop_lone_use_strict: {
options = {
directives: true,
side_effects: true,
unused: true,
}
input: {
function f1() {
@@ -66,10 +66,8 @@ drop_lone_use_strict: {
function f1() {
}
function f2() {
"use strict";
function f3() {
}
}
(function() {})();
}
}

View File

@@ -2444,3 +2444,69 @@ issue_3746: {
}
expect_stdout: "PASS"
}
drop_duplicated_side_effects: {
options = {
toplevel: true,
unused: true,
}
input: {
var a = 0;
for (var i = 1; i--;)
var a = 0, b = ++a;
console.log(a);
}
expect: {
var a = 0;
for (var i = 1; i--;)
a = 0, ++a;
console.log(a);
}
expect_stdout: "1"
}
drop_duplicated_var_catch: {
options = {
unused: true,
}
input: {
function f() {
try {
x();
} catch (a) {
var a, a;
}
}
}
expect: {
function f() {
try {
x();
} catch (a) {
var a;
}
}
}
}
issue_3802: {
options = {
functions: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = 0;
a += 0;
var a = function() {};
console.log(typeof a);
}
expect: {
var a = 0;
a += 0;
a = function() {};
console.log(typeof a);
}
expect_stdout: "function"
}

View File

@@ -2174,3 +2174,19 @@ issue_3738: {
}
expect_stdout: "Infinity"
}
issue_3755: {
options = {
booleans: true,
evaluate: true,
unsafe: true,
unsafe_math: true,
}
input: {
console.log((/4/.exec(1 + (!0 - 5 / "23")) || 0).p);
}
expect: {
console.log((/4/.exec(!0 - 5 / "23" + 1), 0).p);
}
expect_stdout: "undefined"
}

File diff suppressed because it is too large Load Diff

View File

@@ -767,18 +767,17 @@ issue_3071_1: {
var obj = {};
obj.one = 1;
obj.two = 2;
console.log(obj.one);
console.log(obj.one, obj.two);
})();
}
expect: {
console.log(1);
console.log(1, 2);
}
expect_stdout: "1"
expect_stdout: "1 2"
}
issue_3071_2: {
options = {
evaluate: true,
hoist_props: true,
inline: true,
join_vars: true,
@@ -793,19 +792,18 @@ issue_3071_2: {
obj = {};
obj.one = 1;
obj.two = 2;
console.log(obj.one);
console.log(obj.one, obj.two);
var obj;
})();
}
expect: {
console.log(1);
console.log(1, 2);
}
expect_stdout: "1"
expect_stdout: "1 2"
}
issue_3071_2_toplevel: {
options = {
evaluate: true,
hoist_props: true,
inline: true,
join_vars: true,
@@ -821,14 +819,14 @@ issue_3071_2_toplevel: {
obj = {};
obj.one = 1;
obj.two = 2;
console.log(obj.one);
console.log(obj.one, obj.two);
var obj;
})();
}
expect: {
console.log(1);
console.log(1, 2);
}
expect_stdout: "1"
expect_stdout: "1 2"
}
issue_3071_3: {

View File

@@ -2420,3 +2420,43 @@ issue_3750: {
}
expect_stdout: "PASS"
}
issue_3823: {
options = {
ie8: true,
toplevel: true,
unused: true,
}
input: {
for (var i = 0; i < 1; i++) {
var a = a ? function f() {
f;
} : 0;
console.log("PASS", typeof f);
}
}
expect: {
for (var i = 0; i < 1; i++) {
(function f() {
f;
});
console.log("PASS", typeof f);
}
}
expect_stdout: "PASS undefined"
}
issue_3825: {
options = {
ie8: true,
pure_getters: "strict",
side_effects: true,
}
input: {
console.log({}[void (0..length ? 1 : 2)]);
}
expect: {
console.log({}[void 0]);
}
expect_stdout: "undefined"
}

View File

@@ -90,13 +90,13 @@ non_hoisted_function_after_return_2a: {
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:7,16]",
"WARN: Dropping unused variable a [test/compress/issue-1034.js:4,20]",
"WARN: Dropping unused function nope [test/compress/issue-1034.js:11,21]",
"INFO: pass 0: last_count: Infinity, count: 37",
"INFO: pass 0: last_count: Infinity, count: 36",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:9,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:9,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:12,12]",
"INFO: Dropping unused variable b [test/compress/issue-1034.js:7,20]",
"INFO: Dropping unused variable c [test/compress/issue-1034.js:9,16]",
"INFO: pass 1: last_count: 37, count: 18",
"INFO: pass 1: last_count: 36, count: 18",
]
}
@@ -248,13 +248,13 @@ non_hoisted_function_after_return_2a_strict: {
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:8,16]",
"WARN: Dropping unused variable a [test/compress/issue-1034.js:5,20]",
"WARN: Dropping unused function nope [test/compress/issue-1034.js:12,21]",
"INFO: pass 0: last_count: Infinity, count: 48",
"INFO: pass 0: last_count: Infinity, count: 47",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:10,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:10,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:13,12]",
"INFO: Dropping unused variable b [test/compress/issue-1034.js:8,20]",
"INFO: Dropping unused variable c [test/compress/issue-1034.js:10,16]",
"INFO: pass 1: last_count: 48, count: 29",
"INFO: pass 1: last_count: 47, count: 29",
]
}

View File

@@ -22,8 +22,9 @@ issue_1639_1: {
console.log(a, b);
}
expect: {
for (var a = 100, b = 10, L1 = 5; --L1 > 0;)
if (--b, 0) var ignore = 0;
for (var a = 100, b = 10, L1 = 5, ignore; --L1 > 0;) {
--b;
}
console.log(a, b);
}
expect_stdout: "100 6"

View File

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

128
test/compress/issue-3768.js Normal file
View File

@@ -0,0 +1,128 @@
mangle: {
mangle = {
toplevel: true,
}
input: {
var e = eval, x = 42;
(function() {
console.log(e("typeof x"));
})();
}
expect: {
var e = eval, x = 42;
(function() {
console.log(e("typeof x"));
})();
}
expect_stdout: true
}
compress: {
options = {
collapse_vars: true,
inline: true,
unused: true,
}
input: {
console.log(function() {
var a = 42;
return eval("typeof a");
}(), function(e) {
var a = null;
return e("typeof a");
}(eval), function(eval) {
var a = false;
return eval("typeof a");
}(eval), function(f) {
var a = "STRING";
var eval = f;
return eval("typeof a");
}(eval), function(g) {
var a = eval;
function eval() {
return g;
}
return eval()("typeof a");
}(eval));
}
expect: {
console.log(function() {
var a = 42;
return eval("typeof a");
}(), (0, eval)("typeof a"), function(eval) {
var a = false;
return eval("typeof a");
}(eval), function(f) {
var a = "STRING";
var eval = f;
return eval("typeof a");
}(eval), function(g) {
var a = eval;
function eval() {
return g;
}
return eval()("typeof a");
}(eval));
}
expect_stdout: "number undefined boolean string undefined"
}
call_arg_1: {
mangle = {
toplevel: true,
}
input: {
var z = "foo";
(function() {
var z = false;
(function(e) {
var z = 42;
e("console.log(typeof z)");
})(eval);
})();
}
expect: {
var z = "foo";
(function() {
var o = false;
(function(o) {
var a = 42;
o("console.log(typeof z)");
})(eval);
})();
}
expect_stdout: true
}
call_arg_2: {
mangle = {
toplevel: true,
}
input: {
function eval() {
console.log("PASS");
}
var z = "foo";
(function() {
var z = false;
(function(e) {
var z = 42;
e("console.log(typeof z)");
})(eval);
})();
}
expect: {
function n() {
console.log("PASS");
}
var o = "foo";
(function() {
var o = false;
(function(o) {
var n = 42;
o("console.log(typeof z)");
})(n);
})();
}
expect_stdout: "PASS"
}

View File

@@ -8,7 +8,7 @@ remove_sequence: {
(0, 1, _decorators.logThis)();
}
expect: {
eval();
(0, eval)();
logThis();
(0, _decorators.logThis)();
}

View File

@@ -53,20 +53,23 @@ this_binding_conditionals: {
this_binding_collapse_vars: {
options = {
collapse_vars: true,
toplevel: true,
unused: true,
}
input: {
"use strict";
var c = a; c();
var d = a.b; d();
var e = eval; e();
function f() {
"use strict";
var c = a; c();
var d = a.b; d();
var e = eval; e();
}
}
expect: {
"use strict";
a();
(0, a.b)();
(0, eval)();
function f() {
"use strict";
a();
(0, a.b)();
(0, eval)();
}
}
}
@@ -97,7 +100,7 @@ this_binding_side_effects: {
(function(foo) {
foo();
(0, foo.bar)();
eval("console.log(foo);");
(0, eval)("console.log(foo);");
}());
(function(foo) {
"use strict";
@@ -144,7 +147,7 @@ this_binding_sequences: {
return eval("this");
}()),
console.log(typeof function() {
return eval("this");
return (0, eval)("this");
}()),
console.log(typeof function() {
"use strict";

991
test/compress/join_vars.js Normal file
View File

@@ -0,0 +1,991 @@
join_vars_assign: {
options = {
join_vars: true,
unused: true,
}
input: {
var y, x;
x = Object("PAS");
y = Object("S");
console.log(x + y);
}
expect: {
var x = Object("PAS"), y = Object("S");
console.log(x + y);
}
expect_stdout: "PASS"
}
join_object_assignments_1: {
options = {
evaluate: true,
join_vars: true,
}
input: {
console.log(function() {
var x = {
a: 1,
c: (console.log("c"), "C"),
};
x.b = 2;
x[3] = function() {
console.log(x);
},
x["a"] = /foo/,
x.bar = x;
return x;
}());
}
expect: {
console.log(function() {
var x = {
a: 1,
c: (console.log("c"), "C"),
b: 2,
3: function() {
console.log(x);
},
a: /foo/,
};
x.bar = x;
return x;
}());
}
expect_stdout: true
}
join_object_assignments_2: {
options = {
evaluate: true,
hoist_props: true,
join_vars: true,
passes: 3,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
foo: 1,
};
o.bar = 2;
o.baz = 3;
console.log(o.foo, o.bar + o.bar, o.foo * o.bar * o.baz);
}
expect: {
console.log(1, 4, 6);
}
expect_stdout: "1 4 6"
}
join_object_assignments_3: {
options = {
evaluate: true,
join_vars: true,
}
input: {
console.log(function() {
var o = {
a: "PASS",
}, a = o.a;
o.a = "FAIL";
return a;
}());
}
expect: {
console.log(function() {
var o = {
a: "PASS",
}, a = o.a;
o.a = "FAIL";
return a;
}());
}
expect_stdout: "PASS"
}
join_object_assignments_4: {
options = {
join_vars: true,
sequences: true,
}
input: {
var o;
console.log(o);
o = {};
o.a = "foo";
console.log(o.b);
o.b = "bar";
console.log(o.a);
}
expect: {
var o;
console.log(o),
o = {
a: "foo",
},
console.log(o.b),
o.b = "bar",
console.log(o.a);
}
expect_stdout: [
"undefined",
"undefined",
"foo",
]
}
join_object_assignments_return_1: {
options = {
join_vars: true,
}
input: {
console.log(function() {
var o = {
p: 3
};
return o.q = "foo";
}());
}
expect: {
console.log(function() {
var o = {
p: 3,
q: "foo"
};
return o.q;
}());
}
expect_stdout: "foo"
}
join_object_assignments_return_2: {
options = {
join_vars: true,
}
input: {
console.log(function() {
var o = {
p: 3
};
return o.q = /foo/,
o.r = "bar";
}());
}
expect: {
console.log(function() {
var o = {
p: 3,
q: /foo/,
r: "bar"
};
return o.r;
}());
}
expect_stdout: "bar"
}
join_object_assignments_return_3: {
options = {
join_vars: true,
}
input: {
console.log(function() {
var o = {
p: 3
};
return o.q = "foo",
o.p += "",
console.log(o.q),
o.p;
}());
}
expect: {
console.log(function() {
var o = {
p: 3,
q: "foo"
};
return o.p += "",
console.log(o.q),
o.p;
}());
}
expect_stdout: [
"foo",
"3",
]
}
join_object_assignments_for: {
options = {
join_vars: true,
}
input: {
console.log(function() {
var o = {
p: 3
};
for (o.q = "foo"; console.log(o.q););
return o.p;
}());
}
expect: {
console.log(function() {
for (var o = {
p: 3,
q: "foo"
}; console.log(o.q););
return o.p;
}());
}
expect_stdout: [
"foo",
"3",
]
}
join_object_assignments_if: {
options = {
join_vars: true,
}
input: {
console.log(function() {
var o = {};
if (o.a = "PASS") return o.a;
}())
}
expect: {
console.log(function() {
var o = { a: "PASS" };
if (o.a) return o.a;
}());
}
expect_stdout: "PASS"
}
join_object_assignments_forin: {
options = {
join_vars: true,
}
input: {
console.log(function() {
var o = {};
for (var a in o.a = "PASS", o)
return o[a];
}())
}
expect: {
console.log(function() {
var o = { a: "PASS" };
for (var a in o)
return o[a];
}());
}
expect_stdout: "PASS"
}
join_object_assignments_negative: {
options = {
evaluate: true,
join_vars: true,
properties: true,
}
input: {
var o = {};
o[0] = 0;
o[-0] = 1;
o[-1] = 2;
console.log(o[0], o[-0], o[-1]);
}
expect: {
var o = {
0: 0,
0: 1,
"-1": 2
};
console.log(o[0], o[-0], o[-1]);
}
expect_stdout: "1 1 2"
}
join_object_assignments_NaN_1: {
options = {
join_vars: true,
}
input: {
var o = {};
o[NaN] = 1;
o[0/0] = 2;
console.log(o[NaN], o[NaN]);
}
expect: {
var o = {};
o[NaN] = 1;
o[0/0] = 2;
console.log(o[NaN], o[NaN]);
}
expect_stdout: "2 2"
}
join_object_assignments_NaN_2: {
options = {
evaluate: true,
join_vars: true,
properties: true,
}
input: {
var o = {};
o[NaN] = 1;
o[0/0] = 2;
console.log(o[NaN], o[NaN]);
}
expect: {
var o = {
NaN: 1,
NaN: 2
};
console.log(o.NaN, o.NaN);
}
expect_stdout: "2 2"
}
join_object_assignments_null_0: {
options = {
join_vars: true,
}
input: {
var o = {};
o[null] = 1;
console.log(o[null]);
}
expect: {
var o = {};
o[null] = 1;
console.log(o[null]);
}
expect_stdout: "1"
}
join_object_assignments_null_1: {
options = {
evaluate: true,
join_vars: true,
properties: true,
}
input: {
var o = {};
o[null] = 1;
console.log(o[null]);
}
expect: {
var o = {
null: 1
};
console.log(o.null);
}
expect_stdout: "1"
}
join_object_assignments_void_0: {
options = {
evaluate: true,
join_vars: true,
}
input: {
var o = {};
o[void 0] = 1;
console.log(o[void 0]);
}
expect: {
var o = {
undefined: 1
};
console.log(o[void 0]);
}
expect_stdout: "1"
}
join_object_assignments_undefined_1: {
options = {
join_vars: true,
}
input: {
var o = {};
o[undefined] = 1;
console.log(o[undefined]);
}
expect: {
var o = {};
o[void 0] = 1;
console.log(o[void 0]);
}
expect_stdout: "1"
}
join_object_assignments_undefined_2: {
options = {
evaluate: true,
join_vars: true,
properties: true,
}
input: {
var o = {};
o[undefined] = 1;
console.log(o[undefined]);
}
expect: {
var o = {
undefined : 1
};
console.log(o[void 0]);
}
expect_stdout: "1"
}
join_object_assignments_Infinity: {
options = {
evaluate: true,
join_vars: true,
properties: true,
}
input: {
var o = {};
o[Infinity] = 1;
o[1/0] = 2;
o[-Infinity] = 3;
o[-1/0] = 4;
console.log(o[Infinity], o[1/0], o[-Infinity], o[-1/0]);
}
expect: {
var o = {
Infinity: 1,
Infinity: 2,
"-Infinity": 3,
"-Infinity": 4
};
console.log(o[1/0], o[1/0], o[-1/0], o[-1/0]);
}
expect_stdout: "2 2 4 4"
}
join_object_assignments_regex: {
options = {
evaluate: true,
join_vars: true,
properties: true,
}
input: {
var o = {};
o[/rx/] = 1;
console.log(o[/rx/]);
}
expect: {
var o = {
"/rx/": 1
};
console.log(o[/rx/]);
}
expect_stdout: "1"
}
issue_2816: {
options = {
join_vars: true,
}
input: {
"use strict";
var o = {
a: 1
};
o.b = 2;
o.a = 3;
o.c = 4;
console.log(o.a, o.b, o.c);
}
expect: {
"use strict";
var o = {
a: 1,
b: 2
};
o.a = 3;
o.c = 4;
console.log(o.a, o.b, o.c);
}
expect_stdout: "3 2 4"
}
issue_2893_1: {
options = {
join_vars: true,
}
input: {
var o = {
get a() {
return "PASS";
},
};
o.a = "FAIL";
console.log(o.a);
}
expect: {
var o = {
get a() {
return "PASS";
},
};
o.a = "FAIL";
console.log(o.a);
}
expect_stdout: "PASS"
}
issue_2893_2: {
options = {
join_vars: true,
}
input: {
var o = {
set a(v) {
this.b = v;
},
b: "FAIL",
};
o.a = "PASS";
console.log(o.b);
}
expect: {
var o = {
set a(v) {
this.b = v;
},
b: "FAIL",
};
o.a = "PASS";
console.log(o.b);
}
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, a = { b: 0 };
switch (a.b) {
case 0:
c = "PASS";
}
})();
console.log(c);
}
expect_stdout: "PASS"
}
issue_3786: {
options = {
join_vars: true,
}
input: {
try {
var a = b;
b = 0;
console.log("FAIL");
} catch (e) {
console.log("PASS");
}
}
expect: {
try {
var a = b;
b = 0;
console.log("FAIL");
} catch (e) {
console.log("PASS");
}
}
expect_stdout: "PASS"
}
issue_3788: {
options = {
inline: true,
join_vars: true,
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var a = "FAIL";
function f() {
function g() {
function h() {
a = 42;
a = "PASS";
return "PASS";
}
var b = h();
console.log(b);
}
g();
}
f();
console.log(a);
}
expect: {
var b, a = "FAIL";
a = 42,
a = "PASS",
b = "PASS",
console.log(b),
console.log(a);
}
expect_stdout: [
"PASS",
"PASS",
]
}
issue_3789_1: {
options = {
join_vars: true,
}
input: {
try {
c;
console.log("FAIL");
} catch (e) {
console.log("PASS");
}
try {} catch (c) {
var a;
c = 0;
}
}
expect: {
try {
c;
console.log("FAIL");
} catch (e) {
console.log("PASS");
}
try {} catch (c) {
var a;
c = 0;
}
}
expect_stdout: "PASS"
}
issue_3789_2: {
options = {
join_vars: true,
}
input: {
try {
c;
console.log("FAIL");
} catch (e) {
console.log("PASS");
}
try {} catch (c) {
try {} catch (c) {
var a;
c = 0;
}
}
}
expect: {
try {
c;
console.log("FAIL");
} catch (e) {
console.log("PASS");
}
try {} catch (c) {
try {} catch (c) {
var a;
c = 0;
}
}
}
expect_stdout: "PASS"
}
issue_3791_1: {
options = {
collapse_vars: true,
join_vars: true,
toplevel: true,
}
input: {
var a = "PASS";
switch (a) {
case console:
}
var a = a;
console.log(a);
}
expect: {
var a;
switch (a = "PASS") {
case console:
}
var a = a;
console.log(a);
}
expect_stdout: "PASS"
}
issue_3791_2: {
options = {
collapse_vars: true,
join_vars: true,
}
input: {
function f(a) {
var b;
return b = a || g;
function g() {
return b;
}
}
console.log(typeof f()());
}
expect: {
function f(a) {
var b;
return b = a || g;
function g() {
return b;
}
}
console.log(typeof f()());
}
expect_stdout: "function"
}
issue_3795: {
options = {
collapse_vars: true,
conditionals: true,
dead_code: true,
evaluate: true,
join_vars: true,
loops: true,
passes: 2,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = "FAIL";
function f(b) {
for (var i = 1; b && i; --i) return 0;
a = "PASS";
}
var c = f(a = "");
console.log(a);
}
expect: {
var a = "FAIL";
(function(b) {
a = "";
a = "PASS";
})();
console.log(a);
}
expect_stdout: "PASS"
}
if_body: {
options = {
join_vars: true,
}
input: {
var a;
if (x)
var b;
else
var c;
}
expect: {
var a, b, c;
if (x);
else;
}
}
if_switch: {
options = {
join_vars: true,
}
input: {
var a;
if (x) switch (y) {
case 1:
var b;
default:
var c;
}
}
expect: {
var a, b, c;
if (x) switch (y) {
case 1:
default:
}
}
}
loop_body_1: {
options = {
join_vars: true,
}
input: {
var a;
for (;x;)
var b;
}
expect: {
for (var a, b; x;);
}
}
loop_body_2: {
options = {
join_vars: true,
}
input: {
for (var a; x;)
var b;
}
expect: {
for (var a, b; x;);
}
}
loop_body_3: {
options = {
join_vars: true,
}
input: {
var a;
for (var b; x;)
var c;
}
expect: {
for (var a, b, c; x;);
}
}
conditional_assignments_1: {
options = {
conditionals: true,
join_vars: true,
sequences: true,
}
input: {
function f(b, c, d) {
var a = b;
if (c) a = d;
return a;
}
function g(b, c, d) {
var a = b;
if (c); else a = d;
return a;
}
console.log(f("FAIL", 1, "PASS"), g("PASS", 1, "FAIL"));
}
expect: {
function f(b, c, d) {
var a = c ? d : b;
return a;
}
function g(b, c, d) {
var a = c ? b : d;
return a;
}
console.log(f("FAIL", 1, "PASS"), g("PASS", 1, "FAIL"));
}
expect_stdout: "PASS PASS"
}
conditional_assignments_2: {
options = {
conditionals: true,
join_vars: true,
sequences: true,
}
input: {
function f1(c, d) {
var a = b;
if (c) a = d;
return a;
}
function f2(b, d) {
var a = b;
if (c) a = d;
return a;
}
function f3(b, c) {
var a = b;
if (c) a = d;
return a;
}
}
expect: {
function f1(c, d) {
var a = b;
return c && (a = d), a;
}
function f2(b, d) {
var a = b;
return c && (a = d), a;
}
function f3(b, c) {
var a = b;
return c && (a = d), a;
}
}
}
conditional_assignments_3: {
options = {
conditionals: true,
sequences: true,
}
input: {
console.log(function(b) {
var a = "PASS";
if (b) a = a;
return a;
}(0, 1));
}
expect: {
console.log(function(b) {
var a = "PASS";
return b && (a = a), a;
}(0, 1));
}
expect_stdout: "PASS"
}

View File

@@ -1226,8 +1226,7 @@ chained_3: {
}
expect: {
console.log(function(b) {
var c = 1;
c = b;
var c = 1, c = b;
b++;
return c;
}(2));

View File

@@ -3,6 +3,7 @@ labels_1: {
conditionals: true,
dead_code: true,
if_return: true,
unused: true,
}
input: {
out: {
@@ -21,6 +22,7 @@ labels_2: {
conditionals: true,
dead_code: true,
if_return: true,
unused: true,
}
input: {
out: {
@@ -61,6 +63,7 @@ labels_4: {
conditionals: true,
dead_code: true,
if_return: true,
unused: true,
}
input: {
out: for (var i = 0; i < 5; ++i) {
@@ -105,6 +108,9 @@ labels_5: {
}
labels_6: {
options = {
dead_code: true,
}
input: {
out: break out;
};
@@ -159,6 +165,7 @@ labels_9: {
conditionals: true,
dead_code: true,
if_return: true,
unused: true,
}
input: {
out: while (foo) {

View File

@@ -549,6 +549,7 @@ issue_2740_2: {
dead_code: true,
loops: true,
passes: 2,
unused: true,
}
input: {
L1: while (x()) {
@@ -564,6 +565,7 @@ issue_2740_3: {
options = {
dead_code: true,
loops: true,
unused: true,
}
input: {
L1: for (var x = 0; x < 3; x++) {
@@ -589,6 +591,7 @@ issue_2740_4: {
dead_code: true,
loops: true,
passes: 2,
unused: true,
}
input: {
L1: for (var x = 0; x < 3; x++) {
@@ -613,6 +616,7 @@ issue_2740_5: {
dead_code: true,
loops: true,
passes: 2,
unused: true,
}
input: {
L1: for (var x = 0; x < 3; x++) {
@@ -763,6 +767,7 @@ issue_3631_1: {
loops: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var c = 0;
@@ -789,6 +794,7 @@ issue_3631_2: {
loops: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
L: for (var a = 1; a--; console.log(b)) {

View File

@@ -1143,558 +1143,6 @@ const_prop_assign_pure: {
}
}
join_object_assignments_1: {
options = {
evaluate: true,
join_vars: true,
}
input: {
console.log(function() {
var x = {
a: 1,
c: (console.log("c"), "C"),
};
x.b = 2;
x[3] = function() {
console.log(x);
},
x["a"] = /foo/,
x.bar = x;
return x;
}());
}
expect: {
console.log(function() {
var x = {
a: 1,
c: (console.log("c"), "C"),
b: 2,
3: function() {
console.log(x);
},
a: /foo/,
};
x.bar = x;
return x;
}());
}
expect_stdout: true
}
join_object_assignments_2: {
options = {
evaluate: true,
hoist_props: true,
join_vars: true,
passes: 3,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
foo: 1,
};
o.bar = 2;
o.baz = 3;
console.log(o.foo, o.bar + o.bar, o.foo * o.bar * o.baz);
}
expect: {
console.log(1, 4, 6);
}
expect_stdout: "1 4 6"
}
join_object_assignments_3: {
options = {
evaluate: true,
join_vars: true,
}
input: {
console.log(function() {
var o = {
a: "PASS",
}, a = o.a;
o.a = "FAIL";
return a;
}());
}
expect: {
console.log(function() {
var o = {
a: "PASS",
}, a = o.a;
o.a = "FAIL";
return a;
}());
}
expect_stdout: "PASS"
}
join_object_assignments_4: {
options = {
join_vars: true,
sequences: true,
}
input: {
var o;
console.log(o);
o = {};
o.a = "foo";
console.log(o.b);
o.b = "bar";
console.log(o.a);
}
expect: {
var o;
console.log(o),
o = {
a: "foo",
},
console.log(o.b),
o.b = "bar",
console.log(o.a);
}
expect_stdout: [
"undefined",
"undefined",
"foo",
]
}
join_object_assignments_return_1: {
options = {
join_vars: true,
}
input: {
console.log(function() {
var o = {
p: 3
};
return o.q = "foo";
}());
}
expect: {
console.log(function() {
var o = {
p: 3,
q: "foo"
};
return o.q;
}());
}
expect_stdout: "foo"
}
join_object_assignments_return_2: {
options = {
join_vars: true,
}
input: {
console.log(function() {
var o = {
p: 3
};
return o.q = /foo/,
o.r = "bar";
}());
}
expect: {
console.log(function() {
var o = {
p: 3,
q: /foo/,
r: "bar"
};
return o.r;
}());
}
expect_stdout: "bar"
}
join_object_assignments_return_3: {
options = {
join_vars: true,
}
input: {
console.log(function() {
var o = {
p: 3
};
return o.q = "foo",
o.p += "",
console.log(o.q),
o.p;
}());
}
expect: {
console.log(function() {
var o = {
p: 3,
q: "foo"
};
return o.p += "",
console.log(o.q),
o.p;
}());
}
expect_stdout: [
"foo",
"3",
]
}
join_object_assignments_for: {
options = {
join_vars: true,
}
input: {
console.log(function() {
var o = {
p: 3
};
for (o.q = "foo"; console.log(o.q););
return o.p;
}());
}
expect: {
console.log(function() {
for (var o = {
p: 3,
q: "foo"
}; console.log(o.q););
return o.p;
}());
}
expect_stdout: [
"foo",
"3",
]
}
join_object_assignments_if: {
options = {
join_vars: true,
}
input: {
console.log(function() {
var o = {};
if (o.a = "PASS") return o.a;
}())
}
expect: {
console.log(function() {
var o = { a: "PASS" };
if (o.a) return o.a;
}());
}
expect_stdout: "PASS"
}
join_object_assignments_forin: {
options = {
join_vars: true,
}
input: {
console.log(function() {
var o = {};
for (var a in o.a = "PASS", o)
return o[a];
}())
}
expect: {
console.log(function() {
var o = { a: "PASS" };
for (var a in o)
return o[a];
}());
}
expect_stdout: "PASS"
}
join_object_assignments_negative: {
options = {
evaluate: true,
join_vars: true,
properties: true,
}
input: {
var o = {};
o[0] = 0;
o[-0] = 1;
o[-1] = 2;
console.log(o[0], o[-0], o[-1]);
}
expect: {
var o = {
0: 0,
0: 1,
"-1": 2
};
console.log(o[0], o[-0], o[-1]);
}
expect_stdout: "1 1 2"
}
join_object_assignments_NaN_1: {
options = {
join_vars: true,
}
input: {
var o = {};
o[NaN] = 1;
o[0/0] = 2;
console.log(o[NaN], o[NaN]);
}
expect: {
var o = {};
o[NaN] = 1;
o[0/0] = 2;
console.log(o[NaN], o[NaN]);
}
expect_stdout: "2 2"
}
join_object_assignments_NaN_2: {
options = {
evaluate: true,
join_vars: true,
properties: true,
}
input: {
var o = {};
o[NaN] = 1;
o[0/0] = 2;
console.log(o[NaN], o[NaN]);
}
expect: {
var o = {
NaN: 1,
NaN: 2
};
console.log(o.NaN, o.NaN);
}
expect_stdout: "2 2"
}
join_object_assignments_null_0: {
options = {
join_vars: true,
}
input: {
var o = {};
o[null] = 1;
console.log(o[null]);
}
expect: {
var o = {};
o[null] = 1;
console.log(o[null]);
}
expect_stdout: "1"
}
join_object_assignments_null_1: {
options = {
evaluate: true,
join_vars: true,
properties: true,
}
input: {
var o = {};
o[null] = 1;
console.log(o[null]);
}
expect: {
var o = {
null: 1
};
console.log(o.null);
}
expect_stdout: "1"
}
join_object_assignments_void_0: {
options = {
evaluate: true,
join_vars: true,
}
input: {
var o = {};
o[void 0] = 1;
console.log(o[void 0]);
}
expect: {
var o = {
undefined: 1
};
console.log(o[void 0]);
}
expect_stdout: "1"
}
join_object_assignments_undefined_1: {
options = {
join_vars: true,
}
input: {
var o = {};
o[undefined] = 1;
console.log(o[undefined]);
}
expect: {
var o = {};
o[void 0] = 1;
console.log(o[void 0]);
}
expect_stdout: "1"
}
join_object_assignments_undefined_2: {
options = {
evaluate: true,
join_vars: true,
properties: true,
}
input: {
var o = {};
o[undefined] = 1;
console.log(o[undefined]);
}
expect: {
var o = {
undefined : 1
};
console.log(o[void 0]);
}
expect_stdout: "1"
}
join_object_assignments_Infinity: {
options = {
evaluate: true,
join_vars: true,
properties: true,
}
input: {
var o = {};
o[Infinity] = 1;
o[1/0] = 2;
o[-Infinity] = 3;
o[-1/0] = 4;
console.log(o[Infinity], o[1/0], o[-Infinity], o[-1/0]);
}
expect: {
var o = {
Infinity: 1,
Infinity: 2,
"-Infinity": 3,
"-Infinity": 4
};
console.log(o[1/0], o[1/0], o[-1/0], o[-1/0]);
}
expect_stdout: "2 2 4 4"
}
join_object_assignments_regex: {
options = {
evaluate: true,
join_vars: true,
properties: true,
}
input: {
var o = {};
o[/rx/] = 1;
console.log(o[/rx/]);
}
expect: {
var o = {
"/rx/": 1
};
console.log(o[/rx/]);
}
expect_stdout: "1"
}
issue_2816: {
options = {
join_vars: true,
}
input: {
"use strict";
var o = {
a: 1
};
o.b = 2;
o.a = 3;
o.c = 4;
console.log(o.a, o.b, o.c);
}
expect: {
"use strict";
var o = {
a: 1,
b: 2
};
o.a = 3;
o.c = 4;
console.log(o.a, o.b, o.c);
}
expect_stdout: "3 2 4"
}
issue_2893_1: {
options = {
join_vars: true,
}
input: {
var o = {
get a() {
return "PASS";
},
};
o.a = "FAIL";
console.log(o.a);
}
expect: {
var o = {
get a() {
return "PASS";
},
};
o.a = "FAIL";
console.log(o.a);
}
expect_stdout: "PASS"
}
issue_2893_2: {
options = {
join_vars: true,
}
input: {
var o = {
set a(v) {
this.b = v;
},
b: "FAIL",
};
o.a = "PASS";
console.log(o.b);
}
expect: {
var o = {
set a(v) {
this.b = v;
},
b: "FAIL",
};
o.a = "PASS";
console.log(o.b);
}
expect_stdout: "PASS"
}
issue_869_1: {
mangle = {
properties: {
@@ -1856,36 +1304,6 @@ issue_3188_3: {
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"
}
issue_3389: {
options = {
evaluate: true,

View File

@@ -223,6 +223,25 @@ unsafe_evaluate: {
expect_stdout: true
}
unsafe_evaluate_defun: {
options = {
evaluate: true,
reduce_vars: true,
unsafe: true,
unused: true,
}
input: {
console.log(function() {
function f() {}
return ++f;
}());
}
expect: {
console.log(NaN);
}
expect_stdout: "NaN"
}
unsafe_evaluate_side_effect_free_1: {
options = {
evaluate: true,
@@ -2289,11 +2308,10 @@ redefine_farg_2: {
console.log(f([]), g([]), h([]));
}
expect: {
console.log((a = [], typeof a), "number",function(a, b) {
console.log(typeof [], "number",function(a, b) {
a = b;
return typeof a;
}([]));
var a;
}
expect_stdout: "object number undefined"
}
@@ -4571,7 +4589,7 @@ perf_8: {
expect_stdout: "348150"
}
issue_2485: {
issue_2485_1: {
options = {
reduce_funcs: true,
reduce_vars: true,
@@ -4619,6 +4637,53 @@ issue_2485: {
expect_stdout: "6"
}
issue_2485_2: {
options = {
inline: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
var foo = function(bar) {
var n = function(a, b) {
return a + b;
};
var sumAll = function(arg) {
return arg.reduce(n, 0);
};
var runSumAll = function(arg) {
return sumAll(arg);
};
bar.baz = function(arg) {
var n = runSumAll(arg);
return (n.get = 1), n;
};
return bar;
};
var bar = foo({});
console.log(bar.baz([1, 2, 3]));
}
expect: {
var foo = function(bar) {
var n = function(a, b) {
return a + b;
};
var runSumAll = function(arg) {
return arg.reduce(n, 0);
};
bar.baz = function(arg) {
var n = runSumAll(arg);
return (n.get = 1), n;
};
return bar;
};
var bar = foo({});
console.log(bar.baz([1, 2, 3]));
}
expect_stdout: "6"
}
issue_2455: {
options = {
reduce_vars: true,
@@ -5435,8 +5500,7 @@ lvalues_def_1: {
}
expect: {
var b = 1;
var a = b++;
b = NaN;
var a = b++, b = NaN;
console.log(a, b);
}
expect_stdout: "1 NaN"
@@ -5455,8 +5519,7 @@ lvalues_def_2: {
}
expect: {
var b = 1;
var a = b += 1;
b = NaN;
var a = b += 1, b = NaN;
console.log(a, b);
}
expect_stdout: "2 NaN"
@@ -6511,17 +6574,17 @@ issue_3240_3: {
}
expect: {
(function() {
(function f(b) {
f();
function f(b) {
if (!f.a) f.a = 0;
console.log(f.a.toString());
var g = function() {
(function() {
(b ? function() {} : function() {
f.a++;
f(1);
})();
};
g();
})();
})();
}
})();
}
expect_stdout: [
@@ -6555,7 +6618,8 @@ issue_3240_4: {
}
expect: {
(function() {
(function f(b) {
f();
function f(b) {
if (!f.a) f.a = 0;
console.log(f.a.toString());
(function() {
@@ -6564,7 +6628,7 @@ issue_3240_4: {
f(1);
})();
})();
})();
}
})();
}
expect_stdout: [
@@ -6867,9 +6931,48 @@ issue_3666: {
} finally {
for (;!a;)
a++;
var b = a = "PASS";
a = "PASS";
}
console.log(a, b);
console.log(a, "PASS");
}
expect_stdout: "PASS PASS"
}
issue_3774: {
options = {
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
var f = function() {
function g() {
if (!g.p) {
g.p = 1;
console.log("PASS");
}
}
return function() {
g();
};
}();
f();
f();
}
expect: {
var f = function() {
function g() {
if (!g.p) {
g.p = 1;
console.log("PASS");
}
}
return function() {
g();
};
}();
f();
f();
}
expect_stdout: "PASS"
}

View File

@@ -69,6 +69,7 @@ label_if_break: {
dead_code: true,
evaluate: true,
side_effects: true,
unused: true,
}
input: {
L: if (true) {

View File

@@ -435,3 +435,25 @@ emberjs_global: {
}
expect_stdout: Error("PASS")
}
issue_3817: {
options = {
comparisons: true,
conditionals: true,
passes: 2,
typeofs: true,
}
input: {
if ("A" == typeof A || !console.log("PASS")) switch (false) {
case "undefined" == typeof A:
console.log("FAIL");
}
}
expect: {
if ("A" == typeof A || !console.log("PASS")) switch (false) {
case "undefined" == typeof A:
console.log("FAIL");
}
}
expect_stdout: "PASS"
}

View File

@@ -13,3 +13,4 @@ exports["to_ascii"] = to_ascii;
exports["tokenizer"] = tokenizer;
exports["TreeTransformer"] = TreeTransformer;
exports["TreeWalker"] = TreeWalker;
exports["vlq_decode"] = vlq_decode;

View File

@@ -1,2 +1,41 @@
function _toConsumableArray(arr){if(Array.isArray(arr)){for(var i=0,arr2=Array(arr.length);i<arr.length;i++){arr2[i]=arr[i]}return arr2}else{return Array.from(arr)}}var _require=require("bar"),foo=_require.foo;var _require2=require("world"),hello=_require2.hello;foo.x.apply(foo,_toConsumableArray(foo.y(hello.z)));
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImlucHV0Mi5qcyJdLCJuYW1lcyI6WyJyZXF1aXJlIiwiYXJyIl0sIm1hcHBpbmdzIjoiMEpBQWNBLEtBQVFDIiwic291cmNlc0NvbnRlbnQiOlsiY29uc3Qge2Zvb30gPSByZXF1aXJlKFwiYmFyXCIpO1xuY29uc3Qge2hlbGxvfSA9IHJlcXVpcmUoXCJ3b3JsZFwiKTtcblxuZm9vLngoLi4uZm9vLnkoaGVsbG8ueikpO1xuIl19
"use strict";
function _toConsumableArray(arr) {
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
}
function _nonIterableSpread() {
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _unsupportedIterableToArray(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(n);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}
function _iterableToArray(iter) {
if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);
}
function _arrayWithoutHoles(arr) {
if (Array.isArray(arr)) return _arrayLikeToArray(arr);
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) {
arr2[i] = arr[i];
}
return arr2;
}
var _require = require("bar"), foo = _require.foo;
var _require2 = require("world"), hello = _require2.hello;
foo.x.apply(foo, _toConsumableArray(foo.y(hello.z)));
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImlucHV0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbImNvbnN0IHtmb299ID0gcmVxdWlyZShcImJhclwiKTtcbmNvbnN0IHtoZWxsb30gPSByZXF1aXJlKFwid29ybGRcIik7XG5cbmZvby54KC4uLmZvby55KGhlbGxvLnopKTtcbiJdLCJuYW1lcyI6WyJyZXF1aXJlIiwiZm9vIiwiaGVsbG8iLCJ4IiwiYXBwbHkiLCJfdG9Db25zdW1hYmxlQXJyYXkiLCJ5IiwieiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7ZUFBY0EsUUFBUSxRQUFmQyxNLFNBQUFBOztBLGdCQUNTRCxRQUFRLFVBQWpCRSxRLFVBQUFBOztBQUVQRCxJQUFJRSxFQUFKQyxNQUFBSCxLQUFHSSxtQkFBTUosSUFBSUssRUFBRUosTUFBTUsifQ==

View File

@@ -1,4 +1,16 @@
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
"use strict";
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
var _require = require("bar"),
foo = _require.foo;

View File

@@ -1 +1,11 @@
{"version":3,"sources":["input2.js"],"names":["require","foo","hello","x","apply","_toConsumableArray","y","z"],"mappings":"kLAAcA,QAAQ,OAAfC,aAAAA,kBACSD,QAAQ,SAAjBE,gBAAAA,MAEPD,IAAIE,EAAJC,MAAAH,IAAAI,mBAASJ,IAAIK,EAAEJ,MAAMK","sourcesContent":["const {foo} = require(\"bar\");\nconst {hello} = require(\"world\");\n\nfoo.x(...foo.y(hello.z));\n"]}
{
"version": 3,
"sources": [
"input.js"
],
"names": [],
"mappings": ";;;;;;;;;;;;;;eAAc,OAAO,CAAC,KAAD,C;IAAd,G,YAAA,G;;gBACS,OAAO,CAAC,OAAD,C;IAAhB,K,aAAA,K;;AAEP,GAAG,CAAC,CAAJ,OAAA,GAAG,qBAAM,GAAG,CAAC,CAAJ,CAAM,KAAK,CAAC,CAAZ,CAAN,EAAH",
"sourcesContent": [
"const {foo} = require(\"bar\");\nconst {hello} = require(\"world\");\n\nfoo.x(...foo.y(hello.z));\n"
]
}

View File

@@ -1,2 +1,2 @@
new function(){console.log(3)};
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxJQUFyQyxXQUFnQkEsUUFBUUMsSUFBSSIsInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl19
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxJQUFyQyxXQUFnQkEsUUFBUUMsSUFBSSJ9

View File

@@ -2,4 +2,4 @@ function test(a){
"aaaaaaaaaaaaaaaa"
;a(err,data),a(err,
data)}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsidGVzdCIsImNhbGxiYWNrIiwiZXJyIiwiZGF0YSJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsS0FBS0M7QUFDVjtDQUNBQSxFQUFTQyxJQUFLQyxNQUNkRixFQUFTQztBQUFLQyJ9
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsidGVzdCIsImNhbGxiYWNrIiwiZXJyIiwiZGF0YSJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsS0FBS0M7O0NBRVZBLEVBQVNDLElBQUtDLE1BQ2RGLEVBQVNDO0FBQUtDIn0=

View File

@@ -1,2 +1,2 @@
new function(){console.log(3)};
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxJQUFyQyxXQUFnQkEsUUFBUUMsSUFBSSIsInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl19
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxJQUFyQyxXQUFnQkEsUUFBUUMsSUFBSSJ9

View File

@@ -1,6 +1,6 @@
function f(x) {
return g(x);
function g(x) {
return x;
return x + x;
}
}

View File

@@ -8,15 +8,14 @@ if (typeof phantom == "undefined") {
require("../tools/exit");
var args = process.argv.slice(2);
var debug = args.indexOf("--debug");
if (debug >= 0) {
if (debug < 0) {
debug = false;
} else {
args.splice(debug, 1);
debug = true;
} else {
debug = false;
}
if (!args.length) {
args.push("-mcb", "beautify=false,webkit");
}
args.unshift("bin/uglifyjs");
if (!args.length) args.push("-mcb", "beautify=false,webkit");
args.push("--timings");
var child_process = require("child_process");
var fetch = require("./fetch");
@@ -39,10 +38,10 @@ if (typeof phantom == "undefined") {
});
if (/\.js$/.test(url)) {
var stderr = "";
var uglifyjs = child_process.fork("bin/uglifyjs", args, {
var uglifyjs = child_process.spawn(process.argv[0], args, {
silent: true
}).on("exit", function(code) {
console.log("uglifyjs", url.slice(site.length + 1), args.join(" "));
console.log("uglifyjs", url.slice(site.length + 1), args.slice(1).join(" "));
console.log(stderr);
if (code) throw new Error("uglifyjs failed with code " + code);
});

View File

@@ -2,6 +2,7 @@ var assert = require("assert");
var exec = require("child_process").exec;
var fs = require("fs");
var run_code = require("../sandbox").run_code;
var to_ascii = require("../node").to_ascii;
function read(path) {
return fs.readFileSync(path, "utf8");
@@ -48,6 +49,62 @@ describe("bin/uglifyjs", function() {
done();
});
});
it("Should work with --source-map names=true", function(done) {
exec([
uglifyjscmd,
"--beautify",
"--source-map", [
"names=true",
"url=inline",
].join(","),
].join(" "), function(err, stdout) {
if (err) throw err;
var expected = [
"var obj = {",
" p: a,",
" q: b",
"};",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,",
].join("\n")
assert.strictEqual(stdout.slice(0, expected.length), expected);
var map = JSON.parse(to_ascii(stdout.slice(expected.length).trim()));
assert.deepEqual(map.names, [ "obj", "p", "a", "q", "b" ]);
done();
}).stdin.end([
"var obj = {",
" p: a,",
" q: b",
"};",
].join("\n"));
});
it("Should work with --source-map names=false", function(done) {
exec([
uglifyjscmd,
"--beautify",
"--source-map", [
"names=false",
"url=inline",
].join(","),
].join(" "), function(err, stdout) {
if (err) throw err;
var expected = [
"var obj = {",
" p: a,",
" q: b",
"};",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,",
].join("\n")
assert.strictEqual(stdout.slice(0, expected.length), expected);
var map = JSON.parse(to_ascii(stdout.slice(expected.length).trim()));
assert.deepEqual(map.names, []);
done();
}).stdin.end([
"var obj = {",
" p: a,",
" q: b",
"};",
].join("\n"));
});
it("Should give sensible error against invalid input source map", function(done) {
var command = uglifyjscmd + " test/mocha.js --source-map content=blah,url=inline --verbose";
exec(command, function(err, stdout, stderr) {
@@ -109,9 +166,12 @@ describe("bin/uglifyjs", function() {
}
var command = [
uglifyjscmd,
"--source-map", "content=" + mapFile,
"--source-map", "includeSources=true",
"--source-map", "url=inline",
"--beautify",
"--source-map", [
"content=" + mapFile,
"includeSources",
"url=inline",
].join(","),
].join(" ");
var child = exec(command, function(err, stdout) {
@@ -245,7 +305,7 @@ describe("bin/uglifyjs", function() {
if (err) throw err;
assert.strictEqual(stdout, [
"var Foo=function Foo(){console.log(1+2)};new Foo;var bar=function(){function foo(bar){return bar}return foo}();",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwidGVzdC9pbnB1dC9pc3N1ZS0xMzIzL3NhbXBsZS5qcyJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFNBQUFBLE1BQWdCQyxRQUFRQyxJQUFJLEVBQUUsSUFBTyxJQUFJRixJQ0FuRCxJQUFJRyxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwidGVzdC9pbnB1dC9pc3N1ZS0xMzIzL3NhbXBsZS5qcyJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFNBQUVBLE1BQWNDLFFBQVFDLElBQUksRUFBRSxJQUFPLElBQUlGLElDQW5ELElBQUlHLElBQU0sV0FDTixTQUFTQyxJQUFLRCxLQUNWLE9BQU9BLElBR1gsT0FBT0MsSUFMRCJ9",
"",
].join("\n"));
var stderrLines = stderr.split("\n");
@@ -587,7 +647,7 @@ describe("bin/uglifyjs", function() {
});
function read_map() {
var map = JSON.parse(read("./test/input/issue-1236/simple.js.map"));
var map = JSON.parse(read("test/input/issue-1236/simple.js.map"));
delete map.sourcesContent;
return JSON.stringify(map).replace(/"/g, '\\"');
}
@@ -674,7 +734,7 @@ describe("bin/uglifyjs", function() {
var command = uglifyjscmd + " test/input/rename/input.js --rename";
exec(command, function(err, stdout, stderr) {
if (err) throw err;
assert.strictEqual(stdout, "function f(a){return b(a);function b(c){return c}}\n");
assert.strictEqual(stdout, "function f(a){return b(a);function b(c){return c+c}}\n");
done();
});
});
@@ -682,7 +742,7 @@ describe("bin/uglifyjs", function() {
var command = uglifyjscmd + " test/input/rename/input.js -mc passes=2 --no-rename";
exec(command, function(err, stdout, stderr) {
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)}\n");
done();
});
});
@@ -690,7 +750,7 @@ describe("bin/uglifyjs", function() {
var command = uglifyjscmd + " test/input/rename/input.js -mc passes=2";
exec(command, function(err, stdout, stderr) {
if (err) throw err;
assert.strictEqual(stdout, "function f(n){return n}\n");
assert.strictEqual(stdout, "function f(n){return n+n}\n");
done();
});
});
@@ -698,7 +758,7 @@ describe("bin/uglifyjs", function() {
var command = uglifyjscmd + " test/input/rename/input.js -c passes=2";
exec(command, function(err, stdout, stderr) {
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}(x)}\n");
done();
});
});

View File

@@ -1,7 +1,7 @@
var assert = require("assert");
var readFileSync = require("fs").readFileSync;
var run_code = require("../sandbox").run_code;
var UglifyJS = require("../../");
var UglifyJS = require("../..");
function read(path) {
return readFileSync(path, "utf8");
@@ -9,18 +9,30 @@ function read(path) {
describe("minify", function() {
it("Should test basic sanity of minify with default options", function() {
var js = 'function foo(bar) { if (bar) return 3; else return 7; var u = not_called(); }';
var js = "function foo(bar) { if (bar) return 3; else return 7; var u = not_called(); }";
var result = UglifyJS.minify(js);
assert.strictEqual(result.code, 'function foo(n){return n?3:7}');
if (result.error) throw result.error;
assert.strictEqual(result.code, "function foo(n){return n?3:7}");
});
it("Should not mutate minify `options`", function() {
var options = {
compress: true,
mangle: false,
output: {},
};
var value = JSON.stringify(options);
var result = UglifyJS.minify("print(6 * 7);", options);
if (result.error) throw result.error;
assert.strictEqual(result.code, "print(42);");
assert.strictEqual(JSON.stringify(options), value);
})
it("Should skip inherited keys from `files`", function() {
var files = Object.create({ skip: this });
files[0] = "alert(1 + 1)";
var result = UglifyJS.minify(files);
if (result.error) throw result.error;
assert.strictEqual(result.code, "alert(2);");
});
it("Should work with mangle.cache", function() {
var cache = {};
var original = "";
@@ -53,7 +65,6 @@ describe("minify", function() {
].join(""));
assert.strictEqual(run_code(compressed, true), run_code(original, true));
});
it("Should work with nameCache", function() {
var cache = {};
var original = "";
@@ -86,7 +97,6 @@ describe("minify", function() {
].join(""));
assert.strictEqual(run_code(compressed, true), run_code(original, true));
});
it("Should avoid cached names when mangling top-level variables", function() {
var cache = {};
var original = "";
@@ -115,7 +125,6 @@ describe("minify", function() {
].join(""));
assert.strictEqual(run_code(compressed, true), run_code(original, true));
});
it("Should avoid cached names when mangling inner-scoped variables", function() {
var cache = {};
var original = "";
@@ -139,7 +148,6 @@ describe("minify", function() {
].join(""));
assert.strictEqual(run_code(compressed, true), run_code(original, true));
});
it("Should not parse invalid use of reserved words", function() {
assert.strictEqual(UglifyJS.minify("function enum(){}").error, undefined);
assert.strictEqual(UglifyJS.minify("function static(){}").error, undefined);
@@ -155,7 +163,6 @@ describe("minify", function() {
}});
assert.strictEqual(result.code, 'var foo={"x":1,y:2,"z":3};');
});
it("Should preserve quote styles when quote_style is 3", function() {
var js = 'var foo = {"x": 1, y: 2, \'z\': 3};';
var result = UglifyJS.minify(js, {
@@ -165,7 +172,6 @@ describe("minify", function() {
}});
assert.strictEqual(result.code, 'var foo={"x":1,y:2,\'z\':3};');
});
it("Should not preserve quotes in object literals when disabled", function() {
var js = 'var foo = {"x": 1, y: 2, \'z\': 3};';
var result = UglifyJS.minify(js, {

View File

@@ -186,7 +186,7 @@ describe("test/reduce.js", function() {
].join("\n"));
});
it("Should reduce infinite loops with reasonable performance", function() {
if (semver.satisfies(process.version, "0.10")) return;
if (semver.satisfies(process.version, "<=0.10")) return;
this.timeout(120000);
var result = reduce_test("while (/9/.test(1 - .8));", {
compress: {
@@ -211,7 +211,7 @@ describe("test/reduce.js", function() {
it("Should ignore difference in Error.message", function() {
var result = reduce_test("null[function() {\n}];");
if (result.error) throw result.error;
assert.strictEqual(result.code, (semver.satisfies(process.version, "0.10") ? [
assert.strictEqual(result.code, (semver.satisfies(process.version, "<=0.10") ? [
"// Can't reproduce test failure",
"// minify options: {}",
] : [
@@ -246,4 +246,54 @@ describe("test/reduce.js", function() {
"// }",
].join("\n"));
});
it("Should reduce test case which differs only in Error.message", function() {
var code = [
"var a=0;",
"try{",
"null[function(){}]",
"}catch(e){",
"for(var i in e.toString())",
"a++,console.log()",
"}",
"console.log(a);",
].join("");
var result = reduce_test(code, {
compress: false,
mangle: false,
output: {
beautify: true,
},
});
if (result.error) throw result.error;
assert.deepEqual(result.warnings, []);
assert.strictEqual(result.code.replace(/function \(/g, "function("), (semver.satisfies(process.version, "<=0.10") ? [
"// Can't reproduce test failure",
"// minify options: {",
'// "compress": false,',
'// "mangle": false,',
'// "output": {',
'// "beautify": true',
"// }",
"// }",
] : [
[
"try{",
"null[function(){}]",
"}catch(e){",
"console.log(e)",
"}",
].join(""),
"// output: TypeError: Cannot read property 'function(){}' of null",
"// ",
"// minify: TypeError: Cannot read property 'function() {}' of null",
"// ",
"// options: {",
'// "compress": false,',
'// "mangle": false,',
'// "output": {',
'// "beautify": true',
"// }",
"// }",
]).join("\n"));
});
});

View File

@@ -1,18 +1,19 @@
var assert = require("assert");
var readFileSync = require("fs").readFileSync;
var SourceMapConsumer = require("source-map").SourceMapConsumer;
var fs = require("fs");
var UglifyJS = require("../node");
function read(path) {
return readFileSync(path, "utf8");
return fs.readFileSync(path, "utf8");
}
function source_map(code) {
return JSON.parse(UglifyJS.minify(code, {
var result = UglifyJS.minify(code, {
compress: false,
mangle: false,
sourceMap: true,
}).map);
});
if (result.error) throw result.error;
return JSON.parse(result.map);
}
function get_map() {
@@ -44,7 +45,7 @@ function prepare_map(sourceMap) {
}
});
if (result.error) throw result.error;
return new SourceMapConsumer(result.map);
return JSON.parse(result.map);
}
describe("sourcemaps", function() {
@@ -66,6 +67,40 @@ describe("sourcemaps", function() {
].join("\n"));
assert.deepEqual(map.names, [ "enabled", "x" ]);
});
it("Should work with sourceMap.names=true", function() {
var result = UglifyJS.minify([
"var obj = {",
" p: a,",
" q: b",
"};",
].join("\n"), {
compress: false,
mangle: false,
sourceMap: {
names: true,
},
});
if (result.error) throw result.error;
var map = JSON.parse(result.map);
assert.deepEqual(map.names, [ "obj", "p", "a", "q", "b" ]);
});
it("Should work with sourceMap.names=false", function() {
var result = UglifyJS.minify([
"var obj = {",
" p: a,",
" q: b",
"};",
].join("\n"), {
compress: false,
mangle: false,
sourceMap: {
names: false,
},
});
if (result.error) throw result.error;
var map = JSON.parse(result.map);
assert.deepEqual(map.names, []);
});
it("Should mark array/object literals", function() {
var result = UglifyJS.minify([
"var obj = {};",
@@ -87,7 +122,7 @@ describe("sourcemaps", function() {
});
if (result.error) throw result.error;
assert.strictEqual(result.code, code);
assert.strictEqual(result.map, '{"version":3,"sources":["0"],"names":["console","log"],"mappings":"AAAAA,QAAQC,IAAI","sourceRoot":"//foo.bar/"}');
assert.strictEqual(result.map, '{"version":3,"sourceRoot":"//foo.bar/","sources":["0"],"names":["console","log"],"mappings":"AAAAA,QAAQC,IAAI"}');
});
it("Should produce same source map with DOS or UNIX line endings", function() {
var code = [
@@ -108,9 +143,9 @@ describe("sourcemaps", function() {
describe("inSourceMap", function() {
it("Should read the given string filename correctly when sourceMapIncludeSources is enabled", function() {
var result = UglifyJS.minify(read("./test/input/issue-1236/simple.js"), {
var result = UglifyJS.minify(read("test/input/issue-1236/simple.js"), {
sourceMap: {
content: read("./test/input/issue-1236/simple.js.map"),
content: read("test/input/issue-1236/simple.js.map"),
filename: "simple.min.js",
includeSources: true
}
@@ -122,7 +157,7 @@ describe("sourcemaps", function() {
assert.equal(map.sourcesContent[0], 'let foo = x => "foo " + x;\nconsole.log(foo("bar"));');
});
it("Should process inline source map", function() {
var result = UglifyJS.minify(read("./test/input/issue-520/input.js"), {
var result = UglifyJS.minify(read("test/input/issue-520/input.js"), {
compress: { toplevel: true },
sourceMap: {
content: "inline",
@@ -131,10 +166,10 @@ describe("sourcemaps", function() {
}
});
if (result.error) throw result.error;
assert.strictEqual(result.code + "\n", readFileSync("test/input/issue-520/output.js", "utf8"));
assert.strictEqual(result.code + "\n", read("test/input/issue-520/output.js"));
});
it("Should warn for missing inline source map", function() {
var result = UglifyJS.minify(read("./test/input/issue-1323/sample.js"), {
var result = UglifyJS.minify(read("test/input/issue-1323/sample.js"), {
mangle: false,
sourceMap: {
content: "inline"
@@ -146,8 +181,8 @@ describe("sourcemaps", function() {
});
it("Should handle multiple input and inline source map", function() {
var result = UglifyJS.minify([
read("./test/input/issue-520/input.js"),
read("./test/input/issue-1323/sample.js"),
read("test/input/issue-520/input.js"),
read("test/input/issue-1323/sample.js"),
], {
sourceMap: {
content: "inline",
@@ -163,7 +198,7 @@ describe("sourcemaps", function() {
assert.deepEqual(result.warnings, [ "WARN: inline source map not found: 1" ]);
});
it("Should drop source contents for includeSources=false", function() {
var result = UglifyJS.minify(read("./test/input/issue-520/input.js"), {
var result = UglifyJS.minify(read("test/input/issue-520/input.js"), {
compress: false,
mangle: false,
sourceMap: {
@@ -186,7 +221,7 @@ describe("sourcemaps", function() {
assert.ok(!("sourcesContent" in map));
});
it("Should parse the correct sourceMappingURL", function() {
var result = UglifyJS.minify(read("./test/input/issue-3294/input.js"), {
var result = UglifyJS.minify(read("test/input/issue-3294/input.js"), {
compress: { toplevel: true },
sourceMap: {
content: "inline",
@@ -195,10 +230,10 @@ describe("sourcemaps", function() {
}
});
if (result.error) throw result.error;
assert.strictEqual(result.code + "\n", readFileSync("test/input/issue-3294/output.js", "utf8"));
assert.strictEqual(result.code + "\n", read("test/input/issue-3294/output.js"));
});
it("Should work in presence of unrecognised annotations", function() {
var result = UglifyJS.minify(read("./test/input/issue-3441/input.js"), {
var result = UglifyJS.minify(read("test/input/issue-3441/input.js"), {
compress: false,
mangle: false,
sourceMap: {
@@ -230,7 +265,7 @@ describe("sourcemaps", function() {
assert.strictEqual(code, "var a=function(n){return n};");
});
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,
},
@@ -242,7 +277,7 @@ describe("sourcemaps", function() {
}
});
if (result.error) throw result.error;
assert.strictEqual(result.code, read("./test/input/issue-505/output.js"));
assert.strictEqual(result.code, read("test/input/issue-505/output.js"));
});
it("Should work with unicode characters", function() {
var code = [
@@ -278,32 +313,42 @@ describe("sourcemaps", function() {
});
describe("input sourcemaps", function() {
it("Should not modify input source map", function() {
var orig = get_map();
var original = JSON.stringify(orig);
var map = prepare_map(orig);
assert.strictEqual(JSON.stringify(orig), original);
});
it("Should copy over original sourcesContent", function() {
var orig = get_map();
var map = prepare_map(orig);
assert.equal(map.sourceContentFor("index.js"), orig.sourcesContent[0]);
assert.strictEqual(map.sources.length, 1);
assert.strictEqual(map.sources[0], "index.js");
assert.strictEqual(map.sourcesContent.length, 1);
assert.equal(map.sourcesContent[0], orig.sourcesContent[0]);
});
it("Should copy sourcesContent if sources are relative", function() {
var relativeMap = get_map();
relativeMap.sources = ['./index.js'];
var map = prepare_map(relativeMap);
assert.notEqual(map.sourcesContent, null);
assert.equal(map.sourcesContent.length, 1);
assert.equal(map.sourceContentFor("index.js"), relativeMap.sourcesContent[0]);
assert.strictEqual(map.sources.length, 1);
assert.strictEqual(map.sources[0], "./index.js");
assert.strictEqual(map.sourcesContent.length, 1);
assert.equal(map.sourcesContent[0], relativeMap.sourcesContent[0]);
});
it("Should not have invalid mappings from inputSourceMap", function() {
var map = prepare_map(get_map());
// The original source has only 2 lines, check that mappings don't have more lines
var msg = "Mapping should not have higher line number than the original file had";
map.eachMapping(function(mapping) {
assert.ok(mapping.originalLine <= 2, msg);
});
map.allGeneratedPositionsFor({
source: "index.js",
line: 1,
column: 1
}).forEach(function(pos) {
assert.ok(pos.line <= 2, msg);
var lines = map.mappings.split(/;/);
assert.ok(lines.length <= 2, msg);
var indices = [ 0, 0, 1, 0, 0];
lines.forEach(function(segments) {
indices[0] = 0;
segments.split(/,/).forEach(function(segment) {
UglifyJS.vlq_decode(indices, segment);
assert.ok(indices[2] <= 2, msg);
});
});
});
});

View File

@@ -1,6 +1,6 @@
var fs = require("fs");
new Function("MOZ_SourceMap", "exports", require("../tools/node").FILES.map(function(file) {
new Function("exports", require("../tools/node").FILES.map(function(file) {
if (/exports\.js$/.test(file)) file = require.resolve("./exports");
return fs.readFileSync(file, "utf8");
}).join("\n\n"))(require("source-map"), exports);
}).join("\n\n"))(exports);

View File

@@ -1,5 +1,5 @@
var crypto = require("crypto");
var U = require("./node");
var U = require("..");
var List = U.List;
var os = require("os");
var sandbox = require("./sandbox");
@@ -24,6 +24,10 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
reduce_options = reduce_options || {};
var max_iterations = reduce_options.max_iterations || 1000;
var max_timeout = reduce_options.max_timeout || 10000;
var warnings = [];
var log = reduce_options.log || function(msg) {
warnings.push(msg);
};
var verbose = reduce_options.verbose;
var minify_options_json = JSON.stringify(minify_options, null, 2);
var result_cache = Object.create(null);
@@ -31,7 +35,7 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
var differs = producesDifferentResultWhenMinified(result_cache, testcase, minify_options, max_timeout);
if (verbose) {
console.error("// Node.js " + process.version + " on " + os.platform() + " " + os.arch());
log("// Node.js " + process.version + " on " + os.platform() + " " + os.arch());
}
if (!differs) {
// same stdout result produced when minified
@@ -39,16 +43,19 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
code: [
"// Can't reproduce test failure",
"// minify options: " + to_comment(minify_options_json)
].join("\n")
].join("\n"),
warnings: warnings,
};
} else if (differs.timed_out) {
return {
code: [
"// Can't reproduce test failure within " + max_timeout + "ms",
"// minify options: " + to_comment(minify_options_json)
].join("\n")
].join("\n"),
warnings: warnings,
};
} else if (differs.error) {
differs.warnings = warnings;
return differs;
} else if (is_error(differs.unminified_result)
&& is_error(differs.minified_result)
@@ -57,7 +64,8 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
code: [
"// No differences except in error message",
"// minify options: " + to_comment(minify_options_json)
].join("\n")
].join("\n"),
warnings: warnings,
};
} else {
max_timeout = Math.min(100 * differs.elapsed, max_timeout);
@@ -125,40 +133,13 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
}
}
else if (node instanceof U.AST_Binary) {
CHANGED = true;
var permute = ((node.start._permute += step) * steps | 0) % 4;
var expr = [
node.left,
node.right,
][ permute & 1 ];
if (permute < 2) return expr;
// wrap with console.log()
return new U.AST_Call({
expression: new U.AST_Dot({
expression: new U.AST_SymbolRef({
name: "console",
start: {},
}),
property: "log",
start: {},
}),
args: [ expr ],
start: {},
});
}
else if (node instanceof U.AST_Catch || node instanceof U.AST_Finally) {
// drop catch or finally block
node.start._permute++;
CHANGED = true;
return null;
}
else if (node instanceof U.AST_Conditional) {
CHANGED = true;
return [
node.condition,
node.consequent,
node.alternative,
][ ((node.start._permute += step) * steps | 0) % 3 ];
return permute < 2 ? expr : wrap_with_console_log(expr);
}
else if (node instanceof U.AST_BlockStatement) {
if (in_list) {
@@ -193,12 +174,26 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
return to_sequence(seq);
}
}
else if (node instanceof U.AST_Catch) {
// drop catch block
node.start._permute++;
CHANGED = true;
return null;
}
else if (node instanceof U.AST_Conditional) {
CHANGED = true;
return [
node.condition,
node.consequent,
node.alternative,
][ ((node.start._permute += step) * steps | 0) % 3 ];
}
else if (node instanceof U.AST_Defun) {
switch (((node.start._permute += step) * steps | 0) % 2) {
case 0:
CHANGED = true;
return List.skip;
case 1:
default:
if (!has_exit(node)) {
// hoist function declaration body
var body = node.body;
@@ -230,15 +225,11 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
return to_statement(expr);
}
}
else if (node instanceof U.AST_PropAccess) {
var expr = [
node.expression,
node.property instanceof U.AST_Node && node.property,
][ node.start._permute++ % 2 ];
if (expr) {
CHANGED = true;
return expr;
}
else if (node instanceof U.AST_Finally) {
// drop finally block
node.start._permute++;
CHANGED = true;
return null;
}
else if (node instanceof U.AST_For) {
var expr = [
@@ -287,6 +278,16 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
return expr;
}
}
else if (node instanceof U.AST_PropAccess) {
var expr = [
node.expression,
node.property instanceof U.AST_Node && node.property,
][ node.start._permute++ % 2 ];
if (expr) {
CHANGED = true;
return expr;
}
}
else if (node instanceof U.AST_SimpleStatement) {
if (node.body instanceof U.AST_Call && node.body.expression instanceof U.AST_Function) {
// hoist simple statement IIFE function expression body
@@ -414,19 +415,41 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
}
});
var diff_error_message;
for (var pass = 1; pass <= 3; ++pass) {
var testcase_ast = U.parse(testcase);
if (diff_error_message === testcase) {
// only difference detected is in error message, so expose that and try again
testcase_ast.transform(new U.TreeTransformer(function(node, descend) {
if (node.TYPE == "Call" && node.expression.print_to_string() == "console.log") {
return to_sequence(node.args);
}
if (node instanceof U.AST_Catch) {
descend(node, this);
node.body.unshift(new U.AST_SimpleStatement({
body: wrap_with_console_log(new U.AST_SymbolRef(node.argname)),
start: {},
}));
return node;
}
}));
var code = testcase_ast.print_to_string();
if (diff = producesDifferentResultWhenMinified(result_cache, code, minify_options, max_timeout)) {
testcase = code;
differs = diff;
} else {
testcase_ast = U.parse(testcase);
}
}
diff_error_message = null;
testcase_ast.walk(new U.TreeWalker(function(node) {
// unshare start props to retain visit data between iterations
node.start = JSON.parse(JSON.stringify(node.start));
node.start._permute = 0;
}));
for (var c = 0; c < max_iterations; ++c) {
if (verbose) {
if (pass == 1 && c % 25 == 0) {
console.error("// reduce test pass "
+ pass + ", iteration " + c + ": " + testcase.length + " bytes");
}
if (verbose && pass == 1 && c % 25 == 0) {
log("// reduce test pass " + pass + ", iteration " + c + ": " + testcase.length + " bytes");
}
var CHANGED = false;
var code_ast = testcase_ast.clone(true).transform(tt);
@@ -436,9 +459,9 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
} catch (ex) {
// AST is not well formed.
// no harm done - just log the error, ignore latest change and continue iterating.
console.error("*** Error generating code from AST.");
console.error(ex);
console.error("*** Discarding permutation and continuing.");
log("*** Error generating code from AST.");
log(ex.stack);
log("*** Discarding permutation and continuing.");
continue;
}
var diff = producesDifferentResultWhenMinified(result_cache, code, minify_options, max_timeout);
@@ -449,14 +472,15 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
} else if (diff.error) {
// something went wrong during minify() - could be malformed AST or genuine bug.
// no harm done - just log code & error, ignore latest change and continue iterating.
console.error("*** Error during minification.");
console.error(code);
console.error(diff.error);
console.error("*** Discarding permutation and continuing.");
log("*** Error during minification.");
log(code);
log(diff.error.stack);
log("*** Discarding permutation and continuing.");
} else if (is_error(diff.unminified_result)
&& is_error(diff.minified_result)
&& diff.unminified_result.name == diff.minified_result.name) {
// ignore difference in error messages caused by minification
diff_error_message = testcase;
} else {
// latest permutation is valid, so use it as the basis of new changes
testcase_ast = code_ast;
@@ -467,7 +491,7 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
}
if (c == 0) break;
if (verbose) {
console.error("// reduce test pass " + pass + ": " + testcase.length + " bytes");
log("// reduce test pass " + pass + ": " + testcase.length + " bytes");
}
}
testcase = try_beautify(result_cache, testcase, minify_options, differs.unminified_result, max_timeout);
@@ -488,6 +512,7 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
}
lines.push("// options: " + to_comment(minify_options_json));
testcase.code += lines.join("\n");
testcase.warnings = warnings;
return testcase;
}
};
@@ -592,6 +617,22 @@ function to_statement(node) {
});
}
function wrap_with_console_log(node) {
// wrap with console.log()
return new U.AST_Call({
expression: new U.AST_Dot({
expression: new U.AST_SymbolRef({
name: "console",
start: {},
}),
property: "log",
start: {},
}),
args: [ node ],
start: {},
});
}
function run_code(result_cache, code, toplevel, timeout) {
var key = crypto.createHash("sha1").update(code).digest("base64");
return result_cache[key] || (result_cache[key] = sandbox.run_code(code, toplevel, timeout));

View File

@@ -1,6 +1,3 @@
setInterval(function() {
process.stderr.write("\0");
}, 8 * 60 * 1000).unref();
require("./run")([
"-b",
"-b braces",

View File

@@ -764,10 +764,18 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
return createObjectLiteral(recurmax, stmtDepth, canThrow) + "." + getDotKey();
case p++:
var name = getVarName();
return name + " && " + name + "[" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "]";
var s = name + "[" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "]";
return canThrow && rng(8) == 0 ? s : name + " && " + s;
case p++:
var name = getVarName();
return name + " && " + name + "." + getDotKey();
var s = name + "." + getDotKey();
return canThrow && rng(8) == 0 ? s : name + " && " + s;
case p++:
case p++:
var name = getVarName();
var s = name + "." + getDotKey();
s = "typeof " + s + ' == "function" && --_calls_ >= 0 && ' + s + "(" + createArgs(recurmax, stmtDepth, canThrow) + ")";
return canThrow && rng(8) == 0 ? s : name + " && " + s;
case p++:
case p++:
case p++:
@@ -1023,7 +1031,7 @@ function log_suspects(minify_options, component) {
errorln(result.error);
} else {
var r = sandbox.run_code(result.code, sandbox.has_toplevel(m));
return sandbox.same_stdout(original_result, r);
return !sandbox.same_stdout(uglify_result, r);
}
}
});
@@ -1037,10 +1045,8 @@ function log_suspects(minify_options, component) {
}
function log_suspects_global(options) {
var o = {};
UglifyJS.minify("", o);
var suspects = Object.keys(o).filter(function(component) {
return typeof o[component] != "object";
var suspects = Object.keys(default_options).filter(function(component) {
return typeof default_options[component] != "object";
}).filter(function(component) {
var m = JSON.parse(options);
m[component] = false;
@@ -1050,7 +1056,7 @@ function log_suspects_global(options) {
errorln(result.error);
} else {
var r = sandbox.run_code(result.code, sandbox.has_toplevel(m));
return sandbox.same_stdout(original_result, r);
return !sandbox.same_stdout(uglify_result, r);
}
});
if (suspects.length > 0) {
@@ -1107,7 +1113,10 @@ function log(options) {
errorln(JSON.stringify(JSON.parse(options), null, 2));
errorln();
if (!ok && typeof uglify_code == "string") {
Object.keys(default_options).forEach(log_suspects.bind(null, JSON.parse(options)));
Object.keys(default_options).filter(function(component) {
var defs = default_options[component];
return defs && typeof defs == "object";
}).forEach(log_suspects.bind(null, JSON.parse(options)));
log_suspects_global(options);
errorln("!!!!!! Failed... round " + round);
}
@@ -1150,7 +1159,7 @@ for (var round = 1; round <= num_iterations; round++) {
uglify_code = uglify_code.code;
uglify_result = sandbox.run_code(uglify_code, toplevel);
ok = sandbox.same_stdout(original_result, uglify_result);
if (!ok && typeof uglify_result == "string" && o.compress.unsafe_math) {
if (!ok && typeof uglify_result == "string" && o.compress && o.compress.unsafe_math) {
ok = fuzzy_match(original_result, uglify_result);
if (!ok) {
var fuzzy_result = sandbox.run_code(original_code.replace(/( - 0\.1){3}/g, " - 0.3"), toplevel);

View File

@@ -5,7 +5,7 @@ process.exit = function() {
process.once("uncaughtException", function() {
(function callback() {
if (process.stdout.bufferSize || process.stderr.bufferSize) {
setImmediate(callback);
setTimeout(callback, 1);
} else {
exit.apply(process, args);
}

View File

@@ -15,13 +15,13 @@ exports.FILES = [
require.resolve("./exports.js"),
];
new Function("MOZ_SourceMap", "exports", function() {
new Function("exports", function() {
var code = exports.FILES.map(function(file) {
return fs.readFileSync(file, "utf8");
});
code.push("exports.describe_ast = " + describe_ast.toString());
return code.join("\n\n");
}())(require("source-map"), exports);
}())(exports);
function describe_ast() {
var out = OutputStream({ beautify: true });
@@ -66,8 +66,8 @@ function infer_options(options) {
}
exports.default_options = function() {
var defs = {};
Object.keys(infer_options({ 0: 0 })).forEach(function(component) {
var defs = infer_options({ 0: 0 });
Object.keys(defs).forEach(function(component) {
var options = {};
options[component] = { 0: 0 };
if (options = infer_options(options)) {